@nxgt/material 3.46.0 → 3.48.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 (96) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +3 -3
  3. package/dist/{async-slice-DPM9l8dd.js → async-slice-DlvKCKAa.js} +2 -2
  4. package/dist/{button-DR_EdcfV.js → button-yaltbQmC.js} +1 -1
  5. package/dist/charts.js +3 -3
  6. package/dist/{chip-olzYjs30.js → chip-BqWbbr1b.js} +1 -1
  7. package/dist/{code-editor-CCc-piPv.js → code-editor-C9qBNoYb.js} +4 -4
  8. package/dist/code-editor.js +4 -4
  9. package/dist/{code-language-items-mjN3a33n.js → code-language-items-DAHtfQ7W.js} +2 -2
  10. package/dist/{components-CfttRxBs.js → components-Ox6FHmpx.js} +13953 -13551
  11. package/dist/components.js +15 -15
  12. package/dist/{dialog-DOhEoEP2.js → dialog-CCCcnTIx.js} +1 -1
  13. package/dist/dnd.js +1 -1
  14. package/dist/{dropdown-menu-CFO3E-rO.js → dropdown-menu-Df8785nt.js} +1 -1
  15. package/dist/editor.js +7 -7
  16. package/dist/{empty-state-CTX0gKR3.js → empty-state-DcF4TBzi.js} +1 -1
  17. package/dist/hooks.js +2 -2
  18. package/dist/{i18n-provider-BnVQVqAF.js → i18n-provider-C0fB0sEL.js} +1 -1
  19. package/dist/i18n.js +5 -5
  20. package/dist/{icon-badge-BRys8Tuo.js → icon-badge-aJ22mKGh.js} +1 -1
  21. package/dist/lib/components/ui/collections/filter/query/filter-query-context.d.ts +1 -1
  22. package/dist/lib/components/ui/collections/filter/query/filter-query-model.d.ts +49 -0
  23. package/dist/lib/components/ui/collections/filter/query/types.d.ts +8 -0
  24. package/dist/lib/components/ui/collections/filter/query/use-filter-query-options.d.ts +2 -1
  25. package/dist/lib/components/ui/collections/filter/query/use-filter-query-value.d.ts +1 -0
  26. package/dist/lib/components/ui/collections/filter/query/use-filter-query.d.ts +3 -47
  27. package/dist/lib/components/ui/collections/filter/sections/filter-form-error.d.ts +16 -4
  28. package/dist/lib/components/ui/collections/server-table/types.d.ts +5 -0
  29. package/dist/lib/components/ui/display/timeline/index.d.ts +1 -1
  30. package/dist/lib/components/ui/display/timeline/partials/timeline-day-heading.d.ts +14 -0
  31. package/dist/lib/components/ui/display/timeline/partials/timeline-empty.d.ts +8 -0
  32. package/dist/lib/components/ui/display/timeline/partials/timeline-groups.d.ts +22 -0
  33. package/dist/lib/components/ui/display/timeline/partials/timeline-item-body.d.ts +13 -0
  34. package/dist/lib/components/ui/display/timeline/partials/timeline-item-card.d.ts +5 -0
  35. package/dist/lib/components/ui/display/timeline/partials/timeline-item-rail.d.ts +8 -0
  36. package/dist/lib/components/ui/display/timeline/partials/timeline-item-time.d.ts +12 -0
  37. package/dist/lib/components/ui/display/timeline/partials/timeline-skeleton.d.ts +4 -0
  38. package/dist/lib/components/ui/display/timeline/timeline-item.d.ts +13 -2
  39. package/dist/lib/components/ui/display/timeline/timeline-marker.d.ts +12 -0
  40. package/dist/lib/components/ui/display/timeline/timeline-rows.d.ts +23 -0
  41. package/dist/lib/components/ui/display/timeline/timeline.d.ts +32 -2
  42. package/dist/lib/components/ui/display/timeline/types.d.ts +6 -0
  43. package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
  44. package/dist/lib/components/ui/fields/opening-hours/logic/status.d.ts +13 -2
  45. package/dist/lib/components/ui/fields/opening-hours/opening-hours-summary.d.ts +7 -3
  46. package/dist/lib/components/ui/layout/stepper/partials/header-nav.d.ts +10 -0
  47. package/dist/lib/components/ui/layout/stepper/partials/header-segments.d.ts +6 -0
  48. package/dist/lib/components/ui/layout/stepper/partials/header-summary.d.ts +12 -0
  49. package/dist/lib/components/ui/layout/stepper/partials/stepper-content.d.ts +8 -0
  50. package/dist/lib/components/ui/layout/stepper/partials/stepper-step-text.d.ts +13 -0
  51. package/dist/lib/components/ui/layout/stepper/stepper-connector.d.ts +6 -0
  52. package/dist/lib/components/ui/layout/stepper/stepper-header.d.ts +12 -0
  53. package/dist/lib/components/ui/layout/stepper/stepper-icon.d.ts +5 -0
  54. package/dist/lib/components/ui/layout/stepper/stepper-layout.d.ts +25 -0
  55. package/dist/lib/components/ui/layout/stepper/stepper-step.d.ts +9 -2
  56. package/dist/lib/components/ui/layout/stepper/stepper.d.ts +13 -3
  57. package/dist/lib/i18n/resources/en/en.d.ts +7 -0
  58. package/dist/lib/i18n/resources/en/material.json.d.ts +9 -2
  59. package/dist/lib/i18n/resources/fr/fr.d.ts +7 -0
  60. package/dist/lib/i18n/resources/fr/material.json.d.ts +9 -2
  61. package/dist/lib/i18n/resources/resources.d.ts +14 -0
  62. package/dist/lib/i18n/translator.d.ts +1 -1
  63. package/dist/lib.js +1 -1
  64. package/dist/main.js +21 -21
  65. package/dist/map.js +4 -4
  66. package/dist/material.css +1 -1
  67. package/dist/pdf-reader.js +1 -1
  68. package/dist/print.js +2 -2
  69. package/dist/{public-BmA6r0EK.js → public-zVb_Nq_D.js} +6 -6
  70. package/dist/{rich-code-block-BgPtzSnv.js → rich-code-block-DMWZZJma.js} +4 -4
  71. package/dist/{sortable-provider-CceARBYP.js → sortable-provider-DstbgMVf.js} +1 -1
  72. package/dist/{spinner-7orqNAEy.js → spinner-C4CgDEYm.js} +1 -1
  73. package/dist/{stored-language-BHmxU75w.js → stored-language-IaL1Ftn_.js} +18 -4
  74. package/dist/styles.css +8 -0
  75. package/dist/theme-picker.js +2 -2
  76. package/dist/{theme-toggle-_RJgLHs9.js → theme-toggle-CGW2_K54.js} +1 -1
  77. package/dist/{toolbar-items-BCy6DMzb.js → toolbar-items-CsLGJMEJ.js} +2 -2
  78. package/dist/{translate-material-n0YBXLGp.js → translate-material-v9u-e7Kd.js} +2 -2
  79. package/dist/{translator-B_ue2XEg.js → translator-Dk4_qE6U.js} +1 -1
  80. package/dist/{use-chat-composer-FDmwZSua.js → use-chat-composer-Brcb5f7r.js} +12 -12
  81. package/dist/{use-heading-spy-O6_EATtA.js → use-heading-spy-DjKixjLm.js} +1 -1
  82. package/dist/{use-material-translation-CkPcqI6q.js → use-material-translation-DOkTaWK_.js} +2 -2
  83. package/docs/components/data-display.md +43 -4
  84. package/docs/components/data-table-filter-and-lists.md +28 -1
  85. package/docs/components/form-fields.md +1 -1
  86. package/docs/components/navigation-and-layout.md +66 -23
  87. package/docs/guides/i18n.md +4 -1
  88. package/docs/guides/ssr.md +3 -1
  89. package/docs/previews/data-display-timeline.webp +0 -0
  90. package/docs/previews/data-table-filter-lists-filter.webp +0 -0
  91. package/docs/previews/navigation-layout-stepper.webp +0 -0
  92. package/docs/roadmap.md +24 -0
  93. package/docs/troubleshooting.md +24 -0
  94. package/lib/styles.css +8 -0
  95. package/package.json +1 -1
  96. package/dist/lib/components/ui/fields/opening-hours/logic/zoned.d.ts +0 -10
