@ixfx/components 0.13.2 → 0.13.4

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/bundle/index.d.ts +1649 -128
  2. package/bundle/index.js +1595 -44437
  3. package/bundle/rolldown-runtime-CEoa-xHZ.js +1 -0
  4. package/dist/ac-text.d.ts +2 -3
  5. package/dist/ac-text.js +0 -2
  6. package/dist/{ac-token-TCLAZeVg.d.ts → ac-token--_vCHXWw.d.ts} +2 -3
  7. package/dist/ac-token.d.ts +1 -1
  8. package/dist/ac-token.js +1 -3
  9. package/dist/button-B7mgqtxR.js +0 -2
  10. package/dist/{button-CTL45aBl.d.ts → button-BYuf72aR.d.ts} +2 -3
  11. package/dist/button.d.ts +1 -1
  12. package/dist/checkbox.d.ts +1 -2
  13. package/dist/checkbox.js +0 -2
  14. package/dist/checked-select-CglRukbP.d.ts +1 -2
  15. package/dist/checked-select-lDgAQQ7v.js +0 -2
  16. package/dist/colour-picker-BCMU7W7R.js +0 -2
  17. package/dist/colour-picker.d.ts +1 -1
  18. package/dist/crumbs.d.ts +2 -3
  19. package/dist/crumbs.js +1 -3
  20. package/dist/data-controller-DOlmqNKb.js +0 -2
  21. package/dist/data-display.d.ts +1 -2
  22. package/dist/data-display.js +0 -2
  23. package/dist/{data-grid-Ck1Qx2H1.d.ts → data-grid-BtBZt8M1.d.ts} +10 -9
  24. package/dist/data-grid-FHr7wZ_k.js +2108 -0
  25. package/dist/data-grid.d.ts +1 -1
  26. package/dist/data-grid.js +1 -1923
  27. package/dist/data-provider-35TyWclX.js +0 -2
  28. package/dist/data-provider-BAn_-oR1.d.ts +1 -2
  29. package/dist/decorate-VRK8rslU.js +0 -2
  30. package/dist/defaults-B4ePs4LB.js +0 -2
  31. package/dist/detail-list-BfYHNh6B.js +1999 -0
  32. package/dist/{detail-list-C1xzr1z7.d.ts → detail-list-u2rWnAXQ.d.ts} +13 -5
  33. package/dist/detail-list.d.ts +2 -2
  34. package/dist/detail-list.js +1 -1680
  35. package/dist/drag-ghost-DtSDvjri.js +0 -2
  36. package/dist/editable-label-rzXkjf1H.d.ts +1 -2
  37. package/dist/editable-label.js +0 -2
  38. package/dist/fallbacks-DQ_5OsmR.js +0 -2
  39. package/dist/{flat-list-Ohxqsy0g.d.ts → flat-list-DNnTQ65v.d.ts} +3 -4
  40. package/dist/flat-list.d.ts +1 -1
  41. package/dist/flat-list.js +5 -3
  42. package/dist/form-CsXJX15p.js +0 -2
  43. package/dist/form.d.ts +1 -2
  44. package/dist/{grid-list-pefLORIr.d.ts → grid-list-BLnV9oZE.d.ts} +9 -3
  45. package/dist/{grid-list-DjIl910A.js → grid-list-CkU8gHCh.js} +189 -42
  46. package/dist/grid-list.d.ts +1 -1
  47. package/dist/grid-list.js +1 -1
  48. package/dist/{grouped-item-lister-Bhyo-dkH.d.ts → grouped-item-lister-DETte0Dh.d.ts} +2 -3
  49. package/dist/grouped-item-lister.d.ts +1 -1
  50. package/dist/grouped-item-lister.js +0 -2
  51. package/dist/grouping-CUKgmkMm.d.ts +1 -2
  52. package/dist/grouping-RYPnHkrS.js +0 -2
  53. package/dist/handle-DAXs7kbJ.js +0 -2
  54. package/dist/hex-editor-Caq8vNQk.d.ts +1 -2
  55. package/dist/hex-editor-DiYpgIKs.js +0 -2
  56. package/dist/highlight-B-eQrhhb.js +0 -2
  57. package/dist/icon-1gpwtPx8.js +0 -2
  58. package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +2 -3
  59. package/dist/icons.d.ts +2 -2
  60. package/dist/icons.js +0 -2
  61. package/dist/{incr-search-D91M4Ozq.js → incr-search-JIhwB49y.js} +26 -6
  62. package/dist/incr-search.d.ts +1 -1
  63. package/dist/incr-search.js +1 -1
  64. package/dist/{index-Dq30pOnn.d.ts → index-B-hzcIP0.d.ts} +3 -4
  65. package/dist/{index-CxZ61DO1.d.ts → index-BYIRgv49.d.ts} +9 -3
  66. package/dist/index-CCC0G1nO.d.ts +324 -0
  67. package/dist/{index-garxxqgV.d.ts → index-CYndvTWH.d.ts} +2 -3
  68. package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -3
  69. package/dist/index-DV3iaUBW.d.ts +1 -2
  70. package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +2 -3
  71. package/dist/index-o-CWDt11.d.ts +1 -2
  72. package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -3
  73. package/dist/index.d.ts +21 -22
  74. package/dist/index.js +48 -29
  75. package/dist/item-appearance-BjcMyauw.js +0 -2
  76. package/dist/keyboard-B5xD7Fz-.js +0 -2
  77. package/dist/labelled-input-base-BFa4xlYV.js +0 -2
  78. package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -3
  79. package/dist/labelled-radial-input.d.ts +3 -4
  80. package/dist/labelled-radial-input.js +0 -2
  81. package/dist/labelled-range-input.d.ts +1 -1
  82. package/dist/labelled-range-input.js +0 -2
  83. package/dist/labelled-slider-input-FdCRi6st.js +0 -2
  84. package/dist/labelled-slider-input.d.ts +1 -1
  85. package/dist/led.d.ts +1 -2
  86. package/dist/led.js +0 -2
  87. package/dist/list-group-header.d.ts +2 -3
  88. package/dist/list-group-header.js +0 -2
  89. package/dist/list-item-animation-BUoEKi5s.js +0 -2
  90. package/dist/list-native-drag-controller-B9xO0XWn.js +0 -2
  91. package/dist/list-native-drag-controller-ChIi3eK5.d.ts +1 -2
  92. package/dist/list-selection-controller-BeE70lbB.js +0 -2
  93. package/dist/list-selection-types-PjKdhF-a.d.ts +1 -2
  94. package/dist/list-viewport-types-BRZsLcvp.d.ts +1 -2
  95. package/dist/menu-CwcXXeLM.js +0 -2
  96. package/dist/menu-item-BDEekBVy.js +0 -2
  97. package/dist/{menu-item-B0zqw2xp.d.ts → menu-item-bF6narIz.d.ts} +2 -3
  98. package/dist/menu.d.ts +2 -2
  99. package/dist/miller.d.ts +2 -3
  100. package/dist/miller.js +146 -102
  101. package/dist/narrowed-text.js +1 -3
  102. package/dist/notification-pill-DyZydXoZ.d.ts +1 -2
  103. package/dist/notifier.js +0 -2
  104. package/dist/pan-text-CoYmt2qd.d.ts +1 -2
  105. package/dist/pan-text-CqtvjPyK.js +0 -2
  106. package/dist/panel.d.ts +2 -3
  107. package/dist/panel.js +0 -2
  108. package/dist/polar-pad.d.ts +1 -2
  109. package/dist/polar-pad.js +0 -2
  110. package/dist/popup-D80sj2QC.js +0 -2
  111. package/dist/prominence-DlFShic3.js +0 -2
  112. package/dist/radial-input-DU6t2hYO.d.ts +1 -2
  113. package/dist/radial-input-KMVltQfe.js +0 -2
  114. package/dist/range-input.d.ts +1 -2
  115. package/dist/range-input.js +0 -2
  116. package/dist/range.d.ts +1 -2
  117. package/dist/range.js +0 -2
  118. package/dist/registry-BEtb8_wB.js +0 -2
  119. package/dist/{scroll-fade-BrNUIYnm.js → scroll-fade-Xx28D7mH.js} +11 -7
  120. package/dist/select-horiz.d.ts +1 -2
  121. package/dist/select-horiz.js +1 -3
  122. package/dist/slider-input-BxURAAmD.d.ts +1 -2
  123. package/dist/slider-input-ByHdotzp.js +0 -2
  124. package/dist/snackbar.d.ts +1 -2
  125. package/dist/snackbar.js +0 -2
  126. package/dist/snap-container.d.ts +1 -2
  127. package/dist/snap-container.js +0 -2
  128. package/dist/{split-layout-CXotkdbx.js → split-layout-Deoxy47d.js} +5 -2
  129. package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +2 -3
  130. package/dist/split-layout.d.ts +1 -1
  131. package/dist/split-layout.js +1 -1
  132. package/dist/swipe.d.ts +1 -2
  133. package/dist/swipe.js +0 -2
  134. package/dist/{tab-list-v8mKX7Fu.d.ts → tab-list-CexFFg6O.d.ts} +3 -5
  135. package/dist/tabs.d.ts +1 -1
  136. package/dist/tabs.js +23 -3
  137. package/dist/tickled-controller-D-HZymaZ.js +0 -2
  138. package/dist/tickled-controller-DodxD3eQ.d.ts +1 -2
  139. package/dist/tickled-styles-BrAHEj1q.js +0 -2
  140. package/dist/timeline-BP1Ux2EV.js +0 -2
  141. package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +2 -3
  142. package/dist/titlebar.d.ts +1 -1
  143. package/dist/titlebar.js +0 -2
  144. package/dist/tooltip-BlvBUQxx.d.ts +1 -2
  145. package/dist/tooltip-CJt3WLmN.js +0 -2
  146. package/dist/transitory-label.d.ts +1 -2
  147. package/dist/transitory-label.js +0 -2
  148. package/dist/{tree-DGveys4K.js → tree-DD8OaqsK.js} +1009 -231
  149. package/dist/tree-component-Cj8V3uar.d.ts +1 -2
  150. package/dist/tree.d.ts +4 -267
  151. package/dist/tree.js +1 -1
  152. package/dist/types-DQ7KOUIj.d.ts +1 -2
  153. package/dist/{vertical-list-CqBc-t8w.d.ts → vertical-list-m7GJtXwv.d.ts} +3 -3
  154. package/dist/vertical-list.d.ts +1 -1
  155. package/dist/vertical-list.js +114 -27
  156. package/dist/wheel-nudge-By5s_ioH.d.ts +1 -2
  157. package/dist/wheel-nudge-D5rmht3v.js +0 -2
  158. package/dist/xy-axis-CyMd_Bn1.js +0 -2
  159. package/dist/xy-axis-DQqd2yXJ.d.ts +1 -2
  160. package/dist/xy-pad.d.ts +1 -2
  161. package/dist/xy-pad.js +0 -2
  162. package/docs-user/data-grid.md +74 -4
  163. package/docs-user/detail-list.md +65 -0
  164. package/docs-user/grid-list.md +81 -4
  165. package/docs-user/index.json +2 -2
  166. package/docs-user/miller.md +59 -3
  167. package/docs-user/tree.md +63 -2
  168. package/docs-user/vertical-list.md +9 -1
  169. package/package.json +6 -1
  170. package/bundle/index.d.ts.map +0 -1
  171. package/bundle/index.js.map +0 -1
  172. package/bundle/rolldown-runtime-D7D4PA-g.js +0 -13
  173. package/dist/ac-text.d.ts.map +0 -1
  174. package/dist/ac-text.js.map +0 -1
  175. package/dist/ac-token-TCLAZeVg.d.ts.map +0 -1
  176. package/dist/ac-token.js.map +0 -1
  177. package/dist/button-B7mgqtxR.js.map +0 -1
  178. package/dist/button-CTL45aBl.d.ts.map +0 -1
  179. package/dist/checkbox.d.ts.map +0 -1
  180. package/dist/checkbox.js.map +0 -1
  181. package/dist/checked-select-CglRukbP.d.ts.map +0 -1
  182. package/dist/checked-select-lDgAQQ7v.js.map +0 -1
  183. package/dist/colour-picker-BCMU7W7R.js.map +0 -1
  184. package/dist/crumbs.d.ts.map +0 -1
  185. package/dist/crumbs.js.map +0 -1
  186. package/dist/data-controller-DOlmqNKb.js.map +0 -1
  187. package/dist/data-display.d.ts.map +0 -1
  188. package/dist/data-display.js.map +0 -1
  189. package/dist/data-grid-Ck1Qx2H1.d.ts.map +0 -1
  190. package/dist/data-grid.js.map +0 -1
  191. package/dist/data-provider-35TyWclX.js.map +0 -1
  192. package/dist/data-provider-BAn_-oR1.d.ts.map +0 -1
  193. package/dist/decorate-VRK8rslU.js.map +0 -1
  194. package/dist/defaults-B4ePs4LB.js.map +0 -1
  195. package/dist/detail-list-C1xzr1z7.d.ts.map +0 -1
  196. package/dist/detail-list.js.map +0 -1
  197. package/dist/drag-ghost-DtSDvjri.js.map +0 -1
  198. package/dist/editable-label-rzXkjf1H.d.ts.map +0 -1
  199. package/dist/editable-label.js.map +0 -1
  200. package/dist/fallbacks-DQ_5OsmR.js.map +0 -1
  201. package/dist/flat-list-Ohxqsy0g.d.ts.map +0 -1
  202. package/dist/flat-list.js.map +0 -1
  203. package/dist/form-CsXJX15p.js.map +0 -1
  204. package/dist/form.d.ts.map +0 -1
  205. package/dist/grid-list-DjIl910A.js.map +0 -1
  206. package/dist/grid-list-pefLORIr.d.ts.map +0 -1
  207. package/dist/grouped-item-lister-Bhyo-dkH.d.ts.map +0 -1
  208. package/dist/grouped-item-lister.js.map +0 -1
  209. package/dist/grouping-CUKgmkMm.d.ts.map +0 -1
  210. package/dist/grouping-RYPnHkrS.js.map +0 -1
  211. package/dist/handle-DAXs7kbJ.js.map +0 -1
  212. package/dist/hex-editor-Caq8vNQk.d.ts.map +0 -1
  213. package/dist/hex-editor-DiYpgIKs.js.map +0 -1
  214. package/dist/highlight-B-eQrhhb.js.map +0 -1
  215. package/dist/icon-1gpwtPx8.js.map +0 -1
  216. package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
  217. package/dist/icons.js.map +0 -1
  218. package/dist/incr-search-D91M4Ozq.js.map +0 -1
  219. package/dist/index-BOUaDIW-.d.ts.map +0 -1
  220. package/dist/index-BUB5SICW.d.ts.map +0 -1
  221. package/dist/index-CJ5fshD3.d.ts.map +0 -1
  222. package/dist/index-CxZ61DO1.d.ts.map +0 -1
  223. package/dist/index-DV3iaUBW.d.ts.map +0 -1
  224. package/dist/index-Dq30pOnn.d.ts.map +0 -1
  225. package/dist/index-garxxqgV.d.ts.map +0 -1
  226. package/dist/index-o-CWDt11.d.ts.map +0 -1
  227. package/dist/index.d.ts.map +0 -1
  228. package/dist/index.js.map +0 -1
  229. package/dist/item-appearance-BjcMyauw.js.map +0 -1
  230. package/dist/keyboard-B5xD7Fz-.js.map +0 -1
  231. package/dist/labelled-input-base-BFa4xlYV.js.map +0 -1
  232. package/dist/labelled-input-base-Dp_9KP0G.d.ts.map +0 -1
  233. package/dist/labelled-radial-input.d.ts.map +0 -1
  234. package/dist/labelled-radial-input.js.map +0 -1
  235. package/dist/labelled-range-input.js.map +0 -1
  236. package/dist/labelled-slider-input-FdCRi6st.js.map +0 -1
  237. package/dist/led.d.ts.map +0 -1
  238. package/dist/led.js.map +0 -1
  239. package/dist/list-group-header.d.ts.map +0 -1
  240. package/dist/list-group-header.js.map +0 -1
  241. package/dist/list-item-animation-BUoEKi5s.js.map +0 -1
  242. package/dist/list-native-drag-controller-B9xO0XWn.js.map +0 -1
  243. package/dist/list-native-drag-controller-ChIi3eK5.d.ts.map +0 -1
  244. package/dist/list-selection-controller-BeE70lbB.js.map +0 -1
  245. package/dist/list-selection-types-PjKdhF-a.d.ts.map +0 -1
  246. package/dist/list-viewport-types-BRZsLcvp.d.ts.map +0 -1
  247. package/dist/menu-CwcXXeLM.js.map +0 -1
  248. package/dist/menu-item-B0zqw2xp.d.ts.map +0 -1
  249. package/dist/menu-item-BDEekBVy.js.map +0 -1
  250. package/dist/miller.d.ts.map +0 -1
  251. package/dist/miller.js.map +0 -1
  252. package/dist/narrowed-text.js.map +0 -1
  253. package/dist/notification-pill-DyZydXoZ.d.ts.map +0 -1
  254. package/dist/notifier.js.map +0 -1
  255. package/dist/pan-text-CoYmt2qd.d.ts.map +0 -1
  256. package/dist/pan-text-CqtvjPyK.js.map +0 -1
  257. package/dist/panel.d.ts.map +0 -1
  258. package/dist/panel.js.map +0 -1
  259. package/dist/polar-pad.d.ts.map +0 -1
  260. package/dist/polar-pad.js.map +0 -1
  261. package/dist/popup-D80sj2QC.js.map +0 -1
  262. package/dist/prominence-DlFShic3.js.map +0 -1
  263. package/dist/radial-input-DU6t2hYO.d.ts.map +0 -1
  264. package/dist/radial-input-KMVltQfe.js.map +0 -1
  265. package/dist/range-input.d.ts.map +0 -1
  266. package/dist/range-input.js.map +0 -1
  267. package/dist/range.d.ts.map +0 -1
  268. package/dist/range.js.map +0 -1
  269. package/dist/registry-BEtb8_wB.js.map +0 -1
  270. package/dist/scroll-fade-BrNUIYnm.js.map +0 -1
  271. package/dist/select-horiz.d.ts.map +0 -1
  272. package/dist/select-horiz.js.map +0 -1
  273. package/dist/slider-input-BxURAAmD.d.ts.map +0 -1
  274. package/dist/slider-input-ByHdotzp.js.map +0 -1
  275. package/dist/snackbar.d.ts.map +0 -1
  276. package/dist/snackbar.js.map +0 -1
  277. package/dist/snap-container.d.ts.map +0 -1
  278. package/dist/snap-container.js.map +0 -1
  279. package/dist/split-layout-C5SYbDrq.d.ts.map +0 -1
  280. package/dist/split-layout-CXotkdbx.js.map +0 -1
  281. package/dist/swipe.d.ts.map +0 -1
  282. package/dist/swipe.js.map +0 -1
  283. package/dist/tab-list-v8mKX7Fu.d.ts.map +0 -1
  284. package/dist/tabs.js.map +0 -1
  285. package/dist/tickled-controller-D-HZymaZ.js.map +0 -1
  286. package/dist/tickled-controller-DodxD3eQ.d.ts.map +0 -1
  287. package/dist/tickled-styles-BrAHEj1q.js.map +0 -1
  288. package/dist/timeline-BP1Ux2EV.js.map +0 -1
  289. package/dist/titlebar-B5zSTZnF.d.ts.map +0 -1
  290. package/dist/titlebar.js.map +0 -1
  291. package/dist/tooltip-BlvBUQxx.d.ts.map +0 -1
  292. package/dist/tooltip-CJt3WLmN.js.map +0 -1
  293. package/dist/transitory-label.d.ts.map +0 -1
  294. package/dist/transitory-label.js.map +0 -1
  295. package/dist/tree-DGveys4K.js.map +0 -1
  296. package/dist/tree-component-Cj8V3uar.d.ts.map +0 -1
  297. package/dist/tree.d.ts.map +0 -1
  298. package/dist/types-DQ7KOUIj.d.ts.map +0 -1
  299. package/dist/vertical-list-CqBc-t8w.d.ts.map +0 -1
  300. package/dist/vertical-list.js.map +0 -1
  301. package/dist/wheel-nudge-By5s_ioH.d.ts.map +0 -1
  302. package/dist/wheel-nudge-D5rmht3v.js.map +0 -1
  303. package/dist/xy-axis-CyMd_Bn1.js.map +0 -1
  304. package/dist/xy-axis-DQqd2yXJ.d.ts.map +0 -1
  305. package/dist/xy-pad.d.ts.map +0 -1
  306. package/dist/xy-pad.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"item-appearance-BjcMyauw.js","names":[],"sources":["../src/common/item-appearance.ts"],"sourcesContent":["/**\n * Shared helpers for the list components' per-item appearance hooks — the\n * per-item icon colour / text colour / badge that miller-list, detail-list,\n * grid-list, data-grid and vertical-list all accept.\n *\n * Every component takes these three features in its own idiom (plain fields\n * on a `TreeItem`, a property-name lookup, an adapter function, a nominated\n * column) but they all agree on what \"not supplied\" means, and on never\n * emitting an empty slot for an absent value.\n */\n\n/**\n * Whether a per-item appearance value counts as \"not supplied\". `false` and\n * `''` are included so a consumer can clear a feature without rebuilding the\n * collection — e.g. `badge: flags && tagChip(flags.colour)`.\n */\nexport function appearanceAbsent(value: unknown): boolean {\n return value === undefined || value === null || value === false || value === ``;\n}\n\n/**\n * A usable CSS colour from a per-item value, or `undefined`. Non-strings and\n * empty strings are ignored rather than stringified, so a stray number or\n * `0` never lands in a `style` attribute.\n */\nexport function appearanceColor(value: unknown): string | undefined {\n return typeof value === `string` && value.length > 0 ? value : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,iBAAiB,OAAyB;CACxD,OAAO,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,SAAS,UAAU;AAC/E;;;;;;AAOA,SAAgB,gBAAgB,OAAoC;CAClE,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"keyboard-B5xD7Fz-.js","names":[],"sources":["../src/keyboard.ts"],"sourcesContent":["/**\n * Keyboard interaction constants\n */\nexport const KEY_STEP_DIVISOR = 10;\n\n/**\n * Resolve the effective keyboard nudge step for a single numeric axis.\n *\n * Priority: stops (quantised grid) > explicit step > percentage of range.\n *\n * @param range max - min for the axis\n * @param stops number of quantised divisions (undefined or ≤1 = ignored)\n * @param step explicit absolute step size (undefined = ignored)\n * @param defaultFraction fraction of range used when neither stops nor step is set (default 0.1 = 10%)\n */\nexport function resolveStep(\n range: number,\n stops: number | undefined,\n step: number | undefined,\n defaultFraction = 0.1,\n): number {\n if (stops !== undefined && stops > 1)\n return range / stops;\n if (step !== undefined)\n return step;\n return range * defaultFraction;\n}\n\n/**\n * Resolve the effective nudge step after applying the Shift-key fine divisor.\n *\n * Convenience wrapper around `resolveStep` that combines step resolution with\n * the Shift modifier. Hold Shift to nudge by 1/`KEY_STEP_DIVISOR` of the\n * resolved step.\n *\n * @param range max - min for the axis\n * @param stops number of quantised divisions (undefined or ≤1 = ignored)\n * @param step explicit absolute step size (undefined = ignored)\n * @param shiftKey whether the Shift modifier is held\n * @param defaultFraction fraction of range used when neither stops nor step is set (default 0.1 = 10%)\n */\nexport function resolveAxisStep(\n range: number,\n stops: number | undefined,\n step: number | undefined,\n shiftKey: boolean,\n defaultFraction = 0.1,\n): number {\n const divisor = shiftKey ? KEY_STEP_DIVISOR : 1;\n return resolveStep(range, stops, step, defaultFraction) / divisor;\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,YACd,OACA,OACA,MACA,kBAAkB,IACV;CACR,IAAI,UAAU,KAAA,KAAa,QAAQ,GACjC,OAAO,QAAQ;CACjB,IAAI,SAAS,KAAA,GACX,OAAO;CACT,OAAO,QAAQ;AACjB;;;;;;;;;;;;;;AAeA,SAAgB,gBACd,OACA,OACA,MACA,UACA,kBAAkB,IACV;CACR,MAAM,UAAU,WAAA,KAA8B;CAC9C,OAAO,YAAY,OAAO,OAAO,MAAM,eAAe,IAAI;AAC5D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-input-base-BFa4xlYV.js","names":[],"sources":["../src/mixins/labelled-input-util.ts","../src/mixins/labelled-input-base.ts"],"sourcesContent":["export function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nexport function applyValue(\n el: Element | null,\n value: number,\n): void {\n if (el == null) {\n return;\n }\n (el as any).value = value;\n}\n","import { html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { applyValue } from './labelled-input-util.js';\n\nexport abstract class LabelledInputBase extends LitElement {\n @property() label = ``;\n\n @property({ type: Number }) min = 0;\n @property({ type: Number }) max = 1;\n @property({ type: Number }) value = 0;\n @property({ type: Number }) step = 0.01;\n @property({ type: Number }) precision = 0;\n @property({ type: Number, attribute: `drag-sensitivity` }) dragSensitivity = 1;\n\n @property({ type: Number, attribute: `mini-width-threshold` }) miniWidthThreshold = 120;\n @property({ type: Number, attribute: `mini-height-threshold` }) miniHeightThreshold = 45;\n\n @property({ attribute: `display-text-logic` }) displayTextLogic: `hidden` | `show` | `override` | `transient` = `transient`;\n\n @state() protected _isMini = false;\n @state() protected _isDragging = false;\n @state() protected _formatter?: (value: string) => string;\n\n private _debounceTimer: number | undefined = undefined;\n private _resizeObserver?: ResizeObserver;\n\n abstract readonly inputSelector: string;\n\n get formatter(): (value: string) => string {\n return this._formatter ?? ((v: string) => v);\n }\n\n set formatter(value: ((value: string) => string) | undefined) {\n this._formatter = value;\n }\n\n protected get hasCustomFormatter(): boolean {\n return this._formatter !== undefined;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._resizeObserver = new ResizeObserver(entries => this._handleResize(entries));\n this._resizeObserver.observe(this);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._resizeObserver = undefined;\n }\n\n protected _handleResize(entries: ResizeObserverEntry[]): void {\n const { width, height } = entries[0].contentRect;\n const miniOverride = getComputedStyle(this).getPropertyValue(`--mini`).trim();\n if (miniOverride === `1`) {\n this._isMini = true;\n return;\n }\n if (miniOverride === `0`) {\n this._isMini = false;\n return;\n }\n this._isMini = width < this.miniWidthThreshold || height < this.miniHeightThreshold;\n }\n\n protected _handleNumberChange = (e: CustomEvent<{ value: string }>): void => {\n const valueStr = e.detail?.value ?? String(this.value);\n const newValue = Number.parseFloat(valueStr);\n this.value = newValue;\n this._syncValue(newValue);\n this.dispatchEvent(new CustomEvent(`change`, {\n detail: { value: valueStr },\n bubbles: true,\n composed: true,\n }));\n };\n\n protected _handleInputChange = (e: CustomEvent<{ value: number }>): void => {\n const value = e.detail?.value ?? this.value;\n this.value = value;\n clearTimeout(this._debounceTimer);\n this._debounceTimer = window.setTimeout(() => {\n this._isDragging = false;\n }, 300);\n this.dispatchEvent(new CustomEvent(`change`, {\n detail: { value: String(value) },\n bubbles: true,\n composed: true,\n }));\n };\n\n protected _handleSliderInput = (e: CustomEvent<{ value: number }>): void => {\n const value = e.detail?.value ?? this.value;\n console.log(`[LABELLED-INPUT] _handleSliderInput called`, { value, composedPath: e.composedPath() });\n this.value = value;\n this._isDragging = true;\n clearTimeout(this._debounceTimer);\n this.dispatchEvent(new CustomEvent(`input`, {\n detail: { value },\n bubbles: true,\n composed: true,\n }));\n };\n\n protected _syncValue(v: number): void {\n const input = this.renderRoot?.querySelector(this.inputSelector);\n if (input) {\n applyValue(input, v);\n }\n const editableNumber = this.renderRoot?.querySelector(`ixfx-editable-number`);\n if (editableNumber) {\n applyValue(editableNumber, v);\n (editableNumber as any)._requestDisplayUpdate?.();\n }\n }\n\n protected _renderEditableNumber() {\n if (this._isMini) {\n return nothing;\n }\n return html`\n <ixfx-editable-number\n class=\"number\"\n mode=\"label\"\n no-drag\n .value=${String(this.value)}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .dragSensitivity=${this.dragSensitivity}\n .precision=${this.precision}\n .displayText=${this.label}\n .displayTextLogic=${this._isDragging ? `hidden` : this.displayTextLogic}\n .formatter=${this._formatter}\n @change=${this._handleNumberChange}\n ></ixfx-editable-number>\n `;\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has(`value`)) {\n this._syncValue(this.value);\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-input-base-Dp_9KP0G.d.ts","names":[],"sources":["../src/mixins/labelled-input-base.ts"],"mappings":";;uBAIsB,0BAA0B;EAClC;EAEgB;EACA;EACA;EACA;EACA;EAC+B;EAEI;EACC;EAEjB;YAE5B;YACA;YACA,cAAc;UAEzB;UACA;oBAEU;MAEd,cAAc;MAId,UAAU,SAAS;gBAIT;EAIL;EAMA;YAMC,cAAc,SAAS;YAcvB,sBAAuB,GAAG;IAAc;;YAYxC,qBAAsB,GAAG;IAAc;;YAcvC,qBAAsB,GAAG;IAAc;;YAavC,WAAW;YAYX,uCAAqB,2BAAA;EAuBtB,QAAQ,mBAAmB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-radial-input.d.ts","names":[],"sources":["../src/labelled-radial-input/labelled-radial-input.ts"],"mappings":";;;;cA0Da,4BAA4B;WAC9B;EAGA;EACA;EAEmB;EACA;EAC2B,aAAa;EACvC;EACwB,WAAW;EACnC;EACA;EAEoC;;EAGpC;UAEZ;UAIT;YAeW,cAAc,SAAS;YAMvB,uCAAqB,2BAAA;EA0B/B,wBAAM;UA6BP;SAYD,QAAQ;;QA0ET;YACI;IACR,8BAA8B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-radial-input.js","names":["customElement"],"sources":["../src/labelled-radial-input/labelled-radial-input.ts"],"sourcesContent":["/**\n * <ixfx-labelled-radial-input> — labelled radial input combining ixfx-editable-number and ixfx-radial-input.\n *\n * Layout is driven by container queries on the component's own aspect ratio (width / height):\n * - width / height >= 1.5 (wide) → horizontal layout (label to the left of dial)\n * - width / height < 1.5 (tall/square) → vertical layout (label above dial)\n *\n * Mini mode: hides ixfx-editable-number, shows only the dial with tooltip forced on.\n * Triggered when width < --mini-width-threshold (default 120px)\n * OR height < --mini-height-threshold (default 45px).\n * Force on/off with CSS variable: --mini: 1 (always mini) | 0 (never mini).\n *\n * Override layout entirely with --flow: row | column.\n *\n * CSS variables (passes through to ixfx-radial-input):\n * --dial-border-width, --dial-border-color, --dial-fill, --radius\n * --marker-color, --marker-thickness, --marker-length, --marker-offset\n * --marker-border-width, --marker-border-color\n * --midpoint-color, --midpoint-thickness, --midpoint-length, --midpoint-offset\n * --lane-width, --lane-color, --lane-border-width, --lane-offset, --lane-dasharray\n * --wedge-fill, --wedge-fill-opacity, --wedge-border-width, --wedge-border-color\n *\n * Properties:\n * label Label text content\n * min / max / value / step Range bounds and current value\n * drag-sensitivity Steps per pixel of drag (default: 1)\n * precision Decimal places (default: 0)\n * radius Dial size, 10-50 range (default: 45)\n * flatten How much circle to hide, 0-1 (default: 0.3)\n * markerStyle 'needle' | 'dot' | 'none' (default: 'needle')\n * wedge Show filled wedge sector (default: false)\n * valueMode 'range' | 'bipolar' | 'unipolar' (default: 'range')\n * aspectRatioThreshold Width/height ratio to trigger horizontal layout (default: 1.5)\n * mini-width-threshold Width (in pixels) below which mini mode activates (default: 120)\n * mini-height-threshold Height (in pixels) below which mini mode activates (default: 45)\n * tooltip Boolean — show dial tooltip\n * flip Boolean — place label after dial (bottom in vertical, right in horizontal)\n * display-text-logic 'hidden' | 'show' | 'override' | 'transient'\n * formatter Function (value: string) => string — formats value for display\n * lighttouch Boolean — passed through to the inner dial and editable-number so wheel\n * adjusts the value on hover instead of requiring focus on either\n *\n * Events:\n * change — CustomEvent<{ value: string }>, bubbles + composed\n * Fired when value changes via dial or editable-number commit\n * input — CustomEvent<{ value: number }>, bubbles + composed\n * Fired on every dial interaction\n */\nimport type { CSSResultGroup } from 'lit';\nimport type { MarkerStyle, ValueMode } from '../radial-input/types.js';\nimport { css, html, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { LabelledInputBase } from '../mixins/labelled-input-base.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../radial-input/radial-input.js';\n\n@customElement(`ixfx-labelled-radial-input`)\nexport class LabelledRadialInput extends LabelledInputBase {\n readonly inputSelector = `ixfx-radial-input`;\n\n // Override LabelledInputBase defaults (max=1, step=0.01) to match ixfx-radial-input defaults\n override max = 100;\n override step = 1;\n\n @property({ type: Number }) radius = 45;\n @property({ type: Number }) flatten = 0.3;\n @property({ type: String, attribute: `marker-style` }) markerStyle: MarkerStyle = `needle`;\n @property({ type: Boolean }) wedge = false;\n @property({ type: String, attribute: `value-mode` }) valueMode: ValueMode = `range`;\n @property({ type: Boolean }) tooltip = false;\n @property({ type: Boolean }) flip = false;\n\n @property({ type: Number, attribute: `aspect-ratio-threshold` }) aspectRatioThreshold = 1.5;\n\n /** Pass-through: enables wheel-on-hover for the inner dial and editable-number. */\n @property({ type: Boolean }) lighttouch = false;\n\n @state() private _isWide = false;\n\n // Returns effective precision: uses explicit value if set, otherwise computes based on step or range.\n // Prefers step-derived precision, falls back to range-based heuristic.\n private _getEffectivePrecision(): number {\n if (this.hasAttribute(`precision`)) {\n return this.precision;\n }\n // If step is set, derive precision from it (e.g., step=0.5 → precision=1, step=1 → precision=0)\n if (this.step !== undefined) {\n const stepStr = String(this.step);\n const decimalPart = stepStr.split(`.`)[1];\n return decimalPart ? decimalPart.length : 0;\n }\n // Fallback: range > 10 → precision 0 (integers), range <= 10 → precision 2\n const range = this.max - this.min;\n return range > 10 ? 0 : 2;\n }\n\n protected override _handleResize(entries: ResizeObserverEntry[]): void {\n super._handleResize(entries);\n const { width, height } = entries[0].contentRect;\n this._isWide = height > 0 && (width / height) >= this.aspectRatioThreshold;\n }\n\n protected override _renderEditableNumber() {\n if (this._isMini) {\n return nothing;\n }\n const labelMinWidth = Math.max(this.label?.length ?? 0, 3) + 1;\n return html`\n <ixfx-editable-number\n class=\"number\"\n mode=\"label\"\n no-drag\n ?lighttouch=${this.lighttouch}\n .value=${String(this.value)}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .dragSensitivity=${this.dragSensitivity}\n .precision=${this._getEffectivePrecision()}\n .displayText=${this.label}\n .displayTextLogic=${this._isDragging ? `hidden` : this.displayTextLogic}\n .formatter=${this._formatter}\n style=\"--label-min-width: var(--label-width, ${labelMinWidth}ch); --label-align: center;\"\n @change=${this._handleNumberChange}\n ></ixfx-editable-number>\n `;\n }\n\n override render() {\n const showTooltip = this.tooltip || this._isMini;\n const tooltipValue = this._getTooltipValue();\n\n return html`\n <div class=\"wrap ${this._isMini ? `mini` : ``} ${this._isWide ? `wide` : ``} ${this.flip ? `flip` : ``}\">\n ${this._renderEditableNumber()}\n <ixfx-radial-input\n class=\"dial\"\n ?lighttouch=${this.lighttouch}\n .value=${this.value}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .radius=${this.radius}\n .flatten=${this.flatten}\n .markerStyle=${this.markerStyle}\n ?wedge=${this.wedge}\n .valueMode=${this.valueMode}\n data-tooltip-anchor=\"top\"\n data-tooltip=${tooltipValue}\n data-tooltip-live=${showTooltip ? `input` : nothing}\n @input=${this._handleSliderInput}\n @change=${this._handleInputChange}\n ></ixfx-radial-input>\n </div>\n `;\n }\n\n private _getTooltipValue(): string {\n const range = this.max - this.min;\n const numValue = Number(this.value);\n if (this.min === 0 && this.max === 1) {\n return `${Math.round(numValue * 100)}%`;\n }\n if (range > 10) {\n return String(Math.floor(numValue));\n }\n return numValue.toFixed(2);\n }\n\n static styles: CSSResultGroup = [themeFallbacks, css`\n :host {\n display: block;\n min-height: var(--min-height, 60px);\n min-width: var(--min-width, 60px);\n width: var(--width, auto);\n height: var(--height, auto);\n }\n\n :host(:focus-within) {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n\n .wrap {\n display: flex;\n width: 100%;\n height: 100%;\n align-items: center;\n justify-content: center;\n flex-direction: var(--flow, column);\n }\n\n ixfx-editable-number {\n flex-shrink: 0;\n --label-align: center;\n width: 100%;\n }\n\n ixfx-radial-input {\n flex-shrink: 1;\n min-height: 0;\n min-width: 0;\n max-width: 100%;\n --radial-input-svg-focus-outline: none;\n --radial-input-svg-focus-outline-offset: 0;\n --prominence-tickled-opacity: 1;\n --prominence-tickled-saturate: 1;\n }\n\n /* Wide layout (aspect ratio >= threshold): label to the left of dial */\n .wrap.wide {\n flex-direction: var(--flow, row);\n justify-content: space-evenly;\n }\n\n .wrap.wide ixfx-editable-number {\n --label-align: left;\n width: var(--label-width, 5ch);\n }\n\n .wrap.wide ixfx-radial-input {\n height: auto;\n max-width: none;\n }\n\n /* Flip: label after dial (bottom in column, right in row) */\n .wrap.flip ixfx-editable-number {\n order: 1;\n }\n\n /* Mini mode: dial fills the component */\n .wrap.mini {\n justify-content: center;\n gap: 0;\n }\n\n .wrap.mini ixfx-radial-input {\n width: 100%;\n height: 100%;\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-labelled-radial-input': LabelledRadialInput;\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-range-input.js","names":["customElement"],"sources":["../src/labelled-range-input/labelled-range-input.ts"],"sourcesContent":["/**\n * <ixfx-labelled-range-input> — labelled range input combining ixfx-editable-number and ixfx-range-input.\n *\n * Layout is driven by container queries on the component's own height:\n * - height >= 80px → vertical (label above slider) — the default with height: 100px\n * - height < 80px → horizontal (label beside slider)\n *\n * Mini mode: hides ixfx-editable-number, shows only the slider with tooltip forced on.\n * Triggered when width < --mini-width-threshold (default 120px)\n * OR height < --mini-height-threshold (default 45px).\n * Force on/off with CSS variable: --mini: 1 (always mini) | 0 (never mini).\n *\n * Override layout entirely with --flow: row | column (bypasses the container query).\n * Override height with --height (e.g. --height: 100% to fill a constrained container).\n * Override the editable-number width (horizontal layout only) with --label-width (e.g. 4em).\n *\n * CSS variables (passes through to child components):\n *\n * From ixfx-editable-number:\n * --label-font-size (default: var(--text-m))\n * --label-font-family (default: var(--font-family))\n * --label-color (default: var(--surface-2-text))\n * --label-muted-color (default: var(--surface-muted-text))\n * --label-padding (default: var(--space-xs) var(--space-s))\n * --label-radius (default: var(--radius-s))\n * --label-align (default: center)\n *\n * From ixfx-range-input:\n * --track-thickness (default: 1.5em)\n * --thumb-color (default: var(--surface-2-text))\n * --thumb-color-active (default: var(--accent))\n * --thumb-size (default: var(--track-thickness))\n * --thumb-thickness (default: 2em)\n * --thumb-radius (default: 0)\n * --thumb-border (default: none)\n * --thumb-shadow (default: none)\n * --background-track (default: var(--surface-4))\n * --background-track-hover (default: --background-track)\n * --background-track-value (default: var(--surface-6))\n * --background-track-value-hover (default: var(--accent))\n * --background-track-value-active (default: var(--accent))\n *\n * Properties:\n * label Label text content\n * min / max / value / step Range bounds and current value\n * drag-sensitivity Steps per pixel of drag (default: 1)\n * precision Decimal places (default: 0)\n * orientation 'horizontal' | 'vertical' (slider orientation)\n * tooltip Boolean — show slider tooltip\n * tooltip-orientation 'top' | 'right'\n * switch-height Height threshold for vertical↔horizontal switch (default: 80)\n * mini-width-threshold Width (in pixels) below which mini mode activates (default: 120)\n * mini-height-threshold Height (in pixels) below which mini mode activates (default: 45)\n * display-text-logic 'hidden' | 'show' | 'override' | 'transient'\n * formatter Function (value: string) => string — formats value for display and tooltip\n * lighttouch Boolean — passed through to the inner slider and editable-number so wheel\n * adjusts the value on hover instead of requiring focus on either\n *\n * Events:\n * change — CustomEvent<{ value: string }>, bubbles + composed\n * Fired when value changes via slider or editable-number commit\n * input — CustomEvent<{ value: number }>, bubbles + composed\n * Fired on every slider move\n */\nimport type { CSSResultGroup } from 'lit';\nimport { css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LabelledInputBase } from '../mixins/labelled-input-base.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-labelled-range-input`)\nexport class LabelledRangeInput extends LabelledInputBase {\n readonly inputSelector = `ixfx-range-input`;\n\n @property({ type: String }) orientation: `horizontal` | `vertical` = `horizontal`;\n @property({ type: Boolean }) tooltip = false;\n @property({ type: Boolean, attribute: `no-tooltip` }) noTooltip = false;\n @property({ type: String, attribute: `tooltip-orientation` }) tooltipOrientation: `top` | `right` = `top`;\n /** Pass-through: enables wheel-on-hover for the inner slider and editable-number. */\n @property({ type: Boolean }) lighttouch = false;\n\n @property({ type: Number, attribute: `switch-height` }) switchHeight = 80;\n\n protected override _renderEditableNumber() {\n // Override base implementation to pass lighttouch through to the inner\n // editable-number. Mirrors the props forwarded in LabelledInputBase.\n if (this._isMini) {\n // Mini mode: no editable-number rendered at all (matches base behaviour).\n return html``;\n }\n return html`\n <ixfx-editable-number\n class=\"number\"\n mode=\"label\"\n no-drag\n ?lighttouch=${this.lighttouch}\n .value=${String(this.value)}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .dragSensitivity=${this.dragSensitivity}\n .precision=${this.precision}\n .displayText=${this.label}\n .displayTextLogic=${this._isDragging ? `hidden` : this.displayTextLogic}\n .formatter=${this._formatter}\n @change=${this._handleNumberChange}\n ></ixfx-editable-number>\n `;\n }\n\n override render() {\n const sliderLabelFormatter = this._formatter\n ? (raw: number) => this._formatter!(String(raw))\n : undefined;\n const showTooltip = !this.noTooltip && (this.tooltip || this._isMini);\n\n return html`\n <div class=\"wrap ${this._isMini ? `mini` : ``}\">\n ${this._renderEditableNumber()}\n <ixfx-range-input\n class=\"slider\"\n ?lighttouch=${this.lighttouch}\n .value=${this.value}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .orientation=${this.orientation}\n ?tooltip=${showTooltip}\n .tooltipOrientation=${this.tooltipOrientation}\n .labelFormatter=${sliderLabelFormatter}\n @input=${this._handleSliderInput}\n @change=${this._handleInputChange}\n ></ixfx-range-input>\n </div>\n `;\n }\n\n static styles: CSSResultGroup = css`\n :host {\n display: block;\n container-type: size;\n min-height: var(--min-height, 20px);\n min-width: var(--min-width, 50px);\n width: var(--width, auto);\n height: var(--height, 50px);\n }\n\n .wrap {\n display: flex;\n width: 100%;\n height: 100%;\n gap: var(--space-s, 4px);\n align-items: center;\n }\n\n ixfx-editable-number {\n flex-shrink: 0;\n }\n\n ixfx-range-input {\n flex: 1;\n min-width: 0;\n }\n\n /* Default (compact): horizontal — label beside slider */\n .wrap {\n flex-direction: var(--flow, row);\n justify-content: flex-start;\n align-items: center;\n }\n\n ixfx-editable-number {\n --label-align: left;\n width: var(--label-width, 5ch);\n --label-min-width: var(--label-width, 5ch);\n /* Block fill/background variables from reaching editable-number */\n --fill-color: initial;\n --fill-opacity: initial;\n --fill-image: initial;\n }\n\n /* Vertically-stacked layout: when container has enough height */\n @container (height >= 45px) {\n .wrap {\n flex-direction: var(--flow, column);\n justify-content: flex-start;\n align-items: center;\n }\n\n ixfx-editable-number {\n --label-align: center;\n align-self: center;\n width: 100%;\n }\n\n ixfx-range-input {\n width: 100%;\n }\n }\n\n /* Mini mode: slider fills the full component */\n .wrap.mini {\n gap: 0;\n }\n\n .wrap.mini ixfx-range-input {\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-labelled-range-input': LabelledRangeInput;\n }\n}\n"],"mappings":";;;;;AAuEO,IAAM,qBAAN,MAAM,2BAA2B,kBAAkB;;;EAC/B,KAAA,gBAAA;EAE4C,KAAA,cAAA;EAC9B,KAAA,UAAA;EAC2B,KAAA,YAAA;EACkC,KAAA,qBAAA;EAE1D,KAAA,aAAA;EAE6B,KAAA,eAAA;;CAEvE,wBAA2C;EAGzC,IAAI,KAAK,SAEP,OAAO,IAAI;EAEb,OAAO,IAAI;;;;;sBAKO,KAAK,WAAW;iBACrB,OAAO,KAAK,KAAK,EAAE;eACrB,KAAK,IAAI;eACT,KAAK,IAAI;gBACR,KAAK,KAAK;2BACC,KAAK,gBAAgB;qBAC3B,KAAK,UAAU;uBACb,KAAK,MAAM;4BACN,KAAK,cAAc,WAAW,KAAK,iBAAiB;qBAC3D,KAAK,WAAW;kBACnB,KAAK,oBAAoB;;;CAGzC;CAEA,SAAkB;EAChB,MAAM,uBAAuB,KAAK,cAC7B,QAAgB,KAAK,WAAY,OAAO,GAAG,CAAC,IAC7C,KAAA;EACJ,MAAM,cAAc,CAAC,KAAK,cAAc,KAAK,WAAW,KAAK;EAE7D,OAAO,IAAI;yBACU,KAAK,UAAU,SAAS,GAAG;UAC1C,KAAK,sBAAsB,EAAE;;;wBAGf,KAAK,WAAW;mBACrB,KAAK,MAAM;iBACb,KAAK,IAAI;iBACT,KAAK,IAAI;kBACR,KAAK,KAAK;yBACH,KAAK,YAAY;qBACrB,YAAY;gCACD,KAAK,mBAAmB;4BAC5B,qBAAqB;mBAC9B,KAAK,mBAAmB;oBACvB,KAAK,mBAAmB;;;;CAI1C;;EAEgC,KAAA,SAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyErC;AAxIG,WAAA,CAAA,SAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,mBAAA,WAAA,eAAA,KAAA,CAAA;AACzB,WAAA,CAAA,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,GAAA,mBAAA,WAAA,WAAA,KAAA,CAAA;AAC1B,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,WAAW;AAAa,CAAC,CAAA,GAAA,mBAAA,WAAA,aAAA,KAAA,CAAA;AACnD,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,WAAW;AAAsB,CAAC,CAAA,GAAA,mBAAA,WAAA,sBAAA,KAAA,CAAA;AAE3D,WAAA,CAAA,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,GAAA,mBAAA,WAAA,cAAA,KAAA,CAAA;AAE1B,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,WAAW;AAAgB,CAAC,CAAA,GAAA,mBAAA,WAAA,gBAAA,KAAA,CAAA;AAXvDA,qBAAAA,WAAAA,CAAAA,kBAAc,2BAA2B,CAAA,GAAA,kBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"labelled-slider-input-FdCRi6st.js","names":["#lastInputValue","#dragStartY","#dragStartValue","#dragCurrentValue","#dragging","#hasDragged","customElement","customElement"],"sources":["../src/editable-label/editable-number.ts","../src/labelled-slider-input/labelled-slider-input.ts"],"sourcesContent":["/**\n * <ixfx-editable-number> — inline editable number label with Ableton-style drag.\n *\n * Extends <ixfx-editable-label> with:\n * • Pointer drag to adjust value — drag up to increase, down to decrease,\n * without entering full text-edit mode.\n * • Click gives focus; pressing any key while focused enters text-edit mode.\n * • Optional min/max clamping and step snapping.\n * • Optional fill-bar visualization behind the label text.\n *\n * Attributes:\n * min Minimum value (no clamping if unset)\n * max Maximum value (no clamping if unset)\n * step Snap increment, also informs decimal-place display (unset = no snapping)\n * stops Number of quantised keyboard stops (unset = no snapping). Wins over `step` when > 1.\n * drag-sensitivity Steps changed per pixel of drag (default: 1); multiply by step to get units/px\n * precision Decimal places applied when rounding drag-produced values (default: 0 = integers).\n * Has no effect when step is set (step implies its own precision).\n * Typed values are never precision-rounded — the user can always enter finer values.\n * fill-style 'linear' (default) or 'circular' — shape of the fill visualization\n * linear-style 'range' (default), 'bipolar', or 'unipolar' — how value maps to fill (linear mode only)\n * circular-style 'grow' (default), 'offset', or 'dot' — how value maps to fill (circular mode only)\n * no-drag Boolean — disables drag interaction; text editing still works\n * lighttouch Boolean — wheel adjusts the value on hover instead of requiring focus.\n * Wheel is suppressed while the user is typing (`_editing === true`).\n *\n * CSS variables:\n * --fill-color Fill bar color (default: var(--accent))\n * --fill-opacity Fill bar opacity as 0..1 (default: 0.25)\n * --value Current normalized value (0..1)\n *\n * All CSS variables from <ixfx-editable-label> are also inherited.\n *\n * Events:\n * change — CustomEvent<{ value: string }>, bubbles + composed\n * Fired on text-edit commit AND on drag-end (if value changed).\n */\nimport type { CSSResult } from 'lit';\nimport type { WheelDirection } from '../mixins/wheel-nudge.js';\nimport type { EditableLabelChangeDetail } from './editable-label.js';\nimport { css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { resolveAxisStep } from '../keyboard.js';\nimport { WheelNudgeMixin } from '../mixins/wheel-nudge.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { prominenceStyles } from '../styles/prominence.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport { EditableLabel } from './editable-label.js';\n\nconst DRAG_THRESHOLD_PX = 3;\n\n@customElement(`ixfx-editable-number`)\nexport class EditableNumber extends WheelNudgeMixin(EditableLabel) {\n @property({ type: Number }) min?: number;\n @property({ type: Number }) max?: number;\n @property({ type: Number }) step?: number;\n /** Quantised stops for keyboard nudging. Overrides `step` when > 1. */\n @property({ type: Number }) stops?: number;\n @property({ type: Number, attribute: `drag-sensitivity` }) dragSensitivity = 1;\n @property({ attribute: `fill-style` }) fillStyle?: `linear` | `circular`;\n @property({ attribute: `linear-style` }) linearStyle?: `range` | `bipolar` | `unipolar`;\n @property({ attribute: `circular-style` }) circularStyle?: `grow` | `offset` | `dot`;\n @property({ type: Boolean, attribute: `no-drag` }) noDrag = false;\n @property({ type: Number }) precision = 0;\n\n // ── Drag state (not reactive — managed imperatively to avoid Lit cycles) ──\n #dragStartY = 0;\n #dragStartValue = 0;\n #dragging = false;\n #hasDragged = false;\n #dragCurrentValue = 0;\n #lastInputValue = ``;\n #firstUpdateComplete = false;\n\n constructor() {\n super();\n // Override parent defaults for a number input context\n this.mode = `editor`;\n this.entryMode = `number`;\n this.value = `0`;\n }\n\n // ── Render ───────────────────────────────────────────────────────────────────\n\n override render() {\n return html`\n ${this.fillStyle ? html`<div class=\"track\"></div>` : ``}\n ${this.fillStyle ? html`<div class=\"value\"><div class=\"bar\"></div></div>` : ``}\n <div\n class=\"number\"\n part=\"content\"\n tabindex=\"${this.disabled ? -1 : 0}\"\n contenteditable=\"${this._editing ? `plaintext-only` : `false`}\"\n data-placeholder=\"${this.placeholder}\"\n @click=${this._handleClick}\n @focus=${this._handleFocus}\n @blur=${this._handleBlur}\n @keydown=${this._handleKeydown}\n @beforeinput=${this._handleBeforeInput}\n @input=${this._stopNativeInput}\n ></div>\n `;\n }\n\n private _stopNativeInput = (e: Event): void => {\n e.stopPropagation();\n };\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`pointerdown`, this._onPointerDown);\n this.addEventListener(`pointermove`, this._onPointerMove);\n this.addEventListener(`pointerup`, this._onPointerUp);\n this.addEventListener(`keydown`, this._onKeyDown);\n this.addEventListener(`click`, this._interceptClick, { capture: true });\n this.addEventListener(`mouseenter`, this._handleMouseEnter);\n this.addEventListener(`mouseleave`, this._handleMouseLeave);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`pointerdown`, this._onPointerDown);\n this.removeEventListener(`pointermove`, this._onPointerMove);\n this.removeEventListener(`pointerup`, this._onPointerUp);\n this.removeEventListener(`keydown`, this._onKeyDown);\n this.removeEventListener(`click`, this._interceptClick);\n this.removeEventListener(`mouseenter`, this._handleMouseEnter);\n this.removeEventListener(`mouseleave`, this._handleMouseLeave);\n }\n\n private _handleMouseEnter = (): void => {\n if (this.displayTextLogic !== `transient` || this._editing)\n return;\n this._hovering = true;\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n this._transientShowingValue = true;\n this._requestDisplayUpdate();\n }, this.appearDelay);\n };\n\n private _handleMouseLeave = (): void => {\n if (this.displayTextLogic !== `transient` || this._editing)\n return;\n this._hovering = false;\n this._clearTransientTimer();\n if (this._transientShowingValue) {\n this._transientTimer = window.setTimeout(() => {\n if (!this._hovering) {\n this._transientShowingValue = false;\n this._requestDisplayUpdate();\n }\n }, this.disappearDelay);\n }\n };\n\n // ── Override parent interaction — focus only, edit via keypress ───────────\n\n /** Click just focuses; edit mode is entered by pressing a key while focused. */\n protected _handleClick = (): void => {\n if (this.disabled)\n return;\n this.renderRoot?.querySelector<HTMLElement>(`.number`)?.focus();\n };\n\n /** Suppress auto-edit-on-focus from editor mode; keydown handles it instead. */\n protected override _handleFocus = (): void => { /* intentional no-op */ };\n\n /** Override to use .number instead of .content for text display */\n protected get _contentEl(): HTMLElement | undefined {\n const el = this.renderRoot?.querySelector<HTMLElement>(`.number`);\n return el ?? undefined;\n }\n\n override firstUpdated(changedProperties: Map<string, unknown>): void {\n super.firstUpdated(changedProperties);\n // For 'show' mode, start by showing displayText at rest\n if (this.displayTextLogic === `show`) {\n this._showModeWaitingToHide = true;\n }\n this._updateValueCss(this._normalizedValue());\n this._requestDisplayUpdate();\n }\n\n protected _onUserInteraction(): void {\n if (this.displayTextLogic === `show` && !this._editing) {\n this._clearTransientTimer();\n this._showModeWaitingToHide = false;\n this._requestDisplayUpdate();\n this._transientTimer = window.setTimeout(() => {\n this._showModeWaitingToHide = true;\n this._requestDisplayUpdate();\n }, this.disappearDelay);\n return;\n }\n if (this.displayTextLogic === `transient` && !this._editing) {\n this._clearTransientTimer();\n this._transientShowingValue = true;\n this._requestDisplayUpdate();\n this._transientTimer = window.setTimeout(() => {\n if (!this._hovering) {\n this._transientShowingValue = false;\n this._requestDisplayUpdate();\n }\n }, this.disappearDelay);\n return;\n }\n super._onUserInteraction();\n }\n\n private _onValueChange(): void {\n if (this.displayTextLogic !== `show` || this._editing)\n return;\n\n this._clearTransientTimer();\n this._showModeWaitingToHide = false;\n this._requestDisplayUpdate();\n this._transientTimer = window.setTimeout(() => {\n this._showModeWaitingToHide = true;\n this._requestDisplayUpdate();\n }, this.disappearDelay);\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n // Note: We do NOT call _onValueChange here for 'show' mode.\n // The parent class handles display updates via _requestDisplayUpdate\n // in firstUpdated. Additional value changes are handled via\n // drag/keyboard events that call _onValueChange directly.\n if (!this._editing) {\n this._updateValueCss(this._normalizedValue());\n }\n }\n\n private _updateValueCss(normalized: number): void {\n this.style.setProperty(`--value`, String(normalized));\n\n let valueStart = 0;\n let valueEnd = normalized;\n\n if (this.linearStyle === `bipolar`) {\n if (normalized <= 0.5) {\n valueStart = normalized;\n valueEnd = 0.5;\n } else {\n valueStart = 0.5;\n valueEnd = normalized;\n }\n } else if (this.linearStyle === `unipolar`) {\n valueStart = 0.5 - normalized * 0.5;\n valueEnd = 0.5 + normalized * 0.5;\n }\n\n this.style.setProperty(`--value-start`, String(valueStart));\n this.style.setProperty(`--value-end`, String(valueEnd));\n\n // For circular offset mode, compute pixel offset from center\n // and set component dimensions for radius calculation\n if (this.fillStyle === `circular` && this.circularStyle === `offset`) {\n const h = this.offsetHeight;\n const w = this.offsetWidth;\n const r = h / 2 - 2; // radius with margin to prevent clipping at top/bottom\n // Circle edges must stay 2px inside component edges:\n // - at value=0: circle left edge at 2px\n // - at value=1: circle right edge at w-2px\n const leftEdge = 2;\n const rightEdge = w - 2;\n const valueCenterPx = leftEdge + r + normalized * (rightEdge - leftEdge - 2 * r);\n this.style.setProperty(`--radius`, `${r}px`);\n this.style.setProperty(`--value-center-px`, `${valueCenterPx}px`);\n this.style.setProperty(`--component-width-px`, `${w}px`);\n this.style.setProperty(`--component-height-px`, `${h}px`);\n }\n }\n\n protected override _getDisplayText(): string {\n // In override mode, always show displayText (even when dragging or editing)\n if (this._shouldUseDisplayText()) {\n return this.displayText ?? ``;\n }\n // For transient mode, show the drag value while dragging\n if (this.#dragging) {\n const formatted = this.step !== undefined\n ? this._formatNumber(this.#dragCurrentValue)\n : this.#dragCurrentValue.toFixed(this.precision);\n return this.formatter ? this.formatter(formatted) : formatted;\n }\n // Normal case: when a custom formatter is set, pass raw value so formatter\n // can apply its own precision logic (e.g. \"0.5\" → \"50%\" without precision loss)\n if (this.formatter) {\n const raw = Number.parseFloat(this.value);\n return this.formatter(Number.isNaN(raw) ? this.value : String(raw));\n }\n return this._formatDisplay();\n }\n\n // ── Clamp before parent commits (overrides parent's private _tryCommit) ──\n\n protected override _tryCommit(): void {\n const el = this.renderRoot?.querySelector<HTMLElement>(`.number`);\n if (el) {\n const n = Number.parseFloat(el.textContent?.trim() ?? ``);\n if (!Number.isNaN(n)) {\n el.textContent = this._formatNumber(this._clamp(this._snap(n)));\n }\n }\n super._tryCommit();\n }\n\n // ── Override parent's input handling — fire 'input' events on each keypress ──\n\n protected override _handleBeforeInput = (e: InputEvent): void => {\n if (e.inputType !== `insertText` || !e.data) {\n return;\n }\n\n if (!this._isAllowedInput(e.data)) {\n e.preventDefault();\n return;\n }\n\n const contentEl = this._contentEl;\n if (!contentEl) {\n return;\n }\n\n const currentContent = contentEl.textContent ?? ``;\n const insertPosition = (contentEl as HTMLInputElement).selectionStart ?? currentContent.length;\n const newValue = currentContent.slice(0, insertPosition) + e.data + currentContent.slice(insertPosition);\n\n if (newValue !== this.#lastInputValue) {\n this.#lastInputValue = newValue;\n this.dispatchEvent(new CustomEvent(`input`, {\n detail: { value: newValue },\n bubbles: true,\n composed: true,\n }));\n }\n };\n\n protected override _handleKeydown = (e: KeyboardEvent): void => {\n if (!this._editing) {\n return;\n }\n\n if (e.key === `Enter`) {\n e.preventDefault();\n this._tryCommit();\n if (this.mode === `editor`)\n this._contentEl?.blur();\n } else if (e.key === `Escape`) {\n e.preventDefault();\n this.dispatchEvent(new CustomEvent(`cancelled`, {\n detail: { value: this._prevValue },\n bubbles: true,\n composed: true,\n }));\n this._cancelEdit();\n this.dispatchEvent(new CustomEvent(`change`, {\n detail: { value: this._prevValue },\n bubbles: true,\n composed: true,\n }));\n if (this.mode === `editor`)\n this._contentEl?.blur();\n }\n };\n\n // ── Drag event handlers ───────────────────────────────────────────────────\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (this._editing || this.disabled)\n return;\n\n if (this._handleArrowKey(e)) {\n return;\n }\n\n // Printable characters while focused → enter edit mode.\n // Enter is intentionally excluded: the parent handles Enter for commit,\n // and including it here would re-enter edit mode immediately after commit.\n if (e.key.length === 1) {\n this._onUserInteraction();\n this._beginEdit();\n }\n };\n\n private _handleArrowKey(e: KeyboardEvent): boolean {\n const range = (this.max ?? 100) - (this.min ?? 0);\n if (range === 0)\n return false;\n\n const effectiveStep = resolveAxisStep(range, this.stops, this.step, e.shiftKey);\n\n let delta = 0;\n let handled = false;\n\n switch (e.key) {\n case `ArrowUp`:\n case `ArrowRight`:\n delta = effectiveStep;\n handled = true;\n break;\n case `ArrowDown`:\n case `ArrowLeft`:\n delta = -effectiveStep;\n handled = true;\n break;\n case `Home`:\n delta = -(this._parseValue() - (this.min ?? 0));\n handled = true;\n break;\n case `End`:\n delta = (this.max ?? 0) - this._parseValue();\n handled = true;\n break;\n }\n\n if (handled) {\n e.preventDefault();\n this._applyDelta(delta);\n return true;\n }\n\n return false;\n }\n\n /**\n * Apply a signed delta to the current value, clamp/snap/format, and fire\n * `input`/`change`. Shared between arrow-key handler and the wheel handler.\n */\n private _applyDelta(delta: number): void {\n const prev = this.value;\n const current = this._parseValue();\n const newValue = this._clamp(this._snap(current + delta));\n\n const newValueStr = this.step !== undefined\n ? this._formatNumber(newValue)\n : newValue.toFixed(this.precision);\n\n this.value = newValueStr;\n\n this._requestDisplayUpdate();\n this._updateValueCss(this._normalizedValue(newValue));\n\n if (newValueStr !== prev) {\n this.dispatchEvent(new CustomEvent(`input`, {\n detail: { value: newValueStr },\n bubbles: true,\n composed: true,\n }));\n }\n\n requestAnimationFrame(() => {\n if (this.value !== prev) {\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`change`, {\n detail: { value: this.value },\n bubbles: true,\n composed: true,\n }));\n }\n });\n }\n\n // Wheel handler — installed by WheelNudgeMixin on the host. Skipped during\n // text edit so wheel-scrolling the value doesn't fight with the user's typing.\n override _shouldHandleWheel(): boolean {\n if (this._editing)\n return false;\n return super._shouldHandleWheel();\n }\n\n override _applyWheelDelta(direction: WheelDirection, event: WheelEvent): void {\n const range = (this.max ?? 100) - (this.min ?? 0);\n if (range === 0)\n return;\n const effectiveStep = resolveAxisStep(range, this.stops, this.step, event.shiftKey);\n this._applyDelta(direction * effectiveStep);\n }\n\n private _onPointerDown = (e: PointerEvent): void => {\n if (e.button !== 0)\n return; // left button only\n if (this._editing)\n return; // let contenteditable handle it\n if (this.disabled || this.noDrag)\n return;\n e.preventDefault(); // suppress browser text-select / native drag\n this.renderRoot?.querySelector<HTMLElement>(`.number`)?.focus(); // restore focus manually\n\n this.#dragStartY = e.clientY;\n this.#dragStartValue = this._parseValue();\n this.#dragCurrentValue = this.#dragStartValue;\n this.#dragging = false;\n this.#hasDragged = false;\n this.setPointerCapture(e.pointerId);\n };\n\n private _onPointerMove = (e: PointerEvent): void => {\n if (!(e.buttons & 1))\n return; // left button must be held\n if (this._editing)\n return;\n if (this.disabled || this.noDrag)\n return;\n\n const deltaY = this.#dragStartY - e.clientY; // up = positive\n if (!this.#dragging && Math.abs(deltaY) < DRAG_THRESHOLD_PX)\n return;\n\n this.#dragging = true;\n this.#hasDragged = true;\n this.toggleAttribute(`dragging`, true);\n this._onUserInteraction();\n\n const raw = this.#dragStartValue + deltaY * this.dragSensitivity * (this.step || 1);\n const snapped = this._clamp(this._snap(raw));\n // When step is set, snapping already gives the right precision.\n // When step is unset, round to `precision` decimal places.\n this.#dragCurrentValue = this.step !== undefined\n ? snapped\n : Number.parseFloat(snapped.toFixed(this.precision));\n\n const dragValueStr = this.step !== undefined\n ? this._formatNumber(this.#dragCurrentValue)\n : this.#dragCurrentValue.toFixed(this.precision);\n\n if (dragValueStr !== this.#lastInputValue) {\n this.#lastInputValue = dragValueStr;\n this.dispatchEvent(new CustomEvent(`input`, {\n detail: { value: dragValueStr },\n bubbles: true,\n composed: true,\n }));\n }\n\n // Update display using parent's displayTextLogic handling\n this._requestDisplayUpdate();\n this._updateValueCss(this._normalizedValue(this.#dragCurrentValue));\n };\n\n private _onPointerUp = (e: PointerEvent): void => {\n if (this.hasPointerCapture(e.pointerId))\n this.releasePointerCapture(e.pointerId);\n if (!this.#dragging)\n return;\n if (this.disabled || this.noDrag)\n return;\n\n this.#dragging = false;\n this.toggleAttribute(`dragging`, false);\n // Format with step-based or precision-based dp so trailing zeros are preserved\n // in the stored string (e.g. \"5.0\" when precision=1, not \"5\").\n const finalStr = this.step !== undefined\n ? this._formatNumber(this.#dragCurrentValue)\n : this.#dragCurrentValue.toFixed(this.precision);\n const prev = this.value;\n this.value = finalStr;\n if (finalStr !== prev) {\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`change`, {\n detail: { value: finalStr },\n bubbles: true,\n composed: true,\n }));\n }\n };\n\n private _interceptClick = (e: MouseEvent): void => {\n if (this.#hasDragged) {\n e.stopImmediatePropagation();\n this.#hasDragged = false;\n }\n };\n\n // ── Number helpers ────────────────────────────────────────────────────────\n\n private _parseValue(): number {\n return Number.parseFloat(this.value) || 0;\n }\n\n /**\n * Formats the stored value for display, inferring decimal places from the value\n * string itself. This preserves typed precision (e.g. \"0.1234\" stays \"0.1234\")\n * and also respects trailing zeros written by drag storage (e.g. \"5.0\" stays \"5.0\").\n */\n private _formatDisplay(): string {\n const n = Number.parseFloat(this.value);\n if (Number.isNaN(n))\n return this.value;\n if (this.precision !== undefined) {\n return n.toFixed(this.precision);\n }\n const dot = this.value.indexOf(`.`);\n const dp = dot >= 0 ? this.value.length - dot - 1 : 0;\n return n.toFixed(dp);\n }\n\n private _clamp(n: number): number {\n if (this.min !== undefined)\n n = Math.max(this.min, n);\n if (this.max !== undefined)\n n = Math.min(this.max, n);\n return n;\n }\n\n private _snap(n: number): number {\n if (this.stops && this.stops > 1) {\n const min = this.min ?? 0;\n const range = (this.max ?? 100) - min;\n const stopStep = range / this.stops;\n return Math.round((n - min) / stopStep) * stopStep + min;\n }\n if (!this.step)\n return n;\n return Math.round(n / this.step) * this.step;\n }\n\n private _inferDecimals(n?: number): number {\n if (this.step !== undefined) {\n const s = String(this.step);\n const dot = s.indexOf(`.`);\n return dot >= 0 ? s.length - dot - 1 : 0;\n }\n // No step set: infer from the value being formatted so floats are preserved\n const s = String(n ?? this._parseValue());\n const dot = s.indexOf(`.`);\n return dot >= 0 ? s.length - dot - 1 : 0;\n }\n\n private _formatNumber(n: number): string {\n return n.toFixed(this._inferDecimals(n));\n }\n\n /** Returns a 0..1 fraction for the given value within [min, max]. */\n private _normalizedValue(n = this._parseValue()): number {\n if (this.min === undefined || this.max === undefined)\n return 0;\n if (this.max === this.min)\n return 0;\n return Math.max(0, Math.min(1, (n - this.min) / (this.max - this.min)));\n }\n\n // ── Styles ───────────────────────────────────────────────────────────────\n\n static override styles: CSSResult[] = [\n themeFallbacks,\n prominenceStyles,\n ...EditableLabel.styles,\n css`\n :host {\n font-size: var(--text-s,11px);\n --value: 0;\n --value-start: 0;\n --value-end: 0;\n --_fill-color-alpha: color-mix(\n in oklch,\n var(--fill-color, var(--accent, oklch(60% 0.15 140))) calc(var(--fill-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n /* ── Layout (when fill-style is enabled) ── */\n :host([fill-style]) {\n display: grid;\n position: relative;\n grid-template-columns: 1fr;\n grid-template-rows: 1fr;\n min-height: 1.5em;\n min-width: 5em;\n }\n\n :host([fill-style]) .track,\n :host([fill-style]) .value {\n grid-area: 1 / 1;\n position: absolute;\n inset: 0;\n }\n\n /* Track background styling */\n :host([fill-style]) .track {\n z-index: 0;\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n }\n\n :host([fill-style]) .value {\n z-index: 1;\n }\n\n :host([fill-style=\"linear\"]) .track {\n border-radius: var(--radius-s, 3px);\n }\n\n :host([fill-style=\"circular\"]) .track {\n border-radius: 50%;\n overflow: hidden;\n }\n\n /* Linear: all linear-styles use .bar positioned via --value-start and --value-end */\n :host([fill-style=\"linear\"]) .value {\n overflow: hidden;\n }\n\n :host([fill-style=\"linear\"]) .bar {\n position: absolute;\n top: 0;\n bottom: 0;\n left: calc(var(--value-start, 0) * 100%);\n width: calc((var(--value-end, 0) - var(--value-start, 0)) * 100%);\n background: var(--fill-image, var(--_fill-color-alpha));\n }\n\n /* Circular grow: filled circle growing from center */\n :host([fill-style=\"circular\"][circular-style=\"grow\"]) .value,\n :host([fill-style=\"circular\"]:not([circular-style])) .value {\n background: var(--fill-image, var(--_fill-color-alpha));\n clip-path: circle(calc(var(--value) * 50%) at 50% 50%);\n }\n\n /* Circular offset: value circle slides left/right from center.\n Track circle is centered, filling the height.\n Value circle is same size, offset by --value-offset-px.\n At value=0.5: value circle centered on track (invisible when overlaid)\n At value=0: value circle at far left\n At value=1: value circle at far right\n */\n :host([fill-style=\"circular\"][circular-style=\"offset\"]) {\n min-width: 80px;\n min-height: 26px;\n overflow: hidden;\n }\n\n :host([fill-style=\"circular\"][circular-style=\"offset\"]) .track {\n position: absolute;\n top: 50%;\n border-radius: 50%;\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n width: calc(var(--radius, 11px) * 2);\n height: calc(var(--radius, 11px) * 2);\n left: 50%;\n transform: translate(-50%, -50%);\n }\n\n :host([fill-style=\"circular\"][circular-style=\"offset\"]) .value {\n position: absolute;\n top: 50%;\n background: var(--fill-image, var(--_fill-color-alpha));\n border-radius: 50%;\n width: calc(var(--radius, 11px) * 2);\n height: calc(var(--radius, 11px) * 2);\n transform: translate(calc(var(--value-center-px, 13px) - var(--radius, 11px)), -50%);\n }\n\n :host([fill-style=\"circular\"][circular-style=\"offset\"]) .number {\n border-radius: 0;\n }\n\n /* Circular dot: full circle */\n :host([fill-style=\"circular\"][circular-style=\"dot\"]) .value {\n background: var(--fill-image, var(--_fill-color-alpha));\n }\n\n /* ── Number (top layer - text display) ── */\n :host([fill-style]) .number {\n position: absolute;\n inset: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n padding: var(--space-xs, 3px) var(--space-s, 4px);\n }\n\n :host([fill-style=\"circular\"]) .number {\n border-radius: 50%;\n }\n\n /* Drag cursor + no text selection while not in text-edit mode */\n :host(:not([disabled]):not([no-drag])) .number:not([contenteditable=\"plaintext-only\"]) {\n cursor: ns-resize;\n user-select: none;\n -webkit-user-select: none;\n touch-action: none;\n }\n\n /* Focus outline */\n :host .number {\n outline: none;\n }\n\n :host .number:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n\n /* ── Circular host sizing ── */\n :host([fill-style=\"circular\"][circular-style=\"grow\"]),\n :host([fill-style=\"circular\"]:not([circular-style])) {\n aspect-ratio: 1;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-editable-number': EditableNumber;\n }\n}\n","/**\n * <ixfx-labelled-slider-input> — labelled slider input combining ixfx-editable-number and ixfx-slider-input.\n *\n * Layout is driven by container queries on the component's own height:\n * - height >= 80px → vertical (label above slider) — the default with height: 100px\n * - height < 80px → horizontal (label beside slider)\n *\n * Mini mode: hides ixfx-editable-number, shows only the slider.\n * Triggered when width < --mini-width-threshold (default 120px)\n * OR height < --mini-height-threshold (default 45px).\n * Force on/off with CSS variable: --mini: 1 (always mini) | 0 (never mini).\n *\n * Override layout entirely with --flow: row | column (bypasses the container query;\n * --flow: column stacks at any --height, so a tight --height hugs label + slider\n * with no dead space above/below).\n * Override height with --height (e.g. --height: 100% to fill a constrained container).\n * Override the editable-number width (horizontal layout only) with --label-width (e.g. 4em).\n * Override the slider's band thickness in the stacked layout with --slider-thickness (default: 2.5em);\n * extra component height beyond label + slider is split evenly above and below the group.\n *\n * CSS variables (passes through to child components):\n *\n * From ixfx-editable-number:\n * --label-font-size (default: var(--text-m))\n * --label-font-family (default: var(--font-family))\n * --label-color (default: var(--surface-2-text))\n * --label-muted-color (default: var(--surface-muted-text))\n * --label-padding (default: var(--space-xs) var(--space-s))\n * --label-radius (default: var(--radius-s))\n * --label-align (default: center)\n *\n * From ixfx-slider-input:\n * --lane-track-color, --lane-value-color, --lane-color, --lane-<key>-color\n * --lane-dasharray, --lane-dashoffset, --lane-linecap (round | butt)\n * --marker-color, --marker-thickness, --marker-length, --marker-offset\n * --marker-border-width, --marker-border-color, --marker-a-color, etc.\n * --track-color, --track-width, --track-margin\n * --midpoint-color, --midpoint-thickness, --midpoint-length\n *\n * Properties:\n * label Label text content\n * min / max / value / step Range bounds and current value\n * stops Quantise to N discrete positions (default: undefined)\n * drag-sensitivity Steps per pixel of drag (default: 1)\n * precision Decimal places (default: 0)\n * orientation 'horizontal' | 'vertical' (slider orientation)\n * single-style 'range' | 'bipolar' | 'unipolar' (single mode only)\n * marker-style 'needle' | 'dot' | 'triangle' | 'none'\n * disabled Boolean — disables all interaction\n * swipeable Boolean — swipe-to-draw gesture (no pointer capture,\n * for step-sequencer layouts; mirrors ixfx-slider-input)\n * switch-height Height threshold for vertical↔horizontal switch (default: 80)\n * mini-width-threshold Width (in pixels) below which mini mode activates (default: 120)\n * mini-height-threshold Height (in pixels) below which mini mode activates (default: 45)\n * display-text-logic 'hidden' | 'show' | 'override' | 'transient'\n * formatter Function (value: string) => string — formats value for display\n * lighttouch Boolean — passed through to the inner slider and editable-number so wheel\n * adjusts the value on hover instead of requiring focus on either\n *\n * Events:\n * change — CustomEvent<{ value: string }>, bubbles + composed\n * Fired when value changes via slider or editable-number commit\n * input — CustomEvent<{ value: number }>, bubbles + composed\n * Fired on every slider move\n */\nimport type { CSSResultGroup } from 'lit';\nimport type { SliderMarkerStyle, SliderSingleStyle } from '../slider-input/types.js';\nimport { css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LabelledInputBase } from '../mixins/labelled-input-base.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../editable-label/editable-number.js';\nimport '../slider-input/slider-input.js';\n\n@customElement(`ixfx-labelled-slider-input`)\nexport class LabelledSliderInput extends LabelledInputBase {\n readonly inputSelector = `ixfx-slider-input`;\n\n @property({ type: String }) orientation: `horizontal` | `vertical` = `horizontal`;\n @property({ type: String, attribute: `single-style` }) singleStyle: SliderSingleStyle = `range`;\n @property({ type: String, attribute: `marker-style` }) markerStyle: SliderMarkerStyle = `needle`;\n @property({ type: Number }) stops: number | undefined = undefined;\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: Boolean, reflect: true }) swipeable = false;\n /** Pass-through: enables wheel-on-hover for the inner slider and editable-number. */\n @property({ type: Boolean }) lighttouch = false;\n\n @property({ type: Number, attribute: `switch-height` }) switchHeight = 80;\n\n protected override _renderEditableNumber() {\n // Override base implementation to pass lighttouch through to the inner\n // editable-number. Mirrors the props forwarded in LabelledInputBase.\n if (this._isMini) {\n // Mini mode: no editable-number rendered at all (matches base behaviour).\n return html``;\n }\n return html`\n <ixfx-editable-number\n class=\"number\"\n mode=\"label\"\n no-drag\n ?lighttouch=${this.lighttouch}\n .value=${String(this.value)}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .dragSensitivity=${this.dragSensitivity}\n .precision=${this.precision}\n .displayText=${this.label}\n .displayTextLogic=${this._isDragging ? `hidden` : this.displayTextLogic}\n .formatter=${this._formatter}\n @change=${this._handleNumberChange}\n ></ixfx-editable-number>\n `;\n }\n\n protected override _syncValue(v: number): void {\n super._syncValue(v);\n // Base applyValue() sets `.value`, but ixfx-slider-input holds its value\n // in `.valueA` — sync it directly so programmatic changes propagate.\n const input = this.renderRoot?.querySelector(this.inputSelector) as unknown as { valueA?: number } | null;\n if (input && typeof input.valueA === `number` && input.valueA !== v) {\n input.valueA = v;\n }\n }\n\n override render() {\n // No tooltip on the inner slider: the editable-number already shows the\n // value, so a slider tooltip would be redundant.\n return html`\n <div class=\"wrap ${this._isMini ? `mini` : ``}\">\n ${this._renderEditableNumber()}\n <ixfx-slider-input\n class=\"slider\"\n ?lighttouch=${this.lighttouch}\n ?disabled=${this.disabled}\n ?swipeable=${this.swipeable}\n .valueA=${this.value}\n .min=${this.min}\n .max=${this.max}\n .step=${this.step}\n .stops=${this.stops}\n .orientation=${this.orientation}\n .singleStyle=${this.singleStyle}\n .markerStyle=${this.markerStyle}\n @input=${this._handleSliderInput}\n @change=${this._handleInputChange}\n ></ixfx-slider-input>\n </div>\n `;\n }\n\n static styles: CSSResultGroup = css`\n :host {\n display: block;\n container-type: size;\n min-height: var(--min-height, 20px);\n min-width: var(--min-width, 50px);\n width: var(--width, auto);\n height: var(--height, 100px);\n }\n\n /* One focus ring for the whole control: the inner slider's own ring is\n suppressed (see ixfx-slider-input below) and re-drawn here so it wraps\n the label + slider group instead of just the track. */\n :host(:focus-within) {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n\n .wrap {\n display: flex;\n width: 100%;\n height: 100%;\n align-items: center;\n }\n\n ixfx-editable-number {\n flex-shrink: 0;\n }\n\n ixfx-slider-input {\n flex: 1;\n min-width: 0;\n /* Suppress the slider's own focus ring; the wrapper draws one around\n the whole control via :host(:focus-within) above. */\n --slider-input-svg-focus-outline: none;\n --slider-input-svg-focus-outline-offset: 0;\n }\n\n /* Default (compact): horizontal — label beside slider */\n .wrap {\n flex-direction: var(--flow, row);\n justify-content: flex-start;\n align-items: center;\n }\n\n ixfx-editable-number {\n --label-align: left;\n width: var(--label-width, 5ch);\n --label-min-width: var(--label-width, 5ch);\n /* Block fill/background variables from reaching editable-number */\n --fill-color: initial;\n --fill-opacity: initial;\n --fill-image: initial;\n }\n\n /* Vertically-stacked layout: applied when the container is tall enough\n to fit label + slider, OR when the author forces it with --flow:\n column (a style query, so an explicit --flow: column brings the\n label/slider companion rules too — not just the flex direction — and\n therefore works at any --height, not only >= 80px). */\n @container (height >= 80px) or style(--flow: column) {\n .wrap {\n flex-direction: var(--flow, column);\n /* Centre the label+slider group so any height the component is\n given beyond what the two need is split evenly above and below,\n rather than dumped into a stretched slider. */\n justify-content: center;\n align-items: center;\n }\n\n ixfx-editable-number {\n --label-align: center;\n /* Stretch (not width: 100%): in the normal stacked column this is\n visually identical (full-width centered label), but a hardcoded\n 100% width would also apply when --flow forces a row at this\n height — eating the whole row and squeezing the slider to zero. */\n align-self: stretch;\n width: auto;\n }\n\n ixfx-slider-input {\n width: 100%;\n /* Don't stretch to fill the column. The slider paints its bar\n thickness as a fraction of the height it's handed, so a fat\n lane-track-width in a tall slot leaves most of that slot as\n dead space. Cap it to a sensible band (override with\n --slider-thickness) and let the centred group absorb the rest. */\n flex: 0 1 auto;\n height: var(--slider-thickness, 2.5em);\n max-height: 100%;\n }\n }\n\n /* Mini mode: slider fills the full component */\n .wrap.mini {\n gap: 0;\n }\n\n .wrap.mini ixfx-slider-input {\n width: 100%;\n height: 100%;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-labelled-slider-input': LabelledSliderInput;\n }\n}\n"],"mappings":"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"}
package/dist/led.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"led.d.ts","names":[],"sources":["../src/led/led.ts"],"mappings":";;KAIY;cAGC,mBAAmB;;EAE9B;EAGA;EAGA;EAGA;;;;;;;;;EAWA,MAAM;;;;;EAON;EAGA;;EAIA;;EAIA;;;;;;EAQA;EAWA,WAAW,mBAAmB;EA+C9B;;;;;;;EAYA;YA6EU,wBAAM;SAIT,sBAAM;;QAwEP;YACI;IACR,YAAY"}
package/dist/led.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"led.js","names":["#pulseFrom","#pulsePeak","#pulseStart","#pulseLevel","#pulseRaf","#pulseTick","#appliedMode","#onModeChange","#updateBlinking","#stopBlinking","#stopPulse","#blinkInterval","customElement"],"sources":["../src/led/led.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\n\nexport type LedMode = `brightness` | `blink` | `pulse`;\n\n@customElement(`ixfx-led`)\nexport class LedElement extends LitElement {\n @property({ type: Number })\n value = 0;\n\n @property({ type: Boolean, attribute: `lit`, reflect: true })\n lit = false;\n\n @property({ type: String })\n color = `oklch(50% 0.15 25)`;\n\n @property({ type: Boolean, attribute: `glow`, reflect: true })\n glow = false;\n\n /**\n * Operating mode:\n * - `brightness` (default): {@link value} sets the LED brightness directly\n * - `blink`: LED blinks on/off every {@link rate} milliseconds (this mode\n * is what the legacy `blinking` attribute now selects)\n * - `pulse`: LED sits unlit until {@link pulse} is called, which fires an\n * attack/release envelope up to {@link value} and back down\n */\n @property({ type: String, reflect: true })\n mode: LedMode = `brightness`;\n\n /**\n * Legacy alias for `mode=\"blink\"`. Setting `blinking` switches {@link mode}\n * to `blink`; clearing it returns to `brightness`.\n */\n @property({ type: Boolean, attribute: `blinking`, reflect: true })\n blinking = false;\n\n @property({ type: Number, attribute: `rate` })\n rate = 500;\n\n /** Pulse-mode attack time in milliseconds (0 → instant). */\n @property({ type: Number, attribute: `attack-time` })\n attackTime = 40;\n\n /** Pulse-mode release/decay time in milliseconds (0 → instant). */\n @property({ type: Number, attribute: `release-time` })\n releaseTime = 400;\n\n /**\n * Pulse-mode retrigger behaviour. When set, each {@link pulse} call restarts\n * the envelope from 0. When unset (default), the attack ramps from wherever\n * the envelope currently sits, so a retrigger mid-decay is continuous.\n */\n @property({ type: Boolean, attribute: `pulse-retrigger` })\n pulseRetrigger = false;\n\n #blinkInterval: number | undefined;\n #appliedMode: LedMode = `brightness`;\n\n #pulseRaf: number | undefined;\n #pulseStart = 0;\n #pulsePeak = 0;\n #pulseFrom = 0;\n #pulseLevel = 0;\n\n willUpdate(changedProperties: Map<string, unknown>) {\n // `blinking` is a compatibility alias for mode=\"blink\".\n if (changedProperties.has(`blinking`)) {\n if (this.blinking) {\n this.mode = `blink`;\n } else if (this.mode === `blink`) {\n this.mode = `brightness`;\n }\n }\n\n // Handle a mode change (including one triggered by `blinking`, above, in\n // this same update). `#appliedMode` is compared directly rather than via\n // `changedProperties` so a same-pass change is still caught.\n if (this.mode !== this.#appliedMode) {\n this.#appliedMode = this.mode;\n this.#onModeChange();\n }\n\n if (changedProperties.has(`lit`)) {\n // Map `lit` onto `value`, but don't let the initial (undefined -> false)\n // change clobber an explicit `value` attribute.\n if (this.lit) {\n this.value = 1;\n } else if (changedProperties.get(`lit`) !== undefined) {\n this.value = 0;\n }\n }\n\n if (changedProperties.has(`color`)) {\n this.style.setProperty(`--_color-attr`, this.color);\n }\n\n // In pulse mode `--value` is driven by the envelope, not by `value`.\n if (\n this.mode !== `pulse`\n && (changedProperties.has(`value`) || changedProperties.has(`lit`))\n ) {\n this.style.setProperty(`--value`, String(this.value));\n }\n\n if (changedProperties.has(`rate`)) {\n this.#updateBlinking();\n const transitionMs = this.rate < 300 ? this.rate * 0.5 : 150;\n this.style.setProperty(`--transition-duration`, `${transitionMs}ms`);\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#stopBlinking();\n this.#stopPulse();\n }\n\n /**\n * Pulse-mode trigger: lights the LED to {@link value} using an attack/release\n * envelope, then decays back to unlit. Calling again restarts the envelope\n * (from 0 if {@link pulseRetrigger} is set, otherwise from the current level).\n * No-op unless {@link mode} is `pulse`.\n */\n pulse() {\n if (this.mode !== `pulse`)\n return;\n this.#pulsePeak = this.value;\n this.#pulseFrom = this.pulseRetrigger ? 0 : this.#pulseLevel;\n this.#pulseStart = performance.now();\n if (this.#pulseRaf === undefined) {\n this.#pulseRaf = requestAnimationFrame(this.#pulseTick);\n }\n }\n\n #onModeChange() {\n this.#stopPulse();\n this.#pulseLevel = 0;\n this.blinking = this.mode === `blink`;\n this.#updateBlinking();\n this.style.setProperty(\n `--value`,\n this.mode === `pulse` ? `0` : String(this.value),\n );\n }\n\n #pulseTick = (now: number) => {\n const attack = Math.max(0, this.attackTime);\n const release = Math.max(0, this.releaseTime);\n const from = this.#pulseFrom;\n const peak = this.#pulsePeak;\n const elapsed = now - this.#pulseStart;\n\n let level: number;\n if (attack > 0 && elapsed < attack) {\n // Ramp from the envelope's starting level up to the peak.\n level = from + (peak - from) * (elapsed / attack);\n } else if (elapsed < attack + release) {\n level = release > 0 ? peak * (1 - (elapsed - attack) / release) : 0;\n } else {\n level = 0;\n }\n level = Math.max(0, Math.min(Math.max(from, peak), level));\n this.#pulseLevel = level;\n this.style.setProperty(`--value`, String(level));\n\n if (elapsed < attack + release) {\n this.#pulseRaf = requestAnimationFrame(this.#pulseTick);\n } else {\n this.#pulseRaf = undefined;\n this.#pulseLevel = 0;\n }\n };\n\n #stopPulse() {\n if (this.#pulseRaf !== undefined) {\n cancelAnimationFrame(this.#pulseRaf);\n this.#pulseRaf = undefined;\n }\n }\n\n #updateBlinking() {\n const wasBlinking = this.#blinkInterval !== undefined;\n this.#stopBlinking();\n if (this.mode === `blink` && this.rate > 0) {\n this.#blinkInterval = window.setInterval(() => {\n this.value = this.value === 0 ? 1 : 0;\n }, this.rate);\n } else if (wasBlinking || this.mode === `blink`) {\n // Leaving blink mode (or blink with rate 0): settle to off.\n this.value = 0;\n }\n }\n\n #stopBlinking() {\n if (this.#blinkInterval !== undefined) {\n clearInterval(this.#blinkInterval);\n this.#blinkInterval = undefined;\n }\n }\n\n protected render() {\n return html`<div part=\"circle\"></div>`;\n }\n\n static styles = css`\n :host {\n --_size: var(--size, 1ex);\n /* Resolved colour: explicit --colour wins, then the \\`color\\` attribute, then a default. */\n --_colour: var(--colour, var(--_color-attr, oklch(50% 0.15 25)));\n display: inline-block;\n min-width: 1ex;\n min-height: 1ex;\n width: var(--_size);\n height: var(--_size);\n vertical-align: middle;\n }\n\n div {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: color-mix(in oklch, var(--_colour), white calc((1 - var(--value, 0)) * 50%));\n transition: background var(--transition-duration, 150ms) ease-out;\n }\n\n /* Glow: a more realistic domed LED with a specular highlight and coloured bloom. */\n :host([glow]) {\n /* Body darkens toward black as the LED dims, so an unlit LED reads as a dark dome. */\n --_body: color-mix(in oklch, var(--_colour), black calc((1 - var(--value, 0)) * 60%));\n overflow: visible;\n }\n\n :host([glow]) div {\n background:\n radial-gradient(circle at 32% 28%,\n color-mix(in oklch, var(--_body), white 55%) 0%,\n var(--_body) 45%,\n color-mix(in oklch, var(--_body), black 32%) 100%);\n box-shadow:\n /* inner rim shading for depth */\n inset 0 calc(var(--_size) * -0.1) calc(var(--_size) * 0.18)\n color-mix(in oklch, var(--_body), black 45%),\n inset 0 calc(var(--_size) * 0.08) calc(var(--_size) * 0.14)\n color-mix(in oklch, var(--_body), white 25%),\n /* coloured bloom, scaled by value so it only glows when lit */\n 0 0 calc(var(--_size) * 0.6 * var(--value, 0)) calc(var(--_size) * 0.12 * var(--value, 0))\n var(--_colour),\n 0 0 calc(var(--_size) * 1.7 * var(--value, 0)) calc(var(--_size) * 0.5 * var(--value, 0))\n color-mix(in oklch, var(--_colour), transparent 45%);\n transition:\n background var(--transition-duration, 150ms) ease-out,\n box-shadow var(--transition-duration, 150ms) ease-out;\n }\n\n /* Specular highlight blob near the top-left. */\n :host([glow]) div::after {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: 50%;\n background: radial-gradient(ellipse 55% 45% at 30% 22%,\n color-mix(in oklch, white, transparent 10%) 0%,\n transparent 60%);\n pointer-events: none;\n }\n\n /* Pulse mode animates --value frame-by-frame, so drop the CSS transition\n that would otherwise smear the envelope. Placed last to win over the\n glow rule for elements matching both. */\n :host([mode=\"pulse\"]) div {\n transition: none;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-led\": LedElement;\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-group-header.d.ts","names":[],"sources":["../src/list-group-header/list-group-header.ts"],"mappings":";;;;;;;;cAWa,+BAA+B;SAC1B,sBAAM;EAuEtB;EAGA;EAGA;EAGA;EAES;YAKU;YAKA,wBAAM;;QAUnB;YACI;IACR,0BAA0B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-group-header.js","names":["customElement"],"sources":["../src/list-group-header/list-group-header.ts"],"sourcesContent":["import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\n/**\n * Collapsible group header used by `ixfx-grid-list` and `ixfx-detail-list`.\n * Look matches the group rows of `ixfx-data-grid`: caret, bold label, muted\n * count, and a hairline divider. The host list owns the click handling.\n */\n@customElement(`ixfx-list-group-header`)\nexport class ListGroupHeaderElement extends LitElement {\n static override styles = css`\n :host {\n --_height: var(--list-group-header-height, 28px);\n --_border: var(--list-group-header-border, var(--border));\n\n display: flex;\n align-items: center;\n gap: var(--space-s);\n box-sizing: border-box;\n min-height: var(--_height);\n padding: 0 var(--space-s);\n background: transparent;\n color: var(--list-group-header-text, var(--surface-3-text));\n border-bottom: 1px solid var(--_border);\n font-weight: 600;\n cursor: pointer;\n user-select: none;\n }\n\n .caret {\n display: inline-flex;\n transition: transform 0.15s;\n }\n\n :host([collapsed]) .caret {\n transform: rotate(-90deg);\n }\n\n .count {\n opacity: 0.6;\n font-weight: 400;\n font-size: 0.9em;\n }\n\n .label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n }\n\n .divider {\n flex: 1;\n height: 1px;\n background: var(--_border);\n margin-left: var(--space-s);\n }\n\n /* Single-row (grid-list \\`row\\` orientation) layout: a narrow column cell. */\n :host([orientation=\"vertical\"]) {\n flex-direction: column;\n justify-content: flex-start;\n padding: var(--space-s) 0;\n border-bottom: 0;\n border-right: 1px solid var(--_border);\n min-height: 0;\n }\n\n :host([orientation=\"vertical\"]) .divider {\n width: 1px;\n height: auto;\n margin-left: 0;\n margin-top: var(--space-s);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .caret { transition: none; }\n }\n `;\n\n @property({ type: String, reflect: true })\n label = ``;\n\n @property({ type: Number, reflect: true })\n count = 0;\n\n @property({ type: Boolean, reflect: true })\n collapsed = false;\n\n @property({ type: String, reflect: true })\n orientation: `horizontal` | `vertical` = `horizontal`;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute(`role`, `button`);\n }\n\n protected override willUpdate(): void {\n this.setAttribute(`aria-expanded`, this.collapsed ? `false` : `true`);\n this.setAttribute(`aria-label`, `${this.label}, ${this.count} ${this.count === 1 ? `item` : `items`}`);\n }\n\n protected override render() {\n return html`\n <span class=\"caret\"><ixfx-icon name=\"chevron-down\" size=\"12\"></ixfx-icon></span>\n <span class=\"label\" part=\"label\">${this.label}</span>\n <span class=\"count\" part=\"count\">(${this.count})</span>\n <span class=\"divider\" part=\"divider\"></span>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-list-group-header': ListGroupHeaderElement;\n }\n}\n"],"mappings":";;;;;AAWO,IAAM,yBAAN,MAAM,+BAA+B,WAAW;;;EAwE7C,KAAA,QAAA;EAGA,KAAA,QAAA;EAGI,KAAA,YAAA;EAG6B,KAAA,cAAA;;;EAhFhB,KAAA,SAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkF5B,oBAAmC;EACjC,MAAM,kBAAkB;EACxB,KAAK,aAAa,QAAQ,QAAQ;CACpC;CAEA,aAAsC;EACpC,KAAK,aAAa,iBAAiB,KAAK,YAAY,UAAU,MAAM;EACpE,KAAK,aAAa,cAAc,GAAG,KAAK,MAAM,IAAI,KAAK,MAAM,GAAG,KAAK,UAAU,IAAI,SAAS,SAAS;CACvG;CAEA,SAA4B;EAC1B,OAAO,IAAI;;yCAE0B,KAAK,MAAM;0CACV,KAAK,MAAM;;;CAGnD;AACF;AA9BG,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,SAAA,KAAA,CAAA;AAGxC,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,SAAA,KAAA,CAAA;AAGxC,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,aAAA,KAAA,CAAA;AAGzC,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,uBAAA,WAAA,eAAA,KAAA,CAAA;AAjF1CA,yBAAAA,WAAAA,CAAAA,kBAAc,wBAAwB,CAAA,GAAA,sBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-item-animation-BUoEKi5s.js","names":[],"sources":["../src/interaction/list-item-animation.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * Shared insertion / removal animation for the list & tree components.\n *\n * Two flavours, because the components split into two layout families:\n *\n * - **Flow layouts** (`ixfx-vertical-list`, `ixfx-detail-list`, `ixfx-tree-*`) —\n * rows sit in normal flow, so a new row can collapse in from zero height and a\n * leaving row can collapse back to zero, and the rows around it slide to make\n * or close the gap for free. Use {@link animateListItemIn} /\n * {@link animateListItemOut} (Web Animations API, exact measured sizes).\n *\n * - **Virtualised layouts** (`ixfx-grid-list`, `ixfx-data-grid`) — rows are\n * absolutely positioned (`transform` / `top`), so collapsing a row's box moves\n * nothing. Those components instead fade the entering / leaving row with the\n * {@link listItemFadeKeyframes} keyframes and slide the survivors by\n * transitioning their position for a short window after the change.\n *\n * Everything here is a no-op under `prefers-reduced-motion: reduce`.\n */\n\n/** Default duration (ms) for both flavours; overridable per call / per component. */\nexport const LIST_ITEM_MOTION_MS = 200;\n\nexport function prefersReducedMotion(): boolean {\n return (\n typeof window !== `undefined`\n && typeof window.matchMedia === `function`\n && window.matchMedia(`(prefers-reduced-motion: reduce)`).matches\n );\n}\n\n/**\n * Opacity keyframes for the virtualised components. Each one adds its own\n * one-line rule binding `.<row>.ixfx-item-entering` / `.ixfx-item-leaving` to\n * these, plus a `prefers-reduced-motion` guard on its own selectors.\n */\nexport const listItemFadeKeyframes = css`\n @keyframes ixfx-list-item-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes ixfx-list-item-out {\n from { opacity: 1; }\n to { opacity: 0; }\n }\n`;\n\nexport interface ListItemMotionOptions {\n /**\n * Animation duration in ms. When omitted, the element's\n * `--ixfx-list-item-move-duration` custom property is used if set (accepts\n * `ms` or `s`), otherwise {@link LIST_ITEM_MOTION_MS}.\n */\n duration?: number;\n /** Which axis collapses — `block` (height, default) or `inline` (width). */\n axis?: `block` | `inline`;\n easing?: string;\n}\n\nfunction measure(el: HTMLElement, axis: `block` | `inline`): number {\n const rect = el.getBoundingClientRect();\n return axis === `inline` ? rect.width : rect.height;\n}\n\nfunction resolveDuration(el: HTMLElement, explicit?: number): number {\n if (explicit !== undefined)\n return explicit;\n const raw = getComputedStyle(el).getPropertyValue(`--ixfx-list-item-move-duration`).trim();\n if (raw) {\n const n = Number.parseFloat(raw);\n if (!Number.isNaN(n))\n return raw.endsWith(`ms`) ? n : raw.endsWith(`s`) ? n * 1000 : n;\n }\n return LIST_ITEM_MOTION_MS;\n}\n\nfunction collapsedFrame(axis: `block` | `inline`): Keyframe {\n const prop = axis === `inline` ? `width` : `height`;\n const minProp = axis === `inline` ? `minWidth` : `minHeight`;\n return { [prop]: `0px`, [minProp]: `0px`, opacity: 0, overflow: `hidden` };\n}\n\nfunction fullFrame(size: number, axis: `block` | `inline`): Keyframe {\n const prop = axis === `inline` ? `width` : `height`;\n const minProp = axis === `inline` ? `minWidth` : `minHeight`;\n return { [prop]: `${size}px`, [minProp]: `0px`, opacity: 1, overflow: `hidden` };\n}\n\n/**\n * Collapse + fade `el` in from nothing to its natural size. Call it just after\n * the element has been inserted (it must already be laid out at full size so it\n * can be measured). No-op under reduced motion.\n */\nexport function animateListItemIn(el: HTMLElement, options: ListItemMotionOptions = {}): Animation | undefined {\n if (prefersReducedMotion())\n return undefined;\n const { axis = `block`, easing = `ease` } = options;\n const duration = resolveDuration(el, options.duration);\n const size = measure(el, axis);\n if (size <= 0)\n return undefined;\n return el.animate([collapsedFrame(axis), fullFrame(size, axis)], { duration, easing });\n}\n\n/**\n * Result of {@link animateListItemOut}: a promise that resolves once the\n * animation finishes, carrying the underlying `Animation` handle (if any) so\n * callers can `cancel()` superseded work. Awaiting / `.then()` behaves like\n * the previous `Promise<void>` return type.\n */\nexport type ListItemOutResult = Promise<void> & {\n /** The running collapse animation, or `undefined` under reduced motion / zero size. */\n animation: Animation | undefined;\n};\n\nfunction outResult(finished: Promise<void>, animation: Animation | undefined): ListItemOutResult {\n return Object.assign(finished, { animation });\n}\n\n/**\n * Start the collapse + fade-out animation for `el` and return the handle.\n * Returns `undefined` when no animation was started (reduced motion or zero\n * size). The caller owns the handle and must `cancel()` it if the removal is\n * reversed — a retained `fill: forwards` frame otherwise keeps overriding the\n * element's ordinary CSS indefinitely.\n */\nexport function startListItemOutAnimation(el: HTMLElement, options: ListItemMotionOptions = {}): Animation | undefined {\n if (prefersReducedMotion())\n return undefined;\n const { axis = `block`, easing = `ease` } = options;\n const duration = resolveDuration(el, options.duration);\n const size = measure(el, axis);\n if (size <= 0)\n return undefined;\n return el.animate([fullFrame(size, axis), collapsedFrame(axis)], {\n duration,\n easing,\n fill: `forwards`,\n });\n}\n\n/**\n * Collapse + fade `el` out. Resolves once the animation finishes (or straight\n * away under reduced motion); the caller detaches the element after. The final\n * collapsed state is held (`fill: forwards`) so there's no flash back to full\n * size in the gap before removal.\n *\n * The returned promise carries an `.animation` handle. If the removal is\n * reversed (the same key becomes visible again), cancel that handle so its\n * filled final frame stops overriding the reused element's style.\n */\nexport function animateListItemOut(el: HTMLElement, options: ListItemMotionOptions = {}): ListItemOutResult {\n const animation = startListItemOutAnimation(el, options);\n if (!animation)\n return outResult(Promise.resolve(), undefined);\n const finished = animation.finished.then(() => undefined, () => undefined);\n return outResult(finished, animation);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,sBAAsB;AAEnC,SAAgB,uBAAgC;CAC9C,OACE,OAAO,WAAW,eACf,OAAO,OAAO,eAAe,cAC7B,OAAO,WAAW,kCAAkC,CAAC,CAAC;AAE7D;;;;;;AAOA,MAAa,wBAAwB,GAAG;;;;;;;;;;AAuBxC,SAAS,QAAQ,IAAiB,MAAkC;CAClE,MAAM,OAAO,GAAG,sBAAsB;CACtC,OAAO,SAAS,WAAW,KAAK,QAAQ,KAAK;AAC/C;AAEA,SAAS,gBAAgB,IAAiB,UAA2B;CACnE,IAAI,aAAa,KAAA,GACf,OAAO;CACT,MAAM,MAAM,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,gCAAgC,CAAC,CAAC,KAAK;CACzF,IAAI,KAAK;EACP,MAAM,IAAI,OAAO,WAAW,GAAG;EAC/B,IAAI,CAAC,OAAO,MAAM,CAAC,GACjB,OAAO,IAAI,SAAS,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,IAAI,IAAI,MAAO;CACnE;CACA,OAAA;AACF;AAEA,SAAS,eAAe,MAAoC;CAC1D,MAAM,OAAO,SAAS,WAAW,UAAU;CAC3C,MAAM,UAAU,SAAS,WAAW,aAAa;CACjD,OAAO;GAAG,OAAO;GAAQ,UAAU;EAAO,SAAS;EAAG,UAAU;CAAS;AAC3E;AAEA,SAAS,UAAU,MAAc,MAAoC;CACnE,MAAM,OAAO,SAAS,WAAW,UAAU;CAC3C,MAAM,UAAU,SAAS,WAAW,aAAa;CACjD,OAAO;GAAG,OAAO,GAAG,KAAK;GAAM,UAAU;EAAO,SAAS;EAAG,UAAU;CAAS;AACjF;;;;;;AAOA,SAAgB,kBAAkB,IAAiB,UAAiC,CAAC,GAA0B;CAC7G,IAAI,qBAAqB,GACvB,OAAO,KAAA;CACT,MAAM,EAAE,OAAO,SAAS,SAAS,WAAW;CAC5C,MAAM,WAAW,gBAAgB,IAAI,QAAQ,QAAQ;CACrD,MAAM,OAAO,QAAQ,IAAI,IAAI;CAC7B,IAAI,QAAQ,GACV,OAAO,KAAA;CACT,OAAO,GAAG,QAAQ,CAAC,eAAe,IAAI,GAAG,UAAU,MAAM,IAAI,CAAC,GAAG;EAAE;EAAU;CAAO,CAAC;AACvF;AAaA,SAAS,UAAU,UAAyB,WAAqD;CAC/F,OAAO,OAAO,OAAO,UAAU,EAAE,UAAU,CAAC;AAC9C;;;;;;;;AASA,SAAgB,0BAA0B,IAAiB,UAAiC,CAAC,GAA0B;CACrH,IAAI,qBAAqB,GACvB,OAAO,KAAA;CACT,MAAM,EAAE,OAAO,SAAS,SAAS,WAAW;CAC5C,MAAM,WAAW,gBAAgB,IAAI,QAAQ,QAAQ;CACrD,MAAM,OAAO,QAAQ,IAAI,IAAI;CAC7B,IAAI,QAAQ,GACV,OAAO,KAAA;CACT,OAAO,GAAG,QAAQ,CAAC,UAAU,MAAM,IAAI,GAAG,eAAe,IAAI,CAAC,GAAG;EAC/D;EACA;EACA,MAAM;CACR,CAAC;AACH;;;;;;;;;;;AAYA,SAAgB,mBAAmB,IAAiB,UAAiC,CAAC,GAAsB;CAC1G,MAAM,YAAY,0BAA0B,IAAI,OAAO;CACvD,IAAI,CAAC,WACH,OAAO,UAAU,QAAQ,QAAQ,GAAG,KAAA,CAAS;CAE/C,OAAO,UADU,UAAU,SAAS,WAAW,KAAA,SAAiB,KAAA,CACxC,GAAG,SAAS;AACtC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-native-drag-controller-B9xO0XWn.js","names":["#host","#config","#dragging","#bind","#observer","#unbind","#renderRoot","#boundRoot","#onDragStart","#onDragEnd","#boundHost","#seenDragStarts"],"sources":["../src/interaction/list-drag-preview-default.ts","../src/interaction/list-native-drag-controller.ts"],"sourcesContent":["import type { ListDragEntry, ListDragPreview, ListDragPreviewContext } from './list-drag-types.js';\n\nconst CARD_DEFAULT = 72;\nconst CARD_MIN = 48;\nconst CARD_MAX = 96;\nconst LIST_WIDTH = 220;\nconst LIST_MAX_ROWS = 5;\nconst MAX_CANVAS_DIM = 1024;\n\nfunction cssVar(style: CSSStyleDeclaration, name: string, fallback: string): string {\n try {\n const value = style.getPropertyValue(name)?.trim();\n return value || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction fontOf(style: CSSStyleDeclaration): string {\n try {\n const font = style.font?.trim();\n if (font)\n return font;\n } catch {\n // Ignore.\n }\n return `12px system-ui, sans-serif`;\n}\n\n/** Caption for a drag entry — explicit element labels win, then data values, then generic element text, then the key. */\nexport function captionForEntry(entry: ListDragEntry<unknown>): string {\n const el = entry.element ?? (entry.item instanceof Element ? entry.item : undefined);\n if (el) {\n const labelled = el.getAttribute(`data-label`)\n ?? el.querySelector(`[data-grid-list-caption]`)?.textContent?.trim()\n ?? el.getAttribute(`data-search-label`)\n ?? el.querySelector(`.cell`)?.textContent?.trim();\n if (labelled)\n return labelled.slice(0, 80);\n }\n const item = entry.item;\n if (typeof item === `string` && item.length > 0)\n return item.slice(0, 80);\n if (item !== null && typeof item === `object` && !(item instanceof Element)) {\n const record = item as Record<string, unknown>;\n for (const field of [`label`, `name`, `title`, `text`]) {\n const value = record[field];\n if (typeof value === `string` && value.length > 0)\n return value.slice(0, 80);\n }\n }\n // Generic element text last: a data-backed virtual cell (`.cell`) contains\n // both the adapter output and the caption band, so its raw `textContent`\n // would duplicate the caption — prefer the data-derived caption above.\n if (el) {\n const text = el.textContent?.trim();\n if (text)\n return text.slice(0, 80);\n }\n return entry.key;\n}\n\nfunction glyphFor(caption: string): string {\n const first = caption.trim().at(0);\n return first ? first.toLocaleUpperCase() : `?`;\n}\n\nfunction hasUsableDimensions(source: CanvasImageSource): boolean {\n if (source instanceof HTMLImageElement || source instanceof HTMLVideoElement || source instanceof HTMLCanvasElement) {\n return source.clientWidth > 0 && source.clientHeight > 0;\n }\n if (source instanceof ImageBitmap) {\n return source.width > 0 && source.height > 0;\n }\n if (`naturalWidth` in source && `naturalHeight` in source) {\n const sized = source as unknown as { naturalWidth: number; naturalHeight: number };\n return sized.naturalWidth > 0 && sized.naturalHeight > 0;\n }\n return true;\n}\n\nfunction sourceImage(entry: ListDragEntry<unknown>, resolveDragPreviewSource?: (entry: ListDragEntry<unknown>) => CanvasImageSource | undefined): CanvasImageSource | undefined {\n if (resolveDragPreviewSource) {\n try {\n const source = resolveDragPreviewSource(entry);\n if (source && hasUsableDimensions(source))\n return source;\n } catch {\n // resolver threw — fall through to DOM lookup\n }\n }\n return decodedImage(entry);\n}\n\n/** A decoded `<img>` ready for `drawImage`, if the entry's element has one. */\nfunction decodedImage(entry: ListDragEntry<unknown>): HTMLImageElement | undefined {\n const scope = entry.element ?? (entry.item instanceof Element ? entry.item : undefined);\n if (!scope || typeof scope.querySelector !== `function`)\n return undefined;\n // The entry element itself may be an <img> (e.g. slotted image content).\n if (scope instanceof HTMLImageElement) {\n if (scope.complete && scope.naturalWidth > 0)\n return scope;\n return undefined;\n }\n try {\n const img = scope.querySelector(`img`);\n if (img instanceof HTMLImageElement && img.complete && img.naturalWidth > 0)\n return img;\n } catch {\n // Ignore.\n }\n return undefined;\n}\n\nfunction cardSize(metrics: ListDragPreviewContext<unknown>[`metrics`]): number {\n if (metrics.itemSize !== undefined && Number.isFinite(metrics.itemSize))\n return Math.max(CARD_MIN, Math.min(CARD_MAX, Math.round(metrics.itemSize)));\n return CARD_DEFAULT;\n}\n\nfunction rowHeight(metrics: ListDragPreviewContext<unknown>[`metrics`]): number {\n const raw = metrics.rowHeight;\n if (raw !== undefined && Number.isFinite(raw))\n return Math.max(24, Math.min(36, Math.round(raw)));\n return 28;\n}\n\nfunction thumbCell(doc: Document, caption: string, img: CanvasImageSource | undefined, size: number): HTMLElement {\n const well = doc.createElement(`div`);\n well.setAttribute(`data-thumb`, ``);\n well.style.cssText = `width:${size}px;height:${size}px;border-radius:4px;overflow:hidden;`\n + `background:var(--surface-5, rgba(128,128,128,0.25));flex-shrink:0;display:flex;`\n + `align-items:center;justify-content:center;font-size:${Math.round(size * 0.4)}px;font-weight:600;`;\n if (img instanceof HTMLImageElement) {\n try {\n const clone = img.cloneNode(true) as HTMLImageElement;\n clone.style.cssText = `width:100%;height:100%;object-fit:cover;`;\n clone.removeAttribute(`id`);\n well.appendChild(clone);\n } catch {\n well.textContent = glyphFor(caption);\n }\n } else {\n well.textContent = glyphFor(caption);\n }\n return well;\n}\n\nfunction buildCardsElement(ctx: ListDragPreviewContext<unknown>, captions: string[], images: Array<CanvasImageSource | undefined>): HTMLElement {\n const doc = document;\n const size = cardSize(ctx.metrics);\n const gap = 6;\n const pad = 8;\n const root = doc.createElement(`div`);\n root.setAttribute(`data-preview`, `cards`);\n root.setAttribute(`part`, `drag-preview`);\n root.style.cssText = `position:fixed;top:-9999px;left:-9999px;display:flex;flex-direction:row;gap:${gap}px;`\n + `padding:${pad}px;background:var(--surface-4, #333);color:var(--surface-4-text, #fff);`\n + `border:1px solid var(--border-subtle, #555);border-radius:var(--radius-m, 8px);`\n + `box-shadow:0 4px 16px rgba(0,0,0,0.3);font-family:system-ui,sans-serif;font-size:11px;`\n + `max-width:320px;z-index:999999;pointer-events:none;`;\n const n = ctx.selected.length;\n for (let i = 0; i < n; i++) {\n const card = doc.createElement(`div`);\n card.setAttribute(`data-card`, ``);\n card.style.cssText = `display:flex;flex-direction:column;gap:4px;align-items:center;width:${size}px;`;\n card.appendChild(thumbCell(doc, captions[i], images[i], Math.round(size * 0.72)));\n const label = doc.createElement(`span`);\n label.setAttribute(`data-caption`, ``);\n label.style.cssText = `max-width:${size}px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:0.9;`;\n label.textContent = captions[i];\n card.appendChild(label);\n root.appendChild(card);\n }\n return root;\n}\n\nfunction buildListElement(\n ctx: ListDragPreviewContext<unknown>,\n captions: string[],\n images: Array<CanvasImageSource | undefined>,\n): HTMLElement {\n const doc = document;\n const rh = rowHeight(ctx.metrics);\n const thumb = Math.round(rh * 0.78);\n const root = doc.createElement(`div`);\n root.setAttribute(`data-preview`, `list`);\n root.setAttribute(`part`, `drag-preview`);\n root.style.cssText = `position:fixed;top:-9999px;left:-9999px;display:flex;flex-direction:column;gap:4px;`\n + `padding:8px;background:var(--surface-4, #333);color:var(--surface-4-text, #fff);`\n + `border:1px solid var(--border-subtle, #555);border-radius:var(--radius-m, 8px);`\n + `box-shadow:0 4px 16px rgba(0,0,0,0.3);font-family:system-ui,sans-serif;font-size:12px;`\n + `width:${LIST_WIDTH}px;max-width:${LIST_WIDTH}px;z-index:999999;pointer-events:none;`;\n const header = doc.createElement(`div`);\n header.setAttribute(`data-header`, ``);\n header.style.cssText = `font-weight:600;padding-bottom:4px;border-bottom:1px solid var(--border-subtle, #555);margin-bottom:4px;`;\n header.textContent = `${ctx.selected.length} items`;\n root.appendChild(header);\n for (let i = 0; i < Math.min(LIST_MAX_ROWS, captions.length); i++) {\n const row = doc.createElement(`div`);\n row.setAttribute(`data-row`, ``);\n row.style.cssText = `display:flex;align-items:center;gap:6px;height:${rh}px;overflow:hidden;`;\n row.appendChild(thumbCell(doc, captions[i], images[i], thumb));\n const label = doc.createElement(`span`);\n label.setAttribute(`data-caption`, ``);\n label.style.cssText = `flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;`;\n label.textContent = captions[i];\n row.appendChild(label);\n root.appendChild(row);\n }\n if (captions.length > LIST_MAX_ROWS) {\n const more = doc.createElement(`div`);\n more.setAttribute(`data-more`, ``);\n more.style.cssText = `opacity:0.6;text-align:center;`;\n more.textContent = `+${captions.length - LIST_MAX_ROWS} more`;\n root.appendChild(more);\n }\n return root;\n}\n\ntype Palette = {\n bg: string;\n fg: string;\n subtle: string;\n accent: string;\n radius: number;\n font: string;\n};\n\nfunction paletteOf(style: CSSStyleDeclaration): Palette {\n const bg = cssVar(style, `--surface-4`, `#333333`);\n const fg = cssVar(style, `--surface-4-text`, `#ffffff`);\n const subtle = cssVar(style, `--border-subtle`, `#555555`);\n const accent = cssVar(style, `--accent`, `#4da3ff`);\n const radiusRaw = cssVar(style, `--radius-m`, `8`);\n const radius = Number.parseFloat(radiusRaw) || 8;\n return { bg, fg, subtle, accent, radius, font: fontOf(style) };\n}\n\nfunction fitCanvas(canvas: HTMLCanvasElement, cssW: number, cssH: number): { scale: number; dpr: number } {\n const dpr = Math.max(1, Math.min(3, (typeof devicePixelRatio === `number` && devicePixelRatio > 0) ? devicePixelRatio : 1));\n let scale = dpr;\n // Bound the backing store so huge selections cannot allocate unbounded canvases.\n const maxScaleW = MAX_CANVAS_DIM / Math.max(1, cssW);\n const maxScaleH = MAX_CANVAS_DIM / Math.max(1, cssH);\n scale = Math.min(scale, maxScaleW, maxScaleH);\n canvas.width = Math.max(1, Math.round(cssW * scale));\n canvas.height = Math.max(1, Math.round(cssH * scale));\n canvas.style.width = `${cssW}px`;\n canvas.style.height = `${cssH}px`;\n return { scale, dpr: scale };\n}\n\nfunction roundRectPath(context: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const radius = Math.max(0, Math.min(r, w / 2, h / 2));\n if (typeof context.roundRect === `function`) {\n context.beginPath();\n context.roundRect(x, y, w, h, radius);\n return;\n }\n context.beginPath();\n context.moveTo(x + radius, y);\n context.arcTo(x + w, y, x + w, y + h, radius);\n context.arcTo(x + w, y + h, x, y + h, radius);\n context.arcTo(x, y + h, x, y, radius);\n context.arcTo(x, y, x + w, y, radius);\n context.closePath();\n}\n\nfunction paintCards(\n context: CanvasRenderingContext2D,\n scale: number,\n palette: Palette,\n captions: string[],\n images: Array<CanvasImageSource | undefined>,\n size: number,\n cssW: number,\n cssH: number,\n): void {\n context.save();\n context.scale(scale, scale);\n roundRectPath(context, 0, 0, cssW, cssH, palette.radius);\n context.fillStyle = palette.bg;\n context.fill();\n context.strokeStyle = palette.subtle;\n context.lineWidth = 1;\n context.stroke();\n context.clip();\n\n const gap = 6;\n const pad = 8;\n const wellSize = Math.round(size * 0.72);\n context.font = palette.font;\n context.textBaseline = `middle`;\n for (let i = 0; i < captions.length; i++) {\n const x = pad + i * (size + gap);\n const wellX = x + (size - wellSize) / 2;\n const wellY = pad;\n roundRectPath(context, wellX, wellY, wellSize, wellSize, 4);\n context.fillStyle = palette.subtle;\n context.globalAlpha = 0.35;\n context.fill();\n context.globalAlpha = 1;\n const img = images[i];\n if (img) {\n try {\n context.save();\n context.clip();\n context.drawImage(img, wellX, wellY, wellSize, wellSize);\n context.restore();\n } catch {\n // Placeholder below already painted.\n }\n } else {\n context.fillStyle = palette.fg;\n context.globalAlpha = 0.9;\n context.font = `600 ${Math.round(wellSize * 0.4)}px system-ui, sans-serif`;\n context.textAlign = `center`;\n context.fillText(glyphFor(captions[i]), wellX + wellSize / 2, wellY + wellSize / 2 + 1);\n context.globalAlpha = 1;\n context.textAlign = `left`;\n context.font = palette.font;\n }\n context.fillStyle = palette.fg;\n context.globalAlpha = 0.9;\n context.font = palette.font;\n const label = captions[i].length > 12 ? `${captions[i].slice(0, 11)}…` : captions[i];\n const textWidth = context.measureText(label).width;\n context.fillText(label, x + (size - Math.min(size, textWidth)) / 2, wellY + wellSize + 10, size);\n context.globalAlpha = 1;\n }\n context.restore();\n}\n\nfunction paintList(\n context: CanvasRenderingContext2D,\n scale: number,\n palette: Palette,\n captions: string[],\n images: Array<CanvasImageSource | undefined>,\n rh: number,\n cssW: number,\n cssH: number,\n): void {\n context.save();\n context.scale(scale, scale);\n roundRectPath(context, 0, 0, cssW, cssH, palette.radius);\n context.fillStyle = palette.bg;\n context.fill();\n context.strokeStyle = palette.subtle;\n context.lineWidth = 1;\n context.stroke();\n context.clip();\n\n const pad = 8;\n context.fillStyle = palette.fg;\n context.font = `600 ${palette.font}`;\n context.textBaseline = `middle`;\n context.fillText(`${captions.length} items`, pad, pad + 8, cssW - pad * 2);\n context.strokeStyle = palette.subtle;\n context.beginPath();\n context.moveTo(pad, pad + 20);\n context.lineTo(cssW - pad, pad + 20);\n context.stroke();\n\n const thumb = Math.round(rh * 0.78);\n const rows = Math.min(LIST_MAX_ROWS, captions.length);\n context.font = palette.font;\n for (let i = 0; i < rows; i++) {\n const y = pad + 24 + i * rh;\n roundRectPath(context, pad, y + (rh - thumb) / 2, thumb, thumb, 4);\n context.fillStyle = palette.subtle;\n context.globalAlpha = 0.35;\n context.fill();\n context.globalAlpha = 1;\n const img = images[i];\n if (img) {\n try {\n context.save();\n context.clip();\n context.drawImage(img, pad, y + (rh - thumb) / 2, thumb, thumb);\n context.restore();\n } catch {\n // Placeholder already painted.\n }\n } else {\n context.fillStyle = palette.fg;\n context.font = `600 ${Math.round(thumb * 0.45)}px system-ui, sans-serif`;\n context.textAlign = `center`;\n context.fillText(glyphFor(captions[i]), pad + thumb / 2, y + rh / 2 + 1);\n context.textAlign = `left`;\n context.font = palette.font;\n }\n context.fillStyle = palette.fg;\n context.globalAlpha = 0.92;\n const maxText = cssW - pad * 2 - thumb - 6;\n context.fillText(captions[i], pad + thumb + 6, y + rh / 2 + 1, Math.max(8, maxText));\n context.globalAlpha = 1;\n }\n if (captions.length > LIST_MAX_ROWS) {\n context.fillStyle = palette.fg;\n context.globalAlpha = 0.6;\n context.textAlign = `center`;\n context.fillText(`+${captions.length - LIST_MAX_ROWS} more`, cssW / 2, cssH - pad - 6, cssW - pad * 2);\n context.textAlign = `left`;\n context.globalAlpha = 1;\n }\n context.restore();\n}\n\n/**\n * Uniform built-in HTML+canvas drag preview for all four list components.\n *\n * - ≤5 selected → a row of small cards (thumbnail well + caption).\n * - >5 selected → a compact list (`N items` header, up to 5 rows, `+N more`).\n *\n * Always returns an offscreen `element` for `DataTransfer.setDragImage()` and,\n * when a 2D context is available, a DPR-aware painted `canvas` for native\n * hosts. Colours track the active theme via `ctx.hostStyle` CSS variables.\n *\n * When `ctx.resolveDragPreviewSource` is provided, it is called for each\n * selected entry before the default DOM-image lookup. The resolver must\n * return an already-loaded `CanvasImageSource` (e.g. an `<img>`, `<canvas>`,\n * `<video>`, or `ImageBitmap`) or `undefined`. Returning `undefined` or\n * throwing causes the painter to fall back to the standard\n * descendant-`<img>` inspection, and ultimately to the glyph fallback.\n */\nexport function createDefaultListDragPreview<T>(context: ListDragPreviewContext<T>): ListDragPreview {\n // Safe: the resolver is only ever invoked below with entries drawn from\n // this same context's `selected`, so the erased `T` never actually mixes\n // with another list's entries. `resolveDragPreviewSource` is contravariant\n // in `T` (it's a function parameter position), so `ListDragPreviewContext<T>`\n // isn't structurally assignable to `<unknown>` — this cast is the one place\n // that boundary is crossed for the rest of this (internally `<unknown>`-typed) file.\n const ctx = context as unknown as ListDragPreviewContext<unknown>;\n const entries = ctx.selected;\n const captions = entries.map(entry => captionForEntry(entry));\n const images = entries.map(entry => sourceImage(entry, ctx.resolveDragPreviewSource));\n const isCards = entries.length <= 5;\n\n let element: HTMLElement;\n let cssW: number;\n let cssH: number;\n if (isCards) {\n const size = cardSize(ctx.metrics);\n const gap = 6;\n const pad = 8;\n cssW = entries.length * size + Math.max(0, entries.length - 1) * gap + pad * 2;\n cssH = Math.round(size * 0.72) + 22 + pad * 2;\n element = buildCardsElement(ctx, captions, images);\n } else {\n const rh = rowHeight(ctx.metrics);\n const pad = 8;\n const rows = Math.min(LIST_MAX_ROWS, entries.length);\n const more = entries.length > LIST_MAX_ROWS ? 18 : 0;\n cssW = LIST_WIDTH + 16;\n cssH = pad * 2 + 24 + rows * rh + more;\n element = buildListElement(ctx, captions, images);\n }\n\n let canvas: HTMLCanvasElement | undefined;\n try {\n const candidate = document.createElement(`canvas`);\n const paint = candidate.getContext(`2d`);\n if (paint) {\n const { scale } = fitCanvas(candidate, cssW, cssH);\n const palette = paletteOf(ctx.hostStyle);\n if (isCards) {\n paintCards(paint, scale, palette, captions, images, cardSize(ctx.metrics), cssW, cssH);\n } else {\n paintList(paint, scale, palette, captions, images, rowHeight(ctx.metrics), cssW, cssH);\n }\n canvas = candidate;\n }\n } catch {\n canvas = undefined;\n }\n\n return {\n element,\n hotspot: { x: 16, y: 16 },\n ...(canvas ? { canvas } : {}),\n dispose: () => {},\n };\n}\n","import type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport type {\n ListDragEntry,\n ListDragPreview,\n ListDragPreviewContext,\n ListDragPreviewRenderer,\n ListDragPreviewSourceResolver,\n ListDragSource,\n ListNativeDragStartDetail,\n} from './list-drag-types.js';\nimport { createDefaultListDragPreview } from './list-drag-preview-default.js';\n\nexport type ListNativeDragControllerConfig<T> = {\n readonly source: ListDragSource;\n /** `itemsDraggable && selection usable` */\n isEnabled: () => boolean;\n /** Event target → item key, or `undefined` when the drag did not start on an item. */\n resolveEventToKey: (target: EventTarget | null) => string | undefined;\n /**\n * Apply the origin rule (origin ∉ selection ⇒ replace with origin); return\n * display-ordered `{ origin, selected }` for both modes, or `undefined` when\n * the origin is not selectable.\n */\n prepareSelection: (originKey: string) => { origin: ListDragEntry<T>; selected: Array<ListDragEntry<T>> } | undefined;\n getMetrics: () => ListDragPreviewContext<T>[`metrics`];\n getRenderer: () => ListDragPreviewRenderer<T> | undefined;\n getDragPreviewSourceResolver?: () => ListDragPreviewSourceResolver<T> | undefined;\n /** Fire the cancelable `list-native-drag-start`; return `!defaultPrevented`. */\n dispatch: (detail: ListNativeDragStartDetail<T>) => boolean;\n /**\n * Optional: write custom payloads onto the drag's `DataTransfer` (e.g. a\n * MIME type for same-app drops). Called once, after a non-cancelled dispatch,\n * inside the synchronous `dragstart` turn.\n */\n writeDataTransfer?: (dataTransfer: DataTransfer, detail: ListNativeDragStartDetail<T>) => void;\n /** Host toggles `data-native-dragging` / `aria-label`, re-renders. */\n onActiveChange: (active: boolean, originKey?: string) => void;\n /** Host clears state + starts its post-drag click-suppress timer. */\n onEnd: () => void;\n /** Optional: sync `draggable` on light-DOM / slotted children while enabled. */\n syncLightDomDraggable?: () => void;\n /**\n * Optional. Called at the very top of the capture-phase `dragstart`, before\n * enablement / key resolution. Return `false` to abort the native drag — the\n * controller calls `event.preventDefault()` so the browser starts no drag.\n * Use when the gesture belongs to another interaction (e.g. marquee select).\n */\n shouldStart?: (event: DragEvent) => boolean;\n};\n\ntype DragHost = ReactiveControllerHost & HTMLElement;\n\n/**\n * Shared native item/row drag-out for list components.\n *\n * Owns capture-phase `dragstart` / `dragend` listeners on the host and its\n * render root, a `MutationObserver` that keeps light-DOM / slotted item `draggable`\n * attributes in sync, and a single post-dispatch disposal on\n * `requestAnimationFrame`. All DOM / selection knowledge lives in the host\n * config callbacks.\n */\nexport class ListNativeDragController<T> implements ReactiveController {\n readonly #host: DragHost;\n readonly #config: ListNativeDragControllerConfig<T>;\n\n #dragging = false;\n #boundRoot: EventTarget | undefined;\n #boundHost = false;\n #seenDragStarts = new WeakSet<Event>();\n #observer: MutationObserver | undefined;\n\n constructor(host: DragHost, config: ListNativeDragControllerConfig<T>) {\n this.#host = host;\n this.#config = config;\n host.addController(this);\n }\n\n get isDragging(): boolean {\n return this.#dragging;\n }\n\n /** `\"true\"` when enabled, else `\"false\"` — for shadow-row template bindings. */\n get draggableAttr(): string {\n try {\n return this.#config.isEnabled() ? `true` : `false`;\n } catch {\n return `false`;\n }\n }\n\n /** Re-run the light-DOM `draggable` sync (e.g. after `itemsDraggable` flips). */\n refreshDraggable(): void {\n try {\n this.#config.syncLightDomDraggable?.();\n } catch {\n // Host sync must never break the controller.\n }\n }\n\n hostConnected(): void {\n this.#bind();\n this.#observer ??= new MutationObserver(() => this.refreshDraggable());\n try {\n this.#observer.observe(this.#host, { childList: true, subtree: true });\n } catch {\n // happy-dom-safe: observing must never throw.\n }\n this.refreshDraggable();\n }\n\n /** `renderRoot` does not exist yet at `hostConnected` for a shadow-DOM host — rebind once it does. */\n hostUpdated(): void {\n this.#bind();\n }\n\n hostDisconnected(): void {\n this.#unbind();\n try {\n this.#observer?.disconnect();\n } catch {\n // Ignore.\n }\n this.#dragging = false;\n }\n\n #renderRoot(): EventTarget {\n const maybe = this.#host as unknown as { renderRoot?: EventTarget };\n return maybe.renderRoot ?? this.#host;\n }\n\n #bind(): void {\n // Capture on both the host (light-DOM / slotted items, and everything in\n // happy-dom where slot distribution is not reflected in the event path)\n // and the render root (shadow cells). A shadow-originated drag reaches\n // both — `#seenDragStarts` dedups the second call.\n const root = this.#renderRoot();\n if (root !== this.#boundRoot) {\n this.#unbind();\n this.#boundRoot = root;\n root.addEventListener(`dragstart`, this.#onDragStart as EventListener, { capture: true });\n root.addEventListener(`dragend`, this.#onDragEnd as EventListener, { capture: true });\n }\n if (!this.#boundHost) {\n this.#boundHost = true;\n this.#host.addEventListener(`dragstart`, this.#onDragStart as EventListener, { capture: true });\n this.#host.addEventListener(`dragend`, this.#onDragEnd as EventListener, { capture: true });\n }\n }\n\n #unbind(): void {\n this.#boundRoot?.removeEventListener(`dragstart`, this.#onDragStart as EventListener, { capture: true });\n this.#boundRoot?.removeEventListener(`dragend`, this.#onDragEnd as EventListener, { capture: true });\n this.#boundRoot = undefined;\n if (this.#boundHost) {\n this.#boundHost = false;\n this.#host.removeEventListener(`dragstart`, this.#onDragStart as EventListener, { capture: true });\n this.#host.removeEventListener(`dragend`, this.#onDragEnd as EventListener, { capture: true });\n }\n }\n\n #onDragStart = (event: Event): void => {\n if (!(event instanceof DragEvent))\n return;\n if (this.#seenDragStarts.has(event))\n return;\n if (this.#config.shouldStart) {\n let ok = true;\n try {\n ok = this.#config.shouldStart(event);\n } catch {\n ok = false;\n }\n if (!ok) {\n try {\n event.preventDefault();\n } catch {\n // Ignore — stubbed events in tests.\n }\n return;\n }\n }\n let enabled = false;\n try {\n enabled = this.#config.isEnabled();\n } catch {\n return;\n }\n if (!enabled)\n return;\n let originKey: string | undefined;\n try {\n originKey = this.#config.resolveEventToKey(event.target);\n } catch {\n return;\n }\n // Do NOT mark the event seen until we have a key. This handler is bound to\n // both the host and the render root; on a shadow-DOM host the host-level\n // invocation sees a retargeted `event.target` and resolves no key — it must\n // not poison the dedup for the render-root invocation that will succeed.\n if (originKey)\n this.#seenDragStarts.add(event);\n if (!originKey)\n return;\n let prepared: { origin: ListDragEntry<T>; selected: Array<ListDragEntry<T>> } | undefined;\n try {\n prepared = this.#config.prepareSelection(originKey);\n } catch {\n return;\n }\n if (!prepared || prepared.selected.length === 0)\n return;\n const { origin, selected } = prepared;\n\n let hostStyle: CSSStyleDeclaration;\n try {\n hostStyle = getComputedStyle(this.#host);\n } catch {\n hostStyle = document.createElement(`div`).style as unknown as CSSStyleDeclaration;\n }\n let metrics: ListDragPreviewContext<T>[`metrics`] = {};\n try {\n metrics = this.#config.getMetrics() ?? {};\n } catch {\n metrics = {};\n }\n let resolveDragPreviewSource;\n try {\n resolveDragPreviewSource = this.#config.getDragPreviewSourceResolver?.();\n } catch {\n resolveDragPreviewSource = undefined;\n }\n const context: ListDragPreviewContext<T> = {\n source: this.#config.source,\n origin,\n selected,\n metrics,\n hostStyle,\n ...(resolveDragPreviewSource ? { resolveDragPreviewSource } : {}),\n };\n let renderer: ListDragPreviewRenderer<T> | undefined;\n try {\n renderer = this.#config.getRenderer();\n } catch {\n renderer = undefined;\n }\n let preview: ListDragPreview;\n try {\n preview = renderer ? renderer(context) : createDefaultListDragPreview(context);\n } catch {\n preview = createDefaultListDragPreview(context);\n }\n try {\n document.body.appendChild(preview.element);\n } catch {\n // happy-dom-safe.\n }\n\n const detail: ListNativeDragStartDetail<T> = {\n key: origin.key,\n index: origin.index,\n item: origin.item,\n selectedKeys: selected.map(entry => entry.key),\n selected,\n preview,\n };\n let notCancelled = true;\n try {\n notCancelled = this.#config.dispatch(detail);\n } catch {\n notCancelled = true;\n }\n\n if (notCancelled) {\n if (event.dataTransfer) {\n try {\n // Let drop targets show a \"move\" / \"copy\" cursor.\n if (event.dataTransfer.effectAllowed === `none` || event.dataTransfer.effectAllowed === `uninitialized`)\n event.dataTransfer.effectAllowed = `copyMove`;\n } catch {\n // read-only in some contexts — non-fatal.\n }\n try {\n this.#config.writeDataTransfer?.(event.dataTransfer, detail);\n } catch {\n // A misbehaving payload writer must not abort the drag.\n }\n }\n const hotspot = preview.hotspot ?? { x: 16, y: 16 };\n try {\n event.dataTransfer?.setDragImage(preview.element, hotspot.x, hotspot.y);\n } catch {\n // Stubbed dataTransfer in tests may throw — non-fatal.\n }\n this.#dragging = true;\n try {\n this.#config.onActiveChange(true, origin.key);\n } catch {\n // Ignore.\n }\n } else {\n try {\n event.preventDefault();\n } catch {\n // Ignore.\n }\n }\n requestAnimationFrame(() => {\n try {\n preview.element.remove();\n } catch {\n // Ignore.\n }\n try {\n preview.dispose?.();\n } catch {\n // Ignore.\n }\n });\n };\n\n #onDragEnd = (): void => {\n if (!this.#dragging)\n return;\n this.#dragging = false;\n try {\n this.#config.onActiveChange(false);\n } catch {\n // Ignore.\n }\n try {\n this.#config.onEnd();\n } catch {\n // Ignore.\n }\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-native-drag-controller-ChIi3eK5.d.ts","names":[],"sources":["../src/interaction/list-native-drag-controller.ts"],"mappings":";;;KAYY,+BAA+B;WAChC,QAAQ;;EAEjB;;EAEA,oBAAoB,QAAQ;;;;;;EAM5B,mBAAmB;IAAwB,QAAQ,cAAc;IAAI,UAAU,MAAM,cAAc;;EACnG,kBAAkB,uBAAuB;EACzC,mBAAmB,wBAAwB;EAC3C,qCAAqC,8BAA8B;;EAEnE,WAAW,QAAQ,0BAA0B;;;;;;EAM7C,qBAAqB,cAAc,cAAc,QAAQ,0BAA0B;;EAEnF,iBAAiB,iBAAiB;;EAElC;;EAEA;;;;;;;EAOA,eAAe,OAAO;;KAGnB,WAAW,yBAAyB;;;;;;;;;;cAW5B,yBAAyB,cAAc;;EAUtC,YAAA,MAAM,UAAU,QAAQ,+BAA+B;MAM/D;;MAKA;;EASJ;EAQA;;EAYA;EAIA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-selection-controller-BeE70lbB.js","names":["#host","#config","#dragging","#suppressClick","#bindSurface","#onPointerMove","#onPointerUp","#onPointerCancel","#unbindSurface","#stopAutoScroll","#reset","#safeSurface","#boundSurface","#onPointerDown","#enabledTypes","#pointerId","#startClientX","#startClientY","#currentClientX","#currentClientY","#startX","#startY","#base","#lastMode","#lastModifiers","#threshold","#updatePreview","#kickAutoScroll","#surfaceBox","#currentRect","#modeFor","#preview","#raf","#autoScrollTick","#config","#selected","#anchor","#apply","#clamped","#groupOf","#clampToFirstGroup","#effectiveMulti"],"sources":["../src/interaction/list-drag-select-controller.ts","../src/interaction/list-selection-controller.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/** Surface-relative rectangle: origin at the scroll container's top-left. */\nexport type DragSelectRect = {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n};\n\nexport type ListDragSelectControllerConfig<T> = {\n /** Element the marquee is drawn in and pointer geometry is measured against. */\n getSurface: () => HTMLElement | undefined;\n /** Is drag-select currently allowed? (multi-capable, has items, not disabled) */\n isEnabled: () => boolean;\n /** Pointer types that may start a drag. Default ['mouse', 'pen'] — touch still scrolls. */\n pointerTypes?: readonly string[];\n /** Movement in px before a press becomes a drag. Default 4. */\n threshold?: number;\n /** Map a surface-relative rect to covered items. */\n hitTest: (rect: DragSelectRect) => Iterable<T>;\n /**\n * Selection snapshotted when the drag starts, combined with the hit set\n * while modifiers are held: Shift adds (`base + hit`), Cmd / Ctrl inverts\n * (covered items toggle, the rest is untouched).\n */\n getBaseSelection: () => ReadonlySet<T>;\n /** Continuous visual feedback: the preview set + current rect (undefined when idle). */\n onPreview: (preview: ReadonlySet<T>, rect: DragSelectRect | undefined) => void;\n /**\n * Fired once on release with the final set. Host applies it to its\n * selection. `additive` is `true` when the drag ran with Shift (add) or\n * Cmd / Ctrl (invert) held.\n */\n onCommit: (finalSet: ReadonlySet<T>, info: { additive: boolean }) => void;\n /** Optional: scroll the surface when the pointer nears an edge during a drag. */\n autoScroll?: (dx: number, dy: number) => void;\n /**\n * Optional predicate called on pointerdown before the controller records its\n * pointer id or later calls setPointerCapture/preventDefault. Return false\n * to yield to another gesture (e.g. native item drag).\n */\n shouldStart?: (event: PointerEvent) => boolean;\n};\n\ntype DragHost = ReactiveControllerHost & HTMLElement;\n\nconst DEFAULT_POINTER_TYPES = [`mouse`, `pen`] as const;\nconst DEFAULT_THRESHOLD = 4;\n/** Pointer distance (px) from an edge that triggers auto-scroll. */\nconst EDGE_ZONE = 28;\n/** Max auto-scroll speed in px per frame. */\nconst MAX_SCROLL_SPEED = 16;\n\n/**\n * Shared pointer-drag (marquee / rubber-band) selection for list components.\n *\n * Owns all pointer plumbing and rectangle state; knows nothing about DOM\n * geometry or the selection model — those are host callbacks. Mirrors the\n * `TickledController` attach pattern (`new ListDragSelectController(this, …)`).\n *\n * Behaviour: `pointerdown` on the surface records a start point; once the\n * pointer moves past `threshold`, the surface captures the pointer and every\n * move recomputes the rect, hit-tests, and calls `onPreview`. On release the\n * final set is delivered once via `onCommit`. A press that never crosses the\n * threshold does nothing (the normal `@click` path runs).\n */\nexport class ListDragSelectController<T> implements ReactiveController {\n readonly #host: DragHost;\n readonly #config: ListDragSelectControllerConfig<T>;\n\n #boundSurface: EventTarget | undefined;\n\n #pointerId: number | undefined;\n #startClientX = 0;\n #startClientY = 0;\n #startX = 0;\n #startY = 0;\n #currentClientX = 0;\n #currentClientY = 0;\n #lastModifiers = { shiftKey: false, ctrlKey: false, metaKey: false };\n #dragging = false;\n #suppressClick = false;\n /** Selection as it was when the drag started — the combine baseline. */\n #base: ReadonlySet<T> = new Set();\n /** Combine mode of the most recent preview (drives the commit flag). */\n #lastMode: `replace` | `add` | `invert` = `replace`;\n #preview: ReadonlySet<T> = new Set();\n #raf = 0;\n\n constructor(host: DragHost, config: ListDragSelectControllerConfig<T>) {\n this.#host = host;\n this.#config = config;\n host.addController(this);\n }\n\n /** `true` while a drag is in progress or its trailing click is still pending. */\n get isDragging(): boolean {\n return this.#dragging || this.#suppressClick;\n }\n\n /** `true` once the press has crossed the threshold and a rect is live. */\n get isActive(): boolean {\n return this.#dragging;\n }\n\n hostConnected(): void {\n this.#bindSurface();\n window.addEventListener(`pointermove`, this.#onPointerMove);\n window.addEventListener(`pointerup`, this.#onPointerUp);\n window.addEventListener(`pointercancel`, this.#onPointerCancel);\n }\n\n hostDisconnected(): void {\n this.#unbindSurface();\n window.removeEventListener(`pointermove`, this.#onPointerMove);\n window.removeEventListener(`pointerup`, this.#onPointerUp);\n window.removeEventListener(`pointercancel`, this.#onPointerCancel);\n this.#stopAutoScroll();\n this.#reset();\n }\n\n /** Re-bind when the surface element appears/changes (e.g. first render). */\n hostUpdated(): void {\n const next = this.#safeSurface() ?? this.#host;\n if (next !== this.#boundSurface) {\n this.#bindSurface();\n }\n }\n\n #safeSurface(): HTMLElement | undefined {\n try {\n return this.#config.getSurface();\n } catch {\n return undefined;\n }\n }\n\n #bindSurface(): void {\n const next = this.#safeSurface() ?? this.#host;\n if (next === this.#boundSurface)\n return;\n this.#unbindSurface();\n this.#boundSurface = next;\n next.addEventListener(`pointerdown`, this.#onPointerDown as EventListener);\n }\n\n #unbindSurface(): void {\n this.#boundSurface?.removeEventListener(`pointerdown`, this.#onPointerDown as EventListener);\n this.#boundSurface = undefined;\n }\n\n #enabledTypes(): readonly string[] {\n return this.#config.pointerTypes ?? DEFAULT_POINTER_TYPES;\n }\n\n #threshold(): number {\n return this.#config.threshold ?? DEFAULT_THRESHOLD;\n }\n\n #onPointerDown = (event: PointerEvent): void => {\n if (event.button !== 0)\n return;\n if (!this.#enabledTypes().includes(event.pointerType))\n return;\n let enabled = false;\n try {\n enabled = this.#config.isEnabled();\n } catch {\n return;\n }\n if (!enabled)\n return;\n const target = event.target as Element | null;\n if (target instanceof Element && typeof target.closest === `function`) {\n if (target.closest(`input,button,a,select,textarea,[contenteditable]`))\n return;\n }\n if (this.#config.shouldStart) {\n try {\n if (!this.#config.shouldStart(event))\n return;\n } catch {\n return;\n }\n }\n const surface = this.#safeSurface() ?? this.#host;\n const box = surface.getBoundingClientRect();\n this.#pointerId = event.pointerId;\n this.#startClientX = event.clientX;\n this.#startClientY = event.clientY;\n this.#currentClientX = event.clientX;\n this.#currentClientY = event.clientY;\n this.#startX = Math.min(Math.max(event.clientX - box.left, 0), Math.max(0, box.width));\n this.#startY = Math.min(Math.max(event.clientY - box.top, 0), Math.max(0, box.height));\n this.#dragging = false;\n this.#suppressClick = false;\n this.#base = new Set();\n this.#lastMode = `replace`;\n this.#lastModifiers = { shiftKey: event.shiftKey, ctrlKey: event.ctrlKey, metaKey: event.metaKey };\n // Do not capture yet — a sub-threshold press is a plain click.\n };\n\n /** Combine mode for the current modifiers: Shift adds, Cmd/Ctrl inverts. */\n #modeFor(modifiers: { shiftKey: boolean; ctrlKey: boolean; metaKey: boolean }): `replace` | `add` | `invert` {\n if (modifiers.metaKey || modifiers.ctrlKey)\n return `invert`;\n if (modifiers.shiftKey)\n return `add`;\n return `replace`;\n }\n\n #onPointerMove = (event: PointerEvent): void => {\n if (this.#pointerId === undefined || event.pointerId !== this.#pointerId)\n return;\n this.#currentClientX = event.clientX;\n this.#currentClientY = event.clientY;\n this.#lastModifiers = { shiftKey: event.shiftKey, ctrlKey: event.ctrlKey, metaKey: event.metaKey };\n const moved = Math.hypot(event.clientX - this.#startClientX, event.clientY - this.#startClientY);\n if (!this.#dragging) {\n if (moved < this.#threshold())\n return;\n this.#dragging = true;\n try {\n this.#base = new Set(this.#config.getBaseSelection());\n } catch {\n this.#base = new Set();\n }\n const surface = this.#safeSurface() ?? this.#host;\n try {\n if (typeof surface.setPointerCapture === `function`)\n surface.setPointerCapture(event.pointerId);\n } catch {\n // happy-dom and some environments lack setPointerCapture — non-fatal.\n }\n }\n try {\n event.preventDefault?.();\n } catch {\n // Ignore — prevents native image drag where supported.\n }\n this.#updatePreview();\n this.#kickAutoScroll();\n };\n\n #surfaceBox(): DOMRect | undefined {\n const surface = this.#safeSurface() ?? this.#host;\n try {\n return surface.getBoundingClientRect();\n } catch {\n return undefined;\n }\n }\n\n #currentRect(): DragSelectRect | undefined {\n const box = this.#surfaceBox();\n if (!box)\n return undefined;\n const cx = Math.min(Math.max(this.#currentClientX - box.left, 0), Math.max(0, box.width));\n const cy = Math.min(Math.max(this.#currentClientY - box.top, 0), Math.max(0, box.height));\n return {\n x: Math.min(this.#startX, cx),\n y: Math.min(this.#startY, cy),\n width: Math.abs(cx - this.#startX),\n height: Math.abs(cy - this.#startY),\n };\n }\n\n #updatePreview(): void {\n const rect = this.#currentRect();\n if (!rect)\n return;\n let hit: Iterable<T> = [];\n try {\n hit = this.#config.hitTest(rect);\n } catch {\n hit = [];\n }\n const mode = this.#modeFor(this.#lastModifiers);\n this.#lastMode = mode;\n const hitSet = new Set(hit);\n let preview: ReadonlySet<T>;\n if (mode === `add`) {\n preview = new Set([...this.#base, ...hitSet]);\n } else if (mode === `invert`) {\n const toggled = new Set(this.#base);\n for (const item of hitSet) {\n if (toggled.has(item))\n toggled.delete(item);\n else\n toggled.add(item);\n }\n preview = toggled;\n } else {\n preview = hitSet;\n }\n this.#preview = preview;\n try {\n this.#config.onPreview(preview, rect);\n } catch {\n // Host preview must never break the gesture.\n }\n }\n\n #onPointerUp = (event: PointerEvent): void => {\n if (this.#pointerId === undefined || event.pointerId !== this.#pointerId)\n return;\n this.#lastModifiers = { shiftKey: event.shiftKey, ctrlKey: event.ctrlKey, metaKey: event.metaKey };\n const wasDragging = this.#dragging;\n const surface = this.#safeSurface() ?? this.#host;\n try {\n if (typeof surface.hasPointerCapture === `function`\n && typeof surface.releasePointerCapture === `function`\n && surface.hasPointerCapture(event.pointerId)) {\n surface.releasePointerCapture(event.pointerId);\n }\n } catch {\n // Non-fatal (see pointermove).\n }\n this.#stopAutoScroll();\n this.#pointerId = undefined;\n if (!wasDragging) {\n this.#reset();\n return;\n }\n this.#dragging = false;\n const final = this.#preview;\n try {\n this.#config.onCommit(final, { additive: this.#lastMode !== `replace` });\n } catch {\n // Host commit must never break state reset.\n }\n try {\n this.#config.onPreview(new Set(), undefined);\n } catch {\n // Ignore.\n }\n this.#preview = new Set();\n // Keep `isDragging` true until the trailing synthetic `click` has been\n // dispatched so hosts can swallow it; clicks dispatch before timers fire.\n this.#suppressClick = true;\n window.setTimeout(() => {\n this.#suppressClick = false;\n }, 0);\n };\n\n #onPointerCancel = (event: PointerEvent): void => {\n if (this.#pointerId === undefined || event.pointerId !== this.#pointerId)\n return;\n this.#stopAutoScroll();\n this.#pointerId = undefined;\n this.#dragging = false;\n this.#preview = new Set();\n try {\n this.#config.onPreview(new Set(), undefined);\n } catch {\n // Ignore.\n }\n this.#suppressClick = false;\n };\n\n #kickAutoScroll(): void {\n if (!this.#config.autoScroll || this.#raf !== 0)\n return;\n this.#raf = requestAnimationFrame(this.#autoScrollTick);\n }\n\n #autoScrollTick = (): void => {\n this.#raf = 0;\n if (!this.#dragging || this.#pointerId === undefined)\n return;\n const box = this.#surfaceBox();\n if (!box)\n return;\n const px = this.#currentClientX - box.left;\n const py = this.#currentClientY - box.top;\n let dx = 0;\n let dy = 0;\n if (px < EDGE_ZONE)\n dx = -Math.ceil(MAX_SCROLL_SPEED * (1 - Math.max(0, px) / EDGE_ZONE));\n else if (px > box.width - EDGE_ZONE)\n dx = Math.ceil(MAX_SCROLL_SPEED * (1 - Math.max(0, box.width - px) / EDGE_ZONE));\n if (py < EDGE_ZONE)\n dy = -Math.ceil(MAX_SCROLL_SPEED * (1 - Math.max(0, py) / EDGE_ZONE));\n else if (py > box.height - EDGE_ZONE)\n dy = Math.ceil(MAX_SCROLL_SPEED * (1 - Math.max(0, box.height - py) / EDGE_ZONE));\n if (dx === 0 && dy === 0)\n return;\n const autoScroll = this.#config.autoScroll;\n if (!autoScroll)\n return;\n try {\n autoScroll(dx, dy);\n } catch {\n // Ignore.\n }\n // Scrolling changes which items a fixed surface-relative rect covers\n // (hosts add the scroll offset in hitTest), so re-run the preview.\n this.#updatePreview();\n this.#raf = requestAnimationFrame(this.#autoScrollTick);\n };\n\n #stopAutoScroll(): void {\n if (this.#raf !== 0) {\n cancelAnimationFrame(this.#raf);\n this.#raf = 0;\n }\n }\n\n #reset(): void {\n this.#dragging = false;\n this.#suppressClick = false;\n this.#base = new Set();\n this.#lastMode = `replace`;\n this.#preview = new Set();\n }\n}\n","import type { ListInteractionMode, ListSelectionMode } from './list-selection-types.js';\n\n/** Modifier state needed to route a click gesture per interaction mode. */\nexport type ListSelectionGesture = {\n readonly ctrlKey: boolean;\n readonly metaKey: boolean;\n readonly shiftKey: boolean;\n};\n\nexport type ListSelectionModes = {\n readonly selectionMode: ListSelectionMode;\n readonly interactionMode: ListInteractionMode;\n};\n\n/**\n * Configuration supplied by the host component.\n *\n * The controller owns selection *state* only — everything DOM- or\n * component-specific is expressed through these callbacks.\n */\nexport type ListSelectionControllerConfig<T> = {\n /** Visible items in navigation order — used for range selection and select-all. */\n readonly getOrderedItems: () => readonly T[];\n /** Whether an item may join the selection (e.g. reject `not-checked` rows). */\n readonly isSelectable: (item: T) => boolean;\n /** Current modes; read on every gesture so property changes apply immediately. */\n readonly getModes: () => ListSelectionModes;\n /**\n * Fired after every selection change. The host syncs DOM state\n * (`data-selected` / `data-checked`), dispatches `list-select`, and\n * requests an update.\n */\n readonly onChange: (selected: ReadonlySet<T>, previous: ReadonlySet<T>) => void;\n /**\n * Optional: derive a stable string key for an item. Enables `selectedKeys`\n * and `selectKeys()`. When omitted, `selectedKeys` is always empty.\n */\n readonly getKey?: (item: T) => string | undefined;\n /**\n * Optional: the group an item belongs to (`null` when ungrouped or the item\n * cannot be resolved). With this set and `crossGroupSelection` off, gestures\n * are confined to a single group — same rules as `ixfx-data-grid` and\n * `ixfx-grouped-item-lister`. Programmatic key APIs are never clamped.\n */\n readonly getGroupKey?: (item: T) => string | null;\n /** Whether selection may span groups. Read on every gesture; defaults to `false`. */\n readonly crossGroupSelection?: () => boolean;\n /** Group used by `selectAll` when there is no anchor (e.g. the cursor's group). */\n readonly getFallbackGroupKey?: () => string | null;\n};\n\n/** Whether the interaction mode allows building a multi-item selection. */\nexport function isMultiMode(mode: ListInteractionMode): boolean {\n return mode === `checked` || mode === `sticky` || mode === `vscode` || mode === `standard`;\n}\n\n/**\n * Generic selection state machine shared by list components.\n *\n * Owns the selected set plus the range-selection anchor, the selection\n * primitives (`replace` / `toggle` / `rangeTo` / `clear` / `selectAll` /\n * `selectMany` / `deselect`) and the per-interactionMode gesture routers\n * (`handleClick` / `handleSpace`).\n *\n * Identity is generic: both `ixfx-vertical-list` and `ixfx-detail-list` use\n * `ListSelectionController<Element>`.\n *\n * @example\n * ```ts\n * const selection = new ListSelectionController<Element>({\n * getOrderedItems: () => this.getVisibleItems(),\n * isSelectable: el => !el.hasAttribute(`not-checked`),\n * getModes: () => ({ selectionMode: this.selectionMode, interactionMode: this.interactionMode }),\n * onChange: (selected, previous) => {\n * this.syncItemStates();\n * this.dispatchEvent(new CustomEvent(`list-select`, { detail: { selected, previous } }));\n * },\n * });\n * ```\n */\nexport class ListSelectionController<T> {\n readonly #config: ListSelectionControllerConfig<T>;\n #selected: ReadonlySet<T> = new Set();\n #anchor: T | undefined;\n\n constructor(config: ListSelectionControllerConfig<T>) {\n this.#config = config;\n }\n\n /** The current selection set (read-only). */\n get selected(): ReadonlySet<T> {\n return this.#selected;\n }\n\n /**\n * The current selection as stable string keys (read-only). Empty unless a\n * `getKey` was supplied in config. Items whose `getKey` returns `undefined`\n * are omitted.\n */\n get selectedKeys(): ReadonlySet<string> {\n const getKey = this.#config.getKey;\n const out = new Set<string>();\n if (getKey) {\n for (const item of this.#selected) {\n const key = getKey(item);\n if (key !== undefined) {\n out.add(key);\n }\n }\n }\n return out;\n }\n\n /** Anchor for range (shift) selection — the last plainly-selected item. */\n get anchor(): T | undefined {\n return this.#anchor;\n }\n\n /** Whether \"select all\" (Cmd/Ctrl+A) is currently permitted. */\n canSelectAll(): boolean {\n return this.canSelectMultiple() && this.#config.getModes().selectionMode !== `none`;\n }\n\n /** Whether a multi-item selection can be built in the current modes. */\n canSelectMultiple(): boolean {\n const { selectionMode, interactionMode } = this.#config.getModes();\n return selectionMode === `multiple` || isMultiMode(interactionMode);\n }\n\n // --- Selection primitives ---\n\n /** Replace the entire selection with a single item; updates the anchor. */\n replace(item: T): void {\n if (this.#config.getModes().selectionMode === `none`)\n return;\n if (!this.#config.isSelectable(item))\n return;\n this.#anchor = item;\n this.#apply(new Set([item]));\n }\n\n /** Toggle a single item in/out of the selection without replacing it. Anchor unchanged. */\n toggle(item: T): void {\n const { selectionMode, interactionMode } = this.#config.getModes();\n if (!this.#config.isSelectable(item))\n return;\n // checked/vscode/sticky modes imply multiple selection capacity\n if (selectionMode === `none` && interactionMode !== `checked` && interactionMode !== `sticky`)\n return;\n\n const next = new Set(this.#selected);\n if (next.has(item)) {\n next.delete(item);\n } else {\n if (!this.canSelectMultiple())\n next.clear();\n if (this.#clamped()) {\n const g = this.#groupOf(item);\n for (const other of [...next]) {\n if (this.#groupOf(other) !== g)\n next.delete(other);\n }\n }\n next.add(item);\n }\n this.#apply(next);\n }\n\n /** Select the contiguous ordered range from the anchor to `item`. Anchor unchanged. */\n rangeTo(item: T): void {\n if (this.#config.getModes().selectionMode === `none`)\n return;\n if (this.#anchor === undefined) {\n this.replace(item);\n return;\n }\n const ordered = this.#config.getOrderedItems();\n const anchorIdx = ordered.indexOf(this.#anchor);\n const targetIdx = ordered.indexOf(item);\n if (anchorIdx === -1 || targetIdx === -1) {\n this.replace(item);\n return;\n }\n if (this.#clamped()) {\n const group = this.#groupOf(this.#anchor);\n if (group !== this.#groupOf(item)) {\n this.replace(item);\n return;\n }\n const inGroup = ordered.filter(t => this.#groupOf(t) === group);\n const a = inGroup.indexOf(this.#anchor);\n const b = inGroup.indexOf(item);\n if (a === -1 || b === -1) {\n this.replace(item);\n return;\n }\n this.#apply(new Set(inGroup.slice(Math.min(a, b), Math.max(a, b) + 1).filter(t => this.#config.isSelectable(t))));\n return;\n }\n const start = Math.min(anchorIdx, targetIdx);\n const end = Math.max(anchorIdx, targetIdx);\n this.#apply(new Set(ordered.slice(start, end + 1).filter(t => this.#config.isSelectable(t))));\n }\n\n /** Clear the selection. No change event when the selection is already empty. */\n clear(): void {\n if (this.#selected.size === 0)\n return;\n this.#apply(new Set());\n }\n\n /** Select every ordered item that passes `isSelectable`. */\n selectAll(): void {\n let ordered = this.#config.getOrderedItems();\n if (ordered.length === 0)\n return;\n if (this.#clamped()) {\n const group = (this.#anchor === undefined ? null : this.#groupOf(this.#anchor))\n ?? this.#config.getFallbackGroupKey?.()\n ?? null;\n if (group !== null)\n ordered = ordered.filter(t => this.#groupOf(t) === group);\n }\n const next = new Set(ordered.filter(t => this.#config.isSelectable(t)));\n if (next.size === 0)\n return;\n this.#apply(next);\n }\n\n /**\n * Replace the selection with many items at once. Requires\n * `selectionMode=\"multiple\"`, throws otherwise. Updates the anchor.\n */\n selectMany(items: Iterable<T>): void {\n const { selectionMode } = this.#config.getModes();\n if (selectionMode !== `multiple`) {\n throw new Error(`selectMany requires selectionMode=\"multiple\" (current: \"${selectionMode}\")`);\n }\n const next = this.#clampToFirstGroup(new Set([...items].filter(t => this.#config.isSelectable(t))));\n if (next.size === 0)\n return;\n this.#anchor = [...next].at(-1);\n this.#apply(next);\n }\n\n /**\n * Whether a drag / marquee gesture may build a selection in the current\n * modes: `selectionMode=\"multiple\"`, or a multi interaction mode\n * (`checked` / `sticky` / `vscode`) outside `selectionMode=\"none\"`.\n * Stricter than `canSelectMultiple()` — `single` + `standard` does not\n * qualify (a drag there would be a surprising multi-select).\n */\n canDragSelect(): boolean {\n return this.#config.getModes().selectionMode !== `none` && this.#effectiveMulti();\n }\n\n /**\n * Replace the selection with `items` from a drag / marquee gesture. Like\n * `selectMany` but gated on `canDragSelect()` instead of throwing, and a\n * no-op in single/none modes. Non-selectable items are dropped; the anchor\n * moves to the last item. Fires `onChange` once. An empty result clears a\n * non-empty selection (e.g. a Cmd-drag that toggles everything off) but is\n * a no-op when nothing is selected.\n */\n applyDragSelection(items: Iterable<T>): void {\n if (!this.canDragSelect())\n return;\n const next = this.#clampToFirstGroup(new Set([...items].filter(t => this.#config.isSelectable(t))));\n if (next.size === 0 && this.#selected.size === 0)\n return;\n this.#anchor = [...next].at(-1);\n this.#apply(next);\n }\n\n /** Remove a single item from the selection. */\n deselect(item: T): void {\n if (!this.#selected.has(item))\n return;\n const next = new Set(this.#selected);\n next.delete(item);\n this.#apply(next);\n }\n\n // --- Key-based selection ---\n\n /**\n * Whether the current modes permit a selection of more than one item.\n * Stricter than `canSelectMultiple()`: `standard` / `implicit` only count\n * as multi when `selectionMode=\"multiple\"`.\n */\n #effectiveMulti(): boolean {\n const { selectionMode, interactionMode } = this.#config.getModes();\n return selectionMode === `multiple`\n || interactionMode === `checked`\n || interactionMode === `sticky`\n || interactionMode === `vscode`;\n }\n\n /**\n * Replace the selection with the items resolved from `keys`. Keys that\n * `resolve` cannot map, or that resolve to a non-selectable item, are\n * ignored. `selectionMode=\"none\"` is a no-op. When multi-select is not\n * available, only the last resolvable key is kept. `onChange` fires once.\n */\n selectKeys(keys: Iterable<string>, resolve: (key: string) => T | undefined): void {\n if (this.#config.getModes().selectionMode === `none`)\n return;\n let next = new Set<T>();\n for (const key of new Set(keys)) {\n const item = resolve(key);\n if (item !== undefined && this.#config.isSelectable(item)) {\n next.add(item);\n }\n }\n if (!this.#effectiveMulti() && next.size > 1) {\n const last = [...next].at(-1);\n next = last === undefined ? new Set() : new Set([last]);\n }\n this.#anchor = [...next].at(-1);\n this.#apply(next);\n }\n\n /**\n * Add the items resolved from `keys` to the selection (multi-select only;\n * a no-op otherwise). `onChange` fires once if anything changed.\n */\n addKeys(keys: Iterable<string>, resolve: (key: string) => T | undefined): void {\n if (!this.#effectiveMulti())\n return;\n const next = new Set(this.#selected);\n let changed = false;\n for (const key of new Set(keys)) {\n const item = resolve(key);\n if (item !== undefined && !next.has(item) && this.#config.isSelectable(item)) {\n next.add(item);\n changed = true;\n }\n }\n if (changed) {\n this.#apply(next);\n }\n }\n\n /**\n * Remove the items resolved from `keys` from the selection. `onChange`\n * fires once if anything changed.\n */\n removeKeys(keys: Iterable<string>, resolve: (key: string) => T | undefined): void {\n if (this.#selected.size === 0)\n return;\n const next = new Set(this.#selected);\n let changed = false;\n for (const key of new Set(keys)) {\n const item = resolve(key);\n if (item !== undefined && next.delete(item)) {\n changed = true;\n }\n }\n if (changed) {\n this.#apply(next);\n }\n }\n\n // --- Gesture routers ---\n\n /** Route a click on `item` according to the current interaction mode. */\n handleClick(item: T, gesture: ListSelectionGesture): void {\n const { selectionMode, interactionMode: mode } = this.#config.getModes();\n if (mode === `manual`)\n return;\n if (selectionMode === `none` && mode !== `checked` && mode !== `sticky`)\n return;\n\n switch (mode) {\n case `implicit`:\n // Single-select only; modifier keys have no effect\n this.replace(item);\n break;\n\n case `standard`:\n case `vscode`:\n if (gesture.ctrlKey || gesture.metaKey) {\n // Ctrl/Cmd+click: toggle item; requires effective multi-select\n if (selectionMode === `multiple` || mode === `vscode`) {\n this.toggle(item);\n }\n } else if (gesture.shiftKey && (selectionMode === `multiple` || mode === `vscode`)) {\n // Shift+click: range-select from anchor\n this.rangeTo(item);\n } else {\n // Plain click: replace selection, update anchor\n this.replace(item);\n }\n break;\n\n case `checked`:\n // Body clicks do nothing — only the checkbox column toggles.\n break;\n\n case `sticky`:\n // Every tap/click toggles — multi-select without modifier keys (touchscreens).\n this.toggle(item);\n break;\n }\n }\n\n /** Route a Space keypress on `item` according to the current interaction mode. */\n handleSpace(item: T): void {\n const mode = this.#config.getModes().interactionMode;\n if (mode === `manual`)\n return;\n if (mode === `implicit`) {\n // Space selects (same as click) in implicit mode\n this.replace(item);\n } else {\n // standard / vscode / checked / sticky: Space toggles\n this.toggle(item);\n }\n }\n\n // --- Maintenance ---\n\n /** Drop the range-selection anchor (e.g. when the interaction mode changes). */\n clearAnchor(): void {\n this.#anchor = undefined;\n }\n\n /**\n * Re-key the selection across an identity boundary — e.g. when items are\n * wrapped/unwrapped and the selected Element references change. Silent:\n * no `onChange` is fired.\n */\n remap(fn: (item: T) => T): void {\n if (this.#selected.size === 0)\n return;\n this.#selected = new Set([...this.#selected].map(fn));\n }\n\n /**\n * Hard reset: empty the selection and clear the anchor without firing\n * `onChange` (e.g. when all items are removed).\n */\n reset(): void {\n this.#selected = new Set();\n this.#anchor = undefined;\n }\n\n /**\n * Replace the selection and anchor silently (no `onChange`). Used to\n * re-key the selection when items are rebuilt from data — e.g. matching\n * new elements to previously selected keys.\n */\n seed(items: Iterable<T>, anchor?: T): void {\n this.#selected = new Set(items);\n this.#anchor = anchor;\n }\n\n // --- Grouping ---\n\n /** Whether gestures must stay inside one group. */\n #clamped(): boolean {\n return this.#config.getGroupKey !== undefined && !(this.#config.crossGroupSelection?.() ?? false);\n }\n\n #groupOf(item: T): string | null {\n return this.#config.getGroupKey?.(item) ?? null;\n }\n\n /** Keep only items in the group of the first item (in display order) when clamped. */\n #clampToFirstGroup(items: ReadonlySet<T>): Set<T> {\n if (!this.#clamped() || items.size === 0)\n return new Set(items);\n const first = this.#config.getOrderedItems().find(t => items.has(t)) ?? [...items][0];\n const group = this.#groupOf(first);\n return new Set([...items].filter(t => this.#groupOf(t) === group));\n }\n\n #apply(next: ReadonlySet<T>): void {\n const previous = this.#selected;\n this.#selected = next;\n this.#config.onChange(next, previous);\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-selection-types-PjKdhF-a.d.ts","names":[],"sources":["../src/interaction/list-selection-types.ts"],"mappings":";KAWY;;;;;;;;;;;;;KAcA;KAEA;WACD,UAAU,YAAY;WACtB,UAAU,YAAY;;;;;WAKtB,cAAc;;KAGb;WACD,MAAM;;KAGL;WACD,MAAM;;KAGL;WACD,MAAM;;KAGL,kBAAkB,YAAY;KAC9B,kBAAkB,YAAY;KAC9B,oBAAoB,YAAY;KAChC,qBAAqB,YAAY;UAE5B;EACf,eAAe;EACf,eAAe;EACf,iBAAiB;EACjB,mBAAmB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-viewport-types-BRZsLcvp.d.ts","names":[],"sources":["../src/interaction/list-viewport-types.ts"],"mappings":";;;;;;;;;;;;;KAaY;;WAED;;WAEA;;KAGC,0BAA0B,YAAY"}