@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
@@ -1,4 +1,4 @@
1
- import { HelixFormElement } from '@fusion.dev/helix-core';
1
+ import { HelixFormElement, type HourCycle } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../listbox/index.js';
4
4
  import '../../option/index.js';
@@ -10,14 +10,19 @@ declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fu
10
10
  * Shows the times at each `step` as a `Listbox`, which provides the keyboard
11
11
  * behavior, typeahead, scrolling into view, and announcements for a set of
12
12
  * options. `variant="wheels"` shows a column each for the hour, the minute, and
13
- * the meridiem.
13
+ * the meridiem, and one for the second with `seconds`. Left and Right move
14
+ * between the wheels, and Tab does too.
15
+ *
16
+ * `hour-cycle` writes every time on a twelve or a twenty-four hour clock
17
+ * whatever the locale, and `seconds` holds times to the second.
14
18
  *
15
19
  * The step keeps the list usable. At the default of 15 minutes a day is 96
16
20
  * rows, which people can scroll or type into. At 1 minute it is 1,440. Use the
17
21
  * list for the times your product offers, and Time Input for any time, the same
18
22
  * way Date Input separates typing a date from picking one on the calendar.
19
23
  *
20
- * The value is always `HH:mm` on a 24-hour clock. A form submits that shape,
24
+ * The value is always `HH:mm` on a 24-hour clock, or `HH:mm:ss` with
25
+ * `seconds`. A form submits that shape,
21
26
  * `min` and `max` compare against it, and it sorts as a string. Each row's text
22
27
  * follows the person's own conventions, from `Intl`.
23
28
  *
@@ -96,6 +101,15 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
96
101
  * reached honestly rather than by handing over an empty range.
97
102
  */
98
103
  disableTimes: string;
104
+ /**
105
+ * The clock the times are written on: `h12` for twelve hours with a
106
+ * meridiem, `h23` for twenty-four.
107
+ *
108
+ * Absent is the locale's own, which is right for a reader's own form. Set it
109
+ * where every reader must see the same clock whatever their language, as a
110
+ * timetable does. The value is `HH:mm` on twenty-four hours either way.
111
+ */
112
+ hourCycle?: HourCycle;
99
113
  /**
100
114
  * What the wheel of hours is called, read by screen readers.
101
115
  */
@@ -178,15 +192,19 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
178
192
  */
179
193
  rangeUnderflowMessage?: string;
180
194
  /**
181
- * Every time on offer, as minutes since midnight.
195
+ * Every time on offer, as seconds since midnight.
182
196
  *
183
197
  * Built from `min` upward rather than from midnight, so a list that starts at
184
198
  * `09:00` steps from nine rather than offering `09:15` because that is where
185
199
  * the quarter hours from midnight happen to land. A step that does not divide
186
200
  * the hour is a real thing to want, twenty minutes being the obvious one, and
187
- * this is the reading that makes it behave.
201
+ * this is the reading that makes it behave. See `offeredTimes`.
188
202
  */
189
203
  private get times();
204
+ /** The locale with the clock `hour-cycle` asks for. */
205
+ private get clock();
206
+ /** A time as the value writes it, to the second where `seconds` asks. */
207
+ private valueFor;
190
208
  /**
191
209
  * Whether a time is barred by name.
192
210
  *
@@ -199,6 +217,8 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
199
217
  * outside the bounds is absent rather than present and refused.
200
218
  */
201
219
  private barred;
220
+ /** The same question of seconds since midnight, matching `09:30` and `09:30:00` alike. */
221
+ private barredAt;
202
222
  /**
203
223
  * The offered time nearest to one the wheels built, which keeps them inside
204
224
  * `min`, `max` and `step`.
@@ -243,7 +263,7 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
243
263
  private readonly handleChange;
244
264
  /** Whether a time falls inside a range, which is what gets banded. */
245
265
  private between;
