@eclipse-lyra/extension-notebook 0.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-runtime-CFgw3UmB.js","sources":["../src/notebook-runtime.ts"],"sourcesContent":["import { css, html } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { Ref, createRef, ref } from \"lit/directives/ref.js\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { marked } from \"marked\";\nimport * as monaco from 'monaco-editor';\nimport monacoStyles from \"monaco-editor/min/vs/editor/editor.main.css?raw\";\nimport type { EditorInput } from \"@eclipse-lyra/core\";\nimport { File, workspaceService } from \"@eclipse-lyra/core\";\nimport { PyEnv, pythonPackageManagerService } from \"@eclipse-lyra/extension-python-runtime/api\";\nimport { LyraPart } from \"@eclipse-lyra/core\";\nimport type { NotebookCell, NotebookData, NotebookEditorLike } from \"./notebook-types\";\n\n@customElement('lyra-notebook-editor')\nexport class LyraNotebookEditor extends LyraPart implements NotebookEditorLike {\n @property({ attribute: false })\n public input?: EditorInput;\n\n @state()\n public notebook?: NotebookData;\n\n @state()\n private cellOutputs: Map<number, any> = new Map();\n\n @state()\n private executingCells: Set<number> = new Set();\n\n @state()\n private pyenv?: PyEnv;\n\n @state()\n private pyConnected: boolean = false;\n\n @state()\n private pyConnecting: boolean = false;\n\n @state()\n private pyVersion?: string;\n\n @state()\n private editingMarkdownCells: Set<number> = new Set();\n\n @state()\n private executionCounter: number = 0;\n\n @state()\n private isRunningAll: boolean = false;\n\n @state()\n private highlightedCellIndex: number = -1;\n\n public focusedCellIndex: number = -1;\n private cancelRunAll: boolean = false;\n\n private monacoEditors: Map<number, monaco.editor.IStandaloneCodeEditor> = new Map();\n private cellRefs: Map<number, Ref<HTMLElement>> = new Map();\n private themeObserver?: MutationObserver;\n\n protected doClose() {\n this.input = undefined;\n this.notebook = undefined;\n this.cellOutputs.clear();\n this.executingCells.clear();\n\n // Dispose Monaco editors\n this.monacoEditors.forEach(editor => editor.dispose());\n this.monacoEditors.clear();\n this.cellRefs.clear();\n this.focusedCellIndex = -1;\n\n if (this.themeObserver) {\n this.themeObserver.disconnect();\n this.themeObserver = undefined;\n }\n\n if (this.pyenv) {\n this.pyenv.close();\n this.pyenv = undefined;\n }\n\n this.pyConnected = false;\n this.pyVersion = undefined;\n }\n\n async save() {\n if (!this.notebook || !this.input) return;\n\n try {\n // Update cell contents from Monaco editors before saving\n this.saveEditorContents();\n\n this.notebook.cells.forEach((cell, index) => {\n if (cell.cell_type === 'code') {\n const output = this.cellOutputs.get(index);\n cell.outputs = output ? this.convertOutputToJupyter(output, cell.execution_count) : [];\n }\n });\n\n // Serialize notebook to JSON\n const notebookJson = JSON.stringify(this.notebook, null, 2);\n\n // Save to file\n const file: File = this.input.data;\n await file.saveContents(notebookJson);\n\n // Mark as not dirty\n this.markDirty(false);\n } catch (error) {\n console.error(\"Failed to save notebook:\", error);\n throw error;\n }\n }\n\n protected doBeforeUI() {\n // Start loading notebook asynchronously\n this.loadNotebook();\n }\n\n protected renderToolbar() {\n const connectionTitle = this.pyConnecting \n ? 'Connecting to Python...' \n : this.pyConnected \n ? 'Python Connected' \n : 'Python Disconnected - Click to connect';\n \n const connectionText = this.pyConnecting\n ? 'Connecting...'\n : this.pyConnected && this.pyVersion \n ? `Python ${this.pyVersion}` \n : 'Not connected';\n \n const iconColor = this.pyConnected\n ? \"var(--wa-color-green-40)\"\n : this.pyConnecting\n ? \"var(--wa-color-warning-500)\"\n : \"var(--wa-color-red-40)\";\n\n const runAllButton = this.isRunningAll ? html`\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.cancelAllCells()} title=\"Cancel running all cells\">\n <wa-icon name=\"stop\" label=\"Stop\"></wa-icon>\n Cancel All\n </wa-button>\n ` : html`\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.runAllCells()} title=\"Run all code cells sequentially\">\n <wa-icon name=\"play\" label=\"Run\"></wa-icon>\n Run All\n </wa-button>\n `;\n\n return html`\n <wa-button \n appearance=\"plain\" \n size=\"small\"\n style=\"display: flex; align-items: center; gap: 0.5rem;\"\n ?disabled=${this.pyConnecting}\n @click=${() => this.connectPython()}\n title=${connectionTitle}>\n <wa-icon \n name=\"circle\"\n label=\"Python status\"\n style=${styleMap({ color: iconColor })}\n ></wa-icon>\n ${connectionText}\n </wa-button>\n ${runAllButton}\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.clearAllOutputs()}\n title=\"Clear all outputs and reset execution counter\">\n <wa-icon name=\"eraser\" label=\"Clear\"></wa-icon>\n Clear Outputs\n </wa-button>\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.restartKernel()}\n title=\"Restart Python kernel (clears all variables and state)\"\n ?disabled=${!this.pyConnected || this.pyConnecting}>\n <wa-icon name=\"arrows-rotate\" label=\"Restart\"></wa-icon>\n Restart Kernel\n </wa-button>\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.openPackageManager()}\n title=\"Manage required packages for this notebook\">\n <wa-icon name=\"box\" label=\"Packages\"></wa-icon>\n Packages\n </wa-button>\n `;\n }\n\n protected doInitUI() {\n this.setupThemeObserver();\n }\n\n private async loadNotebook() {\n const file: File = this.input!.data;\n const contents = await file.getContents();\n\n try {\n this.notebook = JSON.parse(contents as string);\n } catch (e) {\n console.error(\"Failed to parse notebook:\", e);\n this.notebook = {\n cells: [{\n cell_type: 'markdown',\n source: ['# Error\\nFailed to parse notebook file.']\n }]\n };\n }\n\n // Initialize execution counter from existing cells\n if (this.notebook?.cells) {\n const maxCount = this.notebook.cells\n .filter(cell => cell.cell_type === 'code')\n .map(cell => cell.execution_count ?? 0)\n .reduce((max, count) => Math.max(max, count), 0);\n this.executionCounter = maxCount;\n\n this.notebook.cells.forEach((cell, index) => {\n if (cell.cell_type === 'code' && cell.outputs && cell.outputs.length > 0) {\n const output = this.convertOutputFromJupyter(cell.outputs[0]);\n if (output) {\n this.cellOutputs.set(index, output);\n }\n }\n });\n }\n }\n\n private setupThemeObserver() {\n const rootElement = document.documentElement;\n let currentTheme = this.getMonacoTheme();\n\n this.themeObserver = new MutationObserver(() => {\n const newTheme = this.getMonacoTheme();\n // Only update if theme actually changed\n if (newTheme !== currentTheme) {\n currentTheme = newTheme;\n monaco.editor.setTheme(newTheme);\n }\n });\n\n this.themeObserver.observe(rootElement, {\n attributes: true,\n attributeFilter: ['class']\n });\n }\n\n private getCellSource(cell: NotebookCell): string {\n return Array.isArray(cell.source) ? cell.source.join('') : cell.source;\n }\n\n private convertOutputToJupyter(output: any, executionCount: number | null | undefined): any[] {\n if (output.type === 'execute_result') {\n const data: any = {};\n if (output.imageData) data['image/png'] = output.imageData;\n if (output.data) data['text/plain'] = output.data;\n return [{\n output_type: 'execute_result',\n data,\n execution_count: executionCount,\n metadata: {}\n }];\n } else if (output.type === 'error') {\n return [{\n output_type: 'error',\n ename: 'Error',\n evalue: output.data,\n traceback: [output.data]\n }];\n }\n return [];\n }\n\n private convertOutputFromJupyter(jupyterOutput: any): any | null {\n if (jupyterOutput.output_type === 'execute_result' && jupyterOutput.data) {\n return {\n type: 'execute_result',\n data: jupyterOutput.data['text/plain'] || '',\n imageData: jupyterOutput.data['image/png'] || undefined\n };\n } else if (jupyterOutput.output_type === 'error') {\n return {\n type: 'error',\n data: jupyterOutput.evalue || jupyterOutput.traceback?.join('\\n') || 'Unknown error'\n };\n }\n return null;\n }\n\n private renderHeaderActions(index: number, additionalButton?: any) {\n return html`\n <div class=\"cell-header-actions\">\n ${additionalButton || ''}\n ${additionalButton ? html`<span class=\"divider\"></span>` : ''}\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.addCell(index, 'code')} title=\"Add code cell before\">\n <wa-icon name=\"plus\"></wa-icon>\n <wa-icon name=\"code\" label=\"Code\"></wa-icon>\n </wa-button>\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.addCell(index, 'markdown')} title=\"Add markdown cell before\">\n <wa-icon name=\"plus\"></wa-icon>\n <wa-icon name=\"font\" label=\"Markdown\"></wa-icon>\n </wa-button>\n <span class=\"divider\"></span>\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.deleteCell(index)} title=\"Delete cell\" ?disabled=${this.notebook!.cells.length <= 1}>\n <wa-icon name=\"trash\" label=\"Delete cell\"></wa-icon>\n </wa-button>\n </div>\n `;\n }\n\n private renderFooterActions(index: number) {\n return html`\n <div class=\"cell-footer\">\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.addCell(index + 1, 'code')} title=\"Add code cell after\">\n <wa-icon name=\"code\" label=\"Code\"></wa-icon>\n <wa-icon name=\"plus\"></wa-icon>\n </wa-button>\n <wa-button size=\"small\" appearance=\"plain\" @click=${() => this.addCell(index + 1, 'markdown')} title=\"Add markdown cell after\">\n <wa-icon name=\"font\" label=\"Markdown\"></wa-icon>\n <wa-icon name=\"plus\"></wa-icon>\n </wa-button>\n </div>\n `;\n }\n\n // Helper to convert string to Jupyter source format\n private stringToSourceArray(content: string): string[] {\n if (!content) return [''];\n const lines = content.split('\\n').map(line => line + '\\n');\n // Remove trailing newline from last line\n if (lines.length > 0) {\n lines[lines.length - 1] = lines[lines.length - 1].replace(/\\n$/, '');\n }\n return lines;\n }\n\n // Helper to create a new cell\n private createCell(cellType: 'code' | 'markdown'): NotebookCell {\n const newCell: NotebookCell = {\n cell_type: cellType,\n source: [''],\n metadata: {}\n };\n\n if (cellType === 'code') {\n newCell.execution_count = null;\n newCell.outputs = [];\n }\n\n return newCell;\n }\n\n private async initPyodide() {\n if (!this.pyenv) {\n this.pyenv = new PyEnv();\n const workspace = await workspaceService.getWorkspace();\n if (workspace) {\n await this.pyenv.init(workspace);\n this.pyConnected = true;\n\n // Get Python version using sys.version\n try {\n const response = await this.pyenv.execCode('import sys; sys.version.split()[0]');\n this.pyVersion = response?.result || 'Unknown';\n } catch (error) {\n console.error(\"Failed to get Python version:\", error);\n this.pyVersion = 'Unknown';\n }\n\n // Load required packages from notebook metadata\n const requiredPackages = this.notebook?.metadata?.required_packages || [];\n if (requiredPackages.length > 0) {\n try {\n await this.pyenv.loadPackages(requiredPackages);\n } catch (error) {\n console.error(\"Failed to load required packages:\", error);\n }\n }\n\n // Set up matplotlib backend and patch plt.show() if matplotlib is installed\n try {\n await this.pyenv.execCode(`\ntry:\n import matplotlib\n matplotlib.use('agg')\n \n import matplotlib.pyplot as plt\n import io\n import base64\n \n _original_show = plt.show\n _display_data = None\n \n def _patched_show(*args, **kwargs):\n \"\"\"Patched plt.show() that captures the current figure for notebook display.\"\"\"\n global _display_data\n if plt.get_fignums():\n fig = plt.gcf()\n buffer = io.BytesIO()\n fig.savefig(buffer, format='png', bbox_inches='tight', dpi=100)\n buffer.seek(0)\n _display_data = base64.b64encode(buffer.read()).decode('utf-8')\n plt.close(fig)\n # Don't call original show() as it would try to display in a window\n \n plt.show = _patched_show\nexcept ImportError:\n # matplotlib not installed - skip configuration\n pass\n`);\n } catch (error) {\n console.error(\"Failed to configure matplotlib:\", error);\n }\n }\n }\n }\n\n public async executeCell(cellIndex: number) {\n const cell = this.notebook!.cells[cellIndex];\n if (cell.cell_type !== 'code') return;\n\n this.executingCells.add(cellIndex);\n this.requestUpdate();\n\n try {\n await this.initPyodide();\n\n // Get code from Monaco editor if available, otherwise from cell source\n const editor = this.monacoEditors.get(cellIndex);\n let code = editor ? editor.getValue() : this.getCellSource(cell);\n\n // PyEnv now runs in a worker and returns { result, console }\n const response = await this.pyenv!.execCode(code);\n\n // Build output from console output and result\n const outputParts: string[] = [];\n\n // Add console output (stdout/stderr) if present\n if (response && typeof response === 'object' && 'console' in response) {\n const consoleOutput = response.console;\n if (Array.isArray(consoleOutput) && consoleOutput.length > 0) {\n const filteredOutput = consoleOutput.filter(s => s && s.trim());\n if (filteredOutput.length > 0) {\n outputParts.push(...filteredOutput);\n }\n }\n }\n\n // Check if plt.show() was called (which stores data in _display_data)\n let imageData: string | undefined = undefined;\n try {\n const checkDisplayData = await this.pyenv!.execCode('_display_data if \"_display_data\" in dir() else None');\n const displayResult = checkDisplayData && typeof checkDisplayData === 'object' ? \n checkDisplayData.result : checkDisplayData;\n \n if (displayResult && String(displayResult) !== 'None' && String(displayResult) !== 'undefined') {\n imageData = String(displayResult);\n // Clear the display data for next execution\n await this.pyenv!.execCode('_display_data = None');\n }\n } catch (e) {\n // No display data, which is fine\n console.debug('No display data to retrieve:', e);\n }\n\n // Add the return value if it exists, but only if we didn't capture a matplotlib figure\n // (matplotlib functions return objects like Text, Line2D etc that aren't useful to display)\n if (!imageData) {\n const result = response && typeof response === 'object' ? response.result : response;\n if (result !== undefined && result !== null && String(result) !== 'undefined') {\n const resultStr = String(result);\n if (resultStr && resultStr !== 'undefined') {\n outputParts.push(resultStr);\n }\n }\n }\n\n this.cellOutputs.set(cellIndex, {\n type: 'execute_result',\n data: outputParts.length > 0 ? outputParts.join('\\n') : undefined,\n imageData: imageData\n });\n\n // Update execution count\n this.executionCounter++;\n cell.execution_count = this.executionCounter;\n this.markDirty(true);\n\n } catch (error) {\n // Check if execution is still marked as running (not cancelled)\n if (this.executingCells.has(cellIndex)) {\n this.cellOutputs.set(cellIndex, {\n type: 'error',\n data: String(error)\n });\n }\n } finally {\n this.executingCells.delete(cellIndex);\n this.requestUpdate();\n }\n }\n\n private async cancelExecution(cellIndex: number) {\n if (!this.pyenv) return;\n\n // Check if graceful interrupt is available (requires SharedArrayBuffer)\n if (this.pyenv.canInterrupt()) {\n // Use interrupt buffer - Python will raise KeyboardInterrupt\n this.pyenv.interrupt();\n // The KeyboardInterrupt will be caught in executeCell's catch block\n } else {\n // SharedArrayBuffer not available - must terminate worker\n this.cellOutputs.set(cellIndex, {\n type: 'error',\n data: 'Execution cancelled by user (worker terminated - SharedArrayBuffer not available for graceful interrupt)'\n });\n\n this.executingCells.delete(cellIndex);\n\n // Terminate and reinitialize\n this.pyenv.close();\n this.pyenv = undefined;\n this.pyConnected = false;\n this.pyVersion = undefined;\n\n // Reinitialize for future executions\n try {\n await this.initPyodide();\n } catch (error) {\n console.error(\"Failed to reinitialize Python after cancellation:\", error);\n }\n\n this.requestUpdate();\n }\n }\n\n private clearAllOutputs() {\n // Clear all outputs\n this.cellOutputs.clear();\n\n // Reset execution counter\n this.executionCounter = 0;\n\n // Reset execution counts on all code cells\n if (this.notebook?.cells) {\n this.notebook.cells.forEach(cell => {\n if (cell.cell_type === 'code') {\n cell.execution_count = null;\n cell.outputs = [];\n }\n });\n }\n\n // Mark as dirty since we've modified the notebook\n this.markDirty(true);\n\n // Force re-render\n this.requestUpdate();\n }\n\n private async restartKernel() {\n if (!this.pyenv || this.pyConnecting) return;\n\n try {\n this.pyConnecting = true;\n \n // Close current environment\n this.pyenv.close();\n this.pyenv = undefined;\n this.pyConnected = false;\n this.pyVersion = undefined;\n\n // Force re-render to show reconnecting state\n this.requestUpdate();\n\n // Reinitialize\n await this.initPyodide();\n\n // Force re-render to show connected state\n this.requestUpdate();\n } catch (error) {\n console.error(\"Failed to restart kernel:\", error);\n } finally {\n this.pyConnecting = false;\n }\n }\n\n private async runAllCells() {\n if (!this.notebook?.cells) return;\n\n this.isRunningAll = true;\n this.cancelRunAll = false;\n this.requestUpdate();\n\n try {\n // Execute all code cells sequentially\n for (let i = 0; i < this.notebook.cells.length; i++) {\n // Check if cancellation was requested\n if (this.cancelRunAll) {\n break;\n }\n\n const cell = this.notebook.cells[i];\n if (cell.cell_type === 'code') {\n await this.executeCell(i);\n }\n }\n } finally {\n this.isRunningAll = false;\n this.cancelRunAll = false;\n this.requestUpdate();\n }\n }\n\n private cancelAllCells() {\n this.cancelRunAll = true;\n }\n\n private toggleMarkdownEdit(index: number) {\n if (this.editingMarkdownCells.has(index)) {\n this.editingMarkdownCells.delete(index);\n } else {\n this.editingMarkdownCells.add(index);\n }\n this.requestUpdate();\n }\n\n private saveMarkdownEdit(index: number, event: Event) {\n const textarea = event.target as HTMLTextAreaElement;\n const newContent = textarea.value;\n\n // Update the cell source\n if (this.notebook && this.notebook.cells[index]) {\n const cell = this.notebook.cells[index];\n const oldContent = this.getCellSource(cell);\n\n cell.source = this.stringToSourceArray(newContent);\n\n // Mark dirty if content changed\n if (oldContent !== newContent) {\n this.markDirty(true);\n }\n }\n\n this.editingMarkdownCells.delete(index);\n this.requestUpdate();\n }\n\n private renderMarkdownCell(cell: NotebookCell, index: number) {\n const source = this.getCellSource(cell);\n const isEmpty = !source || source.trim() === '';\n const isEditing = this.editingMarkdownCells.has(index);\n\n if (isEditing) {\n const editButtons = html`\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${(e: Event) => {\n const textarea = (e.target as HTMLElement).closest('.markdown-cell')?.querySelector('textarea');\n if (textarea) {\n this.saveMarkdownEdit(index, { target: textarea } as any);\n }\n }}\n title=\"Save changes\">\n <wa-icon name=\"check\" label=\"Save\"></wa-icon>\n </wa-button>\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.toggleMarkdownEdit(index)}\n title=\"Cancel editing\">\n <wa-icon name=\"xmark\" label=\"Cancel\"></wa-icon>\n </wa-button>\n `;\n \n return html`\n <div class=\"cell-wrapper\">\n <wa-animation \n name=\"bounce\" \n duration=\"1000\" \n iterations=\"1\"\n ?play=${this.highlightedCellIndex === index}\n @wa-finish=${() => this.highlightedCellIndex = -1}>\n <div class=\"cell markdown-cell editing\">\n <div class=\"cell-header\">\n ${this.renderHeaderActions(index, editButtons)}\n <span class=\"cell-label\">Markdown</span>\n </div>\n <textarea \n class=\"markdown-editor\"\n .value=${source}\n @blur=${(e: Event) => this.saveMarkdownEdit(index, e)}\n placeholder=\"Enter markdown content here... (# for headings, ** for bold, etc.)\"></textarea>\n ${this.renderFooterActions(index)}\n </div>\n </wa-animation>\n </div>\n `;\n }\n\n const rendered = marked.parse(source) as string;\n\n const editButton = html`\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.toggleMarkdownEdit(index)}\n title=\"Edit markdown\">\n <wa-icon name=\"pencil\" label=\"Edit\"></wa-icon>\n </wa-button>\n `;\n\n return html`\n <div class=\"cell-wrapper\">\n <wa-animation \n name=\"bounce\" \n duration=\"1000\" \n iterations=\"1\"\n ?play=${this.highlightedCellIndex === index}\n @wa-finish=${() => this.highlightedCellIndex = -1}>\n <div class=\"cell markdown-cell ${isEmpty ? 'empty' : ''}\" @dblclick=${() => this.toggleMarkdownEdit(index)}>\n <div class=\"cell-header\">\n ${this.renderHeaderActions(index, editButton)}\n <span class=\"cell-label\"></span>\n </div>\n <div class=\"cell-content\">\n ${isEmpty ? html`\n <div class=\"markdown-placeholder\">\n <wa-icon name=\"font\" label=\"Markdown\"></wa-icon>\n <span>Double-click or click the pencil icon to edit markdown</span>\n </div>\n ` : unsafeHTML(rendered)}\n </div>\n ${this.renderFooterActions(index)}\n </div>\n </wa-animation>\n </div>\n `;\n }\n\n private renderCodeCell(cell: NotebookCell, index: number) {\n const output = this.cellOutputs.get(index);\n const isExecuting = this.executingCells.has(index);\n\n // Create or get ref for this cell\n if (!this.cellRefs.has(index)) {\n this.cellRefs.set(index, createRef());\n }\n const cellRef = this.cellRefs.get(index)!;\n\n const runButton = isExecuting ? html`\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.cancelExecution(index)}\n title=\"Stop execution\">\n <wa-icon name=\"stop\" label=\"Stop\" style=\"color: var(--wa-color-danger-500);\"></wa-icon>\n </wa-button>\n ` : html`\n <lyra-command \n cmd=\"python\"\n icon=\"play\"\n title=\"Run cell\"\n size=\"small\"\n appearance=\"plain\"\n .params=${{ cellIndex: index }}>\n </lyra-command>\n `;\n\n return html`\n <div class=\"cell-wrapper\">\n <wa-animation \n name=\"bounce\" \n duration=\"1000\" \n iterations=\"1\"\n ?play=${this.highlightedCellIndex === index}\n @wa-finish=${() => this.highlightedCellIndex = -1}>\n <div class=\"cell code-cell ${isExecuting ? 'executing' : ''}\">\n <div class=\"cell-header\">\n <span class=\"cell-label\">\n ${isExecuting ? html`\n In [<wa-animation name=\"pulse\" duration=\"1000\" iterations=\"Infinity\" ?play=${isExecuting}>\n <span class=\"executing-indicator\">*</span>\n </wa-animation>]\n ` : html`\n In [${cell.execution_count ?? ' '}]\n `}\n </span>\n ${this.renderHeaderActions(index, runButton)}\n </div>\n <div class=\"cell-input monaco-container\" ${ref(cellRef)} data-cell-index=\"${index}\"></div>\n ${output ? html`\n <div class=\"cell-output ${output.type === 'error' ? 'output-error' : ''}\">\n <div class=\"output-label\">Out [${index + 1}]:</div>\n ${output.imageData ? html`\n <img src=\"data:image/png;base64,${output.imageData}\" alt=\"Output image\" class=\"output-image\" />\n ` : ''}\n ${output.data ? html`<pre><code>${output.data}</code></pre>` : ''}\n </div>\n ` : ''}\n ${this.renderFooterActions(index)}\n </div>\n </wa-animation>\n </div>\n `;\n }\n\n private renderCell(cell: NotebookCell, index: number) {\n if (cell.cell_type === 'markdown') {\n return this.renderMarkdownCell(cell, index);\n } else if (cell.cell_type === 'code') {\n return this.renderCodeCell(cell, index);\n } else {\n // raw cell\n const source = this.getCellSource(cell);\n return html`\n <div class=\"cell raw-cell\">\n <pre><code>${source}</code></pre>\n </div>\n `;\n }\n }\n\n private async connectPython() {\n if (this.pyConnecting || this.pyConnected) {\n return;\n }\n \n try {\n this.pyConnecting = true;\n await this.initPyodide();\n } catch (error) {\n console.error(\"Failed to initialize Pyodide:\", error);\n } finally {\n this.pyConnecting = false;\n }\n }\n\n\n private addCell(index: number, cellType: 'code' | 'markdown' = 'code') {\n if (!this.notebook) return;\n\n // Save editor contents BEFORE modifying the cells array\n this.saveEditorContents();\n \n this.shiftIndices(index, 'up');\n \n this.notebook.cells.splice(index, 0, this.createCell(cellType));\n \n // Automatically enter edit mode for new markdown cells\n if (cellType === 'markdown') {\n this.editingMarkdownCells.add(index);\n }\n \n this.resetCellState();\n \n // Trigger animation and scroll to the new cell\n this.highlightedCellIndex = index;\n this.updateComplete.then(() => {\n this.scrollToCell(index);\n });\n }\n\n private scrollToCell(index: number) {\n // Find the cell wrapper element\n const cellWrapper = this.shadowRoot?.querySelectorAll('.cell-wrapper')[index];\n if (!cellWrapper) return;\n\n // Find the wa-scroller container (parent of this component)\n const scroller = this.closest('wa-scroller');\n if (!scroller) {\n // Fallback to default scrollIntoView if no scroller found\n cellWrapper.scrollIntoView({ \n behavior: 'smooth', \n block: 'center',\n inline: 'nearest'\n });\n return;\n }\n\n // Manually scroll the wa-scroller to the cell position\n const scrollerRect = scroller.getBoundingClientRect();\n const cellRect = cellWrapper.getBoundingClientRect();\n const scrollTop = scroller.scrollTop;\n \n // Calculate target scroll position (center the cell)\n const targetScroll = scrollTop + (cellRect.top - scrollerRect.top) - (scrollerRect.height / 2) + (cellRect.height / 2);\n \n scroller.scrollTo({\n top: targetScroll,\n behavior: 'smooth'\n });\n }\n\n private saveEditorContents() {\n // Update cell contents from Monaco editors\n this.monacoEditors.forEach((editor, index) => {\n const cell = this.notebook!.cells[index];\n if (cell && cell.cell_type === 'code') {\n cell.source = this.stringToSourceArray(editor.getValue());\n }\n });\n }\n\n private resetCellState() {\n // Clear Monaco editors and refs since indices have changed\n this.monacoEditors.forEach(editor => editor.dispose());\n this.monacoEditors.clear();\n this.cellRefs.clear();\n this.markDirty(true);\n }\n\n private deleteCell(index: number) {\n if (!this.notebook || this.notebook.cells.length <= 1) return;\n\n // Save editor contents BEFORE modifying the cells array\n this.saveEditorContents();\n \n // Remove state for the deleted cell\n this.cellOutputs.delete(index);\n this.executingCells.delete(index);\n this.editingMarkdownCells.delete(index);\n \n this.notebook.cells.splice(index, 1);\n \n this.shiftIndices(index, 'down');\n \n this.resetCellState();\n }\n\n private shiftIndices(startIndex: number, direction: 'up' | 'down') {\n const shift = direction === 'up' ? 1 : -1;\n const filterFn = direction === 'up' \n ? (idx: number) => idx >= startIndex\n : (idx: number) => idx > startIndex;\n const sortFn = direction === 'up'\n ? (a: number, b: number) => b - a\n : (a: number, b: number) => a - b;\n\n const shiftMap = <T>(map: Map<number, T>) => {\n const indices = Array.from(map.keys()).filter(filterFn).sort(sortFn);\n indices.forEach(oldIndex => {\n const value = map.get(oldIndex);\n map.delete(oldIndex);\n map.set(oldIndex + shift, value!);\n });\n };\n\n const shiftSet = (set: Set<number>) => {\n const indices = Array.from(set).filter(filterFn).sort(sortFn);\n indices.forEach(oldIndex => {\n set.delete(oldIndex);\n set.add(oldIndex + shift);\n });\n };\n\n shiftMap(this.cellOutputs);\n shiftSet(this.executingCells);\n shiftSet(this.editingMarkdownCells);\n }\n\n private initializeMonacoEditor(container: HTMLElement, cell: NotebookCell, index: number) {\n const source = this.getCellSource(cell);\n const lineCount = source.split('\\n').length;\n const lineHeight = 19;\n const padding = 10;\n const minHeight = 100;\n const calculatedHeight = Math.max(minHeight, lineCount * lineHeight + padding);\n\n container.style.height = `${calculatedHeight}px`;\n\n const editor = monaco.editor.create(container, {\n value: source,\n language: 'python',\n theme: this.getMonacoTheme(),\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n lineNumbers: 'on',\n renderLineHighlight: 'all',\n automaticLayout: true,\n fontSize: 14,\n tabSize: 4,\n wordWrap: 'on',\n });\n\n let isEditorFocused = false;\n editor.onDidFocusEditorText(() => { \n isEditorFocused = true;\n this.focusedCellIndex = index;\n });\n editor.onDidBlurEditorText(() => { \n isEditorFocused = false;\n if (this.focusedCellIndex === index) {\n this.focusedCellIndex = -1;\n }\n });\n\n container.addEventListener('wheel', (e: WheelEvent) => {\n if (!isEditorFocused) {\n const scrollTop = editor.getScrollTop();\n const scrollHeight = editor.getScrollHeight();\n const contentHeight = editor.getContentHeight();\n const canScroll = scrollHeight > contentHeight;\n const atBoundary = (e.deltaY < 0 && scrollTop <= 0) || \n (e.deltaY > 0 && scrollTop + contentHeight >= scrollHeight);\n\n if (!canScroll || atBoundary) {\n e.stopImmediatePropagation();\n }\n }\n }, { passive: true, capture: true });\n\n editor.onDidContentSizeChange(() => {\n const contentHeight = editor.getContentHeight();\n container.style.height = `${Math.max(minHeight, contentHeight + padding)}px`;\n editor.layout();\n });\n\n editor.onDidChangeModelContent(() => {\n const currentValue = editor.getValue();\n const originalValue = this.getCellSource(cell);\n if (currentValue !== originalValue) {\n this.markDirty(true);\n }\n });\n\n this.monacoEditors.set(index, editor);\n }\n\n private getMonacoTheme(): string {\n const rootElement = document.documentElement;\n if (rootElement.classList.contains('wa-dark')) {\n return 'vs-dark';\n } else if (rootElement.classList.contains('wa-light')) {\n return 'vs';\n }\n return 'vs-dark';\n }\n\n private openPackageManager() {\n const packages = this.notebook?.metadata?.required_packages || [];\n \n pythonPackageManagerService.showPackageManager({\n packages,\n pyenv: this.pyenv,\n onPackageAdded: (packageName: string) => {\n if (!this.notebook) return;\n if (!this.notebook.metadata) {\n this.notebook.metadata = {};\n }\n if (!this.notebook.metadata.required_packages) {\n this.notebook.metadata.required_packages = [];\n }\n \n if (!this.notebook.metadata.required_packages.includes(packageName)) {\n this.notebook.metadata.required_packages.push(packageName);\n this.markDirty(true);\n }\n },\n onPackageRemoved: (packageName: string) => {\n if (!this.notebook?.metadata?.required_packages) return;\n \n const index = this.notebook.metadata.required_packages.indexOf(packageName);\n if (index > -1) {\n this.notebook.metadata.required_packages.splice(index, 1);\n this.markDirty(true);\n }\n }\n });\n }\n\n protected updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n\n // Update toolbar when state affecting toolbar changes\n if (changedProperties.has('pyConnected') || \n changedProperties.has('pyConnecting') ||\n changedProperties.has('pyVersion') ||\n changedProperties.has('isRunningAll')) {\n this.updateToolbar();\n }\n\n if (this.notebook?.cells) {\n this.notebook.cells.forEach((cell, index) => {\n if (cell.cell_type === 'code') {\n const ref = this.cellRefs.get(index);\n if (ref?.value && !this.monacoEditors.has(index)) {\n this.initializeMonacoEditor(ref.value, cell, index);\n }\n }\n });\n }\n }\n\n protected render() {\n if (!this.notebook) {\n return html`<div class=\"loading\">Loading notebook...</div>`;\n }\n\n return html`\n <style>\n ${monacoStyles}\n </style>\n <div class=\"noteboocells\">\n ${repeat(\n this.notebook.cells,\n (_cell, index) => index,\n (cell, index) => this.renderCell(cell, index)\n )}\n </div>\n `;\n }\n\n static styles = css`\n :host {\n display: block;\n width: 100%;\n }\n\n .python-status {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .python-version {\n font-size: 0.9rem;\n opacity: 0.8;\n }\n\n .noteboocells {\n display: flex;\n flex-direction: column;\n gap: 3rem;\n max-width: 1200px;\n margin: 0 auto;\n padding: 2rem 1rem;\n width: 100%;\n box-sizing: border-box;\n }\n\n .cell-wrapper {\n position: relative;\n }\n\n .cell {\n border-radius: 4px;\n overflow: hidden;\n opacity: 0.9;\n position: relative;\n }\n\n .cell-header-actions {\n display: flex;\n gap: 0.25rem;\n align-items: center;\n opacity: 0.5;\n transition: opacity 0.2s;\n }\n\n .cell-header-actions .divider {\n width: 1px;\n height: 1rem;\n background: var(--wa-color-outline);\n margin: 0 0.25rem;\n opacity: 0.5;\n }\n\n .cell-header:hover .cell-header-actions {\n opacity: 1;\n }\n\n .cell-footer {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n justify-content: flex-start;\n padding: 0.5rem;\n border-top: 1px solid var(--wa-color-outline);\n opacity: 0.5;\n transition: opacity 0.2s;\n }\n\n .cell-footer:hover {\n opacity: 1;\n }\n\n .markdown-cell {\n cursor: pointer;\n transition: opacity 0.2s;\n }\n\n .markdown-cell:hover:not(.editing) {\n opacity: 0.9;\n }\n \n .markdown-cell .cell-content {\n padding: 1rem;\n }\n\n .markdown-cell.editing {\n cursor: default;\n padding: 0;\n }\n \n .markdown-cell.editing .cell-actions {\n display: none;\n }\n\n .markdown-editor {\n width: 100%;\n min-height: 200px;\n padding: 1rem;\n font-family: monospace;\n font-size: 0.95rem;\n line-height: 1.6;\n border: none;\n outline: none;\n resize: vertical;\n background: transparent;\n color: inherit;\n }\n\n .code-cell {\n border-left: 3px solid var(--wa-color-primary-500);\n transition: all 0.3s ease;\n }\n \n .code-cell.executing {\n border-left: 4px solid var(--wa-color-primary-500);\n box-shadow: 0 0 0 2px var(--wa-color-primary-500, rgba(59, 130, 246, 0.3));\n animation: pulse-cell 2s ease-in-out infinite;\n }\n \n @keyframes pulse-cell {\n 0%, 100% {\n box-shadow: 0 0 0 2px var(--wa-color-primary-500, rgba(59, 130, 246, 0.3));\n opacity: 1;\n }\n 50% {\n box-shadow: 0 0 0 4px var(--wa-color-primary-500, rgba(59, 130, 246, 0.5));\n opacity: 0.95;\n }\n }\n\n .cell-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n flex-wrap: nowrap;\n }\n\n .cell-label {\n font-family: monospace;\n font-weight: bold;\n flex-shrink: 0;\n }\n \n .executing-indicator {\n display: inline-block;\n color: var(--wa-color-primary-500);\n font-weight: bold;\n font-size: 1.2em;\n }\n\n .cell-input {\n margin: 0;\n }\n\n .monaco-container {\n min-height: 100px;\n height: auto;\n width: 100%;\n }\n\n .cell-output {\n padding: 1rem;\n }\n\n .output-label {\n font-family: monospace;\n font-weight: bold;\n margin-bottom: 0.5rem;\n opacity: 0.7;\n }\n\n .cell-output pre {\n margin: 0;\n overflow-x: auto;\n }\n\n .cell-output code {\n font-family: 'Courier New', monospace;\n font-size: 0.9rem;\n line-height: 1.5;\n }\n\n .output-image {\n max-width: 100%;\n height: auto;\n display: block;\n margin: 0.5rem 0;\n border-radius: 4px;\n }\n\n .output-error {\n border-left: 3px solid var(--wa-color-danger-500);\n }\n\n .raw-cell {\n padding: 1rem;\n }\n\n .raw-cell pre {\n margin: 0;\n }\n\n .loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n font-size: 1.2rem;\n }\n\n .markdown-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 3rem 1rem;\n opacity: 0.5;\n font-style: italic;\n transition: opacity 0.2s;\n }\n\n .markdown-cell.empty:hover .markdown-placeholder {\n opacity: 0.8;\n }\n\n .markdown-placeholder wa-icon {\n font-size: 1.5rem;\n }\n `;\n}\n"],"names":["ref"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { EditorInput, LyraPart } from '@eclipse-lyra/core';
2
+ import { NotebookData, NotebookEditorLike } from './notebook-types';
3
+ export declare class LyraNotebookEditor extends LyraPart implements NotebookEditorLike {
4
+ input?: EditorInput;
5
+ notebook?: NotebookData;
6
+ private cellOutputs;
7
+ private executingCells;
8
+ private pyenv?;
9
+ private pyConnected;
10
+ private pyConnecting;
11
+ private pyVersion?;
12
+ private editingMarkdownCells;
13
+ private executionCounter;
14
+ private isRunningAll;
15
+ private highlightedCellIndex;
16
+ focusedCellIndex: number;
17
+ private cancelRunAll;
18
+ private monacoEditors;
19
+ private cellRefs;
20
+ private themeObserver?;
21
+ protected doClose(): void;
22
+ save(): Promise<void>;
23
+ protected doBeforeUI(): void;
24
+ protected renderToolbar(): import('lit-html').TemplateResult<1>;
25
+ protected doInitUI(): void;
26
+ private loadNotebook;
27
+ private setupThemeObserver;
28
+ private getCellSource;
29
+ private convertOutputToJupyter;
30
+ private convertOutputFromJupyter;
31
+ private renderHeaderActions;
32
+ private renderFooterActions;
33
+ private stringToSourceArray;
34
+ private createCell;
35
+ private initPyodide;
36
+ executeCell(cellIndex: number): Promise<void>;
37
+ private cancelExecution;
38
+ private clearAllOutputs;
39
+ private restartKernel;
40
+ private runAllCells;
41
+ private cancelAllCells;
42
+ private toggleMarkdownEdit;
43
+ private saveMarkdownEdit;
44
+ private renderMarkdownCell;
45
+ private renderCodeCell;
46
+ private renderCell;
47
+ private connectPython;
48
+ private addCell;
49
+ private scrollToCell;
50
+ private saveEditorContents;
51
+ private resetCellState;
52
+ private deleteCell;
53
+ private shiftIndices;
54
+ private initializeMonacoEditor;
55
+ private getMonacoTheme;
56
+ private openPackageManager;
57
+ protected updated(changedProperties: Map<string, any>): void;
58
+ protected render(): import('lit-html').TemplateResult<1>;
59
+ static styles: import('lit').CSSResult;
60
+ }
61
+ //# sourceMappingURL=notebook-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-runtime.d.ts","sourceRoot":"","sources":["../src/notebook-runtime.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAgB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEvF,qBACa,kBAAmB,SAAQ,QAAS,YAAW,kBAAkB;IAEnE,KAAK,CAAC,EAAE,WAAW,CAAC;IAGpB,QAAQ,CAAC,EAAE,YAAY,CAAC;IAG/B,OAAO,CAAC,WAAW,CAA+B;IAGlD,OAAO,CAAC,cAAc,CAA0B;IAGhD,OAAO,CAAC,KAAK,CAAC,CAAQ;IAGtB,OAAO,CAAC,WAAW,CAAkB;IAGrC,OAAO,CAAC,YAAY,CAAkB;IAGtC,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,oBAAoB,CAA0B;IAGtD,OAAO,CAAC,gBAAgB,CAAa;IAGrC,OAAO,CAAC,YAAY,CAAkB;IAGtC,OAAO,CAAC,oBAAoB,CAAc;IAEnC,gBAAgB,EAAE,MAAM,CAAM;IACrC,OAAO,CAAC,YAAY,CAAkB;IAEtC,OAAO,CAAC,aAAa,CAA+D;IACpF,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEzC,SAAS,CAAC,OAAO;IA0BX,IAAI;IA6BV,SAAS,CAAC,UAAU;IAKpB,SAAS,CAAC,aAAa;IA2EvB,SAAS,CAAC,QAAQ;YAIJ,YAAY;IAmC1B,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,UAAU;YAeJ,WAAW;IAiEZ,WAAW,CAAC,SAAS,EAAE,MAAM;YAqF5B,eAAe;IAkC7B,OAAO,CAAC,eAAe;YAwBT,aAAa;YA2Bb,WAAW;IA2BzB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,kBAAkB;IA6F1B,OAAO,CAAC,cAAc;IAmEtB,OAAO,CAAC,UAAU;YAgBJ,aAAa;IAgB3B,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,YAAY;IA+BpB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,YAAY;IA+BpB,OAAO,CAAC,sBAAsB;IAoE9B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,kBAAkB;IAgC1B,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;IAuBrD,SAAS,CAAC,MAAM;IAmBhB,MAAM,CAAC,MAAM,0BAwOX;CACL"}
@@ -0,0 +1,23 @@
1
+ export interface NotebookCell {
2
+ cell_type: 'code' | 'markdown' | 'raw';
3
+ source: string | string[];
4
+ outputs?: any[];
5
+ execution_count?: number | null;
6
+ metadata?: any;
7
+ }
8
+ export interface NotebookData {
9
+ cells: NotebookCell[];
10
+ metadata?: {
11
+ required_packages?: string[];
12
+ [key: string]: any;
13
+ };
14
+ nbformat?: number;
15
+ nbformat_minor?: number;
16
+ }
17
+ export interface NotebookEditorLike {
18
+ notebook?: NotebookData;
19
+ focusedCellIndex: number;
20
+ executeCell(index: number): Promise<void>;
21
+ }
22
+ export declare function isNotebookEditorLike(value: unknown): value is NotebookEditorLike;
23
+ //# sourceMappingURL=notebook-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notebook-types.d.ts","sourceRoot":"","sources":["../src/notebook-types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC;IACvC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,GAAG,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE;QACP,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAMhF"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@eclipse-lyra/extension-notebook",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ }
11
+ },
12
+ "dependencies": {
13
+ "@eclipse-lyra/core": "*",
14
+ "@eclipse-lyra/extension-python-runtime": "*",
15
+ "marked": "^12.0.0 || ^16.4.1",
16
+ "monaco-editor": "0.55.1"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.9.3",
20
+ "vite": "^7.1.12",
21
+ "vite-plugin-dts": "^4.5.4"
22
+ },
23
+ "module": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "scripts": {
29
+ "build": "vite build"
30
+ }
31
+ }