@nxgt/material 3.26.1 → 3.28.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 (113) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +2 -2
  3. package/dist/{async-slice-gAbGnQT8.js → async-slice-DmhasXmq.js} +2 -2
  4. package/dist/{button-Cr9GIIj4.js → button-BjIg_Lz6.js} +1 -1
  5. package/dist/charts.js +3 -3
  6. package/dist/{chip-s11lOfxB.js → chip-DIBIDUZH.js} +1 -1
  7. package/dist/{code-editor-DGIjL8Hr.js → code-editor-2EU-q9FV.js} +4 -4
  8. package/dist/code-editor.js +4 -4
  9. package/dist/{code-language-items-DCOQnaCo.js → code-language-items-C_UeMQMm.js} +2 -2
  10. package/dist/components/ui/display/chip/chip-parts.css +19 -0
  11. package/dist/{components-BEN2FVD-.js → components-Cl3Zyoe-.js} +15000 -14487
  12. package/dist/components.js +26 -26
  13. package/dist/{dialog-Crvg-MN5.js → dialog-LtXwv6N3.js} +1 -1
  14. package/dist/dnd.js +1 -1
  15. package/dist/{dropdown-menu-B71aggp0.js → dropdown-menu-ppMPD12c.js} +1 -1
  16. package/dist/editor.js +7 -7
  17. package/dist/{empty-state-8LddxMU4.js → empty-state-X_nikpBS.js} +1 -1
  18. package/dist/hooks.js +2 -2
  19. package/dist/{i18n-provider-BDi9-6DO.js → i18n-provider-BfyDgd2o.js} +1 -1
  20. package/dist/i18n.js +5 -5
  21. package/dist/{icon-badge-DG7wLnHh.js → icon-badge-oLBh3Mlk.js} +1 -1
  22. package/dist/lib/components/ui/collections/facet-group/facet-group.d.ts +1 -1
  23. package/dist/lib/components/ui/collections/facet-group/types.d.ts +2 -0
  24. package/dist/lib/components/ui/collections/filter/bar/filter-bar-classes.d.ts +11 -1
  25. package/dist/lib/components/ui/collections/filter/bar/{filter-bar.d.ts → filter-bar-view.d.ts} +2 -2
  26. package/dist/lib/components/ui/collections/filter/bar/partials/filter-clear-all.d.ts +2 -2
  27. package/dist/lib/components/ui/collections/filter/bar/partials/filter-quick-pill.d.ts +4 -1
  28. package/dist/lib/components/ui/collections/filter/bar/partials/filter-quick-toggle.d.ts +3 -0
  29. package/dist/lib/components/ui/collections/filter/bar/partials/filter-scope-list.d.ts +6 -0
  30. package/dist/lib/components/ui/collections/filter/bar/partials/filter-scope-pill.d.ts +13 -0
  31. package/dist/lib/components/ui/collections/filter/bar/partials/use-quick-condition.d.ts +19 -0
  32. package/dist/lib/components/ui/collections/filter/bar/partials/use-quick-pill.d.ts +30 -0
  33. package/dist/lib/components/ui/collections/filter/bar/use-filter-bar-wiring.d.ts +5 -0
  34. package/dist/lib/components/ui/collections/filter/editors/boolean-editor.d.ts +3 -2
  35. package/dist/lib/components/ui/collections/filter/editors/checkbox-editor.d.ts +1 -1
  36. package/dist/lib/components/ui/collections/filter/editors/switch-editor.d.ts +1 -1
  37. package/dist/lib/components/ui/collections/filter/facets/filter-facets.d.ts +2 -2
  38. package/dist/lib/components/ui/collections/filter/filter-bar-url.d.ts +51 -0
  39. package/dist/lib/components/ui/collections/filter/index.d.ts +2 -0
  40. package/dist/lib/components/ui/collections/filter/internal.d.ts +3 -1
  41. package/dist/lib/components/ui/collections/filter/query/filter-results-status.d.ts +4 -1
  42. package/dist/lib/components/ui/collections/filter/query/types.d.ts +21 -3
  43. package/dist/lib/components/ui/collections/{server-table → filter/query}/use-answer-wait.d.ts +3 -1
  44. package/dist/lib/components/ui/collections/filter/query/use-apply-now.d.ts +6 -0
  45. package/dist/lib/components/ui/collections/filter/query/use-defaults.d.ts +15 -0
  46. package/dist/lib/components/ui/collections/filter/query/use-field-error.d.ts +5 -0
  47. package/dist/lib/components/ui/collections/filter/query/use-filter-query-options.d.ts +14 -0
  48. package/dist/lib/components/ui/collections/filter/query/use-filter-query-value.d.ts +2 -0
  49. package/dist/lib/components/ui/collections/filter/query/use-filter-query.d.ts +6 -2
  50. package/dist/lib/components/ui/collections/filter/query/use-filter-url-query.d.ts +52 -0
  51. package/dist/lib/components/ui/collections/filter/query/use-refusal-announcement.d.ts +10 -0
  52. package/dist/lib/components/ui/collections/filter/sections/chips/condition-panel.d.ts +2 -1
  53. package/dist/lib/components/ui/collections/filter/sections/chips/filter-chip-body.d.ts +4 -2
  54. package/dist/lib/components/ui/collections/filter/sections/chips/filter-chip-list.d.ts +3 -2
  55. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-chip.d.ts +14 -0
  56. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-group.d.ts +16 -0
  57. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-parts.d.ts +12 -0
  58. package/dist/lib/components/ui/collections/filter/sections/chips/filter-error-parts.d.ts +22 -0
  59. package/dist/lib/components/ui/collections/filter/sections/chips/use-control-description.d.ts +13 -0
  60. package/dist/lib/components/ui/collections/filter/sections/filter-facet-section.d.ts +5 -0
  61. package/dist/lib/components/ui/collections/filter/sections/filter-search.d.ts +4 -3
  62. package/dist/lib/components/ui/collections/filter/sections/filter-sections-classes.d.ts +8 -0
  63. package/dist/lib/components/ui/collections/filter/sections/renderers/choice-facet.d.ts +1 -1
  64. package/dist/lib/components/ui/collections/filter/sections/use-filter-shortcuts.d.ts +4 -3
  65. package/dist/lib/components/ui/collections/server-table/partials/server-table-empty-chips.d.ts +1 -1
  66. package/dist/lib/components/ui/collections/server-table/types.d.ts +13 -1
  67. package/dist/lib/components/ui/collections/server-table/use-filter-params.d.ts +5 -4
  68. package/dist/lib/components/ui/collections/server-table/use-table-answer.d.ts +1 -1
  69. package/dist/lib/components/ui/layout/app-shell/activity-column.d.ts +2 -2
  70. package/dist/lib/components/ui/layout/app-shell/activity-layout.d.ts +1 -1
  71. package/dist/lib/components/ui/layout/app-shell/activity-layout.types.d.ts +11 -0
  72. package/dist/lib/components/ui/layout/app-shell/backdrop-layer.d.ts +3 -1
  73. package/dist/lib/components/ui/layout/app-shell/shapes-clear-content.d.ts +24 -0
  74. package/dist/lib/components/ui/layout/app-shell/theme-backdrop.d.ts +3 -1
  75. package/dist/lib/components/ui/layout/app-shell/use-keep-shapes-inside.d.ts +4 -3
  76. package/dist/lib/components/ui/layout/app-shell/watch-content.d.ts +10 -1
  77. package/dist/lib/components/ui/layout/auth-card/auth-card-backdrop.d.ts +4 -2
  78. package/dist/lib/components/ui/layout/auth-card/auth-card.d.ts +4 -2
  79. package/dist/lib/i18n/resources/en/en.d.ts +11 -0
  80. package/dist/lib/i18n/resources/en/material.json.d.ts +11 -0
  81. package/dist/lib/i18n/resources/fr/fr.d.ts +11 -0
  82. package/dist/lib/i18n/resources/fr/material.json.d.ts +11 -0
  83. package/dist/lib/i18n/resources/resources.d.ts +22 -0
  84. package/dist/lib/i18n/translator.d.ts +1 -1
  85. package/dist/lib.js +1 -1
  86. package/dist/main.js +43 -43
  87. package/dist/map.js +4 -4
  88. package/dist/material.css +1 -1
  89. package/dist/pdf-reader.js +1 -1
  90. package/dist/print.js +2 -2
  91. package/dist/{public-QUiFLEoj.js → public-BeM7-x-m.js} +6 -6
  92. package/dist/{rich-code-block-CjD54THr.js → rich-code-block-B4TIjZRA.js} +4 -4
  93. package/dist/{sortable-provider-DYnyzfgR.js → sortable-provider-Dcsw0pgW.js} +1 -1
  94. package/dist/{spinner-CJtTRNAX.js → spinner-1Ia6Akhy.js} +1 -1
  95. package/dist/{stored-language-ClkfkueV.js → stored-language-DoWMr969.js} +22 -0
  96. package/dist/theme-picker.js +2 -2
  97. package/dist/{theme-toggle-ufQL3SO6.js → theme-toggle-GlKtdgYz.js} +1 -1
  98. package/dist/{toolbar-items-DlioFgpM.js → toolbar-items-C1GdN9P9.js} +2 -2
  99. package/dist/{translate-material-O-uasx3u.js → translate-material-BneuBHXZ.js} +2 -2
  100. package/dist/{translator-C0uxN1Nh.js → translator-D88BbpXZ.js} +1 -1
  101. package/dist/{use-chat-composer-DzVO5mwz.js → use-chat-composer-beyfZPBD.js} +12 -12
  102. package/dist/{use-heading-spy-BHCVdJfr.js → use-heading-spy-BN0yeBod.js} +1 -1
  103. package/dist/{use-material-translation-B4Frk3vC.js → use-material-translation-Cqcwkuur.js} +2 -2
  104. package/docs/components/data-table-filter-and-lists.md +184 -3
  105. package/docs/components/navigation-and-layout.md +1 -1
  106. package/docs/guides/app-shell.md +38 -0
  107. package/docs/guides/backgrounds.md +5 -0
  108. package/docs/guides/i18n.md +7 -0
  109. package/docs/guides/server-lists-url.md +114 -1
  110. package/docs/roadmap.md +16 -0
  111. package/docs/troubleshooting.md +73 -5
  112. package/lib/components/ui/display/chip/chip-parts.css +19 -0
  113. package/package.json +2 -2