246
- /** The three readings a wheel shows, from the value or from `min`. */
266
+ /** The readings the wheels show, from the value or from `min`. */
247
267
  private get parts();
248
268
  /** Puts a changed column back together into a whole time. */
249
269
  private readonly moveColumn;
@@ -251,6 +271,8 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
251
271
  private get hours();
252
272
  /** Every minute offered within the hour currently shown. */
253
273
  private get minutes();
274
+ /** Every second offered within the minute currently shown. */
275
+ private get secondsShown();
254
276
  /**
255
277
  * Scrolls each wheel to its selected value, and the list to its selected
256
278
  * time.
@@ -299,7 +321,22 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
299
321
  */
300
322
  required: boolean;
301
323
  /**
302
- * How far apart the offered times are, in minutes.
324
+ * What the wheel of seconds is called, read by screen readers.
325
+ */
326
+ secondLabel: string;
327
+ /**
328
+ * Whether times carry their seconds.
329
+ *
330
+ * The value becomes `HH:mm:ss`, each time is written with its seconds, the
331
+ * wheels take a column of seconds, and `step` counts seconds, the unit
332
+ * `<input type="time">` counts in. A list at a step of one second is 86,400
333
+ * rows, so give `seconds` a `step` and bounds that keep it a list, or use
334
+ * the wheels.
335
+ */
336
+ seconds: boolean;
337
+ /**
338
+ * How far apart the offered times are, in minutes, or in seconds with
339
+ * `seconds`.
303
340
  *
304
341
  * Fifteen, which is four rows an hour and ninety-six in a day: enough that a
305
342
  * reader scrolls rather than hunts, and few enough that the list is a list.
@@ -446,7 +483,16 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
446
483
  * barred only when every minute in it is, since one free minute is a reason to
447
484
  * open the wheel rather than to close it.
448
485
  */
449
- protected renderColumn(part: 'hour' | 'meridiem' | 'minute', label: string, values: string[], written: (one: string) => string, value: string, barred?: (one: string) => boolean): TemplateResult;
486
+ protected renderColumn(part: 'hour' | 'meridiem' | 'minute' | 'second', label: string, values: string[], written: (one: string) => string, value: string, barred?: (one: string) => boolean): TemplateResult;
487
+ /**
488
+ * Left and Right move between the wheels, as Web Awesome's columns do, and
489
+ * Tab still does.
490
+ *
491
+ * A wheel is a listbox and takes Up and Down, so the horizontal pair was
492
+ * free. Along the line of text, which runs from the right on a right-to-left
493
+ * page, and stopping at the first and last wheel.
494
+ */
495
+ private readonly handleColumnsKeydown;
450
496
  private renderSpinner;
