@ixfx/components 0.5.20 → 0.6.1

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 (285) hide show
  1. package/bundle/index.d.ts +586 -261
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +8306 -6624
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +12 -7
  6. package/dist/ac-text.d.ts.map +1 -1
  7. package/dist/ac-text.js +3 -4
  8. package/dist/ac-text.js.map +1 -1
  9. package/dist/ac-token-DVbmHmky.d.ts +107 -0
  10. package/dist/ac-token-DVbmHmky.d.ts.map +1 -0
  11. package/dist/ac-token.d.ts +2 -0
  12. package/dist/ac-token.js +646 -0
  13. package/dist/ac-token.js.map +1 -0
  14. package/dist/{button-pcDaCemT.js → button-Bn0BuLpO.js} +3 -4
  15. package/dist/{button-pcDaCemT.js.map → button-Bn0BuLpO.js.map} +1 -1
  16. package/dist/button.d.ts +2 -3
  17. package/dist/button.d.ts.map +1 -1
  18. package/dist/button.js +1 -1
  19. package/dist/checkbox.d.ts +0 -1
  20. package/dist/checkbox.d.ts.map +1 -1
  21. package/dist/checkbox.js +1 -1
  22. package/dist/checkbox.js.map +1 -1
  23. package/dist/{colour-picker-D43Q96r0.js → colour-picker-0stHB90J.js} +11 -14
  24. package/dist/{colour-picker-D43Q96r0.js.map → colour-picker-0stHB90J.js.map} +1 -1
  25. package/dist/colour-picker.d.ts +1 -1
  26. package/dist/colour-picker.js +1 -1
  27. package/dist/crumbs.d.ts +4 -2
  28. package/dist/crumbs.d.ts.map +1 -1
  29. package/dist/crumbs.js +1152 -1
  30. package/dist/crumbs.js.map +1 -0
  31. package/dist/data-controller-DOlmqNKb.js +171 -0
  32. package/dist/data-controller-DOlmqNKb.js.map +1 -0
  33. package/dist/data-display.d.ts +1 -2
  34. package/dist/data-display.d.ts.map +1 -1
  35. package/dist/data-display.js +24 -22
  36. package/dist/data-display.js.map +1 -1
  37. package/dist/data-grid-BeAkORz2.d.ts +215 -0
  38. package/dist/data-grid-BeAkORz2.d.ts.map +1 -0
  39. package/dist/data-grid.d.ts +2 -0
  40. package/dist/data-grid.js +1225 -0
  41. package/dist/data-grid.js.map +1 -0
  42. package/dist/data-provider-BAn_-oR1.d.ts +61 -0
  43. package/dist/data-provider-BAn_-oR1.d.ts.map +1 -0
  44. package/dist/{decorate-DdjvVHS-.js → decorate-VRK8rslU.js} +2 -2
  45. package/dist/{decorate-DdjvVHS-.js.map → decorate-VRK8rslU.js.map} +1 -1
  46. package/dist/{defaults-BkWCPJFL.js → defaults-BCiDhZbF.js} +20 -3
  47. package/dist/defaults-BCiDhZbF.js.map +1 -0
  48. package/dist/drag-ghost-DtSDvjri.js +85 -0
  49. package/dist/drag-ghost-DtSDvjri.js.map +1 -0
  50. package/dist/editable-label.d.ts +1 -2
  51. package/dist/editable-label.d.ts.map +1 -1
  52. package/dist/editable-label.js +1 -1
  53. package/dist/editable-label.js.map +1 -1
  54. package/dist/{incr-search-CeERfijK.js → element-search-Y8SRfPGM.js} +7 -135
  55. package/dist/element-search-Y8SRfPGM.js.map +1 -0
  56. package/dist/form-CsXJX15p.js +64 -0
  57. package/dist/form-CsXJX15p.js.map +1 -0
  58. package/dist/form.d.ts +15 -0
  59. package/dist/form.d.ts.map +1 -0
  60. package/dist/form.js +2 -0
  61. package/dist/grouped-item-lister-CNLMgdIr.d.ts +121 -0
  62. package/dist/grouped-item-lister-CNLMgdIr.d.ts.map +1 -0
  63. package/dist/grouped-item-lister.d.ts +2 -0
  64. package/dist/grouped-item-lister.js +177 -0
  65. package/dist/grouped-item-lister.js.map +1 -0
  66. package/dist/{hex-editor-B-UI4OZu.js → hex-editor-Bk6rxhfg.js} +6 -8
  67. package/dist/{hex-editor-B-UI4OZu.js.map → hex-editor-Bk6rxhfg.js.map} +1 -1
  68. package/dist/{hex-editor-CMIxtNgT.d.ts → hex-editor-Caq8vNQk.d.ts} +2 -3
  69. package/dist/hex-editor-Caq8vNQk.d.ts.map +1 -0
  70. package/dist/hex.d.ts +1 -1
  71. package/dist/hex.js +1 -1
  72. package/dist/highlight-B-eQrhhb.js.map +1 -1
  73. package/dist/{icon-Bd5BiU4b.d.ts → icon-BUwP1CZ1.d.ts} +3 -4
  74. package/dist/icon-BUwP1CZ1.d.ts.map +1 -0
  75. package/dist/{icon-CK14NUcE.js → icons-Bm2ByQ3s.js} +10 -5
  76. package/dist/icons-Bm2ByQ3s.js.map +1 -0
  77. package/dist/icons.d.ts +2 -2
  78. package/dist/icons.js +2 -8
  79. package/dist/incr-search-vCzuao-2.js +137 -0
  80. package/dist/incr-search-vCzuao-2.js.map +1 -0
  81. package/dist/incr-search.d.ts +1 -1
  82. package/dist/incr-search.js +2 -1
  83. package/dist/{index-DrKRD8_a.d.ts → index-BOUaDIW-.d.ts} +4 -4
  84. package/dist/index-BOUaDIW-.d.ts.map +1 -0
  85. package/dist/{index-CkMIKEWp.d.ts → index-BUB5SICW.d.ts} +3 -4
  86. package/dist/index-BUB5SICW.d.ts.map +1 -0
  87. package/dist/{index-tX6fKF8m.d.ts → index-BeuCXtiO.d.ts} +3 -3
  88. package/dist/index-BeuCXtiO.d.ts.map +1 -0
  89. package/dist/{index-BslNaMLo.d.ts → index-Cu5i8zZY.d.ts} +3 -3
  90. package/dist/index-Cu5i8zZY.d.ts.map +1 -0
  91. package/dist/{index-D87kRcEs.d.ts → index-RqMh1i-O.d.ts} +2 -1
  92. package/dist/index-RqMh1i-O.d.ts.map +1 -0
  93. package/dist/{index-Cdmrn0SZ.d.ts → index-ovq_GTdl.d.ts} +11 -11
  94. package/dist/index-ovq_GTdl.d.ts.map +1 -0
  95. package/dist/index.d.ts +139 -599
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +789 -2845
  98. package/dist/index.js.map +1 -1
  99. package/dist/{labelled-input-base-ORb1rGq6.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -3
  100. package/dist/labelled-input-base-Dp_9KP0G.d.ts.map +1 -0
  101. package/dist/{labelled-input-base-9K_w3oLj.js → labelled-input-base-hoKGwyKT.js} +2 -2
  102. package/dist/{labelled-input-base-9K_w3oLj.js.map → labelled-input-base-hoKGwyKT.js.map} +1 -1
  103. package/dist/labelled-radial-input.d.ts +4 -5
  104. package/dist/labelled-radial-input.d.ts.map +1 -1
  105. package/dist/labelled-radial-input.js +2 -3
  106. package/dist/labelled-radial-input.js.map +1 -1
  107. package/dist/labelled-range-input.d.ts +1 -1
  108. package/dist/labelled-range-input.js +2 -2
  109. package/dist/labelled-range-input.js.map +1 -1
  110. package/dist/led.d.ts +1 -2
  111. package/dist/led.d.ts.map +1 -1
  112. package/dist/led.js +1 -1
  113. package/dist/led.js.map +1 -1
  114. package/dist/menu-DIfU70AA.js +1609 -0
  115. package/dist/menu-DIfU70AA.js.map +1 -0
  116. package/dist/{menu-item-AtoP6bD4.d.ts → menu-item-BG5w7fi4.d.ts} +4 -4
  117. package/dist/menu-item-BG5w7fi4.d.ts.map +1 -0
  118. package/dist/menu.d.ts +2 -2
  119. package/dist/menu.js +1 -2
  120. package/dist/miller.d.ts +7 -5
  121. package/dist/miller.d.ts.map +1 -1
  122. package/dist/miller.js +23 -25
  123. package/dist/miller.js.map +1 -1
  124. package/dist/narrowed-text.d.ts +1 -2
  125. package/dist/narrowed-text.d.ts.map +1 -1
  126. package/dist/narrowed-text.js +14 -13
  127. package/dist/narrowed-text.js.map +1 -1
  128. package/dist/notification-pill-DyZydXoZ.d.ts +68 -0
  129. package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -0
  130. package/dist/notifier.d.ts +2 -0
  131. package/dist/notifier.js +146 -0
  132. package/dist/notifier.js.map +1 -0
  133. package/dist/panel.d.ts +1 -1
  134. package/dist/panel.d.ts.map +1 -1
  135. package/dist/panel.js +1 -2
  136. package/dist/panel.js.map +1 -1
  137. package/dist/plots.d.ts +1 -1
  138. package/dist/plots.js +1 -1
  139. package/dist/polar-pad.d.ts +1 -2
  140. package/dist/polar-pad.d.ts.map +1 -1
  141. package/dist/polar-pad.js +2 -2
  142. package/dist/polar-pad.js.map +1 -1
  143. package/dist/{radial-input-Dhu5ZGP5.d.ts → radial-input-BhZeyyP-.d.ts} +2 -3
  144. package/dist/radial-input-BhZeyyP-.d.ts.map +1 -0
  145. package/dist/{radial-input-C4f-2Bya.js → radial-input-Dk8Wydp5.js} +26 -16
  146. package/dist/radial-input-Dk8Wydp5.js.map +1 -0
  147. package/dist/radial-input.d.ts +1 -1
  148. package/dist/radial-input.js +1 -1
  149. package/dist/range-input.d.ts +2 -3
  150. package/dist/range-input.d.ts.map +1 -1
  151. package/dist/range-input.js +2 -2
  152. package/dist/range-input.js.map +1 -1
  153. package/dist/range.d.ts +2 -3
  154. package/dist/range.d.ts.map +1 -1
  155. package/dist/range.js +2 -2
  156. package/dist/range.js.map +1 -1
  157. package/dist/scroll-fade-CAs1EabA.js +70 -0
  158. package/dist/scroll-fade-CAs1EabA.js.map +1 -0
  159. package/dist/select-horiz.d.ts +50 -0
  160. package/dist/select-horiz.d.ts.map +1 -0
  161. package/dist/select-horiz.js +263 -0
  162. package/dist/select-horiz.js.map +1 -0
  163. package/dist/{slider-input-SW7e2Ac2.js → slider-input-CT4gcF-o.js} +30 -27
  164. package/dist/{slider-input-SW7e2Ac2.js.map → slider-input-CT4gcF-o.js.map} +1 -1
  165. package/dist/{slider-input-BEaztT-g.d.ts → slider-input-TidGhvXt.d.ts} +2 -3
  166. package/dist/slider-input-TidGhvXt.d.ts.map +1 -0
  167. package/dist/slider-input.d.ts +1 -1
  168. package/dist/slider-input.js +1 -1
  169. package/dist/snackbar.d.ts +58 -0
  170. package/dist/snackbar.d.ts.map +1 -0
  171. package/dist/snackbar.js +265 -0
  172. package/dist/snackbar.js.map +1 -0
  173. package/dist/snap-container.d.ts +1 -2
  174. package/dist/snap-container.d.ts.map +1 -1
  175. package/dist/snap-container.js +6 -5
  176. package/dist/snap-container.js.map +1 -1
  177. package/dist/split-layout.d.ts +1 -2
  178. package/dist/split-layout.d.ts.map +1 -1
  179. package/dist/split-layout.js +5 -3
  180. package/dist/split-layout.js.map +1 -1
  181. package/dist/swipe.d.ts +1 -2
  182. package/dist/swipe.d.ts.map +1 -1
  183. package/dist/swipe.js +4 -3
  184. package/dist/swipe.js.map +1 -1
  185. package/dist/{tab-list-B8v9KntS.d.ts → tab-list-Beuh2nom.d.ts} +4 -4
  186. package/dist/tab-list-Beuh2nom.d.ts.map +1 -0
  187. package/dist/tabs.d.ts +1 -1
  188. package/dist/tabs.js +533 -1
  189. package/dist/tabs.js.map +1 -0
  190. package/dist/{tickled-controller-JDOR9B8V.d.ts → tickled-controller-BtevrRLV.d.ts} +1 -2
  191. package/dist/tickled-controller-BtevrRLV.d.ts.map +1 -0
  192. package/dist/{tickled-styles-Bgo_Lpw-.js → tickled-controller-DkAU-0qL.js} +2 -88
  193. package/dist/tickled-controller-DkAU-0qL.js.map +1 -0
  194. package/dist/tickled-styles-BrAHEj1q.js +89 -0
  195. package/dist/tickled-styles-BrAHEj1q.js.map +1 -0
  196. package/dist/{timeline-CdSI003L.js → timeline-B2fgDL4U.js} +3 -3
  197. package/dist/{timeline-CdSI003L.js.map → timeline-B2fgDL4U.js.map} +1 -1
  198. package/dist/timeline.d.ts +1 -1
  199. package/dist/timeline.js +1 -1
  200. package/dist/{tooltip-BMTSUPBU.d.ts → tooltip-BlvBUQxx.d.ts} +2 -3
  201. package/dist/tooltip-BlvBUQxx.d.ts.map +1 -0
  202. package/dist/transitory-label.d.ts +30 -0
  203. package/dist/transitory-label.d.ts.map +1 -0
  204. package/dist/transitory-label.js +249 -0
  205. package/dist/transitory-label.js.map +1 -0
  206. package/dist/{tree-CqPhQRHo.js → tree-BO6BXI2b.js} +9 -10
  207. package/dist/{tree-CqPhQRHo.js.map → tree-BO6BXI2b.js.map} +1 -1
  208. package/dist/{tree-component-CDLO1ITF.d.ts → tree-component-BvV4muxx.d.ts} +8 -124
  209. package/dist/tree-component-BvV4muxx.d.ts.map +1 -0
  210. package/dist/tree.d.ts +9 -4
  211. package/dist/tree.d.ts.map +1 -1
  212. package/dist/tree.js +1 -1
  213. package/dist/types-Bc23SI94.d.ts +72 -0
  214. package/dist/types-Bc23SI94.d.ts.map +1 -0
  215. package/dist/types-DlVNJez_.d.ts +41 -0
  216. package/dist/types-DlVNJez_.d.ts.map +1 -0
  217. package/dist/vertical-list.d.ts +122 -0
  218. package/dist/vertical-list.d.ts.map +1 -0
  219. package/dist/vertical-list.js +737 -0
  220. package/dist/vertical-list.js.map +1 -0
  221. package/dist/{wheel-nudge-Dhzi5nHc.js → wheel-nudge-BlSCe_hD.js} +2 -2
  222. package/dist/{wheel-nudge-Dhzi5nHc.js.map → wheel-nudge-BlSCe_hD.js.map} +1 -1
  223. package/dist/{wheel-nudge-C-ra_1os.d.ts → wheel-nudge-DgMTRYlh.d.ts} +1 -2
  224. package/dist/wheel-nudge-DgMTRYlh.d.ts.map +1 -0
  225. package/dist/{xy-axis-CtDDQzGZ.d.ts → xy-axis-5KhVTNoX.d.ts} +8 -6
  226. package/dist/xy-axis-5KhVTNoX.d.ts.map +1 -0
  227. package/dist/{xy-axis-BpA2eJq6.js → xy-axis-B6yMjckW.js} +8 -112
  228. package/dist/xy-axis-B6yMjckW.js.map +1 -0
  229. package/dist/xy-pad.d.ts +1 -2
  230. package/dist/xy-pad.d.ts.map +1 -1
  231. package/dist/xy-pad.js +2 -2
  232. package/dist/xy-pad.js.map +1 -1
  233. package/docs-user/README.md +4 -2
  234. package/docs-user/data-grid.md +248 -0
  235. package/docs-user/index.json +222 -0
  236. package/docs-user/llms.txt +58 -0
  237. package/docs-user/rating.md +102 -0
  238. package/docs-user/toolbar.md +135 -0
  239. package/llms.txt +58 -0
  240. package/package.json +21 -11
  241. package/dist/crumb-navigation-Pif-kupA.js +0 -1221
  242. package/dist/crumb-navigation-Pif-kupA.js.map +0 -1
  243. package/dist/defaults-BkWCPJFL.js.map +0 -1
  244. package/dist/hex-editor-CMIxtNgT.d.ts.map +0 -1
  245. package/dist/icon-Bd5BiU4b.d.ts.map +0 -1
  246. package/dist/icon-CK14NUcE.js.map +0 -1
  247. package/dist/icons.js.map +0 -1
  248. package/dist/incr-search-CeERfijK.js.map +0 -1
  249. package/dist/index-BslNaMLo.d.ts.map +0 -1
  250. package/dist/index-Cdmrn0SZ.d.ts.map +0 -1
  251. package/dist/index-CkMIKEWp.d.ts.map +0 -1
  252. package/dist/index-D87kRcEs.d.ts.map +0 -1
  253. package/dist/index-DrKRD8_a.d.ts.map +0 -1
  254. package/dist/index-tX6fKF8m.d.ts.map +0 -1
  255. package/dist/interaction-_Y2qO3QI.js +0 -1
  256. package/dist/labelled-input-base-ORb1rGq6.d.ts.map +0 -1
  257. package/dist/menu-BiFarLUA.js +0 -826
  258. package/dist/menu-BiFarLUA.js.map +0 -1
  259. package/dist/menu-item-AtoP6bD4.d.ts.map +0 -1
  260. package/dist/menu-item-yHSPV8nS.js +0 -783
  261. package/dist/menu-item-yHSPV8nS.js.map +0 -1
  262. package/dist/radial-input-C4f-2Bya.js.map +0 -1
  263. package/dist/radial-input-Dhu5ZGP5.d.ts.map +0 -1
  264. package/dist/registry-CkW7q09Q.js +0 -21
  265. package/dist/registry-CkW7q09Q.js.map +0 -1
  266. package/dist/selecthorizontal.d.ts +0 -16
  267. package/dist/selecthorizontal.d.ts.map +0 -1
  268. package/dist/selecthorizontal.js +0 -43
  269. package/dist/selecthorizontal.js.map +0 -1
  270. package/dist/slider-input-BEaztT-g.d.ts.map +0 -1
  271. package/dist/tab-list-B8v9KntS.d.ts.map +0 -1
  272. package/dist/tab-list-CR0v53KJ.js +0 -615
  273. package/dist/tab-list-CR0v53KJ.js.map +0 -1
  274. package/dist/tickled-controller-JDOR9B8V.d.ts.map +0 -1
  275. package/dist/tickled-styles-Bgo_Lpw-.js.map +0 -1
  276. package/dist/tooltip-BMTSUPBU.d.ts.map +0 -1
  277. package/dist/tree-component-CDLO1ITF.d.ts.map +0 -1
  278. package/dist/types-DSfbtHs3.d.ts +0 -8
  279. package/dist/types-DSfbtHs3.d.ts.map +0 -1
  280. package/dist/wheel-nudge-C-ra_1os.d.ts.map +0 -1
  281. package/dist/xy-axis-BpA2eJq6.js.map +0 -1
  282. package/dist/xy-axis-CtDDQzGZ.d.ts.map +0 -1
  283. package/docs-user/selecthorizontal.md +0 -32
  284. /package/bundle/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
  285. /package/dist/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
@@ -1,1221 +0,0 @@
1
- import { n as tickledStyles, r as TickledController, t as tickledItemStyles } from "./tickled-styles-Bgo_Lpw-.js";
2
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
3
- import { n as safeCustomElement, t as __decorate } from "./decorate-DdjvVHS-.js";
4
- import "./interaction-_Y2qO3QI.js";
5
- import "./menu-item-yHSPV8nS.js";
6
- import { t as collectDataResult } from "./data-provider-35TyWclX.js";
7
- import "./narrowed-text.js";
8
- import { LitElement, css, html, nothing, unsafeCSS } from "lit";
9
- import { property, state } from "lit/decorators.js";
10
- //#region src/styles/scroll-fade.ts
11
- /**
12
- * Zero-JS scroll edge fade.
13
- *
14
- * A CSS alpha mask driven by a scroll-linked animation (`scroll-timeline`),
15
- * rather than a JS scroll/resize listener - so it can never go stale after
16
- * a resize (widening a scroller so content fully fits clears the fade
17
- * immediately, with no JS involved), and it fades the whole element
18
- * including its children, not just a background layer that an opaque
19
- * item background would hide.
20
- *
21
- * Apply the returned `.scroll-fade-x` / `.scroll-fade-y` class to
22
- * whichever element actually has `overflow` scrolling on that axis.
23
- *
24
- * CSS variables:
25
- * - `--scroll-fade-width` (default `30px`): how far the fade extends from each edge.
26
- *
27
- * ```ts
28
- * import { scrollFadeStyles } from '../styles/scroll-fade.js';
29
- *
30
- * static styles = [scrollFadeStyles(`x`), css`...`];
31
- * ```
32
- * ```html
33
- * <div class="scroll-fade-x" style="overflow-x: scroll">...</div>
34
- * ```
35
- */
36
- function scrollFadeStyles(axis) {
37
- const className = `scroll-fade-${axis}`;
38
- const start = `--${className}-start`;
39
- const end = `--${className}-end`;
40
- const timeline = `--${className}-timeline`;
41
- const keyframesName = `${className}-fade`;
42
- const gradientDirection = axis === `x` ? `to right` : `to bottom`;
43
- return css`
44
- @property ${unsafeCSS(start)} {
45
- syntax: '<length>';
46
- inherits: false;
47
- initial-value: 0px;
48
- }
49
-
50
- @property ${unsafeCSS(end)} {
51
- syntax: '<length>';
52
- inherits: false;
53
- initial-value: 0px;
54
- }
55
-
56
- @keyframes ${unsafeCSS(keyframesName)} {
57
- 0% { ${unsafeCSS(start)}: 0px; }
58
- 10%, 100% { ${unsafeCSS(start)}: var(--scroll-fade-width, 30px); }
59
- 0%, 90% { ${unsafeCSS(end)}: var(--scroll-fade-width, 30px); }
60
- 100% { ${unsafeCSS(end)}: 0px; }
61
- }
62
-
63
- .${unsafeCSS(className)} {
64
- scroll-timeline: ${unsafeCSS(timeline)} ${unsafeCSS(axis)};
65
- animation: ${unsafeCSS(keyframesName)};
66
- animation-timeline: ${unsafeCSS(timeline)};
67
- mask-image: linear-gradient(${unsafeCSS(gradientDirection)},
68
- transparent,
69
- black var(${unsafeCSS(start)}, 0px) calc(100% - var(${unsafeCSS(end)}, 0px)),
70
- transparent
71
- );
72
- }
73
- `;
74
- }
75
- //#endregion
76
- //#region src/crumbs/crumb-navigation.ts
77
- let CrumbNavigationElement = class CrumbNavigationElement extends LitElement {
78
- constructor(..._args) {
79
- super(..._args);
80
- this._selectedNodes = /* @__PURE__ */ new Set();
81
- this.exclusivity = `none`;
82
- this.selectionFilter = `leaf`;
83
- this._openIdx = -1;
84
- this._isFocused = false;
85
- this._menuOpen = false;
86
- this._focusOnNarrowedText = false;
87
- this.inputMode = ``;
88
- this.noTruncate = false;
89
- this.showSuggestions = false;
90
- this.leadingCaret = false;
91
- this.caretEmbedded = true;
92
- this.hideRoot = false;
93
- this.padEnding = false;
94
- this.withUp = false;
95
- this.#previousSelectionKey = ``;
96
- this.#menuOpenedByKeyboard = false;
97
- this.#currentOpenTrigger = null;
98
- this.tickled = new TickledController(this, {
99
- getItems: () => this.#getTickledItems(),
100
- onTickle: (index) => {
101
- if (index !== void 0) this.#onTickled(index);
102
- }
103
- });
104
- this.#onFocus = () => {
105
- this._isFocused = true;
106
- };
107
- this.#onBlur = () => {
108
- this._isFocused = false;
109
- };
110
- this.#onHostClick = () => {
111
- this.#getHostContainer()?.focus();
112
- };
113
- this.#onMenuTriggerClose = () => {
114
- document.removeEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
115
- this.#currentOpenTrigger = null;
116
- this.#menuOpenedByKeyboard = false;
117
- requestAnimationFrame(() => {
118
- this.#getHostContainer()?.focus();
119
- });
120
- };
121
- this.#onMenuKeyNav = (e) => {
122
- if (!this.#currentOpenTrigger?.querySelector(`ixfx-menu-container`) || !this.#currentOpenTrigger?.isOpen) return;
123
- switch (e.key) {
124
- case `ArrowLeft`:
125
- case `ArrowRight`: {
126
- e.preventDefault();
127
- e.stopPropagation();
128
- this.#currentOpenTrigger.closeMenu();
129
- const r = this.root;
130
- const sel = this.selectedNode;
131
- if (!r || !sel) break;
132
- const totalItems = this.#getTickledItems().length;
133
- const currentTickled = this.tickled.tickledId ?? -1;
134
- if (e.key === `ArrowLeft`) {
135
- if (currentTickled > 0) this.tickled.handleKeyboardNavigation(`previous`);
136
- } else if (currentTickled < totalItems - 1) this.tickled.handleKeyboardNavigation(`next`);
137
- break;
138
- }
139
- }
140
- };
141
- this.#onKeyDown = (e) => {
142
- const r = this.root;
143
- const sel = this.selectedNode;
144
- if (!r || !sel) return;
145
- const totalItems = this.#getTickledItems().length;
146
- const currentTickled = this.tickled.tickledId ?? -1;
147
- switch (e.key) {
148
- case `ArrowRight`:
149
- e.preventDefault();
150
- if (currentTickled < totalItems - 1) this.tickled.handleKeyboardNavigation(`next`);
151
- else if (currentTickled === totalItems - 1 && this.#canFocusSuggestions()) this.#shiftFocusToNarrowedText();
152
- break;
153
- case `ArrowLeft`:
154
- e.preventDefault();
155
- if (currentTickled > 0) this.tickled.handleKeyboardNavigation(`previous`);
156
- break;
157
- case `ArrowDown`:
158
- case `ArrowUp`:
159
- if (this.tickled.tickledId !== void 0) {
160
- e.preventDefault();
161
- if (this.#currentOpenTrigger?.isOpen) {
162
- const popover = this.#currentOpenTrigger.querySelector(`ixfx-menu-container`)?.shadowRoot?.querySelector(`.popover`);
163
- if (popover) popover.dispatchEvent(new KeyboardEvent(`keydown`, {
164
- key: e.key,
165
- bubbles: true
166
- }));
167
- } else this.#handleOpenCaretMenu();
168
- }
169
- break;
170
- case `Enter`:
171
- case ` `:
172
- e.preventDefault();
173
- this.#activateTickled();
174
- break;
175
- case `Escape`:
176
- e.preventDefault();
177
- this._menuOpen = false;
178
- this.tickled.clearTickled();
179
- this.blur();
180
- break;
181
- case `Tab`:
182
- if (e.shiftKey) break;
183
- if (currentTickled === totalItems - 1 && this.#canFocusSuggestions()) {
184
- e.preventDefault();
185
- this.#shiftFocusToNarrowedText();
186
- }
187
- break;
188
- }
189
- };
190
- this.#onNarrowedTextBlur = () => {
191
- this._focusOnNarrowedText = false;
192
- this.#shiftFocusToPath();
193
- };
194
- this.#onNarrowedTextShiftTab = () => {
195
- this._focusOnNarrowedText = false;
196
- this.#shiftFocusToPath();
197
- };
198
- this.#isWheelScrolling = false;
199
- this.#onWheel = (e) => {
200
- const wheelEvent = e;
201
- if (wheelEvent.deltaX !== 0 || wheelEvent.deltaY !== 0) {
202
- e.preventDefault();
203
- if (!this.#isWheelScrolling) {
204
- this.#isWheelScrolling = true;
205
- this.tickled.clearTickled();
206
- }
207
- const hostContainer = this.#getHostContainer();
208
- if (hostContainer) hostContainer.scrollLeft += wheelEvent.deltaX + wheelEvent.deltaY;
209
- clearTimeout(this.#wheelScrollTimeout);
210
- this.#wheelScrollTimeout = setTimeout(() => {
211
- this.#isWheelScrolling = false;
212
- }, 150);
213
- }
214
- };
215
- this.#currentLeadingSiblings = void 0;
216
- }
217
- get selectedNodes() {
218
- return this._selectedNodes;
219
- }
220
- #pendingNode;
221
- #pendingController;
222
- #modelUnsubscribe;
223
- #previousSelectionKey;
224
- #menuOpenedByKeyboard;
225
- #currentOpenTrigger;
226
- #getTickledItems() {
227
- const r = this.root;
228
- const sel = this.selectedNode;
229
- if (!r || !sel) return [];
230
- const pathNodes = this.#findPath(r, sel) ?? [r];
231
- const items = [];
232
- if (this.caretEmbedded) {
233
- pathNodes.forEach((_node, i) => {
234
- items.push({
235
- id: i,
236
- enabled: true
237
- });
238
- });
239
- if (this.#canFocusSuggestions()) items.push({
240
- id: pathNodes.length,
241
- enabled: true
242
- });
243
- } else {
244
- let segmentId = 0;
245
- pathNodes.forEach((node, i) => {
246
- const isLast = i === pathNodes.length - 1;
247
- const hasChildren = node.item.isLeaf !== true && (node.children === void 0 || node.children.length > 0);
248
- const showLeadingCaret = this.leadingCaret && (i > 0 || this.hideRoot) && hasChildren;
249
- const showTrailingCaret = !this.leadingCaret && hasChildren || this.leadingCaret && isLast && hasChildren;
250
- if (showLeadingCaret) items.push({
251
- id: segmentId++,
252
- enabled: true
253
- });
254
- items.push({
255
- id: segmentId++,
256
- enabled: true
257
- });
258
- if (showTrailingCaret) items.push({
259
- id: segmentId++,
260
- enabled: true
261
- });
262
- });
263
- }
264
- return items;
265
- }
266
- #onTickled(index) {
267
- if (this.tickled.inputMode === `keyboard`) this.#scrollTickledIntoView(index);
268
- }
269
- #scrollTickledIntoView(index) {
270
- const r = this.root;
271
- const sel = this.selectedNode;
272
- if (!r || !sel) return;
273
- const pathNodes = this.#findPath(r, sel) ?? [r];
274
- let el = null;
275
- if (this.caretEmbedded && this.#canFocusSuggestions() && index === pathNodes.length) el = this.shadowRoot?.querySelector(`ixfx-narrowed-text`) ?? null;
276
- else el = this.shadowRoot?.querySelectorAll(`.crumb-segment`)[index] ?? null;
277
- el?.scrollIntoView({
278
- inline: `nearest`,
279
- block: `nearest`,
280
- behavior: `smooth`
281
- });
282
- }
283
- #hasChildOptions() {
284
- const s = this.selectedNode;
285
- if (s === void 0) return false;
286
- const isPending = this.#pendingNode === s;
287
- return (s.children ?? []).length > 0 || isPending;
288
- }
289
- /** True when the suggestions (narrowed-text) sub-part is renderable and focusable. */
290
- #canFocusSuggestions() {
291
- return this.showSuggestions && this.#hasChildOptions();
292
- }
293
- #onFocus;
294
- #onBlur;
295
- #getHostContainer() {
296
- return this.shadowRoot?.querySelector(`.host-container`) ?? null;
297
- }
298
- #onHostClick;
299
- #handleOpenCaretMenu() {
300
- const currentTickled = this.tickled.tickledId;
301
- if (currentTickled === void 0) return;
302
- const r = this.root;
303
- const sel = this.selectedNode;
304
- if (!r || !sel) return;
305
- const pathNodes = this.#findPath(r, sel) ?? [r];
306
- if (this.caretEmbedded && this.#canFocusSuggestions() && currentTickled === pathNodes.length) {
307
- this.#shiftFocusToNarrowedText();
308
- return;
309
- }
310
- const trigger = (this.shadowRoot?.querySelectorAll(`.crumb-segment`))?.[currentTickled]?.querySelector(`.caret ixfx-menu-trigger`);
311
- if (trigger) {
312
- this.#menuOpenedByKeyboard = true;
313
- this.#currentOpenTrigger = trigger;
314
- document.addEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
315
- trigger.openMenu();
316
- this.#propagateInputModeToMenu();
317
- }
318
- }
319
- #propagateInputModeToMenu() {
320
- const inputMode = this.tickled.inputMode;
321
- requestAnimationFrame(() => {
322
- const container = this.#currentOpenTrigger?.querySelector(`ixfx-menu-container`);
323
- if (container) container.setAttribute(`data-input-mode`, inputMode);
324
- });
325
- }
326
- #onMenuTriggerClose;
327
- #onMenuKeyNav;
328
- #onKeyDown;
329
- /** Activates the currently tickled item, as if it had been clicked. */
330
- #activateTickled() {
331
- const currentTickled = this.tickled.tickledId;
332
- if (currentTickled === void 0) return;
333
- const r = this.root;
334
- const sel = this.selectedNode;
335
- if (!r || !sel) return;
336
- const pathNodes = this.#findPath(r, sel) ?? [r];
337
- if (this.caretEmbedded && this.#canFocusSuggestions() && currentTickled === pathNodes.length) {
338
- this.#shiftFocusToNarrowedText();
339
- return;
340
- }
341
- (this.shadowRoot?.querySelector(`.crumb-segment[data-segment-id="${currentTickled}"]`))?.click();
342
- }
343
- #shiftFocusToNarrowedText() {
344
- const narrowedText = this.shadowRoot?.querySelector(`ixfx-narrowed-text`);
345
- if (narrowedText) {
346
- this._menuOpen = false;
347
- this._focusOnNarrowedText = true;
348
- narrowedText.focus();
349
- }
350
- }
351
- #shiftFocusToPath() {
352
- this._focusOnNarrowedText = false;
353
- const hostContainer = this.#getHostContainer();
354
- if (hostContainer) hostContainer.focus();
355
- }
356
- #onNarrowedTextBlur;
357
- #onNarrowedTextShiftTab;
358
- select(node) {
359
- this.#setSelected(node);
360
- }
361
- deselect(_node) {}
362
- clearSelection() {
363
- if (this.root) this.#setSelected(this.root);
364
- }
365
- /** Not implemented on crumb-navigation. */
366
- selectAll() {}
367
- /** Not implemented on crumb-navigation. */
368
- deselectAll() {}
369
- getNodes() {
370
- if (!this.root) return [];
371
- const result = [];
372
- const visit = (node, depth) => {
373
- result.push({
374
- node,
375
- depth
376
- });
377
- if (node.children) for (const child of node.children) visit(child, depth + 1);
378
- };
379
- for (const child of this.root.children ?? []) visit(child, 0);
380
- return result;
381
- }
382
- updated(changedProps) {
383
- if (changedProps.has(`model`)) {
384
- this.#modelUnsubscribe?.();
385
- this.#modelUnsubscribe = void 0;
386
- const model = this.model;
387
- if (model) {
388
- this.root = model.root;
389
- this.#modelUnsubscribe = model._subscribe((event) => {
390
- if (event.type === `root`) {
391
- this.root = event.root;
392
- this.requestUpdate();
393
- }
394
- });
395
- }
396
- }
397
- this.#runLayoutUpdate(changedProps);
398
- }
399
- connectedCallback() {
400
- super.connectedCallback();
401
- this.addEventListener(`click`, this.#onHostClick);
402
- this.addEventListener(`wheel`, this.#onWheel, { passive: false });
403
- }
404
- disconnectedCallback() {
405
- super.disconnectedCallback();
406
- this.removeEventListener(`click`, this.#onHostClick);
407
- this.removeEventListener(`wheel`, this.#onWheel);
408
- this.#modelUnsubscribe?.();
409
- this.#modelUnsubscribe = void 0;
410
- document.removeEventListener(`keydown`, this.#onMenuKeyNav, { capture: true });
411
- this.#currentOpenTrigger = null;
412
- }
413
- firstUpdated() {
414
- const hostContainer = this.#getHostContainer();
415
- if (hostContainer) hostContainer.scrollLeft = hostContainer.scrollWidth - hostContainer.clientWidth;
416
- }
417
- #isWheelScrolling;
418
- #onWheel;
419
- #wheelScrollTimeout;
420
- #runLayoutUpdate(_changedProperties) {
421
- if (!this.shadowRoot) return;
422
- const hsiElement = this.shadowRoot.querySelector(`.horiz-select-items`);
423
- if (!hsiElement) return;
424
- const ulElement = hsiElement.querySelector(`ul`);
425
- if (!ulElement) return;
426
- const menuTrigger = this.shadowRoot.querySelector(`ixfx-menu-trigger`);
427
- if (!menuTrigger) return;
428
- if (ulElement.getBoundingClientRect().width > hsiElement.getBoundingClientRect().width) menuTrigger.style.display = `inline-flex`;
429
- else menuTrigger.style.display = `none`;
430
- for (const li of ulElement.querySelectorAll(`li`)) if ((li.getAttribute(`data-key`) ?? ``) === this.#previousSelectionKey) {
431
- this.#scrollToValue(li);
432
- break;
433
- }
434
- }
435
- #scrollToValue(li) {
436
- let l = li.offsetLeft;
437
- const ul = li.parentElement;
438
- if (!ul) return;
439
- l -= ul.offsetLeft;
440
- const horizSelectItems = ul.parentElement;
441
- if (!horizSelectItems) return;
442
- horizSelectItems.scroll({
443
- left: l,
444
- top: 0,
445
- behavior: `smooth`
446
- });
447
- const horizSelect = horizSelectItems.parentElement;
448
- if (!horizSelect) return;
449
- horizSelect.style.minWidth = `${li.getBoundingClientRect().width}px`;
450
- }
451
- #abortPending() {
452
- if (this.#pendingController) {
453
- this.#pendingController.abort();
454
- this.#pendingController = void 0;
455
- this.#pendingNode = void 0;
456
- }
457
- }
458
- #findPath(node, target, acc = []) {
459
- const path = [...acc, node];
460
- if (node === target) return path;
461
- if (!node.children) return void 0;
462
- for (const child of node.children) {
463
- const result = this.#findPath(child, target, path);
464
- if (result) return result;
465
- }
466
- }
467
- #scrollSegmentIntoView(depth) {
468
- if (!this.shadowRoot) return;
469
- this.shadowRoot.querySelectorAll(`.crumb-segment`)[depth]?.scrollIntoView({
470
- block: `nearest`,
471
- inline: `start`
472
- });
473
- }
474
- #updateTrailingWidth() {
475
- if (!this.padEnding || !this.shadowRoot) return;
476
- const hostContainer = this.shadowRoot.querySelector(`.host-container`);
477
- const trailing = this.shadowRoot.querySelector(`.trailing`);
478
- if (!hostContainer || !trailing) return;
479
- const segments = this.shadowRoot.querySelectorAll(`.crumb-segment`);
480
- const lastSegment = segments[segments.length - 1];
481
- if (!lastSegment) return;
482
- const containerWidth = hostContainer.getBoundingClientRect().width;
483
- const itemWidth = lastSegment.getBoundingClientRect().width;
484
- if (itemWidth < containerWidth) {
485
- trailing.style.width = `${containerWidth - itemWidth - 5}px`;
486
- requestAnimationFrame(() => {
487
- if (hostContainer.scrollWidth <= hostContainer.clientWidth) hostContainer.style.setProperty(`--scroll-fade-x-start`, `0px`, `important`);
488
- else hostContainer.style.removeProperty(`--scroll-fade-x-start`);
489
- });
490
- } else trailing.style.width = ``;
491
- }
492
- #setSelected(node) {
493
- const previous = this.selectedNode;
494
- if (previous) this.#previousSelectionKey = previous.item?.key ?? ``;
495
- else this.#previousSelectionKey = ``;
496
- const previousSet = previous ? new Set([previous]) : /* @__PURE__ */ new Set();
497
- this.selectedNode = node;
498
- this._selectedNodes = new Set([node]);
499
- if (this.root) {
500
- const path = this.#findPath(this.root, node);
501
- if (path) {
502
- const depth = this.hideRoot && path.length > 1 ? path.length - 2 : path.length - 1;
503
- requestAnimationFrame(() => {
504
- this.#updateTrailingWidth();
505
- const hostContainer = this.#getHostContainer();
506
- if (hostContainer) hostContainer.scrollLeft = 0;
507
- this.#scrollSegmentIntoView(depth);
508
- });
509
- }
510
- }
511
- this.dispatchEvent(new CustomEvent(`select`, {
512
- detail: {
513
- selected: new Set([node]),
514
- previous: previousSet
515
- },
516
- bubbles: true,
517
- composed: true
518
- }));
519
- }
520
- #onLabelClick(node, depth) {
521
- this._openIdx = -1;
522
- this.#setSelected(node);
523
- this.#scrollSegmentIntoView(depth);
524
- this.dispatchEvent(new CustomEvent(`item-click`, {
525
- detail: {
526
- node,
527
- depth
528
- },
529
- bubbles: true,
530
- composed: true
531
- }));
532
- }
533
- #onCaretClick(node, depth, e) {
534
- e.preventDefault();
535
- e.stopPropagation();
536
- if (this._openIdx === depth) {
537
- this._openIdx = -1;
538
- return;
539
- }
540
- this._openIdx = depth;
541
- if (node.children === void 0 && this.#pendingNode !== node) {
542
- this.#abortPending();
543
- this.#pendingNode = node;
544
- const controller = new AbortController();
545
- this.#pendingController = controller;
546
- if (this.loadChildren) this.#invokeLoadChildren(node, depth, controller).catch(() => {});
547
- }
548
- this.requestUpdate();
549
- }
550
- async #invokeLoadChildren(node, depth, controller) {
551
- try {
552
- const children = [...await collectDataResult(this.loadChildren({
553
- node,
554
- depth
555
- }, controller.signal), controller.signal)];
556
- if (controller.signal.aborted) return;
557
- node.children = children;
558
- this.#pendingNode = void 0;
559
- this.#pendingController = void 0;
560
- this.dispatchEvent(new CustomEvent(`expand`, {
561
- detail: {
562
- node,
563
- depth
564
- },
565
- bubbles: true,
566
- composed: true
567
- }));
568
- this.requestUpdate();
569
- } catch {
570
- if (controller.signal.aborted) return;
571
- node.children = [];
572
- this.#pendingNode = void 0;
573
- this.#pendingController = void 0;
574
- this.requestUpdate();
575
- }
576
- }
577
- #onSegmentMenuCommand(e, node, depth) {
578
- const key = e.detail.command;
579
- if (this.leadingCaret) {
580
- const child = node.children?.find((c) => c.item.key === key);
581
- if (child) {
582
- this.#onChildClick(child, depth + 1);
583
- return;
584
- }
585
- if (this.#currentLeadingSiblings) {
586
- const sibling = this.#currentLeadingSiblings.find((c) => c.item.key === key);
587
- if (sibling) this.#onChildClick(sibling, depth);
588
- this.#currentLeadingSiblings = void 0;
589
- return;
590
- }
591
- }
592
- const child = node.children?.find((c) => c.item.key === key);
593
- if (child) this.#onChildClick(child, depth + 1);
594
- }
595
- #currentLeadingSiblings;
596
- #getSiblingMenuItems(pathNodes, index) {
597
- if (index === 0) {
598
- if (!this.hideRoot || !this.root) return [];
599
- const siblings = [...this.root.children ?? []].sort((a, b) => (a.item.label ?? ``).localeCompare(b.item.label ?? ``));
600
- this.#currentLeadingSiblings = siblings;
601
- return siblings.map((sibling) => html`
602
- <ixfx-menu-item
603
- label="${sibling.item.label}"
604
- command="${sibling.item.key}"
605
- icon-name="${sibling.item.icon ?? nothing}"
606
- @click=${() => {
607
- this.#onChildClick(sibling, index);
608
- }}
609
- ></ixfx-menu-item>
610
- `);
611
- }
612
- const siblings = [...pathNodes[index - 1].children ?? []].sort((a, b) => (a.item.label ?? ``).localeCompare(b.item.label ?? ``));
613
- this.#currentLeadingSiblings = siblings;
614
- return siblings.map((sibling) => html`
615
- <ixfx-menu-item
616
- label="${sibling.item.label}"
617
- command="${sibling.item.key}"
618
- icon-name="${sibling.item.icon ?? nothing}"
619
- @click=${() => {
620
- this.#onChildClick(sibling, index);
621
- }}
622
- ></ixfx-menu-item>
623
- `);
624
- }
625
- #onChildClick(node, depth) {
626
- this._openIdx = -1;
627
- this.#setSelected(node);
628
- this.dispatchEvent(new CustomEvent(`item-click`, {
629
- detail: {
630
- node,
631
- depth
632
- },
633
- bubbles: true,
634
- composed: true
635
- }));
636
- }
637
- #onUpClick() {
638
- const r = this.root;
639
- const sel = this.selectedNode;
640
- if (!r || !sel) return;
641
- const path = this.#findPath(r, sel);
642
- if (!path || path.length <= 1) return;
643
- const parent = path[path.length - 2];
644
- this.#setSelected(parent);
645
- }
646
- /** Navigate to a node by key path. Returns false if any key is not found in already-loaded children. */
647
- navigateTo(keys) {
648
- if (!this.root?.children) return false;
649
- let current = this.root;
650
- for (const key of keys) {
651
- const found = current?.children?.find((n) => n.item.key === key);
652
- if (!found) return false;
653
- current = found;
654
- }
655
- if (current && current !== this.root) this.#setSelected(current);
656
- return true;
657
- }
658
- /** Navigate to the first node matching the predicate. Returns false if not found. */
659
- navigateToNode(predicate) {
660
- if (!this.root) return false;
661
- const keyPath = this.#findNodePath(this.root.children ?? [], predicate);
662
- if (!keyPath) return false;
663
- return this.navigateTo(keyPath);
664
- }
665
- #findNodePath(nodes, predicate, prefix = []) {
666
- for (const node of nodes) {
667
- const path = [...prefix, node.item.key];
668
- if (predicate(node)) return path;
669
- if (node.children?.length) {
670
- const result = this.#findNodePath(node.children, predicate, path);
671
- if (result) return result;
672
- }
673
- }
674
- }
675
- #onMenuCommand(e) {
676
- const node = this.selectedNode;
677
- if (!node?.children) return;
678
- const key = e.detail.command;
679
- const child = node.children.find((c) => c.item.key === key);
680
- if (child) {
681
- const depth = this.root ? this.#findPath(this.root, node)?.length ?? 1 : 1;
682
- this.#onChildClick(child, depth);
683
- }
684
- }
685
- render() {
686
- const r = this.root;
687
- const sel = this.selectedNode;
688
- if (!r || !sel) return html``;
689
- this.inputMode = this.tickled.inputMode;
690
- let pathNodes = this.#findPath(r, sel) ?? [r];
691
- if (this.hideRoot && pathNodes.length > 1) pathNodes = pathNodes.slice(1);
692
- this.#hasChildOptions();
693
- const isAtRoot = (() => {
694
- return (this.#findPath(r, sel) ?? [r]).length <= 1;
695
- })();
696
- const parts = [];
697
- let segmentId = 0;
698
- pathNodes.forEach((node, i) => {
699
- const isLast = i === pathNodes.length - 1;
700
- const isPending = this.#pendingNode === node;
701
- const isOpen = this._openIdx === i;
702
- const hasChildren = node.item.isLeaf !== true && (node.children === void 0 || node.children.length > 0);
703
- const isTickled = this.tickled.isTickled(i);
704
- const showLeadingCaret = this.leadingCaret && (i > 0 || this.hideRoot) && hasChildren;
705
- const showTrailingCaret = !this.leadingCaret && hasChildren || this.leadingCaret && isLast && hasChildren;
706
- const siblingMenuItems = showLeadingCaret ? this.#getSiblingMenuItems(pathNodes, i) : [];
707
- const childMenuItems = (node.children ?? []).map((c) => html`
708
- <ixfx-menu-item
709
- label="${c.item.label}"
710
- command="${c.item.key}"
711
- icon-name="${c.item.icon ?? nothing}"
712
- ></ixfx-menu-item>
713
- `);
714
- if (this.caretEmbedded) {
715
- const canTruncate = !this.noTruncate && !isLast && !isTickled;
716
- parts.push(html`
717
- <div class="item crumb-segment ${isTickled ? `tickled` : ``} ${canTruncate ? `truncatable` : ``} ${this.leadingCaret ? `leading-caret` : ``} ${isLast ? `last-label` : ``}" data-segment-id="${i}" data-path-index="${i}"
718
- @click=${(e) => {
719
- if (e.target.closest(`.caret`)) return;
720
- this.#onLabelClick(node, i);
721
- }}
722
- >
723
- ${showLeadingCaret ? html`
724
- <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
725
- ${isPending ? html`<span class="loading-spinner"></span>` : html`
726
- <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
727
- <ixfx-menu-container slot="menu">
728
- ${siblingMenuItems}
729
- </ixfx-menu-container>
730
- </ixfx-menu-trigger>
731
- `}
732
- </span>
733
- ` : nothing}
734
- <span class="label">${node.item.label}</span>
735
- ${showTrailingCaret ? html`
736
- <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
737
- ${isPending ? html`<span class="loading-spinner"></span>` : html`
738
- <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
739
- <ixfx-menu-container slot="menu">
740
- ${childMenuItems}
741
- </ixfx-menu-container>
742
- </ixfx-menu-trigger>
743
- `}
744
- </span>
745
- ` : nothing}
746
- </div>
747
- `);
748
- } else {
749
- const leadingCaretTickled = showLeadingCaret ? this.tickled.isTickled(segmentId) : false;
750
- if (showLeadingCaret) {
751
- parts.push(html`
752
- <div class="item crumb-segment ${leadingCaretTickled ? `tickled` : ``}" data-segment-id="${segmentId}" data-path-index="${i}"
753
- @click=${(e) => {
754
- const trigger = e.target.closest(`.crumb-segment`)?.querySelector(`ixfx-menu-trigger`);
755
- if (trigger) trigger.openMenu();
756
- }}
757
- >
758
- <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
759
- ${isPending ? html`<span class="loading-spinner"></span>` : html`
760
- <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} placement="right-start" @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
761
- <ixfx-menu-container slot="menu">
762
- ${siblingMenuItems}
763
- </ixfx-menu-container>
764
- </ixfx-menu-trigger>
765
- `}
766
- </span>
767
- </div>
768
- `);
769
- segmentId++;
770
- }
771
- const labelTickled = this.tickled.isTickled(segmentId);
772
- const canTruncate = !this.noTruncate && !isLast && !labelTickled;
773
- parts.push(html`
774
- <div class="item crumb-segment ${labelTickled ? `tickled` : ``} ${canTruncate ? `truncatable` : ``} ${isLast ? `last-label` : ``}" data-segment-id="${segmentId}" data-path-index="${i}"
775
- @click=${(e) => {
776
- if (e.target.closest(`.caret`)) return;
777
- this.#onLabelClick(node, i);
778
- }}
779
- >
780
- <span class="label">${node.item.label}</span>
781
- </div>
782
- `);
783
- segmentId++;
784
- if (showTrailingCaret) {
785
- const trailingCaretTickled = this.tickled.isTickled(segmentId);
786
- parts.push(html`
787
- <div class="item crumb-segment ${trailingCaretTickled ? `tickled` : ``}" data-segment-id="${segmentId}" data-path-index="${i}"
788
- @click=${(e) => {
789
- const trigger = e.target.closest(`.crumb-segment`)?.querySelector(`ixfx-menu-trigger`);
790
- if (trigger) trigger.openMenu();
791
- }}
792
- >
793
- <span class="caret ${isOpen ? `open` : ``} ${isPending ? `pending` : ``}">
794
- ${isPending ? html`<span class="loading-spinner"></span>` : html`
795
- <ixfx-menu-trigger mode="trigger" label="›" .tabStop=${false} @menu-command=${(e) => this.#onSegmentMenuCommand(e, node, i)}>
796
- <ixfx-menu-container slot="menu">
797
- ${childMenuItems}
798
- </ixfx-menu-container>
799
- </ixfx-menu-trigger>
800
- `}
801
- </span>
802
- </div>
803
- `);
804
- segmentId++;
805
- }
806
- }
807
- });
808
- return html`
809
- <div class="crumb-wrapper">
810
- ${this.withUp ? html`
811
- <button
812
- class="up-button"
813
- ?disabled=${isAtRoot}
814
- aria-label="Go up one level"
815
- @click=${this.#onUpClick}
816
- >
817
- <ixfx-icon name="folder-up"></ixfx-icon>
818
- </button>
819
- ` : nothing}
820
- <div
821
- class="host-container scroll-fade-x"
822
- tabindex="0"
823
- @focus=${this.#onFocus}
824
- @blur=${this.#onBlur}
825
- @keydown=${this.#onKeyDown}
826
- @click=${this.#onHostClick}
827
- @menu-trigger-close=${this.#onMenuTriggerClose}
828
- @mouseout=${(e) => this.tickled.handlePointerLeave(e)}
829
- >
830
- <div class="parts"
831
- @mouseover=${(e) => {
832
- if (this.#isWheelScrolling) return;
833
- const target = e.target;
834
- if (!(target instanceof HTMLElement)) return;
835
- const segment = target.closest(`.crumb-segment`);
836
- if (!segment) return;
837
- const segmentId = parseInt(segment.dataset.segmentId ?? ``, 10);
838
- if (Number.isNaN(segmentId)) return;
839
- const pathIndex = parseInt(segment.dataset.pathIndex ?? ``, 10);
840
- const node = pathNodes[pathIndex];
841
- if (!node) return;
842
- this.tickled.handlePointerEnter(segmentId);
843
- this.dispatchEvent(new CustomEvent(`tickle`, {
844
- detail: {
845
- node,
846
- depth: pathIndex
847
- },
848
- bubbles: true,
849
- composed: true
850
- }));
851
- }}
852
- >${parts}${this.padEnding ? html`<div class="trailing"></div>` : nothing}</div>
853
- ${this.showSuggestions ? this.#renderChildOptions() : nothing}
854
- </div>
855
- </div>
856
- `;
857
- }
858
- #renderChildOptions() {
859
- const s = this.selectedNode;
860
- if (s === void 0) return nothing;
861
- const isPending = this.#pendingNode === s;
862
- const children = s.children ?? [];
863
- if (children.length === 0 && !isPending) return nothing;
864
- if (isPending) return html`
865
- <div class="horiz-select">
866
- <div class="horiz-select-items">
867
- <span class="loading-spinner"></span>
868
- </div>
869
- </div>
870
- `;
871
- return html`
872
- <ixfx-narrowed-text
873
- class="horiz-select"
874
- selection-mode="single"
875
- orientation="horizontal"
876
- nowrap
877
- width=${this.#getChildOptionsWidth()}
878
- @change=${this.#onNarrowedTextChange}
879
- @narrowed-text-blur=${this.#onNarrowedTextBlur}
880
- @narrowed-text-shift-tab=${this.#onNarrowedTextShiftTab}
881
- >
882
- ${children.map((c) => html`
883
- <span data-value="${c.item.key}" data-label="${c.item.label}"></span>
884
- `)}
885
- </ixfx-narrowed-text>
886
- `;
887
- }
888
- #onNarrowedTextChange(e) {
889
- e.stopPropagation();
890
- const detail = e.detail;
891
- const node = this.selectedNode;
892
- if (!node?.children) return;
893
- const child = node.children.find((c) => c.item.key === detail.item.value);
894
- if (child) {
895
- const depth = this.root ? this.#findPath(this.root, node)?.length ?? 1 : 1;
896
- this.#onChildClick(child, depth);
897
- }
898
- }
899
- #getChildOptionsWidth() {
900
- return `var(--child-options-width, 50ch)`;
901
- }
902
- static {
903
- this.styles = [
904
- themeFallbacks,
905
- tickledStyles,
906
- tickledItemStyles,
907
- scrollFadeStyles(`x`),
908
- css`
909
- :host {
910
- --crumb-item-bg: var(--item-bg, transparent);
911
- --crumb-item-bg-tickled: var(--item-bg-tickled);
912
- --crumb-item-text-tickled: var(--item-text-tickled);
913
- --crumb-item-border: var(--item-border);
914
- --crumb-item-border-tickled: var(--item-border-tickled);
915
- --crumb-item-padding: var(--space-s, 2px);
916
- --crumb-item-border-radius: var(--item-border-radius);
917
- --crumb-item-gap: var(--item-gap, var(--space-xs));
918
- --crumb-separator: var(--surface-muted-text);
919
- --crumb-truncate-min-width: 10ch;
920
- display: flex;
921
- width: 100%;
922
- }
923
-
924
- /* Outline goes on :host, not .host-container: .host-container carries the
925
- * scroll-fade mask-image, and CSS masks clip everything painted outside
926
- * the masked box - including an outline, which paints outside the border edge. */
927
- :host(:focus-within) {
928
- outline: 2px solid var(--accent);
929
- outline-offset: 2px;
930
- }
931
-
932
- .crumb-wrapper {
933
- display: flex;
934
- align-items: center;
935
- gap: var(--crumb-item-gap);
936
- width: 100%;
937
- }
938
-
939
- .up-button {
940
- display: inline-flex;
941
- align-items: center;
942
- justify-content: center;
943
- flex-shrink: 0;
944
- background: var(--crumb-item-bg);
945
- border: var(--crumb-item-border);
946
- border-radius: var(--crumb-item-border-radius);
947
- padding: var(--crumb-item-padding);
948
- cursor: pointer;
949
- color: inherit;
950
- }
951
-
952
- .up-button:disabled {
953
- opacity: 0.5;
954
- cursor: not-allowed;
955
- }
956
-
957
- .up-button:hover:not(:disabled) {
958
- background: var(--crumb-item-bg-tickled);
959
- border-color: var(--crumb-item-border-tickled);
960
- }
961
-
962
- .up-button ixfx-icon {
963
- width: 1em;
964
- height: 1em;
965
- pointer-events: none;
966
- }
967
-
968
- /* Edge fade (shows/hides based on scroll position) comes from the
969
- * shared .scroll-fade-x class - see ../styles/scroll-fade.ts */
970
- .host-container {
971
- display: flex;
972
- flex: 1;
973
- min-width: 0;
974
- outline: none;
975
- overflow: scroll;
976
- scroll-snap-type: x mandatory;
977
- scrollbar-width: none;
978
- overscroll-behavior: none;
979
- }
980
-
981
- .host-container::-webkit-scrollbar {
982
- display: none;
983
- }
984
-
985
- .parts {
986
- display: flex;
987
- gap: var(--space-s);
988
- }
989
-
990
- .trailing {
991
- flex-shrink: 0;
992
- }
993
-
994
- .crumb-segment {
995
- display: flex;
996
- align-items: center;
997
- flex-shrink: 0;
998
- background: var(--crumb-item-bg);
999
- border: var(--crumb-item-border);
1000
- border-radius: var(--crumb-item-border-radius);
1001
- padding:0;
1002
- }
1003
-
1004
- .crumb-segment.leading-caret {
1005
- flex-direction: row;
1006
- }
1007
-
1008
- .crumb-segment.tickled {
1009
- background: var(--crumb-item-bg-tickled);
1010
- border-color: var(--crumb-item-border-tickled);
1011
- color: var(--crumb-item-text-tickled);
1012
- flex-shrink: 0;
1013
- min-width: auto;
1014
- }
1015
-
1016
- .crumb-segment.truncatable {
1017
- flex-shrink: 1;
1018
- min-width: min(var(--crumb-truncate-min-width), auto);
1019
- overflow: hidden;
1020
- }
1021
-
1022
- .crumb-segment.truncatable .label {
1023
- overflow: hidden;
1024
- text-overflow: ellipsis;
1025
- white-space: nowrap;
1026
- min-width: 0;
1027
- }
1028
-
1029
- .label {
1030
- padding: var(--crumb-item-padding);
1031
- cursor: pointer;
1032
- white-space: nowrap;
1033
- color: inherit;
1034
- }
1035
-
1036
- .crumb-segment.last-label .label {
1037
- color: var(--crumb-last-label-color, inherit);
1038
- font-style: var(--crumb-last-label-font-style, inherit);
1039
- font-weight: var(--crumb-last-label-font-weight, inherit);
1040
- text-decoration: var(--crumb-last-label-text-decoration, inherit);
1041
- text-underline-offset: var(--crumb-last-label-text-underline-offset, auto);
1042
- }
1043
-
1044
- .crumb-segment.tickled .label {
1045
- color: var(--crumb-item-text-tickled);
1046
- overflow: visible;
1047
- text-overflow: clip;
1048
- }
1049
-
1050
- .crumb-segment ixfx-menu-trigger {
1051
- --ixfx-button-padding: var(--space-s, 2px);
1052
- }
1053
-
1054
- .caret {
1055
- position: relative;
1056
- cursor: pointer;
1057
- color: var(--crumb-separator);
1058
- display: inline-flex;
1059
- align-items: center;
1060
- justify-content: center;
1061
- transition: all 0.2s ease-in-out;
1062
- }
1063
-
1064
- .caret.open {
1065
- background: color-mix(in srgb, var(--surface-5) 40%, transparent);
1066
- }
1067
-
1068
- .caret.pending {
1069
- display: inline-flex;
1070
- }
1071
-
1072
- .caret > ixfx-menu-trigger {
1073
- display: inline-flex;
1074
- margin: 0;
1075
- --_trigger-hover-bg: transparent;
1076
- --_trigger-hover-opacity: 0.6;
1077
- }
1078
-
1079
- .caret > ixfx-menu-trigger::part(base) {
1080
- background: none;
1081
- border: none;
1082
- color: inherit;
1083
- cursor: pointer;
1084
- font-size: inherit;
1085
- line-height: 1;
1086
- }
1087
-
1088
- .caret > ixfx-menu-trigger::part(base):hover {
1089
- background: none;
1090
- opacity: 0.6;
1091
- }
1092
-
1093
- .separator {
1094
- margin-left: var(--crumb-item-gap);
1095
- margin-right: var(--crumb-item-gap);
1096
- color: var(--crumb-separator);
1097
- }
1098
-
1099
- .separator-trigger {
1100
- display: inline-flex;
1101
- margin-left: var(--crumb-item-gap);
1102
- margin-right: var(--crumb-item-gap);
1103
- --_trigger-hover-bg: transparent;
1104
- --_trigger-hover-opacity: 0.6;
1105
- }
1106
-
1107
- .separator-trigger::part(base) {
1108
- background: none;
1109
- border: none;
1110
- color: var(--crumb-separator);
1111
- padding: 0;
1112
- cursor: pointer;
1113
- font-size: inherit;
1114
- line-height: 1;
1115
- }
1116
-
1117
- .separator-trigger::part(base):hover {
1118
- background: none;
1119
- opacity: 0.6;
1120
- }
1121
-
1122
- .separator-trigger.tickled::part(base) {
1123
- }
1124
-
1125
- ixfx-menu-trigger {
1126
- display: none;
1127
- }
1128
-
1129
- .horiz-select > ixfx-menu-trigger {
1130
- display: inline-flex;
1131
- }
1132
-
1133
- .horiz-select {
1134
- display: flex;
1135
- min-width: 5ch;
1136
- }
1137
-
1138
- .loading-spinner {
1139
- display: inline-block;
1140
- width: 12px;
1141
- height: 12px;
1142
- border: 2px solid var(--surface-5);
1143
- border-top-color: var(--accent);
1144
- border-radius: 50%;
1145
- animation: crumb-spin 0.7s linear infinite;
1146
- }
1147
-
1148
- @keyframes crumb-spin {
1149
- to { transform: rotate(360deg); }
1150
- }
1151
-
1152
- ::slotted(*), option {
1153
- user-select: none;
1154
- scroll-snap-align: start;
1155
- }
1156
- `
1157
- ];
1158
- }
1159
- };
1160
- __decorate([property({ type: Object })], CrumbNavigationElement.prototype, "root", void 0);
1161
- __decorate([property({ attribute: false })], CrumbNavigationElement.prototype, "model", void 0);
1162
- __decorate([property({ type: Object })], CrumbNavigationElement.prototype, "selectedNode", void 0);
1163
- __decorate([state()], CrumbNavigationElement.prototype, "_selectedNodes", void 0);
1164
- __decorate([property({ attribute: false })], CrumbNavigationElement.prototype, "loadChildren", void 0);
1165
- __decorate([property({ attribute: false })], CrumbNavigationElement.prototype, "filterPredicate", void 0);
1166
- __decorate([property({
1167
- reflect: true,
1168
- attribute: `exclusivity`
1169
- })], CrumbNavigationElement.prototype, "exclusivity", void 0);
1170
- __decorate([property({
1171
- reflect: true,
1172
- attribute: `selection-filter`
1173
- })], CrumbNavigationElement.prototype, "selectionFilter", void 0);
1174
- __decorate([state()], CrumbNavigationElement.prototype, "_openIdx", void 0);
1175
- __decorate([state()], CrumbNavigationElement.prototype, "_isFocused", void 0);
1176
- __decorate([state()], CrumbNavigationElement.prototype, "_menuOpen", void 0);
1177
- __decorate([state()], CrumbNavigationElement.prototype, "_focusOnNarrowedText", void 0);
1178
- __decorate([property({
1179
- reflect: true,
1180
- attribute: `input-mode`
1181
- })], CrumbNavigationElement.prototype, "inputMode", void 0);
1182
- __decorate([property({
1183
- type: Boolean,
1184
- reflect: true,
1185
- attribute: `no-truncate`
1186
- })], CrumbNavigationElement.prototype, "noTruncate", void 0);
1187
- __decorate([property({
1188
- type: Boolean,
1189
- reflect: true,
1190
- attribute: `show-suggestions`
1191
- })], CrumbNavigationElement.prototype, "showSuggestions", void 0);
1192
- __decorate([property({
1193
- type: Boolean,
1194
- reflect: true,
1195
- attribute: `leading-caret`
1196
- })], CrumbNavigationElement.prototype, "leadingCaret", void 0);
1197
- __decorate([property({
1198
- type: Boolean,
1199
- reflect: true,
1200
- attribute: `caret-embedded`
1201
- })], CrumbNavigationElement.prototype, "caretEmbedded", void 0);
1202
- __decorate([property({
1203
- type: Boolean,
1204
- reflect: true,
1205
- attribute: `hide-root`
1206
- })], CrumbNavigationElement.prototype, "hideRoot", void 0);
1207
- __decorate([property({
1208
- type: Boolean,
1209
- reflect: true,
1210
- attribute: `pad-ending`
1211
- })], CrumbNavigationElement.prototype, "padEnding", void 0);
1212
- __decorate([property({
1213
- type: Boolean,
1214
- reflect: true,
1215
- attribute: `with-up`
1216
- })], CrumbNavigationElement.prototype, "withUp", void 0);
1217
- CrumbNavigationElement = __decorate([safeCustomElement(`ixfx-crumb-navigation`)], CrumbNavigationElement);
1218
- //#endregion
1219
- export { scrollFadeStyles as n, CrumbNavigationElement as t };
1220
-
1221
- //# sourceMappingURL=crumb-navigation-Pif-kupA.js.map