@fusion.dev/helix-headless 0.143.0 → 0.145.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/custom-elements.json +16990 -1383
  2. package/dist/accordion/item/accordion-item.d.ts +48 -12
  3. package/dist/accordion/item/accordion-item.js +26 -5
  4. package/dist/accordion/root/accordion-root.d.ts +6 -0
  5. package/dist/accordion/root/accordion-root.js +7 -1
  6. package/dist/announcement/root/announcement-root.d.ts +21 -1
  7. package/dist/announcement/root/announcement-root.js +36 -1
  8. package/dist/app-header/root/app-header-root.d.ts +7 -0
  9. package/dist/app-header/root/app-header-root.js +5 -1
  10. package/dist/app-header/sectioning.d.ts +7 -0
  11. package/dist/app-header/sectioning.js +26 -0
  12. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  13. package/dist/area-chart/root/area-chart-root.js +24 -7
  14. package/dist/avatar/root/avatar-root.d.ts +14 -0
  15. package/dist/avatar/root/avatar-root.js +23 -9
  16. package/dist/badge/root/badge-root.d.ts +11 -7
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +12 -3
  19. package/dist/bar-chart/root/bar-chart-root.js +17 -10
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
  22. package/dist/button/root/button-root.d.ts +47 -1
  23. package/dist/button/root/button-root.js +38 -4
  24. package/dist/callout/root/callout-root.d.ts +18 -1
  25. package/dist/callout/root/callout-root.js +15 -4
  26. package/dist/canvas/root/canvas-root.d.ts +38 -3
  27. package/dist/canvas/root/canvas-root.js +121 -40
  28. package/dist/card/root/card-root.d.ts +30 -1
  29. package/dist/card/root/card-root.js +38 -5
  30. package/dist/carousel/root/carousel-root.d.ts +90 -0
  31. package/dist/carousel/root/carousel-root.js +134 -12
  32. package/dist/chat/composer/chat-composer.d.ts +38 -6
  33. package/dist/chat/composer/chat-composer.js +42 -9
  34. package/dist/chat/message/chat-message.d.ts +32 -1
  35. package/dist/chat/message/chat-message.js +25 -9
  36. package/dist/chat/naming.d.ts +22 -0
  37. package/dist/chat/naming.js +12 -0
  38. package/dist/chat/relative-clock.d.ts +39 -0
  39. package/dist/chat/relative-clock.js +31 -0
  40. package/dist/chat/root/chat-root.d.ts +36 -0
  41. package/dist/chat/root/chat-root.js +24 -1
  42. package/dist/checkbox/root/checkbox-root.js +2 -0
  43. package/dist/checkbox-group/root/checkbox-group-root.d.ts +53 -3
  44. package/dist/checkbox-group/root/checkbox-group-root.js +71 -22
  45. package/dist/code-block/lines.d.ts +13 -0
  46. package/dist/code-block/lines.js +2 -0
  47. package/dist/code-block/root/code-block-root.d.ts +38 -1
  48. package/dist/code-block/root/code-block-root.js +28 -7
  49. package/dist/color-input/root/color-input-root.d.ts +34 -1
  50. package/dist/color-input/root/color-input-root.js +23 -4
  51. package/dist/color-picker/channels.d.ts +26 -0
  52. package/dist/color-picker/channels.js +84 -0
  53. package/dist/color-picker/root/color-picker-root.d.ts +81 -5
  54. package/dist/color-picker/root/color-picker-root.js +103 -10
  55. package/dist/combobox/root/combobox-root.d.ts +38 -3
  56. package/dist/combobox/root/combobox-root.js +64 -2
  57. package/dist/command/root/command-root.d.ts +30 -4
  58. package/dist/command/root/command-root.js +33 -3
  59. package/dist/copy-button/from.d.ts +22 -0
  60. package/dist/copy-button/from.js +28 -0
  61. package/dist/copy-button/root/copy-button-root.d.ts +47 -1
  62. package/dist/copy-button/root/copy-button-root.js +44 -8
  63. package/dist/data-table/root/data-table-root.d.ts +150 -2
  64. package/dist/data-table/root/data-table-root.js +303 -29
  65. package/dist/data-table/tree.d.ts +40 -0
  66. package/dist/data-table/tree.js +55 -0
  67. package/dist/date-input/root/date-input-root.d.ts +73 -4
  68. package/dist/date-input/root/date-input-root.js +93 -43
  69. package/dist/date-picker/root/date-picker-root.d.ts +145 -1
  70. package/dist/date-picker/root/date-picker-root.js +239 -48
  71. package/dist/description-list/item/description-list-item.d.ts +17 -2
  72. package/dist/description-list/item/description-list-item.js +15 -2
  73. package/dist/description-list/root/description-list-root.d.ts +27 -1
  74. package/dist/description-list/root/description-list-root.js +26 -1
  75. package/dist/dialog/description.d.ts +9 -0
  76. package/dist/dialog/description.js +14 -0
  77. package/dist/dialog/root/dialog-root.d.ts +64 -1
  78. package/dist/dialog/root/dialog-root.js +49 -23
  79. package/dist/donut-chart/root/donut-chart-root.d.ts +25 -4
  80. package/dist/donut-chart/root/donut-chart-root.js +21 -6
  81. package/dist/drawer/root/drawer-root.d.ts +63 -2
  82. package/dist/drawer/root/drawer-root.js +95 -19
  83. package/dist/drawer/swipe-start.d.ts +9 -0
  84. package/dist/drawer/swipe-start.js +12 -0
  85. package/dist/drilldown/item/drilldown-item.d.ts +11 -6
  86. package/dist/drilldown/item/drilldown-item.js +8 -5
  87. package/dist/drilldown/root/drilldown-root.d.ts +11 -0
  88. package/dist/drilldown/root/drilldown-root.js +8 -3
  89. package/dist/element-events.generated.js +61 -13
  90. package/dist/empty/root/empty-root.d.ts +1 -1
  91. package/dist/file-input/root/file-input-root.d.ts +47 -0
  92. package/dist/file-input/root/file-input-root.js +60 -22
  93. package/dist/file-input/screen.d.ts +35 -0
  94. package/dist/file-input/screen.js +49 -0
  95. package/dist/filter-input/menu/filter-menu.d.ts +3 -0
  96. package/dist/filter-input/menu/filter-menu.js +8 -4
  97. package/dist/filter-input/root/filter-input-root.d.ts +38 -4
  98. package/dist/filter-input/root/filter-input-root.js +67 -3
  99. package/dist/filter-input/suggest.d.ts +17 -0
  100. package/dist/filter-input/suggest.js +23 -0
  101. package/dist/format-date/options.d.ts +33 -0
  102. package/dist/format-date/options.js +42 -0
  103. package/dist/format-date/root/format-date-root.d.ts +51 -0
  104. package/dist/format-date/root/format-date-root.js +58 -38
  105. package/dist/heatmap/root/heatmap-root.d.ts +23 -6
  106. package/dist/heatmap/root/heatmap-root.js +24 -13
  107. package/dist/icon/index.d.ts +2 -0
  108. package/dist/icon/index.js +2 -0
  109. package/dist/icon/registry.d.ts +37 -0
  110. package/dist/icon/registry.js +83 -0
  111. package/dist/icon/root/icon-root.d.ts +30 -4
  112. package/dist/icon/root/icon-root.js +41 -6
  113. package/dist/icon/root/index.d.ts +2 -0
  114. package/dist/icon/root/index.js +2 -0
  115. package/dist/icon/set.d.ts +1 -0
  116. package/dist/icon/set.js +3 -0
  117. package/dist/image/root/image-root.d.ts +14 -0
  118. package/dist/image/root/image-root.js +23 -2
  119. package/dist/input/root/input-root.d.ts +11 -0
  120. package/dist/input/root/input-root.js +16 -1
  121. package/dist/kbd/root/kbd-root.d.ts +20 -13
  122. package/dist/kbd/root/kbd-root.js +35 -37
  123. package/dist/kbd/shortcut.d.ts +18 -0
  124. package/dist/kbd/shortcut.js +35 -0
  125. package/dist/legend/hidden-series.d.ts +8 -0
  126. package/dist/legend/hidden-series.js +13 -0
  127. package/dist/legend/root/legend-root.d.ts +56 -0
  128. package/dist/legend/root/legend-root.js +54 -5
  129. package/dist/lightbox/item/lightbox-item.d.ts +15 -0
  130. package/dist/lightbox/item/lightbox-item.js +10 -1
  131. package/dist/lightbox/root/lightbox-root.d.ts +61 -1
  132. package/dist/lightbox/root/lightbox-root.js +94 -4
  133. package/dist/line-chart/root/line-chart-root.d.ts +11 -3
  134. package/dist/line-chart/root/line-chart-root.js +19 -5
  135. package/dist/list/item/list-item.d.ts +68 -1
  136. package/dist/list/item/list-item.js +66 -4
  137. package/dist/list/numbering.d.ts +14 -0
  138. package/dist/list/numbering.js +8 -0
  139. package/dist/list/root/list-root.d.ts +106 -9
  140. package/dist/list/root/list-root.js +189 -4
  141. package/dist/list/selection.d.ts +19 -0
  142. package/dist/list/selection.js +21 -0
  143. package/dist/listbox/root/listbox-root.d.ts +74 -3
  144. package/dist/listbox/root/listbox-root.js +86 -9
  145. package/dist/loader/busy.d.ts +17 -0
  146. package/dist/loader/busy.js +24 -0
  147. package/dist/loader/root/loader-root.d.ts +37 -0
  148. package/dist/loader/root/loader-root.js +52 -3
  149. package/dist/map/root/map-root.d.ts +6 -2
  150. package/dist/map/root/map-root.js +5 -2
  151. package/dist/megamenu/root/megamenu-root.d.ts +21 -0
  152. package/dist/megamenu/root/megamenu-root.js +16 -2
  153. package/dist/menu/index.d.ts +1 -0
  154. package/dist/menu/index.js +1 -0
  155. package/dist/menu/item/menu-item.d.ts +38 -11
  156. package/dist/menu/item/menu-item.js +33 -1
  157. package/dist/menu/root/menu-root.d.ts +25 -1
  158. package/dist/menu/root/menu-root.js +63 -6
  159. package/dist/menu/section/menu-section.d.ts +55 -0
  160. package/dist/menu/section/menu-section.js +60 -0
  161. package/dist/meter/root/meter-root.d.ts +7 -0
  162. package/dist/meter/root/meter-root.js +6 -3
  163. package/dist/navigation/root/navigation-root.d.ts +16 -1
  164. package/dist/navigation/root/navigation-root.js +27 -1
  165. package/dist/notifications/feed-keys.d.ts +10 -0
  166. package/dist/notifications/feed-keys.js +14 -0
  167. package/dist/notifications/notification/notification.d.ts +17 -0
  168. package/dist/notifications/notification/notification.js +21 -2
  169. package/dist/notifications/root/notifications-root.d.ts +60 -0
  170. package/dist/notifications/root/notifications-root.js +76 -1
  171. package/dist/number-input/root/number-input-root.d.ts +47 -0
  172. package/dist/number-input/root/number-input-root.js +58 -22
  173. package/dist/object-inspector/root/object-inspector-root.d.ts +98 -16
  174. package/dist/object-inspector/root/object-inspector-root.js +180 -80
  175. package/dist/object-inspector/rows.d.ts +57 -0
  176. package/dist/object-inspector/rows.js +86 -0
  177. package/dist/option/root/option-root.d.ts +54 -5
  178. package/dist/option/root/option-root.js +34 -5
  179. package/dist/outline/levels.d.ts +31 -0
  180. package/dist/outline/levels.js +23 -0
  181. package/dist/outline/root/outline-root.d.ts +68 -3
  182. package/dist/outline/root/outline-root.js +73 -8
  183. package/dist/pagination/size/pagination-size.d.ts +11 -2
  184. package/dist/pagination/size/pagination-size.js +19 -4
  185. package/dist/pin-input/format.d.ts +7 -0
  186. package/dist/pin-input/format.js +16 -0
  187. package/dist/pin-input/root/pin-input-root.d.ts +21 -0
  188. package/dist/pin-input/root/pin-input-root.js +29 -2
  189. package/dist/popover/root/popover-root.d.ts +62 -4
  190. package/dist/popover/root/popover-root.js +53 -5
  191. package/dist/progress/root/progress-root.d.ts +7 -0
  192. package/dist/progress/root/progress-root.js +9 -3
  193. package/dist/qr-code/export.d.ts +31 -0
  194. package/dist/qr-code/export.js +10 -0
  195. package/dist/qr-code/root/qr-code-root.d.ts +26 -0
  196. package/dist/qr-code/root/qr-code-root.js +49 -2
  197. package/dist/radio/group/radio-group.d.ts +17 -0
  198. package/dist/radio/group/radio-group.js +14 -1
  199. package/dist/rating/root/rating-root.d.ts +25 -0
  200. package/dist/rating/root/rating-root.js +46 -4
  201. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  202. package/dist/scatter-chart/root/scatter-chart-root.js +25 -7
  203. package/dist/scroll-area/root/scroll-area-root.d.ts +113 -0
  204. package/dist/scroll-area/root/scroll-area-root.js +218 -3
  205. package/dist/scroll-area/scrollbar.d.ts +65 -0
  206. package/dist/scroll-area/scrollbar.js +24 -0
  207. package/dist/select/root/select-root.d.ts +24 -0
  208. package/dist/select/root/select-root.js +21 -7
  209. package/dist/skeleton/root/skeleton-root.d.ts +25 -0
  210. package/dist/skeleton/root/skeleton-root.js +17 -2
  211. package/dist/slider/root/slider-root.d.ts +39 -0
  212. package/dist/slider/root/slider-root.js +45 -9
  213. package/dist/splitter/root/splitter-root.d.ts +13 -0
  214. package/dist/splitter/root/splitter-root.js +20 -2
  215. package/dist/splitter/snap.d.ts +9 -0
  216. package/dist/splitter/snap.js +12 -0
  217. package/dist/stat/root/stat-root.d.ts +2 -0
  218. package/dist/stat/root/stat-root.js +1 -1
  219. package/dist/steps/reach.d.ts +15 -0
  220. package/dist/steps/reach.js +12 -0
  221. package/dist/steps/root/steps-root.d.ts +30 -0
  222. package/dist/steps/root/steps-root.js +53 -0
  223. package/dist/steps/step/step.d.ts +39 -2
  224. package/dist/steps/step/step.js +29 -7
  225. package/dist/switch/root/switch-root.d.ts +12 -2
  226. package/dist/switch/root/switch-root.js +6 -1
  227. package/dist/table/column/table-column.d.ts +11 -0
  228. package/dist/table/column/table-column.js +6 -1
  229. package/dist/table/root/table-root.d.ts +101 -0
  230. package/dist/table/root/table-root.js +166 -5
  231. package/dist/table/row/table-row.d.ts +47 -1
  232. package/dist/table/row/table-row.js +39 -2
  233. package/dist/tabs/panel/tab-panel.d.ts +9 -5
  234. package/dist/tabs/panel/tab-panel.js +3 -4
  235. package/dist/tabs/root/tabs-root.d.ts +25 -1
  236. package/dist/tabs/root/tabs-root.js +21 -3
  237. package/dist/tabs/tab/tab.d.ts +36 -4
  238. package/dist/tabs/tab/tab.js +46 -3
  239. package/dist/tag/group/tag-group.d.ts +107 -0
  240. package/dist/tag/group/tag-group.js +157 -0
  241. package/dist/tag/index.d.ts +1 -0
  242. package/dist/tag/index.js +1 -0
  243. package/dist/tag/root/tag-root.d.ts +60 -0
  244. package/dist/tag/root/tag-root.js +74 -18
  245. package/dist/tag/selection.d.ts +10 -0
  246. package/dist/tag/selection.js +12 -0
  247. package/dist/textarea/grow.d.ts +22 -0
  248. package/dist/textarea/grow.js +20 -0
  249. package/dist/textarea/root/textarea-root.d.ts +9 -0
  250. package/dist/textarea/root/textarea-root.js +9 -1
  251. package/dist/time-input/root/time-input-root.d.ts +44 -5
  252. package/dist/time-input/root/time-input-root.js +69 -39
  253. package/dist/time-picker/root/time-picker-root.d.ts +54 -8
  254. package/dist/time-picker/root/time-picker-root.js +121 -91
  255. package/dist/timeline/group/timeline-group.d.ts +46 -0
  256. package/dist/timeline/group/timeline-group.js +37 -0
  257. package/dist/timeline/index.d.ts +1 -0
  258. package/dist/timeline/index.js +1 -0
  259. package/dist/timeline/root/timeline-root.d.ts +10 -3
  260. package/dist/toast/hotkey.d.ts +22 -0
  261. package/dist/toast/hotkey.js +23 -0
  262. package/dist/toast/item/toast-item.d.ts +26 -18
  263. package/dist/toast/item/toast-item.js +55 -48
  264. package/dist/toast/root/toast-root.d.ts +42 -8
  265. package/dist/toast/root/toast-root.js +64 -4
  266. package/dist/toggle/group/toggle-group.d.ts +57 -15
  267. package/dist/toggle/group/toggle-group.js +69 -9
  268. package/dist/toggle/root/toggle-root.d.ts +12 -1
  269. package/dist/toggle/root/toggle-root.js +11 -3
  270. package/dist/toolbar/root/toolbar-root.d.ts +13 -0
  271. package/dist/toolbar/root/toolbar-root.js +15 -5
  272. package/dist/tooltip/focus-target.d.ts +6 -0
  273. package/dist/tooltip/focus-target.js +9 -0
  274. package/dist/tooltip/root/tooltip-root.d.ts +42 -17
  275. package/dist/tooltip/root/tooltip-root.js +50 -9
  276. package/dist/tour/naming.d.ts +30 -0
  277. package/dist/tour/naming.js +10 -0
  278. package/dist/tour/root/tour-root.d.ts +35 -0
  279. package/dist/tour/root/tour-root.js +56 -5
  280. package/dist/tour/stop/tour-stop.d.ts +53 -8
  281. package/dist/tour/stop/tour-stop.js +45 -15
  282. package/dist/tour/wait.d.ts +11 -0
  283. package/dist/tour/wait.js +19 -0
  284. package/dist/tree/item/tree-item.d.ts +54 -1
  285. package/dist/tree/item/tree-item.js +89 -20
  286. package/dist/tree/root/tree-root.d.ts +37 -0
  287. package/dist/tree/root/tree-root.js +51 -6
  288. package/dist/tree/selection.d.ts +24 -0
  289. package/dist/tree/selection.js +26 -0
  290. package/dist/trend/root/trend-root.d.ts +13 -0
  291. package/dist/trend/root/trend-root.js +14 -9
  292. package/dist/video/media-events.d.ts +49 -0
  293. package/dist/video/media-events.js +39 -0
  294. package/dist/video/root/video-root.d.ts +99 -13
  295. package/dist/video/root/video-root.js +84 -47
  296. package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -0
  297. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  298. package/dist/video-playlist/order.d.ts +41 -0
  299. package/dist/video-playlist/order.js +34 -0
  300. package/dist/video-playlist/root/video-playlist-root.d.ts +70 -2
  301. package/dist/video-playlist/root/video-playlist-root.js +60 -16
  302. package/dist/virtual-list/controls.d.ts +4 -0
  303. package/dist/virtual-list/controls.js +30 -0
  304. package/dist/virtual-list/fill.d.ts +30 -0
  305. package/dist/virtual-list/fill.js +39 -0
  306. package/dist/virtual-list/keys.d.ts +15 -0
  307. package/dist/virtual-list/keys.js +24 -0
  308. package/dist/virtual-list/root/virtual-list-root.d.ts +155 -23
  309. package/dist/virtual-list/root/virtual-list-root.js +175 -34
  310. package/lint.json +1 -1
  311. package/package.json +5 -5
  312. package/types/jsx.d.ts +8871 -1286
  313. package/types/svelte.d.ts +3 -0
  314. package/types/vue.d.ts +1918 -269