451
497
  /**
452
498
  * The flat list of times, for the variant that is not wheels, behind a seam the styled tier can move.
@@ -4,17 +4,12 @@ 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 { valueAsTime as asTime, customElement, elementById, fillTemplate, timeAsValue as fromTime, HelixFormElement, MixinControllerValue, minutesAsValue, reportValues, valueAsMinutes, writeTime, writtenList, } from '@fusion.dev/helix-core';
7
+ import { clockLocale, commaList, customElement, dayPeriod, elementById, fillTemplate, HelixFormElement, inlineStep, isTwelveHour, MixinControllerValue, nearestTime, offeredTimes, reportValues, secondsAsValue, timeBarred, timeFault, valueAsSeconds, wheelParts, wholeHour, writeClock, } from '@fusion.dev/helix-core';
8
8
  import { nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { html } from 'lit/static-html.js';
11
11
  import '../../listbox/index.js';
12
12
  import '../../option/index.js';
13
- const isTwelveHour = (locale) => new Intl.DateTimeFormat(locale || undefined, { timeStyle: 'short' }).resolvedOptions().hour12 ===
14
- true;
15
- const dayPeriod = (half, locale) => new Intl.DateTimeFormat(locale || undefined, { hour: 'numeric', hour12: true, timeZone: 'UTC' })
16
- .formatToParts(new Date(Date.UTC(1970, 0, 1, half === 'AM' ? 9 : 21)))
17
- .find((part) => part.type === 'dayPeriod')?.value ?? half;
18
13
  let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControllerValue(HelixFormElement) {
19
14
  constructor() {
20
15
  super(...arguments);
@@ -60,69 +55,78 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
60
55
  if (this.isDisabled) {
61
56
  return;
62
57
  }
63
- const { hour, meridiem, minute } = this.parts;
64
- let next = hour * 60 + minute;
58
+ const { hour, meridiem, minute, second } = this.parts;
59
+ let [h, m, sec] = [hour, minute, second];
65
60
  if (part === 'minute') {
66
- next = hour * 60 + Number(to);
61
+ m = Number(to);
62
+ }
63
+ else if (part === 'second') {
64
+ sec = Number(to);
67
65
  }
68
66
  else if (part === 'hour') {
69
- const shown = Number(to);
70
- const whole = isTwelveHour(this.locale) ? (shown % 12) + (meridiem === 'PM' ? 12 : 0) : shown;
71
- next = whole * 60 + minute;
67
+ h = wholeHour(Number(to), isTwelveHour(this.clock) ? meridiem : undefined);
72
68
  }
73
69
  else {
74
- const half = hour % 12;
75
- next = (half + (to === 'PM' ? 12 : 0)) * 60 + minute;
70
+ h = (hour % 12) + (to === 'PM' ? 12 : 0);
76
71
  }
77
- const whole = minutesAsValue(this.nearest(next));
78
- if (this.barred(whole)) {
72
+ const nearest = this.nearest(h * 3600 + m * 60 + sec);
73
+ if (this.barredAt(nearest)) {
79
74
  return;
80
75
  }
81
- this.requestValue(whole);
76
+ this.requestValue(this.valueFor(nearest));
82
77
  };
83
78
  this.readOnly = false;
84
79
  this.required = false;
80
+ this.secondLabel = 'Second';
81
+ this.seconds = false;
85
82
  this.step = 15;
86
83
  this.listRevealed = false;
87
84
  this.naming = undefined;
85
+ this.handleColumnsKeydown = (event) => {
86
+ const step = inlineStep(this, event.key);
87
+ if (step === 0 || event.altKey || event.ctrlKey || event.metaKey) {
88
+ return;
89
+ }
90
+ const columns = [...(this.renderRoot?.querySelectorAll('[part="column"]') ?? [])];
91
+ const at = columns.findIndex((column) => event.composedPath().includes(column));
92
+ const next = columns[at + step];
93
+ if (at < 0 || !next) {
94
+ return;
95
+ }
96
+ event.preventDefault();
97
+ next.focus();
98
+ };
88
99
  }
89
100
  get times() {
90
- const from = valueAsMinutes(this.min) ?? 0;
91
- const to = valueAsMinutes(this.max) ?? 1439;
92
- const step = Math.max(1, Math.round(this.step));
93
- const found = [];
94
- for (let at = from; at <= to; at += step) {
95
- found.push(at);
96
- }
97
- return found;
101
+ return offeredTimes(this.min, this.max, this.step, this.seconds);
102
+ }
103
+ get clock() {
104
+ return clockLocale(this.locale, this.hourCycle);
105
+ }
106
+ valueFor(at) {
107
+ return secondsAsValue(at, this.seconds);
98
108
  }
99
109
  barred(at) {
100
- return writtenList(this.disableTimes).includes(at);
101
- }
102
- nearest(minutes) {
103
- const times = this.times;
104
- let best = times[0] ?? minutes;
105
- for (const at of times) {
106
- if (Math.abs(at - minutes) < Math.abs(best - minutes)) {
107
- best = at;
108
- }
109
- }
110
- return best;
110
+ const seconds = valueAsSeconds(at);
111
+ return seconds !== null && this.barredAt(seconds);
112
+ }
113
+ barredAt(at) {
114
+ return timeBarred(at, this.disableTimes);
115
+ }
116
+ nearest(at) {
117
+ return nearestTime(this.times, at);
111
118
  }
112
119
  wholeHourBarred(shown, half) {
113
- const whole = half === undefined ? shown : (shown % 12) + (half === 'PM' ? 12 : 0);
114
- const within = this.times.filter((at) => Math.floor(at / 60) === whole);
115
- return within.length > 0 && within.every((at) => this.barred(minutesAsValue(at)));
120
+ const whole = wholeHour(shown, half);
121
+ const within = this.times.filter((at) => Math.floor(at / 3600) === whole);
122
+ return within.length > 0 && within.every((at) => this.barredAt(at));
116
123
  }
117
124
  halfBarred(half) {
118
- const within = this.times.filter((at) => (half === 'PM') === at >= 720);
119
- return within.length > 0 && within.every((at) => this.barred(minutesAsValue(at)));
125
+ const within = this.times.filter((at) => (half === 'PM') === at >= 43_200);
126
+ return within.length > 0 && within.every((at) => this.barredAt(at));
120
127
  }
121
128
  get held() {
122
- return this.value
123
- .split(',')
124
- .map((one) => one.trim())
125
- .filter(Boolean);
129
+ return commaList(this.value);
126
130
  }
127
131
  between(at) {
128
132
  if (this.mode !== 'range') {
@@ -132,17 +136,25 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
132
136
  return from !== undefined && to !== undefined && at > from && at < to;
133
137
  }
134
138
  get parts() {
135
- const at = valueAsMinutes(this.value) ?? valueAsMinutes(this.min) ?? 0;
136
- const hour = Math.floor(at / 60);
137
- return { hour, meridiem: hour < 12 ? 'AM' : 'PM', minute: at % 60 };
139
+ const at = valueAsSeconds(this.value) ?? valueAsSeconds(this.min) ?? 0;
140
+ return wheelParts(at, isTwelveHour(this.clock));
138
141
  }
139
142
  get hours() {
140
- const found = new Set(this.times.map((at) => Math.floor(at / 60)));
143
+ const found = new Set(this.times.map((at) => Math.floor(at / 3600)));
141
144
  return [...found];
142
145
  }
143
146
  get minutes() {
144
147
  const hour = this.parts.hour;
145
- return this.times.filter((at) => Math.floor(at / 60) === hour).map((at) => at % 60);
148
+ const found = new Set(this.times
149
+ .filter((at) => Math.floor(at / 3600) === hour)
150
+ .map((at) => Math.floor(at / 60) % 60));
151
+ return [...found];
152
+ }
153
+ get secondsShown() {
154
+ const { hour, minute } = this.parts;
155
+ return this.times
156
+ .filter((at) => Math.floor(at / 60) === hour * 60 + minute)
157
+ .map((at) => at % 60);
146
158
  }
147
159
  reveal() {
148
160
  if (this.mode !== undefined) {
@@ -163,32 +175,33 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
163
175
  return super.requestValue(next);
164
176
  }
165
177
  fault(at) {
166
- const minutes = valueAsMinutes(at) ?? 0;
167
- const floor = valueAsMinutes(this.min) ?? 0;
168
- const ceiling = valueAsMinutes(this.max) ?? 1439;
169
- if (minutes < floor) {
170
- return [
171
- 'rangeUnderflow',
172
- fillTemplate(this.rangeUnderflowMessage || 'Choose a time at or after {min}.', {
173
- min: writeTime(this.min, this.locale),
174
- }),
175
- ];
176
- }
177
- if (minutes > ceiling) {
178
- return [
179
- 'rangeOverflow',
180
- fillTemplate(this.rangeOverflowMessage || 'Choose a time at or before {max}.', {
181
- max: writeTime(this.max, this.locale),
182
- }),
183
- ];
184
- }
185
- if (this.barred(at)) {
186
- return ['badInput', this.unavailableMessage || 'Choose a time that is available.'];
187
- }
188
- if (!this.times.includes(minutes)) {
189
- return ['stepMismatch', this.stepMismatchMessage || 'Choose one of the times on offer.'];
178
+ switch (timeFault(at, {
179
+ disableTimes: this.disableTimes,
180
+ max: this.max,
181
+ min: this.min,
182
+ offered: this.times,
183
+ })) {
184
+ case 'rangeUnderflow':
185
+ return [
186
+ 'rangeUnderflow',
187
+ fillTemplate(this.rangeUnderflowMessage || 'Choose a time at or after {min}.', {
188
+ min: writeClock(this.min, this.clock, this.seconds),
189
+ }),
190
+ ];
191
+ case 'rangeOverflow':
192
+ return [
193
+ 'rangeOverflow',
194
+ fillTemplate(this.rangeOverflowMessage || 'Choose a time at or before {max}.', {
195
+ max: writeClock(this.max, this.clock, this.seconds),
196
+ }),
197
+ ];
198
+ case 'unavailable':
199
+ return ['badInput', this.unavailableMessage || 'Choose a time that is available.'];
200
+ case 'stepMismatch':
201
+ return ['stepMismatch', this.stepMismatchMessage || 'Choose one of the times on offer.'];
202
+ default:
203
+ return undefined;
190
204
  }
191
- return undefined;
192
205
  }
193
206
  reportRequired() {
194
207
  const anchor = this.partNamed('list') ?? undefined;
@@ -197,11 +210,12 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
197
210
  return;
198
211
  }
199
212
  const held = this.held;
200
- if (held.length > 0 && held.some((one) => asTime(one) === null)) {
213
+ if (held.length > 0 && held.some((one) => valueAsSeconds(one) === null)) {
214
+ const shape = this.seconds ? 'HH:mm:ss' : 'HH:mm';
201
215
  this.internals.setValidity({ badInput: true }, this.badInputMessage ||
202
216
  (this.mode === undefined
203
- ? 'Enter a time as HH:mm.'
204
- : 'Enter times as HH:mm, separated by commas.'), anchor);
217
+ ? `Enter a time as ${shape}.`
218
+ : `Enter times as ${shape}, separated by commas.`), anchor);
205
219
  return;
206
220
  }
207
221
  for (const one of held) {
@@ -297,9 +311,8 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
297
311
  </${this.tag('listbox')}>`;
298
312
  }
299
313
  renderSpinner() {
300
- const twelve = isTwelveHour(this.locale);
301
- const { hour, meridiem, minute } = this.parts;
302
- const shownHour = twelve ? String(hour % 12 === 0 ? 12 : hour % 12) : String(hour);
314
+ const twelve = isTwelveHour(this.clock);
315
+ const { hour, meridiem, minute, second, shown } = this.parts;
303
316
  const hours = twelve
304
317
  ? [...new Set(this.hours.map((one) => (one % 12 === 0 ? 12 : one % 12)))].sort((a, b) => a - b)
305
318
  : this.hours;
@@ -308,11 +321,15 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
308
321
  role="group"
309
322
  aria-label=${this.listName}
310
323
  data-unset=${this.value === '' ? '' : nothing}
324
+ @keydown=${this.handleColumnsKeydown}
311
325
  >
312
- ${this.renderColumn('hour', this.hourLabel, hours.map(String), (one) => (twelve ? one : one.padStart(2, '0')), shownHour, (one) => this.wholeHourBarred(Number(one), twelve ? meridiem : undefined))}
313
- ${this.renderColumn('minute', this.minuteLabel, this.minutes.map(String), (one) => one.padStart(2, '0'), String(minute), (one) => this.barred(minutesAsValue(hour * 60 + Number(one))))}
326
+ ${this.renderColumn('hour', this.hourLabel, hours.map(String), (one) => (twelve ? one : one.padStart(2, '0')), String(shown), (one) => this.wholeHourBarred(Number(one), twelve ? meridiem : undefined))}
327
+ ${this.renderColumn('minute', this.minuteLabel, this.minutes.map(String), (one) => one.padStart(2, '0'), String(minute), (one) => this.barredAt(hour * 3600 + Number(one) * 60))}
328
+ ${this.seconds
329
+ ? this.renderColumn('second', this.secondLabel, this.secondsShown.map(String), (one) => one.padStart(2, '0'), String(second), (one) => this.barredAt(hour * 3600 + minute * 60 + Number(one)))
330
+ : nothing}
314
331
  ${twelve
315
- ? this.renderColumn('meridiem', this.meridiemLabel, ['AM', 'PM'], (one) => dayPeriod(one, this.locale), meridiem, (one) => this.halfBarred(one))
332
+ ? this.renderColumn('meridiem', this.meridiemLabel, ['AM', 'PM'], (one) => dayPeriod(one, this.clock), meridiem, (one) => this.halfBarred(one))
316
333
  : nothing}
317
334
  </div>`;
318
335
  }
@@ -332,8 +349,8 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
332
349
  @helix-before-change=${this.handleChange}
333
350
  @input=${this.handleListInput}
334
351
  >
335
- ${this.times.map((minutes) => {
336
- const at = minutesAsValue(minutes);
352
+ ${this.times.map((seconds) => {
353
+ const at = this.valueFor(seconds);
337
354
  const between = this.between(at);
338
355
  return html `<${this.tag('option')}
339
356
  part="option${between ? ' option-between' : ''}"
@@ -344,7 +361,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
344
361
  ?disabled=${this.barred(at)}
345
362
  ?selected=${this.held.includes(at)}
346
363
  data-between=${between ? '' : nothing}
347
- >${writeTime(at, this.locale)}</${this.tag('option')}
364
+ >${writeClock(at, this.clock, this.seconds)}</${this.tag('option')}
348
365
  >`;
349
366
  })}
350
367
  </${this.tag('listbox')}>`;
@@ -356,16 +373,20 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
356
373
  return html `${this.renderList()}`;
357
374
  }
358
375
  get valueAsDate() {
359
- return asTime(this.value);
376
+ const at = valueAsSeconds(this.value);
377
+ return at === null ? null : new Date(at * 1000);
360
378
  }
361
379
  set valueAsDate(date) {
362
- this.value = fromTime(date);
380
+ this.valueAsNumber = date ? date.getTime() : Number.NaN;
363
381
  }
364
382
  get valueAsNumber() {
365
- return asTime(this.value)?.getTime() ?? Number.NaN;
383
+ const at = valueAsSeconds(this.value);
384
+ return at === null ? Number.NaN : at * 1000;
366
385
  }
367
386
  set valueAsNumber(ms) {
368
- this.value = Number.isNaN(ms) ? '' : fromTime(new Date(ms));
387
+ this.value = Number.isNaN(ms)
388
+ ? ''
389
+ : this.valueFor(Math.floor((((ms % 86_400_000) + 86_400_000) % 86_400_000) / 1000));
369
390
  }
370
391
  };
371
392
  __decorate([
@@ -374,6 +395,9 @@ __decorate([
374
395
  __decorate([
375
396
  property({ attribute: 'disable-times' })
376
397
  ], HelixHeadlessTimePicker.prototype, "disableTimes", void 0);
398
+ __decorate([
399
+ property({ attribute: 'hour-cycle' })
400
+ ], HelixHeadlessTimePicker.prototype, "hourCycle", void 0);
377
401
  __decorate([
378
402
  property({ attribute: 'hour-label' })
379
403
  ], HelixHeadlessTimePicker.prototype, "hourLabel", void 0);
@@ -416,6 +440,12 @@ __decorate([
416
440
  __decorate([
417
441
  property({ reflect: true, type: Boolean })
418
442
  ], HelixHeadlessTimePicker.prototype, "required", void 0);
443
+ __decorate([
444
+ property({ attribute: 'second-label' })
445
+ ], HelixHeadlessTimePicker.prototype, "secondLabel", void 0);
446
+ __decorate([
447
+ property({ type: Boolean })
448
+ ], HelixHeadlessTimePicker.prototype, "seconds", void 0);
419
449
  __decorate([
420
450
  property({ type: Number })
421
451
  ], HelixHeadlessTimePicker.prototype, "step", void 0);
@@ -0,0 +1,46 @@
1
+ import { HelixElement } from '@fusion.dev/helix-core';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
+ /**
4
+ * @summary A run of timeline entries under a heading, such as a day.
5
+ *
6
+ * @description
7
+ * Groups entries by date, such as "Today" and "Yesterday", in a timeline that
8
+ * holds many. The group is an entry of the timeline, and its entries are a
9
+ * list of their own, named by the heading. A screen reader lists the heading
10
+ * with the page's headings and hears how many entries each day holds.
11
+ *
12
+ * The heading's level is `heading-level`, and 3 where it is not set.
13
+ *
14
+ * Each group draws its own line, so the line stops at the last entry of one
15
+ * day and starts again at the first entry of the next.
16
+ *
17
+ * @since 0.1.0
18
+ * @status stable
19
+ * @aliases Day, Section, Date group
20
+ * @documentation https://fusion.dev/helix/components/timeline
21
+ *
22
+ * @slot - The entries.
23
+ * @slot heading - The heading, when it is more than text. Falls back to `label`.
24
+ *
25
+ * @csspart entries - The list that holds the entries.
26
+ * @csspart heading - The heading.
27
+ */
28
+ export declare class HelixHeadlessTimelineGroup extends HelixElement {
29
+ /**
30
+ * The level of the group's heading, from 1 to 6.
31
+ */
32
+ headingLevel?: number;
33
+ /**
34
+ * The heading, when it is plain text, such as "Today".
35
+ *
36
+ * The fallback of the `heading` slot, so slotted content replaces it.
37
+ */
38
+ label: string;
39
+ protected willUpdate(changed: PropertyValues): void;
40
+ protected render(): TemplateResult;
41
+ }
42
+ declare global {
43
+ interface HTMLElementTagNameMap {
44
+ 'helix-headless-timeline-group': HelixHeadlessTimelineGroup;
45
+ }
46
+ }
@@ -0,0 +1,37 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
+ import { html } from 'lit';
9
+ import { property } from 'lit/decorators.js';
10
+ const HEADING_ID = 'heading';
11
+ let HelixHeadlessTimelineGroup = class HelixHeadlessTimelineGroup extends HelixElement {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.label = '';
15
+ }
16
+ willUpdate(changed) {
17
+ super.willUpdate(changed);
18
+ hostAria(this.internals, { role: 'listitem' });
19
+ }
20
+ render() {
21
+ const level = Math.min(6, Math.max(1, Math.trunc(this.headingLevel ?? 3)));
22
+ return html `<div part="heading" id=${HEADING_ID} role="heading" aria-level=${level}>
23
+ <slot name="heading">${this.label}</slot>
24
+ </div>
25
+ <div part="entries" role="list" aria-labelledby=${HEADING_ID}><slot></slot></div>`;
26
+ }
27
+ };
28
+ __decorate([
29
+ property({ attribute: 'heading-level', type: Number })
30
+ ], HelixHeadlessTimelineGroup.prototype, "headingLevel", void 0);
31
+ __decorate([
32
+ property()
33
+ ], HelixHeadlessTimelineGroup.prototype, "label", void 0);
34
+ HelixHeadlessTimelineGroup = __decorate([
35
+ customElement('helix-headless-timeline-group')
36
+ ], HelixHeadlessTimelineGroup);
37
+ export { HelixHeadlessTimelineGroup };
@@ -1,2 +1,3 @@
1
+ export * from './group/timeline-group.js';
1
2
  export * from './item/timeline-item.js';
