diff --git a/.playwright-mcp/markdown-outlet-bright-bottom.png b/.playwright-mcp/markdown-outlet-bright-bottom.png new file mode 100644 index 0000000..a42c154 Binary files /dev/null and b/.playwright-mcp/markdown-outlet-bright-bottom.png differ diff --git a/.playwright-mcp/markdown-outlet-bright.png b/.playwright-mcp/markdown-outlet-bright.png new file mode 100644 index 0000000..a42c154 Binary files /dev/null and b/.playwright-mcp/markdown-outlet-bright.png differ diff --git a/.playwright-mcp/markdown-outlet-dark.png b/.playwright-mcp/markdown-outlet-dark.png new file mode 100644 index 0000000..4847028 Binary files /dev/null and b/.playwright-mcp/markdown-outlet-dark.png differ diff --git a/.playwright-mcp/markdown-outlet-full.png b/.playwright-mcp/markdown-outlet-full.png new file mode 100644 index 0000000..bc20b6d Binary files /dev/null and b/.playwright-mcp/markdown-outlet-full.png differ diff --git a/changelog.md b/changelog.md index a69d543..527c1ff 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-12-31 - 3.22.0 - feat(workspace) +add resizable markdown editor/preview split with draggable handle and markdown outlet styling/demo + +- Introduce a flexible split layout for the workspace markdown editor with a draggable resize handle (splitRatio, minPanelSize, dragging state, mouse handlers and cleanup). +- Enhance dees-workspace-markdown: switch from grid to flex, add resize handle UI, prevent pointer selection while dragging, notify Monaco on resize. +- Add comprehensive styling and demo content for dees-workspace-markdownoutlet (dark/light themed markdown styles, syntax highlighting classes, and demo scenarios). +- Fix typescript-intellisense monaco model update: only set model value when content actually changed to avoid cursor resets. +- Add markdown outlet demo helper and numerous screenshot/image assets (.playwright-mcp) for demos/documentation. + ## 2025-12-31 - 3.21.0 - feat(terminal) add dynamic bright/dark theming for terminal components and terminal preview diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 9c2bd38..ffcf0b2 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.21.0', + version: '3.22.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-workspace/dees-workspace-markdown/dees-workspace-markdown.ts b/ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts index c4f8386..54f7be4 100644 --- a/ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-markdown/dees-workspace-markdown.ts @@ -6,7 +6,8 @@ import { type TemplateResult, css, cssManager, - domtools + domtools, + state, } from '@design.estate/dees-element'; import { themeDefaultStyles } from '../../00theme.js'; import { DeesWorkspaceMonaco } from '../dees-workspace-monaco/dees-workspace-monaco.js'; @@ -27,31 +28,113 @@ export class DeesWorkspaceMarkdown extends DeesElement { themeDefaultStyles, cssManager.defaultStyles, css` - /* TODO: Migrate hardcoded values to --dees-* CSS variables */ - .gridcontainer { + :host { + display: block; + position: relative; + width: 100%; + height: 100%; + } + + .splitContainer { position: absolute; height: 100%; width: 100%; - display: grid; - grid-template-columns: 60% 40%; + display: flex; + flex-direction: row; } + .editorContainer { position: relative; + height: 100%; + min-width: 100px; + overflow: hidden; } + + .resizeHandle { + width: 6px; + height: 100%; + background: ${cssManager.bdTheme('#e5e7eb', '#30363d')}; + cursor: col-resize; + flex-shrink: 0; + transition: background 0.15s ease; + position: relative; + } + + .resizeHandle:hover, + .resizeHandle.dragging { + background: ${cssManager.bdTheme('#3b82f6', '#58a6ff')}; + } + + .resizeHandle::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 2px; + height: 32px; + background: ${cssManager.bdTheme('#9ca3af', '#6e7681')}; + border-radius: 1px; + opacity: 0.6; + } + + .resizeHandle:hover::after, + .resizeHandle.dragging::after { + background: ${cssManager.bdTheme('#ffffff', '#ffffff')}; + opacity: 1; + } + .outletContainer { - background: #111; - color: #fff; - font-family: 'Roboto Slab'; + position: relative; + height: 100%; + min-width: 100px; + background: ${cssManager.bdTheme('#ffffff', '#0d1117')}; + color: ${cssManager.bdTheme('#24292f', '#e6edf3')}; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; padding: 20px; - overflow-y: scroll; + overflow-y: auto; + box-sizing: border-box; + } + + /* Prevent text selection while dragging */ + .splitContainer.dragging { + user-select: none; + } + + .splitContainer.dragging .editorContainer, + .splitContainer.dragging .outletContainer { + pointer-events: none; } `, ]; + /** + * Initial split ratio for the editor (left) panel. + * Value from 0 to 100 representing percentage width. + * Default is 50 (50/50 split). + */ + @property({ type: Number }) + accessor splitRatio: number = 50; + + /** + * Minimum width percentage for either panel. + */ + @property({ type: Number }) + accessor minPanelSize: number = 10; + + @state() + accessor currentSplitRatio: number = 50; + + @state() + accessor isDragging: boolean = false; + + private resizeHandleElement: HTMLElement; + private containerElement: HTMLElement; + public render() { return html` -
-
+
+
-
+
+
@@ -87,9 +174,17 @@ const hello = 'yes' public async firstUpdated(_changedPropertiesArg) { await super.firstUpdated(_changedPropertiesArg); + + // Initialize current ratio from property + this.currentSplitRatio = this.splitRatio; + + // Cache elements + this.containerElement = this.shadowRoot.querySelector('.splitContainer'); + this.resizeHandleElement = this.shadowRoot.querySelector('.resizeHandle'); + const editor = this.shadowRoot.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; - // lets care about wiring the markdown stuff. + // Wire up markdown rendering const markdownOutlet = this.shadowRoot.querySelector('dees-workspace-markdownoutlet'); const smartmarkdownInstance = new domtools.plugins.smartmarkdown.SmartMarkdown(); const mdParsedResult = await smartmarkdownInstance.getMdParsedResultFromMarkdown('loading...') @@ -97,6 +192,64 @@ const hello = 'yes' await mdParsedResult.updateFromMarkdownString(contentArg) const html = mdParsedResult.html; markdownOutlet.updateHtmlText(html); - }) + }); + } + + private handleMouseDown = (e: MouseEvent) => { + e.preventDefault(); + this.isDragging = true; + + document.addEventListener('mousemove', this.handleMouseMove); + document.addEventListener('mouseup', this.handleMouseUp); + }; + + private handleMouseMove = (e: MouseEvent) => { + if (!this.isDragging || !this.containerElement) return; + + const containerRect = this.containerElement.getBoundingClientRect(); + const containerWidth = containerRect.width; + const mouseX = e.clientX - containerRect.left; + + // Calculate percentage, accounting for the resize handle width (6px) + let newRatio = (mouseX / containerWidth) * 100; + + // Clamp to min/max + newRatio = Math.max(this.minPanelSize, Math.min(100 - this.minPanelSize, newRatio)); + + this.currentSplitRatio = newRatio; + }; + + private handleMouseUp = () => { + this.isDragging = false; + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('mouseup', this.handleMouseUp); + + // Trigger resize on monaco editor + const editor = this.shadowRoot.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco; + if (editor) { + // Monaco needs to be notified of size changes + window.dispatchEvent(new Event('resize')); + } + }; + + async disconnectedCallback() { + await super.disconnectedCallback(); + // Clean up event listeners + document.removeEventListener('mousemove', this.handleMouseMove); + document.removeEventListener('mouseup', this.handleMouseUp); + } + + /** + * Programmatically set the split ratio + */ + public setSplitRatio(ratio: number) { + this.currentSplitRatio = Math.max(this.minPanelSize, Math.min(100 - this.minPanelSize, ratio)); + } + + /** + * Reset to initial split ratio + */ + public resetSplitRatio() { + this.currentSplitRatio = this.splitRatio; } } diff --git a/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.demo.ts b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.demo.ts new file mode 100644 index 0000000..3d8567a --- /dev/null +++ b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.demo.ts @@ -0,0 +1,289 @@ +import { html, css } from '@design.estate/dees-element'; +import '@design.estate/dees-wcctools/demotools'; +import '../../dees-panel/dees-panel.js'; +import type { DeesWorkspaceMarkdownoutlet } from './dees-workspace-markdownoutlet.js'; + +export const demoFunc = () => html` + + + +
+ + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +

Heading Level 1

+

Heading Level 2

+

Heading Level 3

+

Heading Level 4

+
Heading Level 5
+
Heading Level 6
+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +

This is a paragraph with bold text and italic text.

+

You can also use bold italic for emphasis.

+

Here's a link example and some inline code.

+

Press Ctrl + C to copy text.

+
+

Above is a horizontal rule separator.

+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +

Unordered List

+
    +
  • First item
  • +
  • Second item +
      +
    • Nested item 1
    • +
    • Nested item 2
    • +
    +
  • +
  • Third item
  • +
+ +

Ordered List

+
    +
  1. Step one
  2. +
  3. Step two
  4. +
  5. Step three
  6. +
+ +

Task List

+
    +
  • Completed task
  • +
  • Pending task
  • +
  • Another task
  • +
+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +

Inline code: const greeting = "Hello, World!";

+ +

TypeScript Example

+
import { html, css } from '@design.estate/dees-element';
+
+interface IUser {
+  name: string;
+  email: string;
+  age?: number;
+}
+
+const getUser = async (id: string): Promise<IUser> => {
+  const response = await fetch(\`/api/users/\${id}\`);
+  return response.json();
+};
+ +

JSON Example

+
{
+  "name": "dees-catalog",
+  "version": "3.0.0",
+  "dependencies": {
+    "@design.estate/dees-element": "^2.0.0"
+  }
+}
+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureStatusPriority
Dark mode supportCompletedHigh
Responsive designIn ProgressMedium
AccessibilityPlannedHigh
DocumentationIn ProgressLow
+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +
+

This is a standard blockquote. It's great for highlighting important information or quotes from other sources.

+
+ +
+

Note: This is an informational note to draw attention to important details.

+
+ +
+

Tip: Here's a helpful tip to improve your workflow.

+
+ +
+

Important: This information is crucial for understanding the topic.

+
+ +
+

Warning: Be careful when performing this action.

+
+ +
+

Caution: This action may have unintended consequences.

+
+ `); + }} + > + +
+ + + { + const outlet = panelEl.querySelector('dees-workspace-markdownoutlet') as DeesWorkspaceMarkdownoutlet; + await outlet?.updateHtmlText(` +

Getting Started Guide

+

Welcome to the dees-catalog component library. This guide will help you get up and running quickly.

+ +

Installation

+

Install the package using your preferred package manager:

+
# Using pnpm (recommended)
+pnpm add @design.estate/dees-catalog
+
+# Using npm
+npm install @design.estate/dees-catalog
+ +

Basic Usage

+

Import and use components in your TypeScript files:

+
import { DeesButton } from '@design.estate/dees-catalog';
+
+// Use in your templates
+html\`<dees-button>Click me</dees-button>\`
+ +
+

Tip: Check the demo showcase for live examples of all components.

+
+ +

Available Components

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentDescription
dees-buttonPrimary button component
dees-input-textText input field
dees-tableData table with sorting
dees-modalModal dialog
+ +

Next Steps

+ + +
+

"The best component library is one that gets out of your way." — Design Systems Team

+
+ `); + }} + > + +
+
+
+`; diff --git a/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts index 5a18c2f..1f3ab58 100644 --- a/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts +++ b/ts_web/elements/00group-workspace/dees-workspace-markdownoutlet/dees-workspace-markdownoutlet.ts @@ -1,4 +1,13 @@ -import { customElement, DeesElement, html, type TemplateResult } from '@design.estate/dees-element'; +import { + customElement, + DeesElement, + html, + type TemplateResult, + css, + cssManager, +} from '@design.estate/dees-element'; +import { themeDefaultStyles } from '../../00theme.js'; +import { demoFunc } from './dees-workspace-markdownoutlet.demo.js'; declare global { interface HTMLElementTagNameMap { @@ -9,27 +18,382 @@ declare global { @customElement('dees-workspace-markdownoutlet') export class DeesWorkspaceMarkdownoutlet extends DeesElement { // DEMO - public static demo = () => html``; + public static demo = demoFunc; + + public static styles = [ + themeDefaultStyles, + cssManager.defaultStyles, + css` + :host { + display: block; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 1.6; + color: ${cssManager.bdTheme('#24292f', '#e6edf3')}; + } + + .outlet { + word-wrap: break-word; + } + + /* Headings */ + h1, h2, h3, h4, h5, h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; + color: ${cssManager.bdTheme('#1f2328', '#f0f6fc')}; + } + + h1 { + font-size: 2em; + padding-bottom: 0.3em; + border-bottom: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + } + + h2 { + font-size: 1.5em; + padding-bottom: 0.3em; + border-bottom: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + } + + h3 { + font-size: 1.25em; + } + + h4 { + font-size: 1em; + } + + h5 { + font-size: 0.875em; + } + + h6 { + font-size: 0.85em; + color: ${cssManager.bdTheme('#656d76', '#8b949e')}; + } + + /* Paragraphs and text */ + p { + margin-top: 0; + margin-bottom: 16px; + } + + /* Links */ + a { + color: ${cssManager.bdTheme('#0969da', '#58a6ff')}; + text-decoration: none; + } + + a:hover { + text-decoration: underline; + } + + /* Strong and emphasis */ + strong { + font-weight: 600; + color: ${cssManager.bdTheme('#1f2328', '#f0f6fc')}; + } + + em { + font-style: italic; + } + + /* Lists */ + ul, ol { + margin-top: 0; + margin-bottom: 16px; + padding-left: 2em; + } + + li { + margin-top: 4px; + } + + li + li { + margin-top: 4px; + } + + ul ul, ul ol, ol ul, ol ol { + margin-top: 0; + margin-bottom: 0; + } + + /* Blockquotes */ + blockquote { + margin: 0 0 16px 0; + padding: 0 1em; + color: ${cssManager.bdTheme('#656d76', '#8b949e')}; + border-left: 4px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + } + + blockquote > :first-child { + margin-top: 0; + } + + blockquote > :last-child { + margin-bottom: 0; + } + + /* Inline code */ + code { + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace; + background-color: ${cssManager.bdTheme('rgba(175, 184, 193, 0.2)', 'rgba(110, 118, 129, 0.4)')}; + border-radius: 6px; + white-space: break-spaces; + } + + /* Code blocks */ + pre { + margin-top: 0; + margin-bottom: 16px; + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace; + background-color: ${cssManager.bdTheme('#f6f8fa', '#161b22')}; + border-radius: 6px; + word-wrap: normal; + } + + pre code { + display: block; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; + font-size: 100%; + white-space: pre; + } + + /* Tables */ + table { + width: max-content; + max-width: 100%; + margin-top: 0; + margin-bottom: 16px; + border-spacing: 0; + border-collapse: collapse; + overflow: auto; + display: block; + } + + table th { + font-weight: 600; + padding: 6px 13px; + border: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + background-color: ${cssManager.bdTheme('#f6f8fa', '#161b22')}; + color: ${cssManager.bdTheme('#1f2328', '#e6edf3')}; + } + + table td { + padding: 6px 13px; + border: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + color: ${cssManager.bdTheme('#1f2328', '#e6edf3')}; + } + + table tr { + background-color: ${cssManager.bdTheme('#ffffff', '#0d1117')}; + border-top: 1px solid ${cssManager.bdTheme('#d1d9e0', '#21262d')}; + } + + table tr:nth-child(2n) { + background-color: ${cssManager.bdTheme('#f6f8fa', '#161b22')}; + } + + /* Horizontal rules */ + hr { + height: 4px; + padding: 0; + margin: 24px 0; + background-color: ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + border: 0; + border-radius: 2px; + } + + /* Images */ + img { + max-width: 100%; + box-sizing: border-box; + border-radius: 6px; + } + + /* Task lists */ + .task-list-item { + list-style-type: none; + } + + .task-list-item input { + margin: 0 0.2em 0.25em -1.4em; + vertical-align: middle; + } + + /* Definition lists */ + dl { + padding: 0; + } + + dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; + } + + dl dd { + padding: 0 16px; + margin-bottom: 16px; + } + + /* Keyboard input */ + kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace; + line-height: 10px; + color: ${cssManager.bdTheme('#1f2328', '#e6edf3')}; + vertical-align: middle; + background-color: ${cssManager.bdTheme('#f6f8fa', '#161b22')}; + border: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + border-radius: 6px; + box-shadow: inset 0 -1px 0 ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + } + + /* Footnotes */ + .footnotes { + font-size: 12px; + color: ${cssManager.bdTheme('#656d76', '#8b949e')}; + border-top: 1px solid ${cssManager.bdTheme('#d1d9e0', '#30363d')}; + padding-top: 16px; + margin-top: 32px; + } + + /* Alerts/Admonitions */ + .markdown-alert { + padding: 8px 16px; + margin-bottom: 16px; + border-left: 4px solid; + border-radius: 6px; + } + + .markdown-alert-note { + border-color: ${cssManager.bdTheme('#0969da', '#58a6ff')}; + background-color: ${cssManager.bdTheme('rgba(9, 105, 218, 0.1)', 'rgba(56, 139, 253, 0.1)')}; + } + + .markdown-alert-warning { + border-color: ${cssManager.bdTheme('#bf8700', '#d29922')}; + background-color: ${cssManager.bdTheme('rgba(191, 135, 0, 0.1)', 'rgba(187, 128, 9, 0.1)')}; + } + + .markdown-alert-important { + border-color: ${cssManager.bdTheme('#8250df', '#a371f7')}; + background-color: ${cssManager.bdTheme('rgba(130, 80, 223, 0.1)', 'rgba(163, 113, 247, 0.1)')}; + } + + .markdown-alert-caution { + border-color: ${cssManager.bdTheme('#cf222e', '#f85149')}; + background-color: ${cssManager.bdTheme('rgba(207, 34, 46, 0.1)', 'rgba(248, 81, 73, 0.1)')}; + } + + .markdown-alert-tip { + border-color: ${cssManager.bdTheme('#1a7f37', '#3fb950')}; + background-color: ${cssManager.bdTheme('rgba(26, 127, 55, 0.1)', 'rgba(46, 160, 67, 0.1)')}; + } + + /* Syntax highlighting for code blocks */ + .hljs-comment, + .hljs-quote { + color: ${cssManager.bdTheme('#6a737d', '#8b949e')}; + } + + .hljs-keyword, + .hljs-selector-tag, + .hljs-addition { + color: ${cssManager.bdTheme('#d73a49', '#ff7b72')}; + } + + .hljs-number, + .hljs-string, + .hljs-meta .hljs-meta-string, + .hljs-literal, + .hljs-doctag, + .hljs-regexp { + color: ${cssManager.bdTheme('#032f62', '#a5d6ff')}; + } + + .hljs-title, + .hljs-section, + .hljs-name, + .hljs-selector-id, + .hljs-selector-class { + color: ${cssManager.bdTheme('#6f42c1', '#d2a8ff')}; + } + + .hljs-attribute, + .hljs-attr, + .hljs-variable, + .hljs-template-variable, + .hljs-class .hljs-title, + .hljs-type { + color: ${cssManager.bdTheme('#005cc5', '#79c0ff')}; + } + + .hljs-symbol, + .hljs-bullet, + .hljs-subst, + .hljs-meta, + .hljs-meta .hljs-keyword, + .hljs-selector-attr, + .hljs-selector-pseudo, + .hljs-link { + color: ${cssManager.bdTheme('#e36209', '#ffa657')}; + } + + .hljs-built_in, + .hljs-deletion { + color: ${cssManager.bdTheme('#b31d28', '#ffa198')}; + } + + .hljs-formula { + background-color: ${cssManager.bdTheme('#f6f8fa', '#161b22')}; + } + + .hljs-emphasis { + font-style: italic; + } + + .hljs-strong { + font-weight: bold; + } + `, + ]; // INSTANCE private outlet: HTMLElement; public render(): TemplateResult { return html` -
-

Hi there

+
+

Markdown Preview

+

Content will appear here when markdown is parsed.

`; } 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); + this.outlet = this.shadowRoot.querySelector('.outlet'); } public async updateHtmlText(htmlTextArg: string) { diff --git a/ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts b/ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts index 41e240d..08220a5 100644 --- a/ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts +++ b/ts_web/elements/00group-workspace/dees-workspace/typescript-intellisense.ts @@ -378,7 +378,10 @@ export class TypeScriptIntelliSenseManager { const existingModel = this.monacoInstance.editor.getModel(uri); if (existingModel) { - existingModel.setValue(content); + // Only update if content actually changed (prevents cursor reset) + if (existingModel.getValue() !== content) { + existingModel.setValue(content); + } } else { const language = this.getLanguageFromPath(path); this.monacoInstance.editor.createModel(content, language, uri);