@jimka/typescript-ui 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/dist/lib/{AbstractInput-B10DfLOf.js → AbstractInput-sRNPzWel.js} +2 -2
  2. package/dist/lib/{AbstractInput-B10DfLOf.js.map → AbstractInput-sRNPzWel.js.map} +1 -1
  3. package/dist/lib/Anchor-CwRhdP2J.js +2 -0
  4. package/dist/lib/Anchor-CwRhdP2J.js.map +1 -0
  5. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js +2 -0
  6. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js.map +1 -0
  7. package/dist/lib/Border-0DJFDiij.js +2 -0
  8. package/dist/lib/Border-0DJFDiij.js.map +1 -0
  9. package/dist/lib/Button-MpMIYBYJ.js +2 -0
  10. package/dist/lib/Button-MpMIYBYJ.js.map +1 -0
  11. package/dist/lib/{Card-CD3jxshU.js → Card-QYo27r5b.js} +2 -2
  12. package/dist/lib/{Card-CD3jxshU.js.map → Card-QYo27r5b.js.map} +1 -1
  13. package/dist/lib/Checkbox-D0JYK-wc.js +2 -0
  14. package/dist/lib/Checkbox-D0JYK-wc.js.map +1 -0
  15. package/dist/lib/CheckboxMenuRow-CesLhSnp.js +2 -0
  16. package/dist/lib/CheckboxMenuRow-CesLhSnp.js.map +1 -0
  17. package/dist/lib/{CodeEditor-BGlB232h.js → CodeEditor-N1FQodcF.js} +2 -2
  18. package/dist/lib/CodeEditor-N1FQodcF.js.map +1 -0
  19. package/dist/lib/ComboBox-Dx8Tk9yg.js +2 -0
  20. package/dist/lib/ComboBox-Dx8Tk9yg.js.map +1 -0
  21. package/dist/lib/Component-B0ShfPVi.js +2 -0
  22. package/dist/lib/Component-B0ShfPVi.js.map +1 -0
  23. package/dist/lib/Container-abY5Ww3W.js +2 -0
  24. package/dist/lib/{Container-C7RPLQEc.js.map → Container-abY5Ww3W.js.map} +1 -1
  25. package/dist/lib/{DOM-Ba8YRVel.js → DOM-C-Edb3tA.js} +2 -2
  26. package/dist/lib/DOM-C-Edb3tA.js.map +1 -0
  27. package/dist/lib/Dialog-cbA9V17e.js +2 -0
  28. package/dist/lib/Dialog-cbA9V17e.js.map +1 -0
  29. package/dist/lib/{FieldDecorator-HG65hEtk.js → FieldDecorator-BlYMfZ9L.js} +2 -2
  30. package/dist/lib/{FieldDecorator-HG65hEtk.js.map → FieldDecorator-BlYMfZ9L.js.map} +1 -1
  31. package/dist/lib/{Fit-Cg3dPyZg.js → Fit-BhlB-HAo.js} +2 -2
  32. package/dist/lib/{Fit-Cg3dPyZg.js.map → Fit-BhlB-HAo.js.map} +1 -1
  33. package/dist/lib/{FloatingPanel-D5buuVrQ.js → FloatingPanel-DkJXsZ2D.js} +2 -2
  34. package/dist/lib/{FloatingPanel-D5buuVrQ.js.map → FloatingPanel-DkJXsZ2D.js.map} +1 -1
  35. package/dist/lib/{Glyph-DeJF_zsR.js → Glyph-_VeBacS2.js} +2 -2
  36. package/dist/lib/{Glyph-DeJF_zsR.js.map → Glyph-_VeBacS2.js.map} +1 -1
  37. package/dist/lib/{Grid-BYBohJIA.js → Grid-Daiz7F5d.js} +2 -2
  38. package/dist/lib/Grid-Daiz7F5d.js.map +1 -0
  39. package/dist/lib/GridConstraints-C58LuTqM.js +2 -0
  40. package/dist/lib/{GridConstraints-Bts284FI.js.map → GridConstraints-C58LuTqM.js.map} +1 -1
  41. package/dist/lib/{Header-BIFJK9nR.js → Header-Dql3Zxc6.js} +2 -2
  42. package/dist/lib/{Header-BIFJK9nR.js.map → Header-Dql3Zxc6.js.map} +1 -1
  43. package/dist/lib/{IconText-Dsb1xS-E.js → IconText-PUjhTLlp.js} +2 -2
  44. package/dist/lib/{IconText-Dsb1xS-E.js.map → IconText-PUjhTLlp.js.map} +1 -1
  45. package/dist/lib/LayoutSerialization-CMxunLfV.js +2 -0
  46. package/dist/lib/LayoutSerialization-CMxunLfV.js.map +1 -0
  47. package/dist/lib/List-nx8220Fi.js +2 -0
  48. package/dist/lib/{List-BPd-IXZR.js.map → List-nx8220Fi.js.map} +1 -1
  49. package/dist/lib/MemoryStore-DhPoU-7X.js +2 -0
  50. package/dist/lib/MemoryStore-DhPoU-7X.js.map +1 -0
  51. package/dist/lib/Menu-Q0bpXXze.js +2 -0
  52. package/dist/lib/Menu-Q0bpXXze.js.map +1 -0
  53. package/dist/lib/{MenuButton-BR4KOFld.js → MenuButton-DCXi0tsP.js} +2 -2
  54. package/dist/lib/{MenuButton-BR4KOFld.js.map → MenuButton-DCXi0tsP.js.map} +1 -1
  55. package/dist/lib/OverlayFade-3pof2AJH.js +2 -0
  56. package/dist/lib/OverlayFade-3pof2AJH.js.map +1 -0
  57. package/dist/lib/{Panel-CpNQTLNF.js → Panel-Cy1pdlWO.js} +2 -2
  58. package/dist/lib/{Panel-CpNQTLNF.js.map → Panel-Cy1pdlWO.js.map} +1 -1
  59. package/dist/lib/{Position-PBVBW1JS.js → Position-BwtxouxK.js} +2 -2
  60. package/dist/lib/{Position-PBVBW1JS.js.map → Position-BwtxouxK.js.map} +1 -1
  61. package/dist/lib/{ProgressSpinner-lAsK26C-.js → ProgressSpinner-DK8xEQ9y.js} +2 -2
  62. package/dist/lib/{ProgressSpinner-lAsK26C-.js.map → ProgressSpinner-DK8xEQ9y.js.map} +1 -1
  63. package/dist/lib/RadioButton-BEwpqg1k.js +2 -0
  64. package/dist/lib/{RadioButton-CCcIaL54.js.map → RadioButton-BEwpqg1k.js.map} +1 -1
  65. package/dist/lib/RadioMenuRow-DP5qPyFR.js +2 -0
  66. package/dist/lib/RadioMenuRow-DP5qPyFR.js.map +1 -0
  67. package/dist/lib/{RovingTabIndex-C2Vzq0IX.js → RovingTabIndex-pHEv5oLD.js} +2 -2
  68. package/dist/lib/{RovingTabIndex-C2Vzq0IX.js.map → RovingTabIndex-pHEv5oLD.js.map} +1 -1
  69. package/dist/lib/Scrollbar-t8fFrUVQ.js +2 -0
  70. package/dist/lib/Scrollbar-t8fFrUVQ.js.map +1 -0
  71. package/dist/lib/{Slider-DZ9drUxn.js → Slider-CTbwR6HR.js} +2 -2
  72. package/dist/lib/{Slider-DZ9drUxn.js.map → Slider-CTbwR6HR.js.map} +1 -1
  73. package/dist/lib/{Spacer-SDhOMp2g.js → Spacer-srdN2d2b.js} +2 -2
  74. package/dist/lib/{Spacer-SDhOMp2g.js.map → Spacer-srdN2d2b.js.map} +1 -1
  75. package/dist/lib/TabButton-DLoMQzky.js +2 -0
  76. package/dist/lib/TabButton-DLoMQzky.js.map +1 -0
  77. package/dist/lib/TabCloseButton-CY7BGitY.js +2 -0
  78. package/dist/lib/TabCloseButton-CY7BGitY.js.map +1 -0
  79. package/dist/lib/{Text-CdHf3B-1.js → Text-CMKnK9uB.js} +2 -2
  80. package/dist/lib/{Text-CdHf3B-1.js.map → Text-CMKnK9uB.js.map} +1 -1
  81. package/dist/lib/{Tooltip-B_UF5bXD.js → Tooltip-CUOJOqQi.js} +3 -3
  82. package/dist/lib/Tooltip-CUOJOqQi.js.map +1 -0
  83. package/dist/lib/Tree-C64JNPWJ.js +2 -0
  84. package/dist/lib/Tree-C64JNPWJ.js.map +1 -0
  85. package/dist/lib/VBox-DfJPWXqc.js +2 -0
  86. package/dist/lib/VBox-DfJPWXqc.js.map +1 -0
  87. package/dist/lib/VirtualScroller-DTIn19o1.js +2 -0
  88. package/dist/lib/VirtualScroller-DTIn19o1.js.map +1 -0
  89. package/dist/lib/assets/StoreWorker-B5NwRM2I.js +2 -0
  90. package/dist/lib/assets/StoreWorker-B5NwRM2I.js.map +1 -0
  91. package/dist/lib/component/button.es.js +1 -1
  92. package/dist/lib/component/button.es.js.map +1 -1
  93. package/dist/lib/component/chart.es.js +1 -1
  94. package/dist/lib/component/container.es.js +1 -1
  95. package/dist/lib/component/container.es.js.map +1 -1
  96. package/dist/lib/component/diagram.es.js +1 -1
  97. package/dist/lib/component/diagram.es.js.map +1 -1
  98. package/dist/lib/component/display.es.js +1 -1
  99. package/dist/lib/component/display.es.js.map +1 -1
  100. package/dist/lib/component/editor.es.js +2 -2
  101. package/dist/lib/component/editor.es.js.map +1 -1
  102. package/dist/lib/component/input.es.js +1 -1
  103. package/dist/lib/component/input.es.js.map +1 -1
  104. package/dist/lib/component/list.es.js +1 -1
  105. package/dist/lib/component/list.es.js.map +1 -1
  106. package/dist/lib/component/menubar.es.js +1 -1
  107. package/dist/lib/component/menubar.es.js.map +1 -1
  108. package/dist/lib/component/table.es.js +6 -3
  109. package/dist/lib/component/table.es.js.map +1 -1
  110. package/dist/lib/component/tree.es.js +1 -1
  111. package/dist/lib/core.es.js +1 -1
  112. package/dist/lib/core.es.js.map +1 -1
  113. package/dist/lib/data.es.js +1 -1
  114. package/dist/lib/glyphs/solid/index.es.js +1 -1
  115. package/dist/lib/layout.es.js +1 -1
  116. package/dist/lib/layout.es.js.map +1 -1
  117. package/dist/lib/overlay.es.js +1 -1
  118. package/dist/lib/overlay.es.js.map +1 -1
  119. package/dist/lib/primitive.es.js +1 -1
  120. package/dist/lib/router.es.js +1 -1
  121. package/dist/lib/router.es.js.map +1 -1
  122. package/dist/lib/selectionsEqual-gMG7gCVI.js +2 -0
  123. package/dist/lib/selectionsEqual-gMG7gCVI.js.map +1 -0
  124. package/dist/lib/types/component/button/Button.d.ts +13 -0
  125. package/dist/lib/types/component/button/MenuButton.d.ts +1 -0
  126. package/dist/lib/types/component/button/PopupButton.d.ts +22 -0
  127. package/dist/lib/types/component/button/TabButton.d.ts +4 -0
  128. package/dist/lib/types/component/button/index.d.ts +2 -0
  129. package/dist/lib/types/component/container/CheckboxMenuRow.d.ts +33 -0
  130. package/dist/lib/types/component/container/CollapseButton.d.ts +11 -3
  131. package/dist/lib/types/component/container/MenuItem.d.ts +15 -5
  132. package/dist/lib/types/component/container/MenuRow.d.ts +24 -0
  133. package/dist/lib/types/component/container/MenuSeparator.d.ts +4 -2
  134. package/dist/lib/types/component/container/RadioMenuRow.d.ts +33 -0
  135. package/dist/lib/types/component/container/Scrollbar.d.ts +5 -0
  136. package/dist/lib/types/component/container/SplitGutter.d.ts +7 -2
  137. package/dist/lib/types/component/container/TabBar.d.ts +2 -0
  138. package/dist/lib/types/component/container/WindowBorder.d.ts +1 -1
  139. package/dist/lib/types/component/container/index.d.ts +6 -1
  140. package/dist/lib/types/component/display/WebGLCanvas.d.ts +1 -0
  141. package/dist/lib/types/component/input/AbstractCalendarDropdown.d.ts +2 -0
  142. package/dist/lib/types/component/input/AbstractPickerField.d.ts +3 -2
  143. package/dist/lib/types/component/list/AbstractSelectableList.d.ts +1 -1
  144. package/dist/lib/types/component/list/MultiSelectList.d.ts +2 -1
  145. package/dist/lib/types/component/shared/VirtualRowView.d.ts +2 -0
  146. package/dist/lib/types/component/table/Body.d.ts +22 -1
  147. package/dist/lib/types/component/table/Column.d.ts +3 -1
  148. package/dist/lib/types/component/table/ColumnConfig.d.ts +2 -0
  149. package/dist/lib/types/component/table/ColumnFilter.d.ts +27 -0
  150. package/dist/lib/types/component/table/Header.d.ts +30 -3
  151. package/dist/lib/types/component/table/Row.d.ts +4 -0
  152. package/dist/lib/types/component/table/Table.d.ts +29 -0
  153. package/dist/lib/types/component/table/TableExporter.d.ts +4 -3
  154. package/dist/lib/types/component/table/TreeBody.d.ts +2 -1
  155. package/dist/lib/types/component/table/cell/CellText.d.ts +9 -0
  156. package/dist/lib/types/component/table/cell/Filter.d.ts +54 -0
  157. package/dist/lib/types/component/table/cell/FilterClauseBadge.d.ts +21 -0
  158. package/dist/lib/types/component/table/cell/GroupSeparator.d.ts +9 -0
  159. package/dist/lib/types/component/table/cell/Header.d.ts +1 -0
  160. package/dist/lib/types/component/table/cell/editor/CellEditor.d.ts +1 -0
  161. package/dist/lib/types/component/table/cell/renderer/CellRenderer.d.ts +1 -0
  162. package/dist/lib/types/component/table/cell/renderer/Combo.d.ts +2 -0
  163. package/dist/lib/types/component/table/cell/renderer/Date.d.ts +2 -0
  164. package/dist/lib/types/component/table/cell/renderer/DateTime.d.ts +2 -0
  165. package/dist/lib/types/component/table/cell/renderer/Filter.d.ts +16 -0
  166. package/dist/lib/types/component/table/cell/renderer/Glyph.d.ts +1 -0
  167. package/dist/lib/types/component/table/cell/renderer/Link.d.ts +2 -0
  168. package/dist/lib/types/component/table/cell/renderer/Number.d.ts +3 -1
  169. package/dist/lib/types/component/table/cell/renderer/String.d.ts +2 -0
  170. package/dist/lib/types/component/table/cell/renderer/Time.d.ts +2 -0
  171. package/dist/lib/types/component/table/cell/renderer/TreeCell.d.ts +1 -0
  172. package/dist/lib/types/component/table/index.d.ts +6 -0
  173. package/dist/lib/types/component/tree/Tree.d.ts +17 -1
  174. package/dist/lib/types/component/tree/index.d.ts +1 -1
  175. package/dist/lib/types/core/AnimatedDropdown.d.ts +0 -9
  176. package/dist/lib/types/core/Body.d.ts +4 -0
  177. package/dist/lib/types/core/ClassStyleRules.d.ts +1 -0
  178. package/dist/lib/types/core/DOM.d.ts +10 -0
  179. package/dist/lib/types/core/Event.d.ts +11 -2
  180. package/dist/lib/types/core/OverlayFade.d.ts +12 -0
  181. package/dist/lib/types/core/OverlayPosition.d.ts +6 -0
  182. package/dist/lib/types/core/Theme.d.ts +8 -0
  183. package/dist/lib/types/core/index.d.ts +5 -3
  184. package/dist/lib/types/data/AbstractStore.d.ts +3 -0
  185. package/dist/lib/types/data/FilterDescriptor.d.ts +13 -0
  186. package/dist/lib/types/data/index.d.ts +2 -1
  187. package/dist/lib/types/data/temporalText.d.ts +2 -0
  188. package/dist/lib/types/layout/BoxLayout.d.ts +6 -1
  189. package/dist/lib/types/layout/Grid.d.ts +1 -0
  190. package/dist/lib/types/layout/HFlow.d.ts +1 -1
  191. package/dist/lib/types/layout/Split.d.ts +10 -1
  192. package/dist/lib/types/layout/Tab.d.ts +7 -1
  193. package/dist/lib/types/layout/VFlow.d.ts +1 -1
  194. package/dist/lib/types/layout/index.d.ts +1 -1
  195. package/dist/lib/types/overlay/Dock.d.ts +1 -0
  196. package/dist/lib/types/overlay/Menu.d.ts +1 -1
  197. package/dist/lib/types/overlay/Popover.d.ts +3 -0
  198. package/dist/lib/types/overlay/PopupPanel.d.ts +17 -0
  199. package/dist/lib/types/overlay/Window.d.ts +2 -0
  200. package/dist/lib/types/overlay/index.d.ts +2 -0
  201. package/dist/lib/types/router/RoutePattern.d.ts +7 -0
  202. package/dist/lib/types/router/Router.d.ts +6 -2
  203. package/dist/lib/types/router/index.d.ts +1 -1
  204. package/dist/lib/validation.es.js +1 -1
  205. package/llms.txt +4 -0
  206. package/package.json +1 -1
  207. package/dist/lib/AbstractBooleanInput-CbW7ZrDT.js +0 -2
  208. package/dist/lib/AbstractBooleanInput-CbW7ZrDT.js.map +0 -1
  209. package/dist/lib/Anchor-BsblS5it.js +0 -2
  210. package/dist/lib/Anchor-BsblS5it.js.map +0 -1
  211. package/dist/lib/AnimatedDropdown-kL47HPGP.js +0 -2
  212. package/dist/lib/AnimatedDropdown-kL47HPGP.js.map +0 -1
  213. package/dist/lib/Border-CNS6aEXB.js +0 -2
  214. package/dist/lib/Border-CNS6aEXB.js.map +0 -1
  215. package/dist/lib/Button-T16zSZip.js +0 -2
  216. package/dist/lib/Button-T16zSZip.js.map +0 -1
  217. package/dist/lib/CodeEditor-BGlB232h.js.map +0 -1
  218. package/dist/lib/ComboBox-C9FYMuLv.js +0 -2
  219. package/dist/lib/ComboBox-C9FYMuLv.js.map +0 -1
  220. package/dist/lib/Component-w65rPK75.js +0 -2
  221. package/dist/lib/Component-w65rPK75.js.map +0 -1
  222. package/dist/lib/Container-C7RPLQEc.js +0 -2
  223. package/dist/lib/DOM-Ba8YRVel.js.map +0 -1
  224. package/dist/lib/DragManager-UvPHSoRm.js +0 -2
  225. package/dist/lib/DragManager-UvPHSoRm.js.map +0 -1
  226. package/dist/lib/Grid-BYBohJIA.js.map +0 -1
  227. package/dist/lib/GridConstraints-Bts284FI.js +0 -2
  228. package/dist/lib/LayoutSerialization-ySzY1h2l.js +0 -2
  229. package/dist/lib/LayoutSerialization-ySzY1h2l.js.map +0 -1
  230. package/dist/lib/LayoutSizes-DKDK1Cle.js +0 -2
  231. package/dist/lib/LayoutSizes-DKDK1Cle.js.map +0 -1
  232. package/dist/lib/List-BPd-IXZR.js +0 -2
  233. package/dist/lib/MemoryStore-BgP7-Uzn.js +0 -2
  234. package/dist/lib/MemoryStore-BgP7-Uzn.js.map +0 -1
  235. package/dist/lib/Menu-C0roOCY7.js +0 -2
  236. package/dist/lib/Menu-C0roOCY7.js.map +0 -1
  237. package/dist/lib/RadioButton-CCcIaL54.js +0 -2
  238. package/dist/lib/Scrollbar-C3ZZyZ1e.js +0 -2
  239. package/dist/lib/Scrollbar-C3ZZyZ1e.js.map +0 -1
  240. package/dist/lib/TabButton-DNo4ZgV8.js +0 -2
  241. package/dist/lib/TabButton-DNo4ZgV8.js.map +0 -1
  242. package/dist/lib/Tooltip-B_UF5bXD.js.map +0 -1
  243. package/dist/lib/Tree-C7qLbIYH.js +0 -2
  244. package/dist/lib/Tree-C7qLbIYH.js.map +0 -1
  245. package/dist/lib/VBox-32fxpkDl.js +0 -2
  246. package/dist/lib/VBox-32fxpkDl.js.map +0 -1
  247. package/dist/lib/VirtualScroller-cvFNMS7U.js +0 -2
  248. package/dist/lib/VirtualScroller-cvFNMS7U.js.map +0 -1
  249. package/dist/lib/assets/StoreWorker-CgOBYoai.js +0 -2
  250. package/dist/lib/assets/StoreWorker-CgOBYoai.js.map +0 -1
  251. package/dist/lib/selectionsEqual-BrTxPMmK.js +0 -2
  252. package/dist/lib/selectionsEqual-BrTxPMmK.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{l as e}from"./Position-PBVBW1JS.js";var RovingTabIndex=class{_items=[];_activeIndex=0;_preventScroll;constructor(e={}){this._preventScroll=e.preventScroll??!1}getItems(){return this._items}getActiveIndex(){return this._activeIndex}add(e){let t=this._items.length===0;return this._items.push(e),e.getAria().setTabIndex(t?0:-1),this}remove(e){let t=this._items.indexOf(e);return t<0?this:(this._items.splice(t,1),this._items.length===0?(this._activeIndex=0,this):(t===this._activeIndex?this.moveTo(Math.max(0,t-1)):t<this._activeIndex&&--this._activeIndex,this))}moveTo(t){if(this._items.length===0)return;let n=e.clamp(t,0,this._items.length-1),r=this._items[this._activeIndex];r&&n!==this._activeIndex&&r.getAria().setTabIndex(-1),this._activeIndex=n;let i=this._items[this._activeIndex];i&&(i.getAria().setTabIndex(0),i.focus(this._preventScroll))}moveNext(){let e=this._items.length;e!==0&&this.moveTo((this._activeIndex+1)%e)}movePrev(){let e=this._items.length;e!==0&&this.moveTo((this._activeIndex-1+e)%e)}};export{RovingTabIndex as t};
