@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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Menu-Wz4MK6sA.js","names":[],"sources":["../../src/typescript/lib/component/container/MenuItem.ts","../../src/typescript/lib/component/container/MenuSeparator.ts","../../src/typescript/lib/overlay/Menu.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time component-level options for {@link MenuItem}. Use this\n * for cosmetic/layout overrides on the item row; the menu data (text, action,\n * shortcut, submenu) still comes through {@link MenuItemConfig}.\n *\n * @category Components\n */\nexport interface MenuItemOptions extends ComponentOptions {\n text?: string;\n enabled?: boolean;\n focused?: boolean;\n}\n\n/**\n * Selects which CSS-variable family a `MenuItem` reads its colours from.\n *\n * `'menu-bar'` resolves to `--ts-ui-menu-bar-item-*` tokens; `'context-menu'`\n * resolves to `--ts-ui-context-menu-item-*` tokens. The [`Menu`](/api/overlay/classes/Menu) class chooses\n * the prefix based on its mode.\n */\nexport type MenuItemCSSVarPrefix = \"menu-bar\" | \"context-menu\";\n\n/**\n * Describes a leaf action item, submenu trigger, or separator row inside a [`Menu`](/api/overlay/classes/Menu).\n *\n * @remarks When `separator` is true all other fields are ignored; the item renders as\n * a thin horizontal rule. When `submenu` is set the item opens a child [`Menu`](/api/overlay/classes/Menu)\n * instead of calling `action`.\n *\n * @category Components\n */\nexport interface MenuItemConfig {\n /** Display label shown in the menu row. */\n text?: string;\n /** Called when the item is activated (click or Enter). Ignored when `submenu` is set. */\n action?: () => void;\n /** Defaults to `true`. Disabled items are dimmed and non-interactive. */\n enabled?: boolean;\n /** Keyboard shortcut hint displayed on the right (e.g. `\"Ctrl+S\"`). */\n shortcut?: string;\n /**\n * Icon displayed on the left (e.g. a Unicode character).\n *\n * @remarks Prefer `glyph` for crisp SVG output from the framework's glyph\n * registry; `icon` remains supported for callers that want to embed a raw\n * character.\n */\n icon?: string;\n /**\n * Registry glyph name displayed on the left of the item row. Takes\n * precedence over `icon` when both are provided.\n */\n glyph?: string;\n /**\n * Optional colour for the leading `glyph`, overriding the item's default\n * foreground (e.g. a severity tint). Any CSS colour string. Ignored when the\n * row has no `glyph`.\n */\n glyphColor?: string;\n /** When present this item opens a submenu rather than calling `action`. */\n submenu?: MenuConfig;\n /** When `true` the item renders as a separator; all other fields are ignored. */\n separator?: true;\n}\n\n/**\n * Describes one top-level entry in a [`MenuBar`](/api/component/menubar/classes/MenuBar).\n *\n * @category Components\n */\nexport interface MenuConfig {\n /** Label shown in the bar button (e.g. `\"File\"`). */\n label: string;\n /**\n * The items in the dropdown panel: either a fixed array, or a provider called\n * to produce them when the panel is built. A submenu panel is (re)built each\n * time it opens, so a provider on a submenu's `items` is re-invoked on every\n * open — letting the submenu reflect current state (e.g. an export chooser\n * whose labels track the active tab) without the parent menu rebuilding.\n */\n items: MenuItemConfig[] | (() => MenuItemConfig[]);\n /**\n * Optional registry glyph name displayed to the left of the bar button's\n * label (e.g. `\"file\"`, `\"eye\"`, `\"info-circle\"`). Omit for a text-only\n * menu button.\n */\n glyph?: string;\n}\n\n/**\n * A single row inside a [`Menu`](/api/overlay/classes/Menu) panel.\n *\n * Renders a four-zone layout: icon | text | shortcut | chevron. When\n * `config.separator` is true the item renders instead as a thin horizontal\n * rule and ignores all other config fields.\n *\n * Mouse hover triggers the submenu open callback after a 150 ms delay.\n * Keyboard focus is applied programmatically via `setFocused`.\n *\n * @category Components\n */\nclass MenuItem extends Component {\n\n /** Fixed pixel height for every non-separator menu item. */\n static readonly HEIGHT: number = 24;\n\n private static readonly SEPARATOR_HEIGHT: number = 9;\n /** Title left inset when the menu reserves no icon column. */\n static readonly TEXT_INSET: number = 8;\n /** Title left offset when the menu reserves an icon column. */\n static readonly ICON_ZONE: number = 24;\n /** Width reserved for a submenu chevron in the right zone. */\n static readonly CHEVRON_ZONE: number = 16;\n /** Padding after the right zone, at the panel's inner edge. */\n static readonly RIGHT_PAD: number = 8;\n /**\n * Gap between the title column and the shortcut/chevron right zone, so a\n * content-sized menu never butts the label against them.\n */\n static readonly TEXT_GAP: number = 10;\n\n private readonly _config: MenuItemConfig;\n private readonly _onActivate: () => void;\n private readonly _onOpenSubmenu: (item: MenuItem) => void;\n private readonly _cssVarPrefix: MenuItemCSSVarPrefix;\n\n private _iconText: Text | null = null;\n private _iconGlyph: Glyph | null = null;\n private _titleText: Text | null = null;\n private _shortcutText: Text | null = null;\n private _chevronText: Text | null = null;\n\n // Column geometry applied by the parent Menu so every item lines up: the\n // title's left offset and the shared title-column width the right zone begins\n // after. Null until the menu sets them (a standalone item falls back to its\n // own natural metrics).\n private _iconStart: number | null = null;\n private _titleColumn: number | null = null;\n\n private _submenuTimer: ReturnType<typeof setTimeout> | null = null;\n\n private readonly _onMouseOver: () => void;\n private readonly _onMouseOut: () => void;\n private readonly _onClick: () => void;\n\n /**\n * Constructs a MenuItem from a config descriptor.\n *\n * @param config - The item descriptor including text, action, shortcut, icon, and submenu.\n * @param onActivate - Called when this item is activated (click or Enter on a leaf item).\n * @param onOpenSubmenu - Called when this item's submenu should open (or close others when no submenu).\n * @param cssVarPrefix - Selects which CSS-variable family supplies disabled, hover, and shortcut colours. Defaults to `'menu-bar'`.\n */\n constructor(\n config: MenuItemConfig,\n onActivate: () => void,\n onOpenSubmenu: (item: MenuItem) => void,\n cssVarPrefix: MenuItemCSSVarPrefix = \"menu-bar\",\n options?: MenuItemOptions\n ) {\n // Child components are built first; options are applied via applyOptions at the constructor tail.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n this._config = config;\n this._onActivate = onActivate;\n this._onOpenSubmenu = onOpenSubmenu;\n this._cssVarPrefix = cssVarPrefix;\n\n if (config.separator) {\n this.setHeight(MenuItem.SEPARATOR_HEIGHT);\n this.setPreferredSize(0, MenuItem.SEPARATOR_HEIGHT);\n this.setBackgroundColor(\"transparent\");\n this.setElementCSSRule(\n \"borderTop\",\n `1px solid var(--ts-ui-${cssVarPrefix}-separator-color, rgb(220, 220, 220))`\n );\n this.setElementCSSRule(\"margin\", \"4px 0\");\n this.getAria().setRole(\"separator\");\n\n this._onMouseOver = () => {};\n this._onMouseOut = () => {};\n this._onClick = () => {};\n\n if (options) {\n this.applyOptions(options);\n }\n\n return;\n }\n\n const enabled = config.enabled !== false;\n\n this.setHeight(MenuItem.HEIGHT);\n this.setPreferredSize(0, MenuItem.HEIGHT);\n this.setBackgroundColor(\"transparent\");\n this.setElementCSSRule(\"fontSize\", \"var(--ts-ui-button-font-size, var(--ts-ui-font-size))\");\n this.setCursor(enabled ? \"pointer\" : \"default\");\n this.getAria().setRole(\"menuitem\");\n\n if (!enabled) {\n this.setForegroundColor(\n `var(--ts-ui-${cssVarPrefix}-item-disabled-color, rgb(170, 170, 170))`\n );\n this.getAria().setDisabled(true);\n }\n\n if (config.glyph) {\n this._iconGlyph = new Glyph(config.glyph);\n this._iconGlyph.setPointerEvents(\"none\");\n this._iconGlyph.setPreferredSize(16, 16);\n\n if (config.glyphColor) {\n this._iconGlyph.setForegroundColor(config.glyphColor);\n }\n\n this.addComponent(this._iconGlyph);\n } else {\n this._iconText = new Text(config.icon ?? \"\");\n this._iconText.setPointerEvents(\"none\");\n this._iconText.centerInHeight(MenuItem.HEIGHT);\n this._iconText.setVisible(!!config.icon);\n this.addComponent(this._iconText);\n }\n\n this._titleText = new Text(config.text ?? \"\");\n this._titleText.setPointerEvents(\"none\");\n this._titleText.centerInHeight(MenuItem.HEIGHT);\n this._titleText.setWhiteSpace(\"nowrap\");\n this._titleText.setOverflow(\"hidden\");\n this._titleText.setTextOverflow(\"ellipsis\");\n this.addComponent(this._titleText);\n\n if (config.shortcut) {\n this._shortcutText = new Text(config.shortcut);\n this._shortcutText.setPointerEvents(\"none\");\n this._shortcutText.centerInHeight(MenuItem.HEIGHT);\n this._shortcutText.setTextAlign(\"left\");\n this._shortcutText.setForegroundColor(\n `var(--ts-ui-${cssVarPrefix}-item-shortcut-color, rgb(140, 140, 140))`\n );\n this.addComponent(this._shortcutText);\n }\n\n if (this.hasSubmenu()) {\n this._chevronText = new Text(\"▶\");\n this._chevronText.setPointerEvents(\"none\");\n this._chevronText.centerInHeight(MenuItem.HEIGHT);\n this._chevronText.setTextAlign(\"center\");\n this._chevronText.setForegroundColor(\n `var(--ts-ui-${cssVarPrefix}-item-shortcut-color, rgb(140, 140, 140))`\n );\n this.addComponent(this._chevronText);\n this.getAria().setHasPopup(\"menu\");\n this.getAria().setExpanded(false);\n }\n\n this._onMouseOver = () => {\n this.setFocused(true);\n\n // A disabled item never opens its own submenu; it still signals the\n // parent (the else branch) so hovering it closes any sibling submenu.\n if (enabled && this.hasSubmenu()) {\n this._submenuTimer = setTimeout(() => {\n this._submenuTimer = null;\n this._onOpenSubmenu(this);\n }, 150);\n } else {\n this._onOpenSubmenu(this);\n }\n };\n\n this._onMouseOut = () => {\n this.setFocused(false);\n\n if (this._submenuTimer !== null) {\n clearTimeout(this._submenuTimer);\n this._submenuTimer = null;\n }\n };\n\n this._onClick = () => {\n if (enabled && !this.hasSubmenu()) {\n this._onActivate();\n }\n };\n\n Event.addListener(this, \"mouseover\", this._onMouseOver);\n Event.addListener(this, \"mouseout\", this._onMouseOut);\n Event.addListener(this, \"click\", this._onClick);\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link MenuItemOptions} bag, dispatching menu item label,\n * enabled state, and focus highlight after inherited Component fields.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: MenuItemOptions): this {\n super.applyOptions(options);\n\n if (options.text !== undefined && this._titleText) {\n this._titleText.setText(options.text);\n }\n\n if (options.enabled !== undefined) {\n this.getAria().setDisabled(!options.enabled);\n this.setCursor(options.enabled ? \"pointer\" : \"default\");\n }\n\n if (options.focused !== undefined) {\n this.setFocused(options.focused);\n }\n\n return this;\n }\n\n /**\n * Returns `true` if this item has a child submenu.\n *\n * @returns Whether a `submenu` config was provided.\n */\n hasSubmenu(): boolean {\n return !!this._config.submenu;\n }\n\n /** True when the item reserves an icon column (has a glyph or icon slot). */\n hasIcon(): boolean {\n return !!this._config.icon || !!this._config.glyph;\n }\n\n /** The item's measured title width, feeding the menu's shared title column. */\n titleTextWidth(): number {\n return Math.ceil(this._titleText?.getPreferredSize()?.width ?? 0);\n }\n\n /** The item's measured shortcut width, or 0 when it has no shortcut. */\n shortcutTextWidth(): number {\n if (!this._config.shortcut || this._shortcutText === null) {\n return 0;\n }\n\n return Math.ceil(this._shortcutText.getPreferredSize()?.width ?? 0);\n }\n\n /**\n * Applies the menu-computed column geometry so every item lines up: the title\n * left offset (icon column, or the bare inset) and the shared title-column\n * width the shortcut/chevron right zone begins after.\n *\n * @param iconStart - The title's left offset in pixels.\n * @param titleColumn - The shared title-column width across the menu's items.\n */\n setColumns(iconStart: number, titleColumn: number): void {\n this._iconStart = iconStart;\n this._titleColumn = titleColumn;\n\n this.scheduleLayout();\n }\n\n /**\n * Returns the submenu config, or `null` if this item has no submenu.\n *\n * @returns The [`MenuConfig`](/api/component/container/interfaces/MenuConfig) for the child panel, or null.\n */\n getSubmenuConfig(): MenuConfig | null {\n return this._config.submenu ?? null;\n }\n\n /**\n * Applies or removes the keyboard-focus highlight background.\n *\n * @param focused - `true` to highlight, `false` to clear.\n */\n setFocused(focused: boolean): this {\n this.setBackgroundColor(\n focused\n ? `var(--ts-ui-${this._cssVarPrefix}-item-hover-bg, rgba(30, 100, 200, 0.12))`\n : \"transparent\"\n );\n\n return this;\n }\n\n /**\n * Returns `true` when this item was constructed with `separator: true`.\n *\n * @returns Whether this item is a non-interactive separator row.\n */\n isSeparator(): boolean {\n return !!this._config.separator;\n }\n\n /**\n * Returns `true` when the item is interactive (not disabled).\n *\n * @returns Whether `enabled` was not explicitly set to `false`.\n */\n isEnabled(): boolean {\n return this._config.enabled !== false;\n }\n\n /**\n * Activates this item as if the user clicked or pressed Enter.\n *\n * For submenu items, calls `onOpenSubmenu` immediately (skipping the hover delay).\n * For leaf items, calls `onActivate`. Does nothing for disabled or separator items.\n */\n activate(): void {\n if (this.isSeparator() || !this.isEnabled()) {\n return;\n }\n\n if (this.hasSubmenu()) {\n this._onOpenSubmenu(this);\n } else {\n this._onActivate();\n }\n }\n\n /**\n * Removes all Event listeners registered by this item and cancels any pending submenu timer.\n */\n dispose(): void {\n if (this._submenuTimer !== null) {\n clearTimeout(this._submenuTimer);\n this._submenuTimer = null;\n }\n\n Event.removeListener(this, \"mouseover\", this._onMouseOver);\n Event.removeListener(this, \"mouseout\", this._onMouseOut);\n Event.removeListener(this, \"click\", this._onClick);\n }\n\n /**\n * Returns the offset from the top of the menu item to the title text's baseline.\n *\n * @returns The baseline offset in pixels, or `null` when the title has no baseline\n * (e.g. for a separator row).\n */\n getBaseline(): number | null {\n if (this._titleText === null) {\n return null;\n }\n\n return this.wrapInnerBaseline(this._titleText.getBaseline());\n }\n\n /**\n * Positions the four label zones within the item's bounds.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n if (this._config.separator) {\n return this;\n }\n\n const H = MenuItem.HEIGHT;\n const totalWidth = this.getWidth();\n const hasShortcut = !!this._config.shortcut && this._shortcutText !== null;\n const hasSub = this.hasSubmenu();\n\n // The menu aligns every item into shared columns; a standalone item falls\n // back to its own icon offset and natural title width.\n const iconStart = this._iconStart ?? (this.hasIcon() ? MenuItem.ICON_ZONE : MenuItem.TEXT_INSET);\n const titleColumn = this._titleColumn ?? this.titleTextWidth();\n\n if (this._iconGlyph) {\n const size = this._iconGlyph.getPreferredSize() ?? { width: 16, height: 16 };\n const iconY = Math.max(0, Math.floor((H - size.height) / 2));\n\n this._iconGlyph.setX(4);\n this._iconGlyph.setY(iconY);\n this._iconGlyph.setWidth(size.width);\n this._iconGlyph.setHeight(size.height);\n } else if (this._iconText) {\n this._iconText.setX(4);\n this._iconText.setY(0);\n this._iconText.setWidth(20);\n this._iconText.setHeight(H);\n }\n\n // Title fills the shared title column, left-aligned from the icon offset.\n if (this._titleText) {\n this._titleText.setX(iconStart);\n this._titleText.setY(0);\n this._titleText.setWidth(titleColumn);\n this._titleText.setHeight(H);\n }\n\n // Chevron: right-justified at the panel's inner edge.\n if (hasSub && this._chevronText) {\n this._chevronText.setX(totalWidth - MenuItem.RIGHT_PAD - MenuItem.CHEVRON_ZONE);\n this._chevronText.setY(0);\n this._chevronText.setWidth(MenuItem.CHEVRON_ZONE);\n this._chevronText.setHeight(H);\n }\n\n // Shortcut: left-justified in the right zone, one gap past the title column.\n if (hasShortcut && this._shortcutText) {\n this._shortcutText.setX(iconStart + titleColumn + MenuItem.TEXT_GAP);\n this._shortcutText.setY(0);\n this._shortcutText.setWidth(this.shortcutTextWidth());\n this._shortcutText.setHeight(H);\n }\n\n return this;\n }\n}\n\nconst MenuItemCallable = callable(MenuItem);\ntype MenuItemCallable = MenuItem;\nexport {\n MenuItem as _MenuItem,\n MenuItemCallable as MenuItem\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport type { MenuItemCSSVarPrefix } from \"~/component/container/MenuItem.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link MenuSeparator}.\n *\n * @category Components\n */\nexport interface MenuSeparatorOptions extends ComponentOptions {\n}\n\n/**\n * Empty subclass-default const so the super call follows the framework's\n * `(options, defaults)` shape uniformly. MenuSeparator owns no class-level\n * option overrides today; the const exists so a future field has a place to\n * land without reshuffling the super call.\n */\nconst _defaultMenuSeparatorOptions: Partial<MenuSeparatorOptions> = {};\n\n/**\n * A horizontal separator rule used inside a [`Menu`](/api/overlay/classes/Menu) panel to visually group menu items.\n *\n * Renders as a thin border line. Width is set externally by `Menu.doLayout()`.\n *\n * @category Components\n */\nclass MenuSeparator extends Component<MenuSeparatorOptions> {\n\n /** Fixed pixel height of every separator. */\n static readonly HEIGHT: number = 9;\n\n /**\n * Constructs a MenuSeparator with a thin horizontal rule appearance.\n *\n * @param cssVarPrefix - Selects which CSS-variable family supplies the border colour. Defaults to `'menu-bar'`.\n */\n constructor(cssVarPrefix: MenuItemCSSVarPrefix = \"menu-bar\", options?: MenuSeparatorOptions) {\n super(options, _defaultMenuSeparatorOptions);\n\n this.setHeight(MenuSeparator.HEIGHT);\n this.setPreferredSize(0, MenuSeparator.HEIGHT);\n this.setBackgroundColor(\"transparent\");\n this.setElementCSSRule(\n \"borderTop\",\n `1px solid var(--ts-ui-${cssVarPrefix}-separator-color, rgb(220, 220, 220))`\n );\n this.setElementCSSRule(\"margin\", \"4px 0\");\n this.getAria().setRole(\"separator\");\n }\n}\n\nconst MenuSeparatorCallable = callable(MenuSeparator);\ntype MenuSeparatorCallable = MenuSeparator;\nexport {\n MenuSeparator as _MenuSeparator,\n MenuSeparatorCallable as MenuSeparator\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle, Rect } from \"~/core/DOM.js\";\nimport { LayerManager, DismissableLayer, LayerDismissMode } from \"~/core/LayerManager.js\";\nimport { positionAligned, positionFlexibleAnchored } from \"~/core/OverlayPosition.js\";\nimport { fadeShow, fadeHideAndDetach } from \"~/core/AnimatedDropdown.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport type { Size } from \"~/primitive/Size.js\";\nimport { VBox } from \"~/layout/VBox.js\";\nimport { MenuItem, MenuItemConfig } from \"~/component/container/MenuItem.js\";\nimport { MenuSeparator } from \"~/component/container/MenuSeparator.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { Util } from \"~/core/Util.js\";\n\n/**\n * Pixel bounds a content-sized menu panel clamps to. Menus size to their widest\n * item (via the layout manager's preferred width); the floor keeps a short menu\n * from looking cramped, and the ceiling stops a very long label running off-screen\n * (the item's title ellipsizes past it).\n */\nconst MIN_MENU_WIDTH = 120;\nconst MAX_MENU_WIDTH = 360;\n\n/** Duration (ms) of the fade-in / fade-out transitions on every menu panel. */\nconst MENU_ANIM_DURATION_MS = 120;\n\n/** Pixels kept between a clamped menu and the viewport edge so the panel\n * border and shadow are never flush against the screen. Mirrors the small\n * inset used by other floating panels; purely cosmetic breathing room. */\nconst VIEWPORT_MARGIN = 4;\n\n/** A resolved rebuild-mode placement: the panel's top-left plus the height room at it. */\ninterface MenuPlacement { x: number; y: number; available: number; }\n\n/**\n * A zero-size rect at a cursor point. A cursor is a degenerate anchor: with\n * `left === right` and `top === bottom`, the adjacency and alignment flips\n * collapse to the same operation — grow down-right from the point, or end at it.\n * That is native context-menu behaviour, so a pointer needs no separate path.\n */\nfunction pointRect(x: number, y: number): Rect {\n return { x, y, left: x, top: y, right: x, bottom: y, width: 0, height: 0 };\n}\n\n/**\n * Resolves a rebuild-mode panel's placement against `anchorRect` at `size`.\n * Vertically the panel is size-flexible (it caps its height and scrolls), so it\n * grows below the anchor and flips to end at the anchor's top when the room below\n * is short. Horizontally it is fixed-size (a natural width, no horizontal scroll),\n * so its left edge aligns with the anchor's left and flips to align its right edge\n * with the anchor's right when the left alignment overflows.\n *\n * @param anchorRect - The trigger rect, or a zero-size rect at the cursor.\n * @param size - The panel's current width/height to place.\n * @param vp - The viewport size to flip/clamp within.\n * @returns The resolved top-left coordinate and the vertical room available there.\n */\nfunction resolvePlacement(anchorRect: Rect, size: Size, vp: Size): MenuPlacement {\n const v = positionFlexibleAnchored(anchorRect.top, anchorRect.bottom, size.height, vp.height, VIEWPORT_MARGIN);\n const x = positionAligned(anchorRect.left, anchorRect.right, size.width, vp.width, VIEWPORT_MARGIN);\n\n // `available` is the room on the side the panel actually landed on — never\n // re-derive it from `v.start`, which measures the wrong side for a flipped\n // panel and lets an over-tall menu grow back across the cursor.\n return { x, y: v.start, available: v.available };\n}\n\n/**\n * A floating menu panel that operates in one of two modes:\n *\n * - **Rebuild mode** (`new Menu()`): a right-click context menu. Items are passed per\n * `show(x, y, items)` call and disposed on the next show or hide.\n * - **Persistent mode** (`new Menu(items, onClose)`): a [`MenuBar`](/api/component/menubar/classes/MenuBar) dropdown. Items are\n * built once in the constructor and reused across `open()` / `close()` cycles.\n *\n * The two API surfaces are disjoint by mode:\n * `show()` / `hide()` / `setMenuWidth()` are valid only in rebuild mode;\n * `open()` / `close()` / focus and submenu methods are valid only in persistent mode.\n *\n * @example\n * ```typescript\n * // Rebuild mode — right-click context menu\n * const menu = new Menu();\n * Event.addListener(myComponent, 'contextmenu', (e: MouseEvent) => {\n * e.preventDefault();\n * menu.show(e.clientX, e.clientY, [\n * { text: 'Cut', action: () => cut() },\n * { separator: true },\n * { text: 'Paste', action: () => paste() },\n * ]);\n * });\n *\n * // Persistent mode — MenuBar dropdown\n * const panel = new Menu(\n * [{ text: 'Save', shortcut: 'Ctrl+S', action: () => save() }],\n * () => bar.closeMenu()\n * );\n * panel.open(buttonElement);\n * ```\n *\n * @category Components\n */\nclass Menu extends Component implements DismissableLayer {\n\n private readonly _persistent: boolean;\n // A persistent menu's items provider, kept so each open() re-resolves it —\n // null when the items were passed as a fixed array (built once, never rebuilt).\n private readonly _itemsProvider: (() => MenuItemConfig[]) | null;\n private readonly _onClose: (() => void) | null;\n private _menuItems: Array<MenuItem | MenuSeparator> = [];\n private _focusedIndex: number = -1;\n private _openSubmenuPanel: Menu | null = null;\n private _openSubmenuItem: MenuItem | null = null;\n private _excludedEl: Handle | null = null;\n // An explicit rebuild-mode width set via setMenuWidth; null means size to\n // content (the widest item, clamped to [MIN_MENU_WIDTH, MAX_MENU_WIDTH]).\n private _menuWidth: number | null = null;\n private _rebuildOnClose: (() => void) | null = null;\n private _currentOpener: Handle | null = null;\n // Rebuild-mode: when true, each show() scrolls the menu to the bottom after\n // layout so the latest (bottom-most) items are visible on open.\n private _scrollToBottomOnShow: boolean = false;\n\n /**\n * Constructs a Menu. With no arguments, a rebuild-mode (right-click context)\n * menu whose items are supplied per `show()` call. With `items` (and `onClose`),\n * a persistent-mode ([`MenuBar`](/api/component/menubar/classes/MenuBar) dropdown)\n * menu whose items are built immediately and reused across `open()` / `close()`\n * cycles.\n *\n * A single optional-parameter signature, deliberately not an overload pair: the\n * `callable()` export's construct/call type is derived via TS `ConstructorParameters`,\n * which captures only the *last* overload — an overload pair would drop the\n * no-arg form and make `Menu()` a type error for consumers.\n *\n * @param items - The menu item configurations, or a provider called once now\n * to produce them. A submenu is rebuilt on each open, so a provider passed\n * for a submenu's items is re-invoked every time that submenu opens. Omit for\n * a rebuild-mode context menu.\n * @param onClose - Callback invoked when the panel should close (item activated or outside click).\n */\n constructor(items?: MenuItemConfig[] | (() => MenuItemConfig[]), onClose?: () => void) {\n super();\n\n this._persistent = items !== undefined;\n this._itemsProvider = typeof items === \"function\" ? items : null;\n this._onClose = onClose ?? null;\n\n const vbox = new VBox();\n\n vbox.setComponentSpacing(0);\n vbox.setStretching(true);\n\n this.setLayoutManager(vbox);\n\n if (this._persistent) {\n this.applyPersistentChrome();\n // Fixed array: build once now. A provider defers to open(), which\n // re-resolves it on every open (so the sole resolution is per-open).\n if (this._itemsProvider === null) {\n this.buildPersistentItems(items as MenuItemConfig[]);\n }\n } else {\n this.applyRebuildChrome();\n }\n }\n\n /**\n * Lays the menu's items into aligned columns and returns the panel width.\n * Every title shares one column sized to the widest title; the shortcut/chevron\n * right zone is the widest of the shortcut column and a submenu chevron, so\n * shortcuts left-justify in a column and chevrons right-justify at the edge.\n * The width is clamped to `[MIN_MENU_WIDTH, MAX_MENU_WIDTH]`; when the ceiling\n * bites, the title column shrinks and its titles ellipsize. Measured from the\n * items directly so a menu reused across shows re-measures its new content.\n *\n * @returns The clamped panel width in pixels.\n */\n private layOutColumns(): number {\n const items = this._menuItems.filter(\n (i): i is MenuItem => i instanceof MenuItem && !i.isSeparator()\n );\n\n const iconStart = items.some(i => i.hasIcon()) ? MenuItem.ICON_ZONE : MenuItem.TEXT_INSET;\n const maxTitle = items.reduce((m, i) => Math.max(m, i.titleTextWidth()), 0);\n const maxShortcut = items.reduce((m, i) => Math.max(m, i.shortcutTextWidth()), 0);\n const hasChevron = items.some(i => i.hasSubmenu());\n const rightZone = Math.max(maxShortcut, hasChevron ? MenuItem.CHEVRON_ZONE : 0);\n const rightReserve = rightZone > 0 ? MenuItem.TEXT_GAP + rightZone : 0;\n\n const natural = iconStart + maxTitle + rightReserve + MenuItem.RIGHT_PAD;\n const width = Math.min(MAX_MENU_WIDTH, Math.max(MIN_MENU_WIDTH, natural));\n\n // When the ceiling bites, the title column absorbs the shortfall (titles\n // ellipsize); otherwise it is the full widest-title width.\n const titleColumn = Math.min(maxTitle, width - iconStart - rightReserve - MenuItem.RIGHT_PAD);\n\n for (const item of items) {\n item.setColumns(iconStart, titleColumn);\n }\n\n return width;\n }\n\n /**\n * Shows the menu at the given viewport coordinates, replacing any previously\n * displayed items with the new list. **Rebuild-mode only.**\n *\n * The menu grows down-right from the cursor; when there is no room it flips\n * so its bottom / right edge ends at the cursor, never covering it. A menu\n * taller than the room on the side it lands on is capped there and scrolls.\n *\n * @param x - Horizontal viewport coordinate (e.g. `MouseEvent.clientX`).\n * @param y - Vertical viewport coordinate (e.g. `MouseEvent.clientY`).\n * @param configs - Ordered list of item descriptors to render.\n * @param onClose - Optional callback invoked once when the menu next closes\n * (item activated or dismissed by an outside click), letting the opener\n * revert an open-state affordance such as a rotated dropdown chevron.\n * @param excludeEl - Optional element whose subtree is exempt from the\n * outside-click-to-close check. Pass the trigger that opened the menu (e.g.\n * a [`SplitButton`](/api/component/button/classes/SplitButton) chevron) so a\n * pointerdown on it does not self-close the menu before the trigger's own\n * click can toggle it shut — mirroring [`MenuBar`](/api/component/menubar/classes/MenuBar)'s\n * dropdown-button exclusion.\n */\n show(x: number, y: number, configs: MenuItemConfig[], onClose?: () => void, excludeEl?: Handle | null): this {\n this.assertRebuildMode(\"show\");\n\n // The placement primitives only guarantee an on-screen result for an anchor\n // inside the viewport. A cursor from a real event always is; show() is public,\n // so pin it here rather than in showAnchored, which also takes real trigger\n // rects that may legitimately extend past a viewport edge.\n const vp = DOM.source.getViewportSize();\n\n return this.showAnchored(\n pointRect(Util.clamp(x, 0, vp.width), Util.clamp(y, 0, vp.height)),\n configs, onClose ?? null, excludeEl ?? null,\n );\n }\n\n /**\n * Rebuild-mode geometry-and-content core shared by {@link show} (pointer-anchored)\n * and {@link toggleFor} (rect-anchored). Both grow down-right from `anchorRect`\n * and flip per axis when the room runs short. Tears down and rebuilds the item\n * list, then resolves `anchorRect` to a placement and applies the resulting\n * position and height clamp.\n *\n * @param anchorRect - The cursor point (as a zero-size rect) or trigger rect to\n * place the panel against.\n * @param configs - Ordered list of item descriptors to render.\n * @param onClose - Callback invoked once when the menu next closes, or `null`.\n * @param excludeEl - Element whose subtree is exempt from the outside-click\n * check, or `null`.\n */\n private showAnchored(anchorRect: Rect, configs: MenuItemConfig[], onClose: (() => void) | null, excludeEl: Handle | null): this {\n this._rebuildOnClose = onClose;\n this._excludedEl = excludeEl;\n\n for (const item of this._menuItems) {\n if (item instanceof MenuItem) {\n item.dispose();\n }\n }\n\n this._menuItems = [];\n this.removeAllComponents();\n\n this.pauseLayout();\n\n for (const config of configs) {\n const item: MenuItem | MenuSeparator = config.separator === true\n ? new MenuSeparator(\"context-menu\")\n : new MenuItem(\n config,\n () => {\n config.action?.();\n this.hide();\n },\n (hoveredItem) => { this.handleItemOpenSubmenu(hoveredItem); },\n \"context-menu\"\n );\n\n this.addComponent(item);\n this._menuItems.push(item);\n }\n\n this.resumeLayout();\n\n const contentWidth = this.layOutColumns();\n const naturalWidth = this._menuWidth ?? contentWidth;\n\n this.setWidth(naturalWidth);\n\n // A reused menu still carries the previous show's max-height — set by\n // `applyViewportHeightClamp` to that show's available room. Because\n // `getPreferredSize` clamps to the component's own max, leaving it in\n // place would cap the new content at the old height, so a menu that\n // grew past its previous size would neither expand nor reserve a\n // scrollbar gutter on reopen. Clear it before measuring.\n this.setMaxSize(Number.MAX_VALUE, Number.MAX_VALUE);\n\n const totalHeight = this.getPreferredSize()?.height ?? 0;\n\n const el = this.getElement(true)!;\n\n const vp = DOM.source.getViewportSize();\n\n // First pass at the natural width resolves the vertical room. Width does not\n // affect the vertical placement, so `available` stays correct after the\n // scrollbar-gutter widening below; only `x` needs the second pass.\n const available = resolvePlacement(anchorRect, { width: naturalWidth, height: totalHeight }, vp).available;\n\n // When the content is taller than the room on the side the menu lands on,\n // `applyViewportHeightClamp` caps the height and the `overflow-y: auto`\n // scrollbar engages. Reserve its width as a right inset — and widen the\n // content-sized panel to match — so items lay out beside the native\n // scrollbar instead of beneath it. `Component.getInnerSize` subtracts the\n // inset, so the VBox stretches items to `naturalWidth`, unchanged from the\n // no-scroll case.\n const gutter = totalHeight > available ? DOM.source.getScrollBarWidth() : 0;\n\n this.setInsets(new Insets(4, gutter, 4, 0));\n this.setWidth(naturalWidth + gutter);\n\n const placement = resolvePlacement(anchorRect, { width: this.getWidth(), height: totalHeight }, vp);\n\n this.setX(placement.x);\n this.setY(placement.y);\n this.applyViewportHeightClamp(placement.available, totalHeight);\n\n this.scheduleLayout();\n\n LayerManager.mount(el);\n\n this.setVisible(true);\n this.fadeIn();\n\n // Join the central layer tree: the manager owns the outside-pointerdown /\n // window-blur / Escape dismissal and stamps the z-index. Registering while\n // whatever opened the menu is topmost links it under that layer, so a\n // context menu raised over a modal dialog inherits the dialog band and\n // paints in front of it.\n LayerManager.register(this);\n this.setZIndex(LayerManager.getZIndex(this));\n\n // Optionally reveal the bottom of the list on open (e.g. a history menu\n // whose latest entries sit at the bottom). Flush the scheduled layout\n // first so the item heights are committed and `getMaxScrollTop` is\n // accurate; when nothing overflows the offset is 0 and this is a no-op.\n if (this._scrollToBottomOnShow) {\n this.flushLayout();\n this.setScrollTop(this.getMaxScrollTop());\n }\n\n return this;\n }\n\n /**\n * Opens or closes the menu for a given opener element. **Rebuild-mode only.**\n *\n * This is the toggle form of {@link show} for a left-click dropdown trigger\n * (e.g. a [`SplitButton`](/api/component/button/classes/SplitButton) chevron\n * or a [`ToolBar`](/api/component/menubar/classes/ToolBar) overflow button):\n * the opener is excluded from the outside-click dismissal (so its own\n * pointerdown does not self-close the menu) and remembered, so a second press\n * of the *same* opener closes the menu instead of reopening it. Pressing a\n * *different* opener while the menu is open switches it to that opener. The\n * menu opens below `anchorRect` and flips above it when the room below is\n * short, right-aligning to it when the left alignment overflows. Plain\n * {@link show} stays the right call for right-click context menus, which\n * should reposition — not close — on a repeat trigger; the remaining\n * distinction from `toggleFor` is the toggle identity, the opener exclusion,\n * and the empty-list suppression below.\n *\n * An empty `configs` opens nothing: the menu is not shown, `onClose` fires once\n * so the opener can revert an open-state affordance, and no opener state is\n * recorded. A repeat press of the *same* opener still closes an open menu — the\n * toggle-shut branch runs before the empty check.\n *\n * @param openerEl - The element that triggers the menu; excluded from the\n * outside-click check and used as the toggle identity.\n * @param anchorRect - The trigger's viewport rect (e.g.\n * `DOM.source.getViewportRect(button)`); the menu opens below it and flips\n * above it when the room below is short.\n * @param configs - Ordered list of item descriptors to render. An empty list\n * opens nothing (see above).\n * @param onClose - Optional callback invoked once when the menu next closes,\n * or when an empty `configs` suppresses the open.\n *\n * @returns This menu, for method chaining.\n */\n toggleFor(openerEl: Handle, anchorRect: Rect, configs: MenuItemConfig[], onClose?: () => void): this {\n this.assertRebuildMode(\"toggleFor\");\n\n // Same opener fired again while its menu is open: close it. Its pointerdown\n // was excluded from the dismissal above, so this click is the toggle-shut.\n // MUST stay ahead of the empty check below — a provider that has since gone\n // empty must still be able to close the panel it opened.\n if (this._currentOpener === openerEl) {\n this.hide();\n\n return this;\n }\n\n // Nothing to show: an empty panel is never useful, so open nothing. `onClose`\n // still fires so the opener reverts an optimistic open-state affordance (e.g.\n // SplitButton's spun-up chevron), and `_currentOpener` stays untouched, so the\n // next press of this opener is a fresh open rather than a stale toggle-shut.\n if (configs.length === 0) {\n onClose?.();\n\n return this;\n }\n\n // Closed, or open for a different opener: (re)show anchored for this one.\n this.showAnchored(anchorRect, configs, onClose ?? null, openerEl);\n this._currentOpener = openerEl;\n\n return this;\n }\n\n /**\n * Hides the menu and detaches it from the DOM. **Rebuild-mode only.**\n *\n * The instance remains alive and can be shown again by calling `show()`.\n */\n hide(): this {\n this.assertRebuildMode(\"hide\");\n\n this.closeOpenSubmenu();\n\n LayerManager.unregister(this);\n\n this.fadeOutAndDetach();\n\n // Forget the toggle opener so the next `toggleFor` for it opens rather\n // than seeing a stale match and closing an already-closed menu.\n this._currentOpener = null;\n\n // Fire the per-show close callback exactly once, clearing it first so a\n // later bare `hide()` (or re-show) can't re-invoke a stale opener's hook.\n const onClose = this._rebuildOnClose;\n this._rebuildOnClose = null;\n onClose?.();\n\n return this;\n }\n\n /**\n * Returns the current pixel width of the rebuild-mode menu panel (the\n * content-fit width, or an explicit override set via {@link setMenuWidth}).\n *\n * @returns The current panel width in pixels.\n */\n getMenuWidth(): number {\n return this.getWidth();\n }\n\n /**\n * Pins the rebuild-mode menu panel to an explicit width, overriding the\n * default content-fit sizing. **Rebuild-mode only.**\n *\n * @param width - Width in pixels.\n */\n setMenuWidth(width: number): this {\n this.assertRebuildMode(\"setMenuWidth\");\n\n this._menuWidth = width;\n\n return this;\n }\n\n /**\n * Controls whether the menu scrolls to the bottom of its item list each time\n * it is shown. **Rebuild-mode only.**\n *\n * Use this for a menu whose latest entries sit at the bottom (e.g. a\n * chronological notification history), so the most recent items are visible\n * on open rather than the user having to scroll down. A no-op when the list\n * fits without scrolling.\n *\n * @param value - `true` to scroll to the bottom on every show.\n *\n * @returns This menu, for method chaining.\n */\n setScrollToBottomOnShow(value: boolean): this {\n this.assertRebuildMode(\"setScrollToBottomOnShow\");\n\n this._scrollToBottomOnShow = value;\n\n return this;\n }\n\n /**\n * Opens this panel positioned below the anchor element (top-level) or to the\n * right of the parent panel (submenu). Appends to `document.documentElement`.\n * **Persistent-mode only.**\n *\n * @param anchorEl - The `HTMLElement` of the triggering button or menu item.\n * @param parentPanel - When set, positions the panel as a submenu of this parent.\n */\n open(anchorEl: Handle, parentPanel?: Menu): this {\n this.assertPersistentMode(\"open\");\n\n // A provider-sourced menu re-resolves its items on every open, so labels\n // and enabled state reflect current state each time it is shown (a submenu\n // is a fresh panel per open, but a reused top-level dropdown is not).\n if (this._itemsProvider) {\n this.rebuildPersistentItems(this._itemsProvider());\n }\n\n // Clear the previous open's max-height (set by `applyViewportHeightClamp`)\n // before measuring, so a provider-sourced dropdown that grew reflects its\n // new content height rather than being capped at the old available room.\n this.setMaxSize(Number.MAX_VALUE, Number.MAX_VALUE);\n\n const totalHeight = this.getPreferredSize()?.height ?? (this._menuItems.length * MenuItem.HEIGHT + 8);\n const width = this.getWidth();\n\n const el = this.getElement(true)!;\n LayerManager.mount(el);\n\n const vp = DOM.source.getViewportSize();\n\n if (parentPanel) {\n const parentEl = parentPanel.getElement();\n const parentRect = parentEl\n ? DOM.source.getElementRect(parentEl)\n : { left: 0, right: 0, top: 0, bottom: 0 };\n const anchorRect = DOM.source.getElementRect(anchorEl);\n\n let x = parentRect.right;\n\n if (x + width > vp.width) {\n x = parentRect.left - width;\n }\n\n // A submenu grows down from the anchor item's top, and flips up\n // against that same top edge when there is more room above.\n const y = this.placeVertically(anchorRect.top, anchorRect.top, totalHeight, vp.height);\n\n this.setAutoCommitStyle(false);\n this.setX(Math.max(0, x));\n this.setY(Math.max(0, y));\n this.setAutoCommitStyle(true);\n } else {\n const anchorRect = DOM.source.getElementRect(anchorEl);\n\n let x = anchorRect.left;\n\n if (x + width > vp.width) {\n x = vp.width - width;\n }\n\n // A top-level dropdown grows down from the anchor's bottom, and\n // flips up against the anchor's top when there is more room above.\n const y = this.placeVertically(anchorRect.bottom, anchorRect.top, totalHeight, vp.height);\n\n this.setAutoCommitStyle(false);\n this.setX(Math.max(0, x));\n this.setY(Math.max(0, y));\n this.setAutoCommitStyle(true);\n }\n\n const anchorId = DOM.source.getId(anchorEl);\n\n if (anchorId) {\n this.getAria().setLabelledBy(anchorId);\n }\n\n this.setVisible(true);\n this.doLayout();\n this.fadeIn();\n\n // Join the central layer tree so the manager owns dismissal and the\n // z-stamp. A submenu opened via `open(item, this)` registers while its\n // parent menu is topmost, so it links under the parent — a pointerdown\n // inside the submenu counts as inside the parent (cross-portal\n // containment) and keeps the whole chain open.\n LayerManager.register(this);\n this.setZIndex(LayerManager.getZIndex(this));\n\n return this;\n }\n\n /**\n * Closes this panel and any open child submenus. Detaches from the DOM.\n * **Persistent-mode only.**\n */\n close(): this {\n this.assertPersistentMode(\"close\");\n\n this.closeOpenSubmenu();\n\n this.setFocusedIndex(-1);\n this.clearItemHighlights();\n\n LayerManager.unregister(this);\n\n this.fadeOutAndDetach();\n\n return this;\n }\n\n /**\n * Clears the hover highlight from every item. A click that activates an item\n * dismisses the menu, detaching the panel from the DOM under the pointer; the\n * browser fires no `mouseout` for an element removed under a stationary\n * pointer, so the hovered item's `setFocused(true)` is never undone by\n * `_onMouseOut`. `setFocusedIndex(-1)` only resets the keyboard-tracked item,\n * not one highlighted purely by hover. Persistent-mode menus reuse these item\n * elements across open/close, so without this sweep the stale highlight\n * reappears the next time the menu opens.\n */\n private clearItemHighlights(): void {\n for (const item of this._menuItems) {\n if (item instanceof MenuItem) {\n item.setFocused(false);\n }\n }\n }\n\n /**\n * Plays the standard menu-panel entrance fade. Cancels any in-flight\n * fade-out so the deferred detach skips removing the still-visible panel.\n */\n private fadeIn(): void {\n fadeShow(this, { durationMs: MENU_ANIM_DURATION_MS });\n }\n\n /**\n * Plays the standard menu-panel exit fade, then hides and detaches the\n * panel from the DOM when the transition completes. A fresh `show()` /\n * `open()` during the fade cancels the deferred detach.\n */\n private fadeOutAndDetach(): void {\n fadeHideAndDetach(this, { durationMs: MENU_ANIM_DURATION_MS });\n }\n\n /**\n * Moves keyboard focus to the item at the given index. Pass `-1` to clear focus.\n * **Persistent-mode only.**\n *\n * @param index - Zero-based item index, or `-1` to clear.\n */\n focusItem(index: number): this {\n this.assertPersistentMode(\"focusItem\");\n\n this.setFocusedIndex(index);\n\n return this;\n }\n\n /**\n * Moves focus to the next focusable item, wrapping around and skipping separators.\n * **Persistent-mode only.**\n */\n focusNext(): this {\n this.assertPersistentMode(\"focusNext\");\n\n let next = this._focusedIndex + 1;\n\n while (next < this._menuItems.length && this.isItemSeparator(next)) {\n next++;\n }\n\n if (next >= this._menuItems.length) {\n next = 0;\n\n while (next < this._menuItems.length && this.isItemSeparator(next)) {\n next++;\n }\n }\n\n this.setFocusedIndex(next);\n\n return this;\n }\n\n /**\n * Moves focus to the previous focusable item, wrapping around and skipping separators.\n * **Persistent-mode only.**\n */\n focusPrev(): this {\n this.assertPersistentMode(\"focusPrev\");\n\n let prev = this._focusedIndex - 1;\n\n while (prev >= 0 && this.isItemSeparator(prev)) {\n prev--;\n }\n\n if (prev < 0) {\n prev = this._menuItems.length - 1;\n\n while (prev >= 0 && this.isItemSeparator(prev)) {\n prev--;\n }\n }\n\n this.setFocusedIndex(prev);\n\n return this;\n }\n\n /**\n * Activates the currently focused item. No-op when no item is focused or the item\n * is disabled or a separator. **Persistent-mode only.**\n */\n activateFocused(): void {\n this.assertPersistentMode(\"activateFocused\");\n\n if (this._focusedIndex < 0 || this._focusedIndex >= this._menuItems.length) {\n return;\n }\n\n const item = this._menuItems[this._focusedIndex];\n\n if (item instanceof MenuItem && !item.isSeparator() && item.isEnabled()) {\n item.activate();\n }\n }\n\n /**\n * Returns the index of the currently focused item, or `-1` if no item is focused.\n * **Persistent-mode only.**\n *\n * @returns The focused item index, or -1.\n */\n getFocusedIndex(): number {\n this.assertPersistentMode(\"getFocusedIndex\");\n\n return this._focusedIndex;\n }\n\n /**\n * Sets an element whose subtree is excluded from the outside-click-to-close check.\n * **Persistent-mode only.**\n *\n * Used by [`MenuBar`](/api/component/menubar/classes/MenuBar) to prevent a pointerdown on its own buttons from closing the panel\n * before the button's click handler has a chance to toggle the menu.\n *\n * @param el - The element to exclude, or `null` to clear.\n */\n setExcludedElement(el: Handle | null): this {\n this.assertPersistentMode(\"setExcludedElement\");\n\n this._excludedEl = el;\n\n return this;\n }\n\n /**\n * Returns the element whose subtree is currently excluded from the\n * outside-click-to-close check, or `null` if none is set.\n *\n * @returns The excluded element, or null.\n */\n getExcludedElement(): Handle | null {\n return this._excludedEl;\n }\n\n /**\n * Disposes all [`MenuItem`](/api/component/container/classes/MenuItem) children, removing their Event listeners.\n * **Persistent-mode only.**\n */\n dispose(): void {\n this.assertPersistentMode(\"dispose\");\n\n for (const item of this._menuItems) {\n if (item instanceof MenuItem) {\n item.dispose();\n }\n }\n }\n\n /**\n * Applies the persistent-mode chrome (MenuBar dropdown CSS variables, aria role).\n */\n private applyPersistentChrome(): void {\n this.setBackgroundColor(\"var(--ts-ui-menu-bar-panel-bg, rgb(255, 255, 255))\");\n this.setInsets(new Insets(4, 0, 4, 0));\n this.setBorder({ border: \"1px solid var(--ts-ui-menu-bar-panel-border, rgb(200, 200, 200))\" });\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setShadow(\"var(--ts-ui-menu-bar-panel-shadow, 2px 4px 8px rgba(0, 0, 0, 0.15))\");\n this.getAria().setRole(\"menu\");\n this.setContain(\"layout\");\n\n this.enableVerticalScroll();\n }\n\n /**\n * Applies the rebuild-mode chrome (right-click context-menu CSS variables).\n */\n private applyRebuildChrome(): void {\n this.setVisible(false);\n this.setBackgroundColor(\"var(--ts-ui-context-menu-bg, rgb(255, 255, 255))\");\n this.setInsets(new Insets(4, 0, 4, 0));\n this.setBorder({ border: \"1px solid var(--ts-ui-context-menu-border, rgb(200, 200, 200))\" });\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setShadow(\"var(--ts-ui-context-menu-shadow, 2px 4px 8px rgba(0, 0, 0, 0.15))\");\n this.setContain(\"layout\");\n\n this.enableVerticalScroll();\n }\n\n /**\n * Wires the native vertical-scroll primitives so an over-tall menu scrolls\n * its items instead of overflowing the clamped panel height. This is the\n * `\"y\"` case of [`Panel.setAutoScroll`](/api/core/classes/Panel#setautoscroll)\n * replicated directly: `overflow-x: hidden` (so a `visible` x-axis does not\n * compute to `auto` and sprout a spurious horizontal scrollbar), `overflow-y:\n * auto`, and the layout manager's vertical overflow flag so the `VBox` lays\n * items out past the clamped inner height rather than compressing them.\n */\n private enableVerticalScroll(): void {\n this.setOverflowX(\"hidden\");\n this.setOverflowY(\"auto\");\n\n (this.getLayoutManager() as VBox).setOverflowing(false, true);\n }\n\n /**\n * Caps the menu's height to the vertical room available at its anchored\n * position, then applies the content height. Because `Menu` is a\n * `clampsToContentSize()` component, `setHeight` runs `contentHeight` through\n * `clampHeight`, which caps it at `availableHeight`; when the content fits no\n * clamp fires, and when it overflows the height is capped and the\n * `overflow-y: auto` scrollbar engages. Width is left unconstrained via the\n * `Number.MAX_VALUE` \"no constraint\" sentinel — horizontal scroll is a\n * non-goal.\n *\n * @param availableHeight - Vertical room (px) the menu may occupy at its anchor.\n * @param contentHeight - The unclamped preferred height (px) of the menu's items.\n */\n private applyViewportHeightClamp(availableHeight: number, contentHeight: number): void {\n this.setMaxSize(Number.MAX_VALUE, Math.max(0, availableHeight));\n this.setHeight(contentHeight);\n }\n\n /**\n * Resolves the persistent-mode panel's top coordinate and applies the\n * matching height clamp. The menu grows downward from `growTop` unless the\n * content overflows the room below *and* the room above the anchor is\n * larger, in which case it flips to grow upward from `anchorTop`. Delegates\n * the room/flip arithmetic to {@link positionFlexibleAnchored}, which measures\n * the room against the side the menu actually grows toward — never re-derived\n * from a clamped top, which would let a flipped, viewport-pinned menu grow\n * back down across its anchor.\n *\n * @param growTop - The viewport edge the menu grows downward from.\n * @param anchorTop - The anchor edge the menu flips up against.\n * @param totalHeight - The unclamped preferred height (px) of the menu's items.\n * @param viewportHeight - The current viewport height (px).\n * @returns The resolved top coordinate (px) for the panel.\n */\n private placeVertically(growTop: number, anchorTop: number, totalHeight: number, viewportHeight: number): number {\n const { start, available } = positionFlexibleAnchored(anchorTop, growTop, totalHeight, viewportHeight, VIEWPORT_MARGIN);\n\n this.applyViewportHeightClamp(available, totalHeight);\n\n return start;\n }\n\n /**\n * Tear down the current persistent items and rebuild them from `configs`.\n * Used by `open()` to re-resolve a provider-sourced dropdown each time it\n * shows, so its labels / enabled state track current state. Mirrors the\n * rebuild-mode `show()` teardown, then defers to {@link buildPersistentItems}.\n *\n * @param configs - The freshly-resolved item configurations.\n */\n private rebuildPersistentItems(configs: MenuItemConfig[]): void {\n this.closeOpenSubmenu();\n\n for (const item of this._menuItems) {\n if (item instanceof MenuItem) {\n item.dispose();\n }\n }\n\n this._menuItems = [];\n this._focusedIndex = -1;\n this.removeAllComponents();\n\n this.buildPersistentItems(configs);\n }\n\n /**\n * Builds the item list for persistent mode and sets the panel width.\n *\n * @param items - The item configs from the constructor.\n */\n private buildPersistentItems(items: MenuItemConfig[]): void {\n this.pauseLayout();\n\n for (const config of items) {\n const item = new MenuItem(\n config,\n () => { config.action?.(); this._onClose!(); },\n (hoveredItem) => { this.handleItemOpenSubmenu(hoveredItem); }\n );\n\n this.addComponent(item);\n this._menuItems.push(item);\n }\n\n this.resumeLayout();\n\n this.setWidth(this.layOutColumns());\n }\n\n /**\n * Updates the focused-item highlight, clearing the previous item and setting the new one.\n *\n * @param index - The new focused index, or -1 to clear.\n */\n private setFocusedIndex(index: number): void {\n if (this._focusedIndex >= 0 && this._focusedIndex < this._menuItems.length) {\n const prev = this._menuItems[this._focusedIndex];\n\n if (prev instanceof MenuItem) {\n prev.setFocused(false);\n }\n }\n\n this._focusedIndex = index;\n\n if (index >= 0 && index < this._menuItems.length) {\n const next = this._menuItems[index];\n\n if (next instanceof MenuItem) {\n next.setFocused(true);\n }\n }\n }\n\n /**\n * Returns `true` if the item at the given index should be skipped during focus traversal.\n *\n * @param index - Zero-based item index.\n * @returns Whether the item is a separator (or [`MenuSeparator`](/api/component/container/classes/MenuSeparator) instance).\n */\n private isItemSeparator(index: number): boolean {\n const item = this._menuItems[index];\n\n if (item instanceof MenuSeparator) {\n return true;\n }\n\n if (item instanceof MenuItem) {\n return item.isSeparator();\n }\n\n return false;\n }\n\n /**\n * Closes and forgets this menu's open child submenu, if any. Shared by the\n * teardown paths (`hide` / `close`) and by the submenu switch in\n * `handleItemOpenSubmenu` when a different item takes the child slot.\n */\n private closeOpenSubmenu(): void {\n if (this._openSubmenuPanel) {\n this._openSubmenuPanel.close();\n this._openSubmenuItem?.getAria().setExpanded(false);\n this._openSubmenuPanel = null;\n this._openSubmenuItem = null;\n }\n }\n\n /**\n * Closes the whole menu chain through the current mode's close path: the\n * persistent-mode `onClose` callback (a menubar dropdown), or `hide()` for a\n * rebuild-mode context menu — which also tears down any open child submenu.\n * Used by an activated submenu leaf and the outside-click / window-blur\n * dismissals, so a submenu selection closes the parent context menu too.\n */\n private dismissAll(): void {\n if (this._persistent) {\n this._onClose!();\n } else {\n this.hide();\n }\n }\n\n // ----- DismissableLayer -----\n\n /**\n * Returns the menu panel's root element for the central layer tree.\n *\n * @returns The menu's element, or null when not yet rendered.\n */\n getLayerElement(): Handle | null {\n return this.getElement() ?? null;\n }\n\n /**\n * Returns the dismiss mode the document-level handlers consult. A menu is\n * `\"click-outside\"`: dismissed by a `pointerdown` outside its layer subtree\n * (and its excluded trigger) and by a window blur, but never by a focus\n * move — exactly the pointerdown + window-blur behaviour the menu owned\n * before it joined the layer tree.\n *\n * @returns The layer dismiss mode.\n */\n getDismissMode(): LayerDismissMode {\n return \"click-outside\";\n }\n\n /**\n * Advisory close request from the manager (an outside `pointerdown`, a\n * window blur, or Escape). Routes through the mode-aware close chain: a\n * persistent (MenuBar) menu fires its `onClose`, a rebuild (context) menu\n * calls `hide()`; either way any open submenu is torn down.\n */\n requestClose(): void {\n this.dismissAll();\n }\n\n /**\n * Returns the trigger element excluded from the manager's outside-pointerdown\n * test — the context-menu opener passed to {@link show} / {@link toggleFor},\n * or the [`MenuBar`](/api/component/menubar/classes/MenuBar) button set via\n * {@link setExcludedElement} — so the gesture that opened the menu does not\n * immediately re-close it.\n *\n * @returns The excluded element, or null.\n */\n getAnchorElement(): Handle | null {\n return this._excludedEl;\n }\n\n /**\n * Returns the dropdown z-index band so an unrelated top-level menu stacks in\n * the dropdown family. A submenu — or a menu opened while another layer is\n * topmost — inherits its opener's band instead, so it rises above the\n * surface it was opened from.\n *\n * @returns The dropdown band base.\n */\n getBand(): number {\n return LayerManager.Band.Dropdown;\n }\n\n /**\n * Mirrors a manager-allocated z-index onto the element when the layer this\n * menu was opened inside is raised via the manager's bring-to-front path,\n * so an open menu never falls behind the surface it belongs to.\n *\n * @param zIndex - The fresh z-index assigned by the manager.\n */\n onZIndexChanged(zIndex: number): void {\n this.setZIndex(zIndex);\n }\n\n /**\n * Handles the open-submenu signal from a hovered or activated [`MenuItem`](/api/component/container/classes/MenuItem).\n *\n * Closes any existing child submenu when the item has no submenu (or is\n * disabled); opens or switches to the child panel when it does.\n *\n * @param item - The [`MenuItem`](/api/component/container/classes/MenuItem) that triggered the signal.\n */\n private handleItemOpenSubmenu(item: MenuItem): void {\n // A disabled item opens no submenu (even though it has one); like a plain\n // item, hovering it just closes any sibling submenu that is open.\n if (!item.hasSubmenu() || !item.isEnabled()) {\n this.closeOpenSubmenu();\n\n return;\n }\n\n if (this._openSubmenuItem === item) {\n return;\n }\n\n this.closeOpenSubmenu();\n\n const submenuPanel = new Menu(\n item.getSubmenuConfig()!.items,\n () => { this.dismissAll(); }\n );\n\n this._openSubmenuPanel = submenuPanel;\n this._openSubmenuItem = item;\n item.getAria().setExpanded(true);\n\n submenuPanel.setExcludedElement(this.getElement(true)!);\n submenuPanel.open(item.getElement(true)!, this);\n }\n\n /**\n * Throws if the method called is not valid in the current mode (rebuild-only check).\n *\n * @param method - Name of the method that was invoked, used in the error message.\n */\n private assertRebuildMode(method: string): void {\n if (this._persistent) {\n throw new Error(`Menu.${method}() is only valid in rebuild mode (constructed without arguments).`);\n }\n }\n\n /**\n * Throws if the method called is not valid in the current mode (persistent-only check).\n *\n * @param method - Name of the method that was invoked, used in the error message.\n */\n private assertPersistentMode(method: string): void {\n if (!this._persistent) {\n throw new Error(`Menu.${method}() is only valid in persistent mode (constructed with items and onClose).`);\n }\n }\n}\n\nconst MenuCallable = callable(Menu);\ntype MenuCallable = Menu;\nexport {\n Menu as _Menu,\n MenuCallable as Menu\n};\n"],"mappings":"2VA6gBA,IAAM,EAAmB,EAAS,MAha5B,iBAAiB,CAAU,CAG7B,OAAgB,OAAiB,GAEjC,OAAwB,iBAA2B,EAEnD,OAAgB,WAAqB,EAErC,OAAgB,UAAoB,GAEpC,OAAgB,aAAuB,GAEvC,OAAgB,UAAoB,EAKpC,OAAgB,SAAmB,GAEnC,QACA,YACA,eACA,cAEA,UAAiC,KACjC,WAAmC,KACnC,WAAkC,KAClC,cAAqC,KACrC,aAAoC,KAMpC,WAAoC,KACpC,aAAsC,KAEtC,cAA8D,KAE9D,aACA,YACA,SAUA,YACI,EACA,EACA,EACA,EAAqC,WACrC,EACF,CAUE,GAPA,MAAM,EAEN,KAAK,QAAU,EACf,KAAK,YAAc,EACnB,KAAK,eAAiB,EACtB,KAAK,cAAgB,EAEjB,EAAO,UAAW,CAClB,KAAK,UAAU,SAAS,gBAAgB,EACxC,KAAK,iBAAiB,EAAG,SAAS,gBAAgB,EAClD,KAAK,mBAAmB,aAAa,EACrC,KAAK,kBACD,YACA,yBAAyB,EAAa,sCAC1C,EACA,KAAK,kBAAkB,SAAU,OAAO,EACxC,KAAK,QAAQ,CAAC,CAAC,QAAQ,WAAW,EAElC,KAAK,iBAAqB,CAAC,EAC3B,KAAK,gBAAoB,CAAC,EAC1B,KAAK,aAAiB,CAAC,EAEnB,GACA,KAAK,aAAa,CAAO,EAG7B,MACJ,CAEA,IAAM,EAAU,EAAO,UAAY,GAEnC,KAAK,UAAU,SAAS,MAAM,EAC9B,KAAK,iBAAiB,EAAG,SAAS,MAAM,EACxC,KAAK,mBAAmB,aAAa,EACrC,KAAK,kBAAkB,WAAY,uDAAuD,EAC1F,KAAK,UAAU,EAAU,UAAY,SAAS,EAC9C,KAAK,QAAQ,CAAC,CAAC,QAAQ,UAAU,EAE5B,IACD,KAAK,mBACD,eAAe,EAAa,0CAChC,EACA,KAAK,QAAQ,CAAC,CAAC,YAAY,EAAI,GAG/B,EAAO,OACP,KAAK,WAAa,IAAI,EAAM,EAAO,KAAK,EACxC,KAAK,WAAW,iBAAiB,MAAM,EACvC,KAAK,WAAW,iBAAiB,GAAI,EAAE,EAEnC,EAAO,YACP,KAAK,WAAW,mBAAmB,EAAO,UAAU,EAGxD,KAAK,aAAa,KAAK,UAAU,IAEjC,KAAK,UAAY,IAAI,EAAK,EAAO,MAAQ,EAAE,EAC3C,KAAK,UAAU,iBAAiB,MAAM,EACtC,KAAK,UAAU,eAAe,SAAS,MAAM,EAC7C,KAAK,UAAU,WAAW,CAAC,CAAC,EAAO,IAAI,EACvC,KAAK,aAAa,KAAK,SAAS,GAGpC,KAAK,WAAa,IAAI,EAAK,EAAO,MAAQ,EAAE,EAC5C,KAAK,WAAW,iBAAiB,MAAM,EACvC,KAAK,WAAW,eAAe,SAAS,MAAM,EAC9C,KAAK,WAAW,cAAc,QAAQ,EACtC,KAAK,WAAW,YAAY,QAAQ,EACpC,KAAK,WAAW,gBAAgB,UAAU,EAC1C,KAAK,aAAa,KAAK,UAAU,EAE7B,EAAO,WACP,KAAK,cAAgB,IAAI,EAAK,EAAO,QAAQ,EAC7C,KAAK,cAAc,iBAAiB,MAAM,EAC1C,KAAK,cAAc,eAAe,SAAS,MAAM,EACjD,KAAK,cAAc,aAAa,MAAM,EACtC,KAAK,cAAc,mBACf,eAAe,EAAa,0CAChC,EACA,KAAK,aAAa,KAAK,aAAa,GAGpC,KAAK,WAAW,IAChB,KAAK,aAAe,IAAI,EAAK,GAAG,EAChC,KAAK,aAAa,iBAAiB,MAAM,EACzC,KAAK,aAAa,eAAe,SAAS,MAAM,EAChD,KAAK,aAAa,aAAa,QAAQ,EACvC,KAAK,aAAa,mBACd,eAAe,EAAa,0CAChC,EACA,KAAK,aAAa,KAAK,YAAY,EACnC,KAAK,QAAQ,CAAC,CAAC,YAAY,MAAM,EACjC,KAAK,QAAQ,CAAC,CAAC,YAAY,EAAK,GAGpC,KAAK,iBAAqB,CACtB,KAAK,WAAW,EAAI,EAIhB,GAAW,KAAK,WAAW,EAC3B,KAAK,cAAgB,eAAiB,CAClC,KAAK,cAAgB,KACrB,KAAK,eAAe,IAAI,CAC5B,EAAG,GAAG,EAEN,KAAK,eAAe,IAAI,CAEhC,EAEA,KAAK,gBAAoB,CACrB,KAAK,WAAW,EAAK,EAEjB,KAAK,gBAAkB,OACvB,aAAa,KAAK,aAAa,EAC/B,KAAK,cAAgB,KAE7B,EAEA,KAAK,aAAiB,CACd,GAAW,CAAC,KAAK,WAAW,GAC5B,KAAK,YAAY,CAEzB,EAEA,EAAM,YAAY,KAAM,YAAa,KAAK,YAAY,EACtD,EAAM,YAAY,KAAM,WAAY,KAAK,WAAW,EACpD,EAAM,YAAY,KAAM,QAAS,KAAK,QAAQ,EAE1C,GACA,KAAK,aAAa,CAAO,CAEjC,CAQA,aAAuB,EAAgC,CAgBnD,OAfA,MAAM,aAAa,CAAO,EAEtB,EAAQ,OAAS,IAAA,IAAa,KAAK,YACnC,KAAK,WAAW,QAAQ,EAAQ,IAAI,EAGpC,EAAQ,UAAY,IAAA,KACpB,KAAK,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAQ,OAAO,EAC3C,KAAK,UAAU,EAAQ,QAAU,UAAY,SAAS,GAGtD,EAAQ,UAAY,IAAA,IACpB,KAAK,WAAW,EAAQ,OAAO,EAG5B,IACX,CAOA,YAAsB,CAClB,MAAO,CAAC,CAAC,KAAK,QAAQ,OAC1B,CAGA,SAAmB,CACf,MAAO,CAAC,CAAC,KAAK,QAAQ,MAAQ,CAAC,CAAC,KAAK,QAAQ,KACjD,CAGA,gBAAyB,CACrB,OAAO,KAAK,KAAK,KAAK,YAAY,iBAAiB,CAAC,EAAE,OAAS,CAAC,CACpE,CAGA,mBAA4B,CAKxB,MAJI,CAAC,KAAK,QAAQ,UAAY,KAAK,gBAAkB,KAC1C,EAGJ,KAAK,KAAK,KAAK,cAAc,iBAAiB,CAAC,EAAE,OAAS,CAAC,CACtE,CAUA,WAAW,EAAmB,EAA2B,CACrD,KAAK,WAAa,EAClB,KAAK,aAAe,EAEpB,KAAK,eAAe,CACxB,CAOA,kBAAsC,CAClC,OAAO,KAAK,QAAQ,SAAW,IACnC,CAOA,WAAW,EAAwB,CAO/B,OANA,KAAK,mBACD,EACM,eAAe,KAAK,cAAc,2CAClC,aACV,EAEO,IACX,CAOA,aAAuB,CACnB,MAAO,CAAC,CAAC,KAAK,QAAQ,SAC1B,CAOA,WAAqB,CACjB,OAAO,KAAK,QAAQ,UAAY,EACpC,CAQA,UAAiB,CACT,KAAK,YAAY,GAAK,CAAC,KAAK,UAAU,IAItC,KAAK,WAAW,EAChB,KAAK,eAAe,IAAI,EAExB,KAAK,YAAY,EAEzB,CAKA,SAAgB,CACR,KAAK,gBAAkB,OACvB,aAAa,KAAK,aAAa,EAC/B,KAAK,cAAgB,MAGzB,EAAM,eAAe,KAAM,YAAa,KAAK,YAAY,EACzD,EAAM,eAAe,KAAM,WAAY,KAAK,WAAW,EACvD,EAAM,eAAe,KAAM,QAAS,KAAK,QAAQ,CACrD,CAQA,aAA6B,CAKzB,OAJI,KAAK,aAAe,KACb,KAGJ,KAAK,kBAAkB,KAAK,WAAW,YAAY,CAAC,CAC/D,CAOA,UAAiB,CAGb,GAFA,MAAM,SAAS,EAEX,KAAK,QAAQ,UACb,OAAO,KAGX,IAAM,EAAI,SAAS,OACb,EAAa,KAAK,SAAS,EAC3B,EAAc,CAAC,CAAC,KAAK,QAAQ,UAAY,KAAK,gBAAkB,KAChE,EAAS,KAAK,WAAW,EAIzB,EAAc,KAAK,aAAe,KAAK,QAAQ,EAAI,SAAS,UAAY,SAAS,YACjF,EAAc,KAAK,cAAgB,KAAK,eAAe,EAE7D,GAAI,KAAK,WAAY,CACjB,IAAM,EAAQ,KAAK,WAAW,iBAAiB,GAAK,CAAE,MAAO,GAAI,OAAQ,EAAG,EACtE,EAAQ,KAAK,IAAI,EAAG,KAAK,OAAO,EAAI,EAAK,QAAU,CAAC,CAAC,EAE3D,KAAK,WAAW,KAAK,CAAC,EACtB,KAAK,WAAW,KAAK,CAAK,EAC1B,KAAK,WAAW,SAAS,EAAK,KAAK,EACnC,KAAK,WAAW,UAAU,EAAK,MAAM,CACzC,MAAW,KAAK,YACZ,KAAK,UAAU,KAAK,CAAC,EACrB,KAAK,UAAU,KAAK,CAAC,EACrB,KAAK,UAAU,SAAS,EAAE,EAC1B,KAAK,UAAU,UAAU,CAAC,GA2B9B,OAvBI,KAAK,aACL,KAAK,WAAW,KAAK,CAAS,EAC9B,KAAK,WAAW,KAAK,CAAC,EACtB,KAAK,WAAW,SAAS,CAAW,EACpC,KAAK,WAAW,UAAU,CAAC,GAI3B,GAAU,KAAK,eACf,KAAK,aAAa,KAAK,EAAa,SAAS,UAAY,SAAS,YAAY,EAC9E,KAAK,aAAa,KAAK,CAAC,EACxB,KAAK,aAAa,SAAS,SAAS,YAAY,EAChD,KAAK,aAAa,UAAU,CAAC,GAI7B,GAAe,KAAK,gBACpB,KAAK,cAAc,KAAK,EAAY,EAAc,SAAS,QAAQ,EACnE,KAAK,cAAc,KAAK,CAAC,EACzB,KAAK,cAAc,SAAS,KAAK,kBAAkB,CAAC,EACpD,KAAK,cAAc,UAAU,CAAC,GAG3B,IACX,CACJ,CAE0C,ECzfpC,EAA8D,CAAC,EAkC/D,EAAwB,EAAS,MAzBjC,sBAAsB,CAAgC,CAGxD,OAAgB,OAAiB,EAOjC,YAAY,EAAqC,WAAY,EAAgC,CACzF,MAAM,EAAS,CAA4B,EAE3C,KAAK,UAAU,cAAc,MAAM,EACnC,KAAK,iBAAiB,EAAG,cAAc,MAAM,EAC7C,KAAK,mBAAmB,aAAa,EACrC,KAAK,kBACD,YACA,yBAAyB,EAAa,sCAC1C,EACA,KAAK,kBAAkB,SAAU,OAAO,EACxC,KAAK,QAAQ,CAAC,CAAC,QAAQ,WAAW,CACtC,CACJ,CAEoD,EChC9C,EAAiB,IACjB,EAAiB,IAGjB,EAAwB,IAKxB,EAAkB,EAWxB,SAAS,UAAU,EAAW,EAAiB,CAC3C,MAAO,CAAE,IAAG,IAAG,KAAM,EAAG,IAAK,EAAG,MAAO,EAAG,OAAQ,EAAG,MAAO,EAAG,OAAQ,CAAE,CAC7E,CAeA,SAAS,iBAAiB,EAAkB,EAAY,EAAyB,CAC7E,IAAM,EAAI,EAAyB,EAAW,IAAK,EAAW,OAAQ,EAAK,OAAQ,EAAG,OAAQ,CAAe,EAM7G,MAAO,CAAE,EALC,EAAgB,EAAW,KAAM,EAAW,MAAO,EAAK,MAAO,EAAG,MAAO,CAK1E,EAAG,EAAG,EAAE,MAAO,UAAW,EAAE,SAAU,CACnD,CA0hCA,IAAM,EAAe,EAAS,MAr/BxB,aAAa,CAAsC,CAErD,YAGA,eACA,SACA,WAAsD,CAAC,EACvD,cAAgC,GAChC,kBAAyC,KACzC,iBAA4C,KAC5C,YAAqC,KAGrC,WAAoC,KACpC,gBAA+C,KAC/C,eAAwC,KAGxC,sBAAyC,GAoBzC,YAAY,EAAqD,EAAsB,CACnF,MAAM,EAEN,KAAK,YAAc,IAAU,IAAA,GAC7B,KAAK,eAAiB,OAAO,GAAU,WAAa,EAAQ,KAC5D,KAAK,SAAW,GAAW,KAE3B,IAAM,EAAO,IAAI,EAEjB,EAAK,oBAAoB,CAAC,EAC1B,EAAK,cAAc,EAAI,EAEvB,KAAK,iBAAiB,CAAI,EAEtB,KAAK,aACL,KAAK,sBAAsB,EAGvB,KAAK,iBAAmB,MACxB,KAAK,qBAAqB,CAAyB,GAGvD,KAAK,mBAAmB,CAEhC,CAaA,eAAgC,CAC5B,IAAM,EAAQ,KAAK,WAAW,OACzB,GAAqB,aAAa,GAAY,CAAC,EAAE,YAAY,CAClE,EAEM,EAAe,EAAM,KAAK,GAAK,EAAE,QAAQ,CAAC,EAAI,EAAS,UAAY,EAAS,WAC5E,EAAe,EAAM,QAAQ,EAAG,IAAM,KAAK,IAAI,EAAG,EAAE,eAAe,CAAC,EAAG,CAAC,EACxE,EAAe,EAAM,QAAQ,EAAG,IAAM,KAAK,IAAI,EAAG,EAAE,kBAAkB,CAAC,EAAG,CAAC,EAC3E,EAAe,EAAM,KAAK,GAAK,EAAE,WAAW,CAAC,EAC7C,EAAe,KAAK,IAAI,EAAa,EAAa,EAAS,aAAe,CAAC,EAC3E,EAAe,EAAY,EAAI,EAAS,SAAW,EAAY,EAE/D,EAAU,EAAY,EAAW,EAAe,EAAS,UACzD,EAAU,KAAK,IAAI,EAAgB,KAAK,IAAI,EAAgB,CAAO,CAAC,EAIpE,EAAc,KAAK,IAAI,EAAU,EAAQ,EAAY,EAAe,EAAS,SAAS,EAE5F,IAAK,IAAM,KAAQ,EACf,EAAK,WAAW,EAAW,CAAW,EAG1C,OAAO,CACX,CAuBA,KAAK,EAAW,EAAW,EAA2B,EAAsB,EAAiC,CACzG,KAAK,kBAAkB,MAAM,EAM7B,IAAM,EAAK,EAAI,OAAO,gBAAgB,EAEtC,OAAO,KAAK,aACR,UAAU,EAAK,MAAM,EAAG,EAAG,EAAG,KAAK,EAAG,EAAK,MAAM,EAAG,EAAG,EAAG,MAAM,CAAC,EACjE,EAAS,GAAW,KAAM,GAAa,IAC3C,CACJ,CAgBA,aAAqB,EAAkB,EAA2B,EAA8B,EAAgC,CAC5H,KAAK,gBAAkB,EACvB,KAAK,YAAc,EAEnB,IAAK,IAAM,KAAQ,KAAK,WAChB,aAAgB,GAChB,EAAK,QAAQ,EAIrB,KAAK,WAAa,CAAC,EACnB,KAAK,oBAAoB,EAEzB,KAAK,YAAY,EAEjB,IAAK,IAAM,KAAU,EAAS,CAC1B,IAAM,EAAiC,EAAO,YAAc,GACtD,IAAI,EAAc,cAAc,EAChC,IAAI,EACF,MACM,CACF,EAAO,SAAS,EAChB,KAAK,KAAK,CACd,EACC,GAAgB,CAAE,KAAK,sBAAsB,CAAW,CAAG,EAC5D,cACJ,EAEJ,KAAK,aAAa,CAAI,EACtB,KAAK,WAAW,KAAK,CAAI,CAC7B,CAEA,KAAK,aAAa,EAElB,IAAM,EAAe,KAAK,cAAc,EAClC,EAAe,KAAK,YAAc,EAExC,KAAK,SAAS,CAAY,EAQ1B,KAAK,WAAW,OAAO,UAAW,OAAO,SAAS,EAElD,IAAM,EAAc,KAAK,iBAAiB,CAAC,EAAE,QAAU,EAEjD,EAAK,KAAK,WAAW,EAAI,EAEzB,EAAK,EAAI,OAAO,gBAAgB,EAchC,EAAS,EATG,iBAAiB,EAAY,CAAE,MAAO,EAAc,OAAQ,CAAY,EAAG,CAAE,CAAC,CAAC,UASxD,EAAI,OAAO,kBAAkB,EAAI,EAE1E,KAAK,UAAU,IAAI,EAAO,EAAG,EAAQ,EAAG,CAAC,CAAC,EAC1C,KAAK,SAAS,EAAe,CAAM,EAEnC,IAAM,EAAY,iBAAiB,EAAY,CAAE,MAAO,KAAK,SAAS,EAAG,OAAQ,CAAY,EAAG,CAAE,EA8BlG,OA5BA,KAAK,KAAK,EAAU,CAAC,EACrB,KAAK,KAAK,EAAU,CAAC,EACrB,KAAK,yBAAyB,EAAU,UAAW,CAAW,EAE9D,KAAK,eAAe,EAEpB,EAAa,MAAM,CAAE,EAErB,KAAK,WAAW,EAAI,EACpB,KAAK,OAAO,EAOZ,EAAa,SAAS,IAAI,EAC1B,KAAK,UAAU,EAAa,UAAU,IAAI,CAAC,EAMvC,KAAK,wBACL,KAAK,YAAY,EACjB,KAAK,aAAa,KAAK,gBAAgB,CAAC,GAGrC,IACX,CAoCA,UAAU,EAAkB,EAAkB,EAA2B,EAA4B,CA2BjG,OA1BA,KAAK,kBAAkB,WAAW,EAM9B,KAAK,iBAAmB,GACxB,KAAK,KAAK,EAEH,MAOP,EAAQ,SAAW,GACnB,IAAU,EAEH,OAIX,KAAK,aAAa,EAAY,EAAS,GAAW,KAAM,CAAQ,EAChE,KAAK,eAAiB,EAEf,KACX,CAOA,MAAa,CACT,KAAK,kBAAkB,MAAM,EAE7B,KAAK,iBAAiB,EAEtB,EAAa,WAAW,IAAI,EAE5B,KAAK,iBAAiB,EAItB,KAAK,eAAiB,KAItB,IAAM,EAAU,KAAK,gBAIrB,MAHA,MAAK,gBAAkB,KACvB,IAAU,EAEH,IACX,CAQA,cAAuB,CACnB,OAAO,KAAK,SAAS,CACzB,CAQA,aAAa,EAAqB,CAK9B,OAJA,KAAK,kBAAkB,cAAc,EAErC,KAAK,WAAa,EAEX,IACX,CAeA,wBAAwB,EAAsB,CAK1C,OAJA,KAAK,kBAAkB,yBAAyB,EAEhD,KAAK,sBAAwB,EAEtB,IACX,CAUA,KAAK,EAAkB,EAA0B,CAC7C,KAAK,qBAAqB,MAAM,EAK5B,KAAK,gBACL,KAAK,uBAAuB,KAAK,eAAe,CAAC,EAMrD,KAAK,WAAW,OAAO,UAAW,OAAO,SAAS,EAElD,IAAM,EAAc,KAAK,iBAAiB,CAAC,EAAE,QAAW,KAAK,WAAW,OAAS,EAAS,OAAS,EAC7F,EAAc,KAAK,SAAS,EAE5B,EAAK,KAAK,WAAW,EAAI,EAC/B,EAAa,MAAM,CAAE,EAErB,IAAM,EAAK,EAAI,OAAO,gBAAgB,EAEtC,GAAI,EAAa,CACb,IAAM,EAAW,EAAY,WAAW,EAClC,EAAa,EACb,EAAI,OAAO,eAAe,CAAQ,EAClC,CAAE,KAAM,EAAG,MAAO,EAAG,IAAK,EAAG,OAAQ,CAAE,EACvC,EAAa,EAAI,OAAO,eAAe,CAAQ,EAEjD,EAAI,EAAW,MAEf,EAAI,EAAQ,EAAG,QACf,EAAI,EAAW,KAAO,GAK1B,IAAM,EAAI,KAAK,gBAAgB,EAAW,IAAK,EAAW,IAAK,EAAa,EAAG,MAAM,EAErF,KAAK,mBAAmB,EAAK,EAC7B,KAAK,KAAK,KAAK,IAAI,EAAG,CAAC,CAAC,EACxB,KAAK,KAAK,KAAK,IAAI,EAAG,CAAC,CAAC,EACxB,KAAK,mBAAmB,EAAI,CAChC,KAAO,CACH,IAAM,EAAa,EAAI,OAAO,eAAe,CAAQ,EAEjD,EAAI,EAAW,KAEf,EAAI,EAAQ,EAAG,QACf,EAAI,EAAG,MAAQ,GAKnB,IAAM,EAAI,KAAK,gBAAgB,EAAW,OAAQ,EAAW,IAAK,EAAa,EAAG,MAAM,EAExF,KAAK,mBAAmB,EAAK,EAC7B,KAAK,KAAK,KAAK,IAAI,EAAG,CAAC,CAAC,EACxB,KAAK,KAAK,KAAK,IAAI,EAAG,CAAC,CAAC,EACxB,KAAK,mBAAmB,EAAI,CAChC,CAEA,IAAM,EAAW,EAAI,OAAO,MAAM,CAAQ,EAkB1C,OAhBI,GACA,KAAK,QAAQ,CAAC,CAAC,cAAc,CAAQ,EAGzC,KAAK,WAAW,EAAI,EACpB,KAAK,SAAS,EACd,KAAK,OAAO,EAOZ,EAAa,SAAS,IAAI,EAC1B,KAAK,UAAU,EAAa,UAAU,IAAI,CAAC,EAEpC,IACX,CAMA,OAAc,CAYV,OAXA,KAAK,qBAAqB,OAAO,EAEjC,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EAAE,EACvB,KAAK,oBAAoB,EAEzB,EAAa,WAAW,IAAI,EAE5B,KAAK,iBAAiB,EAEf,IACX,CAYA,qBAAoC,CAChC,IAAK,IAAM,KAAQ,KAAK,WAChB,aAAgB,GAChB,EAAK,WAAW,EAAK,CAGjC,CAMA,QAAuB,CACnB,EAAS,KAAM,CAAE,WAAY,CAAsB,CAAC,CACxD,CAOA,kBAAiC,CAC7B,EAAkB,KAAM,CAAE,WAAY,CAAsB,CAAC,CACjE,CAQA,UAAU,EAAqB,CAK3B,OAJA,KAAK,qBAAqB,WAAW,EAErC,KAAK,gBAAgB,CAAK,EAEnB,IACX,CAMA,WAAkB,CACd,KAAK,qBAAqB,WAAW,EAErC,IAAI,EAAO,KAAK,cAAgB,EAEhC,KAAO,EAAO,KAAK,WAAW,QAAU,KAAK,gBAAgB,CAAI,GAC7D,IAGJ,GAAI,GAAQ,KAAK,WAAW,OAGxB,IAFA,EAAO,EAEA,EAAO,KAAK,WAAW,QAAU,KAAK,gBAAgB,CAAI,GAC7D,IAMR,OAFA,KAAK,gBAAgB,CAAI,EAElB,IACX,CAMA,WAAkB,CACd,KAAK,qBAAqB,WAAW,EAErC,IAAI,EAAO,KAAK,cAAgB,EAEhC,KAAO,GAAQ,GAAK,KAAK,gBAAgB,CAAI,GACzC,IAGJ,GAAI,EAAO,EAGP,IAFA,EAAO,KAAK,WAAW,OAAS,EAEzB,GAAQ,GAAK,KAAK,gBAAgB,CAAI,GACzC,IAMR,OAFA,KAAK,gBAAgB,CAAI,EAElB,IACX,CAMA,iBAAwB,CAGpB,GAFA,KAAK,qBAAqB,iBAAiB,EAEvC,KAAK,cAAgB,GAAK,KAAK,eAAiB,KAAK,WAAW,OAChE,OAGJ,IAAM,EAAO,KAAK,WAAW,KAAK,eAE9B,aAAgB,GAAY,CAAC,EAAK,YAAY,GAAK,EAAK,UAAU,GAClE,EAAK,SAAS,CAEtB,CAQA,iBAA0B,CAGtB,OAFA,KAAK,qBAAqB,iBAAiB,EAEpC,KAAK,aAChB,CAWA,mBAAmB,EAAyB,CAKxC,OAJA,KAAK,qBAAqB,oBAAoB,EAE9C,KAAK,YAAc,EAEZ,IACX,CAQA,oBAAoC,CAChC,OAAO,KAAK,WAChB,CAMA,SAAgB,CACZ,KAAK,qBAAqB,SAAS,EAEnC,IAAK,IAAM,KAAQ,KAAK,WAChB,aAAgB,GAChB,EAAK,QAAQ,CAGzB,CAKA,uBAAsC,CAClC,KAAK,mBAAmB,oDAAoD,EAC5E,KAAK,UAAU,IAAI,EAAO,EAAG,EAAG,EAAG,CAAC,CAAC,EACrC,KAAK,UAAU,CAAE,OAAQ,kEAAmE,CAAC,EAC7F,KAAK,gBAAgB,iCAAiC,EACtD,KAAK,UAAU,qEAAqE,EACpF,KAAK,QAAQ,CAAC,CAAC,QAAQ,MAAM,EAC7B,KAAK,WAAW,QAAQ,EAExB,KAAK,qBAAqB,CAC9B,CAKA,oBAAmC,CAC/B,KAAK,WAAW,EAAK,EACrB,KAAK,mBAAmB,kDAAkD,EAC1E,KAAK,UAAU,IAAI,EAAO,EAAG,EAAG,EAAG,CAAC,CAAC,EACrC,KAAK,UAAU,CAAE,OAAQ,gEAAiE,CAAC,EAC3F,KAAK,gBAAgB,iCAAiC,EACtD,KAAK,UAAU,mEAAmE,EAClF,KAAK,WAAW,QAAQ,EAExB,KAAK,qBAAqB,CAC9B,CAWA,sBAAqC,CACjC,KAAK,aAAa,QAAQ,EAC1B,KAAK,aAAa,MAAM,EAExB,KAAM,iBAAiB,CAAC,CAAU,eAAe,GAAO,EAAI,CAChE,CAeA,yBAAiC,EAAyB,EAA6B,CACnF,KAAK,WAAW,OAAO,UAAW,KAAK,IAAI,EAAG,CAAe,CAAC,EAC9D,KAAK,UAAU,CAAa,CAChC,CAkBA,gBAAwB,EAAiB,EAAmB,EAAqB,EAAgC,CAC7G,GAAM,CAAE,QAAO,aAAc,EAAyB,EAAW,EAAS,EAAa,EAAgB,CAAe,EAItH,OAFA,KAAK,yBAAyB,EAAW,CAAW,EAE7C,CACX,CAUA,uBAA+B,EAAiC,CAC5D,KAAK,iBAAiB,EAEtB,IAAK,IAAM,KAAQ,KAAK,WAChB,aAAgB,GAChB,EAAK,QAAQ,EAIrB,KAAK,WAAa,CAAC,EACnB,KAAK,cAAgB,GACrB,KAAK,oBAAoB,EAEzB,KAAK,qBAAqB,CAAO,CACrC,CAOA,qBAA6B,EAA+B,CACxD,KAAK,YAAY,EAEjB,IAAK,IAAM,KAAU,EAAO,CACxB,IAAM,EAAO,IAAI,EACb,MACM,CAAE,EAAO,SAAS,EAAG,KAAK,SAAU,CAAG,EAC5C,GAAgB,CAAE,KAAK,sBAAsB,CAAW,CAAG,CAChE,EAEA,KAAK,aAAa,CAAI,EACtB,KAAK,WAAW,KAAK,CAAI,CAC7B,CAEA,KAAK,aAAa,EAElB,KAAK,SAAS,KAAK,cAAc,CAAC,CACtC,CAOA,gBAAwB,EAAqB,CACzC,GAAI,KAAK,eAAiB,GAAK,KAAK,cAAgB,KAAK,WAAW,OAAQ,CACxE,IAAM,EAAO,KAAK,WAAW,KAAK,eAE9B,aAAgB,GAChB,EAAK,WAAW,EAAK,CAE7B,CAIA,GAFA,KAAK,cAAgB,EAEjB,GAAS,GAAK,EAAQ,KAAK,WAAW,OAAQ,CAC9C,IAAM,EAAO,KAAK,WAAW,GAEzB,aAAgB,GAChB,EAAK,WAAW,EAAI,CAE5B,CACJ,CAQA,gBAAwB,EAAwB,CAC5C,IAAM,EAAO,KAAK,WAAW,GAU7B,OARI,aAAgB,GAIhB,aAAgB,GACT,EAAK,YAAY,CAIhC,CAOA,kBAAiC,CACzB,KAAK,oBACL,KAAK,kBAAkB,MAAM,EAC7B,KAAK,kBAAkB,QAAQ,CAAC,CAAC,YAAY,EAAK,EAClD,KAAK,kBAAoB,KACzB,KAAK,iBAAmB,KAEhC,CASA,YAA2B,CACnB,KAAK,YACL,KAAK,SAAU,EAEf,KAAK,KAAK,CAElB,CASA,iBAAiC,CAC7B,OAAO,KAAK,WAAW,GAAK,IAChC,CAWA,gBAAmC,CAC/B,MAAO,eACX,CAQA,cAAqB,CACjB,KAAK,WAAW,CACpB,CAWA,kBAAkC,CAC9B,OAAO,KAAK,WAChB,CAUA,SAAkB,CACd,OAAO,EAAa,KAAK,QAC7B,CASA,gBAAgB,EAAsB,CAClC,KAAK,UAAU,CAAM,CACzB,CAUA,sBAA8B,EAAsB,CAGhD,GAAI,CAAC,EAAK,WAAW,GAAK,CAAC,EAAK,UAAU,EAAG,CACzC,KAAK,iBAAiB,EAEtB,MACJ,CAEA,GAAI,KAAK,mBAAqB,EAC1B,OAGJ,KAAK,iBAAiB,EAEtB,IAAM,EAAe,IAAI,KACrB,EAAK,iBAAiB,CAAC,CAAE,UACnB,CAAE,KAAK,WAAW,CAAG,CAC/B,EAEA,KAAK,kBAAoB,EACzB,KAAK,iBAAmB,EACxB,EAAK,QAAQ,CAAC,CAAC,YAAY,EAAI,EAE/B,EAAa,mBAAmB,KAAK,WAAW,EAAI,CAAE,EACtD,EAAa,KAAK,EAAK,WAAW,EAAI,EAAI,IAAI,CAClD,CAOA,kBAA0B,EAAsB,CAC5C,GAAI,KAAK,YACL,MAAU,MAAM,QAAQ,EAAO,kEAAkE,CAEzG,CAOA,qBAA6B,EAAsB,CAC/C,GAAI,CAAC,KAAK,YACN,MAAU,MAAM,QAAQ,EAAO,0EAA0E,CAEjH,CACJ,CAEkC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{u as e}from"./Position-B-WfZYAJ.js";import{f as t}from"./Component-BR2f0Itb.js";import{t as n}from"./Button-DEUtBqK4.js";import{t as r}from"./Menu-Wz4MK6sA.js";var i=t(class MenuButton extends n{_menu=null;_boundToggleMenu=()=>{this.toggleMenu()};constructor(e,t,n){let r;typeof e==`string`?r=e:e!==void 0&&(t=e),super(r,t,n),this.on(`action`,this._boundToggleMenu),Object.getPrototypeOf(this)===MenuButton.prototype&&this.applyListeners(t?.listeners)}setMenuItems(e){return this._options.menuItems=e,this}getMenuItems(){return this._options.menuItems??this._defaultOptions.menuItems??null}isScrollToBottomOnShow(){return this._options.scrollToBottomOnShow??this._defaultOptions.scrollToBottomOnShow??!1}applyOptions(e){return super.applyOptions(e),e.menuItems!==void 0&&this.setMenuItems(e.menuItems),e.scrollToBottomOnShow!==void 0&&(this._options.scrollToBottomOnShow=e.scrollToBottomOnShow),this}toggleMenu(){let t=this.getElement();t&&(this._menu??=new r().setScrollToBottomOnShow(this.isScrollToBottomOnShow()),this._menu.toggleFor(t,e.source.getViewportRect(this),this.resolveMenuItems()))}resolveMenuItems(){let e=this.getMenuItems();return typeof e==`function`?e():e??[]}});export{i as t};
|
|
2
|
-
//# sourceMappingURL=MenuButton-JQQaKThJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MenuButton-JQQaKThJ.js","names":[],"sources":["../../src/typescript/lib/component/button/MenuButton.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Button, ButtonOptions } from \"~/component/button/Button.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport { Menu } from \"~/overlay/Menu.js\";\nimport { MenuItemConfig } from \"~/component/container/MenuItem.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link MenuButton}.\n *\n * @category Components\n */\nexport interface MenuButtonOptions extends ButtonOptions {\n /** Items for the dropdown, or a provider re-invoked on every open. */\n menuItems?: MenuItemConfig[] | (() => MenuItemConfig[]);\n /** Open the menu scrolled to the bottom of its item list. Default `false`. */\n scrollToBottomOnShow?: boolean;\n}\n\n/**\n * A push button whose click toggles a rebuild-mode dropdown [`Menu`](/api/overlay/classes/Menu)\n * anchored under its bottom-left corner. The menu opens below the button, and\n * flips above it when the room below is short — see\n * [`Menu.toggleFor`](/api/overlay/classes/Menu#togglefor). A provider resolving\n * to an empty item list opens nothing (the click is a no-op beyond the\n * `\"action\"` event still firing).\n *\n * The dropdown panel is created lazily on first open and reused across opens;\n * `menuItems` accepts either a fixed array or a provider function, and the\n * provider is re-invoked on every open so its output (e.g. relative\n * timestamps, current record counts) is always current.\n *\n * @example\n * ```typescript\n * import { MenuButton } from '@jimka/typescript-ui/component/button';\n *\n * const exportBtn = MenuButton({\n * glyph: 'file-export',\n * menuItems: [\n * { text: 'Export as CSV', action: () => exportCsv() },\n * { text: 'Export as JSON', action: () => exportJson() },\n * ],\n * });\n * toolbar.addComponent(exportBtn);\n * ```\n *\n * @category Components\n */\nclass MenuButton<TOptions extends MenuButtonOptions = MenuButtonOptions> extends Button<TOptions> {\n\n // Lazily created on first open and reused across opens; a rebuild-mode Menu\n // rebuilds its items on every toggle, so a provider's output is always current.\n private _menu: Menu | null = null;\n\n private readonly _boundToggleMenu: () => void = () => { this.toggleMenu(); };\n\n /**\n * Constructs a MenuButton with an optional title and options bag (both\n * optional — an empty MenuButton renders as a chrome-shaped placeholder).\n *\n * @example\n * ```typescript\n * new MenuButton('Export', { menuItems: [ … ] });\n * MenuButton({ glyph: 'file-export', menuItems: [ … ] });\n * ```\n */\n constructor(text?: string, options?: TOptions, subclassDefaults?: Partial<TOptions>);\n constructor(options: TOptions);\n constructor(\n textOrOptions?: string | TOptions,\n options?: TOptions,\n subclassDefaults?: Partial<TOptions>,\n ) {\n // Normalise the overload: a non-string first argument is the options bag.\n // Copied from Button.ts:437-443 in shape. Legal before super() because it\n // touches no `this` (TS >= 4.6); the field initializers still run after\n // super() returns.\n let text: string | undefined;\n\n if (typeof textOrOptions === \"string\") {\n text = textOrOptions;\n } else if (textOrOptions !== undefined) {\n options = textOrOptions;\n }\n\n super(text, options, subclassDefaults);\n\n this.on(\"action\", this._boundToggleMenu);\n\n // Button wires the listener bag only when it is the directly-constructed\n // class; mirror its instance-identity guard so a MenuButton subclass wires\n // its own bag once, from its own constructor.\n if (Object.getPrototypeOf(this) === MenuButton.prototype) {\n this.applyListeners(options?.listeners);\n }\n }\n\n /**\n * Replaces the configured dropdown items — a fixed array, or a provider\n * re-invoked on every open.\n *\n * @param items - The new item configurations or provider.\n *\n * @returns This button, for method chaining.\n */\n setMenuItems(items: MenuItemConfig[] | (() => MenuItemConfig[])): this {\n this._options.menuItems = items;\n\n return this;\n }\n\n /**\n * Returns the configured dropdown items or provider — the caller value,\n * else the class default, else `null` when neither is set.\n *\n * @returns The configured items/provider, or `null`.\n */\n getMenuItems(): MenuItemConfig[] | (() => MenuItemConfig[]) | null {\n return this._options.menuItems ?? this._defaultOptions.menuItems ?? null;\n }\n\n /**\n * Returns whether the menu opens scrolled to the bottom of its item list —\n * the caller value, else the class default, else `false`.\n *\n * @returns Whether the menu opens scrolled to the bottom.\n */\n isScrollToBottomOnShow(): boolean {\n return this._options.scrollToBottomOnShow ?? this._defaultOptions.scrollToBottomOnShow ?? false;\n }\n\n /**\n * Applies a {@link MenuButtonOptions} bag, dispatching `menuItems` after\n * the inherited Button fields cascade.\n *\n * @param options - The options bag carrying the values to apply.\n *\n * @returns This button, for method chaining.\n */\n protected applyOptions(options: TOptions): this {\n super.applyOptions(options);\n\n if (options.menuItems !== undefined) {\n this.setMenuItems(options.menuItems);\n }\n\n // No setter: a construction-time-only option read once when the lazy\n // Menu is created, so a pure bag write is all that is needed.\n if (options.scrollToBottomOnShow !== undefined) {\n this._options.scrollToBottomOnShow = options.scrollToBottomOnShow;\n }\n\n return this;\n }\n\n /**\n * Toggles the menu anchored under the button's bottom-left corner, flipping\n * above the button when the room below is short. No-op when the button is not\n * yet attached (no anchor rect to read), or when the items resolve to an empty\n * list — `Menu.toggleFor` owns that suppression, so no check is needed here.\n */\n private toggleMenu(): void {\n const el = this.getElement();\n\n if (!el) {\n return;\n }\n\n this._menu ??= new Menu().setScrollToBottomOnShow(this.isScrollToBottomOnShow());\n\n // Items are resolved eagerly as an argument, so a provider re-runs on\n // every toggle — including a toggle that only closes the menu, whose\n // result Menu.toggleFor discards. Keeping toggleFor the single source of\n // truth for open-vs-close is worth that spare provider call; the\n // alternative (asking the menu whether it is open before resolving)\n // reintroduces the open-state desync toggleFor exists to avoid.\n this._menu.toggleFor(el, DOM.source.getViewportRect(this), this.resolveMenuItems());\n }\n\n /** Resolves the configured items — invoking the provider form on every open. */\n private resolveMenuItems(): MenuItemConfig[] {\n const items = this.getMenuItems();\n\n if (typeof items === \"function\") {\n return items();\n }\n\n return items ?? [];\n }\n}\n\nconst MenuButtonCallable = callable(MenuButton);\ntype MenuButtonCallable<TOptions extends MenuButtonOptions = MenuButtonOptions> = MenuButton<TOptions>;\nexport {\n MenuButton as _MenuButton,\n MenuButtonCallable as MenuButton,\n};\n"],"mappings":"uKAgMA,IAAM,EAAqB,EAAS,MA/I9B,mBAA2E,CAAiB,CAI9F,MAA6B,KAE7B,qBAAsD,CAAE,KAAK,WAAW,CAAG,EAc3E,YACI,EACA,EACA,EACF,CAKE,IAAI,EAEA,OAAO,GAAkB,SACzB,EAAO,EACA,IAAkB,IAAA,KACzB,EAAU,GAGd,MAAM,EAAM,EAAS,CAAgB,EAErC,KAAK,GAAG,SAAU,KAAK,gBAAgB,EAKnC,OAAO,eAAe,IAAI,IAAM,WAAW,WAC3C,KAAK,eAAe,GAAS,SAAS,CAE9C,CAUA,aAAa,EAA0D,CAGnE,MAFA,MAAK,SAAS,UAAY,EAEnB,IACX,CAQA,cAAmE,CAC/D,OAAO,KAAK,SAAS,WAAa,KAAK,gBAAgB,WAAa,IACxE,CAQA,wBAAkC,CAC9B,OAAO,KAAK,SAAS,sBAAwB,KAAK,gBAAgB,sBAAwB,EAC9F,CAUA,aAAuB,EAAyB,CAa5C,OAZA,MAAM,aAAa,CAAO,EAEtB,EAAQ,YAAc,IAAA,IACtB,KAAK,aAAa,EAAQ,SAAS,EAKnC,EAAQ,uBAAyB,IAAA,KACjC,KAAK,SAAS,qBAAuB,EAAQ,sBAG1C,IACX,CAQA,YAA2B,CACvB,IAAM,EAAK,KAAK,WAAW,EAEtB,IAIL,KAAK,QAAU,IAAI,EAAK,CAAC,CAAC,wBAAwB,KAAK,uBAAuB,CAAC,EAQ/E,KAAK,MAAM,UAAU,EAAI,EAAI,OAAO,gBAAgB,IAAI,EAAG,KAAK,iBAAiB,CAAC,EACtF,CAGA,kBAA6C,CACzC,IAAM,EAAQ,KAAK,aAAa,EAMhC,OAJI,OAAO,GAAU,WACV,EAAM,EAGV,GAAS,CAAC,CACrB,CACJ,CAE8C"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./DOM-DeF_dWe2.js";import{n as t}from"./Position-DJKB0N3l.js";import{_ as n,f as r,g as i,y as a}from"./Component-Bs6TvaGZ.js";import{i as o,n as s,r as c,t as l}from"./Scrollbar-DQdCdj94.js";import{t as u}from"./Container-CzyZeMyZ.js";var d={tag:`div`,insets:new t(4,4,4,4)},f=`PanelOverlayScroller`,p=null;function ensureOverlayScrollerClassRule(){p||=[new n({scope:`class`,name:f,styles:{scrollbarWidth:`none`}}),new n({scope:`selector`,name:`.${f}::-webkit-scrollbar`,styles:{display:`none`}})]}var Panel=class extends u{_shadowOverlayStyle=new i;_lastChildCount=0;_overlayScrollStyle=new i;_onOverlayScrollV=e=>{this.setScrollTop(e)};_onOverlayScrollH=e=>{this.setScrollLeft(e)};constructor(e,n){let r=e?.flush?{insets:new t(0,0,0,0)}:{};super(e,{...d,...n??{},...r})}applyOptions(e){return super.applyOptions(e),this.setScrollbarGutter(0,0),this._shadowEdges={top:0,bottom:0,left:0,right:0},this._lastContentExtent={width:0,height:0},this.setAutoScroll(e.autoScroll??`none`),this._shadowOverlay=null,this._shadowScrollHandler=null,this.setScrollShadows(e.scrollShadows??!0),this._overlayScrollElement=null,this._scrollbarV=null,this._scrollbarH=null,this._overlayScrollHandler=null,this.setScrollbarStyle(e.scrollbarStyle??`overlay`),this}setAutoScroll(e){switch(this._autoScroll=e,e){case`none`:this.setOverflowX(`hidden`).setOverflowY(`hidden`);break;case`auto`:this.setOverflowX(`auto`).setOverflowY(`auto`);break;case`x`:this.setOverflowX(`auto`).setOverflowY(`hidden`);break;case`y`:this.setOverflowX(`hidden`).setOverflowY(`auto`);break;case`both`:this.setOverflowX(`scroll`).setOverflowY(`scroll`);break}e===`none`&&(this._scrollbarGutter.right!==0||this._scrollbarGutter.bottom!==0)&&this.setScrollbarGutter(0,0);let t=this.scrollableAxes();return this.getLayoutManager()?.setOverflowing(t.x,t.y),this.refreshOverlayScrollbars(),this.refreshScrollShadows(),this}setLayoutManager(e){return super.setLayoutManager(e),this.setAutoScroll(this._autoScroll),this}getAutoScroll(){return this._autoScroll}clearAutoScroll(){return this.setAutoScroll(`none`)}setScrollShadows(e){return this._scrollShadows=e,this.refreshScrollShadows(),this}getScrollShadows(){return this._scrollShadows}setScrollbarStyle(e){return this._scrollbarStyle=e,this.refreshOverlayScrollbars(),this.refreshScrollShadows(),this}getScrollbarStyle(){return this._scrollbarStyle}getScrollElement(){return this._overlayScrollElement??this.getElement()}getInnerSize(){let e=super.getInnerSize();return e?{width:e.width-this._scrollbarGutter.right,height:e.height-this._scrollbarGutter.bottom}:null}doLayout(){return super.doLayout(),this.commitElementStyle(),this.resizeScrollShadowOverlay(),this.measureScrollbarGutter(),this.updateScrollShadows(),this.scheduleGutterSettleOnShrink(),this}scheduleGutterSettleOnShrink(){if(this._autoScroll===`none`)return;let e=this.getComponents().length,t=e<this._lastChildCount;this._lastChildCount=e;let n=!1;if(this.showsScrollAffordance()){let e=this.getPreferredSize(),t=e?e.width:0,r=e?e.height:0;n=t<this._lastContentExtent.width||r<this._lastContentExtent.height,this._lastContentExtent={width:t,height:r}}(t||n)&&this.scheduleLayout()}showsScrollAffordance(){return this._scrollbarGutter.right>0||this._scrollbarGutter.bottom>0||this._shadowEdges.top>0||this._shadowEdges.bottom>0||this._shadowEdges.left>0||this._shadowEdges.right>0}init(e){super.init(e);let t=e??this.getElement();return t&&this._scrollbarStyle===`overlay`&&this._autoScroll!==`none`&&(this.installOverlayScrollbars(t),this.layoutOverlayScrollbars(t)),t&&this._scrollShadows&&this._autoScroll!==`none`&&(this.installScrollShadows(t),this.updateScrollShadows(t)),this}destructor(){this.removeScrollShadows(),this.removeOverlayScrollbars(),super.destructor()}scrollableAxes(){let e=this._autoScroll;return{x:e===`x`||e===`auto`||e===`both`,y:e===`y`||e===`auto`||e===`both`}}setScrollbarGutter(e,t){this._scrollbarGutter={right:e,bottom:t}}measureScrollbarGutter(){if(this._autoScroll===`none`)return;if(this._scrollbarStyle===`overlay`){this.layoutOverlayScrollbars();return}let t=this.getElement();if(!t)return;let n=e.source.getScrollBarWidth();if(n===0)return;let r,i;if(this._autoScroll===`both`)r=!0,i=!0;else{let n=this.scrollableAxes(),a=e.source.getScrollMetrics(t);r=n.y&&a.scrollHeight>a.clientHeight,i=n.x&&a.scrollWidth>a.clientWidth}let a=r?n:0,o=i?n:0;a===this._scrollbarGutter.right&&o===this._scrollbarGutter.bottom||(this.setScrollbarGutter(a,o),this.scheduleLayout())}refreshScrollShadows(){if(!this._scrollShadows||this._autoScroll===`none`){this.removeScrollShadows();return}let e=this.getElement();e&&(this.installScrollShadows(e),this.updateScrollShadows(e))}installScrollShadows(e){if(this._shadowOverlay||this.createScrollShadowOverlay(e),!this._shadowScrollHandler){let handler=()=>{this.updateScrollShadows()};this._shadowScrollHandler=handler,a.addSubtreeListener(this,`scroll`,handler)}}createScrollShadowOverlay(t){let n=e.sink.createElement(`div`);this._shadowOverlayStyle.attach(n),this._shadowOverlayStyle.setMany({position:`sticky`,left:`0px`,top:`0px`,pointerEvents:`none`,zIndex:`1`,boxShadow:s()}),e.sink.appendChild(t,n),this.trackHandle(n),this._shadowOverlay=n}removeScrollShadows(){this._shadowScrollHandler&&=(a.removeSubtreeListener(this,`scroll`,this._shadowScrollHandler),null),this._shadowOverlay&&(e.sink.removeElement(this._shadowOverlay),this.untrackHandle(this._shadowOverlay),e.sink.release(this._shadowOverlay),this._shadowOverlay=null,this._shadowOverlayStyle=new i),this._shadowEdges={top:0,bottom:0,left:0,right:0}}resizeScrollShadowOverlay(t){let n=t??this.getElement();if(!n||!this._shadowOverlay)return;let{clientWidth:r,clientHeight:i}=e.source.getScrollMetrics(n),a=this._scrollbarStyle===`overlay`?this._scrollbarGutter.right:0,o=this._scrollbarStyle===`overlay`?this._scrollbarGutter.bottom:0;this._shadowOverlayStyle.setMany({width:r-a+`px`,height:i-o+`px`})}updateScrollShadows(t){let n=t??this.getElement();if(!n||!this._shadowOverlay)return;let{scrollTop:r,scrollLeft:i,scrollWidth:a,scrollHeight:s,clientWidth:c,clientHeight:l}=e.source.getScrollMetrics(this.getScrollElement()??n);this.resizeScrollShadowOverlay(n);let u=s-l,d=a-c,f=o,p=this.scrollableAxes();this.setShadowEdge(`top`,`--ts-ss-top`,p.y?f(r):0),this.setShadowEdge(`bottom`,`--ts-ss-bottom`,p.y?f(u-r):0),this.setShadowEdge(`left`,`--ts-ss-left`,p.x?f(i):0),this.setShadowEdge(`right`,`--ts-ss-right`,p.x?f(d-i):0)}setShadowEdge(e,t,n){let r=Math.round(n*100);this._shadowEdges[e]!==r&&(this._shadowEdges[e]=r,this._shadowOverlayStyle.set(t,c(r)))}refreshOverlayScrollbars(){if(this._scrollbarStyle!==`overlay`||this._autoScroll===`none`){this.removeOverlayScrollbars();return}let e=this.getElement();e&&(this.installOverlayScrollbars(e),this.layoutOverlayScrollbars(e))}installOverlayScrollbars(t){if(!this._overlayScrollElement){ensureOverlayScrollerClassRule();let n=e.sink.createElement(`div`);this._overlayScrollStyle.attach(n),this._overlayScrollStyle.setMany({position:`absolute`,left:`0px`,top:`0px`,width:`100%`,height:`100%`}),e.sink.apply(n,{addClass:[f]}),e.sink.appendChild(t,n),this.reparentContent(t,n),this.trackHandle(n),this._overlayScrollElement=n}let n=this.scrollableAxes();if(this._overlayScrollStyle.setMany({overflowX:n.x?`auto`:`hidden`,overflowY:n.y?`auto`:`hidden`}),this._scrollbarV||(this._scrollbarV=new l(`vertical`),this._scrollbarV.setZIndex(2),e.sink.appendChild(t,this._scrollbarV.getElement(!0)),this._scrollbarV.on(`scroll`,this._onOverlayScrollV)),this._scrollbarH||(this._scrollbarH=new l(`horizontal`),this._scrollbarH.setZIndex(2),e.sink.appendChild(t,this._scrollbarH.getElement(!0)),this._scrollbarH.on(`scroll`,this._onOverlayScrollH)),!this._overlayScrollHandler){let handler=()=>{this.syncOverlayScrollbars()};this._overlayScrollHandler=handler,a.addSubtreeListener(this,`scroll`,handler)}this.setNativeScrollbarHidden(!0)}removeOverlayScrollbars(){if(this._overlayScrollHandler&&=(a.removeSubtreeListener(this,`scroll`,this._overlayScrollHandler),null),this._scrollbarV&&=(this._scrollbarV.off(`scroll`,this._onOverlayScrollV),this._scrollbarV.removeElement(),null),this._scrollbarH&&=(this._scrollbarH.off(`scroll`,this._onOverlayScrollH),this._scrollbarH.removeElement(),null),this._overlayScrollElement){let t=this.getElement();t&&this.reparentContent(this._overlayScrollElement,t),e.sink.removeElement(this._overlayScrollElement),this.untrackHandle(this._overlayScrollElement),e.sink.release(this._overlayScrollElement),this._overlayScrollElement=null,this._overlayScrollStyle=new i}this.setNativeScrollbarHidden(!1),this.setScrollbarGutter(0,0)}setNativeScrollbarHidden(e){this.setElementCSSRule(`scrollbarWidth`,e?`none`:null),this.createStyleRule(`::-webkit-scrollbar`).set(`display`,e?`none`:null)}layoutOverlayScrollbars(t){let n=t??this.getElement(),r=this._overlayScrollElement;if(!n||!r||!this._scrollbarV||!this._scrollbarH)return;let i=this._scrollbarV.getTrackWidth(),a=e.source.getScrollMetrics(n),o=a.clientWidth,s=a.clientHeight,c=this._scrollbarGutter.right,l=this._scrollbarGutter.bottom;this._overlayScrollStyle.setMany({width:o-c+`px`,height:s-l+`px`});let u=e.source.getScrollMetrics(r),d=this.scrollableAxes(),f=d.y&&u.scrollHeight>u.clientHeight,p=d.x&&u.scrollWidth>u.clientWidth,m=o-(f?i:0),h=s-(p?i:0);(m!==o-c||h!==s-l)&&this._overlayScrollStyle.setMany({width:m+`px`,height:h+`px`}),this._scrollbarV.setX(m),this._scrollbarV.setY(0),this._scrollbarV.setHeight(h),this._scrollbarV.setMetrics(h,u.scrollHeight,u.scrollTop),this._scrollbarH.setX(0),this._scrollbarH.setY(h),this._scrollbarH.setWidth(m),this._scrollbarH.setMetrics(m,u.scrollWidth,u.scrollLeft);let g=f?i:0,_=p?i:0;(g!==c||_!==l)&&(this.setScrollbarGutter(g,_),this.scheduleLayout())}syncOverlayScrollbars(){let t=this._overlayScrollElement;if(!t||!this._scrollbarV||!this._scrollbarH)return;let n=e.source.getScrollMetrics(t);this._scrollbarV.setMetrics(n.clientHeight,n.scrollHeight,n.scrollTop),this._scrollbarH.setMetrics(n.clientWidth,n.scrollWidth,n.scrollLeft)}},m=r(Panel);export{m as t};
|
|
2
|
-
//# sourceMappingURL=Panel-DApa7vA6.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Panel-DApa7vA6.js","names":[],"sources":["../../src/typescript/lib/core/Panel.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Container, ContainerOptions } from \"~/core/Container.js\";\nimport { Insets } from \"~/primitive/Insets\";\nimport { LayoutManager } from \"~/layout/LayoutManager.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { InlineStyle, StyleRule } from \"~/core/StyleTarget.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { scrollShadowBoxShadow, scrollShadowEdgeValue, scrollShadowRamp } from \"~/core/ScrollShadow.js\";\nimport { Scrollbar } from \"~/component/container/Scrollbar.js\";\n\n/**\n * Per-edge shadow strength for a panel's scroll shadows, cached as a whole\n * percentage (0–100). The per-scroll update only rewrites a custom property\n * when an edge's quantised strength actually changes, so a scroll that doesn't\n * move the visible strength costs nothing here.\n */\ntype ScrollShadowEdges = { top: number; bottom: number; left: number; right: number };\n\n/**\n * Selects the per-axis scroll behaviour for a {@link Panel}.\n *\n * - `\"none\"` — never scroll; oversized children clip (the default).\n * - `\"auto\"` — scrollbars appear on either axis only when content overflows.\n * - `\"x\"` — horizontal scrollbar on overflow; vertical overflow clips.\n * - `\"y\"` — vertical scrollbar on overflow; horizontal overflow clips.\n * - `\"both\"` — both scrollbars are always shown (`overflow: scroll`).\n *\n * @remarks For every value except `\"none\"` the panel measures the native\n * scrollbar gutter after each `doLayout` pass and subtracts it from\n * `getInnerSize` when a scrollbar is actually visible, so layout managers\n * naturally lay out children within the post-gutter content area instead of\n * letting them spill behind the scrollbar (which the browser would otherwise\n * resolve by adding the opposite-axis scrollbar — the classic V→H cascade).\n * A scrollbar transition triggers a one-frame re-layout via `scheduleLayout`.\n *\n * @category Core\n */\nexport type AutoScrollMode = \"none\" | \"auto\" | \"x\" | \"y\" | \"both\";\n\n/**\n * Selects how a scrolling {@link Panel} renders its scrollbar.\n *\n * - `\"overlay\"` — the default. Scrolling stays native (`overflow: auto`), the\n * native scrollbar is hidden visually, and two custom `Scrollbar` widgets\n * are overlaid at the trailing edges, synced to the element's native\n * `scrollTop` / `scrollLeft`. Every native scroll behaviour (keyboard, find,\n * focus-scroll, caret scroll, assistive tech) is preserved.\n * - `\"native\"` — the OS scrollbar renders as usual; the panel reserves the\n * measured native gutter width instead of the fixed overlay track width.\n *\n * Ignored while `autoScroll === \"none\"` (a non-scrolling panel shows neither).\n *\n * @category Core\n */\nexport type ScrollbarStyle = \"native\" | \"overlay\";\n\n/**\n * Construction-time options for {@link Panel}.\n *\n * @remarks `insets` is inherited from {@link ComponentOptions} but defaults to\n * `(4, 4, 4, 4)` for `Panel` (Component itself defaults to zero insets). Pass\n * an explicit `insets` to override.\n *\n * @category Core\n */\nexport interface PanelOptions extends ContainerOptions {\n tag?: string;\n\n /**\n * Construction-time shortcut for [`Panel.setAutoScroll`](/api/core/classes/Panel#setautoscroll). Defaults to\n * `\"none\"` (oversized children clip, matching the inherited `Component`\n * `overflow: hidden` behaviour).\n */\n autoScroll?: AutoScrollMode;\n\n /**\n * When `true` (the default), an `autoScroll` panel paints a fading edge\n * shadow on each side where hidden content can still be scrolled into\n * view — a cue that the content continues past the viewport border rather\n * than ending there. Set `false` to suppress the shadows. Ignored while\n * `autoScroll === \"none\"` (a non-scrolling panel never shows them).\n */\n scrollShadows?: boolean;\n\n /**\n * Selects the scrollbar rendering for an `autoScroll` panel. Defaults to\n * `\"overlay\"` — a scrolling panel hides its native bar and paints synced\n * overlay `Scrollbar` widgets instead. Pass `\"native\"` to opt out and keep\n * the OS scrollbar. Ignored while `autoScroll === \"none\"`.\n */\n scrollbarStyle?: ScrollbarStyle;\n\n /**\n * When `true`, the panel's default content insets are zero instead of the\n * usual `(4, 4, 4, 4)` — the rail-style default for a fixed-width strip\n * (activity rail, narrow Border/VBox region) that must sit flush against\n * its host and keep a constant width. Construction-time only; a\n * caller-supplied `insets` still wins. Defaults to `false`.\n */\n flush?: boolean;\n}\n\n/**\n * User-overridable defaults forwarded to `super` via the options bag. The\n * cascade in `Component`'s constructor dispatches `setInsets` once with the\n * final value, so a caller-supplied `insets` wins over the panel default.\n */\nconst _defaultPanelOptions: Partial<PanelOptions> = {\n tag: \"div\",\n insets: new Insets(4, 4, 4, 4),\n};\n\n/**\n * Class applied to the raw inner scroll element of an overlay-mode panel. The\n * inner element has no `#id` (it is not a `Component`), so its native bar is\n * hidden through a shared class rule rather than the per-`#id`\n * `setElementCSSRule` path the panel element uses — the framework's module-level\n * shared class-rule pattern (as the focus-ring and `Component` class rules use).\n */\nconst OVERLAY_SCROLLER_CLASS = \"PanelOverlayScroller\";\n\n// The shared inner-scroller class rules, retained once registered (mirrors the\n// CollapseButton / header-glyph module-singleton pattern). The array doubles as\n// the idempotency guard.\nlet _scrollerClassRules: StyleRule[] | null = null;\n\n/**\n * Registers, once, the shared class rules that hide the native scrollbar on an\n * overlay panel's raw inner scroll element: `scrollbar-width: none` (Firefox /\n * Chromium >= 121) plus a `::-webkit-scrollbar { display: none }` selector rule\n * (WebKit / older Blink) — the two-write pair the panel element's\n * `setNativeScrollbarHidden` uses, expressed as a shared class instead of a\n * per-`#id` rule.\n */\nfunction ensureOverlayScrollerClassRule(): void {\n if (_scrollerClassRules) {\n return;\n }\n\n _scrollerClassRules = [\n new StyleRule({\n scope: \"class\",\n name: OVERLAY_SCROLLER_CLASS,\n styles: { scrollbarWidth: \"none\" },\n }),\n new StyleRule({\n scope: \"selector\",\n name: `.${OVERLAY_SCROLLER_CLASS}::-webkit-scrollbar`,\n styles: { display: \"none\" },\n }),\n ];\n}\n\n/**\n * A [`Container`](/api/core/classes/Container) subclass that applies a default 4-pixel inset on all sides.\n *\n * Use `Panel` as the base class for grouped UI containers where children\n * should not sit flush against the outer edge. A plain [`Container`](/api/core/classes/Container) fits\n * its parent's allocation with zero insets to keep structural regions\n * pixel-predictable; `Panel` opts into the visual breathing room that grouped\n * content layouts typically want.\n *\n * `Panel` also exposes `setAutoScroll` to opt the container into native\n * browser scrolling when its children overflow the allocated rect.\n *\n * Pass `flush: true` to opt a panel into zero default insets instead of the\n * 4px default, for rail-style fixed-width strips that must sit flush against\n * their host.\n *\n * @category Core\n */\nclass Panel<TOptions extends PanelOptions = PanelOptions> extends Container<TOptions> {\n\n // `declare` rather than initialiser to dodge the class-field super-cascade\n // trap: a `= \"none\"` initialiser runs *after* super() returns, which\n // overwrites whatever `setAutoScroll(options.autoScroll)` had already\n // written during the super-time cascade. `applyOptions` below always\n // dispatches `setAutoScroll`, so the field gets seeded there.\n declare private _autoScroll: AutoScrollMode;\n declare private _scrollbarGutter: { right: number; bottom: number };\n\n // Scroll-shadow state. `_scrollShadows`, `_shadowOverlay` and `_shadowScrollHandler`\n // are written by `setScrollShadows` / `setAutoScroll` during the super-time\n // options cascade, so they are `declare`d (no initialiser) and seeded in\n // `applyOptions` to dodge the class-field super-cascade trap — an\n // initialiser would run after super() and clobber the seeded value.\n declare private _scrollShadows: boolean;\n declare private _shadowOverlay: Handle | null;\n declare private _shadowScrollHandler: (() => void) | null; // cached bound scroll handler — wired once\n\n // Runtime-only: never touched during the super cascade (the overlay only\n // exists post-render), so a plain initialiser is safe here.\n private _shadowOverlayStyle: InlineStyle = new InlineStyle();\n // Read during the super-time options cascade (setAutoScroll → doLayout →\n // scheduleGutterSettleOnShrink → showsScrollAffordance inspects the edges),\n // so `declare`d and seeded in `applyOptions` to dodge the class-field\n // super-cascade trap, exactly like `_scrollbarGutter`.\n declare private _shadowEdges: ScrollShadowEdges;\n // Child count observed on the previous layout pass, so a shrink (removed\n // children) can force one follow-up gutter/shadow re-measure. See\n // `scheduleGutterSettleOnShrink`.\n private _lastChildCount: number = 0;\n\n // Content preferred extent observed on the previous layout pass while a\n // scroll affordance was showing, so a shrink that happens inside a nested\n // descendant (whose removal leaves this panel's own child count unchanged)\n // still forces the follow-up re-measure. See `scheduleGutterSettleOnShrink`.\n // `declare`d + seeded in `applyOptions` for the same super-cascade reason.\n declare private _lastContentExtent: { width: number; height: number };\n\n // Overlay-scrollbar state. `_scrollbarStyle` is written by\n // `setScrollbarStyle` during the super-time options cascade, and\n // `_overlayScrollElement` / `_scrollbarV` / `_scrollbarH` / `_overlayScrollHandler`\n // are read (for the teardown guard) by the setter's install/refresh path\n // it triggers — so all five are `declare`d and seeded in `applyOptions`\n // for the same class-field super-cascade reason as the scroll-shadow\n // fields above.\n declare private _scrollbarStyle: ScrollbarStyle;\n declare private _overlayScrollElement: Handle | null; // raw inner scroll div (bars are its siblings)\n declare private _scrollbarV: Scrollbar | null;\n declare private _scrollbarH: Scrollbar | null;\n declare private _overlayScrollHandler: (() => void) | null; // native \"scroll\" -> sync\n\n // Runtime-only: never touched during the super cascade (the inner scroll\n // element only exists post-render), so a plain initialiser is safe here —\n // mirrors `_shadowOverlayStyle`.\n private _overlayScrollStyle: InlineStyle = new InlineStyle();\n\n // Bound scroll-forwarders wired to each overlay Scrollbar's \"scroll\"\n // event. Named class fields (per ARCHITECTURE.md *Listeners must\n // reference a named function*) so they are stable, removable references.\n private _onOverlayScrollV = (position: number): void => { this.setScrollTop(position); };\n private _onOverlayScrollH = (position: number): void => { this.setScrollLeft(position); };\n\n /**\n * Creates a panel with 4-pixel insets on all sides by default.\n *\n * @param options - Optional. Construction-time options applied to the panel.\n * `options.tag` overrides the default `\"div\"` tag for subclasses that need\n * a different element (e.g. `\"header\"`, `\"section\"`). `options.insets`\n * overrides the default `(4, 4, 4, 4)` perimeter. `options.flush` zeroes\n * that default instead (a caller-supplied `insets` still wins).\n */\n constructor(options?: TOptions, subclassDefaults?: Partial<TOptions>) {\n // `flush` seeds a zero-inset default; a caller-supplied `insets` still\n // wins because Component.applyOptions dispatches setInsets only when\n // options.insets is defined, overriding whatever default we pick here.\n const flushDefault: Partial<TOptions> =\n options?.flush ? ({ insets: new Insets(0, 0, 0, 0) } as Partial<TOptions>) : {};\n\n super(\n options,\n { ..._defaultPanelOptions, ...(subclassDefaults ?? {}), ...flushDefault } as Partial<TOptions>,\n );\n }\n\n /**\n * Dispatches `Panel`-specific options after delegating the inherited\n * {@link Component} options bag to `super`.\n *\n * @param options - The options bag whose fields populate this panel.\n *\n * @returns This panel, for method chaining.\n */\n protected applyOptions(options: TOptions): this {\n super.applyOptions(options);\n\n // Seed the scrollbar gutter cache before `setAutoScroll` — the latter\n // reads `_scrollbarGutter` to decide whether to clear it on a\n // `\"none\"` transition, and the `declare`d field would otherwise be\n // undefined at first dispatch.\n this.setScrollbarGutter(0, 0);\n\n // Seed the shadow-edge and content-extent caches for the same reason:\n // `setAutoScroll` below triggers a `doLayout` whose\n // `scheduleGutterSettleOnShrink` reads both, and their `declare`d fields\n // would otherwise be undefined during this super-time cascade.\n this._shadowEdges = { top: 0, bottom: 0, left: 0, right: 0 };\n this._lastContentExtent = { width: 0, height: 0 };\n\n // Always dispatch `setAutoScroll` — the `?? \"none\"` covers the\n // no-option default. Routing through the setter (even for the\n // default) keeps the `declare`d backing field initialised and\n // dodges the class-field super-cascade trap that would bite a\n // `= \"none\"` initialiser.\n this.setAutoScroll(options.autoScroll ?? \"none\");\n\n // Seed the `declare`d overlay/handler fields before `setScrollShadows`\n // dispatches — the setter's teardown branch reads them, and the\n // `declare` leaves them `undefined` until first written.\n this._shadowOverlay = null;\n this._shadowScrollHandler = null;\n\n // Always dispatch (default on) so the backing field is seeded through\n // the setter, mirroring the `setAutoScroll` cascade above.\n this.setScrollShadows(options.scrollShadows ?? true);\n\n // Seed the `declare`d overlay fields before `setScrollbarStyle`\n // dispatches — its refresh path (via `refreshOverlayScrollbars` ->\n // `removeOverlayScrollbars`) reads them, and the `declare` leaves\n // them `undefined` until first written.\n this._overlayScrollElement = null;\n this._scrollbarV = null;\n this._scrollbarH = null;\n this._overlayScrollHandler = null;\n\n // Always dispatch so the backing field is seeded through the setter\n // (default \"overlay\"), mirroring the `setAutoScroll` / `setScrollShadows`\n // cascades above. Must run after `setAutoScroll` — the install path\n // this triggers reads `_autoScroll`.\n this.setScrollbarStyle(options.scrollbarStyle ?? \"overlay\");\n\n return this;\n }\n\n /**\n * Selects the panel's native scroll behaviour. Translates `mode` to\n * per-axis `overflow` writes via [`Component.setOverflowX`](/api/core/classes/Component#setoverflowx) /\n * [`Component.setOverflowY`](/api/core/classes/Component#setoverflowy).\n *\n * @param mode - The {@link AutoScrollMode} to apply.\n *\n * @returns This panel, for method chaining.\n *\n * @remarks Children render at their preferred size when `mode !== \"none\"`\n * — the panel no longer clips them to its allocated rect.\n *\n * Whenever a scrollbar becomes visible, `doLayout` measures the gutter\n * and shrinks the panel's reported inner size by that amount so the next\n * layout pass keeps children inside the visible content area (preventing\n * the classic V→H cascade where a right-anchored child gets exposed\n * behind a freshly-shown V scrollbar and triggers an H one).\n *\n * Do not combine with a [`Scrollbar`](/api/component/container/classes/Scrollbar) overlay or a\n * component (e.g. [`Table`](/api/component/table/classes/Table)) that already manages its own scroll\n * state — stacking native overflow on top of the custom scrollbar would\n * produce two scrollbars.\n */\n setAutoScroll(mode: AutoScrollMode): this {\n this._autoScroll = mode;\n\n switch (mode) {\n case \"none\":\n this.setOverflowX(\"hidden\").setOverflowY(\"hidden\");\n break;\n case \"auto\":\n this.setOverflowX(\"auto\").setOverflowY(\"auto\");\n break;\n case \"x\":\n this.setOverflowX(\"auto\").setOverflowY(\"hidden\");\n break;\n case \"y\":\n this.setOverflowX(\"hidden\").setOverflowY(\"auto\");\n break;\n case \"both\":\n this.setOverflowX(\"scroll\").setOverflowY(\"scroll\");\n break;\n }\n\n // Mode switched — drop any cached gutter from the previous mode so\n // the next `doLayout` re-measures against the new overflow setting.\n // (\"none\" never has a gutter; the other modes recompute below.)\n if (mode === \"none\" && (this._scrollbarGutter.right !== 0 || this._scrollbarGutter.bottom !== 0)) {\n this.setScrollbarGutter(0, 0);\n }\n\n // Forward the per-axis \"let children overflow the host\" decision to\n // the layout manager. Each manager honours these flags from its own\n // `doLayout` so trailing children land past `innerSize` when their\n // combined minSize exceeds the host's allocated rect, producing the\n // scrollbar the CSS `overflow: auto` above is waiting for.\n const axes = this.scrollableAxes();\n\n this.getLayoutManager()?.setOverflowing(axes.x, axes.y);\n\n // Re-evaluate the overlay scrollbar for the new mode FIRST: a transition\n // into `\"none\"` tears it (and the inner scroll element) down, a\n // transition into a scrolling mode installs it (when\n // `scrollbarStyle === \"overlay\"`). Must precede `refreshScrollShadows`\n // so `getScrollElement()` already resolves to the inner element when the\n // shadow refresh reads its scroll offsets. No-op before the element\n // exists (creation is deferred to `init`).\n this.refreshOverlayScrollbars();\n\n // Then re-evaluate the shadows for the new mode against the (now\n // correct) scroll element.\n this.refreshScrollShadows();\n\n return this;\n }\n\n /**\n * Re-applies the cached `autoScroll` mode to the new layout manager so\n * swapping managers preserves scroll behaviour. The base `setLayoutManager`\n * does the attach work; this override only forwards the overflow flags.\n *\n * @param layoutManager - The new LayoutManager to use for this panel.\n *\n * @returns This panel, for method chaining.\n */\n setLayoutManager(layoutManager: LayoutManager): this {\n super.setLayoutManager(layoutManager);\n this.setAutoScroll(this._autoScroll);\n\n return this;\n }\n\n /**\n * Returns the panel's current scroll mode.\n *\n * @returns The cached {@link AutoScrollMode}; `\"none\"` if never set.\n */\n getAutoScroll(): AutoScrollMode {\n return this._autoScroll;\n }\n\n /**\n * Resets the panel's scroll mode to `\"none\"`, restoring the inherited\n * `overflow: hidden` clipping behaviour.\n *\n * @returns This panel, for method chaining.\n */\n clearAutoScroll(): this {\n return this.setAutoScroll(\"none\");\n }\n\n /**\n * Enables or disables the position-aware edge shadows on a scrolling\n * panel. When enabled (the default), each side that can still be scrolled\n * toward fades its content into the viewport border; the shadows are\n * suppressed entirely while `autoScroll === \"none\"` or when content does\n * not overflow.\n *\n * @param enabled - `true` to paint the edge shadows, `false` to suppress them.\n *\n * @returns This panel, for method chaining.\n */\n setScrollShadows(enabled: boolean): this {\n this._scrollShadows = enabled;\n\n this.refreshScrollShadows();\n\n return this;\n }\n\n /**\n * Returns whether the panel's scroll edge shadows are enabled.\n *\n * @returns The cached `scrollShadows` flag; `true` unless explicitly disabled.\n */\n getScrollShadows(): boolean {\n return this._scrollShadows;\n }\n\n /**\n * Selects the scrollbar rendering for this panel — the overlay default\n * (native scroll, hidden native bar, two synced `Scrollbar` widgets) or\n * `\"native\"` to keep the OS scrollbar. Installs or tears down the overlay\n * immediately when the element already exists; a no-op before render\n * beyond caching the value (the first install happens in `init`).\n *\n * @param style - The {@link ScrollbarStyle} to apply.\n *\n * @returns This panel, for method chaining.\n */\n setScrollbarStyle(style: ScrollbarStyle): this {\n this._scrollbarStyle = style;\n\n this.refreshOverlayScrollbars();\n\n // Re-home the shadow metric source: an overlay<->native toggle changes\n // which element `getScrollElement()` resolves to (inner element vs panel\n // element), so the shadows must re-read from the new scroller.\n this.refreshScrollShadows();\n\n return this;\n }\n\n /**\n * Returns the panel's current scrollbar style.\n *\n * @returns The cached {@link ScrollbarStyle}; `\"overlay\"` unless\n * explicitly set to `\"native\"`.\n */\n getScrollbarStyle(): ScrollbarStyle {\n return this._scrollbarStyle;\n }\n\n /**\n * Routes every scroll read/write, the child host, and the content frame to\n * the inner scroll element while overlay mode is installed, and to the panel\n * element otherwise (native mode, `autoScroll: \"none\"`, pre-render). This is\n * the single seam that lets the overlay restructure move the actual scroller\n * inward without each scroll-plumbing call site knowing about it.\n *\n * @returns The inner scroll element in overlay mode, else the panel element.\n */\n protected getScrollElement(): Handle | undefined {\n return this._overlayScrollElement ?? this.getElement();\n }\n\n /**\n * Returns the panel's usable inner size with the currently-reserved\n * scrollbar gutter subtracted from each axis. Layout managers read this\n * to lay out children inside the post-gutter content area when a native\n * scrollbar is visible, instead of letting them fill the full rect and\n * spill behind (or be clipped by) the scrollbar.\n *\n * @returns The inner size minus the active scrollbar gutter, or null\n * when the element is not yet in the DOM (matches the base\n * `Component.getInnerSize` contract).\n */\n getInnerSize(): { width: number, height: number } | null {\n const size = super.getInnerSize();\n if (!size) {\n return null;\n }\n\n return {\n width: size.width - this._scrollbarGutter.right,\n height: size.height - this._scrollbarGutter.bottom,\n };\n }\n\n /**\n * Lays out children, then measures the post-layout scrollbar visibility\n * and, when it has changed since the last pass, caches the new gutter\n * and schedules a follow-up layout so children land inside the new\n * post-gutter content area. The follow-up is the \"one-frame reflow\"\n * documented on {@link AutoScrollMode}.\n *\n * @returns This panel, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n // Flush queued inline-style writes (own size in particular) before\n // reading scrollbar geometry: `LayoutManager.commitBounds` runs us\n // with `autoCommitStyle === false`, so the new width/height\n // `setSize` queued during the parent's layout pass haven't reached\n // the DOM yet — `scrollHeight` / `clientHeight` would otherwise\n // report the previous frame's dimensions and `measureScrollbarGutter`\n // wouldn't see the scrollbar transition.\n this.commitElementStyle();\n\n // Re-size the scroll-shadow overlay against the just-committed geometry\n // before measuring: it is the only in-flow child, so a stale height left\n // over from the previous pass floors `scrollHeight` and fakes an overflow\n // on every pass that shrinks the panel. See `resizeScrollShadowOverlay`.\n this.resizeScrollShadowOverlay();\n this.measureScrollbarGutter();\n\n // Re-pin the overlay and recompute edge state against the freshly\n // committed geometry (content-size or scrollbar-gutter changes can\n // flip which edges overflow). The preceding `commitElementStyle`\n // guarantees the reads see this frame's dimensions.\n this.updateScrollShadows();\n\n this.scheduleGutterSettleOnShrink();\n\n return this;\n }\n\n /**\n * Forces one follow-up layout pass after this panel's content shrinks, so a\n * shrink that brings overflowing content back within the viewport re-clears\n * the reserved scrollbar gutter and scroll shadow.\n *\n * `measureScrollbarGutter` only reschedules a pass when the gutter *value*\n * it reads changes. When content is removed, the overflow→fit transition\n * often has not settled on the pass that runs immediately after the\n * removal — the DOM `scrollHeight` still reads its old (overflowing) value,\n * so both the gutter and the shadow measure stale, see no change, and\n * schedule nothing; the stale gutter and shadow then linger until some later\n * unrelated layout (or a scroll event) re-measures. So this schedules one\n * more pass off a signal that *is* accurate at layout time — the content's\n * preferred extent, which drops synchronously when content is removed — and\n * the next frame re-measures against the settled content and clears anything\n * no longer needed.\n *\n * Two shrink signals are used. A direct-child-count drop is the cheap common\n * case. But content can also shrink inside a nested descendant (e.g. rows\n * removed from a grid several levels down), leaving this panel's own child\n * count unchanged; a drop in the panel's preferred extent catches that. The\n * preferred-extent read is gated behind an actually-showing scroll affordance\n * (a reserved gutter or a painted shadow edge) so it costs nothing on the\n * overwhelming majority of layouts, where there is nothing to settle.\n *\n * Bounded and non-looping: it fires only on the pass *after* a shrink (the\n * follow-up pass sees an unchanged count and extent), and never for a\n * `\"none\"` panel, which reserves no gutter and paints no shadow.\n */\n private scheduleGutterSettleOnShrink(): void {\n if (this._autoScroll === \"none\") {\n return;\n }\n\n const count = this.getComponents().length;\n const childShrank = count < this._lastChildCount;\n\n this._lastChildCount = count;\n\n // A shrink inside a nested descendant leaves `count` unchanged, so also\n // watch the preferred extent — but only while a scroll affordance is on\n // screen, since that is the only state a shrink could leave stale.\n let contentShrank = false;\n\n if (this.showsScrollAffordance()) {\n const preferred = this.getPreferredSize();\n const width = preferred ? preferred.width : 0;\n const height = preferred ? preferred.height : 0;\n\n contentShrank = width < this._lastContentExtent.width\n || height < this._lastContentExtent.height;\n\n this._lastContentExtent = { width, height };\n }\n\n if (childShrank || contentShrank) {\n this.scheduleLayout();\n }\n }\n\n /**\n * Whether this panel is currently painting a scroll affordance — a reserved\n * scrollbar gutter or any lit shadow edge. Used by\n * {@link Panel.scheduleGutterSettleOnShrink} to decide whether a shrink could\n * have left a stale gutter/shadow worth re-measuring.\n *\n * @returns `true` when a gutter is reserved or any shadow edge is lit.\n */\n private showsScrollAffordance(): boolean {\n return this._scrollbarGutter.right > 0\n || this._scrollbarGutter.bottom > 0\n || this._shadowEdges.top > 0\n || this._shadowEdges.bottom > 0\n || this._shadowEdges.left > 0\n || this._shadowEdges.right > 0;\n }\n\n /**\n * Initialises the panel element, then installs the scroll-shadow overlay\n * if the panel is a scroll-shadow candidate. Overlay creation is deferred\n * to here (rather than `applyOptions`) because the element only exists\n * once rendered.\n *\n * @param element - Optional. The element to initialise; falls back to the rendered element.\n *\n * @returns This panel, for method chaining.\n */\n protected init(element?: Handle): this {\n super.init(element);\n\n // `getElement()` is still undefined inside `init` (the base assigns\n // `_element` only after `render` returns), so hand the resolved\n // element straight to the installer instead of re-reading it.\n const resolved = element ?? this.getElement();\n\n // Install the overlay scrollbars (which create the inner scroll element)\n // BEFORE the scroll shadows, so `getScrollElement()` already resolves to\n // the inner element when `updateScrollShadows` first reads its offsets.\n if (resolved && this._scrollbarStyle === \"overlay\" && this._autoScroll !== \"none\") {\n this.installOverlayScrollbars(resolved);\n this.layoutOverlayScrollbars(resolved);\n }\n\n if (resolved && this._scrollShadows && this._autoScroll !== \"none\") {\n this.installScrollShadows(resolved);\n this.updateScrollShadows(resolved);\n }\n\n return this;\n }\n\n /**\n * Removes the cached scroll listener before the base destructor detaches\n * the element. The overlay is a child of that element, so it is removed\n * with it; only the window-level listener registration needs explicit\n * cleanup.\n */\n protected destructor(): void {\n this.removeScrollShadows();\n this.removeOverlayScrollbars();\n\n super.destructor();\n }\n\n /**\n * Which axes the current `autoScroll` mode lets the user scroll along. The\n * single source of truth behind the layout manager's overflow flags, the\n * gutter measurement, and the shadow edges — all three must agree on what\n * \"scrollable\" means or the panel paints an affordance for an axis that\n * cannot move.\n *\n * @returns A flag per axis; `true` when that axis scrolls under the current mode.\n */\n private scrollableAxes(): { x: boolean; y: boolean } {\n const mode = this._autoScroll;\n\n return {\n x: mode === \"x\" || mode === \"auto\" || mode === \"both\",\n y: mode === \"y\" || mode === \"auto\" || mode === \"both\",\n };\n }\n\n /**\n * Caches the new gutter for each axis. Internal — driven by\n * `measureScrollbarGutter` after a layout pass; consumers can't\n * configure this (it's derived from runtime DOM measurement, not a\n * declarative input), so it stays off the `PanelOptions` bag.\n *\n * @param right - Reserved gutter on the right edge in pixels.\n * @param bottom - Reserved gutter on the bottom edge in pixels.\n */\n private setScrollbarGutter(right: number, bottom: number): void {\n this._scrollbarGutter = { right, bottom };\n }\n\n /**\n * Reads the post-layout scrollbar visibility from the live DOM and\n * updates the cached gutter to match. When the gutter changed,\n * schedules a follow-up layout pass so children re-flow inside the new\n * inner area. No-op for `mode === \"none\"` and on browsers whose\n * scrollbars don't reserve space (e.g. macOS overlay scrollbars, where\n * the native width measures as 0 — the cascade can't happen there).\n */\n private measureScrollbarGutter(): void {\n if (this._autoScroll === \"none\") {\n return;\n }\n\n if (this._scrollbarStyle === \"overlay\") {\n this.layoutOverlayScrollbars();\n\n return;\n }\n\n const el = this.getElement();\n if (!el) {\n return;\n }\n\n const trackW = DOM.source.getScrollBarWidth();\n if (trackW === 0) {\n return;\n }\n\n // `\"both\"` forces both scrollbars on (`overflow: scroll` on both\n // axes), so the gutter is always reserved on both sides. The\n // single-axis modes only show their one bar, and `\"auto\"` shows\n // each independently; reading `scrollHeight > clientHeight` (and\n // its X-axis twin) detects whichever bars the browser has chosen\n // to render this frame, which matches the visible-only criterion.\n let vReserved: boolean;\n let hReserved: boolean;\n\n if (this._autoScroll === \"both\") {\n vReserved = true;\n hReserved = true;\n } else {\n const axes = this.scrollableAxes();\n const metrics = DOM.source.getScrollMetrics(el);\n\n vReserved = axes.y && metrics.scrollHeight > metrics.clientHeight;\n hReserved = axes.x && metrics.scrollWidth > metrics.clientWidth;\n }\n\n const newRight = vReserved ? trackW : 0;\n const newBottom = hReserved ? trackW : 0;\n\n if (newRight === this._scrollbarGutter.right && newBottom === this._scrollbarGutter.bottom) {\n return;\n }\n\n this.setScrollbarGutter(newRight, newBottom);\n this.scheduleLayout();\n }\n\n /**\n * Brings the scroll-shadow overlay into the state implied by the current\n * `scrollShadows` / `autoScroll` settings: torn down when disabled or\n * non-scrolling, otherwise installed and refreshed. No-op before the\n * element exists — `init` performs the first install once rendered.\n */\n private refreshScrollShadows(): void {\n if (!this._scrollShadows || this._autoScroll === \"none\") {\n this.removeScrollShadows();\n\n return;\n }\n\n const element = this.getElement();\n if (!element) {\n return;\n }\n\n this.installScrollShadows(element);\n this.updateScrollShadows(element);\n }\n\n /**\n * Creates the overlay and wires the scroll listener if they are not\n * already present. Idempotent: the `_shadowOverlay` / `_shadowScrollHandler` guards\n * keep it from stacking a duplicate overlay or listener across repeated\n * calls (the \"wire once\" rule).\n *\n * @param element - The rendered panel element to append the overlay to.\n */\n private installScrollShadows(element: Handle): void {\n if (!this._shadowOverlay) {\n this.createScrollShadowOverlay(element);\n }\n\n if (!this._shadowScrollHandler) {\n const handler = (): void => {\n this.updateScrollShadows();\n };\n\n this._shadowScrollHandler = handler;\n // Subtree, not exact-target: in overlay mode the scroll fires on the\n // id-less inner element, which only reaches the panel's id-keyed\n // listener bag by climbing the subtree. Native mode's scroll fires on\n // the panel element itself, which the subtree walk also matches.\n Event.addSubtreeListener(this, \"scroll\", handler);\n }\n }\n\n /**\n * Builds the non-interactive shadow overlay: an id-less, listener-free\n * presentational sheath (mirroring the clip/content frames) carrying four\n * blurred inset edge shadows, one per side. Each shadow's colour is a local\n * custom property defaulting to `transparent`, so the per-scroll path only\n * flips a property to light an edge rather than rebuilding the shadow.\n *\n * @param element - The panel element the overlay is appended to.\n */\n private createScrollShadowOverlay(element: Handle): void {\n const overlay = DOM.sink.createElement(\"div\");\n\n this._shadowOverlayStyle.attach(overlay);\n this._shadowOverlayStyle.setMany({\n // `sticky` pins the overlay to the scroll-port viewport on the\n // compositor: the browser keeps it at the `top: 0` / `left: 0`\n // edge as the content scrolls underneath, so it tracks the\n // viewport without any per-scroll JS write (no transform repin, no\n // main-thread flicker). It also does not extend the scrollable\n // region, since it stays inside the viewport box.\n position: \"sticky\",\n left: \"0px\",\n top: \"0px\",\n pointerEvents: \"none\",\n // Paint above the content frame: `setContentFrame` re-appends that\n // frame as the element's last child during layout, so DOM order\n // alone would let it cover an overlay appended here at `init`.\n zIndex: \"1\",\n // Four blurred inset shadows — one per edge — each gated by a local\n // custom property defaulting to `transparent` (flipped to the theme\n // colour by `setShadowEdge`). See `scrollShadowBoxShadow`.\n boxShadow: scrollShadowBoxShadow(),\n });\n\n DOM.sink.appendChild(element, overlay);\n // Track the panel-owned overlay so a discarded panel releases it on GC\n // even if removeScrollShadows never runs; untracked there on eager removal.\n this.trackHandle(overlay);\n this._shadowOverlay = overlay;\n }\n\n /**\n * Tears the overlay down and unwires the scroll listener, resetting the\n * cached edge state. Each step is guarded so this is safe to call before\n * the overlay was ever created (e.g. during the construction cascade).\n */\n private removeScrollShadows(): void {\n if (this._shadowScrollHandler) {\n Event.removeSubtreeListener(this, \"scroll\", this._shadowScrollHandler);\n this._shadowScrollHandler = null;\n }\n\n if (this._shadowOverlay) {\n DOM.sink.removeElement(this._shadowOverlay);\n this.untrackHandle(this._shadowOverlay);\n DOM.sink.release(this._shadowOverlay);\n this._shadowOverlay = null;\n\n // The buffer was bound to the now-removed overlay; a fresh one is\n // needed for any future re-install (mirrors `disposeFrame`).\n this._shadowOverlayStyle = new InlineStyle();\n }\n\n this._shadowEdges = { top: 0, bottom: 0, left: 0, right: 0 };\n }\n\n /**\n * Re-asserts the shadow overlay's size against the live viewport box (a\n * no-op write unless it changed).\n *\n * The overlay is the panel's only in-flow child — every child *component*\n * is absolutely positioned — so its height alone floors the element's\n * `scrollHeight`. That makes its size load-bearing for\n * {@link Panel.measureScrollbarGutter}, not merely cosmetic: while it\n * carries the previous pass's height, a panel that just shrank reads\n * `scrollHeight` (the stale, taller overlay) above `clientHeight` (the\n * freshly committed height) and reserves a scrollbar gutter for an overflow\n * that does not exist. Hence `doLayout` re-sizes the overlay *before* it\n * measures, which is what keeps the \"stays inside the viewport box, so it\n * never extends the scrollable region\" invariant true on the shrinking pass\n * as well as the settled one.\n *\n * @param element - Optional. The panel element; falls back to the rendered\n * element. Passed explicitly from `init`, where `getElement` is not yet\n * populated.\n */\n private resizeScrollShadowOverlay(element?: Handle): void {\n const el = element ?? this.getElement();\n if (!el || !this._shadowOverlay) {\n return;\n }\n\n const { clientWidth, clientHeight } = DOM.source.getScrollMetrics(el);\n\n // In overlay-scrollbar mode the native bar is hidden, so clientWidth /\n // clientHeight still span the strip the overlay Scrollbar paints on.\n // Inset the shadow overlay by the reserved overlay gutter so each edge\n // shadow lands just inside its bar — aligned with the content viewport\n // getInnerSize exposes — instead of bleeding under the translucent bar\n // track (which reads as the shadow painting on top of the scrollbar).\n // Native mode needs no inset: clientWidth / clientHeight already exclude\n // the OS scrollbar, so the gutter there is physical, not overlaid.\n const rightInset = this._scrollbarStyle === \"overlay\" ? this._scrollbarGutter.right : 0;\n const bottomInset = this._scrollbarStyle === \"overlay\" ? this._scrollbarGutter.bottom : 0;\n\n // Size the overlay to the viewport box; `position: sticky` keeps it\n // pinned there as the content scrolls, so no transform is needed.\n this._shadowOverlayStyle.setMany({\n width: (clientWidth - rightInset) + \"px\",\n height: (clientHeight - bottomInset) + \"px\",\n });\n }\n\n /**\n * Sizes the overlay to the live viewport and recomputes each edge's shadow\n * strength from its distance to that extreme. `sticky` handles the\n * positioning, so the per-scroll path only re-asserts the viewport size (a\n * no-op write unless it changed) and rescales the edges — no positioning\n * work runs here.\n *\n * @param element - Optional. The panel element; falls back to the rendered\n * element. Passed explicitly from `init`, where `getElement` is not yet\n * populated.\n */\n private updateScrollShadows(element?: Handle): void {\n const el = element ?? this.getElement();\n if (!el || !this._shadowOverlay) {\n return;\n }\n\n // Read the scroll offsets and extents from the element that actually\n // scrolls — the inner scroller in overlay mode (the panel element's own\n // offsets are always 0 there), the panel element otherwise. The overlay\n // is still sized against, and pinned to, the panel element (`el`).\n const { scrollTop, scrollLeft, scrollWidth, scrollHeight, clientWidth, clientHeight } =\n DOM.source.getScrollMetrics(this.getScrollElement() ?? el);\n\n this.resizeScrollShadowOverlay(el);\n\n const maxTop = scrollHeight - clientHeight;\n const maxLeft = scrollWidth - clientWidth;\n\n // Ramp an edge in by its distance past that extreme (see `scrollShadowRamp`).\n const ramp = scrollShadowRamp;\n\n // A shadow says \"there is more content this way, scroll to reach it\", so\n // only an axis the user can actually scroll may light its edges. A\n // clipped axis still reports overflow through `scrollWidth` /\n // `scrollHeight` — an `autoScroll: \"y\"` panel whose content is a few px\n // wider than its post-gutter width reads a non-zero `maxLeft` — and\n // ramping that would paint a right-edge fade promising content no\n // gesture can reveal.\n const axes = this.scrollableAxes();\n\n this.setShadowEdge(\"top\", \"--ts-ss-top\", axes.y ? ramp(scrollTop) : 0);\n this.setShadowEdge(\"bottom\", \"--ts-ss-bottom\", axes.y ? ramp(maxTop - scrollTop) : 0);\n this.setShadowEdge(\"left\", \"--ts-ss-left\", axes.x ? ramp(scrollLeft) : 0);\n this.setShadowEdge(\"right\", \"--ts-ss-right\", axes.x ? ramp(maxLeft - scrollLeft): 0);\n }\n\n /**\n * Sets a single edge's shadow strength by scaling the theme shadow colour\n * toward transparent. Strength is quantised to a whole percent so an\n * in-ramp scroll only repaints when the visible strength actually changes\n * (and never sub-pixel-thrashes); at zero the property is unset so the\n * `box-shadow` layer falls back to `transparent`.\n *\n * @param edge - The edge whose cached strength this updates.\n * @param property - The overlay custom property backing that edge's shadow.\n * @param strength - The target strength in the range 0–1.\n */\n private setShadowEdge(edge: keyof ScrollShadowEdges, property: string, strength: number): void {\n const percent = Math.round(strength * 100); // quantise: 0–1 → 0–100%\n\n if (this._shadowEdges[edge] === percent) {\n return;\n }\n\n this._shadowEdges[edge] = percent;\n this._shadowOverlayStyle.set(property, scrollShadowEdgeValue(percent));\n }\n\n /**\n * Brings the overlay scrollbar into the state implied by the current\n * `scrollbarStyle` / `autoScroll` settings: torn down when native or\n * non-scrolling, otherwise installed and laid out. No-op before the\n * element exists — `init` performs the first install once rendered.\n */\n private refreshOverlayScrollbars(): void {\n if (this._scrollbarStyle !== \"overlay\" || this._autoScroll === \"none\") {\n this.removeOverlayScrollbars();\n\n return;\n }\n\n const element = this.getElement();\n if (!element) {\n return;\n }\n\n this.installOverlayScrollbars(element);\n this.layoutOverlayScrollbars(element);\n }\n\n /**\n * Creates the inner scroll element (if absent), appends the two `Scrollbar`\n * widgets as its siblings on the panel element, and hides the native bar.\n * Idempotent: the element/bars/listener are each guarded by a `null` check,\n * so repeated calls neither stack duplicates nor re-hide an already-hidden\n * bar — but the inner element's per-axis overflow IS re-asserted on every\n * call so a runtime `setAutoScroll` mode-to-mode change (which keeps the\n * existing inner element) updates which axes scroll.\n *\n * @param element - The rendered panel element to append the inner scroller\n * and bars into.\n */\n private installOverlayScrollbars(element: Handle): void {\n if (!this._overlayScrollElement) {\n // The native scroll happens on this inner element, physically inset\n // by the reserved track (see `layoutOverlayScrollbars`) so content\n // clips at the inner viewport edge and can never scroll under a bar.\n // The bars are its SIBLINGS on the panel element (below), outside\n // this element's overflow clip — the two-element structure\n // `VirtualScroller` uses. The panel element keeps its own\n // `overflow: auto` (inert: the inner element is absolute / out of\n // flow and always fits, so the panel element never scrolls).\n ensureOverlayScrollerClassRule();\n\n const inner = DOM.sink.createElement(\"div\");\n\n // `width/height: 100%` fills the panel element's padding box (its\n // containing block, since every Component is positioned) so the\n // first overflow read sees the full viewport; `layoutOverlayScrollbars`\n // then overrides with the explicit post-gutter px size each pass.\n this._overlayScrollStyle.attach(inner);\n this._overlayScrollStyle.setMany({\n position: \"absolute\",\n left: \"0px\",\n top: \"0px\",\n width: \"100%\",\n height: \"100%\",\n });\n\n // Hide the inner element's own native bar via the shared class rule\n // (it has no `#id`, so the panel element's per-`#id` path can't reach it).\n DOM.sink.apply(inner, { addClass: [OVERLAY_SCROLLER_CLASS] });\n DOM.sink.appendChild(element, inner);\n\n // Shift the existing children (or the active content frame) onto the\n // inner scroller, preserving the scroll offset across the host swap.\n this.reparentContent(element, inner);\n\n this.trackHandle(inner);\n this._overlayScrollElement = inner;\n }\n\n // Re-assert the inner element's per-axis overflow every call: on a\n // runtime `setAutoScroll` mode-to-mode change the inner element already\n // exists (no teardown), so the guard above is skipped — but the newly\n // scrollable axis must flip from `hidden` to `auto` (and vice versa) or\n // native wheel/keyboard scroll and the matching bar would be inert.\n const axes = this.scrollableAxes();\n this._overlayScrollStyle.setMany({\n overflowX: axes.x ? \"auto\" : \"hidden\",\n overflowY: axes.y ? \"auto\" : \"hidden\",\n });\n\n if (!this._scrollbarV) {\n this._scrollbarV = new Scrollbar(\"vertical\");\n this._scrollbarV.setZIndex(2); // above the shadow overlay's z-index: 1\n DOM.sink.appendChild(element, this._scrollbarV.getElement(true)!);\n this._scrollbarV.on(\"scroll\", this._onOverlayScrollV);\n }\n\n if (!this._scrollbarH) {\n this._scrollbarH = new Scrollbar(\"horizontal\");\n this._scrollbarH.setZIndex(2);\n DOM.sink.appendChild(element, this._scrollbarH.getElement(true)!);\n this._scrollbarH.on(\"scroll\", this._onOverlayScrollH);\n }\n\n if (!this._overlayScrollHandler) {\n // Subtree, not exact-target: the inner scroll element is a raw,\n // id-less div, so its native \"scroll\" only reaches the panel's\n // id-keyed listener bag by climbing the subtree to the panel element\n // (the same mechanism the wheel listener uses). The handler reads\n // `getScrollElement()`, not the event target, so a nested\n // descendant's scroll only triggers a harmless re-read.\n const handler = (): void => {\n this.syncOverlayScrollbars();\n };\n\n this._overlayScrollHandler = handler;\n Event.addSubtreeListener(this, \"scroll\", handler);\n }\n\n this.setNativeScrollbarHidden(true);\n }\n\n /**\n * Tears the overlay scrollbar down: unwires the native scroll listener,\n * detaches and discards both bars, removes the sticky host, un-hides the\n * native bar, and clears any reserved gutter. Each step is guarded so\n * this is safe to call before the overlay was ever created (e.g. during\n * the construction cascade).\n */\n private removeOverlayScrollbars(): void {\n if (this._overlayScrollHandler) {\n Event.removeSubtreeListener(this, \"scroll\", this._overlayScrollHandler);\n this._overlayScrollHandler = null;\n }\n\n if (this._scrollbarV) {\n this._scrollbarV.off(\"scroll\", this._onOverlayScrollV);\n this._scrollbarV.removeElement();\n this._scrollbarV = null;\n }\n\n if (this._scrollbarH) {\n this._scrollbarH.off(\"scroll\", this._onOverlayScrollH);\n this._scrollbarH.removeElement();\n this._scrollbarH = null;\n }\n\n if (this._overlayScrollElement) {\n // Re-parent the children (or content frame) back onto the panel\n // element — which resumes scrolling in native mode — before the\n // inner element is destroyed, preserving the scroll offset.\n const element = this.getElement();\n\n if (element) {\n this.reparentContent(this._overlayScrollElement, element);\n }\n\n DOM.sink.removeElement(this._overlayScrollElement);\n this.untrackHandle(this._overlayScrollElement);\n DOM.sink.release(this._overlayScrollElement);\n this._overlayScrollElement = null;\n\n // The buffer was bound to the now-removed inner element; a fresh one\n // is needed for any future re-install (mirrors `_shadowOverlayStyle`\n // in `removeScrollShadows`).\n this._overlayScrollStyle = new InlineStyle();\n }\n\n this.setNativeScrollbarHidden(false);\n\n // Unconditional (rather than gated on the previous value, as\n // `setAutoScroll`'s native-path gutter-clear is): `setLayoutManager`\n // can re-enter this teardown from inside `Component.applyOptions`'s\n // own `layoutManager` option handling, before Panel's `applyOptions`\n // body has seeded `_scrollbarGutter` at all. The assignment itself is\n // a cheap plain-object write, so skipping the read-before-write\n // avoids that ordering hazard for free.\n this.setScrollbarGutter(0, 0);\n }\n\n /**\n * Hides or restores the native scrollbar through the framework's deferred\n * style seams — a `scrollbar-width: none` write on the component's own\n * `#id` rule (Firefox / Chromium >= 121) plus a `#id::-webkit-scrollbar {\n * display: none }` state rule (WebKit / older Blink).\n *\n * @param hidden - `true` to hide the native bar, `false` to restore it.\n */\n private setNativeScrollbarHidden(hidden: boolean): void {\n this.setElementCSSRule(\"scrollbarWidth\", hidden ? \"none\" : null);\n this.createStyleRule(\"::-webkit-scrollbar\").set(\"display\", hidden ? \"none\" : null);\n }\n\n /**\n * Sizes the inner scroll element to the available viewport minus the track\n * on each axis whose perpendicular bar is visible, positions both bars in\n * the reserved band at the trailing edges, pushes their metrics, and\n * reserves the matching gutter — rescheduling a layout pass when it changed.\n * Called from `init` (first install) and from `measureScrollbarGutter`'s\n * overlay branch (every `doLayout` pass).\n *\n * The dual read is the crux: the **available viewport** comes from the panel\n * element (which never scrolls, so its client box is the full viewport),\n * while content extent, offsets, and the current inner client box come from\n * the **inner scroll element**. Physically insetting the inner element is\n * what makes overflowing content clip before the bar band instead of\n * scrolling under it.\n *\n * @param element - Optional. The panel element; falls back to the rendered\n * element. Passed explicitly from `init`, where `getElement` is not yet\n * populated.\n */\n private layoutOverlayScrollbars(element?: Handle): void {\n const panelEl = element ?? this.getElement();\n const innerEl = this._overlayScrollElement;\n if (!panelEl || !innerEl || !this._scrollbarV || !this._scrollbarH) {\n return;\n }\n\n const trackW = this._scrollbarV.getTrackWidth();\n\n // Available viewport: the panel element's client box. The parent layout\n // sizes the panel element (and `doLayout` flushes it via\n // `commitElementStyle`) before this runs, so `avail` is always current —\n // it never lags a resize.\n const avail = DOM.source.getScrollMetrics(panelEl);\n const availW = avail.clientWidth;\n const availH = avail.clientHeight;\n\n const curRight = this._scrollbarGutter.right;\n const curBottom = this._scrollbarGutter.bottom;\n\n // Size the inner scroller to the CURRENT viewport (minus the currently\n // reserved gutter) BEFORE reading its metrics, so its `clientWidth`/\n // `clientHeight` — and thus `scrollWidth`/`scrollHeight`, which the\n // browser floors at the client box — reflect THIS frame's viewport. The\n // inner element otherwise carries the previous pass's size, which lags a\n // resize in BOTH directions: on expand the stale-small client box kept a\n // bar the widened viewport no longer needs; on shrink the stale-large\n // client box floored `scrollWidth` so content that now fits still read as\n // overflowing — each flickered a transient bar that could stick. A gutter\n // change below re-sizes and reschedules, converging in one extra pass.\n this._overlayScrollStyle.setMany({\n width: (availW - curRight) + \"px\",\n height: (availH - curBottom) + \"px\",\n });\n\n // Content extent, offsets, and the now-current inner client box.\n const m = DOM.source.getScrollMetrics(innerEl);\n const axes = this.scrollableAxes();\n\n // A bar shows when content exceeds the inner scroller's (now current)\n // viewport. The V<->H dependency — reserving one bar shrinks the other's\n // viewport — settles across passes via the gutter-change reschedule\n // below, the same one-extra-pass convergence the gutter always used.\n const vVisible = axes.y && m.scrollHeight > m.clientHeight;\n const hVisible = axes.x && m.scrollWidth > m.clientWidth;\n\n const innerW = availW - (vVisible ? trackW : 0);\n const innerH = availH - (hVisible ? trackW : 0);\n\n // Re-inset the inner scroller when this pass's gutter differs from the\n // one the pre-read sizing used, so overflowing content clips at the inner\n // viewport edge and can never scroll under a bar.\n if (innerW !== availW - curRight || innerH !== availH - curBottom) {\n this._overlayScrollStyle.setMany({ width: innerW + \"px\", height: innerH + \"px\" });\n }\n\n // Bars occupy the reserved band at the trailing edges, sized to the\n // inner extent so each stops short of the shared corner. setMetrics\n // takes the same reduced viewport (`innerH`/`innerW`) the visibility\n // test used, so a bar's shown/hidden state and the reserved gutter\n // never disagree.\n this._scrollbarV.setX(innerW);\n this._scrollbarV.setY(0);\n this._scrollbarV.setHeight(innerH);\n this._scrollbarV.setMetrics(innerH, m.scrollHeight, m.scrollTop);\n\n this._scrollbarH.setX(0);\n this._scrollbarH.setY(innerH);\n this._scrollbarH.setWidth(innerW);\n this._scrollbarH.setMetrics(innerW, m.scrollWidth, m.scrollLeft);\n\n const newRight = vVisible ? trackW : 0;\n const newBottom = hVisible ? trackW : 0;\n\n if (newRight !== curRight || newBottom !== curBottom) {\n this.setScrollbarGutter(newRight, newBottom);\n this.scheduleLayout();\n }\n }\n\n /**\n * Re-pushes metrics (thumb size/position only) to both overlay bars against\n * the inner scroller's live scroll offset. Called from the native `\"scroll\"`\n * handler — geometry (bar position/size, reserved gutter, inner element\n * size) changes only on layout, so this never repositions or resizes\n * anything and never schedules a layout.\n */\n private syncOverlayScrollbars(): void {\n const innerEl = this._overlayScrollElement;\n if (!innerEl || !this._scrollbarV || !this._scrollbarH) {\n return;\n }\n\n const m = DOM.source.getScrollMetrics(innerEl);\n\n this._scrollbarV.setMetrics(m.clientHeight, m.scrollHeight, m.scrollTop);\n this._scrollbarH.setMetrics(m.clientWidth, m.scrollWidth, m.scrollLeft);\n }\n}\n\nconst PanelCallable = callable(Panel);\ntype PanelCallable<TOptions extends PanelOptions = PanelOptions> = Panel<TOptions>;\nexport {\n Panel as _Panel,\n PanelCallable as Panel\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n as e,u as t}from"./Position-B-WfZYAJ.js";import{_ as n,f as r,g as i,y as a}from"./Component-BR2f0Itb.js";import{i as o,n as s,r as c,t as l}from"./Scrollbar-DchfiFKC.js";import{t as u}from"./Container-3KsvsJ6S.js";var d={tag:`div`,insets:new e(4,4,4,4)},f=`PanelOverlayScroller`,p=null;function ensureOverlayScrollerClassRule(){p||=[new n({scope:`class`,name:f,styles:{scrollbarWidth:`none`}}),new n({scope:`selector`,name:`.${f}::-webkit-scrollbar`,styles:{display:`none`}})]}var Panel=class extends u{_shadowOverlayStyle=new i;_lastChildCount=0;_overlayScrollStyle=new i;_onOverlayScrollV=e=>{this.setScrollTop(e)};_onOverlayScrollH=e=>{this.setScrollLeft(e)};constructor(t,n){let r=t?.flush?{insets:new e(0,0,0,0)}:{};super(t,{...d,...n??{},...r})}applyOptions(e){return super.applyOptions(e),this.setScrollbarGutter(0,0),this._shadowEdges={top:0,bottom:0,left:0,right:0},this._lastContentExtent={width:0,height:0},this.setAutoScroll(e.autoScroll??`none`),this._shadowOverlay=null,this._shadowScrollHandler=null,this.setScrollShadows(e.scrollShadows??!0),this._overlayScrollElement=null,this._scrollbarV=null,this._scrollbarH=null,this._overlayScrollHandler=null,this.setScrollbarStyle(e.scrollbarStyle??`overlay`),this}setAutoScroll(e){switch(this._autoScroll=e,e){case`none`:this.setOverflowX(`hidden`).setOverflowY(`hidden`);break;case`auto`:this.setOverflowX(`auto`).setOverflowY(`auto`);break;case`x`:this.setOverflowX(`auto`).setOverflowY(`hidden`);break;case`y`:this.setOverflowX(`hidden`).setOverflowY(`auto`);break;case`both`:this.setOverflowX(`scroll`).setOverflowY(`scroll`);break}e===`none`&&(this._scrollbarGutter.right!==0||this._scrollbarGutter.bottom!==0)&&this.setScrollbarGutter(0,0);let t=this.scrollableAxes();return this.getLayoutManager()?.setOverflowing(t.x,t.y),this.refreshOverlayScrollbars(),this.refreshScrollShadows(),this}setLayoutManager(e){return super.setLayoutManager(e),this.setAutoScroll(this._autoScroll),this}getAutoScroll(){return this._autoScroll}clearAutoScroll(){return this.setAutoScroll(`none`)}setScrollShadows(e){return this._scrollShadows=e,this.refreshScrollShadows(),this}getScrollShadows(){return this._scrollShadows}setScrollbarStyle(e){return this._scrollbarStyle=e,this.refreshOverlayScrollbars(),this.refreshScrollShadows(),this}getScrollbarStyle(){return this._scrollbarStyle}getScrollElement(){return this._overlayScrollElement??this.getElement()}getInnerSize(){let e=super.getInnerSize();return e?{width:e.width-this._scrollbarGutter.right,height:e.height-this._scrollbarGutter.bottom}:null}doLayout(){return super.doLayout(),this.commitElementStyle(),this.resizeScrollShadowOverlay(),this.measureScrollbarGutter(),this.updateScrollShadows(),this.scheduleGutterSettleOnShrink(),this}scheduleGutterSettleOnShrink(){if(this._autoScroll===`none`)return;let e=this.getComponents().length,t=e<this._lastChildCount;this._lastChildCount=e;let n=!1;if(this.showsScrollAffordance()){let e=this.getPreferredSize(),t=e?e.width:0,r=e?e.height:0;n=t<this._lastContentExtent.width||r<this._lastContentExtent.height,this._lastContentExtent={width:t,height:r}}(t||n)&&this.scheduleLayout()}showsScrollAffordance(){return this._scrollbarGutter.right>0||this._scrollbarGutter.bottom>0||this._shadowEdges.top>0||this._shadowEdges.bottom>0||this._shadowEdges.left>0||this._shadowEdges.right>0}init(e){super.init(e);let t=e??this.getElement();return t&&this._scrollbarStyle===`overlay`&&this._autoScroll!==`none`&&(this.installOverlayScrollbars(t),this.layoutOverlayScrollbars(t)),t&&this._scrollShadows&&this._autoScroll!==`none`&&(this.installScrollShadows(t),this.updateScrollShadows(t)),this}destructor(){this.removeScrollShadows(),this.removeOverlayScrollbars(),super.destructor()}scrollableAxes(){let e=this._autoScroll;return{x:e===`x`||e===`auto`||e===`both`,y:e===`y`||e===`auto`||e===`both`}}setScrollbarGutter(e,t){this._scrollbarGutter={right:e,bottom:t}}measureScrollbarGutter(){if(this._autoScroll===`none`)return;if(this._scrollbarStyle===`overlay`){this.layoutOverlayScrollbars();return}let e=this.getElement();if(!e)return;let n=t.source.getScrollBarWidth();if(n===0)return;let r,i;if(this._autoScroll===`both`)r=!0,i=!0;else{let n=this.scrollableAxes(),a=t.source.getScrollMetrics(e);r=n.y&&a.scrollHeight>a.clientHeight,i=n.x&&a.scrollWidth>a.clientWidth}let a=r?n:0,o=i?n:0;a===this._scrollbarGutter.right&&o===this._scrollbarGutter.bottom||(this.setScrollbarGutter(a,o),this.scheduleLayout())}refreshScrollShadows(){if(!this._scrollShadows||this._autoScroll===`none`){this.removeScrollShadows();return}let e=this.getElement();e&&(this.installScrollShadows(e),this.updateScrollShadows(e))}installScrollShadows(e){if(this._shadowOverlay||this.createScrollShadowOverlay(e),!this._shadowScrollHandler){let handler=()=>{this.updateScrollShadows()};this._shadowScrollHandler=handler,a.addSubtreeListener(this,`scroll`,handler)}}createScrollShadowOverlay(e){let n=t.sink.createElement(`div`);this._shadowOverlayStyle.attach(n),this._shadowOverlayStyle.setMany({position:`sticky`,left:`0px`,top:`0px`,pointerEvents:`none`,zIndex:`1`,boxShadow:s()}),t.sink.appendChild(e,n),this.trackHandle(n),this._shadowOverlay=n}removeScrollShadows(){this._shadowScrollHandler&&=(a.removeSubtreeListener(this,`scroll`,this._shadowScrollHandler),null),this._shadowOverlay&&(t.sink.removeElement(this._shadowOverlay),this.untrackHandle(this._shadowOverlay),t.sink.release(this._shadowOverlay),this._shadowOverlay=null,this._shadowOverlayStyle=new i),this._shadowEdges={top:0,bottom:0,left:0,right:0}}resizeScrollShadowOverlay(e){let n=e??this.getElement();if(!n||!this._shadowOverlay)return;let{clientWidth:r,clientHeight:i}=t.source.getScrollMetrics(n),a=this._scrollbarStyle===`overlay`?this._scrollbarGutter.right:0,o=this._scrollbarStyle===`overlay`?this._scrollbarGutter.bottom:0;this._shadowOverlayStyle.setMany({width:r-a+`px`,height:i-o+`px`})}updateScrollShadows(e){let n=e??this.getElement();if(!n||!this._shadowOverlay)return;let{scrollTop:r,scrollLeft:i,scrollWidth:a,scrollHeight:s,clientWidth:c,clientHeight:l}=t.source.getScrollMetrics(this.getScrollElement()??n);this.resizeScrollShadowOverlay(n);let u=s-l,d=a-c,f=o,p=this.scrollableAxes();this.setShadowEdge(`top`,`--ts-ss-top`,p.y?f(r):0),this.setShadowEdge(`bottom`,`--ts-ss-bottom`,p.y?f(u-r):0),this.setShadowEdge(`left`,`--ts-ss-left`,p.x?f(i):0),this.setShadowEdge(`right`,`--ts-ss-right`,p.x?f(d-i):0)}setShadowEdge(e,t,n){let r=Math.round(n*100);this._shadowEdges[e]!==r&&(this._shadowEdges[e]=r,this._shadowOverlayStyle.set(t,c(r)))}refreshOverlayScrollbars(){if(this._scrollbarStyle!==`overlay`||this._autoScroll===`none`){this.removeOverlayScrollbars();return}let e=this.getElement();e&&(this.installOverlayScrollbars(e),this.layoutOverlayScrollbars(e))}installOverlayScrollbars(e){if(!this._overlayScrollElement){ensureOverlayScrollerClassRule();let n=t.sink.createElement(`div`);this._overlayScrollStyle.attach(n),this._overlayScrollStyle.setMany({position:`absolute`,left:`0px`,top:`0px`,width:`100%`,height:`100%`}),t.sink.apply(n,{addClass:[f]}),t.sink.appendChild(e,n),this.reparentContent(e,n),this.trackHandle(n),this._overlayScrollElement=n}let n=this.scrollableAxes();if(this._overlayScrollStyle.setMany({overflowX:n.x?`auto`:`hidden`,overflowY:n.y?`auto`:`hidden`}),this._scrollbarV||(this._scrollbarV=new l(`vertical`),this._scrollbarV.setZIndex(2),t.sink.appendChild(e,this._scrollbarV.getElement(!0)),this._scrollbarV.on(`scroll`,this._onOverlayScrollV)),this._scrollbarH||(this._scrollbarH=new l(`horizontal`),this._scrollbarH.setZIndex(2),t.sink.appendChild(e,this._scrollbarH.getElement(!0)),this._scrollbarH.on(`scroll`,this._onOverlayScrollH)),!this._overlayScrollHandler){let handler=()=>{this.syncOverlayScrollbars()};this._overlayScrollHandler=handler,a.addSubtreeListener(this,`scroll`,handler)}this.setNativeScrollbarHidden(!0)}removeOverlayScrollbars(){if(this._overlayScrollHandler&&=(a.removeSubtreeListener(this,`scroll`,this._overlayScrollHandler),null),this._scrollbarV&&=(this._scrollbarV.off(`scroll`,this._onOverlayScrollV),this._scrollbarV.removeElement(),null),this._scrollbarH&&=(this._scrollbarH.off(`scroll`,this._onOverlayScrollH),this._scrollbarH.removeElement(),null),this._overlayScrollElement){let e=this.getElement();e&&this.reparentContent(this._overlayScrollElement,e),t.sink.removeElement(this._overlayScrollElement),this.untrackHandle(this._overlayScrollElement),t.sink.release(this._overlayScrollElement),this._overlayScrollElement=null,this._overlayScrollStyle=new i}this.setNativeScrollbarHidden(!1),this.setScrollbarGutter(0,0)}setNativeScrollbarHidden(e){this.setElementCSSRule(`scrollbarWidth`,e?`none`:null),this.createStyleRule(`::-webkit-scrollbar`).set(`display`,e?`none`:null)}layoutOverlayScrollbars(e){let n=e??this.getElement(),r=this._overlayScrollElement;if(!n||!r||!this._scrollbarV||!this._scrollbarH)return;let i=this._scrollbarV.getTrackWidth(),a=t.source.getScrollMetrics(n),o=a.clientWidth,s=a.clientHeight,c=this._scrollbarGutter.right,l=this._scrollbarGutter.bottom;this._overlayScrollStyle.setMany({width:o-c+`px`,height:s-l+`px`});let u=t.source.getScrollMetrics(r),d=this.scrollableAxes(),f=d.y&&u.scrollHeight>u.clientHeight,p=d.x&&u.scrollWidth>u.clientWidth,m=o-(f?i:0),h=s-(p?i:0);(m!==o-c||h!==s-l)&&this._overlayScrollStyle.setMany({width:m+`px`,height:h+`px`}),this._scrollbarV.setX(m),this._scrollbarV.setY(0),this._scrollbarV.setHeight(h),this._scrollbarV.setMetrics(h,u.scrollHeight,u.scrollTop),this._scrollbarH.setX(0),this._scrollbarH.setY(h),this._scrollbarH.setWidth(m),this._scrollbarH.setMetrics(m,u.scrollWidth,u.scrollLeft);let g=f?i:0,_=p?i:0;(g!==c||_!==l)&&(this.setScrollbarGutter(g,_),this.scheduleLayout())}syncOverlayScrollbars(){let e=this._overlayScrollElement;if(!e||!this._scrollbarV||!this._scrollbarH)return;let n=t.source.getScrollMetrics(e);this._scrollbarV.setMetrics(n.clientHeight,n.scrollHeight,n.scrollTop),this._scrollbarH.setMetrics(n.clientWidth,n.scrollWidth,n.scrollLeft)}},m=r(Panel);export{m as t};
|
|
2
|
-
//# sourceMappingURL=Panel-DIsdaqc2.js.map
|