@eifi1/ui-kit 0.21.0 → 0.23.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 (320) hide show
  1. package/README.md +42 -25
  2. package/dist/chart.d.ts +19 -14
  3. package/dist/components/account-chips.d.ts +10 -3
  4. package/dist/components/account-chips.js +5 -2
  5. package/dist/components/account-chips.js.map +1 -1
  6. package/dist/components/account-settings.d.ts +33 -2
  7. package/dist/components/account-settings.js +43 -21
  8. package/dist/components/account-settings.js.map +1 -1
  9. package/dist/components/amount-input.d.ts +53 -14
  10. package/dist/components/amount-input.js +17 -28
  11. package/dist/components/amount-input.js.map +1 -1
  12. package/dist/components/autocomplete.d.ts +29 -0
  13. package/dist/components/autocomplete.js +134 -104
  14. package/dist/components/autocomplete.js.map +1 -1
  15. package/dist/components/button-group.d.ts +19 -14
  16. package/dist/components/calculator.d.ts +19 -14
  17. package/dist/components/checkbox-group.d.ts +104 -0
  18. package/dist/components/checkbox-group.js +111 -0
  19. package/dist/components/checkbox-group.js.map +1 -0
  20. package/dist/components/checkbox.d.ts +19 -0
  21. package/dist/components/checkbox.js +30 -7
  22. package/dist/components/checkbox.js.map +1 -1
  23. package/dist/components/chip.d.ts +18 -0
  24. package/dist/components/chip.js +47 -10
  25. package/dist/components/chip.js.map +1 -1
  26. package/dist/components/column-mapper.d.ts +182 -0
  27. package/dist/components/column-mapper.js +375 -0
  28. package/dist/components/column-mapper.js.map +1 -0
  29. package/dist/components/combobox-core.d.ts +39 -2
  30. package/dist/components/combobox-core.js +29 -6
  31. package/dist/components/combobox-core.js.map +1 -1
  32. package/dist/components/combobox.d.ts +91 -2
  33. package/dist/components/combobox.js +454 -308
  34. package/dist/components/combobox.js.map +1 -1
  35. package/dist/components/confirm-dialog.d.ts +69 -161
  36. package/dist/components/confirm-dialog.js +7 -8
  37. package/dist/components/confirm-dialog.js.map +1 -1
  38. package/dist/components/copy-button.d.ts +16 -11
  39. package/dist/components/country-select.d.ts +167 -0
  40. package/dist/components/country-select.js +293 -0
  41. package/dist/components/country-select.js.map +1 -0
  42. package/dist/components/currency-select.d.ts +17 -1
  43. package/dist/components/currency-select.js +56 -23
  44. package/dist/components/currency-select.js.map +1 -1
  45. package/dist/components/danger-confirm.d.ts +69 -166
  46. package/dist/components/danger-confirm.js +144 -50
  47. package/dist/components/danger-confirm.js.map +1 -1
  48. package/dist/components/data-table-cells.d.ts +1 -2
  49. package/dist/components/data-table-filter-popover.d.ts +1 -2
  50. package/dist/components/data-table-filters.d.ts +1 -2
  51. package/dist/components/data-table-labels.d.ts +4 -97
  52. package/dist/components/data-table-labels.js +9 -1
  53. package/dist/components/data-table-labels.js.map +1 -1
  54. package/dist/components/data-table-pagination.d.ts +3 -1
  55. package/dist/components/data-table.d.ts +1 -2
  56. package/dist/components/data-table.js +98 -3
  57. package/dist/components/data-table.js.map +1 -1
  58. package/dist/components/date-picker.d.ts +66 -5
  59. package/dist/components/date-picker.js +378 -66
  60. package/dist/components/date-picker.js.map +1 -1
  61. package/dist/components/entity-combobox.d.ts +42 -1
  62. package/dist/components/entity-combobox.js +154 -113
  63. package/dist/components/entity-combobox.js.map +1 -1
  64. package/dist/components/facing-pair.d.ts +19 -14
  65. package/dist/components/field-parts.d.ts +224 -0
  66. package/dist/components/field-parts.js +156 -0
  67. package/dist/components/field-parts.js.map +1 -0
  68. package/dist/components/field-strip.d.ts +105 -0
  69. package/dist/components/field-strip.js +46 -0
  70. package/dist/components/field-strip.js.map +1 -0
  71. package/dist/components/file-button.d.ts +19 -14
  72. package/dist/components/file-button.js +13 -3
  73. package/dist/components/file-button.js.map +1 -1
  74. package/dist/components/file-dropzone.d.ts +41 -15
  75. package/dist/components/file-dropzone.js +57 -34
  76. package/dist/components/file-dropzone.js.map +1 -1
  77. package/dist/components/form-actions.d.ts +18 -13
  78. package/dist/components/form-actions.js +69 -5
  79. package/dist/components/form-actions.js.map +1 -1
  80. package/dist/components/iban-input.d.ts +69 -0
  81. package/dist/components/iban-input.js +125 -0
  82. package/dist/components/iban-input.js.map +1 -0
  83. package/dist/components/icon-picker.d.ts +21 -2
  84. package/dist/components/icon-picker.js +19 -4
  85. package/dist/components/icon-picker.js.map +1 -1
  86. package/dist/components/inline-edit-field.d.ts +167 -0
  87. package/dist/components/inline-edit-field.js +293 -0
  88. package/dist/components/inline-edit-field.js.map +1 -0
  89. package/dist/components/language-select.d.ts +130 -0
  90. package/dist/components/language-select.js +18 -0
  91. package/dist/components/language-select.js.map +1 -0
  92. package/dist/components/line-items.d.ts +25 -3
  93. package/dist/components/line-items.js +55 -46
  94. package/dist/components/line-items.js.map +1 -1
  95. package/dist/components/list.d.ts +25 -0
  96. package/dist/components/list.js +16 -5
  97. package/dist/components/list.js.map +1 -1
  98. package/dist/components/money-field.d.ts +32 -14
  99. package/dist/components/money-field.js.map +1 -1
  100. package/dist/components/month-picker.d.ts +52 -4
  101. package/dist/components/month-picker.js +291 -86
  102. package/dist/components/month-picker.js.map +1 -1
  103. package/dist/components/multi-entity-combobox.d.ts +26 -1
  104. package/dist/components/multi-entity-combobox.js +143 -102
  105. package/dist/components/multi-entity-combobox.js.map +1 -1
  106. package/dist/components/multi-select.d.ts +8 -1
  107. package/dist/components/multi-select.js +9 -4
  108. package/dist/components/multi-select.js.map +1 -1
  109. package/dist/components/number-field.d.ts +34 -19
  110. package/dist/components/number-field.js +6 -20
  111. package/dist/components/number-field.js.map +1 -1
  112. package/dist/components/number-input.d.ts +79 -19
  113. package/dist/components/number-input.js +90 -38
  114. package/dist/components/number-input.js.map +1 -1
  115. package/dist/components/numpad-sheet.d.ts +19 -14
  116. package/dist/components/one-time-code-input.d.ts +100 -0
  117. package/dist/components/one-time-code-input.js +137 -0
  118. package/dist/components/one-time-code-input.js.map +1 -0
  119. package/dist/components/phone-input.d.ts +69 -0
  120. package/dist/components/phone-input.js +171 -0
  121. package/dist/components/phone-input.js.map +1 -0
  122. package/dist/components/reauth-dialog.d.ts +2 -2
  123. package/dist/components/reauth-dialog.js +6 -8
  124. package/dist/components/reauth-dialog.js.map +1 -1
  125. package/dist/components/series-chart.d.ts +19 -14
  126. package/dist/components/settings-fields.d.ts +19 -14
  127. package/dist/components/share-card.d.ts +16 -11
  128. package/dist/components/sign-chip.d.ts +66 -0
  129. package/dist/components/sign-chip.js +39 -0
  130. package/dist/components/sign-chip.js.map +1 -0
  131. package/dist/components/swatch-picker.d.ts +43 -2
  132. package/dist/components/swatch-picker.js +80 -32
  133. package/dist/components/swatch-picker.js.map +1 -1
  134. package/dist/components/switch.d.ts +19 -0
  135. package/dist/components/switch.js +24 -6
  136. package/dist/components/switch.js.map +1 -1
  137. package/dist/components/text-link.d.ts +18 -13
  138. package/dist/components/tile-radio.d.ts +88 -13
  139. package/dist/components/tile-radio.js +28 -11
  140. package/dist/components/tile-radio.js.map +1 -1
  141. package/dist/components/time-input.d.ts +24 -15
  142. package/dist/components/time-input.js.map +1 -1
  143. package/dist/components/toggle-group.d.ts +47 -1
  144. package/dist/components/toggle-group.js +110 -69
  145. package/dist/components/toggle-group.js.map +1 -1
  146. package/dist/components/trigger-aria.d.ts +3 -0
  147. package/dist/components/trigger-aria.js +3 -1
  148. package/dist/components/trigger-aria.js.map +1 -1
  149. package/dist/components/ui.d.ts +16 -11
  150. package/dist/components/ui.js +284 -88
  151. package/dist/components/ui.js.map +1 -1
  152. package/dist/components/use-table-state.d.ts +1 -2
  153. package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
  154. package/dist/data-table.d.ts +1 -2
  155. package/dist/data-table.js +2 -1
  156. package/dist/data-table.js.map +1 -1
  157. package/dist/feedback/feedback-attachment.d.ts +1 -1
  158. package/dist/feedback/feedback-attachment.js +348 -41
  159. package/dist/feedback/feedback-attachment.js.map +1 -1
  160. package/dist/feedback/feedback-dialog.d.ts +1 -1
  161. package/dist/feedback/feedback-dialog.js.map +1 -1
  162. package/dist/feedback/feedback-inbox.d.ts +3 -2
  163. package/dist/feedback/feedback-inbox.js.map +1 -1
  164. package/dist/feedback/feedback-thread.d.ts +68 -253
  165. package/dist/feedback/feedback-thread.js +46 -10
  166. package/dist/feedback/feedback-thread.js.map +1 -1
  167. package/dist/{kit-labels-D1J2_jyD.d.ts → feedback-BxeQVzwq.d.ts} +1206 -20
  168. package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-fGAzZPf0.d.ts} +178 -11
  169. package/dist/feedback.d.ts +66 -2
  170. package/dist/hooks/use-file-drop.d.ts +19 -14
  171. package/dist/i18n/defaults.d.ts +19 -14
  172. package/dist/i18n/defaults.js +19 -2
  173. package/dist/i18n/defaults.js.map +1 -1
  174. package/dist/i18n/german.d.ts +19 -14
  175. package/dist/i18n/german.js +84 -5
  176. package/dist/i18n/german.js.map +1 -1
  177. package/dist/i18n/kit-labels.d.ts +15 -10
  178. package/dist/i18n/kit-labels.js +8 -2
  179. package/dist/i18n/kit-labels.js.map +1 -1
  180. package/dist/i18n/languages.d.ts +19 -14
  181. package/dist/i18n/locales/de-CH.d.ts +19 -14
  182. package/dist/i18n/locales/en.d.ts +19 -14
  183. package/dist/i18n/locales/en.js +16 -0
  184. package/dist/i18n/locales/en.js.map +1 -1
  185. package/dist/i18n/locales/es.d.ts +19 -14
  186. package/dist/i18n/locales/es.js +83 -5
  187. package/dist/i18n/locales/es.js.map +1 -1
  188. package/dist/i18n/locales/fr.d.ts +19 -14
  189. package/dist/i18n/locales/fr.js +82 -5
  190. package/dist/i18n/locales/fr.js.map +1 -1
  191. package/dist/i18n/locales/hu.d.ts +19 -14
  192. package/dist/i18n/locales/hu.js +85 -5
  193. package/dist/i18n/locales/hu.js.map +1 -1
  194. package/dist/i18n/locales/it.d.ts +19 -14
  195. package/dist/i18n/locales/it.js +84 -5
  196. package/dist/i18n/locales/it.js.map +1 -1
  197. package/dist/i18n/locales/zh.d.ts +19 -14
  198. package/dist/i18n/locales/zh.js +80 -5
  199. package/dist/i18n/locales/zh.js.map +1 -1
  200. package/dist/i18n/review.d.ts +19 -14
  201. package/dist/i18n/review.js +27 -1
  202. package/dist/i18n/review.js.map +1 -1
  203. package/dist/index.d.ts +21 -10
  204. package/dist/index.js +73 -2
  205. package/dist/index.js.map +1 -1
  206. package/dist/lib/column-mapping.d.ts +81 -0
  207. package/dist/lib/column-mapping.js +108 -0
  208. package/dist/lib/column-mapping.js.map +1 -0
  209. package/dist/lib/countries.d.ts +43 -0
  210. package/dist/lib/countries.js +39 -0
  211. package/dist/lib/countries.js.map +1 -0
  212. package/dist/lib/decimal-marks.d.ts +46 -0
  213. package/dist/lib/decimal-marks.js +40 -0
  214. package/dist/lib/decimal-marks.js.map +1 -0
  215. package/dist/lib/iban.d.ts +98 -0
  216. package/dist/lib/iban.js +154 -0
  217. package/dist/lib/iban.js.map +1 -0
  218. package/dist/lib/isin.d.ts +30 -0
  219. package/dist/lib/isin.js +36 -0
  220. package/dist/lib/isin.js.map +1 -0
  221. package/dist/lib/phone.d.ts +69 -0
  222. package/dist/lib/phone.js +121 -0
  223. package/dist/lib/phone.js.map +1 -0
  224. package/dist/lib/table-text.d.ts +109 -1
  225. package/dist/lib/table-text.js +122 -1
  226. package/dist/lib/table-text.js.map +1 -1
  227. package/dist/rhf/fields.d.ts +233 -18
  228. package/dist/rhf/fields.js +456 -3
  229. package/dist/rhf/fields.js.map +1 -1
  230. package/dist/rhf/form.d.ts +19 -14
  231. package/dist/rhf.d.ts +22 -15
  232. package/dist/rhf.js.map +1 -1
  233. package/dist/shell/app-shell.d.ts +18 -13
  234. package/dist/shell/top-bar-brand.d.ts +19 -14
  235. package/dist/shell/topbar-action-menu.d.ts +36 -3
  236. package/dist/shell/topbar-action-menu.js +74 -33
  237. package/dist/shell/topbar-action-menu.js.map +1 -1
  238. package/dist/shell.d.ts +18 -13
  239. package/dist/table-text.d.ts +1 -1
  240. package/dist/tour/tour.js +20 -24
  241. package/dist/tour/tour.js.map +1 -1
  242. package/dist/wizard/stepper-nav.d.ts +49 -16
  243. package/dist/wizard/stepper-nav.js +4 -0
  244. package/dist/wizard/stepper-nav.js.map +1 -1
  245. package/dist/wizard.d.ts +19 -14
  246. package/package.json +1 -1
  247. package/src/components/account-chips.tsx +17 -3
  248. package/src/components/account-settings.tsx +92 -26
  249. package/src/components/amount-input.tsx +68 -56
  250. package/src/components/autocomplete.tsx +198 -114
  251. package/src/components/checkbox-group.tsx +229 -0
  252. package/src/components/checkbox.tsx +72 -8
  253. package/src/components/chip.tsx +80 -10
  254. package/src/components/column-mapper.tsx +666 -0
  255. package/src/components/combobox-core.tsx +82 -9
  256. package/src/components/combobox.tsx +661 -340
  257. package/src/components/confirm-dialog.tsx +12 -8
  258. package/src/components/country-select.tsx +556 -0
  259. package/src/components/currency-select.tsx +109 -33
  260. package/src/components/danger-confirm.tsx +429 -82
  261. package/src/components/data-table-labels.ts +16 -1
  262. package/src/components/data-table.tsx +175 -6
  263. package/src/components/date-picker.tsx +595 -71
  264. package/src/components/entity-combobox.tsx +235 -124
  265. package/src/components/field-parts.tsx +403 -0
  266. package/src/components/field-strip.tsx +149 -0
  267. package/src/components/file-button.tsx +36 -3
  268. package/src/components/file-dropzone.tsx +106 -38
  269. package/src/components/form-actions.tsx +147 -6
  270. package/src/components/iban-input.tsx +231 -0
  271. package/src/components/icon-picker.tsx +47 -6
  272. package/src/components/inline-edit-field.tsx +533 -0
  273. package/src/components/language-select.tsx +78 -0
  274. package/src/components/line-items.tsx +35 -2
  275. package/src/components/list.tsx +55 -6
  276. package/src/components/money-field.tsx +13 -0
  277. package/src/components/month-picker.tsx +400 -63
  278. package/src/components/multi-entity-combobox.tsx +207 -120
  279. package/src/components/multi-select.tsx +80 -58
  280. package/src/components/number-field.tsx +28 -46
  281. package/src/components/number-input.tsx +210 -43
  282. package/src/components/one-time-code-input.tsx +288 -0
  283. package/src/components/phone-input.tsx +299 -0
  284. package/src/components/reauth-dialog.tsx +17 -18
  285. package/src/components/sign-chip.tsx +103 -0
  286. package/src/components/swatch-picker.tsx +143 -31
  287. package/src/components/switch.tsx +58 -7
  288. package/src/components/tile-radio.tsx +145 -29
  289. package/src/components/time-input.tsx +8 -1
  290. package/src/components/toggle-group.tsx +206 -73
  291. package/src/components/trigger-aria.ts +5 -0
  292. package/src/components/ui.tsx +479 -138
  293. package/src/data-table.ts +2 -1
  294. package/src/feedback/feedback-attachment.tsx +597 -46
  295. package/src/feedback/feedback-dialog.tsx +9 -3
  296. package/src/feedback/feedback-inbox.tsx +3 -2
  297. package/src/feedback/feedback-thread.tsx +113 -9
  298. package/src/i18n/defaults.ts +18 -1
  299. package/src/i18n/german.ts +89 -0
  300. package/src/i18n/kit-labels.tsx +82 -2
  301. package/src/i18n/locales/en.ts +36 -4
  302. package/src/i18n/locales/es.ts +87 -0
  303. package/src/i18n/locales/fr.ts +87 -0
  304. package/src/i18n/locales/hu.ts +83 -0
  305. package/src/i18n/locales/it.ts +88 -0
  306. package/src/i18n/locales/zh.ts +76 -0
  307. package/src/i18n/review.ts +26 -0
  308. package/src/index.ts +71 -3
  309. package/src/lib/column-mapping.ts +234 -0
  310. package/src/lib/countries.ts +91 -0
  311. package/src/lib/decimal-marks.ts +99 -0
  312. package/src/lib/iban.ts +171 -0
  313. package/src/lib/isin.ts +62 -0
  314. package/src/lib/phone.ts +211 -0
  315. package/src/lib/table-text.ts +271 -0
  316. package/src/rhf/fields.tsx +860 -9
  317. package/src/rhf.ts +3 -1
  318. package/src/shell/topbar-action-menu.tsx +134 -38
  319. package/src/tour/tour.tsx +66 -28
  320. package/src/wizard/stepper-nav.tsx +35 -1