2
3
  export * from './root/timeline-root.js';
@@ -1,2 +1,3 @@
1
+ export * from './group/timeline-group.js';
1
2
  export * from './item/timeline-item.js';
2
3
  export * from './root/timeline-root.js';
@@ -16,8 +16,15 @@ import { type PropertyValues, type TemplateResult } from 'lit';
16
16
  * The host has `role="list"`, because the entries are your elements in the
17
17
  * light DOM. `Steps` does the same.
18
18
  *
19
- * A timeline runs down the page and has no horizontal layout. For stages laid
20
- * out horizontally, use `Steps`, which is horizontal by default.
19
+ * **Group entries by date with `Timeline.Group`**, which puts a heading such as
20
+ * "Today" over its entries. The group is an entry of the timeline, and its
21
+ * entries are a list of their own named by the heading.
22
+ *
23
+ * **The reading order is the order you write the entries in**, in every layout
24
+ * the styled tier draws: down the page, either side of a line down the middle,
25
+ * or across the page. Inside each entry the time is read before what happened.
26
+ * Write the entries in the order the events happened, oldest or newest first,
27
+ * and the layout only moves where they are drawn.
21
28
  *
22
29
  * @since 0.1.0
23
30
  * @status stable
@@ -25,7 +32,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
25
32
  * @aliases Activity feed, History, Changelog, Audit trail
