@jimka/typescript-ui 0.1.1 → 0.3.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/README.md +4 -0
- package/THIRD-PARTY-NOTICES.md +7 -3
- package/dist/lib/{AbstractBooleanInput-C3rj7sje.js → AbstractBooleanInput-C3O4kv7_.js} +2 -2
- package/dist/lib/{AbstractBooleanInput-C3rj7sje.js.map → AbstractBooleanInput-C3O4kv7_.js.map} +1 -1
- package/dist/lib/{AbstractInput-CfjW_HM2.js → AbstractInput-DFWniHqq.js} +2 -2
- package/dist/lib/{AbstractInput-CfjW_HM2.js.map → AbstractInput-DFWniHqq.js.map} +1 -1
- package/dist/lib/AnchorConstraints-CSUcj8Wx.js +2 -0
- package/dist/lib/AnchorConstraints-CSUcj8Wx.js.map +1 -0
- package/dist/lib/AnimatedDropdown-e9urCXK1.js +2 -0
- package/dist/lib/AnimatedDropdown-e9urCXK1.js.map +1 -0
- package/dist/lib/Border-Dq6dXkmS.js +2 -0
- package/dist/lib/Border-Dq6dXkmS.js.map +1 -0
- package/dist/lib/Button-B36rBMKC.js +2 -0
- package/dist/lib/Button-B36rBMKC.js.map +1 -0
- package/dist/lib/{Card-AKIUAWYS.js → Card-P8iUH2-C.js} +2 -2
- package/dist/lib/{Card-AKIUAWYS.js.map → Card-P8iUH2-C.js.map} +1 -1
- package/dist/lib/ComboBox-BjAhXXkY.js +2 -0
- package/dist/lib/ComboBox-BjAhXXkY.js.map +1 -0
- package/dist/lib/Component-CHTzJxEf.js +2 -0
- package/dist/lib/Component-CHTzJxEf.js.map +1 -0
- package/dist/lib/Container-xUbHk6l_.js +2 -0
- package/dist/lib/{Container-3KsvsJ6S.js.map → Container-xUbHk6l_.js.map} +1 -1
- package/dist/lib/DOM-BeR95tE8.js +2 -0
- package/dist/lib/DOM-BeR95tE8.js.map +1 -0
- package/dist/lib/{DragManager-c6M_mE3e.js → DragManager-T5Oljd0F.js} +2 -2
- package/dist/lib/{DragManager-tPMnbjeO.js.map → DragManager-T5Oljd0F.js.map} +1 -1
- package/dist/lib/FieldDecorator-BaTGfKiW.js +2 -0
- package/dist/lib/{FieldDecorator-Bl0h9UEF.js.map → FieldDecorator-BaTGfKiW.js.map} +1 -1
- package/dist/lib/{Fit-CFIr4P9R.js → Fit-E-EIZv1k.js} +2 -2
- package/dist/lib/{Fit-CUS1JXy3.js.map → Fit-E-EIZv1k.js.map} +1 -1
- package/dist/lib/Glyph-CnNslL95.js +2 -0
- package/dist/lib/Glyph-CnNslL95.js.map +1 -0
- package/dist/lib/{Grid-Czux--Mr.js → Grid-BXS2T8MT.js} +2 -2
- package/dist/lib/{Grid-D8luwRPI.js.map → Grid-BXS2T8MT.js.map} +1 -1
- package/dist/lib/GridConstraints-D_kbd-h2.js +2 -0
- package/dist/lib/GridConstraints-D_kbd-h2.js.map +1 -0
- package/dist/lib/HBox-Dm3xgsDE.js +2 -0
- package/dist/lib/{HBox-BWMf9h6r.js.map → HBox-Dm3xgsDE.js.map} +1 -1
- package/dist/lib/{Header-CQjomjo0.js → Header-CqFc2OUx.js} +2 -2
- package/dist/lib/{Header-CQjomjo0.js.map → Header-CqFc2OUx.js.map} +1 -1
- package/dist/lib/{IconText-BXJK0MOq.js → IconText-CTM2r0Tv.js} +2 -2
- package/dist/lib/{IconText-BXJK0MOq.js.map → IconText-CTM2r0Tv.js.map} +1 -1
- package/dist/lib/LayoutConstraints-DkctJZXB.js +2 -0
- package/dist/lib/LayoutConstraints-DkctJZXB.js.map +1 -0
- package/dist/lib/LayoutSerialization-D1OHmxSB.js +2 -0
- package/dist/lib/LayoutSerialization-D1OHmxSB.js.map +1 -0
- package/dist/lib/LayoutSizes-CvMmMgHJ.js +2 -0
- package/dist/lib/LayoutSizes-CvMmMgHJ.js.map +1 -0
- package/dist/lib/List-DHeOPAK2.js +2 -0
- package/dist/lib/List-DHeOPAK2.js.map +1 -0
- package/dist/lib/MemoryStore-DT6iWWco.js +2 -0
- package/dist/lib/MemoryStore-DT6iWWco.js.map +1 -0
- package/dist/lib/Menu-B6ippw-p.js +2 -0
- package/dist/lib/Menu-B6ippw-p.js.map +1 -0
- package/dist/lib/{MenuButton-D15cSbMf.js → MenuButton-Bjm1OyB-.js} +2 -2
- package/dist/lib/{MenuButton-D15cSbMf.js.map → MenuButton-Bjm1OyB-.js.map} +1 -1
- package/dist/lib/Panel-D9lTLGqP.js +2 -0
- package/dist/lib/Panel-D9lTLGqP.js.map +1 -0
- package/dist/lib/Position-DRSlWn4Z.js +2 -0
- package/dist/lib/Position-DRSlWn4Z.js.map +1 -0
- package/dist/lib/ProgressSpinner-glv-29eK.js +2 -0
- package/dist/lib/ProgressSpinner-glv-29eK.js.map +1 -0
- package/dist/lib/RadioButton-R4S3c9WD.js +2 -0
- package/dist/lib/RadioButton-R4S3c9WD.js.map +1 -0
- package/dist/lib/{RovingTabIndex-CFIzIjjU.js → RovingTabIndex-Dgt01LOE.js} +2 -2
- package/dist/lib/{RovingTabIndex-D-zOuptw.js.map → RovingTabIndex-Dgt01LOE.js.map} +1 -1
- package/dist/lib/Scrollbar-CiVV3axj.js +2 -0
- package/dist/lib/Scrollbar-CiVV3axj.js.map +1 -0
- package/dist/lib/Slider-_JVvuQ8M.js +2 -0
- package/dist/lib/Slider-_JVvuQ8M.js.map +1 -0
- package/dist/lib/{Spacer-BVQncB5B.js → Spacer-B57i2-_G.js} +2 -2
- package/dist/lib/{Spacer-BVQncB5B.js.map → Spacer-B57i2-_G.js.map} +1 -1
- package/dist/lib/{TabButton-DqYDfN7P.js → TabButton-DEypdlZf.js} +2 -2
- package/dist/lib/{TabButton-DqYDfN7P.js.map → TabButton-DEypdlZf.js.map} +1 -1
- package/dist/lib/Text-Bni4icFY.js +2 -0
- package/dist/lib/Text-Bni4icFY.js.map +1 -0
- package/dist/lib/Tooltip-BUy6uFKN.js +3 -0
- package/dist/lib/Tooltip-BUy6uFKN.js.map +1 -0
- package/dist/lib/VBox-Dr7Ge9M6.js +2 -0
- package/dist/lib/VBox-Dr7Ge9M6.js.map +1 -0
- package/dist/lib/{VirtualScroller-BKMvTisA.js → VirtualScroller-BPy6KmSX.js} +2 -2
- package/dist/lib/{VirtualScroller-BKMvTisA.js.map → VirtualScroller-BPy6KmSX.js.map} +1 -1
- 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/chart.es.js.map +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 +3 -3
- 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/menubar.es.js +1 -1
- package/dist/lib/component/menubar.es.js.map +1 -1
- package/dist/lib/component/table.es.js +2 -2
- package/dist/lib/component/table.es.js.map +1 -1
- package/dist/lib/component/tree.es.js +1 -1
- package/dist/lib/component/tree.es.js.map +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/data.es.js.map +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/{VirtualRowView-C18j90n5.js → selectionsEqual-2PJrcimg.js} +2 -2
- package/dist/lib/{VirtualRowView-C18j90n5.js.map → selectionsEqual-2PJrcimg.js.map} +1 -1
- package/dist/lib/types/component/button/Button.d.ts +4 -3
- package/dist/lib/types/component/chart/AbstractChart.d.ts +1 -1
- package/dist/lib/types/component/chart/ChartLegend.d.ts +1 -1
- package/dist/lib/types/component/container/DialogBackdrop.d.ts +2 -1
- package/dist/lib/types/component/container/MenuItem.d.ts +1 -1
- package/dist/lib/types/component/container/ScrollStrip.d.ts +1 -0
- package/dist/lib/types/component/container/SplitGutter.d.ts +3 -2
- package/dist/lib/types/component/container/TabBar.d.ts +1 -2
- package/dist/lib/types/component/container/TabPanel.d.ts +6 -3
- package/dist/lib/types/component/container/WindowBorder.d.ts +2 -1
- package/dist/lib/types/component/container/WindowHeader.d.ts +2 -1
- package/dist/lib/types/component/diagram/DiagramEdgeLayer.d.ts +14 -1
- package/dist/lib/types/component/diagram/DiagramModel.d.ts +1 -0
- package/dist/lib/types/component/diagram/DiagramNode.d.ts +4 -0
- package/dist/lib/types/component/diagram/DiagramView.d.ts +76 -5
- package/dist/lib/types/component/diagram/ElkLayoutEngine.d.ts +14 -1
- package/dist/lib/types/component/diagram/index.d.ts +2 -2
- package/dist/lib/types/component/display/Glyph.d.ts +2 -1
- package/dist/lib/types/component/display/Markdown.d.ts +1 -1
- package/dist/lib/types/component/display/PaginationBar.d.ts +1 -1
- package/dist/lib/types/component/display/SpinnerWrap.d.ts +2 -0
- package/dist/lib/types/component/display/Video.d.ts +1 -1
- package/dist/lib/types/component/display/VideoPlayer.d.ts +1 -1
- package/dist/lib/types/component/editor/CodeEditor.d.ts +5 -3
- package/dist/lib/types/component/editor/MarkdownEditor.d.ts +1 -1
- package/dist/lib/types/component/input/Checkbox.d.ts +2 -1
- package/dist/lib/types/component/input/Link.d.ts +1 -1
- package/dist/lib/types/component/input/RadioButton.d.ts +2 -1
- package/dist/lib/types/component/input/Slider.d.ts +2 -1
- package/dist/lib/types/component/input/Text.d.ts +4 -4
- package/dist/lib/types/component/input/TextInput.d.ts +3 -2
- package/dist/lib/types/component/list/AbstractSelectableList.d.ts +2 -1
- package/dist/lib/types/component/menubar/MenuBarButton.d.ts +1 -1
- package/dist/lib/types/component/shared/selectionsEqual.d.ts +1 -0
- package/dist/lib/types/component/table/Column.d.ts +2 -0
- package/dist/lib/types/component/table/ColumnConfig.d.ts +1 -0
- package/dist/lib/types/component/table/Header.d.ts +1 -0
- package/dist/lib/types/component/table/Table.d.ts +20 -0
- package/dist/lib/types/component/table/cell/Header.d.ts +1 -0
- package/dist/lib/types/component/table/index.d.ts +1 -1
- package/dist/lib/types/component/tree/Tree.d.ts +1 -0
- package/dist/lib/types/core/AnimatedDropdown.d.ts +6 -2
- package/dist/lib/types/core/Animation.d.ts +9 -6
- package/dist/lib/types/core/Aria.d.ts +0 -2
- package/dist/lib/types/core/Body.d.ts +1 -0
- package/dist/lib/types/core/ClassStyleRules.d.ts +17 -0
- package/dist/lib/types/core/Component.d.ts +26 -13
- package/dist/lib/types/core/ComponentDefaults.d.ts +1 -0
- package/dist/lib/types/core/DOM.d.ts +19 -2
- package/dist/lib/types/core/ElementAttributes.d.ts +15 -0
- package/dist/lib/types/core/Event.d.ts +12 -6
- package/dist/lib/types/core/PendingTransitions.d.ts +4 -0
- package/dist/lib/types/core/StyleTarget.d.ts +1 -0
- package/dist/lib/types/core/Util.d.ts +2 -0
- package/dist/lib/types/core/index.d.ts +3 -2
- package/dist/lib/types/layout/Accordion.d.ts +2 -0
- package/dist/lib/types/layout/Border.d.ts +2 -0
- package/dist/lib/types/layout/CollapseSupport.d.ts +5 -1
- package/dist/lib/types/layout/LayoutConstraints.d.ts +1 -0
- package/dist/lib/types/layout/LayoutManager.d.ts +2 -0
- package/dist/lib/types/layout/Split.d.ts +1 -0
- package/dist/lib/types/layout/Tab.d.ts +13 -3
- package/dist/lib/types/layout/Table.d.ts +1 -0
- package/dist/lib/types/overlay/AbstractWindow.d.ts +10 -2
- package/dist/lib/types/overlay/Dialog.d.ts +6 -0
- package/dist/lib/types/overlay/Dock.d.ts +12 -2
- package/dist/lib/types/overlay/Drawer.d.ts +5 -0
- package/dist/lib/types/overlay/Menu.d.ts +3 -1
- package/dist/lib/types/overlay/Notification.d.ts +3 -0
- package/dist/lib/types/overlay/Popover.d.ts +3 -1
- package/dist/lib/types/overlay/Rail.d.ts +7 -0
- package/dist/lib/types/overlay/Tooltip.d.ts +3 -0
- package/dist/lib/types/overlay/index.d.ts +1 -1
- package/dist/lib/types/router/RoutePattern.d.ts +7 -0
- package/dist/lib/types/router/Router.d.ts +13 -2
- package/dist/lib/types/router/index.d.ts +1 -1
- package/dist/lib/validation.es.js +1 -1
- package/llms.txt +2 -2
- package/package.json +4 -8
- package/dist/lib/AbstractBooleanInput-C6CidMMX.js +0 -2
- package/dist/lib/AbstractBooleanInput-C6CidMMX.js.map +0 -1
- package/dist/lib/AbstractInput-DD-NpicS.js +0 -2
- package/dist/lib/AbstractInput-DD-NpicS.js.map +0 -1
- package/dist/lib/AnimatedDropdown-BFz-DO7R.js +0 -2
- package/dist/lib/AnimatedDropdown-BFz-DO7R.js.map +0 -1
- package/dist/lib/AnimatedDropdown-BbGCs70E.js +0 -2
- package/dist/lib/AnimatedDropdown-BbGCs70E.js.map +0 -1
- package/dist/lib/Border-5Ki2DCWz.js +0 -2
- package/dist/lib/Border-5Ki2DCWz.js.map +0 -1
- package/dist/lib/Border-oZC_SDy8.js +0 -2
- package/dist/lib/Border-oZC_SDy8.js.map +0 -1
- package/dist/lib/BoxLayout-8ryMD4j5.js +0 -2
- package/dist/lib/BoxLayout-8ryMD4j5.js.map +0 -1
- package/dist/lib/BoxLayout-DgZukB5_.js +0 -2
- package/dist/lib/BoxLayout-DgZukB5_.js.map +0 -1
- package/dist/lib/Button-Cdq2ySPL.js +0 -2
- package/dist/lib/Button-Cdq2ySPL.js.map +0 -1
- package/dist/lib/Button-DEUtBqK4.js +0 -2
- package/dist/lib/Button-DEUtBqK4.js.map +0 -1
- package/dist/lib/Card-UF0fq8cQ.js +0 -2
- package/dist/lib/Card-UF0fq8cQ.js.map +0 -1
- package/dist/lib/ComboBox-GOBOAJ1N.js +0 -2
- package/dist/lib/ComboBox-GOBOAJ1N.js.map +0 -1
- package/dist/lib/ComboBox-e_YVsWBr.js +0 -2
- package/dist/lib/ComboBox-e_YVsWBr.js.map +0 -1
- package/dist/lib/Component-BR2f0Itb.js +0 -2
- package/dist/lib/Component-BR2f0Itb.js.map +0 -1
- package/dist/lib/Component-Bs6TvaGZ.js +0 -2
- package/dist/lib/Component-Bs6TvaGZ.js.map +0 -1
- package/dist/lib/Container-3KsvsJ6S.js +0 -2
- package/dist/lib/Container-CzyZeMyZ.js +0 -2
- package/dist/lib/Container-CzyZeMyZ.js.map +0 -1
- package/dist/lib/DOM-DeF_dWe2.js +0 -2
- package/dist/lib/DOM-DeF_dWe2.js.map +0 -1
- package/dist/lib/DragManager-c6M_mE3e.js.map +0 -1
- package/dist/lib/DragManager-tPMnbjeO.js +0 -2
- package/dist/lib/FieldDecorator-Bl0h9UEF.js +0 -2
- package/dist/lib/FieldDecorator-E7WzutjO.js +0 -2
- package/dist/lib/FieldDecorator-E7WzutjO.js.map +0 -1
- package/dist/lib/Fit-CFIr4P9R.js.map +0 -1
- package/dist/lib/Fit-CUS1JXy3.js +0 -2
- package/dist/lib/Glyph-6Ki3A1_a.js +0 -2
- package/dist/lib/Glyph-6Ki3A1_a.js.map +0 -1
- package/dist/lib/Glyph-WUqTF_Z9.js +0 -2
- package/dist/lib/Glyph-WUqTF_Z9.js.map +0 -1
- package/dist/lib/Grid-Czux--Mr.js.map +0 -1
- package/dist/lib/Grid-D8luwRPI.js +0 -2
- package/dist/lib/GridConstraints-CzC0w4i-.js +0 -2
- package/dist/lib/GridConstraints-CzC0w4i-.js.map +0 -1
- package/dist/lib/GridConstraints-Q3wvuovN.js +0 -2
- package/dist/lib/GridConstraints-Q3wvuovN.js.map +0 -1
- package/dist/lib/HBox-BWMf9h6r.js +0 -2
- package/dist/lib/HBox-Q8y1PHlk.js +0 -2
- package/dist/lib/HBox-Q8y1PHlk.js.map +0 -1
- package/dist/lib/Header-zPdvC2AX.js +0 -2
- package/dist/lib/Header-zPdvC2AX.js.map +0 -1
- package/dist/lib/IconText-BvGfu7eq.js +0 -2
- package/dist/lib/IconText-BvGfu7eq.js.map +0 -1
- package/dist/lib/LayoutConstraints-CHI2lhPd.js +0 -2
- package/dist/lib/LayoutConstraints-CHI2lhPd.js.map +0 -1
- package/dist/lib/LayoutSerialization-CWU0iEuV.js +0 -2
- package/dist/lib/LayoutSerialization-CWU0iEuV.js.map +0 -1
- package/dist/lib/LayoutSerialization-C_zcwaN3.js +0 -2
- package/dist/lib/LayoutSerialization-C_zcwaN3.js.map +0 -1
- package/dist/lib/LayoutSizes-BW4wyGDI.js +0 -2
- package/dist/lib/LayoutSizes-BW4wyGDI.js.map +0 -1
- package/dist/lib/LayoutSizes-XdhpAOmc.js +0 -2
- package/dist/lib/LayoutSizes-XdhpAOmc.js.map +0 -1
- package/dist/lib/List-BgxnLWnl.js +0 -2
- package/dist/lib/List-BgxnLWnl.js.map +0 -1
- package/dist/lib/List-D-GhoVgB.js +0 -2
- package/dist/lib/List-D-GhoVgB.js.map +0 -1
- package/dist/lib/Menu-BdnwRY0M.js +0 -2
- package/dist/lib/Menu-BdnwRY0M.js.map +0 -1
- package/dist/lib/Menu-Wz4MK6sA.js +0 -2
- package/dist/lib/Menu-Wz4MK6sA.js.map +0 -1
- package/dist/lib/MenuButton-JQQaKThJ.js +0 -2
- package/dist/lib/MenuButton-JQQaKThJ.js.map +0 -1
- package/dist/lib/Panel-DApa7vA6.js +0 -2
- package/dist/lib/Panel-DApa7vA6.js.map +0 -1
- package/dist/lib/Panel-DIsdaqc2.js +0 -2
- package/dist/lib/Panel-DIsdaqc2.js.map +0 -1
- package/dist/lib/Position-B-WfZYAJ.js +0 -2
- package/dist/lib/Position-B-WfZYAJ.js.map +0 -1
- package/dist/lib/Position-DJKB0N3l.js +0 -2
- package/dist/lib/Position-DJKB0N3l.js.map +0 -1
- package/dist/lib/ProgressSpinner-CNYcsBhw.js +0 -2
- package/dist/lib/ProgressSpinner-CNYcsBhw.js.map +0 -1
- package/dist/lib/ProgressSpinner-Dzaka7_c.js +0 -2
- package/dist/lib/ProgressSpinner-Dzaka7_c.js.map +0 -1
- package/dist/lib/RadioButton-CepkneSA.js +0 -2
- package/dist/lib/RadioButton-CepkneSA.js.map +0 -1
- package/dist/lib/RadioButton-eI3-vXn3.js +0 -2
- package/dist/lib/RadioButton-eI3-vXn3.js.map +0 -1
- package/dist/lib/RovingTabIndex-CFIzIjjU.js.map +0 -1
- package/dist/lib/RovingTabIndex-D-zOuptw.js +0 -2
- package/dist/lib/Scrollbar-DQdCdj94.js +0 -2
- package/dist/lib/Scrollbar-DQdCdj94.js.map +0 -1
- package/dist/lib/Scrollbar-DchfiFKC.js +0 -2
- package/dist/lib/Scrollbar-DchfiFKC.js.map +0 -1
- package/dist/lib/Slider-DvDdVvRm.js +0 -2
- package/dist/lib/Slider-DvDdVvRm.js.map +0 -1
- package/dist/lib/Slider-xRxNSjFN.js +0 -2
- package/dist/lib/Slider-xRxNSjFN.js.map +0 -1
- package/dist/lib/Spacer-BqiPiCqz.js +0 -2
- package/dist/lib/Spacer-BqiPiCqz.js.map +0 -1
- package/dist/lib/TabButton-pZKFYg7b.js +0 -2
- package/dist/lib/TabButton-pZKFYg7b.js.map +0 -1
- package/dist/lib/Text-D1RrBY52.js +0 -2
- package/dist/lib/Text-D1RrBY52.js.map +0 -1
- package/dist/lib/Text-DJoUHukb.js +0 -2
- package/dist/lib/Text-DJoUHukb.js.map +0 -1
- package/dist/lib/Tooltip-4lU_tf6r.js +0 -3
- package/dist/lib/Tooltip-4lU_tf6r.js.map +0 -1
- package/dist/lib/Tooltip-5BR7yYEX.js +0 -3
- package/dist/lib/Tooltip-5BR7yYEX.js.map +0 -1
- package/dist/lib/VBox-CdV9VGxR.js +0 -2
- package/dist/lib/VBox-CdV9VGxR.js.map +0 -1
- package/dist/lib/VBox-D5B9ecw0.js +0 -2
- package/dist/lib/VBox-D5B9ecw0.js.map +0 -1
- package/dist/lib/VirtualRowView-Con9SWiU.js +0 -2
- package/dist/lib/VirtualRowView-Con9SWiU.js.map +0 -1
- package/dist/lib/VirtualScroller-BPDmO1ir.js +0 -2
- package/dist/lib/VirtualScroller-BPDmO1ir.js.map +0 -1
package/dist/lib/primitive.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./Position-
|
|
1
|
+
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./Position-DRSlWn4Z.js";import{t as c}from"./Placement-7kqdaK4Z.js";var Point=class extends t{_x;_y;constructor(e,t){super(),this._x=e??0,this._y=t??0}getX(){return this._x??0}getY(){return this._y??0}render(){return this.getX()+` `+this.getY()}};export{r as Insets,c as Placement,Point,s as Position,e as UNBOUNDED,a as borderSideWidth,n as borderToStyle,i as isUnbounded,o as saturate};
|
|
2
2
|
//# sourceMappingURL=primitive.es.js.map
|
package/dist/lib/router.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./DOM-
|
|
1
|
+
import{t as e}from"./DOM-BeR95tE8.js";import{t}from"./ListenerBag-WPdKuuds.js";function normalizePath(e){let t=e.startsWith(`#`)?e.slice(1):e,n=t.indexOf(`?`);return n>=0&&(t=t.slice(0,n)),`/`+splitPath(t).join(`/`)}function splitPath(e){return e.split(`/`).filter(e=>e.length>0)}function splitFragment(e){let t=e.indexOf(`#`);return t===-1?{path:e,fragment:``}:{path:e.slice(0,t),fragment:e.slice(t+1)}}function normalizeBase(e){let t=splitPath(e);return t.length===0?`/`:`/`+t.join(`/`)+`/`}function stripBase(e,t){let n=normalizeBase(e).slice(0,-1);return n!==``&&(t===n||t.startsWith(n+`/`))?normalizePath(t.slice(n.length)):normalizePath(t)}function joinBase(e,t){let n=normalizeBase(e),r=normalizePath(t);return r===`/`?n:n.slice(0,-1)+r}function compilePattern(e){let t=normalizePath(e),n=splitPath(t),r=n.map((t,r)=>{if(t===`*`){if(r!==n.length-1)throw Error(`RoutePattern: "*" is only valid as the final segment of "${e}"`);return{kind:`catchAll`,value:``}}return t.startsWith(`:`)?{kind:`param`,value:t.slice(1)}:{kind:`static`,value:t}});return{pattern:t,key:r.map(e=>e.kind===`static`?e.value:e.kind===`param`?`:`:`*`).join(`/`),segments:r}}function matchPattern(e,t){let n=e.segments,r=n.length>0&&n.at(-1).kind===`catchAll`,i=r?n.length-1:n.length;if(r?t.length<i:t.length!==i)return null;let a={};for(let e=0;e<i;e+=1){let r=n[e],i=t[e];if(r.kind===`static`){if(r.value!==i)return null}else r.kind===`param`&&(a[r.value]=decodeSegment(i))}return a}function decodeSegment(e){try{return decodeURIComponent(e)}catch{return e}}var n={static:2,param:1,catchAll:0};function rankAt(e,t){return t>=e.length?3:n[e[t].kind]}function selectPattern(e,t){let n=splitPath(t),r=null,i=null;for(let t of e){let e=matchPattern(t,n);e!==null&&(r===null||isMoreSpecific(t.segments,r.segments))&&(r=t,i=e)}return r===null?null:{compiled:r,params:i}}function isMoreSpecific(e,t){let n=Math.max(e.length,t.length);for(let r=0;r<n;r+=1){let n=rankAt(e,r),i=rankAt(t,r);if(n!==i)return n>i}return!1}var Router=class{_routes=new Map;_listeners=new t;_started=!1;_mode;_base;_onHashChange=()=>this.handleHashChange();_onPopState=()=>this.handlePopState();constructor(e){this.applyOptions(e??{})}register(e,t){let n=compilePattern(e),r=this._routes.get(n.key);return r!==void 0&&r.pattern!==n.pattern&&console.warn(`Router: "${r.pattern}" and "${n.pattern}" have the same specificity; "${n.pattern}" replaces it.`),this._routes.set(n.key,{...n,handler:t}),this}start(){return this._started?(console.warn(`Router: start() called on an already-started router; ignoring.`),this):(this._started=!0,this.applyCurrentRoute(),this._mode===`history`?e.sink.addListener(e.source.getWindow(),`popstate`,this._onPopState):e.sink.addListener(e.source.getWindow(),`hashchange`,this._onHashChange),this)}stop(){return this._started?(this._mode===`history`?e.sink.removeListener(e.source.getWindow(),`popstate`,this._onPopState):e.sink.removeListener(e.source.getWindow(),`hashchange`,this._onHashChange),this._started=!1,this):this}navigate(t,n){let r=splitFragment(t);if(this._mode===`hash`){let t=`#/`+splitPath(normalizePath(r.path)).map(e=>encodeURIComponent(e)).join(`/`);return n?.replace===!0?e.sink.replaceLocationHash(t):e.sink.setLocationHash(t),this}let i=normalizePath(r.path),a=r.fragment;if(i===this.getPath()&&a===this.getFragment())return this;let o=this.getHref(a===``?i:`${i}#${a}`);return n?.replace===!0?e.sink.replaceHistoryPath(o):e.sink.pushHistoryPath(o),this.applyCurrentRoute(),this}getHref(e){let t=splitFragment(e),n=`/`+splitPath(normalizePath(t.path)).map(e=>encodeURIComponent(e)).join(`/`);if(this._mode===`hash`)return`#`+n;let r=joinBase(this._base,n);return t.fragment===``?r:`${r}#${t.fragment}`}getPath(t){if(this._mode===`hash`){let n=t??e.source.getLocationHash();return this.decodePath(normalizePath(n))}let n=t??e.source.getLocationPathname();return this.decodePath(stripBase(this._base,splitFragment(n).path))}getFragment(t){if(this._mode===`hash`)return``;if(t!==void 0)return splitFragment(t).fragment;let n=e.source.getLocationHash();return n.startsWith(`#`)?n.slice(1):n}decodePath(e){return`/`+splitPath(e).map(e=>{try{return decodeURIComponent(e)}catch{return e}}).join(`/`)}on(e,t){return this._listeners.add(e,t),this}off(e,t){return this._listeners.remove(e,t),this}emit(e,t){this._listeners.fire(e,t)}applyCurrentRoute(){let e=this.getPath(),t=this.getFragment(),n=selectPattern(Array.from(this._routes.values()),e);if(n===null){this.emit(`nomatch`,e);return}let r={pattern:n.compiled.pattern,params:n.params,path:e,fragment:t};n.compiled.handler(n.params,e,t),this.emit(`navigate`,r)}applyOptions(e){if(this._mode=e.mode??`hash`,this._base=normalizeBase(e.base??`/`),e.routes!==void 0)for(let t of Object.keys(e.routes))this.register(t,e.routes[t]);if(e.listeners!==void 0)for(let t of Object.keys(e.listeners)){let n=e.listeners[t];n!==void 0&&this._listeners.add(t,n)}}handleHashChange(){this.applyCurrentRoute()}handlePopState(){this.applyCurrentRoute()}};export{Router};
|
|
2
2
|
//# sourceMappingURL=router.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.es.js","names":[],"sources":["../../src/typescript/lib/router/RoutePattern.ts","../../src/typescript/lib/router/Router.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n// Pure route-pattern mechanics behind Router: normalizing a hash/path,\n// compiling a registered pattern into segments + an ambiguity key, matching a\n// path against a compiled pattern, and picking the most specific match. No\n// DOM seam involved — internal to router/, not exported from the barrel.\n\n/** The kind of a single pattern segment. */\nexport type SegmentKind = \"static\" | \"param\" | \"catchAll\";\n\n/** One segment of a compiled pattern. */\nexport interface RouteSegment {\n kind: SegmentKind;\n /** Literal text for \"static\", the parameter name for \"param\", \"\" for \"catchAll\". */\n value: string;\n}\n\n/** A pattern parsed into segments, plus its ambiguity key. */\nexport interface CompiledPattern {\n /** The pattern string as registered, after normalization (e.g. \"/data/:id\"). */\n pattern: string;\n /** Ambiguity key: static segments by literal, \"param\" as \":\", \"catchAll\" as \"*\". */\n key: string;\n segments: RouteSegment[];\n}\n\n/**\n * Normalizes a hash or path to a leading-slash, no-trailing-slash path: strips\n * a leading `\"#\"`, discards everything from the first `\"?\"` onward, and\n * collapses empty segments (so a doubled `\"//\"` and a trailing `\"/\"` both\n * disappear). `\"\"`, `\"#\"`, and `\"#/\"` all normalize to `\"/\"`.\n *\n * @param input - The raw hash (with or without its leading `\"#\"`) or path.\n * @returns The normalized path.\n */\nexport function normalizePath(input: string): string {\n let path = input.startsWith(\"#\") ? input.slice(1) : input;\n const queryIndex = path.indexOf(\"?\");\n\n if (queryIndex >= 0) {\n path = path.slice(0, queryIndex);\n }\n\n return \"/\" + splitPath(path).join(\"/\");\n}\n\n/**\n * Splits a normalized path into its non-empty segments.\n *\n * @param path - The path to split.\n * @returns The segments, in order.\n */\nexport function splitPath(path: string): string[] {\n return path.split(\"/\").filter((segment) => segment.length > 0);\n}\n\n/**\n * Parses a registered pattern into {@link RouteSegment}s and derives its\n * ambiguity key.\n *\n * @param pattern - The pattern string, e.g. `\"/data/rows/:sel\"`.\n * @returns The compiled pattern.\n * @throws If `\"*\"` appears anywhere but the final segment.\n */\nexport function compilePattern(pattern: string): CompiledPattern {\n const normalized = normalizePath(pattern);\n const rawSegments = splitPath(normalized);\n\n const segments: RouteSegment[] = rawSegments.map((raw, i) => {\n if (raw === \"*\") {\n if (i !== rawSegments.length - 1) {\n throw new Error(`RoutePattern: \"*\" is only valid as the final segment of \"${pattern}\"`);\n }\n\n return { kind: \"catchAll\", value: \"\" };\n }\n\n if (raw.startsWith(\":\")) {\n return { kind: \"param\", value: raw.slice(1) };\n }\n\n return { kind: \"static\", value: raw };\n });\n\n const key = segments\n .map((segment) => segment.kind === \"static\" ? segment.value : segment.kind === \"param\" ? \":\" : \"*\")\n .join(\"/\");\n\n return { pattern: normalized, key, segments };\n}\n\n/**\n * Returns the extracted params when `segments` match `compiled`, or `null`\n * when they don't. A trailing `catchAll` segment matches zero or more\n * remaining segments; every other kind requires an exact segment count.\n * Captured `:param` values run through `decodeURIComponent`, falling back to\n * the raw segment text on a malformed escape.\n *\n * @param compiled - The compiled pattern to match against.\n * @param segments - The candidate path's segments (from {@link splitPath}).\n * @returns The extracted params, or `null` when there is no match.\n */\nexport function matchPattern(compiled: CompiledPattern, segments: string[]): Record<string, string> | null {\n const patternSegments = compiled.segments;\n const isCatchAll = patternSegments.length > 0 && patternSegments.at(-1)!.kind === \"catchAll\";\n const staticLength = isCatchAll ? patternSegments.length - 1 : patternSegments.length;\n\n if (isCatchAll ? segments.length < staticLength : segments.length !== staticLength) {\n return null;\n }\n\n const params: Record<string, string> = {};\n\n for (let i = 0; i < staticLength; i += 1) {\n const patternSegment = patternSegments[i];\n const value = segments[i];\n\n if (patternSegment.kind === \"static\") {\n if (patternSegment.value !== value) {\n return null;\n }\n } else if (patternSegment.kind === \"param\") {\n params[patternSegment.value] = decodeSegment(value);\n }\n }\n\n return params;\n}\n\n/**\n * Decodes a captured path segment, falling back to the raw text when it\n * carries a malformed percent-escape.\n *\n * @param value - The raw segment text.\n * @returns The decoded value, or `value` unchanged on a decode failure.\n */\nfunction decodeSegment(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\n/** Rank of each real segment kind: higher wins a specificity tie-break. */\nconst KIND_RANK: Record<SegmentKind, number> = { static: 2, param: 1, catchAll: 0 };\n\n/**\n * Rank of position `i` in `segments`. Reaching the end of the pattern (`i` at\n * or past its length) outranks every real segment kind — see\n * {@link selectPattern}.\n *\n * @param segments - The pattern's segments.\n * @param i - The position to rank.\n * @returns The rank at that position.\n */\nfunction rankAt(segments: readonly RouteSegment[], i: number): number {\n return i >= segments.length ? 3 : KIND_RANK[segments[i].kind];\n}\n\n/**\n * Returns the highest-ranked pattern in `compiled` that matches `path`, or\n * `null` when none match. Patterns are compared segment by segment from the\n * left via {@link rankAt}; the first position where two matching patterns\n * differ decides the winner. Two patterns can never tie on every position —\n * that would mean identical ambiguity keys, which the route table (see\n * `Router`) forbids. Registration order never affects the result.\n *\n * @param compiled - The candidate compiled patterns.\n * @param path - The normalized path to match.\n * @returns The winning pattern and its extracted params, or `null`.\n */\nexport function selectPattern<T extends CompiledPattern>(\n compiled: readonly T[],\n path: string,\n): { compiled: T; params: Record<string, string> } | null {\n const segments = splitPath(path);\n\n let best: T | null = null;\n let bestParams: Record<string, string> | null = null;\n\n for (const candidate of compiled) {\n const params = matchPattern(candidate, segments);\n\n if (params === null) {\n continue;\n }\n\n if (best === null || isMoreSpecific(candidate.segments, best.segments)) {\n best = candidate;\n bestParams = params;\n }\n }\n\n return best === null ? null : { compiled: best, params: bestParams! };\n}\n\n/**\n * Whether `a` outranks `b` by {@link rankAt} at the first position where they\n * differ.\n *\n * @param a - The candidate pattern's segments.\n * @param b - The current best pattern's segments.\n * @returns `true` when `a` is more specific than `b`.\n */\nfunction isMoreSpecific(a: readonly RouteSegment[], b: readonly RouteSegment[]): boolean {\n const length = Math.max(a.length, b.length);\n\n for (let i = 0; i < length; i += 1) {\n const rankA = rankAt(a, i);\n const rankB = rankAt(b, i);\n\n if (rankA !== rankB) {\n return rankA > rankB;\n }\n }\n\n return false;\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from '~/core/DOM.js';\nimport { ListenerBag } from '~/core/ListenerBag.js';\nimport { compilePattern, normalizePath, splitPath, selectPattern, type CompiledPattern } from '~/router/RoutePattern.js';\n\n/** Params extracted from a matched pattern's `:name` segments. */\nexport type RouteParams = Record<string, string>;\n\n/** A registered route's callback: drives whatever it fronts, never builds it. */\nexport type RouteHandler = (params: RouteParams, path: string) => void;\n\n/** The events a {@link Router} emits. */\nexport type RouterEvent = \"navigate\" | \"nomatch\";\n\n/** The pattern and params a navigation resolved to. */\nexport interface RouteMatch {\n /** The pattern that won, as registered. */\n pattern: string;\n params: RouteParams;\n /** The normalized path that was matched. */\n path: string;\n}\n\n/** Construction options for {@link Router}. */\nexport interface RouterOptions {\n /** Patterns to `register` at construction, keyed by pattern string. */\n routes?: Record<string, RouteHandler>;\n listeners?: Partial<{\n navigate: (match: RouteMatch) => void;\n nomatch: (path: string) => void;\n }>;\n}\n\n/** A registered route: its compiled pattern plus the handler it drives. */\ntype CompiledRoute = CompiledPattern & { handler: RouteHandler };\n\n/**\n * Maps the URL hash to a single top-level app section. Patterns are\n * registered with {@link register} (e.g. `\"/data/rows/:sel\"`); on a\n * navigation, the router selects the most specific matching pattern, extracts\n * its `:param` values, and calls that pattern's handler — the handler drives\n * components that already exist, it never builds them.\n *\n * {@link start} reads the current hash, applies the matching route\n * synchronously, then installs the `hashchange` listener; call it once the\n * app has built its component tree and before the first layout pass runs, so\n * the routed section is already selected when that pass runs. {@link stop}\n * removes the listener.\n *\n * It is a plain class (no DOM element, so not `callable()`-wrapped) — it\n * follows the shape of a data store: an options bag, a private listener bag,\n * and typed `on` / `off` / `emit` forwarders.\n *\n * @category Core\n */\nexport class Router {\n\n private _routes: Map<string, CompiledRoute> = new Map();\n private _listeners: ListenerBag<RouterEvent> = new ListenerBag<RouterEvent>();\n private _started: boolean = false;\n\n // Stable reference so add/remove pair up; delegates to a named method.\n private readonly _onHashChange: () => void = () => this.handleHashChange();\n\n /**\n * @param options - Routes and listeners to register at construction.\n */\n constructor(options?: RouterOptions) {\n this.applyOptions(options ?? {});\n }\n\n /**\n * Registers a pattern's handler. Re-registering the exact same pattern\n * string replaces its handler silently. Registering a *different*\n * pattern string that collides with an already-registered one on\n * specificity (e.g. `\"/users/:id\"` and `\"/users/:name\"`) replaces it too,\n * but logs a warning naming both patterns — that collision usually\n * signals an authoring mistake.\n *\n * @param pattern - The route pattern, e.g. `\"/data/rows/:sel\"`.\n * @param handler - Called with the extracted params and the normalized\n * path when this pattern wins a navigation.\n * @returns This router, for chaining.\n */\n register(pattern: string, handler: RouteHandler): this {\n const compiled = compilePattern(pattern);\n const existing = this._routes.get(compiled.key);\n\n if (existing !== undefined && existing.pattern !== compiled.pattern) {\n console.warn(`Router: \"${existing.pattern}\" and \"${compiled.pattern}\" have the same specificity; \"${compiled.pattern}\" replaces it.`);\n }\n\n this._routes.set(compiled.key, { ...compiled, handler });\n\n return this;\n }\n\n /**\n * Reads the current hash, applies the matching route synchronously, then\n * installs the `hashchange` listener. Calling `start()` again on an\n * already-started router logs a warning and is otherwise a no-op — it\n * does not install a second listener.\n *\n * @returns This router, for chaining.\n */\n start(): this {\n if (this._started) {\n console.warn(`Router: start() called on an already-started router; ignoring.`);\n\n return this;\n }\n\n this._started = true;\n this.applyCurrentRoute();\n DOM.sink.addListener(DOM.source.getWindow(), \"hashchange\", this._onHashChange);\n\n return this;\n }\n\n /**\n * Removes the `hashchange` listener. Safe to call when never started, or\n * more than once.\n *\n * @returns This router, for chaining.\n */\n stop(): this {\n if (!this._started) {\n return this;\n }\n\n DOM.sink.removeListener(DOM.source.getWindow(), \"hashchange\", this._onHashChange);\n this._started = false;\n\n return this;\n }\n\n /**\n * Writes `path` into the hash — pushing a history entry, or replacing the\n * current one when `options.replace` is `true`. Each segment is\n * percent-encoded. Writing the path already in the hash is a same-value\n * write: it fires no `hashchange` and re-runs no handler.\n *\n * @param path - The path to navigate to, e.g. `\"/settings\"`.\n * @param options - `replace` to replace the current history entry instead\n * of pushing a new one.\n * @returns This router, for chaining.\n */\n navigate(path: string, options?: { replace?: boolean }): this {\n const segments = splitPath(normalizePath(path));\n const hash = \"#/\" + segments.map((segment) => encodeURIComponent(segment)).join(\"/\");\n\n if (options?.replace === true) {\n DOM.sink.replaceLocationHash(hash);\n } else {\n DOM.sink.setLocationHash(hash);\n }\n\n return this;\n }\n\n /**\n * The normalized path currently in the hash.\n *\n * @returns The current path.\n */\n getPath(): string {\n return normalizePath(DOM.source.getLocationHash());\n }\n\n on(event: \"navigate\", listener: (match: RouteMatch) => void): this;\n on(event: \"nomatch\", listener: (path: string) => void): this;\n\n /**\n * Subscribes a listener to a router event. Listeners fire in\n * registration order.\n *\n * @param event - The event to listen for.\n * @param listener - The callback to invoke.\n * @returns This router, for chaining.\n */\n on(event: RouterEvent, listener: Function): this {\n this._listeners.add(event, listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered listener. No-op if it was never\n * registered for that event.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The exact callback reference to remove.\n * @returns This router, for chaining.\n */\n off(event: RouterEvent, listener: Function): this {\n this._listeners.remove(event, listener);\n\n return this;\n }\n\n /**\n * Notifies all listeners registered for an event, in registration order.\n *\n * @param event - The event to emit.\n * @param payload - The value passed to each listener.\n */\n protected emit(event: RouterEvent, payload: unknown): void {\n this._listeners.fire(event, payload);\n }\n\n /**\n * Reads the current hash and calls the most specific matching pattern's\n * handler, emitting `\"navigate\"` — or emits `\"nomatch\"` when nothing\n * matches. Shared by {@link start} and the `hashchange` listener.\n */\n private applyCurrentRoute(): void {\n const path = this.getPath();\n const result = selectPattern(Array.from(this._routes.values()), path);\n\n if (result === null) {\n this.emit(\"nomatch\", path);\n\n return;\n }\n\n const match: RouteMatch = { pattern: result.compiled.pattern, params: result.params, path };\n\n result.compiled.handler(result.params, path);\n this.emit(\"navigate\", match);\n }\n\n /**\n * Applies an {@link RouterOptions} bag: registers `routes`, then wires\n * `listeners`. Called from the constructor body, after every field\n * initializer has run.\n *\n * @param options - The options bag to apply.\n */\n protected applyOptions(options: RouterOptions): void {\n if (options.routes !== undefined) {\n for (const pattern of Object.keys(options.routes)) {\n this.register(pattern, options.routes[pattern]);\n }\n }\n\n if (options.listeners !== undefined) {\n for (const event of Object.keys(options.listeners) as RouterEvent[]) {\n const listener = options.listeners[event];\n\n if (listener !== undefined) {\n this._listeners.add(event, listener);\n }\n }\n }\n }\n\n private handleHashChange(): void {\n this.applyCurrentRoute();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.es.js","names":[],"sources":["../../src/typescript/lib/router/RoutePattern.ts","../../src/typescript/lib/router/Router.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n// Pure route-pattern mechanics behind Router: normalizing a hash/path,\n// compiling a registered pattern into segments + an ambiguity key, matching a\n// path against a compiled pattern, and picking the most specific match. No\n// DOM seam involved — internal to router/, not exported from the barrel.\n\n/** The kind of a single pattern segment. */\nexport type SegmentKind = \"static\" | \"param\" | \"catchAll\";\n\n/** One segment of a compiled pattern. */\nexport interface RouteSegment {\n kind: SegmentKind;\n /** Literal text for \"static\", the parameter name for \"param\", \"\" for \"catchAll\". */\n value: string;\n}\n\n/** A pattern parsed into segments, plus its ambiguity key. */\nexport interface CompiledPattern {\n /** The pattern string as registered, after normalization (e.g. \"/data/:id\"). */\n pattern: string;\n /** Ambiguity key: static segments by literal, \"param\" as \":\", \"catchAll\" as \"*\". */\n key: string;\n segments: RouteSegment[];\n}\n\n/**\n * Normalizes a hash or path to a leading-slash, no-trailing-slash path: strips\n * a leading `\"#\"`, discards everything from the first `\"?\"` onward, and\n * collapses empty segments (so a doubled `\"//\"` and a trailing `\"/\"` both\n * disappear). `\"\"`, `\"#\"`, and `\"#/\"` all normalize to `\"/\"`.\n *\n * @param input - The raw hash (with or without its leading `\"#\"`) or path.\n * @returns The normalized path.\n */\nexport function normalizePath(input: string): string {\n let path = input.startsWith(\"#\") ? input.slice(1) : input;\n const queryIndex = path.indexOf(\"?\");\n\n if (queryIndex >= 0) {\n path = path.slice(0, queryIndex);\n }\n\n return \"/\" + splitPath(path).join(\"/\");\n}\n\n/**\n * Splits a normalized path into its non-empty segments.\n *\n * @param path - The path to split.\n * @returns The segments, in order.\n */\nexport function splitPath(path: string): string[] {\n return path.split(\"/\").filter((segment) => segment.length > 0);\n}\n\n/**\n * Splits a URL-ish string at its first `\"#\"`: the part before, and the\n * fragment without its `\"#\"`. Everything after the first `\"#\"` is the\n * fragment verbatim — a second `\"#\"` in the input stays part of it. Never\n * normalizes either half; the caller runs `path` through {@link normalizePath}.\n *\n * @param input - The raw href or path, with or without a fragment.\n * @returns The part before the first `\"#\"`, and the fragment without it.\n */\nexport function splitFragment(input: string): { path: string; fragment: string } {\n const hashIndex = input.indexOf(\"#\");\n\n if (hashIndex === -1) {\n return { path: input, fragment: \"\" };\n }\n\n return { path: input.slice(0, hashIndex), fragment: input.slice(hashIndex + 1) };\n}\n\n/**\n * Normalizes a base to leading-and-trailing-slash form, so\n * {@link stripBase} and {@link joinBase} can both assume that shape.\n * `\"\"`, `\"/\"`, `\"x\"`, `\"/x\"`, and `\"/x/\"` all become `\"/\"` or `\"/x/\"`.\n *\n * @param base - The raw base path.\n * @returns The normalized base.\n */\nexport function normalizeBase(base: string): string {\n const segments = splitPath(base);\n\n return segments.length === 0 ? \"/\" : \"/\" + segments.join(\"/\") + \"/\";\n}\n\n/**\n * Removes `base` from the front of `pathname`, then normalizes what is\n * left through {@link normalizePath}. A `pathname` that does not start with\n * `base` is normalized as-is rather than rejected.\n *\n * @param base - The site base, in any shape {@link normalizeBase} accepts.\n * @param pathname - The URL path to strip the base from.\n * @returns The normalized path with `base` removed.\n */\nexport function stripBase(base: string, pathname: string): string {\n const normalizedBase = normalizeBase(base);\n // Base without its trailing slash, e.g. \"/typescript-ui\" (\"\" at the root).\n const basePrefix = normalizedBase.slice(0, -1);\n\n if (basePrefix !== \"\" && (pathname === basePrefix || pathname.startsWith(basePrefix + \"/\"))) {\n return normalizePath(pathname.slice(basePrefix.length));\n }\n\n return normalizePath(pathname);\n}\n\n/**\n * Joins a normalized base and a normalized path into a URL path — the\n * inverse of {@link stripBase}.\n *\n * @param base - The site base, in any shape {@link normalizeBase} accepts.\n * @param path - The route path, in any shape {@link normalizePath} accepts.\n * @returns The joined URL path.\n */\nexport function joinBase(base: string, path: string): string {\n const normalizedBase = normalizeBase(base);\n const normalizedPath = normalizePath(path);\n\n if (normalizedPath === \"/\") {\n return normalizedBase;\n }\n\n return normalizedBase.slice(0, -1) + normalizedPath;\n}\n\n/**\n * Parses a registered pattern into {@link RouteSegment}s and derives its\n * ambiguity key.\n *\n * @param pattern - The pattern string, e.g. `\"/data/rows/:sel\"`.\n * @returns The compiled pattern.\n * @throws If `\"*\"` appears anywhere but the final segment.\n */\nexport function compilePattern(pattern: string): CompiledPattern {\n const normalized = normalizePath(pattern);\n const rawSegments = splitPath(normalized);\n\n const segments: RouteSegment[] = rawSegments.map((raw, i) => {\n if (raw === \"*\") {\n if (i !== rawSegments.length - 1) {\n throw new Error(`RoutePattern: \"*\" is only valid as the final segment of \"${pattern}\"`);\n }\n\n return { kind: \"catchAll\", value: \"\" };\n }\n\n if (raw.startsWith(\":\")) {\n return { kind: \"param\", value: raw.slice(1) };\n }\n\n return { kind: \"static\", value: raw };\n });\n\n const key = segments\n .map((segment) => segment.kind === \"static\" ? segment.value : segment.kind === \"param\" ? \":\" : \"*\")\n .join(\"/\");\n\n return { pattern: normalized, key, segments };\n}\n\n/**\n * Returns the extracted params when `segments` match `compiled`, or `null`\n * when they don't. A trailing `catchAll` segment matches zero or more\n * remaining segments; every other kind requires an exact segment count.\n * Captured `:param` values run through `decodeURIComponent`, falling back to\n * the raw segment text on a malformed escape.\n *\n * @param compiled - The compiled pattern to match against.\n * @param segments - The candidate path's segments (from {@link splitPath}).\n * @returns The extracted params, or `null` when there is no match.\n */\nexport function matchPattern(compiled: CompiledPattern, segments: string[]): Record<string, string> | null {\n const patternSegments = compiled.segments;\n const isCatchAll = patternSegments.length > 0 && patternSegments.at(-1)!.kind === \"catchAll\";\n const staticLength = isCatchAll ? patternSegments.length - 1 : patternSegments.length;\n\n if (isCatchAll ? segments.length < staticLength : segments.length !== staticLength) {\n return null;\n }\n\n const params: Record<string, string> = {};\n\n for (let i = 0; i < staticLength; i += 1) {\n const patternSegment = patternSegments[i];\n const value = segments[i];\n\n if (patternSegment.kind === \"static\") {\n if (patternSegment.value !== value) {\n return null;\n }\n } else if (patternSegment.kind === \"param\") {\n params[patternSegment.value] = decodeSegment(value);\n }\n }\n\n return params;\n}\n\n/**\n * Decodes a captured path segment, falling back to the raw text when it\n * carries a malformed percent-escape.\n *\n * @param value - The raw segment text.\n * @returns The decoded value, or `value` unchanged on a decode failure.\n */\nfunction decodeSegment(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\n/** Rank of each real segment kind: higher wins a specificity tie-break. */\nconst KIND_RANK: Record<SegmentKind, number> = { static: 2, param: 1, catchAll: 0 };\n\n/**\n * Rank of position `i` in `segments`. Reaching the end of the pattern (`i` at\n * or past its length) outranks every real segment kind — see\n * {@link selectPattern}.\n *\n * @param segments - The pattern's segments.\n * @param i - The position to rank.\n * @returns The rank at that position.\n */\nfunction rankAt(segments: readonly RouteSegment[], i: number): number {\n return i >= segments.length ? 3 : KIND_RANK[segments[i].kind];\n}\n\n/**\n * Returns the highest-ranked pattern in `compiled` that matches `path`, or\n * `null` when none match. Patterns are compared segment by segment from the\n * left via {@link rankAt}; the first position where two matching patterns\n * differ decides the winner. Two patterns can never tie on every position —\n * that would mean identical ambiguity keys, which the route table (see\n * `Router`) forbids. Registration order never affects the result.\n *\n * @param compiled - The candidate compiled patterns.\n * @param path - The normalized path to match.\n * @returns The winning pattern and its extracted params, or `null`.\n */\nexport function selectPattern<T extends CompiledPattern>(\n compiled: readonly T[],\n path: string,\n): { compiled: T; params: Record<string, string> } | null {\n const segments = splitPath(path);\n\n let best: T | null = null;\n let bestParams: Record<string, string> | null = null;\n\n for (const candidate of compiled) {\n const params = matchPattern(candidate, segments);\n\n if (params === null) {\n continue;\n }\n\n if (best === null || isMoreSpecific(candidate.segments, best.segments)) {\n best = candidate;\n bestParams = params;\n }\n }\n\n return best === null ? null : { compiled: best, params: bestParams! };\n}\n\n/**\n * Whether `a` outranks `b` by {@link rankAt} at the first position where they\n * differ.\n *\n * @param a - The candidate pattern's segments.\n * @param b - The current best pattern's segments.\n * @returns `true` when `a` is more specific than `b`.\n */\nfunction isMoreSpecific(a: readonly RouteSegment[], b: readonly RouteSegment[]): boolean {\n const length = Math.max(a.length, b.length);\n\n for (let i = 0; i < length; i += 1) {\n const rankA = rankAt(a, i);\n const rankB = rankAt(b, i);\n\n if (rankA !== rankB) {\n return rankA > rankB;\n }\n }\n\n return false;\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from '~/core/DOM.js';\nimport { ListenerBag } from '~/core/ListenerBag.js';\nimport { compilePattern, normalizePath, splitPath, splitFragment, selectPattern, normalizeBase, stripBase, joinBase, type CompiledPattern } from '~/router/RoutePattern.js';\n\n/** Params extracted from a matched pattern's `:name` segments. */\nexport type RouteParams = Record<string, string>;\n\n/** A registered route's callback: drives whatever it fronts, never builds it. */\nexport type RouteHandler = (params: RouteParams, path: string, fragment: string) => void;\n\n/** The events a {@link Router} emits. */\nexport type RouterEvent = \"navigate\" | \"nomatch\";\n\n/** Where a {@link Router} reads and writes the route: the URL hash, or the path. */\nexport type RouterMode = \"hash\" | \"history\";\n\n/** The pattern and params a navigation resolved to. */\nexport interface RouteMatch {\n /** The pattern that won, as registered. */\n pattern: string;\n params: RouteParams;\n /** The normalized path that was matched. */\n path: string;\n /** The URL fragment without its `\"#\"`, or `\"\"` when there is none. Always `\"\"` in hash mode. */\n fragment: string;\n}\n\n/** Construction options for {@link Router}. */\nexport interface RouterOptions {\n /** Defaults to `\"hash\"`. */\n mode?: RouterMode;\n /** Path prefix the site is served under, e.g. `\"/typescript-ui/\"`. History mode only; defaults to `\"/\"`. */\n base?: string;\n /** Patterns to `register` at construction, keyed by pattern string. */\n routes?: Record<string, RouteHandler>;\n listeners?: Partial<{\n navigate: (match: RouteMatch) => void;\n nomatch: (path: string) => void;\n }>;\n}\n\n/** A registered route: its compiled pattern plus the handler it drives. */\ntype CompiledRoute = CompiledPattern & { handler: RouteHandler };\n\n/**\n * Maps the URL hash or path to a single top-level app section. Patterns are\n * registered with {@link register} (e.g. `\"/data/rows/:sel\"`); on a\n * navigation, the router selects the most specific matching pattern, extracts\n * its `:param` values, and calls that pattern's handler — the handler drives\n * components that already exist, it never builds them.\n *\n * {@link start} reads the current hash or path, applies the matching route\n * synchronously, then installs the `hashchange` (or, in History mode,\n * `popstate`) listener; call it once the app has built its component tree\n * and before the first layout pass runs, so the routed section is already\n * selected when that pass runs. {@link stop} removes the listener.\n *\n * It is a plain class (no DOM element, so not `callable()`-wrapped) — it\n * follows the shape of a data store: an options bag, a private listener bag,\n * and typed `on` / `off` / `emit` forwarders.\n *\n * @category Core\n */\nexport class Router {\n\n private _routes: Map<string, CompiledRoute> = new Map();\n private _listeners: ListenerBag<RouterEvent> = new ListenerBag<RouterEvent>();\n private _started: boolean = false;\n // Set once in applyOptions and never reassigned after — construction-only,\n // like the compiled route table. Not `readonly`: strictPropertyInitialization\n // rejects a readonly field assigned from a method the constructor merely calls.\n private _mode!: RouterMode;\n private _base!: string;\n\n // Stable references so add/remove pair up; each delegates to a named method.\n private readonly _onHashChange: () => void = () => this.handleHashChange();\n private readonly _onPopState: () => void = () => this.handlePopState();\n\n /**\n * @param options - Routes and listeners to register at construction.\n */\n constructor(options?: RouterOptions) {\n this.applyOptions(options ?? {});\n }\n\n /**\n * Registers a pattern's handler. Re-registering the exact same pattern\n * string replaces its handler silently. Registering a *different*\n * pattern string that collides with an already-registered one on\n * specificity (e.g. `\"/users/:id\"` and `\"/users/:name\"`) replaces it too,\n * but logs a warning naming both patterns — that collision usually\n * signals an authoring mistake.\n *\n * @param pattern - The route pattern, e.g. `\"/data/rows/:sel\"`.\n * @param handler - Called with the extracted params and the normalized\n * path when this pattern wins a navigation.\n * @returns This router, for chaining.\n */\n register(pattern: string, handler: RouteHandler): this {\n const compiled = compilePattern(pattern);\n const existing = this._routes.get(compiled.key);\n\n if (existing !== undefined && existing.pattern !== compiled.pattern) {\n console.warn(`Router: \"${existing.pattern}\" and \"${compiled.pattern}\" have the same specificity; \"${compiled.pattern}\" replaces it.`);\n }\n\n this._routes.set(compiled.key, { ...compiled, handler });\n\n return this;\n }\n\n /**\n * Reads the current hash or path, applies the matching route\n * synchronously, then installs the `hashchange` (hash mode) or\n * `popstate` (History mode) listener. Calling `start()` again on an\n * already-started router logs a warning and is otherwise a no-op — it\n * does not install a second listener.\n *\n * @returns This router, for chaining.\n */\n start(): this {\n if (this._started) {\n console.warn(`Router: start() called on an already-started router; ignoring.`);\n\n return this;\n }\n\n this._started = true;\n this.applyCurrentRoute();\n\n if (this._mode === \"history\") {\n DOM.sink.addListener(DOM.source.getWindow(), \"popstate\", this._onPopState);\n } else {\n DOM.sink.addListener(DOM.source.getWindow(), \"hashchange\", this._onHashChange);\n }\n\n return this;\n }\n\n /**\n * Removes the `hashchange` (hash mode) or `popstate` (History mode)\n * listener. Safe to call when never started, or more than once.\n *\n * @returns This router, for chaining.\n */\n stop(): this {\n if (!this._started) {\n return this;\n }\n\n if (this._mode === \"history\") {\n DOM.sink.removeListener(DOM.source.getWindow(), \"popstate\", this._onPopState);\n } else {\n DOM.sink.removeListener(DOM.source.getWindow(), \"hashchange\", this._onHashChange);\n }\n\n this._started = false;\n\n return this;\n }\n\n /**\n * Navigates to `path` — pushing a history entry, or replacing the\n * current one when `options.replace` is `true`. In hash mode this writes\n * the hash, discarding any `#fragment` in `path` (the `#` is already\n * spent on the route); in History mode this writes `location.pathname`\n * and `location.hash` via `pushState` / `replaceState` and — since\n * neither fires an event — applies the matching route itself. Either\n * way, navigating to the path (and, in History mode, fragment) already\n * current is a same-value write: no history entry is written and no\n * handler re-runs.\n *\n * @param path - The path to navigate to, e.g. `\"/settings\"` or, in\n * History mode, `\"/settings#section\"`.\n * @param options - `replace` to replace the current history entry instead\n * of pushing a new one.\n * @returns This router, for chaining.\n */\n navigate(path: string, options?: { replace?: boolean }): this {\n const split = splitFragment(path);\n\n if (this._mode === \"hash\") {\n const segments = splitPath(normalizePath(split.path));\n const hash = \"#/\" + segments.map((segment) => encodeURIComponent(segment)).join(\"/\");\n\n if (options?.replace === true) {\n DOM.sink.replaceLocationHash(hash);\n } else {\n DOM.sink.setLocationHash(hash);\n }\n\n return this;\n }\n\n const target = normalizePath(split.path);\n const fragment = split.fragment;\n\n if (target === this.getPath() && fragment === this.getFragment()) {\n return this;\n }\n\n const url = this.getHref(fragment === \"\" ? target : `${target}#${fragment}`);\n\n if (options?.replace === true) {\n DOM.sink.replaceHistoryPath(url);\n } else {\n DOM.sink.pushHistoryPath(url);\n }\n\n this.applyCurrentRoute(); // pushState/replaceState fire no event; apply it ourselves\n\n return this;\n }\n\n /**\n * The href an `<a>` for `path` should carry, in this router's mode and\n * base: a `\"#/…\"` fragment in hash mode, a base-joined path in History\n * mode. Each segment is percent-encoded. A `#fragment` in `path` is\n * dropped first and, in History mode only, re-appended verbatim\n * (unencoded, so it keeps matching a heading `id`) after the encoded\n * path — hash mode has nowhere to put it, since its own `#` is already\n * spent on the route.\n *\n * @param path - The route path to format, e.g. `\"/guide/installation\"`\n * or, in History mode, `\"/guide/installation#section\"`.\n * @returns The formatted href.\n */\n getHref(path: string): string {\n const split = splitFragment(path);\n const segments = splitPath(normalizePath(split.path)).map((segment) => encodeURIComponent(segment));\n const encodedPath = \"/\" + segments.join(\"/\");\n\n if (this._mode === \"hash\") {\n return \"#\" + encodedPath;\n }\n\n const href = joinBase(this._base, encodedPath);\n\n return split.fragment === \"\" ? href : `${href}#${split.fragment}`;\n }\n\n /**\n * The route path for `href`, or — with no argument — for the current\n * URL. The inverse of {@link getHref}: percent-encoded segments are\n * decoded, and in History mode the base is stripped first and any\n * `#fragment` is split off before normalizing (see {@link getFragment}\n * to read it).\n *\n * @param href - The href to parse; defaults to the current hash (hash\n * mode) or `location.pathname` (History mode), read through the DOM seam.\n * @returns The normalized, decoded path, without a fragment.\n */\n getPath(href?: string): string {\n if (this._mode === \"hash\") {\n const raw = href ?? DOM.source.getLocationHash();\n\n return this.decodePath(normalizePath(raw));\n }\n\n const raw = href ?? DOM.source.getLocationPathname();\n\n return this.decodePath(stripBase(this._base, splitFragment(raw).path));\n }\n\n /**\n * The fragment for `href`, or — with no argument — for the current URL,\n * without its leading `\"#\"`. Always `\"\"` in hash mode, since the `#`\n * there is already spent on the route.\n *\n * @param href - The href to parse; defaults to the current\n * `location.hash`, read through the DOM seam.\n * @returns The fragment, or `\"\"` when there is none.\n */\n getFragment(href?: string): string {\n if (this._mode === \"hash\") {\n return \"\";\n }\n\n if (href !== undefined) {\n return splitFragment(href).fragment;\n }\n\n const hash = DOM.source.getLocationHash();\n\n return hash.startsWith(\"#\") ? hash.slice(1) : hash;\n }\n\n /**\n * Decodes each percent-encoded segment of an already-normalized path,\n * falling back to the raw segment text on a malformed escape.\n *\n * @param path - The normalized path to decode.\n * @returns The decoded path.\n */\n private decodePath(path: string): string {\n const segments = splitPath(path).map((segment) => {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n });\n\n return \"/\" + segments.join(\"/\");\n }\n\n on(event: \"navigate\", listener: (match: RouteMatch) => void): this;\n on(event: \"nomatch\", listener: (path: string) => void): this;\n\n /**\n * Subscribes a listener to a router event. Listeners fire in\n * registration order.\n *\n * @param event - The event to listen for.\n * @param listener - The callback to invoke.\n * @returns This router, for chaining.\n */\n on(event: RouterEvent, listener: Function): this {\n this._listeners.add(event, listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered listener. No-op if it was never\n * registered for that event.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The exact callback reference to remove.\n * @returns This router, for chaining.\n */\n off(event: RouterEvent, listener: Function): this {\n this._listeners.remove(event, listener);\n\n return this;\n }\n\n /**\n * Notifies all listeners registered for an event, in registration order.\n *\n * @param event - The event to emit.\n * @param payload - The value passed to each listener.\n */\n protected emit(event: RouterEvent, payload: unknown): void {\n this._listeners.fire(event, payload);\n }\n\n /**\n * Reads the current hash or path and calls the most specific matching\n * pattern's handler, emitting `\"navigate\"` — or emits `\"nomatch\"` when\n * nothing matches. Shared by {@link start}, the `hashchange` listener,\n * the `popstate` listener, and History-mode {@link navigate}.\n */\n private applyCurrentRoute(): void {\n const path = this.getPath();\n const fragment = this.getFragment();\n const result = selectPattern(Array.from(this._routes.values()), path);\n\n if (result === null) {\n this.emit(\"nomatch\", path);\n\n return;\n }\n\n const match: RouteMatch = { pattern: result.compiled.pattern, params: result.params, path, fragment };\n\n result.compiled.handler(result.params, path, fragment);\n this.emit(\"navigate\", match);\n }\n\n /**\n * Applies an {@link RouterOptions} bag: sets `mode` and `base`, registers\n * `routes`, then wires `listeners`. Called from the constructor body,\n * after every field initializer has run.\n *\n * @param options - The options bag to apply.\n */\n protected applyOptions(options: RouterOptions): void {\n this._mode = options.mode ?? \"hash\";\n this._base = normalizeBase(options.base ?? \"/\");\n\n if (options.routes !== undefined) {\n for (const pattern of Object.keys(options.routes)) {\n this.register(pattern, options.routes[pattern]);\n }\n }\n\n if (options.listeners !== undefined) {\n for (const event of Object.keys(options.listeners) as RouterEvent[]) {\n const listener = options.listeners[event];\n\n if (listener !== undefined) {\n this._listeners.add(event, listener);\n }\n }\n }\n }\n\n private handleHashChange(): void {\n this.applyCurrentRoute();\n }\n\n private handlePopState(): void {\n this.applyCurrentRoute();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./DOM-
|
|
2
|
-
//# sourceMappingURL=
|
|
1
|
+
import{t as e}from"./DOM-BeR95tE8.js";import{t}from"./Component-CHTzJxEf.js";import{t as n}from"./VirtualScroller-BPy6KmSX.js";var r=2,VirtualRowView=class extends t{_rowPool=[];_boundIndices=[];_rowGeom=[];_rowDisplayed=[];_scroller=null;initScroller(e){this._scroller=new n(this,e,()=>this.onScrollerTick());for(let e of this._scroller.ownedHandles())this.trackHandle(e)}onScrollerTick(){this.renderWindow()}onPoolRowAdded(){}setScrollX(e){return this._scroller?.resetWheelEase(),this._scroller?.setScrollX(e),this}setScrollY(e){return this._scroller?.resetWheelEase(),this._scroller?.setScrollY(e),this}computeVisibleWindow(e,t,n){let i=this.getRowHeight(),a=Math.max(0,Math.floor(e/i)-r),o=Math.min(n-1,Math.ceil((e+t)/i)+r);return{firstRow:a,lastRow:o,windowSize:o-a+1>0?o-a+1:0}}computePoolTarget(e,t,n){return Math.min(n,Math.max(e,Math.ceil(t/this.getRowHeight())+2*r+2))}computePageSize(){let e=this.getRowHeight();return Math.max(1,Math.floor((this.getHeight()||e)/e))}growRowPool(t){if(!this._scroller||this._rowPool.length>=t)return;let n=this._scroller.getRowsContainer(),r=e.sink.createDocumentFragment();for(;this._rowPool.length<t;){let t=this.createPoolRow(),n=t.getElement(!0);e.sink.appendChild(r,n),t.setY(0),t.setWillChange(`transform`),this._rowPool.push(t),this._boundIndices.push(-1),this._rowGeom.push(null),this._rowDisplayed.push(!1),this.onPoolRowAdded()}e.sink.appendChild(n,r),e.sink.release(r)}positionRow(e,t,n){let r=this._rowPool[e],i=this.getRowHeight(),a=this._rowGeom[e],o=!a||a.ty!==t||a.w!==n||a.h!==i;return o&&(r.setAutoCommitStyle(!1),r.setX(0),r.setTranslate(0,t),r.setWidth(n),r.setHeight(i),r.setAutoCommitStyle(!0),this._rowGeom[e]={ty:t,w:n,h:i}),this._rowDisplayed[e]||(r.setDisplayed(!0),this._rowDisplayed[e]=!0),o}hideExcessPoolRows(e){for(let t=e;t<this._rowPool.length;t++)this._rowDisplayed[t]&&(this._rowPool[t].setDisplayed(!1),this._rowDisplayed[t]=!1),this._boundIndices[t]=-1,this._rowGeom[t]=null}invalidateGeom(){for(let e=0;e<this._rowGeom.length;e++)this._rowGeom[e]=null}scrollRowIntoView(e){if(e<0||!this._scroller)return;let t=this.getRowHeight(),n=e*t,r=n+t,i=this._scroller.getScrollY(),a=this.getHeight(),o=i+a,s=i;n<i?s=n:r>o&&(s=r-a),s!==i&&this.setScrollY(s)}};function selectionsEqual(e,t){if(e.size!==t.size)return!1;for(let n of e)if(!t.has(n))return!1;return!0}export{VirtualRowView as n,selectionsEqual as t};
|
|
2
|
+
//# sourceMappingURL=selectionsEqual-2PJrcimg.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualRowView-C18j90n5.js","names":[],"sources":["../../src/typescript/lib/component/shared/VirtualRowView.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { VirtualScroller } from \"~/component/container/VirtualScroller.js\";\n\n/** Number of off-screen rows to render above and below the visible viewport. */\nconst SCROLL_BUFFER = 2;\n\n/**\n * Shared transform-windowed virtual-scroll base for the data views —\n * `table/Body` and `tree/Tree` are its only two subclasses. It owns the\n * recycled row pool (`_rowPool` and the parallel `_boundIndices` / `_rowGeom` /\n * `_rowDisplayed` bookkeeping arrays), the {@link VirtualScroller} wiring, and\n * the window / pool-growth / geometry reconciliation primitives each subclass's\n * render pass composes.\n *\n * Only two things genuinely diverge between the two consumers, so only those\n * are hooks:\n *\n * - **Row height** — `Body` derives it live from the theme line box; `Tree`\n * uses a fixed constant. Read through {@link getRowHeight} on every call so a\n * live theme change is honoured.\n * - **Row construction** — the pool-row scaffolding (fragment batching, `setY(0)`\n * pin, `will-change` promotion, parallel-array bookkeeping) is identical; only\n * the row object each subclass builds differs. {@link createPoolRow} returns a\n * fully-constructed, un-appended row and the base owns the rest.\n *\n * The per-frame render pass itself ({@link renderWindow}) stays subclass-specific\n * because the content-width derivation genuinely diverges; the base exposes the\n * shared primitives it calls ({@link computeVisibleWindow},\n * {@link computePoolTarget}, {@link growRowPool}, {@link positionRow},\n * {@link hideExcessPoolRows}).\n *\n * @typeParam TRow - The concrete pooled row component type.\n * @typeParam TOptions - The subclass's options bag.\n *\n * @internal Not barrel-exported; the two subclasses are the only consumers.\n */\nabstract class VirtualRowView<\n TRow extends Component,\n TOptions extends ComponentOptions = ComponentOptions,\n> extends Component<TOptions> {\n\n protected _rowPool : TRow[] = [];\n protected _boundIndices : number[] = [];\n protected _rowGeom : Array<{ ty: number, w: number, h: number } | null> = [];\n protected _rowDisplayed : boolean[] = [];\n protected _scroller : VirtualScroller | null = null;\n\n /**\n * Returns the height in pixels of a single row. Read on every window /\n * geometry calculation, so a subclass that recomputes it (e.g. on a theme\n * change) reflects the new value immediately.\n */\n protected abstract getRowHeight(): number;\n\n /**\n * Constructs one pool row, fully wired but not yet appended to the\n * rows container — the base's {@link growRowPool} owns the append, the\n * `setY(0)` pin, the `will-change` promotion, and the parallel-array\n * bookkeeping.\n */\n protected abstract createPoolRow(): TRow;\n\n /**\n * Recomputes and reconciles the visible row window against the current\n * scroll position and dataset. Subclass-specific because the content-width\n * derivation diverges; both implementations compose the shared primitives\n * on this base.\n */\n protected abstract renderWindow(): void;\n\n /**\n * Constructs the {@link VirtualScroller} for this view and tracks its\n * container handles so they are released with the component. The scroller's\n * onScroll hook is routed through {@link onScrollerTick}.\n *\n * @param element - This view's initialised element handle.\n */\n protected initScroller(element: Handle): void {\n this._scroller = new VirtualScroller(this, element, () => this.onScrollerTick());\n\n // Track the scroller's created container handles so they are released\n // with this view (on destructor or GC); the scroller is not a Component.\n for (const handle of this._scroller.ownedHandles()) {\n this.trackHandle(handle);\n }\n }\n\n /**\n * Invoked on every scroller tick. Default behaviour re-renders the window;\n * `Body` overrides it to additionally emit its scroll events.\n */\n protected onScrollerTick(): void {\n this.renderWindow();\n }\n\n /**\n * Hook invoked once per pool slot added by {@link growRowPool}, after the\n * base parallel arrays have been extended. Default is a no-op; `Body`\n * overrides it to extend its own `_cellGeom` array in lockstep.\n */\n protected onPoolRowAdded(): void {\n // Default no-op; subclasses that own extra parallel arrays override.\n }\n\n /**\n * Sets the JS-controlled horizontal scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param x - The new scroll position in pixels.\n */\n setScrollX(x: number): this {\n this._scroller?.resetWheelEase();\n this._scroller?.setScrollX(x);\n\n return this;\n }\n\n /**\n * Sets the JS-controlled vertical scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param y - The new scroll position in pixels.\n */\n setScrollY(y: number): this {\n this._scroller?.resetWheelEase();\n this._scroller?.setScrollY(y);\n\n return this;\n }\n\n /**\n * Computes the `[firstRow, lastRow]` data-index window visible in the\n * current viewport, padded by `SCROLL_BUFFER` on each side and clamped to\n * the dataset bounds.\n *\n * @param scrollY - The current scroll offset in pixels.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The `firstRow` / `lastRow` data indices and the number of rows in the window.\n */\n protected computeVisibleWindow(scrollY: number, visibleHeight: number, totalRows: number): { firstRow: number, lastRow: number, windowSize: number } {\n const rowHeight = this.getRowHeight();\n const firstRow = Math.max(0, Math.floor(scrollY / rowHeight) - SCROLL_BUFFER);\n const lastRow = Math.min(\n totalRows - 1,\n Math.ceil((scrollY + visibleHeight) / rowHeight) + SCROLL_BUFFER\n );\n const windowSize = lastRow - firstRow + 1 > 0 ? lastRow - firstRow + 1 : 0;\n\n return { firstRow, lastRow, windowSize };\n }\n\n /**\n * Computes the row-pool target size: the max possible window for the\n * current viewport, not just the current windowSize. windowSize shrinks\n * near the top/bottom edges of the dataset because firstRow clamps to 0\n * (and lastRow to totalRows-1); growing only to windowSize would force\n * regrowth mid-scroll once the user passes a viewport-edge boundary. Pre-\n * growing pays the per-row first-layout cost once.\n *\n * @param windowSize - The current visible-window size.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The pool target size.\n */\n protected computePoolTarget(windowSize: number, visibleHeight: number, totalRows: number): number {\n return Math.min(\n totalRows,\n Math.max(\n windowSize,\n Math.ceil(visibleHeight / this.getRowHeight()) + 2 * SCROLL_BUFFER + 2\n )\n );\n }\n\n /**\n * Computes the number of whole rows a page-nav keystroke should move by:\n * one viewport height, floored to at least one row.\n *\n * @returns The page size in rows.\n */\n protected computePageSize(): number {\n const rowHeight = this.getRowHeight();\n\n return Math.max(1, Math.floor((this.getHeight() || rowHeight) / rowHeight));\n }\n\n /**\n * Grows the row pool up to `poolTarget`, batching new row elements through\n * a {@link DocumentFragment} so the live rows container sees a single\n * append instead of N. Each new slot pins its static top to 0, promotes it\n * to its own compositor layer, and extends the parallel bookkeeping arrays\n * in lockstep.\n *\n * @param poolTarget - The target pool size.\n */\n protected growRowPool(poolTarget: number): void {\n if (!this._scroller || this._rowPool.length >= poolTarget) {\n return;\n }\n\n const rowsContainer = this._scroller.getRowsContainer();\n const growFragment = DOM.sink.createDocumentFragment();\n\n while (this._rowPool.length < poolTarget) {\n const row = this.createPoolRow();\n const rowEl = row.getElement(true)!;\n\n DOM.sink.appendChild(growFragment, rowEl);\n\n // Pin row's static top to 0 once. Per-frame Y offset comes from\n // translateY, which is composite-only (avoids layout/paint per\n // scroll tick).\n row.setY(0);\n\n // Pre-promote pooled rows to their own compositor layer so the first\n // scroll-driven translate doesn't pay a layer-creation cost.\n row.setWillChange(\"transform\");\n\n this._rowPool.push(row);\n this._boundIndices.push(-1);\n this._rowGeom.push(null);\n this._rowDisplayed.push(false);\n this.onPoolRowAdded();\n }\n\n DOM.sink.appendChild(rowsContainer, growFragment);\n DOM.sink.release(growFragment);\n }\n\n /**\n * Positions the pool slot at `slot` to `targetY` and sizes it to `rowWidth`,\n * writing the translate/size only when the cached geometry differs from the\n * target, and toggling the row displayed on the false→true edge.\n *\n * @param slot - The pool-slot index.\n * @param targetY - The row's translate-Y offset in pixels.\n * @param rowWidth - The row's width in pixels.\n * @returns `true` when the geometry changed (the subclass may need to re-lay\n * out the row's children), `false` when it was already at the target.\n */\n protected positionRow(slot: number, targetY: number, rowWidth: number): boolean {\n const row = this._rowPool[slot];\n const rowHeight = this.getRowHeight();\n const prev = this._rowGeom[slot];\n const geomChanged = !prev || prev.ty !== targetY || prev.w !== rowWidth || prev.h !== rowHeight;\n\n if (geomChanged) {\n row.setAutoCommitStyle(false);\n row.setX(0);\n row.setTranslate(0, targetY);\n row.setWidth(rowWidth);\n row.setHeight(rowHeight);\n row.setAutoCommitStyle(true);\n this._rowGeom[slot] = { ty: targetY, w: rowWidth, h: rowHeight };\n }\n\n if (!this._rowDisplayed[slot]) {\n row.setDisplayed(true);\n this._rowDisplayed[slot] = true;\n }\n\n return geomChanged;\n }\n\n /**\n * Hides pool slots whose index falls outside the visible window and\n * clears their cached binding so the next bind triggers a full rebuild.\n *\n * @param windowSize - The number of pool slots currently in use.\n */\n protected hideExcessPoolRows(windowSize: number): void {\n for (let i = windowSize; i < this._rowPool.length; i++) {\n if (this._rowDisplayed[i]) {\n this._rowPool[i].setDisplayed(false);\n this._rowDisplayed[i] = false;\n }\n this._boundIndices[i] = -1;\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Clears the cached row geometry so the next render re-applies positions and\n * sizes for every slot. `Body` overrides this to additionally clear its\n * per-cell geometry cache.\n */\n protected invalidateGeom(): void {\n for (let i = 0; i < this._rowGeom.length; i++) {\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Scrolls the view so the row at `index` is fully visible, without moving\n * the viewport unless necessary. Delegates through {@link VirtualScroller}\n * so the header translate + scrollbar thumb stay in sync.\n *\n * @param index - The data index of the row to reveal. A negative index is a\n * no-op (the row is not in the current view).\n */\n protected scrollRowIntoView(index: number): void {\n if (index < 0 || !this._scroller) {\n return;\n }\n\n const rowHeight = this.getRowHeight();\n const top = index * rowHeight;\n const bottom = top + rowHeight;\n const scrollTop = this._scroller.getScrollY();\n const viewportHeight = this.getHeight();\n const visibleBottom = scrollTop + viewportHeight;\n\n let target = scrollTop;\n if (top < scrollTop) {\n target = top;\n } else if (bottom > visibleBottom) {\n target = bottom - viewportHeight;\n }\n if (target !== scrollTop) {\n this.setScrollY(target);\n }\n }\n}\n\nexport { VirtualRowView };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selectionsEqual-2PJrcimg.js","names":[],"sources":["../../src/typescript/lib/component/shared/VirtualRowView.ts","../../src/typescript/lib/component/shared/selectionsEqual.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { VirtualScroller } from \"~/component/container/VirtualScroller.js\";\n\n/** Number of off-screen rows to render above and below the visible viewport. */\nconst SCROLL_BUFFER = 2;\n\n/**\n * Shared transform-windowed virtual-scroll base for the data views —\n * `table/Body` and `tree/Tree` are its only two subclasses. It owns the\n * recycled row pool (`_rowPool` and the parallel `_boundIndices` / `_rowGeom` /\n * `_rowDisplayed` bookkeeping arrays), the {@link VirtualScroller} wiring, and\n * the window / pool-growth / geometry reconciliation primitives each subclass's\n * render pass composes.\n *\n * Only two things genuinely diverge between the two consumers, so only those\n * are hooks:\n *\n * - **Row height** — `Body` derives it live from the theme line box; `Tree`\n * uses a fixed constant. Read through {@link getRowHeight} on every call so a\n * live theme change is honoured.\n * - **Row construction** — the pool-row scaffolding (fragment batching, `setY(0)`\n * pin, `will-change` promotion, parallel-array bookkeeping) is identical; only\n * the row object each subclass builds differs. {@link createPoolRow} returns a\n * fully-constructed, un-appended row and the base owns the rest.\n *\n * The per-frame render pass itself ({@link renderWindow}) stays subclass-specific\n * because the content-width derivation genuinely diverges; the base exposes the\n * shared primitives it calls ({@link computeVisibleWindow},\n * {@link computePoolTarget}, {@link growRowPool}, {@link positionRow},\n * {@link hideExcessPoolRows}).\n *\n * @typeParam TRow - The concrete pooled row component type.\n * @typeParam TOptions - The subclass's options bag.\n *\n * @internal Not barrel-exported; the two subclasses are the only consumers.\n */\nabstract class VirtualRowView<\n TRow extends Component,\n TOptions extends ComponentOptions = ComponentOptions,\n> extends Component<TOptions> {\n\n protected _rowPool : TRow[] = [];\n protected _boundIndices : number[] = [];\n protected _rowGeom : Array<{ ty: number, w: number, h: number } | null> = [];\n protected _rowDisplayed : boolean[] = [];\n protected _scroller : VirtualScroller | null = null;\n\n /**\n * Returns the height in pixels of a single row. Read on every window /\n * geometry calculation, so a subclass that recomputes it (e.g. on a theme\n * change) reflects the new value immediately.\n */\n protected abstract getRowHeight(): number;\n\n /**\n * Constructs one pool row, fully wired but not yet appended to the\n * rows container — the base's {@link growRowPool} owns the append, the\n * `setY(0)` pin, the `will-change` promotion, and the parallel-array\n * bookkeeping.\n */\n protected abstract createPoolRow(): TRow;\n\n /**\n * Recomputes and reconciles the visible row window against the current\n * scroll position and dataset. Subclass-specific because the content-width\n * derivation diverges; both implementations compose the shared primitives\n * on this base.\n */\n protected abstract renderWindow(): void;\n\n /**\n * Constructs the {@link VirtualScroller} for this view and tracks its\n * container handles so they are released with the component. The scroller's\n * onScroll hook is routed through {@link onScrollerTick}.\n *\n * @param element - This view's initialised element handle.\n */\n protected initScroller(element: Handle): void {\n this._scroller = new VirtualScroller(this, element, () => this.onScrollerTick());\n\n // Track the scroller's created container handles so they are released\n // with this view (on destructor or GC); the scroller is not a Component.\n for (const handle of this._scroller.ownedHandles()) {\n this.trackHandle(handle);\n }\n }\n\n /**\n * Invoked on every scroller tick. Default behaviour re-renders the window;\n * `Body` overrides it to additionally emit its scroll events.\n */\n protected onScrollerTick(): void {\n this.renderWindow();\n }\n\n /**\n * Hook invoked once per pool slot added by {@link growRowPool}, after the\n * base parallel arrays have been extended. Default is a no-op; `Body`\n * overrides it to extend its own `_cellGeom` array in lockstep.\n */\n protected onPoolRowAdded(): void {\n // Default no-op; subclasses that own extra parallel arrays override.\n }\n\n /**\n * Sets the JS-controlled horizontal scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param x - The new scroll position in pixels.\n */\n setScrollX(x: number): this {\n this._scroller?.resetWheelEase();\n this._scroller?.setScrollX(x);\n\n return this;\n }\n\n /**\n * Sets the JS-controlled vertical scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param y - The new scroll position in pixels.\n */\n setScrollY(y: number): this {\n this._scroller?.resetWheelEase();\n this._scroller?.setScrollY(y);\n\n return this;\n }\n\n /**\n * Computes the `[firstRow, lastRow]` data-index window visible in the\n * current viewport, padded by `SCROLL_BUFFER` on each side and clamped to\n * the dataset bounds.\n *\n * @param scrollY - The current scroll offset in pixels.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The `firstRow` / `lastRow` data indices and the number of rows in the window.\n */\n protected computeVisibleWindow(scrollY: number, visibleHeight: number, totalRows: number): { firstRow: number, lastRow: number, windowSize: number } {\n const rowHeight = this.getRowHeight();\n const firstRow = Math.max(0, Math.floor(scrollY / rowHeight) - SCROLL_BUFFER);\n const lastRow = Math.min(\n totalRows - 1,\n Math.ceil((scrollY + visibleHeight) / rowHeight) + SCROLL_BUFFER\n );\n const windowSize = lastRow - firstRow + 1 > 0 ? lastRow - firstRow + 1 : 0;\n\n return { firstRow, lastRow, windowSize };\n }\n\n /**\n * Computes the row-pool target size: the max possible window for the\n * current viewport, not just the current windowSize. windowSize shrinks\n * near the top/bottom edges of the dataset because firstRow clamps to 0\n * (and lastRow to totalRows-1); growing only to windowSize would force\n * regrowth mid-scroll once the user passes a viewport-edge boundary. Pre-\n * growing pays the per-row first-layout cost once.\n *\n * @param windowSize - The current visible-window size.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The pool target size.\n */\n protected computePoolTarget(windowSize: number, visibleHeight: number, totalRows: number): number {\n return Math.min(\n totalRows,\n Math.max(\n windowSize,\n Math.ceil(visibleHeight / this.getRowHeight()) + 2 * SCROLL_BUFFER + 2\n )\n );\n }\n\n /**\n * Computes the number of whole rows a page-nav keystroke should move by:\n * one viewport height, floored to at least one row.\n *\n * @returns The page size in rows.\n */\n protected computePageSize(): number {\n const rowHeight = this.getRowHeight();\n\n return Math.max(1, Math.floor((this.getHeight() || rowHeight) / rowHeight));\n }\n\n /**\n * Grows the row pool up to `poolTarget`, batching new row elements through\n * a {@link DocumentFragment} so the live rows container sees a single\n * append instead of N. Each new slot pins its static top to 0, promotes it\n * to its own compositor layer, and extends the parallel bookkeeping arrays\n * in lockstep.\n *\n * @param poolTarget - The target pool size.\n */\n protected growRowPool(poolTarget: number): void {\n if (!this._scroller || this._rowPool.length >= poolTarget) {\n return;\n }\n\n const rowsContainer = this._scroller.getRowsContainer();\n const growFragment = DOM.sink.createDocumentFragment();\n\n while (this._rowPool.length < poolTarget) {\n const row = this.createPoolRow();\n const rowEl = row.getElement(true)!;\n\n DOM.sink.appendChild(growFragment, rowEl);\n\n // Pin row's static top to 0 once. Per-frame Y offset comes from\n // translateY, which is composite-only (avoids layout/paint per\n // scroll tick).\n row.setY(0);\n\n // Pre-promote pooled rows to their own compositor layer so the first\n // scroll-driven translate doesn't pay a layer-creation cost.\n row.setWillChange(\"transform\");\n\n this._rowPool.push(row);\n this._boundIndices.push(-1);\n this._rowGeom.push(null);\n this._rowDisplayed.push(false);\n this.onPoolRowAdded();\n }\n\n DOM.sink.appendChild(rowsContainer, growFragment);\n DOM.sink.release(growFragment);\n }\n\n /**\n * Positions the pool slot at `slot` to `targetY` and sizes it to `rowWidth`,\n * writing the translate/size only when the cached geometry differs from the\n * target, and toggling the row displayed on the false→true edge.\n *\n * @param slot - The pool-slot index.\n * @param targetY - The row's translate-Y offset in pixels.\n * @param rowWidth - The row's width in pixels.\n * @returns `true` when the geometry changed (the subclass may need to re-lay\n * out the row's children), `false` when it was already at the target.\n */\n protected positionRow(slot: number, targetY: number, rowWidth: number): boolean {\n const row = this._rowPool[slot];\n const rowHeight = this.getRowHeight();\n const prev = this._rowGeom[slot];\n const geomChanged = !prev || prev.ty !== targetY || prev.w !== rowWidth || prev.h !== rowHeight;\n\n if (geomChanged) {\n row.setAutoCommitStyle(false);\n row.setX(0);\n row.setTranslate(0, targetY);\n row.setWidth(rowWidth);\n row.setHeight(rowHeight);\n row.setAutoCommitStyle(true);\n this._rowGeom[slot] = { ty: targetY, w: rowWidth, h: rowHeight };\n }\n\n if (!this._rowDisplayed[slot]) {\n row.setDisplayed(true);\n this._rowDisplayed[slot] = true;\n }\n\n return geomChanged;\n }\n\n /**\n * Hides pool slots whose index falls outside the visible window and\n * clears their cached binding so the next bind triggers a full rebuild.\n *\n * @param windowSize - The number of pool slots currently in use.\n */\n protected hideExcessPoolRows(windowSize: number): void {\n for (let i = windowSize; i < this._rowPool.length; i++) {\n if (this._rowDisplayed[i]) {\n this._rowPool[i].setDisplayed(false);\n this._rowDisplayed[i] = false;\n }\n this._boundIndices[i] = -1;\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Clears the cached row geometry so the next render re-applies positions and\n * sizes for every slot. `Body` overrides this to additionally clear its\n * per-cell geometry cache.\n */\n protected invalidateGeom(): void {\n for (let i = 0; i < this._rowGeom.length; i++) {\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Scrolls the view so the row at `index` is fully visible, without moving\n * the viewport unless necessary. Delegates through {@link VirtualScroller}\n * so the header translate + scrollbar thumb stay in sync.\n *\n * @param index - The data index of the row to reveal. A negative index is a\n * no-op (the row is not in the current view).\n */\n protected scrollRowIntoView(index: number): void {\n if (index < 0 || !this._scroller) {\n return;\n }\n\n const rowHeight = this.getRowHeight();\n const top = index * rowHeight;\n const bottom = top + rowHeight;\n const scrollTop = this._scroller.getScrollY();\n const viewportHeight = this.getHeight();\n const visibleBottom = scrollTop + viewportHeight;\n\n let target = scrollTop;\n if (top < scrollTop) {\n target = top;\n } else if (bottom > visibleBottom) {\n target = bottom - viewportHeight;\n }\n if (target !== scrollTop) {\n this.setScrollY(target);\n }\n }\n}\n\nexport { VirtualRowView };\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * Compares two selection sets by membership only — size and element\n * identity, regardless of insertion order.\n *\n * Pure; no DOM, no component state.\n *\n * @typeParam T - The selection identity type.\n * @param a - One selection set.\n * @param b - The other selection set.\n * @returns `true` when both sets have the same size and every member of\n * `a` is present in `b`.\n *\n * @internal Shared by `Tree` and `Body`; not barrel-exported.\n */\nexport function selectionsEqual<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {\n if (a.size !== b.size) {\n return false;\n }\n\n for (const item of a) {\n if (!b.has(item)) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":"+HAQA,IAAM,EAAgB,EAgCP,eAAf,cAGU,CAAoB,CAE1B,SAAgF,CAAC,EACjF,cAA+E,CAAC,EAChF,SAA+E,CAAC,EAChF,cAA+E,CAAC,EAChF,UAA+E,KAgC/E,aAAuB,EAAuB,CAC1C,KAAK,UAAY,IAAI,EAAgB,KAAM,MAAe,KAAK,eAAe,CAAC,EAI/E,IAAK,IAAM,KAAU,KAAK,UAAU,aAAa,EAC7C,KAAK,YAAY,CAAM,CAE/B,CAMA,gBAAiC,CAC7B,KAAK,aAAa,CACtB,CAOA,gBAAiC,CAEjC,CAQA,WAAW,EAAiB,CAIxB,OAHA,KAAK,WAAW,eAAe,EAC/B,KAAK,WAAW,WAAW,CAAC,EAErB,IACX,CAQA,WAAW,EAAiB,CAIxB,OAHA,KAAK,WAAW,eAAe,EAC/B,KAAK,WAAW,WAAW,CAAC,EAErB,IACX,CAYA,qBAA+B,EAAiB,EAAuB,EAA8E,CACjJ,IAAM,EAAY,KAAK,aAAa,EAC9B,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM,EAAU,CAAS,EAAI,CAAa,EACvE,EAAY,KAAK,IACnB,EAAY,EACZ,KAAK,MAAM,EAAU,GAAiB,CAAS,EAAI,CACvD,EAGA,MAAO,CAAE,WAAU,UAAS,WAFT,EAAU,EAAW,EAAI,EAAI,EAAU,EAAW,EAAI,CAElC,CAC3C,CAeA,kBAA4B,EAAoB,EAAuB,EAA2B,CAC9F,OAAO,KAAK,IACR,EACA,KAAK,IACD,EACA,KAAK,KAAK,EAAgB,KAAK,aAAa,CAAC,EAAI,EAAI,EAAgB,CACzE,CACJ,CACJ,CAQA,iBAAoC,CAChC,IAAM,EAAY,KAAK,aAAa,EAEpC,OAAO,KAAK,IAAI,EAAG,KAAK,OAAO,KAAK,UAAU,GAAK,GAAa,CAAS,CAAC,CAC9E,CAWA,YAAsB,EAA0B,CAC5C,GAAI,CAAC,KAAK,WAAa,KAAK,SAAS,QAAU,EAC3C,OAGJ,IAAM,EAAgB,KAAK,UAAU,iBAAiB,EAChD,EAAgB,EAAI,KAAK,uBAAuB,EAEtD,KAAO,KAAK,SAAS,OAAS,GAAY,CACtC,IAAM,EAAQ,KAAK,cAAc,EAC3B,EAAQ,EAAI,WAAW,EAAI,EAEjC,EAAI,KAAK,YAAY,EAAc,CAAK,EAKxC,EAAI,KAAK,CAAC,EAIV,EAAI,cAAc,WAAW,EAE7B,KAAK,SAAS,KAAK,CAAG,EACtB,KAAK,cAAc,KAAK,EAAE,EAC1B,KAAK,SAAS,KAAK,IAAI,EACvB,KAAK,cAAc,KAAK,EAAK,EAC7B,KAAK,eAAe,CACxB,CAEA,EAAI,KAAK,YAAY,EAAe,CAAY,EAChD,EAAI,KAAK,QAAQ,CAAY,CACjC,CAaA,YAAsB,EAAc,EAAiB,EAA2B,CAC5E,IAAM,EAAY,KAAK,SAAS,GAC1B,EAAY,KAAK,aAAa,EAC9B,EAAY,KAAK,SAAS,GAC1B,EAAc,CAAC,GAAQ,EAAK,KAAO,GAAW,EAAK,IAAM,GAAY,EAAK,IAAM,EAiBtF,OAfI,IACA,EAAI,mBAAmB,EAAK,EAC5B,EAAI,KAAK,CAAC,EACV,EAAI,aAAa,EAAG,CAAO,EAC3B,EAAI,SAAS,CAAQ,EACrB,EAAI,UAAU,CAAS,EACvB,EAAI,mBAAmB,EAAI,EAC3B,KAAK,SAAS,GAAQ,CAAE,GAAI,EAAS,EAAG,EAAU,EAAG,CAAU,GAG9D,KAAK,cAAc,KACpB,EAAI,aAAa,EAAI,EACrB,KAAK,cAAc,GAAQ,IAGxB,CACX,CAQA,mBAA6B,EAA0B,CACnD,IAAK,IAAI,EAAI,EAAY,EAAI,KAAK,SAAS,OAAQ,IAC3C,KAAK,cAAc,KACnB,KAAK,SAAS,EAAE,CAAC,aAAa,EAAK,EACnC,KAAK,cAAc,GAAK,IAE5B,KAAK,cAAc,GAAK,GACxB,KAAK,SAAS,GAAK,IAE3B,CAOA,gBAAiC,CAC7B,IAAK,IAAI,EAAI,EAAG,EAAI,KAAK,SAAS,OAAQ,IACtC,KAAK,SAAS,GAAK,IAE3B,CAUA,kBAA4B,EAAqB,CAC7C,GAAI,EAAQ,GAAK,CAAC,KAAK,UACnB,OAGJ,IAAM,EAAiB,KAAK,aAAa,EACnC,EAAiB,EAAQ,EACzB,EAAiB,EAAM,EACvB,EAAiB,KAAK,UAAU,WAAW,EAC3C,EAAiB,KAAK,UAAU,EAChC,EAAiB,EAAY,EAE/B,EAAS,EACT,EAAM,EACN,EAAS,EACF,EAAS,IAChB,EAAS,EAAS,GAElB,IAAW,GACX,KAAK,WAAW,CAAM,CAE9B,CACJ,ECvTA,SAAgB,gBAAmB,EAAmB,EAA4B,CAC9E,GAAI,EAAE,OAAS,EAAE,KACb,MAAO,GAGX,IAAK,IAAM,KAAQ,EACf,GAAI,CAAC,EAAE,IAAI,CAAI,EACX,MAAO,GAIf,MAAO,EACX"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, ComponentOptions } from "../../core/Component.js";
|
|
2
|
+
import { Event } from "../../core/Event.js";
|
|
2
3
|
import { Text } from "../../component/input/Text.js";
|
|
3
4
|
import { Glyph } from "../../component/display/Glyph.js";
|
|
4
5
|
import { FillType } from "../../layout/FillType.js";
|
|
@@ -7,7 +8,7 @@ import { BorderOptions } from "../../primitive/Border.js";
|
|
|
7
8
|
import { Insets } from "../../primitive/Insets.js";
|
|
8
9
|
import { Size } from "../../primitive/Size.js";
|
|
9
10
|
export type ButtonEvent = "action";
|
|
10
|
-
export type ClickListener = (event: MouseEvent) =>
|
|
11
|
+
export type ClickListener = (event: MouseEvent) => Event.ListenerResult;
|
|
11
12
|
export interface ButtonOptions extends ComponentOptions {
|
|
12
13
|
text?: string;
|
|
13
14
|
description?: string;
|
|
@@ -98,7 +99,7 @@ declare class Button<TOptions extends ButtonOptions = ButtonOptions> extends Com
|
|
|
98
99
|
on(event: "action", listener: ClickListener): this;
|
|
99
100
|
off(event: "action", listener: ClickListener): this;
|
|
100
101
|
click(): this;
|
|
101
|
-
addPointerDownListener(listener:
|
|
102
|
+
addPointerDownListener(listener: Event.Listener): this;
|
|
102
103
|
isChromeless(): boolean;
|
|
103
104
|
setChromeless(value: boolean): this;
|
|
104
105
|
private _clearChrome;
|
|
@@ -110,7 +111,7 @@ declare class Button<TOptions extends ButtonOptions = ButtonOptions> extends Com
|
|
|
110
111
|
private _applyFlatChrome;
|
|
111
112
|
private _resolveInsets;
|
|
112
113
|
setInsets(insets: Insets): this;
|
|
113
|
-
setPreferredSize(
|
|
114
|
+
setPreferredSize(size: Size): this;
|
|
114
115
|
getPreferredSize(): Size | null;
|
|
115
116
|
protected recomputePreferredSize(): void;
|
|
116
117
|
protected computePreferredSize(): {
|
|
@@ -31,7 +31,7 @@ declare class ChartLegend extends Panel<ChartLegendOptions> {
|
|
|
31
31
|
on(event: "toggle", listener: (seriesIndex: number) => void): this;
|
|
32
32
|
off(event: "toggle", listener: (seriesIndex: number) => void): this;
|
|
33
33
|
protected emit(event: ChartLegendEvent, seriesIndex: number): void;
|
|
34
|
-
|
|
34
|
+
protected destructor(): void;
|
|
35
35
|
}
|
|
36
36
|
declare const ChartLegendCallable: import("../../core/Callable.js").Callable<typeof ChartLegend>;
|
|
37
37
|
type ChartLegendCallable = ChartLegend;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Component, ComponentOptions } from "../../core/Component.js";
|
|
2
|
+
import { Event } from "../../core/Event.js";
|
|
2
3
|
interface DialogBackdropOptions extends ComponentOptions {
|
|
3
4
|
}
|
|
4
5
|
declare class DialogBackdrop extends Component<DialogBackdropOptions> {
|
|
5
6
|
constructor(options?: DialogBackdropOptions);
|
|
6
|
-
addClickListener(listener:
|
|
7
|
+
addClickListener(listener: Event.Listener): this;
|
|
7
8
|
resize(): void;
|
|
8
9
|
destroy(): void;
|
|
9
10
|
}
|
|
@@ -52,6 +52,7 @@ declare class ScrollStrip extends Panel<ScrollStripOptions> {
|
|
|
52
52
|
private trailClicked;
|
|
53
53
|
revealItem(itemElement: Handle): void;
|
|
54
54
|
containsArrow(target: EventTarget | null): boolean;
|
|
55
|
+
protected destructor(): void;
|
|
55
56
|
}
|
|
56
57
|
declare const ScrollStripCallable: import("../../core/Callable.js").Callable<typeof ScrollStrip>;
|
|
57
58
|
type ScrollStripCallable = ScrollStrip;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, ComponentOptions } from "../../core/Component.js";
|
|
2
2
|
import type { Handle } from "../../core/DOM.js";
|
|
3
3
|
import { CollapseDirection } from "../../component/container/CollapseButton.js";
|
|
4
|
+
import { Event } from "../../core/Event.js";
|
|
4
5
|
export type SplitGutterEvent = "dragstart" | "drag" | "dragend" | "collapse";
|
|
5
6
|
export interface SplitGutterOptions extends ComponentOptions {
|
|
6
7
|
orientation?: string;
|
|
@@ -52,8 +53,8 @@ declare class SplitGutter extends Component<SplitGutterOptions> {
|
|
|
52
53
|
destroy(): void;
|
|
53
54
|
private _dispatchDrag;
|
|
54
55
|
onDragStart(evnt: MouseEvent): void;
|
|
55
|
-
onDragStop(
|
|
56
|
-
onDrag(evnt: MouseEvent):
|
|
56
|
+
onDragStop(): Event.ListenerResult;
|
|
57
|
+
onDrag(evnt: MouseEvent): Event.ListenerResult;
|
|
57
58
|
private dragCursor;
|
|
58
59
|
private applyCursor;
|
|
59
60
|
render(): Handle;
|
|
@@ -46,7 +46,6 @@ declare class TabBar extends Container<TabBarOptions> {
|
|
|
46
46
|
private _fixedWidth;
|
|
47
47
|
private _underBorderFullWidth;
|
|
48
48
|
private _underBorderFromTheme;
|
|
49
|
-
private _themeCleanup;
|
|
50
49
|
private _indicator;
|
|
51
50
|
private _side;
|
|
52
51
|
private _align;
|
|
@@ -74,7 +73,7 @@ declare class TabBar extends Container<TabBarOptions> {
|
|
|
74
73
|
private dispatchBarOptions;
|
|
75
74
|
setBarSurfaceColor(color: string): this;
|
|
76
75
|
protected init(element?: Handle): this;
|
|
77
|
-
|
|
76
|
+
protected destructor(): void;
|
|
78
77
|
private applyUnderBorder;
|
|
79
78
|
setWidthMode(mode: TabWidthMode): this;
|
|
80
79
|
getWidthMode(): TabWidthMode;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Container, ContainerOptions } from "../../core/Container.js";
|
|
2
2
|
import { Component } from "../../core/Component.js";
|
|
3
|
+
import type { ComponentFactory } from "../../core/Component.js";
|
|
3
4
|
import { Tab, TabOptions } from "../../layout/Tab.js";
|
|
4
5
|
export interface TabEntryConfig {
|
|
5
6
|
label: string;
|
|
6
|
-
component: Component;
|
|
7
|
+
component: Component | ComponentFactory;
|
|
7
8
|
closeable?: boolean;
|
|
8
9
|
glyph?: string;
|
|
10
|
+
lazy?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export interface TabPanelOptions extends ContainerOptions {
|
|
11
13
|
tabs?: TabEntryConfig[];
|
|
@@ -14,11 +16,12 @@ export interface TabPanelOptions extends ContainerOptions {
|
|
|
14
16
|
}
|
|
15
17
|
declare class TabPanel<TOptions extends TabPanelOptions = TabPanelOptions> extends Container<TOptions> {
|
|
16
18
|
constructor(options?: TOptions);
|
|
17
|
-
addTab(component: Component, label: string, options?: {
|
|
19
|
+
addTab(component: Component | ComponentFactory, label: string, options?: {
|
|
18
20
|
closeable?: boolean;
|
|
19
21
|
glyph?: string;
|
|
22
|
+
lazy?: boolean;
|
|
20
23
|
}): this;
|
|
21
|
-
addLazyTab(factory:
|
|
24
|
+
addLazyTab(factory: ComponentFactory, label: string, options?: {
|
|
22
25
|
closeable?: boolean;
|
|
23
26
|
glyph?: string;
|
|
24
27
|
}): this;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, ComponentOptions } from "../../core/Component.js";
|
|
2
|
+
import { Event } from "../../core/Event.js";
|
|
2
3
|
export type WindowBorderEvent = "drag";
|
|
3
4
|
export declare enum Direction {
|
|
4
5
|
NORTH = 0,
|
|
@@ -34,7 +35,7 @@ declare class WindowBorder extends Component<WindowBorderOptions> {
|
|
|
34
35
|
isSnapTarget(): boolean;
|
|
35
36
|
setSnapTarget(value: boolean): this;
|
|
36
37
|
onDragStart(): void;
|
|
37
|
-
onDragStop(
|
|
38
|
+
onDragStop(): Event.ListenerResult;
|
|
38
39
|
private dragCursor;
|
|
39
40
|
render(): import("../../core/DOM.js").Handle;
|
|
40
41
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Header, HeaderOptions } from "../../component/display/Header.js";
|
|
2
2
|
import type { Handle } from "../../core/DOM.js";
|
|
3
|
+
import { Event } from "../../core/Event.js";
|
|
3
4
|
import { Glyph } from "../../component/display/Glyph.js";
|
|
4
5
|
export interface WindowHeaderOptions extends HeaderOptions {
|
|
5
6
|
closeable?: boolean;
|
|
@@ -37,7 +38,7 @@ declare class WindowHeader extends Header {
|
|
|
37
38
|
addExitButtonListener(listener: Function): this;
|
|
38
39
|
addMinimizeButtonListener(listener: Function): this;
|
|
39
40
|
addMaximizeButtonListener(listener: Function): this;
|
|
40
|
-
addHeaderDoubleClickListener(listener:
|
|
41
|
+
addHeaderDoubleClickListener(listener: Event.Listener): this;
|
|
41
42
|
getMinContentWidth(textBudget?: number): number;
|
|
42
43
|
getMinimizeButtonElement(): Handle | undefined;
|
|
43
44
|
getMaximizeButtonElement(): Handle | undefined;
|
|
@@ -2,6 +2,7 @@ import { Component, ComponentOptions } from "../../core/Component.js";
|
|
|
2
2
|
import type { Handle } from "../../core/DOM.js";
|
|
3
3
|
import type { ElkEdgeSection } from "../../component/diagram/ElkLayoutEngine.js";
|
|
4
4
|
import type { DiagramEdgeStyle } from "../../component/diagram/DiagramModel.js";
|
|
5
|
+
export declare const EDGE_MARKER_EXTENT: number;
|
|
5
6
|
export interface DiagramEdgeRoute {
|
|
6
7
|
id: string;
|
|
7
8
|
sections: ElkEdgeSection[];
|
|
@@ -9,17 +10,29 @@ export interface DiagramEdgeRoute {
|
|
|
9
10
|
}
|
|
10
11
|
declare class DiagramEdgeLayer extends Component<ComponentOptions> {
|
|
11
12
|
private _edges;
|
|
12
|
-
private
|
|
13
|
+
private _drawn;
|
|
14
|
+
private _edgeEmphasis;
|
|
15
|
+
private _dimLayer;
|
|
16
|
+
private _normalLayer;
|
|
13
17
|
private readonly _markerId;
|
|
14
18
|
private readonly _crowsFootMarkerIds;
|
|
15
19
|
constructor(options?: ComponentOptions);
|
|
16
20
|
private markerUrl;
|
|
17
21
|
setEdges(edges: DiagramEdgeRoute[]): this;
|
|
22
|
+
setEdgeEmphasis(ids: readonly string[] | null): this;
|
|
23
|
+
getEdgeEmphasis(): string[];
|
|
24
|
+
edgeIdAt(target: EventTarget | null): string | null;
|
|
25
|
+
edgesNear(x: number, y: number): DiagramEdgeRoute[];
|
|
26
|
+
private groupFor;
|
|
18
27
|
protected createRootElement(): Handle;
|
|
28
|
+
private createEdgeGroup;
|
|
19
29
|
private createArrowMarker;
|
|
20
30
|
private createCrowsFootMarker;
|
|
21
31
|
protected render(): Handle;
|
|
22
32
|
private rebuildPaths;
|
|
33
|
+
private drawHitPath;
|
|
34
|
+
private drawVisiblePath;
|
|
35
|
+
private releaseDrawnEdge;
|
|
23
36
|
private drawLabel;
|
|
24
37
|
}
|
|
25
38
|
declare const DiagramEdgeLayerCallable: import("../../core/Callable.js").Callable<typeof DiagramEdgeLayer>;
|
|
@@ -3,10 +3,13 @@ import type { Handle } from "../../core/DOM.js";
|
|
|
3
3
|
export interface DiagramNodeOptions extends PanelOptions {
|
|
4
4
|
label?: string;
|
|
5
5
|
glyph?: string;
|
|
6
|
+
badge?: string;
|
|
6
7
|
selected?: boolean;
|
|
7
8
|
}
|
|
8
9
|
declare class DiagramNode extends Panel<DiagramNodeOptions> {
|
|
10
|
+
private _label;
|
|
9
11
|
private _content;
|
|
12
|
+
private _badge?;
|
|
10
13
|
private _selectedStyleRule?;
|
|
11
14
|
private get selectedStyleRule();
|
|
12
15
|
constructor(options?: DiagramNodeOptions);
|
|
@@ -14,6 +17,7 @@ declare class DiagramNode extends Panel<DiagramNodeOptions> {
|
|
|
14
17
|
private buildContent;
|
|
15
18
|
setLabel(value: string): this;
|
|
16
19
|
getLabel(): string | null;
|
|
20
|
+
getBadge(): string | null;
|
|
17
21
|
setSelected(value: boolean): this;
|
|
18
22
|
isSelected(): boolean;
|
|
19
23
|
protected init(element?: Handle): this;
|