@nxgt/material 3.7.5 → 3.8.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 (176) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +39 -6
  3. package/bin/nxgt-theme.js +6 -0
  4. package/dist/{async-slice-o_fpqeGX.js → async-slice-DDjaJY_F.js} +2 -2
  5. package/dist/background--Bf_EbFR.js +159 -0
  6. package/dist/backgrounds/backgrounds.css +2 -0
  7. package/dist/backgrounds/css-react/moon.css +97 -0
  8. package/dist/backgrounds.js +3 -139
  9. package/dist/browser-only-DQ94lWF8.js +18 -0
  10. package/dist/bubble-input-B7BVd9fX.js +237 -0
  11. package/dist/{button--cF4gY14.js → button-DbfdITBB.js} +51 -57
  12. package/dist/charts.js +3 -3
  13. package/dist/{chip-D1B1dL77.js → chip-DpySRqCy.js} +2 -2
  14. package/dist/{client-only.utils-lQ7GqP8w.js → client-only.utils-3nHNzCki.js} +1 -1
  15. package/dist/{code-editor-0CdGwKDg.js → code-editor-BiA14xua.js} +7 -7
  16. package/dist/code-editor.js +6 -6
  17. package/dist/{code-language-items-CGARRbVm.js → code-language-items-C_dJ6GVs.js} +2 -2
  18. package/dist/components/theme-tokens.css +34 -35
  19. package/dist/components/tones/app-tones.css +2 -1
  20. package/dist/components/tones/containers.css +4 -1
  21. package/dist/components/tones/index.css +2 -0
  22. package/dist/components/tones/surface.css +1 -0
  23. package/dist/components/tones/tokens.css +8 -3
  24. package/dist/components/tones/zone-paint.css +15 -0
  25. package/dist/components/ui/feedback/toast/toast-tokens.css +1 -0
  26. package/dist/components/ui/layout/app-shell/activity-backdrop.css +26 -0
  27. package/dist/components/ui/layout/sidebar/sidebar-tokens.css +5 -2
  28. package/dist/components/ui/media/media-player/nxgt-media-player.css +7 -32
  29. package/dist/components/ui/primitives/field-box/field-box-tokens.css +5 -2
  30. package/dist/{components-CDrQCOsU.js → components-B9EIfMdd.js} +18622 -18531
  31. package/dist/components.js +24 -22
  32. package/dist/{dialog-DdJ1C4BR.js → dialog-CkIYpJXk.js} +55 -53
  33. package/dist/dist-B7RjY7SL.js +158 -0
  34. package/dist/dist-C4wtXCjf.js +593 -0
  35. package/dist/dist-DVRQkaTK.js +111 -0
  36. package/dist/dist-lmHmz_bu.js +419 -0
  37. package/dist/dnd.js +1 -1
  38. package/dist/dropdown-menu-BC5Tbhb9.js +908 -0
  39. package/dist/editor.js +527 -527
  40. package/dist/empty-state-s2CSjKXJ.js +126 -0
  41. package/dist/{escape-owner-B8k7DvFa.js → escape-owner-CripBce_.js} +2 -1
  42. package/dist/{field-blur-DFUazxsL.js → field-blur-DPLsMufs.js} +1 -1
  43. package/dist/{field-blur-context-Dw9ZAgBr.js → field-blur-context-1ZwJgsHE.js} +2 -2
  44. package/dist/has-text-content-Ds2dkHX_.js +10 -0
  45. package/dist/hooks.js +35 -33
  46. package/dist/{hover-card-D5iHS9q1.js → hover-card-Cox-tPDz.js} +41 -39
  47. package/dist/{i18n-provider-C6SBK_nO.js → i18n-provider-C6HhBw34.js} +1 -1
  48. package/dist/i18n.js +6 -6
  49. package/dist/{icon-badge-Bb5-73XP.js → icon-badge-q3Ve8gra.js} +3 -3
  50. package/dist/{icon-button-5A6Mrj6w.js → icon-button-DJcWpIhu.js} +2 -1
  51. package/dist/{in-dialog-AiwTD3DK.js → in-dialog-Vwkyp-M5.js} +6 -5
  52. package/dist/lib/backgrounds/background/available.d.ts +3 -3
  53. package/dist/lib/backgrounds/background/background.d.ts +7 -3
  54. package/dist/lib/backgrounds/background/types.d.ts +7 -1
  55. package/dist/lib/backgrounds/index.d.ts +1 -1
  56. package/dist/lib/components/ui/layout/app-shell/activity-chrome.d.ts +17 -0
  57. package/dist/lib/components/ui/layout/app-shell/activity-layout.d.ts +6 -4
  58. package/dist/lib/components/ui/layout/app-shell/backdrop-layer.d.ts +11 -0
  59. package/dist/lib/components/ui/layout/app-shell/keep-shapes-inside.d.ts +17 -0
  60. package/dist/lib/components/ui/layout/app-shell/theme-backdrop.d.ts +6 -0
  61. package/dist/lib/components/ui/layout/app-shell/use-activity-backdrop.d.ts +18 -0
  62. package/dist/lib/components/ui/layout/app-shell/use-keep-shapes-inside.d.ts +9 -0
  63. package/dist/lib/hooks/resolve-theme.d.ts +46 -1
  64. package/dist/lib/hooks/theme-store.d.ts +35 -4
  65. package/dist/lib/hooks/use-theme.d.ts +20 -4
  66. package/dist/lib/i18n/resources/en/en.d.ts +4 -0
  67. package/dist/lib/i18n/resources/en/material.json.d.ts +4 -0
  68. package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
  69. package/dist/lib/i18n/resources/fr/material.json.d.ts +4 -0
  70. package/dist/lib/i18n/resources/resources.d.ts +8 -0
  71. package/dist/lib/i18n/translator.d.ts +1 -1
  72. package/dist/lib/theme-picker/index.d.ts +7 -0
  73. package/dist/lib/theme-picker/partials/mini-background.d.ts +10 -0
  74. package/dist/lib/theme-picker/partials/mode-control.d.ts +5 -0
  75. package/dist/lib/theme-picker/partials/theme-tile.d.ts +12 -0
  76. package/dist/lib/theme-picker/theme-label.d.ts +7 -0
  77. package/dist/lib/theme-picker/theme-picker.d.ts +25 -0
  78. package/dist/lib/themes/index.d.ts +14 -0
  79. package/dist/lib/themes/nxgt-theme-provider.d.ts +29 -0
  80. package/dist/lib/themes/nxgt-theme.d.ts +22 -0
  81. package/dist/lib/themes/theme-context.d.ts +28 -0
  82. package/dist/lib/themes/theme-value.d.ts +5 -0
  83. package/dist/lib/vite/index.d.ts +1 -1
  84. package/dist/lib.js +3 -3
  85. package/dist/main.js +43 -39
  86. package/dist/map.js +8 -8
  87. package/dist/material.css +1 -1
  88. package/dist/nxgt-theme-CgSb9Obl.js +37 -0
  89. package/dist/pdf-reader.js +1 -1
  90. package/dist/print.js +2 -2
  91. package/dist/{public-SsiazLEv.js → public-Ce30uvp0.js} +591 -587
  92. package/dist/read-storage-C2J90bNm.js +10 -0
  93. package/dist/{rich-code-block-CwNwQs5z.js → rich-code-block-C2Fp_FDU.js} +5 -5
  94. package/dist/{sortable-provider-BvD98s8Y.js → sortable-provider-pVaEZzty.js} +3 -3
  95. package/dist/{spinner-CtGCPza-.js → spinner-CsHcmcpF.js} +2 -2
  96. package/dist/{stored-language-Bb7yX5uE.js → stored-language-BeIKw3-K.js} +15 -15
  97. package/dist/styles.css +8 -1
  98. package/dist/theme-context-BagPvRcz.js +16 -0
  99. package/dist/theme-picker.js +118 -0
  100. package/dist/theme-store-CSl51uNH.js +91 -0
  101. package/dist/theme-toggle-C8os82b4.js +48 -0
  102. package/dist/themes.js +42 -0
  103. package/dist/toggle-group-j8zaxEg1.js +69 -0
  104. package/dist/{toolbar-items-DsDDD5AY.js → toolbar-items-CqHvlTU8.js} +443 -589
  105. package/dist/tooltip-rhbqNmr3.js +1064 -0
  106. package/dist/{translate-material-Bsjc4Tow.js → translate-material-CGZljjp1.js} +2 -2
  107. package/dist/{translator-or2y0JJB.js → translator-DCYO4Ij3.js} +3 -3
  108. package/dist/{use-background-activity-B8jLHNop.js → use-background-activity-KxQgelFF.js} +1 -1
  109. package/dist/{use-chat-composer-DZ01a16D.js → use-chat-composer-CDrgWGMM.js} +4684 -4886
  110. package/dist/{use-heading-spy-ByOQNnFZ.js → use-heading-spy-DXo6IOX9.js} +52 -121
  111. package/dist/{use-material-translation-hLQzOjF0.js → use-material-translation-DkxcLbLM.js} +2 -2
  112. package/dist/use-slice-reducer-BGkeGtML.js +42 -0
  113. package/dist/use-theme-Cd-aiDJo.js +31 -0
  114. package/docs/README.md +2 -1
  115. package/docs/components/foundations.md +39 -0
  116. package/docs/components/navigation-and-layout.md +3 -3
  117. package/docs/getting-started.md +1 -1
  118. package/docs/guides/app-shell.md +41 -6
  119. package/docs/guides/backgrounds.md +43 -7
  120. package/docs/guides/i18n.md +1 -1
  121. package/docs/guides/themes.md +103 -0
  122. package/docs/guides/theming.md +288 -84
  123. package/docs/guides/vite-plugin.md +26 -0
  124. package/docs/previews/backgrounds-background-from-theme.webp +0 -0
  125. package/docs/previews/backgrounds-geometry-more.webp +0 -0
  126. package/docs/previews/backgrounds-geometry.webp +0 -0
  127. package/docs/previews/backgrounds-illustrated-scenes.webp +0 -0
  128. package/docs/previews/backgrounds-light-more.webp +0 -0
  129. package/docs/previews/backgrounds-light.webp +0 -0
  130. package/docs/previews/backgrounds-material-more.webp +0 -0
  131. package/docs/previews/backgrounds-matrix.webp +0 -0
  132. package/docs/previews/backgrounds-moon.webp +0 -0
  133. package/docs/previews/backgrounds-motif-shapes.webp +0 -0
  134. package/docs/previews/backgrounds-motifs.webp +0 -0
  135. package/docs/previews/foundations-themes-themepicker.webp +0 -0
  136. package/docs/roadmap.md +25 -0
  137. package/docs/troubleshooting.md +35 -7
  138. package/lib/backgrounds/backgrounds.css +2 -0
  139. package/lib/backgrounds/css-react/moon.css +97 -0
  140. package/lib/components/theme-tokens.css +34 -35
  141. package/lib/components/tones/app-tones.css +2 -1
  142. package/lib/components/tones/containers.css +4 -1
  143. package/lib/components/tones/index.css +2 -0
  144. package/lib/components/tones/surface.css +1 -0
  145. package/lib/components/tones/tokens.css +8 -3
  146. package/lib/components/tones/zone-paint.css +15 -0
  147. package/lib/components/ui/feedback/toast/toast-tokens.css +1 -0
  148. package/lib/components/ui/layout/app-shell/activity-backdrop.css +26 -0
  149. package/lib/components/ui/layout/sidebar/sidebar-tokens.css +5 -2
  150. package/lib/components/ui/media/media-player/nxgt-media-player.css +7 -32
  151. package/lib/components/ui/primitives/field-box/field-box-tokens.css +5 -2
  152. package/lib/styles.css +8 -1
  153. package/lib/theme-picker/theme-picker-list.css +29 -0
  154. package/lib/theme-picker/theme-picker.css +192 -0
  155. package/lib/theme-picker/theme-tile-background.css +77 -0
  156. package/lib/theme-picker/theme-tile-textures-night.css +63 -0
  157. package/lib/theme-picker/theme-tile-textures.css +153 -0
  158. package/lib/themes/ambre.css +134 -0
  159. package/lib/themes/ardoise.css +133 -0
  160. package/lib/themes/bleumono.css +136 -0
  161. package/lib/themes/bluemoon.css +136 -0
  162. package/lib/themes/corail.css +136 -0
  163. package/lib/themes/foret.css +133 -0
  164. package/lib/themes/lavande.css +133 -0
  165. package/lib/themes/menthe.css +136 -0
  166. package/lib/themes/ocean.css +136 -0
  167. package/lib/themes/pink.css +134 -0
  168. package/lib/themes/prune.css +133 -0
  169. package/lib/themes/sable.css +133 -0
  170. package/lib/themes/slate.css +133 -0
  171. package/lib/themes/teal.css +137 -0
  172. package/package.json +30 -2
  173. package/dist/dropdown-menu-DWtgUVW7.js +0 -1490
  174. package/dist/empty-state-CRWLQ1sM.js +0 -191
  175. package/dist/tooltip-tmFoTU_d.js +0 -1582
  176. package/dist/use-slice-reducer-0r5dXnJe.js +0 -58
