@fusion.dev/helix-headless 0.142.0 → 0.143.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 (217) hide show
  1. package/custom-elements.json +16710 -707
  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.js +16 -5
  11. package/dist/avatar/group/avatar-group.d.ts +24 -3
  12. package/dist/avatar/group/avatar-group.js +34 -2
  13. package/dist/avatar/root/avatar-root.d.ts +3 -1
  14. package/dist/avatar/root/avatar-root.js +8 -1
  15. package/dist/badge/root/badge-root.d.ts +8 -0
  16. package/dist/bar-chart/root/bar-chart-root.d.ts +19 -3
  17. package/dist/bar-chart/root/bar-chart-root.js +43 -13
  18. package/dist/blockquote/root/blockquote-root.d.ts +12 -7
  19. package/dist/blockquote/root/blockquote-root.js +6 -4
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
  22. package/dist/button/root/button-root.d.ts +37 -0
  23. package/dist/button/root/button-root.js +44 -0
  24. package/dist/callout/root/callout-root.d.ts +14 -5
  25. package/dist/callout/root/callout-root.js +11 -3
  26. package/dist/canvas/root/canvas-root.d.ts +1 -0
  27. package/dist/canvas/root/canvas-root.js +10 -1
  28. package/dist/carousel/root/carousel-root.d.ts +47 -5
  29. package/dist/carousel/root/carousel-root.js +53 -21
  30. package/dist/chat/composer/chat-composer.d.ts +13 -11
  31. package/dist/chat/composer/chat-composer.js +6 -12
  32. package/dist/chat/message/chat-message.js +8 -1
  33. package/dist/chat/root/chat-root.d.ts +1 -0
  34. package/dist/chat/root/chat-root.js +2 -1
  35. package/dist/checkbox/root/checkbox-root.d.ts +7 -0
  36. package/dist/checkbox/root/checkbox-root.js +7 -3
  37. package/dist/checkbox-group/root/checkbox-group-root.d.ts +65 -32
  38. package/dist/checkbox-group/root/checkbox-group-root.js +85 -37
  39. package/dist/code/root/code-root.d.ts +1 -1
  40. package/dist/code-block/root/code-block-root.d.ts +19 -0
  41. package/dist/code-block/root/code-block-root.js +21 -1
  42. package/dist/color-input/root/color-input-root.d.ts +26 -1
  43. package/dist/color-input/root/color-input-root.js +32 -3
  44. package/dist/color-picker/root/color-picker-root.d.ts +37 -7
  45. package/dist/color-picker/root/color-picker-root.js +83 -6
  46. package/dist/combobox/root/combobox-root.d.ts +90 -2
  47. package/dist/combobox/root/combobox-root.js +160 -19
  48. package/dist/command/root/command-root.d.ts +17 -6
  49. package/dist/command/root/command-root.js +12 -1
  50. package/dist/copy-button/root/copy-button-root.d.ts +21 -6
  51. package/dist/copy-button/root/copy-button-root.js +11 -1
  52. package/dist/data-table/root/data-table-root.d.ts +164 -10
  53. package/dist/data-table/root/data-table-root.js +488 -57
  54. package/dist/date-input/root/date-input-root.d.ts +53 -8
  55. package/dist/date-input/root/date-input-root.js +70 -18
  56. package/dist/date-picker/root/date-picker-root.d.ts +84 -17
  57. package/dist/date-picker/root/date-picker-root.js +125 -20
  58. package/dist/dialog/root/dialog-root.d.ts +38 -10
  59. package/dist/dialog/root/dialog-root.js +55 -2
  60. package/dist/donut-chart/root/donut-chart-root.d.ts +39 -15
  61. package/dist/donut-chart/root/donut-chart-root.js +30 -10
  62. package/dist/drawer/root/drawer-root.d.ts +32 -7
  63. package/dist/drawer/root/drawer-root.js +50 -5
  64. package/dist/drilldown/item/drilldown-item.d.ts +16 -13
  65. package/dist/drilldown/item/drilldown-item.js +6 -2
  66. package/dist/drilldown/root/drilldown-root.d.ts +21 -5
  67. package/dist/drilldown/root/drilldown-root.js +26 -10
  68. package/dist/element-events.generated.js +35 -9
  69. package/dist/file-input/root/file-input-root.d.ts +18 -1
  70. package/dist/file-input/root/file-input-root.js +34 -8
  71. package/dist/filter-input/menu/filter-menu.d.ts +9 -0
  72. package/dist/filter-input/menu/filter-menu.js +8 -0
  73. package/dist/filter-input/root/filter-input-root.d.ts +5 -2
  74. package/dist/filter-input/root/filter-input-root.js +22 -7
  75. package/dist/format-date/root/format-date-root.d.ts +11 -3
  76. package/dist/format-date/root/format-date-root.js +26 -5
  77. package/dist/graph/root/graph-root.d.ts +24 -3
  78. package/dist/graph/root/graph-root.js +66 -12
  79. package/dist/heatmap/root/buckets.d.ts +2 -1
  80. package/dist/heatmap/root/buckets.js +5 -1
  81. package/dist/heatmap/root/heatmap-root.d.ts +27 -6
  82. package/dist/heatmap/root/heatmap-root.js +23 -6
  83. package/dist/icon/root/icon-root.d.ts +24 -3
  84. package/dist/icon/root/icon-root.js +34 -1
  85. package/dist/icon-button/root/icon-button-root.d.ts +1 -1
  86. package/dist/image/root/image-root.d.ts +9 -2
  87. package/dist/image/root/image-root.js +8 -2
  88. package/dist/input/root/input-root.d.ts +51 -9
  89. package/dist/input/root/input-root.js +46 -5
  90. package/dist/kbd/root/kbd-root.d.ts +12 -4
  91. package/dist/kbd/root/kbd-root.js +10 -11
  92. package/dist/legend/root/legend-root.d.ts +7 -0
  93. package/dist/legend/root/legend-root.js +7 -2
  94. package/dist/lightbox/item/lightbox-item.d.ts +2 -1
  95. package/dist/lightbox/root/lightbox-root.d.ts +16 -5
  96. package/dist/lightbox/root/lightbox-root.js +24 -3
  97. package/dist/line-chart/root/line-chart-root.d.ts +19 -2
  98. package/dist/line-chart/root/line-chart-root.js +40 -13
  99. package/dist/list/item/list-item.d.ts +11 -5
  100. package/dist/list/item/list-item.js +5 -6
  101. package/dist/listbox/root/listbox-root.d.ts +111 -2
  102. package/dist/listbox/root/listbox-root.js +144 -16
  103. package/dist/map/root/map-root.d.ts +19 -4
  104. package/dist/map/root/map-root.js +36 -7
  105. package/dist/megamenu/root/megamenu-root.d.ts +10 -1
  106. package/dist/megamenu/root/megamenu-root.js +10 -1
  107. package/dist/menu/item/menu-item.d.ts +41 -12
  108. package/dist/menu/item/menu-item.js +46 -3
  109. package/dist/menu/root/menu-root.d.ts +32 -2
  110. package/dist/menu/root/menu-root.js +48 -8
  111. package/dist/meter/root/meter-root.d.ts +6 -0
  112. package/dist/meter/root/meter-root.js +18 -2
  113. package/dist/navigation/root/navigation-root.d.ts +10 -2
  114. package/dist/navigation/root/navigation-root.js +13 -2
  115. package/dist/notifications/group/notification-group.d.ts +1 -0
  116. package/dist/notifications/notification/notification.d.ts +12 -0
  117. package/dist/notifications/notification/notification.js +31 -2
  118. package/dist/notifications/root/notifications-root.d.ts +7 -0
  119. package/dist/notifications/root/notifications-root.js +17 -2
  120. package/dist/number-input/root/number-input-root.d.ts +62 -7
  121. package/dist/number-input/root/number-input-root.js +68 -16
  122. package/dist/object-inspector/root/object-inspector-root.d.ts +48 -5
  123. package/dist/object-inspector/root/object-inspector-root.js +91 -11
  124. package/dist/option/root/option-root.d.ts +4 -1
  125. package/dist/option/root/option-root.js +1 -0
  126. package/dist/outline/root/outline-root.d.ts +13 -2
  127. package/dist/outline/root/outline-root.js +4 -2
  128. package/dist/pagination/root/pagination-root.d.ts +19 -1
  129. package/dist/pagination/root/pagination-root.js +49 -9
  130. package/dist/pagination/size/pagination-size.d.ts +13 -3
  131. package/dist/pagination/size/pagination-size.js +7 -0
  132. package/dist/pin-input/root/pin-input-root.d.ts +16 -0
  133. package/dist/pin-input/root/pin-input-root.js +19 -5
  134. package/dist/popover/root/popover-root.d.ts +19 -2
  135. package/dist/popover/root/popover-root.js +22 -1
  136. package/dist/progress/root/progress-root.d.ts +16 -1
  137. package/dist/progress/root/progress-root.js +31 -7
  138. package/dist/qr-code/root/qr-code-root.d.ts +19 -0
  139. package/dist/qr-code/root/qr-code-root.js +29 -1
  140. package/dist/radio/group/radio-group.d.ts +41 -0
  141. package/dist/radio/group/radio-group.js +50 -14
  142. package/dist/radio/root/radio-root.d.ts +8 -5
  143. package/dist/radio/root/radio-root.js +1 -2
  144. package/dist/rating/root/rating-root.d.ts +24 -1
  145. package/dist/rating/root/rating-root.js +24 -7
  146. package/dist/scatter-chart/root/scatter-chart-root.js +15 -7
  147. package/dist/select/root/select-root.d.ts +69 -3
  148. package/dist/select/root/select-root.js +92 -8
  149. package/dist/skeleton/root/skeleton-root.d.ts +14 -3
  150. package/dist/skeleton/root/skeleton-root.js +17 -3
  151. package/dist/skip-link/root/skip-link-root.d.ts +10 -0
  152. package/dist/skip-link/root/skip-link-root.js +15 -1
  153. package/dist/slider/root/slider-root.d.ts +20 -2
  154. package/dist/slider/root/slider-root.js +41 -3
  155. package/dist/sparkline/root/sparkline-root.d.ts +9 -10
  156. package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
  157. package/dist/speed-dial/item/speed-dial-item.js +7 -2
  158. package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
  159. package/dist/speed-dial/root/speed-dial-root.js +19 -5
  160. package/dist/splitter/root/splitter-root.d.ts +28 -6
  161. package/dist/splitter/root/splitter-root.js +35 -1
  162. package/dist/stat/root/stat-root.d.ts +7 -1
  163. package/dist/stat/root/stat-root.js +14 -1
  164. package/dist/steps/root/steps-root.js +1 -1
  165. package/dist/switch/root/switch-root.d.ts +2 -0
  166. package/dist/switch/root/switch-root.js +1 -0
  167. package/dist/table/cell/table-cell.d.ts +24 -4
  168. package/dist/table/cell/table-cell.js +21 -1
  169. package/dist/table/column/table-column.d.ts +32 -6
  170. package/dist/table/column/table-column.js +36 -6
  171. package/dist/table/root/table-root.d.ts +94 -3
  172. package/dist/table/root/table-root.js +128 -5
  173. package/dist/table/row/table-row.d.ts +7 -0
  174. package/dist/table/row/table-row.js +9 -1
  175. package/dist/tabs/root/tabs-root.d.ts +6 -1
  176. package/dist/tabs/root/tabs-root.js +6 -2
  177. package/dist/tag/root/tag-root.d.ts +23 -1
  178. package/dist/tag/root/tag-root.js +16 -2
  179. package/dist/textarea/root/textarea-root.d.ts +4 -0
  180. package/dist/textarea/root/textarea-root.js +1 -1
  181. package/dist/time-input/root/time-input-root.d.ts +28 -2
  182. package/dist/time-input/root/time-input-root.js +46 -10
  183. package/dist/time-picker/root/time-picker-root.d.ts +101 -18
  184. package/dist/time-picker/root/time-picker-root.js +115 -16
  185. package/dist/toast/root/toast-root.d.ts +64 -1
  186. package/dist/toast/root/toast-root.js +147 -2
  187. package/dist/toggle/group/toggle-group.d.ts +38 -1
  188. package/dist/toggle/group/toggle-group.js +34 -8
  189. package/dist/toggle/root/toggle-root.d.ts +14 -10
  190. package/dist/toggle/root/toggle-root.js +3 -3
  191. package/dist/toolbar/root/toolbar-root.d.ts +55 -15
  192. package/dist/toolbar/root/toolbar-root.js +99 -16
  193. package/dist/tooltip/root/tooltip-root.d.ts +37 -4
  194. package/dist/tooltip/root/tooltip-root.js +48 -0
  195. package/dist/tour/root/tour-root.d.ts +34 -5
  196. package/dist/tour/root/tour-root.js +51 -14
  197. package/dist/tour/stop/tour-stop.d.ts +18 -1
  198. package/dist/tour/stop/tour-stop.js +25 -5
  199. package/dist/tree/item/tree-item.d.ts +21 -5
  200. package/dist/tree/item/tree-item.js +14 -4
  201. package/dist/tree/root/tree-root.d.ts +29 -5
  202. package/dist/tree/root/tree-root.js +64 -8
  203. package/dist/trend/root/trend-root.d.ts +23 -1
  204. package/dist/trend/root/trend-root.js +28 -7
  205. package/dist/video/root/keys.d.ts +5 -0
  206. package/dist/video/root/keys.js +13 -1
  207. package/dist/video/root/video-root.d.ts +19 -0
  208. package/dist/video/root/video-root.js +48 -4
  209. package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
  210. package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
  211. package/dist/video-playlist/root/video-playlist-root.js +6 -3
  212. package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
  213. package/dist/virtual-list/root/virtual-list-root.js +103 -21
  214. package/lint.json +1 -1
  215. package/package.json +5 -5
  216. package/types/jsx.d.ts +4348 -965
  217. package/types/vue.d.ts +972 -232