@@ -29,19 +29,80 @@ interface DatePickerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "onC
29
29
  disabled?: boolean;
30
30
  /** Required and unanswered — {@link FIELD_INVALID}. See {@link Input}'s `invalid`. */
31
31
  invalid?: boolean;
32
+ /**
33
+ * Standing advice for the field (keksdose K4, "uniform field anatomy"), as on a
34
+ * {@link Select}: plain TEXT is a caption under the field, attached with
35
+ * `aria-describedby`; a {@link FieldHint} rides the label line (or, unlabelled, sits
36
+ * at the field's end, outside the box).
37
+ */
38
+ hint?: ReactNode;
39
+ /**
40
+ * What is wrong with the date, in the caller's words ("The due date is before the
41
+ * invoice date") — {@link Input}'s `error` (keksdose K4: DateField errors had no slot).
42
+ * Rendered under the field (under the whole row, with `step` / `today`), attached to
43
+ * the trigger with `aria-describedby` — merged with any the caller passed, after the
44
+ * caption — and implies `invalid`. Passing the key at all keeps the field's box while
45
+ * there is no message, so the trigger is never remounted as one comes and goes.
46
+ */
47
+ error?: ReactNode;
32
48
  className?: string;
33
- /** Intl options for the trigger's formatted date (default: locale short date). */
49
+ /** Intl options for the trigger's formatted date (default: locale short date). Win
50
+ * over the provider's `formatDate`. */
34
51
  formatOptions?: Intl.DateTimeFormatOptions;
