From 15bca090862014c0a629136a750a175159136150 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Wed, 31 Dec 2025 12:37:14 +0000 Subject: [PATCH] feat(workspace): rename editor components to workspace group and move terminal & TypeScript intellisense into workspace --- changelog.md | 9 + scripts/update-monaco-version.cjs | 10 +- ts_web/00_commitinfo_data.ts | 2 +- .../dees-editor-filetree/index.ts | 1 - .../dees-editor-markdown/index.ts | 1 - .../dees-editor-markdownoutlet/index.ts | 1 - .../dees-editor-monaco/index.ts | 1 - ts_web/elements/00group-editor/index.ts | 6 - .../dees-input-code/dees-input-code.ts | 24 +- .../dees-simple-appdash.ts | 10 +- .../dees-workspace-filetree.ts} | 8 +- .../dees-workspace-filetree/index.ts | 1 + .../dees-workspace-markdown.ts} | 20 +- .../dees-workspace-markdown/index.ts | 1 + .../dees-workspace-markdownoutlet.ts} | 8 +- .../dees-workspace-markdownoutlet/index.ts | 1 + .../dees-workspace-monaco.ts} | 16 +- .../dees-workspace-monaco/index.ts | 1 + .../dees-workspace-monaco}/version.ts | 0 .../dees-workspace-terminal-preview.ts | 361 ++++++++++++++++++ .../dees-workspace-terminal-preview/index.ts | 1 + .../dees-workspace-terminal.ts} | 14 +- .../dees-workspace-terminal/index.ts | 1 + .../dees-workspace/dees-workspace.ts} | 95 ++++- .../dees-workspace}/index.ts | 2 +- .../typescript-intellisense.ts | 0 ts_web/elements/00group-workspace/index.ts | 8 + ts_web/elements/dees-terminal/index.ts | 1 - ts_web/elements/index.ts | 4 +- 29 files changed, 517 insertions(+), 91 deletions(-) delete mode 100644 ts_web/elements/00group-editor/dees-editor-filetree/index.ts delete mode 100644 ts_web/elements/00group-editor/dees-editor-markdown/index.ts delete mode 100644 ts_web/elements/00group-editor/dees-editor-markdownoutlet/index.ts delete mode 100644 ts_web/elements/00group-editor/dees-editor-monaco/index.ts delete mode 100644 ts_web/elements/00group-editor/index.ts rename ts_web/elements/{00group-editor/dees-editor-filetree/dees-editor-filetree.ts => 00group-workspace/dees-workspace-filetree/dees-workspace-filetree.ts} (99%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-filetree/index.ts rename ts_web/elements/{00group-editor/dees-editor-markdown/dees-editor-markdown.ts => 00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts} (76%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-markdown/index.ts rename ts_web/elements/{00group-editor/dees-editor-markdownoutlet/dees-editor-markdownoutlet.ts => 00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts} (78%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/index.ts rename ts_web/elements/{00group-editor/dees-editor-monaco/dees-editor-monaco.ts => 00group-workspace/dees-workspace-monaco/dees-workspace-monaco.ts} (93%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-monaco/index.ts rename ts_web/elements/{00group-editor/dees-editor-monaco => 00group-workspace/dees-workspace-monaco}/version.ts (100%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-terminal-preview/dees-workspace-terminal-preview.ts create mode 100644 ts_web/elements/00group-workspace/dees-workspace-terminal-preview/index.ts rename ts_web/elements/{dees-terminal/dees-terminal.ts => 00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts} (96%) create mode 100644 ts_web/elements/00group-workspace/dees-workspace-terminal/index.ts rename ts_web/elements/{00group-editor/dees-editor-workspace/dees-editor-workspace.ts => 00group-workspace/dees-workspace/dees-workspace.ts} (93%) rename ts_web/elements/{00group-editor/dees-editor-workspace => 00group-workspace/dees-workspace}/index.ts (51%) rename ts_web/elements/{00group-editor/dees-editor-workspace => 00group-workspace/dees-workspace}/typescript-intellisense.ts (100%) create mode 100644 ts_web/elements/00group-workspace/index.ts delete mode 100644 ts_web/elements/dees-terminal/index.ts diff --git a/changelog.md b/changelog.md index aeedeb3..7315a1a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-12-31 - 3.20.0 - feat(workspace) +rename editor components to workspace group and move terminal & TypeScript intellisense into workspace + +- Renamed components and modules from 00group-editor/dees-editor-* to 00group-workspace/dees-workspace-* (e.g. dees-editor-monaco -> dees-workspace-monaco). +- Moved terminal implementation from dees-terminal to dees-workspace-terminal and updated related imports/usages. +- Moved TypeScript intellisense manager into 00group-workspace and updated paths. +- Updated ts_web elements index to export 00group-workspace instead of 00group-editor and adjusted internal imports accordingly. +- Updated scripts/update-monaco-version.cjs to write MONACO_VERSION into the new workspace path and updated log tags. + ## 2025-12-31 - 3.19.1 - fix(intellisense) Debounce TypeScript/JavaScript IntelliSense processing and cache missing packages to reduce work and noisy logs diff --git a/scripts/update-monaco-version.cjs b/scripts/update-monaco-version.cjs index f31de27..6c67c8c 100755 --- a/scripts/update-monaco-version.cjs +++ b/scripts/update-monaco-version.cjs @@ -11,7 +11,7 @@ function resolveMonacoPackageJson() { }); return resolvedPath; } catch (error) { - console.error('[dees-editor] Unable to resolve monaco-editor/package.json'); + console.error('[dees-workspace] Unable to resolve monaco-editor/package.json'); throw error; } } @@ -20,25 +20,25 @@ function getMonacoVersion() { const monacoPackagePath = resolveMonacoPackageJson(); const monacoPackage = require(monacoPackagePath); if (!monacoPackage.version) { - throw new Error('[dees-editor] monaco-editor/package.json does not expose a version field'); + throw new Error('[dees-workspace] monaco-editor/package.json does not expose a version field'); } return monacoPackage.version; } function writeVersionModule(version) { - const targetDir = path.join(projectRoot, 'ts_web', 'elements', '00group-editor', 'dees-editor-monaco'); + const targetDir = path.join(projectRoot, 'ts_web', 'elements', '00group-workspace', 'dees-workspace-monaco'); fs.mkdirSync(targetDir, { recursive: true }); const targetFile = path.join(targetDir, 'version.ts'); const fileContent = `// Auto-generated by scripts/update-monaco-version.cjs\nexport const MONACO_VERSION = '${version}';\n`; fs.writeFileSync(targetFile, fileContent, 'utf8'); - console.log(`[dees-editor] Wrote ${path.relative(projectRoot, targetFile)} with monaco-editor@${version}`); + console.log(`[dees-workspace] Wrote ${path.relative(projectRoot, targetFile)} with monaco-editor@${version}`); } try { const version = getMonacoVersion(); writeVersionModule(version); } catch (error) { - console.error('[dees-editor] Failed to update Monaco version module.'); + console.error('[dees-workspace] Failed to update Monaco version module.'); console.error(error instanceof Error ? error.message : error); process.exitCode = 1; } diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 84718f7..38a7561 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: '3.19.1', + version: '3.20.0', description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.' } diff --git a/ts_web/elements/00group-editor/dees-editor-filetree/index.ts b/ts_web/elements/00group-editor/dees-editor-filetree/index.ts deleted file mode 100644 index 653e6ba..0000000 --- a/ts_web/elements/00group-editor/dees-editor-filetree/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dees-editor-filetree.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-markdown/index.ts b/ts_web/elements/00group-editor/dees-editor-markdown/index.ts deleted file mode 100644 index 65454dc..0000000 --- a/ts_web/elements/00group-editor/dees-editor-markdown/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dees-editor-markdown.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-markdownoutlet/index.ts b/ts_web/elements/00group-editor/dees-editor-markdownoutlet/index.ts deleted file mode 100644 index 7d15930..0000000 --- a/ts_web/elements/00group-editor/dees-editor-markdownoutlet/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dees-editor-markdownoutlet.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-monaco/index.ts b/ts_web/elements/00group-editor/dees-editor-monaco/index.ts deleted file mode 100644 index 58f495d..0000000 --- a/ts_web/elements/00group-editor/dees-editor-monaco/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dees-editor-monaco.js'; diff --git a/ts_web/elements/00group-editor/index.ts b/ts_web/elements/00group-editor/index.ts deleted file mode 100644 index fafab95..0000000 --- a/ts_web/elements/00group-editor/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Editor Components -export * from './dees-editor-monaco/index.js'; -export * from './dees-editor-filetree/index.js'; -export * from './dees-editor-workspace/index.js'; -export * from './dees-editor-markdown/index.js'; -export * from './dees-editor-markdownoutlet/index.js'; diff --git a/ts_web/elements/00group-input/dees-input-code/dees-input-code.ts b/ts_web/elements/00group-input/dees-input-code/dees-input-code.ts index e891381..11fbe9b 100644 --- a/ts_web/elements/00group-input/dees-input-code/dees-input-code.ts +++ b/ts_web/elements/00group-input/dees-input-code/dees-input-code.ts @@ -12,8 +12,8 @@ import { themeDefaultStyles } from '../../00theme.js'; import { DeesModal } from '../../dees-modal/dees-modal.js'; import '../../dees-icon/dees-icon.js'; import '../../dees-label/dees-label.js'; -import '../../00group-editor/dees-editor-monaco/dees-editor-monaco.js'; -import { DeesEditorMonaco } from '../../00group-editor/dees-editor-monaco/dees-editor-monaco.js'; +import '../../00group-workspace/dees-workspace-monaco/dees-workspace-monaco.js'; +import { DeesWorkspaceMonaco } from '../../00group-workspace/dees-workspace-monaco/dees-workspace-monaco.js'; declare global { interface HTMLElementTagNameMap { @@ -77,7 +77,7 @@ export class DeesInputCode extends DeesInputBase { @state() accessor copySuccess: boolean = false; - private editorElement: DeesEditorMonaco | null = null; + private editorElement: DeesWorkspaceMonaco | null = null; public static styles = [ themeDefaultStyles, @@ -207,7 +207,7 @@ export class DeesInputCode extends DeesInputBase { position: relative; } - dees-editor-monaco { + dees-workspace-monaco { display: block; } @@ -295,12 +295,12 @@ export class DeesInputCode extends DeesInputBase {
- + >
@@ -308,7 +308,7 @@ export class DeesInputCode extends DeesInputBase { } async firstUpdated() { - this.editorElement = this.shadowRoot?.querySelector('dees-editor-monaco') as DeesEditorMonaco; + this.editorElement = this.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; if (this.editorElement) { // Subscribe to content changes from the editor this.editorElement.contentSubject.subscribe((newContent: string) => { @@ -386,7 +386,7 @@ export class DeesInputCode extends DeesInputBase { public async openFullscreen() { const currentValue = this.value; - let modalEditorElement: DeesEditorMonaco | null = null; + let modalEditorElement: DeesWorkspaceMonaco | null = null; // Modal-specific state let modalLanguage = this.language; @@ -579,11 +579,11 @@ export class DeesInputCode extends DeesInputBase { `, menuOptions: [ @@ -597,7 +597,7 @@ export class DeesInputCode extends DeesInputBase { name: 'Save & Close', action: async (modalRef) => { // Get the editor content from the modal - modalEditorElement = modalRef.shadowRoot?.querySelector('dees-editor-monaco') as DeesEditorMonaco; + modalEditorElement = modalRef.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; if (modalEditorElement) { const editor = await modalEditorElement.editorDeferred.promise; const newValue = editor.getValue(); @@ -611,7 +611,7 @@ export class DeesInputCode extends DeesInputBase { // Wait for modal to render await new Promise(resolve => setTimeout(resolve, 100)); - modalEditorElement = modal.shadowRoot?.querySelector('dees-editor-monaco') as DeesEditorMonaco; + modalEditorElement = modal.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; // Wire up toolbar event handlers const toolbar = modal.shadowRoot?.querySelector('.modal-toolbar'); diff --git a/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts b/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts index 0a093ea..d57955d 100644 --- a/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts +++ b/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts @@ -14,7 +14,7 @@ import { domtools, } from '@design.estate/dees-element'; import '../../dees-icon/dees-icon.js'; -import type { DeesTerminal } from '../../dees-terminal/dees-terminal.js'; +import type { DeesWorkspaceTerminal } from '../../00group-workspace/dees-workspace-terminal/dees-workspace-terminal.js'; import { themeDefaultStyles } from '../../00theme.js'; declare global { @@ -393,7 +393,7 @@ export class DeesSimpleAppDash extends DeesElement { } } - public currentTerminal: DeesTerminal; + public currentTerminal: DeesWorkspaceTerminal; public async launchTerminal() { const domtools = await this.domtoolsPromise; if (this.currentTerminal) { @@ -401,10 +401,10 @@ export class DeesSimpleAppDash extends DeesElement { await this.closeTerminal(); return; } - + const maincontainer = this.shadowRoot.querySelector('.maincontainer'); - const { DeesTerminal } = await import('../../dees-terminal/dees-terminal.js'); - const terminal = new DeesTerminal(); + const { DeesWorkspaceTerminal } = await import('../../00group-workspace/dees-workspace-terminal/dees-workspace-terminal.js'); + const terminal = new DeesWorkspaceTerminal(); terminal.setupCommand = this.terminalSetupCommand; this.currentTerminal = terminal; maincontainer.appendChild(terminal); diff --git a/ts_web/elements/00group-editor/dees-editor-filetree/dees-editor-filetree.ts b/ts_web/elements/00group-workspace/dees-workspace-filetree/dees-workspace-filetree.ts similarity index 99% rename from ts_web/elements/00group-editor/dees-editor-filetree/dees-editor-filetree.ts rename to ts_web/elements/00group-workspace/dees-workspace-filetree/dees-workspace-filetree.ts index 396413a..c3f202b 100644 --- a/ts_web/elements/00group-editor/dees-editor-filetree/dees-editor-filetree.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-filetree/dees-workspace-filetree.ts @@ -20,7 +20,7 @@ import { DeesInputText } from '../../00group-input/dees-input-text/dees-input-te declare global { interface HTMLElementTagNameMap { - 'dees-editor-filetree': DeesEditorFiletree; + 'dees-workspace-filetree': DeesWorkspaceFiletree; } } @@ -30,11 +30,11 @@ interface ITreeNode extends IFileEntry { level: number; } -@customElement('dees-editor-filetree') -export class DeesEditorFiletree extends DeesElement { +@customElement('dees-workspace-filetree') +export class DeesWorkspaceFiletree extends DeesElement { public static demo = () => html`
- +
`; diff --git a/ts_web/elements/00group-workspace/dees-workspace-filetree/index.ts b/ts_web/elements/00group-workspace/dees-workspace-filetree/index.ts new file mode 100644 index 0000000..ab9c004 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-filetree/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-filetree.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-markdown/dees-editor-markdown.ts b/ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts similarity index 76% rename from ts_web/elements/00group-editor/dees-editor-markdown/dees-editor-markdown.ts rename to ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts index b629fcf..c4f8386 100644 --- a/ts_web/elements/00group-editor/dees-editor-markdown/dees-editor-markdown.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts @@ -9,19 +9,19 @@ import { domtools } from '@design.estate/dees-element'; import { themeDefaultStyles } from '../../00theme.js'; -import { DeesEditorMonaco } from '../dees-editor-monaco/dees-editor-monaco.js'; +import { DeesWorkspaceMonaco } from '../dees-workspace-monaco/dees-workspace-monaco.js'; const deferred = domtools.plugins.smartpromise.defer(); declare global { interface HTMLElementTagNameMap { - 'dees-editormarkdown': DeesEditorMarkdown; + 'dees-workspace-markdown': DeesWorkspaceMarkdown; } } -@customElement('dees-editormarkdown') -export class DeesEditorMarkdown extends DeesElement { - public static demo = () => html``; +@customElement('dees-workspace-markdown') +export class DeesWorkspaceMarkdown extends DeesElement { + public static demo = () => html``; public static styles = [ themeDefaultStyles, @@ -52,7 +52,7 @@ export class DeesEditorMarkdown extends DeesElement { return html`
- + >
- +
`; @@ -87,10 +87,10 @@ const hello = 'yes' public async firstUpdated(_changedPropertiesArg) { await super.firstUpdated(_changedPropertiesArg); - const editor = this.shadowRoot.querySelector('dees-editor-monaco') as DeesEditorMonaco; + const editor = this.shadowRoot.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; // lets care about wiring the markdown stuff. - const markdownOutlet = this.shadowRoot.querySelector('dees-editormarkdownoutlet'); + const markdownOutlet = this.shadowRoot.querySelector('dees-workspace-markdownoutlet'); const smartmarkdownInstance = new domtools.plugins.smartmarkdown.SmartMarkdown(); const mdParsedResult = await smartmarkdownInstance.getMdParsedResultFromMarkdown('loading...') editor.contentSubject.subscribe(async contentArg => { diff --git a/ts_web/elements/00group-workspace/dees-workspace-markdown/index.ts b/ts_web/elements/00group-workspace/dees-workspace-markdown/index.ts new file mode 100644 index 0000000..c416736 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-markdown/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-markdown.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-markdownoutlet/dees-editor-markdownoutlet.ts b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts similarity index 78% rename from ts_web/elements/00group-editor/dees-editor-markdownoutlet/dees-editor-markdownoutlet.ts rename to ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts index 3920c16..5a18c2f 100644 --- a/ts_web/elements/00group-editor/dees-editor-markdownoutlet/dees-editor-markdownoutlet.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts @@ -2,14 +2,14 @@ import { customElement, DeesElement, html, type TemplateResult } from '@design.e declare global { interface HTMLElementTagNameMap { - 'dees-editormarkdownoutlet': DeesEditorMarkdownOutlet; + 'dees-workspace-markdownoutlet': DeesWorkspaceMarkdownoutlet; } } -@customElement('dees-editormarkdownoutlet') -export class DeesEditorMarkdownOutlet extends DeesElement { +@customElement('dees-workspace-markdownoutlet') +export class DeesWorkspaceMarkdownoutlet extends DeesElement { // DEMO - public static demo = () => html``; + public static demo = () => html``; // INSTANCE private outlet: HTMLElement; diff --git a/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/index.ts b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/index.ts new file mode 100644 index 0000000..30fdf10 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-markdownoutlet.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-monaco/dees-editor-monaco.ts b/ts_web/elements/00group-workspace/dees-workspace-monaco/dees-workspace-monaco.ts similarity index 93% rename from ts_web/elements/00group-editor/dees-editor-monaco/dees-editor-monaco.ts rename to ts_web/elements/00group-workspace/dees-workspace-monaco/dees-workspace-monaco.ts index 25c1fa6..bb92967 100644 --- a/ts_web/elements/00group-editor/dees-editor-monaco/dees-editor-monaco.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-monaco/dees-workspace-monaco.ts @@ -15,14 +15,14 @@ import type * as monaco from 'monaco-editor'; declare global { interface HTMLElementTagNameMap { - 'dees-editor-monaco': DeesEditorMonaco; + 'dees-workspace-monaco': DeesWorkspaceMonaco; } } -@customElement('dees-editor-monaco') -export class DeesEditorMonaco extends DeesElement { +@customElement('dees-workspace-monaco') +export class DeesWorkspaceMonaco extends DeesElement { // DEMO - public static demo = () => html``; + public static demo = () => html``; // STATIC public static monacoDeferred: ReturnType; @@ -98,17 +98,17 @@ export class DeesEditorMonaco extends DeesElement { const container = this.shadowRoot.getElementById('container'); const monacoCdnBase = `https://cdn.jsdelivr.net/npm/monaco-editor@${MONACO_VERSION}`; - if (!DeesEditorMonaco.monacoDeferred) { - DeesEditorMonaco.monacoDeferred = domtools.plugins.smartpromise.defer(); + if (!DeesWorkspaceMonaco.monacoDeferred) { + DeesWorkspaceMonaco.monacoDeferred = domtools.plugins.smartpromise.defer(); const scriptUrl = `${monacoCdnBase}/min/vs/loader.js`; const script = document.createElement('script'); script.src = scriptUrl; script.onload = () => { - DeesEditorMonaco.monacoDeferred.resolve(); + DeesWorkspaceMonaco.monacoDeferred.resolve(); }; document.head.appendChild(script); } - await DeesEditorMonaco.monacoDeferred.promise; + await DeesWorkspaceMonaco.monacoDeferred.promise; (window as any).require.config({ paths: { vs: `${monacoCdnBase}/min/vs` }, diff --git a/ts_web/elements/00group-workspace/dees-workspace-monaco/index.ts b/ts_web/elements/00group-workspace/dees-workspace-monaco/index.ts new file mode 100644 index 0000000..01a3b97 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-monaco/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-monaco.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-monaco/version.ts b/ts_web/elements/00group-workspace/dees-workspace-monaco/version.ts similarity index 100% rename from ts_web/elements/00group-editor/dees-editor-monaco/version.ts rename to ts_web/elements/00group-workspace/dees-workspace-monaco/version.ts diff --git a/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/dees-workspace-terminal-preview.ts b/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/dees-workspace-terminal-preview.ts new file mode 100644 index 0000000..5933e86 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/dees-workspace-terminal-preview.ts @@ -0,0 +1,361 @@ +import { + DeesElement, + property, + html, + customElement, + type TemplateResult, + css, + cssManager, +} from '@design.estate/dees-element'; +import { Terminal } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; +import { themeDefaultStyles } from '../../00theme.js'; + +declare global { + interface HTMLElementTagNameMap { + 'dees-workspace-terminal-preview': DeesWorkspaceTerminalPreview; + } +} + +/** + * A read-only terminal preview component using xterm.js for rendering. + * Used during workspace initialization to show onInit command progress. + */ +@customElement('dees-workspace-terminal-preview') +export class DeesWorkspaceTerminalPreview extends DeesElement { + public static demo = () => html` + + `; + + /** + * The command being displayed (shown in header) + */ + @property({ type: String }) + accessor command: string = ''; + + /** + * Output lines to display + */ + @property({ type: Array }) + accessor lines: string[] = []; + + private terminal: Terminal | null = null; + private fitAddon: FitAddon | null = null; + private lastLineCount: number = 0; + private resizeObserver: ResizeObserver | null = null; + + public static styles = [ + themeDefaultStyles, + cssManager.defaultStyles, + css` + :host { + display: block; + height: 200px; + } + + .terminal-preview { + height: 100%; + border-radius: 8px; + overflow: hidden; + background: #000000; + border: 1px solid hsl(0 0% 20%); + display: flex; + flex-direction: column; + } + + .terminal-header { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: hsl(0 0% 10%); + font-size: 12px; + font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace; + color: hsl(0 0% 60%); + border-bottom: 1px solid hsl(0 0% 20%); + flex-shrink: 0; + } + + .terminal-header-icon { + color: hsl(0 0% 50%); + } + + .terminal-header-command { + color: hsl(0 0% 80%); + font-weight: 500; + } + + .terminal-container { + flex: 1; + position: relative; + padding: 8px; + } + + #xterm-container { + position: absolute; + top: 8px; + left: 8px; + right: 8px; + bottom: 8px; + } + + /* xterm.js styles */ + .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; + z-index: 5; + } + + .xterm .xterm-helper-textarea { + padding: 0; + border: 0; + margin: 0; + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -5; + white-space: nowrap; + overflow: hidden; + resize: none; + } + + .xterm .composition-view { + background: #000000; + color: #fff; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; + } + + .xterm .composition-view.active { + display: block; + } + + .xterm .xterm-viewport { + background-color: #000000; + 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 { + cursor: default; + } + + .xterm.xterm-cursor-pointer { + cursor: pointer; + } + + .xterm.column-select.focus { + 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; + } + + /* Custom scrollbar for xterm viewport */ + .xterm .xterm-viewport::-webkit-scrollbar { + width: 8px; + } + + .xterm .xterm-viewport::-webkit-scrollbar-track { + background: hsl(0 0% 8%); + } + + .xterm .xterm-viewport::-webkit-scrollbar-thumb { + background: hsl(0 0% 25%); + border-radius: 4px; + } + + .xterm .xterm-viewport::-webkit-scrollbar-thumb:hover { + background: hsl(0 0% 35%); + } + `, + ]; + + public render(): TemplateResult { + return html` +
+
+ $ + ${this.command || 'Waiting...'} +
+
+
+
+
+ `; + } + + public async firstUpdated( + _changedProperties: Map + ): Promise { + super.firstUpdated(_changedProperties); + + const container = this.shadowRoot?.getElementById('xterm-container'); + if (!container) return; + + // Create xterm terminal in read-only mode + this.terminal = new Terminal({ + convertEol: true, + cursorBlink: false, + disableStdin: true, + fontSize: 12, + fontFamily: "'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace", + theme: { + background: '#000000', + foreground: '#cccccc', + }, + scrollback: 1000, + }); + + this.fitAddon = new FitAddon(); + this.terminal.loadAddon(this.fitAddon); + this.terminal.open(container); + this.fitAddon.fit(); + + // Set up resize observer to refit terminal + this.resizeObserver = new ResizeObserver(() => { + if (this.fitAddon) { + this.fitAddon.fit(); + } + }); + this.resizeObserver.observe(container); + + // Write any existing lines + this.writeNewLines(); + } + + public async updated(changedProperties: Map) { + super.updated(changedProperties); + + if (changedProperties.has('lines')) { + this.writeNewLines(); + } + } + + private writeNewLines() { + if (!this.terminal) return; + + // Write only new lines since last update + const newLines = this.lines.slice(this.lastLineCount); + for (const line of newLines) { + this.terminal.writeln(line); + } + this.lastLineCount = this.lines.length; + } + + public async disconnectedCallback(): Promise { + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + } + if (this.terminal) { + this.terminal.dispose(); + this.terminal = null; + } + await super.disconnectedCallback(); + } + + /** + * Add a new line to the output + */ + public addLine(line: string) { + this.lines = [...this.lines, line]; + } + + /** + * Clear all output lines + */ + public clear() { + this.lines = []; + this.lastLineCount = 0; + if (this.terminal) { + this.terminal.clear(); + } + } +} diff --git a/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/index.ts b/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/index.ts new file mode 100644 index 0000000..7d72d67 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-terminal-preview/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-terminal-preview.js'; diff --git a/ts_web/elements/dees-terminal/dees-terminal.ts b/ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts similarity index 96% rename from ts_web/elements/dees-terminal/dees-terminal.ts rename to ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts index c9a4c87..79b25f4 100644 --- a/ts_web/elements/dees-terminal/dees-terminal.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts @@ -11,21 +11,21 @@ import * as domtools from '@design.estate/dees-domtools'; import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; -import { themeDefaultStyles } from '../00theme.js'; -import type { IExecutionEnvironment } from '../00group-runtime/index.js'; -import { WebContainerEnvironment } from '../00group-runtime/index.js'; +import { themeDefaultStyles } from '../../00theme.js'; +import type { IExecutionEnvironment } from '../../00group-runtime/index.js'; +import { WebContainerEnvironment } from '../../00group-runtime/index.js'; declare global { interface HTMLElementTagNameMap { - 'dees-terminal': DeesTerminal; + 'dees-workspace-terminal': DeesWorkspaceTerminal; } } -@customElement('dees-terminal') -export class DeesTerminal extends DeesElement { +@customElement('dees-workspace-terminal') +export class DeesWorkspaceTerminal extends DeesElement { public static demo = () => { const env = new WebContainerEnvironment(); - return html``; + return html``; }; // INSTANCE diff --git a/ts_web/elements/00group-workspace/dees-workspace-terminal/index.ts b/ts_web/elements/00group-workspace/dees-workspace-terminal/index.ts new file mode 100644 index 0000000..061a727 --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-terminal/index.ts @@ -0,0 +1 @@ +export * from './dees-workspace-terminal.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts b/ts_web/elements/00group-workspace/dees-workspace/dees-workspace.ts similarity index 93% rename from ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts rename to ts_web/elements/00group-workspace/dees-workspace/dees-workspace.ts index 67cabe5..c84ede4 100644 --- a/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts +++ b/ts_web/elements/00group-workspace/dees-workspace/dees-workspace.ts @@ -13,18 +13,19 @@ import { themeDefaultStyles } from '../../00theme.js'; import type { IExecutionEnvironment, IFileWatcher } from '../../00group-runtime/index.js'; import { WebContainerEnvironment } from '../../00group-runtime/index.js'; import type { FileSystemTree } from '@webcontainer/api'; -import '../dees-editor-monaco/dees-editor-monaco.js'; -import '../dees-editor-filetree/dees-editor-filetree.js'; -import { DeesEditorFiletree } from '../dees-editor-filetree/dees-editor-filetree.js'; -import '../../dees-terminal/dees-terminal.js'; +import '../dees-workspace-monaco/dees-workspace-monaco.js'; +import '../dees-workspace-filetree/dees-workspace-filetree.js'; +import { DeesWorkspaceFiletree } from '../dees-workspace-filetree/dees-workspace-filetree.js'; +import '../dees-workspace-terminal/dees-workspace-terminal.js'; +import '../dees-workspace-terminal-preview/dees-workspace-terminal-preview.js'; import '../../dees-icon/dees-icon.js'; -import { DeesEditorMonaco } from '../dees-editor-monaco/dees-editor-monaco.js'; +import { DeesWorkspaceMonaco } from '../dees-workspace-monaco/dees-workspace-monaco.js'; import { TypeScriptIntelliSenseManager } from './typescript-intellisense.js'; import { DeesContextmenu } from '../../dees-contextmenu/dees-contextmenu.js'; declare global { interface HTMLElementTagNameMap { - 'dees-editor-workspace': DeesEditorWorkspace; + 'dees-workspace': DeesWorkspace; } } @@ -35,8 +36,8 @@ interface IOpenFile { modified: boolean; } -@customElement('dees-editor-workspace') -export class DeesEditorWorkspace extends DeesElement { +@customElement('dees-workspace') +export class DeesWorkspace extends DeesElement { public static demo = () => { const env = new WebContainerEnvironment(); @@ -175,10 +176,10 @@ testSmartPromise(); return html`
- + >
`; }; @@ -232,7 +233,7 @@ testSmartPromise(); resource: { path: string }; }> = []; - private editorElement: DeesEditorMonaco | null = null; + private editorElement: DeesWorkspaceMonaco | null = null; private initializationStarted: boolean = false; private intelliSenseManager: TypeScriptIntelliSenseManager | null = null; private intelliSenseInitialized: boolean = false; @@ -247,6 +248,13 @@ testSmartPromise(); accessor autoSave: boolean = false; private autoSaveInterval: ReturnType | null = null; + // Init terminal preview state + @state() + accessor initCommand: string = ''; + + @state() + accessor initOutput: string[] = []; + // Keyboard shortcut handler (bound for proper cleanup) private keydownHandler = (e: KeyboardEvent) => { // Cmd+S (Mac) or Ctrl+S (Windows/Linux) - Save @@ -630,6 +638,11 @@ testSmartPromise(); opacity: 0.5; } + @keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } + } + .initializing { display: flex; flex-direction: column; @@ -641,7 +654,17 @@ testSmartPromise(); gap: 12px; } - dees-editor-filetree { + .initializing dees-icon { + animation: spin 1s linear infinite; + } + + .initializing dees-workspace-terminal-preview { + margin-top: 24px; + width: 80%; + max-width: 600px; + } + + dees-workspace-filetree { position: absolute; top: 0; left: 0; @@ -649,7 +672,7 @@ testSmartPromise(); bottom: 0; } - dees-editor-monaco { + dees-workspace-monaco { position: absolute; top: 0; left: 0; @@ -657,7 +680,7 @@ testSmartPromise(); bottom: 0; } - dees-terminal { + dees-workspace-terminal { position: absolute; top: 0; left: 0; @@ -679,6 +702,12 @@ testSmartPromise();
Initializing workspace... + ${this.initCommand ? html` + + ` : ''}
`; } @@ -690,11 +719,11 @@ testSmartPromise(); class="filetree-panel ${this.isFileTreeCollapsed ? 'collapsed' : ''}" style="width: ${this.isFileTreeCollapsed ? 0 : this.fileTreeWidth}px" > - + > ` : ''} @@ -725,12 +754,12 @@ testSmartPromise(); Select a file to edit ` : html` - + > `} @@ -770,10 +799,10 @@ testSmartPromise();
- + >
${this.renderProblemsPanel()} @@ -856,12 +885,36 @@ testSmartPromise(); if (onInit && typeof onInit === 'string') { console.log('Executing onInit command:', onInit); + + // Set command for terminal preview display + this.initCommand = onInit; + this.initOutput = []; + // Parse command and args const [cmd, ...args] = onInit.split(' '); const process = await this.executionEnvironment.spawn(cmd, args); + + // Capture stdout/stderr for terminal preview + process.output.pipeTo( + new WritableStream({ + write: (data) => { + // Split data into lines and append + const lines = data.split('\n'); + for (const line of lines) { + if (line) { + this.initOutput = [...this.initOutput, line]; + } + } + }, + }) + ); + // Wait for completion const exitCode = await process.exit; console.log('onInit command completed with exit code:', exitCode); + + // Add completion message + this.initOutput = [...this.initOutput, '', `Command completed with exit code: ${exitCode}`]; } } } catch (error) { @@ -1212,7 +1265,7 @@ testSmartPromise(); // Wait for editor to be ready, then navigate to the line await this.updateComplete; - const editorElement = this.shadowRoot?.querySelector('dees-editor-monaco') as DeesEditorMonaco; + const editorElement = this.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; if (editorElement) { const editor = await editorElement.editorDeferred.promise; editor.revealLineInCenter(marker.startLineNumber); diff --git a/ts_web/elements/00group-editor/dees-editor-workspace/index.ts b/ts_web/elements/00group-workspace/dees-workspace/index.ts similarity index 51% rename from ts_web/elements/00group-editor/dees-editor-workspace/index.ts rename to ts_web/elements/00group-workspace/dees-workspace/index.ts index ab7e62f..ef7fabb 100644 --- a/ts_web/elements/00group-editor/dees-editor-workspace/index.ts +++ b/ts_web/elements/00group-workspace/dees-workspace/index.ts @@ -1,2 +1,2 @@ -export * from './dees-editor-workspace.js'; +export * from './dees-workspace.js'; export * from './typescript-intellisense.js'; diff --git a/ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts b/ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts similarity index 100% rename from ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts rename to ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts diff --git a/ts_web/elements/00group-workspace/index.ts b/ts_web/elements/00group-workspace/index.ts new file mode 100644 index 0000000..869d201 --- /dev/null +++ b/ts_web/elements/00group-workspace/index.ts @@ -0,0 +1,8 @@ +// Workspace Components +export * from './dees-workspace/index.js'; +export * from './dees-workspace-monaco/index.js'; +export * from './dees-workspace-filetree/index.js'; +export * from './dees-workspace-terminal/index.js'; +export * from './dees-workspace-terminal-preview/index.js'; +export * from './dees-workspace-markdown/index.js'; +export * from './dees-workspace-markdownoutlet/index.js'; diff --git a/ts_web/elements/dees-terminal/index.ts b/ts_web/elements/dees-terminal/index.ts deleted file mode 100644 index a3aa6e9..0000000 --- a/ts_web/elements/dees-terminal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dees-terminal.js'; diff --git a/ts_web/elements/index.ts b/ts_web/elements/index.ts index 2b44b36..0ce20e6 100644 --- a/ts_web/elements/index.ts +++ b/ts_web/elements/index.ts @@ -6,7 +6,7 @@ export * from './00group-appui/index.js'; export * from './00group-button/index.js'; export * from './00group-chart/index.js'; export * from './00group-dataview/index.js'; -export * from './00group-editor/index.js'; +export * from './00group-workspace/index.js'; export * from './00group-form/index.js'; export * from './00group-input/index.js'; export * from './00group-pdf/index.js'; @@ -34,7 +34,7 @@ export * from './dees-spinner/index.js'; export * from './dees-statsgrid/index.js'; export * from './dees-stepper/index.js'; export * from './dees-table/index.js'; -export * from './dees-terminal/index.js'; +// dees-terminal is now part of 00group-workspace as dees-workspace-terminal export * from './dees-toast/index.js'; export * from './dees-updater/index.js'; export * from './dees-windowcontrols/index.js';