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.
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/THIRD_PARTY_LICENSES.md +53 -0
- package/css/base.css +3439 -0
- package/css/flexdesk.css +5797 -0
- package/css/overrides.css +2349 -0
- package/css/reset.css +46 -0
- package/css/tokens.css +137 -0
- package/dist/charts.js +780 -0
- package/dist/charts.js.map +7 -0
- package/dist/chunk-3PHCPZHT.js +222 -0
- package/dist/chunk-3PHCPZHT.js.map +7 -0
- package/dist/chunk-CT4YXXLP.js +1770 -0
- package/dist/chunk-CT4YXXLP.js.map +7 -0
- package/dist/chunk-DRYCDMEG.js +2217 -0
- package/dist/chunk-DRYCDMEG.js.map +7 -0
- package/dist/chunk-DVU44T77.js +855 -0
- package/dist/chunk-DVU44T77.js.map +7 -0
- package/dist/chunk-FL5KFNQH.js +640 -0
- package/dist/chunk-FL5KFNQH.js.map +7 -0
- package/dist/chunk-FOOS3T5L.js +117 -0
- package/dist/chunk-FOOS3T5L.js.map +7 -0
- package/dist/chunk-JYWURG5T.js +32 -0
- package/dist/chunk-JYWURG5T.js.map +7 -0
- package/dist/chunk-TLZUUFOE.js +276 -0
- package/dist/chunk-TLZUUFOE.js.map +7 -0
- package/dist/chunk-UCJ2WD4D.js +625 -0
- package/dist/chunk-UCJ2WD4D.js.map +7 -0
- package/dist/chunk-WVFGV5FT.js +205 -0
- package/dist/chunk-WVFGV5FT.js.map +7 -0
- package/dist/core.js +1098 -0
- package/dist/core.js.map +7 -0
- package/dist/editor.js +1661 -0
- package/dist/editor.js.map +7 -0
- package/dist/flexdesk.css +5797 -0
- package/dist/host.js +132 -0
- package/dist/host.js.map +7 -0
- package/dist/reset.css +46 -0
- package/dist/tile_registry-6WZPTUZV.js +28 -0
- package/dist/tile_registry-6WZPTUZV.js.map +7 -0
- package/dist/tiles.js +2068 -0
- package/dist/tiles.js.map +7 -0
- package/dist/tokens.css +137 -0
- package/dist/widgets.js +5438 -0
- package/dist/widgets.js.map +7 -0
- package/dist/wm.js +4830 -0
- package/dist/wm.js.map +7 -0
- package/package.json +80 -0
- package/src/charts/chart_types.js +699 -0
- package/src/charts/data_series_plot_window.js +761 -0
- package/src/charts/downsample.js +119 -0
- package/src/charts/plot_config.js +176 -0
- package/src/charts/plot_popout_window.js +1560 -0
- package/src/charts/plotly_wrapper.js +432 -0
- package/src/core/event_bus.js +230 -0
- package/src/core/logging.js +300 -0
- package/src/core/settings.js +813 -0
- package/src/core/state_guard.js +382 -0
- package/src/core/state_guard_config.js +309 -0
- package/src/core/state_machine.js +258 -0
- package/src/editor/editor_pane.js +264 -0
- package/src/editor/monaco_editor_factory.js +449 -0
- package/src/editor/monaco_loader.js +74 -0
- package/src/editor/notebook_search.js +460 -0
- package/src/editor/notebook_tab_bar.js +456 -0
- package/src/editor/notebook_undo_manager.js +108 -0
- package/src/editor/split_pane_container.js +197 -0
- package/src/help/help_modal.js +409 -0
- package/src/help/help_registry.js +65 -0
- package/src/host/host.js +69 -0
- package/src/host/pywebview_host.js +133 -0
- package/src/tiles/config_schema.js +256 -0
- package/src/tiles/layout_persistence.js +662 -0
- package/src/tiles/tile_base.js +785 -0
- package/src/tiles/tile_grid.js +905 -0
- package/src/tiles/tile_registry.js +136 -0
- package/src/tiling/command_palette.js +328 -0
- package/src/tiling/content_registry.js +110 -0
- package/src/tiling/desktops.js +133 -0
- package/src/tiling/entity_sources.js +179 -0
- package/src/tiling/keymap.js +156 -0
- package/src/tiling/kind_taxonomy.js +172 -0
- package/src/tiling/landing_table.js +717 -0
- package/src/tiling/loading_overlay.js +33 -0
- package/src/tiling/nav_panel.js +142 -0
- package/src/tiling/page_factory.js +215 -0
- package/src/tiling/panel_keys.js +145 -0
- package/src/tiling/shell.js +437 -0
- package/src/tiling/tile_breadcrumb.js +222 -0
- package/src/tiling/tile_renderer.js +459 -0
- package/src/tiling/tile_tab_menu.js +340 -0
- package/src/tiling/tile_tree.js +880 -0
- package/src/tiling/wm.js +1352 -0
- package/src/ui/base/component_base.js +30 -0
- package/src/ui/base/controller_base.js +48 -0
- package/src/ui/base/page_base.js +102 -0
- package/src/ui/components/about_dialog.js +224 -0
- package/src/ui/components/action_dropdown.js +389 -0
- package/src/ui/components/attribute_list_editor.js +652 -0
- package/src/ui/components/autocomplete_field.js +732 -0
- package/src/ui/components/computing_status_window.js +81 -0
- package/src/ui/components/confirm_dialog.js +307 -0
- package/src/ui/components/context_menu.js +87 -0
- package/src/ui/components/data_table.js +2228 -0
- package/src/ui/components/detail_header.js +177 -0
- package/src/ui/components/drag_reorder.js +0 -0
- package/src/ui/components/gallery_picker.js +147 -0
- package/src/ui/components/inline_renamer.js +129 -0
- package/src/ui/components/managed_window.js +804 -0
- package/src/ui/components/modal.js +512 -0
- package/src/ui/components/notification_history.js +264 -0
- package/src/ui/components/slide_out_panel.js +185 -0
- package/src/ui/components/slider_field.js +122 -0
- package/src/ui/components/sortable_list.js +309 -0
- package/src/ui/components/table_state_store.js +81 -0
- package/src/ui/components/toast.js +59 -0
- package/src/ui/components/tree_view.js +460 -0
- package/src/ui/components/window_taskbar.js +143 -0
- package/src/ui/controllers/panel_state_machine.js +634 -0
- package/src/ui/controllers/window_chrome_controller.js +659 -0
- package/src/ui/notification_center.js +576 -0
- package/src/ui/utils/overlay_scrollbar.js +492 -0
- package/src/ui/utils/raf_resize_observer.js +31 -0
- package/src/ui/utils/tooltip_service.js +406 -0
package/dist/wm.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/tiling/command_palette.js", "../src/tiling/content_registry.js", "../src/tiling/tile_tree.js", "../src/tiling/desktops.js", "../src/tiling/entity_sources.js", "../src/tiling/keymap.js", "../src/tiling/kind_taxonomy.js", "../src/tiling/panel_keys.js", "../src/tiling/landing_table.js", "../src/tiling/loading_overlay.js", "../src/tiling/nav_panel.js", "../src/tiling/tile_breadcrumb.js", "../src/tiling/page_factory.js", "../src/tiling/tile_renderer.js", "../src/tiling/wm.js", "../src/tiling/tile_tab_menu.js", "../src/tiling/shell.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * command_palette.js \u2014 Ctrl+K center popup.\n *\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 search\u2026 \u2502\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n * \u2502 [chip] [chip] [chip] [chip] \u2502 top-nav shortcut chips\n * \u2502 [chip] [chip] \u2502\n * \u2502 \u2502\n * \u2502 \u2610 left nav \u2610 right panel \u2610 bottom \u2502 panel toggles\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n * \u2502 matched entity rows\u2026 \u2502 search results\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n *\n * The chips are the injected taxonomy's top-nav kinds; clicking one\n * loads it into the primary tile. The toggles flip the corresponding\n * panel-tile on/off. Typing searches the injected entity catalog\n * (fetched lazily on first open).\n */\n\nimport { HelpModal } from '../help/help_modal.js';\n\nconst ROOT_ID = 'twm-cmdpal';\n\n// Non-entity commands surfaced in the palette's search results. They\n// carry an `action` so `commit()` runs them instead of opening a tile.\nconst STATIC_COMMANDS = [\n { kind: 'command', id: 'shortcuts', label: 'Keyboard shortcuts',\n hint: 'Show all key bindings (?)', icon: 'keyboard',\n action: () => HelpModal.open('keyboard-shortcuts') },\n];\n\n/** @param taxonomy injected ontology \u2014 supplies the chip strip + row icons\n * @param catalog injected entity catalog \u2014 supplies the searchable rows\n * @param placeholder input placeholder. It names the embedder's entity types\n * (\"try foo:bar\"), so the embedder owns the string. */\nexport function createCommandPalette({ wm, api, taxonomy, catalog, placeholder = 'Search\u2026' }) {\n if (!taxonomy) throw new Error('createCommandPalette: a taxonomy is required');\n if (!catalog) throw new Error('createCommandPalette: an entity catalog is required');\n let overlay = null;\n let entities = [];\n\n const isOpen = () => !!overlay;\n const close = () => {\n if (!overlay) return;\n overlay.remove();\n overlay = null;\n };\n const toggle = () => { isOpen() ? close() : open(); };\n\n const open = async () => {\n if (overlay) return;\n overlay = document.createElement('div');\n overlay.id = ROOT_ID;\n overlay.className = 'twm-cmdpal-overlay';\n overlay.innerHTML = _markup(taxonomy, placeholder);\n document.body.appendChild(overlay);\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) close();\n });\n\n const input = overlay.querySelector('.twm-cmdpal__input');\n const list = overlay.querySelector('[data-role=\"list\"]');\n const chipSlot = overlay.querySelector('[data-role=\"type-chip\"]');\n const chips = overlay.querySelectorAll('[data-shortcut]');\n const toggles = overlay.querySelectorAll('[data-toggle]');\n\n // Reflect current panel state in toggle buttons.\n for (const btn of toggles) {\n const which = btn.dataset.toggle;\n btn.classList.toggle('twm-chip--on', wm.isPanelOpen(which));\n }\n\n chips.forEach((btn) => btn.addEventListener('click', () => {\n const kind = btn.dataset.shortcut;\n wm.openInPrimary(kind);\n close();\n }));\n toggles.forEach((btn) => btn.addEventListener('click', () => {\n const which = btn.dataset.toggle;\n wm.togglePanel(which);\n btn.classList.toggle('twm-chip--on', wm.isPanelOpen(which));\n }));\n\n // Scoped-search state. Typing `<prefix>:` converts the prefix\n // into a visual chip that lives to the left of the input;\n // subsequent typing only matches entities whose navKind is in\n // the chip's set. Cleared by clicking the chip's \u00D7, by pressing\n // Backspace when the input is empty, or by Esc (which closes the\n // palette). A prefix can resolve to MULTIPLE navKinds, so the\n // user's mental model can win over the embedder's internal\n // taxonomy. The resolver lives on the injected catalog, next to\n // the alias table it consults.\n let filtered = [];\n let active = 0;\n let typeFilter = null; // null | string[] (navKinds)\n let typeFilterLabel = null; // chip text, derived from the resolved kinds\n\n const renderChip = () => {\n if (!typeFilter) {\n chipSlot.innerHTML = '';\n return;\n }\n // Display: first kind's icon/label from the taxonomy. A\n // multi-kind alias gets the leading kind's label, which\n // reads as narrower than the alias actually is \u2014 so we\n // override with the typed alias (passed from `refilter`)\n // when it carries information the taxonomy can't infer.\n const head = typeFilter[0];\n const meta = taxonomy.meta(head);\n const label = typeFilterLabel || meta?.label || head;\n chipSlot.innerHTML = `\n <span class=\"twm-cmdpal__type-chip\" title=\"Filtering by ${_esc(label)} (${typeFilter.length} kind${typeFilter.length === 1 ? '' : 's'})\">\n <span class=\"material-symbols-outlined twm-cmdpal__type-chip-icon\">${meta?.icon || 'arrow_right'}</span>\n <span class=\"twm-cmdpal__type-chip-label\">${_esc(label)}</span>\n <button type=\"button\" class=\"twm-cmdpal__type-chip-x\"\n data-action=\"clear-type\"\n aria-label=\"Clear type filter\">\u00D7</button>\n </span>\n `;\n chipSlot.querySelector('[data-action=\"clear-type\"]')\n ?.addEventListener('click', (ev) => {\n ev.preventDefault();\n typeFilter = null;\n typeFilterLabel = null;\n renderChip();\n input.focus();\n refilter();\n });\n };\n\n const render = () => {\n list.innerHTML = filtered.slice(0, 200).map((e, i) => `\n <div class=\"twm-cmdpal__item${i === active ? ' twm-cmdpal__item--active' : ''}\"\n data-idx=\"${i}\">\n <span class=\"material-symbols-outlined twm-cmdpal__icon\">${e.icon || 'arrow_right'}</span>\n <span class=\"twm-cmdpal__label\">${_esc(e.label || e.id)}</span>\n <span class=\"twm-cmdpal__kind\">${e.kind}</span>\n <span class=\"twm-cmdpal__hint\">${_esc(e.hint || '')}</span>\n </div>\n `).join('') || '';\n list.querySelectorAll('[data-idx]').forEach((el) => {\n el.addEventListener('click', () => commit(Number(el.dataset.idx)));\n });\n };\n const commit = (i) => {\n const pick = filtered[i];\n if (!pick) return;\n close();\n if (pick.action) { try { pick.action(); } catch (err) { console.error(err); } return; }\n wm.openInPrimary(pick.kind, pick.props || { id: pick.id, label: pick.label });\n };\n\n /** Look for a `<prefix>:` at the start of the raw input. If the\n * prefix resolves to one or more known kinds, promote it to\n * the visual chip and strip it from the input field. Returns\n * true when a chip was set so the caller can decide whether\n * to re-render. */\n const tryConsumePrefix = () => {\n if (typeFilter) return false;\n const m = input.value.match(/^([a-zA-Z][a-zA-Z0-9_-]*):/);\n if (!m) return false;\n const kinds = catalog.resolveTypePrefix(m[1]);\n if (!kinds || kinds.length === 0) return false;\n typeFilter = kinds;\n typeFilterLabel = _titleCase(m[1]);\n input.value = input.value.slice(m[0].length);\n renderChip();\n return true;\n };\n\n const refilter = () => {\n tryConsumePrefix();\n const q = input.value.trim().toLowerCase();\n const filterSet = typeFilter ? new Set(typeFilter) : null;\n const pool = filterSet\n ? entities.filter((e) => filterSet.has(e.kind))\n : entities;\n if (!q) {\n // Scoped + empty query \u2192 list every entity of that\n // kind so the user sees what's available. Unscoped +\n // empty query \u2192 blank list (matches the old behavior\n // where typing nothing meant nothing).\n filtered = typeFilter\n ? pool.slice().sort((a, b) =>\n String(a.label || a.id).localeCompare(b.label || b.id))\n : [];\n } else {\n filtered = _search(pool, q);\n }\n active = 0;\n render();\n };\n input.addEventListener('input', refilter);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n active = Math.min(filtered.length - 1, active + 1);\n render();\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n active = Math.max(0, active - 1);\n render();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n commit(active);\n } else if (e.key === 'Escape') {\n close();\n } else if (e.key === 'Backspace' && input.value === '' && typeFilter) {\n // Empty input + active chip \u2192 consume Backspace to drop\n // the chip. Same idiom as Gmail / Linear / VS Code's\n // command palette: the chip behaves like a token before\n // the caret.\n e.preventDefault();\n typeFilter = null;\n typeFilterLabel = null;\n renderChip();\n refilter();\n }\n });\n input.focus();\n\n // Commands are searchable instantly; entity rows are lazy-loaded\n // \u2014 the palette stays usable for shortcuts/commands while we wait.\n // The set is rebuilt on every open so the palette reflects\n // entities the user just added this session (cheap; the catalog\n // runs every source in parallel).\n entities = _decorateIcons(STATIC_COMMANDS.slice(), taxonomy);\n if (api) {\n try {\n entities = _decorateIcons(\n [...STATIC_COMMANDS, ...await catalog.loadAll(api)], taxonomy);\n if (input.value) refilter();\n } catch (err) {\n console.warn('[cmdpal] entity load failed', err);\n }\n }\n };\n\n return { open, close, toggle, isOpen };\n}\n\nfunction _markup(taxonomy, placeholder) {\n const chips = taxonomy.topNavEntries().map((k) => `\n <button class=\"twm-chip\" data-shortcut=\"${k.kind}\">\n <span class=\"material-symbols-outlined\">${k.icon}</span>\n ${k.label}\n </button>\n `).join('');\n return `\n <div class=\"twm-cmdpal\" role=\"dialog\" aria-label=\"Command palette\">\n <div class=\"twm-cmdpal__inputrow\">\n <span class=\"twm-cmdpal__type-chip-slot\" data-role=\"type-chip\"></span>\n <input type=\"text\" class=\"twm-cmdpal__input\"\n placeholder=\"${_esc(placeholder)}\"\n autocomplete=\"off\" />\n </div>\n <div class=\"twm-cmdpal__chips\">${chips}</div>\n <div class=\"twm-cmdpal__toggles\">\n <button class=\"twm-chip\" data-toggle=\"left\">\n <span class=\"material-symbols-outlined\">menu</span>\n Left nav\n </button>\n <button class=\"twm-chip\" data-toggle=\"right\">\n <span class=\"material-symbols-outlined\">dock_to_left</span>\n Right panel\n </button>\n <button class=\"twm-chip\" data-toggle=\"bottom\">\n <span class=\"material-symbols-outlined\">dock_to_bottom</span>\n Bottom panel\n </button>\n </div>\n <div class=\"twm-cmdpal__list\" data-role=\"list\"></div>\n <div class=\"twm-cmdpal__footer\">\n <span><kbd>\u2191</kbd><kbd>\u2193</kbd> navigate</span>\n <span><kbd>Enter</kbd> open</span>\n <span><kbd>Esc</kbd> close</span>\n </div>\n </div>\n `;\n}\n\n/** Attach an icon per row by consulting the injected taxonomy. Keeps the\n * palette and breadcrumb visually consistent: one source of truth for\n * what icon represents a given kind. */\nfunction _decorateIcons(rows, taxonomy) {\n return rows.map((r) => {\n if (r.icon) return r;\n const meta = taxonomy.meta(r.kind);\n return { ...r, icon: meta?.icon || 'arrow_right' };\n });\n}\n\nfunction _search(entities, q) {\n const scored = [];\n for (const e of entities) {\n const id = String(e.id || '').toLowerCase();\n const label = String(e.label || '').toLowerCase();\n const hint = String(e.hint || '').toLowerCase();\n let r;\n if (id === q || label === q) r = 0;\n else if (id.startsWith(q)) r = 1;\n else if (label.startsWith(q)) r = 2;\n else if (id.includes(q)) r = 3;\n else if (label.includes(q)) r = 4;\n else if (hint.includes(q)) r = 5;\n else continue;\n scored.push({ e, r });\n }\n scored.sort((a, b) => a.r - b.r || a.e.label.localeCompare(b.e.label));\n return scored.map((x) => x.e);\n}\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n}\n\n/** Display form for a typed prefix: capitalise the first letter, and\n * swap any underscores/hyphens for spaces so a multi-word alias reads\n * as prose. Used for the scope chip's label, so it reflects what the\n * user actually typed rather than the kind it resolved to. */\nfunction _titleCase(s) {\n const str = String(s || '').replace(/[_-]+/g, ' ').trim();\n if (!str) return '';\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n", "/**\n * content_registry.js \u2014 maps a content kind string to a factory that\n * mounts that content into a tile body element.\n *\n * A content factory has the shape:\n *\n * (hostEl, props, ctx) -> { destroy?(), title?, ... }\n *\n * The tile renderer calls the factory once when the leaf is first\n * mounted with a given (kind, props) pair, and `destroy()` on unmount.\n *\n * \u2500\u2500 ONE REGISTRY PER SHELL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * This module used to hold a module-level `Map` plus a `register(kind, fn)`\n * export. Two problems, both structural:\n *\n * 1. Two shells on one page shared their kind -> factory table, so a\n * foreign-ontology shell silently inherited the other embedder's\n * factories. A module singleton is the global we are removing,\n * wearing a hat.\n * 2. `register()` could be called AFTER the first mount. A leaf mounted\n * against a missing factory renders the placeholder and the renderer\n * caches that DOM per (kind, props) \u2014 a later registration invalidates\n * nothing, so an entire restored session stays wrong.\n *\n * `createContentRegistry(map)` fixes both: the map is a REQUIRED\n * constructor argument of `createShell()`, validated up-front, and frozen\n * before the WM is built. There is nothing left to call late.\n *\n * This module knows no kind names but one \u2014 `window-placeholder`, which is\n * the WM's OWN content (shown in a tile whose content was promoted into a\n * managed window). Defaulting it here means an embedder cannot forget it\n * and get a \"no factory registered\" tile the first time it promotes.\n */\n\nexport const PLACEHOLDER_KIND = 'window-placeholder';\n\n/** Shown in a tile while its content lives in a managed window. Pure\n * `twm-*` markup; clicking the button demotes the window back. */\nfunction windowPlaceholderFactory(hostEl, props, ctx) {\n hostEl.innerHTML = `\n <div class=\"twm-window-placeholder\">\n <span class=\"material-symbols-outlined twm-window-placeholder__icon\">open_in_new</span>\n <div class=\"twm-window-placeholder__title\">${_esc(props.originalTitle || props.originalKind || 'content')}</div>\n <div class=\"twm-window-placeholder__hint\">is open in a managed window</div>\n <button class=\"twm-window-placeholder__btn\" data-action=\"bring-back\">\n Bring back to this tile\n </button>\n </div>\n `;\n hostEl.querySelector('[data-action=\"bring-back\"]')?.addEventListener('click', () => {\n ctx.wm?.bringBackWindow?.(props.windowId);\n });\n return { title: `${props.originalTitle || props.originalKind} (window)` };\n}\n\n/**\n * Build a shell-scoped content registry.\n *\n * @param {Object<string, Function>} map kind -> content factory\n * @returns {{ has(kind): boolean, mount(kind, hostEl, props, ctx): object }}\n */\nexport function createContentRegistry(map = {}) {\n if (!map || typeof map !== 'object') {\n throw new TypeError('createContentRegistry: `content` must be an object of kind -> factory');\n }\n for (const [kind, factory] of Object.entries(map)) {\n if (typeof factory !== 'function') {\n throw new TypeError(\n `createContentRegistry: factory for \"${kind}\" must be a function`);\n }\n }\n const factories = new Map(Object.entries(map));\n if (!factories.has(PLACEHOLDER_KIND)) {\n factories.set(PLACEHOLDER_KIND, windowPlaceholderFactory);\n }\n\n return Object.freeze({\n has: (kind) => factories.has(kind),\n\n mount: (kind, hostEl, props, ctx) => {\n const factory = factories.get(kind) || _placeholder(kind);\n try {\n return factory(hostEl, props || {}, ctx || {}) || {};\n } catch (err) {\n console.error('[content_registry] mount failed for', kind, err);\n hostEl.innerHTML =\n `<div class=\"twm-tile-error\">Mount failed: ${err && err.message || err}</div>`;\n return {};\n }\n },\n });\n}\n\nfunction _placeholder(kind) {\n return (hostEl) => {\n hostEl.innerHTML = `\n <div class=\"tile-placeholder\">\n <div class=\"tile-placeholder__title\">${kind}</div>\n <div class=\"tile-placeholder__hint\">no factory registered yet</div>\n </div>\n `;\n return { title: kind };\n };\n}\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => (\n { '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[c]\n ));\n}\n", "/**\n * tile_tree.js \u2014 i3/sway-style binary tree for the tiling window manager.\n *\n * A workspace is one tree of Node objects:\n *\n * Node = { id, kind: 'split' | 'leaf', parentId, ... }\n * Split: { dir: 'h' | 'v', children: [childId, ...], sizes: [number, ...] }\n * Leaf: { tabs: [{kind, props, title}], activeTabIdx, content, title }\n *\n * **Tabs**. Each leaf carries an ordered list of tab specs and an active\n * index. The active tab is mirrored onto the legacy `content` /\n * `title` fields so the rest of the codebase (renderer, WM,\n * breadcrumb, navigateBack, \u2026) keeps reading `leaf.content.kind`\n * unchanged. Single-tab leaves behave identically to today; multi-tab\n * leaves expose a small TabBar at the bottom of the tile.\n *\n * The tree carries no DOM. A separate renderer maps it to flex containers.\n * Mutations return new node-id arrays; consumers re-render after each call.\n */\n\nlet _idCounter = 1;\nfunction _newId(prefix) { return `${prefix}-${_idCounter++}`; }\n\nfunction _isPanel(leaf) {\n return String(leaf?.content?.kind || '').startsWith('panel:');\n}\n\n/** Mirror the active tab back onto `leaf.content` / `leaf.title` so the\n * rest of the system sees no diff. Called after every tab mutation. */\nfunction _syncActiveTab(leaf) {\n if (!leaf || leaf.kind !== 'leaf') return;\n const tabs = leaf.tabs || [];\n if (tabs.length === 0) {\n leaf.content = null;\n leaf.title = leaf.title || '';\n leaf.activeTabIdx = 0;\n return;\n }\n if (leaf.activeTabIdx == null\n || leaf.activeTabIdx < 0\n || leaf.activeTabIdx >= tabs.length) {\n leaf.activeTabIdx = Math.max(0, Math.min(tabs.length - 1, leaf.activeTabIdx || 0));\n }\n const t = tabs[leaf.activeTabIdx];\n leaf.content = { kind: t.kind, props: t.props || {} };\n leaf.title = t.title || t.kind || '';\n}\n\nexport function makeLeaf({ content = null, title = '' } = {}) {\n const leaf = {\n id: _newId('leaf'),\n kind: 'leaf',\n parentId: null,\n // Tabs are the source of truth; content/title mirror tabs[active].\n tabs: content\n ? [{ kind: content.kind, props: content.props || {}, title: title || content.kind || '' }]\n : [],\n activeTabIdx: content ? 0 : 0,\n content,\n title,\n // Per-top-nav-page tab archive. When a top-nav button switches\n // this leaf to another page, the current `tabs` + `activeTabIdx`\n // get stashed here under the LEAVING page's key, and the target\n // page's archived list (if any) gets restored. This is what\n // makes a tile remember its tab set when the user clicks away to\n // another top-nav page and back. Keyed by top-nav kind \u2014 see the\n // taxonomy's `topNavFor`.\n pageTabs: {},\n };\n _syncActiveTab(leaf);\n return leaf;\n}\n\nexport function makeSplit({ dir = 'h', children = [], sizes = null } = {}) {\n return {\n id: _newId('split'),\n kind: 'split',\n parentId: null,\n dir,\n children: children.slice(),\n sizes: sizes ? sizes.slice() : children.map(() => 1),\n };\n}\n\n/**\n * TileTree \u2014 holds the node table and root, exposes mutation operations.\n * Every mutation operates by node id; the tree never hands out raw nodes\n * to callers (defensive copies via .get()).\n */\nexport class TileTree {\n constructor() {\n this.nodes = new Map();\n this.rootId = null;\n this.focusedLeafId = null;\n // Stack of recently-focused leaves. New content loads target the\n // top of this stack \u2014 i.e. the last leaf the user focused.\n this.focusStack = [];\n }\n\n // \u2500\u2500 Read helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 get(id) { return this.nodes.get(id) || null; }\n root() { return this.rootId ? this.get(this.rootId) : null; }\n focused() { return this.focusedLeafId ? this.get(this.focusedLeafId) : null; }\n\n leaves() {\n const out = [];\n const walk = (id) => {\n const n = this.get(id);\n if (!n) return;\n if (n.kind === 'leaf') out.push(n);\n else n.children.forEach(walk);\n };\n if (this.rootId) walk(this.rootId);\n return out;\n }\n\n // \u2500\u2500 Construction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 setRoot(node) {\n this._register(node);\n this.rootId = node.id;\n if (node.kind === 'leaf') {\n this.focus(node.id);\n }\n return node.id;\n }\n\n _register(node) {\n this.nodes.set(node.id, node);\n if (node.kind === 'split') {\n for (const cid of node.children) {\n const c = this.get(cid);\n if (c) c.parentId = node.id;\n }\n }\n }\n\n // \u2500\u2500 Focus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 focus(leafId) {\n if (!this.nodes.has(leafId)) return;\n const node = this.get(leafId);\n if (node.kind !== 'leaf') return;\n this.focusedLeafId = leafId;\n this.focusStack = this.focusStack.filter((id) => id !== leafId);\n this.focusStack.unshift(leafId);\n }\n\n /** The leaf where \"open content\" should land \u2014 top of focus stack,\n * skipping panel:* tiles which are chrome, not content. */\n primaryLeafId() {\n for (const id of this.focusStack) {\n const n = this.nodes.get(id);\n if (n && n.kind === 'leaf' && !_isPanel(n)) return id;\n }\n for (const leaf of this.leaves()) {\n if (!_isPanel(leaf)) return leaf.id;\n }\n return null;\n }\n\n // \u2500\u2500 Mutations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Replace the leaf's tab list with a single tab carrying `content`.\n * Closes any existing tabs in that leaf \u2014 this is the \"open in\n * place\" / \"replace tile\" path that the WM has always used. */\n setLeafContent(leafId, content, title = '') {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n if (content) {\n n.tabs = [{\n kind: content.kind,\n props: content.props || {},\n title: title || content.kind || '',\n }];\n n.activeTabIdx = 0;\n } else {\n n.tabs = [];\n n.activeTabIdx = 0;\n }\n _syncActiveTab(n);\n if (title) n.title = title;\n return true;\n }\n\n /** Page-aware swap: archive the leaf's current tab list under its\n * current top-nav key, then restore the target top-nav's archived\n * list (or initialize one with the requested kind/props). Used\n * by top-nav / palette navigation so each top-nav page keeps its\n * own tab set across page switches.\n *\n * Parameters:\n * leafId The primary leaf.\n * target { kind, props, title } \u2014 what the user clicked.\n * currentTopNav Top-nav of the leaf's current page (may be null).\n * targetTopNav Top-nav of the target kind (must be set).\n *\n * When `currentTopNav === targetTopNav` (already on the right\n * page), the swap is skipped and we either focus an existing\n * matching tab or replace the active one. This is what makes\n * clicking the top-nav button for the page you're already on\n * feel like \"Home for this page\" without resetting tabs. */\n swapToPage(leafId, target, currentTopNav, targetTopNav, opts = {}) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n if (!target || !target.kind) return false;\n n.pageTabs = n.pageTabs || {};\n const recordHistory = opts.recordHistory !== false;\n\n // Helper: mirror what replaceActiveTabContent does \u2014 push the\n // outgoing tab onto the (incoming) tab's history stack so\n // Backspace can walk back. `extra` is an optional annotation\n // (e.g. `{ topNav: currentTopNav }`) for cross-page entries so\n // navigateBack can re-route via swapToPage when popping.\n const _pushPrev = (history, prev, next, extra) => {\n if (!recordHistory || !prev || !prev.kind) return history;\n const last = history[history.length - 1];\n const sameAsPrev = last\n && last.kind === prev.kind\n && String(last.props?.id ?? '') === String(prev.props?.id ?? '');\n const sameAsTarget = next\n && prev.kind === next.kind\n && String(prev.props?.id ?? '') === String(next.props?.id ?? '');\n if (!sameAsPrev && !sameAsTarget) {\n history.push({\n kind: prev.kind,\n props: prev.props || {},\n title: prev.title || '',\n ...(extra || {}),\n });\n }\n return history;\n };\n\n const same = currentTopNav && currentTopNav === targetTopNav;\n if (same) {\n const tabs = n.tabs || [];\n const matchIdx = tabs.findIndex((t) =>\n t.kind === target.kind\n && String(t.props?.id ?? '') === String(target.props?.id ?? ''));\n if (matchIdx >= 0) {\n n.activeTabIdx = matchIdx;\n } else if (tabs.length === 0) {\n n.tabs = [{\n kind: target.kind,\n props: target.props || {},\n title: target.title || target.kind,\n history: [],\n }];\n n.activeTabIdx = 0;\n } else {\n const prev = tabs[n.activeTabIdx];\n const history = Array.isArray(prev?.history) ? prev.history : [];\n _pushPrev(history, prev, target, null);\n tabs[n.activeTabIdx] = {\n kind: target.kind,\n props: target.props || {},\n title: target.title || target.kind,\n history,\n };\n }\n _syncActiveTab(n);\n return true;\n }\n\n // Snapshot the source tab BEFORE archiving \u2014 used to seed the\n // target tab's history with a cross-page back entry.\n const srcTabs = Array.isArray(n.tabs) ? n.tabs : [];\n const srcActive = srcTabs[n.activeTabIdx];\n const sourceEntry = (currentTopNav && srcActive?.kind) ? {\n kind: srcActive.kind,\n props: srcActive.props || {},\n title: srcActive.title || '',\n topNav: currentTopNav,\n } : null;\n\n // Archive the current page \u2014 preserve `history` so the user\n // doesn't lose in-tile back depth when they walk away and\n // return to this page.\n if (currentTopNav && srcTabs.length > 0) {\n // Don't archive transient tabs (add-row forms etc.) \u2014 they\n // shouldn't reappear when the user returns to this page.\n const archived = srcTabs\n .filter((t) => !t.transient)\n .map((t) => ({\n kind: t.kind, props: { ...(t.props || {}) }, title: t.title,\n history: Array.isArray(t.history) ? t.history.slice() : [],\n }));\n n.pageTabs[currentTopNav] = {\n tabs: archived,\n activeTabIdx: Math.max(0, Math.min(archived.length - 1, n.activeTabIdx || 0)),\n };\n }\n\n // Restore the target page, or initialize fresh.\n const saved = n.pageTabs[targetTopNav];\n if (saved && Array.isArray(saved.tabs) && saved.tabs.length > 0) {\n n.tabs = saved.tabs.map((t) => ({\n kind: t.kind, props: { ...(t.props || {}) }, title: t.title,\n history: Array.isArray(t.history) ? t.history.slice() : [],\n }));\n n.activeTabIdx = Math.max(0,\n Math.min(n.tabs.length - 1, saved.activeTabIdx || 0));\n // The caller asked for a specific entity (props.id) OR for a\n // page kind that ISN'T the nav category itself (e.g. `settings`\n // lives under the `home` topNav). In both cases we must surface\n // the requested target rather than silently showing whatever\n // the restored page happened to hold. A bare top-nav click\n // (target.kind === targetTopNav, no id) falls through and just\n // restores the saved tabs as-is.\n const wantsTarget = target.props?.id != null\n || target.kind !== targetTopNav;\n if (wantsTarget) {\n const wantId = target.props?.id != null;\n const matchIdx = n.tabs.findIndex((t) =>\n t.kind === target.kind\n && (!wantId\n || String(t.props?.id ?? '') === String(target.props.id)));\n if (matchIdx >= 0) {\n n.activeTabIdx = matchIdx;\n } else {\n const history = [];\n if (sourceEntry) _pushPrev(history, sourceEntry, target, { topNav: currentTopNav });\n n.tabs.push({\n kind: target.kind,\n props: target.props || {},\n title: target.title || target.kind,\n history,\n });\n n.activeTabIdx = n.tabs.length - 1;\n }\n }\n } else {\n const history = [];\n if (sourceEntry) _pushPrev(history, sourceEntry, target, { topNav: currentTopNav });\n n.tabs = [{\n kind: target.kind,\n props: target.props || {},\n title: target.title || target.kind,\n history,\n }];\n n.activeTabIdx = 0;\n }\n _syncActiveTab(n);\n return true;\n }\n\n /** Update any tab whose (kind, props.id) matches the given pair to\n * reflect a new label. Called from the WM in response to the\n * embedder's entity-renamed bus event, so tab titles stay live as\n * the underlying entity is renamed. */\n renameMatchingTabs(kind, id, newLabel) {\n if (!kind || !id || !newLabel) return false;\n let touched = false;\n const visit = (tabs) => {\n if (!Array.isArray(tabs)) return;\n for (const t of tabs) {\n if (t.kind === kind && String(t.props?.id ?? '') === String(id)) {\n t.title = String(newLabel);\n if (t.props) t.props.label = String(newLabel);\n touched = true;\n }\n }\n };\n for (const n of this.nodes.values()) {\n if (n.kind !== 'leaf') continue;\n visit(n.tabs);\n if (n.pageTabs) {\n for (const arc of Object.values(n.pageTabs)) visit(arc?.tabs);\n }\n _syncActiveTab(n);\n }\n return touched;\n }\n\n /** Replace the active tab's content in place, preserving every\n * other tab in the leaf. This is the \"in-tile navigation\" path:\n * clicking a row on a landing page, walking back via Backspace,\n * or clicking a breadcrumb segment should swap THIS tab's\n * content without disturbing the user's other open tabs.\n *\n * By default the previous content is pushed onto the active\n * tab's `history` stack so the user can Backspace through their\n * own click-path (per-tab \"browser back\"). Callers that are\n * themselves popping the history pass `{ recordHistory: false }`\n * so we don't double-record. Same applies to programmatic loads\n * that aren't user navigations.\n *\n * Falls back to `setLeafContent` for empty leaves so the WM\n * never has to special-case the initial load. Returns true on\n * success. */\n replaceActiveTabContent(leafId, content, title = '', opts = {}) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = Array.isArray(n.tabs) ? n.tabs : [];\n if (tabs.length === 0) {\n return this.setLeafContent(leafId, content, title);\n }\n if (!content) return false;\n const idx = Math.max(0, Math.min(tabs.length - 1, n.activeTabIdx || 0));\n const prev = tabs[idx];\n const recordHistory = opts.recordHistory !== false;\n const history = Array.isArray(prev?.history) ? prev.history : [];\n if (recordHistory && prev && prev.kind) {\n // Avoid pushing duplicates when the user re-clicks the\n // same row \u2014 same kind + same primary id \u2192 no-op.\n const last = history[history.length - 1];\n const sameAsPrev = last\n && last.kind === prev.kind\n && String(last.props?.id ?? '') === String(prev.props?.id ?? '');\n const sameAsTarget = prev.kind === content.kind\n && String(prev.props?.id ?? '') === String(content.props?.id ?? '');\n if (!sameAsPrev && !sameAsTarget) {\n history.push({\n kind: prev.kind,\n props: prev.props || {},\n title: prev.title || '',\n });\n }\n }\n tabs[idx] = {\n kind: content.kind,\n props: content.props || {},\n title: title || content.kind || '',\n history,\n };\n _syncActiveTab(n);\n return true;\n }\n\n /** Merge `patch` into the active tab's `props`. Used when an\n * in-tile editor surfaces metadata that should be captured in\n * history snapshots (e.g. which sub-tab is open) so Backspace\n * restores the user's view, not the default landing. Does not\n * re-render or push history \u2014 pure metadata write. */\n updateActiveTabProps(leafId, patch) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = Array.isArray(n.tabs) ? n.tabs : [];\n if (tabs.length === 0) return false;\n const idx = Math.max(0, Math.min(tabs.length - 1, n.activeTabIdx || 0));\n const cur = tabs[idx];\n if (!cur) return false;\n cur.props = { ...(cur.props || {}), ...(patch || {}) };\n return true;\n }\n\n /** Pop one entry off the active tab's history stack and return it,\n * or null when empty. Doesn't mutate the tab beyond the stack \u2014\n * the caller is expected to apply the returned content via\n * `replaceActiveTabContent(..., { recordHistory: false })`. */\n popActiveTabHistory(leafId) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return null;\n const tabs = Array.isArray(n.tabs) ? n.tabs : [];\n if (tabs.length === 0) return null;\n const idx = Math.max(0, Math.min(tabs.length - 1, n.activeTabIdx || 0));\n const cur = tabs[idx];\n const history = Array.isArray(cur?.history) ? cur.history : [];\n if (history.length === 0) return null;\n return history.pop();\n }\n\n /** Inspect the active tab's history stack without popping. Used\n * by the keymap to show / hide the back affordance and for\n * diagnostics. */\n activeTabHistory(leafId) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return [];\n const tabs = Array.isArray(n.tabs) ? n.tabs : [];\n if (tabs.length === 0) return [];\n const idx = Math.max(0, Math.min(tabs.length - 1, n.activeTabIdx || 0));\n const cur = tabs[idx];\n return Array.isArray(cur?.history) ? cur.history : [];\n }\n\n /** Append a new tab to a leaf and focus it. Returns the new tab's\n * index, or -1 on failure. Panel tiles never grow tabs (they're\n * chrome). */\n appendLeafTab(leafId, content, title = '', opts = {}) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return -1;\n if (_isPanel(n)) return -1;\n if (!content) return -1;\n const tab = {\n kind: content.kind,\n props: content.props || {},\n title: title || content.kind || '',\n // Transient tabs (e.g. an add-row form) are not persisted /\n // restored \u2014 see serialize() + the pageTabs archive.\n ...(opts.transient ? { transient: true } : {}),\n };\n n.tabs = Array.isArray(n.tabs) ? n.tabs : [];\n n.tabs.push(tab);\n n.activeTabIdx = n.tabs.length - 1;\n _syncActiveTab(n);\n return n.activeTabIdx;\n }\n\n /** Switch the active tab on a leaf. No-op if `idx` is out of range. */\n setActiveLeafTab(leafId, idx) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n if (!Array.isArray(n.tabs) || idx < 0 || idx >= n.tabs.length) return false;\n n.activeTabIdx = idx;\n _syncActiveTab(n);\n return true;\n }\n\n /** Remove a tab. If the active tab was removed, the previous one\n * becomes active. If the last tab was removed, the leaf's content\n * drops to null (and the WM should treat that as an empty tile \u2014\n * same as before tabs existed). Returns the (possibly clamped)\n * active index after the operation, or -1 on failure. */\n removeLeafTab(leafId, idx) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return -1;\n if (!Array.isArray(n.tabs) || idx < 0 || idx >= n.tabs.length) return -1;\n n.tabs.splice(idx, 1);\n if (n.tabs.length === 0) {\n n.activeTabIdx = 0;\n _syncActiveTab(n);\n return 0;\n }\n if (idx < n.activeTabIdx) n.activeTabIdx -= 1;\n else if (idx === n.activeTabIdx) n.activeTabIdx = Math.max(0, idx - 1);\n _syncActiveTab(n);\n return n.activeTabIdx;\n }\n\n /** Bulk-close every tab in a leaf except the one at `keepIdx`.\n * Used by the tab right-click \"Close others\" action. */\n closeOtherTabs(leafId, keepIdx) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = n.tabs || [];\n if (keepIdx < 0 || keepIdx >= tabs.length) return false;\n n.tabs = [tabs[keepIdx]];\n n.activeTabIdx = 0;\n _syncActiveTab(n);\n return true;\n }\n\n /** Close every tab after `idx`. */\n closeTabsAfter(leafId, idx) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = n.tabs || [];\n if (idx < 0 || idx >= tabs.length - 1) return false;\n n.tabs = tabs.slice(0, idx + 1);\n if (n.activeTabIdx > idx) n.activeTabIdx = idx;\n _syncActiveTab(n);\n return true;\n }\n\n /** Close every tab before `idx`. */\n closeTabsBefore(leafId, idx) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = n.tabs || [];\n if (idx <= 0 || idx >= tabs.length) return false;\n n.tabs = tabs.slice(idx);\n n.activeTabIdx = Math.max(0, n.activeTabIdx - idx);\n _syncActiveTab(n);\n return true;\n }\n\n /** Reorder a tab from `from` to `to` within the same leaf. */\n moveLeafTab(leafId, from, to) {\n const n = this.get(leafId);\n if (!n || n.kind !== 'leaf') return false;\n const tabs = n.tabs || [];\n if (from < 0 || from >= tabs.length || to < 0 || to >= tabs.length) return false;\n const moved = tabs.splice(from, 1)[0];\n tabs.splice(to, 0, moved);\n // Keep the moved tab focused if it was the active one.\n if (n.activeTabIdx === from) n.activeTabIdx = to;\n else if (from < n.activeTabIdx && to >= n.activeTabIdx) n.activeTabIdx -= 1;\n else if (from > n.activeTabIdx && to <= n.activeTabIdx) n.activeTabIdx += 1;\n _syncActiveTab(n);\n return true;\n }\n\n /**\n * Split a leaf in the given direction; existing content stays in the\n * original leaf, a new empty leaf is added next to it. Returns the\n * new leaf id, or null on failure.\n */\n split(leafId, dir /* 'h' | 'v' */) {\n const leaf = this.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') return null;\n\n const newLeaf = makeLeaf();\n // Case 1: root split. Wrap root in a new Split.\n if (!leaf.parentId) {\n const wrap = makeSplit({ dir, children: [leaf.id, newLeaf.id] });\n this._register(newLeaf);\n this._register(wrap);\n this.rootId = wrap.id;\n leaf.parentId = wrap.id;\n newLeaf.parentId = wrap.id;\n this.focus(newLeaf.id);\n return newLeaf.id;\n }\n\n const parent = this.get(leaf.parentId);\n const idx = parent.children.indexOf(leaf.id);\n if (idx < 0) return null;\n\n // Case 2: parent already matches the split direction \u2014 insert\n // the new leaf as a sibling.\n if (parent.dir === dir) {\n parent.children.splice(idx + 1, 0, newLeaf.id);\n const avg = parent.sizes.reduce((a, b) => a + b, 0) / parent.children.length;\n parent.sizes.splice(idx + 1, 0, avg);\n newLeaf.parentId = parent.id;\n this._register(newLeaf);\n this.focus(newLeaf.id);\n return newLeaf.id;\n }\n\n // Case 3: cross-direction \u2014 wrap the original leaf in a new\n // Split that contains [leaf, newLeaf]. Replace leaf in parent.\n const wrap = makeSplit({ dir, children: [leaf.id, newLeaf.id] });\n wrap.parentId = parent.id;\n parent.children[idx] = wrap.id;\n leaf.parentId = wrap.id;\n newLeaf.parentId = wrap.id;\n this._register(newLeaf);\n this._register(wrap);\n this.focus(newLeaf.id);\n return newLeaf.id;\n }\n\n /**\n * Close a leaf, collapsing any single-child splits that result. If\n * the last leaf is closed, leaves an empty tree (no root) \u2014 caller\n * is expected to repopulate.\n */\n close(leafId) {\n const leaf = this.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') return false;\n\n // Root leaf \u2014 clear the tree.\n if (!leaf.parentId) {\n this.nodes.clear();\n this.rootId = null;\n this.focusedLeafId = null;\n this.focusStack = [];\n return true;\n }\n\n const parent = this.get(leaf.parentId);\n const idx = parent.children.indexOf(leaf.id);\n parent.children.splice(idx, 1);\n parent.sizes.splice(idx, 1);\n this.nodes.delete(leaf.id);\n this.focusStack = this.focusStack.filter((id) => id !== leaf.id);\n\n // Parent collapse \u2014 if a Split has only one child left, replace\n // it with that child in *its* parent (or as root).\n this._collapse(parent);\n\n if (this.focusedLeafId === leaf.id) {\n const remaining = this.leaves();\n this.focusedLeafId = remaining.length ? remaining[0].id : null;\n if (this.focusedLeafId) this.focus(this.focusedLeafId);\n }\n return true;\n }\n\n _collapse(node) {\n if (!node || node.kind !== 'split') return;\n if (node.children.length > 1) return;\n if (node.children.length === 0) {\n // Empty split \u2014 remove from its parent (or clear root).\n if (!node.parentId) {\n this.nodes.delete(node.id);\n this.rootId = null;\n return;\n }\n const gp = this.get(node.parentId);\n const idx = gp.children.indexOf(node.id);\n gp.children.splice(idx, 1);\n gp.sizes.splice(idx, 1);\n this.nodes.delete(node.id);\n this._collapse(gp);\n return;\n }\n // Exactly one child \u2014 promote it.\n const only = this.get(node.children[0]);\n if (!node.parentId) {\n this.rootId = only.id;\n only.parentId = null;\n } else {\n const gp = this.get(node.parentId);\n const idx = gp.children.indexOf(node.id);\n gp.children[idx] = only.id;\n only.parentId = gp.id;\n }\n this.nodes.delete(node.id);\n }\n\n // \u2500\u2500 Directional focus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Move focus from current leaf in the given direction. Walks up the\n * tree looking for an ancestor split whose direction matches the\n * move (h for left/right, v for up/down) and which has a sibling on\n * the requested side; then descends along the matching edge.\n */\n focusDir(dir /* 'left' | 'right' | 'up' | 'down' */) {\n const cur = this.focused();\n if (!cur) return false;\n const wantDir = (dir === 'left' || dir === 'right') ? 'h' : 'v';\n const forward = (dir === 'right' || dir === 'down');\n\n let child = cur;\n let parent = child.parentId ? this.get(child.parentId) : null;\n while (parent) {\n if (parent.dir === wantDir) {\n const idx = parent.children.indexOf(child.id);\n const sibIdx = forward ? idx + 1 : idx - 1;\n if (sibIdx >= 0 && sibIdx < parent.children.length) {\n const target = this._descendEdge(parent.children[sibIdx],\n wantDir, !forward);\n if (target) {\n this.focus(target);\n return true;\n }\n }\n }\n child = parent;\n parent = child.parentId ? this.get(child.parentId) : null;\n }\n return false;\n }\n\n /**\n * Walk down to a leaf. For the matching direction we take the\n * `edge` end (first/last). For the orthogonal direction we just\n * take the first child.\n */\n _descendEdge(nodeId, matchDir, takeFirst) {\n let n = this.get(nodeId);\n while (n && n.kind !== 'leaf') {\n const idx = n.dir === matchDir\n ? (takeFirst ? 0 : n.children.length - 1)\n : 0;\n n = this.get(n.children[idx]);\n }\n return n ? n.id : null;\n }\n\n // \u2500\u2500 Move tile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Move the focused leaf one position in the given direction. Simple\n * version: swap with the immediate sibling in the matching parent;\n * if no such sibling, no-op (deep moves come later if needed).\n */\n moveDir(dir) {\n const cur = this.focused();\n if (!cur || !cur.parentId) return false;\n const wantDir = (dir === 'left' || dir === 'right') ? 'h' : 'v';\n const forward = (dir === 'right' || dir === 'down');\n\n let child = cur;\n let parent = this.get(child.parentId);\n while (parent && parent.dir !== wantDir) {\n child = parent;\n parent = child.parentId ? this.get(child.parentId) : null;\n }\n if (!parent) return false;\n const idx = parent.children.indexOf(child.id);\n const swap = forward ? idx + 1 : idx - 1;\n if (swap < 0 || swap >= parent.children.length) return false;\n [parent.children[idx], parent.children[swap]] =\n [parent.children[swap], parent.children[idx]];\n [parent.sizes[idx], parent.sizes[swap]] =\n [parent.sizes[swap], parent.sizes[idx]];\n return true;\n }\n\n // \u2500\u2500 Resize \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 setSplitSizes(splitId, sizes) {\n const n = this.get(splitId);\n if (!n || n.kind !== 'split') return false;\n if (sizes.length !== n.children.length) return false;\n n.sizes = sizes.slice();\n return true;\n }\n\n // \u2500\u2500 Serialization (for desktops persistence) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n serialize() {\n if (!this.rootId) return null;\n const dump = (id) => {\n const n = this.get(id);\n if (n.kind === 'leaf') {\n // Transient tabs (add-row forms etc.) are not persisted.\n const liveTabs = (Array.isArray(n.tabs) ? n.tabs : [])\n .filter((t) => !t.transient)\n .map((t) => ({ kind: t.kind, props: t.props, title: t.title }));\n return {\n kind: 'leaf',\n title: n.title,\n content: n.content,\n tabs: liveTabs,\n activeTabIdx: Math.max(0, Math.min(liveTabs.length - 1, n.activeTabIdx || 0)),\n // Page-archive: per-top-nav-kind saved tab lists so\n // switching to a previously-visited page restores\n // its tabs across reloads.\n pageTabs: n.pageTabs\n ? Object.fromEntries(\n Object.entries(n.pageTabs).map(([k, v]) => {\n const pt = (v.tabs || [])\n .filter((t) => !t.transient)\n .map((t) => ({ kind: t.kind, props: t.props, title: t.title }));\n return [k, {\n tabs: pt,\n activeTabIdx: Math.max(0, Math.min(pt.length - 1, v.activeTabIdx || 0)),\n }];\n }))\n : {},\n };\n }\n return {\n kind: 'split', dir: n.dir, sizes: n.sizes.slice(),\n children: n.children.map(dump),\n };\n };\n return {\n root: dump(this.rootId),\n focusedTitle: this.focused()?.title || null,\n };\n }\n\n static deserialize(blob) {\n const t = new TileTree();\n if (!blob || !blob.root) return t;\n const build = (raw) => {\n if (raw.kind === 'leaf') {\n // Forward-compat with the pre-tabs layout: an old\n // serialized leaf carries `content` but no `tabs`.\n // makeLeaf will derive a single-tab list from `content`.\n const leaf = makeLeaf({ content: raw.content, title: raw.title });\n if (Array.isArray(raw.tabs) && raw.tabs.length > 0) {\n leaf.tabs = raw.tabs.map((tab) => ({\n kind: tab.kind,\n props: tab.props || {},\n title: tab.title || tab.kind || '',\n }));\n leaf.activeTabIdx = Math.max(0,\n Math.min(leaf.tabs.length - 1, raw.activeTabIdx || 0));\n _syncActiveTab(leaf);\n }\n if (raw.pageTabs && typeof raw.pageTabs === 'object') {\n leaf.pageTabs = {};\n for (const [k, v] of Object.entries(raw.pageTabs)) {\n if (!v || !Array.isArray(v.tabs)) continue;\n leaf.pageTabs[k] = {\n tabs: v.tabs.map((t) => ({\n kind: t.kind,\n props: t.props || {},\n title: t.title || t.kind || '',\n })),\n activeTabIdx: v.activeTabIdx || 0,\n };\n }\n }\n return leaf;\n }\n const children = raw.children.map(build);\n const split = makeSplit({\n dir: raw.dir, children: children.map((c) => c.id),\n sizes: raw.sizes,\n });\n children.forEach((c) => t._register(c));\n return split;\n };\n const root = build(blob.root);\n t.setRoot(root);\n return t;\n }\n}\n", "/**\n * desktops.js \u2014 independent tile trees per virtual desktop, persisted\n * through the host's `state` capability under the logical key `desktops`.\n * Where that key actually lands is the embedder's business (see the host's\n * `resolvePath`); this module only names it.\n *\n * Each desktop = { id, label, tree (TileTree), windows ([]), panels }.\n * Switching desktops swaps the active tree under the renderer.\n */\n\nimport { TileTree, makeLeaf } from './tile_tree.js';\n\nconst DEFAULT_PANEL_STATE = {\n left: true,\n right: true,\n bottom: true,\n};\n\n/**\n * `seed()` yields the leaf a fresh (or emptied) desktop starts with. It comes\n * from the taxonomy's root kind \u2014 see WindowManager, which supplies it. The\n * WM used to hardcode `{ kind: 'home', title: 'Home' }` here, which meant an\n * embedder with a different ontology still got an EcoAgent Home tile it had\n * never registered, and got the content_registry placeholder instead. There is\n * deliberately NO default: a silent 'home' fallback is the exact bug this\n * parameter exists to remove.\n */\nfunction _makeDesktop(label, seed) {\n const tree = new TileTree();\n tree.setRoot(makeLeaf(seed()));\n return {\n id: `desk-${Math.random().toString(36).slice(2, 8)}`,\n label,\n tree,\n windows: [],\n // boot default: left + right + bottom all open. Names are\n // assigned by wm._canonicalize via PANEL_TITLES.\n panels: { ...DEFAULT_PANEL_STATE },\n };\n}\n\nexport class DesktopManager {\n /** @param {{seed: () => object}} opts `seed` builds the root leaf. Required. */\n constructor({ seed } = {}) {\n if (typeof seed !== 'function') {\n throw new Error('DesktopManager: a `seed` function is required (the taxonomy root leaf)');\n }\n this.seed = seed;\n this.desktops = [_makeDesktop('1', seed)];\n this.activeIdx = 0;\n }\n\n active() { return this.desktops[this.activeIdx]; }\n\n switchTo(idx) {\n if (idx < 0 || idx >= this.desktops.length) return false;\n if (idx === this.activeIdx) return false;\n this.activeIdx = idx;\n return true;\n }\n\n ensureCount(n) {\n while (this.desktops.length < n) {\n this.desktops.push(_makeDesktop(String(this.desktops.length + 1), this.seed));\n }\n }\n\n addDesktop(label = null) {\n const d = _makeDesktop(label || String(this.desktops.length + 1), this.seed);\n this.desktops.push(d);\n return d;\n }\n\n serialize() {\n return {\n activeIdx: this.activeIdx,\n desktops: this.desktops.map((d) => ({\n id: d.id, label: d.label,\n tree: d.tree.serialize(),\n panels: { ...d.panels },\n // windows serialized at WM level since we don't own\n // managed-window state in this module.\n })),\n };\n }\n\n static deserialize(blob, { seed } = {}) {\n const m = new DesktopManager({ seed });\n if (!blob || !Array.isArray(blob.desktops) || blob.desktops.length === 0) return m;\n m.desktops = blob.desktops.map((raw) => ({\n id: raw.id || `desk-${Math.random().toString(36).slice(2,8)}`,\n label: raw.label || '?',\n tree: raw.tree ? TileTree.deserialize(raw.tree) : new TileTree(),\n windows: [],\n panels: { ...DEFAULT_PANEL_STATE, ...(raw.panels || {}) },\n }));\n // Empty tree \u2192 seed with the taxonomy root so the desktop is usable.\n for (const d of m.desktops) {\n if (!d.tree.rootId) d.tree.setRoot(makeLeaf(seed()));\n }\n m.activeIdx = Math.min(Math.max(0, blob.activeIdx | 0), m.desktops.length - 1);\n return m;\n }\n}\n\n/**\n * Persistence helpers. They take a host `state` capability; a host without\n * one is legal and they no-op. We don't fail loudly \u2014 the WM stays functional\n * against a host that cannot persist (e.g. the standalone demo).\n */\n\nconst DESKTOPS_KEY = 'desktops';\n\nexport async function loadDesktops(state) {\n if (!state) return null;\n try {\n return await state.read(DESKTOPS_KEY);\n } catch (err) {\n console.warn('[desktops] load failed', err);\n return null;\n }\n}\n\nexport async function saveDesktops(state, blob) {\n if (!state) return false;\n try {\n await state.write(DESKTOPS_KEY, blob);\n return true;\n } catch (err) {\n console.warn('[desktops] save failed', err);\n return false;\n }\n}\n", "/**\n * entity_sources.js \u2014 the entity-source PORT.\n *\n * The command palette, the tile hamburger menu, and any other \"find me a\n * thing\" surface need a list of every searchable entity. Where those\n * entities come from \u2014 which endpoint returns them, what a row looks\n * like, what to call it \u2014 is the EMBEDDER's knowledge, not the shell's.\n *\n * So the source list is INJECTED. The embedder describes its sources and\n * hands them to `createEntityCatalog()` at boot. Nothing in this file\n * names an entity type or a bridge route.\n *\n * ## EntitySource\n *\n * navKind The content kind used to open a row via `wm.navigate`.\n * The taxonomy resolves its icon + label.\n *\n * list `(api) => Promise<rawList>` \u2014 per-source fetcher. Used by\n * the fan-out path, and by `loadOne` when a caller wants a\n * subset rather than the whole catalog.\n *\n * pluck? `(raw) => Array` \u2014 extract the actual list when the\n * endpoint wraps it. Defaults to \"raw is an array, else\n * raw.items if that's an array, else []\".\n *\n * shape `(row) => { id, label, hint? } | null` \u2014 normalise one raw\n * row to the record shape every search surface consumes.\n * Return `null` to skip the row.\n *\n * ## Aggregation\n *\n * An embedder whose backend can answer for every source in ONE call\n * passes `aggregate: (api) => Promise<{ [navKind]: rawList } | null>`.\n * The catalog prefers it and fans out only for the navKinds it failed to\n * answer for. Absent \u21D2 straight fan-out. Absent capability, absent key:\n * the shell never probes for a named endpoint of its own accord.\n *\n * Errors from any single source are logged and treated as \"empty\", so\n * one broken endpoint can't blank the entire palette.\n */\n\nexport function createEntityCatalog({ sources, aliases = {}, aggregate = null } = {}) {\n if (!Array.isArray(sources)) {\n throw new TypeError('createEntityCatalog: `sources` must be an array');\n }\n for (const s of sources) {\n if (!s?.navKind || typeof s.list !== 'function' || typeof s.shape !== 'function') {\n throw new TypeError(\n `createEntityCatalog: source '${s?.navKind ?? '?'}' needs navKind + list() + shape()`);\n }\n }\n if (aggregate != null && typeof aggregate !== 'function') {\n throw new TypeError('createEntityCatalog: `aggregate` must be a function when present');\n }\n\n const _sources = Object.freeze(sources.map((s) => Object.freeze({ ...s })));\n const _byKind = new Map(_sources.map((s) => [s.navKind, s]));\n const _aliases = Object.freeze({ ...aliases });\n\n const get = (navKind) => _byKind.get(navKind) || null;\n\n /** Unwrap one source's raw payload into a row array. */\n const _extract = (src, raw) => {\n const list = src.pluck\n ? src.pluck(raw)\n : (Array.isArray(raw) ? raw\n : Array.isArray(raw?.items) ? raw.items\n : []);\n return Array.isArray(list) ? list : [];\n };\n\n /** Shape a source's rows, dropping the ones `shape` rejects or\n * throws on. Shared by the palette AND the tile menu so their\n * semantics cannot drift apart \u2014 the menu used to re-implement\n * this loop by hand. */\n const shapeRows = (navKind, rows) => {\n const src = _byKind.get(navKind);\n if (!src || !Array.isArray(rows)) return [];\n const out = [];\n for (const row of rows) {\n let shaped;\n try { shaped = src.shape(row); }\n catch (err) {\n console.warn('[entity-catalog]', navKind, 'shape failed', err, row);\n continue;\n }\n if (!shaped || !shaped.id) continue;\n out.push(shaped);\n }\n return out;\n };\n\n /** Fetch ONE source's raw rows. Used by surfaces that only care\n * about a subset of the catalog. */\n const loadOne = async (navKind, api) => {\n const src = _byKind.get(navKind);\n if (!src || !api) return [];\n try { return _extract(src, await src.list(api)); }\n catch (err) {\n console.warn('[entity-catalog]', navKind, 'fetch failed', err);\n return [];\n }\n };\n\n /** Fetch every source's raw rows, grouped by navKind.\n *\n * The aggregator runs first when the embedder supplied one; the\n * fan-out only fires for sources it didn't answer for (it threw, it\n * isn't there, or it doesn't know a newly-added navKind yet).\n *\n * Shape: `{ [navKind]: rawRow[] }` \u2014 every navKind is always\n * present (empty on failure) so consumers can destructure safely. */\n const loadGrouped = async (api) => {\n const out = {};\n for (const s of _sources) out[s.navKind] = [];\n if (!api) return out;\n\n let bulk = null;\n if (aggregate) {\n try { bulk = await aggregate(api); }\n catch (err) {\n console.warn('[entity-catalog] aggregate failed, falling back to fan-out', err);\n }\n if (bulk && typeof bulk !== 'object') bulk = null;\n }\n\n const missing = [];\n for (const src of _sources) {\n const raw = bulk ? bulk[src.navKind] : undefined;\n if (raw == null) { missing.push(src); continue; }\n out[src.navKind] = _extract(src, raw);\n }\n if (missing.length === 0) return out;\n\n await Promise.all(missing.map(async (src) => {\n out[src.navKind] = await loadOne(src.navKind, api);\n }));\n return out;\n };\n\n /** Flat-and-shaped form for search surfaces. Builds on\n * `loadGrouped` so there is a single fetch path and the palette /\n * explorer can't drift apart in coverage. */\n const loadAll = async (api) => {\n const grouped = await loadGrouped(api);\n const out = [];\n for (const src of _sources) {\n for (const shaped of shapeRows(src.navKind, grouped[src.navKind] || [])) {\n out.push({ kind: src.navKind, ...shaped });\n }\n }\n return out;\n };\n\n /** Resolve a user-typed type prefix to a list of canonical navKinds.\n * Accepts the embedder's aliases first, then navKinds verbatim,\n * then the underscore spelling of a hyphenated kind. Returns an\n * array of navKinds on hit, `null` otherwise. */\n const resolveTypePrefix = (prefix) => {\n const p = String(prefix || '').toLowerCase().trim();\n if (!p) return null;\n if (_aliases[p]) return _aliases[p];\n for (const src of _sources) {\n if (src.navKind === p) return [src.navKind];\n if (src.navKind.replace(/-/g, '_') === p) return [src.navKind];\n }\n return null;\n };\n\n return Object.freeze({\n sources: _sources,\n get,\n loadOne,\n loadGrouped,\n loadAll,\n shapeRows,\n resolveTypePrefix,\n });\n}\n", "/**\n * keymap.js \u2014 Alt-based shortcuts for the tiling window manager.\n *\n * Alt+H split focused tile horizontally (new empty pane)\n * Alt+V split focused tile vertically (new empty pane)\n * Alt+Shift+H open focused tile's content in a horizontal split\n * Alt+Shift+V open focused tile's content in a vertical split\n * Alt+T open focused tile's content in a new tab\n * Alt+N open focused tile's content in a new window\n * Alt+W close focused tile\n * Alt+F promote focused tile <-> managed window (moves it)\n * Alt+ArrowLeft/Right/Up/Down move focus\n * Alt+Shift+Arrow\u2026 swap focused tile with neighbour\n * Alt+1..9 switch desktop\n * Alt+Shift+1..9 move focused tile to desktop N\n * Ctrl+ArrowLeft/Right iterate virtual desktops\n * Shift+ArrowLeft/Right iterate bottom-panel tabs (when present)\n * Ctrl+Tab / Ctrl+Shift+Tab next / previous main-panel tab (focused tile)\n * F1..F8 jump to the Nth top-nav page\n * Ctrl+K open command palette\n * ? open Help (lists every shortcut) \u2014 bound globally\n * by help_modal.js, not here\n * Esc close palette / managed-modal\n *\n * The full user-facing reference is the Help modal's \"Keyboard shortcuts\"\n * topic (ui/js/help/help_service.js) \u2014 keep that table in sync when\n * binding new chords here.\n *\n * The handler refuses to act when focus is in an editable field, unless\n * the chord uses the Alt modifier (which is never typed into a field).\n */\n\nexport function installKeymap({ wm, palette }) {\n document.addEventListener('keydown', (e) => {\n const inField = e.target?.closest?.(\n 'input, textarea, select, [contenteditable=\"true\"]');\n\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k' && !e.shiftKey) {\n e.preventDefault();\n palette.toggle();\n return;\n }\n // \u2500\u2500 Ctrl+Tab / Ctrl+Shift+Tab \u2192 next / previous main-panel tab in the\n // focused tile (wraps). Works everywhere (Tab isn't a text key here);\n // no-op when the tile has a single tab.\n if ((e.ctrlKey || e.metaKey) && !e.altKey && e.key === 'Tab') {\n e.preventDefault();\n wm.cycleFocusedTab(e.shiftKey ? -1 : 1);\n return;\n }\n if (e.key === 'Escape') {\n if (palette.isOpen()) { palette.close(); return; }\n // Let managed-window system handle its own Esc.\n }\n // Backspace = walk one step up the breadcrumb hierarchy. Skips\n // when the user is typing in a field so it doesn't steal\n // text-deletion.\n if (e.key === 'Backspace' && !inField && !e.metaKey && !e.ctrlKey) {\n e.preventDefault();\n wm.navigateBack?.();\n return;\n }\n\n // \u2500\u2500 F1..F8 \u2192 jump straight to the Nth top-nav page. F-keys never\n // type, but we still skip while a field is focused so editing\n // flows (query editor, filters) keep keyboard focus.\n const fMatch = /^F([1-9]|1[0-2])$/.exec(e.key);\n if (fMatch && !inField && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) {\n const btns = document.querySelectorAll(\n '.twm-global-top-bar .twm-bar-center.twm-top-nav .twm-top-nav__btn');\n const idx = Number(fMatch[1]) - 1;\n if (idx < btns.length) {\n e.preventDefault();\n btns[idx].click();\n return;\n }\n }\n\n // \u2500\u2500 Shift+Left/Right \u2192 previous/next bottom-panel tab. No-op when\n // no bottom panel is mounted. Skipped in fields so Shift+Arrow\n // keeps selecting text there.\n if (e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey && !inField\n && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {\n const tabs = [...document.querySelectorAll('.twm-bp__tabs .twm-bp__tab')];\n if (tabs.length) {\n const cur = tabs.findIndex((t) => t.classList.contains('twm-bp__tab--on'));\n const dir = e.key === 'ArrowRight' ? 1 : -1;\n const next = ((cur < 0 ? 0 : cur) + dir + tabs.length) % tabs.length;\n e.preventDefault();\n tabs[next].click();\n return;\n }\n }\n\n // \u2500\u2500 Ctrl+Left/Right \u2192 iterate virtual desktops (wraps).\n if (e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !inField\n && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {\n e.preventDefault();\n wm.cycleDesktop(e.key === 'ArrowRight' ? 1 : -1);\n return;\n }\n\n if (!e.altKey) return;\n // Browser Alt+letter triggers menu-access in some browsers \u2014 always preventDefault.\n const key = e.key.toLowerCase();\n\n // Desktop switch / move \u2014 Alt+digit\n if (/^[1-9]$/.test(e.key)) {\n e.preventDefault();\n const idx = Number(e.key) - 1;\n if (e.shiftKey) wm.moveFocusedToDesktop(idx);\n else wm.switchDesktop(idx);\n return;\n }\n\n switch (key) {\n // Plain Alt+H/V split into an empty pane; with Shift they open\n // the focused tile's own content in the new split.\n case 'h':\n e.preventDefault();\n e.shiftKey ? wm.splitFocusedWith('h') : wm.split('h');\n return;\n case 'v':\n e.preventDefault();\n e.shiftKey ? wm.splitFocusedWith('v') : wm.split('v');\n return;\n case 't': e.preventDefault(); wm.openFocusedInTab(); return;\n case 'n': e.preventDefault(); wm.openFocusedInWindow(); return;\n case 'w': e.preventDefault(); wm.closeFocused(); return;\n case 'f': e.preventDefault(); wm.toggleManagedFocused(); return;\n case 'arrowleft':\n e.preventDefault();\n e.shiftKey ? wm.moveFocused('left') : wm.focusDir('left');\n return;\n case 'arrowright':\n e.preventDefault();\n e.shiftKey ? wm.moveFocused('right') : wm.focusDir('right');\n return;\n case 'arrowup':\n e.preventDefault();\n e.shiftKey ? wm.moveFocused('up') : wm.focusDir('up');\n return;\n case 'arrowdown':\n e.preventDefault();\n e.shiftKey ? wm.moveFocused('down') : wm.focusDir('down');\n return;\n }\n\n // Suppress accidental browser menu-access on bare Alt+letter\n // chords we don't bind (so the user doesn't get a Firefox/Chromium\n // menu popping open mid-flow).\n if (key.length === 1 && /[a-z]/.test(key) && !inField) {\n e.preventDefault();\n }\n });\n}\n", "/**\n * kind_taxonomy.js \u2014 the taxonomy PORT.\n *\n * A \"kind\" is a content type the user can navigate to. The tiling shell\n * needs to know four things about one: what to call it, what icon it\n * wears, which top-nav slot owns it, and what sits above it. It must\n * NOT know what any of them mean.\n *\n * So the taxonomy is INJECTED, not imported. The embedder describes its\n * own ontology and hands it to `createTaxonomy()` at boot; the shell\n * closes over the result. Nothing in this file names a kind, and the\n * framework runs unchanged on a completely different vocabulary.\n *\n * Consumed by:\n *\n * - install.js \u2192 top-nav buttons + active-state highlight\n * - tile_breadcrumb.js \u2192 breadcrumb segments\n * - wm.js navigateBack \u2192 Backspace parent\n * - command_palette.js \u2192 palette chip strip + row icons\n * - tile_tab_menu.js \u2192 which sources a tile's hamburger lists\n *\n * ## KindDef\n *\n * label Long form, used in breadcrumb segments + palette.\n * shortLabel Optional \u22644-char chip text for the top-nav.\n * Falls back to `label` when omitted.\n * icon Material Symbols name.\n * topNav Top-nav category this kind belongs to. Determines which\n * button lights up + which segment the breadcrumb inserts\n * after the root. Omit on the top-nav kind itself.\n * isTopNav True iff this kind owns a slot in the top-nav strip.\n * order Sort key for top-nav display (lower = leftward).\n * appGlobal True iff the kind is not scoped to the root entity (a\n * preferences page, say). Its breadcrumb omits the root.\n * sources Entity-source ids the tile hamburger lists when a tile\n * is on this page. Only meaningful on top-nav kinds; the\n * root's list is the fallback.\n *\n * ancestors? `(props) => [{ kind, id, label? }]` \u2014 the entity-level\n * ancestors of ONE instance, root-most first, EXCLUDING\n * the top-nav segment and the node itself. This is the\n * hook that replaces every hardcoded \"split the id to\n * find its parent\" branch: naming conventions are the\n * embedder's business, not the shell's.\n * labelOf? `(props) => string` \u2014 display label for ONE instance.\n * Defaults to `props.label`, then `props.id`.\n */\n\n/** Build a taxonomy from an embedder's kind map. Validated eagerly and\n * frozen \u2014 a typo in a `topNav` pointer is a boot error, not a chrome\n * surface that silently renders nothing six clicks later. */\nexport function createTaxonomy({ kinds, root } = {}) {\n if (!kinds || typeof kinds !== 'object') {\n throw new TypeError('createTaxonomy: `kinds` must be an object of KindDefs');\n }\n if (!root || !kinds[root]) {\n throw new Error(`createTaxonomy: root kind '${root}' is not in the taxonomy`);\n }\n for (const [kind, def] of Object.entries(kinds)) {\n if (!def || typeof def !== 'object') {\n throw new TypeError(`createTaxonomy: '${kind}' is not a KindDef`);\n }\n if (def.topNav && !kinds[def.topNav]) {\n throw new Error(\n `createTaxonomy: '${kind}' hangs off unknown topNav '${def.topNav}'`);\n }\n if (def.isTopNav && def.topNav) {\n throw new Error(\n `createTaxonomy: '${kind}' is both a top-nav kind and owned by one`);\n }\n }\n const _kinds = Object.freeze({ ...kinds });\n\n /** Lookup. `undefined` for unknown kinds \u2014 chrome code treats that\n * as \"render the kind name verbatim\". */\n const meta = (kind) => _kinds[kind];\n\n /** Top-nav category id that owns `kind`. For a top-nav kind itself,\n * returns the same kind. `undefined` when the kind isn't in the\n * taxonomy (caller renders a fallback). */\n const topNavFor = (kind) => {\n const m = _kinds[kind];\n if (!m) return undefined;\n return m.isTopNav ? kind : m.topNav;\n };\n\n /** Backspace target \u2014 walk one step up the KIND hierarchy. A\n * top-nav page goes to the root; everything else goes to its\n * top-nav. The root itself returns `null`. */\n const parentKindFor = (kind) => {\n if (kind === root) return null;\n const m = _kinds[kind];\n if (!m) return null;\n if (m.isTopNav) return root;\n return m.topNav || root;\n };\n\n /** Entity-level ancestors of one instance, root-most first. Empty\n * unless the KindDef supplies an `ancestors` hook. Normalised to\n * `{ kind, props }` so callers hand the result straight to\n * `wm.navigate`. A throwing hook is a warning, never a crash: the\n * breadcrumb degrades to its generic form. */\n const ancestors = (kind, props) => {\n const fn = _kinds[kind]?.ancestors;\n if (typeof fn !== 'function') return [];\n let out;\n try { out = fn(props || {}); }\n catch (err) {\n console.warn('[taxonomy] ancestors() threw for', kind, err);\n return [];\n }\n if (!Array.isArray(out)) return [];\n return out\n .filter((a) => a && a.kind)\n .map((a) => ({ kind: a.kind, props: { id: a.id, label: a.label ?? a.id } }));\n };\n\n /** The nearest entity-level ancestor, or `null`. */\n const parentOf = (kind, props) => {\n const chain = ancestors(kind, props);\n return chain.length ? chain[chain.length - 1] : null;\n };\n\n /** Display label for one instance of `kind`. */\n const labelOf = (kind, props) => {\n const fn = _kinds[kind]?.labelOf;\n if (typeof fn === 'function') {\n try {\n const s = fn(props || {});\n if (s) return String(s);\n } catch (err) {\n console.warn('[taxonomy] labelOf() threw for', kind, err);\n }\n }\n if (props?.label) return String(props.label);\n return props?.id != null ? String(props.id) : '';\n };\n\n /** Entity-source ids a tile on `kind` should offer. Falls back to\n * the root's list, which is the \"everything\" default. */\n const sourcesFor = (kind) => {\n const s = _kinds[kind]?.sources ?? _kinds[root]?.sources;\n return Array.isArray(s) ? s : [];\n };\n\n /** Top-nav entries in display order:\n * { kind, label (short), longLabel, icon }\n * `label` is the chip text; `longLabel` is what the palette shows. */\n const topNavEntries = () =>\n Object.entries(_kinds)\n .filter(([, m]) => m.isTopNav)\n .sort((a, b) => (a[1].order ?? 1000) - (b[1].order ?? 1000))\n .map(([kind, m]) => ({\n kind,\n label: m.shortLabel || m.label,\n longLabel: m.label,\n icon: m.icon,\n }));\n\n return Object.freeze({\n root,\n kinds: _kinds,\n meta,\n topNavFor,\n parentKindFor,\n ancestors,\n parentOf,\n labelOf,\n sourcesFor,\n topNavEntries,\n });\n}\n", "/**\n * panel_keys.js \u2014 central keyboard router for panel-local navigation.\n *\n * THE PROBLEM IT SOLVES\n * ---------------------\n * Several panels want plain-key navigation (\u2191/\u2193 to move a cursor, Enter to\n * open, single letters for actions): the landing tables, the top-nav\n * overview pages, and any future browser panel. Each one used to attach its\n * OWN `document` keydown listener gated by the heuristic\n *\n * hostEl.contains(document.activeElement) || activeElement === <body>\n *\n * That heuristic is wrong as soon as there is more than one tile. When the\n * user selects a different tile, focus usually rests on `<body>`, so EVERY\n * mounted landing's listener still fires \u2014 the \"main\" panel keeps eating\n * arrow keys even though another panel is selected, and two panels can move\n * their cursors at once. The selected tile is never actually consulted.\n *\n * THE CONCEPT\n * -----------\n * One listener, one authority. Panels do not listen on `document`\n * themselves; they REGISTER a handler bound to their host element. On each\n * keydown the router asks the window manager which leaf is currently\n * focused (the single source of truth \u2014 `WindowManager.focusedLeafEl()`)\n * and dispatches the event to the handler whose host lives inside that leaf\n * \u2014 and to no one else. A panel automatically receives keys exactly when,\n * and only when, it is the selected tile.\n *\n * Content rendered OUTSIDE the tile tree (a promoted managed window or a\n * floating shell) has no focused-leaf concept; for those hosts the router\n * falls back to the focus-containment scope so they keep working.\n *\n * USAGE\n * -----\n * import { registerPanelKeys } from './panel_keys.js';\n * const off = registerPanelKeys(hostEl, (ev) => { ... });\n * // later, on teardown:\n * off();\n *\n * The handler is responsible for its own key semantics (which keys, whether\n * to skip editable targets, when to preventDefault). The router only decides\n * WHETHER this panel is the active keyboard target. A handler that calls\n * `ev.preventDefault()` stops the event from reaching any other handler in\n * the same leaf.\n *\n * When no router has been installed (unit tests, or a landing used outside\n * the WM), `registerPanelKeys` degrades to a self-contained listener using\n * the legacy focus-containment scope, so callers work in isolation too.\n */\n\nlet _router = null;\n\n/** Install the singleton router. Called once by the WindowManager. */\nexport function installPanelKeyRouter(wm) {\n if (_router) _router.destroy();\n _router = new PanelKeyRouter(wm);\n return _router;\n}\n\n/** The installed router, or null if the WM hasn't built one yet. */\nexport function getPanelKeyRouter() { return _router; }\n\n/** Tear down the singleton (test cleanup / shell teardown). */\nexport function uninstallPanelKeyRouter() {\n _router?.destroy();\n _router = null;\n}\n\n/**\n * Register `handler` as the key handler for `hostEl`'s panel. Returns an\n * unregister function \u2014 call it on teardown. Routes through the installed\n * router when present, otherwise falls back to a legacy scoped listener so\n * the panel still works outside the WM.\n */\nexport function registerPanelKeys(hostEl, handler) {\n if (!hostEl || typeof handler !== 'function') return () => {};\n if (_router) return _router.register(hostEl, handler);\n return _legacyRegister(hostEl, handler);\n}\n\nexport class PanelKeyRouter {\n constructor(wm) {\n this._wm = wm;\n this._entries = []; // { hostEl, handler }\n this._onKey = this._dispatch.bind(this);\n document.addEventListener('keydown', this._onKey);\n }\n\n register(hostEl, handler) {\n const entry = { hostEl, handler };\n this._entries.push(entry);\n return () => {\n const i = this._entries.indexOf(entry);\n if (i >= 0) this._entries.splice(i, 1);\n };\n }\n\n destroy() {\n document.removeEventListener('keydown', this._onKey);\n this._entries.length = 0;\n }\n\n /** Is `hostEl` the panel that should receive keys right now? */\n _isActiveTarget(hostEl) {\n if (!hostEl?.isConnected) return false;\n const leaf = hostEl.closest?.('.twm-leaf');\n if (leaf) {\n // Inside the tile tree: only the focused leaf is live. This is\n // the whole point \u2014 compare against the WM's single source of\n // truth, not against `document.activeElement`.\n return leaf === this._wm?.focusedLeafEl?.();\n }\n // Outside any tile (managed window / floating shell): no focused\n // leaf to consult, so fall back to focus containment.\n return hostEl.contains(document.activeElement)\n || document.activeElement === document.body;\n }\n\n _dispatch(ev) {\n // Snapshot: a handler may unregister (e.g. navigate away) mid-loop.\n for (const entry of [...this._entries]) {\n if (!this._isActiveTarget(entry.hostEl)) continue;\n try { entry.handler(ev); }\n catch (err) { console.warn('[panel-keys] handler threw', err); }\n // A handler that consumed the key ends the chain so a second\n // handler in the same leaf (e.g. the action-footer shortcuts)\n // doesn't double-fire on the same press.\n if (ev.defaultPrevented) return;\n }\n }\n}\n\n/** Legacy fallback used only when no router is installed. Mirrors the old\n * per-panel scope check so isolated/test usage keeps its previous\n * behavior. */\nfunction _legacyRegister(hostEl, handler) {\n const wrapped = (ev) => {\n if (!hostEl.isConnected) return;\n if (!hostEl.contains(document.activeElement)\n && document.activeElement !== document.body) return;\n handler(ev);\n };\n document.addEventListener('keydown', wrapped);\n return () => document.removeEventListener('keydown', wrapped);\n}\n", "/**\n * landing_table.js \u2014 shared helpers for the \"navigation table\"\n * pattern used by SFC / Markets / Scenarios / KPIs landings (and the\n * market-archetype instances table). Three responsibilities:\n *\n * 1. Single-click row \u2192 open the entity (handled by callers).\n * 2. Right-click row \u2192 custom context menu with Open / Edit / Delete\n * (replaces DataTable's default copy-as-TSV menu for these tables;\n * the default still applies to data tables outside this helper).\n * 3. Renders an \"actions\" column with inline edit + delete icons so\n * the user can act on a row without opening it first.\n *\n * Callers configure the per-kind behaviour via the `entityActions`\n * object: `{ open(row), edit(row), delete(row) }` \u2014 any of which may be\n * omitted to hide the corresponding action.\n */\n\nimport { showContextMenu } from '../ui/components/context_menu.js';\nimport { registerPanelKeys } from './panel_keys.js';\n\n/** Attach the navigation-table interactions to a host element that\n * contains a `<table>` already rendered by DataTable. Returns a\n * teardown function.\n *\n * `entityActions` maps action names to handlers. The canonical names\n * are `open` / `edit` / `delete` (plus `openInTab` / `openInWindow`),\n * but ANY `data-twm-action=\"<name>\"` button or context-menu item\n * dispatches to `entityActions[<name>]` \u2014 so tree landings can wire\n * `toggle`, `contract`, etc. through the same robust path instead of\n * hand-rolling their own tbody listeners (which is how the Agents /\n * Markets pages used to drift out of sync with this helper).\n *\n * `options.buildMenu(row) => items[]` overrides the default\n * Open / Edit / Delete right-click menu for tree-shaped rows that need\n * conditional entries (expand/collapse, contract detail). Each item's\n * `action` is dispatched the same way as a button. */\nexport function attachLandingTableBehavior(host, getRow, entityActions, options = {}) {\n if (!host) return () => {};\n\n // Delegate from the stable `host` container, NOT the <tbody>. DataTable\n // rebuilds its <tbody> on every internal re-render \u2014 pagination, filter,\n // sort, and the post-layout column-width sync \u2014 and each re-render\n // re-installs ITS OWN row listeners (data_table.js `_installInteractions`)\n // but knows nothing about ours. A listener bound directly to the tbody\n // therefore goes silently dead after the first re-render: events still\n // reach the live tbody (DataTable's copy menu still pops) while our\n // handlers sit orphaned on a detached node. Binding on `host` and\n // resolving the row at event time survives any number of tbody rebuilds.\n\n // Dispatch an action name to its handler. The `open-tab` /\n // `open-window` menu aliases map onto the `openInTab` /\n // `openInWindow` handlers; every other name (including `edit`,\n // `delete`, and tree-only verbs like `toggle` / `contract`) routes\n // straight to `entityActions[name]`.\n const dispatch = (action, row) => {\n if (!row) return;\n const fn = action === 'open-tab' ? entityActions.openInTab\n : action === 'open-window' ? entityActions.openInWindow\n : entityActions[action];\n try { fn?.(row); }\n catch (e) { console.warn(`[landing] action \"${action}\" failed`, e); }\n };\n\n // The BODY <tr> for an event, re-found live each time. Excludes the\n // header / filter row (it lives in the separate non-scrolling header\n // wrap, not inside `.preview-table-wrap`'s tbody).\n const bodyRowFor = (ev) => {\n const tr = ev.target.closest('tr');\n if (!tr || !tr.closest('tbody')) return null;\n const wrap = tr.closest('.twm-preview-table-wrap');\n if (!wrap || !host.contains(wrap)) return null;\n return tr;\n };\n\n const onClick = (ev) => {\n // Inline action buttons short-circuit the row-open default and\n // suppress every other listener (DataTable's row-selection\n // listener, etc.). `stopImmediatePropagation` is load-bearing.\n const actionBtn = ev.target.closest('[data-twm-action]');\n if (actionBtn && host.contains(actionBtn)) {\n ev.preventDefault();\n ev.stopPropagation();\n ev.stopImmediatePropagation();\n const tr = actionBtn.closest('tr');\n dispatch(actionBtn.dataset.twmAction, tr ? getRow(tr.__rowIndex) : null);\n return;\n }\n // Plain row click \u2192 open. Ignore clicks on interactive controls\n // (buttons, filter inputs, links) and anything outside a body row\n // (pagination strip, header, empty space).\n if (ev.target.closest('button, a, input, select, textarea')) return;\n const tr = bodyRowFor(ev);\n if (tr) dispatch('open', getRow(tr.__rowIndex));\n };\n\n const defaultMenu = (row) => {\n const items = [];\n if (entityActions.open) {\n items.push({ label: 'Open', icon: 'open_in_new', action: 'open' });\n if (entityActions.openInTab) {\n items.push({ label: 'Open in new tab', icon: 'tab', action: 'open-tab' });\n }\n if (entityActions.openInWindow) {\n items.push({ label: 'Open in new window', icon: 'open_in_full',\n action: 'open-window' });\n }\n }\n if (entityActions.edit) items.push({ label: 'Rename / edit', icon: 'edit', action: 'edit' });\n if (entityActions.delete) {\n if (items.length) items.push({ separator: true });\n items.push({ label: 'Delete', icon: 'delete', action: 'delete', danger: true });\n }\n return items;\n };\n const buildMenu = typeof options.buildMenu === 'function'\n ? options.buildMenu\n : defaultMenu;\n\n const onContextMenu = (ev) => {\n const tr = bodyRowFor(ev);\n if (!tr) return;\n ev.preventDefault();\n // Bypass DataTable's own copy-as-TSV/CSV menu by stopping\n // propagation \u2014 the right-click for a navigation row is about the\n // *entity*, not the cell text. Capture phase on `host` runs before\n // DataTable's bubble-phase contextmenu on the tbody.\n ev.stopPropagation();\n const row = getRow(tr.__rowIndex);\n if (!row) return;\n const items = buildMenu(row) || [];\n if (items.length === 0) return;\n showContextMenu(ev.clientX, ev.clientY, items, (action) => dispatch(action, row));\n };\n\n // Click in bubble phase (after DataTable's row-selection); contextmenu\n // in CAPTURE phase so ours runs before DataTable's bubble copy menu.\n host.addEventListener('click', onClick);\n host.addEventListener('contextmenu', onContextMenu, true);\n return () => {\n host.removeEventListener('click', onClick);\n host.removeEventListener('contextmenu', onContextMenu, true);\n };\n}\n\n/** Wire pane-focus highlighting. SfcLandingTab gives each\n * `.ea-sfc-landing__pane` an `--focused` modifier when it's the\n * active pane \u2014 that's what paints the blue head + accent title.\n * Other landings need the same treatment to read as consistent.\n *\n * Single-pane landings can call this once: the only pane stays\n * focused at all times. Multi-pane landings get mousedown wiring\n * per pane and a reflectFocus() helper they can call from keyboard\n * navigation if they implement it. */\nexport function wireLandingPaneFocus(hostEl) {\n const panes = Array.from(hostEl.querySelectorAll('.twm-landing__pane'));\n if (panes.length === 0) return { focus: () => {}, panes };\n let focused = panes[0];\n const reflect = () => {\n for (const p of panes) {\n p.classList.toggle('twm-landing__pane--focused', p === focused);\n }\n };\n reflect();\n for (const p of panes) {\n p.addEventListener('mousedown', () => {\n if (focused === p) return;\n focused = p;\n reflect();\n });\n }\n return {\n focus: (pane) => { if (pane && panes.includes(pane)) { focused = pane; reflect(); } },\n panes,\n };\n}\n\n/** Arrow-key navigation for a landing page's DataTable.\n *\n * - ArrowDown / ArrowUp moves a row cursor within `host`.\n * - Enter (and the optional `activateKey`, e.g. `o`) opens the row.\n * - Home / End jump to the first / last row.\n * - Captures the keys at the document level so the user doesn't have\n * to click inside the table first \u2014 same UX as sfc_landing_tab.\n *\n * The visible cursor is the `ea-row-cursor` CSS class on the active\n * `<tr>`; the row also `scrollIntoView({block:'nearest'})` so the\n * selection stays visible during keyboard scroll-through.\n *\n * Returns `{ teardown, refresh, focusFirst }`. Call `refresh()` after\n * the table re-renders so the cursor lands on the right row again.\n */\nexport function attachLandingKeyboardNav(host, getRows, onActivate, options = {}) {\n if (!host) return { teardown: () => {}, refresh: () => {}, focusFirst: () => {} };\n\n let cursor = 0;\n const tbody = () => host.querySelector('tbody');\n\n const repaintCursor = () => {\n const tb = tbody();\n if (!tb) return;\n const rows = getRows() || [];\n if (rows.length === 0) { cursor = 0; return; }\n if (cursor >= rows.length) cursor = rows.length - 1;\n if (cursor < 0) cursor = 0;\n let active = null;\n tb.querySelectorAll('tr').forEach((tr) => {\n const on = tr.__rowIndex === cursor;\n tr.classList.toggle('twm-row-cursor', on);\n if (on) active = tr;\n });\n if (active) active.scrollIntoView({ block: 'nearest' });\n };\n\n const move = (delta) => {\n const rows = getRows() || [];\n if (rows.length === 0) return;\n cursor = Math.max(0, Math.min(rows.length - 1, cursor + delta));\n repaintCursor();\n };\n\n const open = () => {\n const rows = getRows() || [];\n const row = rows[cursor];\n if (row) onActivate(row);\n };\n\n const onKey = (ev) => {\n if (!host.isConnected) return;\n // Stay out of the way of inputs and unrelated focus targets.\n const t = ev.target;\n const editable = t && (\n t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' ||\n t.tagName === 'SELECT' || t.isContentEditable);\n if (editable) return;\n // Scope (which tile is selected) is owned by the panel-key router.\n\n if (ev.key === 'ArrowDown') { ev.preventDefault(); move(+1); }\n else if (ev.key === 'ArrowUp') { ev.preventDefault(); move(-1); }\n else if (ev.key === 'Home') { ev.preventDefault(); cursor = 0; repaintCursor(); }\n else if (ev.key === 'End') {\n ev.preventDefault();\n const rows = getRows() || [];\n cursor = Math.max(0, rows.length - 1);\n repaintCursor();\n }\n else if (ev.key === 'Enter') { ev.preventDefault(); open(); }\n else if (options.activateKey && ev.key === options.activateKey\n && !ev.metaKey && !ev.ctrlKey && !ev.altKey) {\n ev.preventDefault(); open();\n }\n };\n\n const offKey = registerPanelKeys(host, onKey);\n // Re-paint immediately so the cursor is visible from first render.\n setTimeout(repaintCursor, 0);\n\n return {\n teardown: () => offKey(),\n refresh: () => repaintCursor(),\n focusFirst: () => { cursor = 0; repaintCursor(); },\n };\n}\n\n\n/** Unified landing-page keyboard shell.\n *\n * Wires the four behaviors every landing should share, in one call:\n *\n * - Pane focus highlight (`.ea-sfc-landing__pane--focused`) \u2014 click\n * on a pane or Tab to it, the header band lights up.\n * - ArrowUp / ArrowDown moves the row cursor within the focused\n * pane's table; Home / End jump to first / last. The visible cursor\n * is `.ea-row-cursor` on the active `<tr>`.\n * - Tab / Shift+Tab cycles between panes. Single-pane landings just\n * no-op the Tab \u2014 the behaviour is a property of the shell, not\n * the page.\n * - Enter activates the cursor row via `onActivate(row)`.\n * - ArrowRight / ArrowLeft expand / collapse the cursor row when\n * the pane provides `onExpandToggle` + `isExpanded` (tree-shaped\n * tables; harmless on flat tables that don't define them).\n *\n * Each pane spec:\n * {\n * paneEl, // .ea-sfc-landing__pane element\n * getRows, // () => Array<row>\n * onActivate, // (row) => void \u2014 Enter\n * onExpandToggle?, // (row, expand:bool) => void\n * isExpanded?, // (row) => bool\n * isExpandable?, // (row) => bool \u2014 gates Left/Right\n * tableHost?, // override pane.querySelector('.twm-landing__table')\n * }\n *\n * Returns `{ teardown, refresh, focusPane(idx) }`. Call `refresh()` after\n * the pane tables re-render so the cursor lands on the right row again.\n *\n * Backspace is intentionally **not** handled here \u2014 `keymap.js` owns\n * it globally and walks `wm.navigateBack()` regardless of which\n * landing is showing. */\nexport function attachLandingShell(hostEl, { panes, initialPane = 0 } = {}) {\n if (!hostEl || !Array.isArray(panes) || panes.length === 0) {\n return { teardown: () => {}, refresh: () => {}, focusPane: () => {} };\n }\n\n const state = panes.map((spec) => ({\n spec,\n paneEl: spec.paneEl,\n tableHost: spec.tableHost\n || spec.paneEl?.querySelector('.twm-landing__table')\n || spec.paneEl,\n cursor: 0,\n }));\n let focusedIdx = Math.max(0, Math.min(panes.length - 1, initialPane));\n\n const reflectPaneFocus = () => {\n state.forEach((s, i) => {\n s.paneEl?.classList.toggle(\n 'twm-landing__pane--focused', i === focusedIdx);\n });\n };\n\n const repaintCursor = (idx = focusedIdx) => {\n const s = state[idx];\n if (!s) return;\n const tbody = s.tableHost?.querySelector('tbody');\n if (!tbody) return;\n const rows = s.spec.getRows?.() || [];\n if (rows.length === 0) { s.cursor = 0; return; }\n if (s.cursor >= rows.length) s.cursor = rows.length - 1;\n if (s.cursor < 0) s.cursor = 0;\n let active = null;\n tbody.querySelectorAll('tr').forEach((tr) => {\n const on = tr.__rowIndex === s.cursor;\n tr.classList.toggle('twm-row-cursor', on);\n if (on) active = tr;\n });\n if (active && idx === focusedIdx) {\n active.scrollIntoView({ block: 'nearest' });\n }\n };\n\n const move = (delta) => {\n const s = state[focusedIdx];\n if (!s) return;\n const rows = s.spec.getRows?.() || [];\n if (rows.length === 0) return;\n s.cursor = Math.max(0, Math.min(rows.length - 1, s.cursor + delta));\n repaintCursor();\n };\n\n const jump = (toEnd) => {\n const s = state[focusedIdx];\n if (!s) return;\n const rows = s.spec.getRows?.() || [];\n s.cursor = toEnd ? Math.max(0, rows.length - 1) : 0;\n repaintCursor();\n };\n\n const currentRow = () => {\n const s = state[focusedIdx];\n if (!s) return null;\n const rows = s.spec.getRows?.() || [];\n return rows[s.cursor] ?? null;\n };\n\n const activate = () => {\n const row = currentRow();\n if (!row) return;\n try { state[focusedIdx].spec.onActivate?.(row); }\n catch (err) { console.warn('[landing-shell] activate failed', err); }\n };\n\n /** Open the current row in a new tab on the tile. Pane spec opts in\n * by providing `onActivateInTab(row)`; the default-Enter handler\n * remains `onActivate`. Falls back to `onActivate` so panes that\n * haven't been migrated still respond to Ctrl+Enter. */\n const activateInTab = () => {\n const row = currentRow();\n if (!row) return;\n const spec = state[focusedIdx].spec;\n const fn = spec.onActivateInTab || spec.onActivate;\n try { fn?.(row); }\n catch (err) { console.warn('[landing-shell] activate-tab failed', err); }\n };\n\n /** Open the current row in a fresh managed window. Same opt-in\n * pattern as activateInTab \u2014 panes provide `onActivateInWindow`\n * for Shift+Enter, fall back to onActivate when absent. */\n const activateInWindow = () => {\n const row = currentRow();\n if (!row) return;\n const spec = state[focusedIdx].spec;\n const fn = spec.onActivateInWindow || spec.onActivate;\n try { fn?.(row); }\n catch (err) { console.warn('[landing-shell] activate-window failed', err); }\n };\n\n const expandToggle = (expand) => {\n const s = state[focusedIdx];\n if (!s?.spec.onExpandToggle) return false;\n const row = currentRow();\n if (!row) return false;\n if (s.spec.isExpandable && !s.spec.isExpandable(row)) return false;\n const currentlyExpanded = s.spec.isExpanded\n ? !!s.spec.isExpanded(row)\n : false;\n if (expand === currentlyExpanded) return false;\n try { s.spec.onExpandToggle(row, expand); }\n catch (err) { console.warn('[landing-shell] expand failed', err); }\n return true;\n };\n\n const focusPane = (idx) => {\n if (idx < 0 || idx >= state.length) return;\n if (idx === focusedIdx) return;\n focusedIdx = idx;\n reflectPaneFocus();\n repaintCursor();\n };\n\n const cyclePane = (dir) => {\n if (state.length < 2) return;\n focusPane((focusedIdx + dir + state.length) % state.length);\n };\n\n const onMouseDown = (ev) => {\n // Find which pane the click landed in. Inline action buttons\n // and the like still focus the surrounding pane.\n const paneEl = ev.target.closest?.('.twm-landing__pane');\n if (!paneEl) return;\n const idx = state.findIndex((s) => s.paneEl === paneEl);\n if (idx < 0 || idx === focusedIdx) return;\n focusedIdx = idx;\n reflectPaneFocus();\n repaintCursor();\n };\n\n const onKey = (ev) => {\n if (!hostEl.isConnected) return;\n // Scope is owned by the panel-key router: this handler only runs\n // when our tile is the selected one. We still skip editable\n // targets so typing in a field inside the tile isn't hijacked.\n const t = ev.target;\n const editable = t && (\n t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' ||\n t.tagName === 'SELECT' || t.isContentEditable);\n if (editable) return;\n // Browser-style activation chords (caught BEFORE the modifier\n // guard so the WM keymap doesn't swallow them):\n // Ctrl/Cmd + Enter \u2192 open in new TAB on this tile\n // Shift + Enter \u2192 open in new managed WINDOW\n if (ev.key === 'Enter' && (ev.metaKey || ev.ctrlKey) && !ev.altKey) {\n ev.preventDefault();\n activateInTab();\n return;\n }\n if (ev.key === 'Enter' && ev.shiftKey && !ev.altKey\n && !ev.metaKey && !ev.ctrlKey) {\n ev.preventDefault();\n activateInWindow();\n return;\n }\n // Other modifier chords belong to the WM / browser.\n if (ev.metaKey || ev.ctrlKey || ev.altKey || ev.shiftKey) return;\n\n switch (ev.key) {\n case 'ArrowDown':\n ev.preventDefault(); move(+1); return;\n case 'ArrowUp':\n ev.preventDefault(); move(-1); return;\n case 'Home':\n ev.preventDefault(); jump(false); return;\n case 'End':\n ev.preventDefault(); jump(true); return;\n case 'Enter':\n ev.preventDefault(); activate(); return;\n case 'Tab':\n // Cycle panes; single-pane case still preventDefault so\n // focus doesn't escape into the browser chrome.\n ev.preventDefault();\n cyclePane(ev.shiftKey ? -1 : +1);\n return;\n case 'ArrowRight':\n if (expandToggle(true)) ev.preventDefault();\n return;\n case 'ArrowLeft':\n if (expandToggle(false)) ev.preventDefault();\n return;\n }\n };\n\n hostEl.addEventListener('mousedown', onMouseDown);\n const offKey = registerPanelKeys(hostEl, onKey);\n reflectPaneFocus();\n // Initial cursor paint runs after the synchronous mount returns so\n // tables that render asynchronously already have their tbody.\n setTimeout(() => state.forEach((_, i) => repaintCursor(i)), 0);\n\n // Park native focus on hostEl when our leaf is the active one. The\n // panel-key router no longer depends on this for arrow routing (it\n // keys off the focused leaf, not document.activeElement), but parking\n // focus keeps native focus semantics \u2014 scroll-into-view, :focus-within\n // styling, and screen-reader context \u2014 anchored to the live tile.\n //\n // Guarded by the WM's `.twm-leaf--focused` class so we don't steal\n // focus when another tile owns the user's attention. The\n // requestAnimationFrame second pass catches the case where the\n // focus class is applied a frame after mount.\n const parkFocusIfActive = () => {\n const leaf = hostEl.closest?.('.twm-leaf');\n // Page is rendered outside a tile (managed window / floating\n // shell) \u2014 there is no focused-leaf concept; safe to take focus.\n const inTile = !!leaf;\n if (inTile && !leaf.classList.contains('twm-leaf--focused')) return;\n if (hostEl.contains(document.activeElement)) return;\n if (hostEl.tabIndex == null || hostEl.tabIndex < -1) hostEl.tabIndex = -1;\n try { hostEl.focus({ preventScroll: true }); } catch {}\n };\n parkFocusIfActive();\n requestAnimationFrame(parkFocusIfActive);\n\n return {\n teardown: () => {\n hostEl.removeEventListener('mousedown', onMouseDown);\n offKey();\n },\n refresh: () => state.forEach((_, i) => repaintCursor(i)),\n focusPane,\n currentRow,\n };\n}\n\n\n/** Standardized action-footer renderer.\n *\n * Each action: `{ id, label, icon, shortcut?, title?, onClick }`.\n *\n * When `shortcut` is set (single letter), the button label gets a\n * `[N]` suffix and pressing that key (without modifiers, outside any\n * text input, while focus is in `hostEl` or on the body) fires the\n * action. The visible chip + the keydown handler are the same source\n * of truth, so users can never wonder which letter triggers what.\n *\n * Returns `{ teardown, refresh(actions) }`. */\n\n\n// \u2500\u2500\u2500 #143 \u2014 shared landing shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Mount the boilerplate every landing repeats: a detail-header with\n * title + stat fields, a single `.ea-sfc-landing__pane` with title +\n * keyboard-shortcut hint, the DataTable host, and a footer slot for\n * `mountLandingActions` to fill.\n *\n * Callers receive `{paneEl, tableHost, footerEl, setStat(key, value)}`\n * \u2014 `paneEl` feeds straight into `attachLandingShell({panes: [{paneEl,\n * \u2026}]})`; `tableHost` is where `new DataTable(host, \u2026)` mounts;\n * `footerEl` is the second arg to `mountLandingActions`; `setStat`\n * patches a single stat by `data-role` without rebuilding the header.\n *\n * HTML output is identical to what each landing built by hand before\n * this helper existed \u2014 only the source location moves.\n *\n * @param {HTMLElement} hostEl\n * @param {object} opts\n * @param {string} opts.title \u2014 `<h2>` text on the left of the header.\n * @param {Array<{key,label,initial?}>} [opts.stats] \u2014 header chip per stat. `key` is the `data-role` for setStat(); `label` is the muted label above the value; `initial` defaults to `0`.\n * @param {object} opts.pane\n * @param {string} opts.pane.key \u2014 the `data-pane=\"\u2026\"` value (also doubles as the table-host's `data-role=\"<key>-host\"`).\n * @param {string} opts.pane.title \u2014 pane-head title.\n * @param {string} opts.pane.hint \u2014 pane-head keyboard-shortcut hint.\n * @returns {{headerEl: HTMLElement, paneEl: HTMLElement, tableHost: HTMLElement, footerEl: HTMLElement, setStat: (key: string, value: any) => void}}\n */\nexport function mountLandingShell(hostEl, opts) {\n const {\n title = '',\n stats = [],\n pane = { key: 'rows', title: '', hint: '' },\n } = opts || {};\n const paneKey = String(pane.key || 'rows');\n\n const _esc = (s) => String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n\n const statsHtml = (stats || []).map((s) => `\n <span class=\"twm-landing__stat twm-entity-header__field\">\n <span>${_esc(s.label || '')}</span>\n <strong data-role=\"${_esc(s.key)}\">${_esc(s.initial != null ? s.initial : 0)}</strong>\n </span>\n `).join('');\n\n hostEl.classList.add('twm-landing');\n hostEl.innerHTML = `\n <header class=\"twm-entity-header\">\n <h2>${_esc(title)}</h2>\n ${statsHtml}\n <span class=\"twm-entity-header__spacer\"></span>\n </header>\n <div class=\"twm-landing__split twm-landing__split--single\">\n <section class=\"twm-landing__pane\" data-pane=\"${_esc(paneKey)}\">\n <div class=\"twm-landing__pane-head\">\n <span class=\"twm-landing__pane-title\">${_esc(pane.title || '')}</span>\n <span class=\"twm-landing__pane-hint\">${_esc(pane.hint || '')}</span>\n </div>\n <div class=\"twm-landing__table\" data-role=\"${_esc(paneKey)}-host\"></div>\n </section>\n </div>\n <footer class=\"twm-landing__actions\" data-role=\"actions\"></footer>\n `;\n\n const headerEl = hostEl.querySelector('.twm-entity-header');\n const paneEl = hostEl.querySelector(`[data-pane=\"${paneKey}\"]`);\n const tableHost = hostEl.querySelector(`[data-role=\"${paneKey}-host\"]`);\n const footerEl = hostEl.querySelector('[data-role=\"actions\"]');\n\n const setStat = (key, value) => {\n const el = hostEl.querySelector(`[data-role=\"${key}\"]`);\n if (el) el.textContent = String(value);\n };\n\n return { headerEl, paneEl, tableHost, footerEl, setStat };\n}\n\n\nexport function mountLandingActions(footerEl, actions, hostEl) {\n if (!footerEl) return { teardown: () => {}, refresh: () => {} };\n let current = [];\n const renderInto = (list) => {\n current = (list || []).filter(Boolean);\n footerEl.innerHTML = '';\n for (const a of current) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-action-btn';\n if (a.id) btn.dataset.action = a.id;\n if (a.title) btn.title = a.title;\n const icon = a.icon\n ? `<span class=\"material-symbols-outlined\">${_esc(a.icon)}</span>`\n : '';\n const sc = a.shortcut\n ? ` <span class=\"twm-action-btn__kbd\">[${_esc(a.shortcut.toUpperCase())}]</span>`\n : '';\n btn.innerHTML = `${icon}<span>${_esc(a.label || '')}</span>${sc}`;\n btn.addEventListener('click', (ev) => {\n ev.preventDefault();\n try { a.onClick?.(ev); }\n catch (err) { console.warn('[landing-actions] click failed', err); }\n });\n footerEl.appendChild(btn);\n }\n };\n\n const onKey = (ev) => {\n if (!footerEl.isConnected) return;\n if (ev.metaKey || ev.ctrlKey || ev.altKey) return;\n // Scope is owned by the panel-key router; we only guard editable\n // targets so single-letter shortcuts don't fire while typing.\n const t = ev.target;\n const editable = t && (\n t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' ||\n t.tagName === 'SELECT' || t.isContentEditable);\n if (editable) return;\n const k = ev.key.length === 1 ? ev.key.toLowerCase() : ev.key;\n const hit = current.find((a) =>\n a.shortcut && String(a.shortcut).toLowerCase() === k);\n if (!hit) return;\n ev.preventDefault();\n try { hit.onClick?.(ev); }\n catch (err) { console.warn('[landing-actions] shortcut failed', err); }\n };\n\n renderInto(actions);\n const scopeEl = hostEl || footerEl.closest('.twm-landing') || footerEl;\n const offKey = registerPanelKeys(scopeEl, onKey);\n return {\n teardown: () => offKey(),\n refresh: renderInto,\n };\n}\n\n\n/** A DataTable `renderCell` hook that paints inline Edit + Delete icon\n * buttons in the configured action column. Use as:\n *\n * renderCell: actionsCellRenderer(actionsColIdx, { edit: true, delete: true })\n *\n * Other columns fall through to the default text renderer. */\nexport function actionsCellRenderer(actionsColIdx, options = { edit: true, delete: true }) {\n return (td, _value, colIdx) => {\n if (colIdx !== actionsColIdx) return false;\n const parts = [];\n if (options.edit) {\n parts.push(`<button type=\"button\" class=\"twm-row-action\"\n data-twm-action=\"edit\"\n title=\"Edit\"\n aria-label=\"Edit\">\n <span class=\"material-symbols-outlined\">edit</span>\n </button>`);\n }\n if (options.delete) {\n parts.push(`<button type=\"button\" class=\"twm-row-action twm-row-action--danger\"\n data-twm-action=\"delete\"\n title=\"Delete\"\n aria-label=\"Delete\">\n <span class=\"material-symbols-outlined\">delete</span>\n </button>`);\n }\n td.classList.add('twm-row-actions-cell');\n td.innerHTML = parts.join('');\n return true;\n };\n}\n\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n}\n", "/**\n * loading_overlay.js \u2014 the canonical \"content is loading\" overlay.\n *\n * An absolutely-positioned spinner layer dropped over a slot while an async\n * mount is in flight, with an 80ms grace period so cache hits / instant\n * renders never strobe a spinner. Returns a `done()` that removes it.\n *\n * Uses the global `twm-tile-loading` styles (ui/css/tiling/host.css). Shared\n * by the WM page-stub shell and the agent Code tab's split view.\n *\n * const done = makeLoadingOverlay(slot);\n * try { await mount(); } finally { done(); }\n */\n\n/** Drop a loading overlay over `slot` and return a `done()` to remove it.\n * The overlay stays invisible for `delay` ms (default 80) so fast renders\n * don't flash a spinner. `slot` must be a positioned ancestor (or pass one\n * that is); the overlay is `position:absolute; inset:0`. */\nexport function makeLoadingOverlay(slot, { delay = 80 } = {}) {\n const overlay = document.createElement('div');\n overlay.className = 'twm-tile-loading twm-tile-loading--pending';\n overlay.innerHTML =\n '<div class=\"twm-tile-loading__spinner\" aria-label=\"Loading\"></div>';\n slot.appendChild(overlay);\n // Promote to visible only if the mount hasn't finished within the grace.\n const showTimer = setTimeout(() => {\n overlay.classList.remove('twm-tile-loading--pending');\n }, delay);\n return () => {\n clearTimeout(showTimer);\n overlay.remove();\n };\n}\n", "/**\n * nav_panel.js \u2014 the left navigation panel-tile: a mode strip, a shared\n * filter box, and one lazily-mounted pane per mode.\n *\n * \u250C\u2500[ mode ][ mode ][ mode ]\u2500\u2500\u2500\u2500\u2500\u2510 mode tabs\n * \u2502 \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\u2510 \u2502\n * \u2502 \u2502 Filter\u2026 \u2502 \u2502 unified filter (sidebar-controls)\n * \u2502 \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\u2518 \u2502\n * \u2502 \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\u2510 \u2502\n * \u2502 \u2502 (pane body) \u2502 \u2502\n * \u2502 \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\u2518 \u2502\n *\n * The panel owns the strip, the filter and the pane hosts. It owns NONE of\n * the panes: the embedder passes them in. There used to be three hardcoded\n * modes here (a file tree, an object tree, a git view) plus a dead category\n * browser; all of that is the embedder's, and lives on its side now.\n *\n * A mode:\n *\n * {\n * id, icon, label,\n * mount(paneEl, { wm, eventBus }) -> {\n * activate?(), // called every time the mode is selected (may be async)\n * filter?(query), // the shared filter box changed\n * destroy?(),\n * }\n * }\n *\n * `mount()` runs at most once, the first time its mode is selected.\n * `activate()` runs on every selection, INCLUDING the first \u2014 a pane that\n * has to rebuild on each visit (a git status list, say) does its work there.\n * The filter query is remembered per mode.\n */\n\nexport function mountNavPanel(hostEl, {\n modes = [],\n wm = null,\n eventBus = null,\n filterPlaceholder = 'Filter\u2026',\n} = {}) {\n if (!Array.isArray(modes) || modes.length === 0) {\n throw new Error('mountNavPanel: at least one mode is required');\n }\n\n hostEl.classList.add('twm-nav');\n hostEl.innerHTML = `\n <div class=\"twm-nav__modes\" data-role=\"modes\"></div>\n <div class=\"twm-sidebar-controls twm-nav__filter\">\n <span class=\"material-symbols-outlined twm-sidebar-search-icon\">search</span>\n <input class=\"twm-data-page__search twm-nav__filter-input\"\n type=\"search\" placeholder=\"${_esc(filterPlaceholder)}\"\n autocomplete=\"off\" />\n </div>\n <div class=\"twm-nav__body\" data-role=\"body\"></div>\n `;\n const modesEl = hostEl.querySelector('[data-role=\"modes\"]');\n const bodyEl = hostEl.querySelector('[data-role=\"body\"]');\n const filterEl = hostEl.querySelector('.twm-nav__filter-input');\n\n modesEl.innerHTML = modes.map((m) => `\n <button class=\"twm-nav__mode twm-has-tooltip\" data-mode=\"${_esc(m.id)}\"\n data-tooltip=\"${_esc(m.label)}\">\n <span class=\"material-symbols-outlined\">${_esc(m.icon)}</span>\n <span>${_esc(m.label)}</span>\n </button>\n `).join('');\n\n const byId = new Map(modes.map((m) => [m.id, m]));\n const hosts = {}; // mode id -> pane host element\n const panes = {}; // mode id -> the object the mode's mount() returned\n const filterByMode = Object.fromEntries(modes.map((m) => [m.id, '']));\n let mode = modes[0].id;\n\n const ensureHost = (id) => {\n if (hosts[id]) return hosts[id];\n const el = document.createElement('div');\n el.className = `twm-nav__pane twm-nav__pane--${id}`;\n el.style.display = 'none';\n bodyEl.appendChild(el);\n hosts[id] = el;\n return el;\n };\n\n const activate = async (next) => {\n const def = byId.get(next);\n if (!def) return;\n mode = next;\n for (const m of modes) {\n ensureHost(m.id).style.display = (m.id === next) ? 'flex' : 'none';\n }\n modesEl.querySelectorAll('[data-mode]').forEach((b) =>\n b.classList.toggle('twm-nav__mode--on', b.dataset.mode === next));\n filterEl.value = filterByMode[next] || '';\n\n const paneEl = ensureHost(next);\n if (!panes[next]) {\n try { panes[next] = def.mount(paneEl, { wm, eventBus }) || {}; }\n catch (err) {\n console.error('[nav] mode mount failed', next, err);\n panes[next] = {};\n }\n }\n // `activate()` runs on EVERY selection, including the first. A pane that\n // must rebuild on each visit (a git status list) does its work here.\n try { await panes[next].activate?.(); }\n catch (err) { console.error('[nav] mode activate failed', next, err); }\n _applyFilter();\n };\n\n const _applyFilter = () => {\n const q = filterByMode[mode] || '';\n try { panes[mode]?.filter?.(q); }\n catch (err) { console.warn('[nav] filter failed', mode, err); }\n };\n\n filterEl.addEventListener('input', () => {\n filterByMode[mode] = filterEl.value;\n _applyFilter();\n });\n\n modesEl.addEventListener('click', (e) => {\n const btn = e.target.closest('[data-mode]');\n if (btn) activate(btn.dataset.mode);\n });\n\n activate(mode);\n\n return {\n refresh: () => activate(mode),\n destroy: () => {\n for (const p of Object.values(panes)) {\n try { p?.destroy?.(); } catch { /* ignore */ }\n }\n },\n };\n}\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => (\n { '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[c]\n ));\n}\n", "/**\n * tile_breadcrumb.js \u2014 per-tile breadcrumb strip rendered above each\n * page's content.\n *\n * Reuses the existing `topbar-breadcrumb__*` CSS classes so the look\n * matches the rest of the app (notebook editor, etc.). Segments are\n * built from the leaf's content kind + props.id, and clicking a\n * non-current segment routes through wm.navigate so the user jumps to\n * that level.\n *\n * The path is assembled from FOUR taxonomy questions, none of which this\n * module answers itself:\n *\n * 1. `ctx.rootCrumb` the leading segment + how its label stays fresh\n * 2. `taxonomy.topNavFor` which section owns the kind\n * 3. `taxonomy.ancestors` the entity-level chain above ONE instance\n * 4. `taxonomy.labelOf` what to call that instance\n *\n * (3) is the one that matters. Deriving an instance's parent from its id\n * is a naming convention, and naming conventions belong to the embedder;\n * this file used to hardcode two of them.\n */\n\n/** Build a breadcrumb strip element + render initial state. Returns\n * `{ el, destroy }`. The strip is wired to the WM (clicks open content\n * in the primary tile) and, when the embedder supplies a `rootCrumb`\n * with a `subscribe` hook, to whatever keeps the root label fresh. */\nexport function mountTileBreadcrumb(kind, props, ctx) {\n const eventBus = ctx?.eventBus;\n const taxonomy = ctx?.taxonomy;\n const rootCrumb = ctx?.rootCrumb || null;\n if (!taxonomy) {\n console.error('[breadcrumb] no taxonomy in ctx \u2014 cannot render');\n return { el: document.createElement('nav'), destroy: () => {} };\n }\n const root = document.createElement('nav');\n root.className = 'twm-topbar-breadcrumb twm-tile-breadcrumb';\n root.setAttribute('aria-label', 'Tile breadcrumb');\n\n // Look up wm late (at click time) instead of capturing it once at\n // mount. ctx.wm should always be set by the renderer, but fall\n // back to the global escape hatch (set by install.js after\n // wm.load()) so a closure that lost ctx.wm \u2014 or a mount called\n // before the renderer threaded wm through \u2014 still navigates.\n const getWm = () => ctx?.wm || window.__twm?.wm || null;\n\n // Breadcrumb segments route through the canonical `wm.navigate`\n // helper so the same three-axis routing (window \u2192 replace window,\n // tile \u2192 replace active tab, panel/none \u2192 primary) lives in one\n // place. Critically, this is what makes the breadcrumb work in\n // WINDOWED mode \u2014 passing `ctx` keeps windowId in scope so the\n // segment click stays inside the floating window instead of\n // jumping back to the primary tile.\n const navigate = (k, p = {}) => {\n const wm = getWm();\n if (!wm) {\n console.error('[breadcrumb] no WM available \u2014 click ignored', k);\n return;\n }\n if (typeof wm.navigate === 'function') {\n wm.navigate(k, p, { ctx, dest: 'origin' });\n } else if (typeof wm.openInPrimary === 'function') {\n // Fallback for older WM revisions.\n wm.openInPrimary(k, p);\n } else {\n console.error('[breadcrumb] WM has no navigate/openInPrimary');\n }\n };\n\n // The root segment's label is the embedder's to supply and to keep\n // fresh (it names whatever the root entity is \u2014 a project, a\n // workspace, a document). Absent `rootCrumb` \u21D2 no root segment, and\n // the breadcrumb simply starts at the top-nav.\n let rootLabel = rootCrumb?.label || '';\n\n const render = () => {\n _renderInto(root, _segments(kind, props, taxonomy, rootCrumb, rootLabel, navigate));\n };\n render();\n\n let unsubscribe = null;\n if (typeof rootCrumb?.subscribe === 'function') {\n try {\n unsubscribe = rootCrumb.subscribe((next) => {\n if (next?.label) rootLabel = next.label;\n render();\n }, { api: ctx?.api, host: ctx?.host, eventBus });\n } catch (err) {\n console.warn('[breadcrumb] rootCrumb.subscribe threw', err);\n }\n }\n\n return {\n el: root,\n destroy: () => {\n try { unsubscribe?.(); }\n catch (err) { console.warn('[breadcrumb] rootCrumb teardown threw', err); }\n },\n };\n}\n\nfunction _segments(kind, props, taxonomy, rootCrumb, rootLabel, navigate) {\n const segs = [];\n const meta = taxonomy.meta(kind);\n\n // App-global kinds (e.g. a preferences page) aren't scoped to the\n // root entity \u2014 they open with no project loaded and persist to\n // app-level storage \u2014 so their breadcrumb has no root ancestor.\n if (meta?.appGlobal) {\n return [{ icon: meta.icon, label: meta.label, onClick: null }];\n }\n\n // 1. The root segment \u2192 clicks back to the root page.\n if (rootCrumb) {\n segs.push({\n icon: rootCrumb.icon,\n label: rootLabel || rootCrumb.label,\n onClick: () => navigate(rootCrumb.navKind ?? taxonomy.root),\n });\n }\n\n // 2. The top-nav segment. Skipped on the root itself (the root\n // segment already names it) and when the kind isn't in the\n // taxonomy at all.\n const topNav = taxonomy.topNavFor(kind);\n const topNavMeta = topNav ? taxonomy.meta(topNav) : null;\n if (topNav && topNav !== taxonomy.root && topNavMeta) {\n segs.push({\n icon: topNavMeta.icon,\n label: topNavMeta.label,\n onClick: () => navigate(topNav),\n });\n }\n\n // 3. Entity-level ancestors, root-most first \u2014 supplied by the\n // taxonomy, not by string surgery on the id.\n for (const anc of taxonomy.ancestors(kind, props)) {\n segs.push({\n icon: taxonomy.meta(anc.kind)?.icon || 'description',\n label: anc.props.label ?? anc.props.id,\n onClick: () => navigate(anc.kind, anc.props),\n });\n }\n\n // 4. The node itself.\n const hasEntity = !!props?.id;\n if (meta) {\n if (hasEntity) {\n segs.push({\n icon: meta.icon,\n label: taxonomy.labelOf(kind, props),\n onClick: null,\n });\n } else if (kind !== topNav) {\n // The kind IS the top-nav (e.g. opening a landing page).\n // Don't duplicate the chip \u2014 the segment above already\n // names it.\n segs.push({\n icon: meta.icon,\n label: meta.label,\n onClick: null,\n });\n }\n } else if (hasEntity) {\n // Kind isn't in the taxonomy yet \u2014 still surface the entity\n // name so the user sees where they are, just without an icon.\n segs.push({\n icon: 'description',\n label: props.label || props.id,\n onClick: null,\n });\n }\n return segs;\n}\n\nfunction _renderInto(container, segments) {\n container.innerHTML = '';\n if (!segments?.length) return;\n const ol = document.createElement('ol');\n ol.className = 'twm-topbar-breadcrumb__list';\n segments.forEach((seg, i) => {\n const li = document.createElement('li');\n li.className = 'twm-topbar-breadcrumb__item';\n const isLast = i === segments.length - 1;\n if (isLast || !seg.onClick) {\n li.classList.add('twm-topbar-breadcrumb__item--current');\n li.innerHTML = `\n <span class=\"material-symbols-outlined twm-topbar-breadcrumb__icon\">${_esc(seg.icon)}</span>\n <span class=\"twm-topbar-breadcrumb__current\">${_esc(seg.label)}</span>\n `;\n } else {\n const btn = document.createElement('button');\n btn.className = 'twm-topbar-breadcrumb__link';\n btn.type = 'button';\n btn.innerHTML = `\n <span class=\"material-symbols-outlined twm-topbar-breadcrumb__icon\">${_esc(seg.icon)}</span>\n <span>${_esc(seg.label)}</span>\n `;\n btn.addEventListener('click', () => {\n btn.classList.add('twm-tile-breadcrumb__link--flash');\n setTimeout(() => {\n btn.classList.remove('twm-tile-breadcrumb__link--flash');\n }, 180);\n try { seg.onClick(); }\n catch (e) { console.error('[breadcrumb] segment click threw', e); }\n });\n li.appendChild(btn);\n const sep = document.createElement('span');\n sep.className = 'twm-topbar-breadcrumb__separator';\n sep.textContent = '\u203A';\n li.appendChild(sep);\n }\n ol.appendChild(li);\n });\n container.appendChild(ol);\n}\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n}\n", "/**\n * page_factory.js \u2014 the MECHANISM behind a tile's content, with no\n * knowledge of what that content is about.\n *\n * `createPageFactories()` returns the four wrappers an embedder uses to\n * turn its own page/tab modules into content factories:\n *\n * tabFactory(kind, factory) breadcrumb page-shell + a mounted tab\n * bareTabFactory(kind, factory) same, minus the breadcrumb (transient forms)\n * stubPageFactory(kind, render) breadcrumb + a plain render fn + loading overlay\n * mountTabBody / makeShim the pieces the three are built from\n *\n * \u2500\u2500 makeShim: the navigation contract \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Mounted content receives a `workspaceTabs` object. That object IS the\n * library's public navigation API in embryo:\n *\n * openTab open a kind in THIS tile (openFromContext)\n * openInTab open it as a new TAB in this tile (openInTabFromContext)\n * openInWindow open it in a fresh managed window\n * updateProps persist editor sub-state into this tile's tab props\n * closeTab close this tab (falls back to closing the tile)\n * notifyChanged broadcast \"I mutated the project\" so sidebars refresh\n *\n * \u2500\u2500 refreshOn / events: no bus-name literals here \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * This module used to hardcode five bus names (`<domain>:run:tick`, \u2026) and\n * one mutation event. Both are now INJECTED:\n *\n * refreshOn { [busEvent]: reasonString } fanned into tab.refresh(reason)\n * events { projectChanged? } emitted by close/notifyChanged\n *\n * An absent key means an absent subscription / an absent emit, so an\n * embedder with no run loop simply passes `{}` and nothing fires.\n */\n\nimport { makeLoadingOverlay } from './loading_overlay.js';\nimport { mountTileBreadcrumb } from './tile_breadcrumb.js';\n\n/**\n * @param {object} cfg\n * @param {object} cfg.eventBus the embedder's bus (may be null)\n * @param {object} cfg.events { projectChanged?: string }\n * @param {object} cfg.refreshOn { [busEventName]: reason } -> tab.refresh(reason)\n */\nexport function createPageFactories({ eventBus = null, events = {}, refreshOn = {} } = {}) {\n const projectChanged = events?.projectChanged || null;\n\n // The `workspaceTabs` API tile content calls to open/close tabs and\n // broadcast mutations. Shared by breadcrumbed and bare tabs.\n const makeShim = (ctx) => ({\n // Route through openFromContext so navigation triggered from a\n // split tile / window stays in that container.\n openTab: ({ kind: k, entityId, label, icon, subTab }) =>\n ctx.wm?.openFromContext(ctx, k, { id: entityId, label, icon, subTab }),\n // Open the same content as a NEW TAB in the current tile.\n openInTab: ({ kind: k, entityId, label, icon, subTab }) =>\n ctx.wm?.openInTabFromContext(ctx, k, { id: entityId, label, icon, subTab }),\n // Open the same content in a fresh managed window.\n openInWindow: ({ kind: k, entityId, label, icon, subTab }) =>\n ctx.wm?.navigate(k, { id: entityId, label, icon, subTab }, { ctx, dest: 'window' }),\n // Persist editor sub-state into this tile's WM tab props.\n updateProps: (patch) => {\n try { ctx.wm?.updateActiveTabProps?.(ctx.leafId, patch); }\n catch (err) { console.warn('[shim] updateProps failed', err); }\n },\n // Close just THIS tab (not the whole tile); falls back to closing\n // the tile when it's the last tab. Also broadcasts so sidebars /\n // landings / nav refresh against the mutated project state.\n closeTab: (_id) => {\n if (projectChanged) {\n try { eventBus?.emit?.(projectChanged, { source: 'twm-tab-close' }); } catch {}\n }\n try { ctx.wm?.closeActiveTab?.(ctx.leafId); } catch (err) {\n console.warn('[shim] closeTab failed', err);\n }\n },\n // Non-closing mutations (Save/New/Rename) broadcast so listeners refresh.\n notifyChanged: (domain) => {\n if (!projectChanged) return;\n try {\n eventBus?.emit?.(projectChanged,\n { source: 'tab-mutation', domain: domain || null });\n } catch {}\n },\n registerProvider: () => {},\n getActiveTab: () => null,\n });\n\n // Run a content factory inside a content slot: build the shim, mount\n // the tab, drive the loading overlay, and fan the embedder's declared\n // events into the tab's refresh(reason) hook (tabs that don't\n // self-subscribe would otherwise freeze mid-run). Returns a teardown\n // that removes listeners + disposes the tab.\n const mountTabBody = (factory, contentSlot, props, ctx) => {\n const shim = makeShim(ctx);\n const tab = factory(contentSlot, props?.id ?? props?.entityId ?? null, {\n logger: null, eventBus, workspaceTabs: shim,\n wm: ctx.wm, leafId: ctx.leafId, windowId: ctx.windowId,\n });\n const hideLoading = makeLoadingOverlay(contentSlot);\n try {\n const ret = tab?.mount?.(props);\n if (ret && typeof ret.then === 'function') {\n ret.then(hideLoading, (err) => {\n console.error('[page] mount failed', err);\n hideLoading();\n });\n } else {\n requestAnimationFrame(hideLoading);\n }\n } catch (err) {\n console.error('[page] mount failed', err);\n hideLoading();\n }\n const listeners = {};\n if (typeof tab?.refresh === 'function' && eventBus?.on) {\n for (const [busEvent, reason] of Object.entries(refreshOn || {})) {\n const fn = () => {\n try { tab.refresh(reason); }\n catch (err) { console.warn('[page] refresh failed', busEvent, err); }\n };\n listeners[busEvent] = fn;\n eventBus.on(busEvent, fn);\n }\n }\n return () => {\n for (const [n, fn] of Object.entries(listeners)) {\n try { eventBus?.off?.(n, fn); } catch {}\n }\n try { tab?.dispose?.(); tab?.unmount?.(); } catch {}\n };\n };\n\n /** Wrap a tab factory in a \"page shell\" \u2014 breadcrumb strip at the top,\n * content fills the rest. `kind` is captured at build time so the\n * breadcrumb knows which crumbs to build. */\n const tabFactory = (kind, factory) => (host, props, ctx) => {\n host.classList.add('twm-page-shell');\n host.innerHTML = '';\n const contentSlot = document.createElement('div');\n contentSlot.className = 'twm-page-shell__content';\n // Focusable via JS so `document.activeElement` lands inside the\n // page when the tile is activated.\n contentSlot.tabIndex = -1;\n\n // A breadcrumb navigates the host TILE \u2014 meaningless for an entity\n // opened in a standalone managed window, where we want only the\n // entity view. Skip the crumb when mounted in a window.\n let crumb = null;\n if (!ctx?.windowId) {\n const breadcrumbSlot = document.createElement('div');\n breadcrumbSlot.className = 'twm-page-shell__breadcrumb';\n host.appendChild(breadcrumbSlot);\n crumb = mountTileBreadcrumb(kind, props, { ...ctx, eventBus });\n breadcrumbSlot.appendChild(crumb.el);\n }\n host.appendChild(contentSlot);\n\n const teardown = mountTabBody(factory, contentSlot, props, ctx);\n return {\n destroy: () => {\n teardown();\n try { crumb?.destroy(); } catch {}\n },\n };\n };\n\n // Like tabFactory but with NO breadcrumb chrome \u2014 for transient /\n // form content (e.g. an add-row entry mask) that isn't an entity\n // view. Content still gets the full ctx (wm/leafId) + shim, so it\n // can self-close via wm.closeActiveTab.\n const bareTabFactory = (kind, factory) => (host, props, ctx) => {\n host.classList.add('twm-page-shell');\n host.innerHTML = '';\n const contentSlot = document.createElement('div');\n contentSlot.className = 'twm-page-shell__content';\n contentSlot.tabIndex = -1;\n host.appendChild(contentSlot);\n return { destroy: mountTabBody(factory, contentSlot, props, ctx) };\n };\n\n /** Page with a breadcrumb at the top and a plain `render(slot, props, ctx)`\n * body \u2014 for content that isn't a full tab object. If `render` returns a\n * `ready` promise the loading overlay waits on it. */\n const stubPageFactory = (kind, render) => (host, props, ctx) => {\n host.classList.add('twm-page-shell');\n host.innerHTML = '';\n const breadcrumbSlot = document.createElement('div');\n breadcrumbSlot.className = 'twm-page-shell__breadcrumb';\n const contentSlot = document.createElement('div');\n contentSlot.className = 'twm-page-shell__content';\n contentSlot.tabIndex = -1;\n host.appendChild(breadcrumbSlot);\n host.appendChild(contentSlot);\n const crumb = mountTileBreadcrumb(kind, props, { ...ctx, eventBus });\n breadcrumbSlot.appendChild(crumb.el);\n const hideLoading = makeLoadingOverlay(contentSlot);\n const ret = render(contentSlot, props, ctx) || {};\n // Most landings kick off their own async refresh after the\n // synchronous render returns. If render exposes a `ready`\n // promise we await it; otherwise hide on the next frame.\n if (ret.ready && typeof ret.ready.then === 'function') {\n ret.ready.then(hideLoading, hideLoading);\n } else {\n requestAnimationFrame(hideLoading);\n }\n return {\n title: ret.title,\n destroy: () => { try { crumb.destroy(); } catch {} ret.destroy?.(); },\n };\n };\n\n return Object.freeze({\n makeShim, mountTabBody, tabFactory, bareTabFactory, stubPageFactory,\n });\n}\n", "/**\n * tile_renderer.js \u2014 maps a TileTree into nested flex containers, with\n * resize splitters between siblings and a chrome strip per leaf.\n *\n * The renderer keeps a small per-leaf DOM cache so content factories\n * mount exactly once per (kind, props) pair \u2014 switching the focused\n * leaf or resizing doesn't re-mount tabs / pages.\n */\n\nconst SPLITTER_PX = 4;\n\nexport class TileRenderer {\n constructor({ root, tree, content, ctx, onFocusChange }) {\n if (!content || typeof content.mount !== 'function') {\n throw new Error('TileRenderer: a content registry is required');\n }\n this.root = root;\n this.tree = tree;\n // Shell-scoped kind -> factory table (see content_registry.js).\n this.content = content;\n this.ctx = ctx || {};\n this.onFocusChange = onFocusChange || (() => {});\n // leafId -> { wrapEl, bodyEl, chromeEl, content, kindKey }\n this._leafCache = new Map();\n this._drag = null;\n this.root.classList.add('twm-root');\n this.root.addEventListener('mousedown', this._onMouseDown.bind(this));\n }\n\n render() {\n // Detaching a wrap (remove() then re-append() in `_mount`) wipes\n // `scrollTop` on every scrollable descendant of that wrap.\n // Snapshot per-leaf so we can restore after re-attach \u2014 keyed\n // by element refs that survive the detach.\n const savedScrolls = new Map(); // leafId -> [{el, top}, \u2026]\n for (const [leafId, entry] of this._leafCache.entries()) {\n const snap = [];\n entry.wrapEl.querySelectorAll('*').forEach((el) => {\n if (el.scrollTop > 0 || el.scrollLeft > 0) {\n snap.push({ el, top: el.scrollTop, left: el.scrollLeft });\n }\n });\n savedScrolls.set(leafId, snap);\n entry.wrapEl.remove();\n }\n this.root.innerHTML = '';\n const tree = this.tree;\n if (!tree.rootId) {\n const empty = document.createElement('div');\n empty.className = 'twm-empty';\n empty.textContent = 'Empty desktop \u2014 Ctrl+K to open something.';\n this.root.appendChild(empty);\n this._cleanCache(new Set());\n return;\n }\n const liveLeafIds = new Set();\n this._mount(tree.rootId, this.root, liveLeafIds);\n this._cleanCache(liveLeafIds);\n this._updateFocusClasses();\n\n // Restore scrolls \u2014 once synchronously and once next frame so\n // any layout reflow between detach/reattach doesn't leave the\n // browser's clamped value in place.\n const restore = () => {\n for (const [leafId, snap] of savedScrolls) {\n if (!this._leafCache.has(leafId)) continue;\n for (const { el, top, left } of snap) {\n if (el.isConnected) {\n el.scrollTop = top;\n el.scrollLeft = left;\n }\n }\n }\n };\n restore();\n requestAnimationFrame(restore);\n }\n\n _cleanCache(liveSet) {\n for (const [leafId, entry] of [...this._leafCache.entries()]) {\n if (!liveSet.has(leafId)) {\n try { entry.content?.destroy?.(); } catch (_) {}\n entry.wrapEl.remove();\n this._leafCache.delete(leafId);\n }\n }\n }\n\n _mount(nodeId, parentEl, liveSet) {\n const node = this.tree.get(nodeId);\n if (!node) return;\n if (node.kind === 'leaf') {\n liveSet.add(node.id);\n const el = this._leafEl(node);\n parentEl.appendChild(el);\n return;\n }\n // Split node \u2014 flex container with N children + N-1 splitters.\n const split = document.createElement('div');\n split.className = `twm-split twm-split--${node.dir}`;\n split.dataset.splitId = node.id;\n parentEl.appendChild(split);\n const total = node.sizes.reduce((a, b) => a + b, 0) || node.children.length;\n node.children.forEach((cid, i) => {\n const slot = document.createElement('div');\n slot.className = 'twm-slot';\n const frac = (node.sizes[i] || 1) / total;\n slot.style.flex = `${frac} ${frac} 0`;\n split.appendChild(slot);\n this._mount(cid, slot, liveSet);\n if (i < node.children.length - 1) {\n const splitter = document.createElement('div');\n splitter.className = `twm-splitter twm-splitter--${node.dir}`;\n splitter.dataset.splitId = node.id;\n splitter.dataset.slotIdx = String(i);\n split.appendChild(splitter);\n }\n });\n }\n\n _leafEl(leaf) {\n // Tab strip key is part of the cache key so the strip's chrome\n // (which tabs exist, which one is active) re-renders when tabs\n // mutate, but the active tab's body itself stays cached when the\n // user clicks back to a tab they already visited.\n const activeTab = (Array.isArray(leaf.tabs) && leaf.tabs.length > 0)\n ? leaf.tabs[Math.max(0, Math.min(leaf.tabs.length - 1, leaf.activeTabIdx || 0))]\n : null;\n const tabFingerprint = (leaf.tabs || []).map((t) =>\n `${t.kind}::${JSON.stringify(t.props || {})}`).join('|') + `#${leaf.activeTabIdx || 0}`;\n const kindKey = leaf.content\n ? `${leaf.content.kind}::${JSON.stringify(leaf.content.props || {})}::tabs:${tabFingerprint}`\n : '__empty__';\n\n let entry = this._leafCache.get(leaf.id);\n if (entry && entry.kindKey === kindKey) {\n entry.titleEl.textContent = leaf.title || (leaf.content ? leaf.content.kind : 'empty');\n return entry.wrapEl;\n }\n // Build fresh.\n if (entry) {\n try { entry.content?.destroy?.(); } catch (_) {}\n entry.wrapEl.remove();\n }\n const wrap = document.createElement('div');\n wrap.className = 'twm-leaf';\n wrap.dataset.leafId = leaf.id;\n // No tabIndex on the wrap \u2014 that would capture focus on click\n // and break the `hostEl.contains(document.activeElement)` guard\n // many tab modules use to scope their keyboard handlers. The\n // body is given tabIndex=-1 below so we can focus the body\n // (which IS the hostEl seen by the mounted tab content) on\n // tile activation.\n const chrome = document.createElement('div');\n chrome.className = 'twm-leaf__chrome';\n const title = document.createElement('span');\n title.className = 'twm-leaf__title';\n title.textContent = leaf.title || (leaf.content ? leaf.content.kind : 'empty');\n const actions = document.createElement('span');\n actions.className = 'twm-leaf__actions';\n // Panel tiles (left nav / right / bottom) can't be promoted to\n // managed windows \u2014 they're chrome, not content. Hide the\n // promote button in their chrome.\n const isPanel = String(leaf.content?.kind || '').startsWith('panel:');\n // Split + promote are structural actions on a content tile; panels\n // (left nav / right / bottom) are chrome, not content, so they only\n // get the close affordance.\n actions.innerHTML = `\n ${isPanel ? '' : `\n <button class=\"twm-leaf__btn\" data-action=\"split-h\" title=\"Split horizontally (Alt+H)\">\n <span class=\"material-symbols-outlined\">splitscreen_vertical_add</span>\n </button>\n <button class=\"twm-leaf__btn\" data-action=\"split-v\" title=\"Split vertically (Alt+V)\">\n <span class=\"material-symbols-outlined\">splitscreen_add</span>\n </button>\n <button class=\"twm-leaf__btn\" data-action=\"promote\" title=\"Promote to window (Alt+F)\">\n <span class=\"material-symbols-outlined\">open_in_new</span>\n </button>`}\n <button class=\"twm-leaf__btn\" data-action=\"close\" title=\"Close (Alt+W)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n `;\n chrome.append(title, actions);\n const body = document.createElement('div');\n body.className = 'twm-leaf__body';\n body.tabIndex = -1; // focusable via JS so document.activeElement\n // lands inside the body when the tile is\n // activated (keyboard-handler scope check).\n // Bottom tab strip \u2014 only rendered when the leaf carries\n // more than one tab. The strip is built/rebuilt as part of\n // the leaf element, not the body, so it stays pinned at the\n // bottom of the tile regardless of body scroll.\n const tabBar = document.createElement('div');\n tabBar.className = 'twm-leaf__tabbar';\n if (!Array.isArray(leaf.tabs) || leaf.tabs.length <= 1) {\n tabBar.classList.add('twm-leaf__tabbar--hidden');\n }\n wrap.append(chrome, body, tabBar);\n\n wrap.addEventListener('mousedown', (e) => {\n if (e.target.closest('.twm-splitter')) return;\n this.tree.focus(leaf.id);\n this._updateFocusClasses();\n this.onFocusChange(leaf.id);\n // Park focus on the deepest focus host inside the body so\n // page modules whose keydown scope is\n // `hostEl.contains(document.activeElement)` actually see\n // the activation. The page-shell wrapper, when present,\n // is what tab modules treat as `hostEl`; falling back to\n // the leaf body itself is fine for panel tiles.\n const tgt = e.target;\n const focusable = tgt.closest?.(\n 'input, textarea, select, button, a, [contenteditable=\"true\"], [tabindex]');\n if (!focusable || !body.contains(focusable)) {\n setTimeout(() => {\n const ps = body.querySelector('.twm-page-shell__content')\n ?? body;\n if (ps.tabIndex == null || ps.tabIndex < -1) ps.tabIndex = -1;\n ps.focus({ preventScroll: true });\n }, 0);\n }\n });\n // Right-click on the chrome \u2192 tile context menu (split, close,\n // promote, move to desktop). Listening on `chrome` only so the\n // tile body keeps its own contextmenu (e.g. DataTable's).\n chrome.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.tree.focus(leaf.id);\n this._updateFocusClasses();\n this.onFocusChange(leaf.id);\n this.ctx.onTileContextMenu?.(leaf.id, e.clientX, e.clientY);\n });\n actions.addEventListener('click', (e) => {\n const btn = e.target.closest('button');\n if (!btn) return;\n e.stopPropagation();\n this.ctx.onLeafAction?.(leaf.id, btn.dataset.action);\n });\n\n // Mount content. The per-leaf ctx carries `leafId` so the\n // mounted content can route subsequent navigation (e.g.\n // `workspaceTabs.openTab(...)`) back into its own tile via\n // `wm.openFromContext(ctx, ...)` instead of always hitting\n // the primary tile.\n let content = {};\n if (leaf.content) {\n const leafCtx = { ...this.ctx, leafId: leaf.id };\n // Mount with the ACTIVE TAB's props, not `content.props`.\n // `wm.updateActiveTabProps` (the canonical per-tile view-state\n // store \u2014 survives reload + desktop switches via desktops.json)\n // writes only into `tabs[active].props` and deliberately leaves\n // `content.props` untouched so the cache key (kindKey) stays\n // stable and a tab-prop change doesn't churn-rebuild the leaf.\n // The trade-off: `content.props` goes stale, so a leaf rebuilt\n // after a desktop round-trip must read the fresh tab props here.\n const activeProps = activeTab?.props ?? leaf.content.props;\n content = this.content.mount(leaf.content.kind, body, activeProps, leafCtx);\n if (content.title) title.textContent = content.title;\n } else {\n body.innerHTML = `<div class=\"tile-placeholder\"><div class=\"tile-placeholder__hint\">empty tile</div></div>`;\n }\n entry = { wrapEl: wrap, bodyEl: body, chromeEl: chrome,\n titleEl: title, content, kindKey, tabBarEl: tabBar };\n this._leafCache.set(leaf.id, entry);\n\n // Render tab strip last so it has access to the cached entry.\n this._renderTabBar(leaf, entry);\n return wrap;\n }\n\n /** Paint a leaf's bottom tab strip. The strip is hidden for\n * single-tab leaves (the common case) so existing layouts read as\n * identical to today. Hamburger button at the start, then one\n * trapezoid-shaped tab per stored tab spec. */\n _renderTabBar(leaf, entry) {\n const bar = entry.tabBarEl;\n if (!bar) return;\n const tabs = Array.isArray(leaf.tabs) ? leaf.tabs : [];\n if (tabs.length <= 1) {\n bar.classList.add('twm-leaf__tabbar--hidden');\n bar.innerHTML = '';\n return;\n }\n bar.classList.remove('twm-leaf__tabbar--hidden');\n const activeIdx = Math.max(0, Math.min(tabs.length - 1, leaf.activeTabIdx || 0));\n bar.innerHTML = `\n <button type=\"button\" class=\"twm-leaf__tab-hamburger\"\n data-action=\"tab-menu\"\n title=\"Open in new tab from this page's content\">\n <span class=\"material-symbols-outlined\">menu</span>\n </button>\n <ol class=\"twm-leaf__tabs\" role=\"tablist\">\n ${tabs.map((t, i) => `\n <li class=\"twm-leaf__tab${i === activeIdx ? ' twm-leaf__tab--on' : ''}\"\n role=\"tab\" data-tab-idx=\"${i}\"\n title=\"${_esc(t.title || t.kind)}\"\n draggable=\"true\">\n <span class=\"twm-leaf__tab-label\">${_esc(t.title || t.kind)}</span>\n <button type=\"button\" class=\"twm-leaf__tab-close\"\n data-action=\"tab-close\" data-tab-idx=\"${i}\"\n title=\"Close this tab\"\n aria-label=\"Close tab\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </li>\n `).join('')}\n </ol>\n `;\n\n // Tab activation. Click anywhere on a tab (except its \u00D7 button)\n // switches to it; the \u00D7 closes it.\n bar.querySelectorAll('.twm-leaf__tab').forEach((li) => {\n li.addEventListener('click', (ev) => {\n if (ev.target.closest('[data-action=\"tab-close\"]')) return;\n const idx = Number(li.dataset.tabIdx);\n this.ctx.onLeafTabAction?.(leaf.id, 'switch', { idx });\n });\n // Right-click \u2192 browser-style tab context menu (close, close\n // others, close right / left). The WM mounts the actual menu\n // \u2014 we just hand it the (idx, x, y) anchor.\n li.addEventListener('contextmenu', (ev) => {\n ev.preventDefault();\n ev.stopPropagation();\n const idx = Number(li.dataset.tabIdx);\n this.ctx.onLeafTabAction?.(leaf.id, 'menu',\n { idx, x: ev.clientX, y: ev.clientY });\n });\n });\n bar.querySelectorAll('[data-action=\"tab-close\"]').forEach((btn) => {\n btn.addEventListener('click', (ev) => {\n ev.preventDefault();\n ev.stopPropagation();\n const idx = Number(btn.dataset.tabIdx);\n this.ctx.onLeafTabAction?.(leaf.id, 'close', { idx });\n });\n });\n bar.querySelector('[data-action=\"tab-menu\"]')\n ?.addEventListener('click', (ev) => {\n ev.preventDefault();\n const r = ev.currentTarget.getBoundingClientRect();\n this.ctx.onLeafTabAction?.(leaf.id, 'open-menu',\n { x: r.left, y: r.top });\n });\n\n // Drag-to-reorder. Stash the source idx in dataTransfer; the\n // drop target reads it and emits a 'move' action. We don't use\n // HTML5 setData('text/plain') for the live state because the\n // dragstart/drop pair runs entirely within the same tab list.\n let dragFromIdx = null;\n bar.querySelectorAll('.twm-leaf__tab').forEach((li) => {\n li.addEventListener('dragstart', (ev) => {\n dragFromIdx = Number(li.dataset.tabIdx);\n ev.dataTransfer.effectAllowed = 'move';\n // Firefox refuses to start a drag unless setData is\n // called \u2014 supply a placeholder string.\n try { ev.dataTransfer.setData('text/plain', String(dragFromIdx)); }\n catch {}\n });\n li.addEventListener('dragover', (ev) => {\n if (dragFromIdx == null) return;\n ev.preventDefault();\n ev.dataTransfer.dropEffect = 'move';\n });\n li.addEventListener('drop', (ev) => {\n if (dragFromIdx == null) return;\n ev.preventDefault();\n const toIdx = Number(li.dataset.tabIdx);\n if (toIdx !== dragFromIdx) {\n this.ctx.onLeafTabAction?.(leaf.id, 'move',\n { from: dragFromIdx, to: toIdx });\n }\n dragFromIdx = null;\n });\n });\n }\n\n _updateFocusClasses() {\n const focused = this.tree.focusedLeafId;\n for (const [leafId, entry] of this._leafCache) {\n entry.wrapEl.classList.toggle('twm-leaf--focused', leafId === focused);\n }\n }\n\n /** The `.twm-leaf` wrap element for a leaf id, or null if it isn't\n * currently rendered. Used by the panel-key router to resolve which\n * DOM subtree owns keyboard input. */\n leafEl(leafId) {\n return this._leafCache.get(leafId)?.wrapEl || null;\n }\n\n // \u2500\u2500 Drag-resize \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _onMouseDown(e) {\n const splitter = e.target.closest('.twm-splitter');\n if (!splitter) return;\n e.preventDefault();\n const splitId = splitter.dataset.splitId;\n const slotIdx = Number(splitter.dataset.slotIdx);\n const split = this.tree.get(splitId);\n if (!split) return;\n const containerEl = splitter.parentElement;\n const horizontal = split.dir === 'h';\n const rect = containerEl.getBoundingClientRect();\n const totalPx = horizontal ? rect.width : rect.height;\n this._drag = {\n splitId, slotIdx, horizontal, totalPx,\n startSizes: split.sizes.slice(),\n startPos: horizontal ? e.clientX : e.clientY,\n split,\n };\n document.body.classList.add('twm-dragging');\n const move = (ev) => this._onMouseMove(ev);\n const up = (ev) => {\n this._onMouseUp(ev);\n document.removeEventListener('mousemove', move);\n document.removeEventListener('mouseup', up);\n };\n document.addEventListener('mousemove', move);\n document.addEventListener('mouseup', up);\n }\n\n _onMouseMove(e) {\n if (!this._drag) return;\n const { horizontal, totalPx, startSizes, startPos, slotIdx, split } = this._drag;\n const delta = (horizontal ? e.clientX : e.clientY) - startPos;\n const totalSize = startSizes.reduce((a, b) => a + b, 0);\n const px = totalPx - SPLITTER_PX * (split.children.length - 1);\n if (px <= 0) return;\n const deltaFrac = (delta / px) * totalSize;\n const minFrac = totalSize * 0.05;\n const newSizes = startSizes.slice();\n newSizes[slotIdx] = Math.max(minFrac, startSizes[slotIdx] + deltaFrac);\n newSizes[slotIdx + 1] = Math.max(minFrac, startSizes[slotIdx + 1] - deltaFrac);\n // Snap back to total to avoid drift.\n const sum = newSizes.reduce((a, b) => a + b, 0);\n const scale = totalSize / sum;\n for (let i = 0; i < newSizes.length; i++) newSizes[i] *= scale;\n this.tree.setSplitSizes(split.id, newSizes);\n // Cheap update: just rewrite flex on the slots.\n const containerEl = document.querySelector(`.twm-split[data-split-id=\"${split.id}\"]`);\n if (!containerEl) return;\n const slots = containerEl.querySelectorAll(':scope > .twm-slot');\n slots.forEach((slot, i) => {\n const frac = newSizes[i] / totalSize;\n slot.style.flex = `${frac} ${frac} 0`;\n });\n }\n\n _onMouseUp() {\n this._drag = null;\n document.body.classList.remove('twm-dragging');\n }\n}\n\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n}\n", "/**\n * wm.js \u2014 WindowManager facade. Owns the desktop manager, the active\n * tree's renderer, the managed-window stack, and the panel-tile state.\n * Exposes a small imperative API consumed by the palette, keymap, top\n * bar, bottom bar, and nav panel.\n *\n * wm.openInPrimary(kind, props) load a content into the primary tile\n * wm.split(dir) split the focused tile\n * wm.closeFocused() close the focused tile\n * wm.focusDir(dir) / wm.moveFocused(dir)\n * wm.toggleManagedFocused() tile <-> managed window\n * wm.togglePanel(side) left | right | bottom\n * wm.isPanelOpen(side) boolean\n * wm.switchDesktop(idx) / wm.addDesktop() / wm.moveFocusedToDesktop(idx)\n */\n\nimport { DesktopManager, saveDesktops, loadDesktops } from './desktops.js';\nimport { TileRenderer } from './tile_renderer.js';\nimport { makeLeaf } from './tile_tree.js';\nimport { PLACEHOLDER_KIND } from './content_registry.js';\nimport { installPanelKeyRouter } from './panel_keys.js';\nimport { ManagedWindow } from '../ui/components/managed_window.js';\nimport { showContextMenu } from '../ui/components/context_menu.js';\n\nconst PANEL_KINDS = new Set(['panel:left', 'panel:right', 'panel:bottom']);\n\nconst PANEL_TITLES = {\n left: 'Navigator',\n right: 'Inspector',\n bottom: 'Console',\n};\n\nexport class WindowManager {\n constructor({ rootEl, api, ctx, onChange, eventBus, host, taxonomy, events, content }) {\n if (!taxonomy) throw new Error('WindowManager: a taxonomy is required');\n if (!content || typeof content.mount !== 'function') {\n throw new Error('WindowManager: a content registry is required '\n + '(createContentRegistry / createShell owns it)');\n }\n this.rootEl = rootEl;\n // The shell-scoped content registry (kind -> factory). NOT a module\n // singleton: two shells on one page must not share a kind table, and\n // nothing may register a kind after the first mount.\n this.content = content;\n this.api = api || null;\n // The host port. `this.api` stays: 20 domain page factories still read\n // `ctx.api` \u2014 that coupling is P3's problem, not the host port's.\n this.host = host || null;\n // The injected ontology (see tiling/kind_taxonomy.js). The WM asks it\n // for Backspace parents and top-nav sections; it names no kind itself.\n this.taxonomy = taxonomy;\n // Bus events the shell reacts to. Absent key \u21D2 no subscription.\n this.events = events || {};\n this.ctx = ctx || {};\n this.eventBus = eventBus || null;\n this.onChange = onChange || (() => {});\n\n // The leaf a fresh or emptied desktop starts with. Comes from the\n // taxonomy's root kind \u2014 NOT a hardcoded 'home'. An embedder with a\n // different ontology used to get an EcoAgent Home tile it had never\n // registered, and therefore the content_registry placeholder.\n this._rootLeaf = () => {\n const kind = this.taxonomy.root;\n return {\n content: { kind, props: {} },\n title: this.taxonomy.meta(kind)?.label || kind,\n };\n };\n this.desktops = new DesktopManager({ seed: this._rootLeaf });\n this.renderer = new TileRenderer({\n root: rootEl,\n tree: this.desktops.active().tree,\n content,\n ctx: {\n ...this.ctx,\n wm: this,\n onLeafAction: (leafId, action) => this._leafAction(leafId, action),\n onLeafTabAction: (leafId, action, data) =>\n this._leafTabAction(leafId, action, data),\n },\n onFocusChange: () => this._notifyChange(),\n });\n this._persistTimer = null;\n // Window-id \u2192 leaf-id mapping so a managed-window demote can\n // restore its original tile slot.\n this._windowToLeaf = new Map();\n\n // Central keyboard router: panels register key handlers and the\n // router dispatches each keydown only to the panel inside the\n // currently focused leaf (see panel_keys.js). One authority for\n // \"which panel owns the keyboard\" instead of every panel guessing\n // from document.activeElement.\n this.panelKeys = installPanelKeyRouter(this);\n\n // Live-update tab titles when entities are renamed. The embedder\n // names the event (`events.entityRenamed`); its per-entity editors\n // fire it on Save. Walks every leaf's `tabs` and `pageTabs` archive\n // so an archived page's tab labels stay accurate too. No event\n // configured \u21D2 no subscription, and tab titles are simply static.\n const renamedEvent = this.events.entityRenamed;\n if (renamedEvent) {\n this.eventBus?.on?.(renamedEvent, ({ kind, entityId, label } = {}) => {\n if (!kind || !entityId || !label) return;\n let touched = false;\n for (const d of this.desktops.desktops) {\n if (d.tree.renameMatchingTabs?.(kind, entityId, label)) {\n touched = true;\n }\n }\n if (touched) {\n this.renderer.render();\n this._persist();\n }\n });\n }\n }\n\n /** Emit on bus + call onChange. Use this instead of the bare callback\n * so other surfaces (palette, top-bar toggles, page shortcuts) can\n * subscribe through the existing event system. */\n _notifyChange(reason = null) {\n try { this.onChange(reason); } catch (err) { console.error('[wm] onChange threw', err); }\n try { this.eventBus?.emit?.('wm:changed', { reason, wm: this }); }\n catch (err) { console.warn('[wm] event emit failed', err); }\n // Emit the canonical `workspace:tabs:activated` event for the\n // current primary leaf \u2014 the existing sidebars (ProjectSidebar\n // etc.) already listen for this to highlight the active row.\n try {\n const tree = this._tree();\n const id = tree.primaryLeafId();\n const leaf = id ? tree.get(id) : null;\n const kind = leaf?.content?.kind;\n if (kind && kind !== 'window-placeholder') {\n this.eventBus?.emit?.('workspace:tabs:activated', {\n kind,\n entityId: leaf.content.props?.id ?? null,\n label: leaf.title,\n from: reason || 'wm',\n });\n }\n } catch (_) {}\n }\n\n // \u2500\u2500 Persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 async load() {\n const blob = await loadDesktops(this.host?.state);\n if (blob) {\n this.desktops = DesktopManager.deserialize(blob, { seed: this._rootLeaf });\n this.renderer.tree = this.desktops.active().tree;\n }\n // Normalize: managed windows don't survive a reload, so any\n // window-placeholder leaves restore their original content.\n for (const d of this.desktops.desktops) {\n for (const leaf of d.tree.leaves()) {\n if (leaf.content?.kind === PLACEHOLDER_KIND) {\n const p = leaf.content.props || {};\n if (p.originalKind) {\n d.tree.setLeafContent(leaf.id,\n { kind: p.originalKind, props: p.originalProps || {} },\n p.originalTitle || p.originalKind);\n }\n }\n }\n this._canonicalize(d.tree, d);\n }\n this.renderer.tree = this.desktops.active().tree;\n this.renderer.render();\n this._notifyChange();\n }\n\n _persist() {\n if (this._persistTimer) clearTimeout(this._persistTimer);\n this._persistTimer = setTimeout(async () => {\n this._persistTimer = null;\n await saveDesktops(this.host?.state, this.desktops.serialize());\n }, 500);\n }\n\n // \u2500\u2500 Content loading \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Load content into the primary tile (last-active non-panel leaf).\n /** Walk back one step. Bound to Backspace.\n *\n * Priority order:\n * 1. Active tab's per-tab history stack (browser-style \"back\"):\n * any in-tile navigation (relationships click-through,\n * landing-row open, \"Open\" buttons inside tables) pushed\n * the previous state, and Backspace pops it. This is the\n * canonical user-facing back affordance.\n * 2. When the history is empty (the user landed on this page\n * via top-nav / palette / direct link), fall back to the\n * canonical taxonomy walk: a sub-page goes to its\n * top-nav, a top-nav page goes to Home.\n *\n * Adding a new kind to the injected taxonomy wires the fallback path\n * for Backspace + breadcrumb + top-nav highlight in one shot.\n * Adding a new \"Open from X\" click that should be a back-able\n * navigation just needs to use one of the in-tile routing\n * methods (openFromContext / openInLeaf / navigateActiveTab) \u2014\n * they all record history by default. */\n navigateBack() {\n const tree = this._tree();\n // Prefer the FOCUSED leaf \u2014 that's where the user was just\n // interacting (Open click, breadcrumb step, etc.). Falls back\n // to the primary leaf for keyboard-driven Backspace when no\n // tile is explicitly focused (panels excluded). If the focused\n // leaf is a panel, walk back on the primary content leaf\n // instead (Backspace from the nav panel should still navigate\n // the user's content area).\n const focusedId = tree.focusedLeafId;\n const primaryId = tree.primaryLeafId();\n const focusedLeaf = focusedId ? tree.get(focusedId) : null;\n const focusedKind = focusedLeaf?.content?.kind || '';\n const id = (focusedId && focusedKind\n && !focusedKind.startsWith('panel:')\n && focusedKind !== 'window-placeholder')\n ? focusedId : primaryId;\n if (!id) return;\n // (1) Per-tab history pop, if anything was recorded.\n const prior = tree.popActiveTabHistory?.(id);\n if (prior && prior.kind) {\n // Cross-page back entries carry a `topNav` marker \u2014 pop\n // routes via swapToPage so we land on the correct page.\n const leafNow = tree.get(id);\n const curKind = leafNow?.content?.kind;\n const curTopNav = curKind ? this.taxonomy.topNavFor(curKind) : null;\n if (prior.topNav && curTopNav && prior.topNav !== curTopNav) {\n tree.swapToPage?.(\n id,\n { kind: prior.kind, props: prior.props || {},\n title: prior.title || _tabTitle(prior.kind, prior.props) },\n curTopNav, prior.topNav,\n { recordHistory: false },\n );\n } else {\n tree.replaceActiveTabContent(\n id,\n { kind: prior.kind, props: prior.props || {} },\n prior.title || _tabTitle(prior.kind, prior.props),\n { recordHistory: false },\n );\n }\n tree.focus(id);\n this.renderer.render();\n this._persist();\n this._notifyChange('navigate-back');\n return;\n }\n // (2) Taxonomy fallback \u2014 the user's path is gone, so walk the\n // canonical parent instead. An ENTITY-level parent wins (the\n // instance one level up, e.g. the parent an id names); failing\n // that, the KIND-level parent (this page's section).\n const leaf = tree.get(id);\n if (!leaf?.content) return;\n const { kind, props } = leaf.content;\n const up = this.taxonomy.parentOf(kind, props);\n if (up) { this.navigateActiveTab(id, up.kind, up.props); return; }\n const parent = this.taxonomy.parentKindFor(kind);\n if (parent) this.navigateActiveTab(id, parent);\n }\n\n /** True when `navigateBack` would do something user-visible \u2014 i.e.\n * the active tab has per-tab history, OR the current kind has a\n * taxonomy parent. Used by the breadcrumb to grey out / hide the\n * Back button when there's nowhere to go. */\n canNavigateBack() {\n const tree = this._tree();\n const focusedId = tree.focusedLeafId;\n const primaryId = tree.primaryLeafId();\n const focusedLeaf = focusedId ? tree.get(focusedId) : null;\n const focusedKind = focusedLeaf?.content?.kind || '';\n const id = (focusedId && focusedKind\n && !focusedKind.startsWith('panel:')\n && focusedKind !== 'window-placeholder')\n ? focusedId : primaryId;\n if (!id) return false;\n const history = tree.activeTabHistory?.(id) || [];\n if (history.length > 0) return true;\n const leaf = tree.get(id);\n const kind = leaf?.content?.kind;\n return !!(kind && this.taxonomy.parentKindFor(kind));\n }\n\n /** Persist editor sub-state (e.g. active sub-tab) into the active\n * tab's WM props so future history snapshots restore the user's\n * view rather than the default landing. Pure metadata write \u2014 no\n * re-render, no history push. */\n updateActiveTabProps(leafId, patch) {\n const tree = this._tree();\n if (!tree?.updateActiveTabProps) return;\n tree.updateActiveTabProps(leafId, patch);\n this._persist();\n }\n\n /** Navigate inside the current tab \u2014 preserves every other tab in\n * the leaf. Used by Backspace + breadcrumb segments + anything\n * else that should walk WITHIN the tile rather than reset it. */\n navigateActiveTab(leafId, kind, props = {}) {\n const tree = this._tree();\n const leaf = tree.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') {\n this.openInPrimary(kind, props);\n return;\n }\n tree.replaceActiveTabContent(leafId, { kind, props }, _tabTitle(kind, props));\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('navigate-active-tab');\n }\n\n /** Route a navigation request to the right container based on\n * where it came from:\n *\n * - `ctx.windowId` set \u2192 replace the managed-window content (the\n * user is navigating inside a windowed tile; the window stays).\n * - `ctx.leafId` set AND that leaf is NOT `panel:left` \u2192 replace\n * the leaf's content in place (the user is in a split tile;\n * the click stays in that tile).\n * - Otherwise (palette, top-nav shortcuts, click in the\n * navigator panel, backspace, plain bus event) \u2192 primary tile.\n *\n * The left nav (`panel:left`) is the only tile whose clicks\n * intentionally jump out to the primary tile \u2014 every other\n * container is self-contained. */\n openFromContext(ctx, kind, props = {}) {\n if (ctx?.windowId && this._windowToLeaf.has(ctx.windowId)) {\n this.openInWindow(ctx.windowId, kind, props);\n return;\n }\n if (ctx?.leafId) {\n const tree = this._tree();\n const leaf = tree.get(ctx.leafId);\n const k = leaf?.content?.kind;\n if (leaf && k && k !== 'panel:left' && !k.startsWith('panel:')) {\n this.openInLeaf(ctx.leafId, kind, props);\n return;\n }\n }\n this.openInPrimary(kind, props);\n }\n\n /** Replace the leaf's **active tab** in place \u2014 preserves every\n * other tab. This is the routing for navigation that originated\n * INSIDE the tile: clicking a row on a landing page, walking a\n * breadcrumb segment, Backspace. Outside-the-tile navigation\n * (top-nav, palette, side-nav) uses `openInPrimary` instead, which\n * resets the leaf to a single fresh tab.\n *\n * For a leaf that has only one tab (the common case before the\n * tab feature shipped), the behavior is identical to the old\n * setLeafContent: one tab in, one tab out. */\n openInLeaf(leafId, kind, props = {}) {\n const tree = this._tree();\n const leaf = tree.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') {\n this.openInPrimary(kind, props);\n return;\n }\n tree.replaceActiveTabContent(leafId, { kind, props }, _tabTitle(kind, props));\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n /** Replace a managed window's content in place. Tears down the\n * previous mount, mounts the new kind into the same contentEl,\n * and updates the window's title. */\n openInWindow(winId, kind, props = {}) {\n const rec = this._windowToLeaf.get(winId);\n if (!rec) { this.openInPrimary(kind, props); return; }\n try { rec.mountInfo?.destroy?.(); } catch {}\n rec.contentEl.innerHTML = '';\n const mountInfo = this.content.mount(kind, rec.contentEl, props,\n { ...this.ctx, wm: this, windowId: winId });\n rec.mountInfo = mountInfo;\n rec.original = {\n kind, props: { ...(props || {}) },\n title: mountInfo?.title || kind,\n };\n // Update window title (DOM + the ManagedWindow instance).\n try {\n const titleEl = rec.window.element?.querySelector('.twm-managed-window__title');\n if (titleEl) titleEl.textContent = rec.original.title;\n if (rec.window) rec.window.title = rec.original.title;\n } catch {}\n // `rec.original` now holds the latest content, so a later \"back to\n // tile\" docks the current view (not the kind first promoted). The\n // window owns no tile in the tree, so there is no leaf to update.\n this._persist();\n this._notifyChange('window-content-changed');\n }\n\n /** Load content into the primary tile (last-active non-panel leaf).\n * If only panel tiles exist (or the tree is empty), spawn a new\n * content leaf and canonicalize so the panels wrap it. */\n openInPrimary(kind, props = {}) {\n const tree = this._tree();\n let leafId = tree.primaryLeafId();\n let spawned = false;\n if (!leafId) {\n leafId = this._spawnContentLeaf(tree);\n spawned = true;\n }\n if (!leafId) return;\n // Page-aware swap: archive the leaf's current page tabs and\n // restore (or initialize) the target page's. This is what makes\n // a tile remember its tab set when the user clicks away to\n // another top-nav page and back. `swapToPage` is a no-op when\n // the leaf has no current page (just-spawned content leaf) \u2014\n // the default branch initializes a fresh single tab.\n const leaf = tree.get(leafId);\n const currentTopNav = leaf?.content?.kind\n ? this.taxonomy.topNavFor(leaf.content.kind) || null\n : null;\n const targetTopNav = this.taxonomy.topNavFor(kind) || kind;\n const title = _tabTitle(kind, props);\n tree.swapToPage(leafId,\n { kind, props, title },\n currentTopNav, targetTopNav);\n tree.focus(leafId);\n if (spawned) this._canonicalize(tree, this.desktops.active());\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n // \u2500\u2500 Split / close / focus / move \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 split(dir) {\n const tree = this._tree();\n const focused = tree.focusedLeafId;\n if (!focused) return;\n tree.split(focused, dir);\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n /** Split `leafId` along `dir` and mount `kind`/`props` in the freshly\n * created sibling \u2014 the \"open this content in a new split\" primitive\n * behind the code-pane split buttons, the per-pane context menu and\n * Alt+Shift+H / Alt+Shift+V. The source leaf keeps its content\n * untouched; the new pane gets a FRESH mount (so e.g. opening a Code\n * pane in a split never dismounts the original). Returns the new\n * leaf id, or null if the leaf can't be split. */\n splitLeafWith(leafId, dir, kind, props = {}, title = '') {\n const tree = this._tree();\n const src = leafId ? tree.get(leafId) : null;\n if (!src || src.kind !== 'leaf') return null;\n const newId = tree.split(leafId, dir);\n if (!newId) return null;\n tree.setLeafContent(newId, { kind, props }, title || _tabTitle(kind, props));\n tree.focus(newId);\n this.renderer.render();\n this._persist();\n this._notifyChange('split-with');\n return newId;\n }\n\n /** Resolve the focused tile's active content for the keyboard-driven\n * \"open focused tile elsewhere\" chords (Alt+T / Alt+N / Alt+Shift+H /\n * Alt+Shift+V). Returns null for panels, window placeholders and\n * empty tiles \u2014 none of which can be meaningfully duplicated. */\n _focusedContent() {\n const tree = this._tree();\n const id = tree.focusedLeafId;\n const leaf = id ? tree.get(id) : null;\n if (!leaf || leaf.kind !== 'leaf' || !leaf.content) return null;\n const kind = leaf.content.kind;\n if (!kind || kind === PLACEHOLDER_KIND || kind.startsWith('panel:')) return null;\n return { leafId: id, kind, props: leaf.content.props || {}, title: leaf.title };\n }\n\n /** Alt+T \u2014 open the focused tile's content in a new tab on that tile. */\n openFocusedInTab() {\n const c = this._focusedContent();\n if (!c) return;\n this.openInTabFromContext({ leafId: c.leafId }, c.kind, c.props);\n }\n\n /** Alt+N \u2014 open the focused tile's content in a fresh managed window.\n * Unlike Alt+F (promote) this DUPLICATES: the source tile stays put. */\n openFocusedInWindow() {\n const c = this._focusedContent();\n if (!c) return;\n this._navigateWindow(c.kind, c.props);\n }\n\n /** Alt+Shift+H / Alt+Shift+V \u2014 split the focused tile and open a fresh\n * copy of its content in the new pane. Falls back to an empty split\n * when the focused tile has no duplicable content (e.g. a panel). */\n splitFocusedWith(dir) {\n const c = this._focusedContent();\n if (!c) { this.split(dir); return; }\n this.splitLeafWith(c.leafId, dir, c.kind, c.props, c.title);\n }\n\n closeFocused() {\n const tree = this._tree();\n const focusedId = tree.focusedLeafId;\n if (!focusedId) return;\n const leaf = tree.get(focusedId);\n const kind = leaf?.content?.kind;\n\n // Closing a placeholder closes its window \u2014 the window's onClose\n // handler restores the leaf, then we close that leaf too.\n if (kind === PLACEHOLDER_KIND) {\n const winId = leaf.content?.props?.windowId;\n const rec = winId ? this._windowToLeaf.get(winId) : null;\n if (rec) {\n // Drop the mapping so the onClose handler doesn't restore.\n this._windowToLeaf.delete(winId);\n try { rec.window.close({ force: true }); } catch {}\n }\n tree.close(focusedId);\n }\n // Closing a panel: also flip the desktop's panel state off so\n // the top-bar toggle button reflects the closure.\n else if (PANEL_KINDS.has(kind)) {\n const d = this.desktops.active();\n const side = kind.split(':')[1];\n d.panels[side] = false;\n this._canonicalize(tree, d);\n }\n else {\n tree.close(focusedId);\n }\n\n // Re-canonicalize so the remaining panels fill the area\n // properly (no leftover wrap from the content leaf). The user\n // is allowed to close the last content tile \u2014 the panels can\n // fully occupy the WM. A new content leaf is spawned later by\n // openInPrimary when something needs it.\n this._canonicalize(tree, this.desktops.active());\n\n this.renderer.render();\n this._persist();\n this._notifyChange('tile-closed');\n }\n\n /** Close the ACTIVE tab of a leaf (e.g. a Cancel button inside the\n * tab's content). Mirrors the tab-strip \u00D7 handler: remove just that\n * tab, or close the whole tile if it was the last one. Lets content\n * self-close without nuking sibling tabs. */\n closeActiveTab(leafId) {\n const tree = this._tree();\n const leaf = leafId ? tree.get(leafId) : null;\n if (!leaf || leaf.kind !== 'leaf') {\n // No tabbed leaf (e.g. content in a managed window) \u2014 fall\n // back to closing the focused container.\n this.closeFocused();\n return;\n }\n const tabs = leaf.tabs || [];\n if (tabs.length <= 1) {\n tree.focus(leafId);\n this.closeFocused();\n return;\n }\n const idx = Math.max(0, Math.min(tabs.length - 1, leaf.activeTabIdx || 0));\n tree.removeLeafTab(leafId, idx);\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('twm-tab-close');\n }\n\n /** Insert a new empty content leaf at the centre of the layout\n * (wraps the current root in an h-split with the content on the\n * left, 4:1 ratio). If the tree is empty, becomes the root. */\n _spawnContentLeaf(tree) {\n const newLeaf = makeLeaf({ content: null, title: '' });\n if (!tree.rootId) { tree.setRoot(newLeaf); return newLeaf.id; }\n tree._register(newLeaf);\n const split = {\n id: `split-spawn-${Date.now().toString(36)}`,\n kind: 'split', parentId: null, dir: 'h',\n children: [newLeaf.id, tree.rootId], sizes: [4, 1],\n };\n tree.nodes.set(split.id, split);\n const oldRoot = tree.get(tree.rootId);\n if (oldRoot) oldRoot.parentId = split.id;\n newLeaf.parentId = split.id;\n tree.rootId = split.id;\n tree.focus(newLeaf.id);\n return newLeaf.id;\n }\n\n focusDir(dir) {\n if (this._tree().focusDir(dir)) {\n this.renderer._updateFocusClasses();\n this._notifyChange();\n }\n }\n\n /** The `.twm-leaf` DOM element of the currently focused leaf on the\n * active desktop, or null. The panel-key router consults this to\n * decide which panel owns the keyboard \u2014 it is the single source of\n * truth for \"the selected tile\". */\n focusedLeafEl() {\n const id = this._tree().focusedLeafId;\n return id ? this.renderer.leafEl(id) : null;\n }\n\n moveFocused(dir) {\n if (this._tree().moveDir(dir)) {\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n }\n\n // \u2500\u2500 Tile <-> Managed window \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Promote the focused tile into a managed window and CLOSE the\n * source tile \u2014 promoting means the content leaves the grid, so the\n * origin slot is removed rather than left as an empty placeholder.\n * \"Back to tile\" re-docks the content into the primary tile. */\n toggleManagedFocused() {\n const tree = this._tree();\n const focused = tree.focused();\n if (!focused || !focused.content) return;\n if (PANEL_KINDS.has(focused.content.kind)) return;\n if (focused.content.kind === PLACEHOLDER_KIND) return;\n\n const leafId = focused.id;\n const desktopIdx = this.desktops.activeIdx;\n const original = {\n kind: focused.content.kind,\n props: { ...(focused.content.props || {}) },\n title: focused.title,\n };\n\n const contentEl = document.createElement('div');\n contentEl.className = 'twm-window-content';\n contentEl.style.cssText = 'display:flex; flex-direction:column; flex:1; min-width:0; min-height:0; height:100%;';\n\n const winId = `twm-mw-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 5)}`;\n const mountInfo = this.content.mount(original.kind, contentEl, original.props,\n { ...this.ctx, wm: this, windowId: winId });\n const win = new ManagedWindow({\n id: winId,\n title: mountInfo?.title || original.title,\n icon: 'web_asset',\n content: contentEl,\n canMinimize: true,\n canMaximize: true,\n canResize: true,\n modal: false,\n onClose: () => this._onManagedWindowClosed(winId, mountInfo),\n });\n\n this._windowToLeaf.set(winId, {\n // Promoting CLOSES the source tile \u2014 the content lives in the\n // window now, not the tree. leafId is null so \"back to tile\"\n // re-docks into the primary tile (see _onManagedWindowClosed).\n leafId: null, desktopIdx, original, mountInfo, window: win,\n contentEl,\n // Set to true by bringBackWindow so the close path knows to\n // restore the content instead of destroying it.\n _demoting: false,\n });\n\n // Close the origin tile so it doesn't linger as an empty\n // \"(window)\" placeholder. Re-canonicalize so panels reflow; the\n // desktop is allowed to end up with no content tile (panels can\n // fill it, and openInPrimary re-spawns one on demand) \u2014 same as\n // closeFocused on the last tile.\n tree.close(leafId);\n this._canonicalize(tree, this.desktops.active());\n\n this.renderer.render();\n win.show();\n this._decorateManagedWindow(win, winId);\n this._persist();\n this._notifyChange('window-promoted');\n }\n\n /** Dock the window's content back into the desktop's primary tile\n * (the source tile was closed on promote), then close the window. */\n bringBackWindow(windowId) {\n const rec = this._windowToLeaf.get(windowId);\n if (!rec) return;\n rec._demoting = true;\n try { rec.window.close({ force: true }); }\n catch (err) { console.warn('[wm] bringBack: close failed', err); }\n }\n\n /** Re-home a managed window to another desktop. The window itself\n * stays on screen (managed windows are global) and leaves no tile\n * behind on either desktop; only its \"home\" changes, so bringing it\n * back will land on the new desktop's primary tile. */\n moveWindowToDesktop(windowId, targetIdx) {\n const rec = this._windowToLeaf.get(windowId);\n if (!rec) return;\n if (rec.desktopIdx === targetIdx) return;\n this.desktops.ensureCount(targetIdx + 1);\n rec.desktopIdx = targetIdx;\n this._persist();\n this._notifyChange('window-moved');\n }\n\n _onManagedWindowClosed(winId, mountInfo) {\n const rec = this._windowToLeaf.get(winId);\n this._windowToLeaf.delete(winId);\n if (!rec) return;\n try { mountInfo?.destroy?.(); } catch {}\n const tree = this.desktops.desktops[rec.desktopIdx]?.tree;\n if (!tree) return;\n\n if (rec._demoting) {\n // \"Back to tile\": the source tile was closed when the window was\n // promoted, so dock the (latest) content into the desktop's\n // primary tile as a new tab, spawning a tile when it has none.\n let pid = tree.primaryLeafId();\n let spawned = false;\n if (!pid) { pid = this._spawnContentLeaf(tree); spawned = true; }\n if (pid) {\n tree.appendLeafTab(pid,\n { kind: rec.original.kind, props: rec.original.props },\n rec.original.title);\n tree.focus(pid);\n if (spawned) this._canonicalize(tree, this.desktops.desktops[rec.desktopIdx]);\n }\n }\n // Plain close (rec._demoting === false): the window and its content\n // are discarded. The source tile was already closed on promote, so\n // there is nothing left in the tree to clean up.\n if (this.desktops.active().tree === tree) this.renderer.render();\n this._persist();\n this._notifyChange(rec._demoting ? 'window-demoted' : 'window-closed');\n }\n\n /** Post-show DOM hook: inject a \"back to tile\" button into the\n * window chrome and wire a right-click context menu on the topbar. */\n _decorateManagedWindow(win, winId) {\n const topbar = win.element?.querySelector?.('.twm-managed-window__topbar');\n const buttons = topbar?.querySelector?.('.twm-managed-window__buttons');\n if (!buttons) return;\n const backBtn = document.createElement('button');\n backBtn.type = 'button';\n backBtn.className = 'twm-managed-window__btn managed-window__btn--demote';\n backBtn.title = 'Back to tile';\n backBtn.innerHTML = `<span class=\"material-symbols-outlined\" style=\"font-size:14px\">close_fullscreen</span>`;\n backBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.bringBackWindow(winId);\n });\n const closeBtn = buttons.querySelector('.twm-managed-window__btn--close');\n if (closeBtn) buttons.insertBefore(backBtn, closeBtn);\n else buttons.appendChild(backBtn);\n\n topbar.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n const rec = this._windowToLeaf.get(winId);\n if (!rec) return;\n const items = [\n { label: 'Back to tile', icon: 'close_fullscreen', action: 'back' },\n ];\n if (this.desktops.desktops.length > 1) {\n items.push({ separator: true });\n for (const [i, d] of this.desktops.desktops.entries()) {\n if (i === rec.desktopIdx) continue;\n items.push({\n label: `Move to desktop ${d.label}`, icon: 'sweep',\n action: `move:${i}`,\n });\n }\n }\n items.push({ separator: true });\n items.push({ label: 'Close window', icon: 'close',\n action: 'close', danger: true });\n showContextMenu(e.clientX, e.clientY, items, (action) => {\n if (action === 'back') this.bringBackWindow(winId);\n else if (action === 'close') {\n try { win.close({ force: true }); } catch {}\n }\n else if (action?.startsWith?.('move:')) {\n this.moveWindowToDesktop(winId, Number(action.slice(5)));\n }\n });\n });\n }\n\n // \u2500\u2500 Panel-tiles (left nav / right / bottom) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Panels are virtual: they live in the active desktop's tree as\n * leaves with content kinds 'panel:left', 'panel:right',\n * 'panel:bottom'. Toggling either inserts them at the appropriate\n * edge (a recursive split) or closes that leaf. */\n isPanelOpen(side) {\n const d = this.desktops.active();\n return !!d.panels[side];\n }\n\n togglePanel(side) {\n const d = this.desktops.active();\n d.panels[side] = !d.panels[side];\n this._canonicalize(this._tree(), d);\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n /** Rebuild the tree so panel:* leaves sit in the canonical positions:\n *\n * v-split\n * \u251C h-split \u2190 the \"content row\"\n * \u2502 \u251C panel:left (if open)\n * \u2502 \u251C content (whatever non-panel subtree)\n * \u2502 \u2514 panel:right (if open)\n * \u2514 panel:bottom (if open, full width below the content row)\n *\n * Existing panel leaves are detached + re-attached (same id), so the\n * renderer cache keeps the mounted content (nav filter state, etc.). */\n _canonicalize(tree, desktop) {\n // 1. Find existing panel leaves.\n const panel = {};\n for (const leaf of tree.leaves()) {\n const kind = leaf.content?.kind;\n if (kind === 'panel:left') panel.left = leaf;\n else if (kind === 'panel:right') panel.right = leaf;\n else if (kind === 'panel:bottom') panel.bottom = leaf;\n }\n\n // 2. Detach each panel leaf from its current parent. (We don't\n // use tree.close because that deletes the node; we want to\n // preserve identity so the renderer keeps the mounted body.)\n const detach = (leaf) => {\n if (!leaf) return;\n const pid = leaf.parentId;\n if (!pid) {\n tree.rootId = null;\n leaf.parentId = null;\n return;\n }\n const parent = tree.get(pid);\n if (!parent) return;\n const idx = parent.children.indexOf(leaf.id);\n if (idx >= 0) {\n parent.children.splice(idx, 1);\n parent.sizes.splice(idx, 1);\n }\n leaf.parentId = null;\n tree._collapse(parent);\n };\n detach(panel.left); detach(panel.right); detach(panel.bottom);\n\n // 3. The content subtree may legitimately be empty \u2014 the user\n // is allowed to close the last main tile and let panels\n // take over the entire WM area. If so, seed root from the\n // first requested panel; otherwise content stays as root.\n let seededSide = null;\n if (!tree.rootId) {\n seededSide = desktop.panels.left ? 'left'\n : desktop.panels.bottom ? 'bottom'\n : desktop.panels.right ? 'right'\n : null;\n if (seededSide) {\n const seed = panel[seededSide] || makeLeaf({\n content: { kind: `panel:${seededSide}`, props: {} },\n title: PANEL_TITLES[seededSide] || seededSide,\n });\n if (panel[seededSide] && PANEL_TITLES[seededSide]) {\n panel[seededSide].title = PANEL_TITLES[seededSide];\n }\n if (!panel[seededSide]) tree._register(seed);\n if (!tree.nodes.has(seed.id)) tree.nodes.set(seed.id, seed);\n seed.parentId = null;\n tree.rootId = seed.id;\n }\n // else: nothing requested; tree stays empty (renderer shows\n // the \"Empty desktop\" placeholder).\n }\n\n // 4. Wrap content row with left + right (h-split), then wrap\n // that with bottom (v-split) so bottom spans full width.\n const wrap = (panelLeaf, side) => {\n // Re-register the leaf if it was orphaned by detach.\n if (panelLeaf && !tree.nodes.has(panelLeaf.id)) {\n tree.nodes.set(panelLeaf.id, panelLeaf);\n }\n const leaf = panelLeaf || makeLeaf({\n content: { kind: `panel:${side}`, props: {} },\n title: PANEL_TITLES[side] || side,\n });\n // Heal old leaves whose stored title is still 'left'/etc.\n if (panelLeaf && PANEL_TITLES[side] && panelLeaf.title !== PANEL_TITLES[side]) {\n panelLeaf.title = PANEL_TITLES[side];\n }\n if (!panelLeaf) tree._register(leaf);\n const before = (side === 'left');\n const dir = (side === 'bottom') ? 'v' : 'h';\n const children = before ? [leaf.id, tree.rootId] : [tree.rootId, leaf.id];\n const sizes = (side === 'bottom') ? [4, 1]\n : (side === 'left') ? [1, 4]\n : [4, 1];\n const split = {\n id: `split-panel-${side}-${Math.random().toString(36).slice(2, 7)}`,\n kind: 'split', parentId: null, dir, children, sizes,\n };\n tree.nodes.set(split.id, split);\n const oldRoot = tree.get(tree.rootId);\n if (oldRoot) oldRoot.parentId = split.id;\n leaf.parentId = split.id;\n tree.rootId = split.id;\n };\n // Skip the side already consumed as the seed root (would\n // otherwise wrap a fresh duplicate leaf around the existing\n // panel-as-root).\n if (desktop.panels.left && seededSide !== 'left' && tree.rootId) wrap(panel.left, 'left');\n if (desktop.panels.right && seededSide !== 'right' && tree.rootId) wrap(panel.right, 'right');\n if (desktop.panels.bottom && seededSide !== 'bottom' && tree.rootId) wrap(panel.bottom, 'bottom');\n\n // GC orphaned nodes (panel leaves whose `panels.X` flipped to\n // false stayed in tree.nodes after detach).\n const reachable = new Set();\n const walk = (id) => {\n if (!id || reachable.has(id)) return;\n reachable.add(id);\n const n = tree.get(id);\n if (n?.kind === 'split') n.children.forEach(walk);\n };\n walk(tree.rootId);\n for (const id of [...tree.nodes.keys()]) {\n if (!reachable.has(id)) tree.nodes.delete(id);\n }\n }\n\n _findPanelLeaf(side) {\n const kind = `panel:${side}`;\n for (const leaf of this._tree().leaves()) {\n if (leaf.content?.kind === kind) return leaf;\n }\n return null;\n }\n\n // \u2500\u2500 Desktops \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 switchDesktop(idx) {\n this.desktops.ensureCount(idx + 1);\n if (!this.desktops.switchTo(idx)) return;\n const d = this.desktops.active();\n // Runtime-created desktops (ensureCount / addDesktop) are bare\n // home-leaf trees whose panels haven't been materialized yet \u2014\n // only desktops present at load() were canonicalized. Without\n // this, the new desktop shows no panels while the toggle buttons\n // (which read `d.panels`) report them open. Canonicalize on every\n // switch: it's idempotent for already-canonical trees.\n this._canonicalize(d.tree, d);\n this.renderer.tree = d.tree;\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n addDesktop() {\n this.desktops.addDesktop();\n this._notifyChange();\n this._persist();\n }\n\n /** Step to the previous (-1) or next (+1) existing desktop, wrapping\n * around. No-op with a single desktop. Iterates only desktops that\n * already exist \u2014 use switchDesktop(idx) to create-on-demand. */\n cycleDesktop(dir) {\n const m = this.desktops;\n const n = m.desktops.length;\n if (n <= 1) return;\n const next = (m.activeIdx + (dir < 0 ? -1 : 1) + n) % n;\n this.switchDesktop(next);\n }\n\n /** Cycle the focused tile's main-panel tabs (Ctrl+Tab / Ctrl+Shift+Tab).\n * Wraps; no-op when the focused leaf has 0 or 1 tabs. */\n cycleFocusedTab(dir) {\n const tree = this._tree();\n const leafId = tree.focusedLeafId;\n const leaf = leafId ? tree.get(leafId) : null;\n const tabs = (leaf && Array.isArray(leaf.tabs)) ? leaf.tabs : [];\n if (tabs.length <= 1) return;\n const cur = Math.max(0, Math.min(tabs.length - 1, leaf.activeTabIdx || 0));\n const next = (cur + (dir < 0 ? -1 : 1) + tabs.length) % tabs.length;\n this._leafTabAction(leafId, 'switch', { idx: next });\n }\n\n removeDesktop(idx) {\n const m = this.desktops;\n if (m.desktops.length <= 1) return false;\n if (idx < 0 || idx >= m.desktops.length) return false;\n m.desktops.splice(idx, 1);\n if (m.activeIdx >= m.desktops.length) m.activeIdx = m.desktops.length - 1;\n this.renderer.tree = m.active().tree;\n this.renderer.render();\n this._persist();\n this._notifyChange();\n return true;\n }\n\n moveFocusedToDesktop(idx) {\n const tree = this._tree();\n const focused = tree.focused();\n if (!focused || !focused.content) return;\n const payload = { kind: focused.content.kind, props: focused.content.props, title: focused.title };\n this.desktops.ensureCount(idx + 1);\n const target = this.desktops.desktops[idx];\n // Place into the target tree's primary leaf.\n const targetTree = target.tree;\n const primary = targetTree.primaryLeafId();\n if (primary) targetTree.setLeafContent(primary, { kind: payload.kind, props: payload.props }, payload.title);\n // Remove from current desktop.\n tree.close(focused.id);\n if (!tree.rootId) tree.setRoot(makeLeaf(this._rootLeaf()));\n this.renderer.render();\n this._persist();\n this._notifyChange();\n }\n\n // \u2500\u2500 Internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _tree() { return this.desktops.active().tree; }\n\n _leafAction(leafId, action) {\n const tree = this._tree();\n tree.focus(leafId);\n if (action === 'close') this.closeFocused();\n else if (action === 'promote') this.toggleManagedFocused();\n // Chrome split buttons mirror Alt+H / Alt+V: structural split of\n // this tile into a fresh empty pane (the user then fills it).\n else if (action === 'split-h') this.split('h');\n else if (action === 'split-v') this.split('v');\n }\n\n /** Tab-strip event dispatcher. The renderer fires actions\n * (`switch` / `close` / `move` / `open-menu`) and the WM\n * translates them into tile-tree mutations + a re-render. */\n _leafTabAction(leafId, action, data = {}) {\n const tree = this._tree();\n const leaf = tree.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') return;\n if (action === 'switch') {\n tree.setActiveLeafTab(leafId, data.idx);\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-switch');\n return;\n }\n if (action === 'close') {\n const tabs = leaf.tabs || [];\n // Closing the last remaining tab closes the tile \u2014 same\n // behavior as Alt+W on a single-tab leaf today.\n if (tabs.length <= 1) {\n tree.focus(leafId);\n this.closeFocused();\n return;\n }\n tree.removeLeafTab(leafId, data.idx);\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('twm-tab-close');\n return;\n }\n if (action === 'move') {\n tree.moveLeafTab(leafId, data.from, data.to);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-move');\n return;\n }\n if (action === 'menu') {\n this._showTabContextMenu(leafId, data.idx, data.x, data.y);\n return;\n }\n if (action === 'close-others') {\n tree.closeOtherTabs(leafId, data.idx);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-close-others');\n return;\n }\n if (action === 'close-right') {\n tree.closeTabsAfter(leafId, data.idx);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-close-right');\n return;\n }\n if (action === 'close-left') {\n tree.closeTabsBefore(leafId, data.idx);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-close-left');\n return;\n }\n if (action === 'open-menu') {\n // Defer to a per-WM callback if anyone wired one (the\n // hamburger menu mounts via this hook). The renderer hands\n // us screen coordinates so the menu can anchor below the\n // hamburger button.\n try {\n this.ctx?.onTileTabMenu?.(leafId, data.x, data.y);\n } catch (err) {\n console.warn('[wm] tab menu hook failed', err);\n }\n }\n }\n\n /** Central navigation entry point. Every nav action \u2014 left menu,\n * breadcrumb, landing-row click, in-tile reference, panel\n * reference, entity-to-entity \u2014 should route through this so the\n * one holistic routing concept lives in one place.\n *\n * A link declares its target as TWO axes:\n *\n * `opts.dest` \u2014 WHERE the content lands:\n * 'main' \u2192 the primary content tile (default).\n * The nav panel always uses this.\n * 'origin' \u2192 the tile/window the click came from\n * (needs `ctx`). Breadcrumbs use this so\n * a segment click stays in the current\n * tile (and inside a floating window when\n * windowed).\n * 'window' \u2192 a fresh managed window.\n * `opts.newTab` \u2014 HOW it lands in that destination:\n * false \u2192 replace the destination's active tab\n * (default). true \u2192 append a NEW tab.\n * Ignored for 'window' (one window = one\n * content).\n *\n * `opts.ctx` \u2014 the caller's mount context (`leafId`,\n * `windowId`); required for `dest:'origin'`.\n * `opts.transient` \u2014 the appended tab is not persisted/restored\n * (e.g. an add-row form). Only meaningful with\n * `newTab:true`.\n *\n * Back-compat: the legacy `opts.target` enum still works and maps\n * onto the axes \u2014 'auto'\u2192origin, 'tab'\u2192origin+newTab,\n * 'primary'\u2192main, 'window'\u2192window. Prefer the two-axis form.\n *\n * The lower-level primitives (`openFromContext`,\n * `openInTabFromContext`, `openInTabInPrimary`, `openInPrimary`,\n * `openInWindow`) stay internal; callers prefer `wm.navigate(...)`. */\n navigate(kind, props = {}, opts = {}) {\n const { ctx = null, transient = false } = opts;\n // Resolve the two axes, honoring the legacy `target` alias.\n let { dest = 'main', newTab = false } = opts;\n if (opts.target != null) {\n switch (opts.target) {\n case 'window': dest = 'window'; newTab = false; break;\n case 'primary': dest = 'main'; newTab = false; break;\n case 'tab': dest = 'origin'; newTab = true; break;\n case 'split-h': dest = 'split-h'; break;\n case 'split-v': dest = 'split-v'; break;\n case 'auto':\n default: dest = 'origin'; newTab = false; break;\n }\n }\n // Split destinations: split the originating tile (or, lacking a\n // tile context, the focused tile) and mount a fresh instance in\n // the new pane. This is the routing for the code-pane \"open in\n // horizontal/vertical split\" buttons.\n if (dest === 'split-h' || dest === 'split-v') {\n const dir = dest === 'split-h' ? 'h' : 'v';\n const leafId = ctx?.leafId || this._tree().focusedLeafId;\n return this.splitLeafWith(leafId, dir, kind, props, _tabTitle(kind, props));\n }\n if (dest === 'window') return this._navigateWindow(kind, props);\n if (dest === 'main') {\n return newTab\n ? this.openInTabInPrimary(kind, props, transient)\n : this.openInPrimary(kind, props);\n }\n // dest === 'origin'\n return newTab\n ? this._navigateTab(ctx, kind, props, transient)\n : this._navigateAuto(ctx, kind, props);\n }\n\n _navigateAuto(ctx, kind, props) {\n // Windowed content \u2192 replace window in place.\n if (ctx?.windowId && this._windowToLeaf.has(ctx.windowId)) {\n this.openInWindow(ctx.windowId, kind, props);\n return;\n }\n // In-tile content \u2192 replace ACTIVE TAB only (preserves siblings).\n // Panel tiles (left/right/bottom) fall through \u2014 their clicks\n // target the primary content tile, not the panel itself.\n if (ctx?.leafId) {\n const tree = this._tree();\n const leaf = tree.get(ctx.leafId);\n const k = leaf?.content?.kind;\n if (leaf && k && !k.startsWith('panel:')) {\n this.openInLeaf(ctx.leafId, kind, props);\n return;\n }\n }\n // Outside the tile (top-nav, panel, palette) \u2192 primary tile,\n // page-aware swap that preserves per-page tab archives.\n this.openInPrimary(kind, props);\n }\n\n _navigateTab(ctx, kind, props, transient = false) {\n // Windows aren't tabbed \u2014 \"open in tab\" inside a window just\n // replaces the window's content.\n if (ctx?.windowId && this._windowToLeaf.has(ctx.windowId)) {\n this.openInWindow(ctx.windowId, kind, props);\n return;\n }\n this.openInTabFromContext(ctx || {}, kind, props, transient);\n }\n\n /** Spawn a fresh ManagedWindow with the requested content. No\n * source leaf \u2014 closing the window just disposes the content. */\n _navigateWindow(kind, props) {\n const winId = `twm-mw-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 5)}`;\n const contentEl = document.createElement('div');\n contentEl.className = 'twm-window-content';\n contentEl.style.cssText = 'display:flex; flex-direction:column; flex:1; min-width:0; min-height:0; height:100%;';\n const title = _tabTitle(kind, props);\n const mountInfo = this.content.mount(kind, contentEl, props,\n { ...this.ctx, wm: this, windowId: winId });\n const win = new ManagedWindow({\n id: winId,\n title: mountInfo?.title || title,\n icon: 'web_asset',\n content: contentEl,\n canMinimize: true,\n canMaximize: true,\n canResize: true,\n modal: false,\n onClose: () => this._onManagedWindowClosed(winId, mountInfo),\n });\n // leafId is null \u2014 `_onManagedWindowClosed` already short-circuits\n // both branches when there's no source leaf, so the close path\n // just disposes the content and drops the map entry.\n this._windowToLeaf.set(winId, {\n leafId: null,\n desktopIdx: this.desktops.activeIdx,\n original: { kind, props: { ...(props || {}) },\n title: mountInfo?.title || title },\n mountInfo, window: win, contentEl,\n _demoting: false,\n });\n win.show();\n // Cascade: a fresh window centers by default, so opening one from\n // another window would land exactly on top \u2014 reading as the\n // calling window being replaced. Offset by the current window\n // count (cycling every 6) so each new window is slightly inset\n // from the last.\n const _n = this._windowToLeaf.size; // includes this new window\n if (_n > 1 && typeof win._applyPosition === 'function') {\n const step = ((_n - 1) % 6) * 28;\n win.x = (win.x || 0) + step;\n win.y = (win.y || 0) + step;\n win._applyPosition();\n }\n this._decorateManagedWindow(win, winId);\n this._notifyChange('window-spawned');\n }\n\n /** Browser-style tab context menu. Items reflect the leaf's current\n * tab list \u2014 \"Close others\" is hidden when only one tab is open,\n * \"Close to the right / left\" are hidden at the edges. The actual\n * mutations route back through `_leafTabAction` so persistence +\n * notify stay in one place. */\n _showTabContextMenu(leafId, idx, x, y) {\n const tree = this._tree();\n const leaf = tree.get(leafId);\n if (!leaf || leaf.kind !== 'leaf') return;\n const tabs = leaf.tabs || [];\n if (tabs.length === 0) return;\n const items = [\n { label: 'Close tab', icon: 'close', action: 'close' },\n ];\n if (tabs.length > 1) {\n items.push({ label: 'Close other tabs', icon: 'tab_close', action: 'close-others' });\n }\n if (idx < tabs.length - 1) {\n items.push({ label: 'Close tabs to the right', icon: 'chevron_right',\n action: 'close-right' });\n }\n if (idx > 0) {\n items.push({ label: 'Close tabs to the left', icon: 'chevron_left',\n action: 'close-left' });\n }\n showContextMenu(x, y, items, (action) => {\n this._leafTabAction(leafId, action, { idx });\n });\n }\n\n /** Open content in a new tab on the leaf where the call originated.\n * Mirrors `openFromContext` (windowed / split-leaf / primary\n * routing) but uses `appendLeafTab` so the existing content\n * stays in place as a tab. */\n openInTabFromContext(ctx, kind, props = {}, transient = false) {\n // Managed-window content: just open in the window \u2014 managed\n // windows aren't tabbed (one window = one content).\n if (ctx?.windowId && this._windowToLeaf.has(ctx.windowId)) {\n this.openInWindow(ctx.windowId, kind, props);\n return;\n }\n const tree = this._tree();\n let leafId = ctx?.leafId;\n if (!leafId) leafId = tree.primaryLeafId();\n const leaf = leafId ? tree.get(leafId) : null;\n const k = leaf?.content?.kind;\n if (!leaf || !leafId || (k && k.startsWith('panel:'))) {\n // Panel tiles can't host content tabs \u2014 fall back to the\n // primary leaf (matches openFromContext fall-through).\n this.openInPrimary(kind, props);\n return;\n }\n tree.appendLeafTab(leafId, { kind, props }, _tabTitle(kind, props), { transient });\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-open');\n }\n\n /** Open content as a NEW tab in the primary content tile, regardless\n * of where the call came from (the `dest:'main', newTab:true` path).\n * Unlike `openInTabFromContext`, this never falls back to a replace:\n * it targets the primary leaf directly and always appends, so a\n * click from outside the tile system (e.g. the bottom-panel\n * \"Add row\" button, which passes no ctx) reliably lands as a sibling\n * tab in the main tile rather than swapping its content. */\n openInTabInPrimary(kind, props = {}, transient = false) {\n const tree = this._tree();\n const leafId = tree.primaryLeafId();\n // No content tile on this desktop (e.g. a panels-only layout) \u2014\n // open in a managed window rather than spawning a bare tile. The\n // caller asked for \"a tab in the main tile\"; with no main tile to\n // tab into, a floating window is the least-surprising fallback.\n if (!leafId) { this._navigateWindow(kind, props); return; }\n tree.appendLeafTab(leafId, { kind, props }, _tabTitle(kind, props), { transient });\n tree.focus(leafId);\n this.renderer.render();\n this._persist();\n this._notifyChange('tab-open');\n }\n}\n\n\n/** Derive a tab's display title from the content it carries \u2014 entity\n * label first, then id, then the bare kind. Used everywhere a tab is\n * created, so the bar names what the user opened rather than the kind\n * of thing it is. The rename-bus listener in the WM keeps these in\n * sync when the underlying entity is renamed. */\nfunction _tabTitle(kind, props) {\n if (props && typeof props.label === 'string' && props.label) return props.label;\n if (props && (typeof props.id === 'string' || typeof props.id === 'number')\n && String(props.id)) return String(props.id);\n return kind || '';\n}\n", "/**\n * tile_tab_menu.js \u2014 pop-out menu mounted by the tile's hamburger\n * button. Surfaces the same content the tile's *home page* would\n * list, grouped into one section per source table, with a built-in\n * search, per-section pagination, and full keyboard navigation.\n *\n * Click (or Enter on the active row) to open the entity in a NEW TAB\n * on the same tile. The menu only exists when the tab bar is visible\n * (\u22652 tabs).\n *\n * Source resolution: the menu asks the injected taxonomy which entity\n * sources a tile on this page should list (`taxonomy.sourcesFor`), then\n * asks the injected catalog to fetch and shape them. It knows the name\n * of neither. Which sources a page offers is one field on the\n * embedder's KindDef; it used to be a hardcoded table right here.\n *\n * Keyboard interactions:\n * \u2191 \u2193 move the row cursor across ALL visible items (the\n * cursor flows section-to-section, not just within one).\n * Home/End jump to the first / last visible row.\n * PageDown/ flip the focused section's pager when no search is active.\n * PageUp\n * Enter pick the cursor row.\n * Esc close.\n *\n * Search semantics:\n * - Match runs against the shaped (label, id, hint) of every raw row,\n * so the menu's search behaves the same as the command palette's.\n * - Pagination is OFF when a query is active \u2014 all matches show flat\n * within each section. Without a query, each section caps to\n * `PAGE_SIZE` rows with prev/next controls.\n */\n\n/** Items per category in browse mode (no search). Tuned small so the\n * menu stays compact; users page through with prev/next or type to\n * search the entire set. */\nconst PAGE_SIZE = 10;\n\n\n/** Open the menu anchored at (x, y). Closes on Escape, click-outside,\n * or selection. Returns a teardown closure for the caller, but the\n * menu also self-disposes on close. */\nexport function openTileTabMenu({\n x, y, leafKind, onPick, api, taxonomy, entities,\n}) {\n if (!taxonomy || !entities) {\n console.error('[tile-tab-menu] taxonomy + entity catalog are required');\n return () => {};\n }\n // Resolve which sources to list for the leaf's current page. An\n // unknown kind falls back to the root's list, which is the\n // \"everything\" default.\n const topNav = taxonomy.topNavFor(leafKind) || leafKind;\n const sources = taxonomy.sourcesFor(topNav)\n .map((nav) => entities.get(nav))\n .filter(Boolean);\n\n // Build the overlay + panel chrome.\n const overlay = document.createElement('div');\n overlay.className = 'twm-tile-tabmenu-overlay';\n overlay.innerHTML = `\n <div class=\"twm-tile-tabmenu\" role=\"dialog\" aria-label=\"Open in new tab\">\n <header class=\"twm-tile-tabmenu__head\">\n <span class=\"material-symbols-outlined twm-tile-tabmenu__head-icon\">tab</span>\n <span class=\"twm-tile-tabmenu__head-label\">Open in new tab</span>\n <button type=\"button\" class=\"twm-tile-tabmenu__close\"\n data-action=\"close\"\n aria-label=\"Close\">\u00D7</button>\n </header>\n <div class=\"twm-tile-tabmenu__search\">\n <span class=\"material-symbols-outlined\">search</span>\n <input type=\"search\"\n data-role=\"search\"\n placeholder=\"Filter rows across all sections\u2026\"\n autocomplete=\"off\" />\n </div>\n <div class=\"twm-tile-tabmenu__body\" data-role=\"body\">\n <div class=\"twm-tile-tabmenu__loading\">Loading\u2026</div>\n </div>\n </div>\n `;\n document.body.appendChild(overlay);\n\n // Anchor below the hamburger. clip to viewport so it never opens\n // off-screen when the tile sits at the right edge.\n const panel = overlay.querySelector('.twm-tile-tabmenu');\n panel.style.position = 'fixed';\n panel.style.left = `${Math.max(8, Math.min(window.innerWidth - 360, x))}px`;\n panel.style.top = `${Math.max(8, Math.min(window.innerHeight - 480, y - 480 + 22))}px`;\n\n let alive = true;\n let _query = '';\n let _cursor = 0; // index into _visibleItems\n let _visibleItems = []; // flat list rebuilt on every render\n // navKind \u2192 { rows, page, shaped (pre-shaped per row in source order) }\n const sectionState = new Map(sources.map((s) =>\n [s.navKind, { rows: [], page: 0, shaped: [] }]));\n\n const close = () => {\n if (!alive) return;\n alive = false;\n document.removeEventListener('mousedown', onOutside, true);\n document.removeEventListener('keydown', onKey, true);\n overlay.remove();\n };\n const onOutside = (ev) => {\n if (!overlay.contains(ev.target)) close();\n };\n\n const moveCursor = (delta) => {\n if (_visibleItems.length === 0) return;\n _cursor = Math.max(0, Math.min(_visibleItems.length - 1, _cursor + delta));\n _paintCursor();\n };\n const jumpCursor = (toEnd) => {\n if (_visibleItems.length === 0) return;\n _cursor = toEnd ? _visibleItems.length - 1 : 0;\n _paintCursor();\n };\n const pickCursor = () => {\n const cur = _visibleItems[_cursor];\n if (!cur) return;\n close();\n try { onPick?.(cur.navKind, cur.shaped); }\n catch (err) { console.warn('[tile-tab-menu] pick failed', err); }\n };\n\n const onKey = (ev) => {\n if (!alive) return;\n // Ignore arrow/Enter typed inside the search box's IME, etc.\n if (ev.isComposing) return;\n switch (ev.key) {\n case 'Escape':\n ev.preventDefault(); close(); return;\n case 'ArrowDown':\n ev.preventDefault(); moveCursor(+1); return;\n case 'ArrowUp':\n ev.preventDefault(); moveCursor(-1); return;\n case 'Home':\n ev.preventDefault(); jumpCursor(false); return;\n case 'End':\n ev.preventDefault(); jumpCursor(true); return;\n case 'Enter':\n ev.preventDefault(); pickCursor(); return;\n case 'PageDown': {\n if (_query) return;\n ev.preventDefault();\n const cur = _visibleItems[_cursor];\n const st = cur ? sectionState.get(cur.navKind) : null;\n if (st) {\n const pages = _pageCountFor(cur.navKind);\n if (st.page < pages - 1) { st.page += 1; _render(); }\n }\n return;\n }\n case 'PageUp': {\n if (_query) return;\n ev.preventDefault();\n const cur = _visibleItems[_cursor];\n const st = cur ? sectionState.get(cur.navKind) : null;\n if (st && st.page > 0) { st.page -= 1; _render(); }\n return;\n }\n }\n };\n document.addEventListener('mousedown', onOutside, true);\n document.addEventListener('keydown', onKey, true);\n overlay.querySelector('[data-action=\"close\"]')\n .addEventListener('click', close);\n\n const searchInput = overlay.querySelector('[data-role=\"search\"]');\n searchInput.addEventListener('input', () => {\n _query = searchInput.value.trim().toLowerCase();\n for (const st of sectionState.values()) st.page = 0;\n _cursor = 0;\n _render();\n });\n\n const bodyEl = overlay.querySelector('[data-role=\"body\"]');\n\n const _pageCountFor = (navKind) => {\n const st = sectionState.get(navKind);\n if (!st) return 1;\n const total = (_query\n ? st.shaped.filter((s) => _matchesShaped(s, _query))\n : st.shaped).length;\n return Math.max(1, Math.ceil(total / PAGE_SIZE));\n };\n\n const _render = () => {\n if (!alive) return;\n _visibleItems = [];\n const sections = [];\n for (const src of sources) {\n const st = sectionState.get(src.navKind);\n const meta = taxonomy.meta(src.navKind);\n const all = st.shaped;\n const filtered = _query\n ? all.filter((s) => _matchesShaped(s, _query))\n : all;\n const total = filtered.length;\n // Pagination is OFF during search \u2014 show every match. In\n // browse mode each section caps to PAGE_SIZE.\n let view;\n let page = 0;\n let pages = 1;\n if (_query) {\n view = filtered;\n } else {\n pages = Math.max(1, Math.ceil(total / PAGE_SIZE));\n page = Math.min(st.page, pages - 1);\n const start = page * PAGE_SIZE;\n view = filtered.slice(start, start + PAGE_SIZE);\n }\n // Append to the flat cursor list, in render order.\n for (const shaped of view) {\n _visibleItems.push({ navKind: src.navKind, shaped });\n }\n sections.push({ src, meta, view, total, page, pages });\n }\n if (_cursor >= _visibleItems.length) {\n _cursor = Math.max(0, _visibleItems.length - 1);\n }\n let flatIdx = 0;\n bodyEl.innerHTML = sections.map((s) => {\n const items = s.view.map((shaped) => {\n const idx = flatIdx++;\n const label = shaped.label || shaped.id || '';\n const hint = shaped.hint || '';\n return `\n <li class=\"twm-tile-tabmenu__item${idx === _cursor ? ' twm-tile-tabmenu__item--cursor' : ''}\"\n data-flat-idx=\"${idx}\">\n <span class=\"twm-tile-tabmenu__item-label\">${_esc(label)}</span>\n ${hint ? `<span class=\"twm-tile-tabmenu__item-hint\">${_esc(hint)}</span>` : ''}\n </li>\n `;\n }).join('');\n return `\n <section class=\"twm-tile-tabmenu__section\"\n data-section=\"${_esc(s.src.navKind)}\">\n <header class=\"twm-tile-tabmenu__section-head\">\n <span class=\"material-symbols-outlined\">${_esc(s.meta?.icon || 'arrow_right')}</span>\n <span class=\"twm-tile-tabmenu__section-label\">${_esc(s.meta?.label || s.src.navKind)}</span>\n <span class=\"twm-tile-tabmenu__section-count\">${s.total}</span>\n </header>\n ${s.view.length === 0 ? `\n <div class=\"twm-tile-tabmenu__empty\">${\n _query ? 'No matches.' : '\u2014 none \u2014'\n }</div>\n ` : `<ul class=\"twm-tile-tabmenu__list\">${items}</ul>`}\n ${(!_query && s.pages > 1) ? `\n <div class=\"twm-tile-tabmenu__pager\">\n <button type=\"button\" data-action=\"prev\"\n data-section=\"${_esc(s.src.navKind)}\"\n ${s.page === 0 ? 'disabled' : ''}><</button>\n <span>${s.page + 1} / ${s.pages}</span>\n <button type=\"button\" data-action=\"next\"\n data-section=\"${_esc(s.src.navKind)}\"\n ${s.page >= s.pages - 1 ? 'disabled' : ''}>></button>\n </div>\n ` : ''}\n </section>\n `;\n }).join('');\n bodyEl.querySelectorAll('.twm-tile-tabmenu__item').forEach((li) => {\n const idx = Number(li.dataset.flatIdx);\n li.addEventListener('mousemove', () => {\n if (_cursor !== idx) { _cursor = idx; _paintCursor(); }\n });\n li.addEventListener('click', () => {\n _cursor = idx;\n pickCursor();\n });\n });\n bodyEl.querySelectorAll('[data-action=\"prev\"], [data-action=\"next\"]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const navKind = btn.dataset.section;\n const st = sectionState.get(navKind);\n if (!st) return;\n st.page += (btn.dataset.action === 'next') ? 1 : -1;\n _render();\n });\n });\n };\n\n const _paintCursor = () => {\n bodyEl.querySelectorAll('.twm-tile-tabmenu__item').forEach((li) => {\n const idx = Number(li.dataset.flatIdx);\n const on = idx === _cursor;\n li.classList.toggle('twm-tile-tabmenu__item--cursor', on);\n if (on) li.scrollIntoView({ block: 'nearest' });\n });\n };\n\n // Kick off the fetch \u2014 in parallel, and only for the sources this\n // tile cares about. `loadOne` + `shapeRows` are the catalog's own\n // primitives, so this menu and the command palette cannot drift\n // apart on what a row is or which rows get dropped (they used to:\n // this loop was a hand-rolled copy of the palette's).\n (async () => {\n await Promise.all(sources.map(async (src) => {\n const st = sectionState.get(src.navKind);\n if (!st) return;\n st.rows = await entities.loadOne(src.navKind, api);\n // Pre-shape once and stash so search/render don't re-shape\n // on every keystroke. Rows that shape() rejects are dropped.\n st.shaped = entities.shapeRows(src.navKind, st.rows);\n }));\n _render();\n // Park the cursor on the first visible row so Enter picks\n // something immediately after open.\n if (_visibleItems.length > 0) {\n _cursor = 0;\n _paintCursor();\n }\n })();\n\n searchInput.focus();\n return close;\n}\n\n\n/** Match a shaped record (`{id, label, hint}`) against `query`.\n * Case-insensitive substring against any field. Mirrors the command\n * palette's matching so search semantics are consistent across both\n * surfaces. */\nfunction _matchesShaped(shaped, query) {\n if (!shaped) return false;\n const id = String(shaped.id ?? '').toLowerCase();\n const label = String(shaped.label ?? '').toLowerCase();\n const hint = String(shaped.hint ?? '').toLowerCase();\n return id.includes(query) || label.includes(query) || hint.includes(query);\n}\n\n\nfunction _esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n }[c]));\n}\n", "/**\n * shell.js \u2014 `createShell()`, the library's composition entry point.\n *\n * Requires: root, taxonomy, entities, content\n * Hosts: chrome (ELEMENTS, never selectors), host port, bus, stores\n * Owns: the content registry, the WM, the palette, the keymap, the\n * chrome painters, the tile context menus.\n * Knows: nothing about the embedder. No `document.body`, no selector it\n * did not author, no bus-event string, no content kind.\n *\n * \u2500\u2500 The seam \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * The embedder does everything up to \"hand the framework a root element and\n * a content map\", and everything after `createShell()` resolves:\n *\n * embedder: gate (is there anything to show?) -> install its own widgets\n * -> build/clear the root element -> build the content map\n * library: registry -> WM -> palette -> keymap -> chrome -> wm.load()\n * embedder: publish the shell, install post-mount extras\n *\n * That order is not stylistic. The widgets decorate DOM the embedder then\n * DELETES to make room for the root element, so `root` cannot exist before\n * the widgets have run \u2014 which is exactly why `createShell` does not try to\n * own a `prepare`/`widgets` lifecycle. It takes a root element that already\n * exists and mounts into it.\n *\n * \u2500\u2500 Content is a constructor argument \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * `content` is REQUIRED, validated, and frozen into a per-shell registry\n * BEFORE the WM is built. There is no module-level `register()` to call\n * late. That matters: a leaf mounted against a missing factory renders a\n * placeholder, and the renderer caches tile DOM per (kind, props) \u2014 a late\n * registration invalidates nothing, so a whole restored session stays wrong.\n * Making registration impossible after the first mount is the fix.\n *\n * \u2500\u2500 Chrome is elements, not selectors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * A selector parameter would be the coupling wearing a hat: the framework\n * would still have to know that a \"top-nav host\" is a thing you find by CSS\n * in someone else's markup. Handing it a node is the smallest honest\n * abstraction \u2014 and an embedder with no chrome passes `chrome: {}` and gets\n * a working WM with none.\n */\n\nimport { WindowManager } from './wm.js';\nimport { createContentRegistry } from './content_registry.js';\nimport { createCommandPalette } from './command_palette.js';\nimport { installKeymap } from './keymap.js';\nimport { openTileTabMenu } from './tile_tab_menu.js';\nimport { showContextMenu } from '../ui/components/context_menu.js';\nimport { openForm } from '../ui/components/modal.js';\n\n/**\n * @param {object} cfg\n * @param {Element} cfg.root the element the WM mounts into\n * @param {object} cfg.taxonomy createTaxonomy(...) \u2014 required\n * @param {object} cfg.entities createEntityCatalog(...) \u2014 required\n * @param {object} cfg.content { [kind]: (hostEl, props, ctx) => {...} }\n * @param {object} [cfg.host] the host port (createHost)\n * @param {object} [cfg.api] an opaque back-end handle, threaded into\n * ctx.api for content factories. The library\n * never calls a method on it; it only passes\n * it through (the palette + tile tab menu\n * hand it to the entity catalog's fetchers).\n * @param {object} [cfg.eventBus]\n * @param {object} [cfg.logger]\n * @param {object} [cfg.tableStore] threaded into ctx for table persistence\n * @param {object} [cfg.events] bus-event NAMES the WM listens for\n * @param {object} [cfg.rootCrumb] the breadcrumb's leading segment\n * @param {object} [cfg.palette] { placeholder }\n * @param {object} [cfg.chrome] { topNav?, paletteButton?, desktops?,\n * panelToggles?: { left?, right?, bottom? } }\n * @returns {Promise<object>} the frozen shell\n */\nexport async function createShell({\n root,\n taxonomy,\n entities,\n content,\n host = null,\n api = null,\n eventBus = null,\n logger = null,\n tableStore = null,\n events = {},\n rootCrumb = null,\n palette: paletteCfg = {},\n chrome = {},\n} = {}) {\n // A bad shell is a BOOT error, not a runtime surprise. Same doctrine as\n // createHost / createTaxonomy.\n if (!root || typeof root.appendChild !== 'function') {\n throw new TypeError('createShell: `root` must be an element');\n }\n if (!taxonomy) throw new Error('createShell: a taxonomy is required');\n if (!entities) throw new Error('createShell: an entity catalog is required');\n\n const log = logger ?? { info(){}, warn(){}, error(){}, debug(){} };\n const registry = createContentRegistry(content); // throws on a non-function\n\n let wm = null;\n let topNavEl = null;\n let desktopsEl = null;\n let toggles = null;\n\n const syncChrome = () => {\n if (!wm) return;\n syncPanelToggles(toggles, wm);\n syncDesktopBar(desktopsEl, wm);\n syncTopNav(topNavEl, wm);\n };\n\n wm = new WindowManager({\n rootEl: root,\n content: registry,\n api,\n eventBus,\n host,\n taxonomy,\n events,\n // `ctx` is the delivery vehicle for leaf-mounted chrome: tile_renderer\n // spreads it into every content factory, which is how the breadcrumb\n // gets `taxonomy` + `rootCrumb` without a content factory knowing they\n // exist. The two `onTile*Menu` keys are read with OPTIONAL CHAINING in\n // tile_renderer \u2014 drop one and right-click silently does nothing.\n ctx: {\n api, eventBus, host, tableStore,\n taxonomy, entities, rootCrumb, events,\n onTileContextMenu: (leafId, x, y) => _tileContextMenu(wm, leafId, x, y),\n onTileTabMenu: (leafId, x, y) => _tileTabMenu(wm, leafId, x, y),\n },\n onChange: () => syncChrome(),\n });\n\n const palette = createCommandPalette({\n wm, api, taxonomy, catalog: entities, ...paletteCfg,\n });\n installKeymap({ wm, palette });\n\n // Chrome \u2014 painted into the ELEMENTS the embedder handed over. An absent\n // key means absent chrome, not a crash.\n const paletteBtn = mountPaletteButton(chrome.paletteButton, palette);\n topNavEl = mountTopNav(chrome.topNav, taxonomy, wm);\n desktopsEl = mountDesktopBar(chrome.desktops, wm);\n // NOTE: bindPanelToggles CLONES the buttons (to strip whatever state the\n // embedder's own machinery left on them) and returns the FRESH nodes. The\n // originals are detached from here on \u2014 sync against the returned map, not\n // against `chrome.panelToggles`.\n toggles = bindPanelToggles(chrome.panelToggles, wm);\n\n // Belt-and-braces: anything else that mutates the WM fans out to chrome.\n eventBus?.on?.('wm:changed', syncChrome);\n\n await wm.load(); // \u2190 FIRST MOUNT\n syncChrome();\n\n log.info?.('shell mounted');\n\n return Object.freeze({\n wm,\n palette,\n taxonomy,\n entities,\n root,\n content: registry,\n chrome: Object.freeze({\n paletteButtonEl: paletteBtn,\n topNavEl,\n desktopsEl,\n panelToggles: toggles,\n }),\n dispose: () => {\n try { eventBus?.off?.('wm:changed', syncChrome); } catch { /* ignore */ }\n },\n });\n}\n\n\n// \u2550\u2550 Chrome painters \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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// Each takes an ELEMENT (or nothing) and returns whatever the sync half\n// needs. None of them queries the document.\n\n/** One shortcut button per top-nav kind in the taxonomy, painted into the\n * element the embedder gave us. Clicking opens that kind in the primary tile. */\nfunction mountTopNav(hostEl, taxonomy, wm) {\n if (!hostEl) return null;\n hostEl.innerHTML = '';\n hostEl.classList.add('twm-top-nav');\n for (const k of taxonomy.topNavEntries()) {\n const btn = document.createElement('button');\n btn.className = 'twm-top-nav__btn twm-has-tooltip';\n btn.dataset.kind = k.kind;\n btn.dataset.tooltip = k.label;\n btn.dataset.tooltipPlacement = 'bottom';\n btn.setAttribute('aria-label', k.label);\n btn.innerHTML = `\n <span class=\"material-symbols-outlined twm-top-nav__icon\">${k.icon}</span>\n <span class=\"twm-top-nav__label\">${k.label}</span>\n `;\n hostEl.appendChild(btn);\n }\n hostEl.addEventListener('click', (e) => {\n const btn = e.target.closest('[data-kind]');\n if (!btn) return;\n wm.openInPrimary(btn.dataset.kind);\n });\n return hostEl;\n}\n\nfunction syncTopNav(hostEl, wm) {\n if (!hostEl) return;\n const tree = wm.desktops.active().tree;\n const primaryId = tree.primaryLeafId();\n const primaryKind = primaryId ? tree.get(primaryId)?.content?.kind : null;\n // topNavFor maps an entity kind onto its owning top-nav category. Falls\n // back to the primary kind so unknown kinds at least try to match a button.\n const topNavKind = wm.taxonomy.topNavFor(primaryKind) || primaryKind;\n hostEl.querySelectorAll('[data-kind]').forEach((b) => {\n b.classList.toggle('twm-top-nav__btn--on', b.dataset.kind === topNavKind);\n });\n}\n\nfunction mountPaletteButton(hostEl, palette) {\n if (!hostEl) return null;\n const existing = hostEl.querySelector('#twm-palette-btn');\n if (existing) return existing;\n const btn = document.createElement('button');\n btn.id = 'twm-palette-btn';\n btn.className = 'twm-panel-toggle-btn twm-has-tooltip';\n btn.dataset.tooltip = 'Command palette (Ctrl+K)';\n btn.dataset.tooltipPlacement = 'bottom';\n btn.setAttribute('aria-label', 'Open command palette');\n btn.innerHTML = '<span class=\"material-symbols-outlined\">menu_open</span>';\n btn.addEventListener('click', () => palette.toggle());\n hostEl.insertBefore(btn, hostEl.firstChild);\n return btn;\n}\n\n/**\n * Take ownership of the embedder's three panel-toggle buttons.\n *\n * cloneNode copies any state the embedder's own machinery left on a button\n * (.active/.pinned/.disabled, the disabled attr, aria-pressed). We strip it so\n * the WM is the sole, clean source of truth \u2014 `syncPanelToggles` manages only\n * `.panel-toggle-btn--on` from here on. The clone keeps the id, so an embedder\n * that drives a toggle by `getElementById(...).click()` still works.\n *\n * @returns {{left?:Element, right?:Element, bottom?:Element}} the FRESH nodes\n */\nfunction bindPanelToggles(map, wm) {\n const fresh = {};\n for (const side of ['left', 'right', 'bottom']) {\n const btn = map?.[side];\n if (!btn) continue;\n const el = btn.cloneNode(true);\n el.classList.remove('active', 'pinned', 'disabled');\n el.disabled = false;\n el.removeAttribute('aria-disabled');\n el.removeAttribute('aria-pressed');\n btn.replaceWith(el);\n el.addEventListener('click', () => wm.togglePanel(side));\n fresh[side] = el;\n }\n return fresh;\n}\n\nfunction syncPanelToggles(map, wm) {\n for (const side of ['left', 'right', 'bottom']) {\n const btn = map?.[side];\n if (!btn) continue;\n btn.classList.toggle('twm-panel-toggle-btn--on', wm.isPanelOpen(side));\n }\n}\n\nfunction mountDesktopBar(hostEl, wm) {\n if (!hostEl) return null;\n let el = hostEl.querySelector('#twm-desktops');\n if (!el) {\n el = document.createElement('div');\n el.id = 'twm-desktops';\n el.className = 'twm-desktops';\n hostEl.appendChild(el);\n }\n el.addEventListener('click', (e) => {\n const btn = e.target.closest('[data-desktop]');\n if (!btn) return;\n const v = btn.dataset.desktop;\n if (v === '+') { wm.addDesktop(); syncDesktopBar(el, wm); return; }\n wm.switchDesktop(Number(v));\n });\n // Double-click a desktop chip \u2192 inline rename. Faster than the context\n // menu's Rename\u2026 for the common case. Persists via wm._persist so the new\n // label survives a restart.\n el.addEventListener('dblclick', async (e) => {\n const btn = e.target.closest('[data-desktop]');\n if (!btn || btn.dataset.desktop === '+') return;\n e.preventDefault();\n const idx = Number(btn.dataset.desktop);\n const d = wm.desktops.desktops[idx];\n if (!d) return;\n const result = await openForm({\n title: 'Rename desktop',\n fields: [{ name: 'label', label: 'Name', type: 'text', required: true,\n hint: 'Up to 24 characters. Shown in the bottom-bar chip and the Alt+N tooltip.' }],\n defaults: { label: d.label },\n submitLabel: 'Rename',\n });\n if (!result || !result.label) return;\n d.label = String(result.label).slice(0, 24);\n syncDesktopBar(el, wm);\n wm._persist();\n });\n el.addEventListener('contextmenu', (e) => {\n const btn = e.target.closest('[data-desktop]');\n if (!btn || btn.dataset.desktop === '+') return;\n e.preventDefault();\n const idx = Number(btn.dataset.desktop);\n const m = wm.desktops;\n const d = m.desktops[idx];\n const canDelete = m.desktops.length > 1;\n showContextMenu(e.clientX, e.clientY, [\n { label: `Switch to ${d.label}`, icon: 'desktop_windows',\n action: 'switch', disabled: idx === m.activeIdx },\n { label: 'Rename\u2026', icon: 'edit', action: 'rename' },\n { separator: true },\n { label: 'New desktop', icon: 'add', action: 'add' },\n { label: 'Delete desktop', icon: 'delete', action: 'delete',\n danger: true, disabled: !canDelete },\n ], async (action) => {\n if (action === 'switch') wm.switchDesktop(idx);\n else if (action === 'rename') {\n const result = await openForm({\n title: 'Rename desktop',\n fields: [{ name: 'label', label: 'Name', type: 'text', required: true }],\n defaults: { label: d.label },\n submitLabel: 'Rename',\n });\n if (!result || !result.label) return;\n d.label = String(result.label).slice(0, 24);\n syncDesktopBar(el, wm);\n wm._persist();\n }\n else if (action === 'add') { wm.addDesktop(); syncDesktopBar(el, wm); }\n else if (action === 'delete') { wm.removeDesktop(idx); syncDesktopBar(el, wm); }\n });\n });\n return el;\n}\n\nfunction syncDesktopBar(el, wm) {\n if (!el) return;\n const m = wm.desktops;\n el.innerHTML =\n m.desktops.map((d, i) => `\n <button class=\"twm-desk__btn${i === m.activeIdx ? ' twm-desk__btn--on' : ''}\"\n data-desktop=\"${i}\"\n title=\"Desktop ${d.label} (Alt+${i + 1}) \u00B7 right-click to delete\">\n ${d.label}\n </button>`).join('')\n + `<button class=\"twm-desk__btn twm-desk__btn--add\"\n data-desktop=\"+\" title=\"Add desktop\">+</button>`;\n}\n\n\n// \u2550\u2550 Tile menus \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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/** Hamburger button in a tile's tab bar. Lists the same content the tile's\n * home page would, with search + pagination. Clicking a row opens the entity\n * in a NEW TAB on the ORIGINATING tile (the leaf id is captured at click\n * time, so a focus change between click and pick doesn't reroute it). */\nfunction _tileTabMenu(wm, leafId, x, y) {\n const tree = wm.desktops.active().tree;\n const leaf = tree.get(leafId);\n if (!leaf) return;\n const kind = leaf.content?.kind || wm.taxonomy.root;\n openTileTabMenu({\n x, y, leafKind: kind, api: wm.api,\n taxonomy: wm.taxonomy, entities: wm.ctx.entities,\n onPick: (navKind, shaped) => {\n tree.appendLeafTab(leafId, {\n kind: navKind,\n props: { id: shaped.id, label: shaped.label },\n }, shaped.label || shaped.id);\n tree.focus(leafId);\n wm.renderer.render();\n wm._persist?.();\n wm._notifyChange?.('tab-open-from-menu');\n },\n });\n}\n\n/** Right-click on a tile's chrome strip: structural actions on that leaf. */\nfunction _tileContextMenu(wm, leafId, x, y) {\n const tree = wm.desktops.active().tree;\n const leaf = tree.get(leafId);\n if (!leaf) return;\n const isPanel = String(leaf.content?.kind || '').startsWith('panel:');\n tree.focus(leafId);\n wm.renderer._updateFocusClasses();\n\n const items = [\n { label: 'Split horizontally', icon: 'splitscreen_vertical_add', action: 'split-h' },\n { label: 'Split vertically', icon: 'splitscreen_add', action: 'split-v' },\n { separator: true },\n { label: 'Open in new tab', icon: 'tab',\n action: 'open-tab', disabled: isPanel || !leaf.content },\n { label: 'Open in new window', icon: 'open_in_full',\n action: 'open-window', disabled: isPanel || !leaf.content },\n { label: 'Promote to window', icon: 'open_in_new',\n action: 'promote', disabled: isPanel || !leaf.content },\n ];\n if (wm.desktops.desktops.length > 1 && !isPanel) {\n for (const [i, d] of wm.desktops.desktops.entries()) {\n if (i === wm.desktops.activeIdx) continue;\n items.push({ label: `Move to desktop ${d.label}`, icon: 'sweep',\n action: `move:${i}` });\n }\n }\n items.push({ separator: true });\n items.push({ label: 'Close tile', icon: 'close', action: 'close',\n danger: true, disabled: isPanel });\n\n showContextMenu(x, y, items, (action) => {\n if (action === 'split-h') wm.split('h');\n else if (action === 'split-v') wm.split('v');\n else if (action === 'open-tab') {\n const c = leaf.content;\n if (c) wm.openInTabFromContext({ leafId }, c.kind, c.props || {});\n }\n else if (action === 'open-window') {\n const c = leaf.content;\n if (c) wm.navigate(c.kind, c.props || {}, { target: 'window' });\n }\n else if (action === 'promote') wm.toggleManagedFocused();\n else if (action === 'close') wm.closeFocused();\n else if (action?.startsWith?.('move:')) {\n wm.moveFocusedToDesktop(Number(action.slice(5)));\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["_esc", "wrap", "t", "tr", "_esc", "_esc", "_esc", "_esc", "_esc"]
|
|
7
|
+
}
|