35
- /** Render the trigger's text for an ISO date yourself; wins over `formatOptions`.
52
+ /** Render the trigger's text for an ISO date yourself; wins over `formatOptions` and
53
+ * over the provider's `formatDate`.
36
54
  * For a host whose date rendering is more than one `Intl` call can say — Keksdose
37
55
  * puts the weekday's name in the UI language beside digits ordered by a separate
38
- * format preference, two locales in one string. `locale` still drives the calendar. */
56
+ * format preference, two locales in one string. `locale` still drives the calendar.
57
+ * Set that rendering once with `<UiKitProvider formatDate>` (keksdose K12) and this
58
+ * is for the one field that differs. */
39
59
  formatValue?: (iso: string) => string;
40
60
  /** Passed through to the {@link MiniCalendar} this opens. Its month arrows are
41
61
  * icon-only, so their `aria-label` is the only name they have — and the package
42
62
  * ships English defaults, which a translating host has to be able to replace.
43
63
  * Usually unnecessary now: the calendar reads `miniCalendar` from the provider. */
44
64
  calendarLabels?: MiniCalendarProps["labels"];
65
+ /**
66
+ * Make the panel's caption ("July 2026") a button that opens the year's twelve
67
+ * months, with ‹ › stepping a year; picking a month returns to its days. Far dates
68
+ * stop being a march of month arrows.
69
+ *
70
+ * kastlan is why: its service-charge period runs July to June, and with one month on
71
+ * screen and ‹ › the only way across, the end of the period was eleven clicks past
72
+ * the start — so kastlan kept two date fields instead of `RhfDateRangePicker`. With
73
+ * the jump the whole period is open, caption, Jul, 1, caption, next year, Jun, 30.
74
+ *
75
+ * What it adds, for the keyboard and a screen reader:
76
+ * - the caption is a disclosure button (`aria-expanded`). Its name is the month it
77
+ * shows, so speech input can say what it sees; it is `aria-live`, as the
78
+ * calendar's caption was, so paging months still says where you landed; and it is
79
+ * described by `monthPicker.panel` ("Choose a month").
80
+ * - the month grid is `MonthPicker`'s grid: one tab stop, arrows walk the months
81
+ * (across the year's edge), Home/End the row, PageUp/PageDown a year, Enter or a
82
+ * click picks. Focus opens on the month on show and comes back on its days — the
83
+ * selected day if it is in that month, else the 1st. Months outside `min`/`max`
84
+ * are `aria-disabled`, and a year arrow is once the whole year beyond is.
85
+ * - Escape in the month grid goes back to the days without closing the panel (focus
86
+ * on the caption); in the days, Escape closes the panel as before.
87
+ *
88
+ * No new strings: the month arrows keep `miniCalendar.previousMonth` / `nextMonth`
89
+ * (`calendarLabels`), and the month grid speaks with `MonthPicker`'s words —
90
+ * `monthPicker.previousYear` / `nextYear` / `month` / `panel` — because it is that
91
+ * grid, and a host that translated it once should not have to again.
92
+ *
93
+ * Off by default: the caption becomes one more stop in the panel's tab order, which a
94
+ * 0.x minor does not spring on a form. Works in the popover and in
95
+ * `DateRangePicker`'s phone sheet alike, beside presets and in `commit="apply"`
96
+ * (a preset picked while the months are open goes back to the days, on its start).
97
+ *
98
+ * Why not a two-month panel (`months={2}`) instead, or beside it: for a twelve-month
99
+ * period it still pages six times where this takes one year step, and two
100
+ * `MiniCalendar`s side by side each follow the value on their own — picking the end
101
+ * in the right-hand month would pull the left one onto it — so the calendar would
102
+ * have to learn to share a month first. Not worth that for a saving of one arrow on a
103
+ * range across a single month boundary.
104
+ */
105
+ monthJump?: boolean;
45
106
  }
