@fusion.dev/helix-headless 0.142.1 → 0.144.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 (285) hide show
  1. package/custom-elements.json +25381 -1202
  2. package/dist/accordion/item/accordion-item.d.ts +38 -2
  3. package/dist/accordion/item/accordion-item.js +38 -6
  4. package/dist/accordion/root/accordion-root.d.ts +23 -1
  5. package/dist/accordion/root/accordion-root.js +39 -3
  6. package/dist/announcement/root/announcement-root.d.ts +11 -7
  7. package/dist/announcement/root/announcement-root.js +1 -1
  8. package/dist/app-header/root/app-header-root.d.ts +21 -0
  9. package/dist/app-header/root/app-header-root.js +31 -5
  10. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  11. package/dist/area-chart/root/area-chart-root.js +39 -11
  12. package/dist/avatar/group/avatar-group.d.ts +24 -3
  13. package/dist/avatar/group/avatar-group.js +34 -2
  14. package/dist/avatar/root/avatar-root.d.ts +17 -1
  15. package/dist/avatar/root/avatar-root.js +31 -10
  16. package/dist/badge/root/badge-root.d.ts +12 -0
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
  19. package/dist/bar-chart/root/bar-chart-root.js +58 -21
  20. package/dist/blockquote/root/blockquote-root.d.ts +12 -7
  21. package/dist/blockquote/root/blockquote-root.js +6 -4
  22. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
  23. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
  24. package/dist/button/root/button-root.d.ts +84 -1
  25. package/dist/button/root/button-root.js +81 -3
  26. package/dist/callout/root/callout-root.d.ts +32 -6
  27. package/dist/callout/root/callout-root.js +26 -7
  28. package/dist/canvas/root/canvas-root.d.ts +1 -0
  29. package/dist/canvas/root/canvas-root.js +10 -1
  30. package/dist/card/root/card-root.d.ts +30 -1
  31. package/dist/card/root/card-root.js +38 -5
  32. package/dist/carousel/root/carousel-root.d.ts +47 -5
  33. package/dist/carousel/root/carousel-root.js +53 -21
  34. package/dist/chat/composer/chat-composer.d.ts +13 -11
  35. package/dist/chat/composer/chat-composer.js +6 -12
  36. package/dist/chat/message/chat-message.js +8 -1
  37. package/dist/chat/root/chat-root.d.ts +1 -0
  38. package/dist/chat/root/chat-root.js +2 -1
  39. package/dist/checkbox/root/checkbox-root.d.ts +7 -0
  40. package/dist/checkbox/root/checkbox-root.js +9 -3
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
  42. package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
  43. package/dist/code/root/code-root.d.ts +1 -1
  44. package/dist/code-block/lines.d.ts +13 -0
  45. package/dist/code-block/lines.js +2 -0
  46. package/dist/code-block/root/code-block-root.d.ts +49 -0
  47. package/dist/code-block/root/code-block-root.js +44 -3
  48. package/dist/color-input/root/color-input-root.d.ts +60 -2
  49. package/dist/color-input/root/color-input-root.js +55 -7
  50. package/dist/color-picker/channels.d.ts +26 -0
  51. package/dist/color-picker/channels.js +84 -0
  52. package/dist/color-picker/root/color-picker-root.d.ts +118 -12
  53. package/dist/color-picker/root/color-picker-root.js +183 -13
  54. package/dist/combobox/root/combobox-root.d.ts +126 -3
  55. package/dist/combobox/root/combobox-root.js +224 -21
  56. package/dist/command/root/command-root.d.ts +47 -10
  57. package/dist/command/root/command-root.js +45 -4
  58. package/dist/copy-button/from.d.ts +22 -0
  59. package/dist/copy-button/from.js +28 -0
  60. package/dist/copy-button/root/copy-button-root.d.ts +48 -7
  61. package/dist/copy-button/root/copy-button-root.js +54 -8
  62. package/dist/data-table/root/data-table-root.d.ts +164 -10
  63. package/dist/data-table/root/data-table-root.js +488 -57
  64. package/dist/date-input/root/date-input-root.d.ts +123 -9
  65. package/dist/date-input/root/date-input-root.js +147 -45
  66. package/dist/date-picker/root/date-picker-root.d.ts +229 -18
  67. package/dist/date-picker/root/date-picker-root.js +342 -46
  68. package/dist/dialog/description.d.ts +9 -0
  69. package/dist/dialog/description.js +14 -0
  70. package/dist/dialog/root/dialog-root.d.ts +101 -10
  71. package/dist/dialog/root/dialog-root.js +83 -4
  72. package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
  73. package/dist/donut-chart/root/donut-chart-root.js +48 -13
  74. package/dist/drawer/root/drawer-root.d.ts +93 -7
  75. package/dist/drawer/root/drawer-root.js +126 -5
  76. package/dist/drawer/swipe-start.d.ts +9 -0
  77. package/dist/drawer/swipe-start.js +12 -0
  78. package/dist/drilldown/item/drilldown-item.d.ts +16 -13
  79. package/dist/drilldown/item/drilldown-item.js +6 -2
  80. package/dist/drilldown/root/drilldown-root.d.ts +21 -5
  81. package/dist/drilldown/root/drilldown-root.js +26 -10
  82. package/dist/element-events.generated.js +42 -13
  83. package/dist/empty/root/empty-root.d.ts +1 -1
  84. package/dist/file-input/root/file-input-root.d.ts +65 -1
  85. package/dist/file-input/root/file-input-root.js +76 -12
  86. package/dist/file-input/screen.d.ts +35 -0
  87. package/dist/file-input/screen.js +49 -0
  88. package/dist/filter-input/menu/filter-menu.d.ts +9 -0
  89. package/dist/filter-input/menu/filter-menu.js +8 -0
  90. package/dist/filter-input/root/filter-input-root.d.ts +43 -6
  91. package/dist/filter-input/root/filter-input-root.js +89 -10
  92. package/dist/filter-input/suggest.d.ts +17 -0
  93. package/dist/filter-input/suggest.js +23 -0
  94. package/dist/format-date/options.d.ts +33 -0
  95. package/dist/format-date/options.js +42 -0
  96. package/dist/format-date/root/format-date-root.d.ts +62 -3
  97. package/dist/format-date/root/format-date-root.js +78 -37
  98. package/dist/graph/root/graph-root.d.ts +24 -3
  99. package/dist/graph/root/graph-root.js +66 -12
  100. package/dist/heatmap/root/buckets.d.ts +2 -1
  101. package/dist/heatmap/root/buckets.js +5 -1
  102. package/dist/heatmap/root/heatmap-root.d.ts +47 -9
  103. package/dist/heatmap/root/heatmap-root.js +46 -18
  104. package/dist/icon/index.d.ts +2 -0
  105. package/dist/icon/index.js +2 -0
  106. package/dist/icon/registry.d.ts +37 -0
  107. package/dist/icon/registry.js +83 -0
  108. package/dist/icon/root/icon-root.d.ts +53 -6
  109. package/dist/icon/root/icon-root.js +72 -4
  110. package/dist/icon/root/index.d.ts +2 -0
  111. package/dist/icon/root/index.js +2 -0
  112. package/dist/icon/set.d.ts +1 -0
  113. package/dist/icon/set.js +3 -0
  114. package/dist/icon-button/root/icon-button-root.d.ts +1 -1
  115. package/dist/image/root/image-root.d.ts +23 -2
  116. package/dist/image/root/image-root.js +23 -4
  117. package/dist/input/root/input-root.d.ts +62 -9
  118. package/dist/input/root/input-root.js +61 -5
  119. package/dist/kbd/root/kbd-root.d.ts +26 -11
  120. package/dist/kbd/root/kbd-root.js +35 -38
  121. package/dist/kbd/shortcut.d.ts +18 -0
  122. package/dist/kbd/shortcut.js +35 -0
  123. package/dist/legend/hidden-series.d.ts +8 -0
  124. package/dist/legend/hidden-series.js +13 -0
  125. package/dist/legend/root/legend-root.d.ts +63 -0
  126. package/dist/legend/root/legend-root.js +61 -7
  127. package/dist/lightbox/item/lightbox-item.d.ts +17 -1
  128. package/dist/lightbox/item/lightbox-item.js +10 -1
  129. package/dist/lightbox/root/lightbox-root.d.ts +77 -6
  130. package/dist/lightbox/root/lightbox-root.js +116 -5
  131. package/dist/line-chart/root/line-chart-root.d.ts +29 -4
  132. package/dist/line-chart/root/line-chart-root.js +58 -17
  133. package/dist/list/item/list-item.d.ts +11 -5
  134. package/dist/list/item/list-item.js +5 -6
  135. package/dist/listbox/range.d.ts +17 -0
  136. package/dist/listbox/range.js +5 -0
  137. package/dist/listbox/root/listbox-root.d.ts +184 -4
  138. package/dist/listbox/root/listbox-root.js +229 -23
  139. package/dist/loader/busy.d.ts +17 -0
  140. package/dist/loader/busy.js +24 -0
  141. package/dist/loader/root/loader-root.d.ts +37 -0
  142. package/dist/loader/root/loader-root.js +52 -3
  143. package/dist/map/root/map-root.d.ts +19 -4
  144. package/dist/map/root/map-root.js +36 -7
  145. package/dist/megamenu/root/megamenu-root.d.ts +10 -1
  146. package/dist/megamenu/root/megamenu-root.js +10 -1
  147. package/dist/menu/item/menu-item.d.ts +41 -12
  148. package/dist/menu/item/menu-item.js +46 -3
  149. package/dist/menu/root/menu-root.d.ts +32 -2
  150. package/dist/menu/root/menu-root.js +48 -8
  151. package/dist/meter/root/meter-root.d.ts +13 -0
  152. package/dist/meter/root/meter-root.js +24 -5
  153. package/dist/navigation/root/navigation-root.d.ts +10 -2
  154. package/dist/navigation/root/navigation-root.js +13 -2
  155. package/dist/notifications/feed-keys.d.ts +10 -0
  156. package/dist/notifications/feed-keys.js +14 -0
  157. package/dist/notifications/group/notification-group.d.ts +1 -0
  158. package/dist/notifications/notification/notification.d.ts +29 -0
  159. package/dist/notifications/notification/notification.js +51 -3
  160. package/dist/notifications/root/notifications-root.d.ts +49 -0
  161. package/dist/notifications/root/notifications-root.js +76 -2
  162. package/dist/number-input/root/number-input-root.d.ts +109 -7
  163. package/dist/number-input/root/number-input-root.js +109 -21
  164. package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
  165. package/dist/object-inspector/root/object-inspector-root.js +92 -12
  166. package/dist/option/root/option-root.d.ts +58 -6
  167. package/dist/option/root/option-root.js +35 -5
  168. package/dist/outline/root/outline-root.d.ts +13 -2
  169. package/dist/outline/root/outline-root.js +4 -2
  170. package/dist/pagination/root/pagination-root.d.ts +19 -1
  171. package/dist/pagination/root/pagination-root.js +49 -9
  172. package/dist/pagination/size/pagination-size.d.ts +13 -3
  173. package/dist/pagination/size/pagination-size.js +7 -0
  174. package/dist/pin-input/format.d.ts +7 -0
  175. package/dist/pin-input/format.js +16 -0
  176. package/dist/pin-input/root/pin-input-root.d.ts +37 -0
  177. package/dist/pin-input/root/pin-input-root.js +48 -7
  178. package/dist/popover/root/popover-root.d.ts +78 -3
  179. package/dist/popover/root/popover-root.js +74 -5
  180. package/dist/progress/root/progress-root.d.ts +23 -1
  181. package/dist/progress/root/progress-root.js +40 -10
  182. package/dist/qr-code/export.d.ts +31 -0
  183. package/dist/qr-code/export.js +10 -0
  184. package/dist/qr-code/root/qr-code-root.d.ts +45 -0
  185. package/dist/qr-code/root/qr-code-root.js +78 -3
  186. package/dist/radio/group/radio-group.d.ts +64 -0
  187. package/dist/radio/group/radio-group.js +66 -12
  188. package/dist/radio/root/radio-root.d.ts +8 -5
  189. package/dist/radio/root/radio-root.js +1 -2
  190. package/dist/rating/root/rating-root.d.ts +49 -1
  191. package/dist/rating/root/rating-root.js +69 -10
  192. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  193. package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
  194. package/dist/select/root/select-root.d.ts +93 -3
  195. package/dist/select/root/select-root.js +111 -13
  196. package/dist/skeleton/root/skeleton-root.d.ts +39 -3
  197. package/dist/skeleton/root/skeleton-root.js +33 -4
  198. package/dist/skip-link/root/skip-link-root.d.ts +10 -0
  199. package/dist/skip-link/root/skip-link-root.js +15 -1
  200. package/dist/slider/root/slider-root.d.ts +59 -2
  201. package/dist/slider/root/slider-root.js +82 -8
  202. package/dist/sparkline/root/sparkline-root.d.ts +9 -10
  203. package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
  204. package/dist/speed-dial/item/speed-dial-item.js +7 -2
  205. package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
  206. package/dist/speed-dial/root/speed-dial-root.js +19 -5
  207. package/dist/splitter/root/splitter-root.d.ts +28 -6
  208. package/dist/splitter/root/splitter-root.js +35 -1
  209. package/dist/stat/root/stat-root.d.ts +9 -1
  210. package/dist/stat/root/stat-root.js +15 -2
  211. package/dist/steps/root/steps-root.js +1 -1
  212. package/dist/steps/step/step.d.ts +1 -0
  213. package/dist/steps/step/step.js +1 -1
  214. package/dist/switch/root/switch-root.d.ts +14 -2
  215. package/dist/switch/root/switch-root.js +7 -1
  216. package/dist/table/cell/table-cell.d.ts +24 -4
  217. package/dist/table/cell/table-cell.js +21 -1
  218. package/dist/table/column/table-column.d.ts +32 -6
  219. package/dist/table/column/table-column.js +36 -6
  220. package/dist/table/root/table-root.d.ts +94 -3
  221. package/dist/table/root/table-root.js +128 -5
  222. package/dist/table/row/table-row.d.ts +7 -0
  223. package/dist/table/row/table-row.js +9 -1
  224. package/dist/tabs/root/tabs-root.d.ts +6 -1
  225. package/dist/tabs/root/tabs-root.js +6 -2
  226. package/dist/tag/group/tag-group.d.ts +107 -0
  227. package/dist/tag/group/tag-group.js +157 -0
  228. package/dist/tag/index.d.ts +1 -0
  229. package/dist/tag/index.js +1 -0
  230. package/dist/tag/root/tag-root.d.ts +83 -1
  231. package/dist/tag/root/tag-root.js +87 -17
  232. package/dist/tag/selection.d.ts +10 -0
  233. package/dist/tag/selection.js +12 -0
  234. package/dist/textarea/grow.d.ts +22 -0
  235. package/dist/textarea/grow.js +20 -0
  236. package/dist/textarea/root/textarea-root.d.ts +13 -0
  237. package/dist/textarea/root/textarea-root.js +10 -2
  238. package/dist/time-input/root/time-input-root.d.ts +71 -6
  239. package/dist/time-input/root/time-input-root.js +110 -44
  240. package/dist/time-picker/root/time-picker-root.d.ts +155 -26
  241. package/dist/time-picker/root/time-picker-root.js +192 -63
  242. package/dist/toast/hotkey.d.ts +22 -0
  243. package/dist/toast/hotkey.js +23 -0
  244. package/dist/toast/item/toast-item.d.ts +16 -1
  245. package/dist/toast/item/toast-item.js +41 -13
  246. package/dist/toast/root/toast-root.d.ts +105 -8
  247. package/dist/toast/root/toast-root.js +209 -4
  248. package/dist/toggle/group/toggle-group.d.ts +95 -16
  249. package/dist/toggle/group/toggle-group.js +99 -13
  250. package/dist/toggle/root/toggle-root.d.ts +26 -11
  251. package/dist/toggle/root/toggle-root.js +14 -6
  252. package/dist/toolbar/root/toolbar-root.d.ts +55 -15
  253. package/dist/toolbar/root/toolbar-root.js +99 -16
  254. package/dist/tooltip/focus-target.d.ts +6 -0
  255. package/dist/tooltip/focus-target.js +9 -0
  256. package/dist/tooltip/root/tooltip-root.d.ts +73 -15
  257. package/dist/tooltip/root/tooltip-root.js +96 -7
  258. package/dist/tour/naming.d.ts +30 -0
  259. package/dist/tour/naming.js +10 -0
  260. package/dist/tour/root/tour-root.d.ts +67 -3
  261. package/dist/tour/root/tour-root.js +105 -17
  262. package/dist/tour/stop/tour-stop.d.ts +65 -3
  263. package/dist/tour/stop/tour-stop.js +61 -11
  264. package/dist/tour/wait.d.ts +11 -0
  265. package/dist/tour/wait.js +19 -0
  266. package/dist/tree/item/tree-item.d.ts +21 -5
  267. package/dist/tree/item/tree-item.js +14 -4
  268. package/dist/tree/root/tree-root.d.ts +29 -5
  269. package/dist/tree/root/tree-root.js +64 -8
  270. package/dist/trend/root/trend-root.d.ts +36 -1
  271. package/dist/trend/root/trend-root.js +41 -15
  272. package/dist/video/root/keys.d.ts +5 -0
  273. package/dist/video/root/keys.js +13 -1
  274. package/dist/video/root/video-root.d.ts +19 -0
  275. package/dist/video/root/video-root.js +48 -4
  276. package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
  277. package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
  278. package/dist/video-playlist/root/video-playlist-root.js +6 -3
  279. package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
  280. package/dist/virtual-list/root/virtual-list-root.js +103 -21
  281. package/lint.json +1 -1
  282. package/package.json +5 -5
  283. package/types/jsx.d.ts +9140 -1149
  284. package/types/svelte.d.ts +1 -0
  285. package/types/vue.d.ts +2089 -267