2
- //# sourceMappingURL=RovingTabIndex-C2Vzq0IX.js.map
1
+ import{l as e}from"./Position-BwtxouxK.js";var RovingTabIndex=class{_items=[];_activeIndex=0;_preventScroll;constructor(e={}){this._preventScroll=e.preventScroll??!1}getItems(){return this._items}getActiveIndex(){return this._activeIndex}add(e){let t=this._items.length===0;return this._items.push(e),e.getAria().setTabIndex(t?0:-1),this}remove(e){let t=this._items.indexOf(e);return t<0?this:(this._items.splice(t,1),this._items.length===0?(this._activeIndex=0,this):(t===this._activeIndex?this.moveTo(Math.max(0,t-1)):t<this._activeIndex&&--this._activeIndex,this))}moveTo(t){if(this._items.length===0)return;let n=e.clamp(t,0,this._items.length-1),r=this._items[this._activeIndex];r&&n!==this._activeIndex&&r.getAria().setTabIndex(-1),this._activeIndex=n;let i=this._items[this._activeIndex];i&&(i.getAria().setTabIndex(0),i.focus(this._preventScroll))}moveNext(){let e=this._items.length;e!==0&&this.moveTo((this._activeIndex+1)%e)}movePrev(){let e=this._items.length;e!==0&&this.moveTo((this._activeIndex-1+e)%e)}};export{RovingTabIndex as t};
2
+ //# sourceMappingURL=RovingTabIndex-pHEv5oLD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RovingTabIndex-C2Vzq0IX.js","names":[],"sources":["../../src/typescript/lib/core/RovingTabIndex.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Util } from \"~/core/Util.js\";\n\n/**\n * Manages the roving tabindex pattern for a group of sibling {@link Component} items.\n *\n * Exactly one item in the group has `tabindex=0` at any time; all others have `tabindex=-1`.\n * Calling {@link moveTo} updates the tabindices and transfers DOM focus to the new active item.\n *\n * @example\n * ```typescript\n * const group = new RovingTabIndex();\n * group.add(buttonA);\n * group.add(buttonB);\n * group.moveTo(1); // focus buttonB\n * ```\n *\n * @category Core\n */\nexport class RovingTabIndex {\n\n private _items: Component[] = [];\n private _activeIndex: number = 0;\n private readonly _preventScroll: boolean;\n\n /**\n * @param options.preventScroll - When `true`, {@link moveTo} focuses the\n * active item without the browser scrolling it into view. Use it when the\n * group's host owns its own scroll offset (e.g. the\n * [`Tab`](/api/layout/classes/Tab) strip's native clip-frame scroll), so a\n * browser focus-scroll cannot fight or desync it. Defaults to `false` —\n * the standard focus-reveals-the-item behaviour.\n */\n constructor(options: { preventScroll?: boolean } = {}) {\n this._preventScroll = options.preventScroll ?? false;\n }\n\n /**\n * Returns all items currently managed by this roving group.\n *\n * @returns The array of managed {@link Component} instances.\n */\n getItems(): Component[] {\n return this._items;\n }\n\n /**\n * Returns the zero-based index of the currently active item.\n *\n * @returns The active index.\n */\n getActiveIndex(): number {\n return this._activeIndex;\n }\n\n /**\n * Appends a component to the group.\n *\n * @remarks The first item added receives `tabindex=0`; all subsequent items receive `tabindex=-1`.\n * @param component - The component to add.\n */\n add(component: Component): this {\n const isFirst = this._items.length === 0;\n\n this._items.push(component);\n component.getAria().setTabIndex(isFirst ? 0 : -1);\n\n return this;\n }\n\n /**\n * Removes a component from the group.\n *\n * @remarks If the removed item was active, focus moves to the previous item (or index 0).\n * @param component - The component to remove.\n */\n remove(component: Component): this {\n const idx = this._items.indexOf(component);\n\n if (idx < 0) {\n return this;\n }\n\n this._items.splice(idx, 1);\n\n if (this._items.length === 0) {\n this._activeIndex = 0;\n\n return this;\n }\n\n if (idx === this._activeIndex) {\n this.moveTo(Math.max(0, idx - 1));\n } else if (idx < this._activeIndex) {\n this._activeIndex -= 1;\n }\n\n return this;\n }\n\n /**\n * Activates the item at the given index, updating `tabindex` on both the old and new items and transferring DOM focus.\n *\n * @param index - Zero-based index of the item to activate. Clamped to valid range.\n */\n moveTo(index: number): void {\n if (this._items.length === 0) {\n return;\n }\n\n const clampedIndex = Util.clamp(index, 0, this._items.length - 1);\n\n const prev = this._items[this._activeIndex];\n\n if (prev && clampedIndex !== this._activeIndex) {\n prev.getAria().setTabIndex(-1);\n }\n\n this._activeIndex = clampedIndex;\n\n const next = this._items[this._activeIndex];\n\n if (next) {\n next.getAria().setTabIndex(0);\n next.focus(this._preventScroll);\n }\n }\n\n /**\n * Moves focus to the next item, wrapping from the last item back to the first.\n */\n moveNext(): void {\n const count = this._items.length;\n\n if (count === 0) {\n return;\n }\n\n this.moveTo((this._activeIndex + 1) % count);\n }\n\n /**\n * Moves focus to the previous item, wrapping from the first item back to the last.\n */\n movePrev(): void {\n const count = this._items.length;\n\n if (count === 0) {\n return;\n }\n\n this.moveTo((this._activeIndex - 1 + count) % count);\n }\n}\n"],"mappings":"2CAqBA,IAAa,eAAb,KAA4B,CAExB,OAA8B,CAAC,EAC/B,aAA+B,EAC/B,eAUA,YAAY,EAAuC,CAAC,EAAG,CACnD,KAAK,eAAiB,EAAQ,eAAiB,EACnD,CAOA,UAAwB,CACpB,OAAO,KAAK,MAChB,CAOA,gBAAyB,CACrB,OAAO,KAAK,YAChB,CAQA,IAAI,EAA4B,CAC5B,IAAM,EAAU,KAAK,OAAO,SAAW,EAKvC,OAHA,KAAK,OAAO,KAAK,CAAS,EAC1B,EAAU,QAAQ,CAAC,CAAC,YAAY,EAAU,EAAI,EAAE,EAEzC,IACX,CAQA,OAAO,EAA4B,CAC/B,IAAM,EAAM,KAAK,OAAO,QAAQ,CAAS,EAoBzC,OAlBI,EAAM,EACC,MAGX,KAAK,OAAO,OAAO,EAAK,CAAC,EAErB,KAAK,OAAO,SAAW,GACvB,KAAK,aAAe,EAEb,OAGP,IAAQ,KAAK,aACb,KAAK,OAAO,KAAK,IAAI,EAAG,EAAM,CAAC,CAAC,EACzB,EAAM,KAAK,cAClB,OAAK,aAGF,MACX,CAOA,OAAO,EAAqB,CACxB,GAAI,KAAK,OAAO,SAAW,EACvB,OAGJ,IAAM,EAAe,EAAK,MAAM,EAAO,EAAG,KAAK,OAAO,OAAS,CAAC,EAE1D,EAAO,KAAK,OAAO,KAAK,cAE1B,GAAQ,IAAiB,KAAK,cAC9B,EAAK,QAAQ,CAAC,CAAC,YAAY,EAAE,EAGjC,KAAK,aAAe,EAEpB,IAAM,EAAO,KAAK,OAAO,KAAK,cAE1B,IACA,EAAK,QAAQ,CAAC,CAAC,YAAY,CAAC,EAC5B,EAAK,MAAM,KAAK,cAAc,EAEtC,CAKA,UAAiB,CACb,IAAM,EAAQ,KAAK,OAAO,OAEtB,IAAU,GAId,KAAK,QAAQ,KAAK,aAAe,GAAK,CAAK,CAC/C,CAKA,UAAiB,CACb,IAAM,EAAQ,KAAK,OAAO,OAEtB,IAAU,GAId,KAAK,QAAQ,KAAK,aAAe,EAAI,GAAS,CAAK,CACvD,CACJ"}
1
+ {"version":3,"file":"RovingTabIndex-pHEv5oLD.js","names":[],"sources":["../../src/typescript/lib/core/RovingTabIndex.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Util } from \"~/core/Util.js\";\n\n/**\n * Manages the roving tabindex pattern for a group of sibling {@link Component} items.\n *\n * Exactly one item in the group has `tabindex=0` at any time; all others have `tabindex=-1`.\n * Calling {@link moveTo} updates the tabindices and transfers DOM focus to the new active item.\n *\n * @example\n * ```typescript\n * const group = new RovingTabIndex();\n * group.add(buttonA);\n * group.add(buttonB);\n * group.moveTo(1); // focus buttonB\n * ```\n *\n * @category Core\n */\nexport class RovingTabIndex {\n\n private _items: Component[] = [];\n private _activeIndex: number = 0;\n private readonly _preventScroll: boolean;\n\n /**\n * @param options.preventScroll - When `true`, {@link moveTo} focuses the\n * active item without the browser scrolling it into view. Use it when the\n * group's host owns its own scroll offset (e.g. the\n * [`Tab`](/api/layout/classes/Tab) strip's native clip-frame scroll), so a\n * browser focus-scroll cannot fight or desync it. Defaults to `false` —\n * the standard focus-reveals-the-item behaviour.\n */\n constructor(options: { preventScroll?: boolean } = {}) {\n this._preventScroll = options.preventScroll ?? false;\n }\n\n /**\n * Returns all items currently managed by this roving group.\n *\n * @returns The array of managed {@link Component} instances.\n */\n getItems(): Component[] {\n return this._items;\n }\n\n /**\n * Returns the zero-based index of the currently active item.\n *\n * @returns The active index.\n */\n getActiveIndex(): number {\n return this._activeIndex;\n }\n\n /**\n * Appends a component to the group.\n *\n * @remarks The first item added receives `tabindex=0`; all subsequent items receive `tabindex=-1`.\n * @param component - The component to add.\n */\n add(component: Component): this {\n const isFirst = this._items.length === 0;\n\n this._items.push(component);\n component.getAria().setTabIndex(isFirst ? 0 : -1);\n\n return this;\n }\n\n /**\n * Removes a component from the group.\n *\n * @remarks If the removed item was active, focus moves to the previous item (or index 0).\n * @param component - The component to remove.\n */\n remove(component: Component): this {\n const idx = this._items.indexOf(component);\n\n if (idx < 0) {\n return this;\n }\n\n this._items.splice(idx, 1);\n\n if (this._items.length === 0) {\n this._activeIndex = 0;\n\n return this;\n }\n\n if (idx === this._activeIndex) {\n this.moveTo(Math.max(0, idx - 1));\n } else if (idx < this._activeIndex) {\n this._activeIndex -= 1;\n }\n\n return this;\n }\n\n /**\n * Activates the item at the given index, updating `tabindex` on both the old and new items and transferring DOM focus.\n *\n * @param index - Zero-based index of the item to activate. Clamped to valid range.\n */\n moveTo(index: number): void {\n if (this._items.length === 0) {\n return;\n }\n\n const clampedIndex = Util.clamp(index, 0, this._items.length - 1);\n\n const prev = this._items[this._activeIndex];\n\n if (prev && clampedIndex !== this._activeIndex) {\n prev.getAria().setTabIndex(-1);\n }\n\n this._activeIndex = clampedIndex;\n\n const next = this._items[this._activeIndex];\n\n if (next) {\n next.getAria().setTabIndex(0);\n next.focus(this._preventScroll);\n }\n }\n\n /**\n * Moves focus to the next item, wrapping from the last item back to the first.\n */\n moveNext(): void {\n const count = this._items.length;\n\n if (count === 0) {\n return;\n }\n\n this.moveTo((this._activeIndex + 1) % count);\n }\n\n /**\n * Moves focus to the previous item, wrapping from the first item back to the last.\n */\n movePrev(): void {\n const count = this._items.length;\n\n if (count === 0) {\n return;\n }\n\n this.moveTo((this._activeIndex - 1 + count) % count);\n }\n}\n"],"mappings":"2CAqBA,IAAa,eAAb,KAA4B,CAExB,OAA8B,CAAC,EAC/B,aAA+B,EAC/B,eAUA,YAAY,EAAuC,CAAC,EAAG,CACnD,KAAK,eAAiB,EAAQ,eAAiB,EACnD,CAOA,UAAwB,CACpB,OAAO,KAAK,MAChB,CAOA,gBAAyB,CACrB,OAAO,KAAK,YAChB,CAQA,IAAI,EAA4B,CAC5B,IAAM,EAAU,KAAK,OAAO,SAAW,EAKvC,OAHA,KAAK,OAAO,KAAK,CAAS,EAC1B,EAAU,QAAQ,CAAC,CAAC,YAAY,EAAU,EAAI,EAAE,EAEzC,IACX,CAQA,OAAO,EAA4B,CAC/B,IAAM,EAAM,KAAK,OAAO,QAAQ,CAAS,EAoBzC,OAlBI,EAAM,EACC,MAGX,KAAK,OAAO,OAAO,EAAK,CAAC,EAErB,KAAK,OAAO,SAAW,GACvB,KAAK,aAAe,EAEb,OAGP,IAAQ,KAAK,aACb,KAAK,OAAO,KAAK,IAAI,EAAG,EAAM,CAAC,CAAC,EACzB,EAAM,KAAK,cAClB,OAAK,aAGF,MACX,CAOA,OAAO,EAAqB,CACxB,GAAI,KAAK,OAAO,SAAW,EACvB,OAGJ,IAAM,EAAe,EAAK,MAAM,EAAO,EAAG,KAAK,OAAO,OAAS,CAAC,EAE1D,EAAO,KAAK,OAAO,KAAK,cAE1B,GAAQ,IAAiB,KAAK,cAC9B,EAAK,QAAQ,CAAC,CAAC,YAAY,EAAE,EAGjC,KAAK,aAAe,EAEpB,IAAM,EAAO,KAAK,OAAO,KAAK,cAE1B,IACA,EAAK,QAAQ,CAAC,CAAC,YAAY,CAAC,EAC5B,EAAK,MAAM,KAAK,cAAc,EAEtC,CAKA,UAAiB,CACb,IAAM,EAAQ,KAAK,OAAO,OAEtB,IAAU,GAId,KAAK,QAAQ,KAAK,aAAe,GAAK,CAAK,CAC/C,CAKA,UAAiB,CACb,IAAM,EAAQ,KAAK,OAAO,OAEtB,IAAU,GAId,KAAK,QAAQ,KAAK,aAAe,EAAI,GAAS,CAAK,CACvD,CACJ"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./DOM-C-Edb3tA.js";import{S as t,b as n,h as r,t as i,v as a}from"./Component-B0ShfPVi.js";import{t as o}from"./ListenerBag-WPdKuuds.js";import{t as s}from"./Glyph-_VeBacS2.js";var AutoRepeat=class{_initialDelay;_decay;_floor;_onTick;_handle=null;_delay;constructor(e){this._initialDelay=e.initialDelay,this._decay=e.decay,this._floor=e.floor,this._onTick=e.onTick,this._delay=e.initialDelay}start(){this._onTick(),this._delay=this._initialDelay,this.scheduleNext()}stop(){this._handle!==null&&(clearTimeout(this._handle),this._handle=null),this._delay=this._initialDelay}isRunning(){return this._handle!==null}scheduleNext(){this._handle=setTimeout(()=>{this._onTick(),this._delay=Math.max(this._floor,this._delay*this._decay),this.scheduleNext()},this._delay)}};function scrollShadowRamp(e){return Math.max(0,Math.min(1,(e-1)/40))}function scrollShadowBoxShadow(){let e=`12px`;return`inset 0 ${e} ${e} -${e} var(--ts-ss-top, transparent),inset 0 -${e} ${e} -${e} var(--ts-ss-bottom, transparent),inset ${e} 0 ${e} -${e} var(--ts-ss-left, transparent),inset -${e} 0 ${e} -${e} var(--ts-ss-right, transparent)`}function scrollShadowEdgeValue(e){return e===0?null:`color-mix(in srgb, var(--ts-ui-scroll-shadow-color) ${e}%, transparent)`}var c=`ts-ui-dragging`,l=!1;function ensureSuppressRule(){l||(l=!0,new n({scope:`selector`,name:`html.ts-ui-dragging > *`,styles:{pointerEvents:`none`}}))}function beginPointerDrag(t){ensureSuppressRule(),e.sink.apply(e.source.getDocumentElement(),{addClass:[c],style:{cursor:t}})}function endPointerDrag(){e.sink.apply(e.source.getDocumentElement(),{removeClass:[c],style:{cursor:``}})}var u=2,d=30,f=10,p=400,m=.75,h=40,g=40,ScrollArrowButton=class extends i{_glyph;_disabled=!1;_listeners=new o;_repeat;constructor(e){super(),this.setWidth(12),this.setHeight(12),this.setCursor(`default`),this.setBackgroundColor(`var(--ts-ui-scrollbar-arrow-bg, transparent)`),this.setForegroundColor(`var(--ts-ui-scrollbar-arrow-color, rgba(0, 0, 0, 0.55))`),a.isReducedMotion()||this.setTransition(`color 120ms ease-out`),this._glyph=new s(`unicode-arrow-`+e),this._glyph.setPreferredSize({width:12,height:12}),this._glyph.setFontSize(f),this._glyph.setPointerEvents(`none`),super.addComponent(this._glyph),this._repeat=new AutoRepeat({initialDelay:p,decay:m,floor:h,onTick:()=>this.emit(`tick`)}),t.addListener(this,`mousedown`,{stop:!0,prevent:!0,handler:this._onMouseDown}),t.addListener(this,`mouseover`,this._onMouseOver),t.addListener(this,`mouseout`,this._onMouseOut),t.addViewportListener(this,`mouseup`,this._onMouseUp),t.addViewportListener(this,`mouseleave`,this._onMouseUp)}on(e,t){return this._listeners.add(e,t),this}off(e,t){return this._listeners.remove(e,t),this}emit(e,...t){this._listeners.fire(e,...t)}isDisabledState(){return this._disabled}setDisabledState(e){this._disabled!==e&&(this._disabled=e,e?(this._repeat.stop(),this.setForegroundColor(`var(--ts-ui-scrollbar-arrow-disabled-color, rgba(0, 0, 0, 0.18))`)):this.setForegroundColor(`var(--ts-ui-scrollbar-arrow-color, rgba(0, 0, 0, 0.55))`))}_onMouseDown=e=>{this._disabled||this._repeat.start()};_onMouseUp=()=>{this._repeat.isRunning()&&this._repeat.stop()};_onMouseOver=()=>{this._disabled||this.setBackgroundColor(`var(--ts-ui-scrollbar-arrow-hover-bg, rgba(0, 0, 0, 0.06))`)};_onMouseOut=()=>{this.setBackgroundColor(`var(--ts-ui-scrollbar-arrow-bg, transparent)`)}},_={backgroundColor:`var(--ts-ui-scrollbar-track, rgba(0, 0, 0, 0.04))`,touchAction:`none`};function isScrollbarTarget(t){if(!e.source.isNode(t.target))return!1;for(let n=e.source.intern(t.target);n;n=e.source.getParentElement(n))if(e.source.matches(n,`.Scrollbar`))return!0;return!1}var Scrollbar=class extends i{_orientation=`vertical`;_thumb;_viewportSize=0;_contentSize=0;_scrollPosition=0;_thumbSize=-1;_thumbPos=-1;_dragStartClient=0;_dragStartScroll=0;_thumbHovered=!1;_thumbDragging=!1;_listeners=new o;_arrowsEnabled=!0;_arrowStep=g;_arrowStart=null;_arrowEnd=null;constructor(e=`vertical`,n,r){super(n,{..._,...r??{}}),this._orientation=e,n?.arrowStep!==void 0&&(this._arrowStep=n.arrowStep),n?.arrowsEnabled!==void 0&&(this._arrowsEnabled=n.arrowsEnabled),this.setUserSelect(`none`),this.getAria().setHidden(!0),this.isVertical()?this.setWidth(12):this.setHeight(12),this._thumb=new i,this._thumb.setBackgroundColor(`var(--ts-ui-scrollbar-thumb, rgba(0, 0, 0, 0.35))`),this._thumb.setCursor(`grab`),this._thumb.setWillChange(`transform`),this.isVertical()?(this._thumb.setX(u),this._thumb.setY(0),this._thumb.setWidth(8)):(this._thumb.setX(0),this._thumb.setY(u),this._thumb.setHeight(8)),super.addComponent(this._thumb),this._arrowsEnabled&&this.buildArrows(),t.addListener(this._thumb,`mousedown`,{prevent:!0,handler:this._onDragStart}),t.addListener(this._thumb,`touchstart`,{passive:!1,prevent:!0,handler:this._onDragStart}),t.addListener(this._thumb,`mouseover`,this._onThumbMouseOver),t.addListener(this._thumb,`mouseout`,this._onThumbMouseOut),t.addListener(this,`mousedown`,{prevent:!0,handler:this._onTrackClick}),t.addListener(this,`touchstart`,{passive:!1,prevent:!0,handler:this._onTrackClick}),this.applyListeners(n?.listeners)}buildArrows(){let e=this.isVertical()?`up`:`left`,t=this.isVertical()?`down`:`right`;this._arrowStart=new ScrollArrowButton(e),this._arrowStart.setX(0),this._arrowStart.setY(0),this._arrowStart.on(`tick`,this._onArrowStartTick),this._arrowStart.setDisabledState(!0),super.addComponent(this._arrowStart),this._arrowEnd=new ScrollArrowButton(t),this._arrowEnd.setX(0),this._arrowEnd.setY(0),this._arrowEnd.on(`tick`,this._onArrowEndTick),super.addComponent(this._arrowEnd)}_onArrowStartTick=()=>this.onArrowTick(-1);_onArrowEndTick=()=>this.onArrowTick(1);onArrowTick(e){let t=Math.max(0,this._contentSize-this._viewportSize),n=Math.max(0,Math.min(t,this._scrollPosition+e*this._arrowStep));n!==this._scrollPosition&&this.emit(`scroll`,n)}disposeArrows(){this._arrowStart&&=(super.removeComponent(this._arrowStart),null),this._arrowEnd&&=(super.removeComponent(this._arrowEnd),null)}_onThumbMouseOver=()=>{this._thumbHovered=!0,this.updateThumbFill()};_onThumbMouseOut=()=>{this._thumbHovered=!1,this.updateThumbFill()};updateThumbFill(){this._thumb.setBackgroundColor(this._thumbHovered||this._thumbDragging?`var(--ts-ui-scrollbar-thumb-hover, rgba(0, 0, 0, 0.55))`:`var(--ts-ui-scrollbar-thumb, rgba(0, 0, 0, 0.35))`)}on(e,t){return this._listeners.add(e,t),this}off(e,t){return this._listeners.remove(e,t),this}emit(e,...t){this._listeners.fire(e,...t)}setMetrics(e,t,n){this._viewportSize=e,this._contentSize=t,this._scrollPosition=n;let r=t>e;if(this.setDisplayed(r),!r)return this;let i=this.getTrackLength();if(i<=0)return this;let a=e/t,o=Math.max(d,Math.floor(i*a));this._thumbSize!==o&&(this._thumbSize=o,this.setThumbSize(o));let s=Math.max(0,t-e),c=Math.max(0,i-o),l=s>0?Math.round(n/s*c):0;this._thumbPos!==l&&(this._thumbPos=l,this.setThumbPos(l));let f=this.axisBox();if(this.isVertical()?(this._thumb.setX(f.crossOrigin+u),this._thumb.setWidth(f.crossExtent-4)):(this._thumb.setY(f.crossOrigin+u),this._thumb.setHeight(f.crossExtent-4)),this._arrowsEnabled&&this._arrowStart&&this._arrowEnd){let e=f.origin+f.extent-12;this.isVertical()?(this._arrowStart.setX(f.crossOrigin),this._arrowStart.setY(f.origin),this._arrowStart.setWidth(f.crossExtent),this._arrowEnd.setX(f.crossOrigin),this._arrowEnd.setY(e),this._arrowEnd.setWidth(f.crossExtent)):(this._arrowStart.setY(f.crossOrigin),this._arrowStart.setX(f.origin),this._arrowStart.setHeight(f.crossExtent),this._arrowEnd.setY(f.crossOrigin),this._arrowEnd.setX(e),this._arrowEnd.setHeight(f.crossExtent)),this._arrowStart.setDisabledState(n<=0),this._arrowEnd.setDisabledState(n>=s)}return this}getTrackWidth(){return 12}getOrientation(){return this._orientation}isArrowsEnabled(){return this._arrowsEnabled}setArrowsEnabled(e){return this._arrowsEnabled===e?this:(this._arrowsEnabled=e,e?this.buildArrows():this.disposeArrows(),this.setMetrics(this._viewportSize,this._contentSize,this._scrollPosition),this)}getArrowStep(){return this._arrowStep}setArrowStep(e){return this._arrowStep=e,this}isVertical(){return this._orientation===`vertical`}axisBox(){let e=this.getContentBounds()??{x:0,y:0,width:this.getWidth()||0,height:this.getHeight()||0};return this.isVertical()?{origin:e.y,extent:e.height,crossOrigin:e.x,crossExtent:e.width}:{origin:e.x,extent:e.width,crossOrigin:e.y,crossExtent:e.height}}getTrackLength(){let e=this._arrowsEnabled?24:0;return Math.max(0,this.axisBox().extent-e)}getTrackOrigin(){return this.axisBox().origin+(this._arrowsEnabled?12:0)}setThumbSize(e){this.isVertical()?this._thumb.setHeight(e):this._thumb.setWidth(e)}setThumbPos(e){let t=this.getTrackOrigin();this.isVertical()?this._thumb.setTranslate(0,t+e):this._thumb.setTranslate(t+e,0)}extractClientPrimary(e){let t=this.isVertical(),n=e;if(n.touches!==void 0){let e=n.touches.length>0?n.touches[0]:n.changedTouches[0];return e?t?e.clientY:e.clientX:0}let r=e;return t?r.clientY:r.clientX}_onDragStart=e=>{this._dragStartClient=this.extractClientPrimary(e),this._dragStartScroll=this._scrollPosition,this._thumbDragging=!0,this.updateThumbFill(),t.addViewportListener(this,`mousemove`,this._onDragMove),t.addViewportListener(this,`mouseup`,this._onDragEnd),t.addViewportListener(this,`touchmove`,this._onDragMove),t.addViewportListener(this,`touchend`,this._onDragEnd),t.addViewportListener(this,`touchcancel`,this._onDragEnd),beginPointerDrag(`grabbing`)};_onDragMove=e=>{let t=this.getTrackLength(),n=Math.max(0,this._contentSize-this._viewportSize),r=Math.max(0,t-this._thumbSize);if(r<=0)return!0;let i=(this.extractClientPrimary(e)-this._dragStartClient)/r*n,a=Math.max(0,Math.min(n,this._dragStartScroll+i));return this.emit(`scroll`,a),!0};_onDragEnd=e=>(t.removeViewportListener(this,`mousemove`,this._onDragMove),t.removeViewportListener(this,`mouseup`,this._onDragEnd),t.removeViewportListener(this,`touchmove`,this._onDragMove),t.removeViewportListener(this,`touchend`,this._onDragEnd),t.removeViewportListener(this,`touchcancel`,this._onDragEnd),this._thumbDragging=!1,this.updateThumbFill(),endPointerDrag(),!0);_onTrackClick=t=>{let n=this.isVertical(),r,i=t;if(i.touches!==void 0){let t=i.touches.length>0?i.touches[0]:i.changedTouches[0],a=this.getElement();if(!t||!a)return;let o=e.source.getViewportRect(this),s=this.getBorderSize();r=n?t.clientY-o.top-s.top:t.clientX-o.left-s.left}else{let e=t;r=n?e.offsetY:e.offsetX}let a=this.axisBox(),o=this.getTrackOrigin(),s=a.origin+a.extent;if(this._arrowsEnabled&&(r<o||r>=s-12))return;let c=r-o<this._thumbPos+this._thumbSize/2?-1:1,l=Math.max(0,this._contentSize-this._viewportSize),u=Math.max(0,Math.min(l,this._scrollPosition+c*this._viewportSize));this.emit(`scroll`,u)}},v=r(Scrollbar);export{scrollShadowBoxShadow as a,AutoRepeat as c,endPointerDrag as i,isScrollbarTarget as n,scrollShadowEdgeValue as o,beginPointerDrag as r,scrollShadowRamp as s,v as t};
2
+ //# sourceMappingURL=Scrollbar-t8fFrUVQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Scrollbar-t8fFrUVQ.js","names":[],"sources":["../../src/typescript/lib/core/AutoRepeat.ts","../../src/typescript/lib/core/ScrollShadow.ts","../../src/typescript/lib/core/PointerDrag.ts","../../src/typescript/lib/component/container/Scrollbar.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * Construction options for {@link AutoRepeat}.\n *\n * @category Core\n */\nexport interface AutoRepeatOptions {\n /** Delay before the first repeat tick, in ms. */\n initialDelay: number;\n /** Multiplier applied to the delay after each tick (`0 < decay <= 1`). */\n decay: number;\n /** Lower bound the decaying delay never drops below, in ms. */\n floor: number;\n /** Invoked once immediately on {@link AutoRepeat.start} and once per scheduled tick. */\n onTick: () => void;\n}\n\n/**\n * The press-and-hold *accelerating* auto-repeat state machine, extracted from the\n * spin button and scrollbar arrow so both drive one implementation.\n *\n * {@link start} fires `onTick` once immediately, then schedules repeats whose\n * interval starts at `initialDelay` and shrinks by `decay` after every tick,\n * never dropping below `floor`. {@link stop} cancels the schedule and resets the\n * interval, so a subsequent press begins again at `initialDelay`.\n *\n * It is a plain class (no DOM element, so not `callable()`-wrapped) and drives an\n * owner-supplied callback rather than emitting its own events — each host keeps\n * dispatching through its own event surface. `setTimeout` is a process timer, not\n * a DOM call, so it does not route through the DOM seam.\n *\n * @category Core\n */\nexport class AutoRepeat {\n\n private readonly _initialDelay: number;\n private readonly _decay: number;\n private readonly _floor: number;\n private readonly _onTick: () => void;\n private _handle: ReturnType<typeof setTimeout> | null = null;\n private _delay: number;\n\n /**\n * @param options - The repeat timing and the per-tick callback.\n */\n constructor(options: AutoRepeatOptions) {\n this._initialDelay = options.initialDelay;\n this._decay = options.decay;\n this._floor = options.floor;\n this._onTick = options.onTick;\n this._delay = options.initialDelay;\n }\n\n /**\n * Fires `onTick` immediately, then schedules accelerating repeats starting\n * at `initialDelay`.\n */\n start(): void {\n this._onTick();\n this._delay = this._initialDelay;\n this.scheduleNext();\n }\n\n /**\n * Cancels any pending schedule and resets the interval to `initialDelay`.\n */\n stop(): void {\n if (this._handle !== null) {\n clearTimeout(this._handle);\n this._handle = null;\n }\n\n this._delay = this._initialDelay;\n }\n\n /**\n * Returns whether a repeat schedule is currently armed.\n *\n * @returns `true` between {@link start} and {@link stop}.\n */\n isRunning(): boolean {\n return this._handle !== null;\n }\n\n /**\n * Schedules the next tick at the current interval, then decays the interval\n * (×`decay`, floored at `floor`) for the tick after it.\n */\n private scheduleNext(): void {\n this._handle = setTimeout(() => {\n this._onTick();\n this._delay = Math.max(this._floor, this._delay * this._decay);\n this.scheduleNext();\n }, this._delay);\n }\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * Shared visual recipe for the position-aware scroll-edge shadows. Both scroll\n * systems paint the same fade — {@link Panel} over native `overflow` scrolling\n * and {@link VirtualScroller} over transform-based virtual lists — so the\n * geometry constants, the box-shadow recipe, and the per-edge colour ramp live\n * here as the single source of truth. Each owner keeps its own overlay element\n * and per-edge cache; only the drift-prone visual maths is shared.\n *\n * @category Core\n */\n\n/**\n * Reach in pixels of each scroll-edge shadow — used as the inset shadow's\n * offset, blur, and (negative) spread, so each edge's fade hugs its border and\n * dies out roughly this far inward.\n *\n * Fixed framework-side rather than themed, for the same reason the keyboard\n * focus indicator fixes its `2px` width (see `Theme.indicator.focus`): the\n * colour is the only part a theme needs to vary, and a constant keeps the\n * overlay's four-shadow geometry simple. `12px` reads as a soft edge cue\n * without masking a meaningful strip of content.\n */\nexport const SCROLL_SHADOW_EXTENT_PX = 12;\n\n/**\n * Distance in pixels over which an edge's shadow ramps from none to full as the\n * scroll position moves away from that edge's extreme. The strength is\n * `clamp(distanceFromExtreme / this, 0, 1)`, so the shadow fades in smoothly\n * just after leaving an edge and fades out as the opposite edge is approached,\n * instead of popping on/off at a single-pixel threshold. `40px` gives a visible\n * fade without staying faint through a meaningful amount of overflow.\n */\nexport const SCROLL_SHADOW_RAMP_PX = 40;\n\n/**\n * Ramps an edge's shadow in by how far the scroll position sits past that\n * edge's extreme. The `- 1` folds in a sub-pixel epsilon: within 1px of an\n * extreme the strength is 0, so a fractional scrollSize/clientSize mismatch\n * can't leave a phantom fade.\n *\n * @param distance - Pixels the scroll position is past the edge's extreme.\n * @returns The edge strength in the range 0–1.\n */\nexport function scrollShadowRamp(distance: number): number {\n return Math.max(0, Math.min(1, (distance - 1) / SCROLL_SHADOW_RAMP_PX));\n}\n\n/**\n * Builds the four-layer inset `box-shadow` recipe — one blurred shadow per edge,\n * each gated by a local custom property (`--ts-ss-top` / `-bottom` / `-left` /\n * `-right`) defaulting to `transparent`, so lighting an edge is a single\n * property flip rather than a shadow rebuild. The `-extent` spread keeps each\n * shadow hugging its own edge while the equal blur fades it inward over\n * `extent`px, so the edge reads as a soft cast shadow rather than the\n * hard-terminated band a `linear-gradient` would paint.\n *\n * @returns The `box-shadow` value.\n */\nexport function scrollShadowBoxShadow(): string {\n const extent = SCROLL_SHADOW_EXTENT_PX + \"px\";\n\n return (\n `inset 0 ${extent} ${extent} -${extent} var(--ts-ss-top, transparent),` +\n `inset 0 -${extent} ${extent} -${extent} var(--ts-ss-bottom, transparent),` +\n `inset ${extent} 0 ${extent} -${extent} var(--ts-ss-left, transparent),` +\n `inset -${extent} 0 ${extent} -${extent} var(--ts-ss-right, transparent)`\n );\n}\n\n/**\n * Value for one edge's shadow custom property: the theme shadow colour scaled\n * toward transparent by `percent`, or `null` at zero so the `box-shadow` layer\n * falls back to its `transparent` default.\n *\n * @param percent - The edge strength as a whole percentage (0–100).\n * @returns The `color-mix` value, or `null` when the edge is off.\n */\nexport function scrollShadowEdgeValue(percent: number): string | null {\n return percent === 0\n ? null\n : `color-mix(in srgb, var(--ts-ui-scroll-shadow-color) ${percent}%, transparent)`;\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { DOM } from \"~/core/DOM.js\";\nimport { StyleRule } from \"~/core/StyleTarget.js\";\n\n/**\n * Body-level bookkeeping shared by every component that drags a handle against\n * the viewport — a split gutter, a window border, a table column edge, a\n * scrollbar thumb.\n *\n * Two things have to happen together for the duration of such a drag, which is\n * why they live in one call rather than at each drag site:\n *\n * 1. Every direct child of `<html>` stops taking pointer events, so the drag\n * can't snag on whatever the pointer passes over. This is `<body>` plus\n * anything a `Window`, `Drawer`, or `LayerManager`-hosted overlay (Dialog,\n * Menu, Notification, Popover) appends straight to `document.documentElement`\n * rather than into `<body>` — suppressing only `<body>` would leave those\n * subtrees hit-testable, letting a drag that passes over a window's own\n * content (not just ordinary page content) steal the cursor back.\n * 2. The document element holds the drag cursor. This is the half that is easy\n * to miss: suppressing (1) also takes every suppressed subtree — the drag\n * handle included — out of hit-testing, so nothing there resolves a cursor\n * any more and the pointer reverts to the default arrow mid-drag. The\n * document element itself is deliberately left out of the suppression and\n * is what the cursor falls back to, so it has to carry the cursor instead.\n */\n\nconst DRAGGING_CLASS = \"ts-ui-dragging\";\n\n// Module-singleton shared rule, mirroring ensureFrameworkStyleRule in\n// ClassStyleRules.ts: created once, on the first drag, and never disposed.\nlet _suppressRuleCreated = false;\n\nfunction ensureSuppressRule(): void {\n if (_suppressRuleCreated) {\n return;\n }\n\n _suppressRuleCreated = true;\n\n new StyleRule({\n scope: \"selector\",\n name: \"html.\" + DRAGGING_CLASS + \" > *\",\n styles: { pointerEvents: \"none\" },\n });\n}\n\n/**\n * Suppresses pointer events on every direct child of `<html>` and pins\n * `cursor` on `<html>` itself for the duration of a drag. Pair every call\n * with {@link endPointerDrag}.\n *\n * @param cursor - The CSS cursor to hold until the drag ends, normally the one\n * the handle shows on hover so the two can't disagree.\n */\nexport function beginPointerDrag(cursor: string): void {\n ensureSuppressRule();\n\n DOM.sink.apply(DOM.source.getDocumentElement(), {\n addClass: [DRAGGING_CLASS],\n style: { cursor },\n });\n}\n\n/**\n * Restores pointer events and hands the cursor back to whatever the pointer\n * is actually over. Safe to call without a matching {@link beginPointerDrag}\n * — it only clears the class and the inline cursor.\n */\nexport function endPointerDrag(): void {\n DOM.sink.apply(DOM.source.getDocumentElement(), {\n removeClass: [DRAGGING_CLASS],\n style: { cursor: \"\" },\n });\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Animation } from \"~/core/Animation.js\";\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { beginPointerDrag, endPointerDrag } from \"~/core/PointerDrag.js\";\nimport { ListenerBag } from \"~/core/ListenerBag.js\";\nimport { AutoRepeat } from \"~/core/AutoRepeat.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport type { HorizontalSide } from \"~/primitive/Edge.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport type { AxisOrientation } from \"~/primitive/Axis.js\";\n\n/**\n * String-literal union of the events emitted by {@link Scrollbar}.\n *\n * @category Components\n */\nexport type ScrollbarEvent = \"scroll\";\n\n/**\n * String-literal union of the events emitted by the file-local\n * `ScrollArrowButton`.\n */\ntype ScrollArrowEvent = \"tick\";\n\n// Fixed cross-axis (track) width of the custom Scrollbar, in pixels —\n// independent of the OS/browser's native scrollbar width, which\n// `DOM.source.getScrollBarWidth()` measures separately for genuinely\n// native scroll paths. Exported so a caller that needs to reserve space\n// for a Scrollbar it doesn't hold an instance of yet (e.g. Table's\n// column-width and header-button layout math) can read the value\n// directly — the same shape `CollapseSupport.ts` uses for\n// `COLLAPSE_STRIP_SIZE`.\nexport const TRACK_WIDTH = 12;\nconst THUMB_INSET = 2;\nconst THUMB_MIN_SIZE = 30;\n\n// Font size for the Unicode triangle character rendered in each arrow button.\n// The arrow box is TRACK_WIDTH (12) px square; the ambient 14 px theme font\n// produces a 16 px line-box that overflows the 12 px element and is clipped\n// at the bottom by `overflow: hidden`, leaving the visible triangle slid up\n// against the top edge. 10 px shrinks the line-box (= font-size × line-height\n// 1) below the element height so the character fits with even padding above\n// and below — matches the value [`AccordionIndicator`](./AccordionIndicator.ts)\n// uses for its `▶` chevron.\nconst ARROW_GLYPH_FONT_SIZE = 10;\n\n// Initial hold-repeat delay and acceleration parameters for ScrollArrowButton.\n// Mirrors SpinButton's scheduler so a long press on either widget produces the\n// same accelerating tick cadence — 400 ms first interval, multiplied by 0.75\n// each tick, floored at 40 ms.\nconst ARROW_REPEAT_INITIAL_MS = 400;\nconst ARROW_REPEAT_DECAY = 0.75;\nconst ARROW_REPEAT_FLOOR_MS = 40;\n\n// Default per-click scroll step in pixels for arrow buttons. Roughly two rows\n// at default font size in the Table; chosen as a fixed pixel value rather than\n// a derived fraction of viewport so the step size stays predictable as content\n// grows. Owners can override via `setArrowStep(px)`.\nconst DEFAULT_ARROW_STEP_PX = 40;\n\n// Crossfade duration for the arrow's enabled↔disabled colour swap. Matches the\n// 120 ms ease-out cadence Checkbox / Toggle / RadioButton use for their state\n// crossfades so the scrollbar's arrows read as the same UI vocabulary; short\n// enough to feel instant while softening the hard colour flip at each edge.\nconst ARROW_FADE_DURATION_MS = 120;\n\n/**\n * Callback type fired by {@link Scrollbar} when the user drags the thumb or\n * clicks the track. Receives the new scroll position in pixels.\n *\n * @category Components\n */\nexport type ScrollbarListener = (position: number) => void;\n\n/**\n * Construction-time options for {@link Scrollbar}.\n *\n * @category Components\n */\nexport interface ScrollbarOptions extends ComponentOptions {\n\n /**\n * When `true`, the scrollbar renders classic OS-style arrow buttons at\n * each end of the track (up/down for vertical, left/right for horizontal).\n * The buttons step the scroll position by {@link ScrollbarOptions.arrowStep}\n * pixels per click and accelerate while held. The matching arrow shows a\n * dimmed disabled-state colour when scroll is already at that edge.\n * Defaults to `true`; set `false` to suppress the arrows for a minimalist\n * look.\n */\n arrowsEnabled?: boolean;\n\n /**\n * Per-click scroll step in pixels for the arrow buttons. Ignored when\n * `arrowsEnabled` is `false`. Defaults to `40`.\n */\n arrowStep?: number;\n\n /**\n * Multi-event listener bag dispatched to {@link Scrollbar.on} at\n * construction time.\n */\n listeners?: {\n scroll?: ScrollbarListener;\n };\n}\n\n/**\n * Direction for a `ScrollArrowButton`. `\"up\"` / `\"down\"` go on the ends\n * of a vertical scrollbar; `\"left\"` / `\"right\"` on a horizontal one.\n */\ntype ArrowDirection = HorizontalSide | \"up\" | \"down\";\n\n/**\n * A press-and-hold arrow button rendered at one end of a {@link Scrollbar}'s\n * track when arrows are enabled. File-local — not exported from the container\n * barrel because it is a Scrollbar implementation detail.\n *\n * Mirrors the [`SpinButton`](/api/component/input/classes/SpinButton)\n * hold-repeat cadence: a click fires one tick, holding accelerates from a\n * 400 ms initial interval to a 40 ms floor, and release cancels the schedule.\n * When in the disabled state, mousedown is ignored and the glyph renders in\n * the dim colour token.\n */\nclass ScrollArrowButton extends Component {\n\n private _glyph: Glyph;\n private _disabled: boolean = false;\n private _listeners: ListenerBag<ScrollArrowEvent> = new ListenerBag<ScrollArrowEvent>();\n private _repeat: AutoRepeat;\n\n /**\n * Constructs a square TRACK_WIDTH × TRACK_WIDTH arrow button pointing in\n * the given direction.\n *\n * @param direction - One of `\"up\"`, `\"down\"`, `\"left\"`, `\"right\"`.\n */\n constructor(direction: ArrowDirection) {\n super();\n\n this.setWidth(TRACK_WIDTH);\n this.setHeight(TRACK_WIDTH);\n this.setCursor(\"default\");\n this.setBackgroundColor(\"var(--ts-ui-scrollbar-arrow-bg, transparent)\");\n this.setForegroundColor(\"var(--ts-ui-scrollbar-arrow-color, rgba(0, 0, 0, 0.55))\");\n\n // Fade the enabled↔disabled colour swap in setDisabledState instead of a hard\n // switch. Declared at construction (mirrors Checkbox's crossfade) so the initial\n // colour — the start arrow's dim state set by Scrollbar.buildArrows before first\n // paint — appears instantly, and only later at-edge toggles fade. Honours\n // prefers-reduced-motion.\n if (!Animation.isReducedMotion()) {\n this.setTransition(\"color \" + ARROW_FADE_DURATION_MS + \"ms ease-out\");\n }\n\n // Fill the full TRACK_WIDTH × TRACK_WIDTH button so `text-align: center`\n // + `line-height: 1` (Glyph char-mode defaults) centre the character\n // within that box. The explicit `fontSize` shrinks the inherited\n // 14 px size so the Unicode triangle's line-box (which scales with\n // font-size) fits inside the 12 px element box and isn't clipped at\n // the bottom by `overflow: hidden` — mirrors the same fix\n // AccordionIndicator applies to its `▶` chevron.\n this._glyph = new Glyph(\"unicode-arrow-\" + direction);\n this._glyph.setPreferredSize({ width: TRACK_WIDTH, height: TRACK_WIDTH });\n this._glyph.setFontSize(ARROW_GLYPH_FONT_SIZE);\n // The glyph fills the whole button, so without this a click's target is\n // the glyph element. The Event system routes `addListener` callbacks only\n // to the exact target id (no bubbling), so the arrow's own\n // mousedown/mouseover/mouseout handlers below would never fire. Making\n // the glyph non-interactive lets pointer events fall through to the arrow.\n this._glyph.setPointerEvents(\"none\");\n\n super.addComponent(this._glyph);\n\n this._repeat = new AutoRepeat({\n initialDelay: ARROW_REPEAT_INITIAL_MS,\n decay: ARROW_REPEAT_DECAY,\n floor: ARROW_REPEAT_FLOOR_MS,\n onTick: () => this.emit(\"tick\"),\n });\n\n Event.addListener(this, \"mousedown\", { stop: true, prevent: true, handler: this._onMouseDown });\n Event.addListener(this, \"mouseover\", this._onMouseOver);\n Event.addListener(this, \"mouseout\", this._onMouseOut);\n Event.addViewportListener(this, \"mouseup\", this._onMouseUp);\n Event.addViewportListener(this, \"mouseleave\", this._onMouseUp);\n }\n\n /**\n * Registers a listener for one of this arrow button's events.\n *\n * @param event - `\"tick\"` fires on each logical tick (initial mousedown\n * plus every subsequent hold-repeat tick).\n * @param listener - The callback invoked when the event fires.\n *\n * @returns This arrow button, for method chaining.\n */\n on(event: \"tick\", listener: () => void): this;\n on(event: ScrollArrowEvent, listener: Function): this {\n this._listeners.add(event, listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered listener. The exact callback reference\n * must match.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The callback to remove.\n *\n * @returns This arrow button, for method chaining.\n */\n off(event: ScrollArrowEvent, listener: Function): this {\n this._listeners.remove(event, listener);\n\n return this;\n }\n\n /**\n * Fires every listener registered for `event` with no arguments.\n *\n * @param event - The event to emit.\n */\n protected emit(event: \"tick\"): void;\n protected emit(event: ScrollArrowEvent, ...payload: unknown[]): void {\n this._listeners.fire(event, ...payload);\n }\n\n /**\n * Returns whether this arrow is currently in the at-edge disabled state.\n *\n * @returns `true` when disabled, `false` otherwise.\n */\n isDisabledState(): boolean {\n return this._disabled;\n }\n\n /**\n * Toggles the disabled visual state and behaviour. Disabled arrows render\n * the glyph in the dim colour token and ignore mousedown events; any\n * in-flight hold-repeat schedule is cancelled.\n *\n * @param disabled - `true` to disable, `false` to enable.\n */\n setDisabledState(disabled: boolean): void {\n if (this._disabled === disabled) {\n return;\n }\n\n this._disabled = disabled;\n\n if (disabled) {\n this._repeat.stop();\n this.setForegroundColor(\"var(--ts-ui-scrollbar-arrow-disabled-color, rgba(0, 0, 0, 0.18))\");\n } else {\n this.setForegroundColor(\"var(--ts-ui-scrollbar-arrow-color, rgba(0, 0, 0, 0.55))\");\n }\n }\n\n /**\n * Handles mousedown on the button. Stops propagation so the parent\n * Scrollbar's track-click handler does not also fire, then (if not\n * disabled) fires the first tick and schedules accelerating repeats.\n *\n * @param e - The mousedown event. Only ever a primary-button press — the\n * default `button: \"primary\"` registration filters the rest.\n *\n * @remarks Consumes the press and suppresses the browser's default text\n * selection via the registration's `stop`/`prevent` floor.\n */\n private _onMouseDown = (_e: MouseEvent): void => {\n if (!this._disabled) {\n this._repeat.start();\n }\n };\n\n /**\n * Cancels the hold-repeat schedule on mouseup or when the pointer leaves\n * the viewport.\n */\n private _onMouseUp = (): void => {\n if (!this._repeat.isRunning()) {\n return;\n }\n\n this._repeat.stop();\n };\n\n /**\n * Darkens the button background on hover, mirroring the thumb-hover idiom.\n */\n private _onMouseOver = (): void => {\n if (this._disabled) {\n return;\n }\n\n this.setBackgroundColor(\"var(--ts-ui-scrollbar-arrow-hover-bg, rgba(0, 0, 0, 0.06))\");\n };\n\n /**\n * Restores the resting background when the pointer leaves the button.\n */\n private _onMouseOut = (): void => {\n this.setBackgroundColor(\"var(--ts-ui-scrollbar-arrow-bg, transparent)\");\n };\n\n}\n\nconst _defaultScrollbarOptions: Partial<ScrollbarOptions> = {\n backgroundColor: \"var(--ts-ui-scrollbar-track, rgba(0, 0, 0, 0.04))\",\n touchAction: \"none\",\n};\n\n/**\n * The DOM class every {@link Scrollbar} root element carries. `Component.init`\n * stamps `this.constructor.name` on every component's element unconditionally\n * (alongside the shared `ts-ui-component` class), and this is the literal that\n * produces for a `Scrollbar` instance.\n */\nconst SCROLLBAR_ROOT_CLASS = \"Scrollbar\";\n\n/**\n * Returns whether `e`'s target lies inside a {@link Scrollbar}'s own DOM\n * subtree (track, thumb, or arrow buttons). Scrollbars are raw-appended by\n * `Panel.installOverlayScrollbars` outside the Component tree (never through\n * `addComponent`), so a caller can't recognise one by walking\n * `getParentComponent()` — this walks the live DOM instead.\n *\n * This exists for callers that install a blanket `pointerdown` guard over a\n * whole subtree (e.g. a dropdown panel's focus-loss protection, which calls\n * `preventDefault()` so clicking inside the panel doesn't blur the host\n * input before a click is delivered). Calling `preventDefault()` on a\n * `pointerdown` whose target is inside a Scrollbar is exactly what breaks\n * it: per the Pointer Events spec, that suppresses the browser's synthesized\n * `mousedown` compatibility event for a real mouse pointer, and the thumb\n * drag / track-page handlers (`_onDragStart` / `_onTrackClick`) are wired to\n * `mousedown` — so the scrollbar goes dead to mouse input. A blanket guard\n * must check this and skip `preventDefault()` when it's true; doing so can't\n * reintroduce the focus-loss bug the guard exists for, since a Scrollbar\n * never holds DOM focus.\n *\n * @param e - The DOM event to test.\n * @returns True when the event originated inside a Scrollbar's element.\n */\nexport function isScrollbarTarget(e: Event): boolean {\n if (!DOM.source.isNode(e.target)) {\n return false;\n }\n\n for (let handle: Handle | null = DOM.source.intern(e.target); handle; handle = DOM.source.getParentElement(handle)) {\n if (DOM.source.matches(handle, \".\" + SCROLLBAR_ROOT_CLASS)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * A custom virtual scrollbar overlay.\n *\n * Designed for components that own their own scroll state (e.g. transform-based\n * virtual lists) and don't expose native browser scrolling. The owner pushes\n * viewport/content metrics in via {@link Scrollbar.setMetrics} and subscribes\n * to scroll position changes via {@link Scrollbar.on}.\n *\n * The thumb is dragged with the mouse; clicking the track above/beside the\n * thumb pages by one viewport. The scrollbar hides itself when content fits in\n * the viewport. Classic OS-style arrow buttons at each end of the track are\n * controlled by {@link ScrollbarOptions.arrowsEnabled} — enabled by default;\n * set it `false` for a minimalist look.\n *\n * Available in vertical (default) and horizontal orientations; the owner is\n * responsible for sizing the primary axis (height for vertical, width for\n * horizontal) and positioning the bar on the cross axis.\n *\n * @category Components\n */\nclass Scrollbar extends Component<ScrollbarOptions> {\n\n private _orientation : AxisOrientation = \"vertical\";\n private _thumb : Component;\n private _viewportSize : number = 0;\n private _contentSize : number = 0;\n private _scrollPosition : number = 0;\n // Sentinel `-1` rather than `0` so the first `setMetrics` call always\n // writes the thumb's size/position through to the DOM, even when the\n // computed values happen to be `0` (e.g. scroll position at top with\n // arrows enabled, where the constructor-time `setY(0)` would otherwise\n // never get corrected to the arrow-region origin offset).\n private _thumbSize : number = -1;\n private _thumbPos : number = -1;\n private _dragStartClient : number = 0;\n private _dragStartScroll : number = 0;\n // Track hover and drag independently so the thumb-hover fill (driven by\n // updateThumbFill) can stay applied for the whole drag even once the\n // pointer strays outside the thumb's bounds and fires a native mouseout.\n private _thumbHovered : boolean = false;\n private _thumbDragging : boolean = false;\n private _listeners : ListenerBag<ScrollbarEvent> = new ListenerBag<ScrollbarEvent>();\n\n private _arrowsEnabled : boolean = true;\n private _arrowStep : number = DEFAULT_ARROW_STEP_PX;\n private _arrowStart : ScrollArrowButton | null = null;\n private _arrowEnd : ScrollArrowButton | null = null;\n\n /**\n * Constructs a Scrollbar.\n *\n * @param orientation - `\"vertical\"` (default) or `\"horizontal\"`.\n * @param options - Optional configuration bag. ComponentOptions fields are\n * forwarded to `super` so the standard cascade applies; the\n * arrow-specific fields are read here ahead of any DOM construction.\n * @param subclassDefaults - Per-subclass default bag layered over this\n * class's defaults; subclasses forward their `_defaultXxxOptions`\n * constant here.\n */\n constructor(orientation: AxisOrientation = \"vertical\", options?: ScrollbarOptions, subclassDefaults?: Partial<ScrollbarOptions>) {\n super(options, { ..._defaultScrollbarOptions, ...(subclassDefaults ?? {}) });\n\n this._orientation = orientation;\n\n // Pull arrow configuration out of options ahead of any DOM work so the\n // thumb / arrow construction below sees the final flags. ComponentOptions\n // fields (visible, backgroundColor, etc.) are already applied by super.\n if (options?.arrowStep !== undefined) {\n this._arrowStep = options.arrowStep;\n }\n if (options?.arrowsEnabled !== undefined) {\n this._arrowsEnabled = options.arrowsEnabled;\n }\n\n this.setUserSelect(\"none\");\n\n // Purely decorative: the real scroll semantics live on the native scroll\n // region this widget mirrors (overlay Panel, VirtualScroller), so hide the\n // track / thumb / arrow subtree from assistive tech rather than have it\n // announce a stack of non-interactive divs. Matches Spacer / Glyph.\n this.getAria().setHidden(true);\n\n if (this.isVertical()) {\n this.setWidth(TRACK_WIDTH);\n } else {\n this.setHeight(TRACK_WIDTH);\n }\n\n this._thumb = new Component();\n this._thumb.setBackgroundColor(\"var(--ts-ui-scrollbar-thumb, rgba(0, 0, 0, 0.35))\");\n this._thumb.setCursor(\"grab\");\n\n // Pre-promote to its own compositor layer: setThumbPos moves the\n // thumb via translate on every scroll tick, so the layer should\n // already exist before the first drag/scroll pays to create it.\n this._thumb.setWillChange(\"transform\");\n\n if (this.isVertical()) {\n this._thumb.setX(THUMB_INSET);\n this._thumb.setY(0);\n this._thumb.setWidth(TRACK_WIDTH - 2 * THUMB_INSET);\n } else {\n this._thumb.setX(0);\n this._thumb.setY(THUMB_INSET);\n this._thumb.setHeight(TRACK_WIDTH - 2 * THUMB_INSET);\n }\n\n super.addComponent(this._thumb);\n\n if (this._arrowsEnabled) {\n this.buildArrows();\n }\n\n Event.addListener(this._thumb, \"mousedown\", { prevent: true, handler: this._onDragStart });\n // touchstart defaults to a passive native listener (see Event.ts's\n // PASSIVE_TYPES), which silently no-ops preventDefault() — override\n // explicitly so the `prevent: true` floor above actually applies.\n // NOTE: Event installs exactly one window-level native listener per\n // event type, shared by every registration of that type — so this\n // isn't scoped to just this Scrollbar. Constructing ANY Scrollbar\n // locks \"touchstart\" as passive: false for the WHOLE PAGE for the\n // lifetime of the app (see docs/reference/migration/next.md).\n Event.addListener(this._thumb, \"touchstart\", { passive: false, prevent: true, handler: this._onDragStart });\n Event.addListener(this._thumb, \"mouseover\", this._onThumbMouseOver);\n Event.addListener(this._thumb, \"mouseout\", this._onThumbMouseOut);\n Event.addListener(this, \"mousedown\", { prevent: true, handler: this._onTrackClick });\n // touchstart defaults to a passive native listener (see Event.ts's\n // PASSIVE_TYPES), which silently no-ops preventDefault() — override\n // explicitly so the `prevent: true` floor above actually applies.\n // Same page-wide-lock caveat as the thumb's registration above.\n Event.addListener(this, \"touchstart\", { passive: false, prevent: true, handler: this._onTrackClick });\n\n this.applyListeners(options?.listeners);\n }\n\n /**\n * Constructs and wires the two arrow buttons. Both are seeded at `(0, 0)`;\n * their real position and cross-axis extent are set in `setMetrics`, which\n * is the first point the bar's content box is known. Disabled-state for the\n * start arrow is pre-set since `_scrollPosition` defaults to 0 — without\n * this the start arrow renders enabled for one frame before `setMetrics`\n * corrects it.\n */\n private buildArrows(): void {\n const startDirection: ArrowDirection = this.isVertical() ? \"up\" : \"left\";\n const endDirection: ArrowDirection = this.isVertical() ? \"down\" : \"right\";\n\n this._arrowStart = new ScrollArrowButton(startDirection);\n this._arrowStart.setX(0);\n this._arrowStart.setY(0);\n this._arrowStart.on(\"tick\", this._onArrowStartTick);\n this._arrowStart.setDisabledState(true);\n super.addComponent(this._arrowStart);\n\n this._arrowEnd = new ScrollArrowButton(endDirection);\n // Both axes depend on the bar's content box, which is not resolved yet;\n // `setMetrics` writes the origin and the cross-axis extent.\n this._arrowEnd.setX(0);\n this._arrowEnd.setY(0);\n this._arrowEnd.on(\"tick\", this._onArrowEndTick);\n super.addComponent(this._arrowEnd);\n }\n\n /**\n * Bound forwarder for the start arrow's `\"tick\"` event. Kept as a class\n * field so {@link off}-style detachment would have a stable reference.\n */\n private _onArrowStartTick = (): void => this.onArrowTick(-1);\n\n /**\n * Bound forwarder for the end arrow's `\"tick\"` event.\n */\n private _onArrowEndTick = (): void => this.onArrowTick(+1);\n\n /**\n * Computes the next scroll position one `_arrowStep` away from the current\n * one, clamps it to the valid range, and fires scroll listeners if it\n * changed. The owner's listener call back into `setMetrics` next frame,\n * which refreshes `atStart` / `atEnd` and updates the arrow disabled state.\n *\n * @param direction - `-1` for the start arrow, `+1` for the end arrow.\n */\n private onArrowTick(direction: -1 | 1): void {\n const maxScroll = Math.max(0, this._contentSize - this._viewportSize);\n const newPosition = Math.max(0, Math.min(maxScroll, this._scrollPosition + direction * this._arrowStep));\n\n if (newPosition !== this._scrollPosition) {\n this.emit(\"scroll\", newPosition);\n }\n }\n\n /**\n * Tears down both arrow buttons. Called when arrows are toggled off at\n * runtime; safe when no arrows are currently mounted.\n */\n private disposeArrows(): void {\n if (this._arrowStart) {\n super.removeComponent(this._arrowStart);\n this._arrowStart = null;\n }\n if (this._arrowEnd) {\n super.removeComponent(this._arrowEnd);\n this._arrowEnd = null;\n }\n }\n\n /**\n * Darkens the thumb fill when the cursor moves over it.\n */\n private _onThumbMouseOver = (): void => {\n this._thumbHovered = true;\n this.updateThumbFill();\n };\n\n /**\n * Restores the thumb's resting fill when the cursor leaves it, unless a\n * drag is still in progress.\n */\n private _onThumbMouseOut = (): void => {\n this._thumbHovered = false;\n this.updateThumbFill();\n };\n\n /**\n * Applies the thumb-hover fill whenever the pointer is over the thumb or a\n * drag is in progress, and the resting fill otherwise — so the highlight\n * persists for the whole drag even once the pointer strays outside the\n * thumb's bounds (which fires a native mouseout mid-drag).\n */\n private updateThumbFill(): void {\n this._thumb.setBackgroundColor(this._thumbHovered || this._thumbDragging\n ? \"var(--ts-ui-scrollbar-thumb-hover, rgba(0, 0, 0, 0.55))\"\n : \"var(--ts-ui-scrollbar-thumb, rgba(0, 0, 0, 0.35))\");\n }\n\n /**\n * Registers a listener for one of this scrollbar's events.\n *\n * @param event - `\"scroll\"` fires when the user changes the scroll\n * position by dragging the thumb, clicking the track, or pressing an\n * arrow button, receiving the new scroll position in pixels.\n * @param listener - The callback to invoke when the event fires.\n *\n * @returns This scrollbar, for method chaining.\n */\n on(event: \"scroll\", listener: ScrollbarListener): this;\n on(event: ScrollbarEvent, listener: Function): this {\n this._listeners.add(event, listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered listener. The exact callback reference\n * must match.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The callback to remove.\n *\n * @returns This scrollbar, for method chaining.\n */\n off(event: ScrollbarEvent, listener: Function): this {\n this._listeners.remove(event, listener);\n\n return this;\n }\n\n /**\n * Fires every listener registered for `event` with `payload`, in\n * registration order.\n *\n * @param event - The event to emit.\n * @param payload - Forwarded to each listener.\n */\n protected emit(event: \"scroll\", position: number): void;\n protected emit(event: ScrollbarEvent, ...payload: unknown[]): void {\n this._listeners.fire(event, ...payload);\n }\n\n /**\n * Pushes viewport/content metrics and the current scroll position into the\n * scrollbar. Recomputes the thumb's size, position, and cross-axis extent\n * against the content box, and hides the scrollbar if the content fits in\n * the viewport. When arrows are enabled, repositions both arrows against\n * the content box and refreshes the disabled-at-edge state on both.\n *\n * @param viewportSize - The visible window size in pixels along the scroll axis.\n * @param contentSize - The total scrollable content size in pixels along the scroll axis.\n * @param scrollPosition - The current scroll offset in pixels.\n */\n setMetrics(viewportSize: number, contentSize: number, scrollPosition: number): this {\n this._viewportSize = viewportSize;\n this._contentSize = contentSize;\n this._scrollPosition = scrollPosition;\n\n const overflow = contentSize > viewportSize;\n this.setDisplayed(overflow);\n\n if (!overflow) {\n return this;\n }\n\n const trackLength = this.getTrackLength();\n if (trackLength <= 0) {\n return this;\n }\n\n const ratio = viewportSize / contentSize;\n const newThumbSize = Math.max(THUMB_MIN_SIZE, Math.floor(trackLength * ratio));\n if (this._thumbSize !== newThumbSize) {\n this._thumbSize = newThumbSize;\n this.setThumbSize(newThumbSize);\n }\n\n const maxScroll = Math.max(0, contentSize - viewportSize);\n const maxThumb = Math.max(0, trackLength - newThumbSize);\n const newThumbPos = maxScroll > 0 ? Math.round((scrollPosition / maxScroll) * maxThumb) : 0;\n if (this._thumbPos !== newThumbPos) {\n this._thumbPos = newThumbPos;\n this.setThumbPos(newThumbPos);\n }\n\n const axis = this.axisBox();\n\n // The thumb's cross-axis extent narrows with a bordered/padded content\n // box; re-derived every call, mirroring the end arrow's write below.\n if (this.isVertical()) {\n this._thumb.setX(axis.crossOrigin + THUMB_INSET);\n this._thumb.setWidth(axis.crossExtent - 2 * THUMB_INSET);\n } else {\n this._thumb.setY(axis.crossOrigin + THUMB_INSET);\n this._thumb.setHeight(axis.crossExtent - 2 * THUMB_INSET);\n }\n\n if (this._arrowsEnabled && this._arrowStart && this._arrowEnd) {\n // Position both arrows against the content box — the start arrow\n // at its origin, the end arrow at (origin + extent - TRACK_WIDTH).\n const endPos = axis.origin + axis.extent - TRACK_WIDTH;\n\n // The cross-axis extent too, not just the origin: the arrows are\n // built as a rigid TRACK_WIDTH square, so a bordered bar would keep\n // them at their full width inside a narrower box and overrun the\n // side the border is on. The main axis stays TRACK_WIDTH — that is\n // the gutter the track math reserves at each end.\n if (this.isVertical()) {\n this._arrowStart.setX(axis.crossOrigin);\n this._arrowStart.setY(axis.origin);\n this._arrowStart.setWidth(axis.crossExtent);\n this._arrowEnd.setX(axis.crossOrigin);\n this._arrowEnd.setY(endPos);\n this._arrowEnd.setWidth(axis.crossExtent);\n } else {\n this._arrowStart.setY(axis.crossOrigin);\n this._arrowStart.setX(axis.origin);\n this._arrowStart.setHeight(axis.crossExtent);\n this._arrowEnd.setY(axis.crossOrigin);\n this._arrowEnd.setX(endPos);\n this._arrowEnd.setHeight(axis.crossExtent);\n }\n\n this._arrowStart.setDisabledState(scrollPosition <= 0);\n this._arrowEnd.setDisabledState(scrollPosition >= maxScroll);\n }\n\n return this;\n }\n\n /**\n * Returns the static track width in pixels (the cross-axis dimension).\n *\n * @returns The fixed track width.\n */\n getTrackWidth(): number {\n return TRACK_WIDTH;\n }\n\n /**\n * Returns the scrollbar's orientation.\n *\n * @returns `\"vertical\"` or `\"horizontal\"`.\n */\n getOrientation(): AxisOrientation {\n return this._orientation;\n }\n\n /**\n * Returns whether the arrow buttons at each end of the track are enabled.\n *\n * @returns `true` when arrows are rendered, `false` otherwise.\n */\n isArrowsEnabled(): boolean {\n return this._arrowsEnabled;\n }\n\n /**\n * Enables or disables the end-cap arrow buttons. Intended for\n * construction-time use via {@link ScrollbarOptions.arrowsEnabled};\n * runtime toggles are supported but tear down or build the arrow\n * components on the fly and re-run `setMetrics` against the cached\n * viewport / content / scroll-position triple so the thumb size / position\n * recompute against the new track length.\n *\n * @param enabled - `true` to render arrows, `false` to remove them.\n * @returns This scrollbar, for method chaining.\n */\n setArrowsEnabled(enabled: boolean): this {\n if (this._arrowsEnabled === enabled) {\n return this;\n }\n\n this._arrowsEnabled = enabled;\n\n if (enabled) {\n this.buildArrows();\n } else {\n this.disposeArrows();\n }\n\n this.setMetrics(this._viewportSize, this._contentSize, this._scrollPosition);\n\n return this;\n }\n\n /**\n * Returns the per-click scroll step in pixels used by the arrow buttons.\n *\n * @returns The cached arrow step.\n */\n getArrowStep(): number {\n return this._arrowStep;\n }\n\n /**\n * Sets the per-click scroll step in pixels used by the arrow buttons.\n * No-op when arrows are not enabled, except that the new value is cached\n * and applies on a subsequent {@link Scrollbar.setArrowsEnabled}`(true)`.\n *\n * @param px - The new step size in pixels.\n * @returns This scrollbar, for method chaining.\n */\n setArrowStep(px: number): this {\n this._arrowStep = px;\n\n return this;\n }\n\n /**\n * Returns true if this is a vertical scrollbar.\n *\n * @returns True for vertical, false for horizontal.\n */\n private isVertical(): boolean {\n return this._orientation === \"vertical\";\n }\n\n /**\n * The content box projected onto the scroll axis: `origin` and `extent` run\n * along it, `crossOrigin` and `crossExtent` across it. Falls back to the\n * outer box while the element does not exist yet.\n */\n private axisBox(): { origin: number; extent: number; crossOrigin: number; crossExtent: number } {\n const box = this.getContentBounds()\n ?? { x: 0, y: 0, width: this.getWidth() || 0, height: this.getHeight() || 0 };\n\n return this.isVertical()\n ? { origin: box.y, extent: box.height, crossOrigin: box.x, crossExtent: box.width }\n : { origin: box.x, extent: box.width, crossOrigin: box.y, crossExtent: box.height };\n }\n\n /**\n * Returns the length of the track along the scroll axis available for the\n * thumb to travel, measured in the content box. Subtracts the two arrow\n * regions when arrows are enabled so the thumb travel range stays inside\n * the track between them.\n */\n private getTrackLength(): number {\n const inset = this._arrowsEnabled ? 2 * TRACK_WIDTH : 0;\n\n return Math.max(0, this.axisBox().extent - inset);\n }\n\n /**\n * Returns the primary-axis offset, in the content box, where the track\n * region (thumb travel area) starts. The content-box origin, plus\n * `TRACK_WIDTH` when arrows are enabled (skipping the start arrow).\n */\n private getTrackOrigin(): number {\n const axis = this.axisBox();\n\n return axis.origin + (this._arrowsEnabled ? TRACK_WIDTH : 0);\n }\n\n /**\n * Sets the thumb's size along the scroll axis.\n *\n * @param size - The new thumb size in pixels.\n */\n private setThumbSize(size: number): void {\n if (this.isVertical()) {\n this._thumb.setHeight(size);\n } else {\n this._thumb.setWidth(size);\n }\n }\n\n /**\n * Sets the thumb's position along the scroll axis, offset by the track\n * origin so the thumb sits inside the track region between the arrows\n * when those are enabled.\n *\n * @param pos - The new thumb position in pixels, relative to the track region.\n *\n * @remarks Written through `setTranslate`, not `setX`/`setY`: this runs on\n * every scroll tick, and a `top`/`left` write forces layout + paint where a\n * transform is composite-only. The thumb's static X/Y (set at construction\n * and, for the cross axis, in `setMetrics`) stays put; the full along-axis\n * offset lives entirely in the translate, mirroring the row pool's\n * `setY(0)` + per-frame `setTranslate` split in `VirtualRowView`.\n */\n private setThumbPos(pos: number): void {\n const origin = this.getTrackOrigin();\n\n if (this.isVertical()) {\n this._thumb.setTranslate(0, origin + pos);\n } else {\n this._thumb.setTranslate(origin + pos, 0);\n }\n }\n\n\n /**\n * Reads the client coordinate along the scroll axis from a mouse or touch\n * event, preferring the active touch on touchstart/touchmove and the\n * changed touch on touchend.\n *\n * @param e - A mouse or touch event.\n * @returns The primary-axis coordinate in viewport space.\n */\n private extractClientPrimary(e: MouseEvent | TouchEvent): number {\n const vertical = this.isVertical();\n const touchEvent = e as TouchEvent;\n\n if (touchEvent.touches !== undefined) {\n const t = touchEvent.touches.length > 0\n ? touchEvent.touches[0]\n : touchEvent.changedTouches[0];\n if (!t) {\n return 0;\n }\n return vertical ? t.clientY : t.clientX;\n }\n\n const mouse = e as MouseEvent;\n return vertical ? mouse.clientY : mouse.clientX;\n }\n\n /**\n * Captures the initial client coordinate and scroll position, then attaches\n * viewport listeners so the drag continues even when the pointer or finger\n * leaves the thumb. Holds the hover fill and pins a grabbing cursor for the\n * whole drag.\n *\n * @param e - The mousedown or touchstart event on the thumb. Only ever a\n * primary-button press — the default `button: \"primary\"` registration\n * filters the rest. `preventDefault` is applied by the registration's\n * `prevent: true` floor.\n */\n private _onDragStart = (e: MouseEvent | TouchEvent): void => {\n this._dragStartClient = this.extractClientPrimary(e);\n this._dragStartScroll = this._scrollPosition;\n this._thumbDragging = true;\n this.updateThumbFill();\n\n Event.addViewportListener(this, \"mousemove\", this._onDragMove);\n Event.addViewportListener(this, \"mouseup\", this._onDragEnd);\n Event.addViewportListener(this, \"touchmove\", this._onDragMove);\n Event.addViewportListener(this, \"touchend\", this._onDragEnd);\n Event.addViewportListener(this, \"touchcancel\", this._onDragEnd);\n\n // Suppresses pointer events on document.body for the duration of the\n // drag so the cursor can't snag on other elements, and pins a grabbing\n // cursor on the document element — required because suppressing body\n // pointer events also takes the thumb out of hit-testing, so its own\n // \"grab\" cursor can no longer win a hit test (see PointerDrag.ts).\n beginPointerDrag(\"grabbing\");\n };\n\n /**\n * Translates the client-axis delta into a scroll-position delta proportional\n * to the content/track ratio, clamps it, and fires scroll listeners.\n *\n * @param e - The viewport mousemove or touchmove event during a drag.\n * @returns `true` while a thumb drag is in progress, consuming the move so nothing else tracks the pointer.\n */\n private _onDragMove = (e: MouseEvent | TouchEvent): Event.ListenerResult => {\n const trackLength = this.getTrackLength();\n const maxScroll = Math.max(0, this._contentSize - this._viewportSize);\n const maxThumb = Math.max(0, trackLength - this._thumbSize);\n\n if (maxThumb <= 0) {\n return true;\n }\n\n const delta = this.extractClientPrimary(e) - this._dragStartClient;\n const scrollDelta = (delta / maxThumb) * maxScroll;\n const newPosition = Math.max(0, Math.min(maxScroll, this._dragStartScroll + scrollDelta));\n\n this.emit(\"scroll\", newPosition);\n\n return true;\n };\n\n /**\n * Removes viewport listeners, restores body pointer events and the\n * document cursor, and drops the hover fill unless the pointer is still\n * over the thumb.\n *\n * @param _e - The mouseup/touchend/touchcancel event ending the drag.\n * @returns `true`, consuming the release that ends the thumb drag.\n */\n private _onDragEnd = (_e: Event): Event.ListenerResult => {\n Event.removeViewportListener(this, \"mousemove\", this._onDragMove);\n Event.removeViewportListener(this, \"mouseup\", this._onDragEnd);\n Event.removeViewportListener(this, \"touchmove\", this._onDragMove);\n Event.removeViewportListener(this, \"touchend\", this._onDragEnd);\n Event.removeViewportListener(this, \"touchcancel\", this._onDragEnd);\n\n this._thumbDragging = false;\n this.updateThumbFill();\n\n endPointerDrag();\n\n return true;\n };\n\n /**\n * Pages the scroll position by one viewport size when the user clicks or\n * taps the track outside the thumb. Events on the thumb itself are caught\n * by a separate listener and don't reach here. When arrows are enabled,\n * clicks that land inside an arrow region are ignored so the arrow\n * button's own handler is the sole authority on arrow-region clicks.\n *\n * @param e - The mousedown or touchstart event on the track. Only ever a\n * primary-button press — the default `button: \"primary\"` registration\n * filters the rest. `preventDefault` is applied by the registration's\n * `prevent: true` floor.\n */\n private _onTrackClick = (e: MouseEvent | TouchEvent): void => {\n const vertical = this.isVertical();\n let click: number;\n\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches !== undefined) {\n const t = touchEvent.touches.length > 0\n ? touchEvent.touches[0]\n : touchEvent.changedTouches[0];\n const el = this.getElement();\n if (!t || !el) {\n return;\n }\n // getViewportRect's top-left is the border box, while the mouse\n // branch's offsetX/offsetY below is padding-box-relative; subtract\n // the leading border side so both branches agree before being\n // compared against the content-box-relative axisBox() values.\n const rect = DOM.source.getViewportRect(this);\n const border = this.getBorderSize();\n click = vertical\n ? t.clientY - rect.top - border.top\n : t.clientX - rect.left - border.left;\n } else {\n const mouse = e as MouseEvent;\n click = vertical ? mouse.offsetY : mouse.offsetX;\n }\n\n // When arrows are enabled, ignore clicks that landed inside either\n // arrow region — those are handled by the arrow's own mousedown\n // listener (which also stops propagation, but the touchstart path\n // does not, so we double-check here).\n const axis = this.axisBox();\n const origin = this.getTrackOrigin();\n const outer = axis.origin + axis.extent;\n if (this._arrowsEnabled && (click < origin || click >= outer - TRACK_WIDTH)) {\n return;\n }\n\n // Subtract origin so the thumb-position comparison stays in the\n // track-relative coordinate space (matches `_thumbPos`).\n const trackClick = click - origin;\n const thumbCenter = this._thumbPos + this._thumbSize / 2;\n const direction = trackClick < thumbCenter ? -1 : 1;\n const maxScroll = Math.max(0, this._contentSize - this._viewportSize);\n const newPosition = Math.max(0, Math.min(maxScroll, this._scrollPosition + direction * this._viewportSize));\n\n this.emit(\"scroll\", newPosition);\n };\n}\n\nconst ScrollbarCallable = callable(Scrollbar);\ntype ScrollbarCallable = Scrollbar;\nexport {\n Scrollbar as _Scrollbar,\n ScrollbarCallable as Scrollbar\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./DOM-Ba8YRVel.js";import{a as t,l as n}from"./Position-PBVBW1JS.js";import{S as r,h as i,t as a}from"./Component-w65rPK75.js";import{t as o}from"./Text-CdHf3B-1.js";import{t as s}from"./AbstractInput-B10DfLOf.js";var Label=class extends o{_forId;constructor(e,t,n){if(!t)throw Error(`Label requires a non-empty forId. Use Text for standalone text.`);super(e,{...n??{},tag:n?.tag??`label`}),this._forId=t}getForId(){return this._forId}setForId(t){if(!t)throw Error(`Label forId must be non-empty.`);this._forId=t;let n=this.getElement();return n&&e.sink.apply(n,{setAttr:{for:t}}),this}render(){let t=super.render();return e.sink.apply(t,{setAttr:{for:this._forId}}),t}},c=i(Label),l=4,u=16,d=0,f=100,p=1,m={outline:`none`,cursor:`pointer`},Slider=class extends s{_track;_activeTrack;_thumb;_draggingPointer=null;constructor(e,t){if(super({...e??{}},{...m,...t??{}}),this._track=new a,this._track.setBackgroundColor(`var(--ts-ui-slider-track-bg, rgb(220, 220, 220))`),this._track.setBorderRadius(`999px`),this._track.setPointerEvents(`none`),this._activeTrack=new a,this._activeTrack.setBackgroundColor(`var(--ts-ui-slider-track-active-bg, rgb(30, 100, 200))`),this._activeTrack.setBorderRadius(`999px`),this._activeTrack.setPointerEvents(`none`),this._thumb=new a,this._thumb.setBackgroundColor(`var(--ts-ui-slider-thumb-bg, rgb(255, 255, 255))`),this._thumb.setBorderRadius(`50%`),this._thumb.setBorder(`1px solid var(--ts-ui-form-border, rgb(160, 160, 160))`),this._thumb.setShadow(`0 1px 2px rgba(0, 0, 0, 0.25)`),this._thumb.setPreferredSize({width:u,height:u}),this._thumb.setMaxSize({width:u,height:u}),this._thumb.setPointerEvents(`none`),this._track.addComponent(this._activeTrack),super.addComponent(this._track),super.addComponent(this._thumb),this.getAria().setRole(`slider`),this.getAria().setTabIndex(0),this.getAria().setValueMin(d),this.getAria().setValueMax(f),this.getAria().setValueNow(d),this.installInteraction(),this._options.minValue!==void 0&&this._options.min===void 0&&(this._options.min=this._options.minValue),this._options.maxValue!==void 0&&this._options.max===void 0&&(this._options.max=this._options.maxValue),this._options.min!==void 0&&this.applyMin(this._options.min),this._options.max!==void 0&&this.applyMax(this._options.max),this.applyOrientation(this.getOrientation(),this._options),this._options.value!==void 0){let e=this.snap(this._options.value);this._options.value=e,this.applyValue(e)}else this.applyValue(this.getMin());this._options.enabled!==void 0&&this.applyEnabled(this._options.enabled),this._options.readOnly!==void 0&&this.applyReadOnly(this._options.readOnly)}applyOptions(e){return super.applyOptions(e),e.value!==void 0&&(this._options.value=e.value),e.min!==void 0&&(this._options.min=e.min),e.max!==void 0&&(this._options.max=e.max),e.minValue!==void 0&&(this._options.minValue=e.minValue),e.maxValue!==void 0&&(this._options.maxValue=e.maxValue),e.step!==void 0&&(this._options.step=e.step),e.largeStep!==void 0&&(this._options.largeStep=e.largeStep),e.orientation!==void 0&&(this._options.orientation=e.orientation),e.showTicks!==void 0&&(this._options.showTicks=e.showTicks),e.enabled!==void 0&&(this._options.enabled=e.enabled),e.readOnly!==void 0&&(this._options.readOnly=e.readOnly),this}getValue(){return this._options.value??this.getMin()}setValue(e){let t=this.snap(e);return t===this.getValue()?this:(this._options.value=t,this.applyValue(t),this.notifyChange(t),r.fireEvent(this,`input`),this)}getMin(){return this._options.min??d}setMin(e){return this._options.min=e,this.applyMin(e),this.applyValue(this.snap(this.getValue())),this}getMax(){return this._options.max??f}setMax(e){return this._options.max=e,this.applyMax(e),this.applyValue(this.snap(this.getValue())),this}setMinValue(e){return this.setMin(e)}getMinValue(){return this.getMin()}setMaxValue(e){return this.setMax(e)}getMaxValue(){return this.getMax()}getStep(){return this._options.step??p}setStep(e){return this._options.step=e,this}getLargeStep(){return this._options.largeStep??this.getStep()*10}setLargeStep(e){return this._options.largeStep=e,this}getOrientation(){return this._options.orientation??`horizontal`}setOrientation(e){return this._options.orientation=e,this.applyOrientation(e),this.applyValue(this.getValue()),this}isShowTicks(){return this._options.showTicks??!1}setShowTicks(e){return this._options.showTicks=e,this}on(e,t){return e===`action`?(r.addListener(this,`input`,t),this):super.on(e,t)}off(e,t){return e===`action`?(r.removeListener(this,`input`,t),this):super.off(e,t)}getBaseline(){let e=this.getPreferredSize();return e?e.height-2:null}doLayout(){let e=this.getContentBounds();if(!e)return this;let t=this.getOrientation()===`horizontal`,n=e.width,r=e.height,i=this.getMin(),a=this.getMax()-i,o=a>0?(this.getValue()-i)/a:0;if(t){let t=Math.round((r-l)/2);this._track.setX(e.x),this._track.setY(e.y+t),this._track.setSize({width:n,height:l});let i=Math.round(n*o);this._activeTrack.setX(0),this._activeTrack.setY(0),this._activeTrack.setSize({width:i,height:l});let a=Math.round((n-u)*o),s=Math.round((r-u)/2);this._thumb.setSize({width:u,height:u}),this._thumb.setX(e.x+a),this._thumb.setY(e.y+s)}else{let t=Math.round((n-l)/2);this._track.setX(e.x+t),this._track.setY(e.y),this._track.setSize({width:l,height:r});let i=Math.round(r*o);this._activeTrack.setX(0),this._activeTrack.setY(r-i),this._activeTrack.setSize({width:l,height:i});let a=Math.round((n-u)/2),s=Math.round((r-u)*(1-o));this._thumb.setSize({width:u,height:u}),this._thumb.setX(e.x+a),this._thumb.setY(e.y+s)}return this}installInteraction(){r.addListener(this,`pointerdown`,t=>{if(!this.isEnabled()||this.isReadOnly())return;t.preventDefault(),this.focus();let n=this.getElement();n&&(e.sink.setPointerCapture(n,t.pointerId),this._draggingPointer=t.pointerId),this.setValue(this.valueAtPointer(t))}),r.addListener(this,`pointermove`,e=>{this._draggingPointer===e.pointerId&&this.setValue(this.valueAtPointer(e))});let release=t=>{if(this._draggingPointer!==t.pointerId)return;let n=this.getElement();n&&e.source.hasPointerCapture(n,t.pointerId)&&e.sink.releasePointerCapture(n,t.pointerId),this._draggingPointer=null};r.addListener(this,`pointerup`,release),r.addListener(this,`pointercancel`,release),r.addListener(this,`lostpointercapture`,release),r.addListener(this,`keydown`,e=>{if(!this.isEnabled()||this.isReadOnly())return;let t=this.getStep(),n=this.getLargeStep(),r=this.getMin(),i=this.getMax();switch(e.key){case`ArrowRight`:case`ArrowUp`:e.preventDefault(),this.setValue(this.getValue()+t);break;case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),this.setValue(this.getValue()-t);break;case`PageUp`:e.preventDefault(),this.setValue(this.getValue()+n);break;case`PageDown`:e.preventDefault(),this.setValue(this.getValue()-n);break;case`Home`:e.preventDefault(),this.setValue(r);break;case`End`:e.preventDefault(),this.setValue(i)}})}valueAtPointer(t){if(!this.getElement())return this.getValue();let r=e.source.getViewportRect(this),i=this.getContentBounds()??{x:0,y:0,width:r.width,height:r.height},a=this.getBorderSize(),o=r.left+a.left+i.x,s=r.top+a.top+i.y,c=this.getOrientation()===`horizontal`?i.width>0?(t.clientX-o)/i.width:0:i.height>0?1-(t.clientY-s)/i.height:0,l=n.clamp(c,0,1),u=this.getMin();return u+(this.getMax()-u)*l}snap(e){let t=this.getMin(),r=this.getMax(),i=this.getStep(),a=n.clamp(e,t,r);if(i<=0)return a;let o=t+Math.round((a-t)/i)*i;return n.clamp(o,t,r)}applyValue(e){this._options.value=e,this.getAria().setValueNow(e),this.scheduleLayout()}applyMin(e){this.getAria().setValueMin(e)}applyMax(e){this.getAria().setValueMax(e)}applyOrientation(e,n){this.getAria().setOrientation(e);let r=e===`horizontal`;n?.preferredSize===void 0?this.setPreferredSize(r?{width:200,height:u}:{width:u,height:200}):this.setPreferredSize(n.preferredSize),n?.maxSize===void 0?this.setMaxSize(r?{width:t,height:u}:{width:u,height:t}):this.setMaxSize(n.maxSize),this.scheduleLayout()}applyEnabled(e){this.getAria().setDisabled(!e),this.getAria().setTabIndex(e?0:-1),this.setCursor(e?`pointer`:`default`)}applyReadOnly(e){this.getAria().setReadOnly(e)}},h=i(Slider);export{c as n,h as t};
2
- //# sourceMappingURL=Slider-DZ9drUxn.js.map
1
+ import{t as e}from"./DOM-C-Edb3tA.js";import{a as t,l as n}from"./Position-BwtxouxK.js";import{S as r,h as i,t as a}from"./Component-B0ShfPVi.js";import{t as o}from"./Text-CMKnK9uB.js";import{t as s}from"./AbstractInput-sRNPzWel.js";var Label=class extends o{_forId;constructor(e,t,n){if(!t)throw Error(`Label requires a non-empty forId. Use Text for standalone text.`);super(e,{...n??{},tag:n?.tag??`label`}),this._forId=t}getForId(){return this._forId}setForId(t){if(!t)throw Error(`Label forId must be non-empty.`);this._forId=t;let n=this.getElement();return n&&e.sink.apply(n,{setAttr:{for:t}}),this}render(){let t=super.render();return e.sink.apply(t,{setAttr:{for:this._forId}}),t}},c=i(Label),l=4,u=16,d=0,f=100,p=1,m={outline:`none`,cursor:`pointer`},Slider=class extends s{_track;_activeTrack;_thumb;_draggingPointer=null;constructor(e,t){if(super({...e??{}},{...m,...t??{}}),this._track=new a,this._track.setBackgroundColor(`var(--ts-ui-slider-track-bg, rgb(220, 220, 220))`),this._track.setBorderRadius(`999px`),this._track.setPointerEvents(`none`),this._activeTrack=new a,this._activeTrack.setBackgroundColor(`var(--ts-ui-slider-track-active-bg, rgb(30, 100, 200))`),this._activeTrack.setBorderRadius(`999px`),this._activeTrack.setPointerEvents(`none`),this._thumb=new a,this._thumb.setBackgroundColor(`var(--ts-ui-slider-thumb-bg, rgb(255, 255, 255))`),this._thumb.setBorderRadius(`50%`),this._thumb.setBorder(`1px solid var(--ts-ui-form-border, rgb(160, 160, 160))`),this._thumb.setShadow(`0 1px 2px rgba(0, 0, 0, 0.25)`),this._thumb.setPreferredSize({width:u,height:u}),this._thumb.setMaxSize({width:u,height:u}),this._thumb.setPointerEvents(`none`),this._track.addComponent(this._activeTrack),super.addComponent(this._track),super.addComponent(this._thumb),this.getAria().setRole(`slider`),this.getAria().setTabIndex(0),this.getAria().setValueMin(d),this.getAria().setValueMax(f),this.getAria().setValueNow(d),this.installInteraction(),this._options.minValue!==void 0&&this._options.min===void 0&&(this._options.min=this._options.minValue),this._options.maxValue!==void 0&&this._options.max===void 0&&(this._options.max=this._options.maxValue),this._options.min!==void 0&&this.applyMin(this._options.min),this._options.max!==void 0&&this.applyMax(this._options.max),this.applyOrientation(this.getOrientation(),this._options),this._options.value!==void 0){let e=this.snap(this._options.value);this._options.value=e,this.applyValue(e)}else this.applyValue(this.getMin());this._options.enabled!==void 0&&this.applyEnabled(this._options.enabled),this._options.readOnly!==void 0&&this.applyReadOnly(this._options.readOnly)}applyOptions(e){return super.applyOptions(e),e.value!==void 0&&(this._options.value=e.value),e.min!==void 0&&(this._options.min=e.min),e.max!==void 0&&(this._options.max=e.max),e.minValue!==void 0&&(this._options.minValue=e.minValue),e.maxValue!==void 0&&(this._options.maxValue=e.maxValue),e.step!==void 0&&(this._options.step=e.step),e.largeStep!==void 0&&(this._options.largeStep=e.largeStep),e.orientation!==void 0&&(this._options.orientation=e.orientation),e.showTicks!==void 0&&(this._options.showTicks=e.showTicks),e.enabled!==void 0&&(this._options.enabled=e.enabled),e.readOnly!==void 0&&(this._options.readOnly=e.readOnly),this}getValue(){return this._options.value??this.getMin()}setValue(e){let t=this.snap(e);return t===this.getValue()?this:(this._options.value=t,this.applyValue(t),this.notifyChange(t),r.fireEvent(this,`input`),this)}getMin(){return this._options.min??d}setMin(e){return this._options.min=e,this.applyMin(e),this.applyValue(this.snap(this.getValue())),this}getMax(){return this._options.max??f}setMax(e){return this._options.max=e,this.applyMax(e),this.applyValue(this.snap(this.getValue())),this}setMinValue(e){return this.setMin(e)}getMinValue(){return this.getMin()}setMaxValue(e){return this.setMax(e)}getMaxValue(){return this.getMax()}getStep(){return this._options.step??p}setStep(e){return this._options.step=e,this}getLargeStep(){return this._options.largeStep??this.getStep()*10}setLargeStep(e){return this._options.largeStep=e,this}getOrientation(){return this._options.orientation??`horizontal`}setOrientation(e){return this._options.orientation=e,this.applyOrientation(e),this.applyValue(this.getValue()),this}isShowTicks(){return this._options.showTicks??!1}setShowTicks(e){return this._options.showTicks=e,this}on(e,t){return e===`action`?(r.addListener(this,`input`,t),this):super.on(e,t)}off(e,t){return e===`action`?(r.removeListener(this,`input`,t),this):super.off(e,t)}getBaseline(){let e=this.getPreferredSize();return e?e.height-2:null}doLayout(){let e=this.getContentBounds();if(!e)return this;let t=this.getOrientation()===`horizontal`,n=e.width,r=e.height,i=this.getMin(),a=this.getMax()-i,o=a>0?(this.getValue()-i)/a:0;if(t){let t=Math.round((r-l)/2);this._track.setX(e.x),this._track.setY(e.y+t),this._track.setSize({width:n,height:l});let i=Math.round(n*o);this._activeTrack.setX(0),this._activeTrack.setY(0),this._activeTrack.setSize({width:i,height:l});let a=Math.round((n-u)*o),s=Math.round((r-u)/2);this._thumb.setSize({width:u,height:u}),this._thumb.setX(e.x+a),this._thumb.setY(e.y+s)}else{let t=Math.round((n-l)/2);this._track.setX(e.x+t),this._track.setY(e.y),this._track.setSize({width:l,height:r});let i=Math.round(r*o);this._activeTrack.setX(0),this._activeTrack.setY(r-i),this._activeTrack.setSize({width:l,height:i});let a=Math.round((n-u)/2),s=Math.round((r-u)*(1-o));this._thumb.setSize({width:u,height:u}),this._thumb.setX(e.x+a),this._thumb.setY(e.y+s)}return this}installInteraction(){r.addListener(this,`pointerdown`,t=>{if(!this.isEnabled()||this.isReadOnly())return;this.focus();let n=this.getElement();return n&&(e.sink.setPointerCapture(n,t.pointerId),this._draggingPointer=t.pointerId),this.setValue(this.valueAtPointer(t)),{prevent:!0}}),r.addListener(this,`pointermove`,e=>{this._draggingPointer===e.pointerId&&this.setValue(this.valueAtPointer(e))});let release=t=>{if(this._draggingPointer!==t.pointerId)return;let n=this.getElement();n&&e.source.hasPointerCapture(n,t.pointerId)&&e.sink.releasePointerCapture(n,t.pointerId),this._draggingPointer=null};r.addListener(this,`pointerup`,release),r.addListener(this,`pointercancel`,release),r.addListener(this,`lostpointercapture`,release),r.addListener(this,`keydown`,e=>{if(!this.isEnabled()||this.isReadOnly())return;let t=this.getStep(),n=this.getLargeStep(),r=this.getMin(),i=this.getMax();switch(e.key){case`ArrowRight`:case`ArrowUp`:return this.setValue(this.getValue()+t),{prevent:!0};case`ArrowLeft`:case`ArrowDown`:return this.setValue(this.getValue()-t),{prevent:!0};case`PageUp`:return this.setValue(this.getValue()+n),{prevent:!0};case`PageDown`:return this.setValue(this.getValue()-n),{prevent:!0};case`Home`:return this.setValue(r),{prevent:!0};case`End`:return this.setValue(i),{prevent:!0}}})}valueAtPointer(t){if(!this.getElement())return this.getValue();let r=e.source.getViewportRect(this),i=this.getContentBounds()??{x:0,y:0,width:r.width,height:r.height},a=this.getBorderSize(),o=r.left+a.left+i.x,s=r.top+a.top+i.y,c=this.getOrientation()===`horizontal`?i.width>0?(t.clientX-o)/i.width:0:i.height>0?1-(t.clientY-s)/i.height:0,l=n.clamp(c,0,1),u=this.getMin();return u+(this.getMax()-u)*l}snap(e){let t=this.getMin(),r=this.getMax(),i=this.getStep(),a=n.clamp(e,t,r);if(i<=0)return a;let o=t+Math.round((a-t)/i)*i;return n.clamp(o,t,r)}applyValue(e){this._options.value=e,this.getAria().setValueNow(e),this.scheduleLayout()}applyMin(e){this.getAria().setValueMin(e)}applyMax(e){this.getAria().setValueMax(e)}applyOrientation(e,n){this.getAria().setOrientation(e);let r=e===`horizontal`;n?.preferredSize===void 0?this.setPreferredSize(r?{width:200,height:u}:{width:u,height:200}):this.setPreferredSize(n.preferredSize),n?.maxSize===void 0?this.setMaxSize(r?{width:t,height:u}:{width:u,height:t}):this.setMaxSize(n.maxSize),this.scheduleLayout()}applyEnabled(e){this.getAria().setDisabled(!e),this.getAria().setTabIndex(e?0:-1),this.setCursor(e?`pointer`:`default`)}applyReadOnly(e){this.getAria().setReadOnly(e)}},h=i(Slider);export{c as n,h as t};
2
+ //# sourceMappingURL=Slider-CTbwR6HR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Slider-DZ9drUxn.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\nconst _defaultSliderOptions: Partial<SliderOptions> = {\n outline: \"none\",\n cursor: \"pointer\",\n};\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 * @param subclassDefaults - Per-subclass default bag layered over this\n * class's defaults; subclasses forward their `_defaultXxxOptions`\n * constant here.\n */\n constructor(options?: SliderOptions, subclassDefaults?: Partial<SliderOptions>);\n constructor(options?: TOptions, subclassDefaults?: Partial<TOptions>) {\n super(\n { ...(options ?? {}) } as TOptions,\n { ..._defaultSliderOptions, ...(subclassDefaults ?? {}) } as Partial<TOptions>,\n );\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({ width: THUMB_SIZE, height: THUMB_SIZE });\n this._thumb.setMaxSize({ width: THUMB_SIZE, height: 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.getAria().setRole(\"slider\");\n this.getAria().setTabIndex(0);\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 this.applyOrientation(this.getOrientation(), this._options);\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: Event.Listener): 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 as Event.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 as Event.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 // The content box, not the inner size: the inner size is the right\n // extent but carries no origin, so a padded slider would lay its track\n // out at the inner edge of its border and ignore the padding it just\n // subtracted. `_activeTrack` keeps its own zero origin — it is a child\n // of `_track`, so it is already inside the track's box.\n const box = this.getContentBounds();\n if (!box) {\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 `box` 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 = box.width;\n const innerHeight = box.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(box.x);\n this._track.setY(box.y + 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(box.x + thumbX);\n this._thumb.setY(box.y + thumbY);\n } else {\n const trackLeft = Math.round((innerWidth - TRACK_THICKNESS) / 2);\n this._track.setX(box.x + trackLeft);\n this._track.setY(box.y);\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(box.x + thumbX);\n this._thumb.setY(box.y + 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 // Measured against the same content box `doLayout` draws the track in,\n // not the outer rect: with padding the two disagree by that padding on\n // every pointer sample, and the thumb would trail the cursor. The\n // viewport rect is the border box, so reaching the content origin from\n // it costs the border as well as `getContentBounds`' own offset, which\n // is measured from the padding box.\n const rect = DOM.source.getViewportRect(this);\n const box = this.getContentBounds() ?? { x: 0, y: 0, width: rect.width, height: rect.height };\n const border = this.getBorderSize();\n const left = rect.left + border.left + box.x;\n const top = rect.top + border.top + box.y;\n const horizontal = this.getOrientation() === \"horizontal\";\n const fraction = horizontal\n ? (box.width > 0 ? (e.clientX - left) / box.width : 0)\n : (box.height > 0 ? 1 - (e.clientY - top) / box.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. A caller-supplied\n * `preferredSize` / `maxSize` wins over the orientation-derived default.\n *\n * @param orientation - `\"horizontal\"` or `\"vertical\"`.\n * @param options - Passed only from the constructor, so a caller-supplied\n * `preferredSize` / `maxSize` wins there; every runtime caller (the public\n * {@link setOrientation}) omits it, so both are always recomputed from\n * `orientation`.\n */\n private applyOrientation(orientation: AxisOrientation, options?: SliderOptions): void {\n this.getAria().setOrientation(orientation);\n\n const horizontal = orientation === \"horizontal\";\n\n if (options?.preferredSize !== undefined) {\n this.setPreferredSize(options.preferredSize);\n } else {\n this.setPreferredSize(horizontal\n ? { width: 200, height: THUMB_SIZE }\n : { width: THUMB_SIZE, height: 200 });\n }\n\n if (options?.maxSize !== undefined) {\n this.setMaxSize(options.maxSize);\n } else {\n this.setMaxSize(horizontal\n ? { width: UNBOUNDED, height: THUMB_SIZE }\n : { width: THUMB_SIZE, height: 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
+ {"version":3,"file":"Slider-CTbwR6HR.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\nconst _defaultSliderOptions: Partial<SliderOptions> = {\n outline: \"none\",\n cursor: \"pointer\",\n};\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 * @param subclassDefaults - Per-subclass default bag layered over this\n * class's defaults; subclasses forward their `_defaultXxxOptions`\n * constant here.\n */\n constructor(options?: SliderOptions, subclassDefaults?: Partial<SliderOptions>);\n constructor(options?: TOptions, subclassDefaults?: Partial<TOptions>) {\n super(\n { ...(options ?? {}) } as TOptions,\n { ..._defaultSliderOptions, ...(subclassDefaults ?? {}) } as Partial<TOptions>,\n );\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({ width: THUMB_SIZE, height: THUMB_SIZE });\n this._thumb.setMaxSize({ width: THUMB_SIZE, height: 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.getAria().setRole(\"slider\");\n this.getAria().setTabIndex(0);\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 this.applyOrientation(this.getOrientation(), this._options);\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: Event.Listener): 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 as Event.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 as Event.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 // The content box, not the inner size: the inner size is the right\n // extent but carries no origin, so a padded slider would lay its track\n // out at the inner edge of its border and ignore the padding it just\n // subtracted. `_activeTrack` keeps its own zero origin — it is a child\n // of `_track`, so it is already inside the track's box.\n const box = this.getContentBounds();\n if (!box) {\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 `box` 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 = box.width;\n const innerHeight = box.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(box.x);\n this._track.setY(box.y + 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(box.x + thumbX);\n this._thumb.setY(box.y + thumbY);\n } else {\n const trackLeft = Math.round((innerWidth - TRACK_THICKNESS) / 2);\n this._track.setX(box.x + trackLeft);\n this._track.setY(box.y);\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(box.x + thumbX);\n this._thumb.setY(box.y + 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): Event.ListenerResult => {\n if (!this.isEnabled() || this.isReadOnly()) {\n return;\n }\n\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 return { prevent: true };\n });\n\n // pointermove defaults to a button-agnostic registration (see\n // Event.ts's PRIMARY_BUTTON_TYPES) since the spec reports its\n // button as always -1. The pointerId check below is the actual gate.\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 // pointercancel and lostpointercapture both default to a\n // button-agnostic registration (see Event.ts's PRIMARY_BUTTON_TYPES),\n // so this cleanup still runs regardless of which button was held.\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): Event.ListenerResult => {\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 this.setValue(this.getValue() + step);\n\n return { prevent: true };\n case \"ArrowLeft\":\n case \"ArrowDown\":\n this.setValue(this.getValue() - step);\n\n return { prevent: true };\n case \"PageUp\":\n this.setValue(this.getValue() + largeStep);\n\n return { prevent: true };\n case \"PageDown\":\n this.setValue(this.getValue() - largeStep);\n\n return { prevent: true };\n case \"Home\":\n this.setValue(min);\n\n return { prevent: true };\n case \"End\":\n this.setValue(max);\n\n return { prevent: true };\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 // Measured against the same content box `doLayout` draws the track in,\n // not the outer rect: with padding the two disagree by that padding on\n // every pointer sample, and the thumb would trail the cursor. The\n // viewport rect is the border box, so reaching the content origin from\n // it costs the border as well as `getContentBounds`' own offset, which\n // is measured from the padding box.\n const rect = DOM.source.getViewportRect(this);\n const box = this.getContentBounds() ?? { x: 0, y: 0, width: rect.width, height: rect.height };\n const border = this.getBorderSize();\n const left = rect.left + border.left + box.x;\n const top = rect.top + border.top + box.y;\n const horizontal = this.getOrientation() === \"horizontal\";\n const fraction = horizontal\n ? (box.width > 0 ? (e.clientX - left) / box.width : 0)\n : (box.height > 0 ? 1 - (e.clientY - top) / box.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. A caller-supplied\n * `preferredSize` / `maxSize` wins over the orientation-derived default.\n *\n * @param orientation - `\"horizontal\"` or `\"vertical\"`.\n * @param options - Passed only from the constructor, so a caller-supplied\n * `preferredSize` / `maxSize` wins there; every runtime caller (the public\n * {@link setOrientation}) omits it, so both are always recomputed from\n * `orientation`.\n */\n private applyOrientation(orientation: AxisOrientation, options?: SliderOptions): void {\n this.getAria().setOrientation(orientation);\n\n const horizontal = orientation === \"horizontal\";\n\n if (options?.preferredSize !== undefined) {\n this.setPreferredSize(options.preferredSize);\n } else {\n this.setPreferredSize(horizontal\n ? { width: 200, height: THUMB_SIZE }\n : { width: THUMB_SIZE, height: 200 });\n }\n\n if (options?.maxSize !== undefined) {\n this.setMaxSize(options.maxSize);\n } else {\n this.setMaxSize(horizontal\n ? { width: UNBOUNDED, height: THUMB_SIZE }\n : { width: THUMB_SIZE, height: 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 +1,2 @@
1
- import{h as e,t}from"./Component-w65rPK75.js";import{t as n}from"./LayoutConstraints-LIHYYd2F.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({width:t,height: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-SDhOMp2g.js.map
1
+ import{h as e,t}from"./Component-B0ShfPVi.js";import{t as n}from"./LayoutConstraints-LIHYYd2F.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({width:t,height: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-srdN2d2b.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Spacer-SDhOMp2g.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({ width: w, height: 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,IAAI,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,EACJ,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,CAAE,MAAO,EAAG,OAAQ,CAAE,CAAC,CACjD,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
+ {"version":3,"file":"Spacer-srdN2d2b.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({ width: w, height: 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,IAAI,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,EACJ,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,CAAE,MAAO,EAAG,OAAQ,CAAE,CAAC,CACjD,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"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./DOM-C-Edb3tA.js";import{i as t}from"./Position-BwtxouxK.js";import{S as n,b as r,h as i,r as a,t as o,v as s}from"./Component-B0ShfPVi.js";import{t as c}from"./Button-MpMIYBYJ.js";import{t as l}from"./TabCloseButton-CY7BGitY.js";var ToggleButton=class extends c{get selectedStyleRule(){return this._selectedStyleRule??=this.createStyleRule(`.selected:not(:hover)`)}constructor(e,t,r){super(e,void 0,r),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)`),n.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 n.addListener(this,`change`,t),this}off(e,t){return n.removeListener(this,`change`,t),this}isSelected(){return this._options.selected??!1}setSelected(t){this._options.selected=t,this.getAria().setPressed(t);let n=this.getElement();return n&&e.sink.apply(n,{toggleClass:{selected:t}}),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(e){let n=typeof e==`string`?{border:e}:e;return this.selectedStyleRule.setMany(t(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()),n.fireEvent(this,`change`)}render(){let t=super.render();return e.sink.apply(t,{toggleClass:{selected:this.isSelected()}}),t}},u=i(ToggleButton),d=`ts-ui-tab-busy-pulse`,f=.22;r.ensureKeyframes(d,`0% { opacity: 0.10; } 50% { opacity: 0.30; } 100% { opacity: 0.10; }`);var p=null;function ensureBusyIndicatorClassRule(){p||=new r({scope:`class`,name:`TabBusyIndicator`,styles:{position:`absolute`,top:`0`,right:`0`,bottom:`0`,left:`0`,pointerEvents:`none`}})}var TabBusyIndicator=class extends o{constructor(){ensureBusyIndicatorClassRule(),super(),this.setBackgroundColor(`var(--ts-ui-tab-busy-color, var(--ts-ui-tab-indicator-color, #1a73e8))`)}},m={backgroundColor:`var(--ts-ui-tab-button-bg, #b8b8c3)`,backgroundImage:`var(--ts-ui-tab-button-bg, #b8b8c3)`,border:{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))`},borderRadius:void 0,shadow:void 0,hoverBackgroundColor:`var(--ts-ui-tab-button-hover-bg, #c4c4cf)`,hoverBackgroundImage:`var(--ts-ui-tab-button-hover-bg, #c4c4cf)`,hoverShadow:`none`},TabButton=class extends u{_closeable=!1;_closeButton=null;_busy=!1;_busyIndicator=null;constructor(e,t,n){super(e,void 0,{...m,...n??{}}),this._closeable=t?.closeable??!1,t&&this.applyOptions(t),this.applyTabStyling(t),t?.glyph!==void 0&&this.setGlyph(t.glyph),this._closeable&&this.buildCloseButton(),this.applyListeners(t?.listeners)}destructor(){this._closeButton?.dispose(),this._busyIndicator?.dispose(),super.destructor()}applyTabStyling(e){this.setHoverBorder(e?.hoverBorder??{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 t=new l;t.setBackgroundColor(`transparent`),t.setBackgroundImage(`none`),t.setHoverBackgroundColor(`var(--ts-ui-tab-close-hover-bg, rgba(0, 0, 0, 0.12))`),t.setHoverBackgroundImage(`none`),t.setHoverShadow(`none`),t.setBorderRadius(`3px`),t.clearBorder(),t.clearShadow(),t.setZIndex(1);let n=a.getResolvedScale();t.setWidth(n.tabClose),t.setHeight(n.tabClose),t.pinGlyphSize(n.tabCloseGlyph),e.sink.appendChild(this.getElement(!0),t.getElement(!0)),this._closeButton=t}getCloseButton(){return this._closeButton}isCloseable(){return this._closeable}setBusy(t){return this._busy===t?this:(this._busy=t,t?(this._busyIndicator||(this._busyIndicator=new TabBusyIndicator,e.sink.appendChild(this.getElement(!0),this._busyIndicator.getElement(!0))),this._busyIndicator.setVisible(!0),s.isReducedMotion()?(this._busyIndicator.clearAnimation(),this._busyIndicator.setOpacity(f)):this._busyIndicator.setAnimation(`${d} 1.2s ease-in-out infinite`),this):(this._busyIndicator?.clearAnimation(),this._busyIndicator?.setVisible(!1),this))}isBusy(){return this._busy}},h=i(TabButton);export{u as n,h as t};
2
+ //# sourceMappingURL=TabButton-DLoMQzky.js.map