@@ -13,7 +13,13 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
13
13
  *
14
14
  * You can type a date as well as pick one. The native `<input type="date">`
15
15
  * gives a picker and locale formatting but allows almost no styling, so the
16
- * field is a text field.
16
+ * field is a text field. Typing sends `input` on each keystroke and `change`
17
+ * when you leave the field, as a text field does. A date picked from the
18
+ * calendar sends both.
19
+ *
20
+ * The trigger opens the calendar with focus on the selected day, and Escape
21
+ * closes it and returns focus to the field. Focusing the field opens the
22
+ * calendar too, and Tab out of the field closes it again.
17
23
  *
18
24
  * @since 0.1.0
19
25
  * @status stable
@@ -23,6 +29,8 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
23
29
  *
24
30
  * @slot feedback - The error message under the field.
25
31
  * @slot hint - The help text under the field.
32
+ * @slot next-icon - The icon on the calendar's next month control.
33
+ * @slot previous-icon - The icon on the calendar's previous month control.
26
34
  * @slot trigger - The icon on the button that opens the calendar.
27
35
  *
28
36
  * @event {Event} change - Fired after the value changes.
@@ -30,7 +38,7 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
30
38
  * @event {HelixBeforeCloseEvent} helix-before-close - Fired before the calendar closes. Cancelable: call `preventDefault()` to keep it open.
