From f29a8de50422a67618adc82c74e82b166e7aa517 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Mon, 22 Jan 2024 17:12:58 +0100 Subject: [PATCH] fix(core): update --- package.json | 6 +- pnpm-lock.yaml | 32 ++ ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/00colors.ts | 2 + ts_web/elements/dees-editor-markdown.ts | 98 +++++++ ts_web/elements/dees-editor-markdownoutlet.ts | 42 +++ ts_web/elements/dees-editor.ts | 126 ++++++++ ts_web/elements/dees-icon.ts | 4 + ts_web/elements/dees-simple-appdash.ts | 69 ++++- ts_web/elements/dees-terminal.ts | 274 ++++++++++++++++++ ts_web/elements/index.ts | 4 + 11 files changed, 647 insertions(+), 12 deletions(-) create mode 100644 ts_web/elements/dees-editor-markdown.ts create mode 100644 ts_web/elements/dees-editor-markdownoutlet.ts create mode 100644 ts_web/elements/dees-editor.ts create mode 100644 ts_web/elements/dees-terminal.ts diff --git a/package.json b/package.json index 81bea98..3ceabb7 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,13 @@ "@push.rocks/smartpromise": "^4.0.3", "@push.rocks/smartstring": "^4.0.13", "@tsclass/tsclass": "^4.0.46", + "@webcontainer/api": "^1.1.8", "highlight.js": "11.9.0", "ibantools": "^4.3.9", - "pdfjs-dist": "^4.0.379" + "monaco-editor": "^0.45.0", + "pdfjs-dist": "^4.0.379", + "xterm": "^5.3.0", + "xterm-addon-fit": "^0.8.0" }, "devDependencies": { "@git.zone/tsbuild": "^2.1.72", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db4c633..e8900d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,15 +38,27 @@ dependencies: '@tsclass/tsclass': specifier: ^4.0.46 version: 4.0.46 + '@webcontainer/api': + specifier: ^1.1.8 + version: 1.1.8 highlight.js: specifier: 11.9.0 version: 11.9.0 ibantools: specifier: ^4.3.9 version: 4.3.9 + monaco-editor: + specifier: ^0.45.0 + version: 0.45.0 pdfjs-dist: specifier: ^4.0.379 version: 4.0.379 + xterm: + specifier: ^5.3.0 + version: 5.3.0 + xterm-addon-fit: + specifier: ^0.8.0 + version: 0.8.0(xterm@5.3.0) devDependencies: '@git.zone/tsbuild': @@ -2084,6 +2096,10 @@ packages: - utf-8-validate dev: true + /@webcontainer/api@1.1.8: + resolution: {integrity: sha512-m9WRj38oCoFPrqZOTeJcncPjnZ00FZUMq9YHEXxdhAoYhhQ69Rz4qK5p444cIPaMy2j8H7HcNLcAIwMGWnpMpw==} + dev: false + /@xmldom/xmldom@0.8.10: resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} engines: {node: '>=10.0.0'} @@ -5095,6 +5111,10 @@ packages: yargs-unparser: 1.6.0 dev: true + /monaco-editor@0.45.0: + resolution: {integrity: sha512-mjv1G1ZzfEE3k9HZN0dQ2olMdwIfaeAAjFiwNprLfYNRSz7ctv9XuCT7gPtBGrMUeV1/iZzYKj17Khu1hxoHOA==} + dev: false + /ms@2.0.0: resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} dev: true @@ -6871,6 +6891,18 @@ packages: engines: {node: '>=0.4.0'} dev: true + /xterm-addon-fit@0.8.0(xterm@5.3.0): + resolution: {integrity: sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==} + peerDependencies: + xterm: ^5.0.0 + dependencies: + xterm: 5.3.0 + dev: false + + /xterm@5.3.0: + resolution: {integrity: sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==} + dev: false + /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} dev: true diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index f07c0f0..c0b3117 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-catalog', - version: '1.0.261', + version: '1.0.262', description: 'website for lossless.com' } diff --git a/ts_web/elements/00colors.ts b/ts_web/elements/00colors.ts index 81e1853..7774c1e 100644 --- a/ts_web/elements/00colors.ts +++ b/ts_web/elements/00colors.ts @@ -1,11 +1,13 @@ export const dark = { blue: '#0050b9', blueActive: '#0069f2', + blueMuted: '#012452', text: '#ffffff', } export const bright = { blue: '#0050b9', blueActive: '#0069f2', + blueMuted: '#0069f2', text: '#333333', } \ No newline at end of file diff --git a/ts_web/elements/dees-editor-markdown.ts b/ts_web/elements/dees-editor-markdown.ts new file mode 100644 index 0000000..5445c51 --- /dev/null +++ b/ts_web/elements/dees-editor-markdown.ts @@ -0,0 +1,98 @@ +import { + DeesElement, + property, + html, + customElement, + type TemplateResult, + css, + cssManager, + domtools +} from '@design.estate/dees-element'; + +const deferred = domtools.plugins.smartpromise.defer(); + +declare global { + interface HTMLElementTagNameMap { + 'dees-editormarkdown': DeesEditorMarkdown; + } +} + +@customElement('dees-editormarkdown') +export class DeesEditorMarkdown extends DeesElement { + public static demo = () => html``; + + public static styles = [ + cssManager.defaultStyles, + css` + .gridcontainer { + position: absolute; + height: 100%; + width: 100%; + display: grid; + grid-template-columns: 60% 40%; + } + .editorContainer { + position: relative; + } + .outletContainer { + background: #111; + color: #fff; + font-family: 'Roboto Slab'; + padding: 20px; + overflow-y: scroll; + } + `, + ]; + + public render() { + return html` +
+
+ note: +There is something going on. + +\`\`\`typescript +const hello = 'yes' +\`\`\` +`} + wordWrap="bounded" + > +
+
+ +
+
+ `; + } + + public async firstUpdated(_changedPropertiesArg) { + await super.firstUpdated(_changedPropertiesArg); + const editor = this.shadowRoot.querySelector('dees-editor'); + + // lets care about wiring the markdown stuff. + const markdownOutlet = this.shadowRoot.querySelector('dees-editormarkdownoutlet'); + const smartmarkdownInstance = new domtools.plugins.smartmarkdown.SmartMarkdown(); + const mdParsedResult = await smartmarkdownInstance.getMdParsedResultFromMarkdown('loading...') + editor.contentSubject.subscribe(async contentArg => { + await mdParsedResult.updateFromMarkdownString(contentArg) + const html = mdParsedResult.html; + markdownOutlet.updateHtmlText(html); + }) + } +} diff --git a/ts_web/elements/dees-editor-markdownoutlet.ts b/ts_web/elements/dees-editor-markdownoutlet.ts new file mode 100644 index 0000000..3920c16 --- /dev/null +++ b/ts_web/elements/dees-editor-markdownoutlet.ts @@ -0,0 +1,42 @@ +import { customElement, DeesElement, html, type TemplateResult } from '@design.estate/dees-element'; + +declare global { + interface HTMLElementTagNameMap { + 'dees-editormarkdownoutlet': DeesEditorMarkdownOutlet; + } +} + +@customElement('dees-editormarkdownoutlet') +export class DeesEditorMarkdownOutlet extends DeesElement { + // DEMO + public static demo = () => html``; + + // INSTANCE + private outlet: HTMLElement; + + public render(): TemplateResult { + return html` +
+

