@jimka/typescript-ui 0.6.0 → 0.8.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 (306) hide show
  1. package/dist/lib/AbstractInput-Dt9ooHjo.js +2 -0
  2. package/dist/lib/AbstractInput-Dt9ooHjo.js.map +1 -0
  3. package/dist/lib/AccordionConstraints-DahZEfEp.js +2 -0
  4. package/dist/lib/AccordionConstraints-DahZEfEp.js.map +1 -0
  5. package/dist/lib/{Anchor-CwRhdP2J.js → Anchor-DdYgyn2V.js} +2 -2
  6. package/dist/lib/{Anchor-CwRhdP2J.js.map → Anchor-DdYgyn2V.js.map} +1 -1
  7. package/dist/lib/AnimatedDropdown-_KhHzX5D.js +2 -0
  8. package/dist/lib/AnimatedDropdown-_KhHzX5D.js.map +1 -0
  9. package/dist/lib/Border-BELbqMDJ.js +2 -0
  10. package/dist/lib/Border-BELbqMDJ.js.map +1 -0
  11. package/dist/lib/Button-CKzjQyqA.js +2 -0
  12. package/dist/lib/Button-CKzjQyqA.js.map +1 -0
  13. package/dist/lib/{Card-QYo27r5b.js → Card-CAp7LcB5.js} +2 -2
  14. package/dist/lib/{Card-QYo27r5b.js.map → Card-CAp7LcB5.js.map} +1 -1
  15. package/dist/lib/Checkbox-CvAZJ4_T.js +2 -0
  16. package/dist/lib/Checkbox-CvAZJ4_T.js.map +1 -0
  17. package/dist/lib/CodeEditor-DoGGdL1Y.js +2 -0
  18. package/dist/lib/CodeEditor-DoGGdL1Y.js.map +1 -0
  19. package/dist/lib/ComboBox-DgjMnpdh.js +2 -0
  20. package/dist/lib/ComboBox-DgjMnpdh.js.map +1 -0
  21. package/dist/lib/Component-YrLXKJZS.js +2 -0
  22. package/dist/lib/Component-YrLXKJZS.js.map +1 -0
  23. package/dist/lib/Container-C5cxnioS.js +2 -0
  24. package/dist/lib/{Container-abY5Ww3W.js.map → Container-C5cxnioS.js.map} +1 -1
  25. package/dist/lib/DOM-DDhDN8lQ.js +2 -0
  26. package/dist/lib/DOM-DDhDN8lQ.js.map +1 -0
  27. package/dist/lib/Diagnostics-MI6Yw-3E.js +2 -0
  28. package/dist/lib/Diagnostics-MI6Yw-3E.js.map +1 -0
  29. package/dist/lib/Dialog-CXQXRQQK.js +2 -0
  30. package/dist/lib/Dialog-CXQXRQQK.js.map +1 -0
  31. package/dist/lib/DragManager-D5pBaPPg.js +2 -0
  32. package/dist/lib/DragManager-D5pBaPPg.js.map +1 -0
  33. package/dist/lib/{FieldDecorator-BlYMfZ9L.js → FieldDecorator-37IgKHHm.js} +2 -2
  34. package/dist/lib/{FieldDecorator-BlYMfZ9L.js.map → FieldDecorator-37IgKHHm.js.map} +1 -1
  35. package/dist/lib/{Fit-BhlB-HAo.js → Fit-amTWlJM2.js} +2 -2
  36. package/dist/lib/{Fit-BhlB-HAo.js.map → Fit-amTWlJM2.js.map} +1 -1
  37. package/dist/lib/{FloatingPanel-DkJXsZ2D.js → FloatingPanel-CwsFPYbc.js} +2 -2
  38. package/dist/lib/{FloatingPanel-DkJXsZ2D.js.map → FloatingPanel-CwsFPYbc.js.map} +1 -1
  39. package/dist/lib/Glyph-Cof7BxfJ.js +2 -0
  40. package/dist/lib/Glyph-Cof7BxfJ.js.map +1 -0
  41. package/dist/lib/{Grid-Daiz7F5d.js → Grid-BQZ4UIUH.js} +2 -2
  42. package/dist/lib/{Grid-Daiz7F5d.js.map → Grid-BQZ4UIUH.js.map} +1 -1
  43. package/dist/lib/GridConstraints-BkXa62z0.js +2 -0
  44. package/dist/lib/GridConstraints-BkXa62z0.js.map +1 -0
  45. package/dist/lib/{Header-Dql3Zxc6.js → Header-Cj33ABP1.js} +2 -2
  46. package/dist/lib/{Header-Dql3Zxc6.js.map → Header-Cj33ABP1.js.map} +1 -1
  47. package/dist/lib/{IconText-PUjhTLlp.js → IconText-Dp64iq_q.js} +2 -2
  48. package/dist/lib/{IconText-PUjhTLlp.js.map → IconText-Dp64iq_q.js.map} +1 -1
  49. package/dist/lib/LabeledGrid-Dpelrc1k.js +2 -0
  50. package/dist/lib/LabeledGrid-Dpelrc1k.js.map +1 -0
  51. package/dist/lib/LayoutSerialization-DgLJSuew.js +2 -0
  52. package/dist/lib/LayoutSerialization-DgLJSuew.js.map +1 -0
  53. package/dist/lib/Link-DE8tE3u3.js +2 -0
  54. package/dist/lib/Link-DE8tE3u3.js.map +1 -0
  55. package/dist/lib/List-TfgHScl3.js +2 -0
  56. package/dist/lib/List-TfgHScl3.js.map +1 -0
  57. package/dist/lib/ListenerBag-DYRl4TSb.js +2 -0
  58. package/dist/lib/ListenerBag-DYRl4TSb.js.map +1 -0
  59. package/dist/lib/{MemoryStore-DhPoU-7X.js → MemoryStore-ByGDEKYI.js} +2 -2
  60. package/dist/lib/{MemoryStore-DhPoU-7X.js.map → MemoryStore-ByGDEKYI.js.map} +1 -1
  61. package/dist/lib/Menu-BCQISKiQ.js +2 -0
  62. package/dist/lib/Menu-BCQISKiQ.js.map +1 -0
  63. package/dist/lib/{MenuButton-DCXi0tsP.js → MenuButton-BO4y3jf2.js} +2 -2
  64. package/dist/lib/{MenuButton-DCXi0tsP.js.map → MenuButton-BO4y3jf2.js.map} +1 -1
  65. package/dist/lib/{OverlayFade-3pof2AJH.js → OverlayFade-C1yQKffL.js} +2 -2
  66. package/dist/lib/{OverlayFade-3pof2AJH.js.map → OverlayFade-C1yQKffL.js.map} +1 -1
  67. package/dist/lib/{Panel-Cy1pdlWO.js → Panel-DlsVVuvn.js} +2 -2
  68. package/dist/lib/{Panel-Cy1pdlWO.js.map → Panel-DlsVVuvn.js.map} +1 -1
  69. package/dist/lib/{Position-BwtxouxK.js → Position-DWR1nIpA.js} +2 -2
  70. package/dist/lib/Position-DWR1nIpA.js.map +1 -0
  71. package/dist/lib/ProgressSpinner-BI9tFIVm.js +2 -0
  72. package/dist/lib/ProgressSpinner-BI9tFIVm.js.map +1 -0
  73. package/dist/lib/RadioButton-BxcuFChp.js +2 -0
  74. package/dist/lib/RadioButton-BxcuFChp.js.map +1 -0
  75. package/dist/lib/RadioMenuRow-B2bthoxj.js +2 -0
  76. package/dist/lib/RadioMenuRow-B2bthoxj.js.map +1 -0
  77. package/dist/lib/{RovingTabIndex-pHEv5oLD.js → RovingTabIndex-BttlsARv.js} +2 -2
  78. package/dist/lib/{RovingTabIndex-pHEv5oLD.js.map → RovingTabIndex-BttlsARv.js.map} +1 -1
  79. package/dist/lib/Scrollbar-orAWHWap.js +2 -0
  80. package/dist/lib/Scrollbar-orAWHWap.js.map +1 -0
  81. package/dist/lib/SelectableText-BbS_lRzY.js +2 -0
  82. package/dist/lib/SelectableText-BbS_lRzY.js.map +1 -0
  83. package/dist/lib/Slider-BvXc-cx5.js +2 -0
  84. package/dist/lib/Slider-BvXc-cx5.js.map +1 -0
  85. package/dist/lib/Spacer-C6faKe1V.js +2 -0
  86. package/dist/lib/Spacer-C6faKe1V.js.map +1 -0
  87. package/dist/lib/StyleTraits-CAtzeyRR.js +2 -0
  88. package/dist/lib/StyleTraits-CAtzeyRR.js.map +1 -0
  89. package/dist/lib/TabButton-BQDaBszs.js +2 -0
  90. package/dist/lib/TabButton-BQDaBszs.js.map +1 -0
  91. package/dist/lib/TabCloseButton-B-iLVPGZ.js +2 -0
  92. package/dist/lib/TabCloseButton-B-iLVPGZ.js.map +1 -0
  93. package/dist/lib/Table-3McEw5gr.js +7 -0
  94. package/dist/lib/Table-3McEw5gr.js.map +1 -0
  95. package/dist/lib/Text-CGFXPhHD.js +2 -0
  96. package/dist/lib/Text-CGFXPhHD.js.map +1 -0
  97. package/dist/lib/Tooltip-DgRHQZhL.js +3 -0
  98. package/dist/lib/Tooltip-DgRHQZhL.js.map +1 -0
  99. package/dist/lib/Tree-Bq2pjjAz.js +2 -0
  100. package/dist/lib/Tree-Bq2pjjAz.js.map +1 -0
  101. package/dist/lib/{VBox-DfJPWXqc.js → VBox-hFIZAEpT.js} +2 -2
  102. package/dist/lib/{VBox-DfJPWXqc.js.map → VBox-hFIZAEpT.js.map} +1 -1
  103. package/dist/lib/{VirtualScroller-DTIn19o1.js → VirtualScroller-Csa3GBSM.js} +2 -2
  104. package/dist/lib/{VirtualScroller-DTIn19o1.js.map → VirtualScroller-Csa3GBSM.js.map} +1 -1
  105. package/dist/lib/Window-CQ14_65z.js +2 -0
  106. package/dist/lib/Window-CQ14_65z.js.map +1 -0
  107. package/dist/lib/component/button.es.js +1 -1
  108. package/dist/lib/component/button.es.js.map +1 -1
  109. package/dist/lib/component/chart.es.js +1 -1
  110. package/dist/lib/component/chart.es.js.map +1 -1
  111. package/dist/lib/component/container.es.js +1 -1
  112. package/dist/lib/component/container.es.js.map +1 -1
  113. package/dist/lib/component/diagram.es.js +1 -1
  114. package/dist/lib/component/diagram.es.js.map +1 -1
  115. package/dist/lib/component/display.es.js +1 -1
  116. package/dist/lib/component/display.es.js.map +1 -1
  117. package/dist/lib/component/editor.es.js +2 -2
  118. package/dist/lib/component/editor.es.js.map +1 -1
  119. package/dist/lib/component/input.es.js +1 -1
  120. package/dist/lib/component/input.es.js.map +1 -1
  121. package/dist/lib/component/list.es.js +1 -1
  122. package/dist/lib/component/list.es.js.map +1 -1
  123. package/dist/lib/component/menubar.es.js +1 -1
  124. package/dist/lib/component/menubar.es.js.map +1 -1
  125. package/dist/lib/component/table.es.js +1 -6
  126. package/dist/lib/component/table.es.js.map +1 -1
  127. package/dist/lib/component/tree.es.js +1 -1
  128. package/dist/lib/component/tree.es.js.map +1 -1
  129. package/dist/lib/core-DpzpKLWE.js +2 -0
  130. package/dist/lib/core-DpzpKLWE.js.map +1 -0
  131. package/dist/lib/core.es.js +1 -2
  132. package/dist/lib/data.es.js +1 -1
  133. package/dist/lib/diagnostics.es.js +24 -0
  134. package/dist/lib/diagnostics.es.js.map +1 -0
  135. package/dist/lib/glyphs/solid/index.es.js +1 -1
  136. package/dist/lib/layout.es.js +1 -1
  137. package/dist/lib/layout.es.js.map +1 -1
  138. package/dist/lib/overlay.es.js +1 -1
  139. package/dist/lib/overlay.es.js.map +1 -1
  140. package/dist/lib/primitive-8YvORgGS.js +2 -0
  141. package/dist/lib/primitive-8YvORgGS.js.map +1 -0
  142. package/dist/lib/primitive.es.js +1 -2
  143. package/dist/lib/router.es.js +1 -1
  144. package/dist/lib/selectionsEqual-DWdW5pxP.js +2 -0
  145. package/dist/lib/{selectionsEqual-gMG7gCVI.js.map → selectionsEqual-DWdW5pxP.js.map} +1 -1
  146. package/dist/lib/types/component/button/Button.d.ts +7 -6
  147. package/dist/lib/types/component/button/TabButton.d.ts +3 -0
  148. package/dist/lib/types/component/button/TabCloseButton.d.ts +3 -0
  149. package/dist/lib/types/component/button/ToggleButton.d.ts +2 -2
  150. package/dist/lib/types/component/chart/AbstractChart.d.ts +2 -0
  151. package/dist/lib/types/component/container/AccordionHeader.d.ts +6 -1
  152. package/dist/lib/types/component/container/AccordionIndicator.d.ts +2 -0
  153. package/dist/lib/types/component/container/FieldSet.d.ts +2 -0
  154. package/dist/lib/types/component/container/LabeledFieldSet.d.ts +1 -1
  155. package/dist/lib/types/component/container/LabeledGrid.d.ts +4 -1
  156. package/dist/lib/types/component/container/Legend.d.ts +2 -2
  157. package/dist/lib/types/component/container/MenuItem.d.ts +1 -0
  158. package/dist/lib/types/component/container/WindowBorder.d.ts +2 -2
  159. package/dist/lib/types/component/container/WindowHeader.d.ts +6 -0
  160. package/dist/lib/types/component/diagram/DiagramEdgeLayer.d.ts +10 -0
  161. package/dist/lib/types/component/diagram/DiagramGroupNode.d.ts +2 -0
  162. package/dist/lib/types/component/diagram/DiagramNode.d.ts +6 -2
  163. package/dist/lib/types/component/diagram/DiagramNodeLayer.d.ts +25 -0
  164. package/dist/lib/types/component/diagram/DiagramResidency.d.ts +11 -0
  165. package/dist/lib/types/component/diagram/DiagramView.d.ts +22 -0
  166. package/dist/lib/types/component/display/Markdown.d.ts +2 -1
  167. package/dist/lib/types/component/input/AbstractCalendarDropdown.d.ts +4 -2
  168. package/dist/lib/types/component/input/AbstractInput.d.ts +1 -0
  169. package/dist/lib/types/component/input/AbstractPickerField.d.ts +4 -0
  170. package/dist/lib/types/component/input/AutoCompleteDropdown.d.ts +2 -0
  171. package/dist/lib/types/component/input/AutoCompleteField.d.ts +1 -0
  172. package/dist/lib/types/component/input/ComboBox.d.ts +6 -1
  173. package/dist/lib/types/component/input/Link.d.ts +2 -0
  174. package/dist/lib/types/component/input/PasswordField.d.ts +2 -0
  175. package/dist/lib/types/component/input/PickerButton.d.ts +5 -2
  176. package/dist/lib/types/component/input/PickerInput.d.ts +2 -0
  177. package/dist/lib/types/component/input/SelectableText.d.ts +11 -0
  178. package/dist/lib/types/component/input/SpinButton.d.ts +3 -0
  179. package/dist/lib/types/component/input/Text.d.ts +12 -2
  180. package/dist/lib/types/component/input/TextArea.d.ts +2 -0
  181. package/dist/lib/types/component/input/TextField.d.ts +2 -0
  182. package/dist/lib/types/component/input/TextInput.d.ts +4 -0
  183. package/dist/lib/types/component/input/TimePickerDropdown.d.ts +3 -1
  184. package/dist/lib/types/component/input/UsernameField.d.ts +2 -0
  185. package/dist/lib/types/component/input/index.d.ts +2 -0
  186. package/dist/lib/types/component/list/AbstractMarkerList.d.ts +2 -0
  187. package/dist/lib/types/component/list/AbstractSelectableList.d.ts +6 -2
  188. package/dist/lib/types/component/list/ListItem.d.ts +2 -1
  189. package/dist/lib/types/component/menubar/MenuBarButton.d.ts +3 -0
  190. package/dist/lib/types/component/menubar/ToolBar.d.ts +2 -0
  191. package/dist/lib/types/component/table/Body.d.ts +54 -20
  192. package/dist/lib/types/component/table/Column.d.ts +2 -0
  193. package/dist/lib/types/component/table/ColumnConfig.d.ts +1 -0
  194. package/dist/lib/types/component/table/Footer.d.ts +2 -0
  195. package/dist/lib/types/component/table/Header.d.ts +8 -1
  196. package/dist/lib/types/component/table/Row.d.ts +22 -2
  197. package/dist/lib/types/component/table/Table.d.ts +6 -1
  198. package/dist/lib/types/component/table/TableExporter.d.ts +3 -0
  199. package/dist/lib/types/component/table/TablePanel.d.ts +6 -0
  200. package/dist/lib/types/component/table/TreeTablePanel.d.ts +6 -0
  201. package/dist/lib/types/component/table/cell/Cell.d.ts +8 -2
  202. package/dist/lib/types/component/table/cell/Default.d.ts +1 -1
  203. package/dist/lib/types/component/table/cell/Header.d.ts +4 -0
  204. package/dist/lib/types/component/table/cell/ParentHeader.d.ts +4 -0
  205. package/dist/lib/types/component/table/cell/ResizeHandle.d.ts +1 -1
  206. package/dist/lib/types/component/table/cell/renderer/CellRenderer.d.ts +2 -2
  207. package/dist/lib/types/component/table/cell/renderer/String.d.ts +3 -1
  208. package/dist/lib/types/component/table/index.d.ts +1 -1
  209. package/dist/lib/types/component/tree/TreeRow.d.ts +2 -0
  210. package/dist/lib/types/core/AnimatedDropdown.d.ts +2 -0
  211. package/dist/lib/types/core/Binding.d.ts +1 -0
  212. package/dist/lib/types/core/ClassStyleRules.d.ts +69 -4
  213. package/dist/lib/types/core/Component.d.ts +69 -14
  214. package/dist/lib/types/core/DOM.d.ts +11 -1
  215. package/dist/lib/types/core/Diagnostics.d.ts +22 -0
  216. package/dist/lib/types/core/Event.d.ts +7 -0
  217. package/dist/lib/types/core/LayerManager.d.ts +3 -0
  218. package/dist/lib/types/core/ListenerBag.d.ts +1 -0
  219. package/dist/lib/types/core/StyleTarget.d.ts +14 -0
  220. package/dist/lib/types/core/StyleTraits.d.ts +4 -0
  221. package/dist/lib/types/core/Theme.d.ts +6 -2
  222. package/dist/lib/types/core/Util.d.ts +4 -0
  223. package/dist/lib/types/core/index.d.ts +6 -3
  224. package/dist/lib/types/diagnostics/DiagnosticsOverlay.d.ts +29 -0
  225. package/dist/lib/types/diagnostics/DiagnosticsSampler.d.ts +61 -0
  226. package/dist/lib/types/diagnostics/StyleAudit.d.ts +19 -0
  227. package/dist/lib/types/diagnostics/StyleAuditOverlay.d.ts +12 -0
  228. package/dist/lib/types/diagnostics/StyleAuditView.d.ts +13 -0
  229. package/dist/lib/types/diagnostics/index.d.ts +7 -0
  230. package/dist/lib/types/layout/LayoutManager.d.ts +3 -0
  231. package/dist/lib/types/layout/Table.d.ts +3 -0
  232. package/dist/lib/types/overlay/AbstractWindow.d.ts +36 -0
  233. package/dist/lib/types/overlay/ButtonGroup.d.ts +1 -0
  234. package/dist/lib/types/overlay/Dialog.d.ts +1 -0
  235. package/dist/lib/types/overlay/Menu.d.ts +2 -0
  236. package/dist/lib/types/overlay/Notification.d.ts +0 -1
  237. package/dist/lib/types/overlay/PopupPanel.d.ts +2 -0
  238. package/dist/lib/types/overlay/RailHandle.d.ts +4 -5
  239. package/dist/lib/types/overlay/TabWindow.d.ts +3 -0
  240. package/dist/lib/types/overlay/Tooltip.d.ts +1 -0
  241. package/dist/lib/types/overlay/Window.d.ts +4 -1
  242. package/dist/lib/validation.es.js +1 -1
  243. package/llms.txt +2 -0
  244. package/package.json +5 -1
  245. package/dist/lib/AbstractInput-sRNPzWel.js +0 -2
  246. package/dist/lib/AbstractInput-sRNPzWel.js.map +0 -1
  247. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js +0 -2
  248. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js.map +0 -1
  249. package/dist/lib/Border-0DJFDiij.js +0 -2
  250. package/dist/lib/Border-0DJFDiij.js.map +0 -1
  251. package/dist/lib/Button-MpMIYBYJ.js +0 -2
  252. package/dist/lib/Button-MpMIYBYJ.js.map +0 -1
  253. package/dist/lib/Checkbox-D0JYK-wc.js +0 -2
  254. package/dist/lib/Checkbox-D0JYK-wc.js.map +0 -1
  255. package/dist/lib/CheckboxMenuRow-CesLhSnp.js +0 -2
  256. package/dist/lib/CheckboxMenuRow-CesLhSnp.js.map +0 -1
  257. package/dist/lib/CodeEditor-N1FQodcF.js +0 -2
  258. package/dist/lib/CodeEditor-N1FQodcF.js.map +0 -1
  259. package/dist/lib/ComboBox-Dx8Tk9yg.js +0 -2
  260. package/dist/lib/ComboBox-Dx8Tk9yg.js.map +0 -1
  261. package/dist/lib/Component-B0ShfPVi.js +0 -2
  262. package/dist/lib/Component-B0ShfPVi.js.map +0 -1
  263. package/dist/lib/Container-abY5Ww3W.js +0 -2
  264. package/dist/lib/DOM-C-Edb3tA.js +0 -2
  265. package/dist/lib/DOM-C-Edb3tA.js.map +0 -1
  266. package/dist/lib/Dialog-cbA9V17e.js +0 -2
  267. package/dist/lib/Dialog-cbA9V17e.js.map +0 -1
  268. package/dist/lib/Glyph-_VeBacS2.js +0 -2
  269. package/dist/lib/Glyph-_VeBacS2.js.map +0 -1
  270. package/dist/lib/GridConstraints-C58LuTqM.js +0 -2
  271. package/dist/lib/GridConstraints-C58LuTqM.js.map +0 -1
  272. package/dist/lib/LayoutSerialization-CMxunLfV.js +0 -2
  273. package/dist/lib/LayoutSerialization-CMxunLfV.js.map +0 -1
  274. package/dist/lib/List-nx8220Fi.js +0 -2
  275. package/dist/lib/List-nx8220Fi.js.map +0 -1
  276. package/dist/lib/ListenerBag-WPdKuuds.js +0 -2
  277. package/dist/lib/ListenerBag-WPdKuuds.js.map +0 -1
  278. package/dist/lib/Menu-Q0bpXXze.js +0 -2
  279. package/dist/lib/Menu-Q0bpXXze.js.map +0 -1
  280. package/dist/lib/Position-BwtxouxK.js.map +0 -1
  281. package/dist/lib/ProgressSpinner-DK8xEQ9y.js +0 -2
  282. package/dist/lib/ProgressSpinner-DK8xEQ9y.js.map +0 -1
  283. package/dist/lib/RadioButton-BEwpqg1k.js +0 -2
  284. package/dist/lib/RadioButton-BEwpqg1k.js.map +0 -1
  285. package/dist/lib/RadioMenuRow-DP5qPyFR.js +0 -2
  286. package/dist/lib/RadioMenuRow-DP5qPyFR.js.map +0 -1
  287. package/dist/lib/Scrollbar-t8fFrUVQ.js +0 -2
  288. package/dist/lib/Scrollbar-t8fFrUVQ.js.map +0 -1
  289. package/dist/lib/Slider-CTbwR6HR.js +0 -2
  290. package/dist/lib/Slider-CTbwR6HR.js.map +0 -1
  291. package/dist/lib/Spacer-srdN2d2b.js +0 -2
  292. package/dist/lib/Spacer-srdN2d2b.js.map +0 -1
  293. package/dist/lib/TabButton-DLoMQzky.js +0 -2
  294. package/dist/lib/TabButton-DLoMQzky.js.map +0 -1
  295. package/dist/lib/TabCloseButton-CY7BGitY.js +0 -2
  296. package/dist/lib/TabCloseButton-CY7BGitY.js.map +0 -1
  297. package/dist/lib/Text-CMKnK9uB.js +0 -2
  298. package/dist/lib/Text-CMKnK9uB.js.map +0 -1
  299. package/dist/lib/Tooltip-CUOJOqQi.js +0 -3
  300. package/dist/lib/Tooltip-CUOJOqQi.js.map +0 -1
  301. package/dist/lib/Tree-C64JNPWJ.js +0 -2
  302. package/dist/lib/Tree-C64JNPWJ.js.map +0 -1
  303. package/dist/lib/core.es.js.map +0 -1
  304. package/dist/lib/primitive.es.js.map +0 -1
  305. package/dist/lib/selectionsEqual-gMG7gCVI.js +0 -2
  306. package/dist/lib/types/component/table/CellGeometry.d.ts +0 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dialog-CXQXRQQK.js","names":[],"sources":["../../src/typescript/lib/overlay/Popover.ts","../../src/typescript/lib/component/container/DialogBackdrop.ts","../../src/typescript/lib/overlay/Dialog.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { LayerManager, DismissableLayer, LayerDismissMode } from \"~/core/LayerManager.js\";\nimport { trapWheel, untrapWheel } from \"~/core/WheelTrap.js\";\nimport { Util } from \"~/core/Util.js\";\nimport { fadeShow, fadeHideAndDetach } from \"~/core/OverlayFade.js\";\nimport type { Animation } from \"~/core/Animation.js\";\nimport { Container, ContainerOptions } from \"~/core/Container.js\";\nimport type { Edge } from \"~/primitive/Edge.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { VBox } from \"~/layout/VBox.js\";\nimport { HBox } from \"~/layout/HBox.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { Button } from \"~/component/button/Button.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM, type Rect, type Handle } from \"~/core/DOM.js\";\n\n/** Fallback arrow side length used until the theme token is read. */\nconst DEFAULT_ARROW_SIZE_PX: number = 14;\n\n/**\n * Half of the visual extent of the rotated arrow along either axis. The\n * arrow is a square of side `DEFAULT_ARROW_SIZE_PX` rotated 45°, so its\n * bounding rectangle is `DEFAULT_ARROW_SIZE_PX * sqrt(2)` on each side and\n * each corner sits half that far from the centre.\n */\nconst ARROW_VISUAL_HALF: number = (DEFAULT_ARROW_SIZE_PX / 2) * Math.SQRT2;\n\n/** Pixel gap between the arrow tip and the anchor element. */\nconst ARROW_ANCHOR_GAP_PX: number = 2;\n\n/**\n * Pixel gap between the popover edge and the anchor element. Sized so the\n * arrow tip lands {@link ARROW_ANCHOR_GAP_PX} away from the anchor.\n */\nconst POPOVER_ANCHOR_GAP: number = Math.ceil(ARROW_VISUAL_HALF) + ARROW_ANCHOR_GAP_PX;\n\n/** Pixel inset preserved between the arrow and the popover corner. */\nconst ARROW_EDGE_INSET_PX: number = 6;\n\n/** Pixel inset preserved between the arrow / popover and any viewport edge. */\nconst VIEWPORT_EDGE_INSET_PX: number = 5;\n\n/** Fade duration matched to the rest of the floating-overlay family. */\nconst POPOVER_FADE_DURATION_MS: number = 120;\n\n/**\n * Placement of a {@link Popover} relative to its anchor element. `\"auto\"`\n * picks the side with the most viewport space at `show()` time.\n *\n * @category Core\n */\nexport type PopoverPlacement = Edge | \"auto\";\n\n/**\n * Strategy used to dismiss a {@link Popover}:\n *\n * - `\"click-outside\"`: closes on a `pointerdown` outside both the popover and\n * its anchor element (the anchor is excluded so the trigger click can\n * re-open without immediate re-close).\n * - `\"blur\"`: closes when focus or a pointer leaves the popover subtree —\n * including a portaled descendant layer such as a dropdown opened inside\n * the popover, which now keeps the popover open.\n * - `\"manual\"`: caller drives `hide()` explicitly.\n *\n * @remarks Dismissal is executed by {@link LayerManager}: the popover reports\n * this mode from its {@link DismissableLayer.getDismissMode} and the manager's\n * document-level handlers decide when to call `requestClose`. This is the\n * public option name; it maps 1:1 onto {@link LayerDismissMode}.\n *\n * @category Core\n */\nexport type PopoverDismissMode = \"click-outside\" | \"blur\" | \"manual\";\n\n/**\n * Construction-time options for {@link Popover}.\n *\n * @category Core\n */\nexport interface PopoverOptions extends ContainerOptions {\n /** Resolved placement relative to the anchor. Default `\"auto\"`. */\n placement?: PopoverPlacement;\n /** Dismiss strategy. Default `\"click-outside\"`. */\n dismissOn?: PopoverDismissMode;\n /** When `false`, the arrow tail is not rendered. Default `true`. */\n showArrow?: boolean;\n /** Optional title row rendered above the body. */\n title?: string;\n /** Callback invoked once whenever the popover closes, for any reason\n * (an explicit `hide()` or an outside-click `requestClose()`). Mirrors\n * [`Menu`](/api/overlay/classes/Menu)'s persistent-mode `onClose`. */\n onClose?: () => void;\n}\n\n/**\n * User-overridable visual defaults forwarded to `super` via the options bag.\n * The cascade in `Component`'s constructor dispatches each present setter once\n * with the final value, so any field the caller supplied wins.\n */\nconst _defaultPopoverOptions: Partial<PopoverOptions> = {\n insets: new Insets(5, 5, 5, 5),\n placement: \"auto\",\n dismissOn: \"click-outside\",\n showArrow: true,\n backgroundColor: \"var(--ts-ui-popover-bg, rgb(255, 255, 255))\",\n foregroundColor: \"var(--ts-ui-popover-color, rgb(0, 0, 0))\",\n // Theme-driven chrome.\n border: { border: \"1px solid var(--ts-ui-popover-border, rgb(200, 200, 200))\" },\n borderRadius: \"var(--ts-ui-popover-radius, 6px)\",\n shadow: \"var(--ts-ui-popover-shadow, 2px 4px 12px rgba(0, 0, 0, 0.18))\",\n};\n\n/**\n * An anchored, non-modal floating bubble with a directional arrow tail. Use\n * `Popover` for click-triggered, interactive content (title, body, action\n * buttons, or any arbitrary subtree) — for ephemeral hover hints reach for\n * [`Tooltip`](/api/overlay/classes/Tooltip), and for modal containment reach\n * for [`Dialog`](/api/overlay/classes/Dialog).\n *\n * `Popover` extends {@link Container} so authors can compose freely via\n * `addComponent`; the `setTitle` / `setBody` / `addAction` conveniences are\n * sugar over the same container surface.\n *\n * Positioning is anchor-relative. `attachToComponent(Component)` records the\n * anchor. While the popover is open, `window` `resize` and each scrollable\n * ancestor's `scroll` event trigger a reposition so the bubble follows the\n * anchor.\n *\n * Fade-in / fade-out reuse the shared [`fadeShow`](/api/core/functions/fadeShow)\n * and [`fadeHideAndDetach`](/api/core/functions/fadeHideAndDetach) helpers,\n * inheriting the standard 120 ms `opacity + translateY` transition and the\n * re-entrancy guard against a fresh `show()` mid-fade.\n *\n * @example\n * ```typescript\n * const popover = new Popover({ placement: \"auto\" });\n * popover.setTitle(\"Confirm delete\");\n * popover.setBody(\"This action cannot be undone.\");\n * popover.addAction(\"Delete\", () => doDelete());\n * popover.addAction(\"Cancel\", () => popover.hide());\n *\n * Event.addListener(triggerButton, \"click\", () => {\n * popover.attachToComponent(triggerButton);\n * popover.show();\n * });\n * ```\n *\n * @category Core\n */\nclass Popover extends Container<PopoverOptions> implements DismissableLayer {\n\n // Option-backed fields use `declare` rather than initializers to dodge the\n // class-field super-cascade trap: an initializer runs *after* super()\n // returns, overwriting whatever the cascade-dispatched setter wrote\n // during the super-time `applyOptions` call. The applyOptions override\n // below always dispatches each setter with a fallback so the field is\n // seeded even when no caller option was supplied.\n declare private _placement: PopoverPlacement;\n private _resolvedPlacement: PopoverPlacement = \"bottom\";\n declare private _dismissOn: PopoverDismissMode;\n declare private _showArrow: boolean;\n declare private _title: string | null;\n declare private _titleComponent: Text | null;\n declare private _onClose: (() => void) | null;\n private _bodyComponent: Component | null = null;\n private _actionsRow: Component | null = null;\n\n // In-flight fades, cancelled on teardown so their fallback timers cannot\n // fire against this popover's released element handle.\n private _fadeShowAnimation: Animation.CancelHandle | null = null;\n private _fadeHideAnimation: Animation.CancelHandle | null = null;\n private _anchorElement: Handle | null = null;\n private _arrowComponent: Component | null = null;\n private _isOpen: boolean = false;\n private _scrollAncestors: Handle[] = [];\n\n private readonly _onWindowResize: () => void;\n private readonly _onScroll: () => void;\n\n /**\n * Creates a popover with a 5px layout-side inset and the default chrome\n * wired to the theme tokens.\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?: PopoverOptions, subclassDefaults?: Partial<PopoverOptions>) {\n super(options as PopoverOptions, { ..._defaultPopoverOptions, ...(subclassDefaults ?? {}) });\n\n const vbox = new VBox();\n\n vbox.setStretching(true);\n this.setLayoutManager(vbox);\n\n // Overlay placement: top-level, viewport-fixed. The z-index is\n // stamped from LayerManager's Popover band at show() time, so no\n // static value is set here.\n this.setPosition(Position.FIXED);\n this.setVisible(false);\n\n // `paint` containment would clip the arrow tail (which straddles the\n // popover edge), so use `layout` containment only. The framework\n // default `overflow: hidden` would also clip the arrow, so opt out.\n this.setContain(\"layout\");\n this.setOverflow(\"visible\");\n this.getAria().setRole(\"dialog\");\n\n this._onWindowResize = () => this._reposition();\n this._onScroll = () => this._reposition();\n\n // Seed the `declare`-d title/onClose fields after the cascade has had\n // its chance to write them via setTitle / applyOptions. Without a\n // `title` (or `onClose`) option the cascade dispatch above skips\n // writing it entirely, so the field would otherwise remain undefined\n // (declare allocates no default).\n this._title ??= null;\n this._titleComponent ??= null;\n this._onClose ??= null;\n }\n\n /**\n * Applies a {@link PopoverOptions} bag, dispatching popover-specific\n * fields after the inherited Container cascade.\n *\n * @param options - The options bag carrying the values to apply.\n * @returns This popover, for method chaining.\n */\n protected applyOptions(options: PopoverOptions): this {\n super.applyOptions(options);\n\n // placement/dismissOn/showArrow carry a class default and seed\n // construction-time state, so always dispatch the caller value or the\n // class default; title has no default.\n this.setPlacement(options.placement ?? this.getPlacement());\n this.setDismissOn(options.dismissOn ?? this.getDismissOn());\n this.setShowArrow(options.showArrow ?? this.isShowArrow());\n if (options.title !== undefined) this.setTitle(options.title);\n // onClose has no setter (it's a plain callback, not a rendered/\n // resolvable field), so it's assigned directly, same as title has no\n // class default to fall back to.\n if (options.onClose !== undefined) this._onClose = options.onClose;\n\n return this;\n }\n\n /**\n * Sets the requested placement relative to the anchor.\n *\n * @param p - One of `\"top\"`, `\"bottom\"`, `\"left\"`, `\"right\"`, or `\"auto\"`.\n * @returns This popover, for method chaining.\n */\n setPlacement(p: PopoverPlacement): this {\n this._placement = p;\n\n return this;\n }\n\n /**\n * Returns the configured placement.\n *\n * @returns The placement set via {@link setPlacement}, or `\"auto\"` by default.\n */\n getPlacement(): PopoverPlacement {\n return this._placement ?? this._defaultOptions.placement!;\n }\n\n /**\n * Sets the dismiss strategy.\n *\n * @param mode - One of `\"click-outside\"`, `\"blur\"`, or `\"manual\"`.\n * @returns This popover, for method chaining.\n */\n setDismissOn(mode: PopoverDismissMode): this {\n this._dismissOn = mode;\n\n return this;\n }\n\n /**\n * Returns the active dismiss strategy.\n *\n * @returns The dismiss strategy set via {@link setDismissOn}.\n */\n getDismissOn(): PopoverDismissMode {\n return this._dismissOn ?? this._defaultOptions.dismissOn!;\n }\n\n /**\n * Enables or disables the arrow tail.\n *\n * @param value - `true` to render the arrow, `false` to hide it.\n * @returns This popover, for method chaining.\n */\n setShowArrow(value: boolean): this {\n this._showArrow = value;\n\n if (this._arrowComponent) {\n this._arrowComponent.setVisible(value);\n }\n\n return this;\n }\n\n /**\n * Returns whether the arrow tail is currently enabled.\n *\n * @returns `true` if the arrow is rendered.\n */\n isShowArrow(): boolean {\n return this._showArrow ?? this._defaultOptions.showArrow!;\n }\n\n /**\n * Sets the title row text. Lazily creates the underlying\n * [`Text`](/api/component/input/classes/Text) child on first call. Passing\n * `null` clears the title.\n *\n * @param text - The title string, or `null` to clear.\n * @returns This popover, for method chaining.\n */\n setTitle(text: string | null): this {\n if (text === null) {\n return this.clearTitle();\n }\n\n this._title = text;\n\n if (!this._titleComponent) {\n this._titleComponent = new Text(text);\n this._titleComponent.setFontWeight(\"bold\");\n\n this.insertComponent(this._titleComponent, 0);\n } else {\n this._titleComponent.setText(text);\n }\n\n this._reflowIfOpen();\n\n return this;\n }\n\n /**\n * Returns the current title string, or `null` if no title is set.\n *\n * @returns The title set via {@link setTitle}, or `null`.\n */\n getTitle(): string | null {\n return this._title;\n }\n\n /**\n * Removes the title row.\n *\n * @returns This popover, for method chaining.\n */\n clearTitle(): this {\n if (this._titleComponent) {\n this.removeComponent(this._titleComponent);\n this._titleComponent = null;\n }\n\n this._title = null;\n\n this._reflowIfOpen();\n\n return this;\n }\n\n /**\n * Sets the body content. A `string` is wrapped in a\n * [`Text`](/api/component/input/classes/Text) child; a `Component` is used\n * directly. Replaces any previous body.\n *\n * @param content - The body string or component.\n * @returns This popover, for method chaining.\n */\n setBody(content: Component | string): this {\n if (this._bodyComponent) {\n this.removeComponent(this._bodyComponent);\n this._bodyComponent = null;\n }\n\n const next: Component = typeof content === \"string\"\n ? new Text(content)\n : content;\n\n this._bodyComponent = next;\n\n // Insert after the title (if any) and before the actions row (if any).\n const titleOffset = this._titleComponent ? 1 : 0;\n\n this.insertComponent(next, titleOffset);\n\n this._reflowIfOpen();\n\n return this;\n }\n\n /**\n * Returns the current body component, or `null` when none has been set.\n *\n * @returns The body component, or `null`.\n */\n getBody(): Component | null {\n return this._bodyComponent;\n }\n\n /**\n * Appends an action button to the actions row. Lazily creates the row\n * (an [`HBox`](/api/layout/classes/HBox)-laid `Panel`) on first call.\n *\n * @param label - The button label.\n * @param onClick - Handler invoked when the button is activated.\n * @returns This popover, for method chaining.\n */\n addAction(label: string, onClick: () => void): this {\n if (!this._actionsRow) {\n this._actionsRow = new Component();\n this._actionsRow.setLayoutManager(new HBox());\n\n this.addComponent(this._actionsRow);\n }\n\n const button = new Button(label);\n\n button.on(\"action\", onClick);\n\n this._actionsRow.addComponent(button);\n\n return this;\n }\n\n /**\n * Removes every action button previously registered via {@link addAction}.\n *\n * @returns This popover, for method chaining.\n */\n clearActions(): this {\n if (this._actionsRow) {\n this.removeComponent(this._actionsRow);\n this._actionsRow = null;\n }\n\n return this;\n }\n\n /**\n * Records the raw DOM element used as the positioning anchor.\n *\n * @param el - The anchor element.\n * @returns This popover, for method chaining.\n */\n private _attachToElement(el: Handle): this {\n this._anchorElement = el;\n\n return this;\n }\n\n /**\n * Records the anchor by resolving the given component's element. Must be\n * called before {@link Popover.show}.\n *\n * @param c - The component whose element should be used as the anchor.\n * @returns This popover, for method chaining.\n */\n attachToComponent(c: Component): this {\n return this._attachToElement(c.getElement(true)!);\n }\n\n /**\n * Mounts the popover on `document.documentElement` (if not already\n * mounted), resolves the final placement, positions the bubble + arrow,\n * fades it in, and wires the dismiss listeners.\n *\n * @returns This popover, for method chaining.\n */\n show(): this {\n if (!this._anchorElement) {\n console.warn(\"Popover.show(): no anchor attached; call attachToComponent first.\");\n return this;\n }\n\n this._isOpen = true;\n\n // Join the central layer tree and mirror its band-based z-stamp so a\n // popover opened from inside a window or dropdown stacks correctly.\n LayerManager.register(this);\n this.setZIndex(LayerManager.getZIndex(this));\n\n const el = this.getElement(true)!;\n\n LayerManager.mount(el);\n\n // Trap wheels no inner scroller claimed so they cannot fall through to\n // scrollable content behind the popover.\n trapWheel(this);\n\n this.ensureArrow();\n this.setVisible(true);\n\n // First measurement pass: compute preferred size so we can resolve\n // placement against the real bubble dimensions.\n this.doLayout();\n this._reposition();\n\n this._fadeShowAnimation?.cancel();\n this._fadeShowAnimation = fadeShow(this, { durationMs: POPOVER_FADE_DURATION_MS });\n\n this.attachRepositionListeners();\n\n return this;\n }\n\n /**\n * Plays the exit fade, detaches the popover from the DOM, removes every\n * dismiss / reposition listener, and fires `onClose` (if configured)\n * once for this open→close transition.\n *\n * @returns This popover, for method chaining.\n */\n hide(): this {\n if (!this._isOpen) {\n return this;\n }\n\n this._isOpen = false;\n\n this.detachRepositionListeners();\n\n LayerManager.unregister(this);\n untrapWheel(this);\n\n this._fadeHideAnimation?.cancel();\n this._fadeHideAnimation = fadeHideAndDetach(this, { durationMs: POPOVER_FADE_DURATION_MS });\n\n // The `_isOpen` guard above already makes this method run at most\n // once per open→close transition, so `onClose` needs no separate\n // re-entrancy guard of its own.\n this._onClose?.();\n\n return this;\n }\n\n /**\n * Returns whether the popover is currently open (showing or fading in).\n *\n * @returns `true` when the popover is open.\n */\n isOpen(): boolean {\n return this._isOpen;\n }\n\n // ----- DismissableLayer -----\n\n /**\n * Returns the popover's root element for the central layer tree.\n *\n * @returns The popover's element, or null when not yet rendered.\n */\n getLayerElement(): Handle | null {\n return this.getElement() ?? null;\n }\n\n /**\n * Returns the dismiss mode the document-level handlers consult, mapping\n * the public {@link PopoverDismissMode} directly onto the manager's\n * vocabulary (the two share the `\"click-outside\"` / `\"blur\"` / `\"manual\"`\n * names). The manager now executes dismissal; the `\"blur\"` mode works for\n * a nested dropdown because the dropdown registers as the popover's child.\n *\n * @returns The layer dismiss mode.\n */\n getDismissMode(): LayerDismissMode {\n return this._dismissOn ?? this._defaultOptions.dismissOn!;\n }\n\n /**\n * Advisory close request from the manager — runs the standard\n * {@link Popover.hide} teardown, which unregisters the layer.\n */\n requestClose(): void {\n this.hide();\n }\n\n /**\n * Returns the anchor element excluded from outside-interaction tests so a\n * click on the trigger does not immediately re-close the popover.\n *\n * @returns The anchor element, or null when none is attached.\n */\n getAnchorElement(): Handle | null {\n return this._anchorElement;\n }\n\n /**\n * Returns the popover's z-index band so an unrelated top-level popover\n * stacks above windows but below dropdowns and dialogs.\n *\n * @returns The popover band base.\n */\n getBand(): number {\n return LayerManager.Band.Popover;\n }\n\n /**\n * Lays out children (delegating to the VBox) and positions the arrow\n * tail along the resolved edge.\n *\n * @returns This popover, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n if (this._arrowComponent && this._showArrow && this._anchorElement) {\n this.positionArrow();\n }\n\n return this;\n }\n\n /**\n * Releases per-instance resources. Closes the popover if it is still\n * open, disposes the raw-appended arrow, then defers to the base class\n * for the rest of teardown.\n */\n protected destructor(): void {\n if (this._isOpen) {\n this.hide();\n }\n\n // `_titleComponent` / `_bodyComponent` / `_actionsRow` are all\n // registered via `insertComponent` / `addComponent`, so\n // `super.destructor()`'s child recursion below already disposes\n // them — an explicit call here would run each one's destructor()\n // a second time. `_arrowComponent`, by contrast, is inserted\n // straight into the DOM via `ensureArrow()` (not registered in\n // `_components`), so recursion can never reach it and it must be\n // disposed explicitly.\n // After `hide()` above, since that starts a fresh fade-out whose\n // fallback timer would otherwise outlive the element handle\n // `super.destructor()` releases below.\n this._fadeShowAnimation?.cancel();\n this._fadeShowAnimation = null;\n this._fadeHideAnimation?.cancel();\n this._fadeHideAnimation = null;\n\n this._arrowComponent?.dispose();\n\n this._anchorElement = null;\n this._titleComponent = null;\n this._bodyComponent = null;\n this._actionsRow = null;\n this._arrowComponent = null;\n this._onClose = null;\n\n super.destructor();\n }\n\n /**\n * Re-measures and repositions the popover after a content mutation\n * (`setTitle` / `clearTitle` / `setBody`) — but only while the popover is\n * currently shown. `insertComponent` / `removeComponent` only *schedule*\n * a layout pass (next animation frame), so without this the bubble keeps\n * its old preferred size — and stays anchored at the old `x`/`y` derived\n * from it — until an unrelated `window` resize or ancestor scroll happens\n * to run `_reposition()` next. Mirrors the same \"measure, then position\"\n * pair `show()` runs on first open. A no-op before the first `show()`,\n * matching every other content setter's tolerance for being called on an\n * unshown popover.\n */\n private _reflowIfOpen(): void {\n if (!this._isOpen) {\n return;\n }\n\n this.doLayout();\n this._reposition();\n }\n\n /**\n * Resolves the requested placement against the viewport, anchor rect, and\n * own preferred size; updates the popover's `setX` / `setY` and the\n * resolved-placement field.\n */\n private _reposition(): void {\n if (!this._anchorElement) {\n return;\n }\n\n const anchorRect = DOM.source.getElementRect(this._anchorElement);\n\n // Anchor removed from the DOM or rendered with zero size — close.\n if (anchorRect.width === 0 && anchorRect.height === 0) {\n this.hide();\n return;\n }\n\n const preferred = this.getPreferredSize();\n const width = preferred?.width ?? this.getWidth();\n const height = preferred?.height ?? this.getHeight();\n const vp = DOM.source.getViewportSize();\n\n const resolved = this.resolvePlacement(anchorRect, width, height, vp);\n\n this._resolvedPlacement = resolved;\n\n let x: number = 0;\n let y: number = 0;\n\n if (resolved === \"top\") {\n x = anchorRect.left + (anchorRect.width - width) / 2;\n y = anchorRect.top - height - POPOVER_ANCHOR_GAP;\n } else if (resolved === \"bottom\") {\n x = anchorRect.left + (anchorRect.width - width) / 2;\n y = anchorRect.bottom + POPOVER_ANCHOR_GAP;\n } else if (resolved === \"left\") {\n x = anchorRect.left - width - POPOVER_ANCHOR_GAP;\n y = anchorRect.top + (anchorRect.height - height) / 2;\n } else { // \"right\"\n x = anchorRect.right + POPOVER_ANCHOR_GAP;\n y = anchorRect.top + (anchorRect.height - height) / 2;\n }\n\n // Clamp into viewport so the bubble stays on-screen. The arrow's\n // independent positioning keeps it pointing at the anchor centre\n // even when the bubble is shifted laterally. On the tip-direction\n // side, leave room for the arrow's outward visual extent so the tip\n // also stays at least VIEWPORT_EDGE_INSET_PX inside the viewport.\n let minX = VIEWPORT_EDGE_INSET_PX;\n let maxX = vp.width - width - VIEWPORT_EDGE_INSET_PX;\n let minY = VIEWPORT_EDGE_INSET_PX;\n let maxY = vp.height - height - VIEWPORT_EDGE_INSET_PX;\n\n if (resolved === \"right\") {\n minX += ARROW_VISUAL_HALF;\n } else if (resolved === \"left\") {\n maxX -= ARROW_VISUAL_HALF;\n } else if (resolved === \"bottom\") {\n minY += ARROW_VISUAL_HALF;\n } else {\n maxY -= ARROW_VISUAL_HALF;\n }\n\n x = Util.clamp(x, minX, maxX);\n y = Util.clamp(y, minY, maxY);\n\n this.setX(x);\n this.setY(y);\n this.setWidth(width);\n this.setHeight(height);\n\n if (this._arrowComponent && this._showArrow) {\n this.positionArrow();\n }\n }\n\n /**\n * Picks the placement to use given the configured value and the available\n * viewport space. `\"auto\"` selects the side with the most room; an\n * explicit side is honoured unless it would overflow, in which case the\n * opposite side is used and a console warning is logged.\n *\n * @param anchor - The anchor's `DOMRect`.\n * @param width - The popover's preferred width in pixels.\n * @param height - The popover's preferred height in pixels.\n * @param vp - The viewport size returned by `DOM.source.getViewportSize`.\n * @returns The resolved placement.\n */\n private resolvePlacement(\n anchor: Rect,\n width: number,\n height: number,\n vp: { width: number; height: number },\n ): PopoverPlacement {\n const spaceTop = anchor.top;\n const spaceBottom = vp.height - anchor.bottom;\n const spaceLeft = anchor.left;\n const spaceRight = vp.width - anchor.right;\n\n if (this._placement === \"auto\") {\n const needsH = height + POPOVER_ANCHOR_GAP;\n const needsV = width + POPOVER_ANCHOR_GAP;\n\n const candidates: Array<{ side: PopoverPlacement; space: number; need: number }> = [\n { side: \"bottom\", space: spaceBottom, need: needsH },\n { side: \"top\", space: spaceTop, need: needsH },\n { side: \"right\", space: spaceRight, need: needsV },\n { side: \"left\", space: spaceLeft, need: needsV },\n ];\n\n // Prefer a side that physically fits; otherwise pick the one\n // with the most absolute space.\n const fitting = candidates.filter(c => c.space >= c.need);\n const pool = fitting.length > 0 ? fitting : candidates;\n\n pool.sort((a, b) => b.space - a.space);\n\n return pool[0].side;\n }\n\n // Explicit placement — honour unless the requested side cannot fit.\n const fits = (side: PopoverPlacement): boolean => {\n if (side === \"top\") { return spaceTop >= height + POPOVER_ANCHOR_GAP; }\n if (side === \"bottom\") { return spaceBottom >= height + POPOVER_ANCHOR_GAP; }\n if (side === \"left\") { return spaceLeft >= width + POPOVER_ANCHOR_GAP; }\n\n return spaceRight >= width + POPOVER_ANCHOR_GAP;\n };\n\n if (fits(this._placement)) {\n return this._placement;\n }\n\n const opposite: Record<Exclude<PopoverPlacement, \"auto\">, Exclude<PopoverPlacement, \"auto\">> = {\n top: \"bottom\",\n bottom: \"top\",\n left: \"right\",\n right: \"left\",\n };\n\n const flipped = opposite[this._placement as Exclude<PopoverPlacement, \"auto\">];\n\n console.warn(`Popover: explicit placement \"${this._placement}\" overflows the viewport; falling back to \"${flipped}\".`);\n\n return flipped;\n }\n\n /**\n * Lazily creates the arrow tail component on first show.\n *\n * @remarks The arrow's element is inserted as the *first* DOM child of\n * the popover (not via `addComponent`) so the VBox layout manager does\n * not size it AND so it paints beneath subsequent sibling content. The\n * outward half of the diamond is still visible because it lies outside\n * the popover's bounds; the inward half is overlaid by the bubble's\n * children, preventing the arrow from obscuring the title/body text.\n */\n private ensureArrow(): void {\n if (this._arrowComponent) {\n return;\n }\n\n const arrow = new Component();\n const size = DEFAULT_ARROW_SIZE_PX;\n\n arrow.setBackgroundColor(\"var(--ts-ui-popover-bg, rgb(255, 255, 255))\");\n arrow.setWidth(size);\n arrow.setHeight(size);\n arrow.setTransform(\"rotate(45deg)\");\n arrow.setPointerEvents(\"none\");\n arrow.setVisible(this._showArrow);\n\n this._arrowComponent = arrow;\n\n const popoverEl = this.getElement(true)!;\n DOM.sink.insertBefore(popoverEl, arrow.getElement(true)!, DOM.source.getFirstChild(popoverEl));\n }\n\n /**\n * Positions the arrow tail along the resolved popover edge so it points\n * at the anchor centre, clamped to keep it within the popover's lateral\n * extent. Also re-applies the directional inset box-shadow that draws the\n * two outward-facing edges of the rotated diamond so the popover outline\n * appears continuous through the arrow.\n */\n private positionArrow(): void {\n if (!this._anchorElement || !this._arrowComponent) {\n return;\n }\n\n const anchorRect = DOM.source.getElementRect(this._anchorElement);\n const size = DEFAULT_ARROW_SIZE_PX;\n const half = size / 2;\n const popoverX = this.getX();\n const popoverY = this.getY();\n const popoverW = this.getWidth();\n const popoverH = this.getHeight();\n\n // High-first clamp (not Util.clamp): when the popover is larger than the\n // viewport, maxLocal < minLocal, and the arrow must pin to the leading\n // inset (minLocal), which the low-first Util.clamp would not do.\n const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(value, max));\n\n // Inset box-shadow draws a 1px line on the two outward-facing edges\n // of the rotated diamond. The mapping below is given in\n // pre-rotation coordinates (the element's own CSS axes); after the\n // 45° clockwise rotation, original TOP/RIGHT/BOTTOM/LEFT edges map to\n // the rotated NE/SE/SW/NW edges.\n const borderColor = \"var(--ts-ui-popover-border, rgb(200, 200, 200))\";\n let arrowShadow: string;\n\n if (this._resolvedPlacement === \"bottom\") {\n arrowShadow = `inset 1px 0 0 ${borderColor}, inset 0 1px 0 ${borderColor}`;\n } else if (this._resolvedPlacement === \"top\") {\n arrowShadow = `inset -1px 0 0 ${borderColor}, inset 0 -1px 0 ${borderColor}`;\n } else if (this._resolvedPlacement === \"right\") {\n arrowShadow = `inset 1px 0 0 ${borderColor}, inset 0 -1px 0 ${borderColor}`;\n } else {\n arrowShadow = `inset 0 1px 0 ${borderColor}, inset -1px 0 0 ${borderColor}`;\n }\n\n this._arrowComponent.setShadow(arrowShadow);\n\n const vp = DOM.source.getViewportSize();\n const border = this.getBorderSize();\n\n // `position: absolute` measures from the popover's padding box (i.e.\n // inside the border). Subtracting the border width centres the\n // rotated diamond on the popover's *outer* edge, keeping the tip-to-\n // anchor gap predictable regardless of border thickness.\n if (this._resolvedPlacement === \"top\" || this._resolvedPlacement === \"bottom\") {\n const anchorCentreX = anchorRect.left + anchorRect.width / 2;\n const minLocalX = Math.max(\n ARROW_EDGE_INSET_PX,\n VIEWPORT_EDGE_INSET_PX - popoverX + ARROW_VISUAL_HALF - half,\n );\n const maxLocalX = Math.min(\n popoverW - size - ARROW_EDGE_INSET_PX,\n vp.width - VIEWPORT_EDGE_INSET_PX - popoverX - half - ARROW_VISUAL_HALF,\n );\n const localX = clamp(anchorCentreX - popoverX - half - border.left, minLocalX, maxLocalX);\n\n this._arrowComponent.setX(localX);\n\n // Pull the arrow half its own size outside the body so the\n // rotated diamond reads as a triangle straddling the edge.\n if (this._resolvedPlacement === \"bottom\") {\n this._arrowComponent.setY(-half - border.top);\n } else {\n this._arrowComponent.setY(popoverH - half - border.top);\n }\n } else {\n const anchorCentreY = anchorRect.top + anchorRect.height / 2;\n const minLocalY = Math.max(\n ARROW_EDGE_INSET_PX,\n VIEWPORT_EDGE_INSET_PX - popoverY + ARROW_VISUAL_HALF - half,\n );\n const maxLocalY = Math.min(\n popoverH - size - ARROW_EDGE_INSET_PX,\n vp.height - VIEWPORT_EDGE_INSET_PX - popoverY - half - ARROW_VISUAL_HALF,\n );\n const localY = clamp(anchorCentreY - popoverY - half - border.top, minLocalY, maxLocalY);\n\n this._arrowComponent.setY(localY);\n\n if (this._resolvedPlacement === \"right\") {\n this._arrowComponent.setX(-half - border.left);\n } else {\n this._arrowComponent.setX(popoverW - half - border.left);\n }\n }\n }\n\n /**\n * Registers `window` resize and `scroll` listeners on every scrollable\n * ancestor of the anchor so the popover follows the anchor while open.\n */\n private attachRepositionListeners(): void {\n Event.addViewportListener(this, \"resize\", this._onWindowResize);\n\n if (this._anchorElement) {\n this._scrollAncestors = this.collectScrollAncestors(this._anchorElement);\n\n for (const ancestor of this._scrollAncestors) {\n DOM.sink.addListener(ancestor, \"scroll\", this._onScroll, { passive: true });\n }\n }\n }\n\n /**\n * Detaches every reposition listener registered by {@link attachRepositionListeners}.\n */\n private detachRepositionListeners(): void {\n Event.removeViewportListener(this, \"resize\", this._onWindowResize);\n\n for (const ancestor of this._scrollAncestors) {\n DOM.sink.removeListener(ancestor, \"scroll\", this._onScroll);\n }\n\n this._scrollAncestors = [];\n }\n\n /**\n * Walks the anchor's ancestor chain up to `document.documentElement` and\n * collects every element whose computed `overflow` makes it scrollable.\n *\n * @param node - The starting element.\n * @returns The list of scrollable ancestors plus `document.documentElement`.\n */\n private collectScrollAncestors(node: Handle): Handle[] {\n const out: Handle[] = [];\n let cursor: Handle | null = DOM.source.getParentElement(node);\n\n while (cursor && cursor !== DOM.source.getDocumentElement()) {\n const style = DOM.source.getComputedOverflow(cursor);\n const overflow = style.overflow + style.overflowX + style.overflowY;\n\n if (/(auto|scroll|overlay)/.test(overflow)) {\n out.push(cursor);\n }\n\n cursor = DOM.source.getParentElement(cursor);\n }\n\n out.push(DOM.source.getDocumentElement());\n\n return out;\n }\n}\n\nconst PopoverCallable = callable(Popover);\ntype PopoverCallable = Popover;\nexport {\n Popover as _Popover,\n PopoverCallable as Popover\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link DialogBackdrop}.\n *\n * @category Components\n */\ninterface DialogBackdropOptions extends ComponentOptions {\n}\n\n/**\n * Empty subclass-default const so the super call follows the framework's\n * `(options, defaults)` shape uniformly.\n */\nconst _defaultDialogBackdropOptions: Partial<DialogBackdropOptions> = {};\n\n/**\n * A full-viewport fixed overlay that visually blocks content behind a modal dialog.\n *\n * Appended to `document.documentElement` as a sibling of the dialog panel at a lower\n * z-index, mirroring the pattern used by [`Notification`](/api/overlay/classes/Notification) and [`Menu`](/api/overlay/classes/Menu).\n */\nclass DialogBackdrop extends Component<DialogBackdropOptions> {\n\n /**\n * Creates the backdrop and applies viewport-filling fixed positioning.\n *\n * @param options - Optional construction 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?: DialogBackdropOptions, subclassDefaults?: Partial<DialogBackdropOptions>) {\n super(options, { ..._defaultDialogBackdropOptions, ...(subclassDefaults ?? {}) });\n\n const vp = DOM.source.getViewportSize();\n\n this.setPosition(Position.FIXED);\n this.setX(0);\n this.setY(0);\n this.setWidth(vp.width);\n this.setHeight(vp.height);\n this.setZIndex(10100);\n this.setBackgroundColor(\"var(--ts-ui-dialog-backdrop-bg)\");\n }\n\n /**\n * Registers a click listener on this backdrop element.\n *\n * @param listener - Called when the user clicks the backdrop area.\n */\n addClickListener(listener: Event.Listener): this {\n Event.addListener(this, \"click\", listener);\n\n return this;\n }\n\n /**\n * Updates backdrop dimensions to match the current viewport size.\n */\n resize(): void {\n const vp = DOM.source.getViewportSize();\n\n this.setWidth(vp.width);\n this.setHeight(vp.height);\n }\n\n /**\n * Removes the backdrop from the DOM and runs component cleanup.\n */\n destroy(): void {\n this.removeElement();\n this.destructor();\n }\n}\n\nconst DialogBackdropCallable = callable(DialogBackdrop);\ntype DialogBackdropCallable = DialogBackdrop;\nexport {\n DialogBackdrop as _DialogBackdrop,\n DialogBackdropCallable as DialogBackdrop\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Panel } from \"~/core/Panel.js\";\nimport { Animation } from \"~/core/Animation.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { LayerManager, DismissableLayer, LayerDismissMode } from \"~/core/LayerManager.js\";\nimport { trapWheel, untrapWheel } from \"~/core/WheelTrap.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { SelectableText } from \"~/component/input/SelectableText.js\";\nimport { Button } from \"~/component/button/Button.js\";\nimport { Glyph } from \"~/component/display/Glyph.js\";\nimport { DialogBackdrop } from \"~/component/container/DialogBackdrop.js\";\nimport { Border as BorderLayout } from \"~/layout/Border.js\";\nimport { Fit } from \"~/layout/Fit.js\";\nimport { Placement } from \"~/primitive/Placement.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { xmark } from \"~/glyphs/solid/xmark.js\";\nimport { circle_check } from \"~/glyphs/solid/circle_check.js\";\nimport { circle_info } from \"~/glyphs/solid/circle_info.js\";\nimport { triangle_exclamation } from \"~/glyphs/solid/triangle_exclamation.js\";\nimport { circle_exclamation } from \"~/glyphs/solid/circle_exclamation.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { ThemeManager } from \"~/core/Theme.js\";\n\n/**\n * Square edge length used for the dialog's title-bar glyph — the theme's\n * `glyphLg` default icon step (16px at the shipped base). Read per call, not\n * frozen in a module constant, so a theme that raises `scale.base` moves the\n * icon with it.\n */\nfunction titleGlyphPx(): number {\n return ThemeManager.getResolvedScale().glyphLg;\n}\n\nGlyph.register(xmark, circle_check, circle_info, triangle_exclamation, circle_exclamation);\n\n/**\n * The result produced when a dialog is dismissed.\n *\n * @category Core\n */\nexport type DialogResult = 'confirm' | 'cancel' | 'close';\n\n/**\n * Configuration for a single button in a dialog's button row.\n *\n * @category Core\n */\nexport interface DialogButtonConfig {\n /** The label text displayed on the button. */\n text : string;\n /** The result value emitted when this button is clicked. Defaults to `'cancel'`. */\n result? : DialogResult;\n /** When true, renders the button with primary (confirm) styling. */\n primary?: boolean;\n /** Optional registry glyph name shown to the left of the button label. */\n glyph? : string;\n /**\n * Optional foreground colour applied to the button's leading glyph. Accepts\n * any CSS colour string — typically a theme variable reference such as\n * `'var(--ts-ui-dialog-confirm-color)'`. When omitted the glyph inherits\n * the button's `currentColor`. The {@link DialogButtons} presets supply\n * the appropriate tint by default; reach for this field at the call site\n * only when overriding a preset or building a one-off button.\n */\n tint? : string;\n /**\n * Optional async guard run when this button is clicked, before the dialog\n * closes. Return (or resolve) `false` to veto the close: the dialog stays\n * open and its `show()` promise does not resolve, so the caller can show\n * its own in-content validation error and let the user retry with no\n * rebuild. Return (or resolve) `true` — or omit `onClick` entirely — to\n * close normally with this button's `result`, exactly as before this\n * field existed.\n *\n * Every button in the row is disabled for the duration of a pending\n * `onClick` call, so a slow validation/submit can't race a second click.\n * A rejected/thrown `onClick` also vetoes the close (buttons re-enable),\n * and the rejection propagates to the caller — reserve throwing for a\n * genuine bug, not an expected validation failure; return `false` for that.\n *\n * Only chrome buttons go through this guard: Escape, a backdrop click, and\n * the title-bar close button all still close unconditionally, so a user\n * always has an unvalidated way out of the dialog.\n */\n onClick?: () => boolean | Promise<boolean>;\n}\n\n/**\n * Severity tone for a dialog's title bar, mirroring\n * [`NotificationType`](/api/core/type-aliases/NotificationType). When set it\n * tints the header and shows a matching leading glyph, taking precedence over\n * the tone otherwise derived from the buttons.\n *\n * @category Core\n */\nexport type DialogSeverity = 'info' | 'success' | 'warning' | 'error';\n\n/**\n * Configuration object passed to `new Dialog(config)` or `Dialog.show(config)`.\n *\n * @category Core\n */\nexport interface DialogConfig {\n /** Text displayed in the dialog title bar. */\n title : string;\n /** Plain-text body message. Ignored when `contentComponent` is provided. */\n message? : string;\n /** A custom component rendered in the content area instead of a message label. */\n contentComponent?: Component;\n /**\n * Button definitions for the footer row.\n * Defaults to a single OK button that resolves with `'confirm'`.\n */\n buttons? : DialogButtonConfig[];\n /** Dialog panel width in pixels. Defaults to 480. */\n width? : number;\n /** Dialog panel height in pixels. When omitted the height is computed from content. */\n height? : number;\n /** When true, clicking the backdrop closes the dialog with result `'close'`. Defaults to false. */\n closeOnBackdrop? : boolean;\n /**\n * When `false`, the dialog is a mandatory modal: no title-bar close button,\n * Escape does not close it, and a backdrop click does not close it (regardless\n * of `closeOnBackdrop`). Defaults to `true`.\n */\n dismissable? : boolean;\n /**\n * Optional severity tone for the title bar (`'info'`, `'success'`,\n * `'warning'`, `'error'`). When set it tints the header and shows a matching\n * leading glyph, overriding the tone derived from the buttons. Omit for the\n * default button-derived chrome.\n */\n severity? : DialogSeverity;\n /**\n * Component to receive focus when the dialog opens, overriding the default\n * (the first focusable element in the content region). Use it when the field\n * that should take focus is not the first one — a form whose first control is\n * a read-only summary, say. Ignored when the component has no focusable\n * element on open, which falls back to the default order.\n */\n initialFocus? : Component;\n}\n\n// ---------------------------------------------------------------------------\n// Private constants\n// ---------------------------------------------------------------------------\n\nconst TITLE_HEIGHT : number = 36;\nconst BUTTON_HEIGHT : number = 52;\nconst BUTTON_WIDTH : number = 90;\nconst BUTTON_GAP : number = 8;\nconst BUTTON_V_PAD : number = 11;\nconst CLOSE_SIZE : number = 20;\nconst TITLE_H_PAD : number = 12;\nconst MIN_DIALOG_WIDTH : number = 320;\nconst MIN_DIALOG_HEIGHT: number = 160;\nconst MIN_CONTENT_HEIGHT: number = 80;\n// Minimum gap kept between a content-resized dialog and each viewport edge, so a\n// dialog grown to tall content never runs flush to the top/bottom of the screen.\nconst DIALOG_VIEWPORT_MARGIN: number = 24;\n\n// Leading title-bar glyph per severity tone, mirroring Notification's badges.\nconst SEVERITY_GLYPH: Record<DialogSeverity, string> = {\n info: \"circle-info\",\n success: \"circle-check\",\n warning: \"triangle-exclamation\",\n error: \"circle-exclamation\",\n};\n\n/**\n * Shared duration (ms) for the dialog entrance/exit transition. The backdrop\n * fade and the panel's opacity + scale all run for this many milliseconds.\n */\nconst DIALOG_ANIM_DURATION_MS: number = 150;\n\n/**\n * CSS selector matching the focusable elements inside a dialog — the Tab\n * focus-trap boundary set, the initial-focus candidates, and the primary-button\n * lookup all share it so the notion of \"focusable\" stays single-sourced.\n */\nconst FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Vertical breathing room reserved above and below the title text inside the\n * `TITLE_HEIGHT` row. 4 px on each side: keeps the bold label off the divider\n * border and gives a balanced visual cap height. Used both for the text's\n * line-height (via {@link Text.centerInHeight}) and for its laid-out height\n * inside the bar.\n */\nconst TITLE_V_PAD: number = 4;\n\n/**\n * Horizontal gap between the close button and the right edge of the title\n * bar, plus the gap between the title text and the close button. Two\n * separate offsets share the same value so the close-button column reads as\n * a balanced `[gap][icon][gap]` strip.\n */\nconst TITLE_RIGHT_GAP: number = 4;\n\n/**\n * Horizontal gap between the optional leading glyph and the title text.\n * Matches the 8 px gutter the WindowHeader uses between its title icon and\n * label so the two surfaces feel consistent.\n */\nconst TITLE_GLYPH_TEXT_GAP: number = 8;\n\n// ---------------------------------------------------------------------------\n// Private: DialogTitleBar\n// ---------------------------------------------------------------------------\n\n/**\n * Title bar that occupies the NORTH slot of a Dialog's border layout.\n * Contains a text label on the left, an optional leading glyph, and a glyph\n * close button on the right.\n *\n * @remarks\n * Reach this instance via [`Dialog.getTitleBar()`](/api/overlay/classes/Dialog#gettitlebar) — there is no public\n * constructor. The supported surface is `getTitleText()` (for tinting the\n * title text colour), `setGlyph()` / `getGlyph()` (for the optional leading\n * icon), and any inherited [`Component`](/api/core/classes/Component) setter\n * (e.g. `setBackgroundColor`).\n *\n * @category Core\n */\nclass DialogTitleBar extends Component {\n\n private readonly _titleText : Text;\n private _closeButton: Button | null = null;\n private _titleGlyph: Glyph | null = null;\n\n /**\n * @param title - Text to display in the title bar.\n * @param onClose - Called when the user clicks the close button.\n * @param dismissable - When `false`, the close button is not built at all\n * (mandatory-modal title bar).\n */\n constructor(title: string, onClose: () => void, dismissable: boolean) {\n super();\n\n this.setBackgroundColor(\"var(--ts-ui-body-bg)\");\n this.setBorder({\n border: \"none\",\n borderBottom: \"1px solid var(--ts-ui-dialog-border)\",\n });\n this.setPreferredSize({ width: 0, height: TITLE_HEIGHT });\n\n this._titleText = new Text(title);\n this._titleText.setFontWeight(\"bold\");\n this._titleText.setOverflow(\"hidden\");\n this._titleText.setTextOverflow(\"ellipsis\");\n this._titleText.setWhiteSpace(\"nowrap\");\n // Centre the label within the inner area of the row (TITLE_HEIGHT\n // minus the top + bottom TITLE_V_PAD breathing room).\n this._titleText.centerInHeight(TITLE_HEIGHT - TITLE_V_PAD * 2);\n this.addComponent(this._titleText);\n\n if (dismissable) {\n this._closeButton = new Button({ glyph: \"xmark\" });\n this._closeButton.setInsets(new Insets(0, 0, 0, 0));\n this._closeButton.setBorder(\"none\");\n this._closeButton.clearBackgroundImage();\n this._closeButton.setBackgroundColor(\"transparent\");\n this._closeButton.clearShadow();\n this._closeButton.clearPressedShadow();\n this._closeButton.clearHoverShadow();\n // Hover and pressed background swap out the framework's gray\n // var(--ts-ui-button-hover-bg, …) for a translucent overlay that\n // darkens whatever tinted header sits underneath without\n // imposing its own colour. Also drop the hover gradient so it\n // doesn't double up over the overlay.\n this._closeButton.setHoverBackgroundColor(\"var(--ts-ui-titlebar-btn-hover-bg, rgba(0, 0, 0, 0.08))\");\n this._closeButton.setPressedBackgroundColor(\"var(--ts-ui-titlebar-btn-active-bg, rgba(0, 0, 0, 0.16))\");\n this._closeButton.clearHoverBackgroundImage();\n this._closeButton.clearPressedBackgroundImage();\n this._closeButton.setPreferredSize({ width: CLOSE_SIZE, height: CLOSE_SIZE });\n this.addComponent(this._closeButton);\n\n this._closeButton.on(\"action\", onClose);\n }\n }\n\n /**\n * Returns the title bar's close button, or `null` when the title bar was\n * built non-dismissable (no close affordance).\n *\n * @returns The close [`Button`](/api/component/button/classes/Button), or `null`.\n */\n getCloseButton(): Button | null {\n return this._closeButton;\n }\n\n /**\n * Returns the title-text component, for callers that need to tint or\n * otherwise restyle it from outside the title bar.\n *\n * @returns The internal title [`Text`](/api/component/input/classes/Text) instance.\n */\n getTitleText(): Text {\n return this._titleText;\n }\n\n /**\n * Sets or clears an optional leading glyph shown to the left of the title text.\n *\n * @param name - Registry glyph name to display, or `null` to clear an existing glyph.\n *\n * @returns This component, for method chaining.\n *\n * @remarks\n * The current implementation positions the glyph in `doLayout`; only the\n * notification-detail path uses this slot, and the glyph never coexists with\n * other left-side decoration on a Dialog title bar.\n */\n setGlyph(name: string): this {\n if (this._titleGlyph) {\n this.removeComponent(this._titleGlyph);\n this._titleGlyph = null;\n }\n\n const glyph = new Glyph(name);\n const iconPx = titleGlyphPx();\n glyph.setPointerEvents(\"none\");\n glyph.setPreferredSize({ width: iconPx, height: iconPx });\n this._titleGlyph = glyph;\n this.addComponent(glyph);\n\n this.doLayout();\n\n return this;\n }\n\n /**\n * Removes the leading title-bar glyph from the dialog, if one is present.\n *\n * @returns This component, for method chaining.\n */\n clearGlyph(): this {\n if (this._titleGlyph) {\n this.removeComponent(this._titleGlyph);\n this._titleGlyph = null;\n this.doLayout();\n }\n\n return this;\n }\n\n /**\n * Returns the optional leading title-glyph component, or null if none is set.\n *\n * @returns The leading [`Glyph`](/api/component/display/classes/Glyph) instance, or null.\n */\n getGlyph(): Glyph | null {\n return this._titleGlyph;\n }\n\n /**\n * Positions the title label, optional leading glyph, and close button within\n * the title bar's content box.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (!box) {\n return this;\n }\n\n const w = box.width;\n const h = box.height;\n const closeX = w - CLOSE_SIZE - TITLE_RIGHT_GAP;\n const centerY = Math.floor((h - CLOSE_SIZE) / 2);\n const rightBound = this._closeButton\n ? closeX // reserve the close-button slot\n : (w - TITLE_H_PAD); // no button: label runs to the right pad\n\n let labelX = TITLE_H_PAD;\n\n if (this._titleGlyph) {\n const fallbackPx = titleGlyphPx();\n const glyphSize = this._titleGlyph.getPreferredSize() ?? { width: fallbackPx, height: fallbackPx };\n const glyphY = Math.max(0, Math.floor((h - glyphSize.height) / 2));\n\n this._titleGlyph.setX(box.x + TITLE_H_PAD);\n this._titleGlyph.setY(box.y + glyphY);\n this._titleGlyph.setWidth(glyphSize.width);\n this._titleGlyph.setHeight(glyphSize.height);\n\n labelX = TITLE_H_PAD + glyphSize.width + TITLE_GLYPH_TEXT_GAP;\n }\n\n // Reserve TITLE_RIGHT_GAP of space between the label and the close button.\n const labelWidth = Math.max(0, rightBound - labelX - TITLE_RIGHT_GAP);\n const labelH = h - TITLE_V_PAD * 2;\n\n this._titleText.setX(box.x + labelX);\n this._titleText.setY(box.y + TITLE_V_PAD);\n this._titleText.setWidth(labelWidth);\n this._titleText.setHeight(labelH);\n\n if (this._closeButton) {\n this._closeButton.setX(box.x + closeX);\n this._closeButton.setY(box.y + centerY);\n this._closeButton.setWidth(CLOSE_SIZE);\n this._closeButton.setHeight(CLOSE_SIZE);\n // setX/setY/setWidth/setHeight don't cascade — explicitly relayout the\n // close button so its internal Fit layout sizes the times glyph.\n this._closeButton.doLayout();\n }\n\n return this;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private: DialogButtonRow\n// ---------------------------------------------------------------------------\n\n/**\n * Footer row that occupies the SOUTH slot of a Dialog's border layout.\n * Lays out one or more buttons, right-aligned.\n */\nclass DialogButtonRow extends Component {\n\n private readonly _buttons : Button[] = [];\n private readonly _onButton: (result: DialogResult) => void;\n\n /**\n * @param configs - Button definitions to render.\n * @param onButton - Called with the resolved [`DialogResult`](/api/overlay/type-aliases/DialogResult) when a button's click clears its own `onClick` guard (or has none).\n */\n constructor(configs: DialogButtonConfig[], onButton: (result: DialogResult) => void) {\n super();\n\n this._onButton = onButton;\n\n this.setBorder({\n border: \"none\",\n borderTop: \"1px solid var(--ts-ui-dialog-border)\",\n });\n this.setBackgroundColor(\"var(--ts-ui-body-bg)\");\n this.setPreferredSize({ width: 0, height: BUTTON_HEIGHT });\n\n for (const cfg of configs) {\n const btn = new Button(cfg.text, cfg.glyph !== undefined ? { glyph: cfg.glyph } : undefined);\n const result = cfg.result ?? 'cancel';\n\n if (cfg.primary) {\n btn.setBackgroundImage(\"var(--ts-ui-toggle-selected-bg, rgb(200, 200, 200))\");\n }\n\n if (cfg.glyph !== undefined) {\n const glyph = btn.getGlyph();\n const tint = cfg.tint;\n\n if (glyph !== null && tint) {\n glyph.setForegroundColor(tint);\n }\n }\n\n btn.on(\"action\", () => void this.handleClick(cfg, result));\n this._buttons.push(btn);\n this.addComponent(btn);\n }\n }\n\n /**\n * Runs `cfg.onClick` (if any) before reporting the click upward. Disables\n * every button in the row for the duration of a pending guard, so a slow\n * validation/submit can't race a second click; re-enables them once the\n * guard settles (a `true`/omitted result is about to tear this row down\n * anyway, so re-enabling then is harmless). A guard that rejects/throws\n * still re-enables the row and propagates — see `DialogButtonConfig.onClick`'s doc.\n *\n * @param cfg - The clicked button's own config (carries its `onClick`).\n * @param result - The `DialogResult` to report once the guard clears.\n */\n private async handleClick(cfg: DialogButtonConfig, result: DialogResult): Promise<void> {\n if (!cfg.onClick) {\n this._onButton(result);\n\n return;\n }\n\n this.setButtonsEnabled(false);\n\n let proceed: boolean;\n\n try {\n proceed = await cfg.onClick();\n } finally {\n this.setButtonsEnabled(true);\n }\n\n if (proceed) {\n this._onButton(result);\n }\n }\n\n /**\n * Enables or disables every button in the row at once — used to lock the\n * whole footer while one button's `onClick` guard is pending.\n *\n * @param enabled - The enabled state to apply to every button.\n */\n private setButtonsEnabled(enabled: boolean): void {\n for (const btn of this._buttons) {\n btn.setEnabled(enabled);\n }\n }\n\n /**\n * Positions buttons right-aligned within the footer row's content box.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (!box) {\n return this;\n }\n\n const btnH = box.height - BUTTON_V_PAD * 2;\n const totalW = this._buttons.length * BUTTON_WIDTH + (this._buttons.length - 1) * BUTTON_GAP;\n let x = Math.round((box.width - totalW) / 2);\n\n for (const btn of this._buttons) {\n btn.setX(box.x + x);\n btn.setY(box.y + BUTTON_V_PAD);\n btn.setWidth(BUTTON_WIDTH);\n btn.setHeight(btnH);\n\n btn.doLayout();\n\n x += BUTTON_WIDTH + BUTTON_GAP;\n }\n\n return this;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public: Dialog\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical dialog button presets. Spread into the `buttons` array of a\n * {@link DialogConfig} to inherit the standard text / result / glyph mapping\n * for the three universal dismiss-row affordances; override `primary` per\n * call site since which button is default-focused is contextual (Cancel is\n * primary when paired with Confirm; Confirm is primary when it stands alone).\n *\n * Centralising the `glyph` here is the rule that prevents drift — the\n * checkmark/xmark mapping is bound to the button's identity, never re-typed\n * at the call site. {@link Dialog} also inspects the resolved result set to\n * pick the title-bar variant (only `confirm` → info header with leading\n * `circle-info`; `confirm` + `cancel` → affirm header).\n *\n * @category Core\n * @example\n * ```typescript\n * Dialog.show({\n * title: 'Delete record',\n * message: 'This cannot be undone.',\n * buttons: [\n * { ...DialogButtons.Cancel, primary: true },\n * DialogButtons.Confirm,\n * ],\n * });\n * ```\n */\nexport const DialogButtons = {\n /** Affirm an action — emits `'confirm'`, carries the green-tinted `circle-check` glyph. Paired with {@link Cancel} for action prompts. */\n Confirm: { text: 'Confirm', result: 'confirm', glyph: 'circle-check', tint: 'var(--ts-ui-dialog-confirm-color)' },\n /** Acknowledge information — emits `'confirm'`, carries the green-tinted `circle-check` glyph. Stands alone on informational dialogs. */\n Ok: { text: 'Ok', result: 'confirm', glyph: 'circle-check', tint: 'var(--ts-ui-dialog-confirm-color)' },\n /** Reject an action — emits `'cancel'`, carries the red-tinted `xmark` glyph. Paired with {@link Confirm}. */\n Cancel: { text: 'Cancel', result: 'cancel', glyph: 'xmark', tint: 'var(--ts-ui-dialog-cancel-color)' },\n /** Dismiss without choosing — emits `'close'`, carries the red-tinted `xmark` glyph (same icon family as cancel; the result value disambiguates). */\n Close: { text: 'Close', result: 'close', glyph: 'xmark', tint: 'var(--ts-ui-dialog-cancel-color)' },\n} as const satisfies Record<string, DialogButtonConfig>;\n\n/** Default button set when no buttons are supplied in config. */\nconst DEFAULT_BUTTONS: DialogButtonConfig[] = [\n { ...DialogButtons.Ok, primary: true },\n];\n\n/**\n * A modal dialog component with a title bar, scrollable content area, and button row.\n *\n * Use the static `Dialog.show(config)` convenience method for one-shot confirm/cancel\n * prompts, or construct an instance and call `show()` for fine-grained control.\n *\n * @example\n * ```typescript\n * const result = await Dialog.show({\n * title : 'Confirm deletion',\n * message: 'Are you sure you want to delete this record?',\n * buttons: [\n * { text: 'Delete', result: 'confirm', primary: true },\n * { text: 'Cancel', result: 'cancel' },\n * ],\n * });\n * if (result === 'confirm') { ... }\n * ```\n *\n * @category Core\n */\nclass Dialog extends Component implements DismissableLayer {\n\n private readonly _titleBar : DialogTitleBar;\n private readonly _contentContainer: Panel;\n private readonly _buttonRow : DialogButtonRow;\n private readonly _backdrop : DialogBackdrop;\n private readonly _config : DialogConfig;\n\n private _resolvePromise : ((result: DialogResult) => void) | null = null;\n private _previousFocus : Handle | null = null;\n private _boundKeyHandler : (e: KeyboardEvent) => Event.ListenerResult;\n private _boundResizeHandler: () => void;\n\n // In-flight entrance / dismiss animations for the panel and its backdrop,\n // cancelled on teardown so their fallback timers cannot fire against\n // released element handles.\n private _panelInAnimation : Animation.CancelHandle | null = null;\n private _backdropInAnimation : Animation.CancelHandle | null = null;\n private _panelOutAnimation : Animation.CancelHandle | null = null;\n private _backdropOutAnimation: Animation.CancelHandle | null = null;\n\n // True once `hide()`'s finalize has begun. `finalize` calls `destructor()`\n // partway through and finishes the rest afterwards, so the destructor uses\n // this to tell \"reached from a completing hide\" (leave the remainder to\n // finalize) from \"reached from a bare dispose\" (run it here, because the\n // cancelled dismiss animation will never call finalize at all).\n private _finalizing: boolean = false;\n\n /**\n * Constructs a Dialog but does not display it. Call `show()` to open.\n *\n * @param config - Dialog configuration.\n */\n constructor(config: DialogConfig) {\n super();\n\n this._config = config;\n\n const dialogWidth = Math.max(MIN_DIALOG_WIDTH, config.width ?? 480);\n const buttons = config.buttons ?? DEFAULT_BUTTONS;\n const contentHeight = Math.max(MIN_CONTENT_HEIGHT, this.computeContentHeight(config));\n const dialogHeight = Math.max(\n MIN_DIALOG_HEIGHT,\n config.height ?? (TITLE_HEIGHT + contentHeight + BUTTON_HEIGHT)\n );\n\n this.setPosition(Position.FIXED);\n this.setWidth(dialogWidth);\n this.setHeight(dialogHeight);\n // z-index is stamped from LayerManager's Dialog band at open() time\n // so stacked dialogs ascend monotonically; the backdrop is set one\n // below the panel there.\n this.setBackgroundColor(\"var(--ts-ui-body-bg)\");\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setShadow(\"var(--ts-ui-dialog-shadow)\");\n this.setOverflow(\"hidden\");\n // Fixed dimensions, hidden overflow, no escaping descendants — full strict containment.\n this.setContain(\"strict\");\n\n const layout = new BorderLayout();\n layout.setComponentSpacing(0);\n this.setLayoutManager(layout);\n\n this._titleBar = new DialogTitleBar(config.title, () => this.hide('close'), config.dismissable !== false);\n this.addComponent(this._titleBar, { placement: Placement.NORTH });\n\n // An explicit severity tone wins over the tone derived from the buttons,\n // so an error/warning dialog reads as such regardless of its footer.\n if (config.severity) {\n this.applySeverityHeader(config.severity);\n } else {\n this.applyHeaderVariant(this.computeHeaderVariant(buttons));\n }\n\n // A Panel (not a bare Component) so the content area is a real scroll\n // region: `autoScroll: \"y\"` opts it into the framework's overflow\n // handling, and — because Panel does not clamp itself to its content size\n // (`clampsToContentSize` is false) — a dialog capped shorter than its\n // content (see resizeToContent) shrinks this container to the available\n // space and scrolls, instead of a bare Component flooring to its content\n // height and clipping. Vertical only: a horizontal scrollbar would cover\n // the bottom rows of body text and is rarely useful for dialog content.\n // Zero insets so content sits flush, matching the former bare container.\n this._contentContainer = new Panel({\n autoScroll: \"y\",\n layoutManager: new Fit(),\n insets: new Insets(0, 0, 0, 0),\n });\n\n if (config.contentComponent) {\n this._contentContainer.addComponent(config.contentComponent);\n } else {\n const messageText = new SelectableText(config.message ?? '');\n messageText.setWhiteSpace(\"normal\");\n messageText.setWordBreak(\"break-word\");\n messageText.setPadding(new Insets(16, 16, 16, 16));\n this._contentContainer.addComponent(messageText);\n }\n\n this.addComponent(this._contentContainer, { placement: Placement.CENTER });\n\n this._buttonRow = new DialogButtonRow(buttons, (result) => this.hide(result));\n this.addComponent(this._buttonRow, { placement: Placement.SOUTH });\n\n this._backdrop = new DialogBackdrop();\n\n this._boundKeyHandler = (e: KeyboardEvent) => this.onKeyDown(e);\n this._boundResizeHandler = () => this.onViewportResize();\n }\n\n /**\n * Picks the title-bar tint variant for this dialog by inspecting the set\n * of button results. The variant is derived from the buttons rather than\n * a config flag so callers cannot signal one intent via buttons and a\n * conflicting intent via a separate option.\n *\n * @param buttons - The resolved button configuration array.\n * @returns `'info'` for a single confirm-result button (informational\n * dialog), `'affirm'` when both confirm and cancel are present\n * (affirmative-action dialog), `'plain'` otherwise.\n */\n private computeHeaderVariant(buttons: DialogButtonConfig[]): 'info' | 'affirm' | 'plain' {\n const results = new Set(buttons.map(b => b.result ?? 'cancel'));\n\n if (results.size === 1 && results.has('confirm')) {\n return 'info';\n }\n\n if (results.has('confirm') && results.has('cancel')) {\n return 'affirm';\n }\n\n return 'plain';\n }\n\n /**\n * Applies the chosen header variant's background, title-text foreground,\n * and (for the info variant only) a leading `circle-info` glyph. The\n * close button inside the title bar is intentionally untouched — dismiss\n * affordances stay on `currentColor` per the modal-glyph-theming rule.\n *\n * @param variant - One of `'info'`, `'affirm'`, or `'plain'`.\n */\n private applyHeaderVariant(variant: 'info' | 'affirm' | 'plain'): void {\n if (variant === 'plain') {\n return;\n }\n\n const bgVar = variant === 'info' ? 'var(--ts-ui-dialog-info-bg)' : 'var(--ts-ui-dialog-affirm-bg)';\n const fgVar = variant === 'info' ? 'var(--ts-ui-dialog-info-fg)' : 'var(--ts-ui-dialog-affirm-fg)';\n\n this._titleBar.setBackgroundColor(bgVar);\n this._titleBar.getTitleText().setForegroundColor(fgVar);\n\n if (variant === 'info') {\n this._titleBar.setGlyph('circle-info');\n\n const headerGlyph = this._titleBar.getGlyph();\n\n if (headerGlyph !== null) {\n headerGlyph.setForegroundColor(fgVar);\n }\n }\n }\n\n /**\n * Tints the title bar for an explicit {@link DialogSeverity}, reusing the\n * notification severity palette and leading glyph (matching the\n * notification-detail dialog). The border colour doubles as the title-text\n * and glyph foreground, as it does for a notification.\n *\n * @param severity - The severity tone to apply.\n */\n private applySeverityHeader(severity: DialogSeverity): void {\n const bgVar = `var(--ts-ui-notification-${severity}-bg)`;\n const fgVar = `var(--ts-ui-notification-${severity}-border)`;\n\n this._titleBar.setBackgroundColor(bgVar);\n this._titleBar.getTitleText().setForegroundColor(fgVar);\n this._titleBar.setGlyph(SEVERITY_GLYPH[severity]);\n\n const headerGlyph = this._titleBar.getGlyph();\n\n if (headerGlyph !== null) {\n headerGlyph.setForegroundColor(fgVar);\n }\n }\n\n /**\n * Computes the default content area height based on config.\n *\n * @param config - Dialog configuration.\n * @returns Height in pixels for the content region.\n *\n * @remarks\n * Content whose height depends on its width — a wrapping {@link Text} only\n * knows its line count once laid out — reports a single-line height here,\n * before it has been sized. {@link resizeToContent}, scheduled after the\n * first layout in {@link open}, re-fits the dialog once the content has\n * settled at the dialog width.\n */\n private computeContentHeight(config: DialogConfig): number {\n if (config.contentComponent) {\n const ps = config.contentComponent.getPreferredSize();\n\n if (ps) {\n return ps.height;\n }\n }\n\n return 100;\n }\n\n /**\n * Displays the dialog, attaches event listeners, and returns a promise that\n * resolves when the dialog is dismissed.\n *\n * @returns A promise resolving to the [`DialogResult`](/api/overlay/type-aliases/DialogResult) of the closing action.\n */\n show(): Promise<DialogResult> {\n return new Promise((resolve) => {\n this._resolvePromise = resolve;\n this.open();\n });\n }\n\n /**\n * Re-fits the dialog's height to its content's current preferred size and\n * re-centres it. A dialog's height is otherwise fixed at construction, so a\n * form whose content grows or shrinks after `show()` (e.g. add/remove rows)\n * is stretched or clipped to the original box; call this after mutating the\n * content so the dialog tracks it.\n *\n * The new height is `TITLE_HEIGHT + content + BUTTON_HEIGHT`, floored at the\n * dialog minimum and capped so the panel keeps a margin from the top and\n * bottom viewport edges — past that cap the content area scrolls (its\n * container is already `overflow-y: auto`). No-op before `show()` (nothing to\n * re-centre) and when the height is unchanged. Width is untouched.\n *\n * @returns This dialog, for method chaining.\n */\n resizeToContent(): this {\n if (!this.getElement()) {\n return this;\n }\n\n const contentHeight = Math.max(MIN_CONTENT_HEIGHT, this.computeContentHeight(this._config));\n const target = Math.max(MIN_DIALOG_HEIGHT, TITLE_HEIGHT + contentHeight + BUTTON_HEIGHT);\n\n const vp = DOM.source.getViewportSize();\n const capped = Math.min(target, Math.max(MIN_DIALOG_HEIGHT, vp.height - DIALOG_VIEWPORT_MARGIN * 2));\n\n if (capped === this.getHeight()) {\n return this;\n }\n\n this.setHeight(capped);\n this.scheduleLayout();\n this.center();\n\n return this;\n }\n\n /**\n * Appends backdrop and dialog to the DOM, centers the panel, and captures focus.\n */\n private open(): void {\n this._previousFocus = DOM.source.getActiveElement();\n\n if (this._config.closeOnBackdrop && this._config.dismissable !== false) {\n this._backdrop.addClickListener(() => { this.hide('close'); });\n }\n\n // Join the central layer tree and stamp the panel from the Dialog\n // band; the backdrop sits one below the panel so stacked dialogs keep\n // each panel above its own backdrop.\n LayerManager.register(this);\n\n const panelZ = LayerManager.getZIndex(this);\n this.setZIndex(panelZ);\n this._backdrop.setZIndex(panelZ - 1);\n\n const backdropEl = this._backdrop.getElement(true)!;\n LayerManager.mount(backdropEl);\n\n const dialogEl = this.getElement(true)!;\n LayerManager.mount(dialogEl);\n\n // Trap wheels no inner scroller claimed so the content behind a modal\n // dialog stays inert, matching modality.\n trapWheel(this);\n\n this.scheduleLayout();\n this.center();\n this.animateIn();\n\n // The construction-time height assumed single-line content; once the\n // first layout has sized the content at the dialog width, content whose\n // height depends on width (wrapping Text) has settled, so re-fit to it.\n // A no-op for content whose height did not change (resizeToContent bails\n // when the height is unchanged), so only width-dependent content reflows.\n Component.afterNextLayout(() => this.resizeToContent());\n\n Event.addViewportListener(this, 'keydown', this._boundKeyHandler);\n Event.addViewportListener(this, 'resize', this._boundResizeHandler);\n\n // Deferred past the scheduled layout: focusing synchronously here does\n // land on the right element, but the first layout then wraps the content\n // in its frame and re-parents the subtree into it. Moving a focused\n // element out of the document blurs it — silently, with no blur event —\n // so the focus is undone a frame later and lands nowhere.\n Component.afterNextLayout(() => this.focusFirst());\n }\n\n /**\n * Fades the backdrop in and the dialog panel in from `opacity: 0` +\n * `scale(0.97)` to `opacity: 1` + `scale(1)` over 150ms. No-op when\n * `prefers-reduced-motion: reduce` is set.\n */\n private animateIn(): void {\n const el = this.getElement();\n const bdEl = this._backdrop.getElement();\n\n if (!el) {\n return;\n }\n\n this._panelInAnimation?.cancel();\n this._panelInAnimation = Animation.play(el, {\n from: { opacity: \"0\", transform: \"scale(0.97)\" },\n to: { opacity: \"1\", transform: \"scale(1)\" },\n durationMs: DIALOG_ANIM_DURATION_MS,\n properties: [\"opacity\", \"transform\"],\n });\n\n if (bdEl) {\n this._backdropInAnimation?.cancel();\n this._backdropInAnimation = Animation.play(bdEl, {\n from: { opacity: \"0\" },\n to: { opacity: \"1\" },\n durationMs: DIALOG_ANIM_DURATION_MS,\n properties: [\"opacity\"],\n });\n }\n }\n\n /**\n * Centers the dialog panel within the viewport.\n */\n private center(): void {\n const vp = DOM.source.getViewportSize();\n const x = Math.max(0, Math.round((vp.width - this.getWidth()) / 2));\n const y = Math.max(0, Math.round((vp.height - this.getHeight()) / 2));\n\n this.setX(x);\n this.setY(y);\n }\n\n /**\n * Moves initial focus into the dialog. Prefers the configured\n * `initialFocus` component, then the first focusable element in the content\n * region, so a form field — not the title-bar close button, which is first in\n * DOM order — receives focus on open. Falls back to the primary action\n * button, then to the first focusable element anywhere in the dialog.\n *\n * @remarks Must run after the dialog's first layout, which re-parents the\n * content into its frame and would blur anything focused before it.\n */\n private focusFirst(): void {\n const requested = this.requestedFocusElement();\n\n if (requested) {\n DOM.sink.focus(requested);\n\n return;\n }\n\n const contentEl = this._contentContainer.getElement();\n const inContent = contentEl ? DOM.source.querySelectorAll(contentEl, FOCUSABLE_SELECTOR) : [];\n\n if (inContent.length > 0) {\n DOM.sink.focus(inContent[0]);\n\n return;\n }\n\n const primary = this.primaryButtonElement();\n\n if (primary) {\n DOM.sink.focus(primary);\n\n return;\n }\n\n const el = this.getElement();\n const focusable = el ? DOM.source.querySelectorAll(el, FOCUSABLE_SELECTOR) : [];\n\n if (focusable.length > 0) {\n DOM.sink.focus(focusable[0]);\n }\n }\n\n /**\n * Resolves the configured `initialFocus` component to the element that\n * should take focus: the component's own root element when it is itself\n * focusable (a `TextField` renders as the `<input>`), otherwise its first\n * focusable descendant (a `Panel` wrapping a field).\n *\n * @returns The element to focus, or `null` when no `initialFocus` is\n * configured or it offers nothing focusable — both of which fall through\n * to the default order.\n */\n private requestedFocusElement(): Handle | null {\n const component = this._config.initialFocus;\n const element = component?.getElement();\n\n if (!element) {\n return null;\n }\n\n if (DOM.source.matches(element, FOCUSABLE_SELECTOR)) {\n return element;\n }\n\n return DOM.source.querySelector(element, FOCUSABLE_SELECTOR);\n }\n\n /**\n * Returns the DOM element of the primary action button, used as the initial\n * focus target when the content region has nothing focusable. Resolves by\n * position: the index of the `primary` entry in the resolved button set maps\n * to the same-indexed focusable in the button row.\n *\n * @returns The primary button element, or `null` when none is primary or the\n * row is not yet rendered.\n */\n private primaryButtonElement(): Handle | null {\n const buttons = this._config.buttons ?? DEFAULT_BUTTONS;\n const index = buttons.findIndex(b => b.primary);\n\n if (index < 0) {\n return null;\n }\n\n const rowEl = this._buttonRow.getElement();\n const focusable = rowEl ? DOM.source.querySelectorAll(rowEl, FOCUSABLE_SELECTOR) : [];\n\n return focusable[index] ?? null;\n }\n\n /**\n * Collects all currently focusable elements inside the dialog.\n *\n * @returns An array of focusable elements in DOM order.\n */\n private getFocusable(): Handle[] {\n const el = this.getElement();\n\n if (!el) {\n return [];\n }\n\n return DOM.source.querySelectorAll(el, FOCUSABLE_SELECTOR)\n .filter(el => !DOM.source.hasAttribute(el, 'disabled'));\n }\n\n /**\n * Handles document-level keydown events for Escape and Tab focus trapping.\n *\n * @param e - The keyboard event.\n * @returns A stop-and-prevent disposition when the dialog handles the key (the Tab trap, or Enter); nothing otherwise, so unhandled keys keep propagating.\n */\n private onKeyDown(e: KeyboardEvent): Event.ListenerResult {\n // Escape is owned by LayerManager's keydown handler, which closes the\n // topmost non-manual layer (this dialog when it is on top). The dialog\n // keeps only the Tab focus-trap and the Enter-confirms-the-primary\n // shortcut here.\n //\n // Both are scoped to \"I am the topmost layer\": every open Dialog gets\n // this same keydown broadcast (that's the event dispatcher's policy,\n // and other consumers rely on it — see Event.addViewportListener), so\n // a backgrounded Dialog stacked under another one must not act on a\n // key meant for whichever Dialog is actually on top. Without this, a\n // \"name this preset\" prompt opened from inside a login dialog would\n // have Enter in its field also confirm the login dialog underneath.\n if (!LayerManager.isTopmostInputLayer(this)) {\n return;\n }\n\n if (e.key === 'Enter') {\n return this.onEnter(e);\n }\n\n if (e.key === 'Tab') {\n const focusable = this.getFocusable();\n\n if (focusable.length === 0) {\n return { stop: true, prevent: true };\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (e.shiftKey) {\n if (DOM.source.getActiveElement() === first) {\n DOM.sink.focus(last);\n\n return { stop: true, prevent: true };\n }\n } else {\n if (DOM.source.getActiveElement() === last) {\n DOM.sink.focus(first);\n\n return { stop: true, prevent: true };\n }\n }\n }\n\n return;\n }\n\n /**\n * Confirms the dialog on Enter by resolving the primary button's result,\n * so a simple form submits like one without the caller wiring Enter itself.\n *\n * @remarks Deliberately inert when focus is on a `<textarea>` (Enter inserts\n * a newline) or on a `<button>` (the button activates itself on Enter, and\n * hijacking it would fire the wrong action). No-op when no button is marked\n * `primary`, so a dialog with no clear default action does not submit blind.\n *\n * @param _e - The keydown event for the Enter press.\n * @returns `{ stop: true, prevent: true }` when Enter confirms the dialog; nothing when there is nothing to confirm.\n */\n private onEnter(_e: KeyboardEvent): Event.ListenerResult {\n const active = DOM.source.getActiveElement();\n const tag = active ? DOM.source.getTagName(active).toLowerCase() : null;\n\n if (tag === 'textarea' || tag === 'button') {\n return;\n }\n\n const result = this.primaryResult();\n\n if (result === null) {\n return;\n }\n\n this.hide(result);\n\n return { stop: true, prevent: true };\n }\n\n /**\n * Returns the result of the button marked `primary` in this dialog's\n * resolved button set — the action Enter confirms — or `null` when none is\n * primary.\n *\n * @returns The primary button's [`DialogResult`](/api/overlay/type-aliases/DialogResult), or `null`.\n */\n private primaryResult(): DialogResult | null {\n const buttons = this._config.buttons ?? DEFAULT_BUTTONS;\n const primary = buttons.find(b => b.primary);\n\n return primary ? (primary.result ?? 'cancel') : null;\n }\n\n /**\n * Re-fits the dialog to the resized viewport: {@link Dialog.resizeToContent}\n * grows it back toward its content when the viewport gained room, or caps it\n * (so the content area scrolls) when the viewport shrank below the content —\n * keeping the dialog within the viewport instead of overflowing it. The\n * backdrop is resized to the new viewport and the panel re-centred (again\n * unconditionally here, since `resizeToContent` skips re-centring when the\n * height is unchanged).\n */\n private onViewportResize(): void {\n this._backdrop.resize();\n this.resizeToContent();\n this.center();\n }\n\n /**\n * Dismisses the dialog with a brief fade-and-scale animation, restores\n * focus, and resolves the promise.\n *\n * @param result - The result to resolve the promise with.\n *\n * @remarks Honours `prefers-reduced-motion: reduce` — the transition is\n * skipped when motion is reduced.\n */\n hide(result: DialogResult): this {\n Event.removeViewportListener(this, 'keydown', this._boundKeyHandler);\n Event.removeViewportListener(this, 'resize', this._boundResizeHandler);\n\n const finalize = (): void => {\n this._finalizing = true;\n\n this._backdrop.destroy();\n this.removeElement();\n this.destructor();\n\n LayerManager.unregister(this);\n untrapWheel(this);\n\n if (this._previousFocus !== null) {\n DOM.sink.focus(this._previousFocus);\n }\n\n if (this._resolvePromise) {\n this._resolvePromise(result);\n this._resolvePromise = null;\n }\n };\n\n const el = this.getElement();\n const bdEl = this._backdrop.getElement();\n\n if (!el) {\n finalize();\n return this;\n }\n\n this._panelOutAnimation?.cancel();\n this._panelOutAnimation = Animation.play(el, {\n to: { opacity: \"0\", transform: \"scale(0.97)\" },\n durationMs: DIALOG_ANIM_DURATION_MS,\n properties: [\"opacity\", \"transform\"],\n onComplete: finalize,\n });\n\n if (bdEl) {\n this._backdropOutAnimation?.cancel();\n this._backdropOutAnimation = Animation.play(bdEl, {\n to: { opacity: \"0\" },\n durationMs: DIALOG_ANIM_DURATION_MS,\n properties: [\"opacity\"],\n });\n }\n\n return this;\n }\n\n /**\n * Cancels any in-flight panel / backdrop animation, then defers to the base\n * class. Reached from `hide()`'s completion callback as well as from a\n * direct dispose: on that path the dismiss animation is already finished, so\n * cancelling it is a no-op.\n */\n protected destructor(): void {\n this._panelInAnimation?.cancel();\n this._panelInAnimation = null;\n this._backdropInAnimation?.cancel();\n this._backdropInAnimation = null;\n this._panelOutAnimation?.cancel();\n this._panelOutAnimation = null;\n this._backdropOutAnimation?.cancel();\n this._backdropOutAnimation = null;\n\n // A dispose that lands mid-dismiss cancels the animation whose\n // completion callback owns the rest of teardown, so run that work here.\n // The backdrop is a private field rather than a registered child, so the\n // base class's recursion cannot reach it and it would otherwise stay\n // mounted over the whole app; the promise `show()` handed the caller\n // would never settle. Skipped when `finalize` is already running, which\n // reaches this method partway through and completes the rest itself —\n // including resolving with the caller's real result rather than the\n // `\"close\"` stand-in used here.\n if (!this._finalizing) {\n this._backdrop.destroy();\n\n LayerManager.unregister(this);\n untrapWheel(this);\n\n if (this._resolvePromise) {\n this._resolvePromise('close');\n this._resolvePromise = null;\n }\n }\n\n super.destructor();\n }\n\n /**\n * Returns the content container component where custom content is rendered.\n *\n * @returns The content container [`Component`](/api/core/classes/Component).\n */\n getContentComponent(): Component {\n return this._contentContainer;\n }\n\n /**\n * The dialog sizes itself explicitly — its height is computed to fit its\n * content at construction and re-fit (capped to the viewport) in\n * {@link Dialog.resizeToContent} — so it must not additionally floor itself\n * to its content's min-size. If it did, a dialog whose content is taller\n * than the viewport could not shrink to the capped height, and its\n * `autoScroll` content container would never get the constrained space it\n * needs to scroll (it would clip instead). The `MIN_DIALOG_HEIGHT` floor is\n * applied explicitly wherever the height is set.\n */\n protected clampsToContentSize(): boolean {\n return false;\n }\n\n /**\n * Returns the dialog's title-bar component.\n *\n * @returns The internal title-bar instance, exposing `getTitleText()` and\n * `setGlyph()` for callers (e.g. the notification detail dialog)\n * that need to tint or decorate the header.\n *\n * @remarks\n * The `DialogTitleBar` class itself is not exported — callers reach it\n * only through this accessor and interact via its few public methods\n * (`getTitleText`, `setGlyph`, `getGlyph`).\n */\n getTitleBar(): DialogTitleBar {\n return this._titleBar;\n }\n\n // ----- DismissableLayer -----\n\n /**\n * Returns the dialog panel's root element for the central layer tree.\n *\n * @returns The dialog's element, or null when not yet rendered.\n */\n getLayerElement(): Handle | null {\n return this.getElement() ?? null;\n }\n\n /**\n * Returns the dismiss mode the document-level handlers consult. A dialog\n * is `\"modal\"`: the manager neither dismisses ancestors on an outside\n * interaction nor lets one fall through, and it owns the Escape-to-close\n * shortcut. The dialog keeps its own Tab focus-trap.\n *\n * @returns The layer dismiss mode.\n */\n getDismissMode(): LayerDismissMode {\n return \"modal\";\n }\n\n /**\n * Advisory close request from the manager — closes the dialog with the\n * `'close'` result, matching the title-bar close affordance.\n *\n * @remarks No-op when `dismissable` is `false`: this is the Escape path\n * (`LayerManager` routes Escape to the topmost non-`\"manual\"` layer's\n * `requestClose()`), so a mandatory modal swallows Escape rather than\n * closing. `getDismissMode()` deliberately stays `\"modal\"` here — a\n * `\"manual\"` layer would be skipped by the Escape loop, letting Escape\n * fall through to close a layer beneath this one.\n */\n requestClose(): void {\n if (this._config.dismissable === false) {\n return;\n }\n\n this.hide('close');\n }\n\n /**\n * Returns the dialog's z-index band so unrelated dialogs stack above\n * every other overlay family.\n *\n * @returns The dialog band base.\n */\n getBand(): number {\n return LayerManager.Band.Dialog;\n }\n\n /**\n * Displays a modal dialog and returns a promise that resolves on dismissal.\n *\n * @param config - Dialog configuration.\n * @returns A promise resolving to the [`DialogResult`](/api/overlay/type-aliases/DialogResult) of the closing action.\n *\n * @example\n * ```typescript\n * const result = await Dialog.show({ title: 'Confirm', message: 'Proceed?' });\n * ```\n */\n static show(config: DialogConfig): Promise<DialogResult> {\n const dialog = new Dialog(config);\n\n return dialog.show();\n }\n\n /**\n * Displays a confirm/cancel dialog and resolves to `true` when the user confirms.\n *\n * Buttons are ordered Cancel (default focus) then Confirm, so pressing Enter or\n * Escape both safely default to cancellation.\n *\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n * @returns A promise resolving to `true` if the user clicked Confirm, `false` otherwise.\n *\n * @example\n * ```typescript\n * if (await Dialog.confirm('Delete record', 'This cannot be undone.')) {\n * store.remove(record);\n * }\n * ```\n */\n static async confirm(title: string, message: string): Promise<boolean> {\n const result = await Dialog.show({\n title,\n message,\n buttons: [\n { ...DialogButtons.Cancel, primary: true },\n DialogButtons.Confirm,\n ],\n });\n\n return result === 'confirm';\n }\n\n /**\n * Displays a severity-toned dialog with a single OK button and resolves once\n * the user acknowledges it. Shared by the {@link Dialog.info} /\n * {@link Dialog.success} / {@link Dialog.warning} / {@link Dialog.error}\n * shorthands.\n *\n * @param severity - The title-bar severity tone (see {@link DialogConfig.severity}).\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n */\n private static async alert(severity: DialogSeverity, title: string, message: string): Promise<void> {\n await Dialog.show({\n title,\n message,\n severity,\n buttons: [{ ...DialogButtons.Ok, primary: true }],\n });\n }\n\n /**\n * Displays an info-toned dialog with a single OK button and resolves once the\n * user acknowledges it.\n *\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n *\n * @example\n * ```typescript\n * await Dialog.info('Import complete', 'Loaded 1,204 rows.');\n * ```\n */\n static info(title: string, message: string): Promise<void> {\n return Dialog.alert('info', title, message);\n }\n\n /**\n * Displays a success-toned dialog with a single OK button and resolves once\n * the user acknowledges it.\n *\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n *\n * @example\n * ```typescript\n * await Dialog.success('Saved', 'Your changes have been stored.');\n * ```\n */\n static success(title: string, message: string): Promise<void> {\n return Dialog.alert('success', title, message);\n }\n\n /**\n * Displays a warning-toned dialog with a single OK button and resolves once\n * the user acknowledges it.\n *\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n *\n * @example\n * ```typescript\n * await Dialog.warning('Unsaved changes', 'They will be lost if you continue.');\n * ```\n */\n static warning(title: string, message: string): Promise<void> {\n return Dialog.alert('warning', title, message);\n }\n\n /**\n * Displays an error-toned dialog with a single OK button and resolves once\n * the user acknowledges it. The title bar carries the error severity tint and\n * glyph (see {@link DialogConfig.severity}).\n *\n * @param title - Text displayed in the title bar.\n * @param message - Body message shown in the content area.\n *\n * @example\n * ```typescript\n * await Dialog.error('Connection failed', 'Host not allowed.');\n * ```\n */\n static error(title: string, message: string): Promise<void> {\n return Dialog.alert('error', title, message);\n }\n}\n\nconst DialogCallable = callable(Dialog);\ntype DialogCallable = Dialog;\nexport {\n Dialog as _Dialog,\n DialogCallable as Dialog,\n DialogTitleBar\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./DOM-DDhDN8lQ.js";import{t}from"./Position-DWR1nIpA.js";import{T as n,g as r,t as i,v as a}from"./Component-YrLXKJZS.js";import{a as o}from"./Tooltip-DgRHQZhL.js";import{t as s}from"./Text-CGFXPhHD.js";import{t as c}from"./Checkbox-CvAZJ4_T.js";import{i as l,r as u}from"./Menu-BCQISKiQ.js";var d=new WeakSet;function swallowUnconsumedWheel(e){if(a(e))return{prevent:!0}}function trapWheel(e){d.has(e)||(d.add(e),n.addSubtreeListener(e,`wheel`,{passive:!1,handler:swallowUnconsumedWheel}))}function untrapWheel(e){d.has(e)&&(d.delete(e),n.removeSubtreeListener(e,`wheel`,swallowUnconsumedWheel))}var f=.5,CheckboxMenuRow=class extends l{_checkbox;_iconStart=null;_checkZone=null;_onMouseOver;_onMouseOut;_onClick;constructor(e,t){super(e,t),this._checkbox=new c({label:e?.text??``,selected:e?.checked??!1,enabled:e?.enabled??!0}),this._checkbox.setPointerEvents(`none`),this.addComponent(this._checkbox),e?.enabled===!1&&(this.setPointerEvents(`none`),this.setOpacity(f)),this._onMouseOver=()=>{this.setFocused(!0)},this._onMouseOut=()=>{this.setFocused(!1)},this._onClick=()=>{this.activate()},n.addListener(this,`mouseover`,this._onMouseOver),n.addListener(this,`mouseout`,this._onMouseOut),n.addListener(this,`click`,this._onClick),this.applyListeners(e?.listeners)}isChecked(){return this._checkbox.isSelected()}setChecked(e){return this._checkbox.setSelected(e),this}isNavigable(){return!0}isEnabled(){return this._checkbox.isEnabled()}activate(){this.isEnabled()&&this.setChecked(!this.isChecked())}getContentWidth(){return Math.ceil(this._checkbox.getPreferredSize()?.width??0)+u.RIGHT_PAD}setColumns(e,t,n){this._checkZone=e,this._iconStart=t,this.scheduleLayout()}doLayout(){super.doLayout();let e=this.getContentBounds();if(!e)return this;let t=this._checkbox.getPreferredSize()??{width:0,height:0},n=this._checkZone??0,r=this._iconStart!==null&&this._iconStart-n===u.ICON_ZONE?n+4:this._iconStart??u.TEXT_INSET,i=Math.max(0,Math.floor((e.height-t.height)/2));return this._checkbox.setX(e.x+r),this._checkbox.setY(e.y+i),this._checkbox.setWidth(Math.max(0,e.width-r-u.RIGHT_PAD)),this._checkbox.setHeight(t.height),this}on(e,t){return n.addListener(this,`click`,t),this}off(e,t){return n.removeListener(this,`click`,t),this}},p=r(CheckboxMenuRow),m=o.Band.Window-1,DragFeedback=class extends i{_valid=!0;constructor(){super(),this.setPosition(t.ABSOLUTE),this.setZIndex(m),this.setPointerEvents(`none`),this.applyTintForValidity()}isValid(){return this._valid}setValid(e){this._valid!==e&&(this._valid=e,this.applyTintForValidity())}attachTo(t,n){let r=this.getElement(!0);if(n&&n!==t){this.setX(t.getX()),this.setY(t.getY()),this.setWidth(t.getWidth()),this.setHeight(t.getHeight());let i=n.getElement(!0);e.source.getParentElement(r)!==i&&e.sink.appendChild(i,r);return}this.setX(0),this.setY(0),this.setWidth(t.getWidth()),this.setHeight(t.getHeight());let i=t.getElement(!0);e.source.getParentElement(r)!==i&&e.sink.appendChild(i,r)}detach(){this.removeElement()}applyTintForValidity(){let e=this._valid?`valid`:`invalid`;this.setBackgroundColor(`var(--ts-ui-drag-feedback-${e}-bg)`),this.setBorder({border:`2px solid var(--ts-ui-drag-feedback-${e}-border)`})}},h=r(DragFeedback),g=10200,_=160,v=28,y=6,DragGhost=class extends i{_label=null;constructor(e,n,r){super(),this.setPosition(t.FIXED),this.setZIndex(g),this.setPointerEvents(`none`),this.setWidth(n??_),this.setHeight(r??v),this.setBackgroundColor(`var(--ts-ui-drag-ghost-bg)`),this.setBorder({border:`1px solid var(--ts-ui-drag-ghost-border)`}),this.setShadow(`var(--ts-ui-drag-ghost-shadow)`),this.setBorderRadius(`var(--ts-ui-border-radius, 4px)`),this.setOpacity(.85),e!==void 0&&(this._label=new s(e),this._label.setPointerEvents(`none`),this.addComponent(this._label))}moveTo(e,t){this.setX(e),this.setY(t)}show(){let t=this.getElement(!0);this.scheduleLayout(),e.sink.appendChild(e.source.getDocumentElement(),t)}hide(){this.removeElement()}doLayout(){super.doLayout();let e=this.getContentBounds();return this._label&&e&&(this._label.setX(e.x+y),this._label.setY(e.y+y),this._label.setWidth(e.width-12),this._label.setHeight(e.height-12)),this}},b=r(DragGhost),x=o.Band.Window-1,S=2,C=1,ReorderIndicator=class extends i{constructor(){super(),this.setPosition(t.ABSOLUTE),this.setZIndex(x),this.setPointerEvents(`none`),this.setHeight(S),this.setBackgroundColor(`var(--ts-ui-drag-reorder-color)`)}setInsertionY(e){this.setY(e-C)}attachTo(t){let n=t.getElement(!0),r=this.getElement(!0);this.setX(0),this.setWidth(t.getWidth()),e.source.getParentElement(r)!==n&&e.sink.appendChild(n,r)}detach(){this.removeElement()}},w=r(ReorderIndicator),T=new Map,E=1e3,D=12,O=12,k=new Map,A=new Map,j=null,M;(function(e){function makeDragSource(e,t){return k.set(e.getId(),{component:e,options:t}),e.addMouseDownSubtreeListener(onSourceMouseDown),tearDownDragSource.bind(null,e)}e.makeDragSource=makeDragSource;function makeDropTarget(e,t){return A.set(e.getId(),{component:e,options:t}),tearDownDropTarget.bind(null,e)}e.makeDropTarget=makeDropTarget;function isDragging(){return j!==null&&j.committed}e.isDragging=isDragging;function cancel(){j!==null&&endSession(!1,0,0)}e.cancel=cancel})(M||={});function resolveDragData(e){return typeof e.dragData==`function`?e.dragData():e.dragData}function tearDownDragSource(e){e.removeMouseDownSubtreeListener(onSourceMouseDown),k.delete(e.getId())}function tearDownDropTarget(e){A.delete(e.getId())}function onSourceMouseDown(t){if(j!==null||t.button!==0)return;let r=k.get(this.getId());if(!r)return;let i=r.component,a=r.options;j={source:i,sourceOptions:a,dragData:resolveDragData(a),startX:t.clientX,startY:t.clientY,committed:!1,ghost:null,feedback:null,indicator:null,currentTarget:null,previousBodyCursor:e.source.getInlineStyle(e.source.getBody(),`cursor`)},n.addViewportListener(i,`mousemove`,onMouseMove),n.addViewportListener(i,`mouseup`,onMouseUp),n.addViewportListener(i,`selectstart`,onSelectStart)}function commitSession(t){t.committed=!0;let n=t.sourceOptions.ghostFactory?t.sourceOptions.ghostFactory(t.source,t.dragData):new b;if(t.ghost=n,t.feedback=new h,t.indicator=new w,typeof n.show==`function`)n.show();else{let t=n.getElement(!0);e.sink.appendChild(e.source.getDocumentElement(),t)}t.sourceOptions.cursor&&e.sink.apply(e.source.getBody(),{style:{cursor:t.sourceOptions.cursor}})}function buildDetail(e,t,n){return{dragData:e.dragData,sourceId:e.source.getId(),clientX:t,clientY:n}}function pickDropTarget(t,n){let r=e.source.elementsFromPoint(t,n);for(let t of r){let n=A.get(e.source.getId(t));if(n)return n}return null}function leaveCurrentTarget(e,t){if(e.currentTarget===null)return;let n=A.get(e.currentTarget.getId());n&&n.options.onDragLeave&&n.options.onDragLeave(t),e.feedback&&e.feedback.detach(),e.indicator&&e.indicator.detach(),e.currentTarget=null}function enterNewTarget(e,t,n){let r=t.options.accepts(n);if(e.feedback&&!t.options.suppressValidityTint&&(e.feedback.setValid(r),e.feedback.attachTo(t.component,t.options.feedbackHost)),!r){e.currentTarget=t.component;return}let i=t.options.onDragOver?.(n);typeof i==`number`&&e.indicator?(e.indicator.attachTo(t.component),e.indicator.setInsertionY(i)):e.indicator&&e.indicator.detach(),e.currentTarget=t.component}function onSelectStart(){return{stop:!0,prevent:!0}}function onMouseMove(e){if(j===null)return;let t=j;if(!t.committed){let r=e.clientX-t.startX,i=e.clientY-t.startY;if(r*r+i*i<16)return{stop:!0,prevent:!0};let a=buildDetail(t,e.clientX,e.clientY);if(t.sourceOptions.onDragStart?.(a)===!1)return endSession(!1,e.clientX,e.clientY),{stop:!0,prevent:!0};commitSession(t),n.fireEvent(t.source,`dragstart`,{detail:a})}if(t.ghost){let n=t.ghost;typeof n.moveTo==`function`?n.moveTo(e.clientX+D,e.clientY+O):(t.ghost.setX(e.clientX+D),t.ghost.setY(e.clientY+O))}let r=buildDetail(t,e.clientX,e.clientY),i=pickDropTarget(e.clientX,e.clientY);if(i===null)return leaveCurrentTarget(t,r),{stop:!0,prevent:!0};if(t.currentTarget!==i.component)return leaveCurrentTarget(t,r),enterNewTarget(t,i,r),{stop:!0,prevent:!0};let a=i.options.accepts(r);if(t.feedback&&!i.options.suppressValidityTint&&t.feedback.setValid(a),!a)return t.indicator&&t.indicator.detach(),{stop:!0,prevent:!0};let o=i.options.onDragOver?.(r);return typeof o==`number`&&t.indicator?(t.indicator.attachTo(i.component),t.indicator.setInsertionY(o)):t.indicator&&t.indicator.detach(),{stop:!0,prevent:!0}}function onMouseUp(e){if(j===null)return;let t=j,r=buildDetail(t,e.clientX,e.clientY),i=!1;if(t.committed&&t.currentTarget!==null){let e=A.get(t.currentTarget.getId());e&&(e.options.accepts(r)&&e.options.onDrop?.(r)!==!1&&n.fireEvent(t.source,`drop`,{detail:r}),i=!0)}return endSession(i,e.clientX,e.clientY),!0}function endSession(t,r,i){if(j===null)return;let a=j;if(n.removeViewportListener(a.source,`mousemove`,onMouseMove),n.removeViewportListener(a.source,`mouseup`,onMouseUp),n.removeViewportListener(a.source,`selectstart`,onSelectStart),a.feedback&&a.feedback.dispose(),a.indicator&&a.indicator.dispose(),a.ghost){if(a.sourceOptions.ghostFactory){let e=a.ghost;typeof e.hide==`function`?e.hide():a.ghost.removeElement()}else a.ghost.dispose()}if(a.sourceOptions.cursor&&e.sink.apply(e.source.getBody(),{style:{cursor:a.previousBodyCursor}}),a.committed){let e=buildDetail(a,r,i);n.fireEvent(a.source,`dragend`,{detail:e}),a.sourceOptions.onDragEnd?.(e,t)}j=null}export{b as a,trapWheel as c,w as i,untrapWheel as l,E as n,h as o,T as r,p as s,M as t};