31
39
  * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the calendar opens. Cancelable: call `preventDefault()` to keep it closed.
32
40
  * @event {Event} input - Fired after the value changes.
33
- * @event {Event} toggle - Fired when the calendar opens or closes, with `newState` and `oldState`.
41
+ * @event {ToggleEvent} toggle - Fired when the calendar opens or closes, with `newState` and `oldState`.
34
42
  *
35
43
  * @csspart control - The text input.
36
44
  * @csspart date - One held date, as a tag, in `multiple`.
@@ -82,6 +90,12 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
82
90
  * postal code can never be filled in for a reader.
83
91
  */
84
92
  autocomplete: string;
93
+ /**
94
+ * The name of the calendar's grid of days, read by screen readers.
95
+ */
96
+ calendarLabel: string;
97
+ /** Typed, so a keystroke is announced as `input` alone. See `announcesInput`. */
98
+ protected readonly announcesInput = true;
85
99
  /**
86
100
  * How a date is written in the field: `short` through `full`, or ISO.
87
101
  *
@@ -108,19 +122,23 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
108
122
  */
109
123
  dateStyle: 'full' | 'iso' | 'long' | 'medium' | 'short';
110
124
  /**
111
- * Dates that cannot be chosen, as a comma-separated `YYYY-MM-DD` list.
125
+ * Dates that cannot be chosen, as `YYYY-MM-DD`, separated by commas or
126
+ * spaces.
112
127
  */