46
107
  /**
47
108
  * Everything the kit's own trigger button carries, handed to a custom one
@@ -107,7 +168,7 @@ interface DatePickerProps extends DatePickerBaseProps {
107
168
  todayLabel?: string;
108
169
  }
109
170
  /** Single-date picker: a field showing the formatted date, opening a calendar. */
110
- declare function DatePicker({ value, onChange, locale: localeProp, placeholder, min, max, formatOptions, formatValue, step, stepLabels, today, todayLabel, className, calendarLabels, label, clearable, clearLabel, disabled, invalid, "aria-required": ariaRequired, ...rest }: DatePickerProps): react.JSX.Element;
171
+ declare function DatePicker(props: DatePickerProps): react.JSX.Element;
111
172
  interface DateRangePickerPreset {
112
173
  /**
113
174
  * The preset's identity, independent of its dates — `"last_3_months"`, not two ISO
@@ -230,6 +291,6 @@ interface DateRangeTriggerRenderProps {
230
291
  /** Two-date range picker: click a start then an end; closes once both are set.
231
292
  * With `presets`, a column of named ranges is shown beside the calendar; with
232
293
  * `commit="apply"` the panel drafts and commits on Apply (see {@link DateRangeCommit}). */
233
- declare function DateRangePicker({ from, to, onChange, locale: localeProp, placeholder, min, max, formatOptions, formatValue, separator, presets, preset, commit, renderTrigger, sheetBackCloses, renderDraftSummary, calendarLabels, label, clearable, clearLabel, disabled, invalid, ...rest }: DateRangePickerProps): react.JSX.Element;
294
+ declare function DateRangePicker(props: DateRangePickerProps): react.JSX.Element;
234
295
 
235
296
  export { DatePicker, type DatePickerProps, type DateRangeCommit, type DateRangeDraftSummary, DateRangePicker, type DateRangePickerPreset, type DateRangePickerProps, type DateRangeTriggerRenderProps, type DateTriggerAttributes };
@@ -1,26 +1,40 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useId, useMemo, useRef, useState } from "react";
4
- import { Calendar, CalendarClock, ChevronLeft, ChevronRight, X } from "lucide-react";
4
+ import { Calendar, CalendarClock, ChevronDown, ChevronLeft, ChevronRight, X } from "lucide-react";
5
5
  import { cn } from "../lib/cn.js";
