flexdesk 0.1.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.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/THIRD_PARTY_LICENSES.md +53 -0
  4. package/css/base.css +3439 -0
  5. package/css/flexdesk.css +5797 -0
  6. package/css/overrides.css +2349 -0
  7. package/css/reset.css +46 -0
  8. package/css/tokens.css +137 -0
  9. package/dist/charts.js +780 -0
  10. package/dist/charts.js.map +7 -0
  11. package/dist/chunk-3PHCPZHT.js +222 -0
  12. package/dist/chunk-3PHCPZHT.js.map +7 -0
  13. package/dist/chunk-CT4YXXLP.js +1770 -0
  14. package/dist/chunk-CT4YXXLP.js.map +7 -0
  15. package/dist/chunk-DRYCDMEG.js +2217 -0
  16. package/dist/chunk-DRYCDMEG.js.map +7 -0
  17. package/dist/chunk-DVU44T77.js +855 -0
  18. package/dist/chunk-DVU44T77.js.map +7 -0
  19. package/dist/chunk-FL5KFNQH.js +640 -0
  20. package/dist/chunk-FL5KFNQH.js.map +7 -0
  21. package/dist/chunk-FOOS3T5L.js +117 -0
  22. package/dist/chunk-FOOS3T5L.js.map +7 -0
  23. package/dist/chunk-JYWURG5T.js +32 -0
  24. package/dist/chunk-JYWURG5T.js.map +7 -0
  25. package/dist/chunk-TLZUUFOE.js +276 -0
  26. package/dist/chunk-TLZUUFOE.js.map +7 -0
  27. package/dist/chunk-UCJ2WD4D.js +625 -0
  28. package/dist/chunk-UCJ2WD4D.js.map +7 -0
  29. package/dist/chunk-WVFGV5FT.js +205 -0
  30. package/dist/chunk-WVFGV5FT.js.map +7 -0
  31. package/dist/core.js +1098 -0
  32. package/dist/core.js.map +7 -0
  33. package/dist/editor.js +1661 -0
  34. package/dist/editor.js.map +7 -0
  35. package/dist/flexdesk.css +5797 -0
  36. package/dist/host.js +132 -0
  37. package/dist/host.js.map +7 -0
  38. package/dist/reset.css +46 -0
  39. package/dist/tile_registry-6WZPTUZV.js +28 -0
  40. package/dist/tile_registry-6WZPTUZV.js.map +7 -0
  41. package/dist/tiles.js +2068 -0
  42. package/dist/tiles.js.map +7 -0
  43. package/dist/tokens.css +137 -0
  44. package/dist/widgets.js +5438 -0
  45. package/dist/widgets.js.map +7 -0
  46. package/dist/wm.js +4830 -0
  47. package/dist/wm.js.map +7 -0
  48. package/package.json +80 -0
  49. package/src/charts/chart_types.js +699 -0
  50. package/src/charts/data_series_plot_window.js +761 -0
  51. package/src/charts/downsample.js +119 -0
  52. package/src/charts/plot_config.js +176 -0
  53. package/src/charts/plot_popout_window.js +1560 -0
  54. package/src/charts/plotly_wrapper.js +432 -0
  55. package/src/core/event_bus.js +230 -0
  56. package/src/core/logging.js +300 -0
  57. package/src/core/settings.js +813 -0
  58. package/src/core/state_guard.js +382 -0
  59. package/src/core/state_guard_config.js +309 -0
  60. package/src/core/state_machine.js +258 -0
  61. package/src/editor/editor_pane.js +264 -0
  62. package/src/editor/monaco_editor_factory.js +449 -0
  63. package/src/editor/monaco_loader.js +74 -0
  64. package/src/editor/notebook_search.js +460 -0
  65. package/src/editor/notebook_tab_bar.js +456 -0
  66. package/src/editor/notebook_undo_manager.js +108 -0
  67. package/src/editor/split_pane_container.js +197 -0
  68. package/src/help/help_modal.js +409 -0
  69. package/src/help/help_registry.js +65 -0
  70. package/src/host/host.js +69 -0
  71. package/src/host/pywebview_host.js +133 -0
  72. package/src/tiles/config_schema.js +256 -0
  73. package/src/tiles/layout_persistence.js +662 -0
  74. package/src/tiles/tile_base.js +785 -0
  75. package/src/tiles/tile_grid.js +905 -0
  76. package/src/tiles/tile_registry.js +136 -0
  77. package/src/tiling/command_palette.js +328 -0
  78. package/src/tiling/content_registry.js +110 -0
  79. package/src/tiling/desktops.js +133 -0
  80. package/src/tiling/entity_sources.js +179 -0
  81. package/src/tiling/keymap.js +156 -0
  82. package/src/tiling/kind_taxonomy.js +172 -0
  83. package/src/tiling/landing_table.js +717 -0
  84. package/src/tiling/loading_overlay.js +33 -0
  85. package/src/tiling/nav_panel.js +142 -0
  86. package/src/tiling/page_factory.js +215 -0
  87. package/src/tiling/panel_keys.js +145 -0
  88. package/src/tiling/shell.js +437 -0
  89. package/src/tiling/tile_breadcrumb.js +222 -0
  90. package/src/tiling/tile_renderer.js +459 -0
  91. package/src/tiling/tile_tab_menu.js +340 -0
  92. package/src/tiling/tile_tree.js +880 -0
  93. package/src/tiling/wm.js +1352 -0
  94. package/src/ui/base/component_base.js +30 -0
  95. package/src/ui/base/controller_base.js +48 -0
  96. package/src/ui/base/page_base.js +102 -0
  97. package/src/ui/components/about_dialog.js +224 -0
  98. package/src/ui/components/action_dropdown.js +389 -0
  99. package/src/ui/components/attribute_list_editor.js +652 -0
  100. package/src/ui/components/autocomplete_field.js +732 -0
  101. package/src/ui/components/computing_status_window.js +81 -0
  102. package/src/ui/components/confirm_dialog.js +307 -0
  103. package/src/ui/components/context_menu.js +87 -0
  104. package/src/ui/components/data_table.js +2228 -0
  105. package/src/ui/components/detail_header.js +177 -0
  106. package/src/ui/components/drag_reorder.js +0 -0
  107. package/src/ui/components/gallery_picker.js +147 -0
  108. package/src/ui/components/inline_renamer.js +129 -0
  109. package/src/ui/components/managed_window.js +804 -0
  110. package/src/ui/components/modal.js +512 -0
  111. package/src/ui/components/notification_history.js +264 -0
  112. package/src/ui/components/slide_out_panel.js +185 -0
  113. package/src/ui/components/slider_field.js +122 -0
  114. package/src/ui/components/sortable_list.js +309 -0
  115. package/src/ui/components/table_state_store.js +81 -0
  116. package/src/ui/components/toast.js +59 -0
  117. package/src/ui/components/tree_view.js +460 -0
  118. package/src/ui/components/window_taskbar.js +143 -0
  119. package/src/ui/controllers/panel_state_machine.js +634 -0
  120. package/src/ui/controllers/window_chrome_controller.js +659 -0
  121. package/src/ui/notification_center.js +576 -0
  122. package/src/ui/utils/overlay_scrollbar.js +492 -0
  123. package/src/ui/utils/raf_resize_observer.js +31 -0
  124. package/src/ui/utils/tooltip_service.js +406 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/editor/notebook_tab_bar.js", "../src/editor/editor_pane.js", "../src/editor/monaco_loader.js", "../src/editor/monaco_editor_factory.js", "../src/editor/notebook_search.js", "../src/editor/notebook_undo_manager.js", "../src/editor/split_pane_container.js"],
