@nxgt/material 3.90.0 → 3.92.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 (91) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/{alert-dialog-BFk4ye-3.js → alert-dialog-Bz5PlYKp.js} +1 -1
  4. package/dist/{async-slice-gGyfyUw2.js → async-slice-veSVxKqt.js} +1 -1
  5. package/dist/{button-C5OEq9bi.js → button-a3tH3pq4.js} +1 -1
  6. package/dist/{calculator-Dg_L6d3R.js → calculator-BtuKV3PK.js} +10 -10
  7. package/dist/calculator-field.js +6 -6
  8. package/dist/{calculator-segment-CvAaDqKf.js → calculator-segment-CyB9IhEq.js} +1 -1
  9. package/dist/calculator.js +1 -1
  10. package/dist/charts.js +3 -3
  11. package/dist/{chip-DOxFA4BI.js → chip-BwGvGx_S.js} +2 -2
  12. package/dist/{code-editor-tiAjhXW-.js → code-editor-BLkmEoCi.js} +4 -4
  13. package/dist/code-editor.js +4 -4
  14. package/dist/{code-language-items-CcdzQvLT.js → code-language-items-DhAC_tCs.js} +2 -2
  15. package/dist/{components-HQy9UW9D.js → components-DX4aHtgP.js} +17850 -17677
  16. package/dist/components.js +38 -38
  17. package/dist/{conversion-variant-4gCdFWV-.js → conversion-variant-C4t7aH9d.js} +3 -3
  18. package/dist/{currency-field-CIqe7Wg4.js → currency-field-D0UQb5pn.js} +5 -5
  19. package/dist/{dialog-d6Kdf5wc.js → dialog-vQMypIOm.js} +3 -3
  20. package/dist/dnd.js +1 -1
  21. package/dist/{dropdown-menu-DO5kUvof.js → dropdown-menu-B2ctUFti.js} +1 -1
  22. package/dist/editor.js +7 -7
  23. package/dist/{empty-state-DQnICuun.js → empty-state-Bs44jnWk.js} +1 -1
  24. package/dist/{financial-variant-D80C1hVD.js → financial-variant-B5iZ3pYf.js} +5 -5
  25. package/dist/{hooks-C-yLDF39.js → hooks-CJtRFDYD.js} +2 -2
  26. package/dist/hooks.js +2 -2
  27. package/dist/{hover-card-DU3TAME4.js → hover-card-B8PYUsv_.js} +1 -1
  28. package/dist/i18n.js +3 -3
  29. package/dist/{icon-badge-BGczZ4Hc.js → icon-badge-YT98b2Vx.js} +1 -1
  30. package/dist/{icon-button-D0xjBCst.js → icon-button-BylI02aX.js} +1 -1
  31. package/dist/{input-group-CSlXMFxu.js → input-group-CiayHfBN.js} +1 -1
  32. package/dist/lib/components/ui/collections/day-grouped-list/day-grouped-list.d.ts +30 -2
  33. package/dist/lib/components/ui/collections/day-grouped-list/index.d.ts +1 -2
  34. package/dist/lib/components/ui/collections/day-grouped-list/partials/day-group-section.d.ts +17 -0
  35. package/dist/lib/components/ui/collections/day-grouped-list/use-day-groups.d.ts +24 -0
  36. package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
  37. package/dist/lib/components/ui/layout/sticky-action-bar/sticky-action-bar.d.ts +3 -1
  38. package/dist/lib/components/ui/layout/sticky-action-bar/use-bar-clearance.d.ts +10 -0
  39. package/dist/lib/components/ui/media/file-list/file-list-describe.d.ts +8 -0
  40. package/dist/lib/components/ui/media/file-list/file-list-field-row.d.ts +4 -1
  41. package/dist/lib/components/ui/media/file-list/file-list-field.d.ts +13 -0
  42. package/dist/lib/components/ui/media/file-list/index.d.ts +1 -1
  43. package/dist/lib/components/ui/media/file-list/partials/file-list-items.d.ts +5 -1
  44. package/dist/lib/components/ui/media/file-list/partials/file-list-move-buttons.d.ts +9 -0
  45. package/dist/lib/components/ui/media/file-list/partials/file-list-row-actions.d.ts +3 -1
  46. package/dist/lib/components/ui/media/file-list/types.d.ts +9 -0
  47. package/dist/lib/components/ui/media/file-list/use-file-list-field.d.ts +7 -1
  48. package/dist/lib/components/ui/media/file-list/use-file-list-move.d.ts +24 -0
  49. package/dist/lib/components/ui/media/upload/network-upload-field/network-upload-item.d.ts +7 -0
  50. package/dist/lib/components/ui/widgets/editor/extensions/marks/compact-mark-buttons.d.ts +5 -1
  51. package/dist/lib/components/ui/widgets/editor/kit/editor-features.d.ts +2 -1
  52. package/dist/lib/components/ui/widgets/editor/kit/features/marks.d.ts +6 -1
  53. package/dist/lib/i18n/resources/en/en.d.ts +3 -0
  54. package/dist/lib/i18n/resources/en/material.json.d.ts +4 -1
  55. package/dist/lib/i18n/resources/fr/fr.d.ts +3 -0
  56. package/dist/lib/i18n/resources/fr/material.json.d.ts +4 -1
  57. package/dist/lib/i18n/resources/resources.d.ts +6 -0
  58. package/dist/lib/i18n/translator.d.ts +1 -1
  59. package/dist/lib.js +1 -1
  60. package/dist/main.js +54 -54
  61. package/dist/map.js +7 -7
  62. package/dist/pdf-reader.js +1 -1
  63. package/dist/{percent-field-DyJ2yOH4.js → percent-field-DuoZieW9.js} +1 -1
  64. package/dist/{picker-surface-CnlOKQ3D.js → picker-surface-BKzM6TWN.js} +4 -4
  65. package/dist/{popover-BevReSHi.js → popover-ukgGm5B6.js} +1 -1
  66. package/dist/{pos-types-BrZBX0Zg.js → pos-types-BNXbls3v.js} +1 -1
  67. package/dist/{pos-variant-G12HCSfQ.js → pos-variant-CZ3OZtPq.js} +4 -4
  68. package/dist/print.js +1 -1
  69. package/dist/{programmer-variant-WWLwTGRF.js → programmer-variant-DVu-pYhB.js} +2 -2
  70. package/dist/{public-C1a6wQ6o.js → public-DtXwn8bx.js} +9 -9
  71. package/dist/{rich-code-block-Dh9J-VZ8.js → rich-code-block-DUaSLxLT.js} +5 -5
  72. package/dist/{scientific-variant-BvutlF8a.js → scientific-variant-Ku9feVN1.js} +2 -2
  73. package/dist/{sortable-provider-BrA5tfJX.js → sortable-provider-DIb1HgZA.js} +2 -2
  74. package/dist/{spinner-JnLLiLIO.js → spinner-CHWFXCfd.js} +1 -1
  75. package/dist/{tabs-dXCZGShv.js → tabs-BideU0Rb.js} +1 -1
  76. package/dist/theme-picker.js +2 -2
  77. package/dist/{theme-toggle-BmcK6mXV.js → theme-toggle-DUQTEe1y.js} +1 -1
  78. package/dist/{toolbar-items-B-kMYsDT.js → toolbar-items-azkXY5w2.js} +4 -4
  79. package/dist/{translate-material-BmpcP1p1.js → translate-material-d8Q5K5a_.js} +1 -1
  80. package/dist/{translator-CfoXTrZd.js → translator-CxyFsfO0.js} +8 -2
  81. package/dist/{use-chat-composer-DFD_eF-r.js → use-chat-composer-FACltVyX.js} +32 -31
  82. package/dist/{use-heading-spy-BcNK1qvq.js → use-heading-spy-DHd5TScW.js} +4 -4
  83. package/dist/{use-material-translation-DoymV6IP.js → use-material-translation-DA5ECZfA.js} +1 -1
  84. package/dist/{use-return-focus-CLEnhfka.js → use-return-focus-CAAvJ6p5.js} +1 -1
  85. package/docs/components/data-table-filter-and-lists.md +32 -0
  86. package/docs/components/feedback-and-status.md +9 -1
  87. package/docs/components/media-and-files.md +16 -0
  88. package/docs/components/navigation-and-layout.md +5 -0
  89. package/docs/components/rich-widgets.md +15 -0
  90. package/docs/troubleshooting.md +4 -0
  91. package/package.json +3 -3