26
33
  * @documentation https://fusion.dev/helix/components/timeline
27
34
  *
28
- * @slot - The entries.
35
+ * @slot - The entries, and any groups of them.
29
36
  */
30
37
  export declare class HelixHeadlessTimeline extends HelixElement {
31
38
  /**
@@ -0,0 +1,22 @@
1
+ import { type ChordPress } from '@fusion.dev/helix-core';
2
+ /** A key and the modifiers held with it. */
3
+ export interface Chord {
4
+ alt: boolean;
5
+ ctrl: boolean;
6
+ key: string;
7
+ meta: boolean;
8
+ shift: boolean;
9
+ }
10
+ /** What a key press carries that a chord is compared against. */
11
+ export type Pressed = ChordPress;
12
+ /**
13
+ * Reads a chord written as keys joined by `+`, such as `F8` or `Alt+T`, case
14
+ * aside. The last part is the key. Empty, or a chord with no key, is none.
15
+ *
16
+ * Split as core's `chordParts` splits every chord, and read more strictly than
17
+ * Kbd reads one: four modifiers by their own names, no `mod`, and Shift held
18
+ * exactly as written, so the key that moves to the stack is the one written.
19
+ */
20
+ export declare const parseHotkey: (text: string) => Chord | null;
21
+ /** Whether a press is the chord: the same key, case aside, and exactly its modifiers. */
22
+ export declare const matchesHotkey: (pressed: Pressed, chord: Chord | null) => boolean;
@@ -0,0 +1,23 @@
1
+ import { chordParts } from '@fusion.dev/helix-core';
2
+ const MODIFIERS = new Set(['alt', 'ctrl', 'meta', 'shift']);
3
+ export const parseHotkey = (text) => {
4
+ const parts = chordParts(text);
5
+ const key = parts.pop();
6
+ if (!key || MODIFIERS.has(key.toLowerCase())) {
7
+ return null;
8
+ }
9
+ const held = new Set(parts.map((one) => one.toLowerCase()));
10
+ return {
11
+ alt: held.has('alt'),
12
+ ctrl: held.has('ctrl'),
13
+ key,
14
+ meta: held.has('meta'),
15
+ shift: held.has('shift'),
16
+ };
17
+ };
18
+ export const matchesHotkey = (pressed, chord) => chord !== null &&
19
+ pressed.key.toLowerCase() === chord.key.toLowerCase() &&
20
+ pressed.altKey === chord.alt &&
21
+ pressed.ctrlKey === chord.ctrl &&
22
+ pressed.metaKey === chord.meta &&
23
+ pressed.shiftKey === chord.shift;