@@ -1,77 +1,8 @@
1
- import { n as e } from "./stored-language-Bb7yX5uE.js";
2
- import { r as t } from "./i18n-provider-C6SBK_nO.js";
3
- import { t as n } from "./use-ssr-media-query-C6M5m8sf.js";
4
- import { _ as r, g as i, h as a, n as o, v as s, y as c } from "./number.utils-BG_eEt5g.js";
5
- import { useCallback as l, useEffect as u, useMemo as d, useRef as f, useState as p, useSyncExternalStore as m } from "react";
6
- //#region lib/hooks/resolve-theme.ts
7
- function h(e, t) {
8
- let n = e === "light" || e === "dark" ? e : "system";
9
- return {
10
- theme: n === "system" ? t ? "dark" : "light" : n,
11
- preference: n
12
- };
13
- }
14
- function g(e) {
15
- typeof document > "u" || (document.documentElement.classList.toggle("dark", e === "dark"), document.documentElement.style.colorScheme = e);
16
- }
17
- //#endregion
18
- //#region lib/hooks/use-is-client.ts
19
- function _() {
20
- let [e, t] = p(!1);
21
- return u(() => {
22
- t(!0);
23
- }, []), e;
24
- }
25
- //#endregion
26
- //#region lib/hooks/theme-store.ts
27
- var v = "theme", y = /* @__PURE__ */ new Set(), b;
28
- function x() {
29
- let t = e(v);
30
- if (t == null) return b;
31
- try {
32
- let e = JSON.parse(t);
33
- return typeof e == "string" ? e : void 0;
34
- } catch {
35
- return t;
36
- }
37
- }
38
- function S() {
39
- for (let e of y) e();
40
- }
41
- function C(e) {
42
- (e.key === v || e.key === null) && S();
43
- }
44
- var w = {
45
- subscribe(e) {
46
- return y.add(e), y.size === 1 && typeof window < "u" && window.addEventListener("storage", C), () => {
47
- y.delete(e), y.size === 0 && typeof window < "u" && window.removeEventListener("storage", C);
48
- };
49
- },
50
- getSnapshot: x,
51
- getServerSnapshot: () => void 0,
52
- set(e) {
53
- b = e === "system" ? void 0 : e;
54
- try {
55
- e === "system" ? globalThis.localStorage?.removeItem(v) : globalThis.localStorage?.setItem(v, JSON.stringify(e));
56
- } catch {}
57
- S();
58
- }
59
- };
60
- //#endregion
61
- //#region lib/hooks/use-theme.ts
62
- function T() {
63
- let e = n("(prefers-color-scheme: dark)", !1), { theme: t, preference: r } = h(m(w.subscribe, w.getSnapshot, w.getServerSnapshot), e);
64
- return {
65
- theme: t,
66
- preference: r,
67
- updateTheme: l((t) => {
68
- w.set(t), g(h(t === "system" ? void 0 : t, e).theme);
69
- }, [e])
70
- };
71
- }
72
- //#endregion
1
+ import { r as e } from "./i18n-provider-C6HhBw34.js";
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
+ import { useCallback as s, useEffect as c, useMemo as l, useRef as u } from "react";
73
4
  //#region ../../node_modules/date-fns/locale/fr/_lib/formatDistance.js