@@ -1,3 +1,3 @@
1
- import { t as e } from "./public-BmA6r0EK.js";
1
+ import { t as e } from "./public-zVb_Nq_D.js";
2
2
  import { configurePdfReader as t } from "@nxgt/material-core/pdf-reader";
3
3
  export { e as PdfReader, t as configurePdfReader };
package/dist/print.js CHANGED
@@ -1,5 +1,5 @@
1
- import { r as e } from "./i18n-provider-BnVQVqAF.js";
2
- import { t } from "./translate-material-n0YBXLGp.js";
1
+ import { r as e } from "./i18n-provider-C0fB0sEL.js";
2
+ import { t } from "./translate-material-v9u-e7Kd.js";
3
3
  import { Children as n, createContext as r, isValidElement as i, useCallback as a, useContext as o, useEffect as s, useMemo as c, useState as l } from "react";
4
4
  import { jsx as u, jsxs as d } from "react/jsx-runtime";
5
5
  import { resolvePdfFileName as f } from "@nxgt/material-core/pdf-file-name";
@@ -6,18 +6,18 @@ import { c as i, i as a, l as o, n as s, o as c, s as l } from "./dist-lmHmz_bu.
6
6
  import { a as u, o as d } from "./tooltip-CkttDIab.js";
7
7
  import { i as f } from "./dist-C4wtXCjf.js";
8
8
  import { r as p, t as m } from "./in-dialog-Vwkyp-M5.js";
9
- import { C as h, D as g, E as _, O as v, S as y, T as b, _ as x, f as S, g as ee, k as te, r as ne, t as C, u as re, w } from "./dialog-DOhEoEP2.js";
10
- import { c as T, d as ie, f as E, i as ae, l as oe, n as se, o as D, t as ce, u as O } from "./dropdown-menu-CFO3E-rO.js";
11
- import { S as le, a as k, d as A, g as ue, h as de, i as fe, m as pe, n as j, r as me, t as M, u as he, w as ge } from "./toolbar-items-BCy6DMzb.js";
12
- import { t as N } from "./use-material-translation-CkPcqI6q.js";
13
- import { t as _e } from "./button-DR_EdcfV.js";
9
+ import { C as h, D as g, E as _, O as v, S as y, T as b, _ as x, f as S, g as ee, k as te, r as ne, t as C, u as re, w } from "./dialog-CCCcnTIx.js";
10
+ import { c as T, d as ie, f as E, i as ae, l as oe, n as se, o as D, t as ce, u as O } from "./dropdown-menu-Df8785nt.js";
11
+ import { S as le, a as k, d as A, g as ue, h as de, i as fe, m as pe, n as j, r as me, t as M, u as he, w as ge } from "./toolbar-items-CsLGJMEJ.js";
12
+ import { t as N } from "./use-material-translation-DOkTaWK_.js";
13
+ import { t as _e } from "./button-yaltbQmC.js";
14
14
  import { n as ve, t as ye } from "./icon-button-CN9r5TNE.js";
15
15
  import { t as be } from "./useEvent-2fKq-6w8.js";
16
16
  import { n as xe, t as Se } from "./toggle-group-BMJNcFAC.js";
17
17
  import { o as Ce } from "./escape-owner-C4W_sOAU.js";
18
18
  import { n as we } from "./use-slice-reducer-BGkeGtML.js";
19
19
  import { r as Te } from "./use-csp-nonce-ZKs9k-ov.js";
20
- import { n as Ee, t as De } from "./empty-state-CTX0gKR3.js";
20
+ import { n as Ee, t as De } from "./empty-state-DcF4TBzi.js";
21
21
  import { t as Oe } from "./client-only.utils-3nHNzCki.js";
22
22
  import { t as ke } from "./use-scroll-away-PQRFZkT2.js";
23
23
  import { ArrowLeft as Ae, BookOpenText as je, ChevronDown as Me, ChevronLeft as Ne, ChevronRight as Pe, ChevronUp as Fe, Download as Ie, Eraser as Le, FileText as Re, FileWarning as ze, FileX2 as Be, Highlighter as Ve, KeyRound as He, LayoutGrid as Ue, List as We, Loader2 as Ge, Maximize as Ke, MessageSquareText as qe, Minimize as Je, MoreVertical as Ye, MousePointer2 as Xe, MoveHorizontal as Ze, PanelLeft as Qe, Pen as $e, PencilLine as et, Printer as tt, RotateCw as nt, Search as rt, StickyNote as it, Type as at, Underline as ot, Undo2 as st, Volume2 as ct, X as lt, XIcon as ut, ZoomIn as dt, ZoomOut as ft } from "lucide-react";
@@ -1,7 +1,7 @@
1
1
  import { t as e } from "./tooltip-CkttDIab.js";
