@jimka/typescript-ui 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/{AbstractInput-B10DfLOf.js → AbstractInput-sRNPzWel.js} +2 -2
- package/dist/lib/{AbstractInput-B10DfLOf.js.map → AbstractInput-sRNPzWel.js.map} +1 -1
- package/dist/lib/Anchor-CwRhdP2J.js +2 -0
- package/dist/lib/Anchor-CwRhdP2J.js.map +1 -0
- package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js +2 -0
- package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js.map +1 -0
- package/dist/lib/Border-0DJFDiij.js +2 -0
- package/dist/lib/Border-0DJFDiij.js.map +1 -0
- package/dist/lib/Button-MpMIYBYJ.js +2 -0
- package/dist/lib/Button-MpMIYBYJ.js.map +1 -0
- package/dist/lib/{Card-CD3jxshU.js → Card-QYo27r5b.js} +2 -2
- package/dist/lib/{Card-CD3jxshU.js.map → Card-QYo27r5b.js.map} +1 -1
- package/dist/lib/Checkbox-D0JYK-wc.js +2 -0
- package/dist/lib/Checkbox-D0JYK-wc.js.map +1 -0
- package/dist/lib/CheckboxMenuRow-CesLhSnp.js +2 -0
- package/dist/lib/CheckboxMenuRow-CesLhSnp.js.map +1 -0
- package/dist/lib/{CodeEditor-BGlB232h.js → CodeEditor-N1FQodcF.js} +2 -2
- package/dist/lib/CodeEditor-N1FQodcF.js.map +1 -0
- package/dist/lib/ComboBox-Dx8Tk9yg.js +2 -0
- package/dist/lib/ComboBox-Dx8Tk9yg.js.map +1 -0
- package/dist/lib/Component-B0ShfPVi.js +2 -0
- package/dist/lib/Component-B0ShfPVi.js.map +1 -0
- package/dist/lib/Container-abY5Ww3W.js +2 -0
- package/dist/lib/{Container-C7RPLQEc.js.map → Container-abY5Ww3W.js.map} +1 -1
- package/dist/lib/{DOM-Ba8YRVel.js → DOM-C-Edb3tA.js} +2 -2
- package/dist/lib/DOM-C-Edb3tA.js.map +1 -0
- package/dist/lib/Dialog-cbA9V17e.js +2 -0
- package/dist/lib/Dialog-cbA9V17e.js.map +1 -0
- package/dist/lib/{FieldDecorator-HG65hEtk.js → FieldDecorator-BlYMfZ9L.js} +2 -2
- package/dist/lib/{FieldDecorator-HG65hEtk.js.map → FieldDecorator-BlYMfZ9L.js.map} +1 -1
- package/dist/lib/{Fit-Cg3dPyZg.js → Fit-BhlB-HAo.js} +2 -2
- package/dist/lib/{Fit-Cg3dPyZg.js.map → Fit-BhlB-HAo.js.map} +1 -1
- package/dist/lib/{FloatingPanel-D5buuVrQ.js → FloatingPanel-DkJXsZ2D.js} +2 -2
- package/dist/lib/{FloatingPanel-D5buuVrQ.js.map → FloatingPanel-DkJXsZ2D.js.map} +1 -1
- package/dist/lib/{Glyph-DeJF_zsR.js → Glyph-_VeBacS2.js} +2 -2
- package/dist/lib/{Glyph-DeJF_zsR.js.map → Glyph-_VeBacS2.js.map} +1 -1
- package/dist/lib/{Grid-BYBohJIA.js → Grid-Daiz7F5d.js} +2 -2
- package/dist/lib/Grid-Daiz7F5d.js.map +1 -0
- package/dist/lib/GridConstraints-C58LuTqM.js +2 -0
- package/dist/lib/{GridConstraints-Bts284FI.js.map → GridConstraints-C58LuTqM.js.map} +1 -1
- package/dist/lib/{Header-BIFJK9nR.js → Header-Dql3Zxc6.js} +2 -2
- package/dist/lib/{Header-BIFJK9nR.js.map → Header-Dql3Zxc6.js.map} +1 -1
- package/dist/lib/{IconText-Dsb1xS-E.js → IconText-PUjhTLlp.js} +2 -2
- package/dist/lib/{IconText-Dsb1xS-E.js.map → IconText-PUjhTLlp.js.map} +1 -1
- package/dist/lib/LayoutSerialization-CMxunLfV.js +2 -0
- package/dist/lib/LayoutSerialization-CMxunLfV.js.map +1 -0
- package/dist/lib/List-nx8220Fi.js +2 -0
- package/dist/lib/{List-BPd-IXZR.js.map → List-nx8220Fi.js.map} +1 -1
- package/dist/lib/MemoryStore-DhPoU-7X.js +2 -0
- package/dist/lib/MemoryStore-DhPoU-7X.js.map +1 -0
- package/dist/lib/Menu-Q0bpXXze.js +2 -0
- package/dist/lib/Menu-Q0bpXXze.js.map +1 -0
- package/dist/lib/{MenuButton-BR4KOFld.js → MenuButton-DCXi0tsP.js} +2 -2
- package/dist/lib/{MenuButton-BR4KOFld.js.map → MenuButton-DCXi0tsP.js.map} +1 -1
- package/dist/lib/OverlayFade-3pof2AJH.js +2 -0
- package/dist/lib/OverlayFade-3pof2AJH.js.map +1 -0
- package/dist/lib/{Panel-CpNQTLNF.js → Panel-Cy1pdlWO.js} +2 -2
- package/dist/lib/{Panel-CpNQTLNF.js.map → Panel-Cy1pdlWO.js.map} +1 -1
- package/dist/lib/{Position-PBVBW1JS.js → Position-BwtxouxK.js} +2 -2
- package/dist/lib/{Position-PBVBW1JS.js.map → Position-BwtxouxK.js.map} +1 -1
- package/dist/lib/{ProgressSpinner-lAsK26C-.js → ProgressSpinner-DK8xEQ9y.js} +2 -2
- package/dist/lib/{ProgressSpinner-lAsK26C-.js.map → ProgressSpinner-DK8xEQ9y.js.map} +1 -1
- package/dist/lib/RadioButton-BEwpqg1k.js +2 -0
- package/dist/lib/{RadioButton-CCcIaL54.js.map → RadioButton-BEwpqg1k.js.map} +1 -1
- package/dist/lib/RadioMenuRow-DP5qPyFR.js +2 -0
- package/dist/lib/RadioMenuRow-DP5qPyFR.js.map +1 -0
- package/dist/lib/{RovingTabIndex-C2Vzq0IX.js → RovingTabIndex-pHEv5oLD.js} +2 -2
- package/dist/lib/{RovingTabIndex-C2Vzq0IX.js.map → RovingTabIndex-pHEv5oLD.js.map} +1 -1
- package/dist/lib/Scrollbar-t8fFrUVQ.js +2 -0
- package/dist/lib/Scrollbar-t8fFrUVQ.js.map +1 -0
- package/dist/lib/{Slider-DZ9drUxn.js → Slider-CTbwR6HR.js} +2 -2
- package/dist/lib/{Slider-DZ9drUxn.js.map → Slider-CTbwR6HR.js.map} +1 -1
- package/dist/lib/{Spacer-SDhOMp2g.js → Spacer-srdN2d2b.js} +2 -2
- package/dist/lib/{Spacer-SDhOMp2g.js.map → Spacer-srdN2d2b.js.map} +1 -1
- package/dist/lib/TabButton-DLoMQzky.js +2 -0
- package/dist/lib/TabButton-DLoMQzky.js.map +1 -0
- package/dist/lib/TabCloseButton-CY7BGitY.js +2 -0
- package/dist/lib/TabCloseButton-CY7BGitY.js.map +1 -0
- package/dist/lib/{Text-CdHf3B-1.js → Text-CMKnK9uB.js} +2 -2
- package/dist/lib/{Text-CdHf3B-1.js.map → Text-CMKnK9uB.js.map} +1 -1
- package/dist/lib/{Tooltip-B_UF5bXD.js → Tooltip-CUOJOqQi.js} +3 -3
- package/dist/lib/Tooltip-CUOJOqQi.js.map +1 -0
- package/dist/lib/Tree-C64JNPWJ.js +2 -0
- package/dist/lib/Tree-C64JNPWJ.js.map +1 -0
- package/dist/lib/VBox-DfJPWXqc.js +2 -0
- package/dist/lib/VBox-DfJPWXqc.js.map +1 -0
- package/dist/lib/VirtualScroller-DTIn19o1.js +2 -0
- package/dist/lib/VirtualScroller-DTIn19o1.js.map +1 -0
- package/dist/lib/assets/StoreWorker-B5NwRM2I.js +2 -0
- package/dist/lib/assets/StoreWorker-B5NwRM2I.js.map +1 -0
- package/dist/lib/component/button.es.js +1 -1
- package/dist/lib/component/button.es.js.map +1 -1
- package/dist/lib/component/chart.es.js +1 -1
- package/dist/lib/component/container.es.js +1 -1
- package/dist/lib/component/container.es.js.map +1 -1
- package/dist/lib/component/diagram.es.js +1 -1
- package/dist/lib/component/diagram.es.js.map +1 -1
- package/dist/lib/component/display.es.js +1 -1
- package/dist/lib/component/display.es.js.map +1 -1
- package/dist/lib/component/editor.es.js +2 -2
- package/dist/lib/component/editor.es.js.map +1 -1
- package/dist/lib/component/input.es.js +1 -1
- package/dist/lib/component/input.es.js.map +1 -1
- package/dist/lib/component/list.es.js +1 -1
- package/dist/lib/component/list.es.js.map +1 -1
- package/dist/lib/component/menubar.es.js +1 -1
- package/dist/lib/component/menubar.es.js.map +1 -1
- package/dist/lib/component/table.es.js +6 -3
- package/dist/lib/component/table.es.js.map +1 -1
- package/dist/lib/component/tree.es.js +1 -1
- package/dist/lib/core.es.js +1 -1
- package/dist/lib/core.es.js.map +1 -1
- package/dist/lib/data.es.js +1 -1
- package/dist/lib/glyphs/solid/index.es.js +1 -1
- package/dist/lib/layout.es.js +1 -1
- package/dist/lib/layout.es.js.map +1 -1
- package/dist/lib/overlay.es.js +1 -1
- package/dist/lib/overlay.es.js.map +1 -1
- package/dist/lib/primitive.es.js +1 -1
- package/dist/lib/router.es.js +1 -1
- package/dist/lib/router.es.js.map +1 -1
- package/dist/lib/selectionsEqual-gMG7gCVI.js +2 -0
- package/dist/lib/selectionsEqual-gMG7gCVI.js.map +1 -0
- package/dist/lib/types/component/button/Button.d.ts +13 -0
- package/dist/lib/types/component/button/MenuButton.d.ts +1 -0
- package/dist/lib/types/component/button/PopupButton.d.ts +22 -0
- package/dist/lib/types/component/button/TabButton.d.ts +4 -0
- package/dist/lib/types/component/button/index.d.ts +2 -0
- package/dist/lib/types/component/container/CheckboxMenuRow.d.ts +33 -0
- package/dist/lib/types/component/container/CollapseButton.d.ts +11 -3
- package/dist/lib/types/component/container/MenuItem.d.ts +15 -5
- package/dist/lib/types/component/container/MenuRow.d.ts +24 -0
- package/dist/lib/types/component/container/MenuSeparator.d.ts +4 -2
- package/dist/lib/types/component/container/RadioMenuRow.d.ts +33 -0
- package/dist/lib/types/component/container/Scrollbar.d.ts +5 -0
- package/dist/lib/types/component/container/SplitGutter.d.ts +7 -2
- package/dist/lib/types/component/container/TabBar.d.ts +2 -0
- package/dist/lib/types/component/container/WindowBorder.d.ts +1 -1
- package/dist/lib/types/component/container/index.d.ts +6 -1
- package/dist/lib/types/component/display/WebGLCanvas.d.ts +1 -0
- package/dist/lib/types/component/input/AbstractCalendarDropdown.d.ts +2 -0
- package/dist/lib/types/component/input/AbstractPickerField.d.ts +3 -2
- package/dist/lib/types/component/list/AbstractSelectableList.d.ts +1 -1
- package/dist/lib/types/component/list/MultiSelectList.d.ts +2 -1
- package/dist/lib/types/component/shared/VirtualRowView.d.ts +2 -0
- package/dist/lib/types/component/table/Body.d.ts +22 -1
- package/dist/lib/types/component/table/Column.d.ts +3 -1
- package/dist/lib/types/component/table/ColumnConfig.d.ts +2 -0
- package/dist/lib/types/component/table/ColumnFilter.d.ts +27 -0
- package/dist/lib/types/component/table/Header.d.ts +30 -3
- package/dist/lib/types/component/table/Row.d.ts +4 -0
- package/dist/lib/types/component/table/Table.d.ts +29 -0
- package/dist/lib/types/component/table/TableExporter.d.ts +4 -3
- package/dist/lib/types/component/table/TreeBody.d.ts +2 -1
- package/dist/lib/types/component/table/cell/CellText.d.ts +9 -0
- package/dist/lib/types/component/table/cell/Filter.d.ts +54 -0
- package/dist/lib/types/component/table/cell/FilterClauseBadge.d.ts +21 -0
- package/dist/lib/types/component/table/cell/GroupSeparator.d.ts +9 -0
- package/dist/lib/types/component/table/cell/Header.d.ts +1 -0
- package/dist/lib/types/component/table/cell/editor/CellEditor.d.ts +1 -0
- package/dist/lib/types/component/table/cell/renderer/CellRenderer.d.ts +1 -0
- package/dist/lib/types/component/table/cell/renderer/Combo.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/Date.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/DateTime.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/Filter.d.ts +16 -0
- package/dist/lib/types/component/table/cell/renderer/Glyph.d.ts +1 -0
- package/dist/lib/types/component/table/cell/renderer/Link.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/Number.d.ts +3 -1
- package/dist/lib/types/component/table/cell/renderer/String.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/Time.d.ts +2 -0
- package/dist/lib/types/component/table/cell/renderer/TreeCell.d.ts +1 -0
- package/dist/lib/types/component/table/index.d.ts +6 -0
- package/dist/lib/types/component/tree/Tree.d.ts +17 -1
- package/dist/lib/types/component/tree/index.d.ts +1 -1
- package/dist/lib/types/core/AnimatedDropdown.d.ts +0 -9
- package/dist/lib/types/core/Body.d.ts +4 -0
- package/dist/lib/types/core/ClassStyleRules.d.ts +1 -0
- package/dist/lib/types/core/DOM.d.ts +10 -0
- package/dist/lib/types/core/Event.d.ts +11 -2
- package/dist/lib/types/core/OverlayFade.d.ts +12 -0
- package/dist/lib/types/core/OverlayPosition.d.ts +6 -0
- package/dist/lib/types/core/Theme.d.ts +8 -0
- package/dist/lib/types/core/index.d.ts +5 -3
- package/dist/lib/types/data/AbstractStore.d.ts +3 -0
- package/dist/lib/types/data/FilterDescriptor.d.ts +13 -0
- package/dist/lib/types/data/index.d.ts +2 -1
- package/dist/lib/types/data/temporalText.d.ts +2 -0
- package/dist/lib/types/layout/BoxLayout.d.ts +6 -1
- package/dist/lib/types/layout/Grid.d.ts +1 -0
- package/dist/lib/types/layout/HFlow.d.ts +1 -1
- package/dist/lib/types/layout/Split.d.ts +10 -1
- package/dist/lib/types/layout/Tab.d.ts +7 -1
- package/dist/lib/types/layout/VFlow.d.ts +1 -1
- package/dist/lib/types/layout/index.d.ts +1 -1
- package/dist/lib/types/overlay/Dock.d.ts +1 -0
- package/dist/lib/types/overlay/Menu.d.ts +1 -1
- package/dist/lib/types/overlay/Popover.d.ts +3 -0
- package/dist/lib/types/overlay/PopupPanel.d.ts +17 -0
- package/dist/lib/types/overlay/Window.d.ts +2 -0
- package/dist/lib/types/overlay/index.d.ts +2 -0
- package/dist/lib/types/router/RoutePattern.d.ts +7 -0
- package/dist/lib/types/router/Router.d.ts +6 -2
- package/dist/lib/types/router/index.d.ts +1 -1
- package/dist/lib/validation.es.js +1 -1
- package/llms.txt +4 -0
- package/package.json +1 -1
- package/dist/lib/AbstractBooleanInput-CbW7ZrDT.js +0 -2
- package/dist/lib/AbstractBooleanInput-CbW7ZrDT.js.map +0 -1
- package/dist/lib/Anchor-BsblS5it.js +0 -2
- package/dist/lib/Anchor-BsblS5it.js.map +0 -1
- package/dist/lib/AnimatedDropdown-kL47HPGP.js +0 -2
- package/dist/lib/AnimatedDropdown-kL47HPGP.js.map +0 -1
- package/dist/lib/Border-CNS6aEXB.js +0 -2
- package/dist/lib/Border-CNS6aEXB.js.map +0 -1
- package/dist/lib/Button-T16zSZip.js +0 -2
- package/dist/lib/Button-T16zSZip.js.map +0 -1
- package/dist/lib/CodeEditor-BGlB232h.js.map +0 -1
- package/dist/lib/ComboBox-C9FYMuLv.js +0 -2
- package/dist/lib/ComboBox-C9FYMuLv.js.map +0 -1
- package/dist/lib/Component-w65rPK75.js +0 -2
- package/dist/lib/Component-w65rPK75.js.map +0 -1
- package/dist/lib/Container-C7RPLQEc.js +0 -2
- package/dist/lib/DOM-Ba8YRVel.js.map +0 -1
- package/dist/lib/DragManager-UvPHSoRm.js +0 -2
- package/dist/lib/DragManager-UvPHSoRm.js.map +0 -1
- package/dist/lib/Grid-BYBohJIA.js.map +0 -1
- package/dist/lib/GridConstraints-Bts284FI.js +0 -2
- package/dist/lib/LayoutSerialization-ySzY1h2l.js +0 -2
- package/dist/lib/LayoutSerialization-ySzY1h2l.js.map +0 -1
- package/dist/lib/LayoutSizes-DKDK1Cle.js +0 -2
- package/dist/lib/LayoutSizes-DKDK1Cle.js.map +0 -1
- package/dist/lib/List-BPd-IXZR.js +0 -2
- package/dist/lib/MemoryStore-BgP7-Uzn.js +0 -2
- package/dist/lib/MemoryStore-BgP7-Uzn.js.map +0 -1
- package/dist/lib/Menu-C0roOCY7.js +0 -2
- package/dist/lib/Menu-C0roOCY7.js.map +0 -1
- package/dist/lib/RadioButton-CCcIaL54.js +0 -2
- package/dist/lib/Scrollbar-C3ZZyZ1e.js +0 -2
- package/dist/lib/Scrollbar-C3ZZyZ1e.js.map +0 -1
- package/dist/lib/TabButton-DNo4ZgV8.js +0 -2
- package/dist/lib/TabButton-DNo4ZgV8.js.map +0 -1
- package/dist/lib/Tooltip-B_UF5bXD.js.map +0 -1
- package/dist/lib/Tree-C7qLbIYH.js +0 -2
- package/dist/lib/Tree-C7qLbIYH.js.map +0 -1
- package/dist/lib/VBox-32fxpkDl.js +0 -2
- package/dist/lib/VBox-32fxpkDl.js.map +0 -1
- package/dist/lib/VirtualScroller-cvFNMS7U.js +0 -2
- package/dist/lib/VirtualScroller-cvFNMS7U.js.map +0 -1
- package/dist/lib/assets/StoreWorker-CgOBYoai.js +0 -2
- package/dist/lib/assets/StoreWorker-CgOBYoai.js.map +0 -1
- package/dist/lib/selectionsEqual-BrTxPMmK.js +0 -2
- package/dist/lib/selectionsEqual-BrTxPMmK.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"../DOM-
|
|
1
|
+
import{t as e}from"../DOM-C-Edb3tA.js";import{n as t}from"../Position-BwtxouxK.js";import{h as n,t as r}from"../Component-B0ShfPVi.js";import{t as i}from"../Glyph-_VeBacS2.js";import{t as a}from"../Text-CMKnK9uB.js";import{n as o,r as s}from"../VBox-DfJPWXqc.js";import{i as c,n as l,r as u,t as d}from"../List-nx8220Fi.js";import{t as f}from"../reduceModifierSelection-DTo8HyFl.js";var MultiSelectList=class extends l{constructor(e){super(e),this.getAria().setMultiselectable(!0),this._options.selectedIndices!==void 0&&this.applyInitialSelection(this._options.selectedIndices)}applyOptions(e){return super.applyOptions(e),e.selectedIndices!==void 0&&(this._options.selectedIndices=e.selectedIndices),this}setValues(e){let t=new Set(e);this._selectedSet.clear();for(let e=0;e<this._items.length;e++)t.has(this._items[e].key)&&this._selectedSet.add(e);return this._anchorIndex=this._selectedSet.size>0?Math.max(...this._selectedSet):null,this.refreshRowVisualState(),this.updateActiveDescendant(),this}setValue(e){return this.setValues(e)}getValue(){return[...this._selectedSet].sort((e,t)=>e-t).map(e=>this._items[e].key)}getSelectedRecords(){let e=this.getStore();if(!e)return[];let t=e.getRecords(),n=[...this._selectedSet].sort((e,t)=>e-t),r=[];for(let e of n)e<t.length&&r.push(t[e]);return r}setSelectedRecords(e){let t=this.getStore();if(!t)return this;let n=new Set(e),r=t.getRecords(),i=[];for(let e=0;e<this._items.length&&e<r.length;e++)n.has(r[e])&&i.push(this._items[e].key);return this.setValues(i)}reduceSelection(e,t){this._anchorIndex=f(this._selectedSet,this._anchorIndex,e,e=>e,e=>e,t),this._focusedIndex=e}notifyUserChange(){this.fireChange()}handleKeyDown(e){if(!(!this.isEnabled()||this.isReadOnly()))return(e.ctrlKey||e.metaKey)&&(e.key===`a`||e.key===`A`)?(this.selectAll(),{prevent:!0}):super.handleKeyDown(e)}selectAll(){if(this._items.length!==0){this._selectedSet.clear();for(let e=0;e<this._items.length;e++)this._selectedSet.add(e);this._anchorIndex=0,this._focusedIndex=this._items.length-1,this.refreshRowVisualState(),this.updateActiveDescendant(),this.notifyUserChange()}}applyInitialSelection(e){this._selectedSet.clear();for(let t of e)t>=0&&t<this._items.length&&this._selectedSet.add(t);this._selectedSet.size>0&&(this._anchorIndex=Math.max(...this._selectedSet)),this.refreshRowVisualState(),this.updateActiveDescendant()}},p=n(MultiSelectList),AbstractMarkerList=class extends r{_markerColumnWidth=0;constructor(e,n,r,i){super(r,{tag:e,padding:new t(0,0,0,25),layoutManager:new o({spacing:0,stretching:!0}),itemStyle:n,...i??{}}),this.setElementCSSRule(`listStyleType`,`none`),this.getAria().setRole(`list`)}applyOptions(e){return super.applyOptions(e),this.setStyle(e.itemStyle??this.getStyle()),this}getStyle(){return this._style??this._defaultOptions.itemStyle}setStyle(e){return this._style=e,this.renumber(),this}getMarkerColumnWidth(){return this._markerColumnWidth}doLayout(){return this.isLayoutPaused()?this:(this.syncMarkerColumn(),super.doLayout())}syncMarkerColumn(){let e=this.getComponents(),t=0;for(let n of e)t=Math.max(t,n.getMarkerWidth());this._markerColumnWidth=t;for(let n of e)n.setMarkerColumnWidth(t)}renumber(){let e=this.getComponents();for(let t=0;t<e.length;t++)e[t].setMarker(this.markerText(t))}addComponent(e,t){return super.addComponent(e,t),this}insertComponent(e,t,n){return super.insertComponent(e,t,n),this.renumber(),this}removeComponent(e){let t=super.removeComponent(e);return this.renumber(),t}sortComponents(e){return super.sortComponents(e),this.renumber(),this}},m=function(e){return e.NONE=`none`,e.DISC=`disc`,e.CIRCLE=`circle`,e.SQUARE=`square`,e}({}),h={[m.NONE]:``,[m.DISC]:`•`,[m.CIRCLE]:`◦`,[m.SQUARE]:`▪`},BulletedList=class extends AbstractMarkerList{constructor(e){super(`ul`,m.DISC,e)}markerText(e){return h[this.getStyle()]}},g=n(BulletedList),_=function(e){return e.NONE=`none`,e.DECIMAL=`decimal`,e.DECIMAL_LEADING_ZERO=`decimal-leading-zero`,e.LOWER_ALPHA=`lower-alpha`,e.LOWER_GREEK=`lower-greek`,e.LOWER_LATIN=`lower-latin`,e.LOWER_ROMAN=`lower-roman`,e.UPPER_ALPHA=`upper-alpha`,e.UPPER_GREEK=`upper-greek`,e.UPPER_LATIN=`upper-latin`,e.UPPER_ROMAN=`upper-roman`,e}({}),v=2,y=3999,b=`abcdefghijklmnopqrstuvwxyz`,x=`αβγδεζηθικλμνξοπρστυφχψω`,S=[[1e3,`m`],[900,`cm`],[500,`d`],[400,`cd`],[100,`c`],[90,`xc`],[50,`l`],[40,`xl`],[10,`x`],[9,`ix`],[5,`v`],[4,`iv`],[1,`i`]];function alphabetic(e,t){let n=t.length,r=``,i=e;for(;i>0;)--i,r=t[i%n]+r,i=Math.floor(i/n);return r}function roman(e){if(e>y)return String(e);let t=``,n=e;for(let[e,r]of S)for(;n>=e;)t+=r,n-=e;return t}var C={[_.DECIMAL]:e=>String(e),[_.DECIMAL_LEADING_ZERO]:e=>String(e).padStart(v,`0`),[_.LOWER_ALPHA]:e=>alphabetic(e,b),[_.LOWER_LATIN]:e=>alphabetic(e,b),[_.UPPER_ALPHA]:e=>alphabetic(e,b).toUpperCase(),[_.UPPER_LATIN]:e=>alphabetic(e,b).toUpperCase(),[_.LOWER_GREEK]:e=>alphabetic(e,x),[_.UPPER_GREEK]:e=>alphabetic(e,x).toUpperCase(),[_.LOWER_ROMAN]:e=>roman(e),[_.UPPER_ROMAN]:e=>roman(e).toUpperCase()},NumberedList=class extends AbstractMarkerList{constructor(e){super(`ol`,_.DECIMAL,e)}markerText(e){let t=this.getStyle();return t===_.NONE?``:C[t](e+1)+`.`}},w=n(NumberedList),T=4,E={tag:`li`},ListItem=class extends r{_key;_marker;_text;constructor(e,t,n,r){super(n,{...E,layoutManager:new s({spacing:T}),...r??{}}),this._key=e,this._marker=new a(void 0,{textAlign:`right`}),this._text=new a,this.addComponent(this._marker),this.addComponent(this._text,{weight:1}),this._marker.getAria().setHidden(!0),this.getAria().setRole(`listitem`),this.setText(this._options.text??t),this.setMarker(``)}applyOptions(e){return super.applyOptions(e),e.text!==void 0&&(this._options.text=e.text),this}getKey(){return this._key}getText(){return this._text.getText().valueOf()}setText(e){return this._text.setText(e),this}getMarker(){return this._marker.getText().valueOf()}setMarker(e){return this._marker.setText(e),this._marker.setDisplayed(e.length>0),this}getMarkerWidth(){return this._marker.getPreferredSize(),this._marker.getPreferredSizeConstraint()?.width??0}setMarkerColumnWidth(e){return this._marker.setMinSize({width:e,height:0}),this}render(){let t=super.render();return e.sink.apply(t,{dataset:{key:this._key}}),t}},D=n(ListItem),O=20,k=16,GlyphListItemRenderer=class extends c{_icon=null;_label;_currentGlyph=null;_measured=!1;constructor(){super(),this.clearInsets(),this._label=new a,this._label.clearInsets(),this._label.setAutoMeasure(!1)}update(t){let n=t.item.glyph?t.item.glyph:null;if(n!==this._currentGlyph){let t=this.getElement();if(t&&this._icon){let n=this._icon.getElement();n&&e.source.getParentNode(n)===t&&e.sink.removeChild(t,n)}this._icon=null,this._currentGlyph=n,n!==null&&(this._icon=new i(n),this._icon.clearInsets(),this._icon.setPointerEvents(`none`),t&&e.sink.insertBefore(t,this._icon.getElement(!0),this._label.getElement()??null))}this._label.setText(t.item.label),this._measured=!1}getContentWidth(){this._measured||=(this._label.measure(),!0);let e=this._label.getPreferredSize()?.width??0;return(this._icon?O:0)+e}layoutChildren(e,t){let n=this.getContentBounds()??{x:0,y:0,width:e,height:t};this._icon&&(this._icon.setAutoCommitStyle(!1),this._icon.setX(n.x),this._icon.setY(n.y+Math.max(0,(n.height-k)/2)),this._icon.setWidth(k),this._icon.setHeight(k),this._icon.setAutoCommitStyle(!0));let r=n.x+(this._icon?O:0),i=Math.max(0,n.x+n.width-r);this._label.setAutoCommitStyle(!1),this._label.setX(r),this._label.setY(n.y),this._label.setWidth(i),this._label.setHeight(n.height),this._label.setLineHeight(n.height),this._label.setAutoCommitStyle(!0)}init(t){super.init(t);let n=t||this.getElement();return n?(this._icon&&e.sink.appendChild(n,this._icon.getElement(!0)),e.sink.appendChild(n,this._label.getElement(!0)),this):this}},A=n(GlyphListItemRenderer);export{AbstractMarkerList,g as BulletedList,m as BulletedListItemStyle,A as GlyphListItemRenderer,u as LabelListItemRenderer,d as List,D as ListItem,c as ListItemRenderer,p as MultiSelectList,w as NumberedList,_ as NumberedListItemStyle};
|
|
2
2
|
//# sourceMappingURL=list.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.es.js","names":[],"sources":["../../../src/typescript/lib/component/list/MultiSelectList.ts","../../../src/typescript/lib/component/list/AbstractMarkerList.ts","../../../src/typescript/lib/component/list/BulletedListItemStyle.ts","../../../src/typescript/lib/component/list/BulletedList.ts","../../../src/typescript/lib/component/list/NumberedListItemStyle.ts","../../../src/typescript/lib/component/list/NumberedList.ts","../../../src/typescript/lib/component/list/ListItem.ts","../../../src/typescript/lib/component/list/renderer/Glyph.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractSelectableList, AbstractSelectableListOptions } from \"~/component/list/AbstractSelectableList.js\";\nimport { ModelRecord } from \"~/data/ModelRecord.js\";\nimport { reduceModifierSelection } from \"~/component/shared/reduceModifierSelection.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link MultiSelectList}.\n *\n * @category Components\n */\nexport interface MultiSelectListOptions extends AbstractSelectableListOptions {\n selectedIndices?: number[];\n}\n\n/**\n * A scrollable multi-selection list box.\n *\n * Rendered as a `<div role=\"listbox\" aria-multiselectable=\"true\">`\n * populated with `<div role=\"option\">` rows. Implements\n * [`Bindable<string[]>`](/api/core/interfaces/Bindable) so it can be\n * plugged into a [`Binding`](/api/core/classes/Binding) directly — earlier\n * versions required explicit `BindingAccessors` because the single-value\n * `Bindable<string>` contract didn't fit. Selection follows the\n * standard modifier-key model:\n *\n * - Plain click / Enter / Space replaces the selection with the\n * clicked row.\n * - Ctrl-click (Cmd on macOS) / Ctrl+Space toggles the clicked row's\n * selection.\n * - Shift-click / Shift+Arrow extends the selection from the anchor\n * row to the targeted row.\n *\n * @category Components\n */\nclass MultiSelectList extends AbstractSelectableList<string[], MultiSelectListOptions> {\n\n /**\n * @param options - Optional. Construction-time options applied to\n * the list.\n */\n constructor(options?: MultiSelectListOptions) {\n super(options);\n\n this.getAria().setMultiselectable(true);\n\n // Late-built state: `selectedIndices` was written pure to\n // `_options` by the super-time cascade. Dispatch it now that the\n // row pool exists (`super()` already populated `_items` from\n // `items` / `store`, and applied `enabled` / `readOnly`).\n if (this._options.selectedIndices !== undefined) {\n this.applyInitialSelection(this._options.selectedIndices);\n }\n }\n\n /**\n * Applies a {@link MultiSelectListOptions} bag. Multi-select state\n * fields are written pure into `_options` here and dispatched from the\n * constructor body after the row pool is built.\n *\n * @param options - The options bag carrying the values to apply.\n *\n * @returns This component, for method chaining.\n */\n protected applyOptions(options: MultiSelectListOptions): this {\n super.applyOptions(options);\n\n if (options.selectedIndices !== undefined) this._options.selectedIndices = options.selectedIndices;\n\n return this;\n }\n\n /**\n * Replaces the selection with the rows whose keys appear in\n * `values`. Programmatic — does not fire the `change` event; user-\n * driven gestures route through the click / keyboard reducer\n * instead.\n *\n * @param values - The row keys to select.\n *\n * @returns This component, for method chaining.\n */\n setValues(values: string[]): this {\n const valueSet = new Set(values);\n\n this._selectedSet.clear();\n\n for (let i = 0; i < this._items.length; i++) {\n if (valueSet.has(this._items[i].key)) {\n this._selectedSet.add(i);\n }\n }\n\n // Park the anchor at the last selected index when there is one,\n // so a follow-up Shift-arrow extends from a sensible position.\n if (this._selectedSet.size > 0) {\n this._anchorIndex = Math.max(...this._selectedSet);\n } else {\n this._anchorIndex = null;\n }\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n\n return this;\n }\n\n /**\n * `Bindable<string[]>` write-side — alias of {@link setValues}.\n *\n * @param value - The row keys to select.\n *\n * @returns This component, for method chaining.\n */\n setValue(value: string[]): this {\n return this.setValues(value);\n }\n\n /**\n * Returns the keys of every currently selected row, sorted by row\n * order. Satisfies the `Bindable<string[]>` read-side.\n *\n * @returns The selected row keys.\n */\n getValue(): string[] {\n const indices = [...this._selectedSet].sort((a, b) => a - b);\n\n return indices.map(i => this._items[i].key);\n }\n\n /**\n * Returns the store records that correspond to the currently\n * selected rows.\n *\n * @returns The selected [`ModelRecord`](/api/data/classes/ModelRecord)\n * instances in row order, or an empty array when no store is bound.\n */\n getSelectedRecords(): ModelRecord[] {\n const store = this.getStore();\n\n if (!store) {\n return [];\n }\n\n const records = store.getRecords();\n const indices = [...this._selectedSet].sort((a, b) => a - b);\n const result: ModelRecord[] = [];\n\n for (const i of indices) {\n if (i < records.length) {\n result.push(records[i]);\n }\n }\n\n return result;\n }\n\n /**\n * Replaces the selection with the rows whose backing records appear\n * in `records`. Relies on the parallel ordering of `_items` and\n * `store.getRecords()` that the store-bound refresh guarantees — see\n * [`setStore`](/api/component/list/classes/MultiSelectList#setstore).\n *\n * @param records - The store records to select.\n *\n * @returns This component, for method chaining.\n */\n setSelectedRecords(records: ModelRecord[]): this {\n const store = this.getStore();\n\n if (!store) {\n return this;\n }\n\n const recordSet = new Set(records);\n const storeRecords = store.getRecords();\n const values: string[] = [];\n\n for (let i = 0; i < this._items.length && i < storeRecords.length; i++) {\n if (recordSet.has(storeRecords[i])) {\n values.push(this._items[i].key);\n }\n }\n\n return this.setValues(values);\n }\n\n /**\n * Reduces a click / keyboard gesture into the multi-select shape.\n * Ported verbatim from [`Body.onRowClick`](/api/component/table/classes/Body) — the same modifier\n * rules apply: plain replaces, `ctrl` toggles individual rows,\n * `shift` extends the selection from the anchor row to `idx`.\n *\n * @param idx - The row index the gesture targeted.\n * @param ev - The normalised modifier flags.\n */\n protected reduceSelection(idx: number, ev: { ctrl: boolean, shift: boolean }): void {\n this._anchorIndex = reduceModifierSelection(\n this._selectedSet,\n this._anchorIndex,\n idx,\n i => i,\n i => i,\n ev,\n );\n\n this._focusedIndex = idx;\n }\n\n /**\n * User-driven selection commit. Fires the `change` event the same\n * way the prior native `<select multiple>` did — only user-driven\n * gestures (click / keyboard reducer) route through it.\n */\n protected notifyUserChange(): void {\n this.fireChange();\n }\n\n /**\n * Extends the base keyboard map with `Ctrl+A` (select-all) — every\n * other key delegates to {@link AbstractSelectableList.handleKeyDown}.\n *\n * @param e - The keyboard event.\n */\n protected handleKeyDown(e: KeyboardEvent): void {\n if (!this.isEnabled() || this.isReadOnly()) {\n return;\n }\n\n const ctrl = e.ctrlKey || e.metaKey;\n\n if (ctrl && (e.key === \"a\" || e.key === \"A\")) {\n e.preventDefault();\n this.selectAll();\n\n return;\n }\n\n super.handleKeyDown(e);\n }\n\n /**\n * Selects every row in the list. Used by the Ctrl+A keyboard shortcut.\n */\n protected selectAll(): void {\n if (this._items.length === 0) {\n return;\n }\n\n this._selectedSet.clear();\n\n for (let i = 0; i < this._items.length; i++) {\n this._selectedSet.add(i);\n }\n\n this._anchorIndex = 0;\n this._focusedIndex = this._items.length - 1;\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n this.notifyUserChange();\n }\n\n /**\n * Construction-tail dispatch of `selectedIndices`. Writes the\n * indices directly into the selection set without firing `change`,\n * matching the construct-time semantics of `setValues` (programmatic\n * writes are silent; user gestures emit `change`).\n *\n * @param indices - Initial selection indices from the options bag.\n */\n private applyInitialSelection(indices: number[]): void {\n this._selectedSet.clear();\n\n for (const i of indices) {\n if (i >= 0 && i < this._items.length) {\n this._selectedSet.add(i);\n }\n }\n\n if (this._selectedSet.size > 0) {\n this._anchorIndex = Math.max(...this._selectedSet);\n }\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n }\n}\n\nconst MultiSelectListCallable = callable(MultiSelectList);\ntype MultiSelectListCallable = MultiSelectList;\nexport {\n MultiSelectList as _MultiSelectList,\n MultiSelectListCallable as MultiSelectList,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Comparator, Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { VBox } from \"~/layout/VBox.js\";\nimport { LayoutConstraints } from \"~/layout/LayoutConstraints.js\";\nimport { BulletedListItemStyle } from \"~/component/list/BulletedListItemStyle.js\";\nimport { NumberedListItemStyle } from \"~/component/list/NumberedListItemStyle.js\";\nimport { ListItem } from \"~/component/list/ListItem.js\";\n\n/**\n * Construction-time options for {@link AbstractMarkerList}.\n *\n * @category Components\n */\nexport interface AbstractMarkerListOptions<U extends BulletedListItemStyle | NumberedListItemStyle> extends ComponentOptions {\n itemStyle?: U;\n}\n\n/**\n * Abstract base for bulleted and numbered list components.\n *\n * Owns each item's marker string — the bullet or number — and rewrites every\n * one whenever the children or the style change; the browser's own marker is\n * suppressed. Restricts child components to ListItem instances. Items are\n * stacked vertically by a [`VBox`](/api/layout/classes/VBox), and the list sizes\n * itself to them. Concrete subclasses supply the HTML tag, the default style,\n * and the marker string for a given position.\n *\n * Also owns the shared marker column: each layout pass measures every item's\n * marker and widens all of them to the widest, so markers share a right edge\n * and labels share a left one however much their widths differ.\n */\nexport abstract class AbstractMarkerList<U extends BulletedListItemStyle | NumberedListItemStyle> extends Component<AbstractMarkerListOptions<U>> {\n\n // `declare` rather than initializer to dodge the class-field\n // super-cascade trap: the cascade-time setStyle write would otherwise\n // be clobbered by a `= undefined` initializer running after super().\n // The cascade always dispatches setStyle because the constructor seeds\n // `itemStyle: style` into the defaults bag below.\n declare private _style: U | undefined;\n\n // Framework-managed derived state: recomputed from the items on every\n // layout pass, so it gets no setter and no options field. A plain\n // initializer is safe because no cascade-dispatched setter writes it.\n private _markerColumnWidth: number = 0;\n\n constructor(\n tag: string,\n style: U,\n options?: AbstractMarkerListOptions<U>,\n subclassDefaults?: Partial<AbstractMarkerListOptions<U>>,\n ) {\n super(options, {\n tag,\n // The left padding indents every item. The marker is drawn inside\n // the item's own box, not in this band — see ListItem.\n padding: new Insets(0, 0, 0, 25),\n layoutManager: new VBox({ spacing: 0, stretching: true }),\n itemStyle: style,\n ...(subclassDefaults ?? {}),\n } as Partial<AbstractMarkerListOptions<U>>);\n\n // Each item paints its own marker, so the browser must not paint a\n // second one beside it.\n this.setElementCSSRule(\"listStyleType\", \"none\");\n this.getAria().setRole(\"list\");\n }\n\n /**\n * Applies an {@link AbstractMarkerListOptions} bag, dispatching the list\n * marker style after inherited Component fields.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: AbstractMarkerListOptions<U>): this {\n super.applyOptions(options);\n\n // `itemStyle` is always defaulted (the constructor seeds the required\n // `style` param into `_defaultOptions`), so always dispatch the caller\n // value or the class default — this seeds the `declare`d `_style` field\n // without touching `_options`.\n this.setStyle(options.itemStyle ?? this.getStyle()!);\n\n return this;\n }\n\n /**\n * Returns the current marker style.\n *\n * @returns The current style enum value, or undefined if not yet set.\n */\n getStyle() {\n return this._style ?? this._defaultOptions.itemStyle;\n }\n\n /**\n * Sets the marker style and rewrites every item's marker to match.\n *\n * @param style - The list item style enum value to apply.\n */\n setStyle(style: U) : this {\n this._style = style;\n this.renumber();\n\n return this;\n }\n\n /**\n * Returns the width every item's marker slot is currently widened to.\n *\n * @returns The shared marker column width in pixels; 0 before the first\n * layout, and 0 for a list whose style shows no marker.\n */\n getMarkerColumnWidth(): number {\n return this._markerColumnWidth;\n }\n\n /**\n * Recomputes the shared marker column, then lays the items out.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n // The pause check is duplicated from Component.doLayout on purpose:\n // without it a paused list would still measure and write minimum sizes,\n // and each write would schedule a layout on its parent.\n if (this.isLayoutPaused()) {\n return this;\n }\n\n this.syncMarkerColumn();\n\n return super.doLayout();\n }\n\n /**\n * Measures every item's marker and pushes the widest width onto all of them,\n * so each item's label starts at the same offset.\n *\n * @remarks Walks every child rather than only the displayed ones, for the\n * same reason the renumbering pass does — hiding the item that carries the\n * widest marker would otherwise shift every remaining label sideways on the\n * next unrelated layout.\n */\n protected syncMarkerColumn(): void {\n const items = this.getComponents() as ListItem[];\n let width = 0;\n\n for (const item of items) {\n width = Math.max(width, item.getMarkerWidth());\n }\n\n this._markerColumnWidth = width;\n\n for (const item of items) {\n item.setMarkerColumnWidth(width);\n }\n }\n\n /**\n * Returns the marker string for the child at `index` under the current\n * style. Implemented by each concrete list.\n *\n * @param index - The child's zero-based position in the list.\n *\n * @returns The marker string, or `\"\"` when the style shows no marker.\n */\n protected abstract markerText(index: number): string;\n\n /**\n * Rewrites every child's marker from its current position. A no-op while\n * the list is empty, which is what makes the construction-time style\n * dispatch harmless.\n *\n * @remarks Walks every child rather than only the displayed ones, so a\n * hidden item still consumes its number — nothing notifies a list when a\n * child's displayed flag flips, so position-dependent markers would\n * otherwise go stale the moment a consumer hid an item.\n */\n protected renumber(): void {\n const items = this.getComponents() as ListItem[];\n\n for (let i = 0; i < items.length; i++) {\n items[i].setMarker(this.markerText(i));\n }\n }\n\n /**\n * Adds a ListItem child; restricts the type accepted by this container to ListItem.\n *\n * @param component - The ListItem to add.\n * @param constraints - Optional. Layout constraints for the item.\n */\n addComponent(component: ListItem, constraints?: LayoutConstraints): this {\n super.addComponent(component, constraints);\n\n return this;\n }\n\n /**\n * Inserts a ListItem child at `index` and renumbers the list.\n *\n * @param component - The ListItem to insert.\n * @param index - The position to insert at.\n * @param constraints - Optional. Layout constraints for the item.\n */\n insertComponent(component: ListItem, index: number, constraints?: LayoutConstraints): this {\n super.insertComponent(component, index, constraints);\n this.renumber();\n\n return this;\n }\n\n /**\n * Removes a ListItem child and renumbers the survivors.\n *\n * @param component - The ListItem instance to remove.\n *\n * @returns The layout constraints that were registered for the removed item, or undefined.\n */\n removeComponent(component: ListItem) {\n const constraints = super.removeComponent(component);\n\n this.renumber();\n\n return constraints;\n }\n\n /**\n * Reorders the items and renumbers them in the new order.\n *\n * @param comparator - The comparator to sort the items by.\n *\n * @remarks `sortComponents` is the only reorder path that does not express\n * itself through insert/remove, so it needs its own hook.\n */\n sortComponents(comparator: Comparator<Component, Component> | undefined): this {\n super.sortComponents(comparator);\n this.renumber();\n\n return this;\n }\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * CSS list-style-type values for bulleted (unordered) lists.\n *\n * @category Components\n */\nexport enum BulletedListItemStyle {\n NONE = \"none\",\n DISC = \"disc\",\n CIRCLE = \"circle\",\n SQUARE = \"square\"\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractMarkerList, AbstractMarkerListOptions } from \"~/component/list/AbstractMarkerList.js\";\nimport { BulletedListItemStyle } from \"~/component/list/BulletedListItemStyle.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link BulletedList}.\n *\n * @category Components\n */\nexport interface BulletedListOptions extends AbstractMarkerListOptions<BulletedListItemStyle> {\n}\n\n/** The character each bullet style paints, keyed by style. */\nconst BULLET_MARKERS: Record<BulletedListItemStyle, string> = {\n [BulletedListItemStyle.NONE]: \"\",\n [BulletedListItemStyle.DISC]: \"•\", // • BULLET\n [BulletedListItemStyle.CIRCLE]: \"◦\", // ◦ WHITE BULLET\n [BulletedListItemStyle.SQUARE]: \"▪\", // ▪ BLACK SMALL SQUARE\n};\n\n/**\n * An unordered (bulleted) list component.\n *\n * Renders a `<ul>` element and defaults to the DISC bullet style. Every\n * [`BulletedListItemStyle`](/api/component/list/enumerations/BulletedListItemStyle)\n * member renders; `NONE` collapses the marker slot away entirely.\n *\n * @category Components\n */\nclass BulletedList extends AbstractMarkerList<BulletedListItemStyle> {\n\n constructor(options?: BulletedListOptions) {\n super(\"ul\", BulletedListItemStyle.DISC, options);\n }\n\n /**\n * Returns the bullet character for the current style. Every item in a\n * bulleted list carries the same marker, so the position is unused.\n *\n * @param _index - The item's position, which does not affect a bullet.\n *\n * @returns The bullet character, or `\"\"` under the NONE style.\n */\n protected markerText(_index: number): string {\n return BULLET_MARKERS[this.getStyle()!];\n }\n}\n\nconst BulletedListCallable = callable(BulletedList);\ntype BulletedListCallable = BulletedList;\nexport {\n BulletedList as _BulletedList,\n BulletedListCallable as BulletedList\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * CSS list-style-type values for numbered (ordered) lists.\n *\n * @category Components\n */\nexport enum NumberedListItemStyle {\n NONE = \"none\",\n DECIMAL = \"decimal\",\n DECIMAL_LEADING_ZERO = \"decimal-leading-zero\",\n LOWER_ALPHA = \"lower-alpha\",\n LOWER_GREEK = \"lower-greek\",\n LOWER_LATIN = \"lower-latin\",\n LOWER_ROMAN = \"lower-roman\",\n UPPER_ALPHA = \"upper-alpha\",\n UPPER_GREEK = \"upper-greek\",\n UPPER_LATIN = \"upper-latin\",\n UPPER_ROMAN = \"upper-roman\"\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractMarkerList, AbstractMarkerListOptions } from \"~/component/list/AbstractMarkerList.js\";\nimport { NumberedListItemStyle } from \"~/component/list/NumberedListItemStyle.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link NumberedList}.\n *\n * @category Components\n */\nexport interface NumberedListOptions extends AbstractMarkerListOptions<NumberedListItemStyle> {\n}\n\n/** CSS `decimal-leading-zero` pads to a minimum of two digits and never truncates. */\nconst DECIMAL_MIN_DIGITS = 2;\n\n/**\n * The largest item number roman numerals cover. CSS Counter Styles gives\n * `lower-roman` / `upper-roman` the range 1–3999 and falls back to `decimal`\n * outside it; above 3999 the additive symbol set has no notation left.\n */\nconst ROMAN_MAX = 3999;\n\n/** Latin letters, in the order CSS's `lower-alpha` / `lower-latin` counts them. */\nconst LOWER_LATIN_LETTERS = \"abcdefghijklmnopqrstuvwxyz\";\n\n/** The 24 Greek letters CSS's `lower-greek` counts, with `σ` and no final sigma. */\nconst LOWER_GREEK_LETTERS = \"αβγδεζηθικλμνξοπρστυφχψω\";\n\n/** Roman symbols in descending value order, subtractive pairs included. */\nconst ROMAN_SYMBOLS: ReadonlyArray<readonly [number, string]> = [\n [1000, \"m\"], [900, \"cm\"], [500, \"d\"], [400, \"cd\"],\n [100, \"c\"], [90, \"xc\"], [50, \"l\"], [40, \"xl\"],\n [10, \"x\"], [9, \"ix\"], [5, \"v\"], [4, \"iv\"],\n [1, \"i\"],\n];\n\n/**\n * Counts `n` in bijective base-N over `alphabet` — the \"alphabetic\" system CSS\n * counter styles use, where the value after the last letter is `aa`, not a wrap.\n *\n * @param n - The one-based item number to convert.\n * @param alphabet - The symbols to count over, in order.\n *\n * @returns The alphabetic representation of `n`.\n */\nfunction alphabetic(n: number, alphabet: string): string {\n const base = alphabet.length;\n let out = \"\";\n let rest = n;\n\n while (rest > 0) {\n rest -= 1;\n out = alphabet[rest % base] + out;\n rest = Math.floor(rest / base);\n }\n\n return out;\n}\n\n/**\n * Converts `n` to lowercase roman numerals, falling back to decimal past ROMAN_MAX.\n *\n * @param n - The one-based item number to convert.\n *\n * @returns The roman numeral for `n`, or its decimal form when `n` exceeds the\n * range CSS gives the predefined roman counter styles.\n */\nfunction roman(n: number): string {\n if (n > ROMAN_MAX) {\n return String(n);\n }\n\n let out = \"\";\n let rest = n;\n\n for (const [value, symbol] of ROMAN_SYMBOLS) {\n while (rest >= value) {\n out += symbol;\n rest -= value;\n }\n }\n\n return out;\n}\n\n/** Every numbering style except NONE, which the caller short-circuits. */\ntype CountingStyle = Exclude<NumberedListItemStyle, NumberedListItemStyle.NONE>;\n\n/**\n * The number-to-string conversion for each counting style. Typing the record\n * over CountingStyle rather than the whole enum makes it exhaustive: adding an\n * enum member becomes a compile error rather than a silent undefined lookup.\n */\nconst NUMBER_FORMATTERS: Record<CountingStyle, (n: number) => string> = {\n [NumberedListItemStyle.DECIMAL]: n => String(n),\n [NumberedListItemStyle.DECIMAL_LEADING_ZERO]: n => String(n).padStart(DECIMAL_MIN_DIGITS, \"0\"),\n [NumberedListItemStyle.LOWER_ALPHA]: n => alphabetic(n, LOWER_LATIN_LETTERS),\n [NumberedListItemStyle.LOWER_LATIN]: n => alphabetic(n, LOWER_LATIN_LETTERS),\n [NumberedListItemStyle.UPPER_ALPHA]: n => alphabetic(n, LOWER_LATIN_LETTERS).toUpperCase(),\n [NumberedListItemStyle.UPPER_LATIN]: n => alphabetic(n, LOWER_LATIN_LETTERS).toUpperCase(),\n [NumberedListItemStyle.LOWER_GREEK]: n => alphabetic(n, LOWER_GREEK_LETTERS),\n [NumberedListItemStyle.UPPER_GREEK]: n => alphabetic(n, LOWER_GREEK_LETTERS).toUpperCase(),\n [NumberedListItemStyle.LOWER_ROMAN]: n => roman(n),\n [NumberedListItemStyle.UPPER_ROMAN]: n => roman(n).toUpperCase(),\n};\n\n/**\n * An ordered (numbered) list component.\n *\n * Renders an `<ol>` element and defaults to the DECIMAL numbering style. Every\n * member of\n * [`NumberedListItemStyle`](/api/component/list/enumerations/NumberedListItemStyle)\n * renders; `lower-alpha` / `lower-latin` are aliases of one another, as are the\n * upper pair, and the roman styles fall back to decimal above item 3999, which\n * is the range CSS gives them.\n *\n * @category Components\n */\nclass NumberedList extends AbstractMarkerList<NumberedListItemStyle> {\n\n constructor(options?: NumberedListOptions) {\n super(\"ol\", NumberedListItemStyle.DECIMAL, options);\n }\n\n /**\n * Returns the marker for the item at `index` under the current style.\n *\n * @param index - The item's zero-based position in the list.\n *\n * @returns `\"\"` under the NONE style, otherwise the one-based position\n * converted by the current style and followed by a full stop.\n */\n protected markerText(index: number): string {\n const style = this.getStyle()!;\n\n if (style === NumberedListItemStyle.NONE) {\n return \"\";\n }\n\n return NUMBER_FORMATTERS[style](index + 1) + \".\";\n }\n}\n\nconst NumberedListCallable = callable(NumberedList);\ntype NumberedListCallable = NumberedList;\nexport {\n NumberedList as _NumberedList,\n NumberedListCallable as NumberedList\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { HBox } from \"~/layout/HBox.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Construction-time options for {@link ListItem}.\n *\n * @category Components\n */\nexport interface ListItemOptions extends ComponentOptions {\n text?: string;\n}\n\n/**\n * Pixels between the marker slot and the label — roughly one space at the\n * framework's default font size, which is what makes the two read as separate\n * runs rather than one word. Structural separation between two content slots,\n * the same role `IconText`'s `gap` plays.\n */\nconst MARKER_GAP_PX = 4;\n\n/**\n * Class-level defaults. Only `tag` is a genuine class default; the\n * positional `value` is a per-instance value resolved in the constructor\n * body, not smuggled through this bag.\n */\nconst _defaultListItemOptions: Partial<ListItemOptions> = {\n tag: \"li\",\n};\n\n/**\n * A single list item component backed by a `<li>` element.\n *\n * Pairs a marker slot with a label, laid out horizontally. The marker is a real\n * child component rather than the browser's own `::marker`, so the framework\n * measures and positions it like any other content. Its owning list writes the\n * marker string and rewrites every item's whenever the children change; an item\n * never markers itself.\n *\n * @category Components\n */\nclass ListItem extends Component<ListItemOptions> {\n\n private _key: string;\n private _marker!: Text;\n private _text!: Text;\n\n /**\n * @param key - The item's stable key.\n * @param value - The item's label text.\n * @param options - Optional construction-time options.\n * @param subclassDefaults - Per-subclass default bag layered over this\n * class's defaults; subclasses forward their `_defaultXxxOptions`\n * constant here.\n */\n constructor(\n key: string,\n value: string,\n options?: ListItemOptions,\n subclassDefaults?: Partial<ListItemOptions>,\n ) {\n // The HBox sits in the defaults bag (under user options) so a caller\n // that wants a different layoutManager can still override it, and is\n // built per instance because a layout manager holds container state.\n super(options, {\n ..._defaultListItemOptions,\n layoutManager: new HBox({ spacing: MARKER_GAP_PX }),\n ...(subclassDefaults ?? {}),\n });\n\n this._key = key;\n\n // The marker sits in a slot shared with every other item in the list,\n // widened to the widest marker among them, so it hugs the slot's right\n // edge and the trailing full stops line up down the list.\n this._marker = new Text(undefined, { textAlign: \"right\" });\n this._text = new Text();\n\n this.addComponent(this._marker);\n // The label absorbs whatever width the marker leaves.\n this.addComponent(this._text, { weight: 1 });\n\n // The marker duplicates what a screen reader already announces from the\n // item's position in the list, so it is hidden from the accessibility\n // tree while the list and item carry explicit list semantics.\n this._marker.getAria().setHidden(true);\n this.getAria().setRole(\"listitem\");\n\n // Late-built state: the text setter reaches into a child that did not\n // exist during super's cascade, so dispatch from `_options` now. An\n // explicit `text` option wins over the positional value.\n this.setText(this._options.text ?? value);\n this.setMarker(\"\");\n }\n\n /**\n * Applies a {@link ListItemOptions} bag. Inherited Component fields cascade\n * through `super.applyOptions`; `text` is written pure to `_options` here\n * and dispatched from the constructor body once the label exists.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: ListItemOptions): this {\n super.applyOptions(options);\n\n if (options.text !== undefined) this._options.text = options.text;\n\n return this;\n }\n\n /**\n * Returns the data-key identifier for this list item.\n *\n * @returns The key string.\n */\n getKey() {\n return this._key;\n }\n\n /**\n * Returns the item's label text.\n *\n * @returns The label string.\n */\n getText(): string {\n return this._text.getText().valueOf();\n }\n\n /**\n * Updates the item's label text.\n *\n * @param text - The new label string.\n *\n * @returns This component, for method chaining.\n */\n setText(text: string): this {\n this._text.setText(text);\n\n return this;\n }\n\n /**\n * Returns the marker string the owning list wrote.\n *\n * @returns The marker string, or `\"\"` when this item has no marker.\n */\n getMarker(): string {\n return this._marker.getText().valueOf();\n }\n\n /**\n * Sets the marker string. Called by the owning list, which owns numbering\n * and bullet selection; an empty string hides the marker slot entirely.\n *\n * @param text - The marker string, or `\"\"` for no marker.\n *\n * @returns This component, for method chaining.\n */\n setMarker(text: string): this {\n this._marker.setText(text);\n // Box layouts iterate the displayed children, so hiding the slot drops\n // both its width and the gap that would follow it.\n this._marker.setDisplayed(text.length > 0);\n\n return this;\n }\n\n /**\n * Returns the marker's own measured width, before any shared column widens it.\n *\n * @returns The measured width in pixels, or 0 when nothing has been measured.\n *\n * @remarks Called by the owning list to size its shared marker column.\n */\n getMarkerWidth(): number {\n // Force the lazy measurement, then read the raw measured width back off\n // the preferred-size constraint. getPreferredSize() would floor the\n // width at the shared column this item already carries, which would\n // ratchet the column wider on every pass and never let it shrink.\n this._marker.getPreferredSize();\n\n return this._marker.getPreferredSizeConstraint()?.width ?? 0;\n }\n\n /**\n * Widens the marker slot to the owning list's shared column width.\n *\n * @param width - The shared column width in pixels.\n *\n * @returns This component, for method chaining.\n */\n setMarkerColumnWidth(width: number): this {\n // A minimum, not a preferred size: Text republishes its own measurement\n // through setPreferredSize, and pinning one would freeze the measurement\n // this list has to read back.\n this._marker.setMinSize({ width: width, height: 0 });\n\n return this;\n }\n\n /**\n * Renders the li element and sets its data-key attribute.\n *\n * @returns The created HTMLElement (`<li>`) with data-key set. The label\n * text is written by the child `Text`, not here.\n */\n protected render() {\n let element = super.render();\n\n DOM.sink.apply(element, { dataset: { key: this._key } });\n\n return element;\n }\n}\n\nconst ListItemCallable = callable(ListItem);\ntype ListItemCallable = ListItem;\nexport {\n ListItem as _ListItem,\n ListItemCallable as ListItem\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { ListItemRenderer } from \"~/component/list/ListItemRenderer.js\";\nimport { ListItemRenderContext } from \"~/component/list/ListItemRenderContext.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Pixel width reserved for the icon column (icon plus a small gap before the\n * label). Mirrors the tree icon-label renderer so a glyph list row and a glyph\n * tree row share the same icon gutter.\n */\nconst ICON_WIDTH = 20;\n\n/** Square edge length used for the icon glyph, matching the tree renderer. */\nconst ICON_SIZE = 16;\n\n/**\n * A [`ListItemRenderer`](/api/component/list/classes/ListItemRenderer) that\n * paints an icon before the item label, sourcing the icon from each item's\n * `glyph` field.\n *\n * @remarks\n * The glyph name comes from the bound item (`SelectableListItem.glyph`), populated\n * either directly on an array-supplied item or from a store record via the\n * list's `glyphField`. An item with no glyph renders label-only, with the label\n * filling the full row — matching the render-blank-on-empty contract of the\n * table glyph cell renderer. Because [`Glyph`](/api/component/display/classes/Glyph)\n * names are immutable, a fresh `Glyph` is constructed whenever the bound name\n * changes, matching the pattern `TreeRow` uses for its toggle.\n *\n * Register the glyphs the items reference before use, exactly as the table\n * glyph cell renderer requires:\n *\n * @example\n * ```typescript\n * import { star } from \"~/glyphs/solid/star.js\";\n *\n * Glyph.register(star);\n * list.setRendererFactory(() => new GlyphListItemRenderer());\n * list.setItems([{ key: \"a\", label: \"Alpha\", glyph: \"star\" }]);\n * ```\n *\n * @category Components\n */\nclass GlyphListItemRenderer extends ListItemRenderer {\n\n private _icon: Glyph | null = null;\n private _label: Text;\n private _currentGlyph: string | null = null;\n /**\n * Whether `_label`'s cached natural width matches the bound text. The label\n * runs with `autoMeasure(false)`, so the measure is driven from\n * {@link getContentWidth} rather than {@link update} — a list with\n * horizontal scrolling off never asks, and so never pays for it.\n */\n private _measured: boolean = false;\n\n /**\n * Constructs a glyph+label renderer with an empty label and no icon. Both\n * are populated on the first {@link update} call.\n */\n constructor() {\n super();\n this.clearInsets();\n\n this._label = new Text();\n this._label.clearInsets();\n this._label.setAutoMeasure(false);\n }\n\n /**\n * Rebinds the icon (constructing a new Glyph when the item's glyph name\n * changed, removing it when the item has none) and the label text.\n *\n * @param context - The bound-item state for this render pass.\n */\n update(context: ListItemRenderContext): void {\n const next = context.item.glyph ? context.item.glyph : null;\n\n if (next !== this._currentGlyph) {\n const el = this.getElement();\n\n if (el && this._icon) {\n const oldEl = this._icon.getElement();\n if (oldEl && DOM.source.getParentNode(oldEl) === el) {\n DOM.sink.removeChild(el, oldEl);\n }\n }\n\n this._icon = null;\n this._currentGlyph = next;\n\n if (next !== null) {\n this._icon = new Glyph(next);\n this._icon.clearInsets();\n this._icon.setPointerEvents(\"none\");\n\n if (el) {\n DOM.sink.insertBefore(el, this._icon.getElement(true)!, this._label.getElement() ?? null);\n }\n }\n }\n\n this._label.setText(context.item.label);\n this._measured = false;\n }\n\n /**\n * Returns the natural width of the bound content — the icon gutter, when an\n * icon is bound, plus the label's natural width (measured on first ask\n * after each {@link update}). Mirrors {@link layoutChildren}'s geometry, so\n * a row sized to this width fits the icon and the whole label.\n *\n * @returns The bound content's natural width in pixels.\n */\n getContentWidth(): number {\n if (!this._measured) {\n this._label.measure();\n this._measured = true;\n }\n\n const labelWidth = this._label.getPreferredSize()?.width ?? 0;\n\n return (this._icon ? ICON_WIDTH : 0) + labelWidth;\n }\n\n /**\n * Positions the icon (vertically centred in the row) and the label. When no\n * icon is bound the label fills the full width from the left edge.\n *\n * Both go inside this renderer's content box, so a border or padding on the\n * renderer shrinks them rather than being painted over.\n *\n * @param width - The horizontal extent of the row in pixels. Used only\n * while the renderer has no element yet and the content box is\n * unavailable.\n * @param height - The vertical extent of the row in pixels, used under the\n * same condition as `width`.\n */\n layoutChildren(width: number, height: number): void {\n const box = this.getContentBounds() ?? { x: 0, y: 0, width, height };\n\n if (this._icon) {\n this._icon.setAutoCommitStyle(false);\n this._icon.setX(box.x);\n this._icon.setY(box.y + Math.max(0, (box.height - ICON_SIZE) / 2));\n this._icon.setWidth(ICON_SIZE);\n this._icon.setHeight(ICON_SIZE);\n this._icon.setAutoCommitStyle(true);\n }\n\n const labelX = box.x + (this._icon ? ICON_WIDTH : 0);\n const labelWidth = Math.max(0, box.x + box.width - labelX);\n\n this._label.setAutoCommitStyle(false);\n this._label.setX(labelX);\n this._label.setY(box.y);\n this._label.setWidth(labelWidth);\n this._label.setHeight(box.height);\n this._label.setLineHeight(box.height);\n this._label.setAutoCommitStyle(true);\n }\n\n /**\n * Appends the label sub-component element (and the icon, when one is\n * already bound) to the renderer's DOM element. Later icon changes are\n * inserted before the label by {@link update}.\n *\n * @param element - Optional element passed by the rendering pipeline; falls\n * back to getElement().\n *\n * @returns This renderer, for method chaining.\n */\n protected init(element?: Handle): this {\n super.init(element);\n\n const el = element || this.getElement();\n if (!el) {\n return this;\n }\n\n if (this._icon) {\n DOM.sink.appendChild(el, this._icon.getElement(true)!);\n }\n\n DOM.sink.appendChild(el, this._label.getElement(true)!);\n\n return this;\n }\n}\n\nconst GlyphListItemRendererCallable = callable(GlyphListItemRenderer);\ntype GlyphListItemRendererCallable = GlyphListItemRenderer;\nexport {\n GlyphListItemRenderer as _GlyphListItemRenderer,\n GlyphListItemRendererCallable as GlyphListItemRenderer,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"list.es.js","names":[],"sources":["../../../src/typescript/lib/component/list/MultiSelectList.ts","../../../src/typescript/lib/component/list/AbstractMarkerList.ts","../../../src/typescript/lib/component/list/BulletedListItemStyle.ts","../../../src/typescript/lib/component/list/BulletedList.ts","../../../src/typescript/lib/component/list/NumberedListItemStyle.ts","../../../src/typescript/lib/component/list/NumberedList.ts","../../../src/typescript/lib/component/list/ListItem.ts","../../../src/typescript/lib/component/list/renderer/Glyph.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractSelectableList, AbstractSelectableListOptions } from \"~/component/list/AbstractSelectableList.js\";\nimport { ModelRecord } from \"~/data/ModelRecord.js\";\nimport { reduceModifierSelection } from \"~/component/shared/reduceModifierSelection.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { Event } from \"~/core/Event.js\";\n\n/**\n * Construction-time options for {@link MultiSelectList}.\n *\n * @category Components\n */\nexport interface MultiSelectListOptions extends AbstractSelectableListOptions {\n selectedIndices?: number[];\n}\n\n/**\n * A scrollable multi-selection list box.\n *\n * Rendered as a `<div role=\"listbox\" aria-multiselectable=\"true\">`\n * populated with `<div role=\"option\">` rows. Implements\n * [`Bindable<string[]>`](/api/core/interfaces/Bindable) so it can be\n * plugged into a [`Binding`](/api/core/classes/Binding) directly — earlier\n * versions required explicit `BindingAccessors` because the single-value\n * `Bindable<string>` contract didn't fit. Selection follows the\n * standard modifier-key model:\n *\n * - Plain click / Enter / Space replaces the selection with the\n * clicked row.\n * - Ctrl-click (Cmd on macOS) / Ctrl+Space toggles the clicked row's\n * selection.\n * - Shift-click / Shift+Arrow extends the selection from the anchor\n * row to the targeted row.\n *\n * @category Components\n */\nclass MultiSelectList extends AbstractSelectableList<string[], MultiSelectListOptions> {\n\n /**\n * @param options - Optional. Construction-time options applied to\n * the list.\n */\n constructor(options?: MultiSelectListOptions) {\n super(options);\n\n this.getAria().setMultiselectable(true);\n\n // Late-built state: `selectedIndices` was written pure to\n // `_options` by the super-time cascade. Dispatch it now that the\n // row pool exists (`super()` already populated `_items` from\n // `items` / `store`, and applied `enabled` / `readOnly`).\n if (this._options.selectedIndices !== undefined) {\n this.applyInitialSelection(this._options.selectedIndices);\n }\n }\n\n /**\n * Applies a {@link MultiSelectListOptions} bag. Multi-select state\n * fields are written pure into `_options` here and dispatched from the\n * constructor body after the row pool is built.\n *\n * @param options - The options bag carrying the values to apply.\n *\n * @returns This component, for method chaining.\n */\n protected applyOptions(options: MultiSelectListOptions): this {\n super.applyOptions(options);\n\n if (options.selectedIndices !== undefined) this._options.selectedIndices = options.selectedIndices;\n\n return this;\n }\n\n /**\n * Replaces the selection with the rows whose keys appear in\n * `values`. Programmatic — does not fire the `change` event; user-\n * driven gestures route through the click / keyboard reducer\n * instead.\n *\n * @param values - The row keys to select.\n *\n * @returns This component, for method chaining.\n */\n setValues(values: string[]): this {\n const valueSet = new Set(values);\n\n this._selectedSet.clear();\n\n for (let i = 0; i < this._items.length; i++) {\n if (valueSet.has(this._items[i].key)) {\n this._selectedSet.add(i);\n }\n }\n\n // Park the anchor at the last selected index when there is one,\n // so a follow-up Shift-arrow extends from a sensible position.\n if (this._selectedSet.size > 0) {\n this._anchorIndex = Math.max(...this._selectedSet);\n } else {\n this._anchorIndex = null;\n }\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n\n return this;\n }\n\n /**\n * `Bindable<string[]>` write-side — alias of {@link setValues}.\n *\n * @param value - The row keys to select.\n *\n * @returns This component, for method chaining.\n */\n setValue(value: string[]): this {\n return this.setValues(value);\n }\n\n /**\n * Returns the keys of every currently selected row, sorted by row\n * order. Satisfies the `Bindable<string[]>` read-side.\n *\n * @returns The selected row keys.\n */\n getValue(): string[] {\n const indices = [...this._selectedSet].sort((a, b) => a - b);\n\n return indices.map(i => this._items[i].key);\n }\n\n /**\n * Returns the store records that correspond to the currently\n * selected rows.\n *\n * @returns The selected [`ModelRecord`](/api/data/classes/ModelRecord)\n * instances in row order, or an empty array when no store is bound.\n */\n getSelectedRecords(): ModelRecord[] {\n const store = this.getStore();\n\n if (!store) {\n return [];\n }\n\n const records = store.getRecords();\n const indices = [...this._selectedSet].sort((a, b) => a - b);\n const result: ModelRecord[] = [];\n\n for (const i of indices) {\n if (i < records.length) {\n result.push(records[i]);\n }\n }\n\n return result;\n }\n\n /**\n * Replaces the selection with the rows whose backing records appear\n * in `records`. Relies on the parallel ordering of `_items` and\n * `store.getRecords()` that the store-bound refresh guarantees — see\n * [`setStore`](/api/component/list/classes/MultiSelectList#setstore).\n *\n * @param records - The store records to select.\n *\n * @returns This component, for method chaining.\n */\n setSelectedRecords(records: ModelRecord[]): this {\n const store = this.getStore();\n\n if (!store) {\n return this;\n }\n\n const recordSet = new Set(records);\n const storeRecords = store.getRecords();\n const values: string[] = [];\n\n for (let i = 0; i < this._items.length && i < storeRecords.length; i++) {\n if (recordSet.has(storeRecords[i])) {\n values.push(this._items[i].key);\n }\n }\n\n return this.setValues(values);\n }\n\n /**\n * Reduces a click / keyboard gesture into the multi-select shape.\n * Ported verbatim from [`Body.onRowClick`](/api/component/table/classes/Body) — the same modifier\n * rules apply: plain replaces, `ctrl` toggles individual rows,\n * `shift` extends the selection from the anchor row to `idx`.\n *\n * @param idx - The row index the gesture targeted.\n * @param ev - The normalised modifier flags.\n */\n protected reduceSelection(idx: number, ev: { ctrl: boolean, shift: boolean }): void {\n this._anchorIndex = reduceModifierSelection(\n this._selectedSet,\n this._anchorIndex,\n idx,\n i => i,\n i => i,\n ev,\n );\n\n this._focusedIndex = idx;\n }\n\n /**\n * User-driven selection commit. Fires the `change` event the same\n * way the prior native `<select multiple>` did — only user-driven\n * gestures (click / keyboard reducer) route through it.\n */\n protected notifyUserChange(): void {\n this.fireChange();\n }\n\n /**\n * Extends the base keyboard map with `Ctrl+A` (select-all) — every\n * other key delegates to {@link AbstractSelectableList.handleKeyDown}.\n *\n * @param e - The keyboard event.\n */\n protected handleKeyDown(e: KeyboardEvent): Event.ListenerResult {\n if (!this.isEnabled() || this.isReadOnly()) {\n return;\n }\n\n const ctrl = e.ctrlKey || e.metaKey;\n\n if (ctrl && (e.key === \"a\" || e.key === \"A\")) {\n this.selectAll();\n\n return { prevent: true };\n }\n\n return super.handleKeyDown(e);\n }\n\n /**\n * Selects every row in the list. Used by the Ctrl+A keyboard shortcut.\n */\n protected selectAll(): void {\n if (this._items.length === 0) {\n return;\n }\n\n this._selectedSet.clear();\n\n for (let i = 0; i < this._items.length; i++) {\n this._selectedSet.add(i);\n }\n\n this._anchorIndex = 0;\n this._focusedIndex = this._items.length - 1;\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n this.notifyUserChange();\n }\n\n /**\n * Construction-tail dispatch of `selectedIndices`. Writes the\n * indices directly into the selection set without firing `change`,\n * matching the construct-time semantics of `setValues` (programmatic\n * writes are silent; user gestures emit `change`).\n *\n * @param indices - Initial selection indices from the options bag.\n */\n private applyInitialSelection(indices: number[]): void {\n this._selectedSet.clear();\n\n for (const i of indices) {\n if (i >= 0 && i < this._items.length) {\n this._selectedSet.add(i);\n }\n }\n\n if (this._selectedSet.size > 0) {\n this._anchorIndex = Math.max(...this._selectedSet);\n }\n\n this.refreshRowVisualState();\n this.updateActiveDescendant();\n }\n}\n\nconst MultiSelectListCallable = callable(MultiSelectList);\ntype MultiSelectListCallable = MultiSelectList;\nexport {\n MultiSelectList as _MultiSelectList,\n MultiSelectListCallable as MultiSelectList,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Comparator, Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { VBox } from \"~/layout/VBox.js\";\nimport { LayoutConstraints } from \"~/layout/LayoutConstraints.js\";\nimport { BulletedListItemStyle } from \"~/component/list/BulletedListItemStyle.js\";\nimport { NumberedListItemStyle } from \"~/component/list/NumberedListItemStyle.js\";\nimport { ListItem } from \"~/component/list/ListItem.js\";\n\n/**\n * Construction-time options for {@link AbstractMarkerList}.\n *\n * @category Components\n */\nexport interface AbstractMarkerListOptions<U extends BulletedListItemStyle | NumberedListItemStyle> extends ComponentOptions {\n itemStyle?: U;\n}\n\n/**\n * Abstract base for bulleted and numbered list components.\n *\n * Owns each item's marker string — the bullet or number — and rewrites every\n * one whenever the children or the style change; the browser's own marker is\n * suppressed. Restricts child components to ListItem instances. Items are\n * stacked vertically by a [`VBox`](/api/layout/classes/VBox), and the list sizes\n * itself to them. Concrete subclasses supply the HTML tag, the default style,\n * and the marker string for a given position.\n *\n * Also owns the shared marker column: each layout pass measures every item's\n * marker and widens all of them to the widest, so markers share a right edge\n * and labels share a left one however much their widths differ.\n */\nexport abstract class AbstractMarkerList<U extends BulletedListItemStyle | NumberedListItemStyle> extends Component<AbstractMarkerListOptions<U>> {\n\n // `declare` rather than initializer to dodge the class-field\n // super-cascade trap: the cascade-time setStyle write would otherwise\n // be clobbered by a `= undefined` initializer running after super().\n // The cascade always dispatches setStyle because the constructor seeds\n // `itemStyle: style` into the defaults bag below.\n declare private _style: U | undefined;\n\n // Framework-managed derived state: recomputed from the items on every\n // layout pass, so it gets no setter and no options field. A plain\n // initializer is safe because no cascade-dispatched setter writes it.\n private _markerColumnWidth: number = 0;\n\n constructor(\n tag: string,\n style: U,\n options?: AbstractMarkerListOptions<U>,\n subclassDefaults?: Partial<AbstractMarkerListOptions<U>>,\n ) {\n super(options, {\n tag,\n // The left padding indents every item. The marker is drawn inside\n // the item's own box, not in this band — see ListItem.\n padding: new Insets(0, 0, 0, 25),\n layoutManager: new VBox({ spacing: 0, stretching: true }),\n itemStyle: style,\n ...(subclassDefaults ?? {}),\n } as Partial<AbstractMarkerListOptions<U>>);\n\n // Each item paints its own marker, so the browser must not paint a\n // second one beside it.\n this.setElementCSSRule(\"listStyleType\", \"none\");\n this.getAria().setRole(\"list\");\n }\n\n /**\n * Applies an {@link AbstractMarkerListOptions} bag, dispatching the list\n * marker style after inherited Component fields.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: AbstractMarkerListOptions<U>): this {\n super.applyOptions(options);\n\n // `itemStyle` is always defaulted (the constructor seeds the required\n // `style` param into `_defaultOptions`), so always dispatch the caller\n // value or the class default — this seeds the `declare`d `_style` field\n // without touching `_options`.\n this.setStyle(options.itemStyle ?? this.getStyle()!);\n\n return this;\n }\n\n /**\n * Returns the current marker style.\n *\n * @returns The current style enum value, or undefined if not yet set.\n */\n getStyle() {\n return this._style ?? this._defaultOptions.itemStyle;\n }\n\n /**\n * Sets the marker style and rewrites every item's marker to match.\n *\n * @param style - The list item style enum value to apply.\n */\n setStyle(style: U) : this {\n this._style = style;\n this.renumber();\n\n return this;\n }\n\n /**\n * Returns the width every item's marker slot is currently widened to.\n *\n * @returns The shared marker column width in pixels; 0 before the first\n * layout, and 0 for a list whose style shows no marker.\n */\n getMarkerColumnWidth(): number {\n return this._markerColumnWidth;\n }\n\n /**\n * Recomputes the shared marker column, then lays the items out.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n // The pause check is duplicated from Component.doLayout on purpose:\n // without it a paused list would still measure and write minimum sizes,\n // and each write would schedule a layout on its parent.\n if (this.isLayoutPaused()) {\n return this;\n }\n\n this.syncMarkerColumn();\n\n return super.doLayout();\n }\n\n /**\n * Measures every item's marker and pushes the widest width onto all of them,\n * so each item's label starts at the same offset.\n *\n * @remarks Walks every child rather than only the displayed ones, for the\n * same reason the renumbering pass does — hiding the item that carries the\n * widest marker would otherwise shift every remaining label sideways on the\n * next unrelated layout.\n */\n protected syncMarkerColumn(): void {\n const items = this.getComponents() as ListItem[];\n let width = 0;\n\n for (const item of items) {\n width = Math.max(width, item.getMarkerWidth());\n }\n\n this._markerColumnWidth = width;\n\n for (const item of items) {\n item.setMarkerColumnWidth(width);\n }\n }\n\n /**\n * Returns the marker string for the child at `index` under the current\n * style. Implemented by each concrete list.\n *\n * @param index - The child's zero-based position in the list.\n *\n * @returns The marker string, or `\"\"` when the style shows no marker.\n */\n protected abstract markerText(index: number): string;\n\n /**\n * Rewrites every child's marker from its current position. A no-op while\n * the list is empty, which is what makes the construction-time style\n * dispatch harmless.\n *\n * @remarks Walks every child rather than only the displayed ones, so a\n * hidden item still consumes its number — nothing notifies a list when a\n * child's displayed flag flips, so position-dependent markers would\n * otherwise go stale the moment a consumer hid an item.\n */\n protected renumber(): void {\n const items = this.getComponents() as ListItem[];\n\n for (let i = 0; i < items.length; i++) {\n items[i].setMarker(this.markerText(i));\n }\n }\n\n /**\n * Adds a ListItem child; restricts the type accepted by this container to ListItem.\n *\n * @param component - The ListItem to add.\n * @param constraints - Optional. Layout constraints for the item.\n */\n addComponent(component: ListItem, constraints?: LayoutConstraints): this {\n super.addComponent(component, constraints);\n\n return this;\n }\n\n /**\n * Inserts a ListItem child at `index` and renumbers the list.\n *\n * @param component - The ListItem to insert.\n * @param index - The position to insert at.\n * @param constraints - Optional. Layout constraints for the item.\n */\n insertComponent(component: ListItem, index: number, constraints?: LayoutConstraints): this {\n super.insertComponent(component, index, constraints);\n this.renumber();\n\n return this;\n }\n\n /**\n * Removes a ListItem child and renumbers the survivors.\n *\n * @param component - The ListItem instance to remove.\n *\n * @returns The layout constraints that were registered for the removed item, or undefined.\n */\n removeComponent(component: ListItem) {\n const constraints = super.removeComponent(component);\n\n this.renumber();\n\n return constraints;\n }\n\n /**\n * Reorders the items and renumbers them in the new order.\n *\n * @param comparator - The comparator to sort the items by.\n *\n * @remarks `sortComponents` is the only reorder path that does not express\n * itself through insert/remove, so it needs its own hook.\n */\n sortComponents(comparator: Comparator<Component, Component> | undefined): this {\n super.sortComponents(comparator);\n this.renumber();\n\n return this;\n }\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * CSS list-style-type values for bulleted (unordered) lists.\n *\n * @category Components\n */\nexport enum BulletedListItemStyle {\n NONE = \"none\",\n DISC = \"disc\",\n CIRCLE = \"circle\",\n SQUARE = \"square\"\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractMarkerList, AbstractMarkerListOptions } from \"~/component/list/AbstractMarkerList.js\";\nimport { BulletedListItemStyle } from \"~/component/list/BulletedListItemStyle.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link BulletedList}.\n *\n * @category Components\n */\nexport interface BulletedListOptions extends AbstractMarkerListOptions<BulletedListItemStyle> {\n}\n\n/** The character each bullet style paints, keyed by style. */\nconst BULLET_MARKERS: Record<BulletedListItemStyle, string> = {\n [BulletedListItemStyle.NONE]: \"\",\n [BulletedListItemStyle.DISC]: \"•\", // • BULLET\n [BulletedListItemStyle.CIRCLE]: \"◦\", // ◦ WHITE BULLET\n [BulletedListItemStyle.SQUARE]: \"▪\", // ▪ BLACK SMALL SQUARE\n};\n\n/**\n * An unordered (bulleted) list component.\n *\n * Renders a `<ul>` element and defaults to the DISC bullet style. Every\n * [`BulletedListItemStyle`](/api/component/list/enumerations/BulletedListItemStyle)\n * member renders; `NONE` collapses the marker slot away entirely.\n *\n * @category Components\n */\nclass BulletedList extends AbstractMarkerList<BulletedListItemStyle> {\n\n constructor(options?: BulletedListOptions) {\n super(\"ul\", BulletedListItemStyle.DISC, options);\n }\n\n /**\n * Returns the bullet character for the current style. Every item in a\n * bulleted list carries the same marker, so the position is unused.\n *\n * @param _index - The item's position, which does not affect a bullet.\n *\n * @returns The bullet character, or `\"\"` under the NONE style.\n */\n protected markerText(_index: number): string {\n return BULLET_MARKERS[this.getStyle()!];\n }\n}\n\nconst BulletedListCallable = callable(BulletedList);\ntype BulletedListCallable = BulletedList;\nexport {\n BulletedList as _BulletedList,\n BulletedListCallable as BulletedList\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * CSS list-style-type values for numbered (ordered) lists.\n *\n * @category Components\n */\nexport enum NumberedListItemStyle {\n NONE = \"none\",\n DECIMAL = \"decimal\",\n DECIMAL_LEADING_ZERO = \"decimal-leading-zero\",\n LOWER_ALPHA = \"lower-alpha\",\n LOWER_GREEK = \"lower-greek\",\n LOWER_LATIN = \"lower-latin\",\n LOWER_ROMAN = \"lower-roman\",\n UPPER_ALPHA = \"upper-alpha\",\n UPPER_GREEK = \"upper-greek\",\n UPPER_LATIN = \"upper-latin\",\n UPPER_ROMAN = \"upper-roman\"\n}","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractMarkerList, AbstractMarkerListOptions } from \"~/component/list/AbstractMarkerList.js\";\nimport { NumberedListItemStyle } from \"~/component/list/NumberedListItemStyle.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link NumberedList}.\n *\n * @category Components\n */\nexport interface NumberedListOptions extends AbstractMarkerListOptions<NumberedListItemStyle> {\n}\n\n/** CSS `decimal-leading-zero` pads to a minimum of two digits and never truncates. */\nconst DECIMAL_MIN_DIGITS = 2;\n\n/**\n * The largest item number roman numerals cover. CSS Counter Styles gives\n * `lower-roman` / `upper-roman` the range 1–3999 and falls back to `decimal`\n * outside it; above 3999 the additive symbol set has no notation left.\n */\nconst ROMAN_MAX = 3999;\n\n/** Latin letters, in the order CSS's `lower-alpha` / `lower-latin` counts them. */\nconst LOWER_LATIN_LETTERS = \"abcdefghijklmnopqrstuvwxyz\";\n\n/** The 24 Greek letters CSS's `lower-greek` counts, with `σ` and no final sigma. */\nconst LOWER_GREEK_LETTERS = \"αβγδεζηθικλμνξοπρστυφχψω\";\n\n/** Roman symbols in descending value order, subtractive pairs included. */\nconst ROMAN_SYMBOLS: ReadonlyArray<readonly [number, string]> = [\n [1000, \"m\"], [900, \"cm\"], [500, \"d\"], [400, \"cd\"],\n [100, \"c\"], [90, \"xc\"], [50, \"l\"], [40, \"xl\"],\n [10, \"x\"], [9, \"ix\"], [5, \"v\"], [4, \"iv\"],\n [1, \"i\"],\n];\n\n/**\n * Counts `n` in bijective base-N over `alphabet` — the \"alphabetic\" system CSS\n * counter styles use, where the value after the last letter is `aa`, not a wrap.\n *\n * @param n - The one-based item number to convert.\n * @param alphabet - The symbols to count over, in order.\n *\n * @returns The alphabetic representation of `n`.\n */\nfunction alphabetic(n: number, alphabet: string): string {\n const base = alphabet.length;\n let out = \"\";\n let rest = n;\n\n while (rest > 0) {\n rest -= 1;\n out = alphabet[rest % base] + out;\n rest = Math.floor(rest / base);\n }\n\n return out;\n}\n\n/**\n * Converts `n` to lowercase roman numerals, falling back to decimal past ROMAN_MAX.\n *\n * @param n - The one-based item number to convert.\n *\n * @returns The roman numeral for `n`, or its decimal form when `n` exceeds the\n * range CSS gives the predefined roman counter styles.\n */\nfunction roman(n: number): string {\n if (n > ROMAN_MAX) {\n return String(n);\n }\n\n let out = \"\";\n let rest = n;\n\n for (const [value, symbol] of ROMAN_SYMBOLS) {\n while (rest >= value) {\n out += symbol;\n rest -= value;\n }\n }\n\n return out;\n}\n\n/** Every numbering style except NONE, which the caller short-circuits. */\ntype CountingStyle = Exclude<NumberedListItemStyle, NumberedListItemStyle.NONE>;\n\n/**\n * The number-to-string conversion for each counting style. Typing the record\n * over CountingStyle rather than the whole enum makes it exhaustive: adding an\n * enum member becomes a compile error rather than a silent undefined lookup.\n */\nconst NUMBER_FORMATTERS: Record<CountingStyle, (n: number) => string> = {\n [NumberedListItemStyle.DECIMAL]: n => String(n),\n [NumberedListItemStyle.DECIMAL_LEADING_ZERO]: n => String(n).padStart(DECIMAL_MIN_DIGITS, \"0\"),\n [NumberedListItemStyle.LOWER_ALPHA]: n => alphabetic(n, LOWER_LATIN_LETTERS),\n [NumberedListItemStyle.LOWER_LATIN]: n => alphabetic(n, LOWER_LATIN_LETTERS),\n [NumberedListItemStyle.UPPER_ALPHA]: n => alphabetic(n, LOWER_LATIN_LETTERS).toUpperCase(),\n [NumberedListItemStyle.UPPER_LATIN]: n => alphabetic(n, LOWER_LATIN_LETTERS).toUpperCase(),\n [NumberedListItemStyle.LOWER_GREEK]: n => alphabetic(n, LOWER_GREEK_LETTERS),\n [NumberedListItemStyle.UPPER_GREEK]: n => alphabetic(n, LOWER_GREEK_LETTERS).toUpperCase(),\n [NumberedListItemStyle.LOWER_ROMAN]: n => roman(n),\n [NumberedListItemStyle.UPPER_ROMAN]: n => roman(n).toUpperCase(),\n};\n\n/**\n * An ordered (numbered) list component.\n *\n * Renders an `<ol>` element and defaults to the DECIMAL numbering style. Every\n * member of\n * [`NumberedListItemStyle`](/api/component/list/enumerations/NumberedListItemStyle)\n * renders; `lower-alpha` / `lower-latin` are aliases of one another, as are the\n * upper pair, and the roman styles fall back to decimal above item 3999, which\n * is the range CSS gives them.\n *\n * @category Components\n */\nclass NumberedList extends AbstractMarkerList<NumberedListItemStyle> {\n\n constructor(options?: NumberedListOptions) {\n super(\"ol\", NumberedListItemStyle.DECIMAL, options);\n }\n\n /**\n * Returns the marker for the item at `index` under the current style.\n *\n * @param index - The item's zero-based position in the list.\n *\n * @returns `\"\"` under the NONE style, otherwise the one-based position\n * converted by the current style and followed by a full stop.\n */\n protected markerText(index: number): string {\n const style = this.getStyle()!;\n\n if (style === NumberedListItemStyle.NONE) {\n return \"\";\n }\n\n return NUMBER_FORMATTERS[style](index + 1) + \".\";\n }\n}\n\nconst NumberedListCallable = callable(NumberedList);\ntype NumberedListCallable = NumberedList;\nexport {\n NumberedList as _NumberedList,\n NumberedListCallable as NumberedList\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { HBox } from \"~/layout/HBox.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Construction-time options for {@link ListItem}.\n *\n * @category Components\n */\nexport interface ListItemOptions extends ComponentOptions {\n text?: string;\n}\n\n/**\n * Pixels between the marker slot and the label — roughly one space at the\n * framework's default font size, which is what makes the two read as separate\n * runs rather than one word. Structural separation between two content slots,\n * the same role `IconText`'s `gap` plays.\n */\nconst MARKER_GAP_PX = 4;\n\n/**\n * Class-level defaults. Only `tag` is a genuine class default; the\n * positional `value` is a per-instance value resolved in the constructor\n * body, not smuggled through this bag.\n */\nconst _defaultListItemOptions: Partial<ListItemOptions> = {\n tag: \"li\",\n};\n\n/**\n * A single list item component backed by a `<li>` element.\n *\n * Pairs a marker slot with a label, laid out horizontally. The marker is a real\n * child component rather than the browser's own `::marker`, so the framework\n * measures and positions it like any other content. Its owning list writes the\n * marker string and rewrites every item's whenever the children change; an item\n * never markers itself.\n *\n * @category Components\n */\nclass ListItem extends Component<ListItemOptions> {\n\n private _key: string;\n private _marker!: Text;\n private _text!: Text;\n\n /**\n * @param key - The item's stable key.\n * @param value - The item's label text.\n * @param options - Optional construction-time options.\n * @param subclassDefaults - Per-subclass default bag layered over this\n * class's defaults; subclasses forward their `_defaultXxxOptions`\n * constant here.\n */\n constructor(\n key: string,\n value: string,\n options?: ListItemOptions,\n subclassDefaults?: Partial<ListItemOptions>,\n ) {\n // The HBox sits in the defaults bag (under user options) so a caller\n // that wants a different layoutManager can still override it, and is\n // built per instance because a layout manager holds container state.\n super(options, {\n ..._defaultListItemOptions,\n layoutManager: new HBox({ spacing: MARKER_GAP_PX }),\n ...(subclassDefaults ?? {}),\n });\n\n this._key = key;\n\n // The marker sits in a slot shared with every other item in the list,\n // widened to the widest marker among them, so it hugs the slot's right\n // edge and the trailing full stops line up down the list.\n this._marker = new Text(undefined, { textAlign: \"right\" });\n this._text = new Text();\n\n this.addComponent(this._marker);\n // The label absorbs whatever width the marker leaves.\n this.addComponent(this._text, { weight: 1 });\n\n // The marker duplicates what a screen reader already announces from the\n // item's position in the list, so it is hidden from the accessibility\n // tree while the list and item carry explicit list semantics.\n this._marker.getAria().setHidden(true);\n this.getAria().setRole(\"listitem\");\n\n // Late-built state: the text setter reaches into a child that did not\n // exist during super's cascade, so dispatch from `_options` now. An\n // explicit `text` option wins over the positional value.\n this.setText(this._options.text ?? value);\n this.setMarker(\"\");\n }\n\n /**\n * Applies a {@link ListItemOptions} bag. Inherited Component fields cascade\n * through `super.applyOptions`; `text` is written pure to `_options` here\n * and dispatched from the constructor body once the label exists.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: ListItemOptions): this {\n super.applyOptions(options);\n\n if (options.text !== undefined) this._options.text = options.text;\n\n return this;\n }\n\n /**\n * Returns the data-key identifier for this list item.\n *\n * @returns The key string.\n */\n getKey() {\n return this._key;\n }\n\n /**\n * Returns the item's label text.\n *\n * @returns The label string.\n */\n getText(): string {\n return this._text.getText().valueOf();\n }\n\n /**\n * Updates the item's label text.\n *\n * @param text - The new label string.\n *\n * @returns This component, for method chaining.\n */\n setText(text: string): this {\n this._text.setText(text);\n\n return this;\n }\n\n /**\n * Returns the marker string the owning list wrote.\n *\n * @returns The marker string, or `\"\"` when this item has no marker.\n */\n getMarker(): string {\n return this._marker.getText().valueOf();\n }\n\n /**\n * Sets the marker string. Called by the owning list, which owns numbering\n * and bullet selection; an empty string hides the marker slot entirely.\n *\n * @param text - The marker string, or `\"\"` for no marker.\n *\n * @returns This component, for method chaining.\n */\n setMarker(text: string): this {\n this._marker.setText(text);\n // Box layouts iterate the displayed children, so hiding the slot drops\n // both its width and the gap that would follow it.\n this._marker.setDisplayed(text.length > 0);\n\n return this;\n }\n\n /**\n * Returns the marker's own measured width, before any shared column widens it.\n *\n * @returns The measured width in pixels, or 0 when nothing has been measured.\n *\n * @remarks Called by the owning list to size its shared marker column.\n */\n getMarkerWidth(): number {\n // Force the lazy measurement, then read the raw measured width back off\n // the preferred-size constraint. getPreferredSize() would floor the\n // width at the shared column this item already carries, which would\n // ratchet the column wider on every pass and never let it shrink.\n this._marker.getPreferredSize();\n\n return this._marker.getPreferredSizeConstraint()?.width ?? 0;\n }\n\n /**\n * Widens the marker slot to the owning list's shared column width.\n *\n * @param width - The shared column width in pixels.\n *\n * @returns This component, for method chaining.\n */\n setMarkerColumnWidth(width: number): this {\n // A minimum, not a preferred size: Text republishes its own measurement\n // through setPreferredSize, and pinning one would freeze the measurement\n // this list has to read back.\n this._marker.setMinSize({ width: width, height: 0 });\n\n return this;\n }\n\n /**\n * Renders the li element and sets its data-key attribute.\n *\n * @returns The created HTMLElement (`<li>`) with data-key set. The label\n * text is written by the child `Text`, not here.\n */\n protected render() {\n let element = super.render();\n\n DOM.sink.apply(element, { dataset: { key: this._key } });\n\n return element;\n }\n}\n\nconst ListItemCallable = callable(ListItem);\ntype ListItemCallable = ListItem;\nexport {\n ListItem as _ListItem,\n ListItemCallable as ListItem\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { ListItemRenderer } from \"~/component/list/ListItemRenderer.js\";\nimport { ListItemRenderContext } from \"~/component/list/ListItemRenderContext.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Pixel width reserved for the icon column (icon plus a small gap before the\n * label). Mirrors the tree icon-label renderer so a glyph list row and a glyph\n * tree row share the same icon gutter.\n */\nconst ICON_WIDTH = 20;\n\n/** Square edge length used for the icon glyph, matching the tree renderer. */\nconst ICON_SIZE = 16;\n\n/**\n * A [`ListItemRenderer`](/api/component/list/classes/ListItemRenderer) that\n * paints an icon before the item label, sourcing the icon from each item's\n * `glyph` field.\n *\n * @remarks\n * The glyph name comes from the bound item (`SelectableListItem.glyph`), populated\n * either directly on an array-supplied item or from a store record via the\n * list's `glyphField`. An item with no glyph renders label-only, with the label\n * filling the full row — matching the render-blank-on-empty contract of the\n * table glyph cell renderer. Because [`Glyph`](/api/component/display/classes/Glyph)\n * names are immutable, a fresh `Glyph` is constructed whenever the bound name\n * changes, matching the pattern `TreeRow` uses for its toggle.\n *\n * Register the glyphs the items reference before use, exactly as the table\n * glyph cell renderer requires:\n *\n * @example\n * ```typescript\n * import { star } from \"~/glyphs/solid/star.js\";\n *\n * Glyph.register(star);\n * list.setRendererFactory(() => new GlyphListItemRenderer());\n * list.setItems([{ key: \"a\", label: \"Alpha\", glyph: \"star\" }]);\n * ```\n *\n * @category Components\n */\nclass GlyphListItemRenderer extends ListItemRenderer {\n\n private _icon: Glyph | null = null;\n private _label: Text;\n private _currentGlyph: string | null = null;\n /**\n * Whether `_label`'s cached natural width matches the bound text. The label\n * runs with `autoMeasure(false)`, so the measure is driven from\n * {@link getContentWidth} rather than {@link update} — a list with\n * horizontal scrolling off never asks, and so never pays for it.\n */\n private _measured: boolean = false;\n\n /**\n * Constructs a glyph+label renderer with an empty label and no icon. Both\n * are populated on the first {@link update} call.\n */\n constructor() {\n super();\n this.clearInsets();\n\n this._label = new Text();\n this._label.clearInsets();\n this._label.setAutoMeasure(false);\n }\n\n /**\n * Rebinds the icon (constructing a new Glyph when the item's glyph name\n * changed, removing it when the item has none) and the label text.\n *\n * @param context - The bound-item state for this render pass.\n */\n update(context: ListItemRenderContext): void {\n const next = context.item.glyph ? context.item.glyph : null;\n\n if (next !== this._currentGlyph) {\n const el = this.getElement();\n\n if (el && this._icon) {\n const oldEl = this._icon.getElement();\n if (oldEl && DOM.source.getParentNode(oldEl) === el) {\n DOM.sink.removeChild(el, oldEl);\n }\n }\n\n this._icon = null;\n this._currentGlyph = next;\n\n if (next !== null) {\n this._icon = new Glyph(next);\n this._icon.clearInsets();\n this._icon.setPointerEvents(\"none\");\n\n if (el) {\n DOM.sink.insertBefore(el, this._icon.getElement(true)!, this._label.getElement() ?? null);\n }\n }\n }\n\n this._label.setText(context.item.label);\n this._measured = false;\n }\n\n /**\n * Returns the natural width of the bound content — the icon gutter, when an\n * icon is bound, plus the label's natural width (measured on first ask\n * after each {@link update}). Mirrors {@link layoutChildren}'s geometry, so\n * a row sized to this width fits the icon and the whole label.\n *\n * @returns The bound content's natural width in pixels.\n */\n getContentWidth(): number {\n if (!this._measured) {\n this._label.measure();\n this._measured = true;\n }\n\n const labelWidth = this._label.getPreferredSize()?.width ?? 0;\n\n return (this._icon ? ICON_WIDTH : 0) + labelWidth;\n }\n\n /**\n * Positions the icon (vertically centred in the row) and the label. When no\n * icon is bound the label fills the full width from the left edge.\n *\n * Both go inside this renderer's content box, so a border or padding on the\n * renderer shrinks them rather than being painted over.\n *\n * @param width - The horizontal extent of the row in pixels. Used only\n * while the renderer has no element yet and the content box is\n * unavailable.\n * @param height - The vertical extent of the row in pixels, used under the\n * same condition as `width`.\n */\n layoutChildren(width: number, height: number): void {\n const box = this.getContentBounds() ?? { x: 0, y: 0, width, height };\n\n if (this._icon) {\n this._icon.setAutoCommitStyle(false);\n this._icon.setX(box.x);\n this._icon.setY(box.y + Math.max(0, (box.height - ICON_SIZE) / 2));\n this._icon.setWidth(ICON_SIZE);\n this._icon.setHeight(ICON_SIZE);\n this._icon.setAutoCommitStyle(true);\n }\n\n const labelX = box.x + (this._icon ? ICON_WIDTH : 0);\n const labelWidth = Math.max(0, box.x + box.width - labelX);\n\n this._label.setAutoCommitStyle(false);\n this._label.setX(labelX);\n this._label.setY(box.y);\n this._label.setWidth(labelWidth);\n this._label.setHeight(box.height);\n this._label.setLineHeight(box.height);\n this._label.setAutoCommitStyle(true);\n }\n\n /**\n * Appends the label sub-component element (and the icon, when one is\n * already bound) to the renderer's DOM element. Later icon changes are\n * inserted before the label by {@link update}.\n *\n * @param element - Optional element passed by the rendering pipeline; falls\n * back to getElement().\n *\n * @returns This renderer, for method chaining.\n */\n protected init(element?: Handle): this {\n super.init(element);\n\n const el = element || this.getElement();\n if (!el) {\n return this;\n }\n\n if (this._icon) {\n DOM.sink.appendChild(el, this._icon.getElement(true)!);\n }\n\n DOM.sink.appendChild(el, this._label.getElement(true)!);\n\n return this;\n }\n}\n\nconst GlyphListItemRendererCallable = callable(GlyphListItemRenderer);\ntype GlyphListItemRendererCallable = GlyphListItemRenderer;\nexport {\n GlyphListItemRenderer as _GlyphListItemRenderer,\n GlyphListItemRendererCallable as GlyphListItemRenderer,\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"../DOM-
|
|
1
|
+
import{t as e}from"../DOM-C-Edb3tA.js";import{n as t}from"../Position-BwtxouxK.js";import{S as n,h as r,t as i}from"../Component-B0ShfPVi.js";import{t as a}from"../Container-abY5Ww3W.js";import{t as o}from"../Glyph-_VeBacS2.js";import{t as s}from"../RovingTabIndex-pHEv5oLD.js";import{a as c}from"../Tooltip-CUOJOqQi.js";import{n as l,r as u}from"../VBox-DfJPWXqc.js";import{t as d}from"../Button-MpMIYBYJ.js";import{t as f}from"../Menu-Q0bpXXze.js";import{t as p}from"../Spacer-srdN2d2b.js";import{ellipsis_v as m}from"../glyphs/solid/ellipsis_v.es.js";var h=10,g={backgroundColor:`var(--ts-ui-menu-bar-btn-bg, transparent)`,foregroundColor:`var(--ts-ui-menu-bar-btn-fg, inherit)`,cursor:`pointer`,chromeless:!0,insets:new t(0,h,0,h)},_=4,MenuBarButton=class extends d{_onClickHandler;_onMouseOverHandler;constructor(e,t,r,i,a){super(e,{...i,styleRules:[...i?.styleRules??[],{suffix:`:hover`,styles:{backgroundColor:`var(--ts-ui-menu-bar-btn-hover-bg, rgba(30, 100, 200, 0.10))`}}]},{...g,...a??{}}),this._content.getLayoutManager().setComponentSpacing(_),this.getAria().setRole(`menuitem`),this.getAria().setHasPopup(`menu`),this.getAria().setExpanded(!1),this._onClickHandler=()=>{t()},this._onMouseOverHandler=()=>{r()},n.addListener(this,`click`,this._onClickHandler),n.addListener(this,`mouseover`,this._onMouseOverHandler)}computePreferredSize(){let{width:e}=super.computePreferredSize();return{width:e,height:28}}setActive(e){return this.setBackgroundColor(e?`var(--ts-ui-menu-bar-btn-hover-bg, rgba(30, 100, 200, 0.10))`:`var(--ts-ui-menu-bar-btn-bg, transparent)`),this.getAria().setExpanded(e),this.setTooltipSuppressed(e),this}},v=r(MenuBarButton),y={backgroundColor:`var(--ts-ui-menu-bar-bg, rgb(245, 245, 245))`,minSize:{width:0,height:28}},MenuBar=class extends i{_buttons=[];_panels=[];_openIndex=-1;_quickSwitchActive=!1;_keydownListening=!1;_onKeyDown;constructor(t,n){super(t,{...y,...n??{}});let r=new u;r.setComponentSpacing(0),r.setStretching(!0),this.setLayoutManager(r),this.setElementCSSRule(`borderBottom`,`1px solid var(--ts-ui-menu-bar-border, rgb(220, 220, 220))`),this.getAria().setRole(`menubar`),this.getAria().setLabel(`Main menu`),this.getAria().setTabIndex(0),this._onKeyDown=t=>{if(this._openIndex<0)return;let n=this._panels[this._openIndex],r=t.target===null?null:e.source.intern(t.target);if(!c.containsAcrossLayers(n,r))switch(t.key){case`Escape`:return this.closeMenu(),{stop:!0,prevent:!0};case`ArrowLeft`:return this.openMenu((this._openIndex-1+this._panels.length)%this._panels.length),{stop:!0,prevent:!0};case`ArrowRight`:return this.openMenu((this._openIndex+1)%this._panels.length),{stop:!0,prevent:!0};case`ArrowDown`:return n.getFocusedIndex()<0?n.focusItem(0):n.focusNext(),{stop:!0,prevent:!0};case`ArrowUp`:return n.focusPrev(),{stop:!0,prevent:!0};case`Enter`:return n.activateFocused(),{stop:!0,prevent:!0}}},t?.menus&&this.setMenus(t.menus)}setMenus(e){this._openIndex>=0&&this.closeMenu();for(let e of this._panels)e.dispose();this._buttons.length=0,this._panels.length=0,this.disposeAllComponents();for(let t=0;t<e.length;t++){let n=e[t],r=t,i=new v(n.label,()=>{this._openIndex===r?this.closeMenu():this.openMenu(r)},()=>{this._quickSwitchActive&&this._openIndex!==r&&this.openMenu(r)},n.glyph===void 0?void 0:{glyph:n.glyph}),a=new f(n.items,()=>{this.closeMenu()});this._buttons.push(i),this._panels.push(a),this.addComponent(i)}return this}destructor(){for(let e of this._panels)e.dispose();super.destructor()}openMenu(e){return e<0||e>=this._panels.length||e===this._openIndex?this:(this._openIndex>=0&&(this._panels[this._openIndex].close(),this._buttons[this._openIndex].setActive(!1)),this._openIndex=e,this._quickSwitchActive=!0,this._buttons[e].setActive(!0),this._panels[e].setExcludedElement(this._buttons[e].getElement(!0)),this._panels[e].open(this._buttons[e].getElement(!0)),this._keydownListening||(this._keydownListening=!0,n.addViewportListener(this,`keydown`,this._onKeyDown)),this)}closeMenu(){return this._openIndex<0?this:(this._panels[this._openIndex].close(),this._buttons[this._openIndex].setActive(!1),this._openIndex=-1,this._quickSwitchActive=!1,this._keydownListening&&(this._keydownListening=!1,n.removeViewportListener(this,`keydown`,this._onKeyDown)),this)}getOpenIndex(){return this._openIndex}},b=r(MenuBar);o.register(m);var x=4,S=`ellipsis-v`,C={orientation:`horizontal`,compact:!0,overflow:`clip`,overflowSide:`end`,flat:!0,backgroundColor:`var(--ts-ui-toolbar-bg, rgb(245, 245, 245))`},ToolBar=class extends a{constructor(e,t){super(e,{...C,...t??{}}),this.getAria().setRole(`toolbar`),this.getAria().setTabIndex(0),this._onKeyDown=e=>{let t=this._orientation===`horizontal`,n=t?`ArrowRight`:`ArrowDown`,r=t?`ArrowLeft`:`ArrowUp`;if(e.key===n)return this._rovingTabIndex.moveNext(),{prevent:!0};if(e.key===r)return this._rovingTabIndex.movePrev(),{prevent:!0}},n.addSubtreeListener(this,`keydown`,this._onKeyDown)}applyOptions(e){return super.applyOptions(e),this.applyOrientation(e.orientation??this.getOrientation(),e),this.setCompact(e.compact??this.isCompact()),this.setOverflowSide(e.overflowSide??this.getOverflowSide()),this.setOverflow(e.overflow??this.getOverflow()),this.setFlat(e.flat??this.isFlat()),this}setOrientation(e){return this.applyOrientation(e),this}applyOrientation(e,t){if(e===this._orientation)return;let n=this.getLayoutManager(),r=n instanceof u||n instanceof l?n.getComponentSpacing():0,i=e===`horizontal`?new u:new l;if(i.setComponentSpacing(r),i.setStretching(!0),this.setLayoutManager(i),this._orientation=e,this.getAria().setOrientation(e),t?.border!==void 0){this.setBorder(t.border);return}let a=`var(--ts-ui-toolbar-border, rgb(220, 220, 220))`;e===`horizontal`?this.setBorder({borderBottom:`1px solid ${a}`}):this.setBorder({borderRight:`1px solid ${a}`})}getOrientation(){return this._orientation??this._defaultOptions.orientation}setCompact(e){if(e===this._compact)return this;this._compact=e;let n=e?0:4;this.setInsets(new t(n,n,n,n));for(let t of this.getComponents())t instanceof d&&t.setCompact(e);return this.doLayout(),this}isCompact(){return this._compact??this._defaultOptions.compact}setOverflow(e){return this._overflowMode=e,e===`menu`&&this._overflowButton===void 0&&this._createOverflowAffordance(),this.doLayout(),this}_createOverflowAffordance(){let e=new d({flat:!0,glyph:S});e.setDisplayed(!1),e.getAria().setLabel(`More`),e.getAria().setHasPopup(`menu`),e.on(`action`,()=>{this._toggleOverflowMenu()}),this._overflowButton=e,this._overflowMenu=new f,this._overflowSpacer=p.flex(),super.addComponent(e),this._positionOverflowTrigger()}_positionOverflowTrigger(){let e=this._overflowButton,t=this._overflowSpacer;e!=null&&t!=null&&(this._overflowSide===`end`?(t.getParentComponent()!==this&&super.addComponent(t),this.moveComponent(e,this.getComponents().length-1),this.moveComponent(t,this.getComponents().length-2)):(t.getParentComponent()===this&&this.removeComponent(t),this.moveComponent(e,0)))}getOverflow(){return this._overflowMode??this._defaultOptions.overflow}setOverflowSide(e){return e===this._overflowSide?this:(this._overflowSide=e,this._positionOverflowTrigger(),this.doLayout(),this)}getOverflowSide(){return this._overflowSide??this._defaultOptions.overflowSide}setFlat(e){if(e===this._flat)return this;this._flat=e;for(let t of this.getComponents())t instanceof d&&t.setFlat(e);return this}isFlat(){return this._flat??this._defaultOptions.flat}addComponent(e,t){return super.addComponent(e,t),this._rovingTabIndex===void 0&&(this._rovingTabIndex=new s),e.getAria().getTabIndex()!==-1&&this._rovingTabIndex.add(e),this._flat&&e instanceof d&&e.setFlat(!0),this._compact&&e instanceof d&&e.setCompact(!0),this._positionOverflowTrigger(),this}doLayout(){return super.doLayout(),this._overflowMode!==`menu`||this._orientation!==`horizontal`||this._overflowButton===void 0||this._overflowButton===null||this._reflowOverflow(this._overflowButton),this}_reflowOverflow(e){let t=this.getInsets(),n=this.getWidth()-t.getLeft()-t.getRight(),r=this.getLayoutManager(),i=r instanceof u?r.getComponentSpacing():x,a=this.getComponents().filter(t=>t!==e&&t!==this._overflowSpacer),o=this._computeOverflowed(a,e,n,i),s=!1;for(let e of a){let t=o.includes(e);e.isDisplayed()===t&&(e.setDisplayed(!t),s=!0)}let c=o.length>0;e.isDisplayed()!==c&&(e.setDisplayed(c),s=!0),s&&super.doLayout()}_computeOverflowed(e,t,n,r){let widthOf=e=>e.getPreferredSize()?.width??0,i=0;for(let t=0;t<e.length;t++)i+=widthOf(e[t]),t>0&&(i+=r);if(i<=n)return[];let a=n-(widthOf(t)+r),o=[],s=0,c=!1;for(let t=0;t<e.length;t++){let n=e[t],i=s+widthOf(n)+(t>0?r:0);i>a&&(c=!0),c&&n instanceof d?o.push(n):s=i}return o}destructor(){this._overflowMenu?.dispose(),super.destructor()}_toggleOverflowMenu(){let t=this._overflowButton,n=this._overflowMenu;if(t==null||n==null)return;let r=[];for(let e of this.getComponents()){if(e===t||e.isDisplayed()||!(e instanceof d))continue;let n=e.getGlyph()?.getGlyphName();r.push({text:e.getText(),glyph:n,action:()=>{e.click()}})}let i=t.getElement();if(!i)return;let a=e.source.getViewportRect(t);n.toggleFor(i,a,r)}},w=r(ToolBar),T={backgroundColor:`var(--ts-ui-toolbar-separator-color, rgb(220, 220, 220))`},E=r(class ToolBarSeparator extends i{static THICKNESS=1;_orientation;constructor(e,t){super(e,{...T,...t??{}}),this._orientation=e?.orientation??`vertical`,this._orientation===`vertical`?(this.setPreferredSize({width:ToolBarSeparator.THICKNESS,height:0}),this.setMaxSize({width:ToolBarSeparator.THICKNESS,height:Number.MAX_VALUE})):(this.setPreferredSize({width:0,height:ToolBarSeparator.THICKNESS}),this.setMaxSize({width:Number.MAX_VALUE,height:ToolBarSeparator.THICKNESS})),this.getAria().setRole(`separator`),this.getAria().setOrientation(this._orientation),this.getAria().setTabIndex(-1)}getOrientation(){return this._orientation}});export{b as MenuBar,v as MenuBarButton,w as ToolBar,E as ToolBarSeparator};
|
|
2
2
|
//# sourceMappingURL=menubar.es.js.map
|