113
128
  disableDates: string;
114
129
  /**
115
130
  * Days of the week that cannot be chosen, from `0` for Sunday to `6` for
116
- * Saturday.
131
+ * Saturday, separated by commas or spaces.
117
132
  */
118
133
  disableDays: string;
119
134
  /**
120
135
  * The day in the calendar's first column, from `0` for Sunday to `6` for
121
136
  * Saturday.
137
+ *
138
+ * Absent follows `locale`, where the engine knows the week of that language,
139
+ * and is Sunday otherwise.
122
140
  */
123
- firstDayOfWeek: number;
141
+ firstDayOfWeek?: number;
124
142
  /**
125
143
  * The language tag for the names of months and days in the calendar.
126
144
  */
@@ -182,10 +200,18 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
182
200
  */
183
201
  protected placed(room: number | undefined): void;
184
202
  protected willUpdate(changed: PropertyValues): void;
203
+ /**
204
+ * The name of the calendar's control that moves to the next month.
205
+ */
206
+ nextLabel: string;
185
207
  /**
186
208
  * The text the field shows before a date is entered.
187
209
  */
188
210
  placeholder: string;
211
+ /**
212
+ * The name of the calendar's control that moves to the previous month.
213
+ */
214
+ previousLabel: string;
189
215
  /**
190
216
  * The message shown when a range holds more than two dates.
191
217
  *
@@ -221,6 +247,14 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
221
247
  * platform's base.
222
248
  */