2
- import { c as t, n, t as r } from "./dropdown-menu-CFO3E-rO.js";
3
- import { t as i } from "./use-material-translation-CkPcqI6q.js";
4
- import { a, i as o, n as s, o as c, t as l } from "./code-language-items-mjN3a33n.js";
2
+ import { c as t, n, t as r } from "./dropdown-menu-Df8785nt.js";
3
+ import { t as i } from "./use-material-translation-DOkTaWK_.js";
4
+ import { a, i as o, n as s, o as c, t as l } from "./code-language-items-DAHtfQ7W.js";
5
5
  import { i as u, n as d, r as f, s as p } from "./dist-C3GR7kJd.js";
6
6
  import { t as m } from "./code-block-spec-CGLKRhwD.js";
7
7
  import { Check as h, ChevronDown as g, Copy as _, Maximize2 as v, WrapText as y } from "lucide-react";
@@ -143,7 +143,7 @@ function M({ node: e, editor: t, updateAttributes: n, editable: r, wrap: a, onWr
143
143
  }
144
144
  //#endregion
145
145
  //#region lib/components/ui/widgets/editor/extensions/code/code-block-open.tsx
146
- var N = x(() => import("./code-editor-CCc-piPv.js").then((e) => e.n).then((e) => ({ default: e.CodeEditor })));
146
+ var N = x(() => import("./code-editor-C9qBNoYb.js").then((e) => e.n).then((e) => ({ default: e.CodeEditor })));
147
147
  function P() {
148
148
  let { t: e } = i();
149
149
  return /* @__PURE__ */ T("div", {
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./utils-BLfntITJ.js";
2
2
  import { t } from "./dist-DVRQkaTK.js";
3
- import { t as n } from "./use-material-translation-CkPcqI6q.js";
3
+ import { t as n } from "./use-material-translation-DOkTaWK_.js";
4
4
  import { t as r } from "./icon-button-CN9r5TNE.js";
5
5
  import { t as i } from "./compose-refs-DZ0iIVF-.js";
6
6
  import { GripVertical as a } from "lucide-react";
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./utils-BLfntITJ.js";
2
2
  import { o as t } from "./tooltip-CkttDIab.js";
3
- import { t as n } from "./use-material-translation-CkPcqI6q.js";
3
+ import { t as n } from "./use-material-translation-DOkTaWK_.js";
4
4
  import { jsx as r } from "react/jsx-runtime";
5
5
  //#region lib/components/ui/feedback/spinner/spinner.tsx
6
6
  var i = t("transition-all duration-500", {
@@ -1167,7 +1167,8 @@ var t = {
1167
1167
  "now-indicator": { label: "Current time: {time}" },
1168
1168
  timeline: {
1169
1169
  label: "Timeline",
1170
- empty: "No activity yet"
1170
+ empty: "No activity yet",
1171
+ events: "{count, plural, one {# event} other {# events}}"
1171
1172
  },
1172
1173
  copy: {
1173
1174
  copy: "Copy",
@@ -1290,7 +1291,13 @@ var t = {
1290
1291
  stepper: {
1291
1292
  step: "Step {step}",
1292
1293
  completed: "Completed",
1293
- error: "Error"
1294
+ error: "Error",
1295
+ "step-of": "Step {step} of {total}",
1296
+ back: "Back",
1297
+ next: "Next",
1298
+ optional: "Optional",
1299
+ attention: "Needs attention",
1300
+ failed: "Steps needing attention: {count}"
1294
1301
  },
1295
1302
  "location-field": {
1296
1303
  placeholder: "No location selected",
@@ -3992,7 +3999,8 @@ var t = {
3992
3999
  "now-indicator": { label: "Heure actuelle : {time}" },
3993
4000
  timeline: {
3994
4001
  label: "Chronologie",
3995
- empty: "Aucune activité"
4002
+ empty: "Aucune activité",
4003
+ events: "{count, plural, one {# événement} other {# événements}}"
3996
4004
  },
3997
4005
  copy: {
3998
4006
  copy: "Copier",
@@ -4115,7 +4123,13 @@ var t = {
4115
4123
  stepper: {
4116
4124
  step: "Étape {step}",
4117
4125
  completed: "Terminée",
4118
- error: "Erreur"
4126
+ error: "Erreur",
4127
+ "step-of": "Étape {step} sur {total}",
4128
+ back: "Précédent",
4129
+ next: "Suivant",
4130
+ optional: "Facultative",
4131
+ attention: "À corriger",
4132
+ failed: "Étapes à corriger : {count}"
4119
4133
  },
4120
4134
  "location-field": {
4121
4135
  placeholder: "Aucun emplacement sélectionné",
package/dist/styles.css CHANGED
@@ -157,3 +157,11 @@
157
157
  bottom: -0.1875rem;
158
158
  transform: rotate(-45deg) scale(0.75);
159
159
  }
160
+
161
+ /* A state change on a Stepper's shape: a small spring-in (no motion under
162
+ * prefers-reduced-motion: the catalogue's reduced-motion rule ends it). */
163
+ @keyframes nxgt-pop {
164
+ from {
165
+ transform: scale(0.55);
166
+ }
167
+ }
@@ -1,10 +1,10 @@
1
1
  import { t as e } from "./utils-BLfntITJ.js";
2
2
  import { a as t, i as n, n as r, o as i, r as a, t as o } from "./bubble-input-B7BVd9fX.js";
3
- import { t as s } from "./use-material-translation-CkPcqI6q.js";
3
+ import { t as s } from "./use-material-translation-DOkTaWK_.js";
4
4
  import { a as c, r as l } from "./icon-sprites-CaYXzOL4.js";
5
5
  import { t as u } from "./use-theme-DMcyJ52N.js";
6
6
  import { a as d, r as f } from "./theme-context-Cofk6vgs.js";
7
- import { t as p } from "./theme-toggle-_RJgLHs9.js";
7
+ import { t as p } from "./theme-toggle-CGW2_K54.js";
8
8
  import { n as m, t as h } from "./nxgt-theme-ZS945iMP.js";
9
9
  import { Check as g } from "lucide-react";
10
10
  import { useContext as _ } from "react";
@@ -1,4 +1,4 @@
1
- import { t as e } from "./use-material-translation-CkPcqI6q.js";
1
+ import { t as e } from "./use-material-translation-DOkTaWK_.js";
2
2
  import { i as t } from "./theme-store-CSl51uNH.js";
3
3
  import { n, t as r } from "./use-theme-DMcyJ52N.js";
4
4
  import { r as i } from "./theme-context-Cofk6vgs.js";
@@ -4,9 +4,9 @@ import { a as i, c as a, i as o, l as s, r as c, s as l } from "./dist-lmHmz_bu.
4
4
  import { b as u, c as d, d as f, f as p, l as m, t as h, u as g, x as _ } from "./tooltip-CkttDIab.js";
5
5
  import { i as v, n as y, r as b, t as x } from "./dist-C4wtXCjf.js";
6
6
  import { a as S, c as C, l as w, o as T, r as ee, s as te, t as E } from "./in-dialog-Vwkyp-M5.js";
7
- import { A as ne, M as re, N as ie, b as ae, d as oe, f as se, i as ce, j as le, l as ue, n as de, o as fe, r as pe, t as me, u as he, y as ge } from "./dropdown-menu-CFO3E-rO.js";
7
+ import { A as ne, M as re, N as ie, b as ae, d as oe, f as se, i as ce, j as le, l as ue, n as de, o as fe, r as pe, t as me, u as he, y as ge } from "./dropdown-menu-Df8785nt.js";
8
8
  import { a as _e, n as ve, r as ye, t as be } from "./dist-B7RjY7SL.js";
9
- import { t as xe } from "./use-material-translation-CkPcqI6q.js";
9
+ import { t as xe } from "./use-material-translation-DOkTaWK_.js";
10
10
  import { t as Se } from "./warn-once-C_e47JM8.js";
11
11
  import { o as Ce } from "./escape-owner-C4W_sOAU.js";
12
12
  import { ChevronLeft as we, ChevronRightIcon as Te, MoreVertical as Ee } from "lucide-react";
@@ -1,5 +1,5 @@
1
- import "./stored-language-BHmxU75w.js";
2
- import { a as e, r as t } from "./translator-B_ue2XEg.js";
1
+ import "./stored-language-IaL1Ftn_.js";
2
+ import { a as e, r as t } from "./translator-Dk4_qE6U.js";
3
3
  //#region lib/i18n/translate-material.ts
4
4
  function n(n, r, i, a) {
5
5
  if (n) for (let e of /* @__PURE__ */ new Set([n, n.split("-")[0]])) {
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./is-production-GLw59WU8.js";
2
- import { a as t, i as n, r, t as i } from "./stored-language-BHmxU75w.js";
2
+ import { a as t, i as n, r, t as i } from "./stored-language-IaL1Ftn_.js";
3
3
  import { t as a } from "./get-CTzJAwfc.js";
4
4
  //#region ../../node_modules/@formatjs/fast-memoize/index.js
5
5
  function o(e, t) {
@@ -7,21 +7,21 @@ import { a as o, c as s, i as c, l, n as u, o as d, r as f, s as p, t as m } fro
7
7
  import { _ as h, a as g, g as _, h as v, m as y, o as b, p as x, t as S, v as C, y as w } from "./tooltip-CkttDIab.js";
8
8
  import { a as T, i as E, n as D, r as O, t as k } from "./dist-C4wtXCjf.js";
9
9
  import { i as A, n as ee, t as j } from "./in-dialog-Vwkyp-M5.js";
10
- import { A as M, C as N, D as te, E as ne, O as P, S as re, T as ie, _ as F, b as ae, f as oe, g as se, k as I, l as ce, m as le, n as ue, o as de, r as fe, s as pe, t as me, u as he, v as ge, w as _e, x as ve, y as ye } from "./dialog-DOhEoEP2.js";
10
+ import { A as M, C as N, D as te, E as ne, O as P, S as re, T as ie, _ as F, b as ae, f as oe, g as se, k as I, l as ce, m as le, n as ue, o as de, r as fe, s as pe, t as me, u as he, v as ge, w as _e, x as ve, y as ye } from "./dialog-CCCcnTIx.js";
11
11
  import { A as be, C as xe, D as Se, E as Ce, O as we, S as Te, T as Ee, _ as De, a as Oe, b as ke, d as Ae, f as je, g as Me, h as Ne, i as Pe, k as Fe, l as Ie, m as Le, n as Re, o as ze, p as Be, r as Ve, s as He, t as Ue, u as We, v as Ge, w as Ke, x as qe, y as Je } from "./floating-ui.dom-KkZSW8_E.js";
12
- import { D as Ye, E as Xe, N as Ze, O as Qe, c as $e, d as et, f as tt, i as nt, k as rt, m as it, n as at, o as ot, p as st, t as ct, u as lt } from "./dropdown-menu-CFO3E-rO.js";
12
+ import { D as Ye, E as Xe, N as Ze, O as Qe, c as $e, d as et, f as tt, i as nt, k as rt, m as it, n as at, o as ot, p as st, t as ct, u as lt } from "./dropdown-menu-Df8785nt.js";
13
13
  import { a as ut, i as dt, n as ft } from "./field-blur-context-Cft9s7Hg.js";
14
- import { C as pt, S as mt, a as ht, c as gt, d as _t, l as vt, n as yt, o as bt, s as xt, u as St } from "./toolbar-items-BCy6DMzb.js";
14
+ import { C as pt, S as mt, a as ht, c as gt, d as _t, l as vt, n as yt, o as bt, s as xt, u as St } from "./toolbar-items-CsLGJMEJ.js";
15
15
  import { a as Ct, i as wt, n as Tt, o as Et, t as Dt } from "./bubble-input-B7BVd9fX.js";
16
16
  import { i as Ot } from "./dist-B7RjY7SL.js";
17
- import "./stored-language-BHmxU75w.js";
18
- import { a as kt } from "./translator-B_ue2XEg.js";
17
+ import "./stored-language-IaL1Ftn_.js";
18
+ import { a as kt } from "./translator-Dk4_qE6U.js";
19
19
  import { h as At } from "./get-CTzJAwfc.js";
20
20
  import { t as jt } from "./isEmpty-F_g3jLf8.js";
21
- import { t as L } from "./use-material-translation-CkPcqI6q.js";
22
- import { t as Mt } from "./spinner-7orqNAEy.js";
21
+ import { t as L } from "./use-material-translation-DOkTaWK_.js";
22
+ import { t as Mt } from "./spinner-C4CgDEYm.js";
23
23
  import { a as Nt } from "./button-tones-BwuVvAmd.js";
24
- import { a as Pt, i as Ft, o as It, r as Lt, t as Rt } from "./button-DR_EdcfV.js";
24
+ import { a as Pt, i as Ft, o as It, r as Lt, t as Rt } from "./button-yaltbQmC.js";
25
25
  import { t as R } from "./icon-button-CN9r5TNE.js";
26
26
  import { a as zt, r as Bt } from "./icon-sprites-CaYXzOL4.js";
27
27
  import { t as Vt } from "./use-ssr-media-query-C6M5m8sf.js";
@@ -35,10 +35,10 @@ import { a as tn, i as nn, o as rn } from "./escape-owner-C4W_sOAU.js";
35
35
  import { n as an } from "./use-slice-reducer-BGkeGtML.js";
36
36
  import { t as on } from "./browser-only-DQ94lWF8.js";
37
37
  import { t as sn } from "./compose-refs-DZ0iIVF-.js";
38
- import { n as cn, r as ln, t as un } from "./chip-olzYjs30.js";
39
- import { n as dn, t as fn } from "./icon-badge-BRys8Tuo.js";
38
+ import { n as cn, r as ln, t as un } from "./chip-BqWbbr1b.js";
39
+ import { n as dn, t as fn } from "./icon-badge-aJ22mKGh.js";
40
40
  import { r as pn } from "./use-csp-nonce-ZKs9k-ov.js";
41
- import { t as mn } from "./empty-state-CTX0gKR3.js";
41
+ import { t as mn } from "./empty-state-DcF4TBzi.js";
42
42
  import { t as hn } from "./skeleton-DSdtr2qc.js";
43
43
  import { H as gn, V as _n, X as vn, bt as yn, it as bn, lt as xn, n as Sn, t as Cn, xt as wn, yt as Tn } from "./dist-moutbfbd.js";
44
44
  import { t as En } from "./markdown-Dw_uH7j7.js";
@@ -11082,7 +11082,7 @@ var RS = (e = {}) => Dn({
11082
11082
  let [{ default: t }, { lowlight: n }, { richCodeBlock: r }] = await Promise.all([
11083
11083
  import("./dist-CRMFGjng.js"),
11084
11084
  import("./lowlight-OtcjU2Sa.js"),
11085
- import("./rich-code-block-BgPtzSnv.js")
11085
+ import("./rich-code-block-DMWZZJma.js")
11086
11086
  ]);
11087
11087
  return [r(t, {
11088
11088
  lowlight: n,
@@ -1,4 +1,4 @@
1
- import { r as e } from "./i18n-provider-BnVQVqAF.js";
1
+ import { r as e } from "./i18n-provider-C0fB0sEL.js";
2
2
  import { _ as t, g as n, h as r, n as i, v as a, y as o } from "./number.utils-BG_eEt5g.js";
3
3
  import { useCallback as s, useEffect as c, useMemo as l, useRef as u, useState as d } from "react";
4
4
  import { busySettler as f, busySettler as p, createSubmitGuard as m, createSubmitGuard as h } from "@nxgt/material-core/submit-guard";
@@ -1,5 +1,5 @@
1
- import { r as e } from "./i18n-provider-BnVQVqAF.js";
2
- import { t } from "./translate-material-n0YBXLGp.js";
1
+ import { r as e } from "./i18n-provider-C0fB0sEL.js";
2
+ import { t } from "./translate-material-v9u-e7Kd.js";
3
3
  import { useCallback as n } from "react";
4
4
  //#region lib/i18n/use-material-translation.ts
5
5
  function r() {
@@ -24,7 +24,7 @@ from `@nxgt/material/components`.
24
24
  | <img src="../previews/data-display-entityheader.webp" width="96" alt=""> | [EntityHeader](#entityheader) | Page header with status, metadata and actions |
25
25
  | <img src="../previews/data-display-listtile.webp" width="96" alt=""> | [ListTile](#listtile) | Row with leading / trailing slots, row actions, chips and a divided variant |
26
26
  | <img src="../previews/data-display-accordioncard.webp" width="96" alt=""> | [AccordionCard](#accordioncard) | Accordion rendered from `items` |
27
- | <img src="../previews/data-display-timeline.webp" width="96" alt=""> | [Timeline](#timeline) | Vertical event timeline with relative times |
27
+ | <img src="../previews/data-display-timeline.webp" width="96" alt=""> | [Timeline](#timeline) | Vertical event timeline: shaped markers, cards, alternating sides, day groups (`DaySeparator` headings, words from `material.day-separator.*`), relative times; `layout="auto"` needs a parent with a definite width (`rail` in a `w-fit` parent) |
28
28
  | <img src="../previews/data-display-changehistory.webp" width="96" alt=""> | [ChangeHistory](#changehistory) | History of the changes made to anything, as a rail or as cards |
29
29
  | <img src="../previews/data-display-zonedtime.webp" width="96" alt=""> | [ZonedTime](#zonedtime) | A moment written in a given time zone, identical on the server and the client |
30
30
  | <img src="../previews/data-display-eventchip.webp" width="96" alt=""> | [EventChip](#eventchip) | Calendar event pill, soft, solid or outlined |
@@ -965,7 +965,12 @@ import { AccordionCard } from '@nxgt/material/components';
965
965
 
966
966
  ![Timeline](../previews/data-display-timeline.webp)
967
967
 
968
- Vertical event timeline with toned icons and relative times.
968
+ Vertical event timeline with toned markers and relative times. Each marker is
969
+ 44px and takes a shape by tone (circle, squircle, cookie, clover, diamond,
970
+ burst) in the tone's container colour; an item with `children` is a rounded
971
+ card with a subtle tone bar. Once the timeline's own container is 48rem wide
972
+ (a container query, not the viewport) the two sides alternate; narrower, it is
973
+ a single rail. `grouped` opens each day with a `DaySeparator` heading.
969
974
 
970
975
  ```tsx
971
976
  import { Package, Pencil } from 'lucide-react';
@@ -984,11 +989,45 @@ Parts: `Timeline`, `TimelineItem` (one row, for your own list),
984
989
 
985
990
  | Prop | Type | Default | Effect |
986
991
  | --- | --- | --- | --- |
987
- | `items` | `TimelineItemData[]` | — | `title`, `description`, `timestamp`, `icon` or `avatar`, `tone`, `children` |
992
+ | `items` | `TimelineItemData[]` | — | `title`, `description`, `timestamp`, `icon` or `avatar`, `tone`, `children` (rendered as a card) |
993
+ | `grouped` | `boolean` | `false` | a heading per day ("Today", "Yesterday", a weekday or a date: a `DaySeparator`, real `<h3>`, with a `<time dateTime>` and its count); items keep the order given |
994
+ | `headingLevel` | `2 \| 3 \| 4 \| 5 \| 6` | `3` | the level of the day headings |
995
+ | `layout` | `'auto' \| 'rail'` | `'auto'` | `'auto'` alternates sides in a wide container (it measures its own container: its parent needs a definite width, see below); `'rail'` never does |
996
+ | `timeZone` | `string` | — | the zone the days are cut in |
997
+ | `now` | `Date` | — | the reference instant for "Today" and "Yesterday" |
988
998
  | `loading` | `boolean` | `false` | skeleton rows |
989
999
  | `empty` | `ReactNode` | "No activity yet" | shown when `items` is empty |
990
1000
 
991
- **Storybook:** `Data display/Timeline` · **Vue:** `Timeline`, `TimelineItem`, `RelativeTime` (without `now`, `tooltip`, `focusable` and `ref`, React only)
1001
+ ```tsx
1002
+ // Grouped on the server too: fix the zone and the reference instant.
1003
+ <Timeline items={items} grouped timeZone="UTC" now={new Date('2026-03-15T12:00:00Z')} aria-label="Order history" />
1004
+
1005
+ // One rail, never alternating sides.
1006
+ <Timeline items={items} layout="rail" aria-label="Order history" />
1007
+ ```
1008
+
1009
+ **Server rendering.** Without both `timeZone` and `now`, `grouped` renders no
1010
+ day headings on the server and on the first client render, and adds them once
1011
+ mounted (and logs a development warning once). With both, the headings render
1012
+ on the server too. The list is one flat `<ol>`: each heading sits inside the first `<li>` of
1013
+ its day, ahead of the item's content (a list may only hold `<li>`s, so a
1014
+ standalone heading row fails axe), never around the items, so an item keeps its
1015
+ parent, its key and its state when they appear (a counter inside an item is not reset).
1016
+ **Width.** `layout="auto"` is a container query on the Timeline itself, so its
1017
+ parent needs a definite width (a block, a grid cell, a fixed width). In a
1018
+ shrink-to-fit parent (`w-fit`, an inline flex item) it collapses to 0 wide:
1019
+ use `layout="rail"` there, which sets no container. In right-to-left the wide
1020
+ layout mirrors, time labels included. `now` also fixes the relative times
1021
+ ("5 minutes ago") of the items. **Accessibility:** the list keeps its
1022
+ `aria-label`, markers are decorative, each day heading is a real heading whose
1023
+ count reads as "N events", and every item of a day has `aria-describedby`
1024
+ pointing to that heading (a nested list labelled by it would put the items
1025
+ under a new parent). **Migrating:** the new look is the default; pass
1026
+ `layout="rail"` for a single rail. Children now render as a card, not as text
1027
+ under the title. New key: `material.timeline.events`; the day words come from
1028
+ `material.day-separator.today` and `yesterday`.
1029
+
1030
+ **Storybook:** `Data display/Timeline` · **Vue:** `Timeline`, `TimelineItem`, `RelativeTime` (without `now`, `tooltip`, `focusable` and `ref`, React only); the redesign and `grouped`, `layout`, `timeZone`, `now` are React only for now (#1810)
992
1031
 
993
1032
  ---
994
1033
 
@@ -1890,6 +1890,32 @@ one. The page clears it when the condition changes, by passing no error. The
1890
1890
  words are `material.filter.error.*`; `fieldErrors(errors, model, locked)` in
1891
1891
  the core lists what the bar shows.
1892
1892
 
1893
+ #### The refused fields' words under the bar
1894
+
1895
+ The pill only reads "Invalid", so when a refused query leaves the list empty
1896
+ the page would show a red pill and nothing that says what to fix (WCAG 3.3.1,
1897
+ 3.3.3). By default the bar also says the words, in the place `formError` uses:
1898
+ one error `Alert` under the bar with a line per refused field that names it,
1899
+ "Period: choose 366 days or fewer." `formError` comes first when both are
1900
+ set. It is one Alert, not one per field, and it is no live region: the bar's
1901
+ one tells the refusal once, as before. The lines are plain text.
1902
+
1903
+ ```tsx
1904
+ <FilterBar model={model} params={params} onParamsChange={setParams}
1905
+ errors={{ period: 'Choose 366 days or fewer.' }} /> // pill + the line under the bar
1906
+ <FilterBar ... errors={...} errorSummary={false} /> // the pills only, as before this release
1907
+ ```
1908
+
1909
+ In the facets panel each refused facet already shows its message in its
1910
+ section, so there the Alert holds `formError` and the lines of the refused
1911
+ fields that have no section (a plain chip would read "Invalid" alone), never
1912
+ a field line twice; the bar and the facets on a phone (whose sections sit in
1913
+ the sheet) keep the full summary.
1914
+
1915
+ `errorSummary` (default `true`) is on `Filter`, `FilterBar` and
1916
+ `ServerTable`'s `filter`: `<ServerTable filter={{ model, errors, errorSummary: false }} />`
1917
+ keeps the pills only.
1918
+
1893
1919
  #### A refused search, and a refusal of no field
1894
1920
 
1895
1921
  `errors` is keyed by field id, so it cannot name the search box nor carry a
@@ -1913,7 +1939,8 @@ refusal that belongs to no field. Two more props, on the same three surfaces
1913
1939
  - **`formError`** (a node) is a refusal that belongs to no field: one error
1914
1940
  `Alert` under the bar, in place (under the bar's row in `FilterBar`, between
1915
1941
  the band and the chips in `ServerTable`, under the search in the facets
1916
- panel). It is no live region of its own.
1942
+ panel). It is no live region of its own. The refused fields' lines join it
1943
+ (`errorSummary`, above).
1917
1944
 
1918
1945
  Both are told by the bar's one polite live region, the same refusal path as a
1919
1946
  field's, once and after the count: "Search: Not a valid item." and the
@@ -1830,7 +1830,7 @@ summary shows a quiet "Hours not set" (`empty` replaces the text,
1830
1830
  | --- | --- | --- | --- |
1831
1831
  | `data` | `OpeningHour[] \| null` | `[]` | the hours |
1832
1832
  | `now` | `Date` | the clock | the moment read as now |
1833
- | `timeZone` | `string` | the viewer's | the IANA zone of the place, resolved with `Intl.DateTimeFormat` |
1833
+ | `timeZone` | `string` | the viewer's | the IANA zone of the place, read with the shared `@nxgt/material-core/zone` helpers. A name `Intl` does not know is read as `UTC`, like `DateField`'s `timeZone`, never as the viewer's clock (so the status agrees with the date fields for the same string) |
1834
1834
  | `locale` | `string` | the `I18nProvider` language, else `en` | day and time names |
1835
1835
  | `weekStartsOn` | `0`-`6` | the locale's | first day of the week |
1836
1836
  | `label` | `string` | "Opening Hours" | names the region |
@@ -21,7 +21,7 @@ documentation-site shell. Everything is imported from
21
21
  | <img src="../previews/navigation-layout-pager.webp" width="96" alt=""> | [Pager](#pager) | Previous / next cards |
22
22
  | <img src="../previews/navigation-layout-seealso.webp" width="96" alt=""> | [SeeAlso](#seealso) | Related links |
23
23
  | <img src="../previews/navigation-layout-toc.webp" width="96" alt=""> | [Toc](#toc) | On-this-page outline |
24
- | <img src="../previews/navigation-layout-stepper.webp" width="96" alt=""> | [Stepper](#stepper) | Clickable steps with progress |
24
+ | <img src="../previews/navigation-layout-stepper.webp" width="96" alt=""> | [Stepper](#stepper) | Clickable steps with progress: shaped indicators, optional steps, a phone header |
25
25
  | <img src="../previews/navigation-layout-steps.webp" width="96" alt=""> | [Steps](#steps) | Numbered editorial steps |
26
26
  | <img src="../previews/navigation-layout-hero.webp" width="96" alt=""> | [Hero](#hero) | Landing band |
27
27
  | <img src="../previews/navigation-layout-doc.webp" width="96" alt=""> | [Doc](#doc) | Documentation site shell |
@@ -657,23 +657,41 @@ const items: TocItem[] = [
657
657
 
658
658
  ![Stepper](../previews/navigation-layout-stepper.webp)
659
659
 
660
- Clickable horizontal or vertical steps with status and progress; compact on mobile.
660
+ Clickable horizontal or vertical steps with status and progress. The look is
661
+ expressive: the current step is a cookie, a completed one a filled circle with
662
+ a check, an upcoming one a muted outlined circle and a failed one a cookie in
663
+ the error container, joined by thick pill tracks that fill with the spatial
664
+ spring (no motion under `prefers-reduced-motion`). Below `sm` a header card
665
+ replaces the steps.
661
666
 
662
667
  ```tsx
663
668
  import { CreditCard, Truck, User } from 'lucide-react';
664
- import { Stepper, TooltipProvider } from '@nxgt/material/components';
669
+ import { Stepper } from '@nxgt/material/components';
670
+
671
+ <Stepper
672
+ active={active}
673
+ onChange={setActive}
674
+ steps={[
675
+ { icon: <User />, title: 'Account', description: 'Your profile details.' },
676
+ { icon: <Truck />, title: 'Shipping', status: 'completed' },
677
+ { icon: <CreditCard />, title: 'Payment' },
678
+ ]}
679
+ />
680
+ ```
665
681
 
666
- <TooltipProvider>
667
- <Stepper
668
- active={active}
669
- onChange={setActive}
670
- steps={[
671
- { icon: <User />, title: 'Account', description: 'Your profile details.' },
672
- { icon: <Truck />, title: 'Shipping', status: 'completed' },
673
- { icon: <CreditCard />, title: 'Payment' },
674
- ]}
675
- />
676
- </TooltipProvider>
682
+ An optional step with a card under it, and Back / Next in the phone header
683
+ (they call `onChange(active ± 1)`):
684
+
685
+ ```tsx
686
+ <Stepper
687
+ active={active}
688
+ onChange={setActive}
689
+ steps={[
690
+ { title: 'Account' },
691
+ { title: 'Address', optional: true, content: <p>Skip this if you pick up in store.</p> },
692
+ { title: 'Payment' },
693
+ ]}
694
+ />
677
695
  ```
678
696
 
679
697
  Parts: `Stepper`, `StepperIndicator` (the progress bar alone: `current`,
@@ -681,10 +699,10 @@ Parts: `Stepper`, `StepperIndicator` (the progress bar alone: `current`,
681
699
 
682
700
  | Prop | Type | Default | Effect |
683
701
  | --- | --- | --- | --- |
684
- | `steps` | `{ icon?; title; description?; status? }[]` | — | `status`: `'completed' \| 'error' \| 'upcoming'`, else derived from `active` |
685
- | `active` | `number` | `0` | current step; its `description` shows under the bar |
702
+ | `steps` | `{ icon?; title; description?; status?; optional?; content? }[]` | — | `status`: `'completed' \| 'error' \| 'upcoming'`, else derived from `active`. `optional` adds "· Optional" to the label; `content` is a tinted card shown under the current step |
703
+ | `active` | `number` | `0` | current step; its `description` shows under the steps (in the header card on a phone) |
686
704
  | `onChange` | `(index: number) => void` | — | makes steps clickable |
687
- | `orientation` | `'horizontal' \| 'vertical' \| 'responsive'` | `'horizontal'` | `'vertical'`: a column from `md`, phones get the compact bar. `'responsive'`: every step in a column below `sm` (640px), a row from `sm` |
705
+ | `orientation` | `'horizontal' \| 'vertical' \| 'responsive'` | `'horizontal'` | `'vertical'`: a column from `sm` (640px), phones get the header card. `'responsive'`: every step in a column below `sm` (640px), a row from `sm` |
688
706
  | `renderStepLabel` | `(step, index) => ReactNode` | — | replaces the "Step n" caption |
689
707
  | `name` | `string` | — | the stepper's `data-pw` (`stepper` without it), and the prefix of each step's: `<name>-step-N` instead of `step-N` |
690
708
 
@@ -692,12 +710,37 @@ Each step is an `<li>` with `data-pw="step-N"` (`<name>-step-N` with `name`),
692
710
  N counted from 0, for tests to select; the current step's button carries
693
711
  `aria-current="step"`, and a completed or failed step is announced as such.
694
712
 
695
- A server renders the desktop layout (every step), as does a hydrating client;
696
- a phone switches to the compact bar right after hydrating (with
697
- `orientation="responsive"`, to the column of every step). A page rendered
698
- only in the browser starts on the real layout.
699
-
700
- **Storybook:** `Navigation & layout/Stepper` · **Vue:** `Stepper`
713
+ Below `sm` a header card shows "Step 3 of 5", the title, the description and a
714
+ segmented progress bar (one segment per step, toned by state); with `onChange`
715
+ it also has Back and Next buttons, which stay focusable but inactive (`aria-disabled`) at the ends. Titles clamp to two
716
+ lines. The info tooltip on the current step is gone: read the description
717
+ under the steps.
718
+
719
+ **Server rendering.** The layout is chosen by CSS breakpoints, not by the
720
+ screen width in JavaScript, so the server and the client render the same
721
+ markup and nothing switches after hydration. Both layouts are in the markup
722
+ and the unused one is hidden; ids stay unique.
723
+
724
+ **Accessibility.** The steps are a list, the current step's button carries
725
+ `aria-current="step"`, a completed or failed step is announced as such, and
726
+ steps are focusable when `onChange` is given. The header's progress bar is
727
+ decorative: the "Step n of N" text carries the meaning. The live header
728
+ announces a failed current step and the number of failed steps; Back and Next
729
+ use `aria-disabled` and stay focusable at the ends.
730
+
731
+ **Migrating.** The new look is the default and the props are unchanged;
732
+ `optional` and `content` are additive. Update any test that selected the old
733
+ info button on the current step. New `material.stepper.*` keys: `step-of`,
734
+ `back`, `next`, `optional`, `attention`, `failed`. The `attention` text ("Needs attention") is shown under the title of a failed step, as a visual cue only: the announced status stays "Error".
735
+
736
+ Migration notes:
737
+
738
+ - `data-orientation` now repeats the `orientation` prop; a `responsive` Stepper no longer reports `vertical` or `horizontal` by width.
739
+ - Below 640px the horizontal step list is hidden and the header card replaces it.
740
+ - `horizontal` and `vertical` switch at `sm` (640px), not `md` (768px).
741
+ - `Stepper` no longer renders `StepperIndicator` (still exported).
742
+
743
+ **Storybook:** `Navigation & layout/Stepper` · **Vue:** `Stepper`, with the earlier look: the redesign, `optional` and `content` are React only for now (#1810)
701
744
 
702
745
  ---
703
746
 
@@ -334,7 +334,10 @@ names of its −/+ buttons, "Increase hours" / "Decrease hours" /
334
334
  "Increase minutes" / "Decrease minutes"
335
335
  (`material['duration-field']['increase-hours']` and the three others); the status a
336
336
  `Stepper` step announces after its title, "Completed" or "Error"
337
- (`material.stepper.completed` / `error`, "Terminée" / "Erreur" in French); and
337
+ (`material.stepper.completed` / `error`, "Terminée" / "Erreur" in French); the
338
+ Stepper's phone header (`material.stepper.step-of`, `back`, `next`, `optional`,
339
+ `attention`, `failed`) and the Timeline's day-heading count (`material.timeline.events`; its
340
+ "Today" and "Yesterday" are `DaySeparator`'s); and
338
341
  the pagination buttons' names and text: `PaginationPrevious` /
339
342
  `PaginationNext`'s "Previous" / "Next" (`material.pagination.previous` /
340
343
  `next`), `PaginationFirst` / `PaginationLast`'s "First" / "Last"
@@ -167,8 +167,10 @@ State the server cannot know must be resolved the same way on both sides:
167
167
  | Language | no `localStorage`: `defaultLanguage` | Resolve it from the request and pass `initialLanguage` to `I18nProvider`. See [i18n](i18n.md#server-rendering) |
168
168
  | Theme | no preference: light | An inline boot script in `<head>`, and `suppressHydrationWarning` on `<html>`. See [theming](theming.md#no-flash-on-load-a-boot-script) |
169
169
  | `formatAmount`, `formatDate` | the server's locale and time zone, unless you pass them | Use `useFormatters({ timeZone })`, which follows the `I18nProvider` language, or pass `locale` and `timeZone` (`createFormatters` binds them). A date-only `YYYY-MM-DD` is the same everywhere. See [printing](printing.md#formatamount-and-formatdate) |
170
- | Screen width, `prefers-color-scheme` (`useIsMobile`, `useTheme`, `AppHeader`, `DataTable`, `TimeField`, `Stepper`, `PaneLayout`, `ListDetailsLayout`, the code blocks, …) | no screen: a desktop, light | Nothing: a hydrating client renders the same, then switches on a phone or a dark screen |
170
+ | Screen width, `prefers-color-scheme` (`useIsMobile`, `useTheme`, `AppHeader`, `DataTable`, `TimeField`, `PaneLayout`, `ListDetailsLayout`, the code blocks, …) | no screen: a desktop, light | Nothing: a hydrating client renders the same, then switches on a phone or a dark screen |
171
171
  | An attribute's `DATETIME` / `TIME` instant (`AttributesSummary`, `AttributesEditor`), the opening hours' first day of the week | the server's time zone and Intl data differ from the browser's | Nothing: the instant is written in UTC and the week starts on the language's first day until mount, then the viewer's zone and the locale's week info take over, so hydration matches |
172
+ | `Stepper` layout, `Timeline` sides | CSS breakpoints and a container query, no screen width in JavaScript | Nothing: server and client markup are the same |
173
+ | `Timeline` `grouped` | the server's time zone and clock differ from the browser's | Pass `timeZone` and `now` to group on the server too; without them the day headings appear after mount (the items do not remount) |
172
174
  | Step form (`createStepFormSlice`) | no `localStorage`: step 0 | Nothing with `useSliceReducer`: a hydrating client renders step 0, then resumes. A slice in a Redux store: see [forms](forms.md#a-multi-step-form) |
173
175
  | Zod messages | no `localStorage`: English | Pass the request's language, `zodLocaleError({ language })`, where the server formats messages. See [forms](forms.md#validation-messages) |
174
176
 
package/docs/roadmap.md CHANGED
@@ -330,6 +330,30 @@ version they shipped in, and planned entries may name the major they target.
330
330
 
331
331
  ## Shipped
332
332
 
333
+ - **A refused field says why** (3.48.0) — the filter bar shows the words of a
334
+ refused field under it, in one error `Alert`: "Period: choose 366 days or
335
+ fewer.", after `formError`, so a refused, empty list no longer shows a red
336
+ "Invalid" pill and no reason. `errorSummary` (on by default) is on `Filter`,
337
+ `FilterBar` and `ServerTable`'s `filter`; `false` keeps the pills only. The
338
+ facets panel keeps each message inline and adds a line only for a field with
339
+ no section. React only for now; the Vue twin is a `vue` issue.
340
+ [Filter errors](components/data-table-filter-and-lists.md#filter-bar) ·
341
+ [Troubleshooting](troubleshooting.md)
342
+
343
+ - **Stepper and Timeline, expressive** — both have a new look by default, with
344
+ the same props. `Stepper` shows the current step as a cookie, a completed one
345
+ as a circle with a check and a failed one in the error container, joined by
346
+ thick tracks that fill with a spring; below `sm` a header card ("Step 3 of
347
+ 5", a segmented bar, Back and Next with `onChange`) replaces the steps, and
348
+ the layout no longer depends on JavaScript, so the server and the client
349
+ match. `Step` gains `optional` and `content`. `Timeline` has shaped markers
350
+ by tone, cards for items with `children`, alternating sides in a wide
351
+ container (`layout="rail"` for one rail) and `grouped` day headings (`DaySeparator`, level
352
+ set with `headingLevel`), with
353
+ `timeZone` and `now` to group on the server. React only for now; the Vue
354
+ twin is a `vue` issue.
355
+ [Stepper](components/navigation-and-layout.md#stepper) ·
356
+ [Timeline](components/data-display.md#timeline)
333
357
  - **Two-step verification** — the pieces every app rebuilt for a one-time
334
358
  code. `VerificationCode` is the form (app or e-mailed code, "Use a recovery
335
359
  code", resend, wrong with the tries left, expired, busy, locked, throttled