2
+ //# sourceMappingURL=DragManager-D5pBaPPg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DragManager-D5pBaPPg.js","names":[],"sources":["../../src/typescript/lib/core/WheelTrap.ts","../../src/typescript/lib/component/container/CheckboxMenuRow.ts","../../src/typescript/lib/overlay/DragFeedback.ts","../../src/typescript/lib/overlay/DragGhost.ts","../../src/typescript/lib/overlay/ReorderIndicator.ts","../../src/typescript/lib/overlay/DragManager.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport type { Component } from \"~/core/Component.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { consumeWheel } from \"~/core/SmoothScroller.js\";\n\n/**\n * Components that currently have the wheel trap installed. Used purely for\n * idempotency — the listener itself ({@link swallowUnconsumedWheel}) captures\n * nothing per component, so one shared reference serves every overlay. Keyed\n * weakly, mirroring how the layer registry keys per-layer state, so a closed\n * overlay's entry is collectable without an explicit purge.\n */\nconst _trapped = new WeakSet<Component>();\n\n/**\n * Subtree `wheel` handler shared by every trapped overlay: claims the event via\n * the framework's wheel once-marker and, when the claim succeeds (no inner\n * scroller took it first), `preventDefault()`s it so the native wheel never\n * reaches a scrollable ancestor behind the overlay.\n *\n * @param e - The wheel event reaching the overlay as the outermost ancestor.\n */\nfunction swallowUnconsumedWheel(e: WheelEvent): Event.ListenerResult {\n if (consumeWheel(e)) {\n return { prevent: true };\n }\n}\n\n/**\n * Registers a non-passive subtree `wheel` listener on `component` that\n * `preventDefault()`s any wheel the event reaches it unconsumed — trapping\n * wheels an inner scroller did not claim so they cannot fall through to content\n * behind a floating overlay. Idempotent per component.\n *\n * @param component - The overlay to install the trap on. Must already be mounted,\n * since the subtree listener resolves the component's element.\n *\n * @remarks Subtree events dispatch descendant-first, so any inner scroll\n * container under the pointer claims the wheel first and the overlay's handler,\n * firing last as the outermost ancestor, sees it already consumed and does\n * nothing — inner scroll proceeds untouched. The listener is `{ passive: false }`\n * to match the only other `wheel` registration (the inner scroll pipeline) and\n * because `preventDefault()` is a no-op on a passive listener.\n */\nexport function trapWheel(component: Component): void {\n if (_trapped.has(component)) {\n return;\n }\n\n _trapped.add(component);\n Event.addSubtreeListener(component, \"wheel\", { passive: false, handler: swallowUnconsumedWheel });\n}\n\n/**\n * Removes the trap installed by {@link trapWheel}. Safe to call when none was\n * installed.\n *\n * @param component - The overlay whose trap should be removed.\n */\nexport function untrapWheel(component: Component): void {\n if (!_trapped.has(component)) {\n return;\n }\n\n _trapped.delete(component);\n Event.removeSubtreeListener(component, \"wheel\", swallowUnconsumedWheel);\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { ComponentOptions } from \"~/core/Component.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { Checkbox } from \"~/component/input/Checkbox.js\";\nimport { MenuItem } from \"~/component/container/MenuItem.js\";\nimport { MenuRow } from \"~/component/container/MenuRow.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/** Events exposed by {@link CheckboxMenuRow}. */\nexport type CheckboxMenuRowEvent = \"action\";\n\n// Dim applied to a disabled row, matching the framework's other composite\n// disabled controls (Button.setEnabled, NumberSpinner.applyEnabled).\nconst DISABLED_OPACITY = 0.5;\n\n/**\n * Construction-time options for {@link CheckboxMenuRow}.\n *\n * @category Components\n */\nexport interface CheckboxMenuRowOptions extends ComponentOptions {\n /** Row label, rendered beside the checkbox graphic. */\n text?: string;\n /** Initial checked state. Defaults to `false`. */\n checked?: boolean;\n /** Defaults to `true`. Disabled rows are dimmed and non-interactive. */\n enabled?: boolean;\n /**\n * Construction-time listener bag; `action` fires after each toggle.\n */\n listeners?: { action?: () => void };\n}\n\n/**\n * A [`Menu`](/api/overlay/classes/Menu) row hosting a real\n * [`Checkbox`](/api/component/input/classes/Checkbox), for a multi-select menu.\n *\n * Built via `{ row: () => new CheckboxMenuRow({ text, checked }) }` on a\n * `MenuItemConfig`. Toggles on a click anywhere in the row or on Enter (via\n * {@link activate}) and leaves the menu open — unlike a plain `MenuItem`,\n * activating it never closes the panel. `isNavigable()` reports `true`, so\n * the menu's roving arrow-key highlight lands on it like any other row.\n *\n * @category Components\n */\nclass CheckboxMenuRow extends MenuRow<CheckboxMenuRowOptions> {\n\n private _checkbox: Checkbox;\n // The title offset the owning Menu pushed in, or null when this row is\n // standalone — in which case doLayout falls back to MenuItem.TEXT_INSET.\n private _iconStart: number | null = null;\n // The check-column width the owning Menu pushed in, alongside _iconStart —\n // needed to tell whether _iconStart was widened for a sibling's icon (see\n // doLayout's `iconColumnReserved`).\n private _checkZone: number | null = null;\n\n private readonly _onMouseOver: () => void;\n private readonly _onMouseOut: () => void;\n private readonly _onClick: () => void;\n\n /**\n * Constructs a CheckboxMenuRow.\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?: CheckboxMenuRowOptions, subclassDefaults?: Partial<CheckboxMenuRowOptions>) {\n super(options, subclassDefaults);\n\n // `text` / `checked` are read from the raw constructor argument, not\n // `this._options`: neither field has a matching setter for\n // `applyOptions` to dispatch through (there is no live `setText`, and\n // `setChecked` below writes straight to `_checkbox`, which cannot\n // exist yet during the `super()` cascade), so `this._options` is\n // never populated for them — `_checkbox` itself is the state cache\n // for `checked` from this point on.\n this._checkbox = new Checkbox({\n label: options?.text ?? \"\",\n selected: options?.checked ?? false,\n enabled: options?.enabled ?? true,\n });\n // Pointer-inert child so a click anywhere in the row hits the row\n // element and toggles — the same arrangement MenuItem uses for its\n // five labels and SelectableListRow uses for its renderer. The row's\n // own `click` listener is exact-target, so the Checkbox's internal\n // synthetic click (fired from setSelected on its own element) cannot\n // re-enter it.\n this._checkbox.setPointerEvents(\"none\");\n this.addComponent(this._checkbox);\n\n if (options?.enabled === false) {\n // Pointer-inert, not merely guarded: a consumer's `on(\"action\", …)`\n // handler is a second click listener on this row, which no guard\n // inside `activate()` can suppress. Keeping the click off the row\n // is what makes a disabled row truly non-interactive.\n this.setPointerEvents(\"none\");\n this.setOpacity(DISABLED_OPACITY);\n }\n\n this._onMouseOver = () => {\n this.setFocused(true);\n };\n\n this._onMouseOut = () => {\n this.setFocused(false);\n };\n\n this._onClick = () => {\n this.activate();\n };\n\n Event.addListener(this, \"mouseover\", this._onMouseOver);\n Event.addListener(this, \"mouseout\", this._onMouseOut);\n Event.addListener(this, \"click\", this._onClick);\n\n this.applyListeners(options?.listeners);\n }\n\n /**\n * Returns the row's current checked state.\n *\n * @returns Whether the checkbox is currently checked.\n */\n isChecked(): boolean {\n return this._checkbox.isSelected();\n }\n\n /**\n * Sets the checked state.\n *\n * @param value - `true` to check, `false` to uncheck.\n * @returns This row, for method chaining.\n */\n setChecked(value: boolean): this {\n this._checkbox.setSelected(value);\n\n return this;\n }\n\n /**\n * Returns `true` — a `CheckboxMenuRow` behaves like a menu item, so the\n * menu's roving highlight lands on it and Enter activates it.\n *\n * @returns `true`.\n */\n isNavigable(): boolean {\n return true;\n }\n\n /**\n * Overrides {@link MenuRow.isEnabled}, reading the inner `Checkbox`'s\n * own enabled state — the cache for this row's `enabled` option, just as\n * it already is for `checked`.\n *\n * @returns Whether this row is interactive.\n */\n isEnabled(): boolean {\n return this._checkbox.isEnabled();\n }\n\n /**\n * Flips the checkbox. Called by a click on the row or by\n * `Menu.activateFocused()` on Enter. A no-op when the row is disabled.\n */\n activate(): void {\n if (!this.isEnabled()) {\n return;\n }\n\n this.setChecked(!this.isChecked());\n }\n\n /**\n * Returns the row's own content width — the checkbox's natural width\n * plus right padding, excluding any left inset of its own (`Menu` adds\n * the shared `iconStart` uniformly; see {@link MenuRow.getContentWidth}).\n * Read by `Menu.layOutColumns` **before** {@link setColumns} runs, so\n * this must never depend on the injected `iconStart` value itself.\n *\n * @returns The row's preferred content width in pixels.\n */\n getContentWidth(): number {\n const width = Math.ceil(this._checkbox.getPreferredSize()?.width ?? 0);\n\n return width + MenuItem.RIGHT_PAD;\n }\n\n /**\n * Stores the menu-computed left offset so the checkbox lines up with the\n * `MenuItem`s around it. `titleColumn` is unused — this row has no shared\n * title column of its own.\n *\n * @param checkZone - Width reserved for the menu's leading checkmark column.\n * @param iconStart - The left offset (in pixels) to align the checkbox to.\n * @param _titleColumn - Unused.\n */\n setColumns(checkZone: number, iconStart: number, _titleColumn: number): void {\n this._checkZone = checkZone;\n this._iconStart = iconStart;\n this.scheduleLayout();\n }\n\n /**\n * Positions the checkbox within the row's content box, vertically\n * centred, at the injected `iconStart` (or `MenuItem.TEXT_INSET` when\n * this row was never given one).\n *\n * When a sibling row reserves an icon column, `iconStart` is pushed out\n * to align with icon rows' *title text* — past their icon — which would\n * otherwise indent this row's checkbox behind an icon-sized gap of empty\n * space. Aligning with the icon's own position instead (`checkZone + 4`,\n * matching {@link MenuItem}'s icon inset) keeps the checkbox flush with\n * where a sibling's icon renders, since the checkbox plays the same\n * visual role. With no icon column, `iconStart` already collapses to\n * `checkZone + MenuItem.TEXT_INSET`, so this leaves a plain\n * checkbox-only menu's layout unchanged.\n *\n * @returns This row, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (!box) {\n return this;\n }\n\n const size = this._checkbox.getPreferredSize() ?? { width: 0, height: 0 };\n const checkZone = this._checkZone ?? 0;\n const iconColumnReserved = this._iconStart !== null && this._iconStart - checkZone === MenuItem.ICON_ZONE;\n const left = iconColumnReserved ? checkZone + 4 : (this._iconStart ?? MenuItem.TEXT_INSET);\n const top = Math.max(0, Math.floor((box.height - size.height) / 2));\n\n this._checkbox.setX(box.x + left);\n this._checkbox.setY(box.y + top);\n this._checkbox.setWidth(Math.max(0, box.width - left - MenuItem.RIGHT_PAD));\n this._checkbox.setHeight(size.height);\n\n return this;\n }\n\n /**\n * Registers a listener for this row's `\"action\"` event — fired after\n * each toggle (click or {@link activate}). A typed semantic shorthand\n * over {@link Event.addListener} (the underlying DOM event is `\"click\"`).\n *\n * @param event - The event name. Only `\"action\"` is accepted.\n * @param listener - The callback to invoke after each toggle.\n * @returns This row, for method chaining.\n */\n on(event: \"action\", listener: () => void): this;\n on(_event: \"action\", listener: () => void): this {\n Event.addListener(this, \"click\", listener);\n\n return this;\n }\n\n /**\n * Removes a previously registered `\"action\"` listener.\n *\n * @param event - The event the listener was registered for.\n * @param listener - The callback to remove.\n * @returns This row, for method chaining.\n */\n off(event: \"action\", listener: () => void): this;\n off(_event: \"action\", listener: () => void): this {\n Event.removeListener(this, \"click\", listener);\n\n return this;\n }\n}\n\nconst CheckboxMenuRowCallable = callable(CheckboxMenuRow);\ntype CheckboxMenuRowCallable = CheckboxMenuRow;\nexport {\n CheckboxMenuRow as _CheckboxMenuRow,\n CheckboxMenuRowCallable as CheckboxMenuRow\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order for the drop-target validity tint. The tint highlights a drop target,\n * which lives in ordinary app content — so it must sit **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) or it paints over a\n * floating window, while still sitting above the target's own content (app\n * z-indexes top out near 3). The app tree establishes no isolating stacking\n * context, so a higher value escapes to the root context and beats windows —\n * which is exactly the bug `Band.Window - 1` avoids. Shared rationale with\n * {@link ReorderIndicator}; the drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/**\n * A validity tint overlay drawn on top of the row currently being hovered\n * during an active drag. The colour swaps between the `valid` and\n * `invalid` theme tokens via {@link setValid}; the geometry is mirrored\n * onto a drop target via {@link attachTo}.\n *\n * Owned by [`DragManager`](/api/overlay/variables/DragManager) — application\n * code does not instantiate this directly.\n *\n * @category Core\n */\nclass DragFeedback extends Component {\n\n private _valid: boolean = true;\n\n /**\n * Constructs a drag-feedback overlay. The overlay is not attached\n * until {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n\n this.applyTintForValidity();\n }\n\n /**\n * Returns whether the overlay is currently showing the \"valid drop\"\n * tint.\n *\n * @returns `true` for the valid tint, `false` for the invalid tint.\n */\n isValid(): boolean {\n return this._valid;\n }\n\n /**\n * Switches the overlay between the `valid` and `invalid` theme\n * tokens. Idempotent — repeated calls with the same value are a\n * no-op.\n *\n * @param valid - `true` to show the valid tint, `false` for invalid.\n */\n setValid(valid: boolean): void {\n if (this._valid === valid) {\n return;\n }\n\n this._valid = valid;\n\n this.applyTintForValidity();\n }\n\n /**\n * Sizes this overlay to cover the drop target and appends it to the DOM.\n *\n * With no `host`, the tint is a child of the target, covering its body. When\n * a `host` is given, the tint instead lives in that (non-scrolling) layer,\n * sized to the target's box within it — so a target that scrolls its own\n * content (a Tab strip's clip frame) gets a tint over the *viewport* that\n * stays put instead of riding the scroll.\n *\n * @param target - The drop target whose box the tint should cover.\n * @param host - Optional non-scrolling layer to host the tint (see\n * {@link DropTargetOptions.feedbackHost}). Defaults to the target.\n */\n attachTo(target: Component, host?: Component): void {\n const myEl = this.getElement(true)!;\n\n if (host && host !== target) {\n // Overlay the target's box from within the host layer.\n this.setX(target.getX());\n this.setY(target.getY());\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const hostEl = host.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== hostEl) {\n DOM.sink.appendChild(hostEl, myEl);\n }\n\n return;\n }\n\n // Cover the target's own body as a child of it.\n this.setX(0);\n this.setY(0);\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const targetEl = target.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== targetEl) {\n DOM.sink.appendChild(targetEl, myEl);\n }\n }\n\n /**\n * Removes the overlay element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n\n /**\n * Writes the background and border CSS variables that correspond to\n * the cached validity state. Called from the constructor and from\n * {@link setValid} on transitions.\n */\n private applyTintForValidity(): void {\n const suffix = this._valid ? \"valid\" : \"invalid\";\n\n this.setBackgroundColor(`var(--ts-ui-drag-feedback-${suffix}-bg)`);\n this.setBorder({ border: `2px solid var(--ts-ui-drag-feedback-${suffix}-border)` });\n }\n}\n\nconst DragFeedbackCallable = callable(DragFeedback);\ntype DragFeedbackCallable = DragFeedback;\nexport {\n DragFeedback as _DragFeedback,\n DragFeedbackCallable as DragFeedback,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order ceiling for the drag ghost. The follow-the-cursor preview rides above\n * everything during a drag — appended at the document root, above the\n * LayerManager bands — so it is never occluded by a floating window or by the\n * per-target highlights ([`DragFeedback`](/api/overlay/classes/DragFeedback) /\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)), which deliberately\n * sit *below* the window band instead.\n */\nconst Z_INDEX = 10200;\n\n/**\n * Default ghost width when the caller omits an explicit size. Picked to\n * comfortably surround a one-line label without measuring text.\n */\nconst DEFAULT_WIDTH = 160;\n\n/** Default ghost height — one row's worth of vertical room. */\nconst DEFAULT_HEIGHT = 28;\n\n/**\n * Inner padding around the optional ghost label so text doesn't crowd the\n * border at the framework's default font size.\n */\nconst LABEL_INSET = 6;\n\n/**\n * A floating drag preview that follows the pointer during an active drag\n * session, drawn above every other overlay. Created and owned by\n * [`DragManager`](/api/overlay/variables/DragManager); application code does\n * not instantiate this directly.\n *\n * The ghost is `Position.FIXED` (one of the documented overlay carve-outs\n * in `ARCHITECTURE.md` §Positioning) and renders with\n * `pointer-events: none` so the manager's\n * `document.elementsFromPoint` hit-test always returns the row underneath.\n *\n * @category Core\n */\nclass DragGhost extends Component {\n\n private _label: Text | null = null;\n\n /**\n * Constructs a drag ghost. The caller positions it via\n * {@link moveTo} and toggles visibility through {@link show} /\n * {@link hide}.\n *\n * @param label - Optional text drawn inside the ghost.\n * @param width - Optional width in pixels (defaults to 160).\n * @param height - Optional height in pixels (defaults to 28).\n */\n constructor(label?: string, width?: number, height?: number) {\n super();\n\n this.setPosition(Position.FIXED);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setWidth(width ?? DEFAULT_WIDTH);\n this.setHeight(height ?? DEFAULT_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-ghost-bg)\");\n this.setBorder({ border: \"1px solid var(--ts-ui-drag-ghost-border)\" });\n this.setShadow(\"var(--ts-ui-drag-ghost-shadow)\");\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setOpacity(Number(\"0.85\"));\n\n if (label !== undefined) {\n this._label = new Text(label);\n this._label.setPointerEvents(\"none\");\n this.addComponent(this._label);\n }\n }\n\n /**\n * Repositions the ghost so its top-left corner sits at\n * `(clientX, clientY)`. `DragManager` calls this on every `mousemove`\n * during an active drag.\n *\n * @param clientX - The viewport X (already offset from the cursor by the manager).\n * @param clientY - The viewport Y (already offset from the cursor by the manager).\n */\n moveTo(clientX: number, clientY: number): void {\n this.setX(clientX);\n this.setY(clientY);\n }\n\n /**\n * Appends the ghost to `<html>` and schedules a layout pass. Used by\n * `DragManager` when a drag commits past the movement threshold.\n */\n show(): void {\n const el = this.getElement(true)!;\n\n this.scheduleLayout();\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n /**\n * Removes the ghost element from the DOM. Used by `DragManager` on\n * mouseup / cancel.\n */\n hide(): void {\n this.removeElement();\n }\n\n /**\n * Lays out the optional label inside the ghost's content box.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (this._label && box) {\n this._label.setX(box.x + LABEL_INSET);\n this._label.setY(box.y + LABEL_INSET);\n this._label.setWidth(box.width - LABEL_INSET * 2);\n this._label.setHeight(box.height - LABEL_INSET * 2);\n }\n\n return this;\n }\n}\n\nconst DragGhostCallable = callable(DragGhost);\ntype DragGhostCallable = DragGhost;\nexport {\n DragGhost as _DragGhost,\n DragGhostCallable as DragGhost,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order shared with {@link DragFeedback}: just **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) so this drop-target\n * insertion line — drawn over app content that establishes no isolating\n * stacking context — never paints over a floating window, while still sitting\n * above the target's own content. The drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/** Height of the insertion-line bar in pixels. */\nconst BAR_HEIGHT = 2;\n\n/**\n * Half the bar height — subtracted in {@link ReorderIndicator.setInsertionY}\n * so the 2 px bar is centred on the insertion line.\n */\nconst BAR_HALF = 1;\n\n/**\n * A 2 px horizontal bar drawn between rows to mark the insertion line\n * during an active drag-reorder gesture.\n *\n * Reserved for future sibling-reorder work — drop-on-directory does not\n * use this overlay. The class ships now so the public API surface and\n * theme tokens stabilise alongside\n * [`DragGhost`](/api/overlay/classes/DragGhost) and\n * [`DragFeedback`](/api/overlay/classes/DragFeedback); the row-DnD wiring\n * in [`TreeTable`](/api/component/table/classes/TreeTable) only attaches\n * the feedback tint.\n *\n * @category Core\n */\nclass ReorderIndicator extends Component {\n\n /**\n * Constructs a reorder indicator. The bar is not attached until\n * {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setHeight(BAR_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-reorder-color)\");\n }\n\n /**\n * Centres the bar on the given y-coordinate within the attached\n * target. The `- BAR_HALF` shift accounts for the 2 px bar height.\n *\n * @param y - Insertion-line y, measured from the target's top edge.\n */\n setInsertionY(y: number): void {\n this.setY(y - BAR_HALF);\n }\n\n /**\n * Mirrors the target's width onto the bar and appends the bar\n * element to the target.\n *\n * @param target - The drop target whose top-left coordinate space\n * the bar is positioned within.\n */\n attachTo(target: Component): void {\n const targetEl = target.getElement(true)!;\n const myEl = this.getElement(true)!;\n\n this.setX(0);\n this.setWidth(target.getWidth());\n\n if (DOM.source.getParentElement(myEl) === targetEl) {\n return;\n }\n\n DOM.sink.appendChild(targetEl, myEl);\n }\n\n /**\n * Removes the bar element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n}\n\nconst ReorderIndicatorCallable = callable(ReorderIndicator);\ntype ReorderIndicatorCallable = ReorderIndicator;\nexport {\n ReorderIndicator as _ReorderIndicator,\n ReorderIndicatorCallable as ReorderIndicator,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { DragFeedback } from \"~/overlay/DragFeedback.js\";\nimport { DragGhost } from \"~/overlay/DragGhost.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { ReorderIndicator } from \"~/overlay/ReorderIndicator.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Arbitrary, caller-defined payload attached to a drag source — the\n * shape is consumer-domain and the manager never inspects fields.\n *\n * @category Core\n */\nexport type DragData = Record<string, unknown>;\n\n/**\n * Payload delivered to every named drag-source / drop-target callback\n * and to every fired DOM event. Field names are stable across\n * `dragstart`, `dragover`, `dragleave`, `drop`, `dragend`.\n *\n * @category Core\n */\nexport interface DragEventDetail {\n /** The source's resolved drag data — read from the source options at session start. */\n dragData : DragData;\n /** The source component's id (`getId()`), useful for cycle / self-drop checks. */\n sourceId : string;\n /** Viewport-relative pointer X at the moment the event was raised. */\n clientX : number;\n /** Viewport-relative pointer Y at the moment the event was raised. */\n clientY : number;\n}\n\n/**\n * Drag-data payload attached to every tab-header drag — the cross-container\n * contract shared by the within-strip reorder path, tab tear-off / re-dock, the\n * Ctrl-drag window re-dock, and the downstream edge-split / dock-manager work.\n * A drop target reads it off {@link DragEventDetail}'s `dragData`. Because\n * {@link DragData} is a plain record it cannot carry a live component reference,\n * so `componentId` keys into the module-level `tabDragRegistry` to resolve the\n * dragged content.\n *\n * @category Core\n */\nexport interface TabDragData {\n /** Discriminator a drop target tests in its `accepts` predicate. */\n tabDrag: true;\n /** The source strip's stable id — distinguishes reorder-within from dock-from-elsewhere. */\n sourceTabId: string;\n /** The dragged content component's id — the key into `tabDragRegistry`. */\n componentId: string;\n /** The tab label — used for the drag ghost and the tear-off window title. */\n label: string;\n}\n\n/**\n * Resolves a {@link TabDragData} `componentId` back to the live content\n * component being dragged. Written when a header drag starts and cleared when it\n * ends, so a drop target — the same strip, another strip, or a torn-off\n * {@link DragData}-carrying window — can move the real component rather than\n * only learning its id. Shared by-import across `Tab` and `Window`; one\n * instance, so a source-side write is visible to the destination-side read.\n */\nexport const tabDragRegistry: Map<string, Component> = new Map<string, Component>();\n\n/**\n * Dwell, in milliseconds, before a tab held over a drop target spring-loads a\n * raise of that target's host window — surfacing a backgrounded float so the user\n * can aim the drop. Shared by the two dock drop surfaces so a region body\n * ([`DockRegion`](/api/layout/classes/DockRegion)) and a tab bar\n * ([`TabBar`](/api/component/container/classes/TabBar)) raise on the same cadence.\n *\n * Long enough that brushing a drag across a background window in transit does not\n * raise it, short enough that a deliberate hover surfaces the target. Set above a\n * `MenuItem` submenu's 150ms hover delay because raising a whole window is a\n * heavier, more disruptive action than opening a submenu, so it should demand a\n * clearly deliberate pause.\n */\nexport const SPRING_RAISE_DELAY_MS = 1000;\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDragSource}.\n *\n * @category Core\n */\nexport interface DragSourceOptions {\n /** Static or factory-produced payload attached to the session. */\n dragData : DragData | (() => DragData);\n /**\n * Optional veto callback fired the moment the threshold is crossed.\n * Return `false` to abort the drag before any overlay is shown.\n */\n onDragStart? : (detail: DragEventDetail) => boolean | void;\n /**\n * Optional ghost factory. The returned component is used in place of\n * the manager's default ghost (which carries no label and matches the\n * source's size). The component must be detached when returned.\n */\n ghostFactory?: (source: Component, data: DragData) => Component;\n /** CSS cursor applied to `<body>` while the drag is active. */\n cursor? : string;\n /**\n * Fired once the gesture ends, after any `onDrop`. `dropped` is `true` when\n * the release was handled by a registered drop target — whether the target\n * accepted the drop or refused it — and `false` only on a release over empty\n * space. Lets a source distinguish a release that landed on a target from a\n * fall-through to empty space (e.g. tab tear-off), the signal the `\"dragend\"`\n * DOM event alone cannot carry.\n */\n onDragEnd? : (detail: DragEventDetail, dropped: boolean) => void;\n}\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDropTarget}.\n *\n * @category Core\n */\nexport interface DropTargetOptions {\n /**\n * Validity predicate. Returns `true` when the dragged source may\n * drop on this target; the visual feedback tint mirrors the result.\n */\n accepts : (detail: DragEventDetail) => boolean;\n /**\n * Optional hover callback. Return a number to position the\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator) at the\n * given y inside the target; return `null` / `undefined` for no\n * reorder line.\n */\n onDragOver? : (detail: DragEventDetail) => number | null | void;\n /** Optional leave callback (cursor exits target's box). */\n onDragLeave? : (detail: DragEventDetail) => void;\n /** Optional drop callback — return `false` to suppress the `drop` event. */\n onDrop? : (detail: DragEventDetail) => boolean | void;\n /**\n * Suppresses the whole-target validity tint\n * ([`DragFeedback`](/api/overlay/classes/DragFeedback)) for this target. Pass it\n * when the target paints its own positional validity feedback (e.g. a\n * [`DockRegion`](/api/layout/classes/DockRegion) colours the drop *zone*\n * blue/red in `onDragOver`) so the two don't stack into a tinted frame *and*\n * a tinted zone. `accepts` still governs whether `onDragOver`/`onDrop` fire.\n */\n suppressValidityTint?: boolean;\n /**\n * Optional non-scrolling layer to host the validity tint, sized to the\n * target's box within it. Pass it when the target scrolls its own content\n * (e.g. a Tab strip's clip frame) so the tint overlays the *viewport* and\n * stays put instead of riding the scroll. Defaults to the target itself.\n */\n feedbackHost?: Component;\n}\n\ninterface DragSourceRecord {\n component: Component;\n options: DragSourceOptions;\n}\n\ninterface DropTargetRecord {\n component: Component;\n options: DropTargetOptions;\n}\n\ninterface DragSession {\n source: Component;\n sourceOptions: DragSourceOptions;\n dragData: DragData;\n startX: number;\n startY: number;\n committed: boolean;\n ghost: Component | null;\n feedback: DragFeedback | null;\n indicator: ReorderIndicator | null;\n currentTarget: Component | null;\n previousBodyCursor: string;\n}\n\n/**\n * Distance the cursor must travel between `mousedown` and `mousemove`\n * before the press-and-drag commits to a drag. The 4 px slop matches\n * the standard HIG threshold on Windows and macOS — anything shorter\n * fires a drag on plain clicks; anything longer feels unresponsive.\n */\nconst DRAG_THRESHOLD = 4;\n\n/**\n * Diagonal offsets applied to the ghost's top-left corner so the cursor\n * stays clear of the preview. Matches Finder / VS Code placement.\n */\nconst GHOST_OFFSET_X = 12;\nconst GHOST_OFFSET_Y = 12;\n\nconst dragSources = new Map<string, DragSourceRecord>();\nconst dropTargets = new Map<string, DropTargetRecord>();\nlet activeSession: DragSession | null = null;\n\n/**\n * Process-wide drag-and-drop coordinator. Maintains the global source /\n * target registry, owns the single active drag session, and\n * positions the three overlay components\n * ([`DragGhost`](/api/overlay/classes/DragGhost),\n * [`DragFeedback`](/api/overlay/classes/DragFeedback),\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)) above the\n * page during a drag.\n *\n * Consumers register through the two factory functions and receive a\n * teardown closure to unwire when the source / target component goes\n * away. The manager itself fires no events directly — every callback\n * lives on the option bag the caller passed to the factory.\n *\n * @example\n * ```typescript\n * const tearDownSrc = DragManager.makeDragSource(row, {\n * dragData: () => ({ recordId: row.getRecord()?.get('id') }),\n * });\n * const tearDownTgt = DragManager.makeDropTarget(folder, {\n * accepts: (d) => d.dragData.recordId !== folder.getRecord()?.get('id'),\n * onDrop: (d) => moveRecord(d.dragData.recordId, folder),\n * });\n * ```\n *\n * @category Core\n */\nexport namespace DragManager {\n\n /**\n * Registers a component as a drag source. The component's mousedown\n * event begins a pending drag session that commits once the cursor\n * travels past the 4 px movement threshold.\n *\n * @param component - The source component.\n * @param options - Drag source configuration.\n *\n * @returns A teardown function that removes the source registration\n * and the mousedown listener.\n */\n export function makeDragSource(component: Component, options: DragSourceOptions): () => void {\n dragSources.set(component.getId(), { component, options });\n component.addMouseDownSubtreeListener(onSourceMouseDown);\n\n return tearDownDragSource.bind(null, component);\n }\n\n /**\n * Registers a component as a drop target. The component is queried\n * for `accepts` during every `mousemove` while a drag is active and\n * receives the configured callbacks at the appropriate phases.\n *\n * @param component - The drop target.\n * @param options - Drop target configuration.\n *\n * @returns A teardown function that removes the target registration.\n */\n export function makeDropTarget(component: Component, options: DropTargetOptions): () => void {\n dropTargets.set(component.getId(), { component, options });\n\n return tearDownDropTarget.bind(null, component);\n }\n\n /**\n * Returns whether a drag is currently in progress (committed past\n * the 4 px movement threshold).\n *\n * @returns `true` while the ghost is visible; `false` otherwise.\n */\n export function isDragging(): boolean {\n return activeSession !== null && activeSession.committed;\n }\n\n /**\n * Aborts an in-flight drag. Mirrors a `mouseup` outside any drop\n * target — no drop callback fires; the session tears down.\n */\n export function cancel(): void {\n if (activeSession === null) {\n return;\n }\n\n endSession(false, 0, 0);\n }\n}\n\n/**\n * Resolves the source's drag-data payload — accepts either a literal or\n * a factory function on every drag start so callers can carry per-row\n * state without re-registering the source.\n */\nfunction resolveDragData(options: DragSourceOptions): DragData {\n return typeof options.dragData === \"function\" ? options.dragData() : options.dragData;\n}\n\n/**\n * Removes the per-component mousedown listener and drops the source\n * record. Bound to `(component)` by `makeDragSource` so the returned\n * teardown closure stays a stable named-function reference.\n */\nfunction tearDownDragSource(component: Component): void {\n component.removeMouseDownSubtreeListener(onSourceMouseDown);\n dragSources.delete(component.getId());\n}\n\n/**\n * Drops the target record. Bound to `(component)` by\n * `makeDropTarget` so the returned teardown closure stays a stable\n * named-function reference.\n */\nfunction tearDownDropTarget(component: Component): void {\n dropTargets.delete(component.getId());\n}\n\n/**\n * Records the pending press and arms the viewport-level move / up\n * listeners. Nothing visual happens until the cursor crosses the\n * threshold.\n *\n * Registered as a subtree mousedown listener on every drag source, so\n * a press on any descendant of the source bubbles up the subtree\n * walker and the framework's Event router applies `component` as\n * `this` for the matching source — the lookup that identifies which\n * source was pressed.\n */\nfunction onSourceMouseDown(this: Component, e: MouseEvent): void {\n if (activeSession !== null) {\n return;\n }\n\n if (e.button !== 0) {\n return;\n }\n\n const record = dragSources.get(this.getId());\n\n if (!record) {\n return;\n }\n\n const source = record.component;\n const options = record.options;\n\n activeSession = {\n source,\n sourceOptions: options,\n dragData: resolveDragData(options),\n startX: e.clientX,\n startY: e.clientY,\n committed: false,\n ghost: null,\n feedback: null,\n indicator: null,\n currentTarget: null,\n previousBodyCursor: DOM.source.getInlineStyle(DOM.source.getBody(), \"cursor\"),\n };\n\n // Viewport listeners route through Event.baseViewportListener, which stops\n // mouseup propagation at window capture phase whenever any viewport\n // listener for the type exists. A raw document-level mouseup binding would\n // race SpinButton-class registrants that already pre-empt mouseup at\n // capture and never fire.\n Event.addViewportListener(source, \"mousemove\", onMouseMove);\n Event.addViewportListener(source, \"mouseup\", onMouseUp);\n Event.addViewportListener(source, \"selectstart\", onSelectStart);\n}\n\n/**\n * Builds the session's three overlay components and writes the page-\n * wide cursor. Called once on the first mousemove that crosses the\n * threshold.\n */\nfunction commitSession(session: DragSession): void {\n session.committed = true;\n\n const ghost = session.sourceOptions.ghostFactory\n ? session.sourceOptions.ghostFactory(session.source, session.dragData)\n : new DragGhost();\n\n session.ghost = ghost;\n session.feedback = new DragFeedback();\n session.indicator = new ReorderIndicator();\n\n if (typeof (ghost as unknown as { show?: () => void }).show === \"function\") {\n (ghost as unknown as { show: () => void }).show();\n } else {\n const el = ghost.getElement(true)!;\n\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.sourceOptions.cursor } });\n }\n}\n\n/**\n * Builds the immutable detail payload threaded through every\n * source / target callback for the current pointer position.\n */\nfunction buildDetail(session: DragSession, clientX: number, clientY: number): DragEventDetail {\n return {\n dragData: session.dragData,\n sourceId: session.source.getId(),\n clientX,\n clientY,\n };\n}\n\n/**\n * Hit-tests under the ghost (which is pointer-events-none) and returns\n * the registered drop target whose element is the first match in the\n * z-stack, or `null` when no registered target sits under the cursor.\n */\nfunction pickDropTarget(clientX: number, clientY: number): DropTargetRecord | null {\n const stack = DOM.source.elementsFromPoint(clientX, clientY);\n\n for (const el of stack) {\n const record = dropTargets.get(DOM.source.getId(el));\n\n if (record) {\n return record;\n }\n }\n\n return null;\n}\n\n/**\n * Detaches the validity tint from the previous target and fires its\n * `onDragLeave`. No-op when there is no previous target.\n */\nfunction leaveCurrentTarget(session: DragSession, detail: DragEventDetail): void {\n if (session.currentTarget === null) {\n return;\n }\n\n const prev = dropTargets.get(session.currentTarget.getId());\n\n if (prev && prev.options.onDragLeave) {\n prev.options.onDragLeave(detail);\n }\n\n if (session.feedback) {\n session.feedback.detach();\n }\n\n if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = null;\n}\n\n/**\n * Attaches the validity tint to the new target, calls `onDragOver`\n * once, and positions the reorder indicator if the callback returned a\n * y value.\n */\nfunction enterNewTarget(session: DragSession, target: DropTargetRecord, detail: DragEventDetail): void {\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n session.feedback.attachTo(target.component, target.options.feedbackHost);\n }\n\n if (!accepted) {\n session.currentTarget = target.component;\n\n return;\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = target.component;\n}\n\n/**\n * Suppresses the browser's own text-selection gesture for the duration of a\n * drag session, which would otherwise run alongside it now that table cell\n * text is selectable — the drag is mouse-driven (mousedown/mousemove), not\n * HTML5 drag-and-drop, so nothing else stops a selection from painting in\n * parallel. `preventDefault()` on `mousemove` does not by itself stop the\n * browser from extending a selection (verified live: the selection still\n * grew with every `mousemove` observably prevented), so the suppression has\n * to target `selectstart` itself. Registered and torn down alongside the\n * mousemove/mouseup viewport listeners, so it is live only while a session\n * exists — including the brief press-to-release window of a plain click\n * that never crosses the drag threshold, where losing the (invisible)\n * collapsed-caret placement a real `selectstart` would otherwise produce\n * has no observable effect on a non-editable table cell.\n *\n * @returns Always suppresses the event while installed.\n */\nfunction onSelectStart(): Event.ListenerResult {\n return { stop: true, prevent: true };\n}\n\n/**\n * Drives the active session forward each frame: commits past the\n * threshold, moves the ghost, hands target changes to the\n * enter / leave helpers, and re-runs `onDragOver` while the cursor stays\n * inside the same target.\n *\n * @returns `true` while a drag session is live, consuming the move so nothing else\n * tracks the pointer; nothing when there is no session, so the move keeps propagating.\n */\nfunction onMouseMove(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n if (!session.committed) {\n const dx = e.clientX - session.startX;\n const dy = e.clientY - session.startY;\n\n if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) {\n return { stop: true, prevent: true };\n }\n\n const startDetail = buildDetail(session, e.clientX, e.clientY);\n\n if (session.sourceOptions.onDragStart?.(startDetail) === false) {\n endSession(false, e.clientX, e.clientY);\n\n return { stop: true, prevent: true };\n }\n\n commitSession(session);\n Event.fireEvent(session.source, \"dragstart\", { detail: startDetail });\n }\n\n if (session.ghost) {\n const dragGhost = session.ghost as unknown as { moveTo?: (x: number, y: number) => void };\n\n if (typeof dragGhost.moveTo === \"function\") {\n dragGhost.moveTo(e.clientX + GHOST_OFFSET_X, e.clientY + GHOST_OFFSET_Y);\n } else {\n session.ghost.setX(e.clientX + GHOST_OFFSET_X);\n session.ghost.setY(e.clientY + GHOST_OFFSET_Y);\n }\n }\n\n const detail = buildDetail(session, e.clientX, e.clientY);\n const target = pickDropTarget(e.clientX, e.clientY);\n\n if (target === null) {\n leaveCurrentTarget(session, detail);\n\n return { stop: true, prevent: true };\n }\n\n if (session.currentTarget !== target.component) {\n leaveCurrentTarget(session, detail);\n enterNewTarget(session, target, detail);\n\n return { stop: true, prevent: true };\n }\n\n // Same target as last frame — re-check accepts so the feedback\n // tint stays accurate (the validity of a drop can change as the\n // cursor moves within the same target, e.g. crossing into a\n // descendant region the source isn't allowed to land on). Skip\n // onDragOver / reorder indicator entirely while the drop is\n // rejected.\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n }\n\n if (!accepted) {\n if (session.indicator) {\n session.indicator.detach();\n }\n\n return { stop: true, prevent: true };\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n return { stop: true, prevent: true };\n}\n\n/**\n * Commits the drop (if any) and tears down the session.\n *\n * @returns `true` when a drag session was live, consuming the release that ends it;\n * nothing when there is no session, so the release keeps propagating.\n */\nfunction onMouseUp(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n const detail = buildDetail(session, e.clientX, e.clientY);\n let dropped = false;\n\n if (session.committed && session.currentTarget !== null) {\n const target = dropTargets.get(session.currentTarget.getId());\n\n if (target) {\n // Released over a registered drop target. Dispatch the drop only\n // when the target accepts; either way the release was *handled* by a\n // target rather than falling through to empty space, so report\n // `dropped` so the source skips its empty-space fallback — e.g. a Tab\n // header snaps back instead of tearing off into a window when the\n // target refused it (a rejected self-dock is a no-op, not a detach).\n if (target.options.accepts(detail)) {\n const onDropResult = target.options.onDrop?.(detail);\n\n if (onDropResult !== false) {\n Event.fireEvent(session.source, \"drop\", { detail });\n }\n }\n\n dropped = true;\n }\n }\n\n endSession(dropped, e.clientX, e.clientY);\n\n return true;\n}\n\n/**\n * Removes overlays, unwires viewport listeners, restores the body\n * cursor, and fires `dragend` when the session committed.\n */\nfunction endSession(dropped: boolean, clientX: number, clientY: number): void {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n Event.removeViewportListener(session.source, \"mousemove\", onMouseMove);\n Event.removeViewportListener(session.source, \"mouseup\", onMouseUp);\n Event.removeViewportListener(session.source, \"selectstart\", onSelectStart);\n\n // The drag chrome is built fresh for every committed gesture in\n // `commitSession` and held only on the session record — none of it is\n // registered through `addComponent`, so `Component.destructor()`'s child\n // recursion can never reach it. Disposing, rather than only detaching,\n // is what reclaims each one's per-instance stylesheet rule before the\n // session reference is dropped; detaching alone grew the shared sheet by\n // one rule per drag, without bound.\n if (session.feedback) {\n session.feedback.dispose();\n }\n\n if (session.indicator) {\n session.indicator.dispose();\n }\n\n if (session.ghost) {\n if (session.sourceOptions.ghostFactory) {\n // A ghost from the caller's factory belongs to the caller, which\n // may hand back the same component on every gesture — so it is\n // detached, never disposed.\n const dragGhost = session.ghost as unknown as { hide?: () => void };\n\n if (typeof dragGhost.hide === \"function\") {\n dragGhost.hide();\n } else {\n session.ghost.removeElement();\n }\n } else {\n session.ghost.dispose();\n }\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.previousBodyCursor } });\n }\n\n if (session.committed) {\n const detail = buildDetail(session, clientX, clientY);\n\n Event.fireEvent(session.source, \"dragend\", { detail });\n session.sourceOptions.onDragEnd?.(detail, dropped);\n }\n\n activeSession = null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{h as e,t}from"./Component-B0ShfPVi.js";import{t as n}from"./Tooltip-CUOJOqQi.js";import{t as r}from"./Fit-BhlB-HAo.js";var FieldDecorator=class extends t{constructor(e,t){super(),this.setLayoutManager(new r),this.clearInsets(),this.setBorderRadius(`var(--ts-ui-border-radius)`);let n=e.getPreferredSize();n?this.setPreferredSize({width:n.width,height:n.height}):this.setPreferredSize({width:e.getWidth(),height:e.getHeight()}),t.removeComponent(e),t.addComponent(this),this.addComponent(e)}showError(e){return this.setOutline(`2px solid var(--ts-ui-validation-error-border)`),n.attach(this,e,{background:`var(--ts-ui-validation-error-tooltip-bg)`,color:`var(--ts-ui-validation-error-tooltip-color)`,border:`var(--ts-ui-validation-error-tooltip-border)`}),this}clearError(){return this.clearOutline(),n.detach(this),this}},i=e(FieldDecorator);export{i as t};
2
- //# sourceMappingURL=FieldDecorator-BlYMfZ9L.js.map
1
+ import{g as e,t}from"./Component-YrLXKJZS.js";import{t as n}from"./Tooltip-DgRHQZhL.js";import{t as r}from"./Fit-amTWlJM2.js";var FieldDecorator=class extends t{constructor(e,t){super(),this.setLayoutManager(new r),this.clearInsets(),this.setBorderRadius(`var(--ts-ui-border-radius)`);let n=e.getPreferredSize();n?this.setPreferredSize({width:n.width,height:n.height}):this.setPreferredSize({width:e.getWidth(),height:e.getHeight()}),t.removeComponent(e),t.addComponent(this),this.addComponent(e)}showError(e){return this.setOutline(`2px solid var(--ts-ui-validation-error-border)`),n.attach(this,e,{background:`var(--ts-ui-validation-error-tooltip-bg)`,color:`var(--ts-ui-validation-error-tooltip-color)`,border:`var(--ts-ui-validation-error-tooltip-border)`}),this}clearError(){return this.clearOutline(),n.detach(this),this}},i=e(FieldDecorator);export{i as t};
2
+ //# sourceMappingURL=FieldDecorator-37IgKHHm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldDecorator-BlYMfZ9L.js","names":[],"sources":["../../src/typescript/lib/validation/FieldDecorator.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from '~/core/Component.js';\nimport { Fit } from '~/layout/Fit.js';\nimport { Tooltip } from '~/overlay/Tooltip.js';\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * A thin wrapper component that provides error visualisation for a field component.\n *\n * On construction the decorator removes the field from its current parent and inserts\n * itself in the parent, then re-adds the field as its own child. This means the error\n * border is applied to the decorator — never to the field itself — so the field's own\n * border is left untouched and removing the validation state is a clean one-step reset.\n *\n * @remarks Due to the framework's append-only `addComponent` API the decorator is\n * placed at the end of the parent's children rather than in the field's original slot.\n * A future `addComponentAt(index, component)` enhancement could address this.\n *\n * @category Validation\n */\nclass FieldDecorator extends Component {\n\n /**\n * Creates a decorator that wraps `field` inside `parent`.\n *\n * The field is removed from `parent` and the decorator is added in its place,\n * then the field is added as a child of the decorator.\n *\n * @param field - The UI component to decorate.\n * @param parent - The current parent container of `field`.\n */\n constructor(field: Component, parent: Component) {\n super();\n\n this.setLayoutManager(new Fit());\n\n // Every Component defaults to 4px insets on all sides. Zero them out so\n // the Fit layout gives the field the decorator's full content area.\n this.clearInsets();\n\n // Inherit the theme border radius so the outline follows the field's rounded corners.\n this.setBorderRadius('var(--ts-ui-border-radius)');\n\n // Mirror the field's preferred size so the parent layout allocates the\n // same space for the decorator as it did for the field. Without this,\n // layouts that fall back to a default width (e.g. HBox defaultComponentWidth)\n // would give the decorator a different — usually smaller — allocation.\n const ps = field.getPreferredSize();\n\n if (ps) {\n this.setPreferredSize({ width: ps.width, height: ps.height });\n } else {\n this.setPreferredSize({ width: field.getWidth(), height: field.getHeight() });\n }\n\n parent.removeComponent(field);\n parent.addComponent(this);\n this.addComponent(field);\n }\n\n /**\n * Applies a red validation-error outline to this decorator and attaches an error\n * tooltip that appears on hover.\n *\n * CSS `outline` is used instead of `border` so that the decorator's content area\n * and the wrapped field's size are completely unaffected — outline renders outside\n * the box model and takes up no layout space.\n *\n * @param message - The error message to display in the tooltip.\n */\n showError(message: string): this {\n this.setOutline('2px solid var(--ts-ui-validation-error-border)');\n\n Tooltip.attach(this, message, {\n background: 'var(--ts-ui-validation-error-tooltip-bg)',\n color : 'var(--ts-ui-validation-error-tooltip-color)',\n border : 'var(--ts-ui-validation-error-tooltip-border)',\n });\n\n return this;\n }\n\n /**\n * Removes the error outline and detaches the error tooltip.\n */\n clearError(): this {\n this.clearOutline();\n Tooltip.detach(this);\n\n return this;\n }\n}\n\nconst FieldDecoratorCallable = callable(FieldDecorator);\ntype FieldDecoratorCallable = FieldDecorator;\nexport {\n FieldDecorator as _FieldDecorator,\n FieldDecoratorCallable as FieldDecorator\n};\n"],"mappings":"8HAqBA,IAAM,eAAN,cAA6B,CAAU,CAWnC,YAAY,EAAkB,EAAmB,CAC7C,MAAM,EAEN,KAAK,iBAAiB,IAAI,CAAK,EAI/B,KAAK,YAAY,EAGjB,KAAK,gBAAgB,4BAA4B,EAMjD,IAAM,EAAK,EAAM,iBAAiB,EAE9B,EACA,KAAK,iBAAiB,CAAE,MAAO,EAAG,MAAO,OAAQ,EAAG,MAAO,CAAC,EAE5D,KAAK,iBAAiB,CAAE,MAAO,EAAM,SAAS,EAAG,OAAQ,EAAM,UAAU,CAAE,CAAC,EAGhF,EAAO,gBAAgB,CAAK,EAC5B,EAAO,aAAa,IAAI,EACxB,KAAK,aAAa,CAAK,CAC3B,CAYA,UAAU,EAAuB,CAS7B,OARA,KAAK,WAAW,gDAAgD,EAEhE,EAAQ,OAAO,KAAM,EAAS,CAC1B,WAAY,2CACZ,MAAY,8CACZ,OAAY,8CAChB,CAAC,EAEM,IACX,CAKA,YAAmB,CAIf,OAHA,KAAK,aAAa,EAClB,EAAQ,OAAO,IAAI,EAEZ,IACX,CACJ,EAEM,EAAyB,EAAS,cAAc"}
1
+ {"version":3,"file":"FieldDecorator-37IgKHHm.js","names":[],"sources":["../../src/typescript/lib/validation/FieldDecorator.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from '~/core/Component.js';\nimport { Fit } from '~/layout/Fit.js';\nimport { Tooltip } from '~/overlay/Tooltip.js';\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * A thin wrapper component that provides error visualisation for a field component.\n *\n * On construction the decorator removes the field from its current parent and inserts\n * itself in the parent, then re-adds the field as its own child. This means the error\n * border is applied to the decorator — never to the field itself — so the field's own\n * border is left untouched and removing the validation state is a clean one-step reset.\n *\n * @remarks Due to the framework's append-only `addComponent` API the decorator is\n * placed at the end of the parent's children rather than in the field's original slot.\n * A future `addComponentAt(index, component)` enhancement could address this.\n *\n * @category Validation\n */\nclass FieldDecorator extends Component {\n\n /**\n * Creates a decorator that wraps `field` inside `parent`.\n *\n * The field is removed from `parent` and the decorator is added in its place,\n * then the field is added as a child of the decorator.\n *\n * @param field - The UI component to decorate.\n * @param parent - The current parent container of `field`.\n */\n constructor(field: Component, parent: Component) {\n super();\n\n this.setLayoutManager(new Fit());\n\n // Every Component defaults to 4px insets on all sides. Zero them out so\n // the Fit layout gives the field the decorator's full content area.\n this.clearInsets();\n\n // Inherit the theme border radius so the outline follows the field's rounded corners.\n this.setBorderRadius('var(--ts-ui-border-radius)');\n\n // Mirror the field's preferred size so the parent layout allocates the\n // same space for the decorator as it did for the field. Without this,\n // layouts that fall back to a default width (e.g. HBox defaultComponentWidth)\n // would give the decorator a different — usually smaller — allocation.\n const ps = field.getPreferredSize();\n\n if (ps) {\n this.setPreferredSize({ width: ps.width, height: ps.height });\n } else {\n this.setPreferredSize({ width: field.getWidth(), height: field.getHeight() });\n }\n\n parent.removeComponent(field);\n parent.addComponent(this);\n this.addComponent(field);\n }\n\n /**\n * Applies a red validation-error outline to this decorator and attaches an error\n * tooltip that appears on hover.\n *\n * CSS `outline` is used instead of `border` so that the decorator's content area\n * and the wrapped field's size are completely unaffected — outline renders outside\n * the box model and takes up no layout space.\n *\n * @param message - The error message to display in the tooltip.\n */\n showError(message: string): this {\n this.setOutline('2px solid var(--ts-ui-validation-error-border)');\n\n Tooltip.attach(this, message, {\n background: 'var(--ts-ui-validation-error-tooltip-bg)',\n color : 'var(--ts-ui-validation-error-tooltip-color)',\n border : 'var(--ts-ui-validation-error-tooltip-border)',\n });\n\n return this;\n }\n\n /**\n * Removes the error outline and detaches the error tooltip.\n */\n clearError(): this {\n this.clearOutline();\n Tooltip.detach(this);\n\n return this;\n }\n}\n\nconst FieldDecoratorCallable = callable(FieldDecorator);\ntype FieldDecoratorCallable = FieldDecorator;\nexport {\n FieldDecorator as _FieldDecorator,\n FieldDecoratorCallable as FieldDecorator\n};\n"],"mappings":"8HAqBA,IAAM,eAAN,cAA6B,CAAU,CAWnC,YAAY,EAAkB,EAAmB,CAC7C,MAAM,EAEN,KAAK,iBAAiB,IAAI,CAAK,EAI/B,KAAK,YAAY,EAGjB,KAAK,gBAAgB,4BAA4B,EAMjD,IAAM,EAAK,EAAM,iBAAiB,EAE9B,EACA,KAAK,iBAAiB,CAAE,MAAO,EAAG,MAAO,OAAQ,EAAG,MAAO,CAAC,EAE5D,KAAK,iBAAiB,CAAE,MAAO,EAAM,SAAS,EAAG,OAAQ,EAAM,UAAU,CAAE,CAAC,EAGhF,EAAO,gBAAgB,CAAK,EAC5B,EAAO,aAAa,IAAI,EACxB,KAAK,aAAa,CAAK,CAC3B,CAYA,UAAU,EAAuB,CAS7B,OARA,KAAK,WAAW,gDAAgD,EAEhE,EAAQ,OAAO,KAAM,EAAS,CAC1B,WAAY,2CACZ,MAAY,8CACZ,OAAY,8CAChB,CAAC,EAEM,IACX,CAKA,YAAmB,CAIf,OAHA,KAAK,aAAa,EAClB,EAAQ,OAAO,IAAI,EAEZ,IACX,CACJ,EAEM,EAAyB,EAAS,cAAc"}
@@ -1,2 +1,2 @@
1
- import{f as e,h as t,m as n}from"./Component-B0ShfPVi.js";var Fit=class extends e{_fill=n.BOTH;constructor(e){super(),e&&this.applyOptions(e)}applyOptions(e){super.applyOptions(e),e.fill!==void 0&&this.setFill(e.fill)}getFill(){return this._fill}setFill(e){return this._fill=e,this}getPreferredSize(){return this.computeSize(e=>e.getPreferredSize())}getMinSize(){return this.computeSize(e=>e.getMinSize())}getMaxSize(){return this.computeSize(e=>e.getMaxSize())}computeSize(e){let t=this.getContainer();if(!t)return null;let n=t.getPerimeterSize(),r=n.left+n.right,i=n.top+n.bottom,a=t.getLaidOutComponents()[0]??null;if(!a)return null;let o=e(a);return o?{width:o.width+r,height:o.height+i}:null}getComponent(){let e=this.getContainer();if(!e)return null;let t=e.getComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;return t.length==1&&(n=t[0]),n}computeTotalMinSize(){let e=this.getContainer();if(!e)return{width:0,height:0};let t=e.getLaidOutComponents()[0];return t?t.getMinSize()??{width:0,height:0}:{width:0,height:0}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getLaidOutComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;if(t.length==1&&(n=t[0]),!n)return;let r=e.getInnerSize(),i=e.getContentInsets();r&&=this.inflateForOverflow(r),this.placeComponent(n,i?i.getLeft():0,i?i.getTop():0,r?r.width:0,r?r.height:0,this._fill)}},r=t(Fit);export{r as t};
2
- //# sourceMappingURL=Fit-BhlB-HAo.js.map
1
+ import{g as e,h as t,p as n}from"./Component-YrLXKJZS.js";var Fit=class extends n{_fill=t.BOTH;constructor(e){super(),e&&this.applyOptions(e)}applyOptions(e){super.applyOptions(e),e.fill!==void 0&&this.setFill(e.fill)}getFill(){return this._fill}setFill(e){return this._fill=e,this}getPreferredSize(){return this.computeSize(e=>e.getPreferredSize())}getMinSize(){return this.computeSize(e=>e.getMinSize())}getMaxSize(){return this.computeSize(e=>e.getMaxSize())}computeSize(e){let t=this.getContainer();if(!t)return null;let n=t.getPerimeterSize(),r=n.left+n.right,i=n.top+n.bottom,a=t.getLaidOutComponents()[0]??null;if(!a)return null;let o=e(a);return o?{width:o.width+r,height:o.height+i}:null}getComponent(){let e=this.getContainer();if(!e)return null;let t=e.getComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;return t.length==1&&(n=t[0]),n}computeTotalMinSize(){let e=this.getContainer();if(!e)return{width:0,height:0};let t=e.getLaidOutComponents()[0];return t?t.getMinSize()??{width:0,height:0}:{width:0,height:0}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getLaidOutComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;if(t.length==1&&(n=t[0]),!n)return;let r=e.getInnerSize(),i=e.getContentInsets();r&&=this.inflateForOverflow(r),this.placeComponent(n,i?i.getLeft():0,i?i.getTop():0,r?r.width:0,r?r.height:0,this._fill)}},r=e(Fit);export{r as t};
2
+ //# sourceMappingURL=Fit-amTWlJM2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Fit-BhlB-HAo.js","names":[],"sources":["../../src/typescript/lib/layout/Fit.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Fit}.\n *\n * @category Layouts\n */\nexport interface FitOptions extends LayoutManagerOptions {\n fill?: FillType;\n}\n\n/**\n * A layout manager that expects exactly one child component and positions it\n * inside the container's entire inner bounds. The default fill mode is\n * `FillType.BOTH` — the child stretches to fill the bounds. Pass\n * `fill: FillType.NONE` (or call {@link Fit.setFill}) to centre the child at\n * its preferred size instead; `HORIZONTAL` / `VERTICAL` stretch on one axis\n * and centre on the other. Throws if the container holds more than one\n * component.\n *\n * @category Layouts\n */\nclass Fit extends LayoutManager {\n\n private _fill: FillType = FillType.BOTH;\n\n constructor(options?: FitOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FitOptions} bag, dispatching the fill mode after the\n * inherited LayoutManager defaults.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FitOptions): void {\n super.applyOptions(options);\n\n if (options.fill !== undefined) {\n this.setFill(options.fill);\n }\n }\n\n /**\n * Returns the fill mode applied to the single child.\n *\n * @returns The current [`FillType`](/api/layout/enumerations/FillType).\n */\n getFill(): FillType {\n return this._fill;\n }\n\n /**\n * Sets the fill mode applied to the single child.\n *\n * @param fill - `BOTH` stretches the child to fill (default), `NONE`\n * centres it at its preferred size, `HORIZONTAL` / `VERTICAL` stretch on\n * one axis and centre on the other.\n *\n * @returns This layout manager, for method chaining.\n */\n setFill(fill: FillType): this {\n this._fill = fill;\n\n return this;\n }\n\n /**\n * Returns the preferred size of the single child component plus the container perimeter.\n *\n * @returns The preferred `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getPreferredSize(): Size | null {\n return this.computeSize(component => component.getPreferredSize());\n }\n\n /**\n * Returns the minimum size of the single child component plus the container perimeter.\n *\n * @returns The minimum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMinSize(): Size | null {\n return this.computeSize(component => component.getMinSize());\n }\n\n /**\n * Returns the maximum size of the single child component plus the container perimeter.\n *\n * @returns The maximum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMaxSize(): Size | null {\n return this.computeSize(component => component.getMaxSize());\n }\n\n /**\n * Shared core of {@link getPreferredSize} / {@link getMinSize} /\n * {@link getMaxSize}: adds the displayed child's size (selected by `sizeOf`)\n * to the container perimeter.\n *\n * @param sizeOf - Selects the child's preferred, minimum, or maximum size.\n * @returns The composed `{width, height}`, or `null` if there is no\n * container, no displayed child, or the child reports no size.\n */\n private computeSize(sizeOf: (component: Component) => Size | null): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n\n const outerWidth = perimeterSize.left + perimeterSize.right;\n const outerHeight = perimeterSize.top + perimeterSize.bottom;\n\n // Size the displayed child only: a hidden sole child contributes no\n // size, so the Fit container reports none and its own parent reserves\n // nothing for it (honouring `displayed`, matching doLayout below).\n const component = container.getLaidOutComponents()[0] ?? null;\n if (!component) {\n return null;\n }\n\n const size = sizeOf(component);\n if (!size) {\n return null;\n }\n\n return {\n width: size.width + outerWidth,\n height: size.height + outerHeight\n };\n }\n\n /**\n * Returns the single child component of the container, or `undefined` if the container is empty.\n *\n * @returns The child component, or `undefined`.\n *\n * @remarks Throws if the container holds more than one component.\n */\n getComponent() {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let components = container.getComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n return component;\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry:\n * the single child's minSize. Used by `doLayout` to inflate the working\n * size when the host has opted into `setOverflowing`.\n *\n * @returns The single child's min-size; `{ width: 0, height: 0 }` when\n * the container is absent or empty.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const component = container.getLaidOutComponents()[0];\n if (!component) {\n return { width: 0, height: 0 };\n }\n\n const min = component.getMinSize();\n\n return min ?? { width: 0, height: 0 };\n }\n\n /**\n * Places the single child component inside the container's inner bounds\n * using the configured fill mode.\n *\n * @remarks Throws if the container holds more than one component. With\n * the default `FillType.BOTH` the child is sized to the full bounds;\n * with `FillType.NONE` it is placed at its preferred size and centred\n * via the inherited anchor-displacement logic in `placeComponent`.\n */\n doLayout() {\n let container = this.getContainer();\n if (!container) {\n return;\n }\n\n // Honour `displayed`: a hidden sole child contributes nothing and a\n // hidden first-of-two is skipped, so the visible child still fits.\n let components = container.getLaidOutComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n if (!component) {\n return;\n }\n\n let containerSize = container.getInnerSize();\n let containerInsets = container.getContentInsets();\n\n // Universal scroll: see HBox.doLayout for the rationale. When the\n // host has marked the corresponding axis as overflowing, grow the\n // working size past the host's inner rect to the child's minSize so\n // the host's CSS `overflow: auto` produces a scrollbar.\n if (containerSize) {\n containerSize = this.inflateForOverflow(containerSize);\n }\n\n this.placeComponent(\n component,\n containerInsets ? containerInsets.getLeft() : 0,\n containerInsets ? containerInsets.getTop() : 0,\n containerSize ? containerSize.width : 0,\n containerSize ? containerSize.height : 0,\n this._fill\n );\n }\n}\n\nconst FitCallable = callable(Fit);\ntype FitCallable = Fit;\nexport {\n Fit as _Fit,\n FitCallable as Fit\n};\n"],"mappings":"0DA4BA,IAAM,IAAN,cAAkB,CAAc,CAE5B,MAA0B,EAAS,KAEnC,YAAY,EAAsB,CAG9B,MAAM,EAEF,GACA,KAAK,aAAa,CAAO,CAEjC,CAQA,aAAuB,EAA2B,CAC9C,MAAM,aAAa,CAAO,EAEtB,EAAQ,OAAS,IAAA,IACjB,KAAK,QAAQ,EAAQ,IAAI,CAEjC,CAOA,SAAoB,CAChB,OAAO,KAAK,KAChB,CAWA,QAAQ,EAAsB,CAG1B,MAFA,MAAK,MAAQ,EAEN,IACX,CAOA,kBAAgC,CAC5B,OAAO,KAAK,YAAY,GAAa,EAAU,iBAAiB,CAAC,CACrE,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAWA,YAAoB,EAA4D,CAC5E,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAgB,EAAU,iBAAiB,EAE3C,EAAa,EAAc,KAAO,EAAc,MAChD,EAAc,EAAc,IAAM,EAAc,OAKhD,EAAY,EAAU,qBAAqB,CAAC,CAAC,IAAM,KACzD,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAO,EAAO,CAAS,EAK7B,OAJK,EAIE,CACH,MAAO,EAAK,MAAQ,EACpB,OAAQ,EAAK,OAAS,CAC1B,EANW,IAOf,CASA,cAAe,CACX,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAAO,KAGX,IAAI,EAAa,EAAU,cAAc,EAEzC,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,OAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGpB,CACX,CAUA,qBAAsC,CAClC,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,MAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EAGjC,IAAM,EAAY,EAAU,qBAAqB,CAAC,CAAC,GAOnD,OANK,EAIO,EAAU,WAEf,GAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EALzB,CAAE,MAAO,EAAG,OAAQ,CAAE,CAMrC,CAWA,UAAW,CACP,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAKJ,IAAI,EAAa,EAAU,qBAAqB,EAEhD,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,GAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGvB,CAAC,EACD,OAGJ,IAAI,EAAgB,EAAU,aAAa,EACvC,EAAkB,EAAU,iBAAiB,EAMjD,AACI,IAAgB,KAAK,mBAAmB,CAAa,EAGzD,KAAK,eACD,EACA,EAAkB,EAAgB,QAAQ,EAAI,EAC9C,EAAkB,EAAgB,OAAO,EAAI,EAC7C,EAAgB,EAAc,MAAQ,EACtC,EAAgB,EAAc,OAAS,EACvC,KAAK,KACT,CACJ,CACJ,EAEM,EAAc,EAAS,GAAG"}
1
+ {"version":3,"file":"Fit-amTWlJM2.js","names":[],"sources":["../../src/typescript/lib/layout/Fit.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Fit}.\n *\n * @category Layouts\n */\nexport interface FitOptions extends LayoutManagerOptions {\n fill?: FillType;\n}\n\n/**\n * A layout manager that expects exactly one child component and positions it\n * inside the container's entire inner bounds. The default fill mode is\n * `FillType.BOTH` — the child stretches to fill the bounds. Pass\n * `fill: FillType.NONE` (or call {@link Fit.setFill}) to centre the child at\n * its preferred size instead; `HORIZONTAL` / `VERTICAL` stretch on one axis\n * and centre on the other. Throws if the container holds more than one\n * component.\n *\n * @category Layouts\n */\nclass Fit extends LayoutManager {\n\n private _fill: FillType = FillType.BOTH;\n\n constructor(options?: FitOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FitOptions} bag, dispatching the fill mode after the\n * inherited LayoutManager defaults.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FitOptions): void {\n super.applyOptions(options);\n\n if (options.fill !== undefined) {\n this.setFill(options.fill);\n }\n }\n\n /**\n * Returns the fill mode applied to the single child.\n *\n * @returns The current [`FillType`](/api/layout/enumerations/FillType).\n */\n getFill(): FillType {\n return this._fill;\n }\n\n /**\n * Sets the fill mode applied to the single child.\n *\n * @param fill - `BOTH` stretches the child to fill (default), `NONE`\n * centres it at its preferred size, `HORIZONTAL` / `VERTICAL` stretch on\n * one axis and centre on the other.\n *\n * @returns This layout manager, for method chaining.\n */\n setFill(fill: FillType): this {\n this._fill = fill;\n\n return this;\n }\n\n /**\n * Returns the preferred size of the single child component plus the container perimeter.\n *\n * @returns The preferred `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getPreferredSize(): Size | null {\n return this.computeSize(component => component.getPreferredSize());\n }\n\n /**\n * Returns the minimum size of the single child component plus the container perimeter.\n *\n * @returns The minimum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMinSize(): Size | null {\n return this.computeSize(component => component.getMinSize());\n }\n\n /**\n * Returns the maximum size of the single child component plus the container perimeter.\n *\n * @returns The maximum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMaxSize(): Size | null {\n return this.computeSize(component => component.getMaxSize());\n }\n\n /**\n * Shared core of {@link getPreferredSize} / {@link getMinSize} /\n * {@link getMaxSize}: adds the displayed child's size (selected by `sizeOf`)\n * to the container perimeter.\n *\n * @param sizeOf - Selects the child's preferred, minimum, or maximum size.\n * @returns The composed `{width, height}`, or `null` if there is no\n * container, no displayed child, or the child reports no size.\n */\n private computeSize(sizeOf: (component: Component) => Size | null): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n\n const outerWidth = perimeterSize.left + perimeterSize.right;\n const outerHeight = perimeterSize.top + perimeterSize.bottom;\n\n // Size the displayed child only: a hidden sole child contributes no\n // size, so the Fit container reports none and its own parent reserves\n // nothing for it (honouring `displayed`, matching doLayout below).\n const component = container.getLaidOutComponents()[0] ?? null;\n if (!component) {\n return null;\n }\n\n const size = sizeOf(component);\n if (!size) {\n return null;\n }\n\n return {\n width: size.width + outerWidth,\n height: size.height + outerHeight\n };\n }\n\n /**\n * Returns the single child component of the container, or `undefined` if the container is empty.\n *\n * @returns The child component, or `undefined`.\n *\n * @remarks Throws if the container holds more than one component.\n */\n getComponent() {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let components = container.getComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n return component;\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry:\n * the single child's minSize. Used by `doLayout` to inflate the working\n * size when the host has opted into `setOverflowing`.\n *\n * @returns The single child's min-size; `{ width: 0, height: 0 }` when\n * the container is absent or empty.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const component = container.getLaidOutComponents()[0];\n if (!component) {\n return { width: 0, height: 0 };\n }\n\n const min = component.getMinSize();\n\n return min ?? { width: 0, height: 0 };\n }\n\n /**\n * Places the single child component inside the container's inner bounds\n * using the configured fill mode.\n *\n * @remarks Throws if the container holds more than one component. With\n * the default `FillType.BOTH` the child is sized to the full bounds;\n * with `FillType.NONE` it is placed at its preferred size and centred\n * via the inherited anchor-displacement logic in `placeComponent`.\n */\n doLayout() {\n let container = this.getContainer();\n if (!container) {\n return;\n }\n\n // Honour `displayed`: a hidden sole child contributes nothing and a\n // hidden first-of-two is skipped, so the visible child still fits.\n let components = container.getLaidOutComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n if (!component) {\n return;\n }\n\n let containerSize = container.getInnerSize();\n let containerInsets = container.getContentInsets();\n\n // Universal scroll: see HBox.doLayout for the rationale. When the\n // host has marked the corresponding axis as overflowing, grow the\n // working size past the host's inner rect to the child's minSize so\n // the host's CSS `overflow: auto` produces a scrollbar.\n if (containerSize) {\n containerSize = this.inflateForOverflow(containerSize);\n }\n\n this.placeComponent(\n component,\n containerInsets ? containerInsets.getLeft() : 0,\n containerInsets ? containerInsets.getTop() : 0,\n containerSize ? containerSize.width : 0,\n containerSize ? containerSize.height : 0,\n this._fill\n );\n }\n}\n\nconst FitCallable = callable(Fit);\ntype FitCallable = Fit;\nexport {\n Fit as _Fit,\n FitCallable as Fit\n};\n"],"mappings":"0DA4BA,IAAM,IAAN,cAAkB,CAAc,CAE5B,MAA0B,EAAS,KAEnC,YAAY,EAAsB,CAG9B,MAAM,EAEF,GACA,KAAK,aAAa,CAAO,CAEjC,CAQA,aAAuB,EAA2B,CAC9C,MAAM,aAAa,CAAO,EAEtB,EAAQ,OAAS,IAAA,IACjB,KAAK,QAAQ,EAAQ,IAAI,CAEjC,CAOA,SAAoB,CAChB,OAAO,KAAK,KAChB,CAWA,QAAQ,EAAsB,CAG1B,MAFA,MAAK,MAAQ,EAEN,IACX,CAOA,kBAAgC,CAC5B,OAAO,KAAK,YAAY,GAAa,EAAU,iBAAiB,CAAC,CACrE,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAWA,YAAoB,EAA4D,CAC5E,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAgB,EAAU,iBAAiB,EAE3C,EAAa,EAAc,KAAO,EAAc,MAChD,EAAc,EAAc,IAAM,EAAc,OAKhD,EAAY,EAAU,qBAAqB,CAAC,CAAC,IAAM,KACzD,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAO,EAAO,CAAS,EAK7B,OAJK,EAIE,CACH,MAAO,EAAK,MAAQ,EACpB,OAAQ,EAAK,OAAS,CAC1B,EANW,IAOf,CASA,cAAe,CACX,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAAO,KAGX,IAAI,EAAa,EAAU,cAAc,EAEzC,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,OAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGpB,CACX,CAUA,qBAAsC,CAClC,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,MAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EAGjC,IAAM,EAAY,EAAU,qBAAqB,CAAC,CAAC,GAOnD,OANK,EAIO,EAAU,WAEf,GAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EALzB,CAAE,MAAO,EAAG,OAAQ,CAAE,CAMrC,CAWA,UAAW,CACP,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAKJ,IAAI,EAAa,EAAU,qBAAqB,EAEhD,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,GAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGvB,CAAC,EACD,OAGJ,IAAI,EAAgB,EAAU,aAAa,EACvC,EAAkB,EAAU,iBAAiB,EAMjD,AACI,IAAgB,KAAK,mBAAmB,CAAa,EAGzD,KAAK,eACD,EACA,EAAkB,EAAgB,QAAQ,EAAI,EAC9C,EAAkB,EAAgB,OAAO,EAAI,EAC7C,EAAgB,EAAc,MAAQ,EACtC,EAAgB,EAAc,OAAS,EACvC,KAAK,KACT,CACJ,CACJ,EAEM,EAAc,EAAS,GAAG"}