223
249
  step: number;
250
+ /**
251
+ * The message shown when a date is not on `step`.
252
+ */
253
+ stepMismatchMessage?: string;
254
+ /**
255
+ * The name of the button that opens the calendar, read by screen readers.
256
+ */
257
+ triggerLabel: string;
224
258
  /**
225
259
  * What the calendar should show, which is only ever a whole date.
226
260
  *
@@ -259,10 +293,9 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
259
293
  /** What is wrong with the dates, which the text input cannot say. */
260
294
  protected validate(): string;
261
295
  /**
262
- * The name of the button that opens the calendar, read by screen readers.
296
+ * The message shown when `disable-dates` or `disable-days` bars a date.
263
297
  */
264
- triggerLabel: string;
265
- protected updated(changed: PropertyValues): void;
298
+ unavailableMessage?: string;
266
299
  /**
267
300
  * The calendar the field opens, behind a seam the styled tier can move.
268
301
  *
@@ -273,6 +306,18 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
273
306
  * one from the same template.
274
307
  */
275
308
  protected renderPicker(): TemplateResult;
309
+ /**
310
+ * Passes an icon slotted on the field to the calendar's slot of that name.
311
+ *
312
+ * **Forwarded only while the field holds one.** A forwarded slot is assigned
313
+ * to the calendar's slot even when it is empty, and an assigned slot does
314
+ * not show its fallback, so the calendar's own caret went missing whenever
315
+ * the field had no icon. With no `slot` attribute the forwarding slot is
316
+ * assigned nowhere, as the calendar has no default slot, and it still hears
317
+ * an icon arrive or leave.
318
+ */
319
+ private renderIconSlot;
320
+ private readonly handleIconChange;
276
321
  /**
277
322
  * One chosen date, as a tag, behind a seam the styled tier can move.
278
323
  *
@@ -4,7 +4,7 @@ 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, valueAsDate as asDate, customElement, fillTemplate, dateAsValue as fromDate, HelixFormElement, isDateValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinTokens, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, valueAsDate as asDate, customElement, fillTemplate, dateAsValue as fromDate, HelixFormElement, isDateValue, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerEditing, MixinPickerField, MixinTokens, writtenList, } from '@fusion.dev/helix-core';
8
8
  import { calendarBlank } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -24,19 +24,23 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
24
24
  target: () => this.partNamed('control'),
25
25
  });
26
26
  this.autocomplete = '';
27
+ this.calendarLabel = 'Date Picker';
28
+ this.announcesInput = true;
27
29
  this.dateStyle = 'long';
28
30
  this.disableDates = '';
29
31
  this.disableDays = '';
30
- this.firstDayOfWeek = 0;
31
32
  this.locale = '';
32
33
  this.max = '';
33
34
  this.min = '';
34
35
  this.months = 1;
35
36
  this.fitted = undefined;
36
37
  this.wide = undefined;
38
+ this.nextLabel = 'Next month';
37
39
  this.placeholder = 'YYYY-MM-DD';
40
+ this.previousLabel = 'Previous month';
38
41
  this.removeLabel = 'Remove {name}';
39
42
  this.step = 1;
43
+ this.triggerLabel = 'Choose a date';
40
44
  this.draft = '';
41
45
  this.handleInput = (event) => {
42
46
  event.stopPropagation();
@@ -59,30 +63,36 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
59
63
  if (event.key === 'Enter' && isDateValue(this.draft)) {
60
64
  event.preventDefault();
61
65
  if (!held.includes(this.draft)) {
62
- this.requestValue([...held, this.draft].join(','));
66
+ this.requestPicked([...held, this.draft].join(','));
63
67
  }
64
68
  this.draft = '';
65
69
  }
66
70
  else if (event.key === 'Backspace' && this.draft === '' && held.length > 0) {
67
- this.requestValue(held.slice(0, -1).join(','));
71
+ this.requestPicked(held.slice(0, -1).join(','));
68
72
  }
69
73
  };
70
74
  this.removeDate = (date) => {
71
- this.requestValue(dates(this.value)
75
+ this.requestPicked(dates(this.value)
72
76
  .filter((one) => one !== date)
73
77
  .join(','));
74
78
  };
75
79
  this.handleCalendarChange = (event) => {
76
80
  event.stopPropagation();
77
81
  const { value } = event.detail;
78
- this.requestValue(value);
82
+ if (!this.requestPicked(value)) {
83
+ event.preventDefault();
84
+ this.restore();
85
+ return;
86
+ }
79
87
  this.restore();
80
88
  if (this.mode === undefined) {
81
89
  this.requestOpen(false);
82
90
  this.updateComplete.then(() => this.returnFocus());
83
91
  }
84
92
  };
85
- this.triggerLabel = 'Choose a date';
93
+ this.handleIconChange = () => {
94
+ this.requestUpdate();
95
+ };
86
96
  }
87
97
  placed(room) {
88
98
  const all = Math.max(1, Math.floor(this.months) || 1);
@@ -160,17 +170,27 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
160
170
  max: this.written(this.max),
161
171
  });
162
172
  }
173
+ const days = writtenList(this.disableDays);
174
+ const listed = writtenList(this.disableDates);
175
+ if (held.some((one) => listed.includes(one) || days.includes(String(asDate(one)?.getUTCDay() ?? '')))) {
176
+ return this.unavailableMessage || 'Choose a date that is available.';
177
+ }
178
+ const step = Math.max(1, Math.floor(this.step) || 1);
179
+ if (step > 1) {
180
+ const base = asDate(this.min)?.getTime() ?? 0;
181
+ const off = held.some((one) => {
182
+ const at = asDate(one)?.getTime();
183
+ return at !== undefined && Math.round((at - base) / 86_400_000) % step !== 0;
184
+ });
185
+ if (off) {
186
+ return this.stepMismatchMessage || 'Choose one of the dates the calendar offers.';
187
+ }
188
+ }
163
189
  if (this.mode === 'range' && held.length > 2) {
164
190
  return this.rangeLengthMessage || 'A range is two dates.';
165
191
  }
166
192
  return '';
167
193
  }
168
- updated(changed) {
169
- super.updated(changed);
170
- if (this.open && changed.has('open')) {
171
- this.partNamed('picker')?.focus();
172
- }
173
- }
174
194
  renderPicker() {
175
195
  return html `<${this.tag('date-picker')}
176
196
  part="picker"
@@ -188,15 +208,29 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
188
208
  .value=${this.picked}
189
209
  disable-dates=${this.disableDates || nothing}
190
210
  disable-days=${this.disableDays || nothing}
191
- first-day-of-week=${this.firstDayOfWeek}
211
+ first-day-of-week=${this.firstDayOfWeek ?? nothing}
212
+ label=${this.calendarLabel}
192
213
  locale=${this.locale || nothing}
193
214
  max=${this.max || nothing}
194
215
  min=${this.min || nothing}
216
+ next-label=${this.nextLabel}
217
+ previous-label=${this.previousLabel}
195
218
  step=${this.step}
196
219
  @helix-before-change=${this.handleCalendarChange}
197
220
  @change=${this.stopInner}
198
221
  @input=${this.stopInner}
199
- ></${this.tag('date-picker')}>`;
222
+ >
223
+ ${this.renderIconSlot('previous-icon')}
224
+ ${this.renderIconSlot('next-icon')}
225
+ </${this.tag('date-picker')}>`;
226
+ }
227
+ renderIconSlot(name) {
228
+ const given = this.querySelector?.(`:scope > [slot="${name}"]`) != null;
229
+ return html `<slot
230
+ name=${name}
231
+ slot=${given ? name : nothing}
232
+ @slotchange=${this.handleIconChange}
233
+ ></slot>`;
200
234
  }
201
235
  renderTag(date) {
202
236
  return html `<${this.tag('tag')}
@@ -240,19 +274,22 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
240
274
  ?readonly=${this.readOnly}
241
275
  ?required=${this.required}
242
276
  @blur=${this.handleBlur}
277
+ @change=${this.handleCommit}
243
278
  @focus=${this.handleFocus}
244
279
  @input=${this.handleInput}
245
280
  @keydown=${this.handleDraftKey}
281
+ @keypress=${this.handleKeypress}
246
282
  />
247
283
  <button
248
284
  part="trigger"
249
285
  type="button"
250
286
  aria-controls="surface"
287
+ aria-disabled=${this.readOnly ? 'true' : nothing}
251
288
  aria-expanded=${this.open ? 'true' : 'false'}
252
289
  aria-haspopup="dialog"
253
290
  aria-label=${this.triggerLabel}
254
291
  ?disabled=${this.isDisabled}
255
- @click=${() => this.toggleOpen()}
292
+ @click=${this.handleTriggerClick}
256
293
  >
257
294
  ${this.renderTrigger()}
258
295
  </button>
@@ -287,6 +324,9 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
287
324
  __decorate([
288
325
  property()
289
326
  ], HelixHeadlessDateInput.prototype, "autocomplete", void 0);
327
+ __decorate([
328
+ property({ attribute: 'calendar-label' })
329
+ ], HelixHeadlessDateInput.prototype, "calendarLabel", void 0);
290
330
  __decorate([
291
331
  property({ attribute: 'date-style' })
292
332
  ], HelixHeadlessDateInput.prototype, "dateStyle", void 0);
@@ -317,9 +357,15 @@ __decorate([
317
357
  __decorate([
318
358
  state()
319
359
  ], HelixHeadlessDateInput.prototype, "fitted", void 0);
360
+ __decorate([
361
+ property({ attribute: 'next-label' })
362
+ ], HelixHeadlessDateInput.prototype, "nextLabel", void 0);
320
363
  __decorate([
321
364
  property()
322
365
  ], HelixHeadlessDateInput.prototype, "placeholder", void 0);
366
+ __decorate([
367
+ property({ attribute: 'previous-label' })
368
+ ], HelixHeadlessDateInput.prototype, "previousLabel", void 0);
323
369
  __decorate([
324
370
  property({ attribute: 'range-length-message' })
325
371
  ], HelixHeadlessDateInput.prototype, "rangeLengthMessage", void 0);
@@ -336,11 +382,17 @@ __decorate([
336
382
  property({ type: Number })
337
383
  ], HelixHeadlessDateInput.prototype, "step", void 0);
338
384
  __decorate([
339
- state()
340
- ], HelixHeadlessDateInput.prototype, "draft", void 0);
385
+ property({ attribute: 'step-mismatch-message' })
386
+ ], HelixHeadlessDateInput.prototype, "stepMismatchMessage", void 0);
341
387
  __decorate([
342
388
  property({ attribute: 'trigger-label' })
343
389
  ], HelixHeadlessDateInput.prototype, "triggerLabel", void 0);
390
+ __decorate([
391
+ state()
392
+ ], HelixHeadlessDateInput.prototype, "draft", void 0);
393
+ __decorate([
394
+ property({ attribute: 'unavailable-message' })
395
+ ], HelixHeadlessDateInput.prototype, "unavailableMessage", void 0);
344
396
  HelixHeadlessDateInput = __decorate([
345
397
  customElement('helix-headless-date-input')
346
398
  ], HelixHeadlessDateInput);
@@ -23,6 +23,12 @@ declare const HelixHeadlessDatePicker_base: (new (...args: any[]) => import("@fu
23
23
  * marks the dates between them, and `multiple` toggles each date. All three
24
24
  * read and write the same comma-separated `value`.
25
25
  *
26
+ * The month heading is a live region, so a screen reader hears the new month
27
+ * when Previous or Next is pressed. Neither moves past `min` or `max`, and the
28
+ * keys stop at them too. A value outside the bounds, on a barred day, or off
29
+ * `step` reports `rangeUnderflow`, `rangeOverflow`, `badInput` or
30
+ * `stepMismatch`, so a form does not submit it.
31
+ *
26
32
  * @since 0.1.0
27
33
  * @status stable
28
34
  * @category forms
@@ -74,17 +80,22 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
74
80
  */
