@framesquared/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/panel/Panel.ts","../src/ZIndexManager.ts","../src/window/Window.ts","../src/window/MessageBox.ts","../src/button/Button.ts","../src/button/SplitButton.ts","../src/button/CycleButton.ts","../src/button/SegmentedButton.ts","../src/toolbar/Toolbar.ts","../src/toolbar/Paging.ts","../src/menu/Menu.ts","../src/menu/MenuManager.ts","../src/menu/MenuItem.ts","../src/menu/CheckItem.ts","../src/menu/Separator.ts","../src/tip/Tooltip.ts","../src/tip/QuickTip.ts","../src/view/DataView.ts","../src/view/ListView.ts","../src/tab/TabBar.ts","../src/tab/Tab.ts","../src/tab/TabPanel.ts","../src/container/Viewport.ts","../src/container/Accordion.ts","../src/container/CardContainer.ts","../src/navigation/Breadcrumb.ts","../../data/src/Model.ts","../../data/src/field/Field.ts","../../data/src/association/Association.ts","../../data/src/association/HasOne.ts","../../data/src/association/HasMany.ts","../../data/src/association/BelongsTo.ts","../../data/src/association/ManyToMany.ts","../../data/src/Schema.ts","../../data/src/ModelCollection.ts","../../data/src/validators.ts","../../data/src/store/Store.ts","../../data/src/store/Collection.ts","../../data/src/ResultSet.ts","../../data/src/reader/Reader.ts","../../data/src/writer/Writer.ts","../../data/src/proxy/Proxy.ts","../../data/src/proxy/ClientProxy.ts","../../data/src/proxy/ServerProxy.ts","../../data/src/store/TreeStore.ts","../../data/src/mixin/NodeInterface.ts","../../data/src/model/TreeModel.ts","../../data/src/reader/TreeReader.ts","../../data/src/writer/TreeWriter.ts","../../data/src/store/BufferedStore.ts","../../data/src/proxy/GraphQLProxy.ts","../../data/src/proxy/WebSocketProxy.ts","../../data/src/proxy/BatchProxy.ts","../../data/src/data/Connection.ts","../../data/src/data/Session.ts","../src/treegrid/TreeGridColumn.ts","../src/treegrid/TreeGridView.ts","../src/treegrid/TreeGridSelectionModel.ts","../src/treegrid/TreeGrid.ts","../src/treegrid/TreeGridDragDrop.ts","../src/treegrid/TreeGridCellEditing.ts","../src/treegrid/TreeGridRowEditing.ts","../src/treegrid/TreeGridClipboard.ts","../src/treegrid/TreeGridSummary.ts","../src/treegrid/TreeGridGroupingSummary.ts","../src/treegrid/TreeGridRowExpander.ts","../src/treegrid/TreeGridFilterPlugin.ts","../src/treegrid/TreeGridStateMixin.ts","../src/treegrid/TreeGridLockable.ts","../src/treegrid/TreeGridExporter.ts","../src/tree/TreeColumn.ts","../src/tree/TreeView.ts","../src/selection/TreeSelectionModel.ts","../src/tree/TreePanel.ts","../src/tree/CheckboxModel.ts","../src/tree/TreeDragZone.ts","../src/tree/TreeDropZone.ts","../src/tree/TreeViewDragDrop.ts","../src/tree/CellEditingPlugin.ts"],"sourcesContent":["/**\n * @framesquared/ui – Panel\n *\n * The primary container with header, body, tools, and docking.\n * Panel extends Container to provide:\n * - Header with title, icon, and tool buttons\n * - Body with custom padding/styling\n * - Optional footer\n * - Docked items (top/bottom/left/right)\n * - Collapsible/expandable behavior\n * - Closable with events\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component, Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ToolConfig {\n type: string;\n handler?: (event: MouseEvent, tool: HTMLElement, panel: Panel) => void;\n hidden?: boolean;\n tooltip?: string;\n}\n\nexport interface PanelConfig extends ContainerConfig {\n title?: string;\n titleAlign?: 'left' | 'center' | 'right';\n iconCls?: string;\n icon?: string;\n header?: boolean;\n footer?: boolean;\n tools?: ToolConfig[];\n collapsible?: boolean;\n collapsed?: boolean;\n collapseDirection?: 'top' | 'bottom' | 'left' | 'right';\n animCollapse?: boolean;\n closable?: boolean;\n bodyPadding?: number | string;\n bodyStyle?: Record<string, string> | string;\n bodyCls?: string;\n frame?: boolean;\n border?: boolean;\n dockedItems?: Component[];\n}\n\n// ---------------------------------------------------------------------------\n// Panel\n// ---------------------------------------------------------------------------\n\nexport class Panel extends Container {\n static override $className = 'Ext.panel.Panel';\n static _titleCounter = 0;\n\n // Internal DOM references\n declare private _headerEl: HTMLElement | null;\n declare private _titleTextEl: HTMLElement | null;\n declare private _titleWrapEl: HTMLElement | null;\n declare private _iconEl: HTMLElement | null;\n declare private _toolsEl: HTMLElement | null;\n declare private _panelBodyEl: HTMLElement | null;\n declare private _footerEl: HTMLElement | null;\n\n // State\n declare private _collapsed: boolean;\n declare private _title: string;\n declare private _iconCls: string;\n declare private _dockedItems: Component[];\n\n constructor(config: PanelConfig = {}) {\n super(config);\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as PanelConfig;\n this._headerEl = null;\n this._titleTextEl = null;\n this._titleWrapEl = null;\n this._iconEl = null;\n this._toolsEl = null;\n this._panelBodyEl = null;\n this._footerEl = null;\n this._collapsed = cfg.collapsed ?? false;\n this._title = cfg.title ?? '';\n this._iconCls = cfg.iconCls ?? '';\n this._dockedItems = [];\n }\n\n protected override afterRender(): void {\n // Skip Container's afterRender — we build our own DOM structure\n // Call Component's afterRender instead\n const cfg = this._config as PanelConfig;\n\n // Root element classes\n this.el!.classList.add('x-panel');\n if (cfg.frame) this.el!.classList.add('x-panel-framed');\n if (cfg.border === false) this.el!.classList.add('x-panel-noborder');\n\n // -- Header --\n const showHeader = this.shouldShowHeader(cfg);\n if (showHeader) {\n this.buildHeader(cfg);\n }\n\n // -- Docked items (top) — before body --\n // Rendered after body is created; see below\n\n // -- Body --\n this._panelBodyEl = document.createElement('div');\n this._panelBodyEl.classList.add('x-panel-body');\n this.applyBodyStyles(cfg);\n this.el!.appendChild(this._panelBodyEl);\n\n // Point Container's body to our panel-body\n (this as any)._bodyEl = this._panelBodyEl;\n\n // -- Footer --\n if (cfg.footer) {\n this._footerEl = document.createElement('div');\n this._footerEl.classList.add('x-panel-footer');\n this.el!.appendChild(this._footerEl);\n }\n\n // -- Auto tools (collapsible / closable) --\n this.addAutoTools(cfg);\n\n // -- Collapsed state --\n if (this._collapsed) {\n this._panelBodyEl.style.display = 'none';\n this.el!.classList.add('x-panel-collapsed');\n }\n\n // -- Render items that were added before render --\n for (const child of (this as any)._items as Component[]) {\n if (!child.rendered) {\n child.render(this._panelBodyEl);\n }\n }\n\n // -- Add initial items from config --\n const items = cfg.items;\n if (items && (items as any[]).length > 0) {\n this.add(...(items as any[]));\n }\n\n // -- Docked items from config --\n if (cfg.dockedItems) {\n for (const docked of cfg.dockedItems) {\n this.addDocked(docked);\n }\n }\n\n // -- ARIA --\n this.el!.setAttribute('role', 'region');\n if (cfg.title) this.el!.setAttribute('aria-label', cfg.title);\n if (cfg.collapsible) {\n this.el!.setAttribute('aria-expanded', String(!this._collapsed));\n }\n }\n\n protected override onDestroy(): void {\n // Destroy docked items\n for (const item of [...this._dockedItems]) {\n item.destroy();\n }\n this._dockedItems.length = 0;\n super.onDestroy();\n }\n\n // -----------------------------------------------------------------------\n // Header construction\n // -----------------------------------------------------------------------\n\n private shouldShowHeader(cfg: PanelConfig): boolean {\n if (cfg.header === false) return false;\n if (cfg.header === true) return true;\n // Show header if there's a title, icon, or tools\n return !!(cfg.title || cfg.iconCls || cfg.icon || cfg.tools?.length || cfg.closable || cfg.collapsible);\n }\n\n private buildHeader(cfg: PanelConfig): void {\n this._headerEl = document.createElement('div');\n this._headerEl.classList.add('x-panel-header');\n\n // Icon\n if (cfg.iconCls || cfg.icon) {\n this._iconEl = document.createElement('span');\n this._iconEl.classList.add('x-panel-header-icon');\n if (cfg.iconCls) this._iconEl.classList.add(cfg.iconCls);\n if (cfg.icon) this._iconEl.style.backgroundImage = `url(${cfg.icon})`;\n this._headerEl.appendChild(this._iconEl);\n }\n\n // Title\n this._titleWrapEl = document.createElement('div');\n this._titleWrapEl.classList.add('x-panel-header-title');\n if (cfg.titleAlign) {\n this._titleWrapEl.style.textAlign = cfg.titleAlign;\n }\n\n this._titleTextEl = document.createElement('span');\n this._titleTextEl.classList.add('x-panel-header-text');\n this._titleTextEl.id = `ext-panel-title-${Panel._titleCounter++}`;\n this._titleTextEl.textContent = this._title;\n this._titleWrapEl.appendChild(this._titleTextEl);\n this._headerEl.appendChild(this._titleWrapEl);\n\n // Tools container\n this._toolsEl = document.createElement('div');\n this._toolsEl.classList.add('x-panel-header-tools');\n this._headerEl.appendChild(this._toolsEl);\n\n // Render configured tools\n if (cfg.tools) {\n for (const tool of cfg.tools) {\n this.renderTool(tool);\n }\n }\n\n this.el!.appendChild(this._headerEl);\n }\n\n private addAutoTools(cfg: PanelConfig): void {\n if (cfg.collapsible && !this.hasToolType('collapse')) {\n this.addTool({\n type: 'collapse',\n handler: () => this.toggleCollapse(),\n });\n }\n if (cfg.closable && !this.hasToolType('close')) {\n this.addTool({\n type: 'close',\n handler: () => this.close(),\n });\n }\n }\n\n private hasToolType(type: string): boolean {\n if (!this._toolsEl) return false;\n return this._toolsEl.querySelector(`.x-tool-${type}`) !== null;\n }\n\n // -----------------------------------------------------------------------\n // Body styling\n // -----------------------------------------------------------------------\n\n private applyBodyStyles(cfg: PanelConfig): void {\n const body = this._panelBodyEl!;\n\n if (cfg.bodyPadding !== undefined) {\n body.style.padding = typeof cfg.bodyPadding === 'number'\n ? `${cfg.bodyPadding}px`\n : cfg.bodyPadding;\n }\n\n if (cfg.bodyStyle) {\n if (typeof cfg.bodyStyle === 'string') {\n body.style.cssText += cfg.bodyStyle;\n } else {\n for (const [prop, val] of Object.entries(cfg.bodyStyle)) {\n (body.style as any)[prop] = val;\n }\n }\n }\n\n if (cfg.bodyCls) {\n body.classList.add(cfg.bodyCls);\n }\n }\n\n // -----------------------------------------------------------------------\n // Title\n // -----------------------------------------------------------------------\n\n setTitle(title: string): void {\n const oldTitle = this._title;\n this._title = title;\n if (this._titleTextEl) {\n this._titleTextEl.textContent = title;\n }\n this.fire('titlechange', this, title, oldTitle);\n }\n\n getTitle(): string {\n return this._title;\n }\n\n // -----------------------------------------------------------------------\n // Icon\n // -----------------------------------------------------------------------\n\n setIconCls(iconCls: string): void {\n const oldCls = this._iconCls;\n if (this._iconEl) {\n if (oldCls) this._iconEl.classList.remove(oldCls);\n this._iconEl.classList.add(iconCls);\n }\n this._iconCls = iconCls;\n this.fire('iconchange', this, iconCls, oldCls);\n }\n\n getIconCls(): string {\n return this._iconCls;\n }\n\n // -----------------------------------------------------------------------\n // Tools\n // -----------------------------------------------------------------------\n\n addTool(tool: ToolConfig): void {\n // Ensure header and tools container exist\n if (!this._headerEl) {\n this.buildHeader(this._config as PanelConfig);\n }\n this.renderTool(tool);\n }\n\n private renderTool(tool: ToolConfig): void {\n if (!this._toolsEl) return;\n\n const toolEl = document.createElement('div');\n toolEl.classList.add('x-tool', `x-tool-${tool.type}`);\n toolEl.setAttribute('role', 'button');\n toolEl.setAttribute('tabindex', '0');\n\n if (tool.tooltip) {\n toolEl.setAttribute('title', tool.tooltip);\n }\n\n if (tool.hidden) {\n toolEl.style.display = 'none';\n }\n\n if (tool.handler) {\n const handler = tool.handler;\n toolEl.addEventListener('click', (e: MouseEvent) => {\n handler(e, toolEl, this);\n });\n }\n\n this._toolsEl.appendChild(toolEl);\n }\n\n // -----------------------------------------------------------------------\n // Collapse / Expand\n // -----------------------------------------------------------------------\n\n collapse(): void {\n if (this._collapsed) return;\n this.fire('beforecollapse', this);\n this._collapsed = true;\n if (this._panelBodyEl) {\n this._panelBodyEl.style.display = 'none';\n }\n this.el?.classList.add('x-panel-collapsed');\n this.fire('collapse', this);\n }\n\n expand(): void {\n if (!this._collapsed) return;\n this.fire('beforeexpand', this);\n this._collapsed = false;\n if (this._panelBodyEl) {\n this._panelBodyEl.style.display = '';\n }\n this.el?.classList.remove('x-panel-collapsed');\n this.fire('expand', this);\n }\n\n toggleCollapse(): void {\n if (this._collapsed) {\n this.expand();\n } else {\n this.collapse();\n }\n }\n\n isCollapsed(): boolean {\n return this._collapsed;\n }\n\n // -----------------------------------------------------------------------\n // Close\n // -----------------------------------------------------------------------\n\n close(): void {\n this.fire('beforeclose', this);\n this.fire('close', this);\n this.destroy();\n }\n\n // -----------------------------------------------------------------------\n // Docked items\n // -----------------------------------------------------------------------\n\n addDocked(item: Component, _pos?: number): void {\n this._dockedItems.push(item);\n\n if (this.rendered && this.el) {\n const dock = (item as any)._config?.dock as string ?? 'top';\n const body = this._panelBodyEl ?? this.el;\n\n if (dock === 'top' || dock === 'left') {\n // Insert before body\n item.render(this.el);\n this.el.insertBefore(item.el!, body);\n } else {\n // Insert after body\n item.render(this.el);\n if (body.nextSibling) {\n this.el.insertBefore(item.el!, body.nextSibling);\n }\n // If no nextSibling, render already appended it\n }\n\n item.el?.classList.add('x-docked', `x-docked-${dock}`);\n }\n\n this.fire('dockedadd', this, item);\n }\n\n removeDocked(item: Component, destroy = false): void {\n const idx = this._dockedItems.indexOf(item);\n if (idx === -1) return;\n\n this._dockedItems.splice(idx, 1);\n\n if (item.el?.parentNode) {\n item.el.parentNode.removeChild(item.el);\n }\n\n this.fire('dockedremove', this, item);\n\n if (destroy) {\n item.destroy();\n }\n }\n\n getDockedItems(_selector?: string): Component[] {\n return [...this._dockedItems];\n }\n}\n","/**\n * @framesquared/ui – ZIndexManager\n *\n * Manages z-index stack for floating components (Windows, menus, etc.).\n * Tracks registration order; bringToFront/sendToBack reorder and\n * reassign z-indices.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Component } from '@framesquared/component';\n\nconst BASE_Z = 9000;\n\nexport class ZIndexManager {\n private static instance: ZIndexManager | null = null;\n\n /** Ordered stack, lowest first, highest last. */\n private stack: Component[] = [];\n\n private constructor() {}\n\n static getInstance(): ZIndexManager {\n if (!ZIndexManager.instance) {\n ZIndexManager.instance = new ZIndexManager();\n }\n return ZIndexManager.instance;\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n register(component: Component): void {\n if (!this.stack.includes(component)) {\n this.stack.push(component);\n this.syncZIndices();\n }\n }\n\n unregister(component: Component): void {\n const idx = this.stack.indexOf(component);\n if (idx !== -1) {\n this.stack.splice(idx, 1);\n this.syncZIndices();\n }\n }\n\n bringToFront(component: Component): void {\n const idx = this.stack.indexOf(component);\n if (idx === -1) return;\n this.stack.splice(idx, 1);\n this.stack.push(component);\n this.syncZIndices();\n\n // Fire activate on the component\n if (typeof (component as any).fireEvent === 'function') {\n (component as any).fireEvent('activate', component);\n }\n }\n\n sendToBack(component: Component): void {\n const idx = this.stack.indexOf(component);\n if (idx === -1) return;\n this.stack.splice(idx, 1);\n this.stack.unshift(component);\n this.syncZIndices();\n }\n\n /** Returns the topmost (active) component. */\n getActive(): Component | undefined {\n return this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined;\n }\n\n /** Iterates from highest z to lowest. */\n eachTopDown(fn: (component: Component) => void): void {\n for (let i = this.stack.length - 1; i >= 0; i--) {\n fn(this.stack[i]);\n }\n }\n\n clear(): void {\n this.stack.length = 0;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private syncZIndices(): void {\n for (let i = 0; i < this.stack.length; i++) {\n const cmp = this.stack[i];\n if (cmp.el) {\n cmp.el.style.zIndex = String(BASE_Z + i * 10);\n }\n }\n }\n}\n","/**\n * @framesquared/ui – Window\n *\n * A floating Panel rendered into document.body. Supports dragging\n * (by header), modal mask, maximize/minimize/restore, constrain to\n * viewport, and z-index management via ZIndexManager.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Panel } from '../panel/Panel.js';\nimport type { PanelConfig } from '../panel/Panel.js';\nimport { ZIndexManager } from '../ZIndexManager.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WindowConfig extends PanelConfig {\n modal?: boolean;\n draggable?: boolean;\n resizable?: boolean;\n constrain?: boolean;\n constrainTo?: Element;\n maximizable?: boolean;\n minimizable?: boolean;\n maximized?: boolean;\n x?: number;\n y?: number;\n defaultFocus?: string;\n closeAction?: 'destroy' | 'hide';\n ghost?: boolean;\n autoShow?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Window\n// ---------------------------------------------------------------------------\n\nexport class Window extends Panel {\n static override $className = 'Ext.window.Window';\n\n // State\n declare private _modal: boolean;\n declare private _maskEl: HTMLElement | null;\n declare private _maximized: boolean;\n declare private _restoreState: { left: string; top: string; width: string; height: string } | null;\n declare private _closeAction: 'destroy' | 'hide';\n declare private _draggable: boolean;\n declare private _dragCleanup: (() => void) | null;\n\n constructor(config: WindowConfig = {}) {\n // Ensure closable by default\n const merged: WindowConfig = {\n closable: true,\n ...config,\n };\n super(merged);\n\n // Auto-show\n if (merged.autoShow !== false && merged.autoShow !== undefined) {\n if (merged.autoShow) this.show();\n }\n }\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as WindowConfig;\n this._modal = cfg.modal ?? false;\n this._maskEl = null;\n this._maximized = false;\n this._restoreState = null;\n this._closeAction = cfg.closeAction ?? 'destroy';\n this._draggable = cfg.draggable ?? true;\n this._dragCleanup = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as WindowConfig;\n\n // Window classes\n this.el!.classList.add('x-window');\n this.el!.style.position = 'fixed';\n\n // Initial position\n if (cfg.x !== undefined) this.el!.style.left = `${cfg.x}px`;\n if (cfg.y !== undefined) this.el!.style.top = `${cfg.y}px`;\n\n // Auto tools\n if (cfg.maximizable) {\n this.addTool({ type: 'maximize', handler: () => this.toggleMaximize() });\n }\n if (cfg.minimizable) {\n this.addTool({ type: 'minimize', handler: () => this.minimize() });\n }\n\n // Dragging\n if (this._draggable) {\n this.setupDrag();\n }\n\n // Modal\n if (this._modal) {\n this.showMask();\n }\n\n // Register with ZIndexManager\n ZIndexManager.getInstance().register(this);\n\n // Maximized config\n if (cfg.maximized) {\n this.maximize();\n }\n\n // ARIA\n this.el!.setAttribute('role', 'dialog');\n if (this._modal) {\n this.el!.setAttribute('aria-modal', 'true');\n }\n // Link to title element via aria-labelledby\n const titleEl = this.el!.querySelector('.x-panel-header-text');\n if (titleEl && titleEl.id) {\n this.el!.setAttribute('aria-labelledby', titleEl.id);\n }\n }\n\n // -----------------------------------------------------------------------\n // Show / render into body\n // -----------------------------------------------------------------------\n\n override show(): void {\n if (!this.rendered) {\n this.render(document.body);\n }\n super.show();\n if (this._modal && !this._maskEl) {\n this.showMask();\n }\n }\n\n // -----------------------------------------------------------------------\n // Close (override Panel)\n // -----------------------------------------------------------------------\n\n override close(): void {\n this.fire('beforeclose', this);\n this.fire('close', this);\n\n if (this._closeAction === 'hide') {\n this.hide();\n this.hideMask();\n } else {\n this.destroy();\n }\n }\n\n // -----------------------------------------------------------------------\n // Modal mask\n // -----------------------------------------------------------------------\n\n private showMask(): void {\n if (this._maskEl) return;\n this._maskEl = document.createElement('div');\n this._maskEl.classList.add('x-mask');\n this._maskEl.style.position = 'fixed';\n this._maskEl.style.top = '0';\n this._maskEl.style.left = '0';\n this._maskEl.style.width = '100%';\n this._maskEl.style.height = '100%';\n this._maskEl.style.zIndex = String(parseInt(this.el?.style.zIndex ?? '9000', 10) - 1);\n document.body.appendChild(this._maskEl);\n }\n\n private hideMask(): void {\n if (this._maskEl && this._maskEl.parentNode) {\n this._maskEl.parentNode.removeChild(this._maskEl);\n }\n this._maskEl = null;\n }\n\n // -----------------------------------------------------------------------\n // Positioning\n // -----------------------------------------------------------------------\n\n center(): void {\n if (!this.el) return;\n const vw = window.innerWidth || 0;\n const vh = window.innerHeight || 0;\n const w = this.el.offsetWidth || 0;\n const h = this.el.offsetHeight || 0;\n this.el.style.left = `${Math.max(0, (vw - w) / 2)}px`;\n this.el.style.top = `${Math.max(0, (vh - h) / 2)}px`;\n }\n\n // -----------------------------------------------------------------------\n // Maximize / Minimize / Restore\n // -----------------------------------------------------------------------\n\n maximize(): void {\n if (this._maximized || !this.el) return;\n\n // Save restore state\n this._restoreState = {\n left: this.el.style.left,\n top: this.el.style.top,\n width: this.el.style.width,\n height: this.el.style.height,\n };\n\n this.el.style.left = '0px';\n this.el.style.top = '0px';\n this.el.style.width = '100%';\n this.el.style.height = '100%';\n this.el.classList.add('x-window-maximized');\n this._maximized = true;\n this.fire('maximize', this);\n }\n\n restore(): void {\n if (!this._maximized || !this.el || !this._restoreState) return;\n\n this.el.style.left = this._restoreState.left;\n this.el.style.top = this._restoreState.top;\n this.el.style.width = this._restoreState.width;\n this.el.style.height = this._restoreState.height;\n this.el.classList.remove('x-window-maximized');\n this._maximized = false;\n this._restoreState = null;\n this.fire('restore', this);\n }\n\n toggleMaximize(): void {\n if (this._maximized) this.restore();\n else this.maximize();\n }\n\n minimize(): void {\n this.hide();\n this.fire('minimize', this);\n }\n\n // -----------------------------------------------------------------------\n // Z-index\n // -----------------------------------------------------------------------\n\n toFront(): void {\n ZIndexManager.getInstance().bringToFront(this);\n }\n\n toBack(): void {\n ZIndexManager.getInstance().sendToBack(this);\n }\n\n // -----------------------------------------------------------------------\n // Drag\n // -----------------------------------------------------------------------\n\n private setupDrag(): void {\n const header = this.el!.querySelector('.x-panel-header') as HTMLElement | null;\n if (!header) return;\n\n header.style.cursor = 'move';\n\n let startX = 0;\n let startY = 0;\n let origLeft = 0;\n let origTop = 0;\n let dragging = false;\n\n const onPointerDown = (e: MouseEvent) => {\n if (this._maximized) return;\n dragging = true;\n startX = e.clientX;\n startY = e.clientY;\n origLeft = parseInt(this.el!.style.left, 10) || 0;\n origTop = parseInt(this.el!.style.top, 10) || 0;\n e.preventDefault();\n };\n\n const onPointerMove = (e: MouseEvent) => {\n if (!dragging) return;\n const dx = e.clientX - startX;\n const dy = e.clientY - startY;\n this.el!.style.left = `${origLeft + dx}px`;\n this.el!.style.top = `${origTop + dy}px`;\n };\n\n const onPointerUp = () => {\n if (!dragging) return;\n dragging = false;\n this.fire('move', this, parseInt(this.el!.style.left, 10), parseInt(this.el!.style.top, 10));\n };\n\n header.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', onPointerUp);\n\n this._dragCleanup = () => {\n header.removeEventListener('pointerdown', onPointerDown);\n document.removeEventListener('pointermove', onPointerMove);\n document.removeEventListener('pointerup', onPointerUp);\n };\n }\n\n // -----------------------------------------------------------------------\n // Destroy\n // -----------------------------------------------------------------------\n\n protected override onDestroy(): void {\n // Remove drag listeners\n if (this._dragCleanup) {\n this._dragCleanup();\n this._dragCleanup = null;\n }\n\n // Remove mask\n this.hideMask();\n\n // Unregister from ZIndexManager\n ZIndexManager.getInstance().unregister(this);\n\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/ui – MessageBox\n *\n * Static utility class for common dialog patterns:\n * MessageBox.alert(title, message, callback?)\n * MessageBox.confirm(title, message, callback?)\n * MessageBox.prompt(title, message, callback?, multiline?)\n * MessageBox.wait(message, title?)\n * MessageBox.show(config)\n *\n * All dialogs are modal Windows that close on button click.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Window } from './Window.js';\nimport type { WindowConfig } from './Window.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MessageBoxConfig {\n title?: string;\n message?: string;\n icon?: 'INFO' | 'WARNING' | 'ERROR' | 'QUESTION';\n buttons?: string[];\n fn?: (buttonId: string, value?: string) => void;\n prompt?: boolean;\n multiline?: boolean;\n progress?: boolean;\n progressText?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Button labels\n// ---------------------------------------------------------------------------\n\nconst BUTTON_LABELS: Record<string, string> = {\n ok: 'OK',\n yes: 'Yes',\n no: 'No',\n cancel: 'Cancel',\n};\n\n// ---------------------------------------------------------------------------\n// MessageBox\n// ---------------------------------------------------------------------------\n\nexport class MessageBox {\n /**\n * Shows an alert dialog with an OK button.\n */\n static alert(\n title: string,\n message: string,\n callback?: (buttonId: string) => void,\n ): Window {\n return MessageBox.show({\n title,\n message,\n buttons: ['ok'],\n fn: callback,\n });\n }\n\n /**\n * Shows a confirmation dialog with Yes and No buttons.\n */\n static confirm(\n title: string,\n message: string,\n callback?: (buttonId: string) => void,\n ): Window {\n return MessageBox.show({\n title,\n message,\n buttons: ['yes', 'no'],\n fn: callback,\n });\n }\n\n /**\n * Shows a prompt dialog with an input field and OK/Cancel buttons.\n */\n static prompt(\n title: string,\n message: string,\n callback?: (buttonId: string, value?: string) => void,\n multiline?: boolean,\n ): Window {\n return MessageBox.show({\n title,\n message,\n buttons: ['ok', 'cancel'],\n prompt: true,\n multiline,\n fn: callback,\n });\n }\n\n /**\n * Shows a wait/progress dialog (no buttons — must be closed programmatically).\n */\n static wait(\n message: string,\n title?: string,\n ): Window {\n return MessageBox.show({\n title: title ?? '',\n message,\n buttons: [],\n progress: true,\n });\n }\n\n /**\n * General-purpose dialog with full config.\n */\n static show(config: MessageBoxConfig): Window {\n const buttons = config.buttons ?? ['ok'];\n\n // Build body HTML\n let bodyHtml = '';\n\n // Icon\n if (config.icon) {\n bodyHtml += `<div class=\"x-msgbox-icon x-msgbox-icon-${config.icon.toLowerCase()}\"></div>`;\n }\n\n // Message text\n bodyHtml += `<div class=\"x-msgbox-text\">${config.message ?? ''}</div>`;\n\n // Input (prompt)\n if (config.prompt) {\n if (config.multiline) {\n bodyHtml += '<textarea class=\"x-msgbox-input\" rows=\"4\"></textarea>';\n } else {\n bodyHtml += '<input class=\"x-msgbox-input\" type=\"text\" />';\n }\n }\n\n // Buttons\n if (buttons.length > 0) {\n bodyHtml += '<div class=\"x-msgbox-buttons\">';\n for (const btn of buttons) {\n const label = BUTTON_LABELS[btn] ?? btn;\n bodyHtml += `<button class=\"x-msgbox-btn x-msgbox-btn-${btn}\" data-btn=\"${btn}\">${label}</button>`;\n }\n bodyHtml += '</div>';\n }\n\n // Create the Window\n const winConfig: WindowConfig = {\n title: config.title ?? '',\n modal: true,\n closable: true,\n draggable: true,\n autoShow: true,\n closeAction: 'destroy',\n cls: 'x-msgbox',\n html: bodyHtml,\n };\n\n const win = new Window(winConfig);\n\n // Attach button click handlers\n if (win.el) {\n const btnEls = win.el.querySelectorAll('.x-msgbox-btn');\n for (const btnEl of btnEls) {\n btnEl.addEventListener('click', () => {\n const btnId = btnEl.getAttribute('data-btn') ?? 'ok';\n\n if (config.fn) {\n if (config.prompt) {\n const inputEl = win.el!.querySelector('.x-msgbox-input') as\n HTMLInputElement | HTMLTextAreaElement | null;\n config.fn(btnId, inputEl?.value);\n } else {\n config.fn(btnId);\n }\n }\n\n win.close();\n });\n }\n }\n\n return win;\n }\n}\n","/**\n * @framesquared/ui – Button\n *\n * A clickable button component with text, icon, toggle, menu arrow,\n * keyboard support, and accessibility. Renders as native &lt;button&gt;\n * (or &lt;a&gt; if href is provided).\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Toggle group registry (module-level singleton)\n// ---------------------------------------------------------------------------\n\nconst toggleGroups = new Map<string, Set<Button>>();\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface ButtonConfig extends ComponentConfig {\n text?: string;\n iconCls?: string;\n iconAlign?: 'left' | 'right' | 'top' | 'bottom';\n icon?: string;\n scale?: 'small' | 'medium' | 'large';\n handler?: (button: Button, event: Event) => void;\n scope?: object;\n pressed?: boolean;\n enableToggle?: boolean;\n toggleGroup?: string;\n menu?: any;\n menuAlign?: string;\n arrowVisible?: boolean;\n tooltip?: string;\n href?: string;\n target?: string;\n textAlign?: 'left' | 'center' | 'right';\n ui?: string;\n value?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Button\n// ---------------------------------------------------------------------------\n\nexport class Button extends Component {\n static override $className = 'Ext.button.Button';\n\n declare protected _pressed: boolean;\n declare protected _scale: string;\n declare protected _iconCls: string;\n declare protected _textEl: HTMLElement | null;\n declare protected _iconEl: HTMLElement | null;\n\n constructor(config: ButtonConfig = {}) {\n super({ xtype: 'button', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as ButtonConfig;\n this._pressed = cfg.pressed ?? false;\n this._scale = cfg.scale ?? 'medium';\n this._iconCls = cfg.iconCls ?? '';\n this._textEl = null;\n this._iconEl = null;\n }\n\n // -----------------------------------------------------------------------\n // Render — override to create <button> or <a> instead of <div>\n // -----------------------------------------------------------------------\n\n override render(container?: Element | string, position?: number | Element): void {\n if (this.rendered || this.isDestroyed) return;\n\n this.fire('beforerender', this);\n this.beforeRender();\n\n const cfg = this._config as ButtonConfig;\n\n // Create element\n if (cfg.href) {\n this.el = document.createElement('a');\n (this.el as HTMLAnchorElement).href = cfg.href;\n if (cfg.target) (this.el as HTMLAnchorElement).target = cfg.target;\n } else {\n this.el = document.createElement('button');\n (this.el as HTMLButtonElement).type = 'button';\n }\n\n this.el.id = this.componentId;\n this.el.classList.add('x-btn', 'x-component');\n\n // Build inner DOM\n this.buildInnerDom(cfg);\n\n // Apply configs\n this.applyButtonConfigs(cfg);\n\n // Insert into DOM\n const target = typeof container === 'string'\n ? document.querySelector(container)\n : container;\n if (target) {\n if (typeof position === 'number') {\n const ref = target.children[position];\n ref ? target.insertBefore(this.el, ref) : target.appendChild(this.el);\n } else if (position instanceof Element) {\n target.insertBefore(this.el, position);\n } else {\n target.appendChild(this.el);\n }\n }\n\n // Attach events\n this.attachEvents(cfg);\n\n this.rendered = true;\n this.fire('render', this);\n this.afterRender();\n this.fire('afterrender', this);\n }\n\n // -----------------------------------------------------------------------\n // DOM construction\n // -----------------------------------------------------------------------\n\n protected buildInnerDom(cfg: ButtonConfig): void {\n const el = this.el!;\n\n // Icon\n if (cfg.iconCls || cfg.icon) {\n this._iconEl = document.createElement('span');\n this._iconEl.classList.add('x-btn-icon');\n if (cfg.iconCls) this._iconEl.classList.add(cfg.iconCls);\n if (cfg.icon) this._iconEl.style.backgroundImage = `url(${cfg.icon})`;\n el.appendChild(this._iconEl);\n }\n\n // Text\n if (cfg.text) {\n this._textEl = document.createElement('span');\n this._textEl.classList.add('x-btn-text');\n this._textEl.textContent = cfg.text;\n el.appendChild(this._textEl);\n }\n\n // Menu arrow\n if (cfg.menu && cfg.arrowVisible !== false) {\n const arrow = document.createElement('span');\n arrow.classList.add('x-btn-arrow');\n el.appendChild(arrow);\n }\n }\n\n protected applyButtonConfigs(cfg: ButtonConfig): void {\n const el = this.el!;\n\n // Scale\n if (cfg.scale) el.classList.add(`x-btn-${cfg.scale}`);\n\n // UI variant\n if (cfg.ui) el.classList.add(`x-btn-${cfg.ui}`);\n\n // Icon alignment\n if (cfg.iconAlign && cfg.iconAlign !== 'left') {\n el.classList.add(`x-btn-icon-${cfg.iconAlign}`);\n }\n\n // Text align\n if (cfg.textAlign) el.style.textAlign = cfg.textAlign;\n\n // Tooltip\n if (cfg.tooltip) el.setAttribute('title', cfg.tooltip);\n\n // Pressed\n if (this._pressed) el.classList.add('x-btn-pressed');\n\n // Disabled\n if (cfg.disabled) {\n el.classList.add('x-btn-disabled');\n if (el.tagName === 'BUTTON') (el as HTMLButtonElement).disabled = true;\n }\n\n // Toggle group registration\n if (cfg.toggleGroup) {\n let group = toggleGroups.get(cfg.toggleGroup);\n if (!group) { group = new Set(); toggleGroups.set(cfg.toggleGroup, group); }\n group.add(this);\n }\n\n // ARIA\n el.setAttribute('role', 'button');\n if (cfg.text) el.setAttribute('aria-label', cfg.text);\n if (cfg.enableToggle || cfg.toggleGroup) {\n el.setAttribute('aria-pressed', String(!!this._pressed));\n }\n if (cfg.menu) {\n el.setAttribute('aria-haspopup', 'true');\n el.setAttribute('aria-expanded', 'false');\n }\n if (cfg.disabled) {\n el.setAttribute('aria-disabled', 'true');\n }\n }\n\n // -----------------------------------------------------------------------\n // Event attachment\n // -----------------------------------------------------------------------\n\n protected attachEvents(_cfg: ButtonConfig): void {\n const el = this.el!;\n\n el.addEventListener('click', (e: MouseEvent) => {\n this.onButtonClick(e);\n });\n\n el.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.onButtonClick(e);\n }\n });\n\n el.addEventListener('mouseover', (e: MouseEvent) => {\n this.fire('mouseover', this, e);\n });\n\n el.addEventListener('mouseout', (e: MouseEvent) => {\n this.fire('mouseout', this, e);\n });\n }\n\n protected onButtonClick(e: Event): void {\n if (this.isDisabled()) return;\n\n const cfg = this._config as ButtonConfig;\n\n // Toggle\n if (cfg.enableToggle || cfg.toggleGroup) {\n if (cfg.toggleGroup) {\n // Radio behavior: if already pressed, keep pressed\n if (!this._pressed) {\n this.depressGroupMembers(cfg.toggleGroup);\n this.toggle(true);\n }\n } else {\n this.toggle(!this._pressed);\n }\n }\n\n // Menu\n if (cfg.menu) {\n const menu = cfg.menu;\n if (menu.isVisible?.()) {\n menu.hide?.();\n this.el?.setAttribute('aria-expanded', 'false');\n } else {\n menu.showBy?.(this);\n this.el?.setAttribute('aria-expanded', 'true');\n }\n }\n\n // Handler\n if (cfg.handler) {\n const scope = cfg.scope ?? this;\n cfg.handler.call(scope, this, e);\n }\n\n this.fire('click', this, e);\n }\n\n private depressGroupMembers(groupName: string): void {\n const group = toggleGroups.get(groupName);\n if (!group) return;\n for (const member of group) {\n if (member !== this && member._pressed) {\n member.toggle(false);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n toggle(state?: boolean): void {\n const newState = state ?? !this._pressed;\n if (newState === this._pressed) return;\n this._pressed = newState;\n if (this.el) {\n this.el.classList.toggle('x-btn-pressed', newState);\n }\n this.fire('toggle', this, newState);\n }\n\n isPressed(): boolean {\n return this._pressed;\n }\n\n setText(text: string): void {\n if (this._textEl) {\n this._textEl.textContent = text;\n } else if (this.el) {\n this._textEl = document.createElement('span');\n this._textEl.classList.add('x-btn-text');\n this._textEl.textContent = text;\n this.el.appendChild(this._textEl);\n }\n }\n\n setIconCls(iconCls: string): void {\n if (this._iconEl) {\n if (this._iconCls) this._iconEl.classList.remove(this._iconCls);\n this._iconEl.classList.add(iconCls);\n }\n this._iconCls = iconCls;\n }\n\n setIcon(icon: string): void {\n if (this._iconEl) {\n this._iconEl.style.backgroundImage = `url(${icon})`;\n }\n }\n\n setTooltip(tooltip: string): void {\n if (this.el) this.el.setAttribute('title', tooltip);\n }\n\n setScale(scale: string): void {\n if (this.el) {\n this.el.classList.remove(`x-btn-${this._scale}`);\n this.el.classList.add(`x-btn-${scale}`);\n }\n this._scale = scale;\n }\n\n getValue(): string {\n return (this._config as ButtonConfig).value ?? '';\n }\n\n // -----------------------------------------------------------------------\n // Destroy\n // -----------------------------------------------------------------------\n\n protected override onDestroy(): void {\n const cfg = this._config as ButtonConfig;\n if (cfg.toggleGroup) {\n const group = toggleGroups.get(cfg.toggleGroup);\n group?.delete(this);\n }\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/ui – SplitButton\n *\n * A button with two click zones: the main button area and a\n * dropdown arrow area. Clicking the arrow fires `arrowHandler`\n * and `'arrowclick'` event independently from the main click.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Button } from './Button.js';\nimport type { ButtonConfig } from './Button.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface SplitButtonConfig extends ButtonConfig {\n arrowHandler?: (button: SplitButton, event: Event) => void;\n}\n\n// ---------------------------------------------------------------------------\n// SplitButton\n// ---------------------------------------------------------------------------\n\nexport class SplitButton extends Button {\n static override $className = 'Ext.button.SplitButton';\n\n declare private _splitArrowEl: HTMLElement | null;\n\n constructor(config: SplitButtonConfig = {}) {\n super({ arrowVisible: false, ...config }); // we render our own arrow\n }\n\n protected override initialize(): void {\n super.initialize();\n this._splitArrowEl = null;\n }\n\n protected override buildInnerDom(cfg: ButtonConfig): void {\n // Build icon + text from parent\n const el = this.el!;\n\n if (cfg.iconCls || cfg.icon) {\n this._iconEl = document.createElement('span');\n this._iconEl.classList.add('x-btn-icon');\n if (cfg.iconCls) this._iconEl.classList.add(cfg.iconCls);\n if (cfg.icon) this._iconEl.style.backgroundImage = `url(${cfg.icon})`;\n el.appendChild(this._iconEl);\n }\n\n if (cfg.text) {\n this._textEl = document.createElement('span');\n this._textEl.classList.add('x-btn-text');\n this._textEl.textContent = cfg.text;\n el.appendChild(this._textEl);\n }\n\n // Split arrow (always present on SplitButton)\n this._splitArrowEl = document.createElement('span');\n this._splitArrowEl.classList.add('x-btn-split-arrow');\n el.appendChild(this._splitArrowEl);\n\n el.classList.add('x-btn-split');\n }\n\n protected override attachEvents(cfg: ButtonConfig): void {\n super.attachEvents(cfg);\n\n const splitCfg = cfg as SplitButtonConfig;\n\n if (this._splitArrowEl) {\n this._splitArrowEl.addEventListener('click', (e: MouseEvent) => {\n e.stopPropagation(); // don't trigger the main click\n if (this.isDisabled()) return;\n\n if (splitCfg.arrowHandler) {\n splitCfg.arrowHandler(this, e);\n }\n this.fire('arrowclick', this, e);\n });\n }\n }\n}\n","/**\n * @framesquared/ui – CycleButton\n *\n * Cycles through a set of items on each click. Extends SplitButton\n * to show the current item's text and advance on click.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { SplitButton } from './SplitButton.js';\nimport type { SplitButtonConfig } from './SplitButton.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CycleItem {\n text: string;\n iconCls?: string;\n checked?: boolean;\n}\n\nexport interface CycleButtonConfig extends SplitButtonConfig {\n items?: CycleItem[];\n}\n\n// ---------------------------------------------------------------------------\n// CycleButton\n// ---------------------------------------------------------------------------\n\nexport class CycleButton extends SplitButton {\n static override $className = 'Ext.button.CycleButton';\n\n declare _cycleItems: CycleItem[];\n declare private _activeIndex: number;\n\n constructor(config: CycleButtonConfig = {}) {\n const items = config.items ?? [];\n const checkedIdx = items.findIndex(i => i.checked);\n const activeIdx = checkedIdx >= 0 ? checkedIdx : 0;\n const activeItem = items[activeIdx];\n\n super({\n ...config,\n text: activeItem?.text ?? '',\n iconCls: activeItem?.iconCls,\n });\n\n // Store after super (which calls initialize)\n this._cycleItems = items;\n this._activeIndex = activeIdx;\n }\n\n protected override initialize(): void {\n super.initialize();\n this._cycleItems = [];\n this._activeIndex = 0;\n }\n\n // Override click to cycle instead of normal button behavior\n protected override onButtonClick(e: Event): void {\n if (this.isDisabled()) return;\n\n // Advance to next item\n this._activeIndex = (this._activeIndex + 1) % this._cycleItems.length;\n const item = this._cycleItems[this._activeIndex];\n\n this.setText(item.text);\n if (item.iconCls) this.setIconCls(item.iconCls);\n\n this.fire('change', this, item);\n this.fire('click', this, e);\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n getActiveItem(): CycleItem {\n return this._cycleItems[this._activeIndex];\n }\n\n setActiveItem(item: CycleItem): void {\n const idx = this._cycleItems.indexOf(item);\n if (idx === -1) return;\n this._activeIndex = idx;\n this.setText(item.text);\n if (item.iconCls) this.setIconCls(item.iconCls);\n this.fire('change', this, item);\n }\n}\n","/**\n * @framesquared/ui – SegmentedButton\n *\n * A Container that holds buttons in a group with single or multiple\n * selection behavior. Manages toggle state across child buttons.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\nimport { Button } from './Button.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface SegmentedButtonConfig extends ContainerConfig {\n allowMultiple?: boolean;\n allowDepress?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// SegmentedButton\n// ---------------------------------------------------------------------------\n\nexport class SegmentedButton extends Container {\n static override $className = 'Ext.button.SegmentedButton';\n\n declare private _allowMultiple: boolean;\n declare private _allowDepress: boolean;\n\n constructor(config: SegmentedButtonConfig = {}) {\n super(config);\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as SegmentedButtonConfig;\n this._allowMultiple = cfg.allowMultiple ?? false;\n this._allowDepress = cfg.allowDepress ?? false;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-segmented-btn');\n\n // Attach click interceptors to each button\n this.setupButtonListeners();\n }\n\n // Called when items are added — need to re-setup listeners\n private setupButtonListeners(): void {\n for (const item of this.getItems()) {\n if (item instanceof Button) {\n this.attachSegmentListener(item);\n }\n }\n }\n\n private attachSegmentListener(btn: Button): void {\n if ((btn as any)._segmentAttached) return;\n (btn as any)._segmentAttached = true;\n\n btn.el?.addEventListener('click', () => {\n this.onSegmentClick(btn);\n });\n }\n\n private onSegmentClick(btn: Button): void {\n if (btn.isDisabled()) return;\n\n const wasPressed = btn.isPressed();\n\n if (this._allowMultiple) {\n // Multi-select: just toggle the clicked button\n btn.toggle(!wasPressed);\n } else {\n // Single-select\n if (wasPressed) {\n if (this._allowDepress) {\n btn.toggle(false);\n }\n // else keep pressed — no action\n } else {\n // Depress all others, press this one\n for (const item of this.getItems()) {\n if (item instanceof Button && item !== btn && item.isPressed()) {\n item.toggle(false);\n }\n }\n btn.toggle(true);\n }\n }\n\n this.fire('toggle', this, btn, btn.isPressed());\n this.fire('change', this, this.getValue());\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n getValue(): string | string[] {\n const pressed = this.getItems()\n .filter((item): item is Button => item instanceof Button && item.isPressed())\n .map(b => b.getValue());\n\n if (this._allowMultiple) return pressed;\n return pressed[0] ?? '';\n }\n\n setValue(value: string | string[]): void {\n const values = Array.isArray(value) ? value : [value];\n for (const item of this.getItems()) {\n if (item instanceof Button) {\n const match = values.includes(item.getValue());\n item.toggle(match);\n }\n }\n this.fire('change', this, this.getValue());\n }\n}\n","/**\n * @framesquared/ui – Toolbar\n *\n * A Container that arranges items horizontally (or vertically) with\n * special shorthand items: '->' (fill), '-' (separator), ' ' (spacer),\n * and plain text strings. Uses flexbox layout.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component, Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface ToolbarConfig extends ContainerConfig {\n vertical?: boolean;\n enableOverflow?: boolean;\n defaultButtonUI?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Toolbar\n// ---------------------------------------------------------------------------\n\nexport class Toolbar extends Container {\n static override $className = 'Ext.toolbar.Toolbar';\n\n constructor(config: ToolbarConfig = {}) {\n // Pre-process items: convert string shortcuts to Component instances\n const processed = { ...config };\n if (config.items) {\n processed.items = (config.items as any[]).map((item) => resolveToolbarItem(item));\n }\n super({ xtype: 'toolbar', ...processed });\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as ToolbarConfig;\n const el = this.el!;\n const body = this.getBodyEl();\n\n el.classList.add('x-toolbar');\n el.setAttribute('role', 'toolbar');\n\n // Flex layout\n body.style.display = 'flex';\n body.style.flexDirection = cfg.vertical ? 'column' : 'row';\n body.style.alignItems = 'center';\n body.style.gap = '4px';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Resolve string shortcuts to Component instances\n// ---------------------------------------------------------------------------\n\nfunction resolveToolbarItem(item: any): Component {\n if (item instanceof Component) return item;\n\n if (item === '->') return new ToolbarFill();\n if (item === '-') return new ToolbarSeparator();\n if (item === ' ') return new ToolbarSpacer();\n if (typeof item === 'string') return new ToolbarTextItem({ text: item });\n\n // Config object — return as-is (Container.add will resolve)\n return item;\n}\n\n// ---------------------------------------------------------------------------\n// Special toolbar items\n// ---------------------------------------------------------------------------\n\nexport class ToolbarFill extends Component {\n constructor() { super({}); }\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-toolbar-fill');\n this.el!.style.flexGrow = '1';\n }\n}\n\nexport class ToolbarSeparator extends Component {\n constructor() { super({}); }\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-toolbar-separator');\n }\n}\n\nexport class ToolbarSpacer extends Component {\n constructor() { super({}); }\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-toolbar-spacer');\n this.el!.style.width = '8px';\n }\n}\n\nexport class ToolbarTextItem extends Component {\n constructor(config: { text: string }) {\n super({ html: config.text });\n }\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-toolbar-text');\n }\n}\n","/**\n * @framesquared/ui – PagingToolbar\n *\n * A Toolbar bound to a data Store that provides page navigation:\n * first, prev, page input, \"of N\", next, last, refresh.\n * Optionally displays \"Showing X - Y of Z\".\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Toolbar } from './Toolbar.js';\nimport type { ToolbarConfig } from './Toolbar.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface PagingToolbarConfig extends ToolbarConfig {\n store?: any;\n displayInfo?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// PagingToolbar\n// ---------------------------------------------------------------------------\n\nexport class PagingToolbar extends Toolbar {\n static override $className = 'Ext.toolbar.Paging';\n\n declare private _store: any;\n declare private _displayInfo: boolean;\n declare private _pageInput: HTMLInputElement | null;\n declare private _totalEl: HTMLElement | null;\n declare private _infoEl: HTMLElement | null;\n\n constructor(config: PagingToolbarConfig = {}) {\n super({ xtype: 'pagingtoolbar', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as PagingToolbarConfig;\n this._store = cfg.store ?? null;\n this._displayInfo = cfg.displayInfo ?? false;\n this._pageInput = null;\n this._totalEl = null;\n this._infoEl = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n\n this.el!.classList.add('x-paging-toolbar');\n const body = this.getBodyEl();\n\n // Build paging controls directly into body\n const first = this.createBtn('x-paging-first', '⟨⟨', () => this.moveFirst());\n const prev = this.createBtn('x-paging-prev', '⟨', () => this.movePrevious());\n\n // Page input\n this._pageInput = document.createElement('input');\n this._pageInput.classList.add('x-paging-page');\n this._pageInput.type = 'text';\n this._pageInput.size = 3;\n this._pageInput.value = String(this._store?.currentPage ?? 1);\n this._pageInput.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n const page = parseInt(this._pageInput!.value, 10);\n if (!isNaN(page) && page >= 1 && page <= this.getTotalPages()) {\n this.loadPage(page);\n }\n }\n });\n\n // \"of N\" text\n const ofText = document.createElement('span');\n ofText.classList.add('x-paging-of');\n ofText.textContent = ' of ';\n\n this._totalEl = document.createElement('span');\n this._totalEl.classList.add('x-paging-total');\n this._totalEl.textContent = String(this.getTotalPages());\n\n const next = this.createBtn('x-paging-next', '⟩', () => this.moveNext());\n const last = this.createBtn('x-paging-last', '⟩⟩', () => this.moveLast());\n const refresh = this.createBtn('x-paging-refresh', '↻', () => this.doRefresh());\n\n body.appendChild(first);\n body.appendChild(prev);\n body.appendChild(this._pageInput);\n body.appendChild(ofText);\n body.appendChild(this._totalEl);\n body.appendChild(next);\n body.appendChild(last);\n body.appendChild(refresh);\n\n // Display info\n if (this._displayInfo) {\n this._infoEl = document.createElement('span');\n this._infoEl.classList.add('x-paging-info');\n this._infoEl.style.marginLeft = 'auto';\n this.updateInfo();\n body.appendChild(this._infoEl);\n }\n }\n\n // -----------------------------------------------------------------------\n // Navigation\n // -----------------------------------------------------------------------\n\n private moveFirst(): void { this.loadPage(1); }\n\n private movePrevious(): void {\n const page = Math.max(1, (this._store?.currentPage ?? 1) - 1);\n this.loadPage(page);\n }\n\n private moveNext(): void {\n const page = Math.min(this.getTotalPages(), (this._store?.currentPage ?? 1) + 1);\n this.loadPage(page);\n }\n\n private moveLast(): void { this.loadPage(this.getTotalPages()); }\n\n private doRefresh(): void {\n this.loadPage(this._store?.currentPage ?? 1);\n }\n\n private loadPage(page: number): void {\n this.fire('beforechange', this, page);\n if (this._store?.loadPage) {\n this._store.loadPage(page);\n }\n if (this._pageInput) this._pageInput.value = String(page);\n this.fire('change', this, page);\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private getTotalPages(): number {\n if (!this._store) return 1;\n const total = this._store.getTotalCount?.() ?? this._store.totalCount ?? 0;\n const pageSize = this._store.pageSize ?? 25;\n return Math.max(1, Math.ceil(total / pageSize));\n }\n\n private updateInfo(): void {\n if (!this._infoEl || !this._store) return;\n const page = this._store.currentPage ?? 1;\n const pageSize = this._store.pageSize ?? 25;\n const total = this._store.getTotalCount?.() ?? this._store.totalCount ?? 0;\n const start = (page - 1) * pageSize + 1;\n const end = Math.min(page * pageSize, total);\n this._infoEl.textContent = `Displaying ${start} - ${end} of ${total}`;\n }\n\n private createBtn(cls: string, label: string, handler: () => void): HTMLElement {\n const btn = document.createElement('button');\n btn.classList.add(cls, 'x-paging-btn');\n btn.type = 'button';\n btn.textContent = label;\n btn.addEventListener('click', handler);\n return btn;\n }\n}\n","/**\n * @framesquared/ui – Menu\n *\n * A floating container that holds MenuItems. Shows at a specific\n * position or aligned to a component. Registers with MenuManager\n * for outside-click dismissal. Supports keyboard navigation.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Container } from '@framesquared/component';\nimport type { ContainerConfig, Component } from '@framesquared/component';\nimport { MenuManager } from './MenuManager.js';\n\nexport interface MenuConfig extends ContainerConfig {\n plain?: boolean;\n showSeparator?: boolean;\n allowOtherMenus?: boolean;\n}\n\nexport class Menu extends Container {\n static override $className = 'Ext.menu.Menu';\n\n declare private _isMenuVisible: boolean;\n\n constructor(config: MenuConfig = {}) {\n super({ xtype: 'menu', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n this._isMenuVisible = false;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as MenuConfig;\n const el = this.el!;\n\n el.classList.add('x-menu');\n el.style.position = 'fixed';\n el.setAttribute('role', 'menu');\n\n if (cfg.plain) el.classList.add('x-menu-plain');\n\n // Keyboard\n el.tabIndex = -1;\n el.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.hide();\n }\n });\n }\n\n // -----------------------------------------------------------------------\n // Show / Hide\n // -----------------------------------------------------------------------\n\n showAt(x: number, y: number): void {\n if (!this.rendered) {\n this.render(document.body);\n }\n this.el!.style.left = `${x}px`;\n this.el!.style.top = `${y}px`;\n this.el!.style.display = '';\n this._isMenuVisible = true;\n MenuManager.getInstance().register(this);\n this.fire('show', this);\n }\n\n showBy(component: Component, _alignment?: string): void {\n if (!this.rendered) {\n this.render(document.body);\n }\n // Position near the component\n const rect = component.el?.getBoundingClientRect();\n const x = rect?.left ?? 0;\n const y = (rect?.bottom ?? 0);\n this.showAt(x, y);\n }\n\n override hide(): void {\n if (!this._isMenuVisible) return;\n this._isMenuVisible = false;\n if (this.el) this.el.style.display = 'none';\n MenuManager.getInstance().unregister(this);\n this.fire('hide', this);\n }\n\n override isVisible(): boolean {\n return this._isMenuVisible;\n }\n\n override show(): void {\n this.showAt(0, 0);\n }\n\n protected override onDestroy(): void {\n MenuManager.getInstance().unregister(this);\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/ui – MenuManager\n *\n * Singleton that tracks all open menus and closes them when the\n * user clicks outside of any menu.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport class MenuManager {\n private static instance: MenuManager | null = null;\n private menus: any[] = [];\n private listening = false;\n\n private constructor() {}\n\n static getInstance(): MenuManager {\n if (!MenuManager.instance) {\n MenuManager.instance = new MenuManager();\n }\n return MenuManager.instance;\n }\n\n register(menu: any): void {\n if (!this.menus.includes(menu)) {\n this.menus.push(menu);\n }\n this.startListening();\n }\n\n unregister(menu: any): void {\n const idx = this.menus.indexOf(menu);\n if (idx !== -1) this.menus.splice(idx, 1);\n if (this.menus.length === 0) this.stopListening();\n }\n\n getOpenMenus(): any[] {\n return [...this.menus];\n }\n\n closeAll(): void {\n const snapshot = [...this.menus];\n for (const menu of snapshot) {\n if (typeof menu.hide === 'function') menu.hide();\n }\n this.menus.length = 0;\n this.stopListening();\n }\n\n private onDocumentMouseDown = (e: MouseEvent): void => {\n const snapshot = [...this.menus];\n for (const menu of snapshot) {\n if (menu.el && !menu.el.contains(e.target as Node)) {\n menu.hide();\n }\n }\n };\n\n private startListening(): void {\n if (this.listening) return;\n this.listening = true;\n document.addEventListener('mousedown', this.onDocumentMouseDown);\n }\n\n private stopListening(): void {\n if (!this.listening) return;\n this.listening = false;\n document.removeEventListener('mousedown', this.onDocumentMouseDown);\n }\n}\n","/**\n * @framesquared/ui – MenuItem\n *\n * A clickable item within a Menu. Supports text, icon, handler,\n * sub-menu indicator, href (link), and disabled state.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\nexport interface MenuItemConfig extends ComponentConfig {\n text?: string;\n iconCls?: string;\n handler?: (item: MenuItem, event: Event) => void;\n menu?: any;\n href?: string;\n plain?: boolean;\n}\n\nexport class MenuItem extends Component {\n static override $className = 'Ext.menu.MenuItem';\n\n constructor(config: MenuItemConfig = {}) {\n super({ xtype: 'menuitem', ...config });\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as MenuItemConfig;\n const el = this.el!;\n\n el.classList.add('x-menu-item');\n el.setAttribute('role', 'menuitem');\n\n // Icon\n if (cfg.iconCls) {\n const icon = document.createElement('span');\n icon.classList.add('x-menu-item-icon', cfg.iconCls);\n el.appendChild(icon);\n }\n\n // Text / link\n if (cfg.href) {\n const a = document.createElement('a');\n a.classList.add('x-menu-item-link');\n a.href = cfg.href;\n a.textContent = cfg.text ?? '';\n el.appendChild(a);\n } else if (cfg.text) {\n const text = document.createElement('span');\n text.classList.add('x-menu-item-text');\n text.textContent = cfg.text;\n el.appendChild(text);\n }\n\n // Sub-menu arrow\n if (cfg.menu) {\n const arrow = document.createElement('span');\n arrow.classList.add('x-menu-item-arrow');\n el.appendChild(arrow);\n }\n\n // Click handler\n el.addEventListener('click', (e: MouseEvent) => {\n if (this.isDisabled()) return;\n if (cfg.handler) cfg.handler(this, e);\n this.fire('click', this, e);\n });\n }\n}\n","/**\n * @framesquared/ui – CheckItem\n *\n * A menu item with checkbox behavior. Supports radio groups\n * where only one item in the group can be checked at a time.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// Radio group registry\nconst checkGroups = new Map<string, Set<CheckItem>>();\n\nexport interface CheckItemConfig extends ComponentConfig {\n text?: string;\n iconCls?: string;\n checked?: boolean;\n group?: string;\n handler?: (item: CheckItem, event: Event) => void;\n}\n\nexport class CheckItem extends Component {\n static override $className = 'Ext.menu.CheckItem';\n\n declare private _checked: boolean;\n\n constructor(config: CheckItemConfig = {}) {\n super({ xtype: 'menucheckitem', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as CheckItemConfig;\n this._checked = cfg.checked ?? false;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as CheckItemConfig;\n const el = this.el!;\n\n el.classList.add('x-menu-item', 'x-menu-check-item');\n el.setAttribute('role', 'menuitemcheckbox');\n\n if (cfg.iconCls) {\n const icon = document.createElement('span');\n icon.classList.add('x-menu-item-icon', cfg.iconCls);\n el.appendChild(icon);\n }\n\n // Check indicator\n const check = document.createElement('span');\n check.classList.add('x-menu-item-check');\n el.appendChild(check);\n\n // Text\n if (cfg.text) {\n const text = document.createElement('span');\n text.classList.add('x-menu-item-text');\n text.textContent = cfg.text;\n el.appendChild(text);\n }\n\n if (this._checked) {\n el.classList.add('x-menu-item-checked');\n }\n\n // Group registration\n if (cfg.group) {\n let grp = checkGroups.get(cfg.group);\n if (!grp) { grp = new Set(); checkGroups.set(cfg.group, grp); }\n grp.add(this);\n }\n\n // Click\n el.addEventListener('click', (e: MouseEvent) => {\n if (this.isDisabled()) return;\n if (cfg.group) {\n // Radio: uncheck others, check this\n const grp = checkGroups.get(cfg.group);\n if (grp) {\n for (const member of grp) {\n if (member !== this && member._checked) member.setChecked(false);\n }\n }\n this.setChecked(true);\n } else {\n this.setChecked(!this._checked);\n }\n if (cfg.handler) cfg.handler(this, e);\n this.fire('click', this, e);\n });\n }\n\n isChecked(): boolean {\n return this._checked;\n }\n\n setChecked(checked: boolean): void {\n const old = this._checked;\n this._checked = checked;\n if (this.el) {\n this.el.classList.toggle('x-menu-item-checked', checked);\n }\n if (old !== checked) {\n this.fire('checkchange', this, checked);\n }\n }\n\n protected override onDestroy(): void {\n const cfg = this._config as CheckItemConfig;\n if (cfg.group) checkGroups.get(cfg.group)?.delete(this);\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/ui – MenuSeparator\n * A visual separator line within a Menu.\n */\n\nimport { Component } from '@framesquared/component';\n\nexport class MenuSeparator extends Component {\n static override $className = 'Ext.menu.Separator';\n\n constructor(config: Record<string, unknown> = {}) {\n super({ xtype: 'menuseparator', ...config });\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-menu-separator');\n this.el!.setAttribute('role', 'separator');\n }\n}\n","/**\n * @framesquared/ui – Tooltip\n *\n * A floating tip that appears near a target element on mouseenter.\n * Supports show/hide delays, mouse tracking, anchor positioning,\n * event delegation, dismissDelay, and closable mode.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TooltipConfig extends ComponentConfig {\n target?: Element | string;\n html?: string;\n title?: string;\n anchor?: 'top' | 'bottom' | 'left' | 'right';\n autoHide?: boolean;\n showDelay?: number;\n hideDelay?: number;\n dismissDelay?: number;\n trackMouse?: boolean;\n mouseOffset?: [number, number];\n delegate?: string;\n maxWidth?: number;\n closable?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Tooltip\n// ---------------------------------------------------------------------------\n\nexport class Tooltip extends Component {\n static override $className = 'Ext.tip.Tooltip';\n\n // Config\n declare private _targetEl: Element | null;\n declare private _showDelay: number;\n declare private _hideDelay: number;\n declare private _dismissDelay: number;\n declare private _autoHide: boolean;\n declare private _trackMouse: boolean;\n declare private _mouseOffset: [number, number];\n declare private _delegate: string | null;\n declare private _anchor: string | null;\n declare private _maxWidth: number;\n declare private _closable: boolean;\n declare private _tipTitle: string;\n declare private _tipHtml: string;\n\n // State\n declare private _visible: boolean;\n declare private _showTimer: ReturnType<typeof setTimeout> | null;\n declare private _hideTimer: ReturnType<typeof setTimeout> | null;\n declare private _dismissTimer: ReturnType<typeof setTimeout> | null;\n declare private _lastMouseX: number;\n declare private _lastMouseY: number;\n\n // Listener cleanup\n declare private _cleanupFns: (() => void)[];\n\n constructor(config: TooltipConfig = {}) {\n super({ xtype: 'tooltip', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as TooltipConfig;\n\n this._showDelay = cfg.showDelay ?? 500;\n this._hideDelay = cfg.hideDelay ?? 200;\n this._dismissDelay = cfg.dismissDelay ?? 5000;\n this._autoHide = cfg.autoHide ?? true;\n this._trackMouse = cfg.trackMouse ?? false;\n this._mouseOffset = cfg.mouseOffset ?? [15, 15];\n this._delegate = cfg.delegate ?? null;\n this._anchor = cfg.anchor ?? null;\n this._maxWidth = cfg.maxWidth ?? 0;\n this._closable = cfg.closable ?? false;\n this._tipTitle = cfg.title ?? '';\n this._tipHtml = cfg.html ?? '';\n\n this._visible = false;\n this._showTimer = null;\n this._hideTimer = null;\n this._dismissTimer = null;\n this._lastMouseX = 0;\n this._lastMouseY = 0;\n this._cleanupFns = [];\n\n // Resolve and attach to target\n let targetEl: Element | null = null;\n if (cfg.target) {\n targetEl = typeof cfg.target === 'string'\n ? document.querySelector(cfg.target)\n : cfg.target;\n }\n this._targetEl = targetEl;\n\n if (targetEl) {\n this.attachTargetListeners(targetEl);\n }\n }\n\n // -----------------------------------------------------------------------\n // Target event attachment\n // -----------------------------------------------------------------------\n\n private attachTargetListeners(el: Element): void {\n const onEnter = (e: Event) => this.onTargetEnter(e as MouseEvent);\n const onLeave = (e: Event) => this.onTargetLeave(e as MouseEvent);\n const onMove = (e: Event) => this.onTargetMove(e as MouseEvent);\n\n el.addEventListener('mouseenter', onEnter, true);\n el.addEventListener('mouseleave', onLeave, true);\n if (this._trackMouse) {\n el.addEventListener('mousemove', onMove, true);\n }\n\n this._cleanupFns.push(() => {\n el.removeEventListener('mouseenter', onEnter, true);\n el.removeEventListener('mouseleave', onLeave, true);\n el.removeEventListener('mousemove', onMove, true);\n });\n }\n\n // -----------------------------------------------------------------------\n // Mouse event handlers\n // -----------------------------------------------------------------------\n\n private onTargetEnter(e: MouseEvent): void {\n if (this.isDestroyed) return;\n\n // Delegation: check if the entered element matches delegate selector\n if (this._delegate) {\n const delegateTarget = (e.target as Element)?.closest?.(this._delegate);\n if (!delegateTarget) return;\n // Update content from delegate target's data attributes\n const qtip = delegateTarget.getAttribute('data-qtip');\n if (qtip) this._tipHtml = qtip;\n }\n\n this._lastMouseX = e.clientX;\n this._lastMouseY = e.clientY;\n\n this.clearHideTimer();\n this.clearShowTimer();\n\n this._showTimer = setTimeout(() => {\n this._showTimer = null;\n this.showTip();\n }, this._showDelay);\n }\n\n private onTargetLeave(_e: MouseEvent): void {\n if (this.isDestroyed) return;\n\n this.clearShowTimer();\n\n if (!this._autoHide) return;\n\n this.clearHideTimer();\n this._hideTimer = setTimeout(() => {\n this._hideTimer = null;\n this.hide();\n }, this._hideDelay);\n }\n\n private onTargetMove(e: MouseEvent): void {\n if (this.isDestroyed) return;\n this._lastMouseX = e.clientX;\n this._lastMouseY = e.clientY;\n if (this._visible && this._trackMouse) {\n this.positionAtMouse();\n }\n }\n\n // -----------------------------------------------------------------------\n // Show / Hide\n // -----------------------------------------------------------------------\n\n private showTip(): void {\n if (this.isDestroyed) return;\n\n this.fire('beforeshow', this);\n\n if (!this.rendered) {\n this.renderTip();\n }\n\n // Update content (for delegation)\n this.updateContent();\n\n this.el!.style.display = '';\n this.el!.classList.remove('x-tip-hidden');\n this._visible = true;\n this.positionAtMouse();\n\n this.fire('show', this);\n\n // DismissDelay\n this.clearDismissTimer();\n if (this._dismissDelay > 0) {\n this._dismissTimer = setTimeout(() => {\n this._dismissTimer = null;\n this.hide();\n }, this._dismissDelay);\n }\n }\n\n override hide(): void {\n if (!this._visible) return;\n\n this.fire('beforehide', this);\n\n this._visible = false;\n if (this.el) {\n this.el.classList.add('x-tip-hidden');\n this.el.style.display = 'none';\n }\n this.clearDismissTimer();\n\n this.fire('hide', this);\n }\n\n override isVisible(): boolean {\n return this._visible;\n }\n\n // -----------------------------------------------------------------------\n // Rendering\n // -----------------------------------------------------------------------\n\n private renderTip(): void {\n this.render(document.body);\n\n const el = this.el!;\n el.classList.add('x-tooltip');\n el.setAttribute('role', 'tooltip');\n el.style.position = 'fixed';\n el.style.zIndex = '99999';\n\n if (this._anchor) {\n el.classList.add(`x-tip-anchor-${this._anchor}`);\n }\n\n if (this._maxWidth > 0) {\n el.style.maxWidth = `${this._maxWidth}px`;\n }\n\n this.updateContent();\n }\n\n private updateContent(): void {\n if (!this.el) return;\n const el = this.el;\n\n // Clear previous content\n el.innerHTML = '';\n\n // Close button\n if (this._closable) {\n const closeBtn = document.createElement('div');\n closeBtn.classList.add('x-tip-close');\n closeBtn.textContent = '×';\n closeBtn.addEventListener('click', () => this.hide());\n el.appendChild(closeBtn);\n }\n\n // Header\n if (this._tipTitle) {\n const header = document.createElement('div');\n header.classList.add('x-tip-header');\n header.textContent = this._tipTitle;\n el.appendChild(header);\n }\n\n // Body\n const body = document.createElement('div');\n body.classList.add('x-tip-body');\n body.innerHTML = this._tipHtml;\n el.appendChild(body);\n }\n\n // -----------------------------------------------------------------------\n // Positioning\n // -----------------------------------------------------------------------\n\n private positionAtMouse(): void {\n if (!this.el) return;\n const [offX, offY] = this._mouseOffset;\n this.el.style.left = `${this._lastMouseX + offX}px`;\n this.el.style.top = `${this._lastMouseY + offY}px`;\n }\n\n // -----------------------------------------------------------------------\n // Timer management\n // -----------------------------------------------------------------------\n\n private clearShowTimer(): void {\n if (this._showTimer !== null) {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n }\n }\n\n private clearHideTimer(): void {\n if (this._hideTimer !== null) {\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n }\n }\n\n private clearDismissTimer(): void {\n if (this._dismissTimer !== null) {\n clearTimeout(this._dismissTimer);\n this._dismissTimer = null;\n }\n }\n\n // -----------------------------------------------------------------------\n // Destroy\n // -----------------------------------------------------------------------\n\n override destroy(): void {\n this.clearShowTimer();\n this.clearHideTimer();\n this.clearDismissTimer();\n\n for (const fn of this._cleanupFns) fn();\n this._cleanupFns.length = 0;\n\n this._visible = false;\n super.destroy();\n }\n}\n","/**\n * @framesquared/ui – QuickTip\n *\n * Singleton that auto-creates tooltips from DOM data attributes.\n * Uses event delegation on document.body to monitor mouseenter on\n * elements with `data-qtip`, `data-qtitle`, `data-qwidth`.\n *\n * Usage:\n * QuickTip.init(); // Start monitoring\n * // Any element with data-qtip=\"text\" now gets a tooltip\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// ---------------------------------------------------------------------------\n// QuickTip singleton state\n// ---------------------------------------------------------------------------\n\nlet enabled = false;\nlet initialized = false;\nlet currentTipEl: HTMLElement | null = null;\nlet tipElement: HTMLElement | null = null;\nlet showTimer: ReturnType<typeof setTimeout> | null = null;\nlet hideTimer: ReturnType<typeof setTimeout> | null = null;\n\nconst SHOW_DELAY = 500;\nconst HIDE_DELAY = 200;\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nfunction onMouseOver(e: MouseEvent): void {\n if (!enabled) return;\n\n const target = (e.target as Element)?.closest?.('[data-qtip]') as HTMLElement | null;\n if (!target) return;\n if (target === currentTipEl) return;\n\n // Clear any pending hide\n clearHide();\n clearShow();\n\n currentTipEl = target;\n\n showTimer = setTimeout(() => {\n showTimer = null;\n showQuickTip(target, e);\n }, SHOW_DELAY);\n}\n\nfunction onMouseOut(e: MouseEvent): void {\n if (!enabled) return;\n\n const target = (e.target as Element)?.closest?.('[data-qtip]') as HTMLElement | null;\n if (!target || target !== currentTipEl) return;\n\n clearShow();\n\n hideTimer = setTimeout(() => {\n hideTimer = null;\n hideQuickTip();\n }, HIDE_DELAY);\n}\n\nfunction showQuickTip(target: HTMLElement, _e: MouseEvent): void {\n const text = target.getAttribute('data-qtip') ?? '';\n const title = target.getAttribute('data-qtitle') ?? '';\n const width = target.getAttribute('data-qwidth') ?? '';\n\n // If tipElement was removed from DOM (e.g. between tests), recreate\n if (tipElement && !document.body.contains(tipElement)) {\n tipElement = null;\n }\n\n if (!tipElement) {\n tipElement = document.createElement('div');\n tipElement.classList.add('x-tooltip');\n tipElement.style.position = 'fixed';\n tipElement.style.zIndex = '99999';\n document.body.appendChild(tipElement);\n }\n\n tipElement.innerHTML = '';\n\n if (title) {\n const hdr = document.createElement('div');\n hdr.classList.add('x-tip-header');\n hdr.textContent = title;\n tipElement.appendChild(hdr);\n }\n\n const body = document.createElement('div');\n body.classList.add('x-tip-body');\n body.textContent = text;\n tipElement.appendChild(body);\n\n if (width) {\n tipElement.style.maxWidth = `${width}px`;\n } else {\n tipElement.style.maxWidth = '';\n }\n\n // Position near the target\n const rect = target.getBoundingClientRect();\n tipElement.style.left = `${rect.left}px`;\n tipElement.style.top = `${rect.bottom + 5}px`;\n tipElement.style.display = '';\n tipElement.classList.remove('x-tip-hidden');\n}\n\nfunction hideQuickTip(): void {\n if (tipElement) {\n tipElement.classList.add('x-tip-hidden');\n tipElement.style.display = 'none';\n }\n currentTipEl = null;\n}\n\nfunction clearShow(): void {\n if (showTimer !== null) { clearTimeout(showTimer); showTimer = null; }\n}\n\nfunction clearHide(): void {\n if (hideTimer !== null) { clearTimeout(hideTimer); hideTimer = null; }\n}\n\n// ---------------------------------------------------------------------------\n// QuickTip public API\n// ---------------------------------------------------------------------------\n\nexport class QuickTip {\n static init(): void {\n if (!initialized) {\n document.addEventListener('mouseover', onMouseOver as any, true);\n document.addEventListener('mouseout', onMouseOut as any, true);\n initialized = true;\n }\n enabled = true;\n }\n\n static enable(): void {\n enabled = true;\n }\n\n static disable(): void {\n enabled = false;\n clearShow();\n clearHide();\n hideQuickTip();\n }\n\n static isEnabled(): boolean {\n return enabled;\n }\n}\n","/**\n * @framesquared/ui – DataView\n *\n * Renders store records using a template function. Supports item\n * events (click, dblclick, mouseenter, mouseleave), single/multi\n * selection, hover tracking, empty text, and reactive store binding.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface DataViewConfig extends ComponentConfig {\n store?: any;\n itemTpl?: (record: any, index: number) => string;\n itemSelector?: string;\n itemCls?: string;\n selectedItemCls?: string;\n overItemCls?: string;\n emptyText?: string;\n multiSelect?: boolean;\n singleSelect?: boolean;\n trackOver?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// DataView\n// ---------------------------------------------------------------------------\n\nexport class DataView extends Component {\n static override $className = 'Ext.view.DataView';\n\n declare _store: any;\n declare private _itemTpl: (record: any, index: number) => string;\n declare private _itemSelector: string;\n declare private _itemCls: string;\n declare private _selectedItemCls: string;\n declare private _overItemCls: string;\n declare private _emptyText: string;\n declare private _multiSelect: boolean;\n declare private _singleSelect: boolean;\n declare private _trackOver: boolean;\n declare private _selectedRecords: Set<any>;\n declare private _contentEl: HTMLElement | null;\n\n constructor(config: DataViewConfig = {}) {\n super({ xtype: 'dataview', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as DataViewConfig;\n this._store = cfg.store ?? null;\n this._itemTpl = cfg.itemTpl ?? (() => '');\n this._itemSelector = cfg.itemSelector ?? '.x-dataview-item';\n this._itemCls = cfg.itemCls ?? '';\n this._selectedItemCls = cfg.selectedItemCls ?? 'x-item-selected';\n this._overItemCls = cfg.overItemCls ?? '';\n this._emptyText = cfg.emptyText ?? '';\n this._multiSelect = cfg.multiSelect ?? false;\n this._singleSelect = cfg.singleSelect ?? false;\n this._trackOver = cfg.trackOver ?? false;\n this._selectedRecords = new Set();\n this._contentEl = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-dataview');\n\n this._contentEl = document.createElement('div');\n this._contentEl.classList.add('x-dataview-content');\n this.el!.appendChild(this._contentEl);\n\n this.renderItems();\n this.bindStoreEvents();\n }\n\n // -----------------------------------------------------------------------\n // Rendering\n // -----------------------------------------------------------------------\n\n refresh(): void {\n this._selectedRecords.clear();\n this.renderItems();\n }\n\n private renderItems(): void {\n if (!this._contentEl) return;\n this._contentEl.innerHTML = '';\n\n const records = this._store?.getRange?.() ?? [];\n\n if (records.length === 0 && this._emptyText) {\n const emptyEl = document.createElement('div');\n emptyEl.classList.add('x-dataview-empty');\n emptyEl.textContent = this._emptyText;\n this._contentEl.appendChild(emptyEl);\n return;\n }\n\n for (let i = 0; i < records.length; i++) {\n const html = this._itemTpl(records[i], i);\n // Parse the HTML into elements\n const temp = document.createElement('div');\n temp.innerHTML = html;\n const el = temp.firstElementChild as HTMLElement;\n if (!el) continue;\n\n el.setAttribute('data-record-index', String(i));\n if (this._itemCls) el.classList.add(this._itemCls);\n\n this.attachItemEvents(el, records[i], i);\n this._contentEl.appendChild(el);\n }\n }\n\n private attachItemEvents(el: HTMLElement, record: any, index: number): void {\n el.addEventListener('click', (e) => {\n this.fire('itemclick', this, record, el, index, e);\n this.onItemClick(record, el);\n });\n\n el.addEventListener('dblclick', (e) => {\n this.fire('itemdblclick', this, record, el, index, e);\n });\n\n el.addEventListener('mouseenter', (e) => {\n this.fire('itemmouseenter', this, record, el, index, e);\n if (this._trackOver && this._overItemCls) {\n el.classList.add(this._overItemCls);\n }\n });\n\n el.addEventListener('mouseleave', (e) => {\n this.fire('itemmouseleave', this, record, el, index, e);\n if (this._trackOver && this._overItemCls) {\n el.classList.remove(this._overItemCls);\n }\n });\n }\n\n // -----------------------------------------------------------------------\n // Selection\n // -----------------------------------------------------------------------\n\n private onItemClick(record: any, el: HTMLElement): void {\n if (!this._singleSelect && !this._multiSelect) return;\n\n this.fire('beforeselect', this, record);\n\n if (this._singleSelect && !this._multiSelect) {\n // Deselect all others\n this.clearSelectionClasses();\n this._selectedRecords.clear();\n this._selectedRecords.add(record);\n el.classList.add(this._selectedItemCls);\n } else if (this._multiSelect) {\n if (this._selectedRecords.has(record)) {\n this._selectedRecords.delete(record);\n el.classList.remove(this._selectedItemCls);\n } else {\n this._selectedRecords.add(record);\n el.classList.add(this._selectedItemCls);\n }\n }\n\n this.fire('selectionchange', this, [...this._selectedRecords]);\n }\n\n private clearSelectionClasses(): void {\n if (!this._contentEl) return;\n const items = this._contentEl.querySelectorAll(this._itemSelector);\n for (const item of items) {\n item.classList.remove(this._selectedItemCls);\n }\n }\n\n getSelectedRecords(): any[] {\n return [...this._selectedRecords];\n }\n\n // -----------------------------------------------------------------------\n // Node accessors\n // -----------------------------------------------------------------------\n\n getNodes(): HTMLElement[] {\n if (!this._contentEl) return [];\n return Array.from(this._contentEl.querySelectorAll(this._itemSelector));\n }\n\n getNode(record: any): HTMLElement | null {\n const store = this._store;\n if (!store) return null;\n const records = store.getRange();\n const idx = records.indexOf(record);\n if (idx < 0) return null;\n const nodes = this.getNodes();\n return nodes[idx] ?? null;\n }\n\n getRecord(node: HTMLElement): any | null {\n const idx = node.getAttribute('data-record-index');\n if (idx === null) return null;\n return this._store?.getAt?.(parseInt(idx, 10)) ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Store binding\n // -----------------------------------------------------------------------\n\n private bindStoreEvents(): void {\n if (!this._store?.on) return;\n this._store.on('datachanged', () => this.renderItems());\n this._store.on('add', () => this.renderItems());\n this._store.on('remove', () => this.renderItems());\n this._store.on('update', () => this.renderItems());\n }\n}\n","/**\n * @framesquared/ui – ListView\n *\n * A lightweight column-based list view using <table> for alignment.\n * Simpler than a full Grid — no features, plugins, or editing.\n * Supports item events, empty text, and reactive store binding.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface ListColumnConfig {\n text: string;\n dataIndex: string;\n width?: number;\n}\n\nexport interface ListViewConfig extends ComponentConfig {\n store?: any;\n columns?: ListColumnConfig[];\n emptyText?: string;\n}\n\n// ---------------------------------------------------------------------------\n// ListView\n// ---------------------------------------------------------------------------\n\nexport class ListView extends Component {\n static override $className = 'Ext.view.ListView';\n\n declare private _store: any;\n declare private _columns: ListColumnConfig[];\n declare private _emptyText: string;\n declare private _tableEl: HTMLTableElement | null;\n declare private _tbodyEl: HTMLTableSectionElement | null;\n\n constructor(config: ListViewConfig = {}) {\n super({ xtype: 'listview', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as ListViewConfig;\n this._store = cfg.store ?? null;\n this._columns = cfg.columns ?? [];\n this._emptyText = cfg.emptyText ?? '';\n this._tableEl = null;\n this._tbodyEl = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-listview');\n\n this._tableEl = document.createElement('table');\n this._tableEl.classList.add('x-listview-table');\n this._tableEl.style.width = '100%';\n this._tableEl.style.borderCollapse = 'collapse';\n\n // Thead\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n for (const col of this._columns) {\n const th = document.createElement('th');\n th.textContent = col.text;\n if (col.width) th.style.width = `${col.width}px`;\n headerRow.appendChild(th);\n }\n thead.appendChild(headerRow);\n this._tableEl.appendChild(thead);\n\n // Tbody\n this._tbodyEl = document.createElement('tbody');\n this._tableEl.appendChild(this._tbodyEl);\n\n this.el!.appendChild(this._tableEl);\n this.renderRows();\n this.bindStoreEvents();\n }\n\n // -----------------------------------------------------------------------\n // Rendering\n // -----------------------------------------------------------------------\n\n refresh(): void {\n this.renderRows();\n }\n\n private renderRows(): void {\n if (!this._tbodyEl) return;\n this._tbodyEl.innerHTML = '';\n\n const records = this._store?.getRange?.() ?? [];\n\n if (records.length === 0 && this._emptyText) {\n const tr = document.createElement('tr');\n const td = document.createElement('td');\n td.colSpan = this._columns.length || 1;\n td.classList.add('x-listview-empty');\n td.textContent = this._emptyText;\n tr.appendChild(td);\n this._tbodyEl.appendChild(tr);\n return;\n }\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i];\n const tr = document.createElement('tr');\n tr.classList.add('x-listview-row');\n tr.setAttribute('data-rowindex', String(i));\n\n for (const col of this._columns) {\n const td = document.createElement('td');\n const val = record.get ? record.get(col.dataIndex) : record.data?.[col.dataIndex];\n td.textContent = val === null || val === undefined ? '' : String(val);\n tr.appendChild(td);\n }\n\n tr.addEventListener('click', (e) => {\n this.fire('itemclick', this, record, tr, i, e);\n });\n\n tr.addEventListener('dblclick', (e) => {\n this.fire('itemdblclick', this, record, tr, i, e);\n });\n\n this._tbodyEl.appendChild(tr);\n }\n }\n\n // -----------------------------------------------------------------------\n // Store binding\n // -----------------------------------------------------------------------\n\n private bindStoreEvents(): void {\n if (!this._store?.on) return;\n this._store.on('datachanged', () => this.renderRows());\n this._store.on('add', () => this.renderRows());\n this._store.on('remove', () => this.renderRows());\n }\n}\n","/**\n * @framesquared/ui – TabBar\n *\n * A container for Tab components. Renders as a horizontal (or vertical)\n * strip of tabs. Supports adding, removing, and overflow.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\nimport { Tab } from './Tab.js';\n\nexport interface TabBarConfig extends ComponentConfig {\n position?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nexport class TabBar extends Component {\n static override $className = 'Ext.tab.Bar';\n\n declare private _tabs: Tab[];\n declare private _stripEl: HTMLElement | null;\n declare private _position: string;\n\n constructor(config: TabBarConfig = {}) {\n super({ xtype: 'tabbar', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n this._tabs = [];\n this._stripEl = null;\n this._position = (this._config as TabBarConfig).position ?? 'top';\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const el = this.el!;\n el.classList.add('x-tabbar');\n if (this._position !== 'top') {\n el.classList.add(`x-tabbar-${this._position}`);\n }\n el.setAttribute('role', 'tablist');\n\n this._stripEl = document.createElement('div');\n this._stripEl.classList.add('x-tabbar-strip');\n const isVertical = this._position === 'left' || this._position === 'right';\n this._stripEl.style.display = 'flex';\n this._stripEl.style.flexDirection = isVertical ? 'column' : 'row';\n el.appendChild(this._stripEl);\n\n // Render any pre-added tabs\n for (const tab of this._tabs) {\n if (!tab.rendered) tab.render(this._stripEl);\n }\n }\n\n addTab(tab: Tab): void {\n this._tabs.push(tab);\n if (this._stripEl && !tab.rendered) {\n tab.render(this._stripEl);\n }\n }\n\n removeTab(tab: Tab): void {\n const idx = this._tabs.indexOf(tab);\n if (idx >= 0) this._tabs.splice(idx, 1);\n if (tab.el?.parentNode) tab.el.parentNode.removeChild(tab.el);\n tab.destroy();\n }\n\n getTabs(): Tab[] {\n return [...this._tabs];\n }\n}\n","/**\n * @framesquared/ui – Tab\n *\n * A tab component that renders as a clickable element with text,\n * optional icon, optional close button, and active state styling.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\nexport interface TabConfig extends ComponentConfig {\n text?: string;\n iconCls?: string;\n closable?: boolean;\n active?: boolean;\n card?: Component;\n}\n\nexport class Tab extends Component {\n static override $className = 'Ext.tab.Tab';\n\n declare private _text: string;\n declare private _closable: boolean;\n declare private _active: boolean;\n declare private _textEl: HTMLElement | null;\n declare private _closeEl: HTMLElement | null;\n /** The panel this tab represents */\n declare card: Component | null;\n\n constructor(config: TabConfig = {}) {\n super({ xtype: 'tab', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as TabConfig;\n this._text = cfg.text ?? '';\n this._closable = cfg.closable ?? false;\n this._active = cfg.active ?? false;\n this._textEl = null;\n this._closeEl = null;\n this.card = cfg.card ?? null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const el = this.el!;\n el.classList.add('x-tab');\n el.style.cursor = 'pointer';\n el.style.display = 'inline-flex';\n el.style.alignItems = 'center';\n el.setAttribute('role', 'tab');\n\n const cfg = this._config as TabConfig;\n\n // Icon\n if (cfg.iconCls) {\n const icon = document.createElement('span');\n icon.classList.add('x-tab-icon', cfg.iconCls);\n el.appendChild(icon);\n }\n\n // Text\n this._textEl = document.createElement('span');\n this._textEl.classList.add('x-tab-text');\n this._textEl.textContent = this._text;\n el.appendChild(this._textEl);\n\n // Close button\n if (this._closable) {\n this._closeEl = document.createElement('span');\n this._closeEl.classList.add('x-tab-close');\n this._closeEl.textContent = '×';\n this._closeEl.addEventListener('click', (e) => {\n e.stopPropagation();\n this.fire('close', this);\n });\n el.appendChild(this._closeEl);\n }\n\n // Active state\n if (this._active) el.classList.add('x-tab-active');\n\n // Fire component 'click' on DOM click\n el.addEventListener('click', () => {\n this.fire('click', this);\n });\n }\n\n setActive(active: boolean): void {\n this._active = active;\n if (this.el) {\n this.el.classList.toggle('x-tab-active', active);\n }\n }\n\n isActive(): boolean {\n return this._active;\n }\n\n setText(text: string): void {\n this._text = text;\n if (this._textEl) this._textEl.textContent = text;\n }\n}\n","/**\n * @framesquared/ui – TabPanel\n *\n * A Panel that uses a card layout internally. Each child panel\n * becomes a tab in the TabBar. Clicking a tab switches the\n * visible card. Supports closable tabs, deferred rendering,\n * and top/bottom/left/right tab positioning.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport { Panel } from '../panel/Panel.js';\nimport type { PanelConfig } from '../panel/Panel.js';\nimport { TabBar } from './TabBar.js';\nimport { Tab } from './Tab.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TabPanelConfig extends PanelConfig {\n activeTab?: number | Component;\n tabPosition?: 'top' | 'bottom' | 'left' | 'right';\n plain?: boolean;\n deferredRender?: boolean;\n minTabWidth?: number;\n maxTabWidth?: number;\n removePanelHeader?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TabPanel\n// ---------------------------------------------------------------------------\n\nexport class TabPanel extends Panel {\n static override $className = 'Ext.tab.Panel';\n private static _idCounter = 0;\n\n declare private _tabBar: TabBar | null;\n declare private _tabItems: Component[];\n declare private _tabs: Tab[];\n declare private _activeIndex: number;\n declare private _tabPosition: string;\n declare private _deferredRender: boolean;\n declare private _tabBodyEl: HTMLElement | null;\n declare private _pendingTabItems: Component[];\n\n constructor(config: TabPanelConfig = {}) {\n // Stash items on a private config key, pass items:[] to Panel\n const tabItems = (config.items as any[]) ?? [];\n super({ xtype: 'tabpanel', ...config, items: [], _tabPanelItems: tabItems });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as any;\n this._tabBar = null;\n this._tabItems = [];\n this._tabs = [];\n this._activeIndex = typeof cfg.activeTab === 'number' ? cfg.activeTab : 0;\n this._tabPosition = cfg.tabPosition ?? 'top';\n this._deferredRender = cfg.deferredRender ?? false;\n this._tabBodyEl = null;\n this._pendingTabItems = cfg._tabPanelItems ?? [];\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const cfg = this._config as TabPanelConfig;\n this.el!.classList.add('x-tabpanel');\n if (cfg.plain) this.el!.classList.add('x-tabpanel-plain');\n\n const bodyEl = this.getBodyEl();\n bodyEl.classList.add('x-tabpanel-body');\n\n // Create tab body container (card layout area)\n this._tabBodyEl = bodyEl;\n\n // Create TabBar\n this._tabBar = new TabBar({ position: this._tabPosition as any });\n this._tabBar.render(this.el!);\n\n // Position the bar relative to body\n const barEl = this._tabBar.el!;\n if (this._tabPosition === 'bottom' || this._tabPosition === 'right') {\n // Bar after body\n bodyEl.parentNode!.insertBefore(barEl, bodyEl.nextSibling);\n } else {\n // Bar before body (top/left)\n bodyEl.parentNode!.insertBefore(barEl, bodyEl);\n }\n\n // For left/right, wrap in flex container\n if (this._tabPosition === 'left' || this._tabPosition === 'right') {\n const wrapper = bodyEl.parentNode as HTMLElement;\n wrapper.style.display = 'flex';\n if (this._tabPosition === 'right') {\n wrapper.style.flexDirection = 'row';\n }\n bodyEl.style.flexGrow = '1';\n }\n\n // Add tab items\n const pendingItems = (this as any)._pendingTabItems as Component[];\n for (const item of pendingItems) {\n this.addTabItem(item);\n }\n delete (this as any)._pendingTabItems;\n\n // Activate initial tab\n if (this._tabItems.length > 0) {\n this.activateTab(this._activeIndex, true);\n }\n }\n\n // -----------------------------------------------------------------------\n // Tab management\n // -----------------------------------------------------------------------\n\n private addTabItem(item: Component): void {\n const index = this._tabItems.length;\n this._tabItems.push(item);\n\n // Generate unique panel ID for ARIA linking\n const panelId = `ext-tabpanel-${TabPanel._idCounter++}`;\n\n // Create Tab\n const panelCfg = (item as any)._config ?? {};\n const tab = new Tab({\n text: panelCfg.title ?? `Tab ${index + 1}`,\n iconCls: panelCfg.iconCls,\n closable: panelCfg.closable ?? false,\n card: item,\n });\n\n // Tab click → activate\n (tab as any).on('click', () => {\n const idx = this._tabItems.indexOf(item);\n if (idx >= 0) this.setActiveTab(idx);\n });\n\n // Tab close → remove\n (tab as any).on('close', () => {\n this.closeTab(index);\n });\n\n this._tabs.push(tab);\n this._tabBar!.addTab(tab);\n\n // ARIA: link tab to its panel\n if (tab.el) {\n tab.el.setAttribute('aria-controls', panelId);\n tab.el.setAttribute('aria-selected', 'false');\n }\n\n // Handle rendering\n if (this._deferredRender) {\n // Don't render yet — will render on first activation\n // Store panelId for later\n (item as any)._ariaPanelId = panelId;\n } else {\n if (!item.rendered) item.render(this._tabBodyEl!);\n if (item.el) {\n item.el.id = panelId;\n item.el.setAttribute('role', 'tabpanel');\n }\n item.hide();\n }\n }\n\n private closeTab(originalIndex: number): void {\n // Find current index (may have shifted)\n const tab = this._tabs[originalIndex];\n if (!tab) return;\n const item = tab.card;\n const currentIndex = this._tabItems.indexOf(item!);\n if (currentIndex < 0) return;\n\n const cancelled = this.fire('beforetabclose', this, item);\n if (cancelled === false) return;\n\n // Remove tab and item\n this._tabBar!.removeTab(tab);\n this._tabs.splice(this._tabs.indexOf(tab), 1);\n this._tabItems.splice(currentIndex, 1);\n\n if (item?.el?.parentNode) item.el.parentNode.removeChild(item.el);\n\n // If we closed the active tab, activate another\n if (this._activeIndex === currentIndex) {\n const newIndex = Math.min(currentIndex, this._tabItems.length - 1);\n if (newIndex >= 0) {\n this.activateTab(newIndex, true);\n }\n } else if (this._activeIndex > currentIndex) {\n this._activeIndex--;\n }\n }\n\n // -----------------------------------------------------------------------\n // Activation\n // -----------------------------------------------------------------------\n\n setActiveTab(tabOrIndex: number | Component): void {\n let index: number;\n if (typeof tabOrIndex === 'number') {\n index = tabOrIndex;\n } else {\n index = this._tabItems.indexOf(tabOrIndex);\n }\n if (index < 0 || index >= this._tabItems.length) return;\n if (index === this._activeIndex && this._tabItems[index]?.rendered) return;\n\n const oldItem = this._tabItems[this._activeIndex];\n const newItem = this._tabItems[index];\n\n const cancelled = this.fire('beforetabchange', this, newItem, oldItem);\n if (cancelled === false) return;\n\n this.activateTab(index, false);\n }\n\n private activateTab(index: number, skipEvent: boolean): void {\n const oldIndex = this._activeIndex;\n const oldItem = this._tabItems[oldIndex];\n const newItem = this._tabItems[index];\n\n // Deactivate old\n if (this._tabs[oldIndex]) {\n this._tabs[oldIndex].setActive(false);\n this._tabs[oldIndex].el?.setAttribute('aria-selected', 'false');\n }\n if (oldItem?.rendered) oldItem.hide();\n\n // Activate new\n this._activeIndex = index;\n if (this._tabs[index]) {\n this._tabs[index].setActive(true);\n this._tabs[index].el?.setAttribute('aria-selected', 'true');\n }\n\n // Deferred render: render on first activation\n if (!newItem.rendered) {\n newItem.render(this._tabBodyEl!);\n // Apply deferred ARIA panel ID\n const panelId = (newItem as any)._ariaPanelId;\n if (panelId && newItem.el) {\n newItem.el.id = panelId;\n newItem.el.setAttribute('role', 'tabpanel');\n }\n }\n newItem.show();\n\n if (!skipEvent) {\n this.fire('tabchange', this, newItem, oldItem);\n }\n }\n\n getActiveTab(): Component | undefined {\n return this._tabItems[this._activeIndex];\n }\n\n getTabItems(): Component[] {\n return [...this._tabItems];\n }\n\n getTabBar(): TabBar | null {\n return this._tabBar;\n }\n}\n","/**\n * @framesquared/ui – Viewport\n *\n * A Container that fills the entire browser viewport.\n * Renders into document.body, sets overflow: hidden,\n * and fires 'resize' on window resize.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\n\nexport interface ViewportConfig extends ContainerConfig {}\n\nexport class Viewport extends Container {\n static override $className = 'Ext.container.Viewport';\n\n declare private _resizeHandler: (() => void) | null;\n\n constructor(config: ViewportConfig = {}) {\n super({ xtype: 'viewport', renderTo: document.body, ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n this._resizeHandler = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n const el = this.el!;\n el.classList.add('x-viewport');\n el.style.width = '100vw';\n el.style.height = '100vh';\n el.style.overflow = 'hidden';\n el.style.position = 'relative';\n\n document.body.style.margin = '0';\n document.body.style.padding = '0';\n document.body.style.overflow = 'hidden';\n\n this._resizeHandler = () => {\n this.fire('resize', this, window.innerWidth, window.innerHeight);\n };\n window.addEventListener('resize', this._resizeHandler);\n }\n\n protected override onDestroy(): void {\n if (this._resizeHandler) {\n window.removeEventListener('resize', this._resizeHandler);\n this._resizeHandler = null;\n }\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/ui – Accordion\n *\n * A Container that displays child panels as collapsible sections.\n * By default only one panel is expanded at a time (single mode).\n * Set multi:true to allow multiple expanded panels.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\n\nexport interface AccordionConfig extends ContainerConfig {\n multi?: boolean;\n activeItem?: number;\n}\n\nexport class Accordion extends Container {\n static override $className = 'Ext.container.Accordion';\n\n declare private _multi: boolean;\n declare private _expandedSet: Set<number>;\n declare private _headerEls: HTMLElement[];\n\n constructor(config: AccordionConfig = {}) {\n super({ xtype: 'accordion', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as AccordionConfig;\n this._multi = cfg.multi ?? false;\n this._expandedSet = new Set();\n this._headerEls = [];\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-accordion');\n\n const body = this.getBodyEl();\n body.style.display = 'flex';\n body.style.flexDirection = 'column';\n\n // Wrap each child with an accordion section\n const items = this.getItems();\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const section = document.createElement('div');\n section.classList.add('x-accordion-section');\n\n // Header\n const header = document.createElement('div');\n header.classList.add('x-accordion-header');\n header.style.cursor = 'pointer';\n const panelCfg = (item as any)._config ?? {};\n header.textContent = panelCfg.title ?? `Section ${i + 1}`;\n header.addEventListener('click', () => this.toggle(i));\n this._headerEls.push(header);\n section.appendChild(header);\n\n // Body wrapper\n const bodyWrap = document.createElement('div');\n bodyWrap.classList.add('x-accordion-body');\n if (item.el) {\n bodyWrap.appendChild(item.el);\n }\n section.appendChild(bodyWrap);\n\n body.appendChild(section);\n }\n\n // Expand first by default\n const cfg = this._config as AccordionConfig;\n const active = cfg.activeItem ?? 0;\n if (items.length > 0) {\n this.expand(active);\n }\n }\n\n // -----------------------------------------------------------------------\n // Expand / Collapse\n // -----------------------------------------------------------------------\n\n expand(index: number): void {\n if (!this._multi) {\n // Collapse all others\n for (const i of [...this._expandedSet]) {\n if (i !== index) this.doCollapse(i);\n }\n }\n this.doExpand(index);\n }\n\n collapse(index: number): void {\n this.doCollapse(index);\n }\n\n toggle(index: number): void {\n if (this._expandedSet.has(index)) {\n this.collapse(index);\n } else {\n this.expand(index);\n }\n }\n\n isExpanded(index: number): boolean {\n return this._expandedSet.has(index);\n }\n\n private doExpand(index: number): void {\n this._expandedSet.add(index);\n const section = this.getSection(index);\n if (section) {\n const bodyWrap = section.querySelector('.x-accordion-body') as HTMLElement;\n if (bodyWrap) bodyWrap.style.display = '';\n section.classList.add('x-accordion-expanded');\n }\n this.fire('expand', this, index);\n }\n\n private doCollapse(index: number): void {\n this._expandedSet.delete(index);\n const section = this.getSection(index);\n if (section) {\n const bodyWrap = section.querySelector('.x-accordion-body') as HTMLElement;\n if (bodyWrap) bodyWrap.style.display = 'none';\n section.classList.remove('x-accordion-expanded');\n }\n this.fire('collapse', this, index);\n }\n\n private getSection(index: number): HTMLElement | null {\n const body = this.getBodyEl();\n const sections = body.querySelectorAll('.x-accordion-section');\n return (sections[index] as HTMLElement) ?? null;\n }\n}\n","/**\n * @framesquared/ui – CardContainer\n *\n * A Container with card layout behavior: only one child is visible\n * at a time. Provides next(), prev(), and setActiveItem() for\n * wizard-style navigation.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Container } from '@framesquared/component';\nimport type { ContainerConfig } from '@framesquared/component';\n\nexport interface CardContainerConfig extends ContainerConfig {\n activeItem?: number;\n}\n\nexport class CardContainer extends Container {\n static override $className = 'Ext.container.CardContainer';\n\n declare private _activeIndex: number;\n\n constructor(config: CardContainerConfig = {}) {\n super({ xtype: 'cardcontainer', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n this._activeIndex = (this._config as CardContainerConfig).activeItem ?? 0;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-card-container');\n\n const body = this.getBodyEl();\n body.style.position = 'relative';\n\n // Hide all except active\n const items = this.getItems();\n for (let i = 0; i < items.length; i++) {\n if (i !== this._activeIndex) {\n items[i].hide();\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Navigation\n // -----------------------------------------------------------------------\n\n setActiveItem(index: number): void {\n const items = this.getItems();\n if (index < 0 || index >= items.length) return;\n if (index === this._activeIndex) return;\n\n const oldItem = items[this._activeIndex];\n const newItem = items[index];\n const oldIndex = this._activeIndex;\n\n oldItem?.hide();\n newItem?.show();\n this._activeIndex = index;\n\n this.fire('cardchange', this, newItem, oldItem, index, oldIndex);\n }\n\n next(): void {\n const items = this.getItems();\n if (this._activeIndex < items.length - 1) {\n this.setActiveItem(this._activeIndex + 1);\n }\n }\n\n prev(): void {\n if (this._activeIndex > 0) {\n this.setActiveItem(this._activeIndex - 1);\n }\n }\n\n getActiveItem(): any {\n return this.getItems()[this._activeIndex] ?? null;\n }\n\n getActiveIndex(): number {\n return this._activeIndex;\n }\n}\n","/**\n * @framesquared/ui – Breadcrumb\n *\n * Displays a tree store as a breadcrumb path. Each segment is a\n * clickable item. Non-leaf items have a dropdown arrow that shows\n * their children for navigation.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Component } from '@framesquared/component';\nimport type { ComponentConfig } from '@framesquared/component';\n\n// ---------------------------------------------------------------------------\n// Minimal tree node interface (duck-typed, no grid import)\n// ---------------------------------------------------------------------------\n\nexport interface BreadcrumbNode {\n id: string;\n text: string;\n leaf: boolean;\n children: BreadcrumbNode[];\n parent: BreadcrumbNode | null;\n}\n\nexport interface BreadcrumbStore {\n getRoot(): BreadcrumbNode;\n getNodeById(id: string): BreadcrumbNode | null;\n}\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface BreadcrumbConfig extends ComponentConfig {\n store?: BreadcrumbStore;\n selection?: BreadcrumbNode | null;\n showIcons?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Breadcrumb\n// ---------------------------------------------------------------------------\n\nexport class Breadcrumb extends Component {\n static override $className = 'Ext.navigation.Breadcrumb';\n\n declare private _store: BreadcrumbStore | null;\n declare private _selection: BreadcrumbNode | null;\n declare private _contentEl: HTMLElement | null;\n declare private _activeDropdown: HTMLElement | null;\n\n constructor(config: BreadcrumbConfig = {}) {\n super({ xtype: 'breadcrumb', ...config });\n }\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as BreadcrumbConfig;\n this._store = cfg.store ?? null;\n this._selection = cfg.selection ?? this._store?.getRoot() ?? null;\n this._contentEl = null;\n this._activeDropdown = null;\n }\n\n protected override afterRender(): void {\n super.afterRender();\n this.el!.classList.add('x-breadcrumb');\n this.el!.style.display = 'flex';\n this.el!.style.alignItems = 'center';\n\n this._contentEl = this.el!;\n this.renderPath();\n }\n\n // -----------------------------------------------------------------------\n // Rendering\n // -----------------------------------------------------------------------\n\n private renderPath(): void {\n if (!this._contentEl) return;\n this._contentEl.innerHTML = '';\n this.closeDropdown();\n\n if (!this._selection) return;\n\n // Build path from root to selection\n const path = this.getPathToNode(this._selection);\n\n for (let i = 0; i < path.length; i++) {\n const node = path[i];\n\n // Separator\n if (i > 0) {\n const sep = document.createElement('span');\n sep.classList.add('x-breadcrumb-separator');\n sep.textContent = ' › ';\n this._contentEl.appendChild(sep);\n }\n\n // Item\n const item = document.createElement('span');\n item.classList.add('x-breadcrumb-item');\n item.setAttribute('data-node-id', node.id);\n item.style.cursor = 'pointer';\n\n item.addEventListener('click', (e) => {\n // Don't navigate if click was on the arrow\n if ((e.target as HTMLElement).closest('.x-breadcrumb-arrow')) return;\n e.stopPropagation();\n this.navigateTo(node);\n });\n\n // Text\n const text = document.createElement('span');\n text.classList.add('x-breadcrumb-text');\n text.textContent = node.text;\n item.appendChild(text);\n\n // Dropdown arrow for non-leaf\n if (!node.leaf && node.children.length > 0) {\n const arrow = document.createElement('span');\n arrow.classList.add('x-breadcrumb-arrow');\n arrow.textContent = ' ▾';\n arrow.style.cursor = 'pointer';\n arrow.addEventListener('click', (e) => {\n e.stopPropagation();\n this.showDropdown(node, arrow);\n });\n item.appendChild(arrow);\n }\n\n this._contentEl.appendChild(item);\n }\n }\n\n private getPathToNode(node: BreadcrumbNode): BreadcrumbNode[] {\n const path: BreadcrumbNode[] = [];\n let current: BreadcrumbNode | null = node;\n while (current) {\n path.unshift(current);\n current = current.parent;\n }\n return path;\n }\n\n // -----------------------------------------------------------------------\n // Navigation\n // -----------------------------------------------------------------------\n\n private navigateTo(node: BreadcrumbNode): void {\n const old = this._selection;\n this._selection = node;\n this.renderPath();\n this.fire('selectionchange', this, node, old);\n }\n\n setSelection(node: BreadcrumbNode): void {\n this.navigateTo(node);\n }\n\n getSelection(): BreadcrumbNode | null {\n return this._selection;\n }\n\n // -----------------------------------------------------------------------\n // Dropdown\n // -----------------------------------------------------------------------\n\n private showDropdown(node: BreadcrumbNode, anchor: HTMLElement): void {\n this.closeDropdown();\n\n const dropdown = document.createElement('div');\n dropdown.classList.add('x-breadcrumb-dropdown');\n dropdown.style.position = 'absolute';\n dropdown.style.zIndex = '10000';\n\n for (const child of node.children) {\n const option = document.createElement('div');\n option.classList.add('x-breadcrumb-dropdown-item');\n option.textContent = child.text;\n option.style.cursor = 'pointer';\n option.addEventListener('click', (e) => {\n e.stopPropagation();\n this.navigateTo(child);\n });\n dropdown.appendChild(option);\n }\n\n // Position below the arrow\n const rect = anchor.getBoundingClientRect();\n dropdown.style.left = `${rect.left}px`;\n dropdown.style.top = `${rect.bottom}px`;\n\n document.body.appendChild(dropdown);\n this._activeDropdown = dropdown;\n\n // Close on outside click\n const onClickOutside = (e: MouseEvent) => {\n if (!dropdown.contains(e.target as Node)) {\n this.closeDropdown();\n document.removeEventListener('click', onClickOutside);\n }\n };\n setTimeout(() => document.addEventListener('click', onClickOutside), 0);\n }\n\n private closeDropdown(): void {\n if (this._activeDropdown?.parentNode) {\n this._activeDropdown.parentNode.removeChild(this._activeDropdown);\n }\n this._activeDropdown = null;\n }\n\n protected override onDestroy(): void {\n this.closeDropdown();\n super.onDestroy();\n }\n}\n","/**\n * @framesquared/data – Model\n *\n * The foundation of the data layer. A Model represents a record with\n * typed fields, dirty tracking, validation, and event notification.\n *\n * Instances are wrapped in a Proxy so `record.name` transparently\n * delegates to `get('name')` / `set('name', value)` for field access.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Base, Observable } from '@framesquared/core';\nimport { Field, createField } from './field/Field.js';\nimport type { FieldDefinition } from './field/Field.js';\nimport { Schema } from './Schema.js';\nimport type { Association } from './association/Association.js';\nimport { ModelCollection, ManyToManyCollection } from './ModelCollection.js';\n\n// ---------------------------------------------------------------------------\n// ValidationResult\n// ---------------------------------------------------------------------------\n\nexport interface ValidationError {\n field: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n// ---------------------------------------------------------------------------\n// Field resolution helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolves a dot-separated mapping path from raw data.\n */\nfunction getNestedValue(data: Record<string, unknown>, path: string): unknown {\n const segments = path.split('.');\n let current: unknown = data;\n for (const seg of segments) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n\n// ---------------------------------------------------------------------------\n// Proxy handler\n// ---------------------------------------------------------------------------\n\nconst MODEL_PROPS = new Set<string | symbol>([\n // Commonly accessed non-field properties/methods that should NOT\n // be intercepted by the proxy's field get/set logic.\n 'constructor', 'prototype', '__proto__',\n 'get', 'set', 'getData', 'getId', 'setId',\n 'isModified', 'getChanges', 'commit', 'reject', 'validate', 'isValid',\n 'on', 'un', 'fireEvent', 'fireEventArgs', 'addListener', 'removeListener',\n 'hasListener', 'clearListeners', 'suspendEvents', 'resumeEvents', 'isSuspended',\n 'mon', 'mun', 'relayEvents', 'fireEventedAction',\n 'destroy', 'isDestroyed', '$destroyHooks',\n '$className', 'self', '$callStack', '$configInitialized', '$pendingConfig',\n 'hasMixin', 'initConfig', 'callParent',\n 'modified', 'phantom',\n '$associations', '$fieldMap', '$data',\n Symbol.dispose, Symbol.toPrimitive, Symbol.toStringTag,\n]);\n\nfunction createModelProxy(model: Model): Model {\n return new Proxy(model, {\n get(target, prop, receiver) {\n // If it's a known Model/Base property or symbol, use normal access\n if (MODEL_PROPS.has(prop) || typeof prop === 'symbol') {\n return Reflect.get(target, prop, receiver);\n }\n // If it exists directly on the instance or prototype, use normal access\n if (prop in target) {\n const desc = Object.getOwnPropertyDescriptor(target, prop)\n ?? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(target), prop);\n if (desc?.get || typeof desc?.value === 'function') {\n return Reflect.get(target, prop, receiver);\n }\n }\n // Check if it's a field name\n if (typeof prop === 'string' && target.$fieldMap?.has(prop)) {\n return target.get(prop);\n }\n return Reflect.get(target, prop, receiver);\n },\n set(target, prop, value, receiver) {\n if (typeof prop === 'string' && target.$fieldMap?.has(prop)) {\n target.set(prop, value);\n return true;\n }\n return Reflect.set(target, prop, value, receiver);\n },\n });\n}\n\n// ---------------------------------------------------------------------------\n// Model class\n// ---------------------------------------------------------------------------\n\n// Register the Observable mixin class (defined by core's define())\nconst ObservableMixin: typeof Base = Observable;\n\nexport class Model extends Base {\n static override $className = 'Ext.data.Model';\n\n /** Field definitions — override in subclasses. */\n static fields: (FieldDefinition | string)[] = [];\n\n /** Name of the ID field. */\n static idProperty = 'id';\n\n // -- Instance state (non-enumerable to keep proxy clean) --\n\n /** Resolved Field instances keyed by name. */\n $fieldMap!: Map<string, Field>;\n\n /** Current field values. */\n $data!: Record<string, unknown>;\n\n /** Previous values for dirty fields (fieldName → old value). */\n modified: Record<string, unknown> = {};\n\n /** Per-instance association storage: assocName → Model | ModelCollection */\n $associations: Map<string, Model | ModelCollection | ManyToManyCollection> = new Map();\n\n // -----------------------------------------------------------------------\n // Construction\n // -----------------------------------------------------------------------\n\n constructor(_data?: Record<string, unknown>) {\n super();\n // Will be called by create() which sets up fields + proxy\n }\n\n /**\n * Factory method that sets up fields, applies data, wraps in proxy.\n */\n static override create(this: typeof Model, data?: Record<string, unknown>): Model {\n const instance = new this();\n instance.$fieldMap = new Map();\n instance.$data = {};\n instance.modified = {};\n instance.$associations = new Map();\n\n // Resolve field definitions\n const fieldDefs = (this as any).fields as (FieldDefinition | string)[];\n for (const def of fieldDefs) {\n const field = createField(def);\n instance.$fieldMap.set(field.name, field);\n }\n\n // Apply Observable mixin methods if not already present\n ensureObservable(instance);\n\n // Load initial data\n instance.$loadData(data ?? {});\n\n // Process associations — install getters/setters, load nested data\n installAssociations(instance, data ?? {});\n\n // Wrap in proxy\n return createModelProxy(instance);\n }\n\n // -----------------------------------------------------------------------\n // Data loading (initial — not dirty)\n // -----------------------------------------------------------------------\n\n /** @internal Loads initial data without marking as dirty. */\n $loadData(rawData: Record<string, unknown>): void {\n // Store non-schema fields as-is (pass-through for custom data)\n for (const [key, value] of Object.entries(rawData)) {\n if (!this.$fieldMap.has(key)) {\n this.$data[key] = value;\n }\n }\n\n for (const [name, field] of this.$fieldMap) {\n let value: unknown;\n\n // Check mapping first\n if (field.mapping) {\n value = getNestedValue(rawData, field.mapping);\n } else {\n value = rawData[name];\n }\n\n // Apply field conversion\n if (value !== undefined) {\n value = field.convert(value, this);\n } else {\n value = field.defaultValue;\n if (value !== undefined) {\n value = field.convert(value, this);\n }\n }\n\n this.$data[name] = value;\n }\n }\n\n // -----------------------------------------------------------------------\n // get / set\n // -----------------------------------------------------------------------\n\n get(fieldName: string): unknown {\n return this.$data[fieldName];\n }\n\n set(fieldNameOrData: string | Record<string, unknown>, value?: unknown): string[] {\n const changes: Record<string, unknown> =\n typeof fieldNameOrData === 'string'\n ? { [fieldNameOrData]: value }\n : fieldNameOrData;\n\n const modifiedFields: string[] = [];\n\n for (const [name, newValue] of Object.entries(changes)) {\n const field = this.$fieldMap.get(name);\n if (!field) {\n // Pass-through for non-schema fields\n const oldValue = this.$data[name];\n if (newValue !== oldValue) {\n if (!(name in this.modified)) this.modified[name] = oldValue;\n this.$data[name] = newValue;\n modifiedFields.push(name);\n }\n continue;\n }\n\n const converted = field.convert(newValue, this);\n const oldValue = this.$data[name];\n\n if (converted === oldValue) continue;\n\n // Track dirty state — only store the first original value\n if (!(name in this.modified)) {\n this.modified[name] = oldValue;\n }\n\n this.$data[name] = converted;\n modifiedFields.push(name);\n\n // Fire idchanged if the id field changed\n const Ctor = this.constructor as typeof Model;\n if (name === Ctor.idProperty && typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent('idchanged', this, converted, oldValue);\n }\n }\n\n if (modifiedFields.length > 0 && typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent('change', this, modifiedFields);\n }\n\n return modifiedFields;\n }\n\n getData(options?: { serialize?: boolean }): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [name, field] of this.$fieldMap) {\n const value = this.$data[name];\n result[name] = options?.serialize ? field.serialize(value, this) : value;\n }\n return result;\n }\n\n // -----------------------------------------------------------------------\n // Dirty tracking\n // -----------------------------------------------------------------------\n\n isModified(fieldName?: string): boolean {\n if (fieldName) {\n return fieldName in this.modified;\n }\n return Object.keys(this.modified).length > 0;\n }\n\n getChanges(): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const name of Object.keys(this.modified)) {\n result[name] = this.$data[name];\n }\n return result;\n }\n\n commit(silent?: boolean): void {\n this.modified = {};\n if (!silent && typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent('commit', this);\n }\n }\n\n reject(silent?: boolean): void {\n // Revert to previous values\n for (const [name, oldValue] of Object.entries(this.modified)) {\n this.$data[name] = oldValue;\n }\n this.modified = {};\n if (!silent && typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent('reject', this);\n }\n }\n\n // -----------------------------------------------------------------------\n // Identification\n // -----------------------------------------------------------------------\n\n getId(): string | number {\n const Ctor = this.constructor as typeof Model;\n return this.$data[Ctor.idProperty] as string | number;\n }\n\n setId(id: string | number): void {\n const Ctor = this.constructor as typeof Model;\n this.set(Ctor.idProperty, id);\n }\n\n get phantom(): boolean {\n const id = this.getId();\n return id === undefined || id === null || id === 0 || id === '';\n }\n\n // -----------------------------------------------------------------------\n // Validation\n // -----------------------------------------------------------------------\n\n validate(): ValidationResult {\n const errors: ValidationError[] = [];\n\n for (const [name, field] of this.$fieldMap) {\n const value = this.$data[name];\n for (const validator of field.validators) {\n const msg = validator(value, this);\n if (msg) {\n errors.push({ field: name, message: msg });\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n isValid(): boolean {\n return this.validate().valid;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Observable mixin integration\n// ---------------------------------------------------------------------------\n\n/**\n * Ensures the Observable mixin methods are available on the instance.\n * We copy prototype methods from Observable to Model instances at runtime.\n */\nfunction ensureObservable(instance: Model): void {\n const proto = ObservableMixin.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (name === 'constructor') continue;\n if (name in instance) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (desc && typeof desc.value === 'function') {\n (instance as any)[name] = desc.value.bind(instance);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Association integration\n// ---------------------------------------------------------------------------\n\n/**\n * Processes all associations for the given instance's model class.\n * Installs getters/setters, loads nested data, sets up cascade hooks.\n */\nfunction installAssociations(\n instance: Model,\n rawData: Record<string, unknown>,\n): void {\n const modelName = (instance.constructor as typeof Model).$className;\n const assocs = Schema.getAssociations(modelName);\n if (assocs.length === 0) return;\n\n for (const assoc of assocs) {\n if (!assoc.associatedModel) continue;\n\n switch (assoc.type) {\n case 'hasOne':\n installHasOne(instance, assoc, rawData);\n break;\n case 'hasMany':\n installHasMany(instance, assoc, rawData);\n break;\n case 'belongsTo':\n installBelongsTo(instance, assoc, rawData);\n break;\n case 'manyToMany':\n installManyToMany(instance, assoc, rawData);\n break;\n }\n }\n}\n\nfunction installHasOne(\n instance: Model,\n assoc: Association,\n rawData: Record<string, unknown>,\n): void {\n const AssocModel = assoc.associatedModel!;\n const name = assoc.associationName;\n const getterName = assoc.getterName;\n const setterName = assoc.setterName;\n\n // Initialise storage\n instance.$associations.set(name, null as any);\n\n // Getter\n (instance as any)[getterName] = function (): Model | null {\n return (instance.$associations.get(name) as Model) ?? null;\n };\n\n // Setter\n (instance as any)[setterName] = function (child: Model): void {\n instance.$associations.set(name, child);\n // Set foreignKey on child pointing back to this parent\n const parentId = instance.get(assoc.primaryKey);\n if (parentId !== undefined && child.$fieldMap?.has(assoc.foreignKey)) {\n child.set(assoc.foreignKey, parentId);\n }\n };\n\n // Load from nested data\n const nestedData = rawData[name];\n if (nestedData && typeof nestedData === 'object' && !Array.isArray(nestedData)) {\n const childData = { ...nestedData as Record<string, unknown> };\n // Set foreignKey\n const parentId = instance.get(assoc.primaryKey);\n if (parentId !== undefined) {\n childData[assoc.foreignKey] = parentId;\n }\n const child = AssocModel.create(childData);\n instance.$associations.set(name, child);\n }\n\n // Cascade destroy\n if (assoc.cascade) {\n instance.$destroyHooks.push(() => {\n const child = instance.$associations.get(name) as Model | null;\n if (child && !child.isDestroyed) child.destroy();\n });\n }\n}\n\nfunction installHasMany(\n instance: Model,\n assoc: Association,\n rawData: Record<string, unknown>,\n): void {\n const AssocModel = assoc.associatedModel!;\n const name = assoc.associationName;\n const collection = new ModelCollection();\n instance.$associations.set(name, collection);\n\n // Collection accessor — wraps add() to auto-set foreignKey\n const wrappedCollection = {\n getCount: () => collection.getCount(),\n getAll: () => collection.getAll(),\n getById: (id: string | number) => collection.getById(id),\n filter: (fn: (record: Model) => boolean) => collection.filter(fn),\n add(child: Model) {\n const parentId = instance.get(assoc.primaryKey);\n if (parentId !== undefined && child.$fieldMap?.has(assoc.foreignKey)) {\n child.set(assoc.foreignKey, parentId);\n }\n collection.add(child);\n },\n remove(child: Model) {\n collection.remove(child);\n },\n };\n\n // Accessor method (e.g., user.orders())\n (instance as any)[name] = function () {\n return wrappedCollection;\n };\n\n // Load from nested data\n const nestedData = rawData[name];\n if (Array.isArray(nestedData)) {\n const parentId = instance.get(assoc.primaryKey);\n for (const itemData of nestedData) {\n if (typeof itemData === 'object' && itemData !== null) {\n const childData = { ...itemData as Record<string, unknown> };\n if (parentId !== undefined) {\n childData[assoc.foreignKey] = parentId;\n }\n const child = AssocModel.create(childData);\n collection.add(child);\n }\n }\n }\n\n // Cascade destroy\n if (assoc.cascade) {\n instance.$destroyHooks.push(() => {\n collection.destroyAll();\n });\n }\n}\n\nfunction installBelongsTo(\n instance: Model,\n assoc: Association,\n rawData: Record<string, unknown>,\n): void {\n const AssocModel = assoc.associatedModel!;\n const name = assoc.associationName;\n const getterName = assoc.getterName;\n const setterName = assoc.setterName;\n\n // Initialise storage\n instance.$associations.set(name, null as any);\n\n // Getter\n (instance as any)[getterName] = function (): Model | null {\n return (instance.$associations.get(name) as Model) ?? null;\n };\n\n // Setter\n (instance as any)[setterName] = function (parent: Model): void {\n instance.$associations.set(name, parent);\n // Update foreignKey on self\n const parentId = parent.get(assoc.primaryKey);\n if (parentId !== undefined && instance.$fieldMap?.has(assoc.foreignKey)) {\n instance.set(assoc.foreignKey, parentId);\n }\n };\n\n // Load from nested data\n const nestedData = rawData[name];\n if (nestedData && typeof nestedData === 'object' && !Array.isArray(nestedData)) {\n const parent = AssocModel.create(nestedData as Record<string, unknown>);\n instance.$associations.set(name, parent);\n }\n}\n\nfunction installManyToMany(\n instance: Model,\n assoc: Association,\n rawData: Record<string, unknown>,\n): void {\n const AssocModel = assoc.associatedModel!;\n const name = assoc.associationName;\n const collection = new ManyToManyCollection();\n instance.$associations.set(name, collection);\n\n // Accessor method\n (instance as any)[name] = function () {\n return collection;\n };\n\n // Load from nested data\n const nestedData = rawData[name];\n if (Array.isArray(nestedData)) {\n for (const itemData of nestedData) {\n if (typeof itemData === 'object' && itemData !== null) {\n const child = AssocModel.create(itemData as Record<string, unknown>);\n collection.link(child);\n }\n }\n }\n}\n","/**\n * @framesquared/data – Field system\n *\n * Defines field types with type coercion, serialization, and defaults.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// ---------------------------------------------------------------------------\n// FieldType enum\n// ---------------------------------------------------------------------------\n\nexport enum FieldType {\n STRING = 'string',\n INT = 'int',\n FLOAT = 'float',\n BOOLEAN = 'boolean',\n DATE = 'date',\n AUTO = 'auto',\n}\n\n// ---------------------------------------------------------------------------\n// Validator type (function signature)\n// ---------------------------------------------------------------------------\n\nexport type Validator = (value: unknown, record?: any) => string | null;\n\n// ---------------------------------------------------------------------------\n// FieldDefinition\n// ---------------------------------------------------------------------------\n\nexport interface FieldDefinition {\n name: string;\n type?: FieldType;\n defaultValue?: unknown;\n convert?: (value: unknown, record?: any) => unknown;\n serialize?: (value: unknown, record?: any) => unknown;\n mapping?: string;\n persist?: boolean;\n critical?: boolean;\n allowNull?: boolean;\n sortType?: string;\n validators?: Validator[];\n}\n\n// ---------------------------------------------------------------------------\n// Base Field class\n// ---------------------------------------------------------------------------\n\nexport abstract class Field {\n readonly name: string;\n readonly type: FieldType;\n readonly mapping: string | undefined;\n readonly persist: boolean;\n readonly critical: boolean;\n readonly allowNull: boolean;\n readonly sortType: string | undefined;\n readonly validators: Validator[];\n private readonly customConvert?: (value: unknown, record?: any) => unknown;\n private readonly customSerialize?: (value: unknown, record?: any) => unknown;\n private readonly customDefault: unknown;\n\n constructor(def: FieldDefinition) {\n this.name = def.name;\n this.type = def.type ?? FieldType.AUTO;\n this.mapping = def.mapping;\n this.persist = def.persist ?? true;\n this.critical = def.critical ?? false;\n this.allowNull = def.allowNull ?? false;\n this.sortType = def.sortType;\n this.validators = def.validators ?? [];\n this.customConvert = def.convert;\n this.customSerialize = def.serialize;\n this.customDefault = def.defaultValue;\n }\n\n /** Type-specific default (overridden by subclasses). */\n get defaultValue(): unknown {\n return this.customDefault !== undefined ? this.customDefault : this.getTypeDefault();\n }\n\n /** Subclass provides the type-specific default. */\n protected abstract getTypeDefault(): unknown;\n\n /**\n * Converts a raw value to the field's type.\n * If a custom `convert` was specified in the definition, it is used.\n * Otherwise delegates to the subclass's `coerce()`.\n */\n convert(value: unknown, record?: any): unknown {\n if (this.customConvert) {\n return this.customConvert(value, record);\n }\n if (value === null && this.allowNull) return null;\n if (value === undefined) return this.defaultValue;\n return this.coerce(value);\n }\n\n /** Type-specific coercion (subclasses override). */\n protected abstract coerce(value: unknown): unknown;\n\n /**\n * Serializes a value for transport.\n */\n serialize(value: unknown, record?: any): unknown {\n if (this.customSerialize) {\n return this.customSerialize(value, record);\n }\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// StringField\n// ---------------------------------------------------------------------------\n\nexport class StringField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.STRING });\n }\n\n protected getTypeDefault(): unknown { return ''; }\n\n protected coerce(value: unknown): unknown {\n if (value === null) return '';\n return String(value);\n }\n}\n\n// ---------------------------------------------------------------------------\n// IntField\n// ---------------------------------------------------------------------------\n\nexport class IntField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.INT });\n }\n\n protected getTypeDefault(): unknown { return 0; }\n\n protected coerce(value: unknown): unknown {\n if (value === null) return 0;\n if (typeof value === 'boolean') return value ? 1 : 0;\n const n = parseInt(String(value), 10);\n return Number.isNaN(n) ? 0 : n;\n }\n}\n\n// ---------------------------------------------------------------------------\n// FloatField\n// ---------------------------------------------------------------------------\n\nexport class FloatField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.FLOAT });\n }\n\n protected getTypeDefault(): unknown { return 0; }\n\n protected coerce(value: unknown): unknown {\n if (value === null) return 0;\n if (typeof value === 'boolean') return value ? 1 : 0;\n const n = parseFloat(String(value));\n return Number.isNaN(n) ? 0 : n;\n }\n}\n\n// ---------------------------------------------------------------------------\n// BooleanField\n// ---------------------------------------------------------------------------\n\nconst FALSE_STRINGS = new Set(['false', '0', 'no', 'off', '']);\n\nexport class BooleanField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.BOOLEAN });\n }\n\n protected getTypeDefault(): unknown { return false; }\n\n protected coerce(value: unknown): unknown {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') {\n return !FALSE_STRINGS.has(value.toLowerCase());\n }\n return Boolean(value);\n }\n}\n\n// ---------------------------------------------------------------------------\n// DateField\n// ---------------------------------------------------------------------------\n\nexport class DateField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.DATE });\n }\n\n protected getTypeDefault(): unknown { return null; }\n\n protected coerce(value: unknown): unknown {\n if (value instanceof Date) return value;\n if (typeof value === 'number') return new Date(value);\n if (typeof value === 'string') {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n return null;\n }\n\n override serialize(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// AutoField\n// ---------------------------------------------------------------------------\n\nexport class AutoField extends Field {\n constructor(def: Omit<FieldDefinition, 'type'> & { type?: FieldType }) {\n super({ ...def, type: FieldType.AUTO });\n }\n\n protected getTypeDefault(): unknown { return undefined; }\n\n protected coerce(value: unknown): unknown {\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// createField factory\n// ---------------------------------------------------------------------------\n\nconst FIELD_CONSTRUCTORS: Record<string, new (def: FieldDefinition) => Field> = {\n [FieldType.STRING]: StringField,\n [FieldType.INT]: IntField,\n [FieldType.FLOAT]: FloatField,\n [FieldType.BOOLEAN]: BooleanField,\n [FieldType.DATE]: DateField,\n [FieldType.AUTO]: AutoField,\n};\n\n/**\n * Creates a Field instance from a definition or shorthand string.\n */\nexport function createField(def: FieldDefinition | string): Field {\n if (typeof def === 'string') {\n return new AutoField({ name: def });\n }\n const type = def.type ?? FieldType.AUTO;\n const Ctor = FIELD_CONSTRUCTORS[type] ?? AutoField;\n return new Ctor(def);\n}\n","/**\n * @framesquared/data – Association (base class)\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\n\nexport interface AssociationConfig {\n model: string | typeof Model;\n foreignKey: string;\n primaryKey?: string;\n getterName?: string;\n setterName?: string;\n cascade?: boolean;\n /** For ManyToMany: junction model name or class */\n through?: string;\n /** For ManyToMany: the other foreign key in the junction */\n otherKey?: string;\n}\n\nexport type AssociationType = 'hasOne' | 'hasMany' | 'belongsTo' | 'manyToMany';\n\nexport class Association {\n readonly type: AssociationType;\n readonly config: AssociationConfig;\n readonly ownerModelName: string;\n\n /** Resolved associated model class (may be null until forward ref resolves). */\n associatedModel: typeof Model | null = null;\n\n constructor(type: AssociationType, ownerModelName: string, config: AssociationConfig) {\n this.type = type;\n this.ownerModelName = ownerModelName;\n this.config = config;\n }\n\n /**\n * The property name used for nested JSON loading and as the\n * default getter/collection accessor name.\n */\n get associationName(): string {\n if (!this.associatedModel) return '';\n // Derive from classname: 'test.Address' → 'address', 'test.Order' → 'orders'\n const raw = this.associatedModel.$className.split('.').pop()!;\n const lower = raw[0].toLowerCase() + raw.slice(1);\n if (this.type === 'hasMany' || this.type === 'manyToMany') {\n // Simple pluralise: add 's'\n return lower.endsWith('s') ? lower : lower + 's';\n }\n return lower;\n }\n\n get getterName(): string {\n if (this.config.getterName) return this.config.getterName;\n const name = this.associationName;\n return `get${name[0].toUpperCase()}${name.slice(1)}`;\n }\n\n get setterName(): string {\n if (this.config.setterName) return this.config.setterName;\n const name = this.associationName;\n return `set${name[0].toUpperCase()}${name.slice(1)}`;\n }\n\n get foreignKey(): string {\n return this.config.foreignKey;\n }\n\n get primaryKey(): string {\n return this.config.primaryKey ?? 'id';\n }\n\n get cascade(): boolean {\n return this.config.cascade ?? false;\n }\n}\n","/**\n * @framesquared/data – HasOne association\n */\nimport { Association } from './Association.js';\nimport type { AssociationConfig } from './Association.js';\n\nexport class HasOne extends Association {\n constructor(ownerModelName: string, config: AssociationConfig) {\n super('hasOne', ownerModelName, config);\n }\n}\n","/**\n * @framesquared/data – HasMany association\n */\nimport { Association } from './Association.js';\nimport type { AssociationConfig } from './Association.js';\n\nexport class HasMany extends Association {\n constructor(ownerModelName: string, config: AssociationConfig) {\n super('hasMany', ownerModelName, config);\n }\n}\n","/**\n * @framesquared/data – BelongsTo association\n */\nimport { Association } from './Association.js';\nimport type { AssociationConfig } from './Association.js';\n\nexport class BelongsTo extends Association {\n constructor(ownerModelName: string, config: AssociationConfig) {\n super('belongsTo', ownerModelName, config);\n }\n}\n","/**\n * @framesquared/data – ManyToMany association\n */\nimport { Association } from './Association.js';\nimport type { AssociationConfig } from './Association.js';\n\nexport class ManyToMany extends Association {\n constructor(ownerModelName: string, config: AssociationConfig) {\n super('manyToMany', ownerModelName, config);\n }\n\n get through(): string {\n return this.config.through ?? '';\n }\n\n get otherKey(): string {\n return this.config.otherKey ?? '';\n }\n}\n","/**\n * @framesquared/data – Schema\n *\n * Singleton registry for Model classes and their associations.\n * Handles forward references: if Model A declares an association to\n * Model B by string name before B is registered, the reference is\n * resolved when B is later registered.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from './Model.js';\nimport { Association } from './association/Association.js';\nimport type { AssociationConfig } from './association/Association.js';\nimport { HasOne } from './association/HasOne.js';\nimport { HasMany } from './association/HasMany.js';\nimport { BelongsTo } from './association/BelongsTo.js';\nimport { ManyToMany } from './association/ManyToMany.js';\n\n// ---------------------------------------------------------------------------\n// Internal storage\n// ---------------------------------------------------------------------------\n\n/** className → Model class */\nconst models = new Map<string, typeof Model>();\n\n/** className → Association[] (owned by that model) */\nconst associations = new Map<string, Association[]>();\n\n/** modelName → list of unresolved Association references waiting for it */\nconst pendingReferences = new Map<string, Association[]>();\n\n// ---------------------------------------------------------------------------\n// SchemaImpl\n// ---------------------------------------------------------------------------\n\nclass SchemaImpl {\n /**\n * Registers a Model class and processes its association declarations.\n * If the model has `static hasOne`, `static hasMany`, `static belongsTo`,\n * or `static manyToMany` arrays, creates Association instances for each.\n */\n register(ModelClass: typeof Model): void {\n const name = ModelClass.$className;\n models.set(name, ModelClass);\n\n // Process association declarations\n this.processAssociations(ModelClass, 'hasOne', HasOne);\n this.processAssociations(ModelClass, 'hasMany', HasMany);\n this.processAssociations(ModelClass, 'belongsTo', BelongsTo);\n this.processAssociations(ModelClass, 'manyToMany', ManyToMany);\n\n // Resolve any pending forward references to this model\n const pending = pendingReferences.get(name);\n if (pending) {\n for (const assoc of pending) {\n assoc.associatedModel = ModelClass;\n }\n pendingReferences.delete(name);\n }\n }\n\n /**\n * Retrieves a registered Model class by name.\n */\n get(name: string): typeof Model | undefined {\n return models.get(name);\n }\n\n /**\n * Returns all Association instances owned by the given model name.\n */\n getAssociations(modelName: string): Association[] {\n return associations.get(modelName) ?? [];\n }\n\n /**\n * Clears all registrations (for testing).\n */\n clear(): void {\n models.clear();\n associations.clear();\n pendingReferences.clear();\n }\n\n // -----------------------------------------------------------------------\n // Internal: process static association arrays\n // -----------------------------------------------------------------------\n\n private processAssociations(\n ModelClass: typeof Model,\n staticProp: string,\n AssocClass: new (ownerName: string, config: AssociationConfig) => Association,\n ): void {\n const configs = (ModelClass as any)[staticProp] as AssociationConfig[] | undefined;\n if (!configs || !Array.isArray(configs)) return;\n\n const ownerName = ModelClass.$className;\n if (!associations.has(ownerName)) {\n associations.set(ownerName, []);\n }\n const list = associations.get(ownerName)!;\n\n for (const config of configs) {\n const assoc = new AssocClass(ownerName, config);\n\n // Resolve model reference\n const modelRef = config.model;\n if (typeof modelRef === 'string') {\n const resolved = models.get(modelRef);\n if (resolved) {\n assoc.associatedModel = resolved;\n } else {\n // Forward reference — park it for later resolution\n if (!pendingReferences.has(modelRef)) {\n pendingReferences.set(modelRef, []);\n }\n pendingReferences.get(modelRef)!.push(assoc);\n }\n } else {\n // Direct class reference\n assoc.associatedModel = modelRef as typeof Model;\n }\n\n list.push(assoc);\n }\n }\n}\n\n/** Singleton. */\nexport const Schema = new SchemaImpl();\n","/**\n * @framesquared/data – ModelCollection\n *\n * A lightweight collection of Model instances, used by HasMany and\n * ManyToMany associations. Provides add/remove/filter/getById.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from './Model.js';\n\nexport class ModelCollection {\n private items: Model[] = [];\n\n getCount(): number {\n return this.items.length;\n }\n\n getAll(): Model[] {\n return [...this.items];\n }\n\n add(record: Model): void {\n if (!this.items.includes(record)) {\n this.items.push(record);\n }\n }\n\n remove(record: Model): void {\n const idx = this.items.indexOf(record);\n if (idx !== -1) this.items.splice(idx, 1);\n }\n\n getById(id: string | number): Model | undefined {\n return this.items.find((r) => r.getId() === id);\n }\n\n filter(fn: (record: Model) => boolean): Model[] {\n return this.items.filter(fn);\n }\n\n destroyAll(): void {\n for (const item of this.items) {\n if (!item.isDestroyed) item.destroy();\n }\n this.items.length = 0;\n }\n}\n\n/**\n * Extended collection for ManyToMany that exposes link/unlink semantics.\n */\nexport class ManyToManyCollection extends ModelCollection {\n private junctions: Map<Model, any> = new Map();\n\n link(record: Model, _junctionData?: Record<string, unknown>): void {\n this.add(record);\n this.junctions.set(record, _junctionData ?? {});\n }\n\n unlink(record: Model): void {\n this.remove(record);\n this.junctions.delete(record);\n }\n}\n","/**\n * @framesquared/data – Built-in validators\n *\n * Each factory returns a Validator function: (value) => errorMsg | null\n */\n\nimport type { Validator } from './field/Field.js';\n\n/**\n * Value must not be null, undefined, or empty string.\n */\nexport function presence(message = 'is required'): Validator {\n return (value: unknown) => {\n if (value === null || value === undefined || value === '') {\n return message;\n }\n return null;\n };\n}\n\n/**\n * String length must be within min/max bounds.\n */\nexport function length(opts: { min?: number; max?: number; message?: string }): Validator {\n return (value: unknown) => {\n const str = String(value ?? '');\n if (opts.min !== undefined && str.length < opts.min) {\n return opts.message ?? `must be at least ${opts.min} characters`;\n }\n if (opts.max !== undefined && str.length > opts.max) {\n return opts.message ?? `must be at most ${opts.max} characters`;\n }\n return null;\n };\n}\n\n/**\n * Value must match the given regex.\n */\nexport function formatValidator(pattern: RegExp, message?: string): Validator {\n return (value: unknown) => {\n if (!pattern.test(String(value ?? ''))) {\n return message ?? `does not match the required format`;\n }\n return null;\n };\n}\n\n/**\n * Value must be in the allowed list.\n */\nexport function inclusion(list: unknown[], message?: string): Validator {\n return (value: unknown) => {\n if (!list.includes(value)) {\n return message ?? `must be one of: ${list.join(', ')}`;\n }\n return null;\n };\n}\n\n/**\n * Value must NOT be in the disallowed list.\n */\nexport function exclusion(list: unknown[], message?: string): Validator {\n return (value: unknown) => {\n if (list.includes(value)) {\n return message ?? `is not allowed`;\n }\n return null;\n };\n}\n\n/**\n * Numeric value must be within min/max.\n */\nexport function rangeValidator(opts: { min?: number; max?: number; message?: string }): Validator {\n return (value: unknown) => {\n const n = Number(value);\n if (opts.min !== undefined && n < opts.min) {\n return opts.message ?? `must be at least ${opts.min}`;\n }\n if (opts.max !== undefined && n > opts.max) {\n return opts.message ?? `must be at most ${opts.max}`;\n }\n return null;\n };\n}\n\n/**\n * Basic email format check.\n */\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\nexport function email(message = 'is not a valid email address'): Validator {\n return (value: unknown) => {\n if (!EMAIL_RE.test(String(value ?? ''))) {\n return message;\n }\n return null;\n };\n}\n","/**\n * @framesquared/data – Store\n *\n * A client-side collection of Model records with sorting, filtering,\n * grouping, events, and sync/change tracking.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Base, Observable } from '@framesquared/core';\nimport type { Model } from '../Model.js';\nimport { Collection } from './Collection.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface Sorter {\n property: string;\n direction: 'ASC' | 'DESC';\n sorterFn?: (a: Model, b: Model) => number;\n}\n\nexport type FilterOperator = '=' | '!=' | '<' | '<=' | '>' | '>=' | 'like' | 'in' | 'notin';\n\nexport interface Filter {\n property: string;\n value: unknown;\n operator?: FilterOperator;\n filterFn?: (record: Model) => boolean;\n anyMatch?: boolean;\n caseSensitive?: boolean;\n}\n\nexport interface Group {\n name: string;\n children: Model[];\n}\n\nexport interface StoreConfig {\n model: typeof Model;\n data?: Record<string, unknown>[];\n}\n\n// ---------------------------------------------------------------------------\n// Observable bootstrap — install mixin once on Store.prototype\n// ---------------------------------------------------------------------------\n\nconst ObservableMixin: typeof Base = Observable;\n\nfunction ensureObservable(instance: Store): void {\n const proto = ObservableMixin.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (name === 'constructor') continue;\n if (name in instance) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (desc && typeof desc.value === 'function') {\n (instance as any)[name] = desc.value.bind(instance);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Filter matching\n// ---------------------------------------------------------------------------\n\nfunction matchFilter(record: Model, f: Filter): boolean {\n if (f.filterFn) return f.filterFn(record);\n\n const fieldValue = record.get(f.property);\n const filterValue = f.value;\n const op = f.operator ?? '=';\n const ci = !(f.caseSensitive ?? false);\n\n switch (op) {\n case '=':\n return fieldValue === filterValue;\n case '!=':\n return fieldValue !== filterValue;\n case '<':\n return (fieldValue as number) < (filterValue as number);\n case '<=':\n return (fieldValue as number) <= (filterValue as number);\n case '>':\n return (fieldValue as number) > (filterValue as number);\n case '>=':\n return (fieldValue as number) >= (filterValue as number);\n case 'like': {\n const sv = ci ? String(fieldValue).toLowerCase() : String(fieldValue);\n const fv = ci ? String(filterValue).toLowerCase() : String(filterValue);\n return sv.includes(fv);\n }\n case 'in':\n return Array.isArray(filterValue) && filterValue.includes(fieldValue);\n case 'notin':\n return Array.isArray(filterValue) && !filterValue.includes(fieldValue);\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sorter comparator builder\n// ---------------------------------------------------------------------------\n\nfunction buildComparator(sorters: Sorter[]): (a: Model, b: Model) => number {\n return (a: Model, b: Model) => {\n for (const sorter of sorters) {\n if (sorter.sorterFn) {\n const result = sorter.sorterFn(a, b);\n if (result !== 0) return result;\n continue;\n }\n const va = a.get(sorter.property) as string | number;\n const vb = b.get(sorter.property) as string | number;\n const dir = sorter.direction === 'DESC' ? -1 : 1;\n if (va < vb) return -1 * dir;\n if (va > vb) return 1 * dir;\n }\n return 0;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\nexport class Store extends Base {\n static override $className = 'Ext.data.Store';\n\n private ModelClass: typeof Model;\n private data: Collection<Model>;\n private allData: Collection<Model>; // unfiltered snapshot\n private currentSorters: Sorter[] = [];\n private currentFilters: Filter[] = [];\n private groupField: string | null = null;\n private groupDirection: 'ASC' | 'DESC' = 'ASC';\n private cachedGroups: Group[] | null = null;\n private removedRecords: Model[] = [];\n\n // Observable state (populated by ensureObservable)\n $destroyHooks: (() => void)[] = [];\n\n constructor(config: StoreConfig) {\n super();\n ensureObservable(this);\n\n this.ModelClass = config.model;\n this.data = new Collection<Model>((r) => r.getId());\n this.allData = new Collection<Model>((r) => r.getId());\n\n if (config.data) {\n this.loadData(config.data);\n }\n }\n\n // -----------------------------------------------------------------------\n // Data loading\n // -----------------------------------------------------------------------\n\n private loadData(rawRecords: Record<string, unknown>[]): void {\n for (const raw of rawRecords) {\n const record = this.ModelClass.create(raw);\n this.data.add(record);\n this.allData.add(record);\n }\n }\n\n // -----------------------------------------------------------------------\n // CRUD\n // -----------------------------------------------------------------------\n\n add(...records: Model[]): Model[] {\n for (const record of records) {\n this.data.add(record);\n this.allData.add(record);\n }\n this.invalidateGroups();\n this.fire('add', this, records);\n this.fire('datachanged', this);\n return records;\n }\n\n insert(index: number, ...records: Model[]): Model[] {\n for (let i = 0; i < records.length; i++) {\n this.data.insert(index + i, records[i]);\n this.allData.add(records[i]);\n }\n this.invalidateGroups();\n this.fire('add', this, records, index);\n this.fire('datachanged', this);\n return records;\n }\n\n remove(...records: Model[]): Model[] {\n const removed: Model[] = [];\n for (const record of records) {\n if (this.data.remove(record)) {\n this.allData.remove(record);\n removed.push(record);\n if (!record.phantom) {\n this.removedRecords.push(record);\n }\n }\n }\n if (removed.length > 0) {\n this.invalidateGroups();\n this.fire('remove', this, removed);\n this.fire('datachanged', this);\n }\n return removed;\n }\n\n removeAt(index: number, count = 1): Model[] {\n const removed = this.data.removeAt(index, count);\n for (const record of removed) {\n this.allData.remove(record);\n if (!record.phantom) {\n this.removedRecords.push(record);\n }\n }\n if (removed.length > 0) {\n this.invalidateGroups();\n this.fire('remove', this, removed);\n this.fire('datachanged', this);\n }\n return removed;\n }\n\n removeAll(silent?: boolean): void {\n this.data.clear();\n this.allData.clear();\n this.invalidateGroups();\n if (!silent) {\n this.fire('clear', this);\n this.fire('datachanged', this);\n }\n }\n\n // -----------------------------------------------------------------------\n // Lookup\n // -----------------------------------------------------------------------\n\n getAt(index: number): Model | undefined {\n return this.data.getAt(index);\n }\n\n getById(id: string | number): Model | undefined {\n return this.data.getByKey(id);\n }\n\n getRange(start?: number, end?: number): Model[] {\n return this.data.getRange(start, end);\n }\n\n getCount(): number {\n return this.data.getCount();\n }\n\n getTotalCount(): number {\n return this.allData.getCount();\n }\n\n indexOf(record: Model): number {\n return this.data.indexOf(record);\n }\n\n contains(record: Model): boolean {\n return this.data.contains(record);\n }\n\n first(): Model | undefined {\n return this.data.first();\n }\n\n last(): Model | undefined {\n return this.data.last();\n }\n\n each(fn: (record: Model, index: number) => boolean | void): void {\n this.data.each(fn);\n }\n\n collect(fieldName: string): unknown[] {\n const seen = new Set<unknown>();\n this.data.each((r) => {\n seen.add(r.get(fieldName));\n });\n return [...seen];\n }\n\n getData(): Collection<Model> {\n return this.data;\n }\n\n // -----------------------------------------------------------------------\n // Sorting\n // -----------------------------------------------------------------------\n\n sort(fieldOrSorters?: string | Sorter[], direction: 'ASC' | 'DESC' = 'ASC'): void {\n if (typeof fieldOrSorters === 'string') {\n this.currentSorters = [{ property: fieldOrSorters, direction }];\n } else if (Array.isArray(fieldOrSorters)) {\n this.currentSorters = fieldOrSorters;\n }\n\n if (this.currentSorters.length > 0) {\n this.data.sort(buildComparator(this.currentSorters));\n }\n this.invalidateGroups();\n this.fire('sort', this, this.currentSorters);\n }\n\n getSorters(): Sorter[] {\n return [...this.currentSorters];\n }\n\n // -----------------------------------------------------------------------\n // Filtering\n // -----------------------------------------------------------------------\n\n filter(fieldOrFilters: string | Filter[], value?: unknown): void {\n if (typeof fieldOrFilters === 'string') {\n this.currentFilters = [{ property: fieldOrFilters, value }];\n } else {\n this.currentFilters = fieldOrFilters;\n }\n this.applyFilters();\n this.fire('filter', this, this.currentFilters);\n }\n\n clearFilter(suppressEvent?: boolean): void {\n this.currentFilters = [];\n this.applyFilters();\n if (!suppressEvent) {\n this.fire('filter', this, []);\n }\n }\n\n getFilters(): Filter[] {\n return [...this.currentFilters];\n }\n\n private applyFilters(): void {\n if (this.currentFilters.length === 0) {\n // Restore all data\n this.data = new Collection<Model>((r) => r.getId());\n this.allData.each((r) => this.data.add(r));\n } else {\n this.data = new Collection<Model>((r) => r.getId());\n this.allData.each((r) => {\n const passes = this.currentFilters.every((f) => matchFilter(r, f));\n if (passes) this.data.add(r);\n });\n }\n\n // Re-apply sort if active\n if (this.currentSorters.length > 0) {\n this.data.sort(buildComparator(this.currentSorters));\n }\n\n this.invalidateGroups();\n }\n\n // -----------------------------------------------------------------------\n // Grouping\n // -----------------------------------------------------------------------\n\n group(field: string, direction: 'ASC' | 'DESC' = 'ASC'): void {\n this.groupField = field;\n this.groupDirection = direction;\n this.invalidateGroups();\n this.fire('groupchange', this, field, direction);\n }\n\n clearGrouping(): void {\n this.groupField = null;\n this.cachedGroups = null;\n this.fire('groupchange', this, null, null);\n }\n\n isGrouped(): boolean {\n return this.groupField !== null;\n }\n\n getGroups(): Group[] {\n if (!this.groupField) return [];\n if (this.cachedGroups) return this.cachedGroups;\n\n const map = new Map<string, Model[]>();\n this.data.each((r) => {\n const key = String(r.get(this.groupField!) ?? '');\n if (!map.has(key)) map.set(key, []);\n map.get(key)!.push(r);\n });\n\n const groups = [...map.entries()].map(([name, children]) => ({ name, children }));\n const dir = this.groupDirection === 'DESC' ? -1 : 1;\n groups.sort((a, b) => {\n if (a.name < b.name) return -1 * dir;\n if (a.name > b.name) return 1 * dir;\n return 0;\n });\n\n this.cachedGroups = groups;\n return groups;\n }\n\n private invalidateGroups(): void {\n this.cachedGroups = null;\n }\n\n // -----------------------------------------------------------------------\n // Sync / change tracking\n // -----------------------------------------------------------------------\n\n getModifiedRecords(): Model[] {\n const result: Model[] = [];\n this.data.each((r) => {\n if (r.isModified()) result.push(r);\n });\n return result;\n }\n\n getNewRecords(): Model[] {\n const result: Model[] = [];\n this.data.each((r) => {\n if (r.phantom) result.push(r);\n });\n return result;\n }\n\n getRemovedRecords(): Model[] {\n return [...this.removedRecords];\n }\n\n commitChanges(): void {\n this.data.each((r) => {\n if (r.isModified()) r.commit(true);\n });\n this.removedRecords.length = 0;\n }\n\n rejectChanges(): void {\n // Revert modified records\n this.data.each((r) => {\n if (r.isModified()) r.reject(true);\n });\n\n // Re-add removed records\n for (const record of this.removedRecords) {\n this.data.add(record);\n this.allData.add(record);\n }\n this.removedRecords.length = 0;\n this.invalidateGroups();\n }\n\n // -----------------------------------------------------------------------\n // Event helper\n // -----------------------------------------------------------------------\n\n private fire(eventName: string, ...args: unknown[]): void {\n if (typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent(eventName, ...args);\n }\n }\n}\n","/**\n * @framesquared/data – Collection\n *\n * An ordered, optionally keyed collection used internally by Store.\n * Provides add, insert, remove, sort, find, and iteration.\n */\n\nexport class Collection<T> {\n private items: T[] = [];\n private keyMap: Map<unknown, T> | null = null;\n private keyFn: ((item: T) => unknown) | undefined;\n\n constructor(keyFn?: (item: T) => unknown) {\n this.keyFn = keyFn;\n if (keyFn) {\n this.keyMap = new Map();\n }\n }\n\n getCount(): number {\n return this.items.length;\n }\n\n getAt(index: number): T | undefined {\n return this.items[index];\n }\n\n getByKey(key: unknown): T | undefined {\n return this.keyMap?.get(key);\n }\n\n indexOf(item: T): number {\n return this.items.indexOf(item);\n }\n\n contains(item: T): boolean {\n return this.items.includes(item);\n }\n\n add(item: T): void {\n this.items.push(item);\n if (this.keyFn && this.keyMap) {\n this.keyMap.set(this.keyFn(item), item);\n }\n }\n\n insert(index: number, item: T): void {\n this.items.splice(index, 0, item);\n if (this.keyFn && this.keyMap) {\n this.keyMap.set(this.keyFn(item), item);\n }\n }\n\n remove(item: T): T | undefined {\n const idx = this.items.indexOf(item);\n if (idx === -1) return undefined;\n this.items.splice(idx, 1);\n if (this.keyFn && this.keyMap) {\n this.keyMap.delete(this.keyFn(item));\n }\n return item;\n }\n\n removeAt(index: number, count = 1): T[] {\n const removed = this.items.splice(index, count);\n if (this.keyFn && this.keyMap) {\n for (const item of removed) {\n this.keyMap.delete(this.keyFn(item));\n }\n }\n return removed;\n }\n\n clear(): void {\n this.items.length = 0;\n this.keyMap?.clear();\n }\n\n toArray(): T[] {\n return [...this.items];\n }\n\n each(fn: (item: T, index: number) => boolean | void): void {\n for (let i = 0; i < this.items.length; i++) {\n if (fn(this.items[i], i) === false) break;\n }\n }\n\n find(fn: (item: T) => boolean): T | undefined {\n return this.items.find(fn);\n }\n\n filter(fn: (item: T) => boolean): T[] {\n return this.items.filter(fn);\n }\n\n sort(compareFn: (a: T, b: T) => number): void {\n this.items.sort(compareFn);\n }\n\n first(): T | undefined {\n return this.items[0];\n }\n\n last(): T | undefined {\n return this.items[this.items.length - 1];\n }\n\n getRange(start = 0, end?: number): T[] {\n return this.items.slice(start, end);\n }\n\n /** Rebuilds the key map (call after sort or external mutation). */\n rekey(): void {\n if (this.keyFn && this.keyMap) {\n this.keyMap.clear();\n for (const item of this.items) {\n this.keyMap.set(this.keyFn(item), item);\n }\n }\n }\n}\n","/**\n * @framesquared/data – ResultSet\n */\n\nimport type { Model } from './Model.js';\n\nexport interface ResultSetConfig {\n records: Model[];\n total?: number;\n success: boolean;\n message?: string;\n}\n\nexport class ResultSet {\n readonly records: Model[];\n readonly total: number;\n readonly success: boolean;\n readonly message: string | undefined;\n\n constructor(config: ResultSetConfig) {\n this.records = config.records;\n this.total = config.total ?? config.records.length;\n this.success = config.success;\n this.message = config.message;\n }\n}\n","/**\n * @framesquared/data – Readers\n *\n * Parse raw server response data into ResultSet instances.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\nimport { ResultSet } from '../ResultSet.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getNestedValue(obj: any, path: string): unknown {\n const segments = path.split('.');\n let current: any = obj;\n for (const seg of segments) {\n if (current == null || typeof current !== 'object') return undefined;\n current = current[seg];\n }\n return current;\n}\n\n// ---------------------------------------------------------------------------\n// JsonReader\n// ---------------------------------------------------------------------------\n\nexport interface JsonReaderConfig {\n model: typeof Model;\n rootProperty?: string;\n totalProperty?: string;\n successProperty?: string;\n messageProperty?: string;\n}\n\nexport class JsonReader {\n protected config: JsonReaderConfig;\n\n constructor(config: JsonReaderConfig) {\n this.config = config;\n }\n\n read(data: unknown): ResultSet {\n const { model, rootProperty, totalProperty, successProperty, messageProperty } = this.config;\n\n let rawRecords: any[];\n let total: number | undefined;\n let success = true;\n let message: string | undefined;\n\n if (rootProperty) {\n const root = getNestedValue(data, rootProperty);\n rawRecords = Array.isArray(root) ? root : [];\n } else {\n rawRecords = Array.isArray(data) ? data : [];\n }\n\n if (totalProperty && typeof data === 'object' && data !== null) {\n const t = getNestedValue(data, totalProperty);\n if (typeof t === 'number') total = t;\n }\n\n if (successProperty && typeof data === 'object' && data !== null) {\n const s = getNestedValue(data, successProperty);\n if (typeof s === 'boolean') success = s;\n }\n\n if (messageProperty && typeof data === 'object' && data !== null) {\n const m = getNestedValue(data, messageProperty);\n if (typeof m === 'string') message = m;\n }\n\n const records = rawRecords.map((raw) => model.create(raw));\n return new ResultSet({\n records,\n total: total ?? records.length,\n success,\n message,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// ArrayReader\n// ---------------------------------------------------------------------------\n\nexport interface ArrayReaderConfig {\n model: typeof Model;\n}\n\nexport class ArrayReader {\n private config: ArrayReaderConfig;\n\n constructor(config: ArrayReaderConfig) {\n this.config = config;\n }\n\n read(data: unknown[][]): ResultSet {\n const { model } = this.config;\n const fieldNames = (model as any).fields.map((f: any) =>\n typeof f === 'string' ? f : f.name,\n ) as string[];\n\n const records = data.map((row) => {\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < fieldNames.length; i++) {\n if (i < row.length) {\n obj[fieldNames[i]] = row[i];\n }\n }\n return model.create(obj);\n });\n\n return new ResultSet({ records, success: true });\n }\n}\n\n// ---------------------------------------------------------------------------\n// XmlReader\n// ---------------------------------------------------------------------------\n\nexport interface XmlReaderConfig {\n model: typeof Model;\n record: string;\n}\n\nexport class XmlReader {\n private config: XmlReaderConfig;\n\n constructor(config: XmlReaderConfig) {\n this.config = config;\n }\n\n read(xmlString: string): ResultSet {\n const { model, record: tagName } = this.config;\n const parser = new DOMParser();\n const doc = parser.parseFromString(xmlString, 'text/xml');\n const nodes = doc.getElementsByTagName(tagName);\n\n const fieldNames = (model as any).fields.map((f: any) =>\n typeof f === 'string' ? f : f.name,\n ) as string[];\n\n const records: Model[] = [];\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n const obj: Record<string, unknown> = {};\n for (const fieldName of fieldNames) {\n // Try exact tag match first, then first-letter tag ('n' for 'name')\n let el = node.getElementsByTagName(fieldName)[0];\n if (!el) {\n // Fallback: try single-char abbreviation\n el = node.getElementsByTagName(fieldName[0])[0] as Element;\n }\n if (el) {\n obj[fieldName] = el.textContent ?? '';\n }\n }\n records.push(model.create(obj));\n }\n\n return new ResultSet({ records, success: true });\n }\n}\n","/**\n * @framesquared/data – Writers\n *\n * Serialize Model records for transport to the server.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\n\n// ---------------------------------------------------------------------------\n// JsonWriter\n// ---------------------------------------------------------------------------\n\nexport interface JsonWriterConfig {\n writeAllFields?: boolean;\n allowSingle?: boolean;\n encode?: boolean;\n rootProperty?: string;\n}\n\nexport class JsonWriter {\n private config: JsonWriterConfig;\n\n constructor(config: JsonWriterConfig) {\n this.config = {\n writeAllFields: true,\n allowSingle: false,\n encode: false,\n ...config,\n };\n }\n\n write(records: Model[]): unknown {\n const serialized = records.map((r) => this.serializeRecord(r));\n\n let result: unknown;\n\n // allowSingle: unwrap single-element array\n if (this.config.allowSingle && serialized.length === 1) {\n result = serialized[0];\n } else {\n result = serialized;\n }\n\n // rootProperty: wrap under a key\n if (this.config.rootProperty) {\n result = { [this.config.rootProperty]: result };\n }\n\n // encode: convert to JSON string\n if (this.config.encode) {\n return JSON.stringify(result);\n }\n\n return result;\n }\n\n private serializeRecord(record: Model): Record<string, unknown> {\n if (this.config.writeAllFields) {\n return record.getData({ serialize: true });\n }\n\n // writeAllFields=false: only send changed fields + id\n const Ctor = record.constructor as typeof Model;\n const changes = record.getChanges();\n const result: Record<string, unknown> = {};\n\n // Always include the ID\n const idProp = Ctor.idProperty;\n result[idProp] = record.get(idProp);\n\n // Add changed fields\n for (const [key, value] of Object.entries(changes)) {\n result[key] = value;\n }\n\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// XmlWriter\n// ---------------------------------------------------------------------------\n\nexport interface XmlWriterConfig {\n documentRoot?: string;\n record?: string;\n}\n\nexport class XmlWriter {\n private config: XmlWriterConfig;\n\n constructor(config: XmlWriterConfig) {\n this.config = {\n documentRoot: 'xmlData',\n record: 'record',\n ...config,\n };\n }\n\n write(records: Model[]): string {\n const root = this.config.documentRoot!;\n const tag = this.config.record!;\n const parts: string[] = [`<${root}>`];\n\n for (const record of records) {\n parts.push(`<${tag}>`);\n const data = record.getData({ serialize: true });\n for (const [key, value] of Object.entries(data)) {\n parts.push(`<${key}>${escapeXml(String(value ?? ''))}</${key}>`);\n }\n parts.push(`</${tag}>`);\n }\n\n parts.push(`</${root}>`);\n return parts.join('');\n }\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n","/**\n * @framesquared/data – Proxy (abstract base)\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\n\nexport interface BatchOptions {\n create?: Model[];\n update?: Model[];\n destroy?: Model[];\n}\n\nexport interface Batch {\n success: boolean;\n operations: Operation[];\n}\n\nexport interface ProxyConfig {\n model: typeof Model;\n [key: string]: unknown;\n}\n\nexport abstract class Proxy {\n readonly model: typeof Model;\n\n constructor(config: ProxyConfig) {\n this.model = config.model;\n }\n\n abstract read(operation: Operation, signal?: AbortSignal): Promise<ResultSet>;\n abstract create(operation: Operation): Promise<ResultSet>;\n abstract update(operation: Operation): Promise<ResultSet>;\n abstract destroy(operation: Operation): Promise<ResultSet>;\n\n async batch(options: BatchOptions): Promise<Batch> {\n const { Operation: OpClass } = await import('../Operation.js');\n const operations: Operation[] = [];\n let allSuccess = true;\n\n if (options.create && options.create.length > 0) {\n const op = new OpClass({ action: 'create', records: options.create });\n const rs = await this.create(op);\n op.setResult(rs);\n operations.push(op);\n if (!rs.success) allSuccess = false;\n }\n\n if (options.update && options.update.length > 0) {\n const op = new OpClass({ action: 'update', records: options.update });\n const rs = await this.update(op);\n op.setResult(rs);\n operations.push(op);\n if (!rs.success) allSuccess = false;\n }\n\n if (options.destroy && options.destroy.length > 0) {\n const op = new OpClass({ action: 'destroy', records: options.destroy });\n const rs = await this.destroy(op);\n op.setResult(rs);\n operations.push(op);\n if (!rs.success) allSuccess = false;\n }\n\n return { success: allSuccess, operations };\n }\n}\n","/**\n * @framesquared/data – Client Proxies\n *\n * MemoryProxy, LocalStorageProxy, SessionStorageProxy\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\nimport { Proxy } from './Proxy.js';\nimport type { ProxyConfig } from './Proxy.js';\n\n// ---------------------------------------------------------------------------\n// MemoryProxy\n// ---------------------------------------------------------------------------\n\nexport interface MemoryProxyConfig extends ProxyConfig {\n data?: Record<string, unknown>[];\n}\n\nexport class MemoryProxy extends Proxy {\n private store: Record<string, unknown>[];\n\n constructor(config: MemoryProxyConfig) {\n super(config);\n this.store = config.data ? [...config.data] : [];\n }\n\n async read(operation: Operation): Promise<ResultSet> {\n let data = [...this.store];\n\n // Local filtering\n if (operation.filters && operation.filters.length > 0) {\n data = data.filter((raw) => {\n return operation.filters!.every((f: any) => {\n const fieldVal = raw[f.property];\n const op = f.operator ?? '=';\n switch (op) {\n case '=': return fieldVal === f.value;\n case '!=': return fieldVal !== f.value;\n case '<': return (fieldVal as number) < f.value;\n case '<=': return (fieldVal as number) <= f.value;\n case '>': return (fieldVal as number) > f.value;\n case '>=': return (fieldVal as number) >= f.value;\n default: return true;\n }\n });\n });\n }\n\n // Local sorting\n if (operation.sorters && operation.sorters.length > 0) {\n data.sort((a, b) => {\n for (const sorter of operation.sorters!) {\n const va = a[sorter.property] as string | number;\n const vb = b[sorter.property] as string | number;\n const dir = sorter.direction === 'DESC' ? -1 : 1;\n if (va < vb) return -1 * dir;\n if (va > vb) return 1 * dir;\n }\n return 0;\n });\n }\n\n const total = data.length;\n\n // Local paging\n if (operation.start !== undefined || operation.limit !== undefined) {\n const start = operation.start ?? 0;\n const limit = operation.limit ?? data.length;\n data = data.slice(start, start + limit);\n }\n\n const records = data.map((raw) => this.model.create(raw));\n return new ResultSet({ records, total, success: true });\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n for (const record of operation.records) {\n this.store.push(record.getData());\n }\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n for (const record of operation.records) {\n const id = record.getId();\n const idProp = (this.model as any).idProperty ?? 'id';\n const idx = this.store.findIndex((r) => r[idProp] === id);\n if (idx !== -1) {\n this.store[idx] = record.getData();\n }\n }\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n for (const record of operation.records) {\n const id = record.getId();\n const idProp = (this.model as any).idProperty ?? 'id';\n const idx = this.store.findIndex((r) => r[idProp] === id);\n if (idx !== -1) {\n this.store.splice(idx, 1);\n }\n }\n return new ResultSet({ records: operation.records, success: true });\n }\n}\n\n// ---------------------------------------------------------------------------\n// WebStorageProxy (shared logic for localStorage / sessionStorage)\n// ---------------------------------------------------------------------------\n\nexport interface WebStorageProxyConfig extends ProxyConfig {\n id: string;\n}\n\nabstract class WebStorageProxy extends Proxy {\n protected storageId: string;\n protected abstract getStorage(): Storage;\n\n constructor(config: WebStorageProxyConfig) {\n super(config);\n this.storageId = config.id;\n }\n\n private loadAll(): Record<string, unknown>[] {\n const raw = this.getStorage().getItem(this.storageId);\n if (!raw) return [];\n try {\n return JSON.parse(raw) as Record<string, unknown>[];\n } catch {\n return [];\n }\n }\n\n private saveAll(data: Record<string, unknown>[]): void {\n this.getStorage().setItem(this.storageId, JSON.stringify(data));\n }\n\n async read(_operation: Operation): Promise<ResultSet> {\n const data = this.loadAll();\n const records = data.map((raw) => this.model.create(raw));\n return new ResultSet({ records, success: true });\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n const data = this.loadAll();\n for (const record of operation.records) {\n data.push(record.getData({ serialize: true }));\n }\n this.saveAll(data);\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n const data = this.loadAll();\n const idProp = (this.model as any).idProperty ?? 'id';\n for (const record of operation.records) {\n const id = record.getId();\n const idx = data.findIndex((r) => r[idProp] === id);\n if (idx !== -1) {\n data[idx] = record.getData({ serialize: true });\n }\n }\n this.saveAll(data);\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n let data = this.loadAll();\n const idProp = (this.model as any).idProperty ?? 'id';\n for (const record of operation.records) {\n const id = record.getId();\n data = data.filter((r) => r[idProp] !== id);\n }\n this.saveAll(data);\n return new ResultSet({ records: operation.records, success: true });\n }\n}\n\n// ---------------------------------------------------------------------------\n// LocalStorageProxy\n// ---------------------------------------------------------------------------\n\nexport class LocalStorageProxy extends WebStorageProxy {\n protected getStorage(): Storage {\n return localStorage;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SessionStorageProxy\n// ---------------------------------------------------------------------------\n\nexport class SessionStorageProxy extends WebStorageProxy {\n protected getStorage(): Storage {\n return sessionStorage;\n }\n}\n","/**\n * @framesquared/data – Server Proxies\n *\n * AjaxProxy (fetch-based) and RestProxy (RESTful URL patterns).\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\nimport { JsonReader } from '../reader/Reader.js';\nimport { JsonWriter } from '../writer/Writer.js';\nimport { Proxy } from './Proxy.js';\nimport type { ProxyConfig } from './Proxy.js';\n\n// ---------------------------------------------------------------------------\n// AjaxProxy\n// ---------------------------------------------------------------------------\n\nexport interface AjaxProxyConfig extends ProxyConfig {\n url: string;\n api?: Partial<Record<string, string>>;\n headers?: Record<string, string>;\n timeout?: number;\n withCredentials?: boolean;\n}\n\nconst ACTION_METHODS: Record<string, string> = {\n read: 'GET',\n create: 'POST',\n update: 'PUT',\n destroy: 'DELETE',\n};\n\nexport class AjaxProxy extends Proxy {\n protected url: string;\n protected api: Partial<Record<string, string>>;\n protected headers: Record<string, string>;\n protected timeout: number;\n protected withCredentials: boolean;\n protected reader: JsonReader;\n protected writer: JsonWriter;\n\n constructor(config: AjaxProxyConfig) {\n super(config);\n this.url = config.url;\n this.api = config.api ?? {};\n this.headers = config.headers ?? {};\n this.timeout = config.timeout ?? 30000;\n this.withCredentials = config.withCredentials ?? false;\n this.reader = new JsonReader({ model: config.model });\n this.writer = new JsonWriter({});\n }\n\n async read(operation: Operation, signal?: AbortSignal): Promise<ResultSet> {\n return this.doRequest(operation, 'read', signal);\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n return this.doRequest(operation, 'create');\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n return this.doRequest(operation, 'update');\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n return this.doRequest(operation, 'destroy');\n }\n\n protected buildUrl(operation: Operation, action: string): string {\n const base = this.api[action] ?? this.url;\n const params = { ...operation.params };\n\n // Add paging params\n if (operation.start !== undefined) params.start = operation.start;\n if (operation.limit !== undefined) params.limit = operation.limit;\n if (operation.page !== undefined) params.page = operation.page;\n\n const qs = Object.entries(params)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join('&');\n\n return qs ? `${base}?${qs}` : base;\n }\n\n protected async doRequest(\n operation: Operation,\n action: string,\n signal?: AbortSignal,\n ): Promise<ResultSet> {\n const method = ACTION_METHODS[action] ?? 'GET';\n const url = this.buildUrl(operation, action);\n\n const init: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...this.headers,\n },\n credentials: this.withCredentials ? 'include' : 'same-origin',\n signal,\n };\n\n if (method !== 'GET' && operation.records.length > 0) {\n init.body = JSON.stringify(this.writer.write(operation.records));\n }\n\n try {\n const response = await fetch(url, init);\n\n if (!response.ok) {\n let message = `HTTP ${response.status}`;\n try {\n const body = await response.json();\n if (body?.message) message = body.message;\n } catch { /* ignore */ }\n return new ResultSet({ records: [], success: false, message });\n }\n\n const data = await response.json();\n\n // For read, parse through reader\n if (action === 'read') {\n return this.reader.read(data);\n }\n\n // For CUD, build a simple result\n const records = Array.isArray(data)\n ? data.map((d: any) => this.model.create(d))\n : data && typeof data === 'object' && 'id' in data\n ? [this.model.create(data)]\n : operation.records;\n\n return new ResultSet({ records, success: true });\n } catch (err: any) {\n return new ResultSet({\n records: [],\n success: false,\n message: err?.message ?? 'Unknown error',\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// RestProxy\n// ---------------------------------------------------------------------------\n\nexport interface RestProxyConfig extends AjaxProxyConfig {\n appendId?: boolean;\n}\n\nexport class RestProxy extends AjaxProxy {\n private appendId: boolean;\n\n constructor(config: RestProxyConfig) {\n super(config);\n this.appendId = config.appendId ?? true;\n }\n\n protected override buildUrl(operation: Operation, action: string): string {\n let base = this.api[action] ?? this.url;\n\n // Append record ID for single-record operations\n if (this.appendId && action !== 'create' && operation.records.length === 1) {\n const id = operation.records[0].getId();\n if (id !== undefined && id !== null && id !== 0 && id !== '') {\n base = `${base}/${id}`;\n }\n }\n\n // Add query params for read\n const params = { ...operation.params };\n if (operation.start !== undefined) params.start = operation.start;\n if (operation.limit !== undefined) params.limit = operation.limit;\n if (operation.page !== undefined) params.page = operation.page;\n\n const qs = Object.entries(params)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join('&');\n\n return qs ? `${base}?${qs}` : base;\n }\n}\n","/**\n * @framesquared/data – TreeStore\n *\n * Manages hierarchical (tree) data. Records are enhanced with\n * NodeInterface for parent/child navigation, expand/collapse,\n * and nested serialization.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Base, Observable } from '@framesquared/core';\nimport type { Model } from '../Model.js';\nimport { TreeModel } from '../model/TreeModel.js';\nimport { applyNodeInterface } from '../mixin/NodeInterface.js';\nimport type { NodeInterface } from '../mixin/NodeInterface.js';\n\n// ---------------------------------------------------------------------------\n// Observable bootstrap\n// ---------------------------------------------------------------------------\n\nconst ObservableMixin: typeof Base = Observable;\n\nfunction ensureObservable(instance: any): void {\n const proto = ObservableMixin.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (name === 'constructor') continue;\n if (name in instance) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (desc && typeof desc.value === 'function') {\n instance[name] = desc.value.bind(instance);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeStoreConfig {\n model?: typeof Model;\n root?: Record<string, unknown>;\n proxy?: any;\n}\n\n// ---------------------------------------------------------------------------\n// TreeStore\n// ---------------------------------------------------------------------------\n\nexport class TreeStore extends Base {\n static override $className = 'Ext.data.TreeStore';\n\n private ModelClass: typeof Model;\n private rootNode!: NodeInterface;\n private nodeMap = new Map<string | number, NodeInterface>();\n\n $destroyHooks: (() => void)[] = [];\n\n constructor(config: TreeStoreConfig) {\n super();\n ensureObservable(this);\n\n this.ModelClass = config.model ?? TreeModel;\n\n if (config.root) {\n this.replaceRoot(this.buildNode(config.root, 0));\n } else {\n // Create an empty root\n const empty = this.ModelClass.create({ id: '__root__', text: 'Root' });\n applyNodeInterface(empty, 0);\n this.replaceRoot(empty as any as NodeInterface);\n }\n }\n\n // -----------------------------------------------------------------------\n // Root\n // -----------------------------------------------------------------------\n\n getRoot(): NodeInterface {\n return this.rootNode;\n }\n\n getRootNode(): NodeInterface {\n return this.rootNode;\n }\n\n /**\n * Replaces the root with new data (or a pre-built node).\n * Fires 'rootchange'.\n */\n setRoot(nodeOrData: NodeInterface | Record<string, unknown>): NodeInterface {\n let node: NodeInterface;\n if (this.isNodeInterface(nodeOrData)) {\n node = nodeOrData;\n } else {\n node = this.buildNode(nodeOrData as Record<string, unknown>, 0);\n }\n this.replaceRoot(node);\n return node;\n }\n\n private isNodeInterface(value: unknown): value is NodeInterface {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'childNodes' in value &&\n 'parentNode' in value &&\n typeof (value as NodeInterface).isRoot === 'function'\n );\n }\n\n private replaceRoot(node: NodeInterface): void {\n this.rootNode = node;\n this.nodeMap.clear();\n this.registerRecursive(node);\n this.fire('rootchange', this, node);\n }\n\n // -----------------------------------------------------------------------\n // Lookup\n // -----------------------------------------------------------------------\n\n getNodeById(id: string | number): NodeInterface | undefined {\n return this.nodeMap.get(id);\n }\n\n // -----------------------------------------------------------------------\n // Tree operations\n // -----------------------------------------------------------------------\n\n appendChild(parent: NodeInterface, child: NodeInterface): void {\n parent.appendChild(child);\n this.registerRecursive(child);\n this.fire('nodeappend', this, child, parent);\n this.fire('datachanged', this);\n }\n\n removeChild(parent: NodeInterface, child: NodeInterface): void {\n parent.removeChild(child);\n this.unregisterRecursive(child);\n this.fire('noderemove', this, child, parent);\n this.fire('datachanged', this);\n }\n\n insertBefore(node: NodeInterface, refNode: NodeInterface): void {\n const parent = refNode.parentNode;\n if (!parent) return;\n parent.insertBefore(node, refNode);\n this.registerRecursive(node);\n this.fire('nodeinsert', this, node, refNode, parent);\n this.fire('datachanged', this);\n }\n\n // -----------------------------------------------------------------------\n // Expand / Collapse\n // -----------------------------------------------------------------------\n\n expandNode(node: NodeInterface): void {\n node.expanded = true;\n node.loaded = true;\n this.fire('nodeexpand', this, node);\n }\n\n collapseNode(node: NodeInterface): void {\n node.expanded = false;\n this.fire('nodecollapse', this, node);\n }\n\n // -----------------------------------------------------------------------\n // Deep search\n // -----------------------------------------------------------------------\n\n findNode(field: string, value: unknown): NodeInterface | undefined {\n return this.findNodeImpl(this.rootNode, field, value);\n }\n\n private findNodeImpl(\n node: NodeInterface,\n field: string,\n value: unknown,\n ): NodeInterface | undefined {\n const model = node as any as { get(f: string): unknown; getId(): unknown };\n const nodeValue = field === 'id' ? model.getId() : model.get(field);\n if (nodeValue === value) return node;\n for (const child of node.childNodes) {\n const found = this.findNodeImpl(child, field, value);\n if (found) return found;\n }\n return undefined;\n }\n\n // -----------------------------------------------------------------------\n // Collapse / Expand all\n // -----------------------------------------------------------------------\n\n collapseAll(): void {\n this.rootNode.cascadeBy((node) => {\n node.expanded = false;\n });\n }\n\n expandAll(): void {\n this.rootNode.cascadeBy((node) => {\n node.expanded = true;\n });\n }\n\n // -----------------------------------------------------------------------\n // Count helpers\n // -----------------------------------------------------------------------\n\n getCount(): number {\n return this.flattenNodes().length;\n }\n\n getTotalCount(): number {\n return this.nodeMap.size;\n }\n\n // -----------------------------------------------------------------------\n // Flatten (for rendering in a flat list / grid)\n // -----------------------------------------------------------------------\n\n flattenNodes(): Model[] {\n const result: Model[] = [];\n this.flattenWalk(this.rootNode, result);\n return result;\n }\n\n private flattenWalk(node: NodeInterface, out: Model[]): void {\n out.push(node as any as Model);\n if (node.expanded || node.isRoot()) {\n for (const child of node.childNodes) {\n this.flattenWalk(child, out);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Build tree from nested data\n // -----------------------------------------------------------------------\n\n private buildNode(data: Record<string, unknown>, depth: number): NodeInterface {\n const children = data.children as Record<string, unknown>[] | undefined;\n const expanded = data.expanded as boolean | undefined;\n const nodeData = { ...data };\n delete nodeData.children;\n delete nodeData.expanded;\n\n const model = this.ModelClass.create(nodeData);\n applyNodeInterface(model, depth);\n const node = model as any as NodeInterface;\n\n if (expanded) {\n node.expanded = true;\n node.loaded = true;\n }\n\n if (children && Array.isArray(children)) {\n for (const childData of children) {\n const childNode = this.buildNode(childData, depth + 1);\n node.appendChild(childNode);\n }\n node.loaded = true;\n }\n\n return node;\n }\n\n // -----------------------------------------------------------------------\n // Node registration (for id-based lookup)\n // -----------------------------------------------------------------------\n\n private registerRecursive(node: NodeInterface): void {\n const id = (node as any as Model).getId();\n if (id !== undefined && id !== null) {\n this.nodeMap.set(id, node);\n }\n for (const child of node.childNodes) {\n this.registerRecursive(child);\n }\n }\n\n private unregisterRecursive(node: NodeInterface): void {\n const id = (node as any as Model).getId();\n if (id !== undefined && id !== null) {\n this.nodeMap.delete(id);\n }\n for (const child of node.childNodes) {\n this.unregisterRecursive(child);\n }\n }\n\n // -----------------------------------------------------------------------\n // Event helper\n // -----------------------------------------------------------------------\n\n private fire(eventName: string, ...args: unknown[]): void {\n if (typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent(eventName, ...args);\n }\n }\n}\n","/**\n * @framesquared/data – NodeInterface\n *\n * Mixin applied to Model instances to give them tree-node capabilities:\n * parent/child/sibling navigation, depth, expand/collapse state,\n * cascadeBy, bubble, getPath, findChild, sort, and nested serialization.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\nimport type { Sorter } from '../store/Store.js';\n\n// ---------------------------------------------------------------------------\n// NodeInterface\n// ---------------------------------------------------------------------------\n\nexport interface NodeInterface extends Model {\n parentNode: NodeInterface | null;\n childNodes: NodeInterface[];\n firstChild: NodeInterface | null;\n lastChild: NodeInterface | null;\n previousSibling: NodeInterface | null;\n nextSibling: NodeInterface | null;\n depth: number;\n\n /** Node state */\n expanded: boolean;\n loaded: boolean;\n\n isLeaf(): boolean;\n isRoot(): boolean;\n isExpanded(): boolean;\n isLoaded(): boolean;\n\n appendChild(child: NodeInterface): void;\n removeChild(child: NodeInterface): void;\n insertBefore(newChild: NodeInterface, refChild: NodeInterface): void;\n\n getPath(separator?: string): string;\n cascadeBy(fn: (node: NodeInterface) => boolean | void): void;\n bubble(fn: (node: NodeInterface) => boolean | void): void;\n contains(child: NodeInterface): boolean;\n findChild(field: string, value: unknown, deep?: boolean): NodeInterface | undefined;\n sort(sorters: Sorter[]): void;\n serialize(): any;\n\n // Extended methods\n eachChild(fn: (child: NodeInterface, index: number) => boolean | void, scope?: object): void;\n indexOf(child: NodeInterface): number;\n getChildAt(index: number): NodeInterface | undefined;\n childCount(): number;\n hasChildNodes(): boolean;\n getChildren(deep?: boolean): NodeInterface[];\n findChildBy(predicate: (node: NodeInterface) => boolean | void, deep?: boolean): NodeInterface | undefined;\n removeAll(): NodeInterface[];\n copy(deep?: boolean): NodeInterface;\n getDepth(): number;\n}\n\n// ---------------------------------------------------------------------------\n// applyNodeInterface — attaches node methods/properties to a model\n// ---------------------------------------------------------------------------\n\nexport function applyNodeInterface(model: Model, depth = 0): void {\n const node = model as any as NodeInterface;\n\n // Properties\n node.parentNode = node.parentNode ?? null;\n node.childNodes = node.childNodes ?? [];\n node.firstChild = node.firstChild ?? null;\n node.lastChild = node.lastChild ?? null;\n node.previousSibling = node.previousSibling ?? null;\n node.nextSibling = node.nextSibling ?? null;\n node.depth = depth;\n node.expanded = node.expanded ?? false;\n node.loaded = node.loaded ?? false;\n\n // Methods\n node.isLeaf = function (): boolean {\n // Explicitly marked as leaf, OR has no children\n if (this.get('leaf') === true) return true;\n return this.childNodes.length === 0;\n };\n\n node.isRoot = function (): boolean {\n return this.parentNode === null;\n };\n\n node.isExpanded = function (): boolean {\n return this.expanded;\n };\n\n node.isLoaded = function (): boolean {\n return this.loaded;\n };\n\n node.appendChild = function (child: NodeInterface): void {\n const c = child as any as NodeInterface;\n\n // Remove from current parent if any\n if (c.parentNode) {\n c.parentNode.removeChild(c);\n }\n\n c.parentNode = this;\n c.depth = this.depth + 1;\n\n const children = this.childNodes;\n const prevLast = children.length > 0 ? children[children.length - 1] : null;\n\n children.push(c);\n\n // Update sibling links\n if (prevLast) {\n prevLast.nextSibling = c;\n c.previousSibling = prevLast;\n } else {\n c.previousSibling = null;\n }\n c.nextSibling = null;\n\n // Update first/last\n this.firstChild = children[0];\n this.lastChild = children[children.length - 1];\n\n // Update depth recursively\n updateDepthRecursive(c, this.depth + 1);\n };\n\n node.removeChild = function (child: NodeInterface): void {\n const children = this.childNodes;\n const idx = children.indexOf(child);\n if (idx === -1) return;\n\n children.splice(idx, 1);\n\n // Update sibling links\n if (child.previousSibling) {\n child.previousSibling.nextSibling = child.nextSibling;\n }\n if (child.nextSibling) {\n child.nextSibling.previousSibling = child.previousSibling;\n }\n\n child.parentNode = null;\n child.previousSibling = null;\n child.nextSibling = null;\n\n // Update first/last\n this.firstChild = children.length > 0 ? children[0] : null;\n this.lastChild = children.length > 0 ? children[children.length - 1] : null;\n };\n\n node.insertBefore = function (newChild: NodeInterface, refChild: NodeInterface): void {\n const children = this.childNodes;\n const refIdx = children.indexOf(refChild);\n if (refIdx === -1) {\n // If ref not found, append\n this.appendChild(newChild);\n return;\n }\n\n // Remove from current parent if any\n if (newChild.parentNode) {\n newChild.parentNode.removeChild(newChild);\n }\n\n newChild.parentNode = this;\n newChild.depth = this.depth + 1;\n\n children.splice(refIdx, 0, newChild);\n\n // Rebuild sibling links for the affected range\n rebuildSiblings(children);\n\n this.firstChild = children[0];\n this.lastChild = children[children.length - 1];\n\n updateDepthRecursive(newChild, this.depth + 1);\n };\n\n node.getPath = function (separator = '/'): string {\n const parts: string[] = [];\n let current: NodeInterface | null = this;\n while (current) {\n parts.unshift(current.get('text') as string ?? String(current.getId()));\n current = current.parentNode;\n }\n return separator + parts.join(separator);\n };\n\n node.cascadeBy = function (fn: (n: NodeInterface) => boolean | void): void {\n cascadeByImpl(this, fn);\n };\n\n node.bubble = function (fn: (n: NodeInterface) => boolean | void): void {\n let current: NodeInterface | null = this;\n while (current) {\n if (fn(current) === false) return;\n current = current.parentNode;\n }\n };\n\n node.contains = function (descendant: NodeInterface): boolean {\n let current: NodeInterface | null = descendant.parentNode;\n while (current) {\n if (current === (this as any)) return true;\n current = current.parentNode;\n }\n return false;\n };\n\n node.findChild = function (\n field: string,\n value: unknown,\n deep = false,\n ): NodeInterface | undefined {\n for (const child of this.childNodes) {\n if (child.get(field) === value) return child;\n if (deep) {\n const found = child.findChild(field, value, true);\n if (found) return found;\n }\n }\n return undefined;\n };\n\n node.sort = function (sorters: Sorter[]): void {\n this.childNodes.sort((a: NodeInterface, b: NodeInterface) => {\n for (const s of sorters) {\n const va = a.get(s.property) as string | number;\n const vb = b.get(s.property) as string | number;\n const dir = s.direction === 'DESC' ? -1 : 1;\n if (va < vb) return -1 * dir;\n if (va > vb) return 1 * dir;\n }\n return 0;\n });\n rebuildSiblings(this.childNodes);\n this.firstChild = this.childNodes[0] ?? null;\n this.lastChild = this.childNodes[this.childNodes.length - 1] ?? null;\n };\n\n node.serialize = function (): any {\n const data = this.getData();\n if (this.childNodes.length > 0) {\n data.children = this.childNodes.map((c: NodeInterface) => c.serialize());\n }\n return data;\n };\n\n node.eachChild = function (\n fn: (child: NodeInterface, index: number) => boolean | void,\n ): void {\n for (let i = 0; i < this.childNodes.length; i++) {\n if (fn(this.childNodes[i], i) === false) return;\n }\n };\n\n node.indexOf = function (child: NodeInterface): number {\n return this.childNodes.indexOf(child);\n };\n\n node.getChildAt = function (index: number): NodeInterface | undefined {\n return this.childNodes[index];\n };\n\n node.childCount = function (): number {\n return this.childNodes.length;\n };\n\n node.hasChildNodes = function (): boolean {\n return this.childNodes.length > 0;\n };\n\n node.getChildren = function (deep = false): NodeInterface[] {\n if (!deep) {\n return [...this.childNodes];\n }\n const result: NodeInterface[] = [];\n const collect = (n: NodeInterface): void => {\n for (const child of n.childNodes) {\n result.push(child);\n collect(child);\n }\n };\n collect(this);\n return result;\n };\n\n node.findChildBy = function (\n predicate: (n: NodeInterface) => boolean | void,\n deep = false,\n ): NodeInterface | undefined {\n for (const child of this.childNodes) {\n const matched = predicate(child);\n if (matched !== false && matched !== undefined && matched !== null) return child;\n if (deep) {\n const found = child.findChildBy(predicate, true);\n if (found) return found;\n }\n }\n return undefined;\n };\n\n node.removeAll = function (): NodeInterface[] {\n const removed = [...this.childNodes];\n for (const child of removed) {\n child.parentNode = null;\n child.previousSibling = null;\n child.nextSibling = null;\n }\n this.childNodes = [];\n this.firstChild = null;\n this.lastChild = null;\n return removed;\n };\n\n node.copy = function (deep = true): NodeInterface {\n const copyCounter = { i: 0 };\n return copyNodeImpl(this, deep, copyCounter);\n };\n\n node.getDepth = function (): number {\n return this.depth;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction rebuildSiblings(children: NodeInterface[]): void {\n for (let i = 0; i < children.length; i++) {\n children[i].previousSibling = i > 0 ? children[i - 1] : null;\n children[i].nextSibling = i < children.length - 1 ? children[i + 1] : null;\n }\n}\n\nfunction updateDepthRecursive(node: NodeInterface, depth: number): void {\n node.depth = depth;\n for (const child of node.childNodes) {\n updateDepthRecursive(child, depth + 1);\n }\n}\n\n/**\n * Recursively copies a node (and optionally its children) with new IDs.\n */\nfunction copyNodeImpl(\n node: NodeInterface,\n deep: boolean,\n counter: { i: number },\n): NodeInterface {\n counter.i += 1;\n const newId = 'copy-' + Date.now() + '-' + counter.i;\n const data = (node as any).getData() as Record<string, unknown>;\n const Ctor = (node as any).constructor as { create(data: Record<string, unknown>): any };\n const copyModel = Ctor.create({ ...data, id: newId });\n applyNodeInterface(copyModel, 0);\n const copyNode = copyModel as any as NodeInterface;\n\n if (deep) {\n for (const child of node.childNodes) {\n const childCopy = copyNodeImpl(child, true, counter);\n copyNode.appendChild(childCopy);\n }\n }\n\n return copyNode;\n}\n\n/**\n * Depth-first cascade that returns false if iteration was stopped.\n */\nfunction cascadeByImpl(\n node: NodeInterface,\n fn: (n: NodeInterface) => boolean | void,\n): boolean {\n if (fn(node) === false) return false;\n for (const child of [...node.childNodes]) {\n if (!cascadeByImpl(child, fn)) return false;\n }\n return true;\n}\n","/**\n * @framesquared/data – TreeModel\n *\n * A convenience Model subclass with NodeInterface pre-applied via create().\n */\n\nimport { Model } from '../Model.js';\nimport { applyNodeInterface } from '../mixin/NodeInterface.js';\nimport type { NodeInterface } from '../mixin/NodeInterface.js';\nimport { FieldType } from '../field/Field.js';\n\nexport class TreeModel extends Model {\n static override $className = 'Ext.data.TreeModel';\n static override idProperty = 'id';\n static defaultRootId = 'root';\n static defaultRootText = 'Root';\n\n static override fields = [\n { name: 'id', type: FieldType.AUTO },\n { name: 'text', type: FieldType.STRING, defaultValue: '' },\n { name: 'leaf', type: FieldType.BOOLEAN, defaultValue: false },\n { name: 'cls', type: FieldType.STRING, defaultValue: '' },\n { name: 'iconCls', type: FieldType.STRING, defaultValue: '' },\n { name: 'icon', type: FieldType.STRING, defaultValue: '' },\n { name: 'href', type: FieldType.STRING, defaultValue: '' },\n { name: 'hrefTarget', type: FieldType.STRING, defaultValue: '' },\n { name: 'qtip', type: FieldType.STRING, defaultValue: '' },\n { name: 'qtitle', type: FieldType.STRING, defaultValue: '' },\n { name: 'allowDrop', type: FieldType.BOOLEAN, defaultValue: true },\n { name: 'allowDrag', type: FieldType.BOOLEAN, defaultValue: true },\n ];\n\n /**\n * Factory method that creates a TreeModel instance with NodeInterface\n * already applied.\n */\n static override create(\n this: typeof Model,\n data?: Record<string, unknown>,\n ): InstanceType<typeof Model> & NodeInterface {\n const instance = super.create(data);\n applyNodeInterface(instance, 0);\n return instance as InstanceType<typeof Model> & NodeInterface;\n }\n}\n","/**\n * @framesquared/data – TreeReader\n *\n * Reads nested (hierarchical) JSON data, flattening it into a ResultSet\n * while preserving the children references.\n */\n\nimport { JsonReader } from './Reader.js';\nimport type { JsonReaderConfig } from './Reader.js';\nimport { ResultSet } from '../ResultSet.js';\n\nexport interface TreeReaderConfig extends JsonReaderConfig {\n /** Name of the property that holds child records. Defaults to 'children'. */\n childrenProperty?: string;\n}\n\nexport class TreeReader extends JsonReader {\n readonly childrenProperty: string;\n\n constructor(config: TreeReaderConfig) {\n super(config);\n this.childrenProperty = config.childrenProperty ?? 'children';\n }\n\n /**\n * Reads data, recursively collecting ALL nodes (at all levels) into a flat\n * ResultSet. The original children references are preserved on the raw\n * objects, so the tree structure is available to callers (e.g. TreeStore).\n */\n override read(data: unknown): ResultSet {\n const flat: Record<string, unknown>[] = [];\n const rootRecords = this.extractRootArray(data);\n this.collectFlat(rootRecords, flat);\n // Build ResultSet directly to avoid rootProperty re-extraction in super.read()\n const model = this.config.model;\n const records = flat.map((raw) => model.create(raw));\n return new ResultSet({ records, total: records.length, success: true });\n }\n\n /**\n * Returns `{ root, records }` where `root` is the first raw record and\n * `records` is the full flat list of all nodes.\n */\n readTree(data: Record<string, unknown>): {\n root: Record<string, unknown>;\n records: Record<string, unknown>[];\n } {\n const flat: Record<string, unknown>[] = [];\n this.collectFlat([data], flat);\n return { root: data, records: flat };\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n private extractRootArray(data: unknown): Record<string, unknown>[] {\n if (this.config.rootProperty) {\n const root = getNestedValue(data, this.config.rootProperty);\n return Array.isArray(root) ? (root as Record<string, unknown>[]) : [];\n }\n return Array.isArray(data) ? (data as Record<string, unknown>[]) : [];\n }\n\n private collectFlat(\n items: Record<string, unknown>[],\n out: Record<string, unknown>[],\n ): void {\n for (const item of items) {\n out.push(item);\n const children = item[this.childrenProperty];\n if (Array.isArray(children) && children.length > 0) {\n this.collectFlat(children as Record<string, unknown>[], out);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal helper (mirrors Reader.ts private helper)\n// ---------------------------------------------------------------------------\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n const segments = path.split('.');\n let current: unknown = obj;\n for (const seg of segments) {\n if (current == null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[seg];\n }\n return current;\n}\n","/**\n * @framesquared/data – TreeWriter\n *\n * Serializes tree nodes (NodeInterface) into nested JSON structures.\n */\n\nimport type { NodeInterface } from '../mixin/NodeInterface.js';\n\nexport interface TreeWriterConfig {\n /** Name of the property used for child records. Defaults to 'children'. */\n childrenProperty?: string;\n}\n\nexport class TreeWriter {\n readonly childrenProperty: string;\n\n constructor(config?: TreeWriterConfig) {\n this.childrenProperty = config?.childrenProperty ?? 'children';\n }\n\n /**\n * Serializes an array of root-level NodeInterface records to plain objects.\n * Children are nested under the configured `childrenProperty`.\n */\n writeRecords(records: NodeInterface[]): Record<string, unknown>[] {\n return records.map((r) => this.writeRecord(r));\n }\n\n private writeRecord(record: NodeInterface): Record<string, unknown> {\n // getData() returns only the declared model fields (persistent field data)\n const data = record.getData() as Record<string, unknown>;\n\n if (record.childNodes && record.childNodes.length > 0) {\n data[this.childrenProperty] = record.childNodes.map((c: NodeInterface) =>\n this.writeRecord(c),\n );\n }\n\n return data;\n }\n}\n","/**\n * @framesquared/data – BufferedStore\n *\n * For large datasets — loads pages of data on demand via a proxy.\n * Uses a sparse page map instead of loading all records.\n * Prefetches adjacent pages based on configurable buffer zones.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Base, Observable } from '@framesquared/core';\nimport type { Model } from '../Model.js';\nimport { Operation } from '../Operation.js';\n\n// ---------------------------------------------------------------------------\n// Observable bootstrap\n// ---------------------------------------------------------------------------\n\nconst ObservableMixin: typeof Base = Observable;\n\nfunction ensureObservable(instance: any): void {\n const proto = ObservableMixin.prototype;\n for (const name of Object.getOwnPropertyNames(proto)) {\n if (name === 'constructor') continue;\n if (name in instance) continue;\n const desc = Object.getOwnPropertyDescriptor(proto, name);\n if (desc && typeof desc.value === 'function') {\n instance[name] = desc.value.bind(instance);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface BufferedStoreConfig {\n model: typeof Model;\n pageSize?: number;\n leadingBufferZone?: number;\n trailingBufferZone?: number;\n proxy?: any;\n}\n\n// ---------------------------------------------------------------------------\n// BufferedStore\n// ---------------------------------------------------------------------------\n\nexport class BufferedStore extends Base {\n static override $className = 'Ext.data.BufferedStore';\n\n private pageSize: number;\n private leadingBufferZone: number;\n private trailingBufferZone: number;\n private proxyRef: any;\n\n /** Page number → array of Model records for that page. */\n private pageMap = new Map<number, Model[]>();\n\n /** Total count from the server. */\n private totalCount = 0;\n\n /** All loaded records in a flat sparse index. */\n private recordMap = new Map<number, Model>();\n\n /** Pages currently being fetched (to avoid duplicate requests). */\n private pendingPages = new Set<number>();\n\n $destroyHooks: (() => void)[] = [];\n\n constructor(config: BufferedStoreConfig) {\n super();\n ensureObservable(this);\n\n this.pageSize = config.pageSize ?? 25;\n this.leadingBufferZone = config.leadingBufferZone ?? 0;\n this.trailingBufferZone = config.trailingBufferZone ?? 0;\n this.proxyRef = config.proxy ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n getPageSize(): number {\n return this.pageSize;\n }\n\n getCount(): number {\n return this.recordMap.size;\n }\n\n getTotalCount(): number {\n return this.totalCount;\n }\n\n getAt(index: number): Model | undefined {\n return this.recordMap.get(index);\n }\n\n isPageLoaded(pageNumber: number): boolean {\n return this.pageMap.has(pageNumber);\n }\n\n /**\n * Ensures the given range [start, end] of row indices is loaded.\n * Loads missing pages from the proxy and fires 'guaranteedrange'\n * when the requested range is fully available.\n */\n async guaranteeRange(start: number, end: number): Promise<void> {\n const startPage = Math.floor(start / this.pageSize);\n const endPage = Math.floor(end / this.pageSize);\n\n // Collect pages that need loading\n const pagesToLoad: number[] = [];\n for (let p = startPage; p <= endPage; p++) {\n if (!this.pageMap.has(p) && !this.pendingPages.has(p)) {\n pagesToLoad.push(p);\n }\n }\n\n // Load missing pages\n if (pagesToLoad.length > 0) {\n await Promise.all(pagesToLoad.map((p) => this.loadPage(p)));\n }\n\n // Fire event with the records in the requested range\n const records: Model[] = [];\n for (let i = start; i <= end; i++) {\n const rec = this.recordMap.get(i);\n if (rec) records.push(rec);\n }\n this.fire('guaranteedrange', this, records, start, end);\n\n // Prefetch buffer zones (don't await — fire and forget)\n this.prefetchBufferZones(startPage, endPage);\n }\n\n // -----------------------------------------------------------------------\n // Page loading\n // -----------------------------------------------------------------------\n\n private async loadPage(pageNumber: number): Promise<void> {\n if (!this.proxyRef) return;\n if (this.pageMap.has(pageNumber)) return;\n\n this.pendingPages.add(pageNumber);\n\n try {\n const start = pageNumber * this.pageSize;\n const op = new Operation({\n action: 'read',\n start,\n limit: this.pageSize,\n page: pageNumber + 1, // 1-based page for server\n });\n\n const rs = await this.proxyRef.read(op);\n\n if (rs.success) {\n this.pageMap.set(pageNumber, rs.records);\n\n // Index records by their absolute position\n for (let i = 0; i < rs.records.length; i++) {\n this.recordMap.set(start + i, rs.records[i]);\n }\n\n // Update total count from server\n if (rs.total > 0) {\n this.totalCount = rs.total;\n }\n }\n } finally {\n this.pendingPages.delete(pageNumber);\n }\n }\n\n // -----------------------------------------------------------------------\n // Prefetching\n // -----------------------------------------------------------------------\n\n private prefetchBufferZones(startPage: number, endPage: number): void {\n if (this.leadingBufferZone <= 0 && this.trailingBufferZone <= 0) return;\n\n const leadingPages = Math.ceil(this.leadingBufferZone / this.pageSize);\n const trailingPages = Math.ceil(this.trailingBufferZone / this.pageSize);\n\n // Prefetch leading pages (before the requested range)\n for (let p = startPage - leadingPages; p < startPage; p++) {\n if (p >= 0 && !this.pageMap.has(p) && !this.pendingPages.has(p)) {\n this.loadPage(p); // fire and forget\n }\n }\n\n // Prefetch trailing pages (after the requested range)\n const maxPage = this.totalCount > 0\n ? Math.floor((this.totalCount - 1) / this.pageSize)\n : endPage + trailingPages;\n\n for (let p = endPage + 1; p <= endPage + trailingPages && p <= maxPage; p++) {\n if (!this.pageMap.has(p) && !this.pendingPages.has(p)) {\n this.loadPage(p); // fire and forget\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Event helper\n // -----------------------------------------------------------------------\n\n private fire(eventName: string, ...args: unknown[]): void {\n if (typeof (this as any).fireEvent === 'function') {\n (this as any).fireEvent(eventName, ...args);\n }\n }\n}\n","/**\n * @framesquared/data – GraphQLProxy\n *\n * Sends GraphQL queries for read and mutations for CUD operations.\n * Parses response using a rootProperty path into the GraphQL data.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\nimport { Proxy } from './Proxy.js';\nimport type { ProxyConfig } from './Proxy.js';\n\nexport interface GraphQLProxyConfig extends ProxyConfig {\n url: string;\n query?: string;\n mutation?: string;\n rootProperty?: string;\n headers?: Record<string, string>;\n}\n\nexport class GraphQLProxy extends Proxy {\n private url: string;\n private query: string;\n private mutation: string;\n private rootProperty: string;\n private headers: Record<string, string>;\n\n constructor(config: GraphQLProxyConfig) {\n super(config);\n this.url = config.url;\n this.query = config.query ?? '';\n this.mutation = config.mutation ?? '';\n this.rootProperty = config.rootProperty ?? 'data';\n this.headers = config.headers ?? {};\n }\n\n async read(operation: Operation): Promise<ResultSet> {\n return this.doRequest(this.query, operation.params);\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n const variables: Record<string, unknown> = { ...operation.params };\n if (operation.records.length > 0) {\n variables.input = operation.records[0].getData();\n }\n return this.doRequest(this.mutation, variables);\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n const variables: Record<string, unknown> = { ...operation.params };\n if (operation.records.length > 0) {\n variables.input = operation.records[0].getData();\n }\n return this.doRequest(this.mutation, variables);\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n const variables: Record<string, unknown> = { ...operation.params };\n if (operation.records.length > 0) {\n variables.id = operation.records[0].getId();\n }\n return this.doRequest(this.mutation, variables);\n }\n\n private async doRequest(\n queryStr: string,\n variables: Record<string, unknown>,\n ): Promise<ResultSet> {\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.headers },\n body: JSON.stringify({ query: queryStr, variables }),\n });\n\n const data = await response.json();\n\n // Check for GraphQL errors\n if (data.errors && data.errors.length > 0) {\n return new ResultSet({\n records: [],\n success: false,\n message: data.errors[0].message,\n });\n }\n\n // Extract records from rootProperty path\n const raw = this.extractByPath(data, this.rootProperty);\n const items = Array.isArray(raw) ? raw : raw ? [raw] : [];\n const records = items.map((item: any) => this.model.create(item));\n\n return new ResultSet({ records, success: true });\n } catch (err: any) {\n return new ResultSet({\n records: [],\n success: false,\n message: err?.message ?? 'GraphQL request failed',\n });\n }\n }\n\n private extractByPath(obj: any, path: string): unknown {\n const parts = path.split('.');\n let current = obj;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n }\n}\n","/**\n * @framesquared/data – WebSocketProxy\n *\n * Maintains a WebSocket connection for real-time data. Sends\n * CRUD operations as JSON messages. Auto-reconnects on disconnect.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\nimport { Proxy } from './Proxy.js';\nimport type { ProxyConfig } from './Proxy.js';\n\nexport interface WebSocketProxyConfig extends ProxyConfig {\n url: string;\n protocol?: string;\n reconnect?: boolean;\n reconnectInterval?: number;\n}\n\nexport class WebSocketProxy extends Proxy {\n private url: string;\n private reconnect: boolean;\n private reconnectInterval: number;\n private ws: WebSocket | null = null;\n private listeners: Record<string, Function[]> = {};\n private intentionalClose = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(config: WebSocketProxyConfig) {\n super(config);\n this.url = config.url;\n this.reconnect = config.reconnect ?? false;\n this.reconnectInterval = config.reconnectInterval ?? 3000;\n }\n\n // -----------------------------------------------------------------------\n // Connection management\n // -----------------------------------------------------------------------\n\n connect(): void {\n this.intentionalClose = false;\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => this.fire('open');\n this.ws.onerror = (e) => this.fire('error', e);\n this.ws.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data);\n this.fire('message', data);\n } catch {\n this.fire('message', e.data);\n }\n };\n this.ws.onclose = () => {\n this.fire('close');\n if (this.reconnect && !this.intentionalClose) {\n this.reconnectTimer = setTimeout(() => this.connect(), this.reconnectInterval);\n }\n };\n }\n\n disconnect(): void {\n this.intentionalClose = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.ws?.close();\n this.ws = null;\n }\n\n // -----------------------------------------------------------------------\n // Send operations\n // -----------------------------------------------------------------------\n\n send(operation: Operation): void {\n if (!this.ws || this.ws.readyState !== 1) return;\n const message = {\n action: operation.action,\n records: operation.records.map(r => r.getData()),\n params: operation.params,\n };\n this.ws.send(JSON.stringify(message));\n }\n\n // -----------------------------------------------------------------------\n // Proxy interface (returns empty ResultSets — real data comes via events)\n // -----------------------------------------------------------------------\n\n async read(operation: Operation): Promise<ResultSet> {\n this.send(operation);\n return new ResultSet({ records: [], success: true });\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n this.send(operation);\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n this.send(operation);\n return new ResultSet({ records: operation.records, success: true });\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n this.send(operation);\n return new ResultSet({ records: [], success: true });\n }\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n (this.listeners[event] ??= []).push(fn);\n }\n\n off(event: string, fn: Function): void {\n const list = this.listeners[event];\n if (!list) return;\n const idx = list.indexOf(fn);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n private fire(event: string, ...args: unknown[]): void {\n (this.listeners[event] ?? []).forEach(fn => fn(...args));\n }\n}\n","/**\n * @framesquared/data – BatchProxy\n *\n * Combines multiple operations into a single HTTP request.\n * Unwraps the batch response into individual ResultSets.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Operation } from '../Operation.js';\nimport { ResultSet } from '../ResultSet.js';\nimport { Proxy } from './Proxy.js';\nimport type { ProxyConfig } from './Proxy.js';\n\nexport interface BatchProxyConfig extends ProxyConfig {\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class BatchProxy extends Proxy {\n private url: string;\n private headers: Record<string, string>;\n\n constructor(config: BatchProxyConfig) {\n super(config);\n this.url = config.url;\n this.headers = config.headers ?? {};\n }\n\n /**\n * Send multiple operations as a single batched request.\n * Returns an array of ResultSets, one per operation.\n */\n async sendBatch(operations: Operation[]): Promise<ResultSet[]> {\n const body = {\n operations: operations.map(op => ({\n action: op.action,\n records: op.records.map(r => r.getData()),\n params: op.params,\n })),\n };\n\n try {\n const response = await fetch(this.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.headers },\n body: JSON.stringify(body),\n });\n\n const data = await response.json();\n const results: ResultSet[] = [];\n\n if (data.results && Array.isArray(data.results)) {\n for (const r of data.results) {\n const records = (r.records ?? []).map((item: any) => this.model.create(item));\n results.push(new ResultSet({\n records,\n success: r.success ?? false,\n message: r.message,\n }));\n }\n }\n\n return results;\n } catch (err: any) {\n return operations.map(() => new ResultSet({\n records: [],\n success: false,\n message: err?.message ?? 'Batch request failed',\n }));\n }\n }\n\n // Proxy interface — delegate to sendBatch with single operation\n async read(operation: Operation): Promise<ResultSet> {\n const results = await this.sendBatch([operation]);\n return results[0] ?? new ResultSet({ records: [], success: false });\n }\n\n async create(operation: Operation): Promise<ResultSet> {\n const results = await this.sendBatch([operation]);\n return results[0] ?? new ResultSet({ records: [], success: false });\n }\n\n async update(operation: Operation): Promise<ResultSet> {\n const results = await this.sendBatch([operation]);\n return results[0] ?? new ResultSet({ records: [], success: false });\n }\n\n async destroy(operation: Operation): Promise<ResultSet> {\n const results = await this.sendBatch([operation]);\n return results[0] ?? new ResultSet({ records: [], success: false });\n }\n}\n","/**\n * @framesquared/data – Connection\n *\n * Centralized fetch() wrapper. Supports request and response\n * interceptors, default headers, and global error handling.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype RequestInterceptor = (url: string, init: RequestInit) => [string, RequestInit];\ntype ResponseInterceptor = (response: any) => any;\ntype ErrorHandler = (error: Error) => void;\n\nconst requestInterceptors: RequestInterceptor[] = [];\nconst responseInterceptors: ResponseInterceptor[] = [];\nlet defaultHeaders: Record<string, string> = {};\nlet errorHandler: ErrorHandler | null = null;\n\nexport const Connection = {\n /**\n * Fetch with interceptors and default headers applied.\n */\n async fetch(url: string, init: RequestInit = {}): Promise<any> {\n // Apply default headers\n init.headers = { ...defaultHeaders, ...(init.headers as Record<string, string> ?? {}) };\n\n // Apply request interceptors\n let currentUrl = url;\n let currentInit = init;\n for (const interceptor of requestInterceptors) {\n [currentUrl, currentInit] = interceptor(currentUrl, currentInit);\n }\n\n try {\n let response = await fetch(currentUrl, currentInit);\n\n // Apply response interceptors\n for (const interceptor of responseInterceptors) {\n response = interceptor(response);\n }\n\n return response;\n } catch (err: any) {\n if (errorHandler) errorHandler(err);\n throw err;\n }\n },\n\n addRequestInterceptor(fn: RequestInterceptor): void {\n requestInterceptors.push(fn);\n },\n\n addResponseInterceptor(fn: ResponseInterceptor): void {\n responseInterceptors.push(fn);\n },\n\n setDefaultHeaders(headers: Record<string, string>): void {\n defaultHeaders = { ...headers };\n },\n\n setErrorHandler(handler: ErrorHandler): void {\n errorHandler = handler;\n },\n\n reset(): void {\n requestInterceptors.length = 0;\n responseInterceptors.length = 0;\n defaultHeaders = {};\n errorHandler = null;\n },\n};\n","/**\n * @framesquared/data – Session\n *\n * Manages a set of related model instances. Tracks all CRUD\n * operations as a unit. save() sends all changes via a BatchProxy.\n * commit()/reject() clear tracked changes.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Model } from '../Model.js';\nimport { Operation } from '../Operation.js';\nimport type { BatchProxy } from '../proxy/BatchProxy.js';\nimport type { ResultSet } from '../ResultSet.js';\n\nexport interface SessionChanges {\n create: Model[];\n update: Model[];\n destroy: Model[];\n}\n\nexport class Session {\n private created = new Map<unknown, Model>();\n private updated = new Map<unknown, Model>();\n private destroyed = new Map<unknown, Model>();\n\n // -----------------------------------------------------------------------\n // Track operations\n // -----------------------------------------------------------------------\n\n trackCreate(record: Model): void {\n const key = this.recordKey(record);\n this.created.set(key, record);\n }\n\n trackUpdate(record: Model): void {\n const key = this.recordKey(record);\n // If already in created, keep it there (it's still a create)\n if (this.created.has(key)) return;\n this.updated.set(key, record);\n }\n\n trackDestroy(record: Model): void {\n const key = this.recordKey(record);\n // If it was newly created, just remove from created\n if (this.created.has(key)) {\n this.created.delete(key);\n return;\n }\n // Remove from updated if present\n this.updated.delete(key);\n this.destroyed.set(key, record);\n }\n\n // -----------------------------------------------------------------------\n // Accessors\n // -----------------------------------------------------------------------\n\n getCreated(): Model[] { return [...this.created.values()]; }\n getUpdated(): Model[] { return [...this.updated.values()]; }\n getDestroyed(): Model[] { return [...this.destroyed.values()]; }\n\n getChanges(): SessionChanges {\n return {\n create: this.getCreated(),\n update: this.getUpdated(),\n destroy: this.getDestroyed(),\n };\n }\n\n isDirty(): boolean {\n return this.created.size > 0 || this.updated.size > 0 || this.destroyed.size > 0;\n }\n\n // -----------------------------------------------------------------------\n // Save via BatchProxy\n // -----------------------------------------------------------------------\n\n async save(proxy: BatchProxy): Promise<{ success: boolean; results: ResultSet[] }> {\n const ops: Operation[] = [];\n const creates = this.getCreated();\n const updates = this.getUpdated();\n const destroys = this.getDestroyed();\n\n if (creates.length > 0) {\n ops.push(new Operation({ action: 'create', records: creates }));\n }\n if (updates.length > 0) {\n ops.push(new Operation({ action: 'update', records: updates }));\n }\n if (destroys.length > 0) {\n ops.push(new Operation({ action: 'destroy', records: destroys }));\n }\n\n if (ops.length === 0) {\n return { success: true, results: [] };\n }\n\n const results = await proxy.sendBatch(ops);\n const success = results.every(r => r.success);\n return { success, results };\n }\n\n // -----------------------------------------------------------------------\n // Commit / Reject\n // -----------------------------------------------------------------------\n\n commit(): void {\n this.created.clear();\n this.updated.clear();\n this.destroyed.clear();\n }\n\n reject(): void {\n this.created.clear();\n this.updated.clear();\n this.destroyed.clear();\n }\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n private recordKey(record: Model): unknown {\n // Use record identity (reference) as Map key for dedup\n return record;\n }\n}\n","/**\n * @framesquared/ui – TreeGridColumn\n *\n * Column definition for the tree (first) column of a TreeGrid.\n * Renders tree chrome: indentation, expander, icon, checkbox, node text.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Elbow types for tree connector lines\n// ---------------------------------------------------------------------------\n\nexport type ElbowType = 'line' | 'empty' | 'end' | 'end-plus' | 'tee' | 'tee-plus';\n\n// ---------------------------------------------------------------------------\n// Column (plain grid column, not tree column)\n// ---------------------------------------------------------------------------\n\nexport interface EditorConfig {\n xtype: string;\n /** options for combobox/select/radiogroup — array of {value,text} or plain strings */\n options?: Array<{ value: string; text: string } | string>;\n /** legacy: ExtJS-style store for combobox */\n store?: Array<{ value: string; text: string } | string>;\n displayField?: string;\n valueField?: string;\n minValue?: number;\n maxValue?: number;\n step?: number;\n rows?: number;\n allowBlank?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ColumnConfig {\n dataIndex: string;\n text?: string;\n width?: number;\n flex?: number;\n hidden?: boolean;\n renderer?: (value: unknown, record: NodeInterface) => string;\n /** Editor config. Pass false to mark the column as read-only. */\n editor?: EditorConfig | false;\n}\n\nexport class Column {\n readonly isColumn: boolean = true;\n dataIndex: string;\n text: string;\n width: number;\n flex: number;\n hidden: boolean;\n renderer: ((value: unknown, record: NodeInterface) => string) | undefined;\n editor: EditorConfig | false | undefined;\n\n constructor(config: ColumnConfig) {\n this.dataIndex = config.dataIndex;\n this.text = config.text ?? config.dataIndex;\n this.width = config.width ?? 100;\n this.flex = config.flex ?? 0;\n this.hidden = config.hidden ?? false;\n this.renderer = config.renderer;\n this.editor = config.editor;\n }\n\n /**\n * Returns the rendered cell value HTML for this column.\n */\n renderValue(record: NodeInterface): string {\n const raw = (record as any).get(this.dataIndex);\n const value = raw != null ? String(raw) : '';\n if (this.renderer) {\n return this.renderer(raw, record);\n }\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridColumn config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridColumnConfig extends Omit<ColumnConfig, 'dataIndex'> {\n dataIndex?: string;\n indentSize?: number;\n iconProperty?: string;\n iconClsProperty?: string;\n displayProperty?: string;\n defaultFolderIcon?: string;\n defaultFolderOpenIcon?: string;\n defaultLeafIcon?: string;\n showIcons?: boolean;\n showExpanders?: boolean;\n innerRenderer?: (value: unknown, record: NodeInterface) => string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridColumn\n// ---------------------------------------------------------------------------\n\nexport class TreeGridColumn extends Column {\n readonly isTreeGridColumn: boolean = true;\n\n indentSize: number;\n iconProperty: string;\n iconClsProperty: string;\n displayProperty: string;\n defaultFolderIcon: string;\n defaultFolderOpenIcon: string;\n defaultLeafIcon: string;\n showIcons: boolean;\n showExpanders: boolean;\n innerRenderer: ((value: unknown, record: NodeInterface) => string) | undefined;\n\n constructor(config: TreeGridColumnConfig = {}) {\n super({ ...config, dataIndex: config.dataIndex ?? (config.displayProperty ?? 'text') });\n this.indentSize = config.indentSize ?? 20;\n this.iconProperty = config.iconProperty ?? 'icon';\n this.iconClsProperty = config.iconClsProperty ?? 'iconCls';\n this.displayProperty = config.displayProperty ?? config.dataIndex ?? 'text';\n this.defaultFolderIcon = config.defaultFolderIcon ?? 'x-treegrid-icon-folder';\n this.defaultFolderOpenIcon = config.defaultFolderOpenIcon ?? 'x-treegrid-icon-folder-open';\n this.defaultLeafIcon = config.defaultLeafIcon ?? 'x-treegrid-icon-leaf';\n this.showIcons = config.showIcons ?? true;\n this.showExpanders = config.showExpanders ?? true;\n this.innerRenderer = config.innerRenderer;\n }\n\n /**\n * Computes the array of elbow types for a node based on depth and sibling position.\n */\n computeElbows(record: NodeInterface): ElbowType[] {\n const elbows: ElbowType[] = [];\n\n // Collect ancestors from root to this node\n const ancestors: NodeInterface[] = [];\n let curr: NodeInterface | null = record.parentNode;\n while (curr && !curr.isRoot()) {\n ancestors.unshift(curr);\n curr = curr.parentNode;\n }\n\n // For each ancestor's depth level, determine if the ancestor is last\n for (const ancestor of ancestors) {\n const isLast = ancestor.nextSibling === null;\n elbows.push(isLast ? 'empty' : 'line');\n }\n\n // Node's own depth position — use explicit leaf flag for \"is folder\" determination\n const nodeIsLast = record.nextSibling === null;\n const nodeIsExplicitLeaf = (record as any).get('leaf') === true;\n if (nodeIsLast && nodeIsExplicitLeaf) {\n elbows.push('end');\n } else if (nodeIsLast && !nodeIsExplicitLeaf) {\n elbows.push('end-plus');\n } else if (!nodeIsLast && nodeIsExplicitLeaf) {\n elbows.push('tee');\n } else {\n elbows.push('tee-plus');\n }\n\n return elbows;\n }\n\n /**\n * Renders the complete tree cell HTML.\n */\n renderCell(\n record: NodeInterface,\n checkable: boolean,\n lines: boolean,\n ): string {\n const depth = record.depth ?? 0;\n const indent = depth * this.indentSize;\n\n // 1. Elbows or padding\n let elbowsHtml = '';\n let paddingStyle = '';\n if (lines) {\n const elbows = this.computeElbows(record);\n elbowsHtml = elbows\n .map((t) => `<span class=\"x-treegrid-elbow x-treegrid-elbow-${t}\"></span>`)\n .join('');\n } else {\n paddingStyle = `padding-left: ${indent}px;`;\n }\n\n // 2. Expander — use explicit leaf flag so empty-children folders still show expander\n const isExplicitLeaf = (record as any).get('leaf') === true;\n let expanderHtml = '';\n if (this.showExpanders) {\n if (isExplicitLeaf) {\n expanderHtml = '<span class=\"x-treegrid-expander x-treegrid-expander-leaf\"></span>';\n } else {\n const cls = record.isExpanded()\n ? 'x-treegrid-expander-expanded'\n : 'x-treegrid-expander-collapsed';\n const label = record.isExpanded() ? 'Collapse row' : 'Expand row';\n expanderHtml = `<span class=\"x-treegrid-expander ${cls}\" role=\"button\" aria-label=\"${label}\" tabindex=\"-1\"></span>`;\n }\n }\n\n // 3. Checkbox\n let checkboxHtml = '';\n if (checkable) {\n const checked = (record as any).$checked;\n if (checked === true) {\n checkboxHtml =\n '<span class=\"x-treegrid-checkbox x-treegrid-checkbox-checked\" role=\"checkbox\" aria-checked=\"true\" tabindex=\"-1\"></span>';\n } else if (checked === null || checked === undefined || checked === 'indeterminate') {\n const indeterminate = checked === 'indeterminate' || checked === null;\n if (indeterminate && checked !== undefined) {\n checkboxHtml =\n '<span class=\"x-treegrid-checkbox x-treegrid-checkbox-indeterminate\" role=\"checkbox\" aria-checked=\"mixed\" tabindex=\"-1\"></span>';\n } else {\n checkboxHtml =\n '<span class=\"x-treegrid-checkbox\" role=\"checkbox\" aria-checked=\"false\" tabindex=\"-1\"></span>';\n }\n } else {\n checkboxHtml =\n '<span class=\"x-treegrid-checkbox\" role=\"checkbox\" aria-checked=\"false\" tabindex=\"-1\"></span>';\n }\n }\n\n // 4. Icon\n let iconHtml = '';\n if (this.showIcons) {\n const customIconSrc = String((record as any).get(this.iconProperty) ?? '');\n const customIconCls = String((record as any).get(this.iconClsProperty) ?? '');\n if (customIconSrc) {\n iconHtml = `<img class=\"x-treegrid-icon\" src=\"${customIconSrc}\" alt=\"\" />`;\n } else if (customIconCls) {\n iconHtml = `<span class=\"x-treegrid-icon ${customIconCls}\"></span>`;\n } else if (isExplicitLeaf) {\n iconHtml = `<span class=\"x-treegrid-icon ${this.defaultLeafIcon}\"></span>`;\n } else if (record.isExpanded()) {\n iconHtml = `<span class=\"x-treegrid-icon ${this.defaultFolderOpenIcon}\"></span>`;\n } else {\n iconHtml = `<span class=\"x-treegrid-icon ${this.defaultFolderIcon}\"></span>`;\n }\n }\n\n // 5. Text content\n const rawValue = (record as any).get(this.displayProperty);\n let textContent: string;\n if (this.innerRenderer) {\n textContent = this.innerRenderer(rawValue, record);\n } else {\n textContent = rawValue != null ? String(rawValue) : '';\n }\n const textHtml = `<span class=\"x-treegrid-node-text\">${textContent}</span>`;\n\n return `<div class=\"x-treegrid-cell-inner\" style=\"${paddingStyle}\">${elbowsHtml}${expanderHtml}${checkboxHtml}${iconHtml}${textHtml}</div>`;\n }\n}\n","/**\n * @framesquared/ui – TreeGridView\n *\n * Renders the tree grid body: a <table> with rows for each visible node.\n * First column uses TreeGridColumn for tree chrome; subsequent columns render plain values.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { TreeStore, NodeInterface } from '@framesquared/data';\nimport { TreeGridColumn, Column } from './TreeGridColumn.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridViewConfig {\n store: TreeStore;\n columns: (TreeGridColumn | Column)[];\n rootVisible?: boolean;\n checkable?: boolean;\n lines?: boolean;\n animate?: boolean;\n animationDuration?: number;\n expanderSelector?: string;\n checkboxSelector?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridView\n// ---------------------------------------------------------------------------\n\nexport class TreeGridView {\n el: HTMLElement | null = null;\n private tableEl: HTMLTableElement | null = null;\n private tbodyEl: HTMLTableSectionElement | null = null;\n\n private store: TreeStore;\n private columns: (TreeGridColumn | Column)[];\n private rootVisible: boolean;\n private checkable: boolean;\n private lines: boolean;\n\n private listeners: Map<string, Function[]> = new Map();\n private focusedNode: NodeInterface | null = null;\n private _rowCache: Map<string, HTMLTableRowElement> = new Map();\n\n constructor(config: TreeGridViewConfig) {\n this.store = config.store;\n this.columns = config.columns;\n this.rootVisible = config.rootVisible ?? false;\n this.checkable = config.checkable ?? false;\n this.lines = config.lines ?? false;\n }\n\n // -------------------------------------------------------------------------\n // Event system\n // -------------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n if (!this.listeners.has(event)) this.listeners.set(event, []);\n this.listeners.get(event)!.push(fn);\n }\n\n un(event: string, fn: Function): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n const i = fns.indexOf(fn);\n if (i !== -1) fns.splice(i, 1);\n }\n\n private fireEvent(event: string, ...args: unknown[]): void {\n for (const fn of [...(this.listeners.get(event) ?? [])]) fn(...args);\n }\n\n // -------------------------------------------------------------------------\n // Render\n // -------------------------------------------------------------------------\n\n render(container: HTMLElement): void {\n this.el = document.createElement('div');\n this.el.className = 'x-treegrid-view';\n this.el.setAttribute('role', 'treegrid');\n\n this.tableEl = document.createElement('table');\n this.tableEl.className = 'x-treegrid-table';\n this.el.appendChild(this.tableEl);\n\n this.tbodyEl = document.createElement('tbody');\n this.tableEl.appendChild(this.tbodyEl);\n\n container.appendChild(this.el);\n\n this.el.addEventListener('click', this._onViewClick.bind(this));\n this.el.addEventListener('dblclick', this._onViewDblClick.bind(this));\n this.el.addEventListener('contextmenu', this._onViewContextMenu.bind(this));\n this.el.addEventListener('keydown', this._onKeyDown.bind(this));\n\n this.refresh();\n }\n\n // -------------------------------------------------------------------------\n // Node rendering\n // -------------------------------------------------------------------------\n\n refresh(): void {\n if (!this.tbodyEl) return;\n this.tbodyEl.innerHTML = '';\n this._rowCache.clear();\n\n const flatData = this.store.flattenNodes() as NodeInterface[];\n const frag = document.createDocumentFragment();\n for (const node of flatData) {\n if (node.isRoot() && !this.rootVisible) continue;\n frag.appendChild(this._buildRow(node));\n }\n this.tbodyEl.appendChild(frag);\n }\n\n private _buildRow(node: NodeInterface): HTMLTableRowElement {\n const tr = document.createElement('tr');\n tr.className = 'x-grid-row x-treegrid-node';\n tr.setAttribute('role', 'row');\n const nodeId = String((node as any).getId?.() ?? '');\n tr.setAttribute('data-record-id', nodeId);\n tr.setAttribute('data-depth', String(node.depth ?? 0));\n if (nodeId) this._rowCache.set(nodeId, tr);\n tr.setAttribute('tabindex', '-1');\n\n // ARIA\n const isExplicitLeaf = (node as any).get('leaf') === true;\n tr.setAttribute('aria-level', String((node.depth ?? 0) + 1));\n if (!isExplicitLeaf) {\n tr.setAttribute('aria-expanded', node.isExpanded() ? 'true' : 'false');\n }\n tr.setAttribute('aria-selected', 'false');\n\n const parent = node.parentNode;\n if (parent) {\n tr.setAttribute('aria-setsize', String(parent.childNodes.length));\n const idx = parent.childNodes.indexOf(node);\n tr.setAttribute('aria-posinset', String(idx + 1));\n }\n\n if (node.isExpanded()) tr.classList.add('x-treegrid-expanded');\n else if (!isExplicitLeaf) tr.classList.add('x-treegrid-collapsed');\n if (isExplicitLeaf) tr.classList.add('x-treegrid-leaf');\n if (node.isRoot()) tr.classList.add('x-treegrid-root-node');\n\n // Cells\n for (let i = 0; i < this.columns.length; i++) {\n const col = this.columns[i];\n if (col.hidden) continue;\n const td = document.createElement('td');\n td.className = 'x-grid-cell';\n td.setAttribute('role', 'gridcell');\n const inner = document.createElement('div');\n inner.className = 'x-grid-cell-inner';\n\n if (col instanceof TreeGridColumn) {\n td.classList.add('x-treegrid-cell');\n inner.innerHTML = col.renderCell(node, this.checkable, this.lines);\n } else {\n inner.innerHTML = col.renderValue(node);\n }\n\n td.appendChild(inner);\n tr.appendChild(td);\n }\n\n return tr;\n }\n\n refreshNode(record: NodeInterface): void {\n const row = this.getNodeRow(record);\n if (!row || !this.tbodyEl) return;\n const newRow = this._buildRow(record);\n // Transfer focus state\n if (row.getAttribute('tabindex') === '0') {\n newRow.setAttribute('tabindex', '0');\n }\n if (row.getAttribute('aria-selected') === 'true') {\n newRow.setAttribute('aria-selected', 'true');\n newRow.classList.add('x-treegrid-selected');\n }\n this.tbodyEl.replaceChild(newRow, row);\n // _buildRow already updated cache; no extra step needed\n }\n\n // -------------------------------------------------------------------------\n // Expand / Collapse DOM updates\n // -------------------------------------------------------------------------\n\n onNodeExpand(parentNode: NodeInterface, childNodes: NodeInterface[]): void {\n if (!this.tbodyEl) return;\n const parentRow = this.getNodeRow(parentNode);\n\n // Update parent row expand state\n if (parentRow) {\n parentRow.classList.remove('x-treegrid-collapsed');\n parentRow.classList.add('x-treegrid-expanded');\n parentRow.setAttribute('aria-expanded', 'true');\n // Refresh tree column cell (to update expander icon)\n this._refreshTreeColumnCell(parentRow as HTMLTableRowElement, parentNode);\n }\n\n // Insert child rows after parent row\n if (parentRow) {\n const newRows: HTMLTableRowElement[] = [];\n for (const child of this._flattenVisible(parentNode)) {\n if (child === parentNode) continue;\n newRows.push(this._buildRow(child));\n }\n let refNode: Node = parentRow;\n for (const rowEl of newRows) {\n refNode.parentNode?.insertBefore(rowEl, refNode.nextSibling);\n refNode = rowEl;\n }\n }\n\n this.fireEvent('expand', parentNode, childNodes);\n }\n\n onNodeCollapse(parentNode: NodeInterface): void {\n if (!this.tbodyEl) return;\n const parentRow = this.getNodeRow(parentNode);\n\n if (parentRow) {\n parentRow.classList.remove('x-treegrid-expanded');\n parentRow.classList.add('x-treegrid-collapsed');\n parentRow.setAttribute('aria-expanded', 'false');\n this._refreshTreeColumnCell(parentRow as HTMLTableRowElement, parentNode);\n }\n\n // Remove all descendant rows\n const rows = Array.from(this.tbodyEl.querySelectorAll('tr[data-record-id]')) as HTMLElement[];\n const toRemove: HTMLElement[] = [];\n let removing = false;\n\n for (const row of rows) {\n if (removing) {\n const rowDepth = parseInt(row.getAttribute('data-depth') ?? '0', 10);\n const parentDepth = parentNode.depth ?? 0;\n if (rowDepth > parentDepth) {\n toRemove.push(row);\n } else {\n removing = false;\n }\n }\n if (row === parentRow) {\n removing = true;\n }\n }\n\n for (const row of toRemove) {\n const rid = row.getAttribute('data-record-id');\n if (rid) this._rowCache.delete(rid);\n row.remove();\n }\n this.fireEvent('collapse', parentNode);\n }\n\n onNodeInsert(parent: NodeInterface, _node: NodeInterface): void {\n if (!parent.isExpanded() && !parent.isRoot()) return;\n this.refresh();\n }\n\n onNodeRemove(_parent: NodeInterface, node: NodeInterface): void {\n const id = String((node as any).getId?.() ?? '');\n if (id) this._rowCache.delete(id);\n const row = this.getNodeRow(node);\n if (row) row.remove();\n }\n\n onNodeUpdate(node: NodeInterface): void {\n this.refreshNode(node);\n }\n\n // -------------------------------------------------------------------------\n // Node lookup\n // -------------------------------------------------------------------------\n\n getNodeRow(record: NodeInterface): HTMLElement | null {\n if (!this.tbodyEl) return null;\n const id = (record as any).getId?.();\n if (id == null) return null;\n return this._rowCache.get(String(id)) ?? null;\n }\n\n getRecord(rowElement: HTMLElement): NodeInterface | null {\n let el: HTMLElement | null = rowElement;\n while (el) {\n const id = el.getAttribute('data-record-id');\n if (id !== null) {\n return (this.store.getNodeById(id) as NodeInterface | undefined) ?? null;\n }\n el = el.parentElement;\n }\n return null;\n }\n\n getNodeByEvent(event: Event): NodeInterface | null {\n return this.getRecord(event.target as HTMLElement);\n }\n\n // -------------------------------------------------------------------------\n // Focus\n // -------------------------------------------------------------------------\n\n focusRow(record: NodeInterface): void {\n const row = this.getNodeRow(record);\n if (!row) return;\n\n // Remove focus from previous\n if (this.tbodyEl) {\n this.tbodyEl.querySelectorAll('tr[tabindex=\"0\"]').forEach((r) => {\n (r as HTMLElement).setAttribute('tabindex', '-1');\n (r as HTMLElement).classList.remove('x-treegrid-focused');\n });\n }\n\n row.setAttribute('tabindex', '0');\n row.classList.add('x-treegrid-focused');\n this.focusedNode = record;\n row.focus();\n }\n\n getFocusedNode(): NodeInterface | null {\n return this.focusedNode;\n }\n\n // -------------------------------------------------------------------------\n // Selection visual update\n // -------------------------------------------------------------------------\n\n markSelected(record: NodeInterface, selected: boolean): void {\n const row = this.getNodeRow(record);\n if (!row) return;\n row.setAttribute('aria-selected', selected ? 'true' : 'false');\n if (selected) {\n row.classList.add('x-treegrid-selected');\n } else {\n row.classList.remove('x-treegrid-selected');\n }\n }\n\n // -------------------------------------------------------------------------\n // Loading indicator\n // -------------------------------------------------------------------------\n\n showLoadingIndicator(node: NodeInterface): void {\n const row = this.getNodeRow(node);\n if (row) row.classList.add('x-treegrid-loading');\n }\n\n hideLoadingIndicator(node: NodeInterface): void {\n const row = this.getNodeRow(node);\n if (row) row.classList.remove('x-treegrid-loading');\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _refreshTreeColumnCell(row: HTMLTableRowElement, node: NodeInterface): void {\n const treeColIdx = this.columns.findIndex((c) => c instanceof TreeGridColumn);\n if (treeColIdx === -1) return;\n const cells = row.querySelectorAll('td');\n const visibleIdx = this._visibleColumnIndex(treeColIdx);\n const cell = cells[visibleIdx];\n if (!cell) return;\n const inner = cell.querySelector('.x-grid-cell-inner');\n if (inner) {\n inner.innerHTML = (this.columns[treeColIdx] as TreeGridColumn).renderCell(\n node,\n this.checkable,\n this.lines,\n );\n }\n }\n\n private _visibleColumnIndex(colIdx: number): number {\n let count = 0;\n for (let i = 0; i < colIdx; i++) {\n if (!this.columns[i].hidden) count++;\n }\n return count;\n }\n\n private _flattenVisible(node: NodeInterface): NodeInterface[] {\n const result: NodeInterface[] = [];\n const walk = (n: NodeInterface) => {\n result.push(n);\n if (n.isExpanded()) {\n for (const child of n.childNodes) walk(child);\n }\n };\n walk(node);\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Event handlers\n // -------------------------------------------------------------------------\n\n private _getRowRecord(e: Event): NodeInterface | null {\n let el = e.target as HTMLElement | null;\n while (el && el !== this.el) {\n if (el.hasAttribute('data-record-id')) {\n const id = el.getAttribute('data-record-id')!;\n return (this.store.getNodeById(id) as NodeInterface | undefined) ?? null;\n }\n el = el.parentElement;\n }\n return null;\n }\n\n private _onViewClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n\n // Check if click on expander\n if (\n target.classList.contains('x-treegrid-expander') &&\n !target.classList.contains('x-treegrid-expander-leaf')\n ) {\n const record = this._getRowRecord(e);\n if (record) {\n if (record.isExpanded()) {\n this.store.collapseNode(record);\n } else {\n this.store.expandNode(record);\n }\n this.fireEvent('expanderclick', record, e);\n return;\n }\n }\n\n // Check if click on checkbox\n if (target.classList.contains('x-treegrid-checkbox')) {\n const record = this._getRowRecord(e);\n if (record) {\n this.fireEvent('checkboxclick', record, e);\n return;\n }\n }\n\n const record = this._getRowRecord(e);\n if (record) {\n this.fireEvent('itemclick', record, e);\n }\n }\n\n private _onViewDblClick(e: MouseEvent): void {\n const record = this._getRowRecord(e);\n if (record) this.fireEvent('itemdblclick', record, e);\n }\n\n private _onViewContextMenu(e: MouseEvent): void {\n const record = this._getRowRecord(e);\n if (record) this.fireEvent('itemcontextmenu', record, e);\n }\n\n private _onKeyDown(e: KeyboardEvent): void {\n const rows = this.tbodyEl\n ? (Array.from(this.tbodyEl.querySelectorAll('tr[data-record-id]')) as HTMLElement[])\n : [];\n const focused = document.activeElement as HTMLElement;\n const idx = rows.indexOf(focused);\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n const next = rows[idx + 1];\n if (next) {\n focused?.setAttribute('tabindex', '-1');\n focused?.classList.remove('x-treegrid-focused');\n next.setAttribute('tabindex', '0');\n next.classList.add('x-treegrid-focused');\n next.focus();\n const record = this.getRecord(next);\n if (record) this.focusedNode = record;\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n const prev = rows[idx - 1];\n if (prev) {\n focused?.setAttribute('tabindex', '-1');\n focused?.classList.remove('x-treegrid-focused');\n prev.setAttribute('tabindex', '0');\n prev.classList.add('x-treegrid-focused');\n prev.focus();\n const record = this.getRecord(prev);\n if (record) this.focusedNode = record;\n }\n } else if (e.key === 'ArrowRight') {\n const record = this.getRecord(focused);\n if (record && !record.isLeaf()) {\n if (!record.isExpanded()) {\n this.store.expandNode(record);\n this.fireEvent('expanderclick', record, e);\n }\n }\n } else if (e.key === 'ArrowLeft') {\n const record = this.getRecord(focused);\n if (record && record.isExpanded()) {\n this.store.collapseNode(record);\n this.fireEvent('expanderclick', record, e);\n } else if (record && record.parentNode && !record.parentNode.isRoot()) {\n const parentRow = this.getNodeRow(record.parentNode);\n if (parentRow) {\n focused?.setAttribute('tabindex', '-1');\n parentRow.setAttribute('tabindex', '0');\n parentRow.focus();\n this.focusedNode = record.parentNode;\n }\n }\n } else if (e.key === 'Enter' || e.key === ' ') {\n const record = this.getRecord(focused);\n if (record) this.fireEvent('itemclick', record, e);\n } else if (e.key === 'Home') {\n const first = rows[0];\n if (first) {\n focused?.setAttribute('tabindex', '-1');\n first.setAttribute('tabindex', '0');\n first.focus();\n }\n } else if (e.key === 'End') {\n const last = rows[rows.length - 1];\n if (last) {\n focused?.setAttribute('tabindex', '-1');\n last.setAttribute('tabindex', '0');\n last.focus();\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Config updates\n // -------------------------------------------------------------------------\n\n setColumns(columns: (TreeGridColumn | Column)[]): void {\n this.columns = columns;\n this.refresh();\n }\n\n setCheckable(checkable: boolean): void {\n this.checkable = checkable;\n this.refresh();\n }\n}\n","/**\n * @framesquared/ui – TreeGridSelectionModel\n *\n * Selection model for TreeGrid. Supports SINGLE, SIMPLE, and MULTI modes.\n * Tree-aware: tracks selected nodes from flatData, supports range selection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridSelectionModelConfig {\n mode?: 'SINGLE' | 'SIMPLE' | 'MULTI';\n deselectOnCollapse?: boolean;\n pruneRemoved?: boolean;\n checkboxSelect?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridSelectionModel\n// ---------------------------------------------------------------------------\n\nexport class TreeGridSelectionModel {\n private mode: 'SINGLE' | 'SIMPLE' | 'MULTI';\n private selected: Set<NodeInterface> = new Set();\n private listeners: Map<string, Function[]> = new Map();\n readonly deselectOnCollapse: boolean;\n readonly pruneRemoved: boolean;\n readonly checkboxSelect: boolean;\n private anchor: NodeInterface | null = null;\n\n constructor(config: TreeGridSelectionModelConfig = {}) {\n this.mode = config.mode ?? 'SINGLE';\n this.deselectOnCollapse = config.deselectOnCollapse ?? false;\n this.pruneRemoved = config.pruneRemoved ?? true;\n this.checkboxSelect = config.checkboxSelect ?? false;\n }\n\n // -------------------------------------------------------------------------\n // Event system\n // -------------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n if (!this.listeners.has(event)) this.listeners.set(event, []);\n this.listeners.get(event)!.push(fn);\n }\n\n un(event: string, fn: Function): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n const i = fns.indexOf(fn);\n if (i !== -1) fns.splice(i, 1);\n }\n\n private fireEvent(event: string, ...args: unknown[]): void {\n for (const fn of [...(this.listeners.get(event) ?? [])]) fn(...args);\n }\n\n // -------------------------------------------------------------------------\n // Core selection\n // -------------------------------------------------------------------------\n\n select(\n nodes: NodeInterface | NodeInterface[],\n keepExisting = false,\n suppressEvent = false,\n ): void {\n const isArray = Array.isArray(nodes);\n const toSelect = isArray ? (nodes as NodeInterface[]) : [nodes as NodeInterface];\n if (!keepExisting) {\n this.selected.clear();\n }\n for (const node of toSelect) {\n // In SINGLE mode with a single node, enforce single selection\n if (this.mode === 'SINGLE' && !isArray) {\n this.selected.clear();\n }\n this.selected.add(node);\n this.anchor = node;\n }\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n\n deselect(\n nodes: NodeInterface | NodeInterface[],\n suppressEvent = false,\n ): void {\n const toDeselect = Array.isArray(nodes) ? nodes : [nodes];\n for (const node of toDeselect) this.selected.delete(node);\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n\n deselectAll(suppressEvent = false): void {\n this.selected.clear();\n this.anchor = null;\n if (!suppressEvent) this.fireEvent('selectionchange', this, []);\n }\n\n selectAll(flatData: NodeInterface[], suppressEvent = false): void {\n for (const node of flatData) this.selected.add(node);\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n\n /**\n * Selects a range of nodes between anchor and the given node (inclusive).\n */\n selectRange(\n flatData: NodeInterface[],\n toNode: NodeInterface,\n suppressEvent = false,\n ): void {\n if (this.mode !== 'MULTI') return;\n const anchorIdx = this.anchor ? flatData.indexOf(this.anchor) : 0;\n const toIdx = flatData.indexOf(toNode);\n if (anchorIdx === -1 || toIdx === -1) return;\n const lo = Math.min(anchorIdx, toIdx);\n const hi = Math.max(anchorIdx, toIdx);\n this.selected.clear();\n for (let i = lo; i <= hi; i++) this.selected.add(flatData[i]);\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n\n isSelected(node: NodeInterface): boolean {\n return this.selected.has(node);\n }\n\n getSelection(): NodeInterface[] {\n return Array.from(this.selected);\n }\n\n getCount(): number {\n return this.selected.size;\n }\n\n getMode(): string {\n return this.mode;\n }\n\n setMode(mode: 'SINGLE' | 'SIMPLE' | 'MULTI'): void {\n this.mode = mode;\n if (mode === 'SINGLE' && this.selected.size > 1) {\n const first = this.selected.values().next().value;\n this.selected.clear();\n if (first) this.selected.add(first);\n }\n }\n\n /**\n * Removes a node from selection (for use when a node is removed from the store).\n */\n onNodeRemoved(node: NodeInterface): void {\n if (this.pruneRemoved) {\n this.selected.delete(node);\n }\n }\n\n /**\n * If deselectOnCollapse=true, deselects descendants of collapsed node.\n */\n onNodeCollapsed(node: NodeInterface): void {\n if (!this.deselectOnCollapse) return;\n node.cascadeBy((child) => {\n if (child !== node) this.selected.delete(child);\n });\n }\n\n /**\n * Selects all children of a node (direct or deep).\n */\n selectChildren(\n node: NodeInterface,\n deep = false,\n keepExisting = false,\n suppressEvent = false,\n ): void {\n if (!keepExisting) this.selected.clear();\n if (deep) {\n node.cascadeBy((child) => {\n if (child !== node) this.selected.add(child);\n });\n } else {\n node.eachChild((child) => {\n this.selected.add(child);\n });\n }\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n\n deselectChildren(\n node: NodeInterface,\n deep = false,\n suppressEvent = false,\n ): void {\n if (deep) {\n node.cascadeBy((child) => {\n if (child !== node) this.selected.delete(child);\n });\n } else {\n node.eachChild((child) => {\n this.selected.delete(child);\n });\n }\n if (!suppressEvent) this.fireEvent('selectionchange', this, this.getSelection());\n }\n}\n","/**\n * @framesquared/ui – TreeGrid\n *\n * Hybrid tree + grid component. Renders hierarchical data with multiple\n * columns. The first column is a TreeGridColumn (tree chrome + value),\n * subsequent columns display plain field values.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Panel } from '../panel/Panel.js';\nimport type { PanelConfig } from '../panel/Panel.js';\nimport { TreeStore, TreeModel } from '@framesquared/data';\nimport type { TreeStoreConfig, NodeInterface } from '@framesquared/data';\nimport { TreeGridView } from './TreeGridView.js';\nimport { TreeGridColumn, Column } from './TreeGridColumn.js';\nimport type { TreeGridColumnConfig, ColumnConfig } from './TreeGridColumn.js';\nimport { TreeGridSelectionModel } from './TreeGridSelectionModel.js';\nimport type { TreeGridSelectionModelConfig } from './TreeGridSelectionModel.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridConfig extends PanelConfig {\n store: TreeStore | TreeStoreConfig | object[] | NodeInterface;\n rootVisible?: boolean;\n displayField?: string;\n useArrows?: boolean;\n lines?: boolean;\n singleExpand?: boolean;\n animate?: boolean;\n expandOnDblClick?: boolean;\n folderSort?: boolean;\n checkable?: boolean;\n cascadeChecks?: boolean;\n checkPropagation?: 'up' | 'down' | 'both' | 'none';\n onlyLeafCheckable?: boolean;\n columns?: (ColumnConfig | TreeGridColumnConfig)[];\n treeColumn?: TreeGridColumnConfig | number;\n enableDrag?: boolean;\n enableDrop?: boolean;\n ddGroup?: string;\n selModel?: TreeGridSelectionModelConfig;\n emptyText?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGrid\n// ---------------------------------------------------------------------------\n\nexport class TreeGrid extends Panel {\n static override $className = 'Ext.tree.TreeGrid';\n\n readonly isTreeGrid: boolean = true;\n\n declare private _store: TreeStore;\n declare private _columns: (TreeGridColumn | Column)[];\n declare private _treeColumn: TreeGridColumn;\n declare private _view: TreeGridView | null;\n declare private _selModel: TreeGridSelectionModel;\n\n // Config props stored as instance properties for accessor\n declare private _rootVisible: boolean;\n declare private _displayField: string;\n declare private _lines: boolean;\n declare private _singleExpand: boolean;\n declare private _checkable: boolean;\n declare private _cascadeChecks: boolean;\n declare private _checkPropagation: 'up' | 'down' | 'both' | 'none';\n declare private _onlyLeafCheckable: boolean;\n declare private _animate: boolean;\n declare private _expandOnDblClick: boolean;\n declare private _folderSort: boolean;\n\n constructor(config: TreeGridConfig) {\n super(config as any);\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as TreeGridConfig;\n\n // Normalize store\n this._store = this._normalizeStore(cfg.store);\n\n // Config props\n this._rootVisible = cfg.rootVisible ?? false;\n this._displayField = cfg.displayField ?? 'text';\n this._lines = cfg.lines ?? false;\n this._singleExpand = cfg.singleExpand ?? false;\n this._checkable = cfg.checkable ?? false;\n this._cascadeChecks = cfg.cascadeChecks ?? true;\n this._checkPropagation = cfg.checkPropagation ?? 'both';\n this._onlyLeafCheckable = cfg.onlyLeafCheckable ?? false;\n this._animate = cfg.animate ?? true;\n this._expandOnDblClick = cfg.expandOnDblClick ?? true;\n this._folderSort = cfg.folderSort ?? false;\n\n // Normalize columns\n this._columns = this._normalizeColumns(cfg.columns ?? []);\n this._treeColumn = this._columns.find((c) => c instanceof TreeGridColumn) as TreeGridColumn;\n\n // Selection model\n this._selModel = new TreeGridSelectionModel(\n (cfg.selModel as TreeGridSelectionModelConfig) ?? {},\n );\n\n this._view = null;\n\n // Wire store events to relay on this instance\n this._wireStoreEvents();\n }\n\n protected override afterRender(): void {\n super.afterRender();\n\n this.el!.classList.add('x-treegrid');\n\n // Create and render the view into panel body\n this._view = new TreeGridView({\n store: this._store,\n columns: this._columns,\n rootVisible: this._rootVisible,\n checkable: this._checkable,\n lines: this._lines,\n animate: this._animate,\n });\n this._view.render(this.getBodyEl());\n\n // Update ARIA on the view's el\n if (this._view.el) {\n this._view.el.setAttribute('aria-multiselectable', 'false');\n if ((this._config as any).title) {\n this._view.el.setAttribute('aria-label', (this._config as any).title);\n }\n }\n\n // Wire view events\n this._view.on('itemclick', (node: NodeInterface, e: MouseEvent) => {\n this._selModel.select(node, e.ctrlKey || e.metaKey, true);\n this._updateSelectionVisuals();\n this.fire('itemclick', this._view, node, e);\n this.fire('selectionchange', this._selModel, this._selModel.getSelection());\n });\n\n this._view.on('itemdblclick', (node: NodeInterface, e: MouseEvent) => {\n if (this._expandOnDblClick && !node.isLeaf()) {\n this.toggleNode(node);\n }\n this.fire('itemdblclick', this._view, node, e);\n });\n\n this._view.on('itemcontextmenu', (node: NodeInterface, e: MouseEvent) => {\n this.fire('itemcontextmenu', this._view, node, e);\n });\n\n this._view.on('expanderclick', (_node: NodeInterface) => {\n // Already handled by store; just need to refresh\n });\n\n this._view.on('checkboxclick', (node: NodeInterface) => {\n this.toggleChecked(node);\n });\n\n // Wire store events for view refresh\n (this._store as any).on('nodeexpand', (_s: unknown, node: NodeInterface) => {\n if (!node) return;\n if (this._singleExpand) this._collapseSiblings(node);\n this._view?.onNodeExpand(node, node.childNodes);\n this.fire('itemexpand', node, node.childNodes);\n });\n\n (this._store as any).on('nodecollapse', (_s: unknown, node: NodeInterface) => {\n if (!node) return;\n this._selModel.onNodeCollapsed(node);\n this._view?.onNodeCollapse(node);\n this.fire('itemcollapse', node);\n });\n\n (this._store as any).on('nodeappend', (_s: unknown, child: NodeInterface, parent: NodeInterface) => {\n if (!child || !parent) return;\n this._view?.onNodeInsert(parent, child);\n });\n\n (this._store as any).on('nodeinsert', (_s: unknown, node: NodeInterface, _ref: NodeInterface, parent: NodeInterface) => {\n this._view?.onNodeInsert(parent, node);\n });\n\n (this._store as any).on('noderemove', (_s: unknown, child: NodeInterface) => {\n this._selModel.onNodeRemoved(child);\n this._view?.onNodeRemove(child.parentNode ?? this._store.getRootNode(), child);\n });\n\n (this._store as any).on('datachanged', () => {\n this._view?.refresh();\n });\n\n (this._store as any).on('rootchange', () => {\n this._view?.refresh();\n });\n\n // Initialize plugins — must happen after view is rendered\n const plugins = (this._config as any).plugins as any[] | undefined;\n if (plugins) {\n for (const plugin of plugins) {\n if (typeof plugin.init === 'function') {\n plugin.init(this);\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Store normalization\n // -------------------------------------------------------------------------\n\n private _normalizeStore(storeArg: unknown): TreeStore {\n if (storeArg instanceof TreeStore) {\n return storeArg;\n }\n if (Array.isArray(storeArg)) {\n // Array of objects → TreeStore with them as root children\n return new TreeStore({\n model: TreeModel,\n root: {\n id: '__root__',\n text: 'Root',\n expanded: true,\n children: storeArg as Record<string, unknown>[],\n },\n });\n }\n if (typeof storeArg === 'object' && storeArg !== null) {\n // Check if it's a NodeInterface (has childNodes + parentNode + isRoot)\n if (\n 'childNodes' in storeArg &&\n 'parentNode' in storeArg &&\n typeof (storeArg as any).isRoot === 'function'\n ) {\n return new TreeStore({\n model: TreeModel,\n root: (storeArg as any).serialize?.() ?? storeArg,\n });\n }\n // TreeStoreConfig\n if ('model' in storeArg) {\n return new TreeStore(storeArg as TreeStoreConfig);\n }\n // Root data object\n return new TreeStore({\n model: TreeModel,\n root: storeArg as Record<string, unknown>,\n });\n }\n throw new Error('TreeGrid requires a TreeStore or tree data');\n }\n\n // -------------------------------------------------------------------------\n // Column normalization\n // -------------------------------------------------------------------------\n\n private _normalizeColumns(\n cfgColumns: (ColumnConfig | TreeGridColumnConfig)[],\n ): (TreeGridColumn | Column)[] {\n if (cfgColumns.length === 0) {\n // Auto-create a single TreeGridColumn\n return [\n new TreeGridColumn({\n dataIndex: this._displayField,\n text: 'Name',\n flex: 1,\n }),\n ];\n }\n\n const result: (TreeGridColumn | Column)[] = [];\n let treeColCreated = false;\n\n for (let i = 0; i < cfgColumns.length; i++) {\n const cfg = cfgColumns[i] as any;\n if (cfg instanceof TreeGridColumn) {\n result.push(cfg);\n treeColCreated = true;\n } else if (cfg instanceof Column) {\n if (!treeColCreated && i === 0) {\n // Convert first column to TreeGridColumn\n result.push(new TreeGridColumn(cfg as unknown as TreeGridColumnConfig));\n treeColCreated = true;\n } else {\n result.push(cfg);\n }\n } else if (cfg.isTreeGridColumn === true) {\n result.push(new TreeGridColumn(cfg));\n treeColCreated = true;\n } else if (!treeColCreated && i === 0) {\n // Auto-convert first column config to TreeGridColumn\n result.push(new TreeGridColumn(cfg));\n treeColCreated = true;\n } else {\n const col = new Column(cfg);\n (col as any)._autoCreated = true;\n result.push(col);\n }\n }\n\n if (!treeColCreated) {\n result.unshift(\n new TreeGridColumn({ dataIndex: this._displayField, text: 'Name', flex: 1 }),\n );\n }\n\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Store event wiring (relay to this instance)\n // -------------------------------------------------------------------------\n\n private _wireStoreEvents(): void {\n const relayEvents = [\n 'nodeappend',\n 'nodeinsert',\n 'noderemove',\n 'nodemove',\n 'nodeexpand',\n 'nodecollapse',\n 'beforeexpand',\n 'beforecollapse',\n 'nodesort',\n 'rootchange',\n 'checkchange',\n 'load',\n 'beforeload',\n 'datachanged',\n 'refresh',\n ];\n for (const evt of relayEvents) {\n (this._store as any).on(evt, (...args: unknown[]) => {\n this.fire(evt, ...args);\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Store access\n // -------------------------------------------------------------------------\n\n getStore(): TreeStore {\n return this._store;\n }\n\n getRootNode(): NodeInterface {\n return this._store.getRootNode();\n }\n\n setRootNode(rootOrData: NodeInterface | Record<string, unknown>): NodeInterface {\n const root = this._store.setRoot(rootOrData);\n this._view?.refresh();\n return root;\n }\n\n getNodeById(id: string | number): NodeInterface | null {\n return (this._store.getNodeById(id) as NodeInterface | undefined) ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Expand / Collapse\n // -------------------------------------------------------------------------\n\n expandAll(callback?: () => void): void {\n this._store.expandAll();\n this._view?.refresh();\n callback?.();\n }\n\n collapseAll(callback?: () => void): void {\n this._store.collapseAll();\n this._view?.refresh();\n callback?.();\n }\n\n expandNode(node: NodeInterface, deep = false, callback?: (children: NodeInterface[]) => void): void {\n if (this.fire('beforeitemexpand', node) === false) return;\n this._store.expandNode(node);\n if (deep) {\n node.cascadeBy((child) => {\n if (!child.isLeaf() && child !== node) {\n this._store.expandNode(child);\n }\n });\n }\n this._view?.refresh();\n callback?.(node.childNodes);\n }\n\n collapseNode(node: NodeInterface, deep = false, callback?: () => void): void {\n if (this.fire('beforeitemcollapse', node) === false) return;\n this._store.collapseNode(node);\n if (deep) {\n node.cascadeBy((child) => {\n if (!child.isLeaf() && child !== node) {\n this._store.collapseNode(child);\n }\n });\n }\n this._view?.refresh();\n callback?.();\n }\n\n toggleNode(node: NodeInterface): void {\n if (node.isExpanded()) {\n this.collapseNode(node);\n } else {\n this.expandNode(node);\n }\n }\n\n isNodeExpanded(node: NodeInterface): boolean {\n return node.isExpanded();\n }\n\n isNodeLoaded(node: NodeInterface): boolean {\n return node.isLoaded();\n }\n\n async expandPath(\n path: string,\n options: { separator?: string; field?: string; select?: boolean } = {},\n ): Promise<NodeInterface> {\n const separator = options.separator ?? '/';\n const field = options.field ?? 'id';\n const segments = path.split(separator).filter(Boolean);\n\n let current = this._store.getRootNode();\n for (const seg of segments) {\n if (!current.isExpanded()) {\n this._store.expandNode(current);\n }\n const child = current.findChild(field, seg, false);\n if (!child) break;\n current = child;\n }\n\n if (!current.isExpanded() && !current.isLeaf()) {\n this._store.expandNode(current);\n }\n\n this._view?.refresh();\n\n if (options.select) {\n this.select(current);\n }\n return current;\n }\n\n async selectPath(\n path: string,\n options: { separator?: string; field?: string } = {},\n ): Promise<NodeInterface> {\n return this.expandPath(path, { ...options, select: true });\n }\n\n // -------------------------------------------------------------------------\n // Checkbox\n // -------------------------------------------------------------------------\n\n getChecked(): NodeInterface[] {\n if (!this._checkable) return [];\n const result: NodeInterface[] = [];\n this._store.getRootNode().cascadeBy((node) => {\n if ((node as any).$checked === true) result.push(node);\n });\n return result;\n }\n\n getCheckedLeaves(): NodeInterface[] {\n return this.getChecked().filter((n) => n.isLeaf());\n }\n\n setChecked(node: NodeInterface, checked: boolean, suppressEvent = false): void {\n (node as any).$checked = checked;\n\n if (this._cascadeChecks) {\n const prop = this._checkPropagation;\n if (prop === 'both' || prop === 'down') {\n node.cascadeBy((child) => {\n if (child !== node) (child as any).$checked = checked;\n });\n }\n if (prop === 'both' || prop === 'up') {\n this._updateAncestorChecks(node);\n }\n }\n\n this._view?.refreshNode(node);\n\n if (!suppressEvent) {\n this.fire('checkchange', node, checked);\n }\n }\n\n toggleChecked(node: NodeInterface): void {\n const current = (node as any).$checked;\n this.setChecked(node, !current);\n }\n\n checkAll(): void {\n this._store.getRootNode().cascadeBy((node) => {\n (node as any).$checked = true;\n });\n this._view?.refresh();\n }\n\n uncheckAll(): void {\n this._store.getRootNode().cascadeBy((node) => {\n (node as any).$checked = false;\n });\n this._view?.refresh();\n }\n\n private _updateAncestorChecks(node: NodeInterface): void {\n node.bubble((ancestor) => {\n if (ancestor === node || ancestor.isRoot()) return;\n let allChecked = true;\n let someChecked = false;\n ancestor.eachChild((child) => {\n const state = (child as any).$checked;\n if (state === true) someChecked = true;\n else if (state !== true) allChecked = false;\n });\n if (allChecked) {\n (ancestor as any).$checked = true;\n } else if (someChecked) {\n (ancestor as any).$checked = null; // indeterminate\n } else {\n (ancestor as any).$checked = false;\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // Selection\n // -------------------------------------------------------------------------\n\n getSelection(): NodeInterface[] {\n return this._selModel.getSelection();\n }\n\n select(\n nodes: NodeInterface | NodeInterface[] | number | number[],\n keepExisting = false,\n suppressEvent = false,\n ): void {\n const flatData = this._store.flattenNodes() as NodeInterface[];\n const toSelect = (Array.isArray(nodes) ? nodes : [nodes]).map((n) =>\n typeof n === 'number' ? flatData[n] : n,\n ).filter(Boolean) as NodeInterface[];\n\n this._selModel.select(toSelect, keepExisting, suppressEvent);\n this._updateSelectionVisuals();\n if (!suppressEvent) {\n this.fire('selectionchange', this._selModel, this._selModel.getSelection());\n }\n }\n\n deselect(\n nodes: NodeInterface | NodeInterface[] | number | number[],\n suppressEvent = false,\n ): void {\n const flatData = this._store.flattenNodes() as NodeInterface[];\n const toDeselect = (Array.isArray(nodes) ? nodes : [nodes]).map((n) =>\n typeof n === 'number' ? flatData[n] : n,\n ).filter(Boolean) as NodeInterface[];\n\n this._selModel.deselect(toDeselect, suppressEvent);\n this._updateSelectionVisuals();\n }\n\n deselectAll(suppressEvent = false): void {\n const prev = this._selModel.getSelection();\n this._selModel.deselectAll(suppressEvent);\n for (const node of prev) this._view?.markSelected(node, false);\n }\n\n selectAll(suppressEvent = false): void {\n const flatData = this._store.flattenNodes() as NodeInterface[];\n this._selModel.selectAll(flatData, suppressEvent);\n this._updateSelectionVisuals();\n }\n\n private _updateSelectionVisuals(): void {\n const selected = new Set(this._selModel.getSelection());\n const flatData = this._store.flattenNodes() as NodeInterface[];\n for (const node of flatData) {\n this._view?.markSelected(node, selected.has(node));\n }\n }\n\n // -------------------------------------------------------------------------\n // Scroll\n // -------------------------------------------------------------------------\n\n async scrollToNode(\n node: NodeInterface,\n options: { focus?: boolean; select?: boolean } = {},\n ): Promise<void> {\n // Expand ancestors\n let ancestor = node.parentNode;\n while (ancestor && !ancestor.isRoot()) {\n if (!ancestor.isExpanded()) {\n this._store.expandNode(ancestor);\n }\n ancestor = ancestor.parentNode;\n }\n this._view?.refresh();\n\n const row = this._view?.getNodeRow(node);\n row?.scrollIntoView?.({ block: 'nearest' });\n\n if (options.focus) this._view?.focusRow(node);\n if (options.select) this.select(node);\n }\n\n async ensureNodeVisible(node: NodeInterface): Promise<void> {\n return this.scrollToNode(node);\n }\n\n // -------------------------------------------------------------------------\n // View / Column access\n // -------------------------------------------------------------------------\n\n getView(): TreeGridView {\n return this._view!;\n }\n\n getTreeColumn(): TreeGridColumn {\n return this._treeColumn;\n }\n\n getColumns(): (TreeGridColumn | Column)[] {\n return this._columns;\n }\n\n getColumnByDataIndex(dataIndex: string): Column | undefined {\n return this._columns.find((c) => c.dataIndex === dataIndex);\n }\n\n getNodeRow(node: NodeInterface): HTMLElement | null {\n return this._view?.getNodeRow(node) ?? null;\n }\n\n getNodeFromRow(rowEl: HTMLElement): NodeInterface | null {\n return this._view?.getRecord(rowEl) ?? null;\n }\n\n getDepthIndent(depth: number): number {\n return depth * this._treeColumn.indentSize;\n }\n\n // -------------------------------------------------------------------------\n // Reload\n // -------------------------------------------------------------------------\n\n reload(): Promise<NodeInterface[]> {\n this._store.collapseAll();\n this._view?.refresh();\n return Promise.resolve(this._store.getRootNode().childNodes);\n }\n\n // -------------------------------------------------------------------------\n // Config accessors\n // -------------------------------------------------------------------------\n\n isRootVisible(): boolean {\n return this._rootVisible;\n }\n\n isCheckable(): boolean {\n return this._checkable;\n }\n\n getDisplayField(): string {\n return this._displayField;\n }\n\n // -------------------------------------------------------------------------\n // Single expand helper\n // -------------------------------------------------------------------------\n\n private _collapseSiblings(expandedNode: NodeInterface): void {\n const parent = expandedNode.parentNode;\n if (!parent) return;\n parent.eachChild((sibling) => {\n if (sibling !== expandedNode && sibling.isExpanded()) {\n this._store.collapseNode(sibling);\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // Event helper\n // -------------------------------------------------------------------------\n\n protected fire(eventName: string, ...args: unknown[]): boolean {\n if (typeof (this as any).fireEvent === 'function') {\n return (this as any).fireEvent(eventName, ...args);\n }\n return true;\n }\n}\n","/**\n * @framesquared/ui – TreeGridDragDrop\n *\n * Drag-and-drop plugin for TreeGrid. Enables reparenting and reordering\n * of tree nodes via pointer events.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type DropPosition = 'before' | 'after' | 'append';\n\nexport interface DragData {\n records: NodeInterface[];\n source: TreeGrid;\n copy: boolean;\n displayText: string;\n}\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridDragDropConfig {\n enableDrag?: boolean;\n enableDrop?: boolean;\n ddGroup?: string;\n appendOnly?: boolean;\n sortOnDrop?: boolean;\n allowContainerDrops?: boolean;\n expandDelay?: number;\n allowParentInserts?: boolean;\n displayField?: string;\n dragText?: string;\n copy?: boolean;\n allowCopy?: boolean;\n dropHighlightCls?: string;\n dropIndicatorCls?: string;\n nodeHighlightOnDrop?: boolean;\n containerScrollOnDrag?: boolean;\n containerScrollThreshold?: number;\n containerScrollSpeed?: number;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridDragDrop\n// ---------------------------------------------------------------------------\n\nexport class TreeGridDragDrop {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridDragDropConfig>;\n\n // Drag state\n private dragging = false;\n private dragData: DragData | null = null;\n private ghostEl: HTMLElement | null = null;\n private dropIndicatorEl: HTMLElement | null = null;\n private highlightedRow: HTMLElement | null = null;\n private expandTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Captured at pointerdown so movement/scroll can't change which node is dragged\n private _pendingRecord: NodeInterface | null = null;\n private _captureTarget: Element | null = null;\n private _pointerId: number | null = null;\n\n private _downX = 0;\n private _downY = 0;\n private readonly _threshold = 5;\n\n // Bound handlers for cleanup\n private _onPointerDown: (e: PointerEvent) => void;\n private _onPointerMove: (e: PointerEvent) => void;\n private _onPointerUp: (e: PointerEvent) => void;\n\n constructor(config: TreeGridDragDropConfig = {}) {\n this.config = {\n enableDrag: config.enableDrag ?? true,\n enableDrop: config.enableDrop ?? true,\n ddGroup: config.ddGroup ?? 'TreeGridDD',\n appendOnly: config.appendOnly ?? false,\n sortOnDrop: config.sortOnDrop ?? false,\n allowContainerDrops: config.allowContainerDrops ?? false,\n expandDelay: config.expandDelay ?? 500,\n allowParentInserts: config.allowParentInserts ?? true,\n displayField: config.displayField ?? 'text',\n dragText: config.dragText ?? '{0} selected node(s)',\n copy: config.copy ?? false,\n allowCopy: config.allowCopy ?? true,\n dropHighlightCls: config.dropHighlightCls ?? 'x-treegrid-drop-highlight',\n dropIndicatorCls: config.dropIndicatorCls ?? 'x-treegrid-drop-indicator',\n nodeHighlightOnDrop: config.nodeHighlightOnDrop ?? true,\n containerScrollOnDrag: config.containerScrollOnDrag ?? true,\n containerScrollThreshold: config.containerScrollThreshold ?? 40,\n containerScrollSpeed: config.containerScrollSpeed ?? 10,\n };\n\n this._onPointerDown = this._handlePointerDown.bind(this);\n this._onPointerMove = this._handlePointerMove.bind(this);\n this._onPointerUp = this._handlePointerUp.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n const viewEl = treeGrid.getView()?.el;\n if (!viewEl) return;\n viewEl.addEventListener('pointerdown', this._onPointerDown);\n }\n\n destroy(): void {\n const viewEl = this.treeGrid?.getView()?.el;\n if (viewEl) viewEl.removeEventListener('pointerdown', this._onPointerDown);\n document.removeEventListener('pointermove', this._onPointerMove);\n document.removeEventListener('pointerup', this._onPointerUp);\n this._cleanup();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Drag start\n // -------------------------------------------------------------------------\n\n private _handlePointerDown(e: PointerEvent): void {\n if (!this.config.enableDrag) return;\n const record = this.treeGrid?.getView().getNodeByEvent(e);\n if (!record) return;\n if (record.isRoot()) return;\n if ((record as any).get?.('allowDrag') === false) return;\n\n // Prevent native text-selection and browser drag-image from interfering\n e.preventDefault();\n\n this._downX = e.clientX;\n this._downY = e.clientY;\n\n // Capture record now while we're certain which node the pointer is over\n this._pendingRecord = record;\n\n // setPointerCapture ensures pointermove/pointerup reach us even if the\n // pointer leaves the browser window before the user releases\n try {\n (e.target as Element).setPointerCapture(e.pointerId);\n this._captureTarget = e.target as Element;\n this._pointerId = e.pointerId;\n } catch (_) { /* ignore — older browsers */ }\n\n document.addEventListener('pointermove', this._onPointerMove);\n document.addEventListener('pointerup', this._onPointerUp);\n }\n\n private _handlePointerMove(e: PointerEvent): void {\n if (!this.dragging) {\n const dx = Math.abs(e.clientX - this._downX);\n const dy = Math.abs(e.clientY - this._downY);\n if (dx < this._threshold && dy < this._threshold) return;\n\n // Start drag — use the record captured at pointerdown, not a new hit-test\n // (the view may have scrolled since the press, making re-hit-test unreliable)\n const record = this._pendingRecord;\n if (!record) return;\n\n const selection = this.treeGrid?.getSelection() ?? [];\n const records = selection.includes(record) && selection.length > 1\n ? selection\n : [record];\n\n const displayText = records.length === 1\n ? String((records[0] as any).get?.(this.config.displayField) ?? '')\n : this.config.dragText.replace('{0}', String(records.length));\n\n const isCopy = this.config.copy || ((e.ctrlKey || e.metaKey) && this.config.allowCopy);\n\n this.dragData = { records, source: this.treeGrid!, copy: isCopy, displayText };\n this.dragging = true;\n this._createGhost(displayText, e.clientX, e.clientY);\n return;\n }\n\n // Update ghost position\n if (this.ghostEl) {\n this.ghostEl.style.left = `${e.clientX + 10}px`;\n this.ghostEl.style.top = `${e.clientY + 10}px`;\n }\n\n if (!this.config.enableDrop) return;\n\n // Hit test\n const target = this._getRecordAtPoint(e.clientX, e.clientY);\n this._clearDropIndicators();\n\n if (!target) {\n this._cancelExpandTimer();\n return;\n }\n\n // Validate drop\n if (!this._isValidDrop(target)) {\n this._cancelExpandTimer();\n return;\n }\n\n const position = this._computeDropPosition(e.clientY, target);\n this._showDropIndicator(target, position);\n\n // Auto expand on hover\n if (!target.isLeaf() && !target.isExpanded() && position === 'append') {\n this._startExpandTimer(target);\n } else {\n this._cancelExpandTimer();\n }\n }\n\n private _handlePointerUp(e: PointerEvent): void {\n document.removeEventListener('pointermove', this._onPointerMove);\n document.removeEventListener('pointerup', this._onPointerUp);\n\n if (!this.dragging || !this.dragData) {\n this._cleanup();\n return;\n }\n\n const target = this._getRecordAtPoint(e.clientX, e.clientY);\n\n if (target && this.config.enableDrop && this._isValidDrop(target)) {\n const position = this._computeDropPosition(e.clientY, target);\n const isCopy =\n this.config.copy || ((e.ctrlKey || e.metaKey) && this.config.allowCopy);\n this.dragData.copy = isCopy;\n\n // Fire beforedrop\n const store = this.treeGrid?.getStore();\n if (store) {\n this._executeDrop(target, position, store);\n }\n }\n\n this._cleanup();\n }\n\n // -------------------------------------------------------------------------\n // Drop execution\n // -------------------------------------------------------------------------\n\n private _executeDrop(\n target: NodeInterface,\n position: DropPosition,\n store: any,\n ): void {\n if (!this.dragData) return;\n const { records, copy } = this.dragData;\n\n // Deduplicate: remove nodes that are descendants of other dragged nodes\n const deduplicated = records.filter(\n (r) => !records.some((other) => other !== r && other.contains(r)),\n );\n\n if (copy) {\n for (const rec of deduplicated) {\n const clone = (rec as any).copy?.(true) ?? rec;\n this._insertNode(clone, target, position, store);\n }\n } else {\n // Remove from old positions first\n for (const rec of deduplicated) {\n const parent = rec.parentNode;\n if (parent) parent.removeChild(rec);\n }\n // Insert at new position\n for (const rec of deduplicated) {\n this._insertNode(rec, target, position, store);\n }\n }\n\n if (this.config.sortOnDrop) {\n const newParent = position === 'append' ? target : target.parentNode;\n if (newParent) {\n // Re-sort children (basic sort by displayField)\n const field = this.config.displayField;\n newParent.childNodes.sort((a, b) => {\n const av = String((a as any).get?.(field) ?? '');\n const bv = String((b as any).get?.(field) ?? '');\n return av.localeCompare(bv);\n });\n }\n }\n\n // If dropped into a collapsed folder, expand it so the node is visible\n if (position === 'append' && !target.isExpanded()) {\n target.expanded = true;\n }\n\n this.treeGrid?.getView().refresh();\n (this.treeGrid as any)?.fireEvent?.('drop', target, this.dragData, target, position);\n }\n\n private _insertNode(\n node: NodeInterface,\n target: NodeInterface,\n position: DropPosition,\n _store: any,\n ): void {\n if (position === 'append') {\n target.appendChild(node);\n } else if (position === 'before') {\n const parent = target.parentNode;\n if (parent) parent.insertBefore(node, target);\n } else {\n // 'after'\n const parent = target.parentNode;\n if (!parent) return;\n const idx = parent.childNodes.indexOf(target);\n if (idx === parent.childNodes.length - 1) {\n parent.appendChild(node);\n } else {\n parent.insertBefore(node, parent.childNodes[idx + 1]);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Validation\n // -------------------------------------------------------------------------\n\n private _isValidDrop(target: NodeInterface): boolean {\n if (!this.dragData) return false;\n for (const rec of this.dragData.records) {\n if (rec === target) return false;\n if (rec.contains(target)) return false;\n }\n if ((target as any).get?.('allowDrop') === false) return false;\n return true;\n }\n\n private _computeDropPosition(clientY: number, target: NodeInterface): DropPosition {\n if (this.config.appendOnly) return 'append';\n\n const row = this.treeGrid?.getNodeRow(target);\n if (!row) return 'append';\n\n const rect = row.getBoundingClientRect();\n const relY = clientY - rect.top;\n const h = rect.height;\n\n if (target.isLeaf()) {\n return relY < h / 2 ? 'before' : 'after';\n }\n\n if (relY < h * 0.25) return 'before';\n if (relY > h * 0.75) return 'after';\n return 'append';\n }\n\n // -------------------------------------------------------------------------\n // Visual helpers\n // -------------------------------------------------------------------------\n\n private _createGhost(text: string, x: number, y: number): void {\n this.ghostEl = document.createElement('div');\n this.ghostEl.className = 'x-treegrid-drag-ghost';\n this.ghostEl.style.cssText =\n `position:fixed;z-index:9999;pointer-events:none;` +\n `background:#fff;border:1px solid #aaa;padding:4px 8px;` +\n `left:${x + 10}px;top:${y + 10}px;`;\n this.ghostEl.textContent = text;\n document.body.appendChild(this.ghostEl);\n }\n\n private _clearDropIndicators(): void {\n if (this.highlightedRow) {\n this.highlightedRow.classList.remove(this.config.dropHighlightCls);\n this.highlightedRow = null;\n }\n this.dropIndicatorEl?.remove();\n this.dropIndicatorEl = null;\n }\n\n private _showDropIndicator(target: NodeInterface, position: DropPosition): void {\n const row = this.treeGrid?.getNodeRow(target);\n if (!row) return;\n\n if (position === 'append') {\n row.classList.add(this.config.dropHighlightCls);\n this.highlightedRow = row;\n } else {\n // Use position:fixed anchored to getBoundingClientRect so the indicator\n // is always visible regardless of table/tr positioning context differences\n // across browsers (Firefox does not honour position:relative on <tr>).\n const rect = row.getBoundingClientRect();\n const y = position === 'before' ? rect.top : rect.bottom;\n\n this.dropIndicatorEl = document.createElement('div');\n this.dropIndicatorEl.className = this.config.dropIndicatorCls;\n this.dropIndicatorEl.style.cssText =\n `position:fixed;left:${rect.left}px;width:${rect.width}px;` +\n `top:${y - 1}px;height:2px;background:#0070C0;pointer-events:none;z-index:9999;`;\n document.body.appendChild(this.dropIndicatorEl);\n }\n }\n\n private _startExpandTimer(target: NodeInterface): void {\n if (this.expandTimer) return;\n this.expandTimer = setTimeout(() => {\n this.treeGrid?.expandNode(target);\n this.expandTimer = null;\n }, this.config.expandDelay);\n }\n\n private _cancelExpandTimer(): void {\n if (this.expandTimer !== null) {\n clearTimeout(this.expandTimer);\n this.expandTimer = null;\n }\n }\n\n private _cleanup(): void {\n this.dragging = false;\n this.dragData = null;\n this._pendingRecord = null;\n\n if (this._captureTarget !== null && this._pointerId !== null) {\n try {\n this._captureTarget.releasePointerCapture(this._pointerId);\n } catch (_) { /* ignore */ }\n this._captureTarget = null;\n this._pointerId = null;\n }\n\n this.ghostEl?.remove();\n this.ghostEl = null;\n this._clearDropIndicators();\n this._cancelExpandTimer();\n }\n\n // -------------------------------------------------------------------------\n // Hit test\n // -------------------------------------------------------------------------\n\n private _getRecordAtPoint(x: number, y: number): NodeInterface | null {\n const el = document.elementFromPoint(x, y) as HTMLElement | null;\n if (!el) return null;\n return this.treeGrid?.getView().getRecord(el) ?? null;\n }\n}\n","/**\n * @framesquared/ui – TreeGridCellEditing\n *\n * Tree-aware inline cell editing plugin for TreeGrid.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { EditorConfig } from './TreeGridColumn.js';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridCellEditingConfig {\n editableTreeColumn?: boolean;\n addChildOnInsert?: boolean;\n addSiblingOnEnter?: boolean;\n clicksToEdit?: number;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridCellEditing\n// ---------------------------------------------------------------------------\n\nexport class TreeGridCellEditing {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridCellEditingConfig>;\n private activeEditor: HTMLElement | null = null;\n private editingRecord: NodeInterface | null = null;\n private editingField: string | null = null;\n\n private _onClick: (e: MouseEvent) => void;\n private _onDblClick: (e: MouseEvent) => void;\n\n constructor(config: TreeGridCellEditingConfig = {}) {\n this.config = {\n editableTreeColumn: config.editableTreeColumn ?? true,\n addChildOnInsert: config.addChildOnInsert ?? false,\n addSiblingOnEnter: config.addSiblingOnEnter ?? false,\n clicksToEdit: config.clicksToEdit ?? 2,\n };\n this._onClick = this._handleClick.bind(this);\n this._onDblClick = this._handleDblClick.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n const viewEl = treeGrid.getView()?.el;\n if (!viewEl) return;\n if (this.config.clicksToEdit === 1) {\n viewEl.addEventListener('click', this._onClick);\n } else {\n viewEl.addEventListener('dblclick', this._onDblClick);\n }\n }\n\n destroy(): void {\n const viewEl = this.treeGrid?.getView()?.el;\n if (viewEl) {\n viewEl.removeEventListener('click', this._onClick);\n viewEl.removeEventListener('dblclick', this._onDblClick);\n }\n this.cancelEdit();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Edit lifecycle\n // -------------------------------------------------------------------------\n\n startEdit(record: NodeInterface, dataIndex: string): void {\n if (this.activeEditor) this.completeEdit();\n\n const view = this.treeGrid?.getView();\n if (!view) return;\n\n const row = view.getNodeRow(record);\n if (!row) return;\n\n const columns = this.treeGrid?.getColumns() ?? [];\n const colIdx = columns.findIndex((c) => c.dataIndex === dataIndex);\n if (colIdx === -1) return;\n\n const col = columns[colIdx];\n\n // Column marked read-only\n if (col.editor === false) return;\n\n const cells = row.querySelectorAll('td');\n const cell = cells[colIdx] as HTMLElement;\n if (!cell) return;\n\n const value = (record as any).get?.(dataIndex) ?? '';\n this.editingRecord = record;\n this.editingField = dataIndex;\n\n // Create the appropriate editor element\n const editorCfg = col.editor ?? null;\n const editor = this._createEditorElement(editorCfg, value);\n\n cell.style.position = 'relative';\n cell.appendChild(editor);\n\n const focusable = editor.querySelector<HTMLElement>('input,select,textarea') ?? editor;\n if ((focusable as HTMLInputElement).select) {\n (focusable as HTMLInputElement).select?.();\n }\n focusable.focus();\n\n this.activeEditor = editor;\n\n const onKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.completeEdit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n this.cancelEdit();\n } else if (e.key === 'Tab') {\n e.preventDefault();\n this.completeEdit();\n this._focusNextCell(record, dataIndex, e.shiftKey);\n }\n };\n\n const onBlur = (): void => {\n setTimeout(() => {\n if (this.activeEditor === editor) this.completeEdit();\n }, 150);\n };\n\n // Attach to the focusable child (or the editor wrapper for checkboxes etc.)\n focusable.addEventListener('keydown', onKeydown);\n focusable.addEventListener('blur', onBlur);\n\n // For editors that are a wrapper div (checkbox, radiogroup, colorfield):\n // also attach keydown to the wrapper so Escape/Enter still work\n if (editor !== focusable) {\n editor.addEventListener('keydown', onKeydown);\n }\n }\n\n completeEdit(): void {\n if (!this.activeEditor || !this.editingRecord || !this.editingField) return;\n\n const editorCfg = this._currentEditorConfig();\n const newValue = this._getEditorValue(this.activeEditor, editorCfg);\n\n // Fire validateedit — if returns false, cancel\n const canEdit = this.treeGrid?.getView().el?.dispatchEvent(\n new CustomEvent('validateedit', {\n bubbles: true,\n cancelable: true,\n detail: { record: this.editingRecord, field: this.editingField, value: newValue },\n }),\n );\n\n if (canEdit === false) {\n this.cancelEdit();\n return;\n }\n\n (this.editingRecord as any).set?.(this.editingField, newValue);\n this._removeEditor();\n this.treeGrid?.getView().refreshNode(this.editingRecord);\n this.editingRecord = null;\n this.editingField = null;\n }\n\n cancelEdit(): void {\n this._removeEditor();\n this.editingRecord = null;\n this.editingField = null;\n }\n\n isEditing(): boolean {\n return this.activeEditor !== null;\n }\n\n // -------------------------------------------------------------------------\n // Editor creation\n // -------------------------------------------------------------------------\n\n private _createEditorElement(cfg: EditorConfig | null, value: unknown): HTMLElement {\n const xtype = cfg?.xtype ?? 'textfield';\n const base =\n 'position:absolute;top:0;left:0;z-index:100;width:100%;height:100%;' +\n 'box-sizing:border-box;border:2px solid #3b82f6;outline:none;background:#fff;font:inherit;';\n\n switch (xtype) {\n case 'combobox':\n case 'combo':\n case 'select': {\n const select = document.createElement('select');\n select.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-select';\n select.style.cssText = base + 'padding:0 4px;cursor:pointer;';\n const options = cfg?.options ?? cfg?.store ?? [];\n for (const opt of options) {\n const o = document.createElement('option');\n if (typeof opt === 'string') {\n o.value = opt;\n o.text = opt;\n } else {\n o.value = String(opt.value);\n o.text = opt.text;\n }\n select.appendChild(o);\n }\n select.value = String(value ?? '');\n return select;\n }\n\n case 'checkbox': {\n const wrapper = document.createElement('div');\n wrapper.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-checkbox';\n wrapper.style.cssText =\n 'position:absolute;top:0;left:0;z-index:100;width:100%;height:100%;' +\n 'box-sizing:border-box;border:2px solid #3b82f6;background:#fff;' +\n 'display:flex;align-items:center;justify-content:center;cursor:pointer;';\n const input = document.createElement('input');\n input.type = 'checkbox';\n input.style.cssText = 'width:16px;height:16px;cursor:pointer;';\n input.checked = Boolean(value);\n wrapper.appendChild(input);\n // Clicking the wrapper toggles the checkbox\n wrapper.addEventListener('click', (e) => {\n if (e.target !== input) input.checked = !input.checked;\n });\n return wrapper;\n }\n\n case 'radiogroup': {\n const wrapper = document.createElement('div');\n wrapper.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-radiogroup';\n wrapper.style.cssText =\n 'position:absolute;top:0;left:0;z-index:100;width:100%;height:100%;' +\n 'box-sizing:border-box;border:2px solid #3b82f6;background:#fff;' +\n 'display:flex;align-items:center;gap:8px;padding:0 6px;overflow:hidden;';\n wrapper.setAttribute('tabindex', '0');\n const items = cfg?.options ?? cfg?.store ?? [];\n const groupName = `rg_${Date.now()}`;\n for (const item of items) {\n const v = typeof item === 'string' ? item : String(item.value);\n const t = typeof item === 'string' ? item : item.text;\n const label = document.createElement('label');\n label.style.cssText = 'display:flex;align-items:center;gap:3px;cursor:pointer;white-space:nowrap;font:inherit;';\n const radio = document.createElement('input');\n radio.type = 'radio';\n radio.name = groupName;\n radio.value = v;\n radio.checked = String(value) === v;\n label.appendChild(radio);\n label.appendChild(document.createTextNode(t));\n wrapper.appendChild(label);\n }\n return wrapper;\n }\n\n case 'numberfield':\n case 'number': {\n const input = document.createElement('input');\n input.type = 'number';\n input.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-number';\n input.style.cssText = base + 'padding:0 6px;';\n input.value = String(value ?? '');\n if (cfg?.minValue != null) input.min = String(cfg.minValue);\n if (cfg?.maxValue != null) input.max = String(cfg.maxValue);\n if (cfg?.step != null) input.step = String(cfg.step);\n return input;\n }\n\n case 'datefield':\n case 'date': {\n const input = document.createElement('input');\n input.type = 'date';\n input.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-date';\n input.style.cssText = base + 'padding:0 6px;';\n input.value = String(value ?? '');\n return input;\n }\n\n case 'colorfield':\n case 'color': {\n const wrapper = document.createElement('div');\n wrapper.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-color';\n wrapper.style.cssText =\n 'position:absolute;top:0;left:0;z-index:100;width:100%;height:100%;' +\n 'box-sizing:border-box;border:2px solid #3b82f6;background:#fff;' +\n 'display:flex;align-items:center;gap:4px;padding:0 4px;';\n const colorInput = document.createElement('input');\n colorInput.type = 'color';\n colorInput.style.cssText = 'width:32px;height:24px;border:none;padding:0;cursor:pointer;background:transparent;';\n colorInput.value = String(value ?? '#000000');\n const textInput = document.createElement('input');\n textInput.type = 'text';\n textInput.style.cssText = 'flex:1;border:none;outline:none;font:inherit;background:transparent;';\n textInput.value = String(value ?? '');\n colorInput.addEventListener('input', () => { textInput.value = colorInput.value; });\n textInput.addEventListener('input', () => {\n if (/^#[0-9a-fA-F]{6}$/.test(textInput.value)) {\n colorInput.value = textInput.value;\n }\n });\n wrapper.appendChild(colorInput);\n wrapper.appendChild(textInput);\n return wrapper;\n }\n\n case 'textarea':\n case 'textareafield': {\n const ta = document.createElement('textarea');\n ta.className = 'x-treegrid-cell-editor x-treegrid-cell-editor-textarea';\n ta.style.cssText = base + 'padding:2px 6px;resize:none;';\n if (cfg?.rows) ta.rows = cfg.rows;\n ta.value = String(value ?? '');\n return ta;\n }\n\n default: {\n const input = document.createElement('input');\n input.type = 'text';\n input.className = 'x-treegrid-cell-editor';\n input.style.cssText = base + 'padding:0 6px;';\n input.value = String(value ?? '');\n return input;\n }\n }\n }\n\n private _getEditorValue(editor: HTMLElement, cfg: EditorConfig | null): unknown {\n const xtype = cfg?.xtype ?? 'textfield';\n\n switch (xtype) {\n case 'checkbox': {\n const input = editor.querySelector<HTMLInputElement>('input[type=\"checkbox\"]');\n return input ? input.checked : false;\n }\n case 'radiogroup': {\n const checked = editor.querySelector<HTMLInputElement>('input[type=\"radio\"]:checked');\n return checked ? checked.value : '';\n }\n case 'colorfield':\n case 'color': {\n const text = editor.querySelector<HTMLInputElement>('input[type=\"text\"]');\n return text ? text.value : '';\n }\n case 'numberfield':\n case 'number': {\n return (editor as HTMLInputElement).valueAsNumber;\n }\n default: {\n const focusable = editor.querySelector<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>(\n 'input,select,textarea',\n );\n return focusable ? focusable.value : (editor as HTMLInputElement).value ?? '';\n }\n }\n }\n\n private _currentEditorConfig(): EditorConfig | null {\n if (!this.editingField) return null;\n const columns = this.treeGrid?.getColumns() ?? [];\n const col = columns.find((c) => c.dataIndex === this.editingField);\n if (!col || col.editor === false || col.editor == null) return null;\n return col.editor;\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _removeEditor(): void {\n this.activeEditor?.remove();\n this.activeEditor = null;\n }\n\n private _focusNextCell(\n record: NodeInterface,\n currentDataIndex: string,\n reverse = false,\n ): void {\n const columns = this.treeGrid?.getColumns() ?? [];\n const currentIdx = columns.findIndex((c) => c.dataIndex === currentDataIndex);\n const nextIdx = reverse ? currentIdx - 1 : currentIdx + 1;\n\n if (nextIdx >= 0 && nextIdx < columns.length) {\n this.startEdit(record, columns[nextIdx].dataIndex);\n } else {\n // Move to next/prev row's first/last column\n const flatData = this.treeGrid?.getStore().flattenNodes() as NodeInterface[];\n const rowIdx = flatData.indexOf(record);\n const nextRowIdx = reverse ? rowIdx - 1 : rowIdx + 1;\n if (nextRowIdx >= 0 && nextRowIdx < flatData.length) {\n const col = reverse ? columns[columns.length - 1] : columns[0];\n this.startEdit(flatData[nextRowIdx], col.dataIndex);\n }\n }\n }\n\n private _handleClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n // Don't start edit on expander or checkbox\n if (\n target.classList.contains('x-treegrid-expander') ||\n target.classList.contains('x-treegrid-checkbox')\n ) {\n if (this.activeEditor) this.completeEdit();\n return;\n }\n this._startEditFromEvent(e);\n }\n\n private _handleDblClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n if (\n target.classList.contains('x-treegrid-expander') ||\n target.classList.contains('x-treegrid-checkbox')\n ) {\n if (this.activeEditor) this.completeEdit();\n return;\n }\n this._startEditFromEvent(e);\n }\n\n private _startEditFromEvent(e: MouseEvent): void {\n const view = this.treeGrid?.getView();\n if (!view) return;\n const record = view.getNodeByEvent(e);\n if (!record) return;\n\n const cell = (e.target as HTMLElement).closest('td') as HTMLElement;\n if (!cell) return;\n\n const row = cell.parentElement as HTMLElement;\n const cellIdx = Array.from(row.children).indexOf(cell);\n const columns = this.treeGrid?.getColumns() ?? [];\n const col = columns[cellIdx];\n if (!col) return;\n\n this.startEdit(record, col.dataIndex);\n }\n}\n","/**\n * @framesquared/ui – TreeGridRowEditing\n *\n * Tree-aware row editing plugin for TreeGrid.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridRowEditingConfig {\n clicksToEdit?: number;\n autoCancel?: boolean;\n saveBtnText?: string;\n cancelBtnText?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridRowEditing\n// ---------------------------------------------------------------------------\n\nexport class TreeGridRowEditing {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridRowEditingConfig>;\n private editingRecord: NodeInterface | null = null;\n private editorRow: HTMLElement | null = null;\n private fieldMap: Map<string, HTMLInputElement> = new Map();\n\n private _onDblClick: (e: MouseEvent) => void;\n\n constructor(config: TreeGridRowEditingConfig = {}) {\n this.config = {\n clicksToEdit: config.clicksToEdit ?? 2,\n autoCancel: config.autoCancel ?? true,\n saveBtnText: config.saveBtnText ?? 'Update',\n cancelBtnText: config.cancelBtnText ?? 'Cancel',\n };\n this._onDblClick = this._handleDblClick.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n const viewEl = treeGrid.getView()?.el;\n if (viewEl) viewEl.addEventListener('dblclick', this._onDblClick);\n }\n\n destroy(): void {\n const viewEl = this.treeGrid?.getView()?.el;\n if (viewEl) viewEl.removeEventListener('dblclick', this._onDblClick);\n this.cancelEdit();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Edit lifecycle\n // -------------------------------------------------------------------------\n\n startEdit(record: NodeInterface): void {\n if (this.editingRecord) this.cancelEdit();\n\n this.editingRecord = record;\n const view = this.treeGrid?.getView();\n if (!view) return;\n\n const row = view.getNodeRow(record);\n if (!row) return;\n\n const columns = this.treeGrid?.getColumns() ?? [];\n\n // Build editor row\n const editorRow = document.createElement('tr');\n editorRow.className = 'x-treegrid-row-editor';\n this.fieldMap.clear();\n\n for (const col of columns) {\n if (col.hidden) continue;\n const td = document.createElement('td');\n const input = document.createElement('input');\n input.type = 'text';\n input.className = `x-row-editor-field x-row-editor-field-${col.dataIndex}`;\n input.value = String((record as any).get?.(col.dataIndex) ?? '');\n input.setAttribute('data-dataindex', col.dataIndex);\n td.appendChild(input);\n editorRow.appendChild(td);\n this.fieldMap.set(col.dataIndex, input);\n }\n\n // Action buttons\n const actionTd = document.createElement('td');\n actionTd.className = 'x-row-editor-buttons';\n\n const saveBtn = document.createElement('button');\n saveBtn.textContent = this.config.saveBtnText;\n saveBtn.className = 'x-row-editor-save';\n saveBtn.addEventListener('click', () => this.completeEdit());\n\n const cancelBtn = document.createElement('button');\n cancelBtn.textContent = this.config.cancelBtnText;\n cancelBtn.className = 'x-row-editor-cancel';\n cancelBtn.addEventListener('click', () => this.cancelEdit());\n\n actionTd.appendChild(saveBtn);\n actionTd.appendChild(cancelBtn);\n editorRow.appendChild(actionTd);\n\n row.insertAdjacentElement('afterend', editorRow);\n this.editorRow = editorRow;\n\n // Focus first field\n const firstInput = editorRow.querySelector('input') as HTMLInputElement | null;\n firstInput?.focus();\n }\n\n completeEdit(): void {\n if (!this.editingRecord) return;\n for (const [field, input] of this.fieldMap) {\n (this.editingRecord as any).set?.(field, input.value);\n }\n this.treeGrid?.getView().refreshNode(this.editingRecord);\n this._removeEditorRow();\n this.editingRecord = null;\n }\n\n cancelEdit(): void {\n this._removeEditorRow();\n this.editingRecord = null;\n }\n\n isEditing(): boolean {\n return this.editingRecord !== null;\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _removeEditorRow(): void {\n this.editorRow?.remove();\n this.editorRow = null;\n this.fieldMap.clear();\n }\n\n private _handleDblClick(e: MouseEvent): void {\n const view = this.treeGrid?.getView();\n if (!view) return;\n const record = view.getNodeByEvent(e);\n if (!record) return;\n this.startEdit(record);\n }\n}\n","/**\n * @framesquared/ui – TreeGridClipboard\n *\n * Copy/paste plugin for TreeGrid. Supports TSV copy with optional\n * hierarchy indentation and paste as children/siblings.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { TreeModel, applyNodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridClipboardConfig {\n copyHierarchy?: boolean;\n pasteAsChildren?: boolean;\n pasteIndentLevel?: boolean;\n indentCharacter?: string;\n includeHeaders?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridClipboard\n// ---------------------------------------------------------------------------\n\nexport class TreeGridClipboard {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridClipboardConfig>;\n private _onKeyDown: (e: KeyboardEvent) => void;\n\n constructor(config: TreeGridClipboardConfig = {}) {\n this.config = {\n copyHierarchy: config.copyHierarchy ?? false,\n pasteAsChildren: config.pasteAsChildren ?? true,\n pasteIndentLevel: config.pasteIndentLevel ?? false,\n indentCharacter: config.indentCharacter ?? '\\t',\n includeHeaders: config.includeHeaders ?? false,\n };\n this._onKeyDown = this._handleKeyDown.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n const viewEl = treeGrid.getView()?.el;\n if (viewEl) viewEl.addEventListener('keydown', this._onKeyDown);\n }\n\n destroy(): void {\n const viewEl = this.treeGrid?.getView()?.el;\n if (viewEl) viewEl.removeEventListener('keydown', this._onKeyDown);\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Copy\n // -------------------------------------------------------------------------\n\n copyToClipboard(): string {\n const tg = this.treeGrid;\n if (!tg) return '';\n const columns = tg.getColumns();\n const selection = tg.getSelection();\n const nodes = selection.length > 0 ? selection : [];\n\n const rows: string[] = [];\n\n // Header row\n const headers = columns.filter((c) => !c.hidden).map((c) => c.text);\n rows.push(headers.join('\\t'));\n\n for (const node of nodes) {\n const cells: string[] = [];\n for (const col of columns) {\n if (col.hidden) continue;\n let cellValue = String((node as any).get?.(col.dataIndex) ?? '');\n if (this.config.copyHierarchy && col === tg.getTreeColumn()) {\n const depth = node.depth ?? 0;\n cellValue = this.config.indentCharacter.repeat(depth) + cellValue;\n }\n cells.push(cellValue);\n }\n rows.push(cells.join('\\t'));\n }\n\n return rows.join('\\n');\n }\n\n pasteFromText(text: string): void {\n const tg = this.treeGrid;\n if (!tg) return;\n\n const lines = text.split('\\n').filter(Boolean);\n const columns = tg.getColumns().filter((c) => !c.hidden);\n const selection = tg.getSelection();\n const parent =\n selection.length > 0 && this.config.pasteAsChildren\n ? selection[0]\n : tg.getRootNode();\n\n for (const line of lines) {\n const values = line.split('\\t');\n const data: Record<string, unknown> = {};\n for (let i = 0; i < Math.min(values.length, columns.length); i++) {\n data[columns[i].dataIndex] = values[i] ?? '';\n }\n const newNode = TreeModel.create(data) as any;\n if (newNode && typeof newNode.isRoot !== 'function') {\n applyNodeInterface(newNode, (parent.depth ?? 0) + 1);\n }\n tg.getStore().appendChild(parent, newNode);\n }\n\n tg.getView().refresh();\n }\n\n // -------------------------------------------------------------------------\n // Keyboard\n // -------------------------------------------------------------------------\n\n private _handleKeyDown(e: KeyboardEvent): void {\n if ((e.ctrlKey || e.metaKey) && e.key === 'c') {\n e.preventDefault();\n const text = this.copyToClipboard();\n navigator.clipboard?.writeText?.(text);\n }\n }\n}\n","/**\n * @framesquared/ui – TreeGridSummary\n *\n * Feature that adds a summary row aggregating values across visible nodes.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SummaryType = 'sum' | 'count' | 'average' | 'min' | 'max' | 'none';\n\nexport interface SummaryColumnConfig {\n dataIndex: string;\n summaryType?: SummaryType;\n summaryRenderer?: (value: number, count: number) => string;\n}\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridSummaryConfig {\n position?: 'bottom' | 'top';\n includeCollapsed?: boolean;\n treeColumnSummaryText?: string;\n summaryColumns?: SummaryColumnConfig[];\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridSummary\n// ---------------------------------------------------------------------------\n\nexport class TreeGridSummary {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridSummaryConfig>;\n private summaryRowEl: HTMLElement | null = null;\n\n constructor(config: TreeGridSummaryConfig = {}) {\n this.config = {\n position: config.position ?? 'bottom',\n includeCollapsed: config.includeCollapsed ?? true,\n treeColumnSummaryText: config.treeColumnSummaryText ?? 'Summary',\n summaryColumns: config.summaryColumns ?? [],\n };\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n // Wire store events to recalculate\n (treeGrid.getStore() as any).on('datachanged', () => this.updateSummary());\n (treeGrid.getStore() as any).on('nodeexpand', () => this.updateSummary());\n (treeGrid.getStore() as any).on('nodecollapse', () => this.updateSummary());\n }\n\n destroy(): void {\n this.summaryRowEl?.remove();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Render\n // -------------------------------------------------------------------------\n\n renderSummary(): void {\n if (!this.treeGrid) return;\n const viewEl = this.treeGrid.getView()?.el;\n if (!viewEl) return;\n\n this.summaryRowEl?.remove();\n\n const tableEl = viewEl.querySelector('table');\n if (!tableEl) return;\n\n const summaryRow = this._buildSummaryRow();\n this.summaryRowEl = summaryRow;\n\n if (this.config.position === 'top') {\n tableEl.insertAdjacentElement('afterbegin', summaryRow);\n } else {\n tableEl.appendChild(summaryRow);\n }\n }\n\n updateSummary(): void {\n this.renderSummary();\n }\n\n // -------------------------------------------------------------------------\n // Calculation\n // -------------------------------------------------------------------------\n\n calculateSummary(dataIndex: string, summaryType: SummaryType): number {\n const nodes = this._getNodes();\n if (summaryType === 'count') return nodes.length;\n\n const values = nodes\n .map((n) => parseFloat(String((n as any).get?.(dataIndex) ?? '0')))\n .filter((v) => !isNaN(v));\n\n if (values.length === 0) return 0;\n\n switch (summaryType) {\n case 'sum':\n return values.reduce((a, b) => a + b, 0);\n case 'average':\n return values.reduce((a, b) => a + b, 0) / values.length;\n case 'min':\n return Math.min(...values);\n case 'max':\n return Math.max(...values);\n default:\n return 0;\n }\n }\n\n private _getNodes(): NodeInterface[] {\n const tg = this.treeGrid!;\n if (this.config.includeCollapsed) {\n const all: NodeInterface[] = [];\n tg.getRootNode().cascadeBy((n) => {\n if (!n.isRoot()) all.push(n);\n });\n return all;\n }\n // Only visible (expanded) nodes\n return (tg.getStore().flattenNodes() as NodeInterface[]).filter((n) => !n.isRoot());\n }\n\n private _buildSummaryRow(): HTMLElement {\n const tg = this.treeGrid!;\n const columns = tg.getColumns();\n const treeCol = tg.getTreeColumn();\n\n const tr = document.createElement('tr');\n tr.className = 'x-treegrid-summary-row';\n tr.setAttribute('role', 'row');\n\n for (const col of columns) {\n if (col.hidden) continue;\n const td = document.createElement('td');\n td.className = 'x-grid-cell x-treegrid-summary-cell';\n const inner = document.createElement('div');\n inner.className = 'x-grid-cell-inner';\n\n if (col === treeCol) {\n inner.textContent = this.config.treeColumnSummaryText;\n } else {\n const summaryColCfg = this.config.summaryColumns.find(\n (sc) => sc.dataIndex === col.dataIndex,\n );\n if (summaryColCfg && summaryColCfg.summaryType && summaryColCfg.summaryType !== 'none') {\n const val = this.calculateSummary(col.dataIndex, summaryColCfg.summaryType);\n const nodes = this._getNodes();\n inner.textContent = summaryColCfg.summaryRenderer\n ? summaryColCfg.summaryRenderer(val, nodes.length)\n : String(val);\n } else {\n inner.textContent = '';\n }\n }\n\n td.appendChild(inner);\n tr.appendChild(td);\n }\n\n return tr;\n }\n}\n","/**\n * @framesquared/ui – TreeGridGroupingSummary\n *\n * Feature adding per-parent summary rows after each expanded parent's last child.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\nimport type { SummaryType, SummaryColumnConfig } from './TreeGridSummary.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridGroupingSummaryConfig {\n includeDescendants?: boolean;\n summaryRowCls?: string;\n showSummaryFor?: 'all' | 'nonleaf';\n summaryColumns?: SummaryColumnConfig[];\n treeColumnSummaryText?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridGroupingSummary\n// ---------------------------------------------------------------------------\n\nexport class TreeGridGroupingSummary {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridGroupingSummaryConfig>;\n\n constructor(config: TreeGridGroupingSummaryConfig = {}) {\n this.config = {\n includeDescendants: config.includeDescendants ?? false,\n summaryRowCls: config.summaryRowCls ?? 'x-treegrid-summary-row',\n showSummaryFor: config.showSummaryFor ?? 'nonleaf',\n summaryColumns: config.summaryColumns ?? [],\n treeColumnSummaryText: config.treeColumnSummaryText ?? 'Summary',\n };\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n (treeGrid.getStore() as any).on('datachanged', () => this._renderGroupSummaries());\n (treeGrid.getStore() as any).on('nodeexpand', () => this._renderGroupSummaries());\n (treeGrid.getStore() as any).on('nodecollapse', () => this._renderGroupSummaries());\n }\n\n destroy(): void {\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Render\n // -------------------------------------------------------------------------\n\n private _renderGroupSummaries(): void {\n if (!this.treeGrid) return;\n const viewEl = this.treeGrid.getView()?.el;\n if (!viewEl) return;\n\n // Remove existing summary rows\n viewEl.querySelectorAll(`.${this.config.summaryRowCls}`).forEach((el) => el.remove());\n\n const flatData = (this.treeGrid.getStore().flattenNodes() as NodeInterface[]).filter(\n (n) => !n.isRoot(),\n );\n\n // Find expanded non-leaf nodes\n const insertions: { afterEl: HTMLElement; summaryRow: HTMLElement }[] = [];\n\n for (const node of flatData) {\n const shouldShow =\n this.config.showSummaryFor === 'all' || !node.isLeaf();\n if (!shouldShow || !node.isExpanded() || node.isLeaf()) continue;\n\n const lastChild = node.lastChild;\n if (!lastChild) continue;\n\n // Find the last visible descendant of node\n const lastDescendant = this._findLastVisible(node);\n const lastRow = this.treeGrid.getNodeRow(lastDescendant);\n if (!lastRow) continue;\n\n const summaryRow = this._buildGroupSummaryRow(node);\n insertions.push({ afterEl: lastRow, summaryRow });\n }\n\n // Insert in reverse order to maintain positions\n for (const { afterEl, summaryRow } of insertions.reverse()) {\n afterEl.insertAdjacentElement('afterend', summaryRow);\n }\n }\n\n private _findLastVisible(node: NodeInterface): NodeInterface {\n if (node.isLeaf() || !node.isExpanded()) return node;\n const last = node.lastChild;\n if (!last) return node;\n return this._findLastVisible(last);\n }\n\n private _buildGroupSummaryRow(parent: NodeInterface): HTMLElement {\n const tg = this.treeGrid!;\n const columns = tg.getColumns();\n\n const tr = document.createElement('tr');\n tr.className = this.config.summaryRowCls;\n tr.setAttribute('role', 'row');\n tr.setAttribute('aria-selected', 'false');\n tr.setAttribute('data-summary-for', String((parent as any).getId?.() ?? ''));\n\n const depth = (parent.depth ?? 0) + 1;\n const indent = depth * tg.getTreeColumn().indentSize;\n\n for (const col of columns) {\n if (col.hidden) continue;\n const td = document.createElement('td');\n td.className = 'x-grid-cell x-treegrid-summary-cell';\n const inner = document.createElement('div');\n inner.className = 'x-grid-cell-inner';\n\n if (col === tg.getTreeColumn()) {\n inner.style.paddingLeft = `${indent}px`;\n inner.textContent = this.config.treeColumnSummaryText;\n } else {\n const summaryColCfg = this.config.summaryColumns.find(\n (sc) => sc.dataIndex === col.dataIndex,\n );\n if (summaryColCfg?.summaryType && summaryColCfg.summaryType !== 'none') {\n const val = this._calculate(parent, col.dataIndex, summaryColCfg.summaryType);\n const nodes = this._getChildNodes(parent);\n inner.textContent = summaryColCfg.summaryRenderer\n ? summaryColCfg.summaryRenderer(val, nodes.length)\n : String(val);\n }\n }\n\n td.appendChild(inner);\n tr.appendChild(td);\n }\n\n return tr;\n }\n\n private _getChildNodes(parent: NodeInterface): NodeInterface[] {\n if (this.config.includeDescendants) {\n const result: NodeInterface[] = [];\n parent.cascadeBy((n) => {\n if (n !== parent) result.push(n);\n });\n return result;\n }\n return parent.childNodes;\n }\n\n private _calculate(parent: NodeInterface, dataIndex: string, summaryType: SummaryType): number {\n const nodes = this._getChildNodes(parent);\n if (summaryType === 'count') return nodes.length;\n\n const values = nodes\n .map((n) => parseFloat(String((n as any).get?.(dataIndex) ?? '0')))\n .filter((v) => !isNaN(v));\n\n if (values.length === 0) return 0;\n\n switch (summaryType) {\n case 'sum': return values.reduce((a, b) => a + b, 0);\n case 'average': return values.reduce((a, b) => a + b, 0) / values.length;\n case 'min': return Math.min(...values);\n case 'max': return Math.max(...values);\n default: return 0;\n }\n }\n}\n","/**\n * @framesquared/ui – TreeGridRowExpander\n *\n * Plugin adding a detail-view expander column to each row.\n * Independent from tree expand/collapse.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridRowExpanderConfig {\n rowBodyTpl?: string | ((node: NodeInterface) => string);\n expandOnDblClick?: boolean;\n singleRowExpand?: boolean;\n bodyIndent?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridRowExpander\n// ---------------------------------------------------------------------------\n\nexport class TreeGridRowExpander {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridRowExpanderConfig>;\n private expandedRows: Set<string | number> = new Set();\n private bodyRowMap: Map<string | number, HTMLElement> = new Map();\n\n private _onClick: (e: MouseEvent) => void;\n private _onDblClick: (e: MouseEvent) => void;\n\n constructor(config: TreeGridRowExpanderConfig = {}) {\n this.config = {\n rowBodyTpl: config.rowBodyTpl ?? '',\n expandOnDblClick: config.expandOnDblClick ?? false,\n singleRowExpand: config.singleRowExpand ?? false,\n bodyIndent: config.bodyIndent ?? true,\n };\n this._onClick = this._handleClick.bind(this);\n this._onDblClick = this._handleDblClick.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n const viewEl = treeGrid.getView()?.el;\n if (!viewEl) return;\n viewEl.addEventListener('click', this._onClick);\n if (this.config.expandOnDblClick) {\n viewEl.addEventListener('dblclick', this._onDblClick);\n }\n }\n\n destroy(): void {\n const viewEl = this.treeGrid?.getView()?.el;\n if (viewEl) {\n viewEl.removeEventListener('click', this._onClick);\n viewEl.removeEventListener('dblclick', this._onDblClick);\n }\n this.bodyRowMap.forEach((el) => el.remove());\n this.bodyRowMap.clear();\n this.expandedRows.clear();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Expand / Collapse\n // -------------------------------------------------------------------------\n\n expandRow(record: NodeInterface): void {\n const id = (record as any).getId?.();\n if (id == null) return;\n\n if (this.config.singleRowExpand) {\n // Collapse all others first\n for (const existingId of this.expandedRows) {\n if (existingId !== id) this._collapseById(existingId);\n }\n }\n\n if (this.expandedRows.has(id)) return;\n this.expandedRows.add(id);\n this._insertBodyRow(record);\n }\n\n collapseRow(record: NodeInterface): void {\n const id = (record as any).getId?.();\n if (id == null) return;\n this._collapseById(id);\n }\n\n toggleRow(record: NodeInterface): void {\n const id = (record as any).getId?.();\n if (id == null) return;\n if (this.expandedRows.has(id)) {\n this.collapseRow(record);\n } else {\n this.expandRow(record);\n }\n }\n\n isRowExpanded(record: NodeInterface): boolean {\n const id = (record as any).getId?.();\n return id != null && this.expandedRows.has(id);\n }\n\n // -------------------------------------------------------------------------\n // DOM\n // -------------------------------------------------------------------------\n\n private _insertBodyRow(record: NodeInterface): void {\n const tg = this.treeGrid!;\n const view = tg.getView();\n const row = view.getNodeRow(record);\n if (!row) return;\n\n const colCount = tg.getColumns().filter((c) => !c.hidden).length + 1; // +1 for expander col\n\n const bodyRow = document.createElement('tr');\n bodyRow.className = 'x-treegrid-row-body';\n\n const td = document.createElement('td');\n td.colSpan = colCount;\n td.className = 'x-treegrid-row-body-cell';\n\n if (this.config.bodyIndent) {\n const depth = record.depth ?? 0;\n const indent = depth * tg.getTreeColumn().indentSize;\n td.style.paddingLeft = `${indent + tg.getTreeColumn().indentSize}px`;\n }\n\n const tpl = this.config.rowBodyTpl;\n const content = tpl\n ? typeof tpl === 'function' ? tpl(record) : this._renderTpl(tpl, record)\n : '';\n td.innerHTML = content;\n\n bodyRow.appendChild(td);\n\n // Insert after the data row (before tree children)\n row.insertAdjacentElement('afterend', bodyRow);\n\n const id = (record as any).getId?.();\n if (id != null) this.bodyRowMap.set(id, bodyRow);\n }\n\n private _collapseById(id: string | number): void {\n const bodyRow = this.bodyRowMap.get(id);\n bodyRow?.remove();\n this.bodyRowMap.delete(id);\n this.expandedRows.delete(id);\n }\n\n private _renderTpl(tpl: string, record: NodeInterface): string {\n return tpl.replace(/\\{(\\w+)\\}/g, (_match, field) => {\n return String((record as any).get?.(field) ?? '');\n });\n }\n\n // -------------------------------------------------------------------------\n // Event handlers\n // -------------------------------------------------------------------------\n\n private _handleClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n if (!target.classList.contains('x-treegrid-row-expander-btn')) return;\n const view = this.treeGrid?.getView();\n if (!view) return;\n const record = view.getRecord(target);\n if (record) this.toggleRow(record);\n }\n\n private _handleDblClick(e: MouseEvent): void {\n const view = this.treeGrid?.getView();\n if (!view) return;\n const record = view.getNodeByEvent(e);\n if (record) this.toggleRow(record);\n }\n}\n","/**\n * @framesquared/ui – TreeGridFilterPlugin\n *\n * Column filter integration for TreeGrid with tree-aware filtering.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridFilterPluginConfig {\n filterer?: 'bottomup' | 'topdown';\n showFilterRow?: boolean;\n menuFilter?: boolean;\n}\n\nexport interface FilterValue {\n dataIndex: string;\n value: unknown;\n operator?: 'eq' | 'lt' | 'gt' | 'contains' | 'gte' | 'lte';\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridFilterPlugin\n// ---------------------------------------------------------------------------\n\nexport class TreeGridFilterPlugin {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridFilterPluginConfig>;\n private activeFilters: FilterValue[] = [];\n private filterRowEl: HTMLElement | null = null;\n\n constructor(config: TreeGridFilterPluginConfig = {}) {\n this.config = {\n filterer: config.filterer ?? 'bottomup',\n showFilterRow: config.showFilterRow ?? false,\n menuFilter: config.menuFilter ?? true,\n };\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n if (this.config.showFilterRow) {\n this._renderFilterRow();\n }\n }\n\n destroy(): void {\n this.filterRowEl?.remove();\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // Filter API\n // -------------------------------------------------------------------------\n\n addFilter(filter: FilterValue): void {\n const existing = this.activeFilters.findIndex((f) => f.dataIndex === filter.dataIndex);\n if (existing !== -1) {\n this.activeFilters[existing] = filter;\n } else {\n this.activeFilters.push(filter);\n }\n this._applyFilters();\n }\n\n removeFilter(dataIndex: string): void {\n this.activeFilters = this.activeFilters.filter((f) => f.dataIndex !== dataIndex);\n this._applyFilters();\n }\n\n clearFilters(): void {\n this.activeFilters = [];\n this._applyFilters();\n }\n\n getActiveFilters(): FilterValue[] {\n return [...this.activeFilters];\n }\n\n getFilteredCount(): number {\n if (!this.treeGrid) return 0;\n return this._getVisibleNodes().length;\n }\n\n // -------------------------------------------------------------------------\n // Filtering logic\n // -------------------------------------------------------------------------\n\n private _applyFilters(): void {\n if (!this.treeGrid) return;\n\n if (this.activeFilters.length === 0) {\n // Show all nodes\n this._showAllNodes(this.treeGrid.getRootNode());\n this.treeGrid.getView().refresh();\n return;\n }\n\n if (this.config.filterer === 'bottomup') {\n this._applyBottomUp(this.treeGrid.getRootNode());\n } else {\n this._applyTopDown(this.treeGrid.getRootNode(), true);\n }\n\n this.treeGrid.getView().refresh();\n }\n\n /** bottomup: a node is visible if it or any descendant matches */\n private _applyBottomUp(node: NodeInterface): boolean {\n let anyChildVisible = false;\n for (const child of node.childNodes) {\n const visible = this._applyBottomUp(child);\n if (visible) anyChildVisible = true;\n }\n\n if (node.isRoot()) {\n // Root always visible; expand if any children visible\n if (anyChildVisible) node.expanded = true;\n return true;\n }\n\n const nodeMatches = this._matchesAllFilters(node);\n const visible = nodeMatches || anyChildVisible;\n\n // Mark node hidden/shown via a custom property\n (node as any)._filterHidden = !visible;\n\n if (anyChildVisible && !node.isLeaf()) {\n node.expanded = true;\n }\n\n return visible;\n }\n\n /** topdown: a node is visible only if it and all ancestors match */\n private _applyTopDown(node: NodeInterface, parentVisible: boolean): void {\n const visible = parentVisible && (node.isRoot() || this._matchesAllFilters(node));\n (node as any)._filterHidden = !visible;\n\n for (const child of node.childNodes) {\n this._applyTopDown(child, visible);\n }\n }\n\n private _matchesAllFilters(node: NodeInterface): boolean {\n return this.activeFilters.every((f) => this._matchesFilter(node, f));\n }\n\n private _matchesFilter(node: NodeInterface, filter: FilterValue): boolean {\n const nodeVal = (node as any).get?.(filter.dataIndex);\n const filterVal = filter.value;\n const op = filter.operator ?? 'contains';\n\n switch (op) {\n case 'eq':\n return nodeVal === filterVal;\n case 'lt':\n return Number(nodeVal) < Number(filterVal);\n case 'gt':\n return Number(nodeVal) > Number(filterVal);\n case 'gte':\n return Number(nodeVal) >= Number(filterVal);\n case 'lte':\n return Number(nodeVal) <= Number(filterVal);\n case 'contains':\n default:\n return String(nodeVal ?? '').toLowerCase().includes(String(filterVal ?? '').toLowerCase());\n }\n }\n\n private _showAllNodes(node: NodeInterface): void {\n (node as any)._filterHidden = false;\n for (const child of node.childNodes) {\n this._showAllNodes(child);\n }\n }\n\n private _getVisibleNodes(): NodeInterface[] {\n const result: NodeInterface[] = [];\n if (!this.treeGrid) return result;\n this.treeGrid.getRootNode().cascadeBy((n) => {\n if (!n.isRoot() && !(n as any)._filterHidden) result.push(n);\n });\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Filter row UI\n // -------------------------------------------------------------------------\n\n private _renderFilterRow(): void {\n const tg = this.treeGrid!;\n const viewEl = tg.getView()?.el;\n if (!viewEl) return;\n\n const tableEl = viewEl.querySelector('table');\n if (!tableEl) return;\n\n const filterRow = document.createElement('tr');\n filterRow.className = 'x-treegrid-filter-row';\n\n for (const col of tg.getColumns()) {\n if (col.hidden) continue;\n const td = document.createElement('td');\n const input = document.createElement('input');\n input.type = 'text';\n input.placeholder = `Filter ${col.text}...`;\n input.className = 'x-treegrid-filter-input';\n input.setAttribute('data-dataindex', col.dataIndex);\n input.addEventListener('input', () => {\n const val = input.value.trim();\n if (val) {\n this.addFilter({ dataIndex: col.dataIndex, value: val, operator: 'contains' });\n } else {\n this.removeFilter(col.dataIndex);\n }\n });\n td.appendChild(input);\n filterRow.appendChild(td);\n }\n\n tableEl.insertAdjacentElement('afterbegin', filterRow);\n this.filterRowEl = filterRow;\n }\n}\n","/**\n * @framesquared/ui – TreeGridStateMixin\n *\n * State persistence for TreeGrid. Saves and restores column widths,\n * expanded nodes, sort, checked state, scroll position, and filters.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ColumnStateEntry {\n id: string;\n width?: number;\n flex?: number;\n hidden?: boolean;\n}\n\nexport interface TreeGridState {\n columns?: ColumnStateEntry[];\n columnOrder?: string[];\n expandedNodes?: (string | number)[];\n checkedNodes?: (string | number)[];\n selectedNodes?: (string | number)[];\n scrollPosition?: { top: number; left: number };\n sorters?: { property: string; direction: 'ASC' | 'DESC' }[];\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridStateMixin\n// ---------------------------------------------------------------------------\n\nexport class TreeGridStateMixin {\n private treeGrid: TreeGrid | null = null;\n private stateId: string;\n private saveDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly saveDebounceMs = 100;\n\n constructor(stateId: string | { stateId: string }) {\n this.stateId = typeof stateId === 'string' ? stateId : stateId.stateId;\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n this._wireEvents();\n }\n\n destroy(): void {\n if (this.saveDebounceTimer !== null) {\n clearTimeout(this.saveDebounceTimer);\n }\n this.treeGrid = null;\n }\n\n // -------------------------------------------------------------------------\n // State API\n // -------------------------------------------------------------------------\n\n getState(): TreeGridState {\n const tg = this.treeGrid;\n if (!tg) return {};\n\n const columns = tg.getColumns().map((col) => ({\n id: col.dataIndex,\n width: col.width,\n flex: col.flex,\n hidden: col.hidden,\n }));\n\n const expandedNodes: (string | number)[] = [];\n tg.getRootNode().cascadeBy((node) => {\n if (!node.isRoot() && node.isExpanded()) {\n const id = (node as any).getId?.();\n if (id != null) expandedNodes.push(id);\n }\n });\n\n const checkedNodes: (string | number)[] = [];\n if (tg.isCheckable()) {\n for (const node of tg.getChecked()) {\n const id = (node as any).getId?.();\n if (id != null) checkedNodes.push(id);\n }\n }\n\n const selectedNodes: (string | number)[] = [];\n for (const node of tg.getSelection()) {\n const id = (node as any).getId?.();\n if (id != null) selectedNodes.push(id);\n }\n\n const viewEl = tg.getView()?.el;\n const scrollPosition = viewEl\n ? { top: viewEl.scrollTop, left: viewEl.scrollLeft }\n : { top: 0, left: 0 };\n\n return {\n columns,\n columnOrder: columns.map((c) => c.id),\n expandedNodes,\n checkedNodes,\n selectedNodes,\n scrollPosition,\n };\n }\n\n applyState(state: TreeGridState): void {\n const tg = this.treeGrid;\n if (!tg) return;\n\n // Apply column widths/visibility\n if (state.columns) {\n for (const colState of state.columns) {\n const col = tg.getColumnByDataIndex(colState.id);\n if (!col) continue;\n if (colState.width !== undefined) col.width = colState.width;\n if (colState.flex !== undefined) col.flex = colState.flex;\n if (colState.hidden !== undefined) col.hidden = colState.hidden;\n }\n }\n\n // Expand nodes\n if (state.expandedNodes) {\n for (const id of state.expandedNodes) {\n const node = tg.getNodeById(id);\n if (node) tg.getStore().expandNode(node);\n }\n }\n\n // Check nodes\n if (state.checkedNodes && tg.isCheckable()) {\n for (const id of state.checkedNodes) {\n const node = tg.getNodeById(id);\n if (node) (node as any).$checked = true;\n }\n }\n\n // Select nodes\n if (state.selectedNodes) {\n const nodes = state.selectedNodes\n .map((id) => tg.getNodeById(id))\n .filter(Boolean) as NodeInterface[];\n if (nodes.length > 0) tg.select(nodes);\n }\n\n // Scroll position\n if (state.scrollPosition) {\n const viewEl = tg.getView()?.el;\n if (viewEl) {\n viewEl.scrollTop = state.scrollPosition.top;\n viewEl.scrollLeft = state.scrollPosition.left;\n }\n }\n\n tg.getView().refresh();\n }\n\n saveState(): void {\n try {\n const state = this.getState();\n localStorage.setItem(`treegrid.state.${this.stateId}`, JSON.stringify(state));\n } catch {\n // localStorage may not be available\n }\n }\n\n loadState(): TreeGridState | null {\n try {\n const raw = localStorage.getItem(`treegrid.state.${this.stateId}`);\n if (!raw) return null;\n return JSON.parse(raw) as TreeGridState;\n } catch {\n return null;\n }\n }\n\n clearState(): void {\n try {\n localStorage.removeItem(`treegrid.state.${this.stateId}`);\n } catch {\n // ignore\n }\n }\n\n // -------------------------------------------------------------------------\n // Debounced save\n // -------------------------------------------------------------------------\n\n private _debouncedSave(): void {\n if (this.saveDebounceTimer !== null) clearTimeout(this.saveDebounceTimer);\n this.saveDebounceTimer = setTimeout(() => {\n this.saveState();\n this.saveDebounceTimer = null;\n }, this.saveDebounceMs);\n }\n\n private _wireEvents(): void {\n const tg = this.treeGrid!;\n const store = tg.getStore() as any;\n store.on('nodeexpand', () => this._debouncedSave());\n store.on('nodecollapse', () => this._debouncedSave());\n (tg as any).on?.('selectionchange', () => this._debouncedSave());\n (tg as any).on?.('checkchange', () => this._debouncedSave());\n }\n}\n","/**\n * @framesquared/ui – TreeGridLockable\n *\n * Mixin/plugin enabling locked (frozen) columns in a TreeGrid.\n * Splits the grid into locked (left) and normal (right) panels.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { TreeGrid } from './TreeGrid.js';\nimport type { Column } from './TreeGridColumn.js';\nimport { TreeGridColumn } from './TreeGridColumn.js';\nimport { TreeGridView } from './TreeGridView.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeGridLockableConfig {\n syncScroll?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridLockable\n// ---------------------------------------------------------------------------\n\nexport class TreeGridLockable {\n private treeGrid: TreeGrid | null = null;\n private config: Required<TreeGridLockableConfig>;\n\n private lockedViewEl: HTMLElement | null = null;\n private normalViewEl: HTMLElement | null = null;\n private lockedView: TreeGridView | null = null;\n private normalView: TreeGridView | null = null;\n\n private _onLockedScroll: () => void;\n private _onNormalScroll: () => void;\n private _syncingScroll = false;\n\n constructor(config: TreeGridLockableConfig = {}) {\n this.config = {\n syncScroll: config.syncScroll ?? true,\n };\n this._onLockedScroll = this._syncScrollFromLocked.bind(this);\n this._onNormalScroll = this._syncScrollFromNormal.bind(this);\n }\n\n init(treeGrid: TreeGrid): void {\n this.treeGrid = treeGrid;\n\n const columns = treeGrid.getColumns();\n\n // Only split if at least one non-tree column is user-defined (not auto-created from config)\n // or has an explicit locked flag set\n const hasUserDefinedColumns = columns.some(\n (c) =>\n !(c instanceof TreeGridColumn) &&\n (!(c as any)._autoCreated || (c as any).locked === true),\n );\n if (!hasUserDefinedColumns) return;\n\n const lockedCols = columns.filter(\n (c) => c instanceof TreeGridColumn || (c as any).locked === true,\n );\n const normalCols = columns.filter(\n (c) => !(c instanceof TreeGridColumn) && (c as any).locked !== true,\n );\n\n if (lockedCols.length === 0 || normalCols.length === 0) return;\n\n const bodyEl = treeGrid.getBodyEl?.();\n if (!bodyEl) return;\n\n // Build locked panel\n this.lockedViewEl = document.createElement('div');\n this.lockedViewEl.className = 'x-treegrid-locked-panel';\n this.lockedViewEl.style.cssText =\n 'display:inline-block;overflow-x:hidden;overflow-y:auto;vertical-align:top;';\n\n this.lockedView = new TreeGridView({\n store: treeGrid.getStore(),\n columns: lockedCols,\n rootVisible: treeGrid.isRootVisible(),\n checkable: treeGrid.isCheckable(),\n });\n this.lockedView.render(this.lockedViewEl);\n\n // Build normal panel\n this.normalViewEl = document.createElement('div');\n this.normalViewEl.className = 'x-treegrid-normal-panel';\n this.normalViewEl.style.cssText =\n 'display:inline-block;overflow-x:auto;overflow-y:auto;vertical-align:top;';\n\n this.normalView = new TreeGridView({\n store: treeGrid.getStore(),\n columns: normalCols,\n rootVisible: treeGrid.isRootVisible(),\n });\n this.normalView.render(this.normalViewEl);\n\n bodyEl.innerHTML = '';\n bodyEl.appendChild(this.lockedViewEl);\n bodyEl.appendChild(this.normalViewEl);\n\n if (this.config.syncScroll) {\n this.lockedViewEl.addEventListener('scroll', this._onLockedScroll);\n this.normalViewEl.addEventListener('scroll', this._onNormalScroll);\n }\n\n // Wire store events to both views\n const store = treeGrid.getStore() as any;\n store.on('datachanged', () => {\n this.lockedView?.refresh();\n this.normalView?.refresh();\n });\n store.on('nodeexpand', (_s: unknown, node: any) => {\n this.lockedView?.onNodeExpand(node, node.childNodes);\n this.normalView?.onNodeExpand(node, node.childNodes);\n });\n store.on('nodecollapse', (_s: unknown, node: any) => {\n this.lockedView?.onNodeCollapse(node);\n this.normalView?.onNodeCollapse(node);\n });\n }\n\n destroy(): void {\n if (this.config.syncScroll) {\n this.lockedViewEl?.removeEventListener('scroll', this._onLockedScroll);\n this.normalViewEl?.removeEventListener('scroll', this._onNormalScroll);\n }\n this.lockedViewEl?.remove();\n this.normalViewEl?.remove();\n this.lockedView = null;\n this.normalView = null;\n this.lockedViewEl = null;\n this.normalViewEl = null;\n this.treeGrid = null;\n }\n\n getLockedView(): TreeGridView | null {\n return this.lockedView;\n }\n\n getNormalView(): TreeGridView | null {\n return this.normalView;\n }\n\n lockColumn(col: Column): void {\n (col as any).locked = true;\n this._rebuild();\n }\n\n unlockColumn(col: Column): void {\n if (col instanceof TreeGridColumn) return; // Tree col always locked\n (col as any).locked = false;\n this._rebuild();\n }\n\n private _rebuild(): void {\n const grid = this.treeGrid;\n if (grid) {\n this.destroy();\n this.init(grid);\n }\n }\n\n private _syncScrollFromLocked(): void {\n if (this._syncingScroll) return;\n this._syncingScroll = true;\n if (this.normalViewEl && this.lockedViewEl) {\n this.normalViewEl.scrollTop = this.lockedViewEl.scrollTop;\n }\n this._syncingScroll = false;\n }\n\n private _syncScrollFromNormal(): void {\n if (this._syncingScroll) return;\n this._syncingScroll = true;\n if (this.lockedViewEl && this.normalViewEl) {\n this.lockedViewEl.scrollTop = this.normalViewEl.scrollTop;\n }\n this._syncingScroll = false;\n }\n}\n","/**\n * @framesquared/ui – TreeGridExporter\n *\n * Exports TreeGrid data to CSV, JSON, TSV, and XLSX formats.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { TreeGrid } from './TreeGrid.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ExportOptions {\n includeHeaders?: boolean;\n includeHidden?: boolean;\n expandedOnly?: boolean;\n allNodes?: boolean;\n indentCharacter?: string;\n indentMultiplier?: number;\n columns?: string[];\n filename?: string;\n}\n\n// ---------------------------------------------------------------------------\n// TreeGridExporter\n// ---------------------------------------------------------------------------\n\nexport class TreeGridExporter {\n constructor(_options: ExportOptions = {}) {}\n\n /**\n * Exports the TreeGrid to CSV format.\n */\n static exportToCsv(treeGrid: TreeGrid, options: ExportOptions = {}): string {\n const rows = TreeGridExporter._buildRows(treeGrid, options, '\\t', true);\n return rows.map((r) => r.join(',')).join('\\n');\n }\n\n /**\n * Exports the TreeGrid to TSV format.\n */\n static exportToTsv(treeGrid: TreeGrid, options: ExportOptions = {}): string {\n const rows = TreeGridExporter._buildRows(treeGrid, options, '\\t', false);\n return rows.map((r) => r.join('\\t')).join('\\n');\n }\n\n /**\n * Exports the TreeGrid to nested JSON preserving hierarchy.\n */\n static exportToJson(treeGrid: TreeGrid, options: ExportOptions = {}): string {\n const columns = TreeGridExporter._getColumns(treeGrid, options);\n const root = treeGrid.getRootNode();\n\n const serializeNode = (node: NodeInterface): Record<string, unknown> => {\n const data: Record<string, unknown> = {};\n for (const col of columns) {\n data[col.dataIndex] = (node as any).get?.(col.dataIndex);\n }\n if (!node.isLeaf() && node.childNodes.length > 0) {\n const childrenToInclude = options.expandedOnly\n ? node.childNodes.filter((c) => c.isExpanded() || c.isLeaf())\n : node.childNodes;\n if (childrenToInclude.length > 0) {\n data.children = childrenToInclude.map(serializeNode);\n }\n }\n return data;\n };\n\n const childrenToExport = options.expandedOnly\n ? root.childNodes.filter((c) => c.isExpanded() || c.isLeaf())\n : root.childNodes;\n\n if (childrenToExport.length === 1 && !treeGrid.isRootVisible()) {\n return JSON.stringify(serializeNode(childrenToExport[0]), null, 2);\n }\n\n return JSON.stringify(childrenToExport.map(serializeNode), null, 2);\n }\n\n /**\n * Exports the TreeGrid to XLSX format.\n * Returns an ArrayBuffer with the XLSX bytes.\n */\n static exportToXlsx(treeGrid: TreeGrid, options: ExportOptions = {}): ArrayBuffer {\n // Simple XLSX implementation using the SpreadsheetML format\n const rows = TreeGridExporter._buildRows(treeGrid, options, ' ', false);\n\n // Build a minimal xlsx file\n const xmlRows = rows\n .map((row, rowIdx) => {\n const cells = row\n .map((cell, colIdx) => {\n const colLetter = String.fromCharCode(65 + colIdx);\n return `<c r=\"${colLetter}${rowIdx + 1}\" t=\"inlineStr\"><is><t>${_escapeXml(cell)}</t></is></c>`;\n })\n .join('');\n return `<row r=\"${rowIdx + 1}\">${cells}</row>`;\n })\n .join('');\n\n const sheetXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n<sheetData>${xmlRows}</sheetData>\n</worksheet>`;\n\n // Encode to ArrayBuffer — create a proper ArrayBuffer in the current realm\n const bytes: number[] = [];\n for (let i = 0; i < sheetXml.length; i++) {\n const code = sheetXml.charCodeAt(i);\n if (code < 0x80) {\n bytes.push(code);\n } else if (code < 0x800) {\n bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));\n } else {\n bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));\n }\n }\n const buffer = new ArrayBuffer(bytes.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < bytes.length; i++) view[i] = bytes[i];\n return buffer;\n }\n\n /**\n * Triggers a browser download with the given content.\n */\n static download(content: string | ArrayBuffer, filename: string, mimeType: string): void {\n const blob =\n content instanceof ArrayBuffer\n ? new Blob([content], { type: mimeType })\n : new Blob([content], { type: mimeType });\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private static _buildRows(\n treeGrid: TreeGrid,\n options: ExportOptions,\n indentChar: string,\n indentTreeCol: boolean,\n ): string[][] {\n const columns = TreeGridExporter._getColumns(treeGrid, options);\n const nodes = TreeGridExporter._getNodes(treeGrid, options);\n const rows: string[][] = [];\n\n if (options.includeHeaders !== false) {\n rows.push(columns.map((c) => c.text));\n }\n\n const treeCol = treeGrid.getTreeColumn();\n const indentMultiplier = options.indentMultiplier ?? 1;\n\n for (const node of nodes) {\n const row: string[] = [];\n const depth = node.depth ?? 0;\n for (const col of columns) {\n let value = String((node as any).get?.(col.dataIndex) ?? '');\n if (indentTreeCol && col === treeCol) {\n value = (options.indentCharacter ?? indentChar).repeat(depth * indentMultiplier) + value;\n }\n row.push(value);\n }\n rows.push(row);\n }\n\n return rows;\n }\n\n private static _getColumns(treeGrid: TreeGrid, options: ExportOptions) {\n const allColumns = treeGrid.getColumns();\n let cols = options.includeHidden ? allColumns : allColumns.filter((c) => !c.hidden);\n if (options.columns) {\n const allowedSet = new Set(options.columns);\n cols = cols.filter((c) => allowedSet.has(c.dataIndex));\n }\n return cols;\n }\n\n private static _getNodes(treeGrid: TreeGrid, options: ExportOptions): NodeInterface[] {\n if (options.expandedOnly) {\n return (treeGrid.getStore().flattenNodes() as NodeInterface[]).filter(\n (n) => !n.isRoot(),\n );\n }\n // All nodes (default)\n const all: NodeInterface[] = [];\n treeGrid.getRootNode().cascadeBy((n) => {\n if (!n.isRoot()) all.push(n);\n });\n return all;\n }\n}\n\nfunction _escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n","/**\n * @framesquared/ui – TreeColumn\n *\n * Column definition / renderer for tree nodes.\n */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeColumnConfig {\n dataIndex?: string;\n indentSize?: number;\n header?: string;\n width?: number;\n}\n\n// ---------------------------------------------------------------------------\n// TreeColumn\n// ---------------------------------------------------------------------------\n\nexport class TreeColumn {\n dataIndex: string;\n indentSize: number;\n header: string;\n width: number;\n\n constructor(config?: TreeColumnConfig) {\n this.dataIndex = config?.dataIndex ?? 'text';\n this.indentSize = config?.indentSize ?? 20;\n this.header = config?.header ?? '';\n this.width = config?.width ?? 200;\n }\n\n /**\n * Renders the full cell content for a tree node.\n */\n renderCell(record: NodeInterface, checkable?: boolean): string {\n const depth = record.depth ?? 0;\n const paddingLeft = depth * this.indentSize;\n const text = String(record.get(this.dataIndex) ?? '');\n const isLeaf = record.isLeaf();\n const isExpanded = record.isExpanded();\n const iconCls = String(record.get('iconCls') ?? '');\n const customIcon = String(record.get('icon') ?? '');\n\n const expanderHtml = isLeaf\n ? '<span class=\"x-tree-expander-placeholder\"></span>'\n : `<span class=\"x-tree-expander x-tree-expander-${isExpanded ? 'collapse' : 'expand'}\" role=\"button\" aria-label=\"${isExpanded ? 'Collapse' : 'Expand'}\"></span>`;\n\n const checkboxHtml = checkable\n ? `<span class=\"x-tree-checkbox\" role=\"checkbox\"></span>`\n : '';\n\n const defaultIconCls =\n iconCls ||\n (isLeaf\n ? 'x-tree-icon-leaf'\n : isExpanded\n ? 'x-tree-icon-open'\n : 'x-tree-icon-folder');\n\n const iconHtml = customIcon\n ? `<img class=\"x-tree-icon\" src=\"${customIcon}\" alt=\"\">`\n : `<span class=\"x-tree-icon ${defaultIconCls}\"></span>`;\n\n return `\n <div class=\"x-tree-cell-inner\" style=\"padding-left: ${paddingLeft}px\">\n ${expanderHtml}\n ${checkboxHtml}\n ${iconHtml}\n <span class=\"x-tree-node-text\">${text}</span>\n </div>\n `;\n }\n}\n","/**\n * @framesquared/ui – TreeView\n *\n * Renders the flat list of visible tree nodes in a <table>.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { TreeStore, NodeInterface } from '@framesquared/data';\nimport { TreeColumn } from './TreeColumn.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeViewConfig {\n store: TreeStore;\n displayField?: string;\n checkable?: boolean;\n column?: TreeColumn;\n}\n\n// ---------------------------------------------------------------------------\n// TreeView\n// ---------------------------------------------------------------------------\n\nexport class TreeView {\n el: HTMLElement | null = null;\n private tableEl: HTMLTableElement | null = null;\n private store: TreeStore;\n private displayField: string;\n private checkable: boolean;\n private column: TreeColumn;\n private listeners: Map<string, Function[]> = new Map();\n\n constructor(config: TreeViewConfig) {\n this.store = config.store;\n this.displayField = config.displayField ?? 'text';\n this.checkable = config.checkable ?? false;\n this.column = config.column ?? new TreeColumn({ dataIndex: this.displayField });\n }\n\n // -------------------------------------------------------------------------\n // Event system\n // -------------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(fn);\n }\n\n un(event: string, fn: Function): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n const idx = fns.indexOf(fn);\n if (idx !== -1) fns.splice(idx, 1);\n }\n\n private fireEvent(event: string, ...args: unknown[]): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n for (const fn of [...fns]) {\n fn(...args);\n }\n }\n\n // -------------------------------------------------------------------------\n // Render\n // -------------------------------------------------------------------------\n\n render(container: HTMLElement): void {\n this.el = document.createElement('div');\n this.el.className = 'x-tree-view';\n this.el.setAttribute('role', 'tree');\n\n this.tableEl = document.createElement('table');\n this.tableEl.className = 'x-tree-table';\n this.el.appendChild(this.tableEl);\n\n container.appendChild(this.el);\n\n this.el.addEventListener('click', this.onViewClick.bind(this));\n this.el.addEventListener('dblclick', this.onViewDblClick.bind(this));\n this.el.addEventListener('contextmenu', this.onViewContextMenu.bind(this));\n this.el.addEventListener('keydown', this.onKeyDown.bind(this));\n\n this.refresh();\n }\n\n // -------------------------------------------------------------------------\n // Node rendering\n // -------------------------------------------------------------------------\n\n refresh(): void {\n if (!this.tableEl) return;\n this.tableEl.innerHTML = '';\n\n const nodes = this.store.flattenNodes() as NodeInterface[];\n // flattenNodes includes root; we skip root (it has no parentNode)\n for (const node of nodes) {\n if (node.isRoot()) continue;\n const tr = this.buildRow(node);\n this.tableEl.appendChild(tr);\n }\n }\n\n private buildRow(node: NodeInterface): HTMLTableRowElement {\n const tr = document.createElement('tr');\n tr.className = 'x-tree-node';\n tr.setAttribute('role', 'treeitem');\n tr.setAttribute('aria-level', String(node.depth ?? 1));\n tr.setAttribute('tabindex', '-1');\n\n const id = (node as any).getId?.();\n if (id !== undefined && id !== null) {\n tr.setAttribute('data-node-id', String(id));\n }\n\n if (node.isExpanded()) {\n tr.classList.add('x-tree-expanded');\n tr.setAttribute('aria-expanded', 'true');\n } else if (!node.isLeaf()) {\n tr.setAttribute('aria-expanded', 'false');\n }\n\n if (node.isLeaf()) {\n tr.classList.add('x-tree-leaf');\n }\n\n const td = document.createElement('td');\n td.className = 'x-tree-cell';\n td.innerHTML = this.column.renderCell(node, this.checkable);\n tr.appendChild(td);\n\n return tr;\n }\n\n refreshNode(record: NodeInterface): void {\n const row = this.getNode(record);\n if (!row || !this.tableEl) return;\n\n const newRow = this.buildRow(record);\n this.tableEl.replaceChild(newRow, row);\n }\n\n // -------------------------------------------------------------------------\n // Node lookup\n // -------------------------------------------------------------------------\n\n getNode(record: NodeInterface): HTMLElement | null {\n if (!this.tableEl) return null;\n const id = (record as any).getId?.();\n if (id === undefined || id === null) return null;\n return this.tableEl.querySelector(`[data-node-id=\"${String(id).replace(/\"/g, '\\\\\"')}\"]`);\n }\n\n getRecord(el: HTMLElement): NodeInterface | null {\n // Walk up to find a row with data-node-id\n let target: HTMLElement | null = el;\n while (target && target !== this.el) {\n const id = target.getAttribute('data-node-id');\n if (id !== null) {\n return this.store.getNodeById(id) as NodeInterface | null ?? null;\n }\n target = target.parentElement;\n }\n return null;\n }\n\n focusNode(record: NodeInterface): void {\n const row = this.getNode(record);\n if (!row) return;\n // Reset all tabindexes\n if (this.tableEl) {\n this.tableEl.querySelectorAll('[tabindex]').forEach((el) => {\n (el as HTMLElement).setAttribute('tabindex', '-1');\n });\n }\n row.setAttribute('tabindex', '0');\n (row as HTMLElement).focus();\n }\n\n // -------------------------------------------------------------------------\n // Event handlers\n // -------------------------------------------------------------------------\n\n private getRowRecord(e: Event): NodeInterface | null {\n const target = e.target as HTMLElement;\n if (!target) return null;\n let el: HTMLElement | null = target;\n while (el && el !== this.el) {\n if (el.hasAttribute('data-node-id')) {\n const id = el.getAttribute('data-node-id')!;\n return this.store.getNodeById(id) as NodeInterface | null ?? null;\n }\n el = el.parentElement;\n }\n return null;\n }\n\n private onViewClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n // Check if click was on expander\n if (target.classList.contains('x-tree-expander')) {\n const record = this.getRowRecord(e);\n if (record) {\n if (record.isExpanded()) {\n this.store.collapseNode(record);\n } else {\n this.store.expandNode(record);\n }\n this.fireEvent('expanderclick', record);\n return;\n }\n }\n const record = this.getRowRecord(e);\n if (record) {\n this.fireEvent('itemclick', record, e);\n }\n }\n\n private onViewDblClick(e: MouseEvent): void {\n const record = this.getRowRecord(e);\n if (record) {\n this.fireEvent('itemdblclick', record, e);\n }\n }\n\n private onViewContextMenu(e: MouseEvent): void {\n const record = this.getRowRecord(e);\n if (record) {\n this.fireEvent('itemcontextmenu', record, e);\n }\n }\n\n private onKeyDown(e: KeyboardEvent): void {\n const rows = this.tableEl\n ? Array.from(this.tableEl.querySelectorAll('tr[data-node-id]')) as HTMLElement[]\n : [];\n const focused = document.activeElement as HTMLElement;\n const idx = rows.indexOf(focused);\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n const next = rows[idx + 1];\n if (next) {\n next.setAttribute('tabindex', '0');\n focused?.setAttribute('tabindex', '-1');\n next.focus();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n const prev = rows[idx - 1];\n if (prev) {\n prev.setAttribute('tabindex', '0');\n focused?.setAttribute('tabindex', '-1');\n prev.focus();\n }\n } else if (e.key === 'Enter' || e.key === ' ') {\n if (focused) {\n const record = this.getRecord(focused);\n if (record) {\n this.fireEvent('itemclick', record, e);\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Selection helpers\n // -------------------------------------------------------------------------\n\n markSelected(record: NodeInterface, selected: boolean): void {\n const row = this.getNode(record);\n if (!row) return;\n if (selected) {\n row.classList.add('x-tree-selected');\n } else {\n row.classList.remove('x-tree-selected');\n }\n }\n}\n","/**\n * @framesquared/ui – TreeSelectionModel\n *\n * Manages selection state for tree nodes, supporting single and multi-select modes.\n */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeSelectionModelConfig {\n mode?: 'single' | 'multi' | 'simple';\n pruneRemoved?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeSelectionModel\n// ---------------------------------------------------------------------------\n\nexport class TreeSelectionModel {\n private selected: Set<NodeInterface>;\n private mode: string;\n private pruneRemoved: boolean;\n private listeners: Map<string, Function[]>;\n\n constructor(config?: TreeSelectionModelConfig) {\n this.selected = new Set();\n this.mode = config?.mode ?? 'single';\n this.pruneRemoved = config?.pruneRemoved ?? true;\n this.listeners = new Map();\n }\n\n // -------------------------------------------------------------------------\n // Event system\n // -------------------------------------------------------------------------\n\n on(event: string, fn: Function): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(fn);\n }\n\n un(event: string, fn: Function): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n const idx = fns.indexOf(fn);\n if (idx !== -1) fns.splice(idx, 1);\n }\n\n fireEvent(event: string, ...args: unknown[]): void {\n const fns = this.listeners.get(event);\n if (!fns) return;\n for (const fn of [...fns]) {\n fn(...args);\n }\n }\n\n // -------------------------------------------------------------------------\n // Selection API\n // -------------------------------------------------------------------------\n\n select(\n records: NodeInterface | NodeInterface[],\n keepExisting = false,\n suppressEvent = false,\n ): void {\n const toSelect = Array.isArray(records) ? records : [records];\n if (!keepExisting && this.mode !== 'simple') {\n this.selected.clear();\n }\n if (this.mode === 'single' && toSelect.length > 0) {\n this.selected.clear();\n this.selected.add(toSelect[toSelect.length - 1]);\n } else {\n for (const record of toSelect) {\n this.selected.add(record);\n }\n }\n if (!suppressEvent) {\n this.fireEvent('selectionchange', this, this.getSelection());\n }\n }\n\n deselect(records: NodeInterface | NodeInterface[], suppressEvent = false): void {\n const toDeselect = Array.isArray(records) ? records : [records];\n for (const record of toDeselect) {\n this.selected.delete(record);\n }\n if (!suppressEvent) {\n this.fireEvent('selectionchange', this, this.getSelection());\n }\n }\n\n deselectAll(suppressEvent = false): void {\n this.selected.clear();\n if (!suppressEvent) {\n this.fireEvent('selectionchange', this, this.getSelection());\n }\n }\n\n isSelected(record: NodeInterface): boolean {\n return this.selected.has(record);\n }\n\n getSelection(): NodeInterface[] {\n return Array.from(this.selected);\n }\n\n getCount(): number {\n return this.selected.size;\n }\n\n // Convenience aliases matching Ext-style API\n selectNode(\n node: NodeInterface,\n keepExisting = false,\n suppressEvent = false,\n ): void {\n this.select(node, keepExisting, suppressEvent);\n }\n\n deselectNode(node: NodeInterface, suppressEvent = false): void {\n this.deselect(node, suppressEvent);\n }\n\n isNodeSelected(node: NodeInterface): boolean {\n return this.isSelected(node);\n }\n\n // -------------------------------------------------------------------------\n // Pruning\n // -------------------------------------------------------------------------\n\n pruneRemovedNodes(removedNodes: NodeInterface[]): void {\n if (!this.pruneRemoved) return;\n for (const node of removedNodes) {\n this.selected.delete(node);\n }\n }\n}\n","/**\n * @framesquared/ui – TreePanel\n *\n * Main tree component. Extends Panel and uses TreeView for rendering.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { Panel } from '../panel/Panel.js';\nimport type { PanelConfig } from '../panel/Panel.js';\nimport type { TreeStore, NodeInterface } from '@framesquared/data';\nimport { TreeView } from './TreeView.js';\nimport { TreeSelectionModel } from '../selection/TreeSelectionModel.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreePanelConfig extends PanelConfig {\n store: TreeStore;\n rootVisible?: boolean;\n displayField?: string;\n useArrows?: boolean;\n lines?: boolean;\n singleExpand?: boolean;\n checkable?: boolean;\n cascadeChecks?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreePanel\n// ---------------------------------------------------------------------------\n\nexport class TreePanel extends Panel {\n static override $className = 'Ext.tree.Panel';\n\n declare private _store: TreeStore;\n declare private _treeView: TreeView | null;\n declare private _selModel: TreeSelectionModel;\n declare private _rootVisible: boolean;\n declare private _displayField: string;\n declare private _useArrows: boolean;\n declare private _lines: boolean;\n declare private _singleExpand: boolean;\n declare private _checkable: boolean;\n declare private _cascadeChecks: boolean;\n\n constructor(config: TreePanelConfig) {\n super(config);\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n protected override initialize(): void {\n super.initialize();\n const cfg = this._config as TreePanelConfig;\n this._store = cfg.store;\n this._treeView = null;\n this._rootVisible = cfg.rootVisible ?? false;\n this._displayField = cfg.displayField ?? 'text';\n this._useArrows = cfg.useArrows ?? true;\n this._lines = cfg.lines ?? false;\n this._singleExpand = cfg.singleExpand ?? false;\n this._checkable = cfg.checkable ?? false;\n this._cascadeChecks = cfg.cascadeChecks ?? true;\n this._selModel = new TreeSelectionModel({ mode: 'single' });\n }\n\n protected override afterRender(): void {\n super.afterRender();\n\n // Add tree panel CSS class\n this.el!.classList.add('x-tree-panel');\n\n if (this._useArrows) {\n this.el!.classList.add('x-tree-arrows');\n }\n if (this._lines) {\n this.el!.classList.add('x-tree-lines');\n }\n\n // Create and render TreeView into the panel body\n this._treeView = new TreeView({\n store: this._store,\n displayField: this._displayField,\n checkable: this._checkable,\n });\n this._treeView.render(this.getBodyEl());\n\n // Wire store events\n (this._store as any).on('datachanged', () => this._treeView?.refresh());\n (this._store as any).on('nodeexpand', (_store: unknown, node: NodeInterface) => {\n if (this._singleExpand) {\n this._collapseAllExcept(node);\n }\n this._treeView?.refresh();\n });\n (this._store as any).on('nodecollapse', () => this._treeView?.refresh());\n (this._store as any).on('nodeappend', () => this._treeView?.refresh());\n (this._store as any).on('noderemove', () => this._treeView?.refresh());\n (this._store as any).on('nodeinsert', () => this._treeView?.refresh());\n\n // Wire TreeView events to TreePanel events\n this._treeView.on('itemclick', (node: NodeInterface, e: MouseEvent) => {\n this.fire('itemclick', this, node, e);\n });\n this._treeView.on('itemdblclick', (node: NodeInterface, e: MouseEvent) => {\n this.fire('itemdblclick', this, node, e);\n });\n this._treeView.on('itemcontextmenu', (node: NodeInterface, e: MouseEvent) => {\n this.fire('itemcontextmenu', this, node, e);\n });\n }\n\n // -------------------------------------------------------------------------\n // Store / Root\n // -------------------------------------------------------------------------\n\n getStore(): TreeStore {\n return this._store;\n }\n\n getRootNode(): NodeInterface {\n return this._store.getRootNode();\n }\n\n // -------------------------------------------------------------------------\n // Expand / Collapse\n // -------------------------------------------------------------------------\n\n expandAll(): void {\n this._store.expandAll();\n this._treeView?.refresh();\n }\n\n collapseAll(): void {\n this._store.collapseAll();\n this._treeView?.refresh();\n }\n\n expandNode(node: NodeInterface, deep = false): void {\n this._store.expandNode(node);\n if (deep) {\n node.cascadeBy((child) => {\n if (!child.isLeaf()) {\n this._store.expandNode(child);\n }\n });\n }\n this._treeView?.refresh();\n }\n\n collapseNode(node: NodeInterface, deep = false): void {\n this._store.collapseNode(node);\n if (deep) {\n node.cascadeBy((child) => {\n this._store.collapseNode(child);\n });\n }\n this._treeView?.refresh();\n }\n\n private _collapseAllExcept(except: NodeInterface): void {\n const root = this._store.getRootNode();\n root.eachChild((child) => {\n if (child !== except) {\n this._store.collapseNode(child);\n }\n });\n }\n\n // -------------------------------------------------------------------------\n // Selection\n // -------------------------------------------------------------------------\n\n getSelection(): NodeInterface[] {\n return this._selModel.getSelection();\n }\n\n select(nodes: NodeInterface | NodeInterface[]): void {\n this._selModel.select(nodes);\n const selected = this._selModel.getSelection();\n // Update visual state\n if (this._treeView) {\n const allNodes = this._store.flattenNodes() as NodeInterface[];\n for (const node of allNodes) {\n this._treeView.markSelected(node, selected.includes(node));\n }\n }\n }\n\n deselectAll(): void {\n if (this._treeView) {\n for (const node of this._selModel.getSelection()) {\n this._treeView.markSelected(node, false);\n }\n }\n this._selModel.deselectAll();\n }\n\n // -------------------------------------------------------------------------\n // Checked nodes\n // -------------------------------------------------------------------------\n\n getChecked(): NodeInterface[] {\n if (!this._checkable) return [];\n const checked: NodeInterface[] = [];\n const root = this._store.getRootNode();\n root.cascadeBy?.((node) => {\n if ((node as any).$checked === true) checked.push(node);\n });\n return checked;\n }\n\n // -------------------------------------------------------------------------\n // View\n // -------------------------------------------------------------------------\n\n getView(): TreeView {\n return this._treeView!;\n }\n\n scrollToNode(node: NodeInterface): void {\n const row = this._treeView?.getNode(node);\n row?.scrollIntoView?.({ block: 'nearest' });\n }\n\n // -------------------------------------------------------------------------\n // Config accessors\n // -------------------------------------------------------------------------\n\n isRootVisible(): boolean {\n return this._rootVisible;\n }\n\n isCheckable(): boolean {\n return this._checkable;\n }\n}\n","/**\n * @framesquared/ui – CheckboxModel\n *\n * A selection model that adds checkbox-based check state management to tree nodes.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { TreeStore, NodeInterface } from '@framesquared/data';\nimport { TreeSelectionModel } from '../selection/TreeSelectionModel.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface CheckboxModelConfig {\n cascadeChecks?: boolean;\n onlyLeafCheckable?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// CheckboxModel\n// ---------------------------------------------------------------------------\n\nexport class CheckboxModel extends TreeSelectionModel {\n private cascadeChecks: boolean;\n private onlyLeafCheckable: boolean;\n\n constructor(config?: CheckboxModelConfig) {\n super({ mode: 'multi' });\n this.cascadeChecks = config?.cascadeChecks ?? true;\n this.onlyLeafCheckable = config?.onlyLeafCheckable ?? false;\n }\n\n // -------------------------------------------------------------------------\n // Check API\n // -------------------------------------------------------------------------\n\n toggleCheck(node: NodeInterface): void {\n const newState = !((node as any).$checked as boolean);\n this.setChecked(node, newState);\n }\n\n setChecked(node: NodeInterface, checked: boolean): void {\n (node as any).$checked = checked;\n\n if (this.cascadeChecks) {\n node.eachChild?.((child) => {\n this.setChecked(child, checked);\n });\n }\n\n // Bubble up to update parents\n let parent = node.parentNode;\n while (parent) {\n this.updateParentCheck(parent);\n parent = parent.parentNode;\n }\n }\n\n getChecked(store: TreeStore): NodeInterface[] {\n const checked: NodeInterface[] = [];\n const root = store.getRootNode();\n root.cascadeBy?.((node) => {\n if ((node as any).$checked === true) checked.push(node);\n });\n return checked;\n }\n\n private updateParentCheck(node: NodeInterface): void {\n if (!node || node.isRoot()) return;\n const children = node.childNodes;\n if (children.length === 0) return;\n\n const allChecked = children.every((c) => (c as any).$checked === true);\n const someChecked = children.some((c) => (c as any).$checked === true);\n\n if (allChecked) {\n (node as any).$checked = true;\n } else if (someChecked) {\n (node as any).$checked = 'partial';\n } else {\n (node as any).$checked = false;\n }\n }\n\n isCheckable(node: NodeInterface): boolean {\n if (this.onlyLeafCheckable) return node.isLeaf();\n return true;\n }\n}\n","/**\n * @framesquared/ui – TreeDragZone\n *\n * Drag source for tree nodes.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DragData {\n records: NodeInterface[];\n sourceTree: TreePanelLike;\n ddGroup: string;\n}\n\n/** Minimal interface TreeDragZone needs from TreePanel */\nexport interface TreePanelLike {\n getView(): { el: HTMLElement | null };\n getSelection(): NodeInterface[];\n}\n\n// ---------------------------------------------------------------------------\n// TreeDragZone\n// ---------------------------------------------------------------------------\n\nexport class TreeDragZone {\n private tree: TreePanelLike;\n ddGroup: string;\n private dragging = false;\n private ghostEl: HTMLElement | null = null;\n dragData: DragData | null = null;\n private startX = 0;\n private startY = 0;\n private dragThreshold = 5;\n\n private boundPointerDown: (e: PointerEvent) => void;\n private boundPointerMove: (e: PointerEvent) => void;\n private boundPointerUp: (e: PointerEvent) => void;\n\n constructor(tree: TreePanelLike, config?: { ddGroup?: string }) {\n this.tree = tree;\n this.ddGroup = config?.ddGroup ?? 'TreeDD';\n this.boundPointerDown = this.onPointerDown.bind(this);\n this.boundPointerMove = this.onPointerMove.bind(this);\n this.boundPointerUp = this.onPointerUp.bind(this);\n this.init();\n }\n\n private init(): void {\n const el = this.tree.getView().el;\n if (!el) return;\n el.addEventListener('pointerdown', this.boundPointerDown);\n }\n\n private onPointerDown(e: PointerEvent): void {\n const target = e.target as HTMLElement;\n // Only start drag on tree rows\n let row: HTMLElement | null = target;\n while (row && !row.hasAttribute('data-node-id')) {\n row = row.parentElement;\n }\n if (!row) return;\n\n this.startX = e.clientX;\n this.startY = e.clientY;\n\n document.addEventListener('pointermove', this.boundPointerMove);\n document.addEventListener('pointerup', this.boundPointerUp);\n }\n\n private onPointerMove(e: PointerEvent): void {\n const dx = Math.abs(e.clientX - this.startX);\n const dy = Math.abs(e.clientY - this.startY);\n\n if (!this.dragging && (dx > this.dragThreshold || dy > this.dragThreshold)) {\n this.dragging = true;\n const selected = this.tree.getSelection();\n this.dragData = {\n records: selected.length > 0 ? selected : [],\n sourceTree: this.tree,\n ddGroup: this.ddGroup,\n };\n this.createGhost();\n }\n\n if (this.dragging && this.ghostEl) {\n this.ghostEl.style.left = `${e.clientX + 10}px`;\n this.ghostEl.style.top = `${e.clientY + 10}px`;\n }\n }\n\n private onPointerUp(_e: PointerEvent): void {\n this.dragging = false;\n this.removeGhost();\n this.dragData = null;\n document.removeEventListener('pointermove', this.boundPointerMove);\n document.removeEventListener('pointerup', this.boundPointerUp);\n }\n\n private createGhost(): void {\n this.ghostEl = document.createElement('div');\n this.ghostEl.className = 'x-dd-drag-ghost';\n this.ghostEl.style.cssText =\n 'position:fixed;pointer-events:none;z-index:99999;background:#fff;border:1px solid #aaa;padding:4px 8px;';\n const count = this.dragData?.records.length ?? 0;\n this.ghostEl.textContent = `${count} item${count !== 1 ? 's' : ''}`;\n document.body.appendChild(this.ghostEl);\n }\n\n private removeGhost(): void {\n if (this.ghostEl?.parentNode) {\n this.ghostEl.parentNode.removeChild(this.ghostEl);\n }\n this.ghostEl = null;\n }\n\n isDragging(): boolean {\n return this.dragging;\n }\n\n destroy(): void {\n const el = this.tree.getView().el;\n if (el) {\n el.removeEventListener('pointerdown', this.boundPointerDown);\n }\n document.removeEventListener('pointermove', this.boundPointerMove);\n document.removeEventListener('pointerup', this.boundPointerUp);\n this.removeGhost();\n this.dragData = null;\n }\n}\n","/**\n * @framesquared/ui – TreeDropZone\n *\n * Drop target for tree drag-and-drop.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\nimport type { DragData, TreePanelLike } from './TreeDragZone.js';\n\n// ---------------------------------------------------------------------------\n// TreeDropZone\n// ---------------------------------------------------------------------------\n\nexport class TreeDropZone {\n private tree: TreePanelLike & { getStore(): { insertBefore: Function; appendChild: Function } };\n ddGroup: string;\n private appendOnly: boolean;\n private indicatorEl: HTMLElement | null = null;\n private expandTimer: ReturnType<typeof setTimeout> | null = null;\n expandDelay: number;\n\n private boundDragOver: (e: DragEvent) => void;\n private boundDrop: (e: DragEvent) => void;\n\n constructor(\n tree: TreePanelLike & { getStore(): { insertBefore: Function; appendChild: Function } },\n config?: {\n ddGroup?: string;\n appendOnly?: boolean;\n sortOnDrop?: boolean;\n expandDelay?: number;\n },\n ) {\n this.tree = tree;\n this.ddGroup = config?.ddGroup ?? 'TreeDD';\n this.appendOnly = config?.appendOnly ?? false;\n this.expandDelay = config?.expandDelay ?? 500;\n this.boundDragOver = this.onDragOver.bind(this);\n this.boundDrop = this.onDrop.bind(this);\n this.init();\n }\n\n private init(): void {\n const el = this.tree.getView().el;\n if (!el) return;\n el.addEventListener('dragover', this.boundDragOver);\n el.addEventListener('drop', this.boundDrop);\n }\n\n // -------------------------------------------------------------------------\n // Drop position calculation\n // -------------------------------------------------------------------------\n\n getDropPosition(\n targetEl: HTMLElement,\n clientY: number,\n ): 'before' | 'after' | 'append' {\n if (this.appendOnly) return 'append';\n\n const rect = targetEl.getBoundingClientRect();\n const relY = clientY - rect.top;\n const height = rect.height;\n\n if (relY < height * 0.25) return 'before';\n if (relY > height * 0.75) return 'after';\n return 'append';\n }\n\n // -------------------------------------------------------------------------\n // Execute drop\n // -------------------------------------------------------------------------\n\n executeDrop(\n dragData: DragData,\n targetNode: NodeInterface,\n position: 'before' | 'after' | 'append',\n ): void {\n const store = this.tree.getStore();\n\n for (const record of dragData.records) {\n if (position === 'append') {\n store.appendChild(targetNode, record);\n } else if (position === 'before') {\n if (targetNode.parentNode) {\n store.insertBefore(record, targetNode);\n }\n } else {\n // 'after' — insert before next sibling or append\n if (targetNode.nextSibling) {\n store.insertBefore(record, targetNode.nextSibling);\n } else if (targetNode.parentNode) {\n store.appendChild(targetNode.parentNode, record);\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Event handlers\n // -------------------------------------------------------------------------\n\n private onDragOver(e: DragEvent): void {\n e.preventDefault();\n }\n\n private onDrop(e: DragEvent): void {\n e.preventDefault();\n this.clearExpandTimer();\n }\n\n private clearExpandTimer(): void {\n if (this.expandTimer !== null) {\n clearTimeout(this.expandTimer);\n this.expandTimer = null;\n }\n }\n\n private removeIndicator(): void {\n if (this.indicatorEl?.parentNode) {\n this.indicatorEl.parentNode.removeChild(this.indicatorEl);\n }\n this.indicatorEl = null;\n }\n\n destroy(): void {\n const el = this.tree.getView().el;\n if (el) {\n el.removeEventListener('dragover', this.boundDragOver);\n el.removeEventListener('drop', this.boundDrop);\n }\n this.clearExpandTimer();\n this.removeIndicator();\n }\n}\n","/**\n * @framesquared/ui – TreeViewDragDrop\n *\n * Plugin that wires TreeDragZone and TreeDropZone onto a TreePanel.\n */\n\nimport { TreeDragZone } from './TreeDragZone.js';\nimport { TreeDropZone } from './TreeDropZone.js';\nimport type { TreePanelLike } from './TreeDragZone.js';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TreeViewDragDropConfig {\n enableDrag?: boolean;\n enableDrop?: boolean;\n ddGroup?: string;\n appendOnly?: boolean;\n sortOnDrop?: boolean;\n expandDelay?: number;\n allowParentInserts?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// TreeViewDragDrop\n// ---------------------------------------------------------------------------\n\ntype FullTreePanel = TreePanelLike & {\n getStore(): { insertBefore: Function; appendChild: Function };\n};\n\nexport class TreeViewDragDrop {\n private config: TreeViewDragDropConfig;\n private dragZone: TreeDragZone | null = null;\n private dropZone: TreeDropZone | null = null;\n\n constructor(config?: TreeViewDragDropConfig) {\n this.config = config ?? {};\n }\n\n init(tree: FullTreePanel): void {\n if (this.config.enableDrag !== false) {\n this.dragZone = new TreeDragZone(tree, { ddGroup: this.config.ddGroup });\n }\n if (this.config.enableDrop !== false) {\n this.dropZone = new TreeDropZone(tree, {\n ddGroup: this.config.ddGroup,\n appendOnly: this.config.appendOnly,\n sortOnDrop: this.config.sortOnDrop,\n expandDelay: this.config.expandDelay,\n });\n }\n }\n\n getDragZone(): TreeDragZone | null {\n return this.dragZone;\n }\n\n getDropZone(): TreeDropZone | null {\n return this.dropZone;\n }\n\n destroy(): void {\n this.dragZone?.destroy();\n this.dropZone?.destroy();\n this.dragZone = null;\n this.dropZone = null;\n }\n}\n","/**\n * @framesquared/ui – CellEditingPlugin\n *\n * Simple in-place cell editing plugin for tree nodes.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { NodeInterface } from '@framesquared/data';\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface CellEditingConfig {\n clicksToEdit?: number;\n}\n\n/** Minimal interface CellEditingPlugin needs from TreePanel */\nexport interface CellEditingTreePanel {\n on(event: string, fn: Function): void;\n getView(): { getNode(record: NodeInterface): HTMLElement | null };\n}\n\n// ---------------------------------------------------------------------------\n// CellEditingPlugin\n// ---------------------------------------------------------------------------\n\nexport class CellEditingPlugin {\n private tree: CellEditingTreePanel | null = null;\n private config: CellEditingConfig;\n private activeEditor: HTMLInputElement | null = null;\n private editingNode: NodeInterface | null = null;\n private field = 'text';\n\n constructor(config?: CellEditingConfig) {\n this.config = { clicksToEdit: 2, ...config };\n }\n\n init(tree: CellEditingTreePanel): void {\n this.tree = tree;\n const clicksToEdit = this.config.clicksToEdit ?? 2;\n const eventName = clicksToEdit === 1 ? 'itemclick' : 'itemdblclick';\n tree.on(eventName, (node: NodeInterface) => this.startEdit(node));\n }\n\n startEdit(record: NodeInterface, fieldName?: string): void {\n if (this.activeEditor) {\n this.completeEdit();\n }\n\n this.editingNode = record;\n this.field = fieldName ?? 'text';\n\n const view = this.tree?.getView();\n const rowEl = view?.getNode(record);\n if (!rowEl) return;\n\n const textEl = rowEl.querySelector('.x-tree-node-text') as HTMLElement | null;\n if (!textEl) return;\n\n const currentValue = String(record.get(this.field) ?? '');\n\n this.activeEditor = document.createElement('input');\n this.activeEditor.type = 'text';\n this.activeEditor.value = currentValue;\n this.activeEditor.className = 'x-tree-editor';\n\n // Replace text span with editor\n textEl.textContent = '';\n textEl.appendChild(this.activeEditor);\n\n this.activeEditor.focus();\n this.activeEditor.select();\n\n this.activeEditor.addEventListener('blur', () => this.completeEdit());\n this.activeEditor.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n this.completeEdit();\n } else if (e.key === 'Escape') {\n this.cancelEdit();\n }\n });\n }\n\n completeEdit(): void {\n if (!this.activeEditor || !this.editingNode) return;\n\n const newValue = this.activeEditor.value;\n (this.editingNode as any).set(this.field, newValue);\n\n this.cleanupEditor();\n }\n\n cancelEdit(): void {\n if (!this.activeEditor) return;\n this.cleanupEditor();\n }\n\n private cleanupEditor(): void {\n if (this.activeEditor) {\n const parent = this.activeEditor.parentElement;\n if (parent) {\n parent.removeChild(this.activeEditor);\n const node = this.editingNode;\n if (node) {\n parent.textContent = String(node.get(this.field) ?? '');\n }\n }\n }\n this.activeEditor = null;\n this.editingNode = null;\n }\n\n isEditing(): boolean {\n return this.activeEditor !== null;\n }\n\n destroy(): void {\n this.cancelEdit();\n this.tree = null;\n }\n}\n"],"mappings":"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","names":["Component","Container","Container","Component","Container","Container","Container","Component","Component","Component","Component","Component","Component","Component","Component","Container","Container","Container","Component","Base","Observable","oldValue","ObservableMixin","Observable","ensureObservable","Base","record","visible","record"]}