@pyreon/code 0.11.4 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["CMGutterMarker","placeholderExt","undo","redo","setDiagnostics","cmSetDiagnostics"],"sources":["../../../core/core/lib/jsx-runtime.js","../src/components/code-editor.tsx","../src/languages.ts","../src/themes.ts","../src/components/diff-editor.tsx","../src/components/tabbed-editor.tsx","../src/minimap.ts","../src/editor.ts"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from \"@pyreon/core\"\nimport type { CodeEditorProps, EditorInstance } from \"../types\"\n\n/**\n * Code editor component — mounts a CodeMirror 6 instance.\n *\n * @example\n * ```tsx\n * const editor = createEditor({\n * value: 'const x = 1',\n * language: 'typescript',\n * theme: 'dark',\n * })\n *\n * <CodeEditor instance={editor} style=\"height: 400px\" />\n * ```\n */\nexport function CodeEditor(props: CodeEditorProps): VNodeChild {\n const { instance } = props\n\n const containerRef = (el: Element | null) => {\n if (!el) return\n\n // Mount the editor into the container\n const mountable = instance as EditorInstance & {\n _mount?: (parent: HTMLElement) => Promise<void>\n }\n if (mountable._mount) {\n mountable._mount(el as HTMLElement)\n }\n }\n\n const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? \"\"}`\n\n return (\n <div ref={containerRef} class={`pyreon-code-editor ${props.class ?? \"\"}`} style={baseStyle} />\n )\n}\n","import type { Extension } from \"@codemirror/state\"\nimport type { EditorLanguage } from \"./types\"\n\n/**\n * Language extension loaders — lazy-loaded on demand.\n * Only the requested language is imported, keeping the initial bundle small.\n */\nconst languageLoaders: Record<EditorLanguage, () => Promise<Extension>> = {\n javascript: () => import(\"@codemirror/lang-javascript\").then((m) => m.javascript()),\n typescript: () =>\n import(\"@codemirror/lang-javascript\").then((m) => m.javascript({ typescript: true })),\n jsx: () => import(\"@codemirror/lang-javascript\").then((m) => m.javascript({ jsx: true })),\n tsx: () =>\n import(\"@codemirror/lang-javascript\").then((m) =>\n m.javascript({ typescript: true, jsx: true }),\n ),\n html: () => import(\"@codemirror/lang-html\").then((m) => m.html()),\n css: () => import(\"@codemirror/lang-css\").then((m) => m.css()),\n json: () => import(\"@codemirror/lang-json\").then((m) => m.json()),\n markdown: () => import(\"@codemirror/lang-markdown\").then((m) => m.markdown()),\n python: () => import(\"@codemirror/lang-python\").then((m) => m.python()),\n rust: () => import(\"@codemirror/lang-rust\").then((m) => m.rust()),\n sql: () => import(\"@codemirror/lang-sql\").then((m) => m.sql()),\n xml: () => import(\"@codemirror/lang-xml\").then((m) => m.xml()),\n yaml: () => import(\"@codemirror/lang-yaml\").then((m) => m.yaml()),\n cpp: () => import(\"@codemirror/lang-cpp\").then((m) => m.cpp()),\n java: () => import(\"@codemirror/lang-java\").then((m) => m.java()),\n go: () => import(\"@codemirror/lang-go\").then((m) => m.go()),\n php: () => import(\"@codemirror/lang-php\").then((m) => m.php()),\n ruby: () => Promise.resolve([]),\n shell: () => Promise.resolve([]),\n plain: () => Promise.resolve([]),\n}\n\n// Cache loaded language extensions\nconst loaded = new Map<EditorLanguage, Extension>()\n\n/**\n * Load a language extension. Returns cached if already loaded.\n * Language grammars are lazy-imported — zero cost until used.\n *\n * @example\n * ```ts\n * const ext = await loadLanguage('typescript')\n * ```\n */\nexport async function loadLanguage(language: EditorLanguage): Promise<Extension> {\n const cached = loaded.get(language)\n if (cached) return cached\n\n const loader = languageLoaders[language]\n if (!loader) return []\n\n try {\n const ext = await loader()\n loaded.set(language, ext)\n return ext\n } catch {\n // Language package not installed — return empty extension\n return []\n }\n}\n\n/**\n * Get available languages.\n */\nexport function getAvailableLanguages(): EditorLanguage[] {\n return Object.keys(languageLoaders) as EditorLanguage[]\n}\n","import type { Extension } from \"@codemirror/state\"\nimport { EditorView } from \"@codemirror/view\"\nimport type { EditorTheme } from \"./types\"\n\n/**\n * Light theme — clean, minimal.\n */\nexport const lightTheme: Extension = EditorView.theme({\n \"&\": {\n backgroundColor: \"#ffffff\",\n color: \"#1e293b\",\n },\n \".cm-content\": {\n caretColor: \"#1e293b\",\n },\n \".cm-cursor\": {\n borderLeftColor: \"#1e293b\",\n },\n \"&.cm-focused .cm-selectionBackground, .cm-selectionBackground\": {\n backgroundColor: \"#dbeafe\",\n },\n \".cm-gutters\": {\n backgroundColor: \"#f8fafc\",\n color: \"#94a3b8\",\n borderRight: \"1px solid #e2e8f0\",\n },\n \".cm-activeLineGutter\": {\n backgroundColor: \"#f1f5f9\",\n color: \"#475569\",\n },\n \".cm-activeLine\": {\n backgroundColor: \"#f8fafc\",\n },\n \".cm-foldGutter\": {\n color: \"#94a3b8\",\n },\n})\n\n/**\n * Dark theme — VS Code inspired.\n */\nexport const darkTheme: Extension = EditorView.theme(\n {\n \"&\": {\n backgroundColor: \"#1e1e2e\",\n color: \"#cdd6f4\",\n },\n \".cm-content\": {\n caretColor: \"#f5e0dc\",\n },\n \".cm-cursor\": {\n borderLeftColor: \"#f5e0dc\",\n },\n \"&.cm-focused .cm-selectionBackground, .cm-selectionBackground\": {\n backgroundColor: \"#45475a\",\n },\n \".cm-gutters\": {\n backgroundColor: \"#181825\",\n color: \"#585b70\",\n borderRight: \"1px solid #313244\",\n },\n \".cm-activeLineGutter\": {\n backgroundColor: \"#1e1e2e\",\n color: \"#a6adc8\",\n },\n \".cm-activeLine\": {\n backgroundColor: \"#1e1e2e80\",\n },\n \".cm-foldGutter\": {\n color: \"#585b70\",\n },\n \".cm-matchingBracket\": {\n backgroundColor: \"#45475a\",\n color: \"#f5e0dc\",\n },\n },\n { dark: true },\n)\n\n/**\n * Resolve a theme value to a CodeMirror extension.\n */\nexport function resolveTheme(theme: EditorTheme): Extension {\n if (theme === \"light\") return lightTheme\n if (theme === \"dark\") return darkTheme\n return theme // custom Extension\n}\n","import { defaultHighlightStyle, syntaxHighlighting } from \"@codemirror/language\"\nimport { MergeView } from \"@codemirror/merge\"\nimport { EditorState, type Extension } from \"@codemirror/state\"\nimport { EditorView } from \"@codemirror/view\"\nimport type { VNodeChild } from \"@pyreon/core\"\nimport type { Signal } from \"@pyreon/reactivity\"\nimport { loadLanguage } from \"../languages\"\nimport { resolveTheme } from \"../themes\"\nimport type { DiffEditorProps } from \"../types\"\n\n/**\n * Side-by-side or inline diff editor using @codemirror/merge.\n *\n * @example\n * ```tsx\n * <DiffEditor\n * original=\"const x = 1\"\n * modified=\"const x = 2\"\n * language=\"typescript\"\n * theme=\"dark\"\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function DiffEditor(props: DiffEditorProps): VNodeChild {\n const {\n original,\n modified,\n language = \"plain\",\n theme = \"light\",\n readOnly = true,\n inline = false,\n } = props\n\n const containerRef = async (el: Element | null) => {\n if (!el) return\n\n const langExt = await loadLanguage(language)\n const themeExt = resolveTheme(theme)\n\n const extensions: Extension[] = [\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n langExt,\n themeExt,\n EditorView.editable.of(!readOnly),\n EditorState.readOnly.of(readOnly),\n ]\n\n const originalText = typeof original === \"string\" ? original : (original as Signal<string>)()\n const modifiedText = typeof modified === \"string\" ? modified : (modified as Signal<string>)()\n\n // Clear previous content\n ;(el as HTMLElement).innerHTML = \"\"\n\n if (inline) {\n // Unified/inline diff view\n new MergeView({\n a: {\n doc: originalText,\n extensions,\n },\n b: {\n doc: modifiedText,\n extensions,\n },\n parent: el as HTMLElement,\n collapseUnchanged: { margin: 3, minSize: 4 },\n })\n } else {\n // Side-by-side diff\n new MergeView({\n a: {\n doc: originalText,\n extensions,\n },\n b: {\n doc: modifiedText,\n extensions,\n },\n parent: el as HTMLElement,\n collapseUnchanged: { margin: 3, minSize: 4 },\n })\n }\n }\n\n const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? \"\"}`\n\n return (\n <div ref={containerRef} class={`pyreon-diff-editor ${props.class ?? \"\"}`} style={baseStyle} />\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { TabbedEditorProps } from \"../types\"\nimport { CodeEditor } from \"./code-editor\"\n\n/**\n * Tabbed code editor component — renders tab bar + editor.\n * Headless styling — the tab bar is a plain div with button tabs.\n * Consumers can style via CSS classes.\n *\n * @example\n * ```tsx\n * const editor = createTabbedEditor({\n * tabs: [\n * { name: 'index.ts', language: 'typescript', value: 'const x = 1' },\n * { name: 'style.css', language: 'css', value: '.app { }' },\n * ],\n * theme: 'dark',\n * })\n *\n * <TabbedEditor instance={editor} style=\"height: 500px\" />\n * ```\n */\nexport function TabbedEditor(props: TabbedEditorProps): VNodeChild {\n const { instance } = props\n\n const containerStyle = `display: flex; flex-direction: column; width: 100%; height: 100%; ${props.style ?? \"\"}`\n\n const tabBarStyle =\n \"display: flex; overflow-x: auto; background: #f1f5f9; border-bottom: 1px solid #e2e8f0; min-height: 34px; flex-shrink: 0;\"\n\n return (\n <div class={`pyreon-tabbed-editor ${props.class ?? \"\"}`} style={containerStyle}>\n {() => {\n const tabs = instance.tabs()\n const activeId = instance.activeTabId()\n\n return (\n <div class=\"pyreon-tabbed-editor-tabs\" style={tabBarStyle}>\n {tabs.map((tab) => {\n const id = tab.id ?? tab.name\n const isActive = id === activeId\n\n const tabStyle = `display: flex; align-items: center; gap: 6px; padding: 6px 12px; border: none; background: ${isActive ? \"white\" : \"transparent\"}; border-bottom: ${isActive ? \"2px solid #3b82f6\" : \"2px solid transparent\"}; cursor: pointer; font-size: 13px; color: ${isActive ? \"#1e293b\" : \"#64748b\"}; white-space: nowrap; position: relative; font-family: inherit;`\n\n return (\n <button\n type=\"button\"\n key={id}\n class={`pyreon-tab ${isActive ? \"active\" : \"\"} ${tab.modified ? \"modified\" : \"\"}`}\n style={tabStyle}\n onClick={() => instance.switchTab(id)}\n >\n <span>{tab.name}</span>\n {tab.modified && (\n <span\n style=\"width: 6px; height: 6px; border-radius: 50%; background: #f59e0b; flex-shrink: 0;\"\n title=\"Modified\"\n />\n )}\n {tab.closable !== false && (\n <span\n style=\"font-size: 14px; line-height: 1; opacity: 0.5; cursor: pointer; padding: 0 2px; margin-left: 2px;\"\n title=\"Close\"\n onClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance.closeTab(id)\n }}\n >\n ×\n </span>\n )}\n </button>\n )\n })}\n </div>\n )\n }}\n <div style=\"flex: 1; min-height: 0;\">\n <CodeEditor instance={instance.editor} />\n </div>\n </div>\n )\n}\n","import type { Extension } from \"@codemirror/state\"\nimport { EditorView, ViewPlugin, type ViewUpdate } from \"@codemirror/view\"\n\n/**\n * Canvas-based minimap extension for CodeMirror 6.\n * Renders a scaled-down overview of the document on the right side.\n */\n\nconst MINIMAP_WIDTH = 80\nconst CHAR_WIDTH = 1.2\nconst LINE_HEIGHT = 2.5\nconst MINIMAP_BG = \"#1e1e2e\"\nconst MINIMAP_BG_LIGHT = \"#f8fafc\"\nconst TEXT_COLOR = \"#585b70\"\nconst TEXT_COLOR_LIGHT = \"#94a3b8\"\nconst VIEWPORT_COLOR = \"rgba(59, 130, 246, 0.15)\"\nconst VIEWPORT_BORDER = \"rgba(59, 130, 246, 0.4)\"\n\nfunction createMinimapCanvas(): HTMLCanvasElement {\n const canvas = document.createElement(\"canvas\")\n canvas.style.cssText = `position: absolute; right: 0; top: 0; width: ${MINIMAP_WIDTH}px; height: 100%; cursor: pointer; z-index: 5;`\n canvas.width = MINIMAP_WIDTH * 2 // retina\n return canvas\n}\n\nfunction renderMinimap(canvas: HTMLCanvasElement, view: EditorView): void {\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n const doc = view.state.doc\n const totalLines = doc.lines\n const height = canvas.clientHeight\n canvas.height = height * 2 // retina\n\n const isDark = view.dom.classList.contains(\"cm-dark\")\n const bg = isDark ? MINIMAP_BG : MINIMAP_BG_LIGHT\n const textColor = isDark ? TEXT_COLOR : TEXT_COLOR_LIGHT\n\n const scale = 2 // retina\n ctx.setTransform(scale, 0, 0, scale, 0, 0)\n\n // Background\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, MINIMAP_WIDTH, height)\n\n // Calculate visible range in minimap\n const contentHeight = totalLines * LINE_HEIGHT\n const scrollFraction =\n contentHeight > height\n ? view.scrollDOM.scrollTop / (view.scrollDOM.scrollHeight - view.scrollDOM.clientHeight || 1)\n : 0\n const offset = contentHeight > height ? scrollFraction * (contentHeight - height) : 0\n\n // Render text lines\n ctx.fillStyle = textColor\n const startLine = Math.max(1, Math.floor(offset / LINE_HEIGHT))\n const endLine = Math.min(totalLines, startLine + Math.ceil(height / LINE_HEIGHT) + 1)\n\n for (let i = startLine; i <= endLine; i++) {\n const line = doc.line(i)\n const y = (i - 1) * LINE_HEIGHT - offset\n if (y < -LINE_HEIGHT || y > height) continue\n\n const text = line.text\n let x = 4\n for (let j = 0; j < Math.min(text.length, 60); j++) {\n if (text[j] !== \" \" && text[j] !== \"\\t\") {\n ctx.fillRect(x, y, CHAR_WIDTH, 1.5)\n }\n x += CHAR_WIDTH\n }\n }\n\n // Viewport indicator\n const viewportTop = view.scrollDOM.scrollTop\n const viewportHeight = view.scrollDOM.clientHeight\n const docHeight = view.scrollDOM.scrollHeight || 1\n\n const vpY = (viewportTop / docHeight) * Math.min(contentHeight, height)\n const vpH = (viewportHeight / docHeight) * Math.min(contentHeight, height)\n\n ctx.fillStyle = VIEWPORT_COLOR\n ctx.fillRect(0, vpY, MINIMAP_WIDTH, vpH)\n ctx.strokeStyle = VIEWPORT_BORDER\n ctx.lineWidth = 1\n ctx.strokeRect(0.5, vpY + 0.5, MINIMAP_WIDTH - 1, vpH - 1)\n}\n\n/**\n * CodeMirror 6 minimap extension.\n * Renders a canvas-based code overview on the right side of the editor.\n *\n * @example\n * ```ts\n * import { minimapExtension } from '@pyreon/code'\n * // Add to editor extensions\n * ```\n */\nexport function minimapExtension(): Extension {\n return [\n ViewPlugin.fromClass(\n class {\n canvas: HTMLCanvasElement\n view: EditorView\n animFrame: number | null = null\n\n constructor(view: EditorView) {\n this.view = view\n this.canvas = createMinimapCanvas()\n view.dom.style.position = \"relative\"\n view.dom.appendChild(this.canvas)\n\n // Click to scroll\n this.canvas.addEventListener(\"click\", (e) => {\n const rect = this.canvas.getBoundingClientRect()\n const clickY = e.clientY - rect.top\n const fraction = clickY / rect.height\n const scrollTarget =\n fraction * (view.scrollDOM.scrollHeight - view.scrollDOM.clientHeight)\n view.scrollDOM.scrollTo({ top: scrollTarget, behavior: \"smooth\" })\n })\n\n this.render()\n }\n\n render() {\n renderMinimap(this.canvas, this.view)\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.geometryChanged) {\n if (this.animFrame) cancelAnimationFrame(this.animFrame)\n this.animFrame = requestAnimationFrame(() => this.render())\n }\n }\n\n destroy() {\n if (this.animFrame) cancelAnimationFrame(this.animFrame)\n this.canvas.remove()\n }\n },\n ),\n // Add padding on the right for the minimap\n EditorView.theme({\n \".cm-scroller\": {\n paddingRight: `${MINIMAP_WIDTH + 8}px`,\n },\n }),\n ]\n}\n","import {\n autocompletion,\n closeBrackets,\n closeBracketsKeymap,\n completionKeymap,\n} from \"@codemirror/autocomplete\"\nimport {\n redo as cmRedo,\n undo as cmUndo,\n defaultKeymap,\n history,\n historyKeymap,\n indentWithTab,\n} from \"@codemirror/commands\"\nimport {\n bracketMatching,\n defaultHighlightStyle,\n foldGutter,\n foldKeymap,\n indentOnInput,\n indentUnit,\n syntaxHighlighting,\n} from \"@codemirror/language\"\nimport { setDiagnostics as cmSetDiagnostics, lintKeymap } from \"@codemirror/lint\"\nimport { highlightSelectionMatches, searchKeymap } from \"@codemirror/search\"\nimport { Compartment, EditorState, type Extension } from \"@codemirror/state\"\nimport {\n GutterMarker as CMGutterMarker,\n crosshairCursor,\n Decoration,\n type DecorationSet,\n drawSelection,\n dropCursor,\n EditorView,\n gutter,\n highlightActiveLine,\n highlightActiveLineGutter,\n keymap,\n lineNumbers,\n placeholder as placeholderExt,\n rectangularSelection,\n ViewPlugin,\n type ViewUpdate,\n} from \"@codemirror/view\"\nimport { computed, effect, signal } from \"@pyreon/reactivity\"\nimport { loadLanguage } from \"./languages\"\nimport { minimapExtension } from \"./minimap\"\nimport { resolveTheme } from \"./themes\"\nimport type { EditorConfig, EditorInstance, EditorLanguage, EditorTheme } from \"./types\"\n\n/**\n * Create a reactive code editor instance.\n *\n * The editor state (value, language, theme, cursor, selection) is backed\n * by signals. The CodeMirror EditorView is created when mounted via\n * the `<CodeEditor>` component.\n *\n * @param config - Editor configuration\n * @returns A reactive EditorInstance\n *\n * @example\n * ```tsx\n * const editor = createEditor({\n * value: 'const x = 1',\n * language: 'typescript',\n * theme: 'dark',\n * })\n *\n * editor.value() // reactive\n * editor.value.set('new') // updates editor\n *\n * <CodeEditor instance={editor} />\n * ```\n */\nexport function createEditor(config: EditorConfig = {}): EditorInstance {\n const {\n value: initialValue = \"\",\n language: initialLanguage = \"plain\",\n theme: initialTheme = \"light\",\n lineNumbers: showLineNumbers = true,\n readOnly: initialReadOnly = false,\n foldGutter: showFoldGutter = true,\n bracketMatching: enableBracketMatching = true,\n autocomplete: enableAutocomplete = true,\n search: _enableSearch = true,\n highlightIndentGuides: enableIndentGuides = true,\n vim: enableVim = false,\n emacs: enableEmacs = false,\n tabSize: configTabSize = 2,\n lineWrapping: enableLineWrapping = false,\n placeholder: placeholderText,\n minimap: enableMinimap = false,\n extensions: userExtensions = [],\n onChange,\n } = config\n\n // ── Reactive state ───────────────────────────────────────────────────\n\n const value = signal(initialValue)\n const language = signal<EditorLanguage>(initialLanguage)\n const theme = signal<EditorTheme>(initialTheme)\n const readOnly = signal(initialReadOnly)\n const focused = signal(false)\n const view = signal<EditorView | null>(null)\n\n // Internal version tracker for cursor/selection reactivity\n const docVersion = signal(0)\n\n // ── Compartments (for dynamic reconfiguration) ─────────────────────\n\n const languageCompartment = new Compartment()\n const themeCompartment = new Compartment()\n const readOnlyCompartment = new Compartment()\n const extraKeymapCompartment = new Compartment()\n const keyModeCompartment = new Compartment()\n\n // ── Computed ─────────────────────────────────────────────────────────\n\n const cursor = computed(() => {\n docVersion() // subscribe to changes\n const v = view.peek()\n if (!v) return { line: 1, col: 1 }\n const pos = v.state.selection.main.head\n const line = v.state.doc.lineAt(pos)\n return { line: line.number, col: pos - line.from + 1 }\n })\n\n const selection = computed(() => {\n docVersion()\n const v = view.peek()\n if (!v) return { from: 0, to: 0, text: \"\" }\n const sel = v.state.selection.main\n return {\n from: sel.from,\n to: sel.to,\n text: v.state.sliceDoc(sel.from, sel.to),\n }\n })\n\n const lineCount = computed(() => {\n docVersion()\n const v = view.peek()\n return v ? v.state.doc.lines : initialValue.split(\"\\n\").length\n })\n\n // ── Line highlight support ──────────────────────────────────────────\n\n const lineHighlights = new Map<number, string>()\n\n const lineHighlightField = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet\n\n constructor(editorView: EditorView) {\n this.decorations = this.buildDecos(editorView)\n }\n\n buildDecos(editorView: EditorView): DecorationSet {\n const ranges: Array<{ from: number; deco: any }> = []\n for (const [lineNum, cls] of lineHighlights) {\n if (lineNum >= 1 && lineNum <= editorView.state.doc.lines) {\n const lineInfo = editorView.state.doc.line(lineNum)\n ranges.push({\n from: lineInfo.from,\n deco: Decoration.line({ class: cls }),\n })\n }\n }\n return Decoration.set(\n ranges.sort((a, b) => a.from - b.from).map((d) => d.deco.range(d.from)),\n )\n }\n\n update(upd: ViewUpdate) {\n if (upd.docChanged || upd.viewportChanged) {\n this.decorations = this.buildDecos(upd.view)\n }\n }\n },\n { decorations: (plugin) => plugin.decorations },\n )\n\n // ── Gutter marker support ──────────────────────────────────────────\n\n const gutterMarkers = new Map<number, { class?: string; text?: string; title?: string }>()\n\n class CustomGutterMarker extends CMGutterMarker {\n markerText: string\n markerTitle: string\n markerClass: string\n\n constructor(opts: { class?: string; text?: string; title?: string }) {\n super()\n this.markerText = opts.text ?? \"\"\n this.markerTitle = opts.title ?? \"\"\n this.markerClass = opts.class ?? \"\"\n }\n\n override toDOM() {\n const el = document.createElement(\"span\")\n el.textContent = this.markerText\n el.title = this.markerTitle\n if (this.markerClass) el.className = this.markerClass\n el.style.cssText = \"cursor: pointer; display: inline-block; width: 100%; text-align: center;\"\n return el\n }\n }\n\n const gutterMarkerExtension = gutter({\n class: \"pyreon-code-gutter-markers\",\n lineMarker: (gutterView, line) => {\n const lineNo = gutterView.state.doc.lineAt(line.from).number\n const marker = gutterMarkers.get(lineNo)\n if (!marker) return null\n return new CustomGutterMarker(marker)\n },\n initialSpacer: () => new CustomGutterMarker({ text: \" \" }),\n })\n\n // ── Build extensions ─────────────────────────────────────────────────\n\n function buildExtensions(langExt: Extension): Extension[] {\n const exts: Extension[] = [\n // Core\n history(),\n drawSelection(),\n dropCursor(),\n rectangularSelection(),\n crosshairCursor(),\n highlightActiveLine(),\n highlightActiveLineGutter(),\n highlightSelectionMatches(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n indentUnit.of(\" \".repeat(configTabSize)),\n\n // Keymaps\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...foldKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n\n // Dynamic compartments\n languageCompartment.of(langExt),\n themeCompartment.of(resolveTheme(initialTheme)),\n readOnlyCompartment.of(EditorState.readOnly.of(initialReadOnly)),\n extraKeymapCompartment.of([]),\n keyModeCompartment.of([]),\n\n // Update listener — sync CM changes to signal\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n const newValue = update.state.doc.toString()\n // Avoid infinite loop: only set if different\n if (newValue !== value.peek()) {\n value.set(newValue)\n onChange?.(newValue)\n }\n docVersion.update((v) => v + 1)\n }\n if (update.selectionSet) {\n docVersion.update((v) => v + 1)\n }\n if (update.focusChanged) {\n focused.set(update.view.hasFocus)\n }\n }),\n ]\n\n // Optional features\n if (showLineNumbers) exts.push(lineNumbers())\n if (showFoldGutter) exts.push(foldGutter())\n if (enableBracketMatching) exts.push(bracketMatching(), closeBrackets())\n if (enableAutocomplete) exts.push(autocompletion())\n if (enableLineWrapping) exts.push(EditorView.lineWrapping)\n // Indent guides via theme (CM6 doesn't have a built-in extension for this)\n if (enableIndentGuides) {\n exts.push(\n EditorView.theme({\n \".cm-line\": {\n backgroundImage: \"linear-gradient(to right, #e5e7eb 1px, transparent 1px)\",\n backgroundSize: `${configTabSize}ch 100%`,\n backgroundPosition: \"0 0\",\n },\n }),\n )\n }\n if (placeholderText) exts.push(placeholderExt(placeholderText))\n if (enableMinimap) exts.push(minimapExtension())\n\n // Line highlight decoration support\n exts.push(lineHighlightField)\n // Gutter marker support\n exts.push(gutterMarkerExtension)\n\n // User extensions\n exts.push(...userExtensions)\n\n return exts\n }\n\n // ── Mount helper — called by CodeEditor component ────────────────────\n\n let mounted = false\n\n async function mount(parent: HTMLElement): Promise<void> {\n if (mounted) return\n\n const langExt = await loadLanguage(language.peek())\n const extensions = buildExtensions(langExt)\n\n const state = EditorState.create({\n doc: value.peek(),\n extensions,\n })\n\n const editorView = new EditorView({\n state,\n parent,\n })\n\n view.set(editorView)\n mounted = true\n\n // Sync signal → editor for value changes from outside\n effect(() => {\n const val = value()\n const v = view.peek()\n if (!v) return\n const current = v.state.doc.toString()\n if (val !== current) {\n v.dispatch({\n changes: { from: 0, to: current.length, insert: val },\n })\n }\n })\n\n // Sync language changes\n effect(() => {\n const lang = language()\n const v = view.peek()\n if (!v) return\n loadLanguage(lang).then((ext) => {\n v.dispatch({ effects: languageCompartment.reconfigure(ext) })\n })\n })\n\n // Sync theme changes\n effect(() => {\n const t = theme()\n const v = view.peek()\n if (!v) return\n v.dispatch({ effects: themeCompartment.reconfigure(resolveTheme(t)) })\n })\n\n // Sync readOnly changes\n effect(() => {\n const ro = readOnly()\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(ro)),\n })\n })\n }\n\n // ── Actions ──────────────────────────────────────────────────────────\n\n function focus(): void {\n view.peek()?.focus()\n }\n\n function insert(text: string): void {\n const v = view.peek()\n if (!v) return\n const pos = v.state.selection.main.head\n v.dispatch({ changes: { from: pos, insert: text } })\n }\n\n function replaceSelection(text: string): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(v.state.replaceSelection(text))\n }\n\n function select(from: number, to: number): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({ selection: { anchor: from, head: to } })\n }\n\n function selectAll(): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({ selection: { anchor: 0, head: v.state.doc.length } })\n }\n\n function goToLine(line: number): void {\n const v = view.peek()\n if (!v) return\n const lineInfo = v.state.doc.line(Math.min(Math.max(1, line), v.state.doc.lines))\n v.dispatch({\n selection: { anchor: lineInfo.from },\n scrollIntoView: true,\n })\n v.focus()\n }\n\n function undo(): void {\n const v = view.peek()\n if (v) cmUndo(v)\n }\n\n function redo(): void {\n const v = view.peek()\n if (v) cmRedo(v)\n }\n\n function foldAll(): void {\n const v = view.peek()\n if (!v) return\n const { foldAll: foldAllCmd } = require(\"@codemirror/language\")\n foldAllCmd(v)\n }\n\n function unfoldAll(): void {\n const v = view.peek()\n if (!v) return\n const { unfoldAll: unfoldAllCmd } = require(\"@codemirror/language\")\n unfoldAllCmd(v)\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────\n\n function setDiagnostics(diagnostics: import(\"./types\").Diagnostic[]): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(\n cmSetDiagnostics(\n v.state,\n diagnostics.map((d) => ({\n from: d.from,\n to: d.to,\n severity: d.severity === \"hint\" ? \"info\" : d.severity,\n message: d.message,\n ...(d.source != null ? { source: d.source } : {}),\n })),\n ),\n )\n }\n\n function clearDiagnostics(): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(cmSetDiagnostics(v.state, []))\n }\n\n // ── Line highlights ────────────────────────────────────────────────\n\n function highlightLine(line: number, className: string): void {\n lineHighlights.set(line, className)\n // Force re-render of decorations\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n function clearLineHighlights(): void {\n lineHighlights.clear()\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n // ── Gutter markers ────────────────────────────────────────────────\n\n function setGutterMarker(line: number, marker: import(\"./types\").GutterMarker): void {\n gutterMarkers.set(line, marker)\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n function clearGutterMarkers(): void {\n gutterMarkers.clear()\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n // ── Custom keybindings ─────────────────────────────────────────────\n\n const customKeybindings: Array<{ key: string; run: () => boolean }> = []\n\n function addKeybinding(key: string, handler: () => boolean | undefined): void {\n customKeybindings.push({\n key,\n run: () => {\n handler()\n return true\n },\n })\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: extraKeymapCompartment.reconfigure(keymap.of(customKeybindings)),\n })\n }\n\n // ── Text queries ───────────────────────────────────────────────────\n\n function getLine(line: number): string {\n const v = view.peek()\n if (!v) return \"\"\n const clamped = Math.min(Math.max(1, line), v.state.doc.lines)\n return v.state.doc.line(clamped).text\n }\n\n function getWordAtCursor(): string {\n const v = view.peek()\n if (!v) return \"\"\n const pos = v.state.selection.main.head\n const line = v.state.doc.lineAt(pos)\n const col = pos - line.from\n const text = line.text\n\n // Find word boundaries\n let start = col\n let end = col\n while (start > 0 && /\\w/.test(text.charAt(start - 1))) start--\n while (end < text.length && /\\w/.test(text.charAt(end))) end++\n\n return text.slice(start, end)\n }\n\n function scrollTo(pos: number): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: \"center\" }),\n })\n }\n\n // ── Vim / Emacs mode loading ───────────────────────────────────────\n\n async function loadKeyMode(): Promise<void> {\n const v = view.peek()\n if (!v) return\n\n // Use string concat to prevent Vite from statically analyzing these optional imports\n const vimPkg = \"@replit/codemirror-\" + \"vim\"\n const emacsPkg = \"@replit/codemirror-\" + \"emacs\"\n\n if (enableVim) {\n try {\n const mod = await import(/* @vite-ignore */ vimPkg)\n v.dispatch({\n effects: keyModeCompartment.reconfigure(mod.vim()),\n })\n } catch {\n /* @replit/codemirror-vim not installed */\n }\n }\n\n if (enableEmacs) {\n try {\n const mod = await import(/* @vite-ignore */ emacsPkg)\n v.dispatch({\n effects: keyModeCompartment.reconfigure(mod.emacs()),\n })\n } catch {\n /* @replit/codemirror-emacs not installed */\n }\n }\n }\n\n function dispose(): void {\n const v = view.peek()\n if (v) {\n v.destroy()\n view.set(null)\n mounted = false\n }\n }\n\n // ── Expose mount for component ─────────────────────────────────────\n\n const instance: EditorInstance & { _mount: typeof mount } = {\n value,\n language,\n theme,\n readOnly,\n cursor,\n selection,\n lineCount,\n focused,\n view,\n focus,\n insert,\n replaceSelection,\n select,\n selectAll,\n goToLine,\n undo,\n redo,\n foldAll,\n unfoldAll,\n setDiagnostics,\n clearDiagnostics,\n highlightLine,\n clearLineHighlights,\n setGutterMarker,\n clearGutterMarkers,\n addKeybinding,\n getLine,\n getWordAtCursor,\n scrollTo,\n config,\n dispose,\n _mount: async (parent: HTMLElement) => {\n await mount(parent)\n await loadKeyMode()\n },\n }\n\n return instance\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["CMGutterMarker","placeholderExt","undo","redo","setDiagnostics","cmSetDiagnostics"],"sources":["../../../core/core/lib/jsx-runtime.js","../src/components/code-editor.tsx","../src/languages.ts","../src/themes.ts","../src/components/diff-editor.tsx","../src/components/tabbed-editor.tsx","../src/minimap.ts","../src/editor.ts"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport type { CodeEditorProps, EditorInstance } from '../types'\n\n/**\n * Code editor component — mounts a CodeMirror 6 instance.\n *\n * @example\n * ```tsx\n * const editor = createEditor({\n * value: 'const x = 1',\n * language: 'typescript',\n * theme: 'dark',\n * })\n *\n * <CodeEditor instance={editor} style=\"height: 400px\" />\n * ```\n */\nexport function CodeEditor(props: CodeEditorProps): VNodeChild {\n const { instance } = props\n\n const containerRef = (el: Element | null) => {\n if (!el) return\n\n // Mount the editor into the container\n const mountable = instance as EditorInstance & {\n _mount?: (parent: HTMLElement) => Promise<void>\n }\n if (mountable._mount) {\n mountable._mount(el as HTMLElement)\n }\n }\n\n const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ''}`\n\n return (\n <div ref={containerRef} class={`pyreon-code-editor ${props.class ?? ''}`} style={baseStyle} />\n )\n}\n","import type { Extension } from '@codemirror/state'\nimport type { EditorLanguage } from './types'\n\n/**\n * Language extension loaders — lazy-loaded on demand.\n * Only the requested language is imported, keeping the initial bundle small.\n */\nconst languageLoaders: Record<EditorLanguage, () => Promise<Extension>> = {\n javascript: () => import('@codemirror/lang-javascript').then((m) => m.javascript()),\n typescript: () =>\n import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n jsx: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ jsx: true })),\n tsx: () =>\n import('@codemirror/lang-javascript').then((m) =>\n m.javascript({ typescript: true, jsx: true }),\n ),\n html: () => import('@codemirror/lang-html').then((m) => m.html()),\n css: () => import('@codemirror/lang-css').then((m) => m.css()),\n json: () => import('@codemirror/lang-json').then((m) => m.json()),\n markdown: () => import('@codemirror/lang-markdown').then((m) => m.markdown()),\n python: () => import('@codemirror/lang-python').then((m) => m.python()),\n rust: () => import('@codemirror/lang-rust').then((m) => m.rust()),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n xml: () => import('@codemirror/lang-xml').then((m) => m.xml()),\n yaml: () => import('@codemirror/lang-yaml').then((m) => m.yaml()),\n cpp: () => import('@codemirror/lang-cpp').then((m) => m.cpp()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n go: () => import('@codemirror/lang-go').then((m) => m.go()),\n php: () => import('@codemirror/lang-php').then((m) => m.php()),\n ruby: () => Promise.resolve([]),\n shell: () => Promise.resolve([]),\n plain: () => Promise.resolve([]),\n}\n\n// Cache loaded language extensions\nconst loaded = new Map<EditorLanguage, Extension>()\n\n/**\n * Load a language extension. Returns cached if already loaded.\n * Language grammars are lazy-imported — zero cost until used.\n *\n * @example\n * ```ts\n * const ext = await loadLanguage('typescript')\n * ```\n */\nexport async function loadLanguage(language: EditorLanguage): Promise<Extension> {\n const cached = loaded.get(language)\n if (cached) return cached\n\n const loader = languageLoaders[language]\n if (!loader) return []\n\n try {\n const ext = await loader()\n loaded.set(language, ext)\n return ext\n } catch {\n // Language package not installed — return empty extension\n return []\n }\n}\n\n/**\n * Get available languages.\n */\nexport function getAvailableLanguages(): EditorLanguage[] {\n return Object.keys(languageLoaders) as EditorLanguage[]\n}\n","import type { Extension } from '@codemirror/state'\nimport { EditorView } from '@codemirror/view'\nimport type { EditorTheme } from './types'\n\n/**\n * Light theme — clean, minimal.\n */\nexport const lightTheme: Extension = EditorView.theme({\n '&': {\n backgroundColor: '#ffffff',\n color: '#1e293b',\n },\n '.cm-content': {\n caretColor: '#1e293b',\n },\n '.cm-cursor': {\n borderLeftColor: '#1e293b',\n },\n '&.cm-focused .cm-selectionBackground, .cm-selectionBackground': {\n backgroundColor: '#dbeafe',\n },\n '.cm-gutters': {\n backgroundColor: '#f8fafc',\n color: '#94a3b8',\n borderRight: '1px solid #e2e8f0',\n },\n '.cm-activeLineGutter': {\n backgroundColor: '#f1f5f9',\n color: '#475569',\n },\n '.cm-activeLine': {\n backgroundColor: '#f8fafc',\n },\n '.cm-foldGutter': {\n color: '#94a3b8',\n },\n})\n\n/**\n * Dark theme — VS Code inspired.\n */\nexport const darkTheme: Extension = EditorView.theme(\n {\n '&': {\n backgroundColor: '#1e1e2e',\n color: '#cdd6f4',\n },\n '.cm-content': {\n caretColor: '#f5e0dc',\n },\n '.cm-cursor': {\n borderLeftColor: '#f5e0dc',\n },\n '&.cm-focused .cm-selectionBackground, .cm-selectionBackground': {\n backgroundColor: '#45475a',\n },\n '.cm-gutters': {\n backgroundColor: '#181825',\n color: '#585b70',\n borderRight: '1px solid #313244',\n },\n '.cm-activeLineGutter': {\n backgroundColor: '#1e1e2e',\n color: '#a6adc8',\n },\n '.cm-activeLine': {\n backgroundColor: '#1e1e2e80',\n },\n '.cm-foldGutter': {\n color: '#585b70',\n },\n '.cm-matchingBracket': {\n backgroundColor: '#45475a',\n color: '#f5e0dc',\n },\n },\n { dark: true },\n)\n\n/**\n * Resolve a theme value to a CodeMirror extension.\n */\nexport function resolveTheme(theme: EditorTheme): Extension {\n if (theme === 'light') return lightTheme\n if (theme === 'dark') return darkTheme\n return theme // custom Extension\n}\n","import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'\nimport { MergeView } from '@codemirror/merge'\nimport { EditorState, type Extension } from '@codemirror/state'\nimport { EditorView } from '@codemirror/view'\nimport type { VNodeChild } from '@pyreon/core'\nimport { onUnmount } from '@pyreon/core'\nimport type { Signal } from '@pyreon/reactivity'\nimport { watch } from '@pyreon/reactivity'\nimport { loadLanguage } from '../languages'\nimport { resolveTheme } from '../themes'\nimport type { DiffEditorProps } from '../types'\n\nconst readText = (value: string | Signal<string>): string =>\n typeof value === 'string' ? value : value()\n\nconst isSignal = (value: string | Signal<string>): value is Signal<string> =>\n typeof value === 'function'\n\n/**\n * Side-by-side or inline diff editor using @codemirror/merge.\n *\n * Supports reactive `original` and `modified` props — pass a Signal<string>\n * and the diff view updates automatically when the signal changes.\n *\n * @example\n * ```tsx\n * <DiffEditor\n * original=\"const x = 1\"\n * modified=\"const x = 2\"\n * language=\"typescript\"\n * theme=\"dark\"\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function DiffEditor(props: DiffEditorProps): VNodeChild {\n const { original, modified, language = 'plain', theme = 'light', readOnly = true } = props\n\n let mergeView: MergeView | null = null\n const cleanups: (() => void)[] = []\n\n const containerRef = async (el: Element | null) => {\n if (!el) return\n\n const langExt = await loadLanguage(language)\n const themeExt = resolveTheme(theme)\n\n const extensions: Extension[] = [\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n langExt,\n themeExt,\n EditorView.editable.of(!readOnly),\n EditorState.readOnly.of(readOnly),\n ]\n\n const originalText = readText(original)\n const modifiedText = readText(modified)\n\n // Clear previous content\n ;(el as HTMLElement).innerHTML = ''\n\n mergeView = new MergeView({\n a: { doc: originalText, extensions },\n b: { doc: modifiedText, extensions },\n parent: el as HTMLElement,\n collapseUnchanged: { margin: 3, minSize: 4 },\n })\n\n // Track signal changes and update MergeView editors reactively\n if (isSignal(original)) {\n const stop = watch(original, (text) => {\n if (!mergeView) return\n const editor = mergeView.a\n editor.dispatch({\n changes: { from: 0, to: editor.state.doc.length, insert: text },\n })\n })\n cleanups.push(stop)\n }\n\n if (isSignal(modified)) {\n const stop = watch(modified, (text) => {\n if (!mergeView) return\n const editor = mergeView.b\n editor.dispatch({\n changes: { from: 0, to: editor.state.doc.length, insert: text },\n })\n })\n cleanups.push(stop)\n }\n }\n\n onUnmount(() => {\n for (const cleanup of cleanups) cleanup()\n mergeView?.destroy()\n mergeView = null\n })\n\n const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ''}`\n\n return (\n <div ref={containerRef} class={`pyreon-diff-editor ${props.class ?? ''}`} style={baseStyle} />\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { TabbedEditorProps } from '../types'\nimport { CodeEditor } from './code-editor'\n\n/**\n * Tabbed code editor component — renders tab bar + editor.\n * Headless styling — the tab bar is a plain div with button tabs.\n * Consumers can style via CSS classes.\n *\n * @example\n * ```tsx\n * const editor = createTabbedEditor({\n * tabs: [\n * { name: 'index.ts', language: 'typescript', value: 'const x = 1' },\n * { name: 'style.css', language: 'css', value: '.app { }' },\n * ],\n * theme: 'dark',\n * })\n *\n * <TabbedEditor instance={editor} style=\"height: 500px\" />\n * ```\n */\nexport function TabbedEditor(props: TabbedEditorProps): VNodeChild {\n const { instance } = props\n\n const containerStyle = `display: flex; flex-direction: column; width: 100%; height: 100%; ${props.style ?? ''}`\n\n const tabBarStyle =\n 'display: flex; overflow-x: auto; background: #f1f5f9; border-bottom: 1px solid #e2e8f0; min-height: 34px; flex-shrink: 0;'\n\n return (\n <div class={`pyreon-tabbed-editor ${props.class ?? ''}`} style={containerStyle}>\n {() => {\n const tabs = instance.tabs()\n const activeId = instance.activeTabId()\n\n return (\n <div class=\"pyreon-tabbed-editor-tabs\" style={tabBarStyle}>\n {tabs.map((tab) => {\n const id = tab.id ?? tab.name\n const isActive = id === activeId\n\n const tabStyle = `display: flex; align-items: center; gap: 6px; padding: 6px 12px; border: none; background: ${isActive ? 'white' : 'transparent'}; border-bottom: ${isActive ? '2px solid #3b82f6' : '2px solid transparent'}; cursor: pointer; font-size: 13px; color: ${isActive ? '#1e293b' : '#64748b'}; white-space: nowrap; position: relative; font-family: inherit;`\n\n return (\n <button\n type=\"button\"\n key={id}\n class={`pyreon-tab ${isActive ? 'active' : ''} ${tab.modified ? 'modified' : ''}`}\n style={tabStyle}\n onClick={() => instance.switchTab(id)}\n >\n <span>{tab.name}</span>\n {tab.modified && (\n <span\n style=\"width: 6px; height: 6px; border-radius: 50%; background: #f59e0b; flex-shrink: 0;\"\n title=\"Modified\"\n />\n )}\n {tab.closable !== false && (\n <span\n style=\"font-size: 14px; line-height: 1; opacity: 0.5; cursor: pointer; padding: 0 2px; margin-left: 2px;\"\n title=\"Close\"\n onClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance.closeTab(id)\n }}\n >\n ×\n </span>\n )}\n </button>\n )\n })}\n </div>\n )\n }}\n <div style=\"flex: 1; min-height: 0;\">\n <CodeEditor instance={instance.editor} />\n </div>\n </div>\n )\n}\n","import type { Extension } from '@codemirror/state'\nimport { EditorView, ViewPlugin, type ViewUpdate } from '@codemirror/view'\n\n/**\n * Canvas-based minimap extension for CodeMirror 6.\n * Renders a scaled-down overview of the document on the right side.\n */\n\nconst MINIMAP_WIDTH = 80\nconst CHAR_WIDTH = 1.2\nconst LINE_HEIGHT = 2.5\nconst MINIMAP_BG = '#1e1e2e'\nconst MINIMAP_BG_LIGHT = '#f8fafc'\nconst TEXT_COLOR = '#585b70'\nconst TEXT_COLOR_LIGHT = '#94a3b8'\nconst VIEWPORT_COLOR = 'rgba(59, 130, 246, 0.15)'\nconst VIEWPORT_BORDER = 'rgba(59, 130, 246, 0.4)'\n\nfunction createMinimapCanvas(): HTMLCanvasElement {\n const canvas = document.createElement('canvas')\n canvas.style.cssText = `position: absolute; right: 0; top: 0; width: ${MINIMAP_WIDTH}px; height: 100%; cursor: pointer; z-index: 5;`\n canvas.width = MINIMAP_WIDTH * 2 // retina\n return canvas\n}\n\nfunction renderMinimap(canvas: HTMLCanvasElement, view: EditorView): void {\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n\n const doc = view.state.doc\n const totalLines = doc.lines\n const height = canvas.clientHeight\n canvas.height = height * 2 // retina\n\n const isDark = view.dom.classList.contains('cm-dark')\n const bg = isDark ? MINIMAP_BG : MINIMAP_BG_LIGHT\n const textColor = isDark ? TEXT_COLOR : TEXT_COLOR_LIGHT\n\n const scale = 2 // retina\n ctx.setTransform(scale, 0, 0, scale, 0, 0)\n\n // Background\n ctx.fillStyle = bg\n ctx.fillRect(0, 0, MINIMAP_WIDTH, height)\n\n // Calculate visible range in minimap\n const contentHeight = totalLines * LINE_HEIGHT\n const scrollFraction =\n contentHeight > height\n ? view.scrollDOM.scrollTop / (view.scrollDOM.scrollHeight - view.scrollDOM.clientHeight || 1)\n : 0\n const offset = contentHeight > height ? scrollFraction * (contentHeight - height) : 0\n\n // Render text lines\n ctx.fillStyle = textColor\n const startLine = Math.max(1, Math.floor(offset / LINE_HEIGHT))\n const endLine = Math.min(totalLines, startLine + Math.ceil(height / LINE_HEIGHT) + 1)\n\n for (let i = startLine; i <= endLine; i++) {\n const line = doc.line(i)\n const y = (i - 1) * LINE_HEIGHT - offset\n if (y < -LINE_HEIGHT || y > height) continue\n\n const text = line.text\n let x = 4\n for (let j = 0; j < Math.min(text.length, 60); j++) {\n if (text[j] !== ' ' && text[j] !== '\\t') {\n ctx.fillRect(x, y, CHAR_WIDTH, 1.5)\n }\n x += CHAR_WIDTH\n }\n }\n\n // Viewport indicator\n const viewportTop = view.scrollDOM.scrollTop\n const viewportHeight = view.scrollDOM.clientHeight\n const docHeight = view.scrollDOM.scrollHeight || 1\n\n const vpY = (viewportTop / docHeight) * Math.min(contentHeight, height)\n const vpH = (viewportHeight / docHeight) * Math.min(contentHeight, height)\n\n ctx.fillStyle = VIEWPORT_COLOR\n ctx.fillRect(0, vpY, MINIMAP_WIDTH, vpH)\n ctx.strokeStyle = VIEWPORT_BORDER\n ctx.lineWidth = 1\n ctx.strokeRect(0.5, vpY + 0.5, MINIMAP_WIDTH - 1, vpH - 1)\n}\n\n/**\n * CodeMirror 6 minimap extension.\n * Renders a canvas-based code overview on the right side of the editor.\n *\n * @example\n * ```ts\n * import { minimapExtension } from '@pyreon/code'\n * // Add to editor extensions\n * ```\n */\nexport function minimapExtension(): Extension {\n return [\n ViewPlugin.fromClass(\n class {\n canvas: HTMLCanvasElement\n view: EditorView\n animFrame: number | null = null\n\n constructor(view: EditorView) {\n this.view = view\n this.canvas = createMinimapCanvas()\n view.dom.style.position = 'relative'\n view.dom.appendChild(this.canvas)\n\n // Click to scroll\n this.canvas.addEventListener('click', (e) => {\n const rect = this.canvas.getBoundingClientRect()\n const clickY = e.clientY - rect.top\n const fraction = clickY / rect.height\n const scrollTarget =\n fraction * (view.scrollDOM.scrollHeight - view.scrollDOM.clientHeight)\n view.scrollDOM.scrollTo({ top: scrollTarget, behavior: 'smooth' })\n })\n\n this.render()\n }\n\n render() {\n renderMinimap(this.canvas, this.view)\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.geometryChanged) {\n if (this.animFrame) cancelAnimationFrame(this.animFrame)\n this.animFrame = requestAnimationFrame(() => this.render())\n }\n }\n\n destroy() {\n if (this.animFrame) cancelAnimationFrame(this.animFrame)\n this.canvas.remove()\n }\n },\n ),\n // Add padding on the right for the minimap\n EditorView.theme({\n '.cm-scroller': {\n paddingRight: `${MINIMAP_WIDTH + 8}px`,\n },\n }),\n ]\n}\n","import {\n autocompletion,\n closeBrackets,\n closeBracketsKeymap,\n completionKeymap,\n} from '@codemirror/autocomplete'\nimport {\n redo as cmRedo,\n undo as cmUndo,\n defaultKeymap,\n history,\n historyKeymap,\n indentWithTab,\n} from '@codemirror/commands'\nimport {\n bracketMatching,\n defaultHighlightStyle,\n foldGutter,\n foldKeymap,\n indentOnInput,\n indentUnit,\n syntaxHighlighting,\n} from '@codemirror/language'\nimport { setDiagnostics as cmSetDiagnostics, lintKeymap } from '@codemirror/lint'\nimport { highlightSelectionMatches, searchKeymap } from '@codemirror/search'\nimport { Compartment, EditorState, type Extension } from '@codemirror/state'\nimport {\n GutterMarker as CMGutterMarker,\n crosshairCursor,\n Decoration,\n type DecorationSet,\n drawSelection,\n dropCursor,\n EditorView,\n gutter,\n highlightActiveLine,\n highlightActiveLineGutter,\n keymap,\n lineNumbers,\n placeholder as placeholderExt,\n rectangularSelection,\n ViewPlugin,\n type ViewUpdate,\n} from '@codemirror/view'\nimport { computed, effect, signal } from '@pyreon/reactivity'\nimport { loadLanguage } from './languages'\nimport { minimapExtension } from './minimap'\nimport { resolveTheme } from './themes'\nimport type { EditorConfig, EditorInstance, EditorLanguage, EditorTheme } from './types'\n\n/**\n * Create a reactive code editor instance.\n *\n * The editor state (value, language, theme, cursor, selection) is backed\n * by signals. The CodeMirror EditorView is created when mounted via\n * the `<CodeEditor>` component.\n *\n * @param config - Editor configuration\n * @returns A reactive EditorInstance\n *\n * @example\n * ```tsx\n * const editor = createEditor({\n * value: 'const x = 1',\n * language: 'typescript',\n * theme: 'dark',\n * })\n *\n * editor.value() // reactive\n * editor.value.set('new') // updates editor\n *\n * <CodeEditor instance={editor} />\n * ```\n */\nexport function createEditor(config: EditorConfig = {}): EditorInstance {\n const {\n value: initialValue = '',\n language: initialLanguage = 'plain',\n theme: initialTheme = 'light',\n lineNumbers: showLineNumbers = true,\n readOnly: initialReadOnly = false,\n foldGutter: showFoldGutter = true,\n bracketMatching: enableBracketMatching = true,\n autocomplete: enableAutocomplete = true,\n search: _enableSearch = true,\n highlightIndentGuides: enableIndentGuides = true,\n vim: enableVim = false,\n emacs: enableEmacs = false,\n tabSize: configTabSize = 2,\n lineWrapping: enableLineWrapping = false,\n placeholder: placeholderText,\n minimap: enableMinimap = false,\n extensions: userExtensions = [],\n onChange,\n } = config\n\n // ── Reactive state ───────────────────────────────────────────────────\n\n const value = signal(initialValue)\n const language = signal<EditorLanguage>(initialLanguage)\n const theme = signal<EditorTheme>(initialTheme)\n const readOnly = signal(initialReadOnly)\n const focused = signal(false)\n const view = signal<EditorView | null>(null)\n\n // Internal version tracker for cursor/selection reactivity\n const docVersion = signal(0)\n\n // ── Compartments (for dynamic reconfiguration) ─────────────────────\n\n const languageCompartment = new Compartment()\n const themeCompartment = new Compartment()\n const readOnlyCompartment = new Compartment()\n const extraKeymapCompartment = new Compartment()\n const keyModeCompartment = new Compartment()\n\n // ── Computed ─────────────────────────────────────────────────────────\n\n const cursor = computed(() => {\n docVersion() // subscribe to changes\n const v = view.peek()\n if (!v) return { line: 1, col: 1 }\n const pos = v.state.selection.main.head\n const line = v.state.doc.lineAt(pos)\n return { line: line.number, col: pos - line.from + 1 }\n })\n\n const selection = computed(() => {\n docVersion()\n const v = view.peek()\n if (!v) return { from: 0, to: 0, text: '' }\n const sel = v.state.selection.main\n return {\n from: sel.from,\n to: sel.to,\n text: v.state.sliceDoc(sel.from, sel.to),\n }\n })\n\n const lineCount = computed(() => {\n docVersion()\n const v = view.peek()\n return v ? v.state.doc.lines : initialValue.split('\\n').length\n })\n\n // ── Line highlight support ──────────────────────────────────────────\n\n const lineHighlights = new Map<number, string>()\n\n const lineHighlightField = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet\n\n constructor(editorView: EditorView) {\n this.decorations = this.buildDecos(editorView)\n }\n\n buildDecos(editorView: EditorView): DecorationSet {\n const ranges: Array<{ from: number; deco: any }> = []\n for (const [lineNum, cls] of lineHighlights) {\n if (lineNum >= 1 && lineNum <= editorView.state.doc.lines) {\n const lineInfo = editorView.state.doc.line(lineNum)\n ranges.push({\n from: lineInfo.from,\n deco: Decoration.line({ class: cls }),\n })\n }\n }\n return Decoration.set(\n ranges.sort((a, b) => a.from - b.from).map((d) => d.deco.range(d.from)),\n )\n }\n\n update(upd: ViewUpdate) {\n if (upd.docChanged || upd.viewportChanged) {\n this.decorations = this.buildDecos(upd.view)\n }\n }\n },\n { decorations: (plugin) => plugin.decorations },\n )\n\n // ── Gutter marker support ──────────────────────────────────────────\n\n const gutterMarkers = new Map<number, { class?: string; text?: string; title?: string }>()\n\n class CustomGutterMarker extends CMGutterMarker {\n markerText: string\n markerTitle: string\n markerClass: string\n\n constructor(opts: { class?: string; text?: string; title?: string }) {\n super()\n this.markerText = opts.text ?? ''\n this.markerTitle = opts.title ?? ''\n this.markerClass = opts.class ?? ''\n }\n\n override toDOM() {\n const el = document.createElement('span')\n el.textContent = this.markerText\n el.title = this.markerTitle\n if (this.markerClass) el.className = this.markerClass\n el.style.cssText = 'cursor: pointer; display: inline-block; width: 100%; text-align: center;'\n return el\n }\n }\n\n const gutterMarkerExtension = gutter({\n class: 'pyreon-code-gutter-markers',\n lineMarker: (gutterView, line) => {\n const lineNo = gutterView.state.doc.lineAt(line.from).number\n const marker = gutterMarkers.get(lineNo)\n if (!marker) return null\n return new CustomGutterMarker(marker)\n },\n initialSpacer: () => new CustomGutterMarker({ text: ' ' }),\n })\n\n // ── Build extensions ─────────────────────────────────────────────────\n\n function buildExtensions(langExt: Extension): Extension[] {\n const exts: Extension[] = [\n // Core\n history(),\n drawSelection(),\n dropCursor(),\n rectangularSelection(),\n crosshairCursor(),\n highlightActiveLine(),\n highlightActiveLineGutter(),\n highlightSelectionMatches(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n indentUnit.of(' '.repeat(configTabSize)),\n\n // Keymaps\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...foldKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n\n // Dynamic compartments\n languageCompartment.of(langExt),\n themeCompartment.of(resolveTheme(initialTheme)),\n readOnlyCompartment.of(EditorState.readOnly.of(initialReadOnly)),\n extraKeymapCompartment.of([]),\n keyModeCompartment.of([]),\n\n // Update listener — sync CM changes to signal\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n const newValue = update.state.doc.toString()\n // Avoid infinite loop: only set if different\n if (newValue !== value.peek()) {\n value.set(newValue)\n onChange?.(newValue)\n }\n docVersion.update((v) => v + 1)\n }\n if (update.selectionSet) {\n docVersion.update((v) => v + 1)\n }\n if (update.focusChanged) {\n focused.set(update.view.hasFocus)\n }\n }),\n ]\n\n // Optional features\n if (showLineNumbers) exts.push(lineNumbers())\n if (showFoldGutter) exts.push(foldGutter())\n if (enableBracketMatching) exts.push(bracketMatching(), closeBrackets())\n if (enableAutocomplete) exts.push(autocompletion())\n if (enableLineWrapping) exts.push(EditorView.lineWrapping)\n // Indent guides via theme (CM6 doesn't have a built-in extension for this)\n if (enableIndentGuides) {\n exts.push(\n EditorView.theme({\n '.cm-line': {\n backgroundImage: 'linear-gradient(to right, #e5e7eb 1px, transparent 1px)',\n backgroundSize: `${configTabSize}ch 100%`,\n backgroundPosition: '0 0',\n },\n }),\n )\n }\n if (placeholderText) exts.push(placeholderExt(placeholderText))\n if (enableMinimap) exts.push(minimapExtension())\n\n // Line highlight decoration support\n exts.push(lineHighlightField)\n // Gutter marker support\n exts.push(gutterMarkerExtension)\n\n // User extensions\n exts.push(...userExtensions)\n\n return exts\n }\n\n // ── Mount helper — called by CodeEditor component ────────────────────\n\n let mounted = false\n\n async function mount(parent: HTMLElement): Promise<void> {\n if (mounted) return\n\n const langExt = await loadLanguage(language.peek())\n const extensions = buildExtensions(langExt)\n\n const state = EditorState.create({\n doc: value.peek(),\n extensions,\n })\n\n const editorView = new EditorView({\n state,\n parent,\n })\n\n view.set(editorView)\n mounted = true\n\n // Sync signal → editor for value changes from outside\n effect(() => {\n const val = value()\n const v = view.peek()\n if (!v) return\n const current = v.state.doc.toString()\n if (val !== current) {\n v.dispatch({\n changes: { from: 0, to: current.length, insert: val },\n })\n }\n })\n\n // Sync language changes\n effect(() => {\n const lang = language()\n const v = view.peek()\n if (!v) return\n loadLanguage(lang).then((ext) => {\n v.dispatch({ effects: languageCompartment.reconfigure(ext) })\n })\n })\n\n // Sync theme changes\n effect(() => {\n const t = theme()\n const v = view.peek()\n if (!v) return\n v.dispatch({ effects: themeCompartment.reconfigure(resolveTheme(t)) })\n })\n\n // Sync readOnly changes\n effect(() => {\n const ro = readOnly()\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: readOnlyCompartment.reconfigure(EditorState.readOnly.of(ro)),\n })\n })\n }\n\n // ── Actions ──────────────────────────────────────────────────────────\n\n function focus(): void {\n view.peek()?.focus()\n }\n\n function insert(text: string): void {\n const v = view.peek()\n if (!v) return\n const pos = v.state.selection.main.head\n v.dispatch({ changes: { from: pos, insert: text } })\n }\n\n function replaceSelection(text: string): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(v.state.replaceSelection(text))\n }\n\n function select(from: number, to: number): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({ selection: { anchor: from, head: to } })\n }\n\n function selectAll(): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({ selection: { anchor: 0, head: v.state.doc.length } })\n }\n\n function goToLine(line: number): void {\n const v = view.peek()\n if (!v) return\n const lineInfo = v.state.doc.line(Math.min(Math.max(1, line), v.state.doc.lines))\n v.dispatch({\n selection: { anchor: lineInfo.from },\n scrollIntoView: true,\n })\n v.focus()\n }\n\n function undo(): void {\n const v = view.peek()\n if (v) cmUndo(v)\n }\n\n function redo(): void {\n const v = view.peek()\n if (v) cmRedo(v)\n }\n\n function foldAll(): void {\n const v = view.peek()\n if (!v) return\n const { foldAll: foldAllCmd } = require('@codemirror/language')\n foldAllCmd(v)\n }\n\n function unfoldAll(): void {\n const v = view.peek()\n if (!v) return\n const { unfoldAll: unfoldAllCmd } = require('@codemirror/language')\n unfoldAllCmd(v)\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────\n\n function setDiagnostics(diagnostics: import('./types').Diagnostic[]): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(\n cmSetDiagnostics(\n v.state,\n diagnostics.map((d) => ({\n from: d.from,\n to: d.to,\n severity: d.severity === 'hint' ? 'info' : d.severity,\n message: d.message,\n ...(d.source != null ? { source: d.source } : {}),\n })),\n ),\n )\n }\n\n function clearDiagnostics(): void {\n const v = view.peek()\n if (!v) return\n v.dispatch(cmSetDiagnostics(v.state, []))\n }\n\n // ── Line highlights ────────────────────────────────────────────────\n\n function highlightLine(line: number, className: string): void {\n lineHighlights.set(line, className)\n // Force re-render of decorations\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n function clearLineHighlights(): void {\n lineHighlights.clear()\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n // ── Gutter markers ────────────────────────────────────────────────\n\n function setGutterMarker(line: number, marker: import('./types').GutterMarker): void {\n gutterMarkers.set(line, marker)\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n function clearGutterMarkers(): void {\n gutterMarkers.clear()\n const v = view.peek()\n if (v) v.dispatch({ effects: [] })\n }\n\n // ── Custom keybindings ─────────────────────────────────────────────\n\n const customKeybindings: Array<{ key: string; run: () => boolean }> = []\n\n function addKeybinding(key: string, handler: () => boolean | undefined): void {\n customKeybindings.push({\n key,\n run: () => {\n handler()\n return true\n },\n })\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: extraKeymapCompartment.reconfigure(keymap.of(customKeybindings)),\n })\n }\n\n // ── Text queries ───────────────────────────────────────────────────\n\n function getLine(line: number): string {\n const v = view.peek()\n if (!v) return ''\n const clamped = Math.min(Math.max(1, line), v.state.doc.lines)\n return v.state.doc.line(clamped).text\n }\n\n function getWordAtCursor(): string {\n const v = view.peek()\n if (!v) return ''\n const pos = v.state.selection.main.head\n const line = v.state.doc.lineAt(pos)\n const col = pos - line.from\n const text = line.text\n\n // Find word boundaries\n let start = col\n let end = col\n while (start > 0 && /\\w/.test(text.charAt(start - 1))) start--\n while (end < text.length && /\\w/.test(text.charAt(end))) end++\n\n return text.slice(start, end)\n }\n\n function scrollTo(pos: number): void {\n const v = view.peek()\n if (!v) return\n v.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: 'center' }),\n })\n }\n\n // ── Vim / Emacs mode loading ───────────────────────────────────────\n\n async function loadKeyMode(): Promise<void> {\n const v = view.peek()\n if (!v) return\n\n // Use string concat to prevent Vite from statically analyzing these optional imports\n const vimPkg = '@replit/codemirror-' + 'vim'\n const emacsPkg = '@replit/codemirror-' + 'emacs'\n\n if (enableVim) {\n try {\n const mod = await import(/* @vite-ignore */ vimPkg)\n v.dispatch({\n effects: keyModeCompartment.reconfigure(mod.vim()),\n })\n } catch {\n /* @replit/codemirror-vim not installed */\n }\n }\n\n if (enableEmacs) {\n try {\n const mod = await import(/* @vite-ignore */ emacsPkg)\n v.dispatch({\n effects: keyModeCompartment.reconfigure(mod.emacs()),\n })\n } catch {\n /* @replit/codemirror-emacs not installed */\n }\n }\n }\n\n function dispose(): void {\n const v = view.peek()\n if (v) {\n v.destroy()\n view.set(null)\n mounted = false\n }\n }\n\n // ── Expose mount for component ─────────────────────────────────────\n\n const instance: EditorInstance & { _mount: typeof mount } = {\n value,\n language,\n theme,\n readOnly,\n cursor,\n selection,\n lineCount,\n focused,\n view,\n focus,\n insert,\n replaceSelection,\n select,\n selectAll,\n goToLine,\n undo,\n redo,\n foldAll,\n unfoldAll,\n setDiagnostics,\n clearDiagnostics,\n highlightLine,\n clearLineHighlights,\n setGutterMarker,\n clearGutterMarkers,\n addKeybinding,\n getLine,\n getWordAtCursor,\n scrollTo,\n config,\n dispose,\n _mount: async (parent: HTMLElement) => {\n await mount(parent)\n await loadKeyMode()\n },\n }\n\n return instance\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,MAAM,cAAc,EAAE;AACtB,SAAS,EAAE,MAAM,OAAO,GAAG,UAAU;AACpC,QAAO;EACN;EACA,OAAO,SAAS;EAChB,UAAU,kBAAkB,SAAS;EACrC,KAAK,OAAO,OAAO;EACnB;;AAEF,SAAS,kBAAkB,UAAU;AACpC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAK,KAAI,MAAM,QAAQ,SAAS,GAAG,CAAE,QAAO,gBAAgB,SAAS;AAC1G,QAAO;;AAER,SAAS,gBAAgB,UAAU;CAClC,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,SAAS,SAAU,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,GAAG,gBAAgB,MAAM,CAAC;KACzF,QAAO,KAAK,MAAM;AACvB,QAAO;;;;;;;;;AAYR,SAAS,IAAI,MAAM,OAAO,KAAK;CAC9B,MAAM,EAAE,UAAU,GAAG,SAAS;CAC9B,MAAM,eAAe,OAAO,OAAO;EAClC,GAAG;EACH;EACA,GAAG;AACJ,KAAI,OAAO,SAAS,WAAY,QAAO,EAAE,MAAM,aAAa,KAAK,IAAI;EACpE,GAAG;EACH;EACA,GAAG,aAAa;AACjB,QAAO,EAAE,MAAM,cAAc,GAAG,aAAa,KAAK,IAAI,EAAE,GAAG,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;;AAE5G,MAAM,OAAO;;;;;;;;;;;;;;;;;;ACnCb,SAAgB,WAAW,OAAoC;CAC7D,MAAM,EAAE,aAAa;CAErB,MAAM,gBAAgB,OAAuB;AAC3C,MAAI,CAAC,GAAI;EAGT,MAAM,YAAY;AAGlB,MAAI,UAAU,OACZ,WAAU,OAAO,GAAkB;;CAIvC,MAAM,YAAY,gDAAgD,MAAM,SAAS;AAEjF,QACE,oBAAC,OAAD;EAAK,KAAK;EAAc,OAAO,sBAAsB,MAAM,SAAS;EAAM,OAAO;EAAa;;;;;;;;;AC5BlG,MAAM,kBAAoE;CACxE,kBAAkB,OAAO,uCAA+B,MAAM,MAAM,EAAE,YAAY,CAAC;CACnF,kBACE,OAAO,uCAA+B,MAAM,MAAM,EAAE,WAAW,EAAE,YAAY,MAAM,CAAC,CAAC;CACvF,WAAW,OAAO,uCAA+B,MAAM,MAAM,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;CACzF,WACE,OAAO,uCAA+B,MAAM,MAC1C,EAAE,WAAW;EAAE,YAAY;EAAM,KAAK;EAAM,CAAC,CAC9C;CACH,YAAY,OAAO,sBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;CACjE,WAAW,OAAO,uCAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;CAC9D,YAAY,OAAO,sBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;CACjE,gBAAgB,OAAO,sBAA6B,MAAM,MAAM,EAAE,UAAU,CAAC;CAC7E,cAAc,OAAO,sBAA2B,MAAM,MAAM,EAAE,QAAQ,CAAC;CACvE,YAAY,OAAO,sBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;CACjE,WAAW,OAAO,sBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;CAC9D,WAAW,OAAO,sBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;CAC9D,YAAY,OAAO,sBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;CACjE,WAAW,OAAO,sBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;CAC9D,YAAY,OAAO,sBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;CACjE,UAAU,OAAO,sBAAuB,MAAM,MAAM,EAAE,IAAI,CAAC;CAC3D,WAAW,OAAO,sBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;CAC9D,YAAY,QAAQ,QAAQ,EAAE,CAAC;CAC/B,aAAa,QAAQ,QAAQ,EAAE,CAAC;CAChC,aAAa,QAAQ,QAAQ,EAAE,CAAC;CACjC;AAGD,MAAM,yBAAS,IAAI,KAAgC;;;;;;;;;;AAWnD,eAAsB,aAAa,UAA8C;CAC/E,MAAM,SAAS,OAAO,IAAI,SAAS;AACnC,KAAI,OAAQ,QAAO;CAEnB,MAAM,SAAS,gBAAgB;AAC/B,KAAI,CAAC,OAAQ,QAAO,EAAE;AAEtB,KAAI;EACF,MAAM,MAAM,MAAM,QAAQ;AAC1B,SAAO,IAAI,UAAU,IAAI;AACzB,SAAO;SACD;AAEN,SAAO,EAAE;;;;;;AAOb,SAAgB,wBAA0C;AACxD,QAAO,OAAO,KAAK,gBAAgB;;;;;;;;AC5DrC,MAAa,aAAwB,WAAW,MAAM;CACpD,KAAK;EACH,iBAAiB;EACjB,OAAO;EACR;CACD,eAAe,EACb,YAAY,WACb;CACD,cAAc,EACZ,iBAAiB,WAClB;CACD,iEAAiE,EAC/D,iBAAiB,WAClB;CACD,eAAe;EACb,iBAAiB;EACjB,OAAO;EACP,aAAa;EACd;CACD,wBAAwB;EACtB,iBAAiB;EACjB,OAAO;EACR;CACD,kBAAkB,EAChB,iBAAiB,WAClB;CACD,kBAAkB,EAChB,OAAO,WACR;CACF,CAAC;;;;AAKF,MAAa,YAAuB,WAAW,MAC7C;CACE,KAAK;EACH,iBAAiB;EACjB,OAAO;EACR;CACD,eAAe,EACb,YAAY,WACb;CACD,cAAc,EACZ,iBAAiB,WAClB;CACD,iEAAiE,EAC/D,iBAAiB,WAClB;CACD,eAAe;EACb,iBAAiB;EACjB,OAAO;EACP,aAAa;EACd;CACD,wBAAwB;EACtB,iBAAiB;EACjB,OAAO;EACR;CACD,kBAAkB,EAChB,iBAAiB,aAClB;CACD,kBAAkB,EAChB,OAAO,WACR;CACD,uBAAuB;EACrB,iBAAiB;EACjB,OAAO;EACR;CACF,EACD,EAAE,MAAM,MAAM,CACf;;;;AAKD,SAAgB,aAAa,OAA+B;AAC1D,KAAI,UAAU,QAAS,QAAO;AAC9B,KAAI,UAAU,OAAQ,QAAO;AAC7B,QAAO;;;;;ACzET,MAAM,YAAY,UAChB,OAAO,UAAU,WAAW,QAAQ,OAAO;AAE7C,MAAM,YAAY,UAChB,OAAO,UAAU;;;;;;;;;;;;;;;;;;AAmBnB,SAAgB,WAAW,OAAoC;CAC7D,MAAM,EAAE,UAAU,UAAU,WAAW,SAAS,QAAQ,SAAS,WAAW,SAAS;CAErF,IAAI,YAA8B;CAClC,MAAM,WAA2B,EAAE;CAEnC,MAAM,eAAe,OAAO,OAAuB;AACjD,MAAI,CAAC,GAAI;EAET,MAAM,UAAU,MAAM,aAAa,SAAS;EAC5C,MAAM,WAAW,aAAa,MAAM;EAEpC,MAAM,aAA0B;GAC9B,mBAAmB,uBAAuB,EAAE,UAAU,MAAM,CAAC;GAC7D;GACA;GACA,WAAW,SAAS,GAAG,CAAC,SAAS;GACjC,YAAY,SAAS,GAAG,SAAS;GAClC;EAED,MAAM,eAAe,SAAS,SAAS;EACvC,MAAM,eAAe,SAAS,SAAS;AAGtC,EAAC,GAAmB,YAAY;AAEjC,cAAY,IAAI,UAAU;GACxB,GAAG;IAAE,KAAK;IAAc;IAAY;GACpC,GAAG;IAAE,KAAK;IAAc;IAAY;GACpC,QAAQ;GACR,mBAAmB;IAAE,QAAQ;IAAG,SAAS;IAAG;GAC7C,CAAC;AAGF,MAAI,SAAS,SAAS,EAAE;GACtB,MAAM,OAAO,MAAM,WAAW,SAAS;AACrC,QAAI,CAAC,UAAW;IAChB,MAAM,SAAS,UAAU;AACzB,WAAO,SAAS,EACd,SAAS;KAAE,MAAM;KAAG,IAAI,OAAO,MAAM,IAAI;KAAQ,QAAQ;KAAM,EAChE,CAAC;KACF;AACF,YAAS,KAAK,KAAK;;AAGrB,MAAI,SAAS,SAAS,EAAE;GACtB,MAAM,OAAO,MAAM,WAAW,SAAS;AACrC,QAAI,CAAC,UAAW;IAChB,MAAM,SAAS,UAAU;AACzB,WAAO,SAAS,EACd,SAAS;KAAE,MAAM;KAAG,IAAI,OAAO,MAAM,IAAI;KAAQ,QAAQ;KAAM,EAChE,CAAC;KACF;AACF,YAAS,KAAK,KAAK;;;AAIvB,iBAAgB;AACd,OAAK,MAAM,WAAW,SAAU,UAAS;AACzC,aAAW,SAAS;AACpB,cAAY;GACZ;CAEF,MAAM,YAAY,gDAAgD,MAAM,SAAS;AAEjF,QACE,oBAAC,OAAD;EAAK,KAAK;EAAc,OAAO,sBAAsB,MAAM,SAAS;EAAM,OAAO;EAAa;;;;;;;;;;;;;;;;;;;;;;;AC/ElG,SAAgB,aAAa,OAAsC;CACjE,MAAM,EAAE,aAAa;CAErB,MAAM,iBAAiB,qEAAqE,MAAM,SAAS;CAE3G,MAAM,cACJ;AAEF,QACE,qBAAC,OAAD;EAAK,OAAO,wBAAwB,MAAM,SAAS;EAAM,OAAO;YAAhE,OACS;GACL,MAAM,OAAO,SAAS,MAAM;GAC5B,MAAM,WAAW,SAAS,aAAa;AAEvC,UACE,oBAAC,OAAD;IAAK,OAAM;IAA4B,OAAO;cAC3C,KAAK,KAAK,QAAQ;KACjB,MAAM,KAAK,IAAI,MAAM,IAAI;KACzB,MAAM,WAAW,OAAO;KAExB,MAAM,WAAW,8FAA8F,WAAW,UAAU,cAAc,mBAAmB,WAAW,sBAAsB,wBAAwB,6CAA6C,WAAW,YAAY,UAAU;AAE5S,YACE,qBAAC,UAAD;MACE,MAAK;MAEL,OAAO,cAAc,WAAW,WAAW,GAAG,GAAG,IAAI,WAAW,aAAa;MAC7E,OAAO;MACP,eAAe,SAAS,UAAU,GAAG;gBALvC;OAOE,oBAAC,QAAD,YAAO,IAAI,MAAY;OACtB,IAAI,YACH,oBAAC,QAAD;QACE,OAAM;QACN,OAAM;QACN;OAEH,IAAI,aAAa,SAChB,oBAAC,QAAD;QACE,OAAM;QACN,OAAM;QACN,UAAU,MAAkB;AAC1B,WAAE,iBAAiB;AACnB,kBAAS,SAAS,GAAG;;kBAExB;QAEM;OAEF;QAxBF,GAwBE;MAEX;IACE;KAGV,oBAAC,OAAD;GAAK,OAAM;aACT,oBAAC,YAAD,EAAY,UAAU,SAAS,QAAU;GACrC,EACF;;;;;;;;;;ACxEV,MAAM,gBAAgB;AACtB,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AAExB,SAAS,sBAAyC;CAChD,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,MAAM,UAAU,gDAAgD,cAAc;AACrF,QAAO,QAAQ,gBAAgB;AAC/B,QAAO;;AAGT,SAAS,cAAc,QAA2B,MAAwB;CACxE,MAAM,MAAM,OAAO,WAAW,KAAK;AACnC,KAAI,CAAC,IAAK;CAEV,MAAM,MAAM,KAAK,MAAM;CACvB,MAAM,aAAa,IAAI;CACvB,MAAM,SAAS,OAAO;AACtB,QAAO,SAAS,SAAS;CAEzB,MAAM,SAAS,KAAK,IAAI,UAAU,SAAS,UAAU;CACrD,MAAM,KAAK,SAAS,aAAa;CACjC,MAAM,YAAY,SAAS,aAAa;CAExC,MAAM,QAAQ;AACd,KAAI,aAAa,OAAO,GAAG,GAAG,OAAO,GAAG,EAAE;AAG1C,KAAI,YAAY;AAChB,KAAI,SAAS,GAAG,GAAG,eAAe,OAAO;CAGzC,MAAM,gBAAgB,aAAa;CACnC,MAAM,iBACJ,gBAAgB,SACZ,KAAK,UAAU,aAAa,KAAK,UAAU,eAAe,KAAK,UAAU,gBAAgB,KACzF;CACN,MAAM,SAAS,gBAAgB,SAAS,kBAAkB,gBAAgB,UAAU;AAGpF,KAAI,YAAY;CAChB,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,YAAY,CAAC;CAC/D,MAAM,UAAU,KAAK,IAAI,YAAY,YAAY,KAAK,KAAK,SAAS,YAAY,GAAG,EAAE;AAErF,MAAK,IAAI,IAAI,WAAW,KAAK,SAAS,KAAK;EACzC,MAAM,OAAO,IAAI,KAAK,EAAE;EACxB,MAAM,KAAK,IAAI,KAAK,cAAc;AAClC,MAAI,IAAI,CAAC,eAAe,IAAI,OAAQ;EAEpC,MAAM,OAAO,KAAK;EAClB,IAAI,IAAI;AACR,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK,QAAQ,GAAG,EAAE,KAAK;AAClD,OAAI,KAAK,OAAO,OAAO,KAAK,OAAO,IACjC,KAAI,SAAS,GAAG,GAAG,YAAY,IAAI;AAErC,QAAK;;;CAKT,MAAM,cAAc,KAAK,UAAU;CACnC,MAAM,iBAAiB,KAAK,UAAU;CACtC,MAAM,YAAY,KAAK,UAAU,gBAAgB;CAEjD,MAAM,MAAO,cAAc,YAAa,KAAK,IAAI,eAAe,OAAO;CACvE,MAAM,MAAO,iBAAiB,YAAa,KAAK,IAAI,eAAe,OAAO;AAE1E,KAAI,YAAY;AAChB,KAAI,SAAS,GAAG,KAAK,eAAe,IAAI;AACxC,KAAI,cAAc;AAClB,KAAI,YAAY;AAChB,KAAI,WAAW,IAAK,MAAM,IAAK,gBAAgB,GAAG,MAAM,EAAE;;;;;;;;;;;;AAa5D,SAAgB,mBAA8B;AAC5C,QAAO,CACL,WAAW,UACT,MAAM;EACJ;EACA;EACA,YAA2B;EAE3B,YAAY,MAAkB;AAC5B,QAAK,OAAO;AACZ,QAAK,SAAS,qBAAqB;AACnC,QAAK,IAAI,MAAM,WAAW;AAC1B,QAAK,IAAI,YAAY,KAAK,OAAO;AAGjC,QAAK,OAAO,iBAAiB,UAAU,MAAM;IAC3C,MAAM,OAAO,KAAK,OAAO,uBAAuB;IAGhD,MAAM,gBAFS,EAAE,UAAU,KAAK,OACN,KAAK,UAEjB,KAAK,UAAU,eAAe,KAAK,UAAU;AAC3D,SAAK,UAAU,SAAS;KAAE,KAAK;KAAc,UAAU;KAAU,CAAC;KAClE;AAEF,QAAK,QAAQ;;EAGf,SAAS;AACP,iBAAc,KAAK,QAAQ,KAAK,KAAK;;EAGvC,OAAO,QAAoB;AACzB,OAAI,OAAO,cAAc,OAAO,mBAAmB,OAAO,iBAAiB;AACzE,QAAI,KAAK,UAAW,sBAAqB,KAAK,UAAU;AACxD,SAAK,YAAY,4BAA4B,KAAK,QAAQ,CAAC;;;EAI/D,UAAU;AACR,OAAI,KAAK,UAAW,sBAAqB,KAAK,UAAU;AACxD,QAAK,OAAO,QAAQ;;GAGzB,EAED,WAAW,MAAM,EACf,gBAAgB,EACd,cAAc,GAAG,gBAAgB,EAAE,KACpC,EACF,CAAC,CACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1EH,SAAgB,aAAa,SAAuB,EAAE,EAAkB;CACtE,MAAM,EACJ,OAAO,eAAe,IACtB,UAAU,kBAAkB,SAC5B,OAAO,eAAe,SACtB,aAAa,kBAAkB,MAC/B,UAAU,kBAAkB,OAC5B,YAAY,iBAAiB,MAC7B,iBAAiB,wBAAwB,MACzC,cAAc,qBAAqB,MACnC,QAAQ,gBAAgB,MACxB,uBAAuB,qBAAqB,MAC5C,KAAK,YAAY,OACjB,OAAO,cAAc,OACrB,SAAS,gBAAgB,GACzB,cAAc,qBAAqB,OACnC,aAAa,iBACb,SAAS,gBAAgB,OACzB,YAAY,iBAAiB,EAAE,EAC/B,aACE;CAIJ,MAAM,QAAQ,OAAO,aAAa;CAClC,MAAM,WAAW,OAAuB,gBAAgB;CACxD,MAAM,QAAQ,OAAoB,aAAa;CAC/C,MAAM,WAAW,OAAO,gBAAgB;CACxC,MAAM,UAAU,OAAO,MAAM;CAC7B,MAAM,OAAO,OAA0B,KAAK;CAG5C,MAAM,aAAa,OAAO,EAAE;CAI5B,MAAM,sBAAsB,IAAI,aAAa;CAC7C,MAAM,mBAAmB,IAAI,aAAa;CAC1C,MAAM,sBAAsB,IAAI,aAAa;CAC7C,MAAM,yBAAyB,IAAI,aAAa;CAChD,MAAM,qBAAqB,IAAI,aAAa;CAI5C,MAAM,SAAS,eAAe;AAC5B,cAAY;EACZ,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG,QAAO;GAAE,MAAM;GAAG,KAAK;GAAG;EAClC,MAAM,MAAM,EAAE,MAAM,UAAU,KAAK;EACnC,MAAM,OAAO,EAAE,MAAM,IAAI,OAAO,IAAI;AACpC,SAAO;GAAE,MAAM,KAAK;GAAQ,KAAK,MAAM,KAAK,OAAO;GAAG;GACtD;CAEF,MAAM,YAAY,eAAe;AAC/B,cAAY;EACZ,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG,QAAO;GAAE,MAAM;GAAG,IAAI;GAAG,MAAM;GAAI;EAC3C,MAAM,MAAM,EAAE,MAAM,UAAU;AAC9B,SAAO;GACL,MAAM,IAAI;GACV,IAAI,IAAI;GACR,MAAM,EAAE,MAAM,SAAS,IAAI,MAAM,IAAI,GAAG;GACzC;GACD;CAEF,MAAM,YAAY,eAAe;AAC/B,cAAY;EACZ,MAAM,IAAI,KAAK,MAAM;AACrB,SAAO,IAAI,EAAE,MAAM,IAAI,QAAQ,aAAa,MAAM,KAAK,CAAC;GACxD;CAIF,MAAM,iCAAiB,IAAI,KAAqB;CAEhD,MAAM,qBAAqB,WAAW,UACpC,MAAM;EACJ;EAEA,YAAY,YAAwB;AAClC,QAAK,cAAc,KAAK,WAAW,WAAW;;EAGhD,WAAW,YAAuC;GAChD,MAAM,SAA6C,EAAE;AACrD,QAAK,MAAM,CAAC,SAAS,QAAQ,eAC3B,KAAI,WAAW,KAAK,WAAW,WAAW,MAAM,IAAI,OAAO;IACzD,MAAM,WAAW,WAAW,MAAM,IAAI,KAAK,QAAQ;AACnD,WAAO,KAAK;KACV,MAAM,SAAS;KACf,MAAM,WAAW,KAAK,EAAE,OAAO,KAAK,CAAC;KACtC,CAAC;;AAGN,UAAO,WAAW,IAChB,OAAO,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,CAAC,CACxE;;EAGH,OAAO,KAAiB;AACtB,OAAI,IAAI,cAAc,IAAI,gBACxB,MAAK,cAAc,KAAK,WAAW,IAAI,KAAK;;IAIlD,EAAE,cAAc,WAAW,OAAO,aAAa,CAChD;CAID,MAAM,gCAAgB,IAAI,KAAgE;CAE1F,MAAM,2BAA2BA,aAAe;EAC9C;EACA;EACA;EAEA,YAAY,MAAyD;AACnE,UAAO;AACP,QAAK,aAAa,KAAK,QAAQ;AAC/B,QAAK,cAAc,KAAK,SAAS;AACjC,QAAK,cAAc,KAAK,SAAS;;EAGnC,AAAS,QAAQ;GACf,MAAM,KAAK,SAAS,cAAc,OAAO;AACzC,MAAG,cAAc,KAAK;AACtB,MAAG,QAAQ,KAAK;AAChB,OAAI,KAAK,YAAa,IAAG,YAAY,KAAK;AAC1C,MAAG,MAAM,UAAU;AACnB,UAAO;;;CAIX,MAAM,wBAAwB,OAAO;EACnC,OAAO;EACP,aAAa,YAAY,SAAS;GAChC,MAAM,SAAS,WAAW,MAAM,IAAI,OAAO,KAAK,KAAK,CAAC;GACtD,MAAM,SAAS,cAAc,IAAI,OAAO;AACxC,OAAI,CAAC,OAAQ,QAAO;AACpB,UAAO,IAAI,mBAAmB,OAAO;;EAEvC,qBAAqB,IAAI,mBAAmB,EAAE,MAAM,KAAK,CAAC;EAC3D,CAAC;CAIF,SAAS,gBAAgB,SAAiC;EACxD,MAAM,OAAoB;GAExB,SAAS;GACT,eAAe;GACf,YAAY;GACZ,sBAAsB;GACtB,iBAAiB;GACjB,qBAAqB;GACrB,2BAA2B;GAC3B,2BAA2B;GAC3B,eAAe;GACf,mBAAmB,uBAAuB,EAAE,UAAU,MAAM,CAAC;GAC7D,WAAW,GAAG,IAAI,OAAO,cAAc,CAAC;GAGxC,OAAO,GAAG;IACR,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH;IACD,CAAC;GAGF,oBAAoB,GAAG,QAAQ;GAC/B,iBAAiB,GAAG,aAAa,aAAa,CAAC;GAC/C,oBAAoB,GAAG,YAAY,SAAS,GAAG,gBAAgB,CAAC;GAChE,uBAAuB,GAAG,EAAE,CAAC;GAC7B,mBAAmB,GAAG,EAAE,CAAC;GAGzB,WAAW,eAAe,IAAI,WAAW;AACvC,QAAI,OAAO,YAAY;KACrB,MAAM,WAAW,OAAO,MAAM,IAAI,UAAU;AAE5C,SAAI,aAAa,MAAM,MAAM,EAAE;AAC7B,YAAM,IAAI,SAAS;AACnB,iBAAW,SAAS;;AAEtB,gBAAW,QAAQ,MAAM,IAAI,EAAE;;AAEjC,QAAI,OAAO,aACT,YAAW,QAAQ,MAAM,IAAI,EAAE;AAEjC,QAAI,OAAO,aACT,SAAQ,IAAI,OAAO,KAAK,SAAS;KAEnC;GACH;AAGD,MAAI,gBAAiB,MAAK,KAAK,aAAa,CAAC;AAC7C,MAAI,eAAgB,MAAK,KAAK,YAAY,CAAC;AAC3C,MAAI,sBAAuB,MAAK,KAAK,iBAAiB,EAAE,eAAe,CAAC;AACxE,MAAI,mBAAoB,MAAK,KAAK,gBAAgB,CAAC;AACnD,MAAI,mBAAoB,MAAK,KAAK,WAAW,aAAa;AAE1D,MAAI,mBACF,MAAK,KACH,WAAW,MAAM,EACf,YAAY;GACV,iBAAiB;GACjB,gBAAgB,GAAG,cAAc;GACjC,oBAAoB;GACrB,EACF,CAAC,CACH;AAEH,MAAI,gBAAiB,MAAK,KAAKC,YAAe,gBAAgB,CAAC;AAC/D,MAAI,cAAe,MAAK,KAAK,kBAAkB,CAAC;AAGhD,OAAK,KAAK,mBAAmB;AAE7B,OAAK,KAAK,sBAAsB;AAGhC,OAAK,KAAK,GAAG,eAAe;AAE5B,SAAO;;CAKT,IAAI,UAAU;CAEd,eAAe,MAAM,QAAoC;AACvD,MAAI,QAAS;EAGb,MAAM,aAAa,gBADH,MAAM,aAAa,SAAS,MAAM,CAAC,CACR;EAO3C,MAAM,aAAa,IAAI,WAAW;GAChC,OANY,YAAY,OAAO;IAC/B,KAAK,MAAM,MAAM;IACjB;IACD,CAAC;GAIA;GACD,CAAC;AAEF,OAAK,IAAI,WAAW;AACpB,YAAU;AAGV,eAAa;GACX,MAAM,MAAM,OAAO;GACnB,MAAM,IAAI,KAAK,MAAM;AACrB,OAAI,CAAC,EAAG;GACR,MAAM,UAAU,EAAE,MAAM,IAAI,UAAU;AACtC,OAAI,QAAQ,QACV,GAAE,SAAS,EACT,SAAS;IAAE,MAAM;IAAG,IAAI,QAAQ;IAAQ,QAAQ;IAAK,EACtD,CAAC;IAEJ;AAGF,eAAa;GACX,MAAM,OAAO,UAAU;GACvB,MAAM,IAAI,KAAK,MAAM;AACrB,OAAI,CAAC,EAAG;AACR,gBAAa,KAAK,CAAC,MAAM,QAAQ;AAC/B,MAAE,SAAS,EAAE,SAAS,oBAAoB,YAAY,IAAI,EAAE,CAAC;KAC7D;IACF;AAGF,eAAa;GACX,MAAM,IAAI,OAAO;GACjB,MAAM,IAAI,KAAK,MAAM;AACrB,OAAI,CAAC,EAAG;AACR,KAAE,SAAS,EAAE,SAAS,iBAAiB,YAAY,aAAa,EAAE,CAAC,EAAE,CAAC;IACtE;AAGF,eAAa;GACX,MAAM,KAAK,UAAU;GACrB,MAAM,IAAI,KAAK,MAAM;AACrB,OAAI,CAAC,EAAG;AACR,KAAE,SAAS,EACT,SAAS,oBAAoB,YAAY,YAAY,SAAS,GAAG,GAAG,CAAC,EACtE,CAAC;IACF;;CAKJ,SAAS,QAAc;AACrB,OAAK,MAAM,EAAE,OAAO;;CAGtB,SAAS,OAAO,MAAoB;EAClC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;EACR,MAAM,MAAM,EAAE,MAAM,UAAU,KAAK;AACnC,IAAE,SAAS,EAAE,SAAS;GAAE,MAAM;GAAK,QAAQ;GAAM,EAAE,CAAC;;CAGtD,SAAS,iBAAiB,MAAoB;EAC5C,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAAS,EAAE,MAAM,iBAAiB,KAAK,CAAC;;CAG5C,SAAS,OAAO,MAAc,IAAkB;EAC9C,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAAS,EAAE,WAAW;GAAE,QAAQ;GAAM,MAAM;GAAI,EAAE,CAAC;;CAGvD,SAAS,YAAkB;EACzB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAAS,EAAE,WAAW;GAAE,QAAQ;GAAG,MAAM,EAAE,MAAM,IAAI;GAAQ,EAAE,CAAC;;CAGpE,SAAS,SAAS,MAAoB;EACpC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;EACR,MAAM,WAAW,EAAE,MAAM,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,EAAE,EAAE,MAAM,IAAI,MAAM,CAAC;AACjF,IAAE,SAAS;GACT,WAAW,EAAE,QAAQ,SAAS,MAAM;GACpC,gBAAgB;GACjB,CAAC;AACF,IAAE,OAAO;;CAGX,SAASC,SAAa;EACpB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,MAAO,EAAE;;CAGlB,SAASC,SAAa;EACpB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,MAAO,EAAE;;CAGlB,SAAS,UAAgB;EACvB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;EACR,MAAM,EAAE,SAAS,yBAAuB,uBAAuB;AAC/D,aAAW,EAAE;;CAGf,SAAS,YAAkB;EACzB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;EACR,MAAM,EAAE,WAAW,2BAAyB,uBAAuB;AACnE,eAAa,EAAE;;CAKjB,SAASC,iBAAe,aAAmD;EACzE,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SACAC,eACE,EAAE,OACF,YAAY,KAAK,OAAO;GACtB,MAAM,EAAE;GACR,IAAI,EAAE;GACN,UAAU,EAAE,aAAa,SAAS,SAAS,EAAE;GAC7C,SAAS,EAAE;GACX,GAAI,EAAE,UAAU,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,EAAE;GACjD,EAAE,CACJ,CACF;;CAGH,SAAS,mBAAyB;EAChC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAASA,eAAiB,EAAE,OAAO,EAAE,CAAC,CAAC;;CAK3C,SAAS,cAAc,MAAc,WAAyB;AAC5D,iBAAe,IAAI,MAAM,UAAU;EAEnC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,GAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC;;CAGpC,SAAS,sBAA4B;AACnC,iBAAe,OAAO;EACtB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,GAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC;;CAKpC,SAAS,gBAAgB,MAAc,QAA8C;AACnF,gBAAc,IAAI,MAAM,OAAO;EAC/B,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,GAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC;;CAGpC,SAAS,qBAA2B;AAClC,gBAAc,OAAO;EACrB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,EAAG,GAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC;;CAKpC,MAAM,oBAAgE,EAAE;CAExE,SAAS,cAAc,KAAa,SAA0C;AAC5E,oBAAkB,KAAK;GACrB;GACA,WAAW;AACT,aAAS;AACT,WAAO;;GAEV,CAAC;EACF,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAAS,EACT,SAAS,uBAAuB,YAAY,OAAO,GAAG,kBAAkB,CAAC,EAC1E,CAAC;;CAKJ,SAAS,QAAQ,MAAsB;EACrC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG,QAAO;EACf,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,EAAE,EAAE,MAAM,IAAI,MAAM;AAC9D,SAAO,EAAE,MAAM,IAAI,KAAK,QAAQ,CAAC;;CAGnC,SAAS,kBAA0B;EACjC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG,QAAO;EACf,MAAM,MAAM,EAAE,MAAM,UAAU,KAAK;EACnC,MAAM,OAAO,EAAE,MAAM,IAAI,OAAO,IAAI;EACpC,MAAM,MAAM,MAAM,KAAK;EACvB,MAAM,OAAO,KAAK;EAGlB,IAAI,QAAQ;EACZ,IAAI,MAAM;AACV,SAAO,QAAQ,KAAK,KAAK,KAAK,KAAK,OAAO,QAAQ,EAAE,CAAC,CAAE;AACvD,SAAO,MAAM,KAAK,UAAU,KAAK,KAAK,KAAK,OAAO,IAAI,CAAC,CAAE;AAEzD,SAAO,KAAK,MAAM,OAAO,IAAI;;CAG/B,SAAS,SAAS,KAAmB;EACnC,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;AACR,IAAE,SAAS,EACT,SAAS,WAAW,eAAe,KAAK,EAAE,GAAG,UAAU,CAAC,EACzD,CAAC;;CAKJ,eAAe,cAA6B;EAC1C,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,CAAC,EAAG;EAGR,MAAM,SAAS;EACf,MAAM,WAAW;AAEjB,MAAI,UACF,KAAI;GACF,MAAM,MAAM,MAAM;;IAA0B;;AAC5C,KAAE,SAAS,EACT,SAAS,mBAAmB,YAAY,IAAI,KAAK,CAAC,EACnD,CAAC;UACI;AAKV,MAAI,YACF,KAAI;GACF,MAAM,MAAM,MAAM;;IAA0B;;AAC5C,KAAE,SAAS,EACT,SAAS,mBAAmB,YAAY,IAAI,OAAO,CAAC,EACrD,CAAC;UACI;;CAMZ,SAAS,UAAgB;EACvB,MAAM,IAAI,KAAK,MAAM;AACrB,MAAI,GAAG;AACL,KAAE,SAAS;AACX,QAAK,IAAI,KAAK;AACd,aAAU;;;AA4Cd,QAtC4D;EAC1D;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ,OAAO,WAAwB;AACrC,SAAM,MAAM,OAAO;AACnB,SAAM,aAAa;;EAEtB"}
@@ -4,8 +4,8 @@ import { EditorView } from "@codemirror/view";
4
4
  import { Computed, Signal } from "@pyreon/reactivity";
