flexdesk 0.18.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/css/flexdesk.css +33 -5
  3. package/css/tokens.css +7 -0
  4. package/dist/charts.js +78 -12
  5. package/dist/charts.js.map +2 -2
  6. package/dist/{chunk-5W4EEKSK.js → chunk-3BLIVOFD.js} +3 -3
  7. package/dist/{chunk-P74F6I6P.js → chunk-4X4SY3CP.js} +4 -4
  8. package/dist/{chunk-P74F6I6P.js.map → chunk-4X4SY3CP.js.map} +2 -2
  9. package/dist/{chunk-ZL3VKINP.js → chunk-HL3IIHU3.js} +494 -3
  10. package/dist/{chunk-ZL3VKINP.js.map → chunk-HL3IIHU3.js.map} +4 -4
  11. package/dist/{chunk-RKVYIXDC.js → chunk-NFZJ6P42.js} +19 -500
  12. package/dist/chunk-NFZJ6P42.js.map +7 -0
  13. package/dist/{chunk-U5GKJUOC.js → chunk-QRBOIUU3.js} +5 -6
  14. package/dist/chunk-QRBOIUU3.js.map +7 -0
  15. package/dist/flexdesk.css +33 -5
  16. package/dist/flow.js +1 -1
  17. package/dist/git.js +3 -3
  18. package/dist/tiles.js +4 -4
  19. package/dist/tokens.css +7 -0
  20. package/dist/widgets.js +226 -58
  21. package/dist/widgets.js.map +2 -2
  22. package/dist/wm.js +2 -2
  23. package/docs/components/charts.md +40 -0
  24. package/docs/components/chat-shell.md +8 -2
  25. package/docs/components/filter-builder.md +52 -6
  26. package/docs/components/forms-and-dialogs.md +8 -0
  27. package/docs/components/input-fields.md +24 -0
  28. package/docs/components/menus.md +4 -0
  29. package/docs/components/shell.md +4 -0
  30. package/docs/components/workspace-picker.md +46 -2
  31. package/package.json +1 -1
  32. package/src/charts/plot_config_editor.js +92 -6
  33. package/src/charts/plot_grid.js +6 -1
  34. package/src/ui/components/chat_shell.js +7 -1
  35. package/src/ui/components/context_menu.js +8 -2
  36. package/src/ui/components/filter_builder.js +53 -28
  37. package/src/ui/components/filter_model.js +86 -18
  38. package/src/ui/components/inline_renamer.js +10 -5
  39. package/src/ui/components/modal.js +25 -8
  40. package/src/ui/components/workspace_picker.js +125 -27
  41. package/src/ui/utils/tooltip_service.js +81 -14
  42. package/dist/chunk-RKVYIXDC.js.map +0 -7
  43. package/dist/chunk-U5GKJUOC.js.map +0 -7
  44. /package/dist/{chunk-5W4EEKSK.js.map → chunk-3BLIVOFD.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/ui/base/controller_base.js", "../src/ui/base/page_base.js", "../src/ui/components/about_dialog.js", "../src/ui/components/alert_log.js", "../src/ui/components/alerts_pane.js", "../src/ui/components/attribute_list_editor.js", "../src/ui/components/category_picker.js", "../src/ui/components/column_fit.js", "../src/ui/components/computing_status_window.js", "../src/ui/components/chat_state_machine.js", "../src/ui/components/conversation_view.js", "../src/ui/components/chat_shell.js", "../src/ui/components/detail_header.js", "../src/ui/components/fact_table.js", "../src/ui/components/filter_model.js", "../src/ui/components/tag_input.js", "../src/ui/components/filter_builder.js", "../src/ui/components/gallery_picker.js", "../src/ui/notification_center.js", "../src/ui/components/notification_history.js", "../src/ui/components/recent_items.js", "../src/ui/components/record_list.js", "../src/ui/components/section_stack.js", "../src/ui/components/select.js", "../src/ui/components/settings_view.js", "../src/ui/components/slider_field.js", "../src/ui/components/table_state_store.js", "../src/ui/components/tree_view.js", "../src/ui/components/window_taskbar.js", "../src/ui/components/wizard.js", "../src/ui/components/workspace_picker.js", "../src/ui/controllers/window_chrome_controller.js", "../src/ui/utils/auto_scrollbars.js", "../src/ui/utils/native_context_menu.js", "../src/ui/utils/overlay_scrollbar.js", "../src/ui/utils/scroll_lock.js", "../src/ui/utils/tooltip_service.js"],
4
- "sourcesContent": ["/**\r\n * ControllerBase (js_new)\r\n *\r\n * Shared superclass for UI controllers (tab, panel, layout, etc.). Provides\r\n * deterministic teardown, scoped event subscriptions, and dependency injection.\r\n */\r\nexport class ControllerBase {\r\n constructor({ eventBus, dataManager, logger } = {}) {\r\n if (new.target === ControllerBase) {\r\n throw new Error('ControllerBase is abstract \u2013 extend it instead');\r\n }\r\n\r\n this.eventBus = eventBus;\r\n this.dataManager = dataManager;\r\n this.logger = logger;\r\n this._disposers = new Set();\r\n }\r\n\r\n /**\r\n * Register a disposer callback to guarantee teardown.\r\n */\r\n trackDisposer(disposer) {\r\n if (typeof disposer === 'function') {\r\n this._disposers.add(disposer);\r\n }\r\n }\r\n\r\n /**\r\n * Attach controller-specific DOM/event wiring. Subclasses implement this.\r\n */\r\n initialize(/* options */) {\r\n throw new Error('ControllerBase.initialize must be implemented by subclasses');\r\n }\r\n\r\n /**\r\n * Dispose all tracked resources.\r\n */\r\n dispose() {\r\n for (const disposer of this._disposers) {\r\n try {\r\n disposer();\r\n } catch (err) {\r\n this.logger?.error?.('ui', 'Controller disposer failed', err);\r\n }\r\n }\r\n this._disposers.clear();\r\n }\r\n}\r\n", "/**\r\n * PageBase (js_new)\r\n *\r\n * Abstract shell for every top-level UI page (node workspace, simulation, data).\r\n * Handles dependency injection + shared lifecycle hooks so individual pages only\r\n * focus on domain logic.\r\n *\r\n * ## Async Initialization Pattern\r\n * Pages with async initialization should:\r\n * 1. Store the init promise: `this._initPromise = this.init();` in mount()\r\n * 2. Use `await this.waitForReady()` in show()/hydrate() to wait for init\r\n * 3. Mark completion by resolving the promise (init() returns)\r\n *\r\n * Example:\r\n * ```javascript\r\n * mount(container) {\r\n * this.container = container;\r\n * this._initPromise = this.init(); // Store promise\r\n * this._mounted = true;\r\n * }\r\n *\r\n * async show() {\r\n * await this.waitForReady(); // Wait for init if still running\r\n * this.refresh();\r\n * }\r\n * ```\r\n */\r\nexport class PageBase {\r\n constructor({ eventBus, dataManager, notificationCenter, logger } = {}) {\r\n if (new.target === PageBase) {\r\n throw new Error('PageBase is abstract \u2013 extend it instead');\r\n }\r\n\r\n this.eventBus = eventBus;\r\n this.dataManager = dataManager;\r\n this.notificationCenter = notificationCenter;\r\n this.logger = logger;\r\n this._mounted = false;\r\n\r\n /**\r\n * Promise that resolves when async initialization completes.\r\n * Pages with async init should set this in mount().\r\n * @type {Promise<void>|null}\r\n */\r\n this._initPromise = null;\r\n }\r\n\r\n /**\r\n * Mount the page into a DOM container. Concrete pages must override this.\r\n * For pages with async initialization, store the init promise:\r\n * `this._initPromise = this.init();`\r\n */\r\n mount(/* container */) {\r\n throw new Error('PageBase.mount must be implemented by subclasses');\r\n }\r\n\r\n /**\r\n * Wait for the page to complete initialization.\r\n * Returns immediately if no async init or if already complete.\r\n * @returns {Promise<void>}\r\n */\r\n async waitForReady() {\r\n if (this._initPromise) {\r\n try {\r\n await this._initPromise;\r\n } catch (err) {\r\n this.logger?.warn?.('page', 'Init promise rejected', err);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Optional hook invoked after the initial mount to hydrate data/state.\r\n * For pages with async init, this should await waitForReady().\r\n */\r\n async hydrate(/* options */) {\r\n // default: wait for init to complete\r\n await this.waitForReady();\r\n }\r\n\r\n /**\r\n * Optional hook for when the page becomes active (tab switched, etc.).\r\n */\r\n onActivated(/* context */) {\r\n // default no-op\r\n }\r\n\r\n /**\r\n * Optional hook for when the page is hidden/unmounted but not disposed.\r\n */\r\n onDeactivated(/* context */) {\r\n // default no-op\r\n }\r\n\r\n /**\r\n * Dispose resources/event subscriptions.\r\n */\r\n dispose() {\r\n this._mounted = false;\r\n this._initPromise = null;\r\n }\r\n}\r\n", "/**\n * About Dialog Component\n *\n * A modal that shows a product's name, version, license, homepage and\n * third-party credits. It knows NOTHING about which product \u2014 the caller\n * supplies all of it.\n *\n * It used to hardcode EcoAgent's: PRODUCT_NAME, the GitHub URL, the tagline\n * (\"Heterogeneous-agent, stock-flow-consistent macroeconomic simulation\") and\n * two dependency lists. A library that ships an About box for somebody else's\n * application is not a library.\n *\n * EcoAgent's values now live in ui/js/ecoagent/about.js and are pushed in.\n *\n * @typedef {{name: string, license: string, url: string}} Dep\n * @typedef {{title: string, deps: Dep[]}} DepSection\n */\n\nimport { ManagedWindow } from './managed_window.js';\n\nfunction createExternalLink(text, url, className) {\n const a = document.createElement('a');\n a.className = className;\n a.textContent = text;\n a.href = url;\n a.title = url;\n a.addEventListener('click', (e) => {\n e.preventDefault();\n window.open(url, '_blank');\n });\n return a;\n}\n\nfunction buildDepSection(title, deps) {\n const section = document.createElement('div');\n section.className = 'twm-about-dialog__section';\n\n const heading = document.createElement('div');\n heading.className = 'twm-about-dialog__section-title';\n heading.textContent = title;\n section.appendChild(heading);\n\n const list = document.createElement('div');\n list.className = 'twm-about-dialog__dep-list';\n\n for (const dep of deps) {\n const row = document.createElement('div');\n row.className = 'twm-about-dialog__dep';\n\n const link = createExternalLink(dep.name, dep.url, 'twm-about-dialog__dep-name');\n row.appendChild(link);\n\n const lic = document.createElement('span');\n lic.className = 'twm-about-dialog__dep-license';\n lic.textContent = dep.license;\n row.appendChild(lic);\n\n list.appendChild(row);\n }\n\n section.appendChild(list);\n return section;\n}\n\n/**\n * Show the About dialog for whatever product the caller names.\n *\n * @param {Object} product\n * @param {string} product.name Product name \u2014 the title and the heading.\n * @param {string} [product.version]\n * @param {string} [product.tagline]\n * @param {string} [product.license] Shown as \"License: <x>\"; omitted if absent.\n * @param {string} [product.url] Homepage; omitted if absent.\n * @param {string} [product.urlLabel='Homepage']\n * @param {string} [product.logo='info'] Material symbol shown beside the title.\n * @param {DepSection[]} [product.credits=[]] Third-party credit sections.\n * @returns {Promise<void>} Resolves when the dialog is closed.\n */\nexport function showAboutDialog(product = {}) {\n const {\n name = 'Application',\n version = '',\n tagline = '',\n license = '',\n url = '',\n urlLabel = 'Homepage',\n logo = 'info',\n credits = [],\n } = product;\n\n return new Promise((resolve) => {\n let resolved = false;\n\n const finish = () => {\n if (resolved) return;\n resolved = true;\n dialogWindow.close();\n resolve();\n };\n\n // --- Content ---\n const contentEl = document.createElement('div');\n contentEl.className = 'twm-about-dialog__content';\n\n // Header\n const header = document.createElement('div');\n header.className = 'twm-about-dialog__header';\n\n const logoEl = document.createElement('span');\n logoEl.className = 'twm-about-dialog__logo material-symbols-outlined';\n logoEl.textContent = logo;\n header.appendChild(logoEl);\n\n const title = document.createElement('h2');\n title.className = 'twm-about-dialog__title';\n title.textContent = name;\n header.appendChild(title);\n\n if (version) {\n const versionEl = document.createElement('div');\n versionEl.className = 'twm-about-dialog__version';\n versionEl.textContent = `Version ${version}`;\n header.appendChild(versionEl);\n }\n\n if (tagline) {\n const taglineEl = document.createElement('div');\n taglineEl.className = 'twm-about-dialog__tagline';\n taglineEl.textContent = tagline;\n header.appendChild(taglineEl);\n }\n\n contentEl.appendChild(header);\n\n // Body (scrollable)\n const body = document.createElement('div');\n body.className = 'twm-about-dialog__body';\n\n // Project section \u2014 only if there is something to put in it.\n if (url || license) {\n const projectSection = document.createElement('div');\n projectSection.className = 'twm-about-dialog__section';\n\n const projectTitle = document.createElement('div');\n projectTitle.className = 'twm-about-dialog__section-title';\n projectTitle.textContent = 'Project';\n projectSection.appendChild(projectTitle);\n\n const links = document.createElement('div');\n links.className = 'twm-about-dialog__links';\n\n if (url) {\n const link = createExternalLink(urlLabel, url, 'twm-about-dialog__link');\n const icon = document.createElement('span');\n icon.className = 'material-symbols-outlined';\n icon.textContent = 'open_in_new';\n link.prepend(icon);\n links.appendChild(link);\n }\n\n if (license) {\n const licenseSpan = document.createElement('span');\n licenseSpan.className = 'twm-about-dialog__license-text';\n const licIcon = document.createElement('span');\n licIcon.className = 'material-symbols-outlined';\n licIcon.textContent = 'license';\n licenseSpan.appendChild(licIcon);\n licenseSpan.appendChild(document.createTextNode(`License: ${license}`));\n links.appendChild(licenseSpan);\n }\n\n projectSection.appendChild(links);\n body.appendChild(projectSection);\n }\n\n for (const section of credits) {\n body.appendChild(buildDepSection(section.title, section.deps ?? []));\n }\n\n contentEl.appendChild(body);\n\n // Footer\n const footer = document.createElement('div');\n footer.className = 'twm-about-dialog__footer';\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'twm-about-dialog__btn twm-about-dialog__btn--close';\n closeBtn.textContent = 'Close';\n closeBtn.addEventListener('click', finish);\n footer.appendChild(closeBtn);\n\n contentEl.appendChild(footer);\n\n // --- Window ---\n const dialogWindow = new ManagedWindow({\n id: 'about-dialog',\n title: `About ${name}`,\n icon: 'info',\n content: contentEl,\n minWidth: 420,\n minHeight: 400,\n defaultWidth: 460,\n defaultHeight: 540,\n canMinimize: false,\n canMaximize: false,\n canResize: false,\n canDrag: false,\n modal: true,\n onClose: () => {\n if (!resolved) {\n resolved = true;\n resolve();\n }\n },\n });\n\n dialogWindow.show();\n\n requestAnimationFrame(() => {\n closeBtn.focus();\n });\n });\n}\n", "/**\n * \u2550\u2550 THE ALERT LOG \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * What an application told its user, kept: every entry, newest first, read or\n * not, until it is dismissed or falls off the end (FlexDesk STORY-0019, from\n * bugdesk's `alerts.js`). NotificationCenter's toasts are the moment; this is\n * the history the Alerts pane (`alerts_pane.js`) and the bell\n * (NotificationHistory's `alertLog` option) read.\n *\n * An ENTRY is `{ id, at, level, title, body?, ref?, read, ruleId?, rule? }`.\n * `at` is a Date; `level` is one of `info`, `warning`, `alert` (`normalizeLevel`\n * maps the toast's `warn`/`error` and the server's `danger` onto them).\n *\n * WHERE ENTRIES LIVE IS THE EMBEDDER'S \u2014 a pluggable SOURCE:\n *\n * load({ offset, limit }) \u2192 { entries, more?, unread? } a page, newest first\n * markRead(ids | null) \u2192 null is \"all\"\n * dismiss(ids | null) \u2192 optional; without it nothing can be dismissed\n *\n * bugdesk keeps the whole log in its workspace state (`localSource`: one\n * blob, read once, written on every change); Tables pages its server's\n * notifications and has no dismiss. A source's `unread` is the count beyond\n * the loaded page \u2014 the server knows it, the page does not.\n *\n * CHANGES ARE APPLIED HERE FIRST and the source told after, so a click marks\n * read at once; a source that refuses is logged and the log re-read, rather\n * than the click being made to wait on a round trip.\n */\n\n/** The three levels, worst last; `icon` is a Material Symbols name. */\nexport const ALERT_LEVELS = Object.freeze({\n info: Object.freeze({ label: 'Info', icon: 'info' }),\n warning: Object.freeze({ label: 'Warning', icon: 'warning' }),\n alert: Object.freeze({ label: 'Alert', icon: 'notifications_active' }),\n});\n\nconst LEVEL_ALIASES = { warn: 'warning', error: 'alert', danger: 'alert', critical: 'alert', success: 'info' };\n\n/** One of `info`, `warning`, `alert`, whatever the caller spelt. */\nexport function normalizeLevel(level) {\n const l = String(level ?? '').toLowerCase();\n if (ALERT_LEVELS[l]) return l;\n return LEVEL_ALIASES[l] ?? 'info';\n}\n\n/** The worst level among these entries \u2014 a badge's colour \u2014 or null for none. */\nexport function worstLevel(entries) {\n let worst = null;\n for (const e of entries || []) {\n const l = normalizeLevel(e?.level);\n if (l === 'alert') return 'alert';\n if (l === 'warning') worst = 'warning';\n else if (!worst) worst = 'info';\n }\n return worst;\n}\n\n/** \"just now\", \"5 min ago\", \"3 h ago\"; older than a day, the clock time (the day header has the date). */\nexport function ago(at, now = new Date()) {\n const s = Math.max(0, (now - at) / 1000);\n if (s < 60) return 'just now';\n if (s < 3600) return `${Math.floor(s / 60)} min ago`;\n if (s < 86400) return `${Math.floor(s / 3600)} h ago`;\n return at.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/** TODAY, YESTERDAY, or the date \u2014 the Alerts pane's day header. */\nexport function dayLabel(at, now = new Date()) {\n const d = new Date(at.getFullYear(), at.getMonth(), at.getDate());\n const t = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const days = Math.round((t - d) / 86400000);\n if (days === 0) return 'TODAY';\n if (days === 1) return 'YESTERDAY';\n return at.toLocaleDateString([], { weekday: 'short', day: 'numeric', month: 'short', year: 'numeric' })\n .toUpperCase();\n}\n\nlet _seq = 0;\n\n/** An entry in the shape the log keeps, from whatever a source or a caller handed in. */\nfunction normalizeEntry(raw) {\n const at = raw.at instanceof Date ? raw.at : new Date(raw.at ?? Date.now());\n return {\n ...raw,\n id: String(raw.id ?? `${Date.now().toString(36)}-${(_seq++).toString(36)}`),\n at: Number.isNaN(at.getTime()) ? new Date() : at,\n level: normalizeLevel(raw.level),\n title: String(raw.title ?? ''),\n read: !!raw.read,\n };\n}\n\n/**\n * A source that keeps the whole log in one stored value \u2014 bugdesk's workspace\n * state, or localStorage. `read()` answers the saved array (or a promise of\n * it); `write(array)` stores one. Dates are written as ISO strings.\n */\nexport function localSource({ read, write, limit = 300 } = {}) {\n let all = null;\n const save = () => {\n try {\n write?.(all.map((e) => ({ ...e, at: e.at.toISOString() })));\n } catch (err) { console.warn('[alert-log] the log could not be saved', err); }\n };\n const ensure = async () => {\n if (all) return all;\n let saved = [];\n try { saved = (await read?.()) ?? []; } catch (err) {\n console.warn('[alert-log] the log could not be read', err);\n }\n all = (Array.isArray(saved) ? saved : []).filter((e) => e && typeof e === 'object')\n .map(normalizeEntry).sort((a, b) => b.at - a.at).slice(0, limit);\n return all;\n };\n return {\n local: true,\n async load({ offset = 0, limit: n = limit } = {}) {\n const list = await ensure();\n return { entries: list.slice(offset, offset + n), more: offset + n < list.length };\n },\n async add(entry) {\n const list = await ensure();\n list.unshift(entry);\n if (list.length > limit) list.length = limit;\n save();\n },\n async markRead(ids) {\n const want = ids ? new Set(ids) : null;\n for (const e of await ensure()) if (!want || want.has(e.id)) e.read = true;\n save();\n },\n async dismiss(ids) {\n const want = ids ? new Set(ids) : null;\n all = (await ensure()).filter((e) => want && !want.has(e.id));\n save();\n },\n };\n}\n\n/**\n * @param {object} [opts]\n * @param {object} [opts.source] where entries live; none keeps them in memory only\n * @param {number} [opts.limit] most entries held, and a page's size\n * @returns the log\n */\nexport function createAlertLog({ source = null, limit = 300 } = {}) {\n let entries = [];\n let more = false;\n let remoteUnread = null;\n let loaded = false;\n let loading = null;\n const listeners = new Set();\n\n const changed = () => {\n for (const fn of [...listeners]) {\n try { fn(log); } catch (err) { console.warn('[alert-log] listener failed', err); }\n }\n };\n const tell = (verb, ...args) => {\n const fn = source?.[verb];\n if (typeof fn !== 'function') return;\n Promise.resolve().then(() => fn.apply(source, args)).catch((err) => {\n console.warn(`[alert-log] the source refused ${verb}`, err);\n log.refresh();\n });\n };\n const page = async (offset) => {\n const res = (await source?.load?.({ offset, limit })) ?? {};\n const got = (res.entries ?? []).map(normalizeEntry);\n return { got, more: !!res.more, unread: Number.isFinite(res.unread) ? res.unread : null };\n };\n\n const log = {\n /** Loaded entries, newest first. */\n entries: () => entries,\n loaded: () => loaded,\n /** Whether the source has older entries than those loaded. */\n hasMore: () => more,\n /** Whether entries can be dismissed: a log with no source, or a source that can. */\n canDismiss: () => !source || typeof source.dismiss === 'function',\n /** Unread entries: the source's count when it knows one, else the loaded ones. */\n unreadCount() {\n const here = entries.filter((e) => !e.read).length;\n return remoteUnread === null ? here : Math.max(remoteUnread, here);\n },\n /** The worst level among unread entries, or null. */\n worstUnread: () => worstLevel(entries.filter((e) => !e.read)),\n get: (id) => entries.find((e) => e.id === String(id)) ?? null,\n\n /** `fn(log)` after every change; answers the unsubscribe. */\n subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n\n /** The first page, again. */\n refresh() {\n if (!source?.load) { loaded = true; changed(); return Promise.resolve(log); }\n loading = page(0).then(({ got, more: m, unread }) => {\n entries = got;\n more = m;\n remoteUnread = unread;\n loaded = true;\n changed();\n return log;\n }).catch((err) => {\n console.warn('[alert-log] the log could not be loaded', err);\n loaded = true;\n changed();\n return log;\n }).finally(() => { loading = null; });\n return loading;\n },\n /** Load once; later calls answer the same promise or nothing. */\n load() { return loading ?? (loaded ? Promise.resolve(log) : log.refresh()); },\n /** The next page, after the loaded ones. */\n async loadMore() {\n if (!more || !source?.load) return log;\n const { got, more: m, unread } = await page(entries.length);\n const seen = new Set(entries.map((e) => e.id));\n entries = [...entries, ...got.filter((e) => !seen.has(e.id))];\n more = m;\n if (unread !== null) remoteUnread = unread;\n changed();\n return log;\n },\n\n /** A new entry raised HERE (bugdesk's rules): kept, and handed to the source to save. */\n add(raw) {\n const entry = normalizeEntry(raw);\n entries = [entry, ...entries.filter((e) => e.id !== entry.id)];\n if (entries.length > limit) entries.length = limit;\n if (remoteUnread !== null && !entry.read) remoteUnread += 1;\n tell('add', entry);\n changed();\n return entry;\n },\n /** Entries that arrived from the source's side (a push): shown, not saved back. */\n receive(raws) {\n const got = (Array.isArray(raws) ? raws : [raws]).map(normalizeEntry);\n const ids = new Set(got.map((e) => e.id));\n const fresh = got.filter((e) => !entries.some((x) => x.id === e.id));\n entries = [...got, ...entries.filter((e) => !ids.has(e.id))]\n .sort((a, b) => b.at - a.at).slice(0, limit);\n if (remoteUnread !== null) remoteUnread += fresh.filter((e) => !e.read).length;\n changed();\n },\n /** Mark these read \u2014 all of them when `ids` is omitted. */\n markRead(ids = null) {\n const want = ids ? new Set(ids.map(String)) : null;\n let n = 0;\n for (const e of entries) if (!e.read && (!want || want.has(e.id))) { e.read = true; n++; }\n if (remoteUnread !== null) remoteUnread = want ? Math.max(0, remoteUnread - n) : 0;\n if (!n && want) return;\n tell('markRead', want ? [...want] : null);\n changed();\n },\n /** Remove these \u2014 all of them when `ids` is omitted. Nothing, when the source cannot. */\n dismiss(ids = null) {\n if (!log.canDismiss()) return;\n const want = ids ? new Set(ids.map(String)) : null;\n const gone = entries.filter((e) => !want || want.has(e.id));\n if (!gone.length) return;\n entries = want ? entries.filter((e) => !want.has(e.id)) : [];\n if (remoteUnread !== null) {\n remoteUnread = want ? Math.max(0, remoteUnread - gone.filter((e) => !e.read).length) : 0;\n }\n tell('dismiss', want ? [...want] : null);\n changed();\n },\n };\n if (!source?.load) loaded = true;\n return log;\n}\n", "/**\n * \u2550\u2550 THE ALERTS PANE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * An alert log (`alert_log.js`) drawn as the bottom panel's Alerts tab: level\n * chips with counts, a text filter, entries grouped by day with relative\n * times, an unread mark, Open and Dismiss on each row, Mark all read and Clear\n * for the lot (FlexDesk STORY-0019, from bugdesk's `alerts.js`). The same\n * layout whether the log is local or pages a server: *Load older* appears\n * when the source has more.\n *\n * mountAlertsPane(el, { log, onOpen: (entry) => \u2026, onBadge: ({ unread, level }) => \u2026 })\n *\n * OPTIONAL, for an embedder with rules of its own (bugdesk): `rules` is\n * `{ list() \u2192 [{ id, name, level, meta?, off? }], onEdit?, foot? }` \u2014 a column\n * of them on the left that narrows the log to one rule (entries carry\n * `ruleId`) \u2014 and `stillMatches(entry)` \u2192 true / false / null, drawn as \"still\n * matches\" or \"no longer matches\" on each row.\n *\n * NEVER REBUILT UNDER THE POINTER. A log changes on its own \u2014 a push from the\n * server, a rule firing, the minute tick \u2014 and a row repainted between a\n * mousedown and its click loses the click (Tables' recorded trap). While a\n * button is down inside the pane a repaint waits, and runs once it is up.\n * The bar (chips, the filter, the buttons) is built once and updated in\n * place, so typing in the filter never loses the caret either.\n *\n * OLDER ENTRIES LOAD AS YOU SCROLL (Tables STORY-0293): when the list is\n * scrolled to within :data:`MORE_WITHIN_PX` of its end and the source has\n * more, the next page is asked for \u2014 once at a time. *Load older* stays at the\n * end, for a list too short to scroll and for the keyboard.\n */\n\nimport { ALERT_LEVELS, ago, dayLabel, normalizeLevel } from './alert_log.js';\n\nconst CHIPS = [['all', 'All'], ['alert', 'Alert'], ['warning', 'Warning'], ['info', 'Info']];\n\n/** How near the end of the list a scroll asks for the next page. */\nexport const MORE_WITHIN_PX = 48;\n\n/**\n * @param {HTMLElement} host\n * @param {object} opts\n * @param {object} opts.log `createAlertLog(\u2026)`\n * @param {Function}[opts.onOpen] `(entry)` \u2014 Open; the entry is marked read first\n * @param {Function}[opts.onBadge] `({ unread, level })` after every change \u2014 a tab's badge\n * @param {object} [opts.rules] `{ list, onEdit?, foot? }`\n * @param {Function}[opts.stillMatches] `(entry) \u2192 boolean | null`\n * @param {Function}[opts.describe] `(entry) \u2192 string` \u2014 a small chip on the row (bugdesk: the store)\n * @param {string} [opts.status] the footer line\n * @param {object} [opts.empty] `{ none, filtered }` \u2014 the two empty texts\n * @returns {{ refresh, destroy, root }}\n */\nexport function mountAlertsPane(host, {\n log, onOpen = null, onBadge = null, rules = null, stillMatches = null, describe = null,\n status = '', empty = {},\n} = {}) {\n const doc = host.ownerDocument;\n const el = (tag, cls, text) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (text !== undefined) n.textContent = text;\n return n;\n };\n const icon = (name) => el('span', 'material-symbols-outlined', name);\n\n let level = 'all';\n let rule = null;\n let q = '';\n let pointerDown = false;\n let pending = false;\n let destroyed = false;\n\n // \u2500\u2500 the frame, built once \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-alerts');\n let ruleList = null;\n if (rules) {\n const side = el('div', 'twm-alerts__rules');\n const head = el('div', 'twm-alerts__head');\n head.append(el('span', 'twm-alerts__caps', 'RULES'), el('span', 'twm-alerts__spacer'));\n if (rules.onEdit) {\n const edit = el('button', 'twm-alerts__link', 'Edit rules');\n edit.type = 'button';\n edit.dataset.act = 'edit-rules';\n head.append(edit);\n }\n ruleList = el('div', 'twm-alerts__rulelist');\n side.append(head, ruleList);\n if (rules.foot) side.append(el('div', 'twm-alerts__foot', rules.foot));\n root.append(side);\n }\n const main = el('div', 'twm-alerts__main');\n const bar = el('div', 'twm-alerts__bar');\n const chips = el('div', 'twm-alerts__chips');\n chips.setAttribute('role', 'group');\n chips.setAttribute('aria-label', 'Level');\n const chipEls = new Map();\n for (const [key, label] of CHIPS) {\n const chip = el('button', 'twm-alerts__chip');\n chip.type = 'button';\n chip.dataset.level = key;\n chip.append(doc.createTextNode(`${label} `), el('span', 'twm-alerts__count', '0'));\n chips.append(chip);\n chipEls.set(key, chip);\n }\n const input = el('input', 'twm-alerts__q');\n input.type = 'text';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.placeholder = 'Filter';\n input.setAttribute('aria-label', 'Filter alerts');\n const readAll = el('button', 'twm-btn twm-alerts__btn', 'Mark all read');\n readAll.type = 'button';\n readAll.dataset.act = 'read-all';\n const clear = el('button', 'twm-btn twm-alerts__btn', 'Clear');\n clear.type = 'button';\n clear.dataset.act = 'clear';\n bar.append(chips, input, el('span', 'twm-alerts__spacer'), readAll, clear);\n const list = el('div', 'twm-alerts__log');\n const foot = el('div', 'twm-alerts__status', status);\n foot.hidden = !status;\n main.append(bar, list, foot);\n root.append(main);\n host.append(root);\n\n // \u2500\u2500 what is shown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const byRule = () => (rule ? log.entries().filter((e) => String(e.ruleId) === rule) : log.entries());\n const shown = () => {\n const needle = q.trim().toLowerCase();\n return byRule()\n .filter((e) => level === 'all' || e.level === level)\n .filter((e) => !needle || `${e.ref ?? ''} ${e.title} ${e.body ?? ''} ${e.rule ?? ''}`\n .toLowerCase().includes(needle));\n };\n\n function row(entry, now) {\n const lv = ALERT_LEVELS[normalizeLevel(entry.level)];\n const r = el('div', `twm-alerts__row twm-alerts__row--${entry.level}${entry.read ? '' : ' twm-alerts__row--unread'}`);\n r.dataset.id = entry.id;\n const mark = el('span', 'twm-alerts__unread');\n mark.setAttribute('aria-label', entry.read ? 'Read' : 'Unread');\n const ic = icon(lv.icon);\n ic.classList.add('twm-alerts__icon');\n ic.title = lv.label;\n const time = el('span', 'twm-alerts__time', ago(entry.at, now));\n time.title = entry.at.toLocaleString();\n const text = el('span', 'twm-alerts__text');\n text.append(el('span', 'twm-alerts__title', entry.title));\n if (entry.body) text.append(el('span', 'twm-alerts__body', entry.body));\n const cells = [mark, ic, time];\n if (rules) cells.push(el('span', 'twm-alerts__rule', entry.rule ?? ''));\n const tag = describe?.(entry);\n cells.push(el('span', tag ? 'twm-alerts__tag' : 'twm-alerts__tag twm-alerts__tag--none', tag ?? ''));\n const ref = el(entry.ref && onOpen ? 'button' : 'span', 'twm-alerts__ref', entry.ref ?? '');\n if (ref.tagName === 'BUTTON') { ref.type = 'button'; ref.dataset.open = entry.id; }\n cells.push(ref, text);\n if (stillMatches) {\n const still = stillMatches(entry);\n cells.push(el('span', `twm-alerts__state${still === false ? ' twm-alerts__state--gone' : ''}`,\n still === true ? 'still matches' : still === false ? 'no longer matches' : ''));\n }\n const acts = el('span', 'twm-alerts__acts');\n if (onOpen) {\n const open = el('button', 'twm-alerts__icon-btn');\n open.type = 'button';\n open.dataset.open = entry.id;\n open.title = 'Open';\n open.setAttribute('aria-label', 'Open');\n open.append(icon('open_in_new'));\n acts.append(open);\n }\n if (log.canDismiss()) {\n const dis = el('button', 'twm-alerts__icon-btn');\n dis.type = 'button';\n dis.dataset.dismiss = entry.id;\n dis.title = 'Dismiss';\n dis.setAttribute('aria-label', 'Dismiss');\n dis.append(icon('close'));\n acts.append(dis);\n }\n cells.push(acts);\n r.append(...cells);\n return r;\n }\n\n function paint() {\n if (destroyed) return;\n if (pointerDown) { pending = true; return; }\n pending = false;\n const now = new Date();\n const all = log.entries();\n const scoped = byRule();\n\n for (const [key, chip] of chipEls) {\n const on = level === key;\n chip.classList.toggle('twm-alerts__chip--on', on);\n chip.setAttribute('aria-pressed', String(on));\n chip.querySelector('.twm-alerts__count').textContent =\n String(scoped.filter((e) => key === 'all' || e.level === key).length);\n }\n readAll.disabled = !all.some((e) => !e.read) && log.unreadCount() === 0;\n clear.hidden = !log.canDismiss();\n clear.disabled = !all.length;\n\n if (ruleList) {\n const items = [{ id: null, name: 'All alerts', meta: String(all.length) }, ...(rules.list?.() ?? [])];\n ruleList.replaceChildren(...items.map((r) => {\n const key = r.id === null ? null : String(r.id);\n const b = el('button', `twm-alerts__rulebtn${rule === key ? ' twm-alerts__rulebtn--on' : ''}${r.off ? ' twm-alerts__rulebtn--off' : ''}`);\n b.type = 'button';\n b.dataset.rule = key ?? '';\n b.setAttribute('aria-pressed', String(rule === key));\n b.append(el('span', `twm-alerts__dot${r.level ? ` twm-alerts__dot--${normalizeLevel(r.level)}` : ''}`),\n el('span', 'twm-alerts__rulename', r.name || 'Unnamed rule'),\n el('span', 'twm-alerts__meta', r.meta ?? ''));\n return b;\n }));\n }\n\n const rows = [];\n let lastDay = '';\n for (const entry of shown()) {\n const day = dayLabel(entry.at, now);\n if (day !== lastDay) rows.push(el('div', 'twm-alerts__day', day));\n lastDay = day;\n rows.push(row(entry, now));\n }\n if (!rows.length) {\n rows.push(el('div', 'twm-alerts__none', !log.loaded() ? 'Loading\u2026'\n : all.length ? (empty.filtered ?? 'No alerts match.') : (empty.none ?? 'Nothing yet.')));\n }\n if (log.hasMore()) {\n const older = el('button', 'twm-btn twm-alerts__more', 'Load older');\n older.type = 'button';\n older.dataset.act = 'more';\n rows.push(older);\n }\n const scroll = list.scrollTop;\n list.replaceChildren(...rows);\n list.scrollTop = scroll;\n onBadge?.({ unread: log.unreadCount(), level: log.worstUnread() });\n }\n\n // \u2500\u2500 input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const onDown = () => { pointerDown = true; };\n const onUp = () => {\n if (!pointerDown) return;\n // After the click this mouseup belongs to has been dispatched.\n setTimeout(() => {\n pointerDown = false;\n if (pending) paint();\n }, 0);\n };\n root.addEventListener('mousedown', onDown, true);\n root.addEventListener('pointerdown', onDown, true);\n doc.addEventListener('mouseup', onUp, true);\n doc.addEventListener('pointerup', onUp, true);\n doc.addEventListener('pointercancel', onUp, true);\n\n root.addEventListener('click', (event) => {\n const t = event.target;\n const chip = t.closest('[data-level]');\n if (chip) { level = chip.dataset.level; paint(); return; }\n const r = t.closest('[data-rule]');\n if (r) { rule = r.dataset.rule || null; paint(); return; }\n const open = t.closest('[data-open]');\n if (open) {\n const entry = log.get(open.dataset.open);\n if (!entry) return;\n log.markRead([entry.id]);\n onOpen?.(entry);\n return;\n }\n const dis = t.closest('[data-dismiss]');\n if (dis) { log.dismiss([dis.dataset.dismiss]); return; }\n const act = t.closest('[data-act]')?.dataset.act;\n if (act === 'read-all') log.markRead();\n else if (act === 'clear') log.dismiss();\n else if (act === 'more') log.loadMore();\n else if (act === 'edit-rules') rules?.onEdit?.();\n });\n input.addEventListener('input', () => { q = input.value; paint(); });\n\n let loadingMore = false;\n list.addEventListener('scroll', () => {\n if (loadingMore || !log.hasMore()) return;\n if (list.scrollTop + list.clientHeight < list.scrollHeight - MORE_WITHIN_PX) return;\n loadingMore = true;\n Promise.resolve(log.loadMore()).catch(() => {}).finally(() => { loadingMore = false; });\n });\n\n const unsubscribe = log.subscribe(() => paint());\n // \"5 min ago\" moves on its own.\n const timer = setInterval(paint, 60000);\n paint();\n log.load?.();\n\n return {\n root,\n refresh: paint,\n destroy() {\n if (destroyed) return;\n destroyed = true;\n clearInterval(timer);\n unsubscribe();\n doc.removeEventListener('mouseup', onUp, true);\n doc.removeEventListener('pointerup', onUp, true);\n doc.removeEventListener('pointercancel', onUp, true);\n root.remove();\n },\n };\n}\n", "/**\n * attribute_list_editor.js \u2014 generic AttributeSpec list editor.\n *\n * One reusable component for every entity that declares a typed-slot\n * list: Asset.attributes, Archetype.attributes, SectorKind.requires,\n * MarketKind.requires, Flow.params, KPI.params. Mounts a SortableList\n * (drag-reorder + add + remove + empty-state) with typed cells:\n *\n * - scalar (number / integer / string / boolean): typed `<input>`\n * - expression: free-text input \u2014 engine evaluates each tick\n * - ref:<target>: typeahead-ish `<select>` populated by a caller-\n * supplied resolver returning {id, label} lists\n * - list[ref:<target>]: comma-separated input (UI primitive \u2014 chip\n * editor can land later without changing the data shape)\n * - select: dropdown of options (auto when `options[]` is set)\n *\n * Each row exposes the columns in `showColumns` (defaults to the full\n * set); callers narrow it (e.g. SectorKind.requires only needs name +\n * type + description, not default/value). Layout follows the column\n * spec \u2014 header strip aligned via CSS grid using --cols.\n *\n * Usage:\n *\n * import { mountAttributeListEditor } from\n * '../../ui/components/attribute_list_editor.js';\n *\n * const editor = mountAttributeListEditor(hostEl, {\n * items: kind.attributes,\n * showColumns: ['name', 'type', 'default', 'value', 'description'],\n * refResolvers: {\n * 'ref:asset': () => api.assets_list(),\n * },\n * onChange: (next) => { kind.attributes = next; save(); },\n * });\n * editor.refresh(); // call after `items` changes externally\n * editor.dispose(); // teardown\n */\n\nimport { SortableList } from './sortable_list.js';\n\n// The types a generic attribute editor knows about, with no application loaded.\n//\n// This used to also list nine EcoAgent entity kinds \u2014 asset_kind, market,\n// sub_sector, currency, sector, market_kind, asset_kind_template, archetype,\n// kpi \u2014 and derive `ref:<kind>` and `list[ref:<kind>]` from them. `types` was\n// ALREADY an injectable option; it simply had EcoAgent's ontology as its\n// default, which meant every consumer who didn't override it inherited a type\n// dropdown full of macroeconomics.\n//\n// Callers who want reference types build them with refTypesFor() and pass them\n// in, alongside the `refResolvers` that make them resolvable.\nconst SCALAR_TYPES = ['number', 'integer', 'string', 'boolean'];\n\nconst DEFAULT_TYPES = [...SCALAR_TYPES, 'expression'];\n\n/** `['agent']` -> `['ref:agent', 'list[ref:agent]']`. */\nexport function refTypesFor(kinds = []) {\n return [\n ...kinds.map((k) => `ref:${k}`),\n ...kinds.map((k) => `list[ref:${k}]`),\n ];\n}\n\nexport { SCALAR_TYPES, DEFAULT_TYPES };\n\nconst DEFAULT_COLUMNS = ['name', 'type', 'default', 'value', 'description'];\n\nconst COLUMN_TEMPLATES = {\n name: { label: 'name', width: 'minmax(140px, 1.2fr)' },\n type: { label: 'type', width: '140px' },\n default: { label: 'default', width: 'minmax(110px, 1fr)' },\n value: { label: 'value', width: 'minmax(110px, 1fr)' },\n description: { label: 'description', width: 'minmax(160px, 2fr)' },\n required: { label: 'req', width: '60px' },\n readonly: { label: 'r/o', width: '60px' },\n expression: { label: 'expression', width: 'minmax(160px, 2fr)' },\n // Layer N3 \u2014 extended AttributeSpec fields. Opt-in via showColumns\n // so existing single-table layouts (asset_kind editor) stay tight;\n // the agent params surface includes them.\n min: { label: 'min', width: '90px' },\n max: { label: 'max', width: '90px' },\n step: { label: 'step', width: '70px' },\n unit: { label: 'unit', width: '80px' },\n distribution: { label: 'dist', width: '110px' },\n // Distribution and \"selection set\" are two different concepts \u2014\n // numeric params sample from a continuous distribution (uniform /\n // normal / lognormal / \u2026), choice params pick from a discrete\n // option set. Keep them in separate columns so the user can tell\n // which is which at a glance.\n choices: { label: 'choices', width: '130px' },\n // Variation-override flags \u2014 R7 in\n // docs/ARCHETYPE_RETHINK_REQUIREMENTS.md. Tight columns so they\n // stay readable next to the scalar fields.\n enabled: { label: 'on', width: '50px' },\n force: { label: 'lock', width: '50px' },\n optional: { label: 'opt', width: '50px' },\n};\n\nconst DISTRIBUTION_OPTIONS = [\n '', 'constant', 'uniform', 'normal', 'lognormal', 'choice',\n];\n\n\n/** Classify one attribute against its parent-archetype counterpart.\n * Layer 8.J1 inheritance display:\n *\n * - 'inherited' \u2014 entity's effective value matches the archetype's\n * default for the same attribute name. UI paints the row blue.\n * - 'overridden' \u2014 entity's value is set AND differs from the\n * archetype's default. UI paints the row solarized orange + shows\n * a revert button.\n * - 'neutral' \u2014 neither side declares a value (or there's no parent).\n * UI paints the row in default style.\n */\nfunction _classifyRow(row, parentByName) {\n if (!parentByName) return 'neutral';\n const p = parentByName.get(row.name);\n if (!p) return 'neutral';\n const ourValue = (row.value !== undefined && row.value !== null)\n ? row.value : row.default;\n const parentValue = (p.value !== undefined && p.value !== null)\n ? p.value : p.default;\n if (ourValue === undefined || ourValue === null) return 'neutral';\n if (parentValue === undefined || parentValue === null) return 'overridden';\n // Loose equality: handles number vs numeric-string from form inputs.\n if (String(ourValue) === String(parentValue)) return 'inherited';\n return 'overridden';\n}\n\n\nexport function mountAttributeListEditor(hostEl, options = {}) {\n const {\n items = [],\n types = DEFAULT_TYPES,\n showColumns = DEFAULT_COLUMNS,\n refResolvers = {},\n onChange = () => {},\n onFlush = () => {},\n addButtonText = '',\n emptyMessage = 'No entries yet.',\n containerId = `attrs-${Math.random().toString(36).slice(2, 8)}`,\n allowReorder = true,\n allowRemove = true,\n // Layer 8.J1: parent-archetype attributes (the inherited baseline).\n // The editor uses this to classify each row as inherited / overridden /\n // neutral and to provide a revert action. Pass [] when no archetype\n // applies; the editor degrades gracefully (all rows render neutral).\n parentAttributes = null,\n createItem = () => ({\n name: '', type: 'string', default: null,\n value: null, description: '',\n }),\n // Layer N3 \u2014 per-column renderer overrides. Callers can supply\n // `cellOverrides: {column_name: (item, callbacks, ctx) => HTMLElement | null}`\n // to swap in a custom cell. Returning `null` falls through to\n // the default renderer. The `ctx` object exposes:\n // refreshRow() \u2014 force a re-render (the wider list refreshes\n // when the row's items change, e.g. type swap).\n // Use cases: agent params' distribution-dict button cell;\n // structured-type modal openers on the default cell.\n cellOverrides = null,\n // R7 \u2014 when true, this editor is mounted as a *variation* of the\n // parent archetype (not on the archetype itself). Rows where\n // the parent has `force=true` lock their editable cells; the\n // `enabled/force/optional` flag columns themselves stay\n // read-only (variations don't author flags, only the\n // archetype does).\n variationMode = false,\n } = options;\n\n // Lookup map for inheritance classification.\n const parentByName = parentAttributes\n ? new Map(parentAttributes.map((p) => [p.name, p]))\n : null;\n\n if (!hostEl) {\n return { refresh() {}, addItem() {}, dispose() {} };\n }\n\n hostEl.classList.add('twm-attr-editor');\n hostEl.style.setProperty('--cols',\n showColumns.map((c) => COLUMN_TEMPLATES[c]?.width || '1fr').join(' '));\n\n const refsCache = new Map();\n const resolveRefOptions = async (target) => {\n if (refsCache.has(target)) return refsCache.get(target);\n const resolver = refResolvers[`ref:${target}`]\n || refResolvers[`list[ref:${target}]`];\n let list = [];\n if (typeof resolver === 'function') {\n try { list = await resolver() || []; }\n catch (e) { console.warn('ref resolver failed', target, e); }\n }\n const normalised = (list || []).map((o) => {\n if (typeof o === 'string') return { id: o, label: o };\n return { id: o.id ?? o.value ?? '', label: o.label ?? o.id ?? '' };\n }).filter((o) => o.id);\n refsCache.set(target, normalised);\n return normalised;\n };\n\n // Header strip \u2014 mimics the SortableList row layout exactly so\n // header cells align with body cells. Row shape is:\n // [drag-handle] [content-with-cols-grid] [remove-button]\n // The header reuses `.sortable-list__row` chrome with placeholder\n // spans for the handle / remove gutters, then the inner content\n // div carries the same `--cols` grid as each row's content div.\n const header = document.createElement('div');\n header.className = 'twm-sortable-list__row twm-attr-editor__header-row';\n if (allowReorder) {\n const handlePh = document.createElement('span');\n handlePh.className = 'twm-sortable-list__handle twm-attr-editor__header-placeholder';\n header.appendChild(handlePh);\n }\n const headerContent = document.createElement('div');\n headerContent.className = 'twm-sortable-list__content twm-attr-editor__headers';\n for (const col of showColumns) {\n const span = document.createElement('span');\n span.textContent = COLUMN_TEMPLATES[col]?.label ?? col;\n headerContent.appendChild(span);\n }\n header.appendChild(headerContent);\n if (allowRemove) {\n const removePh = document.createElement('span');\n removePh.className = 'twm-sortable-list__remove twm-attr-editor__header-placeholder';\n header.appendChild(removePh);\n }\n hostEl.appendChild(header);\n\n const listHost = document.createElement('div');\n listHost.className = 'ea-attr-editor__rows';\n hostEl.appendChild(listHost);\n\n let list = null;\n\n const renderRow = (contentEl, item, _idx, callbacks) => {\n contentEl.classList.add('twm-attr-editor__row');\n // Layer 8.J1 \u2014 paint inheritance state.\n const cls = _classifyRow(item, parentByName);\n contentEl.classList.remove(\n 'twm-attr-editor__row--inherited',\n 'twm-attr-editor__row--overridden',\n 'twm-attr-editor__row--neutral',\n );\n contentEl.classList.add(`twm-attr-editor__row--${cls}`);\n\n // R7 variation-override flags. `enabled` defaults true, so the\n // disabled treatment only applies when explicitly false.\n // `force` locks the row (variations can't override). `optional`\n // signals the value is a suggestion \u2014 green border, no fill.\n // The flag rules are applied additively so the inheritance\n // classification's background still shows where applicable.\n // In variation mode the relevant flags are the parent's; in\n // archetype mode they're the row's own. (A variation row only\n // has the flags it inherited; it doesn't author its own.)\n const parentRow = parentByName?.get(item.name);\n const flagSource = variationMode && parentRow ? parentRow : item;\n contentEl.classList.toggle(\n 'twm-attr-editor__row--disabled', flagSource.enabled === false);\n contentEl.classList.toggle(\n 'twm-attr-editor__row--forced', flagSource.force === true);\n contentEl.classList.toggle(\n 'twm-attr-editor__row--optional', flagSource.optional === true);\n\n // Attention indicator on overridden rows + revert button.\n if (cls === 'overridden') {\n const attention = document.createElement('span');\n attention.className = 'twm-attr-editor__attention material-symbols-outlined';\n attention.textContent = 'fiber_manual_record';\n attention.title = 'Value overrides the parent default';\n contentEl.appendChild(attention);\n }\n\n for (const col of showColumns) {\n const cell = renderCell(col, item, callbacks);\n contentEl.appendChild(cell);\n }\n // R7 \u2014 lock the row's editable inputs when the parent forced it.\n // The flag columns themselves stay enabled on the archetype\n // (where the author sets them); in variation mode they're\n // read-only because variations don't author flags.\n const FLAG_COLS = new Set(['enabled', 'force', 'optional']);\n if (variationMode && flagSource.force === true) {\n contentEl.querySelectorAll(\n 'input:not([type=\"checkbox\"]), select, textarea'\n ).forEach((el) => { el.disabled = true; });\n }\n if (variationMode) {\n contentEl.querySelectorAll(\n 'input[type=\"checkbox\"].ea-attr-editor__cell--flag'\n ).forEach((el) => { el.disabled = true; });\n }\n void FLAG_COLS; // referenced by future per-column handling\n\n // Revert button \u2014 only rendered for overridden rows. Resets\n // `value` back to the archetype's inherited default. The row\n // re-classifies as 'inherited' on the next render pass.\n if (cls === 'overridden' && parentByName) {\n const p = parentByName.get(item.name);\n const parentDefault = (p?.value !== undefined && p?.value !== null)\n ? p.value : p?.default;\n const revert = document.createElement('button');\n revert.type = 'button';\n revert.className = 'twm-attr-editor__revert material-symbols-outlined';\n revert.textContent = 'undo';\n revert.title =\n `Revert to inherited default (${parentDefault ?? '\u2014'})`;\n revert.addEventListener('click', (e) => {\n e.stopPropagation();\n callbacks.update({ value: parentDefault });\n onFlush();\n // Force a re-render so the row re-classifies.\n list?.setItems(currentItems());\n });\n contentEl.appendChild(revert);\n }\n };\n\n const renderCell = (col, item, callbacks) => {\n // Caller override wins \u2014 used by agent_tab to inject the\n // distribution-dict button + structured-type modal openers.\n if (cellOverrides && typeof cellOverrides[col] === 'function') {\n const ctx = { refreshRow: () => list?.setItems(currentItems()) };\n const custom = cellOverrides[col](item, callbacks, ctx);\n if (custom) return custom;\n }\n if (col === 'name') return renderTextCell(item, 'name', callbacks, 'attr_name');\n if (col === 'type') return renderTypeCell(item, callbacks);\n if (col === 'description') return renderTextCell(item, 'description', callbacks, 'optional');\n if (col === 'required') return renderBoolCell(item, 'required', callbacks);\n if (col === 'readonly') return renderBoolCell(item, 'readonly', callbacks);\n // R7 \u2014 three variation-override flags. `enabled` defaults true,\n // so the checkbox renders checked when the field is undefined;\n // the others default false.\n if (col === 'enabled') return renderFlagCell(item, 'enabled', callbacks, true);\n if (col === 'force') return renderFlagCell(item, 'force', callbacks, false);\n if (col === 'optional') return renderFlagCell(item, 'optional', callbacks, false);\n if (col === 'expression') return renderTextCell(item, 'expression', callbacks, 'expr');\n if (col === 'min') return renderNumericCell(item, 'min', callbacks);\n if (col === 'max') return renderNumericCell(item, 'max', callbacks);\n if (col === 'step') return renderTextCell(item, 'step', callbacks, 'any');\n if (col === 'unit') return renderTextCell(item, 'unit', callbacks, 'USD/%/\u2026');\n if (col === 'distribution') return renderDistributionCell(item, callbacks);\n if (col === 'default' || col === 'value') return renderTypedValueCell(col, item, callbacks);\n // Unknown column \u2014 render a stub.\n const stub = document.createElement('span');\n stub.textContent = '';\n return stub;\n };\n\n const renderNumericCell = (item, field, callbacks) => {\n const el = document.createElement('input');\n el.type = 'number';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.step = 'any';\n el.value = (item[field] === null || item[field] === undefined)\n ? '' : String(item[field]);\n el.placeholder = '\u2014';\n el.addEventListener('input', () => {\n const v = el.value === '' ? null : Number(el.value);\n callbacks.update({ [field]: v });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderDistributionCell = (item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n for (const d of DISTRIBUTION_OPTIONS) {\n const o = document.createElement('option');\n o.value = d; o.textContent = d || '(none)';\n if ((item.distribution || '') === d) o.selected = true;\n el.appendChild(o);\n }\n el.addEventListener('change', () => {\n callbacks.update({ distribution: el.value || null });\n onFlush();\n });\n return el;\n };\n\n const renderTextCell = (item, field, callbacks, placeholder) => {\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.value = item[field] ?? '';\n el.placeholder = placeholder;\n el.addEventListener('input', () => {\n callbacks.update({ [field]: el.value });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderBoolCell = (item, field, callbacks) => {\n const el = document.createElement('input');\n el.type = 'checkbox';\n el.className = 'twm-attr-editor__cell';\n el.checked = !!item[field];\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.checked });\n onFlush();\n });\n return el;\n };\n\n /** Boolean cell for R7 flags. Same as renderBoolCell but treats an\n * undefined value as `defaultIfMissing`, so `enabled` (default\n * true) renders checked on legacy rows that predate the flag. */\n const renderFlagCell = (item, field, callbacks, defaultIfMissing) => {\n const el = document.createElement('input');\n el.type = 'checkbox';\n el.className = 'twm-attr-editor__cell ea-attr-editor__cell--flag';\n const cur = item[field];\n el.checked = (cur === undefined || cur === null)\n ? !!defaultIfMissing : !!cur;\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.checked });\n onFlush();\n });\n return el;\n };\n\n const renderTypeCell = (item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n // Group scalar, expression, ref, list[ref] for readability.\n // Any type the caller hands us that doesn't fit one of those\n // buckets lands in `other` \u2014 that's how param-mode types\n // (float / int / str / bool / choice / map / schedule /\n // string_list) appear without breaking the dispatch.\n const seen = new Set();\n const addOpts = (label, optList) => {\n if (optList.length === 0) return;\n const grp = document.createElement('optgroup');\n grp.label = label;\n for (const t of optList) {\n const o = document.createElement('option');\n o.value = t; o.textContent = t;\n if (t === item.type) o.selected = true;\n grp.appendChild(o);\n seen.add(t);\n }\n el.appendChild(grp);\n };\n addOpts('scalar', types.filter((t) => SCALAR_TYPES.includes(t)));\n addOpts('expression', types.filter((t) => t === 'expression'));\n addOpts('typed reference', types.filter((t) => t.startsWith('ref:')));\n addOpts('list of references',\n types.filter((t) => t.startsWith('list[ref:')));\n addOpts('other', types.filter((t) => !seen.has(t)));\n el.addEventListener('change', () => {\n // On type change, leave default/value as-is \u2014 the user\n // may want to keep e.g. a numeric value when switching\n // from number to integer. The typed value cell renderer\n // coerces on display.\n callbacks.update({ type: el.value });\n onFlush();\n // Force re-render so the value cell picks up the new\n // input type (number \u2192 select, etc.).\n list?.setItems(currentItems());\n });\n return el;\n };\n\n const renderTypedValueCell = (field, item, callbacks) => {\n const t = item.type || 'string';\n if (t === 'boolean') {\n return renderBoolCell(item, field, callbacks);\n }\n if (t === 'integer' || t === 'number') {\n const el = document.createElement('input');\n el.type = 'number';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.step = (t === 'integer') ? '1' : 'any';\n el.value = (item[field] === null || item[field] === undefined)\n ? '' : item[field];\n el.placeholder = field;\n el.addEventListener('input', () => {\n const v = el.value === '' ? null\n : (t === 'integer' ? parseInt(el.value, 10)\n : Number(el.value));\n callbacks.update({ [field]: v });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n }\n if (t === 'expression') {\n // For an expression-typed attribute, the value cell shows\n // the expression itself (read-only by convention \u2014 the\n // engine fills it). Stub: render the expression string;\n // the actual expression authoring lives in the\n // `expression` column when shown.\n const el = document.createElement('span');\n el.className = 'twm-attr-editor__cell twm-attr-editor__cell--readonly';\n el.textContent = item.expression\n ? `\u2192 ${item.expression}` : '\u2014 (engine-evaluated)';\n return el;\n }\n if (t.startsWith('ref:')) {\n return renderRefCell(t.slice(4), field, item, callbacks);\n }\n if (t.startsWith('list[ref:') && t.endsWith(']')) {\n return renderListRefCell(t.slice(9, -1), field, item, callbacks);\n }\n if (Array.isArray(item.options) && item.options.length > 0) {\n return renderEnumCell(item.options, field, item, callbacks);\n }\n // String fallback.\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.value = item[field] ?? '';\n el.placeholder = field;\n el.addEventListener('input', () => {\n callbacks.update({ [field]: el.value });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderRefCell = (target, field, item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = `\u2014 pick ${target} \u2014`;\n el.appendChild(placeholder);\n // Render once with the cached options if we have them; resolve\n // async otherwise and patch.\n const populate = (opts) => {\n // Clear everything except the placeholder.\n while (el.childNodes.length > 1) el.removeChild(el.lastChild);\n for (const o of opts) {\n const node = document.createElement('option');\n node.value = o.id;\n node.textContent = o.label;\n if (o.id === item[field]) node.selected = true;\n el.appendChild(node);\n }\n };\n if (refsCache.has(target)) {\n populate(refsCache.get(target));\n } else {\n resolveRefOptions(target).then(populate);\n }\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.value || null });\n onFlush();\n });\n return el;\n };\n\n const renderListRefCell = (target, field, item, callbacks) => {\n // MVP: comma-separated text input over the underlying string-\n // list. The chip-style picker can replace this without\n // changing the on-disk shape.\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n const arr = Array.isArray(item[field]) ? item[field] : [];\n el.value = arr.join(', ');\n el.placeholder = `${target}, ${target}, \u2026`;\n el.addEventListener('input', () => {\n const next = el.value.split(',')\n .map((s) => s.trim()).filter(Boolean);\n callbacks.update({ [field]: next });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderEnumCell = (options, field, item, callbacks) => {\n // `options` may be either a flat list of strings (legacy:\n // `['fx', 'commodity', \u2026]`) or a list of `{value, label}`\n // pairs (newer callers that want display labels distinct from\n // the stored value, e.g. market-rules ref fields where the\n // value is a currency id and the label is the currency name).\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n // Empty placeholder so the user can clear the selection.\n const blank = document.createElement('option');\n blank.value = '';\n blank.textContent = '\u2014';\n if (item[field] === null || item[field] === undefined || item[field] === '') {\n blank.selected = true;\n }\n el.appendChild(blank);\n for (const opt of options) {\n const o = document.createElement('option');\n if (opt !== null && typeof opt === 'object') {\n o.value = String(opt.value ?? opt.id ?? '');\n o.textContent = String(opt.label ?? opt.value ?? opt.id ?? '');\n } else {\n o.value = String(opt);\n o.textContent = String(opt);\n }\n if (o.value === String(item[field] ?? '')) o.selected = true;\n el.appendChild(o);\n }\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.value === '' ? null : el.value });\n onFlush();\n });\n return el;\n };\n\n // \u2500\u2500\u2500 SortableList wiring \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const itemsCopy = (src) => (src || []).map((it) => ({ ...it }));\n const currentItems = () => list?.getItems?.() || itemsCopy(items);\n\n const buildList = (current) => {\n try { list?.dispose?.(); } catch {}\n listHost.innerHTML = '';\n list = new SortableList({\n containerId,\n items: itemsCopy(current),\n allowReorder,\n allowRemove,\n minItems: 0,\n emptyMessage,\n addButtonText,\n createItem,\n renderItem: renderRow,\n onChange: (next) => onChange(next.map((it) => ({ ...it }))),\n });\n listHost.appendChild(list.render());\n };\n\n buildList(items);\n\n return {\n addItem() { list?.addItem(); },\n refresh(nextItems) {\n // External update: rebuild to pick up new type-cell shapes.\n // Cheaper than setItems when types changed; setItems\n // wouldn't re-render the row controls.\n buildList(nextItems !== undefined ? nextItems : currentItems());\n },\n items() {\n return currentItems();\n },\n dispose() {\n try { list?.dispose?.(); } catch {}\n list = null;\n hostEl.innerHTML = '';\n hostEl.classList.remove('twm-attr-editor');\n },\n };\n}\n", "/**\n * category_picker.js\n *\n * A categorised picker popover (STORY-0126): a search field over three\n * columns \u2014 the categories (colour dot, label, item count), the active\n * category's items (icon, label) and a detail pane for the highlighted item\n * (title, description, an optional monospace preview, an Add button).\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\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\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\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 \u25CF Text 3 \u2502 [H] Heading \u2502 Delay / Lag \u2502\n * \u2502 \u25CF Model 5 \u2502 [\u0394t] Delay / Lag \u2502 The value of an \u2502\n * \u2502 \u25CF Functions 6\u2502 [Tb] Schedule \u2502 expression some time\u2026 \u2502\n * \u2502 \u2502 \u2502 \u250C\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 \u2502 \u2502 lag(inflation, 2) \u2502 \u2502\n * \u2502 \u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u2502 \u2502 \u2502 [Add] \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\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 * Usage:\n * ```javascript\n * const picker = new CategoryPicker({\n * trigger: addButton,\n * categories: [\n * { id: 'text', label: 'Text', color: 'var(--accent-light)', items: [\n * { id: 'heading', label: 'Heading', badge: 'H',\n * description: 'A section heading.', preview: '## Debt dynamics' },\n * ] },\n * ],\n * onSelect: (item, category) => insert(category.id, item.id),\n * });\n * picker.open(); picker.close(); picker.toggle(); picker.destroy();\n * ```\n *\n * It is anchored and dismissed like `ActionDropdown`: the trigger's click\n * toggles it, it is placed by `ActionDropdown.position` (position: fixed,\n * under the trigger or flipped above it, kept 8px inside the window), drawn\n * on `--z-over-windows`, and an outside click or Escape closes it. Escape and\n * a pick give focus back to the trigger.\n *\n * Keyboard. Focus sits in the search field; typing filters. With no query,\n * Up/Down move within the current column (the categories, or the active\n * category's items) and Left/Right move between the two. With a query, the\n * items column is a flat hit list across every category, grouped under the\n * category's label; Up/Down walk it and Left/Right edit the query. Enter\n * picks the highlighted item, Escape closes. A double-click on an item picks\n * it; hovering or clicking one shows it in the detail pane.\n */\nimport { ActionDropdown } from './action_dropdown.js';\n\nlet _seq = 0;\n\n/** Lower-cased words of a query; empty for a blank one. */\nfunction _terms(query) {\n return String(query || '').toLowerCase().split(/\\s+/).filter(Boolean);\n}\n\n/** What a query is matched against: the label, the description, the keywords. */\nfunction _haystack(item) {\n const kw = Array.isArray(item.keywords) ? item.keywords.join(' ') : (item.keywords || '');\n return `${item.label || ''} ${item.description || ''} ${kw}`.toLowerCase();\n}\n\nfunction _el(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text != null) n.textContent = text;\n return n;\n}\n\nexport class CategoryPicker {\n /**\n * @param {Object} config\n * @param {HTMLElement} config.trigger - The element the picker opens from; its click toggles it\n * @param {Array} config.categories - `[{ id, label, color?, items: [{ id, label, icon?, badge?,\n * description?, preview?, keywords? }] }]`. `icon` is a Material Symbols ligature; `badge` a\n * short text drawn as a monospace badge in the category's colour; `preview` is text shown\n * monospace in the detail pane; `keywords` (array or string) are searched but not shown.\n * @param {Function} config.onSelect - `(item, category)` when an item is picked\n * @param {string} [config.className=''] - Additional CSS class for the popover\n * @param {string} [config.placeholder='Search\u2026'] - The search field's placeholder\n * @param {string} [config.addLabel='Add'] - The detail pane's button\n * @param {string} [config.previewLabel] - A caption over the preview block (none when omitted)\n * @param {'start'|'end'} [config.align='start'] - Which trigger edge it lines up with first\n * @param {string} [config.label='Pick'] - The popover's accessible name (its `aria-label`)\n */\n constructor(config) {\n this.trigger = config.trigger;\n this.categories = config.categories || [];\n this.onSelect = config.onSelect;\n this.className = config.className || '';\n this.placeholder = config.placeholder ?? 'Search\u2026';\n this.addLabel = config.addLabel ?? 'Add';\n this.previewLabel = config.previewLabel || '';\n this.align = config.align === 'end' ? 'end' : 'start';\n this.label = config.label || 'Pick';\n\n this.isOpen = false;\n this.el = null;\n\n this._id = `twm-category-picker-${++_seq}`;\n this._query = '';\n this._activeCat = 0; // index of the category whose items show (no query)\n this._column = 'items'; // 'categories' | 'items' \u2014 where Up/Down go\n this._hl = null; // { c, i } \u2014 the highlighted item\n this._rows = []; // the items column's rows, in order: { c, i, el }\n\n this._onDocClick = this._onDocClick.bind(this);\n this._onKeydown = this._onKeydown.bind(this);\n this._onTriggerClick = this._onTriggerClick.bind(this);\n\n if (!this.trigger) {\n console.warn('[CategoryPicker] No trigger element provided');\n return;\n }\n this._build();\n this.trigger.setAttribute('aria-haspopup', 'dialog');\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.addEventListener('click', this._onTriggerClick);\n }\n\n // \u2500\u2500 DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _build() {\n const root = _el('div', `twm-category-picker ${this.className}`.trim());\n root.setAttribute('role', 'dialog');\n root.setAttribute('aria-label', this.label);\n root.hidden = true;\n // FOCUS STAYS IN THE SEARCH FIELD. A press on anything but the field\n // (a row, a group header, the detail text, padding, a disabled button)\n // would otherwise move focus to <body>, outside the popover, and the\n // arrow keys, Enter and typing would stop reaching it while it is\n // open. The click still happens; only the focus move is cancelled\n // (which also means the preview's text cannot be drag-selected).\n root.addEventListener('mousedown', (e) => {\n if (e.target !== this._input) e.preventDefault();\n });\n\n const search = _el('div', 'twm-category-picker__search');\n const input = _el('input', 'twm-category-picker__input');\n input.type = 'search';\n input.placeholder = this.placeholder;\n input.setAttribute('aria-label', this.placeholder || 'Search');\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `${this._id}-items`);\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.addEventListener('input', () => this._setQuery(input.value));\n search.appendChild(input);\n\n const body = _el('div', 'twm-category-picker__body');\n const cats = _el('div', 'twm-category-picker__categories twm-category-picker__column');\n cats.id = `${this._id}-cats`;\n cats.setAttribute('role', 'listbox');\n cats.setAttribute('aria-label', 'Categories');\n const items = _el('div', 'twm-category-picker__items twm-category-picker__column');\n items.id = `${this._id}-items`;\n items.setAttribute('role', 'listbox');\n items.setAttribute('aria-label', 'Items');\n // No aria-live: the input's aria-activedescendant already announces\n // each move, and a live region would read the pane on every one.\n const detail = _el('div', 'twm-category-picker__detail');\n body.append(cats, items, detail);\n\n root.append(search, body);\n document.body.appendChild(root);\n\n this.el = root;\n this._input = input;\n this._catsEl = cats;\n this._itemsEl = items;\n this._detailEl = detail;\n this._render();\n }\n\n /** The items column's entries: the active category's items, or every hit for the query. */\n _visible() {\n const terms = _terms(this._query);\n if (!terms.length) {\n const cat = this.categories[this._activeCat];\n return (cat?.items || []).map((_, i) => ({ c: this._activeCat, i }));\n }\n const out = [];\n this.categories.forEach((cat, c) => (cat.items || []).forEach((item, i) => {\n const hay = _haystack(item);\n if (terms.every((t) => hay.includes(t))) out.push({ c, i });\n }));\n return out;\n }\n\n /** Rebuild both lists and the detail pane. Hover never calls this. */\n _render() {\n if (!this.el) return;\n const searching = _terms(this._query).length > 0;\n const visible = this._visible();\n const hits = new Map();\n for (const v of visible) hits.set(v.c, (hits.get(v.c) || 0) + 1);\n\n // Keep the highlight when it is still listed, else the first entry.\n if (!this._hl || !visible.some((v) => v.c === this._hl.c && v.i === this._hl.i)) {\n this._hl = visible[0] ? { ...visible[0] } : null;\n }\n if (searching && this._hl) this._activeCat = this._hl.c;\n\n // Categories.\n this._catsEl.replaceChildren();\n this.categories.forEach((cat, c) => {\n const btn = _el('button', 'twm-category-picker__category');\n btn.type = 'button';\n btn.tabIndex = -1;\n btn.id = `${this._id}-cat-${c}`;\n btn.setAttribute('role', 'option');\n btn.dataset.index = String(c);\n if (cat.color) btn.style.setProperty('--twm-category-picker-color', cat.color);\n const count = searching ? (hits.get(c) || 0) : (cat.items || []).length;\n if (searching && !count) btn.classList.add('twm-category-picker__category--empty');\n btn.append(\n _el('span', 'twm-category-picker__dot'),\n _el('span', 'twm-category-picker__category-label', cat.label),\n _el('span', 'twm-category-picker__count', String(count)),\n );\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n this._column = 'categories';\n this._chooseCategory(c);\n this._input.focus();\n });\n this._catsEl.appendChild(btn);\n });\n\n // Items (or hits: each category's in a role=\"group\" named by its header).\n this._itemsEl.replaceChildren();\n this._rows = [];\n let lastCat = -1;\n let into = this._itemsEl;\n for (const v of visible) {\n const cat = this.categories[v.c];\n const item = cat.items[v.i];\n if (searching && v.c !== lastCat) {\n const header = _el('div', 'twm-category-picker__group');\n header.id = `${this._id}-group-${v.c}`;\n if (cat.color) header.style.setProperty('--twm-category-picker-color', cat.color);\n header.append(_el('span', 'twm-category-picker__dot'), _el('span', null, cat.label));\n into = _el('div', 'twm-category-picker__hits');\n into.setAttribute('role', 'group');\n into.setAttribute('aria-labelledby', header.id);\n into.appendChild(header);\n this._itemsEl.appendChild(into);\n lastCat = v.c;\n }\n const btn = _el('button', 'twm-category-picker__item');\n btn.type = 'button';\n btn.tabIndex = -1;\n btn.id = `${this._id}-item-${v.c}-${v.i}`;\n btn.setAttribute('role', 'option');\n btn.dataset.category = String(v.c);\n btn.dataset.index = String(v.i);\n if (cat.color) btn.style.setProperty('--twm-category-picker-color', cat.color);\n if (item.icon) {\n btn.appendChild(_el('span', 'material-symbols-outlined twm-category-picker__icon', item.icon));\n } else {\n btn.appendChild(_el('span', 'twm-category-picker__badge', item.badge ?? ''));\n }\n btn.appendChild(_el('span', 'twm-category-picker__item-label', item.label));\n btn.addEventListener('mouseenter', () => this._highlight(v));\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n this._column = 'items';\n this._highlight(v);\n this._input.focus();\n });\n btn.addEventListener('dblclick', (e) => {\n e.preventDefault();\n this._pick(v);\n });\n this._rows.push({ ...v, el: btn });\n into.appendChild(btn);\n }\n if (!visible.length) {\n this._itemsEl.appendChild(_el('div', 'twm-category-picker__empty',\n searching ? `Nothing matches \u201C${this._query.trim()}\u201D.` : 'Nothing here.'));\n }\n\n this._paintState();\n }\n\n /** Classes and ARIA for the active category, the highlight and the current column; the detail pane. */\n _paintState() {\n const searching = _terms(this._query).length > 0;\n [...this._catsEl.children].forEach((btn, c) => {\n const on = c === this._activeCat;\n btn.classList.toggle('twm-category-picker__category--active', on);\n btn.setAttribute('aria-selected', on ? 'true' : 'false');\n });\n for (const r of this._rows) {\n const on = !!this._hl && r.c === this._hl.c && r.i === this._hl.i;\n r.el.classList.toggle('twm-category-picker__item--highlighted', on);\n r.el.setAttribute('aria-selected', on ? 'true' : 'false');\n }\n const column = searching ? 'items' : this._column;\n this._catsEl.classList.toggle('twm-category-picker__column--current', column === 'categories');\n this._itemsEl.classList.toggle('twm-category-picker__column--current', column === 'items');\n\n const hlRow = this._rows.find((r) => this._hl && r.c === this._hl.c && r.i === this._hl.i);\n const activeCatEl = this._catsEl.children[this._activeCat];\n // The input names the option the arrow keys are on: the active\n // category while the categories column is current, else the highlight.\n const current = column === 'categories' ? activeCatEl : hlRow?.el;\n this._input.setAttribute('aria-controls', column === 'categories' ? this._catsEl.id : this._itemsEl.id);\n if (current) this._input.setAttribute('aria-activedescendant', current.id);\n else this._input.removeAttribute('aria-activedescendant');\n hlRow?.el.scrollIntoView?.({ block: 'nearest' });\n activeCatEl?.scrollIntoView?.({ block: 'nearest' });\n\n this._renderDetail();\n }\n\n _renderDetail() {\n const d = this._detailEl;\n d.replaceChildren();\n const item = this._hl ? this.categories[this._hl.c]?.items?.[this._hl.i] : null;\n if (item) {\n d.appendChild(_el('div', 'twm-category-picker__title', item.label));\n if (item.description) d.appendChild(_el('div', 'twm-category-picker__description', item.description));\n if (item.preview != null && item.preview !== '') {\n if (this.previewLabel) d.appendChild(_el('div', 'twm-category-picker__preview-label', this.previewLabel));\n d.appendChild(_el('pre', 'twm-category-picker__preview', String(item.preview)));\n }\n } else {\n d.appendChild(_el('div', 'twm-category-picker__detail-empty', 'Nothing selected.'));\n }\n const add = _el('button', 'twm-btn twm-btn--primary twm-category-picker__add', this.addLabel);\n add.type = 'button';\n add.disabled = !item;\n add.addEventListener('click', (e) => {\n e.preventDefault();\n if (this._hl) this._pick(this._hl);\n });\n d.appendChild(add);\n }\n\n // \u2500\u2500 State changes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _setQuery(q) {\n this._query = String(q || '');\n if (_terms(this._query).length) {\n // A new query highlights its first hit.\n this._hl = null;\n } else if (this._hl) {\n // Back to browsing: the highlight's category is the one shown.\n this._activeCat = this._hl.c;\n }\n this._render();\n }\n\n _highlight(v) {\n if (!v) return;\n this._hl = { c: v.c, i: v.i };\n if (_terms(this._query).length) this._activeCat = v.c;\n this._paintState();\n }\n\n /** Make category `c` the active one. Browsing: show its items. Searching: jump to its first hit. */\n _chooseCategory(c) {\n if (c < 0 || c >= this.categories.length) return;\n if (_terms(this._query).length) {\n const first = this._rows.find((r) => r.c === c);\n if (first) this._highlight(first);\n return;\n }\n this._activeCat = c;\n this._hl = (this.categories[c].items || []).length ? { c, i: 0 } : null;\n this._render();\n }\n\n _moveHighlight(dir) {\n if (!this._rows.length) return;\n let at = this._rows.findIndex((r) => this._hl && r.c === this._hl.c && r.i === this._hl.i);\n at = at < 0 ? (dir > 0 ? 0 : this._rows.length - 1)\n : (at + dir + this._rows.length) % this._rows.length;\n this._highlight(this._rows[at]);\n }\n\n _pick(v) {\n const category = this.categories[v.c];\n const item = category?.items?.[v.i];\n if (!item) return;\n const onSelect = this.onSelect;\n this.close();\n this.trigger?.focus();\n onSelect?.(item, category);\n }\n\n // \u2500\u2500 Events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _onTriggerClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.toggle();\n }\n\n _onDocClick(e) {\n if (!this.isOpen) return;\n if (this.el?.contains(e.target) || this.trigger?.contains(e.target)) return;\n this.close();\n }\n\n _onKeydown(e) {\n if (!this.isOpen) return;\n // An IME composing a character owns Enter and Escape.\n if (e.isComposing || e.keyCode === 229) return;\n if (e.key === 'Escape') {\n // Capture phase, and stopped: an open picker is the innermost\n // thing on screen, so Escape closes it and not the ManagedWindow\n // around it (ActionDropdown's rule).\n e.preventDefault();\n e.stopPropagation();\n this.close();\n this.trigger?.focus();\n return;\n }\n if (!this.el.contains(e.target)) return;\n\n const searching = _terms(this._query).length > 0;\n switch (e.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n e.preventDefault();\n const dir = e.key === 'ArrowDown' ? 1 : -1;\n if (!searching && this._column === 'categories') {\n const n = this.categories.length;\n if (n) this._chooseCategory((this._activeCat + dir + n) % n);\n } else {\n this._moveHighlight(dir);\n }\n break;\n }\n case 'ArrowRight':\n case 'ArrowLeft':\n if (searching) return; // the query's caret\n e.preventDefault();\n this._column = e.key === 'ArrowRight' ? 'items' : 'categories';\n if (this._column === 'items' && !this._hl) this._moveHighlight(1);\n this._paintState();\n break;\n case 'Enter':\n e.preventDefault();\n if (this._hl) this._pick(this._hl);\n break;\n case 'Tab': {\n // Tab stays inside, like a modal ManagedWindow's focus trap:\n // it cycles the search field and Add (when Add is enabled).\n // Leaving would strand an open popover with a dead keyboard.\n e.preventDefault();\n e.stopPropagation();\n const add = this._detailEl.querySelector('.twm-category-picker__add');\n const stops = [this._input, ...(add && !add.disabled ? [add] : [])];\n const at = stops.indexOf(e.target);\n const next = at < 0 ? 0 : (at + (e.shiftKey ? -1 : 1) + stops.length) % stops.length;\n stops[next].focus();\n break;\n }\n default:\n // A printable key typed while a row or the button has focus\n // goes to the search field.\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey\n && e.target !== this._input) {\n this._input.focus();\n }\n }\n }\n\n // \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Open it under (or above) the trigger, with an empty query and focus in the search field. */\n open() {\n if (this.isOpen || !this.el) return;\n this.isOpen = true;\n this._input.value = '';\n this._query = '';\n this._column = 'items';\n // Shown and placed first, then drawn: scrolling the highlight into\n // view does nothing in a hidden popover.\n this.el.hidden = false;\n this.position();\n this._render();\n\n this.trigger?.classList.add('twm-is-open');\n this.trigger?.setAttribute('aria-expanded', 'true');\n document.addEventListener('click', this._onDocClick, true);\n document.addEventListener('keydown', this._onKeydown, true);\n this._input.focus();\n }\n\n close() {\n if (!this.isOpen) return;\n this.isOpen = false;\n if (this.el) this.el.hidden = true;\n this.trigger?.classList.remove('twm-is-open');\n this.trigger?.setAttribute('aria-expanded', 'false');\n document.removeEventListener('click', this._onDocClick, true);\n document.removeEventListener('keydown', this._onKeydown, true);\n }\n\n /** @param {boolean} [force] */\n toggle(force) {\n const want = typeof force === 'boolean' ? force : !this.isOpen;\n if (want) this.open(); else this.close();\n }\n\n /** Place it against the trigger again (after the trigger moved). */\n position() {\n if (!this.el || !this.trigger) return;\n ActionDropdown.position(this.trigger, this.el, { align: this.align });\n // The columns scroll themselves; the popover only shrinks to fit.\n this.el.style.overflowY = 'hidden';\n }\n\n /**\n * Replace the categories. The active category and the highlight are\n * looked up again by `id`, so they are kept when they still exist,\n * wherever they moved to.\n */\n setCategories(categories) {\n const oldCat = this.categories[this._activeCat];\n const oldHlCat = this._hl ? this.categories[this._hl.c] : null;\n const oldHlItem = oldHlCat?.items?.[this._hl.i];\n this.categories = categories || [];\n const catAt = (cat) => (cat ? this.categories.findIndex((c) => c.id === cat.id) : -1);\n\n const active = catAt(oldCat);\n this._activeCat = active >= 0 ? active : 0;\n this._hl = null;\n const hc = catAt(oldHlCat);\n if (hc >= 0 && oldHlItem) {\n const hi = (this.categories[hc].items || []).findIndex((it) => it.id === oldHlItem.id);\n if (hi >= 0) this._hl = { c: hc, i: hi };\n }\n if (this.el) this._render();\n }\n\n destroy() {\n this.close();\n this.trigger?.removeEventListener('click', this._onTriggerClick);\n this.el?.remove();\n this.el = null;\n this.trigger = null;\n this.categories = [];\n this.onSelect = null;\n }\n}\n\nexport default CategoryPicker;\n", "/**\n * column_fit.js \u2014 how wide each column of a table should be.\n *\n * A pure function over measurements, so the policy can be read and tested\n * without a DOM. A table measures its columns, hands them here, and applies\n * the widths it gets back.\n *\n * \u2500\u2500 The policy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Columns are not all alike, and treating them alike is what went wrong\n * before. An id, a date, a status, a person: SHORT columns, whose values are\n * all about as wide as each other, and which are useless the moment they are\n * cut (\"2026-09-\u2026\", \"review-q\u2026\"). A summary or a title: TEXT columns, whose\n * values run as long as people write them, and which are readable cut.\n *\n * The old fit spread spare room EVENLY, so a 40px \"BUG\" chip got 90px while\n * the summary beside it was clipped in nine rows out of ten, and it shrank the\n * WIDEST column first, so a narrow tile crushed the title to 85px while every\n * short column kept its width.\n *\n * 1. Short columns get their full content width. Text columns start at a\n * readable width.\n * 2. Room to spare goes to the text columns, in proportion to what each\n * still needs, and past their content so the table fills its box. With no\n * text column it goes to the last column, so no column in the middle\n * opens a gap.\n * 3. Too little room: shrink in order of harm. Short columns first give up\n * only their rare longest values (down to `typical`, what most values\n * fit). Then text columns go down to a floor. Then short columns go down\n * to theirs, and text columns once more. What still does not fit scrolls\n * sideways rather than being crushed further.\n *\n * Within each step the widest columns give way first and the narrow ones keep\n * their width (a water level), so one long column never forces every other\n * column down with it.\n *\n * Columns the user dragged are PINNED: they keep their width and sit out every\n * step.\n */\n\nexport const COLUMN_FIT = Object.freeze({\n /** Absolute floor, and the drag-resize minimum. */\n FLOOR: 40,\n /** Sub-pixel safety against an ellipsis on content that exactly fits. */\n PAD: 2,\n /** A column whose full width reaches this is free text. */\n TEXT_AT: 240,\n /** A text column's starting share when room allows it. */\n TEXT_MIN: 200,\n /** How far a text column shrinks before short columns go below `typical`. */\n TEXT_FLOOR: 120,\n /** How far a short column shrinks before the table scrolls. */\n SHORT_FLOOR: 56,\n});\n\n/**\n * @typedef {object} ColumnMeasure\n * @property {number} natural widest cell, padding included (px)\n * @property {number} [typical] width most cells fit, e.g. the 95th percentile (px);\n * defaults to `natural`\n * @property {number} [header] the header label's width (px)\n * @property {number} [pinned] a user-dragged width, honoured exactly\n * @property {boolean} [text] force (true) or forbid (false) text treatment;\n * omitted, it is decided from the width\n */\n\n/**\n * @param {ColumnMeasure[]} columns\n * @param {number} avail the width the table has (px); 0 or less means \"not laid out\"\n * @returns {number[]} a width per column (px, possibly fractional). The sum\n * equals `avail` whenever the floors fit, and exceeds it only when they do\n * not, in which case the table should scroll.\n */\nexport function fitColumns(columns, avail) {\n const { FLOOR, PAD, TEXT_AT, TEXT_MIN, TEXT_FLOOR, SHORT_FLOOR } = COLUMN_FIT;\n const n = columns.length;\n const cols = columns.map((c) => {\n const header = Math.max(0, Number(c.header) || 0);\n const natural = Math.max(0, Number(c.natural) || 0);\n const full = Math.max(FLOOR, Math.ceil(Math.max(natural, header) + PAD));\n const typical = Math.min(full, Math.max(FLOOR, Math.ceil(Math.max(\n Number.isFinite(c.typical) ? c.typical : natural, header) + PAD)));\n const pinned = Number.isFinite(c.pinned) ? Math.max(FLOOR, Math.round(c.pinned)) : null;\n const text = pinned == null && (typeof c.text === 'boolean' ? c.text : full >= TEXT_AT);\n return { full, typical, pinned, text };\n });\n\n const text = [];\n const short = [];\n cols.forEach((c, i) => { if (c.pinned == null) (c.text ? text : short).push(i); });\n if (!(avail > 1)) return cols.map((c) => (c.pinned != null ? c.pinned : c.full));\n\n // 1. The starting point: short columns at their full content width, text\n // columns at a readable width (or their content, if shorter).\n const widths = cols.map((c) => {\n if (c.pinned != null) return c.pinned;\n return c.text ? Math.min(c.full, TEXT_MIN) : c.full;\n });\n const total = () => widths.reduce((a, b) => a + b, 0);\n let slack = avail - total();\n\n // 2. Room to spare goes to the text columns, in proportion to what each\n // still needs, then beyond their content so the table fills its box.\n // Widths are not rounded: CSS takes fractional pixels, and rounding is\n // what made the total miss the box by a pixel and a column jitter by one\n // as its tile was resized.\n if (slack >= 0) {\n slack = raise(widths, text, (i) => cols[i].full, slack);\n if (slack > 0) {\n if (text.length) text.forEach((i) => { widths[i] += slack / text.length; });\n else widths[short.length ? short[short.length - 1] : n - 1] += slack;\n }\n return widths;\n }\n\n // 3. Not enough room: shrink in order of harm until it fits.\n const steps = [\n [short, (i) => cols[i].typical],\n [text, () => TEXT_FLOOR],\n [short, (i) => Math.min(cols[i].typical, SHORT_FLOOR)],\n [text, () => FLOOR * 2],\n ];\n for (const [idxs, low] of steps) {\n const over = total() - avail;\n if (over <= 1e-6) break;\n lowerTo(widths, idxs, low, over);\n }\n return widths;\n}\n\n/**\n * Give up to `slack` px to the columns in `idxs`, each toward `target(i)`, in\n * proportion to how far each still is from it. Returns what is left.\n */\nfunction raise(widths, idxs, target, slack) {\n if (!(slack > 0)) return slack;\n const wants = idxs.map((i) => Math.max(0, target(i) - widths[i]));\n const need = wants.reduce((a, b) => a + b, 0);\n if (!(need > 0)) return slack;\n const give = Math.min(slack, need);\n idxs.forEach((i, k) => { widths[i] += give * wants[k] / need; });\n return slack - give;\n}\n\n/**\n * Take up to `over` px off the columns in `idxs`, widest first, none below\n * `low(i)`. A water level: every column above the level is cut down to it, and\n * the level is solved so the total cut is exactly `over`, or everything the\n * lows allow when that is less. Solved on real numbers: the result is exact,\n * and a wider box can never make any column narrower.\n */\nfunction lowerTo(widths, idxs, low, over) {\n const floorOf = (i) => Math.min(widths[i], Math.max(0, low(i)));\n const cand = idxs.filter((i) => widths[i] > floorOf(i));\n if (!cand.length || over <= 0) return;\n const floors = new Map(cand.map((i) => [i, floorOf(i)]));\n const capacity = cand.reduce((a, i) => a + widths[i] - floors.get(i), 0);\n if (capacity <= over) {\n for (const i of cand) widths[i] = floors.get(i);\n return;\n }\n const cutAt = (level) => cand.reduce((a, i) => a + Math.max(0, widths[i] - Math.max(floors.get(i), level)), 0);\n let lo = 0;\n let hi = Math.max(...cand.map((i) => widths[i]));\n for (let k = 0; k < 64; k++) {\n const mid = (lo + hi) / 2;\n if (cutAt(mid) > over) lo = mid; else hi = mid;\n }\n for (const i of cand) widths[i] = Math.min(widths[i], Math.max(floors.get(i), hi));\n}\n", "/**\n * Computing Status Window\n *\n * Lightweight ManagedWindow that shows a spinner (or a progress bar) and a\n * status message while a long-running computation is in progress. Returns a\n * handle with update(), setProgress(), setStep(), complete(), cancelled(),\n * close() and a `result` promise.\n *\n * Optionally shows a Cancel button when an onCancel callback is provided.\n * Only one is open at a time: opening another closes the first, which then\n * settles as cancelled (its onCancel is not called).\n */\n\nimport { ManagedWindow } from './managed_window.js';\nimport { mountJobProgress } from './job_progress.js';\n\nlet _activeWindow = null;\n\n/**\n * Show a computing status window.\n *\n * `result` settles once: `complete({ok, message})` gives `done` or `error`\n * (the window stays, with a Close button, until closed), `cancelled()` gives\n * `cancelled`, and so does closing the window while it runs (by its \u00D7,\n * Escape, `close()` or opening another). Closing never calls `onCancel`: only\n * the Cancel button does. `progress` and `steps` are fixed when the window\n * opens: `setProgress` throws if it was opened without `progress`, and\n * `setStep` if it was opened without `steps`.\n *\n * @param {Object} options\n * @param {string} [options.title='Computing...'] - Window title\n * @param {string} [options.message=''] - Status message below spinner (markup; `update` takes text)\n * @param {string} [options.icon='hourglass_top'] - Material icon name\n * @param {Function} [options.onCancel] - If provided, shows a Cancel button. Called once when clicked.\n * @param {boolean|Object} [options.progress] - A ProgressBar in place of the spinner: `true` or its options.\n * @param {Array} [options.steps] - StepProgress steps, shown above the message.\n * @returns {{ update(msg: string): void, setProgress(next: number|Object): void,\n * setStep(which: string|number, opts?: {pass?: number, passes?: number}): void,\n * complete(result: {ok: boolean, message?: string}): void, cancelled(msg?: string): void,\n * close(): void, result: Promise<{status: 'done'|'error'|'cancelled', message: string}> }}\n */\nexport function showComputingWindow({\n title = 'Computing...', message = '', icon = 'hourglass_top', onCancel,\n progress = null, steps = null,\n} = {}) {\n if (_activeWindow) {\n _activeWindow.close();\n _activeWindow = null;\n }\n\n let finished = false;\n let settle;\n const result = new Promise((resolve) => { settle = resolve; });\n\n const content = document.createElement('div');\n content.className = 'twm-computing-status';\n const spinnerEl = document.createElement('div');\n spinnerEl.className = 'twm-computing-status__spinner';\n const msgEl = document.createElement('div');\n msgEl.className = 'twm-computing-status__message';\n // The opening message is markup, as it always was; every later one is text.\n msgEl.innerHTML = message;\n content.appendChild(spinnerEl);\n const job = mountJobProgress(content, { progress, steps, spinner: spinnerEl });\n content.appendChild(msgEl);\n\n let cancelBtn = null;\n if (typeof onCancel === 'function') {\n cancelBtn = document.createElement('button');\n cancelBtn.className = 'twm-computing-status__cancel-btn';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n cancelBtn.disabled = true;\n msgEl.textContent = 'Cancelling...';\n onCancel();\n }, { once: true });\n content.appendChild(cancelBtn);\n }\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'twm-computing-status__cancel-btn twm-computing-status__close-btn';\n closeBtn.textContent = 'Close';\n closeBtn.hidden = true;\n content.appendChild(closeBtn);\n\n const finish = (status, text) => {\n finished = true;\n spinnerEl.hidden = true;\n if (cancelBtn) cancelBtn.hidden = true;\n msgEl.textContent = text;\n msgEl.classList.toggle('is-ok', status === 'done');\n msgEl.classList.toggle('is-err', status === 'error');\n msgEl.classList.toggle('is-cancelled', status === 'cancelled');\n job.finish(status);\n settle({ status, message: text });\n };\n\n const win = new ManagedWindow({\n id: 'computing-status-window',\n title,\n icon,\n content,\n minWidth: 320,\n minHeight: 140,\n defaultWidth: 380,\n defaultHeight: (onCancel ? 190 : 160) + (job.bar ? 30 : 0) + (job.steps ? 40 : 0),\n canMinimize: true,\n canMaximize: false,\n canResize: false,\n canDrag: true,\n modal: false,\n // BUG-0053. A status window opened by the program, not by the user:\n // it must not take focus from what the user is doing.\n focusOnOpen: false,\n onClose: () => {\n if (_activeWindow === win) _activeWindow = null;\n if (finished) return;\n finish('cancelled', 'Cancelled.');\n },\n });\n closeBtn.addEventListener('click', () => win.close());\n _activeWindow = win;\n win.show();\n\n return {\n result,\n update(msg) {\n if (finished) return;\n msgEl.textContent = msg;\n },\n setProgress(next) {\n if (finished) return;\n job.setProgress(next);\n },\n setStep(which, opts) {\n if (finished) return;\n job.setStep(which, opts);\n },\n complete(res) {\n if (finished) return;\n finish(res?.ok ? 'done' : 'error', res?.message || '');\n closeBtn.hidden = false;\n },\n cancelled(msg) {\n if (finished) return;\n finish('cancelled', msg || 'Cancelled.');\n closeBtn.hidden = false;\n },\n close() {\n if (_activeWindow) {\n _activeWindow.close();\n _activeWindow = null;\n }\n },\n };\n}\n", "/**\n * \u2550\u2550 THE CONVERSATION STATE MACHINE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * The lifecycle of one assistant conversation, with no view and no transport in\n * it. `mountChatShell` (`./chat_shell.js`) drives one; a chat of your own can\n * too.\n *\n * idle \u2500\u2500send\u2500\u2500\u25B6 waiting \u2500\u2500streamStart\u2500\u2500\u25B6 streaming \u2500\u2500streamComplete\u2500\u2500\u25B6 idle\n * \u2514\u2500 streamComplete \u25B6 idle \u251C\u2500 cancel \u25B6 idle\n * \u2514\u2500 cancel \u25B6 idle \u2514\u2500 error \u25B6 error\n * \u2514\u2500 error \u25B6 error\n * error \u2500\u2500send\u2500\u2500\u25B6 waiting error \u2500\u2500reset\u2500\u2500\u25B6 idle\n *\n * TRANSITIONS ARE QUEUED. `StateMachine` (`../../core/state_machine.js`) is\n * asynchronous and refuses a transition that arrives during another. Text can\n * arrive in the same tick as the request that asked for it, so every call here\n * waits for the one before it, in call order, and answers a promise of\n * `{ transitioned, reason? }`. `getState()` therefore lags a call by some\n * microtasks; `settled()` resolves when the queue is empty, and `getState()` is\n * `null` until the machine has entered `idle`. A transition the current state\n * does not have is refused, not thrown.\n *\n * OBSERVERS: `onChange({ state, conversationId, mode })` hears every state\n * entered. With an `eventBus`, the same goes out as `CHAT_BUS_EVENTS.STATE_CHANGED`\n * along with the others below.\n *\n * THE MODE is an opaque string of the caller's (`null` for none): it is kept\n * and handed back, and means nothing here.\n */\n\nimport { StateMachine } from '../../core/state_machine.js';\n\nexport const CHAT_STATES = Object.freeze({\n IDLE: 'idle',\n WAITING: 'waiting',\n STREAMING: 'streaming',\n ERROR: 'error',\n});\n\nexport const CHAT_TRANSITIONS = Object.freeze({\n SEND: 'chat:message:send',\n STREAM_START: 'chat:stream:start',\n STREAM_COMPLETE: 'chat:stream:complete',\n CANCEL: 'chat:cancel',\n ERROR: 'chat:error',\n RESET: 'chat:reset',\n});\n\nexport const CHAT_BUS_EVENTS = Object.freeze({\n STATE_CHANGED: 'chat:state:changed',\n MESSAGE_SENT: 'chat:message:sent',\n STREAM_COMPLETE: 'chat:stream:completed',\n MODE_CHANGED: 'chat:mode:changed',\n CONVERSATION_NEW: 'chat:conversation:new',\n CONVERSATION_LOADED: 'chat:conversation:loaded',\n ERROR: 'chat:error:raised',\n});\n\nexport class ChatStateMachine {\n #machine;\n #eventBus;\n #onChange;\n #queue = Promise.resolve();\n #conversationId = null;\n #mode;\n #lastError = null;\n\n /**\n * @param {object} [deps]\n * @param {object} [deps.eventBus] gets `CHAT_BUS_EVENTS`\n * @param {object} [deps.logger]\n * @param {?string} [deps.mode] the mode to start in\n * @param {Function} [deps.onChange] `({ state, conversationId, mode })` on every state entered\n */\n constructor({ eventBus = null, logger = null, mode = null, onChange = null } = {}) {\n this.#eventBus = eventBus;\n this.#onChange = onChange;\n this.#mode = mode;\n\n const entered = () => this.#entered();\n const send = {\n target: CHAT_STATES.WAITING,\n guard: (ctx) => !!ctx.payload?.message,\n action: (ctx) => this.#messageSent(ctx.payload),\n };\n const inFlight = {\n [CHAT_TRANSITIONS.STREAM_COMPLETE]: {\n target: CHAT_STATES.IDLE,\n action: (ctx) => this.#emit(CHAT_BUS_EVENTS.STREAM_COMPLETE, {\n conversationId: this.#conversationId, ...ctx.payload,\n }),\n },\n [CHAT_TRANSITIONS.CANCEL]: { target: CHAT_STATES.IDLE },\n [CHAT_TRANSITIONS.ERROR]: {\n target: CHAT_STATES.ERROR,\n action: (ctx) => this.#failed(ctx.payload),\n },\n [CHAT_TRANSITIONS.RESET]: { target: CHAT_STATES.IDLE },\n };\n\n this.#machine = new StateMachine({\n name: 'chat',\n initialState: CHAT_STATES.IDLE,\n eventBus,\n logger,\n states: {\n [CHAT_STATES.IDLE]: {\n onEnter: () => {\n this.#lastError = null;\n entered();\n },\n transitions: { [CHAT_TRANSITIONS.SEND]: send },\n },\n [CHAT_STATES.WAITING]: {\n onEnter: entered,\n transitions: {\n [CHAT_TRANSITIONS.STREAM_START]: { target: CHAT_STATES.STREAMING },\n ...inFlight,\n },\n },\n [CHAT_STATES.STREAMING]: { onEnter: entered, transitions: inFlight },\n [CHAT_STATES.ERROR]: {\n onEnter: entered,\n transitions: {\n [CHAT_TRANSITIONS.RESET]: { target: CHAT_STATES.IDLE },\n [CHAT_TRANSITIONS.SEND]: send,\n },\n },\n },\n });\n }\n\n getState() { return this.#machine.getState(); }\n\n get conversationId() { return this.#conversationId; }\n set conversationId(id) { this.#conversationId = id ?? null; }\n\n get mode() { return this.#mode; }\n get lastError() { return this.#lastError; }\n\n setMode(mode) {\n this.#mode = mode;\n this.#emit(CHAT_BUS_EVENTS.MODE_CHANGED, { mode });\n }\n\n /** Resolves when every call so far has taken effect. */\n settled() { return this.#queue; }\n\n sendMessage(message, conversationId = this.#conversationId) {\n this.#conversationId = conversationId ?? null;\n return this.#transition(CHAT_TRANSITIONS.SEND, { message });\n }\n\n streamStart() { return this.#transition(CHAT_TRANSITIONS.STREAM_START); }\n\n /** @param {object} [payload] goes out with `CHAT_BUS_EVENTS.STREAM_COMPLETE` */\n streamComplete(payload = {}) { return this.#transition(CHAT_TRANSITIONS.STREAM_COMPLETE, payload); }\n\n cancel() { return this.#transition(CHAT_TRANSITIONS.CANCEL); }\n\n error(message, detail = null) { return this.#transition(CHAT_TRANSITIONS.ERROR, { message, detail }); }\n\n reset() { return this.#transition(CHAT_TRANSITIONS.RESET); }\n\n /** Back to idle with no conversation, whatever the state. */\n newConversation() {\n this.#conversationId = null;\n return this.#enqueue(async () => {\n await this.#machine.reset(CHAT_STATES.IDLE);\n this.#emit(CHAT_BUS_EVENTS.CONVERSATION_NEW, {});\n });\n }\n\n /** Back to idle on a kept conversation, whatever the state. */\n loadConversation(conversationId) {\n this.#conversationId = conversationId ?? null;\n return this.#enqueue(async () => {\n await this.#machine.reset(CHAT_STATES.IDLE);\n this.#emit(CHAT_BUS_EVENTS.CONVERSATION_LOADED, { conversationId });\n });\n }\n\n canSend() {\n const state = this.getState();\n return state === CHAT_STATES.IDLE || state === CHAT_STATES.ERROR;\n }\n\n isProcessing() {\n const state = this.getState();\n return state === CHAT_STATES.WAITING || state === CHAT_STATES.STREAMING;\n }\n\n #transition(event, payload) {\n return this.#enqueue(() => this.#machine.transition(event, payload));\n }\n\n /** One step after the last; a step that fails rejects its own promise and not the next one's. */\n #enqueue(step) {\n const run = this.#queue.then(step);\n this.#queue = run.then(() => undefined, () => undefined);\n return run;\n }\n\n #messageSent({ message }) {\n this.#lastError = null;\n this.#emit(CHAT_BUS_EVENTS.MESSAGE_SENT, {\n conversationId: this.#conversationId, text: message, mode: this.#mode,\n });\n }\n\n #failed({ message, detail }) {\n this.#lastError = message;\n this.#emit(CHAT_BUS_EVENTS.ERROR, { conversationId: this.#conversationId, message, detail });\n }\n\n #entered() {\n const change = { state: this.getState(), conversationId: this.#conversationId, mode: this.#mode };\n this.#onChange?.(change);\n this.#emit(CHAT_BUS_EVENTS.STATE_CHANGED, change);\n }\n\n #emit(name, payload) { this.#eventBus?.emit(name, payload); }\n}\n", "/**\n * \u2550\u2550 THE CONVERSATION VIEW \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A transcript of role-tagged messages above a composer (FlexDesk STORY-0057).\n * It knows nothing about what a message says or where it came from: no\n * markdown, no model, no provider. The caller draws a message's body (or\n * leaves it as plain text) and is told when the user submits or cancels.\n *\n * const view = mountConversationView(el, {\n * render: (message, bodyEl, { streaming }) => { bodyEl.innerHTML = toHtml(message.text); },\n * onSubmit: (text) => send(text),\n * onCancel: () => stop(),\n * });\n * view.append({ role: 'user', text: 'Hello' });\n * view.beginStream({ role: 'assistant' });\n * view.appendChunk('Hi'); // re-renders ONLY the streaming message\n * view.endStream();\n *\n * MESSAGES are `{ id?, role, text, meta? }`. `id` is assigned when absent;\n * `role` becomes a modifier class (`twm-chat__msg--<role>`); `meta` is the\n * caller's and is handed back untouched. `append`, `remove`, `replaceAll` and\n * `clear` change the list; `messages()` reads it. An id already in the transcript (or\n * repeated within one `replaceAll`) is refused with a throw, and a refused\n * call changes nothing. Each message has an EXTRA SLOT\n * (`slot(id)`), an element below the body the caller fills with whatever\n * belongs to that message \u2014 tool output, buttons, a diff \u2014 and which a\n * re-render of the body never touches.\n *\n * THE RENDER CALLBACK draws one body: `render(message, bodyEl, { streaming })`.\n * The body is emptied before every call. One that throws leaves the message\n * as its plain text (`twm-chat__body--plain`) and the view carries on; the\n * error goes to `onRenderError(error, message)` when given.\n *\n * STREAMING: `beginStream(message?)` appends a message marked streaming,\n * `appendChunk(text)` adds to its text and re-renders that message's body\n * alone, `endStream()` renders it a last time, unmarked. Nothing is deferred to\n * a frame: every call has drawn by the time it returns.\n *\n * PINNED TO THE BOTTOM: the view starts out following new content. Any\n * scroll UP \u2014 even a few px from the end, and whichever frame of a smooth\n * wheel or key scroll reports it \u2014 stops the following and shows *Jump to\n * latest*, and no later chunk moves the reader back. Following resumes only\n * on a scroll down (or a move that is not up) that ends within\n * `pinThreshold` px of the end, a click on *Jump to latest*,\n * `scrollToBottom()`, `replaceAll()` / `clear()`, or a `setScrollTop(px)`\n * that lands within the threshold. Content growing below a pinned view\n * never unpins it, nor does content shrinking under it (the browser clamps\n * `scrollTop` to the new end, which is not a move up). A wheel over\n * a nested scroller (a `<pre>` in a body, say) scrolls that, not the view;\n * nor does a wheel a handler inside the transcript cancelled, a Ctrl+wheel\n * (zoom, or a trackpad pinch), or a wheel up over a transcript already at its\n * top. `scrollTop` is\n * readable and settable (`getScrollTop` / `setScrollTop`) so an embedder can\n * keep it across a remount.\n *\n * THE COMPOSER is a textarea that grows with its text up to\n * `composerMaxHeight`. Enter submits (the trimmed-empty text is ignored) and\n * clears it; Shift+Enter is left to the browser, which inserts the newline\n * (native undo, `input` events). `setBusy(true)` turns Send into Cancel: Enter\n * then submits nothing, and Esc \u2014 wherever focus is inside the view \u2014 or a\n * click on Cancel calls `onCancel`, once per busy period, however often it is\n * pressed. That Esc stops there: it never reaches a window or panel around\n * the view that would close on Escape. An Esc a handler inside the view has\n * already consumed (`preventDefault`, say an inline popup or editor in the\n * transcript closing itself) is left alone: it neither cancels nor is stopped.\n *\n * `destroy()` removes the view. Every listener sits on an element the view\n * created, so they go with it; none is on the host or the document.\n */\n\n/** How near the end of the transcript still counts as \"at the bottom\". */\nexport const CONVERSATION_PIN_WITHIN_PX = 32;\n\n/**\n * A drop in `scrollTop` that still leaves the view this close to its end is\n * the browser clamping it after the content shrank (or sub-pixel rounding),\n * not the reader scrolling up.\n */\nconst AT_END_PX = 1;\n\n/** The tallest the composer grows before it scrolls instead. */\nexport const CONVERSATION_COMPOSER_MAX_PX = 200;\n\n/**\n * @param {HTMLElement} host\n * @param {object} [opts]\n * @param {Function} [opts.render] `(message, bodyEl, { streaming })` \u2014 draws a body; plain text without it\n * @param {Function} [opts.onSubmit] `(text)` \u2014 Enter or Send\n * @param {Function} [opts.onCancel] `()` \u2014 Esc or Cancel while busy\n * @param {Function} [opts.onRenderError] `(error, message)` \u2014 a render that threw\n * @param {number} [opts.pinThreshold] px from the end that still follows new content\n * @param {number} [opts.composerMaxHeight] px the composer grows to\n * @param {string} [opts.placeholder] the composer's placeholder\n * @param {object} [opts.labels] `{ send, cancel, jump, input }` \u2014 button and field texts\n * @returns {object} the view (see the methods below)\n */\nexport function mountConversationView(host, {\n render = null, onSubmit = null, onCancel = null, onRenderError = null,\n pinThreshold = CONVERSATION_PIN_WITHIN_PX, composerMaxHeight = CONVERSATION_COMPOSER_MAX_PX,\n placeholder = '', labels = {},\n} = {}) {\n const text = {\n send: 'Send', cancel: 'Cancel', jump: 'Jump to latest', input: 'Message', ...labels,\n };\n const doc = host.ownerDocument;\n const el = (tag, cls, content) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (content !== undefined) n.textContent = content;\n return n;\n };\n const icon = (name) => {\n const i = el('span', 'material-symbols-outlined', name);\n i.setAttribute('aria-hidden', 'true');\n return i;\n };\n\n /** id \u2192 { message, row, body, extra } in transcript order. */\n const entries = new Map();\n let nextId = 1;\n let streamId = null;\n let pinned = true;\n let lastScrollTop = 0;\n let busy = false;\n let cancelled = false;\n let destroyed = false;\n\n // \u2500\u2500 the frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-chat');\n const viewport = el('div', 'twm-chat__viewport');\n const log = el('div', 'twm-chat__log');\n log.setAttribute('role', 'log');\n log.setAttribute('aria-live', 'polite');\n const jump = el('button', 'twm-chat__jump');\n jump.type = 'button';\n jump.append(icon('arrow_downward'), doc.createTextNode(` ${text.jump}`));\n jump.hidden = true;\n viewport.append(log, jump);\n\n const composer = el('div', 'twm-chat__composer');\n const input = el('textarea', 'twm-chat__input');\n input.rows = 1;\n input.placeholder = placeholder;\n input.setAttribute('aria-label', text.input);\n const send = el('button', 'twm-chat__send');\n send.type = 'button';\n composer.append(input, send);\n root.append(viewport, composer);\n host.append(root);\n\n // \u2500\u2500 scrolling \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const distanceFromEnd = () => log.scrollHeight - log.scrollTop - log.clientHeight;\n const toBottom = () => {\n log.scrollTop = log.scrollHeight;\n lastScrollTop = log.scrollTop;\n };\n const setPinned = (value) => {\n pinned = value;\n jump.hidden = pinned;\n };\n /**\n * Reads the position the reader left: any move up stops following, however\n * near the end it stops (a smooth wheel or key scroll reports its first\n * frame only a few px up). Returns whether the move may follow again: it\n * was not up and ends within `pinThreshold` of the end. Shared by the\n * `scroll` event and by settle(), because a scrollbar drag, a key or a\n * touch moves `scrollTop` before its `scroll` event is dispatched, and a\n * change arriving in between must not snap the reader back.\n */\n function noticeMove() {\n const top = log.scrollTop;\n const distance = distanceFromEnd();\n const movedUp = top < lastScrollTop && distance > AT_END_PX;\n lastScrollTop = top;\n if (movedUp && pinned) setPinned(false);\n return !movedUp && distance <= pinThreshold;\n }\n /** After every change to the transcript: follow it, or leave the reader where they are. */\n const settle = () => {\n noticeMove();\n if (pinned) toBottom();\n };\n\n function onScroll() { if (noticeMove() && !pinned) setPinned(true); }\n /**\n * Whether a wheel up over `target` is kept by something nested inside the\n * transcript \u2014 a scrollable block in a body or an extra slot that is not\n * at its own top, or one at its top whose `overscroll-behavior` keeps the\n * scroll from chaining out \u2014 rather than moving the transcript itself.\n */\n function innerTakesWheelUp(target) {\n const view = doc.defaultView;\n for (let n = target; n && n !== log; n = n.parentElement) {\n if (n.nodeType !== 1 || n.scrollHeight <= n.clientHeight) continue;\n const style = view?.getComputedStyle(n);\n const overflow = style?.overflowY;\n if (overflow !== 'auto' && overflow !== 'scroll' && overflow !== 'overlay') continue;\n if (n.scrollTop > 0) return true;\n const chain = style.getPropertyValue('overscroll-behavior-y');\n if (chain === 'contain' || chain === 'none') return true;\n }\n return false;\n }\n /**\n * A wheel up that will move the transcript stops following at once, before\n * the scroll it causes is reported. One that a nested scroller keeps, or\n * one a handler inside the transcript cancelled (a zoomable chart in a\n * slot, say), leaves the transcript where it is, so it changes nothing.\n * Nor does a Ctrl+wheel (page zoom; a trackpad pinch arrives as one), or\n * a wheel up over a transcript already at its top, which cannot go up.\n */\n function onWheel(e) {\n if (e.deltaY < 0 && pinned && !e.ctrlKey && !e.defaultPrevented && log.scrollTop > 0\n && !innerTakesWheelUp(e.target)) setPinned(false);\n }\n function onJump() { setPinned(true); toBottom(); }\n log.addEventListener('scroll', onScroll);\n log.addEventListener('wheel', onWheel, { passive: true });\n jump.addEventListener('click', onJump);\n\n // \u2500\u2500 messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 fresh id, never one `taken` holds. */\n const newId = (taken = (id) => entries.has(id)) => {\n let id;\n do id = `m${nextId++}`; while (taken(id));\n return id;\n };\n const duplicate = (id) => new Error(`conversation view: duplicate message id \"${id}\"`);\n const roleClass = (role) => String(role ?? '').toLowerCase().replace(/[^a-z0-9-]+/g, '-') || 'none';\n const snapshot = (message) => ({ ...message });\n\n function drawBody(entry, streaming = entry.message.id === streamId) {\n const { message, body } = entry;\n body.replaceChildren();\n body.classList.remove('twm-chat__body--plain');\n if (render) {\n try {\n render(snapshot(message), body, { streaming });\n return;\n } catch (error) {\n body.replaceChildren();\n if (onRenderError) {\n try { onRenderError(error, snapshot(message)); } catch { /* the view keeps working */ }\n }\n }\n }\n body.classList.add('twm-chat__body--plain');\n body.textContent = message.text;\n }\n\n /**\n * One entry, drawn, and added to `into` (the transcript unless a\n * replaceAll is building its own). Throws on an id `into` already holds,\n * before anything is changed.\n */\n function build(spec, { into = entries, taken, streaming = false } = {}) {\n const message = {\n ...spec,\n id: spec?.id ?? newId(taken ?? ((id) => into.has(id))),\n role: spec?.role ?? 'assistant',\n text: String(spec?.text ?? ''),\n };\n if (into.has(message.id)) throw duplicate(message.id);\n const row = el('div', `twm-chat__msg twm-chat__msg--${roleClass(message.role)}`);\n if (streaming) row.classList.add('twm-chat__msg--streaming');\n const body = el('div', 'twm-chat__body');\n const extra = el('div', 'twm-chat__extra');\n row.append(body, extra);\n const entry = { message, row, body, extra };\n into.set(message.id, entry);\n drawBody(entry, streaming);\n return entry;\n }\n\n function append(message) {\n const entry = build(message);\n log.append(entry.row);\n settle();\n return entry.message.id;\n }\n\n /**\n * Takes one message out and leaves every other one, with its slot, as it is.\n * An open stream on that message is over. False for an unknown id.\n */\n function remove(id) {\n const entry = entries.get(id);\n if (!entry) return false;\n if (streamId === id) streamId = null;\n entries.delete(id);\n entry.row.remove();\n settle();\n return true;\n }\n\n /** All or nothing: a repeated id throws before the transcript is touched. No list (undefined or null) empties it. */\n function replaceAll(messages) {\n const list = [...(messages ?? [])];\n const given = new Set();\n for (const m of list) {\n if (m?.id == null) continue;\n if (given.has(m.id)) throw duplicate(m.id);\n given.add(m.id);\n }\n const next = new Map();\n const taken = (id) => given.has(id) || next.has(id);\n const frag = doc.createDocumentFragment();\n for (const m of list) frag.append(build(m, { into: next, taken }).row);\n streamId = null;\n entries.clear();\n for (const [id, entry] of next) entries.set(id, entry);\n log.replaceChildren(frag);\n setPinned(true);\n toBottom();\n }\n\n function clear() { replaceAll([]); }\n\n // \u2500\u2500 streaming \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Refused (a throw, nothing changed, an open stream left open) on an id\n * already present. No message (undefined or null) streams an empty\n * assistant message, as `append` treats them.\n */\n function beginStream(message) {\n if (message?.id != null && entries.has(message.id)) throw duplicate(message.id);\n if (streamId !== null) endStream();\n const entry = build({ role: 'assistant', text: '', ...(message ?? {}) }, { streaming: true });\n streamId = entry.message.id;\n log.append(entry.row);\n settle();\n return streamId;\n }\n\n function appendChunk(chunk) {\n const entry = streamId !== null ? entries.get(streamId) : null;\n if (!entry) return;\n entry.message.text += String(chunk ?? '');\n drawBody(entry);\n settle();\n }\n\n function endStream() {\n const entry = streamId !== null ? entries.get(streamId) : null;\n streamId = null;\n if (!entry) return null;\n entry.row.classList.remove('twm-chat__msg--streaming');\n drawBody(entry);\n settle();\n return entry.message.id;\n }\n\n // \u2500\u2500 the composer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function grow() {\n input.style.height = 'auto';\n input.style.height = `${Math.min(input.scrollHeight, composerMaxHeight)}px`;\n input.style.overflowY = input.scrollHeight > composerMaxHeight ? 'auto' : 'hidden';\n }\n\n function drawSend() {\n send.replaceChildren(icon(busy ? 'stop' : 'send'));\n send.setAttribute('aria-label', busy ? text.cancel : text.send);\n send.title = busy ? text.cancel : text.send;\n send.classList.toggle('twm-chat__send--cancel', busy);\n root.classList.toggle('twm-chat--busy', busy);\n }\n\n function submit() {\n if (busy) return;\n const value = input.value;\n if (!value.trim()) return;\n input.value = '';\n grow();\n onSubmit?.(value);\n }\n\n function cancel() {\n if (!busy || cancelled) return;\n cancelled = true;\n onCancel?.();\n }\n\n /** Enter submits; Shift+Enter (and Ctrl/Meta/Alt+Enter) is the browser's to handle. */\n function onInputKey(e) {\n if (e.isComposing || e.key !== 'Enter') return;\n if (e.shiftKey || e.ctrlKey || e.metaKey || e.altKey) return;\n e.preventDefault();\n submit();\n }\n /**\n * Esc while busy cancels wherever focus is inside the view, and it is the\n * view's alone: it goes no further, so a window or panel holding the view\n * that closes on Escape stays open \u2014 on the cancelling Esc and on any\n * repeat in the same busy period. An Esc a handler inside the view\n * already consumed (defaultPrevented) is that handler's: it neither\n * cancels nor is stopped.\n */\n function onRootKey(e) {\n if (e.isComposing || e.key !== 'Escape' || !busy || e.defaultPrevented) return;\n e.preventDefault();\n e.stopPropagation();\n cancel();\n }\n input.addEventListener('keydown', onInputKey);\n input.addEventListener('input', grow);\n root.addEventListener('keydown', onRootKey);\n send.addEventListener('click', () => (busy ? cancel() : submit()));\n drawSend();\n\n return {\n root,\n append,\n remove,\n replaceAll,\n clear,\n beginStream,\n appendChunk,\n endStream,\n /** A copy of every message, in order. */\n messages: () => [...entries.values()].map((e) => snapshot(e.message)),\n /** The extra slot below a message's body, or null for an unknown id. */\n slot: (id) => entries.get(id)?.extra ?? null,\n /** The id of the message being streamed, or null. */\n streamingId: () => streamId,\n isPinned: () => pinned,\n getScrollTop: () => log.scrollTop,\n /** Scrolls the transcript; pinned again only when that lands at the end. */\n setScrollTop(px) {\n log.scrollTop = px;\n lastScrollTop = log.scrollTop;\n setPinned(distanceFromEnd() <= pinThreshold);\n },\n scrollToBottom: onJump,\n /** `true` turns Send into Cancel; every busy period may cancel once. */\n setBusy(value) {\n if (busy === !!value) return;\n busy = !!value;\n cancelled = false;\n drawSend();\n },\n isBusy: () => busy,\n getText: () => input.value,\n setText(value) { input.value = String(value ?? ''); grow(); },\n focus: () => input.focus(),\n destroy() {\n if (destroyed) return;\n destroyed = true;\n streamId = null;\n busy = false;\n cancelled = false;\n entries.clear();\n root.remove();\n },\n };\n}\n", "/**\n * \u2550\u2550 THE ASSISTANT CHAT SHELL \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A whole assistant chat over the conversation view: conversation tabs, an\n * optional mode toggle, a model picker, a reply that streams (typing dots, tool\n * calls, stop), Markdown bodies, time and copy on every message, and a slot on\n * each assistant message for controls of the caller's. It knows no provider and\n * nothing of what a reply is about. The caller passes a transport and reads\n * back snapshots to keep.\n *\n * const chat = mountChatShell(el, {\n * transport: {\n * send(request, emit) { backend.ask(request, (e) => emit(toChatEvent(e))); },\n * cancel(request) { backend.stop(); },\n * },\n * modes: [{ id: 'ask', label: 'Ask' }, { id: 'act', label: 'Act' }],\n * models: { items: [{ id: 'a', label: 'Large' }], activeId: 'a' },\n * onModelSelect: (item) => chat.setModels({ activeId: item.id }),\n * renderControls: (el, message) => { ... },\n * conversations: saved,\n * onChange: (snapshot) => save(snapshot),\n * });\n *\n * THE TRANSPORT is `{ send(request, emit), cancel?(request) }`. A request is\n * `{ text, tabId, conversationId, mode, model }`. `emit` takes one event at a\n * time (`CHAT_TRANSPORT_EVENTS`):\n *\n * { type: 'text-delta', text }\n * { type: 'tool-use', id?, name, label?, status? } running | done | error\n * { type: 'message-end', text?, conversationId?, meta? }\n * { type: 'error', message }\n *\n * `message-end` and `error` finish the turn. Every `emit` belongs to its turn:\n * what it is handed once that turn has finished or been cancelled is dropped.\n * A `send` that throws, or answers a promise that rejects, is an `error` event.\n * A `tool-use` with the id of one already shown updates it.\n *\n * A backend whose frames carry no run id can only hand them to the latest\n * `emit`, so runs must not overlap: `cancel` answers a promise that settles when\n * the cancelled run is really over, and the next turn's `send` waits for it. That\n * turn shows at once, and until then the old run's frames still reach the dead\n * `emit`. Stopping a turn whose `send` is still waiting calls no `transport.cancel`.\n *\n * A TURN: the user's message goes in, then a streamed reply that shows the\n * typing dots while it is empty. Tool calls are listed under the body. The turn\n * ends in one of three ways, and a reply left with no text, no tool call and no\n * `meta` is taken out in each:\n * - `message-end`: `text` fills the reply only if nothing was streamed; `meta`\n * is merged into the message's.\n * - Stop (Cancel, Esc, or `cancel()`): what arrived stays, running tools become\n * `stopped`, `transport.cancel` is called once `send` has been.\n * - `error`: as Stop, without `transport.cancel`, and an error message follows.\n * While it is the last message it carries Retry, which sends the user message\n * before it again.\n *\n * CONVERSATIONS: the shell owns the tabs. While a turn runs the tab in front\n * cannot be left, closed or cleared; other tabs can still be closed, and the\n * last one never can. `snapshot()` is `{ activeId, tabs: [{ id, title,\n * conversationId, messages }] }`, plain data to keep, and `conversations` takes\n * one back. A message is `{ id, role, text, at?, tools?, meta? }`; `meta` is\n * yours and is handed back untouched. A reply still empty is not in a snapshot.\n *\n * CONTROLS: `renderControls(el, message, chat)` fills an emptied element below an\n * assistant message's body once the reply has finished, and again when the\n * message comes back from a tab switch or `refreshControls(id)`/`updateMeta(id,\n * patch)`. Everything it needs to survive goes in `message.meta`.\n *\n * THE MODEL PICKER is controlled: choosing an item calls `onModelSelect(item)`\n * (an item with an `action` calls `onModelAction(action, item)`), and the picker\n * changes when you call `setModels`, which takes any of `{ items, activeId, label,\n * status }`. With no items and no label there is no button; with no modes either\n * there is no bar.\n *\n * Nothing is stored in the DOM. `destroy()` cancels a running turn and removes\n * everything, the picker's menu on `document.body` included.\n */\n\nimport { ActionDropdown } from './action_dropdown.js';\nimport { CHAT_STATES, ChatStateMachine } from './chat_state_machine.js';\nimport { showConfirmDialog } from './confirm_dialog.js';\nimport { mountConversationView } from './conversation_view.js';\nimport { createTabs } from './tabs.js';\nimport { renderMarkdown } from '../utils/markdown.js';\n\nexport const CHAT_TRANSPORT_EVENTS = Object.freeze({\n TEXT_DELTA: 'text-delta',\n TOOL_USE: 'tool-use',\n MESSAGE_END: 'message-end',\n ERROR: 'error',\n});\n\n/** Every text the shell shows; pass `labels` to replace any of them. */\nexport const CHAT_SHELL_LABELS = Object.freeze({\n send: 'Send',\n cancel: 'Cancel',\n jump: 'Jump to latest',\n input: 'Message',\n conversations: 'Conversations',\n newConversation: 'New chat',\n add: 'New conversation',\n clear: 'Clear conversation',\n clearTitle: 'Clear conversation',\n clearMessage: 'Clear this conversation? This cannot be undone.',\n clearOk: 'Clear',\n clearCancel: 'Cancel',\n rename: 'Conversation name',\n modes: 'Mode',\n selectModel: 'Select model...',\n typing: 'The assistant is replying',\n copy: 'Copy message',\n retry: 'Retry',\n retryTitle: 'Send the message again',\n unknownError: 'Unknown error',\n});\n\nconst TITLE_CHARS = 30;\nconst COPIED_MS = 1500;\nconst TOOL_ICONS = Object.freeze({ running: 'build', done: 'check', error: 'error', stopped: 'block' });\n\nconst defaultTitle = (text) => (text.length > TITLE_CHARS ? `${text.slice(0, TITLE_CHARS)}...` : text);\n\nfunction defaultTime(at) {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return '';\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/**\n * @param {HTMLElement} host\n * @param {object} opts\n * @param {object} opts.transport `{ send(request, emit), cancel?(request) }`\n * @param {Function} [opts.renderControls] `(el, message, chat)` \u2014 an assistant message's controls\n * @param {object} [opts.markdown] options for `renderMarkdown`\n * @param {Function} [opts.onChange] `(snapshot)` \u2014 something worth keeping changed\n * @param {Function} [opts.onConversationChange] `(conversation, reason)` \u2014 another conversation is in front; reason is `new`, `switch`, `close` or `reset`\n * @param {Array} [opts.modes] `[{ id, label, title? }]`; none, no toggle\n * @param {string} [opts.mode] the mode to start in; the first without it\n * @param {Function} [opts.onModeChange] `(id)` \u2014 the user chose a mode\n * @param {object} [opts.models] `{ items, activeId, label, status }`, as `setModels`\n * @param {Function} [opts.onModelSelect] `(item)`\n * @param {Function} [opts.onModelAction] `(action, item)`\n * @param {object} [opts.conversations] a `snapshot()` to restore\n * @param {Function} [opts.titleFrom] `(text)` \u2014 a new conversation's title, from its first message\n * @param {Function} [opts.formatTime] `(at, message)` \u2014 a message's time; `''` shows none\n * @param {string} [opts.placeholder] the composer's placeholder\n * @param {object} [opts.welcome] `{ icon?, text }`, shown while the transcript is empty\n * @param {object} [opts.labels] over `CHAT_SHELL_LABELS`\n * @param {object} [opts.eventBus] gets `CHAT_BUS_EVENTS`\n * @param {object} [opts.logger]\n * @returns {object} the chat (see the methods below)\n */\nexport function mountChatShell(host, {\n transport, renderControls = null, markdown = {}, onChange = null, onConversationChange = null,\n modes = [], mode = null, onModeChange = null, models = null, onModelSelect = null, onModelAction = null,\n conversations = null, titleFrom = defaultTitle, formatTime = defaultTime, placeholder = '', welcome = null,\n labels = {}, eventBus = null, logger = null,\n} = {}) {\n if (typeof transport?.send !== 'function') {\n throw new TypeError('mountChatShell: a transport with send(request, emit) is required');\n }\n const text = { ...CHAT_SHELL_LABELS, ...labels };\n const doc = host.ownerDocument;\n const el = (tag, cls, content) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (content !== undefined) n.textContent = content;\n return n;\n };\n const icon = (name, cls = '') => {\n const i = el('span', `material-symbols-outlined ${cls}`.trim(), name);\n i.setAttribute('aria-hidden', 'true');\n return i;\n };\n const button = (cls, title) => {\n const b = el('button', cls);\n b.type = 'button';\n b.title = title;\n b.setAttribute('aria-label', title);\n return b;\n };\n /** A callback of the caller's: one that throws is logged, and the chat carries on. */\n const safely = (fn, ...args) => {\n try { return fn?.(...args); } catch (error) {\n logger?.error?.('chat-shell', 'A callback threw', { error });\n return undefined;\n }\n };\n\n let destroyed = false;\n /** The exchange in flight: `{ token, replyId, request, started, sent }`, or null. */\n let turn = null;\n /** Settles when the run `transport.cancel` stopped is over; null when none is ending. */\n let runEnding = null;\n /** id \u2192 { at, tools, meta, toolsEl, controlsEl, footerEl }, for the messages on show. */\n const extras = new Map();\n const copyTimers = new Set();\n\n const modeIds = modes.map((m) => m.id);\n const machine = new ChatStateMachine({\n eventBus,\n logger,\n mode: modeIds.includes(mode) ? mode : (modeIds[0] ?? null),\n onChange: ({ state }) => { if (!destroyed) showState(state); },\n });\n\n // \u2500\u2500 the frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-chat-shell');\n const tabBar = el('div', 'twm-chat-shell__tab-bar');\n const tabsHost = el('div', 'twm-chat-shell__tabs');\n const addBtn = button('twm-chat-shell__tab-btn', text.add);\n addBtn.append(icon('add'));\n const clearBtn = button('twm-chat-shell__tab-btn twm-chat-shell__tab-btn--clear', text.clear);\n clearBtn.append(icon('delete_sweep'));\n tabBar.append(tabsHost, addBtn, clearBtn);\n const conversationHost = el('div', 'twm-chat-shell__conversation');\n const bar = el('div', 'twm-chat-shell__bar');\n root.append(tabBar, conversationHost, bar);\n host.append(root);\n\n const view = mountConversationView(conversationHost, {\n render: drawBody,\n onSubmit: (value) => send(value),\n onCancel: () => cancel(),\n onRenderError: (error, message) => logger?.error?.('chat-shell', 'Could not draw a message', { error, message }),\n placeholder,\n labels: { send: text.send, cancel: text.cancel, jump: text.jump, input: text.input },\n });\n\n const welcomeEl = welcome ? el('div', 'twm-chat-shell__welcome') : null;\n if (welcomeEl) {\n if (welcome.icon) welcomeEl.append(icon(welcome.icon, 'twm-chat-shell__welcome-icon'));\n welcomeEl.append(el('p', 'twm-chat-shell__welcome-text', welcome.text ?? ''));\n view.root.querySelector('.twm-chat__viewport').prepend(welcomeEl);\n }\n const syncWelcome = () => { if (welcomeEl) welcomeEl.hidden = view.messages().length > 0; };\n\n function showState(state) {\n const busy = state === CHAT_STATES.WAITING || state === CHAT_STATES.STREAMING;\n view.setBusy(busy);\n addBtn.disabled = busy;\n clearBtn.disabled = busy;\n }\n\n // \u2500\u2500 bodies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** An assistant's body is Markdown, with the typing dots while it is empty and streaming; any other is text. */\n function drawBody(message, body, { streaming }) {\n if (message.role !== 'assistant') {\n body.textContent = message.text;\n return;\n }\n if (streaming && !message.text) {\n const dots = el('span', 'twm-chat-shell__typing');\n dots.setAttribute('role', 'img');\n dots.setAttribute('aria-label', text.typing);\n dots.append(el('span'), el('span'), el('span'));\n body.append(dots);\n return;\n }\n body.innerHTML = renderMarkdown(message.text, markdown);\n }\n\n // \u2500\u2500 what sits below a body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const viewMessage = (id) => view.messages().find((m) => m.id === id) ?? null;\n\n /** A message as it is kept and as callers see it. */\n function kept({ id, role, text: body }) {\n const { at, tools, meta } = extras.get(id) ?? {};\n const message = { id, role, text: body };\n if (at) message.at = at;\n if (tools?.length) message.tools = tools.map((t) => ({ ...t }));\n if (meta !== undefined) message.meta = meta;\n return message;\n }\n\n /** The messages worth showing a caller: a reply with nothing in it yet is not one. */\n function keptMessages() {\n const streaming = view.streamingId();\n return view.messages()\n .filter((m) => m.id !== streaming || m.text || extras.get(m.id)?.tools.length)\n .map(kept);\n }\n\n /** Puts a message's three blocks in its slot and remembers what it carries. */\n function register(id, { at, tools = [], meta }) {\n const entry = {\n at,\n tools,\n meta,\n toolsEl: el('div', 'twm-chat-shell__tools'),\n controlsEl: el('div', 'twm-chat-shell__controls'),\n footerEl: el('div', 'twm-chat-shell__footer'),\n };\n extras.set(id, entry);\n view.slot(id).append(entry.toolsEl, entry.controlsEl, entry.footerEl);\n return entry;\n }\n\n function drawTools(id) {\n const entry = extras.get(id);\n entry.toolsEl.replaceChildren(...entry.tools.map((tool) => {\n const row = el('div', `twm-chat-shell__tool twm-chat-shell__tool--${tool.status}`);\n row.append(\n icon(TOOL_ICONS[tool.status], 'twm-chat-shell__tool-icon'),\n el('span', 'twm-chat-shell__tool-label', tool.label ?? tool.name),\n );\n return row;\n }));\n }\n\n function drawControls(id) {\n const message = viewMessage(id);\n const entry = extras.get(id);\n if (!renderControls || !message || !entry) return;\n if (message.role !== 'assistant' || id === view.streamingId()) return;\n entry.controlsEl.replaceChildren();\n safely(renderControls, entry.controlsEl, kept(message), chat);\n }\n\n function copyButton(id) {\n const copy = button('twm-chat-shell__copy', text.copy);\n const glyph = icon('content_copy');\n copy.append(glyph);\n copy.addEventListener('click', () => {\n Promise.resolve()\n .then(() => doc.defaultView.navigator.clipboard.writeText(viewMessage(id)?.text ?? ''))\n .then(() => {\n copy.classList.add('twm-chat-shell__copy--done');\n glyph.textContent = 'check';\n const timer = setTimeout(() => {\n copyTimers.delete(timer);\n copy.classList.remove('twm-chat-shell__copy--done');\n glyph.textContent = 'content_copy';\n }, COPIED_MS);\n copyTimers.add(timer);\n })\n .catch((error) => logger?.warn?.('chat-shell', 'Could not copy a message', { error }));\n });\n return copy;\n }\n\n /** The user message a failed request sent, while that failure is the last message. */\n function retryable(id, list) {\n const last = list.at(-1);\n if (last?.id !== id || last.role !== 'error') return null;\n return list.slice(0, -1).reverse().find((m) => m.role === 'user') ?? null;\n }\n\n function drawFooter(id, list = view.messages()) {\n const entry = extras.get(id);\n entry.footerEl.replaceChildren();\n if (id === view.streamingId()) return;\n const user = retryable(id, list);\n if (user) {\n const retry = el('button', 'twm-chat-shell__retry');\n retry.type = 'button';\n retry.title = text.retryTitle;\n retry.append(icon('refresh'), doc.createTextNode(text.retry));\n retry.addEventListener('click', () => send(user.text));\n entry.footerEl.append(retry);\n }\n const message = list.find((m) => m.id === id);\n const time = entry.at ? safely(formatTime, entry.at, kept(message)) : '';\n if (time) entry.footerEl.append(el('span', 'twm-chat-shell__time', time));\n entry.footerEl.append(copyButton(id));\n }\n\n /** The slots grew too, and the view only follows changes of its own. */\n const follow = () => { if (view.isPinned()) view.scrollToBottom(); };\n\n /** A message just took the last place: the failure before it loses its Retry. */\n function redrawFailures() {\n const list = view.messages();\n for (const { id, role } of list) if (role === 'error') drawFooter(id, list);\n }\n\n function appendMessage(role, body) {\n const id = view.append({ role, text: body });\n register(id, { at: new Date().toISOString() });\n redrawFailures();\n drawFooter(id);\n follow();\n return id;\n }\n\n // \u2500\u2500 conversations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const newTab = (id) => ({\n id, title: text.newConversation, conversationId: null, messages: [], scrollTop: null,\n });\n const tabs = [];\n let activeId = null;\n let nextTab = 1;\n const tabOf = (id) => tabs.find((t) => t.id === String(id)) ?? null;\n const activeTab = () => tabOf(activeId);\n function freshTab() {\n let id;\n do id = `chat-${nextTab++}`; while (tabOf(id));\n const tab = newTab(id);\n tabs.push(tab);\n return tab;\n }\n\n /** Kept data back into a message list: a tool cannot still be running after a restart. */\n function restored(messages) {\n return (messages ?? [])\n .filter((m) => m && typeof m.role === 'string')\n .map((m) => {\n const tools = m.tools?.map((t) => (t.status === 'running' ? { ...t, status: 'stopped' } : { ...t }));\n return tools ? { ...m, tools } : { ...m };\n });\n }\n\n const strip = createTabs(tabsHost, {\n items: [],\n compact: true,\n label: text.conversations,\n onSelect: (id) => {\n if (id == null || id === activeId) return;\n switchTo(id);\n // A switch refused leaves the conversation in front where it was.\n if (strip.active() !== activeId) strip.update(tabItems(), activeId);\n },\n onClose: (id) => close(id),\n });\n function tabItems() {\n const closable = tabs.length > 1;\n return tabs.map(({ id, title }) => ({ id, label: title, title, closable }));\n }\n const drawTabs = () => strip.update(tabItems(), activeId);\n\n /** Rename over the tab (a tab is a button, whose content cannot be edited). Enter or leaving commits; Escape does not. */\n function beginRename(id, tabEl) {\n if (tabBar.querySelector('.twm-chat-shell__rename')) return;\n const original = tabOf(id)?.title ?? '';\n const barRect = tabBar.getBoundingClientRect();\n const tabRect = tabEl.getBoundingClientRect();\n const input = el('input', 'twm-chat-shell__rename');\n input.type = 'text';\n input.value = original;\n input.spellcheck = false;\n input.setAttribute('aria-label', text.rename);\n input.style.left = `${Math.max(0, tabRect.left - barRect.left)}px`;\n input.style.width = `${Math.max(tabRect.width, 120)}px`;\n tabBar.append(input);\n input.focus();\n input.select();\n let done = false;\n const finish = (commit) => {\n if (done) return;\n done = true;\n input.remove();\n const name = input.value.trim();\n if (commit && name && name !== original) rename(id, name);\n };\n input.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' && e.key !== 'Escape') return;\n e.preventDefault();\n e.stopPropagation();\n finish(e.key === 'Enter');\n });\n input.addEventListener('blur', () => finish(true));\n }\n const renameTarget = (e) => {\n const tab = e.target.closest?.('.twm-tabs__tab');\n if (tab) beginRename(tab.dataset.tabId, tab);\n };\n strip.root.addEventListener('dblclick', renameTarget);\n strip.root.addEventListener('keydown', (e) => { if (e.key === 'F2') renameTarget(e); });\n\n /** The live transcript back into its tab. */\n function stash() {\n const tab = activeTab();\n tab.messages = keptMessages();\n tab.scrollTop = view.getScrollTop();\n }\n\n function showTab(tab) {\n const messages = restored(tab.messages);\n extras.clear();\n view.replaceAll(messages.map(({ id, role, text: body }) => ({ id, role, text: body })));\n const list = view.messages();\n list.forEach(({ id }, i) => {\n const { at, tools, meta } = messages[i];\n register(id, { at, tools: tools ?? [], meta });\n drawTools(id);\n drawControls(id);\n drawFooter(id, list);\n });\n if (tab.scrollTop !== null) view.setScrollTop(tab.scrollTop);\n else view.scrollToBottom();\n syncWelcome();\n }\n\n function snapshot() {\n stash();\n return {\n activeId,\n tabs: tabs.map(({ id, title, conversationId, messages }) => ({\n id, title, conversationId, messages: messages.map((m) => ({ ...m })),\n })),\n };\n }\n const changed = () => { if (onChange) safely(onChange, snapshot()); };\n\n function bringToFront(tab, reason) {\n activeId = tab.id;\n if (tab.conversationId) machine.loadConversation(tab.conversationId);\n else machine.newConversation();\n showTab(tab);\n drawTabs();\n const { id, title, conversationId } = tab;\n safely(onConversationChange, { id, title, conversationId, messages: restored(tab.messages) }, reason);\n changed();\n }\n\n function newConversation() {\n if (turn) return null;\n stash();\n const tab = freshTab();\n bringToFront(tab, 'new');\n return tab.id;\n }\n\n function switchTo(id) {\n const tab = tabOf(id);\n if (turn || !tab || tab.id === activeId) return false;\n stash();\n bringToFront(tab, 'switch');\n return true;\n }\n\n function close(id) {\n const tab = tabOf(id);\n if (!tab || tabs.length <= 1 || (turn && tab.id === activeId)) return false;\n const wasActive = tab.id === activeId;\n tabs.splice(tabs.indexOf(tab), 1);\n if (wasActive) {\n bringToFront(tabs[0], 'close');\n } else {\n drawTabs();\n changed();\n }\n return true;\n }\n\n function rename(id, title) {\n const tab = tabOf(id);\n const name = String(title ?? '').trim();\n if (!tab || !name) return false;\n tab.title = name;\n drawTabs();\n changed();\n return true;\n }\n\n /** Empties the conversation in front and forgets its title and id. */\n function reset() {\n if (turn) return false;\n const tab = activeTab();\n Object.assign(tab, { title: text.newConversation, conversationId: null, messages: [], scrollTop: null });\n bringToFront(tab, 'reset');\n return true;\n }\n\n addBtn.addEventListener('click', () => newConversation());\n clearBtn.addEventListener('click', async () => {\n if (view.messages().length > 0) {\n const confirmed = await showConfirmDialog({\n title: text.clearTitle,\n message: text.clearMessage,\n icon: 'delete_sweep',\n okLabel: text.clearOk,\n cancelLabel: text.clearCancel,\n okVariant: 'danger',\n });\n if (!confirmed || destroyed) return;\n }\n reset();\n });\n\n // \u2500\u2500 the turn \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function send(value) {\n const message = String(value ?? '').trim();\n if (!message || turn) return false;\n const tab = activeTab();\n appendMessage('user', message);\n if (tab.title === text.newConversation) {\n const title = safely(titleFrom, message);\n if (title) {\n tab.title = String(title);\n drawTabs();\n }\n }\n const replyId = view.beginStream({ role: 'assistant' });\n register(replyId, { at: new Date().toISOString() });\n redrawFailures();\n syncWelcome();\n const token = {};\n const request = {\n text: message,\n tabId: tab.id,\n conversationId: tab.conversationId,\n mode: machine.mode,\n model: currentModels.activeId ?? null,\n };\n const current = { token, replyId, request, started: false, sent: false };\n turn = current;\n machine.sendMessage(message, tab.conversationId);\n changed();\n\n const emit = (event) => { if (turn?.token === token) handle(event); };\n const fail = (error) => emit({ type: CHAT_TRANSPORT_EVENTS.ERROR, message: error?.message ?? String(error) });\n const start = () => {\n current.sent = true;\n try {\n Promise.resolve(transport.send(request, emit)).catch(fail);\n } catch (error) {\n fail(error);\n }\n };\n if (runEnding) runEnding.then(() => { if (turn === current) start(); });\n else start();\n return true;\n }\n\n function handle(event) {\n switch (event?.type) {\n case CHAT_TRANSPORT_EVENTS.TEXT_DELTA:\n if (!event.text) return;\n markStarted();\n view.appendChunk(event.text);\n return;\n case CHAT_TRANSPORT_EVENTS.TOOL_USE:\n markStarted();\n useTool(event);\n return;\n case CHAT_TRANSPORT_EVENTS.MESSAGE_END:\n endMessage(event);\n return;\n case CHAT_TRANSPORT_EVENTS.ERROR:\n failTurn(event);\n return;\n default:\n logger?.warn?.('chat-shell', 'Unknown transport event', { event });\n }\n }\n\n function markStarted() {\n if (turn.started) return;\n turn.started = true;\n machine.streamStart();\n }\n\n function useTool({ id, name, label, status = 'running' }) {\n const entry = extras.get(turn.replyId);\n const known = status in TOOL_ICONS ? status : 'running';\n const tool = id != null ? entry.tools.find((t) => t.id === id) : null;\n if (tool) {\n Object.assign(tool, { status: known, name: name ?? tool.name, label: label ?? tool.label });\n } else {\n entry.tools.push({ id: id ?? `tool-${entry.tools.length + 1}`, name, label, status: known });\n }\n drawTools(turn.replyId);\n follow();\n }\n\n /** Ends the reply. Tools still running take `toolStatus`; a reply with nothing to show is taken out. */\n function closeReply(toolStatus) {\n const id = turn.replyId;\n turn = null;\n const entry = extras.get(id);\n for (const tool of entry.tools) if (tool.status === 'running') tool.status = toolStatus;\n if (!viewMessage(id).text && !entry.tools.length && entry.meta === undefined) {\n view.remove(id);\n extras.delete(id);\n return;\n }\n view.endStream();\n drawTools(id);\n drawControls(id);\n drawFooter(id);\n follow();\n }\n\n function endMessage({ text: final, conversationId, meta }) {\n const id = turn.replyId;\n const entry = extras.get(id);\n if (final && !viewMessage(id).text) view.appendChunk(final);\n if (meta !== undefined) entry.meta = { ...(entry.meta ?? {}), ...meta };\n if (conversationId) setConversationId(activeId, conversationId);\n const reply = viewMessage(id).text;\n closeReply('done');\n machine.streamComplete({ text: reply, meta: entry.meta });\n syncWelcome();\n changed();\n }\n\n function failTurn({ message }) {\n const body = message || text.unknownError;\n closeReply('stopped');\n machine.error(body);\n appendMessage('error', body);\n syncWelcome();\n changed();\n }\n\n /** Stops the reply: the chat can send again at once, and that send waits for `runEnding`. */\n function cancel() {\n if (!turn) return false;\n const { request, sent } = turn;\n closeReply('stopped');\n machine.cancel();\n if (sent) callCancel(request);\n syncWelcome();\n changed();\n return true;\n }\n\n function callCancel(request) {\n const failed = (error) => logger?.warn?.('chat-shell', 'Cancel failed', { error });\n try {\n const ended = transport.cancel?.(request);\n if (typeof ended?.then !== 'function') return;\n const ending = Promise.resolve(ended).catch(failed).then(() => {\n if (runEnding === ending) runEnding = null;\n });\n runEnding = ending;\n } catch (error) {\n failed(error);\n }\n }\n\n function setConversationId(tabId, conversationId) {\n const tab = tabOf(tabId);\n if (!tab) return false;\n tab.conversationId = conversationId ?? null;\n if (tab.id === activeId) machine.conversationId = tab.conversationId;\n return true;\n }\n\n /** Replaces a conversation's messages (a backend knew better). The one a turn is writing to refuses. */\n function setMessages(tabId, messages) {\n const tab = tabOf(tabId);\n if (!tab || (turn && tab.id === activeId)) return false;\n tab.messages = restored(messages);\n tab.scrollTop = null;\n if (tab.id === activeId) showTab(tab);\n changed();\n return true;\n }\n\n // \u2500\u2500 the bar: modes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const modeButtons = new Map();\n if (modes.length) {\n const group = el('div', 'twm-chat-shell__modes');\n group.setAttribute('role', 'group');\n group.setAttribute('aria-label', text.modes);\n for (const { id, label, title } of modes) {\n const b = el('button', 'twm-chat-shell__mode', label);\n b.type = 'button';\n if (title) b.title = title;\n b.addEventListener('click', () => {\n if (id === machine.mode) return;\n setMode(id);\n safely(onModeChange, id);\n });\n modeButtons.set(id, b);\n group.append(b);\n }\n bar.append(group);\n }\n function drawMode() {\n for (const [id, b] of modeButtons) {\n const on = id === machine.mode;\n b.classList.toggle('twm-chat-shell__mode--on', on);\n b.setAttribute('aria-pressed', String(on));\n }\n }\n function setMode(id) {\n if (!modeButtons.has(id)) return false;\n machine.setMode(id);\n drawMode();\n return true;\n }\n drawMode();\n bar.append(el('div', 'twm-chat-shell__bar-spacer'));\n\n // \u2500\u2500 the bar: the model picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let currentModels = { items: [], activeId: null, label: null, status: null };\n const modelBtn = el('button', 'twm-chat-shell__model-btn');\n modelBtn.type = 'button';\n modelBtn.setAttribute('aria-haspopup', 'menu');\n const modelDot = el('span', 'twm-chat-shell__status');\n const modelLabel = el('span', 'twm-chat-shell__model-label');\n modelBtn.append(modelDot, modelLabel, icon('expand_more', 'twm-chat-shell__model-chevron'));\n bar.append(modelBtn);\n /** ActionDropdown puts an option's label and description in as markup; these are text. */\n const asMarkup = (value) => {\n const span = el('span');\n span.textContent = String(value ?? '');\n return span.innerHTML;\n };\n const modelMenu = new ActionDropdown({\n trigger: modelBtn,\n options: [],\n className: 'twm-chat-shell__model-menu',\n onSelect: ({ item }) => {\n if (item.action !== undefined) safely(onModelAction, item.action, item);\n else safely(onModelSelect, item);\n },\n });\n\n /**\n * Any of `{ items, activeId, label, status }`; what is left out stays. An item\n * is `{ id, label, description?, icon? }`, `{ action, label, description?, icon? }`\n * or `{ separator: true }`. `label` is the button's text (the active item's\n * without it); `status` is `{ state?: 'ready' | 'pending', label? }`, a dot on it.\n */\n function setModels(patch = {}) {\n currentModels = { ...currentModels, ...patch };\n const { items, activeId: active, label, status } = currentModels;\n modelMenu.setOptions(items.map((item) => {\n if (item.separator) return { separator: true };\n const isAction = item.action !== undefined;\n const radio = item.id === active ? 'radio_button_checked' : 'radio_button_unchecked';\n return {\n type: isAction ? 'action' : 'model',\n item,\n label: asMarkup(item.label),\n icon: item.icon ?? (isAction ? undefined : radio),\n description: item.description ? asMarkup(item.description) : undefined,\n };\n }));\n modelLabel.textContent = label ?? items.find((i) => !i.separator && i.id === active)?.label ?? text.selectModel;\n modelDot.className = status?.state\n ? `twm-chat-shell__status twm-chat-shell__status--${status.state}` : 'twm-chat-shell__status';\n modelDot.title = status?.label ?? '';\n modelDot.hidden = !status;\n modelBtn.hidden = !items.length && !label;\n bar.hidden = modelBtn.hidden && !modes.length;\n }\n setModels(models ?? {});\n\n // \u2500\u2500 the chat \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const chat = {\n root,\n /** Sends as the user would; false when a turn is running or the text is blank. */\n send,\n /** Stops the running reply; false when there is none. */\n cancel,\n /** A turn is running. Answers at once, where `stateMachine` follows in microtasks. */\n isBusy: () => turn !== null,\n stateMachine: machine,\n\n /** The messages of the conversation in front. */\n messages: keptMessages,\n /** Merges into a message's `meta`, redraws its controls, and reports a change. */\n updateMeta(id, patch) {\n const entry = extras.get(id);\n if (!entry) return false;\n entry.meta = { ...(entry.meta ?? {}), ...patch };\n drawControls(id);\n changed();\n return true;\n },\n refreshControls: (id) => drawControls(id),\n /** The element holding a message's controls, or null. */\n controlsSlot: (id) => extras.get(id)?.controlsEl ?? null,\n\n snapshot,\n activeConversation: () => activeId,\n newConversation,\n switchTo,\n close,\n rename,\n reset,\n setConversationId,\n setMessages,\n\n mode: () => machine.mode,\n setMode,\n setModels,\n\n getText: () => view.getText(),\n setText: (value) => view.setText(value),\n focus: () => view.focus(),\n\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (turn) {\n const { request } = turn;\n turn = null;\n callCancel(request);\n }\n for (const timer of copyTimers) clearTimeout(timer);\n copyTimers.clear();\n extras.clear();\n modelMenu.destroy();\n strip.destroy();\n view.destroy();\n root.remove();\n },\n };\n\n // \u2500\u2500 what it starts with \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 for (const saved of conversations?.tabs ?? []) {\n tabs.push({\n ...newTab(String(saved.id)),\n title: saved.title || text.newConversation,\n conversationId: saved.conversationId ?? null,\n messages: restored(saved.messages),\n });\n }\n const first = tabOf(conversations?.activeId) ?? tabs[0] ?? freshTab();\n activeId = first.id;\n if (first.conversationId) machine.loadConversation(first.conversationId);\n showTab(first);\n drawTabs();\n return chat;\n}\n", "/**\n * DetailHeader \u2014 shared header bar for detail views.\n *\n * Usage:\n * import { createDetailHeader, updateDetailHeader } from '../ui/components/detail_header.js';\n *\n * const header = createDetailHeader({\n * title: 'My Scenario',\n * badges: [{ text: 'Static' }],\n * renameable: true,\n * onRename: async (name) => ({ success: true }),\n * actions: [\n * { key: 'run', label: 'Run', icon: 'play_arrow', variant: 'primary', handler: () => {} },\n * { key: 'delete', label: 'Delete', icon: 'delete', variant: 'danger', handler: () => {} },\n * ],\n * });\n * container.appendChild(header);\n *\n * To update in place (e.g., running state changed):\n * updateDetailHeader(header, { ...newConfig });\n */\n\nimport { attachInlineRenamer } from './inline_renamer.js';\n\nconst ESC = (s) => String(s ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n/**\n * @typedef {Object} DetailHeaderBadge\n * @property {string} text\n * @property {string} [className] - Extra class(es) of your own (e.g., 'my-badge--live'); the\n * pill itself is `.twm-detail-header__badge`\n * @property {string} [icon] - Material Symbols icon name\n */\n\n/**\n * @typedef {Object} DetailHeaderAction\n * @property {string} key - data-action value\n * @property {string} label - Button text\n * @property {string} [icon] - Material Symbols icon name (none: label only)\n * @property {'primary'|'secondary'|'danger'} [variant='secondary'] - The button is a `.twm-btn`;\n * 'primary' and 'danger' add `.twm-btn--primary` / `.twm-btn--danger`, and every\n * variant is also named `.twm-detail-header__btn--<variant>`\n * @property {boolean} [disabled=false]\n * @property {string} [title] - Tooltip\n * @property {Function} handler - Click callback\n */\n\n/**\n * @typedef {Object} DetailHeaderConfig\n * @property {string} title\n * @property {string} [subtitle]\n * @property {string} [icon] - Material icon before title\n * @property {DetailHeaderBadge[]} [badges]\n * @property {DetailHeaderAction[]} [actions]\n * @property {HTMLElement[]} [extraElements] - Custom elements appended to actions area\n * @property {boolean} [renameable=false]\n * @property {Function} [onRename] - (newName) => Promise<{success, newValue?}>\n */\n\n/**\n * Create a detail header element.\n * @param {DetailHeaderConfig} config\n * @returns {HTMLElement}\n */\nexport function createDetailHeader(config) {\n const header = document.createElement('header');\n header.className = 'twm-detail-header';\n _populate(header, config);\n return header;\n}\n\n/**\n * Update an existing detail header in place.\n * Destroys previous inline renamer and rebuilds inner DOM.\n * @param {HTMLElement} headerEl\n * @param {DetailHeaderConfig} config\n */\nexport function updateDetailHeader(headerEl, config) {\n // Destroy previous renamer if any\n headerEl._renamer?.destroy();\n headerEl._renamer = null;\n headerEl.innerHTML = '';\n _populate(headerEl, config);\n}\n\n// \u2500\u2500\u2500 Internal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction _populate(header, config) {\n const { title, subtitle, icon, badges = [], actions = [], extraElements = [], renameable = false, onRename } = config;\n\n // Title row\n const titleRow = document.createElement('div');\n titleRow.className = 'twm-detail-header__title-row';\n\n if (icon) {\n const iconEl = document.createElement('span');\n iconEl.className = 'twm-detail-header__icon material-symbols-outlined';\n iconEl.textContent = icon;\n titleRow.appendChild(iconEl);\n }\n\n const nameEl = document.createElement('h2');\n nameEl.className = 'twm-detail-header__name';\n nameEl.textContent = title || '';\n if (renameable) {\n nameEl.dataset.renameable = '';\n nameEl.title = 'Double-click to rename';\n }\n titleRow.appendChild(nameEl);\n\n for (const badge of badges) {\n const badgeEl = document.createElement('span');\n badgeEl.className = `twm-detail-header__badge${badge.className ? ` ${badge.className}` : ''}`;\n if (badge.icon) {\n const bi = document.createElement('span');\n bi.className = 'twm-detail-header__badge-icon material-symbols-outlined';\n bi.textContent = badge.icon;\n badgeEl.appendChild(bi);\n }\n badgeEl.appendChild(document.createTextNode(badge.text));\n titleRow.appendChild(badgeEl);\n }\n\n header.appendChild(titleRow);\n\n // Subtitle\n if (subtitle) {\n const sub = document.createElement('div');\n sub.className = 'twm-detail-header__subtitle';\n sub.innerHTML = subtitle; // may contain <strong> etc.\n header.appendChild(sub);\n }\n\n // Actions\n if (actions.length > 0 || extraElements.length > 0) {\n const actionsEl = document.createElement('div');\n actionsEl.className = 'twm-detail-header__actions';\n\n for (const extra of extraElements) {\n actionsEl.appendChild(extra);\n }\n\n for (const action of actions) {\n const btn = document.createElement('button');\n btn.type = 'button';\n const variant = action.variant || 'secondary';\n // The shared `.twm-btn` look (BUG-0015): 'primary' and 'danger'\n // wear its colour variants; 'secondary' is the plain button.\n const look = variant === 'secondary' ? '' : ` twm-btn--${variant}`;\n btn.className = `twm-btn${look} twm-detail-header__btn twm-detail-header__btn--${variant}`;\n btn.dataset.action = action.key;\n if (action.disabled) btn.disabled = true;\n if (action.title) btn.title = action.title;\n\n if (action.icon) {\n const iconSpan = document.createElement('span');\n iconSpan.className = 'material-symbols-outlined twm-btn__glyph';\n iconSpan.textContent = action.icon;\n btn.appendChild(iconSpan);\n }\n const labelSpan = document.createElement('span');\n labelSpan.className = 'twm-btn__label';\n labelSpan.textContent = action.label ?? '';\n btn.appendChild(labelSpan);\n\n btn.addEventListener('click', () => action.handler?.());\n actionsEl.appendChild(btn);\n }\n\n header.appendChild(actionsEl);\n }\n\n // Inline rename\n if (renameable && onRename) {\n const renamer = attachInlineRenamer({\n label: nameEl,\n onCommit: async (newName) => {\n if (!newName?.trim()) return { success: false };\n return await onRename(newName.trim());\n },\n });\n nameEl.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n renamer.start(e);\n });\n header._renamer = renamer;\n }\n}\n", "/**\n * fact_table.js \u2014 A SHEET OF FACTS: a name and its value, row after row, with\n * no header row, nothing truncated and no height to give it. (0.7.0)\n *\n * Server db-main-01.internal\n * Version 16.4\n * Connection postgresql://tables@db-main-01.internal:5432/tables_control\n * ?application_name=tables-api&sslmode=verify-full\n *\n * A DataTable is the wrong tool for this, for three reasons that are its\n * design rather than its defects: it draws a header row, it clips a cell to\n * one line (a long value becomes an ellipsis), and it fills a box with a\n * height (in a box without one it draws its header and no rows). A fact\n * sheet is the opposite on all three: the names are the header, every value\n * is read whole, and the sheet is exactly as tall as its rows.\n *\n * So this is a plain `<table class=\"twm-facts\">`:\n *\n * - the first column is the LABEL \u2014 muted, and kept on one line (pass\n * `wrapLabels: true` to let a long one wrap, `labelColumn: false` for a\n * sheet whose first column is ordinary data);\n * - every value WRAPS \u2014 at spaces, and inside a long word or URL when it must\n * (`overflow-wrap: anywhere`) \u2014 and keeps its own line breaks, so a\n * pretty-printed JSON value reads as one; `wrap: 'words'` wraps at spaces\n * only and keeps a long word whole (the sheet grows wider, for a sideways\n * scroller around it), and `wrap: 'none'` keeps only the value's own breaks;\n * - a value is text, a number or a NODE (a pill, a link, a button); an\n * object or array is drawn as indented JSON; `null` is an empty cell, or\n * `nullDisplay`;\n * - `mono` draws values in the monospace face, for the whole sheet or one row;\n * - `compare: true` gives each row a BEFORE and an AFTER, with an arrow\n * between: a row whose two sides differ is `--changed`, one that has only\n * an after is `--added`, only a before `--removed`, and the same on both\n * sides `--same`. A row with a plain `value` spans both sides;\n * - `headers` adds a header row after all, for the sheets that have several\n * columns of facts (a list of schemas, a list of pools); rows are then\n * arrays of cells, and `numeric` names the columns of figures.\n *\n * A row may be an OBJECT \u2014 `{label, value}` or `{label, before, after}`, with\n * `mono`, `numeric`, `labelTitle`, `key` and `status` \u2014 or an ARRAY of cells,\n * `[label, value, \u2026]`, which is the positional form a multi-column sheet uses.\n */\n\nlet SEQ = 0;\nconst isNode = (v) => typeof Node !== 'undefined' && v instanceof Node;\n\n/**\n * @typedef {Object} FactRow\n * @property {string|Node} label\n * @property {*} [value]\n * @property {*} [before] - With `compare`: the value before.\n * @property {*} [after] - With `compare`: the value after.\n * @property {boolean} [mono] - This row's values in the monospace face.\n * @property {boolean} [numeric] - This row's values in tabular numerals.\n * @property {string} [labelTitle] - A tooltip on the label.\n * @property {*} [key] - `data-key` on the row.\n * @property {'changed'|'same'|'added'|'removed'} [status] - With `compare`:\n * overrides the status worked out from the two sides.\n */\n\n/**\n * @typedef {Object} FactTableConfig\n * @property {Array<FactRow|Array>} [rows=[]]\n * @property {string[]|null} [headers=null] - A header row. Off by default.\n * @property {boolean} [compare=false] - A before and an after column.\n * @property {boolean} [labelColumn=true] - The first column is a label.\n * @property {boolean} [wrapLabels=false] - Let a long label wrap.\n * @property {'anywhere'|'words'|'none'} [wrap='anywhere'] - How a value wraps:\n * at spaces and inside a long word when it must (the default), at spaces\n * only (`'words'`: a long word stays whole and the sheet grows wider \u2014 for a\n * sheet inside a sideways scroller), or not at all beyond its own line\n * breaks (`'none'`).\n * @property {boolean} [mono=false] - Every value in the monospace face.\n * @property {number[]} [numeric=[]] - Column indices drawn in tabular numerals.\n * @property {string} [nullDisplay=''] - What `null`/`undefined` reads as.\n * @property {string} [missing='\u2014'] - With `compare`: an absent side.\n * @property {Function} [rowClass] - `(row, idx) => string|string[]|null`.\n * @property {Function} [rowAttrs] - `(row, idx) => {name: value}`.\n * @property {string|Node|Function} [emptyState] - Shown when there are no rows.\n * @property {string} [label] - The table's accessible name (`aria-label`).\n * @property {string} [className] - Added to the `<table>`.\n */\n\nexport class FactTable {\n /**\n * @param {HTMLElement|null} host appended to, if given\n * @param {FactTableConfig} [config]\n */\n constructor(host, config = {}) {\n this.config = {\n rows: [],\n headers: null,\n compare: false,\n labelColumn: true,\n wrapLabels: false,\n wrap: 'anywhere',\n mono: false,\n numeric: [],\n nullDisplay: '',\n missing: '\u2014',\n rowClass: null,\n rowAttrs: null,\n emptyState: null,\n label: null,\n className: null,\n ...config,\n };\n this._rows = Array.isArray(this.config.rows) ? this.config.rows.slice() : [];\n this._id = ++SEQ;\n const table = document.createElement('table');\n table.className = 'twm-facts'\n + (this.config.compare ? ' twm-facts--compare' : '')\n + (this.config.labelColumn ? '' : ' twm-facts--no-label')\n + (this.config.wrapLabels ? ' twm-facts--wrap-labels' : '')\n + (this.config.wrap === 'words' ? ' twm-facts--wrap-words'\n : this.config.wrap === 'none' ? ' twm-facts--wrap-none' : '')\n + (this.config.mono ? ' twm-facts--mono' : '')\n + (this.config.className ? ` ${this.config.className}` : '');\n if (this.config.label) table.setAttribute('aria-label', this.config.label);\n this.element = table;\n this._draw();\n if (host) host.appendChild(table);\n }\n\n /** Replace the rows and draw them. */\n setRows(rows) {\n this._rows = Array.isArray(rows) ? rows.slice() : [];\n this._draw();\n }\n\n getRows() {\n return this._rows.slice();\n }\n\n /** The `<tr>` drawn for row `idx`, or null. */\n getRow(idx) {\n return this.element.tBodies[0]?.rows[idx]?.__factIndex === idx\n ? this.element.tBodies[0].rows[idx] : null;\n }\n\n dispose() {\n this.element.remove();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** How many columns the sheet has. */\n _width() {\n const { compare, headers } = this.config;\n if (compare) return 4;\n let n = 2;\n if (Array.isArray(headers)) n = Math.max(n, headers.length);\n for (const r of this._rows) if (Array.isArray(r)) n = Math.max(n, r.length);\n return n;\n }\n\n _draw() {\n const table = this.element;\n table.replaceChildren();\n const width = this._width();\n const { headers, compare } = this.config;\n\n if (Array.isArray(headers) && headers.length) {\n const thead = document.createElement('thead');\n const tr = document.createElement('tr');\n // With `compare`, three names stand over label, before and after;\n // the arrow column gets an empty one.\n const names = compare && headers.length === 3\n ? [headers[0], headers[1], '', headers[2]] : headers;\n for (let i = 0; i < width; i++) {\n const th = document.createElement('th');\n th.scope = 'col';\n appendContent(th, names[i] ?? '');\n if (this._numeric(i)) th.classList.add('twm-facts__num');\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n table.appendChild(thead);\n }\n\n const tbody = document.createElement('tbody');\n this._rows.forEach((row, idx) => tbody.appendChild(this._row(row, idx, width)));\n if (!this._rows.length) {\n let content = this.config.emptyState;\n if (typeof content === 'function') content = content();\n if (content != null && content !== false && content !== '') {\n const tr = document.createElement('tr');\n tr.className = 'twm-facts__empty-row';\n const td = document.createElement('td');\n td.className = 'twm-facts__empty';\n td.colSpan = width;\n appendContent(td, content);\n tr.appendChild(td);\n tbody.appendChild(tr);\n }\n }\n table.classList.toggle('twm-facts--empty', this._rows.length === 0);\n table.appendChild(tbody);\n }\n\n _numeric(col) {\n const n = this.config.numeric;\n return Array.isArray(n) && n.includes(col);\n }\n\n _row(row, idx, width) {\n const tr = document.createElement('tr');\n tr.className = 'twm-facts__row';\n tr.__factIndex = idx;\n tr.__fact = row;\n if (Array.isArray(row)) {\n for (let i = 0; i < width; i++) {\n const td = this._cell(i === 0 && this.config.labelColumn ? 'label' : 'value', row[i]);\n if (this._numeric(i)) td.classList.add('twm-facts__num');\n if (i === row.length - 1 && row.length < width) {\n td.colSpan = width - i;\n tr.appendChild(td);\n break;\n }\n tr.appendChild(td);\n }\n } else {\n const r = row && typeof row === 'object' ? row : { label: row };\n if (r.key !== undefined && r.key !== null) tr.dataset.key = String(r.key);\n const label = this._cell(this.config.labelColumn ? 'label' : 'value', r.label);\n if (r.labelTitle) label.title = String(r.labelTitle);\n tr.appendChild(label);\n const tune = (td) => {\n if (r.mono) td.classList.add('twm-facts__mono');\n if (r.numeric) td.classList.add('twm-facts__num');\n return td;\n };\n const hasBefore = Object.prototype.hasOwnProperty.call(r, 'before');\n const hasAfter = Object.prototype.hasOwnProperty.call(r, 'after');\n if (this.config.compare && (hasBefore || hasAfter)) {\n const status = r.status || statusOf(r, hasBefore, hasAfter);\n tr.classList.add(`twm-facts__row--${String(status).replace(/[^\\w-]/g, '')}`);\n tr.dataset.status = String(status);\n const before = tune(hasBefore ? this._cell('value', r.before) : this._missing());\n before.classList.add('twm-facts__before');\n const arrow = document.createElement('td');\n arrow.className = 'twm-facts__arrow';\n arrow.setAttribute('aria-hidden', 'true');\n arrow.textContent = '\u2192';\n const after = tune(hasAfter ? this._cell('value', r.after) : this._missing());\n after.classList.add('twm-facts__after');\n tr.append(before, arrow, after);\n } else {\n const value = tune(this._cell('value', r.value));\n if (width > 2) value.colSpan = width - 1;\n tr.appendChild(value);\n }\n }\n this._decorate(tr, row, idx);\n return tr;\n }\n\n _cell(kind, content) {\n const isLabel = kind === 'label';\n const td = document.createElement(isLabel ? 'th' : 'td');\n td.className = isLabel ? 'twm-facts__label' : 'twm-facts__value';\n if (isLabel) td.scope = 'row';\n if (content === null || content === undefined) {\n const said = isLabel ? '' : this.config.nullDisplay;\n if (said) {\n td.textContent = String(said);\n td.classList.add('twm-facts__null');\n }\n } else {\n appendContent(td, content);\n }\n return td;\n }\n\n _missing() {\n const td = document.createElement('td');\n td.className = 'twm-facts__value twm-facts__missing';\n td.textContent = String(this.config.missing ?? '');\n return td;\n }\n\n _decorate(tr, row, idx) {\n const { rowClass, rowAttrs } = this.config;\n if (typeof rowClass === 'function') {\n const c = rowClass(row, idx);\n const list = Array.isArray(c) ? c : String(c ?? '').split(/\\s+/);\n for (const name of list) if (name) tr.classList.add(String(name));\n }\n if (typeof rowAttrs === 'function') {\n for (const [name, value] of Object.entries(rowAttrs(row, idx) || {})) {\n if (value == null || value === false) continue;\n try {\n tr.setAttribute(name, value === true ? '' : String(value));\n } catch (err) {\n console.error(`[FactTable] rowAttrs: bad attribute \"${name}\"`, err);\n }\n }\n }\n }\n}\n\n/**\n * Build a fact sheet, append it to `host` (if given) and draw it.\n *\n * @param {HTMLElement|null} host\n * @param {FactTableConfig} [config]\n * @returns {FactTable}\n */\nexport function createFactTable(host, config = {}) {\n return new FactTable(host, config);\n}\n\n/** What a before/after row says, from its two sides. Nodes cannot be\n * compared, so a row that has one is `changed` unless it says otherwise;\n * objects compare by their JSON. */\nfunction statusOf(r, hasBefore, hasAfter) {\n if (!hasBefore) return 'added';\n if (!hasAfter) return 'removed';\n if (isNode(r.before) || isNode(r.after)) return 'changed';\n if (Object.is(r.before, r.after)) return 'same';\n if (r.before && r.after && typeof r.before === 'object' && typeof r.after === 'object') {\n try {\n return JSON.stringify(r.before) === JSON.stringify(r.after) ? 'same' : 'changed';\n } catch {\n return 'changed';\n }\n }\n return 'changed';\n}\n\n/** Text, a number, a node, or an object (drawn as indented JSON) into `el`. */\nfunction appendContent(el, content) {\n if (content === null || content === undefined) return;\n if (isNode(content)) { el.appendChild(content); return; }\n let text;\n if (typeof content === 'object') {\n try { text = JSON.stringify(content, null, 2); } catch { text = String(content); }\n } else {\n text = String(content);\n }\n el.appendChild(document.createTextNode(text));\n}\n", "/**\n * The filter expression language: recursive AND/OR/NOT groups of conditions,\n * with no idea what it is filtering. No DOM; `filter_builder.js` is the editor.\n *\n * Group = { kind: 'group', op: 'AND' | 'OR', negate?: boolean, children: [...] }\n * Clause = { kind: 'clause', field: string, op: string, value?: any }\n *\n * A node of any other kind is carried untouched and never interpreted (it is how\n * `fromConditionTree` keeps a node it cannot read). The expression is plain JSON,\n * so it round-trips through a bridge, a store and the editor as it is.\n *\n * A FIELD CATALOGUE goes in, a bound MODEL comes out:\n *\n * const model = createFilterModel({ fields: [...] });\n * model.matcherFor(expr)(row);\n * model.describeFilter(expr); // \"Status is open AND Size one of s, m\"\n *\n * A field is `{ key, label, type, get?, options?, operators?, editor?, hidden?,\n * group?, time? }`. `get` pulls the COMPARABLE value, not always the displayed\n * one, and defaults to `row[key]`. `options` may be a getter over live data; it\n * is read at use, never cached.\n */\n\n/* \u2500\u2500 operators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * `arity` is what the editor draws and what a condition needs: 0 no value, 1 one,\n * 2 a range. `multi` still has arity 1, but the value is an ARRAY. `input: 'days'`\n * marks a value that is a count of days on a date field. */\n\nconst OPERATOR_LIST = [\n { id: 'is', label: 'is', arity: 1 },\n { id: 'is_not', label: 'is not', arity: 1 },\n { id: 'contains', label: 'contains', arity: 1 },\n { id: 'not_contains', label: 'does not contain', arity: 1 },\n { id: 'starts_with', label: 'starts with', arity: 1 },\n { id: 'ends_with', label: 'ends with', arity: 1 },\n { id: 'gt', label: '>', arity: 1 },\n { id: 'lt', label: '<', arity: 1 },\n { id: 'gte', label: '>=', arity: 1 },\n { id: 'lte', label: '<=', arity: 1 },\n { id: 'between', label: 'between', arity: 2 },\n { id: 'before', label: 'before', arity: 1 },\n { id: 'after', label: 'after', arity: 1 },\n { id: 'in_last_days', label: 'in the last N days', arity: 1, input: 'days' },\n { id: 'one_of', label: 'one of', arity: 1, multi: true },\n { id: 'none_of', label: 'none of', arity: 1, multi: true },\n { id: 'all_of', label: 'all of', arity: 1, multi: true },\n { id: 'is_empty', label: 'is empty', arity: 0 },\n { id: 'is_not_empty', label: 'is not empty', arity: 0 },\n { id: 'is_null', label: 'has no value', arity: 0 },\n { id: 'is_not_null', label: 'has a value', arity: 0 },\n { id: 'is_true', label: 'is true', arity: 0 },\n { id: 'is_false', label: 'is false', arity: 0 },\n];\n\n/** Every operator FlexDesk knows, by id. */\nexport const FILTER_OPERATORS = Object.freeze(\n Object.fromEntries(OPERATOR_LIST.map((o) => [o.id, Object.freeze(o)])),\n);\n\n/** What a field of each type is offered unless its `operators` says otherwise. */\nexport const FILTER_TYPE_OPERATORS = Object.freeze({\n enum: Object.freeze(['is', 'is_not', 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n text: Object.freeze(['is', 'is_not', 'contains', 'not_contains', 'starts_with', 'ends_with',\n 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n number: Object.freeze(['is', 'is_not', 'gt', 'lt', 'gte', 'lte', 'between',\n 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n date: Object.freeze(['is', 'is_not', 'before', 'after', 'between', 'in_last_days',\n 'is_empty', 'is_not_empty']),\n set: Object.freeze(['contains', 'not_contains', 'one_of', 'none_of', 'all_of',\n 'is_empty', 'is_not_empty']),\n bool: Object.freeze(['is_true', 'is_false', 'is_empty']),\n});\n\n/* \u2500\u2500 the expression, without a model \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** A fresh, empty AND group. */\nexport const emptyFilter = () => ({ kind: 'group', op: 'AND', children: [] });\n\n/** A deep copy. The expression is JSON by contract, so this is total. */\nexport const cloneFilter = (expr) => (expr == null ? expr : JSON.parse(JSON.stringify(expr)));\n\n/** The expression as text. */\nexport const serializeFilter = (expr) => JSON.stringify(expr);\n\n/** An expression from `serializeFilter`'s text. Throws on text that is not one. */\nexport function parseFilter(text) {\n const expr = JSON.parse(text);\n if (!expr || typeof expr !== 'object' || Array.isArray(expr) || !expr.kind) {\n throw new Error('[FilterModel] not a filter expression');\n }\n return expr;\n}\n\n/** How many conditions an expression holds. A carried node counts as one. */\nexport function countConditions(node) {\n if (!node) return 0;\n if (node.kind !== 'group') return 1;\n return (node.children || []).reduce((n, child) => n + countConditions(child), 0);\n}\n\n/** A field's options as `{ value, label }`. Bare strings and `{ value | id, label }` are legal. */\nexport function filterOptions(field) {\n return (field?.options || []).map((o) => {\n if (o === null || typeof o !== 'object') return { value: o, label: String(o ?? '') };\n const value = o.value ?? o.id ?? '';\n return { value, label: String(o.label ?? value) };\n });\n}\n\n/* \u2500\u2500 the value a text box writes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** How many significant decimal digits a double holds exactly. */\nconst EXACT_DIGITS = 15;\n\nfunction significantDigits(text) {\n const [whole, fraction = ''] = text.replace(/^[+-]/, '').split('.');\n const lead = whole.replace(/^0+/, '');\n const tail = fraction.replace(/0+$/, '');\n return lead ? lead.length + tail.length : tail.replace(/^0+/, '').length;\n}\n\n/**\n * The value a control's string becomes, typed by the field's declared type, not\n * by sniffing: a number field writes a number when the string is a plain decimal\n * a double holds exactly. It declines (returns `raw`) whenever converting would\n * change the filter rather than type it: an empty box is empty and not zero, a\n * half-typed `-` stays text, and a wider decimal is not rounded. Every other\n * field type keeps the string.\n */\nexport function coerceFilterValue(field, raw) {\n if (typeof raw !== 'string' || field?.type !== 'number') return raw;\n const text = raw.trim();\n if (!/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)$/.test(text)) return raw;\n if (significantDigits(text) > EXACT_DIGITS) return raw;\n const value = Number(text);\n // Too small for a double: \"greater than zero\" is a different filter.\n if (value === 0 && /[1-9]/.test(text)) return raw;\n return value;\n}\n\n/* \u2500\u2500 value coercion for matching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Text comparisons are case-insensitive. A date degrades to a DAY number, so \"is\"\n * means \"same day\" without timezone arithmetic; a field with `time: true` compares\n * instants instead. */\n\nconst low = (v) => String(v ?? '').trim().toLowerCase();\nconst num = (v) => (v === '' || v === null || v === undefined ? NaN : Number(v));\nconst arr = (v) => (Array.isArray(v) ? v : v === '' || v === null || v === undefined ? [] : [v]);\nconst first = (v) => (Array.isArray(v) ? v[0] : v);\n\nfunction day(v) {\n const s = String(v ?? '').trim().slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return NaN;\n return Date.UTC(+s.slice(0, 4), +s.slice(5, 7) - 1, +s.slice(8, 10));\n}\nconst instant = (v) => (v === null || v === undefined || v === '' ? NaN : Date.parse(String(v)));\n\nconst todayUtc = () => {\n const d = new Date();\n return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());\n};\n\nconst isBlank = (v) => v === null || v === undefined || v === ''\n || (Array.isArray(v) && v.length === 0);\n\n/* \u2500\u2500 the condition tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * The other form an expression travels in, for a server that compiles conditions:\n *\n * { op: 'and' | 'or', children: [...] }\n * { op: 'not', children: [one] }\n * { column, operator, value? }\n *\n * docs/components/filter-builder.md has the mapping and what it preserves. */\n\nconst TO_TREE_OPERATOR = Object.freeze({\n is: 'eq',\n is_not: 'ne',\n one_of: 'in',\n none_of: 'not_in',\n is_empty: 'is_blank',\n is_not_empty: 'is_not_blank',\n before: 'lt',\n after: 'gt',\n});\n\nconst FROM_TREE_OPERATOR = Object.freeze({\n eq: 'is',\n ne: 'is_not',\n in: 'one_of',\n not_in: 'none_of',\n is_blank: 'is_empty',\n is_not_blank: 'is_not_empty',\n});\n\nconst isBareNode = (node) => node !== null && typeof node === 'object';\n\n/** An expression as a condition tree. A carried node comes back as it went in. */\nexport function toConditionTree(node) {\n if (!isBareNode(node)) return node;\n if (node.kind === 'clause') {\n const { kind: _kind, field, op, ...rest } = node;\n return { column: field, operator: TO_TREE_OPERATOR[op] ?? op, ...rest };\n }\n if (node.kind !== 'group') return node.kind === 'opaque' ? node.node : node;\n const { kind: _kind, op, negate, children, ...rest } = node;\n const list = (children || []).map(toConditionTree);\n const treeOp = String(op).toLowerCase();\n if (!negate) return { op: treeOp, children: list, ...rest };\n // `not` takes exactly one child, and a group of one needs no group around it.\n return { op: 'not', children: [list.length === 1 ? list[0] : { op: treeOp, children: list }], ...rest };\n}\n\n/**\n * A condition tree as an expression. `null` is the empty filter. A node that is\n * neither a condition, an `and`/`or` group nor a `not` of exactly one child is\n * carried as `{ kind: 'opaque', node }`: the editor shows it read-only, and\n * `toConditionTree` returns it untouched.\n */\nexport function fromConditionTree(node) {\n if (node === null || node === undefined) return emptyFilter();\n if (!isBareNode(node)) return { kind: 'opaque', node };\n const op = String(node.op ?? '').toLowerCase();\n if (!node.op && 'column' in node) {\n const { column, operator, ...rest } = node;\n const id = String(operator ?? 'eq').toLowerCase();\n return { kind: 'clause', field: column, op: FROM_TREE_OPERATOR[id] ?? id, ...rest };\n }\n if ((op === 'and' || op === 'or') && Array.isArray(node.children ?? [])) {\n const { op: _op, children, ...rest } = node;\n return { kind: 'group', op: op.toUpperCase(), children: (children || []).map(fromConditionTree), ...rest };\n }\n if (op === 'not' && Array.isArray(node.children) && node.children.length === 1) {\n const { op: _op, children, ...rest } = node;\n const inner = fromConditionTree(children[0]);\n // `not(and(a, b))` is one negated group. A one-child inner group stays a\n // group, so that the tree comes back with the level it arrived with.\n if (inner.kind === 'group' && !inner.negate && inner.children.length !== 1) {\n return { ...inner, negate: true, ...rest };\n }\n return { kind: 'group', op: 'AND', negate: true, children: [inner], ...rest };\n }\n return { kind: 'opaque', node };\n}\n\n/* \u2500\u2500 the model \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst CACHE_MAX = 200;\n\n/**\n * Bind a field catalogue into everything that needs to know about it.\n *\n * @param {object} o\n * @param {Array} o.fields the catalogue (see the top of this file)\n * @param {string} [o.noun] what one row is called, for messages\n * @param {Array} [o.operators] operators added to the catalogue, or known ones\n * relabelled: `{ id, label, arity?, multi?, input?, match? }`. An id FlexDesk\n * knows keeps what you leave out. `match(rowValue, clauseValue, row)` is what\n * `matcherFor` runs for it; without one a clause using it matches nothing.\n * @param {'everything'|'nothing'} [o.emptyOr] what an empty OR group matches. An\n * empty AND always matches everything.\n * @param {(key: string) => string} [o.unknownName] how a field key the catalogue\n * does not know is shown.\n */\nexport function createFilterModel({\n fields, noun = 'row', operators = [], emptyOr = 'everything', unknownName = (key) => key,\n}) {\n const byKey = new Map(fields.map((f) => [f.key, f]));\n const fieldByKey = (key) => byKey.get(key) || null;\n\n const catalogue = new Map(OPERATOR_LIST.map((o) => [o.id, o]));\n for (const o of operators) {\n const known = catalogue.get(o.id);\n if (!known && !Number.isInteger(o.arity)) {\n throw new Error(`[FilterModel] operator \"${o.id}\" needs an arity`);\n }\n catalogue.set(o.id, { ...known, ...o });\n }\n for (const f of fields) {\n for (const id of f.operators || []) {\n if (!catalogue.has(id)) {\n throw new Error(`[FilterModel] field \"${f.key}\" names unknown operator \"${id}\"`);\n }\n }\n }\n\n /** The operators a field is offered, as definitions. An unknown field has none. */\n const operatorsFor = (fieldKey) => {\n const field = byKey.get(fieldKey);\n if (!field) return [];\n const ids = field.operators || FILTER_TYPE_OPERATORS[field.type] || [];\n return ids.map((id) => catalogue.get(id));\n };\n /** Any operator's definition by id, offered on a field or not; null when unknown. */\n const operatorById = (id) => catalogue.get(id) || null;\n\n /** What a freshly picked (field, operator) starts from; undefined means no value. */\n function defaultValue(field, op) {\n if (!field || !op || !op.arity) return undefined;\n if (op.multi) return [];\n if (op.input === 'days') return 7;\n if (op.arity === 2) return field.type === 'number' ? [null, null] : ['', ''];\n if (field.type === 'number') return null;\n if (field.type === 'enum') return filterOptions(field)[0]?.value ?? '';\n return '';\n }\n\n /** A clause on `key` (default: the first field offered), on its first operator.\n * Null when the catalogue offers nothing. */\n function newClause(key) {\n const field = key ? byKey.get(key) : fields.find((f) => !f.hidden);\n if (!field) return null;\n const op = operatorsFor(field.key)[0] || null;\n const clause = { kind: 'clause', field: field.key, op: op ? op.id : '' };\n const value = defaultValue(field, op);\n if (value !== undefined) clause.value = value;\n return clause;\n }\n\n /* Compiled per type so a clause does its type dispatch ONCE, not on every row. */\n function compileClause(clause) {\n const field = byKey.get(clause?.field);\n if (!field) {\n console.warn('[FilterModel] clause references unknown field', clause?.field);\n return () => false;\n }\n const op = clause.op;\n const raw = clause.value;\n const get = field.get || ((row) => row?.[field.key]);\n\n const custom = catalogue.get(op)?.match;\n if (custom) return (row) => !!custom(get(row), raw, row);\n\n switch (op) {\n case 'is_empty': return (r) => isBlank(get(r));\n case 'is_not_empty': return (r) => !isBlank(get(r));\n case 'is_null': return (r) => get(r) === null || get(r) === undefined;\n case 'is_not_null': return (r) => get(r) !== null && get(r) !== undefined;\n case 'is_true': return (r) => get(r) === true || low(get(r)) === 'true';\n case 'is_false': return (r) => get(r) === false || low(get(r)) === 'false';\n default:\n }\n\n if (field.type === 'number') {\n const a = num(first(raw));\n const b = num(Array.isArray(raw) ? raw[1] : undefined);\n const list = arr(raw).map(num);\n switch (op) {\n case 'is': return (r) => num(get(r)) === a;\n case 'is_not': return (r) => num(get(r)) !== a;\n case 'gt': return (r) => num(get(r)) > a;\n case 'lt': return (r) => num(get(r)) < a;\n case 'gte': return (r) => num(get(r)) >= a;\n case 'lte': return (r) => num(get(r)) <= a;\n case 'between': return (r) => {\n const n = num(get(r));\n return n >= Math.min(a, b) && n <= Math.max(a, b);\n };\n case 'one_of': return (r) => list.includes(num(get(r)));\n case 'none_of': return (r) => !list.includes(num(get(r)));\n default:\n }\n }\n\n if (field.type === 'date') {\n const at = field.time ? instant : day;\n const a = at(first(raw));\n const b = Array.isArray(raw) ? at(raw[1]) : NaN;\n const compare = (test) => (r) => {\n const d = at(get(r));\n return !Number.isNaN(d) && test(d);\n };\n switch (op) {\n case 'is': return (r) => at(get(r)) === a;\n case 'is_not': return (r) => at(get(r)) !== a;\n case 'before': case 'lt': return compare((d) => d < a);\n case 'after': case 'gt': return compare((d) => d > a);\n case 'lte': return compare((d) => d <= a);\n case 'gte': return compare((d) => d >= a);\n case 'between': return compare((d) => d >= Math.min(a, b) && d <= Math.max(a, b));\n // Inclusive of today and of the Nth day back.\n case 'in_last_days': {\n const days = num(first(raw));\n return (r) => {\n const d = day(get(r));\n if (Number.isNaN(d) || Number.isNaN(days)) return false;\n return d >= todayUtc() - (days - 1) * 86400000 && d <= todayUtc();\n };\n }\n default:\n }\n }\n\n const one = low(first(raw));\n const many = arr(raw).map(low).filter((s) => s !== '');\n\n if (field.type === 'set') {\n const vals = (r) => arr(get(r)).map(low);\n switch (op) {\n case 'contains': return (r) => vals(r).includes(one);\n case 'not_contains': return (r) => !vals(r).includes(one);\n case 'one_of': return (r) => { const v = vals(r); return many.some((m) => v.includes(m)); };\n case 'none_of': return (r) => { const v = vals(r); return !many.some((m) => v.includes(m)); };\n case 'all_of': return (r) => { const v = vals(r); return many.every((m) => v.includes(m)); };\n default:\n }\n }\n\n // enum and text share string semantics: enum only constrains what the\n // editor offers, not how a comparison behaves.\n if (field.type === 'enum' || field.type === 'text') {\n switch (op) {\n case 'is': return (r) => low(get(r)) === one;\n case 'is_not': return (r) => low(get(r)) !== one;\n case 'contains': return (r) => low(get(r)).includes(one);\n case 'not_contains': return (r) => !low(get(r)).includes(one);\n case 'starts_with': return (r) => low(get(r)).startsWith(one);\n case 'ends_with': return (r) => low(get(r)).endsWith(one);\n case 'one_of': return (r) => many.includes(low(get(r)));\n case 'none_of': return (r) => !many.includes(low(get(r)));\n default:\n }\n }\n\n console.warn('[FilterModel] clause uses an operator its field cannot run', op, field.key);\n return () => false;\n }\n\n /** What a group with no children matches, before its NOT. */\n const emptyMatches = (group) => String(group?.op).toUpperCase() !== 'OR' || emptyOr === 'everything';\n\n function compile(node) {\n if (!node) return () => true;\n if (node.kind === 'clause') return compileClause(node);\n if (node.kind !== 'group') {\n console.warn('[FilterModel] cannot run a node of kind', node.kind);\n return () => false;\n }\n const children = (Array.isArray(node.children) ? node.children : []).map(compile);\n const negate = !!node.negate;\n if (!children.length) {\n const result = emptyMatches(node) !== negate;\n return () => result;\n }\n const test = String(node.op || 'AND').toUpperCase() === 'OR'\n ? (row) => children.some((c) => c(row))\n : (row) => children.every((c) => c(row));\n return negate ? (row) => !test(row) : test;\n }\n\n /* Cached by the expression's JSON, so a page may call this once per render or\n * per row without recompiling. Bounded: an editor changes the expression on\n * every keystroke. */\n const cache = new Map();\n function matcherFor(expr) {\n const key = JSON.stringify(expr);\n const hit = cache.get(key);\n if (hit) return hit;\n const fn = compile(expr);\n if (cache.size >= CACHE_MAX) cache.clear();\n cache.set(key, fn);\n return fn;\n }\n const evaluateFilter = (expr, row) => matcherFor(expr)(row);\n\n /* \u2500\u2500 description: \"Status is open AND (Size is s OR Size is m)\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n function describeValue(field, op, value, format) {\n if (op.arity === 0) return '';\n const shown = (v) => (format && v !== '' && v !== null && v !== undefined ? format(v, field) : String(v ?? ''));\n if (op.multi) return arr(value).map(shown).join(', ');\n if (op.arity === 2) {\n const [a, b] = arr(value);\n return `${shown(a)} and ${shown(b)}`;\n }\n return shown(first(value));\n }\n\n function describeNode(node, depth, format) {\n if (!node) return '';\n if (node.kind === 'clause') {\n const field = byKey.get(node.field);\n // A field that has gone is SAID, so a filter matching nothing reads\n // as broken, not as empty.\n if (!field) return `\u26A0 unknown field \u201C${unknownName(String(node.field ?? ''))}\u201D`;\n const op = catalogue.get(node.op);\n if (!op) return `${field.label} ${node.op ?? ''}`.trim();\n const val = describeValue(field, op, node.value, format);\n return val ? `${field.label} ${op.label} ${val}` : `${field.label} ${op.label}`;\n }\n if (node.kind !== 'group') return `\u26A0 ${JSON.stringify(node.node ?? node)}`;\n const parts = (Array.isArray(node.children) ? node.children : [])\n .map((c) => describeNode(c, depth + 1, format)).filter(Boolean);\n if (!parts.length) return emptyMatches(node) !== !!node.negate ? 'everything' : 'nothing';\n const joined = parts.join(String(node.op || 'AND').toUpperCase() === 'OR' ? ' OR ' : ' AND ');\n if (node.negate) return `NOT (${joined})`;\n return depth > 0 && parts.length > 1 ? `(${joined})` : joined;\n }\n\n /**\n * One line of words. `formatValue(value, field)` names each value (a key shown\n * as a person's name, say); without it a value is shown as itself.\n */\n const describeFilter = (expr, { formatValue = null } = {}) => describeNode(expr, 0, formatValue);\n\n /** The field keys an expression names that the catalogue does not know. */\n function unknownFields(expr) {\n const out = new Set();\n const walk = (n) => {\n if (!n) return;\n if (n.kind === 'clause') {\n if (!byKey.has(n.field)) out.add(n.field);\n } else if (n.kind === 'group') {\n (Array.isArray(n.children) ? n.children : []).forEach(walk);\n }\n };\n walk(expr);\n return [...out];\n }\n\n /* \u2500\u2500 validation: EVERY problem, not the first \u2500\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 function validateClause(node, errors, path) {\n const field = byKey.get(node.field);\n if (!field) {\n errors.push(`${path}: unknown field \"${unknownName(String(node.field ?? ''))}\"`);\n return;\n }\n const op = operatorsFor(field.key).find((o) => o.id === node.op);\n if (!op) {\n errors.push(`${field.label}: \"${node.op}\" is not a valid operator`);\n return;\n }\n if (op.arity === 0) return;\n const say = (what) => errors.push(`${field.label} ${op.label}: ${what}`);\n if (op.multi) {\n if (!Array.isArray(node.value) || node.value.length === 0) say('pick at least one value');\n return;\n }\n const values = op.arity === 2 ? arr(node.value).slice(0, 2) : [first(node.value)];\n const needed = op.arity === 2 ? 2 : 1;\n if (values.length < needed || values.some(isBlank)) {\n say(needed === 2 ? 'needs two values' : 'needs a value');\n return;\n }\n if (op.input === 'days') {\n if (!(num(values[0]) > 0)) say('value must be a positive number of days');\n } else if (field.type === 'number') {\n if (values.some((v) => Number.isNaN(num(v)))) say('value must be a number');\n } else if (field.type === 'date') {\n const at = field.time ? instant : day;\n if (values.some((v) => Number.isNaN(at(v)))) {\n say(field.time ? 'value must be a date and time' : 'value must be a date (YYYY-MM-DD)');\n }\n }\n }\n\n function validateNode(node, errors, path) {\n if (!node || typeof node !== 'object') {\n errors.push(`${path}: not an expression node`);\n } else if (node.kind === 'group') {\n if (node.op !== 'AND' && node.op !== 'OR') errors.push(`${path}: group op must be AND or OR`);\n if (!Array.isArray(node.children)) {\n errors.push(`${path}: group children must be an array`);\n return;\n }\n node.children.forEach((c, i) => validateNode(c, errors, `${path}/${i}`));\n } else if (node.kind === 'clause') {\n validateClause(node, errors, path);\n } else {\n errors.push(`${path}: unknown node kind \"${node.kind}\"`);\n }\n }\n\n /** `{ ok, errors }`. An empty group is valid. */\n function validateFilter(expr) {\n const errors = [];\n validateNode(expr, errors, 'expr');\n return { ok: errors.length === 0, errors };\n }\n\n /* \u2500\u2500 prune: what is left once half-built rows are dropped \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n function prune(node) {\n if (!node || typeof node !== 'object') return null;\n if (node.kind === 'clause') {\n const op = catalogue.get(node.op);\n if (!op || !byKey.has(node.field) || op.arity === 0) return node;\n const blank = Array.isArray(node.value) ? node.value.every(isBlank) : isBlank(node.value);\n return blank ? null : node;\n }\n if (node.kind !== 'group') return node;\n const children = (node.children || []).map(prune).filter(Boolean);\n if (!children.length) return null;\n // A group of one group is the same predicate with a level nobody asked\n // for, so a round trip does not grow a layer each time.\n if (children.length === 1 && children[0].kind === 'group' && !node.negate) return children[0];\n return { ...node, children };\n }\n\n /**\n * A copy with empty groups and conditions with nothing to compare against\n * dropped, or null when nothing is left. A condition this catalogue cannot\n * read, and a carried node, are kept: they were not built here.\n */\n const pruneFilter = (expr) => prune(cloneFilter(expr));\n\n return Object.freeze({\n fields, noun, fieldByKey, operatorsFor, operatorById, defaultValue, newClause, emptyMatches,\n unknownName, matcherFor, evaluateFilter, describeFilter, validateFilter, unknownFields, pruneFilter,\n });\n}\n", "/**\n * tag_input.js \u2014 A LIST OF SHORT STRINGS, drawn as removable chips followed by\n * a text box. (0.17.0)\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [baseline \u00D7] [stress \u00D7] [q3 \u00D7] Add a tag\u2026 \u2502\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n *\n * The text box commits what was typed \u2014 trimmed, split at commas \u2014 on Enter,\n * on a comma and when it loses focus. Empty pieces are dropped, and so is a\n * piece already in the list unless `allowDuplicates`. Backspace in an empty\n * box removes the last chip. A paste that carries a comma is split into\n * chips at once; a paste without one is ordinary text in the box.\n *\n * Every chip has a remove button with an `aria-label` (`removeLabel(tag)`,\n * \"Remove <tag>\" by default). `readOnly` draws the chips alone: no remove\n * buttons and no text box.\n *\n * `onChange(list)` is called with a fresh copy of the list after every change\n * the reader makes \u2014 never for `setValue`, and never for a commit that added\n * nothing.\n *\n * const tags = createTagInput(host, {\n * value: ['baseline'],\n * placeholder: 'Add a tag\u2026',\n * onChange: (list) => save(list),\n * });\n * tags.getValue(); // ['baseline']\n * tags.setValue(['a', 'b']);\n * tags.dispose();\n *\n * `suggestions` (0.18.0) offers known tags under the box, on `attachInputOptions`:\n * the arrow keys walk the rows, and Enter or a comma takes the active one; with none\n * active they commit what was typed. Whatever the list's source, a row is in the one\n * spelling, says a tag once and is not a tag already in the list. An array is filtered\n * and ordered here, the earliest match first and then alphabetically; a function\n * answers for itself and keeps its own order, and may be async.\n * `normalise` (0.18.0) keeps one spelling of a tag: `Path Finding` and `path-finding`\n * cannot both exist, whichever way one arrives. It is handed the trimmed text.\n */\nimport { attachInputOptions } from './combobox.js';\nimport { shownValue } from './choice_controls.js';\n\nconst optionValue = (o) => (o !== null && typeof o === 'object' ? o.value : o);\n\n/**\n * @typedef {Object} TagInputOptions\n * @property {string[]} [value] - The tags it opens with.\n * @property {string} [placeholder] - The empty text box's placeholder.\n * @property {boolean} [readOnly] - Chips only: no remove buttons, no text box.\n * @property {boolean} [allowDuplicates] - Keep a tag that is already in the list.\n * @property {(list: string[]) => void} [onChange] - After each change the reader makes.\n * @property {string} [label] - The text box's accessible name.\n * @property {(tag: string) => string} [removeLabel] - A remove button's `aria-label`.\n * @property {string} [className] - Extra classes on the root.\n * @property {Array|((query: string, ctx: {signal: AbortSignal}) => Array|Promise<Array>)} [suggestions] -\n * Known tags: strings or `{ value, label?, description?, icon?, hint? }`.\n * @property {(text: string) => string} [normalise] - The one spelling of a tag.\n */\n\n/**\n * @param {HTMLElement} host\n * @param {TagInputOptions} [options]\n */\nexport function createTagInput(host, options = {}) {\n if (!host || typeof host.appendChild !== 'function') {\n throw new Error('[TagInput] host must be an HTMLElement');\n }\n const readOnly = !!options.readOnly;\n const allowDuplicates = !!options.allowDuplicates;\n const removeLabel = typeof options.removeLabel === 'function'\n ? options.removeLabel : (tag) => `Remove ${tag}`;\n const spell = typeof options.normalise === 'function'\n ? (text) => String(options.normalise(text.trim()) ?? '').trim() : (text) => text.trim();\n\n /** The list as spelled, the empty ones left out, and a repeat unless it is allowed. */\n const cleaned = (list) => {\n const out = (Array.isArray(list) ? list : []).map((v) => (v == null ? '' : spell(String(v)))).filter((v) => v !== '');\n return allowDuplicates ? out : [...new Set(out)];\n };\n\n let tags = cleaned(options.value);\n let disposed = false;\n\n const root = document.createElement('div');\n root.className = ['twm-tag-input', readOnly ? 'twm-tag-input--readonly' : '', options.className || '']\n .join(' ').replace(/\\s+/g, ' ').trim();\n root.setAttribute('role', 'group');\n if (options.label) root.setAttribute('aria-label', options.label);\n\n const chips = document.createElement('ul');\n chips.className = 'twm-tag-input__chips';\n root.appendChild(chips);\n\n let input = null;\n if (!readOnly) {\n input = document.createElement('input');\n input.type = 'text';\n input.className = 'twm-tag-input__input';\n input.spellcheck = false;\n input.autocomplete = 'off';\n if (options.placeholder) input.placeholder = options.placeholder;\n if (options.label) input.setAttribute('aria-label', options.label);\n root.appendChild(input);\n }\n\n const changed = () => {\n if (typeof options.onChange === 'function') options.onChange([...tags]);\n };\n\n const chipFor = (tag, idx) => {\n const chip = document.createElement('li');\n chip.className = 'twm-tag-input__chip';\n const text = document.createElement('span');\n text.className = 'twm-tag-input__text';\n text.textContent = tag;\n text.title = tag;\n chip.appendChild(text);\n if (!readOnly) {\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'twm-tag-input__remove';\n remove.setAttribute('aria-label', removeLabel(tag));\n remove.textContent = '\u00D7';\n // The text box keeps the focus: a blur would commit its text\n // and redraw the chips under the pointer before the click.\n remove.addEventListener('mousedown', (ev) => ev.preventDefault());\n remove.addEventListener('click', (ev) => {\n ev.preventDefault();\n ev.stopPropagation();\n removeAt(idx);\n input?.focus();\n });\n chip.appendChild(remove);\n }\n return chip;\n };\n\n /** Redraws every chip. */\n const paint = () => {\n chips.replaceChildren(...tags.map(chipFor));\n };\n\n function removeAt(idx) {\n if (disposed || readOnly || idx < 0 || idx >= tags.length) return;\n tags = tags.filter((_, i) => i !== idx);\n paint();\n changed();\n }\n\n /** Adds the comma-separated pieces of `text`; true when any was added. */\n const commitText = (text) => {\n if (disposed || readOnly) return false;\n const next = [...tags];\n for (const piece of String(text).split(',')) {\n const tag = spell(piece);\n if (tag === '') continue;\n if (!allowDuplicates && next.includes(tag)) continue;\n next.push(tag);\n }\n if (next.length === tags.length) return false;\n // Only the new chips are drawn: the ones already there stay in place,\n // so a remove button that the focus is moving to (Tab out of the box\n // commits its text) is still in the document when the focus lands.\n const added = next.slice(tags.length).map((tag, i) => chipFor(tag, tags.length + i));\n tags = next;\n chips.append(...added);\n changed();\n return true;\n };\n\n /** Known tags as rows: in the one spelling, each once, less those already in the list. */\n const offered = (list) => {\n const seen = new Set();\n const rows = [];\n for (const o of list || []) {\n const tag = spell(shownValue(optionValue(o)));\n if (tag === '' || seen.has(tag) || (!allowDuplicates && tags.includes(tag))) continue;\n seen.add(tag);\n rows.push(o !== null && typeof o === 'object' ? { ...o, value: tag } : tag);\n }\n return rows;\n };\n // What is typed is the query however the list opened: an arrow key or a click\n // reopening it must not offer rows that have nothing to do with the text in the box.\n /** An array of known tags: those holding what is typed, the earliest match first, then alphabetically. */\n const rankedFor = () => {\n const needle = spell(input.value).toLowerCase();\n const word = (o) => shownValue(optionValue(o));\n const at = (o) => word(o).toLowerCase().indexOf(needle);\n return offered(options.suggestions).filter((o) => at(o) >= 0)\n .sort((x, y) => at(x) - at(y) || word(x).localeCompare(word(y)));\n };\n /** A function's answer, whenever it comes. */\n const askedFor = (_query, ctx) => {\n const answer = options.suggestions(input.value, ctx);\n return typeof answer?.then === 'function' ? answer.then(offered) : offered(answer);\n };\n const asking = typeof options.suggestions === 'function';\n\n // Before the box's own keydown listener: a row taken by Enter is not also a commit.\n const menu = input && options.suggestions\n ? attachInputOptions(input, {\n options: asking ? askedFor : rankedFor,\n anchor: root,\n normalise: spell,\n openOnFocus: true,\n passEnter: true,\n debounce: asking ? undefined : 0,\n onPick(option) {\n input.value = '';\n commitText(shownValue(option.value));\n input.focus();\n },\n })\n : null;\n\n const commitInput = () => {\n if (!input) return;\n const text = input.value;\n input.value = '';\n menu?.close();\n commitText(text);\n };\n\n if (input) {\n input.addEventListener('keydown', (ev) => {\n if (ev.isComposing) return;\n if (ev.key === ',' && menu?.takeActive()) {\n ev.preventDefault();\n } else if (ev.key === 'Enter' || ev.key === ',') {\n ev.preventDefault();\n commitInput();\n } else if (ev.key === 'Backspace' && input.value === '' && tags.length) {\n ev.preventDefault();\n removeAt(tags.length - 1);\n }\n });\n // A comma that arrives without its keydown (a soft keyboard, an IME,\n // a drop) commits all the same.\n input.addEventListener('input', () => {\n if (input.value.includes(',')) commitInput();\n });\n input.addEventListener('blur', commitInput);\n input.addEventListener('paste', (ev) => {\n const pasted = ev.clipboardData?.getData('text/plain') ?? '';\n if (!pasted.includes(',')) return;\n ev.preventDefault();\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? start;\n const text = input.value.slice(0, start) + pasted + input.value.slice(end);\n input.value = '';\n commitText(text);\n });\n root.addEventListener('mousedown', (ev) => {\n if (ev.target === root || ev.target === chips) {\n ev.preventDefault();\n input.focus();\n }\n });\n }\n\n paint();\n host.appendChild(root);\n\n return {\n element: root,\n input,\n getValue: () => [...tags],\n /** Replaces the list. Does not call `onChange`. */\n setValue(list) {\n if (disposed) return;\n tags = cleaned(list);\n paint();\n },\n focus() { input?.focus(); },\n dispose() {\n if (disposed) return;\n disposed = true;\n menu?.destroy();\n root.remove();\n },\n };\n}\n", "/**\n * The filter editor: `createFilterBuilder`, mountable anywhere, and\n * `openFilterDialog`, the same builder in a modal with a name, an icon, a\n * consumer's live preview and an async submit.\n *\n * It never decides what a filter MEANS. That is the bound model's\n * (`filter_model.js`); this file only edits the expression and asks the model.\n *\n * Every row closes over the node it edits, so nothing about the expression is\n * kept in the DOM. A STRUCTURAL change (add, remove, field, operator, AND/OR, NOT)\n * redraws the tree and puts the focus back; typing in a value control writes to\n * the node and redraws nothing, so the caret survives.\n *\n * WHAT IT DOES NOT REWRITE. A condition on a field the catalogue does not know, an\n * operator it does not know and a node it cannot read stay exactly as they are\n * until someone changes or removes them: the selects show them as their own marked\n * entry and the value is read-only.\n */\n\nimport { cloneFilter, coerceFilterValue, emptyFilter, filterOptions } from './filter_model.js';\nimport { selectBox } from './choice_controls.js';\nimport { createTagInput } from './tag_input.js';\nimport { openConfirm, openModal } from './modal.js';\n\nconst PREVIEW_DEBOUNCE_MS = 120;\n/** The icon grid's columns; `.twm-filter-dialog__icon-grid` draws the same number. */\nconst ICON_COLUMNS = 8;\nconst SUBMIT = 'submit';\nconst CLEAR = 'clear';\n\nfunction el(tag, className, text) {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text !== undefined && text !== null) node.textContent = String(text);\n return node;\n}\n\nfunction button(className, text, onClick, { title, label } = {}) {\n const node = el('button', className, text);\n node.type = 'button';\n if (title) node.title = title;\n if (label) node.setAttribute('aria-label', label);\n node.addEventListener('click', onClick);\n return node;\n}\n\nconst SELECT_CLASS = 'twm-filter-builder__input twm-filter-builder__select';\nconst INPUT_CLASS = 'twm-filter-builder__input';\nconst SMALL_BUTTON = 'twm-btn twm-filter-builder__add';\nconst REMOVE_BUTTON = 'twm-btn-icon twm-filter-builder__remove';\n\n/** The root is always a group: an expression may legitimately be a bare clause. */\nfunction asRoot(expr) {\n if (!expr || typeof expr !== 'object') return emptyFilter();\n const copy = cloneFilter(expr);\n return copy.kind === 'group' ? copy : { kind: 'group', op: 'AND', children: [copy] };\n}\n\n/**\n * Mount a filter builder.\n *\n * @param {HTMLElement} host\n * @param {object} options\n * @param {object} options.model from `createFilterModel`\n * @param {object} [options.value] the expression to edit (copied)\n * @param {(expr: object) => void} [options.onChange] a copy, after each change\n * @returns {{ el: HTMLElement, getValue(): object, setValue(expr: object): void,\n * validate(): {ok: boolean, errors: string[]}, focus(): void, destroy(): void }}\n */\nexport function createFilterBuilder(host, { model, value = null, onChange = null } = {}) {\n if (!model) throw new Error('[FilterBuilder] needs a filter model');\n const rootEl = el('div', 'twm-filter-builder');\n let root = asRoot(value);\n /** Node to its parent group, for removal; rebuilt by each redraw. */\n let parents = new WeakMap();\n /** Node to its focusable controls by role; rebuilt by each redraw. */\n let controls = new WeakMap();\n /** Each value cell's disposer: a redraw releases what the cells mounted. */\n const cells = new Set();\n\n const changed = () => onChange?.(cloneFilter(root));\n\n const register = (node, role, control) => {\n if (!controls.has(node)) controls.set(node, {});\n controls.get(node)[role] = control;\n };\n\n function redraw(focusNode = null, focusRole = null) {\n for (const cell of cells) cell.dispose();\n cells.clear();\n parents = new WeakMap();\n controls = new WeakMap();\n rootEl.replaceChildren(groupEl(root, true));\n if (focusNode) controls.get(focusNode)?.[focusRole]?.focus();\n }\n\n /** A structural edit: the expression changed shape, so the tree is redrawn. */\n function restructure(focusNode, focusRole) {\n redraw(focusNode, focusRole);\n changed();\n }\n\n /** Remove `node`, and any nested group that leaves empty. Returns the group that remains. */\n function removeNode(node) {\n let gone = node;\n for (;;) {\n const parent = parents.get(gone);\n parent.children.splice(parent.children.indexOf(gone), 1);\n if (parent.children.length || !parents.has(parent)) return parent;\n gone = parent;\n }\n }\n\n const removeButton = (node, label) => button(REMOVE_BUTTON, '\u00D7', () => {\n restructure(removeNode(node), 'addClause');\n }, { title: label, label });\n\n function groupEl(group, isRoot) {\n if (!Array.isArray(group.children)) group.children = [];\n const box = el('div', `twm-filter-builder__group${isRoot ? ' twm-filter-builder__group--root' : ''}`);\n const noun = model.noun;\n\n const head = el('div', 'twm-filter-builder__group-head');\n const seg = el('div', 'twm-filter-builder__seg');\n seg.setAttribute('role', 'group');\n seg.setAttribute('aria-label', 'Match mode');\n for (const op of ['AND', 'OR']) {\n const on = group.op === op;\n const toggle = button(`twm-filter-builder__seg-btn${on ? ' twm-filter-builder__seg-btn--on' : ''}`, op, () => {\n if (group.op === op) return;\n group.op = op;\n restructure(group, op);\n });\n toggle.setAttribute('aria-pressed', String(on));\n register(group, op, toggle);\n seg.appendChild(toggle);\n }\n const not = button(`twm-filter-builder__not${group.negate ? ' twm-filter-builder__not--on' : ''}`, 'NOT', () => {\n if (group.negate) delete group.negate;\n else group.negate = true;\n restructure(group, 'not');\n }, { title: 'Invert this group' });\n not.setAttribute('aria-pressed', String(!!group.negate));\n register(group, 'not', not);\n head.append(seg, not, el('span', 'twm-filter-builder__hint',\n group.op === 'OR' ? 'any condition matches' : 'all conditions match'));\n if (!isRoot) head.appendChild(removeButton(group, 'Remove group'));\n box.appendChild(head);\n\n const children = el('div', 'twm-filter-builder__children');\n for (const child of group.children) {\n parents.set(child, group);\n if (child?.kind === 'group') children.appendChild(groupEl(child, false));\n else if (child?.kind === 'clause') children.appendChild(clauseEl(child));\n else children.appendChild(carriedEl(child));\n }\n if (!group.children.length) {\n const matches = model.emptyMatches(group) !== !!group.negate;\n children.appendChild(el('div', 'twm-filter-builder__empty', matches\n ? `No conditions: this group matches every ${noun}.`\n : `No conditions: this group matches no ${noun}.`));\n }\n box.appendChild(children);\n\n const foot = el('div', 'twm-filter-builder__group-foot');\n const add = (factory, focusRole) => {\n const node = factory();\n if (!node) return;\n group.children.push(node);\n restructure(node, focusRole);\n };\n const offerable = !!model.newClause();\n const addClause = button(SMALL_BUTTON, '+ Condition', () => add(() => model.newClause(), 'field'));\n addClause.disabled = !offerable;\n register(group, 'addClause', addClause);\n // Seeded with one condition: an empty group matches everything, which\n // reads as a mistake the moment it appears.\n const addGroup = button(SMALL_BUTTON, '+ Group', () => add(\n () => ({ kind: 'group', op: 'AND', children: [model.newClause()] }), 'addClause',\n ));\n addGroup.disabled = !offerable;\n foot.append(addClause, addGroup);\n box.appendChild(foot);\n return box;\n }\n\n /** A node the model cannot read: shown as it is and kept as it is. */\n function carriedEl(node) {\n const row = el('div', 'twm-filter-builder__row twm-filter-builder__row--carried');\n const text = el('span', 'twm-filter-builder__carried', model.describeFilter(node));\n text.title = 'This editor cannot draw this condition. It is kept exactly as it is; remove it to drop it.';\n row.append(text, removeButton(node, 'Remove condition'));\n return row;\n }\n\n function fieldChoices(current) {\n const list = [];\n const groups = new Map();\n for (const field of model.fields) {\n if (field.hidden && field.key !== current) continue;\n const option = { value: field.key, label: field.label };\n if (!field.group) {\n list.push(option);\n } else if (groups.has(field.group)) {\n groups.get(field.group).options.push(option);\n } else {\n const entry = { group: field.group, options: [option] };\n groups.set(field.group, entry);\n list.push(entry);\n }\n }\n return list;\n }\n\n function operatorChoices(clause) {\n const offered = model.operatorsFor(clause.field);\n const held = model.operatorById(clause.op);\n const list = held && model.fieldByKey(clause.field) && !offered.includes(held)\n ? [...offered, held] : offered;\n return list.map((op) => ({ value: op.id, label: op.label }));\n }\n\n function clauseEl(clause) {\n const row = el('div', 'twm-filter-builder__row');\n\n const fieldSelect = selectBox(fieldChoices(clause.field), clause.field, {\n label: 'Field',\n className: `${SELECT_CLASS} twm-filter-builder__select--field`,\n notFound: () => `\u26A0 unknown field \u201C${model.unknownName(String(clause.field ?? ''))}\u201D`,\n });\n fieldSelect.box.addEventListener('change', () => {\n const next = model.newClause(fieldSelect.valueOf());\n for (const key of ['op', 'value']) delete clause[key];\n Object.assign(clause, next);\n restructure(clause, 'field');\n });\n register(clause, 'field', fieldSelect.box);\n\n const opSelect = selectBox(operatorChoices(clause), clause.op, {\n label: 'Operator',\n className: `${SELECT_CLASS} twm-filter-builder__select--op`,\n notFound: (id) => `${id} (unknown)`,\n });\n opSelect.box.addEventListener('change', () => {\n clause.op = opSelect.valueOf();\n const fresh = model.defaultValue(model.fieldByKey(clause.field), model.operatorById(clause.op));\n if (fresh === undefined) delete clause.value;\n else clause.value = fresh;\n restructure(clause, 'op');\n });\n register(clause, 'op', opSelect.box);\n\n const cellEl = el('div', 'twm-filter-builder__value');\n const cell = { dispose() {} };\n cells.add(cell);\n const drawCell = (focus = false) => {\n cell.dispose();\n cell.dispose = () => {};\n cellEl.replaceChildren();\n drawValue(clause, cellEl, cell, drawCell);\n if (focus) cellEl.querySelector('select, input')?.focus();\n };\n drawCell();\n\n row.append(fieldSelect.box, opSelect.box, cellEl, removeButton(clause, 'Remove condition'));\n return row;\n }\n\n function drawValue(clause, cellEl, cell, drawCell) {\n const field = model.fieldByKey(clause.field);\n const op = model.operatorById(clause.op);\n if (!field || !op) {\n if (clause.value !== undefined) {\n cellEl.appendChild(el('span', 'twm-filter-builder__carried', JSON.stringify(clause.value)));\n }\n return;\n }\n if (!op.arity) return;\n\n const write = (next) => {\n clause.value = next;\n changed();\n };\n const custom = field.editor?.({ field, op, value: clause.value, label: field.label, onChange: write });\n if (custom) {\n cellEl.appendChild(custom.el);\n cell.dispose = () => custom.destroy?.();\n return;\n }\n\n if (op.multi) {\n if (filterOptions(field).length) drawChosenOptions(clause, field, cellEl, drawCell, write);\n else drawTags(clause, field, cellEl, cell, write);\n return;\n }\n if (op.arity === 2) {\n const pair = Array.isArray(clause.value) ? [...clause.value] : ['', ''];\n const box = (i) => scalarInput(field, op, pair[i], (v) => {\n pair[i] = v;\n write([...pair]);\n });\n cellEl.append(box(0), el('span', 'twm-filter-builder__and', 'and'), box(1));\n return;\n }\n const options = field.type === 'enum' ? filterOptions(field) : [];\n if (options.length) {\n const choice = selectBox(options, clause.value, {\n label: field.label,\n className: `${SELECT_CLASS} twm-filter-builder__select--value`,\n notFound: (v) => `${v} (unknown)`,\n });\n // A select cannot show \"nothing\": what it holds is the honest value.\n if (clause.value === undefined || clause.value === null || clause.value === '') {\n clause.value = choice.valueOf();\n }\n choice.box.addEventListener('change', () => write(choice.valueOf()));\n cellEl.appendChild(choice.box);\n return;\n }\n cellEl.appendChild(scalarInput(field, op, Array.isArray(clause.value) ? clause.value[0] : clause.value, write));\n if (op.input === 'days') cellEl.appendChild(el('span', 'twm-filter-builder__and', 'days'));\n }\n\n function scalarInput(field, op, current, write) {\n const input = el('input', INPUT_CLASS);\n const numeric = field.type === 'number' || op.input === 'days';\n if (numeric) {\n input.type = 'number';\n input.step = 'any';\n } else if (field.type === 'date') {\n input.type = field.time ? 'datetime-local' : 'date';\n } else {\n input.type = 'text';\n input.placeholder = 'value\u2026';\n }\n input.setAttribute('aria-label', field.label);\n input.value = current ?? '';\n const type = numeric ? { type: 'number' } : field;\n input.addEventListener('input', () => write(coerceFilterValue(type, input.value)));\n return input;\n }\n\n function asList(value) {\n if (Array.isArray(value)) return value;\n return value === '' || value === null || value === undefined ? [] : [value];\n }\n\n /** Free values, as tags. */\n function drawTags(clause, field, cellEl, cell, write) {\n const tags = createTagInput(cellEl, {\n value: asList(clause.value).map(String),\n placeholder: 'value\u2026',\n label: field.label,\n className: 'twm-filter-builder__tags',\n onChange: (list) => write(list.map((v) => coerceFilterValue(field, v))),\n });\n cell.dispose = () => tags.dispose();\n }\n\n /** Values from a fixed list: the chosen as chips, and a select of what is left. */\n function drawChosenOptions(clause, field, cellEl, drawCell, write) {\n const options = filterOptions(field);\n const chosen = asList(clause.value);\n const labelOf = (v) => options.find((o) => o.value === v)?.label ?? String(v);\n const box = el('div', 'twm-filter-builder__chosen');\n chosen.forEach((v, i) => {\n const chip = el('span', 'twm-filter-builder__chip', labelOf(v));\n chip.appendChild(button('twm-filter-builder__chip-remove', '\u00D7', () => {\n write(chosen.filter((_, at) => at !== i));\n drawCell(true);\n }, { label: `Remove ${labelOf(v)}` }));\n box.appendChild(chip);\n });\n const rest = options.filter((o) => !chosen.includes(o.value));\n if (rest.length) {\n const adder = selectBox(rest, undefined, {\n empty: '+ value',\n keepMissing: false,\n label: `Add a value to ${field.label}`,\n className: `${SELECT_CLASS} twm-filter-builder__select--add`,\n });\n adder.box.addEventListener('change', () => {\n const next = adder.valueOf();\n if (next === undefined) return;\n write([...chosen, next]);\n drawCell(true);\n });\n box.appendChild(adder.box);\n }\n cellEl.appendChild(box);\n }\n\n redraw();\n host.appendChild(rootEl);\n\n return {\n el: rootEl,\n getValue: () => cloneFilter(root),\n /** Replaces the expression. Does not call `onChange`. */\n setValue(expr) {\n root = asRoot(expr);\n redraw();\n },\n validate: () => model.validateFilter(root),\n focus() { rootEl.querySelector('select, input, button')?.focus(); },\n destroy() {\n for (const cell of cells) cell.dispose();\n cells.clear();\n rootEl.remove();\n },\n };\n}\n\n/** The dialog's icon choice: a button over a searchable grid. */\nfunction createIconPicker({ value, options, onChange }) {\n let current = value;\n const root = el('div', 'twm-filter-dialog__icon');\n const glyph = (name) => el('span', 'material-symbols-outlined', name);\n const trigger = button('twm-btn twm-filter-dialog__icon-trigger', null, () => (pop.hidden ? open() : close()), {\n title: 'Icon', label: 'Icon',\n });\n trigger.setAttribute('aria-haspopup', 'listbox');\n trigger.setAttribute('aria-expanded', 'false');\n const face = glyph(current);\n trigger.appendChild(face);\n\n const pop = el('div', 'twm-filter-dialog__icon-pop');\n pop.hidden = true;\n const search = el('input', `${INPUT_CLASS} twm-filter-dialog__icon-search`);\n search.type = 'text';\n search.placeholder = 'Search icons\u2026';\n search.setAttribute('aria-label', 'Search icons');\n const grid = el('div', 'twm-filter-dialog__icon-grid');\n grid.setAttribute('role', 'listbox');\n grid.setAttribute('aria-label', 'Icon');\n const none = el('div', 'twm-filter-dialog__icon-none', 'No icon matches.');\n pop.append(search, grid, none);\n root.append(trigger, pop);\n\n const pick = (name) => {\n current = name;\n face.textContent = name;\n close();\n onChange(name);\n };\n const drawGrid = () => {\n const query = search.value.trim().toLowerCase();\n const list = query ? options.filter((n) => n.toLowerCase().includes(query)) : options;\n none.hidden = list.length > 0;\n grid.replaceChildren(...list.map((name) => {\n const on = name === current;\n const option = button(`twm-filter-dialog__icon-option${on ? ' twm-filter-dialog__icon-option--on' : ''}`,\n null, () => pick(name), { title: name });\n option.setAttribute('role', 'option');\n option.setAttribute('aria-selected', String(on));\n option.appendChild(glyph(name));\n return option;\n }));\n };\n function open() {\n search.value = '';\n drawGrid();\n pop.hidden = false;\n trigger.setAttribute('aria-expanded', 'true');\n search.focus();\n }\n function close(refocus = true) {\n if (pop.hidden) return;\n pop.hidden = true;\n trigger.setAttribute('aria-expanded', 'false');\n if (refocus) trigger.focus();\n }\n\n search.addEventListener('input', drawGrid);\n search.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n grid.firstElementChild?.focus();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n grid.firstElementChild?.click();\n }\n });\n grid.addEventListener('keydown', (e) => {\n const items = [...grid.children];\n const at = items.indexOf(e.target.closest('button'));\n if (at < 0) return;\n const step = { ArrowRight: 1, ArrowLeft: -1, ArrowDown: ICON_COLUMNS, ArrowUp: -ICON_COLUMNS }[e.key];\n if (step === undefined) return;\n e.preventDefault();\n if (at + step < 0 && e.key === 'ArrowUp') search.focus();\n else items[at + step]?.focus();\n });\n // The window answers an Esc nobody else has: this one closes only the grid.\n pop.addEventListener('keydown', (e) => {\n if (e.key !== 'Escape') return;\n e.preventDefault();\n close();\n });\n\n return { el: root, close, value: () => current };\n}\n\n/**\n * Open the builder in a modal.\n *\n * @param {object} options\n * @param {object} options.model from `createFilterModel`\n * @param {object} [options.value] the expression to edit (copied; Cancel is lossless)\n * @param {string} [options.seedField] a field key: a new empty condition on it is\n * added, so \"filter by this\" lands on a form about that field\n * @param {string} [options.title]\n * @param {string} [options.icon] the window's icon\n * @param {HTMLElement} [options.head] drawn above the conditions\n * @param {{value?: string, label?: string, placeholder?: string, required?: boolean}} [options.name]\n * adds a name box; the result carries `name`\n * @param {{value?: string, options: string[]}} [options.iconChoice]\n * adds an icon picker over those Material Symbols names; the result carries `icon`\n * @param {(host: HTMLElement, state: {expr: object, sentence: string, signal: AbortSignal}) => void} [options.preview]\n * the live preview: draws into `host` on open and, debounced, after each change\n * while the expression can be submitted. `signal` aborts when this drawing is\n * superseded or the dialog closes, for a preview that asks a server.\n * @param {boolean} [options.requireValid] submit only a valid expression (default\n * true); its errors are listed. False lets one with an unknown field through.\n * @param {boolean} [options.prune] drop half-built rows from what is validated,\n * previewed and submitted (`model.pruneFilter`); `expr` is null when nothing is left\n * @param {boolean} [options.confirmDiscard] ask before closing with unsaved changes\n * @param {string} [options.submitLabel]\n * @param {(result: object) => any} [options.onSubmit] may be async: until it settles\n * every button is off and Esc and the X do nothing, so the answer is what happened.\n * If it throws, the dialog shows the error and stays.\n * @param {string} [options.clearLabel] adds a button answering `{ action: 'clear', expr: null }`\n * @param {Array<{label: string, value: string, danger?: boolean, icon?: string,\n * confirm?: object, run?: (result: object) => any}>} [options.actions]\n * more buttons, before Cancel. `confirm` is `openConfirm`'s options, asked first;\n * `run` is like `onSubmit`.\n * @param {number} [options.width]\n * @param {number} [options.height]\n * @returns {Promise<{action: string, expr: object|null, name?: string, icon?: string}|null>}\n * null when dismissed\n */\nexport async function openFilterDialog({\n model, value = null, seedField = null, title = 'Filter', icon = 'filter_alt', head = null,\n name = null, iconChoice = null, preview = null,\n requireValid = true, prune = false, confirmDiscard = false,\n submitLabel = 'Apply', onSubmit = null, clearLabel = null, actions = [],\n width = preview ? 920 : 760, height = 560,\n} = {}) {\n if (!model) throw new Error('[FilterDialog] needs a filter model');\n\n const start = asRoot(value);\n if (seedField) {\n const seeded = model.newClause(seedField);\n if (seeded) start.children.push(seeded);\n }\n\n const content = el('div', 'twm-filter-dialog');\n if (head) content.appendChild(head);\n\n let picker = null;\n let nameInput = null;\n if (name || iconChoice) {\n const row = el('div', 'twm-filter-dialog__identity');\n if (name) {\n const label = el('label', 'twm-filter-dialog__name');\n label.appendChild(el('span', 'twm-filter-dialog__name-label', name.label ?? 'Name'));\n nameInput = el('input', INPUT_CLASS);\n nameInput.type = 'text';\n nameInput.autocomplete = 'off';\n nameInput.value = name.value ?? '';\n if (name.placeholder) nameInput.placeholder = name.placeholder;\n nameInput.addEventListener('input', refresh);\n label.appendChild(nameInput);\n row.appendChild(label);\n }\n if (iconChoice) {\n picker = createIconPicker({\n value: iconChoice.value ?? iconChoice.options[0],\n options: iconChoice.options,\n onChange: refresh,\n });\n row.appendChild(picker.el);\n content.addEventListener('mousedown', (e) => {\n if (!picker.el.contains(e.target)) picker.close(false);\n });\n }\n content.appendChild(row);\n }\n\n const columns = el('div', 'twm-filter-dialog__columns');\n const buildPane = el('section', 'twm-filter-dialog__pane twm-filter-dialog__pane--build');\n columns.appendChild(buildPane);\n content.appendChild(columns);\n\n const errorsEl = el('ul', 'twm-filter-dialog__errors');\n errorsEl.hidden = true;\n const failureEl = el('div', 'twm-filter-dialog__failure');\n failureEl.setAttribute('role', 'alert');\n failureEl.hidden = true;\n\n let sentenceEl = null;\n let slot = null;\n if (preview) {\n const pane = el('section', 'twm-filter-dialog__pane twm-filter-dialog__pane--preview');\n sentenceEl = el('div', 'twm-filter-dialog__sentence');\n slot = el('div', 'twm-filter-dialog__preview');\n pane.append(sentenceEl, errorsEl, slot);\n columns.appendChild(pane);\n }\n\n let previewTimer = 0;\n let previewRun = null;\n let controls = null;\n let busy = false;\n\n const builder = createFilterBuilder(buildPane, {\n model,\n value: start,\n onChange: () => {\n refresh();\n clearTimeout(previewTimer);\n previewTimer = setTimeout(drawPreview, PREVIEW_DEBOUNCE_MS);\n },\n });\n if (!preview) buildPane.appendChild(errorsEl);\n content.appendChild(failureEl);\n\n /** The expression as it would be submitted. */\n function current() {\n const expr = builder.getValue();\n return prune ? model.pruneFilter(expr) : expr;\n }\n const checkOf = (expr) => (expr ? model.validateFilter(expr) : { ok: true, errors: [] });\n\n const nameMissing = () => !!nameInput && name.required !== false && !nameInput.value.trim();\n const canSubmit = () => !busy && !nameMissing() && (!requireValid || checkOf(current()).ok);\n\n function refresh() {\n if (!controls) return;\n for (const { value } of modalActions) {\n controls.setActionEnabled(value, value === SUBMIT ? canSubmit() : !busy);\n }\n }\n\n function showErrors(errors) {\n errorsEl.replaceChildren(...errors.map((message) => el('li', '', message)));\n errorsEl.hidden = errors.length === 0;\n }\n function showFailure(message) {\n failureEl.textContent = message;\n failureEl.hidden = !message;\n }\n\n function drawPreview() {\n const expr = current();\n const { ok, errors } = checkOf(expr);\n previewRun?.abort();\n previewRun = null;\n const blocked = requireValid && !ok;\n showErrors(blocked ? errors : []);\n if (!preview) return;\n slot.hidden = blocked;\n if (blocked) {\n sentenceEl.textContent = '';\n slot.replaceChildren();\n return;\n }\n const shown = expr ?? emptyFilter();\n const sentence = model.describeFilter(shown);\n sentenceEl.textContent = sentence;\n previewRun = new AbortController();\n try {\n preview(slot, { expr: shown, sentence, signal: previewRun.signal });\n } catch (err) {\n showFailure(`Preview failed: ${err?.message ?? err}`);\n }\n }\n\n const snapshot = () => JSON.stringify([builder.getValue(), nameInput?.value ?? null, picker?.value() ?? null]);\n const initial = snapshot();\n\n /**\n * May the dialog close without an answer? Not while an action is in flight:\n * the caller would hear \"dismissed\" about a save that then completes, or\n * never see the error of one that fails. Otherwise, not without asking if\n * that loses what was typed.\n */\n function mayDiscard() {\n if (busy) return false;\n if (!confirmDiscard || snapshot() === initial) return true;\n return openConfirm({\n title: 'Discard changes?',\n message: 'This filter has unsaved changes. Closing now throws them away.',\n confirmLabel: 'Discard',\n cancelLabel: 'Keep editing',\n danger: true,\n });\n }\n\n async function runAction(action, close) {\n if (busy || (action.value === SUBMIT && !canSubmit())) return;\n showFailure('');\n busy = true;\n try {\n // Its question stacks over this window, so the buttons stay as they\n // are until it is answered and focus has a button to come back to.\n if (action.confirm && !await openConfirm(action.confirm)) return;\n refresh();\n const result = { action: action.value, expr: action.value === CLEAR ? null : current() };\n if (nameInput) result.name = nameInput.value.trim();\n if (picker) result.icon = picker.value();\n await action.run?.(result);\n close(result);\n } catch (err) {\n showFailure(err?.message ?? String(err));\n } finally {\n busy = false;\n refresh();\n }\n }\n const asModalAction = (action) => ({\n ...action,\n keepOpen: true,\n onClick: (close) => runAction(action, close),\n });\n\n const modalActions = [\n ...actions.map(asModalAction),\n {\n label: 'Cancel',\n value: 'cancel',\n keepOpen: true,\n onClick: async (close) => { if (await mayDiscard()) close(null); },\n },\n ];\n if (clearLabel) modalActions.push(asModalAction({ label: clearLabel, value: CLEAR }));\n modalActions.push({\n ...asModalAction({ label: submitLabel, value: SUBMIT, run: onSubmit }),\n primary: true,\n disabled: !canSubmit(),\n });\n\n const closed = openModal({\n title,\n icon,\n content,\n actions: modalActions,\n width,\n height,\n maximizable: true,\n beforeClose: mayDiscard,\n onMount: (_body, modalControls) => {\n controls = modalControls;\n refresh();\n },\n });\n drawPreview();\n\n try {\n return await closed;\n } finally {\n clearTimeout(previewTimer);\n previewRun?.abort();\n builder.destroy();\n }\n}\n", "/**\n * gallery_picker.js \u2014 single-select card grid for the starter catalog.\n *\n * G1.3 in docs/STARTER_GALLERY_REQUIREMENTS.md. Used by every\n * \"New X\" modal to let the user pick a starter shape (formerly\n * called a \"template\"). The picker is mounted into a host element\n * and fires `onChange(entry)` whenever the selection changes.\n *\n * The entries come from `opts.entries`, or else from the host's optional\n * `gallery` capability (`host.gallery.list(kind)`, see host.js). Each entry is\n *\n * { id, kind, label, description, fields }\n *\n * The picker shows label + description as a card. `fields` is\n * passed through to the caller untouched on select \u2014 the New-X\n * handler decides what to do with it.\n *\n * Usage:\n *\n * const picker = await mountGalleryPicker(hostEl, {\n * host, // or entries: [...]\n * kind: 'agent',\n * selectedId: 'blank',\n * onChange: (entry) => { \u2026 },\n * });\n *\n * // later \u2026\n * picker.getSelected(); // \u2192 { id, kind, label, description, fields }\n * picker.dispose();\n */\n\nfunction esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;',\n }[c]));\n}\n\n\n/**\n * Mount a starter-gallery picker into `hostEl`.\n *\n * @param {HTMLElement} hostEl\n * @param {object} opts\n * @param {string} opts.kind \u2014 gallery entries to load (e.g. 'agent').\n * When undefined, every kind shows up.\n * @param {string} [opts.selectedId] \u2014 id to pre-select. If absent, the\n * first entry wins.\n * @param {function} [opts.onChange] \u2014 `(entry) => void` fired on selection\n * change AND on initial mount.\n * @param {object[]} [opts.entries] \u2014 explicit entries (the host is not asked).\n * @param {object} [opts.host] \u2014 a Host; its `gallery.list(kind)` supplies\n * the entries when `entries` is absent.\n * With neither, the picker shows\n * `emptyLabel` and warns once.\n * @param {string} [opts.emptyLabel] \u2014 copy shown when the catalog is empty\n * for that kind.\n * @returns {Promise<{getSelected, setSelectedById, dispose}>}\n */\nexport async function mountGalleryPicker(hostEl, opts = {}) {\n const {\n kind = null,\n selectedId = null,\n onChange = () => {},\n entries = null,\n host = null,\n emptyLabel = 'No starters available for this kind.',\n } = opts;\n if (!hostEl) throw new Error('mountGalleryPicker: hostEl is required');\n\n let catalog = entries;\n if (!catalog) {\n const list = host?.gallery?.list;\n if (typeof list !== 'function') {\n console.warn('[gallery-picker] no entries and no host gallery capability; showing the empty label');\n catalog = [];\n } else {\n try {\n catalog = (await list(kind)) || [];\n } catch (err) {\n console.warn('[gallery-picker] host.gallery.list failed', err);\n catalog = [];\n }\n }\n }\n catalog = Array.isArray(catalog) ? catalog : [];\n\n hostEl.classList.add('twm-gallery-picker');\n if (catalog.length === 0) {\n hostEl.innerHTML = `<div class=\"twm-gallery-picker__empty\">${esc(emptyLabel)}</div>`;\n return {\n getSelected: () => null,\n setSelectedById: () => false,\n dispose: () => { hostEl.classList.remove('twm-gallery-picker'); },\n };\n }\n\n let selected = catalog.find((e) => e?.id === selectedId)\n || catalog[0];\n\n const render = () => {\n hostEl.innerHTML = catalog.map((e, i) => {\n const isSel = e === selected;\n const desc = e?.description\n ? `<p class=\"twm-gallery-card__desc\">${esc(e.description)}</p>`\n : '';\n return `\n <button type=\"button\"\n class=\"twm-gallery-card ${isSel ? 'is-selected' : ''}\"\n data-idx=\"${i}\"\n title=\"${esc(e?.id || '')}\">\n <span class=\"twm-gallery-card__label\">${esc(e?.label || e?.id || '')}</span>\n ${desc}\n </button>\n `;\n }).join('');\n };\n render();\n\n const onClick = (ev) => {\n const card = ev.target.closest?.('.twm-gallery-card');\n if (!card || !hostEl.contains(card)) return;\n const idx = Number(card.dataset.idx);\n const next = catalog[idx];\n if (!next || next === selected) return;\n selected = next;\n render();\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] onChange threw', err);\n }\n };\n hostEl.addEventListener('click', onClick);\n\n // Fire the initial selection so the caller can prime any\n // downstream UI (preview pane, defaults, etc.) without a\n // special case for first-render.\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] initial onChange threw', err);\n }\n\n return {\n getSelected: () => (selected ? { ...selected } : null),\n setSelectedById: (id) => {\n const next = catalog.find((e) => e?.id === id);\n if (!next || next === selected) return false;\n selected = next;\n render();\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] onChange threw', err);\n }\n return true;\n },\n dispose: () => {\n hostEl.removeEventListener('click', onClick);\n hostEl.innerHTML = '';\n hostEl.classList.remove('twm-gallery-picker');\n },\n };\n}\n", "/**\n * Notification Center (js_new)\n *\n * Purpose\n * -------\n * Unified notifications/toasts/status-line controller consuming events from the rest of the app.\n *\n * Responsibilities\n * - Render queued notifications with namespace context and severity.\n * - Ingest `log:*` and domain-specific events to present user-facing feedback.\n * - Replace scattered `window.notify` / `status_view.js` hooks.\n *\n * Source Material\n * - html/js/status_view.js and ui_manager.js toast helpers.\n * - html/js/ui_utilities.js notification utilities.\n *\n * Progress toasts (0.17.0)\n * ------------------------\n * `show({ progress })` makes a toast that tracks a job: `progress` is a 0..1\n * fraction, `{ value, total }`, or `null` for indeterminate; `status` is a line\n * under the message and `counts` a label beside the bar. Such a toast is\n * persistent and collapsible, and it RUNS until `update()` gives it an outcome\n * severity (success, error or fatal), which ends its bar (done or error) for\n * good and lets a `durationMs` in the same patch dismiss it. Every toast is\n * drawn once and then patched: `update()` touches only its own nodes, and a\n * toast arriving or leaving moves no other toast's element, so a bar, a\n * collapsed state and a hovered button survive. A running progress toast is\n * never held behind \"+N more\" (and never dropped by 'drop'); it counts toward\n * `maxVisible`, so it takes the place of the newest other toast.\n *\n * History subscribers (0.17.3)\n * ----------------------------\n * `history` holds one entry per toast, whichever way it came (`show()`, the\n * `warn()`/`error()`/... helpers, `toast:show`, `notification:show`,\n * `log:entry`). A toast that leaves marks its own entry `dismissed` with a\n * `reason`; it adds none. `subscribe(fn)` calls `fn(entry, center)` for each\n * entry added, so a history view follows the centre rather than the bus.\n *\n * Copy message (STORY-0131)\n * -------------------------\n * A right-click on a toast, or on its entry in the history, opens the context\n * menu with \"Copy message\": the title, the message and the description, one\n * per line, go to the clipboard as plain text. The text is also selectable:\n * a click on the title, message, description or status, or one that ends a\n * selection, does not close the toast; only a click on its chrome does.\n */\nimport { ComponentBase } from './base/component_base.js';\nimport { getSetting } from '../core/settings.js';\nimport { setToastBus, getToastBus } from './components/toast.js';\nimport { ProgressBar } from './components/progress.js';\nimport { showContextMenu } from './components/context_menu.js';\n\nconst SEVERITIES = ['info', 'success', 'warn', 'error', 'fatal'];\n\n/** The severity a progress toast finishes with, and the state its bar ends in. */\nconst OUTCOME_BAR_STATE = Object.freeze({ success: 'done', error: 'error', fatal: 'error' });\nconst LOG_SEVERITY_MAP = {\n trace: 'info',\n debug: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n fatal: 'fatal',\n};\n\nconst DEFAULT_LOG_LEVELS = new Set(['warn', 'error', 'fatal']);\n\n// Internal namespace identifiers that should not be shown as toast titles.\n// Messages from these namespaces are self-descriptive and need no category header.\nconst SUPPRESSED_NAMESPACE_TITLES = new Set(['bootstrap', 'app']);\n\n/** A notification as plain text: its title, message and description, one per line. */\nexport function notificationText(notification) {\n return [notification.title, notification.message, notification.description]\n .filter((part) => part != null && String(part) !== '')\n .join('\\n');\n}\n\n/**\n * The right-click menu of a toast or a history entry: \"Copy message\". It takes\n * the right-click, so the browser's own menu does not open.\n */\nexport function showNotificationMenu(event, notification, logger) {\n event.preventDefault();\n event.stopPropagation();\n showContextMenu(event.clientX, event.clientY,\n [{ label: 'Copy message', icon: 'content_copy', action: 'copy' }],\n () => {\n Promise.resolve()\n .then(() => navigator.clipboard.writeText(notificationText(notification)))\n .catch((err) => logger?.warn?.('twm-notification-center', 'Copy message failed', { err }));\n });\n}\n\n/** The toast's text: clicking it selects, it does not dismiss. */\nconst TOAST_TEXT = '.twm-notification__title, .twm-notification__body, '\n + '.twm-notification__description, .twm-notification__status';\n\n/** A non-empty text selection inside `el`: a click that ends one is not a click on it. */\nfunction selectsTextIn(el) {\n const sel = el.ownerDocument.getSelection?.();\n return Boolean(sel && !sel.isCollapsed && sel.rangeCount && el.contains(sel.getRangeAt(0).commonAncestorContainer));\n}\n\nexport class NotificationCenter extends ComponentBase {\n #items;\n #summaryEl;\n #historyListeners;\n\n constructor({\n eventBus,\n logger,\n maxVisible = 3,\n historyLimit = 50,\n defaultDurationMs = 6000,\n logLevels = DEFAULT_LOG_LEVELS,\n // What happens past `maxVisible`. 'drop' (the default, as before 0.11):\n // the oldest toast leaves. 'collapse': the toasts on screen stay, the\n // rest wait behind one \"+N more\" toast, and each comes in as one closes\n // \u2014 a sticky alert nobody has read is never pushed off unseen.\n overflow = 'drop',\n // Called with the held-back toasts when the \"+N more\" toast is clicked.\n summaryAction = null,\n } = {}) {\n super({ eventBus, logger });\n\n this.maxVisible = maxVisible;\n this.overflow = overflow === 'collapse' ? 'collapse' : 'drop';\n this.summaryAction = typeof summaryAction === 'function' ? summaryAction : null;\n /** Toasts waiting behind the \"+N more\" summary ('collapse' only), oldest first. */\n this.held = [];\n this.historyLimit = historyLimit;\n this.defaultDurationMs = defaultDurationMs;\n this.logLevels = new Set(logLevels ?? DEFAULT_LOG_LEVELS);\n\n this.notifications = [];\n this.history = [];\n this.sequence = 0;\n this.activeTimers = new Map();\n this.eventDisposers = [];\n /** id -> the drawn toast's nodes, for the toasts on screen. */\n this.#items = new Map();\n this.#summaryEl = null;\n this.#historyListeners = new Set();\n\n this.container = null;\n this.rootEl = null;\n this.listEl = null;\n this.liveRegionEl = null;\n }\n\n mount(container, props = {}) {\n // Always mount to document.body for reliable visibility\n // The passed container is ignored - we create our own fixed-position container\n const existingContainer = document.getElementById('notification-center-root');\n if (existingContainer) {\n this.container = existingContainer;\n this.rootEl = existingContainer.querySelector('.twm-notification-center');\n this.listEl = existingContainer.querySelector('.twm-notification-center__list');\n this.liveRegionEl = existingContainer.querySelector('.twm-notification-center__live-region');\n this._mounted = true;\n this.#subscribeEvents();\n this.#claimToastBus();\n return this;\n }\n\n // Create a new fixed-position container directly on body\n this.container = document.createElement('div');\n this.container.id = 'notification-center-root';\n this.container.style.cssText = 'position: fixed; right: 16px; bottom: 24px; z-index: 10000; pointer-events: none;';\n\n this.rootEl = document.createElement('div');\n this.rootEl.className = 'twm-notification-center';\n\n this.listEl = document.createElement('div');\n this.listEl.className = 'twm-notification-center__list';\n\n this.liveRegionEl = document.createElement('div');\n this.liveRegionEl.className = 'twm-notification-center__live-region';\n this.liveRegionEl.setAttribute('aria-live', 'polite');\n this.liveRegionEl.setAttribute('aria-atomic', 'true');\n this.liveRegionEl.style.position = 'absolute';\n this.liveRegionEl.style.width = '1px';\n this.liveRegionEl.style.height = '1px';\n this.liveRegionEl.style.overflow = 'hidden';\n this.liveRegionEl.style.clip = 'rect(1px, 1px, 1px, 1px)';\n\n this.rootEl.appendChild(this.listEl);\n this.rootEl.appendChild(this.liveRegionEl);\n this.container.appendChild(this.rootEl);\n document.body.appendChild(this.container);\n\n this._mounted = true;\n this.#subscribeEvents();\n this.#claimToastBus();\n\n if (Array.isArray(props.initialNotifications)) {\n props.initialNotifications.forEach((notification) => this.show(notification));\n }\n return this;\n }\n\n dispose() {\n this.#clearTimers();\n this.#unsubscribeEvents();\n this.#historyListeners.clear();\n // Give the toast helpers back to the console \u2014 unless someone has\n // pointed them at another bus since this centre mounted.\n if (this.eventBus && getToastBus() === this.eventBus) setToastBus(null);\n this.#items.forEach((entry) => entry.bar?.dispose());\n this.#items.clear();\n this.#summaryEl = null;\n if (this.rootEl?.parentNode) {\n this.rootEl.parentNode.removeChild(this.rootEl);\n }\n this.container = null;\n this.rootEl = null;\n this.listEl = null;\n this.liveRegionEl = null;\n super.dispose();\n }\n\n show(notification) {\n const normalized = this.#normalizeNotification(notification);\n this.#consoleLog(normalized);\n const running = NotificationCenter.#isRunning(normalized);\n if (this.overflow === 'collapse' && !running && this.notifications.length >= this.maxVisible) {\n // Held, not shown: its timer starts when it comes on screen.\n this.held.push(normalized);\n this.#recordHistory(normalized);\n this.#render();\n this.#announce(normalized);\n return normalized.id;\n }\n this.notifications.push(normalized);\n if (this.overflow === 'collapse') {\n // Only a running progress toast gets here past the limit: the\n // newest other toast steps back behind \"+N more\" to make room.\n this.#rebalance();\n } else if (this.notifications.length > this.maxVisible) {\n // The oldest leaves \u2014 but never a running progress toast.\n const idx = this.notifications.findIndex((item) => !NotificationCenter.#isRunning(item));\n if (idx !== -1) {\n const [removed] = this.notifications.splice(idx, 1);\n this.#stopTimer(removed.id);\n this.#recordDismissal(removed, 'overflow');\n }\n }\n\n this.#recordHistory(normalized);\n this.#scheduleAutoDismiss(normalized);\n this.#render();\n this.#announce(normalized);\n return normalized.id;\n }\n\n dismiss(notificationId, reason = 'dismissed') {\n const idx = this.notifications.findIndex((item) => item.id === notificationId);\n if (idx === -1) {\n const h = this.held.findIndex((item) => item.id === notificationId);\n if (h === -1) return false;\n const [gone] = this.held.splice(h, 1);\n this.#recordDismissal(gone, reason);\n this.#render();\n return true;\n }\n const [removed] = this.notifications.splice(idx, 1);\n this.#stopTimer(notificationId);\n this.#recordDismissal(removed, reason);\n // A place on screen came free: the oldest held-back toast takes it.\n this.#rebalance();\n this.#render();\n return true;\n }\n\n /**\n * Change a notification in place: only its own nodes are touched, and no\n * other toast is redrawn. A held-back toast is changed too and shows the\n * change when it comes on screen.\n *\n * Fields: `message`, `title`, `description`, `severity`, `meta`, and for\n * progress toasts `progress` (fraction, `{ value, total }`, or `null` for\n * indeterminate), `status`, `counts` and `collapsed`; `progress` on a\n * plain toast turns it into a running progress toast (on screen, as with\n * show()). Giving a running progress toast an outcome severity (success,\n * error, fatal) finishes it, and its bar keeps the state it ended in: a\n * later severity only restyles the toast. A `durationMs` on a toast that\n * is not running (re)starts its auto-dismiss (0 keeps it until closed).\n *\n * @param {string} notificationId - The ID of the notification to update\n * @param {Object} updates - The fields to change\n * @returns {boolean} True if the notification was found and updated\n */\n update(notificationId, updates = {}) {\n const notification = this.notifications.find((item) => item.id === notificationId)\n ?? this.held.find((item) => item.id === notificationId);\n if (!notification) {\n return false;\n }\n const hadTitle = Boolean(notification.title);\n const hadDescription = Boolean(notification.description);\n const wasProgress = notification.progress !== undefined;\n const wasRunning = NotificationCenter.#isRunning(notification);\n\n if (updates.message !== undefined) notification.message = updates.message;\n if (updates.title !== undefined) notification.title = updates.title;\n if (updates.description !== undefined) notification.description = updates.description;\n if (updates.meta !== undefined) notification.meta = updates.meta;\n if (updates.status !== undefined) notification.status = updates.status ?? '';\n if (updates.counts !== undefined) notification.counts = updates.counts ?? '';\n if (updates.collapsed !== undefined) notification.collapsed = Boolean(updates.collapsed);\n if (updates.progress !== undefined) {\n if (wasProgress) {\n notification.progress = NotificationCenter.#normalizeProgress(updates.progress);\n } else {\n // A plain toast becomes a running progress toast, set up as show() would.\n Object.assign(notification, NotificationCenter.#progressFields({ ...notification, ...updates }));\n notification.persistent = true;\n this.#stopTimer(notification.id);\n }\n }\n if (updates.severity !== undefined) {\n notification.severity = this.#normalizeSeverity(updates.severity);\n const outcome = OUTCOME_BAR_STATE[notification.severity];\n if (NotificationCenter.#isRunning(notification) && outcome) notification.outcome = outcome;\n }\n const running = NotificationCenter.#isRunning(notification);\n const finished = wasRunning && !running;\n if (updates.durationMs !== undefined && !NotificationCenter.#isRunning(notification)) {\n notification.durationMs = this.#coerceDuration(updates.durationMs);\n notification.persistent = notification.durationMs === 0;\n if (this.notifications.includes(notification)) {\n this.#stopTimer(notification.id);\n this.#scheduleAutoDismiss(notification);\n }\n }\n\n const entry = this.#items.get(notification.id);\n if (entry) {\n const structural = hadTitle !== Boolean(notification.title)\n || hadDescription !== Boolean(notification.description)\n || wasProgress !== (notification.progress !== undefined);\n if (structural) {\n // A part appears or goes: rebuild this one toast, in its place.\n const next = this.#buildItem(notification);\n entry.el.replaceWith(next.el);\n entry.bar?.dispose();\n this.#items.set(notification.id, next);\n } else {\n this.#patchItem(entry, notification);\n }\n }\n if (finished) this.#announce(notification);\n // Started, it comes on screen whatever is held; finished, it folds\n // like any other toast.\n if (running !== wasRunning) this.#rebalance();\n this.#render();\n return true;\n }\n\n clearAll(reason = 'cleared') {\n [...this.notifications].forEach((notification) => this.dismiss(notification.id, reason));\n }\n\n ingestLogEntry(entry) {\n if (!entry || !this.logLevels.has(entry.level)) {\n return;\n }\n\n // Suppress state-guard warnings - these are internal and would cause a cascade\n // (NotificationCenter renders -> triggers state-guard -> logs warning -> creates notification -> repeat)\n if (entry.namespace === 'state-guard') {\n return;\n }\n\n const severity = LOG_SEVERITY_MAP[entry.level] ?? 'info';\n const suppressTitle = SUPPRESSED_NAMESPACE_TITLES.has(entry.namespace);\n const title = suppressTitle\n ? null\n : NotificationCenter.#formatNamespaceTitle(entry.namespace);\n // Info-level log entries from internal namespaces are noise in history\n const skipHistory = severity === 'info' && suppressTitle;\n this.show({\n title,\n message: entry.message,\n severity,\n namespace: entry.namespace,\n meta: entry.data,\n skipHistory,\n });\n }\n\n #consoleLog(notification) {\n if (notification.severity !== 'warn' && notification.severity !== 'error' && notification.severity !== 'fatal') {\n return;\n }\n const method = notification.severity === 'warn' ? console.warn : console.error; // eslint-disable-line no-console\n const prefix = notification.title ? `[${notification.title}]` : '[Notification]';\n const details = notification.meta ?? notification.description ?? '';\n method(`${prefix} ${notification.message}`, details); // eslint-disable-line no-console\n }\n\n #normalizeNotification(notification) {\n if (!notification) {\n throw new TypeError('Notification payload is required');\n }\n const id = notification.id ?? `notification-${++this.sequence}`;\n const severity = this.#normalizeSeverity(notification.severity ?? 'info');\n const isProgress = notification.progress !== undefined;\n return {\n ...(isProgress ? NotificationCenter.#progressFields(notification) : {}),\n id,\n title: notification.title ?? null,\n message: notification.message ?? '',\n description: notification.description ?? null,\n timestamp: notification.timestamp ?? Date.now(),\n severity,\n namespace: notification.namespace ?? null,\n durationMs: this.#coerceDuration(notification.durationMs),\n // A progress toast stays until it finishes (and then until its\n // finishing durationMs, or its \u00D7).\n persistent: isProgress || Boolean(notification.persistent),\n skipHistory: Boolean(notification.skipHistory),\n actions: this.#normalizeActions(notification.actions),\n meta: notification.meta ?? null,\n };\n }\n\n #normalizeSeverity(severity) {\n const value = typeof severity === 'string' ? severity.toLowerCase() : 'info';\n if (!SEVERITIES.includes(value)) {\n return 'info';\n }\n return value;\n }\n\n #coerceDuration(duration) {\n if (duration === null || duration === undefined) {\n return this.defaultDurationMs;\n }\n const value = Number(duration);\n if (!Number.isFinite(value) || value < 0) {\n return this.defaultDurationMs;\n }\n return value;\n }\n\n toast(title, message, type = 'info') {\n // Legacy compatibility method\n this.show({\n title,\n message,\n severity: type,\n persistent: type === 'error' || type === 'fatal',\n });\n }\n\n error(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'error',\n persistent: true,\n });\n }\n\n warn(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'warn',\n });\n }\n\n info(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'info',\n });\n }\n\n success(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'success',\n });\n }\n\n #normalizeActions(actions) {\n if (!Array.isArray(actions) || actions.length === 0) {\n return [];\n }\n return actions.map((action, idx) => ({\n id: action.id ?? `action-${idx}`,\n label: action.label ?? 'Action',\n handler: typeof action.handler === 'function' ? action.handler : null,\n eventName: action.eventName ?? null,\n payload: action.payload ?? null,\n }));\n }\n\n #scheduleAutoDismiss(notification) {\n if (notification.persistent || notification.durationMs === 0) {\n return;\n }\n const timer = setTimeout(() => {\n this.dismiss(notification.id, 'timeout');\n }, notification.durationMs);\n this.activeTimers.set(notification.id, timer);\n }\n\n #stopTimer(notificationId) {\n const timer = this.activeTimers.get(notificationId);\n if (timer) {\n clearTimeout(timer);\n this.activeTimers.delete(notificationId);\n }\n }\n\n #clearTimers() {\n this.activeTimers.forEach((timer) => clearTimeout(timer));\n this.activeTimers.clear();\n }\n\n /**\n * Hear of every entry added to `history`, by `show()`, `warn()`/`error()`/\n * `info()`/`success()` and the bus alike: `listener(entry, center)`, once\n * per toast, after the entry is in `history`. A dismissal changes the\n * toast's own entry and is not an entry of its own. Answers the unsubscribe.\n */\n subscribe(listener) {\n if (typeof listener !== 'function') return () => {};\n this.#historyListeners.add(listener);\n return () => { this.#historyListeners.delete(listener); };\n }\n\n #recordHistory(entry) {\n if (entry.skipHistory) return;\n this.history.push(entry);\n if (this.history.length > this.historyLimit) {\n this.history.shift();\n }\n [...this.#historyListeners].forEach((listener) => {\n try {\n listener(entry, this);\n } catch (err) {\n this.logger?.warn?.('twm-notification-center', 'History listener failed', { err });\n }\n });\n }\n\n /** A toast that left marks its own entry: one toast, one entry. */\n #recordDismissal(notification, reason) {\n if (notification.skipHistory) return;\n const at = this.history.findLastIndex((entry) => entry.id === notification.id);\n if (at === -1) return;\n this.history[at] = { ...notification, dismissed: true, reason };\n }\n\n /** A progress toast that has not been given an outcome yet. */\n static #isRunning(notification) {\n return notification.progress !== undefined && !notification.outcome;\n }\n\n /**\n * The fields a progress toast carries, from a show() payload or an\n * update() that turns a plain toast into one. `outcome` is null while it\n * runs, then the state its bar ended in (done or error).\n */\n static #progressFields(source) {\n return {\n progress: NotificationCenter.#normalizeProgress(source.progress),\n status: source.status ?? '',\n counts: source.counts ?? '',\n collapsed: Boolean(source.collapsed),\n outcome: null,\n };\n }\n\n /** `null` (indeterminate), a 0..1 fraction, or `{ value, total }` -> ProgressBar input. */\n static #normalizeProgress(progress) {\n if (progress === null) return { indeterminate: true };\n if (typeof progress === 'number') {\n return { value: Number.isFinite(progress) ? progress : 0, max: null, indeterminate: false };\n }\n if (typeof progress === 'object') {\n const value = Number(progress.value);\n const total = Number(progress.total);\n return {\n value: Number.isFinite(value) ? value : 0,\n max: Number.isFinite(total) && total > 0 ? total : null,\n indeterminate: false,\n };\n }\n return { indeterminate: true };\n }\n\n /**\n * 'collapse' only: keep at most `maxVisible` on screen, counting running\n * progress toasts, which never leave and are never held (one that started\n * running while held comes on screen first). Past the limit the newest\n * other toast steps back to the front of the held queue (its timer\n * restarts when it returns); under it the oldest held toast comes in.\n */\n #rebalance() {\n if (this.overflow !== 'collapse') return;\n for (let i = 0; i < this.held.length;) {\n if (NotificationCenter.#isRunning(this.held[i])) this.notifications.push(...this.held.splice(i, 1));\n else i++;\n }\n while (this.notifications.length > this.maxVisible) {\n let idx = -1;\n for (let i = this.notifications.length - 1; i >= 0; i--) {\n if (!NotificationCenter.#isRunning(this.notifications[i])) { idx = i; break; }\n }\n if (idx === -1) break;\n const [back] = this.notifications.splice(idx, 1);\n this.#stopTimer(back.id);\n this.held.unshift(back);\n }\n while (this.held.length && this.notifications.length < this.maxVisible) {\n const next = this.held.shift();\n this.notifications.push(next);\n this.#scheduleAutoDismiss(next);\n }\n }\n\n /**\n * Draw the toasts on screen. Each toast's element is built once and kept:\n * a toast arriving or leaving only inserts or removes its own element, so\n * every other toast keeps its nodes (and its bar, collapsed state, hover).\n */\n #render() {\n if (!this._mounted || !this.listEl) {\n return;\n }\n const visible = new Set(this.notifications.map((n) => n.id));\n for (const [id, entry] of this.#items) {\n if (visible.has(id)) continue;\n entry.bar?.dispose();\n entry.el.remove();\n this.#items.delete(id);\n }\n const wanted = this.notifications.map((notification) => {\n let entry = this.#items.get(notification.id);\n if (!entry) {\n entry = this.#buildItem(notification);\n this.#items.set(notification.id, entry);\n }\n return entry.el;\n });\n const summary = this.#syncSummary();\n if (summary) wanted.push(summary);\n wanted.forEach((el, i) => {\n const at = this.listEl.children[i];\n if (at !== el) this.listEl.insertBefore(el, at ?? null);\n });\n // Anything after them is stale (another instance's toasts on a reused root).\n while (this.listEl.children.length > wanted.length) {\n this.listEl.lastElementChild.remove();\n }\n }\n\n // The held-back toasts, as one: \"+N more\". It is a button so the count is\n // reachable by keyboard; what it opens is the consumer's (summaryAction),\n // and it is also announced on the bus for a history panel to answer.\n #syncSummary() {\n if (!this.held.length) {\n this.#summaryEl?.remove();\n this.#summaryEl = null;\n return null;\n }\n if (!this.#summaryEl) {\n const more = document.createElement('button');\n more.type = 'button';\n more.className = 'twm-notification twm-notification--summary';\n more.addEventListener('click', () => {\n const held = [...this.held];\n try { this.summaryAction?.(held); } catch (err) { this.logger?.warn?.('summaryAction failed', err); }\n this.eventBus?.emit?.('notification:summary', { held });\n });\n this.#summaryEl = more;\n }\n const more = this.#summaryEl;\n const count = String(this.held.length);\n if (more.getAttribute('data-notification-summary') !== count) more.setAttribute('data-notification-summary', count);\n NotificationCenter.#setText(more, `+${count} more`);\n const tip = this.held.map((h) => h.title || h.message).join('\\n');\n if (more.title !== tip) more.title = tip;\n return more;\n }\n\n static #setText(node, text) {\n const t = text == null ? '' : String(text);\n if (node.textContent !== t) node.textContent = t;\n }\n\n /** Build one toast's element; `#patchItem` then fills what can change. */\n #buildItem(notification) {\n const isProgress = notification.progress !== undefined;\n const item = document.createElement('div');\n // Use setAttribute to avoid StateGuard blocking dataset mutations\n item.setAttribute('data-notification-id', notification.id);\n const entry = { el: item, severity: null, titleEl: null, bodyEl: null, descriptionEl: null,\n statusEl: null, bar: null, collapseBtn: null };\n\n const header = document.createElement('div');\n header.className = 'twm-notification__header';\n if (notification.title) {\n entry.titleEl = document.createElement('span');\n entry.titleEl.className = 'twm-notification__title';\n header.appendChild(entry.titleEl);\n }\n\n const timeEl = document.createElement('span');\n timeEl.className = 'twm-notification__timestamp';\n timeEl.textContent = this.#formatTimestamp(notification.timestamp);\n header.appendChild(timeEl);\n\n if (isProgress) {\n const toggle = document.createElement('button');\n toggle.className = 'twm-notification__collapse';\n toggle.type = 'button';\n toggle.innerHTML = '<span class=\"material-symbols-outlined\">expand_more</span>';\n toggle.addEventListener('click', () => {\n this.update(notification.id, { collapsed: !notification.collapsed });\n });\n entry.collapseBtn = toggle;\n header.appendChild(toggle);\n }\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'twm-notification__close';\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', 'Dismiss notification');\n closeBtn.innerHTML = '<span class=\"material-symbols-outlined\">close</span>';\n closeBtn.addEventListener('click', () => this.dismiss(notification.id, 'manual'));\n header.appendChild(closeBtn);\n item.appendChild(header);\n\n entry.bodyEl = document.createElement('div');\n entry.bodyEl.className = 'twm-notification__body';\n item.appendChild(entry.bodyEl);\n\n if (isProgress) {\n entry.bar = new ProgressBar(item, {\n ...notification.progress, showCount: false, className: 'twm-notification__progress',\n });\n entry.statusEl = document.createElement('div');\n entry.statusEl.className = 'twm-notification__status';\n item.appendChild(entry.statusEl);\n }\n\n if (notification.description) {\n entry.descriptionEl = document.createElement('div');\n entry.descriptionEl.className = 'twm-notification__description';\n item.appendChild(entry.descriptionEl);\n }\n\n if (notification.actions.length > 0) {\n const actionsEl = document.createElement('div');\n actionsEl.className = 'twm-notification__actions';\n notification.actions.forEach((action) => {\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'twm-notification__action-btn';\n button.textContent = action.label;\n button.addEventListener('click', () => {\n try {\n if (action.handler) {\n action.handler(notification, action);\n } else if (action.eventName && this.eventBus) {\n this.eventBus.emit(action.eventName, action.payload ?? { notificationId: notification.id });\n }\n } catch (err) {\n this.logger?.error?.('twm-notification-center', 'Notification action failed', { err });\n } finally {\n // Don't auto-dismiss error/fatal notifications, or a job\n // still running, after action clicks\n if (notification.severity !== 'error' && notification.severity !== 'fatal'\n && !NotificationCenter.#isRunning(notification)) {\n this.dismiss(notification.id, 'action');\n }\n }\n });\n actionsEl.appendChild(button);\n });\n item.appendChild(actionsEl);\n }\n\n // A click on the text is the start of selecting it (a double-click's\n // first click leaves only a caret), so only the toast's chrome closes it.\n item.addEventListener('click', (event) => {\n if (event.target.closest(`button, ${TOAST_TEXT}`) || NotificationCenter.#isRunning(notification)\n || selectsTextIn(item)) {\n return;\n }\n this.dismiss(notification.id, 'click');\n });\n item.addEventListener('contextmenu', (event) => showNotificationMenu(event, notification, this.logger));\n\n this.#patchItem(entry, notification);\n return entry;\n }\n\n /** Bring a drawn toast's nodes in line with its data, touching only what changed. */\n #patchItem(entry, notification) {\n const item = entry.el;\n if (entry.severity !== notification.severity) {\n if (entry.severity) item.classList.remove(`twm-notification--${entry.severity}`);\n item.classList.add('twm-notification', `twm-notification--${notification.severity}`);\n entry.severity = notification.severity;\n }\n if (entry.titleEl) NotificationCenter.#setText(entry.titleEl, notification.title);\n NotificationCenter.#setText(entry.bodyEl, notification.message);\n if (entry.descriptionEl) NotificationCenter.#setText(entry.descriptionEl, notification.description);\n if (!entry.bar) return;\n\n item.classList.add('twm-notification--progress');\n item.classList.toggle('twm-notification--collapsed', Boolean(notification.collapsed));\n const expanded = String(!notification.collapsed);\n if (entry.collapseBtn.getAttribute('aria-expanded') !== expanded) {\n entry.collapseBtn.setAttribute('aria-expanded', expanded);\n entry.collapseBtn.setAttribute('aria-label', notification.collapsed ? 'Expand notification' : 'Collapse notification');\n }\n NotificationCenter.#setText(entry.statusEl, notification.status);\n entry.statusEl.hidden = !notification.status;\n entry.bar.update({ ...notification.progress, label: notification.counts });\n const end = notification.outcome ?? 'running';\n if (entry.bar.state !== end) entry.bar.setState(end);\n }\n\n #formatTimestamp(timestamp) {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n\n #announce(notification) {\n if (!this.liveRegionEl) {\n return;\n }\n const parts = [notification.title, notification.message].filter(Boolean);\n this.liveRegionEl.textContent = parts.join(': ');\n }\n\n #handleToast(payload = {}) {\n const message = payload.text ?? payload.message ?? (typeof payload === 'string' ? payload : '');\n if (!message) {\n return;\n }\n\n const persistent = payload.persistent === true || payload.autoHide === false;\n const durationMs = persistent ? 0 : (payload.durationMs ?? payload.duration ?? payload.timeout);\n this.show({\n title: payload.title ?? null,\n message,\n severity: payload.type ?? payload.severity ?? 'info',\n durationMs,\n persistent,\n namespace: payload.namespace ?? null,\n actions: payload.actions,\n meta: payload.meta ?? null,\n });\n }\n\n #subscribeEvents() {\n if (!this.eventBus) {\n return;\n }\n this.eventDisposers.push(\n this.eventBus.on('toast:show', (payload) => this.#handleToast(payload)),\n this.eventBus.on('notification:show', (payload) => this.show(payload)),\n this.eventBus.on('notification:update', (payload) => {\n if (payload?.id) {\n this.update(payload.id, payload);\n }\n }),\n this.eventBus.on('log:entry', (entry) => this.ingestLogEntry(entry)),\n this.eventBus.on('workspace:save:failed', (payload) => {\n // Error toasts are shown by default unless explicitly disabled\n if (getSetting('workspace.save.showErrorToast', true)) {\n this.show({\n title: 'Workspace Save Failed',\n message: payload?.reason ? `Save failed: ${payload.reason}` : 'Workspace save failed',\n severity: 'error',\n meta: payload,\n persistent: true,\n });\n }\n }),\n this.eventBus.on('workspace:save:completed', (payload) => {\n // Only show toast if enabled in settings\n if (getSetting('workspace.save.showToast', false)) {\n this.show({\n title: 'Workspace Saved',\n message: 'Changes saved successfully',\n severity: 'success',\n durationMs: 3000,\n meta: payload,\n skipHistory: true,\n });\n }\n }),\n this.eventBus.on('workspace:import:failed', (payload) => {\n // Error toasts are shown by default unless explicitly disabled\n if (getSetting('workspace.import.showErrorToast', true)) {\n this.show({\n title: 'Workspace Import Failed',\n message: payload?.error?.message || 'Import failed',\n severity: 'error',\n meta: payload,\n persistent: true,\n });\n }\n }),\n this.eventBus.on('workspace:import:completed', (payload) => {\n // Show import completion toast if enabled in settings\n if (getSetting('workspace.import.showToast', true)) {\n this.show({\n title: 'Workspace Ready',\n message: 'Workspace import completed',\n severity: 'success',\n durationMs: 3000,\n meta: payload,\n skipHistory: true,\n });\n }\n }),\n );\n }\n\n /** The toast helpers (toast.js) emit on the bus of the centre mounted last. */\n #claimToastBus() {\n if (this.eventBus) setToastBus(this.eventBus);\n }\n\n #unsubscribeEvents() {\n this.eventDisposers.forEach((disposer) => {\n try {\n disposer?.dispose?.();\n } catch (err) {\n this.logger?.warn?.('twm-notification-center', 'Failed to remove event listener', { err });\n }\n });\n this.eventDisposers = [];\n }\n\n static #formatNamespaceTitle(namespace) {\n if (!namespace) return null;\n return namespace\n .split(/[-_]/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n }\n}\n\nNotificationCenter.SEVERITIES = SEVERITIES;\n", "/**\n * NotificationHistory - Bottom bar notification history panel\n *\n * Bell icon in the global-bottom-bar that opens a popover listing past notifications.\n * Reads from NotificationCenter.history and follows it through\n * `notificationCenter.subscribe()` (0.17.3): every entry the centre records \u2014 a\n * toast from `show()`/`warn()`/... or from the bus \u2014 is one unread, until the\n * popover is opened. The bus is not watched for toasts.\n *\n * THREE OPTIONS, all additive (FlexDesk STORY-0020); without them it is the bell\n * it always was:\n *\n * mountPoint the element the bell is appended to. Without it, the hard-coded\n * `.twm-global-bottom-bar .twm-bar-right`, which only FlexDesk's own\n * bottom bar has.\n * alertLog an alert log (`alert_log.js`). The badge is then the log's unread\n * count, in the worst unread level's colour, and nothing when all is\n * read \u2014 not a delta of a toast history the user may never have\n * opened. A click opens the bottom panel's Alerts tab instead of the\n * popover, and the toasts' \"+N more\" (`notification:summary`) does too.\n * alertsTab the tab a click asks for, `bottompanel:show { tab }`; 'alerts'.\n * onOpen a click, instead of the bus event \u2014 for an embedder with no bus,\n * or whose panel must be opened before a tab can be chosen.\n *\n * A right-click on an entry opens the context menu with \"Copy message\"\n * (STORY-0131), the same as on its toast; the popover stays open meanwhile.\n */\nimport { showNotificationMenu } from '../notification_center.js';\n\nexport class NotificationHistory {\n constructor({ notificationCenter, eventBus, logger, mountPoint = null, alertLog = null,\n alertsTab = 'alerts', onOpen = null } = {}) {\n this.notificationCenter = notificationCenter;\n this.eventBus = eventBus || null;\n this.logger = logger || console;\n this.mountPoint = mountPoint;\n this.alertLog = alertLog;\n this.alertsTab = alertsTab;\n this.onOpen = typeof onOpen === 'function' ? onOpen : null;\n\n this.triggerEl = null;\n this.badgeEl = null;\n /** Entries recorded since the popover was last opened. */\n this.unreadCount = 0;\n this._popoverCleanup = null;\n this._subscriptions = [];\n }\n\n mount() {\n const barRight = this.mountPoint\n || document.querySelector('.twm-global-bottom-bar .twm-bar-right');\n if (!barRight) {\n this.logger.warn?.('[NotificationHistory] .bar-right not found');\n return;\n }\n\n // Build trigger button\n this.triggerEl = document.createElement('button');\n this.triggerEl.className = 'twm-notification-history__trigger twm-has-tooltip';\n this.triggerEl.setAttribute('data-tooltip', 'Notification history');\n this.triggerEl.setAttribute('aria-label', 'Notification history');\n this.triggerEl.innerHTML =\n '<span class=\"material-symbols-outlined\">notifications</span>' +\n '<span class=\"twm-notification-history__badge\" style=\"display:none\">0</span>';\n\n this.badgeEl = this.triggerEl.querySelector('.twm-notification-history__badge');\n\n // Park the bell as the LAST child of .bar-right so it always\n // sits at the far-right edge of the status bar \u2014 past the\n // tick readout, streaming dot, and anything else that the\n // global actions cluster mounts before it.\n barRight.appendChild(this.triggerEl);\n\n this.triggerEl.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.alertLog) this.#openAlerts();\n else this.#togglePanel();\n });\n\n if (this.alertLog) {\n this.triggerEl.setAttribute('data-tooltip', 'Alerts');\n this.triggerEl.setAttribute('aria-label', 'Alerts');\n this._subscriptions.push(this.alertLog.subscribe(() => this.#updateBadge()));\n const summary = this.eventBus?.on?.('notification:summary', () => this.#openAlerts());\n if (summary) this._subscriptions.push(() => summary.dispose?.());\n this.#updateBadge();\n return;\n }\n\n // What is in the history at mount is not unread.\n this.unreadCount = 0;\n const unsubscribe = this.notificationCenter?.subscribe?.(() => {\n this.unreadCount += 1;\n this.#updateBadge();\n });\n if (typeof unsubscribe === 'function') this._subscriptions.push(unsubscribe);\n this.#updateBadge();\n }\n\n unmount() {\n this.#closePanel();\n this._subscriptions.forEach(unsub => {\n if (typeof unsub === 'function') unsub();\n });\n this._subscriptions = [];\n if (this.triggerEl?.parentNode) {\n this.triggerEl.parentNode.removeChild(this.triggerEl);\n }\n this.triggerEl = null;\n this.badgeEl = null;\n }\n\n /** The Alerts tab, asked for on the bus \u2014 or the embedder's own verb. */\n #openAlerts() {\n if (this.onOpen) {\n try { this.onOpen(); } catch (err) { this.logger.warn?.('[NotificationHistory] onOpen failed', err); }\n return;\n }\n this.eventBus?.emit?.('bottompanel:show', { tab: this.alertsTab });\n }\n\n #updateBadge() {\n const historyLen = this.notificationCenter?.history?.length ?? 0;\n const unread = this.alertLog\n ? this.alertLog.unreadCount()\n : Math.min(this.unreadCount, historyLen);\n\n if (!this.badgeEl) return;\n\n if (this.alertLog) {\n const level = unread > 0 ? this.alertLog.worstUnread() : null;\n this.badgeEl.className = 'twm-notification-history__badge'\n + (level ? ` twm-notification-history__badge--${level}` : '');\n this.triggerEl?.classList.toggle('twm-notification-history__trigger--unread', unread > 0);\n }\n\n if (unread > 0) {\n this.badgeEl.textContent = unread > 99 ? '99+' : String(unread);\n this.badgeEl.style.display = '';\n } else {\n this.badgeEl.style.display = 'none';\n }\n }\n\n #togglePanel() {\n if (this._popoverCleanup) {\n this.#closePanel();\n } else {\n this.#openPanel();\n }\n }\n\n #closePanel() {\n if (typeof this._popoverCleanup === 'function') {\n try { this._popoverCleanup(); } catch (_) { /* ignore */ }\n this._popoverCleanup = null;\n }\n }\n\n #openPanel() {\n this.#closePanel();\n\n // Mark all as seen\n this.unreadCount = 0;\n this.#updateBadge();\n\n const panel = document.createElement('div');\n panel.className = 'twm-notification-history__panel';\n\n // Header\n const header = document.createElement('div');\n header.className = 'twm-notification-history__header';\n header.innerHTML =\n '<span class=\"twm-notification-history__title\">Notifications</span>' +\n '<button class=\"twm-notification-history__clear-btn twm-has-tooltip\" data-tooltip=\"Clear all\" aria-label=\"Clear all\">' +\n '<span class=\"material-symbols-outlined\">delete_sweep</span>' +\n '</button>' +\n '<button class=\"twm-notification-history__close-btn twm-has-tooltip\" data-tooltip=\"Close\" aria-label=\"Close\">' +\n '<span class=\"material-symbols-outlined\">close</span>' +\n '</button>';\n panel.appendChild(header);\n\n // List\n const list = document.createElement('div');\n list.className = 'twm-notification-history__list';\n panel.appendChild(list);\n\n this.#renderList(list);\n\n // Wire header buttons\n header.querySelector('.twm-notification-history__close-btn')\n .addEventListener('click', () => this.#closePanel());\n\n header.querySelector('.twm-notification-history__clear-btn')\n .addEventListener('click', () => {\n this.notificationCenter.history.splice(0);\n this.unreadCount = 0;\n this.#updateBadge();\n this.#renderList(list);\n });\n\n // Position and attach\n document.body.appendChild(panel);\n this.#positionPanel(panel);\n\n // Popover lifecycle (same pattern as ValidationStatus)\n const cleanup = () => {\n document.removeEventListener('mousedown', onDocDown, true);\n document.removeEventListener('keydown', onKey, true);\n window.removeEventListener('resize', onResize, true);\n try { panel.remove(); } catch (_) { /* ignore */ }\n this._popoverCleanup = null;\n };\n this._popoverCleanup = cleanup;\n\n // The entries' context menu is outside the panel, and using it is not leaving it.\n const onDocDown = (ev) => {\n if (ev.target.closest?.('.twm-context-menu')) return;\n if (!panel.contains(ev.target) && !this.triggerEl.contains(ev.target)) cleanup();\n };\n // Escape closes the innermost layer: an open entry menu closes itself.\n const onKey = (ev) => {\n if (ev.key === 'Escape' && !document.querySelector('.twm-context-menu')) cleanup();\n };\n const onResize = () => cleanup();\n\n document.addEventListener('mousedown', onDocDown, true);\n document.addEventListener('keydown', onKey, true);\n window.addEventListener('resize', onResize, true);\n }\n\n #renderList(listEl) {\n listEl.innerHTML = '';\n const history = this.notificationCenter?.history ?? [];\n\n if (history.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'twm-notification-history__empty';\n empty.textContent = 'No notifications';\n listEl.appendChild(empty);\n return;\n }\n\n // Reverse chronological\n const fragment = document.createDocumentFragment();\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i];\n const item = document.createElement('div');\n const severity = entry.severity || 'info';\n item.className = `twm-notification-history__item twm-notification-history__item--${severity}`;\n\n const itemHeader = document.createElement('div');\n itemHeader.className = 'twm-notification-history__item-header';\n\n if (entry.title) {\n const titleEl = document.createElement('span');\n titleEl.className = 'twm-notification-history__item-title';\n titleEl.textContent = entry.title;\n itemHeader.appendChild(titleEl);\n }\n\n const timeEl = document.createElement('span');\n timeEl.className = 'twm-notification-history__item-time';\n timeEl.textContent = this.#formatTime(entry.timestamp);\n itemHeader.appendChild(timeEl);\n\n item.appendChild(itemHeader);\n\n const body = document.createElement('div');\n body.className = 'twm-notification-history__item-body';\n body.textContent = entry.message || '';\n item.appendChild(body);\n item.addEventListener('contextmenu', (event) => showNotificationMenu(event, entry, this.logger));\n\n fragment.appendChild(item);\n }\n listEl.appendChild(fragment);\n }\n\n #positionPanel(panel) {\n if (!this.triggerEl) return;\n\n const triggerRect = this.triggerEl.getBoundingClientRect();\n const panelWidth = panel.getBoundingClientRect().width;\n const gap = 8;\n\n let left = triggerRect.right - panelWidth;\n\n // Clamp horizontally to the viewport.\n const vw = window.innerWidth;\n left = Math.max(8, Math.min(left, vw - panelWidth - 8));\n\n // Anchor by the panel's BOTTOM edge, pinned just above the bell.\n // Anchoring by `top` leaves the box floating when its content shrinks\n // (notifications cleared/removed): the top stays put while the bottom\n // lifts away from the bell, stranding the panel in mid-air. Pinning\n // the bottom keeps it glued to the bottom bar and lets it grow/shrink\n // upward \u2014 no repositioning needed on re-render.\n const bottom = window.innerHeight - (triggerRect.top - gap);\n\n // Never let the panel run off the top of the viewport: cap its height\n // to the space above the bell (within the design max). The list\n // scrolls within whatever remains.\n const available = triggerRect.top - gap - 8;\n panel.style.maxHeight = `${Math.max(0, Math.min(420, Math.round(available)))}px`;\n\n panel.style.left = `${Math.round(left)}px`;\n panel.style.bottom = `${Math.round(bottom)}px`;\n panel.style.top = 'auto';\n }\n\n #formatTime(timestamp) {\n if (!timestamp) return '';\n const d = new Date(timestamp);\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n}\n", "/**\n * recent_items.js \u2014 a most-recent-first list kept through the Host's `state`\n * capability, so it survives a restart.\n *\n * const recent = createRecentItems({ host, key: 'recent-workspaces' });\n * await recent.load();\n * recent.add({ id: 'w1', name: 'North' });\n * recent.list(); // [{ id: 'w1', name: 'North', openedAt: 1730... }]\n *\n * An entry is any plain object; `identity` says which two are the same one, and\n * `add` stamps `openedAt`. `capacity` is per `groupOf(entry)` when that is\n * given, so one busy kind of entry never pushes another kind out.\n *\n * \u2550\u2550 A READ THAT FAILS IS NOT AN EMPTY LIST \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A `host.state.read` that rejects says nothing about what is stored, so until\n * a read succeeds the stored list is never written: writing would replace\n * entries nobody has seen. Changes made in the meantime show in `list()` at\n * once, are kept, are replayed onto the stored list when it is read, and each\n * of them asks for the read again. A read that answers something other than an\n * array is a read: the store is empty.\n *\n * Writes run one at a time and the last one carries the latest list, because a\n * host may answer them out of order and the older list must not win.\n *\n * A host with no `state` capability keeps the list in memory for this session.\n */\n\n/**\n * @param {object} options\n * @param {object} options.host - The Host; its `state` keeps the list\n * @param {string} options.key - The state key the list is stored under\n * @param {(entry: object) => string} [options.identity] - Which entries are the same one\n * @param {(entry: unknown) => boolean} [options.isValid] - Stored entries that fail this\n * are dropped on read, as is one that makes it, `identity` or `groupOf` throw, so\n * `identity` may assume an entry's shape.\n * @param {number} [options.capacity=10] - The most entries kept, per group\n * @param {(entry: object) => string} [options.groupOf] - Groups the capacity counts within\n * @param {() => void} [options.onChange] - After every change, and after a read that\n * replayed changes\n * @param {object} [options.logger] - Its `warn` hears a failed read or write\n */\nexport function createRecentItems({\n host,\n key,\n identity = (entry) => entry.id,\n isValid = (entry) => !!entry && typeof entry === 'object' && !!identity(entry),\n capacity = 10,\n groupOf = () => '',\n onChange = null,\n logger = null,\n}) {\n const state = host?.state ?? null;\n let entries = [];\n let loaded = !state;\n /** The changes made while the stored list is unread, oldest first: list => list. */\n let pending = [];\n let reading = null;\n let writing = false;\n let writeAgain = false;\n\n const capped = (list) => {\n const counts = new Map();\n return list.filter((entry) => {\n const group = groupOf(entry);\n const count = (counts.get(group) ?? 0) + 1;\n counts.set(group, count);\n return count <= capacity;\n });\n };\n\n const without = (list, entry) => {\n const id = identity(entry);\n return list.filter((other) => identity(other) !== id);\n };\n\n async function write() {\n if (!state) return;\n if (writing) {\n writeAgain = true;\n return;\n }\n writing = true;\n do {\n writeAgain = false;\n try {\n await state.write(key, entries);\n } catch (err) {\n logger?.warn?.(`Could not save the recent list \"${key}\"`, err);\n }\n } while (writeAgain);\n writing = false;\n }\n\n /** A stored entry the list can hold: everything it goes through accepts it. */\n const usable = (entry) => {\n try {\n if (!isValid(entry)) return false;\n identity(entry);\n groupOf(entry);\n return true;\n } catch (err) {\n logger?.warn?.(`Dropped an unreadable entry of the recent list \"${key}\"`, err);\n return false;\n }\n };\n\n async function read() {\n let stored;\n try {\n const saved = await state.read(key);\n stored = Array.isArray(saved) ? capped(saved.filter(usable)) : [];\n } catch (err) {\n logger?.warn?.(`Could not read the recent list \"${key}\"; the stored list is left unchanged until it can be read`, err);\n return false;\n }\n const replay = pending;\n pending = [];\n loaded = true;\n entries = replay.reduce((list, apply) => apply(list), stored);\n if (replay.length > 0) {\n onChange?.();\n void write();\n }\n return true;\n }\n\n /**\n * Read the stored list. Call it once at startup, before anything lists; a\n * change made while the list is unread calls it again. Once a read has\n * succeeded it does not read again.\n * @returns {Promise<boolean>} Whether the stored list has been read\n */\n function load() {\n if (!state) return Promise.resolve(false);\n if (loaded) return Promise.resolve(true);\n reading ??= read().finally(() => { reading = null; });\n return reading;\n }\n\n function change(apply) {\n entries = apply(entries);\n onChange?.();\n if (loaded) {\n void write();\n return;\n }\n pending.push(apply);\n void load();\n }\n\n return Object.freeze({\n load,\n /** @returns {ReadonlyArray<object>} Most recent first */\n list: () => Object.freeze(entries.map((entry) => Object.freeze({ ...entry }))),\n /** Put an entry at the top, dropping the older one with its identity. */\n add(entry) {\n const stamped = { ...entry, openedAt: Date.now() };\n change((list) => capped([stamped, ...without(list, stamped)]));\n },\n /** Drop the entry with this one's identity. */\n remove(entry) {\n change((list) => without(list, entry));\n },\n clear() {\n change(() => []);\n },\n });\n}\n", "/**\n * record_list.js \u2014 A READ-ONLY LIST OF RECORDS, each drawn as two lines: a\n * name, and under it a quiet line of facts; beside them pills and verbs.\n * (0.7.0)\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\u2500\u2500\u2500\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 ETL loader [paused] Resume Revoke \u2502\n * \u2502 tblk_8f2 \u2014 acts with the account \u2014 last used 5 Oct \u2502\n * \u2502 Resume: This key is revoked, and revoking cannot be undone. \u2502\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\u2500\u2500\u2500\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 * It is the shape an administration screen reaches for when a table would\n * be wrong: few records, each with its own verbs, read top to bottom rather\n * than sorted and filtered. Before this component every consumer built it by\n * hand, row by row, and each copy grew its own post-build loop to put a key\n * or a state on the row afterwards. Here the record's key, its classes and\n * its attributes are declared, and the list owns the rest.\n *\n * WHAT A RECORD SAYS ABOUT ITSELF (`describe(record, idx)`, or the record\n * itself when there is no `describe`):\n *\n * {\n * name: 'ETL loader' | Node, the first line\n * mono: true, the name in the monospace face\n * facts: ['tblk_8f2', null, 'last used 5 Oct'] | 'text' | Node,\n * the quiet line; null/'' parts\n * are left out, the rest joined\n * with `factSeparator`\n * pills: ['paused', {text: 'URL', tone: 'danger', title: '\u2026'}],\n * verbs: [{label: 'Resume', onClick(record, ev), refusal: '\u2026' | null,\n * danger, primary, icon, title, name}],\n * state: 'paused' | 'off' | 'dead' | 'error' | 'active' | any word \u2014\n * `data-state` and `twm-record--state-<word>` on the row,\n * error: 'The last delivery failed: 503' | Node, a line in the error colour\n * key: 'k-1', overrides `getKey`\n * }\n *\n * A REFUSED VERB IS A DISABLED BUTTON AND A SENTENCE ON THE SCREEN. The\n * reason is on the button's `title` and `data-refusal` too, but a reason only\n * on a tooltip reads as \"the button does nothing\" \u2014 nobody hovers a button\n * they believe they have just pressed. So each distinct reason is a line of\n * its own under the facts, named by the verbs it refuses\n * (`data-refusal-for`), and the button is `aria-describedby` that line.\n *\n * OPENING A RECORD (`onActivate`) follows DataTable's `onRowActivate` rule,\n * from the same module (`row_activation.js`): a press on a control in the\n * row is that control's, a click that ends a drag selecting text opens\n * nothing, and neither does the second click of a double-click.\n *\n * THE KEYBOARD. With `onActivate` (or `keyboard: true`) the RECORDS are one\n * tab stop \u2014 the one last focused, else the open one, else the first \u2014 and\n * each enabled verb keeps its own, so every verb is reachable by Tab.\n * ArrowUp/ArrowDown move between records (from a record or from one of its\n * verbs), Home/End go to the ends, and Enter on a record opens it. Enter on a\n * verb is the verb's.\n */\nimport { isRowActivation, isRowControl } from './row_activation.js';\n\n/** A field, a select or editable text keeps its own arrow keys. */\nconst OWN_ARROWS = 'input, select, textarea, [contenteditable=\"\"], [contenteditable=\"true\"]';\n\n/** The words a tone may be, after sanitising (`[^\\w-]` dropped). */\nconst safeWord = (s) => String(s).replace(/[^\\w-]/g, '');\n\nlet SEQ = 0;\n\n/**\n * @typedef {Object} RecordVerb\n * @property {string} label - The button's words.\n * @property {Function} [onClick] - `(record, ev) => void`.\n * @property {string|null} [refusal] - Why it cannot be pressed. A disabled\n * button, and the sentence drawn under the record's facts.\n * @property {boolean} [danger]\n * @property {boolean} [primary]\n * @property {string} [icon] - A Material Symbols name, drawn before the label.\n * @property {string} [title] - A tooltip, for a verb that is NOT refused.\n * @property {string} [name] - A stable id: `data-verb`, and what focus is\n * restored to after a redraw. Defaults to the label.\n */\n\n/**\n * @typedef {Object} RecordListConfig\n * @property {Array} [records=[]]\n * @property {Function} [describe] - `(record, idx) => spec`. Without it the\n * record is its own spec.\n * @property {Function} [getKey] - `(record, idx) => string|number`. Defaults to\n * `spec.key`, then `record.key`, then `record.id`, then the index.\n * @property {Function} [onActivate] - `(record, idx, ev) => void`. Opens a record.\n * @property {string|string[]} [activateOn=['click','enter']] - `'click'`,\n * `'dblclick'`, `'enter'`, or several.\n * @property {boolean} [keyboard] - Arrow keys between records. Defaults to on\n * exactly when `onActivate` is set.\n * @property {*} [activeKey] - The record that is open: `twm-record--active`\n * and `aria-current=\"true\"`.\n * @property {Function} [rowClass] - `(record, idx) => string|string[]|null`.\n * @property {Function} [rowAttrs] - `(record, idx) => {name: value}`;\n * `null`/`false` leaves one off, `true` sets it empty.\n * @property {string|Node|Function} [emptyState] - Shown when there are no\n * records. A function is called with no arguments and may return either.\n * @property {string} [factSeparator=' \u2014 ']\n * @property {'wrap'|'ellipsis'} [facts='wrap'] - How a long fact line ends.\n * `'ellipsis'` keeps it to one line and puts the whole line on `title`.\n * @property {string|Function} [verbClass] - The verbs' class names, or\n * `(verb) => string`, for a consumer with its own buttons. Defaults to\n * FlexDesk's `twm-btn` with `--primary`/`--danger`.\n * @property {string} [label] - The list's accessible name (`aria-label`).\n * @property {string} [className] - Added to the root.\n */\n\nexport class RecordList {\n /**\n * @param {HTMLElement|null} host appended to, if given\n * @param {RecordListConfig} [config]\n */\n constructor(host, config = {}) {\n this.config = {\n records: [],\n describe: null,\n getKey: null,\n onActivate: null,\n activateOn: ['click', 'enter'],\n keyboard: undefined,\n activeKey: null,\n rowClass: null,\n rowAttrs: null,\n emptyState: null,\n factSeparator: ' \u2014 ',\n facts: 'wrap',\n verbClass: null,\n label: null,\n className: null,\n ...config,\n };\n this._records = Array.isArray(this.config.records) ? this.config.records.slice() : [];\n this._activeKey = this.config.activeKey ?? null;\n this._tabKey = null;\n this._items = new Map(); // key \u2192 <li>\n this._disposed = false;\n this._id = `twm-record-list-${++SEQ}`;\n\n const root = document.createElement('div');\n root.className = 'twm-record-list'\n + (this.config.facts === 'ellipsis' ? ' twm-record-list--clip' : '')\n + (this._activates() ? ' twm-record-list--clickable' : '')\n + (this.config.className ? ` ${this.config.className}` : '');\n const list = document.createElement('ul');\n list.className = 'twm-record-list__items';\n if (this.config.label) list.setAttribute('aria-label', this.config.label);\n root.appendChild(list);\n this.element = root;\n this.listElement = list;\n\n this._onClick = (ev) => this._gesture(ev, 'click');\n this._onDblClick = (ev) => this._gesture(ev, 'dblclick');\n this._onKeyDown = (ev) => this._key(ev);\n // Only focus ON a record moves the tab stop. Focus on one of its verbs\n // must not: Tab walks forward through the verbs of the records before\n // the stop, and moving the stop behind the focus would leave no record\n // ahead to Tab to (measured in Edge).\n this._onFocusIn = (ev) => {\n const li = this._itemOf(ev.target);\n if (li && ev.target === li) this._setTabStop(li.__recordKey);\n };\n list.addEventListener('click', this._onClick);\n list.addEventListener('dblclick', this._onDblClick);\n list.addEventListener('keydown', this._onKeyDown);\n list.addEventListener('focusin', this._onFocusIn);\n\n this._draw();\n if (host) host.appendChild(root);\n }\n\n // \u2500\u2500 public \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Replace the records and draw them. Focus inside the list is kept on\n * the same record, and on the same verb of it, when it is still there. */\n setRecords(records) {\n if (this._disposed) return;\n this._records = Array.isArray(records) ? records.slice() : [];\n this._draw();\n }\n\n /** The records, as last given. */\n getRecords() {\n return this._records.slice();\n }\n\n /** Draw ONE record again (`describe` asked afresh), or every one with no key. */\n refresh(key) {\n if (this._disposed) return;\n if (key === undefined) { this._draw(); return; }\n const old = this._items.get(this._norm(key));\n if (!old) return;\n const idx = old.__recordIndex;\n const focus = this._focusMemo();\n const fresh = this._item(this._records[idx], idx);\n old.replaceWith(fresh);\n this._items.set(fresh.__recordKey, fresh);\n this._paintTabStop();\n this._restoreFocus(focus);\n }\n\n /** Mark the record that is open (`null` for none). */\n setActiveKey(key) {\n this._activeKey = key ?? null;\n for (const li of this._items.values()) this._paintActive(li);\n if (this._activeKey !== null && this._items.has(this._norm(this._activeKey))) {\n this._setTabStop(this._norm(this._activeKey));\n }\n }\n\n getActiveKey() {\n return this._activeKey;\n }\n\n /** The `<li>` drawn for a key, or null. */\n getItem(key) {\n return this._items.get(this._norm(key)) || null;\n }\n\n /** Move the keyboard focus to a record. */\n focusRecord(key) {\n const li = this.getItem(key);\n if (!li) return false;\n this._setTabStop(li.__recordKey);\n li.focus();\n return true;\n }\n\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n const list = this.listElement;\n list.removeEventListener('click', this._onClick);\n list.removeEventListener('dblclick', this._onDblClick);\n list.removeEventListener('keydown', this._onKeyDown);\n list.removeEventListener('focusin', this._onFocusIn);\n this._items.clear();\n this.element.remove();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _activates() {\n return typeof this.config.onActivate === 'function';\n }\n\n _keyboard() {\n return this.config.keyboard ?? this._activates();\n }\n\n _gestures() {\n const g = this.config.activateOn;\n return new Set(Array.isArray(g) ? g : [g]);\n }\n\n /** Keys compare as strings: a record keyed `7` and an `activeKey` of `'7'` are one. */\n _norm(key) {\n return key === null || key === undefined ? key : String(key);\n }\n\n _spec(record, idx) {\n const { describe } = this.config;\n const spec = typeof describe === 'function' ? describe(record, idx) : record;\n return spec && typeof spec === 'object' ? spec : { name: spec };\n }\n\n _keyOf(record, idx, spec) {\n const { getKey } = this.config;\n let key;\n if (spec.key !== undefined && spec.key !== null) key = spec.key;\n else if (typeof getKey === 'function') key = getKey(record, idx);\n else if (record && typeof record === 'object' && (record.key ?? record.id) != null) key = record.key ?? record.id;\n else key = idx;\n return String(key);\n }\n\n _draw() {\n const focus = this._focusMemo();\n const list = this.listElement;\n list.replaceChildren();\n this._items.clear();\n this.element.querySelector(':scope > .twm-record-list__empty')?.remove();\n\n this._records.forEach((record, idx) => {\n const li = this._item(record, idx);\n if (this._items.has(li.__recordKey)) {\n console.error(`[RecordList] two records share the key \"${li.__recordKey}\"`);\n }\n this._items.set(li.__recordKey, li);\n list.appendChild(li);\n });\n this.element.classList.toggle('twm-record-list--empty', this._records.length === 0);\n if (!this._records.length) this._drawEmpty();\n this._paintTabStop();\n this._restoreFocus(focus);\n }\n\n _drawEmpty() {\n let content = this.config.emptyState;\n if (typeof content === 'function') content = content();\n if (content == null || content === false || content === '') return;\n const p = document.createElement('p');\n p.className = 'twm-record-list__empty';\n if (typeof Node !== 'undefined' && content instanceof Node) p.appendChild(content);\n else p.textContent = String(content);\n this.element.appendChild(p);\n }\n\n _item(record, idx) {\n const spec = this._spec(record, idx);\n const key = this._keyOf(record, idx, spec);\n const li = document.createElement('li');\n li.className = 'twm-record';\n li.__record = record;\n li.__recordIndex = idx;\n li.__recordKey = key;\n li.dataset.recordKey = key;\n if (this._keyboard()) li.tabIndex = -1;\n if (spec.state) {\n li.dataset.state = safeWord(spec.state);\n li.classList.add(`twm-record--state-${safeWord(spec.state)}`);\n }\n\n const main = document.createElement('div');\n main.className = 'twm-record__main';\n const name = document.createElement('div');\n name.className = 'twm-record__name' + (spec.mono ? ' twm-record__name--mono' : '');\n appendContent(name, spec.name);\n main.appendChild(name);\n\n const factsText = this._facts(spec.facts);\n if (factsText !== null) {\n const facts = document.createElement('div');\n facts.className = 'twm-record__facts';\n appendContent(facts, factsText);\n if (this.config.facts === 'ellipsis') facts.title = facts.textContent;\n main.appendChild(facts);\n }\n if (spec.error != null && spec.error !== false && spec.error !== '') {\n const err = document.createElement('div');\n err.className = 'twm-record__error';\n appendContent(err, spec.error);\n main.appendChild(err);\n }\n li.appendChild(main);\n\n const pills = (spec.pills || []).filter((p) => p != null && p !== false && p !== '');\n if (pills.length) {\n const box = document.createElement('div');\n box.className = 'twm-record__pills';\n for (const p of pills) box.appendChild(pill(p));\n li.appendChild(box);\n }\n\n const verbs = (spec.verbs || []).filter(Boolean);\n if (verbs.length) {\n const box = document.createElement('div');\n box.className = 'twm-record__verbs';\n const reasons = new Map(); // sentence \u2192 [labels]\n for (const v of verbs) {\n const b = this._verb(v, record);\n box.appendChild(b);\n if (v.refusal) {\n const said = String(v.refusal);\n if (!reasons.has(said)) reasons.set(said, { labels: [], buttons: [] });\n reasons.get(said).labels.push(v.label);\n reasons.get(said).buttons.push(b);\n }\n }\n li.appendChild(box);\n if (reasons.size) {\n const lines = document.createElement('div');\n lines.className = 'twm-record__refusals';\n let n = 0;\n for (const [said, { labels, buttons }] of reasons) {\n const line = document.createElement('div');\n line.className = 'twm-record__refusal';\n line.id = `${this._id}-r${idx}-${n++}`;\n line.dataset.refusalFor = labels.join(', ');\n line.textContent = labels.length === verbs.length && verbs.length > 1\n ? said : `${labels.join(', ')}: ${said}`;\n for (const b of buttons) b.setAttribute('aria-describedby', line.id);\n lines.appendChild(line);\n }\n main.appendChild(lines);\n }\n }\n\n this._decorate(li, record, idx);\n return li;\n }\n\n _facts(facts) {\n if (facts == null || facts === false) return null;\n if (typeof Node !== 'undefined' && facts instanceof Node) return facts;\n if (!Array.isArray(facts)) {\n const s = String(facts);\n return s === '' ? null : s;\n }\n const parts = facts.filter((f) => f != null && f !== false && f !== '');\n if (!parts.length) return null;\n if (parts.every((p) => !(typeof Node !== 'undefined' && p instanceof Node))) {\n return parts.map(String).join(this.config.factSeparator);\n }\n const frag = document.createDocumentFragment();\n parts.forEach((p, i) => {\n if (i) frag.appendChild(document.createTextNode(this.config.factSeparator));\n appendContent(frag, p);\n });\n return frag;\n }\n\n _verb(v, record) {\n const b = document.createElement('button');\n b.type = 'button';\n const { verbClass } = this.config;\n b.className = typeof verbClass === 'function' ? String(verbClass(v) || '')\n : typeof verbClass === 'string' ? verbClass\n : 'twm-btn' + (v.primary ? ' twm-btn--primary' : '') + (v.danger ? ' twm-btn--danger' : '');\n b.classList.add('twm-record__verb');\n b.dataset.verb = String(v.name ?? v.label);\n if (v.icon) {\n const glyph = document.createElement('span');\n glyph.className = 'material-symbols-outlined twm-record__verb-icon';\n glyph.setAttribute('aria-hidden', 'true');\n glyph.textContent = String(v.icon);\n b.appendChild(glyph);\n }\n const label = document.createElement('span');\n label.className = 'twm-record__verb-label';\n label.textContent = String(v.label ?? '');\n b.appendChild(label);\n if (v.refusal) {\n b.disabled = true;\n b.title = String(v.refusal);\n b.dataset.refusal = String(v.refusal);\n } else {\n if (v.title) b.title = String(v.title);\n if (typeof v.onClick === 'function') b.addEventListener('click', (ev) => v.onClick(record, ev));\n }\n return b;\n }\n\n _decorate(li, record, idx) {\n const { rowClass, rowAttrs } = this.config;\n if (typeof rowClass === 'function') {\n const c = rowClass(record, idx);\n const list = Array.isArray(c) ? c : String(c ?? '').split(/\\s+/);\n for (const name of list) if (name) li.classList.add(String(name));\n }\n if (typeof rowAttrs === 'function') {\n for (const [name, value] of Object.entries(rowAttrs(record, idx) || {})) {\n if (value == null || value === false) continue;\n try {\n li.setAttribute(name, value === true ? '' : String(value));\n } catch (err) {\n console.error(`[RecordList] rowAttrs: bad attribute \"${name}\"`, err);\n }\n }\n }\n this._paintActive(li);\n }\n\n _paintActive(li) {\n const on = this._activeKey !== null && li.__recordKey === this._norm(this._activeKey);\n li.classList.toggle('twm-record--active', on);\n if (on) {\n if (li.getAttribute('aria-current') !== 'true') {\n li.setAttribute('aria-current', 'true');\n li.__twmAriaCurrent = true;\n }\n } else if (li.__twmAriaCurrent) {\n li.__twmAriaCurrent = false;\n li.removeAttribute('aria-current');\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\u2500\u2500\u2500\u2500\u2500\n\n /** The ONE record that takes Tab: the one last focused, else the open\n * one, else the first. */\n _paintTabStop() {\n if (!this._keyboard()) return;\n let key = this._tabKey;\n if (key === null || !this._items.has(key)) {\n const active = this._norm(this._activeKey);\n key = active !== null && this._items.has(active) ? active : (this._items.keys().next().value ?? null);\n }\n this._setTabStop(key);\n }\n\n _setTabStop(key) {\n if (!this._keyboard()) return;\n this._tabKey = key ?? null;\n for (const [k, li] of this._items) li.tabIndex = k === this._tabKey ? 0 : -1;\n }\n\n _focusMemo() {\n const doc = this.element.ownerDocument;\n const active = doc?.activeElement;\n if (!active || !this.listElement.contains(active)) return null;\n const li = this._itemOf(active);\n if (!li) return null;\n return { key: li.__recordKey, verb: active.closest('.twm-record__verb')?.dataset.verb ?? null };\n }\n\n _restoreFocus(memo) {\n if (!memo) return;\n const li = this._items.get(memo.key);\n if (!li) return;\n if (memo.verb !== null) {\n const b = [...li.querySelectorAll('.twm-record__verb')].find((x) => x.dataset.verb === memo.verb);\n if (b && !b.disabled) { b.focus(); return; }\n }\n if (this._keyboard()) { this._setTabStop(li.__recordKey); li.focus(); }\n }\n\n _itemOf(target) {\n const li = target?.closest?.('.twm-record');\n return li && this.listElement.contains(li) && li.parentNode === this.listElement ? li : null;\n }\n\n // \u2500\u2500 gestures \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _gesture(ev, gesture) {\n if (!this._activates() || !this._gestures().has(gesture)) return;\n const li = this._itemOf(ev.target);\n if (!li) return;\n if (!isRowActivation(ev, gesture, { scope: this.listElement })) return;\n this.config.onActivate(li.__record, li.__recordIndex, ev);\n }\n\n _key(ev) {\n if (ev.defaultPrevented) return;\n const li = this._itemOf(ev.target);\n if (!li) return;\n if (ev.key === 'Enter') {\n // Enter on a verb is the verb's; only Enter on the record itself opens it.\n if (ev.target !== li || !this._activates() || !this._gestures().has('enter')) return;\n if (ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey) return;\n ev.preventDefault();\n this.config.onActivate(li.__record, li.__recordIndex, ev);\n return;\n }\n if (!this._keyboard()) return;\n if (ev.target !== li && (ev.target.closest(OWN_ARROWS) || !isRowControl(ev.target, li))) return;\n const items = [...this._items.values()];\n const at = items.indexOf(li);\n let next = null;\n if (ev.key === 'ArrowDown') next = items[Math.min(items.length - 1, at + 1)];\n else if (ev.key === 'ArrowUp') next = items[Math.max(0, at - 1)];\n else if (ev.key === 'Home') next = items[0];\n else if (ev.key === 'End') next = items[items.length - 1];\n else return;\n ev.preventDefault();\n if (next) {\n this._setTabStop(next.__recordKey);\n next.focus();\n }\n }\n}\n\n/**\n * Build a record list, append it to `host` (if given) and draw it.\n *\n * @param {HTMLElement|null} host\n * @param {RecordListConfig} [config]\n * @returns {RecordList}\n */\nexport function createRecordList(host, config = {}) {\n return new RecordList(host, config);\n}\n\n/** One pill: a string, or `{text, tone, title}`. A tone is a word\n * (`muted`, `info`, `success`, `warn`, `danger` are drawn). */\nfunction pill(p) {\n const s = typeof p === 'object' && !(typeof Node !== 'undefined' && p instanceof Node) ? p : { text: p };\n const span = document.createElement('span');\n span.className = 'twm-record__pill' + (s.tone ? ` twm-record__pill--${safeWord(s.tone)}` : '');\n if (typeof Node !== 'undefined' && s.text instanceof Node) span.appendChild(s.text);\n else if (typeof Node !== 'undefined' && p instanceof Node) span.appendChild(p);\n else span.textContent = String(s.text ?? '');\n if (s.title) span.title = String(s.title);\n if (s.tone) span.dataset.tone = safeWord(s.tone);\n return span;\n}\n\n/** Text, a node or nothing, into `el`. */\nfunction appendContent(el, content) {\n if (content == null || content === false) return;\n if (typeof Node !== 'undefined' && content instanceof Node) el.appendChild(content);\n else el.appendChild(document.createTextNode(String(content)));\n}\n", "/**\n * \u2550\u2550 A STACK OF COLLAPSIBLE SECTIONS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * Inspector-style panel content: titled sections, one above the other, each\n * opened and closed from its header (FlexDesk STORY-0036). Until this, only a\n * tree's categories could collapse, and every embedder that wanted a panel of\n * \"Notes / Assistant / Parameters\" built the headers, the arrows and the\n * remembering itself.\n *\n * const stack = createSectionStack(panel, {\n * sections: [\n * { id: 'notes', title: 'Notes', content: notesEl },\n * { id: 'chat', title: 'Assistant', fill: true,\n * actions: [{ id: 'clear', icon: 'delete', label: 'Clear', onClick: clear }] },\n * { id: 'params', title: 'Parameters', defaultExpanded: false },\n * ],\n * key: 'inspector.sections',\n * stateStore: { read: (key) => saved[key], write: (key, map) => { saved[key] = map; } },\n * });\n * stack.body('chat').appendChild(chatEl);\n * const off = stack.on('toggled', ({ id, expanded }) => \u2026);\n *\n * A SECTION is `{ id, title, icon?, content?, actions?, defaultExpanded?, fill? }`.\n * `content` is a Node put into the section's body at mount; `body(id)` hands\n * the same element over for anything mounted later. `defaultExpanded` is true\n * unless it says otherwise.\n *\n * THE HEADER TOGGLES; ITS ACTIONS DO NOT. A click anywhere on the header opens\n * or closes the section and turns its arrow \u2014 except on one of its `actions`\n * (`{ id?, icon, label, title?, onClick(sectionId, event) }`), which runs its\n * own `onClick` and leaves the section as it was.\n *\n * A FILL SECTION (`fill: true`) takes the height the others leave, and its\n * body scrolls inside it (`min-height: 0`), so a long conversation scrolls in\n * its section instead of growing the panel past the window. Give the stack's\n * container a height \u2014 it is `height: 100%` of it.\n *\n * REMEMBERING is the embedder's: `stateStore` is `{ read(key), write(key, map) }`\n * and `map` is `{ [sectionId]: expanded }`, written whenever a section opens or\n * closes. `read` may answer a promise; until it does, sections show their\n * `defaultExpanded`, and a section somebody toggled meanwhile keeps their\n * choice. Such a toggle is written once the read has settled, merged over\n * the stored map, so the defaults on screen never overwrite it. A store that throws, rejects, or answers something that is not a map\n * leaves every section on its `defaultExpanded` \u2014 remembering is a convenience,\n * never a reason for a panel not to draw. `ready` resolves once the read has\n * been applied (at once without a store).\n *\n * `setVisible(id, false)` takes a section off the stack without forgetting it:\n * `setVisible(id, true)` brings it back open or closed exactly as it was.\n *\n * The `toggled` event carries `{ id, expanded, source }`, `source` being\n * `'user'` (a header click), `'api'` (expand / collapse / toggle) or\n * `'restore'` (a stored state that arrived after mount). It fires only on a\n * change. `on()` answers the function that stops listening.\n *\n * `dispose()` removes the one listener the stack adds and every node it made;\n * `content` the embedder handed in goes with its section.\n *\n * Styled by `.twm-collapsible-*` (the tree's primitive) plus `.twm-section-stack*`.\n */\n\n/**\n * @param {HTMLElement} container\n * @param {object} opts\n * @param {Array} opts.sections `{ id, title, icon?, content?, actions?, defaultExpanded?, fill? }`\n * @param {object} [opts.stateStore] `{ read(key): map|Promise<map>, write(key, map) }`\n * @param {string} [opts.key] the key the expanded states live under; required with a store\n */\nexport function createSectionStack(container, { sections = [], stateStore = null, key = null } = {}) {\n if (stateStore && !key) throw new Error('createSectionStack: a stateStore needs a { key }');\n const doc = container.ownerDocument;\n\n const root = doc.createElement('div');\n root.className = 'twm-section-stack';\n\n /** id -> { def, box, toggle, arrow, body, expanded, visible, touched } */\n const byId = new Map();\n /** action button -> { sectionId, action } */\n const actionOf = new Map();\n /** header -> section id */\n const headerOf = new Map();\n const listeners = new Set();\n let disposed = false;\n // While a promised read is out, the sections nobody touched still show\n // their defaults, not what the store holds: writing them then would\n // overwrite the stored states with defaults. A toggle meanwhile only marks\n // the map as owed; it is written once the read has settled.\n let readPending = false;\n let writeOwed = false;\n\n for (const def of sections) {\n if (!def || def.id == null || byId.has(def.id)) {\n throw new Error(`createSectionStack: every section needs a unique id (got ${def?.id})`);\n }\n const expanded = def.defaultExpanded !== false;\n\n const box = doc.createElement('section');\n box.className = 'twm-collapsible-box twm-section-stack__section'\n + (def.fill ? ' twm-section-stack__section--fill' : '');\n\n const header = doc.createElement('div');\n header.className = 'twm-collapsible-header twm-section-stack__header';\n\n const toggle = doc.createElement('button');\n toggle.type = 'button';\n toggle.className = 'twm-section-stack__toggle';\n const arrow = doc.createElement('span');\n arrow.className = 'twm-collapsible-arrow material-symbols-outlined';\n arrow.setAttribute('aria-hidden', 'true');\n arrow.textContent = 'expand_more';\n toggle.appendChild(arrow);\n if (def.icon) {\n const icon = doc.createElement('span');\n icon.className = 'twm-section-stack__icon material-symbols-outlined';\n icon.setAttribute('aria-hidden', 'true');\n icon.textContent = def.icon;\n toggle.appendChild(icon);\n }\n const title = doc.createElement('span');\n title.className = 'twm-section-stack__title';\n title.textContent = def.title ?? String(def.id);\n toggle.appendChild(title);\n header.appendChild(toggle);\n\n if (Array.isArray(def.actions) && def.actions.length) {\n const bar = doc.createElement('div');\n bar.className = 'twm-section-stack__actions';\n for (const action of def.actions) {\n const btn = doc.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-section-stack__action';\n if (action.label) btn.setAttribute('aria-label', action.label);\n if (action.title ?? action.label) btn.setAttribute('title', action.title ?? action.label);\n const glyph = doc.createElement('span');\n glyph.className = 'material-symbols-outlined';\n glyph.setAttribute('aria-hidden', 'true');\n glyph.textContent = action.icon ?? '';\n btn.appendChild(glyph);\n bar.appendChild(btn);\n actionOf.set(btn, { sectionId: def.id, action });\n }\n header.appendChild(bar);\n }\n\n const body = doc.createElement('div');\n body.className = 'twm-collapsible-content twm-section-stack__body';\n if (def.content) body.appendChild(def.content);\n\n box.append(header, body);\n root.appendChild(box);\n headerOf.set(header, def.id);\n const entry = { def, box, toggle, arrow, body, expanded, visible: true, touched: false };\n byId.set(def.id, entry);\n paint(entry);\n }\n\n function paint(entry) {\n entry.box.classList.toggle('twm-section-stack__section--expanded', entry.expanded);\n entry.body.classList.toggle('visible', entry.expanded);\n entry.arrow.classList.toggle('collapsed', !entry.expanded);\n entry.toggle.setAttribute('aria-expanded', String(entry.expanded));\n entry.box.hidden = !entry.visible;\n }\n\n function emit(detail) {\n for (const fn of [...listeners]) {\n try { fn(detail); } catch (err) { console.error('[section-stack] toggled listener failed', err); }\n }\n }\n\n function persist() {\n if (!stateStore?.write) return;\n if (readPending) { writeOwed = true; return; }\n const map = {};\n for (const [id, entry] of byId) map[id] = entry.expanded;\n write(map);\n }\n\n function write(map) {\n try {\n const pending = stateStore.write(key, map);\n pending?.catch?.(() => { /* storage refused: not ours to fix */ });\n } catch { /* storage refused: not ours to fix */ }\n }\n\n /** Set one section's state; true when it changed. */\n function set(id, expanded, source) {\n const entry = byId.get(id);\n if (disposed || !entry || entry.expanded === expanded) return false;\n entry.expanded = expanded;\n if (source !== 'restore') entry.touched = true;\n paint(entry);\n if (source !== 'restore') persist();\n emit({ id, expanded, source });\n return true;\n }\n\n const isMap = (saved) => !!saved && typeof saved === 'object' && !Array.isArray(saved);\n\n function restore(saved, source) {\n if (disposed || !isMap(saved)) return;\n for (const [id, entry] of byId) {\n if (entry.touched || typeof saved[id] !== 'boolean') continue;\n if (source === 'restore') set(id, saved[id], 'restore');\n else { entry.expanded = saved[id]; paint(entry); }\n }\n }\n\n /** A promised read has settled (`saved` is null when it rejected). */\n function settle(saved) {\n restore(saved, 'restore');\n readPending = false;\n if (!writeOwed) return;\n writeOwed = false;\n // The touched sections over what the store holds \u2014 also after a\n // dispose, which must not lose a choice made before the read answered.\n const map = {};\n for (const [id, entry] of byId) {\n map[id] = !entry.touched && isMap(saved) && typeof saved[id] === 'boolean'\n ? saved[id] : entry.expanded;\n }\n write(map);\n }\n\n function onClick(event) {\n const target = event.target;\n const btn = target?.closest?.('.twm-section-stack__action');\n if (btn && actionOf.has(btn)) {\n const { sectionId, action } = actionOf.get(btn);\n event.stopPropagation();\n try { action.onClick?.(sectionId, event); } catch (err) {\n console.error(`[section-stack] action on \"${sectionId}\" failed`, err);\n }\n return;\n }\n const header = target?.closest?.('.twm-section-stack__header');\n if (!header || !headerOf.has(header)) return;\n const id = headerOf.get(header);\n set(id, !byId.get(id).expanded, 'user');\n }\n root.addEventListener('click', onClick);\n\n // Synchronous stored state is applied before the stack is on screen, so it\n // never flashes the defaults; a promise is applied when it answers.\n let ready = Promise.resolve();\n if (stateStore?.read) {\n let saved = null;\n try { saved = stateStore.read(key); } catch { saved = null; }\n if (saved && typeof saved.then === 'function') {\n readPending = true;\n ready = Promise.resolve(saved)\n .then((value) => settle(value), () => settle(null));\n } else {\n restore(saved, 'mount');\n }\n }\n\n container.appendChild(root);\n\n const need = (id) => {\n if (!byId.has(id)) throw new Error(`createSectionStack: no section \"${id}\"`);\n return byId.get(id);\n };\n\n return {\n root,\n ready,\n /** The section's body element, for content mounted after the stack. */\n body: (id) => need(id).body,\n expand(id) { need(id); set(id, true, 'api'); },\n collapse(id) { need(id); set(id, false, 'api'); },\n toggle(id) { set(id, !need(id).expanded, 'api'); },\n isExpanded: (id) => need(id).expanded,\n /** Off the stack, or back on it \u2014 its expanded state is kept either way. */\n setVisible(id, visible) {\n const entry = need(id);\n entry.visible = !!visible;\n paint(entry);\n },\n isVisible: (id) => need(id).visible,\n /** `on('toggled', fn)` \u2014 answers the function that stops listening. */\n on(event, fn) {\n if (event !== 'toggled') throw new Error(`createSectionStack: no \"${event}\" event`);\n if (disposed) return () => {};\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n root.removeEventListener('click', onClick);\n listeners.clear();\n actionOf.clear();\n headerOf.clear();\n root.remove();\n },\n };\n}\n", "/**\n * createSelect \u2014 A SELECT DRAWN IN THE DOM. (0.18.0)\n *\n * A native `<select>` styles down to its closed box: the list is the operating\n * system's, so it cannot show a glyph or a second line, ignores the tokens and\n * opens at the system's type size. `selectBox` (`choice_controls.js`) is the\n * native one, for a list with nothing to say in a tight strip. This one is for\n * the rest: a trigger showing the current value, over a list whose rows have a\n * glyph, a second line and a hint, under group headings, with a search box and,\n * with `allowNew`, a way to type a value nobody listed.\n *\n * THE VALUE IS NEVER SILENTLY CHANGED. A value in none of the options, or naming a\n * disabled one, stays the value and is shown (a disabled option under its label,\n * any other through `notFound`): a list that arrives late or has moved on must not\n * turn it into something else on the next save. Only `null`, `undefined` and `''`\n * with no option of their own read as \"nothing chosen\", showing `placeholder`.\n *\n * Values keep their type, as in `choice_controls.js`; `loose` lets a stored `'2'`\n * name option `2`.\n *\n * Focus stays on the trigger unless there is a search box, which then holds it.\n * Either way the arrow keys move the highlight, named by `aria-activedescendant`,\n * and Tab closes the list and goes on from the trigger.\n */\nimport { openAnchoredLayer } from './anchored_layer.js';\nimport { fireEvent } from '../utils/fire_event.js';\nimport { choiceSections, filterSections, findChoice, flatChoices, shownValue } from './choice_controls.js';\nimport { createOptionList } from './option_list.js';\n\n/** More options than this and a select draws a search box unless told otherwise. */\nconst SEARCH_ABOVE = 7;\n/** Printable keys within this many ms are one word for the type-ahead. */\nconst TYPEAHEAD_MS = 500;\n\nfunction node(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text !== undefined) n.textContent = String(text);\n return n;\n}\n\nfunction glyphNode(className, text = '') {\n const n = node('span', `material-symbols-outlined ${className}`.trim(), text);\n n.setAttribute('aria-hidden', 'true');\n return n;\n}\n\nconst isEmptyValue = (v) => v === null || v === undefined || v === '';\n\n/**\n * @param {object} config\n * @param {Array|(() => Array)} [config.options] Bare values, `{ value, label?, icon?,\n * description?, hint?, keywords?, disabled?, reason? }`, or `{ group, options }`.\n * A function is read each time the list opens and the trigger is painted, for a\n * list that grows while the page lives.\n * @param {*} [config.value]\n * @param {(value: *, option: object|null) => void} [config.onChange] After the reader\n * chooses a different value. `option` is the entry as you gave it, `null` for a\n * new value (`allowNew`). Not called for `value =` or `setOptions`.\n * @param {string} [config.className] Extra classes on the trigger.\n * @param {string} [config.panelClassName] Extra classes on the list's panel.\n * @param {string} [config.placeholder] Shown while nothing is chosen.\n * @param {string} [config.title] The trigger's tooltip; else it says the value.\n * @param {string} [config.ariaLabel] When no `<label>` names the control.\n * @param {boolean} [config.disabled]\n * @param {boolean} [config.showIcon=true] Draw the chosen option's glyph on the trigger too.\n * @param {boolean|{placeholder?: string}} [config.search] The search box. By default it\n * is there with `allowNew` or more than seven options.\n * @param {boolean} [config.allowNew] A value in no option may be typed into the\n * search box; it is offered as its own row at the end of the list.\n * @param {(typed: string) => string} [config.newLabel] That row's words.\n * @param {(value: string) => string} [config.notFound] How an unlisted value reads on the trigger.\n * @param {(typed: string) => string} [config.emptyText] What a list with no rows says.\n * @param {boolean} [config.loose] A stored value names an option of the same text.\n * @param {string} [config.name] A hidden input of this name carries the value\n * as text, for a surrounding form; it fires a bubbling `change` when the reader chooses.\n * @param {HTMLInputElement} [config.carrier] That hidden input, yours, for a field something\n * finds by more than a name (`[data-f]`, an id). Instead of `name`; its attributes are left as they are.\n * @param {'start'|'end'} [config.align]\n * @returns {{el: HTMLElement, input: HTMLInputElement|null, value: *, isOpen: boolean,\n * setOptions: Function, setPlaceholder: Function, setDisabled: Function,\n * open: Function, close: Function, focus: Function, destroy: Function}}\n * `el` is the control to put in your layout: the trigger, or a wrapper round it\n * and the hidden input when there is a `name` or a `carrier`.\n */\nexport function createSelect({\n options = [], value = null, onChange = null, className = '', panelClassName = '', placeholder = 'Choose\u2026',\n title = '', ariaLabel = '', disabled = false, showIcon = true, search = undefined, allowNew = false,\n newLabel = (typed) => `Use \u201C${typed}\u201D`, notFound = (v) => v,\n emptyText = (typed) => (typed ? `Nothing matches \u201C${typed}\u201D.` : 'Nothing to choose from.'),\n loose = false, name = null, carrier = null, align = 'start',\n} = {}) {\n let source = options;\n let current = value;\n let emptyLabel = placeholder;\n let layer = null;\n let typedKeys = '';\n let typedTimer = null;\n\n const given = () => (typeof source === 'function' ? source() : source) || [];\n\n const trigger = node('button', `twm-select${className ? ` ${className}` : ''}`);\n trigger.type = 'button';\n trigger.setAttribute('role', 'combobox');\n trigger.setAttribute('aria-haspopup', 'listbox');\n trigger.setAttribute('aria-expanded', 'false');\n if (ariaLabel) trigger.setAttribute('aria-label', ariaLabel);\n const icon = glyphNode('twm-select__icon');\n const label = node('span', 'twm-select__label');\n trigger.append(icon, label, glyphNode('twm-select__caret', 'expand_more'));\n\n let root = trigger;\n let hidden = carrier;\n if (name && !hidden) {\n hidden = node('input');\n hidden.type = 'hidden';\n hidden.name = name;\n }\n if (hidden) {\n root = node('div', 'twm-select-field');\n root.append(trigger, hidden);\n }\n\n // Whichever holds focus names the active row.\n let focusHolder = trigger;\n const list = createOptionList({\n onPick: (option) => choose(option),\n onActive: (id) => {\n if (id) focusHolder.setAttribute('aria-activedescendant', id);\n else focusHolder.removeAttribute('aria-activedescendant');\n },\n });\n trigger.setAttribute('aria-controls', list.id);\n\n const panel = node('div', `twm-option-panel${panelClassName ? ` ${panelClassName}` : ''}`);\n const searchRow = node('div', 'twm-option-panel__search');\n searchRow.appendChild(glyphNode('', 'search'));\n const searchInput = node('input', 'twm-option-panel__search-input');\n searchInput.type = 'text';\n searchInput.autocomplete = 'off';\n searchInput.spellcheck = false;\n searchInput.setAttribute('role', 'combobox');\n searchInput.setAttribute('aria-expanded', 'true');\n searchInput.setAttribute('aria-autocomplete', 'list');\n searchInput.setAttribute('aria-controls', list.id);\n searchRow.appendChild(searchInput);\n panel.append(searchRow, list.el);\n\n const hasSearch = () => (search === undefined\n ? allowNew || flatChoices(given()).length > SEARCH_ABOVE\n : !!search);\n\n function paint() {\n const flat = flatChoices(given());\n const chosen = findChoice(flat, current, loose);\n const none = !chosen && isEmptyValue(current);\n label.textContent = chosen ? chosen.label : none ? emptyLabel : notFound(shownValue(current));\n trigger.classList.toggle('twm-select--empty', none);\n trigger.title = title || label.textContent;\n const glyph = showIcon ? (chosen?.icon || '') : '';\n icon.textContent = glyph;\n icon.hidden = !glyph;\n if (hidden) hidden.value = isEmptyValue(current) ? '' : shownValue(current);\n }\n\n /** The rows for what is typed, a new-value row after them when it is offered. */\n function draw(typed) {\n const text = typed.trim();\n const all = choiceSections(given());\n const flat = all.flatMap((s) => s.items);\n const taken = (o) => [o.value, o.label].some((v) => shownValue(v).toLowerCase() === text.toLowerCase());\n const shown = filterSections(all, text);\n if (allowNew && text !== '' && !flat.some(taken)) {\n shown.push({ heading: null, items: [{ value: text, label: newLabel(text), icon: 'add', description: null,\n hint: null, disabled: false, reason: null, keywords: null,\n source: null }] });\n }\n const chosen = findChoice(flat, current, loose);\n if (shown.length) {\n list.setRows(shown, { mark: text, isCurrent: (o) => o === chosen });\n // On the current value when it is showing, else on the first row that may be chosen.\n const at = list.options().indexOf(chosen);\n if (at >= 0 && !chosen.disabled) list.setActive(at);\n else list.moveToEnd(1);\n } else {\n list.setMessage(emptyText(text));\n }\n layer?.place();\n }\n\n function choose(option) {\n const changed = !(option.value === current || (loose && String(option.value) === String(current)));\n current = option.value;\n paint();\n layer?.close('pick');\n if (!changed) return;\n if (hidden) fireEvent(hidden, 'change', { bubbles: true });\n onChange?.(current, option.source);\n }\n\n function open() {\n if (layer || trigger.disabled) return;\n const searching = hasSearch();\n searchRow.hidden = !searching;\n focusHolder = searching ? searchInput : trigger;\n if (searching) {\n const word = (typeof search === 'object' && search?.placeholder)\n || (allowNew ? 'Search, or type a new one\u2026' : 'Search\u2026');\n searchInput.placeholder = word;\n searchInput.setAttribute('aria-label', word);\n searchInput.value = '';\n }\n panel.style.width = '';\n layer = openAnchoredLayer({\n anchor: trigger, el: panel, align, gap: 4, matchWidth: true,\n onClose() {\n layer = null;\n trigger.classList.remove('twm-is-open');\n trigger.setAttribute('aria-expanded', 'false');\n focusHolder.removeAttribute('aria-activedescendant');\n },\n });\n if (!layer) return; // the trigger is not on the page\n trigger.classList.add('twm-is-open');\n trigger.setAttribute('aria-expanded', 'true');\n // Once it is on the page: the current value has to scroll into view.\n draw('');\n if (searching) {\n // PINNED, or the panel narrows and widens under the pointer as each\n // keystroke hides or shows the longest name in it.\n const width = Math.round(panel.getBoundingClientRect().width);\n if (width > 0) panel.style.width = `${width}px`;\n searchInput.focus({ preventScroll: true });\n }\n }\n\n const close = () => layer?.close('closed');\n\n /** Printable keys on a trigger with no search box walk to the label they begin. */\n function typeAhead(ch) {\n clearTimeout(typedTimer);\n typedTimer = setTimeout(() => { typedKeys = ''; }, TYPEAHEAD_MS);\n typedKeys += ch.toLowerCase();\n const at = list.options().findIndex((o) => !o.disabled && o.label.toLowerCase().startsWith(typedKeys));\n if (at >= 0) list.setActive(at);\n }\n\n function onKey(ev) {\n if (ev.isComposing) return;\n const inSearch = ev.target === searchInput;\n if (!layer) {\n if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp' || ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault();\n open();\n }\n return;\n }\n if (ev.key === 'Tab') {\n // Not taken: focus goes back to the trigger, and the Tab goes on from there.\n layer.close('tab');\n return;\n }\n if (ev.key === 'ArrowDown') list.move(1);\n else if (ev.key === 'ArrowUp') list.move(-1);\n else if (ev.key === 'Home' && !inSearch) list.moveToEnd(1);\n else if (ev.key === 'End' && !inSearch) list.moveToEnd(-1);\n else if (ev.key === 'Enter' || (ev.key === ' ' && !inSearch)) {\n const option = list.activeOption();\n if (option) choose(option);\n else if (!inSearch) close();\n } else if (!inSearch && ev.key.length === 1 && !ev.ctrlKey && !ev.metaKey && !ev.altKey) {\n typeAhead(ev.key);\n } else {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n }\n\n trigger.addEventListener('click', () => { if (layer) close(); else open(); });\n trigger.addEventListener('keydown', onKey);\n // Some browsers click a button on Space's keyup whatever its keydown did.\n trigger.addEventListener('keyup', (ev) => { if (ev.key === ' ') ev.preventDefault(); });\n searchInput.addEventListener('keydown', onKey);\n searchInput.addEventListener('input', () => draw(searchInput.value));\n\n function setDisabled(off) {\n trigger.disabled = !!off;\n if (off) close();\n }\n\n paint();\n setDisabled(disabled);\n\n return {\n el: root,\n /** The hidden input carrying the value, when there is one. */\n input: hidden,\n get value() { return current; },\n set value(next) { current = next; paint(); },\n get isOpen() { return !!layer; },\n /** Replace the list. Pass `nextValue` to change the value as well; left out, it stays. */\n setOptions(nextOptions, nextValue) {\n source = nextOptions;\n if (arguments.length > 1) current = nextValue;\n paint();\n if (layer) draw(searchInput.value);\n },\n /** The text shown while nothing is chosen: \"Loading\u2026\", the failure, \"Choose\u2026\". */\n setPlaceholder(text) { emptyLabel = text; paint(); },\n setDisabled,\n open,\n close,\n focus() { trigger.focus(); },\n /** Closes the list and takes the control off the page. */\n destroy() {\n clearTimeout(typedTimer);\n close();\n root.remove();\n },\n };\n}\n", "/**\n * SettingsView \u2014 the settings page, drawn from a settings store's schema.\n *\n * const view = new SettingsView({ store, eventBus }); // the bus the store emits on\n * view.mount(host);\n * view.selectCategory('window');\n * view.setQuery('shadow');\n * view.dispose();\n *\n * // or as tile content:\n * createShell({ content: { settings: settingsViewContent({ store, eventBus }) } });\n *\n * `store` is a `createSettingsStore()` handle, or the app-global binding's own\n * (`getSettingsStore()` in `@flexdesk/core`). The view knows no setting: every\n * category, group, label, description and control comes from the store's\n * `getCategories()` and `getSchema()`.\n *\n * THE LAYOUT. A sidebar with a filter box, the categories in their\n * `CategoryDef.order` and *Reset all*; beside it the chosen category's\n * settings under its title, description and *Reset category*, grouped by\n * `SettingDef.group` in schema order. Each row shows its label, a *Modified*\n * marker while its value differs from its default, its description, its path,\n * its control and a reset button. Text typed in the filter searches every\n * category's labels, descriptions and paths, and the matches are listed\n * under their category and group.\n *\n * THE CONTROLS, one per `SettingDef.type`:\n * boolean a ToggleField\n * select a select over `options`\n * number a number box with `min`, `max` and `step`; a value written is\n * snapped to the step (counted from `min`) and clamped to the range,\n * and a box left empty or unreadable goes back to the value\n * text a text box written `textDebounceMs` after the last keystroke,\n * or at once on Enter or blur; emptied, it writes `null` when the\n * default is `null`, else `''`\n * colorList a ColorListField, written on every committed edit while every\n * row holds a colour\n * A type the view does not know shows the value as text, read only.\n *\n * LIVE, BOTH WAYS. A control writes through `store.set()`. The view listens\n * on `eventBus` for `settings:<path>:changed` for every path in the schema,\n * for `settings:changed` with a null path (the resets) and for\n * `settings:registered` (a slice registered after mount: its categories join\n * the sidebar and its settings their category, without a remount). A value\n * changed elsewhere moves its control and its marker. An edit still being\n * typed (a text before its debounce, digits before 'change') is written\n * before the view redraws or syncs its rows, so it is never dropped.\n *\n * RESETS. A row's reset button resets that setting. *Reset category* and\n * *Reset all* ask `confirm(\u2026)` first (default `openConfirm`) and change\n * nothing unless it resolves true.\n *\n * THE SIDEBAR ELSEWHERE (0.17.2). `sidebar: false` leaves the sidebar out:\n * the view is the content alone. A `SettingsCategories` bound to it, mounted\n * anywhere, draws the filter box, the categories and *Reset all* instead:\n *\n * const view = new SettingsView({ store, eventBus, sidebar: false });\n * view.mount(pageHost);\n * const cats = new SettingsCategories({ view });\n * cats.mount(navigatorHost);\n *\n * Both draw from the view's state, so the filter text and the selected\n * category are the same in both, whichever moved them; `view.subscribe(fn)`\n * tells any other listener. *Reset all* there is `view.resetAll()`, so it asks\n * to confirm as before.\n *\n * Every word on screen that comes from the schema, the store or the user is\n * set as text, so a label or a query holding markup is shown as typed.\n *\n * Markup: `.twm-settings` > `.twm-settings__sidebar` (`__search` >\n * `__search-input`, `__nav` > `button.__cat` [`--active`], `__reset-all`)\n * + `.twm-settings__content` (`__header` > `__title`, `__description`,\n * `__reset-category`; `section.__group` > `__group-title` + `.__row`\n * [`--modified`] > `__info` (`__label`, `__marker`, `__description`,\n * `__path`) + `__control` + `__reset`; `__empty`). A `SettingsCategories` is\n * `.twm-settings-categories` > `.twm-settings__search`, `.twm-settings__nav`\n * and `.twm-settings__reset-all`, the same parts as the sidebar's.\n */\n\nimport { ComponentBase } from '../base/component_base.js';\nimport { ToggleField } from './toggle_field.js';\nimport { ColorListField } from './color_list_field.js';\nimport { selectBox, shownValue } from './choice_controls.js';\nimport { openConfirm } from './modal.js';\n\n/** Milliseconds between the last keystroke in a text setting and its write. */\nexport const SETTINGS_TEXT_DEBOUNCE_MS = 300;\n\nfunction el(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text !== undefined && text !== null) n.textContent = String(text);\n return n;\n}\n\nfunction icon(name) {\n const n = el('span', 'material-symbols-outlined', name);\n n.setAttribute('aria-hidden', 'true');\n return n;\n}\n\nfunction same(a, b) {\n if (a === b) return true;\n if (a == null || b == null) return a == null && b == null;\n if (typeof a !== typeof b || typeof a !== 'object') return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n const ka = Object.keys(a);\n const kb = Object.keys(b);\n return ka.length === kb.length && ka.every((k) => same(a[k], b[k]));\n}\n\n/**\n * A number written by a number row, always both in range and on the step grid\n * (`min + k * step`, or `k * step` with no `min`): snapped to the nearest grid\n * point, and a point outside [min, max] is moved inward to the nearest grid\n * point inside. `min` is itself a grid point, so the range holds none only\n * when `max < min`; the value is then `min`. With no step it is only clamped.\n */\nfunction fitNumber(n, { min, max, step }) {\n const lo = min != null && Number.isFinite(Number(min)) ? Number(min) : null;\n const hi = max != null && Number.isFinite(Number(max)) ? Number(max) : null;\n const s = Number(step);\n if (!(Number.isFinite(s) && s > 0)) {\n let v = n;\n if (hi != null) v = Math.min(hi, v);\n if (lo != null) v = Math.max(lo, v);\n return v;\n }\n const base = lo ?? 0;\n const places = (x) => (String(x).split('.')[1] || '').length;\n const decimals = Math.max(places(s), places(base));\n const at = (k) => Number((base + k * s).toFixed(decimals));\n const EPS = 1e-9;\n let k = Math.round((n - base) / s);\n if (hi != null && at(k) > hi) k = Math.floor((hi - base) / s + EPS);\n if (lo != null && at(k) < lo) k = Math.ceil((lo - base) / s - EPS);\n return at(k);\n}\n\n// \u2500\u2500 the sidebar's parts, drawn alike by SettingsView and SettingsCategories \u2500\u2500\n\n/** The filter box: `{ label, input }`; `onInput(text)` on every keystroke. */\nfunction filterBox(onInput) {\n const label = el('label', 'twm-settings__search');\n const input = el('input', 'twm-settings__search-input');\n input.type = 'search';\n input.placeholder = 'Filter settings\u2026';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.setAttribute('aria-label', 'Filter settings');\n input.addEventListener('input', () => onInput(input.value));\n label.append(icon('search'), input);\n return { label, input };\n}\n\n/** The category list; `onSelect(id)` when a category is clicked. */\nfunction categoryNav(onSelect) {\n const nav = el('nav', 'twm-settings__nav');\n nav.setAttribute('aria-label', 'Settings categories');\n nav.addEventListener('click', (e) => {\n const btn = e.target.closest?.('[data-category]');\n if (btn && nav.contains(btn)) onSelect(btn.dataset.category);\n });\n return nav;\n}\n\n/** Draw `categories` into `nav`, `active` (an id, or null) marked. */\nfunction paintCategories(nav, categories, active) {\n const buttons = categories.map((cat) => {\n const b = el('button', 'twm-settings__cat');\n b.type = 'button';\n b.dataset.category = cat.id;\n if (cat.id === active) {\n b.classList.add('twm-settings__cat--active');\n b.setAttribute('aria-current', 'page');\n }\n b.append(icon(cat.icon || 'tune'), el('span', 'twm-settings__cat-label', cat.label ?? cat.id));\n if (cat.description) b.title = String(cat.description);\n return b;\n });\n nav.replaceChildren(...buttons);\n}\n\n/** The *Reset all* button; `onClick()` when pressed. */\nfunction resetAllButton(onClick) {\n const b = el('button', 'twm-btn twm-settings__reset-all');\n b.type = 'button';\n b.append(icon('restart_alt'), el('span', '', 'Reset all'));\n b.addEventListener('click', () => { onClick(); });\n return b;\n}\n\nexport class SettingsView extends ComponentBase {\n /**\n * @param {object} o\n * @param {object} o.store a settings store (`createSettingsStore()` / `getSettingsStore()`)\n * @param {object} o.eventBus the bus the store emits on\n * @param {Function} [o.confirm] `({title, message, confirmLabel, danger}) -> Promise<boolean>`\n * @param {string} [o.category] the category shown first (default: the first)\n * @param {number} [o.textDebounceMs]\n * @param {string} [o.title='Settings'] the sidebar heading\n * @param {boolean} [o.sidebar=true] false leaves the sidebar (filter,\n * categories, *Reset all*) out, for a `SettingsCategories` elsewhere\n */\n constructor({\n store, eventBus, confirm = openConfirm, category = null,\n textDebounceMs = SETTINGS_TEXT_DEBOUNCE_MS, title = 'Settings', sidebar = true, logger,\n } = {}) {\n super({ eventBus, logger });\n if (!store || typeof store.getSchema !== 'function') {\n throw new TypeError('SettingsView: `store` must be a settings store');\n }\n if (!eventBus || typeof eventBus.on !== 'function') {\n throw new TypeError('SettingsView: `eventBus` must be the bus the store emits on');\n }\n this.store = store;\n this._confirm = confirm;\n this._category = category;\n this._query = '';\n this._debounceMs = textDebounceMs;\n this._title = title;\n this._sidebar = sidebar !== false;\n /** `fn({ category, query })` after the category, the filter or the categories change. */\n this._listeners = new Set();\n\n this.root = null;\n this._nav = null;\n this._content = null;\n this._search = null;\n /** path -> { sync(), flush(), dispose() } for the rows on screen. */\n this._rows = new Map();\n /** path -> the bus subscription handle, for every schema path. */\n this._pathSubs = new Map();\n /** Bus subscription handles for the whole-store events. */\n this._subs = [];\n this._disposed = false;\n }\n\n /** Build the view into `container` (once). */\n mount(container) {\n if (this.root) return this.root;\n const root = el('div', 'twm-settings');\n if (this._sidebar) {\n const side = el('aside', 'twm-settings__sidebar');\n const head = el('div', 'twm-settings__sidebar-title');\n head.append(icon('settings'), el('span', '', this._title));\n const search = filterBox((text) => this.setQuery(text));\n this._search = search.input;\n this._nav = categoryNav((id) => this.selectCategory(id));\n side.append(head, search.label, this._nav, resetAllButton(() => this.resetAll()));\n root.append(side);\n }\n\n const content = el('div', 'twm-settings__content');\n this._content = content;\n root.append(content);\n this.root = root;\n container.appendChild(root);\n this._mounted = true;\n\n for (const path of Object.keys(this.store.getSchema())) this.#watch(path);\n this._subs.push(this.eventBus.on('settings:changed', (p) => {\n if (p?.path == null) this.#syncAll();\n }));\n this._subs.push(this.eventBus.on('settings:registered', (p) => this.#onRegistered(p)));\n\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n return root;\n }\n\n /** The category on screen (its id), or null. */\n getCategory() { return this.#activeCategory()?.id ?? null; }\n\n /** The filter text. */\n getQuery() { return this._query; }\n\n /** True while the filter is in effect (its trimmed text is not empty). */\n isFiltering() { return this.#searching(); }\n\n /**\n * `fn({ category, query })` after every change of the category, the filter\n * or the registered categories, until the view is disposed. Answers the\n * unsubscribe.\n */\n subscribe(fn) {\n this._listeners.add(fn);\n return () => this._listeners.delete(fn);\n }\n\n /** Show one category; clears the filter. */\n selectCategory(id) {\n if (!this.root) return;\n if (!this.store.getCategories().some((c) => c.id === id)) return;\n this._category = id;\n this._query = '';\n if (this._search) this._search.value = '';\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n }\n\n /** Search every category; an empty query goes back to the category. */\n setQuery(query) {\n if (!this.root) return;\n const q = String(query ?? '');\n this._query = q;\n if (this._search && this._search.value !== q) this._search.value = q;\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n }\n\n /** Reset one category after `confirm`; resolves true when it was reset. */\n async resetCategory(id = this.getCategory()) {\n const cat = this.store.getCategories().find((c) => c.id === id);\n if (!cat) return false;\n const ok = await this._confirm({\n title: 'Reset category',\n message: `Reset every setting in \u201C${cat.label ?? cat.id}\u201D to its default?`,\n confirmLabel: 'Reset',\n danger: true,\n });\n if (!ok || this._disposed) return false;\n this.#flushAll();\n this.store.resetCategory(id);\n this.#syncAll();\n return true;\n }\n\n /** Reset every setting after `confirm`; resolves true when they were reset. */\n async resetAll() {\n const ok = await this._confirm({\n title: 'Reset all settings',\n message: 'Reset every setting to its default?',\n confirmLabel: 'Reset all',\n danger: true,\n });\n if (!ok || this._disposed) return false;\n this.#flushAll();\n this.store.resetAll();\n this.#syncAll();\n return true;\n }\n\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n this.#flushAll();\n this.#dropRows();\n for (const sub of this._pathSubs.values()) sub.dispose();\n this._pathSubs.clear();\n for (const sub of this._subs) sub.dispose();\n this._subs = [];\n this.root?.remove();\n this.root = null;\n this._nav = null;\n this._content = null;\n this._search = null;\n this._listeners.clear();\n super.dispose();\n }\n\n // \u2500\u2500 store events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #watch(path) {\n if (this._pathSubs.has(path)) return;\n this._pathSubs.set(path, this.eventBus.on(`settings:${path}:changed`, () => {\n this._rows.get(path)?.sync();\n }));\n }\n\n #onRegistered({ paths = [] } = {}) {\n if (!this.root) return;\n const schema = this.store.getSchema();\n for (const path of Object.keys(schema)) this.#watch(path);\n this.#paintNav();\n const active = this.getCategory();\n const touches = this.#searching()\n || !this._rows.size\n || paths.some((p) => schema[p]?.category === active);\n if (touches) {\n this.#paintContent();\n } else {\n // The slice's defaults may have moved values on screen; an edit still\n // being typed is written first, so the sync shows it rather than drop it.\n this.#flushAll();\n this.#syncAll();\n }\n this.#notify();\n }\n\n /** True while a filter is in effect: the trimmed query is not empty. */\n #searching() {\n return this._query.trim() !== '';\n }\n\n #syncAll() {\n for (const row of this._rows.values()) row.sync();\n }\n\n #flushAll() {\n for (const row of this._rows.values()) row.flush();\n }\n\n #dropRows() {\n for (const row of this._rows.values()) row.dispose();\n this._rows.clear();\n }\n\n // \u2500\u2500 painting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #activeCategory() {\n const cats = this.store.getCategories();\n return cats.find((c) => c.id === this._category) ?? cats[0] ?? null;\n }\n\n #paintNav() {\n if (!this._nav) return;\n paintCategories(this._nav, this.store.getCategories(), this.#searching() ? null : this.getCategory());\n }\n\n /** Tell the listeners, after the content is drawn (it settles the category). */\n #notify() {\n const state = { category: this.getCategory(), query: this._query };\n for (const fn of [...this._listeners]) fn(state);\n }\n\n #paintContent() {\n this.#flushAll();\n this.#dropRows();\n const schema = this.store.getSchema();\n const content = this._content;\n content.replaceChildren();\n\n if (this.#searching()) {\n const q = this._query.trim().toLowerCase();\n const cats = this.store.getCategories();\n const labelOf = new Map(cats.map((c) => [c.id, c.label ?? c.id]));\n const rank = new Map(cats.map((c, i) => [c.id, i]));\n const matches = Object.entries(schema)\n .filter(([path, def]) => [def.label, def.description, path]\n .some((t) => t != null && String(t).toLowerCase().includes(q)))\n .map(([path, def]) => ({ path, ...def }));\n matches.sort((a, b) => (rank.get(a.category) ?? Infinity) - (rank.get(b.category) ?? Infinity));\n\n const header = el('header', 'twm-settings__header');\n const info = el('div', 'twm-settings__header-info');\n const n = matches.length;\n info.append(el('h2', 'twm-settings__title',\n `${n} result${n === 1 ? '' : 's'} for \u201C${this._query.trim()}\u201D`));\n header.append(info);\n content.append(header);\n if (!n) {\n content.append(el('div', 'twm-settings__empty', 'No setting matches the filter.'));\n return;\n }\n this.#paintGroups(matches, (def) =>\n `${labelOf.get(def.category) ?? def.category ?? ''} \u203A ${def.group || 'General'}`);\n return;\n }\n\n const cat = this.#activeCategory();\n if (!cat) {\n content.append(el('div', 'twm-settings__empty', 'No settings.'));\n return;\n }\n // The page drawn is the category: a slice registered later, ordered\n // before it, must not move the sidebar marker or getCategory() off it.\n this._category = cat.id;\n const header = el('header', 'twm-settings__header');\n const info = el('div', 'twm-settings__header-info');\n info.append(el('h2', 'twm-settings__title', cat.label ?? cat.id));\n if (cat.description) info.append(el('p', 'twm-settings__description', cat.description));\n const reset = el('button', 'twm-btn twm-settings__reset-category');\n reset.type = 'button';\n reset.append(icon('restart_alt'), el('span', '', 'Reset category'));\n reset.addEventListener('click', () => { this.resetCategory(cat.id); });\n header.append(info, reset);\n content.append(header);\n\n const defs = Object.entries(schema)\n .filter(([, def]) => def.category === cat.id)\n .map(([path, def]) => ({ path, ...def }));\n if (!defs.length) {\n content.append(el('div', 'twm-settings__empty', 'No settings in this category.'));\n return;\n }\n this.#paintGroups(defs, (def) => def.group || 'General');\n }\n\n #paintGroups(defs, groupTitle) {\n const groups = new Map();\n for (const def of defs) {\n const key = groupTitle(def);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key).push(def);\n }\n for (const [title, list] of groups) {\n const section = el('section', 'twm-settings__group');\n section.append(el('h3', 'twm-settings__group-title', title));\n for (const def of list) section.append(this.#row(def));\n this._content.append(section);\n }\n }\n\n // \u2500\u2500 rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #row(def) {\n const { path } = def;\n const store = this.store;\n const row = el('div', 'twm-settings__row');\n row.dataset.path = path;\n\n const info = el('div', 'twm-settings__info');\n const labelLine = el('div', 'twm-settings__label-line');\n const label = el('span', 'twm-settings__label', def.label ?? path);\n const marker = el('span', 'twm-settings__marker', 'Modified');\n labelLine.append(label, marker);\n info.append(labelLine);\n if (def.description) info.append(el('div', 'twm-settings__description', def.description));\n info.append(el('code', 'twm-settings__path', path));\n\n const slot = el('div', 'twm-settings__control');\n const control = this.#control(def, (value) => store.set(path, value));\n slot.append(control.el);\n\n const reset = el('button', 'twm-settings__reset');\n reset.type = 'button';\n reset.title = 'Reset to default';\n reset.setAttribute('aria-label', `Reset ${def.label ?? path} to default`);\n reset.append(icon('restart_alt'));\n reset.addEventListener('click', () => {\n control.cancel?.();\n store.resetOne(path);\n });\n\n row.append(info, slot, reset);\n\n const sync = () => {\n const value = store.get(path);\n control.show(value);\n const modified = !same(value, store.getDefault(path));\n row.classList.toggle('twm-settings__row--modified', modified);\n marker.hidden = !modified;\n reset.hidden = !modified;\n };\n sync();\n this._rows.set(path, {\n sync,\n flush: () => control.flush?.(),\n dispose: () => control.dispose?.(),\n });\n return row;\n }\n\n /** `{ el, show(value), flush?(), cancel?(), dispose?() }` for one setting. */\n #control(def, write) {\n const name = def.label ?? def.path;\n switch (def.type) {\n case 'boolean': {\n const t = new ToggleField({\n checked: !!this.store.get(def.path), ariaLabel: name, compact: true,\n onChange: (on) => write(on),\n });\n return {\n el: t.render(),\n show: (v) => { if (t.get() !== !!v) t.set(!!v); },\n dispose: () => t.dispose(),\n };\n }\n case 'select': {\n const c = selectBox(def.options || [], this.store.get(def.path), {\n label: name, valueAttr: 'value', className: 'twm-settings__select',\n });\n c.box.addEventListener('change', () => {\n // Redrawn as a fresh mount draws the chosen value, so a stray\n // '(not found)' entry goes once an offered option is picked.\n const v = c.valueOf();\n c.setOptions(def.options || [], v);\n write(v);\n });\n return {\n el: c.box,\n // Redrawn with the new value, as a fresh mount draws it: a\n // value the options lack shows as its '(not found)' entry, and\n // a stray entry left from an earlier value goes.\n show: (v) => { if (!same(c.valueOf(), v)) c.setOptions(def.options || [], v); },\n };\n }\n case 'number': {\n const box = el('input', 'twm-settings__number');\n box.type = 'number';\n box.setAttribute('aria-label', name);\n if (def.min != null) box.min = String(def.min);\n if (def.max != null) box.max = String(def.max);\n if (def.step != null) box.step = String(def.step);\n // Digits typed but not yet committed by 'change'.\n let dirty = false;\n const show = (v) => {\n dirty = false;\n const text = v == null ? '' : String(v);\n if (box.value !== text) box.value = text;\n };\n const commit = () => {\n const current = this.store.get(def.path);\n const n = box.value.trim() === '' ? NaN : Number(box.value);\n if (!Number.isFinite(n)) { show(current); return; }\n const v = fitNumber(n, def);\n show(v);\n if (!same(v, current)) write(v);\n };\n box.addEventListener('input', () => { dirty = true; });\n box.addEventListener('change', commit);\n return {\n el: box,\n show,\n flush: () => { if (dirty) commit(); },\n };\n }\n case 'text': {\n const box = el('input', 'twm-settings__text');\n box.type = 'text';\n box.setAttribute('aria-label', name);\n if (def.placeholder != null) box.placeholder = String(def.placeholder);\n let timer = null;\n const valueOf = () => (box.value === '' && def.defaultValue === null ? null : box.value);\n const cancel = () => { if (timer !== null) { clearTimeout(timer); timer = null; } };\n const commit = () => {\n const v = valueOf();\n if (!same(v, this.store.get(def.path))) write(v);\n };\n const flush = () => {\n if (timer === null) return;\n cancel();\n commit();\n };\n box.addEventListener('input', () => {\n cancel();\n timer = setTimeout(() => { timer = null; commit(); }, this._debounceMs);\n });\n box.addEventListener('change', flush);\n box.addEventListener('keydown', (e) => { if (e.key === 'Enter') flush(); });\n return {\n el: box,\n show: (v) => {\n const text = v == null ? '' : String(v);\n if (box.value === text) return;\n cancel();\n box.value = text;\n },\n flush,\n cancel,\n dispose: cancel,\n };\n }\n case 'colorList': {\n const value = this.store.get(def.path);\n const f = new ColorListField({\n value: Array.isArray(value) ? value : [],\n onChange: (colors, { commit }) => { if (commit && colors) write(colors); },\n });\n return {\n el: f.render(),\n show: (v) => {\n const list = Array.isArray(v) ? v : [];\n if (!same(f.getValue(), list)) f.setValue(list);\n },\n dispose: () => f.dispose(),\n };\n }\n default: {\n const out = el('span', 'twm-settings__readonly');\n return {\n el: out,\n show: (v) => { out.textContent = shownValue(v); },\n };\n }\n }\n }\n}\n\n/**\n * SettingsCategories \u2014 a SettingsView's filter box, category list and\n * *Reset all*, mounted wherever the app wants them (0.17.2).\n *\n * const view = new SettingsView({ store, eventBus, sidebar: false });\n * view.mount(pageHost);\n * const cats = new SettingsCategories({ view });\n * cats.mount(navigatorHost);\n * cats.dispose(); // before or with the view\n *\n * It holds no state of its own: typing in its filter is `view.setQuery()`,\n * clicking a category `view.selectCategory()`, *Reset all* `view.resetAll()`\n * (which asks the view's `confirm` first), and it redraws from the view on\n * every `view.subscribe()` call. So the filter text and the selected category\n * are always the view's, however either side moved them, and a category\n * registered later joins the list. Its clicks and keystrokes act once the\n * view is mounted.\n *\n * Markup: `.twm-settings-categories` > `.twm-settings__search` (>\n * `__search-input`), `.twm-settings__nav` > `button.twm-settings__cat`\n * [`--active`], `.twm-settings__reset-all`.\n */\nexport class SettingsCategories extends ComponentBase {\n /**\n * @param {object} o\n * @param {SettingsView} o.view the view it lists the categories of\n */\n constructor({ view, logger } = {}) {\n if (!(view instanceof SettingsView)) {\n throw new TypeError('SettingsCategories: `view` must be a SettingsView');\n }\n super({ eventBus: view.eventBus, logger });\n this.view = view;\n this.root = null;\n this._search = null;\n this._nav = null;\n this._unsubscribe = null;\n }\n\n /** Build the list into `container` (once). */\n mount(container) {\n if (this.root) return this.root;\n const view = this.view;\n const root = el('div', 'twm-settings-categories');\n const search = filterBox((text) => view.setQuery(text));\n this._search = search.input;\n this._nav = categoryNav((id) => view.selectCategory(id));\n root.append(search.label, this._nav, resetAllButton(() => view.resetAll()));\n this.root = root;\n container.appendChild(root);\n this._mounted = true;\n this._unsubscribe = view.subscribe(() => this.#paint());\n this.#paint();\n return root;\n }\n\n dispose() {\n this._unsubscribe?.();\n this._unsubscribe = null;\n this.root?.remove();\n this.root = null;\n this._search = null;\n this._nav = null;\n super.dispose();\n }\n\n #paint() {\n const view = this.view;\n const q = view.getQuery();\n if (this._search.value !== q) this._search.value = q;\n paintCategories(this._nav, view.store.getCategories(), view.isFiltering() ? null : view.getCategory());\n }\n}\n\n/**\n * A content factory for the shell: `(hostEl, props, ctx) -> { title, destroy }`.\n * `props.category` picks the category shown first.\n *\n * @param {object} opts as `new SettingsView(opts)`\n * @returns {Function}\n */\nexport function settingsViewContent(opts = {}) {\n return (hostEl, props = {}) => {\n const view = new SettingsView({ ...opts, category: props?.category ?? opts.category ?? null });\n view.mount(hostEl);\n return {\n title: opts.title ?? 'Settings',\n view,\n destroy: () => view.dispose(),\n };\n };\n}\n", "/**\n * A range slider with optional companions: a linked number box, a readout, a\n * default with a modified state and a reset button, and an enable toggle.\n *\n * Every companion is opt-in through `field`; with none of them the DOM is the\n * range and the helper line, exactly as before.\n *\n * field.min / max / step / value the range (defaults 0 / 100 / 1 / min)\n * field.numberInput true: an editable number box, two-way synced\n * field.readout true, or (value: number) => string\n * field.defaultValue enables the modified state and a reset button\n * field.toggleable true: an enable checkbox before the slider\n * field.enabled the toggle's initial state (default true)\n * field.disabledValue what onChange reports while toggled off (default null)\n * field.emitOnInput also report every drag frame ({ immediate: true })\n * field.disabled / helperText as before\n *\n * onChange(value, { immediate }) receives the slider's value as a string \u2014 the\n * range input's own value, as it always has \u2014 or `disabledValue` while the\n * toggle is off. A commit that leaves the reported value where it was reports\n * nothing, so setValue/setRange/setEnabled cannot echo back into the caller\n * that drove them.\n */\nexport class SliderField {\n #min = 0;\n #max = 100;\n #step = 1;\n #value = 0;\n #enabled = true;\n #hasDefault = false;\n #defaultValue = 0;\n\n constructor({ fieldId, field = {}, onChange = null, logger = null } = {}) {\n if (!fieldId) {\n throw new Error('SliderField requires a fieldId');\n }\n this.fieldId = fieldId;\n this.field = field;\n this.logger = logger;\n this.onChange = typeof onChange === 'function' ? onChange : null;\n\n this.root = null;\n this.sliderInput = null;\n this.numberInput = null;\n this.readoutEl = null;\n this.resetButton = null;\n this.toggleInput = null;\n this.helperEl = null;\n this.emitOnInput = Boolean(field.emitOnInput ?? field.emitsOnInput);\n this._disposers = [];\n\n this.#min = this.#coerceNumber(field.min, 0);\n this.#max = Math.max(this.#min, this.#coerceNumber(field.max, 100));\n this.#step = this.#coercePositiveNumber(field.step, 1);\n this.#value = this.#fit(this.#coerceNumber(field.value, this.#min));\n this.#enabled = field.toggleable ? field.enabled !== false : true;\n this.#hasDefault = this.#isFiniteInput(field.defaultValue);\n if (this.#hasDefault) {\n this.#defaultValue = this.#fit(Number(field.defaultValue));\n }\n }\n\n render() {\n if (this.root) {\n return this.root;\n }\n this.root = document.createElement('div');\n this.root.className = 'twm-slider-field';\n\n this.sliderInput = document.createElement('input');\n this.sliderInput.type = 'range';\n this.sliderInput.className = 'twm-slider-field__input';\n this.#writeRangeAttributes();\n\n // Prevent parent interactions from interfering with slider dragging\n // Use stopImmediatePropagation to ensure no other handlers on this element run\n // DO NOT call preventDefault - allow native slider drag behavior\n const stopDrag = (evt) => {\n evt.stopPropagation();\n evt.stopImmediatePropagation();\n };\n // Use capture phase to intercept before any parent handlers\n this.#listen(this.sliderInput, 'mousedown', stopDrag, { capture: true });\n this.#listen(this.sliderInput, 'touchstart', stopDrag, { passive: false, capture: true });\n\n this.helperEl = document.createElement('div');\n this.helperEl.className = 'twm-slider-field__helper';\n if (this.field.helperText) {\n this.helperEl.textContent = this.field.helperText;\n }\n\n const companions = this.field.toggleable || this.field.numberInput\n || this.field.readout || this.#hasDefault;\n if (companions) {\n const row = document.createElement('div');\n row.className = 'twm-slider-field__row';\n if (this.field.toggleable) {\n row.appendChild(this.#buildToggle());\n }\n row.appendChild(this.sliderInput);\n if (this.field.readout) {\n this.readoutEl = document.createElement('span');\n this.readoutEl.className = 'twm-slider-field__readout';\n row.appendChild(this.readoutEl);\n }\n if (this.field.numberInput) {\n row.appendChild(this.#buildNumberInput());\n }\n if (this.#hasDefault) {\n row.appendChild(this.#buildResetButton());\n }\n this.root.appendChild(row);\n } else {\n this.root.appendChild(this.sliderInput);\n }\n this.root.appendChild(this.helperEl);\n\n // Throttle onInput to animation frames to avoid re-render stutter while dragging\n let rafToken = null;\n let pendingValue = null;\n const flushPending = () => {\n if (rafToken) {\n cancelAnimationFrame(rafToken);\n rafToken = null;\n }\n if (pendingValue === null) return;\n const valueToEmit = pendingValue;\n pendingValue = null;\n if (this.emitOnInput) {\n this.onChange?.(valueToEmit, { immediate: true });\n }\n };\n\n const handleInput = (event) => {\n // The companions follow the thumb on every frame; onChange waits for release.\n this.#value = this.#fit(Number(event.target.value));\n this.#syncCompanions();\n pendingValue = event.target.value;\n if (!rafToken) {\n rafToken = requestAnimationFrame(() => {\n rafToken = null;\n flushPending();\n });\n }\n };\n const handleChange = (event) => {\n flushPending();\n this.#value = this.#fit(Number(event.target.value));\n this.#syncCompanions();\n this.onChange?.(event.target.value, { immediate: false });\n };\n this.#listen(this.sliderInput, 'input', handleInput);\n this.#listen(this.sliderInput, 'change', handleChange);\n\n this.#syncCompanions();\n return this.root;\n }\n\n /** What onChange would report now: the value as a string, or disabledValue while toggled off. */\n getValue() {\n return this.#enabled ? String(this.#value) : this.#disabledValue();\n }\n\n isEnabled() {\n return this.#enabled;\n }\n\n /** True when a defaultValue was given and the value differs from it. */\n isModified() {\n return this.#hasDefault && this.#value !== this.#defaultValue;\n }\n\n /**\n * Clamp to the range and snap to the step. Reports once, unless `silent` or\n * the reported value did not move. A non-finite value is refused (false).\n */\n setValue(value, { silent = false } = {}) {\n if (!this.#isFiniteInput(value)) {\n return false;\n }\n const numeric = Number(value);\n return this.#commit(() => { this.#value = this.#fit(numeric); }, silent);\n }\n\n setEnabled(enabled, { silent = false } = {}) {\n return this.#commit(() => { this.#enabled = Boolean(enabled); }, silent);\n }\n\n /** Change any of min/max/step; the value and the default are refitted into the new range. */\n setRange({ min, max, step } = {}, { silent = false } = {}) {\n return this.#commit(() => {\n this.#min = this.#isFiniteInput(min) ? Number(min) : this.#min;\n this.#max = Math.max(this.#min, this.#isFiniteInput(max) ? Number(max) : this.#max);\n this.#step = this.#coercePositiveNumber(step, this.#step);\n this.#value = this.#fit(this.#value);\n if (this.#hasDefault) {\n this.#defaultValue = this.#fit(this.#defaultValue);\n }\n if (this.sliderInput) {\n this.#writeRangeAttributes();\n }\n }, silent);\n }\n\n /** Restore defaultValue and report it, a commit like a drag release. */\n reset({ silent = false } = {}) {\n if (!this.#hasDefault) {\n return false;\n }\n return this.#commit(() => { this.#value = this.#defaultValue; }, silent);\n }\n\n dispose() {\n this._disposers.forEach((dispose) => {\n try {\n dispose?.();\n } catch (error) {\n this.logger?.warn?.('twm-slider-field', 'Failed to dispose slider listener', { error });\n }\n });\n this._disposers = [];\n this.root = null;\n this.sliderInput = null;\n this.numberInput = null;\n this.readoutEl = null;\n this.resetButton = null;\n this.toggleInput = null;\n this.helperEl = null;\n }\n\n #buildToggle() {\n this.toggleInput = document.createElement('input');\n this.toggleInput.type = 'checkbox';\n this.toggleInput.className = 'twm-slider-field__toggle';\n this.toggleInput.setAttribute('aria-label', 'Enabled');\n if (this.field.disabled) {\n this.toggleInput.disabled = true;\n }\n this.#listen(this.toggleInput, 'change', () => this.setEnabled(this.toggleInput.checked));\n return this.toggleInput;\n }\n\n #buildNumberInput() {\n this.numberInput = document.createElement('input');\n this.numberInput.type = 'text';\n this.numberInput.inputMode = 'decimal';\n this.numberInput.className = 'twm-slider-field__number';\n this.numberInput.setAttribute('aria-label', 'Value');\n // A typed value that is not a finite number is refused and the box shows the value again.\n const commitTyped = () => {\n if (!this.setValue(this.numberInput.value.trim())) {\n this.#syncCompanions();\n }\n };\n this.#listen(this.numberInput, 'keydown', (event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commitTyped();\n } else if (event.key === 'Escape') {\n this.#syncCompanions();\n }\n });\n this.#listen(this.numberInput, 'change', commitTyped);\n return this.numberInput;\n }\n\n #buildResetButton() {\n this.resetButton = document.createElement('button');\n this.resetButton.type = 'button';\n this.resetButton.className = 'twm-slider-field__reset';\n this.resetButton.title = 'Reset to default';\n this.resetButton.setAttribute('aria-label', 'Reset to default');\n const icon = document.createElement('span');\n icon.className = 'material-symbols-outlined';\n icon.textContent = 'restart_alt';\n this.resetButton.appendChild(icon);\n this.#listen(this.resetButton, 'click', () => this.reset());\n return this.resetButton;\n }\n\n /** Apply a change, refresh the DOM, and report once if the reported value moved. */\n #commit(apply, silent) {\n const before = this.getValue();\n apply();\n this.#syncCompanions();\n const after = this.getValue();\n if (after === before) {\n return false;\n }\n if (!silent) {\n this.onChange?.(after, { immediate: false });\n }\n return true;\n }\n\n /** Write the model into every element: slider, box, readout, toggle, states. */\n #syncCompanions() {\n if (!this.root) return;\n const text = String(this.#value);\n if (this.sliderInput.value !== text) {\n this.sliderInput.value = text;\n }\n const off = !this.#enabled;\n const hardDisabled = Boolean(this.field.disabled);\n this.sliderInput.disabled = hardDisabled || off;\n if (this.numberInput) {\n this.numberInput.value = text;\n this.numberInput.disabled = hardDisabled || off;\n }\n if (this.readoutEl) {\n const format = typeof this.field.readout === 'function' ? this.field.readout : null;\n this.readoutEl.textContent = format ? String(format(this.#value)) : text;\n }\n if (this.toggleInput) {\n this.toggleInput.checked = this.#enabled;\n }\n const modified = this.isModified();\n if (this.resetButton) {\n this.resetButton.disabled = hardDisabled || off || !modified;\n }\n this.root.classList.toggle('twm-slider-field--modified', modified);\n this.root.classList.toggle('twm-slider-field--off', off);\n }\n\n #writeRangeAttributes() {\n this.sliderInput.min = String(this.#min);\n this.sliderInput.max = String(this.#max);\n this.sliderInput.step = String(this.#step);\n this.sliderInput.value = String(this.#value);\n }\n\n /** Clamp to [min, max] and snap to the step grid anchored at min, as a range input does. */\n #fit(value) {\n const clamped = Math.min(this.#max, Math.max(this.#min, value));\n let snapped = this.#min + Math.round((clamped - this.#min) / this.#step) * this.#step;\n if (snapped > this.#max) snapped -= this.#step;\n const decimals = Math.max(this.#decimals(this.#step), this.#decimals(this.#min));\n return Number(snapped.toFixed(Math.min(decimals, 12)));\n }\n\n #decimals(value) {\n const text = String(value);\n if (text.includes('e-')) return Number(text.split('e-')[1]);\n const dot = text.indexOf('.');\n return dot === -1 ? 0 : text.length - dot - 1;\n }\n\n #isFiniteInput(value) {\n if (value === null || value === undefined || typeof value === 'boolean') {\n return false;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return false;\n }\n return Number.isFinite(Number(value));\n }\n\n #disabledValue() {\n return this.field.disabledValue === undefined ? null : this.field.disabledValue;\n }\n\n #listen(target, type, handler, options) {\n target.addEventListener(type, handler, options);\n this._disposers.push(() => target.removeEventListener(type, handler, options));\n }\n\n #coerceNumber(value, fallback) {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : fallback;\n }\n\n #coercePositiveNumber(value, fallback) {\n const numeric = this.#coerceNumber(value, fallback);\n if (numeric <= 0) {\n return fallback;\n }\n return numeric;\n }\n}\n", "/**\n * table_state_store.js \u2014 persist DataTable view-state (sort, filters,\n * column widths), keyed by a caller-supplied `persistKey`.\n *\n * A FACTORY, not a singleton: the store reads and writes through a Host's\n * `state` capability (see ui/js/host/host.js) under one logical state key.\n * One blob holds a map of `{ [persistKey]: state }` for every persisted table.\n * Where that key lands on disk is the embedder's business, not ours \u2014 it is\n * decided by the host's `resolvePath`.\n *\n * A host without a `state` capability is legal: tables simply stay ephemeral.\n *\n * The in-memory cache must be dropped when the project changes (the app swaps\n * projects in-place without a page reload) \u2014 `reset()` is wired to the\n * `project:opened` event in app_bootstrap.\n */\n\n/**\n * @param {object} opts\n * @param {object} opts.host a Host. May lack `state` -> tables become ephemeral.\n * @param {string} opts.key logical state key, e.g. 'datatable_state'\n * @param {object} [opts.logger]\n * @param {number} [opts.debounceMs=500]\n */\nexport function createTableStateStore({ host, key, logger = console, debounceMs = 500 }) {\n if (!key) throw new Error('createTableStateStore requires { key }');\n const state = host?.state || null;\n\n let cache = null; // { [persistKey]: state } \u2014 null until first load\n let loadPromise = null;\n let saveTimer = null;\n\n const scheduleSave = () => {\n if (saveTimer) clearTimeout(saveTimer);\n saveTimer = setTimeout(async () => {\n saveTimer = null;\n if (!state || !cache) return;\n try { await state.write(key, cache); }\n catch (err) { logger.warn?.('[table-state] save failed', err); }\n }, debounceMs);\n };\n\n return {\n /** Resolve once the persisted blob has been read into the cache. Safe\n * to call repeatedly \u2014 the read happens at most once per project. */\n ready() {\n if (loadPromise) return loadPromise;\n loadPromise = (async () => {\n if (!state) { cache = {}; return cache; }\n try { cache = (await state.read(key)) || {}; }\n catch (err) { logger.warn?.('[table-state] load failed', err); cache = {}; }\n return cache;\n })();\n return loadPromise;\n },\n\n /** Synchronous read of a table's persisted state. Returns null until\n * the cache is loaded (await `ready()` first to be sure). */\n get(k) {\n if (!k || !cache) return null;\n return cache[k] || null;\n },\n\n /** Merge-and-persist a table's state (debounced). Pass null to forget\n * a key. Writes the whole map back atomically through the host. */\n set(k, s) {\n if (!k) return;\n if (!cache) cache = {};\n if (s == null) delete cache[k]; else cache[k] = s;\n scheduleSave();\n },\n\n /** Drop the cache + pending read so the next access reloads from the\n * newly-opened project. Cancels any in-flight save for the old one. */\n reset() {\n cache = null;\n loadPromise = null;\n if (saveTimer) { clearTimeout(saveTimer); saveTimer = null; }\n },\n };\n}\n", "/**\n * Tree View Component\n *\n * A reusable hierarchical tree view component for displaying nested data.\n * Used by Functions Page (modules/functions) and Data Page (datasets/series).\n *\n * Structure:\n * - TreeView: Container for multiple categories\n * - TreeCategory: Top-level collapsible group (e.g., \"Built-in\", \"Project\")\n * - TreeNode: Expandable node with children (e.g., module, dataset)\n * - TreeItem: Leaf item (e.g., function, series)\n */\n\n/**\n * Labels, subtitles and badge text are TEXT, set with `textContent` after the\n * skeleton is built (BUG-0013): a dataset called 'A <b>B</b>' is shown as\n * those characters, and a name carrying `<img onerror>` runs nothing.\n */\nfunction setText(root, selector, value) {\n const el = root.querySelector(selector);\n if (el) el.textContent = value == null ? '' : String(value);\n}\n\n/**\n * An id as the value of a double-quoted attribute selector (BUG-0013).\n * NOT `CSS.escape`: jsdom does not provide it (see modal.js). Inside a quoted\n * attribute value `\"` and `\\` are escaped, and a line break, which would end\n * the string, becomes its hex escape.\n */\nfunction attrValue(value) {\n return String(value)\n .replace(/[\"\\\\]/g, '\\\\$&')\n .replace(/[\\n\\r\\f]/g, (c) => `\\\\${c.charCodeAt(0).toString(16)} `);\n}\n\n/**\n * Create a tree category (top-level collapsible section)\n * @param {Object} options - Category options\n * @param {string} options.id - Unique category ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon name\n * @param {string} [options.iconClass] - Additional icon CSS class\n * @param {number} [options.count] - Item count to display\n * @param {boolean} [options.expanded=false] - Initial expanded state\n * @param {boolean} [options.readonly=false] - Whether items are readonly\n * @returns {HTMLElement} - Category element\n */\nexport function createTreeCategory(options) {\n const {\n id,\n label,\n icon = 'folder',\n iconClass = '',\n count = 0,\n expanded = false,\n readonly = false,\n } = options;\n\n const node = document.createElement('div');\n node.className = 'twm-collapsible-box twm-tree-category';\n node.dataset.categoryId = id;\n node.dataset.collapsibleId = `tree-category-${id}`;\n node.dataset.collapsibleDefault = expanded ? 'expanded' : 'collapsed';\n if (readonly) node.dataset.readonly = 'true';\n\n node.innerHTML = `\n <div class=\"twm-collapsible-header\" data-collapsible-header=\"true\">\n <button class=\"twm-arrow-toggle\" type=\"button\">\n <span class=\"twm-collapsible-arrow material-symbols-outlined${expanded ? '' : ' collapsed'}\">expand_more</span>\n </button>\n <span class=\"twm-tree-category__icon ${iconClass}\">\n <span class=\"material-symbols-outlined\">${icon}</span>\n </span>\n <span class=\"twm-tree-category__label\"></span>\n <span class=\"twm-tree-category__count\">(${count})</span>\n </div>\n <div class=\"twm-collapsible-content${expanded ? ' visible' : ''}\" data-collapsible-content=\"true\"></div>\n `;\n setText(node, '.twm-tree-category__label', label);\n\n return node;\n}\n\n/**\n * Create a tree node (expandable container with children)\n * @param {Object} options - Node options\n * @param {string} options.id - Unique node ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon name (optional)\n * @param {number} [options.count] - Child count to display\n * @param {boolean} [options.expanded=false] - Initial expanded state\n * @param {boolean} [options.readonly=false] - Whether node is readonly\n * @param {Object} [options.actions] - Action buttons config\n * @returns {HTMLElement} - Node element\n */\nexport function createTreeNode(options) {\n const {\n id,\n label,\n icon = null,\n count = 0,\n expanded = false,\n readonly = false,\n actions = null,\n } = options;\n\n const node = document.createElement('div');\n node.className = `twm-tree-node${readonly ? ' readonly' : ''}`;\n node.dataset.nodeId = id;\n\n const iconHtml = icon\n ? `<span class=\"twm-tree-node__icon\"><span class=\"material-symbols-outlined\">${icon}</span></span>`\n : '';\n\n const actionsHtml = actions ? '<span class=\"twm-tree-node__actions\"></span>' : '';\n\n node.innerHTML = `\n <div class=\"twm-tree-node__header\">\n <span class=\"twm-tree-node__toggle\">\n <span class=\"material-symbols-outlined\">${expanded ? 'expand_more' : 'chevron_right'}</span>\n </span>\n ${iconHtml}\n <span class=\"twm-tree-node__label\"></span>\n <span class=\"twm-tree-node__count\">(${count})</span>\n ${actionsHtml}\n </div>\n <div class=\"twm-tree-node__children\" style=\"display: ${expanded ? 'block' : 'none'};\"></div>\n `;\n setText(node, '.twm-tree-node__label', label);\n\n if (actions) appendActionButtons(node.querySelector('.twm-tree-node__actions'), id, actions);\n\n return node;\n}\n\n/**\n * Fill a node's or an item's actions slot: one `.twm-tree-node__action-btn`\n * per entry. A click on an entry with `onClick` runs `onClick(id, event)` and\n * goes no further, so it neither selects the item nor toggles the node; nor\n * does a double-click, so it never reaches TreeView's onItemDoubleClick.\n * @param {HTMLElement} actionsEl\n * @param {string} id - The node's or item's id\n * @param {Object<string, { icon: string, title?: string, onClick?: Function }>} actions\n */\nfunction appendActionButtons(actionsEl, id, actions) {\n Object.entries(actions).forEach(([actionId, actionConfig]) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-tree-node__action-btn';\n btn.dataset.action = actionId;\n btn.title = actionConfig.title || actionId;\n btn.innerHTML = `<span class=\"material-symbols-outlined\">${actionConfig.icon}</span>`;\n if (actionConfig.onClick) {\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n actionConfig.onClick(id, e);\n });\n btn.addEventListener('dblclick', (e) => e.stopPropagation());\n }\n actionsEl.appendChild(btn);\n });\n}\n\n/**\n * Create a tree item (leaf node)\n * @param {Object} options - Item options\n * @param {string} options.id - Unique item ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon or symbol (e.g., '\u0192', 'insights')\n * @param {boolean} [options.isMaterialIcon=true] - Whether icon is Material icon\n * @param {boolean} [options.readonly=false] - Whether item is readonly\n * @param {boolean} [options.selected=false] - Whether item is selected\n * @param {string} [options.subtitle] - Optional subtitle text\n * @param {Object} [options.data] - Additional data to attach\n * @param {Object} [options.badge] - Optional badge config\n * @param {string} [options.badge.text] - Badge text (if empty, renders as status dot)\n * @param {string} [options.badge.variant] - 'muted'|'pass'|'fail'|'error'\n * @param {Object} [options.actions] - Row actions, as createTreeNode takes them\n * ({ id: { icon, title, onClick(id, event) } }): buttons in one line at the\n * row's end (`.twm-tree-item__actions`), shown on hover, on focus within and\n * on the selected item\n * @returns {HTMLElement} - Item element\n */\nexport function createTreeItem(options) {\n const {\n id,\n label,\n icon = null,\n isMaterialIcon = true,\n readonly = false,\n selected = false,\n subtitle = null,\n data = null,\n badge = null,\n actions = null,\n } = options;\n\n const item = document.createElement('div');\n item.className = `twm-tree-item${readonly ? ' readonly' : ''}${selected ? ' selected' : ''}`;\n item.dataset.itemId = id;\n\n // Attach custom data\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n item.dataset[key] = value;\n });\n }\n\n const iconHtml = icon\n ? isMaterialIcon\n ? `<span class=\"twm-tree-item__icon\"><span class=\"material-symbols-outlined\">${icon}</span></span>`\n : `<span class=\"twm-tree-item__icon twm-tree-item__icon--symbol\">${icon}</span>`\n : '';\n\n const subtitleHtml = subtitle\n ? '<span class=\"twm-tree-item__subtitle\"></span>'\n : '';\n\n let badgeHtml = '';\n if (badge) {\n const variant = badge.variant || 'muted';\n if (badge.text) {\n badgeHtml = `<span class=\"twm-tree-item__badge twm-tree-item__badge--${variant}\"></span>`;\n } else {\n badgeHtml = `<span class=\"twm-tree-item__status-dot twm-tree-item__status-dot--${variant}\"></span>`;\n }\n }\n\n item.innerHTML = `\n ${iconHtml}\n <span class=\"twm-tree-item__label\"></span>\n ${subtitleHtml}\n ${badgeHtml}\n `;\n setText(item, '.twm-tree-item__label', label);\n if (subtitle) setText(item, '.twm-tree-item__subtitle', subtitle);\n if (badge?.text) setText(item, '.twm-tree-item__badge', badge.text);\n\n if (actions) {\n const actionsEl = document.createElement('span');\n actionsEl.className = 'twm-tree-item__actions';\n appendActionButtons(actionsEl, id, actions);\n item.appendChild(actionsEl);\n }\n\n return item;\n}\n\n/**\n * Toggle a collapsible category\n * @param {HTMLElement} categoryEl - Category element\n * @param {boolean} [force] - Force specific state (true = expand, false = collapse)\n */\nexport function toggleCategory(categoryEl, force) {\n if (!categoryEl) return;\n\n const arrow = categoryEl.querySelector(':scope > .twm-collapsible-header .twm-collapsible-arrow');\n const content = categoryEl.querySelector(':scope > .twm-collapsible-content');\n\n if (!content) return;\n\n // Determine whether we should expand\n // force=true means expand, force=false means collapse, undefined means toggle\n const isCurrentlyExpanded = content.classList.contains('visible');\n const shouldExpand = force !== undefined ? force : !isCurrentlyExpanded;\n\n if (shouldExpand) {\n // Expand\n if (arrow) {\n arrow.classList.remove('collapsed');\n }\n content.classList.add('visible');\n } else {\n // Collapse\n if (arrow) {\n arrow.classList.add('collapsed');\n }\n content.classList.remove('visible');\n }\n}\n\n/**\n * Toggle a tree node\n * @param {HTMLElement} nodeEl - Node element\n * @param {boolean} [force] - Force specific state\n */\nexport function toggleNode(nodeEl, force) {\n if (!nodeEl) return;\n\n const toggle = nodeEl.querySelector(':scope > .twm-tree-node__header .twm-tree-node__toggle .material-symbols-outlined');\n const children = nodeEl.querySelector(':scope > .twm-tree-node__children');\n\n if (!children) return;\n\n const isExpanded = force !== undefined\n ? force\n : children.style.display === 'none';\n\n if (isExpanded) {\n children.style.display = 'block';\n if (toggle) toggle.textContent = 'expand_more';\n } else {\n children.style.display = 'none';\n if (toggle) toggle.textContent = 'chevron_right';\n }\n}\n\n/**\n * Filter tree items by text match\n *\n * An item is shown when its label contains the filter. A node or a category is\n * shown when any tree item inside it is shown, whether the item sits directly\n * in it or deeper inside nodes. An empty filter shows everything, so clearing\n * the filter restores the whole tree, empty nodes and categories included.\n *\n * @param {HTMLElement} container - Tree container\n * @param {string} filter - Filter text (case-insensitive)\n * @param {Object} [options] - Filter options\n * @param {boolean} [options.expandMatches=true] - Auto-expand nodes with matches\n */\nexport function filterTree(container, filter, options = {}) {\n const { expandMatches = true } = options;\n const normalizedFilter = (filter || '').toLowerCase().trim();\n\n const visibleItems = new Set();\n container.querySelectorAll('.twm-tree-item').forEach((item) => {\n const label = item.querySelector('.twm-tree-item__label')?.textContent || '';\n const matches = !normalizedFilter || label.toLowerCase().includes(normalizedFilter);\n item.style.display = matches ? '' : 'none';\n item.classList.toggle('twm-filter-match', matches && !!normalizedFilter);\n if (matches) visibleItems.add(item);\n });\n\n const hasVisibleItem = (el) => !normalizedFilter\n || [...el.querySelectorAll('.twm-tree-item')].some((item) => visibleItems.has(item));\n\n container.querySelectorAll('.twm-tree-node').forEach((node) => {\n const visible = hasVisibleItem(node);\n node.style.display = visible ? '' : 'none';\n if (expandMatches && visible && normalizedFilter) toggleNode(node, true);\n });\n\n container.querySelectorAll('.twm-tree-category').forEach((category) => {\n const visible = hasVisibleItem(category);\n category.style.display = visible ? '' : 'none';\n if (expandMatches && visible && normalizedFilter) toggleCategory(category, true);\n });\n}\n\n/**\n * Select a tree item\n * @param {HTMLElement} container - Tree container\n * @param {string} itemId - Item ID to select\n * @param {Object} [options] - Selection options\n * @param {boolean} [options.scrollIntoView=true] - Scroll item into view\n * @param {boolean} [options.expandParents=true] - Expand parent nodes\n */\nexport function selectItem(container, itemId, options = {}) {\n const { scrollIntoView = true, expandParents = true } = options;\n\n // Deselect all\n container.querySelectorAll('.twm-tree-item.selected').forEach((el) => {\n el.classList.remove('selected');\n });\n\n // Find and select item\n const item = container.querySelector(`.twm-tree-item[data-item-id=\"${attrValue(itemId)}\"]`);\n if (!item) return null;\n\n item.classList.add('selected');\n\n // Expand parent nodes\n if (expandParents) {\n let parent = item.parentElement;\n while (parent && parent !== container) {\n if (parent.classList.contains('twm-tree-node__children')) {\n const node = parent.closest('.twm-tree-node');\n if (node) toggleNode(node, true);\n }\n if (parent.classList.contains('twm-collapsible-content')) {\n const category = parent.closest('.twm-tree-category');\n if (category) toggleCategory(category, true);\n }\n parent = parent.parentElement;\n }\n }\n\n // Scroll into view\n if (scrollIntoView) {\n item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n\n return item;\n}\n\n/**\n * TreeView class for managing a complete tree structure\n */\nexport class TreeView {\n constructor(container, options = {}) {\n this.container = container;\n this.options = {\n onItemClick: null,\n onItemDoubleClick: null,\n onNodeToggle: null,\n onCategoryToggle: null,\n ...options,\n };\n\n this._boundHandleClick = this._handleClick.bind(this);\n this._boundHandleDblClick = this._handleDoubleClick.bind(this);\n\n if (container) {\n container.classList.add('twm-tree-view');\n container.addEventListener('click', this._boundHandleClick);\n container.addEventListener('dblclick', this._boundHandleDblClick);\n }\n }\n\n _handleClick(e) {\n // Handle category toggle\n const collapsibleHeader = e.target.closest('.twm-collapsible-header');\n if (collapsibleHeader) {\n const category = collapsibleHeader.closest('.twm-tree-category');\n if (category) {\n toggleCategory(category);\n this.options.onCategoryToggle?.(category.dataset.categoryId, category);\n }\n return;\n }\n\n // Handle node toggle\n const nodeHeader = e.target.closest('.twm-tree-node__header');\n if (nodeHeader) {\n const node = nodeHeader.closest('.twm-tree-node');\n if (node) {\n toggleNode(node);\n this.options.onNodeToggle?.(node.dataset.nodeId, node);\n }\n return;\n }\n\n // Handle item click\n const item = e.target.closest('.twm-tree-item');\n if (item) {\n this.select(item.dataset.itemId);\n this.options.onItemClick?.(item.dataset.itemId, item, e);\n }\n }\n\n _handleDoubleClick(e) {\n const item = e.target.closest('.twm-tree-item');\n if (item) {\n this.options.onItemDoubleClick?.(item.dataset.itemId, item, e);\n }\n }\n\n addCategory(options) {\n const category = createTreeCategory(options);\n this.container.appendChild(category);\n return category;\n }\n\n addNode(categoryId, options) {\n const category = this.container.querySelector(`.twm-tree-category[data-category-id=\"${attrValue(categoryId)}\"]`);\n const content = category?.querySelector('.twm-collapsible-content');\n if (!content) return null;\n\n const node = createTreeNode(options);\n content.appendChild(node);\n return node;\n }\n\n addItem(nodeId, options) {\n const node = this.container.querySelector(`.twm-tree-node[data-node-id=\"${attrValue(nodeId)}\"]`);\n const children = node?.querySelector('.twm-tree-node__children');\n if (!children) return null;\n\n const item = createTreeItem(options);\n children.appendChild(item);\n return item;\n }\n\n select(itemId) {\n return selectItem(this.container, itemId);\n }\n\n filter(text) {\n filterTree(this.container, text);\n }\n\n clear() {\n this.container.innerHTML = '';\n }\n\n dispose() {\n if (this.container) {\n this.container.removeEventListener('click', this._boundHandleClick);\n this.container.removeEventListener('dblclick', this._boundHandleDblClick);\n }\n }\n}\n\nexport default TreeView;\n", "/**\n * WindowTaskbar - Singleton component that manages minimized windows in the global bottom bar.\n *\n * Listens for window events and renders taskbar buttons for minimized windows.\n * Integrates with the existing global-bottom-bar element.\n */\n\nimport { ManagedWindow } from './managed_window.js';\n\nclass WindowTaskbarManager {\n constructor() {\n this._minimizedWindows = new Map(); // id -> { title, icon }\n this._containerEl = null;\n this._leftDivider = null;\n this._rightDivider = null;\n this._initialized = false;\n }\n\n /**\n * Initialize the taskbar. Call once after DOM is ready.\n */\n init() {\n if (this._initialized) return;\n\n // Find or create the container in the global bottom bar\n const bottomBar = document.querySelector('.twm-global-bottom-bar');\n if (!bottomBar) {\n console.warn('[WindowTaskbar] twm-global-bottom-bar not found');\n return;\n }\n\n // Create left divider (always present but hidden when no windows)\n this._leftDivider = document.createElement('div');\n this._leftDivider.className = 'twm-bar-windows__divider twm-bar-windows__divider--left';\n\n // Insert bar-windows container between bar-left and bar-center\n this._containerEl = document.createElement('div');\n this._containerEl.className = 'twm-bar-windows';\n\n // Create right divider (shown when there are windows)\n this._rightDivider = document.createElement('div');\n this._rightDivider.className = 'twm-bar-windows__divider twm-bar-windows__divider--right';\n\n const barCenter = bottomBar.querySelector('.twm-bar-center');\n if (barCenter) {\n bottomBar.insertBefore(this._rightDivider, barCenter);\n bottomBar.insertBefore(this._containerEl, this._rightDivider);\n bottomBar.insertBefore(this._leftDivider, this._containerEl);\n } else {\n bottomBar.appendChild(this._leftDivider);\n bottomBar.appendChild(this._containerEl);\n bottomBar.appendChild(this._rightDivider);\n }\n\n // Listen for window events\n window.addEventListener('managed-window-minimized', (e) => this._onWindowMinimized(e));\n window.addEventListener('managed-window-restored', (e) => this._onWindowRestored(e));\n window.addEventListener('managed-window-closed', (e) => this._onWindowClosed(e));\n\n this._initialized = true;\n this._updateDividers();\n }\n\n /**\n * Handle window minimized event.\n */\n _onWindowMinimized(e) {\n const { id, title, icon } = e.detail;\n this._minimizedWindows.set(id, { title, icon });\n this._render();\n }\n\n /**\n * Handle window restored event.\n */\n _onWindowRestored(e) {\n const { id } = e.detail;\n this._minimizedWindows.delete(id);\n this._render();\n }\n\n /**\n * Handle window closed event.\n */\n _onWindowClosed(e) {\n const { id } = e.detail;\n this._minimizedWindows.delete(id);\n this._render();\n }\n\n /**\n * Update divider visibility based on window count.\n */\n _updateDividers() {\n const hasWindows = this._minimizedWindows.size > 0;\n if (this._leftDivider) {\n this._leftDivider.style.display = hasWindows ? '' : 'none';\n }\n if (this._rightDivider) {\n this._rightDivider.style.display = hasWindows ? '' : 'none';\n }\n }\n\n /**\n * Render the taskbar buttons.\n */\n _render() {\n if (!this._containerEl) return;\n\n this._containerEl.innerHTML = '';\n\n for (const [id, { title, icon }] of this._minimizedWindows) {\n const btn = document.createElement('button');\n btn.className = 'twm-bar-windows__item';\n btn.setAttribute('data-window-id', id);\n btn.title = `Restore: ${title}`;\n\n // Add icon\n if (icon) {\n const iconEl = document.createElement('span');\n iconEl.className = 'twm-bar-windows__item-icon material-symbols-outlined';\n iconEl.textContent = icon;\n btn.appendChild(iconEl);\n }\n\n // Add title\n const titleEl = document.createElement('span');\n titleEl.className = 'twm-bar-windows__item-title';\n titleEl.textContent = title;\n btn.appendChild(titleEl);\n\n btn.addEventListener('click', () => {\n ManagedWindow.restore(id);\n });\n this._containerEl.appendChild(btn);\n }\n\n this._updateDividers();\n }\n}\n\n// Singleton instance\nexport const WindowTaskbar = new WindowTaskbarManager();\n", "/**\n * Wizard \u2014 a multi-step flow: a step indicator, a body slot and a footer with\n * Cancel, Back and Next/Finish, every step gated by its own `canAdvance`.\n *\n * Usage:\n * const wizard = new Wizard({\n * data: { file: null }, // yours; every hook sees it as ctx.data\n * steps: [\n * { id: 'source', label: 'Source', icon: 'upload_file',\n * render(bodyEl, ctx) { \u2026 ; return () => { \u2026 } }, // optional cleanup function\n * canAdvance: (ctx) => ctx.data.file\n * ? { ok: true } : { ok: false, hint: 'Choose a file first' } },\n * { id: 'review', label: 'Review', render(bodyEl, ctx) { \u2026 } },\n * ],\n * onFinish: async (ctx) => { \u2026 }, // rejects \u2192 the step shows the error\n * onCancel: (ctx) => { \u2026 },\n * });\n * wizard.mount(hostEl); // inline \u2026\n * wizard.openInWindow({ id: 'import', title: 'Import' }); // \u2026 or in a window\n *\n * Steps are drawn done / current / upcoming / error and joined by a connector.\n * A done (or errored) step BEFORE the current one is a button that jumps back;\n * a step after it is inert, so the only way forward is Next, through the gate.\n *\n * `canAdvance(ctx)` is asked whenever the footer is drawn, and `revalidate()`\n * draws it again \u2014 the body is rendered once per visit, never by a revalidate,\n * so an input the user is typing into keeps its focus and its value.\n *\n * Every move goes through a core StateMachine:\n *\n * step \u2500\u2500move\u2500\u2500\u25B6 step (guard: back to a visited step, or forward\n * \u2502 one step through the gate)\n * \u251C\u2500\u2500finish\u2500\u2500\u25B6 finishing \u2500\u2500resolve\u2500\u2500\u25B6 finished (closes)\n * \u2502 \u2502\n * \u2502 \u2514\u2500\u2500reject\u2500\u2500\u25B6 step (the step shows the error)\n * \u2514\u2500\u2500cancel\u2500\u2500\u25B6 cancelled (closes, calls onCancel)\n *\n * While `finishing`, every button is disabled and no move is accepted, so an\n * async finish cannot be raced by a click. `finished` and `cancelled` are final:\n * onCancel runs once however many times Cancel is pressed.\n *\n * State lives in this instance only; the DOM carries classes and ARIA, never a\n * data attribute.\n */\nimport { ComponentBase } from '../base/component_base.js';\nimport { StateMachine } from '../../core/state_machine.js';\nimport { ManagedWindow } from './managed_window.js';\n\nconst DEFAULT_LABELS = Object.freeze({\n back: 'Back',\n next: 'Next',\n finish: 'Finish',\n cancel: 'Cancel',\n});\n\nconst OPEN = 'step';\nconst FINISHING = 'finishing';\nconst FINISHED = 'finished';\nconst CANCELLED = 'cancelled';\n\n/** Steps own one override: an error and its message. Everything else about a\n * step's look follows from where it is relative to the current one. */\nconst STEP_STATES = Object.freeze(['error']);\n\nconst isFinal = (state) => state === FINISHED || state === CANCELLED;\n\n/** A step's render may hand back a cleanup function, run when the step is\n * left and on dispose(). */\nfunction runCleanup(cleanup) {\n if (typeof cleanup === 'function') cleanup();\n}\n\nfunction messageOf(err) {\n if (err && typeof err.message === 'string' && err.message) return err.message;\n return err == null ? 'Failed' : String(err);\n}\n\nexport class Wizard extends ComponentBase {\n\n /** @type {Array<object>} */ #steps;\n /** @type {object} */ #labels;\n /** @type {Function|null} */ #onFinish;\n /** @type {Function|null} */ #onCancel;\n /** @type {object} */ #ctx;\n /** @type {StateMachine} */ #machine;\n /** @type {number} */ #index = 0;\n /** @type {Map<string,{state:string,message:string}>} */ #overrides = new Map();\n /** @type {*} */ #cleanup = null;\n /** @type {Promise} */ #queue = Promise.resolve();\n /** @type {ManagedWindow|null} */ #window = null;\n /** @type {boolean} */ #disposed = false;\n\n /** @type {HTMLElement|null} */ #root = null;\n /** @type {HTMLElement[]} */ #stepItems = [];\n /** @type {HTMLButtonElement[]} */#stepButtons = [];\n /** @type {HTMLElement[]} */ #connectors = [];\n /** @type {HTMLElement|null} */ #body = null;\n /** @type {HTMLElement|null} */ #message = null;\n /** @type {HTMLButtonElement|null} */ #cancelBtn = null;\n /** @type {HTMLButtonElement|null} */ #backBtn = null;\n /** @type {HTMLButtonElement|null} */ #nextBtn = null;\n\n /**\n * @param {object} opts\n * @param {Array<{id:string,label:string,icon?:string,\n * render:(bodyEl:HTMLElement, ctx:object)=>(Function|void),\n * canAdvance?:(ctx:object)=>{ok:boolean,hint?:string}}>} opts.steps\n * @param {object} [opts.data={}] Your state; every hook reads it as `ctx.data`.\n * @param {Function} [opts.onFinish] `(ctx) => void|Promise`. A rejection marks the\n * current step as error with the rejection's message.\n * @param {Function} [opts.onCancel] `(ctx) => void`, called once when the wizard is cancelled.\n * @param {object} [opts.labels] `{back, next, finish, cancel}` button labels.\n * @param {object} [opts.eventBus] Passed to the StateMachine (its `fsm:*` events).\n * @param {object} [opts.logger] Passed to the StateMachine.\n */\n constructor({ steps, data = {}, onFinish = null, onCancel = null, labels = {},\n eventBus = null, logger = null } = {}) {\n super({ eventBus, logger });\n if (!Array.isArray(steps) || steps.length === 0) {\n throw new Error('Wizard requires at least one step');\n }\n const ids = new Set();\n for (const step of steps) {\n if (!step || typeof step.id !== 'string' || !step.id) {\n throw new Error('Wizard: every step needs a non-empty string id');\n }\n if (ids.has(step.id)) throw new Error(`Wizard: duplicate step id \"${step.id}\"`);\n if (typeof step.render !== 'function') {\n throw new Error(`Wizard: step \"${step.id}\" needs a render(bodyEl, ctx) function`);\n }\n ids.add(step.id);\n }\n this.#steps = steps.slice();\n this.#labels = { ...DEFAULT_LABELS, ...labels };\n this.#onFinish = onFinish;\n this.#onCancel = onCancel;\n\n const wizard = this;\n this.#ctx = Object.freeze({\n data,\n get step() { return wizard.currentStep; },\n get index() { return wizard.currentIndex; },\n revalidate: () => this.revalidate(),\n next: () => this.next(),\n back: () => this.back(),\n goTo: (target) => this.goTo(target),\n setStepState: (id, state, message) => this.setStepState(id, state, message),\n });\n\n this.#machine = new StateMachine({\n name: 'wizard',\n initialState: OPEN,\n eventBus,\n logger,\n states: {\n [OPEN]: {\n transitions: {\n move: {\n target: OPEN,\n guard: ({ payload }) => this.#canMoveTo(payload.to),\n action: ({ payload }) => this.#enterStep(payload.to),\n },\n finish: {\n target: FINISHING,\n guard: () => this.#isLast() && this.#gate().ok,\n action: () => { this.#overrides.delete(this.currentStep); },\n },\n cancel: { target: CANCELLED },\n },\n },\n [FINISHING]: {\n transitions: {\n resolve: { target: FINISHED },\n reject: {\n target: OPEN,\n action: ({ payload }) => {\n this.#overrides.set(this.currentStep,\n { state: 'error', message: messageOf(payload.error) });\n },\n },\n },\n },\n [FINISHED]: { onEnter: () => this.#close() },\n [CANCELLED]: {\n onEnter: () => {\n this.#close();\n this.#onCancel?.(this.#ctx);\n },\n },\n },\n });\n }\n\n // \u2500\u2500\u2500 Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Mount inline into `container` and render the first step.\n * @param {HTMLElement} container\n * @returns {Wizard}\n */\n mount(container) {\n if (this._mounted) return this;\n this.#build();\n container.appendChild(this.#root);\n this._mounted = true;\n this.#renderBody();\n this.#paint();\n return this;\n }\n\n /**\n * Mount in a ManagedWindow and show it. The window's close button and\n * Escape cancel the wizard (and are refused while a finish is running);\n * finishing or cancelling closes the window.\n * @param {object} [opts] ManagedWindow options: id, title, icon, defaultWidth,\n * defaultHeight, minWidth, minHeight, container, modal (default true).\n * @returns {ManagedWindow}\n */\n openInWindow({ id = 'twm-wizard', title = 'Wizard', icon, defaultWidth = 720,\n defaultHeight = 520, minWidth = 420, minHeight = 320,\n container, modal = true } = {}) {\n if (this._mounted) throw new Error('Wizard is already mounted');\n this.#build();\n this._mounted = true;\n this.#window = new ManagedWindow({\n id, title, icon, defaultWidth, defaultHeight, minWidth, minHeight,\n container, modal,\n content: this.#root,\n canMinimize: false,\n beforeClose: () => {\n if (isFinal(this.state)) return true;\n void this.cancel();\n return false;\n },\n });\n // Rendered and painted BEFORE show, so the window's focus-on-open\n // (BUG-0053) lands on the step's first field \u2014 the stepper's buttons\n // are disabled by then \u2014 and not on the first step button.\n this.#renderBody();\n this.#paint();\n this.#window.show();\n return this.#window;\n }\n\n /** Tear down (and close the window, if any) without calling any callback.\n * Every later move, finish or cancel is refused. */\n dispose() {\n if (this.#disposed) return;\n this.#disposed = true;\n const win = this.#window;\n this.#teardown();\n win?.close({ force: true });\n super.dispose();\n }\n\n // \u2500\u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** The wizard's root element (null before mount). */\n get element() { return this.#root; }\n\n /** The body slot the current step renders into. */\n get bodyElement() { return this.#body; }\n\n /** The ManagedWindow, when opened with `openInWindow`. */\n get window() { return this.#window; }\n\n /** The object every hook receives: `{data, step, index, revalidate, next, back, goTo, setStepState}`. */\n get context() { return this.#ctx; }\n\n /** The current step's id. */\n get currentStep() { return this.#steps[this.#index].id; }\n\n /** The current step's index. */\n get currentIndex() { return this.#index; }\n\n /** 'step' | 'finishing' | 'finished' | 'cancelled' (null for a moment after construction). */\n get state() { return this.#machine.getState(); }\n\n /** True while an async finish is running. */\n get busy() { return this.state === FINISHING; }\n\n /**\n * Ask the current step's `canAdvance` again and redraw the indicator and\n * the footer. The body is NOT re-rendered.\n */\n revalidate() {\n this.#paint();\n }\n\n /** Forward one step, if the current step's gate allows it. Resolves true when it moved. */\n next() {\n return this.#move(() => this.#index + 1);\n }\n\n /** Back one step. Resolves true when it moved. */\n back() {\n return this.#move(() => this.#index - 1);\n }\n\n /**\n * Move to a step by id or index: any step before the current one, or the\n * next one through the gate. Resolves true when it moved.\n * @param {string|number} target\n */\n goTo(target) {\n return this.#move(() => this.#resolveIndex(target));\n }\n\n /**\n * Mark a step as errored (`'error'`, with a message shown while it is the\n * current step), or clear the mark (`null`).\n * @param {string} id\n * @param {'error'|null} state\n * @param {string} [message]\n */\n setStepState(id, state, message = '') {\n const i = this.#resolveIndex(id);\n if (i < 0 || i >= this.#steps.length) throw new Error(`Wizard: no step \"${id}\"`);\n const key = this.#steps[i].id;\n if (state == null) this.#overrides.delete(key);\n else if (STEP_STATES.includes(state)) this.#overrides.set(key, { state, message: String(message ?? '') });\n else throw new Error(`Wizard: unknown step state \"${state}\" (expected 'error' or null)`);\n this.#paint();\n }\n\n /**\n * Run `onFinish` from the last step, if its gate allows. The buttons are\n * disabled until it settles; resolved, the wizard closes; rejected, the\n * step is marked as error with the message. Resolves true when it finished.\n */\n finish() {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const { transitioned } = await this.#machine.transition('finish');\n if (!transitioned) return false;\n this.#paint();\n try {\n await this.#onFinish?.(this.#ctx);\n } catch (error) {\n await this.#machine.transition('reject', { error });\n this.#paint();\n return false;\n }\n await this.#machine.transition('resolve');\n return true;\n });\n }\n\n /**\n * Close the wizard and call `onCancel` \u2014 once. Refused while a finish is\n * running. Resolves true when it cancelled.\n */\n cancel() {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const { transitioned } = await this.#machine.transition('cancel');\n return transitioned;\n });\n }\n\n // \u2500\u2500\u2500 Moves \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Moves run one at a time, so a double click cannot start a transition\n * inside another. The target is computed when the move runs, not when it\n * was asked for. A request made while a finish is running (or after the\n * wizard closed) is refused there and then \u2014 it is not queued behind the\n * finish to run once it settles. */\n #enqueue(fn) {\n if (this.#disposed || this.busy || isFinal(this.state)) return Promise.resolve(false);\n const run = this.#queue.then(() => (this.#disposed ? false : fn()));\n this.#queue = run.catch(() => {});\n return run;\n }\n\n #move(targetOf) {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const to = targetOf();\n if (!this.#canMoveTo(to)) return false;\n const { transitioned } = await this.#machine.transition('move', { to });\n this.#paint();\n return transitioned;\n });\n }\n\n #canMoveTo(to) {\n if (!Number.isInteger(to) || to < 0 || to >= this.#steps.length) return false;\n if (to < this.#index) return true;\n return to === this.#index + 1 && this.#gate().ok;\n }\n\n #enterStep(to) {\n this.#index = to;\n this.#renderBody();\n }\n\n #resolveIndex(target) {\n if (typeof target === 'number') return Number.isInteger(target) ? target : -1;\n return this.#steps.findIndex((s) => s.id === target);\n }\n\n #isLast() {\n return this.#index === this.#steps.length - 1;\n }\n\n /** The current step's gate, normalised to `{ok, hint}`. */\n #gate() {\n const step = this.#steps[this.#index];\n if (typeof step.canAdvance !== 'function') return { ok: true, hint: '' };\n const r = step.canAdvance(this.#ctx) ?? {};\n return { ok: r.ok === true, hint: typeof r.hint === 'string' ? r.hint : '' };\n }\n\n // \u2500\u2500\u2500 DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #build() {\n const root = document.createElement('div');\n root.className = 'twm-wizard';\n\n const steps = document.createElement('ol');\n steps.className = 'twm-wizard__steps';\n this.#steps.forEach((step, i) => {\n if (i > 0) {\n const connector = document.createElement('li');\n connector.className = 'twm-wizard__connector';\n connector.setAttribute('role', 'presentation');\n connector.setAttribute('aria-hidden', 'true');\n steps.appendChild(connector);\n this.#connectors.push(connector);\n }\n const item = document.createElement('li');\n item.className = 'twm-wizard__step';\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-wizard__step-btn';\n const marker = document.createElement('span');\n marker.className = 'twm-wizard__step-marker';\n const label = document.createElement('span');\n label.className = 'twm-wizard__step-label';\n label.textContent = step.label ?? step.id;\n btn.append(marker, label);\n btn.addEventListener('click', () => this.#onStepClick(i));\n item.appendChild(btn);\n steps.appendChild(item);\n this.#stepItems.push(item);\n this.#stepButtons.push(btn);\n });\n\n this.#body = document.createElement('div');\n this.#body.className = 'twm-wizard__body';\n\n const footer = document.createElement('div');\n footer.className = 'twm-wizard__footer';\n this.#message = document.createElement('div');\n this.#message.className = 'twm-wizard__message';\n this.#message.setAttribute('aria-live', 'polite');\n\n const actions = document.createElement('div');\n actions.className = 'twm-wizard__actions';\n this.#cancelBtn = this.#button('twm-wizard__cancel', this.#labels.cancel, () => { void this.cancel(); });\n this.#backBtn = this.#button('twm-wizard__back', this.#labels.back, () => { void this.back(); });\n this.#nextBtn = this.#button('twm-wizard__next twm-btn--primary', this.#labels.next, () => {\n void (this.#isLast() ? this.finish() : this.next());\n });\n actions.append(this.#cancelBtn, this.#backBtn, this.#nextBtn);\n footer.append(this.#message, actions);\n\n root.append(steps, this.#body, footer);\n this.#root = root;\n }\n\n #button(cls, text, onClick) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `twm-btn ${cls}`;\n btn.textContent = text;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n #onStepClick(i) {\n if (i < this.#index) void this.goTo(i);\n }\n\n #renderBody() {\n runCleanup(this.#cleanup);\n this.#cleanup = null;\n this.#body.replaceChildren();\n const step = this.#steps[this.#index];\n this.#cleanup = step.render(this.#body, this.#ctx) ?? null;\n }\n\n /** The visual state of step `i`: an override, else its position. */\n #stepState(i) {\n const override = this.#overrides.get(this.#steps[i].id);\n if (override) return override.state;\n if (i < this.#index) return 'done';\n return i === this.#index ? 'current' : 'upcoming';\n }\n\n #paint() {\n if (!this.#root) return;\n const busy = this.busy;\n this.#root.classList.toggle('twm-wizard--busy', busy);\n this.#root.setAttribute('aria-busy', busy ? 'true' : 'false');\n\n this.#steps.forEach((step, i) => {\n const state = this.#stepState(i);\n const item = this.#stepItems[i];\n for (const s of ['done', 'current', 'upcoming', 'error']) {\n item.classList.toggle(`twm-wizard__step--${s}`, s === state);\n }\n item.classList.toggle('twm-wizard__step--active', i === this.#index);\n const btn = this.#stepButtons[i];\n btn.disabled = busy || i >= this.#index;\n if (i === this.#index) btn.setAttribute('aria-current', 'step');\n else btn.removeAttribute('aria-current');\n const override = this.#overrides.get(step.id);\n btn.title = override?.message || step.label || step.id;\n\n const marker = btn.firstChild;\n const glyph = state === 'done' ? 'check' : state === 'error' ? 'error' : (step.icon || '');\n marker.classList.toggle('material-symbols-outlined', Boolean(glyph));\n marker.textContent = glyph || String(i + 1);\n if (i > 0) {\n this.#connectors[i - 1].classList.toggle('twm-wizard__connector--done', i <= this.#index);\n }\n });\n\n const gate = this.#gate();\n const last = this.#isLast();\n this.#nextBtn.textContent = last ? this.#labels.finish : this.#labels.next;\n this.#nextBtn.disabled = busy || !gate.ok;\n this.#nextBtn.title = gate.ok ? '' : gate.hint;\n this.#backBtn.disabled = busy || this.#index === 0;\n this.#cancelBtn.disabled = busy;\n\n const error = this.#overrides.get(this.currentStep);\n const text = error ? error.message : (gate.ok ? '' : gate.hint);\n this.#message.textContent = text;\n this.#message.classList.toggle('twm-wizard__message--error', Boolean(error));\n this.#message.classList.toggle('twm-wizard__message--hint', !error && Boolean(text));\n if (error) this.#message.setAttribute('role', 'alert');\n else this.#message.removeAttribute('role');\n }\n\n #close() {\n const win = this.#window;\n this.#teardown();\n this._mounted = false;\n win?.close({ force: true });\n }\n\n #teardown() {\n runCleanup(this.#cleanup);\n this.#cleanup = null;\n this.#root?.remove();\n this.#root = null;\n this.#body = null;\n this.#message = null;\n this.#stepItems = [];\n this.#stepButtons = [];\n this.#connectors = [];\n this.#cancelBtn = this.#backBtn = this.#nextBtn = null;\n }\n}\n", "/**\n * workspace_picker.js \u2014 the field in a top bar that names what the window is\n * working in, and the switcher that changes it.\n *\n * field switcher, opened in the field's place\n * +-----------------------+ +------------------------------------+\n * | (i) North Ctrl+P | | (o) nor| |\n * +-----------------------+ | heading 2 of 9|\n * | North (check)(x)|\n * | Northwest |\n * | Load 20 more \u00B7 2 of 9 shown |\n * | + New \"nor\"\u2026 |\n * | card: the current one's links |\n * | status footer verbs |\n * +------------------------------------+\n *\n * Three exports, each usable alone:\n *\n * mountPickerField the field: a name, an icon, a key hint; centred in\n * its host at the width the host can spare, or inline\n * createPickerSwitcher the switcher, on any anchor or on none\n * createWorkspacePicker both, wired together, with an optional chord\n *\n * It knows nothing of what is being picked. Items are the caller's, `describe`\n * turns one into what a row draws, and every string is the caller's or a\n * neutral default the caller can replace through `labels`.\n *\n * \u2550\u2550 ITEMS ARE ASKED FOR ON EVERY OPEN \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * `load({ query, offset, limit, signal })` answers an array, or\n * `{ items, total?, status? }`, now or in a promise. With `search: 'local'` it\n * is asked once per open and typing filters what it answered, names ahead of\n * other matches. With `search: 'remote'` typing is debounced and asked again,\n * and a `total` above what is drawn offers Load more. Either way only the\n * newest question's answer paints: every read carries a sequence number and an\n * AbortSignal, and an answer to an older question is dropped however it\n * arrives. The last unsearched answer, per `cacheKey()`, is drawn at once on\n * the next open while it is asked for again.\n *\n * \u2550\u2550 THE KEYBOARD \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * The caret stays in the input, so typing always types. The arrows walk a\n * highlight over every stop, wrapping: the rows a person can choose (a disabled\n * one is stepped over), Load more, the action rows, the card's buttons, the\n * footer's. Until they move, the highlight is the first row or action row of\n * what is shown, and Enter takes it, or, while the answer to what was typed is\n * on its way, takes the first one when it lands. Shift+Delete removes the\n * highlighted row. Esc closes and gives focus back to where it was, as does a\n * pick or a verb, before it runs, so a dialog it opens opens over nothing. A\n * press outside closes and leaves focus where it was pressed. Tab leaves the\n * input for the panel's buttons, and out of the panel closes it.\n *\n * \u2550\u2550 NOTHING IS REBUILT UNDER A POINTER \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A click fires only when the press and the release land on one node. So every\n * part is reconciled by key: an answer, a card or a `setCurrent` updates nodes\n * in place, and a node is created or removed only for a key that came or went.\n * Which node holds what lives in maps here, never in DOM attributes.\n *\n * Nor is a list moved under one. The list scrolls to the highlight only when the\n * keyboard moved the highlight, `open({ select })` asked for a row, or the row\n * the arrows chose went away; typing and a new query's answer go back to the top.\n * A redraw, Load more by the mouse and a removal leave the scroll where it is.\n *\n * \u2550\u2550 AN ASYNC REMOVE MAY ASK \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * While the promise `onRemove` returned is unsettled the panel and its backdrop\n * step below managed windows and do not close on a press outside, so a\n * confirmation dialog can be answered and the switcher is still there afterwards.\n */\n\nimport { ActionDropdown } from './action_dropdown.js';\nimport { createRafResizeObserver } from '../utils/raf_resize_observer.js';\n\nconst DEFAULT_LABELS = Object.freeze({\n loading: 'Loading\u2026',\n empty: () => 'Nothing to show.',\n noMatch: (query) => `Nothing matches \u201C${query}\u201D.`,\n failed: (err) => `The list could not be read. ${err?.message || ''}`.trim(),\n failedMore: (err) => `The next page could not be read. ${err?.message || ''}`.trim(),\n failedRemove: (err) => `Could not remove it. ${err?.message || ''}`.trim(),\n loadMore: ({ next, shown, total }) => `Load ${next} more \u00B7 ${shown} of ${total} shown`,\n remove: (name) => `Remove ${name}`,\n});\n\nconst PANEL_EDGE = 8;\n/** How far the panel's input row stands above the field it covers. */\nconst OVER_LIFT = 3;\n\nlet nextUid = 0;\n\nfunction part(tag, className, text = null) {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text != null) node.textContent = text;\n return node;\n}\n\nfunction glyph(name, className = '') {\n const node = part('span', `material-symbols-outlined ${className}`.trim(), name);\n node.setAttribute('aria-hidden', 'true');\n return node;\n}\n\n/** Write text only when it changed: a write that changes nothing is still a\n * mutation, and a screen reader hears it. */\nfunction setText(node, text) {\n const value = String(text ?? '');\n if (node.textContent !== value) node.textContent = value;\n}\n\nfunction show(node, shown) {\n node.hidden = !shown;\n}\n\nfunction button(className) {\n const node = part('button', className);\n node.type = 'button';\n return node;\n}\n\n/**\n * Keep `container`'s children one per key: `build()` makes `{ node, ... }` for\n * a new key, `update(entry, item)` brings any entry up to date, a key that went\n * loses its node, and a node already in its place is not moved (moving one\n * under a pressed pointer is half of rebuilding it).\n * @returns {(items: object[], keyOf: (item: object) => unknown) => Map<string, object>}\n */\nfunction keyedChildren(container, build, update) {\n let drawn = new Map();\n return (items, keyOf) => {\n const next = new Map();\n const nodes = items.map((item) => {\n const key = String(keyOf(item));\n const entry = drawn.get(key) ?? build();\n update(entry, item);\n next.set(key, entry);\n return entry.node;\n });\n for (const [key, entry] of drawn) {\n if (!next.has(key)) entry.node.remove();\n }\n drawn = next;\n nodes.forEach((node, index) => {\n if (container.children[index] !== node) {\n container.insertBefore(node, container.children[index] || null);\n }\n });\n return drawn;\n };\n}\n\nfunction parseChord(chord) {\n const parts = String(chord).split('+').map((p) => p.trim().toLowerCase());\n const key = parts.pop();\n const known = new Set(['ctrl', 'cmd', 'meta', 'shift', 'alt']);\n if (!key || parts.some((p) => !known.has(p))) {\n throw new TypeError(`createWorkspacePicker: cannot read the chord \"${chord}\"`);\n }\n return {\n key,\n ctrl: parts.includes('ctrl') || parts.includes('cmd') || parts.includes('meta'),\n shift: parts.includes('shift'),\n alt: parts.includes('alt'),\n };\n}\n\nfunction chordMatches(parsed, event) {\n return (event.ctrlKey || event.metaKey) === parsed.ctrl\n && event.shiftKey === parsed.shift\n && event.altKey === parsed.alt\n && String(event.key).toLowerCase() === parsed.key;\n}\n\n/**\n * Mount the field into `hostEl`.\n *\n * `layout: 'centered'` places it in the middle of `hostEl` (which must be\n * positioned) at the width the host can spare between the elements `avoid`\n * selects: at most `maxWidth`, without the key hint below `tightWidth`, and\n * hidden below `minWidth`. `layout: 'inline'` leaves its width to the host and\n * only drops the key hint.\n *\n * @param {HTMLElement} hostEl\n * @param {object} [options]\n * @param {string} [options.name] - The name it shows\n * @param {string} [options.icon] - A Material Symbols name\n * @param {string} [options.keyHint] - Drawn as a key; none by default\n * @param {boolean} [options.muted] - Draw the name as naming nothing\n * @param {boolean} [options.caret] - A trailing caret, for an inline field\n * @param {string} [options.tooltip]\n * @param {string} [options.ariaLabel]\n * @param {string} [options.className] - Extra classes\n * @param {'centered'|'inline'} [options.layout]\n * @param {string} [options.avoid] - Selector, within `hostEl`, of what it must not cover\n * @param {number} [options.maxWidth]\n * @param {number} [options.minWidth]\n * @param {number} [options.tightWidth]\n * @param {number} [options.gap] - Room kept free in all, shared between the two sides\n * @param {() => void} [options.onActivate] - A click\n * @returns {{ el: HTMLButtonElement, update: (patch: object) => void, setOpen: (open: boolean) => void, fit: () => void, destroy: () => void }}\n */\nexport function mountPickerField(hostEl, {\n name = '',\n icon = '',\n keyHint = '',\n muted = false,\n caret = false,\n tooltip = '',\n ariaLabel = '',\n className = '',\n layout = 'inline',\n avoid = '',\n maxWidth = 440,\n minWidth = 120,\n tightWidth = 230,\n gap = 24,\n onActivate = null,\n} = {}) {\n const centered = layout === 'centered';\n const el = button(['twm-wspicker-field', centered ? 'twm-wspicker-field--centered' : '', className]\n .filter(Boolean).join(' '));\n el.setAttribute('aria-haspopup', 'dialog');\n el.setAttribute('aria-expanded', 'false');\n const iconEl = glyph('', 'twm-wspicker-field__icon');\n const nameEl = part('span', 'twm-wspicker-field__name');\n const keyEl = part('kbd', 'twm-wspicker-field__key');\n el.append(iconEl, nameEl, keyEl);\n if (caret) el.append(glyph('expand_more', 'twm-wspicker-field__caret'));\n\n const update = (patch) => {\n if ('name' in patch) setText(nameEl, patch.name);\n if ('icon' in patch) {\n setText(iconEl, patch.icon);\n show(iconEl, !!patch.icon);\n }\n if ('keyHint' in patch) {\n setText(keyEl, patch.keyHint);\n show(keyEl, !!patch.keyHint);\n }\n if ('muted' in patch) el.classList.toggle('twm-wspicker-field--muted', !!patch.muted);\n if ('tooltip' in patch) {\n el.classList.toggle('twm-has-tooltip', !!patch.tooltip);\n if (patch.tooltip) {\n el.setAttribute('data-tooltip', patch.tooltip);\n el.setAttribute('data-tooltip-placement', 'bottom');\n } else {\n el.removeAttribute('data-tooltip');\n el.removeAttribute('data-tooltip-placement');\n }\n }\n if ('ariaLabel' in patch) {\n if (patch.ariaLabel) el.setAttribute('aria-label', patch.ariaLabel);\n else el.removeAttribute('aria-label');\n }\n };\n update({ name, icon, keyHint, muted, tooltip, ariaLabel });\n\n const fit = () => {\n if (!centered) {\n el.classList.toggle('twm-wspicker-field--tight', el.getBoundingClientRect().width < tightWidth);\n return;\n }\n const box = hostEl.getBoundingClientRect();\n const middle = box.left + box.width / 2;\n let leftEdge = box.left;\n let rightEdge = box.right;\n for (const other of avoid ? hostEl.querySelectorAll(avoid) : []) {\n if (el.contains(other)) continue;\n const r = other.getBoundingClientRect();\n if (r.width <= 0) continue;\n if (r.left + r.width / 2 < middle) leftEdge = Math.max(leftEdge, r.right);\n else rightEdge = Math.min(rightEdge, r.left);\n }\n const width = Math.min(maxWidth, 2 * Math.min(middle - leftEdge, rightEdge - middle) - gap);\n el.classList.toggle('twm-wspicker-field--hidden', width < minWidth);\n el.classList.toggle('twm-wspicker-field--tight', width < tightWidth);\n el.style.width = `${Math.max(minWidth, width)}px`;\n };\n\n let destroyed = false;\n const onClick = () => onActivate?.();\n el.addEventListener('click', onClick);\n hostEl.appendChild(el);\n const observer = createRafResizeObserver(() => {\n if (!destroyed) fit();\n });\n observer.observe(centered ? hostEl : el);\n fit();\n document.fonts?.ready?.then(() => {\n if (!destroyed) fit();\n });\n\n return {\n el,\n update,\n fit,\n setOpen(open) {\n el.classList.toggle('twm-wspicker-field--open', open);\n el.setAttribute('aria-expanded', String(open));\n },\n destroy() {\n destroyed = true;\n observer.disconnect();\n el.removeEventListener('click', onClick);\n el.remove();\n },\n };\n}\n\n/**\n * The switcher. See the file's header for how it asks and how it behaves.\n *\n * @param {object} options\n * @param {HTMLElement} [options.anchor] - What it opens from. With none, or one\n * that takes no room, it opens centred over a dimmed page.\n * @param {'over'|'below'} [options.placement] - `over` lays the input over the\n * anchor; `below` hangs from it, flipped above when there is no room.\n * @param {number} [options.minWidth] - The anchored panel's least width\n * @param {number} [options.visibleRows] - Scroll past this many two-line rows\n * @param {string} [options.className] - Extra classes on the panel\n * @param {string} [options.label] - The panel's accessible name\n * @param {string} [options.listLabel] - The list's accessible name\n * @param {string} [options.placeholder] - The input's placeholder\n * @param {string} [options.glyph] - The icon before the input\n * @param {(request: {query: string, offset: number, limit: number, signal: AbortSignal}) => (object[]|{items: object[], total?: number, status?: string|{text: string, error?: boolean}}|Promise)} options.load\n * @param {'local'|'remote'} [options.search]\n * @param {number} [options.pageSize] - `limit`, in remote search\n * @param {number} [options.debounceMs] - How long typing waits, in remote search\n * @param {() => string} [options.cacheKey] - Whose list the kept answer is\n * @param {(item: object, ctx: {current: boolean}) => {id: string|number, name: string, detail?: string, icon?: string, badge?: string, title?: string, keywords?: string|string[], disabled?: boolean, removable?: boolean}} options.describe\n * @param {(item: object) => void} [options.onPick] - A row other than the current one chosen\n * @param {(item: object) => (boolean|void|Promise<boolean|void>)} [options.onRemove] -\n * Offers a bin on each row whose `removable` is not false. Answering `false`\n * keeps the row; rejecting keeps it and shows the error.\n * @param {(ctx: {query: string}) => Array<{id: string, label: string, detail?: string, icon?: string, always?: boolean, run: (ctx: {query: string}) => void}>} [options.actions] -\n * Rows after the items, narrowed by typing unless `always`.\n * @param {(ctx: {query: string, shown: number, total: number|null}) => ({title?: string, count?: string}|null)} [options.heading]\n * @param {(ctx: {current: object|null, row: object|null}) => ({heading?: string, icon?: string, name: string, detail?: string, open?: {label: string, icon?: string, run: Function}, columns?: number, tiles?: Array<{id: string, label: string, icon?: string, run: Function}>}|null)} [options.card]\n * @param {() => ({start?: object[], end?: object[], keys?: Array<{keys: string[], label: string}>}|null)} [options.footer] -\n * Buttons are `{ id, label, icon?, trailing?, primary?, run }`. `keys` are drawn\n * only when the panel is centred.\n * @param {object} [options.labels] - Replaces any of the default strings\n * @param {(open: boolean) => void} [options.onOpenChange]\n */\nexport function createPickerSwitcher({\n anchor = null,\n placement = 'over',\n minWidth = 520,\n visibleRows = 0,\n className = '',\n label = '',\n listLabel = '',\n placeholder = '',\n glyph: inputGlyph = 'search',\n load,\n search = 'local',\n pageSize = 20,\n debounceMs = 200,\n cacheKey = () => '',\n describe,\n onPick = null,\n onRemove = null,\n actions = null,\n heading = null,\n card = null,\n footer = null,\n labels: labelOverrides = {},\n onOpenChange = null,\n}) {\n const labels = { ...DEFAULT_LABELS, ...labelOverrides };\n const remote = search === 'remote';\n const uid = `twm-wspicker-${++nextUid}`;\n\n let isOpen = false;\n let destroyed = false;\n let current = null;\n /** What the last answer held, in its order. */\n let items = [];\n let total = null;\n let status = null;\n /** The query the drawn items answer, and the newest one asked. */\n let answered = '';\n let asked = '';\n let seq = 0;\n let abort = null;\n let loading = false;\n let loadingMore = false;\n let failure = null;\n let timer = null;\n /** Enter came before the answer to what was typed. */\n let pickFirst = false;\n /** Which row to highlight when the next answer lands. */\n let selectId = null;\n /** An `onRemove` promise is unsettled. */\n let busy = false;\n /** Where focus was when it opened. */\n let opener = null;\n /** Every place the arrows stop, in order. */\n let stops = [];\n let activeKey = null;\n let activeNode = null;\n /** The arrows chose the highlight; an answer does not move it. */\n let moved = false;\n let nextEntryId = 0;\n const kept = new Map();\n\n const idOf = (item) => String(describe(item, { current: false }).id);\n const isCurrent = (item) => current != null && idOf(item) === idOf(current);\n const modelOf = (item) => describe(item, { current: isCurrent(item) });\n const typed = () => input.value.trim();\n\n // \u2500\u2500 the panel, built once \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const backdrop = part('div', 'twm-wspicker-backdrop');\n const panel = part('div', `twm-wspicker ${className}`.trim());\n panel.setAttribute('role', 'dialog');\n if (label) panel.setAttribute('aria-label', label);\n\n const searchRow = part('div', 'twm-wspicker__search');\n const input = part('input', 'twm-wspicker__input');\n input.type = 'text';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.placeholder = placeholder;\n if (placeholder) input.setAttribute('aria-label', placeholder);\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `${uid}-list`);\n searchRow.append(glyph(inputGlyph, 'twm-wspicker__glyph'), input);\n\n const head = part('div', 'twm-wspicker__head');\n const headTitle = part('span', 'twm-wspicker__title');\n const headCount = part('span', 'twm-wspicker__count');\n head.append(headTitle, headCount);\n\n const scroller = part('div', 'twm-wspicker__scroll');\n if (visibleRows > 0) {\n scroller.classList.add('twm-wspicker__scroll--capped');\n scroller.style.setProperty('--twm-wspicker-rows', String(visibleRows));\n }\n const list = part('div', 'twm-wspicker__list');\n list.id = `${uid}-list`;\n list.setAttribute('role', 'listbox');\n if (listLabel) list.setAttribute('aria-label', listLabel);\n const note = part('p', 'twm-wspicker__note');\n note.setAttribute('role', 'status');\n const more = button('twm-btn twm-wspicker__more');\n const moreLabel = part('span', 'twm-wspicker__more-label');\n more.append(glyph('expand_more'), moreLabel);\n const actionList = part('div', 'twm-wspicker__actions');\n actionList.setAttribute('role', 'listbox');\n scroller.append(list, note, more, actionList);\n\n const cardEl = part('section', 'twm-wspicker__card');\n const cardHeading = part('h3', 'twm-wspicker__card-heading');\n const cardHead = part('div', 'twm-wspicker__card-head');\n const cardIcon = glyph('', 'twm-wspicker__card-icon');\n const cardText = part('span', 'twm-wspicker__card-text');\n const cardName = part('span', 'twm-wspicker__card-name');\n const cardDetail = part('span', 'twm-wspicker__card-detail');\n cardText.append(cardName, cardDetail);\n const cardOpen = button('twm-btn twm-wspicker__card-open');\n const cardOpenIcon = glyph('');\n const cardOpenLabel = part('span', '');\n cardOpen.append(cardOpenIcon, cardOpenLabel);\n cardHead.append(cardIcon, cardText, cardOpen);\n const tiles = part('div', 'twm-wspicker__tiles');\n cardEl.append(cardHeading, cardHead, tiles);\n\n const foot = part('div', 'twm-wspicker__foot');\n const footStatus = part('span', 'twm-wspicker__status');\n const footStart = part('div', 'twm-wspicker__foot-group');\n const footEnd = part('div', 'twm-wspicker__foot-group');\n const footKeys = part('span', 'twm-wspicker__keys');\n foot.append(footStart, footStatus, footEnd, footKeys);\n\n panel.append(searchRow, head, scroller, cardEl, foot);\n\n // \u2500\u2500 rows, the items' and the action rows' \u2500\u2500\u2500\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 function buildRow() {\n const node = part('div', 'twm-wspicker__row');\n node.id = `${uid}-row-${++nextEntryId}`;\n node.setAttribute('role', 'option');\n const icon = glyph('', 'twm-wspicker__row-icon');\n const text = part('span', 'twm-wspicker__row-text');\n const name = part('span', 'twm-wspicker__row-name');\n const detail = part('span', 'twm-wspicker__row-detail');\n text.append(name, detail);\n const badge = part('span', 'twm-wspicker__row-badge');\n const check = glyph('check', 'twm-wspicker__row-check');\n const bin = button('twm-wspicker__row-remove');\n bin.tabIndex = -1;\n bin.append(glyph('delete'));\n node.append(icon, text, badge, check, bin);\n const entry = { node, icon, name, detail, badge, check, bin, run: null, remove: null };\n node.addEventListener('click', () => entry.run?.());\n bin.addEventListener('click', (event) => {\n event.stopPropagation();\n entry.remove?.();\n });\n return entry;\n }\n\n function paintRow(entry, { name, detail, icon, badge, title, disabled = false, isCurrentRow = false }) {\n setText(entry.icon, icon);\n setText(entry.name, name);\n setText(entry.detail, detail);\n show(entry.detail, !!detail);\n setText(entry.badge, badge);\n show(entry.badge, !!badge);\n show(entry.check, isCurrentRow);\n entry.node.classList.toggle('twm-wspicker__row--current', isCurrentRow);\n entry.node.classList.toggle('twm-wspicker__row--disabled', disabled);\n entry.node.setAttribute('aria-selected', String(isCurrentRow));\n if (disabled) entry.node.setAttribute('aria-disabled', 'true');\n else entry.node.removeAttribute('aria-disabled');\n entry.node.title = title ?? (detail ? `${name} \u2014 ${detail}` : name);\n }\n\n const syncRows = keyedChildren(list, buildRow, (entry, item) => {\n const model = modelOf(item);\n const disabled = !!model.disabled;\n paintRow(entry, { ...model, disabled, isCurrentRow: isCurrent(item) });\n entry.run = disabled ? null : () => pick(item);\n const removable = !!onRemove && model.removable !== false;\n entry.remove = removable ? () => removeItem(item) : null;\n show(entry.bin, removable);\n if (removable) {\n const words = labels.remove(model.name);\n entry.bin.setAttribute('aria-label', words);\n entry.bin.title = words;\n }\n });\n\n const syncActions = keyedChildren(actionList, buildRow, (entry, action) => {\n paintRow(entry, { name: action.label, detail: action.detail, icon: action.icon, title: action.title });\n entry.run = () => runVerb(action.run);\n show(entry.bin, false);\n });\n\n /** What typing leaves of the answer: names ahead of other matches. */\n function shownItems() {\n const query = typed().toLowerCase();\n if (remote || !query) return items;\n const names = [];\n const others = [];\n for (const item of items) {\n const { name, detail, keywords } = modelOf(item);\n if (String(name).toLowerCase().includes(query)) names.push(item);\n else if ([detail, keywords].flat().some((text) => String(text ?? '').toLowerCase().includes(query))) others.push(item);\n }\n return [...names, ...others];\n }\n\n function shownActions() {\n if (!actions) return [];\n const query = typed();\n const lower = query.toLowerCase();\n return actions({ query }).filter((action) => action.always || !lower\n || String(action.label).toLowerCase().includes(lower));\n }\n\n // \u2500\u2500 the card and the footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function buildVerb(hook) {\n return () => {\n const node = button(`twm-btn ${hook}`);\n const icon = glyph('');\n const text = part('span', '');\n const trailing = glyph('');\n node.append(icon, text, trailing);\n const entry = { node, icon, text, trailing, run: null };\n node.addEventListener('click', () => entry.run?.());\n return entry;\n };\n }\n\n function paintVerb(entry, verb) {\n setText(entry.icon, verb.icon);\n setText(entry.text, verb.label);\n setText(entry.trailing, verb.trailing);\n entry.node.classList.toggle('twm-btn--primary', !!verb.primary);\n entry.node.title = verb.label;\n entry.run = () => runVerb(verb.run);\n }\n\n const syncTiles = keyedChildren(tiles, buildVerb('twm-wspicker__tile'), paintVerb);\n const syncFootStart = keyedChildren(footStart, buildVerb('twm-wspicker__foot-btn'), paintVerb);\n const syncFootEnd = keyedChildren(footEnd, buildVerb('twm-wspicker__foot-btn'), paintVerb);\n let drawnTiles = new Map();\n let drawnFoot = new Map();\n let cardOpenRun = null;\n\n cardOpen.addEventListener('click', () => cardOpenRun?.());\n\n function renderCard() {\n const row = current == null ? null : items.find((item) => isCurrent(item)) ?? null;\n const model = card ? card({ current, row }) : null;\n show(cardEl, !!model);\n drawnTiles = syncTiles(model?.tiles || [], (tile) => tile.id);\n cardOpenRun = model?.open ? () => runVerb(model.open.run) : null;\n show(cardOpen, !!model?.open);\n if (!model) return;\n setText(cardHeading, model.heading);\n show(cardHeading, !!model.heading);\n setText(cardIcon, model.icon);\n setText(cardName, model.name);\n setText(cardDetail, model.detail);\n cardName.title = model.name;\n setText(cardOpenIcon, model.open?.icon);\n setText(cardOpenLabel, model.open?.label);\n tiles.style.setProperty('--twm-wspicker-columns', String(model.columns || 2));\n }\n\n function renderFooter() {\n const model = footer ? footer() : null;\n const start = syncFootStart(model?.start || [], (verb) => verb.id);\n const end = syncFootEnd(model?.end || [], (verb) => verb.id);\n drawnFoot = new Map([...[...start].map(([key, entry]) => [`start:${key}`, entry]),\n ...[...end].map(([key, entry]) => [`end:${key}`, entry])]);\n footKeys.replaceChildren(...(model?.keys || []).map(({ keys, label: words }) => {\n const hint = part('span', 'twm-wspicker__key-hint');\n hint.append(...keys.map((key) => part('kbd', '', key)), ` ${words}`);\n return hint;\n }));\n const { text = '', error = false } = typeof status === 'string' ? { text: status } : status ?? {};\n setText(footStatus, text);\n show(footStatus, !!text);\n footStatus.classList.toggle('twm-wspicker__status--error', !!error);\n const keysShown = footKeys.childElementCount > 0 && panel.classList.contains('twm-wspicker--centered');\n show(foot, !!text || keysShown || drawnFoot.size > 0);\n }\n\n // \u2500\u2500 the highlight \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function collectStops(rowEntries, actionEntries, shown) {\n const next = [];\n for (const item of shown) {\n const entry = rowEntries.get(idOf(item));\n if (entry?.run) next.push({ key: `row:${idOf(item)}`, node: entry.node, run: entry.run, remove: entry.remove, primary: true });\n }\n if (!more.hidden) next.push({ key: 'more', node: more, run: () => loadMore({ byKey: true }) });\n for (const [key, entry] of actionEntries) next.push({ key: `action:${key}`, node: entry.node, run: entry.run, primary: true });\n if (!cardEl.hidden) {\n if (!cardOpen.hidden) next.push({ key: 'card-open', node: cardOpen, run: () => cardOpenRun?.() });\n for (const [key, entry] of drawnTiles) next.push({ key: `tile:${key}`, node: entry.node, run: entry.run });\n }\n for (const [key, entry] of drawnFoot) next.push({ key: `foot:${key}`, node: entry.node, run: entry.run });\n stops = next;\n }\n\n function paintActive() {\n const stop = stops.find((s) => s.key === activeKey) ?? null;\n if (activeNode && activeNode !== stop?.node) activeNode.classList.remove('twm-wspicker__stop--active');\n activeNode = stop?.node ?? null;\n activeNode?.classList.add('twm-wspicker__stop--active');\n if (activeNode?.id) input.setAttribute('aria-activedescendant', activeNode.id);\n else input.removeAttribute('aria-activedescendant');\n }\n\n function revealActive() {\n activeNode?.scrollIntoView?.({ block: 'nearest' });\n }\n\n function settleActive() {\n let reveal = false;\n if (selectId != null && stops.some((s) => s.key === `row:${selectId}`)) {\n activeKey = `row:${selectId}`;\n moved = true;\n selectId = null;\n reveal = true;\n }\n if (!moved || !stops.some((s) => s.key === activeKey)) {\n reveal = moved;\n moved = false;\n activeKey = stops.find((s) => s.primary)?.key ?? null;\n }\n paintActive();\n if (reveal) revealActive();\n }\n\n function move(step) {\n if (!stops.length) return;\n const at = stops.findIndex((s) => s.key === activeKey);\n const next = at === -1 ? (step > 0 ? 0 : stops.length - 1) : (at + step + stops.length) % stops.length;\n activeKey = stops[next].key;\n moved = true;\n paintActive();\n revealActive();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function render() {\n const shown = shownItems();\n const query = remote ? answered : typed();\n const rowEntries = syncRows(shown, idOf);\n const actionEntries = syncActions(shownActions(), (action) => action.id);\n\n const words = heading ? heading({ query, shown: shown.length, total }) : null;\n show(head, !!(words?.title || words?.count));\n setText(headTitle, words?.title);\n setText(headCount, words?.count);\n\n let said = '';\n if (failure) said = failure;\n else if (!shown.length && (loading || total == null)) said = labels.loading;\n else if (!shown.length) said = query ? labels.noMatch(query) : labels.empty();\n setText(note, said);\n show(note, !!said);\n note.classList.toggle('twm-wspicker__note--error', !!failure);\n\n const remaining = remote && total != null ? Math.max(0, total - items.length) : 0;\n show(more, remaining > 0 && !failure);\n if (remaining > 0) {\n setText(moreLabel, labels.loadMore({ next: Math.min(pageSize, remaining), shown: items.length, total }));\n }\n more.disabled = loading || loadingMore;\n\n collectStops(rowEntries, actionEntries, shown);\n settleActive();\n }\n\n function renderEverything() {\n renderCard();\n renderFooter();\n render();\n }\n\n // \u2500\u2500 asking \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function normalize(answer) {\n if (Array.isArray(answer)) return { items: answer, total: answer.length, status: null };\n const list_ = answer?.items || [];\n return {\n items: list_,\n total: Number.isFinite(answer?.total) ? answer.total : list_.length,\n status: answer?.status ?? null,\n };\n }\n\n function unique(all) {\n const seen = new Set();\n return all.filter((item) => {\n const id = idOf(item);\n if (seen.has(id)) return false;\n seen.add(id);\n return true;\n });\n }\n\n async function ask(query) {\n const mine = ++seq;\n asked = query;\n abort?.abort();\n abort = new AbortController();\n const { signal } = abort;\n loading = true;\n failure = null;\n loadingMore = false;\n render();\n try {\n const answer = normalize(await load({ query, offset: 0, limit: pageSize, signal }));\n if (destroyed || mine !== seq) return;\n items = unique(answer.items);\n total = answer.total;\n status = answer.status;\n if (query !== answered) scroller.scrollTop = 0;\n answered = query;\n loading = false;\n if (!query) kept.set(cacheKey(), { items: [...items], total, status });\n renderEverything();\n if (placementNow() === 'below') place();\n if (pickFirst) {\n pickFirst = false;\n stops.find((s) => s.primary)?.run();\n }\n } catch (err) {\n if (destroyed || mine !== seq || err?.name === 'AbortError') return;\n loading = false;\n pickFirst = false;\n items = [];\n total = null;\n status = null;\n answered = query;\n failure = labels.failed(err);\n renderEverything();\n }\n }\n\n async function loadMore({ byKey = false } = {}) {\n if (loading || loadingMore || total == null || items.length >= total) return;\n const mine = seq;\n loadingMore = true;\n render();\n let added = [];\n try {\n const answer = normalize(await load({ query: answered, offset: items.length, limit: pageSize, signal: abort?.signal }));\n if (destroyed || mine !== seq) return;\n const seen = new Set(items.map(idOf));\n added = unique(answer.items).filter((item) => !seen.has(idOf(item)));\n items = items.concat(added);\n // A server that ignores the paging hands back what is drawn: there\n // is no more, whatever it said before.\n total = added.length && Number.isFinite(answer.total) ? answer.total : items.length;\n if (answer.status != null) status = answer.status;\n } catch (err) {\n if (destroyed || mine !== seq || err?.name === 'AbortError') return;\n failure = labels.failedMore(err);\n }\n loadingMore = false;\n // The highlight stays on Load more while there is more, else goes to\n // the first row it brought that can be chosen.\n const stayed = activeKey === 'more';\n if (stayed && items.length >= total) {\n const first = added.find((item) => !modelOf(item).disabled);\n if (first) {\n activeKey = `row:${idOf(first)}`;\n moved = true;\n }\n }\n renderEverything();\n if (byKey && stayed) revealActive();\n }\n\n more.addEventListener('click', () => loadMore());\n\n function setBusy(waiting) {\n busy = waiting;\n panel.classList.toggle('twm-wspicker--waiting', waiting);\n backdrop.classList.toggle('twm-wspicker-backdrop--waiting', waiting);\n }\n\n async function removeItem(item) {\n if (busy) return;\n const removedKey = `row:${idOf(item)}`;\n const at = stops.findIndex((s) => s.key === removedKey);\n const following = stops.slice(at + 1).find((s) => s.key.startsWith('row:'))\n ?? stops.slice(0, Math.max(at, 0)).reverse().find((s) => s.key.startsWith('row:'));\n // Before the call: a dialog it opens takes focus before it returns.\n setBusy(true);\n let outcome;\n try {\n outcome = await onRemove(item);\n } catch (err) {\n setBusy(false);\n if (isOpen) {\n failure = labels.failedRemove(err);\n render();\n input.focus();\n }\n return;\n }\n setBusy(false);\n if (!isOpen) return;\n if (outcome !== false) {\n items = items.filter((other) => idOf(other) !== idOf(item));\n if (total != null) total = Math.max(0, total - 1);\n if (activeKey === removedKey && following) {\n activeKey = following.key;\n moved = true;\n }\n ask(remote ? answered : '');\n }\n input.focus();\n }\n\n // \u2500\u2500 choosing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function pick(item) {\n const same = isCurrent(item);\n close({ restoreFocus: true });\n if (!same) onPick?.(item);\n }\n\n function runVerb(run) {\n const query = typed();\n close({ restoreFocus: true });\n run?.({ query });\n }\n\n function enter() {\n const query = typed();\n if (remote && query !== asked) {\n clearTimeout(timer);\n timer = null;\n pickFirst = true;\n ask(query);\n return;\n }\n if (loading && !moved) {\n pickFirst = true;\n return;\n }\n stops.find((s) => s.key === activeKey)?.run();\n }\n\n // \u2500\u2500 placing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function placementNow() {\n if (!anchor?.isConnected) return 'centered';\n return anchor.getBoundingClientRect().width > 0 ? placement : 'centered';\n }\n\n function place() {\n const mode = placementNow();\n for (const name of ['over', 'below', 'centered']) {\n panel.classList.toggle(`twm-wspicker--${name}`, mode === name);\n }\n show(backdrop, mode === 'centered');\n for (const side of ['top', 'bottom', 'left', 'right', 'width', 'maxHeight', 'overflowY', 'position']) panel.style[side] = '';\n if (mode === 'centered') return;\n const r = anchor.getBoundingClientRect();\n const width = Math.min(Math.max(r.width, minWidth), window.innerWidth - 2 * PANEL_EDGE);\n panel.style.width = `${width}px`;\n if (mode === 'below') {\n ActionDropdown.position(anchor, panel);\n return;\n }\n const left = r.left + r.width / 2 - width / 2;\n panel.style.left = `${Math.max(PANEL_EDGE, Math.min(left, window.innerWidth - width - PANEL_EDGE))}px`;\n // A field in the lower half (a bottom bar) grows upward, its bottom edge\n // where the field's is, because a list hanging below it has no room.\n if (r.top + r.height / 2 > window.innerHeight / 2) {\n panel.style.bottom = `${Math.max(2, window.innerHeight - r.bottom - OVER_LIFT)}px`;\n } else {\n panel.style.top = `${Math.max(2, r.top - OVER_LIFT)}px`;\n }\n }\n\n // \u2500\u2500 opening and closing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function openPanel({ select = null } = {}) {\n if (isOpen || destroyed) return;\n isOpen = true;\n opener = document.activeElement;\n selectId = select == null ? null : String(select);\n input.value = '';\n clearTimeout(timer);\n timer = null;\n pickFirst = false;\n moved = false;\n activeKey = null;\n const last = kept.get(cacheKey());\n items = last ? [...last.items] : [];\n total = last ? last.total : null;\n status = last ? last.status : null;\n answered = '';\n asked = '';\n failure = null;\n document.body.append(backdrop, panel);\n place();\n renderEverything();\n scroller.scrollTop = 0;\n document.addEventListener('mousedown', onDocumentDown, true);\n document.addEventListener('keydown', onDocumentKey);\n window.addEventListener('resize', place);\n input.focus();\n onOpenChange?.(true);\n ask('');\n }\n\n function close({ restoreFocus = false } = {}) {\n if (!isOpen) return;\n isOpen = false;\n clearTimeout(timer);\n timer = null;\n pickFirst = false;\n selectId = null;\n // An answer that lands after the panel closed paints nothing.\n seq += 1;\n abort?.abort();\n loading = false;\n loadingMore = false;\n setBusy(false);\n panel.remove();\n backdrop.remove();\n document.removeEventListener('mousedown', onDocumentDown, true);\n document.removeEventListener('keydown', onDocumentKey);\n window.removeEventListener('resize', place);\n onOpenChange?.(false);\n if (restoreFocus && !destroyed) {\n const back = opener?.isConnected && opener !== document.body ? opener : anchor;\n back?.focus?.();\n }\n opener = null;\n }\n\n /** In the capture phase, so a surface that stops the event still closes it. */\n function onDocumentDown(event) {\n if (busy || panel.contains(event.target) || anchor?.contains?.(event.target)) return;\n close();\n }\n\n /** Esc with the focus outside the panel: on the anchor, say. */\n function onDocumentKey(event) {\n if (busy || event.key !== 'Escape' || panel.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n close({ restoreFocus: true });\n }\n\n // The caret stays in the input whatever is pressed in the panel.\n panel.addEventListener('mousedown', (event) => {\n if (event.target !== input) event.preventDefault();\n });\n\n input.addEventListener('input', () => {\n moved = false;\n scroller.scrollTop = 0;\n if (remote) {\n clearTimeout(timer);\n const query = typed();\n timer = setTimeout(() => {\n timer = null;\n if (query !== asked) ask(query);\n }, debounceMs);\n }\n render();\n });\n\n panel.addEventListener('keydown', (event) => {\n if (event.isComposing || busy) return;\n const { key, shiftKey, target } = event;\n const handled = () => {\n event.preventDefault();\n event.stopPropagation();\n };\n if (key === 'Escape') {\n handled();\n close({ restoreFocus: true });\n } else if (key === 'ArrowDown' || key === 'ArrowUp') {\n handled();\n if (document.activeElement !== input) input.focus();\n move(key === 'ArrowDown' ? 1 : -1);\n } else if (key === 'Enter' && target === input) {\n handled();\n enter();\n } else if (key === 'Delete' && shiftKey && target === input) {\n handled();\n stops.find((s) => s.key === activeKey)?.remove?.();\n } else if (key === 'Backspace' && target !== input) {\n // A window manager's keymap reads Backspace on anything that is not\n // a field as \"up one level\"; a button of this panel is not a field.\n handled();\n }\n });\n\n panel.addEventListener('focusout', (event) => {\n const to = event.relatedTarget;\n if (!busy && to && !panel.contains(to) && !anchor?.contains?.(to)) close();\n });\n\n return {\n panel,\n input,\n get isOpen() { return isOpen; },\n get current() { return current; },\n open: openPanel,\n close,\n toggle() {\n if (isOpen) close({ restoreFocus: true });\n else openPanel();\n },\n /** Which one the window is in, whether or not an answer holds it. */\n setCurrent(item) {\n current = item ?? null;\n if (isOpen) renderEverything();\n },\n /** Ask `actions`, `card` and `footer` again: who may do what changed. */\n refresh() {\n if (isOpen) renderEverything();\n },\n /** Ask `load` again: the list changed behind the switcher's back. */\n reload() {\n if (isOpen) ask(remote ? typed() : '');\n },\n destroy() {\n close();\n destroyed = true;\n },\n };\n}\n\n/**\n * The field and the switcher together: a click on the field, or the chord,\n * opens the switcher in the field's place; `setCurrent` names the current item\n * on the field and marks it in the list.\n *\n * `chord` is none by default. Given (`'Ctrl+P'`; Ctrl also answers to Cmd), it\n * is taken on `window` in the capture phase, ahead of an embedded editor and of\n * the browser's own use of the key, and it is the key hint unless\n * `field.keyHint` says otherwise. It still works while the field is hidden for\n * want of room.\n *\n * @param {HTMLElement} hostEl - Where the field mounts\n * @param {object} options - `createPickerSwitcher`'s, and:\n * @param {object} [options.field] - `mountPickerField`'s. `field.placeholder` is\n * its name while nothing is current; `field.icon`, when given, is its icon\n * whatever is current, and otherwise the current item's `icon` is.\n * @param {string} [options.chord]\n */\nexport function createWorkspacePicker(hostEl, { field: fieldOptions = {}, chord = null, ...switcherOptions }) {\n const { placeholder = '', icon: fixedIcon, ...mountOptions } = fieldOptions;\n const parsed = chord ? parseChord(chord) : null;\n const field = mountPickerField(hostEl, {\n ariaLabel: switcherOptions.label,\n keyHint: chord ?? '',\n ...mountOptions,\n onActivate: () => switcher.toggle(),\n });\n const switcher = createPickerSwitcher({\n ...switcherOptions,\n anchor: field.el,\n onOpenChange: (open) => {\n field.setOpen(open);\n switcherOptions.onOpenChange?.(open);\n },\n });\n\n const paint = () => {\n const item = switcher.current;\n const model = item == null ? null : switcherOptions.describe(item, { current: true });\n field.update({\n name: model ? model.name : placeholder,\n icon: fixedIcon ?? model?.icon ?? '',\n muted: !model,\n });\n };\n paint();\n\n const onKeydown = (event) => {\n if (!chordMatches(parsed, event)) return;\n event.preventDefault();\n event.stopPropagation();\n if (!event.repeat) switcher.toggle();\n };\n if (parsed) window.addEventListener('keydown', onKeydown, true);\n\n return {\n field,\n switcher,\n get el() { return field.el; },\n get isOpen() { return switcher.isOpen; },\n get current() { return switcher.current; },\n open: switcher.open,\n close: switcher.close,\n toggle: switcher.toggle,\n refresh: switcher.refresh,\n reload: switcher.reload,\n setCurrent(item) {\n switcher.setCurrent(item);\n paint();\n },\n destroy() {\n if (parsed) window.removeEventListener('keydown', onKeydown, true);\n switcher.destroy();\n field.destroy();\n },\n };\n}\n", "/**\n * WindowChromeController\n *\n * Handles frameless window management for the desktop application:\n * - Window minimize, maximize, close buttons\n * - Resize handles (edges and corners)\n * - Top bar dragging for window movement\n * - F11 fullscreen toggle\n *\n * Talks to the embedder ONLY through a Host's `window` capability\n * (see src/host/host.js). A host with no `window` capability \u2014 a browser\n * tab, a VS Code webview, the standalone demo \u2014 is legal: we simply don't\n * install custom chrome. That degraded path is also the production path on\n * Linux, macOS and `--browser`, where the OS/browser draws the title bar.\n *\n * THREE MODES, decided by `host.window.chrome()` (which may answer with a\n * promise: the Photino host asks its native side): a browser tab and a window\n * with native chrome get NOTHING from this class (no handles, no buttons, no\n * body class), and only a window that answers `custom` gets the chrome.\n *\n * NATIVE GESTURES. A host that offers `startNativeDrag()` and\n * `startNativeResize(edge)` gets drags on the top bar and presses on the\n * resize handles handed to the OS, which brings snapping and a resize that\n * keeps up with the pointer. A host without them gets the JS move and resize\n * over getBounds/setBounds.\n *\n * @param {object} [opts]\n * @param {object} [opts.host] a Host; only its `window` capability is used\n * @param {string|Element} [opts.topBar='.twm-global-top-bar'] the bar that drags the window\n * @param {string|Element} [opts.controls] where to draw minimise/maximise/close when\n * the page has no `#win-minimize`/`#win-maximize`/`#win-close` of its own\n * (default: the top bar's `.twm-bar-right`, else the top bar itself)\n * @param {string} [opts.noDrag] more selectors that never start a drag\n */\n\nconst SUPPORTS_POINTER = typeof window !== 'undefined' && 'onpointerdown' in window;\nconst MIN_WIDTH = 500;\nconst MIN_HEIGHT = 350;\nconst DRAG_THRESHOLD = 4;\n\nexport class WindowChromeController {\n constructor({ eventBus, logger, host, topBar = '.twm-global-top-bar', controls = null, noDrag = '' } = {}) {\n this.eventBus = eventBus;\n this.logger = logger || console;\n this._topBarOpt = topBar;\n this._controlsOpt = controls;\n this._noDrag = noDrag;\n this._createdControls = null;\n\n // The host's window capability, or null. Never throw on a missing\n // one \u2014 see the class comment.\n this.win = host?.window || null;\n\n this.resizingActive = false;\n this.lastDblClickTs = 0;\n this.handles = {};\n this.topBar = null;\n\n this._disposed = false;\n this._disposers = [];\n }\n\n /**\n * Initialize the window chrome controller\n */\n async initialize() {\n if (this._disposed) return false;\n\n let chrome = 'native';\n try { chrome = this.win ? await this.win.chrome() : 'native'; } catch (_) { chrome = 'native'; }\n if (this._disposed) return false;\n if (chrome !== 'custom') {\n // Native window decorations (Linux/macOS) or the browser already\n // provide a title bar + window controls; our custom chrome would be\n // a redundant second set. Skip it entirely.\n this.logger.info?.('[WindowChrome] Native/browser chrome detected \u2014 custom window chrome disabled');\n return false;\n }\n\n document.body.classList.add('twm-custom-chrome');\n this.#createWindowControls();\n this.#wireWindowButtons();\n this.#createResizeHandles();\n this.#wireTopBarDrag();\n this.#wireKeyboardShortcuts();\n this.#wireNativeStateSync();\n this.#initializeState();\n \n this.logger.info?.('[WindowChrome] Initialized');\n return true;\n }\n\n /** An element from a selector or an element; null when there is none. */\n #resolve(target, within = document) {\n if (!target) return null;\n if (typeof target !== 'string') return target;\n return within.querySelector(target);\n }\n\n /**\n * Draw minimise, maximise/restore and close, unless the page has its own\n * `#win-*` buttons (an embedder's own markup), which are then wired instead.\n */\n #createWindowControls() {\n if (document.getElementById('win-minimize') || document.getElementById('win-close')) return;\n const bar = this.#resolve(this._topBarOpt);\n const host = this.#resolve(this._controlsOpt)\n || bar?.querySelector('.twm-bar-right')\n || bar;\n if (!host) return;\n const box = document.createElement('div');\n box.className = 'twm-window-controls';\n const button = (id, icon, label, extra = '') => {\n const b = document.createElement('button');\n b.type = 'button';\n b.id = id;\n b.className = `twm-window-controls__btn${extra}`;\n b.setAttribute('aria-label', label);\n b.title = label;\n const i = document.createElement('span');\n i.className = 'material-symbols-outlined';\n i.textContent = icon;\n b.appendChild(i);\n box.appendChild(b);\n };\n button('win-minimize', 'remove', 'Minimize');\n button('win-maximize', 'check_box_outline_blank', 'Maximize');\n button('win-close', 'close', 'Close', ' twm-window-controls__btn--close');\n host.appendChild(box);\n this._createdControls = box;\n }\n\n /**\n * Wire minimize, maximize, close buttons\n */\n #wireWindowButtons() {\n const minBtn = document.getElementById('win-minimize');\n const maxBtn = document.getElementById('win-maximize');\n const closeBtn = document.getElementById('win-close');\n\n if (minBtn) {\n const handler = () => this.win.minimize();\n minBtn.addEventListener('click', handler);\n this._disposers.push(() => minBtn.removeEventListener('click', handler));\n }\n\n if (maxBtn) {\n const handler = async () => {\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Maximize toggle failed', e);\n }\n };\n maxBtn.addEventListener('click', handler);\n this._disposers.push(() => maxBtn.removeEventListener('click', handler));\n }\n\n if (closeBtn) {\n const handler = () => this.win.close();\n closeBtn.addEventListener('click', handler);\n this._disposers.push(() => closeBtn.removeEventListener('click', handler));\n }\n }\n\n /**\n * Update maximize button icon and body class\n */\n #updateMaximizeIcon(isMax) {\n const maxBtn = document.getElementById('win-maximize');\n if (!maxBtn) return;\n \n const icon = maxBtn.querySelector('.material-symbols-outlined');\n if (icon) {\n icon.textContent = isMax ? 'filter_none' : 'check_box_outline_blank';\n }\n const tooltipText = isMax ? 'Restore' : 'Maximize';\n window.LatexTooltip?.set(maxBtn, tooltipText);\n maxBtn.setAttribute('aria-label', tooltipText);\n maxBtn.title = tooltipText;\n \n document.body.classList.toggle('twm-window-maximized', isMax);\n }\n\n /**\n * Enable/disable resize handles\n */\n #setResizeHandlesEnabled(enabled) {\n Object.values(this.handles).forEach(handle => {\n if (handle) {\n handle.style.pointerEvents = enabled ? 'auto' : 'none';\n }\n });\n }\n\n /**\n * Set fullscreen body class\n */\n #setFullscreenClass(isFs) {\n document.body.classList.toggle('window-fullscreen', isFs);\n }\n\n /**\n * Create all resize handles\n */\n #createResizeHandles() {\n const positions = ['right', 'left', 'top', 'bottom'];\n const corners = ['br', 'bl', 'tr', 'tl'];\n\n positions.forEach(pos => {\n const handle = document.createElement('div');\n handle.className = `twm-resize-handle ${pos}`;\n document.body.appendChild(handle);\n this.handles[pos] = handle;\n this.#setupResize(handle, pos);\n });\n\n corners.forEach(corner => {\n const handle = document.createElement('div');\n handle.className = `twm-resize-handle corner ${corner}`;\n document.body.appendChild(handle);\n const mode = 'corner' + corner.toUpperCase();\n this.handles[mode] = handle;\n this.#setupResize(handle, mode);\n });\n }\n\n /**\n * Setup resize behavior for a handle\n */\n #setupResize(handle, mode) {\n let startX = 0, startY = 0, startScreenX = 0, startScreenY = 0;\n let startW = 0, startH = 0, startLeft = 0, startTop = 0;\n let pending = null;\n let rafScheduled = false;\n let lastSent = null;\n\n const boundsEqual = (a, b) => {\n return !!a && !!b && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n };\n\n const sendBounds = () => {\n rafScheduled = false;\n if (!pending) return;\n if (lastSent && boundsEqual(lastSent, pending)) return;\n this.win.setBounds({ x: pending.x, y: pending.y, width: pending.w, height: pending.h });\n lastSent = pending;\n };\n\n const scheduleSend = () => {\n if (!rafScheduled) {\n rafScheduled = true;\n requestAnimationFrame(sendBounds);\n }\n };\n\n let activePointerId = null;\n\n const EDGE = {\n right: 'e', left: 'w', top: 'n', bottom: 's',\n cornerBR: 'se', cornerBL: 'sw', cornerTR: 'ne', cornerTL: 'nw',\n };\n\n const startDrag = async (e) => {\n if (e.button != null && e.button !== 0) return;\n e.preventDefault();\n // \u2500\u2500 Native resize: the OS runs its own size loop (it blocks until\n // mouse-up), so the edge stays under the pointer. \u2500\u2500\n if (this.win.startNativeResize) {\n this.resizingActive = true;\n let handled = false;\n try { handled = await this.win.startNativeResize(EDGE[mode]); } catch (_) { handled = false; }\n this.resizingActive = false;\n if (handled) return;\n }\n this.resizingActive = true;\n startX = e.clientX;\n startY = e.clientY;\n startScreenX = e.screenX ?? startX;\n startScreenY = e.screenY ?? startY;\n\n try {\n const res = await this.win.getBounds();\n if (res) {\n startLeft = typeof res.x === 'number' ? res.x : 0;\n startTop = typeof res.y === 'number' ? res.y : 0;\n startW = res.width || document.documentElement.clientWidth;\n startH = res.height || document.documentElement.clientHeight;\n } else {\n startLeft = 0;\n startTop = 0;\n startW = document.documentElement.clientWidth;\n startH = document.documentElement.clientHeight;\n }\n } catch (e) {\n startLeft = 0;\n startTop = 0;\n startW = document.documentElement.clientWidth;\n startH = document.documentElement.clientHeight;\n }\n\n startLeft = Math.round(startLeft);\n startTop = Math.round(startTop);\n startW = Math.round(startW);\n startH = Math.round(startH);\n pending = null;\n lastSent = null;\n rafScheduled = false;\n\n // Capture pointer for smooth resize even when cursor escapes the handle\n if (SUPPORTS_POINTER && e.pointerId != null && handle.setPointerCapture) {\n try {\n handle.setPointerCapture(e.pointerId);\n activePointerId = e.pointerId;\n } catch (_) {}\n }\n\n if (SUPPORTS_POINTER) {\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', endDrag, { once: true });\n } else {\n window.addEventListener('mousemove', onMove, { passive: false });\n window.addEventListener('mouseup', endDrag, { once: true });\n }\n };\n\n const onMove = (e) => {\n const sx = e.screenX ?? e.clientX ?? 0;\n const sy = e.screenY ?? e.clientY ?? 0;\n const dx = sx - startScreenX;\n const dy = sy - startScreenY;\n\n let newX = startLeft;\n let newY = startTop;\n let newW = startW;\n let newH = startH;\n\n const isLeft = mode === 'left' || mode === 'cornerBL' || mode === 'cornerTL';\n const isRight = mode === 'right' || mode === 'cornerBR' || mode === 'cornerTR';\n const isTop = mode === 'top' || mode === 'cornerTR' || mode === 'cornerTL';\n const isBottom = mode === 'bottom' || mode === 'cornerBR' || mode === 'cornerBL';\n\n if (isLeft) {\n const candidateWidth = startW - dx;\n newW = Math.max(MIN_WIDTH, candidateWidth);\n const shift = startW - newW;\n newX = startLeft + shift;\n } else if (isRight) {\n newW = Math.max(MIN_WIDTH, startW + dx);\n }\n\n if (isTop) {\n const candidateHeight = startH - dy;\n newH = Math.max(MIN_HEIGHT, candidateHeight);\n const shiftY = startH - newH;\n newY = startTop + shiftY;\n } else if (isBottom) {\n newH = Math.max(MIN_HEIGHT, startH + dy);\n }\n\n newX = Math.round(newX);\n newY = Math.round(newY);\n newW = Math.max(MIN_WIDTH, Math.round(newW));\n newH = Math.max(MIN_HEIGHT, Math.round(newH));\n\n pending = { x: newX, y: newY, w: newW, h: newH };\n scheduleSend();\n };\n\n const endDrag = () => {\n if (SUPPORTS_POINTER) {\n window.removeEventListener('pointermove', onMove);\n } else {\n window.removeEventListener('mousemove', onMove);\n }\n // Release pointer capture\n if (activePointerId != null && handle.releasePointerCapture) {\n try { handle.releasePointerCapture(activePointerId); } catch (_) {}\n activePointerId = null;\n }\n // Flush any pending bounds update that was waiting for rAF\n if (pending && (!lastSent || !boundsEqual(lastSent, pending))) {\n this.win.setBounds({ x: pending.x, y: pending.y, width: pending.w, height: pending.h });\n }\n pending = null;\n lastSent = null;\n this.resizingActive = false;\n };\n\n const event = SUPPORTS_POINTER ? 'pointerdown' : 'mousedown';\n handle.addEventListener(event, startDrag);\n this._disposers.push(() => handle.removeEventListener(event, startDrag));\n }\n\n /**\n * Setup top bar dragging for window movement\n */\n #wireTopBarDrag() {\n this.topBar = this.#resolve(this._topBarOpt);\n if (!this.topBar) return;\n\n // What never starts a drag: anything you can click or type into. An\n // embedder adds its own with `noDrag`. (`.window-controls` and\n // `.panel-toggles` are kept for embedders' own markup of that shape.)\n // A menu bar in the top bar (a hamburger, STORY-0133) drops its menus\n // inside the bar's DOM: a press on a menu's padding or separator is\n // in the bar, not a drag.\n const NO_DRAG_SELECTOR = [\n '.no-drag', 'button', 'a', 'input', 'select', 'textarea', 'label',\n '[role=\"button\"]', '[role=\"menuitem\"]', '[role=\"tab\"]', '[contenteditable=\"true\"]',\n '.twm-window-controls', '.window-controls', '.panel-toggles', '.twm-menubar',\n this._noDrag,\n ].filter(Boolean).join(', ');\n\n let dragging = false;\n let startSX = 0, startSY = 0, startX = null, startY = null, winW = 0, winH = 0;\n let wasMax = false;\n let didRestore = false;\n let grabRatio = 0.5;\n let raf = null;\n let lastSentX = null, lastSentY = null;\n let activePointerId = null;\n\n // Double-click detection (native drag swallows dblclick events)\n const DBL_CLICK_TIME = 500;\n const DBL_CLICK_DIST = 4;\n let lastDownTime = 0;\n let lastDownX = 0;\n let lastDownY = 0;\n\n const isInteractiveTarget = (t) => !!(t && t.closest && t.closest(NO_DRAG_SELECTOR));\n\n const onMove = (e) => {\n // IMPORTANT: This must NOT be async to avoid race conditions on first drag\n const sx = e.screenX ?? e.clientX ?? 0;\n const sy = e.screenY ?? e.clientY ?? 0;\n const dx = Math.abs(sx - startSX);\n const dy = Math.abs(sy - startSY);\n\n if (!dragging) {\n if (wasMax) {\n if ((dx + dy) <= 0) return;\n // Handle restore from maximized state\n if (!didRestore) {\n didRestore = true;\n // Fire-and-forget the restore, then reposition\n this.win.setMaximized(false).then(() => {\n this.#updateMaximizeIcon(false);\n this.#setResizeHandlesEnabled(true);\n return this.win.getBounds();\n }).then((bounds) => {\n if (bounds) {\n const rw = bounds.width || 800;\n const rh = bounds.height || 600;\n const targetX = Math.max(0, Math.round(startSX - (rw * grabRatio)));\n const targetY = Math.max(0, Math.round(sy - 10));\n this.win.setBounds({ x: targetX, y: targetY, width: rw, height: rh });\n startX = targetX;\n startY = targetY;\n winW = rw;\n winH = rh;\n startSX = sx;\n startSY = sy;\n }\n }).catch((err) => {\n this.logger.warn?.('[WindowChrome] Restore on drag failed', err);\n });\n }\n return; // Don't proceed with normal drag until restore completes\n } else {\n if ((dx + dy) < DRAG_THRESHOLD) return;\n // startX/startY should already be set by startDrag - if not, skip this move\n if (startX == null || startY == null) {\n return;\n }\n }\n dragging = true;\n }\n\n // Use the bounds fetched in startDrag (never default to 0)\n if (startX == null || startY == null) return;\n\n const nx = Math.round(startX + (sx - startSX));\n const ny = Math.round(startY + (sy - startSY));\n\n if (lastSentX === nx && lastSentY === ny) return;\n\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n lastSentX = nx;\n lastSentY = ny;\n this.win.setBounds({ x: nx, y: ny });\n });\n };\n\n const endDrag = () => {\n dragging = false;\n if (raf) {\n cancelAnimationFrame(raf);\n raf = null;\n }\n if (activePointerId != null && this.topBar.releasePointerCapture) {\n try {\n this.topBar.releasePointerCapture(activePointerId);\n } catch (e) {}\n }\n activePointerId = null;\n didRestore = false;\n\n if (SUPPORTS_POINTER) {\n window.removeEventListener('pointermove', onMove, true);\n window.removeEventListener('pointerup', endDrag, true);\n } else {\n window.removeEventListener('mousemove', onMove, true);\n window.removeEventListener('mouseup', endDrag, true);\n }\n };\n\n const startDrag = async (e) => {\n if (this.resizingActive) return;\n if (isInteractiveTarget(e.target)) return;\n if ((Date.now() - this.lastDblClickTs) < 300) return;\n\n // Detect double-click before entering native drag (which\n // blocks the message loop and prevents dblclick events).\n const now = Date.now();\n const cx = e.clientX ?? 0;\n const cy = e.clientY ?? 0;\n if ((now - lastDownTime) < DBL_CLICK_TIME\n && Math.abs(cx - lastDownX) < DBL_CLICK_DIST\n && Math.abs(cy - lastDownY) < DBL_CLICK_DIST) {\n lastDownTime = 0;\n this.lastDblClickTs = now;\n e.preventDefault();\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (err) {\n this.logger.warn?.('[WindowChrome] Double-click maximize failed', err);\n }\n return;\n }\n lastDownTime = now;\n lastDownX = cx;\n lastDownY = cy;\n\n try {\n if (!this.win) return;\n\n // \u2500\u2500 Native drag (enables Aero Snap) \u2500\u2500\n // The call blocks until the OS drag loop ends (mouse-up).\n // On return the window has already moved/snapped.\n if (this.win.startNativeDrag) {\n e.preventDefault();\n if (await this.win.startNativeDrag()) {\n // Sync UI state after native drag (may have snapped/maximized)\n try {\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (_) {}\n return;\n }\n // Native drag unavailable \u2014 fall through to JS drag\n }\n\n // \u2500\u2500 JS drag fallback (non-Windows) \u2500\u2500\n startSX = e.screenX ?? e.clientX ?? 0;\n startSY = e.screenY ?? e.clientY ?? 0;\n\n try {\n wasMax = await this.win.isMaximized();\n } catch (e) {\n wasMax = false;\n }\n\n const barWidth = Math.max(1, window.innerWidth || document.documentElement.clientWidth);\n grabRatio = Math.min(1, Math.max(0, (e.clientX || 0) / barWidth));\n\n if (!wasMax) {\n const bounds = await this.win.getBounds();\n if (bounds) {\n startX = typeof bounds.x === 'number' ? bounds.x : (window.screenX ?? 0);\n startY = typeof bounds.y === 'number' ? bounds.y : (window.screenY ?? 0);\n winW = bounds.width || document.documentElement.clientWidth;\n winH = bounds.height || document.documentElement.clientHeight;\n } else {\n startX = window.screenX ?? 0;\n startY = window.screenY ?? 0;\n winW = document.documentElement.clientWidth;\n winH = document.documentElement.clientHeight;\n }\n }\n\n e.preventDefault();\n\n if (SUPPORTS_POINTER && e.pointerId != null && this.topBar.setPointerCapture) {\n try {\n this.topBar.setPointerCapture(e.pointerId);\n activePointerId = e.pointerId;\n } catch (e) {}\n }\n\n if (SUPPORTS_POINTER) {\n window.addEventListener('pointermove', onMove, true);\n window.addEventListener('pointerup', endDrag, true);\n } else {\n window.addEventListener('mousemove', onMove, true);\n window.addEventListener('mouseup', endDrag, true);\n }\n } catch (err) {\n this.logger.warn?.('[WindowChrome] Start drag failed', err);\n }\n };\n\n // Block drag during resize\n const blocker = (e) => {\n if (this.resizingActive) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n this.topBar.addEventListener('mousedown', blocker, true);\n this.topBar.addEventListener('pointerdown', blocker, true);\n\n // Double-click to toggle maximize (only on blank surfaces)\n const dblClickHandler = async (e) => {\n // Skip maximize if double-click is on interactive elements\n if (isInteractiveTarget(e.target)) {\n return;\n }\n\n this.lastDblClickTs = Date.now();\n e.preventDefault();\n e.stopPropagation();\n if (this.resizingActive) return;\n\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Double-click maximize failed', e);\n }\n };\n this.topBar.addEventListener('dblclick', dblClickHandler);\n\n // Start drag\n const event = SUPPORTS_POINTER ? 'pointerdown' : 'mousedown';\n this.topBar.addEventListener(event, startDrag, false);\n\n this._disposers.push(() => {\n this.topBar.removeEventListener('mousedown', blocker, true);\n this.topBar.removeEventListener('pointerdown', blocker, true);\n this.topBar.removeEventListener('dblclick', dblClickHandler);\n this.topBar.removeEventListener(event, startDrag, false);\n });\n }\n\n /**\n * Listen for browser resize events to sync UI with native state changes\n * (e.g. Win+Arrow maximize/restore, Win+Down minimize).\n */\n #wireNativeStateSync() {\n let syncTimer = null;\n const syncState = async () => {\n if (this.resizingActive || this._disposed) return;\n try {\n if (!this.win) return;\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (_) {}\n };\n const handler = () => {\n // Debounce: native snap triggers multiple resize events\n clearTimeout(syncTimer);\n syncTimer = setTimeout(syncState, 80);\n };\n window.addEventListener('resize', handler);\n this._disposers.push(() => {\n window.removeEventListener('resize', handler);\n clearTimeout(syncTimer);\n });\n }\n\n /**\n * Wire F11 fullscreen toggle\n */\n #wireKeyboardShortcuts() {\n const handler = async (e) => {\n if (e.code === 'F11') {\n e.preventDefault();\n try {\n const isFs = await this.win.toggleFullscreen();\n this.#setFullscreenClass(isFs);\n const max = await this.win.isMaximized();\n this.#setResizeHandlesEnabled(!(isFs || max));\n } catch (e) {\n this.logger.warn?.('[WindowChrome] F11 toggle failed', e);\n }\n }\n };\n window.addEventListener('keydown', handler, true);\n this._disposers.push(() => window.removeEventListener('keydown', handler, true));\n }\n\n /**\n * Initialize window state on startup\n */\n async #initializeState() {\n try {\n if (!this.win) return;\n\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n\n const isFs = await this.win.isFullscreen();\n this.#setFullscreenClass(isFs);\n if (isFs) this.#setResizeHandlesEnabled(false);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Initial state check failed', e);\n }\n }\n\n /**\n * Dispose of the controller\n */\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n\n this._disposers.forEach(dispose => {\n try {\n dispose();\n } catch (e) {}\n });\n this._disposers = [];\n\n // Remove resize handles, and the buttons this drew\n Object.values(this.handles).forEach(handle => {\n if (handle && handle.parentNode) {\n handle.parentNode.removeChild(handle);\n }\n });\n this.handles = {};\n this._createdControls?.remove();\n this._createdControls = null;\n document.body.classList.remove('twm-custom-chrome', 'twm-window-maximized', 'window-fullscreen');\n\n this.logger.info?.('[WindowChrome] Disposed');\n }\n}\n", "/**\n * auto_scrollbars.js \u2014 the overlay scrollbar, on EVERY scrollable element.\n *\n * `installOverlayScrollbar` (overlay_scrollbar.js) gives one container a thin\n * bar that shows on hover and fades away. It is installed container by\n * container, it puts the bar INSIDE the container, and it holds a resize\n * observer, a subtree mutation observer and a window listener for each one.\n * That is fine for a handful of known panes and wrong for \"all of them\": a\n * page that redraws with `innerHTML = ''` deletes its bar for good, and a\n * table body, a dropdown, a textarea and a dialog each want one.\n *\n * So this is the same look, done once for a whole subtree:\n *\n * - Native scrollbars are hidden under `root`, so no element reserves\n * layout width for one and nothing reflows when a bar appears.\n * - Bars live in ONE fixed layer on `document.body`, positioned over the\n * element they belong to. Nothing is added to a scroll container, so a\n * redraw cannot remove a bar, and a textarea (which cannot hold children)\n * gets one too.\n * - An element gets its bars when the pointer is over it or it scrolls, if\n * it actually overflows. They fade out a moment after the pointer leaves\n * or the scrolling stops. Nested scroll areas each show their own.\n * - The thumb drags and the track pages, as a native bar does.\n * - The layer is above everything, so a bar would also draw over whatever\n * covers its element \u2014 a popover, a menu, a dialog. A bar whose track is\n * covered anywhere is not drawn; it comes back when it is uncovered.\n *\n * Discovery is lazy: the pointer and scroll events name the elements worth\n * measuring, so nothing walks the DOM looking for scroll areas.\n */\n\nconst LAYER_ID = 'twm-autoscroll-layer';\nconst ROOT_CLASS = 'twm-autoscroll';\nconst HIDE_AFTER_MS = 900;\nconst MIN_THUMB = 30;\nconst BAR = 6;\n\n/**\n * Where the thumb goes. Pure, so it can be tested without a layout engine.\n *\n * @param {number} scrollSize scrollHeight / scrollWidth\n * @param {number} clientSize clientHeight / clientWidth\n * @param {number} scrollPos scrollTop / scrollLeft\n * @param {number} trackLen the bar's length on screen (px)\n * @returns {{size:number, pos:number}|null} null when nothing overflows\n */\nexport function thumbGeometry(scrollSize, clientSize, scrollPos, trackLen) {\n const max = scrollSize - clientSize;\n if (!(max > 1) || !(trackLen > 0)) return null;\n const size = Math.min(trackLen, Math.max(MIN_THUMB, trackLen * clientSize / scrollSize));\n const pos = (trackLen - size) * Math.min(1, Math.max(0, scrollPos / max));\n return { size, pos };\n}\n\n/**\n * Whether something else covers `el` at any of the points a bar runs along.\n * Pure, so it can be tested without a layout engine.\n *\n * @param {Element} el\n * @param {Element[][]} stacks what `elementsFromPoint` gave at each point,\n * topmost first. The overlay layer's own bars are skipped, and so are the\n * window's `.twm-resize-handle` edge strips (BUG-0036): they lie over every\n * pane flush against a window edge and are chrome, not cover.\n * @returns {boolean}\n */\nexport function barCovered(el, stacks) {\n const passThrough = (h) => h.closest?.('.twm-autoscroll-layer') || h.closest?.('.twm-resize-handle');\n return stacks.some((stack) => {\n const top = (stack || []).find((h) => !passThrough(h));\n return Boolean(top) && top !== el && !el.contains(top);\n });\n}\n\n/** Whether an element scrolls on an axis: its overflow allows it and its\n * content is larger than its box. */\nfunction scrollsOn(el, axis) {\n if (!(el instanceof Element)) return false;\n const cs = getComputedStyle(el);\n const overflow = axis === 'y' ? cs.overflowY : cs.overflowX;\n if (overflow !== 'auto' && overflow !== 'scroll' && !(el.tagName === 'TEXTAREA' && overflow !== 'hidden')) return false;\n return axis === 'y' ? el.scrollHeight - el.clientHeight > 1 : el.scrollWidth - el.clientWidth > 1;\n}\n\n/**\n * Give every scrollable element under `root` an auto-hiding overlay scrollbar.\n *\n * @param {HTMLElement} [root=document.body]\n * @param {{exclude?: (el: Element) => boolean}} [opts] elements to leave to\n * their own scrollbar. Containers that already carry an\n * `installOverlayScrollbar` bar are always left alone.\n * @returns {{dispose: () => void}}\n */\nexport function installAutoScrollbars(root = document.body, { exclude = null } = {}) {\n const doc = root.ownerDocument || document;\n const win = doc.defaultView || window;\n root.classList.add(ROOT_CLASS);\n\n let layer = doc.getElementById(LAYER_ID);\n if (!layer) {\n layer = doc.createElement('div');\n layer.id = LAYER_ID;\n layer.className = 'twm-autoscroll-layer';\n doc.body.appendChild(layer);\n }\n\n /** element -> { v, h, timer, hovered } */\n const managed = new Map();\n let hoverChain = new Set();\n\n const eligible = (el) => el instanceof Element\n && root.contains(el)\n && !el.__overlayScrollbarInstalled\n && !el.closest?.('.twm-autoscroll-layer')\n && !(exclude && exclude(el));\n\n const makeBar = (el, axis) => {\n const bar = doc.createElement('div');\n bar.className = `twm-autoscroll-bar twm-autoscroll-bar--${axis}`;\n const thumb = doc.createElement('div');\n thumb.className = 'twm-autoscroll-thumb';\n bar.appendChild(thumb);\n layer.appendChild(bar);\n\n // The track pages, like a native bar's.\n bar.addEventListener('mousedown', (e) => {\n if (e.target !== bar) return;\n e.preventDefault();\n const r = thumb.getBoundingClientRect();\n const before = axis === 'y' ? e.clientY < r.top : e.clientX < r.left;\n const page = (axis === 'y' ? el.clientHeight : el.clientWidth) * 0.9;\n if (axis === 'y') el.scrollTop += before ? -page : page;\n else el.scrollLeft += before ? -page : page;\n });\n // The thumb drags.\n thumb.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const rec = managed.get(el);\n if (rec) rec.dragging = true;\n const start = axis === 'y' ? e.clientY : e.clientX;\n const startScroll = axis === 'y' ? el.scrollTop : el.scrollLeft;\n const trackLen = axis === 'y' ? bar.getBoundingClientRect().height : bar.getBoundingClientRect().width;\n const thumbLen = axis === 'y' ? thumb.getBoundingClientRect().height : thumb.getBoundingClientRect().width;\n const max = axis === 'y' ? el.scrollHeight - el.clientHeight : el.scrollWidth - el.clientWidth;\n const perPx = trackLen > thumbLen ? max / (trackLen - thumbLen) : 0;\n bar.classList.add('twm-autoscroll-bar--active');\n const move = (mv) => {\n const d = (axis === 'y' ? mv.clientY : mv.clientX) - start;\n if (axis === 'y') el.scrollTop = startScroll + d * perPx;\n else el.scrollLeft = startScroll + d * perPx;\n };\n const up = () => {\n doc.removeEventListener('mousemove', move);\n doc.removeEventListener('mouseup', up);\n bar.classList.remove('twm-autoscroll-bar--active');\n if (rec) rec.dragging = false;\n hideLater(el);\n };\n doc.addEventListener('mousemove', move);\n doc.addEventListener('mouseup', up);\n });\n bar.addEventListener('mouseenter', () => { const rec = managed.get(el); if (rec) { rec.onBar = true; show(el); } });\n bar.addEventListener('mouseleave', () => { const rec = managed.get(el); if (rec) { rec.onBar = false; hideLater(el); } });\n return { bar, thumb };\n };\n\n const record = (el) => {\n let rec = managed.get(el);\n if (!rec) {\n rec = { v: null, h: null, timer: 0, dragging: false, onBar: false };\n managed.set(el, rec);\n }\n return rec;\n };\n\n const coveredAlong = (el, points) => typeof doc.elementsFromPoint === 'function'\n && barCovered(el, points.map(([x, y]) => doc.elementsFromPoint(x, y)));\n\n /** Place and size an element's bars; drop the element when it is gone. */\n const place = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n if (!el.isConnected) { drop(el); return; }\n const r = el.getBoundingClientRect();\n const vw = win.innerWidth;\n const vh = win.innerHeight;\n const top = Math.max(0, r.top);\n const left = Math.max(0, r.left);\n const bottom = Math.min(vh, r.bottom);\n const right = Math.min(vw, r.right);\n // Screen px per CSS px, for content inside a zoomed tile.\n const z = el.offsetHeight ? r.height / el.offsetHeight : 1;\n for (const axis of ['y', 'x']) {\n const key = axis === 'y' ? 'v' : 'h';\n const overflows = scrollsOn(el, axis);\n if (!overflows) { if (rec[key]) rec[key].bar.style.display = 'none'; continue; }\n if (!rec[key]) rec[key] = makeBar(el, axis);\n const { bar, thumb } = rec[key];\n bar.style.display = '';\n if (axis === 'y') {\n const len = bottom - top;\n Object.assign(bar.style, { top: `${top}px`, left: `${right - BAR - 1}px`, height: `${len}px`, width: `${BAR}px` });\n const g = thumbGeometry(el.scrollHeight * z, el.clientHeight * z, el.scrollTop * z, len);\n if (!g) { bar.style.display = 'none'; continue; }\n Object.assign(thumb.style, { top: `${g.pos}px`, height: `${g.size}px`, left: '0', width: '100%' });\n const x = right - BAR / 2 - 1;\n if (coveredAlong(el, [[x, top + 2], [x, top + len / 2], [x, bottom - 2]])) bar.style.display = 'none';\n } else {\n const len = right - left;\n Object.assign(bar.style, { left: `${left}px`, top: `${bottom - BAR - 1}px`, width: `${len}px`, height: `${BAR}px` });\n const g = thumbGeometry(el.scrollWidth * z, el.clientWidth * z, el.scrollLeft * z, len);\n if (!g) { bar.style.display = 'none'; continue; }\n Object.assign(thumb.style, { left: `${g.pos}px`, width: `${g.size}px`, top: '0', height: '100%' });\n const y = bottom - BAR / 2 - 1;\n if (coveredAlong(el, [[left + 2, y], [left + len / 2, y], [right - 2, y]])) bar.style.display = 'none';\n }\n }\n };\n\n const setVisible = (el, on) => {\n const rec = managed.get(el);\n if (!rec) return;\n for (const b of [rec.v, rec.h]) if (b) b.bar.classList.toggle('twm-autoscroll-bar--on', on);\n };\n const show = (el) => {\n const rec = record(el);\n clearTimeout(rec.timer);\n place(el);\n setVisible(el, true);\n };\n const hideLater = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n clearTimeout(rec.timer);\n rec.timer = setTimeout(() => {\n if (rec.dragging || rec.onBar || hoverChain.has(el)) return;\n setVisible(el, false);\n }, HIDE_AFTER_MS);\n };\n const drop = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n clearTimeout(rec.timer);\n rec.v?.bar.remove();\n rec.h?.bar.remove();\n managed.delete(el);\n };\n\n /** The scrollable elements from `target` up to `root`. */\n const scrollChain = (target) => {\n const out = new Set();\n for (let el = target instanceof Element ? target : target?.parentElement; el && el !== doc.documentElement; el = el.parentElement) {\n if (el.closest?.('.twm-autoscroll-layer')) return out;\n if (eligible(el) && (scrollsOn(el, 'y') || scrollsOn(el, 'x'))) out.add(el);\n if (el === root) break;\n }\n return out;\n };\n\n const onOver = (e) => {\n if (e.target?.closest?.('.twm-autoscroll-layer')) return;\n const next = scrollChain(e.target);\n for (const el of hoverChain) if (!next.has(el)) hideLater(el);\n for (const el of next) show(el);\n hoverChain = next;\n };\n const onLeaveWindow = (e) => {\n if (e.relatedTarget) return;\n for (const el of hoverChain) hideLater(el);\n hoverChain = new Set();\n };\n const onScroll = (e) => {\n const el = e.target === doc ? null : e.target;\n if (el && eligible(el)) { show(el); hideLater(el); }\n // A scrolling ancestor moves every bar inside it.\n for (const other of managed.keys()) if (other !== el) place(other);\n };\n let raf = 0;\n const onResize = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => { for (const el of managed.keys()) place(el); });\n };\n // An element taken out of the page (a managed window closed) takes its\n // bars with it at once. They live in the layer, not in the element, so\n // otherwise they would stay on screen through the hide delay and fade.\n const sweep = new MutationObserver((mutations) => {\n if (!managed.size || !mutations.some((m) => m.removedNodes.length)) return;\n for (const el of [...managed.keys()]) {\n if (!el.isConnected) { drop(el); hoverChain.delete(el); }\n }\n });\n sweep.observe(root, { childList: true, subtree: true });\n\n doc.addEventListener('mouseover', onOver, true);\n doc.addEventListener('mouseout', onLeaveWindow, true);\n doc.addEventListener('scroll', onScroll, true);\n win.addEventListener('resize', onResize);\n // A popover or dialog takes the focus as it opens, often over a bar that\n // is showing because the pointer has not moved: look again once it is drawn.\n doc.addEventListener('focusin', onResize, true);\n\n return {\n dispose() {\n doc.removeEventListener('mouseover', onOver, true);\n doc.removeEventListener('mouseout', onLeaveWindow, true);\n doc.removeEventListener('scroll', onScroll, true);\n win.removeEventListener('resize', onResize);\n doc.removeEventListener('focusin', onResize, true);\n sweep.disconnect();\n for (const el of [...managed.keys()]) drop(el);\n root.classList.remove(ROOT_CLASS);\n },\n };\n}\n", "/**\n * native_context_menu.js \u2014 the browser's own right-click menu, only where it helps.\n *\n * A FlexDesk app draws its own context menus (DataTable rows and headers, tabs,\n * tiles, the top bar). Everywhere else a right-click shows the browser's or the\n * webview's menu: Back, Reload, Save as, Print, Inspect. In a desktop window\n * that makes the app look like a web page and offers moves that break it.\n *\n * This keeps the native menu where it is the useful one, editable text (Paste)\n * and selected text (Copy), and prevents it everywhere nobody else claimed the\n * right-click.\n */\n\n/** Input types that take typed text, where Paste belongs. */\nconst TEXT_INPUTS = new Set(['', 'text', 'search', 'url', 'tel', 'email', 'password', 'number',\n 'date', 'datetime-local', 'month', 'week', 'time']);\n\nfunction isEditable(el) {\n if (!el || el.nodeType !== 1) return false;\n const tag = el.tagName;\n if (tag === 'TEXTAREA' || tag === 'SELECT') return true;\n if (tag === 'INPUT') return TEXT_INPUTS.has(String(el.getAttribute('type') || '').toLowerCase());\n return !!el.closest?.('[contenteditable=\"\"],[contenteditable=\"true\"],[contenteditable=\"plaintext-only\"]');\n}\n\n/** A non-empty selection that the click landed inside. */\nfunction onSelection(target, doc) {\n const sel = doc?.getSelection?.();\n if (!sel || sel.isCollapsed || !String(sel).trim()) return false;\n for (let i = 0; i < sel.rangeCount; i += 1) {\n if (sel.getRangeAt(i).intersectsNode?.(target)) return true;\n }\n return false;\n}\n\n/**\n * Prevent the native context menu wherever no handler claimed the right-click.\n *\n * Listens in the bubble phase, so every element handler runs first: one that\n * shows its own menu calls `preventDefault()`, and this leaves it alone. A\n * handler that stops propagation never reaches here at all.\n *\n * @param {object} [opts]\n * @param {EventTarget} [opts.root=document]\n * @param {(e: MouseEvent) => boolean} [opts.allow] true keeps the native menu for that event\n * @returns {{ dispose: () => void }}\n */\nexport function suppressNativeContextMenu({ root, allow } = {}) {\n const r = root ?? (typeof document !== 'undefined' ? document : null);\n if (!r) return { dispose() {} };\n const onMenu = (e) => {\n if (e.defaultPrevented) return;\n const t = e.target;\n if (isEditable(t)) return;\n if (onSelection(t, t?.ownerDocument)) return;\n if (allow?.(e)) return;\n e.preventDefault();\n };\n r.addEventListener('contextmenu', onMenu);\n return { dispose() { r.removeEventListener('contextmenu', onMenu); } };\n}\n", "/**\n * Overlay scrollbar utilities for the js_new UI stack.\n * Ports the unified hover-only scrollbar system from the legacy UI manager.\n */\n\nimport { createRafResizeObserver } from './raf_resize_observer.js';\n\nfunction normalizeOrientation(value) {\n return String(value || 'horizontal').toLowerCase() === 'vertical' ? 'vertical' : 'horizontal';\n}\n\nfunction ensureInstallState(container) {\n if (!container.__overlayScrollbarInstalled) {\n Object.defineProperty(container, '__overlayScrollbarInstalled', {\n value: {},\n writable: true,\n configurable: true,\n });\n }\n}\n\nexport function installOverlayScrollbar(container, options = {}) {\n if (!container) return null;\n\n const orientation = normalizeOrientation(options.orientation);\n const className = options.className || 'overlay-scrollbar';\n const isHorizontal = orientation !== 'vertical';\n const orientationKey = isHorizontal ? 'horizontal' : 'vertical';\n\n ensureInstallState(container);\n if (container.__overlayScrollbarInstalled[orientationKey]) {\n return container.__overlayScrollbarInstalled[orientationKey];\n }\n\n if (options.setOverflow !== false) {\n container.style.overflow = options.overflow || 'auto';\n }\n if (options.setPosition !== false && getComputedStyle(container).position === 'static') {\n container.style.position = 'relative';\n }\n\n // When externalBar is true, place the bar on the parent element instead of\n // inside the scroll container. This avoids overflow clipping issues in certain\n // flex+overflow layouts (e.g. bottom-tabs-header .tabs).\n const externalBar = !!options.externalBar;\n const barHost = externalBar ? container.parentElement : container;\n if (externalBar && barHost && getComputedStyle(barHost).position === 'static') {\n barHost.style.position = 'relative';\n }\n\n const bar = document.createElement('div');\n bar.className = className;\n bar.classList.add(`overlay-scrollbar-${isHorizontal ? 'h' : 'v'}`);\n const track = document.createElement('div');\n track.className = 'track';\n const thumb = document.createElement('div');\n thumb.className = 'thumb';\n bar.appendChild(track);\n bar.appendChild(thumb);\n (barHost || container).appendChild(bar);\n\n const getScrollProps = () => ({\n scrollSize: isHorizontal ? container.scrollWidth : container.scrollHeight,\n clientSize: isHorizontal ? container.clientWidth : container.clientHeight,\n scrollPos: isHorizontal ? (container.scrollLeft || 0) : (container.scrollTop || 0),\n });\n\n // Dragging and hover state - must be declared early so event handlers can access it\n let dragging = false;\n let hovered = false;\n let startPos = 0;\n let thumbStartPos = 0;\n\n let previousHasOverflow = null;\n let previousClientSize = null;\n let isResettingScroll = false;\n\n const update = () => {\n if (isResettingScroll) return;\n\n const { scrollSize, clientSize, scrollPos } = getScrollProps();\n const scrollLeft = container.scrollLeft || 0;\n const scrollTop = container.scrollTop || 0;\n const maxScroll = scrollSize - clientSize;\n const hasOverflow = maxScroll > 2;\n\n if (previousClientSize !== null && clientSize > previousClientSize && hasOverflow && scrollPos > 0) {\n const delta = clientSize - previousClientSize;\n const targetScroll = Math.max(0, scrollPos - delta);\n if (targetScroll !== scrollPos) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = targetScroll;\n } else {\n container.scrollTop = targetScroll;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousClientSize = clientSize;\n previousHasOverflow = hasOverflow;\n return;\n }\n }\n\n previousClientSize = clientSize;\n\n if (previousHasOverflow === true && !hasOverflow && scrollPos > 0) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = 0;\n } else {\n container.scrollTop = 0;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousHasOverflow = hasOverflow;\n return;\n }\n\n const clampedMaxScroll = Math.max(0, maxScroll);\n if (hasOverflow && scrollPos > clampedMaxScroll) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = clampedMaxScroll;\n } else {\n container.scrollTop = clampedMaxScroll;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousHasOverflow = hasOverflow;\n return;\n }\n previousHasOverflow = hasOverflow;\n\n container.dataset.scrollable = hasOverflow ? '1' : '0';\n\n // Position the bar at the scroll viewport edge.\n if (externalBar) {\n // Bar lives on the parent element \u2014 position using container's offset.\n // No scroll-offset compensation needed since bar is outside scroll context.\n if (isHorizontal) {\n bar.style.left = `${container.offsetLeft}px`;\n bar.style.bottom = 'auto';\n bar.style.top = `${container.offsetTop + container.offsetHeight - 6}px`;\n bar.style.width = `${container.clientWidth}px`;\n } else {\n bar.style.top = `${container.offsetTop}px`;\n bar.style.right = 'auto';\n bar.style.left = `${container.offsetLeft + container.offsetWidth - 6}px`;\n bar.style.height = `${container.clientHeight}px`;\n }\n } else {\n // Bar lives inside the container \u2014 compensate for scroll offset\n // on BOTH axes so the bar stays pinned to the viewport edge.\n if (isHorizontal) {\n bar.style.left = `${scrollLeft}px`;\n bar.style.top = `${scrollTop + container.clientHeight - bar.offsetHeight}px`;\n bar.style.bottom = 'auto';\n bar.style.width = `${clientSize}px`;\n } else {\n bar.style.top = `${scrollTop}px`;\n bar.style.left = `${scrollLeft + container.clientWidth - bar.offsetWidth}px`;\n bar.style.right = 'auto';\n bar.style.height = `${clientSize}px`;\n }\n }\n\n if (!hasOverflow) {\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n thumb.style[isHorizontal ? 'width' : 'height'] = '0px';\n thumb.style[isHorizontal ? 'left' : 'top'] = '0px';\n return;\n }\n\n // Don't hide while dragging or hovering\n if (!dragging && !hovered) {\n bar.style.opacity = '0'; // hidden until hover\n bar.style.pointerEvents = 'none';\n }\n\n const ratio = clientSize / scrollSize;\n const thumbSize = Math.max(30, Math.floor(ratio * clientSize));\n const maxThumbPos = clientSize - thumbSize;\n const scrollRatio = maxScroll > 0 ? scrollPos / maxScroll : 0;\n const thumbPos = Math.round(maxThumbPos * scrollRatio);\n\n if (isHorizontal) {\n thumb.style.width = `${thumbSize}px`;\n thumb.style.left = `${thumbPos}px`;\n } else {\n thumb.style.height = `${thumbSize}px`;\n thumb.style.top = `${thumbPos}px`;\n }\n };\n\n const onScroll = () => update();\n container.addEventListener('scroll', onScroll, { passive: true });\n \n // Manage hover visibility entirely in JS to avoid CSS specificity issues.\n // Show bar on mouseenter if scrollable, hide on mouseleave.\n const onMouseEnter = () => {\n hovered = true;\n update();\n if (container.dataset.scrollable === '1') {\n bar.style.opacity = '1';\n bar.style.pointerEvents = '';\n }\n };\n const onMouseLeave = () => {\n hovered = false;\n // Don't hide while dragging\n if (dragging) return;\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n };\n container.addEventListener('mouseenter', onMouseEnter, { passive: true });\n container.addEventListener('mouseleave', onMouseLeave, { passive: true });\n // When bar is external (sibling of container), also listen for hover on the bar\n // itself so moving the mouse to the thumb doesn't trigger a hide.\n if (externalBar) {\n bar.addEventListener('mouseenter', onMouseEnter, { passive: true });\n bar.addEventListener('mouseleave', onMouseLeave, { passive: true });\n }\n\n // Also handle focus-within for keyboard accessibility\n container.addEventListener('focusin', onMouseEnter, { passive: true });\n container.addEventListener('focusout', onMouseLeave, { passive: true });\n\n const resizeObserver = createRafResizeObserver(update);\n try { resizeObserver.observe(container); } catch (_) {}\n\n const mo = new MutationObserver(update);\n try { mo.observe(container, { childList: true, subtree: options.watchSubtree !== false }); } catch (_) {}\n\n let resizeTimeout;\n const onWindowResize = () => {\n update();\n clearTimeout(resizeTimeout);\n resizeTimeout = setTimeout(update, 150);\n };\n window.addEventListener('resize', onWindowResize, { passive: true });\n\n const onMouseDown = (e) => {\n dragging = true;\n startPos = isHorizontal ? e.clientX : e.clientY;\n thumbStartPos = parseFloat(thumb.style[isHorizontal ? 'left' : 'top']) || 0;\n // Keep bar visible while dragging\n bar.style.opacity = '1';\n bar.style.pointerEvents = '';\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp, { once: true });\n e.preventDefault();\n e.stopPropagation();\n };\n\n const onMouseMove = (e) => {\n if (!dragging) return;\n e.preventDefault();\n\n const { scrollSize, clientSize } = getScrollProps();\n const maxScroll = scrollSize - clientSize;\n if (maxScroll <= 0) return;\n\n const thumbSize = parseFloat(thumb.style[isHorizontal ? 'width' : 'height']) || 30;\n const maxThumbPos = clientSize - thumbSize;\n\n const delta = (isHorizontal ? e.clientX : e.clientY) - startPos;\n let newThumbPos = thumbStartPos + delta;\n newThumbPos = Math.max(0, Math.min(maxThumbPos, newThumbPos));\n\n const thumbRatio = maxThumbPos > 0 ? newThumbPos / maxThumbPos : 0;\n if (isHorizontal) {\n container.scrollLeft = thumbRatio * maxScroll;\n } else {\n container.scrollTop = thumbRatio * maxScroll;\n }\n };\n\n const onMouseUp = () => {\n dragging = false;\n document.removeEventListener('mousemove', onMouseMove);\n // Check if mouse is still over container - if not, hide the bar\n const rect = container.getBoundingClientRect();\n const isMouseOver = document.elementsFromPoint(\n (rect.left + rect.right) / 2,\n (rect.top + rect.bottom) / 2\n ).includes(container);\n if (!isMouseOver) {\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n }\n };\n\n thumb.addEventListener('mousedown', onMouseDown);\n\n // Wheel-to-horizontal: convert vertical wheel into horizontal scroll,\n // but only when the container has no vertical overflow (otherwise let\n // the browser handle normal vertical scrolling).\n let onWheel = null;\n if (isHorizontal) {\n onWheel = (e) => {\n const { scrollSize, clientSize } = getScrollProps();\n if (scrollSize <= clientSize) return;\n if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) return;\n // If the container also scrolls vertically, don't hijack the wheel\n if (container.scrollHeight > container.clientHeight) return;\n e.preventDefault();\n container.scrollLeft += e.deltaY;\n };\n container.addEventListener('wheel', onWheel, { passive: false });\n }\n\n requestAnimationFrame(() => {\n requestAnimationFrame(update);\n });\n setTimeout(update, 50);\n\n const cleanup = () => {\n container.removeEventListener('scroll', onScroll);\n container.removeEventListener('mouseenter', onMouseEnter);\n container.removeEventListener('mouseleave', onMouseLeave);\n container.removeEventListener('focusin', onMouseEnter);\n container.removeEventListener('focusout', onMouseLeave);\n if (externalBar) {\n bar.removeEventListener('mouseenter', onMouseEnter);\n bar.removeEventListener('mouseleave', onMouseLeave);\n }\n if (onWheel) container.removeEventListener('wheel', onWheel);\n window.removeEventListener('resize', onWindowResize);\n try { resizeObserver.disconnect(); } catch (_) {}\n try { mo.disconnect(); } catch (_) {}\n bar.remove();\n };\n\n const handle = { update, cleanup, bar, thumb };\n container.__overlayScrollbarInstalled[orientationKey] = handle;\n return handle;\n}\n\nexport function installWorkspaceScrollbars(workspace, options = {}) {\n if (!workspace) return null;\n if (workspace.__workspaceOverlayScrollbarsInstalled) return workspace.__workspaceOverlayScrollbarsUpdate;\n\n installOverlayScrollbar(workspace, {\n orientation: 'vertical',\n className: options.verticalClass || 'panel-scrollbar',\n watchSubtree: options.watchSubtree ?? true,\n });\n installOverlayScrollbar(workspace, {\n orientation: 'horizontal',\n className: options.horizontalClass || 'tabs-scrollbar',\n watchSubtree: options.watchSubtree ?? true,\n });\n\n const update = () => {\n const maxX = Math.max(0, workspace.scrollWidth - workspace.clientWidth);\n const maxY = Math.max(0, workspace.scrollHeight - workspace.clientHeight);\n workspace.dataset.scrollableX = maxX > 1 ? '1' : '0';\n workspace.dataset.scrollableY = maxY > 1 ? '1' : '0';\n };\n\n workspace.__workspaceOverlayScrollbarsInstalled = true;\n workspace.__workspaceOverlayScrollbarsUpdate = update;\n workspace.addEventListener('scroll', update, { passive: true });\n const ro = createRafResizeObserver(update);\n try { ro.observe(workspace); } catch (_) {}\n const mo = new MutationObserver(update);\n try { mo.observe(workspace, { childList: true, subtree: true }); } catch (_) {}\n requestAnimationFrame(update);\n return update;\n}\n\n/**\n * Auto-discover and install vertical overlay scrollbars on\n * `.twm-collapsible-content.visible` elements under `root`. Sections already\n * visible when this is called get a bar at once; a MutationObserver on `root`\n * handles content mounted later (pages mount lazily) and class toggles\n * (expand/collapse). Only class changes under `root` are watched.\n *\n * This used to look up a hard-coded `#twm-fixed-200` that nothing in FlexDesk\n * creates, so the first pass never ran and the observer fell back to the whole\n * document (BUG-0006). The caller names its own root now.\n *\n * Only adds the visual overlay bar \u2014 does NOT change overflow. Elements that are already\n * scrollable via CSS (e.g. accordion `.twm-collapsible-content.visible { overflow-y: auto }`)\n * get the bar; non-scrollable elements get a no-op bar that stays hidden.\n *\n * @param {Element} [root=document.body] The subtree to scan and watch.\n * @returns {Function} disconnect \u2014 stops watching\n */\nexport function installCollapsibleScrollbars(root = document.body) {\n const installOnElement = (el) => {\n installOverlayScrollbar(el, {\n orientation: 'vertical',\n setOverflow: false,\n watchSubtree: true,\n });\n };\n\n if (root.matches?.('.twm-collapsible-content.visible')) installOnElement(root);\n root.querySelectorAll('.twm-collapsible-content.visible').forEach(installOnElement);\n\n // Watch for new elements AND class changes (visible toggled by toggleCategory)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Class change \u2014 check if .twm-collapsible-content just gained .visible\n if (mutation.type === 'attributes' && mutation.attributeName === 'class') {\n const el = mutation.target;\n if (el.classList.contains('twm-collapsible-content') && el.classList.contains('visible')) {\n installOnElement(el);\n }\n continue;\n }\n // New subtrees added (lazy page mount)\n for (const node of mutation.addedNodes) {\n if (node.nodeType !== 1) continue;\n if (node.classList?.contains('twm-collapsible-content') && node.classList?.contains('visible')) {\n installOnElement(node);\n }\n node.querySelectorAll?.('.twm-collapsible-content.visible')?.forEach(installOnElement);\n }\n }\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['class'],\n });\n return () => observer.disconnect();\n}\n\n/**\n * Auto-discover and install horizontal overlay scrollbars on tab strips.\n *\n * Uses a MutationObserver so dynamically created tab strips are picked up\n * without per-page manual setup.\n *\n * The selector list used to be hardcoded as `.tabs, .scenario-detail-tabs`, so\n * a generic scrollbar utility carried the name of one EcoAgent page's tab bar.\n * The caller names its own strips now.\n *\n * @param {string[]} [selectors=['.tabs']] Which elements count as a tab strip.\n * @returns {Function} disconnect \u2014 stops watching for new tabs\n */\nexport function installTabsScrollbars(selectors = ['.tabs']) {\n const selector = selectors.join(', ');\n const classes = selectors\n .filter((s) => s.startsWith('.'))\n .map((s) => s.slice(1));\n const installOnElement = (el) => {\n installOverlayScrollbar(el, {\n orientation: 'horizontal',\n className: 'tabs-scrollbar',\n setOverflow: false,\n externalBar: true,\n watchSubtree: true,\n });\n };\n\n const cleanupElement = (el) => {\n el.__overlayScrollbarInstalled?.horizontal?.cleanup?.();\n delete el.__overlayScrollbarInstalled;\n };\n\n const matches = (el) => classes.some((c) => el.classList?.contains(c));\n\n document.querySelectorAll(selector).forEach(installOnElement);\n\n // Watch for dynamically added/removed elements\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (node.nodeType !== 1) continue;\n if (matches(node)) installOnElement(node);\n node.querySelectorAll?.(selector)?.forEach(installOnElement);\n }\n for (const node of mutation.removedNodes) {\n if (node.nodeType !== 1) continue;\n if (matches(node)) cleanupElement(node);\n node.querySelectorAll?.(selector)?.forEach(cleanupElement);\n }\n }\n });\n\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n}\n", "/**\n * scroll_lock.js \u2014 0.6.1. Several scroll boxes that move as one.\n *\n * A side-by-side comparison (two DataTables in two tiles, \"now\" and \"then\") is\n * only readable if row 40 on the left stays beside row 40 on the right. A lock\n * is a GROUP: every box attached to it copies the scroll position of whichever\n * member the person scrolled, on the axes the lock names.\n *\n * const lock = createScrollLock({ axis: 'y' });\n * new DataTable(left, { \u2026, scrollLock: lock });\n * new DataTable(right, { \u2026, scrollLock: lock });\n * lock.setEnabled(false); // the two scroll freely; true locks them again\n *\n * Any element can join with `lock.attach(el)`, which returns its detach. A\n * DataTable given `scrollLock` attaches its own body box on every render and\n * detaches it on the next render and on dispose, so a re-render (a sort, new\n * data) never strands a dead box in the group.\n *\n * THE ECHO. Setting `scrollTop` on a member fires that member's own `scroll`\n * event a frame later, and a naive group would then copy it back to the first\n * box, which by then may have moved on \u2014 the two fight and the wheel stutters.\n * So a position this lock WROTE is remembered per box, and the scroll event that\n * reports exactly that position is the echo and is ignored.\n *\n * A box that joins is moved to the group's last position, so a pane opened\n * beside a scrolled one starts level with it. Positions are copied as pixels:\n * the lock aligns rows only when the members draw rows of the same height,\n * which is the comparison's own contract (both sides drawn from one aligned\n * row list, a gap row where a side has none).\n */\n\n/**\n * @param {object} [options]\n * @param {'x'|'y'|'both'} [options.axis='y'] which positions are copied\n * @param {boolean} [options.enabled=true]\n */\nexport function createScrollLock({ axis = 'y', enabled = true } = {}) {\n const doY = axis === 'y' || axis === 'both';\n const doX = axis === 'x' || axis === 'both';\n const members = new Map(); // element -> { wrote: {top, left} | null, off }\n let last = { top: 0, left: 0 };\n let on = !!enabled;\n\n function copyFrom(source) {\n last = { top: source.scrollTop, left: source.scrollLeft };\n if (!on) return;\n for (const [el, state] of members) {\n if (el === source) continue;\n const top = doY ? last.top : el.scrollTop;\n const left = doX ? last.left : el.scrollLeft;\n if (el.scrollTop === top && el.scrollLeft === left) continue;\n state.wrote = { top, left };\n if (doY) el.scrollTop = top;\n if (doX) el.scrollLeft = left;\n }\n }\n\n function onScroll(event) {\n const el = event.currentTarget;\n const state = members.get(el);\n if (!state) return;\n const wrote = state.wrote;\n state.wrote = null;\n // THE ECHO of a position this lock set: not a person scrolling.\n if (wrote && Math.abs(el.scrollTop - wrote.top) < 1\n && Math.abs(el.scrollLeft - wrote.left) < 1) return;\n copyFrom(el);\n }\n\n const lock = {\n /** Join the group. Returns the function that leaves it. */\n attach(el) {\n if (!el || typeof el.addEventListener !== 'function') return () => {};\n if (members.has(el)) return () => lock.detach(el);\n const state = { wrote: null };\n members.set(el, state);\n el.addEventListener('scroll', onScroll, { passive: true });\n if (on && (last.top || last.left)) {\n state.wrote = { top: doY ? last.top : el.scrollTop,\n left: doX ? last.left : el.scrollLeft };\n if (doY) el.scrollTop = last.top;\n if (doX) el.scrollLeft = last.left;\n }\n return () => lock.detach(el);\n },\n detach(el) {\n if (!members.has(el)) return;\n members.delete(el);\n el.removeEventListener('scroll', onScroll);\n },\n /** Lock (true) or let the members scroll freely (false). Locking again\n * brings every member level with the one scrolled last. */\n setEnabled(value) {\n const was = on;\n on = !!value;\n if (on && !was) {\n const source = [...members.keys()].find(\n (el) => el.scrollTop === last.top && el.scrollLeft === last.left)\n || members.keys().next().value;\n if (source) copyFrom(source);\n }\n },\n get enabled() { return on; },\n /** How many boxes are in the group (for a consumer's own checks). */\n get size() { return members.size; },\n dispose() {\n for (const el of [...members.keys()]) lock.detach(el);\n },\n };\n return lock;\n}\n", "/**\n * tooltip_service.js\n *\n * JS-driven tooltip system for elements with `has-tooltip` class and `data-tooltip` attribute.\n * Also supports LaTeX tooltips with `has-latex-tooltip` and `data-latex-tooltip`.\n *\n * This replaces CSS-based ::after pseudo-element tooltips for better stacking context\n * and dynamic content support.\n */\n\nlet tooltipElement = null;\nlet currentTarget = null;\nlet listenersAttached = false;\nlet mouseCheckInterval = null;\nlet lastMousePosition = { x: 0, y: 0 };\n\n/**\n * Create or get the tooltip DOM element.\n * @returns {HTMLElement}\n */\nfunction createTooltipElement() {\n if (tooltipElement) return tooltipElement;\n\n tooltipElement = document.createElement('div');\n tooltipElement.className = 'twm-latex-tooltip';\n document.body.appendChild(tooltipElement);\n return tooltipElement;\n}\n\n/**\n * Position the tooltip relative to target element with smart auto-positioning.\n * Automatically flips placement if tooltip would extend outside viewport.\n * @param {HTMLElement} target - Element to position near\n * @param {HTMLElement} tooltip - Tooltip element\n */\nfunction positionTooltip(target, tooltip) {\n const rect = target.getBoundingClientRect();\n const tooltipRect = tooltip.getBoundingClientRect();\n const gap = 12;\n const margin = 10; // Minimum distance from viewport edge\n\n // Get requested placement from data attributes or context\n const requestedPlacement = (target.dataset?.tooltipPlacement || target.getAttribute('data-tooltip-placement') || '').toLowerCase() ||\n (target.dataset?.latexPlacement || target.getAttribute('data-latex-placement') || '').toLowerCase() ||\n (target.closest('.twm-global-top-bar') ? 'bottom' : (target.closest('.twm-fl-bar') ? 'right' : 'top'));\n\n // Auto-positioning: determine best placement based on available space\n let placement = requestedPlacement || 'top';\n\n // Check if explicit placement is set (not auto)\n const isExplicitPlacement = target.hasAttribute('data-tooltip-placement') ||\n target.hasAttribute('data-latex-placement');\n\n if (!isExplicitPlacement) {\n // Calculate available space in each direction\n const spaceAbove = rect.top - margin;\n const spaceBelow = window.innerHeight - rect.bottom - margin;\n const spaceLeft = rect.left - margin;\n const spaceRight = window.innerWidth - rect.right - margin;\n\n // Auto-select placement based on available space\n if (placement === 'top' && tooltipRect.height > spaceAbove && spaceBelow > spaceAbove) {\n placement = 'bottom';\n } else if (placement === 'bottom' && tooltipRect.height > spaceBelow && spaceAbove > spaceBelow) {\n placement = 'top';\n } else if (placement === 'left' && tooltipRect.width > spaceLeft && spaceRight > spaceLeft) {\n placement = 'right';\n } else if (placement === 'right' && tooltipRect.width > spaceRight && spaceLeft > spaceRight) {\n placement = 'left';\n }\n }\n\n // Calculate position based on final placement\n let left, top;\n\n if (placement === 'top') {\n left = rect.left + (rect.width / 2) - (tooltipRect.width / 2);\n top = rect.top - tooltipRect.height - gap;\n } else if (placement === 'bottom') {\n left = rect.left + (rect.width / 2) - (tooltipRect.width / 2);\n top = rect.bottom + gap;\n } else if (placement === 'left') {\n left = rect.left - tooltipRect.width - gap;\n top = rect.top + (rect.height / 2) - (tooltipRect.height / 2);\n } else if (placement === 'right') {\n left = rect.right + gap;\n top = rect.top + (rect.height / 2) - (tooltipRect.height / 2);\n }\n\n // Clamp to viewport\n const clampedLeft = Math.max(margin, Math.min(left, window.innerWidth - tooltipRect.width - margin));\n const clampedTop = Math.max(margin, Math.min(top, window.innerHeight - tooltipRect.height - margin));\n\n tooltip.style.left = `${clampedLeft}px`;\n tooltip.style.top = `${clampedTop}px`;\n\n // Calculate notch/arrow offset to point toward the target element center\n const targetCenterX = rect.left + rect.width / 2;\n const targetCenterY = rect.top + rect.height / 2;\n let notchOffset = 0;\n\n if (placement === 'top' || placement === 'bottom') {\n // Horizontal offset for notch\n const tooltipCenterX = clampedLeft + tooltipRect.width / 2;\n notchOffset = targetCenterX - tooltipCenterX;\n // Clamp notch offset to stay within tooltip bounds\n const maxOffset = (tooltipRect.width / 2) - 16; // 16px from edge minimum\n notchOffset = Math.max(-maxOffset, Math.min(notchOffset, maxOffset));\n } else {\n // Vertical offset for notch\n const tooltipCenterY = clampedTop + tooltipRect.height / 2;\n notchOffset = targetCenterY - tooltipCenterY;\n // Clamp notch offset\n const maxOffset = (tooltipRect.height / 2) - 16;\n notchOffset = Math.max(-maxOffset, Math.min(notchOffset, maxOffset));\n }\n\n // Set placement and notch offset attributes for CSS styling\n const setAttributes = () => {\n tooltip.setAttribute('data-placement', placement);\n tooltip.style.setProperty('--notch-offset', `${notchOffset}px`);\n };\n\n const guard = window.stateGuard;\n if (guard?.executeWithBypass) {\n guard.executeWithBypass('latex-tooltip:set-placement', setAttributes);\n } else {\n setAttributes();\n }\n}\n\n/**\n * Show tooltip for a target element.\n * @param {HTMLElement} target - Element with tooltip data\n */\nfunction showTooltip(target) {\n if (!target || !target.getAttribute) return;\n\n const hasLatex = target.classList && target.classList.contains('has-latex-tooltip');\n const hasPlain = target.classList && target.classList.contains('twm-has-tooltip');\n\n if (!hasLatex && !hasPlain) return;\n\n currentTarget = target;\n const tooltip = createTooltipElement();\n\n if (hasLatex) {\n // Render LaTeX using KaTeX\n const latex = target.getAttribute('data-latex-tooltip');\n if (!latex) return;\n\n try {\n if (typeof katex !== 'undefined') {\n katex.render(latex, tooltip, {\n displayMode: true,\n throwOnError: false,\n trust: false\n });\n } else {\n tooltip.textContent = latex;\n }\n } catch (err) {\n window.logger?.error('nodes', 'KaTeX rendering error:', err);\n tooltip.textContent = latex;\n }\n } else if (hasPlain) {\n // Plain text tooltip with line breaks preserved\n const text = target.getAttribute('data-tooltip');\n if (!text) return;\n\n // Replace &#10; with actual line breaks, preserve formatting\n const formattedText = text.replace(/&#10;/g, '\\n');\n const lines = formattedText.split('\\n');\n\n tooltip.innerHTML = '';\n lines.forEach((line, index) => {\n if (index === 0) {\n // First line is bold header\n const header = document.createElement('strong');\n header.textContent = line;\n tooltip.appendChild(header);\n } else {\n // Add line break and text\n tooltip.appendChild(document.createElement('br'));\n const textNode = document.createTextNode(line);\n tooltip.appendChild(textNode);\n }\n });\n }\n\n // Optional per-target width override (for long plain-text content like\n // widget documentation). Set data-tooltip-max-width on the target with a\n // CSS length (e.g. \"420px\"). Reset between shows so sticky values don't\n // leak across unrelated targets.\n const widthOverride = target.getAttribute('data-tooltip-max-width');\n tooltip.style.maxWidth = widthOverride || '';\n\n // Position and show\n requestAnimationFrame(() => {\n positionTooltip(target, tooltip);\n tooltip.classList.add('visible');\n\n // Start mouse position check for auto-hide\n startMouseCheck();\n });\n}\n\n/**\n * Hide the tooltip and clean up.\n */\nfunction hideTooltip() {\n if (tooltipElement) {\n tooltipElement.classList.remove('visible');\n }\n currentTarget = null;\n\n // Clear mouse check interval\n if (mouseCheckInterval) {\n clearInterval(mouseCheckInterval);\n mouseCheckInterval = null;\n }\n}\n\n/**\n * Start the mouse position check interval.\n * Hides tooltip if mouse is no longer over the target element.\n */\nfunction startMouseCheck() {\n // Clear any existing interval\n if (mouseCheckInterval) {\n clearInterval(mouseCheckInterval);\n }\n\n // Check every 3 seconds if mouse is still on the target element\n mouseCheckInterval = setInterval(() => {\n if (!currentTarget) {\n clearInterval(mouseCheckInterval);\n mouseCheckInterval = null;\n return;\n }\n\n // Get element under the last known mouse position\n const elementUnderMouse = document.elementFromPoint(lastMousePosition.x, lastMousePosition.y);\n\n // Check if the element under mouse is the target or a child of it\n if (elementUnderMouse) {\n const isStillOnTarget = elementUnderMouse === currentTarget ||\n currentTarget.contains(elementUnderMouse) ||\n elementUnderMouse.closest('.twm-has-tooltip, .has-latex-tooltip') === currentTarget;\n\n if (!isStillOnTarget) {\n hideTooltip();\n }\n } else {\n // Mouse is outside the document\n hideTooltip();\n }\n }, 3000);\n}\n\n/**\n * Attach global event listeners for tooltips.\n */\nfunction attachListeners() {\n if (listenersAttached) return;\n listenersAttached = true;\n\n // Remove all title attributes from elements with custom tooltips\n document.querySelectorAll('.twm-has-tooltip, .has-latex-tooltip').forEach(el => {\n el.removeAttribute('title');\n });\n\n // Track mouse position for the 3-second auto-hide check\n document.addEventListener('mousemove', (event) => {\n lastMousePosition.x = event.clientX;\n lastMousePosition.y = event.clientY;\n }, { passive: true });\n\n document.addEventListener('mouseenter', (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const tooltipTarget = target.closest('.has-latex-tooltip, .twm-has-tooltip');\n if (!tooltipTarget) return;\n showTooltip(tooltipTarget);\n }, true);\n\n document.addEventListener('mouseleave', (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const tooltipTarget = target.closest('.has-latex-tooltip, .twm-has-tooltip');\n if (!tooltipTarget) return;\n hideTooltip();\n }, true);\n\n // Hide on scroll\n document.addEventListener('scroll', hideTooltip, true);\n\n // ESC key hides all tooltips application-wide (does not stop propagation)\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') {\n hideTooltip();\n // Note: We intentionally do NOT call event.stopPropagation()\n // so other listeners can also respond to ESC\n }\n }, true);\n}\n\n/**\n * Initialize the tooltip system.\n */\nfunction initializeTooltips() {\n // Wait for KaTeX to load (optional, for latex tooltips)\n const initInterval = setInterval(() => {\n if (typeof katex !== 'undefined') {\n clearInterval(initInterval);\n if (!listenersAttached) {\n attachListeners();\n }\n }\n }, 100);\n\n // Timeout after 2 seconds - attach listeners anyway for plain tooltips\n setTimeout(() => {\n clearInterval(initInterval);\n if (!listenersAttached) {\n attachListeners();\n }\n }, 2000);\n}\n\n/**\n * Set a tooltip on an element programmatically.\n * @param {HTMLElement} element - Target element\n * @param {string} text - Tooltip text\n * @param {boolean} [isLatex=false] - Whether to render as LaTeX\n */\nfunction setTooltip(element, text, isLatex = false) {\n if (!element || !text) return;\n\n // Remove any existing title attribute\n element.removeAttribute('title');\n\n if (isLatex) {\n element.classList.add('has-latex-tooltip');\n element.classList.remove('twm-has-tooltip');\n element.setAttribute('data-latex-tooltip', text);\n } else {\n element.classList.add('twm-has-tooltip');\n element.classList.remove('has-latex-tooltip');\n element.setAttribute('data-tooltip', text);\n }\n}\n\n/**\n * Refresh tooltips for dynamically added content.\n * Removes title attributes that might cause native tooltips.\n * @param {HTMLElement} [container=document] - Container to search within\n */\nfunction refreshTooltips(container = document) {\n container.querySelectorAll('.twm-has-tooltip, .has-latex-tooltip').forEach(el => {\n el.removeAttribute('title');\n });\n}\n\n// ES module exports \u2014 the real interface.\nexport const TooltipService = {\n show: showTooltip,\n hide: hideTooltip,\n set: setTooltip,\n refresh: refreshTooltips,\n init: initializeTooltips\n};\n\nexport default TooltipService;\n\n// Everything below is a side effect of IMPORTING this file, and it is guarded.\n//\n// Unguarded, it touched `document` and `window` at module scope, which made\n// @flexdesk/widgets throw `ReferenceError: window is not defined` the moment anything\n// imported it outside a browser. The DOM check is not defensive programming; it\n// is the difference between a module and a script.\n//\n// `window.LatexTooltip` stays, because unlike `window.InlineRenamer` it is real:\n// roughly 25 call sites read it, all as `window.LatexTooltip?.set(...)`, and one\n// of them is INSIDE the library (window_chrome_controller.js). That last one is a\n// hidden dependency on a global and should import TooltipService instead \u2014 a small\n// piece of P6 cleanup, noted rather than smuggled in here.\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeTooltips);\n } else {\n initializeTooltips();\n }\n}\n\nif (typeof window !== 'undefined') {\n window.LatexTooltip = TooltipService;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\r\n * ControllerBase (js_new)\r\n *\r\n * Shared superclass for UI controllers (tab, panel, layout, etc.). Provides\r\n * deterministic teardown, scoped event subscriptions, and dependency injection.\r\n */\r\nexport class ControllerBase {\r\n constructor({ eventBus, dataManager, logger } = {}) {\r\n if (new.target === ControllerBase) {\r\n throw new Error('ControllerBase is abstract \u2013 extend it instead');\r\n }\r\n\r\n this.eventBus = eventBus;\r\n this.dataManager = dataManager;\r\n this.logger = logger;\r\n this._disposers = new Set();\r\n }\r\n\r\n /**\r\n * Register a disposer callback to guarantee teardown.\r\n */\r\n trackDisposer(disposer) {\r\n if (typeof disposer === 'function') {\r\n this._disposers.add(disposer);\r\n }\r\n }\r\n\r\n /**\r\n * Attach controller-specific DOM/event wiring. Subclasses implement this.\r\n */\r\n initialize(/* options */) {\r\n throw new Error('ControllerBase.initialize must be implemented by subclasses');\r\n }\r\n\r\n /**\r\n * Dispose all tracked resources.\r\n */\r\n dispose() {\r\n for (const disposer of this._disposers) {\r\n try {\r\n disposer();\r\n } catch (err) {\r\n this.logger?.error?.('ui', 'Controller disposer failed', err);\r\n }\r\n }\r\n this._disposers.clear();\r\n }\r\n}\r\n", "/**\r\n * PageBase (js_new)\r\n *\r\n * Abstract shell for every top-level UI page (node workspace, simulation, data).\r\n * Handles dependency injection + shared lifecycle hooks so individual pages only\r\n * focus on domain logic.\r\n *\r\n * ## Async Initialization Pattern\r\n * Pages with async initialization should:\r\n * 1. Store the init promise: `this._initPromise = this.init();` in mount()\r\n * 2. Use `await this.waitForReady()` in show()/hydrate() to wait for init\r\n * 3. Mark completion by resolving the promise (init() returns)\r\n *\r\n * Example:\r\n * ```javascript\r\n * mount(container) {\r\n * this.container = container;\r\n * this._initPromise = this.init(); // Store promise\r\n * this._mounted = true;\r\n * }\r\n *\r\n * async show() {\r\n * await this.waitForReady(); // Wait for init if still running\r\n * this.refresh();\r\n * }\r\n * ```\r\n */\r\nexport class PageBase {\r\n constructor({ eventBus, dataManager, notificationCenter, logger } = {}) {\r\n if (new.target === PageBase) {\r\n throw new Error('PageBase is abstract \u2013 extend it instead');\r\n }\r\n\r\n this.eventBus = eventBus;\r\n this.dataManager = dataManager;\r\n this.notificationCenter = notificationCenter;\r\n this.logger = logger;\r\n this._mounted = false;\r\n\r\n /**\r\n * Promise that resolves when async initialization completes.\r\n * Pages with async init should set this in mount().\r\n * @type {Promise<void>|null}\r\n */\r\n this._initPromise = null;\r\n }\r\n\r\n /**\r\n * Mount the page into a DOM container. Concrete pages must override this.\r\n * For pages with async initialization, store the init promise:\r\n * `this._initPromise = this.init();`\r\n */\r\n mount(/* container */) {\r\n throw new Error('PageBase.mount must be implemented by subclasses');\r\n }\r\n\r\n /**\r\n * Wait for the page to complete initialization.\r\n * Returns immediately if no async init or if already complete.\r\n * @returns {Promise<void>}\r\n */\r\n async waitForReady() {\r\n if (this._initPromise) {\r\n try {\r\n await this._initPromise;\r\n } catch (err) {\r\n this.logger?.warn?.('page', 'Init promise rejected', err);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Optional hook invoked after the initial mount to hydrate data/state.\r\n * For pages with async init, this should await waitForReady().\r\n */\r\n async hydrate(/* options */) {\r\n // default: wait for init to complete\r\n await this.waitForReady();\r\n }\r\n\r\n /**\r\n * Optional hook for when the page becomes active (tab switched, etc.).\r\n */\r\n onActivated(/* context */) {\r\n // default no-op\r\n }\r\n\r\n /**\r\n * Optional hook for when the page is hidden/unmounted but not disposed.\r\n */\r\n onDeactivated(/* context */) {\r\n // default no-op\r\n }\r\n\r\n /**\r\n * Dispose resources/event subscriptions.\r\n */\r\n dispose() {\r\n this._mounted = false;\r\n this._initPromise = null;\r\n }\r\n}\r\n", "/**\n * About Dialog Component\n *\n * A modal that shows a product's name, version, license, homepage and\n * third-party credits. It knows NOTHING about which product \u2014 the caller\n * supplies all of it.\n *\n * It used to hardcode EcoAgent's: PRODUCT_NAME, the GitHub URL, the tagline\n * (\"Heterogeneous-agent, stock-flow-consistent macroeconomic simulation\") and\n * two dependency lists. A library that ships an About box for somebody else's\n * application is not a library.\n *\n * EcoAgent's values now live in ui/js/ecoagent/about.js and are pushed in.\n *\n * @typedef {{name: string, license: string, url: string}} Dep\n * @typedef {{title: string, deps: Dep[]}} DepSection\n */\n\nimport { ManagedWindow } from './managed_window.js';\n\nfunction createExternalLink(text, url, className) {\n const a = document.createElement('a');\n a.className = className;\n a.textContent = text;\n a.href = url;\n a.title = url;\n a.addEventListener('click', (e) => {\n e.preventDefault();\n window.open(url, '_blank');\n });\n return a;\n}\n\nfunction buildDepSection(title, deps) {\n const section = document.createElement('div');\n section.className = 'twm-about-dialog__section';\n\n const heading = document.createElement('div');\n heading.className = 'twm-about-dialog__section-title';\n heading.textContent = title;\n section.appendChild(heading);\n\n const list = document.createElement('div');\n list.className = 'twm-about-dialog__dep-list';\n\n for (const dep of deps) {\n const row = document.createElement('div');\n row.className = 'twm-about-dialog__dep';\n\n const link = createExternalLink(dep.name, dep.url, 'twm-about-dialog__dep-name');\n row.appendChild(link);\n\n const lic = document.createElement('span');\n lic.className = 'twm-about-dialog__dep-license';\n lic.textContent = dep.license;\n row.appendChild(lic);\n\n list.appendChild(row);\n }\n\n section.appendChild(list);\n return section;\n}\n\n/**\n * Show the About dialog for whatever product the caller names.\n *\n * @param {Object} product\n * @param {string} product.name Product name \u2014 the title and the heading.\n * @param {string} [product.version]\n * @param {string} [product.tagline]\n * @param {string} [product.license] Shown as \"License: <x>\"; omitted if absent.\n * @param {string} [product.url] Homepage; omitted if absent.\n * @param {string} [product.urlLabel='Homepage']\n * @param {string} [product.logo='info'] Material symbol shown beside the title.\n * @param {DepSection[]} [product.credits=[]] Third-party credit sections.\n * @returns {Promise<void>} Resolves when the dialog is closed.\n */\nexport function showAboutDialog(product = {}) {\n const {\n name = 'Application',\n version = '',\n tagline = '',\n license = '',\n url = '',\n urlLabel = 'Homepage',\n logo = 'info',\n credits = [],\n } = product;\n\n return new Promise((resolve) => {\n let resolved = false;\n\n const finish = () => {\n if (resolved) return;\n resolved = true;\n dialogWindow.close();\n resolve();\n };\n\n // --- Content ---\n const contentEl = document.createElement('div');\n contentEl.className = 'twm-about-dialog__content';\n\n // Header\n const header = document.createElement('div');\n header.className = 'twm-about-dialog__header';\n\n const logoEl = document.createElement('span');\n logoEl.className = 'twm-about-dialog__logo material-symbols-outlined';\n logoEl.textContent = logo;\n header.appendChild(logoEl);\n\n const title = document.createElement('h2');\n title.className = 'twm-about-dialog__title';\n title.textContent = name;\n header.appendChild(title);\n\n if (version) {\n const versionEl = document.createElement('div');\n versionEl.className = 'twm-about-dialog__version';\n versionEl.textContent = `Version ${version}`;\n header.appendChild(versionEl);\n }\n\n if (tagline) {\n const taglineEl = document.createElement('div');\n taglineEl.className = 'twm-about-dialog__tagline';\n taglineEl.textContent = tagline;\n header.appendChild(taglineEl);\n }\n\n contentEl.appendChild(header);\n\n // Body (scrollable)\n const body = document.createElement('div');\n body.className = 'twm-about-dialog__body';\n\n // Project section \u2014 only if there is something to put in it.\n if (url || license) {\n const projectSection = document.createElement('div');\n projectSection.className = 'twm-about-dialog__section';\n\n const projectTitle = document.createElement('div');\n projectTitle.className = 'twm-about-dialog__section-title';\n projectTitle.textContent = 'Project';\n projectSection.appendChild(projectTitle);\n\n const links = document.createElement('div');\n links.className = 'twm-about-dialog__links';\n\n if (url) {\n const link = createExternalLink(urlLabel, url, 'twm-about-dialog__link');\n const icon = document.createElement('span');\n icon.className = 'material-symbols-outlined';\n icon.textContent = 'open_in_new';\n link.prepend(icon);\n links.appendChild(link);\n }\n\n if (license) {\n const licenseSpan = document.createElement('span');\n licenseSpan.className = 'twm-about-dialog__license-text';\n const licIcon = document.createElement('span');\n licIcon.className = 'material-symbols-outlined';\n licIcon.textContent = 'license';\n licenseSpan.appendChild(licIcon);\n licenseSpan.appendChild(document.createTextNode(`License: ${license}`));\n links.appendChild(licenseSpan);\n }\n\n projectSection.appendChild(links);\n body.appendChild(projectSection);\n }\n\n for (const section of credits) {\n body.appendChild(buildDepSection(section.title, section.deps ?? []));\n }\n\n contentEl.appendChild(body);\n\n // Footer\n const footer = document.createElement('div');\n footer.className = 'twm-about-dialog__footer';\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'twm-about-dialog__btn twm-about-dialog__btn--close';\n closeBtn.textContent = 'Close';\n closeBtn.addEventListener('click', finish);\n footer.appendChild(closeBtn);\n\n contentEl.appendChild(footer);\n\n // --- Window ---\n const dialogWindow = new ManagedWindow({\n id: 'about-dialog',\n title: `About ${name}`,\n icon: 'info',\n content: contentEl,\n minWidth: 420,\n minHeight: 400,\n defaultWidth: 460,\n defaultHeight: 540,\n canMinimize: false,\n canMaximize: false,\n canResize: false,\n canDrag: false,\n modal: true,\n onClose: () => {\n if (!resolved) {\n resolved = true;\n resolve();\n }\n },\n });\n\n dialogWindow.show();\n\n requestAnimationFrame(() => {\n closeBtn.focus();\n });\n });\n}\n", "/**\n * \u2550\u2550 THE ALERT LOG \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * What an application told its user, kept: every entry, newest first, read or\n * not, until it is dismissed or falls off the end (FlexDesk STORY-0019, from\n * bugdesk's `alerts.js`). NotificationCenter's toasts are the moment; this is\n * the history the Alerts pane (`alerts_pane.js`) and the bell\n * (NotificationHistory's `alertLog` option) read.\n *\n * An ENTRY is `{ id, at, level, title, body?, ref?, read, ruleId?, rule? }`.\n * `at` is a Date; `level` is one of `info`, `warning`, `alert` (`normalizeLevel`\n * maps the toast's `warn`/`error` and the server's `danger` onto them).\n *\n * WHERE ENTRIES LIVE IS THE EMBEDDER'S \u2014 a pluggable SOURCE:\n *\n * load({ offset, limit }) \u2192 { entries, more?, unread? } a page, newest first\n * markRead(ids | null) \u2192 null is \"all\"\n * dismiss(ids | null) \u2192 optional; without it nothing can be dismissed\n *\n * bugdesk keeps the whole log in its workspace state (`localSource`: one\n * blob, read once, written on every change); Tables pages its server's\n * notifications and has no dismiss. A source's `unread` is the count beyond\n * the loaded page \u2014 the server knows it, the page does not.\n *\n * CHANGES ARE APPLIED HERE FIRST and the source told after, so a click marks\n * read at once; a source that refuses is logged and the log re-read, rather\n * than the click being made to wait on a round trip.\n */\n\n/** The three levels, worst last; `icon` is a Material Symbols name. */\nexport const ALERT_LEVELS = Object.freeze({\n info: Object.freeze({ label: 'Info', icon: 'info' }),\n warning: Object.freeze({ label: 'Warning', icon: 'warning' }),\n alert: Object.freeze({ label: 'Alert', icon: 'notifications_active' }),\n});\n\nconst LEVEL_ALIASES = { warn: 'warning', error: 'alert', danger: 'alert', critical: 'alert', success: 'info' };\n\n/** One of `info`, `warning`, `alert`, whatever the caller spelt. */\nexport function normalizeLevel(level) {\n const l = String(level ?? '').toLowerCase();\n if (ALERT_LEVELS[l]) return l;\n return LEVEL_ALIASES[l] ?? 'info';\n}\n\n/** The worst level among these entries \u2014 a badge's colour \u2014 or null for none. */\nexport function worstLevel(entries) {\n let worst = null;\n for (const e of entries || []) {\n const l = normalizeLevel(e?.level);\n if (l === 'alert') return 'alert';\n if (l === 'warning') worst = 'warning';\n else if (!worst) worst = 'info';\n }\n return worst;\n}\n\n/** \"just now\", \"5 min ago\", \"3 h ago\"; older than a day, the clock time (the day header has the date). */\nexport function ago(at, now = new Date()) {\n const s = Math.max(0, (now - at) / 1000);\n if (s < 60) return 'just now';\n if (s < 3600) return `${Math.floor(s / 60)} min ago`;\n if (s < 86400) return `${Math.floor(s / 3600)} h ago`;\n return at.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/** TODAY, YESTERDAY, or the date \u2014 the Alerts pane's day header. */\nexport function dayLabel(at, now = new Date()) {\n const d = new Date(at.getFullYear(), at.getMonth(), at.getDate());\n const t = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const days = Math.round((t - d) / 86400000);\n if (days === 0) return 'TODAY';\n if (days === 1) return 'YESTERDAY';\n return at.toLocaleDateString([], { weekday: 'short', day: 'numeric', month: 'short', year: 'numeric' })\n .toUpperCase();\n}\n\nlet _seq = 0;\n\n/** An entry in the shape the log keeps, from whatever a source or a caller handed in. */\nfunction normalizeEntry(raw) {\n const at = raw.at instanceof Date ? raw.at : new Date(raw.at ?? Date.now());\n return {\n ...raw,\n id: String(raw.id ?? `${Date.now().toString(36)}-${(_seq++).toString(36)}`),\n at: Number.isNaN(at.getTime()) ? new Date() : at,\n level: normalizeLevel(raw.level),\n title: String(raw.title ?? ''),\n read: !!raw.read,\n };\n}\n\n/**\n * A source that keeps the whole log in one stored value \u2014 bugdesk's workspace\n * state, or localStorage. `read()` answers the saved array (or a promise of\n * it); `write(array)` stores one. Dates are written as ISO strings.\n */\nexport function localSource({ read, write, limit = 300 } = {}) {\n let all = null;\n const save = () => {\n try {\n write?.(all.map((e) => ({ ...e, at: e.at.toISOString() })));\n } catch (err) { console.warn('[alert-log] the log could not be saved', err); }\n };\n const ensure = async () => {\n if (all) return all;\n let saved = [];\n try { saved = (await read?.()) ?? []; } catch (err) {\n console.warn('[alert-log] the log could not be read', err);\n }\n all = (Array.isArray(saved) ? saved : []).filter((e) => e && typeof e === 'object')\n .map(normalizeEntry).sort((a, b) => b.at - a.at).slice(0, limit);\n return all;\n };\n return {\n local: true,\n async load({ offset = 0, limit: n = limit } = {}) {\n const list = await ensure();\n return { entries: list.slice(offset, offset + n), more: offset + n < list.length };\n },\n async add(entry) {\n const list = await ensure();\n list.unshift(entry);\n if (list.length > limit) list.length = limit;\n save();\n },\n async markRead(ids) {\n const want = ids ? new Set(ids) : null;\n for (const e of await ensure()) if (!want || want.has(e.id)) e.read = true;\n save();\n },\n async dismiss(ids) {\n const want = ids ? new Set(ids) : null;\n all = (await ensure()).filter((e) => want && !want.has(e.id));\n save();\n },\n };\n}\n\n/**\n * @param {object} [opts]\n * @param {object} [opts.source] where entries live; none keeps them in memory only\n * @param {number} [opts.limit] most entries held, and a page's size\n * @returns the log\n */\nexport function createAlertLog({ source = null, limit = 300 } = {}) {\n let entries = [];\n let more = false;\n let remoteUnread = null;\n let loaded = false;\n let loading = null;\n const listeners = new Set();\n\n const changed = () => {\n for (const fn of [...listeners]) {\n try { fn(log); } catch (err) { console.warn('[alert-log] listener failed', err); }\n }\n };\n const tell = (verb, ...args) => {\n const fn = source?.[verb];\n if (typeof fn !== 'function') return;\n Promise.resolve().then(() => fn.apply(source, args)).catch((err) => {\n console.warn(`[alert-log] the source refused ${verb}`, err);\n log.refresh();\n });\n };\n const page = async (offset) => {\n const res = (await source?.load?.({ offset, limit })) ?? {};\n const got = (res.entries ?? []).map(normalizeEntry);\n return { got, more: !!res.more, unread: Number.isFinite(res.unread) ? res.unread : null };\n };\n\n const log = {\n /** Loaded entries, newest first. */\n entries: () => entries,\n loaded: () => loaded,\n /** Whether the source has older entries than those loaded. */\n hasMore: () => more,\n /** Whether entries can be dismissed: a log with no source, or a source that can. */\n canDismiss: () => !source || typeof source.dismiss === 'function',\n /** Unread entries: the source's count when it knows one, else the loaded ones. */\n unreadCount() {\n const here = entries.filter((e) => !e.read).length;\n return remoteUnread === null ? here : Math.max(remoteUnread, here);\n },\n /** The worst level among unread entries, or null. */\n worstUnread: () => worstLevel(entries.filter((e) => !e.read)),\n get: (id) => entries.find((e) => e.id === String(id)) ?? null,\n\n /** `fn(log)` after every change; answers the unsubscribe. */\n subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n\n /** The first page, again. */\n refresh() {\n if (!source?.load) { loaded = true; changed(); return Promise.resolve(log); }\n loading = page(0).then(({ got, more: m, unread }) => {\n entries = got;\n more = m;\n remoteUnread = unread;\n loaded = true;\n changed();\n return log;\n }).catch((err) => {\n console.warn('[alert-log] the log could not be loaded', err);\n loaded = true;\n changed();\n return log;\n }).finally(() => { loading = null; });\n return loading;\n },\n /** Load once; later calls answer the same promise or nothing. */\n load() { return loading ?? (loaded ? Promise.resolve(log) : log.refresh()); },\n /** The next page, after the loaded ones. */\n async loadMore() {\n if (!more || !source?.load) return log;\n const { got, more: m, unread } = await page(entries.length);\n const seen = new Set(entries.map((e) => e.id));\n entries = [...entries, ...got.filter((e) => !seen.has(e.id))];\n more = m;\n if (unread !== null) remoteUnread = unread;\n changed();\n return log;\n },\n\n /** A new entry raised HERE (bugdesk's rules): kept, and handed to the source to save. */\n add(raw) {\n const entry = normalizeEntry(raw);\n entries = [entry, ...entries.filter((e) => e.id !== entry.id)];\n if (entries.length > limit) entries.length = limit;\n if (remoteUnread !== null && !entry.read) remoteUnread += 1;\n tell('add', entry);\n changed();\n return entry;\n },\n /** Entries that arrived from the source's side (a push): shown, not saved back. */\n receive(raws) {\n const got = (Array.isArray(raws) ? raws : [raws]).map(normalizeEntry);\n const ids = new Set(got.map((e) => e.id));\n const fresh = got.filter((e) => !entries.some((x) => x.id === e.id));\n entries = [...got, ...entries.filter((e) => !ids.has(e.id))]\n .sort((a, b) => b.at - a.at).slice(0, limit);\n if (remoteUnread !== null) remoteUnread += fresh.filter((e) => !e.read).length;\n changed();\n },\n /** Mark these read \u2014 all of them when `ids` is omitted. */\n markRead(ids = null) {\n const want = ids ? new Set(ids.map(String)) : null;\n let n = 0;\n for (const e of entries) if (!e.read && (!want || want.has(e.id))) { e.read = true; n++; }\n if (remoteUnread !== null) remoteUnread = want ? Math.max(0, remoteUnread - n) : 0;\n if (!n && want) return;\n tell('markRead', want ? [...want] : null);\n changed();\n },\n /** Remove these \u2014 all of them when `ids` is omitted. Nothing, when the source cannot. */\n dismiss(ids = null) {\n if (!log.canDismiss()) return;\n const want = ids ? new Set(ids.map(String)) : null;\n const gone = entries.filter((e) => !want || want.has(e.id));\n if (!gone.length) return;\n entries = want ? entries.filter((e) => !want.has(e.id)) : [];\n if (remoteUnread !== null) {\n remoteUnread = want ? Math.max(0, remoteUnread - gone.filter((e) => !e.read).length) : 0;\n }\n tell('dismiss', want ? [...want] : null);\n changed();\n },\n };\n if (!source?.load) loaded = true;\n return log;\n}\n", "/**\n * \u2550\u2550 THE ALERTS PANE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * An alert log (`alert_log.js`) drawn as the bottom panel's Alerts tab: level\n * chips with counts, a text filter, entries grouped by day with relative\n * times, an unread mark, Open and Dismiss on each row, Mark all read and Clear\n * for the lot (FlexDesk STORY-0019, from bugdesk's `alerts.js`). The same\n * layout whether the log is local or pages a server: *Load older* appears\n * when the source has more.\n *\n * mountAlertsPane(el, { log, onOpen: (entry) => \u2026, onBadge: ({ unread, level }) => \u2026 })\n *\n * OPTIONAL, for an embedder with rules of its own (bugdesk): `rules` is\n * `{ list() \u2192 [{ id, name, level, meta?, off? }], onEdit?, foot? }` \u2014 a column\n * of them on the left that narrows the log to one rule (entries carry\n * `ruleId`) \u2014 and `stillMatches(entry)` \u2192 true / false / null, drawn as \"still\n * matches\" or \"no longer matches\" on each row.\n *\n * NEVER REBUILT UNDER THE POINTER. A log changes on its own \u2014 a push from the\n * server, a rule firing, the minute tick \u2014 and a row repainted between a\n * mousedown and its click loses the click (Tables' recorded trap). While a\n * button is down inside the pane a repaint waits, and runs once it is up.\n * The bar (chips, the filter, the buttons) is built once and updated in\n * place, so typing in the filter never loses the caret either.\n *\n * OLDER ENTRIES LOAD AS YOU SCROLL (Tables STORY-0293): when the list is\n * scrolled to within :data:`MORE_WITHIN_PX` of its end and the source has\n * more, the next page is asked for \u2014 once at a time. *Load older* stays at the\n * end, for a list too short to scroll and for the keyboard.\n */\n\nimport { ALERT_LEVELS, ago, dayLabel, normalizeLevel } from './alert_log.js';\n\nconst CHIPS = [['all', 'All'], ['alert', 'Alert'], ['warning', 'Warning'], ['info', 'Info']];\n\n/** How near the end of the list a scroll asks for the next page. */\nexport const MORE_WITHIN_PX = 48;\n\n/**\n * @param {HTMLElement} host\n * @param {object} opts\n * @param {object} opts.log `createAlertLog(\u2026)`\n * @param {Function}[opts.onOpen] `(entry)` \u2014 Open; the entry is marked read first\n * @param {Function}[opts.onBadge] `({ unread, level })` after every change \u2014 a tab's badge\n * @param {object} [opts.rules] `{ list, onEdit?, foot? }`\n * @param {Function}[opts.stillMatches] `(entry) \u2192 boolean | null`\n * @param {Function}[opts.describe] `(entry) \u2192 string` \u2014 a small chip on the row (bugdesk: the store)\n * @param {string} [opts.status] the footer line\n * @param {object} [opts.empty] `{ none, filtered }` \u2014 the two empty texts\n * @returns {{ refresh, destroy, root }}\n */\nexport function mountAlertsPane(host, {\n log, onOpen = null, onBadge = null, rules = null, stillMatches = null, describe = null,\n status = '', empty = {},\n} = {}) {\n const doc = host.ownerDocument;\n const el = (tag, cls, text) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (text !== undefined) n.textContent = text;\n return n;\n };\n const icon = (name) => el('span', 'material-symbols-outlined', name);\n\n let level = 'all';\n let rule = null;\n let q = '';\n let pointerDown = false;\n let pending = false;\n let destroyed = false;\n\n // \u2500\u2500 the frame, built once \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-alerts');\n let ruleList = null;\n if (rules) {\n const side = el('div', 'twm-alerts__rules');\n const head = el('div', 'twm-alerts__head');\n head.append(el('span', 'twm-alerts__caps', 'RULES'), el('span', 'twm-alerts__spacer'));\n if (rules.onEdit) {\n const edit = el('button', 'twm-alerts__link', 'Edit rules');\n edit.type = 'button';\n edit.dataset.act = 'edit-rules';\n head.append(edit);\n }\n ruleList = el('div', 'twm-alerts__rulelist');\n side.append(head, ruleList);\n if (rules.foot) side.append(el('div', 'twm-alerts__foot', rules.foot));\n root.append(side);\n }\n const main = el('div', 'twm-alerts__main');\n const bar = el('div', 'twm-alerts__bar');\n const chips = el('div', 'twm-alerts__chips');\n chips.setAttribute('role', 'group');\n chips.setAttribute('aria-label', 'Level');\n const chipEls = new Map();\n for (const [key, label] of CHIPS) {\n const chip = el('button', 'twm-alerts__chip');\n chip.type = 'button';\n chip.dataset.level = key;\n chip.append(doc.createTextNode(`${label} `), el('span', 'twm-alerts__count', '0'));\n chips.append(chip);\n chipEls.set(key, chip);\n }\n const input = el('input', 'twm-alerts__q');\n input.type = 'text';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.placeholder = 'Filter';\n input.setAttribute('aria-label', 'Filter alerts');\n const readAll = el('button', 'twm-btn twm-alerts__btn', 'Mark all read');\n readAll.type = 'button';\n readAll.dataset.act = 'read-all';\n const clear = el('button', 'twm-btn twm-alerts__btn', 'Clear');\n clear.type = 'button';\n clear.dataset.act = 'clear';\n bar.append(chips, input, el('span', 'twm-alerts__spacer'), readAll, clear);\n const list = el('div', 'twm-alerts__log');\n const foot = el('div', 'twm-alerts__status', status);\n foot.hidden = !status;\n main.append(bar, list, foot);\n root.append(main);\n host.append(root);\n\n // \u2500\u2500 what is shown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const byRule = () => (rule ? log.entries().filter((e) => String(e.ruleId) === rule) : log.entries());\n const shown = () => {\n const needle = q.trim().toLowerCase();\n return byRule()\n .filter((e) => level === 'all' || e.level === level)\n .filter((e) => !needle || `${e.ref ?? ''} ${e.title} ${e.body ?? ''} ${e.rule ?? ''}`\n .toLowerCase().includes(needle));\n };\n\n function row(entry, now) {\n const lv = ALERT_LEVELS[normalizeLevel(entry.level)];\n const r = el('div', `twm-alerts__row twm-alerts__row--${entry.level}${entry.read ? '' : ' twm-alerts__row--unread'}`);\n r.dataset.id = entry.id;\n const mark = el('span', 'twm-alerts__unread');\n mark.setAttribute('aria-label', entry.read ? 'Read' : 'Unread');\n const ic = icon(lv.icon);\n ic.classList.add('twm-alerts__icon');\n ic.title = lv.label;\n const time = el('span', 'twm-alerts__time', ago(entry.at, now));\n time.title = entry.at.toLocaleString();\n const text = el('span', 'twm-alerts__text');\n text.append(el('span', 'twm-alerts__title', entry.title));\n if (entry.body) text.append(el('span', 'twm-alerts__body', entry.body));\n const cells = [mark, ic, time];\n if (rules) cells.push(el('span', 'twm-alerts__rule', entry.rule ?? ''));\n const tag = describe?.(entry);\n cells.push(el('span', tag ? 'twm-alerts__tag' : 'twm-alerts__tag twm-alerts__tag--none', tag ?? ''));\n const ref = el(entry.ref && onOpen ? 'button' : 'span', 'twm-alerts__ref', entry.ref ?? '');\n if (ref.tagName === 'BUTTON') { ref.type = 'button'; ref.dataset.open = entry.id; }\n cells.push(ref, text);\n if (stillMatches) {\n const still = stillMatches(entry);\n cells.push(el('span', `twm-alerts__state${still === false ? ' twm-alerts__state--gone' : ''}`,\n still === true ? 'still matches' : still === false ? 'no longer matches' : ''));\n }\n const acts = el('span', 'twm-alerts__acts');\n if (onOpen) {\n const open = el('button', 'twm-alerts__icon-btn');\n open.type = 'button';\n open.dataset.open = entry.id;\n open.title = 'Open';\n open.setAttribute('aria-label', 'Open');\n open.append(icon('open_in_new'));\n acts.append(open);\n }\n if (log.canDismiss()) {\n const dis = el('button', 'twm-alerts__icon-btn');\n dis.type = 'button';\n dis.dataset.dismiss = entry.id;\n dis.title = 'Dismiss';\n dis.setAttribute('aria-label', 'Dismiss');\n dis.append(icon('close'));\n acts.append(dis);\n }\n cells.push(acts);\n r.append(...cells);\n return r;\n }\n\n function paint() {\n if (destroyed) return;\n if (pointerDown) { pending = true; return; }\n pending = false;\n const now = new Date();\n const all = log.entries();\n const scoped = byRule();\n\n for (const [key, chip] of chipEls) {\n const on = level === key;\n chip.classList.toggle('twm-alerts__chip--on', on);\n chip.setAttribute('aria-pressed', String(on));\n chip.querySelector('.twm-alerts__count').textContent =\n String(scoped.filter((e) => key === 'all' || e.level === key).length);\n }\n readAll.disabled = !all.some((e) => !e.read) && log.unreadCount() === 0;\n clear.hidden = !log.canDismiss();\n clear.disabled = !all.length;\n\n if (ruleList) {\n const items = [{ id: null, name: 'All alerts', meta: String(all.length) }, ...(rules.list?.() ?? [])];\n ruleList.replaceChildren(...items.map((r) => {\n const key = r.id === null ? null : String(r.id);\n const b = el('button', `twm-alerts__rulebtn${rule === key ? ' twm-alerts__rulebtn--on' : ''}${r.off ? ' twm-alerts__rulebtn--off' : ''}`);\n b.type = 'button';\n b.dataset.rule = key ?? '';\n b.setAttribute('aria-pressed', String(rule === key));\n b.append(el('span', `twm-alerts__dot${r.level ? ` twm-alerts__dot--${normalizeLevel(r.level)}` : ''}`),\n el('span', 'twm-alerts__rulename', r.name || 'Unnamed rule'),\n el('span', 'twm-alerts__meta', r.meta ?? ''));\n return b;\n }));\n }\n\n const rows = [];\n let lastDay = '';\n for (const entry of shown()) {\n const day = dayLabel(entry.at, now);\n if (day !== lastDay) rows.push(el('div', 'twm-alerts__day', day));\n lastDay = day;\n rows.push(row(entry, now));\n }\n if (!rows.length) {\n rows.push(el('div', 'twm-alerts__none', !log.loaded() ? 'Loading\u2026'\n : all.length ? (empty.filtered ?? 'No alerts match.') : (empty.none ?? 'Nothing yet.')));\n }\n if (log.hasMore()) {\n const older = el('button', 'twm-btn twm-alerts__more', 'Load older');\n older.type = 'button';\n older.dataset.act = 'more';\n rows.push(older);\n }\n const scroll = list.scrollTop;\n list.replaceChildren(...rows);\n list.scrollTop = scroll;\n onBadge?.({ unread: log.unreadCount(), level: log.worstUnread() });\n }\n\n // \u2500\u2500 input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const onDown = () => { pointerDown = true; };\n const onUp = () => {\n if (!pointerDown) return;\n // After the click this mouseup belongs to has been dispatched.\n setTimeout(() => {\n pointerDown = false;\n if (pending) paint();\n }, 0);\n };\n root.addEventListener('mousedown', onDown, true);\n root.addEventListener('pointerdown', onDown, true);\n doc.addEventListener('mouseup', onUp, true);\n doc.addEventListener('pointerup', onUp, true);\n doc.addEventListener('pointercancel', onUp, true);\n\n root.addEventListener('click', (event) => {\n const t = event.target;\n const chip = t.closest('[data-level]');\n if (chip) { level = chip.dataset.level; paint(); return; }\n const r = t.closest('[data-rule]');\n if (r) { rule = r.dataset.rule || null; paint(); return; }\n const open = t.closest('[data-open]');\n if (open) {\n const entry = log.get(open.dataset.open);\n if (!entry) return;\n log.markRead([entry.id]);\n onOpen?.(entry);\n return;\n }\n const dis = t.closest('[data-dismiss]');\n if (dis) { log.dismiss([dis.dataset.dismiss]); return; }\n const act = t.closest('[data-act]')?.dataset.act;\n if (act === 'read-all') log.markRead();\n else if (act === 'clear') log.dismiss();\n else if (act === 'more') log.loadMore();\n else if (act === 'edit-rules') rules?.onEdit?.();\n });\n input.addEventListener('input', () => { q = input.value; paint(); });\n\n let loadingMore = false;\n list.addEventListener('scroll', () => {\n if (loadingMore || !log.hasMore()) return;\n if (list.scrollTop + list.clientHeight < list.scrollHeight - MORE_WITHIN_PX) return;\n loadingMore = true;\n Promise.resolve(log.loadMore()).catch(() => {}).finally(() => { loadingMore = false; });\n });\n\n const unsubscribe = log.subscribe(() => paint());\n // \"5 min ago\" moves on its own.\n const timer = setInterval(paint, 60000);\n paint();\n log.load?.();\n\n return {\n root,\n refresh: paint,\n destroy() {\n if (destroyed) return;\n destroyed = true;\n clearInterval(timer);\n unsubscribe();\n doc.removeEventListener('mouseup', onUp, true);\n doc.removeEventListener('pointerup', onUp, true);\n doc.removeEventListener('pointercancel', onUp, true);\n root.remove();\n },\n };\n}\n", "/**\n * attribute_list_editor.js \u2014 generic AttributeSpec list editor.\n *\n * One reusable component for every entity that declares a typed-slot\n * list: Asset.attributes, Archetype.attributes, SectorKind.requires,\n * MarketKind.requires, Flow.params, KPI.params. Mounts a SortableList\n * (drag-reorder + add + remove + empty-state) with typed cells:\n *\n * - scalar (number / integer / string / boolean): typed `<input>`\n * - expression: free-text input \u2014 engine evaluates each tick\n * - ref:<target>: typeahead-ish `<select>` populated by a caller-\n * supplied resolver returning {id, label} lists\n * - list[ref:<target>]: comma-separated input (UI primitive \u2014 chip\n * editor can land later without changing the data shape)\n * - select: dropdown of options (auto when `options[]` is set)\n *\n * Each row exposes the columns in `showColumns` (defaults to the full\n * set); callers narrow it (e.g. SectorKind.requires only needs name +\n * type + description, not default/value). Layout follows the column\n * spec \u2014 header strip aligned via CSS grid using --cols.\n *\n * Usage:\n *\n * import { mountAttributeListEditor } from\n * '../../ui/components/attribute_list_editor.js';\n *\n * const editor = mountAttributeListEditor(hostEl, {\n * items: kind.attributes,\n * showColumns: ['name', 'type', 'default', 'value', 'description'],\n * refResolvers: {\n * 'ref:asset': () => api.assets_list(),\n * },\n * onChange: (next) => { kind.attributes = next; save(); },\n * });\n * editor.refresh(); // call after `items` changes externally\n * editor.dispose(); // teardown\n */\n\nimport { SortableList } from './sortable_list.js';\n\n// The types a generic attribute editor knows about, with no application loaded.\n//\n// This used to also list nine EcoAgent entity kinds \u2014 asset_kind, market,\n// sub_sector, currency, sector, market_kind, asset_kind_template, archetype,\n// kpi \u2014 and derive `ref:<kind>` and `list[ref:<kind>]` from them. `types` was\n// ALREADY an injectable option; it simply had EcoAgent's ontology as its\n// default, which meant every consumer who didn't override it inherited a type\n// dropdown full of macroeconomics.\n//\n// Callers who want reference types build them with refTypesFor() and pass them\n// in, alongside the `refResolvers` that make them resolvable.\nconst SCALAR_TYPES = ['number', 'integer', 'string', 'boolean'];\n\nconst DEFAULT_TYPES = [...SCALAR_TYPES, 'expression'];\n\n/** `['agent']` -> `['ref:agent', 'list[ref:agent]']`. */\nexport function refTypesFor(kinds = []) {\n return [\n ...kinds.map((k) => `ref:${k}`),\n ...kinds.map((k) => `list[ref:${k}]`),\n ];\n}\n\nexport { SCALAR_TYPES, DEFAULT_TYPES };\n\nconst DEFAULT_COLUMNS = ['name', 'type', 'default', 'value', 'description'];\n\nconst COLUMN_TEMPLATES = {\n name: { label: 'name', width: 'minmax(140px, 1.2fr)' },\n type: { label: 'type', width: '140px' },\n default: { label: 'default', width: 'minmax(110px, 1fr)' },\n value: { label: 'value', width: 'minmax(110px, 1fr)' },\n description: { label: 'description', width: 'minmax(160px, 2fr)' },\n required: { label: 'req', width: '60px' },\n readonly: { label: 'r/o', width: '60px' },\n expression: { label: 'expression', width: 'minmax(160px, 2fr)' },\n // Layer N3 \u2014 extended AttributeSpec fields. Opt-in via showColumns\n // so existing single-table layouts (asset_kind editor) stay tight;\n // the agent params surface includes them.\n min: { label: 'min', width: '90px' },\n max: { label: 'max', width: '90px' },\n step: { label: 'step', width: '70px' },\n unit: { label: 'unit', width: '80px' },\n distribution: { label: 'dist', width: '110px' },\n // Distribution and \"selection set\" are two different concepts \u2014\n // numeric params sample from a continuous distribution (uniform /\n // normal / lognormal / \u2026), choice params pick from a discrete\n // option set. Keep them in separate columns so the user can tell\n // which is which at a glance.\n choices: { label: 'choices', width: '130px' },\n // Variation-override flags \u2014 R7 in\n // docs/ARCHETYPE_RETHINK_REQUIREMENTS.md. Tight columns so they\n // stay readable next to the scalar fields.\n enabled: { label: 'on', width: '50px' },\n force: { label: 'lock', width: '50px' },\n optional: { label: 'opt', width: '50px' },\n};\n\nconst DISTRIBUTION_OPTIONS = [\n '', 'constant', 'uniform', 'normal', 'lognormal', 'choice',\n];\n\n\n/** Classify one attribute against its parent-archetype counterpart.\n * Layer 8.J1 inheritance display:\n *\n * - 'inherited' \u2014 entity's effective value matches the archetype's\n * default for the same attribute name. UI paints the row blue.\n * - 'overridden' \u2014 entity's value is set AND differs from the\n * archetype's default. UI paints the row solarized orange + shows\n * a revert button.\n * - 'neutral' \u2014 neither side declares a value (or there's no parent).\n * UI paints the row in default style.\n */\nfunction _classifyRow(row, parentByName) {\n if (!parentByName) return 'neutral';\n const p = parentByName.get(row.name);\n if (!p) return 'neutral';\n const ourValue = (row.value !== undefined && row.value !== null)\n ? row.value : row.default;\n const parentValue = (p.value !== undefined && p.value !== null)\n ? p.value : p.default;\n if (ourValue === undefined || ourValue === null) return 'neutral';\n if (parentValue === undefined || parentValue === null) return 'overridden';\n // Loose equality: handles number vs numeric-string from form inputs.\n if (String(ourValue) === String(parentValue)) return 'inherited';\n return 'overridden';\n}\n\n\nexport function mountAttributeListEditor(hostEl, options = {}) {\n const {\n items = [],\n types = DEFAULT_TYPES,\n showColumns = DEFAULT_COLUMNS,\n refResolvers = {},\n onChange = () => {},\n onFlush = () => {},\n addButtonText = '',\n emptyMessage = 'No entries yet.',\n containerId = `attrs-${Math.random().toString(36).slice(2, 8)}`,\n allowReorder = true,\n allowRemove = true,\n // Layer 8.J1: parent-archetype attributes (the inherited baseline).\n // The editor uses this to classify each row as inherited / overridden /\n // neutral and to provide a revert action. Pass [] when no archetype\n // applies; the editor degrades gracefully (all rows render neutral).\n parentAttributes = null,\n createItem = () => ({\n name: '', type: 'string', default: null,\n value: null, description: '',\n }),\n // Layer N3 \u2014 per-column renderer overrides. Callers can supply\n // `cellOverrides: {column_name: (item, callbacks, ctx) => HTMLElement | null}`\n // to swap in a custom cell. Returning `null` falls through to\n // the default renderer. The `ctx` object exposes:\n // refreshRow() \u2014 force a re-render (the wider list refreshes\n // when the row's items change, e.g. type swap).\n // Use cases: agent params' distribution-dict button cell;\n // structured-type modal openers on the default cell.\n cellOverrides = null,\n // R7 \u2014 when true, this editor is mounted as a *variation* of the\n // parent archetype (not on the archetype itself). Rows where\n // the parent has `force=true` lock their editable cells; the\n // `enabled/force/optional` flag columns themselves stay\n // read-only (variations don't author flags, only the\n // archetype does).\n variationMode = false,\n } = options;\n\n // Lookup map for inheritance classification.\n const parentByName = parentAttributes\n ? new Map(parentAttributes.map((p) => [p.name, p]))\n : null;\n\n if (!hostEl) {\n return { refresh() {}, addItem() {}, dispose() {} };\n }\n\n hostEl.classList.add('twm-attr-editor');\n hostEl.style.setProperty('--cols',\n showColumns.map((c) => COLUMN_TEMPLATES[c]?.width || '1fr').join(' '));\n\n const refsCache = new Map();\n const resolveRefOptions = async (target) => {\n if (refsCache.has(target)) return refsCache.get(target);\n const resolver = refResolvers[`ref:${target}`]\n || refResolvers[`list[ref:${target}]`];\n let list = [];\n if (typeof resolver === 'function') {\n try { list = await resolver() || []; }\n catch (e) { console.warn('ref resolver failed', target, e); }\n }\n const normalised = (list || []).map((o) => {\n if (typeof o === 'string') return { id: o, label: o };\n return { id: o.id ?? o.value ?? '', label: o.label ?? o.id ?? '' };\n }).filter((o) => o.id);\n refsCache.set(target, normalised);\n return normalised;\n };\n\n // Header strip \u2014 mimics the SortableList row layout exactly so\n // header cells align with body cells. Row shape is:\n // [drag-handle] [content-with-cols-grid] [remove-button]\n // The header reuses `.sortable-list__row` chrome with placeholder\n // spans for the handle / remove gutters, then the inner content\n // div carries the same `--cols` grid as each row's content div.\n const header = document.createElement('div');\n header.className = 'twm-sortable-list__row twm-attr-editor__header-row';\n if (allowReorder) {\n const handlePh = document.createElement('span');\n handlePh.className = 'twm-sortable-list__handle twm-attr-editor__header-placeholder';\n header.appendChild(handlePh);\n }\n const headerContent = document.createElement('div');\n headerContent.className = 'twm-sortable-list__content twm-attr-editor__headers';\n for (const col of showColumns) {\n const span = document.createElement('span');\n span.textContent = COLUMN_TEMPLATES[col]?.label ?? col;\n headerContent.appendChild(span);\n }\n header.appendChild(headerContent);\n if (allowRemove) {\n const removePh = document.createElement('span');\n removePh.className = 'twm-sortable-list__remove twm-attr-editor__header-placeholder';\n header.appendChild(removePh);\n }\n hostEl.appendChild(header);\n\n const listHost = document.createElement('div');\n listHost.className = 'ea-attr-editor__rows';\n hostEl.appendChild(listHost);\n\n let list = null;\n\n const renderRow = (contentEl, item, _idx, callbacks) => {\n contentEl.classList.add('twm-attr-editor__row');\n // Layer 8.J1 \u2014 paint inheritance state.\n const cls = _classifyRow(item, parentByName);\n contentEl.classList.remove(\n 'twm-attr-editor__row--inherited',\n 'twm-attr-editor__row--overridden',\n 'twm-attr-editor__row--neutral',\n );\n contentEl.classList.add(`twm-attr-editor__row--${cls}`);\n\n // R7 variation-override flags. `enabled` defaults true, so the\n // disabled treatment only applies when explicitly false.\n // `force` locks the row (variations can't override). `optional`\n // signals the value is a suggestion \u2014 green border, no fill.\n // The flag rules are applied additively so the inheritance\n // classification's background still shows where applicable.\n // In variation mode the relevant flags are the parent's; in\n // archetype mode they're the row's own. (A variation row only\n // has the flags it inherited; it doesn't author its own.)\n const parentRow = parentByName?.get(item.name);\n const flagSource = variationMode && parentRow ? parentRow : item;\n contentEl.classList.toggle(\n 'twm-attr-editor__row--disabled', flagSource.enabled === false);\n contentEl.classList.toggle(\n 'twm-attr-editor__row--forced', flagSource.force === true);\n contentEl.classList.toggle(\n 'twm-attr-editor__row--optional', flagSource.optional === true);\n\n // Attention indicator on overridden rows + revert button.\n if (cls === 'overridden') {\n const attention = document.createElement('span');\n attention.className = 'twm-attr-editor__attention material-symbols-outlined';\n attention.textContent = 'fiber_manual_record';\n attention.title = 'Value overrides the parent default';\n contentEl.appendChild(attention);\n }\n\n for (const col of showColumns) {\n const cell = renderCell(col, item, callbacks);\n contentEl.appendChild(cell);\n }\n // R7 \u2014 lock the row's editable inputs when the parent forced it.\n // The flag columns themselves stay enabled on the archetype\n // (where the author sets them); in variation mode they're\n // read-only because variations don't author flags.\n const FLAG_COLS = new Set(['enabled', 'force', 'optional']);\n if (variationMode && flagSource.force === true) {\n contentEl.querySelectorAll(\n 'input:not([type=\"checkbox\"]), select, textarea'\n ).forEach((el) => { el.disabled = true; });\n }\n if (variationMode) {\n contentEl.querySelectorAll(\n 'input[type=\"checkbox\"].ea-attr-editor__cell--flag'\n ).forEach((el) => { el.disabled = true; });\n }\n void FLAG_COLS; // referenced by future per-column handling\n\n // Revert button \u2014 only rendered for overridden rows. Resets\n // `value` back to the archetype's inherited default. The row\n // re-classifies as 'inherited' on the next render pass.\n if (cls === 'overridden' && parentByName) {\n const p = parentByName.get(item.name);\n const parentDefault = (p?.value !== undefined && p?.value !== null)\n ? p.value : p?.default;\n const revert = document.createElement('button');\n revert.type = 'button';\n revert.className = 'twm-attr-editor__revert material-symbols-outlined';\n revert.textContent = 'undo';\n revert.title =\n `Revert to inherited default (${parentDefault ?? '\u2014'})`;\n revert.addEventListener('click', (e) => {\n e.stopPropagation();\n callbacks.update({ value: parentDefault });\n onFlush();\n // Force a re-render so the row re-classifies.\n list?.setItems(currentItems());\n });\n contentEl.appendChild(revert);\n }\n };\n\n const renderCell = (col, item, callbacks) => {\n // Caller override wins \u2014 used by agent_tab to inject the\n // distribution-dict button + structured-type modal openers.\n if (cellOverrides && typeof cellOverrides[col] === 'function') {\n const ctx = { refreshRow: () => list?.setItems(currentItems()) };\n const custom = cellOverrides[col](item, callbacks, ctx);\n if (custom) return custom;\n }\n if (col === 'name') return renderTextCell(item, 'name', callbacks, 'attr_name');\n if (col === 'type') return renderTypeCell(item, callbacks);\n if (col === 'description') return renderTextCell(item, 'description', callbacks, 'optional');\n if (col === 'required') return renderBoolCell(item, 'required', callbacks);\n if (col === 'readonly') return renderBoolCell(item, 'readonly', callbacks);\n // R7 \u2014 three variation-override flags. `enabled` defaults true,\n // so the checkbox renders checked when the field is undefined;\n // the others default false.\n if (col === 'enabled') return renderFlagCell(item, 'enabled', callbacks, true);\n if (col === 'force') return renderFlagCell(item, 'force', callbacks, false);\n if (col === 'optional') return renderFlagCell(item, 'optional', callbacks, false);\n if (col === 'expression') return renderTextCell(item, 'expression', callbacks, 'expr');\n if (col === 'min') return renderNumericCell(item, 'min', callbacks);\n if (col === 'max') return renderNumericCell(item, 'max', callbacks);\n if (col === 'step') return renderTextCell(item, 'step', callbacks, 'any');\n if (col === 'unit') return renderTextCell(item, 'unit', callbacks, 'USD/%/\u2026');\n if (col === 'distribution') return renderDistributionCell(item, callbacks);\n if (col === 'default' || col === 'value') return renderTypedValueCell(col, item, callbacks);\n // Unknown column \u2014 render a stub.\n const stub = document.createElement('span');\n stub.textContent = '';\n return stub;\n };\n\n const renderNumericCell = (item, field, callbacks) => {\n const el = document.createElement('input');\n el.type = 'number';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.step = 'any';\n el.value = (item[field] === null || item[field] === undefined)\n ? '' : String(item[field]);\n el.placeholder = '\u2014';\n el.addEventListener('input', () => {\n const v = el.value === '' ? null : Number(el.value);\n callbacks.update({ [field]: v });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderDistributionCell = (item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n for (const d of DISTRIBUTION_OPTIONS) {\n const o = document.createElement('option');\n o.value = d; o.textContent = d || '(none)';\n if ((item.distribution || '') === d) o.selected = true;\n el.appendChild(o);\n }\n el.addEventListener('change', () => {\n callbacks.update({ distribution: el.value || null });\n onFlush();\n });\n return el;\n };\n\n const renderTextCell = (item, field, callbacks, placeholder) => {\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.value = item[field] ?? '';\n el.placeholder = placeholder;\n el.addEventListener('input', () => {\n callbacks.update({ [field]: el.value });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderBoolCell = (item, field, callbacks) => {\n const el = document.createElement('input');\n el.type = 'checkbox';\n el.className = 'twm-attr-editor__cell';\n el.checked = !!item[field];\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.checked });\n onFlush();\n });\n return el;\n };\n\n /** Boolean cell for R7 flags. Same as renderBoolCell but treats an\n * undefined value as `defaultIfMissing`, so `enabled` (default\n * true) renders checked on legacy rows that predate the flag. */\n const renderFlagCell = (item, field, callbacks, defaultIfMissing) => {\n const el = document.createElement('input');\n el.type = 'checkbox';\n el.className = 'twm-attr-editor__cell ea-attr-editor__cell--flag';\n const cur = item[field];\n el.checked = (cur === undefined || cur === null)\n ? !!defaultIfMissing : !!cur;\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.checked });\n onFlush();\n });\n return el;\n };\n\n const renderTypeCell = (item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n // Group scalar, expression, ref, list[ref] for readability.\n // Any type the caller hands us that doesn't fit one of those\n // buckets lands in `other` \u2014 that's how param-mode types\n // (float / int / str / bool / choice / map / schedule /\n // string_list) appear without breaking the dispatch.\n const seen = new Set();\n const addOpts = (label, optList) => {\n if (optList.length === 0) return;\n const grp = document.createElement('optgroup');\n grp.label = label;\n for (const t of optList) {\n const o = document.createElement('option');\n o.value = t; o.textContent = t;\n if (t === item.type) o.selected = true;\n grp.appendChild(o);\n seen.add(t);\n }\n el.appendChild(grp);\n };\n addOpts('scalar', types.filter((t) => SCALAR_TYPES.includes(t)));\n addOpts('expression', types.filter((t) => t === 'expression'));\n addOpts('typed reference', types.filter((t) => t.startsWith('ref:')));\n addOpts('list of references',\n types.filter((t) => t.startsWith('list[ref:')));\n addOpts('other', types.filter((t) => !seen.has(t)));\n el.addEventListener('change', () => {\n // On type change, leave default/value as-is \u2014 the user\n // may want to keep e.g. a numeric value when switching\n // from number to integer. The typed value cell renderer\n // coerces on display.\n callbacks.update({ type: el.value });\n onFlush();\n // Force re-render so the value cell picks up the new\n // input type (number \u2192 select, etc.).\n list?.setItems(currentItems());\n });\n return el;\n };\n\n const renderTypedValueCell = (field, item, callbacks) => {\n const t = item.type || 'string';\n if (t === 'boolean') {\n return renderBoolCell(item, field, callbacks);\n }\n if (t === 'integer' || t === 'number') {\n const el = document.createElement('input');\n el.type = 'number';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.step = (t === 'integer') ? '1' : 'any';\n el.value = (item[field] === null || item[field] === undefined)\n ? '' : item[field];\n el.placeholder = field;\n el.addEventListener('input', () => {\n const v = el.value === '' ? null\n : (t === 'integer' ? parseInt(el.value, 10)\n : Number(el.value));\n callbacks.update({ [field]: v });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n }\n if (t === 'expression') {\n // For an expression-typed attribute, the value cell shows\n // the expression itself (read-only by convention \u2014 the\n // engine fills it). Stub: render the expression string;\n // the actual expression authoring lives in the\n // `expression` column when shown.\n const el = document.createElement('span');\n el.className = 'twm-attr-editor__cell twm-attr-editor__cell--readonly';\n el.textContent = item.expression\n ? `\u2192 ${item.expression}` : '\u2014 (engine-evaluated)';\n return el;\n }\n if (t.startsWith('ref:')) {\n return renderRefCell(t.slice(4), field, item, callbacks);\n }\n if (t.startsWith('list[ref:') && t.endsWith(']')) {\n return renderListRefCell(t.slice(9, -1), field, item, callbacks);\n }\n if (Array.isArray(item.options) && item.options.length > 0) {\n return renderEnumCell(item.options, field, item, callbacks);\n }\n // String fallback.\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n el.value = item[field] ?? '';\n el.placeholder = field;\n el.addEventListener('input', () => {\n callbacks.update({ [field]: el.value });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderRefCell = (target, field, item, callbacks) => {\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = `\u2014 pick ${target} \u2014`;\n el.appendChild(placeholder);\n // Render once with the cached options if we have them; resolve\n // async otherwise and patch.\n const populate = (opts) => {\n // Clear everything except the placeholder.\n while (el.childNodes.length > 1) el.removeChild(el.lastChild);\n for (const o of opts) {\n const node = document.createElement('option');\n node.value = o.id;\n node.textContent = o.label;\n if (o.id === item[field]) node.selected = true;\n el.appendChild(node);\n }\n };\n if (refsCache.has(target)) {\n populate(refsCache.get(target));\n } else {\n resolveRefOptions(target).then(populate);\n }\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.value || null });\n onFlush();\n });\n return el;\n };\n\n const renderListRefCell = (target, field, item, callbacks) => {\n // MVP: comma-separated text input over the underlying string-\n // list. The chip-style picker can replace this without\n // changing the on-disk shape.\n const el = document.createElement('input');\n el.type = 'text';\n el.className = 'twm-sortable-list__input twm-attr-editor__cell';\n const arr = Array.isArray(item[field]) ? item[field] : [];\n el.value = arr.join(', ');\n el.placeholder = `${target}, ${target}, \u2026`;\n el.addEventListener('input', () => {\n const next = el.value.split(',')\n .map((s) => s.trim()).filter(Boolean);\n callbacks.update({ [field]: next });\n });\n el.addEventListener('blur', () => onFlush());\n return el;\n };\n\n const renderEnumCell = (options, field, item, callbacks) => {\n // `options` may be either a flat list of strings (legacy:\n // `['fx', 'commodity', \u2026]`) or a list of `{value, label}`\n // pairs (newer callers that want display labels distinct from\n // the stored value, e.g. market-rules ref fields where the\n // value is a currency id and the label is the currency name).\n const el = document.createElement('select');\n el.className = 'twm-attr-editor__cell';\n // Empty placeholder so the user can clear the selection.\n const blank = document.createElement('option');\n blank.value = '';\n blank.textContent = '\u2014';\n if (item[field] === null || item[field] === undefined || item[field] === '') {\n blank.selected = true;\n }\n el.appendChild(blank);\n for (const opt of options) {\n const o = document.createElement('option');\n if (opt !== null && typeof opt === 'object') {\n o.value = String(opt.value ?? opt.id ?? '');\n o.textContent = String(opt.label ?? opt.value ?? opt.id ?? '');\n } else {\n o.value = String(opt);\n o.textContent = String(opt);\n }\n if (o.value === String(item[field] ?? '')) o.selected = true;\n el.appendChild(o);\n }\n el.addEventListener('change', () => {\n callbacks.update({ [field]: el.value === '' ? null : el.value });\n onFlush();\n });\n return el;\n };\n\n // \u2500\u2500\u2500 SortableList wiring \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const itemsCopy = (src) => (src || []).map((it) => ({ ...it }));\n const currentItems = () => list?.getItems?.() || itemsCopy(items);\n\n const buildList = (current) => {\n try { list?.dispose?.(); } catch {}\n listHost.innerHTML = '';\n list = new SortableList({\n containerId,\n items: itemsCopy(current),\n allowReorder,\n allowRemove,\n minItems: 0,\n emptyMessage,\n addButtonText,\n createItem,\n renderItem: renderRow,\n onChange: (next) => onChange(next.map((it) => ({ ...it }))),\n });\n listHost.appendChild(list.render());\n };\n\n buildList(items);\n\n return {\n addItem() { list?.addItem(); },\n refresh(nextItems) {\n // External update: rebuild to pick up new type-cell shapes.\n // Cheaper than setItems when types changed; setItems\n // wouldn't re-render the row controls.\n buildList(nextItems !== undefined ? nextItems : currentItems());\n },\n items() {\n return currentItems();\n },\n dispose() {\n try { list?.dispose?.(); } catch {}\n list = null;\n hostEl.innerHTML = '';\n hostEl.classList.remove('twm-attr-editor');\n },\n };\n}\n", "/**\n * category_picker.js\n *\n * A categorised picker popover (STORY-0126): a search field over three\n * columns \u2014 the categories (colour dot, label, item count), the active\n * category's items (icon, label) and a detail pane for the highlighted item\n * (title, description, an optional monospace preview, an Add button).\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\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\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\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 \u25CF Text 3 \u2502 [H] Heading \u2502 Delay / Lag \u2502\n * \u2502 \u25CF Model 5 \u2502 [\u0394t] Delay / Lag \u2502 The value of an \u2502\n * \u2502 \u25CF Functions 6\u2502 [Tb] Schedule \u2502 expression some time\u2026 \u2502\n * \u2502 \u2502 \u2502 \u250C\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 \u2502 \u2502 lag(inflation, 2) \u2502 \u2502\n * \u2502 \u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n * \u2502 \u2502 \u2502 [Add] \u2502\n * \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\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 * Usage:\n * ```javascript\n * const picker = new CategoryPicker({\n * trigger: addButton,\n * categories: [\n * { id: 'text', label: 'Text', color: 'var(--accent-light)', items: [\n * { id: 'heading', label: 'Heading', badge: 'H',\n * description: 'A section heading.', preview: '## Debt dynamics' },\n * ] },\n * ],\n * onSelect: (item, category) => insert(category.id, item.id),\n * });\n * picker.open(); picker.close(); picker.toggle(); picker.destroy();\n * ```\n *\n * It is anchored and dismissed like `ActionDropdown`: the trigger's click\n * toggles it, it is placed by `ActionDropdown.position` (position: fixed,\n * under the trigger or flipped above it, kept 8px inside the window), drawn\n * on `--z-over-windows`, and an outside click or Escape closes it. Escape and\n * a pick give focus back to the trigger.\n *\n * Keyboard. Focus sits in the search field; typing filters. With no query,\n * Up/Down move within the current column (the categories, or the active\n * category's items) and Left/Right move between the two. With a query, the\n * items column is a flat hit list across every category, grouped under the\n * category's label; Up/Down walk it and Left/Right edit the query. Enter\n * picks the highlighted item, Escape closes. A double-click on an item picks\n * it; hovering or clicking one shows it in the detail pane.\n */\nimport { ActionDropdown } from './action_dropdown.js';\n\nlet _seq = 0;\n\n/** Lower-cased words of a query; empty for a blank one. */\nfunction _terms(query) {\n return String(query || '').toLowerCase().split(/\\s+/).filter(Boolean);\n}\n\n/** What a query is matched against: the label, the description, the keywords. */\nfunction _haystack(item) {\n const kw = Array.isArray(item.keywords) ? item.keywords.join(' ') : (item.keywords || '');\n return `${item.label || ''} ${item.description || ''} ${kw}`.toLowerCase();\n}\n\nfunction _el(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text != null) n.textContent = text;\n return n;\n}\n\nexport class CategoryPicker {\n /**\n * @param {Object} config\n * @param {HTMLElement} config.trigger - The element the picker opens from; its click toggles it\n * @param {Array} config.categories - `[{ id, label, color?, items: [{ id, label, icon?, badge?,\n * description?, preview?, keywords? }] }]`. `icon` is a Material Symbols ligature; `badge` a\n * short text drawn as a monospace badge in the category's colour; `preview` is text shown\n * monospace in the detail pane; `keywords` (array or string) are searched but not shown.\n * @param {Function} config.onSelect - `(item, category)` when an item is picked\n * @param {string} [config.className=''] - Additional CSS class for the popover\n * @param {string} [config.placeholder='Search\u2026'] - The search field's placeholder\n * @param {string} [config.addLabel='Add'] - The detail pane's button\n * @param {string} [config.previewLabel] - A caption over the preview block (none when omitted)\n * @param {'start'|'end'} [config.align='start'] - Which trigger edge it lines up with first\n * @param {string} [config.label='Pick'] - The popover's accessible name (its `aria-label`)\n */\n constructor(config) {\n this.trigger = config.trigger;\n this.categories = config.categories || [];\n this.onSelect = config.onSelect;\n this.className = config.className || '';\n this.placeholder = config.placeholder ?? 'Search\u2026';\n this.addLabel = config.addLabel ?? 'Add';\n this.previewLabel = config.previewLabel || '';\n this.align = config.align === 'end' ? 'end' : 'start';\n this.label = config.label || 'Pick';\n\n this.isOpen = false;\n this.el = null;\n\n this._id = `twm-category-picker-${++_seq}`;\n this._query = '';\n this._activeCat = 0; // index of the category whose items show (no query)\n this._column = 'items'; // 'categories' | 'items' \u2014 where Up/Down go\n this._hl = null; // { c, i } \u2014 the highlighted item\n this._rows = []; // the items column's rows, in order: { c, i, el }\n\n this._onDocClick = this._onDocClick.bind(this);\n this._onKeydown = this._onKeydown.bind(this);\n this._onTriggerClick = this._onTriggerClick.bind(this);\n\n if (!this.trigger) {\n console.warn('[CategoryPicker] No trigger element provided');\n return;\n }\n this._build();\n this.trigger.setAttribute('aria-haspopup', 'dialog');\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.addEventListener('click', this._onTriggerClick);\n }\n\n // \u2500\u2500 DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _build() {\n const root = _el('div', `twm-category-picker ${this.className}`.trim());\n root.setAttribute('role', 'dialog');\n root.setAttribute('aria-label', this.label);\n root.hidden = true;\n // FOCUS STAYS IN THE SEARCH FIELD. A press on anything but the field\n // (a row, a group header, the detail text, padding, a disabled button)\n // would otherwise move focus to <body>, outside the popover, and the\n // arrow keys, Enter and typing would stop reaching it while it is\n // open. The click still happens; only the focus move is cancelled\n // (which also means the preview's text cannot be drag-selected).\n root.addEventListener('mousedown', (e) => {\n if (e.target !== this._input) e.preventDefault();\n });\n\n const search = _el('div', 'twm-category-picker__search');\n const input = _el('input', 'twm-category-picker__input');\n input.type = 'search';\n input.placeholder = this.placeholder;\n input.setAttribute('aria-label', this.placeholder || 'Search');\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `${this._id}-items`);\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.addEventListener('input', () => this._setQuery(input.value));\n search.appendChild(input);\n\n const body = _el('div', 'twm-category-picker__body');\n const cats = _el('div', 'twm-category-picker__categories twm-category-picker__column');\n cats.id = `${this._id}-cats`;\n cats.setAttribute('role', 'listbox');\n cats.setAttribute('aria-label', 'Categories');\n const items = _el('div', 'twm-category-picker__items twm-category-picker__column');\n items.id = `${this._id}-items`;\n items.setAttribute('role', 'listbox');\n items.setAttribute('aria-label', 'Items');\n // No aria-live: the input's aria-activedescendant already announces\n // each move, and a live region would read the pane on every one.\n const detail = _el('div', 'twm-category-picker__detail');\n body.append(cats, items, detail);\n\n root.append(search, body);\n document.body.appendChild(root);\n\n this.el = root;\n this._input = input;\n this._catsEl = cats;\n this._itemsEl = items;\n this._detailEl = detail;\n this._render();\n }\n\n /** The items column's entries: the active category's items, or every hit for the query. */\n _visible() {\n const terms = _terms(this._query);\n if (!terms.length) {\n const cat = this.categories[this._activeCat];\n return (cat?.items || []).map((_, i) => ({ c: this._activeCat, i }));\n }\n const out = [];\n this.categories.forEach((cat, c) => (cat.items || []).forEach((item, i) => {\n const hay = _haystack(item);\n if (terms.every((t) => hay.includes(t))) out.push({ c, i });\n }));\n return out;\n }\n\n /** Rebuild both lists and the detail pane. Hover never calls this. */\n _render() {\n if (!this.el) return;\n const searching = _terms(this._query).length > 0;\n const visible = this._visible();\n const hits = new Map();\n for (const v of visible) hits.set(v.c, (hits.get(v.c) || 0) + 1);\n\n // Keep the highlight when it is still listed, else the first entry.\n if (!this._hl || !visible.some((v) => v.c === this._hl.c && v.i === this._hl.i)) {\n this._hl = visible[0] ? { ...visible[0] } : null;\n }\n if (searching && this._hl) this._activeCat = this._hl.c;\n\n // Categories.\n this._catsEl.replaceChildren();\n this.categories.forEach((cat, c) => {\n const btn = _el('button', 'twm-category-picker__category');\n btn.type = 'button';\n btn.tabIndex = -1;\n btn.id = `${this._id}-cat-${c}`;\n btn.setAttribute('role', 'option');\n btn.dataset.index = String(c);\n if (cat.color) btn.style.setProperty('--twm-category-picker-color', cat.color);\n const count = searching ? (hits.get(c) || 0) : (cat.items || []).length;\n if (searching && !count) btn.classList.add('twm-category-picker__category--empty');\n btn.append(\n _el('span', 'twm-category-picker__dot'),\n _el('span', 'twm-category-picker__category-label', cat.label),\n _el('span', 'twm-category-picker__count', String(count)),\n );\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n this._column = 'categories';\n this._chooseCategory(c);\n this._input.focus();\n });\n this._catsEl.appendChild(btn);\n });\n\n // Items (or hits: each category's in a role=\"group\" named by its header).\n this._itemsEl.replaceChildren();\n this._rows = [];\n let lastCat = -1;\n let into = this._itemsEl;\n for (const v of visible) {\n const cat = this.categories[v.c];\n const item = cat.items[v.i];\n if (searching && v.c !== lastCat) {\n const header = _el('div', 'twm-category-picker__group');\n header.id = `${this._id}-group-${v.c}`;\n if (cat.color) header.style.setProperty('--twm-category-picker-color', cat.color);\n header.append(_el('span', 'twm-category-picker__dot'), _el('span', null, cat.label));\n into = _el('div', 'twm-category-picker__hits');\n into.setAttribute('role', 'group');\n into.setAttribute('aria-labelledby', header.id);\n into.appendChild(header);\n this._itemsEl.appendChild(into);\n lastCat = v.c;\n }\n const btn = _el('button', 'twm-category-picker__item');\n btn.type = 'button';\n btn.tabIndex = -1;\n btn.id = `${this._id}-item-${v.c}-${v.i}`;\n btn.setAttribute('role', 'option');\n btn.dataset.category = String(v.c);\n btn.dataset.index = String(v.i);\n if (cat.color) btn.style.setProperty('--twm-category-picker-color', cat.color);\n if (item.icon) {\n btn.appendChild(_el('span', 'material-symbols-outlined twm-category-picker__icon', item.icon));\n } else {\n btn.appendChild(_el('span', 'twm-category-picker__badge', item.badge ?? ''));\n }\n btn.appendChild(_el('span', 'twm-category-picker__item-label', item.label));\n btn.addEventListener('mouseenter', () => this._highlight(v));\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n this._column = 'items';\n this._highlight(v);\n this._input.focus();\n });\n btn.addEventListener('dblclick', (e) => {\n e.preventDefault();\n this._pick(v);\n });\n this._rows.push({ ...v, el: btn });\n into.appendChild(btn);\n }\n if (!visible.length) {\n this._itemsEl.appendChild(_el('div', 'twm-category-picker__empty',\n searching ? `Nothing matches \u201C${this._query.trim()}\u201D.` : 'Nothing here.'));\n }\n\n this._paintState();\n }\n\n /** Classes and ARIA for the active category, the highlight and the current column; the detail pane. */\n _paintState() {\n const searching = _terms(this._query).length > 0;\n [...this._catsEl.children].forEach((btn, c) => {\n const on = c === this._activeCat;\n btn.classList.toggle('twm-category-picker__category--active', on);\n btn.setAttribute('aria-selected', on ? 'true' : 'false');\n });\n for (const r of this._rows) {\n const on = !!this._hl && r.c === this._hl.c && r.i === this._hl.i;\n r.el.classList.toggle('twm-category-picker__item--highlighted', on);\n r.el.setAttribute('aria-selected', on ? 'true' : 'false');\n }\n const column = searching ? 'items' : this._column;\n this._catsEl.classList.toggle('twm-category-picker__column--current', column === 'categories');\n this._itemsEl.classList.toggle('twm-category-picker__column--current', column === 'items');\n\n const hlRow = this._rows.find((r) => this._hl && r.c === this._hl.c && r.i === this._hl.i);\n const activeCatEl = this._catsEl.children[this._activeCat];\n // The input names the option the arrow keys are on: the active\n // category while the categories column is current, else the highlight.\n const current = column === 'categories' ? activeCatEl : hlRow?.el;\n this._input.setAttribute('aria-controls', column === 'categories' ? this._catsEl.id : this._itemsEl.id);\n if (current) this._input.setAttribute('aria-activedescendant', current.id);\n else this._input.removeAttribute('aria-activedescendant');\n hlRow?.el.scrollIntoView?.({ block: 'nearest' });\n activeCatEl?.scrollIntoView?.({ block: 'nearest' });\n\n this._renderDetail();\n }\n\n _renderDetail() {\n const d = this._detailEl;\n d.replaceChildren();\n const item = this._hl ? this.categories[this._hl.c]?.items?.[this._hl.i] : null;\n if (item) {\n d.appendChild(_el('div', 'twm-category-picker__title', item.label));\n if (item.description) d.appendChild(_el('div', 'twm-category-picker__description', item.description));\n if (item.preview != null && item.preview !== '') {\n if (this.previewLabel) d.appendChild(_el('div', 'twm-category-picker__preview-label', this.previewLabel));\n d.appendChild(_el('pre', 'twm-category-picker__preview', String(item.preview)));\n }\n } else {\n d.appendChild(_el('div', 'twm-category-picker__detail-empty', 'Nothing selected.'));\n }\n const add = _el('button', 'twm-btn twm-btn--primary twm-category-picker__add', this.addLabel);\n add.type = 'button';\n add.disabled = !item;\n add.addEventListener('click', (e) => {\n e.preventDefault();\n if (this._hl) this._pick(this._hl);\n });\n d.appendChild(add);\n }\n\n // \u2500\u2500 State changes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _setQuery(q) {\n this._query = String(q || '');\n if (_terms(this._query).length) {\n // A new query highlights its first hit.\n this._hl = null;\n } else if (this._hl) {\n // Back to browsing: the highlight's category is the one shown.\n this._activeCat = this._hl.c;\n }\n this._render();\n }\n\n _highlight(v) {\n if (!v) return;\n this._hl = { c: v.c, i: v.i };\n if (_terms(this._query).length) this._activeCat = v.c;\n this._paintState();\n }\n\n /** Make category `c` the active one. Browsing: show its items. Searching: jump to its first hit. */\n _chooseCategory(c) {\n if (c < 0 || c >= this.categories.length) return;\n if (_terms(this._query).length) {\n const first = this._rows.find((r) => r.c === c);\n if (first) this._highlight(first);\n return;\n }\n this._activeCat = c;\n this._hl = (this.categories[c].items || []).length ? { c, i: 0 } : null;\n this._render();\n }\n\n _moveHighlight(dir) {\n if (!this._rows.length) return;\n let at = this._rows.findIndex((r) => this._hl && r.c === this._hl.c && r.i === this._hl.i);\n at = at < 0 ? (dir > 0 ? 0 : this._rows.length - 1)\n : (at + dir + this._rows.length) % this._rows.length;\n this._highlight(this._rows[at]);\n }\n\n _pick(v) {\n const category = this.categories[v.c];\n const item = category?.items?.[v.i];\n if (!item) return;\n const onSelect = this.onSelect;\n this.close();\n this.trigger?.focus();\n onSelect?.(item, category);\n }\n\n // \u2500\u2500 Events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _onTriggerClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.toggle();\n }\n\n _onDocClick(e) {\n if (!this.isOpen) return;\n if (this.el?.contains(e.target) || this.trigger?.contains(e.target)) return;\n this.close();\n }\n\n _onKeydown(e) {\n if (!this.isOpen) return;\n // An IME composing a character owns Enter and Escape.\n if (e.isComposing || e.keyCode === 229) return;\n if (e.key === 'Escape') {\n // Capture phase, and stopped: an open picker is the innermost\n // thing on screen, so Escape closes it and not the ManagedWindow\n // around it (ActionDropdown's rule).\n e.preventDefault();\n e.stopPropagation();\n this.close();\n this.trigger?.focus();\n return;\n }\n if (!this.el.contains(e.target)) return;\n\n const searching = _terms(this._query).length > 0;\n switch (e.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n e.preventDefault();\n const dir = e.key === 'ArrowDown' ? 1 : -1;\n if (!searching && this._column === 'categories') {\n const n = this.categories.length;\n if (n) this._chooseCategory((this._activeCat + dir + n) % n);\n } else {\n this._moveHighlight(dir);\n }\n break;\n }\n case 'ArrowRight':\n case 'ArrowLeft':\n if (searching) return; // the query's caret\n e.preventDefault();\n this._column = e.key === 'ArrowRight' ? 'items' : 'categories';\n if (this._column === 'items' && !this._hl) this._moveHighlight(1);\n this._paintState();\n break;\n case 'Enter':\n e.preventDefault();\n if (this._hl) this._pick(this._hl);\n break;\n case 'Tab': {\n // Tab stays inside, like a modal ManagedWindow's focus trap:\n // it cycles the search field and Add (when Add is enabled).\n // Leaving would strand an open popover with a dead keyboard.\n e.preventDefault();\n e.stopPropagation();\n const add = this._detailEl.querySelector('.twm-category-picker__add');\n const stops = [this._input, ...(add && !add.disabled ? [add] : [])];\n const at = stops.indexOf(e.target);\n const next = at < 0 ? 0 : (at + (e.shiftKey ? -1 : 1) + stops.length) % stops.length;\n stops[next].focus();\n break;\n }\n default:\n // A printable key typed while a row or the button has focus\n // goes to the search field.\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey\n && e.target !== this._input) {\n this._input.focus();\n }\n }\n }\n\n // \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Open it under (or above) the trigger, with an empty query and focus in the search field. */\n open() {\n if (this.isOpen || !this.el) return;\n this.isOpen = true;\n this._input.value = '';\n this._query = '';\n this._column = 'items';\n // Shown and placed first, then drawn: scrolling the highlight into\n // view does nothing in a hidden popover.\n this.el.hidden = false;\n this.position();\n this._render();\n\n this.trigger?.classList.add('twm-is-open');\n this.trigger?.setAttribute('aria-expanded', 'true');\n document.addEventListener('click', this._onDocClick, true);\n document.addEventListener('keydown', this._onKeydown, true);\n this._input.focus();\n }\n\n close() {\n if (!this.isOpen) return;\n this.isOpen = false;\n if (this.el) this.el.hidden = true;\n this.trigger?.classList.remove('twm-is-open');\n this.trigger?.setAttribute('aria-expanded', 'false');\n document.removeEventListener('click', this._onDocClick, true);\n document.removeEventListener('keydown', this._onKeydown, true);\n }\n\n /** @param {boolean} [force] */\n toggle(force) {\n const want = typeof force === 'boolean' ? force : !this.isOpen;\n if (want) this.open(); else this.close();\n }\n\n /** Place it against the trigger again (after the trigger moved). */\n position() {\n if (!this.el || !this.trigger) return;\n ActionDropdown.position(this.trigger, this.el, { align: this.align });\n // The columns scroll themselves; the popover only shrinks to fit.\n this.el.style.overflowY = 'hidden';\n }\n\n /**\n * Replace the categories. The active category and the highlight are\n * looked up again by `id`, so they are kept when they still exist,\n * wherever they moved to.\n */\n setCategories(categories) {\n const oldCat = this.categories[this._activeCat];\n const oldHlCat = this._hl ? this.categories[this._hl.c] : null;\n const oldHlItem = oldHlCat?.items?.[this._hl.i];\n this.categories = categories || [];\n const catAt = (cat) => (cat ? this.categories.findIndex((c) => c.id === cat.id) : -1);\n\n const active = catAt(oldCat);\n this._activeCat = active >= 0 ? active : 0;\n this._hl = null;\n const hc = catAt(oldHlCat);\n if (hc >= 0 && oldHlItem) {\n const hi = (this.categories[hc].items || []).findIndex((it) => it.id === oldHlItem.id);\n if (hi >= 0) this._hl = { c: hc, i: hi };\n }\n if (this.el) this._render();\n }\n\n destroy() {\n this.close();\n this.trigger?.removeEventListener('click', this._onTriggerClick);\n this.el?.remove();\n this.el = null;\n this.trigger = null;\n this.categories = [];\n this.onSelect = null;\n }\n}\n\nexport default CategoryPicker;\n", "/**\n * column_fit.js \u2014 how wide each column of a table should be.\n *\n * A pure function over measurements, so the policy can be read and tested\n * without a DOM. A table measures its columns, hands them here, and applies\n * the widths it gets back.\n *\n * \u2500\u2500 The policy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Columns are not all alike, and treating them alike is what went wrong\n * before. An id, a date, a status, a person: SHORT columns, whose values are\n * all about as wide as each other, and which are useless the moment they are\n * cut (\"2026-09-\u2026\", \"review-q\u2026\"). A summary or a title: TEXT columns, whose\n * values run as long as people write them, and which are readable cut.\n *\n * The old fit spread spare room EVENLY, so a 40px \"BUG\" chip got 90px while\n * the summary beside it was clipped in nine rows out of ten, and it shrank the\n * WIDEST column first, so a narrow tile crushed the title to 85px while every\n * short column kept its width.\n *\n * 1. Short columns get their full content width. Text columns start at a\n * readable width.\n * 2. Room to spare goes to the text columns, in proportion to what each\n * still needs, and past their content so the table fills its box. With no\n * text column it goes to the last column, so no column in the middle\n * opens a gap.\n * 3. Too little room: shrink in order of harm. Short columns first give up\n * only their rare longest values (down to `typical`, what most values\n * fit). Then text columns go down to a floor. Then short columns go down\n * to theirs, and text columns once more. What still does not fit scrolls\n * sideways rather than being crushed further.\n *\n * Within each step the widest columns give way first and the narrow ones keep\n * their width (a water level), so one long column never forces every other\n * column down with it.\n *\n * Columns the user dragged are PINNED: they keep their width and sit out every\n * step.\n */\n\nexport const COLUMN_FIT = Object.freeze({\n /** Absolute floor, and the drag-resize minimum. */\n FLOOR: 40,\n /** Sub-pixel safety against an ellipsis on content that exactly fits. */\n PAD: 2,\n /** A column whose full width reaches this is free text. */\n TEXT_AT: 240,\n /** A text column's starting share when room allows it. */\n TEXT_MIN: 200,\n /** How far a text column shrinks before short columns go below `typical`. */\n TEXT_FLOOR: 120,\n /** How far a short column shrinks before the table scrolls. */\n SHORT_FLOOR: 56,\n});\n\n/**\n * @typedef {object} ColumnMeasure\n * @property {number} natural widest cell, padding included (px)\n * @property {number} [typical] width most cells fit, e.g. the 95th percentile (px);\n * defaults to `natural`\n * @property {number} [header] the header label's width (px)\n * @property {number} [pinned] a user-dragged width, honoured exactly\n * @property {boolean} [text] force (true) or forbid (false) text treatment;\n * omitted, it is decided from the width\n */\n\n/**\n * @param {ColumnMeasure[]} columns\n * @param {number} avail the width the table has (px); 0 or less means \"not laid out\"\n * @returns {number[]} a width per column (px, possibly fractional). The sum\n * equals `avail` whenever the floors fit, and exceeds it only when they do\n * not, in which case the table should scroll.\n */\nexport function fitColumns(columns, avail) {\n const { FLOOR, PAD, TEXT_AT, TEXT_MIN, TEXT_FLOOR, SHORT_FLOOR } = COLUMN_FIT;\n const n = columns.length;\n const cols = columns.map((c) => {\n const header = Math.max(0, Number(c.header) || 0);\n const natural = Math.max(0, Number(c.natural) || 0);\n const full = Math.max(FLOOR, Math.ceil(Math.max(natural, header) + PAD));\n const typical = Math.min(full, Math.max(FLOOR, Math.ceil(Math.max(\n Number.isFinite(c.typical) ? c.typical : natural, header) + PAD)));\n const pinned = Number.isFinite(c.pinned) ? Math.max(FLOOR, Math.round(c.pinned)) : null;\n const text = pinned == null && (typeof c.text === 'boolean' ? c.text : full >= TEXT_AT);\n return { full, typical, pinned, text };\n });\n\n const text = [];\n const short = [];\n cols.forEach((c, i) => { if (c.pinned == null) (c.text ? text : short).push(i); });\n if (!(avail > 1)) return cols.map((c) => (c.pinned != null ? c.pinned : c.full));\n\n // 1. The starting point: short columns at their full content width, text\n // columns at a readable width (or their content, if shorter).\n const widths = cols.map((c) => {\n if (c.pinned != null) return c.pinned;\n return c.text ? Math.min(c.full, TEXT_MIN) : c.full;\n });\n const total = () => widths.reduce((a, b) => a + b, 0);\n let slack = avail - total();\n\n // 2. Room to spare goes to the text columns, in proportion to what each\n // still needs, then beyond their content so the table fills its box.\n // Widths are not rounded: CSS takes fractional pixels, and rounding is\n // what made the total miss the box by a pixel and a column jitter by one\n // as its tile was resized.\n if (slack >= 0) {\n slack = raise(widths, text, (i) => cols[i].full, slack);\n if (slack > 0) {\n if (text.length) text.forEach((i) => { widths[i] += slack / text.length; });\n else widths[short.length ? short[short.length - 1] : n - 1] += slack;\n }\n return widths;\n }\n\n // 3. Not enough room: shrink in order of harm until it fits.\n const steps = [\n [short, (i) => cols[i].typical],\n [text, () => TEXT_FLOOR],\n [short, (i) => Math.min(cols[i].typical, SHORT_FLOOR)],\n [text, () => FLOOR * 2],\n ];\n for (const [idxs, low] of steps) {\n const over = total() - avail;\n if (over <= 1e-6) break;\n lowerTo(widths, idxs, low, over);\n }\n return widths;\n}\n\n/**\n * Give up to `slack` px to the columns in `idxs`, each toward `target(i)`, in\n * proportion to how far each still is from it. Returns what is left.\n */\nfunction raise(widths, idxs, target, slack) {\n if (!(slack > 0)) return slack;\n const wants = idxs.map((i) => Math.max(0, target(i) - widths[i]));\n const need = wants.reduce((a, b) => a + b, 0);\n if (!(need > 0)) return slack;\n const give = Math.min(slack, need);\n idxs.forEach((i, k) => { widths[i] += give * wants[k] / need; });\n return slack - give;\n}\n\n/**\n * Take up to `over` px off the columns in `idxs`, widest first, none below\n * `low(i)`. A water level: every column above the level is cut down to it, and\n * the level is solved so the total cut is exactly `over`, or everything the\n * lows allow when that is less. Solved on real numbers: the result is exact,\n * and a wider box can never make any column narrower.\n */\nfunction lowerTo(widths, idxs, low, over) {\n const floorOf = (i) => Math.min(widths[i], Math.max(0, low(i)));\n const cand = idxs.filter((i) => widths[i] > floorOf(i));\n if (!cand.length || over <= 0) return;\n const floors = new Map(cand.map((i) => [i, floorOf(i)]));\n const capacity = cand.reduce((a, i) => a + widths[i] - floors.get(i), 0);\n if (capacity <= over) {\n for (const i of cand) widths[i] = floors.get(i);\n return;\n }\n const cutAt = (level) => cand.reduce((a, i) => a + Math.max(0, widths[i] - Math.max(floors.get(i), level)), 0);\n let lo = 0;\n let hi = Math.max(...cand.map((i) => widths[i]));\n for (let k = 0; k < 64; k++) {\n const mid = (lo + hi) / 2;\n if (cutAt(mid) > over) lo = mid; else hi = mid;\n }\n for (const i of cand) widths[i] = Math.min(widths[i], Math.max(floors.get(i), hi));\n}\n", "/**\n * Computing Status Window\n *\n * Lightweight ManagedWindow that shows a spinner (or a progress bar) and a\n * status message while a long-running computation is in progress. Returns a\n * handle with update(), setProgress(), setStep(), complete(), cancelled(),\n * close() and a `result` promise.\n *\n * Optionally shows a Cancel button when an onCancel callback is provided.\n * Only one is open at a time: opening another closes the first, which then\n * settles as cancelled (its onCancel is not called).\n */\n\nimport { ManagedWindow } from './managed_window.js';\nimport { mountJobProgress } from './job_progress.js';\n\nlet _activeWindow = null;\n\n/**\n * Show a computing status window.\n *\n * `result` settles once: `complete({ok, message})` gives `done` or `error`\n * (the window stays, with a Close button, until closed), `cancelled()` gives\n * `cancelled`, and so does closing the window while it runs (by its \u00D7,\n * Escape, `close()` or opening another). Closing never calls `onCancel`: only\n * the Cancel button does. `progress` and `steps` are fixed when the window\n * opens: `setProgress` throws if it was opened without `progress`, and\n * `setStep` if it was opened without `steps`.\n *\n * @param {Object} options\n * @param {string} [options.title='Computing...'] - Window title\n * @param {string} [options.message=''] - Status message below spinner (markup; `update` takes text)\n * @param {string} [options.icon='hourglass_top'] - Material icon name\n * @param {Function} [options.onCancel] - If provided, shows a Cancel button. Called once when clicked.\n * @param {boolean|Object} [options.progress] - A ProgressBar in place of the spinner: `true` or its options.\n * @param {Array} [options.steps] - StepProgress steps, shown above the message.\n * @returns {{ update(msg: string): void, setProgress(next: number|Object): void,\n * setStep(which: string|number, opts?: {pass?: number, passes?: number}): void,\n * complete(result: {ok: boolean, message?: string}): void, cancelled(msg?: string): void,\n * close(): void, result: Promise<{status: 'done'|'error'|'cancelled', message: string}> }}\n */\nexport function showComputingWindow({\n title = 'Computing...', message = '', icon = 'hourglass_top', onCancel,\n progress = null, steps = null,\n} = {}) {\n if (_activeWindow) {\n _activeWindow.close();\n _activeWindow = null;\n }\n\n let finished = false;\n let settle;\n const result = new Promise((resolve) => { settle = resolve; });\n\n const content = document.createElement('div');\n content.className = 'twm-computing-status';\n const spinnerEl = document.createElement('div');\n spinnerEl.className = 'twm-computing-status__spinner';\n const msgEl = document.createElement('div');\n msgEl.className = 'twm-computing-status__message';\n // The opening message is markup, as it always was; every later one is text.\n msgEl.innerHTML = message;\n content.appendChild(spinnerEl);\n const job = mountJobProgress(content, { progress, steps, spinner: spinnerEl });\n content.appendChild(msgEl);\n\n let cancelBtn = null;\n if (typeof onCancel === 'function') {\n cancelBtn = document.createElement('button');\n cancelBtn.className = 'twm-computing-status__cancel-btn';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n cancelBtn.disabled = true;\n msgEl.textContent = 'Cancelling...';\n onCancel();\n }, { once: true });\n content.appendChild(cancelBtn);\n }\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'twm-computing-status__cancel-btn twm-computing-status__close-btn';\n closeBtn.textContent = 'Close';\n closeBtn.hidden = true;\n content.appendChild(closeBtn);\n\n const finish = (status, text) => {\n finished = true;\n spinnerEl.hidden = true;\n if (cancelBtn) cancelBtn.hidden = true;\n msgEl.textContent = text;\n msgEl.classList.toggle('is-ok', status === 'done');\n msgEl.classList.toggle('is-err', status === 'error');\n msgEl.classList.toggle('is-cancelled', status === 'cancelled');\n job.finish(status);\n settle({ status, message: text });\n };\n\n const win = new ManagedWindow({\n id: 'computing-status-window',\n title,\n icon,\n content,\n minWidth: 320,\n minHeight: 140,\n defaultWidth: 380,\n defaultHeight: (onCancel ? 190 : 160) + (job.bar ? 30 : 0) + (job.steps ? 40 : 0),\n canMinimize: true,\n canMaximize: false,\n canResize: false,\n canDrag: true,\n modal: false,\n // BUG-0053. A status window opened by the program, not by the user:\n // it must not take focus from what the user is doing.\n focusOnOpen: false,\n onClose: () => {\n if (_activeWindow === win) _activeWindow = null;\n if (finished) return;\n finish('cancelled', 'Cancelled.');\n },\n });\n closeBtn.addEventListener('click', () => win.close());\n _activeWindow = win;\n win.show();\n\n return {\n result,\n update(msg) {\n if (finished) return;\n msgEl.textContent = msg;\n },\n setProgress(next) {\n if (finished) return;\n job.setProgress(next);\n },\n setStep(which, opts) {\n if (finished) return;\n job.setStep(which, opts);\n },\n complete(res) {\n if (finished) return;\n finish(res?.ok ? 'done' : 'error', res?.message || '');\n closeBtn.hidden = false;\n },\n cancelled(msg) {\n if (finished) return;\n finish('cancelled', msg || 'Cancelled.');\n closeBtn.hidden = false;\n },\n close() {\n if (_activeWindow) {\n _activeWindow.close();\n _activeWindow = null;\n }\n },\n };\n}\n", "/**\n * \u2550\u2550 THE CONVERSATION STATE MACHINE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * The lifecycle of one assistant conversation, with no view and no transport in\n * it. `mountChatShell` (`./chat_shell.js`) drives one; a chat of your own can\n * too.\n *\n * idle \u2500\u2500send\u2500\u2500\u25B6 waiting \u2500\u2500streamStart\u2500\u2500\u25B6 streaming \u2500\u2500streamComplete\u2500\u2500\u25B6 idle\n * \u2514\u2500 streamComplete \u25B6 idle \u251C\u2500 cancel \u25B6 idle\n * \u2514\u2500 cancel \u25B6 idle \u2514\u2500 error \u25B6 error\n * \u2514\u2500 error \u25B6 error\n * error \u2500\u2500send\u2500\u2500\u25B6 waiting error \u2500\u2500reset\u2500\u2500\u25B6 idle\n *\n * TRANSITIONS ARE QUEUED. `StateMachine` (`../../core/state_machine.js`) is\n * asynchronous and refuses a transition that arrives during another. Text can\n * arrive in the same tick as the request that asked for it, so every call here\n * waits for the one before it, in call order, and answers a promise of\n * `{ transitioned, reason? }`. `getState()` therefore lags a call by some\n * microtasks; `settled()` resolves when the queue is empty, and `getState()` is\n * `null` until the machine has entered `idle`. A transition the current state\n * does not have is refused, not thrown.\n *\n * OBSERVERS: `onChange({ state, conversationId, mode })` hears every state\n * entered. With an `eventBus`, the same goes out as `CHAT_BUS_EVENTS.STATE_CHANGED`\n * along with the others below.\n *\n * THE MODE is an opaque string of the caller's (`null` for none): it is kept\n * and handed back, and means nothing here.\n */\n\nimport { StateMachine } from '../../core/state_machine.js';\n\nexport const CHAT_STATES = Object.freeze({\n IDLE: 'idle',\n WAITING: 'waiting',\n STREAMING: 'streaming',\n ERROR: 'error',\n});\n\nexport const CHAT_TRANSITIONS = Object.freeze({\n SEND: 'chat:message:send',\n STREAM_START: 'chat:stream:start',\n STREAM_COMPLETE: 'chat:stream:complete',\n CANCEL: 'chat:cancel',\n ERROR: 'chat:error',\n RESET: 'chat:reset',\n});\n\nexport const CHAT_BUS_EVENTS = Object.freeze({\n STATE_CHANGED: 'chat:state:changed',\n MESSAGE_SENT: 'chat:message:sent',\n STREAM_COMPLETE: 'chat:stream:completed',\n MODE_CHANGED: 'chat:mode:changed',\n CONVERSATION_NEW: 'chat:conversation:new',\n CONVERSATION_LOADED: 'chat:conversation:loaded',\n ERROR: 'chat:error:raised',\n});\n\nexport class ChatStateMachine {\n #machine;\n #eventBus;\n #onChange;\n #queue = Promise.resolve();\n #conversationId = null;\n #mode;\n #lastError = null;\n\n /**\n * @param {object} [deps]\n * @param {object} [deps.eventBus] gets `CHAT_BUS_EVENTS`\n * @param {object} [deps.logger]\n * @param {?string} [deps.mode] the mode to start in\n * @param {Function} [deps.onChange] `({ state, conversationId, mode })` on every state entered\n */\n constructor({ eventBus = null, logger = null, mode = null, onChange = null } = {}) {\n this.#eventBus = eventBus;\n this.#onChange = onChange;\n this.#mode = mode;\n\n const entered = () => this.#entered();\n const send = {\n target: CHAT_STATES.WAITING,\n guard: (ctx) => !!ctx.payload?.message,\n action: (ctx) => this.#messageSent(ctx.payload),\n };\n const inFlight = {\n [CHAT_TRANSITIONS.STREAM_COMPLETE]: {\n target: CHAT_STATES.IDLE,\n action: (ctx) => this.#emit(CHAT_BUS_EVENTS.STREAM_COMPLETE, {\n conversationId: this.#conversationId, ...ctx.payload,\n }),\n },\n [CHAT_TRANSITIONS.CANCEL]: { target: CHAT_STATES.IDLE },\n [CHAT_TRANSITIONS.ERROR]: {\n target: CHAT_STATES.ERROR,\n action: (ctx) => this.#failed(ctx.payload),\n },\n [CHAT_TRANSITIONS.RESET]: { target: CHAT_STATES.IDLE },\n };\n\n this.#machine = new StateMachine({\n name: 'chat',\n initialState: CHAT_STATES.IDLE,\n eventBus,\n logger,\n states: {\n [CHAT_STATES.IDLE]: {\n onEnter: () => {\n this.#lastError = null;\n entered();\n },\n transitions: { [CHAT_TRANSITIONS.SEND]: send },\n },\n [CHAT_STATES.WAITING]: {\n onEnter: entered,\n transitions: {\n [CHAT_TRANSITIONS.STREAM_START]: { target: CHAT_STATES.STREAMING },\n ...inFlight,\n },\n },\n [CHAT_STATES.STREAMING]: { onEnter: entered, transitions: inFlight },\n [CHAT_STATES.ERROR]: {\n onEnter: entered,\n transitions: {\n [CHAT_TRANSITIONS.RESET]: { target: CHAT_STATES.IDLE },\n [CHAT_TRANSITIONS.SEND]: send,\n },\n },\n },\n });\n }\n\n getState() { return this.#machine.getState(); }\n\n get conversationId() { return this.#conversationId; }\n set conversationId(id) { this.#conversationId = id ?? null; }\n\n get mode() { return this.#mode; }\n get lastError() { return this.#lastError; }\n\n setMode(mode) {\n this.#mode = mode;\n this.#emit(CHAT_BUS_EVENTS.MODE_CHANGED, { mode });\n }\n\n /** Resolves when every call so far has taken effect. */\n settled() { return this.#queue; }\n\n sendMessage(message, conversationId = this.#conversationId) {\n this.#conversationId = conversationId ?? null;\n return this.#transition(CHAT_TRANSITIONS.SEND, { message });\n }\n\n streamStart() { return this.#transition(CHAT_TRANSITIONS.STREAM_START); }\n\n /** @param {object} [payload] goes out with `CHAT_BUS_EVENTS.STREAM_COMPLETE` */\n streamComplete(payload = {}) { return this.#transition(CHAT_TRANSITIONS.STREAM_COMPLETE, payload); }\n\n cancel() { return this.#transition(CHAT_TRANSITIONS.CANCEL); }\n\n error(message, detail = null) { return this.#transition(CHAT_TRANSITIONS.ERROR, { message, detail }); }\n\n reset() { return this.#transition(CHAT_TRANSITIONS.RESET); }\n\n /** Back to idle with no conversation, whatever the state. */\n newConversation() {\n this.#conversationId = null;\n return this.#enqueue(async () => {\n await this.#machine.reset(CHAT_STATES.IDLE);\n this.#emit(CHAT_BUS_EVENTS.CONVERSATION_NEW, {});\n });\n }\n\n /** Back to idle on a kept conversation, whatever the state. */\n loadConversation(conversationId) {\n this.#conversationId = conversationId ?? null;\n return this.#enqueue(async () => {\n await this.#machine.reset(CHAT_STATES.IDLE);\n this.#emit(CHAT_BUS_EVENTS.CONVERSATION_LOADED, { conversationId });\n });\n }\n\n canSend() {\n const state = this.getState();\n return state === CHAT_STATES.IDLE || state === CHAT_STATES.ERROR;\n }\n\n isProcessing() {\n const state = this.getState();\n return state === CHAT_STATES.WAITING || state === CHAT_STATES.STREAMING;\n }\n\n #transition(event, payload) {\n return this.#enqueue(() => this.#machine.transition(event, payload));\n }\n\n /** One step after the last; a step that fails rejects its own promise and not the next one's. */\n #enqueue(step) {\n const run = this.#queue.then(step);\n this.#queue = run.then(() => undefined, () => undefined);\n return run;\n }\n\n #messageSent({ message }) {\n this.#lastError = null;\n this.#emit(CHAT_BUS_EVENTS.MESSAGE_SENT, {\n conversationId: this.#conversationId, text: message, mode: this.#mode,\n });\n }\n\n #failed({ message, detail }) {\n this.#lastError = message;\n this.#emit(CHAT_BUS_EVENTS.ERROR, { conversationId: this.#conversationId, message, detail });\n }\n\n #entered() {\n const change = { state: this.getState(), conversationId: this.#conversationId, mode: this.#mode };\n this.#onChange?.(change);\n this.#emit(CHAT_BUS_EVENTS.STATE_CHANGED, change);\n }\n\n #emit(name, payload) { this.#eventBus?.emit(name, payload); }\n}\n", "/**\n * \u2550\u2550 THE CONVERSATION VIEW \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A transcript of role-tagged messages above a composer (FlexDesk STORY-0057).\n * It knows nothing about what a message says or where it came from: no\n * markdown, no model, no provider. The caller draws a message's body (or\n * leaves it as plain text) and is told when the user submits or cancels.\n *\n * const view = mountConversationView(el, {\n * render: (message, bodyEl, { streaming }) => { bodyEl.innerHTML = toHtml(message.text); },\n * onSubmit: (text) => send(text),\n * onCancel: () => stop(),\n * });\n * view.append({ role: 'user', text: 'Hello' });\n * view.beginStream({ role: 'assistant' });\n * view.appendChunk('Hi'); // re-renders ONLY the streaming message\n * view.endStream();\n *\n * MESSAGES are `{ id?, role, text, meta? }`. `id` is assigned when absent;\n * `role` becomes a modifier class (`twm-chat__msg--<role>`); `meta` is the\n * caller's and is handed back untouched. `append`, `remove`, `replaceAll` and\n * `clear` change the list; `messages()` reads it. An id already in the transcript (or\n * repeated within one `replaceAll`) is refused with a throw, and a refused\n * call changes nothing. Each message has an EXTRA SLOT\n * (`slot(id)`), an element below the body the caller fills with whatever\n * belongs to that message \u2014 tool output, buttons, a diff \u2014 and which a\n * re-render of the body never touches.\n *\n * THE RENDER CALLBACK draws one body: `render(message, bodyEl, { streaming })`.\n * The body is emptied before every call. One that throws leaves the message\n * as its plain text (`twm-chat__body--plain`) and the view carries on; the\n * error goes to `onRenderError(error, message)` when given.\n *\n * STREAMING: `beginStream(message?)` appends a message marked streaming,\n * `appendChunk(text)` adds to its text and re-renders that message's body\n * alone, `endStream()` renders it a last time, unmarked. Nothing is deferred to\n * a frame: every call has drawn by the time it returns.\n *\n * PINNED TO THE BOTTOM: the view starts out following new content. Any\n * scroll UP \u2014 even a few px from the end, and whichever frame of a smooth\n * wheel or key scroll reports it \u2014 stops the following and shows *Jump to\n * latest*, and no later chunk moves the reader back. Following resumes only\n * on a scroll down (or a move that is not up) that ends within\n * `pinThreshold` px of the end, a click on *Jump to latest*,\n * `scrollToBottom()`, `replaceAll()` / `clear()`, or a `setScrollTop(px)`\n * that lands within the threshold. Content growing below a pinned view\n * never unpins it, nor does content shrinking under it (the browser clamps\n * `scrollTop` to the new end, which is not a move up). A wheel over\n * a nested scroller (a `<pre>` in a body, say) scrolls that, not the view;\n * nor does a wheel a handler inside the transcript cancelled, a Ctrl+wheel\n * (zoom, or a trackpad pinch), or a wheel up over a transcript already at its\n * top. `scrollTop` is\n * readable and settable (`getScrollTop` / `setScrollTop`) so an embedder can\n * keep it across a remount.\n *\n * THE COMPOSER is a textarea that grows with its text up to\n * `composerMaxHeight`. Enter submits (the trimmed-empty text is ignored) and\n * clears it; Shift+Enter is left to the browser, which inserts the newline\n * (native undo, `input` events). `setBusy(true)` turns Send into Cancel: Enter\n * then submits nothing, and Esc \u2014 wherever focus is inside the view \u2014 or a\n * click on Cancel calls `onCancel`, once per busy period, however often it is\n * pressed. That Esc stops there: it never reaches a window or panel around\n * the view that would close on Escape. An Esc a handler inside the view has\n * already consumed (`preventDefault`, say an inline popup or editor in the\n * transcript closing itself) is left alone: it neither cancels nor is stopped.\n *\n * `destroy()` removes the view. Every listener sits on an element the view\n * created, so they go with it; none is on the host or the document.\n */\n\n/** How near the end of the transcript still counts as \"at the bottom\". */\nexport const CONVERSATION_PIN_WITHIN_PX = 32;\n\n/**\n * A drop in `scrollTop` that still leaves the view this close to its end is\n * the browser clamping it after the content shrank (or sub-pixel rounding),\n * not the reader scrolling up.\n */\nconst AT_END_PX = 1;\n\n/** The tallest the composer grows before it scrolls instead. */\nexport const CONVERSATION_COMPOSER_MAX_PX = 200;\n\n/**\n * @param {HTMLElement} host\n * @param {object} [opts]\n * @param {Function} [opts.render] `(message, bodyEl, { streaming })` \u2014 draws a body; plain text without it\n * @param {Function} [opts.onSubmit] `(text)` \u2014 Enter or Send\n * @param {Function} [opts.onCancel] `()` \u2014 Esc or Cancel while busy\n * @param {Function} [opts.onRenderError] `(error, message)` \u2014 a render that threw\n * @param {number} [opts.pinThreshold] px from the end that still follows new content\n * @param {number} [opts.composerMaxHeight] px the composer grows to\n * @param {string} [opts.placeholder] the composer's placeholder\n * @param {object} [opts.labels] `{ send, cancel, jump, input }` \u2014 button and field texts\n * @returns {object} the view (see the methods below)\n */\nexport function mountConversationView(host, {\n render = null, onSubmit = null, onCancel = null, onRenderError = null,\n pinThreshold = CONVERSATION_PIN_WITHIN_PX, composerMaxHeight = CONVERSATION_COMPOSER_MAX_PX,\n placeholder = '', labels = {},\n} = {}) {\n const text = {\n send: 'Send', cancel: 'Cancel', jump: 'Jump to latest', input: 'Message', ...labels,\n };\n const doc = host.ownerDocument;\n const el = (tag, cls, content) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (content !== undefined) n.textContent = content;\n return n;\n };\n const icon = (name) => {\n const i = el('span', 'material-symbols-outlined', name);\n i.setAttribute('aria-hidden', 'true');\n return i;\n };\n\n /** id \u2192 { message, row, body, extra } in transcript order. */\n const entries = new Map();\n let nextId = 1;\n let streamId = null;\n let pinned = true;\n let lastScrollTop = 0;\n let busy = false;\n let cancelled = false;\n let destroyed = false;\n\n // \u2500\u2500 the frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-chat');\n const viewport = el('div', 'twm-chat__viewport');\n const log = el('div', 'twm-chat__log');\n log.setAttribute('role', 'log');\n log.setAttribute('aria-live', 'polite');\n const jump = el('button', 'twm-chat__jump');\n jump.type = 'button';\n jump.append(icon('arrow_downward'), doc.createTextNode(` ${text.jump}`));\n jump.hidden = true;\n viewport.append(log, jump);\n\n const composer = el('div', 'twm-chat__composer');\n const input = el('textarea', 'twm-chat__input');\n input.rows = 1;\n input.placeholder = placeholder;\n input.setAttribute('aria-label', text.input);\n const send = el('button', 'twm-chat__send');\n send.type = 'button';\n composer.append(input, send);\n root.append(viewport, composer);\n host.append(root);\n\n // \u2500\u2500 scrolling \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const distanceFromEnd = () => log.scrollHeight - log.scrollTop - log.clientHeight;\n const toBottom = () => {\n log.scrollTop = log.scrollHeight;\n lastScrollTop = log.scrollTop;\n };\n const setPinned = (value) => {\n pinned = value;\n jump.hidden = pinned;\n };\n /**\n * Reads the position the reader left: any move up stops following, however\n * near the end it stops (a smooth wheel or key scroll reports its first\n * frame only a few px up). Returns whether the move may follow again: it\n * was not up and ends within `pinThreshold` of the end. Shared by the\n * `scroll` event and by settle(), because a scrollbar drag, a key or a\n * touch moves `scrollTop` before its `scroll` event is dispatched, and a\n * change arriving in between must not snap the reader back.\n */\n function noticeMove() {\n const top = log.scrollTop;\n const distance = distanceFromEnd();\n const movedUp = top < lastScrollTop && distance > AT_END_PX;\n lastScrollTop = top;\n if (movedUp && pinned) setPinned(false);\n return !movedUp && distance <= pinThreshold;\n }\n /** After every change to the transcript: follow it, or leave the reader where they are. */\n const settle = () => {\n noticeMove();\n if (pinned) toBottom();\n };\n\n function onScroll() { if (noticeMove() && !pinned) setPinned(true); }\n /**\n * Whether a wheel up over `target` is kept by something nested inside the\n * transcript \u2014 a scrollable block in a body or an extra slot that is not\n * at its own top, or one at its top whose `overscroll-behavior` keeps the\n * scroll from chaining out \u2014 rather than moving the transcript itself.\n */\n function innerTakesWheelUp(target) {\n const view = doc.defaultView;\n for (let n = target; n && n !== log; n = n.parentElement) {\n if (n.nodeType !== 1 || n.scrollHeight <= n.clientHeight) continue;\n const style = view?.getComputedStyle(n);\n const overflow = style?.overflowY;\n if (overflow !== 'auto' && overflow !== 'scroll' && overflow !== 'overlay') continue;\n if (n.scrollTop > 0) return true;\n const chain = style.getPropertyValue('overscroll-behavior-y');\n if (chain === 'contain' || chain === 'none') return true;\n }\n return false;\n }\n /**\n * A wheel up that will move the transcript stops following at once, before\n * the scroll it causes is reported. One that a nested scroller keeps, or\n * one a handler inside the transcript cancelled (a zoomable chart in a\n * slot, say), leaves the transcript where it is, so it changes nothing.\n * Nor does a Ctrl+wheel (page zoom; a trackpad pinch arrives as one), or\n * a wheel up over a transcript already at its top, which cannot go up.\n */\n function onWheel(e) {\n if (e.deltaY < 0 && pinned && !e.ctrlKey && !e.defaultPrevented && log.scrollTop > 0\n && !innerTakesWheelUp(e.target)) setPinned(false);\n }\n function onJump() { setPinned(true); toBottom(); }\n log.addEventListener('scroll', onScroll);\n log.addEventListener('wheel', onWheel, { passive: true });\n jump.addEventListener('click', onJump);\n\n // \u2500\u2500 messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 fresh id, never one `taken` holds. */\n const newId = (taken = (id) => entries.has(id)) => {\n let id;\n do id = `m${nextId++}`; while (taken(id));\n return id;\n };\n const duplicate = (id) => new Error(`conversation view: duplicate message id \"${id}\"`);\n const roleClass = (role) => String(role ?? '').toLowerCase().replace(/[^a-z0-9-]+/g, '-') || 'none';\n const snapshot = (message) => ({ ...message });\n\n function drawBody(entry, streaming = entry.message.id === streamId) {\n const { message, body } = entry;\n body.replaceChildren();\n body.classList.remove('twm-chat__body--plain');\n if (render) {\n try {\n render(snapshot(message), body, { streaming });\n return;\n } catch (error) {\n body.replaceChildren();\n if (onRenderError) {\n try { onRenderError(error, snapshot(message)); } catch { /* the view keeps working */ }\n }\n }\n }\n body.classList.add('twm-chat__body--plain');\n body.textContent = message.text;\n }\n\n /**\n * One entry, drawn, and added to `into` (the transcript unless a\n * replaceAll is building its own). Throws on an id `into` already holds,\n * before anything is changed.\n */\n function build(spec, { into = entries, taken, streaming = false } = {}) {\n const message = {\n ...spec,\n id: spec?.id ?? newId(taken ?? ((id) => into.has(id))),\n role: spec?.role ?? 'assistant',\n text: String(spec?.text ?? ''),\n };\n if (into.has(message.id)) throw duplicate(message.id);\n const row = el('div', `twm-chat__msg twm-chat__msg--${roleClass(message.role)}`);\n if (streaming) row.classList.add('twm-chat__msg--streaming');\n const body = el('div', 'twm-chat__body');\n const extra = el('div', 'twm-chat__extra');\n row.append(body, extra);\n const entry = { message, row, body, extra };\n into.set(message.id, entry);\n drawBody(entry, streaming);\n return entry;\n }\n\n function append(message) {\n const entry = build(message);\n log.append(entry.row);\n settle();\n return entry.message.id;\n }\n\n /**\n * Takes one message out and leaves every other one, with its slot, as it is.\n * An open stream on that message is over. False for an unknown id.\n */\n function remove(id) {\n const entry = entries.get(id);\n if (!entry) return false;\n if (streamId === id) streamId = null;\n entries.delete(id);\n entry.row.remove();\n settle();\n return true;\n }\n\n /** All or nothing: a repeated id throws before the transcript is touched. No list (undefined or null) empties it. */\n function replaceAll(messages) {\n const list = [...(messages ?? [])];\n const given = new Set();\n for (const m of list) {\n if (m?.id == null) continue;\n if (given.has(m.id)) throw duplicate(m.id);\n given.add(m.id);\n }\n const next = new Map();\n const taken = (id) => given.has(id) || next.has(id);\n const frag = doc.createDocumentFragment();\n for (const m of list) frag.append(build(m, { into: next, taken }).row);\n streamId = null;\n entries.clear();\n for (const [id, entry] of next) entries.set(id, entry);\n log.replaceChildren(frag);\n setPinned(true);\n toBottom();\n }\n\n function clear() { replaceAll([]); }\n\n // \u2500\u2500 streaming \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Refused (a throw, nothing changed, an open stream left open) on an id\n * already present. No message (undefined or null) streams an empty\n * assistant message, as `append` treats them.\n */\n function beginStream(message) {\n if (message?.id != null && entries.has(message.id)) throw duplicate(message.id);\n if (streamId !== null) endStream();\n const entry = build({ role: 'assistant', text: '', ...(message ?? {}) }, { streaming: true });\n streamId = entry.message.id;\n log.append(entry.row);\n settle();\n return streamId;\n }\n\n function appendChunk(chunk) {\n const entry = streamId !== null ? entries.get(streamId) : null;\n if (!entry) return;\n entry.message.text += String(chunk ?? '');\n drawBody(entry);\n settle();\n }\n\n function endStream() {\n const entry = streamId !== null ? entries.get(streamId) : null;\n streamId = null;\n if (!entry) return null;\n entry.row.classList.remove('twm-chat__msg--streaming');\n drawBody(entry);\n settle();\n return entry.message.id;\n }\n\n // \u2500\u2500 the composer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function grow() {\n input.style.height = 'auto';\n input.style.height = `${Math.min(input.scrollHeight, composerMaxHeight)}px`;\n input.style.overflowY = input.scrollHeight > composerMaxHeight ? 'auto' : 'hidden';\n }\n\n function drawSend() {\n send.replaceChildren(icon(busy ? 'stop' : 'send'));\n send.setAttribute('aria-label', busy ? text.cancel : text.send);\n send.title = busy ? text.cancel : text.send;\n send.classList.toggle('twm-chat__send--cancel', busy);\n root.classList.toggle('twm-chat--busy', busy);\n }\n\n function submit() {\n if (busy) return;\n const value = input.value;\n if (!value.trim()) return;\n input.value = '';\n grow();\n onSubmit?.(value);\n }\n\n function cancel() {\n if (!busy || cancelled) return;\n cancelled = true;\n onCancel?.();\n }\n\n /** Enter submits; Shift+Enter (and Ctrl/Meta/Alt+Enter) is the browser's to handle. */\n function onInputKey(e) {\n if (e.isComposing || e.key !== 'Enter') return;\n if (e.shiftKey || e.ctrlKey || e.metaKey || e.altKey) return;\n e.preventDefault();\n submit();\n }\n /**\n * Esc while busy cancels wherever focus is inside the view, and it is the\n * view's alone: it goes no further, so a window or panel holding the view\n * that closes on Escape stays open \u2014 on the cancelling Esc and on any\n * repeat in the same busy period. An Esc a handler inside the view\n * already consumed (defaultPrevented) is that handler's: it neither\n * cancels nor is stopped.\n */\n function onRootKey(e) {\n if (e.isComposing || e.key !== 'Escape' || !busy || e.defaultPrevented) return;\n e.preventDefault();\n e.stopPropagation();\n cancel();\n }\n input.addEventListener('keydown', onInputKey);\n input.addEventListener('input', grow);\n root.addEventListener('keydown', onRootKey);\n send.addEventListener('click', () => (busy ? cancel() : submit()));\n drawSend();\n\n return {\n root,\n append,\n remove,\n replaceAll,\n clear,\n beginStream,\n appendChunk,\n endStream,\n /** A copy of every message, in order. */\n messages: () => [...entries.values()].map((e) => snapshot(e.message)),\n /** The extra slot below a message's body, or null for an unknown id. */\n slot: (id) => entries.get(id)?.extra ?? null,\n /** The id of the message being streamed, or null. */\n streamingId: () => streamId,\n isPinned: () => pinned,\n getScrollTop: () => log.scrollTop,\n /** Scrolls the transcript; pinned again only when that lands at the end. */\n setScrollTop(px) {\n log.scrollTop = px;\n lastScrollTop = log.scrollTop;\n setPinned(distanceFromEnd() <= pinThreshold);\n },\n scrollToBottom: onJump,\n /** `true` turns Send into Cancel; every busy period may cancel once. */\n setBusy(value) {\n if (busy === !!value) return;\n busy = !!value;\n cancelled = false;\n drawSend();\n },\n isBusy: () => busy,\n getText: () => input.value,\n setText(value) { input.value = String(value ?? ''); grow(); },\n focus: () => input.focus(),\n destroy() {\n if (destroyed) return;\n destroyed = true;\n streamId = null;\n busy = false;\n cancelled = false;\n entries.clear();\n root.remove();\n },\n };\n}\n", "/**\n * \u2550\u2550 THE ASSISTANT CHAT SHELL \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A whole assistant chat over the conversation view: conversation tabs, an\n * optional mode toggle, a model picker, a reply that streams (typing dots, tool\n * calls, stop), Markdown bodies, time and copy on every message, and a slot on\n * each assistant message for controls of the caller's. It knows no provider and\n * nothing of what a reply is about. The caller passes a transport and reads\n * back snapshots to keep.\n *\n * const chat = mountChatShell(el, {\n * transport: {\n * send(request, emit) { backend.ask(request, (e) => emit(toChatEvent(e))); },\n * cancel(request) { backend.stop(); },\n * },\n * modes: [{ id: 'ask', label: 'Ask' }, { id: 'act', label: 'Act' }],\n * models: { items: [{ id: 'a', label: 'Large' }], activeId: 'a' },\n * onModelSelect: (item) => chat.setModels({ activeId: item.id }),\n * renderControls: (el, message) => { ... },\n * conversations: saved,\n * onChange: (snapshot) => save(snapshot),\n * });\n *\n * THE TRANSPORT is `{ send(request, emit), cancel?(request) }`. A request is\n * `{ text, tabId, conversationId, mode, model }`. `emit` takes one event at a\n * time (`CHAT_TRANSPORT_EVENTS`):\n *\n * { type: 'text-delta', text }\n * { type: 'tool-use', id?, name, label?, status? } running | done | error\n * { type: 'message-end', text?, conversationId?, meta? }\n * { type: 'error', message }\n *\n * `message-end` and `error` finish the turn. Every `emit` belongs to its turn:\n * what it is handed once that turn has finished or been cancelled is dropped.\n * A `send` that throws, or answers a promise that rejects, is an `error` event.\n * A `tool-use` with the id of one already shown updates it.\n *\n * A backend whose frames carry no run id can only hand them to the latest\n * `emit`, so runs must not overlap: `cancel` answers a promise that settles when\n * the cancelled run is really over, and the next turn's `send` waits for it. That\n * turn shows at once, and until then the old run's frames still reach the dead\n * `emit`. Stopping a turn whose `send` is still waiting calls no `transport.cancel`.\n *\n * A TURN: the user's message goes in, then a streamed reply that shows the\n * typing dots while it is empty. Tool calls are listed under the body. The turn\n * ends in one of three ways, and a reply left with no text, no tool call and no\n * `meta` is taken out in each:\n * - `message-end`: `text` fills the reply only if nothing was streamed; `meta`\n * is merged into the message's.\n * - Stop (Cancel, Esc, or `cancel()`): what arrived stays, running tools become\n * `stopped`, `transport.cancel` is called once `send` has been.\n * - `error`: as Stop, without `transport.cancel`, and an error message follows.\n * While it is the last message it carries Retry, which sends the user message\n * before it again.\n *\n * CONVERSATIONS: the shell owns the tabs. While a turn runs the tab in front\n * cannot be left, closed or cleared; other tabs can still be closed, and the\n * last one never can. `snapshot()` is `{ activeId, tabs: [{ id, title,\n * conversationId, messages }] }`, plain data to keep, and `conversations` takes\n * one back. A message is `{ id, role, text, at?, tools?, meta? }`; `meta` is\n * yours and is handed back untouched. A reply still empty is not in a snapshot.\n *\n * CONTROLS: `renderControls(el, message, chat)` fills an emptied element below an\n * assistant message's body once the reply has finished, and again when the\n * message comes back from a tab switch or `refreshControls(id)`/`updateMeta(id,\n * patch)`. Everything it needs to survive goes in `message.meta`.\n *\n * THE MODEL PICKER is controlled: choosing an item calls `onModelSelect(item)`\n * (an item with an `action` calls `onModelAction(action, item)`), and the picker\n * changes when you call `setModels`, which takes any of `{ items, activeId, label,\n * status }`. With no items and no label there is no button; with no modes either\n * there is no bar.\n *\n * Nothing is stored in the DOM. `destroy()` cancels a running turn and removes\n * everything, the picker's menu on `document.body` included.\n */\n\nimport { ActionDropdown } from './action_dropdown.js';\nimport { CHAT_STATES, ChatStateMachine } from './chat_state_machine.js';\nimport { showConfirmDialog } from './confirm_dialog.js';\nimport { mountConversationView } from './conversation_view.js';\nimport { createTabs } from './tabs.js';\nimport { renderMarkdown } from '../utils/markdown.js';\n\nexport const CHAT_TRANSPORT_EVENTS = Object.freeze({\n TEXT_DELTA: 'text-delta',\n TOOL_USE: 'tool-use',\n MESSAGE_END: 'message-end',\n ERROR: 'error',\n});\n\n/** Every text the shell shows; pass `labels` to replace any of them. */\nexport const CHAT_SHELL_LABELS = Object.freeze({\n send: 'Send',\n cancel: 'Cancel',\n jump: 'Jump to latest',\n input: 'Message',\n conversations: 'Conversations',\n newConversation: 'New chat',\n add: 'New conversation',\n clear: 'Clear conversation',\n clearTitle: 'Clear conversation',\n clearMessage: 'Clear this conversation? This cannot be undone.',\n clearOk: 'Clear',\n clearCancel: 'Cancel',\n rename: 'Conversation name',\n modes: 'Mode',\n selectModel: 'Select model...',\n typing: 'The assistant is replying',\n copy: 'Copy message',\n retry: 'Retry',\n retryTitle: 'Send the message again',\n unknownError: 'Unknown error',\n});\n\nconst TITLE_CHARS = 30;\nconst COPIED_MS = 1500;\nconst TOOL_ICONS = Object.freeze({ running: 'build', done: 'check', error: 'error', stopped: 'block' });\n\nconst defaultTitle = (text) => (text.length > TITLE_CHARS ? `${text.slice(0, TITLE_CHARS)}...` : text);\n\nfunction defaultTime(at) {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return '';\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n}\n\n/**\n * @param {HTMLElement} host\n * @param {object} opts\n * @param {object} opts.transport `{ send(request, emit), cancel?(request) }`\n * @param {Function} [opts.renderControls] `(el, message, chat)` \u2014 an assistant message's controls\n * @param {object} [opts.markdown] options for `renderMarkdown`\n * @param {Function} [opts.onChange] `(snapshot)` \u2014 something worth keeping changed\n * @param {Function} [opts.onConversationChange] `(conversation, reason)` \u2014 another conversation is in front; reason is `new`, `switch`, `close` or `reset`\n * @param {Array} [opts.modes] `[{ id, label, title? }]`; none, no toggle\n * @param {string} [opts.mode] the mode to start in; the first without it\n * @param {Function} [opts.onModeChange] `(id)` \u2014 the user chose a mode\n * @param {object} [opts.models] `{ items, activeId, label, status }`, as `setModels`\n * @param {Function} [opts.onModelSelect] `(item)`\n * @param {Function} [opts.onModelAction] `(action, item)`\n * @param {object} [opts.conversations] a `snapshot()` to restore\n * @param {Function} [opts.titleFrom] `(text)` \u2014 a new conversation's title, from its first message\n * @param {Function} [opts.formatTime] `(at, message)` \u2014 a message's time; `''` shows none\n * @param {string} [opts.placeholder] the composer's placeholder\n * @param {object} [opts.welcome] `{ icon?, text }`, shown while the transcript is empty\n * @param {object} [opts.labels] over `CHAT_SHELL_LABELS`\n * @param {object} [opts.eventBus] gets `CHAT_BUS_EVENTS`\n * @param {object} [opts.logger]\n * @returns {object} the chat (see the methods below)\n */\nexport function mountChatShell(host, {\n transport, renderControls = null, markdown = {}, onChange = null, onConversationChange = null,\n modes = [], mode = null, onModeChange = null, models = null, onModelSelect = null, onModelAction = null,\n conversations = null, titleFrom = defaultTitle, formatTime = defaultTime, placeholder = '', welcome = null,\n labels = {}, eventBus = null, logger = null,\n} = {}) {\n if (typeof transport?.send !== 'function') {\n throw new TypeError('mountChatShell: a transport with send(request, emit) is required');\n }\n const text = { ...CHAT_SHELL_LABELS, ...labels };\n const doc = host.ownerDocument;\n const el = (tag, cls, content) => {\n const n = doc.createElement(tag);\n if (cls) n.className = cls;\n if (content !== undefined) n.textContent = content;\n return n;\n };\n const icon = (name, cls = '') => {\n const i = el('span', `material-symbols-outlined ${cls}`.trim(), name);\n i.setAttribute('aria-hidden', 'true');\n return i;\n };\n const button = (cls, title) => {\n const b = el('button', cls);\n b.type = 'button';\n b.title = title;\n b.setAttribute('aria-label', title);\n return b;\n };\n /** A callback of the caller's: one that throws is logged, and the chat carries on. */\n const safely = (fn, ...args) => {\n try { return fn?.(...args); } catch (error) {\n logger?.error?.('chat-shell', 'A callback threw', { error });\n return undefined;\n }\n };\n\n let destroyed = false;\n /** The exchange in flight: `{ token, replyId, request, started, sent }`, or null. */\n let turn = null;\n /** Settles when the run `transport.cancel` stopped is over; null when none is ending. */\n let runEnding = null;\n /** id \u2192 { at, tools, meta, toolsEl, controlsEl, footerEl }, for the messages on show. */\n const extras = new Map();\n const copyTimers = new Set();\n\n const modeIds = modes.map((m) => m.id);\n const machine = new ChatStateMachine({\n eventBus,\n logger,\n mode: modeIds.includes(mode) ? mode : (modeIds[0] ?? null),\n onChange: ({ state }) => { if (!destroyed) showState(state); },\n });\n\n // \u2500\u2500 the frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const root = el('div', 'twm-chat-shell');\n const tabBar = el('div', 'twm-chat-shell__tab-bar');\n const tabsHost = el('div', 'twm-chat-shell__tabs');\n const addBtn = button('twm-chat-shell__tab-btn', text.add);\n addBtn.append(icon('add'));\n const clearBtn = button('twm-chat-shell__tab-btn twm-chat-shell__tab-btn--clear', text.clear);\n clearBtn.append(icon('delete_sweep'));\n tabBar.append(tabsHost, addBtn, clearBtn);\n const conversationHost = el('div', 'twm-chat-shell__conversation');\n const bar = el('div', 'twm-chat-shell__bar');\n root.append(tabBar, conversationHost, bar);\n host.append(root);\n\n const view = mountConversationView(conversationHost, {\n render: drawBody,\n onSubmit: (value) => send(value),\n onCancel: () => cancel(),\n onRenderError: (error, message) => logger?.error?.('chat-shell', 'Could not draw a message', { error, message }),\n placeholder,\n labels: { send: text.send, cancel: text.cancel, jump: text.jump, input: text.input },\n });\n\n const welcomeEl = welcome ? el('div', 'twm-chat-shell__welcome') : null;\n if (welcomeEl) {\n if (welcome.icon) welcomeEl.append(icon(welcome.icon, 'twm-chat-shell__welcome-icon'));\n welcomeEl.append(el('p', 'twm-chat-shell__welcome-text', welcome.text ?? ''));\n view.root.querySelector('.twm-chat__viewport').prepend(welcomeEl);\n }\n const syncWelcome = () => { if (welcomeEl) welcomeEl.hidden = view.messages().length > 0; };\n\n function showState(state) {\n const busy = state === CHAT_STATES.WAITING || state === CHAT_STATES.STREAMING;\n view.setBusy(busy);\n addBtn.disabled = busy;\n clearBtn.disabled = busy;\n }\n\n // \u2500\u2500 bodies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** An assistant's body is Markdown, with the typing dots while it is empty and streaming; any other is text. */\n function drawBody(message, body, { streaming }) {\n if (message.role !== 'assistant') {\n body.textContent = message.text;\n return;\n }\n if (streaming && !message.text) {\n const dots = el('span', 'twm-chat-shell__typing');\n dots.setAttribute('role', 'img');\n dots.setAttribute('aria-label', text.typing);\n dots.append(el('span'), el('span'), el('span'));\n body.append(dots);\n return;\n }\n body.innerHTML = renderMarkdown(message.text, markdown);\n }\n\n // \u2500\u2500 what sits below a body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const viewMessage = (id) => view.messages().find((m) => m.id === id) ?? null;\n\n /** A message as it is kept and as callers see it. */\n function kept({ id, role, text: body }) {\n const { at, tools, meta } = extras.get(id) ?? {};\n const message = { id, role, text: body };\n if (at) message.at = at;\n if (tools?.length) message.tools = tools.map((t) => ({ ...t }));\n if (meta !== undefined) message.meta = meta;\n return message;\n }\n\n /** The messages worth showing a caller: a reply with nothing in it yet is not one. */\n function keptMessages() {\n const streaming = view.streamingId();\n return view.messages()\n .filter((m) => m.id !== streaming || m.text || extras.get(m.id)?.tools.length)\n .map(kept);\n }\n\n /** Puts a message's three blocks in its slot and remembers what it carries. */\n function register(id, { at, tools = [], meta }) {\n const entry = {\n at,\n tools,\n meta,\n toolsEl: el('div', 'twm-chat-shell__tools'),\n controlsEl: el('div', 'twm-chat-shell__controls'),\n footerEl: el('div', 'twm-chat-shell__footer'),\n };\n extras.set(id, entry);\n view.slot(id).append(entry.toolsEl, entry.controlsEl, entry.footerEl);\n return entry;\n }\n\n function drawTools(id) {\n const entry = extras.get(id);\n entry.toolsEl.replaceChildren(...entry.tools.map((tool) => {\n const row = el('div', `twm-chat-shell__tool twm-chat-shell__tool--${tool.status}`);\n row.append(\n icon(TOOL_ICONS[tool.status], 'twm-chat-shell__tool-icon'),\n el('span', 'twm-chat-shell__tool-label', tool.label ?? tool.name),\n );\n return row;\n }));\n }\n\n function drawControls(id) {\n const message = viewMessage(id);\n const entry = extras.get(id);\n if (!renderControls || !message || !entry) return;\n if (message.role !== 'assistant' || id === view.streamingId()) return;\n entry.controlsEl.replaceChildren();\n safely(renderControls, entry.controlsEl, kept(message), chat);\n }\n\n function copyButton(id) {\n const copy = button('twm-chat-shell__copy', text.copy);\n const glyph = icon('content_copy');\n copy.append(glyph);\n copy.addEventListener('click', () => {\n Promise.resolve()\n .then(() => doc.defaultView.navigator.clipboard.writeText(viewMessage(id)?.text ?? ''))\n .then(() => {\n copy.classList.add('twm-chat-shell__copy--done');\n glyph.textContent = 'check';\n const timer = setTimeout(() => {\n copyTimers.delete(timer);\n copy.classList.remove('twm-chat-shell__copy--done');\n glyph.textContent = 'content_copy';\n }, COPIED_MS);\n copyTimers.add(timer);\n })\n .catch((error) => logger?.warn?.('chat-shell', 'Could not copy a message', { error }));\n });\n return copy;\n }\n\n /** The user message a failed request sent, while that failure is the last message. */\n function retryable(id, list) {\n const last = list.at(-1);\n if (last?.id !== id || last.role !== 'error') return null;\n return list.slice(0, -1).reverse().find((m) => m.role === 'user') ?? null;\n }\n\n function drawFooter(id, list = view.messages()) {\n const entry = extras.get(id);\n entry.footerEl.replaceChildren();\n if (id === view.streamingId()) return;\n const user = retryable(id, list);\n if (user) {\n const retry = el('button', 'twm-chat-shell__retry');\n retry.type = 'button';\n retry.title = text.retryTitle;\n retry.append(icon('refresh'), doc.createTextNode(text.retry));\n retry.addEventListener('click', () => send(user.text));\n entry.footerEl.append(retry);\n }\n const message = list.find((m) => m.id === id);\n const time = entry.at ? safely(formatTime, entry.at, kept(message)) : '';\n if (time) entry.footerEl.append(el('span', 'twm-chat-shell__time', time));\n entry.footerEl.append(copyButton(id));\n }\n\n /** The slots grew too, and the view only follows changes of its own. */\n const follow = () => { if (view.isPinned()) view.scrollToBottom(); };\n\n /** A message just took the last place: the failure before it loses its Retry. */\n function redrawFailures() {\n const list = view.messages();\n for (const { id, role } of list) if (role === 'error') drawFooter(id, list);\n }\n\n function appendMessage(role, body) {\n const id = view.append({ role, text: body });\n register(id, { at: new Date().toISOString() });\n redrawFailures();\n drawFooter(id);\n follow();\n return id;\n }\n\n // \u2500\u2500 conversations \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const newTab = (id) => ({\n id, title: text.newConversation, conversationId: null, messages: [], scrollTop: null,\n });\n const tabs = [];\n let activeId = null;\n let nextTab = 1;\n const tabOf = (id) => tabs.find((t) => t.id === String(id)) ?? null;\n const activeTab = () => tabOf(activeId);\n function freshTab() {\n let id;\n do id = `chat-${nextTab++}`; while (tabOf(id));\n const tab = newTab(id);\n tabs.push(tab);\n return tab;\n }\n\n /** Kept data back into a message list: a tool cannot still be running after a restart. */\n function restored(messages) {\n return (messages ?? [])\n .filter((m) => m && typeof m.role === 'string')\n .map((m) => {\n const tools = m.tools?.map((t) => (t.status === 'running' ? { ...t, status: 'stopped' } : { ...t }));\n return tools ? { ...m, tools } : { ...m };\n });\n }\n\n const strip = createTabs(tabsHost, {\n items: [],\n compact: true,\n label: text.conversations,\n onSelect: (id) => {\n if (id == null || id === activeId) return;\n switchTo(id);\n // A switch refused leaves the conversation in front where it was.\n if (strip.active() !== activeId) strip.update(tabItems(), activeId);\n },\n onClose: (id) => close(id),\n });\n function tabItems() {\n const closable = tabs.length > 1;\n return tabs.map(({ id, title }) => ({ id, label: title, title, closable }));\n }\n const drawTabs = () => strip.update(tabItems(), activeId);\n\n /** Rename over the tab (a tab is a button, whose content cannot be edited). Enter or leaving commits; Escape does not. */\n function beginRename(id, tabEl) {\n if (tabBar.querySelector('.twm-chat-shell__rename')) return;\n const original = tabOf(id)?.title ?? '';\n const barRect = tabBar.getBoundingClientRect();\n const tabRect = tabEl.getBoundingClientRect();\n const input = el('input', 'twm-chat-shell__rename');\n input.type = 'text';\n input.value = original;\n input.spellcheck = false;\n input.setAttribute('aria-label', text.rename);\n input.style.left = `${Math.max(0, tabRect.left - barRect.left)}px`;\n input.style.width = `${Math.max(tabRect.width, 120)}px`;\n tabBar.append(input);\n input.focus();\n input.select();\n let done = false;\n const finish = (commit) => {\n if (done) return;\n done = true;\n input.remove();\n const name = input.value.trim();\n if (commit && name && name !== original) rename(id, name);\n };\n input.addEventListener('keydown', (e) => {\n if (e.key !== 'Enter' && e.key !== 'Escape') return;\n e.preventDefault();\n e.stopPropagation();\n finish(e.key === 'Enter');\n });\n input.addEventListener('blur', () => finish(true));\n }\n const renameTarget = (e) => {\n const tab = e.target.closest?.('.twm-tabs__tab');\n if (tab) beginRename(tab.dataset.tabId, tab);\n };\n strip.root.addEventListener('dblclick', renameTarget);\n strip.root.addEventListener('keydown', (e) => { if (e.key === 'F2') renameTarget(e); });\n\n /** The live transcript back into its tab. */\n function stash() {\n const tab = activeTab();\n tab.messages = keptMessages();\n tab.scrollTop = view.getScrollTop();\n }\n\n function showTab(tab) {\n const messages = restored(tab.messages);\n extras.clear();\n view.replaceAll(messages.map(({ id, role, text: body }) => ({ id, role, text: body })));\n const list = view.messages();\n list.forEach(({ id }, i) => {\n const { at, tools, meta } = messages[i];\n register(id, { at, tools: tools ?? [], meta });\n drawTools(id);\n drawControls(id);\n drawFooter(id, list);\n });\n if (tab.scrollTop !== null) view.setScrollTop(tab.scrollTop);\n else view.scrollToBottom();\n syncWelcome();\n }\n\n function snapshot() {\n stash();\n return {\n activeId,\n tabs: tabs.map(({ id, title, conversationId, messages }) => ({\n id, title, conversationId, messages: messages.map((m) => ({ ...m })),\n })),\n };\n }\n const changed = () => { if (onChange) safely(onChange, snapshot()); };\n\n function bringToFront(tab, reason) {\n activeId = tab.id;\n if (tab.conversationId) machine.loadConversation(tab.conversationId);\n else machine.newConversation();\n showTab(tab);\n drawTabs();\n const { id, title, conversationId } = tab;\n safely(onConversationChange, { id, title, conversationId, messages: restored(tab.messages) }, reason);\n changed();\n }\n\n function newConversation() {\n if (turn) return null;\n stash();\n const tab = freshTab();\n bringToFront(tab, 'new');\n return tab.id;\n }\n\n function switchTo(id) {\n const tab = tabOf(id);\n if (turn || !tab || tab.id === activeId) return false;\n stash();\n bringToFront(tab, 'switch');\n return true;\n }\n\n function close(id) {\n const tab = tabOf(id);\n if (!tab || tabs.length <= 1 || (turn && tab.id === activeId)) return false;\n const wasActive = tab.id === activeId;\n tabs.splice(tabs.indexOf(tab), 1);\n if (wasActive) {\n bringToFront(tabs[0], 'close');\n } else {\n drawTabs();\n changed();\n }\n return true;\n }\n\n function rename(id, title) {\n const tab = tabOf(id);\n const name = String(title ?? '').trim();\n if (!tab || !name) return false;\n tab.title = name;\n drawTabs();\n changed();\n return true;\n }\n\n /** Empties the conversation in front and forgets its title and id. */\n function reset() {\n if (turn) return false;\n const tab = activeTab();\n Object.assign(tab, { title: text.newConversation, conversationId: null, messages: [], scrollTop: null });\n bringToFront(tab, 'reset');\n return true;\n }\n\n addBtn.addEventListener('click', () => newConversation());\n clearBtn.addEventListener('click', async () => {\n if (view.messages().length > 0) {\n const confirmed = await showConfirmDialog({\n title: text.clearTitle,\n message: text.clearMessage,\n icon: 'delete_sweep',\n okLabel: text.clearOk,\n cancelLabel: text.clearCancel,\n okVariant: 'danger',\n });\n if (!confirmed || destroyed) return;\n }\n reset();\n });\n\n // \u2500\u2500 the turn \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function send(value) {\n const message = String(value ?? '').trim();\n if (!message || turn) return false;\n const tab = activeTab();\n appendMessage('user', message);\n if (tab.title === text.newConversation) {\n const title = safely(titleFrom, message);\n if (title) {\n tab.title = String(title);\n drawTabs();\n }\n }\n const replyId = view.beginStream({ role: 'assistant' });\n register(replyId, { at: new Date().toISOString() });\n redrawFailures();\n syncWelcome();\n const token = {};\n const request = {\n text: message,\n tabId: tab.id,\n conversationId: tab.conversationId,\n mode: machine.mode,\n model: currentModels.activeId ?? null,\n };\n const current = { token, replyId, request, started: false, sent: false };\n turn = current;\n machine.sendMessage(message, tab.conversationId);\n changed();\n\n const emit = (event) => { if (turn?.token === token) handle(event); };\n const fail = (error) => emit({ type: CHAT_TRANSPORT_EVENTS.ERROR, message: error?.message ?? String(error) });\n const start = () => {\n current.sent = true;\n try {\n Promise.resolve(transport.send(request, emit)).catch(fail);\n } catch (error) {\n fail(error);\n }\n };\n if (runEnding) runEnding.then(() => { if (turn === current) start(); });\n else start();\n return true;\n }\n\n function handle(event) {\n switch (event?.type) {\n case CHAT_TRANSPORT_EVENTS.TEXT_DELTA:\n if (!event.text) return;\n markStarted();\n view.appendChunk(event.text);\n return;\n case CHAT_TRANSPORT_EVENTS.TOOL_USE:\n markStarted();\n useTool(event);\n return;\n case CHAT_TRANSPORT_EVENTS.MESSAGE_END:\n endMessage(event);\n return;\n case CHAT_TRANSPORT_EVENTS.ERROR:\n failTurn(event);\n return;\n default:\n logger?.warn?.('chat-shell', 'Unknown transport event', { event });\n }\n }\n\n function markStarted() {\n if (turn.started) return;\n turn.started = true;\n machine.streamStart();\n }\n\n function useTool({ id, name, label, status = 'running' }) {\n const entry = extras.get(turn.replyId);\n const known = status in TOOL_ICONS ? status : 'running';\n const tool = id != null ? entry.tools.find((t) => t.id === id) : null;\n if (tool) {\n Object.assign(tool, { status: known, name: name ?? tool.name, label: label ?? tool.label });\n } else {\n entry.tools.push({ id: id ?? `tool-${entry.tools.length + 1}`, name, label, status: known });\n }\n drawTools(turn.replyId);\n follow();\n }\n\n /** Ends the reply. Tools still running take `toolStatus`; a reply with nothing to show is taken out. */\n function closeReply(toolStatus) {\n const id = turn.replyId;\n turn = null;\n const entry = extras.get(id);\n for (const tool of entry.tools) if (tool.status === 'running') tool.status = toolStatus;\n if (!viewMessage(id).text && !entry.tools.length && entry.meta === undefined) {\n view.remove(id);\n extras.delete(id);\n return;\n }\n view.endStream();\n drawTools(id);\n drawControls(id);\n drawFooter(id);\n follow();\n }\n\n function endMessage({ text: final, conversationId, meta }) {\n const id = turn.replyId;\n const entry = extras.get(id);\n if (final && !viewMessage(id).text) view.appendChunk(final);\n if (meta !== undefined) entry.meta = { ...(entry.meta ?? {}), ...meta };\n if (conversationId) setConversationId(activeId, conversationId);\n const reply = viewMessage(id).text;\n closeReply('done');\n machine.streamComplete({ text: reply, meta: entry.meta });\n syncWelcome();\n changed();\n }\n\n function failTurn({ message }) {\n const body = message || text.unknownError;\n closeReply('stopped');\n machine.error(body);\n appendMessage('error', body);\n syncWelcome();\n changed();\n }\n\n /**\n * Stops the reply: the chat can send again at once. That send waits for\n * `runEnding`, unless this turn was itself still waiting for it: the person\n * has now said twice that they will not wait, so the next send goes out.\n */\n function cancel() {\n if (!turn) return false;\n const { request, sent } = turn;\n closeReply('stopped');\n machine.cancel();\n if (sent) callCancel(request);\n else runEnding = null;\n syncWelcome();\n changed();\n return true;\n }\n\n function callCancel(request) {\n const failed = (error) => logger?.warn?.('chat-shell', 'Cancel failed', { error });\n try {\n const ended = transport.cancel?.(request);\n if (typeof ended?.then !== 'function') return;\n const ending = Promise.resolve(ended).catch(failed).then(() => {\n if (runEnding === ending) runEnding = null;\n });\n runEnding = ending;\n } catch (error) {\n failed(error);\n }\n }\n\n function setConversationId(tabId, conversationId) {\n const tab = tabOf(tabId);\n if (!tab) return false;\n tab.conversationId = conversationId ?? null;\n if (tab.id === activeId) machine.conversationId = tab.conversationId;\n return true;\n }\n\n /** Replaces a conversation's messages (a backend knew better). The one a turn is writing to refuses. */\n function setMessages(tabId, messages) {\n const tab = tabOf(tabId);\n if (!tab || (turn && tab.id === activeId)) return false;\n tab.messages = restored(messages);\n tab.scrollTop = null;\n if (tab.id === activeId) showTab(tab);\n changed();\n return true;\n }\n\n // \u2500\u2500 the bar: modes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const modeButtons = new Map();\n if (modes.length) {\n const group = el('div', 'twm-chat-shell__modes');\n group.setAttribute('role', 'group');\n group.setAttribute('aria-label', text.modes);\n for (const { id, label, title } of modes) {\n const b = el('button', 'twm-chat-shell__mode', label);\n b.type = 'button';\n if (title) b.title = title;\n b.addEventListener('click', () => {\n if (id === machine.mode) return;\n setMode(id);\n safely(onModeChange, id);\n });\n modeButtons.set(id, b);\n group.append(b);\n }\n bar.append(group);\n }\n function drawMode() {\n for (const [id, b] of modeButtons) {\n const on = id === machine.mode;\n b.classList.toggle('twm-chat-shell__mode--on', on);\n b.setAttribute('aria-pressed', String(on));\n }\n }\n function setMode(id) {\n if (!modeButtons.has(id)) return false;\n machine.setMode(id);\n drawMode();\n return true;\n }\n drawMode();\n bar.append(el('div', 'twm-chat-shell__bar-spacer'));\n\n // \u2500\u2500 the bar: the model picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let currentModels = { items: [], activeId: null, label: null, status: null };\n const modelBtn = el('button', 'twm-chat-shell__model-btn');\n modelBtn.type = 'button';\n modelBtn.setAttribute('aria-haspopup', 'menu');\n modelBtn.setAttribute('aria-expanded', 'false');\n const modelDot = el('span', 'twm-chat-shell__status');\n const modelLabel = el('span', 'twm-chat-shell__model-label');\n modelBtn.append(modelDot, modelLabel, icon('expand_more', 'twm-chat-shell__model-chevron'));\n bar.append(modelBtn);\n /** ActionDropdown puts an option's label and description in as markup; these are text. */\n const asMarkup = (value) => {\n const span = el('span');\n span.textContent = String(value ?? '');\n return span.innerHTML;\n };\n const modelMenu = new ActionDropdown({\n trigger: modelBtn,\n options: [],\n className: 'twm-chat-shell__model-menu',\n onSelect: ({ item }) => {\n if (item.action !== undefined) safely(onModelAction, item.action, item);\n else safely(onModelSelect, item);\n },\n });\n\n /**\n * Any of `{ items, activeId, label, status }`; what is left out stays. An item\n * is `{ id, label, description?, icon? }`, `{ action, label, description?, icon? }`\n * or `{ separator: true }`. `label` is the button's text (the active item's\n * without it); `status` is `{ state?: 'ready' | 'pending', label? }`, a dot on it.\n */\n function setModels(patch = {}) {\n currentModels = { ...currentModels, ...patch };\n const { items, activeId: active, label, status } = currentModels;\n modelMenu.setOptions(items.map((item) => {\n if (item.separator) return { separator: true };\n const isAction = item.action !== undefined;\n const radio = item.id === active ? 'radio_button_checked' : 'radio_button_unchecked';\n return {\n type: isAction ? 'action' : 'model',\n item,\n label: asMarkup(item.label),\n icon: item.icon ?? (isAction ? undefined : radio),\n description: item.description ? asMarkup(item.description) : undefined,\n };\n }));\n modelLabel.textContent = label ?? items.find((i) => !i.separator && i.id === active)?.label ?? text.selectModel;\n modelDot.className = status?.state\n ? `twm-chat-shell__status twm-chat-shell__status--${status.state}` : 'twm-chat-shell__status';\n modelDot.title = status?.label ?? '';\n modelDot.hidden = !status;\n modelBtn.hidden = !items.length && !label;\n bar.hidden = modelBtn.hidden && !modes.length;\n }\n setModels(models ?? {});\n\n // \u2500\u2500 the chat \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const chat = {\n root,\n /** Sends as the user would; false when a turn is running or the text is blank. */\n send,\n /** Stops the running reply; false when there is none. */\n cancel,\n /** A turn is running. Answers at once, where `stateMachine` follows in microtasks. */\n isBusy: () => turn !== null,\n stateMachine: machine,\n\n /** The messages of the conversation in front. */\n messages: keptMessages,\n /** Merges into a message's `meta`, redraws its controls, and reports a change. */\n updateMeta(id, patch) {\n const entry = extras.get(id);\n if (!entry) return false;\n entry.meta = { ...(entry.meta ?? {}), ...patch };\n drawControls(id);\n changed();\n return true;\n },\n refreshControls: (id) => drawControls(id),\n /** The element holding a message's controls, or null. */\n controlsSlot: (id) => extras.get(id)?.controlsEl ?? null,\n\n snapshot,\n activeConversation: () => activeId,\n newConversation,\n switchTo,\n close,\n rename,\n reset,\n setConversationId,\n setMessages,\n\n mode: () => machine.mode,\n setMode,\n setModels,\n\n getText: () => view.getText(),\n setText: (value) => view.setText(value),\n focus: () => view.focus(),\n\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (turn) {\n const { request } = turn;\n turn = null;\n callCancel(request);\n }\n for (const timer of copyTimers) clearTimeout(timer);\n copyTimers.clear();\n extras.clear();\n modelMenu.destroy();\n strip.destroy();\n view.destroy();\n root.remove();\n },\n };\n\n // \u2500\u2500 what it starts with \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 for (const saved of conversations?.tabs ?? []) {\n tabs.push({\n ...newTab(String(saved.id)),\n title: saved.title || text.newConversation,\n conversationId: saved.conversationId ?? null,\n messages: restored(saved.messages),\n });\n }\n const first = tabOf(conversations?.activeId) ?? tabs[0] ?? freshTab();\n activeId = first.id;\n if (first.conversationId) machine.loadConversation(first.conversationId);\n showTab(first);\n drawTabs();\n return chat;\n}\n", "/**\n * DetailHeader \u2014 shared header bar for detail views.\n *\n * Usage:\n * import { createDetailHeader, updateDetailHeader } from '../ui/components/detail_header.js';\n *\n * const header = createDetailHeader({\n * title: 'My Scenario',\n * badges: [{ text: 'Static' }],\n * renameable: true,\n * onRename: async (name) => ({ success: true }),\n * actions: [\n * { key: 'run', label: 'Run', icon: 'play_arrow', variant: 'primary', handler: () => {} },\n * { key: 'delete', label: 'Delete', icon: 'delete', variant: 'danger', handler: () => {} },\n * ],\n * });\n * container.appendChild(header);\n *\n * To update in place (e.g., running state changed):\n * updateDetailHeader(header, { ...newConfig });\n */\n\nimport { attachInlineRenamer } from './inline_renamer.js';\n\nconst ESC = (s) => String(s ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n/**\n * @typedef {Object} DetailHeaderBadge\n * @property {string} text\n * @property {string} [className] - Extra class(es) of your own (e.g., 'my-badge--live'); the\n * pill itself is `.twm-detail-header__badge`\n * @property {string} [icon] - Material Symbols icon name\n */\n\n/**\n * @typedef {Object} DetailHeaderAction\n * @property {string} key - data-action value\n * @property {string} label - Button text\n * @property {string} [icon] - Material Symbols icon name (none: label only)\n * @property {'primary'|'secondary'|'danger'} [variant='secondary'] - The button is a `.twm-btn`;\n * 'primary' and 'danger' add `.twm-btn--primary` / `.twm-btn--danger`, and every\n * variant is also named `.twm-detail-header__btn--<variant>`\n * @property {boolean} [disabled=false]\n * @property {string} [title] - Tooltip\n * @property {Function} handler - Click callback\n */\n\n/**\n * @typedef {Object} DetailHeaderConfig\n * @property {string} title\n * @property {string} [subtitle]\n * @property {string} [icon] - Material icon before title\n * @property {DetailHeaderBadge[]} [badges]\n * @property {DetailHeaderAction[]} [actions]\n * @property {HTMLElement[]} [extraElements] - Custom elements appended to actions area\n * @property {boolean} [renameable=false]\n * @property {Function} [onRename] - (newName) => Promise<{success, newValue?}>\n */\n\n/**\n * Create a detail header element.\n * @param {DetailHeaderConfig} config\n * @returns {HTMLElement}\n */\nexport function createDetailHeader(config) {\n const header = document.createElement('header');\n header.className = 'twm-detail-header';\n _populate(header, config);\n return header;\n}\n\n/**\n * Update an existing detail header in place.\n * Destroys previous inline renamer and rebuilds inner DOM.\n * @param {HTMLElement} headerEl\n * @param {DetailHeaderConfig} config\n */\nexport function updateDetailHeader(headerEl, config) {\n // Destroy previous renamer if any\n headerEl._renamer?.destroy();\n headerEl._renamer = null;\n headerEl.innerHTML = '';\n _populate(headerEl, config);\n}\n\n// \u2500\u2500\u2500 Internal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction _populate(header, config) {\n const { title, subtitle, icon, badges = [], actions = [], extraElements = [], renameable = false, onRename } = config;\n\n // Title row\n const titleRow = document.createElement('div');\n titleRow.className = 'twm-detail-header__title-row';\n\n if (icon) {\n const iconEl = document.createElement('span');\n iconEl.className = 'twm-detail-header__icon material-symbols-outlined';\n iconEl.textContent = icon;\n titleRow.appendChild(iconEl);\n }\n\n const nameEl = document.createElement('h2');\n nameEl.className = 'twm-detail-header__name';\n nameEl.textContent = title || '';\n if (renameable) {\n nameEl.dataset.renameable = '';\n nameEl.title = 'Double-click to rename';\n }\n titleRow.appendChild(nameEl);\n\n for (const badge of badges) {\n const badgeEl = document.createElement('span');\n badgeEl.className = `twm-detail-header__badge${badge.className ? ` ${badge.className}` : ''}`;\n if (badge.icon) {\n const bi = document.createElement('span');\n bi.className = 'twm-detail-header__badge-icon material-symbols-outlined';\n bi.textContent = badge.icon;\n badgeEl.appendChild(bi);\n }\n badgeEl.appendChild(document.createTextNode(badge.text));\n titleRow.appendChild(badgeEl);\n }\n\n header.appendChild(titleRow);\n\n // Subtitle\n if (subtitle) {\n const sub = document.createElement('div');\n sub.className = 'twm-detail-header__subtitle';\n sub.innerHTML = subtitle; // may contain <strong> etc.\n header.appendChild(sub);\n }\n\n // Actions\n if (actions.length > 0 || extraElements.length > 0) {\n const actionsEl = document.createElement('div');\n actionsEl.className = 'twm-detail-header__actions';\n\n for (const extra of extraElements) {\n actionsEl.appendChild(extra);\n }\n\n for (const action of actions) {\n const btn = document.createElement('button');\n btn.type = 'button';\n const variant = action.variant || 'secondary';\n // The shared `.twm-btn` look (BUG-0015): 'primary' and 'danger'\n // wear its colour variants; 'secondary' is the plain button.\n const look = variant === 'secondary' ? '' : ` twm-btn--${variant}`;\n btn.className = `twm-btn${look} twm-detail-header__btn twm-detail-header__btn--${variant}`;\n btn.dataset.action = action.key;\n if (action.disabled) btn.disabled = true;\n if (action.title) btn.title = action.title;\n\n if (action.icon) {\n const iconSpan = document.createElement('span');\n iconSpan.className = 'material-symbols-outlined twm-btn__glyph';\n iconSpan.textContent = action.icon;\n btn.appendChild(iconSpan);\n }\n const labelSpan = document.createElement('span');\n labelSpan.className = 'twm-btn__label';\n labelSpan.textContent = action.label ?? '';\n btn.appendChild(labelSpan);\n\n btn.addEventListener('click', () => action.handler?.());\n actionsEl.appendChild(btn);\n }\n\n header.appendChild(actionsEl);\n }\n\n // Inline rename\n if (renameable && onRename) {\n const renamer = attachInlineRenamer({\n label: nameEl,\n onCommit: async (newName) => {\n if (!newName?.trim()) return { success: false };\n return await onRename(newName.trim());\n },\n });\n nameEl.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n renamer.start(e);\n });\n header._renamer = renamer;\n }\n}\n", "/**\n * fact_table.js \u2014 A SHEET OF FACTS: a name and its value, row after row, with\n * no header row, nothing truncated and no height to give it. (0.7.0)\n *\n * Server db-main-01.internal\n * Version 16.4\n * Connection postgresql://tables@db-main-01.internal:5432/tables_control\n * ?application_name=tables-api&sslmode=verify-full\n *\n * A DataTable is the wrong tool for this, for three reasons that are its\n * design rather than its defects: it draws a header row, it clips a cell to\n * one line (a long value becomes an ellipsis), and it fills a box with a\n * height (in a box without one it draws its header and no rows). A fact\n * sheet is the opposite on all three: the names are the header, every value\n * is read whole, and the sheet is exactly as tall as its rows.\n *\n * So this is a plain `<table class=\"twm-facts\">`:\n *\n * - the first column is the LABEL \u2014 muted, and kept on one line (pass\n * `wrapLabels: true` to let a long one wrap, `labelColumn: false` for a\n * sheet whose first column is ordinary data);\n * - every value WRAPS \u2014 at spaces, and inside a long word or URL when it must\n * (`overflow-wrap: anywhere`) \u2014 and keeps its own line breaks, so a\n * pretty-printed JSON value reads as one; `wrap: 'words'` wraps at spaces\n * only and keeps a long word whole (the sheet grows wider, for a sideways\n * scroller around it), and `wrap: 'none'` keeps only the value's own breaks;\n * - a value is text, a number or a NODE (a pill, a link, a button); an\n * object or array is drawn as indented JSON; `null` is an empty cell, or\n * `nullDisplay`;\n * - `mono` draws values in the monospace face, for the whole sheet or one row;\n * - `compare: true` gives each row a BEFORE and an AFTER, with an arrow\n * between: a row whose two sides differ is `--changed`, one that has only\n * an after is `--added`, only a before `--removed`, and the same on both\n * sides `--same`. A row with a plain `value` spans both sides;\n * - `headers` adds a header row after all, for the sheets that have several\n * columns of facts (a list of schemas, a list of pools); rows are then\n * arrays of cells, and `numeric` names the columns of figures.\n *\n * A row may be an OBJECT \u2014 `{label, value}` or `{label, before, after}`, with\n * `mono`, `numeric`, `labelTitle`, `key` and `status` \u2014 or an ARRAY of cells,\n * `[label, value, \u2026]`, which is the positional form a multi-column sheet uses.\n */\n\nlet SEQ = 0;\nconst isNode = (v) => typeof Node !== 'undefined' && v instanceof Node;\n\n/**\n * @typedef {Object} FactRow\n * @property {string|Node} label\n * @property {*} [value]\n * @property {*} [before] - With `compare`: the value before.\n * @property {*} [after] - With `compare`: the value after.\n * @property {boolean} [mono] - This row's values in the monospace face.\n * @property {boolean} [numeric] - This row's values in tabular numerals.\n * @property {string} [labelTitle] - A tooltip on the label.\n * @property {*} [key] - `data-key` on the row.\n * @property {'changed'|'same'|'added'|'removed'} [status] - With `compare`:\n * overrides the status worked out from the two sides.\n */\n\n/**\n * @typedef {Object} FactTableConfig\n * @property {Array<FactRow|Array>} [rows=[]]\n * @property {string[]|null} [headers=null] - A header row. Off by default.\n * @property {boolean} [compare=false] - A before and an after column.\n * @property {boolean} [labelColumn=true] - The first column is a label.\n * @property {boolean} [wrapLabels=false] - Let a long label wrap.\n * @property {'anywhere'|'words'|'none'} [wrap='anywhere'] - How a value wraps:\n * at spaces and inside a long word when it must (the default), at spaces\n * only (`'words'`: a long word stays whole and the sheet grows wider \u2014 for a\n * sheet inside a sideways scroller), or not at all beyond its own line\n * breaks (`'none'`).\n * @property {boolean} [mono=false] - Every value in the monospace face.\n * @property {number[]} [numeric=[]] - Column indices drawn in tabular numerals.\n * @property {string} [nullDisplay=''] - What `null`/`undefined` reads as.\n * @property {string} [missing='\u2014'] - With `compare`: an absent side.\n * @property {Function} [rowClass] - `(row, idx) => string|string[]|null`.\n * @property {Function} [rowAttrs] - `(row, idx) => {name: value}`.\n * @property {string|Node|Function} [emptyState] - Shown when there are no rows.\n * @property {string} [label] - The table's accessible name (`aria-label`).\n * @property {string} [className] - Added to the `<table>`.\n */\n\nexport class FactTable {\n /**\n * @param {HTMLElement|null} host appended to, if given\n * @param {FactTableConfig} [config]\n */\n constructor(host, config = {}) {\n this.config = {\n rows: [],\n headers: null,\n compare: false,\n labelColumn: true,\n wrapLabels: false,\n wrap: 'anywhere',\n mono: false,\n numeric: [],\n nullDisplay: '',\n missing: '\u2014',\n rowClass: null,\n rowAttrs: null,\n emptyState: null,\n label: null,\n className: null,\n ...config,\n };\n this._rows = Array.isArray(this.config.rows) ? this.config.rows.slice() : [];\n this._id = ++SEQ;\n const table = document.createElement('table');\n table.className = 'twm-facts'\n + (this.config.compare ? ' twm-facts--compare' : '')\n + (this.config.labelColumn ? '' : ' twm-facts--no-label')\n + (this.config.wrapLabels ? ' twm-facts--wrap-labels' : '')\n + (this.config.wrap === 'words' ? ' twm-facts--wrap-words'\n : this.config.wrap === 'none' ? ' twm-facts--wrap-none' : '')\n + (this.config.mono ? ' twm-facts--mono' : '')\n + (this.config.className ? ` ${this.config.className}` : '');\n if (this.config.label) table.setAttribute('aria-label', this.config.label);\n this.element = table;\n this._draw();\n if (host) host.appendChild(table);\n }\n\n /** Replace the rows and draw them. */\n setRows(rows) {\n this._rows = Array.isArray(rows) ? rows.slice() : [];\n this._draw();\n }\n\n getRows() {\n return this._rows.slice();\n }\n\n /** The `<tr>` drawn for row `idx`, or null. */\n getRow(idx) {\n return this.element.tBodies[0]?.rows[idx]?.__factIndex === idx\n ? this.element.tBodies[0].rows[idx] : null;\n }\n\n dispose() {\n this.element.remove();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** How many columns the sheet has. */\n _width() {\n const { compare, headers } = this.config;\n if (compare) return 4;\n let n = 2;\n if (Array.isArray(headers)) n = Math.max(n, headers.length);\n for (const r of this._rows) if (Array.isArray(r)) n = Math.max(n, r.length);\n return n;\n }\n\n _draw() {\n const table = this.element;\n table.replaceChildren();\n const width = this._width();\n const { headers, compare } = this.config;\n\n if (Array.isArray(headers) && headers.length) {\n const thead = document.createElement('thead');\n const tr = document.createElement('tr');\n // With `compare`, three names stand over label, before and after;\n // the arrow column gets an empty one.\n const names = compare && headers.length === 3\n ? [headers[0], headers[1], '', headers[2]] : headers;\n for (let i = 0; i < width; i++) {\n const th = document.createElement('th');\n th.scope = 'col';\n appendContent(th, names[i] ?? '');\n if (this._numeric(i)) th.classList.add('twm-facts__num');\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n table.appendChild(thead);\n }\n\n const tbody = document.createElement('tbody');\n this._rows.forEach((row, idx) => tbody.appendChild(this._row(row, idx, width)));\n if (!this._rows.length) {\n let content = this.config.emptyState;\n if (typeof content === 'function') content = content();\n if (content != null && content !== false && content !== '') {\n const tr = document.createElement('tr');\n tr.className = 'twm-facts__empty-row';\n const td = document.createElement('td');\n td.className = 'twm-facts__empty';\n td.colSpan = width;\n appendContent(td, content);\n tr.appendChild(td);\n tbody.appendChild(tr);\n }\n }\n table.classList.toggle('twm-facts--empty', this._rows.length === 0);\n table.appendChild(tbody);\n }\n\n _numeric(col) {\n const n = this.config.numeric;\n return Array.isArray(n) && n.includes(col);\n }\n\n _row(row, idx, width) {\n const tr = document.createElement('tr');\n tr.className = 'twm-facts__row';\n tr.__factIndex = idx;\n tr.__fact = row;\n if (Array.isArray(row)) {\n for (let i = 0; i < width; i++) {\n const td = this._cell(i === 0 && this.config.labelColumn ? 'label' : 'value', row[i]);\n if (this._numeric(i)) td.classList.add('twm-facts__num');\n if (i === row.length - 1 && row.length < width) {\n td.colSpan = width - i;\n tr.appendChild(td);\n break;\n }\n tr.appendChild(td);\n }\n } else {\n const r = row && typeof row === 'object' ? row : { label: row };\n if (r.key !== undefined && r.key !== null) tr.dataset.key = String(r.key);\n const label = this._cell(this.config.labelColumn ? 'label' : 'value', r.label);\n if (r.labelTitle) label.title = String(r.labelTitle);\n tr.appendChild(label);\n const tune = (td) => {\n if (r.mono) td.classList.add('twm-facts__mono');\n if (r.numeric) td.classList.add('twm-facts__num');\n return td;\n };\n const hasBefore = Object.prototype.hasOwnProperty.call(r, 'before');\n const hasAfter = Object.prototype.hasOwnProperty.call(r, 'after');\n if (this.config.compare && (hasBefore || hasAfter)) {\n const status = r.status || statusOf(r, hasBefore, hasAfter);\n tr.classList.add(`twm-facts__row--${String(status).replace(/[^\\w-]/g, '')}`);\n tr.dataset.status = String(status);\n const before = tune(hasBefore ? this._cell('value', r.before) : this._missing());\n before.classList.add('twm-facts__before');\n const arrow = document.createElement('td');\n arrow.className = 'twm-facts__arrow';\n arrow.setAttribute('aria-hidden', 'true');\n arrow.textContent = '\u2192';\n const after = tune(hasAfter ? this._cell('value', r.after) : this._missing());\n after.classList.add('twm-facts__after');\n tr.append(before, arrow, after);\n } else {\n const value = tune(this._cell('value', r.value));\n if (width > 2) value.colSpan = width - 1;\n tr.appendChild(value);\n }\n }\n this._decorate(tr, row, idx);\n return tr;\n }\n\n _cell(kind, content) {\n const isLabel = kind === 'label';\n const td = document.createElement(isLabel ? 'th' : 'td');\n td.className = isLabel ? 'twm-facts__label' : 'twm-facts__value';\n if (isLabel) td.scope = 'row';\n if (content === null || content === undefined) {\n const said = isLabel ? '' : this.config.nullDisplay;\n if (said) {\n td.textContent = String(said);\n td.classList.add('twm-facts__null');\n }\n } else {\n appendContent(td, content);\n }\n return td;\n }\n\n _missing() {\n const td = document.createElement('td');\n td.className = 'twm-facts__value twm-facts__missing';\n td.textContent = String(this.config.missing ?? '');\n return td;\n }\n\n _decorate(tr, row, idx) {\n const { rowClass, rowAttrs } = this.config;\n if (typeof rowClass === 'function') {\n const c = rowClass(row, idx);\n const list = Array.isArray(c) ? c : String(c ?? '').split(/\\s+/);\n for (const name of list) if (name) tr.classList.add(String(name));\n }\n if (typeof rowAttrs === 'function') {\n for (const [name, value] of Object.entries(rowAttrs(row, idx) || {})) {\n if (value == null || value === false) continue;\n try {\n tr.setAttribute(name, value === true ? '' : String(value));\n } catch (err) {\n console.error(`[FactTable] rowAttrs: bad attribute \"${name}\"`, err);\n }\n }\n }\n }\n}\n\n/**\n * Build a fact sheet, append it to `host` (if given) and draw it.\n *\n * @param {HTMLElement|null} host\n * @param {FactTableConfig} [config]\n * @returns {FactTable}\n */\nexport function createFactTable(host, config = {}) {\n return new FactTable(host, config);\n}\n\n/** What a before/after row says, from its two sides. Nodes cannot be\n * compared, so a row that has one is `changed` unless it says otherwise;\n * objects compare by their JSON. */\nfunction statusOf(r, hasBefore, hasAfter) {\n if (!hasBefore) return 'added';\n if (!hasAfter) return 'removed';\n if (isNode(r.before) || isNode(r.after)) return 'changed';\n if (Object.is(r.before, r.after)) return 'same';\n if (r.before && r.after && typeof r.before === 'object' && typeof r.after === 'object') {\n try {\n return JSON.stringify(r.before) === JSON.stringify(r.after) ? 'same' : 'changed';\n } catch {\n return 'changed';\n }\n }\n return 'changed';\n}\n\n/** Text, a number, a node, or an object (drawn as indented JSON) into `el`. */\nfunction appendContent(el, content) {\n if (content === null || content === undefined) return;\n if (isNode(content)) { el.appendChild(content); return; }\n let text;\n if (typeof content === 'object') {\n try { text = JSON.stringify(content, null, 2); } catch { text = String(content); }\n } else {\n text = String(content);\n }\n el.appendChild(document.createTextNode(text));\n}\n", "/**\n * The filter expression language: recursive AND/OR/NOT groups of conditions,\n * with no idea what it is filtering. No DOM; `filter_builder.js` is the editor.\n *\n * Group = { kind: 'group', op: 'AND' | 'OR', negate?: boolean, children: [...] }\n * Clause = { kind: 'clause', field: string, op: string, value?: any }\n *\n * A node of any other kind is carried untouched and never interpreted (it is how\n * `fromConditionTree` keeps a node it cannot read). The expression is plain JSON,\n * so it round-trips through a bridge, a store and the editor as it is.\n *\n * A FIELD CATALOGUE goes in, a bound MODEL comes out:\n *\n * const model = createFilterModel({ fields: [...] });\n * model.matcherFor(expr)(row);\n * model.describeFilter(expr); // \"Status is open AND Size one of s, m\"\n *\n * A field is `{ key, label, type, get?, options?, operators?, editor?, hidden?,\n * group?, time? }`. `get` pulls the COMPARABLE value, not always the displayed\n * one, and defaults to `row[key]`. `options` may be a getter over live data; it\n * is read at use, never cached.\n */\n\n/* \u2500\u2500 operators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * `arity` is what the editor draws and what a condition needs: 0 no value, 1 one,\n * 2 a range. `multi` still has arity 1, but the value is an ARRAY. `input: 'days'`\n * marks a value that is a count of days on a date field. */\n\nconst OPERATOR_LIST = [\n { id: 'is', label: 'is', arity: 1 },\n { id: 'is_not', label: 'is not', arity: 1 },\n { id: 'contains', label: 'contains', arity: 1 },\n { id: 'not_contains', label: 'does not contain', arity: 1 },\n { id: 'starts_with', label: 'starts with', arity: 1 },\n { id: 'ends_with', label: 'ends with', arity: 1 },\n { id: 'gt', label: '>', arity: 1 },\n { id: 'lt', label: '<', arity: 1 },\n { id: 'gte', label: '>=', arity: 1 },\n { id: 'lte', label: '<=', arity: 1 },\n { id: 'between', label: 'between', arity: 2 },\n { id: 'before', label: 'before', arity: 1 },\n { id: 'after', label: 'after', arity: 1 },\n { id: 'in_last_days', label: 'in the last N days', arity: 1, input: 'days' },\n { id: 'one_of', label: 'one of', arity: 1, multi: true },\n { id: 'none_of', label: 'none of', arity: 1, multi: true },\n { id: 'all_of', label: 'all of', arity: 1, multi: true },\n { id: 'is_empty', label: 'is empty', arity: 0 },\n { id: 'is_not_empty', label: 'is not empty', arity: 0 },\n { id: 'is_null', label: 'has no value', arity: 0 },\n { id: 'is_not_null', label: 'has a value', arity: 0 },\n { id: 'is_true', label: 'is true', arity: 0 },\n { id: 'is_false', label: 'is false', arity: 0 },\n];\n\n/** Every operator FlexDesk knows, by id. */\nexport const FILTER_OPERATORS = Object.freeze(\n Object.fromEntries(OPERATOR_LIST.map((o) => [o.id, Object.freeze(o)])),\n);\n\n/** What a field of each type is offered unless its `operators` says otherwise. */\nexport const FILTER_TYPE_OPERATORS = Object.freeze({\n enum: Object.freeze(['is', 'is_not', 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n text: Object.freeze(['is', 'is_not', 'contains', 'not_contains', 'starts_with', 'ends_with',\n 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n number: Object.freeze(['is', 'is_not', 'gt', 'lt', 'gte', 'lte', 'between',\n 'one_of', 'none_of', 'is_empty', 'is_not_empty']),\n date: Object.freeze(['is', 'is_not', 'before', 'after', 'between', 'in_last_days',\n 'is_empty', 'is_not_empty']),\n set: Object.freeze(['contains', 'not_contains', 'one_of', 'none_of', 'all_of',\n 'is_empty', 'is_not_empty']),\n bool: Object.freeze(['is_true', 'is_false', 'is_empty']),\n});\n\n/* \u2500\u2500 the expression, without a model \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** A fresh, empty AND group. */\nexport const emptyFilter = () => ({ kind: 'group', op: 'AND', children: [] });\n\n/** A deep copy. The expression is JSON by contract, so this is total. */\nexport const cloneFilter = (expr) => (expr == null ? expr : JSON.parse(JSON.stringify(expr)));\n\n/** The expression as text. */\nexport const serializeFilter = (expr) => JSON.stringify(expr);\n\n/** An expression from `serializeFilter`'s text. Throws on text that is not one. */\nexport function parseFilter(text) {\n const expr = JSON.parse(text);\n if (!expr || typeof expr !== 'object' || Array.isArray(expr) || !expr.kind) {\n throw new Error('[FilterModel] not a filter expression');\n }\n return expr;\n}\n\n/** How many conditions an expression holds. A carried node counts as one. */\nexport function countConditions(node) {\n if (!node) return 0;\n if (node.kind !== 'group') return 1;\n return (node.children || []).reduce((n, child) => n + countConditions(child), 0);\n}\n\n/** A field's options as `{ value, label }`. Bare strings and `{ value | id, label }` are legal. */\nexport function filterOptions(field) {\n return (field?.options || []).map((o) => {\n if (o === null || typeof o !== 'object') return { value: o, label: String(o ?? '') };\n const value = o.value ?? o.id ?? '';\n return { value, label: String(o.label ?? value) };\n });\n}\n\n/* \u2500\u2500 the value a text box writes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** How many significant decimal digits a double holds exactly. */\nconst EXACT_DIGITS = 15;\n\nfunction significantDigits(text) {\n const [whole, fraction = ''] = text.replace(/^[+-]/, '').split('.');\n const lead = whole.replace(/^0+/, '');\n const tail = fraction.replace(/0+$/, '');\n return lead ? lead.length + tail.length : tail.replace(/^0+/, '').length;\n}\n\n/**\n * The value a control's string becomes, typed by the field's declared type, not\n * by sniffing: a number field writes a number when the string is a plain decimal\n * a double holds exactly. It declines (returns `raw`) whenever converting would\n * change the filter rather than type it: an empty box is empty and not zero, a\n * half-typed `-` stays text, and a wider decimal is not rounded. Every other\n * field type keeps the string.\n */\nexport function coerceFilterValue(field, raw) {\n if (typeof raw !== 'string' || field?.type !== 'number') return raw;\n const text = raw.trim();\n if (!/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)$/.test(text)) return raw;\n if (significantDigits(text) > EXACT_DIGITS) return raw;\n const value = Number(text);\n // Too small for a double: \"greater than zero\" is a different filter.\n if (value === 0 && /[1-9]/.test(text)) return raw;\n return value;\n}\n\n/* \u2500\u2500 value coercion for matching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Text comparisons are case-insensitive. A date degrades to a DAY number, so \"is\"\n * means \"same day\" without timezone arithmetic; a field with `time: true` compares\n * instants instead. */\n\nconst low = (v) => String(v ?? '').trim().toLowerCase();\nconst num = (v) => (v === '' || v === null || v === undefined ? NaN : Number(v));\nconst arr = (v) => (Array.isArray(v) ? v : v === '' || v === null || v === undefined ? [] : [v]);\nconst first = (v) => (Array.isArray(v) ? v[0] : v);\n\nfunction day(v) {\n const s = String(v ?? '').trim().slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return NaN;\n return Date.UTC(+s.slice(0, 4), +s.slice(5, 7) - 1, +s.slice(8, 10));\n}\nconst instant = (v) => (v === null || v === undefined || v === '' ? NaN : Date.parse(String(v)));\n\nconst todayUtc = () => {\n const d = new Date();\n return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());\n};\n\nconst isBlank = (v) => v === null || v === undefined || v === ''\n || (Array.isArray(v) && v.length === 0);\n\n/* \u2500\u2500 the condition tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * The other form an expression travels in, for a server that compiles conditions:\n *\n * { op: 'and' | 'or', children: [...] }\n * { op: 'not', children: [one] }\n * { column, operator, value? }\n *\n * docs/components/filter-builder.md has the mapping and what it preserves. */\n\nconst TO_TREE_OPERATOR = Object.freeze({\n is: 'eq',\n is_not: 'ne',\n one_of: 'in',\n none_of: 'not_in',\n is_empty: 'is_blank',\n is_not_empty: 'is_not_blank',\n before: 'lt',\n after: 'gt',\n});\n\nconst FROM_TREE_OPERATOR = Object.freeze({\n eq: 'is',\n ne: 'is_not',\n in: 'one_of',\n not_in: 'none_of',\n is_blank: 'is_empty',\n is_not_blank: 'is_not_empty',\n});\n\nconst isBareNode = (node) => node !== null && typeof node === 'object';\n\n/** An expression as a condition tree. A carried node comes back as it went in. */\nexport function toConditionTree(node) {\n if (!isBareNode(node)) return node;\n if (node.kind === 'clause') {\n const { kind: _kind, field, op, ...rest } = node;\n return { column: field, operator: TO_TREE_OPERATOR[op] ?? op, ...rest };\n }\n if (node.kind !== 'group') return node.kind === 'opaque' ? node.node : node;\n const { kind: _kind, op, negate, children, ...rest } = node;\n const list = (children || []).map(toConditionTree);\n const treeOp = String(op).toLowerCase();\n if (!negate) return { op: treeOp, children: list, ...rest };\n // `not` takes exactly one child, and a group of one needs no group around it.\n return { op: 'not', children: [list.length === 1 ? list[0] : { op: treeOp, children: list }], ...rest };\n}\n\n/**\n * A condition tree as an expression. `null` is the empty filter. A node that is\n * neither a condition, an `and`/`or` group nor a `not` of exactly one child is\n * carried as `{ kind: 'opaque', node }`: the editor shows it read-only, and\n * `toConditionTree` returns it untouched.\n */\nexport function fromConditionTree(node) {\n if (node === null || node === undefined) return emptyFilter();\n if (!isBareNode(node)) return { kind: 'opaque', node };\n const op = String(node.op ?? '').toLowerCase();\n if (!node.op && 'column' in node) {\n const { column, operator, ...rest } = node;\n const id = String(operator ?? 'eq').toLowerCase();\n return { kind: 'clause', field: column, op: FROM_TREE_OPERATOR[id] ?? id, ...rest };\n }\n if ((op === 'and' || op === 'or') && Array.isArray(node.children ?? [])) {\n const { op: _op, children, ...rest } = node;\n return { kind: 'group', op: op.toUpperCase(), children: (children || []).map(fromConditionTree), ...rest };\n }\n if (op === 'not' && Array.isArray(node.children) && node.children.length === 1) {\n const { op: _op, children, ...rest } = node;\n const inner = fromConditionTree(children[0]);\n // `not(and(a, b))` is one negated group. A one-child inner group stays a\n // group, so that the tree comes back with the level it arrived with.\n if (inner.kind === 'group' && !inner.negate && inner.children.length !== 1) {\n return { ...inner, negate: true, ...rest };\n }\n return { kind: 'group', op: 'AND', negate: true, children: [inner], ...rest };\n }\n return { kind: 'opaque', node };\n}\n\n/* \u2500\u2500 the model \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst CACHE_MAX = 200;\n\n/**\n * Bind a field catalogue into everything that needs to know about it.\n *\n * @param {object} o\n * @param {Array} o.fields the catalogue (see the top of this file)\n * @param {string} [o.noun] what one row is called, for messages\n * @param {Array} [o.operators] operators added to the catalogue, or known ones\n * relabelled: `{ id, label, arity?, multi?, input?, match? }`. An id FlexDesk\n * knows keeps what you leave out. `match(rowValue, clauseValue, row)` is what\n * `matcherFor` runs for it; without one a clause using it matches nothing.\n * @param {'everything'|'nothing'} [o.emptyOr] what an empty OR group matches. An\n * empty AND always matches everything.\n * @param {(key: string) => string} [o.unknownName] how a field key the catalogue\n * does not know is shown.\n */\nexport function createFilterModel({\n fields, noun = 'row', operators = [], emptyOr = 'everything', unknownName = (key) => key,\n}) {\n const byKey = new Map(fields.map((f) => [f.key, f]));\n const fieldByKey = (key) => byKey.get(key) || null;\n\n const catalogue = new Map(OPERATOR_LIST.map((o) => [o.id, o]));\n for (const o of operators) {\n const known = catalogue.get(o.id);\n if (!known && !Number.isInteger(o.arity)) {\n throw new Error(`[FilterModel] operator \"${o.id}\" needs an arity`);\n }\n catalogue.set(o.id, { ...known, ...o });\n }\n for (const f of fields) {\n for (const id of f.operators || []) {\n if (!catalogue.has(id)) {\n throw new Error(`[FilterModel] field \"${f.key}\" names unknown operator \"${id}\"`);\n }\n }\n }\n\n /** The operators a field is offered, as definitions. An unknown field has none. */\n const operatorsFor = (fieldKey) => {\n const field = byKey.get(fieldKey);\n if (!field) return [];\n const ids = field.operators || FILTER_TYPE_OPERATORS[field.type] || [];\n return ids.map((id) => catalogue.get(id));\n };\n /** Any operator's definition by id, offered on a field or not; null when unknown. */\n const operatorById = (id) => catalogue.get(id) || null;\n\n /** What a freshly picked (field, operator) starts from; undefined means no value. */\n function defaultValue(field, op) {\n if (!field || !op || !op.arity) return undefined;\n if (op.multi) return [];\n if (op.input === 'days') return 7;\n if (op.arity === 2) return field.type === 'number' ? [null, null] : ['', ''];\n if (field.type === 'number') return null;\n if (field.type === 'enum') return filterOptions(field)[0]?.value ?? '';\n return '';\n }\n\n /** A clause on `key` (default: the first field offered), on its first operator.\n * Null when the catalogue offers nothing. */\n function newClause(key) {\n const field = key ? byKey.get(key) : fields.find((f) => !f.hidden);\n if (!field) return null;\n const op = operatorsFor(field.key)[0] || null;\n const clause = { kind: 'clause', field: field.key, op: op ? op.id : '' };\n const value = defaultValue(field, op);\n if (value !== undefined) clause.value = value;\n return clause;\n }\n\n /** Does `clause`'s value still mean something on `field`, under `op`? */\n function valueFits(field, op, value) {\n const errors = [];\n validateClause({ field: field.key, op: op.id, value }, errors, '');\n if (errors.length) return false;\n // A list the editor offers: a text field's single value is typed freely.\n const options = op.multi || field.type === 'enum' ? filterOptions(field) : [];\n return !options.length || arr(value).every((v) => options.some((o) => o.value === v));\n }\n\n /**\n * `clause` moved to the field `key`: its operator stays when that field offers\n * it, and its value when the value still fits; otherwise they start as\n * `newClause(key)`'s do. Null when the catalogue has no such field.\n */\n function moveClause(clause, key) {\n const next = newClause(key);\n if (!next) return null;\n const field = byKey.get(key);\n const op = operatorsFor(key).find((o) => o.id === clause.op);\n if (!op) return next;\n next.op = op.id;\n delete next.value;\n const value = op.arity && valueFits(field, op, clause.value) ? clause.value : defaultValue(field, op);\n if (value !== undefined) next.value = value;\n return next;\n }\n\n /* Compiled per type so a clause does its type dispatch ONCE, not on every row. */\n function compileClause(clause) {\n const field = byKey.get(clause?.field);\n if (!field) {\n console.warn('[FilterModel] clause references unknown field', clause?.field);\n return () => false;\n }\n const op = clause.op;\n const raw = clause.value;\n const get = field.get || ((row) => row?.[field.key]);\n\n const custom = catalogue.get(op)?.match;\n if (custom) return (row) => !!custom(get(row), raw, row);\n\n switch (op) {\n case 'is_empty': return (r) => isBlank(get(r));\n case 'is_not_empty': return (r) => !isBlank(get(r));\n case 'is_null': return (r) => get(r) === null || get(r) === undefined;\n case 'is_not_null': return (r) => get(r) !== null && get(r) !== undefined;\n case 'is_true': return (r) => get(r) === true || low(get(r)) === 'true';\n case 'is_false': return (r) => get(r) === false || low(get(r)) === 'false';\n default:\n }\n\n if (field.type === 'number') {\n const a = num(first(raw));\n const b = num(Array.isArray(raw) ? raw[1] : undefined);\n const list = arr(raw).map(num);\n switch (op) {\n case 'is': return (r) => num(get(r)) === a;\n case 'is_not': return (r) => num(get(r)) !== a;\n case 'gt': return (r) => num(get(r)) > a;\n case 'lt': return (r) => num(get(r)) < a;\n case 'gte': return (r) => num(get(r)) >= a;\n case 'lte': return (r) => num(get(r)) <= a;\n case 'between': return (r) => {\n const n = num(get(r));\n return n >= Math.min(a, b) && n <= Math.max(a, b);\n };\n case 'one_of': return (r) => list.includes(num(get(r)));\n case 'none_of': return (r) => !list.includes(num(get(r)));\n default:\n }\n }\n\n if (field.type === 'date') {\n const at = field.time ? instant : day;\n const a = at(first(raw));\n const b = Array.isArray(raw) ? at(raw[1]) : NaN;\n const compare = (test) => (r) => {\n const d = at(get(r));\n return !Number.isNaN(d) && test(d);\n };\n switch (op) {\n case 'is': return (r) => at(get(r)) === a;\n case 'is_not': return (r) => at(get(r)) !== a;\n case 'before': case 'lt': return compare((d) => d < a);\n case 'after': case 'gt': return compare((d) => d > a);\n case 'lte': return compare((d) => d <= a);\n case 'gte': return compare((d) => d >= a);\n case 'between': return compare((d) => d >= Math.min(a, b) && d <= Math.max(a, b));\n // Inclusive of today and of the Nth day back.\n case 'in_last_days': {\n const days = num(first(raw));\n return (r) => {\n const d = day(get(r));\n if (Number.isNaN(d) || Number.isNaN(days)) return false;\n return d >= todayUtc() - (days - 1) * 86400000 && d <= todayUtc();\n };\n }\n default:\n }\n }\n\n const one = low(first(raw));\n const many = arr(raw).map(low).filter((s) => s !== '');\n\n if (field.type === 'set') {\n const vals = (r) => arr(get(r)).map(low);\n switch (op) {\n case 'contains': return (r) => vals(r).includes(one);\n case 'not_contains': return (r) => !vals(r).includes(one);\n case 'one_of': return (r) => { const v = vals(r); return many.some((m) => v.includes(m)); };\n case 'none_of': return (r) => { const v = vals(r); return !many.some((m) => v.includes(m)); };\n case 'all_of': return (r) => { const v = vals(r); return many.every((m) => v.includes(m)); };\n default:\n }\n }\n\n // enum and text share string semantics: enum only constrains what the\n // editor offers, not how a comparison behaves.\n if (field.type === 'enum' || field.type === 'text') {\n switch (op) {\n case 'is': return (r) => low(get(r)) === one;\n case 'is_not': return (r) => low(get(r)) !== one;\n case 'contains': return (r) => low(get(r)).includes(one);\n case 'not_contains': return (r) => !low(get(r)).includes(one);\n case 'starts_with': return (r) => low(get(r)).startsWith(one);\n case 'ends_with': return (r) => low(get(r)).endsWith(one);\n case 'one_of': return (r) => many.includes(low(get(r)));\n case 'none_of': return (r) => !many.includes(low(get(r)));\n default:\n }\n }\n\n console.warn('[FilterModel] clause uses an operator its field cannot run', op, field.key);\n return () => false;\n }\n\n /** What a group with no children matches, before its NOT. */\n const emptyMatches = (group) => String(group?.op).toUpperCase() !== 'OR' || emptyOr === 'everything';\n\n function compile(node) {\n if (!node) return () => true;\n if (node.kind === 'clause') return compileClause(node);\n if (node.kind !== 'group') {\n console.warn('[FilterModel] cannot run a node of kind', node.kind);\n return () => false;\n }\n const children = (Array.isArray(node.children) ? node.children : []).map(compile);\n const negate = !!node.negate;\n if (!children.length) {\n const result = emptyMatches(node) !== negate;\n return () => result;\n }\n const test = String(node.op || 'AND').toUpperCase() === 'OR'\n ? (row) => children.some((c) => c(row))\n : (row) => children.every((c) => c(row));\n return negate ? (row) => !test(row) : test;\n }\n\n /* Cached by the expression's JSON, so a page may call this once per render or\n * per row without recompiling. Bounded: an editor changes the expression on\n * every keystroke. */\n const cache = new Map();\n function matcherFor(expr) {\n const key = JSON.stringify(expr);\n const hit = cache.get(key);\n if (hit) return hit;\n const fn = compile(expr);\n if (cache.size >= CACHE_MAX) cache.clear();\n cache.set(key, fn);\n return fn;\n }\n const evaluateFilter = (expr, row) => matcherFor(expr)(row);\n\n /* \u2500\u2500 description: \"Status is open AND (Size is s OR Size is m)\" \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n function describeValue(field, op, value, format) {\n if (op.arity === 0) return '';\n const shown = (v) => (format && v !== '' && v !== null && v !== undefined ? format(v, field) : String(v ?? ''));\n if (op.multi) return arr(value).map(shown).join(', ');\n if (op.arity === 2) {\n const [a, b] = arr(value);\n return `${shown(a)} and ${shown(b)}`;\n }\n // Every value of a list, even under an operator that takes one: a saved\n // or foreign condition may hold several, and the sentence must not hide them.\n return Array.isArray(value) ? value.map(shown).join(', ') : shown(value);\n }\n\n function describeNode(node, depth, opts) {\n if (!node) return '';\n if (node.kind === 'clause') {\n const field = byKey.get(node.field);\n const op = catalogue.get(node.op) ?? { label: node.op ?? '', arity: 1 };\n // A field that has gone is SAID, so a filter matching nothing reads\n // as broken, not as empty, and what it asked stays readable.\n const subject = field ? field.label : `\u26A0 unknown field \u201C${unknownName(String(node.field ?? ''))}\u201D`;\n const value = describeValue(field, op, node.value, field ? opts.formatValue : null);\n return [subject, op.label, value].filter(Boolean).join(' ');\n }\n if (node.kind !== 'group') return `\u26A0 ${JSON.stringify(node.node ?? node)}`;\n const parts = (Array.isArray(node.children) ? node.children : [])\n .map((c) => describeNode(c, depth + 1, opts)).filter(Boolean);\n if (!parts.length) return emptyMatches(node) !== !!node.negate ? 'everything' : 'nothing';\n const joined = parts.join(String(node.op || 'AND').toUpperCase() === 'OR' ? ' OR ' : ' AND ');\n const many = parts.length > 1;\n if (opts.groupBrackets) {\n const group = many ? `(${joined})` : joined;\n return node.negate ? `NOT ${group}` : group;\n }\n if (node.negate) return `NOT (${joined})`;\n return depth > 0 && many ? `(${joined})` : joined;\n }\n\n /**\n * One line of words. `formatValue(value, field)` names each value (a key shown\n * as a person's name, say); without it a value is shown as itself. A condition\n * on a field the catalogue does not know says so, with its operator and value,\n * and its value is shown as itself.\n *\n * Brackets go where the sentence would misread without them: a nested group of\n * two or more, and whatever a NOT covers. `groupBrackets` brackets every group of\n * two or more, the root too, and leaves a NOT of one thing unbracketed: `(A AND B)`,\n * `NOT A`, for a surface that reads a group by its brackets.\n */\n const describeFilter = (expr, { formatValue = null, groupBrackets = false } = {}) => (\n describeNode(expr, 0, { formatValue, groupBrackets })\n );\n\n /** The field keys an expression names that the catalogue does not know. */\n function unknownFields(expr) {\n const out = new Set();\n const walk = (n) => {\n if (!n) return;\n if (n.kind === 'clause') {\n if (!byKey.has(n.field)) out.add(n.field);\n } else if (n.kind === 'group') {\n (Array.isArray(n.children) ? n.children : []).forEach(walk);\n }\n };\n walk(expr);\n return [...out];\n }\n\n /* \u2500\u2500 validation: EVERY problem, not the first \u2500\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 function validateClause(node, errors, path) {\n const field = byKey.get(node.field);\n if (!field) {\n errors.push(`${path}: unknown field \"${unknownName(String(node.field ?? ''))}\"`);\n return;\n }\n const op = operatorsFor(field.key).find((o) => o.id === node.op);\n if (!op) {\n errors.push(`${field.label}: \"${node.op}\" is not a valid operator`);\n return;\n }\n if (op.arity === 0) return;\n const say = (what) => errors.push(`${field.label} ${op.label}: ${what}`);\n if (op.multi && (!Array.isArray(node.value) || node.value.length === 0)) {\n say('pick at least one value');\n return;\n }\n const values = op.multi ? node.value : op.arity === 2 ? arr(node.value).slice(0, 2) : [first(node.value)];\n const needed = op.arity === 2 ? 2 : 1;\n if (!op.multi && (values.length < needed || values.some(isBlank))) {\n say(needed === 2 ? 'needs two values' : 'needs a value');\n return;\n }\n if (op.input === 'days') {\n if (!(num(values[0]) > 0)) say('value must be a positive number of days');\n } else if (field.type === 'number') {\n if (values.some((v) => Number.isNaN(num(v)))) say('value must be a number');\n } else if (field.type === 'date') {\n const at = field.time ? instant : day;\n if (values.some((v) => Number.isNaN(at(v)))) {\n say(field.time ? 'value must be a date and time' : 'value must be a date (YYYY-MM-DD)');\n }\n }\n }\n\n function validateNode(node, errors, path) {\n if (!node || typeof node !== 'object') {\n errors.push(`${path}: not an expression node`);\n } else if (node.kind === 'group') {\n if (node.op !== 'AND' && node.op !== 'OR') errors.push(`${path}: group op must be AND or OR`);\n if (!Array.isArray(node.children)) {\n errors.push(`${path}: group children must be an array`);\n return;\n }\n node.children.forEach((c, i) => validateNode(c, errors, `${path}/${i}`));\n } else if (node.kind === 'clause') {\n validateClause(node, errors, path);\n } else {\n errors.push(`${path}: unknown node kind \"${node.kind}\"`);\n }\n }\n\n /** `{ ok, errors }`. An empty group is valid. */\n function validateFilter(expr) {\n const errors = [];\n validateNode(expr, errors, 'expr');\n return { ok: errors.length === 0, errors };\n }\n\n /**\n * What is said of each range in `expr` with one end filled: it is not blank, so\n * `pruneFilter` keeps it, and what it asks (between 5 and nothing) matches nothing.\n */\n function partialRanges(expr) {\n const said = [];\n const walk = (node) => {\n if (node?.kind === 'group') {\n (Array.isArray(node.children) ? node.children : []).forEach(walk);\n return;\n }\n if (node?.kind !== 'clause') return;\n const field = byKey.get(node.field);\n const op = catalogue.get(node.op);\n if (!field || op?.arity !== 2 || op.multi) return;\n const ends = arr(node.value).slice(0, 2);\n const filled = ends.filter((v) => !isBlank(v)).length;\n if (filled === 1) said.push(`${field.label} ${op.label}: needs two values`);\n };\n walk(expr);\n return said;\n }\n\n /* \u2500\u2500 prune: what is left once half-built rows are dropped \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n function prune(node) {\n if (!node || typeof node !== 'object') return null;\n if (node.kind === 'clause') {\n const op = catalogue.get(node.op);\n if (!op || !byKey.has(node.field) || op.arity === 0) return node;\n const blank = Array.isArray(node.value) ? node.value.every(isBlank) : isBlank(node.value);\n return blank ? null : node;\n }\n if (node.kind !== 'group') return node;\n const children = (node.children || []).map(prune).filter(Boolean);\n if (!children.length) return null;\n // A group of one group is the same predicate with a level nobody asked\n // for, so a round trip does not grow a layer each time.\n if (children.length === 1 && children[0].kind === 'group' && !node.negate) return children[0];\n return { ...node, children };\n }\n\n /**\n * A copy with empty groups and conditions with nothing to compare against\n * dropped, or null when nothing is left. A condition this catalogue cannot\n * read, and a carried node, are kept: they were not built here. So is a range\n * with one end filled, which `partialRanges` names: someone meant that.\n */\n const pruneFilter = (expr) => prune(cloneFilter(expr));\n\n return Object.freeze({\n fields, noun, fieldByKey, operatorsFor, operatorById, defaultValue, newClause, moveClause, emptyMatches,\n unknownName, matcherFor, evaluateFilter, describeFilter, validateFilter, unknownFields, pruneFilter,\n partialRanges,\n });\n}\n", "/**\n * tag_input.js \u2014 A LIST OF SHORT STRINGS, drawn as removable chips followed by\n * a text box. (0.17.0)\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n * \u2502 [baseline \u00D7] [stress \u00D7] [q3 \u00D7] Add a tag\u2026 \u2502\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n *\n * The text box commits what was typed \u2014 trimmed, split at commas \u2014 on Enter,\n * on a comma and when it loses focus. Empty pieces are dropped, and so is a\n * piece already in the list unless `allowDuplicates`. Backspace in an empty\n * box removes the last chip. A paste that carries a comma is split into\n * chips at once; a paste without one is ordinary text in the box.\n *\n * Every chip has a remove button with an `aria-label` (`removeLabel(tag)`,\n * \"Remove <tag>\" by default). `readOnly` draws the chips alone: no remove\n * buttons and no text box.\n *\n * `onChange(list)` is called with a fresh copy of the list after every change\n * the reader makes \u2014 never for `setValue`, and never for a commit that added\n * nothing.\n *\n * const tags = createTagInput(host, {\n * value: ['baseline'],\n * placeholder: 'Add a tag\u2026',\n * onChange: (list) => save(list),\n * });\n * tags.getValue(); // ['baseline']\n * tags.setValue(['a', 'b']);\n * tags.dispose();\n *\n * `suggestions` (0.18.0) offers known tags under the box, on `attachInputOptions`:\n * the arrow keys walk the rows, and Enter or a comma takes the active one; with none\n * active they commit what was typed. Whatever the list's source, a row is in the one\n * spelling, says a tag once and is not a tag already in the list. An array is filtered\n * and ordered here, the earliest match first and then alphabetically; a function\n * answers for itself and keeps its own order, and may be async.\n * `normalise` (0.18.0) keeps one spelling of a tag: `Path Finding` and `path-finding`\n * cannot both exist, whichever way one arrives. It is handed the trimmed text.\n */\nimport { attachInputOptions } from './combobox.js';\nimport { shownValue } from './choice_controls.js';\n\nconst optionValue = (o) => (o !== null && typeof o === 'object' ? o.value : o);\n\n/**\n * @typedef {Object} TagInputOptions\n * @property {string[]} [value] - The tags it opens with.\n * @property {string} [placeholder] - The empty text box's placeholder.\n * @property {boolean} [readOnly] - Chips only: no remove buttons, no text box.\n * @property {boolean} [allowDuplicates] - Keep a tag that is already in the list.\n * @property {(list: string[]) => void} [onChange] - After each change the reader makes.\n * @property {string} [label] - The text box's accessible name.\n * @property {(tag: string) => string} [removeLabel] - A remove button's `aria-label`.\n * @property {string} [className] - Extra classes on the root.\n * @property {Array|((query: string, ctx: {signal: AbortSignal}) => Array|Promise<Array>)} [suggestions] -\n * Known tags: strings or `{ value, label?, description?, icon?, hint? }`.\n * @property {(text: string) => string} [normalise] - The one spelling of a tag.\n */\n\n/**\n * @param {HTMLElement} host\n * @param {TagInputOptions} [options]\n */\nexport function createTagInput(host, options = {}) {\n if (!host || typeof host.appendChild !== 'function') {\n throw new Error('[TagInput] host must be an HTMLElement');\n }\n const readOnly = !!options.readOnly;\n const allowDuplicates = !!options.allowDuplicates;\n const removeLabel = typeof options.removeLabel === 'function'\n ? options.removeLabel : (tag) => `Remove ${tag}`;\n const spell = typeof options.normalise === 'function'\n ? (text) => String(options.normalise(text.trim()) ?? '').trim() : (text) => text.trim();\n\n /** The list as spelled, the empty ones left out, and a repeat unless it is allowed. */\n const cleaned = (list) => {\n const out = (Array.isArray(list) ? list : []).map((v) => (v == null ? '' : spell(String(v)))).filter((v) => v !== '');\n return allowDuplicates ? out : [...new Set(out)];\n };\n\n let tags = cleaned(options.value);\n let disposed = false;\n\n const root = document.createElement('div');\n root.className = ['twm-tag-input', readOnly ? 'twm-tag-input--readonly' : '', options.className || '']\n .join(' ').replace(/\\s+/g, ' ').trim();\n root.setAttribute('role', 'group');\n if (options.label) root.setAttribute('aria-label', options.label);\n\n const chips = document.createElement('ul');\n chips.className = 'twm-tag-input__chips';\n root.appendChild(chips);\n\n let input = null;\n if (!readOnly) {\n input = document.createElement('input');\n input.type = 'text';\n input.className = 'twm-tag-input__input';\n input.spellcheck = false;\n input.autocomplete = 'off';\n if (options.placeholder) input.placeholder = options.placeholder;\n if (options.label) input.setAttribute('aria-label', options.label);\n root.appendChild(input);\n }\n\n const changed = () => {\n if (typeof options.onChange === 'function') options.onChange([...tags]);\n };\n\n const chipFor = (tag, idx) => {\n const chip = document.createElement('li');\n chip.className = 'twm-tag-input__chip';\n const text = document.createElement('span');\n text.className = 'twm-tag-input__text';\n text.textContent = tag;\n text.title = tag;\n chip.appendChild(text);\n if (!readOnly) {\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'twm-tag-input__remove';\n remove.setAttribute('aria-label', removeLabel(tag));\n remove.textContent = '\u00D7';\n // The text box keeps the focus: a blur would commit its text\n // and redraw the chips under the pointer before the click.\n remove.addEventListener('mousedown', (ev) => ev.preventDefault());\n remove.addEventListener('click', (ev) => {\n ev.preventDefault();\n ev.stopPropagation();\n removeAt(idx);\n input?.focus();\n });\n chip.appendChild(remove);\n }\n return chip;\n };\n\n /** Redraws every chip. */\n const paint = () => {\n chips.replaceChildren(...tags.map(chipFor));\n };\n\n function removeAt(idx) {\n if (disposed || readOnly || idx < 0 || idx >= tags.length) return;\n tags = tags.filter((_, i) => i !== idx);\n paint();\n changed();\n }\n\n /** Adds the comma-separated pieces of `text`; true when any was added. */\n const commitText = (text) => {\n if (disposed || readOnly) return false;\n const next = [...tags];\n for (const piece of String(text).split(',')) {\n const tag = spell(piece);\n if (tag === '') continue;\n if (!allowDuplicates && next.includes(tag)) continue;\n next.push(tag);\n }\n if (next.length === tags.length) return false;\n // Only the new chips are drawn: the ones already there stay in place,\n // so a remove button that the focus is moving to (Tab out of the box\n // commits its text) is still in the document when the focus lands.\n const added = next.slice(tags.length).map((tag, i) => chipFor(tag, tags.length + i));\n tags = next;\n chips.append(...added);\n changed();\n return true;\n };\n\n /** Known tags as rows: in the one spelling, each once, less those already in the list. */\n const offered = (list) => {\n const seen = new Set();\n const rows = [];\n for (const o of list || []) {\n const tag = spell(shownValue(optionValue(o)));\n if (tag === '' || seen.has(tag) || (!allowDuplicates && tags.includes(tag))) continue;\n seen.add(tag);\n rows.push(o !== null && typeof o === 'object' ? { ...o, value: tag } : tag);\n }\n return rows;\n };\n // What is typed is the query however the list opened: an arrow key or a click\n // reopening it must not offer rows that have nothing to do with the text in the box.\n /** An array of known tags: those holding what is typed, the earliest match first, then alphabetically. */\n const rankedFor = () => {\n const needle = spell(input.value).toLowerCase();\n const word = (o) => shownValue(optionValue(o));\n const at = (o) => word(o).toLowerCase().indexOf(needle);\n return offered(options.suggestions).filter((o) => at(o) >= 0)\n .sort((x, y) => at(x) - at(y) || word(x).localeCompare(word(y)));\n };\n /** A function's answer, whenever it comes. */\n const askedFor = (_query, ctx) => {\n const answer = options.suggestions(input.value, ctx);\n return typeof answer?.then === 'function' ? answer.then(offered) : offered(answer);\n };\n const asking = typeof options.suggestions === 'function';\n\n // Before the box's own keydown listener: a row taken by Enter is not also a commit.\n const menu = input && options.suggestions\n ? attachInputOptions(input, {\n options: asking ? askedFor : rankedFor,\n anchor: root,\n normalise: spell,\n openOnFocus: true,\n passEnter: true,\n debounce: asking ? undefined : 0,\n onPick(option) {\n input.value = '';\n commitText(shownValue(option.value));\n input.focus();\n },\n })\n : null;\n\n const commitInput = () => {\n if (!input) return;\n const text = input.value;\n input.value = '';\n menu?.close();\n commitText(text);\n };\n\n if (input) {\n input.addEventListener('keydown', (ev) => {\n if (ev.isComposing) return;\n if (ev.key === ',' && menu?.takeActive()) {\n ev.preventDefault();\n } else if (ev.key === 'Enter' || ev.key === ',') {\n ev.preventDefault();\n commitInput();\n } else if (ev.key === 'Backspace' && input.value === '' && tags.length) {\n ev.preventDefault();\n removeAt(tags.length - 1);\n }\n });\n // A comma that arrives without its keydown (a soft keyboard, an IME,\n // a drop) commits all the same.\n input.addEventListener('input', () => {\n if (input.value.includes(',')) commitInput();\n });\n input.addEventListener('blur', commitInput);\n input.addEventListener('paste', (ev) => {\n const pasted = ev.clipboardData?.getData('text/plain') ?? '';\n if (!pasted.includes(',')) return;\n ev.preventDefault();\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? start;\n const text = input.value.slice(0, start) + pasted + input.value.slice(end);\n input.value = '';\n commitText(text);\n });\n root.addEventListener('mousedown', (ev) => {\n if (ev.target === root || ev.target === chips) {\n ev.preventDefault();\n input.focus();\n }\n });\n }\n\n paint();\n host.appendChild(root);\n\n return {\n element: root,\n input,\n getValue: () => [...tags],\n /** Replaces the list. Does not call `onChange`. */\n setValue(list) {\n if (disposed) return;\n tags = cleaned(list);\n paint();\n },\n focus() { input?.focus(); },\n dispose() {\n if (disposed) return;\n disposed = true;\n menu?.destroy();\n root.remove();\n },\n };\n}\n", "/**\n * The filter editor: `createFilterBuilder`, mountable anywhere, and\n * `openFilterDialog`, the same builder in a modal with a name, an icon, a\n * consumer's live preview and an async submit.\n *\n * It never decides what a filter MEANS. That is the bound model's\n * (`filter_model.js`); this file only edits the expression and asks the model.\n *\n * Every row closes over the node it edits, so nothing about the expression is\n * kept in the DOM. A STRUCTURAL change (add, remove, field, operator, AND/OR, NOT)\n * redraws the tree and puts the focus back; typing in a value control writes to\n * the node and redraws nothing, so the caret survives.\n *\n * WHAT IT DOES NOT REWRITE. A condition on a field the catalogue does not know, an\n * operator it does not know or its field does not offer, and a node it cannot read\n * stay exactly as they are until someone changes or removes them: the selects show\n * them as their own entry and the value is read-only.\n */\n\nimport { cloneFilter, coerceFilterValue, emptyFilter, filterOptions } from './filter_model.js';\nimport { selectBox } from './choice_controls.js';\nimport { createTagInput } from './tag_input.js';\nimport { openConfirm, openModal } from './modal.js';\n\nconst PREVIEW_DEBOUNCE_MS = 120;\n/** The icon grid's columns; `.twm-filter-dialog__icon-grid` draws the same number. */\nconst ICON_COLUMNS = 8;\nconst SUBMIT = 'submit';\nconst CLEAR = 'clear';\n\nfunction el(tag, className, text) {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text !== undefined && text !== null) node.textContent = String(text);\n return node;\n}\n\nfunction button(className, text, onClick, { title, label } = {}) {\n const node = el('button', className, text);\n node.type = 'button';\n if (title) node.title = title;\n if (label) node.setAttribute('aria-label', label);\n node.addEventListener('click', onClick);\n return node;\n}\n\nconst SELECT_CLASS = 'twm-filter-builder__input twm-filter-builder__select';\nconst INPUT_CLASS = 'twm-filter-builder__input';\nconst SMALL_BUTTON = 'twm-btn twm-filter-builder__add';\nconst REMOVE_BUTTON = 'twm-btn-icon twm-filter-builder__remove';\n\n/** The root is always a group: an expression may legitimately be a bare clause. */\nfunction asRoot(expr) {\n if (!expr || typeof expr !== 'object') return emptyFilter();\n const copy = cloneFilter(expr);\n return copy.kind === 'group' ? copy : { kind: 'group', op: 'AND', children: [copy] };\n}\n\n/**\n * Mount a filter builder.\n *\n * @param {HTMLElement} host\n * @param {object} options\n * @param {object} options.model from `createFilterModel`\n * @param {object} [options.value] the expression to edit (copied)\n * @param {(expr: object) => void} [options.onChange] a copy, after each change\n * @returns {{ el: HTMLElement, getValue(): object, setValue(expr: object): void,\n * validate(): {ok: boolean, errors: string[]}, focus(): void, destroy(): void }}\n */\nexport function createFilterBuilder(host, { model, value = null, onChange = null } = {}) {\n if (!model) throw new Error('[FilterBuilder] needs a filter model');\n const rootEl = el('div', 'twm-filter-builder');\n let root = asRoot(value);\n /** Node to its parent group, for removal; rebuilt by each redraw. */\n let parents = new WeakMap();\n /** Node to its focusable controls by role; rebuilt by each redraw. */\n let controls = new WeakMap();\n /** Each value cell's disposer: a redraw releases what the cells mounted. */\n const cells = new Set();\n\n const changed = () => onChange?.(cloneFilter(root));\n\n const register = (node, role, control) => {\n if (!controls.has(node)) controls.set(node, {});\n controls.get(node)[role] = control;\n };\n\n function redraw(focusNode = null, focusRole = null) {\n for (const cell of cells) cell.dispose();\n cells.clear();\n parents = new WeakMap();\n controls = new WeakMap();\n rootEl.replaceChildren(groupEl(root, true));\n if (focusNode) controls.get(focusNode)?.[focusRole]?.focus();\n }\n\n /** A structural edit: the expression changed shape, so the tree is redrawn. */\n function restructure(focusNode, focusRole) {\n redraw(focusNode, focusRole);\n changed();\n }\n\n /** Remove `node`, and any nested group that leaves empty. Returns the group that remains. */\n function removeNode(node) {\n let gone = node;\n for (;;) {\n const parent = parents.get(gone);\n parent.children.splice(parent.children.indexOf(gone), 1);\n if (parent.children.length || !parents.has(parent)) return parent;\n gone = parent;\n }\n }\n\n const removeButton = (node, label) => button(REMOVE_BUTTON, '\u00D7', () => {\n restructure(removeNode(node), 'addClause');\n }, { title: label, label });\n\n function groupEl(group, isRoot) {\n if (!Array.isArray(group.children)) group.children = [];\n const box = el('div', `twm-filter-builder__group${isRoot ? ' twm-filter-builder__group--root' : ''}`);\n const noun = model.noun;\n\n const head = el('div', 'twm-filter-builder__group-head');\n const seg = el('div', 'twm-filter-builder__seg');\n seg.setAttribute('role', 'group');\n seg.setAttribute('aria-label', 'Match mode');\n for (const op of ['AND', 'OR']) {\n const on = group.op === op;\n const toggle = button(`twm-filter-builder__seg-btn${on ? ' twm-filter-builder__seg-btn--on' : ''}`, op, () => {\n if (group.op === op) return;\n group.op = op;\n restructure(group, op);\n });\n toggle.setAttribute('aria-pressed', String(on));\n register(group, op, toggle);\n seg.appendChild(toggle);\n }\n const not = button(`twm-filter-builder__not${group.negate ? ' twm-filter-builder__not--on' : ''}`, 'NOT', () => {\n if (group.negate) delete group.negate;\n else group.negate = true;\n restructure(group, 'not');\n }, { title: 'Invert this group' });\n not.setAttribute('aria-pressed', String(!!group.negate));\n register(group, 'not', not);\n head.append(seg, not, el('span', 'twm-filter-builder__hint',\n group.op === 'OR' ? 'any condition matches' : 'all conditions match'));\n if (!isRoot) head.appendChild(removeButton(group, 'Remove group'));\n box.appendChild(head);\n\n const children = el('div', 'twm-filter-builder__children');\n for (const child of group.children) {\n parents.set(child, group);\n if (child?.kind === 'group') children.appendChild(groupEl(child, false));\n else if (child?.kind === 'clause') children.appendChild(clauseEl(child));\n else children.appendChild(carriedEl(child));\n }\n if (!group.children.length) {\n const matches = model.emptyMatches(group) !== !!group.negate;\n children.appendChild(el('div', 'twm-filter-builder__empty', matches\n ? `No conditions: this group matches every ${noun}.`\n : `No conditions: this group matches no ${noun}.`));\n }\n box.appendChild(children);\n\n const foot = el('div', 'twm-filter-builder__group-foot');\n const add = (factory, focusRole) => {\n const node = factory();\n if (!node) return;\n group.children.push(node);\n restructure(node, focusRole);\n };\n const offerable = !!model.newClause();\n const addClause = button(SMALL_BUTTON, '+ Condition', () => add(() => model.newClause(), 'field'));\n addClause.disabled = !offerable;\n register(group, 'addClause', addClause);\n // Seeded with one condition: an empty group matches everything, which\n // reads as a mistake the moment it appears.\n const addGroup = button(SMALL_BUTTON, '+ Group', () => add(\n () => ({ kind: 'group', op: 'AND', children: [model.newClause()] }), 'addClause',\n ));\n addGroup.disabled = !offerable;\n foot.append(addClause, addGroup);\n box.appendChild(foot);\n return box;\n }\n\n /** A node the model cannot read: shown as it is and kept as it is. */\n function carriedEl(node) {\n const row = el('div', 'twm-filter-builder__row twm-filter-builder__row--carried');\n const text = el('span', 'twm-filter-builder__carried', model.describeFilter(node));\n text.title = 'This editor cannot draw this condition. It is kept exactly as it is; remove it to drop it.';\n row.append(text, removeButton(node, 'Remove condition'));\n return row;\n }\n\n function fieldChoices(current) {\n const list = [];\n const groups = new Map();\n for (const field of model.fields) {\n if (field.hidden && field.key !== current) continue;\n const option = { value: field.key, label: field.label };\n if (!field.group) {\n list.push(option);\n } else if (groups.has(field.group)) {\n groups.get(field.group).options.push(option);\n } else {\n const entry = { group: field.group, options: [option] };\n groups.set(field.group, entry);\n list.push(entry);\n }\n }\n return list;\n }\n\n function operatorChoices(clause) {\n const offered = model.operatorsFor(clause.field);\n const held = model.operatorById(clause.op);\n const list = held && !offered.includes(held) ? [...offered, held] : offered;\n return list.map((op) => ({ value: op.id, label: op.label }));\n }\n\n function clauseEl(clause) {\n const row = el('div', 'twm-filter-builder__row');\n const known = !!model.fieldByKey(clause.field);\n const unknownWords = `\u26A0 unknown field \u201C${model.unknownName(String(clause.field ?? ''))}\u201D`;\n\n const fieldSelect = selectBox(fieldChoices(clause.field), clause.field, {\n label: 'Field',\n className: `${SELECT_CLASS} twm-filter-builder__select--field${known ? '' : ' twm-filter-builder__select--unknown'}`,\n notFound: () => unknownWords,\n });\n // Its width follows the words, and when the row cannot spare that the\n // tooltip still says the whole name.\n if (!known) fieldSelect.box.title = unknownWords;\n fieldSelect.box.addEventListener('change', () => {\n const next = model.moveClause(clause, fieldSelect.valueOf());\n for (const key of ['op', 'value']) delete clause[key];\n Object.assign(clause, next);\n restructure(clause, 'field');\n });\n register(clause, 'field', fieldSelect.box);\n\n const opSelect = selectBox(operatorChoices(clause), clause.op, {\n label: 'Operator',\n className: `${SELECT_CLASS} twm-filter-builder__select--op`,\n notFound: (id) => `${id} (unknown)`,\n });\n opSelect.box.addEventListener('change', () => {\n clause.op = opSelect.valueOf();\n const fresh = model.defaultValue(model.fieldByKey(clause.field), model.operatorById(clause.op));\n if (fresh === undefined) delete clause.value;\n else clause.value = fresh;\n restructure(clause, 'op');\n });\n register(clause, 'op', opSelect.box);\n\n const cellEl = el('div', 'twm-filter-builder__value');\n const cell = { dispose() {} };\n cells.add(cell);\n const drawCell = (focus = false) => {\n cell.dispose();\n cell.dispose = () => {};\n cellEl.replaceChildren();\n drawValue(clause, cellEl, cell, drawCell);\n if (focus) cellEl.querySelector('select, input')?.focus();\n };\n drawCell();\n\n row.append(fieldSelect.box, opSelect.box, cellEl, removeButton(clause, 'Remove condition'));\n return row;\n }\n\n function drawValue(clause, cellEl, cell, drawCell) {\n const field = model.fieldByKey(clause.field);\n const op = model.operatorById(clause.op);\n // A box drawn for an operator it was not made for would show nothing, or\n // a field's own type, over a value that is still what Apply returns.\n if (!field || !op || (op.arity && !model.operatorsFor(clause.field).includes(op))) {\n if (clause.value !== undefined) {\n cellEl.appendChild(el('span', 'twm-filter-builder__carried', JSON.stringify(clause.value)));\n }\n return;\n }\n if (!op.arity) return;\n\n const write = (next) => {\n clause.value = next;\n changed();\n };\n const custom = field.editor?.({ field, op, value: clause.value, label: field.label, onChange: write });\n if (custom) {\n cellEl.appendChild(custom.el);\n cell.dispose = () => custom.destroy?.();\n return;\n }\n\n if (op.multi) {\n if (filterOptions(field).length) drawChosenOptions(clause, field, cellEl, drawCell, write);\n else drawTags(clause, field, cellEl, cell, write);\n return;\n }\n if (op.arity === 2) {\n const pair = Array.isArray(clause.value) ? [...clause.value] : ['', ''];\n const box = (i) => scalarInput(field, op, pair[i], (v) => {\n pair[i] = v;\n write([...pair]);\n });\n cellEl.append(box(0), el('span', 'twm-filter-builder__and', 'and'), box(1));\n return;\n }\n const options = field.type === 'enum' ? filterOptions(field) : [];\n if (options.length) {\n const choice = selectBox(options, clause.value, {\n label: field.label,\n className: `${SELECT_CLASS} twm-filter-builder__select--value`,\n notFound: (v) => `${v} (unknown)`,\n });\n // A select cannot show \"nothing\": what it holds is the honest value.\n if (clause.value === undefined || clause.value === null || clause.value === '') {\n clause.value = choice.valueOf();\n }\n choice.box.addEventListener('change', () => write(choice.valueOf()));\n cellEl.appendChild(choice.box);\n return;\n }\n cellEl.appendChild(scalarInput(field, op, Array.isArray(clause.value) ? clause.value[0] : clause.value, write));\n if (op.input === 'days') cellEl.appendChild(el('span', 'twm-filter-builder__and', 'days'));\n }\n\n function scalarInput(field, op, current, write) {\n const input = el('input', INPUT_CLASS);\n const numeric = field.type === 'number' || op.input === 'days';\n if (numeric) {\n input.type = 'number';\n input.step = 'any';\n if (op.input === 'days') input.min = '0';\n } else if (field.type === 'date') {\n input.type = field.time ? 'datetime-local' : 'date';\n } else {\n input.type = 'text';\n input.placeholder = 'value\u2026';\n }\n input.setAttribute('aria-label', field.label);\n input.value = current ?? '';\n const type = numeric ? { type: 'number' } : field;\n input.addEventListener('input', () => write(coerceFilterValue(type, input.value)));\n return input;\n }\n\n function asList(value) {\n if (Array.isArray(value)) return value;\n return value === '' || value === null || value === undefined ? [] : [value];\n }\n\n /** Free values, as tags. */\n function drawTags(clause, field, cellEl, cell, write) {\n const tags = createTagInput(cellEl, {\n value: asList(clause.value).map(String),\n placeholder: 'value\u2026',\n label: field.label,\n className: 'twm-filter-builder__tags',\n onChange: (list) => write(list.map((v) => coerceFilterValue(field, v))),\n });\n cell.dispose = () => tags.dispose();\n }\n\n /** Values from a fixed list: the chosen as chips, and a select of what is left. */\n function drawChosenOptions(clause, field, cellEl, drawCell, write) {\n const options = filterOptions(field);\n const chosen = asList(clause.value);\n const labelOf = (v) => options.find((o) => o.value === v)?.label ?? String(v);\n const box = el('div', 'twm-filter-builder__chosen');\n chosen.forEach((v, i) => {\n const chip = el('span', 'twm-filter-builder__chip', labelOf(v));\n chip.appendChild(button('twm-filter-builder__chip-remove', '\u00D7', () => {\n write(chosen.filter((_, at) => at !== i));\n drawCell(true);\n }, { label: `Remove ${labelOf(v)}` }));\n box.appendChild(chip);\n });\n const rest = options.filter((o) => !chosen.includes(o.value));\n if (rest.length) {\n const adder = selectBox(rest, undefined, {\n empty: '+ value',\n keepMissing: false,\n label: `Add a value to ${field.label}`,\n className: `${SELECT_CLASS} twm-filter-builder__select--add`,\n });\n adder.box.addEventListener('change', () => {\n const next = adder.valueOf();\n if (next === undefined) return;\n write([...chosen, next]);\n drawCell(true);\n });\n box.appendChild(adder.box);\n }\n cellEl.appendChild(box);\n }\n\n redraw();\n host.appendChild(rootEl);\n\n return {\n el: rootEl,\n getValue: () => cloneFilter(root),\n /** Replaces the expression. Does not call `onChange`. */\n setValue(expr) {\n root = asRoot(expr);\n redraw();\n },\n validate: () => model.validateFilter(root),\n focus() { rootEl.querySelector('select, input, button')?.focus(); },\n destroy() {\n for (const cell of cells) cell.dispose();\n cells.clear();\n rootEl.remove();\n },\n };\n}\n\n/** The dialog's icon choice: a button over a searchable grid. */\nfunction createIconPicker({ value, options, onChange }) {\n let current = value;\n const root = el('div', 'twm-filter-dialog__icon');\n const glyph = (name) => el('span', 'material-symbols-outlined', name);\n const trigger = button('twm-btn twm-filter-dialog__icon-trigger', null, () => (pop.hidden ? open() : close()), {\n title: 'Icon', label: 'Icon',\n });\n trigger.setAttribute('aria-haspopup', 'listbox');\n trigger.setAttribute('aria-expanded', 'false');\n const face = glyph(current);\n trigger.appendChild(face);\n\n const pop = el('div', 'twm-filter-dialog__icon-pop');\n pop.hidden = true;\n const search = el('input', `${INPUT_CLASS} twm-filter-dialog__icon-search`);\n search.type = 'text';\n search.placeholder = 'Search icons\u2026';\n search.setAttribute('aria-label', 'Search icons');\n const grid = el('div', 'twm-filter-dialog__icon-grid');\n grid.setAttribute('role', 'listbox');\n grid.setAttribute('aria-label', 'Icon');\n const none = el('div', 'twm-filter-dialog__icon-none', 'No icon matches.');\n pop.append(search, grid, none);\n root.append(trigger, pop);\n\n const pick = (name) => {\n current = name;\n face.textContent = name;\n close();\n onChange(name);\n };\n const drawGrid = () => {\n const query = search.value.trim().toLowerCase();\n const list = query ? options.filter((n) => n.toLowerCase().includes(query)) : options;\n none.hidden = list.length > 0;\n grid.replaceChildren(...list.map((name) => {\n const on = name === current;\n const option = button(`twm-filter-dialog__icon-option${on ? ' twm-filter-dialog__icon-option--on' : ''}`,\n null, () => pick(name), { title: name });\n option.setAttribute('role', 'option');\n option.setAttribute('aria-selected', String(on));\n option.appendChild(glyph(name));\n return option;\n }));\n };\n function open() {\n search.value = '';\n drawGrid();\n pop.hidden = false;\n trigger.setAttribute('aria-expanded', 'true');\n search.focus();\n }\n function close(refocus = true) {\n if (pop.hidden) return;\n pop.hidden = true;\n trigger.setAttribute('aria-expanded', 'false');\n if (refocus) trigger.focus();\n }\n\n search.addEventListener('input', drawGrid);\n search.addEventListener('keydown', (e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n grid.firstElementChild?.focus();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n grid.firstElementChild?.click();\n }\n });\n grid.addEventListener('keydown', (e) => {\n const items = [...grid.children];\n const at = items.indexOf(e.target.closest('button'));\n if (at < 0) return;\n const step = { ArrowRight: 1, ArrowLeft: -1, ArrowDown: ICON_COLUMNS, ArrowUp: -ICON_COLUMNS }[e.key];\n if (step === undefined) return;\n e.preventDefault();\n if (at + step < 0 && e.key === 'ArrowUp') search.focus();\n else items[at + step]?.focus();\n });\n // The window answers an Esc nobody else has: this one closes only the grid.\n pop.addEventListener('keydown', (e) => {\n if (e.key !== 'Escape') return;\n e.preventDefault();\n close();\n });\n\n return { el: root, close, value: () => current };\n}\n\n/**\n * Open the builder in a modal.\n *\n * @param {object} options\n * @param {object} options.model from `createFilterModel`\n * @param {object} [options.value] the expression to edit (copied; Cancel is lossless)\n * @param {string} [options.seedField] a field key: a new empty condition on it is\n * added, so \"filter by this\" lands on a form about that field. Beside a negated\n * root, not inside it: a new condition narrows what the filter already says.\n * @param {string} [options.title]\n * @param {string} [options.icon] the window's icon\n * @param {HTMLElement} [options.head] drawn above the conditions\n * @param {{value?: string, label?: string, placeholder?: string, required?: boolean}} [options.name]\n * adds a name box, which opens with its text selected; the result carries `name`\n * @param {{value?: string, options: string[]}} [options.iconChoice]\n * adds an icon picker over those Material Symbols names; the result carries `icon`\n * @param {(host: HTMLElement, state: {expr: object, sentence: string, signal: AbortSignal}) => void} [options.preview]\n * the live preview: draws into `host` on open and, debounced, after each change\n * while the expression can be submitted. `signal` aborts when this drawing is\n * superseded or the dialog closes, for a preview that asks a server.\n * @param {boolean} [options.requireValid] submit only a valid expression (default\n * true); its errors are listed. False lets one with an unknown field through. A\n * range with one end filled is refused either way (`model.partialRanges`).\n * @param {boolean} [options.prune] drop half-built rows from what is validated,\n * previewed and submitted (`model.pruneFilter`); `expr` is null when nothing is left\n * @param {boolean} [options.confirmDiscard] ask before closing with unsaved changes\n * @param {boolean} [options.dismissOnBackdrop] a click on the dimmed page beside the\n * dialog dismisses it, as Esc does (`confirmDiscard` still asks)\n * @param {string} [options.submitLabel]\n * @param {(result: object) => any} [options.onSubmit] may be async: until it settles\n * every button is off and Esc and the X do nothing, so the answer is what happened.\n * If it throws, the dialog shows the error and stays.\n * @param {string} [options.clearLabel] adds a button answering `{ action: 'clear', expr: null }`\n * @param {Array<{label: string, value: string, danger?: boolean, icon?: string,\n * confirm?: object, run?: (result: object) => any}>} [options.actions]\n * more buttons, before Cancel. `confirm` is `openConfirm`'s options, asked first; its\n * `message` may be `(result) => string`, computed when it is asked, so it can quote\n * what was typed. `run` is like `onSubmit`.\n * @param {number} [options.width]\n * @param {number} [options.height]\n * @returns {Promise<{action: string, expr: object|null, name?: string, icon?: string}|null>}\n * null when dismissed\n */\nexport async function openFilterDialog({\n model, value = null, seedField = null, title = 'Filter', icon = 'filter_alt', head = null,\n name = null, iconChoice = null, preview = null,\n requireValid = true, prune = false, confirmDiscard = false, dismissOnBackdrop = false,\n submitLabel = 'Apply', onSubmit = null, clearLabel = null, actions = [],\n width = preview ? 920 : 760, height = 560,\n} = {}) {\n if (!model) throw new Error('[FilterDialog] needs a filter model');\n\n let start = asRoot(value);\n const seeded = seedField ? model.newClause(seedField) : null;\n if (seeded) {\n if (start.negate) start = { kind: 'group', op: 'AND', children: [start, seeded] };\n else start.children.push(seeded);\n }\n\n const content = el('div', 'twm-filter-dialog');\n if (head) content.appendChild(head);\n\n let picker = null;\n let nameInput = null;\n if (name || iconChoice) {\n const row = el('div', 'twm-filter-dialog__identity');\n if (name) {\n const label = el('label', 'twm-filter-dialog__name');\n label.appendChild(el('span', 'twm-filter-dialog__name-label', name.label ?? 'Name'));\n nameInput = el('input', INPUT_CLASS);\n nameInput.type = 'text';\n nameInput.autocomplete = 'off';\n nameInput.value = name.value ?? '';\n if (name.placeholder) nameInput.placeholder = name.placeholder;\n nameInput.addEventListener('input', refresh);\n label.appendChild(nameInput);\n row.appendChild(label);\n }\n if (iconChoice) {\n picker = createIconPicker({\n value: iconChoice.value ?? iconChoice.options[0],\n options: iconChoice.options,\n onChange: refresh,\n });\n row.appendChild(picker.el);\n content.addEventListener('mousedown', (e) => {\n if (!picker.el.contains(e.target)) picker.close(false);\n });\n }\n content.appendChild(row);\n }\n\n const columns = el('div', 'twm-filter-dialog__columns');\n const buildPane = el('section', 'twm-filter-dialog__pane twm-filter-dialog__pane--build');\n columns.appendChild(buildPane);\n content.appendChild(columns);\n\n const errorsEl = el('ul', 'twm-filter-dialog__errors');\n errorsEl.hidden = true;\n const failureEl = el('div', 'twm-filter-dialog__failure');\n failureEl.setAttribute('role', 'alert');\n failureEl.hidden = true;\n\n let sentenceEl = null;\n let slot = null;\n if (preview) {\n const pane = el('section', 'twm-filter-dialog__pane twm-filter-dialog__pane--preview');\n sentenceEl = el('div', 'twm-filter-dialog__sentence');\n slot = el('div', 'twm-filter-dialog__preview');\n pane.append(sentenceEl, errorsEl, slot);\n columns.appendChild(pane);\n }\n\n let previewTimer = 0;\n let previewRun = null;\n let controls = null;\n let busy = false;\n\n const builder = createFilterBuilder(buildPane, {\n model,\n value: start,\n onChange: () => {\n refresh();\n clearTimeout(previewTimer);\n previewTimer = setTimeout(drawPreview, PREVIEW_DEBOUNCE_MS);\n },\n });\n if (!preview) buildPane.appendChild(errorsEl);\n content.appendChild(failureEl);\n\n /** The expression as it would be submitted. */\n function current() {\n const expr = builder.getValue();\n return prune ? model.pruneFilter(expr) : expr;\n }\n /** Why `expr` may not be submitted. */\n const refusals = (expr) => {\n if (!expr) return [];\n return requireValid ? model.validateFilter(expr).errors : model.partialRanges(expr);\n };\n\n const nameMissing = () => !!nameInput && name.required !== false && !nameInput.value.trim();\n const canSubmit = () => !busy && !nameMissing() && !refusals(current()).length;\n\n function refresh() {\n if (!controls) return;\n for (const { value } of modalActions) {\n controls.setActionEnabled(value, value === SUBMIT ? canSubmit() : !busy);\n }\n }\n\n function showErrors(errors) {\n errorsEl.replaceChildren(...errors.map((message) => el('li', '', message)));\n errorsEl.hidden = errors.length === 0;\n }\n function showFailure(message) {\n failureEl.textContent = message;\n failureEl.hidden = !message;\n }\n\n function drawPreview() {\n const expr = current();\n const errors = refusals(expr);\n previewRun?.abort();\n previewRun = null;\n const blocked = errors.length > 0;\n showErrors(errors);\n if (!preview) return;\n slot.hidden = blocked;\n if (blocked) {\n sentenceEl.textContent = '';\n slot.replaceChildren();\n return;\n }\n const shown = expr ?? emptyFilter();\n const sentence = model.describeFilter(shown);\n sentenceEl.textContent = sentence;\n previewRun = new AbortController();\n try {\n preview(slot, { expr: shown, sentence, signal: previewRun.signal });\n } catch (err) {\n showFailure(`Preview failed: ${err?.message ?? err}`);\n }\n }\n\n const snapshot = () => JSON.stringify([builder.getValue(), nameInput?.value ?? null, picker?.value() ?? null]);\n const initial = snapshot();\n\n /**\n * May the dialog close without an answer? Not while an action is in flight:\n * the caller would hear \"dismissed\" about a save that then completes, or\n * never see the error of one that fails. Otherwise, not without asking if\n * that loses what was typed.\n */\n function mayDiscard() {\n if (busy) return false;\n if (!confirmDiscard || snapshot() === initial) return true;\n return openConfirm({\n title: 'Discard changes?',\n message: 'This filter has unsaved changes. Closing now throws them away.',\n confirmLabel: 'Discard',\n cancelLabel: 'Keep editing',\n danger: true,\n });\n }\n\n async function runAction(action, close) {\n if (busy || (action.value === SUBMIT && !canSubmit())) return;\n showFailure('');\n busy = true;\n try {\n const result = { action: action.value, expr: action.value === CLEAR ? null : current() };\n if (nameInput) result.name = nameInput.value.trim();\n if (picker) result.icon = picker.value();\n // Its question stacks over this window, so the buttons stay as they\n // are until it is answered and focus has a button to come back to.\n if (action.confirm) {\n const { message } = action.confirm;\n const asked = typeof message === 'function' ? { ...action.confirm, message: message(result) } : action.confirm;\n if (!await openConfirm(asked)) return;\n }\n refresh();\n await action.run?.(result);\n close(result);\n } catch (err) {\n showFailure(err?.message ?? String(err));\n } finally {\n busy = false;\n refresh();\n }\n }\n const asModalAction = (action) => ({\n ...action,\n keepOpen: true,\n onClick: (close) => runAction(action, close),\n });\n\n const modalActions = [\n ...actions.map(asModalAction),\n {\n label: 'Cancel',\n value: 'cancel',\n keepOpen: true,\n onClick: async (close) => { if (await mayDiscard()) close(null); },\n },\n ];\n if (clearLabel) modalActions.push(asModalAction({ label: clearLabel, value: CLEAR }));\n modalActions.push({\n ...asModalAction({ label: submitLabel, value: SUBMIT, run: onSubmit }),\n primary: true,\n disabled: !canSubmit(),\n });\n\n const closed = openModal({\n title,\n icon,\n content,\n actions: modalActions,\n width,\n height,\n maximizable: true,\n beforeClose: mayDiscard,\n dismissOnBackdrop,\n onMount: (_body, modalControls) => {\n controls = modalControls;\n refresh();\n // Editing a name usually means replacing it, and \" (copy)\" always does.\n nameInput?.focus();\n nameInput?.select();\n },\n });\n drawPreview();\n\n try {\n return await closed;\n } finally {\n clearTimeout(previewTimer);\n previewRun?.abort();\n builder.destroy();\n }\n}\n", "/**\n * gallery_picker.js \u2014 single-select card grid for the starter catalog.\n *\n * G1.3 in docs/STARTER_GALLERY_REQUIREMENTS.md. Used by every\n * \"New X\" modal to let the user pick a starter shape (formerly\n * called a \"template\"). The picker is mounted into a host element\n * and fires `onChange(entry)` whenever the selection changes.\n *\n * The entries come from `opts.entries`, or else from the host's optional\n * `gallery` capability (`host.gallery.list(kind)`, see host.js). Each entry is\n *\n * { id, kind, label, description, fields }\n *\n * The picker shows label + description as a card. `fields` is\n * passed through to the caller untouched on select \u2014 the New-X\n * handler decides what to do with it.\n *\n * Usage:\n *\n * const picker = await mountGalleryPicker(hostEl, {\n * host, // or entries: [...]\n * kind: 'agent',\n * selectedId: 'blank',\n * onChange: (entry) => { \u2026 },\n * });\n *\n * // later \u2026\n * picker.getSelected(); // \u2192 { id, kind, label, description, fields }\n * picker.dispose();\n */\n\nfunction esc(s) {\n return String(s ?? '').replace(/[&<>\"']/g, (c) => ({\n '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;',\n }[c]));\n}\n\n\n/**\n * Mount a starter-gallery picker into `hostEl`.\n *\n * @param {HTMLElement} hostEl\n * @param {object} opts\n * @param {string} opts.kind \u2014 gallery entries to load (e.g. 'agent').\n * When undefined, every kind shows up.\n * @param {string} [opts.selectedId] \u2014 id to pre-select. If absent, the\n * first entry wins.\n * @param {function} [opts.onChange] \u2014 `(entry) => void` fired on selection\n * change AND on initial mount.\n * @param {object[]} [opts.entries] \u2014 explicit entries (the host is not asked).\n * @param {object} [opts.host] \u2014 a Host; its `gallery.list(kind)` supplies\n * the entries when `entries` is absent.\n * With neither, the picker shows\n * `emptyLabel` and warns once.\n * @param {string} [opts.emptyLabel] \u2014 copy shown when the catalog is empty\n * for that kind.\n * @returns {Promise<{getSelected, setSelectedById, dispose}>}\n */\nexport async function mountGalleryPicker(hostEl, opts = {}) {\n const {\n kind = null,\n selectedId = null,\n onChange = () => {},\n entries = null,\n host = null,\n emptyLabel = 'No starters available for this kind.',\n } = opts;\n if (!hostEl) throw new Error('mountGalleryPicker: hostEl is required');\n\n let catalog = entries;\n if (!catalog) {\n const list = host?.gallery?.list;\n if (typeof list !== 'function') {\n console.warn('[gallery-picker] no entries and no host gallery capability; showing the empty label');\n catalog = [];\n } else {\n try {\n catalog = (await list(kind)) || [];\n } catch (err) {\n console.warn('[gallery-picker] host.gallery.list failed', err);\n catalog = [];\n }\n }\n }\n catalog = Array.isArray(catalog) ? catalog : [];\n\n hostEl.classList.add('twm-gallery-picker');\n if (catalog.length === 0) {\n hostEl.innerHTML = `<div class=\"twm-gallery-picker__empty\">${esc(emptyLabel)}</div>`;\n return {\n getSelected: () => null,\n setSelectedById: () => false,\n dispose: () => { hostEl.classList.remove('twm-gallery-picker'); },\n };\n }\n\n let selected = catalog.find((e) => e?.id === selectedId)\n || catalog[0];\n\n const render = () => {\n hostEl.innerHTML = catalog.map((e, i) => {\n const isSel = e === selected;\n const desc = e?.description\n ? `<p class=\"twm-gallery-card__desc\">${esc(e.description)}</p>`\n : '';\n return `\n <button type=\"button\"\n class=\"twm-gallery-card ${isSel ? 'is-selected' : ''}\"\n data-idx=\"${i}\"\n title=\"${esc(e?.id || '')}\">\n <span class=\"twm-gallery-card__label\">${esc(e?.label || e?.id || '')}</span>\n ${desc}\n </button>\n `;\n }).join('');\n };\n render();\n\n const onClick = (ev) => {\n const card = ev.target.closest?.('.twm-gallery-card');\n if (!card || !hostEl.contains(card)) return;\n const idx = Number(card.dataset.idx);\n const next = catalog[idx];\n if (!next || next === selected) return;\n selected = next;\n render();\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] onChange threw', err);\n }\n };\n hostEl.addEventListener('click', onClick);\n\n // Fire the initial selection so the caller can prime any\n // downstream UI (preview pane, defaults, etc.) without a\n // special case for first-render.\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] initial onChange threw', err);\n }\n\n return {\n getSelected: () => (selected ? { ...selected } : null),\n setSelectedById: (id) => {\n const next = catalog.find((e) => e?.id === id);\n if (!next || next === selected) return false;\n selected = next;\n render();\n try { onChange(selected); } catch (err) {\n console.warn('[gallery-picker] onChange threw', err);\n }\n return true;\n },\n dispose: () => {\n hostEl.removeEventListener('click', onClick);\n hostEl.innerHTML = '';\n hostEl.classList.remove('twm-gallery-picker');\n },\n };\n}\n", "/**\n * Notification Center (js_new)\n *\n * Purpose\n * -------\n * Unified notifications/toasts/status-line controller consuming events from the rest of the app.\n *\n * Responsibilities\n * - Render queued notifications with namespace context and severity.\n * - Ingest `log:*` and domain-specific events to present user-facing feedback.\n * - Replace scattered `window.notify` / `status_view.js` hooks.\n *\n * Source Material\n * - html/js/status_view.js and ui_manager.js toast helpers.\n * - html/js/ui_utilities.js notification utilities.\n *\n * Progress toasts (0.17.0)\n * ------------------------\n * `show({ progress })` makes a toast that tracks a job: `progress` is a 0..1\n * fraction, `{ value, total }`, or `null` for indeterminate; `status` is a line\n * under the message and `counts` a label beside the bar. Such a toast is\n * persistent and collapsible, and it RUNS until `update()` gives it an outcome\n * severity (success, error or fatal), which ends its bar (done or error) for\n * good and lets a `durationMs` in the same patch dismiss it. Every toast is\n * drawn once and then patched: `update()` touches only its own nodes, and a\n * toast arriving or leaving moves no other toast's element, so a bar, a\n * collapsed state and a hovered button survive. A running progress toast is\n * never held behind \"+N more\" (and never dropped by 'drop'); it counts toward\n * `maxVisible`, so it takes the place of the newest other toast.\n *\n * History subscribers (0.17.3)\n * ----------------------------\n * `history` holds one entry per toast, whichever way it came (`show()`, the\n * `warn()`/`error()`/... helpers, `toast:show`, `notification:show`,\n * `log:entry`). A toast that leaves marks its own entry `dismissed` with a\n * `reason`; it adds none. `subscribe(fn)` calls `fn(entry, center)` for each\n * entry added, so a history view follows the centre rather than the bus.\n *\n * Copy message (STORY-0131)\n * -------------------------\n * A right-click on a toast, or on its entry in the history, opens the context\n * menu with \"Copy message\": the title, the message and the description, one\n * per line, go to the clipboard as plain text. The text is also selectable:\n * a click on the title, message, description or status, or one that ends a\n * selection, does not close the toast; only a click on its chrome does.\n */\nimport { ComponentBase } from './base/component_base.js';\nimport { getSetting } from '../core/settings.js';\nimport { setToastBus, getToastBus } from './components/toast.js';\nimport { ProgressBar } from './components/progress.js';\nimport { showContextMenu } from './components/context_menu.js';\n\nconst SEVERITIES = ['info', 'success', 'warn', 'error', 'fatal'];\n\n/** The severity a progress toast finishes with, and the state its bar ends in. */\nconst OUTCOME_BAR_STATE = Object.freeze({ success: 'done', error: 'error', fatal: 'error' });\nconst LOG_SEVERITY_MAP = {\n trace: 'info',\n debug: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n fatal: 'fatal',\n};\n\nconst DEFAULT_LOG_LEVELS = new Set(['warn', 'error', 'fatal']);\n\n// Internal namespace identifiers that should not be shown as toast titles.\n// Messages from these namespaces are self-descriptive and need no category header.\nconst SUPPRESSED_NAMESPACE_TITLES = new Set(['bootstrap', 'app']);\n\n/** A notification as plain text: its title, message and description, one per line. */\nexport function notificationText(notification) {\n return [notification.title, notification.message, notification.description]\n .filter((part) => part != null && String(part) !== '')\n .join('\\n');\n}\n\n/**\n * The right-click menu of a toast or a history entry: \"Copy message\". It takes\n * the right-click, so the browser's own menu does not open.\n */\nexport function showNotificationMenu(event, notification, logger) {\n event.preventDefault();\n event.stopPropagation();\n showContextMenu(event.clientX, event.clientY,\n [{ label: 'Copy message', icon: 'content_copy', action: 'copy' }],\n () => {\n Promise.resolve()\n .then(() => navigator.clipboard.writeText(notificationText(notification)))\n .catch((err) => logger?.warn?.('twm-notification-center', 'Copy message failed', { err }));\n });\n}\n\n/** The toast's text: clicking it selects, it does not dismiss. */\nconst TOAST_TEXT = '.twm-notification__title, .twm-notification__body, '\n + '.twm-notification__description, .twm-notification__status';\n\n/** A non-empty text selection inside `el`: a click that ends one is not a click on it. */\nfunction selectsTextIn(el) {\n const sel = el.ownerDocument.getSelection?.();\n return Boolean(sel && !sel.isCollapsed && sel.rangeCount && el.contains(sel.getRangeAt(0).commonAncestorContainer));\n}\n\nexport class NotificationCenter extends ComponentBase {\n #items;\n #summaryEl;\n #historyListeners;\n\n constructor({\n eventBus,\n logger,\n maxVisible = 3,\n historyLimit = 50,\n defaultDurationMs = 6000,\n logLevels = DEFAULT_LOG_LEVELS,\n // What happens past `maxVisible`. 'drop' (the default, as before 0.11):\n // the oldest toast leaves. 'collapse': the toasts on screen stay, the\n // rest wait behind one \"+N more\" toast, and each comes in as one closes\n // \u2014 a sticky alert nobody has read is never pushed off unseen.\n overflow = 'drop',\n // Called with the held-back toasts when the \"+N more\" toast is clicked.\n summaryAction = null,\n } = {}) {\n super({ eventBus, logger });\n\n this.maxVisible = maxVisible;\n this.overflow = overflow === 'collapse' ? 'collapse' : 'drop';\n this.summaryAction = typeof summaryAction === 'function' ? summaryAction : null;\n /** Toasts waiting behind the \"+N more\" summary ('collapse' only), oldest first. */\n this.held = [];\n this.historyLimit = historyLimit;\n this.defaultDurationMs = defaultDurationMs;\n this.logLevels = new Set(logLevels ?? DEFAULT_LOG_LEVELS);\n\n this.notifications = [];\n this.history = [];\n this.sequence = 0;\n this.activeTimers = new Map();\n this.eventDisposers = [];\n /** id -> the drawn toast's nodes, for the toasts on screen. */\n this.#items = new Map();\n this.#summaryEl = null;\n this.#historyListeners = new Set();\n\n this.container = null;\n this.rootEl = null;\n this.listEl = null;\n this.liveRegionEl = null;\n }\n\n mount(container, props = {}) {\n // Always mount to document.body for reliable visibility\n // The passed container is ignored - we create our own fixed-position container\n const existingContainer = document.getElementById('notification-center-root');\n if (existingContainer) {\n this.container = existingContainer;\n this.rootEl = existingContainer.querySelector('.twm-notification-center');\n this.listEl = existingContainer.querySelector('.twm-notification-center__list');\n this.liveRegionEl = existingContainer.querySelector('.twm-notification-center__live-region');\n this._mounted = true;\n this.#subscribeEvents();\n this.#claimToastBus();\n return this;\n }\n\n // Create a new fixed-position container directly on body\n this.container = document.createElement('div');\n this.container.id = 'notification-center-root';\n this.container.style.cssText = 'position: fixed; right: 16px; bottom: 24px; z-index: 10000; pointer-events: none;';\n\n this.rootEl = document.createElement('div');\n this.rootEl.className = 'twm-notification-center';\n\n this.listEl = document.createElement('div');\n this.listEl.className = 'twm-notification-center__list';\n\n this.liveRegionEl = document.createElement('div');\n this.liveRegionEl.className = 'twm-notification-center__live-region';\n this.liveRegionEl.setAttribute('aria-live', 'polite');\n this.liveRegionEl.setAttribute('aria-atomic', 'true');\n this.liveRegionEl.style.position = 'absolute';\n this.liveRegionEl.style.width = '1px';\n this.liveRegionEl.style.height = '1px';\n this.liveRegionEl.style.overflow = 'hidden';\n this.liveRegionEl.style.clip = 'rect(1px, 1px, 1px, 1px)';\n\n this.rootEl.appendChild(this.listEl);\n this.rootEl.appendChild(this.liveRegionEl);\n this.container.appendChild(this.rootEl);\n document.body.appendChild(this.container);\n\n this._mounted = true;\n this.#subscribeEvents();\n this.#claimToastBus();\n\n if (Array.isArray(props.initialNotifications)) {\n props.initialNotifications.forEach((notification) => this.show(notification));\n }\n return this;\n }\n\n dispose() {\n this.#clearTimers();\n this.#unsubscribeEvents();\n this.#historyListeners.clear();\n // Give the toast helpers back to the console \u2014 unless someone has\n // pointed them at another bus since this centre mounted.\n if (this.eventBus && getToastBus() === this.eventBus) setToastBus(null);\n this.#items.forEach((entry) => entry.bar?.dispose());\n this.#items.clear();\n this.#summaryEl = null;\n if (this.rootEl?.parentNode) {\n this.rootEl.parentNode.removeChild(this.rootEl);\n }\n this.container = null;\n this.rootEl = null;\n this.listEl = null;\n this.liveRegionEl = null;\n super.dispose();\n }\n\n show(notification) {\n const normalized = this.#normalizeNotification(notification);\n this.#consoleLog(normalized);\n const running = NotificationCenter.#isRunning(normalized);\n if (this.overflow === 'collapse' && !running && this.notifications.length >= this.maxVisible) {\n // Held, not shown: its timer starts when it comes on screen.\n this.held.push(normalized);\n this.#recordHistory(normalized);\n this.#render();\n this.#announce(normalized);\n return normalized.id;\n }\n this.notifications.push(normalized);\n if (this.overflow === 'collapse') {\n // Only a running progress toast gets here past the limit: the\n // newest other toast steps back behind \"+N more\" to make room.\n this.#rebalance();\n } else if (this.notifications.length > this.maxVisible) {\n // The oldest leaves \u2014 but never a running progress toast.\n const idx = this.notifications.findIndex((item) => !NotificationCenter.#isRunning(item));\n if (idx !== -1) {\n const [removed] = this.notifications.splice(idx, 1);\n this.#stopTimer(removed.id);\n this.#recordDismissal(removed, 'overflow');\n }\n }\n\n this.#recordHistory(normalized);\n this.#scheduleAutoDismiss(normalized);\n this.#render();\n this.#announce(normalized);\n return normalized.id;\n }\n\n dismiss(notificationId, reason = 'dismissed') {\n const idx = this.notifications.findIndex((item) => item.id === notificationId);\n if (idx === -1) {\n const h = this.held.findIndex((item) => item.id === notificationId);\n if (h === -1) return false;\n const [gone] = this.held.splice(h, 1);\n this.#recordDismissal(gone, reason);\n this.#render();\n return true;\n }\n const [removed] = this.notifications.splice(idx, 1);\n this.#stopTimer(notificationId);\n this.#recordDismissal(removed, reason);\n // A place on screen came free: the oldest held-back toast takes it.\n this.#rebalance();\n this.#render();\n return true;\n }\n\n /**\n * Change a notification in place: only its own nodes are touched, and no\n * other toast is redrawn. A held-back toast is changed too and shows the\n * change when it comes on screen.\n *\n * Fields: `message`, `title`, `description`, `severity`, `meta`, and for\n * progress toasts `progress` (fraction, `{ value, total }`, or `null` for\n * indeterminate), `status`, `counts` and `collapsed`; `progress` on a\n * plain toast turns it into a running progress toast (on screen, as with\n * show()). Giving a running progress toast an outcome severity (success,\n * error, fatal) finishes it, and its bar keeps the state it ended in: a\n * later severity only restyles the toast. A `durationMs` on a toast that\n * is not running (re)starts its auto-dismiss (0 keeps it until closed).\n *\n * @param {string} notificationId - The ID of the notification to update\n * @param {Object} updates - The fields to change\n * @returns {boolean} True if the notification was found and updated\n */\n update(notificationId, updates = {}) {\n const notification = this.notifications.find((item) => item.id === notificationId)\n ?? this.held.find((item) => item.id === notificationId);\n if (!notification) {\n return false;\n }\n const hadTitle = Boolean(notification.title);\n const hadDescription = Boolean(notification.description);\n const wasProgress = notification.progress !== undefined;\n const wasRunning = NotificationCenter.#isRunning(notification);\n\n if (updates.message !== undefined) notification.message = updates.message;\n if (updates.title !== undefined) notification.title = updates.title;\n if (updates.description !== undefined) notification.description = updates.description;\n if (updates.meta !== undefined) notification.meta = updates.meta;\n if (updates.status !== undefined) notification.status = updates.status ?? '';\n if (updates.counts !== undefined) notification.counts = updates.counts ?? '';\n if (updates.collapsed !== undefined) notification.collapsed = Boolean(updates.collapsed);\n if (updates.progress !== undefined) {\n if (wasProgress) {\n notification.progress = NotificationCenter.#normalizeProgress(updates.progress);\n } else {\n // A plain toast becomes a running progress toast, set up as show() would.\n Object.assign(notification, NotificationCenter.#progressFields({ ...notification, ...updates }));\n notification.persistent = true;\n this.#stopTimer(notification.id);\n }\n }\n if (updates.severity !== undefined) {\n notification.severity = this.#normalizeSeverity(updates.severity);\n const outcome = OUTCOME_BAR_STATE[notification.severity];\n if (NotificationCenter.#isRunning(notification) && outcome) notification.outcome = outcome;\n }\n const running = NotificationCenter.#isRunning(notification);\n const finished = wasRunning && !running;\n if (updates.durationMs !== undefined && !NotificationCenter.#isRunning(notification)) {\n notification.durationMs = this.#coerceDuration(updates.durationMs);\n notification.persistent = notification.durationMs === 0;\n if (this.notifications.includes(notification)) {\n this.#stopTimer(notification.id);\n this.#scheduleAutoDismiss(notification);\n }\n }\n\n const entry = this.#items.get(notification.id);\n if (entry) {\n const structural = hadTitle !== Boolean(notification.title)\n || hadDescription !== Boolean(notification.description)\n || wasProgress !== (notification.progress !== undefined);\n if (structural) {\n // A part appears or goes: rebuild this one toast, in its place.\n const next = this.#buildItem(notification);\n entry.el.replaceWith(next.el);\n entry.bar?.dispose();\n this.#items.set(notification.id, next);\n } else {\n this.#patchItem(entry, notification);\n }\n }\n if (finished) this.#announce(notification);\n // Started, it comes on screen whatever is held; finished, it folds\n // like any other toast.\n if (running !== wasRunning) this.#rebalance();\n this.#render();\n return true;\n }\n\n clearAll(reason = 'cleared') {\n [...this.notifications].forEach((notification) => this.dismiss(notification.id, reason));\n }\n\n ingestLogEntry(entry) {\n if (!entry || !this.logLevels.has(entry.level)) {\n return;\n }\n\n // Suppress state-guard warnings - these are internal and would cause a cascade\n // (NotificationCenter renders -> triggers state-guard -> logs warning -> creates notification -> repeat)\n if (entry.namespace === 'state-guard') {\n return;\n }\n\n const severity = LOG_SEVERITY_MAP[entry.level] ?? 'info';\n const suppressTitle = SUPPRESSED_NAMESPACE_TITLES.has(entry.namespace);\n const title = suppressTitle\n ? null\n : NotificationCenter.#formatNamespaceTitle(entry.namespace);\n // Info-level log entries from internal namespaces are noise in history\n const skipHistory = severity === 'info' && suppressTitle;\n this.show({\n title,\n message: entry.message,\n severity,\n namespace: entry.namespace,\n meta: entry.data,\n skipHistory,\n });\n }\n\n #consoleLog(notification) {\n if (notification.severity !== 'warn' && notification.severity !== 'error' && notification.severity !== 'fatal') {\n return;\n }\n const method = notification.severity === 'warn' ? console.warn : console.error; // eslint-disable-line no-console\n const prefix = notification.title ? `[${notification.title}]` : '[Notification]';\n const details = notification.meta ?? notification.description ?? '';\n method(`${prefix} ${notification.message}`, details); // eslint-disable-line no-console\n }\n\n #normalizeNotification(notification) {\n if (!notification) {\n throw new TypeError('Notification payload is required');\n }\n const id = notification.id ?? `notification-${++this.sequence}`;\n const severity = this.#normalizeSeverity(notification.severity ?? 'info');\n const isProgress = notification.progress !== undefined;\n return {\n ...(isProgress ? NotificationCenter.#progressFields(notification) : {}),\n id,\n title: notification.title ?? null,\n message: notification.message ?? '',\n description: notification.description ?? null,\n timestamp: notification.timestamp ?? Date.now(),\n severity,\n namespace: notification.namespace ?? null,\n durationMs: this.#coerceDuration(notification.durationMs),\n // A progress toast stays until it finishes (and then until its\n // finishing durationMs, or its \u00D7).\n persistent: isProgress || Boolean(notification.persistent),\n skipHistory: Boolean(notification.skipHistory),\n actions: this.#normalizeActions(notification.actions),\n meta: notification.meta ?? null,\n };\n }\n\n #normalizeSeverity(severity) {\n const value = typeof severity === 'string' ? severity.toLowerCase() : 'info';\n if (!SEVERITIES.includes(value)) {\n return 'info';\n }\n return value;\n }\n\n #coerceDuration(duration) {\n if (duration === null || duration === undefined) {\n return this.defaultDurationMs;\n }\n const value = Number(duration);\n if (!Number.isFinite(value) || value < 0) {\n return this.defaultDurationMs;\n }\n return value;\n }\n\n toast(title, message, type = 'info') {\n // Legacy compatibility method\n this.show({\n title,\n message,\n severity: type,\n persistent: type === 'error' || type === 'fatal',\n });\n }\n\n error(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'error',\n persistent: true,\n });\n }\n\n warn(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'warn',\n });\n }\n\n info(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'info',\n });\n }\n\n success(titleOrMessage, message) {\n const hasTitle = message !== undefined;\n return this.show({\n title: hasTitle ? titleOrMessage : null,\n message: hasTitle ? message : titleOrMessage,\n severity: 'success',\n });\n }\n\n #normalizeActions(actions) {\n if (!Array.isArray(actions) || actions.length === 0) {\n return [];\n }\n return actions.map((action, idx) => ({\n id: action.id ?? `action-${idx}`,\n label: action.label ?? 'Action',\n handler: typeof action.handler === 'function' ? action.handler : null,\n eventName: action.eventName ?? null,\n payload: action.payload ?? null,\n }));\n }\n\n #scheduleAutoDismiss(notification) {\n if (notification.persistent || notification.durationMs === 0) {\n return;\n }\n const timer = setTimeout(() => {\n this.dismiss(notification.id, 'timeout');\n }, notification.durationMs);\n this.activeTimers.set(notification.id, timer);\n }\n\n #stopTimer(notificationId) {\n const timer = this.activeTimers.get(notificationId);\n if (timer) {\n clearTimeout(timer);\n this.activeTimers.delete(notificationId);\n }\n }\n\n #clearTimers() {\n this.activeTimers.forEach((timer) => clearTimeout(timer));\n this.activeTimers.clear();\n }\n\n /**\n * Hear of every entry added to `history`, by `show()`, `warn()`/`error()`/\n * `info()`/`success()` and the bus alike: `listener(entry, center)`, once\n * per toast, after the entry is in `history`. A dismissal changes the\n * toast's own entry and is not an entry of its own. Answers the unsubscribe.\n */\n subscribe(listener) {\n if (typeof listener !== 'function') return () => {};\n this.#historyListeners.add(listener);\n return () => { this.#historyListeners.delete(listener); };\n }\n\n #recordHistory(entry) {\n if (entry.skipHistory) return;\n this.history.push(entry);\n if (this.history.length > this.historyLimit) {\n this.history.shift();\n }\n [...this.#historyListeners].forEach((listener) => {\n try {\n listener(entry, this);\n } catch (err) {\n this.logger?.warn?.('twm-notification-center', 'History listener failed', { err });\n }\n });\n }\n\n /** A toast that left marks its own entry: one toast, one entry. */\n #recordDismissal(notification, reason) {\n if (notification.skipHistory) return;\n const at = this.history.findLastIndex((entry) => entry.id === notification.id);\n if (at === -1) return;\n this.history[at] = { ...notification, dismissed: true, reason };\n }\n\n /** A progress toast that has not been given an outcome yet. */\n static #isRunning(notification) {\n return notification.progress !== undefined && !notification.outcome;\n }\n\n /**\n * The fields a progress toast carries, from a show() payload or an\n * update() that turns a plain toast into one. `outcome` is null while it\n * runs, then the state its bar ended in (done or error).\n */\n static #progressFields(source) {\n return {\n progress: NotificationCenter.#normalizeProgress(source.progress),\n status: source.status ?? '',\n counts: source.counts ?? '',\n collapsed: Boolean(source.collapsed),\n outcome: null,\n };\n }\n\n /** `null` (indeterminate), a 0..1 fraction, or `{ value, total }` -> ProgressBar input. */\n static #normalizeProgress(progress) {\n if (progress === null) return { indeterminate: true };\n if (typeof progress === 'number') {\n return { value: Number.isFinite(progress) ? progress : 0, max: null, indeterminate: false };\n }\n if (typeof progress === 'object') {\n const value = Number(progress.value);\n const total = Number(progress.total);\n return {\n value: Number.isFinite(value) ? value : 0,\n max: Number.isFinite(total) && total > 0 ? total : null,\n indeterminate: false,\n };\n }\n return { indeterminate: true };\n }\n\n /**\n * 'collapse' only: keep at most `maxVisible` on screen, counting running\n * progress toasts, which never leave and are never held (one that started\n * running while held comes on screen first). Past the limit the newest\n * other toast steps back to the front of the held queue (its timer\n * restarts when it returns); under it the oldest held toast comes in.\n */\n #rebalance() {\n if (this.overflow !== 'collapse') return;\n for (let i = 0; i < this.held.length;) {\n if (NotificationCenter.#isRunning(this.held[i])) this.notifications.push(...this.held.splice(i, 1));\n else i++;\n }\n while (this.notifications.length > this.maxVisible) {\n let idx = -1;\n for (let i = this.notifications.length - 1; i >= 0; i--) {\n if (!NotificationCenter.#isRunning(this.notifications[i])) { idx = i; break; }\n }\n if (idx === -1) break;\n const [back] = this.notifications.splice(idx, 1);\n this.#stopTimer(back.id);\n this.held.unshift(back);\n }\n while (this.held.length && this.notifications.length < this.maxVisible) {\n const next = this.held.shift();\n this.notifications.push(next);\n this.#scheduleAutoDismiss(next);\n }\n }\n\n /**\n * Draw the toasts on screen. Each toast's element is built once and kept:\n * a toast arriving or leaving only inserts or removes its own element, so\n * every other toast keeps its nodes (and its bar, collapsed state, hover).\n */\n #render() {\n if (!this._mounted || !this.listEl) {\n return;\n }\n const visible = new Set(this.notifications.map((n) => n.id));\n for (const [id, entry] of this.#items) {\n if (visible.has(id)) continue;\n entry.bar?.dispose();\n entry.el.remove();\n this.#items.delete(id);\n }\n const wanted = this.notifications.map((notification) => {\n let entry = this.#items.get(notification.id);\n if (!entry) {\n entry = this.#buildItem(notification);\n this.#items.set(notification.id, entry);\n }\n return entry.el;\n });\n const summary = this.#syncSummary();\n if (summary) wanted.push(summary);\n wanted.forEach((el, i) => {\n const at = this.listEl.children[i];\n if (at !== el) this.listEl.insertBefore(el, at ?? null);\n });\n // Anything after them is stale (another instance's toasts on a reused root).\n while (this.listEl.children.length > wanted.length) {\n this.listEl.lastElementChild.remove();\n }\n }\n\n // The held-back toasts, as one: \"+N more\". It is a button so the count is\n // reachable by keyboard; what it opens is the consumer's (summaryAction),\n // and it is also announced on the bus for a history panel to answer.\n #syncSummary() {\n if (!this.held.length) {\n this.#summaryEl?.remove();\n this.#summaryEl = null;\n return null;\n }\n if (!this.#summaryEl) {\n const more = document.createElement('button');\n more.type = 'button';\n more.className = 'twm-notification twm-notification--summary';\n more.addEventListener('click', () => {\n const held = [...this.held];\n try { this.summaryAction?.(held); } catch (err) { this.logger?.warn?.('summaryAction failed', err); }\n this.eventBus?.emit?.('notification:summary', { held });\n });\n this.#summaryEl = more;\n }\n const more = this.#summaryEl;\n const count = String(this.held.length);\n if (more.getAttribute('data-notification-summary') !== count) more.setAttribute('data-notification-summary', count);\n NotificationCenter.#setText(more, `+${count} more`);\n const tip = this.held.map((h) => h.title || h.message).join('\\n');\n if (more.title !== tip) more.title = tip;\n return more;\n }\n\n static #setText(node, text) {\n const t = text == null ? '' : String(text);\n if (node.textContent !== t) node.textContent = t;\n }\n\n /** Build one toast's element; `#patchItem` then fills what can change. */\n #buildItem(notification) {\n const isProgress = notification.progress !== undefined;\n const item = document.createElement('div');\n // Use setAttribute to avoid StateGuard blocking dataset mutations\n item.setAttribute('data-notification-id', notification.id);\n const entry = { el: item, severity: null, titleEl: null, bodyEl: null, descriptionEl: null,\n statusEl: null, bar: null, collapseBtn: null };\n\n const header = document.createElement('div');\n header.className = 'twm-notification__header';\n if (notification.title) {\n entry.titleEl = document.createElement('span');\n entry.titleEl.className = 'twm-notification__title';\n header.appendChild(entry.titleEl);\n }\n\n const timeEl = document.createElement('span');\n timeEl.className = 'twm-notification__timestamp';\n timeEl.textContent = this.#formatTimestamp(notification.timestamp);\n header.appendChild(timeEl);\n\n if (isProgress) {\n const toggle = document.createElement('button');\n toggle.className = 'twm-notification__collapse';\n toggle.type = 'button';\n toggle.innerHTML = '<span class=\"material-symbols-outlined\">expand_more</span>';\n toggle.addEventListener('click', () => {\n this.update(notification.id, { collapsed: !notification.collapsed });\n });\n entry.collapseBtn = toggle;\n header.appendChild(toggle);\n }\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'twm-notification__close';\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', 'Dismiss notification');\n closeBtn.innerHTML = '<span class=\"material-symbols-outlined\">close</span>';\n closeBtn.addEventListener('click', () => this.dismiss(notification.id, 'manual'));\n header.appendChild(closeBtn);\n item.appendChild(header);\n\n entry.bodyEl = document.createElement('div');\n entry.bodyEl.className = 'twm-notification__body';\n item.appendChild(entry.bodyEl);\n\n if (isProgress) {\n entry.bar = new ProgressBar(item, {\n ...notification.progress, showCount: false, className: 'twm-notification__progress',\n });\n entry.statusEl = document.createElement('div');\n entry.statusEl.className = 'twm-notification__status';\n item.appendChild(entry.statusEl);\n }\n\n if (notification.description) {\n entry.descriptionEl = document.createElement('div');\n entry.descriptionEl.className = 'twm-notification__description';\n item.appendChild(entry.descriptionEl);\n }\n\n if (notification.actions.length > 0) {\n const actionsEl = document.createElement('div');\n actionsEl.className = 'twm-notification__actions';\n notification.actions.forEach((action) => {\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'twm-notification__action-btn';\n button.textContent = action.label;\n button.addEventListener('click', () => {\n try {\n if (action.handler) {\n action.handler(notification, action);\n } else if (action.eventName && this.eventBus) {\n this.eventBus.emit(action.eventName, action.payload ?? { notificationId: notification.id });\n }\n } catch (err) {\n this.logger?.error?.('twm-notification-center', 'Notification action failed', { err });\n } finally {\n // Don't auto-dismiss error/fatal notifications, or a job\n // still running, after action clicks\n if (notification.severity !== 'error' && notification.severity !== 'fatal'\n && !NotificationCenter.#isRunning(notification)) {\n this.dismiss(notification.id, 'action');\n }\n }\n });\n actionsEl.appendChild(button);\n });\n item.appendChild(actionsEl);\n }\n\n // A click on the text is the start of selecting it (a double-click's\n // first click leaves only a caret), so only the toast's chrome closes it.\n item.addEventListener('click', (event) => {\n if (event.target.closest(`button, ${TOAST_TEXT}`) || NotificationCenter.#isRunning(notification)\n || selectsTextIn(item)) {\n return;\n }\n this.dismiss(notification.id, 'click');\n });\n item.addEventListener('contextmenu', (event) => showNotificationMenu(event, notification, this.logger));\n\n this.#patchItem(entry, notification);\n return entry;\n }\n\n /** Bring a drawn toast's nodes in line with its data, touching only what changed. */\n #patchItem(entry, notification) {\n const item = entry.el;\n if (entry.severity !== notification.severity) {\n if (entry.severity) item.classList.remove(`twm-notification--${entry.severity}`);\n item.classList.add('twm-notification', `twm-notification--${notification.severity}`);\n entry.severity = notification.severity;\n }\n if (entry.titleEl) NotificationCenter.#setText(entry.titleEl, notification.title);\n NotificationCenter.#setText(entry.bodyEl, notification.message);\n if (entry.descriptionEl) NotificationCenter.#setText(entry.descriptionEl, notification.description);\n if (!entry.bar) return;\n\n item.classList.add('twm-notification--progress');\n item.classList.toggle('twm-notification--collapsed', Boolean(notification.collapsed));\n const expanded = String(!notification.collapsed);\n if (entry.collapseBtn.getAttribute('aria-expanded') !== expanded) {\n entry.collapseBtn.setAttribute('aria-expanded', expanded);\n entry.collapseBtn.setAttribute('aria-label', notification.collapsed ? 'Expand notification' : 'Collapse notification');\n }\n NotificationCenter.#setText(entry.statusEl, notification.status);\n entry.statusEl.hidden = !notification.status;\n entry.bar.update({ ...notification.progress, label: notification.counts });\n const end = notification.outcome ?? 'running';\n if (entry.bar.state !== end) entry.bar.setState(end);\n }\n\n #formatTimestamp(timestamp) {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n\n #announce(notification) {\n if (!this.liveRegionEl) {\n return;\n }\n const parts = [notification.title, notification.message].filter(Boolean);\n this.liveRegionEl.textContent = parts.join(': ');\n }\n\n #handleToast(payload = {}) {\n const message = payload.text ?? payload.message ?? (typeof payload === 'string' ? payload : '');\n if (!message) {\n return;\n }\n\n const persistent = payload.persistent === true || payload.autoHide === false;\n const durationMs = persistent ? 0 : (payload.durationMs ?? payload.duration ?? payload.timeout);\n this.show({\n title: payload.title ?? null,\n message,\n severity: payload.type ?? payload.severity ?? 'info',\n durationMs,\n persistent,\n namespace: payload.namespace ?? null,\n actions: payload.actions,\n meta: payload.meta ?? null,\n });\n }\n\n #subscribeEvents() {\n if (!this.eventBus) {\n return;\n }\n this.eventDisposers.push(\n this.eventBus.on('toast:show', (payload) => this.#handleToast(payload)),\n this.eventBus.on('notification:show', (payload) => this.show(payload)),\n this.eventBus.on('notification:update', (payload) => {\n if (payload?.id) {\n this.update(payload.id, payload);\n }\n }),\n this.eventBus.on('log:entry', (entry) => this.ingestLogEntry(entry)),\n this.eventBus.on('workspace:save:failed', (payload) => {\n // Error toasts are shown by default unless explicitly disabled\n if (getSetting('workspace.save.showErrorToast', true)) {\n this.show({\n title: 'Workspace Save Failed',\n message: payload?.reason ? `Save failed: ${payload.reason}` : 'Workspace save failed',\n severity: 'error',\n meta: payload,\n persistent: true,\n });\n }\n }),\n this.eventBus.on('workspace:save:completed', (payload) => {\n // Only show toast if enabled in settings\n if (getSetting('workspace.save.showToast', false)) {\n this.show({\n title: 'Workspace Saved',\n message: 'Changes saved successfully',\n severity: 'success',\n durationMs: 3000,\n meta: payload,\n skipHistory: true,\n });\n }\n }),\n this.eventBus.on('workspace:import:failed', (payload) => {\n // Error toasts are shown by default unless explicitly disabled\n if (getSetting('workspace.import.showErrorToast', true)) {\n this.show({\n title: 'Workspace Import Failed',\n message: payload?.error?.message || 'Import failed',\n severity: 'error',\n meta: payload,\n persistent: true,\n });\n }\n }),\n this.eventBus.on('workspace:import:completed', (payload) => {\n // Show import completion toast if enabled in settings\n if (getSetting('workspace.import.showToast', true)) {\n this.show({\n title: 'Workspace Ready',\n message: 'Workspace import completed',\n severity: 'success',\n durationMs: 3000,\n meta: payload,\n skipHistory: true,\n });\n }\n }),\n );\n }\n\n /** The toast helpers (toast.js) emit on the bus of the centre mounted last. */\n #claimToastBus() {\n if (this.eventBus) setToastBus(this.eventBus);\n }\n\n #unsubscribeEvents() {\n this.eventDisposers.forEach((disposer) => {\n try {\n disposer?.dispose?.();\n } catch (err) {\n this.logger?.warn?.('twm-notification-center', 'Failed to remove event listener', { err });\n }\n });\n this.eventDisposers = [];\n }\n\n static #formatNamespaceTitle(namespace) {\n if (!namespace) return null;\n return namespace\n .split(/[-_]/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n }\n}\n\nNotificationCenter.SEVERITIES = SEVERITIES;\n", "/**\n * NotificationHistory - Bottom bar notification history panel\n *\n * Bell icon in the global-bottom-bar that opens a popover listing past notifications.\n * Reads from NotificationCenter.history and follows it through\n * `notificationCenter.subscribe()` (0.17.3): every entry the centre records \u2014 a\n * toast from `show()`/`warn()`/... or from the bus \u2014 is one unread, until the\n * popover is opened. The bus is not watched for toasts.\n *\n * THREE OPTIONS, all additive (FlexDesk STORY-0020); without them it is the bell\n * it always was:\n *\n * mountPoint the element the bell is appended to. Without it, the hard-coded\n * `.twm-global-bottom-bar .twm-bar-right`, which only FlexDesk's own\n * bottom bar has.\n * alertLog an alert log (`alert_log.js`). The badge is then the log's unread\n * count, in the worst unread level's colour, and nothing when all is\n * read \u2014 not a delta of a toast history the user may never have\n * opened. A click opens the bottom panel's Alerts tab instead of the\n * popover, and the toasts' \"+N more\" (`notification:summary`) does too.\n * alertsTab the tab a click asks for, `bottompanel:show { tab }`; 'alerts'.\n * onOpen a click, instead of the bus event \u2014 for an embedder with no bus,\n * or whose panel must be opened before a tab can be chosen.\n *\n * A right-click on an entry opens the context menu with \"Copy message\"\n * (STORY-0131), the same as on its toast; the popover stays open meanwhile.\n */\nimport { showNotificationMenu } from '../notification_center.js';\n\nexport class NotificationHistory {\n constructor({ notificationCenter, eventBus, logger, mountPoint = null, alertLog = null,\n alertsTab = 'alerts', onOpen = null } = {}) {\n this.notificationCenter = notificationCenter;\n this.eventBus = eventBus || null;\n this.logger = logger || console;\n this.mountPoint = mountPoint;\n this.alertLog = alertLog;\n this.alertsTab = alertsTab;\n this.onOpen = typeof onOpen === 'function' ? onOpen : null;\n\n this.triggerEl = null;\n this.badgeEl = null;\n /** Entries recorded since the popover was last opened. */\n this.unreadCount = 0;\n this._popoverCleanup = null;\n this._subscriptions = [];\n }\n\n mount() {\n const barRight = this.mountPoint\n || document.querySelector('.twm-global-bottom-bar .twm-bar-right');\n if (!barRight) {\n this.logger.warn?.('[NotificationHistory] .bar-right not found');\n return;\n }\n\n // Build trigger button\n this.triggerEl = document.createElement('button');\n this.triggerEl.className = 'twm-notification-history__trigger twm-has-tooltip';\n this.triggerEl.setAttribute('data-tooltip', 'Notification history');\n this.triggerEl.setAttribute('aria-label', 'Notification history');\n this.triggerEl.innerHTML =\n '<span class=\"material-symbols-outlined\">notifications</span>' +\n '<span class=\"twm-notification-history__badge\" style=\"display:none\">0</span>';\n\n this.badgeEl = this.triggerEl.querySelector('.twm-notification-history__badge');\n\n // Park the bell as the LAST child of .bar-right so it always\n // sits at the far-right edge of the status bar \u2014 past the\n // tick readout, streaming dot, and anything else that the\n // global actions cluster mounts before it.\n barRight.appendChild(this.triggerEl);\n\n this.triggerEl.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.alertLog) this.#openAlerts();\n else this.#togglePanel();\n });\n\n if (this.alertLog) {\n this.triggerEl.setAttribute('data-tooltip', 'Alerts');\n this.triggerEl.setAttribute('aria-label', 'Alerts');\n this._subscriptions.push(this.alertLog.subscribe(() => this.#updateBadge()));\n const summary = this.eventBus?.on?.('notification:summary', () => this.#openAlerts());\n if (summary) this._subscriptions.push(() => summary.dispose?.());\n this.#updateBadge();\n return;\n }\n\n // What is in the history at mount is not unread.\n this.unreadCount = 0;\n const unsubscribe = this.notificationCenter?.subscribe?.(() => {\n this.unreadCount += 1;\n this.#updateBadge();\n });\n if (typeof unsubscribe === 'function') this._subscriptions.push(unsubscribe);\n this.#updateBadge();\n }\n\n unmount() {\n this.#closePanel();\n this._subscriptions.forEach(unsub => {\n if (typeof unsub === 'function') unsub();\n });\n this._subscriptions = [];\n if (this.triggerEl?.parentNode) {\n this.triggerEl.parentNode.removeChild(this.triggerEl);\n }\n this.triggerEl = null;\n this.badgeEl = null;\n }\n\n /** The Alerts tab, asked for on the bus \u2014 or the embedder's own verb. */\n #openAlerts() {\n if (this.onOpen) {\n try { this.onOpen(); } catch (err) { this.logger.warn?.('[NotificationHistory] onOpen failed', err); }\n return;\n }\n this.eventBus?.emit?.('bottompanel:show', { tab: this.alertsTab });\n }\n\n #updateBadge() {\n const historyLen = this.notificationCenter?.history?.length ?? 0;\n const unread = this.alertLog\n ? this.alertLog.unreadCount()\n : Math.min(this.unreadCount, historyLen);\n\n if (!this.badgeEl) return;\n\n if (this.alertLog) {\n const level = unread > 0 ? this.alertLog.worstUnread() : null;\n this.badgeEl.className = 'twm-notification-history__badge'\n + (level ? ` twm-notification-history__badge--${level}` : '');\n this.triggerEl?.classList.toggle('twm-notification-history__trigger--unread', unread > 0);\n }\n\n if (unread > 0) {\n this.badgeEl.textContent = unread > 99 ? '99+' : String(unread);\n this.badgeEl.style.display = '';\n } else {\n this.badgeEl.style.display = 'none';\n }\n }\n\n #togglePanel() {\n if (this._popoverCleanup) {\n this.#closePanel();\n } else {\n this.#openPanel();\n }\n }\n\n #closePanel() {\n if (typeof this._popoverCleanup === 'function') {\n try { this._popoverCleanup(); } catch (_) { /* ignore */ }\n this._popoverCleanup = null;\n }\n }\n\n #openPanel() {\n this.#closePanel();\n\n // Mark all as seen\n this.unreadCount = 0;\n this.#updateBadge();\n\n const panel = document.createElement('div');\n panel.className = 'twm-notification-history__panel';\n\n // Header\n const header = document.createElement('div');\n header.className = 'twm-notification-history__header';\n header.innerHTML =\n '<span class=\"twm-notification-history__title\">Notifications</span>' +\n '<button class=\"twm-notification-history__clear-btn twm-has-tooltip\" data-tooltip=\"Clear all\" aria-label=\"Clear all\">' +\n '<span class=\"material-symbols-outlined\">delete_sweep</span>' +\n '</button>' +\n '<button class=\"twm-notification-history__close-btn twm-has-tooltip\" data-tooltip=\"Close\" aria-label=\"Close\">' +\n '<span class=\"material-symbols-outlined\">close</span>' +\n '</button>';\n panel.appendChild(header);\n\n // List\n const list = document.createElement('div');\n list.className = 'twm-notification-history__list';\n panel.appendChild(list);\n\n this.#renderList(list);\n\n // Wire header buttons\n header.querySelector('.twm-notification-history__close-btn')\n .addEventListener('click', () => this.#closePanel());\n\n header.querySelector('.twm-notification-history__clear-btn')\n .addEventListener('click', () => {\n this.notificationCenter.history.splice(0);\n this.unreadCount = 0;\n this.#updateBadge();\n this.#renderList(list);\n });\n\n // Position and attach\n document.body.appendChild(panel);\n this.#positionPanel(panel);\n\n // Popover lifecycle (same pattern as ValidationStatus)\n const cleanup = () => {\n document.removeEventListener('mousedown', onDocDown, true);\n document.removeEventListener('keydown', onKey, true);\n window.removeEventListener('resize', onResize, true);\n try { panel.remove(); } catch (_) { /* ignore */ }\n this._popoverCleanup = null;\n };\n this._popoverCleanup = cleanup;\n\n // The entries' context menu is outside the panel, and using it is not leaving it.\n const onDocDown = (ev) => {\n if (ev.target.closest?.('.twm-context-menu')) return;\n if (!panel.contains(ev.target) && !this.triggerEl.contains(ev.target)) cleanup();\n };\n // Escape closes the innermost layer: an open entry menu closes itself.\n const onKey = (ev) => {\n if (ev.key === 'Escape' && !document.querySelector('.twm-context-menu')) cleanup();\n };\n const onResize = () => cleanup();\n\n document.addEventListener('mousedown', onDocDown, true);\n document.addEventListener('keydown', onKey, true);\n window.addEventListener('resize', onResize, true);\n }\n\n #renderList(listEl) {\n listEl.innerHTML = '';\n const history = this.notificationCenter?.history ?? [];\n\n if (history.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'twm-notification-history__empty';\n empty.textContent = 'No notifications';\n listEl.appendChild(empty);\n return;\n }\n\n // Reverse chronological\n const fragment = document.createDocumentFragment();\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i];\n const item = document.createElement('div');\n const severity = entry.severity || 'info';\n item.className = `twm-notification-history__item twm-notification-history__item--${severity}`;\n\n const itemHeader = document.createElement('div');\n itemHeader.className = 'twm-notification-history__item-header';\n\n if (entry.title) {\n const titleEl = document.createElement('span');\n titleEl.className = 'twm-notification-history__item-title';\n titleEl.textContent = entry.title;\n itemHeader.appendChild(titleEl);\n }\n\n const timeEl = document.createElement('span');\n timeEl.className = 'twm-notification-history__item-time';\n timeEl.textContent = this.#formatTime(entry.timestamp);\n itemHeader.appendChild(timeEl);\n\n item.appendChild(itemHeader);\n\n const body = document.createElement('div');\n body.className = 'twm-notification-history__item-body';\n body.textContent = entry.message || '';\n item.appendChild(body);\n item.addEventListener('contextmenu', (event) => showNotificationMenu(event, entry, this.logger));\n\n fragment.appendChild(item);\n }\n listEl.appendChild(fragment);\n }\n\n #positionPanel(panel) {\n if (!this.triggerEl) return;\n\n const triggerRect = this.triggerEl.getBoundingClientRect();\n const panelWidth = panel.getBoundingClientRect().width;\n const gap = 8;\n\n let left = triggerRect.right - panelWidth;\n\n // Clamp horizontally to the viewport.\n const vw = window.innerWidth;\n left = Math.max(8, Math.min(left, vw - panelWidth - 8));\n\n // Anchor by the panel's BOTTOM edge, pinned just above the bell.\n // Anchoring by `top` leaves the box floating when its content shrinks\n // (notifications cleared/removed): the top stays put while the bottom\n // lifts away from the bell, stranding the panel in mid-air. Pinning\n // the bottom keeps it glued to the bottom bar and lets it grow/shrink\n // upward \u2014 no repositioning needed on re-render.\n const bottom = window.innerHeight - (triggerRect.top - gap);\n\n // Never let the panel run off the top of the viewport: cap its height\n // to the space above the bell (within the design max). The list\n // scrolls within whatever remains.\n const available = triggerRect.top - gap - 8;\n panel.style.maxHeight = `${Math.max(0, Math.min(420, Math.round(available)))}px`;\n\n panel.style.left = `${Math.round(left)}px`;\n panel.style.bottom = `${Math.round(bottom)}px`;\n panel.style.top = 'auto';\n }\n\n #formatTime(timestamp) {\n if (!timestamp) return '';\n const d = new Date(timestamp);\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n}\n", "/**\n * recent_items.js \u2014 a most-recent-first list kept through the Host's `state`\n * capability, so it survives a restart.\n *\n * const recent = createRecentItems({ host, key: 'recent-workspaces' });\n * await recent.load();\n * recent.add({ id: 'w1', name: 'North' });\n * recent.list(); // [{ id: 'w1', name: 'North', openedAt: 1730... }]\n *\n * An entry is any plain object; `identity` says which two are the same one, and\n * `add` stamps `openedAt`. `capacity` is per `groupOf(entry)` when that is\n * given, so one busy kind of entry never pushes another kind out.\n *\n * \u2550\u2550 A READ THAT FAILS IS NOT AN EMPTY LIST \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A `host.state.read` that rejects says nothing about what is stored, so until\n * a read succeeds the stored list is never written: writing would replace\n * entries nobody has seen. Changes made in the meantime show in `list()` at\n * once, are kept, are replayed onto the stored list when it is read, and each\n * of them asks for the read again. A read that answers something other than an\n * array is a read: the store is empty.\n *\n * Writes run one at a time and the last one carries the latest list, because a\n * host may answer them out of order and the older list must not win.\n *\n * A host with no `state` capability keeps the list in memory for this session.\n */\n\n/**\n * @param {object} options\n * @param {object} options.host - The Host; its `state` keeps the list\n * @param {string} options.key - The state key the list is stored under\n * @param {(entry: object) => string} [options.identity] - Which entries are the same one\n * @param {(entry: unknown) => boolean} [options.isValid] - Stored entries that fail this\n * are dropped on read, as is one that makes it, `identity` or `groupOf` throw, so\n * `identity` may assume an entry's shape.\n * @param {number} [options.capacity=10] - The most entries kept, per group\n * @param {(entry: object) => string} [options.groupOf] - Groups the capacity counts within\n * @param {() => void} [options.onChange] - After every change, and after a read that\n * replayed changes\n * @param {object} [options.logger] - Its `warn` hears a failed read or write\n */\nexport function createRecentItems({\n host,\n key,\n identity = (entry) => entry.id,\n isValid = (entry) => !!entry && typeof entry === 'object' && !!identity(entry),\n capacity = 10,\n groupOf = () => '',\n onChange = null,\n logger = null,\n}) {\n const state = host?.state ?? null;\n let entries = [];\n let loaded = !state;\n /** The changes made while the stored list is unread, oldest first: list => list. */\n let pending = [];\n let reading = null;\n let writing = false;\n let writeAgain = false;\n\n const capped = (list) => {\n const counts = new Map();\n return list.filter((entry) => {\n const group = groupOf(entry);\n const count = (counts.get(group) ?? 0) + 1;\n counts.set(group, count);\n return count <= capacity;\n });\n };\n\n const without = (list, entry) => {\n const id = identity(entry);\n return list.filter((other) => identity(other) !== id);\n };\n\n async function write() {\n if (!state) return;\n if (writing) {\n writeAgain = true;\n return;\n }\n writing = true;\n do {\n writeAgain = false;\n try {\n await state.write(key, entries);\n } catch (err) {\n logger?.warn?.(`Could not save the recent list \"${key}\"`, err);\n }\n } while (writeAgain);\n writing = false;\n }\n\n /** A stored entry the list can hold: everything it goes through accepts it. */\n const usable = (entry) => {\n try {\n if (!isValid(entry)) return false;\n identity(entry);\n groupOf(entry);\n return true;\n } catch (err) {\n logger?.warn?.(`Dropped an unreadable entry of the recent list \"${key}\"`, err);\n return false;\n }\n };\n\n async function read() {\n let stored;\n try {\n const saved = await state.read(key);\n stored = Array.isArray(saved) ? capped(saved.filter(usable)) : [];\n } catch (err) {\n logger?.warn?.(`Could not read the recent list \"${key}\"; the stored list is left unchanged until it can be read`, err);\n return false;\n }\n const replay = pending;\n pending = [];\n loaded = true;\n entries = replay.reduce((list, apply) => apply(list), stored);\n if (replay.length > 0) {\n onChange?.();\n void write();\n }\n return true;\n }\n\n /**\n * Read the stored list. Call it once at startup, before anything lists; a\n * change made while the list is unread calls it again. Once a read has\n * succeeded it does not read again.\n * @returns {Promise<boolean>} Whether the stored list has been read\n */\n function load() {\n if (!state) return Promise.resolve(false);\n if (loaded) return Promise.resolve(true);\n reading ??= read().finally(() => { reading = null; });\n return reading;\n }\n\n function change(apply) {\n entries = apply(entries);\n onChange?.();\n if (loaded) {\n void write();\n return;\n }\n pending.push(apply);\n void load();\n }\n\n return Object.freeze({\n load,\n /** @returns {ReadonlyArray<object>} Most recent first */\n list: () => Object.freeze(entries.map((entry) => Object.freeze({ ...entry }))),\n /** Put an entry at the top, dropping the older one with its identity. */\n add(entry) {\n const stamped = { ...entry, openedAt: Date.now() };\n change((list) => capped([stamped, ...without(list, stamped)]));\n },\n /** Drop the entry with this one's identity. */\n remove(entry) {\n change((list) => without(list, entry));\n },\n clear() {\n change(() => []);\n },\n });\n}\n", "/**\n * record_list.js \u2014 A READ-ONLY LIST OF RECORDS, each drawn as two lines: a\n * name, and under it a quiet line of facts; beside them pills and verbs.\n * (0.7.0)\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\u2500\u2500\u2500\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 ETL loader [paused] Resume Revoke \u2502\n * \u2502 tblk_8f2 \u2014 acts with the account \u2014 last used 5 Oct \u2502\n * \u2502 Resume: This key is revoked, and revoking cannot be undone. \u2502\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\u2500\u2500\u2500\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 * It is the shape an administration screen reaches for when a table would\n * be wrong: few records, each with its own verbs, read top to bottom rather\n * than sorted and filtered. Before this component every consumer built it by\n * hand, row by row, and each copy grew its own post-build loop to put a key\n * or a state on the row afterwards. Here the record's key, its classes and\n * its attributes are declared, and the list owns the rest.\n *\n * WHAT A RECORD SAYS ABOUT ITSELF (`describe(record, idx)`, or the record\n * itself when there is no `describe`):\n *\n * {\n * name: 'ETL loader' | Node, the first line\n * mono: true, the name in the monospace face\n * facts: ['tblk_8f2', null, 'last used 5 Oct'] | 'text' | Node,\n * the quiet line; null/'' parts\n * are left out, the rest joined\n * with `factSeparator`\n * pills: ['paused', {text: 'URL', tone: 'danger', title: '\u2026'}],\n * verbs: [{label: 'Resume', onClick(record, ev), refusal: '\u2026' | null,\n * danger, primary, icon, title, name}],\n * state: 'paused' | 'off' | 'dead' | 'error' | 'active' | any word \u2014\n * `data-state` and `twm-record--state-<word>` on the row,\n * error: 'The last delivery failed: 503' | Node, a line in the error colour\n * key: 'k-1', overrides `getKey`\n * }\n *\n * A REFUSED VERB IS A DISABLED BUTTON AND A SENTENCE ON THE SCREEN. The\n * reason is on the button's `title` and `data-refusal` too, but a reason only\n * on a tooltip reads as \"the button does nothing\" \u2014 nobody hovers a button\n * they believe they have just pressed. So each distinct reason is a line of\n * its own under the facts, named by the verbs it refuses\n * (`data-refusal-for`), and the button is `aria-describedby` that line.\n *\n * OPENING A RECORD (`onActivate`) follows DataTable's `onRowActivate` rule,\n * from the same module (`row_activation.js`): a press on a control in the\n * row is that control's, a click that ends a drag selecting text opens\n * nothing, and neither does the second click of a double-click.\n *\n * THE KEYBOARD. With `onActivate` (or `keyboard: true`) the RECORDS are one\n * tab stop \u2014 the one last focused, else the open one, else the first \u2014 and\n * each enabled verb keeps its own, so every verb is reachable by Tab.\n * ArrowUp/ArrowDown move between records (from a record or from one of its\n * verbs), Home/End go to the ends, and Enter on a record opens it. Enter on a\n * verb is the verb's.\n */\nimport { isRowActivation, isRowControl } from './row_activation.js';\n\n/** A field, a select or editable text keeps its own arrow keys. */\nconst OWN_ARROWS = 'input, select, textarea, [contenteditable=\"\"], [contenteditable=\"true\"]';\n\n/** The words a tone may be, after sanitising (`[^\\w-]` dropped). */\nconst safeWord = (s) => String(s).replace(/[^\\w-]/g, '');\n\nlet SEQ = 0;\n\n/**\n * @typedef {Object} RecordVerb\n * @property {string} label - The button's words.\n * @property {Function} [onClick] - `(record, ev) => void`.\n * @property {string|null} [refusal] - Why it cannot be pressed. A disabled\n * button, and the sentence drawn under the record's facts.\n * @property {boolean} [danger]\n * @property {boolean} [primary]\n * @property {string} [icon] - A Material Symbols name, drawn before the label.\n * @property {string} [title] - A tooltip, for a verb that is NOT refused.\n * @property {string} [name] - A stable id: `data-verb`, and what focus is\n * restored to after a redraw. Defaults to the label.\n */\n\n/**\n * @typedef {Object} RecordListConfig\n * @property {Array} [records=[]]\n * @property {Function} [describe] - `(record, idx) => spec`. Without it the\n * record is its own spec.\n * @property {Function} [getKey] - `(record, idx) => string|number`. Defaults to\n * `spec.key`, then `record.key`, then `record.id`, then the index.\n * @property {Function} [onActivate] - `(record, idx, ev) => void`. Opens a record.\n * @property {string|string[]} [activateOn=['click','enter']] - `'click'`,\n * `'dblclick'`, `'enter'`, or several.\n * @property {boolean} [keyboard] - Arrow keys between records. Defaults to on\n * exactly when `onActivate` is set.\n * @property {*} [activeKey] - The record that is open: `twm-record--active`\n * and `aria-current=\"true\"`.\n * @property {Function} [rowClass] - `(record, idx) => string|string[]|null`.\n * @property {Function} [rowAttrs] - `(record, idx) => {name: value}`;\n * `null`/`false` leaves one off, `true` sets it empty.\n * @property {string|Node|Function} [emptyState] - Shown when there are no\n * records. A function is called with no arguments and may return either.\n * @property {string} [factSeparator=' \u2014 ']\n * @property {'wrap'|'ellipsis'} [facts='wrap'] - How a long fact line ends.\n * `'ellipsis'` keeps it to one line and puts the whole line on `title`.\n * @property {string|Function} [verbClass] - The verbs' class names, or\n * `(verb) => string`, for a consumer with its own buttons. Defaults to\n * FlexDesk's `twm-btn` with `--primary`/`--danger`.\n * @property {string} [label] - The list's accessible name (`aria-label`).\n * @property {string} [className] - Added to the root.\n */\n\nexport class RecordList {\n /**\n * @param {HTMLElement|null} host appended to, if given\n * @param {RecordListConfig} [config]\n */\n constructor(host, config = {}) {\n this.config = {\n records: [],\n describe: null,\n getKey: null,\n onActivate: null,\n activateOn: ['click', 'enter'],\n keyboard: undefined,\n activeKey: null,\n rowClass: null,\n rowAttrs: null,\n emptyState: null,\n factSeparator: ' \u2014 ',\n facts: 'wrap',\n verbClass: null,\n label: null,\n className: null,\n ...config,\n };\n this._records = Array.isArray(this.config.records) ? this.config.records.slice() : [];\n this._activeKey = this.config.activeKey ?? null;\n this._tabKey = null;\n this._items = new Map(); // key \u2192 <li>\n this._disposed = false;\n this._id = `twm-record-list-${++SEQ}`;\n\n const root = document.createElement('div');\n root.className = 'twm-record-list'\n + (this.config.facts === 'ellipsis' ? ' twm-record-list--clip' : '')\n + (this._activates() ? ' twm-record-list--clickable' : '')\n + (this.config.className ? ` ${this.config.className}` : '');\n const list = document.createElement('ul');\n list.className = 'twm-record-list__items';\n if (this.config.label) list.setAttribute('aria-label', this.config.label);\n root.appendChild(list);\n this.element = root;\n this.listElement = list;\n\n this._onClick = (ev) => this._gesture(ev, 'click');\n this._onDblClick = (ev) => this._gesture(ev, 'dblclick');\n this._onKeyDown = (ev) => this._key(ev);\n // Only focus ON a record moves the tab stop. Focus on one of its verbs\n // must not: Tab walks forward through the verbs of the records before\n // the stop, and moving the stop behind the focus would leave no record\n // ahead to Tab to (measured in Edge).\n this._onFocusIn = (ev) => {\n const li = this._itemOf(ev.target);\n if (li && ev.target === li) this._setTabStop(li.__recordKey);\n };\n list.addEventListener('click', this._onClick);\n list.addEventListener('dblclick', this._onDblClick);\n list.addEventListener('keydown', this._onKeyDown);\n list.addEventListener('focusin', this._onFocusIn);\n\n this._draw();\n if (host) host.appendChild(root);\n }\n\n // \u2500\u2500 public \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Replace the records and draw them. Focus inside the list is kept on\n * the same record, and on the same verb of it, when it is still there. */\n setRecords(records) {\n if (this._disposed) return;\n this._records = Array.isArray(records) ? records.slice() : [];\n this._draw();\n }\n\n /** The records, as last given. */\n getRecords() {\n return this._records.slice();\n }\n\n /** Draw ONE record again (`describe` asked afresh), or every one with no key. */\n refresh(key) {\n if (this._disposed) return;\n if (key === undefined) { this._draw(); return; }\n const old = this._items.get(this._norm(key));\n if (!old) return;\n const idx = old.__recordIndex;\n const focus = this._focusMemo();\n const fresh = this._item(this._records[idx], idx);\n old.replaceWith(fresh);\n this._items.set(fresh.__recordKey, fresh);\n this._paintTabStop();\n this._restoreFocus(focus);\n }\n\n /** Mark the record that is open (`null` for none). */\n setActiveKey(key) {\n this._activeKey = key ?? null;\n for (const li of this._items.values()) this._paintActive(li);\n if (this._activeKey !== null && this._items.has(this._norm(this._activeKey))) {\n this._setTabStop(this._norm(this._activeKey));\n }\n }\n\n getActiveKey() {\n return this._activeKey;\n }\n\n /** The `<li>` drawn for a key, or null. */\n getItem(key) {\n return this._items.get(this._norm(key)) || null;\n }\n\n /** Move the keyboard focus to a record. */\n focusRecord(key) {\n const li = this.getItem(key);\n if (!li) return false;\n this._setTabStop(li.__recordKey);\n li.focus();\n return true;\n }\n\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n const list = this.listElement;\n list.removeEventListener('click', this._onClick);\n list.removeEventListener('dblclick', this._onDblClick);\n list.removeEventListener('keydown', this._onKeyDown);\n list.removeEventListener('focusin', this._onFocusIn);\n this._items.clear();\n this.element.remove();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _activates() {\n return typeof this.config.onActivate === 'function';\n }\n\n _keyboard() {\n return this.config.keyboard ?? this._activates();\n }\n\n _gestures() {\n const g = this.config.activateOn;\n return new Set(Array.isArray(g) ? g : [g]);\n }\n\n /** Keys compare as strings: a record keyed `7` and an `activeKey` of `'7'` are one. */\n _norm(key) {\n return key === null || key === undefined ? key : String(key);\n }\n\n _spec(record, idx) {\n const { describe } = this.config;\n const spec = typeof describe === 'function' ? describe(record, idx) : record;\n return spec && typeof spec === 'object' ? spec : { name: spec };\n }\n\n _keyOf(record, idx, spec) {\n const { getKey } = this.config;\n let key;\n if (spec.key !== undefined && spec.key !== null) key = spec.key;\n else if (typeof getKey === 'function') key = getKey(record, idx);\n else if (record && typeof record === 'object' && (record.key ?? record.id) != null) key = record.key ?? record.id;\n else key = idx;\n return String(key);\n }\n\n _draw() {\n const focus = this._focusMemo();\n const list = this.listElement;\n list.replaceChildren();\n this._items.clear();\n this.element.querySelector(':scope > .twm-record-list__empty')?.remove();\n\n this._records.forEach((record, idx) => {\n const li = this._item(record, idx);\n if (this._items.has(li.__recordKey)) {\n console.error(`[RecordList] two records share the key \"${li.__recordKey}\"`);\n }\n this._items.set(li.__recordKey, li);\n list.appendChild(li);\n });\n this.element.classList.toggle('twm-record-list--empty', this._records.length === 0);\n if (!this._records.length) this._drawEmpty();\n this._paintTabStop();\n this._restoreFocus(focus);\n }\n\n _drawEmpty() {\n let content = this.config.emptyState;\n if (typeof content === 'function') content = content();\n if (content == null || content === false || content === '') return;\n const p = document.createElement('p');\n p.className = 'twm-record-list__empty';\n if (typeof Node !== 'undefined' && content instanceof Node) p.appendChild(content);\n else p.textContent = String(content);\n this.element.appendChild(p);\n }\n\n _item(record, idx) {\n const spec = this._spec(record, idx);\n const key = this._keyOf(record, idx, spec);\n const li = document.createElement('li');\n li.className = 'twm-record';\n li.__record = record;\n li.__recordIndex = idx;\n li.__recordKey = key;\n li.dataset.recordKey = key;\n if (this._keyboard()) li.tabIndex = -1;\n if (spec.state) {\n li.dataset.state = safeWord(spec.state);\n li.classList.add(`twm-record--state-${safeWord(spec.state)}`);\n }\n\n const main = document.createElement('div');\n main.className = 'twm-record__main';\n const name = document.createElement('div');\n name.className = 'twm-record__name' + (spec.mono ? ' twm-record__name--mono' : '');\n appendContent(name, spec.name);\n main.appendChild(name);\n\n const factsText = this._facts(spec.facts);\n if (factsText !== null) {\n const facts = document.createElement('div');\n facts.className = 'twm-record__facts';\n appendContent(facts, factsText);\n if (this.config.facts === 'ellipsis') facts.title = facts.textContent;\n main.appendChild(facts);\n }\n if (spec.error != null && spec.error !== false && spec.error !== '') {\n const err = document.createElement('div');\n err.className = 'twm-record__error';\n appendContent(err, spec.error);\n main.appendChild(err);\n }\n li.appendChild(main);\n\n const pills = (spec.pills || []).filter((p) => p != null && p !== false && p !== '');\n if (pills.length) {\n const box = document.createElement('div');\n box.className = 'twm-record__pills';\n for (const p of pills) box.appendChild(pill(p));\n li.appendChild(box);\n }\n\n const verbs = (spec.verbs || []).filter(Boolean);\n if (verbs.length) {\n const box = document.createElement('div');\n box.className = 'twm-record__verbs';\n const reasons = new Map(); // sentence \u2192 [labels]\n for (const v of verbs) {\n const b = this._verb(v, record);\n box.appendChild(b);\n if (v.refusal) {\n const said = String(v.refusal);\n if (!reasons.has(said)) reasons.set(said, { labels: [], buttons: [] });\n reasons.get(said).labels.push(v.label);\n reasons.get(said).buttons.push(b);\n }\n }\n li.appendChild(box);\n if (reasons.size) {\n const lines = document.createElement('div');\n lines.className = 'twm-record__refusals';\n let n = 0;\n for (const [said, { labels, buttons }] of reasons) {\n const line = document.createElement('div');\n line.className = 'twm-record__refusal';\n line.id = `${this._id}-r${idx}-${n++}`;\n line.dataset.refusalFor = labels.join(', ');\n line.textContent = labels.length === verbs.length && verbs.length > 1\n ? said : `${labels.join(', ')}: ${said}`;\n for (const b of buttons) b.setAttribute('aria-describedby', line.id);\n lines.appendChild(line);\n }\n main.appendChild(lines);\n }\n }\n\n this._decorate(li, record, idx);\n return li;\n }\n\n _facts(facts) {\n if (facts == null || facts === false) return null;\n if (typeof Node !== 'undefined' && facts instanceof Node) return facts;\n if (!Array.isArray(facts)) {\n const s = String(facts);\n return s === '' ? null : s;\n }\n const parts = facts.filter((f) => f != null && f !== false && f !== '');\n if (!parts.length) return null;\n if (parts.every((p) => !(typeof Node !== 'undefined' && p instanceof Node))) {\n return parts.map(String).join(this.config.factSeparator);\n }\n const frag = document.createDocumentFragment();\n parts.forEach((p, i) => {\n if (i) frag.appendChild(document.createTextNode(this.config.factSeparator));\n appendContent(frag, p);\n });\n return frag;\n }\n\n _verb(v, record) {\n const b = document.createElement('button');\n b.type = 'button';\n const { verbClass } = this.config;\n b.className = typeof verbClass === 'function' ? String(verbClass(v) || '')\n : typeof verbClass === 'string' ? verbClass\n : 'twm-btn' + (v.primary ? ' twm-btn--primary' : '') + (v.danger ? ' twm-btn--danger' : '');\n b.classList.add('twm-record__verb');\n b.dataset.verb = String(v.name ?? v.label);\n if (v.icon) {\n const glyph = document.createElement('span');\n glyph.className = 'material-symbols-outlined twm-record__verb-icon';\n glyph.setAttribute('aria-hidden', 'true');\n glyph.textContent = String(v.icon);\n b.appendChild(glyph);\n }\n const label = document.createElement('span');\n label.className = 'twm-record__verb-label';\n label.textContent = String(v.label ?? '');\n b.appendChild(label);\n if (v.refusal) {\n b.disabled = true;\n b.title = String(v.refusal);\n b.dataset.refusal = String(v.refusal);\n } else {\n if (v.title) b.title = String(v.title);\n if (typeof v.onClick === 'function') b.addEventListener('click', (ev) => v.onClick(record, ev));\n }\n return b;\n }\n\n _decorate(li, record, idx) {\n const { rowClass, rowAttrs } = this.config;\n if (typeof rowClass === 'function') {\n const c = rowClass(record, idx);\n const list = Array.isArray(c) ? c : String(c ?? '').split(/\\s+/);\n for (const name of list) if (name) li.classList.add(String(name));\n }\n if (typeof rowAttrs === 'function') {\n for (const [name, value] of Object.entries(rowAttrs(record, idx) || {})) {\n if (value == null || value === false) continue;\n try {\n li.setAttribute(name, value === true ? '' : String(value));\n } catch (err) {\n console.error(`[RecordList] rowAttrs: bad attribute \"${name}\"`, err);\n }\n }\n }\n this._paintActive(li);\n }\n\n _paintActive(li) {\n const on = this._activeKey !== null && li.__recordKey === this._norm(this._activeKey);\n li.classList.toggle('twm-record--active', on);\n if (on) {\n if (li.getAttribute('aria-current') !== 'true') {\n li.setAttribute('aria-current', 'true');\n li.__twmAriaCurrent = true;\n }\n } else if (li.__twmAriaCurrent) {\n li.__twmAriaCurrent = false;\n li.removeAttribute('aria-current');\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\u2500\u2500\u2500\u2500\u2500\n\n /** The ONE record that takes Tab: the one last focused, else the open\n * one, else the first. */\n _paintTabStop() {\n if (!this._keyboard()) return;\n let key = this._tabKey;\n if (key === null || !this._items.has(key)) {\n const active = this._norm(this._activeKey);\n key = active !== null && this._items.has(active) ? active : (this._items.keys().next().value ?? null);\n }\n this._setTabStop(key);\n }\n\n _setTabStop(key) {\n if (!this._keyboard()) return;\n this._tabKey = key ?? null;\n for (const [k, li] of this._items) li.tabIndex = k === this._tabKey ? 0 : -1;\n }\n\n _focusMemo() {\n const doc = this.element.ownerDocument;\n const active = doc?.activeElement;\n if (!active || !this.listElement.contains(active)) return null;\n const li = this._itemOf(active);\n if (!li) return null;\n return { key: li.__recordKey, verb: active.closest('.twm-record__verb')?.dataset.verb ?? null };\n }\n\n _restoreFocus(memo) {\n if (!memo) return;\n const li = this._items.get(memo.key);\n if (!li) return;\n if (memo.verb !== null) {\n const b = [...li.querySelectorAll('.twm-record__verb')].find((x) => x.dataset.verb === memo.verb);\n if (b && !b.disabled) { b.focus(); return; }\n }\n if (this._keyboard()) { this._setTabStop(li.__recordKey); li.focus(); }\n }\n\n _itemOf(target) {\n const li = target?.closest?.('.twm-record');\n return li && this.listElement.contains(li) && li.parentNode === this.listElement ? li : null;\n }\n\n // \u2500\u2500 gestures \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 _gesture(ev, gesture) {\n if (!this._activates() || !this._gestures().has(gesture)) return;\n const li = this._itemOf(ev.target);\n if (!li) return;\n if (!isRowActivation(ev, gesture, { scope: this.listElement })) return;\n this.config.onActivate(li.__record, li.__recordIndex, ev);\n }\n\n _key(ev) {\n if (ev.defaultPrevented) return;\n const li = this._itemOf(ev.target);\n if (!li) return;\n if (ev.key === 'Enter') {\n // Enter on a verb is the verb's; only Enter on the record itself opens it.\n if (ev.target !== li || !this._activates() || !this._gestures().has('enter')) return;\n if (ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey) return;\n ev.preventDefault();\n this.config.onActivate(li.__record, li.__recordIndex, ev);\n return;\n }\n if (!this._keyboard()) return;\n if (ev.target !== li && (ev.target.closest(OWN_ARROWS) || !isRowControl(ev.target, li))) return;\n const items = [...this._items.values()];\n const at = items.indexOf(li);\n let next = null;\n if (ev.key === 'ArrowDown') next = items[Math.min(items.length - 1, at + 1)];\n else if (ev.key === 'ArrowUp') next = items[Math.max(0, at - 1)];\n else if (ev.key === 'Home') next = items[0];\n else if (ev.key === 'End') next = items[items.length - 1];\n else return;\n ev.preventDefault();\n if (next) {\n this._setTabStop(next.__recordKey);\n next.focus();\n }\n }\n}\n\n/**\n * Build a record list, append it to `host` (if given) and draw it.\n *\n * @param {HTMLElement|null} host\n * @param {RecordListConfig} [config]\n * @returns {RecordList}\n */\nexport function createRecordList(host, config = {}) {\n return new RecordList(host, config);\n}\n\n/** One pill: a string, or `{text, tone, title}`. A tone is a word\n * (`muted`, `info`, `success`, `warn`, `danger` are drawn). */\nfunction pill(p) {\n const s = typeof p === 'object' && !(typeof Node !== 'undefined' && p instanceof Node) ? p : { text: p };\n const span = document.createElement('span');\n span.className = 'twm-record__pill' + (s.tone ? ` twm-record__pill--${safeWord(s.tone)}` : '');\n if (typeof Node !== 'undefined' && s.text instanceof Node) span.appendChild(s.text);\n else if (typeof Node !== 'undefined' && p instanceof Node) span.appendChild(p);\n else span.textContent = String(s.text ?? '');\n if (s.title) span.title = String(s.title);\n if (s.tone) span.dataset.tone = safeWord(s.tone);\n return span;\n}\n\n/** Text, a node or nothing, into `el`. */\nfunction appendContent(el, content) {\n if (content == null || content === false) return;\n if (typeof Node !== 'undefined' && content instanceof Node) el.appendChild(content);\n else el.appendChild(document.createTextNode(String(content)));\n}\n", "/**\n * \u2550\u2550 A STACK OF COLLAPSIBLE SECTIONS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * Inspector-style panel content: titled sections, one above the other, each\n * opened and closed from its header (FlexDesk STORY-0036). Until this, only a\n * tree's categories could collapse, and every embedder that wanted a panel of\n * \"Notes / Assistant / Parameters\" built the headers, the arrows and the\n * remembering itself.\n *\n * const stack = createSectionStack(panel, {\n * sections: [\n * { id: 'notes', title: 'Notes', content: notesEl },\n * { id: 'chat', title: 'Assistant', fill: true,\n * actions: [{ id: 'clear', icon: 'delete', label: 'Clear', onClick: clear }] },\n * { id: 'params', title: 'Parameters', defaultExpanded: false },\n * ],\n * key: 'inspector.sections',\n * stateStore: { read: (key) => saved[key], write: (key, map) => { saved[key] = map; } },\n * });\n * stack.body('chat').appendChild(chatEl);\n * const off = stack.on('toggled', ({ id, expanded }) => \u2026);\n *\n * A SECTION is `{ id, title, icon?, content?, actions?, defaultExpanded?, fill? }`.\n * `content` is a Node put into the section's body at mount; `body(id)` hands\n * the same element over for anything mounted later. `defaultExpanded` is true\n * unless it says otherwise.\n *\n * THE HEADER TOGGLES; ITS ACTIONS DO NOT. A click anywhere on the header opens\n * or closes the section and turns its arrow \u2014 except on one of its `actions`\n * (`{ id?, icon, label, title?, onClick(sectionId, event) }`), which runs its\n * own `onClick` and leaves the section as it was.\n *\n * A FILL SECTION (`fill: true`) takes the height the others leave, and its\n * body scrolls inside it (`min-height: 0`), so a long conversation scrolls in\n * its section instead of growing the panel past the window. Give the stack's\n * container a height \u2014 it is `height: 100%` of it.\n *\n * REMEMBERING is the embedder's: `stateStore` is `{ read(key), write(key, map) }`\n * and `map` is `{ [sectionId]: expanded }`, written whenever a section opens or\n * closes. `read` may answer a promise; until it does, sections show their\n * `defaultExpanded`, and a section somebody toggled meanwhile keeps their\n * choice. Such a toggle is written once the read has settled, merged over\n * the stored map, so the defaults on screen never overwrite it. A store that throws, rejects, or answers something that is not a map\n * leaves every section on its `defaultExpanded` \u2014 remembering is a convenience,\n * never a reason for a panel not to draw. `ready` resolves once the read has\n * been applied (at once without a store).\n *\n * `setVisible(id, false)` takes a section off the stack without forgetting it:\n * `setVisible(id, true)` brings it back open or closed exactly as it was.\n *\n * The `toggled` event carries `{ id, expanded, source }`, `source` being\n * `'user'` (a header click), `'api'` (expand / collapse / toggle) or\n * `'restore'` (a stored state that arrived after mount). It fires only on a\n * change. `on()` answers the function that stops listening.\n *\n * `dispose()` removes the one listener the stack adds and every node it made;\n * `content` the embedder handed in goes with its section.\n *\n * Styled by `.twm-collapsible-*` (the tree's primitive) plus `.twm-section-stack*`.\n */\n\n/**\n * @param {HTMLElement} container\n * @param {object} opts\n * @param {Array} opts.sections `{ id, title, icon?, content?, actions?, defaultExpanded?, fill? }`\n * @param {object} [opts.stateStore] `{ read(key): map|Promise<map>, write(key, map) }`\n * @param {string} [opts.key] the key the expanded states live under; required with a store\n */\nexport function createSectionStack(container, { sections = [], stateStore = null, key = null } = {}) {\n if (stateStore && !key) throw new Error('createSectionStack: a stateStore needs a { key }');\n const doc = container.ownerDocument;\n\n const root = doc.createElement('div');\n root.className = 'twm-section-stack';\n\n /** id -> { def, box, toggle, arrow, body, expanded, visible, touched } */\n const byId = new Map();\n /** action button -> { sectionId, action } */\n const actionOf = new Map();\n /** header -> section id */\n const headerOf = new Map();\n const listeners = new Set();\n let disposed = false;\n // While a promised read is out, the sections nobody touched still show\n // their defaults, not what the store holds: writing them then would\n // overwrite the stored states with defaults. A toggle meanwhile only marks\n // the map as owed; it is written once the read has settled.\n let readPending = false;\n let writeOwed = false;\n\n for (const def of sections) {\n if (!def || def.id == null || byId.has(def.id)) {\n throw new Error(`createSectionStack: every section needs a unique id (got ${def?.id})`);\n }\n const expanded = def.defaultExpanded !== false;\n\n const box = doc.createElement('section');\n box.className = 'twm-collapsible-box twm-section-stack__section'\n + (def.fill ? ' twm-section-stack__section--fill' : '');\n\n const header = doc.createElement('div');\n header.className = 'twm-collapsible-header twm-section-stack__header';\n\n const toggle = doc.createElement('button');\n toggle.type = 'button';\n toggle.className = 'twm-section-stack__toggle';\n const arrow = doc.createElement('span');\n arrow.className = 'twm-collapsible-arrow material-symbols-outlined';\n arrow.setAttribute('aria-hidden', 'true');\n arrow.textContent = 'expand_more';\n toggle.appendChild(arrow);\n if (def.icon) {\n const icon = doc.createElement('span');\n icon.className = 'twm-section-stack__icon material-symbols-outlined';\n icon.setAttribute('aria-hidden', 'true');\n icon.textContent = def.icon;\n toggle.appendChild(icon);\n }\n const title = doc.createElement('span');\n title.className = 'twm-section-stack__title';\n title.textContent = def.title ?? String(def.id);\n toggle.appendChild(title);\n header.appendChild(toggle);\n\n if (Array.isArray(def.actions) && def.actions.length) {\n const bar = doc.createElement('div');\n bar.className = 'twm-section-stack__actions';\n for (const action of def.actions) {\n const btn = doc.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-section-stack__action';\n if (action.label) btn.setAttribute('aria-label', action.label);\n if (action.title ?? action.label) btn.setAttribute('title', action.title ?? action.label);\n const glyph = doc.createElement('span');\n glyph.className = 'material-symbols-outlined';\n glyph.setAttribute('aria-hidden', 'true');\n glyph.textContent = action.icon ?? '';\n btn.appendChild(glyph);\n bar.appendChild(btn);\n actionOf.set(btn, { sectionId: def.id, action });\n }\n header.appendChild(bar);\n }\n\n const body = doc.createElement('div');\n body.className = 'twm-collapsible-content twm-section-stack__body';\n if (def.content) body.appendChild(def.content);\n\n box.append(header, body);\n root.appendChild(box);\n headerOf.set(header, def.id);\n const entry = { def, box, toggle, arrow, body, expanded, visible: true, touched: false };\n byId.set(def.id, entry);\n paint(entry);\n }\n\n function paint(entry) {\n entry.box.classList.toggle('twm-section-stack__section--expanded', entry.expanded);\n entry.body.classList.toggle('visible', entry.expanded);\n entry.arrow.classList.toggle('collapsed', !entry.expanded);\n entry.toggle.setAttribute('aria-expanded', String(entry.expanded));\n entry.box.hidden = !entry.visible;\n }\n\n function emit(detail) {\n for (const fn of [...listeners]) {\n try { fn(detail); } catch (err) { console.error('[section-stack] toggled listener failed', err); }\n }\n }\n\n function persist() {\n if (!stateStore?.write) return;\n if (readPending) { writeOwed = true; return; }\n const map = {};\n for (const [id, entry] of byId) map[id] = entry.expanded;\n write(map);\n }\n\n function write(map) {\n try {\n const pending = stateStore.write(key, map);\n pending?.catch?.(() => { /* storage refused: not ours to fix */ });\n } catch { /* storage refused: not ours to fix */ }\n }\n\n /** Set one section's state; true when it changed. */\n function set(id, expanded, source) {\n const entry = byId.get(id);\n if (disposed || !entry || entry.expanded === expanded) return false;\n entry.expanded = expanded;\n if (source !== 'restore') entry.touched = true;\n paint(entry);\n if (source !== 'restore') persist();\n emit({ id, expanded, source });\n return true;\n }\n\n const isMap = (saved) => !!saved && typeof saved === 'object' && !Array.isArray(saved);\n\n function restore(saved, source) {\n if (disposed || !isMap(saved)) return;\n for (const [id, entry] of byId) {\n if (entry.touched || typeof saved[id] !== 'boolean') continue;\n if (source === 'restore') set(id, saved[id], 'restore');\n else { entry.expanded = saved[id]; paint(entry); }\n }\n }\n\n /** A promised read has settled (`saved` is null when it rejected). */\n function settle(saved) {\n restore(saved, 'restore');\n readPending = false;\n if (!writeOwed) return;\n writeOwed = false;\n // The touched sections over what the store holds \u2014 also after a\n // dispose, which must not lose a choice made before the read answered.\n const map = {};\n for (const [id, entry] of byId) {\n map[id] = !entry.touched && isMap(saved) && typeof saved[id] === 'boolean'\n ? saved[id] : entry.expanded;\n }\n write(map);\n }\n\n function onClick(event) {\n const target = event.target;\n const btn = target?.closest?.('.twm-section-stack__action');\n if (btn && actionOf.has(btn)) {\n const { sectionId, action } = actionOf.get(btn);\n event.stopPropagation();\n try { action.onClick?.(sectionId, event); } catch (err) {\n console.error(`[section-stack] action on \"${sectionId}\" failed`, err);\n }\n return;\n }\n const header = target?.closest?.('.twm-section-stack__header');\n if (!header || !headerOf.has(header)) return;\n const id = headerOf.get(header);\n set(id, !byId.get(id).expanded, 'user');\n }\n root.addEventListener('click', onClick);\n\n // Synchronous stored state is applied before the stack is on screen, so it\n // never flashes the defaults; a promise is applied when it answers.\n let ready = Promise.resolve();\n if (stateStore?.read) {\n let saved = null;\n try { saved = stateStore.read(key); } catch { saved = null; }\n if (saved && typeof saved.then === 'function') {\n readPending = true;\n ready = Promise.resolve(saved)\n .then((value) => settle(value), () => settle(null));\n } else {\n restore(saved, 'mount');\n }\n }\n\n container.appendChild(root);\n\n const need = (id) => {\n if (!byId.has(id)) throw new Error(`createSectionStack: no section \"${id}\"`);\n return byId.get(id);\n };\n\n return {\n root,\n ready,\n /** The section's body element, for content mounted after the stack. */\n body: (id) => need(id).body,\n expand(id) { need(id); set(id, true, 'api'); },\n collapse(id) { need(id); set(id, false, 'api'); },\n toggle(id) { set(id, !need(id).expanded, 'api'); },\n isExpanded: (id) => need(id).expanded,\n /** Off the stack, or back on it \u2014 its expanded state is kept either way. */\n setVisible(id, visible) {\n const entry = need(id);\n entry.visible = !!visible;\n paint(entry);\n },\n isVisible: (id) => need(id).visible,\n /** `on('toggled', fn)` \u2014 answers the function that stops listening. */\n on(event, fn) {\n if (event !== 'toggled') throw new Error(`createSectionStack: no \"${event}\" event`);\n if (disposed) return () => {};\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n root.removeEventListener('click', onClick);\n listeners.clear();\n actionOf.clear();\n headerOf.clear();\n root.remove();\n },\n };\n}\n", "/**\n * createSelect \u2014 A SELECT DRAWN IN THE DOM. (0.18.0)\n *\n * A native `<select>` styles down to its closed box: the list is the operating\n * system's, so it cannot show a glyph or a second line, ignores the tokens and\n * opens at the system's type size. `selectBox` (`choice_controls.js`) is the\n * native one, for a list with nothing to say in a tight strip. This one is for\n * the rest: a trigger showing the current value, over a list whose rows have a\n * glyph, a second line and a hint, under group headings, with a search box and,\n * with `allowNew`, a way to type a value nobody listed.\n *\n * THE VALUE IS NEVER SILENTLY CHANGED. A value in none of the options, or naming a\n * disabled one, stays the value and is shown (a disabled option under its label,\n * any other through `notFound`): a list that arrives late or has moved on must not\n * turn it into something else on the next save. Only `null`, `undefined` and `''`\n * with no option of their own read as \"nothing chosen\", showing `placeholder`.\n *\n * Values keep their type, as in `choice_controls.js`; `loose` lets a stored `'2'`\n * name option `2`.\n *\n * Focus stays on the trigger unless there is a search box, which then holds it.\n * Either way the arrow keys move the highlight, named by `aria-activedescendant`,\n * and Tab closes the list and goes on from the trigger.\n */\nimport { openAnchoredLayer } from './anchored_layer.js';\nimport { fireEvent } from '../utils/fire_event.js';\nimport { choiceSections, filterSections, findChoice, flatChoices, shownValue } from './choice_controls.js';\nimport { createOptionList } from './option_list.js';\n\n/** More options than this and a select draws a search box unless told otherwise. */\nconst SEARCH_ABOVE = 7;\n/** Printable keys within this many ms are one word for the type-ahead. */\nconst TYPEAHEAD_MS = 500;\n\nfunction node(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text !== undefined) n.textContent = String(text);\n return n;\n}\n\nfunction glyphNode(className, text = '') {\n const n = node('span', `material-symbols-outlined ${className}`.trim(), text);\n n.setAttribute('aria-hidden', 'true');\n return n;\n}\n\nconst isEmptyValue = (v) => v === null || v === undefined || v === '';\n\n/**\n * @param {object} config\n * @param {Array|(() => Array)} [config.options] Bare values, `{ value, label?, icon?,\n * description?, hint?, keywords?, disabled?, reason? }`, or `{ group, options }`.\n * A function is read each time the list opens and the trigger is painted, for a\n * list that grows while the page lives.\n * @param {*} [config.value]\n * @param {(value: *, option: object|null) => void} [config.onChange] After the reader\n * chooses a different value. `option` is the entry as you gave it, `null` for a\n * new value (`allowNew`). Not called for `value =` or `setOptions`.\n * @param {string} [config.className] Extra classes on the trigger.\n * @param {string} [config.panelClassName] Extra classes on the list's panel.\n * @param {string} [config.placeholder] Shown while nothing is chosen.\n * @param {string} [config.title] The trigger's tooltip; else it says the value.\n * @param {string} [config.ariaLabel] When no `<label>` names the control.\n * @param {boolean} [config.disabled]\n * @param {boolean} [config.showIcon=true] Draw the chosen option's glyph on the trigger too.\n * @param {boolean|{placeholder?: string}} [config.search] The search box. By default it\n * is there with `allowNew` or more than seven options.\n * @param {boolean} [config.allowNew] A value in no option may be typed into the\n * search box; it is offered as its own row at the end of the list.\n * @param {(typed: string) => string} [config.newLabel] That row's words.\n * @param {(value: string) => string} [config.notFound] How an unlisted value reads on the trigger.\n * @param {(typed: string) => string} [config.emptyText] What a list with no rows says.\n * @param {boolean} [config.loose] A stored value names an option of the same text.\n * @param {string} [config.name] A hidden input of this name carries the value\n * as text, for a surrounding form; it fires a bubbling `change` when the reader chooses.\n * @param {HTMLInputElement} [config.carrier] That hidden input, yours, for a field something\n * finds by more than a name (`[data-f]`, an id). Instead of `name`; its attributes are left as they are.\n * @param {'start'|'end'} [config.align]\n * @returns {{el: HTMLElement, input: HTMLInputElement|null, value: *, isOpen: boolean,\n * setOptions: Function, setPlaceholder: Function, setDisabled: Function,\n * open: Function, close: Function, focus: Function, destroy: Function}}\n * `el` is the control to put in your layout: the trigger, or a wrapper round it\n * and the hidden input when there is a `name` or a `carrier`.\n */\nexport function createSelect({\n options = [], value = null, onChange = null, className = '', panelClassName = '', placeholder = 'Choose\u2026',\n title = '', ariaLabel = '', disabled = false, showIcon = true, search = undefined, allowNew = false,\n newLabel = (typed) => `Use \u201C${typed}\u201D`, notFound = (v) => v,\n emptyText = (typed) => (typed ? `Nothing matches \u201C${typed}\u201D.` : 'Nothing to choose from.'),\n loose = false, name = null, carrier = null, align = 'start',\n} = {}) {\n let source = options;\n let current = value;\n let emptyLabel = placeholder;\n let layer = null;\n let typedKeys = '';\n let typedTimer = null;\n\n const given = () => (typeof source === 'function' ? source() : source) || [];\n\n const trigger = node('button', `twm-select${className ? ` ${className}` : ''}`);\n trigger.type = 'button';\n trigger.setAttribute('role', 'combobox');\n trigger.setAttribute('aria-haspopup', 'listbox');\n trigger.setAttribute('aria-expanded', 'false');\n if (ariaLabel) trigger.setAttribute('aria-label', ariaLabel);\n const icon = glyphNode('twm-select__icon');\n const label = node('span', 'twm-select__label');\n trigger.append(icon, label, glyphNode('twm-select__caret', 'expand_more'));\n\n let root = trigger;\n let hidden = carrier;\n if (name && !hidden) {\n hidden = node('input');\n hidden.type = 'hidden';\n hidden.name = name;\n }\n if (hidden) {\n root = node('div', 'twm-select-field');\n root.append(trigger, hidden);\n }\n\n // Whichever holds focus names the active row.\n let focusHolder = trigger;\n const list = createOptionList({\n onPick: (option) => choose(option),\n onActive: (id) => {\n if (id) focusHolder.setAttribute('aria-activedescendant', id);\n else focusHolder.removeAttribute('aria-activedescendant');\n },\n });\n trigger.setAttribute('aria-controls', list.id);\n\n const panel = node('div', `twm-option-panel${panelClassName ? ` ${panelClassName}` : ''}`);\n const searchRow = node('div', 'twm-option-panel__search');\n searchRow.appendChild(glyphNode('', 'search'));\n const searchInput = node('input', 'twm-option-panel__search-input');\n searchInput.type = 'text';\n searchInput.autocomplete = 'off';\n searchInput.spellcheck = false;\n searchInput.setAttribute('role', 'combobox');\n searchInput.setAttribute('aria-expanded', 'true');\n searchInput.setAttribute('aria-autocomplete', 'list');\n searchInput.setAttribute('aria-controls', list.id);\n searchRow.appendChild(searchInput);\n panel.append(searchRow, list.el);\n\n const hasSearch = () => (search === undefined\n ? allowNew || flatChoices(given()).length > SEARCH_ABOVE\n : !!search);\n\n function paint() {\n const flat = flatChoices(given());\n const chosen = findChoice(flat, current, loose);\n const none = !chosen && isEmptyValue(current);\n label.textContent = chosen ? chosen.label : none ? emptyLabel : notFound(shownValue(current));\n trigger.classList.toggle('twm-select--empty', none);\n trigger.title = title || label.textContent;\n const glyph = showIcon ? (chosen?.icon || '') : '';\n icon.textContent = glyph;\n icon.hidden = !glyph;\n if (hidden) hidden.value = isEmptyValue(current) ? '' : shownValue(current);\n }\n\n /** The rows for what is typed, a new-value row after them when it is offered. */\n function draw(typed) {\n const text = typed.trim();\n const all = choiceSections(given());\n const flat = all.flatMap((s) => s.items);\n const taken = (o) => [o.value, o.label].some((v) => shownValue(v).toLowerCase() === text.toLowerCase());\n const shown = filterSections(all, text);\n if (allowNew && text !== '' && !flat.some(taken)) {\n shown.push({ heading: null, items: [{ value: text, label: newLabel(text), icon: 'add', description: null,\n hint: null, disabled: false, reason: null, keywords: null,\n source: null }] });\n }\n const chosen = findChoice(flat, current, loose);\n if (shown.length) {\n list.setRows(shown, { mark: text, isCurrent: (o) => o === chosen });\n // On the current value when it is showing, else on the first row that may be chosen.\n const at = list.options().indexOf(chosen);\n if (at >= 0 && !chosen.disabled) list.setActive(at);\n else list.moveToEnd(1);\n } else {\n list.setMessage(emptyText(text));\n }\n layer?.place();\n }\n\n function choose(option) {\n const changed = !(option.value === current || (loose && String(option.value) === String(current)));\n current = option.value;\n paint();\n layer?.close('pick');\n if (!changed) return;\n if (hidden) fireEvent(hidden, 'change', { bubbles: true });\n onChange?.(current, option.source);\n }\n\n function open() {\n if (layer || trigger.disabled) return;\n const searching = hasSearch();\n searchRow.hidden = !searching;\n focusHolder = searching ? searchInput : trigger;\n if (searching) {\n const word = (typeof search === 'object' && search?.placeholder)\n || (allowNew ? 'Search, or type a new one\u2026' : 'Search\u2026');\n searchInput.placeholder = word;\n searchInput.setAttribute('aria-label', word);\n searchInput.value = '';\n }\n panel.style.width = '';\n layer = openAnchoredLayer({\n anchor: trigger, el: panel, align, gap: 4, matchWidth: true,\n onClose() {\n layer = null;\n trigger.classList.remove('twm-is-open');\n trigger.setAttribute('aria-expanded', 'false');\n focusHolder.removeAttribute('aria-activedescendant');\n },\n });\n if (!layer) return; // the trigger is not on the page\n trigger.classList.add('twm-is-open');\n trigger.setAttribute('aria-expanded', 'true');\n // Once it is on the page: the current value has to scroll into view.\n draw('');\n if (searching) {\n // PINNED, or the panel narrows and widens under the pointer as each\n // keystroke hides or shows the longest name in it.\n const width = Math.round(panel.getBoundingClientRect().width);\n if (width > 0) panel.style.width = `${width}px`;\n searchInput.focus({ preventScroll: true });\n }\n }\n\n const close = () => layer?.close('closed');\n\n /** Printable keys on a trigger with no search box walk to the label they begin. */\n function typeAhead(ch) {\n clearTimeout(typedTimer);\n typedTimer = setTimeout(() => { typedKeys = ''; }, TYPEAHEAD_MS);\n typedKeys += ch.toLowerCase();\n const at = list.options().findIndex((o) => !o.disabled && o.label.toLowerCase().startsWith(typedKeys));\n if (at >= 0) list.setActive(at);\n }\n\n function onKey(ev) {\n if (ev.isComposing) return;\n const inSearch = ev.target === searchInput;\n if (!layer) {\n if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp' || ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault();\n open();\n }\n return;\n }\n if (ev.key === 'Tab') {\n // Not taken: focus goes back to the trigger, and the Tab goes on from there.\n layer.close('tab');\n return;\n }\n if (ev.key === 'ArrowDown') list.move(1);\n else if (ev.key === 'ArrowUp') list.move(-1);\n else if (ev.key === 'Home' && !inSearch) list.moveToEnd(1);\n else if (ev.key === 'End' && !inSearch) list.moveToEnd(-1);\n else if (ev.key === 'Enter' || (ev.key === ' ' && !inSearch)) {\n const option = list.activeOption();\n if (option) choose(option);\n else if (!inSearch) close();\n } else if (!inSearch && ev.key.length === 1 && !ev.ctrlKey && !ev.metaKey && !ev.altKey) {\n typeAhead(ev.key);\n } else {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n }\n\n trigger.addEventListener('click', () => { if (layer) close(); else open(); });\n trigger.addEventListener('keydown', onKey);\n // Some browsers click a button on Space's keyup whatever its keydown did.\n trigger.addEventListener('keyup', (ev) => { if (ev.key === ' ') ev.preventDefault(); });\n searchInput.addEventListener('keydown', onKey);\n searchInput.addEventListener('input', () => draw(searchInput.value));\n\n function setDisabled(off) {\n trigger.disabled = !!off;\n if (off) close();\n }\n\n paint();\n setDisabled(disabled);\n\n return {\n el: root,\n /** The hidden input carrying the value, when there is one. */\n input: hidden,\n get value() { return current; },\n set value(next) { current = next; paint(); },\n get isOpen() { return !!layer; },\n /** Replace the list. Pass `nextValue` to change the value as well; left out, it stays. */\n setOptions(nextOptions, nextValue) {\n source = nextOptions;\n if (arguments.length > 1) current = nextValue;\n paint();\n if (layer) draw(searchInput.value);\n },\n /** The text shown while nothing is chosen: \"Loading\u2026\", the failure, \"Choose\u2026\". */\n setPlaceholder(text) { emptyLabel = text; paint(); },\n setDisabled,\n open,\n close,\n focus() { trigger.focus(); },\n /** Closes the list and takes the control off the page. */\n destroy() {\n clearTimeout(typedTimer);\n close();\n root.remove();\n },\n };\n}\n", "/**\n * SettingsView \u2014 the settings page, drawn from a settings store's schema.\n *\n * const view = new SettingsView({ store, eventBus }); // the bus the store emits on\n * view.mount(host);\n * view.selectCategory('window');\n * view.setQuery('shadow');\n * view.dispose();\n *\n * // or as tile content:\n * createShell({ content: { settings: settingsViewContent({ store, eventBus }) } });\n *\n * `store` is a `createSettingsStore()` handle, or the app-global binding's own\n * (`getSettingsStore()` in `@flexdesk/core`). The view knows no setting: every\n * category, group, label, description and control comes from the store's\n * `getCategories()` and `getSchema()`.\n *\n * THE LAYOUT. A sidebar with a filter box, the categories in their\n * `CategoryDef.order` and *Reset all*; beside it the chosen category's\n * settings under its title, description and *Reset category*, grouped by\n * `SettingDef.group` in schema order. Each row shows its label, a *Modified*\n * marker while its value differs from its default, its description, its path,\n * its control and a reset button. Text typed in the filter searches every\n * category's labels, descriptions and paths, and the matches are listed\n * under their category and group.\n *\n * THE CONTROLS, one per `SettingDef.type`:\n * boolean a ToggleField\n * select a select over `options`\n * number a number box with `min`, `max` and `step`; a value written is\n * snapped to the step (counted from `min`) and clamped to the range,\n * and a box left empty or unreadable goes back to the value\n * text a text box written `textDebounceMs` after the last keystroke,\n * or at once on Enter or blur; emptied, it writes `null` when the\n * default is `null`, else `''`\n * colorList a ColorListField, written on every committed edit while every\n * row holds a colour\n * A type the view does not know shows the value as text, read only.\n *\n * LIVE, BOTH WAYS. A control writes through `store.set()`. The view listens\n * on `eventBus` for `settings:<path>:changed` for every path in the schema,\n * for `settings:changed` with a null path (the resets) and for\n * `settings:registered` (a slice registered after mount: its categories join\n * the sidebar and its settings their category, without a remount). A value\n * changed elsewhere moves its control and its marker. An edit still being\n * typed (a text before its debounce, digits before 'change') is written\n * before the view redraws or syncs its rows, so it is never dropped.\n *\n * RESETS. A row's reset button resets that setting. *Reset category* and\n * *Reset all* ask `confirm(\u2026)` first (default `openConfirm`) and change\n * nothing unless it resolves true.\n *\n * THE SIDEBAR ELSEWHERE (0.17.2). `sidebar: false` leaves the sidebar out:\n * the view is the content alone. A `SettingsCategories` bound to it, mounted\n * anywhere, draws the filter box, the categories and *Reset all* instead:\n *\n * const view = new SettingsView({ store, eventBus, sidebar: false });\n * view.mount(pageHost);\n * const cats = new SettingsCategories({ view });\n * cats.mount(navigatorHost);\n *\n * Both draw from the view's state, so the filter text and the selected\n * category are the same in both, whichever moved them; `view.subscribe(fn)`\n * tells any other listener. *Reset all* there is `view.resetAll()`, so it asks\n * to confirm as before.\n *\n * Every word on screen that comes from the schema, the store or the user is\n * set as text, so a label or a query holding markup is shown as typed.\n *\n * Markup: `.twm-settings` > `.twm-settings__sidebar` (`__search` >\n * `__search-input`, `__nav` > `button.__cat` [`--active`], `__reset-all`)\n * + `.twm-settings__content` (`__header` > `__title`, `__description`,\n * `__reset-category`; `section.__group` > `__group-title` + `.__row`\n * [`--modified`] > `__info` (`__label`, `__marker`, `__description`,\n * `__path`) + `__control` + `__reset`; `__empty`). A `SettingsCategories` is\n * `.twm-settings-categories` > `.twm-settings__search`, `.twm-settings__nav`\n * and `.twm-settings__reset-all`, the same parts as the sidebar's.\n */\n\nimport { ComponentBase } from '../base/component_base.js';\nimport { ToggleField } from './toggle_field.js';\nimport { ColorListField } from './color_list_field.js';\nimport { selectBox, shownValue } from './choice_controls.js';\nimport { openConfirm } from './modal.js';\n\n/** Milliseconds between the last keystroke in a text setting and its write. */\nexport const SETTINGS_TEXT_DEBOUNCE_MS = 300;\n\nfunction el(tag, className, text) {\n const n = document.createElement(tag);\n if (className) n.className = className;\n if (text !== undefined && text !== null) n.textContent = String(text);\n return n;\n}\n\nfunction icon(name) {\n const n = el('span', 'material-symbols-outlined', name);\n n.setAttribute('aria-hidden', 'true');\n return n;\n}\n\nfunction same(a, b) {\n if (a === b) return true;\n if (a == null || b == null) return a == null && b == null;\n if (typeof a !== typeof b || typeof a !== 'object') return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n const ka = Object.keys(a);\n const kb = Object.keys(b);\n return ka.length === kb.length && ka.every((k) => same(a[k], b[k]));\n}\n\n/**\n * A number written by a number row, always both in range and on the step grid\n * (`min + k * step`, or `k * step` with no `min`): snapped to the nearest grid\n * point, and a point outside [min, max] is moved inward to the nearest grid\n * point inside. `min` is itself a grid point, so the range holds none only\n * when `max < min`; the value is then `min`. With no step it is only clamped.\n */\nfunction fitNumber(n, { min, max, step }) {\n const lo = min != null && Number.isFinite(Number(min)) ? Number(min) : null;\n const hi = max != null && Number.isFinite(Number(max)) ? Number(max) : null;\n const s = Number(step);\n if (!(Number.isFinite(s) && s > 0)) {\n let v = n;\n if (hi != null) v = Math.min(hi, v);\n if (lo != null) v = Math.max(lo, v);\n return v;\n }\n const base = lo ?? 0;\n const places = (x) => (String(x).split('.')[1] || '').length;\n const decimals = Math.max(places(s), places(base));\n const at = (k) => Number((base + k * s).toFixed(decimals));\n const EPS = 1e-9;\n let k = Math.round((n - base) / s);\n if (hi != null && at(k) > hi) k = Math.floor((hi - base) / s + EPS);\n if (lo != null && at(k) < lo) k = Math.ceil((lo - base) / s - EPS);\n return at(k);\n}\n\n// \u2500\u2500 the sidebar's parts, drawn alike by SettingsView and SettingsCategories \u2500\u2500\n\n/** The filter box: `{ label, input }`; `onInput(text)` on every keystroke. */\nfunction filterBox(onInput) {\n const label = el('label', 'twm-settings__search');\n const input = el('input', 'twm-settings__search-input');\n input.type = 'search';\n input.placeholder = 'Filter settings\u2026';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.setAttribute('aria-label', 'Filter settings');\n input.addEventListener('input', () => onInput(input.value));\n label.append(icon('search'), input);\n return { label, input };\n}\n\n/** The category list; `onSelect(id)` when a category is clicked. */\nfunction categoryNav(onSelect) {\n const nav = el('nav', 'twm-settings__nav');\n nav.setAttribute('aria-label', 'Settings categories');\n nav.addEventListener('click', (e) => {\n const btn = e.target.closest?.('[data-category]');\n if (btn && nav.contains(btn)) onSelect(btn.dataset.category);\n });\n return nav;\n}\n\n/** Draw `categories` into `nav`, `active` (an id, or null) marked. */\nfunction paintCategories(nav, categories, active) {\n const buttons = categories.map((cat) => {\n const b = el('button', 'twm-settings__cat');\n b.type = 'button';\n b.dataset.category = cat.id;\n if (cat.id === active) {\n b.classList.add('twm-settings__cat--active');\n b.setAttribute('aria-current', 'page');\n }\n b.append(icon(cat.icon || 'tune'), el('span', 'twm-settings__cat-label', cat.label ?? cat.id));\n if (cat.description) b.title = String(cat.description);\n return b;\n });\n nav.replaceChildren(...buttons);\n}\n\n/** The *Reset all* button; `onClick()` when pressed. */\nfunction resetAllButton(onClick) {\n const b = el('button', 'twm-btn twm-settings__reset-all');\n b.type = 'button';\n b.append(icon('restart_alt'), el('span', '', 'Reset all'));\n b.addEventListener('click', () => { onClick(); });\n return b;\n}\n\nexport class SettingsView extends ComponentBase {\n /**\n * @param {object} o\n * @param {object} o.store a settings store (`createSettingsStore()` / `getSettingsStore()`)\n * @param {object} o.eventBus the bus the store emits on\n * @param {Function} [o.confirm] `({title, message, confirmLabel, danger}) -> Promise<boolean>`\n * @param {string} [o.category] the category shown first (default: the first)\n * @param {number} [o.textDebounceMs]\n * @param {string} [o.title='Settings'] the sidebar heading\n * @param {boolean} [o.sidebar=true] false leaves the sidebar (filter,\n * categories, *Reset all*) out, for a `SettingsCategories` elsewhere\n */\n constructor({\n store, eventBus, confirm = openConfirm, category = null,\n textDebounceMs = SETTINGS_TEXT_DEBOUNCE_MS, title = 'Settings', sidebar = true, logger,\n } = {}) {\n super({ eventBus, logger });\n if (!store || typeof store.getSchema !== 'function') {\n throw new TypeError('SettingsView: `store` must be a settings store');\n }\n if (!eventBus || typeof eventBus.on !== 'function') {\n throw new TypeError('SettingsView: `eventBus` must be the bus the store emits on');\n }\n this.store = store;\n this._confirm = confirm;\n this._category = category;\n this._query = '';\n this._debounceMs = textDebounceMs;\n this._title = title;\n this._sidebar = sidebar !== false;\n /** `fn({ category, query })` after the category, the filter or the categories change. */\n this._listeners = new Set();\n\n this.root = null;\n this._nav = null;\n this._content = null;\n this._search = null;\n /** path -> { sync(), flush(), dispose() } for the rows on screen. */\n this._rows = new Map();\n /** path -> the bus subscription handle, for every schema path. */\n this._pathSubs = new Map();\n /** Bus subscription handles for the whole-store events. */\n this._subs = [];\n this._disposed = false;\n }\n\n /** Build the view into `container` (once). */\n mount(container) {\n if (this.root) return this.root;\n const root = el('div', 'twm-settings');\n if (this._sidebar) {\n const side = el('aside', 'twm-settings__sidebar');\n const head = el('div', 'twm-settings__sidebar-title');\n head.append(icon('settings'), el('span', '', this._title));\n const search = filterBox((text) => this.setQuery(text));\n this._search = search.input;\n this._nav = categoryNav((id) => this.selectCategory(id));\n side.append(head, search.label, this._nav, resetAllButton(() => this.resetAll()));\n root.append(side);\n }\n\n const content = el('div', 'twm-settings__content');\n this._content = content;\n root.append(content);\n this.root = root;\n container.appendChild(root);\n this._mounted = true;\n\n for (const path of Object.keys(this.store.getSchema())) this.#watch(path);\n this._subs.push(this.eventBus.on('settings:changed', (p) => {\n if (p?.path == null) this.#syncAll();\n }));\n this._subs.push(this.eventBus.on('settings:registered', (p) => this.#onRegistered(p)));\n\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n return root;\n }\n\n /** The category on screen (its id), or null. */\n getCategory() { return this.#activeCategory()?.id ?? null; }\n\n /** The filter text. */\n getQuery() { return this._query; }\n\n /** True while the filter is in effect (its trimmed text is not empty). */\n isFiltering() { return this.#searching(); }\n\n /**\n * `fn({ category, query })` after every change of the category, the filter\n * or the registered categories, until the view is disposed. Answers the\n * unsubscribe.\n */\n subscribe(fn) {\n this._listeners.add(fn);\n return () => this._listeners.delete(fn);\n }\n\n /** Show one category; clears the filter. */\n selectCategory(id) {\n if (!this.root) return;\n if (!this.store.getCategories().some((c) => c.id === id)) return;\n this._category = id;\n this._query = '';\n if (this._search) this._search.value = '';\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n }\n\n /** Search every category; an empty query goes back to the category. */\n setQuery(query) {\n if (!this.root) return;\n const q = String(query ?? '');\n this._query = q;\n if (this._search && this._search.value !== q) this._search.value = q;\n this.#paintNav();\n this.#paintContent();\n this.#notify();\n }\n\n /** Reset one category after `confirm`; resolves true when it was reset. */\n async resetCategory(id = this.getCategory()) {\n const cat = this.store.getCategories().find((c) => c.id === id);\n if (!cat) return false;\n const ok = await this._confirm({\n title: 'Reset category',\n message: `Reset every setting in \u201C${cat.label ?? cat.id}\u201D to its default?`,\n confirmLabel: 'Reset',\n danger: true,\n });\n if (!ok || this._disposed) return false;\n this.#flushAll();\n this.store.resetCategory(id);\n this.#syncAll();\n return true;\n }\n\n /** Reset every setting after `confirm`; resolves true when they were reset. */\n async resetAll() {\n const ok = await this._confirm({\n title: 'Reset all settings',\n message: 'Reset every setting to its default?',\n confirmLabel: 'Reset all',\n danger: true,\n });\n if (!ok || this._disposed) return false;\n this.#flushAll();\n this.store.resetAll();\n this.#syncAll();\n return true;\n }\n\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n this.#flushAll();\n this.#dropRows();\n for (const sub of this._pathSubs.values()) sub.dispose();\n this._pathSubs.clear();\n for (const sub of this._subs) sub.dispose();\n this._subs = [];\n this.root?.remove();\n this.root = null;\n this._nav = null;\n this._content = null;\n this._search = null;\n this._listeners.clear();\n super.dispose();\n }\n\n // \u2500\u2500 store events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #watch(path) {\n if (this._pathSubs.has(path)) return;\n this._pathSubs.set(path, this.eventBus.on(`settings:${path}:changed`, () => {\n this._rows.get(path)?.sync();\n }));\n }\n\n #onRegistered({ paths = [] } = {}) {\n if (!this.root) return;\n const schema = this.store.getSchema();\n for (const path of Object.keys(schema)) this.#watch(path);\n this.#paintNav();\n const active = this.getCategory();\n const touches = this.#searching()\n || !this._rows.size\n || paths.some((p) => schema[p]?.category === active);\n if (touches) {\n this.#paintContent();\n } else {\n // The slice's defaults may have moved values on screen; an edit still\n // being typed is written first, so the sync shows it rather than drop it.\n this.#flushAll();\n this.#syncAll();\n }\n this.#notify();\n }\n\n /** True while a filter is in effect: the trimmed query is not empty. */\n #searching() {\n return this._query.trim() !== '';\n }\n\n #syncAll() {\n for (const row of this._rows.values()) row.sync();\n }\n\n #flushAll() {\n for (const row of this._rows.values()) row.flush();\n }\n\n #dropRows() {\n for (const row of this._rows.values()) row.dispose();\n this._rows.clear();\n }\n\n // \u2500\u2500 painting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #activeCategory() {\n const cats = this.store.getCategories();\n return cats.find((c) => c.id === this._category) ?? cats[0] ?? null;\n }\n\n #paintNav() {\n if (!this._nav) return;\n paintCategories(this._nav, this.store.getCategories(), this.#searching() ? null : this.getCategory());\n }\n\n /** Tell the listeners, after the content is drawn (it settles the category). */\n #notify() {\n const state = { category: this.getCategory(), query: this._query };\n for (const fn of [...this._listeners]) fn(state);\n }\n\n #paintContent() {\n this.#flushAll();\n this.#dropRows();\n const schema = this.store.getSchema();\n const content = this._content;\n content.replaceChildren();\n\n if (this.#searching()) {\n const q = this._query.trim().toLowerCase();\n const cats = this.store.getCategories();\n const labelOf = new Map(cats.map((c) => [c.id, c.label ?? c.id]));\n const rank = new Map(cats.map((c, i) => [c.id, i]));\n const matches = Object.entries(schema)\n .filter(([path, def]) => [def.label, def.description, path]\n .some((t) => t != null && String(t).toLowerCase().includes(q)))\n .map(([path, def]) => ({ path, ...def }));\n matches.sort((a, b) => (rank.get(a.category) ?? Infinity) - (rank.get(b.category) ?? Infinity));\n\n const header = el('header', 'twm-settings__header');\n const info = el('div', 'twm-settings__header-info');\n const n = matches.length;\n info.append(el('h2', 'twm-settings__title',\n `${n} result${n === 1 ? '' : 's'} for \u201C${this._query.trim()}\u201D`));\n header.append(info);\n content.append(header);\n if (!n) {\n content.append(el('div', 'twm-settings__empty', 'No setting matches the filter.'));\n return;\n }\n this.#paintGroups(matches, (def) =>\n `${labelOf.get(def.category) ?? def.category ?? ''} \u203A ${def.group || 'General'}`);\n return;\n }\n\n const cat = this.#activeCategory();\n if (!cat) {\n content.append(el('div', 'twm-settings__empty', 'No settings.'));\n return;\n }\n // The page drawn is the category: a slice registered later, ordered\n // before it, must not move the sidebar marker or getCategory() off it.\n this._category = cat.id;\n const header = el('header', 'twm-settings__header');\n const info = el('div', 'twm-settings__header-info');\n info.append(el('h2', 'twm-settings__title', cat.label ?? cat.id));\n if (cat.description) info.append(el('p', 'twm-settings__description', cat.description));\n const reset = el('button', 'twm-btn twm-settings__reset-category');\n reset.type = 'button';\n reset.append(icon('restart_alt'), el('span', '', 'Reset category'));\n reset.addEventListener('click', () => { this.resetCategory(cat.id); });\n header.append(info, reset);\n content.append(header);\n\n const defs = Object.entries(schema)\n .filter(([, def]) => def.category === cat.id)\n .map(([path, def]) => ({ path, ...def }));\n if (!defs.length) {\n content.append(el('div', 'twm-settings__empty', 'No settings in this category.'));\n return;\n }\n this.#paintGroups(defs, (def) => def.group || 'General');\n }\n\n #paintGroups(defs, groupTitle) {\n const groups = new Map();\n for (const def of defs) {\n const key = groupTitle(def);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key).push(def);\n }\n for (const [title, list] of groups) {\n const section = el('section', 'twm-settings__group');\n section.append(el('h3', 'twm-settings__group-title', title));\n for (const def of list) section.append(this.#row(def));\n this._content.append(section);\n }\n }\n\n // \u2500\u2500 rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #row(def) {\n const { path } = def;\n const store = this.store;\n const row = el('div', 'twm-settings__row');\n row.dataset.path = path;\n\n const info = el('div', 'twm-settings__info');\n const labelLine = el('div', 'twm-settings__label-line');\n const label = el('span', 'twm-settings__label', def.label ?? path);\n const marker = el('span', 'twm-settings__marker', 'Modified');\n labelLine.append(label, marker);\n info.append(labelLine);\n if (def.description) info.append(el('div', 'twm-settings__description', def.description));\n info.append(el('code', 'twm-settings__path', path));\n\n const slot = el('div', 'twm-settings__control');\n const control = this.#control(def, (value) => store.set(path, value));\n slot.append(control.el);\n\n const reset = el('button', 'twm-settings__reset');\n reset.type = 'button';\n reset.title = 'Reset to default';\n reset.setAttribute('aria-label', `Reset ${def.label ?? path} to default`);\n reset.append(icon('restart_alt'));\n reset.addEventListener('click', () => {\n control.cancel?.();\n store.resetOne(path);\n });\n\n row.append(info, slot, reset);\n\n const sync = () => {\n const value = store.get(path);\n control.show(value);\n const modified = !same(value, store.getDefault(path));\n row.classList.toggle('twm-settings__row--modified', modified);\n marker.hidden = !modified;\n reset.hidden = !modified;\n };\n sync();\n this._rows.set(path, {\n sync,\n flush: () => control.flush?.(),\n dispose: () => control.dispose?.(),\n });\n return row;\n }\n\n /** `{ el, show(value), flush?(), cancel?(), dispose?() }` for one setting. */\n #control(def, write) {\n const name = def.label ?? def.path;\n switch (def.type) {\n case 'boolean': {\n const t = new ToggleField({\n checked: !!this.store.get(def.path), ariaLabel: name, compact: true,\n onChange: (on) => write(on),\n });\n return {\n el: t.render(),\n show: (v) => { if (t.get() !== !!v) t.set(!!v); },\n dispose: () => t.dispose(),\n };\n }\n case 'select': {\n const c = selectBox(def.options || [], this.store.get(def.path), {\n label: name, valueAttr: 'value', className: 'twm-settings__select',\n });\n c.box.addEventListener('change', () => {\n // Redrawn as a fresh mount draws the chosen value, so a stray\n // '(not found)' entry goes once an offered option is picked.\n const v = c.valueOf();\n c.setOptions(def.options || [], v);\n write(v);\n });\n return {\n el: c.box,\n // Redrawn with the new value, as a fresh mount draws it: a\n // value the options lack shows as its '(not found)' entry, and\n // a stray entry left from an earlier value goes.\n show: (v) => { if (!same(c.valueOf(), v)) c.setOptions(def.options || [], v); },\n };\n }\n case 'number': {\n const box = el('input', 'twm-settings__number');\n box.type = 'number';\n box.setAttribute('aria-label', name);\n if (def.min != null) box.min = String(def.min);\n if (def.max != null) box.max = String(def.max);\n if (def.step != null) box.step = String(def.step);\n // Digits typed but not yet committed by 'change'.\n let dirty = false;\n const show = (v) => {\n dirty = false;\n const text = v == null ? '' : String(v);\n if (box.value !== text) box.value = text;\n };\n const commit = () => {\n const current = this.store.get(def.path);\n const n = box.value.trim() === '' ? NaN : Number(box.value);\n if (!Number.isFinite(n)) { show(current); return; }\n const v = fitNumber(n, def);\n show(v);\n if (!same(v, current)) write(v);\n };\n box.addEventListener('input', () => { dirty = true; });\n box.addEventListener('change', commit);\n return {\n el: box,\n show,\n flush: () => { if (dirty) commit(); },\n };\n }\n case 'text': {\n const box = el('input', 'twm-settings__text');\n box.type = 'text';\n box.setAttribute('aria-label', name);\n if (def.placeholder != null) box.placeholder = String(def.placeholder);\n let timer = null;\n const valueOf = () => (box.value === '' && def.defaultValue === null ? null : box.value);\n const cancel = () => { if (timer !== null) { clearTimeout(timer); timer = null; } };\n const commit = () => {\n const v = valueOf();\n if (!same(v, this.store.get(def.path))) write(v);\n };\n const flush = () => {\n if (timer === null) return;\n cancel();\n commit();\n };\n box.addEventListener('input', () => {\n cancel();\n timer = setTimeout(() => { timer = null; commit(); }, this._debounceMs);\n });\n box.addEventListener('change', flush);\n box.addEventListener('keydown', (e) => { if (e.key === 'Enter') flush(); });\n return {\n el: box,\n show: (v) => {\n const text = v == null ? '' : String(v);\n if (box.value === text) return;\n cancel();\n box.value = text;\n },\n flush,\n cancel,\n dispose: cancel,\n };\n }\n case 'colorList': {\n const value = this.store.get(def.path);\n const f = new ColorListField({\n value: Array.isArray(value) ? value : [],\n onChange: (colors, { commit }) => { if (commit && colors) write(colors); },\n });\n return {\n el: f.render(),\n show: (v) => {\n const list = Array.isArray(v) ? v : [];\n if (!same(f.getValue(), list)) f.setValue(list);\n },\n dispose: () => f.dispose(),\n };\n }\n default: {\n const out = el('span', 'twm-settings__readonly');\n return {\n el: out,\n show: (v) => { out.textContent = shownValue(v); },\n };\n }\n }\n }\n}\n\n/**\n * SettingsCategories \u2014 a SettingsView's filter box, category list and\n * *Reset all*, mounted wherever the app wants them (0.17.2).\n *\n * const view = new SettingsView({ store, eventBus, sidebar: false });\n * view.mount(pageHost);\n * const cats = new SettingsCategories({ view });\n * cats.mount(navigatorHost);\n * cats.dispose(); // before or with the view\n *\n * It holds no state of its own: typing in its filter is `view.setQuery()`,\n * clicking a category `view.selectCategory()`, *Reset all* `view.resetAll()`\n * (which asks the view's `confirm` first), and it redraws from the view on\n * every `view.subscribe()` call. So the filter text and the selected category\n * are always the view's, however either side moved them, and a category\n * registered later joins the list. Its clicks and keystrokes act once the\n * view is mounted.\n *\n * Markup: `.twm-settings-categories` > `.twm-settings__search` (>\n * `__search-input`), `.twm-settings__nav` > `button.twm-settings__cat`\n * [`--active`], `.twm-settings__reset-all`.\n */\nexport class SettingsCategories extends ComponentBase {\n /**\n * @param {object} o\n * @param {SettingsView} o.view the view it lists the categories of\n */\n constructor({ view, logger } = {}) {\n if (!(view instanceof SettingsView)) {\n throw new TypeError('SettingsCategories: `view` must be a SettingsView');\n }\n super({ eventBus: view.eventBus, logger });\n this.view = view;\n this.root = null;\n this._search = null;\n this._nav = null;\n this._unsubscribe = null;\n }\n\n /** Build the list into `container` (once). */\n mount(container) {\n if (this.root) return this.root;\n const view = this.view;\n const root = el('div', 'twm-settings-categories');\n const search = filterBox((text) => view.setQuery(text));\n this._search = search.input;\n this._nav = categoryNav((id) => view.selectCategory(id));\n root.append(search.label, this._nav, resetAllButton(() => view.resetAll()));\n this.root = root;\n container.appendChild(root);\n this._mounted = true;\n this._unsubscribe = view.subscribe(() => this.#paint());\n this.#paint();\n return root;\n }\n\n dispose() {\n this._unsubscribe?.();\n this._unsubscribe = null;\n this.root?.remove();\n this.root = null;\n this._search = null;\n this._nav = null;\n super.dispose();\n }\n\n #paint() {\n const view = this.view;\n const q = view.getQuery();\n if (this._search.value !== q) this._search.value = q;\n paintCategories(this._nav, view.store.getCategories(), view.isFiltering() ? null : view.getCategory());\n }\n}\n\n/**\n * A content factory for the shell: `(hostEl, props, ctx) -> { title, destroy }`.\n * `props.category` picks the category shown first.\n *\n * @param {object} opts as `new SettingsView(opts)`\n * @returns {Function}\n */\nexport function settingsViewContent(opts = {}) {\n return (hostEl, props = {}) => {\n const view = new SettingsView({ ...opts, category: props?.category ?? opts.category ?? null });\n view.mount(hostEl);\n return {\n title: opts.title ?? 'Settings',\n view,\n destroy: () => view.dispose(),\n };\n };\n}\n", "/**\n * A range slider with optional companions: a linked number box, a readout, a\n * default with a modified state and a reset button, and an enable toggle.\n *\n * Every companion is opt-in through `field`; with none of them the DOM is the\n * range and the helper line, exactly as before.\n *\n * field.min / max / step / value the range (defaults 0 / 100 / 1 / min)\n * field.numberInput true: an editable number box, two-way synced\n * field.readout true, or (value: number) => string\n * field.defaultValue enables the modified state and a reset button\n * field.toggleable true: an enable checkbox before the slider\n * field.enabled the toggle's initial state (default true)\n * field.disabledValue what onChange reports while toggled off (default null)\n * field.emitOnInput also report every drag frame ({ immediate: true })\n * field.disabled / helperText as before\n *\n * onChange(value, { immediate }) receives the slider's value as a string \u2014 the\n * range input's own value, as it always has \u2014 or `disabledValue` while the\n * toggle is off. A commit that leaves the reported value where it was reports\n * nothing, so setValue/setRange/setEnabled cannot echo back into the caller\n * that drove them.\n */\nexport class SliderField {\n #min = 0;\n #max = 100;\n #step = 1;\n #value = 0;\n #enabled = true;\n #hasDefault = false;\n #defaultValue = 0;\n\n constructor({ fieldId, field = {}, onChange = null, logger = null } = {}) {\n if (!fieldId) {\n throw new Error('SliderField requires a fieldId');\n }\n this.fieldId = fieldId;\n this.field = field;\n this.logger = logger;\n this.onChange = typeof onChange === 'function' ? onChange : null;\n\n this.root = null;\n this.sliderInput = null;\n this.numberInput = null;\n this.readoutEl = null;\n this.resetButton = null;\n this.toggleInput = null;\n this.helperEl = null;\n this.emitOnInput = Boolean(field.emitOnInput ?? field.emitsOnInput);\n this._disposers = [];\n\n this.#min = this.#coerceNumber(field.min, 0);\n this.#max = Math.max(this.#min, this.#coerceNumber(field.max, 100));\n this.#step = this.#coercePositiveNumber(field.step, 1);\n this.#value = this.#fit(this.#coerceNumber(field.value, this.#min));\n this.#enabled = field.toggleable ? field.enabled !== false : true;\n this.#hasDefault = this.#isFiniteInput(field.defaultValue);\n if (this.#hasDefault) {\n this.#defaultValue = this.#fit(Number(field.defaultValue));\n }\n }\n\n render() {\n if (this.root) {\n return this.root;\n }\n this.root = document.createElement('div');\n this.root.className = 'twm-slider-field';\n\n this.sliderInput = document.createElement('input');\n this.sliderInput.type = 'range';\n this.sliderInput.className = 'twm-slider-field__input';\n this.#writeRangeAttributes();\n\n // Prevent parent interactions from interfering with slider dragging\n // Use stopImmediatePropagation to ensure no other handlers on this element run\n // DO NOT call preventDefault - allow native slider drag behavior\n const stopDrag = (evt) => {\n evt.stopPropagation();\n evt.stopImmediatePropagation();\n };\n // Use capture phase to intercept before any parent handlers\n this.#listen(this.sliderInput, 'mousedown', stopDrag, { capture: true });\n this.#listen(this.sliderInput, 'touchstart', stopDrag, { passive: false, capture: true });\n\n this.helperEl = document.createElement('div');\n this.helperEl.className = 'twm-slider-field__helper';\n if (this.field.helperText) {\n this.helperEl.textContent = this.field.helperText;\n }\n\n const companions = this.field.toggleable || this.field.numberInput\n || this.field.readout || this.#hasDefault;\n if (companions) {\n const row = document.createElement('div');\n row.className = 'twm-slider-field__row';\n if (this.field.toggleable) {\n row.appendChild(this.#buildToggle());\n }\n row.appendChild(this.sliderInput);\n if (this.field.readout) {\n this.readoutEl = document.createElement('span');\n this.readoutEl.className = 'twm-slider-field__readout';\n row.appendChild(this.readoutEl);\n }\n if (this.field.numberInput) {\n row.appendChild(this.#buildNumberInput());\n }\n if (this.#hasDefault) {\n row.appendChild(this.#buildResetButton());\n }\n this.root.appendChild(row);\n } else {\n this.root.appendChild(this.sliderInput);\n }\n this.root.appendChild(this.helperEl);\n\n // Throttle onInput to animation frames to avoid re-render stutter while dragging\n let rafToken = null;\n let pendingValue = null;\n const flushPending = () => {\n if (rafToken) {\n cancelAnimationFrame(rafToken);\n rafToken = null;\n }\n if (pendingValue === null) return;\n const valueToEmit = pendingValue;\n pendingValue = null;\n if (this.emitOnInput) {\n this.onChange?.(valueToEmit, { immediate: true });\n }\n };\n\n const handleInput = (event) => {\n // The companions follow the thumb on every frame; onChange waits for release.\n this.#value = this.#fit(Number(event.target.value));\n this.#syncCompanions();\n pendingValue = event.target.value;\n if (!rafToken) {\n rafToken = requestAnimationFrame(() => {\n rafToken = null;\n flushPending();\n });\n }\n };\n const handleChange = (event) => {\n flushPending();\n this.#value = this.#fit(Number(event.target.value));\n this.#syncCompanions();\n this.onChange?.(event.target.value, { immediate: false });\n };\n this.#listen(this.sliderInput, 'input', handleInput);\n this.#listen(this.sliderInput, 'change', handleChange);\n\n this.#syncCompanions();\n return this.root;\n }\n\n /** What onChange would report now: the value as a string, or disabledValue while toggled off. */\n getValue() {\n return this.#enabled ? String(this.#value) : this.#disabledValue();\n }\n\n isEnabled() {\n return this.#enabled;\n }\n\n /** True when a defaultValue was given and the value differs from it. */\n isModified() {\n return this.#hasDefault && this.#value !== this.#defaultValue;\n }\n\n /**\n * Clamp to the range and snap to the step. Reports once, unless `silent` or\n * the reported value did not move. A non-finite value is refused (false).\n */\n setValue(value, { silent = false } = {}) {\n if (!this.#isFiniteInput(value)) {\n return false;\n }\n const numeric = Number(value);\n return this.#commit(() => { this.#value = this.#fit(numeric); }, silent);\n }\n\n setEnabled(enabled, { silent = false } = {}) {\n return this.#commit(() => { this.#enabled = Boolean(enabled); }, silent);\n }\n\n /** Change any of min/max/step; the value and the default are refitted into the new range. */\n setRange({ min, max, step } = {}, { silent = false } = {}) {\n return this.#commit(() => {\n this.#min = this.#isFiniteInput(min) ? Number(min) : this.#min;\n this.#max = Math.max(this.#min, this.#isFiniteInput(max) ? Number(max) : this.#max);\n this.#step = this.#coercePositiveNumber(step, this.#step);\n this.#value = this.#fit(this.#value);\n if (this.#hasDefault) {\n this.#defaultValue = this.#fit(this.#defaultValue);\n }\n if (this.sliderInput) {\n this.#writeRangeAttributes();\n }\n }, silent);\n }\n\n /** Restore defaultValue and report it, a commit like a drag release. */\n reset({ silent = false } = {}) {\n if (!this.#hasDefault) {\n return false;\n }\n return this.#commit(() => { this.#value = this.#defaultValue; }, silent);\n }\n\n dispose() {\n this._disposers.forEach((dispose) => {\n try {\n dispose?.();\n } catch (error) {\n this.logger?.warn?.('twm-slider-field', 'Failed to dispose slider listener', { error });\n }\n });\n this._disposers = [];\n this.root = null;\n this.sliderInput = null;\n this.numberInput = null;\n this.readoutEl = null;\n this.resetButton = null;\n this.toggleInput = null;\n this.helperEl = null;\n }\n\n #buildToggle() {\n this.toggleInput = document.createElement('input');\n this.toggleInput.type = 'checkbox';\n this.toggleInput.className = 'twm-slider-field__toggle';\n this.toggleInput.setAttribute('aria-label', 'Enabled');\n if (this.field.disabled) {\n this.toggleInput.disabled = true;\n }\n this.#listen(this.toggleInput, 'change', () => this.setEnabled(this.toggleInput.checked));\n return this.toggleInput;\n }\n\n #buildNumberInput() {\n this.numberInput = document.createElement('input');\n this.numberInput.type = 'text';\n this.numberInput.inputMode = 'decimal';\n this.numberInput.className = 'twm-slider-field__number';\n this.numberInput.setAttribute('aria-label', 'Value');\n // A typed value that is not a finite number is refused and the box shows the value again.\n const commitTyped = () => {\n if (!this.setValue(this.numberInput.value.trim())) {\n this.#syncCompanions();\n }\n };\n this.#listen(this.numberInput, 'keydown', (event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commitTyped();\n } else if (event.key === 'Escape') {\n this.#syncCompanions();\n }\n });\n this.#listen(this.numberInput, 'change', commitTyped);\n return this.numberInput;\n }\n\n #buildResetButton() {\n this.resetButton = document.createElement('button');\n this.resetButton.type = 'button';\n this.resetButton.className = 'twm-slider-field__reset';\n this.resetButton.title = 'Reset to default';\n this.resetButton.setAttribute('aria-label', 'Reset to default');\n const icon = document.createElement('span');\n icon.className = 'material-symbols-outlined';\n icon.textContent = 'restart_alt';\n this.resetButton.appendChild(icon);\n this.#listen(this.resetButton, 'click', () => this.reset());\n return this.resetButton;\n }\n\n /** Apply a change, refresh the DOM, and report once if the reported value moved. */\n #commit(apply, silent) {\n const before = this.getValue();\n apply();\n this.#syncCompanions();\n const after = this.getValue();\n if (after === before) {\n return false;\n }\n if (!silent) {\n this.onChange?.(after, { immediate: false });\n }\n return true;\n }\n\n /** Write the model into every element: slider, box, readout, toggle, states. */\n #syncCompanions() {\n if (!this.root) return;\n const text = String(this.#value);\n if (this.sliderInput.value !== text) {\n this.sliderInput.value = text;\n }\n const off = !this.#enabled;\n const hardDisabled = Boolean(this.field.disabled);\n this.sliderInput.disabled = hardDisabled || off;\n if (this.numberInput) {\n this.numberInput.value = text;\n this.numberInput.disabled = hardDisabled || off;\n }\n if (this.readoutEl) {\n const format = typeof this.field.readout === 'function' ? this.field.readout : null;\n this.readoutEl.textContent = format ? String(format(this.#value)) : text;\n }\n if (this.toggleInput) {\n this.toggleInput.checked = this.#enabled;\n }\n const modified = this.isModified();\n if (this.resetButton) {\n this.resetButton.disabled = hardDisabled || off || !modified;\n }\n this.root.classList.toggle('twm-slider-field--modified', modified);\n this.root.classList.toggle('twm-slider-field--off', off);\n }\n\n #writeRangeAttributes() {\n this.sliderInput.min = String(this.#min);\n this.sliderInput.max = String(this.#max);\n this.sliderInput.step = String(this.#step);\n this.sliderInput.value = String(this.#value);\n }\n\n /** Clamp to [min, max] and snap to the step grid anchored at min, as a range input does. */\n #fit(value) {\n const clamped = Math.min(this.#max, Math.max(this.#min, value));\n let snapped = this.#min + Math.round((clamped - this.#min) / this.#step) * this.#step;\n if (snapped > this.#max) snapped -= this.#step;\n const decimals = Math.max(this.#decimals(this.#step), this.#decimals(this.#min));\n return Number(snapped.toFixed(Math.min(decimals, 12)));\n }\n\n #decimals(value) {\n const text = String(value);\n if (text.includes('e-')) return Number(text.split('e-')[1]);\n const dot = text.indexOf('.');\n return dot === -1 ? 0 : text.length - dot - 1;\n }\n\n #isFiniteInput(value) {\n if (value === null || value === undefined || typeof value === 'boolean') {\n return false;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return false;\n }\n return Number.isFinite(Number(value));\n }\n\n #disabledValue() {\n return this.field.disabledValue === undefined ? null : this.field.disabledValue;\n }\n\n #listen(target, type, handler, options) {\n target.addEventListener(type, handler, options);\n this._disposers.push(() => target.removeEventListener(type, handler, options));\n }\n\n #coerceNumber(value, fallback) {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : fallback;\n }\n\n #coercePositiveNumber(value, fallback) {\n const numeric = this.#coerceNumber(value, fallback);\n if (numeric <= 0) {\n return fallback;\n }\n return numeric;\n }\n}\n", "/**\n * table_state_store.js \u2014 persist DataTable view-state (sort, filters,\n * column widths), keyed by a caller-supplied `persistKey`.\n *\n * A FACTORY, not a singleton: the store reads and writes through a Host's\n * `state` capability (see ui/js/host/host.js) under one logical state key.\n * One blob holds a map of `{ [persistKey]: state }` for every persisted table.\n * Where that key lands on disk is the embedder's business, not ours \u2014 it is\n * decided by the host's `resolvePath`.\n *\n * A host without a `state` capability is legal: tables simply stay ephemeral.\n *\n * The in-memory cache must be dropped when the project changes (the app swaps\n * projects in-place without a page reload) \u2014 `reset()` is wired to the\n * `project:opened` event in app_bootstrap.\n */\n\n/**\n * @param {object} opts\n * @param {object} opts.host a Host. May lack `state` -> tables become ephemeral.\n * @param {string} opts.key logical state key, e.g. 'datatable_state'\n * @param {object} [opts.logger]\n * @param {number} [opts.debounceMs=500]\n */\nexport function createTableStateStore({ host, key, logger = console, debounceMs = 500 }) {\n if (!key) throw new Error('createTableStateStore requires { key }');\n const state = host?.state || null;\n\n let cache = null; // { [persistKey]: state } \u2014 null until first load\n let loadPromise = null;\n let saveTimer = null;\n\n const scheduleSave = () => {\n if (saveTimer) clearTimeout(saveTimer);\n saveTimer = setTimeout(async () => {\n saveTimer = null;\n if (!state || !cache) return;\n try { await state.write(key, cache); }\n catch (err) { logger.warn?.('[table-state] save failed', err); }\n }, debounceMs);\n };\n\n return {\n /** Resolve once the persisted blob has been read into the cache. Safe\n * to call repeatedly \u2014 the read happens at most once per project. */\n ready() {\n if (loadPromise) return loadPromise;\n loadPromise = (async () => {\n if (!state) { cache = {}; return cache; }\n try { cache = (await state.read(key)) || {}; }\n catch (err) { logger.warn?.('[table-state] load failed', err); cache = {}; }\n return cache;\n })();\n return loadPromise;\n },\n\n /** Synchronous read of a table's persisted state. Returns null until\n * the cache is loaded (await `ready()` first to be sure). */\n get(k) {\n if (!k || !cache) return null;\n return cache[k] || null;\n },\n\n /** Merge-and-persist a table's state (debounced). Pass null to forget\n * a key. Writes the whole map back atomically through the host. */\n set(k, s) {\n if (!k) return;\n if (!cache) cache = {};\n if (s == null) delete cache[k]; else cache[k] = s;\n scheduleSave();\n },\n\n /** Drop the cache + pending read so the next access reloads from the\n * newly-opened project. Cancels any in-flight save for the old one. */\n reset() {\n cache = null;\n loadPromise = null;\n if (saveTimer) { clearTimeout(saveTimer); saveTimer = null; }\n },\n };\n}\n", "/**\n * Tree View Component\n *\n * A reusable hierarchical tree view component for displaying nested data.\n * Used by Functions Page (modules/functions) and Data Page (datasets/series).\n *\n * Structure:\n * - TreeView: Container for multiple categories\n * - TreeCategory: Top-level collapsible group (e.g., \"Built-in\", \"Project\")\n * - TreeNode: Expandable node with children (e.g., module, dataset)\n * - TreeItem: Leaf item (e.g., function, series)\n */\n\n/**\n * Labels, subtitles and badge text are TEXT, set with `textContent` after the\n * skeleton is built (BUG-0013): a dataset called 'A <b>B</b>' is shown as\n * those characters, and a name carrying `<img onerror>` runs nothing.\n */\nfunction setText(root, selector, value) {\n const el = root.querySelector(selector);\n if (el) el.textContent = value == null ? '' : String(value);\n}\n\n/**\n * An id as the value of a double-quoted attribute selector (BUG-0013).\n * NOT `CSS.escape`: jsdom does not provide it (see modal.js). Inside a quoted\n * attribute value `\"` and `\\` are escaped, and a line break, which would end\n * the string, becomes its hex escape.\n */\nfunction attrValue(value) {\n return String(value)\n .replace(/[\"\\\\]/g, '\\\\$&')\n .replace(/[\\n\\r\\f]/g, (c) => `\\\\${c.charCodeAt(0).toString(16)} `);\n}\n\n/**\n * Create a tree category (top-level collapsible section)\n * @param {Object} options - Category options\n * @param {string} options.id - Unique category ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon name\n * @param {string} [options.iconClass] - Additional icon CSS class\n * @param {number} [options.count] - Item count to display\n * @param {boolean} [options.expanded=false] - Initial expanded state\n * @param {boolean} [options.readonly=false] - Whether items are readonly\n * @returns {HTMLElement} - Category element\n */\nexport function createTreeCategory(options) {\n const {\n id,\n label,\n icon = 'folder',\n iconClass = '',\n count = 0,\n expanded = false,\n readonly = false,\n } = options;\n\n const node = document.createElement('div');\n node.className = 'twm-collapsible-box twm-tree-category';\n node.dataset.categoryId = id;\n node.dataset.collapsibleId = `tree-category-${id}`;\n node.dataset.collapsibleDefault = expanded ? 'expanded' : 'collapsed';\n if (readonly) node.dataset.readonly = 'true';\n\n node.innerHTML = `\n <div class=\"twm-collapsible-header\" data-collapsible-header=\"true\">\n <button class=\"twm-arrow-toggle\" type=\"button\">\n <span class=\"twm-collapsible-arrow material-symbols-outlined${expanded ? '' : ' collapsed'}\">expand_more</span>\n </button>\n <span class=\"twm-tree-category__icon ${iconClass}\">\n <span class=\"material-symbols-outlined\">${icon}</span>\n </span>\n <span class=\"twm-tree-category__label\"></span>\n <span class=\"twm-tree-category__count\">(${count})</span>\n </div>\n <div class=\"twm-collapsible-content${expanded ? ' visible' : ''}\" data-collapsible-content=\"true\"></div>\n `;\n setText(node, '.twm-tree-category__label', label);\n\n return node;\n}\n\n/**\n * Create a tree node (expandable container with children)\n * @param {Object} options - Node options\n * @param {string} options.id - Unique node ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon name (optional)\n * @param {number} [options.count] - Child count to display\n * @param {boolean} [options.expanded=false] - Initial expanded state\n * @param {boolean} [options.readonly=false] - Whether node is readonly\n * @param {Object} [options.actions] - Action buttons config\n * @returns {HTMLElement} - Node element\n */\nexport function createTreeNode(options) {\n const {\n id,\n label,\n icon = null,\n count = 0,\n expanded = false,\n readonly = false,\n actions = null,\n } = options;\n\n const node = document.createElement('div');\n node.className = `twm-tree-node${readonly ? ' readonly' : ''}`;\n node.dataset.nodeId = id;\n\n const iconHtml = icon\n ? `<span class=\"twm-tree-node__icon\"><span class=\"material-symbols-outlined\">${icon}</span></span>`\n : '';\n\n const actionsHtml = actions ? '<span class=\"twm-tree-node__actions\"></span>' : '';\n\n node.innerHTML = `\n <div class=\"twm-tree-node__header\">\n <span class=\"twm-tree-node__toggle\">\n <span class=\"material-symbols-outlined\">${expanded ? 'expand_more' : 'chevron_right'}</span>\n </span>\n ${iconHtml}\n <span class=\"twm-tree-node__label\"></span>\n <span class=\"twm-tree-node__count\">(${count})</span>\n ${actionsHtml}\n </div>\n <div class=\"twm-tree-node__children\" style=\"display: ${expanded ? 'block' : 'none'};\"></div>\n `;\n setText(node, '.twm-tree-node__label', label);\n\n if (actions) appendActionButtons(node.querySelector('.twm-tree-node__actions'), id, actions);\n\n return node;\n}\n\n/**\n * Fill a node's or an item's actions slot: one `.twm-tree-node__action-btn`\n * per entry. A click on an entry with `onClick` runs `onClick(id, event)` and\n * goes no further, so it neither selects the item nor toggles the node; nor\n * does a double-click, so it never reaches TreeView's onItemDoubleClick.\n * @param {HTMLElement} actionsEl\n * @param {string} id - The node's or item's id\n * @param {Object<string, { icon: string, title?: string, onClick?: Function }>} actions\n */\nfunction appendActionButtons(actionsEl, id, actions) {\n Object.entries(actions).forEach(([actionId, actionConfig]) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-tree-node__action-btn';\n btn.dataset.action = actionId;\n btn.title = actionConfig.title || actionId;\n btn.innerHTML = `<span class=\"material-symbols-outlined\">${actionConfig.icon}</span>`;\n if (actionConfig.onClick) {\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n actionConfig.onClick(id, e);\n });\n btn.addEventListener('dblclick', (e) => e.stopPropagation());\n }\n actionsEl.appendChild(btn);\n });\n}\n\n/**\n * Create a tree item (leaf node)\n * @param {Object} options - Item options\n * @param {string} options.id - Unique item ID\n * @param {string} options.label - Display label\n * @param {string} [options.icon] - Material icon or symbol (e.g., '\u0192', 'insights')\n * @param {boolean} [options.isMaterialIcon=true] - Whether icon is Material icon\n * @param {boolean} [options.readonly=false] - Whether item is readonly\n * @param {boolean} [options.selected=false] - Whether item is selected\n * @param {string} [options.subtitle] - Optional subtitle text\n * @param {Object} [options.data] - Additional data to attach\n * @param {Object} [options.badge] - Optional badge config\n * @param {string} [options.badge.text] - Badge text (if empty, renders as status dot)\n * @param {string} [options.badge.variant] - 'muted'|'pass'|'fail'|'error'\n * @param {Object} [options.actions] - Row actions, as createTreeNode takes them\n * ({ id: { icon, title, onClick(id, event) } }): buttons in one line at the\n * row's end (`.twm-tree-item__actions`), shown on hover, on focus within and\n * on the selected item\n * @returns {HTMLElement} - Item element\n */\nexport function createTreeItem(options) {\n const {\n id,\n label,\n icon = null,\n isMaterialIcon = true,\n readonly = false,\n selected = false,\n subtitle = null,\n data = null,\n badge = null,\n actions = null,\n } = options;\n\n const item = document.createElement('div');\n item.className = `twm-tree-item${readonly ? ' readonly' : ''}${selected ? ' selected' : ''}`;\n item.dataset.itemId = id;\n\n // Attach custom data\n if (data) {\n Object.entries(data).forEach(([key, value]) => {\n item.dataset[key] = value;\n });\n }\n\n const iconHtml = icon\n ? isMaterialIcon\n ? `<span class=\"twm-tree-item__icon\"><span class=\"material-symbols-outlined\">${icon}</span></span>`\n : `<span class=\"twm-tree-item__icon twm-tree-item__icon--symbol\">${icon}</span>`\n : '';\n\n const subtitleHtml = subtitle\n ? '<span class=\"twm-tree-item__subtitle\"></span>'\n : '';\n\n let badgeHtml = '';\n if (badge) {\n const variant = badge.variant || 'muted';\n if (badge.text) {\n badgeHtml = `<span class=\"twm-tree-item__badge twm-tree-item__badge--${variant}\"></span>`;\n } else {\n badgeHtml = `<span class=\"twm-tree-item__status-dot twm-tree-item__status-dot--${variant}\"></span>`;\n }\n }\n\n item.innerHTML = `\n ${iconHtml}\n <span class=\"twm-tree-item__label\"></span>\n ${subtitleHtml}\n ${badgeHtml}\n `;\n setText(item, '.twm-tree-item__label', label);\n if (subtitle) setText(item, '.twm-tree-item__subtitle', subtitle);\n if (badge?.text) setText(item, '.twm-tree-item__badge', badge.text);\n\n if (actions) {\n const actionsEl = document.createElement('span');\n actionsEl.className = 'twm-tree-item__actions';\n appendActionButtons(actionsEl, id, actions);\n item.appendChild(actionsEl);\n }\n\n return item;\n}\n\n/**\n * Toggle a collapsible category\n * @param {HTMLElement} categoryEl - Category element\n * @param {boolean} [force] - Force specific state (true = expand, false = collapse)\n */\nexport function toggleCategory(categoryEl, force) {\n if (!categoryEl) return;\n\n const arrow = categoryEl.querySelector(':scope > .twm-collapsible-header .twm-collapsible-arrow');\n const content = categoryEl.querySelector(':scope > .twm-collapsible-content');\n\n if (!content) return;\n\n // Determine whether we should expand\n // force=true means expand, force=false means collapse, undefined means toggle\n const isCurrentlyExpanded = content.classList.contains('visible');\n const shouldExpand = force !== undefined ? force : !isCurrentlyExpanded;\n\n if (shouldExpand) {\n // Expand\n if (arrow) {\n arrow.classList.remove('collapsed');\n }\n content.classList.add('visible');\n } else {\n // Collapse\n if (arrow) {\n arrow.classList.add('collapsed');\n }\n content.classList.remove('visible');\n }\n}\n\n/**\n * Toggle a tree node\n * @param {HTMLElement} nodeEl - Node element\n * @param {boolean} [force] - Force specific state\n */\nexport function toggleNode(nodeEl, force) {\n if (!nodeEl) return;\n\n const toggle = nodeEl.querySelector(':scope > .twm-tree-node__header .twm-tree-node__toggle .material-symbols-outlined');\n const children = nodeEl.querySelector(':scope > .twm-tree-node__children');\n\n if (!children) return;\n\n const isExpanded = force !== undefined\n ? force\n : children.style.display === 'none';\n\n if (isExpanded) {\n children.style.display = 'block';\n if (toggle) toggle.textContent = 'expand_more';\n } else {\n children.style.display = 'none';\n if (toggle) toggle.textContent = 'chevron_right';\n }\n}\n\n/**\n * Filter tree items by text match\n *\n * An item is shown when its label contains the filter. A node or a category is\n * shown when any tree item inside it is shown, whether the item sits directly\n * in it or deeper inside nodes. An empty filter shows everything, so clearing\n * the filter restores the whole tree, empty nodes and categories included.\n *\n * @param {HTMLElement} container - Tree container\n * @param {string} filter - Filter text (case-insensitive)\n * @param {Object} [options] - Filter options\n * @param {boolean} [options.expandMatches=true] - Auto-expand nodes with matches\n */\nexport function filterTree(container, filter, options = {}) {\n const { expandMatches = true } = options;\n const normalizedFilter = (filter || '').toLowerCase().trim();\n\n const visibleItems = new Set();\n container.querySelectorAll('.twm-tree-item').forEach((item) => {\n const label = item.querySelector('.twm-tree-item__label')?.textContent || '';\n const matches = !normalizedFilter || label.toLowerCase().includes(normalizedFilter);\n item.style.display = matches ? '' : 'none';\n item.classList.toggle('twm-filter-match', matches && !!normalizedFilter);\n if (matches) visibleItems.add(item);\n });\n\n const hasVisibleItem = (el) => !normalizedFilter\n || [...el.querySelectorAll('.twm-tree-item')].some((item) => visibleItems.has(item));\n\n container.querySelectorAll('.twm-tree-node').forEach((node) => {\n const visible = hasVisibleItem(node);\n node.style.display = visible ? '' : 'none';\n if (expandMatches && visible && normalizedFilter) toggleNode(node, true);\n });\n\n container.querySelectorAll('.twm-tree-category').forEach((category) => {\n const visible = hasVisibleItem(category);\n category.style.display = visible ? '' : 'none';\n if (expandMatches && visible && normalizedFilter) toggleCategory(category, true);\n });\n}\n\n/**\n * Select a tree item\n * @param {HTMLElement} container - Tree container\n * @param {string} itemId - Item ID to select\n * @param {Object} [options] - Selection options\n * @param {boolean} [options.scrollIntoView=true] - Scroll item into view\n * @param {boolean} [options.expandParents=true] - Expand parent nodes\n */\nexport function selectItem(container, itemId, options = {}) {\n const { scrollIntoView = true, expandParents = true } = options;\n\n // Deselect all\n container.querySelectorAll('.twm-tree-item.selected').forEach((el) => {\n el.classList.remove('selected');\n });\n\n // Find and select item\n const item = container.querySelector(`.twm-tree-item[data-item-id=\"${attrValue(itemId)}\"]`);\n if (!item) return null;\n\n item.classList.add('selected');\n\n // Expand parent nodes\n if (expandParents) {\n let parent = item.parentElement;\n while (parent && parent !== container) {\n if (parent.classList.contains('twm-tree-node__children')) {\n const node = parent.closest('.twm-tree-node');\n if (node) toggleNode(node, true);\n }\n if (parent.classList.contains('twm-collapsible-content')) {\n const category = parent.closest('.twm-tree-category');\n if (category) toggleCategory(category, true);\n }\n parent = parent.parentElement;\n }\n }\n\n // Scroll into view\n if (scrollIntoView) {\n item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n\n return item;\n}\n\n/**\n * TreeView class for managing a complete tree structure\n */\nexport class TreeView {\n constructor(container, options = {}) {\n this.container = container;\n this.options = {\n onItemClick: null,\n onItemDoubleClick: null,\n onNodeToggle: null,\n onCategoryToggle: null,\n ...options,\n };\n\n this._boundHandleClick = this._handleClick.bind(this);\n this._boundHandleDblClick = this._handleDoubleClick.bind(this);\n\n if (container) {\n container.classList.add('twm-tree-view');\n container.addEventListener('click', this._boundHandleClick);\n container.addEventListener('dblclick', this._boundHandleDblClick);\n }\n }\n\n _handleClick(e) {\n // Handle category toggle\n const collapsibleHeader = e.target.closest('.twm-collapsible-header');\n if (collapsibleHeader) {\n const category = collapsibleHeader.closest('.twm-tree-category');\n if (category) {\n toggleCategory(category);\n this.options.onCategoryToggle?.(category.dataset.categoryId, category);\n }\n return;\n }\n\n // Handle node toggle\n const nodeHeader = e.target.closest('.twm-tree-node__header');\n if (nodeHeader) {\n const node = nodeHeader.closest('.twm-tree-node');\n if (node) {\n toggleNode(node);\n this.options.onNodeToggle?.(node.dataset.nodeId, node);\n }\n return;\n }\n\n // Handle item click\n const item = e.target.closest('.twm-tree-item');\n if (item) {\n this.select(item.dataset.itemId);\n this.options.onItemClick?.(item.dataset.itemId, item, e);\n }\n }\n\n _handleDoubleClick(e) {\n const item = e.target.closest('.twm-tree-item');\n if (item) {\n this.options.onItemDoubleClick?.(item.dataset.itemId, item, e);\n }\n }\n\n addCategory(options) {\n const category = createTreeCategory(options);\n this.container.appendChild(category);\n return category;\n }\n\n addNode(categoryId, options) {\n const category = this.container.querySelector(`.twm-tree-category[data-category-id=\"${attrValue(categoryId)}\"]`);\n const content = category?.querySelector('.twm-collapsible-content');\n if (!content) return null;\n\n const node = createTreeNode(options);\n content.appendChild(node);\n return node;\n }\n\n addItem(nodeId, options) {\n const node = this.container.querySelector(`.twm-tree-node[data-node-id=\"${attrValue(nodeId)}\"]`);\n const children = node?.querySelector('.twm-tree-node__children');\n if (!children) return null;\n\n const item = createTreeItem(options);\n children.appendChild(item);\n return item;\n }\n\n select(itemId) {\n return selectItem(this.container, itemId);\n }\n\n filter(text) {\n filterTree(this.container, text);\n }\n\n clear() {\n this.container.innerHTML = '';\n }\n\n dispose() {\n if (this.container) {\n this.container.removeEventListener('click', this._boundHandleClick);\n this.container.removeEventListener('dblclick', this._boundHandleDblClick);\n }\n }\n}\n\nexport default TreeView;\n", "/**\n * WindowTaskbar - Singleton component that manages minimized windows in the global bottom bar.\n *\n * Listens for window events and renders taskbar buttons for minimized windows.\n * Integrates with the existing global-bottom-bar element.\n */\n\nimport { ManagedWindow } from './managed_window.js';\n\nclass WindowTaskbarManager {\n constructor() {\n this._minimizedWindows = new Map(); // id -> { title, icon }\n this._containerEl = null;\n this._leftDivider = null;\n this._rightDivider = null;\n this._initialized = false;\n }\n\n /**\n * Initialize the taskbar. Call once after DOM is ready.\n */\n init() {\n if (this._initialized) return;\n\n // Find or create the container in the global bottom bar\n const bottomBar = document.querySelector('.twm-global-bottom-bar');\n if (!bottomBar) {\n console.warn('[WindowTaskbar] twm-global-bottom-bar not found');\n return;\n }\n\n // Create left divider (always present but hidden when no windows)\n this._leftDivider = document.createElement('div');\n this._leftDivider.className = 'twm-bar-windows__divider twm-bar-windows__divider--left';\n\n // Insert bar-windows container between bar-left and bar-center\n this._containerEl = document.createElement('div');\n this._containerEl.className = 'twm-bar-windows';\n\n // Create right divider (shown when there are windows)\n this._rightDivider = document.createElement('div');\n this._rightDivider.className = 'twm-bar-windows__divider twm-bar-windows__divider--right';\n\n const barCenter = bottomBar.querySelector('.twm-bar-center');\n if (barCenter) {\n bottomBar.insertBefore(this._rightDivider, barCenter);\n bottomBar.insertBefore(this._containerEl, this._rightDivider);\n bottomBar.insertBefore(this._leftDivider, this._containerEl);\n } else {\n bottomBar.appendChild(this._leftDivider);\n bottomBar.appendChild(this._containerEl);\n bottomBar.appendChild(this._rightDivider);\n }\n\n // Listen for window events\n window.addEventListener('managed-window-minimized', (e) => this._onWindowMinimized(e));\n window.addEventListener('managed-window-restored', (e) => this._onWindowRestored(e));\n window.addEventListener('managed-window-closed', (e) => this._onWindowClosed(e));\n\n this._initialized = true;\n this._updateDividers();\n }\n\n /**\n * Handle window minimized event.\n */\n _onWindowMinimized(e) {\n const { id, title, icon } = e.detail;\n this._minimizedWindows.set(id, { title, icon });\n this._render();\n }\n\n /**\n * Handle window restored event.\n */\n _onWindowRestored(e) {\n const { id } = e.detail;\n this._minimizedWindows.delete(id);\n this._render();\n }\n\n /**\n * Handle window closed event.\n */\n _onWindowClosed(e) {\n const { id } = e.detail;\n this._minimizedWindows.delete(id);\n this._render();\n }\n\n /**\n * Update divider visibility based on window count.\n */\n _updateDividers() {\n const hasWindows = this._minimizedWindows.size > 0;\n if (this._leftDivider) {\n this._leftDivider.style.display = hasWindows ? '' : 'none';\n }\n if (this._rightDivider) {\n this._rightDivider.style.display = hasWindows ? '' : 'none';\n }\n }\n\n /**\n * Render the taskbar buttons.\n */\n _render() {\n if (!this._containerEl) return;\n\n this._containerEl.innerHTML = '';\n\n for (const [id, { title, icon }] of this._minimizedWindows) {\n const btn = document.createElement('button');\n btn.className = 'twm-bar-windows__item';\n btn.setAttribute('data-window-id', id);\n btn.title = `Restore: ${title}`;\n\n // Add icon\n if (icon) {\n const iconEl = document.createElement('span');\n iconEl.className = 'twm-bar-windows__item-icon material-symbols-outlined';\n iconEl.textContent = icon;\n btn.appendChild(iconEl);\n }\n\n // Add title\n const titleEl = document.createElement('span');\n titleEl.className = 'twm-bar-windows__item-title';\n titleEl.textContent = title;\n btn.appendChild(titleEl);\n\n btn.addEventListener('click', () => {\n ManagedWindow.restore(id);\n });\n this._containerEl.appendChild(btn);\n }\n\n this._updateDividers();\n }\n}\n\n// Singleton instance\nexport const WindowTaskbar = new WindowTaskbarManager();\n", "/**\n * Wizard \u2014 a multi-step flow: a step indicator, a body slot and a footer with\n * Cancel, Back and Next/Finish, every step gated by its own `canAdvance`.\n *\n * Usage:\n * const wizard = new Wizard({\n * data: { file: null }, // yours; every hook sees it as ctx.data\n * steps: [\n * { id: 'source', label: 'Source', icon: 'upload_file',\n * render(bodyEl, ctx) { \u2026 ; return () => { \u2026 } }, // optional cleanup function\n * canAdvance: (ctx) => ctx.data.file\n * ? { ok: true } : { ok: false, hint: 'Choose a file first' } },\n * { id: 'review', label: 'Review', render(bodyEl, ctx) { \u2026 } },\n * ],\n * onFinish: async (ctx) => { \u2026 }, // rejects \u2192 the step shows the error\n * onCancel: (ctx) => { \u2026 },\n * });\n * wizard.mount(hostEl); // inline \u2026\n * wizard.openInWindow({ id: 'import', title: 'Import' }); // \u2026 or in a window\n *\n * Steps are drawn done / current / upcoming / error and joined by a connector.\n * A done (or errored) step BEFORE the current one is a button that jumps back;\n * a step after it is inert, so the only way forward is Next, through the gate.\n *\n * `canAdvance(ctx)` is asked whenever the footer is drawn, and `revalidate()`\n * draws it again \u2014 the body is rendered once per visit, never by a revalidate,\n * so an input the user is typing into keeps its focus and its value.\n *\n * Every move goes through a core StateMachine:\n *\n * step \u2500\u2500move\u2500\u2500\u25B6 step (guard: back to a visited step, or forward\n * \u2502 one step through the gate)\n * \u251C\u2500\u2500finish\u2500\u2500\u25B6 finishing \u2500\u2500resolve\u2500\u2500\u25B6 finished (closes)\n * \u2502 \u2502\n * \u2502 \u2514\u2500\u2500reject\u2500\u2500\u25B6 step (the step shows the error)\n * \u2514\u2500\u2500cancel\u2500\u2500\u25B6 cancelled (closes, calls onCancel)\n *\n * While `finishing`, every button is disabled and no move is accepted, so an\n * async finish cannot be raced by a click. `finished` and `cancelled` are final:\n * onCancel runs once however many times Cancel is pressed.\n *\n * State lives in this instance only; the DOM carries classes and ARIA, never a\n * data attribute.\n */\nimport { ComponentBase } from '../base/component_base.js';\nimport { StateMachine } from '../../core/state_machine.js';\nimport { ManagedWindow } from './managed_window.js';\n\nconst DEFAULT_LABELS = Object.freeze({\n back: 'Back',\n next: 'Next',\n finish: 'Finish',\n cancel: 'Cancel',\n});\n\nconst OPEN = 'step';\nconst FINISHING = 'finishing';\nconst FINISHED = 'finished';\nconst CANCELLED = 'cancelled';\n\n/** Steps own one override: an error and its message. Everything else about a\n * step's look follows from where it is relative to the current one. */\nconst STEP_STATES = Object.freeze(['error']);\n\nconst isFinal = (state) => state === FINISHED || state === CANCELLED;\n\n/** A step's render may hand back a cleanup function, run when the step is\n * left and on dispose(). */\nfunction runCleanup(cleanup) {\n if (typeof cleanup === 'function') cleanup();\n}\n\nfunction messageOf(err) {\n if (err && typeof err.message === 'string' && err.message) return err.message;\n return err == null ? 'Failed' : String(err);\n}\n\nexport class Wizard extends ComponentBase {\n\n /** @type {Array<object>} */ #steps;\n /** @type {object} */ #labels;\n /** @type {Function|null} */ #onFinish;\n /** @type {Function|null} */ #onCancel;\n /** @type {object} */ #ctx;\n /** @type {StateMachine} */ #machine;\n /** @type {number} */ #index = 0;\n /** @type {Map<string,{state:string,message:string}>} */ #overrides = new Map();\n /** @type {*} */ #cleanup = null;\n /** @type {Promise} */ #queue = Promise.resolve();\n /** @type {ManagedWindow|null} */ #window = null;\n /** @type {boolean} */ #disposed = false;\n\n /** @type {HTMLElement|null} */ #root = null;\n /** @type {HTMLElement[]} */ #stepItems = [];\n /** @type {HTMLButtonElement[]} */#stepButtons = [];\n /** @type {HTMLElement[]} */ #connectors = [];\n /** @type {HTMLElement|null} */ #body = null;\n /** @type {HTMLElement|null} */ #message = null;\n /** @type {HTMLButtonElement|null} */ #cancelBtn = null;\n /** @type {HTMLButtonElement|null} */ #backBtn = null;\n /** @type {HTMLButtonElement|null} */ #nextBtn = null;\n\n /**\n * @param {object} opts\n * @param {Array<{id:string,label:string,icon?:string,\n * render:(bodyEl:HTMLElement, ctx:object)=>(Function|void),\n * canAdvance?:(ctx:object)=>{ok:boolean,hint?:string}}>} opts.steps\n * @param {object} [opts.data={}] Your state; every hook reads it as `ctx.data`.\n * @param {Function} [opts.onFinish] `(ctx) => void|Promise`. A rejection marks the\n * current step as error with the rejection's message.\n * @param {Function} [opts.onCancel] `(ctx) => void`, called once when the wizard is cancelled.\n * @param {object} [opts.labels] `{back, next, finish, cancel}` button labels.\n * @param {object} [opts.eventBus] Passed to the StateMachine (its `fsm:*` events).\n * @param {object} [opts.logger] Passed to the StateMachine.\n */\n constructor({ steps, data = {}, onFinish = null, onCancel = null, labels = {},\n eventBus = null, logger = null } = {}) {\n super({ eventBus, logger });\n if (!Array.isArray(steps) || steps.length === 0) {\n throw new Error('Wizard requires at least one step');\n }\n const ids = new Set();\n for (const step of steps) {\n if (!step || typeof step.id !== 'string' || !step.id) {\n throw new Error('Wizard: every step needs a non-empty string id');\n }\n if (ids.has(step.id)) throw new Error(`Wizard: duplicate step id \"${step.id}\"`);\n if (typeof step.render !== 'function') {\n throw new Error(`Wizard: step \"${step.id}\" needs a render(bodyEl, ctx) function`);\n }\n ids.add(step.id);\n }\n this.#steps = steps.slice();\n this.#labels = { ...DEFAULT_LABELS, ...labels };\n this.#onFinish = onFinish;\n this.#onCancel = onCancel;\n\n const wizard = this;\n this.#ctx = Object.freeze({\n data,\n get step() { return wizard.currentStep; },\n get index() { return wizard.currentIndex; },\n revalidate: () => this.revalidate(),\n next: () => this.next(),\n back: () => this.back(),\n goTo: (target) => this.goTo(target),\n setStepState: (id, state, message) => this.setStepState(id, state, message),\n });\n\n this.#machine = new StateMachine({\n name: 'wizard',\n initialState: OPEN,\n eventBus,\n logger,\n states: {\n [OPEN]: {\n transitions: {\n move: {\n target: OPEN,\n guard: ({ payload }) => this.#canMoveTo(payload.to),\n action: ({ payload }) => this.#enterStep(payload.to),\n },\n finish: {\n target: FINISHING,\n guard: () => this.#isLast() && this.#gate().ok,\n action: () => { this.#overrides.delete(this.currentStep); },\n },\n cancel: { target: CANCELLED },\n },\n },\n [FINISHING]: {\n transitions: {\n resolve: { target: FINISHED },\n reject: {\n target: OPEN,\n action: ({ payload }) => {\n this.#overrides.set(this.currentStep,\n { state: 'error', message: messageOf(payload.error) });\n },\n },\n },\n },\n [FINISHED]: { onEnter: () => this.#close() },\n [CANCELLED]: {\n onEnter: () => {\n this.#close();\n this.#onCancel?.(this.#ctx);\n },\n },\n },\n });\n }\n\n // \u2500\u2500\u2500 Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Mount inline into `container` and render the first step.\n * @param {HTMLElement} container\n * @returns {Wizard}\n */\n mount(container) {\n if (this._mounted) return this;\n this.#build();\n container.appendChild(this.#root);\n this._mounted = true;\n this.#renderBody();\n this.#paint();\n return this;\n }\n\n /**\n * Mount in a ManagedWindow and show it. The window's close button and\n * Escape cancel the wizard (and are refused while a finish is running);\n * finishing or cancelling closes the window.\n * @param {object} [opts] ManagedWindow options: id, title, icon, defaultWidth,\n * defaultHeight, minWidth, minHeight, container, modal (default true).\n * @returns {ManagedWindow}\n */\n openInWindow({ id = 'twm-wizard', title = 'Wizard', icon, defaultWidth = 720,\n defaultHeight = 520, minWidth = 420, minHeight = 320,\n container, modal = true } = {}) {\n if (this._mounted) throw new Error('Wizard is already mounted');\n this.#build();\n this._mounted = true;\n this.#window = new ManagedWindow({\n id, title, icon, defaultWidth, defaultHeight, minWidth, minHeight,\n container, modal,\n content: this.#root,\n canMinimize: false,\n beforeClose: () => {\n if (isFinal(this.state)) return true;\n void this.cancel();\n return false;\n },\n });\n // Rendered and painted BEFORE show, so the window's focus-on-open\n // (BUG-0053) lands on the step's first field \u2014 the stepper's buttons\n // are disabled by then \u2014 and not on the first step button.\n this.#renderBody();\n this.#paint();\n this.#window.show();\n return this.#window;\n }\n\n /** Tear down (and close the window, if any) without calling any callback.\n * Every later move, finish or cancel is refused. */\n dispose() {\n if (this.#disposed) return;\n this.#disposed = true;\n const win = this.#window;\n this.#teardown();\n win?.close({ force: true });\n super.dispose();\n }\n\n // \u2500\u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** The wizard's root element (null before mount). */\n get element() { return this.#root; }\n\n /** The body slot the current step renders into. */\n get bodyElement() { return this.#body; }\n\n /** The ManagedWindow, when opened with `openInWindow`. */\n get window() { return this.#window; }\n\n /** The object every hook receives: `{data, step, index, revalidate, next, back, goTo, setStepState}`. */\n get context() { return this.#ctx; }\n\n /** The current step's id. */\n get currentStep() { return this.#steps[this.#index].id; }\n\n /** The current step's index. */\n get currentIndex() { return this.#index; }\n\n /** 'step' | 'finishing' | 'finished' | 'cancelled' (null for a moment after construction). */\n get state() { return this.#machine.getState(); }\n\n /** True while an async finish is running. */\n get busy() { return this.state === FINISHING; }\n\n /**\n * Ask the current step's `canAdvance` again and redraw the indicator and\n * the footer. The body is NOT re-rendered.\n */\n revalidate() {\n this.#paint();\n }\n\n /** Forward one step, if the current step's gate allows it. Resolves true when it moved. */\n next() {\n return this.#move(() => this.#index + 1);\n }\n\n /** Back one step. Resolves true when it moved. */\n back() {\n return this.#move(() => this.#index - 1);\n }\n\n /**\n * Move to a step by id or index: any step before the current one, or the\n * next one through the gate. Resolves true when it moved.\n * @param {string|number} target\n */\n goTo(target) {\n return this.#move(() => this.#resolveIndex(target));\n }\n\n /**\n * Mark a step as errored (`'error'`, with a message shown while it is the\n * current step), or clear the mark (`null`).\n * @param {string} id\n * @param {'error'|null} state\n * @param {string} [message]\n */\n setStepState(id, state, message = '') {\n const i = this.#resolveIndex(id);\n if (i < 0 || i >= this.#steps.length) throw new Error(`Wizard: no step \"${id}\"`);\n const key = this.#steps[i].id;\n if (state == null) this.#overrides.delete(key);\n else if (STEP_STATES.includes(state)) this.#overrides.set(key, { state, message: String(message ?? '') });\n else throw new Error(`Wizard: unknown step state \"${state}\" (expected 'error' or null)`);\n this.#paint();\n }\n\n /**\n * Run `onFinish` from the last step, if its gate allows. The buttons are\n * disabled until it settles; resolved, the wizard closes; rejected, the\n * step is marked as error with the message. Resolves true when it finished.\n */\n finish() {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const { transitioned } = await this.#machine.transition('finish');\n if (!transitioned) return false;\n this.#paint();\n try {\n await this.#onFinish?.(this.#ctx);\n } catch (error) {\n await this.#machine.transition('reject', { error });\n this.#paint();\n return false;\n }\n await this.#machine.transition('resolve');\n return true;\n });\n }\n\n /**\n * Close the wizard and call `onCancel` \u2014 once. Refused while a finish is\n * running. Resolves true when it cancelled.\n */\n cancel() {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const { transitioned } = await this.#machine.transition('cancel');\n return transitioned;\n });\n }\n\n // \u2500\u2500\u2500 Moves \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 /** Moves run one at a time, so a double click cannot start a transition\n * inside another. The target is computed when the move runs, not when it\n * was asked for. A request made while a finish is running (or after the\n * wizard closed) is refused there and then \u2014 it is not queued behind the\n * finish to run once it settles. */\n #enqueue(fn) {\n if (this.#disposed || this.busy || isFinal(this.state)) return Promise.resolve(false);\n const run = this.#queue.then(() => (this.#disposed ? false : fn()));\n this.#queue = run.catch(() => {});\n return run;\n }\n\n #move(targetOf) {\n return this.#enqueue(async () => {\n if (this.state !== OPEN) return false;\n const to = targetOf();\n if (!this.#canMoveTo(to)) return false;\n const { transitioned } = await this.#machine.transition('move', { to });\n this.#paint();\n return transitioned;\n });\n }\n\n #canMoveTo(to) {\n if (!Number.isInteger(to) || to < 0 || to >= this.#steps.length) return false;\n if (to < this.#index) return true;\n return to === this.#index + 1 && this.#gate().ok;\n }\n\n #enterStep(to) {\n this.#index = to;\n this.#renderBody();\n }\n\n #resolveIndex(target) {\n if (typeof target === 'number') return Number.isInteger(target) ? target : -1;\n return this.#steps.findIndex((s) => s.id === target);\n }\n\n #isLast() {\n return this.#index === this.#steps.length - 1;\n }\n\n /** The current step's gate, normalised to `{ok, hint}`. */\n #gate() {\n const step = this.#steps[this.#index];\n if (typeof step.canAdvance !== 'function') return { ok: true, hint: '' };\n const r = step.canAdvance(this.#ctx) ?? {};\n return { ok: r.ok === true, hint: typeof r.hint === 'string' ? r.hint : '' };\n }\n\n // \u2500\u2500\u2500 DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 #build() {\n const root = document.createElement('div');\n root.className = 'twm-wizard';\n\n const steps = document.createElement('ol');\n steps.className = 'twm-wizard__steps';\n this.#steps.forEach((step, i) => {\n if (i > 0) {\n const connector = document.createElement('li');\n connector.className = 'twm-wizard__connector';\n connector.setAttribute('role', 'presentation');\n connector.setAttribute('aria-hidden', 'true');\n steps.appendChild(connector);\n this.#connectors.push(connector);\n }\n const item = document.createElement('li');\n item.className = 'twm-wizard__step';\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'twm-wizard__step-btn';\n const marker = document.createElement('span');\n marker.className = 'twm-wizard__step-marker';\n const label = document.createElement('span');\n label.className = 'twm-wizard__step-label';\n label.textContent = step.label ?? step.id;\n btn.append(marker, label);\n btn.addEventListener('click', () => this.#onStepClick(i));\n item.appendChild(btn);\n steps.appendChild(item);\n this.#stepItems.push(item);\n this.#stepButtons.push(btn);\n });\n\n this.#body = document.createElement('div');\n this.#body.className = 'twm-wizard__body';\n\n const footer = document.createElement('div');\n footer.className = 'twm-wizard__footer';\n this.#message = document.createElement('div');\n this.#message.className = 'twm-wizard__message';\n this.#message.setAttribute('aria-live', 'polite');\n\n const actions = document.createElement('div');\n actions.className = 'twm-wizard__actions';\n this.#cancelBtn = this.#button('twm-wizard__cancel', this.#labels.cancel, () => { void this.cancel(); });\n this.#backBtn = this.#button('twm-wizard__back', this.#labels.back, () => { void this.back(); });\n this.#nextBtn = this.#button('twm-wizard__next twm-btn--primary', this.#labels.next, () => {\n void (this.#isLast() ? this.finish() : this.next());\n });\n actions.append(this.#cancelBtn, this.#backBtn, this.#nextBtn);\n footer.append(this.#message, actions);\n\n root.append(steps, this.#body, footer);\n this.#root = root;\n }\n\n #button(cls, text, onClick) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `twm-btn ${cls}`;\n btn.textContent = text;\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n #onStepClick(i) {\n if (i < this.#index) void this.goTo(i);\n }\n\n #renderBody() {\n runCleanup(this.#cleanup);\n this.#cleanup = null;\n this.#body.replaceChildren();\n const step = this.#steps[this.#index];\n this.#cleanup = step.render(this.#body, this.#ctx) ?? null;\n }\n\n /** The visual state of step `i`: an override, else its position. */\n #stepState(i) {\n const override = this.#overrides.get(this.#steps[i].id);\n if (override) return override.state;\n if (i < this.#index) return 'done';\n return i === this.#index ? 'current' : 'upcoming';\n }\n\n #paint() {\n if (!this.#root) return;\n const busy = this.busy;\n this.#root.classList.toggle('twm-wizard--busy', busy);\n this.#root.setAttribute('aria-busy', busy ? 'true' : 'false');\n\n this.#steps.forEach((step, i) => {\n const state = this.#stepState(i);\n const item = this.#stepItems[i];\n for (const s of ['done', 'current', 'upcoming', 'error']) {\n item.classList.toggle(`twm-wizard__step--${s}`, s === state);\n }\n item.classList.toggle('twm-wizard__step--active', i === this.#index);\n const btn = this.#stepButtons[i];\n btn.disabled = busy || i >= this.#index;\n if (i === this.#index) btn.setAttribute('aria-current', 'step');\n else btn.removeAttribute('aria-current');\n const override = this.#overrides.get(step.id);\n btn.title = override?.message || step.label || step.id;\n\n const marker = btn.firstChild;\n const glyph = state === 'done' ? 'check' : state === 'error' ? 'error' : (step.icon || '');\n marker.classList.toggle('material-symbols-outlined', Boolean(glyph));\n marker.textContent = glyph || String(i + 1);\n if (i > 0) {\n this.#connectors[i - 1].classList.toggle('twm-wizard__connector--done', i <= this.#index);\n }\n });\n\n const gate = this.#gate();\n const last = this.#isLast();\n this.#nextBtn.textContent = last ? this.#labels.finish : this.#labels.next;\n this.#nextBtn.disabled = busy || !gate.ok;\n this.#nextBtn.title = gate.ok ? '' : gate.hint;\n this.#backBtn.disabled = busy || this.#index === 0;\n this.#cancelBtn.disabled = busy;\n\n const error = this.#overrides.get(this.currentStep);\n const text = error ? error.message : (gate.ok ? '' : gate.hint);\n this.#message.textContent = text;\n this.#message.classList.toggle('twm-wizard__message--error', Boolean(error));\n this.#message.classList.toggle('twm-wizard__message--hint', !error && Boolean(text));\n if (error) this.#message.setAttribute('role', 'alert');\n else this.#message.removeAttribute('role');\n }\n\n #close() {\n const win = this.#window;\n this.#teardown();\n this._mounted = false;\n win?.close({ force: true });\n }\n\n #teardown() {\n runCleanup(this.#cleanup);\n this.#cleanup = null;\n this.#root?.remove();\n this.#root = null;\n this.#body = null;\n this.#message = null;\n this.#stepItems = [];\n this.#stepButtons = [];\n this.#connectors = [];\n this.#cancelBtn = this.#backBtn = this.#nextBtn = null;\n }\n}\n", "/**\n * workspace_picker.js \u2014 the field in a top bar that names what the window is\n * working in, and the switcher that changes it.\n *\n * field switcher, opened in the field's place\n * +-----------------------+ +------------------------------------+\n * | (i) North Ctrl+P | | (o) nor| |\n * +-----------------------+ | heading 2 of 9|\n * | North (check)(x)|\n * | Northwest |\n * | Load 20 more \u00B7 2 of 9 shown |\n * | + New \"nor\"\u2026 |\n * | card: the current one's links |\n * | status footer verbs |\n * +------------------------------------+\n *\n * Three exports, each usable alone:\n *\n * mountPickerField the field: a name, an icon, a key hint; centred in\n * its host at the width the host can spare, or inline\n * createPickerSwitcher the switcher, on any anchor or on none\n * createWorkspacePicker both, wired together, with an optional chord\n *\n * It knows nothing of what is being picked. Items are the caller's, `describe`\n * turns one into what a row draws, and every string is the caller's or a\n * neutral default the caller can replace through `labels`.\n *\n * \u2550\u2550 ITEMS ARE ASKED FOR ON EVERY OPEN \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * `load({ query, offset, limit, signal })` answers an array, or\n * `{ items, total?, status? }`, now or in a promise. With `search: 'local'` it\n * is asked once per open and typing filters what it answered, names ahead of\n * other matches. With `search: 'remote'` typing is debounced and asked again,\n * and a `total` above what is drawn offers Load more. Either way only the\n * newest question's answer paints: every read carries a sequence number and an\n * AbortSignal, and an answer to an older question is dropped however it\n * arrives. The last unsearched answer, per `cacheKey()`, is drawn at once on\n * the next open while it is asked for again.\n *\n * \u2550\u2550 THE KEYBOARD \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * Focus is real: what the keyboard is on is `document.activeElement`, so a screen\n * reader says each stop, a button in the card or the footer included, and Tab and\n * the arrows agree about where the reader is.\n *\n * Opening puts the caret in the input. The arrows walk focus over every stop,\n * wrapping: the input, the rows a person can choose (a disabled one is stepped\n * over), Load more, the action rows, the card's buttons, the footer's; after\n * `open({ select })` they start from the row it chose. Tab is shorter: the rows are\n * ONE tab stop (the row last focused, else the current one, else the first), and so\n * are the action rows. An answer or a redraw leaves focus where it is, on a row that\n * moved too; Load more stays focusable while it loads.\n *\n * Typing always types: a character pressed anywhere in the panel goes to the input.\n * In the input, the first row or action row of what is shown wears the highlight,\n * and Enter takes it, or, while the answer to what was typed is on its way, takes\n * the first one when it lands. Enter or Space on a row takes that row. Shift+Delete\n * removes the highlighted row, and focus goes on to the next. Backspace away from\n * the input stops at the panel. Esc closes and gives focus back to where it was, as\n * does a pick or a verb, before it runs, so a dialog it opens opens over nothing. A\n * press outside closes and leaves focus where it was pressed. Tab out of the panel\n * closes it.\n *\n * \u2550\u2550 NOTHING IS REBUILT UNDER A POINTER \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * A click fires only when the press and the release land on one node. So every\n * part is reconciled by key: an answer, a card or a `setCurrent` updates nodes\n * in place, and a node is created or removed only for a key that came or went.\n * Which node holds what lives in maps here, never in DOM attributes.\n *\n * Nor is a list moved under one. The list scrolls to the highlight only when the\n * keyboard moved it, `open({ select })` asked for a row, or the row the arrows chose\n * went away (focus then goes to the input); typing and a new query's answer go back\n * to the top.\n * A redraw, Load more by the mouse and a removal leave the scroll where it is.\n *\n * \u2550\u2550 AN ASYNC REMOVE MAY ASK \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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 * While the promise `onRemove` returned is unsettled the panel and its backdrop\n * step below managed windows and do not close on a press outside, so a\n * confirmation dialog can be answered and the switcher is still there afterwards.\n */\n\nimport { ActionDropdown } from './action_dropdown.js';\nimport { createRafResizeObserver } from '../utils/raf_resize_observer.js';\n\nconst DEFAULT_LABELS = Object.freeze({\n loading: 'Loading\u2026',\n empty: () => 'Nothing to show.',\n noMatch: (query) => `Nothing matches \u201C${query}\u201D.`,\n failed: (err) => `The list could not be read. ${err?.message || ''}`.trim(),\n failedMore: (err) => `The next page could not be read. ${err?.message || ''}`.trim(),\n failedRemove: (err) => `Could not remove it. ${err?.message || ''}`.trim(),\n loadMore: ({ next, shown, total }) => `Load ${next} more \u00B7 ${shown} of ${total} shown`,\n remove: (name) => `Remove ${name}`,\n});\n\nconst PANEL_EDGE = 8;\n/** How far the panel's input row stands above the field it covers. */\nconst OVER_LIFT = 3;\n\nlet nextUid = 0;\n\nfunction part(tag, className, text = null) {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text != null) node.textContent = text;\n return node;\n}\n\nfunction glyph(name, className = '') {\n const node = part('span', `material-symbols-outlined ${className}`.trim(), name);\n node.setAttribute('aria-hidden', 'true');\n return node;\n}\n\n/** Write text only when it changed: a write that changes nothing is still a\n * mutation, and a screen reader hears it. */\nfunction setText(node, text) {\n const value = String(text ?? '');\n if (node.textContent !== value) node.textContent = value;\n}\n\nfunction show(node, shown) {\n node.hidden = !shown;\n}\n\nfunction button(className) {\n const node = part('button', className);\n node.type = 'button';\n return node;\n}\n\n/**\n * Keep `container`'s children one per key: `build()` makes `{ node, ... }` for\n * a new key, `update(entry, item)` brings any entry up to date, a key that went\n * loses its node, and a node already in its place is not moved (moving one\n * under a pressed pointer is half of rebuilding it). The node holding focus is\n * never moved, wherever it belongs now: the others go round it, because moving it\n * would drop the keyboard on the body.\n * @returns {(items: object[], keyOf: (item: object) => unknown) => Map<string, object>}\n */\nfunction keyedChildren(container, build, update) {\n let drawn = new Map();\n return (items, keyOf) => {\n const next = new Map();\n const nodes = items.map((item) => {\n const key = String(keyOf(item));\n const entry = drawn.get(key) ?? build();\n update(entry, item);\n next.set(key, entry);\n return entry.node;\n });\n for (const [key, entry] of drawn) {\n if (!next.has(key)) entry.node.remove();\n }\n drawn = next;\n const focused = document.activeElement;\n nodes.forEach((node, index) => {\n if (node.contains(focused)) {\n while (container.children[index] !== node) container.append(container.children[index]);\n } else if (container.children[index] !== node) {\n container.insertBefore(node, container.children[index] || null);\n }\n });\n return drawn;\n };\n}\n\nfunction parseChord(chord) {\n const parts = String(chord).split('+').map((p) => p.trim().toLowerCase());\n const key = parts.pop();\n const known = new Set(['ctrl', 'cmd', 'meta', 'shift', 'alt']);\n if (!key || parts.some((p) => !known.has(p))) {\n throw new TypeError(`createWorkspacePicker: cannot read the chord \"${chord}\"`);\n }\n return {\n key,\n ctrl: parts.includes('ctrl') || parts.includes('cmd') || parts.includes('meta'),\n shift: parts.includes('shift'),\n alt: parts.includes('alt'),\n };\n}\n\nfunction chordMatches(parsed, event) {\n return (event.ctrlKey || event.metaKey) === parsed.ctrl\n && event.shiftKey === parsed.shift\n && event.altKey === parsed.alt\n && String(event.key).toLowerCase() === parsed.key;\n}\n\n/**\n * Mount the field into `hostEl`.\n *\n * `layout: 'centered'` places it in the middle of `hostEl` (which must be\n * positioned) at the width the host can spare between the elements `avoid`\n * selects: at most `maxWidth`, without the key hint below `tightWidth`, and\n * hidden below `minWidth`. `layout: 'inline'` leaves its width to the host and\n * only drops the key hint.\n *\n * @param {HTMLElement} hostEl\n * @param {object} [options]\n * @param {string} [options.name] - The name it shows\n * @param {string} [options.icon] - A Material Symbols name\n * @param {string} [options.keyHint] - Drawn as a key; none by default\n * @param {boolean} [options.muted] - Draw the name as naming nothing\n * @param {boolean} [options.caret] - A trailing caret, for an inline field\n * @param {string} [options.tooltip]\n * @param {string} [options.ariaLabel]\n * @param {string} [options.className] - Extra classes\n * @param {'centered'|'inline'} [options.layout]\n * @param {string} [options.avoid] - Selector, within `hostEl`, of what it must not cover\n * @param {number} [options.maxWidth]\n * @param {number} [options.minWidth]\n * @param {number} [options.tightWidth]\n * @param {number} [options.gap] - Room kept free in all, shared between the two sides\n * @param {() => void} [options.onActivate] - A click\n * @returns {{ el: HTMLButtonElement, update: (patch: object) => void, setOpen: (open: boolean) => void, fit: () => void, destroy: () => void }}\n */\nexport function mountPickerField(hostEl, {\n name = '',\n icon = '',\n keyHint = '',\n muted = false,\n caret = false,\n tooltip = '',\n ariaLabel = '',\n className = '',\n layout = 'inline',\n avoid = '',\n maxWidth = 440,\n minWidth = 120,\n tightWidth = 230,\n gap = 24,\n onActivate = null,\n} = {}) {\n const centered = layout === 'centered';\n const el = button(['twm-wspicker-field', centered ? 'twm-wspicker-field--centered' : '', className]\n .filter(Boolean).join(' '));\n el.setAttribute('aria-haspopup', 'dialog');\n el.setAttribute('aria-expanded', 'false');\n const iconEl = glyph('', 'twm-wspicker-field__icon');\n const nameEl = part('span', 'twm-wspicker-field__name');\n const keyEl = part('kbd', 'twm-wspicker-field__key');\n el.append(iconEl, nameEl, keyEl);\n if (caret) el.append(glyph('expand_more', 'twm-wspicker-field__caret'));\n\n const update = (patch) => {\n if ('name' in patch) setText(nameEl, patch.name);\n if ('icon' in patch) {\n setText(iconEl, patch.icon);\n show(iconEl, !!patch.icon);\n }\n if ('keyHint' in patch) {\n setText(keyEl, patch.keyHint);\n show(keyEl, !!patch.keyHint);\n }\n if ('muted' in patch) el.classList.toggle('twm-wspicker-field--muted', !!patch.muted);\n if ('tooltip' in patch) {\n el.classList.toggle('twm-has-tooltip', !!patch.tooltip);\n if (patch.tooltip) {\n el.setAttribute('data-tooltip', patch.tooltip);\n el.setAttribute('data-tooltip-placement', 'bottom');\n } else {\n el.removeAttribute('data-tooltip');\n el.removeAttribute('data-tooltip-placement');\n }\n }\n if ('ariaLabel' in patch) {\n if (patch.ariaLabel) el.setAttribute('aria-label', patch.ariaLabel);\n else el.removeAttribute('aria-label');\n }\n };\n update({ name, icon, keyHint, muted, tooltip, ariaLabel });\n\n const fit = () => {\n if (!centered) {\n el.classList.toggle('twm-wspicker-field--tight', el.getBoundingClientRect().width < tightWidth);\n return;\n }\n const box = hostEl.getBoundingClientRect();\n const middle = box.left + box.width / 2;\n let leftEdge = box.left;\n let rightEdge = box.right;\n for (const other of avoid ? hostEl.querySelectorAll(avoid) : []) {\n if (el.contains(other)) continue;\n const r = other.getBoundingClientRect();\n if (r.width <= 0) continue;\n if (r.left + r.width / 2 < middle) leftEdge = Math.max(leftEdge, r.right);\n else rightEdge = Math.min(rightEdge, r.left);\n }\n const width = Math.min(maxWidth, 2 * Math.min(middle - leftEdge, rightEdge - middle) - gap);\n el.classList.toggle('twm-wspicker-field--hidden', width < minWidth);\n el.classList.toggle('twm-wspicker-field--tight', width < tightWidth);\n el.style.width = `${Math.max(minWidth, width)}px`;\n };\n\n let destroyed = false;\n const onClick = () => onActivate?.();\n el.addEventListener('click', onClick);\n hostEl.appendChild(el);\n const observer = createRafResizeObserver(() => {\n if (!destroyed) fit();\n });\n observer.observe(centered ? hostEl : el);\n fit();\n document.fonts?.ready?.then(() => {\n if (!destroyed) fit();\n });\n\n return {\n el,\n update,\n fit,\n setOpen(open) {\n el.classList.toggle('twm-wspicker-field--open', open);\n el.setAttribute('aria-expanded', String(open));\n },\n destroy() {\n destroyed = true;\n observer.disconnect();\n el.removeEventListener('click', onClick);\n el.remove();\n },\n };\n}\n\n/**\n * The switcher. See the file's header for how it asks and how it behaves.\n *\n * @param {object} options\n * @param {HTMLElement} [options.anchor] - What it opens from. With none, or one\n * that takes no room, it opens centred over a dimmed page.\n * @param {'over'|'below'} [options.placement] - `over` lays the input over the\n * anchor; `below` hangs from it, flipped above when there is no room.\n * @param {number} [options.minWidth] - The anchored panel's least width\n * @param {number} [options.visibleRows] - Scroll past this many two-line rows\n * @param {string} [options.className] - Extra classes on the panel\n * @param {string} [options.label] - The panel's accessible name\n * @param {string} [options.listLabel] - The list's accessible name\n * @param {string} [options.placeholder] - The input's placeholder\n * @param {string} [options.glyph] - The icon before the input\n * @param {(request: {query: string, offset: number, limit: number, signal: AbortSignal}) => (object[]|{items: object[], total?: number, status?: string|{text: string, error?: boolean}}|Promise)} options.load\n * @param {'local'|'remote'} [options.search]\n * @param {number} [options.pageSize] - `limit`, in remote search\n * @param {number} [options.debounceMs] - How long typing waits, in remote search\n * @param {() => string} [options.cacheKey] - Whose list the kept answer is\n * @param {(item: object, ctx: {current: boolean}) => {id: string|number, name: string, detail?: string, icon?: string, badge?: string, title?: string, keywords?: string|string[], disabled?: boolean, removable?: boolean}} options.describe\n * @param {(item: object) => void} [options.onPick] - A row other than the current one chosen\n * @param {(item: object) => (boolean|void|Promise<boolean|void>)} [options.onRemove] -\n * Offers a bin on each row whose `removable` is not false. Answering `false`\n * keeps the row; rejecting keeps it and shows the error.\n * @param {(ctx: {query: string}) => Array<{id: string, label: string, detail?: string, icon?: string, always?: boolean, run: (ctx: {query: string}) => void}>} [options.actions] -\n * Rows after the items, narrowed by typing unless `always`.\n * @param {(ctx: {query: string, shown: number, total: number|null}) => ({title?: string, count?: string}|null)} [options.heading]\n * @param {(ctx: {current: object|null, row: object|null}) => ({heading?: string, icon?: string, name: string, detail?: string, open?: {label: string, icon?: string, run: Function}, columns?: number, tiles?: Array<{id: string, label: string, icon?: string, run: Function}>}|null)} [options.card]\n * @param {() => ({start?: object[], end?: object[], keys?: Array<{keys: string[], label: string}>}|null)} [options.footer] -\n * Buttons are `{ id, label, icon?, trailing?, primary?, run }`. `keys` are drawn\n * only when the panel is centred.\n * @param {object} [options.labels] - Replaces any of the default strings\n * @param {(open: boolean) => void} [options.onOpenChange]\n */\nexport function createPickerSwitcher({\n anchor = null,\n placement = 'over',\n minWidth = 520,\n visibleRows = 0,\n className = '',\n label = '',\n listLabel = '',\n placeholder = '',\n glyph: inputGlyph = 'search',\n load,\n search = 'local',\n pageSize = 20,\n debounceMs = 200,\n cacheKey = () => '',\n describe,\n onPick = null,\n onRemove = null,\n actions = null,\n heading = null,\n card = null,\n footer = null,\n labels: labelOverrides = {},\n onOpenChange = null,\n}) {\n const labels = { ...DEFAULT_LABELS, ...labelOverrides };\n const remote = search === 'remote';\n const uid = `twm-wspicker-${++nextUid}`;\n\n let isOpen = false;\n let destroyed = false;\n let current = null;\n /** What the last answer held, in its order. */\n let items = [];\n let total = null;\n let status = null;\n /** The query the drawn items answer, and the newest one asked. */\n let answered = '';\n let asked = '';\n let seq = 0;\n let abort = null;\n let loading = false;\n let loadingMore = false;\n let failure = null;\n let timer = null;\n /** Enter came before the answer to what was typed. */\n let pickFirst = false;\n /** Which row to highlight when the next answer lands. */\n let selectId = null;\n /** An `onRemove` promise is unsettled. */\n let busy = false;\n /** Where focus was when it opened. */\n let opener = null;\n /** Every place the arrows stop, in order. */\n let stops = [];\n let activeKey = null;\n let activeNode = null;\n /** The arrows chose the highlight; an answer does not move it. */\n let moved = false;\n /** The row last focused, per list of rows. */\n const rovingKeys = {};\n let nextEntryId = 0;\n const kept = new Map();\n\n const idOf = (item) => String(describe(item, { current: false }).id);\n const isCurrent = (item) => current != null && idOf(item) === idOf(current);\n const modelOf = (item) => describe(item, { current: isCurrent(item) });\n const typed = () => input.value.trim();\n\n // \u2500\u2500 the panel, built once \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const backdrop = part('div', 'twm-wspicker-backdrop');\n const panel = part('div', `twm-wspicker ${className}`.trim());\n panel.setAttribute('role', 'dialog');\n if (label) panel.setAttribute('aria-label', label);\n\n const searchRow = part('div', 'twm-wspicker__search');\n const input = part('input', 'twm-wspicker__input');\n input.type = 'text';\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.placeholder = placeholder;\n if (placeholder) input.setAttribute('aria-label', placeholder);\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `${uid}-list`);\n searchRow.append(glyph(inputGlyph, 'twm-wspicker__glyph'), input);\n\n const head = part('div', 'twm-wspicker__head');\n const headTitle = part('span', 'twm-wspicker__title');\n const headCount = part('span', 'twm-wspicker__count');\n head.append(headTitle, headCount);\n\n const scroller = part('div', 'twm-wspicker__scroll');\n if (visibleRows > 0) {\n scroller.classList.add('twm-wspicker__scroll--capped');\n scroller.style.setProperty('--twm-wspicker-rows', String(visibleRows));\n }\n const list = part('div', 'twm-wspicker__list');\n list.id = `${uid}-list`;\n list.setAttribute('role', 'listbox');\n if (listLabel) list.setAttribute('aria-label', listLabel);\n const note = part('p', 'twm-wspicker__note');\n note.setAttribute('role', 'status');\n const more = button('twm-btn twm-wspicker__more');\n const moreLabel = part('span', 'twm-wspicker__more-label');\n more.append(glyph('expand_more'), moreLabel);\n const actionList = part('div', 'twm-wspicker__actions');\n actionList.setAttribute('role', 'listbox');\n scroller.append(list, note, more, actionList);\n\n const cardEl = part('section', 'twm-wspicker__card');\n const cardHeading = part('h3', 'twm-wspicker__card-heading');\n const cardHead = part('div', 'twm-wspicker__card-head');\n const cardIcon = glyph('', 'twm-wspicker__card-icon');\n const cardText = part('span', 'twm-wspicker__card-text');\n const cardName = part('span', 'twm-wspicker__card-name');\n const cardDetail = part('span', 'twm-wspicker__card-detail');\n cardText.append(cardName, cardDetail);\n const cardOpen = button('twm-btn twm-wspicker__card-open');\n const cardOpenIcon = glyph('');\n const cardOpenLabel = part('span', '');\n cardOpen.append(cardOpenIcon, cardOpenLabel);\n cardHead.append(cardIcon, cardText, cardOpen);\n const tiles = part('div', 'twm-wspicker__tiles');\n cardEl.append(cardHeading, cardHead, tiles);\n\n const foot = part('div', 'twm-wspicker__foot');\n const footStatus = part('span', 'twm-wspicker__status');\n const footStart = part('div', 'twm-wspicker__foot-group');\n const footEnd = part('div', 'twm-wspicker__foot-group');\n const footKeys = part('span', 'twm-wspicker__keys');\n foot.append(footStart, footStatus, footEnd, footKeys);\n\n panel.append(searchRow, head, scroller, cardEl, foot);\n\n // \u2500\u2500 rows, the items' and the action rows' \u2500\u2500\u2500\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 function buildRow() {\n const node = part('div', 'twm-wspicker__row');\n node.id = `${uid}-row-${++nextEntryId}`;\n node.setAttribute('role', 'option');\n node.tabIndex = -1;\n const icon = glyph('', 'twm-wspicker__row-icon');\n const text = part('span', 'twm-wspicker__row-text');\n const name = part('span', 'twm-wspicker__row-name');\n const detail = part('span', 'twm-wspicker__row-detail');\n text.append(name, detail);\n const badge = part('span', 'twm-wspicker__row-badge');\n const check = glyph('check', 'twm-wspicker__row-check');\n const bin = button('twm-wspicker__row-remove');\n bin.tabIndex = -1;\n bin.append(glyph('delete'));\n node.append(icon, text, badge, check, bin);\n const entry = { node, icon, name, detail, badge, check, bin, run: null, remove: null };\n node.addEventListener('click', () => entry.run?.());\n bin.addEventListener('click', (event) => {\n event.stopPropagation();\n entry.remove?.();\n });\n return entry;\n }\n\n function paintRow(entry, { name, detail, icon, badge, title, disabled = false, isCurrentRow = false }) {\n setText(entry.icon, icon);\n setText(entry.name, name);\n setText(entry.detail, detail);\n show(entry.detail, !!detail);\n setText(entry.badge, badge);\n show(entry.badge, !!badge);\n show(entry.check, isCurrentRow);\n entry.node.classList.toggle('twm-wspicker__row--current', isCurrentRow);\n entry.node.classList.toggle('twm-wspicker__row--disabled', disabled);\n entry.node.setAttribute('aria-selected', String(isCurrentRow));\n if (disabled) entry.node.setAttribute('aria-disabled', 'true');\n else entry.node.removeAttribute('aria-disabled');\n entry.node.title = title ?? (detail ? `${name} \u2014 ${detail}` : name);\n }\n\n const syncRows = keyedChildren(list, buildRow, (entry, item) => {\n const model = modelOf(item);\n const disabled = !!model.disabled;\n paintRow(entry, { ...model, disabled, isCurrentRow: isCurrent(item) });\n entry.run = disabled ? null : () => pick(item);\n if (disabled) entry.node.tabIndex = -1;\n const removable = !!onRemove && model.removable !== false;\n entry.remove = removable ? () => removeItem(item) : null;\n show(entry.bin, removable);\n if (removable) {\n const words = labels.remove(model.name);\n entry.bin.setAttribute('aria-label', words);\n entry.bin.title = words;\n }\n });\n\n const syncActions = keyedChildren(actionList, buildRow, (entry, action) => {\n paintRow(entry, { name: action.label, detail: action.detail, icon: action.icon, title: action.title });\n entry.run = () => runVerb(action.run);\n show(entry.bin, false);\n });\n\n /** What typing leaves of the answer: names ahead of other matches. */\n function shownItems() {\n const query = typed().toLowerCase();\n if (remote || !query) return items;\n const names = [];\n const others = [];\n for (const item of items) {\n const { name, detail, keywords } = modelOf(item);\n if (String(name).toLowerCase().includes(query)) names.push(item);\n else if ([detail, keywords].flat().some((text) => String(text ?? '').toLowerCase().includes(query))) others.push(item);\n }\n return [...names, ...others];\n }\n\n function shownActions() {\n if (!actions) return [];\n const query = typed();\n const lower = query.toLowerCase();\n return actions({ query }).filter((action) => action.always || !lower\n || String(action.label).toLowerCase().includes(lower));\n }\n\n // \u2500\u2500 the card and the footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function buildVerb(hook) {\n return () => {\n const node = button(`twm-btn ${hook}`);\n const icon = glyph('');\n const text = part('span', '');\n const trailing = glyph('');\n node.append(icon, text, trailing);\n const entry = { node, icon, text, trailing, run: null };\n node.addEventListener('click', () => entry.run?.());\n return entry;\n };\n }\n\n function paintVerb(entry, verb) {\n setText(entry.icon, verb.icon);\n setText(entry.text, verb.label);\n setText(entry.trailing, verb.trailing);\n entry.node.classList.toggle('twm-btn--primary', !!verb.primary);\n entry.node.title = verb.label;\n entry.run = () => runVerb(verb.run);\n }\n\n const syncTiles = keyedChildren(tiles, buildVerb('twm-wspicker__tile'), paintVerb);\n const syncFootStart = keyedChildren(footStart, buildVerb('twm-wspicker__foot-btn'), paintVerb);\n const syncFootEnd = keyedChildren(footEnd, buildVerb('twm-wspicker__foot-btn'), paintVerb);\n let drawnTiles = new Map();\n let drawnFoot = new Map();\n let cardOpenRun = null;\n\n cardOpen.addEventListener('click', () => cardOpenRun?.());\n\n function renderCard() {\n const row = current == null ? null : items.find((item) => isCurrent(item)) ?? null;\n const model = card ? card({ current, row }) : null;\n show(cardEl, !!model);\n drawnTiles = syncTiles(model?.tiles || [], (tile) => tile.id);\n cardOpenRun = model?.open ? () => runVerb(model.open.run) : null;\n show(cardOpen, !!model?.open);\n if (!model) return;\n setText(cardHeading, model.heading);\n show(cardHeading, !!model.heading);\n setText(cardIcon, model.icon);\n setText(cardName, model.name);\n setText(cardDetail, model.detail);\n cardName.title = model.name;\n setText(cardOpenIcon, model.open?.icon);\n setText(cardOpenLabel, model.open?.label);\n tiles.style.setProperty('--twm-wspicker-columns', String(model.columns || 2));\n }\n\n function renderFooter() {\n const model = footer ? footer() : null;\n const start = syncFootStart(model?.start || [], (verb) => verb.id);\n const end = syncFootEnd(model?.end || [], (verb) => verb.id);\n drawnFoot = new Map([...[...start].map(([key, entry]) => [`start:${key}`, entry]),\n ...[...end].map(([key, entry]) => [`end:${key}`, entry])]);\n footKeys.replaceChildren(...(model?.keys || []).map(({ keys, label: words }) => {\n const hint = part('span', 'twm-wspicker__key-hint');\n hint.append(...keys.map((key) => part('kbd', '', key)), ` ${words}`);\n return hint;\n }));\n const { text = '', error = false } = typeof status === 'string' ? { text: status } : status ?? {};\n setText(footStatus, text);\n show(footStatus, !!text);\n footStatus.classList.toggle('twm-wspicker__status--error', !!error);\n const keysShown = footKeys.childElementCount > 0 && panel.classList.contains('twm-wspicker--centered');\n show(foot, !!text || keysShown || drawnFoot.size > 0);\n }\n\n // \u2500\u2500 the highlight \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function collectStops(rowEntries, actionEntries, shown) {\n const next = [];\n for (const item of shown) {\n const entry = rowEntries.get(idOf(item));\n if (entry?.run) next.push({ key: `row:${idOf(item)}`, node: entry.node, run: entry.run, remove: entry.remove, primary: true });\n }\n if (!more.hidden) next.push({ key: 'more', node: more, run: () => loadMore({ byKey: true }) });\n for (const [key, entry] of actionEntries) next.push({ key: `action:${key}`, node: entry.node, run: entry.run, primary: true });\n if (!cardEl.hidden) {\n if (!cardOpen.hidden) next.push({ key: 'card-open', node: cardOpen, run: () => cardOpenRun?.() });\n for (const [key, entry] of drawnTiles) next.push({ key: `tile:${key}`, node: entry.node, run: entry.run });\n }\n for (const [key, entry] of drawnFoot) next.push({ key: `foot:${key}`, node: entry.node, run: entry.run });\n stops = next;\n syncTabStops();\n }\n\n /** One tab stop per list of rows: the row last focused, else the current one, else the first. */\n function syncTabStops() {\n const currentKey = current == null ? null : `row:${idOf(current)}`;\n for (const prefix of ['row:', 'action:']) {\n const rows = stops.filter((s) => s.key.startsWith(prefix));\n const chosen = rows.find((s) => s.key === rovingKeys[prefix])\n ?? rows.find((s) => s.key === currentKey) ?? rows[0];\n for (const stop of rows) stop.node.tabIndex = stop === chosen ? 0 : -1;\n }\n }\n\n function paintActive() {\n const stop = stops.find((s) => s.key === activeKey) ?? null;\n if (activeNode && activeNode !== stop?.node) activeNode.classList.remove('twm-wspicker__stop--active');\n activeNode = stop?.node ?? null;\n activeNode?.classList.add('twm-wspicker__stop--active');\n if (activeNode?.id) input.setAttribute('aria-activedescendant', activeNode.id);\n else input.removeAttribute('aria-activedescendant');\n }\n\n function revealActive() {\n activeNode?.scrollIntoView?.({ block: 'nearest' });\n }\n\n function settleActive() {\n let reveal = false;\n if (selectId != null && stops.some((s) => s.key === `row:${selectId}`)) {\n activeKey = `row:${selectId}`;\n moved = true;\n selectId = null;\n reveal = true;\n }\n if (!moved || !stops.some((s) => s.key === activeKey)) {\n reveal = moved;\n // The stop that held focus went, with its node or by being hidden: the\n // keyboard must not be left on the body, where none of this panel's keys\n // are heard, or on what no longer is a stop.\n const at = document.activeElement;\n if (moved && isOpen && (at === document.body || (panel.contains(at) && at !== input))) input.focus();\n moved = false;\n activeKey = stops.find((s) => s.primary)?.key ?? null;\n }\n paintActive();\n if (reveal) revealActive();\n }\n\n /** Focus on `stop`, without the browser's own scroll: `revealActive` is the one that may. */\n function focusStop(stop) {\n activeKey = stop.key;\n moved = true;\n stop.node.focus({ preventScroll: true });\n paintActive();\n }\n\n function move(step) {\n const walk = [input, ...stops.map((s) => s.node)];\n // `open({ select })` chose a row and left the caret in the input: the arrows\n // go on from that row.\n const from = document.activeElement === input && moved ? activeNode : document.activeElement;\n const next = walk[(walk.indexOf(from) + step + walk.length) % walk.length];\n if (next === input) {\n input.focus();\n return;\n }\n focusStop(stops.find((s) => s.node === next));\n revealActive();\n }\n\n // \u2500\u2500 drawing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function render() {\n const shown = shownItems();\n const query = remote ? answered : typed();\n const rowEntries = syncRows(shown, idOf);\n const actionEntries = syncActions(shownActions(), (action) => action.id);\n\n const words = heading ? heading({ query, shown: shown.length, total }) : null;\n show(head, !!(words?.title || words?.count));\n setText(headTitle, words?.title);\n setText(headCount, words?.count);\n\n let said = '';\n if (failure) said = failure;\n else if (!shown.length && (loading || total == null)) said = labels.loading;\n else if (!shown.length) said = query ? labels.noMatch(query) : labels.empty();\n setText(note, said);\n show(note, !!said);\n note.classList.toggle('twm-wspicker__note--error', !!failure);\n\n const remaining = remote && total != null ? Math.max(0, total - items.length) : 0;\n show(more, remaining > 0 && !failure);\n if (remaining > 0) {\n setText(moreLabel, labels.loadMore({ next: Math.min(pageSize, remaining), shown: items.length, total }));\n }\n // Not `disabled`: that would drop focus on the body. `loadMore` refuses for itself.\n more.setAttribute('aria-disabled', String(loading || loadingMore));\n\n collectStops(rowEntries, actionEntries, shown);\n settleActive();\n }\n\n function renderEverything() {\n renderCard();\n renderFooter();\n render();\n }\n\n // \u2500\u2500 asking \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function normalize(answer) {\n if (Array.isArray(answer)) return { items: answer, total: answer.length, status: null };\n const list_ = answer?.items || [];\n return {\n items: list_,\n total: Number.isFinite(answer?.total) ? answer.total : list_.length,\n status: answer?.status ?? null,\n };\n }\n\n function unique(all) {\n const seen = new Set();\n return all.filter((item) => {\n const id = idOf(item);\n if (seen.has(id)) return false;\n seen.add(id);\n return true;\n });\n }\n\n async function ask(query) {\n const mine = ++seq;\n asked = query;\n abort?.abort();\n abort = new AbortController();\n const { signal } = abort;\n loading = true;\n failure = null;\n loadingMore = false;\n render();\n try {\n const answer = normalize(await load({ query, offset: 0, limit: pageSize, signal }));\n if (destroyed || mine !== seq) return;\n items = unique(answer.items);\n total = answer.total;\n status = answer.status;\n if (query !== answered) scroller.scrollTop = 0;\n answered = query;\n loading = false;\n if (!query) kept.set(cacheKey(), { items: [...items], total, status });\n renderEverything();\n if (placementNow() === 'below') place();\n if (pickFirst) {\n pickFirst = false;\n stops.find((s) => s.primary)?.run();\n }\n } catch (err) {\n if (destroyed || mine !== seq || err?.name === 'AbortError') return;\n loading = false;\n pickFirst = false;\n items = [];\n total = null;\n status = null;\n answered = query;\n failure = labels.failed(err);\n renderEverything();\n }\n }\n\n async function loadMore({ byKey = false } = {}) {\n if (loading || loadingMore || total == null || items.length >= total) return;\n const mine = seq;\n loadingMore = true;\n render();\n let added = [];\n try {\n const answer = normalize(await load({ query: answered, offset: items.length, limit: pageSize, signal: abort?.signal }));\n if (destroyed || mine !== seq) return;\n const seen = new Set(items.map(idOf));\n added = unique(answer.items).filter((item) => !seen.has(idOf(item)));\n items = items.concat(added);\n // A server that ignores the paging hands back what is drawn: there\n // is no more, whatever it said before.\n total = added.length && Number.isFinite(answer.total) ? answer.total : items.length;\n if (answer.status != null) status = answer.status;\n } catch (err) {\n if (destroyed || mine !== seq || err?.name === 'AbortError') return;\n failure = labels.failedMore(err);\n }\n loadingMore = false;\n // Focus stays on Load more while there is more, else goes to the first\n // row it brought that can be chosen. Only the keyboard scrolls to it.\n const stayed = activeKey === 'more';\n if (stayed && items.length >= total) {\n const first = added.find((item) => !modelOf(item).disabled);\n if (first) {\n activeKey = `row:${idOf(first)}`;\n moved = true;\n }\n }\n renderEverything();\n if (stayed) {\n const stop = stops.find((s) => s.key === activeKey);\n if (stop) focusStop(stop);\n if (byKey) revealActive();\n }\n }\n\n more.addEventListener('click', () => loadMore());\n\n function setBusy(waiting) {\n busy = waiting;\n panel.classList.toggle('twm-wspicker--waiting', waiting);\n backdrop.classList.toggle('twm-wspicker-backdrop--waiting', waiting);\n }\n\n async function removeItem(item) {\n if (busy) return;\n const removedKey = `row:${idOf(item)}`;\n const at = stops.findIndex((s) => s.key === removedKey);\n const following = stops.slice(at + 1).find((s) => s.key.startsWith('row:'))\n ?? stops.slice(0, Math.max(at, 0)).reverse().find((s) => s.key.startsWith('row:'));\n const fromRow = stops[at]?.node === document.activeElement;\n // Before the call: a dialog it opens takes focus before it returns.\n setBusy(true);\n let outcome;\n try {\n outcome = await onRemove(item);\n } catch (err) {\n setBusy(false);\n if (isOpen) {\n failure = labels.failedRemove(err);\n render();\n input.focus();\n }\n return;\n }\n setBusy(false);\n if (!isOpen) return;\n if (outcome !== false) {\n items = items.filter((other) => idOf(other) !== idOf(item));\n if (total != null) total = Math.max(0, total - 1);\n if (activeKey === removedKey && following) {\n activeKey = following.key;\n moved = true;\n }\n ask(remote ? answered : '');\n if (fromRow && following) {\n focusStop(following);\n revealActive();\n return;\n }\n }\n input.focus();\n }\n\n // \u2500\u2500 choosing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function pick(item) {\n const same = isCurrent(item);\n close({ restoreFocus: true });\n if (!same) onPick?.(item);\n }\n\n function runVerb(run) {\n const query = typed();\n close({ restoreFocus: true });\n run?.({ query });\n }\n\n function enter() {\n const query = typed();\n if (remote && query !== asked) {\n clearTimeout(timer);\n timer = null;\n pickFirst = true;\n ask(query);\n return;\n }\n if (loading && !moved) {\n pickFirst = true;\n return;\n }\n stops.find((s) => s.key === activeKey)?.run();\n }\n\n // \u2500\u2500 placing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function placementNow() {\n if (!anchor?.isConnected) return 'centered';\n return anchor.getBoundingClientRect().width > 0 ? placement : 'centered';\n }\n\n function place() {\n const mode = placementNow();\n for (const name of ['over', 'below', 'centered']) {\n panel.classList.toggle(`twm-wspicker--${name}`, mode === name);\n }\n show(backdrop, mode === 'centered');\n for (const side of ['top', 'bottom', 'left', 'right', 'width', 'maxHeight', 'overflowY', 'position']) panel.style[side] = '';\n if (mode === 'centered') return;\n const r = anchor.getBoundingClientRect();\n const width = Math.min(Math.max(r.width, minWidth), window.innerWidth - 2 * PANEL_EDGE);\n panel.style.width = `${width}px`;\n if (mode === 'below') {\n ActionDropdown.position(anchor, panel);\n return;\n }\n const left = r.left + r.width / 2 - width / 2;\n panel.style.left = `${Math.max(PANEL_EDGE, Math.min(left, window.innerWidth - width - PANEL_EDGE))}px`;\n // A field in the lower half (a bottom bar) grows upward, its bottom edge\n // where the field's is, because a list hanging below it has no room.\n if (r.top + r.height / 2 > window.innerHeight / 2) {\n panel.style.bottom = `${Math.max(2, window.innerHeight - r.bottom - OVER_LIFT)}px`;\n } else {\n panel.style.top = `${Math.max(2, r.top - OVER_LIFT)}px`;\n }\n }\n\n // \u2500\u2500 opening and closing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 function openPanel({ select = null } = {}) {\n if (isOpen || destroyed) return;\n isOpen = true;\n opener = document.activeElement;\n selectId = select == null ? null : String(select);\n input.value = '';\n clearTimeout(timer);\n timer = null;\n pickFirst = false;\n moved = false;\n activeKey = null;\n delete rovingKeys['row:'];\n delete rovingKeys['action:'];\n const last = kept.get(cacheKey());\n items = last ? [...last.items] : [];\n total = last ? last.total : null;\n status = last ? last.status : null;\n answered = '';\n asked = '';\n failure = null;\n document.body.append(backdrop, panel);\n place();\n renderEverything();\n scroller.scrollTop = 0;\n document.addEventListener('mousedown', onDocumentDown, true);\n document.addEventListener('keydown', onDocumentKey);\n window.addEventListener('resize', place);\n input.focus();\n onOpenChange?.(true);\n ask('');\n }\n\n function close({ restoreFocus = false } = {}) {\n if (!isOpen) return;\n isOpen = false;\n clearTimeout(timer);\n timer = null;\n pickFirst = false;\n selectId = null;\n // An answer that lands after the panel closed paints nothing.\n seq += 1;\n abort?.abort();\n loading = false;\n loadingMore = false;\n setBusy(false);\n panel.remove();\n backdrop.remove();\n document.removeEventListener('mousedown', onDocumentDown, true);\n document.removeEventListener('keydown', onDocumentKey);\n window.removeEventListener('resize', place);\n onOpenChange?.(false);\n if (restoreFocus && !destroyed) {\n const back = opener?.isConnected && opener !== document.body ? opener : anchor;\n back?.focus?.();\n }\n opener = null;\n }\n\n /** In the capture phase, so a surface that stops the event still closes it. */\n function onDocumentDown(event) {\n if (busy || panel.contains(event.target) || anchor?.contains?.(event.target)) return;\n close();\n }\n\n /** Esc with the focus outside the panel: on the anchor, say. */\n function onDocumentKey(event) {\n if (busy || event.key !== 'Escape' || panel.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n close({ restoreFocus: true });\n }\n\n // A press in the panel leaves focus where it is: on a row or a button it is\n // about to act and close; anywhere else it would drop the keyboard on nothing.\n panel.addEventListener('mousedown', (event) => {\n if (event.target !== input) event.preventDefault();\n });\n\n // Focus gets here by the arrows, Tab or a script, and the highlight goes with it.\n panel.addEventListener('focusin', ({ target, relatedTarget }) => {\n if (target === input) {\n // Back from a stop, not in from outside: `open({ select })` chose first.\n if (panel.contains(relatedTarget)) {\n moved = false;\n settleActive();\n }\n return;\n }\n const stop = stops.find((s) => s.node === target);\n if (!stop) return;\n activeKey = stop.key;\n moved = true;\n // The reader has gone on: an answer still to land does not pull the highlight back.\n selectId = null;\n const prefix = ['row:', 'action:'].find((p) => stop.key.startsWith(p));\n if (prefix) rovingKeys[prefix] = stop.key;\n syncTabStops();\n paintActive();\n });\n\n input.addEventListener('input', () => {\n moved = false;\n scroller.scrollTop = 0;\n if (remote) {\n clearTimeout(timer);\n const query = typed();\n timer = setTimeout(() => {\n timer = null;\n if (query !== asked) ask(query);\n }, debounceMs);\n }\n render();\n });\n\n panel.addEventListener('keydown', (event) => {\n if (event.isComposing || busy) return;\n const { key, shiftKey, target } = event;\n const handled = () => {\n event.preventDefault();\n event.stopPropagation();\n };\n const stop = stops.find((s) => s.node === target);\n if (key === 'Escape') {\n handled();\n close({ restoreFocus: true });\n } else if (key === 'ArrowDown' || key === 'ArrowUp') {\n handled();\n move(key === 'ArrowDown' ? 1 : -1);\n } else if (key === 'Enter' && target === input) {\n handled();\n enter();\n } else if ((key === 'Enter' || key === ' ') && stop) {\n // A row is no button, because it holds one; and Load more scrolls for\n // a key and not for a click.\n handled();\n stop.run();\n } else if (key === 'Delete' && shiftKey) {\n handled();\n stops.find((s) => s.key === activeKey)?.remove?.();\n } else if (key === 'Backspace' && target !== input) {\n // A window manager's keymap reads Backspace on anything that is not\n // a field as \"up one level\"; a row or a button here is not a field.\n handled();\n } else if (target !== input && key.length === 1 && key !== ' '\n && !event.ctrlKey && !event.metaKey && !event.altKey) {\n // Moved before the press lands, so the character lands in the input;\n // and no further, because a keymap would read it as a shortcut: the\n // press began on something that is not a field.\n event.stopPropagation();\n input.focus();\n }\n });\n\n panel.addEventListener('focusout', (event) => {\n const to = event.relatedTarget;\n if (!busy && to && !panel.contains(to) && !anchor?.contains?.(to)) close();\n });\n\n return {\n panel,\n input,\n get isOpen() { return isOpen; },\n get current() { return current; },\n open: openPanel,\n close,\n toggle() {\n if (isOpen) close({ restoreFocus: true });\n else openPanel();\n },\n /** Which one the window is in, whether or not an answer holds it. */\n setCurrent(item) {\n current = item ?? null;\n if (isOpen) renderEverything();\n },\n /** Ask `actions`, `card` and `footer` again: who may do what changed. */\n refresh() {\n if (isOpen) renderEverything();\n },\n /** Ask `load` again: the list changed behind the switcher's back. */\n reload() {\n if (isOpen) ask(remote ? typed() : '');\n },\n destroy() {\n close();\n destroyed = true;\n },\n };\n}\n\n/**\n * The field and the switcher together: a click on the field, or the chord,\n * opens the switcher in the field's place; `setCurrent` names the current item\n * on the field and marks it in the list.\n *\n * `chord` is none by default. Given (`'Ctrl+P'`; Ctrl also answers to Cmd), it\n * is taken on `window` in the capture phase, ahead of an embedded editor and of\n * the browser's own use of the key, and it is the key hint unless\n * `field.keyHint` says otherwise. It still works while the field is hidden for\n * want of room.\n *\n * @param {HTMLElement} hostEl - Where the field mounts\n * @param {object} options - `createPickerSwitcher`'s, and:\n * @param {object} [options.field] - `mountPickerField`'s. `field.placeholder` is\n * its name while nothing is current; `field.icon`, when given, is its icon\n * whatever is current, and otherwise the current item's `icon` is.\n * @param {string} [options.chord]\n */\nexport function createWorkspacePicker(hostEl, { field: fieldOptions = {}, chord = null, ...switcherOptions }) {\n const { placeholder = '', icon: fixedIcon, ...mountOptions } = fieldOptions;\n const parsed = chord ? parseChord(chord) : null;\n const field = mountPickerField(hostEl, {\n ariaLabel: switcherOptions.label,\n keyHint: chord ?? '',\n ...mountOptions,\n onActivate: () => switcher.toggle(),\n });\n const switcher = createPickerSwitcher({\n ...switcherOptions,\n anchor: field.el,\n onOpenChange: (open) => {\n field.setOpen(open);\n switcherOptions.onOpenChange?.(open);\n },\n });\n\n const paint = () => {\n const item = switcher.current;\n const model = item == null ? null : switcherOptions.describe(item, { current: true });\n field.update({\n name: model ? model.name : placeholder,\n icon: fixedIcon ?? model?.icon ?? '',\n muted: !model,\n });\n };\n paint();\n\n const onKeydown = (event) => {\n if (!chordMatches(parsed, event)) return;\n event.preventDefault();\n event.stopPropagation();\n if (!event.repeat) switcher.toggle();\n };\n if (parsed) window.addEventListener('keydown', onKeydown, true);\n\n return {\n field,\n switcher,\n get el() { return field.el; },\n get isOpen() { return switcher.isOpen; },\n get current() { return switcher.current; },\n open: switcher.open,\n close: switcher.close,\n toggle: switcher.toggle,\n refresh: switcher.refresh,\n reload: switcher.reload,\n setCurrent(item) {\n switcher.setCurrent(item);\n paint();\n },\n destroy() {\n if (parsed) window.removeEventListener('keydown', onKeydown, true);\n switcher.destroy();\n field.destroy();\n },\n };\n}\n", "/**\n * WindowChromeController\n *\n * Handles frameless window management for the desktop application:\n * - Window minimize, maximize, close buttons\n * - Resize handles (edges and corners)\n * - Top bar dragging for window movement\n * - F11 fullscreen toggle\n *\n * Talks to the embedder ONLY through a Host's `window` capability\n * (see src/host/host.js). A host with no `window` capability \u2014 a browser\n * tab, a VS Code webview, the standalone demo \u2014 is legal: we simply don't\n * install custom chrome. That degraded path is also the production path on\n * Linux, macOS and `--browser`, where the OS/browser draws the title bar.\n *\n * THREE MODES, decided by `host.window.chrome()` (which may answer with a\n * promise: the Photino host asks its native side): a browser tab and a window\n * with native chrome get NOTHING from this class (no handles, no buttons, no\n * body class), and only a window that answers `custom` gets the chrome.\n *\n * NATIVE GESTURES. A host that offers `startNativeDrag()` and\n * `startNativeResize(edge)` gets drags on the top bar and presses on the\n * resize handles handed to the OS, which brings snapping and a resize that\n * keeps up with the pointer. A host without them gets the JS move and resize\n * over getBounds/setBounds.\n *\n * @param {object} [opts]\n * @param {object} [opts.host] a Host; only its `window` capability is used\n * @param {string|Element} [opts.topBar='.twm-global-top-bar'] the bar that drags the window\n * @param {string|Element} [opts.controls] where to draw minimise/maximise/close when\n * the page has no `#win-minimize`/`#win-maximize`/`#win-close` of its own\n * (default: the top bar's `.twm-bar-right`, else the top bar itself)\n * @param {string} [opts.noDrag] more selectors that never start a drag\n */\n\nconst SUPPORTS_POINTER = typeof window !== 'undefined' && 'onpointerdown' in window;\nconst MIN_WIDTH = 500;\nconst MIN_HEIGHT = 350;\nconst DRAG_THRESHOLD = 4;\n\nexport class WindowChromeController {\n constructor({ eventBus, logger, host, topBar = '.twm-global-top-bar', controls = null, noDrag = '' } = {}) {\n this.eventBus = eventBus;\n this.logger = logger || console;\n this._topBarOpt = topBar;\n this._controlsOpt = controls;\n this._noDrag = noDrag;\n this._createdControls = null;\n\n // The host's window capability, or null. Never throw on a missing\n // one \u2014 see the class comment.\n this.win = host?.window || null;\n\n this.resizingActive = false;\n this.lastDblClickTs = 0;\n this.handles = {};\n this.topBar = null;\n\n this._disposed = false;\n this._disposers = [];\n }\n\n /**\n * Initialize the window chrome controller\n */\n async initialize() {\n if (this._disposed) return false;\n\n let chrome = 'native';\n try { chrome = this.win ? await this.win.chrome() : 'native'; } catch (_) { chrome = 'native'; }\n if (this._disposed) return false;\n if (chrome !== 'custom') {\n // Native window decorations (Linux/macOS) or the browser already\n // provide a title bar + window controls; our custom chrome would be\n // a redundant second set. Skip it entirely.\n this.logger.info?.('[WindowChrome] Native/browser chrome detected \u2014 custom window chrome disabled');\n return false;\n }\n\n document.body.classList.add('twm-custom-chrome');\n this.#createWindowControls();\n this.#wireWindowButtons();\n this.#createResizeHandles();\n this.#wireTopBarDrag();\n this.#wireKeyboardShortcuts();\n this.#wireNativeStateSync();\n this.#initializeState();\n \n this.logger.info?.('[WindowChrome] Initialized');\n return true;\n }\n\n /** An element from a selector or an element; null when there is none. */\n #resolve(target, within = document) {\n if (!target) return null;\n if (typeof target !== 'string') return target;\n return within.querySelector(target);\n }\n\n /**\n * Draw minimise, maximise/restore and close, unless the page has its own\n * `#win-*` buttons (an embedder's own markup), which are then wired instead.\n */\n #createWindowControls() {\n if (document.getElementById('win-minimize') || document.getElementById('win-close')) return;\n const bar = this.#resolve(this._topBarOpt);\n const host = this.#resolve(this._controlsOpt)\n || bar?.querySelector('.twm-bar-right')\n || bar;\n if (!host) return;\n const box = document.createElement('div');\n box.className = 'twm-window-controls';\n const button = (id, icon, label, extra = '') => {\n const b = document.createElement('button');\n b.type = 'button';\n b.id = id;\n b.className = `twm-window-controls__btn${extra}`;\n b.setAttribute('aria-label', label);\n b.title = label;\n const i = document.createElement('span');\n i.className = 'material-symbols-outlined';\n i.textContent = icon;\n b.appendChild(i);\n box.appendChild(b);\n };\n button('win-minimize', 'remove', 'Minimize');\n button('win-maximize', 'check_box_outline_blank', 'Maximize');\n button('win-close', 'close', 'Close', ' twm-window-controls__btn--close');\n host.appendChild(box);\n this._createdControls = box;\n }\n\n /**\n * Wire minimize, maximize, close buttons\n */\n #wireWindowButtons() {\n const minBtn = document.getElementById('win-minimize');\n const maxBtn = document.getElementById('win-maximize');\n const closeBtn = document.getElementById('win-close');\n\n if (minBtn) {\n const handler = () => this.win.minimize();\n minBtn.addEventListener('click', handler);\n this._disposers.push(() => minBtn.removeEventListener('click', handler));\n }\n\n if (maxBtn) {\n const handler = async () => {\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Maximize toggle failed', e);\n }\n };\n maxBtn.addEventListener('click', handler);\n this._disposers.push(() => maxBtn.removeEventListener('click', handler));\n }\n\n if (closeBtn) {\n const handler = () => this.win.close();\n closeBtn.addEventListener('click', handler);\n this._disposers.push(() => closeBtn.removeEventListener('click', handler));\n }\n }\n\n /**\n * Update maximize button icon and body class\n */\n #updateMaximizeIcon(isMax) {\n const maxBtn = document.getElementById('win-maximize');\n if (!maxBtn) return;\n \n const icon = maxBtn.querySelector('.material-symbols-outlined');\n if (icon) {\n icon.textContent = isMax ? 'filter_none' : 'check_box_outline_blank';\n }\n const tooltipText = isMax ? 'Restore' : 'Maximize';\n window.LatexTooltip?.set(maxBtn, tooltipText);\n maxBtn.setAttribute('aria-label', tooltipText);\n maxBtn.title = tooltipText;\n \n document.body.classList.toggle('twm-window-maximized', isMax);\n }\n\n /**\n * Enable/disable resize handles\n */\n #setResizeHandlesEnabled(enabled) {\n Object.values(this.handles).forEach(handle => {\n if (handle) {\n handle.style.pointerEvents = enabled ? 'auto' : 'none';\n }\n });\n }\n\n /**\n * Set fullscreen body class\n */\n #setFullscreenClass(isFs) {\n document.body.classList.toggle('window-fullscreen', isFs);\n }\n\n /**\n * Create all resize handles\n */\n #createResizeHandles() {\n const positions = ['right', 'left', 'top', 'bottom'];\n const corners = ['br', 'bl', 'tr', 'tl'];\n\n positions.forEach(pos => {\n const handle = document.createElement('div');\n handle.className = `twm-resize-handle ${pos}`;\n document.body.appendChild(handle);\n this.handles[pos] = handle;\n this.#setupResize(handle, pos);\n });\n\n corners.forEach(corner => {\n const handle = document.createElement('div');\n handle.className = `twm-resize-handle corner ${corner}`;\n document.body.appendChild(handle);\n const mode = 'corner' + corner.toUpperCase();\n this.handles[mode] = handle;\n this.#setupResize(handle, mode);\n });\n }\n\n /**\n * Setup resize behavior for a handle\n */\n #setupResize(handle, mode) {\n let startX = 0, startY = 0, startScreenX = 0, startScreenY = 0;\n let startW = 0, startH = 0, startLeft = 0, startTop = 0;\n let pending = null;\n let rafScheduled = false;\n let lastSent = null;\n\n const boundsEqual = (a, b) => {\n return !!a && !!b && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n };\n\n const sendBounds = () => {\n rafScheduled = false;\n if (!pending) return;\n if (lastSent && boundsEqual(lastSent, pending)) return;\n this.win.setBounds({ x: pending.x, y: pending.y, width: pending.w, height: pending.h });\n lastSent = pending;\n };\n\n const scheduleSend = () => {\n if (!rafScheduled) {\n rafScheduled = true;\n requestAnimationFrame(sendBounds);\n }\n };\n\n let activePointerId = null;\n\n const EDGE = {\n right: 'e', left: 'w', top: 'n', bottom: 's',\n cornerBR: 'se', cornerBL: 'sw', cornerTR: 'ne', cornerTL: 'nw',\n };\n\n const startDrag = async (e) => {\n if (e.button != null && e.button !== 0) return;\n e.preventDefault();\n // \u2500\u2500 Native resize: the OS runs its own size loop (it blocks until\n // mouse-up), so the edge stays under the pointer. \u2500\u2500\n if (this.win.startNativeResize) {\n this.resizingActive = true;\n let handled = false;\n try { handled = await this.win.startNativeResize(EDGE[mode]); } catch (_) { handled = false; }\n this.resizingActive = false;\n if (handled) return;\n }\n this.resizingActive = true;\n startX = e.clientX;\n startY = e.clientY;\n startScreenX = e.screenX ?? startX;\n startScreenY = e.screenY ?? startY;\n\n try {\n const res = await this.win.getBounds();\n if (res) {\n startLeft = typeof res.x === 'number' ? res.x : 0;\n startTop = typeof res.y === 'number' ? res.y : 0;\n startW = res.width || document.documentElement.clientWidth;\n startH = res.height || document.documentElement.clientHeight;\n } else {\n startLeft = 0;\n startTop = 0;\n startW = document.documentElement.clientWidth;\n startH = document.documentElement.clientHeight;\n }\n } catch (e) {\n startLeft = 0;\n startTop = 0;\n startW = document.documentElement.clientWidth;\n startH = document.documentElement.clientHeight;\n }\n\n startLeft = Math.round(startLeft);\n startTop = Math.round(startTop);\n startW = Math.round(startW);\n startH = Math.round(startH);\n pending = null;\n lastSent = null;\n rafScheduled = false;\n\n // Capture pointer for smooth resize even when cursor escapes the handle\n if (SUPPORTS_POINTER && e.pointerId != null && handle.setPointerCapture) {\n try {\n handle.setPointerCapture(e.pointerId);\n activePointerId = e.pointerId;\n } catch (_) {}\n }\n\n if (SUPPORTS_POINTER) {\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', endDrag, { once: true });\n } else {\n window.addEventListener('mousemove', onMove, { passive: false });\n window.addEventListener('mouseup', endDrag, { once: true });\n }\n };\n\n const onMove = (e) => {\n const sx = e.screenX ?? e.clientX ?? 0;\n const sy = e.screenY ?? e.clientY ?? 0;\n const dx = sx - startScreenX;\n const dy = sy - startScreenY;\n\n let newX = startLeft;\n let newY = startTop;\n let newW = startW;\n let newH = startH;\n\n const isLeft = mode === 'left' || mode === 'cornerBL' || mode === 'cornerTL';\n const isRight = mode === 'right' || mode === 'cornerBR' || mode === 'cornerTR';\n const isTop = mode === 'top' || mode === 'cornerTR' || mode === 'cornerTL';\n const isBottom = mode === 'bottom' || mode === 'cornerBR' || mode === 'cornerBL';\n\n if (isLeft) {\n const candidateWidth = startW - dx;\n newW = Math.max(MIN_WIDTH, candidateWidth);\n const shift = startW - newW;\n newX = startLeft + shift;\n } else if (isRight) {\n newW = Math.max(MIN_WIDTH, startW + dx);\n }\n\n if (isTop) {\n const candidateHeight = startH - dy;\n newH = Math.max(MIN_HEIGHT, candidateHeight);\n const shiftY = startH - newH;\n newY = startTop + shiftY;\n } else if (isBottom) {\n newH = Math.max(MIN_HEIGHT, startH + dy);\n }\n\n newX = Math.round(newX);\n newY = Math.round(newY);\n newW = Math.max(MIN_WIDTH, Math.round(newW));\n newH = Math.max(MIN_HEIGHT, Math.round(newH));\n\n pending = { x: newX, y: newY, w: newW, h: newH };\n scheduleSend();\n };\n\n const endDrag = () => {\n if (SUPPORTS_POINTER) {\n window.removeEventListener('pointermove', onMove);\n } else {\n window.removeEventListener('mousemove', onMove);\n }\n // Release pointer capture\n if (activePointerId != null && handle.releasePointerCapture) {\n try { handle.releasePointerCapture(activePointerId); } catch (_) {}\n activePointerId = null;\n }\n // Flush any pending bounds update that was waiting for rAF\n if (pending && (!lastSent || !boundsEqual(lastSent, pending))) {\n this.win.setBounds({ x: pending.x, y: pending.y, width: pending.w, height: pending.h });\n }\n pending = null;\n lastSent = null;\n this.resizingActive = false;\n };\n\n const event = SUPPORTS_POINTER ? 'pointerdown' : 'mousedown';\n handle.addEventListener(event, startDrag);\n this._disposers.push(() => handle.removeEventListener(event, startDrag));\n }\n\n /**\n * Setup top bar dragging for window movement\n */\n #wireTopBarDrag() {\n this.topBar = this.#resolve(this._topBarOpt);\n if (!this.topBar) return;\n\n // What never starts a drag: anything you can click or type into. An\n // embedder adds its own with `noDrag`. (`.window-controls` and\n // `.panel-toggles` are kept for embedders' own markup of that shape.)\n // A menu bar in the top bar (a hamburger, STORY-0133) drops its menus\n // inside the bar's DOM: a press on a menu's padding or separator is\n // in the bar, not a drag.\n const NO_DRAG_SELECTOR = [\n '.no-drag', 'button', 'a', 'input', 'select', 'textarea', 'label',\n '[role=\"button\"]', '[role=\"menuitem\"]', '[role=\"tab\"]', '[contenteditable=\"true\"]',\n '.twm-window-controls', '.window-controls', '.panel-toggles', '.twm-menubar',\n this._noDrag,\n ].filter(Boolean).join(', ');\n\n let dragging = false;\n let startSX = 0, startSY = 0, startX = null, startY = null, winW = 0, winH = 0;\n let wasMax = false;\n let didRestore = false;\n let grabRatio = 0.5;\n let raf = null;\n let lastSentX = null, lastSentY = null;\n let activePointerId = null;\n\n // Double-click detection (native drag swallows dblclick events)\n const DBL_CLICK_TIME = 500;\n const DBL_CLICK_DIST = 4;\n let lastDownTime = 0;\n let lastDownX = 0;\n let lastDownY = 0;\n\n const isInteractiveTarget = (t) => !!(t && t.closest && t.closest(NO_DRAG_SELECTOR));\n\n const onMove = (e) => {\n // IMPORTANT: This must NOT be async to avoid race conditions on first drag\n const sx = e.screenX ?? e.clientX ?? 0;\n const sy = e.screenY ?? e.clientY ?? 0;\n const dx = Math.abs(sx - startSX);\n const dy = Math.abs(sy - startSY);\n\n if (!dragging) {\n if (wasMax) {\n if ((dx + dy) <= 0) return;\n // Handle restore from maximized state\n if (!didRestore) {\n didRestore = true;\n // Fire-and-forget the restore, then reposition\n this.win.setMaximized(false).then(() => {\n this.#updateMaximizeIcon(false);\n this.#setResizeHandlesEnabled(true);\n return this.win.getBounds();\n }).then((bounds) => {\n if (bounds) {\n const rw = bounds.width || 800;\n const rh = bounds.height || 600;\n const targetX = Math.max(0, Math.round(startSX - (rw * grabRatio)));\n const targetY = Math.max(0, Math.round(sy - 10));\n this.win.setBounds({ x: targetX, y: targetY, width: rw, height: rh });\n startX = targetX;\n startY = targetY;\n winW = rw;\n winH = rh;\n startSX = sx;\n startSY = sy;\n }\n }).catch((err) => {\n this.logger.warn?.('[WindowChrome] Restore on drag failed', err);\n });\n }\n return; // Don't proceed with normal drag until restore completes\n } else {\n if ((dx + dy) < DRAG_THRESHOLD) return;\n // startX/startY should already be set by startDrag - if not, skip this move\n if (startX == null || startY == null) {\n return;\n }\n }\n dragging = true;\n }\n\n // Use the bounds fetched in startDrag (never default to 0)\n if (startX == null || startY == null) return;\n\n const nx = Math.round(startX + (sx - startSX));\n const ny = Math.round(startY + (sy - startSY));\n\n if (lastSentX === nx && lastSentY === ny) return;\n\n if (raf) cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n lastSentX = nx;\n lastSentY = ny;\n this.win.setBounds({ x: nx, y: ny });\n });\n };\n\n const endDrag = () => {\n dragging = false;\n if (raf) {\n cancelAnimationFrame(raf);\n raf = null;\n }\n if (activePointerId != null && this.topBar.releasePointerCapture) {\n try {\n this.topBar.releasePointerCapture(activePointerId);\n } catch (e) {}\n }\n activePointerId = null;\n didRestore = false;\n\n if (SUPPORTS_POINTER) {\n window.removeEventListener('pointermove', onMove, true);\n window.removeEventListener('pointerup', endDrag, true);\n } else {\n window.removeEventListener('mousemove', onMove, true);\n window.removeEventListener('mouseup', endDrag, true);\n }\n };\n\n const startDrag = async (e) => {\n if (this.resizingActive) return;\n if (isInteractiveTarget(e.target)) return;\n if ((Date.now() - this.lastDblClickTs) < 300) return;\n\n // Detect double-click before entering native drag (which\n // blocks the message loop and prevents dblclick events).\n const now = Date.now();\n const cx = e.clientX ?? 0;\n const cy = e.clientY ?? 0;\n if ((now - lastDownTime) < DBL_CLICK_TIME\n && Math.abs(cx - lastDownX) < DBL_CLICK_DIST\n && Math.abs(cy - lastDownY) < DBL_CLICK_DIST) {\n lastDownTime = 0;\n this.lastDblClickTs = now;\n e.preventDefault();\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (err) {\n this.logger.warn?.('[WindowChrome] Double-click maximize failed', err);\n }\n return;\n }\n lastDownTime = now;\n lastDownX = cx;\n lastDownY = cy;\n\n try {\n if (!this.win) return;\n\n // \u2500\u2500 Native drag (enables Aero Snap) \u2500\u2500\n // The call blocks until the OS drag loop ends (mouse-up).\n // On return the window has already moved/snapped.\n if (this.win.startNativeDrag) {\n e.preventDefault();\n if (await this.win.startNativeDrag()) {\n // Sync UI state after native drag (may have snapped/maximized)\n try {\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (_) {}\n return;\n }\n // Native drag unavailable \u2014 fall through to JS drag\n }\n\n // \u2500\u2500 JS drag fallback (non-Windows) \u2500\u2500\n startSX = e.screenX ?? e.clientX ?? 0;\n startSY = e.screenY ?? e.clientY ?? 0;\n\n try {\n wasMax = await this.win.isMaximized();\n } catch (e) {\n wasMax = false;\n }\n\n const barWidth = Math.max(1, window.innerWidth || document.documentElement.clientWidth);\n grabRatio = Math.min(1, Math.max(0, (e.clientX || 0) / barWidth));\n\n if (!wasMax) {\n const bounds = await this.win.getBounds();\n if (bounds) {\n startX = typeof bounds.x === 'number' ? bounds.x : (window.screenX ?? 0);\n startY = typeof bounds.y === 'number' ? bounds.y : (window.screenY ?? 0);\n winW = bounds.width || document.documentElement.clientWidth;\n winH = bounds.height || document.documentElement.clientHeight;\n } else {\n startX = window.screenX ?? 0;\n startY = window.screenY ?? 0;\n winW = document.documentElement.clientWidth;\n winH = document.documentElement.clientHeight;\n }\n }\n\n e.preventDefault();\n\n if (SUPPORTS_POINTER && e.pointerId != null && this.topBar.setPointerCapture) {\n try {\n this.topBar.setPointerCapture(e.pointerId);\n activePointerId = e.pointerId;\n } catch (e) {}\n }\n\n if (SUPPORTS_POINTER) {\n window.addEventListener('pointermove', onMove, true);\n window.addEventListener('pointerup', endDrag, true);\n } else {\n window.addEventListener('mousemove', onMove, true);\n window.addEventListener('mouseup', endDrag, true);\n }\n } catch (err) {\n this.logger.warn?.('[WindowChrome] Start drag failed', err);\n }\n };\n\n // Block drag during resize\n const blocker = (e) => {\n if (this.resizingActive) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n this.topBar.addEventListener('mousedown', blocker, true);\n this.topBar.addEventListener('pointerdown', blocker, true);\n\n // Double-click to toggle maximize (only on blank surfaces)\n const dblClickHandler = async (e) => {\n // Skip maximize if double-click is on interactive elements\n if (isInteractiveTarget(e.target)) {\n return;\n }\n\n this.lastDblClickTs = Date.now();\n e.preventDefault();\n e.stopPropagation();\n if (this.resizingActive) return;\n\n try {\n const isMax = await this.win.setMaximized(!(await this.win.isMaximized()));\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Double-click maximize failed', e);\n }\n };\n this.topBar.addEventListener('dblclick', dblClickHandler);\n\n // Start drag\n const event = SUPPORTS_POINTER ? 'pointerdown' : 'mousedown';\n this.topBar.addEventListener(event, startDrag, false);\n\n this._disposers.push(() => {\n this.topBar.removeEventListener('mousedown', blocker, true);\n this.topBar.removeEventListener('pointerdown', blocker, true);\n this.topBar.removeEventListener('dblclick', dblClickHandler);\n this.topBar.removeEventListener(event, startDrag, false);\n });\n }\n\n /**\n * Listen for browser resize events to sync UI with native state changes\n * (e.g. Win+Arrow maximize/restore, Win+Down minimize).\n */\n #wireNativeStateSync() {\n let syncTimer = null;\n const syncState = async () => {\n if (this.resizingActive || this._disposed) return;\n try {\n if (!this.win) return;\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n } catch (_) {}\n };\n const handler = () => {\n // Debounce: native snap triggers multiple resize events\n clearTimeout(syncTimer);\n syncTimer = setTimeout(syncState, 80);\n };\n window.addEventListener('resize', handler);\n this._disposers.push(() => {\n window.removeEventListener('resize', handler);\n clearTimeout(syncTimer);\n });\n }\n\n /**\n * Wire F11 fullscreen toggle\n */\n #wireKeyboardShortcuts() {\n const handler = async (e) => {\n if (e.code === 'F11') {\n e.preventDefault();\n try {\n const isFs = await this.win.toggleFullscreen();\n this.#setFullscreenClass(isFs);\n const max = await this.win.isMaximized();\n this.#setResizeHandlesEnabled(!(isFs || max));\n } catch (e) {\n this.logger.warn?.('[WindowChrome] F11 toggle failed', e);\n }\n }\n };\n window.addEventListener('keydown', handler, true);\n this._disposers.push(() => window.removeEventListener('keydown', handler, true));\n }\n\n /**\n * Initialize window state on startup\n */\n async #initializeState() {\n try {\n if (!this.win) return;\n\n const isMax = await this.win.isMaximized();\n this.#updateMaximizeIcon(isMax);\n this.#setResizeHandlesEnabled(!isMax);\n\n const isFs = await this.win.isFullscreen();\n this.#setFullscreenClass(isFs);\n if (isFs) this.#setResizeHandlesEnabled(false);\n } catch (e) {\n this.logger.warn?.('[WindowChrome] Initial state check failed', e);\n }\n }\n\n /**\n * Dispose of the controller\n */\n dispose() {\n if (this._disposed) return;\n this._disposed = true;\n\n this._disposers.forEach(dispose => {\n try {\n dispose();\n } catch (e) {}\n });\n this._disposers = [];\n\n // Remove resize handles, and the buttons this drew\n Object.values(this.handles).forEach(handle => {\n if (handle && handle.parentNode) {\n handle.parentNode.removeChild(handle);\n }\n });\n this.handles = {};\n this._createdControls?.remove();\n this._createdControls = null;\n document.body.classList.remove('twm-custom-chrome', 'twm-window-maximized', 'window-fullscreen');\n\n this.logger.info?.('[WindowChrome] Disposed');\n }\n}\n", "/**\n * auto_scrollbars.js \u2014 the overlay scrollbar, on EVERY scrollable element.\n *\n * `installOverlayScrollbar` (overlay_scrollbar.js) gives one container a thin\n * bar that shows on hover and fades away. It is installed container by\n * container, it puts the bar INSIDE the container, and it holds a resize\n * observer, a subtree mutation observer and a window listener for each one.\n * That is fine for a handful of known panes and wrong for \"all of them\": a\n * page that redraws with `innerHTML = ''` deletes its bar for good, and a\n * table body, a dropdown, a textarea and a dialog each want one.\n *\n * So this is the same look, done once for a whole subtree:\n *\n * - Native scrollbars are hidden under `root`, so no element reserves\n * layout width for one and nothing reflows when a bar appears.\n * - Bars live in ONE fixed layer on `document.body`, positioned over the\n * element they belong to. Nothing is added to a scroll container, so a\n * redraw cannot remove a bar, and a textarea (which cannot hold children)\n * gets one too.\n * - An element gets its bars when the pointer is over it or it scrolls, if\n * it actually overflows. They fade out a moment after the pointer leaves\n * or the scrolling stops. Nested scroll areas each show their own.\n * - The thumb drags and the track pages, as a native bar does.\n * - The layer is above everything, so a bar would also draw over whatever\n * covers its element \u2014 a popover, a menu, a dialog. A bar whose track is\n * covered anywhere is not drawn; it comes back when it is uncovered.\n *\n * Discovery is lazy: the pointer and scroll events name the elements worth\n * measuring, so nothing walks the DOM looking for scroll areas.\n */\n\nconst LAYER_ID = 'twm-autoscroll-layer';\nconst ROOT_CLASS = 'twm-autoscroll';\nconst HIDE_AFTER_MS = 900;\nconst MIN_THUMB = 30;\nconst BAR = 6;\n\n/**\n * Where the thumb goes. Pure, so it can be tested without a layout engine.\n *\n * @param {number} scrollSize scrollHeight / scrollWidth\n * @param {number} clientSize clientHeight / clientWidth\n * @param {number} scrollPos scrollTop / scrollLeft\n * @param {number} trackLen the bar's length on screen (px)\n * @returns {{size:number, pos:number}|null} null when nothing overflows\n */\nexport function thumbGeometry(scrollSize, clientSize, scrollPos, trackLen) {\n const max = scrollSize - clientSize;\n if (!(max > 1) || !(trackLen > 0)) return null;\n const size = Math.min(trackLen, Math.max(MIN_THUMB, trackLen * clientSize / scrollSize));\n const pos = (trackLen - size) * Math.min(1, Math.max(0, scrollPos / max));\n return { size, pos };\n}\n\n/**\n * Whether something else covers `el` at any of the points a bar runs along.\n * Pure, so it can be tested without a layout engine.\n *\n * @param {Element} el\n * @param {Element[][]} stacks what `elementsFromPoint` gave at each point,\n * topmost first. The overlay layer's own bars are skipped, and so are the\n * window's `.twm-resize-handle` edge strips (BUG-0036): they lie over every\n * pane flush against a window edge and are chrome, not cover.\n * @returns {boolean}\n */\nexport function barCovered(el, stacks) {\n const passThrough = (h) => h.closest?.('.twm-autoscroll-layer') || h.closest?.('.twm-resize-handle');\n return stacks.some((stack) => {\n const top = (stack || []).find((h) => !passThrough(h));\n return Boolean(top) && top !== el && !el.contains(top);\n });\n}\n\n/** Whether an element scrolls on an axis: its overflow allows it and its\n * content is larger than its box. */\nfunction scrollsOn(el, axis) {\n if (!(el instanceof Element)) return false;\n const cs = getComputedStyle(el);\n const overflow = axis === 'y' ? cs.overflowY : cs.overflowX;\n if (overflow !== 'auto' && overflow !== 'scroll' && !(el.tagName === 'TEXTAREA' && overflow !== 'hidden')) return false;\n return axis === 'y' ? el.scrollHeight - el.clientHeight > 1 : el.scrollWidth - el.clientWidth > 1;\n}\n\n/**\n * Give every scrollable element under `root` an auto-hiding overlay scrollbar.\n *\n * @param {HTMLElement} [root=document.body]\n * @param {{exclude?: (el: Element) => boolean}} [opts] elements to leave to\n * their own scrollbar. Containers that already carry an\n * `installOverlayScrollbar` bar are always left alone.\n * @returns {{dispose: () => void}}\n */\nexport function installAutoScrollbars(root = document.body, { exclude = null } = {}) {\n const doc = root.ownerDocument || document;\n const win = doc.defaultView || window;\n root.classList.add(ROOT_CLASS);\n\n let layer = doc.getElementById(LAYER_ID);\n if (!layer) {\n layer = doc.createElement('div');\n layer.id = LAYER_ID;\n layer.className = 'twm-autoscroll-layer';\n doc.body.appendChild(layer);\n }\n\n /** element -> { v, h, timer, hovered } */\n const managed = new Map();\n let hoverChain = new Set();\n\n const eligible = (el) => el instanceof Element\n && root.contains(el)\n && !el.__overlayScrollbarInstalled\n && !el.closest?.('.twm-autoscroll-layer')\n && !(exclude && exclude(el));\n\n const makeBar = (el, axis) => {\n const bar = doc.createElement('div');\n bar.className = `twm-autoscroll-bar twm-autoscroll-bar--${axis}`;\n const thumb = doc.createElement('div');\n thumb.className = 'twm-autoscroll-thumb';\n bar.appendChild(thumb);\n layer.appendChild(bar);\n\n // The track pages, like a native bar's.\n bar.addEventListener('mousedown', (e) => {\n if (e.target !== bar) return;\n e.preventDefault();\n const r = thumb.getBoundingClientRect();\n const before = axis === 'y' ? e.clientY < r.top : e.clientX < r.left;\n const page = (axis === 'y' ? el.clientHeight : el.clientWidth) * 0.9;\n if (axis === 'y') el.scrollTop += before ? -page : page;\n else el.scrollLeft += before ? -page : page;\n });\n // The thumb drags.\n thumb.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const rec = managed.get(el);\n if (rec) rec.dragging = true;\n const start = axis === 'y' ? e.clientY : e.clientX;\n const startScroll = axis === 'y' ? el.scrollTop : el.scrollLeft;\n const trackLen = axis === 'y' ? bar.getBoundingClientRect().height : bar.getBoundingClientRect().width;\n const thumbLen = axis === 'y' ? thumb.getBoundingClientRect().height : thumb.getBoundingClientRect().width;\n const max = axis === 'y' ? el.scrollHeight - el.clientHeight : el.scrollWidth - el.clientWidth;\n const perPx = trackLen > thumbLen ? max / (trackLen - thumbLen) : 0;\n bar.classList.add('twm-autoscroll-bar--active');\n const move = (mv) => {\n const d = (axis === 'y' ? mv.clientY : mv.clientX) - start;\n if (axis === 'y') el.scrollTop = startScroll + d * perPx;\n else el.scrollLeft = startScroll + d * perPx;\n };\n const up = () => {\n doc.removeEventListener('mousemove', move);\n doc.removeEventListener('mouseup', up);\n bar.classList.remove('twm-autoscroll-bar--active');\n if (rec) rec.dragging = false;\n hideLater(el);\n };\n doc.addEventListener('mousemove', move);\n doc.addEventListener('mouseup', up);\n });\n bar.addEventListener('mouseenter', () => { const rec = managed.get(el); if (rec) { rec.onBar = true; show(el); } });\n bar.addEventListener('mouseleave', () => { const rec = managed.get(el); if (rec) { rec.onBar = false; hideLater(el); } });\n return { bar, thumb };\n };\n\n const record = (el) => {\n let rec = managed.get(el);\n if (!rec) {\n rec = { v: null, h: null, timer: 0, dragging: false, onBar: false };\n managed.set(el, rec);\n }\n return rec;\n };\n\n const coveredAlong = (el, points) => typeof doc.elementsFromPoint === 'function'\n && barCovered(el, points.map(([x, y]) => doc.elementsFromPoint(x, y)));\n\n /** Place and size an element's bars; drop the element when it is gone. */\n const place = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n if (!el.isConnected) { drop(el); return; }\n const r = el.getBoundingClientRect();\n const vw = win.innerWidth;\n const vh = win.innerHeight;\n const top = Math.max(0, r.top);\n const left = Math.max(0, r.left);\n const bottom = Math.min(vh, r.bottom);\n const right = Math.min(vw, r.right);\n // Screen px per CSS px, for content inside a zoomed tile.\n const z = el.offsetHeight ? r.height / el.offsetHeight : 1;\n for (const axis of ['y', 'x']) {\n const key = axis === 'y' ? 'v' : 'h';\n const overflows = scrollsOn(el, axis);\n if (!overflows) { if (rec[key]) rec[key].bar.style.display = 'none'; continue; }\n if (!rec[key]) rec[key] = makeBar(el, axis);\n const { bar, thumb } = rec[key];\n bar.style.display = '';\n if (axis === 'y') {\n const len = bottom - top;\n Object.assign(bar.style, { top: `${top}px`, left: `${right - BAR - 1}px`, height: `${len}px`, width: `${BAR}px` });\n const g = thumbGeometry(el.scrollHeight * z, el.clientHeight * z, el.scrollTop * z, len);\n if (!g) { bar.style.display = 'none'; continue; }\n Object.assign(thumb.style, { top: `${g.pos}px`, height: `${g.size}px`, left: '0', width: '100%' });\n const x = right - BAR / 2 - 1;\n if (coveredAlong(el, [[x, top + 2], [x, top + len / 2], [x, bottom - 2]])) bar.style.display = 'none';\n } else {\n const len = right - left;\n Object.assign(bar.style, { left: `${left}px`, top: `${bottom - BAR - 1}px`, width: `${len}px`, height: `${BAR}px` });\n const g = thumbGeometry(el.scrollWidth * z, el.clientWidth * z, el.scrollLeft * z, len);\n if (!g) { bar.style.display = 'none'; continue; }\n Object.assign(thumb.style, { left: `${g.pos}px`, width: `${g.size}px`, top: '0', height: '100%' });\n const y = bottom - BAR / 2 - 1;\n if (coveredAlong(el, [[left + 2, y], [left + len / 2, y], [right - 2, y]])) bar.style.display = 'none';\n }\n }\n };\n\n const setVisible = (el, on) => {\n const rec = managed.get(el);\n if (!rec) return;\n for (const b of [rec.v, rec.h]) if (b) b.bar.classList.toggle('twm-autoscroll-bar--on', on);\n };\n const show = (el) => {\n const rec = record(el);\n clearTimeout(rec.timer);\n place(el);\n setVisible(el, true);\n };\n const hideLater = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n clearTimeout(rec.timer);\n rec.timer = setTimeout(() => {\n if (rec.dragging || rec.onBar || hoverChain.has(el)) return;\n setVisible(el, false);\n }, HIDE_AFTER_MS);\n };\n const drop = (el) => {\n const rec = managed.get(el);\n if (!rec) return;\n clearTimeout(rec.timer);\n rec.v?.bar.remove();\n rec.h?.bar.remove();\n managed.delete(el);\n };\n\n /** The scrollable elements from `target` up to `root`. */\n const scrollChain = (target) => {\n const out = new Set();\n for (let el = target instanceof Element ? target : target?.parentElement; el && el !== doc.documentElement; el = el.parentElement) {\n if (el.closest?.('.twm-autoscroll-layer')) return out;\n if (eligible(el) && (scrollsOn(el, 'y') || scrollsOn(el, 'x'))) out.add(el);\n if (el === root) break;\n }\n return out;\n };\n\n const onOver = (e) => {\n if (e.target?.closest?.('.twm-autoscroll-layer')) return;\n const next = scrollChain(e.target);\n for (const el of hoverChain) if (!next.has(el)) hideLater(el);\n for (const el of next) show(el);\n hoverChain = next;\n };\n const onLeaveWindow = (e) => {\n if (e.relatedTarget) return;\n for (const el of hoverChain) hideLater(el);\n hoverChain = new Set();\n };\n const onScroll = (e) => {\n const el = e.target === doc ? null : e.target;\n if (el && eligible(el)) { show(el); hideLater(el); }\n // A scrolling ancestor moves every bar inside it.\n for (const other of managed.keys()) if (other !== el) place(other);\n };\n let raf = 0;\n const onResize = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => { for (const el of managed.keys()) place(el); });\n };\n // An element taken out of the page (a managed window closed) takes its\n // bars with it at once. They live in the layer, not in the element, so\n // otherwise they would stay on screen through the hide delay and fade.\n const sweep = new MutationObserver((mutations) => {\n if (!managed.size || !mutations.some((m) => m.removedNodes.length)) return;\n for (const el of [...managed.keys()]) {\n if (!el.isConnected) { drop(el); hoverChain.delete(el); }\n }\n });\n sweep.observe(root, { childList: true, subtree: true });\n\n doc.addEventListener('mouseover', onOver, true);\n doc.addEventListener('mouseout', onLeaveWindow, true);\n doc.addEventListener('scroll', onScroll, true);\n win.addEventListener('resize', onResize);\n // A popover or dialog takes the focus as it opens, often over a bar that\n // is showing because the pointer has not moved: look again once it is drawn.\n doc.addEventListener('focusin', onResize, true);\n\n return {\n dispose() {\n doc.removeEventListener('mouseover', onOver, true);\n doc.removeEventListener('mouseout', onLeaveWindow, true);\n doc.removeEventListener('scroll', onScroll, true);\n win.removeEventListener('resize', onResize);\n doc.removeEventListener('focusin', onResize, true);\n sweep.disconnect();\n for (const el of [...managed.keys()]) drop(el);\n root.classList.remove(ROOT_CLASS);\n },\n };\n}\n", "/**\n * native_context_menu.js \u2014 the browser's own right-click menu, only where it helps.\n *\n * A FlexDesk app draws its own context menus (DataTable rows and headers, tabs,\n * tiles, the top bar). Everywhere else a right-click shows the browser's or the\n * webview's menu: Back, Reload, Save as, Print, Inspect. In a desktop window\n * that makes the app look like a web page and offers moves that break it.\n *\n * This keeps the native menu where it is the useful one, editable text (Paste)\n * and selected text (Copy), and prevents it everywhere nobody else claimed the\n * right-click.\n */\n\n/** Input types that take typed text, where Paste belongs. */\nconst TEXT_INPUTS = new Set(['', 'text', 'search', 'url', 'tel', 'email', 'password', 'number',\n 'date', 'datetime-local', 'month', 'week', 'time']);\n\nfunction isEditable(el) {\n if (!el || el.nodeType !== 1) return false;\n const tag = el.tagName;\n if (tag === 'TEXTAREA' || tag === 'SELECT') return true;\n if (tag === 'INPUT') return TEXT_INPUTS.has(String(el.getAttribute('type') || '').toLowerCase());\n return !!el.closest?.('[contenteditable=\"\"],[contenteditable=\"true\"],[contenteditable=\"plaintext-only\"]');\n}\n\n/** A non-empty selection that the click landed inside. */\nfunction onSelection(target, doc) {\n const sel = doc?.getSelection?.();\n if (!sel || sel.isCollapsed || !String(sel).trim()) return false;\n for (let i = 0; i < sel.rangeCount; i += 1) {\n if (sel.getRangeAt(i).intersectsNode?.(target)) return true;\n }\n return false;\n}\n\n/**\n * Prevent the native context menu wherever no handler claimed the right-click.\n *\n * Listens in the bubble phase, so every element handler runs first: one that\n * shows its own menu calls `preventDefault()`, and this leaves it alone. A\n * handler that stops propagation never reaches here at all.\n *\n * @param {object} [opts]\n * @param {EventTarget} [opts.root=document]\n * @param {(e: MouseEvent) => boolean} [opts.allow] true keeps the native menu for that event\n * @returns {{ dispose: () => void }}\n */\nexport function suppressNativeContextMenu({ root, allow } = {}) {\n const r = root ?? (typeof document !== 'undefined' ? document : null);\n if (!r) return { dispose() {} };\n const onMenu = (e) => {\n if (e.defaultPrevented) return;\n const t = e.target;\n if (isEditable(t)) return;\n if (onSelection(t, t?.ownerDocument)) return;\n if (allow?.(e)) return;\n e.preventDefault();\n };\n r.addEventListener('contextmenu', onMenu);\n return { dispose() { r.removeEventListener('contextmenu', onMenu); } };\n}\n", "/**\n * Overlay scrollbar utilities for the js_new UI stack.\n * Ports the unified hover-only scrollbar system from the legacy UI manager.\n */\n\nimport { createRafResizeObserver } from './raf_resize_observer.js';\n\nfunction normalizeOrientation(value) {\n return String(value || 'horizontal').toLowerCase() === 'vertical' ? 'vertical' : 'horizontal';\n}\n\nfunction ensureInstallState(container) {\n if (!container.__overlayScrollbarInstalled) {\n Object.defineProperty(container, '__overlayScrollbarInstalled', {\n value: {},\n writable: true,\n configurable: true,\n });\n }\n}\n\nexport function installOverlayScrollbar(container, options = {}) {\n if (!container) return null;\n\n const orientation = normalizeOrientation(options.orientation);\n const className = options.className || 'overlay-scrollbar';\n const isHorizontal = orientation !== 'vertical';\n const orientationKey = isHorizontal ? 'horizontal' : 'vertical';\n\n ensureInstallState(container);\n if (container.__overlayScrollbarInstalled[orientationKey]) {\n return container.__overlayScrollbarInstalled[orientationKey];\n }\n\n if (options.setOverflow !== false) {\n container.style.overflow = options.overflow || 'auto';\n }\n if (options.setPosition !== false && getComputedStyle(container).position === 'static') {\n container.style.position = 'relative';\n }\n\n // When externalBar is true, place the bar on the parent element instead of\n // inside the scroll container. This avoids overflow clipping issues in certain\n // flex+overflow layouts (e.g. bottom-tabs-header .tabs).\n const externalBar = !!options.externalBar;\n const barHost = externalBar ? container.parentElement : container;\n if (externalBar && barHost && getComputedStyle(barHost).position === 'static') {\n barHost.style.position = 'relative';\n }\n\n const bar = document.createElement('div');\n bar.className = className;\n bar.classList.add(`overlay-scrollbar-${isHorizontal ? 'h' : 'v'}`);\n const track = document.createElement('div');\n track.className = 'track';\n const thumb = document.createElement('div');\n thumb.className = 'thumb';\n bar.appendChild(track);\n bar.appendChild(thumb);\n (barHost || container).appendChild(bar);\n\n const getScrollProps = () => ({\n scrollSize: isHorizontal ? container.scrollWidth : container.scrollHeight,\n clientSize: isHorizontal ? container.clientWidth : container.clientHeight,\n scrollPos: isHorizontal ? (container.scrollLeft || 0) : (container.scrollTop || 0),\n });\n\n // Dragging and hover state - must be declared early so event handlers can access it\n let dragging = false;\n let hovered = false;\n let startPos = 0;\n let thumbStartPos = 0;\n\n let previousHasOverflow = null;\n let previousClientSize = null;\n let isResettingScroll = false;\n\n const update = () => {\n if (isResettingScroll) return;\n\n const { scrollSize, clientSize, scrollPos } = getScrollProps();\n const scrollLeft = container.scrollLeft || 0;\n const scrollTop = container.scrollTop || 0;\n const maxScroll = scrollSize - clientSize;\n const hasOverflow = maxScroll > 2;\n\n if (previousClientSize !== null && clientSize > previousClientSize && hasOverflow && scrollPos > 0) {\n const delta = clientSize - previousClientSize;\n const targetScroll = Math.max(0, scrollPos - delta);\n if (targetScroll !== scrollPos) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = targetScroll;\n } else {\n container.scrollTop = targetScroll;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousClientSize = clientSize;\n previousHasOverflow = hasOverflow;\n return;\n }\n }\n\n previousClientSize = clientSize;\n\n if (previousHasOverflow === true && !hasOverflow && scrollPos > 0) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = 0;\n } else {\n container.scrollTop = 0;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousHasOverflow = hasOverflow;\n return;\n }\n\n const clampedMaxScroll = Math.max(0, maxScroll);\n if (hasOverflow && scrollPos > clampedMaxScroll) {\n isResettingScroll = true;\n if (isHorizontal) {\n container.scrollLeft = clampedMaxScroll;\n } else {\n container.scrollTop = clampedMaxScroll;\n }\n requestAnimationFrame(() => {\n isResettingScroll = false;\n update();\n });\n previousHasOverflow = hasOverflow;\n return;\n }\n previousHasOverflow = hasOverflow;\n\n container.dataset.scrollable = hasOverflow ? '1' : '0';\n\n // Position the bar at the scroll viewport edge.\n if (externalBar) {\n // Bar lives on the parent element \u2014 position using container's offset.\n // No scroll-offset compensation needed since bar is outside scroll context.\n if (isHorizontal) {\n bar.style.left = `${container.offsetLeft}px`;\n bar.style.bottom = 'auto';\n bar.style.top = `${container.offsetTop + container.offsetHeight - 6}px`;\n bar.style.width = `${container.clientWidth}px`;\n } else {\n bar.style.top = `${container.offsetTop}px`;\n bar.style.right = 'auto';\n bar.style.left = `${container.offsetLeft + container.offsetWidth - 6}px`;\n bar.style.height = `${container.clientHeight}px`;\n }\n } else {\n // Bar lives inside the container \u2014 compensate for scroll offset\n // on BOTH axes so the bar stays pinned to the viewport edge.\n if (isHorizontal) {\n bar.style.left = `${scrollLeft}px`;\n bar.style.top = `${scrollTop + container.clientHeight - bar.offsetHeight}px`;\n bar.style.bottom = 'auto';\n bar.style.width = `${clientSize}px`;\n } else {\n bar.style.top = `${scrollTop}px`;\n bar.style.left = `${scrollLeft + container.clientWidth - bar.offsetWidth}px`;\n bar.style.right = 'auto';\n bar.style.height = `${clientSize}px`;\n }\n }\n\n if (!hasOverflow) {\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n thumb.style[isHorizontal ? 'width' : 'height'] = '0px';\n thumb.style[isHorizontal ? 'left' : 'top'] = '0px';\n return;\n }\n\n // Don't hide while dragging or hovering\n if (!dragging && !hovered) {\n bar.style.opacity = '0'; // hidden until hover\n bar.style.pointerEvents = 'none';\n }\n\n const ratio = clientSize / scrollSize;\n const thumbSize = Math.max(30, Math.floor(ratio * clientSize));\n const maxThumbPos = clientSize - thumbSize;\n const scrollRatio = maxScroll > 0 ? scrollPos / maxScroll : 0;\n const thumbPos = Math.round(maxThumbPos * scrollRatio);\n\n if (isHorizontal) {\n thumb.style.width = `${thumbSize}px`;\n thumb.style.left = `${thumbPos}px`;\n } else {\n thumb.style.height = `${thumbSize}px`;\n thumb.style.top = `${thumbPos}px`;\n }\n };\n\n const onScroll = () => update();\n container.addEventListener('scroll', onScroll, { passive: true });\n \n // Manage hover visibility entirely in JS to avoid CSS specificity issues.\n // Show bar on mouseenter if scrollable, hide on mouseleave.\n const onMouseEnter = () => {\n hovered = true;\n update();\n if (container.dataset.scrollable === '1') {\n bar.style.opacity = '1';\n bar.style.pointerEvents = '';\n }\n };\n const onMouseLeave = () => {\n hovered = false;\n // Don't hide while dragging\n if (dragging) return;\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n };\n container.addEventListener('mouseenter', onMouseEnter, { passive: true });\n container.addEventListener('mouseleave', onMouseLeave, { passive: true });\n // When bar is external (sibling of container), also listen for hover on the bar\n // itself so moving the mouse to the thumb doesn't trigger a hide.\n if (externalBar) {\n bar.addEventListener('mouseenter', onMouseEnter, { passive: true });\n bar.addEventListener('mouseleave', onMouseLeave, { passive: true });\n }\n\n // Also handle focus-within for keyboard accessibility\n container.addEventListener('focusin', onMouseEnter, { passive: true });\n container.addEventListener('focusout', onMouseLeave, { passive: true });\n\n const resizeObserver = createRafResizeObserver(update);\n try { resizeObserver.observe(container); } catch (_) {}\n\n const mo = new MutationObserver(update);\n try { mo.observe(container, { childList: true, subtree: options.watchSubtree !== false }); } catch (_) {}\n\n let resizeTimeout;\n const onWindowResize = () => {\n update();\n clearTimeout(resizeTimeout);\n resizeTimeout = setTimeout(update, 150);\n };\n window.addEventListener('resize', onWindowResize, { passive: true });\n\n const onMouseDown = (e) => {\n dragging = true;\n startPos = isHorizontal ? e.clientX : e.clientY;\n thumbStartPos = parseFloat(thumb.style[isHorizontal ? 'left' : 'top']) || 0;\n // Keep bar visible while dragging\n bar.style.opacity = '1';\n bar.style.pointerEvents = '';\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp, { once: true });\n e.preventDefault();\n e.stopPropagation();\n };\n\n const onMouseMove = (e) => {\n if (!dragging) return;\n e.preventDefault();\n\n const { scrollSize, clientSize } = getScrollProps();\n const maxScroll = scrollSize - clientSize;\n if (maxScroll <= 0) return;\n\n const thumbSize = parseFloat(thumb.style[isHorizontal ? 'width' : 'height']) || 30;\n const maxThumbPos = clientSize - thumbSize;\n\n const delta = (isHorizontal ? e.clientX : e.clientY) - startPos;\n let newThumbPos = thumbStartPos + delta;\n newThumbPos = Math.max(0, Math.min(maxThumbPos, newThumbPos));\n\n const thumbRatio = maxThumbPos > 0 ? newThumbPos / maxThumbPos : 0;\n if (isHorizontal) {\n container.scrollLeft = thumbRatio * maxScroll;\n } else {\n container.scrollTop = thumbRatio * maxScroll;\n }\n };\n\n const onMouseUp = () => {\n dragging = false;\n document.removeEventListener('mousemove', onMouseMove);\n // Check if mouse is still over container - if not, hide the bar\n const rect = container.getBoundingClientRect();\n const isMouseOver = document.elementsFromPoint(\n (rect.left + rect.right) / 2,\n (rect.top + rect.bottom) / 2\n ).includes(container);\n if (!isMouseOver) {\n bar.style.opacity = '0';\n bar.style.pointerEvents = 'none';\n }\n };\n\n thumb.addEventListener('mousedown', onMouseDown);\n\n // Wheel-to-horizontal: convert vertical wheel into horizontal scroll,\n // but only when the container has no vertical overflow (otherwise let\n // the browser handle normal vertical scrolling).\n let onWheel = null;\n if (isHorizontal) {\n onWheel = (e) => {\n const { scrollSize, clientSize } = getScrollProps();\n if (scrollSize <= clientSize) return;\n if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) return;\n // If the container also scrolls vertically, don't hijack the wheel\n if (container.scrollHeight > container.clientHeight) return;\n e.preventDefault();\n container.scrollLeft += e.deltaY;\n };\n container.addEventListener('wheel', onWheel, { passive: false });\n }\n\n requestAnimationFrame(() => {\n requestAnimationFrame(update);\n });\n setTimeout(update, 50);\n\n const cleanup = () => {\n container.removeEventListener('scroll', onScroll);\n container.removeEventListener('mouseenter', onMouseEnter);\n container.removeEventListener('mouseleave', onMouseLeave);\n container.removeEventListener('focusin', onMouseEnter);\n container.removeEventListener('focusout', onMouseLeave);\n if (externalBar) {\n bar.removeEventListener('mouseenter', onMouseEnter);\n bar.removeEventListener('mouseleave', onMouseLeave);\n }\n if (onWheel) container.removeEventListener('wheel', onWheel);\n window.removeEventListener('resize', onWindowResize);\n try { resizeObserver.disconnect(); } catch (_) {}\n try { mo.disconnect(); } catch (_) {}\n bar.remove();\n };\n\n const handle = { update, cleanup, bar, thumb };\n container.__overlayScrollbarInstalled[orientationKey] = handle;\n return handle;\n}\n\nexport function installWorkspaceScrollbars(workspace, options = {}) {\n if (!workspace) return null;\n if (workspace.__workspaceOverlayScrollbarsInstalled) return workspace.__workspaceOverlayScrollbarsUpdate;\n\n installOverlayScrollbar(workspace, {\n orientation: 'vertical',\n className: options.verticalClass || 'panel-scrollbar',\n watchSubtree: options.watchSubtree ?? true,\n });\n installOverlayScrollbar(workspace, {\n orientation: 'horizontal',\n className: options.horizontalClass || 'tabs-scrollbar',\n watchSubtree: options.watchSubtree ?? true,\n });\n\n const update = () => {\n const maxX = Math.max(0, workspace.scrollWidth - workspace.clientWidth);\n const maxY = Math.max(0, workspace.scrollHeight - workspace.clientHeight);\n workspace.dataset.scrollableX = maxX > 1 ? '1' : '0';\n workspace.dataset.scrollableY = maxY > 1 ? '1' : '0';\n };\n\n workspace.__workspaceOverlayScrollbarsInstalled = true;\n workspace.__workspaceOverlayScrollbarsUpdate = update;\n workspace.addEventListener('scroll', update, { passive: true });\n const ro = createRafResizeObserver(update);\n try { ro.observe(workspace); } catch (_) {}\n const mo = new MutationObserver(update);\n try { mo.observe(workspace, { childList: true, subtree: true }); } catch (_) {}\n requestAnimationFrame(update);\n return update;\n}\n\n/**\n * Auto-discover and install vertical overlay scrollbars on\n * `.twm-collapsible-content.visible` elements under `root`. Sections already\n * visible when this is called get a bar at once; a MutationObserver on `root`\n * handles content mounted later (pages mount lazily) and class toggles\n * (expand/collapse). Only class changes under `root` are watched.\n *\n * This used to look up a hard-coded `#twm-fixed-200` that nothing in FlexDesk\n * creates, so the first pass never ran and the observer fell back to the whole\n * document (BUG-0006). The caller names its own root now.\n *\n * Only adds the visual overlay bar \u2014 does NOT change overflow. Elements that are already\n * scrollable via CSS (e.g. accordion `.twm-collapsible-content.visible { overflow-y: auto }`)\n * get the bar; non-scrollable elements get a no-op bar that stays hidden.\n *\n * @param {Element} [root=document.body] The subtree to scan and watch.\n * @returns {Function} disconnect \u2014 stops watching\n */\nexport function installCollapsibleScrollbars(root = document.body) {\n const installOnElement = (el) => {\n installOverlayScrollbar(el, {\n orientation: 'vertical',\n setOverflow: false,\n watchSubtree: true,\n });\n };\n\n if (root.matches?.('.twm-collapsible-content.visible')) installOnElement(root);\n root.querySelectorAll('.twm-collapsible-content.visible').forEach(installOnElement);\n\n // Watch for new elements AND class changes (visible toggled by toggleCategory)\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n // Class change \u2014 check if .twm-collapsible-content just gained .visible\n if (mutation.type === 'attributes' && mutation.attributeName === 'class') {\n const el = mutation.target;\n if (el.classList.contains('twm-collapsible-content') && el.classList.contains('visible')) {\n installOnElement(el);\n }\n continue;\n }\n // New subtrees added (lazy page mount)\n for (const node of mutation.addedNodes) {\n if (node.nodeType !== 1) continue;\n if (node.classList?.contains('twm-collapsible-content') && node.classList?.contains('visible')) {\n installOnElement(node);\n }\n node.querySelectorAll?.('.twm-collapsible-content.visible')?.forEach(installOnElement);\n }\n }\n });\n\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['class'],\n });\n return () => observer.disconnect();\n}\n\n/**\n * Auto-discover and install horizontal overlay scrollbars on tab strips.\n *\n * Uses a MutationObserver so dynamically created tab strips are picked up\n * without per-page manual setup.\n *\n * The selector list used to be hardcoded as `.tabs, .scenario-detail-tabs`, so\n * a generic scrollbar utility carried the name of one EcoAgent page's tab bar.\n * The caller names its own strips now.\n *\n * @param {string[]} [selectors=['.tabs']] Which elements count as a tab strip.\n * @returns {Function} disconnect \u2014 stops watching for new tabs\n */\nexport function installTabsScrollbars(selectors = ['.tabs']) {\n const selector = selectors.join(', ');\n const classes = selectors\n .filter((s) => s.startsWith('.'))\n .map((s) => s.slice(1));\n const installOnElement = (el) => {\n installOverlayScrollbar(el, {\n orientation: 'horizontal',\n className: 'tabs-scrollbar',\n setOverflow: false,\n externalBar: true,\n watchSubtree: true,\n });\n };\n\n const cleanupElement = (el) => {\n el.__overlayScrollbarInstalled?.horizontal?.cleanup?.();\n delete el.__overlayScrollbarInstalled;\n };\n\n const matches = (el) => classes.some((c) => el.classList?.contains(c));\n\n document.querySelectorAll(selector).forEach(installOnElement);\n\n // Watch for dynamically added/removed elements\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (node.nodeType !== 1) continue;\n if (matches(node)) installOnElement(node);\n node.querySelectorAll?.(selector)?.forEach(installOnElement);\n }\n for (const node of mutation.removedNodes) {\n if (node.nodeType !== 1) continue;\n if (matches(node)) cleanupElement(node);\n node.querySelectorAll?.(selector)?.forEach(cleanupElement);\n }\n }\n });\n\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n}\n", "/**\n * scroll_lock.js \u2014 0.6.1. Several scroll boxes that move as one.\n *\n * A side-by-side comparison (two DataTables in two tiles, \"now\" and \"then\") is\n * only readable if row 40 on the left stays beside row 40 on the right. A lock\n * is a GROUP: every box attached to it copies the scroll position of whichever\n * member the person scrolled, on the axes the lock names.\n *\n * const lock = createScrollLock({ axis: 'y' });\n * new DataTable(left, { \u2026, scrollLock: lock });\n * new DataTable(right, { \u2026, scrollLock: lock });\n * lock.setEnabled(false); // the two scroll freely; true locks them again\n *\n * Any element can join with `lock.attach(el)`, which returns its detach. A\n * DataTable given `scrollLock` attaches its own body box on every render and\n * detaches it on the next render and on dispose, so a re-render (a sort, new\n * data) never strands a dead box in the group.\n *\n * THE ECHO. Setting `scrollTop` on a member fires that member's own `scroll`\n * event a frame later, and a naive group would then copy it back to the first\n * box, which by then may have moved on \u2014 the two fight and the wheel stutters.\n * So a position this lock WROTE is remembered per box, and the scroll event that\n * reports exactly that position is the echo and is ignored.\n *\n * A box that joins is moved to the group's last position, so a pane opened\n * beside a scrolled one starts level with it. Positions are copied as pixels:\n * the lock aligns rows only when the members draw rows of the same height,\n * which is the comparison's own contract (both sides drawn from one aligned\n * row list, a gap row where a side has none).\n */\n\n/**\n * @param {object} [options]\n * @param {'x'|'y'|'both'} [options.axis='y'] which positions are copied\n * @param {boolean} [options.enabled=true]\n */\nexport function createScrollLock({ axis = 'y', enabled = true } = {}) {\n const doY = axis === 'y' || axis === 'both';\n const doX = axis === 'x' || axis === 'both';\n const members = new Map(); // element -> { wrote: {top, left} | null, off }\n let last = { top: 0, left: 0 };\n let on = !!enabled;\n\n function copyFrom(source) {\n last = { top: source.scrollTop, left: source.scrollLeft };\n if (!on) return;\n for (const [el, state] of members) {\n if (el === source) continue;\n const top = doY ? last.top : el.scrollTop;\n const left = doX ? last.left : el.scrollLeft;\n if (el.scrollTop === top && el.scrollLeft === left) continue;\n state.wrote = { top, left };\n if (doY) el.scrollTop = top;\n if (doX) el.scrollLeft = left;\n }\n }\n\n function onScroll(event) {\n const el = event.currentTarget;\n const state = members.get(el);\n if (!state) return;\n const wrote = state.wrote;\n state.wrote = null;\n // THE ECHO of a position this lock set: not a person scrolling.\n if (wrote && Math.abs(el.scrollTop - wrote.top) < 1\n && Math.abs(el.scrollLeft - wrote.left) < 1) return;\n copyFrom(el);\n }\n\n const lock = {\n /** Join the group. Returns the function that leaves it. */\n attach(el) {\n if (!el || typeof el.addEventListener !== 'function') return () => {};\n if (members.has(el)) return () => lock.detach(el);\n const state = { wrote: null };\n members.set(el, state);\n el.addEventListener('scroll', onScroll, { passive: true });\n if (on && (last.top || last.left)) {\n state.wrote = { top: doY ? last.top : el.scrollTop,\n left: doX ? last.left : el.scrollLeft };\n if (doY) el.scrollTop = last.top;\n if (doX) el.scrollLeft = last.left;\n }\n return () => lock.detach(el);\n },\n detach(el) {\n if (!members.has(el)) return;\n members.delete(el);\n el.removeEventListener('scroll', onScroll);\n },\n /** Lock (true) or let the members scroll freely (false). Locking again\n * brings every member level with the one scrolled last. */\n setEnabled(value) {\n const was = on;\n on = !!value;\n if (on && !was) {\n const source = [...members.keys()].find(\n (el) => el.scrollTop === last.top && el.scrollLeft === last.left)\n || members.keys().next().value;\n if (source) copyFrom(source);\n }\n },\n get enabled() { return on; },\n /** How many boxes are in the group (for a consumer's own checks). */\n get size() { return members.size; },\n dispose() {\n for (const el of [...members.keys()]) lock.detach(el);\n },\n };\n return lock;\n}\n", "/**\n * tooltip_service.js\n *\n * JS-driven tooltip system for elements with `has-tooltip` class and `data-tooltip` attribute.\n * Also supports LaTeX tooltips with `has-latex-tooltip` and `data-latex-tooltip`.\n *\n * This replaces CSS-based ::after pseudo-element tooltips for better stacking context\n * and dynamic content support.\n */\n\nlet tooltipElement = null;\nlet currentTarget = null;\nlet listenersAttached = false;\nlet mouseCheckInterval = null;\nlet lastMousePosition = { x: 0, y: 0 };\n/** The target keyboard focus is showing a tooltip for: no pointer holds it up. */\nlet focusTarget = null;\n/** The last press was a key. Focus that follows a pointer's, or a script's after one, shows nothing. */\nlet byKeyboard = false;\n\n/**\n * Create or get the tooltip DOM element.\n * @returns {HTMLElement}\n */\nfunction createTooltipElement() {\n if (tooltipElement) return tooltipElement;\n\n tooltipElement = document.createElement('div');\n tooltipElement.className = 'twm-latex-tooltip';\n document.body.appendChild(tooltipElement);\n return tooltipElement;\n}\n\n/**\n * Position the tooltip relative to target element with smart auto-positioning.\n * Automatically flips placement if tooltip would extend outside viewport.\n * @param {HTMLElement} target - Element to position near\n * @param {HTMLElement} tooltip - Tooltip element\n */\nfunction positionTooltip(target, tooltip) {\n const rect = target.getBoundingClientRect();\n const tooltipRect = tooltip.getBoundingClientRect();\n const gap = 12;\n const margin = 10; // Minimum distance from viewport edge\n\n // Get requested placement from data attributes or context\n const requestedPlacement = (target.dataset?.tooltipPlacement || target.getAttribute('data-tooltip-placement') || '').toLowerCase() ||\n (target.dataset?.latexPlacement || target.getAttribute('data-latex-placement') || '').toLowerCase() ||\n (target.closest('.twm-global-top-bar') ? 'bottom' : (target.closest('.twm-fl-bar') ? 'right' : 'top'));\n\n // Auto-positioning: determine best placement based on available space\n let placement = requestedPlacement || 'top';\n\n // Check if explicit placement is set (not auto)\n const isExplicitPlacement = target.hasAttribute('data-tooltip-placement') ||\n target.hasAttribute('data-latex-placement');\n\n if (!isExplicitPlacement) {\n // Calculate available space in each direction\n const spaceAbove = rect.top - margin;\n const spaceBelow = window.innerHeight - rect.bottom - margin;\n const spaceLeft = rect.left - margin;\n const spaceRight = window.innerWidth - rect.right - margin;\n\n // Auto-select placement based on available space\n if (placement === 'top' && tooltipRect.height > spaceAbove && spaceBelow > spaceAbove) {\n placement = 'bottom';\n } else if (placement === 'bottom' && tooltipRect.height > spaceBelow && spaceAbove > spaceBelow) {\n placement = 'top';\n } else if (placement === 'left' && tooltipRect.width > spaceLeft && spaceRight > spaceLeft) {\n placement = 'right';\n } else if (placement === 'right' && tooltipRect.width > spaceRight && spaceLeft > spaceRight) {\n placement = 'left';\n }\n }\n\n // Calculate position based on final placement\n let left, top;\n\n if (placement === 'top') {\n left = rect.left + (rect.width / 2) - (tooltipRect.width / 2);\n top = rect.top - tooltipRect.height - gap;\n } else if (placement === 'bottom') {\n left = rect.left + (rect.width / 2) - (tooltipRect.width / 2);\n top = rect.bottom + gap;\n } else if (placement === 'left') {\n left = rect.left - tooltipRect.width - gap;\n top = rect.top + (rect.height / 2) - (tooltipRect.height / 2);\n } else if (placement === 'right') {\n left = rect.right + gap;\n top = rect.top + (rect.height / 2) - (tooltipRect.height / 2);\n }\n\n // Clamp to viewport\n const clampedLeft = Math.max(margin, Math.min(left, window.innerWidth - tooltipRect.width - margin));\n const clampedTop = Math.max(margin, Math.min(top, window.innerHeight - tooltipRect.height - margin));\n\n tooltip.style.left = `${clampedLeft}px`;\n tooltip.style.top = `${clampedTop}px`;\n\n // Calculate notch/arrow offset to point toward the target element center\n const targetCenterX = rect.left + rect.width / 2;\n const targetCenterY = rect.top + rect.height / 2;\n let notchOffset = 0;\n\n if (placement === 'top' || placement === 'bottom') {\n // Horizontal offset for notch\n const tooltipCenterX = clampedLeft + tooltipRect.width / 2;\n notchOffset = targetCenterX - tooltipCenterX;\n // Clamp notch offset to stay within tooltip bounds\n const maxOffset = (tooltipRect.width / 2) - 16; // 16px from edge minimum\n notchOffset = Math.max(-maxOffset, Math.min(notchOffset, maxOffset));\n } else {\n // Vertical offset for notch\n const tooltipCenterY = clampedTop + tooltipRect.height / 2;\n notchOffset = targetCenterY - tooltipCenterY;\n // Clamp notch offset\n const maxOffset = (tooltipRect.height / 2) - 16;\n notchOffset = Math.max(-maxOffset, Math.min(notchOffset, maxOffset));\n }\n\n // Set placement and notch offset attributes for CSS styling\n const setAttributes = () => {\n tooltip.setAttribute('data-placement', placement);\n tooltip.style.setProperty('--notch-offset', `${notchOffset}px`);\n };\n\n const guard = window.stateGuard;\n if (guard?.executeWithBypass) {\n guard.executeWithBypass('latex-tooltip:set-placement', setAttributes);\n } else {\n setAttributes();\n }\n}\n\n/**\n * Show tooltip for a target element.\n * @param {HTMLElement} target - Element with tooltip data\n */\nfunction showTooltip(target) {\n if (!target || !target.getAttribute) return;\n\n const hasLatex = target.classList && target.classList.contains('has-latex-tooltip');\n const hasPlain = target.classList && target.classList.contains('twm-has-tooltip');\n\n if (!hasLatex && !hasPlain) return;\n if (!target.getAttribute(hasLatex ? 'data-latex-tooltip' : 'data-tooltip')) return;\n\n stopMouseCheck();\n currentTarget = target;\n const tooltip = createTooltipElement();\n\n if (hasLatex) {\n // Render LaTeX using KaTeX\n const latex = target.getAttribute('data-latex-tooltip');\n\n try {\n if (typeof katex !== 'undefined') {\n katex.render(latex, tooltip, {\n displayMode: true,\n throwOnError: false,\n trust: false\n });\n } else {\n tooltip.textContent = latex;\n }\n } catch (err) {\n window.logger?.error('nodes', 'KaTeX rendering error:', err);\n tooltip.textContent = latex;\n }\n } else if (hasPlain) {\n // Plain text tooltip with line breaks preserved\n const text = target.getAttribute('data-tooltip');\n\n // Replace &#10; with actual line breaks, preserve formatting\n const formattedText = text.replace(/&#10;/g, '\\n');\n const lines = formattedText.split('\\n');\n\n tooltip.innerHTML = '';\n lines.forEach((line, index) => {\n if (index === 0) {\n // First line is bold header\n const header = document.createElement('strong');\n header.textContent = line;\n tooltip.appendChild(header);\n } else {\n // Add line break and text\n tooltip.appendChild(document.createElement('br'));\n const textNode = document.createTextNode(line);\n tooltip.appendChild(textNode);\n }\n });\n }\n\n // Optional per-target width override (for long plain-text content like\n // widget documentation). Set data-tooltip-max-width on the target with a\n // CSS length (e.g. \"420px\"). Reset between shows so sticky values don't\n // leak across unrelated targets.\n const widthOverride = target.getAttribute('data-tooltip-max-width');\n tooltip.style.maxWidth = widthOverride || '';\n\n // Position and show\n requestAnimationFrame(() => {\n // Gone in the frame's wait: focus passing through, or the pointer leaving.\n if (currentTarget !== target) return;\n positionTooltip(target, tooltip);\n tooltip.classList.add('visible');\n\n // Start mouse position check for auto-hide, unless focus is what holds it.\n if (focusTarget !== target) startMouseCheck();\n });\n}\n\n/**\n * Hide the tooltip and clean up.\n */\nfunction hideTooltip() {\n if (tooltipElement) {\n tooltipElement.classList.remove('visible');\n }\n currentTarget = null;\n focusTarget = null;\n stopMouseCheck();\n}\n\nfunction stopMouseCheck() {\n if (mouseCheckInterval) {\n clearInterval(mouseCheckInterval);\n mouseCheckInterval = null;\n }\n}\n\n/**\n * The pointer has gone from what it showed, or a scroll took that away. What focus\n * holds is not the pointer's to hide: it stays, or comes back from under the\n * pointer's, as long as its target is in sight.\n */\nfunction pointerGone() {\n const held = focusTarget;\n if (held && held === currentTarget) return;\n hideTooltip();\n if (!held) return;\n focusTarget = held;\n showTooltip(held);\n requestAnimationFrame(() => {\n if (held === focusTarget && held === currentTarget) followFocus();\n });\n}\n\n/**\n * A scroll while focus holds the tooltip, the one the focus itself caused included:\n * the tooltip goes with its target, and waits while the target is out of sight.\n */\nfunction followFocus() {\n const { left, top, width, height } = focusTarget.getBoundingClientRect();\n const inSight = focusTarget.contains(document.elementFromPoint(left + width / 2, top + height / 2));\n tooltipElement.classList.toggle('visible', inSight);\n if (inSight) positionTooltip(focusTarget, tooltipElement);\n}\n\n/**\n * Start the mouse position check interval.\n * Hides tooltip if mouse is no longer over the target element.\n */\nfunction startMouseCheck() {\n stopMouseCheck();\n\n // Check every 3 seconds if mouse is still on the target element\n mouseCheckInterval = setInterval(() => {\n if (!currentTarget) {\n clearInterval(mouseCheckInterval);\n mouseCheckInterval = null;\n return;\n }\n\n // Get element under the last known mouse position\n const elementUnderMouse = document.elementFromPoint(lastMousePosition.x, lastMousePosition.y);\n\n // Check if the element under mouse is the target or a child of it\n if (elementUnderMouse) {\n const isStillOnTarget = elementUnderMouse === currentTarget ||\n currentTarget.contains(elementUnderMouse) ||\n elementUnderMouse.closest('.twm-has-tooltip, .has-latex-tooltip') === currentTarget;\n\n if (!isStillOnTarget) {\n pointerGone();\n }\n } else {\n // Mouse is outside the document\n pointerGone();\n }\n }, 3000);\n}\n\n/**\n * Attach global event listeners for tooltips.\n */\nfunction attachListeners() {\n if (listenersAttached) return;\n listenersAttached = true;\n\n // Remove all title attributes from elements with custom tooltips\n document.querySelectorAll('.twm-has-tooltip, .has-latex-tooltip').forEach(el => {\n el.removeAttribute('title');\n });\n\n // Track mouse position for the 3-second auto-hide check\n document.addEventListener('mousemove', (event) => {\n lastMousePosition.x = event.clientX;\n lastMousePosition.y = event.clientY;\n }, { passive: true });\n\n document.addEventListener('mouseenter', (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const tooltipTarget = target.closest('.has-latex-tooltip, .twm-has-tooltip');\n if (!tooltipTarget) return;\n showTooltip(tooltipTarget);\n }, true);\n\n document.addEventListener('mouseleave', (event) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const tooltipTarget = target.closest('.has-latex-tooltip, .twm-has-tooltip');\n if (!tooltipTarget) return;\n pointerGone();\n }, true);\n\n // On the window, ahead of a chord handler that stops the event. A chord is not\n // a person walking the page by keyboard: it says nothing either way.\n window.addEventListener('keydown', (event) => {\n if (!event.ctrlKey && !event.metaKey && !event.altKey) byKeyboard = true;\n }, true);\n window.addEventListener('pointerdown', () => {\n byKeyboard = false;\n }, true);\n\n // Keyboard focus shows what hovering shows. The focus a click leaves, or that\n // its handler moves into a field, would keep a tooltip standing after the pointer\n // has gone. `:focus-visible` cannot tell: it is true for any text field.\n document.addEventListener('focusin', (event) => {\n const target = event.target;\n if (!(target instanceof Element) || !byKeyboard) return;\n const tooltipTarget = target.closest('.has-latex-tooltip, .twm-has-tooltip');\n if (!tooltipTarget) return;\n focusTarget = tooltipTarget;\n showTooltip(tooltipTarget);\n }, true);\n\n document.addEventListener('focusout', (event) => {\n if (!focusTarget) return;\n const next = event.relatedTarget;\n if (next instanceof Node && focusTarget.contains(next)) return;\n // A pointer's tooltip on another target is the pointer's to take down.\n if (focusTarget === currentTarget) hideTooltip();\n else focusTarget = null;\n }, true);\n\n // Hide on scroll, unless focus is what holds it.\n document.addEventListener('scroll', () => {\n if (focusTarget && focusTarget === currentTarget) followFocus();\n else pointerGone();\n }, true);\n\n // ESC key hides all tooltips application-wide (does not stop propagation)\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') {\n hideTooltip();\n // Note: We intentionally do NOT call event.stopPropagation()\n // so other listeners can also respond to ESC\n }\n }, true);\n}\n\n/**\n * Initialize the tooltip system.\n */\nfunction initializeTooltips() {\n // Wait for KaTeX to load (optional, for latex tooltips)\n const initInterval = setInterval(() => {\n if (typeof katex !== 'undefined') {\n clearInterval(initInterval);\n if (!listenersAttached) {\n attachListeners();\n }\n }\n }, 100);\n\n // Timeout after 2 seconds - attach listeners anyway for plain tooltips\n setTimeout(() => {\n clearInterval(initInterval);\n if (!listenersAttached) {\n attachListeners();\n }\n }, 2000);\n}\n\n/**\n * Set a tooltip on an element programmatically.\n * @param {HTMLElement} element - Target element\n * @param {string} text - Tooltip text\n * @param {boolean} [isLatex=false] - Whether to render as LaTeX\n */\nfunction setTooltip(element, text, isLatex = false) {\n if (!element || !text) return;\n\n // Remove any existing title attribute\n element.removeAttribute('title');\n\n if (isLatex) {\n element.classList.add('has-latex-tooltip');\n element.classList.remove('twm-has-tooltip');\n element.setAttribute('data-latex-tooltip', text);\n } else {\n element.classList.add('twm-has-tooltip');\n element.classList.remove('has-latex-tooltip');\n element.setAttribute('data-tooltip', text);\n }\n}\n\n/**\n * Refresh tooltips for dynamically added content.\n * Removes title attributes that might cause native tooltips.\n * @param {HTMLElement} [container=document] - Container to search within\n */\nfunction refreshTooltips(container = document) {\n container.querySelectorAll('.twm-has-tooltip, .has-latex-tooltip').forEach(el => {\n el.removeAttribute('title');\n });\n}\n\n// ES module exports \u2014 the real interface.\nexport const TooltipService = {\n show: showTooltip,\n hide: hideTooltip,\n set: setTooltip,\n refresh: refreshTooltips,\n init: initializeTooltips\n};\n\nexport default TooltipService;\n\n// Everything below is a side effect of IMPORTING this file, and it is guarded.\n//\n// Unguarded, it touched `document` and `window` at module scope, which made\n// @flexdesk/widgets throw `ReferenceError: window is not defined` the moment anything\n// imported it outside a browser. The DOM check is not defensive programming; it\n// is the difference between a module and a script.\n//\n// `window.LatexTooltip` stays, because unlike `window.InlineRenamer` it is real:\n// roughly 25 call sites read it, all as `window.LatexTooltip?.set(...)`, and one\n// of them is INSIDE the library (window_chrome_controller.js). That last one is a\n// hidden dependency on a global and should import TooltipService instead \u2014 a small\n// piece of P6 cleanup, noted rather than smuggled in here.\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeTooltips);\n } else {\n initializeTooltips();\n }\n}\n\nif (typeof window !== 'undefined') {\n window.LatexTooltip = TooltipService;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["icon", "el", "icon", "day", "list", "el", "node", "arr", "options", "_seq", "first", "text", "low", "icon", "el", "icon", "el", "icon", "button", "glyph", "first", "icon", "el", "node", "_kind", "op", "rest", "node", "value", "glyph", "icon", "part", "el", "more", "node", "button", "SEQ", "appendContent", "glyph", "el", "icon", "glyph", "icon", "glyph", "el", "k", "header", "info", "show", "icon", "el", "icon", "node", "icon", "STEP_STATES", "icon", "glyph", "DEFAULT_LABELS", "node", "setText", "button", "icon", "el", "first", "same", "button", "icon", "e", "el", "show", "el", "el", "node", "el", "el"]
7
7
  }