75
81
  defaultMonth: string;
76
82
  /**
77
- * Dates that cannot be chosen, comma separated, as `YYYY-MM-DD`.
83
+ * Dates that cannot be chosen, as `YYYY-MM-DD`, separated by commas or
84
+ * spaces.
78
85
  */
79
86
  disableDates: string;
80
87
  /**
81
- * Days of the week that cannot be chosen, comma separated, `0` to `6`.
88
+ * Days of the week that cannot be chosen, `0` for Sunday to `6` for
89
+ * Saturday, separated by commas or spaces.
82
90
  */
83
91
  disableDays: string;
84
92
  /**
85
93
  * First column of the week, `0` for Sunday through `6` for Saturday.
94
+ *
95
+ * Absent follows `locale`, where the engine knows the week of that language
96
+ * (Firefox does not), and is Sunday otherwise.
86
97
  */
87
- firstDayOfWeek: number;
98
+ firstDayOfWeek?: number;
88
99
  /**
89
100
  * Whether the current selection fails validation.
90
101
  */
@@ -141,19 +152,10 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
141
152
  */
142
153
  previousLabel: string;
143
154
  /**
144
- * Blocks changes to the dates. The value is still submitted with the form.
145
- *
146
- * **Enforced by refusing every request in one place**, which is the seam this
147
- * component already has: `requestValue` is what every path here comes through,
148
- * and gating it once is what stops the next call site from being written
149
- * without the check.
150
- *
151
- * Not `disabled`, which is the confusion worth naming: a disabled control
152
- * submits nothing and leaves the tab order, and a read-only one submits its
153
- * value and stays reachable, which is what a form showing a value somebody
154
- * else set needs.
155
+ * The validation message for a date after `max`. `{max}` is replaced with
156
+ * `max`, written as a date in `locale`.
155
157
  */