4
+ "sourcesContent": ["/**\n * NotebookTabBar \u2014 tab strip showing open files, with dirty indicators,\n * close buttons, drag-and-drop reordering, double-click rename, and\n * right-click context menu.\n *\n * Uses the same `.tab` / `.tab-title` / `.tab-dirty` / `.tab-close` DOM structure\n * as the flow-page tab bar, so all editor tab bars share a unified appearance.\n *\n * Calls back into parent via:\n * onActivate(filePath)\n * onClose(filePath)\n * onCloseOthers(filePath)\n * onCloseToRight(filePath)\n * onCloseAll()\n * onCloseSaved()\n * onRename(oldPath, newPath)\n * onDuplicate(filePath)\n * onReorder(orderedPaths)\n * onRevealInExplorer(filePath)\n * onSplitRight(filePath)\n * onMoveToOtherPane(filePath)\n * onDropFromOtherPane(filePath) \u2014 cross-pane drag-and-drop\n */\n\nimport { DragReorder } from '../ui/components/drag_reorder.js';\n\n/** Custom MIME type so tab bars recognise cross-pane drags. */\nconst TAB_MIME = 'application/x-ecosim-tab';\n\nexport class NotebookTabBar {\n /** @type {HTMLElement} */\n #container = null;\n\n /** @type {object[]} [{filePath, label, fileType, isDirty}] */\n #tabs = [];\n\n /** @type {string|null} */\n #activeTab = null;\n\n /** @type {object} callbacks */\n #callbacks = {};\n\n // \u2500\u2500\u2500 Context menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** @type {HTMLElement|null} */\n #contextMenuEl = null;\n\n /** @type {Function|null} */\n #boundHideContextMenu = null;\n\n // \u2500\u2500\u2500 Drag and drop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Same-pane reorder. Cross-pane drops stay in this class's own\n * container handlers (#onStripDrag*).\n * @type {DragReorder|null} */\n #dragReorder = null;\n\n mount(container, callbacks = {}) {\n this.#container = container;\n this.#callbacks = callbacks;\n this.#container.className = 'tabs notebook-tabs';\n this.#boundHideContextMenu = () => this.#hideContextMenu();\n this.#installStripDnDHandlers();\n this.#dragReorder = new DragReorder({\n container: this.#container,\n itemSelector: '.tab',\n keyAttr: 'path',\n axis: 'x',\n draggableGuard: (e) => {\n if (e.target.closest('.twm-tab-close')) return false;\n const title = e.target.closest('.tab')?.querySelector('.twm-tab-title');\n return title?.getAttribute('contenteditable') !== 'true';\n },\n onDragStart: (e, key) => {\n // Carry the cross-pane MIME so other panes accept this tab.\n try { e.dataTransfer.setData(TAB_MIME, key); } catch (_) {}\n },\n onReorder: (order) => this.#callbacks.onReorder?.(order),\n });\n this.#render();\n }\n\n /**\n * Sync tabs from ProjectModel state.\n * @param {Array<{ filePath: string, fileType: string, isDirty: boolean }>} tabs\n * @param {string|null} activeFilePath\n */\n update(tabs, activeFilePath) {\n this.#tabs = tabs;\n this.#activeTab = activeFilePath;\n this.#render();\n }\n\n markDirty(filePath, isDirty) {\n const tab = this.#tabs.find(t => t.filePath === filePath);\n if (tab) {\n tab.isDirty = isDirty;\n this.#render();\n }\n }\n\n dispose() {\n this.#hideContextMenu();\n this.#removeStripDnDHandlers();\n this.#dragReorder?.destroy();\n this.#dragReorder = null;\n this.#container = null;\n }\n\n // Material symbol per file kind, merged over the generic set. The map used to\n // hardcode EcoAgent's kinds \u2014 `scenario`, `dashboard`, `model` \u2014 so a generic\n // tab bar knew one application's file taxonomy. Pass `fileTypeIcons` to add\n // your own.\n static #FILE_TYPE_ICONS = {\n module: 'extension',\n test: 'fact_check',\n diff: 'difference',\n unknown: 'description',\n };\n\n static #EXTRA_ICONS = {};\n\n /**\n * Add your application's file kinds to the tab-bar icon map.\n *\n * The map used to hardcode `scenario: 'science'`, `dashboard: 'dashboard'` and\n * `model: 'schema'` \u2014 EcoAgent's file taxonomy, baked into a generic tab bar.\n *\n * @param {Object.<string, string>} icons fileType -> material symbol name\n */\n static setFileTypeIcons(icons = {}) {\n NotebookTabBar.#EXTRA_ICONS = { ...icons };\n }\n\n static #iconFor(fileType) {\n return NotebookTabBar.#EXTRA_ICONS[fileType]\n ?? NotebookTabBar.#FILE_TYPE_ICONS[fileType]\n ?? NotebookTabBar.#FILE_TYPE_ICONS.unknown;\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Rendering\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n #render() {\n if (!this.#container) return;\n\n this.#container.innerHTML = '';\n\n for (const tab of this.#tabs) {\n const isActive = tab.filePath === this.#activeTab;\n const rawPath = tab.filePath.replace(/^(diff|builtin):\\/\\//, '');\n const label = tab.label\n ?? (tab.fileType === 'diff'\n ? `\u2194 ${rawPath.split('/').pop()}`\n : rawPath.split('/').pop().replace(/\\.[^.]+$/, ''));\n const icon = NotebookTabBar.#iconFor(tab.fileType);\n\n const tabEl = document.createElement('div');\n tabEl.className = `tab${isActive ? ' active' : ''}${tab.isPreview ? ' tab--preview' : ''}`;\n tabEl.dataset.path = tab.filePath;\n tabEl.title = tab.filePath;\n\n tabEl.innerHTML = `\n <span class=\"material-symbols-outlined tab-icon\">${icon}</span>\n <span class=\"twm-tab-title\">${this.#escHtml(label)}</span>\n ${tab.isDirty ? '<span class=\"tab-dirty\">\\u25cf</span>' : ''}\n ${tab.readonly ? '' : '<button class=\"twm-tab-close\" title=\"Close tab\" aria-label=\"Close tab\">\\u00d7</button>'}\n `;\n\n // Click \u2192 activate\n tabEl.addEventListener('click', (e) => {\n if (e.target.closest('.twm-tab-close')) return;\n if (tabEl.querySelector('.twm-tab-title')?.getAttribute('contenteditable') === 'true') return;\n this.#callbacks.onActivate?.(tab.filePath);\n });\n\n // Close button\n tabEl.querySelector('.twm-tab-close')?.addEventListener('click', (e) => {\n e.stopPropagation();\n this.#callbacks.onClose?.(tab.filePath);\n });\n\n // Double-click \u2192 inline rename\n tabEl.addEventListener('dblclick', (e) => {\n if (e.target.closest('.twm-tab-close')) return;\n this.#beginInlineRename(tab.filePath);\n });\n\n // F2 \u2192 inline rename\n tabEl.addEventListener('keydown', (e) => {\n if (e.key === 'F2') {\n e.preventDefault();\n this.#beginInlineRename(tab.filePath);\n }\n });\n\n // Context menu\n tabEl.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.#showContextMenu(e.clientX, e.clientY, tab.filePath);\n });\n\n this.#container.appendChild(tabEl);\n }\n // Make the freshly-rendered tabs draggable-to-reorder.\n this.#dragReorder?.attach();\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Drag and drop reordering (same-pane + cross-pane)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n #installStripDnDHandlers() {\n if (!this.#container) return;\n this.#container.addEventListener('dragover', this.#onStripDragOver);\n this.#container.addEventListener('drop', this.#onStripDrop);\n this.#container.addEventListener('dragleave', this.#onStripDragLeave);\n }\n\n #removeStripDnDHandlers() {\n if (!this.#container) return;\n this.#container.removeEventListener('dragover', this.#onStripDragOver);\n this.#container.removeEventListener('drop', this.#onStripDrop);\n this.#container.removeEventListener('dragleave', this.#onStripDragLeave);\n }\n\n /** Check whether a drag event carries a cross-pane tab (not from this bar). */\n #isExternalTabDrag(e) {\n if (this.#dragReorder?.isActive()) return false; // same-pane drag is active\n try { return e.dataTransfer.types.includes(TAB_MIME); } catch { return false; }\n }\n\n // Same-pane reorder is handled by the shared DragReorder module (set\n // up in mount()). These container handlers cover ONLY cross-pane tab\n // drops \u2014 gated on `#isExternalTabDrag`, which defers while our own\n // reorder drag is active.\n\n #onStripDragOver = (e) => {\n if (this.#isExternalTabDrag(e)) {\n e.preventDefault();\n try { e.dataTransfer.dropEffect = 'move'; } catch (_) {}\n this.#container.classList.add('notebook-tabs--drop-target');\n }\n };\n\n #onStripDrop = (e) => {\n if (this.#isExternalTabDrag(e)) {\n e.preventDefault();\n this.#container.classList.remove('notebook-tabs--drop-target');\n const filePath = e.dataTransfer.getData(TAB_MIME) || e.dataTransfer.getData('text/plain');\n if (filePath) {\n this.#callbacks.onDropFromOtherPane?.(filePath);\n }\n }\n };\n\n #onStripDragLeave = (e) => {\n if (!this.#container.contains(e.relatedTarget)) {\n this.#container.classList.remove('notebook-tabs--drop-target');\n }\n };\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Context menu\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n #showContextMenu(x, y, filePath) {\n this.#hideContextMenu();\n\n const idx = this.#tabs.findIndex(t => t.filePath === filePath);\n const total = this.#tabs.length;\n\n const allItems = [\n { label: 'Rename', icon: 'edit', action: 'rename', shortcut: 'F2' },\n { label: 'Duplicate', icon: 'content_copy', action: 'duplicate' },\n { separator: true },\n { label: 'Split Right', icon: 'vertical_split', action: 'split-right', shortcut: 'Ctrl+\\\\' },\n { label: 'Move to Other Pane',icon: 'swap_horiz', action: 'move-to-other' },\n { separator: true },\n { label: 'Close', icon: 'close', action: 'close', danger: true },\n { label: 'Close Others', icon: 'close_fullscreen', action: 'close-others', danger: true, disabled: total <= 1 },\n { label: 'Close to the Right',icon: 'tab_close', action: 'close-right', danger: true, disabled: idx === -1 || idx >= total - 1 },\n { label: 'Close All', icon: 'tab_close_inactive', action: 'close-all', danger: true },\n { label: 'Close Saved', icon: 'check_circle', action: 'close-saved', danger: true },\n { separator: true },\n { label: 'Reveal in Explorer', icon: 'folder_open', action: 'reveal' },\n ];\n\n const menuFilter = this.#callbacks.menuFilter;\n const items = menuFilter\n ? allItems.filter(item => item.separator || menuFilter(item.action, filePath) !== false)\n : allItems;\n\n // Collapse consecutive / leading / trailing separators\n const cleaned = [];\n for (const item of items) {\n if (item.separator) {\n if (cleaned.length > 0 && !cleaned[cleaned.length - 1].separator) cleaned.push(item);\n } else {\n cleaned.push(item);\n }\n }\n while (cleaned.length > 0 && cleaned[cleaned.length - 1].separator) cleaned.pop();\n\n const menu = document.createElement('div');\n menu.className = 'nb-context-menu';\n\n for (const item of cleaned) {\n if (item.separator) {\n const sep = document.createElement('div');\n sep.className = 'nb-context-menu__separator';\n menu.appendChild(sep);\n continue;\n }\n\n const btn = document.createElement('button');\n btn.className = 'nb-context-menu__item';\n if (item.danger) btn.classList.add('nb-context-menu__item--danger');\n if (item.disabled) btn.classList.add('nb-context-menu__item--disabled');\n\n btn.innerHTML = `<span class=\"material-symbols-outlined\">${item.icon}</span><span>${this.#escHtml(item.label)}</span>${\n item.shortcut ? `<span class=\"nb-context-menu__shortcut\">${item.shortcut}</span>` : ''\n }`;\n\n if (!item.disabled) {\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.#hideContextMenu();\n this.#handleContextMenuAction(item.action, filePath);\n });\n }\n menu.appendChild(btn);\n }\n\n document.body.appendChild(menu);\n this.#contextMenuEl = menu;\n\n // Position with viewport clamping\n const rect = menu.getBoundingClientRect();\n const left = Math.min(x, window.innerWidth - rect.width - 8);\n const top = Math.min(y, window.innerHeight - rect.height - 8);\n menu.style.left = `${Math.max(0, left)}px`;\n menu.style.top = `${Math.max(0, top)}px`;\n\n // Animate in\n requestAnimationFrame(() => menu.classList.add('visible'));\n\n // Dismiss on outside click or Escape\n setTimeout(() => {\n document.addEventListener('click', this.#boundHideContextMenu, true);\n document.addEventListener('contextmenu', this.#boundHideContextMenu, true);\n }, 0);\n document.addEventListener('keydown', this.#onKeyDown);\n }\n\n #hideContextMenu() {\n if (!this.#contextMenuEl) return;\n this.#contextMenuEl.remove();\n this.#contextMenuEl = null;\n document.removeEventListener('click', this.#boundHideContextMenu, true);\n document.removeEventListener('contextmenu', this.#boundHideContextMenu, true);\n document.removeEventListener('keydown', this.#onKeyDown);\n }\n\n #onKeyDown = (e) => {\n if (e.key === 'Escape') this.#hideContextMenu();\n };\n\n #handleContextMenuAction(action, filePath) {\n switch (action) {\n case 'rename': this.#beginInlineRename(filePath); break;\n case 'duplicate': this.#callbacks.onDuplicate?.(filePath); break;\n case 'close': this.#callbacks.onClose?.(filePath); break;\n case 'close-others': this.#callbacks.onCloseOthers?.(filePath); break;\n case 'close-right': this.#callbacks.onCloseToRight?.(filePath); break;\n case 'close-all': this.#callbacks.onCloseAll?.(); break;\n case 'close-saved': this.#callbacks.onCloseSaved?.(); break;\n case 'split-right': this.#callbacks.onSplitRight?.(filePath); break;\n case 'move-to-other':this.#callbacks.onMoveToOtherPane?.(filePath); break;\n case 'reveal': this.#callbacks.onRevealInExplorer?.(filePath); break;\n }\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Inline rename (contenteditable on tab title)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n #beginInlineRename(filePath) {\n const tabEl = this.#container?.querySelector(`.tab[data-path=\"${CSS.escape(filePath)}\"]`);\n if (!tabEl) return;\n\n const title = tabEl.querySelector('.twm-tab-title');\n if (!title || title.getAttribute('contenteditable') === 'true') return;\n\n const tab = this.#tabs.find(t => t.filePath === filePath);\n if (!tab) return;\n\n // model.notebook, builtin, and readonly files cannot be renamed\n if (tab.fileType === 'model') return;\n if (filePath.startsWith('builtin://')) return;\n if (tab.readonly) return;\n\n const original = title.textContent || '';\n title.setAttribute('contenteditable', 'true');\n title.focus();\n\n try {\n const range = document.createRange();\n range.selectNodeContents(title);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) { /* ignore */ }\n\n let committed = false;\n\n const finish = (commit) => {\n if (committed) return;\n committed = true;\n\n const newName = (title.textContent || '').trim();\n title.removeAttribute('contenteditable');\n title.removeEventListener('keydown', onKeyDown);\n title.removeEventListener('blur', onBlur, true);\n\n try { window.getSelection()?.removeAllRanges?.(); } catch (_) { /* ignore */ }\n\n if (commit && newName && newName !== original && /^[\\w][\\w.-]*$/.test(newName)) {\n title.textContent = newName;\n const dir = filePath.split('/').slice(0, -1).join('/');\n const ext = filePath.split('.').pop();\n const newPath = `${dir}/${newName}.${ext}`;\n this.#callbacks.onRename?.(filePath, newPath);\n } else {\n title.textContent = original;\n }\n };\n\n const onKeyDown = (e) => {\n if (e.key === 'Enter') { e.preventDefault(); finish(true); }\n else if (e.key === 'Escape') { e.preventDefault(); finish(false); }\n e.stopPropagation();\n };\n\n const onBlur = () => finish(true);\n\n title.addEventListener('keydown', onKeyDown);\n title.addEventListener('blur', onBlur, true);\n }\n\n #escHtml(s) {\n return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n}\n", "/**\r\n * EditorPane \u2014 one half (or whole) of the split editor.\r\n *\r\n * Each pane owns:\r\n * - A NotebookTabBar instance\r\n * - An editor container where the active file's editor is mounted\r\n * - A list of file paths assigned to this pane\r\n * - The active file path within this pane\r\n *\r\n * The pane does NOT mount editors itself \u2014 it delegates to the parent\r\n * (NotebookPage) via callbacks, since editor mounting requires access to\r\n * ProjectModel, symbol index, plot controller, etc.\r\n *\r\n * Layout:\r\n * \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\r\n * \u2502 [Tab1] [Tab2] \u2502 \u2190 NotebookTabBar\r\n * \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\r\n * \u2502 \u2502\r\n * \u2502 Editor content \u2502 \u2190 editorContainer\r\n * \u2502 \u2502\r\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n */\r\n\r\nimport { NotebookTabBar } from './notebook_tab_bar.js';\r\n\r\nexport class EditorPane {\r\n /** @type {string} */\r\n #id;\r\n\r\n /** @type {HTMLElement} root element */\r\n #el = null;\r\n\r\n /** @type {NotebookTabBar} */\r\n #tabBar = null;\r\n\r\n /** @type {HTMLElement} */\r\n #editorContainer = null;\r\n\r\n /** @type {string[]} file paths in tab order */\r\n #filePaths = [];\r\n\r\n /** @type {string|null} */\r\n #activeFilePath = null;\r\n\r\n /** @type {string|null} file path of the preview (transient) tab, if any */\r\n #previewFilePath = null;\r\n\r\n /** @type {object} callbacks from parent */\r\n #callbacks = {};\r\n\r\n /** @type {boolean} whether this pane is the focused/active pane */\r\n #focused = false;\r\n\r\n /**\r\n * @param {string} id \u2014 unique pane identifier ('left' or 'right')\r\n * @param {object} callbacks\r\n * @param {Function} callbacks.onActivate \u2014 (paneId, filePath) => void\r\n * @param {Function} callbacks.onClose \u2014 (paneId, filePath) => void\r\n * @param {Function} callbacks.onCloseOthers \u2014 (paneId, filePath) => void\r\n * @param {Function} callbacks.onCloseToRight \u2014 (paneId, filePath) => void\r\n * @param {Function} callbacks.onCloseAll \u2014 (paneId) => void\r\n * @param {Function} callbacks.onCloseSaved \u2014 (paneId) => void\r\n * @param {Function} callbacks.onRename \u2014 (oldPath, newPath) => void\r\n * @param {Function} callbacks.onDuplicate \u2014 (filePath) => void\r\n * @param {Function} callbacks.onReorder \u2014 (paneId, orderedPaths) => void\r\n * @param {Function} callbacks.onRevealInExplorer \u2014 (filePath) => void\r\n * @param {Function} callbacks.onFocus \u2014 (paneId) => void\r\n * @param {Function} callbacks.onSplitRight \u2014 (paneId, filePath) => void\r\n * @param {Function} callbacks.onMoveToOtherPane \u2014 (paneId, filePath) => void\r\n */\r\n constructor(id, callbacks = {}) {\r\n this.#id = id;\r\n this.#callbacks = callbacks;\r\n }\r\n\r\n get id() { return this.#id; }\r\n get activeFilePath() { return this.#activeFilePath; }\r\n get filePaths() { return [...this.#filePaths]; }\r\n get editorContainer() { return this.#editorContainer; }\r\n get element() { return this.#el; }\r\n get isEmpty() { return this.#filePaths.length === 0; }\r\n\r\n /**\r\n * Build DOM and mount the tab bar.\r\n * @returns {HTMLElement} the root element (to be placed in SplitPaneContainer)\r\n */\r\n mount() {\r\n this.#el = document.createElement('div');\r\n this.#el.className = 'editor-pane';\r\n this.#el.dataset.paneId = this.#id;\r\n\r\n // Focus tracking \u2014 clicking anywhere in the pane focuses it\r\n this.#el.addEventListener('mousedown', () => {\r\n this.#callbacks.onFocus?.(this.#id);\r\n }, true);\r\n\r\n // Tab bar\r\n const tabBarEl = document.createElement('div');\r\n this.#el.appendChild(tabBarEl);\r\n\r\n this.#tabBar = new NotebookTabBar();\r\n this.#tabBar.mount(tabBarEl, {\r\n onActivate: (path) => this.#callbacks.onActivate?.(this.#id, path),\r\n onClose: (path) => this.#callbacks.onClose?.(this.#id, path),\r\n onCloseOthers: (path) => this.#callbacks.onCloseOthers?.(this.#id, path),\r\n onCloseToRight: (path) => this.#callbacks.onCloseToRight?.(this.#id, path),\r\n onCloseAll: () => this.#callbacks.onCloseAll?.(this.#id),\r\n onCloseSaved: () => this.#callbacks.onCloseSaved?.(this.#id),\r\n onRename: (o, n) => this.#callbacks.onRename?.(o, n),\r\n onDuplicate: (path) => this.#callbacks.onDuplicate?.(path),\r\n onReorder: (paths) => this.#callbacks.onReorder?.(this.#id, paths),\r\n onRevealInExplorer:(path) => this.#callbacks.onRevealInExplorer?.(path),\r\n onSplitRight: (path) => this.#callbacks.onSplitRight?.(this.#id, path),\r\n onMoveToOtherPane: (path) => this.#callbacks.onMoveToOtherPane?.(this.#id, path),\r\n onDropFromOtherPane: (path) => this.#callbacks.onDropFromOtherPane?.(this.#id, path),\r\n });\r\n\r\n // Editor body wrapper \u2014 positioned container that fills remaining\r\n // flex space. The actual editor container is absolutely positioned\r\n // inside, so its height is ALWAYS the wrapper's height, regardless\r\n // of content. This makes the scroll chain bulletproof \u2014 no flex\r\n // ancestor chain needed for the scrollbar to work.\r\n const body = document.createElement('div');\r\n body.className = 'editor-pane__body';\r\n this.#el.appendChild(body);\r\n\r\n // Editor container (absolutely positioned inside wrapper)\r\n this.#editorContainer = document.createElement('div');\r\n this.#editorContainer.className = 'notebook-editor-container';\r\n body.appendChild(this.#editorContainer);\r\n\r\n // Accept cross-pane tab drops on the editor area too\r\n this.#editorContainer.addEventListener('dragover', (e) => {\r\n if (this.#isExternalTabDrag(e)) {\r\n e.preventDefault();\r\n try { e.dataTransfer.dropEffect = 'move'; } catch {}\r\n this.#editorContainer.classList.add('notebook-editor-container--drop-target');\r\n }\r\n });\r\n this.#editorContainer.addEventListener('drop', (e) => {\r\n if (this.#isExternalTabDrag(e)) {\r\n e.preventDefault();\r\n this.#editorContainer.classList.remove('notebook-editor-container--drop-target');\r\n const filePath = e.dataTransfer.getData('application/x-ecosim-tab')\r\n || e.dataTransfer.getData('text/plain');\r\n if (filePath) {\r\n this.#callbacks.onDropFromOtherPane?.(this.#id, filePath);\r\n }\r\n }\r\n });\r\n this.#editorContainer.addEventListener('dragleave', (e) => {\r\n if (!this.#editorContainer.contains(e.relatedTarget)) {\r\n this.#editorContainer.classList.remove('notebook-editor-container--drop-target');\r\n }\r\n });\r\n\r\n return this.#el;\r\n }\r\n\r\n /**\r\n * Update the file list and active tab.\r\n * @param {Array<{filePath: string, fileType: string, isDirty: boolean}>} tabs\r\n * @param {string|null} activeFilePath\r\n */\r\n syncTabBar(tabs, activeFilePath) {\r\n this.#tabBar?.update(tabs, activeFilePath);\r\n }\r\n\r\n /**\r\n * Set the files assigned to this pane.\r\n * @param {string[]} filePaths\r\n */\r\n setFilePaths(filePaths) {\r\n this.#filePaths = [...filePaths];\r\n }\r\n\r\n /**\r\n * Add a file to this pane's tabs (at end).\r\n * @param {string} filePath\r\n */\r\n addFile(filePath) {\r\n if (!this.#filePaths.includes(filePath)) {\r\n this.#filePaths.push(filePath);\r\n }\r\n }\r\n\r\n /**\r\n * Remove a file from this pane's tabs.\r\n * @param {string} filePath\r\n */\r\n removeFile(filePath) {\r\n this.#filePaths = this.#filePaths.filter(p => p !== filePath);\r\n if (this.#previewFilePath === filePath) this.#previewFilePath = null;\r\n if (this.#activeFilePath === filePath) {\r\n this.#activeFilePath = this.#filePaths.length > 0\r\n ? this.#filePaths[this.#filePaths.length - 1]\r\n : null;\r\n }\r\n }\r\n\r\n hasFile(filePath) {\r\n return this.#filePaths.includes(filePath);\r\n }\r\n\r\n setActiveFile(filePath) {\r\n this.#activeFilePath = filePath;\r\n }\r\n\r\n setFocused(focused) {\r\n this.#focused = focused;\r\n this.#el?.classList.toggle('editor-pane--focused', focused);\r\n }\r\n\r\n markDirty(filePath, isDirty) {\r\n this.#tabBar?.markDirty(filePath, isDirty);\r\n }\r\n\r\n reorderFiles(orderedPaths) {\r\n // Keep only paths that belong to this pane\r\n const valid = orderedPaths.filter(p => this.#filePaths.includes(p));\r\n // Append any missing (shouldn't happen)\r\n for (const p of this.#filePaths) {\r\n if (!valid.includes(p)) valid.push(p);\r\n }\r\n this.#filePaths = valid;\r\n }\r\n\r\n renameFile(oldPath, newPath) {\r\n const idx = this.#filePaths.indexOf(oldPath);\r\n if (idx !== -1) this.#filePaths[idx] = newPath;\r\n if (this.#activeFilePath === oldPath) this.#activeFilePath = newPath;\r\n if (this.#previewFilePath === oldPath) this.#previewFilePath = newPath;\r\n }\r\n\r\n // \u2500\u2500\u2500 Preview (transient) tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n /** @returns {string|null} the preview file path, or null if no preview tab */\r\n get previewFilePath() { return this.#previewFilePath; }\r\n\r\n /** Mark a file as the preview tab. Only one preview tab per pane. */\r\n setPreview(filePath) { this.#previewFilePath = filePath; }\r\n\r\n /** Whether a file is the preview (transient) tab. */\r\n isPreview(filePath) { return this.#previewFilePath === filePath; }\r\n\r\n /** Pin the preview tab (promote to permanent). */\r\n pinPreview() { this.#previewFilePath = null; }\r\n\r\n /** Check if a drag event is carrying a tab from another pane. */\r\n #isExternalTabDrag(e) {\r\n try { return e.dataTransfer.types.includes('application/x-ecosim-tab'); } catch { return false; }\r\n }\r\n\r\n dispose() {\r\n this.#tabBar?.dispose();\r\n this.#tabBar = null;\r\n this.#el?.remove();\r\n this.#el = null;\r\n this.#editorContainer = null;\r\n this.#filePaths = [];\r\n this.#activeFilePath = null;\r\n this.#previewFilePath = null;\r\n }\r\n}\r\n", "/**\n * Monaco Loader \u2014 wraps the AMD require() bootstrap into an ES module Promise.\n *\n * Monaco ships as AMD modules. vs/loader.js is injected dynamically on demand\n * (NOT via a global <script> tag) so it does not pollute window.define before\n * Plotly loads. Plotly auto-detects AMD define and would wrap itself as a module\n * instead of setting window.Plotly if loader.js ran at page load.\n */\n\nlet _resolveMonaco;\nlet _monacoReady = false;\n\n/** @type {Promise<typeof monaco>} */\nexport const monacoReady = new Promise(resolve => { _resolveMonaco = resolve; });\n\nfunction injectLoaderScript(src) {\n return new Promise((resolve, reject) => {\n const s = document.createElement('script');\n s.src = src;\n s.onload = resolve;\n s.onerror = () => reject(new Error(`Failed to load Monaco loader: ${src}`));\n document.head.appendChild(s);\n });\n}\n\nfunction injectMonacoCss(basePath) {\n const id = 'monaco-editor-css';\n if (document.getElementById(id)) return;\n const link = document.createElement('link');\n link.id = id;\n link.rel = 'stylesheet';\n link.href = `${basePath}/vs/editor/editor.main.css`;\n document.head.appendChild(link);\n}\n\n/**\n * Call once when the notebook page initialises.\n * Where Monaco lives is the CONSUMER's business.\n *\n * `basePath` defaulted to 'vendor/monaco' \u2014 a path into ONE application's tree,\n * which would 404 for anyone else. Exactly the bug plotly_wrapper.js had, and it\n * takes exactly the same fix: no default, and say so if nobody supplies one.\n *\n * Monaco is a PEER dependency \u2014 14 MB this bundle deliberately does not contain.\n *\n * @param {string} basePath Path prefix for the vs/ directory. REQUIRED.\n */\nexport async function initMonaco(basePath) {\n if (!basePath) {\n throw new Error(\n '[twm/editor] initMonaco() needs the path to your copy of Monaco, e.g. '\n + \"initMonaco('vendor/monaco'). Monaco is a peer dependency; the library \"\n + 'does not guess where you put it.');\n }\n if (_monacoReady) return monacoReady;\n _monacoReady = true;\n\n // Inject CSS and loader.js dynamically \u2014 kept out of the HTML to avoid global bleed\n injectMonacoCss(basePath);\n if (!window.require) {\n await injectLoaderScript(`${basePath}/vs/loader.js`);\n }\n\n window.require.config({\n paths: { vs: `${basePath}/vs` },\n 'vs/nls': { availableLanguages: {} },\n });\n\n window.require(['vs/editor/editor.main'], () => {\n _resolveMonaco(window.monaco);\n });\n\n return monacoReady;\n}\n", "/**\n * Monaco Editor Factory\n *\n * Creates and manages Monaco editor instances for cells.\n * Handles:\n * - Creating full editors (multi-line, for CodeCells)\n * - Creating single-line inline editors (for ParameterCell values, expression fields)\n * - Theme registration (ecosim-dark, ecosim-light)\n * - Shared editor options\n * - Instance lifecycle (dispose on cell removal)\n */\n\nimport { monacoReady, initMonaco } from './monaco_loader.js';\n// The default language is the CONSUMER's. This imported ECOLANG_ID \u2014 EcoAgent's\n// expression language \u2014 so a generic Monaco factory shipped knowing the name of one\n// application's DSL. Register your language with Monaco and name it here.\nlet _defaultLanguage = 'plaintext';\n\n/** @param {string} id A language id already registered with Monaco. */\nexport function setDefaultLanguage(id) {\n if (typeof id === 'string' && id) _defaultLanguage = id;\n}\n\n/** Dispose a Monaco editor, swallowing the benign \"Canceled\" error from pending async ops. */\nfunction safeDispose(editor) {\n try { editor.dispose(); } catch (e) { if (e?.message !== 'Canceled') throw e; }\n}\n\n// \u2500\u2500\u2500 Theme definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ECOSIM_DARK_THEME = {\n base: 'vs-dark',\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6a9955', fontStyle: 'italic' },\n { token: 'keyword', foreground: '569cd6', fontStyle: 'bold' },\n { token: 'keyword.directive', foreground: 'c586c0', fontStyle: 'bold' },\n { token: 'keyword.operator', foreground: '569cd6' },\n { token: 'constant', foreground: 'c586c0' },\n { token: 'number', foreground: 'b5cea8' },\n { token: 'string', foreground: 'ce9178' },\n { token: 'type.identifier', foreground: '4ec9b0', fontStyle: 'bold' },\n { token: 'support.function', foreground: 'a6e22e' },\n { token: 'identifier', foreground: '4fc1ff' },\n { token: 'operator', foreground: 'd4d4d4' },\n { token: 'delimiter', foreground: '808080' },\n ],\n colors: {\n // Layer-2 input well \u2014 almost black, matches the EcoAgent\n // three-layer contrast pattern (chrome #1a1a1a, content\n // #212121, input/code #0a0a0a). Makes editable surfaces\n // visually recess from the surrounding cards.\n 'editor.background': '#0a0a0a',\n 'editor.foreground': '#e0e0e0',\n 'editor.lineHighlightBackground': '#161616',\n 'editor.selectionBackground': '#264f78',\n 'editor.inactiveSelectionBackground': '#1f3350',\n 'editorLineNumber.foreground': '#5a5a5a',\n 'editorLineNumber.activeForeground': '#c6c6c6',\n 'editorCursor.foreground': '#39ff14',\n 'editor.findMatchBackground': '#9e6a03',\n 'editor.findMatchHighlightBackground': '#f2cc6030',\n 'editorIndentGuide.background1': '#2e2e2e',\n 'editorIndentGuide.activeBackground1': '#5a5a5a',\n 'editorGutter.background': '#0a0a0a',\n // Pop-ups stay slightly lighter so they read as floating\n // surfaces above the editor body, not part of it.\n 'editorWidget.background': '#1a1a1a',\n 'editorSuggestWidget.background': '#1a1a1a',\n 'editorSuggestWidget.border': '#383838',\n 'editorSuggestWidget.selectedBackground': '#094771',\n 'scrollbarSlider.background': '#4a4a4d40',\n 'scrollbarSlider.hoverBackground': '#4a4a4d70',\n },\n};\n\nconst ECOSIM_LIGHT_THEME = {\n base: 'vs',\n inherit: true,\n rules: [\n { token: 'comment', foreground: '6a737d', fontStyle: 'italic' },\n { token: 'keyword', foreground: 'd73a49', fontStyle: 'bold' },\n { token: 'keyword.directive', foreground: '6f42c1', fontStyle: 'bold' },\n { token: 'keyword.operator', foreground: 'd73a49' },\n { token: 'constant', foreground: 'e36209' },\n { token: 'number', foreground: '005cc5' },\n { token: 'string', foreground: '22863a' },\n { token: 'type.identifier', foreground: '005cc5', fontStyle: 'bold' },\n { token: 'support.function', foreground: '6f42c1' },\n { token: 'identifier', foreground: '24292e' },\n { token: 'operator', foreground: 'd73a49' },\n { token: 'delimiter', foreground: '586069' },\n ],\n colors: {\n 'editor.background': '#ffffff',\n 'editor.foreground': '#24292e',\n 'editor.lineHighlightBackground': '#f6f8fa',\n 'editor.selectionBackground': '#c8d3e6',\n 'editorLineNumber.foreground': '#babbbd',\n 'editorLineNumber.activeForeground': '#586069',\n 'editorCursor.foreground': '#044289',\n 'editorGutter.background': '#ffffff',\n 'editorWidget.background': '#f6f8fa',\n 'editorSuggestWidget.background': '#f6f8fa',\n 'editorSuggestWidget.border': '#e1e4e8',\n 'scrollbarSlider.background': '#babbbd40',\n 'scrollbarSlider.hoverBackground': '#babbbd70',\n },\n};\n\nlet _themesRegistered = false;\n\nfunction ensureThemes(monaco) {\n if (_themesRegistered) return;\n _themesRegistered = true;\n monaco.editor.defineTheme('ecosim-dark', ECOSIM_DARK_THEME);\n monaco.editor.defineTheme('ecosim-light', ECOSIM_LIGHT_THEME);\n}\n\n// \u2500\u2500\u2500 Shared editor options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction baseOptions(overrides = {}) {\n return {\n language: _defaultLanguage,\n theme: 'ecosim-dark',\n fontFamily: 'Consolas, \"Courier New\", monospace',\n fontSize: 13,\n lineHeight: 19.5,\n tabSize: 4,\n insertSpaces: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n renderLineHighlight: 'gutter',\n matchBrackets: 'always',\n padding: { top: 8, bottom: 8 },\n overviewRulerLanes: 0,\n hideCursorInOverviewRuler: true,\n overviewRulerBorder: false,\n scrollbar: { handleMouseWheel: false },\n folding: true,\n lineDecorationsWidth: 0,\n // Reserve a couple extra gutter columns so the right-aligned line\n // numbers get some breathing room on the left instead of sitting flush\n // against the editor edge (digits stay right-aligned; the slack lands\n // on the left). Covers up to 5-digit files too.\n lineNumbersMinChars: 5,\n suggest: {\n showKeywords: true,\n showFunctions: true,\n showVariables: true,\n showConstants: true,\n showModules: true,\n snippetsPreventQuickSuggestions: false,\n },\n quickSuggestions: { other: true, comments: false, strings: false },\n parameterHints: { enabled: true },\n wordWrap: 'off',\n fixedOverflowWidgets: true,\n ...overrides,\n };\n}\n\nfunction singleLineOptions(overrides = {}) {\n return baseOptions({\n lineNumbers: 'off',\n lineDecorationsWidth: 0,\n lineNumbersMinChars: 0,\n glyphMargin: false,\n folding: false,\n renderLineHighlight: 'none',\n scrollbar: { vertical: 'hidden', horizontal: 'hidden', handleMouseWheel: false },\n wordWrap: 'off',\n overviewRulerLanes: 0,\n padding: { top: 3, bottom: 3 },\n ...overrides,\n });\n}\n\n// \u2500\u2500\u2500 Factory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * @typedef {{ editor: object, dispose: () => void, getValue: () => string, setValue: (v: string) => void, onDidChange: (cb: () => void) => object }} EditorHandle\n */\n\nexport class MonacoEditorFactory {\n #monaco = null;\n #currentTheme = 'ecosim-dark';\n\n constructor() {}\n\n async init() {\n this.#monaco = await monacoReady;\n ensureThemes(this.#monaco);\n return this;\n }\n\n get monaco() { return this.#monaco; }\n\n /**\n * Set global theme for all editors.\n * @param {'ecosim-dark'|'ecosim-light'} theme\n */\n setTheme(theme) {\n this.#currentTheme = theme;\n this.#monaco?.editor.setTheme(theme);\n }\n\n /**\n * Create a full multi-line editor (for CodeCell).\n *\n * @param {HTMLElement} container\n * @param {string} initialValue\n * @param {{ language?: string, readOnly?: boolean, lineNumbers?: string } & object} [overrides]\n * @returns {EditorHandle}\n */\n createEditor(container, initialValue = '', overrides = {}) {\n if (!this.#monaco) throw new Error('MonacoEditorFactory not initialized');\n\n const { noAutoHeight, ...editorOverrides } = overrides;\n\n const editor = this.#monaco.editor.create(container, {\n ...baseOptions({ theme: this.#currentTheme }),\n value: initialValue,\n ...editorOverrides,\n });\n\n // Auto-resize to content height.\n // When the \"limit code cell height\" setting is active (data-code-max-height=\"true\"\n // on the editor container), cap at 400px so Monaco handles internal scrolling.\n // Otherwise, grow to fit all content with no upper bound.\n //\n // Monaco's handleMouseWheel is toggled dynamically: disabled when the editor\n // auto-sizes to fit content (so wheel events propagate to the notebook scroller),\n // enabled only when content is capped and there is actual internal overflow.\n //\n // When noAutoHeight is true, skip auto-sizing entirely and let the container\n // control dimensions (e.g. flex layout). Mouse wheel scrolling stays enabled.\n let minHeight = 80;\n let heightDisposable = null;\n let updateHeight = null;\n if (noAutoHeight) {\n editor.updateOptions({ scrollbar: { handleMouseWheel: true } });\n } else {\n updateHeight = () => {\n const maxHeightEnabled = container.closest('.notebook-editor-container')?.dataset.codeMaxHeight === 'true';\n const maxH = maxHeightEnabled ? 400 : Infinity;\n const rawContent = editor.getContentHeight();\n const contentHeight = Math.min(maxH, Math.max(minHeight, rawContent));\n container.style.height = `${contentHeight}px`;\n editor.layout();\n\n // Enable Monaco wheel handling only when content overflows the capped height\n const needsInternalScroll = maxHeightEnabled && rawContent > maxH;\n editor.updateOptions({ scrollbar: { handleMouseWheel: needsInternalScroll } });\n };\n heightDisposable = editor.onDidContentSizeChange(updateHeight);\n updateHeight();\n }\n\n // Re-evaluate height when the code-max-height setting changes on the ancestor\n const editorContainer = container.closest('.notebook-editor-container');\n let maxHeightObserver = null;\n if (updateHeight && editorContainer) {\n maxHeightObserver = new MutationObserver(() => updateHeight());\n maxHeightObserver.observe(editorContainer, { attributes: true, attributeFilter: ['data-code-max-height'] });\n }\n\n // Scroll the find widget into view when it becomes visible.\n // The editor auto-sizes to content (no internal scroll), so the notebook\n // container scrolls instead. The find widget sits at top:0 of the editor,\n // which may be above the viewport for tall cells.\n let findWidgetObserver = null;\n const observeFindWidget = () => {\n const overflowGuard = container.querySelector('.overflow-guard');\n if (!overflowGuard) return;\n\n findWidgetObserver = new MutationObserver(() => {\n const fw = container.querySelector('.find-widget.visible');\n if (fw) fw.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n });\n findWidgetObserver.observe(overflowGuard, {\n subtree: true,\n attributes: true,\n attributeFilter: ['class'],\n });\n };\n // Defer slightly \u2014 Monaco builds DOM asynchronously after create()\n requestAnimationFrame(observeFindWidget);\n\n return {\n editor,\n getValue: () => editor.getValue(),\n setValue: (v) => { if (editor.getValue() !== v) editor.setValue(v); },\n onDidChange: (cb) => editor.onDidChangeModelContent(cb),\n focus: () => editor.focus(),\n layout: () => editor.layout(),\n setMinHeight: (h) => { minHeight = h; },\n updateHeight,\n dispose: () => {\n findWidgetObserver?.disconnect();\n maxHeightObserver?.disconnect();\n heightDisposable?.dispose();\n safeDispose(editor);\n },\n };\n }\n\n /**\n * Create a single-line inline editor (for ParameterCell value, expression fields).\n *\n * @param {HTMLElement} container\n * @param {string} initialValue\n * @param {{ language?: string, placeholder?: string } & object} [overrides]\n * @returns {EditorHandle}\n */\n createInlineEditor(container, initialValue = '', overrides = {}) {\n if (!this.#monaco) throw new Error('MonacoEditorFactory not initialized');\n\n container.style.height = '26px';\n\n const editor = this.#monaco.editor.create(container, {\n ...singleLineOptions({ theme: this.#currentTheme }),\n value: initialValue,\n ...overrides,\n });\n\n // Prevent newlines in single-line mode\n editor.onKeyDown((e) => {\n if (e.keyCode === this.#monaco.KeyCode.Enter) {\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return {\n editor,\n getValue: () => editor.getValue(),\n setValue: (v) => { if (editor.getValue() !== v) editor.setValue(v); },\n onDidChange: (cb) => editor.onDidChangeModelContent(cb),\n focus: () => editor.focus(),\n layout: () => editor.layout(),\n dispose: () => safeDispose(editor),\n };\n }\n\n /**\n * Create a plain text editor (for documentation cells with markdown).\n * Uses VS Code's built-in markdown language, no EcoLang features.\n *\n * @param {HTMLElement} container\n * @param {string} initialValue\n * @returns {EditorHandle}\n */\n createMarkdownEditor(container, initialValue = '') {\n return this.createEditor(container, initialValue, {\n language: 'markdown',\n wordWrap: 'on',\n lineNumbers: 'off',\n folding: false,\n quickSuggestions: false,\n });\n }\n\n /**\n * Create a read-only DSL viewer (shown in the \"DSL\" tab of a Godley/parameter cell).\n *\n * @param {HTMLElement} container\n * @param {string} dslContent\n * @returns {EditorHandle}\n */\n createDslViewer(container, dslContent = '') {\n return this.createEditor(container, dslContent, {\n readOnly: true,\n lineNumbers: 'off',\n glyphMargin: false,\n folding: false,\n });\n }\n\n /**\n * Create a side-by-side diff editor for comparing two versions of a file.\n *\n * @param {HTMLElement} container\n * @param {string} originalContent - Left side (e.g. HEAD version)\n * @param {string} modifiedContent - Right side (e.g. working copy)\n * @param {{ language?: string, readOnly?: boolean }} [options]\n * @returns {{ editor: object, dispose: Function, setModels: Function }}\n */\n createDiffEditor(container, originalContent = '', modifiedContent = '', options = {}) {\n const monaco = this.#monaco;\n const language = options.language || 'plaintext';\n\n const originalModel = monaco.editor.createModel(originalContent, language);\n const modifiedModel = monaco.editor.createModel(modifiedContent, language);\n\n const diffEditor = monaco.editor.createDiffEditor(container, {\n theme: this.#currentTheme,\n readOnly: options.readOnly !== false,\n renderSideBySide: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n lineNumbers: 'on',\n glyphMargin: false,\n folding: true,\n renderOverviewRuler: false,\n enableSplitViewResizing: true,\n });\n\n diffEditor.setModel({ original: originalModel, modified: modifiedModel });\n\n return {\n editor: diffEditor,\n setModels(original, modified, lang) {\n originalModel.dispose();\n modifiedModel.dispose();\n const newOrig = monaco.editor.createModel(original, lang || language);\n const newMod = monaco.editor.createModel(modified, lang || language);\n diffEditor.setModel({ original: newOrig, modified: newMod });\n },\n dispose() {\n safeDispose(diffEditor);\n safeDispose(originalModel);\n safeDispose(modifiedModel);\n },\n };\n }\n}\n\n/** Singleton instance, initialized lazily. */\nlet _factoryInstance = null;\n\n// Where the app keeps Monaco. Set once, at boot.\nlet _monacoBasePath = null;\n\n/** @param {string} basePath */\nexport function setMonacoBasePath(basePath) {\n if (typeof basePath === 'string' && basePath) _monacoBasePath = basePath;\n}\n\nexport async function getEditorFactory() {\n if (!_factoryInstance) {\n // Ensure Monaco is initialized \u2014 initMonaco is idempotent, safe to call from any entry point\n initMonaco(_monacoBasePath);\n _factoryInstance = await new MonacoEditorFactory().init();\n }\n return _factoryInstance;\n}\n", "/**\r\n * NotebookSearchBar \u2014 VS Code-style find/replace bar for notebook-level search.\r\n *\r\n * Searches across all cells using getSearchableText(), highlights matches\r\n * via cell-specific applySearchHighlights(), and supports replace for\r\n * Monaco-based cells (code, documentation).\r\n *\r\n * Mounted at the top of the notebook-editor-container (sticky positioned).\r\n */\r\n\r\n// \u2500\u2500\u2500 Match descriptor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n/**\r\n * @typedef {{ cellId: string, indexInCell: number, charOffset: number }} SearchMatch\r\n */\r\n\r\n// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport class NotebookSearchBar {\r\n /** @type {HTMLElement} parent container (.notebook-editor-container) */\r\n #parent = null;\r\n /** @type {HTMLElement} the search bar root element */\r\n #el = null;\r\n /** @type {HTMLInputElement} */\r\n #searchInput = null;\r\n /** @type {HTMLInputElement} */\r\n #replaceInput = null;\r\n /** @type {HTMLElement} match info label */\r\n #matchInfo = null;\r\n\r\n // State\r\n #isOpen = false;\r\n #showReplace = false;\r\n #caseSensitive = false;\r\n #wholeWord = false;\r\n #useRegex = false;\r\n\r\n // Match tracking\r\n /** @type {SearchMatch[]} */\r\n #matches = [];\r\n #currentIndex = -1;\r\n\r\n // Callbacks into NotebookEditor\r\n #getCells = null; // () => [{ id, type }]\r\n #getCellRenderer = null; // (id) => CellBase|null\r\n #getCellElement = null; // (id) => HTMLElement|null\r\n #scrollToCell = null; // (id) => void\r\n\r\n /**\r\n * @param {HTMLElement} parent \u2014 .notebook-editor-container\r\n * @param {{ getCells, getCellRenderer, getCellElement, scrollToCell }} callbacks\r\n */\r\n constructor(parent, { getCells, getCellRenderer, getCellElement, scrollToCell }) {\r\n this.#parent = parent;\r\n this.#getCells = getCells;\r\n this.#getCellRenderer = getCellRenderer;\r\n this.#getCellElement = getCellElement;\r\n this.#scrollToCell = scrollToCell;\r\n\r\n this.#render();\r\n }\r\n\r\n get isOpen() { return this.#isOpen; }\r\n\r\n // \u2500\u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n open(showReplace = false) {\r\n this.#isOpen = true;\r\n this.#showReplace = showReplace;\r\n this.#el.classList.add('nb-search-bar--open');\r\n this.#el.querySelector('.nb-search-bar__replace-row').style.display =\r\n showReplace ? '' : 'none';\r\n this.#updateToggleIcon();\r\n\r\n // Pre-fill with current selection text (if any)\r\n const sel = window.getSelection()?.toString()?.trim();\r\n if (sel && sel.length < 200 && !sel.includes('\\n')) {\r\n this.#searchInput.value = sel;\r\n }\r\n\r\n this.#searchInput.focus();\r\n this.#searchInput.select();\r\n\r\n if (this.#searchInput.value) this.#runSearch();\r\n }\r\n\r\n close() {\r\n this.#isOpen = false;\r\n this.#el.classList.remove('nb-search-bar--open');\r\n this.#clearAllHighlights();\r\n this.#matches = [];\r\n this.#currentIndex = -1;\r\n this.#updateMatchInfo();\r\n }\r\n\r\n dispose() {\r\n this.#clearAllHighlights();\r\n this.#el?.remove();\r\n this.#el = null;\r\n }\r\n\r\n // \u2500\u2500\u2500 Rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #render() {\r\n const el = document.createElement('div');\r\n el.className = 'nb-search-bar';\r\n el.innerHTML = `\r\n <div class=\"nb-search-bar__find-row\">\r\n <button class=\"nb-search-bar__btn nb-search-bar__toggle-replace\" title=\"Toggle Replace\">\r\n <span class=\"material-symbols-outlined\">chevron_right</span>\r\n </button>\r\n <div class=\"nb-search-bar__input-wrap\">\r\n <input class=\"nb-search-bar__input nb-search-bar__find-input\"\r\n type=\"text\" placeholder=\"Find\" spellcheck=\"false\" />\r\n </div>\r\n <span class=\"nb-search-bar__match-info\">No results</span>\r\n <button class=\"nb-search-bar__btn\" data-action=\"prev\" title=\"Previous Match (Shift+Enter)\">\r\n <span class=\"material-symbols-outlined\">arrow_upward</span>\r\n </button>\r\n <button class=\"nb-search-bar__btn\" data-action=\"next\" title=\"Next Match (Enter)\">\r\n <span class=\"material-symbols-outlined\">arrow_downward</span>\r\n </button>\r\n <div class=\"nb-search-bar__separator\"></div>\r\n <button class=\"nb-search-bar__btn nb-search-bar__btn--toggle\" data-action=\"case\"\r\n title=\"Match Case (Alt+C)\">Aa</button>\r\n <button class=\"nb-search-bar__btn nb-search-bar__btn--toggle\" data-action=\"word\"\r\n title=\"Match Whole Word (Alt+W)\">\r\n <span class=\"nb-search-bar__icon-word\">ab</span>\r\n </button>\r\n <button class=\"nb-search-bar__btn nb-search-bar__btn--toggle\" data-action=\"regex\"\r\n title=\"Use Regular Expression (Alt+R)\">.*</button>\r\n <div class=\"nb-search-bar__separator\"></div>\r\n <button class=\"nb-search-bar__btn\" data-action=\"close\" title=\"Close (Escape)\">\r\n <span class=\"material-symbols-outlined\">close</span>\r\n </button>\r\n </div>\r\n <div class=\"nb-search-bar__replace-row\" style=\"display:none\">\r\n <div class=\"nb-search-bar__spacer\"></div>\r\n <div class=\"nb-search-bar__input-wrap\">\r\n <input class=\"nb-search-bar__input nb-search-bar__replace-input\"\r\n type=\"text\" placeholder=\"Replace\" spellcheck=\"false\" />\r\n </div>\r\n <button class=\"nb-search-bar__btn\" data-action=\"replace\" title=\"Replace (Ctrl+Shift+1)\">\r\n <span class=\"material-symbols-outlined\">find_replace</span>\r\n </button>\r\n <button class=\"nb-search-bar__btn\" data-action=\"replace-all\" title=\"Replace All (Ctrl+Alt+Enter)\">\r\n <span class=\"material-symbols-outlined\">swap_horiz</span>\r\n </button>\r\n </div>\r\n `;\r\n\r\n this.#el = el;\r\n this.#searchInput = el.querySelector('.nb-search-bar__find-input');\r\n this.#replaceInput = el.querySelector('.nb-search-bar__replace-input');\r\n this.#matchInfo = el.querySelector('.nb-search-bar__match-info');\r\n\r\n this.#bindEvents();\r\n this.#parent.prepend(el);\r\n }\r\n\r\n #bindEvents() {\r\n // Search input\r\n this.#searchInput.addEventListener('input', () => this.#runSearch());\r\n\r\n this.#searchInput.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.#navigateNext();\r\n } else if (e.key === 'Enter' && e.shiftKey) {\r\n e.preventDefault();\r\n this.#navigatePrev();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n this.close();\r\n }\r\n });\r\n\r\n // Replace input\r\n this.#replaceInput.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.#doReplace();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n this.close();\r\n }\r\n });\r\n\r\n // Buttons\r\n this.#el.addEventListener('click', (e) => {\r\n const btn = e.target.closest('[data-action]');\r\n if (!btn) return;\r\n switch (btn.dataset.action) {\r\n case 'prev': this.#navigatePrev(); break;\r\n case 'next': this.#navigateNext(); break;\r\n case 'close': this.close(); break;\r\n case 'replace': this.#doReplace(); break;\r\n case 'replace-all': this.#doReplaceAll(); break;\r\n case 'case':\r\n this.#caseSensitive = !this.#caseSensitive;\r\n btn.classList.toggle('nb-search-bar__btn--active', this.#caseSensitive);\r\n this.#runSearch();\r\n break;\r\n case 'word':\r\n this.#wholeWord = !this.#wholeWord;\r\n btn.classList.toggle('nb-search-bar__btn--active', this.#wholeWord);\r\n this.#runSearch();\r\n break;\r\n case 'regex':\r\n this.#useRegex = !this.#useRegex;\r\n btn.classList.toggle('nb-search-bar__btn--active', this.#useRegex);\r\n this.#runSearch();\r\n break;\r\n }\r\n });\r\n\r\n // Toggle replace row\r\n this.#el.querySelector('.nb-search-bar__toggle-replace').addEventListener('click', () => {\r\n this.#showReplace = !this.#showReplace;\r\n this.#el.querySelector('.nb-search-bar__replace-row').style.display =\r\n this.#showReplace ? '' : 'none';\r\n this.#updateToggleIcon();\r\n });\r\n\r\n // Alt shortcuts for toggles\r\n this.#el.addEventListener('keydown', (e) => {\r\n if (e.altKey && e.key === 'c') {\r\n e.preventDefault();\r\n this.#caseSensitive = !this.#caseSensitive;\r\n this.#el.querySelector('[data-action=\"case\"]').classList.toggle('nb-search-bar__btn--active', this.#caseSensitive);\r\n this.#runSearch();\r\n } else if (e.altKey && e.key === 'w') {\r\n e.preventDefault();\r\n this.#wholeWord = !this.#wholeWord;\r\n this.#el.querySelector('[data-action=\"word\"]').classList.toggle('nb-search-bar__btn--active', this.#wholeWord);\r\n this.#runSearch();\r\n } else if (e.altKey && e.key === 'r') {\r\n e.preventDefault();\r\n this.#useRegex = !this.#useRegex;\r\n this.#el.querySelector('[data-action=\"regex\"]').classList.toggle('nb-search-bar__btn--active', this.#useRegex);\r\n this.#runSearch();\r\n }\r\n });\r\n\r\n // Prevent keydown from bubbling to NotebookEditor (avoids undo/redo interference)\r\n // Also suppress browser Ctrl+F/Ctrl+H when the search bar already has focus\r\n this.#el.addEventListener('keydown', (e) => {\r\n e.stopPropagation();\r\n if (e.ctrlKey && (e.key === 'f' || e.key === 'h')) {\r\n e.preventDefault();\r\n if (e.key === 'h' && !this.#showReplace) {\r\n this.#showReplace = true;\r\n this.#el.querySelector('.nb-search-bar__replace-row').style.display = '';\r\n this.#updateToggleIcon();\r\n }\r\n }\r\n });\r\n }\r\n\r\n #updateToggleIcon() {\r\n const icon = this.#el.querySelector('.nb-search-bar__toggle-replace .material-symbols-outlined');\r\n if (icon) icon.textContent = this.#showReplace ? 'expand_more' : 'chevron_right';\r\n }\r\n\r\n #updateMatchInfo() {\r\n if (!this.#matchInfo) return;\r\n if (this.#matches.length === 0) {\r\n const hasQuery = this.#searchInput?.value?.length > 0;\r\n this.#matchInfo.textContent = hasQuery ? 'No results' : '';\r\n this.#matchInfo.classList.toggle('nb-search-bar__match-info--no-results', hasQuery);\r\n } else {\r\n this.#matchInfo.textContent = `${this.#currentIndex + 1} of ${this.#matches.length}`;\r\n this.#matchInfo.classList.remove('nb-search-bar__match-info--no-results');\r\n }\r\n }\r\n\r\n // \u2500\u2500\u2500 Search logic \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #buildQuery() {\r\n const raw = this.#searchInput.value;\r\n if (!raw) return null;\r\n\r\n let pattern;\r\n if (this.#useRegex) {\r\n try { pattern = raw; new RegExp(pattern); }\r\n catch { return null; } // invalid regex\r\n } else {\r\n pattern = raw.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n }\r\n\r\n if (this.#wholeWord) pattern = `\\\\b${pattern}\\\\b`;\r\n\r\n const flags = 'g' + (this.#caseSensitive ? '' : 'i');\r\n try { return new RegExp(pattern, flags); }\r\n catch { return null; }\r\n }\r\n\r\n #runSearch() {\r\n this.#clearAllHighlights();\r\n this.#matches = [];\r\n this.#currentIndex = -1;\r\n\r\n const query = this.#buildQuery();\r\n if (!query) {\r\n this.#updateMatchInfo();\r\n return;\r\n }\r\n\r\n const cells = this.#getCells();\r\n\r\n for (const { id } of cells) {\r\n const renderer = this.#getCellRenderer(id);\r\n if (!renderer) continue;\r\n\r\n const text = renderer.getSearchableText();\r\n if (!text) continue;\r\n\r\n query.lastIndex = 0;\r\n let m;\r\n let indexInCell = 0;\r\n while ((m = query.exec(text)) !== null) {\r\n this.#matches.push({ cellId: id, indexInCell, charOffset: m.index });\r\n indexInCell++;\r\n if (!query.global) break;\r\n }\r\n }\r\n\r\n if (this.#matches.length > 0) {\r\n this.#currentIndex = 0;\r\n this.#applyHighlights();\r\n }\r\n\r\n this.#updateMatchInfo();\r\n }\r\n\r\n // \u2500\u2500\u2500 Navigation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #navigateNext() {\r\n if (this.#matches.length === 0) return;\r\n this.#currentIndex = (this.#currentIndex + 1) % this.#matches.length;\r\n this.#applyHighlights();\r\n this.#scrollToCurrentMatch();\r\n this.#updateMatchInfo();\r\n }\r\n\r\n #navigatePrev() {\r\n if (this.#matches.length === 0) return;\r\n this.#currentIndex = (this.#currentIndex - 1 + this.#matches.length) % this.#matches.length;\r\n this.#applyHighlights();\r\n this.#scrollToCurrentMatch();\r\n this.#updateMatchInfo();\r\n }\r\n\r\n #scrollToCurrentMatch() {\r\n const match = this.#matches[this.#currentIndex];\r\n if (!match) return;\r\n this.#scrollToCell(match.cellId);\r\n\r\n // Also scroll the specific highlight into view if possible\r\n requestAnimationFrame(() => {\r\n const cellEl = this.#getCellElement(match.cellId);\r\n if (!cellEl) return;\r\n const active = cellEl.querySelector('.nb-search-match--active');\r\n if (active) active.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\r\n });\r\n }\r\n\r\n // \u2500\u2500\u2500 Highlighting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #applyHighlights() {\r\n const query = this.#buildQuery();\r\n if (!query) return;\r\n\r\n // Group matches by cell\r\n const matchesByCell = new Map();\r\n for (const m of this.#matches) {\r\n if (!matchesByCell.has(m.cellId)) matchesByCell.set(m.cellId, []);\r\n matchesByCell.get(m.cellId).push(m);\r\n }\r\n\r\n const currentMatch = this.#matches[this.#currentIndex];\r\n\r\n // Apply highlights to each cell that has matches\r\n const cells = this.#getCells();\r\n for (const { id } of cells) {\r\n const renderer = this.#getCellRenderer(id);\r\n if (!renderer) continue;\r\n\r\n const cellEl = this.#getCellElement(id);\r\n\r\n if (matchesByCell.has(id)) {\r\n const activeOffset = (currentMatch?.cellId === id)\r\n ? currentMatch.charOffset\r\n : -1;\r\n renderer.applySearchHighlights(query, activeOffset);\r\n cellEl?.classList.add('notebook-cell--search-match');\r\n cellEl?.classList.toggle('notebook-cell--search-active', currentMatch?.cellId === id);\r\n } else {\r\n renderer.clearSearchHighlights();\r\n cellEl?.classList.remove('notebook-cell--search-match', 'notebook-cell--search-active');\r\n }\r\n }\r\n }\r\n\r\n #clearAllHighlights() {\r\n const cells = this.#getCells();\r\n for (const { id } of cells) {\r\n const renderer = this.#getCellRenderer(id);\r\n renderer?.clearSearchHighlights();\r\n const cellEl = this.#getCellElement(id);\r\n cellEl?.classList.remove('notebook-cell--search-match', 'notebook-cell--search-active');\r\n }\r\n }\r\n\r\n // \u2500\u2500\u2500 Replace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #doReplace() {\r\n if (this.#matches.length === 0 || this.#currentIndex < 0) return;\r\n\r\n const match = this.#matches[this.#currentIndex];\r\n const renderer = this.#getCellRenderer(match.cellId);\r\n if (!renderer) return;\r\n\r\n const query = this.#buildQuery();\r\n if (!query) return;\r\n\r\n const replacement = this.#replaceInput.value;\r\n const success = renderer.replaceMatch(query, match.indexInCell, replacement);\r\n\r\n if (success) {\r\n // Re-run search (match count changed), try to stay near same position\r\n const wasIndex = this.#currentIndex;\r\n this.#runSearch();\r\n if (this.#matches.length > 0) {\r\n this.#currentIndex = Math.min(wasIndex, this.#matches.length - 1);\r\n this.#applyHighlights();\r\n this.#scrollToCurrentMatch();\r\n this.#updateMatchInfo();\r\n }\r\n }\r\n }\r\n\r\n #doReplaceAll() {\r\n const query = this.#buildQuery();\r\n if (!query || this.#matches.length === 0) return;\r\n\r\n const replacement = this.#replaceInput.value;\r\n\r\n // Collect unique cell IDs that have matches\r\n const cellIds = [...new Set(this.#matches.map(m => m.cellId))];\r\n let totalReplaced = 0;\r\n\r\n for (const cellId of cellIds) {\r\n const renderer = this.#getCellRenderer(cellId);\r\n if (renderer) totalReplaced += renderer.replaceAll(query, replacement);\r\n }\r\n\r\n if (totalReplaced > 0) this.#runSearch();\r\n }\r\n}\r\n", "/**\r\n * NotebookUndoManager\r\n *\r\n * Command-pattern undo/redo for notebook cell operations.\r\n *\r\n * Each command: { description: string, undo: () => (void | Promise), redo: () => (void | Promise) }\r\n *\r\n * Operations tracked by NotebookEditor:\r\n * - Cell add\r\n * - Cell delete\r\n * - Cell move (up/down, drag-reorder)\r\n * - Cell config change (debounced per-cell snapshot)\r\n */\r\nexport class NotebookUndoManager {\r\n\r\n /** @type {Array<{ description: string, undo: Function, redo: Function }>} */\r\n #undoStack = [];\r\n\r\n /** @type {Array<{ description: string, undo: Function, redo: Function }>} */\r\n #redoStack = [];\r\n\r\n /** @type {number} */\r\n #maxSize;\r\n\r\n /** @type {Function|null} Called with (canUndo: boolean, canRedo: boolean) after each change */\r\n #onStateChange;\r\n\r\n /** @type {boolean} Prevents re-entrant undo/redo */\r\n #applying = false;\r\n\r\n /**\r\n * @param {{ maxSize?: number, onStateChange?: Function }} opts\r\n */\r\n constructor({ maxSize = 100, onStateChange = null } = {}) {\r\n this.#maxSize = maxSize;\r\n this.#onStateChange = onStateChange;\r\n }\r\n\r\n // \u2500\u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n get canUndo() { return this.#undoStack.length > 0; }\r\n get canRedo() { return this.#redoStack.length > 0; }\r\n\r\n /**\r\n * Record a new command. Clears the redo stack.\r\n * Should NOT be called from inside undo/redo callbacks.\r\n *\r\n * @param {{ description: string, undo: Function, redo: Function }} command\r\n */\r\n push(command) {\r\n if (this.#applying) return; // ignore changes triggered by undo/redo\r\n this.#undoStack.push(command);\r\n if (this.#undoStack.length > this.#maxSize) {\r\n this.#undoStack.shift();\r\n }\r\n this.#redoStack = [];\r\n this.#notify();\r\n }\r\n\r\n /**\r\n * Undo the last command.\r\n * @returns {Promise<boolean>} true if something was undone\r\n */\r\n async undo() {\r\n const cmd = this.#undoStack.pop();\r\n if (!cmd) return false;\r\n this.#applying = true;\r\n try {\r\n await cmd.undo();\r\n } finally {\r\n this.#applying = false;\r\n }\r\n this.#redoStack.push(cmd);\r\n this.#notify();\r\n return true;\r\n }\r\n\r\n /**\r\n * Redo the last undone command.\r\n * @returns {Promise<boolean>} true if something was redone\r\n */\r\n async redo() {\r\n const cmd = this.#redoStack.pop();\r\n if (!cmd) return false;\r\n this.#applying = true;\r\n try {\r\n await cmd.redo();\r\n } finally {\r\n this.#applying = false;\r\n }\r\n this.#undoStack.push(cmd);\r\n this.#notify();\r\n return true;\r\n }\r\n\r\n /** Reset both stacks (e.g., after file load). */\r\n clear() {\r\n this.#undoStack = [];\r\n this.#redoStack = [];\r\n this.#notify();\r\n }\r\n\r\n // \u2500\u2500\u2500 Private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #notify() {\r\n this.#onStateChange?.(this.canUndo, this.canRedo);\r\n }\r\n}\r\n", "/**\r\n * SplitPaneContainer \u2014 horizontal split with a draggable divider.\r\n *\r\n * Manages exactly 1 or 2 child panes. When only one pane exists, the divider\r\n * is hidden and the single pane fills the container. When split, both panes\r\n * share space according to a ratio (default 50/50), adjustable via drag.\r\n *\r\n * Usage:\r\n * const split = new SplitPaneContainer();\r\n * split.mount(parentEl);\r\n * split.setPanes(leftEl); // single pane\r\n * split.setPanes(leftEl, rightEl); // split view\r\n * split.setRatio(0.6); // 60/40 split\r\n * split.unsplit(); // collapse to single pane\r\n */\r\n\r\nexport class SplitPaneContainer {\r\n /** @type {HTMLElement} */\r\n #container = null;\r\n\r\n /** @type {HTMLElement} */\r\n #pane1 = null;\r\n\r\n /** @type {HTMLElement} */\r\n #pane2 = null;\r\n\r\n /** @type {HTMLElement} */\r\n #divider = null;\r\n\r\n /** @type {number} 0..1, fraction of width for pane 1 */\r\n #ratio = 0.5;\r\n\r\n /** @type {boolean} */\r\n #isSplit = false;\r\n\r\n /** @type {Function|null} */\r\n #onRatioChanged = null;\r\n\r\n // Drag state\r\n #dragging = false;\r\n #boundOnMouseMove = null;\r\n #boundOnMouseUp = null;\r\n\r\n /**\r\n * @param {{ onRatioChanged?: (ratio: number) => void }} opts\r\n */\r\n constructor(opts = {}) {\r\n this.#onRatioChanged = opts.onRatioChanged ?? null;\r\n }\r\n\r\n get isSplit() { return this.#isSplit; }\r\n get ratio() { return this.#ratio; }\r\n\r\n mount(container) {\r\n this.#container = container;\r\n this.#container.classList.add('split-pane-container');\r\n this.#container.innerHTML = '';\r\n\r\n // Divider\r\n this.#divider = document.createElement('div');\r\n this.#divider.className = 'split-pane-divider';\r\n this.#divider.addEventListener('mousedown', (e) => this.#onDividerMouseDown(e));\r\n\r\n this.#applyLayout();\r\n }\r\n\r\n /**\r\n * Set pane elements. Pass one element for single view, two for split.\r\n * @param {HTMLElement} pane1\r\n * @param {HTMLElement} [pane2]\r\n */\r\n setPanes(pane1, pane2) {\r\n this.#pane1 = pane1;\r\n this.#pane2 = pane2 ?? null;\r\n this.#isSplit = !!pane2;\r\n this.#applyLayout();\r\n }\r\n\r\n /**\r\n * Set the split ratio (fraction for left pane).\r\n * @param {number} ratio \u2014 0.2..0.8\r\n */\r\n setRatio(ratio) {\r\n this.#ratio = Math.max(0.2, Math.min(0.8, ratio));\r\n if (this.#isSplit) this.#applySizes();\r\n }\r\n\r\n /**\r\n * Collapse to single pane (left). Returns the removed right pane element.\r\n * @returns {HTMLElement|null}\r\n */\r\n unsplit() {\r\n if (!this.#isSplit) return null;\r\n const removed = this.#pane2;\r\n this.#pane2 = null;\r\n this.#isSplit = false;\r\n this.#applyLayout();\r\n return removed;\r\n }\r\n\r\n dispose() {\r\n this.#stopDrag();\r\n this.#container = null;\r\n this.#pane1 = null;\r\n this.#pane2 = null;\r\n this.#divider = null;\r\n }\r\n\r\n // \u2500\u2500\u2500 Layout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #applyLayout() {\r\n if (!this.#container) return;\r\n this.#container.innerHTML = '';\r\n\r\n if (!this.#pane1) return;\r\n\r\n if (!this.#isSplit) {\r\n // Single pane: fills container\r\n this.#pane1.className = 'split-pane';\r\n this.#pane1.style.flex = '1 1 0';\r\n this.#pane1.style.minWidth = '0';\r\n this.#container.appendChild(this.#pane1);\r\n this.#container.classList.remove('split-pane-container--split');\r\n } else {\r\n // Split view\r\n this.#pane1.className = 'split-pane';\r\n this.#pane2.className = 'split-pane';\r\n this.#pane1.style.minWidth = '0';\r\n this.#pane2.style.minWidth = '0';\r\n\r\n this.#container.appendChild(this.#pane1);\r\n this.#container.appendChild(this.#divider);\r\n this.#container.appendChild(this.#pane2);\r\n this.#container.classList.add('split-pane-container--split');\r\n\r\n this.#applySizes();\r\n }\r\n }\r\n\r\n #applySizes() {\r\n if (!this.#pane1 || !this.#pane2) return;\r\n // Use flex-grow proportional to ratio\r\n const r = this.#ratio;\r\n this.#pane1.style.flex = `${r} 1 0`;\r\n this.#pane2.style.flex = `${1 - r} 1 0`;\r\n }\r\n\r\n // \u2500\u2500\u2500 Divider drag \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n #onDividerMouseDown(e) {\r\n if (e.button !== 0) return;\r\n e.preventDefault();\r\n this.#dragging = true;\r\n this.#divider.classList.add('split-pane-divider--active');\r\n document.body.style.cursor = 'col-resize';\r\n\r\n // Prevent text selection and iframes capturing mouse\r\n document.body.style.userSelect = 'none';\r\n this.#container.querySelectorAll('iframe').forEach(f => f.style.pointerEvents = 'none');\r\n\r\n this.#boundOnMouseMove = (e) => this.#onMouseMove(e);\r\n this.#boundOnMouseUp = () => this.#onMouseUp();\r\n document.addEventListener('mousemove', this.#boundOnMouseMove);\r\n document.addEventListener('mouseup', this.#boundOnMouseUp);\r\n }\r\n\r\n #onMouseMove(e) {\r\n if (!this.#dragging || !this.#container) return;\r\n const rect = this.#container.getBoundingClientRect();\r\n const dividerWidth = this.#divider.offsetWidth;\r\n const usable = rect.width - dividerWidth;\r\n if (usable <= 0) return;\r\n\r\n const x = e.clientX - rect.left - dividerWidth / 2;\r\n const ratio = Math.max(0.2, Math.min(0.8, x / usable));\r\n this.#ratio = ratio;\r\n this.#applySizes();\r\n }\r\n\r\n #onMouseUp() {\r\n this.#stopDrag();\r\n this.#onRatioChanged?.(this.#ratio);\r\n }\r\n\r\n #stopDrag() {\r\n if (!this.#dragging) return;\r\n this.#dragging = false;\r\n this.#divider?.classList.remove('split-pane-divider--active');\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n this.#container?.querySelectorAll('iframe').forEach(f => f.style.pointerEvents = '');\r\n document.removeEventListener('mousemove', this.#boundOnMouseMove);\r\n document.removeEventListener('mouseup', this.#boundOnMouseUp);\r\n this.#boundOnMouseMove = null;\r\n this.#boundOnMouseUp = null;\r\n }\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["e"]
7
+ }