@@ -1,3 +1,3 @@
1
- import { t as e } from "./public-QUiFLEoj.js";
1
+ import { t as e } from "./public-BeM7-x-m.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-BDi9-6DO.js";
2
- import { t } from "./translate-material-O-uasx3u.js";
1
+ import { r as e } from "./i18n-provider-BfyDgd2o.js";
2
+ import { t } from "./translate-material-BneuBHXZ.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-Crvg-MN5.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-B71aggp0.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-DlioFgpM.js";
12
- import { t as N } from "./use-material-translation-B4Frk3vC.js";
13
- import { t as _e } from "./button-Cr9GIIj4.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-LtXwv6N3.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-ppMPD12c.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-C1GdN9P9.js";
12
+ import { t as N } from "./use-material-translation-Cqcwkuur.js";
13
+ import { t as _e } from "./button-BjIg_Lz6.js";
14
14
  import { n as ve, t as ye } from "./icon-button-ifTpXt0A.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-8LddxMU4.js";
20
+ import { n as Ee, t as De } from "./empty-state-X_nikpBS.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-B71aggp0.js";
3
- import { t as i } from "./use-material-translation-B4Frk3vC.js";
4
- import { a, i as o, n as s, o as c, t as l } from "./code-language-items-DCOQnaCo.js";
2
+ import { c as t, n, t as r } from "./dropdown-menu-ppMPD12c.js";
3
+ import { t as i } from "./use-material-translation-Cqcwkuur.js";
4
+ import { a, i as o, n as s, o as c, t as l } from "./code-language-items-C_UeMQMm.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-DGIjL8Hr.js").then((e) => e.n).then((e) => ({ default: e.CodeEditor })));
146
+ var N = x(() => import("./code-editor-2EU-q9FV.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-B4Frk3vC.js";
3
+ import { t as n } from "./use-material-translation-Cqcwkuur.js";
4
4
  import { t as r } from "./icon-button-ifTpXt0A.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-B4Frk3vC.js";
3
+ import { t as n } from "./use-material-translation-Cqcwkuur.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", {
@@ -1278,6 +1278,17 @@ var t = {
1278
1278
  until: "Until {value}",
1279
1279
  "up-to": "Up to {value}"
1280
1280
  },
1281
+ default: {
1282
+ label: "Default",
1283
+ hint: "Default value, in effect until you choose one",
1284
+ tag: "· {default}",
1285
+ change: "{filter}, default value. Change"
1286
+ },
1287
+ error: {
1288
+ tag: "Invalid",
1289
+ label: "Invalid: {message}",
1290
+ announce: "{field}: {message}"
1291
+ },
1281
1292
  bar: {
1282
1293
  label: "Filters",
1283
1294
  search: "Search",
@@ -3930,6 +3941,17 @@ var t = {
3930
3941
  until: "Jusqu'au {value}",
3931
3942
  "up-to": "Jusqu'à {value}"
3932
3943
  },
3944
+ default: {
3945
+ label: "Par défaut",
3946
+ hint: "Valeur par défaut, appliquée tant que vous n'en choisissez pas une",
3947
+ tag: "· {default}",
3948
+ change: "{filter}, valeur par défaut. Modifier"
3949
+ },
3950
+ error: {
3951
+ tag: "Invalide",
3952
+ label: "Invalide : {message}",
3953
+ announce: "{field} : {message}"
3954
+ },
3933
3955
  bar: {
3934
3956
  label: "Filtres",
3935
3957
  search: "Rechercher",
@@ -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-B4Frk3vC.js";
3
+ import { t as s } from "./use-material-translation-Cqcwkuur.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-ufQL3SO6.js";
7
+ import { t as p } from "./theme-toggle-GlKtdgYz.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-B4Frk3vC.js";
1
+ import { t as e } from "./use-material-translation-Cqcwkuur.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-B71aggp0.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-ppMPD12c.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-B4Frk3vC.js";
9
+ import { t as xe } from "./use-material-translation-Cqcwkuur.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-ClkfkueV.js";
2
- import { a as e, r as t } from "./translator-C0uxN1Nh.js";
1
+ import "./stored-language-DoWMr969.js";
2
+ import { a as e, r as t } from "./translator-D88BbpXZ.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-ClkfkueV.js";
2
+ import { a as t, i as n, r, t as i } from "./stored-language-DoWMr969.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-Crvg-MN5.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-LtXwv6N3.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-B71aggp0.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-ppMPD12c.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-DlioFgpM.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-C1GdN9P9.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-ClkfkueV.js";
18
- import { a as kt } from "./translator-C0uxN1Nh.js";
17
+ import "./stored-language-DoWMr969.js";
18
+ import { a as kt } from "./translator-D88BbpXZ.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-B4Frk3vC.js";
22
- import { t as Mt } from "./spinner-CJtTRNAX.js";
21
+ import { t as L } from "./use-material-translation-Cqcwkuur.js";
22
+ import { t as Mt } from "./spinner-1Ia6Akhy.js";
23
23
  import { a as Nt } from "./button-tones-BwuVvAmd.js";
24
- import { a as Pt, i as Ft, n as It, r as Lt, t as Rt } from "./button-Cr9GIIj4.js";
24
+ import { a as Pt, i as Ft, n as It, r as Lt, t as Rt } from "./button-BjIg_Lz6.js";
25
25
  import { t as R } from "./icon-button-ifTpXt0A.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-s11lOfxB.js";
39
- import { n as dn, t as fn } from "./icon-badge-DG7wLnHh.js";
38
+ import { n as cn, r as ln, t as un } from "./chip-DIBIDUZH.js";
39
+ import { n as dn, t as fn } from "./icon-badge-oLBh3Mlk.js";
40
40
  import { r as pn } from "./use-csp-nonce-ZKs9k-ov.js";
41
- import { t as mn } from "./empty-state-8LddxMU4.js";
41
+ import { t as mn } from "./empty-state-X_nikpBS.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";
@@ -10782,7 +10782,7 @@ var CS = (e = {}) => Dn({
10782
10782
  let [{ default: t }, { lowlight: n }, { richCodeBlock: r }] = await Promise.all([
10783
10783
  import("./dist-CRMFGjng.js"),
10784
10784
  import("./lowlight-OtcjU2Sa.js"),
10785
- import("./rich-code-block-CjD54THr.js")
10785
+ import("./rich-code-block-B4TIjZRA.js")
10786
10786
  ]);
10787
10787
  return [r(t, {
10788
10788
  lowlight: n,
@@ -1,4 +1,4 @@
1
- import { r as e } from "./i18n-provider-BDi9-6DO.js";
1
+ import { r as e } from "./i18n-provider-BfyDgd2o.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 } from "react";
4
4
  //#region ../../node_modules/date-fns/locale/fr/_lib/formatDistance.js
@@ -1,5 +1,5 @@
1
- import { r as e } from "./i18n-provider-BDi9-6DO.js";
2
- import { t } from "./translate-material-O-uasx3u.js";
1
+ import { r as e } from "./i18n-provider-BfyDgd2o.js";
2
+ import { t } from "./translate-material-BneuBHXZ.js";
3
3
  import { useCallback as n } from "react";
4
4
  //#region lib/i18n/use-material-translation.ts
5
5
  function r() {
@@ -878,7 +878,7 @@ Its props are `ServerTableProps<T>`; `filter` is a `ServerTableFilter`,
878
878
  | `rows`, `totalCount`, `pageInfo` | the connection's page | — | `pageInfo: { endCursor?, hasNextPage }`; `rows` stable per answer |
879
879
  | `pageSize` | `number` | — | the footer's range ("21–40 of 45") |
880
880
  | `getRowId` | `(row) => string` | — | the selection's key |
881
- | `filter` | `ServerTableFilter` | — | `{ model, locked?, fieldProps?, variant?, sheetTrigger?, quick?, density?, shortcuts?, previewCount?, counts?, liveDelayMs?, label?, searchLabel?, searchPlaceholder?, searchApply?, searchMinLength?, codec? }` |
881
+ | `filter` | `ServerTableFilter` | — | `{ model, locked?, fieldProps?, variant?, sheetTrigger?, quick?, density?, shortcuts?, previewCount?, counts?, liveDelayMs?, label?, searchLabel?, searchPlaceholder?, searchApply?, searchMinLength?, codec?, defaults?, errors? }` |
882
882
  | `filter.codec` | `{ keepKnownValues?, encoding? }` | — | how the page reads and writes the URL: pass the loader's `keepKnownValues` / `encoding` so chips and rows agree |
883
883
  | `title` | `ReactNode` | — | the band's title (a string is an `<h2>`). Leave it out when the page's `h1` is elsewhere (the app bar's): the band then has no heading |
884
884
  | `description` | `ReactNode` | — | a muted line under the `title`, or alone above the band's controls without one; the `actions` stay at the band's end |
@@ -1252,8 +1252,12 @@ overload per kind, so `<Filter variant="bar" />` does not compile).
1252
1252
  `query` / `defaultQuery` + `onQueryChange` carry the user's query, never a
1253
1253
  locked condition; `density` (a `FilterDensity`: `'comfortable'` or
1254
1254
  `'compact'`, the controls' size and the gap between them), `bandDensity`
1255
- (`'comfortable'` or `'compact'`, the bar's own vertical room: see below), `label`, `searchLabel`, `searchPlaceholder`, `liveDelayMs`
1256
- (200 ms), `searchApply` and `searchMinLength` tune it. A locked chip is a focusable group named by its text ("Year is 2026-2027"), with "Locked: <reason>" as its description. The other variants
1255
+ (`'comfortable'` or `'compact'`, the bar's own vertical room: see below), `label`,
1256
+ `searchLabel`, `searchPlaceholder`, `liveDelayMs`
1257
+ (200 ms), `searchApply` and `searchMinLength` tune it; `defaults` gives the
1258
+ `default: 'page'` fields their values (see [A field's default](#a-fields-default))
1259
+ and `errors` shows a server's refusal of a condition (see
1260
+ [A refused condition](#a-refused-condition)). A locked chip is a focusable group named by its text ("Year is 2026-2027"), with "Locked: <reason>" as its description. The other variants
1257
1261
  and `FilterProps` are unchanged.
1258
1262
 
1259
1263
  #### A compact band for a list inside a page section
@@ -1373,6 +1377,59 @@ function StudentsFilter({ total }: { total: number }) {
1373
1377
  }
1374
1378
  ```
1375
1379
 
1380
+ #### Filter bar outside a table
1381
+
1382
+ A feed or a list that is no table hosts the same bar with `FilterBar`: it
1383
+ reads its query from the search params and writes it back, so there is no
1384
+ `parseFilterQuery` / `serializeFilterQuery` to wire. It is the bar of
1385
+ `ServerTable`'s band: the search, the chips, "Clear all", the count announced
1386
+ once the page answers, "Filters (N)" opening the sheet on a phone, and a
1387
+ `widens` field (a "Show archived" switch) as a toggle, never a chip.
1388
+
1389
+ ```tsx
1390
+ import { FilterBar } from '@nxgt/material/components';
1391
+ import { useSearchParams } from 'react-router';
1392
+
1393
+ function Notifications({ items }: { items: Notification[] }) {
1394
+ const [params, setParams] = useSearchParams();
1395
+ return (
1396
+ <>
1397
+ <FilterBar
1398
+ model={NOTIFICATION_FILTERS}
1399
+ params={params}
1400
+ onParamsChange={(next) => setParams(next, { replace: true })}
1401
+ resultCount={items.length}
1402
+ />
1403
+ <ul>{items.map((n) => <NotificationRow key={n.id} {...n} />)}</ul>
1404
+ </>
1405
+ );
1406
+ }
1407
+ ```
1408
+
1409
+ - **Props** (`FilterBarProps`). `model`, `params`, `onParamsChange`, then
1410
+ `locked`, `codec` (a `FilterUrlCodec`: `keepKnownValues`, `encoding`, the
1411
+ loader's own options), `reset` (the params dropped on every write, a cursor
1412
+ or a page number), `defaults` (the values of the `default: 'page'` fields,
1413
+ the loader's own; see [A field's default](#a-fields-default)),
1414
+ `resultCount`, `loading`; every other prop of `Filter variant="bar"`
1415
+ (`quick`, `counts`, `previewCount`, `fieldProps`, `density`, `shortcuts`,
1416
+ `searchApply`, `searchMinLength`, `errors`, `label`...) passes through. There is no `query`,
1417
+ `defaultQuery` nor `onQueryChange`: the URL is the query.
1418
+ - **One write.** An edit writes the search, every `f=` and the aliased params,
1419
+ drops the `reset` ones and keeps the page's others (a tab, a sort).
1420
+ `onParamsChange` receives the next params for your router; the bar then
1421
+ holds the count back until the router has taken them, and until `loading`
1422
+ ends. Pass `replace`, so Back leaves the list rather than undoing every chip;
1423
+ a Back or a link that changes the params shows at once.
1424
+ - **The hook.** `useFilterUrlQuery(options)` takes a
1425
+ `UseFilterUrlQueryOptions` (`{ model, params, onParamsChange, locked,
1426
+ defaults, codec, reset }`) and returns a `FilterUrlQuery` (`{ query,
1427
+ onQueryChange, waiting, heading }`): the bar's URL half, for a page that
1428
+ lays `Filter` out itself.
1429
+ `ServerTable` uses the same hook, so a list and a table write the same URL.
1430
+ - **Not a router.** Nothing is imported from one: `params` is a
1431
+ `URLSearchParams`, and `onParamsChange` is yours.
1432
+
1376
1433
  #### Locked conditions
1377
1434
 
1378
1435
  A condition the page imposes (a class's roster, the school year) goes in
@@ -1411,6 +1468,116 @@ for you), pass the table `announceEmpty={false}` and `announceLoading={false}`:
1411
1468
  the bar's live region tells the count and "no results", so the table's own
1412
1469
  status stays quiet and the answer is said once.
1413
1470
 
1471
+ #### A field's default
1472
+
1473
+ A field declared with a `default` (a fixed list, or `'page'` with a `defaults`
1474
+ prop the page computes per request, the loader's own) narrows the list while the
1475
+ user has chosen nothing for it. `Filter`, `FilterBar` and `ServerTable`'s
1476
+ `filter` take `defaults`; the display is:
1477
+
1478
+ | Field | Shown as |
1479
+ | --- | --- |
1480
+ | select, multi-select, any non-quick field | a hint chip in the active filters, "Status: Active, Upcoming · Default": dashed, no ✕, a button named "Status: Active, Upcoming, default value. Change" that opens the field's editor on the default, like an applied chip |
1481
+ | quick pill | the pill reads the default, tagged "· Default" (`material.filter.default.tag`, for the eye only: the pill is described "Default value, …"), and opens its editor, which shows the default checked; no ✕ until the user picks a value |
1482
+ | switch or checkbox quick toggle | pressed (`aria-pressed`), marked "Default" and described so; pressing writes an explicit "No" |
1483
+ | facets panel and phone sheet | the default values checked, "Default" beside the field's title (`FacetGroup`'s `hint`); the section starts open |
1484
+
1485
+ A default is never in `query`: it is not counted in "Filters (N)" or the
1486
+ announcement. Choosing or changing a value replaces it (removing the last value
1487
+ returns to it). "Clear all" returns the fields to their defaults. A locked field shows
1488
+ its lock only. The words are `material.filter.default.*`.
1489
+
1490
+ ```tsx
1491
+ // `status` has a fixed `default: ['active', 'upcoming']`: its hint chip needs no
1492
+ // prop. `mine` is a switch with `default: 'page'`: the page gives its value.
1493
+ <FilterBar model={EVENT_FILTERS} params={params} onParamsChange={setParams}
1494
+ defaults={{ mine: ['1'] }} />
1495
+ <ServerTable filter={{ model: EVENT_FILTERS, defaults: { mine: ['1'] } }} {...table} />
1496
+ ```
1497
+
1498
+ #### A scope field
1499
+
1500
+ A list scoped by a value the user changes but never clears (the period or the
1501
+ workspace it shows) declares `scope: true`. It is not a narrowing filter, so
1502
+ it is never counted, chipped or cleared, and it needs a `default` (the value
1503
+ while the user chose none) and a single-value type (`select`, `radio-group` or
1504
+ `chips-single`); `defineFilterModel` throws without a default, with another
1505
+ type, or together with `widens` (a field is one role or the other).
1506
+
1507
+ ```ts
1508
+ { id: 'period', type: 'select', label: 'Period', options: PERIODS,
1509
+ scope: true, default: 'page' } // or default: ['p2']
1510
+ ```
1511
+
1512
+ - **Its control** is the bar's leading pill, "Period: P2": a button
1513
+ (`aria-haspopup="dialog"`) that opens the field's editor, with the value
1514
+ always shown (the default while the user chose none, with no "Default" tag)
1515
+ and no ✕. `ServerTable`'s band shows it the same way, and the facets panel
1516
+ and the phone sheet list it as the first section, with no count and no
1517
+ Clear. On a phone the pill stays in the bar beside the search (44px
1518
+ target): a tap opens the filters sheet on the period's section, focused,
1519
+ not a popover. Below 640px the search takes the whole first row, and the
1520
+ pill and "Filters" share the second (pill first, "Filters" at the end);
1521
+ without a scope field the single row stays.
1522
+ - **Not a filter.** It is never a chip, never in "Add filter", and never
1523
+ counted: not in "Filters (N)", not in the announcement, not in `isFiltered`
1524
+ or `isNarrowing`. "Clear all" and `withoutFilters` keep it, so the list
1525
+ keeps its scope; "Clear all" shows from two filters *beside* it.
1526
+ - **In the URL** it is an explicit choice like any other (`f=period:is:p1`, or
1527
+ its alias); an invalid value means the default. It filters the rows
1528
+ (`matchQuery`, `effectiveConditions`) as any field does. A `locked`
1529
+ condition on it wins: the lock chip shows, the pill does not.
1530
+ - **Core.** `isKeptField(model, id)` is true for a `widens` or a `scope`
1531
+ field, `isScopeField(model, id)` for a scope alone.
1532
+
1533
+ #### A field only a link sets
1534
+
1535
+ A field a detail page sets through a link (`/items?item=abc`) must be in the
1536
+ model, so its condition is parsed, filters the rows and shows as a chip. Declare
1537
+ it `addable: false` so the user is never offered it with nothing to pick:
1538
+
1539
+ ```ts
1540
+ { id: 'item', type: 'autocomplete', label: 'Item', style: 'single', multiple: false,
1541
+ addable: false }
1542
+ ```
1543
+
1544
+ It is a plain filter in every other way: read from the URL and written back,
1545
+ a chip with its ✕ while it has a value, counted, and removed by "Clear all"
1546
+ (unlike a `scope` field, which is always shown and never cleared). It is
1547
+ left out of "Add filter" and of the quick filters (also when listed in
1548
+ `quick`), and the phone sheet and the facets panel list its section only
1549
+ while the applied query holds a value. Core: `isAddableField(model, id)`.
1550
+
1551
+ #### A refused condition
1552
+
1553
+ A server can refuse a value (a date span too long, an end before a start).
1554
+ Pass its message per field id, a record `{ [fieldId]: message }`, as `errors`
1555
+ (`Filter`, `FilterBar` and `ServerTable`'s `filter`), built from what the
1556
+ loader's API answered:
1557
+
1558
+ ```tsx
1559
+ <ServerTable filter={{ model, errors: { period: 'The period cannot exceed 366 days.' } }} {...table} />
1560
+ ```
1561
+
1562
+ The field's control turns to the error tone and reads "Invalid" (an icon and
1563
+ a word, never colour alone): a chip, a quick pill, a scope pill (on a phone
1564
+ too), a quick switch or checkbox toggle, and the default chip. It is described "Invalid: <message>"; its
1565
+ editor and its facets section show the message under the title; and the
1566
+ polite live region tells it ("Period: The period cannot exceed 366 days."),
1567
+ once, after the count, also when the page opens with it; the next count replaces it. A dashed control (a toggle, the default chip) keeps its dashes
1568
+ and takes the error tone on its line and text. Only a field of the model that the page does not lock shows
1569
+ one. The page clears it when the condition changes, by passing no error. The
1570
+ words are `material.filter.error.*`; `fieldErrors(errors, model, locked)` in
1571
+ the core lists what the bar shows.
1572
+
1573
+ #### A list without a search box
1574
+
1575
+ `defineFilterModel({ search: false, fields })` declares a list with no text
1576
+ search (invitations by status, where the API has none): the bar, the facets
1577
+ panel and the phone sheet render no search box, `/` goes to the first quick
1578
+ filter (nothing without one), and the codec neither reads nor writes the
1579
+ search param, so `q` is free for a field. `model.search.enabled` tells.
1580
+
1414
1581
  #### Quick filters
1415
1582
 
1416
1583
  Fields declared `quick: true` in the model (or listed in `quick`) show as
@@ -1439,6 +1606,19 @@ archived") is a switch or checkbox in its editor, and off removes its
1439
1606
  condition (it never writes `0`). A plain boolean ("Scholarship") offers Yes
1440
1607
  and No as two radios, and "No" is a condition of its own, with its chip.
1441
1608
 
1609
+ A switch that only narrows ("Only unassigned") declares `off: 'remove'`
1610
+ (`'no'` is the default; with `widens: true` it is `'remove'`, and `widens`
1611
+ with `off: 'no'` throws). Its editor is one switch, with no Yes or No; on
1612
+ is a filter like any other, counted ("Clear all" appears, the phone sheet
1613
+ counts it) and shown as a chip, and off removes the condition and writes
1614
+ nothing to the URL. An old `?f=unassigned:is:0` link on such a field is
1615
+ dropped silently, so it shows every row. A field that does not opt in
1616
+ behaves as before.
1617
+
1618
+ ```ts
1619
+ { id: 'unassigned', type: 'switch', label: 'Only unassigned', off: 'remove' }
1620
+ ```
1621
+
1442
1622
  A chip's popover is titled with its field and operator ("Level is not") and
1443
1623
  edits the values only. To change the operator, go back through "Add filter":
1444
1624
  it lists an active field with its current condition, and picking it
@@ -1869,6 +2049,7 @@ const [levels, setLevels] = useState<string[]>(['ce1']);
1869
2049
  | Prop | Type | Default | Effect |
1870
2050
  | --- | --- | --- | --- |
1871
2051
  | `title` | `string` | — | the facet's name, in the header; a string, because it builds the accessible names |
2052
+ | `hint` | `ReactNode` | — | a quiet word after the title (a field's "Default"); part of the toggle's name unless `activeCount > 0` names it |
1872
2053
  | `activeCount` | `number` | `0` | how many values are active: the count Badge (hidden at 0) and the toggle's name |
1873
2054
  | `onClear` | `() => void` | — | the "Clear" button, shown while `activeCount > 0`; the focus then goes to the toggle |
1874
2055
  | `open` / `defaultOpen` / `onOpenChange` | `boolean` / `boolean` / `(open) => void` | uncontrolled, open | controlled or not |
@@ -207,7 +207,7 @@ import { AuthCard, Button, EmailField, LanguageSwitcher, PasswordField } from '@
207
207
  | `banner` | `ReactNode` | — | above that row (an update notice) |
208
208
  | `footer` | `ReactNode` | — | under the card |
209
209
  | `backdrop` | `ReactNode \| false` | the theme's background | what is drawn behind the page: a `Background` preset or any node; `false` for none. Without a theme provider nothing is drawn |
210
- | `keepClear` | `boolean` | `true` | glyphs (shapes or icons) of the backdrop that would meet the brand row, the card or the page's surfaces, text or controls are dropped (never moved); `false` lets them run under the card |
210
+ | `keepClear` | `boolean \| 'gaps'` | `true` | glyphs (shapes or icons) of the backdrop that would meet the brand row, the card or the page's surfaces, text or controls are dropped (never moved); `false` lets them run under the card; `'gaps'` also keeps a glyph that fits in a gap of 24px or more between two surfaces |
211
211
 
212
212
  ```tsx
213
213
  import { Background } from '@nxgt/material/backgrounds';
@@ -210,6 +210,7 @@ partitionMenu(items); // { content, footer }
210
210
  | `menuOpen` | `boolean` | — | Controls the phone's menu sheet: open while `true`. Leave it out and the layout manages the sheet. Only a phone shows the sheet |
211
211
  | `onMenuOpenChange` | `(open: boolean) => void` | — | Called for every change of the sheet: the menu button, Escape, the close button, a followed link, a new location |
212
212
  | `backdrop` | `ReactNode \| false` | — | An exception to the theme's background (the page ground, [`--ground`](#the-page-ground), is painted either way), which the layout draws by default (Lavande's: the built-in gradient and blobs). A node replaces it for this screen: usually a `Background` preset from `@nxgt/material/backgrounds` (see [Use a background preset behind the shell](#use-a-background-preset-behind-the-shell)); `false` draws no background, a plain page |
213
+ | `keepClear` | `boolean \| 'gaps'` | `true` | how the backdrop's glyphs keep clear of the page: `true` drops every glyph within 8px of a surface, a text or a control; `'gaps'` also keeps a glyph that fits in a gap of 24px or more between two surfaces; `false` keeps nothing clear (the edge and the header band still are). See [Keep the backdrop clear of the content](#keep-the-backdrop-clear-of-the-content) |
213
214
 
214
215
  On a page with `viewport-fit=cover` (an installed PWA drawing under a
215
216
  notch and the home indicator), the shell pads clear of
@@ -646,6 +647,43 @@ export function Shell({ items }: { items: MenuItem[] }) {
646
647
  - The `--nxgt-bg-blob-1..3` variables recolour the built-in blobs only; the
647
648
  `blobs` preset reads them too.
648
649
 
650
+ ## Keep the backdrop clear of the content
651
+
652
+ Behind the shell a glyph of the backdrop (a shape or an icon) is dropped, never
653
+ moved, when its box meets the page's content. `keepClear` sets how strict that
654
+ is:
655
+
656
+ | `keepClear` | Result |
657
+ | --- | --- |
658
+ | `true` (default) | a glyph within 8px of a surface (a card, a stat card, a list, a table), a text or a control is dropped |
659
+ | `'gaps'` | the same for text, controls and the inside of a surface, but a glyph may stay between two surfaces when its whole box fits in a gap of 24px or more (4px to spare from each card) |
660
+ | `false` | the content is not measured; only the layer's edge and the header band drop a glyph |
661
+
662
+ On a dense page (stat cards, a list, a grid of cards 24 to 32px apart) `true`
663
+ leaves almost no glyph. `'gaps'` is opt-in and keeps the glyphs small enough
664
+ for the gutters, so use it on such a page. It adds little on a page with wide
665
+ open areas, where `true` already draws them. It never keeps a glyph that sits
666
+ on a card, on text or on a control, and it measures the same way as `true`:
667
+ boxes are read first, then written in one frame, with the 150 ms fade. A
668
+ floating (`animated`) scene keeps its drift margin, so it rarely fits a gutter.
669
+
670
+ ```tsx
671
+ import { ActivityLayout } from '@nxgt/material/components';
672
+ import { Background, MOTIF_SHAPES_ALL } from '@nxgt/material/backgrounds';
673
+
674
+ <ActivityLayout
675
+ items={items}
676
+ backdrop={<Background preset="shapes" motif={{ shapes: MOTIF_SHAPES_ALL }} />}
677
+ keepClear="gaps"
678
+ >
679
+ <Outlet />
680
+ </ActivityLayout>
681
+ ```
682
+
683
+ `AuthCard` takes the same prop (`keepClear="gaps"`). Its card and brand row
684
+ are kept whole, so there it only adds glyphs between the page's other
685
+ surfaces, such as a banner.
686
+
649
687
  ## Route transitions
650
688
 
651
689
  `ActivityLayout` wraps its content region (`data-slot="activity-content-region"`)
@@ -548,6 +548,11 @@ good.
548
548
  away. It runs again on resize and when the content changes.
549
549
  - The open areas keep their glyphs; the space behind and between cards is empty. `keepClear={false}` on an `AuthCard`
550
550
  lets the glyphs run under the card.
551
+ - **`keepClear="gaps"`** (on `ActivityLayout` and `AuthCard`, opt-in; `true` stays the default) lets a glyph stay between
552
+ two surfaces when its whole box fits in a gap of 24 px or more, with 4 px to spare from each. It is still dropped when
553
+ it meets a text, a control or the inside of a surface. Use it on a dense page (stat cards, a list and a grid of cards
554
+ 24 to 32 px apart), where `true` leaves almost nothing. A glyph wider than the gap is dropped as before. See
555
+ [Keep the backdrop clear of the content](./app-shell.md#keep-the-backdrop-clear-of-the-content).
551
556
  - See [The theme's background](./app-shell.md#the-themes-background) for the shell and `AuthCard` in
552
557
  [navigation and layout](../components/navigation-and-layout.md#authcard) for the sign-in page.
553
558
 
@@ -286,6 +286,13 @@ chip's description), and a chip's words: `chip` "{field} {operator}
286
286
  `operator` "Operator", `operator-placeholder` "Operator…", `no-operator`,
287
287
  `back` "Back", `done` "Done", `live` "Applied as you go" and `no-value` "No
288
288
  value to enter." (an operator such as "is empty")),
289
+ `material.filter.default.*` for a field's default shown as a hint (`label`
290
+ "Default", `hint` "Default value, in effect until you choose one", `tag`
291
+ "· {default}" after a title, a pill's or a toggle's words, and `change`
292
+ "{filter}, default value. Change", the hint chip's name),
293
+ `material.filter.error.*` for a condition the server refused (`tag`
294
+ "Invalid", `label` "Invalid: {message}", the chip's description, and
295
+ `announce` "{field}: {message}", told in the live region),
289
296
  `material.filter.announce.*` for its live region (`results`, `cleared`,
290
297
  `cleared-count`, `added`, `added-count`, each an ICU plural over `count`),
291
298
  `material.filter.summary.*` for values (`yes`, `no`, `quoted`, `range-and`,