156
- readOnly: boolean;
158
+ rangeOverflowMessage?: string;
157
159
  /**
158
160
  * The date the grid's tab stop is on.
159
161
  *
@@ -162,6 +164,17 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
162
164
  private focused;
163
165
  /** The selected dates, in order. */
164
166
  private get selected();
167
+ /** The day the week starts on: `firstDayOfWeek`, or the locale's. */
168
+ private get weekStart();
169
+ /**
170
+ * Whether the last date the reader moved to is this picker's own doing.
171
+ *
172
+ * A value that moves from outside, typed into Date Input or set by a script,
173
+ * takes the tab stop to the selected day, as the APG date picker does. A
174
+ * value this grid chose leaves it where the reader pressed, which in a range
175
+ * is the end they just picked.
176
+ */
177
+ private choosing;
165
178
  /** The range's ends, when there are two and the mode asks for them. */
166
179
  private get range();
167
180
  private isSelected;
@@ -200,6 +213,12 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
200
213
  * one that moves.
201
214
  */
202
215
  private barred;
216
+ /** Pulls a date inside `min` and `max`, so the keys stop at the bounds. */
217
+ private clamp;
218
+ /** Whether the month before the first one shown is wholly before `min`. */
219
+ private get atStart();
220
+ /** Whether the month after the last one shown is wholly after `max`. */
221
+ private get atEnd();
203
222
  /**
204
223
  * Moves the view, announcing it first.
205
224
  *
@@ -219,14 +238,42 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
219
238
  */