74
- var E = {
5
+ var d = {
75
6
  lessThanXSeconds: {
76
7
  one: "moins d’une seconde",
77
8
  other: "moins de {{count}} secondes"
@@ -133,11 +64,11 @@ var E = {
133
64
  one: "presqu’un an",
134
65
  other: "presque {{count}} ans"
135
66
  }
136
- }, D = (e, t, n) => {
137
- let r, i = E[e];
67
+ }, f = (e, t, n) => {
68
+ let r, i = d[e];
138
69
  return r = typeof i == "string" ? i : t === 1 ? i.one : i.other.replace("{{count}}", String(t)), n?.addSuffix ? n.comparison && n.comparison > 0 ? "dans " + r : "il y a " + r : r;
139
- }, O = {
140
- date: c({
70
+ }, p = {
71
+ date: o({
141
72
  formats: {
142
73
  full: "EEEE d MMMM y",
143
74
  long: "d MMMM y",
@@ -146,7 +77,7 @@ var E = {
146
77
  },
147
78
  defaultWidth: "full"
148
79
  }),
149
- time: c({
80
+ time: o({
150
81
  formats: {
151
82
  full: "HH:mm:ss zzzz",
152
83
  long: "HH:mm:ss z",
@@ -155,7 +86,7 @@ var E = {
155
86
  },
156
87
  defaultWidth: "full"
157
88
  }),
158
- dateTime: c({
89
+ dateTime: o({
159
90
  formats: {
160
91
  full: "{{date}} 'à' {{time}}",
161
92
  long: "{{date}} 'à' {{time}}",
@@ -164,18 +95,18 @@ var E = {
164
95
  },
165
96
  defaultWidth: "full"
166
97
  })
167
- }, k = {
98
+ }, m = {
168
99
  lastWeek: "eeee 'dernier à' p",
169
100
  yesterday: "'hier à' p",
170
101
  today: "'aujourd’hui à' p",
171
102
  tomorrow: "'demain à' p'",
172
103
  nextWeek: "eeee 'prochain à' p",
173
104
  other: "P"
174
- }, A = (e, t, n, r) => k[e], j = {
105
+ }, h = (e, t, n, r) => m[e], g = {
175
106
  narrow: ["av. J.-C", "ap. J.-C"],
176
107
  abbreviated: ["av. J.-C", "ap. J.-C"],
177
108
  wide: ["avant Jésus-Christ", "après Jésus-Christ"]
178
- }, M = {
109
+ }, _ = {
179
110
  narrow: [
180
111
  "T1",
181
112
  "T2",
@@ -194,7 +125,7 @@ var E = {
194
125
  "3ème trimestre",
195
126
  "4ème trimestre"
196
127
  ]
197
- }, N = {
128
+ }, v = {
198
129
  narrow: [
199
130
  "J",
200
131
  "F",
@@ -237,7 +168,7 @@ var E = {
237
168
  "novembre",
238
169
  "décembre"
239
170
  ]
240
- }, P = {
171
+ }, y = {
241
172
  narrow: [
242
173
  "D",
243
174
  "L",
@@ -274,7 +205,7 @@ var E = {
274
205
  "vendredi",
275
206
  "samedi"
276
207
  ]
277
- }, F = {
208
+ }, b = {
278
209
  narrow: {
279
210
  am: "AM",
280
211
  pm: "PM",
@@ -305,7 +236,7 @@ var E = {
305
236
  evening: "du soir",
306
237
  night: "du matin"
307
238
  }
308
- }, I = (e, t) => {
239
+ }, x = (e, t) => {
309
240
  let n = Number(e), r = t?.unit;
310
241
  if (n === 0) return "0";
311
242
  let i = [
@@ -316,48 +247,48 @@ var E = {
316
247
  "second"
317
248
  ], a;
318
249
  return a = n === 1 ? r && i.includes(r) ? "ère" : "er" : "ème", n + a;
319
- }, L = ["MMM", "MMMM"], R = {
320
- en: a,
250
+ }, S = ["MMM", "MMMM"], C = {
251
+ en: r,
321
252
  fr: {
322
253
  code: "fr",
323
- formatDistance: D,
324
- formatLong: O,
325
- formatRelative: A,
254
+ formatDistance: f,
255
+ formatLong: p,
256
+ formatRelative: h,
326
257
  localize: {
327
- preprocessor: (e, t) => e.getDate() === 1 || !t.some((e) => e.isToken && L.includes(e.value)) ? t : t.map((e) => e.isToken && e.value === "do" ? {
258
+ preprocessor: (e, t) => e.getDate() === 1 || !t.some((e) => e.isToken && S.includes(e.value)) ? t : t.map((e) => e.isToken && e.value === "do" ? {
328
259
  isToken: !0,
329
260
  value: "d"
330
261
  } : e),
331
- ordinalNumber: I,
332
- era: s({
333
- values: j,
262
+ ordinalNumber: x,
263
+ era: a({
264
+ values: g,
334
265
  defaultWidth: "wide"
335
266
  }),
336
- quarter: s({
337
- values: M,
267
+ quarter: a({
268
+ values: _,
338
269
  defaultWidth: "wide",
339
270
  argumentCallback: (e) => e - 1
340
271
  }),
341
- month: s({
342
- values: N,
272
+ month: a({
273
+ values: v,
343
274
  defaultWidth: "wide"
344
275
  }),
345
- day: s({
346
- values: P,
276
+ day: a({
277
+ values: y,
347
278
  defaultWidth: "wide"
348
279
  }),
349
- dayPeriod: s({
350
- values: F,
280
+ dayPeriod: a({
281
+ values: b,
351
282
  defaultWidth: "wide"
352
283
  })
353
284
  },
354
285
  match: {
355
- ordinalNumber: i({
286
+ ordinalNumber: n({
356
287
  matchPattern: /^(\d+)(ième|ère|ème|er|e)?/i,
357
288
  parsePattern: /\d+/i,
358
289
  valueCallback: (e) => parseInt(e)
359
290
  }),
360
- era: r({
291
+ era: t({
361
292
  matchPatterns: {
362
293
  narrow: /^(av\.J\.C|ap\.J\.C|ap\.J\.-C)/i,
363
294
  abbreviated: /^(av\.J\.-C|av\.J-C|apr\.J\.-C|apr\.J-C|ap\.J-C)/i,
@@ -367,7 +298,7 @@ var E = {
367
298
  parsePatterns: { any: [/^av/i, /^ap/i] },
368
299
  defaultParseWidth: "any"
369
300
  }),
370
- quarter: r({
301
+ quarter: t({
371
302
  matchPatterns: {
372
303
  narrow: /^T?[1234]/i,
373
304
  abbreviated: /^[1234](er|ème|e)? trim\.?/i,
@@ -383,7 +314,7 @@ var E = {
383
314
  defaultParseWidth: "any",
384
315
  valueCallback: (e) => e + 1
385
316
  }),
386
- month: r({
317
+ month: t({
387
318
  matchPatterns: {
388
319
  narrow: /^[jfmasond]/i,
389
320
  abbreviated: /^(janv|févr|mars|avr|mai|juin|juill|juil|août|sept|oct|nov|déc)\.?/i,
@@ -422,7 +353,7 @@ var E = {
422
353
  },
423
354
  defaultParseWidth: "any"
424
355
  }),
425
- day: r({
356
+ day: t({
426
357
  matchPatterns: {
427
358
  narrow: /^[lmjvsd]/i,
428
359
  short: /^(di|lu|ma|me|je|ve|sa)/i,
@@ -452,7 +383,7 @@ var E = {
452
383
  },
453
384
  defaultParseWidth: "any"
454
385
  }),
455
- dayPeriod: r({
386
+ dayPeriod: t({
456
387
  matchPatterns: {
457
388
  narrow: /^(a|p|minuit|midi|mat\.?|ap\.?m\.?|soir|nuit)/i,
458
389
  any: /^([ap]\.?\s?m\.?|du matin|de l'après[-\s]midi|du soir|de la nuit)/i
@@ -477,28 +408,28 @@ var E = {
477
408
  }
478
409
  }
479
410
  };
480
- function z() {
481
- let e = t()?.language ?? "en", n = d(() => R[e] ?? a, [e]);
411
+ function w() {
412
+ let t = e()?.language ?? "en", n = l(() => C[t] ?? r, [t]);
482
413
  return {
483
- language: e,
414
+ language: t,
484
415
  locale: n,
485
- format: l((e, t) => o.format(e, t, n), [n])
416
+ format: s((e, t) => i.format(e, t, n), [n])
486
417
  };
487
418
  }
488
419
  //#endregion
489
420
  //#region lib/hooks/use-focus-on-mount.ts
490
- function B(e = !0) {
491
- let t = f(null);
492
- return u(() => {
421
+ function T(e = !0) {
422
+ let t = u(null);
423
+ return c(() => {
493
424
  e && t.current?.focus();
494
425
  }, [e]), t;
495
426
  }
496
427
  //#endregion
497
428
  //#region lib/hooks/use-heading-spy.ts
498
- var V = "0px 0px -65% 0px", H = [0, 1];
499
- function U(e, t, n) {
500
- let r = n?.rootMargin ?? V, i = n?.threshold ?? H;
501
- u(() => {
429
+ var E = "0px 0px -65% 0px", D = [0, 1];
430
+ function O(e, t, n) {
431
+ let r = n?.rootMargin ?? E, i = n?.threshold ?? D;
432
+ c(() => {
502
433
  if (e.length === 0) return;
503
434
  let n = e.map((e) => document.getElementById(e)).filter((e) => e != null);
504
435
  if (n.length === 0) return;
@@ -519,4 +450,4 @@ function U(e, t, n) {
519
450
  ]);
520
451
  }
521
452
  //#endregion
522
- export { _ as a, T as i, B as n, g as o, z as r, h as s, U as t };
453
+ export { T as n, w as r, O as t };
@@ -1,5 +1,5 @@
1
- import { r as e } from "./i18n-provider-C6SBK_nO.js";
2
- import { t } from "./translate-material-Bsjc4Tow.js";
1
+ import { r as e } from "./i18n-provider-C6HhBw34.js";
2
+ import { t } from "./translate-material-CGZljjp1.js";
3
3
  import { useCallback as n } from "react";
4
4
  //#region lib/i18n/use-material-translation.ts
5
5
  function r() {
@@ -0,0 +1,42 @@
1
+ import { useEffect as e, useMemo as t, useReducer as n, useState as r, useSyncExternalStore as i } from "react";
2
+ //#region lib/lib/redux/bind-slice-actions.ts
3
+ function a(e, t) {
4
+ let n = {};
5
+ for (let r of Object.keys(e)) {
6
+ let i = e[r];
7
+ n[r] = (...e) => t(i(...e));
8
+ }
9
+ return n;
10
+ }
11
+ //#endregion
12
+ //#region lib/lib/redux/slice-server-state.ts
13
+ var o = /* @__PURE__ */ new WeakMap();
14
+ function s(e, t) {
15
+ o.set(e, t);
16
+ }
17
+ function c(e) {
18
+ return o.get(e);
19
+ }
20
+ //#endregion
21
+ //#region lib/lib/redux/use-slice-reducer.ts
22
+ function l(e, t) {
23
+ return t ? {
24
+ ...e,
25
+ ...t
26
+ } : e;
27
+ }
28
+ var u = "nxgt/useSliceReducer/restore", d = () => () => {}, f = () => !1;
29
+ function p(e) {
30
+ return (t, n) => n.type === u ? n.payload : e(t, n);
31
+ }
32
+ function m(o, s) {
33
+ let m = c(o), h = i(d, f, () => m !== void 0), [g] = r(h), [_, v] = n(t(() => p(o.reducer), [o.reducer]), s, (e) => l(h && m ? m() : o.getInitialState(), e));
34
+ return e(() => {
35
+ g && v({
36
+ type: u,
37
+ payload: l(o.getInitialState(), s)
38
+ });
39
+ }, []), [_, t(() => a(o.actions, v), [o.actions])];
40
+ }
41
+ //#endregion
42
+ export { a as i, m as n, s as r, l as t };
@@ -0,0 +1,31 @@
1
+ import { t as e } from "./use-ssr-media-query-C6M5m8sf.js";
2
+ import { i as t, n, o as r, r as i, s as a, t as o } from "./theme-store-CSl51uNH.js";
3
+ import { a as s } from "./theme-context-BagPvRcz.js";
4
+ import { useCallback as c, useEffect as l, useState as u, useSyncExternalStore as d } from "react";
5
+ import { PRESET_SCHEMES as f } from "@nxgt/material-core/theme/boot";
6
+ //#region lib/hooks/use-is-client.ts
7
+ function p() {
8
+ let [e, t] = u(!1);
9
+ return l(() => {
10
+ t(!0);
11
+ }, []), e;
12
+ }
13
+ //#endregion
14
+ //#region lib/hooks/use-theme.ts
15
+ var m = new Map(Object.entries(f));
16
+ function h(l = {}) {
17
+ let u = s(), f = d(o.subscribe, o.getSnapshot, o.getServerSnapshot), p = u?.name ?? a(f, void 0, i), h = l.defaultMode ?? (u ? u.defaultMode : m.get(p)) ?? "system", g = e("(prefers-color-scheme: dark)", !1), { theme: _, preference: v } = r(d(n.subscribe, n.getSnapshot, n.getServerSnapshot), g, h);
18
+ return {
19
+ theme: _,
20
+ preference: v,
21
+ updateTheme: c((e) => {
22
+ n.set(e, h), t(r(e, g, h).theme);
23
+ }, [g, h]),
24
+ themeName: p,
25
+ setThemeName: c((e) => {
26
+ o.set(e);
27
+ }, [])
28
+ };
29
+ }
30
+ //#endregion
31
+ export { p as n, h as t };
package/docs/README.md CHANGED
@@ -8,6 +8,7 @@ detail: every option, the second example, and the traps.
8
8
  | [Getting started](getting-started.md) | You are installing the package, wiring its styles and icons, or upgrading to a new release |
9
9
  | [Components](components/README.md) | You are looking for a component — one preview per category, then one page per category |
10
10
  | [Forms](guides/forms.md) | You are building a form: the field / `*FormField` pair, React Hook Form + Zod, what each field emits, server errors, multi-step forms |
11
+ | [Themes for your app](guides/themes.md) | You define your own themes: `defineTheme` modules, the Vite plugin's `themes` option, the `nxgt-theme` command and its CI check, the tone warnings |
11
12
  | [Charts](guides/charts.md) | You draw charts with `@nxgt/material/charts`: each chart, the shared props, zoom and phone scroll, the keyboard, accessibility, theming the `--chart-1..5` tokens, and moving off the Nivo charts, removed in 3.0 |
12
13
  | [Cards and tiles](guides/cards-and-tiles.md) | You want a `DataTable` as a list of cards or tiles: `layout`, `renderCard`, `renderTile`, the card's one link, selection, the sort control, columns by the list's width |
13
14
  | [DataGrid](guides/data-grid.md) | You are building an editable grid: columns and editors, save modes and conflicts, resizing, hiding and reordering columns, paste, fill and series, undo, totals, long lists, phones, custom editors, CSP |
@@ -15,7 +16,7 @@ detail: every option, the second example, and the traps.
15
16
  | [i18n](guides/i18n.md) | You want the components in French, your own strings typed, or translated Zod messages |
16
17
  | [App shell](guides/app-shell.md) | You are mounting the sidebar, header and breadcrumbs (`ActivityLayout`) around your routes |
17
18
  | [Animations](guides/animations.md) | You animate with `animate-*` classes: setup next to `tw-animate-css`, every animation with its defaults, the modifiers, stagger, text splitting, scroll-driven animation, appear/disappear, reduced motion, recipes and browser support |
18
- | [Theming](guides/theming.md) | You want to change colours or radius, add dark mode without a flash, use tones (the `data-tone` channel and app tones), or use the compiled CSS without Tailwind |
19
+ | [Theming](guides/theming.md) | You want to change colours or radius, use a shipped theme (`@nxgt/material/themes/<name>.css`) or a themed zone, add dark mode without a flash, use tones (the `data-tone` channel and app tones), or use the compiled CSS without Tailwind |
19
20
  | [Printing](guides/printing.md) | You render PDF documents with `@nxgt/material/print`, turn them into a download, a new tab or a server response, write them as plain data, or bundle them into an SSR server |
20
21
  | [PDF reader](guides/pdf-reader.md) | You render PDFs with `@nxgt/material/pdf-reader`: the pdf.js assets and worker, `configurePdfReader`, server rendering, the Content-Security-Policy and moving from the classic reader (removed in 3.0) |
21
22
  | [Media players](guides/media.md) | You play video or audio: embedded, audio cards, playlists, chapters and transcript, sound across pages with `MediaPlayerHost`, the lightbox, CSP and keyboard |
@@ -6,6 +6,7 @@ The full guide, with every animation's defaults, recipes and browser support, is
6
6
 
7
7
  | | Component | What it does |
8
8
  | --- | --- | --- |
9
+ | <img src="../previews/foundations-themes-themepicker.webp" width="96" alt=""> | [ThemePicker](#themepicker) | A radiogroup of theme tiles with a mini preview and the light / dark / system control |
9
10
  | | [Animations](#animations) | Tailwind 4 animation classes and modifiers, pure CSS: entrances and exits, attention seekers, loops and ambient motion, stagger, text reveals, scroll-driven animation, appear and disappear |
10
11
 
11
12
  ## Animations
@@ -157,3 +158,41 @@ out with no JavaScript: `@starting-style` for the way in, `allow-discrete` so
157
158
  - Reduced motion: a 150ms fade, no movement or scale.
158
159
 
159
160
  The Storybook page *Foundations / Animations* shows every class with controls.
161
+
162
+ ## ThemePicker
163
+
164
+ ![ThemePicker](../previews/foundations-themes-themepicker.webp)
165
+
166
+ A radiogroup of tiles, one per theme. Each tile is a zone of its own theme, so its
167
+ three swatches (primary, secondary, tertiary) and its mini background (the theme's
168
+ tone and preset's texture, drawn by CSS) are that theme's colours in the page's
169
+ mode. The light / dark / system control sits beneath. The arrow keys move the
170
+ choice; the selected tile is tinted, with a start bar and its name in primary text.
171
+
172
+ ```tsx
173
+ import { ThemePicker } from '@nxgt/material/theme-picker';
174
+ import { NxgtThemeProvider } from '@nxgt/material/themes';
175
+
176
+ <NxgtThemeProvider>
177
+ <ThemePicker />
178
+ </NxgtThemeProvider>;
179
+ ```
180
+
181
+ | Option | Type | Default | Effect |
182
+ | --- | --- | --- | --- |
183
+ | `themes` | `readonly Theme[]` | the provider's, else the presets | the tiles; add your own `defineTheme` results (give the same list to `NxgtThemeProvider`, which resolves the stored name) |
184
+ | `value` / `onValueChange` | `ThemeName` / `(name) => void` | the current theme | controlled: the choice is not stored; uncontrolled: it is stored (`setThemeName`) |
185
+ | `showMode` | `boolean` | `true` | the light / dark / system control |
186
+ | `showBackground` | `boolean` | `true` | the mini background in each tile |
187
+ | `layout` | `'grid' \| 'list'` | `'grid'` | `'list'` for a menu or a narrow sheet; the grid goes from 2 to 4 columns with its width |
188
+
189
+ A tile's name is the theme's `label` in the current language (a string, or one per
190
+ locale; the capitalised name when there is none). The group is named by
191
+ `material.theme-picker.label` and the mode control by `material.theme-picker.mode`; the mode control is `ThemeToggle`, whose Light, Dark and System names keep their own keys.
192
+ It writes no inline style, so a strict CSP needs nothing. Its tiles are styled by
193
+ an opt-in stylesheet, `@import "@nxgt/material/theme-picker.css";` after
194
+ `styles.css` (about 3.3 KB gzipped, not part of `styles.css`, so an app without
195
+ the picker pays nothing); the app also imports each theme's stylesheet
196
+ (`@nxgt/material/themes/<name>.css`), as for any theme.
197
+
198
+ **Storybook:** `Foundations/Themes/ThemePicker` · **Vue:** none
@@ -24,7 +24,7 @@ documentation-site shell. Everything is imported from
24
24
  | <img src="../previews/navigation-layout-steps.webp" width="96" alt=""> | [Steps](#steps) | Numbered editorial steps |
25
25
  | <img src="../previews/navigation-layout-hero.webp" width="96" alt=""> | [Hero](#hero) | Landing band |
26
26
  | <img src="../previews/navigation-layout-doc.webp" width="96" alt=""> | [Doc](#doc) | Documentation site shell |
27
- | <img src="../previews/navigation-layout-background.webp" width="96" alt=""> | [Background](#background) | Gradient backdrop with colour blobs |
27
+ | <img src="../previews/navigation-layout-background.webp" width="96" alt=""> | [Background](#background) | Gradient backdrop with colour blobs; the `/backgrounds` one takes its unset props from the nearest theme |
28
28
  | | [NavigationRail](#navigationrail) | Placeholder, no props yet |
29
29
 
30
30
  ## ActivityLayout
@@ -81,7 +81,7 @@ phone's menu sheet pad clear of `env(safe-area-inset-*)`, as classes; see the
81
81
  | `titleAs` | `'h1'` … `'h6'` \| `'div'` | `'h1'` | `ActivityContent`: the title's heading level |
82
82
  | `inset` | `boolean` | `false` | `ActivityContent`: pads the content 1rem on each side. Off, it lines up with the app bar and the cards |
83
83
  | `align` | `'start' \| 'center'` | `'start'` | `ActivityLayout`, `AppSidebar`: the collapsed rail's entries sit right under the brand, or `'center'` for centred in the height below it |
84
- | `backdrop` | `ReactNode` | — | `ActivityLayout`: a decorative background behind the frame, in place of the gradient and its blobs: a `Background` preset from `@nxgt/material/backgrounds`. Rendered in an `inert`, `aria-hidden` layer as wide as the content column and one viewport high, fixed in the viewport while the content scrolls; the chrome (app bar, breadcrumb, tabs strip) is lightly translucent and frosted over it (80%, 87% for the sidebar, breadcrumb and tabs strip, 92% and no blur under `prefers-reduced-transparency` or without `backdrop-filter`), and the lists, tables and cards stay opaque; `--nxgt-backdrop-chrome` sets the chrome's fill and `--nxgt-backdrop-surface` the lists'. See [Use a background preset behind the shell](../guides/app-shell.md#use-a-background-preset-behind-the-shell) |
84
+ | `backdrop` | `ReactNode \| false` | — | `ActivityLayout`: an exception to the theme's background (drawn by default; Lavande's is the built-in gradient and blobs); `false` draws a plain page. A node is a decorative background behind the frame: a `Background` preset from `@nxgt/material/backgrounds`. Rendered in an `inert`, `aria-hidden` layer as wide as the content column and one viewport high, fixed in the viewport while the content scrolls; the chrome (app bar, breadcrumb, tabs strip) is lightly translucent and frosted over it (80%, 87% for the sidebar, breadcrumb and tabs strip, 92% and no blur under `prefers-reduced-transparency` or without `backdrop-filter`), and the lists, tables and cards stay opaque; `--nxgt-backdrop-chrome` sets the chrome's fill and `--nxgt-backdrop-surface` the lists'. See [Use a background preset behind the shell](../guides/app-shell.md#use-a-background-preset-behind-the-shell) |
85
85
  | `routeTransition` | `boolean \| Omit<ViewTransitionProps, 'children' \| 'ref'>` | `true` | `ActivityLayout`: React's `<ViewTransition>` around the content region, so a navigation cross-fades it. `false` renders none (your app has its own boundary); an object passes `default` / `update` classes, `name`, callbacks through. See [Route transitions](../guides/app-shell.md#route-transitions) |
86
86
 
87
87
  The active entry is the longest match across the whole menu, segment-aware.
@@ -742,7 +742,7 @@ import { Background, Card } from '@nxgt/material/components';
742
742
  It fills the viewport; pass a `className` such as `h-96 w-full` to use it as a band.
743
743
  It is plain CSS from `styles.css`, with no inline `style`, and its colours lift
744
744
  in dark. `ActivityLayout` and `ThreadLayout` sit on it. The superset with `grain`,
745
- `seed`, `fill`, `motif` and the other presets (light, geometry and motif families) is `Background` from `/backgrounds`; see the [backgrounds guide](../guides/backgrounds.md). Light presets there: `mesh`, `aurora`, `spotlight`, `bokeh`, `rays`, `halo`, `plasma`, `glass`, `ripples`, `blobs`, `paper`, `linen`, `concrete`, `marble`, `grain`; geometry: `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`, `hexagons`, `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`; motifs: `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons`, `school`, `night-sky`, `bubbles`, `leaves`, `science`, `music`, `travel`, `sport`.
745
+ `seed`, `fill`, `motif` and the other presets (light, geometry and motif families) is `Background` from `/backgrounds`; see the [backgrounds guide](../guides/backgrounds.md). Light presets there: `mesh`, `aurora`, `spotlight`, `bokeh`, `rays`, `halo`, `plasma`, `glass`, `ripples`, `blobs`, `paper`, `linen`, `concrete`, `marble`, `grain`; geometry: `isometric`, `blueprint`, `dots`, `stripes`, `low-poly`, `topography`, `waves`, `hexagons`, `circuit`, `graph-paper`, `checker`, `diagonal-checker`, `chevrons`; motifs: `shapes`, `confetti-grid`, `constellation`, `halftone`, `truchet`, `floating`, `scatter-icons`, `school`, `night-sky`, `bubbles`, `leaves`, `science`, `music`, `travel`, `sport`, `moon`.
746
746
 
747
747
  **Storybook:** `Navigation & layout/Background` · **Vue:** `Background`
748
748
 
@@ -139,7 +139,7 @@ and need nothing.
139
139
  | `@nxgt/material/editor/viewer` | `RichTextViewer`: shows a saved document (HTML, JSON or Markdown) read-only. **Server-safe**: no editor instance, no `'use client'` ([RichTextViewer](components/rich-widgets.md#richtextviewer)) |
140
140
  | `@nxgt/material/editor/collab` | `collaboration()`: several people editing one `DocumentEditor` through a Yjs document and provider your app supplies. Needs `yjs` and `y-protocols` ([Collaboration](components/rich-widgets.md#collaboration)) |
141
141
  | `@nxgt/material/editor/pm` | The editor's own tiptap and ProseMirror classes (`Extension`, `Node`, `Plugin`, `PluginKey`, `TextSelection`, `ProseMirrorNode`, `Fragment`, `DecorationSet`, …) for a custom feature's extensions, so `instanceof` agrees with the editor. Shares the editor's code; **server-safe** ([A custom feature](components/rich-widgets.md#a-custom-feature)) |
142
- | `@nxgt/material/backgrounds` | Background presets: `Background` (a superset of the `/components` one: `preset` (44 ids, `AVAILABLE_BACKGROUND_PRESETS`), `tone`, `intensity`, `animated`, `grain`, `seed`, `fill` and `motif` (`shapes`, `density`, `size`, `rotate`, `shapeFill`, `opacitySpread`)), and the types and tables re-exported from `@nxgt/material-core/backgrounds`. **Its own entry**, with an opt-in stylesheet ([backgrounds](guides/backgrounds.md)) |
142
+ | `@nxgt/material/backgrounds` | Background presets: `Background` (a superset of the `/components` one: `preset` (45 ids, `AVAILABLE_BACKGROUND_PRESETS`), `tone`, `intensity`, `animated`, `grain`, `seed`, `fill` and `motif` (`shapes`, `density`, `size`, `rotate`, `shapeFill`, `opacitySpread`)), and the types and tables re-exported from `@nxgt/material-core/backgrounds`. **Its own entry**, with an opt-in stylesheet ([backgrounds](guides/backgrounds.md)) |
143
143
  | `@nxgt/material/media-hls` | `hlsStreaming()`: the HLS adapter for `MediaPlayer`, `hls.js` loaded lazily ([streaming](guides/media-streaming.md)) |
144
144
  | `@nxgt/material/vite` | Build-time helper for consumers: `pdfkitStandardFonts()` ([printing](guides/printing.md#bundling-print-into-an-ssr-server)) |
145
145
  | `@nxgt/material/hooks` | `useTheme`, `useIsClient`, `useIsMobile`, `useLocalizedDate`, … ([helpers](guides/helpers.md#nxgtmaterialhooks)) |
@@ -191,7 +191,7 @@ partitionMenu(items); // { content, footer }
191
191
  | `align` | `'start' \| 'center'` | `'start'` | Where the collapsed rail's entries sit: right under the brand, or centred in the height below it |
192
192
  | `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 |
193
193
  | `onMenuOpenChange` | `(open: boolean) => void` | — | Called for every change of the sheet: the menu button, Escape, the close button, a followed link, a new location |
194
- | `backdrop` | `ReactNode` | — | A decorative background drawn behind the frame in place of the built-in gradient and blobs: usually a `Background` preset from `@nxgt/material/backgrounds` (see [Use a background preset behind the shell](#use-a-background-preset-behind-the-shell)) |
194
+ | `backdrop` | `ReactNode \| false` | — | An exception to the theme's background, 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 |
195
195
 
196
196
  On a page with `viewport-fit=cover` (an installed PWA drawing under a
197
197
  notch and the home indicator), the shell pads clear of
@@ -484,10 +484,44 @@ while the sheet is open, so leave ids out of it. A link in `brand` (a home
484
484
  link around the logo) is the sheet's first focusable element, so it takes
485
485
  the focus when the sheet opens.
486
486
 
487
+ ## The theme's background
488
+
489
+ `ActivityLayout` draws the background of the nearest theme (`NxgtThemeProvider`
490
+ or an `NxgtTheme` zone around it; see [Themes](./theming.md#the-provider-and-zones)).
491
+ `backdrop` is the exception:
492
+
493
+ | Case | What is drawn |
494
+ | --- | --- |
495
+ | no theme, or Lavande (a `gradient` background in the `primary` tone, default intensity) | the built-in gradient and its three blobs; the markup is what it was, plus `data-slot="activity-content-header"` on the content header card |
496
+ | any other theme background | that background in the backdrop layer, with the frosted chrome described below (`@nxgt/material/backgrounds.css` is yours to import) |
497
+ | a theme with `background: false` | no background |
498
+ | `backdrop={<Background … />}` | that node, for this screen |
499
+ | `backdrop={false}` | no background and no blobs: a plain page (`data-plain` on the root) |
500
+
501
+ The theme's shapes (the motif and illustrated presets) stay whole: a shape that
502
+ would cross the layer's edge, or reach the app bar, the breadcrumb, the header
503
+ card or an `EntityHeader`, is not drawn, and nothing shows until that first
504
+ check has run. Full-width textures such as `waves` and the gradient are not
505
+ shapes and are not filtered. A `Background` passed as `backdrop` is kept whole the same way; any other node is left as it is.
506
+
507
+ `backdrop={false}` used to draw the built-in gradient, as if it were left out;
508
+ it now removes it. To keep the gradient, leave `backdrop` out. A theme's
509
+ background is loaded on demand (the scene engine, about 21 KB gzipped, is
510
+ not part of `@nxgt/material/components`): a streaming server render sends it in
511
+ the same response, `renderToString` fills the layer once the chunk has loaded.
512
+
513
+ **Server render and a stored theme.** The server does not know the stored theme
514
+ name: it renders `defaultTheme` (Lavande by default). A visitor whose stored theme
515
+ is another one gets that theme's colours at once from the boot script, but the
516
+ theme's backdrop (its background, shapes and the frosted chrome) appears only after
517
+ hydration, once the stored name has been read. The first paint shows the default
518
+ backdrop, or none. An app that must show the right backdrop in the first HTML has
519
+ to know the theme on the server (a cookie, passed to `defaultTheme`).
520
+
487
521
  ## Use a background preset behind the shell
488
522
 
489
523
  The shell draws the gradient with three blurred blobs behind its frame. To use
490
- one of the 44 presets of `@nxgt/material/backgrounds` instead, pass it as
524
+ one of the 45 presets of `@nxgt/material/backgrounds` instead, pass it as
491
525
  `backdrop`:
492
526
 
493
527
  ```tsx
@@ -508,10 +542,11 @@ export function Shell({ items }: { items: MenuItem[] }) {
508
542
  }
509
543
  ```
510
544
 
511
- - **It replaces the gradient.** While `backdrop` is given the layout's root
512
- carries `data-backdrop`, and the built-in gradient (its tint and three blobs) is not drawn (plain
513
- CSS, no inline `style`). Without it the markup and the look are what they
514
- were; `null`, `undefined` and `false` count as none.
545
+ - **It replaces the gradient.** While a `backdrop` node is given the layout's
546
+ root carries `data-backdrop`, and the built-in gradient (its tint and three
547
+ blobs) is not drawn (plain CSS, no inline `style`). Without it the look is
548
+ what it was (and the markup, bar the `activity-content-header` slot on the header card); `null` and `undefined` count as none, and `false`
549
+ is not none: it draws a plain page (see [The theme's background](#the-themes-background)).
515
550
  - **It sits behind the content column.** The node is wrapped in a layer
516
551
  (`[data-slot="activity-layout-backdrop"]`) that spans the column's width beside the
517
552
  sidebar, under the app bar, the breadcrumb and the content. The layer is `inert`, `aria-hidden="true"`