@jimka/typescript-ui 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/{AbstractBooleanInput-C3rj7sje.js → AbstractBooleanInput-BGesvIZy.js} +2 -2
- package/dist/lib/{AbstractBooleanInput-C3rj7sje.js.map → AbstractBooleanInput-BGesvIZy.js.map} +1 -1
- package/dist/lib/{AbstractInput-CfjW_HM2.js → AbstractInput-BxOtFrER.js} +2 -2
- package/dist/lib/{AbstractInput-CfjW_HM2.js.map → AbstractInput-BxOtFrER.js.map} +1 -1
- package/dist/lib/AnimatedDropdown-CZQEqQi-.js +2 -0
- package/dist/lib/AnimatedDropdown-CZQEqQi-.js.map +1 -0
- package/dist/lib/Border-BgaZkc1R.js +2 -0
- package/dist/lib/Border-BgaZkc1R.js.map +1 -0
- package/dist/lib/{BoxLayout-8ryMD4j5.js → BoxLayout-DrKGfsup.js} +2 -2
- package/dist/lib/{BoxLayout-8ryMD4j5.js.map → BoxLayout-DrKGfsup.js.map} +1 -1
- package/dist/lib/Button-U1rsP4v8.js +2 -0
- package/dist/lib/Button-U1rsP4v8.js.map +1 -0
- package/dist/lib/{Card-AKIUAWYS.js → Card-BVwOS8AG.js} +2 -2
- package/dist/lib/{Card-AKIUAWYS.js.map → Card-BVwOS8AG.js.map} +1 -1
- package/dist/lib/ComboBox-B9EDPu6T.js +2 -0
- package/dist/lib/ComboBox-B9EDPu6T.js.map +1 -0
- package/dist/lib/Component-DXf5a3g0.js +2 -0
- package/dist/lib/Component-DXf5a3g0.js.map +1 -0
- package/dist/lib/Container-D5H8VxJK.js +2 -0
- package/dist/lib/{Container-3KsvsJ6S.js.map → Container-D5H8VxJK.js.map} +1 -1
- package/dist/lib/DOM-CGn7xyTw.js +2 -0
- package/dist/lib/DOM-CGn7xyTw.js.map +1 -0
- package/dist/lib/{DragManager-c6M_mE3e.js → DragManager-CI4mZQFy.js} +2 -2
- package/dist/lib/{DragManager-tPMnbjeO.js.map → DragManager-CI4mZQFy.js.map} +1 -1
- package/dist/lib/FieldDecorator-CJs9gwqH.js +2 -0
- package/dist/lib/{FieldDecorator-Bl0h9UEF.js.map → FieldDecorator-CJs9gwqH.js.map} +1 -1
- package/dist/lib/{Fit-CFIr4P9R.js → Fit-DjRsiwlg.js} +2 -2
- package/dist/lib/{Fit-CUS1JXy3.js.map → Fit-DjRsiwlg.js.map} +1 -1
- package/dist/lib/Glyph-KEf4nIv2.js +2 -0
- package/dist/lib/Glyph-KEf4nIv2.js.map +1 -0
- package/dist/lib/{Grid-Czux--Mr.js → Grid-DdL9TVeJ.js} +2 -2
- package/dist/lib/{Grid-D8luwRPI.js.map → Grid-DdL9TVeJ.js.map} +1 -1
- package/dist/lib/GridConstraints-DkLueyrf.js +2 -0
- package/dist/lib/GridConstraints-DkLueyrf.js.map +1 -0
- package/dist/lib/{HBox-BWMf9h6r.js → HBox-Ce0GTCJP.js} +2 -2
- package/dist/lib/{HBox-BWMf9h6r.js.map → HBox-Ce0GTCJP.js.map} +1 -1
- package/dist/lib/{Header-CQjomjo0.js → Header-BQIVpBte.js} +2 -2
- package/dist/lib/{Header-CQjomjo0.js.map → Header-BQIVpBte.js.map} +1 -1
- package/dist/lib/{IconText-BXJK0MOq.js → IconText-Bo4Qcnot.js} +2 -2
- package/dist/lib/{IconText-BXJK0MOq.js.map → IconText-Bo4Qcnot.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-BT66TY83.js +2 -0
- package/dist/lib/LayoutSerialization-BT66TY83.js.map +1 -0
- package/dist/lib/LayoutSizes-DU3qSq0w.js +2 -0
- package/dist/lib/LayoutSizes-DU3qSq0w.js.map +1 -0
- package/dist/lib/List-DtTVTyWW.js +2 -0
- package/dist/lib/List-DtTVTyWW.js.map +1 -0
- package/dist/lib/Menu-Dz4L7EKJ.js +2 -0
- package/dist/lib/Menu-Dz4L7EKJ.js.map +1 -0
- package/dist/lib/{MenuButton-D15cSbMf.js → MenuButton-VJ5uC3c1.js} +2 -2
- package/dist/lib/{MenuButton-D15cSbMf.js.map → MenuButton-VJ5uC3c1.js.map} +1 -1
- package/dist/lib/Panel-DzWdYwq1.js +2 -0
- package/dist/lib/Panel-DzWdYwq1.js.map +1 -0
- package/dist/lib/{Position-DJKB0N3l.js → Position-A39T7-_1.js} +2 -2
- package/dist/lib/{Position-DJKB0N3l.js.map → Position-A39T7-_1.js.map} +1 -1
- package/dist/lib/ProgressSpinner-zJKtGyNJ.js +2 -0
- package/dist/lib/ProgressSpinner-zJKtGyNJ.js.map +1 -0
- package/dist/lib/RadioButton-CYSSv4nV.js +2 -0
- package/dist/lib/RadioButton-CYSSv4nV.js.map +1 -0
- package/dist/lib/{RovingTabIndex-CFIzIjjU.js → RovingTabIndex-BSZ31Vp5.js} +2 -2
- package/dist/lib/{RovingTabIndex-D-zOuptw.js.map → RovingTabIndex-BSZ31Vp5.js.map} +1 -1
- package/dist/lib/Scrollbar-BhtOjqkG.js +2 -0
- package/dist/lib/Scrollbar-BhtOjqkG.js.map +1 -0
- package/dist/lib/Slider-CdXm7E64.js +2 -0
- package/dist/lib/Slider-CdXm7E64.js.map +1 -0
- package/dist/lib/{Spacer-BVQncB5B.js → Spacer-D9NGW4QG.js} +2 -2
- package/dist/lib/{Spacer-BVQncB5B.js.map → Spacer-D9NGW4QG.js.map} +1 -1
- package/dist/lib/{TabButton-DqYDfN7P.js → TabButton-CThevdY_.js} +2 -2
- package/dist/lib/{TabButton-DqYDfN7P.js.map → TabButton-CThevdY_.js.map} +1 -1
- package/dist/lib/Text-gz6qjFfP.js +2 -0
- package/dist/lib/Text-gz6qjFfP.js.map +1 -0
- package/dist/lib/Tooltip-tkXDk5Bo.js +3 -0
- package/dist/lib/Tooltip-tkXDk5Bo.js.map +1 -0
- package/dist/lib/{VBox-CdV9VGxR.js → VBox-EIqw85Rh.js} +2 -2
- package/dist/lib/{VBox-CdV9VGxR.js.map → VBox-EIqw85Rh.js.map} +1 -1
- package/dist/lib/{VirtualRowView-C18j90n5.js → VirtualRowView-BxpHQ_u8.js} +2 -2
- package/dist/lib/{VirtualRowView-C18j90n5.js.map → VirtualRowView-BxpHQ_u8.js.map} +1 -1
- package/dist/lib/{VirtualScroller-BKMvTisA.js → VirtualScroller-DwEEJE1_.js} +2 -2
- package/dist/lib/{VirtualScroller-BKMvTisA.js.map → VirtualScroller-DwEEJE1_.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 +2 -2
- package/dist/lib/component/editor.es.js.map +1 -1
- package/dist/lib/component/input.es.js +1 -1
- package/dist/lib/component/input.es.js.map +1 -1
- package/dist/lib/component/list.es.js +1 -1
- package/dist/lib/component/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/layout.es.js +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/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/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 +2 -1
- 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 +1 -3
- 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/core/AnimatedDropdown.d.ts +6 -2
- package/dist/lib/types/core/Animation.d.ts +9 -6
- package/dist/lib/types/core/Component.d.ts +16 -11
- package/dist/lib/types/core/DOM.d.ts +8 -0
- package/dist/lib/types/core/Event.d.ts +12 -6
- package/dist/lib/types/core/index.d.ts +2 -2
- package/dist/lib/types/layout/Accordion.d.ts +2 -0
- package/dist/lib/types/layout/Border.d.ts +1 -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 +10 -3
- package/dist/lib/types/overlay/AbstractWindow.d.ts +9 -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/validation.es.js +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- 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-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-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/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-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":"Slider-xRxNSjFN.js","names":[],"sources":["../../src/typescript/lib/component/input/Label.ts","../../src/typescript/lib/component/input/Slider.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Text, TextOptions } from \"~/component/input/Text.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Label}.\n *\n * @category Components\n */\nexport interface LabelOptions extends TextOptions {\n}\n\n/**\n * A label component backed by a `<label>` element.\n *\n * Always associated with a form control via the HTML `for` attribute.\n * For standalone text without a form-control association, use {@link Text} instead.\n *\n * @example\n * ```typescript\n * import { Label, TextField } from '@jimka/typescript-ui/component/input';\n*\n * const field = new TextField();\n * const label = new Label('Name:', field.getId());\n * panel.addComponent(label);\n * panel.addComponent(field);\n * ```\n *\n * @category Components\n */\nclass Label extends Text<LabelOptions> {\n\n private _forId: string;\n\n constructor(text: string, forId: string, options?: LabelOptions) {\n if (!forId) {\n throw new Error(\"Label requires a non-empty forId. Use Text for standalone text.\");\n }\n\n super(text, { ...(options ?? {}), tag: options?.tag ?? \"label\" });\n\n this._forId = forId;\n }\n\n /**\n * Returns the ID of the form element this label is associated with.\n *\n * @returns The value of the HTML `for` attribute.\n */\n public getForId() : string {\n return this._forId;\n }\n\n /**\n * Sets the for/htmlFor association and updates the DOM element.\n *\n * @param id - The ID of the form control this label should be associated with. Must be non-empty.\n *\n * @returns This component, for method chaining.\n */\n public setForId(id : string): this {\n if (!id) {\n throw new Error(\"Label forId must be non-empty.\");\n }\n\n this._forId = id;\n\n let element = this.getElement();\n if (!element) {\n return this;\n }\n\n DOM.sink.apply(element, { setAttr: { for: id } });\n\n return this;\n }\n\n /**\n * Renders the label element and sets its htmlFor attribute.\n *\n * @returns The created HTMLLabelElement with htmlFor initialised.\n */\n protected render(): Handle {\n let element = super.render();\n\n DOM.sink.apply(element, { setAttr: { for: this._forId } });\n\n return element;\n }\n}\n\nconst LabelCallable = callable(Label);\ntype LabelCallable = Label;\nexport {\n Label as _Label,\n LabelCallable as Label\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { AbstractInput, AbstractInputOptions } from \"~/component/input/AbstractInput.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { Util } from \"~/core/Util.js\";\nimport { UNBOUNDED } from \"~/primitive/Size.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport type { AxisOrientation } from \"~/primitive/Axis.js\";\n\n/**\n * Construction-time options for {@link Slider}.\n *\n * @category Components\n */\nexport interface SliderOptions extends AbstractInputOptions {\n value?: number;\n min?: number;\n max?: number;\n step?: number;\n largeStep?: number;\n orientation?: AxisOrientation;\n showTicks?: boolean;\n\n /** @deprecated use {@link SliderOptions.min} */\n minValue?: number;\n /** @deprecated use {@link SliderOptions.max} */\n maxValue?: number;\n /**\n * Construction-time listener bag — the declarative form of `on()`. Adds the\n * slider's `action` shorthand to the inherited `change` / `binding`.\n */\n listeners?: {\n action?: () => void;\n change?: (value: number) => void;\n binding?: () => void;\n };\n}\n\nconst TRACK_THICKNESS = 4;\nconst THUMB_SIZE = 16;\nconst DEFAULT_MIN = 0;\nconst DEFAULT_MAX = 100;\nconst DEFAULT_STEP = 1;\n\n/**\n * A custom-drawn range slider rendered as a focusable `<div>` with\n * `role=\"slider\"`.\n *\n * The track + thumb are real Components; drag is implemented via\n * `pointerdown` + `setPointerCapture` so the cursor can leave the track\n * during a drag without losing the stream. Keyboard navigation follows the\n * WAI-ARIA Authoring Practices slider model (Arrow / PageUp / PageDown /\n * Home / End).\n *\n * @category Components\n */\nclass Slider<TOptions extends SliderOptions = SliderOptions>\n extends AbstractInput<number, TOptions>\n{\n private _track: Component;\n private _activeTrack: Component;\n private _thumb: Component;\n private _draggingPointer: number | null = null;\n\n /**\n * Constructs a Slider.\n *\n * @param options - Optional construction-time options.\n */\n constructor(options?: TOptions) {\n super({ ...(options ?? {}) } as TOptions);\n\n this._track = new Component();\n this._track.setBackgroundColor(\"var(--ts-ui-slider-track-bg, rgb(220, 220, 220))\");\n this._track.setBorderRadius(\"999px\");\n // Pointer-events pass through to the slider root so `addListener`\n // matches by id on every press, and the root's cursor is what shows\n // on hover anywhere over the control.\n this._track.setPointerEvents(\"none\");\n\n this._activeTrack = new Component();\n this._activeTrack.setBackgroundColor(\"var(--ts-ui-slider-track-active-bg, rgb(30, 100, 200))\");\n this._activeTrack.setBorderRadius(\"999px\");\n this._activeTrack.setPointerEvents(\"none\");\n\n this._thumb = new Component();\n this._thumb.setBackgroundColor(\"var(--ts-ui-slider-thumb-bg, rgb(255, 255, 255))\");\n this._thumb.setBorderRadius(\"50%\");\n this._thumb.setBorder(\"1px solid var(--ts-ui-form-border, rgb(160, 160, 160))\");\n this._thumb.setShadow(\"0 1px 2px rgba(0, 0, 0, 0.25)\");\n this._thumb.setPreferredSize(THUMB_SIZE, THUMB_SIZE);\n this._thumb.setMaxSize(THUMB_SIZE, THUMB_SIZE);\n this._thumb.setPointerEvents(\"none\");\n\n this._track.addComponent(this._activeTrack);\n super.addComponent(this._track);\n super.addComponent(this._thumb);\n\n this.setPreferredSize(200, THUMB_SIZE);\n this.setMaxSize(UNBOUNDED, THUMB_SIZE);\n this.setOutline(\"none\");\n this.setCursor(\"pointer\");\n\n this.getAria().setRole(\"slider\");\n this.getAria().setTabIndex(0);\n this.getAria().setOrientation(\"horizontal\");\n this.getAria().setValueMin(DEFAULT_MIN);\n this.getAria().setValueMax(DEFAULT_MAX);\n this.getAria().setValueNow(DEFAULT_MIN);\n\n this.installInteraction();\n\n if (this._options.minValue !== undefined && this._options.min === undefined) {\n this._options.min = this._options.minValue;\n }\n\n if (this._options.maxValue !== undefined && this._options.max === undefined) {\n this._options.max = this._options.maxValue;\n }\n\n if (this._options.min !== undefined) {\n this.applyMin(this._options.min);\n }\n\n if (this._options.max !== undefined) {\n this.applyMax(this._options.max);\n }\n\n if (this._options.orientation !== undefined) {\n this.applyOrientation(this._options.orientation);\n }\n\n if (this._options.value !== undefined) {\n const snapped = this.snap(this._options.value);\n this._options.value = snapped;\n this.applyValue(snapped);\n } else {\n this.applyValue(this.getMin());\n }\n\n if (this._options.enabled !== undefined) {\n this.applyEnabled(this._options.enabled);\n }\n\n if (this._options.readOnly !== undefined) {\n this.applyReadOnly(this._options.readOnly);\n }\n }\n\n /**\n * Applies a {@link SliderOptions} bag. Inherited Component fields cascade\n * through `super.applyOptions`; slider-specific fields are stored pure on\n * `_options` so the constructor body can dispatch them after children\n * are built.\n *\n * @param options - The options bag carrying the values to apply.\n *\n * @returns This component, for method chaining.\n */\n protected applyOptions(options: TOptions): this {\n super.applyOptions(options);\n\n if (options.value !== undefined) this._options.value = options.value;\n if (options.min !== undefined) this._options.min = options.min;\n if (options.max !== undefined) this._options.max = options.max;\n if (options.minValue !== undefined) this._options.minValue = options.minValue;\n if (options.maxValue !== undefined) this._options.maxValue = options.maxValue;\n if (options.step !== undefined) this._options.step = options.step;\n if (options.largeStep !== undefined) this._options.largeStep = options.largeStep;\n if (options.orientation !== undefined) this._options.orientation = options.orientation;\n if (options.showTicks !== undefined) this._options.showTicks = options.showTicks;\n if (options.enabled !== undefined) this._options.enabled = options.enabled;\n if (options.readOnly !== undefined) this._options.readOnly = options.readOnly;\n\n return this;\n }\n\n /**\n * Returns the current slider value.\n *\n * @returns The current numeric value.\n */\n getValue(): number {\n return this._options.value ?? this.getMin();\n }\n\n /**\n * Sets the slider value, clamped to `[min, max]` and snapped to `step`.\n * Notifies change and binding listeners only on a real transition.\n *\n * @param value - The desired value.\n *\n * @returns This component, for method chaining.\n */\n setValue(value: number): this {\n const next = this.snap(value);\n if (next === this.getValue()) {\n return this;\n }\n\n this._options.value = next;\n this.applyValue(next);\n this.notifyChange(next);\n\n // Existing consumers wire to \"input\" via `on(\"action\", fn)`. Fire so\n // demos that read `slider.getValue()` from an `input` callback keep\n // working.\n Event.fireEvent(this, \"input\");\n\n return this;\n }\n\n /**\n * Returns the minimum value.\n *\n * @returns The current minimum.\n */\n getMin(): number {\n return this._options.min ?? DEFAULT_MIN;\n }\n\n /**\n * Sets the minimum value. The current value is reclamped if it falls\n * below the new minimum.\n *\n * @param value - The new minimum.\n *\n * @returns This component, for method chaining.\n */\n setMin(value: number): this {\n this._options.min = value;\n this.applyMin(value);\n this.applyValue(this.snap(this.getValue()));\n\n return this;\n }\n\n /**\n * Returns the maximum value.\n *\n * @returns The current maximum.\n */\n getMax(): number {\n return this._options.max ?? DEFAULT_MAX;\n }\n\n /**\n * Sets the maximum value. The current value is reclamped if it exceeds\n * the new maximum.\n *\n * @param value - The new maximum.\n *\n * @returns This component, for method chaining.\n */\n setMax(value: number): this {\n this._options.max = value;\n this.applyMax(value);\n this.applyValue(this.snap(this.getValue()));\n\n return this;\n }\n\n /**\n * Deprecated alias for {@link setMin}. Kept so existing demos compile;\n * remove in a follow-up cleanup once all consumers are migrated.\n *\n * @param value - The new minimum.\n *\n * @returns This component, for method chaining.\n *\n * @deprecated Use {@link setMin}.\n */\n setMinValue(value: number): this {\n return this.setMin(value);\n }\n\n /**\n * Deprecated alias for {@link getMin}.\n *\n * @returns The current minimum.\n *\n * @deprecated Use {@link getMin}.\n */\n getMinValue(): number {\n return this.getMin();\n }\n\n /**\n * Deprecated alias for {@link setMax}.\n *\n * @param value - The new maximum.\n *\n * @returns This component, for method chaining.\n *\n * @deprecated Use {@link setMax}.\n */\n setMaxValue(value: number): this {\n return this.setMax(value);\n }\n\n /**\n * Deprecated alias for {@link getMax}.\n *\n * @returns The current maximum.\n *\n * @deprecated Use {@link getMax}.\n */\n getMaxValue(): number {\n return this.getMax();\n }\n\n /**\n * Returns the step increment.\n *\n * @returns The current step.\n */\n getStep(): number {\n return this._options.step ?? DEFAULT_STEP;\n }\n\n /**\n * Sets the step increment used by keyboard navigation and value snapping.\n *\n * @param value - The new step.\n *\n * @returns This component, for method chaining.\n */\n setStep(value: number): this {\n this._options.step = value;\n\n return this;\n }\n\n /**\n * Returns the large-step increment used by PageUp / PageDown. Defaults to\n * `10 * step` when not explicitly set.\n *\n * @returns The current large-step.\n */\n getLargeStep(): number {\n return this._options.largeStep ?? this.getStep() * 10;\n }\n\n /**\n * Sets the PageUp / PageDown increment.\n *\n * @param value - The new large-step.\n *\n * @returns This component, for method chaining.\n */\n setLargeStep(value: number): this {\n this._options.largeStep = value;\n\n return this;\n }\n\n /**\n * Returns the current orientation.\n *\n * @returns `\"horizontal\"` or `\"vertical\"`.\n */\n getOrientation(): AxisOrientation {\n return this._options.orientation ?? \"horizontal\";\n }\n\n /**\n * Sets the slider orientation. Updates the ARIA attribute, the keyboard\n * model, and the track + thumb layout.\n *\n * @param orientation - `\"horizontal\"` or `\"vertical\"`.\n *\n * @returns This component, for method chaining.\n */\n setOrientation(orientation: AxisOrientation): this {\n this._options.orientation = orientation;\n this.applyOrientation(orientation);\n this.applyValue(this.getValue());\n\n return this;\n }\n\n /**\n * Returns whether tick marks are visible. (Not yet rendered visually —\n * the field is reserved for a follow-up.)\n *\n * @returns `true` when ticks should be shown.\n */\n isShowTicks(): boolean {\n return this._options.showTicks ?? false;\n }\n\n /**\n * Toggles tick mark visibility. Reserved option; no visual side effect\n * yet.\n *\n * @param value - `true` to show ticks.\n *\n * @returns This component, for method chaining.\n */\n setShowTicks(value: boolean): this {\n this._options.showTicks = value;\n\n return this;\n }\n\n /**\n * Registers a listener for one of this slider's events. `\"action\"` is a\n * typed semantic shorthand over {@link Event.addListener} for the\n * value-change event (the native `input`, fired on each drag step);\n * `\"change\"` and `\"binding\"` are the inherited {@link AbstractInput}\n * listener-bag events.\n *\n * @param event - The event name.\n * @param listener - The callback to invoke when the event fires.\n *\n * @returns This component, for method chaining.\n */\n on(event: \"action\", listener: Function): this;\n on(event: \"change\", listener: (value: number) => void): this;\n on(event: \"binding\", listener: () => void): this;\n on(event: \"action\" | \"change\" | \"binding\", listener: Function): this {\n if (event === \"action\") {\n Event.addListener(this, \"input\", listener);\n\n return this;\n }\n\n return super.on(event as \"change\", listener as (value: number) => void);\n }\n\n /**\n * Removes a previously registered listener. The exact callback\n * reference must match the one passed to {@link on}.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The callback to remove.\n *\n * @returns This component, for method chaining.\n */\n off(event: \"action\" | \"change\" | \"binding\", listener: Function): this {\n if (event === \"action\") {\n Event.removeListener(this, \"input\", listener);\n\n return this;\n }\n\n return super.off(event, listener);\n }\n\n /**\n * Returns a baseline near the bottom edge so the slider participates in\n * baseline alignment — sitting with its bottom roughly on the surrounding\n * text baseline — instead of being vertically centred in the row. The 2px\n * lift matches the other graphical controls so it doesn't sit below the\n * text descenders.\n *\n * @returns The preferred height minus 2, or `null` before a size is set.\n */\n getBaseline(): number | null {\n const size = this.getPreferredSize();\n\n return size ? size.height - 2 : null;\n }\n\n /**\n * Lays out the track, active fill, and thumb for the current size.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n const inner = this.getInnerSize();\n if (!inner) {\n return this;\n }\n\n const horizontal = this.getOrientation() === \"horizontal\";\n\n // `Component.setWidth` / `setHeight` clamp to the component's own\n // maxSize, so `inner` is already bounded by our `setMaxSize(_,\n // THUMB_SIZE)` (or `setMaxSize(THUMB_SIZE, _)` when vertical) — no\n // extra cross-axis clamp is needed here.\n const innerWidth = inner.width;\n const innerHeight = inner.height;\n const min = this.getMin();\n const max = this.getMax();\n const range = max - min;\n const fraction = range > 0 ? (this.getValue() - min) / range : 0;\n\n // doLayout only setX/setY/setSize on the children; their preferredSize\n // is a hint for parent layouts and never reaches their own DOM. Size\n // the thumb explicitly so it renders at THUMB_SIZE rather than\n // collapsing to its 2 × 2 border box.\n if (horizontal) {\n const trackTop = Math.round((innerHeight - TRACK_THICKNESS) / 2);\n this._track.setX(0);\n this._track.setY(trackTop);\n this._track.setSize({ width: innerWidth, height: TRACK_THICKNESS });\n\n const activeWidth = Math.round(innerWidth * fraction);\n this._activeTrack.setX(0);\n this._activeTrack.setY(0);\n this._activeTrack.setSize({ width: activeWidth, height: TRACK_THICKNESS });\n\n const thumbX = Math.round((innerWidth - THUMB_SIZE) * fraction);\n const thumbY = Math.round((innerHeight - THUMB_SIZE) / 2);\n this._thumb.setSize({ width: THUMB_SIZE, height: THUMB_SIZE });\n this._thumb.setX(thumbX);\n this._thumb.setY(thumbY);\n } else {\n const trackLeft = Math.round((innerWidth - TRACK_THICKNESS) / 2);\n this._track.setX(trackLeft);\n this._track.setY(0);\n this._track.setSize({ width: TRACK_THICKNESS, height: innerHeight });\n\n // Vertical slider: zero is at the bottom by convention.\n const activeHeight = Math.round(innerHeight * fraction);\n this._activeTrack.setX(0);\n this._activeTrack.setY(innerHeight - activeHeight);\n this._activeTrack.setSize({ width: TRACK_THICKNESS, height: activeHeight });\n\n const thumbX = Math.round((innerWidth - THUMB_SIZE) / 2);\n const thumbY = Math.round((innerHeight - THUMB_SIZE) * (1 - fraction));\n this._thumb.setSize({ width: THUMB_SIZE, height: THUMB_SIZE });\n this._thumb.setX(thumbX);\n this._thumb.setY(thumbY);\n }\n\n return this;\n }\n\n /**\n * Wires pointer drag (with setPointerCapture) and keyboard navigation.\n */\n private installInteraction(): void {\n // `pointer-events: none` on the inner visual children forwards pointer\n // hits to the root, so the exact-target `addListener` matches the\n // slider's id. `setPointerCapture` below then routes the move / up /\n // cancel stream to the same root element.\n Event.addListener(this, \"pointerdown\", (e: PointerEvent) => {\n if (!this.isEnabled() || this.isReadOnly()) {\n return;\n }\n\n e.preventDefault();\n this.focus();\n\n const element = this.getElement();\n if (element) {\n DOM.sink.setPointerCapture(element, e.pointerId);\n this._draggingPointer = e.pointerId;\n }\n\n this.setValue(this.valueAtPointer(e));\n });\n\n Event.addListener(this, \"pointermove\", (e: PointerEvent) => {\n if (this._draggingPointer !== e.pointerId) {\n return;\n }\n\n this.setValue(this.valueAtPointer(e));\n });\n\n const release = (e: PointerEvent): void => {\n if (this._draggingPointer !== e.pointerId) {\n return;\n }\n\n const element = this.getElement();\n if (element && DOM.source.hasPointerCapture(element, e.pointerId)) {\n DOM.sink.releasePointerCapture(element, e.pointerId);\n }\n\n this._draggingPointer = null;\n };\n\n Event.addListener(this, \"pointerup\", release);\n Event.addListener(this, \"pointercancel\", release);\n // Browser releases pointer capture on alt-tab / focus loss. Clear our\n // mirror so the next pointerdown starts clean and there's no stuck-drag.\n Event.addListener(this, \"lostpointercapture\", release);\n\n Event.addListener(this, \"keydown\", (e: KeyboardEvent) => {\n if (!this.isEnabled() || this.isReadOnly()) {\n return;\n }\n\n const step = this.getStep();\n const largeStep = this.getLargeStep();\n const min = this.getMin();\n const max = this.getMax();\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowUp\":\n e.preventDefault();\n this.setValue(this.getValue() + step);\n break;\n case \"ArrowLeft\":\n case \"ArrowDown\":\n e.preventDefault();\n this.setValue(this.getValue() - step);\n break;\n case \"PageUp\":\n e.preventDefault();\n this.setValue(this.getValue() + largeStep);\n break;\n case \"PageDown\":\n e.preventDefault();\n this.setValue(this.getValue() - largeStep);\n break;\n case \"Home\":\n e.preventDefault();\n this.setValue(min);\n break;\n case \"End\":\n e.preventDefault();\n this.setValue(max);\n break;\n }\n });\n }\n\n /**\n * Converts a pointer position into the corresponding slider value.\n */\n private valueAtPointer(e: PointerEvent): number {\n const element = this.getElement();\n if (!element) {\n return this.getValue();\n }\n\n const rect = DOM.source.getViewportRect(this);\n const horizontal = this.getOrientation() === \"horizontal\";\n const fraction = horizontal\n ? (rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0)\n : (rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0);\n\n const clamped = Util.clamp(fraction, 0, 1);\n const min = this.getMin();\n const max = this.getMax();\n\n return min + (max - min) * clamped;\n }\n\n /**\n * Clamps `value` to `[min, max]` and snaps to the nearest step boundary.\n */\n private snap(value: number): number {\n const min = this.getMin();\n const max = this.getMax();\n const step = this.getStep();\n\n const clamped = Util.clamp(value, min, max);\n\n if (step <= 0) {\n return clamped;\n }\n\n const snapped = min + Math.round((clamped - min) / step) * step;\n\n return Util.clamp(snapped, min, max);\n }\n\n /**\n * Updates the value-related ARIA state and re-runs layout to move the\n * thumb.\n */\n private applyValue(value: number): void {\n this._options.value = value;\n this.getAria().setValueNow(value);\n this.scheduleLayout();\n }\n\n /**\n * Pushes the new minimum into the ARIA cache.\n */\n private applyMin(value: number): void {\n this.getAria().setValueMin(value);\n }\n\n /**\n * Pushes the new maximum into the ARIA cache.\n */\n private applyMax(value: number): void {\n this.getAria().setValueMax(value);\n }\n\n /**\n * Reflects the orientation in ARIA, swaps the preferred size between\n * landscape and portrait, and forces a layout.\n */\n private applyOrientation(orientation: AxisOrientation): void {\n this.getAria().setOrientation(orientation);\n\n if (orientation === \"horizontal\") {\n this.setPreferredSize(200, THUMB_SIZE);\n this.setMaxSize(UNBOUNDED, THUMB_SIZE);\n } else {\n this.setPreferredSize(THUMB_SIZE, 200);\n this.setMaxSize(THUMB_SIZE, UNBOUNDED);\n }\n\n this.scheduleLayout();\n }\n\n /**\n * Reflects the enabled flag in the ARIA tree and tabindex.\n */\n protected applyEnabled(value: boolean): void {\n this.getAria().setDisabled(!value);\n this.getAria().setTabIndex(value ? 0 : -1);\n this.setCursor(value ? \"pointer\" : \"default\");\n }\n\n /**\n * Reflects the read-only flag in the ARIA tree.\n */\n protected applyReadOnly(value: boolean): void {\n this.getAria().setReadOnly(value);\n }\n}\n\nconst SliderCallable = callable(Slider);\ntype SliderCallable<TOptions extends SliderOptions = SliderOptions> = Slider<TOptions>;\nexport {\n Slider as _Slider,\n SliderCallable as Slider\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{f as e,t}from"./Component-Bs6TvaGZ.js";import{t as n}from"./LayoutConstraints-CHI2lhPd.js";var r=e(class Spacer extends t{_flex=!1;_flexWeight=1;constructor(e,t){super();let n;n=typeof e==`number`?{width:e,height:t??e}:e??{},this.setBackgroundColor(`transparent`),this.setPointerEvents(`none`),this.getAria().setHidden(!0),this.applyOptions(n)}static flex(e=1){return new Spacer({flex:!0,flexWeight:e})}isFlex(){return this._flex}setFlex(e){return this._flex===e?this:(this._flex=e,this.syncFlexConstraints(),this)}getFlexWeight(){return this._flexWeight}setFlexWeight(e){return this._flexWeight===e?this:(this._flexWeight=e,this._flex&&this.syncFlexConstraints(),this)}syncFlexConstraints(){let e=this.getParentComponent();if(!e)return;let t=e.getLayoutManager();if(t)if(this._flex){let e=t.getLayoutConstraints(this)??new n;e.weight=this._flexWeight,t.setLayoutConstraints(this,e)}else{let e=t.getLayoutConstraints(this);e&&e.weight!==void 0&&(e.weight=void 0,t.setLayoutConstraints(this,e))}}applyOptions(e){if(super.applyOptions(e),e.width!==void 0||e.height!==void 0){let t=e.width??0,n=e.height??t;this.setPreferredSize(t,n)}return e.flexWeight!==void 0&&this.setFlexWeight(e.flexWeight),e.flex!==void 0&&this.setFlex(e.flex),this}init(e){return super.init(e),this._flex&&this.syncFlexConstraints(),this}});export{r as t};
|
|
2
|
-
//# sourceMappingURL=Spacer-BqiPiCqz.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Spacer-BqiPiCqz.js","names":[],"sources":["../../src/typescript/lib/component/container/Spacer.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { LayoutConstraints } from \"~/layout/LayoutConstraints.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Spacer}.\n *\n * @category Components\n */\nexport interface SpacerOptions extends ComponentOptions {\n /** Fixed preferred width in pixels. Defaults to `0`. */\n width?: number;\n\n /** Fixed preferred height in pixels. Defaults to `width` (or `0`). */\n height?: number;\n\n /**\n * When `true`, the spacer absorbs remaining row/column space inside an\n * [`HBox`](/api/layout/classes/HBox) or [`VBox`](/api/layout/classes/VBox)\n * parent via the `weight` layout constraint. Defaults to `false`.\n */\n flex?: boolean;\n\n /**\n * Flex weight, used when `flex` is `true`. Defaults to `1`. Multiple flex\n * spacers in the same row/column share the leftover space proportionally\n * to their weights.\n */\n flexWeight?: number;\n}\n\n/**\n * A deliberately invisible leaf {@link Component} whose only job is to take up\n * space inside a layout. Two modes:\n *\n * - **Fixed** — advertises a hard `(width, height)` preferred size via the\n * inherited `setPreferredSize`. Use `new Spacer(16)` for a 16-pixel square\n * gap, or `new Spacer(16, 0)` for a 16-pixel horizontal gap.\n * - **Flex** — absorbs the row/column's leftover space by writing a `weight`\n * entry into the parent's [`LayoutConstraints`](/api/layout/classes/LayoutConstraints).\n * Meaningful only inside an [`HBox`](/api/layout/classes/HBox) or\n * [`VBox`](/api/layout/classes/VBox); other layout managers ignore `weight`\n * and the spacer falls back to its `(0, 0)` preferred size.\n *\n * The element carries `aria-hidden=\"true\"`, a transparent background, and\n * `pointer-events: none` so it never intercepts hover or click events and\n * never appears in the accessibility tree.\n *\n * @example\n * ```typescript\n * new HBox().getContainer()\n * .add(Button(\"A\"), Spacer(16), Button(\"B\"), Spacer.flex(), Button(\"C\"));\n * ```\n *\n * @category Components\n */\nclass Spacer extends Component<SpacerOptions> {\n\n private _flex: boolean = false;\n private _flexWeight: number = 1;\n\n /**\n * Constructs a fixed-size spacer.\n *\n * @param width - Preferred width in pixels.\n * @param height - Optional. Preferred height in pixels. Defaults to `width`.\n */\n constructor(width: number, height?: number);\n\n /**\n * Constructs a spacer from an options bag — use for the flex variant.\n *\n * @param options - Optional. {@link SpacerOptions} bag.\n */\n constructor(options?: SpacerOptions);\n\n constructor(arg1?: number | SpacerOptions, arg2?: number) {\n super();\n\n let opts: SpacerOptions;\n if (typeof arg1 === \"number\") {\n opts = { width: arg1, height: arg2 ?? arg1 };\n } else {\n opts = arg1 ?? {};\n }\n\n // Invisible by design — no chrome, no hit-testing, no a11y noise.\n this.setBackgroundColor(\"transparent\");\n this.setPointerEvents(\"none\");\n this.getAria().setHidden(true);\n\n this.applyOptions(opts);\n }\n\n /**\n * Factory for the absorb-rest variant. Equivalent to\n * `new Spacer({ flex: true, flexWeight: weight })`.\n *\n * @param weight - Optional. Flex weight; defaults to `1`.\n *\n * @returns A new flex `Spacer`.\n */\n static flex(weight: number = 1): Spacer {\n return new Spacer({ flex: true, flexWeight: weight });\n }\n\n /**\n * Returns whether this spacer is in flex (absorb-rest) mode.\n *\n * @returns The cached flex flag.\n */\n isFlex(): boolean {\n return this._flex;\n }\n\n /**\n * Toggles flex mode. When a parent is already attached, the stored\n * [`LayoutConstraints`](/api/layout/classes/LayoutConstraints) on the\n * parent's layout manager are updated immediately.\n *\n * @param value - `true` to enable flex (weight-based) sizing.\n *\n * @returns This component, for method chaining.\n */\n setFlex(value: boolean): this {\n if (this._flex === value) {\n return this;\n }\n\n this._flex = value;\n\n this.syncFlexConstraints();\n\n return this;\n }\n\n /**\n * Returns the flex weight used in flex mode.\n *\n * @returns The cached flex weight (defaults to `1`).\n */\n getFlexWeight(): number {\n return this._flexWeight;\n }\n\n /**\n * Sets the flex weight. Only meaningful when `isFlex()` is `true`.\n * Multiple flex spacers in the same row/column share leftover space\n * proportionally to their weights.\n *\n * @param weight - The new flex weight.\n *\n * @returns This component, for method chaining.\n */\n setFlexWeight(weight: number): this {\n if (this._flexWeight === weight) {\n return this;\n }\n\n this._flexWeight = weight;\n\n if (this._flex) {\n this.syncFlexConstraints();\n }\n\n return this;\n }\n\n /**\n * Writes `_flex` / `_flexWeight` into the parent's\n * [`LayoutConstraints`](/api/layout/classes/LayoutConstraints) map.\n *\n * @remarks Silently no-ops when no parent or no layout manager is\n * attached; `init()` re-runs the sync once the spacer is rendered as a\n * child of a parent that owns a layout manager.\n */\n private syncFlexConstraints(): void {\n const parent = this.getParentComponent();\n if (!parent) {\n return;\n }\n\n const lm = parent.getLayoutManager();\n if (!lm) {\n return;\n }\n\n if (this._flex) {\n const existing = lm.getLayoutConstraints(this);\n const constraints = existing ?? new LayoutConstraints();\n constraints.weight = this._flexWeight;\n lm.setLayoutConstraints(this, constraints);\n } else {\n const existing = lm.getLayoutConstraints(this);\n if (existing && existing.weight !== undefined) {\n existing.weight = undefined;\n lm.setLayoutConstraints(this, existing);\n }\n }\n }\n\n /**\n * Applies a {@link SpacerOptions} bag. The `width` / `height` keys are\n * Spacer-specific sugar over the inherited `preferredSize` option; both\n * route through `setPreferredSize`.\n *\n * @param options - The options to apply.\n *\n * @returns This component, for method chaining.\n */\n protected applyOptions(options: SpacerOptions): this {\n super.applyOptions(options);\n\n if (options.width !== undefined || options.height !== undefined) {\n const w = options.width ?? 0;\n const h = options.height ?? w;\n this.setPreferredSize(w, h);\n }\n\n if (options.flexWeight !== undefined) {\n this.setFlexWeight(options.flexWeight);\n }\n\n if (options.flex !== undefined) {\n this.setFlex(options.flex);\n }\n\n return this;\n }\n\n /**\n * Initialises the element. Overridden so a flex spacer installs its\n * `weight` constraint on the parent's layout manager the first time it\n * is realised in the DOM — the parent has set `_parent` and rendered\n * the child by this point, so the layout manager is reachable.\n *\n * @param element - Optional. The element being initialised.\n *\n * @returns This component, for method chaining.\n */\n protected init(element?: Handle): this {\n super.init(element);\n\n if (this._flex) {\n this.syncFlexConstraints();\n }\n\n return this;\n }\n}\n\nconst SpacerCallable = callable(Spacer);\ntype SpacerCallable = Spacer;\nexport {\n Spacer as _Spacer,\n SpacerCallable as Spacer\n};\n"],"mappings":"kGA8PA,IAAM,EAAiB,EAAS,MAnM1B,eAAe,CAAyB,CAE1C,MAA+B,GAC/B,YAA+B,EAiB/B,YAAY,EAA+B,EAAe,CACtD,MAAM,EAEN,IAAI,EACJ,AAGI,EAHA,OAAO,GAAS,SACT,CAAE,MAAO,EAAM,OAAQ,GAAQ,CAAK,EAEpC,GAAQ,CAAC,EAIpB,KAAK,mBAAmB,aAAa,EACrC,KAAK,iBAAiB,MAAM,EAC5B,KAAK,QAAQ,CAAC,CAAC,UAAU,EAAI,EAE7B,KAAK,aAAa,CAAI,CAC1B,CAUA,OAAO,KAAK,EAAiB,EAAW,CACpC,OAAO,IAAI,OAAO,CAAE,KAAM,GAAM,WAAY,CAAO,CAAC,CACxD,CAOA,QAAkB,CACd,OAAO,KAAK,KAChB,CAWA,QAAQ,EAAsB,CAS1B,OARI,KAAK,QAAU,EACR,MAGX,KAAK,MAAQ,EAEb,KAAK,oBAAoB,EAElB,KACX,CAOA,eAAwB,CACpB,OAAO,KAAK,WAChB,CAWA,cAAc,EAAsB,CAWhC,OAVI,KAAK,cAAgB,EACd,MAGX,KAAK,YAAc,EAEf,KAAK,OACL,KAAK,oBAAoB,EAGtB,KACX,CAUA,qBAAoC,CAChC,IAAM,EAAS,KAAK,mBAAmB,EACvC,GAAI,CAAC,EACD,OAGJ,IAAM,EAAK,EAAO,iBAAiB,EAC9B,KAIL,GAAI,KAAK,MAAO,CAEZ,IAAM,EADW,EAAG,qBAAqB,IACrB,GAAY,IAAI,EACpC,EAAY,OAAS,KAAK,YAC1B,EAAG,qBAAqB,KAAM,CAAW,CAC7C,KAAO,CACH,IAAM,EAAW,EAAG,qBAAqB,IAAI,EACzC,GAAY,EAAS,SAAW,IAAA,KAChC,EAAS,OAAS,IAAA,GAClB,EAAG,qBAAqB,KAAM,CAAQ,EAE9C,CACJ,CAWA,aAAuB,EAA8B,CAGjD,GAFA,MAAM,aAAa,CAAO,EAEtB,EAAQ,QAAU,IAAA,IAAa,EAAQ,SAAW,IAAA,GAAW,CAC7D,IAAM,EAAI,EAAQ,OAAU,EACtB,EAAI,EAAQ,QAAU,EAC5B,KAAK,iBAAiB,EAAG,CAAC,CAC9B,CAUA,OARI,EAAQ,aAAe,IAAA,IACvB,KAAK,cAAc,EAAQ,UAAU,EAGrC,EAAQ,OAAS,IAAA,IACjB,KAAK,QAAQ,EAAQ,IAAI,EAGtB,IACX,CAYA,KAAe,EAAwB,CAOnC,OANA,MAAM,KAAK,CAAO,EAEd,KAAK,OACL,KAAK,oBAAoB,EAGtB,IACX,CACJ,CAEsC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as e,n as t,u as n}from"./Position-B-WfZYAJ.js";import{f as r,n as i,y as a}from"./Component-BR2f0Itb.js";import{t as o}from"./Glyph-WUqTF_Z9.js";import{t as s}from"./Button-DEUtBqK4.js";import{xmark as c}from"./glyphs/solid/xmark.es.js";var ToggleButton=class extends s{get selectedStyleRule(){return this._selectedStyleRule??=this.createStyleRule(`.selected:not(:hover)`)}constructor(e,t){super(e),this.selectedStyleRule.set(`boxShadow`,`var(--ts-ui-toggle-selected-shadow, 2px 2px 1px inset grey)`),this.selectedStyleRule.set(`backgroundColor`,`var(--ts-ui-toggle-selected-bg, rgb(200, 200, 200))`),this.selectedStyleRule.set(`backgroundImage`,`var(--ts-ui-toggle-selected-bg, none)`),a.addListener(this,`click`,()=>this.onAction()),t&&this.applyOptions(t),this.applyListeners(t?.listeners)}applyOptions(e){return super.applyOptions(e),e.selected!==void 0&&this.setSelected(e.selected),this.isFlat()&&(this.setSelectedShadow(`var(--ts-ui-button-flat-pressed-shadow, inset 1px 1px 3px rgba(0, 0, 0, 0.25))`),this.setSelectedBackgroundColor(`var(--ts-ui-button-flat-pressed-bg, rgba(0, 0, 0, 0.10))`)),this}on(e,t){return a.addListener(this,`change`,t),this}off(e,t){return a.removeListener(this,`change`,t),this}isSelected(){return this._options.selected??!1}setSelected(e){this._options.selected=e,this.getAria().setPressed(e);let t=this.getElement();return t&&n.sink.apply(t,{toggleClass:{selected:e}}),this}setSelectedBackgroundColor(e){return this.selectedStyleRule.set(`backgroundColor`,e),this}setSelectedBackgroundImage(e){return this.selectedStyleRule.set(`backgroundImage`,e),this}setSelectedShadow(e){return this.selectedStyleRule.set(`boxShadow`,e),this}setSelectedBorder(t){let n=typeof t==`string`?{border:t}:t;return this.selectedStyleRule.setMany(e(n)),this}setFlat(e){return super.setFlat(e),this.isFlat()?(this.setSelectedShadow(`var(--ts-ui-button-flat-pressed-shadow, inset 1px 1px 3px rgba(0, 0, 0, 0.25))`),this.setSelectedBackgroundColor(`var(--ts-ui-button-flat-pressed-bg, rgba(0, 0, 0, 0.10))`)):(this.setSelectedShadow(`var(--ts-ui-toggle-selected-shadow, 2px 2px 1px inset grey)`),this.setSelectedBackgroundColor(`var(--ts-ui-toggle-selected-bg, rgb(200, 200, 200))`)),this}onAction(){this.setSelected(!this.isSelected()),a.fireEvent(this,`change`)}render(){let e=super.render();return n.sink.apply(e,{toggleClass:{selected:this.isSelected()}}),e}},l=r(ToggleButton);o.register(c);var u={preferredSize:{width:16,height:16},insets:new t(0,0,0,0),foregroundColor:`var(--ts-ui-close-button-fg, #555)`},TabCloseButton=class extends s{constructor(e){super(void 0,e,{...u,glyph:`xmark`})}},d=r(TabCloseButton),TabButton=class extends l{_closeable=!1;_closeButton=null;constructor(e,t){super(e),this._closeable=t?.closeable??!1,t&&this.applyOptions(t),this.applyTabStyling(),t?.glyph!==void 0&&this.setGlyph(t.glyph),this._closeable&&this.buildCloseButton(),this.applyListeners(t?.listeners)}applyTabStyling(){this.setBackgroundColor(`var(--ts-ui-tab-button-bg, #b8b8c3)`),this.setBackgroundImage(`var(--ts-ui-tab-button-bg, #b8b8c3)`),this.setBorder({borderTop:`var(--ts-ui-tab-button-border-top, var(--ts-ui-tab-button-border, none))`,borderRight:`var(--ts-ui-tab-button-border-right, var(--ts-ui-tab-button-border, none))`,borderBottom:`var(--ts-ui-tab-button-border-bottom, var(--ts-ui-tab-button-border, none))`,borderLeft:`var(--ts-ui-tab-button-border-left, var(--ts-ui-tab-button-border, none))`}),this.clearBorderRadius(),this.clearShadow(),this.setHoverBackgroundColor(`var(--ts-ui-tab-button-hover-bg, #c4c4cf)`),this.setHoverBackgroundImage(`var(--ts-ui-tab-button-hover-bg, #c4c4cf)`),this.setHoverShadow(`none`),this.setHoverBorder({borderTop:`var(--ts-ui-tab-button-hover-border-top, var(--ts-ui-tab-button-hover-border, none))`,borderRight:`var(--ts-ui-tab-button-hover-border-right, var(--ts-ui-tab-button-hover-border, none))`,borderBottom:`var(--ts-ui-tab-button-hover-border-bottom, var(--ts-ui-tab-button-hover-border, none))`,borderLeft:`var(--ts-ui-tab-button-hover-border-left, var(--ts-ui-tab-button-hover-border, none))`}),this.setSelectedBackgroundColor(`var(--ts-ui-tab-button-selected-bg, rgb(255, 255, 255))`),this.setSelectedBackgroundImage(`var(--ts-ui-tab-button-selected-bg, rgb(255, 255, 255))`),this.setSelectedShadow(`none`),this.setSelectedBorder({borderTop:`var(--ts-ui-tab-button-selected-border-top, var(--ts-ui-tab-button-selected-border, none))`,borderRight:`var(--ts-ui-tab-button-selected-border-right, var(--ts-ui-tab-button-selected-border, none))`,borderBottom:`var(--ts-ui-tab-button-selected-border-bottom, var(--ts-ui-tab-button-selected-border, none))`,borderLeft:`var(--ts-ui-tab-button-selected-border-left, var(--ts-ui-tab-button-selected-border, none))`})}buildCloseButton(){let e=new d;e.setBackgroundColor(`transparent`),e.setBackgroundImage(`none`),e.setHoverBackgroundColor(`var(--ts-ui-tab-close-hover-bg, rgba(0, 0, 0, 0.12))`),e.setHoverBackgroundImage(`none`),e.setHoverShadow(`none`),e.setBorderRadius(`3px`),e.clearBorder(),e.clearShadow(),e.setZIndex(1),e.pinGlyphSize(i.getResolvedScale().tabCloseGlyph),n.sink.appendChild(this.getElement(!0),e.getElement(!0)),this._closeButton=e}getCloseButton(){return this._closeButton}isCloseable(){return this._closeable}},f=r(TabButton);export{d as n,l as r,f as t};
|
|
2
|
-
//# sourceMappingURL=TabButton-pZKFYg7b.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TabButton-pZKFYg7b.js","names":[],"sources":["../../src/typescript/lib/component/button/ToggleButton.ts","../../src/typescript/lib/component/button/TabCloseButton.ts","../../src/typescript/lib/component/button/TabButton.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from \"~/core/DOM.js\";\nimport { StyleRule } from \"~/core/StyleTarget.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { BorderOptions, borderToStyle } from \"~/primitive/Border.js\";\nimport { Button, ButtonOptions, ClickListener } from \"~/component/button/Button.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link ToggleButton}.\n *\n * @category Components\n */\nexport interface ToggleButtonOptions extends ButtonOptions {\n selected?: boolean;\n}\n\n/**\n * A toggle button component that switches between selected and unselected states on each click.\n *\n * Maintains a separate CSS rule for the `.selected` class to allow independent styling of\n * the active state, and fires a 'change' event whenever the selection state changes.\n *\n * @category Components\n */\nclass ToggleButton extends Button<ToggleButtonOptions> {\n\n // Lazy `.selected` rule. The slot is a fast-path cache for the wrapper\n // returned by Component's `createStyleRule` builder, which dedupes by\n // selector suffix — see Button's `_pressedStyleRule` for the full\n // explanation.\n private declare _selectedStyleRule?: StyleRule;\n private get selectedStyleRule(): StyleRule {\n return this._selectedStyleRule ??= this.createStyleRule(\".selected:not(:hover)\");\n }\n\n constructor(text: string, options?: ToggleButtonOptions) {\n // Button is a children-build class: it builds its inner text/HBox row\n // in its constructor body. We forward the positional `text` to super\n // (no options), queue the selected-state styles into the lazy rule,\n // then dispatch the consumer options through `applyOptions` at the\n // tail so Button's own option-backed setters run after children exist.\n super(text);\n\n this.selectedStyleRule.set(\"boxShadow\", \"var(--ts-ui-toggle-selected-shadow, 2px 2px 1px inset grey)\");\n this.selectedStyleRule.set(\"backgroundColor\", \"var(--ts-ui-toggle-selected-bg, rgb(200, 200, 200))\");\n this.selectedStyleRule.set(\"backgroundImage\", \"var(--ts-ui-toggle-selected-bg, none)\");\n\n Event.addListener(this, \"click\", () => this.onAction());\n\n if (options) {\n this.applyOptions(options);\n }\n\n // Button's constructor skipped the listener bag (it wires only a plain\n // Button); wire it here, after super() and applyOptions, as the leaf.\n this.applyListeners(options?.listeners);\n }\n\n /**\n * Applies a {@link ToggleButtonOptions} bag, dispatching the toggle's\n * `selected` state after inherited Button/Component fields.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: ToggleButtonOptions): this {\n super.applyOptions(options);\n\n if (options.selected !== undefined) {\n this.setSelected(options.selected);\n }\n\n // Button's flat branch runs in `applyChromeOptions` and re-points only\n // Button's own hover/pressed rules — it never touches this toggle's\n // `.selected` rule. Re-point it here so a `new ToggleButton(text,\n // { flat: true })` reads depressed when selected, mirroring `setFlat`.\n if (this.isFlat()) {\n this.setSelectedShadow(\"var(--ts-ui-button-flat-pressed-shadow, inset 1px 1px 3px rgba(0, 0, 0, 0.25))\");\n this.setSelectedBackgroundColor(\"var(--ts-ui-button-flat-pressed-bg, rgba(0, 0, 0, 0.10))\");\n }\n\n return this;\n }\n\n /**\n * Registers a listener for this toggle button's `\"action\"` event — fired\n * when the toggle state changes. Overrides the inherited\n * [`Button`](/api/component/button/classes/Button) `on` so `\"action\"`\n * routes to the DOM `\"change\"` event (the toggle) rather than the base\n * `\"click\"`. A typed semantic shorthand over {@link Event.addListener}.\n *\n * @param event - The event name. Only `\"action\"` is accepted.\n * @param listener - The callback to invoke when the toggle state changes.\n *\n * @returns This button, for method chaining.\n */\n on(event: \"action\", listener: ClickListener): this;\n on(_event: \"action\", listener: ClickListener): this {\n Event.addListener(this, \"change\", listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered `\"action\"` listener. The exact\n * callback reference must match the one passed to {@link on}.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The callback to remove.\n *\n * @returns This button, for method chaining.\n */\n off(event: \"action\", listener: ClickListener): this;\n off(_event: \"action\", listener: ClickListener): this {\n Event.removeListener(this, \"change\", listener);\n\n return this;\n }\n\n /**\n * Returns whether the toggle button is currently in the selected state.\n *\n * @returns True if the button is currently selected.\n */\n isSelected(): boolean {\n return this._options.selected ?? false;\n }\n\n /**\n * Sets the selected state, toggles the 'selected' CSS class, and updates `aria-pressed`.\n *\n * @param value - True to select the button, false to deselect it.\n */\n setSelected(value: boolean) : this {\n this._options.selected = value;\n\n this.getAria().setPressed(value);\n\n let element = this.getElement();\n if (element) {\n DOM.sink.apply(element, { toggleClass: { selected: value } });\n }\n\n return this;\n }\n\n /**\n * Sets the background color for the `.selected` CSS rule, overriding the\n * default `--ts-ui-toggle-selected-bg` token for this instance.\n *\n * @param backgroundColor - A CSS color string.\n *\n * @returns This button, for method chaining.\n */\n setSelectedBackgroundColor(backgroundColor: string): this {\n this.selectedStyleRule.set(\"backgroundColor\", backgroundColor);\n\n return this;\n }\n\n /**\n * Sets the background image for the `.selected` CSS rule. Pairs with\n * {@link setSelectedBackgroundColor} so a plain colour drops out (invalid\n * as an image) and a gradient wins, matching the framework's background\n * colour/image auto-routing.\n *\n * @param backgroundImage - A CSS background-image string.\n *\n * @returns This button, for method chaining.\n */\n setSelectedBackgroundImage(backgroundImage: string): this {\n this.selectedStyleRule.set(\"backgroundImage\", backgroundImage);\n\n return this;\n }\n\n /**\n * Sets the box-shadow for the `.selected` CSS rule, overriding the default\n * `--ts-ui-toggle-selected-shadow` token for this instance.\n *\n * @param shadow - A CSS box-shadow string (e.g. `\"none\"`).\n *\n * @returns This button, for method chaining.\n */\n setSelectedShadow(shadow: string): this {\n this.selectedStyleRule.set(\"boxShadow\", shadow);\n\n return this;\n }\n\n /**\n * Sets the border for the `.selected` CSS rule, overriding the default\n * selected-state border for this instance. Accepts either a {@link BorderOptions}\n * bag or a CSS `border` shorthand string (sugar for `{ border: <string> }`,\n * e.g. `\"1px solid rgb(...)\"` or `\"none\"`).\n *\n * @param options - Border configuration, or a CSS `border` shorthand value.\n *\n * @returns This button, for method chaining.\n */\n setSelectedBorder(options: BorderOptions | string): this {\n const border = typeof options === \"string\" ? { border: options } : options;\n this.selectedStyleRule.setMany(borderToStyle(border));\n\n return this;\n }\n\n /**\n * Toggles the flat appearance, then re-points the `.selected:not(:hover)`\n * rule so a toggled-on flat button reads as depressed with the same sunken\n * treatment Button's flat `:active` state uses. Flattening points the\n * selected shadow/background at the `--ts-ui-button-flat-pressed-*` tokens;\n * un-flattening restores the default `--ts-ui-toggle-selected-*` tokens.\n *\n * @param value - The new flat state.\n *\n * @returns This button, for method chaining.\n */\n setFlat(value: boolean): this {\n super.setFlat(value);\n\n // Read the resolved state, not the requested `value`: `super.setFlat`\n // can refuse the flip (chromeless wins) or no-op on an unchanged value,\n // and the selected rule must track whatever flat state actually holds.\n if (this.isFlat()) {\n this.setSelectedShadow(\"var(--ts-ui-button-flat-pressed-shadow, inset 1px 1px 3px rgba(0, 0, 0, 0.25))\");\n this.setSelectedBackgroundColor(\"var(--ts-ui-button-flat-pressed-bg, rgba(0, 0, 0, 0.10))\");\n } else {\n this.setSelectedShadow(\"var(--ts-ui-toggle-selected-shadow, 2px 2px 1px inset grey)\");\n this.setSelectedBackgroundColor(\"var(--ts-ui-toggle-selected-bg, rgb(200, 200, 200))\");\n }\n\n return this;\n }\n\n /**\n * Toggles the selected state and fires a 'change' event when the button is clicked.\n */\n private onAction() {\n this.setSelected(!this.isSelected());\n\n Event.fireEvent(this, \"change\");\n }\n\n /**\n * Renders the button element and applies the 'selected' class if currently selected.\n *\n * @returns The created button element with the 'selected' class applied if appropriate.\n */\n render() {\n let element = super.render();\n DOM.sink.apply(element, { toggleClass: { selected: this.isSelected() } });\n return element;\n }\n}\n\nconst ToggleButtonCallable = callable(ToggleButton);\ntype ToggleButtonCallable = ToggleButton;\nexport {\n ToggleButton as _ToggleButton,\n ToggleButtonCallable as ToggleButton\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Button, ButtonOptions } from \"~/component/button/Button.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport { xmark } from \"~/glyphs/solid/xmark.js\";\n\nGlyph.register(xmark);\n\n/**\n * Construction-time options for {@link TabCloseButton}.\n *\n * @category Components\n */\nexport interface TabCloseButtonOptions extends ButtonOptions {\n}\n\n/**\n * User-overridable visual defaults forwarded to `super` via the options bag.\n * Layered on top of [`Button`](/api/component/button/classes/Button)'s own\n * defaults, then overlaid with consumer options before the seed `glyph`\n * pins the close icon.\n */\nconst _defaultTabCloseButtonOptions: Partial<TabCloseButtonOptions> = {\n preferredSize: { width: 16, height: 16 },\n insets: new Insets(0, 0, 0, 0),\n foregroundColor: \"var(--ts-ui-close-button-fg, #555)\",\n};\n\n/**\n * A compact close button displaying the `xmark` glyph, sized to sit flush inside a tab header.\n *\n * @category Components\n */\nclass TabCloseButton extends Button<TabCloseButtonOptions> {\n\n /**\n * Creates a TabCloseButton seeded with the `xmark` glyph and sized for use in a tab toolbar.\n */\n constructor(options?: TabCloseButtonOptions) {\n // The seed `glyph` is in the defaults bag — a caller-supplied\n // `options.glyph` still wins because Button resolves the effective\n // glyph as `options.glyph ?? _defaultOptions.glyph` at construction.\n super(undefined, options, {\n ..._defaultTabCloseButtonOptions,\n glyph: \"xmark\",\n });\n }\n}\n\nconst TabCloseButtonCallable = callable(TabCloseButton);\ntype TabCloseButtonCallable = TabCloseButton;\nexport {\n TabCloseButton as _TabCloseButton,\n TabCloseButtonCallable as TabCloseButton\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from \"~/core/DOM.js\";\nimport { ThemeManager } from \"~/core/Theme.js\";\nimport { ToggleButton, ToggleButtonOptions } from \"~/component/button/ToggleButton.js\";\nimport { TabCloseButton } from \"~/component/button/TabCloseButton.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link TabButton}.\n *\n * `text` (the label), `glyph`, and `selected` are inherited from\n * {@link ToggleButtonOptions}.\n *\n * @category Components\n */\nexport interface TabButtonOptions extends ToggleButtonOptions {\n /** When true, builds and overlays the close (✕) affordance. Default false. */\n closeable?: boolean;\n}\n\n/**\n * A tab-styled toggle button: a {@link ToggleButton} that paints its own\n * unselected/hover/selected fill from the `--ts-ui-tab-button-*` theme tokens\n * and optionally overlays a close (✕) affordance built from\n * {@link TabCloseButton}.\n *\n * `TabButton` is a [`TabBar`](/api/component/container/classes/TabBar)\n * collaborator, not a general-purpose button. It owns the per-tab styling and\n * close-button *construction* that the strip previously replayed inline for\n * every cell; the strip keeps every geometry concern — insets, writing mode,\n * min/max clamp, and the per-layout re-pin of the overlaid close button (which\n * is positioned via the exposed {@link getCloseButton}). It adds no selection\n * or roving-tab-index logic of its own — those slot through the inherited\n * `ToggleButton` surface.\n *\n * @category Components\n */\nclass TabButton extends ToggleButton {\n\n // Whether this tab carries a close affordance. Construction-time only (the\n // close button is built or not when the tab is created), so it is set once\n // in the constructor and never via an option-dispatched setter — hence a\n // plain field rather than a `declare`d cascade-written one.\n private _closeable: boolean = false;\n\n // The overlaid close button, or null when the tab is not closeable. Built\n // in the constructor and raw-appended onto this button's own element (the\n // standard overlay pattern); TabBar reads it to wire its \"action\" and to\n // position/re-pin it each layout.\n private _closeButton: TabCloseButton | null = null;\n\n /**\n * Builds a tab-styled toggle button with the given label, applying the\n * `--ts-ui-tab-button-*` fill/border/hover/selected styling and, when\n * `closeable` is set, building and overlaying the close affordance.\n *\n * @param text - The visible label for the tab.\n * @param options - Tab button options; `closeable` gates the close button.\n */\n constructor(text: string, options?: TabButtonOptions) {\n // ToggleButton (via Button) builds its inner text/HBox content row in\n // its constructor body, so forward the positional `text` to super\n // first; the styling setters below then fire on a fully-built button.\n super(text);\n\n this._closeable = options?.closeable ?? false;\n\n if (options) {\n this.applyOptions(options);\n }\n\n // Paint the tab styling AFTER applyOptions, not before: the cascade\n // re-applies Button's chrome defaults from _defaultButtonOptions (the\n // \"2px ridge\" border, the 4px border-radius, the button drop-shadow), so\n // tab styling applied earlier would be clobbered back to a rounded,\n // ridged, shadowed button. Running it last lets the flat tab tokens and\n // the cleared radius/shadow win — matching the legacy createBarEntry,\n // which styled a no-options ToggleButton with nothing applied afterward.\n this.applyTabStyling();\n\n // Button's constructor late-dispatches `setGlyph` from the options bag\n // once, before this subclass's `applyOptions` runs; a glyph passed to a\n // ToggleButton subclass is therefore only pure-written to `_options` and\n // never rendered. Dispatch it explicitly here, mirroring how TabBar\n // called `setGlyph(constraints.glyph)` after construction.\n if (options?.glyph !== undefined) {\n this.setGlyph(options.glyph);\n }\n\n if (this._closeable) {\n this.buildCloseButton();\n }\n\n // ToggleButton's constructor wired the listener bag from the options it\n // received — but `super(text)` above passed none, so it wired nothing.\n // Wire the bag here, as the leaf, after super() and applyOptions, so a\n // `new TabButton(name, { listeners: { action } })` is not silently\n // dropped (ARCHITECTURE.md, Event handling).\n this.applyListeners(options?.listeners);\n }\n\n /**\n * Paints the tab's unselected, hover, and selected states from the\n * `--ts-ui-tab-button-*` theme tokens. The unselected fill routes the tab\n * token through both the background colour *and* image layer so Button's\n * inherited `--ts-ui-button-bg` gradient drops out (invalid as an image)\n * and the tab colour wins, killing the gradient bleed-through.\n */\n private applyTabStyling(): void {\n this.setBackgroundColor(\"var(--ts-ui-tab-button-bg, #b8b8c3)\");\n this.setBackgroundImage(\"var(--ts-ui-tab-button-bg, #b8b8c3)\");\n this.setBorder({\n borderTop: \"var(--ts-ui-tab-button-border-top, var(--ts-ui-tab-button-border, none))\",\n borderRight: \"var(--ts-ui-tab-button-border-right, var(--ts-ui-tab-button-border, none))\",\n borderBottom: \"var(--ts-ui-tab-button-border-bottom, var(--ts-ui-tab-button-border, none))\",\n borderLeft: \"var(--ts-ui-tab-button-border-left, var(--ts-ui-tab-button-border, none))\",\n });\n this.clearBorderRadius();\n this.clearShadow();\n\n // Hover state.\n this.setHoverBackgroundColor(\"var(--ts-ui-tab-button-hover-bg, #c4c4cf)\");\n this.setHoverBackgroundImage(\"var(--ts-ui-tab-button-hover-bg, #c4c4cf)\");\n this.setHoverShadow(\"none\");\n this.setHoverBorder({\n borderTop: \"var(--ts-ui-tab-button-hover-border-top, var(--ts-ui-tab-button-hover-border, none))\",\n borderRight: \"var(--ts-ui-tab-button-hover-border-right, var(--ts-ui-tab-button-hover-border, none))\",\n borderBottom: \"var(--ts-ui-tab-button-hover-border-bottom, var(--ts-ui-tab-button-hover-border, none))\",\n borderLeft: \"var(--ts-ui-tab-button-hover-border-left, var(--ts-ui-tab-button-hover-border, none))\",\n });\n\n // Selected (active) state.\n this.setSelectedBackgroundColor(\"var(--ts-ui-tab-button-selected-bg, rgb(255, 255, 255))\");\n this.setSelectedBackgroundImage(\"var(--ts-ui-tab-button-selected-bg, rgb(255, 255, 255))\");\n this.setSelectedShadow(\"none\");\n this.setSelectedBorder({\n borderTop: \"var(--ts-ui-tab-button-selected-border-top, var(--ts-ui-tab-button-selected-border, none))\",\n borderRight: \"var(--ts-ui-tab-button-selected-border-right, var(--ts-ui-tab-button-selected-border, none))\",\n borderBottom: \"var(--ts-ui-tab-button-selected-border-bottom, var(--ts-ui-tab-button-selected-border, none))\",\n borderLeft: \"var(--ts-ui-tab-button-selected-border-left, var(--ts-ui-tab-button-selected-border, none))\",\n });\n }\n\n /**\n * Builds the close (✕) affordance and overlays its element on this button's\n * own element. Transparent so the tab's background shows through, with a\n * faint rounded hover tint giving the ✕ its affordance. The ✕ is overlaid\n * (raw-appended) rather than enrolled in a layout so it floats at the corner\n * of the tab; TabBar pins its precise position each layout.\n */\n private buildCloseButton(): void {\n const closeButton = new TabCloseButton();\n\n // Transparent so the tab's own background shows through; a faint rounded\n // tint on hover gives the ✕ its affordance. `--ts-ui-tab-close-hover-bg`\n // has no themeToVars entry, so the inline rgba fallback is the actual\n // source of the value — keep it verbatim.\n closeButton.setBackgroundColor(\"transparent\");\n closeButton.setBackgroundImage(\"none\");\n closeButton.setHoverBackgroundColor(\"var(--ts-ui-tab-close-hover-bg, rgba(0, 0, 0, 0.12))\");\n closeButton.setHoverBackgroundImage(\"none\");\n closeButton.setHoverShadow(\"none\");\n closeButton.setBorderRadius(\"3px\");\n closeButton.clearBorder();\n closeButton.clearShadow();\n closeButton.setZIndex(1);\n\n // Shrink the ✕ glyph to roughly half the close-button hit box, centred —\n // the button stays the click target while the mark reads lighter. Pin it\n // (Glyph.setPreferredSize locks min/max too) so the line-height sync\n // never re-tracks the glyph to the title line height; TabBar's\n // per-layout re-pin keeps it at the base-scaled size.\n closeButton.pinGlyphSize(ThemeManager.getResolvedScale().tabCloseGlyph);\n\n // Overlay it on this button's own element rather than enrolling it in a\n // layout (which would stretch it over the whole tab); TabBar pins it to\n // the right edge each layout.\n DOM.sink.appendChild(this.getElement(true)!, closeButton.getElement(true)!);\n\n this._closeButton = closeButton;\n }\n\n /**\n * Returns the overlaid close button, or `null` when this tab is not\n * closeable. TabBar wires its `\"action\"` event and positions/re-pins it on\n * each layout pass.\n *\n * @returns The close button, or `null`.\n */\n getCloseButton(): TabCloseButton | null {\n return this._closeButton;\n }\n\n /**\n * Returns whether this tab carries a close affordance. Construction-time\n * only — there is no runtime toggle.\n *\n * @returns True when the tab was built closeable.\n */\n isCloseable(): boolean {\n return this._closeable;\n }\n}\n\nconst TabButtonCallable = callable(TabButton);\ntype TabButtonCallable = TabButton;\nexport {\n TabButton as _TabButton,\n TabButtonCallable as TabButton\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{l as e,u as t}from"./Position-B-WfZYAJ.js";import{f as n,n as r,t as i}from"./Component-BR2f0Itb.js";var a={tag:`span`,textAlign:`left`,fontKerning:`auto`,fontSize:14,fontSizeAdjust:`none`,fontStretch:`normal`,fontStyle:`normal`,fontVariant:`normal`,fontWeight:`normal`,truncate:!0},o=100,s=`calc(1em + var(--ts-ui-line-padding, 2px))`,Text=class extends i{_hasExplicitPreferredSize=!1;_fontSizeCSSVar=`--ts-ui-font-size`;_fontSizeCSSRule=`var(--ts-ui-font-size, 14px)`;_unsubscribeTheme;_lineHeightCSSVar=null;_lineHeightCSSRule=s;_measuredBaseline=null;_measuredMinSize=null;_autoMeasure=!0;_measurementDirty=!0;_wordBreak=null;_lineClamp=null;_textOverflow=null;_truncate=!0;constructor(e,t,n){super(t,{...a,...n??{}}),this._defaultOptions.fontFamily=`var(--ts-ui-font-family, system-ui, sans-serif)`,this.clearInsets(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule),this._unsubscribeTheme=r.onThemeChange(()=>{if(this._fontSizeCSSVar){let e=this.resolveBoundFontSizePx();e!==null&&(this._options.fontSize=e)}this._lineHeightCSSVar&&(this._defaultOptions.lineHeight=this.readThemeLineHeightPx()),this.calculateSize()}),e!==void 0&&this._options.text===void 0&&this.setText(e),this._measurementDirty=!0}applyOptions(e){return super.applyOptions(e),e.text!==void 0&&this.setText(e.text),e.textAlign!==void 0&&this.setTextAlign(e.textAlign),e.textShadow!==void 0&&this.setTextShadow(e.textShadow),e.fontFamily!==void 0&&this.setFontFamily(e.fontFamily),e.fontSize!==void 0&&this.setFontSize(e.fontSize),e.fontWeight!==void 0&&this.setFontWeight(e.fontWeight),e.fontStyle!==void 0&&this.setFontStyle(e.fontStyle),e.fontVariant!==void 0&&this.setFontVariant(e.fontVariant),e.fontStretch!==void 0&&this.setFontStretch(e.fontStretch),e.fontKerning!==void 0&&this.setFontKerning(e.fontKerning),e.fontSizeAdjust!==void 0&&this.setFontSizeAdjust(e.fontSizeAdjust),e.lineHeight!==void 0&&this.setLineHeight(e.lineHeight),e.textOverflow!==void 0&&this.setTextOverflow(e.textOverflow),e.whiteSpace!==void 0&&this.setWhiteSpace(e.whiteSpace),this.setTruncate(e.truncate??this._defaultOptions.truncate),this}readThemeLineHeightPx(){let n=this._options.fontSize??this._defaultOptions.fontSize??14;if(this._lineHeightCSSVar){let e=t.source.getThemeVar(this._lineHeightCSSVar),n=parseFloat(e);if(!isNaN(n))return n}return e.lineHeightPx({fontSizePx:n})}getElement(e=!1){return super.getElement(e)}resolveBoundFontSizePx(){if(!this._fontSizeCSSVar)return null;let e=parseFloat(t.source.getThemeVar(this._fontSizeCSSVar));return isNaN(e)?t.source.resolveFontSizePx(this._fontSizeCSSRule??`var(${this._fontSizeCSSVar})`):e}setPreferredSize(e,t){return this._hasExplicitPreferredSize=!0,super.setPreferredSize(e,t),this}setCalculatedSize(e,t){this._hasExplicitPreferredSize||super.setPreferredSize(e,t)}calculateSize(){if(this._measurementDirty=!1,this._defaultOptions.lineHeight===void 0&&(this._defaultOptions.lineHeight=this.readThemeLineHeightPx()),!this._autoMeasure)return;let e=this.getLineHeight()??this.readThemeLineHeightPx(),n=Math.ceil(e),r=this._options.text;if(r){let e=t.source.measureText(r.toString(),this.measureOptions()),i=this.measuredHeight(r.toString(),e.width,e.height);this._measuredBaseline=e.baseline,this.setCalculatedSize(e.width,i);let a=this._truncate?Math.min(e.width,o):e.width;this._measuredMinSize={width:a,height:Math.max(i,n)}}else this._measuredBaseline=null,this.setCalculatedSize(0,0),this._measuredMinSize={width:0,height:0}}measure(){let e=this._autoMeasure;this._autoMeasure=!0,this.calculateSize(),this._autoMeasure=e}getBaseline(){return this._measurementDirty&&this.calculateSize(),this.wrapInnerBaseline(this._measuredBaseline)}measureOptions(){let e=this.getFontSize(),t=this.getLineHeight();return{fontFamily:this.getFontFamily()??void 0,fontSize:this._fontSizeCSSRule??(e===null?void 0:`${e}px`),fontWeight:this.getFontWeight()??void 0,fontStyle:this.getFontStyle()??void 0,fontVariant:this.getFontVariant()??void 0,fontStretch:this.getFontStretch()??void 0,lineHeight:this._lineHeightCSSRule??(t===null?void 0:`${t}px`)}}isWrapping(){let e=this.getWhiteSpace();return e===`normal`||e===`pre-wrap`||e===`pre-line`||e===`break-spaces`}measuredHeight(e,n,r){if(!this.isWrapping()||this.isVerticalWritingMode())return r;let i=this.getWidth();if(Number.isNaN(i))return r;let a=this.getPerimeterSize(),o=i-a.left-a.right;if(o>=n)return r;let s=t.source.measureText(e,{...this.measureOptions(),maxWidth:o}),c=Math.ceil(this.getLineHeight()??this.readThemeLineHeightPx());return Math.max(s.height,c)}setWidth(e){let t=this.getWidth();return super.setWidth(e),this.isWrapping()&&this.getWidth()!==t&&(this._measurementDirty=!0,this.calculateSize()),this}getPreferredSize(){this._measurementDirty&&this.calculateSize();let e=super.getPreferredSize();return e&&this.isVerticalWritingMode()?{width:e.height,height:e.width}:e}isVerticalWritingMode(){let e=this.getWritingMode();return e!==null&&(e.startsWith(`vertical`)||e.startsWith(`sideways`))}getMinSize(){this._measurementDirty&&this.calculateSize();let e=this._measuredMinSize,t=super.getMinSize();return e?this.isVerticalWritingMode()?t?{width:Math.max(t.width,e.height),height:t.height}:{width:e.height,height:0}:t?{width:t.width,height:Math.max(t.height,e.height)}:{width:0,height:e.height}:t}getText(){return this._options.text||``}setText(e){this._options.text=e||``,this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout();let n=this.getElement();return n&&t.sink.apply(n,{text:e.valueOf()}),this}setAutoMeasure(e){return this._autoMeasure=e,this}getTextAlign(){return this._options.textAlign??this._defaultOptions.textAlign??null}setTextAlign(e){return this._options.textAlign=e,this.setElementCSSRule(`textAlign`,e),this}getTextShadow(){return this._options.textShadow??null}setTextShadow(e){return this._options.textShadow=e,this.setElementCSSRule(`textShadow`,e),this}clearTextShadow(){return this._options.textShadow===void 0?this:(this._options.textShadow=void 0,this.setElementCSSRule(`textShadow`,null),this)}getFontFamily(){return this._options.fontFamily??this._defaultOptions.fontFamily??null}setFontFamily(e){return this._options.fontFamily=e,this.setElementCSSRule(`fontFamily`,e),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getFontKerning(){return this._options.fontKerning??this._defaultOptions.fontKerning??null}setFontKerning(e){return this._options.fontKerning=e,this.setElementCSSRule(`fontKerning`,e),this}getFontSize(){return this._options.fontSize??this._defaultOptions.fontSize??null}setFontSize(e){if(typeof e==`number`)this._options.fontSize=e,this._fontSizeCSSVar=null,this._fontSizeCSSRule=null,this.setElementCSSRule(`fontSize`,e+`px`);else{let t=this.getFontSize()??14;this._fontSizeCSSVar=e,this._fontSizeCSSRule=`var(${e}, ${t}px)`,this.setElementCSSRule(`fontSize`,this._fontSizeCSSRule);let n=this.resolveBoundFontSizePx();n!==null&&(this._options.fontSize=n)}return this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getFontSizeAdjust(){return this._options.fontSizeAdjust??this._defaultOptions.fontSizeAdjust??null}setFontSizeAdjust(e){return this._options.fontSizeAdjust=e,this.setElementCSSRule(`fontSizeAdjust`,e),this}getFontStretch(){return this._options.fontStretch??this._defaultOptions.fontStretch??null}setFontStretch(e){return this._options.fontStretch=e,this.setElementCSSRule(`fontStretch`,e),this}getFontStyle(){return this._options.fontStyle??this._defaultOptions.fontStyle??null}setFontStyle(e){return this._options.fontStyle=e,this.setElementCSSRule(`fontStyle`,e),this}getFontVariant(){return this._options.fontVariant??this._defaultOptions.fontVariant??null}setFontVariant(e){return this._options.fontVariant=e,this.setElementCSSRule(`fontVariant`,e),this}getFontWeight(){return this._options.fontWeight??this._defaultOptions.fontWeight??null}setFontWeight(e){return this._options.fontWeight=e,this.setElementCSSRule(`fontWeight`,e),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getLineHeight(){return this._options.lineHeight??this._defaultOptions.lineHeight??null}setLineHeight(e){if(typeof e==`number`){if(this._options.lineHeight===e&&this._lineHeightCSSVar===null&&this._lineHeightCSSRule===null)return this;this._options.lineHeight=e,this._lineHeightCSSVar=null,this._lineHeightCSSRule=null,this.setElementCSSRule(`lineHeight`,e+`px`)}else this._lineHeightCSSVar=e,this._lineHeightCSSRule=`var(${e}, ${s})`,this._options.lineHeight=this.readThemeLineHeightPx(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule);return this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}centerInHeight(e){return e===null?(this._lineHeightCSSVar=null,this._lineHeightCSSRule=s,this._options.lineHeight=this.readThemeLineHeightPx(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this):this.setLineHeight(e)}getTextOverflow(){return this._textOverflow}setTextOverflow(e){return this._textOverflow=e,this.setElementCSSRule(`textOverflow`,e),this}clearTextOverflow(){return this._textOverflow===null?this:(this._textOverflow=null,this.setElementCSSRule(`textOverflow`,null),this)}isTruncate(){return this._truncate}setTruncate(e){return this._truncate=e,e?(this.setWhiteSpace(`nowrap`),this.setOverflow(`hidden`),this.setTextOverflow(`ellipsis`)):(this.setElementCSSRule(`whiteSpace`,null),this.setOverflow(`visible`),this.setElementCSSRule(`textOverflow`,null),this._textOverflow=null),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getWordBreak(){return this._wordBreak}setWordBreak(e){return this._wordBreak===e?this:(this._wordBreak=e,this.setElementCSSRule(`wordBreak`,e),this)}getLineClamp(){return this._lineClamp}setLineClamp(e){return this._lineClamp===e?this:(this._lineClamp=e,this.setElementCSSRules({display:`-webkit-box`,webkitBoxOrient:`vertical`,webkitLineClamp:String(e),overflow:`hidden`,textOverflow:`ellipsis`}),this)}clearLineClamp(){return this._lineClamp===null?this:(this._lineClamp=null,this.setElementCSSRules({display:null,webkitBoxOrient:null,webkitLineClamp:null,overflow:null,textOverflow:null}),this)}applyStyle(e){super.applyStyle(e);let t=this.getFontSize(),n=this.getLineHeight();return this.setElementCSSRules({fontFamily:this.getFontFamily()??``,textAlign:this.getTextAlign()??``,textShadow:this.getTextShadow()??``,fontKerning:this.getFontKerning()??``,fontSize:this._fontSizeCSSRule??(t===null?``:`${t}px`),fontSizeAdjust:this.getFontSizeAdjust()??``,fontStretch:this.getFontStretch()??``,fontStyle:this.getFontStyle()??``,fontVariant:this.getFontVariant()??``,fontWeight:this.getFontWeight()??``,lineHeight:this._lineHeightCSSRule??(n===null?``:`${n}px`)}),this}dispose(){this._unsubscribeTheme()}render(){let e=super.render();return t.sink.apply(e,{text:this.getText().valueOf()}),e}},c=n(Text);export{c as t};
|
|
2
|
-
//# sourceMappingURL=Text-D1RrBY52.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Text-D1RrBY52.js","names":[],"sources":["../../src/typescript/lib/component/input/Text.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { ThemeManager } from \"~/core/Theme.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { Util } from \"~/core/Util.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Text}.\n *\n * @category Components\n */\nexport interface TextOptions extends ComponentOptions {\n tag?: string;\n text?: string;\n textAlign?: string;\n textShadow?: string;\n fontFamily?: string;\n fontSize?: number | string;\n fontWeight?: string;\n fontStyle?: string;\n fontVariant?: string;\n fontStretch?: string;\n fontKerning?: string;\n fontSizeAdjust?: string;\n lineHeight?: number | string;\n textOverflow?: string;\n whiteSpace?: string;\n /**\n * When `true` (default), the text is single-line + clipped + ellipsised\n * when its rendered width is below its natural width, and `minSize.width`\n * is capped at `100` so parent layouts can shrink the text past its\n * natural width.\n *\n * When `false`, no ellipsis is applied and `minSize.width` reports the\n * full natural width — the text refuses to be squeezed, forcing the\n * parent to widen (used by [`Button`](/api/component/button/classes/Button)\n * for the label so the button grows to fit its text instead of clipping).\n */\n truncate?: boolean;\n}\n\n/**\n * Module-level class defaults forwarded to `super` via the options bag so the\n * `applyOptions` cascade dispatches each setter once with the final value.\n *\n * `fontFamily` and `lineHeight` are intentionally **omitted**:\n *\n * - `fontFamily` must remain a getter-fallback only. Routing it through\n * `setFontFamily(...)` would write the literal `var(--ts-ui-font-family, …)`\n * onto every Text's CSS rule, blocking a parent's `font-family` override\n * from cascading through.\n * - `lineHeight` is theme-derived (`readThemeLineHeightPx()`), so the value\n * isn't known at module load. It is resolved lazily on first\n * `calculateSize()` (post-attach), keeping construction JS-only per\n * ARCHITECTURE.md \"Defer DOM work to render time\".\n */\nconst _defaultTextOptions: Partial<TextOptions> = {\n tag: \"span\",\n textAlign: \"left\",\n fontKerning: \"auto\",\n fontSize: 14,\n fontSizeAdjust: \"none\",\n fontStretch: \"normal\",\n fontStyle: \"normal\",\n fontVariant: \"normal\",\n fontWeight: \"normal\",\n truncate: true,\n};\n\n// Upper bound for the auto-derived `minSize.width` from text measurement —\n// short labels report their full measured width (so they're never truncated\n// when the container has room), longer text caps here so the parent layout\n// always has room to shrink the Text below its natural width.\nconst TEXT_AUTO_MIN_WIDTH_CAP_PX = 100;\n\n// Default theme-tracking line-height rule: the control's own font size plus the\n// `--ts-ui-line-padding` leading, so the line box scales per font size. `1em`\n// resolves against the element's own font-size at both render and measure time.\n// `2px` is the shipped `--ts-ui-line-padding` default, used only if the var is\n// absent. A control overrides this with an explicit px via `setLineHeight`.\nconst ADDITIVE_LINE_HEIGHT_RULE = \"calc(1em + var(--ts-ui-line-padding, 2px))\";\n\n/**\n * A text-displaying component with comprehensive font and layout controls.\n *\n * Uses an off-screen probe element to measure text dimensions and automatically\n * updates the preferred size whenever the text or a font property changes.\n *\n * `Text` subscribes to {@link ThemeManager} on construction so it re-measures itself\n * on every theme change. Components that create `Text` instances dynamically and\n * remove them from the page should call `text.dispose()` to detach the listener.\n *\n * @category Components\n */\nclass Text<TOptions extends TextOptions = TextOptions> extends Component<TOptions> {\n\n private _hasExplicitPreferredSize: boolean = false;\n private _fontSizeCSSVar : string | null = \"--ts-ui-font-size\";\n private _fontSizeCSSRule: string | null = \"var(--ts-ui-font-size, 14px)\";\n private readonly _unsubscribeTheme: () => void;\n private _lineHeightCSSVar : string | null = null;\n private _lineHeightCSSRule: string | null = ADDITIVE_LINE_HEIGHT_RULE;\n private _measuredBaseline: number | null = null;\n private _measuredMinSize: Size | null = null;\n private _autoMeasure: boolean = true;\n private _measurementDirty: boolean = true;\n private _wordBreak: string | null = null;\n private _lineClamp: number | null = null;\n private _textOverflow: string | null = null;\n private _truncate: boolean = true;\n\n // `NoInfer` on `options` keeps a partial options literal from narrowing\n // TOptions to just the keys it carries: `new Text(\"x\", { fontWeight: \"600\" })`\n // must stay a `Text<TextOptions>` (assignable to Component), not a\n // `Text<{ fontWeight: string }>` (whose narrowed option type is not). Subclasses\n // still fix TOptions through `extends Text<MyOptions>`, not argument inference.\n constructor(text?: String, options?: NoInfer<TOptions>, subclassDefaults?: Partial<TOptions>) {\n super(\n options,\n { ..._defaultTextOptions, ...(subclassDefaults ?? {}) } as Partial<TOptions>,\n );\n\n // Carve-out fallbacks — see `_defaultTextOptions` for why these two\n // don't ride the merge-defaults cascade. Both are consulted by their\n // getters as a fallback when `_options.X` is undefined.\n //\n // Note: the cascade-driven `setFontSize(14)` clobbers `fontSizeCSSVar`\n // and `fontSizeCSSRule` to null, but Text's field initializers (which\n // run after super returns) restore both to their var-binding values —\n // so theme reactivity is preserved by the DOM `var(...)` binding even\n // though the cascade temporarily writes a literal.\n //\n // `_defaultOptions.lineHeight` is resolved lazily on first\n // `calculateSize()` (post-attach) — see ARCHITECTURE.md \"Defer DOM\n // work to render time\".\n this._defaultOptions.fontFamily = \"var(--ts-ui-font-family, system-ui, sans-serif)\";\n\n this.clearInsets();\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n\n this._unsubscribeTheme = ThemeManager.onThemeChange(() => {\n if (this._fontSizeCSSVar) {\n // Resolve from the element's computed font-size (the cascade has\n // applied the new var by the time onThemeChange fires); the root\n // custom property reads back as an unevaluated calc() string.\n const resolved = this.resolveBoundFontSizePx();\n\n if (resolved !== null) {\n // Route to `_options` so the post-cascade explicit value\n // (set by `setFontSize(14)` during applyOptions) is\n // overwritten on theme change. Writing to `_defaultOptions`\n // here would be shadowed by `_options.fontSize = 14` in\n // the `getFontSize` fallback, breaking re-flow.\n this._options.fontSize = resolved as TOptions[\"fontSize\"];\n }\n }\n\n if (this._lineHeightCSSVar) {\n this._defaultOptions.lineHeight = this.readThemeLineHeightPx();\n }\n\n this.calculateSize();\n });\n\n // Positional `text` constructor argument: write to the bag only when\n // the caller didn't also pass `options.text` (which would have been\n // dispatched via super's applyOptions cascade and should win).\n if (text !== undefined && this._options.text === undefined) {\n this.setText(text);\n }\n\n // Off-screen text measurement is deferred until the first\n // getPreferredSize / getBaseline call so construction stays JS-only\n // (no forced layout from `DOM.source.measureText`).\n this._measurementDirty = true;\n }\n\n /**\n * Applies a {@link TextOptions} bag to this component, dispatching font and\n * text properties to their corresponding setters after the inherited\n * Component fields have been applied.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: TOptions): this {\n super.applyOptions(options);\n\n // Dispatch only caller-supplied values. Class-level font defaults (e.g.\n // the 14px size, a subclass's bold weight) are resolved lazily by the\n // font getters' `_defaultOptions` fallback, which `applyStyle` re-reads\n // at render — so they never enter `_options`.\n if (options.text !== undefined) {\n this.setText(options.text);\n }\n\n if (options.textAlign !== undefined) {\n this.setTextAlign(options.textAlign);\n }\n\n if (options.textShadow !== undefined) {\n this.setTextShadow(options.textShadow);\n }\n\n if (options.fontFamily !== undefined) {\n this.setFontFamily(options.fontFamily);\n }\n\n if (options.fontSize !== undefined) {\n this.setFontSize(options.fontSize);\n }\n\n if (options.fontWeight !== undefined) {\n this.setFontWeight(options.fontWeight);\n }\n\n if (options.fontStyle !== undefined) {\n this.setFontStyle(options.fontStyle);\n }\n\n if (options.fontVariant !== undefined) {\n this.setFontVariant(options.fontVariant);\n }\n\n if (options.fontStretch !== undefined) {\n this.setFontStretch(options.fontStretch);\n }\n\n if (options.fontKerning !== undefined) {\n this.setFontKerning(options.fontKerning);\n }\n\n if (options.fontSizeAdjust !== undefined) {\n this.setFontSizeAdjust(options.fontSizeAdjust);\n }\n\n if (options.lineHeight !== undefined) {\n this.setLineHeight(options.lineHeight);\n }\n\n if (options.textOverflow !== undefined) {\n this.setTextOverflow(options.textOverflow);\n }\n\n if (options.whiteSpace !== undefined) {\n this.setWhiteSpace(options.whiteSpace);\n }\n\n // `truncate` carries a class default (true) and applies its CSS\n // (white-space / overflow / text-overflow) imperatively via the setter\n // with no render re-read, so always dispatch the caller value or the\n // default — otherwise a default-truncating Text never gets the CSS.\n this.setTruncate(options.truncate ?? this._defaultOptions.truncate!);\n\n return this;\n }\n\n /**\n * Resolves this `Text`'s line box height in pixels under the additive\n * leading model.\n *\n * @returns `Util.lineHeightPx(fontSize)` — the control's own font size plus\n * the `--ts-ui-line-padding` leading — for the default theme-tracking case.\n * A legacy custom line-height var binding resolves that var as a fixed line\n * box instead, falling back to the additive value when it is unparseable.\n *\n * @remarks `_options.fontSize` is always a resolved px number here (a CSS\n * var passed to `setFontSize` is resolved and stored as a number), so the\n * leading scales with the control's actual font size — a 12px button title\n * and a 14px label get proportionate line boxes from the one token. This is\n * the same arithmetic `Util.lineHeightPx` applies for input box heights, so\n * a `Text` measures and renders at the line height a sibling input expects.\n */\n private readThemeLineHeightPx(): number {\n // `_options.fontSize` is the resolved px the bound var evaluates to —\n // `setFontSize`/`onThemeChange` populate it through the probe-backed\n // `resolveBoundFontSizePx`, so it is correct even pre-attach (a calc()\n // token included). No element read here: a parent reads this at\n // construction, before this Text's own element is styled.\n const fs = (this._options.fontSize as number | undefined) ?? (this._defaultOptions.fontSize as number | undefined) ?? 14;\n\n if (this._lineHeightCSSVar) {\n const raw = DOM.source.getThemeVar(this._lineHeightCSSVar);\n const parsed = parseFloat(raw);\n\n if (!isNaN(parsed)) {\n return parsed;\n }\n }\n\n return Util.lineHeightPx({ fontSizePx: fs });\n }\n\n /**\n * Returns the DOM element handle.\n *\n * @param createIfMissing - Optional. When true, renders the element if it does not yet exist.\n *\n * @returns The component's element handle.\n */\n getElement(createIfMissing: boolean = false): Handle | undefined {\n return super.getElement(createIfMissing);\n }\n\n /**\n * Resolves the bound font-size var to a px number. A simple var (e.g. the\n * `--ts-ui-font-size` base) parses straight off the document root; a relative\n * font token's var holds a `calc(...)` that `getPropertyValue` returns\n * unevaluated (so `parseFloat` reads `NaN`), so it falls back to a\n * cascade-evaluating probe via `DOM.source.resolveFontSizePx`. The probe path\n * works **pre-attach** — before this component's own element is styled —\n * which is when a parent (e.g. a `Header`) first reads the line-box size.\n *\n * @returns The resolved font size in px, or `null` when no var is bound (an\n * explicit numeric size was set instead) — callers keep the cached number.\n */\n private resolveBoundFontSizePx(): number | null {\n if (!this._fontSizeCSSVar) return null; // explicit px size — no var bound\n\n const raw = parseFloat(DOM.source.getThemeVar(this._fontSizeCSSVar));\n if (!isNaN(raw)) return raw; // simple var — cheap, no probe\n\n return DOM.source.resolveFontSizePx(this._fontSizeCSSRule ?? `var(${this._fontSizeCSSVar})`);\n }\n\n /**\n * Sets the preferred size from an explicit caller, locking it against automatic recalculation.\n *\n * @returns This component, for method chaining.\n */\n setPreferredSize(width: number, height: number): this {\n this._hasExplicitPreferredSize = true;\n super.setPreferredSize(width, height);\n\n return this;\n }\n\n /**\n * Updates the preferred size from a measurement only when no explicit size has been set.\n */\n private setCalculatedSize(width: number, height: number): void {\n if (!this._hasExplicitPreferredSize) {\n super.setPreferredSize(width, height);\n }\n }\n\n /**\n * Measures the text using an off-screen probe element and sets the preferred size.\n *\n * @remarks Creates a temporary fixed-positioned invisible `<span>`, appends it to the body\n * to obtain its bounding rect, then removes it. Sets preferred size to (0, 0) when no text is set.\n * No-op when {@link setAutoMeasure} is `false` — the parent layout is expected to size this Text.\n */\n private calculateSize(): void {\n this._measurementDirty = false;\n\n // First-read deferral: populate the default line-height the first\n // time we measure, when the component is attached and\n // `getComputedStyle` is safe. Subsequent reads come through the\n // `ThemeManager.onThemeChange` callback above. Placed before the\n // `_autoMeasure` gate so non-measuring `Text` instances still get\n // a resolved value populated for `getLineHeight()` callers.\n if (this._defaultOptions.lineHeight === undefined) {\n this._defaultOptions.lineHeight = this.readThemeLineHeightPx();\n }\n\n if (!this._autoMeasure) {\n return;\n }\n\n // Floor the reported minimum height to one line so a single-line label\n // is never squeezed below its line box (the measured height is 0 for\n // empty text and unset before the first probe).\n const lineHeightPx = this.getLineHeight() ?? this.readThemeLineHeightPx();\n const minLineHeight = Math.ceil(lineHeightPx);\n\n const text = this._options.text;\n if (text) {\n // Natural (single-line) measurement establishes the preferred WIDTH\n // and the baseline; the height then follows the box's current width,\n // growing when a wrapping run has been laid out narrower than natural.\n const natural = DOM.source.measureText(text.toString(), this.measureOptions());\n const height = this.measuredHeight(text.toString(), natural.width, natural.height);\n\n this._measuredBaseline = natural.baseline;\n this.setCalculatedSize(natural.width, height);\n // Store the measured floor as per-instance derived state (like\n // `_measuredBaseline`), kept out of `_defaultOptions`, which holds\n // the class-level Text defaults rather than per-instance\n // measurements. `getMinSize` folds this into the inherited min.\n // When truncation is disabled, report the full natural width so the\n // parent layout widens to fit instead of squeezing the text;\n // otherwise cap it so the parent can shrink the text past its\n // natural width.\n const autoMinWidth = this._truncate\n ? Math.min(natural.width, TEXT_AUTO_MIN_WIDTH_CAP_PX)\n : natural.width;\n this._measuredMinSize = {\n width: autoMinWidth,\n height: Math.max(height, minLineHeight),\n };\n } else {\n // No glyphs means no baseline — report null so HBox doesn't try\n // to baseline-align surrounding components against an empty box.\n // Reserve no line height either: an empty Text (e.g. the label slot\n // of an icon-only button) must collapse so it doesn't inflate the\n // container and knock the icon off-centre. The one-line floor only\n // applies once there is text to keep on its line.\n this._measuredBaseline = null;\n this.setCalculatedSize(0, 0);\n this._measuredMinSize = { width: 0, height: 0 };\n }\n }\n\n /**\n * Forces a one-off text measurement that ignores {@link setAutoMeasure}.\n * Use when the caller has opted out of auto-measure but needs an up-to-date\n * preferred size after a programmatic text change.\n */\n measure(): void {\n const wasAuto = this._autoMeasure;\n this._autoMeasure = true;\n this.calculateSize();\n this._autoMeasure = wasAuto;\n }\n\n /**\n * Returns the visual baseline of the rendered text, accounting for any\n * border, padding, or framework insets on this component.\n *\n * @returns The baseline offset from the component's outer top, in pixels,\n * or `null` when no text has been measured yet.\n *\n * @remarks Forces a measurement when the cached value is stale — the\n * off-screen probe is deferred from construction so first-call timing\n * shifts to whoever asks for a size first (usually `doLayout`).\n */\n getBaseline(): number | null {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n return this.wrapInnerBaseline(this._measuredBaseline);\n }\n\n /**\n * Builds the font/line-height option bag for a {@link DOM.measureText} probe\n * from this Text's resolved styling. Shared by the natural (single-line)\n * measurement and the wrap-aware height re-measurement in\n * {@link measuredHeight}, which adds a `maxWidth`.\n *\n * @returns The measure options (font family/size/weight/style/variant/stretch\n * and line height), each `undefined` when unset so the probe's own default\n * applies.\n */\n private measureOptions() {\n const fontSize = this.getFontSize();\n const lineHeight = this.getLineHeight();\n\n return {\n fontFamily : this.getFontFamily() ?? undefined,\n fontSize : this._fontSizeCSSRule ?? (fontSize !== null ? `${fontSize}px` : undefined),\n fontWeight : this.getFontWeight() ?? undefined,\n fontStyle : this.getFontStyle() ?? undefined,\n fontVariant: this.getFontVariant() ?? undefined,\n fontStretch: this.getFontStretch() ?? undefined,\n lineHeight : this._lineHeightCSSRule ?? (lineHeight !== null ? `${lineHeight}px` : undefined),\n };\n }\n\n /**\n * Whether this Text wraps onto multiple lines — i.e. its `white-space` is a\n * wrapping value rather than `nowrap`/`pre`. Only a wrapping Text's height\n * depends on the width it is given.\n *\n * @returns `true` when the text soft-wraps at its box width.\n */\n private isWrapping(): boolean {\n const ws = this.getWhiteSpace();\n\n return ws === \"normal\" || ws === \"pre-wrap\" || ws === \"pre-line\" || ws === \"break-spaces\";\n }\n\n /**\n * The height the text needs given its current laid-out width.\n *\n * A `nowrap` label — or one not yet given a width, or in a vertical writing\n * mode — is width-independent, so its natural single-line height stands. A\n * wrapping label whose box is narrower than its natural run re-measures at\n * the current inner width (its own border/insets removed): the extra lines\n * make it taller. The re-measure uses the same line-height as the render, so\n * the reported height matches what is drawn — line-height is the per-line\n * unit the whole calculation stacks.\n *\n * @param text - The text run being measured.\n * @param naturalWidth - The natural single-line width (nowrap), the wrap threshold.\n * @param naturalHeight - The natural single-line height, used when it does not wrap.\n * @returns The height (px) at the current width; floored at one line.\n */\n private measuredHeight(text: string, naturalWidth: number, naturalHeight: number): number {\n if (!this.isWrapping() || this.isVerticalWritingMode()) {\n return naturalHeight;\n }\n\n const width = this.getWidth();\n\n if (Number.isNaN(width)) {\n return naturalHeight;\n }\n\n const perimeter = this.getPerimeterSize();\n const innerWidth = width - perimeter.left - perimeter.right;\n\n // Wide enough for the whole run on one line → no wrapping; keep the exact\n // single-line height and skip a redundant probe.\n if (innerWidth >= naturalWidth) {\n return naturalHeight;\n }\n\n const wrapped = DOM.source.measureText(text, { ...this.measureOptions(), maxWidth: innerWidth });\n const minLineHeight = Math.ceil(this.getLineHeight() ?? this.readThemeLineHeightPx());\n\n return Math.max(wrapped.height, minLineHeight);\n }\n\n /**\n * Sets the laid-out width and, for a wrapping Text, re-measures at the new\n * width so its preferred height tracks the number of wrapped lines.\n *\n * A wrapping run's height depends on the width it is given, but the\n * preferred-size protocol resolves heights bottom-up before widths are\n * assigned top-down — so the height is only knowable once the box has a\n * width. Re-measuring here updates the preferred height, and\n * `Component.setPreferredSize` fires the ancestor notify, so the parent\n * re-lays-out one pass later at the taller height (the box's own min height\n * also rises, so the current pass already reserves the room rather than\n * clipping). A `nowrap` label's height is width-independent, so its width\n * changes need no re-measure. Idempotent once the width settles: an\n * unchanged width re-measures to the same height and the notify is suppressed.\n *\n * @param width - The new outer width in pixels.\n * @returns This component, for chaining.\n */\n override setWidth(width: number): this {\n const previous = this.getWidth();\n\n super.setWidth(width);\n\n if (this.isWrapping() && this.getWidth() !== previous) {\n this._measurementDirty = true;\n // Re-measure now (at the new width) so the updated preferred height\n // propagates before the next layout pass reads it.\n this.calculateSize();\n }\n\n return this;\n }\n\n /**\n * Returns the preferred size, lazily measuring the text on the first call.\n *\n * @returns The preferred Size, or `null` per the inherited contract.\n *\n * @remarks Construction no longer eagerly probes `document.body` for text\n * dimensions; the first reader of the preferred size pays the measurement\n * cost. After attach this is `doLayout`, so the probe happens at layout\n * time rather than construction time.\n */\n getPreferredSize() {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n const size = super.getPreferredSize();\n\n // `measureTextMetrics` always measures the run horizontally. A vertical\n // writing mode rotates it onto the block axis, so the natural text length\n // becomes the height and the line box becomes the width — swap to report\n // the on-screen extents.\n if (size && this.isVerticalWritingMode()) {\n return { width: size.height, height: size.width };\n }\n\n return size;\n }\n\n /**\n * Whether the active {@link Component.setWritingMode | writing mode} rotates\n * the text run onto the block (vertical) axis, so the measured horizontal\n * extents must be swapped to describe the on-screen size.\n *\n * @returns `true` for a `vertical-*` or `sideways-*` writing mode.\n */\n private isVerticalWritingMode(): boolean {\n const mode = this.getWritingMode();\n\n return mode !== null && (mode.startsWith(\"vertical\") || mode.startsWith(\"sideways\"));\n }\n\n /**\n * Returns the effective minimum size, folding the measured one-line height\n * floor (from `calculateSize`) into the inherited component/layout minimum.\n *\n * @returns The minimum `{width, height}`, never shorter than one line of\n * text, or `null` only when neither a measurement nor an inherited minimum\n * exists.\n *\n * @remarks Only the **height** floor participates in the hard minimum —\n * text cannot render below its line box without clipping. The measured\n * width is deliberately *not* folded in: surfacing each label's natural\n * width as a hard minimum would stop parent layouts (e.g. an equal-mode tab\n * bar) from compressing short labels to fit, which is why `Text.minSize`\n * has historically reported a zero width. The floor is per-instance derived\n * state held in `_measuredMinSize`, not a class default, so it lives outside\n * `_defaultOptions`. An explicit caller `setMinSize` taller than the floor\n * still wins via `Math.max`; a value shorter than one line is lifted to it.\n */\n getMinSize(): Size | null {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n const measured = this._measuredMinSize;\n const base = super.getMinSize();\n\n if (!measured) {\n return base;\n }\n\n // Vertical writing mode: the one-line floor guards the line *thickness*,\n // which is now the width rather than the height (the length runs down the\n // block axis and stays freely compressible).\n if (this.isVerticalWritingMode()) {\n if (!base) {\n return { width: measured.height, height: 0 };\n }\n\n return {\n width: Math.max(base.width, measured.height),\n height: base.height,\n };\n }\n\n if (!base) {\n return { width: 0, height: measured.height };\n }\n\n return {\n width: base.width,\n height: Math.max(base.height, measured.height),\n };\n }\n\n /**\n * Returns the current text content, or an empty string if none is set.\n *\n * @returns The current text string, or \"\" if no text is set.\n */\n getText() {\n return this._options.text || \"\";\n }\n\n /**\n * Sets the text content, recalculates the preferred size, and updates the DOM element.\n *\n * @param text - The new text to display.\n *\n * @returns This component, for method chaining.\n */\n setText(text: String): this {\n this._options.text = (text || \"\") as TOptions[\"text\"];\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n let element = this.getElement();\n if (!element) {\n return this;\n }\n\n DOM.sink.apply(element, { text: text.valueOf() });\n\n return this;\n }\n\n /**\n * Enables or disables automatic text measurement on `setText`.\n *\n * @param enabled - When `false`, `setText` skips the off-screen probe and\n * leaves preferred size and baseline unchanged. Use only when\n * the parent layout (e.g. [`Fit`](/api/layout/classes/Fit)) sizes this Text from\n * the container, so the measured preferred size is unused.\n *\n * @returns This component, for method chaining.\n */\n setAutoMeasure(enabled: boolean): this {\n this._autoMeasure = enabled;\n\n return this;\n }\n\n /**\n * Returns the current CSS text-align value.\n *\n * @returns The CSS text-align string, or null if not set.\n */\n getTextAlign() {\n return this._options.textAlign ?? this._defaultOptions.textAlign ?? null;\n }\n\n /**\n * Sets the CSS text-align and updates the component's CSS rule.\n *\n * @param align - A CSS text-align value (e.g. \"left\", \"center\", \"right\").\n *\n * @returns This component, for method chaining.\n */\n setTextAlign(align: string): this {\n this._options.textAlign = align;\n\n this.setElementCSSRule(\"textAlign\", align);\n\n return this;\n }\n\n /**\n * Returns the CSS text-shadow value.\n *\n * @returns The CSS text-shadow string, or null if not set.\n */\n getTextShadow() {\n return this._options.textShadow ?? null;\n }\n\n /**\n * Sets the CSS text-shadow and updates the component's CSS rule.\n *\n * @param shadow - A CSS text-shadow value.\n *\n * @returns This component, for method chaining.\n */\n setTextShadow(shadow: string): this {\n this._options.textShadow = shadow;\n\n this.setElementCSSRule(\"textShadow\", shadow);\n\n return this;\n }\n\n /**\n * Removes the text-shadow CSS property from the component's CSS rule.\n *\n * @returns This component, for method chaining.\n */\n clearTextShadow(): this {\n if (this._options.textShadow === undefined) {\n return this;\n }\n\n this._options.textShadow = undefined;\n this.setElementCSSRule(\"textShadow\", null);\n\n return this;\n }\n\n /**\n * Returns the CSS font-family value.\n *\n * @returns The CSS font-family string, or null if not set.\n */\n getFontFamily() {\n return this._options.fontFamily ?? this._defaultOptions.fontFamily ?? null;\n }\n\n /**\n * Sets the CSS font-family, updates the rule, and recalculates preferred size.\n *\n * @param value - The CSS font-family string (e.g. \"sans-serif\", \"'Arial', sans-serif\").\n *\n * @returns This component, for method chaining.\n */\n setFontFamily(value: string): this {\n this._options.fontFamily = value;\n\n this.setElementCSSRule(\"fontFamily\", value);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the CSS font-kerning value.\n *\n * @returns The CSS font-kerning string, or null if not set.\n */\n getFontKerning() {\n return this._options.fontKerning ?? this._defaultOptions.fontKerning ?? null;\n }\n\n /**\n * Sets the CSS font-kerning and updates the component's CSS rule.\n *\n * @param value - A CSS font-kerning value (e.g. \"auto\", \"normal\", \"none\").\n *\n * @returns This component, for method chaining.\n */\n setFontKerning(value: string): this {\n this._options.fontKerning = value;\n\n this.setElementCSSRule(\"fontKerning\", value);\n\n return this;\n }\n\n /**\n * Returns the font size in pixels.\n *\n * @returns The font size as a number, or null if not set.\n */\n getFontSize() {\n return (this._options.fontSize as number | undefined) ?? (this._defaultOptions.fontSize as number | undefined) ?? null;\n }\n\n /**\n * Sets the font size. Pass a number for an explicit pixel value, or a CSS variable name\n * (e.g. `\"--ts-ui-header-font-size\"`) to bind to a theme token.\n *\n * @param value - Pixel size as a number, or a CSS custom property name as a string.\n *\n * @returns This component, for method chaining.\n */\n setFontSize(value: number | string): this {\n if (typeof value === 'number') {\n this._options.fontSize = value as TOptions[\"fontSize\"];\n this._fontSizeCSSVar = null;\n this._fontSizeCSSRule = null;\n this.setElementCSSRule(\"fontSize\", value + \"px\");\n } else {\n const fallbackPx = (this.getFontSize() as number | undefined) ?? 14;\n this._fontSizeCSSVar = value;\n this._fontSizeCSSRule = `var(${value}, ${fallbackPx}px)`;\n this.setElementCSSRule(\"fontSize\", this._fontSizeCSSRule);\n\n // Cache the resolved px so line-box/baseline math has the real size\n // even pre-attach — resolveBoundFontSizePx probes the cascade for a\n // calc()-valued token rather than parseFloat-ing its raw var string.\n const resolved = this.resolveBoundFontSizePx();\n if (resolved !== null) {\n this._options.fontSize = resolved as TOptions[\"fontSize\"];\n }\n }\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the CSS font-size-adjust value.\n *\n * @returns The CSS font-size-adjust string, or null if not set.\n */\n getFontSizeAdjust() {\n return this._options.fontSizeAdjust ?? this._defaultOptions.fontSizeAdjust ?? null;\n }\n\n /**\n * Sets the CSS font-size-adjust and updates the component's CSS rule.\n *\n * @param value - A CSS font-size-adjust value.\n *\n * @returns This component, for method chaining.\n */\n setFontSizeAdjust(value: string): this {\n this._options.fontSizeAdjust = value;\n\n this.setElementCSSRule(\"fontSizeAdjust\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-stretch value.\n *\n * @returns The CSS font-stretch string, or null if not set.\n */\n getFontStretch() {\n return this._options.fontStretch ?? this._defaultOptions.fontStretch ?? null;\n }\n\n /**\n * Sets the CSS font-stretch and updates the component's CSS rule.\n *\n * @param value - A CSS font-stretch value (e.g. \"normal\", \"condensed\", \"expanded\").\n *\n * @returns This component, for method chaining.\n */\n setFontStretch(value: string): this {\n this._options.fontStretch = value;\n\n this.setElementCSSRule(\"fontStretch\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-style value (e.g. \"normal\", \"italic\").\n *\n * @returns The CSS font-style string, or null if not set.\n */\n getFontStyle() {\n return this._options.fontStyle ?? this._defaultOptions.fontStyle ?? null;\n }\n\n /**\n * Sets the CSS font-style and updates the component's CSS rule.\n *\n * @param value - A CSS font-style value (e.g. \"normal\", \"italic\", \"oblique\").\n *\n * @returns This component, for method chaining.\n */\n setFontStyle(value: string): this {\n this._options.fontStyle = value;\n\n this.setElementCSSRule(\"fontStyle\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-variant value.\n *\n * @returns The CSS font-variant string, or null if not set.\n */\n getFontVariant() {\n return this._options.fontVariant ?? this._defaultOptions.fontVariant ?? null;\n }\n\n /**\n * Sets the CSS font-variant and updates the component's CSS rule.\n *\n * @param value - A CSS font-variant value (e.g. \"normal\", \"small-caps\").\n *\n * @returns This component, for method chaining.\n */\n setFontVariant(value: string): this {\n this._options.fontVariant = value;\n\n this.setElementCSSRule(\"fontVariant\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-weight value.\n *\n * @returns The CSS font-weight string, or null if not set.\n */\n getFontWeight() {\n return this._options.fontWeight ?? this._defaultOptions.fontWeight ?? null;\n }\n\n /**\n * Sets the CSS font-weight, updates the rule, and recalculates preferred size.\n *\n * @param value - A CSS font-weight value (e.g. \"normal\", \"bold\", \"700\").\n *\n * @returns This component, for method chaining.\n */\n setFontWeight(value: string): this {\n this._options.fontWeight = value;\n\n this.setElementCSSRule(\"fontWeight\", value);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the line height in pixels, or null if not set.\n *\n * @returns The line height as a number, or null if not set.\n */\n getLineHeight() {\n return (this._options.lineHeight as number | undefined) ?? (this._defaultOptions.lineHeight as number | undefined) ?? null;\n }\n\n /**\n * Sets the line height. Pass a number for an explicit fixed pixel value\n * (which stops tracking the theme — this is the per-control override of the\n * additive default), or a CSS variable name to bind the line box to a\n * custom token, resolved as a fixed line box for measurement.\n *\n * @param value - Pixel value as a number, or a CSS custom property name as a string.\n *\n * @returns This component, for method chaining.\n */\n setLineHeight(value: number | string): this {\n if (typeof value === 'number') {\n // Idempotent re-apply: a no-op numeric line-height must not re-arm\n // the layout flush. CellRenderer.doLayout syncs the Text child's\n // line-height to the cell height on every pass; without this guard\n // that unconditional scheduleLayout below re-dirtied the renderer\n // each frame, spinning a silent CPU-pinning relayout loop. Only skip\n // when already in pure-numeric mode with the same value (the initial\n // additive-rule state has a non-null _lineHeightCSSRule, so the first\n // apply still runs). Mirrors the framework's \"unchanged value → early\n // return before scheduleLayout\" idiom (Card.setVisibleComponentId).\n if (this._options.lineHeight === value && this._lineHeightCSSVar === null && this._lineHeightCSSRule === null) {\n return this;\n }\n\n this._options.lineHeight = value as TOptions[\"lineHeight\"];\n this._lineHeightCSSVar = null;\n this._lineHeightCSSRule = null;\n this.setElementCSSRule(\"lineHeight\", value + \"px\");\n } else {\n this._lineHeightCSSVar = value;\n this._lineHeightCSSRule = `var(${value}, ${ADDITIVE_LINE_HEIGHT_RULE})`;\n this._options.lineHeight = this.readThemeLineHeightPx() as TOptions[\"lineHeight\"];\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n }\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Sets the line-height equal to the given pixel height so a single-line\n * text sits vertically centred in a fixed-height inline box.\n *\n * @param px - Pixel value matching the container's height, or `null` to\n * revert to the theme's additive line box (font size +\n * `--ts-ui-line-padding`).\n *\n * @returns This component, for method chaining.\n *\n * @example\n * ```typescript\n * const label = new Text(\"File\");\n * label.centerInHeight(28);\n * ```\n */\n centerInHeight(px: number | null): this {\n if (px === null) {\n this._lineHeightCSSVar = null;\n this._lineHeightCSSRule = ADDITIVE_LINE_HEIGHT_RULE;\n this._options.lineHeight = this.readThemeLineHeightPx() as TOptions[\"lineHeight\"];\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n return this.setLineHeight(px);\n }\n\n /**\n * Returns the CSS text-overflow value last passed to {@link setTextOverflow},\n * or `null` if not set.\n *\n * @returns The text-overflow string, or null.\n */\n getTextOverflow(): string | null {\n return this._textOverflow;\n }\n\n /**\n * Sets the CSS text-overflow property and updates the component's CSS rule.\n *\n * @param value - A CSS text-overflow value (e.g. \"clip\", \"ellipsis\").\n *\n * @returns This component, for method chaining.\n */\n setTextOverflow(value: string): this {\n this._textOverflow = value;\n\n this.setElementCSSRule(\"textOverflow\", value);\n\n return this;\n }\n\n /**\n * Removes the text-overflow CSS property from the component's CSS rule.\n *\n * @returns This component, for method chaining.\n */\n clearTextOverflow(): this {\n if (this._textOverflow === null) {\n return this;\n }\n\n this._textOverflow = null;\n this.setElementCSSRule(\"textOverflow\", null);\n\n return this;\n }\n\n /**\n * Returns whether single-line truncation + ellipsis is enabled (default `true`).\n *\n * @returns `true` when the text clips with \"…\" once narrower than its\n * natural width; `false` when the text refuses to shrink past its\n * natural width.\n */\n isTruncate(): boolean {\n return this._truncate;\n }\n\n /**\n * Toggles single-line truncation mode. When `true`, the text renders as\n * single-line + `overflow: hidden` + `text-overflow: ellipsis` and reports\n * `minSize.width = Math.min(natural, 100)`. When `false`, those CSS\n * properties are cleared and the text reports its full natural width as\n * `minSize.width` so parent layouts widen to fit instead of clipping.\n *\n * @param value - `true` to enable ellipsised truncation, `false` to\n * disable (the text expands to its natural width).\n *\n * @returns This component, for method chaining.\n */\n setTruncate(value: boolean): this {\n this._truncate = value;\n\n if (value) {\n this.setWhiteSpace(\"nowrap\");\n this.setOverflow(\"hidden\");\n this.setTextOverflow(\"ellipsis\");\n } else {\n this.setElementCSSRule(\"whiteSpace\", null);\n this.setOverflow(\"visible\");\n this.setElementCSSRule(\"textOverflow\", null);\n this._textOverflow = null;\n }\n\n // The auto-min cap depends on `_truncate`; re-measure so the parent\n // layout sees the new floor on the next layout pass.\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the current CSS `word-break` value, or null if not set.\n *\n * @returns The word-break string, or null.\n */\n getWordBreak(): string | null {\n return this._wordBreak;\n }\n\n /**\n * Sets the CSS `word-break` property on the component's CSS rule.\n *\n * @param value - A CSS word-break value (e.g. \"break-word\", \"normal\", \"keep-all\").\n *\n * @returns This component, for method chaining.\n */\n setWordBreak(value: string): this {\n if (this._wordBreak === value) {\n return this;\n }\n\n this._wordBreak = value;\n this.setElementCSSRule(\"wordBreak\", value);\n\n return this;\n }\n\n /**\n * Returns the current line-clamp line count, or null if no clamp is applied.\n *\n * @returns The maximum line count, or null.\n */\n getLineClamp(): number | null {\n return this._lineClamp;\n }\n\n /**\n * Clamps the rendered text to a maximum line count via CSS line-clamp.\n *\n * Writes `display: -webkit-box`, `-webkit-box-orient: vertical`,\n * `-webkit-line-clamp`, `overflow: hidden`, and `text-overflow: ellipsis`\n * in a single call. Use {@link clearLineClamp} to remove the clamp.\n *\n * @param lines - The maximum number of lines to display before the ellipsis.\n *\n * @returns This component, for method chaining.\n */\n setLineClamp(lines: number): this {\n if (this._lineClamp === lines) {\n return this;\n }\n\n this._lineClamp = lines;\n this.setElementCSSRules({\n display: \"-webkit-box\",\n webkitBoxOrient: \"vertical\",\n webkitLineClamp: String(lines),\n overflow: \"hidden\",\n textOverflow: \"ellipsis\"\n });\n\n return this;\n }\n\n /**\n * Removes the line-clamp styling previously applied by {@link setLineClamp}.\n *\n * @returns This component, for method chaining.\n */\n clearLineClamp(): this {\n if (this._lineClamp === null) {\n return this;\n }\n\n this._lineClamp = null;\n this.setElementCSSRules({\n display: null,\n webkitBoxOrient: null,\n webkitLineClamp: null,\n overflow: null,\n textOverflow: null\n });\n\n return this;\n }\n\n /**\n * Applies all text-specific style properties to the element's CSS rule in addition to base styles.\n *\n * @param element - The element handle to apply styles to.\n */\n applyStyle(element: Handle): this {\n super.applyStyle(element);\n\n const fontSize = this.getFontSize();\n const lineHeight = this.getLineHeight();\n\n this.setElementCSSRules({\n fontFamily: this.getFontFamily() ?? '',\n textAlign: this.getTextAlign() ?? '',\n textShadow: this.getTextShadow() ?? '',\n fontKerning: this.getFontKerning() ?? '',\n fontSize: this._fontSizeCSSRule ?? (fontSize !== null ? `${fontSize}px` : ''),\n fontSizeAdjust: this.getFontSizeAdjust() ?? '',\n fontStretch: this.getFontStretch() ?? '',\n fontStyle: this.getFontStyle() ?? '',\n fontVariant: this.getFontVariant() ?? '',\n fontWeight: this.getFontWeight() ?? '',\n lineHeight: this._lineHeightCSSRule ?? (lineHeight !== null ? `${lineHeight}px` : '')\n });\n\n return this;\n }\n\n /**\n * Removes the theme-change listener. Call when the component is permanently removed.\n */\n dispose() {\n this._unsubscribeTheme();\n }\n\n /**\n * Renders the element and sets its text content.\n *\n * @returns The created element with textContent initialised.\n */\n protected render() {\n let element = super.render();\n\n DOM.sink.apply(element, { text: this.getText().valueOf() });\n\n return element;\n }\n}\n\nconst TextCallable = callable(Text);\ntype TextCallable<TOptions extends TextOptions = TextOptions> = Text<TOptions>;\nexport {\n Text as _Text,\n TextCallable as Text\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./DOM-DeF_dWe2.js";import{l as t}from"./Position-DJKB0N3l.js";import{f as n,n as r,t as i}from"./Component-Bs6TvaGZ.js";var a={tag:`span`,textAlign:`left`,fontKerning:`auto`,fontSize:14,fontSizeAdjust:`none`,fontStretch:`normal`,fontStyle:`normal`,fontVariant:`normal`,fontWeight:`normal`,truncate:!0},o=100,s=`calc(1em + var(--ts-ui-line-padding, 2px))`,Text=class extends i{_hasExplicitPreferredSize=!1;_fontSizeCSSVar=`--ts-ui-font-size`;_fontSizeCSSRule=`var(--ts-ui-font-size, 14px)`;_unsubscribeTheme;_lineHeightCSSVar=null;_lineHeightCSSRule=s;_measuredBaseline=null;_measuredMinSize=null;_autoMeasure=!0;_measurementDirty=!0;_wordBreak=null;_lineClamp=null;_textOverflow=null;_truncate=!0;constructor(e,t,n){super(t,{...a,...n??{}}),this._defaultOptions.fontFamily=`var(--ts-ui-font-family, system-ui, sans-serif)`,this.clearInsets(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule),this._unsubscribeTheme=r.onThemeChange(()=>{if(this._fontSizeCSSVar){let e=this.resolveBoundFontSizePx();e!==null&&(this._options.fontSize=e)}this._lineHeightCSSVar&&(this._defaultOptions.lineHeight=this.readThemeLineHeightPx()),this.calculateSize()}),e!==void 0&&this._options.text===void 0&&this.setText(e),this._measurementDirty=!0}applyOptions(e){return super.applyOptions(e),e.text!==void 0&&this.setText(e.text),e.textAlign!==void 0&&this.setTextAlign(e.textAlign),e.textShadow!==void 0&&this.setTextShadow(e.textShadow),e.fontFamily!==void 0&&this.setFontFamily(e.fontFamily),e.fontSize!==void 0&&this.setFontSize(e.fontSize),e.fontWeight!==void 0&&this.setFontWeight(e.fontWeight),e.fontStyle!==void 0&&this.setFontStyle(e.fontStyle),e.fontVariant!==void 0&&this.setFontVariant(e.fontVariant),e.fontStretch!==void 0&&this.setFontStretch(e.fontStretch),e.fontKerning!==void 0&&this.setFontKerning(e.fontKerning),e.fontSizeAdjust!==void 0&&this.setFontSizeAdjust(e.fontSizeAdjust),e.lineHeight!==void 0&&this.setLineHeight(e.lineHeight),e.textOverflow!==void 0&&this.setTextOverflow(e.textOverflow),e.whiteSpace!==void 0&&this.setWhiteSpace(e.whiteSpace),this.setTruncate(e.truncate??this._defaultOptions.truncate),this}readThemeLineHeightPx(){let n=this._options.fontSize??this._defaultOptions.fontSize??14;if(this._lineHeightCSSVar){let t=e.source.getThemeVar(this._lineHeightCSSVar),n=parseFloat(t);if(!isNaN(n))return n}return t.lineHeightPx({fontSizePx:n})}getElement(e=!1){return super.getElement(e)}resolveBoundFontSizePx(){if(!this._fontSizeCSSVar)return null;let t=parseFloat(e.source.getThemeVar(this._fontSizeCSSVar));return isNaN(t)?e.source.resolveFontSizePx(this._fontSizeCSSRule??`var(${this._fontSizeCSSVar})`):t}setPreferredSize(e,t){return this._hasExplicitPreferredSize=!0,super.setPreferredSize(e,t),this}setCalculatedSize(e,t){this._hasExplicitPreferredSize||super.setPreferredSize(e,t)}calculateSize(){if(this._measurementDirty=!1,this._defaultOptions.lineHeight===void 0&&(this._defaultOptions.lineHeight=this.readThemeLineHeightPx()),!this._autoMeasure)return;let t=this.getLineHeight()??this.readThemeLineHeightPx(),n=Math.ceil(t),r=this._options.text;if(r){let t=e.source.measureText(r.toString(),this.measureOptions()),i=this.measuredHeight(r.toString(),t.width,t.height);this._measuredBaseline=t.baseline,this.setCalculatedSize(t.width,i);let a=this._truncate?Math.min(t.width,o):t.width;this._measuredMinSize={width:a,height:Math.max(i,n)}}else this._measuredBaseline=null,this.setCalculatedSize(0,0),this._measuredMinSize={width:0,height:0}}measure(){let e=this._autoMeasure;this._autoMeasure=!0,this.calculateSize(),this._autoMeasure=e}getBaseline(){return this._measurementDirty&&this.calculateSize(),this.wrapInnerBaseline(this._measuredBaseline)}measureOptions(){let e=this.getFontSize(),t=this.getLineHeight();return{fontFamily:this.getFontFamily()??void 0,fontSize:this._fontSizeCSSRule??(e===null?void 0:`${e}px`),fontWeight:this.getFontWeight()??void 0,fontStyle:this.getFontStyle()??void 0,fontVariant:this.getFontVariant()??void 0,fontStretch:this.getFontStretch()??void 0,lineHeight:this._lineHeightCSSRule??(t===null?void 0:`${t}px`)}}isWrapping(){let e=this.getWhiteSpace();return e===`normal`||e===`pre-wrap`||e===`pre-line`||e===`break-spaces`}measuredHeight(t,n,r){if(!this.isWrapping()||this.isVerticalWritingMode())return r;let i=this.getWidth();if(Number.isNaN(i))return r;let a=this.getPerimeterSize(),o=i-a.left-a.right;if(o>=n)return r;let s=e.source.measureText(t,{...this.measureOptions(),maxWidth:o}),c=Math.ceil(this.getLineHeight()??this.readThemeLineHeightPx());return Math.max(s.height,c)}setWidth(e){let t=this.getWidth();return super.setWidth(e),this.isWrapping()&&this.getWidth()!==t&&(this._measurementDirty=!0,this.calculateSize()),this}getPreferredSize(){this._measurementDirty&&this.calculateSize();let e=super.getPreferredSize();return e&&this.isVerticalWritingMode()?{width:e.height,height:e.width}:e}isVerticalWritingMode(){let e=this.getWritingMode();return e!==null&&(e.startsWith(`vertical`)||e.startsWith(`sideways`))}getMinSize(){this._measurementDirty&&this.calculateSize();let e=this._measuredMinSize,t=super.getMinSize();return e?this.isVerticalWritingMode()?t?{width:Math.max(t.width,e.height),height:t.height}:{width:e.height,height:0}:t?{width:t.width,height:Math.max(t.height,e.height)}:{width:0,height:e.height}:t}getText(){return this._options.text||``}setText(t){this._options.text=t||``,this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout();let n=this.getElement();return n&&e.sink.apply(n,{text:t.valueOf()}),this}setAutoMeasure(e){return this._autoMeasure=e,this}getTextAlign(){return this._options.textAlign??this._defaultOptions.textAlign??null}setTextAlign(e){return this._options.textAlign=e,this.setElementCSSRule(`textAlign`,e),this}getTextShadow(){return this._options.textShadow??null}setTextShadow(e){return this._options.textShadow=e,this.setElementCSSRule(`textShadow`,e),this}clearTextShadow(){return this._options.textShadow===void 0?this:(this._options.textShadow=void 0,this.setElementCSSRule(`textShadow`,null),this)}getFontFamily(){return this._options.fontFamily??this._defaultOptions.fontFamily??null}setFontFamily(e){return this._options.fontFamily=e,this.setElementCSSRule(`fontFamily`,e),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getFontKerning(){return this._options.fontKerning??this._defaultOptions.fontKerning??null}setFontKerning(e){return this._options.fontKerning=e,this.setElementCSSRule(`fontKerning`,e),this}getFontSize(){return this._options.fontSize??this._defaultOptions.fontSize??null}setFontSize(e){if(typeof e==`number`)this._options.fontSize=e,this._fontSizeCSSVar=null,this._fontSizeCSSRule=null,this.setElementCSSRule(`fontSize`,e+`px`);else{let t=this.getFontSize()??14;this._fontSizeCSSVar=e,this._fontSizeCSSRule=`var(${e}, ${t}px)`,this.setElementCSSRule(`fontSize`,this._fontSizeCSSRule);let n=this.resolveBoundFontSizePx();n!==null&&(this._options.fontSize=n)}return this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getFontSizeAdjust(){return this._options.fontSizeAdjust??this._defaultOptions.fontSizeAdjust??null}setFontSizeAdjust(e){return this._options.fontSizeAdjust=e,this.setElementCSSRule(`fontSizeAdjust`,e),this}getFontStretch(){return this._options.fontStretch??this._defaultOptions.fontStretch??null}setFontStretch(e){return this._options.fontStretch=e,this.setElementCSSRule(`fontStretch`,e),this}getFontStyle(){return this._options.fontStyle??this._defaultOptions.fontStyle??null}setFontStyle(e){return this._options.fontStyle=e,this.setElementCSSRule(`fontStyle`,e),this}getFontVariant(){return this._options.fontVariant??this._defaultOptions.fontVariant??null}setFontVariant(e){return this._options.fontVariant=e,this.setElementCSSRule(`fontVariant`,e),this}getFontWeight(){return this._options.fontWeight??this._defaultOptions.fontWeight??null}setFontWeight(e){return this._options.fontWeight=e,this.setElementCSSRule(`fontWeight`,e),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getLineHeight(){return this._options.lineHeight??this._defaultOptions.lineHeight??null}setLineHeight(e){if(typeof e==`number`){if(this._options.lineHeight===e&&this._lineHeightCSSVar===null&&this._lineHeightCSSRule===null)return this;this._options.lineHeight=e,this._lineHeightCSSVar=null,this._lineHeightCSSRule=null,this.setElementCSSRule(`lineHeight`,e+`px`)}else this._lineHeightCSSVar=e,this._lineHeightCSSRule=`var(${e}, ${s})`,this._options.lineHeight=this.readThemeLineHeightPx(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule);return this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}centerInHeight(e){return e===null?(this._lineHeightCSSVar=null,this._lineHeightCSSRule=s,this._options.lineHeight=this.readThemeLineHeightPx(),this.setElementCSSRule(`lineHeight`,this._lineHeightCSSRule),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this):this.setLineHeight(e)}getTextOverflow(){return this._textOverflow}setTextOverflow(e){return this._textOverflow=e,this.setElementCSSRule(`textOverflow`,e),this}clearTextOverflow(){return this._textOverflow===null?this:(this._textOverflow=null,this.setElementCSSRule(`textOverflow`,null),this)}isTruncate(){return this._truncate}setTruncate(e){return this._truncate=e,e?(this.setWhiteSpace(`nowrap`),this.setOverflow(`hidden`),this.setTextOverflow(`ellipsis`)):(this.setElementCSSRule(`whiteSpace`,null),this.setOverflow(`visible`),this.setElementCSSRule(`textOverflow`,null),this._textOverflow=null),this._measurementDirty=!0,(this.getParentComponent()??this).scheduleLayout(),this}getWordBreak(){return this._wordBreak}setWordBreak(e){return this._wordBreak===e?this:(this._wordBreak=e,this.setElementCSSRule(`wordBreak`,e),this)}getLineClamp(){return this._lineClamp}setLineClamp(e){return this._lineClamp===e?this:(this._lineClamp=e,this.setElementCSSRules({display:`-webkit-box`,webkitBoxOrient:`vertical`,webkitLineClamp:String(e),overflow:`hidden`,textOverflow:`ellipsis`}),this)}clearLineClamp(){return this._lineClamp===null?this:(this._lineClamp=null,this.setElementCSSRules({display:null,webkitBoxOrient:null,webkitLineClamp:null,overflow:null,textOverflow:null}),this)}applyStyle(e){super.applyStyle(e);let t=this.getFontSize(),n=this.getLineHeight();return this.setElementCSSRules({fontFamily:this.getFontFamily()??``,textAlign:this.getTextAlign()??``,textShadow:this.getTextShadow()??``,fontKerning:this.getFontKerning()??``,fontSize:this._fontSizeCSSRule??(t===null?``:`${t}px`),fontSizeAdjust:this.getFontSizeAdjust()??``,fontStretch:this.getFontStretch()??``,fontStyle:this.getFontStyle()??``,fontVariant:this.getFontVariant()??``,fontWeight:this.getFontWeight()??``,lineHeight:this._lineHeightCSSRule??(n===null?``:`${n}px`)}),this}dispose(){this._unsubscribeTheme()}render(){let t=super.render();return e.sink.apply(t,{text:this.getText().valueOf()}),t}},c=n(Text);export{c as t};
|
|
2
|
-
//# sourceMappingURL=Text-DJoUHukb.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Text-DJoUHukb.js","names":[],"sources":["../../src/typescript/lib/component/input/Text.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { ThemeManager } from \"~/core/Theme.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { Util } from \"~/core/Util.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Text}.\n *\n * @category Components\n */\nexport interface TextOptions extends ComponentOptions {\n tag?: string;\n text?: string;\n textAlign?: string;\n textShadow?: string;\n fontFamily?: string;\n fontSize?: number | string;\n fontWeight?: string;\n fontStyle?: string;\n fontVariant?: string;\n fontStretch?: string;\n fontKerning?: string;\n fontSizeAdjust?: string;\n lineHeight?: number | string;\n textOverflow?: string;\n whiteSpace?: string;\n /**\n * When `true` (default), the text is single-line + clipped + ellipsised\n * when its rendered width is below its natural width, and `minSize.width`\n * is capped at `100` so parent layouts can shrink the text past its\n * natural width.\n *\n * When `false`, no ellipsis is applied and `minSize.width` reports the\n * full natural width — the text refuses to be squeezed, forcing the\n * parent to widen (used by [`Button`](/api/component/button/classes/Button)\n * for the label so the button grows to fit its text instead of clipping).\n */\n truncate?: boolean;\n}\n\n/**\n * Module-level class defaults forwarded to `super` via the options bag so the\n * `applyOptions` cascade dispatches each setter once with the final value.\n *\n * `fontFamily` and `lineHeight` are intentionally **omitted**:\n *\n * - `fontFamily` must remain a getter-fallback only. Routing it through\n * `setFontFamily(...)` would write the literal `var(--ts-ui-font-family, …)`\n * onto every Text's CSS rule, blocking a parent's `font-family` override\n * from cascading through.\n * - `lineHeight` is theme-derived (`readThemeLineHeightPx()`), so the value\n * isn't known at module load. It is resolved lazily on first\n * `calculateSize()` (post-attach), keeping construction JS-only per\n * ARCHITECTURE.md \"Defer DOM work to render time\".\n */\nconst _defaultTextOptions: Partial<TextOptions> = {\n tag: \"span\",\n textAlign: \"left\",\n fontKerning: \"auto\",\n fontSize: 14,\n fontSizeAdjust: \"none\",\n fontStretch: \"normal\",\n fontStyle: \"normal\",\n fontVariant: \"normal\",\n fontWeight: \"normal\",\n truncate: true,\n};\n\n// Upper bound for the auto-derived `minSize.width` from text measurement —\n// short labels report their full measured width (so they're never truncated\n// when the container has room), longer text caps here so the parent layout\n// always has room to shrink the Text below its natural width.\nconst TEXT_AUTO_MIN_WIDTH_CAP_PX = 100;\n\n// Default theme-tracking line-height rule: the control's own font size plus the\n// `--ts-ui-line-padding` leading, so the line box scales per font size. `1em`\n// resolves against the element's own font-size at both render and measure time.\n// `2px` is the shipped `--ts-ui-line-padding` default, used only if the var is\n// absent. A control overrides this with an explicit px via `setLineHeight`.\nconst ADDITIVE_LINE_HEIGHT_RULE = \"calc(1em + var(--ts-ui-line-padding, 2px))\";\n\n/**\n * A text-displaying component with comprehensive font and layout controls.\n *\n * Uses an off-screen probe element to measure text dimensions and automatically\n * updates the preferred size whenever the text or a font property changes.\n *\n * `Text` subscribes to {@link ThemeManager} on construction so it re-measures itself\n * on every theme change. Components that create `Text` instances dynamically and\n * remove them from the page should call `text.dispose()` to detach the listener.\n *\n * @category Components\n */\nclass Text<TOptions extends TextOptions = TextOptions> extends Component<TOptions> {\n\n private _hasExplicitPreferredSize: boolean = false;\n private _fontSizeCSSVar : string | null = \"--ts-ui-font-size\";\n private _fontSizeCSSRule: string | null = \"var(--ts-ui-font-size, 14px)\";\n private readonly _unsubscribeTheme: () => void;\n private _lineHeightCSSVar : string | null = null;\n private _lineHeightCSSRule: string | null = ADDITIVE_LINE_HEIGHT_RULE;\n private _measuredBaseline: number | null = null;\n private _measuredMinSize: Size | null = null;\n private _autoMeasure: boolean = true;\n private _measurementDirty: boolean = true;\n private _wordBreak: string | null = null;\n private _lineClamp: number | null = null;\n private _textOverflow: string | null = null;\n private _truncate: boolean = true;\n\n // `NoInfer` on `options` keeps a partial options literal from narrowing\n // TOptions to just the keys it carries: `new Text(\"x\", { fontWeight: \"600\" })`\n // must stay a `Text<TextOptions>` (assignable to Component), not a\n // `Text<{ fontWeight: string }>` (whose narrowed option type is not). Subclasses\n // still fix TOptions through `extends Text<MyOptions>`, not argument inference.\n constructor(text?: String, options?: NoInfer<TOptions>, subclassDefaults?: Partial<TOptions>) {\n super(\n options,\n { ..._defaultTextOptions, ...(subclassDefaults ?? {}) } as Partial<TOptions>,\n );\n\n // Carve-out fallbacks — see `_defaultTextOptions` for why these two\n // don't ride the merge-defaults cascade. Both are consulted by their\n // getters as a fallback when `_options.X` is undefined.\n //\n // Note: the cascade-driven `setFontSize(14)` clobbers `fontSizeCSSVar`\n // and `fontSizeCSSRule` to null, but Text's field initializers (which\n // run after super returns) restore both to their var-binding values —\n // so theme reactivity is preserved by the DOM `var(...)` binding even\n // though the cascade temporarily writes a literal.\n //\n // `_defaultOptions.lineHeight` is resolved lazily on first\n // `calculateSize()` (post-attach) — see ARCHITECTURE.md \"Defer DOM\n // work to render time\".\n this._defaultOptions.fontFamily = \"var(--ts-ui-font-family, system-ui, sans-serif)\";\n\n this.clearInsets();\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n\n this._unsubscribeTheme = ThemeManager.onThemeChange(() => {\n if (this._fontSizeCSSVar) {\n // Resolve from the element's computed font-size (the cascade has\n // applied the new var by the time onThemeChange fires); the root\n // custom property reads back as an unevaluated calc() string.\n const resolved = this.resolveBoundFontSizePx();\n\n if (resolved !== null) {\n // Route to `_options` so the post-cascade explicit value\n // (set by `setFontSize(14)` during applyOptions) is\n // overwritten on theme change. Writing to `_defaultOptions`\n // here would be shadowed by `_options.fontSize = 14` in\n // the `getFontSize` fallback, breaking re-flow.\n this._options.fontSize = resolved as TOptions[\"fontSize\"];\n }\n }\n\n if (this._lineHeightCSSVar) {\n this._defaultOptions.lineHeight = this.readThemeLineHeightPx();\n }\n\n this.calculateSize();\n });\n\n // Positional `text` constructor argument: write to the bag only when\n // the caller didn't also pass `options.text` (which would have been\n // dispatched via super's applyOptions cascade and should win).\n if (text !== undefined && this._options.text === undefined) {\n this.setText(text);\n }\n\n // Off-screen text measurement is deferred until the first\n // getPreferredSize / getBaseline call so construction stays JS-only\n // (no forced layout from `DOM.source.measureText`).\n this._measurementDirty = true;\n }\n\n /**\n * Applies a {@link TextOptions} bag to this component, dispatching font and\n * text properties to their corresponding setters after the inherited\n * Component fields have been applied.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: TOptions): this {\n super.applyOptions(options);\n\n // Dispatch only caller-supplied values. Class-level font defaults (e.g.\n // the 14px size, a subclass's bold weight) are resolved lazily by the\n // font getters' `_defaultOptions` fallback, which `applyStyle` re-reads\n // at render — so they never enter `_options`.\n if (options.text !== undefined) {\n this.setText(options.text);\n }\n\n if (options.textAlign !== undefined) {\n this.setTextAlign(options.textAlign);\n }\n\n if (options.textShadow !== undefined) {\n this.setTextShadow(options.textShadow);\n }\n\n if (options.fontFamily !== undefined) {\n this.setFontFamily(options.fontFamily);\n }\n\n if (options.fontSize !== undefined) {\n this.setFontSize(options.fontSize);\n }\n\n if (options.fontWeight !== undefined) {\n this.setFontWeight(options.fontWeight);\n }\n\n if (options.fontStyle !== undefined) {\n this.setFontStyle(options.fontStyle);\n }\n\n if (options.fontVariant !== undefined) {\n this.setFontVariant(options.fontVariant);\n }\n\n if (options.fontStretch !== undefined) {\n this.setFontStretch(options.fontStretch);\n }\n\n if (options.fontKerning !== undefined) {\n this.setFontKerning(options.fontKerning);\n }\n\n if (options.fontSizeAdjust !== undefined) {\n this.setFontSizeAdjust(options.fontSizeAdjust);\n }\n\n if (options.lineHeight !== undefined) {\n this.setLineHeight(options.lineHeight);\n }\n\n if (options.textOverflow !== undefined) {\n this.setTextOverflow(options.textOverflow);\n }\n\n if (options.whiteSpace !== undefined) {\n this.setWhiteSpace(options.whiteSpace);\n }\n\n // `truncate` carries a class default (true) and applies its CSS\n // (white-space / overflow / text-overflow) imperatively via the setter\n // with no render re-read, so always dispatch the caller value or the\n // default — otherwise a default-truncating Text never gets the CSS.\n this.setTruncate(options.truncate ?? this._defaultOptions.truncate!);\n\n return this;\n }\n\n /**\n * Resolves this `Text`'s line box height in pixels under the additive\n * leading model.\n *\n * @returns `Util.lineHeightPx(fontSize)` — the control's own font size plus\n * the `--ts-ui-line-padding` leading — for the default theme-tracking case.\n * A legacy custom line-height var binding resolves that var as a fixed line\n * box instead, falling back to the additive value when it is unparseable.\n *\n * @remarks `_options.fontSize` is always a resolved px number here (a CSS\n * var passed to `setFontSize` is resolved and stored as a number), so the\n * leading scales with the control's actual font size — a 12px button title\n * and a 14px label get proportionate line boxes from the one token. This is\n * the same arithmetic `Util.lineHeightPx` applies for input box heights, so\n * a `Text` measures and renders at the line height a sibling input expects.\n */\n private readThemeLineHeightPx(): number {\n // `_options.fontSize` is the resolved px the bound var evaluates to —\n // `setFontSize`/`onThemeChange` populate it through the probe-backed\n // `resolveBoundFontSizePx`, so it is correct even pre-attach (a calc()\n // token included). No element read here: a parent reads this at\n // construction, before this Text's own element is styled.\n const fs = (this._options.fontSize as number | undefined) ?? (this._defaultOptions.fontSize as number | undefined) ?? 14;\n\n if (this._lineHeightCSSVar) {\n const raw = DOM.source.getThemeVar(this._lineHeightCSSVar);\n const parsed = parseFloat(raw);\n\n if (!isNaN(parsed)) {\n return parsed;\n }\n }\n\n return Util.lineHeightPx({ fontSizePx: fs });\n }\n\n /**\n * Returns the DOM element handle.\n *\n * @param createIfMissing - Optional. When true, renders the element if it does not yet exist.\n *\n * @returns The component's element handle.\n */\n getElement(createIfMissing: boolean = false): Handle | undefined {\n return super.getElement(createIfMissing);\n }\n\n /**\n * Resolves the bound font-size var to a px number. A simple var (e.g. the\n * `--ts-ui-font-size` base) parses straight off the document root; a relative\n * font token's var holds a `calc(...)` that `getPropertyValue` returns\n * unevaluated (so `parseFloat` reads `NaN`), so it falls back to a\n * cascade-evaluating probe via `DOM.source.resolveFontSizePx`. The probe path\n * works **pre-attach** — before this component's own element is styled —\n * which is when a parent (e.g. a `Header`) first reads the line-box size.\n *\n * @returns The resolved font size in px, or `null` when no var is bound (an\n * explicit numeric size was set instead) — callers keep the cached number.\n */\n private resolveBoundFontSizePx(): number | null {\n if (!this._fontSizeCSSVar) return null; // explicit px size — no var bound\n\n const raw = parseFloat(DOM.source.getThemeVar(this._fontSizeCSSVar));\n if (!isNaN(raw)) return raw; // simple var — cheap, no probe\n\n return DOM.source.resolveFontSizePx(this._fontSizeCSSRule ?? `var(${this._fontSizeCSSVar})`);\n }\n\n /**\n * Sets the preferred size from an explicit caller, locking it against automatic recalculation.\n *\n * @returns This component, for method chaining.\n */\n setPreferredSize(width: number, height: number): this {\n this._hasExplicitPreferredSize = true;\n super.setPreferredSize(width, height);\n\n return this;\n }\n\n /**\n * Updates the preferred size from a measurement only when no explicit size has been set.\n */\n private setCalculatedSize(width: number, height: number): void {\n if (!this._hasExplicitPreferredSize) {\n super.setPreferredSize(width, height);\n }\n }\n\n /**\n * Measures the text using an off-screen probe element and sets the preferred size.\n *\n * @remarks Creates a temporary fixed-positioned invisible `<span>`, appends it to the body\n * to obtain its bounding rect, then removes it. Sets preferred size to (0, 0) when no text is set.\n * No-op when {@link setAutoMeasure} is `false` — the parent layout is expected to size this Text.\n */\n private calculateSize(): void {\n this._measurementDirty = false;\n\n // First-read deferral: populate the default line-height the first\n // time we measure, when the component is attached and\n // `getComputedStyle` is safe. Subsequent reads come through the\n // `ThemeManager.onThemeChange` callback above. Placed before the\n // `_autoMeasure` gate so non-measuring `Text` instances still get\n // a resolved value populated for `getLineHeight()` callers.\n if (this._defaultOptions.lineHeight === undefined) {\n this._defaultOptions.lineHeight = this.readThemeLineHeightPx();\n }\n\n if (!this._autoMeasure) {\n return;\n }\n\n // Floor the reported minimum height to one line so a single-line label\n // is never squeezed below its line box (the measured height is 0 for\n // empty text and unset before the first probe).\n const lineHeightPx = this.getLineHeight() ?? this.readThemeLineHeightPx();\n const minLineHeight = Math.ceil(lineHeightPx);\n\n const text = this._options.text;\n if (text) {\n // Natural (single-line) measurement establishes the preferred WIDTH\n // and the baseline; the height then follows the box's current width,\n // growing when a wrapping run has been laid out narrower than natural.\n const natural = DOM.source.measureText(text.toString(), this.measureOptions());\n const height = this.measuredHeight(text.toString(), natural.width, natural.height);\n\n this._measuredBaseline = natural.baseline;\n this.setCalculatedSize(natural.width, height);\n // Store the measured floor as per-instance derived state (like\n // `_measuredBaseline`), kept out of `_defaultOptions`, which holds\n // the class-level Text defaults rather than per-instance\n // measurements. `getMinSize` folds this into the inherited min.\n // When truncation is disabled, report the full natural width so the\n // parent layout widens to fit instead of squeezing the text;\n // otherwise cap it so the parent can shrink the text past its\n // natural width.\n const autoMinWidth = this._truncate\n ? Math.min(natural.width, TEXT_AUTO_MIN_WIDTH_CAP_PX)\n : natural.width;\n this._measuredMinSize = {\n width: autoMinWidth,\n height: Math.max(height, minLineHeight),\n };\n } else {\n // No glyphs means no baseline — report null so HBox doesn't try\n // to baseline-align surrounding components against an empty box.\n // Reserve no line height either: an empty Text (e.g. the label slot\n // of an icon-only button) must collapse so it doesn't inflate the\n // container and knock the icon off-centre. The one-line floor only\n // applies once there is text to keep on its line.\n this._measuredBaseline = null;\n this.setCalculatedSize(0, 0);\n this._measuredMinSize = { width: 0, height: 0 };\n }\n }\n\n /**\n * Forces a one-off text measurement that ignores {@link setAutoMeasure}.\n * Use when the caller has opted out of auto-measure but needs an up-to-date\n * preferred size after a programmatic text change.\n */\n measure(): void {\n const wasAuto = this._autoMeasure;\n this._autoMeasure = true;\n this.calculateSize();\n this._autoMeasure = wasAuto;\n }\n\n /**\n * Returns the visual baseline of the rendered text, accounting for any\n * border, padding, or framework insets on this component.\n *\n * @returns The baseline offset from the component's outer top, in pixels,\n * or `null` when no text has been measured yet.\n *\n * @remarks Forces a measurement when the cached value is stale — the\n * off-screen probe is deferred from construction so first-call timing\n * shifts to whoever asks for a size first (usually `doLayout`).\n */\n getBaseline(): number | null {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n return this.wrapInnerBaseline(this._measuredBaseline);\n }\n\n /**\n * Builds the font/line-height option bag for a {@link DOM.measureText} probe\n * from this Text's resolved styling. Shared by the natural (single-line)\n * measurement and the wrap-aware height re-measurement in\n * {@link measuredHeight}, which adds a `maxWidth`.\n *\n * @returns The measure options (font family/size/weight/style/variant/stretch\n * and line height), each `undefined` when unset so the probe's own default\n * applies.\n */\n private measureOptions() {\n const fontSize = this.getFontSize();\n const lineHeight = this.getLineHeight();\n\n return {\n fontFamily : this.getFontFamily() ?? undefined,\n fontSize : this._fontSizeCSSRule ?? (fontSize !== null ? `${fontSize}px` : undefined),\n fontWeight : this.getFontWeight() ?? undefined,\n fontStyle : this.getFontStyle() ?? undefined,\n fontVariant: this.getFontVariant() ?? undefined,\n fontStretch: this.getFontStretch() ?? undefined,\n lineHeight : this._lineHeightCSSRule ?? (lineHeight !== null ? `${lineHeight}px` : undefined),\n };\n }\n\n /**\n * Whether this Text wraps onto multiple lines — i.e. its `white-space` is a\n * wrapping value rather than `nowrap`/`pre`. Only a wrapping Text's height\n * depends on the width it is given.\n *\n * @returns `true` when the text soft-wraps at its box width.\n */\n private isWrapping(): boolean {\n const ws = this.getWhiteSpace();\n\n return ws === \"normal\" || ws === \"pre-wrap\" || ws === \"pre-line\" || ws === \"break-spaces\";\n }\n\n /**\n * The height the text needs given its current laid-out width.\n *\n * A `nowrap` label — or one not yet given a width, or in a vertical writing\n * mode — is width-independent, so its natural single-line height stands. A\n * wrapping label whose box is narrower than its natural run re-measures at\n * the current inner width (its own border/insets removed): the extra lines\n * make it taller. The re-measure uses the same line-height as the render, so\n * the reported height matches what is drawn — line-height is the per-line\n * unit the whole calculation stacks.\n *\n * @param text - The text run being measured.\n * @param naturalWidth - The natural single-line width (nowrap), the wrap threshold.\n * @param naturalHeight - The natural single-line height, used when it does not wrap.\n * @returns The height (px) at the current width; floored at one line.\n */\n private measuredHeight(text: string, naturalWidth: number, naturalHeight: number): number {\n if (!this.isWrapping() || this.isVerticalWritingMode()) {\n return naturalHeight;\n }\n\n const width = this.getWidth();\n\n if (Number.isNaN(width)) {\n return naturalHeight;\n }\n\n const perimeter = this.getPerimeterSize();\n const innerWidth = width - perimeter.left - perimeter.right;\n\n // Wide enough for the whole run on one line → no wrapping; keep the exact\n // single-line height and skip a redundant probe.\n if (innerWidth >= naturalWidth) {\n return naturalHeight;\n }\n\n const wrapped = DOM.source.measureText(text, { ...this.measureOptions(), maxWidth: innerWidth });\n const minLineHeight = Math.ceil(this.getLineHeight() ?? this.readThemeLineHeightPx());\n\n return Math.max(wrapped.height, minLineHeight);\n }\n\n /**\n * Sets the laid-out width and, for a wrapping Text, re-measures at the new\n * width so its preferred height tracks the number of wrapped lines.\n *\n * A wrapping run's height depends on the width it is given, but the\n * preferred-size protocol resolves heights bottom-up before widths are\n * assigned top-down — so the height is only knowable once the box has a\n * width. Re-measuring here updates the preferred height, and\n * `Component.setPreferredSize` fires the ancestor notify, so the parent\n * re-lays-out one pass later at the taller height (the box's own min height\n * also rises, so the current pass already reserves the room rather than\n * clipping). A `nowrap` label's height is width-independent, so its width\n * changes need no re-measure. Idempotent once the width settles: an\n * unchanged width re-measures to the same height and the notify is suppressed.\n *\n * @param width - The new outer width in pixels.\n * @returns This component, for chaining.\n */\n override setWidth(width: number): this {\n const previous = this.getWidth();\n\n super.setWidth(width);\n\n if (this.isWrapping() && this.getWidth() !== previous) {\n this._measurementDirty = true;\n // Re-measure now (at the new width) so the updated preferred height\n // propagates before the next layout pass reads it.\n this.calculateSize();\n }\n\n return this;\n }\n\n /**\n * Returns the preferred size, lazily measuring the text on the first call.\n *\n * @returns The preferred Size, or `null` per the inherited contract.\n *\n * @remarks Construction no longer eagerly probes `document.body` for text\n * dimensions; the first reader of the preferred size pays the measurement\n * cost. After attach this is `doLayout`, so the probe happens at layout\n * time rather than construction time.\n */\n getPreferredSize() {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n const size = super.getPreferredSize();\n\n // `measureTextMetrics` always measures the run horizontally. A vertical\n // writing mode rotates it onto the block axis, so the natural text length\n // becomes the height and the line box becomes the width — swap to report\n // the on-screen extents.\n if (size && this.isVerticalWritingMode()) {\n return { width: size.height, height: size.width };\n }\n\n return size;\n }\n\n /**\n * Whether the active {@link Component.setWritingMode | writing mode} rotates\n * the text run onto the block (vertical) axis, so the measured horizontal\n * extents must be swapped to describe the on-screen size.\n *\n * @returns `true` for a `vertical-*` or `sideways-*` writing mode.\n */\n private isVerticalWritingMode(): boolean {\n const mode = this.getWritingMode();\n\n return mode !== null && (mode.startsWith(\"vertical\") || mode.startsWith(\"sideways\"));\n }\n\n /**\n * Returns the effective minimum size, folding the measured one-line height\n * floor (from `calculateSize`) into the inherited component/layout minimum.\n *\n * @returns The minimum `{width, height}`, never shorter than one line of\n * text, or `null` only when neither a measurement nor an inherited minimum\n * exists.\n *\n * @remarks Only the **height** floor participates in the hard minimum —\n * text cannot render below its line box without clipping. The measured\n * width is deliberately *not* folded in: surfacing each label's natural\n * width as a hard minimum would stop parent layouts (e.g. an equal-mode tab\n * bar) from compressing short labels to fit, which is why `Text.minSize`\n * has historically reported a zero width. The floor is per-instance derived\n * state held in `_measuredMinSize`, not a class default, so it lives outside\n * `_defaultOptions`. An explicit caller `setMinSize` taller than the floor\n * still wins via `Math.max`; a value shorter than one line is lifted to it.\n */\n getMinSize(): Size | null {\n if (this._measurementDirty) {\n this.calculateSize();\n }\n\n const measured = this._measuredMinSize;\n const base = super.getMinSize();\n\n if (!measured) {\n return base;\n }\n\n // Vertical writing mode: the one-line floor guards the line *thickness*,\n // which is now the width rather than the height (the length runs down the\n // block axis and stays freely compressible).\n if (this.isVerticalWritingMode()) {\n if (!base) {\n return { width: measured.height, height: 0 };\n }\n\n return {\n width: Math.max(base.width, measured.height),\n height: base.height,\n };\n }\n\n if (!base) {\n return { width: 0, height: measured.height };\n }\n\n return {\n width: base.width,\n height: Math.max(base.height, measured.height),\n };\n }\n\n /**\n * Returns the current text content, or an empty string if none is set.\n *\n * @returns The current text string, or \"\" if no text is set.\n */\n getText() {\n return this._options.text || \"\";\n }\n\n /**\n * Sets the text content, recalculates the preferred size, and updates the DOM element.\n *\n * @param text - The new text to display.\n *\n * @returns This component, for method chaining.\n */\n setText(text: String): this {\n this._options.text = (text || \"\") as TOptions[\"text\"];\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n let element = this.getElement();\n if (!element) {\n return this;\n }\n\n DOM.sink.apply(element, { text: text.valueOf() });\n\n return this;\n }\n\n /**\n * Enables or disables automatic text measurement on `setText`.\n *\n * @param enabled - When `false`, `setText` skips the off-screen probe and\n * leaves preferred size and baseline unchanged. Use only when\n * the parent layout (e.g. [`Fit`](/api/layout/classes/Fit)) sizes this Text from\n * the container, so the measured preferred size is unused.\n *\n * @returns This component, for method chaining.\n */\n setAutoMeasure(enabled: boolean): this {\n this._autoMeasure = enabled;\n\n return this;\n }\n\n /**\n * Returns the current CSS text-align value.\n *\n * @returns The CSS text-align string, or null if not set.\n */\n getTextAlign() {\n return this._options.textAlign ?? this._defaultOptions.textAlign ?? null;\n }\n\n /**\n * Sets the CSS text-align and updates the component's CSS rule.\n *\n * @param align - A CSS text-align value (e.g. \"left\", \"center\", \"right\").\n *\n * @returns This component, for method chaining.\n */\n setTextAlign(align: string): this {\n this._options.textAlign = align;\n\n this.setElementCSSRule(\"textAlign\", align);\n\n return this;\n }\n\n /**\n * Returns the CSS text-shadow value.\n *\n * @returns The CSS text-shadow string, or null if not set.\n */\n getTextShadow() {\n return this._options.textShadow ?? null;\n }\n\n /**\n * Sets the CSS text-shadow and updates the component's CSS rule.\n *\n * @param shadow - A CSS text-shadow value.\n *\n * @returns This component, for method chaining.\n */\n setTextShadow(shadow: string): this {\n this._options.textShadow = shadow;\n\n this.setElementCSSRule(\"textShadow\", shadow);\n\n return this;\n }\n\n /**\n * Removes the text-shadow CSS property from the component's CSS rule.\n *\n * @returns This component, for method chaining.\n */\n clearTextShadow(): this {\n if (this._options.textShadow === undefined) {\n return this;\n }\n\n this._options.textShadow = undefined;\n this.setElementCSSRule(\"textShadow\", null);\n\n return this;\n }\n\n /**\n * Returns the CSS font-family value.\n *\n * @returns The CSS font-family string, or null if not set.\n */\n getFontFamily() {\n return this._options.fontFamily ?? this._defaultOptions.fontFamily ?? null;\n }\n\n /**\n * Sets the CSS font-family, updates the rule, and recalculates preferred size.\n *\n * @param value - The CSS font-family string (e.g. \"sans-serif\", \"'Arial', sans-serif\").\n *\n * @returns This component, for method chaining.\n */\n setFontFamily(value: string): this {\n this._options.fontFamily = value;\n\n this.setElementCSSRule(\"fontFamily\", value);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the CSS font-kerning value.\n *\n * @returns The CSS font-kerning string, or null if not set.\n */\n getFontKerning() {\n return this._options.fontKerning ?? this._defaultOptions.fontKerning ?? null;\n }\n\n /**\n * Sets the CSS font-kerning and updates the component's CSS rule.\n *\n * @param value - A CSS font-kerning value (e.g. \"auto\", \"normal\", \"none\").\n *\n * @returns This component, for method chaining.\n */\n setFontKerning(value: string): this {\n this._options.fontKerning = value;\n\n this.setElementCSSRule(\"fontKerning\", value);\n\n return this;\n }\n\n /**\n * Returns the font size in pixels.\n *\n * @returns The font size as a number, or null if not set.\n */\n getFontSize() {\n return (this._options.fontSize as number | undefined) ?? (this._defaultOptions.fontSize as number | undefined) ?? null;\n }\n\n /**\n * Sets the font size. Pass a number for an explicit pixel value, or a CSS variable name\n * (e.g. `\"--ts-ui-header-font-size\"`) to bind to a theme token.\n *\n * @param value - Pixel size as a number, or a CSS custom property name as a string.\n *\n * @returns This component, for method chaining.\n */\n setFontSize(value: number | string): this {\n if (typeof value === 'number') {\n this._options.fontSize = value as TOptions[\"fontSize\"];\n this._fontSizeCSSVar = null;\n this._fontSizeCSSRule = null;\n this.setElementCSSRule(\"fontSize\", value + \"px\");\n } else {\n const fallbackPx = (this.getFontSize() as number | undefined) ?? 14;\n this._fontSizeCSSVar = value;\n this._fontSizeCSSRule = `var(${value}, ${fallbackPx}px)`;\n this.setElementCSSRule(\"fontSize\", this._fontSizeCSSRule);\n\n // Cache the resolved px so line-box/baseline math has the real size\n // even pre-attach — resolveBoundFontSizePx probes the cascade for a\n // calc()-valued token rather than parseFloat-ing its raw var string.\n const resolved = this.resolveBoundFontSizePx();\n if (resolved !== null) {\n this._options.fontSize = resolved as TOptions[\"fontSize\"];\n }\n }\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the CSS font-size-adjust value.\n *\n * @returns The CSS font-size-adjust string, or null if not set.\n */\n getFontSizeAdjust() {\n return this._options.fontSizeAdjust ?? this._defaultOptions.fontSizeAdjust ?? null;\n }\n\n /**\n * Sets the CSS font-size-adjust and updates the component's CSS rule.\n *\n * @param value - A CSS font-size-adjust value.\n *\n * @returns This component, for method chaining.\n */\n setFontSizeAdjust(value: string): this {\n this._options.fontSizeAdjust = value;\n\n this.setElementCSSRule(\"fontSizeAdjust\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-stretch value.\n *\n * @returns The CSS font-stretch string, or null if not set.\n */\n getFontStretch() {\n return this._options.fontStretch ?? this._defaultOptions.fontStretch ?? null;\n }\n\n /**\n * Sets the CSS font-stretch and updates the component's CSS rule.\n *\n * @param value - A CSS font-stretch value (e.g. \"normal\", \"condensed\", \"expanded\").\n *\n * @returns This component, for method chaining.\n */\n setFontStretch(value: string): this {\n this._options.fontStretch = value;\n\n this.setElementCSSRule(\"fontStretch\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-style value (e.g. \"normal\", \"italic\").\n *\n * @returns The CSS font-style string, or null if not set.\n */\n getFontStyle() {\n return this._options.fontStyle ?? this._defaultOptions.fontStyle ?? null;\n }\n\n /**\n * Sets the CSS font-style and updates the component's CSS rule.\n *\n * @param value - A CSS font-style value (e.g. \"normal\", \"italic\", \"oblique\").\n *\n * @returns This component, for method chaining.\n */\n setFontStyle(value: string): this {\n this._options.fontStyle = value;\n\n this.setElementCSSRule(\"fontStyle\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-variant value.\n *\n * @returns The CSS font-variant string, or null if not set.\n */\n getFontVariant() {\n return this._options.fontVariant ?? this._defaultOptions.fontVariant ?? null;\n }\n\n /**\n * Sets the CSS font-variant and updates the component's CSS rule.\n *\n * @param value - A CSS font-variant value (e.g. \"normal\", \"small-caps\").\n *\n * @returns This component, for method chaining.\n */\n setFontVariant(value: string): this {\n this._options.fontVariant = value;\n\n this.setElementCSSRule(\"fontVariant\", value);\n\n return this;\n }\n\n /**\n * Returns the CSS font-weight value.\n *\n * @returns The CSS font-weight string, or null if not set.\n */\n getFontWeight() {\n return this._options.fontWeight ?? this._defaultOptions.fontWeight ?? null;\n }\n\n /**\n * Sets the CSS font-weight, updates the rule, and recalculates preferred size.\n *\n * @param value - A CSS font-weight value (e.g. \"normal\", \"bold\", \"700\").\n *\n * @returns This component, for method chaining.\n */\n setFontWeight(value: string): this {\n this._options.fontWeight = value;\n\n this.setElementCSSRule(\"fontWeight\", value);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the line height in pixels, or null if not set.\n *\n * @returns The line height as a number, or null if not set.\n */\n getLineHeight() {\n return (this._options.lineHeight as number | undefined) ?? (this._defaultOptions.lineHeight as number | undefined) ?? null;\n }\n\n /**\n * Sets the line height. Pass a number for an explicit fixed pixel value\n * (which stops tracking the theme — this is the per-control override of the\n * additive default), or a CSS variable name to bind the line box to a\n * custom token, resolved as a fixed line box for measurement.\n *\n * @param value - Pixel value as a number, or a CSS custom property name as a string.\n *\n * @returns This component, for method chaining.\n */\n setLineHeight(value: number | string): this {\n if (typeof value === 'number') {\n // Idempotent re-apply: a no-op numeric line-height must not re-arm\n // the layout flush. CellRenderer.doLayout syncs the Text child's\n // line-height to the cell height on every pass; without this guard\n // that unconditional scheduleLayout below re-dirtied the renderer\n // each frame, spinning a silent CPU-pinning relayout loop. Only skip\n // when already in pure-numeric mode with the same value (the initial\n // additive-rule state has a non-null _lineHeightCSSRule, so the first\n // apply still runs). Mirrors the framework's \"unchanged value → early\n // return before scheduleLayout\" idiom (Card.setVisibleComponentId).\n if (this._options.lineHeight === value && this._lineHeightCSSVar === null && this._lineHeightCSSRule === null) {\n return this;\n }\n\n this._options.lineHeight = value as TOptions[\"lineHeight\"];\n this._lineHeightCSSVar = null;\n this._lineHeightCSSRule = null;\n this.setElementCSSRule(\"lineHeight\", value + \"px\");\n } else {\n this._lineHeightCSSVar = value;\n this._lineHeightCSSRule = `var(${value}, ${ADDITIVE_LINE_HEIGHT_RULE})`;\n this._options.lineHeight = this.readThemeLineHeightPx() as TOptions[\"lineHeight\"];\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n }\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Sets the line-height equal to the given pixel height so a single-line\n * text sits vertically centred in a fixed-height inline box.\n *\n * @param px - Pixel value matching the container's height, or `null` to\n * revert to the theme's additive line box (font size +\n * `--ts-ui-line-padding`).\n *\n * @returns This component, for method chaining.\n *\n * @example\n * ```typescript\n * const label = new Text(\"File\");\n * label.centerInHeight(28);\n * ```\n */\n centerInHeight(px: number | null): this {\n if (px === null) {\n this._lineHeightCSSVar = null;\n this._lineHeightCSSRule = ADDITIVE_LINE_HEIGHT_RULE;\n this._options.lineHeight = this.readThemeLineHeightPx() as TOptions[\"lineHeight\"];\n this.setElementCSSRule(\"lineHeight\", this._lineHeightCSSRule);\n\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n return this.setLineHeight(px);\n }\n\n /**\n * Returns the CSS text-overflow value last passed to {@link setTextOverflow},\n * or `null` if not set.\n *\n * @returns The text-overflow string, or null.\n */\n getTextOverflow(): string | null {\n return this._textOverflow;\n }\n\n /**\n * Sets the CSS text-overflow property and updates the component's CSS rule.\n *\n * @param value - A CSS text-overflow value (e.g. \"clip\", \"ellipsis\").\n *\n * @returns This component, for method chaining.\n */\n setTextOverflow(value: string): this {\n this._textOverflow = value;\n\n this.setElementCSSRule(\"textOverflow\", value);\n\n return this;\n }\n\n /**\n * Removes the text-overflow CSS property from the component's CSS rule.\n *\n * @returns This component, for method chaining.\n */\n clearTextOverflow(): this {\n if (this._textOverflow === null) {\n return this;\n }\n\n this._textOverflow = null;\n this.setElementCSSRule(\"textOverflow\", null);\n\n return this;\n }\n\n /**\n * Returns whether single-line truncation + ellipsis is enabled (default `true`).\n *\n * @returns `true` when the text clips with \"…\" once narrower than its\n * natural width; `false` when the text refuses to shrink past its\n * natural width.\n */\n isTruncate(): boolean {\n return this._truncate;\n }\n\n /**\n * Toggles single-line truncation mode. When `true`, the text renders as\n * single-line + `overflow: hidden` + `text-overflow: ellipsis` and reports\n * `minSize.width = Math.min(natural, 100)`. When `false`, those CSS\n * properties are cleared and the text reports its full natural width as\n * `minSize.width` so parent layouts widen to fit instead of clipping.\n *\n * @param value - `true` to enable ellipsised truncation, `false` to\n * disable (the text expands to its natural width).\n *\n * @returns This component, for method chaining.\n */\n setTruncate(value: boolean): this {\n this._truncate = value;\n\n if (value) {\n this.setWhiteSpace(\"nowrap\");\n this.setOverflow(\"hidden\");\n this.setTextOverflow(\"ellipsis\");\n } else {\n this.setElementCSSRule(\"whiteSpace\", null);\n this.setOverflow(\"visible\");\n this.setElementCSSRule(\"textOverflow\", null);\n this._textOverflow = null;\n }\n\n // The auto-min cap depends on `_truncate`; re-measure so the parent\n // layout sees the new floor on the next layout pass.\n this._measurementDirty = true;\n (this.getParentComponent() ?? this).scheduleLayout();\n\n return this;\n }\n\n /**\n * Returns the current CSS `word-break` value, or null if not set.\n *\n * @returns The word-break string, or null.\n */\n getWordBreak(): string | null {\n return this._wordBreak;\n }\n\n /**\n * Sets the CSS `word-break` property on the component's CSS rule.\n *\n * @param value - A CSS word-break value (e.g. \"break-word\", \"normal\", \"keep-all\").\n *\n * @returns This component, for method chaining.\n */\n setWordBreak(value: string): this {\n if (this._wordBreak === value) {\n return this;\n }\n\n this._wordBreak = value;\n this.setElementCSSRule(\"wordBreak\", value);\n\n return this;\n }\n\n /**\n * Returns the current line-clamp line count, or null if no clamp is applied.\n *\n * @returns The maximum line count, or null.\n */\n getLineClamp(): number | null {\n return this._lineClamp;\n }\n\n /**\n * Clamps the rendered text to a maximum line count via CSS line-clamp.\n *\n * Writes `display: -webkit-box`, `-webkit-box-orient: vertical`,\n * `-webkit-line-clamp`, `overflow: hidden`, and `text-overflow: ellipsis`\n * in a single call. Use {@link clearLineClamp} to remove the clamp.\n *\n * @param lines - The maximum number of lines to display before the ellipsis.\n *\n * @returns This component, for method chaining.\n */\n setLineClamp(lines: number): this {\n if (this._lineClamp === lines) {\n return this;\n }\n\n this._lineClamp = lines;\n this.setElementCSSRules({\n display: \"-webkit-box\",\n webkitBoxOrient: \"vertical\",\n webkitLineClamp: String(lines),\n overflow: \"hidden\",\n textOverflow: \"ellipsis\"\n });\n\n return this;\n }\n\n /**\n * Removes the line-clamp styling previously applied by {@link setLineClamp}.\n *\n * @returns This component, for method chaining.\n */\n clearLineClamp(): this {\n if (this._lineClamp === null) {\n return this;\n }\n\n this._lineClamp = null;\n this.setElementCSSRules({\n display: null,\n webkitBoxOrient: null,\n webkitLineClamp: null,\n overflow: null,\n textOverflow: null\n });\n\n return this;\n }\n\n /**\n * Applies all text-specific style properties to the element's CSS rule in addition to base styles.\n *\n * @param element - The element handle to apply styles to.\n */\n applyStyle(element: Handle): this {\n super.applyStyle(element);\n\n const fontSize = this.getFontSize();\n const lineHeight = this.getLineHeight();\n\n this.setElementCSSRules({\n fontFamily: this.getFontFamily() ?? '',\n textAlign: this.getTextAlign() ?? '',\n textShadow: this.getTextShadow() ?? '',\n fontKerning: this.getFontKerning() ?? '',\n fontSize: this._fontSizeCSSRule ?? (fontSize !== null ? `${fontSize}px` : ''),\n fontSizeAdjust: this.getFontSizeAdjust() ?? '',\n fontStretch: this.getFontStretch() ?? '',\n fontStyle: this.getFontStyle() ?? '',\n fontVariant: this.getFontVariant() ?? '',\n fontWeight: this.getFontWeight() ?? '',\n lineHeight: this._lineHeightCSSRule ?? (lineHeight !== null ? `${lineHeight}px` : '')\n });\n\n return this;\n }\n\n /**\n * Removes the theme-change listener. Call when the component is permanently removed.\n */\n dispose() {\n this._unsubscribeTheme();\n }\n\n /**\n * Renders the element and sets its text content.\n *\n * @returns The created element with textContent initialised.\n */\n protected render() {\n let element = super.render();\n\n DOM.sink.apply(element, { text: this.getText().valueOf() });\n\n return element;\n }\n}\n\nconst TextCallable = callable(Text);\ntype TextCallable<TOptions extends TextOptions = TextOptions> = Text<TOptions>;\nexport {\n Text as _Text,\n TextCallable as Text\n};\n"],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{l as e,u as t}from"./Position-B-WfZYAJ.js";import{h as n,t as r,y as i}from"./Component-BR2f0Itb.js";import{t as a}from"./Text-D1RrBY52.js";var o=9e3,s=9800,c=1e4,l=11e3,u=12e3,d=new r,f;(function(e){let n=[],r=new WeakMap,a=0,f=null,p=!1;e.Band={Window:o,Popover:s,Dropdown:c,Dialog:l,Tooltip:u};function bandFor(e,t){return e?e.band:t}function register(e){if(r.has(e))return;let t=n.length>0?n[n.length-1]:null,i=e.isLayerRoot?.()?null:t,o=bandFor(i,e.getBand?.()??c),s={layer:e,parent:i,children:[],band:o,zIndex:o+ ++a};r.set(e,s),n.push(s),i&&i.children.push(s),p||installListeners()}e.register=register;function mount(e){t.source.contains(t.source.getDocumentElement(),e)||t.sink.appendChild(t.source.getDocumentElement(),e)}e.mount=mount;function unregister(e){let t=r.get(e);if(!t)return;r.delete(e);let i=n.indexOf(t);if(i>=0&&n.splice(i,1),t.parent){let e=t.parent.children.indexOf(t);e>=0&&t.parent.children.splice(e,1)}f===e&&(f=null),n.length===0&&p&&uninstallListeners()}e.unregister=unregister;function containsAcrossLayers(e,n){if(!n)return!1;let i=r.get(e);if(!i){let r=e.getLayerElement();return r?t.source.contains(r,n):!1}return nodeContains(i,n)}e.containsAcrossLayers=containsAcrossLayers;function getTopLayer(){return n.length>0?n[n.length-1].layer:null}e.getTopLayer=getTopLayer;function bringToFront(e){let t=r.get(e);t&&(restampSubtree(t),markActive(e))}e.bringToFront=bringToFront;function getZIndex(e){let t=r.get(e);return t?t.zIndex:c}e.getZIndex=getZIndex;function restampSubtree(e){let walk=e=>{e.zIndex=e.band+ ++a,e.layer.onZIndexChanged?.(e.zIndex);for(let t of e.children)walk(t)};walk(e)}function nodeContains(e,n){let r=e.layer.getLayerElement();if(r&&t.source.contains(r,n))return!0;for(let t of e.children)if(nodeContains(t,n))return!0;return!1}function markActive(e){f!==e&&(deactivateActive(),f=e,e.onActivate&&e.onActivate(!0))}function deactivateActive(){f&&f.onActivate&&f.onActivate(!1),f=null}function activatableAncestor(e){let t=e;for(;t;){if(t.layer.onActivate)return t.layer;t=t.parent}return null}function handleOutside(e,r){let i=n.slice().reverse(),a=!1,o=!1;for(let n of i){let i=n.layer.getDismissMode();if(containsAcrossLayers(n.layer,e)){markActive(activatableAncestor(n)??n.layer),a=!0,o=!0;break}let s=n.layer.getAnchorElement?.();if(s&&e&&t.source.contains(s,e)){o=!0;break}if(i===`manual`||i===`modal`||!(r?i===`blur`:i===`click-outside`||i===`blur`)){if(i===`modal`){o=!0;break}continue}n.layer.requestClose()}!a&&!o&&!r&&deactivateActive()}function onPointerDown(e){handleOutside(e.target===null?null:t.source.intern(e.target),!1)}function onWindowBlur(e){t.source.isWindow(e.target===null?null:t.source.intern(e.target))&&handleOutside(null,!1)}function onFocusIn(e){handleOutside(e.target===null?null:t.source.intern(e.target),!0)}function onKeyDown(e){if(e.key===`Escape`){for(let e=n.length-1;e>=0;e--)if(n[e].layer.getDismissMode()!==`manual`){n[e].layer.requestClose();return}}}function installListeners(){i.addViewportListener(d,`pointerdown`,onPointerDown),i.addViewportListener(d,`focusin`,onFocusIn),i.addViewportListener(d,`keydown`,onKeyDown),i.addViewportListener(d,`blur`,onWindowBlur),p=!0}function uninstallListeners(){i.removeViewportListener(d,`pointerdown`,onPointerDown),i.removeViewportListener(d,`focusin`,onFocusIn),i.removeViewportListener(d,`keydown`,onKeyDown),i.removeViewportListener(d,`blur`,onWindowBlur),p=!1}})(f||={});function positionAdjacent(e,t,n,r,i){let a=t+i,o=r-a,s=e-i;return n<=o?a:n<=s?e-n-i:o>=s?Math.max(0,r-n):0}function positionAligned(e,t,n,r,i){if(e>=i&&e+n<=r-i)return e;let a=t-n;return a>=i&&a+n<=r-i?a:clampAxis(e,n,r,i)}function clampAxis(t,n,r,i){return e.clamp(t,i,Math.max(i,r-n-i))}function positionFlexibleAnchored(e,t,n,r,i){let a=r-t-i,o=e-i;return n<=a||a>=o?{start:t,available:a}:{start:e-Math.min(n,o),available:o}}function positionAnchored(e,t,n,r){let i=r.gap??0,a=r.margin??0;if(r.axis===`vertical`){let r=positionAdjacent(e.top,e.bottom,t.height,n.height,i);return{x:positionAligned(e.left,e.right,t.width,n.width,a),y:r}}return{x:positionAdjacent(e.left,e.right,t.width,n.width,i),y:positionAligned(e.top,e.bottom,t.height,n.height,a)}}var p=100,m=class Tooltip extends r{static instance=null;static showTimer=null;static attachments=new Map;static elementAttachments=new Map;static activeElement=null;static watching=!1;static _onAnchorWatch=()=>{Tooltip.activeElement!==null&&!t.source.isConnected(Tooltip.activeElement)&&Tooltip.hide()};static dismissing=!1;static H_PADDING=16;static V_PADDING=8;static MAX_WIDTH=300;static ITEM_HEIGHT=20;static CURSOR_LEFT=4;static CURSOR_RIGHT=12;static CURSOR_UP=0;static CURSOR_DOWN=12;static CURSOR_GAP=2;_text;_lineCount=1;_perLine=Tooltip.ITEM_HEIGHT;constructor(){super(),this.setVisible(!1),this.setZIndex(f.Band.Tooltip),this.setBackgroundColor(`var(--ts-ui-tooltip-bg, rgb(255, 255, 240))`),this.setForegroundColor(`var(--ts-ui-tooltip-color, rgb(0, 0, 0))`),this.setBorder({border:`1px solid var(--ts-ui-tooltip-border, rgb(180, 180, 100))`}),this.setShadow(`var(--ts-ui-tooltip-shadow, 1px 2px 4px rgba(0, 0, 0, 0.2))`),this.setBorderRadius(`var(--ts-ui-border-radius, 4px)`),this.setPointerEvents(`none`),this.setContain(`layout paint`),this._text=new a,this._text.setPointerEvents(`none`),this._text.setWhiteSpace(`pre-wrap`),this.addComponent(this._text)}static getInstance(){return Tooltip.instance||=new Tooltip,Tooltip.instance}static show(r,a,o){Tooltip.showTimer!==null&&(clearTimeout(Tooltip.showTimer),Tooltip.showTimer=null);let s=Tooltip.getInstance(),c=s.isVisible()&&!Tooltip.dismissing;s._text.setText(r);let l=r.split(`
|
|
2
|
-
`),u=l.reduce((t,n)=>Math.max(t,e.measureTextWidth(n)),0);s._perLine=s._perLineHeight();let d=Math.min(Tooltip.MAX_WIDTH,u+Tooltip.H_PADDING);if(u+Tooltip.H_PADDING>Tooltip.MAX_WIDTH){let e=d-Tooltip.H_PADDING,n=t.source.measureText(r,{maxWidth:e}).height;s._lineCount=Math.max(l.length,Math.round(n/s._perLine))}else s._lineCount=l.length;let m=s._lineCount*s._perLine+Tooltip.V_PADDING;s._lineCount===1&&(m=Math.max(m,Tooltip.ITEM_HEIGHT+Tooltip.V_PADDING)),s.setWidth(d),s.setHeight(m);let h=t.source.getViewportSize(),g=e.clamp(a,0,h.width),_=e.clamp(o,0,h.height);s.setX(positionAdjacent(g-Tooltip.CURSOR_LEFT,g+Tooltip.CURSOR_RIGHT,d,h.width,Tooltip.CURSOR_GAP)),s.setY(positionAdjacent(_-Tooltip.CURSOR_UP,_+Tooltip.CURSOR_DOWN,m,h.height,Tooltip.CURSOR_GAP));let v=s.getElement(!0);if(s.scheduleLayout(),f.mount(v),s.setVisible(!0),Tooltip.watching||=(i.addViewportListener(s,`mousemove`,Tooltip._onAnchorWatch),!0),Tooltip.dismissing=!1,c){t.sink.apply(v,{style:{opacity:`1`}});return}n.play(v,{from:{opacity:`0`},to:{opacity:`1`},durationMs:p,properties:[`opacity`]})}static hide(){Tooltip.showTimer!==null&&(clearTimeout(Tooltip.showTimer),Tooltip.showTimer=null);let e=Tooltip.getInstance(),t=e.getElement();Tooltip.watching&&=(i.removeViewportListener(e,`mousemove`,Tooltip._onAnchorWatch),!1),Tooltip.activeElement=null,t&&(Tooltip.dismissing=!0,n.play(t,{to:{opacity:`0`},durationMs:p,properties:[`opacity`],onComplete:()=>{Tooltip.dismissing&&(Tooltip.dismissing=!1,e.setVisible(!1),e.removeElement())}}))}static attach(e,t,n){Tooltip.detach(e);let r=0,a=0,mouseoverFn=i=>{Tooltip.showTimer===null&&(r=i.clientX,a=i.clientY,Tooltip.showTimer=setTimeout(()=>{Tooltip._applyColors(n),Tooltip.activeElement=e.getElement()??null,Tooltip.show(t,r,a),Tooltip.showTimer=null},500))},mousemoveFn=e=>{r=e.clientX,a=e.clientY},mouseoutFn=()=>{Tooltip.hide()},mousedownFn=()=>{Tooltip.hide()};i.addListener(e,`mouseover`,mouseoverFn),i.addListener(e,`mousemove`,mousemoveFn),i.addListener(e,`mouseout`,mouseoutFn),i.addListener(e,`mousedown`,mousedownFn),Tooltip.attachments.set(e.getId(),{text:t,colors:n,mouseoverFn,mousemoveFn,mouseoutFn,mousedownFn})}static detach(e){let t=e.getId(),n=Tooltip.attachments.get(t);n&&(i.removeListener(e,`mouseover`,n.mouseoverFn),i.removeListener(e,`mousemove`,n.mousemoveFn),i.removeListener(e,`mouseout`,n.mouseoutFn),i.removeListener(e,`mousedown`,n.mousedownFn),Tooltip.attachments.delete(t),Tooltip.hide())}static _applyColors(e){let t=Tooltip.getInstance();t.setBackgroundColor(e?.background??`var(--ts-ui-tooltip-bg, rgb(255, 255, 240))`),t.setForegroundColor(e?.color??`var(--ts-ui-tooltip-color, rgb(0, 0, 0))`),t.setBorder({border:`1px solid ${e?.border??`var(--ts-ui-tooltip-border, rgb(180, 180, 100))`}`})}static attachToElement(e,n){let r=Tooltip.elementAttachments.get(e),i=Tooltip.activeElement===e,a=r?r.lastX:0,o=r?r.lastY:0;Tooltip.detachElement(e);let s={text:n,showTimer:null,lastX:a,lastY:o,mouseoverFn:function onTooltipMouseOver(t){s.showTimer===null&&(s.lastX=t.clientX,s.lastY=t.clientY,s.showTimer=setTimeout(function onTooltipShowTimer(){Tooltip.activeElement=e,Tooltip.show(s.text,s.lastX,s.lastY),s.showTimer=null},500))},mousemoveFn:function onTooltipMouseMove(e){s.lastX=e.clientX,s.lastY=e.clientY},mouseoutFn:function onTooltipMouseOut(){s.showTimer!==null&&(clearTimeout(s.showTimer),s.showTimer=null),Tooltip.activeElement===e&&(Tooltip.activeElement=null),Tooltip.hide()},mousedownFn:function onTooltipMouseDown(){s.showTimer!==null&&(clearTimeout(s.showTimer),s.showTimer=null),Tooltip.hide()}};t.sink.addListener(e,`mouseover`,s.mouseoverFn),t.sink.addListener(e,`mousemove`,s.mousemoveFn),t.sink.addListener(e,`mouseout`,s.mouseoutFn),t.sink.addListener(e,`mousedown`,s.mousedownFn),Tooltip.elementAttachments.set(e,s),i&&(Tooltip.activeElement=e,Tooltip.show(n,s.lastX,s.lastY))}static detachElement(e){let n=Tooltip.elementAttachments.get(e);n&&(t.sink.removeListener(e,`mouseover`,n.mouseoverFn),t.sink.removeListener(e,`mousemove`,n.mousemoveFn),t.sink.removeListener(e,`mouseout`,n.mouseoutFn),t.sink.removeListener(e,`mousedown`,n.mousedownFn),n.showTimer!==null&&(clearTimeout(n.showTimer),n.showTimer=null),Tooltip.elementAttachments.delete(e),Tooltip.activeElement===e&&(Tooltip.activeElement=null))}_perLineHeight(){let{height:e}=t.source.measureText(`X`);return Math.ceil(e)}doLayout(){return super.doLayout(),this._text.setX(Tooltip.H_PADDING/2),this._text.setY(Tooltip.V_PADDING/2),this._text.setWidth(Math.max(0,this.getWidth()-Tooltip.H_PADDING)),this._text.setHeight(this._lineCount*this._perLine),this}};export{f as a,positionFlexibleAnchored as i,positionAligned as n,positionAnchored as r,m as t};
|
|
3
|
-
//# sourceMappingURL=Tooltip-4lU_tf6r.js.map
|