220
239
  private select;
221
240
  private readonly handleKeydown;
241
+ /**
242
+ * Moves focus to the grid's tab stop: the selected day, or the day last
243
+ * moved to, or the first of the month.
244
+ *
245
+ * Date Input calls this when its trigger opens the calendar, which is where
246
+ * the APG date picker dialog puts focus. The host is not focusable, so a
247
+ * plain `focus()` on it did nothing and focus stayed on the trigger.
248
+ */
249
+ focus(options?: FocusOptions): void;
222
250
  connectedCallback(): void;
223
251
  disconnectedCallback(): void;
224
252
  /**
225
- * Stops the form from submitting while no date is chosen.
253
+ * The validation message for a date before `min`. `{min}` is replaced with
254
+ * `min`, written as a date in `locale`.
226
255
  */
227
- required: boolean;
256
+ rangeUnderflowMessage?: string;
228
257
  /** Refuses every change while read-only. See `readOnly`. */
229
258
  requestValue(next: string): boolean;
259
+ /**
260
+ * Blocks changes to the dates. The value is still submitted with the form.
261
+ *
262
+ * **Enforced by refusing every request in one place**, which is the seam this
263
+ * component already has: `requestValue` is what every path here comes through,
264
+ * and gating it once is what stops the next call site from being written
265
+ * without the check.
266
+ *
267
+ * Not `disabled`, which is the confusion worth naming: a disabled control
268
+ * submits nothing and leaves the tab order, and a read-only one submits its
269
+ * value and stays reachable, which is what a form showing a value somebody
270
+ * else set needs.
271
+ */
272
+ readOnly: boolean;
273
+ /**
274
+ * Stops the form from submitting while no date is chosen.
275
+ */
276
+ required: boolean;
230
277
  /**
231
278
  * How far apart the selectable dates are, in days.
232
279
  *
@@ -241,10 +288,30 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
241
288
  * date including the one already chosen.
242
289
  */
243
290
  step: number;
291
+ /**
292
+ * The validation message for a date that `step` skips.
293
+ */
294
+ stepMismatchMessage?: string;
295
+ /**
296
+ * The validation message for a date that `disable-dates` or `disable-days`
297
+ * bars.
298
+ */
299
+ unavailableMessage?: string;
244
300
  /**
245
301
  * The validation message for a required date picker with no date chosen.
246
302
  */
247
303
  valueMissingMessage?: string;
304
+ /** A date written for a message, in `locale`. */
305
+ private spoken;
306
+ /**
307
+ * What is wrong with a date the calendar can read, as a validity flag and a
308
+ * message, or nothing.
309
+ *
310
+ * Measured before this: a value before `min`, after `max`, or on a barred
311
+ * day reported valid and was submitted, where a native date input reports
312
+ * the bound it is past.
313
+ */
314
+ private fault;
248
315
  /**
249
316
  * Reports "required and empty", or clears it.
250
317
  *