@@ -4,27 +4,29 @@ 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, valueAsTime as asTime, customElement, fillTemplate, timeAsValue as fromTime, HelixFormElement, isTimeValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinTokens, valueAsMinutes, writeTime, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, valueAsTime as asTime, clockLocale, customElement, fillTemplate, timeAsValue as fromTime, HelixFormElement, isClockValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinSegmentedField, MixinTokens, timeFault, writeClock, } from '@fusion.dev/helix-core';
8
8
  import { clock } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
12
12
  import { html } from 'lit/static-html.js';
13
- import '../../icon/index.js';
14
13
  import '../../tag/index.js';
15
14
  import '../../time-picker/index.js';
16
- let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEditing(MixinPickerField(MixinControllerOpen(MixinTokens(MixinControllerValue(MixinField(HelixFormElement)))))) {
15
+ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmentedField(MixinPickerEditing(MixinPickerField(MixinControllerOpen(MixinTokens(MixinControllerValue(MixinField(HelixFormElement))))))) {
17
16
  constructor() {
18
17
  super(...arguments);
19
18
  this.aria = new AriaForwardController(this, {
20
- target: () => this.partNamed('control'),
19
+ target: () => this.partNamed('control') ?? this.segmentGroup,
21
20
  });
22
21
  this.autocomplete = '';
22
+ this.announcesInput = true;
23
+ this.disableTimes = '';
23
24
  this.locale = '';
24
25
  this.max = '23:59';
25
26
  this.min = '00:00';
26
27
  this.placeholder = 'HH:mm';
27
28
  this.removeLabel = 'Remove {name}';
29
+ this.seconds = false;
28
30
  this.step = 15;
29
31
  this.timeStyle = 'local';
30
32
  this.triggerLabel = 'Choose a time';
@@ -34,19 +36,19 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
34
36
  return;
35
37
  }
36
38
  const held = this.held;
37
- if (event.key === 'Enter' && isTimeValue(this.draft)) {
39
+ if (event.key === 'Enter' && this.isTime(this.draft)) {
38
40
  event.preventDefault();
39
41
  if (!held.includes(this.draft)) {
40
- this.requestValue([...held, this.draft].sort().join(','));
42
+ this.requestPicked([...held, this.draft].sort().join(','));
41
43
  }
42
44
  this.draft = '';
43
45
  }
44
46
  else if (event.key === 'Backspace' && this.draft === '' && held.length > 0) {
45
- this.requestValue(held.slice(0, -1).join(','));
47
+ this.requestPicked(held.slice(0, -1).join(','));
46
48
  }
47
49
  };
48
50
  this.removeTime = (at) => {
49
- this.requestValue(this.held.filter((one) => one !== at).join(','));
51
+ this.requestPicked(this.held.filter((one) => one !== at).join(','));
50
52
  };
51
53
  this.handleInput = (event) => {
52
54
  event.stopPropagation();
@@ -61,19 +63,30 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
61
63
  .split(',')
62
64
  .map((one) => one.trim())
63
65
  .filter(Boolean);
64
- const whole = held.length > 0 && held.every(isTimeValue);
66
+ const whole = held.length > 0 && held.every((one) => this.isTime(one));
65
67
  this.requestValue(whole ? held.join(',') : typed);
66
68
  this.restore();
67
69
  };
68
70
  this.handlePicked = (event) => {
69
71
  event.stopPropagation();
70
- this.requestValue(event.detail.value);
72
+ if (!this.requestPicked(event.detail.value)) {
73
+ event.preventDefault();
74
+ this.restore();
75
+ return;
76
+ }
71
77
  this.restore();
72
- if (this.mode === undefined) {
78
+ if (this.mode === undefined && this.variant !== 'wheels') {
73
79
  this.requestOpen(false);
74
80
  this.updateComplete.then(() => this.returnFocus());
75
81
  }
76
82
  };
83
+ this.handleWheelEnter = (event) => {
84
+ if (event.key === 'Enter' && this.variant === 'wheels' && this.open) {
85
+ event.preventDefault();
86
+ this.requestOpen(false);
87
+ this.returnFocus();
88
+ }
89
+ };
77
90
  }
78
91
  get held() {
79
92
  return this.value
@@ -82,8 +95,25 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
82
95
  .map((one) => one.trim())
83
96
  .filter(Boolean);
84
97
  }
98
+ get segmentable() {
99
+ return this.mode === undefined;
100
+ }
101
+ get segmentedKind() {
102
+ return 'time';
103
+ }
104
+ get segmentLocale() {
105
+ return this.locale;
106
+ }
107
+ get segmentOptions() {
108
+ return { hourCycle: this.hourCycle, seconds: this.seconds };
109
+ }
110
+ isTime(at) {
111
+ return isClockValue(at, this.seconds);
112
+ }
85
113
  written(at) {
86
- return this.timeStyle === 'iso' || !isTimeValue(at) ? at : writeTime(at, this.locale);
114
+ return this.timeStyle === 'iso' || !this.isTime(at)
115
+ ? at
116
+ : writeClock(at, clockLocale(this.locale, this.hourCycle), this.seconds);
87
117
  }
88
118
  get display() {
89
119
  if (this.mode === 'multiple') {
@@ -105,31 +135,35 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
105
135
  }
106
136
  get picked() {
107
137
  const held = this.held;
108
- return held.length > 0 && held.every(isTimeValue) ? held.join(',') : '';
138
+ return held.length > 0 && held.every((one) => this.isTime(one)) ? held.join(',') : '';
109
139
  }
110
140
  get answers() {
111
141
  return this.mode === undefined ? undefined : this.held;
112
142
  }
113
143
  validate() {
114
144
  const held = this.held;
115
- const floor = valueAsMinutes(this.min) ?? 0;
116
- const ceiling = valueAsMinutes(this.max) ?? 1439;
117
- if (held.length > 0 && !held.every(isTimeValue)) {
145
+ const shape = this.seconds ? 'HH:mm:ss' : 'HH:mm';
146
+ if (held.length > 0 && !held.every((one) => this.isTime(one))) {
118
147
  return (this.badInputMessage ||
119
148
  (this.mode === undefined
120
- ? 'Enter a time as HH:mm.'
121
- : 'Enter times as HH:mm, separated by commas.'));
149
+ ? `Enter a time as ${shape}.`
150
+ : `Enter times as ${shape}, separated by commas.`));
122
151
  }
123
- if (held.some((one) => (valueAsMinutes(one) ?? 0) < floor)) {
152
+ const rules = { disableTimes: this.disableTimes, max: this.max, min: this.min };
153
+ const faults = held.map((one) => timeFault(one, rules));
154
+ if (faults.includes('rangeUnderflow')) {
124
155
  return fillTemplate(this.rangeUnderflowMessage || 'Choose a time at or after {min}.', {
125
- min: writeTime(this.min, this.locale),
156
+ min: writeClock(this.min, clockLocale(this.locale, this.hourCycle), this.seconds),
126
157
  });
127
158
  }
128
- if (held.some((one) => (valueAsMinutes(one) ?? 0) > ceiling)) {
159
+ if (faults.includes('rangeOverflow')) {
129
160
  return fillTemplate(this.rangeOverflowMessage || 'Choose a time at or before {max}.', {
130
- max: writeTime(this.max, this.locale),
161
+ max: writeClock(this.max, clockLocale(this.locale, this.hourCycle), this.seconds),
131
162
  });
132
163
  }
164
+ if (faults.includes('unavailable')) {
165
+ return this.unavailableMessage || 'Choose a time that is available.';
166
+ }
133
167
  if (this.mode === 'range' && held.length > 2) {
134
168
  return this.rangeLengthMessage || 'A range is two times.';
135
169
  }
@@ -162,10 +196,14 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
162
196
  ?invalid=${this.resolvedFeedback !== ''}
163
197
  mode=${this.mode ?? nothing}
164
198
  variant=${this.variant ?? nothing}
199
+ disable-times=${this.disableTimes || nothing}
200
+ manual
165
201
  label=${this.label || 'Time'}
202
+ hour-cycle=${this.hourCycle ?? nothing}
166
203
  locale=${this.locale || nothing}
167
204
  max=${this.max}
168
205
  min=${this.min}
206
+ ?seconds=${this.seconds}
169
207
  step=${this.step}
170
208
  .value=${this.picked}
171
209
  @helix-before-change=${this.handlePicked}
@@ -176,7 +214,7 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
176
214
  renderTag(at) {
177
215
  return html `<${this.tag('tag')}
178
216
  part="time"
179
- exportparts="dismiss: time-dismiss, dismiss-mark: time-dismiss-mark, label: time-label, start: time-start"
217
+ exportparts="cell: time-cell, dismiss: time-dismiss, dismiss-mark: time-dismiss-mark, label: time-label, link: time-link, start: time-start"
180
218
  dismissible
181
219
  dismiss-label=${fillTemplate(this.removeLabel, { name: this.written(at) })}
182
220
  ?disabled=${this.isDisabled}
@@ -198,39 +236,55 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
198
236
  ${this.mode === 'multiple'
199
237
  ? this.renderTokenRow(this.shownTimes.map((at) => this.renderTag(at)), this.restCount)
200
238
  : nothing}
201
- <input
202
- part="control"
203
- id=${this.controlId}
204
- type="text"
205
- .value=${this.display}
206
- name=${this.name || nothing}
207
- placeholder=${this.mode === 'multiple' && this.held.length > 0 ? nothing : this.placeholder || nothing}
208
- autocomplete=${this.autocomplete || nothing}
209
- aria-describedby=${this.describedBy ?? nothing}
210
- aria-invalid=${this.invalidity ?? nothing}
211
- ?disabled=${this.isDisabled}
212
- ?readonly=${this.readOnly}
213
- ?required=${this.required}
214
- @blur=${this.handleBlur}
215
- @focus=${this.handleFocus}
216
- @input=${this.handleInput}
217
- @keydown=${this.handleDraftKey}
218
- />
239
+ ${this.segmentsShown
240
+ ? this.renderSegments()
241
+ : html `<input
242
+ part="control"
243
+ id=${this.controlId}
244
+ type="text"
245
+ .value=${this.display}
246
+ name=${this.name || nothing}
247
+ placeholder=${this.mode === 'multiple' && this.held.length > 0
248
+ ? nothing
249
+ : this.placeholder || nothing}
250
+ autocomplete=${this.autocomplete || nothing}
251
+ aria-describedby=${this.describedBy ?? nothing}
252
+ aria-invalid=${this.invalidity ?? nothing}
253
+ ?disabled=${this.isDisabled}
254
+ ?readonly=${this.readOnly}
255
+ ?required=${this.required}
256
+ @blur=${this.handleBlur}
257
+ @change=${this.handleCommit}
258
+ @focus=${this.handleFocus}
259
+ @input=${this.handleInput}
260
+ @keydown=${this.handleDraftKey}
261
+ @keypress=${this.handleKeypress}
262
+ />`}
219
263
  <button
220
264
  part="trigger"
221
265
  type="button"
222
266
  aria-controls="surface"
267
+ aria-disabled=${this.readOnly ? 'true' : nothing}
223
268
  aria-expanded=${this.open ? 'true' : 'false'}
224
- aria-haspopup="listbox"
269
+ aria-haspopup="dialog"
225
270
  aria-label=${this.triggerLabel}
226
271
  ?disabled=${this.isDisabled}
227
- @click=${() => this.toggleOpen()}
272
+ @click=${this.handleTriggerClick}
228
273
  >
229
274
  ${this.renderTrigger()}
230
275
  </button>
231
276
  </div>
232
277
 
233
- <div part="surface" id="surface" popover="manual" ?hidden=${!this.open}>
278
+ ${''}
279
+ <div
280
+ part="surface"
281
+ id="surface"
282
+ role="dialog"
283
+ aria-label=${this.triggerLabel}
284
+ popover="manual"
285
+ ?hidden=${!this.open}
286
+ @keydown=${this.handleWheelEnter}
287
+ >
234
288
  ${this.renderPicker()}
235
289
  </div>
236
290
  ${this.renderHint()}${this.renderFeedback()}`;
@@ -251,6 +305,12 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinPickerEdi
251
305
  __decorate([
252
306
  property()
253
307
  ], HelixHeadlessTimeInput.prototype, "autocomplete", void 0);
308
+ __decorate([
309
+ property({ attribute: 'disable-times' })
310
+ ], HelixHeadlessTimeInput.prototype, "disableTimes", void 0);
311
+ __decorate([
312
+ property({ attribute: 'hour-cycle' })
313
+ ], HelixHeadlessTimeInput.prototype, "hourCycle", void 0);
254
314
  __decorate([
255
315
  property()
256
316
  ], HelixHeadlessTimeInput.prototype, "locale", void 0);
@@ -278,6 +338,9 @@ __decorate([
278
338
  __decorate([
279
339
  property({ attribute: 'remove-label' })
280
340
  ], HelixHeadlessTimeInput.prototype, "removeLabel", void 0);
341
+ __decorate([
342
+ property({ type: Boolean })
343
+ ], HelixHeadlessTimeInput.prototype, "seconds", void 0);
281
344
  __decorate([
282
345
  property({ type: Number })
283
346
  ], HelixHeadlessTimeInput.prototype, "step", void 0);
@@ -287,6 +350,9 @@ __decorate([
287
350
  __decorate([
288
351
  property({ attribute: 'trigger-label' })
289
352
  ], HelixHeadlessTimeInput.prototype, "triggerLabel", void 0);
353
+ __decorate([
354
+ property({ attribute: 'unavailable-message' })
355
+ ], HelixHeadlessTimeInput.prototype, "unavailableMessage", void 0);
290
356
  __decorate([
291
357
  state()
292
358
  ], HelixHeadlessTimeInput.prototype, "draft", void 0);
@@ -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
  *
@@ -84,7 +89,7 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
84
89
  */
85
90
  badInputMessage?: string;
86
91
  /**
87
- * Times that cannot be chosen, comma separated, as `HH:mm`.
92
+ * Times that cannot be chosen, as `HH:mm`, separated by commas or spaces.
88
93
  *
89
94
  * The counterpart to Date Picker's `disable-dates`, and it exists for the same
90
95
  * shape of problem: `min` and `max` take away a span, and what a booking
@@ -96,6 +101,19 @@ 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;
113
+ /**
114
+ * What the wheel of hours is called, read by screen readers.
115
+ */
116
+ hourLabel: string;
99
117
  /**
100
118
  * Whether the current selection fails validation.
101
119
  *
@@ -108,6 +126,8 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
108
126
  invalid: boolean;
109
127
  /**
110
128
  * Accessible name for the list, which has no visible one of its own.
129
+ *
130
+ * An `aria-label` or `aria-labelledby` on the host names the list instead.
111
131
  */
112
132
  label: string;
113
133
  /**
@@ -116,14 +136,31 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
116
136
  * Absent uses the runtime's own.
117
137
  */
118
138
  locale: string;
139
+ /**
140
+ * Stops the arrow keys in the list from choosing each time they move to.
141
+ * Enter, Space or a click chooses.
142
+ *
143
+ * Time Input sets it, so a reader moves through the list before the panel
144
+ * closes on a time.
145
+ */
146
+ manual: boolean;
119
147
  /**
120
148
  * Latest time offered, as `HH:mm`.
121
149
  */
122
150
  max: string;
151
+ /**
152
+ * What the wheel of the half of the day is called, read by screen readers.
153
+ * Its two options are written as the locale writes them, such as AM and PM.
154
+ */
155
+ meridiemLabel: string;
123
156
  /**
124
157
  * Earliest time offered, as `HH:mm`.
125
158
  */
126
159
  min: string;
160
+ /**
161
+ * What the wheel of minutes is called, read by screen readers.
162
+ */
163
+ minuteLabel: string;
127
164
  /**
128
165
  * How many times can be held at once.
129
166
  *
@@ -145,33 +182,29 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
145
182
  */
146
183
  mode?: 'multiple' | 'range';
147
184
  /**
148
- * Blocks changes to the time. The value is still submitted with the form.
149
- *
150
- * **Enforced by refusing every request in one place**, which is the seam this
151
- * component already has: `requestValue` is what every path here comes through,
152
- * and gating it once is what stops the next call site from being written
153
- * without the check.
154
- *
155
- * Not `disabled`, which is the confusion worth naming: a disabled control
156
- * submits nothing and leaves the tab order, and a read-only one submits its
157
- * value and stays reachable, which is what a form showing a value somebody
158
- * else set needs.
185
+ * The validation message for a time after `max`. `{max}` is replaced with
186
+ * `max`, written in `locale`.
159
187
  */
160
- readOnly: boolean;
188
+ rangeOverflowMessage?: string;
161
189
  /**
162
- * Stops the form from submitting while no time is chosen.
190
+ * The validation message for a time before `min`. `{min}` is replaced with
191
+ * `min`, written in `locale`.
163
192
  */
164
- required: boolean;
193
+ rangeUnderflowMessage?: string;
165
194
  /**
166
- * Every time on offer, as minutes since midnight.
195
+ * Every time on offer, as seconds since midnight.
167
196
  *
168
197
  * Built from `min` upward rather than from midnight, so a list that starts at
169
198
  * `09:00` steps from nine rather than offering `09:15` because that is where
170
199
  * the quarter hours from midnight happen to land. A step that does not divide
171
200
  * the hour is a real thing to want, twenty minutes being the obvious one, and
172
- * this is the reading that makes it behave.
201
+ * this is the reading that makes it behave. See `offeredTimes`.
173
202
  */
174
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;
175
208
  /**
176
209
  * Whether a time is barred by name.
177
210
  *
@@ -184,6 +217,19 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
184
217
  * outside the bounds is absent rather than present and refused.
185
218
  */
186
219
  private barred;
220
+ /** The same question of seconds since midnight, matching `09:30` and `09:30:00` alike. */
221
+ private barredAt;
222
+ /**
223
+ * The offered time nearest to one the wheels built, which keeps them inside
224
+ * `min`, `max` and `step`.
225
+ *
226
+ * A wheel sets one part of a time and keeps the others, so moving the hour
227
+ * from 16:45 to 17 built 17:45 against a `max` of 17:00, and moving the half
228
+ * of the day built 05:45 against a `min` of 09:00. Measured before this,
229
+ * both reported valid and were submitted. The nearest earlier time wins a
230
+ * tie, so a step past `max` lands on `max`'s own row.
231
+ */
232
+ private nearest;
187
233
  /**
188
234
  * Whether every offered time in an hour is barred.
189
235
  *
@@ -217,7 +263,7 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
217
263
  private readonly handleChange;
218
264
  /** Whether a time falls inside a range, which is what gets banded. */
219
265
  private between;
220
- /** The three readings a wheel shows, from the value or from `min`. */
266
+ /** The readings the wheels show, from the value or from `min`. */
221
267
  private get parts();
222
268
  /** Puts a changed column back together into a whole time. */
223
269
  private readonly moveColumn;
@@ -225,6 +271,8 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
225
271
  private get hours();
226
272
  /** Every minute offered within the hour currently shown. */
227
273
  private get minutes();
274
+ /** Every second offered within the minute currently shown. */
275
+ private get secondsShown();
228
276
  /**
229
277
  * Scrolls each wheel to its selected value, and the list to its selected
230
278
  * time.
@@ -253,19 +301,69 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
253
301
  */
254
302
  reveal(): void;
255
303
  /**
256
- * How far apart the offered times are, in minutes.
304
+ * Blocks changes to the time. The value is still submitted with the form.
305
+ *
306
+ * **Enforced by refusing every request in one place**, which is the seam this
307
+ * component already has: `requestValue` is what every path here comes through,
308
+ * and gating it once is what stops the next call site from being written
309
+ * without the check.
310
+ *
311
+ * Not `disabled`, which is the confusion worth naming: a disabled control
312
+ * submits nothing and leaves the tab order, and a read-only one submits its
313
+ * value and stays reachable, which is what a form showing a value somebody
314
+ * else set needs.
315
+ */
316
+ readOnly: boolean;
317
+ /** Refuses every change while read-only. See `readOnly`. */
318
+ requestValue(next: string): boolean;
319
+ /**
320
+ * Stops the form from submitting while no time is chosen.
321
+ */
322
+ required: boolean;
323
+ /**
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`.
257
340
  *
258
341
  * Fifteen, which is four rows an hour and ninety-six in a day: enough that a
259
342
  * reader scrolls rather than hunts, and few enough that the list is a list.
260
343
  * Anything under five is a thousand rows and wants a field instead.
261
344
  */
262
345
  step: number;
263
- /** Refuses every change while read-only. See `readOnly`. */
264
- requestValue(next: string): boolean;
346
+ /**
347
+ * The validation message for a time that `step` skips.
348
+ */
349
+ stepMismatchMessage?: string;
350
+ /**
351
+ * The validation message for a time that `disable-times` bars.
352
+ */
353
+ unavailableMessage?: string;
265
354
  /**
266
355
  * The validation message for a required time picker with no time chosen.
267
356
  */
268
357
  valueMissingMessage?: string;
358
+ /**
359
+ * What is wrong with a time the picker can read, as a validity flag and a
360
+ * message, or nothing.
361
+ *
362
+ * Measured before this: a time past `max` or one `disable-times` bars,
363
+ * whether set by a script or built on the wheels, reported valid and was
364
+ * submitted, where a native time input reports the bound it is past.
365
+ */
366
+ private fault;
269
367
  /**
270
368
  * Shows the times as one `list`, or as `wheels` with a column for each part
271
369
  * of the time.
@@ -346,9 +444,31 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
346
444
  * and after that only whatever opens a panel calls `reveal`.
347
445
  */
348
446
  private listRevealed;
447
+ /**
448
+ * The list's name: the host's `aria-labelledby` read out, then its
449
+ * `aria-label`, then `label`.
450
+ *
451
+ * Read out as words, because the list is inside two shadow roots and an id on
452
+ * the page reaches neither. Measured before this: `<helix-time-picker
453
+ * aria-label="Slot">` was a listbox named "Time".
454
+ */
455
+ private get listName();
456
+ /**
457
+ * Hears the host's `aria-label` and `aria-labelledby` change, which no
458
+ * property reports. Made on connection, there being no `MutationObserver` on
459
+ * a server.
460
+ */
461
+ private naming;
462
+ connectedCallback(): void;
463
+ disconnectedCallback(): void;
349
464
  protected willUpdate(changed: PropertyValues): void;
350
465
  protected updated(changed: PropertyValues): void;
351
- /** Moves focus to the list, which is the only control in the picker. */
466
+ /**
467
+ * Moves focus to the list, or to the first wheel.
468
+ *
469
+ * The wheels render no list, so focus went nowhere on them and a wrapping
470
+ * component could not move focus into the picker.
471
+ */
352
472
  focus(options?: FocusOptions): void;
353
473
  /**
354
474
  * One wheel, which is a listbox like the whole list is.
@@ -363,7 +483,16 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
363
483
  * barred only when every minute in it is, since one free minute is a reason to
364
484
  * open the wheel rather than to close it.
365
485
  */
366
- 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;
367
496
  private renderSpinner;
368
497
  /**
369
498
  * The flat list of times, for the variant that is not wheels, behind a seam the styled tier can move.