6
- import { dirOf } from "../lib/direction.js";
7
- import { addDaysIso, parseIsoDate } from "../lib/dates.js";
6
+ import { dirOf, horizontalStep } from "../lib/direction.js";
7
+ import { addDaysIso, monthKey, pad, parseIsoDate } from "../lib/dates.js";
8
8
  import {
9
9
  DEFAULT_DATE_PICKER_LABELS,
10
10
  DEFAULT_PICKER_SHEET_LABELS,
11
+ useKitDateFormatter,
11
12
  useKitLabels,
12
13
  useKitLocale
13
14
  } from "../i18n/kit-labels.js";
14
15
  import { splitTriggerAria } from "./trigger-aria.js";
15
- import { Button, FieldLabel, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui.js";
16
+ import { Button, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui.js";
17
+ import { FieldBox, FieldLabelLine, useFieldMessages } from "./field-parts.js";
16
18
  import { FullBleedDialog } from "./full-bleed-dialog.js";
17
19
  import { useMediaQuery } from "../hooks/use-media-query.js";
18
- import { MiniCalendar } from "./mini-calendar.js";
20
+ import { DEFAULT_MINI_CALENDAR_LABELS, MiniCalendar } from "./mini-calendar.js";
21
+ import { DEFAULT_MONTH_PICKER_LABELS } from "./month-picker.js";
19
22
  import { Popover } from "./popover.js";
20
23
  import { Tooltip } from "./tooltip.js";
21
24
  function formatDate(iso, locale, options) {
22
25
  return parseIsoDate(iso)?.toLocaleDateString(locale, options) ?? "";
23
26
  }
27
+ function useTriggerFormat(source, locale, formatOptions, formatValue) {
28
+ const fromProvider = useKitDateFormatter();
29
+ if (formatValue) return formatValue;
30
+ return (iso) => {
31
+ if (formatOptions === void 0 && fromProvider) {
32
+ const text = fromProvider(iso, { unit: "day", source, locale, weekday: source === "datePicker" });
33
+ if (text) return text;
34
+ }
35
+ return formatDate(iso, locale, formatOptions);
36
+ };
37
+ }
24
38
  function CustomTrigger({
25
39
  render,
26
40
  attrs,
@@ -118,6 +132,7 @@ function DateField({
118
132
  sheet = false,
119
133
  sheetBackCloses = true,
120
134
  renderTrigger,
135
+ labelHint,
121
136
  children,
122
137
  // The trigger's, not the wrapper's: `Field`'s render-prop spreads it with the id
123
138
  // pair, and a required date read as optional while it sat on the role-less div.
@@ -188,7 +203,7 @@ function DateField({
188
203
  // The caller's attributes land here, on the field's own box — the trigger inside is
189
204
  // named by `aria-labelledby` and must keep the id pair it is given.
190
205
  /* @__PURE__ */ jsxs("div", { ...wrapperRest, ref: rootRef, className: cn("relative", className), children: [
191
- label !== void 0 && /* @__PURE__ */ jsx(FieldLabel, { children: label }),
206
+ label !== void 0 && /* @__PURE__ */ jsx(FieldLabelLine, { label, hint: labelHint }),
192
207
  named && /* @__PURE__ */ jsx("span", { id: labelId, "aria-hidden": true, className: "sr-only-fixed", children: label }),
193
208
  sheet ? /* @__PURE__ */ jsxs(Fragment, { children: [
194
209
  fieldTrigger({ open: sheetOpen, toggle: () => setSheetOpen((v) => !v), ref: sheetTriggerRef }),
@@ -256,6 +271,263 @@ function StepButton({
256
271
  }
257
272
  ) });
258
273
  }
274
+ const monthIndex = (key) => Number(key.slice(0, 4)) * 12 + Number(key.slice(5, 7)) - 1;
275
+ const keyOfIndex = (index) => `${String(Math.floor(index / 12)).padStart(4, "0")}-${pad(index % 12 + 1)}`;
276
+ const shiftKey = (key, delta) => keyOfIndex(monthIndex(key) + delta);
277
+ const firstOfKey = (key) => new Date(Number(key.slice(0, 4)), Number(key.slice(5, 7)) - 1, 1);
278
+ const upperFirst = (text, locale) => text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);
279
+ const MONTH_COLUMNS = 3;
280
+ function openingMonth(from, to, lo, hi) {
281
+ const start = parseIsoDate(from) ?? parseIsoDate(to) ?? /* @__PURE__ */ new Date();
282
+ if (lo && start < lo) return monthKey(lo);
283
+ if (hi && start > hi) return monthKey(hi);
284
+ return monthKey(start);
285
+ }
286
+ function PanelCalendar({ monthJump, ...calendar }) {
287
+ return monthJump ? /* @__PURE__ */ jsx(JumpCalendar, { ...calendar }) : /* @__PURE__ */ jsx(MiniCalendar, { ...calendar });
288
+ }
289
+ function JumpCalendar({
290
+ from = "",
291
+ to = "",
292
+ mode = "range",
293
+ locale,
294
+ min,
295
+ max,
296
+ labels,
297
+ onSelect,
298
+ focusOnOpen
299
+ }) {
300
+ const calendarText = useKitLabels("miniCalendar", DEFAULT_MINI_CALENDAR_LABELS, labels);
301
+ const monthText = useKitLabels("monthPicker", DEFAULT_MONTH_PICKER_LABELS);
302
+ const id = useId();
303
+ const captionId = `${id}-caption`;
304
+ const hintId = `${id}-hint`;
305
+ const captionRef = useRef(null);
306
+ const monthsRef = useRef(null);
307
+ const lo = min ? parseIsoDate(min) : null;
308
+ const hi = max ? parseIsoDate(max) : null;
309
+ const minKey = lo ? monthKey(lo) : null;
310
+ const maxKey = hi ? monthKey(hi) : null;
311
+ const outOfBounds = (key) => Boolean(minKey && key < minKey || maxKey && key > maxKey);
312
+ const clampKey = (key) => minKey && key < minKey ? minKey : maxKey && key > maxKey ? maxKey : key;
313
+ const [view, setView] = useState("days");
314
+ const [shown, setShown] = useState(() => openingMonth(from, to, lo, hi));
315
+ const [dayGrid, setDayGrid] = useState(() => ({ key: 0, focus: Boolean(focusOnOpen) }));
316
+ const [active, setActive] = useState(shown);
317
+ const [lastValue, setLastValue] = useState({ from, to });
318
+ if (lastValue.from !== from || lastValue.to !== to) {
319
+ const changed = lastValue.from !== from ? from : to;
320
+ setLastValue({ from, to });
321
+ const next = parseIsoDate(changed) ?? parseIsoDate(from) ?? parseIsoDate(to);
322
+ const key = next ? monthKey(next) : null;
323
+ if (key && (key !== shown || view === "months")) {
324
+ setShown(key);
325
+ setView("days");
326
+ setDayGrid((d) => ({ key: d.key + 1, month: key, focus: false }));
327
+ }
328
+ }
329
+ const pendingFocus = useRef(null);
330
+ useEffect(() => {
331
+ const key = pendingFocus.current;
332
+ if (!key) return;
333
+ pendingFocus.current = null;
334
+ monthsRef.current?.querySelector(`[data-month="${key}"]`)?.focus();
335
+ });
336
+ const showMonth = (key) => {
337
+ setShown(key);
338
+ setDayGrid((d) => ({ ...d, month: key }));
339
+ };
340
+ const openMonths = () => {
341
+ const start = clampKey(shown);
342
+ pendingFocus.current = start;
343
+ setActive(start);
344
+ setView("months");
345
+ };
346
+ const closeMonths = (focusCaption) => {
347
+ setView("days");
348
+ setDayGrid((d) => ({ ...d, month: shown, focus: false }));
349
+ if (focusCaption) captionRef.current?.focus();
350
+ };
351
+ const pick = (key) => {
352
+ setShown(key);
353
+ setView("days");
354
+ setDayGrid((d) => ({ key: d.key + 1, month: key, focus: true }));
355
+ };
356
+ const moveActive = (key, focus) => {
357
+ if (focus) pendingFocus.current = key;
358
+ setActive(key);
359
+ };
360
+ const inDays = view === "days";
361
+ const escapeToDays = (e) => {
362
+ if (e.key !== "Escape" || inDays) return;
363
+ e.preventDefault();
364
+ e.stopPropagation();
365
+ closeMonths(true);
366
+ };
367
+ const onMonthKeyDown = (e) => {
368
+ if (e.key === "Escape") return escapeToDays(e);
369
+ const step = horizontalStep(e.key, e.currentTarget);
370
+ const col = monthIndex(active) % 12 % MONTH_COLUMNS;
371
+ let delta;
372
+ switch (step ? "horizontal" : e.key) {
373
+ case "horizontal":
374
+ delta = step;
375
+ break;
376
+ case "ArrowUp":
377
+ delta = -MONTH_COLUMNS;
378
+ break;
379
+ case "ArrowDown":
380
+ delta = MONTH_COLUMNS;
381
+ break;
382
+ case "Home":
383
+ delta = -col;
384
+ break;
385
+ case "End":
386
+ delta = MONTH_COLUMNS - 1 - col;
387
+ break;
388
+ case "PageUp":
389
+ delta = -12;
390
+ break;
391
+ case "PageDown":
392
+ delta = 12;
393
+ break;
394
+ default:
395
+ return;
396
+ }
397
+ e.preventDefault();
398
+ if (delta !== 0) moveActive(shiftKey(active, delta), true);
399
+ };
400
+ const year = Number(active.slice(0, 4));
401
+ const prevYearBlocked = Boolean(minKey && year - 1 < Number(minKey.slice(0, 4)));
402
+ const nextYearBlocked = Boolean(maxKey && year + 1 > Number(maxKey.slice(0, 4)));
403
+ const prevBlocked = !inDays && prevYearBlocked;
404
+ const nextBlocked = !inDays && nextYearBlocked;
405
+ const longName = useMemo(() => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }), [locale]);
406
+ const shortNames = useMemo(() => {
407
+ const fmt = new Intl.DateTimeFormat(locale, { month: "short" });
408
+ return Array.from({ length: 12 }, (_, i) => upperFirst(fmt.format(new Date(2e3, i, 1)), locale));
409
+ }, [locale]);
410
+ const caption = inDays ? upperFirst(longName.format(firstOfKey(shown)), locale) : new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date(year, 0, 1));
411
+ const fromDate = parseIsoDate(from);
412
+ const toDate = parseIsoDate(to);
413
+ const fromKey = fromDate ? monthKey(fromDate) : null;
414
+ const toKey = toDate ? monthKey(toDate) : null;
415
+ const low = fromKey ?? toKey;
416
+ const high = toKey ?? fromKey;
417
+ const currentKey = monthKey(/* @__PURE__ */ new Date());
418
+ const arrow = "rounded p-1 text-[var(--text-muted)] hover:bg-[var(--bg-hover)] aria-disabled:cursor-not-allowed aria-disabled:opacity-30 aria-disabled:hover:bg-transparent";
419
+ return /* @__PURE__ */ jsxs("div", { className: "select-none", children: [
420
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-1 pb-1", children: [
421
+ /* @__PURE__ */ jsx(
422
+ "button",
423
+ {
424
+ type: "button",
425
+ "aria-label": inDays ? calendarText.previousMonth : monthText.previousYear,
426
+ "aria-disabled": prevBlocked || void 0,
427
+ onClick: () => {
428
+ if (inDays) showMonth(shiftKey(shown, -1));
429
+ else if (!prevBlocked) moveActive(shiftKey(active, -12), false);
430
+ },
431
+ onKeyDown: escapeToDays,
432
+ className: arrow,
433
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 rtl:-scale-x-100", "aria-hidden": true })
434
+ }
435
+ ),
436
+ /* @__PURE__ */ jsxs(
437
+ "button",
438
+ {
439
+ ref: captionRef,
440
+ type: "button",
441
+ "aria-expanded": !inDays,
442
+ "aria-describedby": inDays ? hintId : void 0,
443
+ onClick: inDays ? openMonths : () => closeMonths(false),
444
+ onKeyDown: escapeToDays,
445
+ className: "inline-flex min-w-0 items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]",
446
+ children: [
447
+ /* @__PURE__ */ jsx("span", { id: captionId, "aria-live": "polite", className: "truncate", children: caption }),
448
+ /* @__PURE__ */ jsx(
449
+ ChevronDown,
450
+ {
451
+ "aria-hidden": true,
452
+ className: cn("size-3.5 shrink-0 text-[var(--text-muted)]", !inDays && "rotate-180")
453
+ }
454
+ )
455
+ ]
456
+ }
457
+ ),
458
+ /* @__PURE__ */ jsx(
459
+ "button",
460
+ {
461
+ type: "button",
462
+ "aria-label": inDays ? calendarText.nextMonth : monthText.nextYear,
463
+ "aria-disabled": nextBlocked || void 0,
464
+ onClick: () => {
465
+ if (inDays) showMonth(shiftKey(shown, 1));
466
+ else if (!nextBlocked) moveActive(shiftKey(active, 12), false);
467
+ },
468
+ onKeyDown: escapeToDays,
469
+ className: arrow,
470
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:-scale-x-100", "aria-hidden": true })
471
+ }
472
+ )
473
+ ] }),
474
+ /* @__PURE__ */ jsx("span", { id: hintId, hidden: true, children: monthText.panel }),
475
+ inDays ? /* @__PURE__ */ jsx(
476
+ MiniCalendar,
477
+ {
478
+ mode,
479
+ from,
480
+ to,
481
+ locale,
482
+ min,
483
+ max,
484
+ labels,
485
+ onSelect,
486
+ focusOnOpen: dayGrid.focus,
487
+ hideNavigation: true,
488
+ month: dayGrid.month,
489
+ onMonthChange: showMonth
490
+ },
491
+ dayGrid.key
492
+ ) : /* @__PURE__ */ jsx("div", { ref: monthsRef, role: "grid", "aria-labelledby": captionId, className: "grid gap-1", children: Array.from({ length: 12 / MONTH_COLUMNS }, (_, row) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-3 gap-1", children: Array.from({ length: MONTH_COLUMNS }, (_2, c) => {
493
+ const index = row * MONTH_COLUMNS + c;
494
+ const key = keyOfIndex(year * 12 + index);
495
+ const disabled = outOfBounds(key);
496
+ const selected = low !== null && high !== null && key >= low && key <= high;
497
+ const end = key === fromKey || key === toKey;
498
+ const current = key === currentKey;
499
+ return /* @__PURE__ */ jsx(
500
+ "button",
501
+ {
502
+ type: "button",
503
+ role: "gridcell",
504
+ "data-month": key,
505
+ tabIndex: key === active ? 0 : -1,
506
+ "aria-label": monthText.month(longName.format(firstOfKey(key))),
507
+ "aria-selected": selected,
508
+ "aria-disabled": disabled || void 0,
509
+ "aria-current": current ? "date" : void 0,
510
+ onClick: () => {
511
+ if (!disabled) pick(key);
512
+ },
513
+ onKeyDown: onMonthKeyDown,
514
+ className: cn(
515
+ // 44px rows: the touch-target size, and four of them stand as tall
516
+ // as a month of days, so the panel does not jump as the views swap.
517
+ "h-11 rounded px-1 text-sm tabular-nums transition-colors",
518
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset",
519
+ // A --brand ring on a --brand fill exists only in the DOM.
520
+ end && !disabled ? "focus-visible:ring-[var(--brand-contrast)]" : "focus-visible:ring-[var(--brand)]",
521
+ disabled ? "cursor-not-allowed text-[var(--text-placeholder)]" : end ? "bg-[var(--brand)] text-[var(--brand-contrast)] hover:bg-[var(--brand-hover)]" : selected ? "bg-[var(--brand-bg)] font-medium text-[var(--brand-muted)] hover:bg-[var(--brand-bg-hover)]" : "text-[var(--text-primary)] hover:bg-[var(--bg-hover)]",
522
+ current && !selected && !disabled && "ring-1 ring-inset ring-[var(--border-strong)]"
523
+ ),
524
+ children: shortNames[index]
525
+ },
526
+ c
527
+ );
528
+ }) }, row)) })
529
+ ] });
530
+ }
259
531
  function useDatePickerLabels(clearLabel, stepLabels, todayLabel) {
260
532
  const prev = stepLabels?.prev;
261
533
  const next = stepLabels?.next;
@@ -269,54 +541,75 @@ function useDatePickerLabels(clearLabel, stepLabels, todayLabel) {
269
541
  }, [clearLabel, prev, next, todayLabel]);