@@ -1299,7 +1299,10 @@ var r = {
1299
1299
  download: "Download",
1300
1300
  remove: "Remove",
1301
1301
  replace: "Replace",
1302
- retry: "Retry"
1302
+ retry: "Retry",
1303
+ "move-up": "Move {name} up",
1304
+ "move-down": "Move {name} down",
1305
+ moved: "Moved {name} to position {to}"
1303
1306
  },
1304
1307
  "inline-edit": {
1305
1308
  edit: "Edit",
@@ -4776,7 +4779,10 @@ var r = {
4776
4779
  download: "Télécharger",
4777
4780
  remove: "Retirer",
4778
4781
  replace: "Remplacer",
4779
- retry: "Réessayer"
4782
+ retry: "Réessayer",
4783
+ "move-up": "Monter {name}",
4784
+ "move-down": "Descendre {name}",
4785
+ moved: "{name} déplacé en position {to}"
4780
4786
  },
4781
4787
  "inline-edit": {
4782
4788
  edit: "Modifier",
@@ -4,28 +4,28 @@ import { t as n } from "./utils-BLfntITJ.js";
4
4
  import { n as r } from "./use-shape-morph-BKA_R5P5.js";
5
5
  import { n as i, o as a, t as o } from "./dist-DVRQkaTK.js";
6
6
  import { i as s, n as c, r as l, t as u } from "./dist-DWZXlCZR.js";
7
- import { _ as d, a as f, b as p, g as m, h, i as g, m as _, n as v, o as y, r as b, s as x, t as S, v as C, y as w } from "./spinner-JnLLiLIO.js";
7
+ import { _ as d, a as f, b as p, g as m, h, i as g, m as _, n as v, o as y, r as b, s as x, t as S, v as C, y as w } from "./spinner-CHWFXCfd.js";
8
8
  import { a as T, i as E, n as D, r as O, t as k } from "./dist-DHdUUM1w.js";
9
9
  import { a as A, i as ee } from "./dist-DOK3zo5C.js";
10
10
  import { i as j, n as M } from "./in-dialog-D61Yeaol.js";
11
- import { c as N, l as P, n as te, r as F, t as ne } from "./alert-dialog-BFk4ye-3.js";
11
+ import { c as N, l as P, n as te, r as F, t as ne } from "./alert-dialog-Bz5PlYKp.js";
12
12
  import { A as re, C as ie, D as ae, E as oe, O as se, S as I, T as ce, _ as le, a as ue, b as de, d as fe, f as pe, g as me, h as he, i as ge, k as _e, l as ve, m as ye, n as be, o as xe, p as Se, r as Ce, s as we, t as Te, u as Ee, v as De, w as Oe, x as ke, y as Ae } from "./floating-ui.dom-KkZSW8_E.js";
13
- import { D as je, E as Me, N as Ne, O as Pe, c as Fe, d as Ie, f as Le, i as Re, k as ze, m as Be, n as Ve, o as He, p as Ue, t as We, u as Ge } from "./dropdown-menu-DO5kUvof.js";
13
+ import { D as je, E as Me, N as Ne, O as Pe, c as Fe, d as Ie, f as Le, i as Re, k as ze, m as Be, n as Ve, o as He, p as Ue, t as We, u as Ge } from "./dropdown-menu-B2ctUFti.js";
14
14
  import { a as Ke, i as qe, n as Je } from "./field-blur-context-BLGgf_3z.js";
15
- import { i as Ye, n as Xe, r as Ze, t as Qe } from "./popover-BevReSHi.js";
15
+ import { i as Ye, n as Xe, r as Ze, t as Qe } from "./popover-ukgGm5B6.js";
16
16
  import { a as $e, i as et, n as tt, o as nt, t as rt } from "./bubble-input-CQwVSoU3.js";
17
- import { d as it, n as at, r as ot, t as st } from "./tabs-dXCZGShv.js";
18
- import { a as ct, n as lt, o as ut, s as dt, v as ft, y as pt } from "./toolbar-items-B-kMYsDT.js";
17
+ import { d as it, n as at, r as ot, t as st } from "./tabs-BideU0Rb.js";
18
+ import { a as ct, n as lt, o as ut, s as dt, v as ft, y as pt } from "./toolbar-items-azkXY5w2.js";
19
19
  import { t as mt } from "./dist-DkQbkF9T.js";
20
20
  import { o as ht, s as gt, t as _t } from "./use-click-lock-Bwg_caHO.js";
21
21
  import { a as vt, r as yt } from "./icon-sprites-CaYXzOL4.js";
22
22
  import { t as bt } from "./warn-once-C_e47JM8.js";
23
- import { r as xt, t as St } from "./button-C5OEq9bi.js";
24
- import { a as Ct } from "./translator-CfoXTrZd.js";
23
+ import { r as xt, t as St } from "./button-a3tH3pq4.js";
24
+ import { a as Ct } from "./translator-CxyFsfO0.js";
25
25
  import { h as wt } from "./get-CTzJAwfc.js";
26
26
  import { t as Tt } from "./isEmpty-F_g3jLf8.js";
27
- import { t as L } from "./use-material-translation-DoymV6IP.js";
28
- import { t as R } from "./icon-button-D0xjBCst.js";
27
+ import { t as L } from "./use-material-translation-DA5ECZfA.js";
28
+ import { t as R } from "./icon-button-BylI02aX.js";
29
29
  import { t as Et } from "./use-ssr-media-query-C6M5m8sf.js";
30
30
  import { n as Dt, t as Ot } from "./typography-CYEquVeb.js";
31
31
  import { n as kt, t as At } from "./util-4heV2LPI.js";
@@ -36,15 +36,15 @@ import { a as Bt } from "./toggle-group-CVMxEpWi.js";
36
36
  import { n as Vt } from "./use-slice-reducer-BGkeGtML.js";
37
37
  import { t as Ht } from "./browser-only-DQ94lWF8.js";
38
38
  import { t as Ut } from "./compose-refs-G4J4kaUA.js";
39
- import { n as Wt, r as Gt, t as Kt } from "./chip-DOxFA4BI.js";
39
+ import { n as Wt, r as Gt, t as Kt } from "./chip-BwGvGx_S.js";
40
40
  import { c as qt, o as Jt, r as Yt, s as Xt, t as Zt } from "./input-CC2joTjB.js";
41
- import { i as Qt, n as $t, t as en } from "./input-group-CSlXMFxu.js";
41
+ import { i as Qt, n as $t, t as en } from "./input-group-CiayHfBN.js";
42
42
  import { t as tn } from "./text-field-BAdY-kpO.js";
43
43
  import { r as nn } from "./use-csp-nonce-ZKs9k-ov.js";
44
- import { t as rn } from "./empty-state-DQnICuun.js";
44
+ import { t as rn } from "./empty-state-Bs44jnWk.js";
45
45
  import { t as an } from "./skeleton-DSdtr2qc.js";
46
- import { l as on, n as sn, o as cn, r as ln, s as un, t as dn, u as fn } from "./dialog-d6Kdf5wc.js";
47
- import { t as pn } from "./icon-badge-BGczZ4Hc.js";
46
+ import { l as on, n as sn, o as cn, r as ln, s as un, t as dn, u as fn } from "./dialog-vQMypIOm.js";
47
+ import { t as pn } from "./icon-badge-YT98b2Vx.js";
48
48
  import { H as mn, V as hn, X as gn, bt as _n, it as vn, lt as yn, n as bn, t as xn, xt as Sn, yt as Cn } from "./dist-moutbfbd.js";
49
49
  import { t as wn } from "./markdown-Dw_uH7j7.js";
50
50
  import { r as Tn, t as En } from "./create-store-Dqp-PLLn.js";
@@ -11180,7 +11180,7 @@ var eS = (e = {}) => Tn({
11180
11180
  let [{ default: t }, { lowlight: n }, { richCodeBlock: r }] = await Promise.all([
11181
11181
  import("./dist-CRMFGjng.js"),
11182
11182
  import("./lowlight-OtcjU2Sa.js"),
11183
- import("./rich-code-block-Dh9J-VZ8.js")
11183
+ import("./rich-code-block-DUaSLxLT.js")
11184
11184
  ]);
11185
11185
  return [r(t, {
11186
11186
  lowlight: n,
@@ -21099,40 +21099,40 @@ function nF({ editor: e }) {
21099
21099
  //#endregion
21100
21100
  //#region lib/components/ui/widgets/editor/extensions/marks/compact-mark-buttons.tsx
21101
21101
  function rF({ editor: e }) {
21102
- let { t } = L(), n = Rt({
21102
+ let { t } = L(), n = !!e.schema.marks.strike, r = Rt({
21103
21103
  editor: e,
21104
21104
  selector: (e) => ({
21105
21105
  isBold: e.editor.isActive("bold") ?? !1,
21106
21106
  canBold: e.editor.can().chain().toggleBold().run() ?? !1,
21107
21107
  isItalic: e.editor.isActive("italic") ?? !1,
21108
21108
  canItalic: e.editor.can().chain().toggleItalic().run() ?? !1,
21109
- isStrike: e.editor.isActive("strike") ?? !1,
21110
- canStrike: e.editor.can().chain().toggleStrike().run() ?? !1
21109
+ isStrike: n && (e.editor.isActive("strike") ?? !1),
21110
+ canStrike: n && (e.editor.can().chain().toggleStrike().run() ?? !1)
21111
21111
  })
21112
21112
  });
21113
21113
  return /* @__PURE__ */ K(Jr, { children: [
21114
21114
  /* @__PURE__ */ G(Hy, {
21115
- variant: n.isBold ? "filled" : "ghost",
21116
- "aria-pressed": n.isBold,
21115
+ variant: r.isBold ? "filled" : "ghost",
21116
+ "aria-pressed": r.isBold,
21117
21117
  tooltip: t("material.rich-text-editor.bold", "Bold"),
21118
21118
  onClick: () => e.chain().focus().toggleBold().run(),
21119
- disabled: !n.canBold,
21119
+ disabled: !r.canBold,
21120
21120
  children: /* @__PURE__ */ G(ci, {})
21121
21121
  }),
21122
21122
  /* @__PURE__ */ G(Hy, {
21123
- variant: n.isItalic ? "filled" : "ghost",
21124
- "aria-pressed": n.isItalic,
21123
+ variant: r.isItalic ? "filled" : "ghost",
21124
+ "aria-pressed": r.isItalic,
21125
21125
  tooltip: t("material.rich-text-editor.italic", "Italic"),
21126
21126
  onClick: () => e.chain().focus().toggleItalic().run(),
21127
- disabled: !n.canItalic,
21127
+ disabled: !r.canItalic,
21128
21128
  children: /* @__PURE__ */ G(Ui, {})
21129
21129
  }),
21130
- /* @__PURE__ */ G(Hy, {
21131
- variant: n.isStrike ? "filled" : "ghost",
21132
- "aria-pressed": n.isStrike,
21130
+ n && /* @__PURE__ */ G(Hy, {
21131
+ variant: r.isStrike ? "filled" : "ghost",
21132
+ "aria-pressed": r.isStrike,
21133
21133
  tooltip: t("material.rich-text-editor.strikethrough", "Strikethrough"),
21134
21134
  onClick: () => e.chain().focus().toggleStrike().run(),
21135
- disabled: !n.canStrike,
21135
+ disabled: !r.canStrike,
21136
21136
  children: /* @__PURE__ */ G(Ha, {})
21137
21137
  })
21138
21138
  ] });
@@ -21181,7 +21181,7 @@ function oF({ editor: e, part: t = "all" }) {
21181
21181
  strike: n("material.rich-text-editor.strikethrough", "Strikethrough"),
21182
21182
  subscript: n("material.rich-text-editor.subscript", "Subscript"),
21183
21183
  superscript: n("material.rich-text-editor.superscript", "Superscript")
21184
- }, i = iF.filter((e) => t === "all" || t === "main" == !!e.main), a = Rt({
21184
+ }, i = iF.filter((n) => e.schema.marks[n.name] && (t === "all" || t === "main" == !!n.main)), a = Rt({
21185
21185
  editor: e,
21186
21186
  selector: (e) => i.map((t) => aF(e.editor, t.name)),
21187
21187
  equalityFn: (e, t) => t !== null && e.length === t.length && e.every((e, n) => e.on === t[n]?.on && e.can === t[n]?.can)
@@ -21209,11 +21209,12 @@ function cF({ editor: e }) {
21209
21209
  }
21210
21210
  //#endregion
21211
21211
  //#region lib/components/ui/widgets/editor/kit/features/marks.ts
21212
- var lF = ({ compact: e = !1 } = {}) => Tn({
21212
+ var lF = ({ compact: e = !1, strike: t = !0 } = {}) => Tn({
21213
21213
  name: "marks",
21214
21214
  extensions: (e) => [
21215
21215
  Tr.configure({
21216
21216
  codeBlock: !1,
21217
+ strike: t ? void 0 : !1,
21217
21218
  dropcursor: {
21218
21219
  color: "var(--primary)",
21219
21220
  width: 2,
@@ -1,8 +1,8 @@
1
1
  import { t as e } from "./utils-BLfntITJ.js";
2
- import { a as t, c as n, d as r, i, n as a, r as o, t as s, u as c } from "./alert-dialog-BFk4ye-3.js";
3
- import { a as l } from "./button-C5OEq9bi.js";
4
- import { i as u } from "./translate-material-BmpcP1p1.js";
5
- import { t as d } from "./use-material-translation-DoymV6IP.js";
2
+ import { a as t, c as n, d as r, i, n as a, r as o, t as s, u as c } from "./alert-dialog-Bz5PlYKp.js";
3
+ import { a as l } from "./button-a3tH3pq4.js";
4
+ import { i as u } from "./translate-material-d8Q5K5a_.js";
5
+ import { t as d } from "./use-material-translation-DA5ECZfA.js";
6
6
  import { _ as f, g as p, h as m, t as h, v as g, y as _ } from "./date.utils-JTEIo3mM.js";
7
7
  import { useCallback as v, useEffect as y, useMemo as b, useRef as x, useState as S } from "react";
8
8
  import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
@@ -1,4 +1,4 @@
1
- import { i as e, t } from "./translate-material-BmpcP1p1.js";
1
+ import { i as e, t } from "./translate-material-d8Q5K5a_.js";
2
2
  import { useCallback as n } from "react";
3
3
  //#region lib/i18n/use-material-translation.ts
4
4
  function r() {
@@ -1,6 +1,6 @@
1
1
  import { o as e, r as t } from "./dist-DVRQkaTK.js";
2
2
  import { i as n, n as r, r as i, t as a } from "./dist-DWZXlCZR.js";
3
- import { C as o, S as s, x as c } from "./spinner-JnLLiLIO.js";
3
+ import { C as o, S as s, x as c } from "./spinner-CHWFXCfd.js";
4
4
  import { a as l, i as u, r as d } from "./dist-DHdUUM1w.js";
5
5
  import { c as f, i as p, l as m, o as h, r as g, s as ee } from "./in-dialog-D61Yeaol.js";
6
6
  import { r as te } from "./escape-owner-DpaP0lm1.js";
@@ -1720,10 +1720,42 @@ import { DayGroupedList } from '@nxgt/material/components';
1720
1720
  </div>
1721
1721
  ```
1722
1722
 
1723
+ For an agenda, `groupBy="date"` gives each distinct calendar date its own
1724
+ section, upcoming days included, with an aside such as a total beside the
1725
+ heading (outside the `<h3>`, so the heading's name stays the date). Undated
1726
+ items go last under "No date". Pass `now` and `timeZone` from the server so the
1727
+ headings match on hydration; an unknown `timeZone` falls back to the runtime's
1728
+ with a warning in development. The split is also plain data:
1729
+ `groupByDate` (re-exported by `@nxgt/material/components`, beside `groupByDay`).
1730
+ `calendarDateOf`, `formatCalendarDate` and `isValidTimeZone` are in
1731
+ `@nxgt/material-core/day-math`.
1732
+
1733
+ ```tsx
1734
+ import { DayGroupedList } from '@nxgt/material/components';
1735
+
1736
+ // `sumMinutes` and `formatMinutes` are the app's own helpers.
1737
+ <DayGroupedList
1738
+ items={tasks}
1739
+ getDate={(task) => task.due}
1740
+ getKey={(task) => task.id}
1741
+ renderItem={(task) => <TaskRow task={task} />}
1742
+ now={serverNow}
1743
+ groupBy="date"
1744
+ timeZone="America/Toronto"
1745
+ renderAside={(_day, list) => formatMinutes(sumMinutes(list))}
1746
+ />
1747
+ ```
1748
+
1723
1749
  | Prop | Type | Default | Effect |
1724
1750
  | --- | --- | --- | --- |
1725
1751
  | `items` / `getDate` / `getKey` / `renderItem` | — | required | the items, the date each is filed under, its key and its content |
1726
1752
  | `now` | `Date \| number` | required | the day the buckets count from, in the runtime's time zone; pass the same value to the server and the browser |
1753
+ | `groupBy` | `'relative' \| 'date'` | `'relative'` | `date` gives each distinct calendar date its own section, past and future, instead of the relative buckets |
1754
+ | `order` | `'asc' \| 'desc'` | `'asc'` | with `groupBy="date"`, earliest or latest date first |
1755
+ | `timeZone` | IANA zone | runtime's | with `groupBy="date"`, the zone instants are read in; pass the same to server and browser. A date-only string (`'2026-11-03'`) is that date in any zone |
1756
+ | `locale` | BCP 47 tag | active i18n language | with `groupBy="date"`, the language of the headings (weekday, day, month; the year only off the current year) |
1757
+ | `formatHeading` | `(day: string, items: T[]) => ReactNode` | — | with `groupBy="date"`, replaces a heading; `day` is `YYYY-MM-DD` (or `undated`) |
1758
+ | `renderAside` | `(key: string, items: T[]) => ReactNode` | — | content beside each heading, such as a day's total; `key` is the date (or `undated`), or `today`, `yesterday`… |
1727
1759
  | `labels` | `Partial<Record<DayGroupKey, ReactNode>>` | — | replaces a heading |
1728
1760
  | `sticky` | `boolean` | `true` | headings stick while their items scroll |
1729
1761
  | `showCount` | `boolean` | `false` | the count beside each heading |
@@ -1148,7 +1148,15 @@ of a [`MediaPlayerHost`](./media-and-files.md#mediaplayerhost)'s docked bar
1148
1148
  corner (`--nxgt-media-float`: a host's, or a `floatOnScroll` player's, with
1149
1149
  or without a host), so toasts never cover them. An
1150
1150
  `offset` or `mobileOffset` you pass replaces that default: add the variables
1151
- yourself, e.g. `offset={{ bottom: 'calc(32px + var(--nxgt-media-dock, 0px) + var(--nxgt-media-float, 0px))' }}`.
1151
+ yourself, e.g. `offset={{ bottom: 'calc(32px + var(--nxgt-media-dock, 0px) + var(--nxgt-media-float, 0px) + var(--nxgt-sticky-bar, 0px))' }}`.
1152
+
1153
+ **Above a `StickyActionBar`:** the bottom offsets, on a desktop and on a
1154
+ phone, also add the height of a mounted
1155
+ [`StickyActionBar`](./navigation-and-layout.md#stickyactionbar)
1156
+ (`--nxgt-sticky-bar`, 0 when none is mounted), so a toast never covers the
1157
+ bar's primary action. An `offset` or `mobileOffset` you pass drops that too:
1158
+ add `var(--nxgt-sticky-bar, 0px)` yourself, e.g.
1159
+ `offset={{ bottom: 'calc(32px + var(--nxgt-sticky-bar, 0px))' }}`.
1152
1160
 
1153
1161
  ```tsx
1154
1162
  <Toaster /> // bottom-right on a desktop, top-center on a phone
@@ -258,6 +258,22 @@ saved images).
258
258
  | `value` / `onValueChange` | `string[]` | `[]` | field variants: the stored URLs |
259
259
  | `onUpload` / `getPresignedUrl` | see [S3UploadField](#s3uploadfield-networkuploadfield) | — | field variants: how a file is sent |
260
260
  | `required` | `boolean` | — | field variants: the asterisk, and a "required" description on the field group (below) |
261
+ | `describe` | `(value: string) => FileDescription \| null \| undefined` | — | field variants: names, sizes and types a kept value (an id, a key) instead of showing the value. `FileDescription` is `{ name?, size?, type?, href? }`; `href` is its download link (dropped when not safe: `javascript:` and the like get no Download button). `null` or `undefined` falls back to the plain display. Runs on every render: keep it pure and cheap |
262
+ | `reorderable` | `boolean` | `false` | field variants: move up / move down buttons on the kept files, disabled at the ends and when the field is `disabled`; `onValueChange` receives the new order. The focus stays on the pressed button (the row's other one at an end) and a polite status says "Moved {name} to position {to}". Uploads in flight sit last until they finish |
263
+
264
+ Kept files by name, size and type, reorderable (the value stays a `string[]`):
265
+
266
+ ```tsx
267
+ <FileListS3Field
268
+ value={ids}
269
+ onValueChange={setIds}
270
+ getPresignedUrl={getPresignedUrl}
271
+ describe={(id) => files[id]} // { name, size, type, href? } | undefined
272
+ reorderable
273
+ />
274
+ ```
275
+
276
+ A row's data is `NetworkUploadDisplayItem`, which gains an optional `type` and `href` (`null`: described with a link that is not safe). New `material.*` keys: `file-list.move-up` (`Move {name} up`), `file-list.move-down` (`Move {name} down`) and `file-list.moved` (`Moved {name} to position {to}`).
261
277
 
262
278
  The dropzone is a button, and a button may not carry `aria-required`, so the
263
279
  field's list and dropzone sit in a `group` named by the label. With `required`,
@@ -599,6 +599,11 @@ the page. It takes a `div`'s props.
599
599
  (`interactive-widget=resizes-content`) needs no lift, and none is applied.
600
600
  Pinch-zoom is not treated as a keyboard.
601
601
  - **Name.** With `aria-label` or `aria-labelledby` the bar is a `group`.
602
+ - **Toasts clear it.** While mounted and sticky, the bar publishes its height as
603
+ `--nxgt-sticky-bar` on the document root and removes it on unmount; the
604
+ [`Toaster`](./feedback-and-status.md#toaster)'s bottom offsets add it. With
605
+ several bars the latest wins. From `md` the bar is inline, so a desktop
606
+ toast is lifted by the bar's height.
602
607
 
603
608
  | Prop | Type | Default | Effect |
604
609
  | --- | --- | --- | --- |
@@ -1108,6 +1108,21 @@ const [html, setHtml] = useState('<p></p>');
1108
1108
  `compactKit` and `chatKit` show bold, italic, strikethrough and inline code
1109
1109
  (`editorFeatures.inlineCode`) in the toolbar; underline, subscript and
1110
1110
  superscript stay readable in the content but have no button.
1111
+ Strikethrough can be left out. `strike` defaults to `true` and works on both
1112
+ the compact and the full editor: `editorFeatures.marks({ compact: true, strike: false })`
1113
+ (replacing the kit's `marks` feature) drops the mark and its button, `~~x~~`
1114
+ in pasted Markdown reads as plain `x`, and the
1115
+ mark buttons also hide any mark the editor's schema lacks (for example a
1116
+ starter kit configured with `strike: false`):
1117
+
1118
+ ```tsx
1119
+ <CompactEditor
1120
+ features={(kit) => [
1121
+ ...kit.filter((f) => f.name !== 'marks'),
1122
+ editorFeatures.marks({ compact: true, strike: false }),
1123
+ ]}
1124
+ />
1125
+ ```
1111
1126
  - The toolbar opens with undo and redo (one group, kept last when the row folds), and the block type is one menu (Paragraph, Heading 1 to 6) whose button names the block under the caret; its label shows from 64rem of width, an icon alone below.
1112
1127
  - The toolbar is one row on the library's `Toolbar` (one tab stop, arrow keys), each feature's group a `ToolbarGroup`: groups that do not fit fold into the `Toolbar`'s More menu as a unit, lowest `priority` first: a group of two or more rows is a section under its name (its `label`, else `material.editor.group.<id>`, translated; else its id), a group of one row lists that row alone, and a single-choice group (the alignments) stays a radio group under its name. In that menu a toggle is a checkbox row with its state (bold, a list), the alignments one radio group (`menuitemradio` rows, the current one checked), a button a row that runs it (a dialog it opens, the link, the table, the image or the video, keeps the focus, and gives it back to the document when it closes; in the bar a dialog gives it back to its own button, and the image address, which has no button of its own, to the document), a menu control a submenu (the block type and the font as radio rows, the current one checked and shown on the row; the callout types, translated; the image's upload and address), and a popover control (the text colour, the highlight, the emoji) a row that opens its popover at the More button; Escape there gives the focus back to More, a choice to the document. An editor panel opened from More (the outline, the comments) stays open while you use More, and its row turns it off, the focus then going to the document. `EditorRoot` takes `look` (`'classic'` by default for a root you compose; the presets pass `'expressive'`), which `EditorToolbar` reads (`useEditorContext().look`); `EditorToolbar` takes `density` (`'compact'`: 36 px tools in the expressive look), `variant` (`docked`, the default, or `floating`) and `layout="wrap"` to keep every group on screen. `orientation` is `'horizontal'` (the default) or `'vertical'`, a column with Up and Down for the arrow keys, which folds what does not fit its height into the same More menu, at its bottom; `layout="page"` uses it for its rail, and you can use it in your own layout:
1113
1128
 
@@ -2115,6 +2115,10 @@ offset's `top` (80 by default, so toasts start below that bar):
2115
2115
  <Toaster position="bottom-center" /> // bottom-center on every screen
2116
2116
  ```
2117
2117
 
2118
+ A mounted `StickyActionBar` is cleared automatically (`--nxgt-sticky-bar`). An
2119
+ explicit `offset` or `mobileOffset` drops that, so add
2120
+ `var(--nxgt-sticky-bar, 0px)` to its `bottom` yourself.
2121
+
2118
2122
  ### A toast never goes away after a tap
2119
2123
 
2120
2124
  **When:** on a phone (or any touch screen), a toast that should time out stays
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/material",
3
- "version": "3.90.0",
3
+ "version": "3.92.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"
@@ -390,7 +390,7 @@
390
390
  "docs:previews": "rm -rf node_modules/.cache/nxgt-preview-free/missing && NXGT_PREVIEW_FREE=1 vitest run --project previews && bun .storybook/preview-free-report.ts"
391
391
  },
392
392
  "dependencies": {
393
- "@nxgt/material-core": "^0.53.0",
393
+ "@nxgt/material-core": "^0.54.0",
394
394
  "@base-ui/react": "^1.6.0",
395
395
  "@dnd-kit/core": "^6.3.1",
396
396
  "@dnd-kit/sortable": "^10.0.0",
@@ -477,7 +477,7 @@
477
477
  "@fontsource-variable/inter": "^5",
478
478
  "@fortawesome/fontawesome-free": "7.3.1",
479
479
  "@nxgt/material-testing": "0.0.0",
480
- "@nxgt/playwright": "^0.12.0",
480
+ "@nxgt/playwright": "^0.17.0",
481
481
  "@react-leaflet/core": "^3.0.0",
482
482
  "@react-pdf/renderer": "^4.9.0",
483
483
  "@storybook/addon-a11y": "10.6.0",