@@ -4,22 +4,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement, HelixSelectEvent, MixinControllerOpen, } from '@fusion.dev/helix-core';
8
- import { caretDown } from '@fusion.dev/helix-icons';
7
+ import { customElement, HelixElement, HelixLoadEvent, HelixSelectEvent, MixinControllerOpen, } from '@fusion.dev/helix-core';
8
+ import { caretDown, check, minus } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
12
12
  let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerOpen(HelixElement) {
13
13
  constructor() {
14
14
  super(...arguments);
15
+ this.checkable = false;
16
+ this.checked = false;
17
+ this.disabled = false;
15
18
  this.heads = false;
16
19
  this.href = '';
20
+ this.lazy = false;
17
21
  this.rel = '';
18
22
  this.selected = false;
19
23
  this.target = '';
20
24
  this.focusable = false;
21
25
  this.value = '';
22
26
  this.branch = false;
27
+ this.handleCheckClick = (event) => {
28
+ event.preventDefault();
29
+ event.stopPropagation();
30
+ this.select();
31
+ };
23
32
  this.handleToggleClick = (event) => {
24
33
  event.preventDefault();
25
34
  event.stopPropagation();
@@ -27,7 +36,11 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
27
36
  };
28
37
  this.handleRowClick = (event) => {
29
38
  const onLink = event.composedPath().some((node) => node instanceof HTMLAnchorElement);
30
- if (this.branch && this.href === '') {
39
+ if (this.disabled) {
40
+ event.preventDefault();
41
+ return;
42
+ }
43
+ if (this.isBranch && this.href === '') {
31
44
  if (!onLink) {
32
45
  if (this.choosable) {
33
46
  this.select();
@@ -51,10 +64,10 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
51
64
  });
52
65
  }
53
66
  get choosable() {
54
- return this.value !== '' && !this.heads;
67
+ return this.value !== '' && !this.heads && !this.checkable && !this.disabled;
55
68
  }
56
69
  get isBranch() {
57
- return this.branch;
70
+ return this.branch || this.lazy;
58
71
  }
59
72
  focusItem() {
60
73
  this.renderRoot
@@ -62,12 +75,21 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
62
75
  ?.focus({ preventScroll: true });
63
76
  }
64
77
  select() {
78
+ if (this.disabled) {
79
+ return;
80
+ }
65
81
  this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
66
82
  }
67
83
  activate() {
84
+ if (this.disabled) {
85
+ return;
86
+ }
68
87
  this.select();
69
88
  this.follow();
70
89
  }
90
+ toggleOpen() {
91
+ return this.disabled ? false : super.toggleOpen();
92
+ }
71
93
  follow() {
72
94
  const own = this.renderRoot?.querySelector('a[part="row"]');
73
95
  if (own) {
@@ -85,18 +107,32 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
85
107
  }
86
108
  }
87
109
  }
110
+ renderToggle() {
111
+ return html `<slot
112
+ name="chevron"
113
+ @click=${this.href === '' ? nothing : this.handleToggleClick}
114
+ ><svg part="toggle" fill="currentColor" viewBox=${caretDown.viewBox} aria-hidden="true">
115
+ ${unsafeSVG(caretDown.content)}
116
+ </svg></slot
117
+ >`;
118
+ }
119
+ renderCheckbox() {
120
+ if (!this.checkable) {
121
+ return nothing;
122
+ }
123
+ const mixed = this.checked === 'mixed';
124
+ const glyph = mixed ? minus : this.checked ? check : undefined;
125
+ return html `<span
126
+ part="checkbox${mixed ? ' checkbox-mixed' : this.checked ? ' checkbox-checked' : ''}"
127
+ aria-hidden="true"
128
+ @click=${this.handleCheckClick}
129
+ >${glyph
130
+ ? html `<svg fill="currentColor" viewBox=${glyph.viewBox}>${unsafeSVG(glyph.content)}</svg>`
131
+ : nothing}</span
132
+ >`;
133
+ }
88
134
  renderRow() {
89
- return html `${this.branch
90
- ? html `<svg
91
- part="toggle"
92
- fill="currentColor"
93
- viewBox=${caretDown.viewBox}
94
- aria-hidden="true"
95
- @click=${this.href === '' ? nothing : this.handleToggleClick}
96
- >
97
- ${unsafeSVG(caretDown.content)}
98
- </svg>`
99
- : nothing}
135
+ return html `${this.isBranch ? this.renderToggle() : nothing}${this.renderCheckbox()}
100
136
  <slot name="start"></slot>
101
137
  <span part="label"><slot></slot></span>
102
138
  <slot name="end"></slot>`;
@@ -104,21 +140,39 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
104
140
  willUpdate(changed) {
105
141
  super.willUpdate(changed);
106
142
  this.toggleState('selected', this.selected);
143
+ this.toggleState('loading', this.open && this.lazy);
107
144
  if (this.childrenKnown) {
108
145
  this.branch = this.knownChildren.some((child) => child.slot === 'children');
109
146
  }
110
147
  }
148
+ updated(changed) {
149
+ super.updated(changed);
150
+ if (changed.has('open') && this.open && this.lazy) {
151
+ this.dispatchEvent(new HelixLoadEvent());
152
+ }
153
+ }
111
154
  render() {
112
155
  const linked = this.href !== '';
113
156
  const level = this.level ?? 1;
114
157
  const depth = this.level ?? nothing;
115
- const expanded = this.branch ? (this.open ? 'true' : 'false') : nothing;
158
+ const expanded = this.isBranch ? (this.open ? 'true' : 'false') : nothing;
159
+ const chosen = this.checkable ? undefined : this.selected ? 'true' : 'false';
160
+ const checked = this.checkable
161
+ ? this.checked === 'mixed'
162
+ ? 'mixed'
163
+ : String(this.checked)
164
+ : undefined;
165
+ const busy = this.open && this.lazy ? 'true' : nothing;
166
+ const off = this.disabled ? 'true' : nothing;
116
167
  const tabIndex = this.focusable || !this.childrenKnown ? '0' : '-1';
117
168
  return html `<div
118
169
  part="item"
119
170
  role=${linked ? 'none' : 'treeitem'}
120
171
  aria-expanded=${linked ? nothing : expanded}
121
- aria-selected=${linked ? nothing : this.selected ? 'true' : 'false'}
172
+ aria-selected=${linked ? nothing : (chosen ?? nothing)}
173
+ aria-checked=${linked ? nothing : (checked ?? nothing)}
174
+ aria-disabled=${linked ? nothing : off}
175
+ aria-busy=${linked ? nothing : busy}
122
176
  aria-level=${linked ? nothing : depth}
123
177
  tabindex=${linked ? nothing : tabIndex}
124
178
  >
@@ -126,11 +180,14 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
126
180
  ? html `<a
127
181
  part="row"
128
182
  role="treeitem"
129
- href=${this.href}
183
+ href=${this.disabled ? nothing : this.href}
130
184
  target=${this.target || nothing}
131
185
  rel=${this.rel || nothing}
132
186
  aria-expanded=${expanded}
133
- aria-selected=${this.selected ? 'true' : 'false'}
187
+ aria-selected=${chosen ?? nothing}
188
+ aria-checked=${checked ?? nothing}
189
+ aria-disabled=${off}
190
+ aria-busy=${busy}
134
191
  aria-level=${depth}
135
192
  tabindex=${tabIndex}
136
193
  style="--tree-level: ${level}"
@@ -152,12 +209,24 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
152
209
  </div>`;
153
210
  }
154
211
  };
212
+ __decorate([
213
+ property({ attribute: false })
214
+ ], HelixHeadlessTreeItem.prototype, "checkable", void 0);
215
+ __decorate([
216
+ property({ attribute: false })
217
+ ], HelixHeadlessTreeItem.prototype, "checked", void 0);
218
+ __decorate([
219
+ property({ reflect: true, type: Boolean })
220
+ ], HelixHeadlessTreeItem.prototype, "disabled", void 0);
155
221
  __decorate([
156
222
  property({ attribute: false })
157
223
  ], HelixHeadlessTreeItem.prototype, "heads", void 0);
158
224
  __decorate([
159
225
  property()
160
226
  ], HelixHeadlessTreeItem.prototype, "href", void 0);
227
+ __decorate([
228
+ property({ reflect: true, type: Boolean })
229
+ ], HelixHeadlessTreeItem.prototype, "lazy", void 0);
161
230
  __decorate([
162
231
  property({ attribute: false, type: Number })
163
232
  ], HelixHeadlessTreeItem.prototype, "level", void 0);
@@ -16,6 +16,14 @@ declare const HelixHeadlessTree_base: (new (...args: any[]) => import("@fusion.d
16
16
  * Typing a letter moves to the next visible item whose name starts with it,
17
17
  * and `*` opens every branch beside the focused item.
18
18
  *
19
+ * `selection-mode="multiple"` draws a check mark on every row and lets a
20
+ * reader check many, as Web Awesome's and Ark UI's checkbox trees do. Checking
21
+ * a branch checks every item under it, and a branch some of whose items are
22
+ * checked is partly checked. Space or a press on the mark checks the focused
23
+ * row, and Enter or a press on a branch's row opens it. `active` then holds the
24
+ * checked values, comma separated, which `values` also gives as a list, and
25
+ * the tree says `aria-multiselectable`.
26
+ *
19
27
  * @since 0.1.0
20
28
  * @status stable
21
29
  * @category navigation
@@ -82,6 +90,21 @@ export declare class HelixHeadlessTree extends HelixHeadlessTree_base {
82
90
  * The resting state is the absence of the attribute, which is `peer`.
83
91
  */
84
92
  nesting?: 'heading' | 'peer' | 'subordinate';
93
+ /**
94
+ * Whether a reader can check many items. Unset, one item is chosen at a
95
+ * time.
96
+ *
97
+ * Optional, so a tree of one choice writes no attribute onto the host.
98
+ */
99
+ selectionMode?: 'multiple';
100
+ /**
101
+ * The checked values, as a list, under `selection-mode="multiple"`, and the
102
+ * chosen value alone otherwise. Writing it sets `active`.
103
+ */
104
+ get values(): string[];
105
+ set values(next: string[]);
106
+ /** Whether many items can be checked. */
107
+ private get multiple();
85
108
  private watcher;
86
109
  /**
87
110
  * Every item, in the order a reader moving down would meet them.
@@ -100,6 +123,20 @@ export declare class HelixHeadlessTree extends HelixHeadlessTree_base {
100
123
  /** Items a reader can actually reach: not inside a collapsed branch. */
101
124
  private get visibleItems();
102
125
  private readonly handleSelection;
126
+ /** Every value in the tree, in the order a reader meets the items. */
127
+ private get order();
128
+ /**
129
+ * Whether an item holds others, read from the tree as well as from the item.
130
+ *
131
+ * **An item hydrating what a server sent has not said it is a branch yet**:
132
+ * it learns that from its children on the render after, and nothing then
133
+ * asks the tree again. Read from its own render alone, a folder served with
134
+ * one of its files checked was counted a leaf and drawn unchecked rather
135
+ * than partly checked, once hydrated.
136
+ */
137
+ private holds;
138
+ /** What the multiple selection reads of an item. */
139
+ private rowOf;
103
140
  /**
104
141
  * Pushes tree-owned state down: which item is selected, which holds the tab
105
142
  * stop, and how deep each one sits.
@@ -4,10 +4,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, MixinCollection, MixinControllerActive, scrollItemIntoView, slottedWords, Typeahead, typesCharacter, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, closestInstance, commaList, customElement, HelixElement, inlineStep, keyClaimed, MixinCollection, MixinControllerActive, scrollItemIntoView, slottedWords, Typeahead, typesCharacter, whenHydrated, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { HelixHeadlessTreeItem } from '../item/tree-item.js';
11
+ import { checkedState, pressRow } from '../selection.js';
11
12
  const KEYS = new Set([
12
13
  'ArrowDown',
13
14
  'ArrowUp',
@@ -33,7 +34,9 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
33
34
  return;
34
35
  }
35
36
  if (!event.defaultPrevented) {
36
- this.requestActive(event.detail.value);
37
+ this.requestActive(this.multiple
38
+ ? pressRow(this.rowOf(origin), this.values, this.order).join(',')
39
+ : event.detail.value);
37
40
  }
38
41
  this.syncItems();
39
42
  };
@@ -51,6 +54,11 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
51
54
  }
52
55
  this.typeahead.reset();
53
56
  const along = inlineStep(this, event.key);
57
+ if (this.multiple && event.key === ' ') {
58
+ current.select();
59
+ event.preventDefault();
60
+ return;
61
+ }
54
62
  if (event.key === 'ArrowDown') {
55
63
  this.move(current, 1);
56
64
  }
@@ -64,7 +72,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
64
72
  this.focusOn(this.visibleItems.at(-1));
65
73
  }
66
74
  else if (along === 1) {
67
- if (current.isBranch && !current.open) {
75
+ if (current.isBranch && !current.open && !current.disabled) {
68
76
  current.requestOpen(true);
69
77
  this.syncItems();
70
78
  }
@@ -73,7 +81,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
73
81
  }
74
82
  }
75
83
  else if (along === -1) {
76
- if (current.isBranch && current.open) {
84
+ if (current.isBranch && current.open && !current.disabled) {
77
85
  current.requestOpen(false);
78
86
  this.syncItems();
79
87
  }
@@ -100,6 +108,15 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
100
108
  this.syncItems();
101
109
  };
102
110
  }
111
+ get values() {
112
+ return this.multiple ? commaList(this.active) : this.active === '' ? [] : [this.active];
113
+ }
114
+ set values(next) {
115
+ this.active = next.join(',');
116
+ }
117
+ get multiple() {
118
+ return this.selectionMode === 'multiple';
119
+ }
103
120
  get items() {
104
121
  return [...this.querySelectorAll('*')].filter((node) => node instanceof HelixHeadlessTreeItem);
105
122
  }
@@ -115,6 +132,25 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
115
132
  return true;
116
133
  });
117
134
  }
135
+ get order() {
136
+ return this.items.map((item) => item.value).filter((value) => value !== '');
137
+ }
138
+ holds(item) {
139
+ return item.isBranch || this.items.some((other) => other !== item && item.contains(other));
140
+ }
141
+ rowOf(item) {
142
+ const branch = this.holds(item);
143
+ const leaves = branch
144
+ ? this.items
145
+ .filter((other) => other !== item &&
146
+ item.contains(other) &&
147
+ !this.holds(other) &&
148
+ !other.disabled &&
149
+ other.value !== '')
150
+ .map((other) => other.value)
151
+ : [];
152
+ return { branch, disabled: item.disabled, leaves, value: item.value };
153
+ }
118
154
  syncItems() {
119
155
  const visible = this.visibleItems;
120
156
  const chosen = this.resolveActive(visible);
@@ -122,8 +158,11 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
122
158
  this.visibleAncestor(this.items.find((item) => item.focusable));
123
159
  const stop = held ?? chosen;
124
160
  const heads = this.nesting === 'heading';
161
+ const multiple = this.multiple;
162
+ const checked = new Set(this.values);
125
163
  for (const item of this.items) {
126
- const selected = item.value !== '' && item.value === this.active;
164
+ const selected = !multiple && item.value !== '' && item.value === this.active;
165
+ const state = multiple ? checkedState(this.rowOf(item), checked) : false;
127
166
  const focusable = item === stop;
128
167
  let level = 1;
129
168
  let parent = item.parentElement;
@@ -135,6 +174,8 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
135
174
  }
136
175
  whenHydrated(item, () => {
137
176
  item.selected = selected;
177
+ item.checkable = multiple;
178
+ item.checked = state;
138
179
  item.focusable = focusable;
139
180
  item.level = level;
140
181
  item.heads = heads;
@@ -214,7 +255,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
214
255
  }
215
256
  updated(changed) {
216
257
  super.updated(changed);
217
- if (changed.has('active') || changed.has('nesting')) {
258
+ if (changed.has('active') || changed.has('nesting') || changed.has('selectionMode')) {
218
259
  this.syncItems();
219
260
  }
220
261
  }
@@ -223,6 +264,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
223
264
  part="tree"
224
265
  role="tree"
225
266
  aria-busy=${this.loading ? 'true' : nothing}
267
+ aria-multiselectable=${this.multiple ? 'true' : nothing}
226
268
  aria-label=${this.label}
227
269
  >
228
270
  <slot
@@ -241,6 +283,9 @@ __decorate([
241
283
  __decorate([
242
284
  property({ reflect: true })
243
285
  ], HelixHeadlessTree.prototype, "nesting", void 0);
286
+ __decorate([
287
+ property({ attribute: 'selection-mode', reflect: true })
288
+ ], HelixHeadlessTree.prototype, "selectionMode", void 0);
244
289
  HelixHeadlessTree = __decorate([
245
290
  customElement('helix-headless-tree')
246
291
  ], HelixHeadlessTree);
@@ -0,0 +1,24 @@
1
+ /** What the multiple selection reads of a row. */
2
+ export interface CheckableRow {
3
+ /** Whether the row is a branch, holding rows of its own. */
4
+ branch: boolean;
5
+ /** Whether the row is out of play. Its value is never added or taken away. */
6
+ disabled: boolean;
7
+ /** The values of the leaves under a branch, in order. Empty for a leaf. */
8
+ leaves: readonly string[];
9
+ /** The row's own value. */
10
+ value: string;
11
+ }
12
+ /**
13
+ * Whether a row is checked in a tree of check marks: a leaf by its value, and
14
+ * a branch by its leaves, `mixed` where some of them are.
15
+ */
16
+ export declare const checkedState: (row: CheckableRow, chosen: ReadonlySet<string>) => boolean | 'mixed';
17
+ /**
18
+ * The checked values after a press on `row`, in `order`.
19
+ *
20
+ * A leaf comes in or out. A branch checks every leaf under it, or clears them
21
+ * all where every one is already checked, as Ark UI's and Web Awesome's
22
+ * checkbox trees do. A disabled row changes nothing.
23
+ */
24
+ export declare const pressRow: (row: CheckableRow, chosen: readonly string[], order: readonly string[]) => string[];
@@ -0,0 +1,26 @@
1
+ const valuesOf = (row) => row.branch && row.leaves.length > 0 ? [...row.leaves] : row.value === '' ? [] : [row.value];
2
+ export const checkedState = (row, chosen) => {
3
+ const values = valuesOf(row);
4
+ const count = values.filter((value) => chosen.has(value)).length;
5
+ if (count === 0) {
6
+ return false;
7
+ }
8
+ return count === values.length ? true : 'mixed';
9
+ };
10
+ export const pressRow = (row, chosen, order) => {
11
+ if (row.disabled) {
12
+ return [...chosen];
13
+ }
14
+ const values = valuesOf(row);
15
+ const all = values.every((value) => chosen.includes(value));
16
+ const next = new Set(chosen);
17
+ for (const value of values) {
18
+ if (all) {
19
+ next.delete(value);
20
+ }
21
+ else {
22
+ next.add(value);
23
+ }
24
+ }
25
+ return order.filter((value) => next.has(value));
26
+ };
@@ -30,6 +30,7 @@ import { type TemplateResult } from 'lit';
30
30
  * @documentation https://fusion.dev/helix/components/trend
31
31
  *
32
32
  * @slot - The metric that moved.
33
+ * @slot icon - Replaces the arrow, such as with a glyph of your own set. Slot the one for the current direction.
33
34
  * @slot label - The period the metric moved over.
34
35
  *
35
36
  * @csspart direction - The direction as a word, for people who cannot see the arrow.
@@ -77,6 +78,18 @@ export declare class HelixHeadlessTrend extends HelixElement {
77
78
  * The word read out after the direction when the move is a setback.
78
79
  */
79
80
  worseLabel: string;
81
+ /**
82
+ * The arrow for the direction, as the fallback of the `icon` slot.
83
+ *
84
+ * Slot fallback, so the page replaces it by slotting a glyph of its own and
85
+ * a trend with none draws the arrow it always did; and a method, so the tier
86
+ * above replaces it by overriding. The word beside it still says the
87
+ * direction either way.
88
+ */
89
+ protected renderIcon(icon: {
90
+ content: string;
91
+ viewBox: string;
92
+ }): TemplateResult;
80
93
  protected render(): TemplateResult;
81
94
  }
82
95
  declare global {
@@ -24,20 +24,25 @@ let HelixHeadlessTrend = class HelixHeadlessTrend extends HelixElement {
24
24
  this.upLabel = 'Up';
25
25
  this.worseLabel = 'worse';
26
26
  }
27
- render() {
28
- const direction = readDirection(this.direction);
29
- const judgment = this.good && this.direction && this.direction !== 'neutral'
30
- ? `, ${this.good === this.direction ? this.betterLabel : this.worseLabel}`
31
- : '';
32
- return html `<svg
27
+ renderIcon(icon) {
28
+ return html `<slot name="icon"
29
+ ><svg
33
30
  aria-hidden="true"
34
31
  data-glyph
35
32
  fill="currentColor"
36
33
  part="icon"
37
- viewBox=${direction.icon.viewBox}
34
+ viewBox=${icon.viewBox}
38
35
  >
39
- ${unsafeSVG(direction.icon.content)}
40
- </svg>
36
+ ${unsafeSVG(icon.content)}
37
+ </svg></slot
38
+ >`;
39
+ }
40
+ render() {
41
+ const direction = readDirection(this.direction);
42
+ const judgment = this.good && this.direction && this.direction !== 'neutral'
43
+ ? `, ${this.good === this.direction ? this.betterLabel : this.worseLabel}`
44
+ : '';
45
+ return html `${this.renderIcon(direction.icon)}
41
46
  <span part="direction">${`${this[direction.word]}${judgment}`}</span>
42
47
  <slot></slot>
43
48
  <slot name="label"></slot>`;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The media events a player sends on from its inner `<video>`, and how.
3
+ *
4
+ * Separable because the set is a decision about the platform, and nothing in it
5
+ * draws. It is the HTML standard's own summary of the events a media element
6
+ * fires, every one of them, so a consumer who listened on a `<video>` listens
7
+ * on the player with the same names and hears the same things. A shorter list
8
+ * would be one more list for a consumer to learn.
9
+ *
10
+ * None of these crosses a shadow boundary on its own. The video is inside the
11
+ * player's shadow root, so a listener on the element a consumer wrote hears
12
+ * nothing at all without the relay.
13
+ */
14
+ /**
15
+ * Every event a media element fires, by the standard's names, sorted.
16
+ *
17
+ * `resize` is on the list because the standard puts it there: it fires when the
18
+ * video's own width or height changes, which is the moment a consumer sizing
19
+ * something to the picture needs.
20
+ */
21
+ export declare const MEDIA_EVENTS: readonly ['abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error', 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress', 'ratechange', 'resize', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting'];
22
+ /** One of the media events the player relays. */
23
+ export type MediaEventName = (typeof MEDIA_EVENTS)[number];
24
+ /**
25
+ * The copy the host sends: the same name, neither bubbling nor composed.
26
+ *
27
+ * **As the platform sends it, which is what makes it reach a React consumer at
28
+ * all.** These names are in react-dom's `nonDelegatedEvents`, which React wires
29
+ * on a `<video>` and never on a custom element, so its root listener hears none
30
+ * of them. `bindReactHandler` closes that for an event that does not bubble,
31
+ * and skips one that does, on the grounds that a bubbling relay already reaches
32
+ * React's delegated listener and binding it again would double every call. A
33
+ * copy sent with `bubbles: true` lands in the branch that refuses to bind, and
34
+ * `onPlay` on the player is silent.
35
+ *
36
+ * Not cancelable, as the platform's are not: the media has already moved by the
37
+ * time the event is sent, and a refusal would have nothing to stop.
38
+ */
39
+ export declare const relayedCopy: (event: Event) => Event;
40
+ /**
41
+ * Sends each media event the video fires on from the host, and returns what
42
+ * stops it.
43
+ *
44
+ * Bound once, after the first render, so the player's own listeners in its
45
+ * template are ahead of it on the same video: what a consumer reads off the
46
+ * player in a handler (`paused`, `volume`, `currentTime`) is already the
47
+ * player's state by the time the copy reaches them.
48
+ */
49
+ export declare const relayMedia: (video: EventTarget, host: EventTarget) => (() => void);
@@ -0,0 +1,39 @@
1
+ export const MEDIA_EVENTS = [
2
+ 'abort',
3
+ 'canplay',
4
+ 'canplaythrough',
5
+ 'durationchange',
6
+ 'emptied',
7
+ 'ended',
8
+ 'error',
9
+ 'loadeddata',
10
+ 'loadedmetadata',
11
+ 'loadstart',
12
+ 'pause',
13
+ 'play',
14
+ 'playing',
15
+ 'progress',
16
+ 'ratechange',
17
+ 'resize',
18
+ 'seeked',
19
+ 'seeking',
20
+ 'stalled',
21
+ 'suspend',
22
+ 'timeupdate',
23
+ 'volumechange',
24
+ 'waiting',
25
+ ];
26
+ export const relayedCopy = (event) => new Event(event.type, { bubbles: false, cancelable: false, composed: false });
27
+ export const relayMedia = (video, host) => {
28
+ const relay = (event) => {
29
+ host.dispatchEvent(relayedCopy(event));
30
+ };
31
+ for (const name of MEDIA_EVENTS) {
32
+ video.addEventListener(name, relay);
33
+ }
34
+ return () => {
35
+ for (const name of MEDIA_EVENTS) {
36
+ video.removeEventListener(name, relay);
37
+ }
38
+ };
39
+ };