270
542
  return useKitLabels("datePicker", DEFAULT_DATE_PICKER_LABELS, fromProps);
271
543
  }
272
- function DatePicker({
273
- value,
274
- onChange,
275
- locale: localeProp,
276
- placeholder,
277
- min,
278
- max,
279
- formatOptions,
280
- formatValue,
281
- step,
282
- stepLabels,
283
- today,
284
- todayLabel,
285
- className,
286
- calendarLabels,
287
- label,
288
- clearable,
289
- clearLabel,
290
- disabled,
291
- invalid,
292
- // Named so it reaches the field (and so its trigger) when a step/today row is the
293
- // root and takes the rest of the caller's props.
294
- "aria-required": ariaRequired,
295
- ...rest
296
- }) {
544
+ function withEndHint(field, hint) {
545
+ if (hint === void 0) return field;
546
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
547
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: field }),
548
+ /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center", children: hint })
549
+ ] });
550
+ }
551
+ function DatePicker(props) {
552
+ const {
553
+ value,
554
+ onChange,
555
+ locale: localeProp,
556
+ placeholder,
557
+ min,
558
+ max,
559
+ formatOptions,
560
+ formatValue,
561
+ step,
562
+ stepLabels,
563
+ today,
564
+ todayLabel,
565
+ className,
566
+ calendarLabels,
567
+ monthJump,
568
+ label,
569
+ clearable,
570
+ clearLabel,
571
+ disabled,
572
+ invalid,
573
+ hint,
574
+ error,
575
+ // Named so it reaches the field (and so its trigger) when a step/today row is the
576
+ // root and takes the rest of the caller's props.
577
+ "aria-required": ariaRequired,
578
+ ...rest
579
+ } = props;
297
580
  const locale = useKitLocale(localeProp);
298
581
  const text = useDatePickerLabels(clearLabel, stepLabels, todayLabel);
299
- const render = formatValue ?? ((iso) => formatDate(iso, locale, formatOptions));
582
+ const render = useTriggerFormat("datePicker", locale, formatOptions, formatValue);
583
+ const messages = useFieldMessages({
584
+ hint,
585
+ error,
586
+ invalid,
587
+ describedBy: rest["aria-describedby"],
588
+ ariaInvalid: rest["aria-invalid"]
589
+ });
300
590
  const wrapped = Boolean(step || today);
301
591
  const [triggerAria, wrapperRest] = splitTriggerAria(rest);
302
592
  const field = /* @__PURE__ */ jsx(
303
593
  DateField,
304
594
  {
305
595
  ...wrapped ? triggerAria : rest,
596
+ "aria-describedby": messages.describedBy,
306
597
  "aria-required": ariaRequired,
307
598
  label,
599
+ labelHint: messages.labelHint,
308
600
  clearable,
309
601
  clearLabel: text.clear,
310
602
  panelLabel: text.panel,
311
603
  disabled,
312
- invalid,
604
+ invalid: messages.isInvalid,
313
605
  className: step ? "min-w-0 flex-1" : className,
314
606
  hasValue: Boolean(value),
315
607
  triggerText: value ? render(value) : placeholder ?? "",
316
608
  onClear: () => onChange(""),
317
609
  children: (close) => /* @__PURE__ */ jsx(
318
- MiniCalendar,
610
+ PanelCalendar,
319
611
  {
612
+ monthJump,
320
613
  mode: "single",
321
614
  focusOnOpen: true,
322
615
  from: value,
@@ -333,7 +626,11 @@ function DatePicker({
333
626
  )
334
627
  }
335
628
  );
336
- if (!wrapped) return field;
629
+ const reserve = "error" in props || "hint" in props;
630
+ const endHint = label === void 0 ? messages.labelHint : void 0;
631
+ if (!wrapped) {
632
+ return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve, children: withEndHint(field, endHint) });
633
+ }
337
634
  const target = (days) => value ? addDaysIso(value, days) : "";
338
635
  const outOfBounds = (iso) => Boolean(min && iso < min || max && iso > max);
339
636
  const blocked = (days) => {
@@ -341,7 +638,7 @@ function DatePicker({
341
638
  if (!next || disabled) return true;
342
639
  return outOfBounds(next);
343
640
  };
344
- return (
641
+ const row = (
345
642
  // ONE joined control, not three boxes in a row: the buttons and the field share
346
643
  // their borders (each piece overlaps the previous by a pixel) and only the outer
347
644
  // ends are rounded — the button-group shape, so ‹ date › reads as one field with
@@ -400,6 +697,7 @@ function DatePicker({
400
697
  }
401
698
  )
402
699
  );
700
+ return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve, children: withEndHint(row, endHint) });
403
701
  }
404
702
  function markedPreset(presets, from, to, activeId, controlled) {
405
703
  const matches = (p) => p.from === from && p.to === to;
@@ -477,7 +775,7 @@ function RangePanel({
477
775
  const complete = Boolean(draft.from && draft.to);
478
776
  const summary = drafting && renderDraftSummary ? renderDraftSummary({ from: draft.from, to: draft.to, preset: presets?.[marked] }) : null;
479
777
  const picker = /* @__PURE__ */ jsx(
480
- MiniCalendar,
778
+ PanelCalendar,
481
779
  {
482
780
  ...calendarProps,
483
781
  focusOnOpen: true,
@@ -539,34 +837,45 @@ function RangePanel({
539
837
  ] })
540
838
  );
541
839
  }
542
- function DateRangePicker({
543
- from,
544
- to,
545
- onChange,
546
- locale: localeProp,
547
- placeholder,
548
- min,
549
- max,
550
- formatOptions,
551
- formatValue,
552
- separator = " \u2013 ",
553
- presets,
554
- preset,
555
- commit = "immediate",
556
- renderTrigger,
557
- sheetBackCloses,
558
- renderDraftSummary,
559
- calendarLabels,
560
- label,
561
- clearable,
562
- clearLabel,
563
- disabled,
564
- invalid,
565
- ...rest
566
- }) {
840
+ function DateRangePicker(props) {
841
+ const {
842
+ from,
843
+ to,
844
+ onChange,
845
+ locale: localeProp,
846
+ placeholder,
847
+ min,
848
+ max,
849
+ formatOptions,
850
+ formatValue,
851
+ separator = " \u2013 ",
852
+ presets,
853
+ preset,
854
+ commit = "immediate",
855
+ renderTrigger,
856
+ sheetBackCloses,
857
+ renderDraftSummary,
858
+ calendarLabels,
859
+ monthJump,
860
+ label,
861
+ clearable,
862
+ clearLabel,
863
+ disabled,
864
+ invalid,
865
+ hint,
866
+ error,
867
+ ...rest
868
+ } = props;
567
869
  const locale = useKitLocale(localeProp);
568
870
  const text = useDatePickerLabels(clearLabel, void 0, void 0);
569
- const render = formatValue ?? ((iso) => formatDate(iso, locale, formatOptions));
871
+ const render = useTriggerFormat("dateRangePicker", locale, formatOptions, formatValue);
872
+ const messages = useFieldMessages({
873
+ hint,
874
+ error,
875
+ invalid,
876
+ describedBy: rest["aria-describedby"],
877
+ ariaInvalid: rest["aria-invalid"]
878
+ });
570
879
  const [ownPreset, setOwnPreset] = useState(void 0);
571
880
  const controlled = preset !== void 0;
572
881
  const activeId = controlled ? preset : ownPreset;
@@ -580,16 +889,18 @@ function DateRangePicker({
580
889
  if (presetId === void 0) onChange(f, t);
581
890
  else onChange(f, t, presetId);
582
891
  };
583
- return /* @__PURE__ */ jsx(
892
+ const field = /* @__PURE__ */ jsx(
584
893
  DateField,
585
894
  {
586
895
  ...rest,
896
+ "aria-describedby": messages.describedBy,
587
897
  label,
898
+ labelHint: messages.labelHint,
588
899
  clearable,
589
900
  clearLabel: text.clear,
590
901
  panelLabel: text.rangePanel,
591
902
  disabled,
592
- invalid,
903
+ invalid: messages.isInvalid,
593
904
  width: hasPresets ? 440 : void 0,
594
905
  hasValue: Boolean(from || to),
595
906
  triggerText,
@@ -618,13 +929,14 @@ function DateRangePicker({
618
929
  frame,
619
930
  sheet,
620
931
  commitRange,
621
- calendarProps: { locale, min, max, labels: calendarLabels },
932
+ calendarProps: { locale, min, max, labels: calendarLabels, monthJump },
622
933
  labels: text,
623
934
  renderDraftSummary
624
935
  }
625
936
  )
626
937
  }
627
938
  );
939
+ return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve: "error" in props || "hint" in props, children: withEndHint(field, label === void 0 ? messages.labelHint : void 0) });
628
940
  }
629
941
  export {
630
942
  DatePicker,