5
5
 
6
6
  //#region src/types.d.ts
7
- type EditorLanguage = "javascript" | "typescript" | "jsx" | "tsx" | "html" | "css" | "json" | "markdown" | "python" | "rust" | "sql" | "xml" | "yaml" | "cpp" | "java" | "go" | "php" | "ruby" | "shell" | "plain";
8
- type EditorTheme = "light" | "dark" | Extension;
7
+ type EditorLanguage = 'javascript' | 'typescript' | 'jsx' | 'tsx' | 'html' | 'css' | 'json' | 'markdown' | 'python' | 'rust' | 'sql' | 'xml' | 'yaml' | 'cpp' | 'java' | 'go' | 'php' | 'ruby' | 'shell' | 'plain';
8
+ type EditorTheme = 'light' | 'dark' | Extension;
9
9
  interface EditorConfig {
10
10
  /** Initial value */
11
11
  value?: string;
@@ -125,7 +125,7 @@ interface Diagnostic {
125
125
  /** End position (character offset) */
126
126
  to: number;
127
127
  /** Severity */
128
- severity: "error" | "warning" | "info" | "hint";
128
+ severity: 'error' | 'warning' | 'info' | 'hint';
129
129
  /** Message */
130
130
  message: string;
131
131
  /** Optional source (e.g., "typescript", "eslint") */
@@ -180,7 +180,7 @@ interface TabbedEditorConfig {
180
180
  /** Theme — 'light', 'dark', or custom */
181
181
  theme?: EditorTheme;
182
182
  /** Editor config applied to all tabs */
183
- editorConfig?: Omit<EditorConfig, "value" | "language" | "theme">;
183
+ editorConfig?: Omit<EditorConfig, 'value' | 'language' | 'theme'>;
184
184
  }
185
185
  interface TabbedEditorInstance {
186
186
  /** The underlying editor instance */
@@ -239,6 +239,9 @@ declare function CodeEditor(props: CodeEditorProps): VNodeChild;
239
239
  /**
240
240
  * Side-by-side or inline diff editor using @codemirror/merge.
241
241
  *
242
+ * Supports reactive `original` and `modified` props — pass a Signal<string>
243
+ * and the diff view updates automatically when the signal changes.
244
+ *
242
245
  * @example
243
246
  * ```tsx
244
247
  * <DiffEditor
@@ -1 +1 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/components/code-editor.tsx","../../../src/components/diff-editor.tsx","../../../src/components/tabbed-editor.tsx","../../../src/editor.ts","../../../src/languages.ts","../../../src/minimap.ts","../../../src/themes.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/components/code-editor.tsx","../../../src/components/diff-editor.tsx","../../../src/components/tabbed-editor.tsx","../../../src/editor.ts","../../../src/languages.ts","../../../src/minimap.ts","../../../src/themes.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,20 +1,17 @@
1
1
  {
2
2
  "name": "@pyreon/code",
3
- "version": "0.11.4",
3
+ "version": "0.11.6",
4
4
  "description": "Reactive code editor for Pyreon — CodeMirror 6 with signals, minimap, diff editor, lazy-loaded languages",
5
+ "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/code#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/pyreon/pyreon/issues"
8
+ },
5
9
  "license": "MIT",
6
10
  "repository": {
7
11
  "type": "git",
8
12
  "url": "https://github.com/pyreon/pyreon.git",
9
13
  "directory": "packages/fundamentals/code"
10
14
  },
11
- "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/code#readme",
12
- "bugs": {
13
- "url": "https://github.com/pyreon/pyreon/issues"
14
- },
15
- "publishConfig": {
16
- "access": "public"
17
- },
18
15
  "files": [
19
16
  "lib",
20
17
  "src",
@@ -22,6 +19,7 @@
22
19
  "LICENSE"
23
20
  ],
24
21
  "type": "module",
22
+ "sideEffects": false,
25
23
  "main": "./lib/index.js",
26
24
  "module": "./lib/index.js",
27
25
  "types": "./lib/types/index.d.ts",
@@ -32,13 +30,15 @@
32
30
  "types": "./lib/types/index.d.ts"
33
31
  }
34
32
  },
35
- "sideEffects": false,
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
36
  "scripts": {
37
37
  "build": "vl_rolldown_build",
38
38
  "dev": "vl_rolldown_build-watch",
39
39
  "test": "vitest run",
40
40
  "typecheck": "tsc --noEmit",
41
- "lint": "biome check ."
41
+ "lint": "oxlint ."
42
42
  },
43
43
  "dependencies": {
44
44
  "@codemirror/autocomplete": "^6.20.1",
@@ -51,30 +51,30 @@
51
51
  "@codemirror/view": "^6.40.0",
52
52
  "codemirror": "^6.0.2"
53
53
  },
54
+ "devDependencies": {
55
+ "@happy-dom/global-registrator": "^20.8.3",
56
+ "@pyreon/core": "^0.11.6",
57
+ "@pyreon/reactivity": "^0.11.6",
58
+ "@vitus-labs/tools-lint": "^1.11.0"
59
+ },
60
+ "peerDependencies": {
61
+ "@pyreon/core": "^0.11.6",
62
+ "@pyreon/reactivity": "^0.11.6"
63
+ },
54
64
  "optionalDependencies": {
55
- "@codemirror/lang-javascript": "^6.2.5",
56
- "@codemirror/lang-html": "^6.4.11",
65
+ "@codemirror/lang-cpp": "^6.0.2",
57
66
  "@codemirror/lang-css": "^6.3.1",
67
+ "@codemirror/lang-go": "^6.0.1",
68
+ "@codemirror/lang-html": "^6.4.11",
69
+ "@codemirror/lang-java": "^6.0.1",
70
+ "@codemirror/lang-javascript": "^6.2.5",
58
71
  "@codemirror/lang-json": "^6.0.2",
59
- "@codemirror/lang-python": "^6.2.1",
60
72
  "@codemirror/lang-markdown": "^6.5.0",
73
+ "@codemirror/lang-php": "^6.0.1",
74
+ "@codemirror/lang-python": "^6.2.1",
61
75
  "@codemirror/lang-rust": "^6.0.2",
62
76
  "@codemirror/lang-sql": "^6.10.0",
63
77
  "@codemirror/lang-xml": "^6.1.0",
64
- "@codemirror/lang-yaml": "^6.1.2",
65
- "@codemirror/lang-cpp": "^6.0.2",
66
- "@codemirror/lang-java": "^6.0.1",
67
- "@codemirror/lang-go": "^6.0.1",
68
- "@codemirror/lang-php": "^6.0.1"
69
- },
70
- "peerDependencies": {
71
- "@pyreon/core": "^0.11.4",
72
- "@pyreon/reactivity": "^0.11.4"
73
- },
74
- "devDependencies": {
75
- "@happy-dom/global-registrator": "^20.8.3",
76
- "@pyreon/core": "^0.11.4",
77
- "@pyreon/reactivity": "^0.11.4",
78
- "@vitus-labs/tools-lint": "^1.11.0"
78
+ "@codemirror/lang-yaml": "^6.1.2"
79
79
  }
80
80
  }
@@ -1,5 +1,5 @@
1
- import type { VNodeChild } from "@pyreon/core"
2
- import type { CodeEditorProps, EditorInstance } from "../types"
1
+ import type { VNodeChild } from '@pyreon/core'
2
+ import type { CodeEditorProps, EditorInstance } from '../types'
3
3
 
4
4
  /**
5
5
  * Code editor component — mounts a CodeMirror 6 instance.
@@ -30,9 +30,9 @@ export function CodeEditor(props: CodeEditorProps): VNodeChild {
30
30
  }
31
31
  }
32
32
 
33
- const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ""}`
33
+ const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ''}`
34
34
 
35
35
  return (
36
- <div ref={containerRef} class={`pyreon-code-editor ${props.class ?? ""}`} style={baseStyle} />
36
+ <div ref={containerRef} class={`pyreon-code-editor ${props.class ?? ''}`} style={baseStyle} />
37
37
  )
38
38
  }
@@ -1,16 +1,27 @@
1
- import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language"
2
- import { MergeView } from "@codemirror/merge"
3
- import { EditorState, type Extension } from "@codemirror/state"
4
- import { EditorView } from "@codemirror/view"
5
- import type { VNodeChild } from "@pyreon/core"
6
- import type { Signal } from "@pyreon/reactivity"
7
- import { loadLanguage } from "../languages"
8
- import { resolveTheme } from "../themes"
9
- import type { DiffEditorProps } from "../types"
1
+ import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'
2
+ import { MergeView } from '@codemirror/merge'
3
+ import { EditorState, type Extension } from '@codemirror/state'
4
+ import { EditorView } from '@codemirror/view'
5
+ import type { VNodeChild } from '@pyreon/core'
6
+ import { onUnmount } from '@pyreon/core'
7
+ import type { Signal } from '@pyreon/reactivity'
8
+ import { watch } from '@pyreon/reactivity'
9
+ import { loadLanguage } from '../languages'
10
+ import { resolveTheme } from '../themes'
11
+ import type { DiffEditorProps } from '../types'
12
+
13
+ const readText = (value: string | Signal<string>): string =>
14
+ typeof value === 'string' ? value : value()
15
+
16
+ const isSignal = (value: string | Signal<string>): value is Signal<string> =>
17
+ typeof value === 'function'
10
18
 
11
19
  /**
12
20
  * Side-by-side or inline diff editor using @codemirror/merge.
13
21
  *
22
+ * Supports reactive `original` and `modified` props — pass a Signal<string>
23
+ * and the diff view updates automatically when the signal changes.
24
+ *
14
25
  * @example
15
26
  * ```tsx
16
27
  * <DiffEditor
@@ -23,14 +34,10 @@ import type { DiffEditorProps } from "../types"
23
34
  * ```
24
35
  */
25
36
  export function DiffEditor(props: DiffEditorProps): VNodeChild {
26
- const {
27
- original,
28
- modified,
29
- language = "plain",
30
- theme = "light",
31
- readOnly = true,
32
- inline = false,
33
- } = props
37
+ const { original, modified, language = 'plain', theme = 'light', readOnly = true } = props
38
+
39
+ let mergeView: MergeView | null = null
40
+ const cleanups: (() => void)[] = []
34
41
 
35
42
  const containerRef = async (el: Element | null) => {
36
43
  if (!el) return
@@ -46,46 +53,52 @@ export function DiffEditor(props: DiffEditorProps): VNodeChild {
46
53
  EditorState.readOnly.of(readOnly),
47
54
  ]
48
55
 
49
- const originalText = typeof original === "string" ? original : (original as Signal<string>)()
50
- const modifiedText = typeof modified === "string" ? modified : (modified as Signal<string>)()
56
+ const originalText = readText(original)
57
+ const modifiedText = readText(modified)
51
58
 
52
59
  // Clear previous content
53
- ;(el as HTMLElement).innerHTML = ""
60
+ ;(el as HTMLElement).innerHTML = ''
54
61
 
55
- if (inline) {
56
- // Unified/inline diff view
57
- new MergeView({
58
- a: {
59
- doc: originalText,
60
- extensions,
61
- },
62
- b: {
63
- doc: modifiedText,
64
- extensions,
65
- },
66
- parent: el as HTMLElement,
67
- collapseUnchanged: { margin: 3, minSize: 4 },
62
+ mergeView = new MergeView({
63
+ a: { doc: originalText, extensions },
64
+ b: { doc: modifiedText, extensions },
65
+ parent: el as HTMLElement,
66
+ collapseUnchanged: { margin: 3, minSize: 4 },
67
+ })
68
+
69
+ // Track signal changes and update MergeView editors reactively
70
+ if (isSignal(original)) {
71
+ const stop = watch(original, (text) => {
72
+ if (!mergeView) return
73
+ const editor = mergeView.a
74
+ editor.dispatch({
75
+ changes: { from: 0, to: editor.state.doc.length, insert: text },
76
+ })
68
77
  })
69
- } else {
70
- // Side-by-side diff
71
- new MergeView({
72
- a: {
73
- doc: originalText,
74
- extensions,
75
- },
76
- b: {
77
- doc: modifiedText,
78
- extensions,
79
- },
80
- parent: el as HTMLElement,
81
- collapseUnchanged: { margin: 3, minSize: 4 },
78
+ cleanups.push(stop)
79
+ }
80
+
81
+ if (isSignal(modified)) {
82
+ const stop = watch(modified, (text) => {
83
+ if (!mergeView) return
84
+ const editor = mergeView.b
85
+ editor.dispatch({
86
+ changes: { from: 0, to: editor.state.doc.length, insert: text },
87
+ })
82
88
  })
89
+ cleanups.push(stop)
83
90
  }
84
91
  }
85
92
 
86
- const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ""}`
93
+ onUnmount(() => {
94
+ for (const cleanup of cleanups) cleanup()
95
+ mergeView?.destroy()
96
+ mergeView = null
97
+ })
98
+
99
+ const baseStyle = `width: 100%; height: 100%; overflow: hidden; ${props.style ?? ''}`
87
100
 
88
101
  return (
89
- <div ref={containerRef} class={`pyreon-diff-editor ${props.class ?? ""}`} style={baseStyle} />
102
+ <div ref={containerRef} class={`pyreon-diff-editor ${props.class ?? ''}`} style={baseStyle} />
90
103
  )
91
104
  }