Hi there

+
+ `; + } + + public async firstUpdated(_changedProperties: Map) { + await super.firstUpdated(_changedProperties); + const styleElement = document.createElement('style'); + const cssText = await ( + await fetch('https://unpkg.com/github-markdown-css@5.1.0/github-markdown-dark.css') + ).text(); + styleElement.textContent = cssText; + this.shadowRoot.append(styleElement); + } + + public async updateHtmlText(htmlTextArg: string) { + await this.updateComplete; + if (!this.outlet) { + this.outlet = this.shadowRoot.querySelector('.outlet'); + } + this.outlet.innerHTML = htmlTextArg; + } +} diff --git a/ts_web/elements/dees-editor.ts b/ts_web/elements/dees-editor.ts new file mode 100644 index 0000000..1fab4a9 --- /dev/null +++ b/ts_web/elements/dees-editor.ts @@ -0,0 +1,126 @@ +import { + DeesElement, + property, + html, + customElement, + type TemplateResult, + css, + cssManager, +} from '@design.estate/dees-element'; +import * as domtools from '@design.estate/dees-domtools'; + +import type * as monaco from 'monaco-editor'; + +declare global { + interface HTMLElementTagNameMap { + 'dees-editor': DeesEditor; + } +} + +@customElement('dees-editor') +export class DeesEditor extends DeesElement { + // DEMO + public static demo = () => html` `; + + // STATIC + public static monacoDeferred: ReturnType; + + // INSTANCE + public editorDeferred = domtools.plugins.smartpromise.defer(); + public language = 'typescript'; + + @property({ + type: String + }) + public content = "function hello() {\n\talert('Hello world!');\n}"; + + @property({ + type: Object + }) + public contentSubject = new domtools.plugins.smartrx.rxjs.Subject(); + + @property({ + type: Boolean + }) + public wordWrap: monaco.editor.IStandaloneEditorConstructionOptions['wordWrap'] = 'off'; + + constructor() { + super(); + domtools.DomTools.setupDomTools(); + } + + public static styles = [ + domtools.elementBasic.staticStyles, + css` + :host { + } + + * { + box-sizing: border-box; + } + + #container { + position: absolute; + height: 100%; + width: 100%; + } + `, + ]; + + public render(): TemplateResult { + return html` +
+
+
+ `; + } + + public async firstUpdated( + _changedProperties: Map + ): Promise { + super.firstUpdated(_changedProperties); + const container = this.shadowRoot.getElementById('container'); + + if (!DeesEditor.monacoDeferred) { + DeesEditor.monacoDeferred = domtools.plugins.smartpromise.defer(); + const scriptUrl = `https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/loader.js`; + const script = document.createElement('script'); + script.src = scriptUrl; + script.onload = () => { + DeesEditor.monacoDeferred.resolve(); + }; + document.head.appendChild(script); + } + await DeesEditor.monacoDeferred.promise; + + (window as any).require.config({ + paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor/min/vs' }, + }); + (window as any).require(['vs/editor/editor.main'], async () => { + const editor = ((window as any).monaco.editor as typeof monaco.editor).create(container, { + value: this.content, + language: this.language, + theme: 'vs-dark', + useShadowDOM: true, + fontSize: 16, + automaticLayout: true, + wordWrap: this.wordWrap + }); + this.editorDeferred.resolve(editor); + }); + const css = await ( + await fetch('https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/editor/editor.main.css') + ).text(); + const styleElement = document.createElement('style'); + styleElement.textContent = css; + this.shadowRoot.append(styleElement); + + + // editor is setup let do the rest + const editor = await this.editorDeferred.promise; + editor.onDidChangeModelContent(async eventArg => { + this.contentSubject.next(editor.getValue()); + }); + this.contentSubject.next(editor.getValue()); + } +} diff --git a/ts_web/elements/dees-icon.ts b/ts_web/elements/dees-icon.ts index d490d3b..6417e5b 100644 --- a/ts_web/elements/dees-icon.ts +++ b/ts_web/elements/dees-icon.ts @@ -57,6 +57,7 @@ import { faMoneyCheckDollar as faMoneyCheckDollarSolid, faMugHot as faMugHotSolid, faMinus as faMinusSolid, + faNetworkWired as faNetworkWiredSolid, faPaperclip as faPaperclipSolid, faPaste as faPasteSolid, faPenToSquare as faPenToSquareSolid, @@ -66,6 +67,7 @@ import { faUsers as faUsersSolid, faShare as faShareSolid, faSun as faSunSolid, + faTerminal as faTerminalSolid, faTrash as faTrashSolid, faTrashCan as faTrashCanSolid, faWallet as faWalletSolid, @@ -104,6 +106,7 @@ export const faIcons = { moneyCheckDollar: faMoneyCheckDollarSolid, mugHot: faMugHotSolid, minus: faMinusSolid, + networkWired: faNetworkWiredSolid, paperclip: faPaperclipSolid, paste: faPasteRegular, pasteSolid: faPasteSolid, @@ -114,6 +117,7 @@ export const faIcons = { share: faShareSolid, sun: faSunRegular, sunSolid: faSunSolid, + terminal: faTerminalSolid, trash: faTrashSolid, trashSolid: faTrashSolid, trashCan: faTrashCanRegular, diff --git a/ts_web/elements/dees-simple-appdash.ts b/ts_web/elements/dees-simple-appdash.ts index 4cb94f7..8950d53 100644 --- a/ts_web/elements/dees-simple-appdash.ts +++ b/ts_web/elements/dees-simple-appdash.ts @@ -1,4 +1,6 @@ import { demoFunc } from './dees-simple-appdash.demo.js'; +import * as colors from './00colors.js'; + import { customElement, html, @@ -10,7 +12,9 @@ import { unsafeCSS, type CSSResult, state, + domtools, } from '@design.estate/dees-element'; +import { DeesTerminal } from './dees-terminal.js'; declare global { interface HTMLElementTagNameMap { @@ -28,7 +32,8 @@ export class DeesSimpleAppDash extends DeesElement { public name = 'Dees Simple Login'; @property() - public views: Array<{ name: string; icon: string; viewFunction: () => Promise }> = []; + public views: Array<{ name: string; icon: string; viewFunction: () => Promise }> = + []; public static styles = [ cssManager.defaultStyles, @@ -40,12 +45,12 @@ export class DeesSimpleAppDash extends DeesElement { .appbar { position: fixed; top: 0; - height: 40px; + height: 32px; width: 100%; background: ${cssManager.bdTheme('#eeeeeb', '#222')}; border-bottom: 1px solid ${cssManager.bdTheme('#ccc', '#ffffff10')}; font-size: 14px; - line-height: 40px; + line-height: 32px; font-family: 'Roboto', 'Inter', sans-serif; padding: 0px 16px; z-index: 2; @@ -62,7 +67,8 @@ export class DeesSimpleAppDash extends DeesElement { display: flex; } - .appActions .action {} + .appActions .action { + } .appActions .action:hover { color: ${cssManager.bdTheme('#000', '#fff')}; } @@ -70,13 +76,35 @@ export class DeesSimpleAppDash extends DeesElement { .appcontent { z-index: 1; position: fixed; - top: 40px; - height: calc(100vh - 40px); - bottom: 0px; + top: 32px; + height: calc(100vh - 32px - 24px); + bottom: 24px; width: 100%; overflow: auto; background: ${cssManager.bdTheme('#eeeeeb', '#000')}; } + + .controlbar { + color: #fff; + position: absolute; + bottom: 0px; + left: 0px; + width: 100%; + height: 24px; + background: ${cssManager.bdTheme(colors.bright.blueMuted, colors.dark.blueMuted)}; + z-index: 2; + display: flex; + justify-content: flex-end; + align-items: center; + flex-direction: row; + } + + .control { + width: min-content; + margin-right: 16px; + font-size: 12px; + white-space: nowrap; + } `, ]; @@ -86,14 +114,20 @@ export class DeesSimpleAppDash extends DeesElement {
${this.name}
-
- Logout -
+
Logout
+
+
+ +
+
+ +
+
`; } @@ -101,4 +135,19 @@ export class DeesSimpleAppDash extends DeesElement { const domtools = await this.domtoolsPromise; super.firstUpdated(_changedProperties); } + + public async launchTerminal() { + const appcontent = this.shadowRoot.querySelector('.appcontent'); + const terminal = new DeesTerminal(); + terminal.style.position = 'absolute'; + terminal.style.top = '0px'; + terminal.style.left = '0px'; + terminal.style.opacity = '0'; + terminal.style.transform = 'translateY(20px)'; + terminal.style.transition = 'all 0.2s'; + appcontent.appendChild(terminal); + await domtools.plugins.smartdelay.delayFor(0); + terminal.style.opacity = '1'; + terminal.style.transform = 'translateY(0px)'; + } } diff --git a/ts_web/elements/dees-terminal.ts b/ts_web/elements/dees-terminal.ts new file mode 100644 index 0000000..e505c52 --- /dev/null +++ b/ts_web/elements/dees-terminal.ts @@ -0,0 +1,274 @@ +import { + DeesElement, + property, + html, + customElement, + type TemplateResult, + css, + cssManager, +} from '@design.estate/dees-element'; +import * as domtools from '@design.estate/dees-domtools'; + +import * as webcontainer from '@webcontainer/api'; + +import { Terminal } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; + +declare global { + interface HTMLElementTagNameMap { + 'dees-terminal': DeesTerminal; + } +} + +@customElement('dees-terminal') +export class DeesTerminal extends DeesElement { + public static demo = () => html` `; + + constructor() { + super(); + domtools.DomTools.setupDomTools(); + } + + public static styles = [ + domtools.elementBasic.staticStyles, + css` + :host { + padding: 20px; + background: #000; + position: absolute; + height: 100%; + width: 100%; + } + + * { + box-sizing: border-box; + } + + #container { + position: absolute; + height: calc(100% - 40px); + width: calc(100% - 40px); + } + /** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + + /** + * Default styles for xterm.js + */ + + .xterm { + font-feature-settings: 'liga' 0; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + } + + .xterm.focus, + .xterm:focus { + outline: none; + } + + .xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 5; + } + + .xterm .xterm-helper-textarea { + padding: 0; + border: 0; + margin: 0; + /* Move textarea out of the screen to the far left, so that the cursor is not visible */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -5; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; + } + + .xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #fff; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; + } + + .xterm .composition-view.active { + display: block; + } + + .xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; + } + + .xterm .xterm-screen { + position: relative; + } + + .xterm .xterm-screen canvas { + position: absolute; + left: 0; + top: 0; + } + + .xterm .xterm-scroll-area { + visibility: hidden; + } + + .xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + top: 0; + left: -9999em; + line-height: normal; + } + + .xterm { + cursor: text; + } + + .xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; + } + + .xterm.xterm-cursor-pointer { + cursor: pointer; + } + + .xterm.column-select.focus { + /* Column selection mode */ + cursor: crosshair; + } + + .xterm .xterm-accessibility, + .xterm .xterm-message { + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 10; + color: transparent; + } + + .xterm .live-region { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; + } + + .xterm-dim { + opacity: 0.5; + } + + .xterm-underline { + text-decoration: underline; + } + `, + ]; + + public render(): TemplateResult { + return html` +
+
+
+ `; + } + + public async firstUpdated( + _changedProperties: Map + ): Promise { + const domtools = await this.domtoolsPromise; + super.firstUpdated(_changedProperties); + const container = this.shadowRoot.getElementById('container'); + + const term = new Terminal({ + convertEol: true, + cursorBlink: true, + }); + const fitAddon = new FitAddon(); + term.loadAddon(fitAddon); + + // Open the terminal in #terminal-container + term.open(container); + + // Make the terminal's size and geometry fit the size of #terminal-container + fitAddon.fit(); + + term.write(`dees-terminal custom terminal. \r\n$ `); + + // lets start the webcontainer + // Call only once + const webcontainerInstance = await webcontainer.WebContainer.boot(); + const shellProcess = await webcontainerInstance.spawn('jsh'); + shellProcess.output.pipeTo( + new WritableStream({ + write(data) { + term.write(data); + }, + }) + ); + const input = shellProcess.input.getWriter(); + term.onData((data) => { + input.write(data); + }); + await domtools.convenience.smartdelay.delayFor(5000); + input.write(`pnpm add isomorphic-git @git.zone/tsbuild\n`); + } +} diff --git a/ts_web/elements/index.ts b/ts_web/elements/index.ts index 5aafa0b..ddb2010 100644 --- a/ts_web/elements/index.ts +++ b/ts_web/elements/index.ts @@ -4,6 +4,9 @@ export * from './dees-chips.js'; export * from './dees-contextmenu.js'; export * from './dees-dataview-codebox.js'; export * from './dees-dataview-statusobject.js'; +export * from './dees-editor.js'; +export * from './dees-editor-markdown.js'; +export * from './dees-editor-markdownoutlet.js'; export * from './dees-form-submit.js'; export * from './dees-form.js'; export * from './dees-hint.js'; @@ -29,6 +32,7 @@ export * from './dees-speechbubble.js'; export * from './dees-spinner.js'; export * from './dees-stepper.js'; export * from './dees-table.js'; +export * from './dees-terminal.js'; export * from './dees-toast.js'; export * from './dees-updater.js'; export * from './dees-windowcontrols.js';