@cueplusplus/ui 0.14.1 → 0.16.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 (182) hide show
  1. package/CHANGELOG.md +415 -0
  2. package/README.md +26 -0
  3. package/dist/agent-runtime/tool-call-card.js +1 -1
  4. package/dist/chat/message-list.js +2 -1
  5. package/dist/chat/message.js +1 -1
  6. package/dist/chrome/_tabs-scroll.d.ts +17 -1
  7. package/dist/chrome/_tabs-scroll.js +20 -3
  8. package/dist/chrome/app-bar.js +2 -1
  9. package/dist/chrome/band.js +13 -5
  10. package/dist/chrome/eyebrow.js +1 -1
  11. package/dist/chrome/footer.js +1 -1
  12. package/dist/chrome/panel.js +2 -1
  13. package/dist/chrome/section-header.js +1 -1
  14. package/dist/color/color-field.d.ts +2 -1
  15. package/dist/color/color-picker.d.ts +2 -1
  16. package/dist/configurator/configurator.js +1 -1
  17. package/dist/configurator/export-dialog.js +1 -1
  18. package/dist/configurator/panel-sections.js +1 -1
  19. package/dist/configurator/token-editor.js +1 -1
  20. package/dist/date/calendar.js +2 -2
  21. package/dist/date/date-field.d.ts +2 -1
  22. package/dist/date/date-picker.d.ts +2 -1
  23. package/dist/date/date-range-picker.d.ts +2 -1
  24. package/dist/date/time-field.d.ts +2 -1
  25. package/dist/elements/context-usage.js +3 -3
  26. package/dist/elements/transcript-rules.js +1 -1
  27. package/dist/forms/_chassis-size.d.ts +22 -0
  28. package/dist/forms/_chassis.d.ts +3 -10
  29. package/dist/forms/_chassis.js +2 -1
  30. package/dist/forms/autocomplete.d.ts +2 -1
  31. package/dist/forms/combobox.d.ts +2 -1
  32. package/dist/forms/env-var-input.d.ts +2 -1
  33. package/dist/forms/field.js +1 -1
  34. package/dist/forms/index.d.ts +2 -1
  35. package/dist/forms/input-group.d.ts +2 -1
  36. package/dist/forms/input.d.ts +2 -1
  37. package/dist/forms/multi-select.d.ts +2 -1
  38. package/dist/forms/otp-field.d.ts +2 -1
  39. package/dist/forms/password-input.d.ts +2 -1
  40. package/dist/forms/scrub-input.d.ts +2 -1
  41. package/dist/forms/search-input.d.ts +2 -1
  42. package/dist/forms/select.d.ts +2 -1
  43. package/dist/forms/select.js +2 -1
  44. package/dist/forms/slider.js +1 -1
  45. package/dist/forms/tags-input.d.ts +2 -1
  46. package/dist/forms/toggle-group.d.ts +1 -1
  47. package/dist/forms/toggle.d.ts +1 -1
  48. package/dist/index.d.ts +2 -1
  49. package/dist/instruments/code-block.js +1 -1
  50. package/dist/instruments/ledger.js +1 -1
  51. package/dist/instruments/log-viewer.js +2 -1
  52. package/dist/instruments/progress.js +1 -1
  53. package/dist/instruments/stat.js +1 -1
  54. package/dist/instruments/table.js +2 -2
  55. package/dist/instruments/terminal-frame.js +1 -1
  56. package/dist/layout/_ground.js +1 -1
  57. package/dist/layout/card.js +3 -1
  58. package/dist/layout/collapsible.js +1 -1
  59. package/dist/layout/description-list.js +1 -1
  60. package/dist/layout/preview.d.ts +13 -1
  61. package/dist/layout/preview.js +16 -9
  62. package/dist/layout/sidebar.js +1 -1
  63. package/dist/layout/stepper.js +1 -1
  64. package/dist/midi/musical-time-input.d.ts +2 -1
  65. package/dist/overlays/_surface.d.ts +2 -2
  66. package/dist/overlays/_surface.js +4 -2
  67. package/dist/overlays/command-palette.js +1 -1
  68. package/dist/overlays/toast.js +1 -1
  69. package/dist/primitives/button.js +2 -1
  70. package/dist/primitives/chip.d.ts +1 -1
  71. package/dist/primitives/chip.js +2 -2
  72. package/dist/system/_paint-elevation.js +9 -0
  73. package/dist/system/_paint-glass.js +46 -0
  74. package/dist/system/_paint-glow.js +32 -0
  75. package/dist/system/_paint-ground-pattern.js +30 -0
  76. package/dist/system/_paint-rim.js +41 -0
  77. package/dist/system/_paint-stroke-sunken.js +19 -0
  78. package/dist/system/_paint-stroke-surface-1.js +19 -0
  79. package/dist/system/_paint-stroke-surface-2.js +27 -0
  80. package/dist/system/_paint-texture.js +53 -0
  81. package/dist/system/density.d.ts +11 -2
  82. package/dist/system/density.js +29 -9
  83. package/dist/system/portal.js +8 -2
  84. package/dist/system/prepaint.d.ts +18 -1
  85. package/dist/system/prepaint.js +8 -2
  86. package/dist/system/theme-provider.d.ts +64 -38
  87. package/dist/system/theme-provider.js +70 -23
  88. package/dist/system/vocabulary.d.ts +1 -1
  89. package/dist/system/vocabulary.js +14 -2
  90. package/manifest/components/alert-dialog.json +13 -1
  91. package/manifest/components/app-bar.json +4 -0
  92. package/manifest/components/autocomplete.json +13 -1
  93. package/manifest/components/band.json +9 -2
  94. package/manifest/components/button.json +4 -0
  95. package/manifest/components/calendar.json +3 -1
  96. package/manifest/components/card.json +6 -0
  97. package/manifest/components/channel-matrix.json +13 -1
  98. package/manifest/components/chart-tooltip-content.json +13 -1
  99. package/manifest/components/chip.json +1 -0
  100. package/manifest/components/code-block.json +2 -1
  101. package/manifest/components/collapsible.json +2 -1
  102. package/manifest/components/color-field.json +4 -0
  103. package/manifest/components/color-picker.json +4 -0
  104. package/manifest/components/colors-section.json +2 -1
  105. package/manifest/components/combobox.json +13 -1
  106. package/manifest/components/command-palette.json +13 -1
  107. package/manifest/components/composer.json +4 -0
  108. package/manifest/components/context-menu.json +13 -1
  109. package/manifest/components/context-usage.json +1 -0
  110. package/manifest/components/date-field.json +4 -0
  111. package/manifest/components/date-picker.json +4 -0
  112. package/manifest/components/date-range-picker.json +4 -0
  113. package/manifest/components/density.json +19 -0
  114. package/manifest/components/description-list.json +2 -1
  115. package/manifest/components/dialog.json +13 -1
  116. package/manifest/components/disclosure.json +2 -1
  117. package/manifest/components/dmx-bar.json +13 -1
  118. package/manifest/components/dmx-strip.json +13 -1
  119. package/manifest/components/drawer.json +13 -1
  120. package/manifest/components/dropdown-menu.json +13 -1
  121. package/manifest/components/env-var-input.json +4 -0
  122. package/manifest/components/export-dialog.json +2 -1
  123. package/manifest/components/eyebrow.json +2 -1
  124. package/manifest/components/field-description.json +2 -1
  125. package/manifest/components/field-error.json +2 -1
  126. package/manifest/components/field-label.json +2 -1
  127. package/manifest/components/field.json +2 -1
  128. package/manifest/components/footer.json +1 -0
  129. package/manifest/components/frames.json +2 -1
  130. package/manifest/components/hover-card.json +13 -1
  131. package/manifest/components/input-group.json +4 -0
  132. package/manifest/components/input.json +4 -0
  133. package/manifest/components/ledger.json +2 -1
  134. package/manifest/components/log-viewer.json +7 -0
  135. package/manifest/components/menubar.json +13 -1
  136. package/manifest/components/message-list.json +7 -0
  137. package/manifest/components/message.json +2 -1
  138. package/manifest/components/multi-select.json +13 -1
  139. package/manifest/components/musical-time-input.json +4 -0
  140. package/manifest/components/navigation-menu.json +13 -1
  141. package/manifest/components/number-field.json +4 -0
  142. package/manifest/components/otp-field.json +4 -0
  143. package/manifest/components/panel-header.json +2 -0
  144. package/manifest/components/panel.json +2 -0
  145. package/manifest/components/password-input.json +4 -0
  146. package/manifest/components/popover.json +13 -1
  147. package/manifest/components/preset-section.json +2 -1
  148. package/manifest/components/preview.json +21 -1
  149. package/manifest/components/progress.json +2 -1
  150. package/manifest/components/scrollable-tabs-list.json +1 -0
  151. package/manifest/components/scrub-input.json +4 -0
  152. package/manifest/components/search-input.json +4 -0
  153. package/manifest/components/section-header.json +2 -1
  154. package/manifest/components/segmented-control.json +1 -0
  155. package/manifest/components/select.json +11 -0
  156. package/manifest/components/shape-section.json +2 -1
  157. package/manifest/components/sheet.json +13 -1
  158. package/manifest/components/sidebar.json +2 -1
  159. package/manifest/components/slider.json +2 -1
  160. package/manifest/components/stat.json +1 -0
  161. package/manifest/components/stepper.json +2 -1
  162. package/manifest/components/table-scroll-region.json +2 -1
  163. package/manifest/components/table.json +2 -1
  164. package/manifest/components/tabs.json +1 -0
  165. package/manifest/components/tags-input.json +13 -1
  166. package/manifest/components/terminal-frame.json +1 -0
  167. package/manifest/components/textarea.json +4 -0
  168. package/manifest/components/theme-configurator.json +13 -1
  169. package/manifest/components/theme-provider.json +20 -1
  170. package/manifest/components/time-boundary.json +2 -1
  171. package/manifest/components/time-field.json +4 -0
  172. package/manifest/components/toast.json +13 -0
  173. package/manifest/components/toggle-group.json +1 -19
  174. package/manifest/components/toggle.json +0 -6
  175. package/manifest/components/token-editor.json +2 -1
  176. package/manifest/components/tool-call-card.json +2 -1
  177. package/manifest/components/toolbar.json +1 -0
  178. package/manifest/components/tooltip.json +13 -1
  179. package/manifest/components/unread-divider.json +2 -1
  180. package/manifest/manifest.json +94 -94
  181. package/manifest/tokens.json +48 -2
  182. package/package.json +6 -6
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
3
3
  import { AgentSkinContext } from "./agent-skin.js";
4
- import { DensityContext, StyleSetContext } from "./density.js";
4
+ import { DensityContext, PaintContext, StyleSetContext } from "./density.js";
5
5
  import { OverridesContext } from "./overrides.js";
6
6
  import { FontFamiliesContext, FontScaleContext, ThemeContext } from "./theme-provider.js";
7
7
  import * as React from "react";
@@ -31,6 +31,7 @@ function usePortalStamp() {
31
31
  const overrides = React.useContext(OverridesContext);
32
32
  const skin = React.useContext(AgentSkinContext);
33
33
  const styleSet = React.useContext(StyleSetContext);
34
+ const paint = React.useContext(PaintContext);
34
35
  return {
35
36
  theme: theme?.theme ?? DEFAULT_THEME,
36
37
  density: island ?? theme?.density ?? "compact",
@@ -41,7 +42,8 @@ function usePortalStamp() {
41
42
  overrides,
42
43
  skin: skin?.skin ?? null,
43
44
  fidelity: skin?.fidelity ?? null,
44
- styleSet
45
+ styleSet,
46
+ paint
45
47
  };
46
48
  }
47
49
  /**
@@ -97,6 +99,7 @@ function useCuePortalProps() {
97
99
  stamp.density,
98
100
  stamp.font,
99
101
  stamp.styleSet,
102
+ stamp.paint,
100
103
  stamp.mode,
101
104
  stamp.fontScale,
102
105
  stamp.fontFamilies?.sans,
@@ -132,6 +135,8 @@ function applyStamp(element, stamp) {
132
135
  element.setAttribute("data-mode", stamp.mode);
133
136
  if (stamp.styleSet === null) element.removeAttribute("data-style");
134
137
  else element.setAttribute("data-style", stamp.styleSet);
138
+ if (stamp.paint === null) element.removeAttribute("data-paint");
139
+ else element.setAttribute("data-paint", stamp.paint);
135
140
  if (stamp.skin === null) element.removeAttribute("data-cue-skin");
136
141
  else element.setAttribute("data-cue-skin", stamp.skin);
137
142
  if (stamp.fidelity === null) element.removeAttribute("data-cue-fidelity");
@@ -182,6 +187,7 @@ function CuePortalFrame({ children, className, style }) {
182
187
  "data-font": stamp.font,
183
188
  "data-mode": stamp.mode,
184
189
  "data-style": stamp.styleSet ?? void 0,
190
+ "data-paint": stamp.paint ?? void 0,
185
191
  "data-cue-skin": stamp.skin ?? void 0,
186
192
  "data-cue-fidelity": stamp.fidelity ?? void 0,
187
193
  className,
@@ -1,4 +1,4 @@
1
- import { StyleSet } from "@cueplusplus/tokens";
1
+ import { Paint, StyleSet } from "@cueplusplus/tokens";
2
2
  import { Density as Density$1, FontName, Mode, ThemeManifest, ThemeName } from "@cueplusplus/theme-base";
3
3
  //#region src/system/prepaint.d.ts
4
4
  /** localStorage key the ThemeProvider and the pre-paint script share by default. */
@@ -21,6 +21,13 @@ interface PersistedPreferences {
21
21
  * value to hold an opinion about.
22
22
  */
23
23
  style?: string;
24
+ /**
25
+ * Last look pack the user picked, or absent — which is what "no pack" means,
26
+ * for exactly the reason `style` above gives. An application that never
27
+ * touches this axis keeps storing the object it always stored, and the
28
+ * pre-paint script has no sixth value to hold an opinion about.
29
+ */
30
+ paint?: string;
24
31
  }
25
32
  /**
26
33
  * The server-authoritative fallback stamped when storage is absent or ignored.
@@ -52,6 +59,16 @@ interface PrepaintDefaults {
52
59
  * (stored, then this) rather than four.
53
60
  */
54
61
  styleSet?: StyleSet;
62
+ /**
63
+ * The look pack an unstamped page opens on, or omitted for none.
64
+ *
65
+ * The second axis whose absence is a value, and it behaves exactly as
66
+ * `styleSet` does: omitted means the script REMOVES `data-paint` rather than
67
+ * stamping a default, because a page in no pack has made no claim about
68
+ * finish and `[data-paint]` blocks key their whole value-set on the attribute
69
+ * being there.
70
+ */
71
+ paint?: Paint;
55
72
  }
56
73
  /** Options form for apps whose server projection, not localStorage, owns first paint. */
57
74
  interface PrepaintOptions {
@@ -1,5 +1,5 @@
1
1
  import { vocabulary } from "./vocabulary.js";
2
- import { DEFAULT_DENSITY, DEFAULT_FONT, STYLE_SETS } from "@cueplusplus/tokens";
2
+ import { DEFAULT_DENSITY, DEFAULT_FONT, PAINTS, STYLE_SETS } from "@cueplusplus/tokens";
3
3
  import { MODES } from "@cueplusplus/theme-base";
4
4
  //#region src/system/prepaint.ts
5
5
  /**
@@ -114,7 +114,13 @@ function prepaintScript(storageKeyOrOptions = DEFAULT_STORAGE_KEY, defaultTheme
114
114
  */
115
115
  const styleSets = scriptSafe(JSON.stringify([...STYLE_SETS]));
116
116
  const fallbackStyleSet = defaults.styleSet === void 0 ? "null" : jsStringLiteral(defaults.styleSet);
117
- return `!function(){try{var k=${key},e=document.documentElement,s=null;` + (readStoredPreferences ? "try{var r=localStorage.getItem(k);s=r?JSON.parse(r):null}catch(_){}" : "") + `s=s&&typeof s=="object"?s:{};var T=${themes},A=${axes},P=/^[a-z][a-z0-9-]*$/i;var t=T?(T.indexOf(s.theme)>-1?s.theme:${fallbackTheme}):(typeof s.theme=="string"&&P.test(s.theme)?s.theme:${fallbackTheme});var a=A[T?t:""]||A[""]||{d:[],f:[]};var d=a.d.indexOf(s.density)>-1?s.density:(a.d.indexOf(${fallbackDensity})>-1?${fallbackDensity}:(a.p&&a.d.indexOf(a.p)>-1?a.p:${baseDensity}));var f=a.f.indexOf(s.font)>-1?s.font:(a.f.indexOf(${fallbackFont})>-1?${fallbackFont}:(a.q&&a.f.indexOf(a.q)>-1?a.q:${baseFont}));var m=${modes}.indexOf(s.mode)>-1?s.mode:${fallbackMode};var S=${styleSets},y=S.indexOf(s.style)>-1?s.style:${fallbackStyleSet};e.setAttribute("data-theme",t);e.setAttribute("data-density",d);e.setAttribute("data-font",f);e.setAttribute("data-mode",m);y?e.setAttribute("data-style",y):e.removeAttribute("data-style");e.style.colorScheme=a.l===false?"dark":(m==="system"?"light dark":m)}catch(_){}}()`;
117
+ /**
118
+ * The packs, inlined for the same reason as everything above it, and the
119
+ * second axis whose absence is a legal value.
120
+ */
121
+ const paints = scriptSafe(JSON.stringify([...PAINTS]));
122
+ const fallbackPaint = defaults.paint === void 0 ? "null" : jsStringLiteral(defaults.paint);
123
+ return `!function(){try{var k=${key},e=document.documentElement,s=null;` + (readStoredPreferences ? "try{var r=localStorage.getItem(k);s=r?JSON.parse(r):null}catch(_){}" : "") + `s=s&&typeof s=="object"?s:{};var T=${themes},A=${axes},P=/^[a-z][a-z0-9-]*$/i;var t=T?(T.indexOf(s.theme)>-1?s.theme:${fallbackTheme}):(typeof s.theme=="string"&&P.test(s.theme)?s.theme:${fallbackTheme});var a=A[T?t:""]||A[""]||{d:[],f:[]};var d=a.d.indexOf(s.density)>-1?s.density:(a.d.indexOf(${fallbackDensity})>-1?${fallbackDensity}:(a.p&&a.d.indexOf(a.p)>-1?a.p:${baseDensity}));var f=a.f.indexOf(s.font)>-1?s.font:(a.f.indexOf(${fallbackFont})>-1?${fallbackFont}:(a.q&&a.f.indexOf(a.q)>-1?a.q:${baseFont}));var m=${modes}.indexOf(s.mode)>-1?s.mode:${fallbackMode};var S=${styleSets},y=S.indexOf(s.style)>-1?s.style:${fallbackStyleSet};var G=${paints},g=G.indexOf(s.paint)>-1?s.paint:${fallbackPaint};e.setAttribute("data-theme",t);e.setAttribute("data-density",d);e.setAttribute("data-font",f);e.setAttribute("data-mode",m);y?e.setAttribute("data-style",y):e.removeAttribute("data-style");g?e.setAttribute("data-paint",g):e.removeAttribute("data-paint");e.style.colorScheme=a.l===false?"dark":(m==="system"?"light dark":m)}catch(_){}}()`;
118
124
  }
119
125
  //#endregion
120
126
  export { DEFAULT_STORAGE_KEY, prepaintScript };
@@ -1,6 +1,6 @@
1
1
  import { TokenOverrides } from "./overrides.js";
2
2
  import * as React from "react";
3
- import { StyleSet } from "@cueplusplus/tokens";
3
+ import { Paint, StyleSet } from "@cueplusplus/tokens";
4
4
  import { Density as Density$1, FontName, Mode, ThemeManifest, ThemeName } from "@cueplusplus/theme-base";
5
5
  //#region src/system/theme-provider.d.ts
6
6
  /** A mode that has been resolved to an actual palette — `"system"` never survives this far. */
@@ -33,6 +33,14 @@ interface ThemeContextValue {
33
33
  * `StyleSetContext` the portal and stage stamps read are one value.
34
34
  */
35
35
  styleSet: StyleSet | null;
36
+ /**
37
+ * The look pack in force on this subtree, or `null`.
38
+ *
39
+ * *In force*, not *named here*, exactly as `styleSet` is: a provider that
40
+ * names no pack reports the one stamped around it, so this and the
41
+ * `PaintContext` the portal and stage stamps read are one value.
42
+ */
43
+ paint: Paint | null;
36
44
  /** Mode after resolving `"system"` against `prefers-color-scheme`. */
37
45
  resolvedMode: ResolvedMode;
38
46
  /** Switch theme and persist the new preference triple. */
@@ -58,6 +66,8 @@ interface ThemeContextValue {
58
66
  * out-specify an ancestor's in a cascade.
59
67
  */
60
68
  setStyleSet: (next: StyleSet | null) => void;
69
+ /** Switch the look pack and persist it. `null` clears the attribute. */
70
+ setPaint: (next: Paint | null) => void;
61
71
  }
62
72
  /** Provider-owned font-family overrides that detached portals must republish. */
63
73
  interface FontFamilies {
@@ -164,6 +174,11 @@ interface ThemeProviderProps {
164
174
  * holds its own rather than handing the axis up to the root.
165
175
  */
166
176
  styleSet?: StyleSet;
177
+ /**
178
+ * A look pack for this subtree. Opt-in: a provider that names none stamps no
179
+ * `data-paint`, and a nested one inherits the pack stamped around it.
180
+ */
181
+ paint?: Paint;
167
182
  /** Multiplier on every text token, published as `--cue-font-scale`. Defaults to `1`. */
168
183
  fontScale?: number;
169
184
  /** Optional app-owned font stacks, published as inline CUE font custom properties. */
@@ -237,48 +252,59 @@ interface ThemeProviderProps {
237
252
  /** Restore and write root preferences in localStorage. Defaults to `true`. */
238
253
  persistPreferences?: boolean;
239
254
  /**
240
- * The Content-Security-Policy nonce for every `<style>` element this tree
241
- * renders — this library's and Base UI's.
255
+ * The Content-Security-Policy nonce this provider hands on: to its own
256
+ * density-layer `<style>`, and — through Base UI's `CSPProvider` — to Base
257
+ * UI's scrollbar `<style>` and to the pre-hydration `<script>` a
258
+ * `<Slider thumbAlignment="edge">` renders. List it in `script-src`, and in
259
+ * whichever directive governs style elements: `style-src-elem` if the policy
260
+ * has one, otherwise `style-src`. It does not reach `ThemeConfigurator`'s
261
+ * `<style>` or the application's pre-paint `<script>`.
242
262
  *
243
- * When `overrides.densities` is set this provider emits one `<style>`
244
- * element (see {@link ThemeProviderProps.overrides}). Under a policy of
245
- * `style-src-elem 'self' 'nonce-<per-request>'` the browser refuses that
246
- * element on every page load, because an element React renders on the client
247
- * cannot pick up a server nonce by itself. Pass the request's nonce here and
248
- * it is set on the element.
263
+ * The density layer — one `<style data-cue-overrides>` when
264
+ * `overrides.densities` yields a valid declaration (see
265
+ * {@link ThemeProviderProps.overrides}) — takes its nonce **from this prop
266
+ * alone**: not from an outer `CSPProvider`, and not from an outer
267
+ * `ThemeProvider`. A nested provider that sets its own `overrides.densities`
268
+ * needs its own `nonce`.
249
269
  *
250
- * It also reaches **Base UI**. Given a nonce, this provider renders
251
- * `@base-ui/react`'s own `CSPProvider` around the tree, so the hoisted
252
- * `<style>` that `ScrollAreaRoot` and `SelectPopup` emit carries it too.
253
- * Without that, a strict policy refuses it by content hash on every page
254
- * rendering a Select, a Popover or a ScrollArea — and a consumer has no way
255
- * to guess the remedy lives in a peer dependency's provider. An outer
256
- * `CSPProvider` a consumer renders itself is left alone: no nonce here means
257
- * no provider here, rather than one that overwrites theirs with `undefined`.
270
+ * Base UI's scrollbar rule gets the nonce wherever React creates it in the
271
+ * browser. **It does not get it in server-rendered HTML** under a framework
272
+ * that hands React a script-only nonce, which includes Next.js 16: React's
273
+ * server renderer (19.2, and the canary Next.js 16 bundles) writes a
274
+ * `precedence` style's nonce only from its render option `nonce: { style }`.
275
+ * Allow that rule by hash, or turn on Base
276
+ * UI's `disableStyleElements` and ship the rule yourself;
277
+ * `docs/CONSUMING.md` §4.5 has both, with the hash.
258
278
  *
259
279
  * `prepaintScript()` returns a *string* the application renders in a
260
- * `<script>` of its own — so the application already controls that element's
261
- * nonce, and between it and this prop a strict policy needs nothing else
262
- * from here.
280
+ * `<script>` of its own, so put the same nonce on that element yourself.
263
281
  *
264
- * **Pass this OR render your own `CSPProvider` — not both.** Base UI's
265
- * context carries a second value beside the nonce, `disableStyleElements`,
266
- * and its provider is the only public way to set either: the package exports
267
- * `CSPProvider` and no hook, so a provider rendered here *replaces* an outer
268
- * one rather than extending it. Given a nonce this provider therefore sets
269
- * `disableStyleElements` back to its default, and a consumer who had turned
270
- * it on outside loses it silently — Base UI resumes emitting the very style
271
- * element they suppressed. An application already rendering its own
272
- * `CSPProvider` needs nothing from this prop: leave it unset and the outer
273
- * context survives untouched, which is the case
274
- * `base-ui-nonce-outer-provider.test.tsx` pins.
282
+ * **An outer `CSPProvider` that sets `disableStyleElements` is switched off
283
+ * inside this provider once a nonce is given.** Base UI's `CSPProvider`
284
+ * builds its context from its own props alone, so the one rendered here
285
+ * *replaces* an outer one rather than extending it. Either leave this prop
286
+ * unset — only when no `overrides.densities` needs it and, wherever a
287
+ * `<Slider thumbAlignment="edge">` renders, the outer provider carries the
288
+ * nonce — or render
289
+ * `<CSPProvider nonce={nonce} disableStyleElements>` again inside this
290
+ * provider's children (with the nonce, or Base UI's pre-hydration script
291
+ * there loses it), and again inside any nested provider given a nonce. An
292
+ * application already rendering its own `CSPProvider` can leave this prop
293
+ * unset: Base UI's pre-hydration script takes the outer nonce, and so does
294
+ * its scrollbar rule wherever React creates it in the browser — the case
295
+ * `base-ui-nonce-outer-provider.test.tsx` pins — but the density layer then
296
+ * has none.
275
297
  *
276
- * **A nonce cannot rescue a style ATTRIBUTE**, and this provider always sets
277
- * one on its root: `color-scheme` and `--cue-font-scale`, plus the font
278
- * families and overrides where they are given. CSP has no nonce form for
279
- * `style-src-attr` — it is `'unsafe-inline'` or `'none'` — so an application
280
- * serving `style-src-attr 'none'` loses those declarations, silently. That is
281
- * a policy decision rather than something this prop can change.
298
+ * **A nonce cannot rescue a style ATTRIBUTE.** This provider's root always
299
+ * carries one — `color-scheme` and `--cue-font-scale`, plus `fontFamilies`,
300
+ * `overrides.colors`, `overrides.fonts` and `style` where given — and many
301
+ * components, and Base UI's form roots, render their own. A policy whose
302
+ * `style-src` (or, without one, `default-src`) does not allow all inline
303
+ * style — a nonce or a hash in it, or no `'unsafe-inline'` — therefore needs
304
+ * an explicit `style-src-attr 'unsafe-inline'`: a nonce or hash in the
305
+ * governing list makes the browser ignore `'unsafe-inline'`. The browser
306
+ * reports a refused attribute as a CSP violation; this library adds no
307
+ * warning of its own.
282
308
  */
283
309
  nonce?: string;
284
310
  /** Stamp the single child element instead of rendering a wrapper `<div>`. */
@@ -330,6 +356,6 @@ interface ThemeProviderProps {
330
356
  * <App />
331
357
  * </ThemeProvider>
332
358
  */
333
- declare function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp, font: fontProp, styleSet: styleSetProp, fontScale, fontFamilies, overrides, storageKey, persistPreferences, nonce, asChild, className, style: styleProp, children }: ThemeProviderProps): React.JSX.Element;
359
+ declare function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp, font: fontProp, styleSet: styleSetProp, paint: paintProp, fontScale, fontFamilies, overrides, storageKey, persistPreferences, nonce, asChild, className, style: styleProp, children }: ThemeProviderProps): React.JSX.Element;
334
360
  //#endregion
335
361
  export { FontFamilies, ResolvedMode, ThemeContextValue, ThemeProvider, ThemeProviderProps };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { useIsomorphicInsertionEffect, useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
4
- import { AmbientThemeContext, DensityContext, StyleSetContext } from "./density.js";
5
- import { buildRegistry, isStyleSet, vocabulary, warnOnce } from "./vocabulary.js";
4
+ import { AmbientThemeContext, DensityContext, PaintContext, StyleSetContext } from "./density.js";
5
+ import { buildRegistry, isPaint, isStyleSet, vocabulary, warnOnce } from "./vocabulary.js";
6
6
  import { OverridesContext, inlineOverrides, overridesCss, reportOverrides } from "./overrides.js";
7
7
  import { DEFAULT_STORAGE_KEY } from "./prepaint.js";
8
8
  import { ThemeRegistryContext } from "./theme-registry.js";
@@ -117,16 +117,21 @@ function acceptedPreferences(vocab, stored, fallback) {
117
117
  density: vocab.acceptsDensity(theme, stored.density) ? stored.density : vocab.acceptsDensity(theme, fallback.density) ? fallback.density : vocab.preferredDensity(theme),
118
118
  font: vocab.acceptsFont(theme, stored.font) ? stored.font : vocab.acceptsFont(theme, fallback.font) ? fallback.font : vocab.preferredFont(theme),
119
119
  mode: isOneOf(MODES, stored.mode) ? stored.mode : fallback.mode,
120
- styleSet: isStyleSet(stored.style) ? stored.style : fallback.styleSet
120
+ styleSet: isStyleSet(stored.style) ? stored.style : fallback.styleSet,
121
+ paint: isPaint(stored.paint) ? stored.paint : fallback.paint
121
122
  };
122
123
  }
123
124
  function writePreferences(storageKey, preferences) {
124
125
  if (typeof localStorage === "undefined") return;
125
- const { styleSet, ...axes } = preferences;
126
- const payload = styleSet === null ? axes : {
126
+ const { styleSet, paint, ...axes } = preferences;
127
+ const withStyle = styleSet === null ? axes : {
127
128
  ...axes,
128
129
  style: styleSet
129
130
  };
131
+ const payload = paint === null ? withStyle : {
132
+ ...withStyle,
133
+ paint
134
+ };
130
135
  try {
131
136
  localStorage.setItem(storageKey, JSON.stringify(payload));
132
137
  } catch {}
@@ -171,10 +176,11 @@ function writePreferences(storageKey, preferences) {
171
176
  * <App />
172
177
  * </ThemeProvider>
173
178
  */
174
- function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp = DEFAULT_MODE, font: fontProp, styleSet: styleSetProp, fontScale = 1, fontFamilies, overrides, storageKey = DEFAULT_STORAGE_KEY, persistPreferences = true, nonce, asChild = false, className, style: styleProp, children }) {
179
+ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp = DEFAULT_MODE, font: fontProp, styleSet: styleSetProp, paint: paintProp, fontScale = 1, fontFamilies, overrides, storageKey = DEFAULT_STORAGE_KEY, persistPreferences = true, nonce, asChild = false, className, style: styleProp, children }) {
175
180
  const ambient = React.useContext(ThemeContext);
176
181
  const isRoot = ambient === null;
177
182
  const outerStyleSet = React.useContext(StyleSetContext);
183
+ const outerPaint = React.useContext(PaintContext);
178
184
  const ambientRegistry = React.useContext(ThemeRegistryContext);
179
185
  const themes = themesProp ?? ambientRegistry?.themes ?? EMPTY;
180
186
  const vocab = React.useMemo(() => vocabulary(themes), [themes]);
@@ -200,10 +206,12 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
200
206
  const initialDensity = densityProp ?? vocab.preferredDensity(initialTheme);
201
207
  const initialFont = fontProp ?? vocab.preferredFont(initialTheme);
202
208
  const initialStyleSet = styleSetProp ?? (isRoot ? null : outerStyleSet);
209
+ const initialPaint = paintProp ?? (isRoot ? null : outerPaint);
203
210
  const [theme, setThemeState] = React.useState(initialTheme);
204
211
  const [densityState, setDensityState] = React.useState(initialDensity);
205
212
  const [mode, setModeState] = React.useState(modeProp);
206
213
  const [styleSet, setStyleSetState] = React.useState(initialStyleSet);
214
+ const [paint, setPaintState] = React.useState(initialPaint);
207
215
  const [storedSeed] = React.useState(() => {
208
216
  if (!isRoot || !persistPreferences) return {
209
217
  theme: initialTheme,
@@ -245,14 +253,16 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
245
253
  density,
246
254
  font,
247
255
  mode,
248
- styleSet
256
+ styleSet,
257
+ paint
249
258
  });
250
259
  setThemeState(next.theme);
251
260
  setDensityState(next.density);
252
261
  setRootFontState(next.font);
253
262
  setModeState(next.mode);
254
263
  setStyleSetState(next.styleSet);
255
- if (stored.theme !== void 0 && stored.theme !== next.theme || stored.density !== void 0 && stored.density !== next.density || stored.font !== void 0 && stored.font !== next.font || stored.mode !== void 0 && stored.mode !== next.mode || stored.style !== void 0 && !isStyleSet(stored.style)) writePreferences(storageKey, next);
264
+ setPaintState(next.paint);
265
+ if (stored.theme !== void 0 && stored.theme !== next.theme || stored.density !== void 0 && stored.density !== next.density || stored.font !== void 0 && stored.font !== next.font || stored.mode !== void 0 && stored.mode !== next.mode || stored.style !== void 0 && !isStyleSet(stored.style) || stored.paint !== void 0 && !isPaint(stored.paint)) writePreferences(storageKey, next);
256
266
  }, [
257
267
  isRoot,
258
268
  persistPreferences,
@@ -263,7 +273,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
263
273
  density: densityProp,
264
274
  mode: modeProp,
265
275
  font: fontProp,
266
- styleSet: styleSetProp
276
+ styleSet: styleSetProp,
277
+ paint: paintProp
267
278
  });
268
279
  React.useEffect(() => {
269
280
  const previous = lastProps.current;
@@ -272,19 +283,22 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
272
283
  density: densityProp,
273
284
  mode: modeProp,
274
285
  font: fontProp,
275
- styleSet: styleSetProp
286
+ styleSet: styleSetProp,
287
+ paint: paintProp
276
288
  };
277
289
  if (previous.theme !== themeProp && themeProp !== void 0) setThemeState(themeProp);
278
290
  if (previous.density !== densityProp && densityProp !== void 0) setDensityState(densityProp);
279
291
  if (previous.mode !== modeProp) setModeState(modeProp);
280
292
  if (previous.font !== fontProp && fontProp !== void 0) setRootFontState(fontProp);
281
293
  if (previous.styleSet !== styleSetProp && styleSetProp !== void 0) setStyleSetState(styleSetProp);
294
+ if (previous.paint !== paintProp && paintProp !== void 0) setPaintState(paintProp);
282
295
  }, [
283
296
  themeProp,
284
297
  densityProp,
285
298
  modeProp,
286
299
  fontProp,
287
- styleSetProp
300
+ styleSetProp,
301
+ paintProp
288
302
  ]);
289
303
  useIsomorphicLayoutEffect(() => {
290
304
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
@@ -299,7 +313,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
299
313
  density: densityState,
300
314
  mode,
301
315
  font: rawFont,
302
- styleSet
316
+ styleSet,
317
+ paint
303
318
  });
304
319
  useIsomorphicLayoutEffect(() => {
305
320
  stateRef.current = {
@@ -307,7 +322,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
307
322
  density: densityState,
308
323
  mode,
309
324
  font: rawFont,
310
- styleSet
325
+ styleSet,
326
+ paint
311
327
  };
312
328
  });
313
329
  const persist = React.useCallback((patch) => {
@@ -345,6 +361,10 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
345
361
  setStyleSetState(next);
346
362
  persist({ styleSet: next });
347
363
  }, [persist]);
364
+ const setPaint = React.useCallback((next) => {
365
+ setPaintState(next);
366
+ persist({ paint: next });
367
+ }, [persist]);
348
368
  const originalStamp = React.useRef(null);
349
369
  useIsomorphicInsertionEffect(() => {
350
370
  if (!isRoot || typeof document === "undefined") return;
@@ -354,7 +374,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
354
374
  density,
355
375
  font,
356
376
  mode,
357
- styleSet
377
+ styleSet,
378
+ paint
358
379
  };
359
380
  const next = restored || !persistPreferences ? current : acceptedPreferences(vocab, readPreferences(storageKey), current);
360
381
  originalStamp.current ??= {
@@ -363,6 +384,7 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
363
384
  font: root.getAttribute("data-font"),
364
385
  mode: root.getAttribute("data-mode"),
365
386
  style: root.getAttribute("data-style"),
387
+ paint: root.getAttribute("data-paint"),
366
388
  colorScheme: root.style.colorScheme
367
389
  };
368
390
  const write = (name, value) => {
@@ -375,6 +397,9 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
375
397
  if (next.styleSet === null) {
376
398
  if (root.hasAttribute("data-style")) root.removeAttribute("data-style");
377
399
  } else write("data-style", next.styleSet);
400
+ if (next.paint === null) {
401
+ if (root.hasAttribute("data-paint")) root.removeAttribute("data-paint");
402
+ } else write("data-paint", next.paint);
378
403
  const scheme = (themes.find((m) => m.name === next.theme) ?? null)?.supportsLight === false ? "dark" : next.mode === "system" ? "light dark" : next.mode;
379
404
  if (root.style.colorScheme !== scheme) root.style.colorScheme = scheme;
380
405
  }, [
@@ -404,9 +429,19 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
404
429
  restore("data-font", original.font);
405
430
  restore("data-mode", original.mode);
406
431
  restore("data-style", original.style);
432
+ restore("data-paint", original.paint);
407
433
  root.style.colorScheme = original.colorScheme;
408
434
  }, []);
409
435
  const effectiveStyleSet = styleSet ?? outerStyleSet;
436
+ /**
437
+ * The pack in force, for the same reason and with the same caveat: it is what
438
+ * `useTheme().paint` reports, and it does NOT feed the `data-paint` stamp.
439
+ * That stays on this provider's own `paint` state, so a root that named none
440
+ * stamps nothing on itself and nothing on `<html>` however much is stamped
441
+ * around it — which keeps a `<Density paint>` island out of the document-wide
442
+ * attribute and out of the storage the pre-paint script reads back.
443
+ */
444
+ const effectivePaint = paint ?? outerPaint;
410
445
  const contextValue = React.useMemo(() => ({
411
446
  theme,
412
447
  manifest,
@@ -414,12 +449,14 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
414
449
  mode,
415
450
  font,
416
451
  styleSet: effectiveStyleSet,
452
+ paint: effectivePaint,
417
453
  resolvedMode,
418
454
  setTheme,
419
455
  setDensity,
420
456
  setMode,
421
457
  setFont,
422
- setStyleSet
458
+ setStyleSet,
459
+ setPaint
423
460
  }), [
424
461
  theme,
425
462
  manifest,
@@ -427,12 +464,14 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
427
464
  mode,
428
465
  font,
429
466
  effectiveStyleSet,
467
+ effectivePaint,
430
468
  resolvedMode,
431
469
  setTheme,
432
470
  setDensity,
433
471
  setMode,
434
472
  setFont,
435
- setStyleSet
473
+ setStyleSet,
474
+ setPaint
436
475
  ]);
437
476
  /** The axes on offer under the theme that is actually active. */
438
477
  const registry = React.useMemo(() => buildRegistry(themes, theme), [themes, theme]);
@@ -491,7 +530,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
491
530
  "data-theme": theme,
492
531
  "data-density": density,
493
532
  "data-mode": mode,
494
- ...styleSet === null ? null : { "data-style": styleSet }
533
+ ...styleSet === null ? null : { "data-style": styleSet },
534
+ ...paint === null ? null : { "data-paint": paint }
495
535
  };
496
536
  let root;
497
537
  if (asChild) {
@@ -516,18 +556,25 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
516
556
  children: overridesStyle
517
557
  });
518
558
  /**
519
- * Base UI's own style elements, which this provider's nonce also has to reach.
559
+ * Base UI's own style and script elements, which this provider's nonce also
560
+ * has to reach.
520
561
  *
521
562
  * `@base-ui/react` renders one style element — a hoisted
522
563
  * `<style precedence>` carrying `.base-ui-disable-scrollbar` — from
523
564
  * `utils/styles.mjs`. `ScrollAreaRoot` and `SelectPopup` pass it a nonce they
524
565
  * read from Base UI's own `CSPContext`, and nothing fills that context unless
525
566
  * a `CSPProvider` is rendered above them. Without one it ships bare and a
526
- * `style-src-elem` policy refuses it by content hash, on every page that
527
- * renders a Select, a Popover or a ScrollArea — which is most authenticated
528
- * pages of a real application, and no page of its sign-in screen. A consumer
529
- * cannot reasonably guess that the fix lives in a peer dependency's provider,
530
- * and this library already takes the nonce and already sits at the root.
567
+ * `style-src-elem` policy refuses it on every page that mounts a ScrollArea
568
+ * or a Select's popup — and the browser's message names neither Base UI nor
569
+ * this prop, so a consumer cannot reasonably guess that the fix lives in a
570
+ * peer dependency's provider. This library already takes the nonce and
571
+ * already sits at the root.
572
+ *
573
+ * It reaches the element React creates in the browser. A ScrollArea's
574
+ * element in server-rendered HTML is written by React's server renderer,
575
+ * which takes a `precedence` style's nonce only from its own render option
576
+ * `nonce: { style }`; the `nonce` prop's docblock says what that means under
577
+ * Next.js, and what to do about it.
531
578
  *
532
579
  * Rendered **only when a nonce was given**, and that is not tidiness. A
533
580
  * consumer that wraps its own application in `CSPProvider` is the case this
@@ -1,4 +1,4 @@
1
- import { StyleSet } from "@cueplusplus/tokens";
1
+ import { Paint, StyleSet } from "@cueplusplus/tokens";
2
2
  import { Density as Density$1, DensityEntry, FontEntry, FontName, ThemeManifest } from "@cueplusplus/theme-base";
3
3
  //#region src/system/vocabulary.d.ts
4
4
  /** What the three registry hooks read: the manifests, and the axes the ACTIVE theme offers. */
@@ -1,4 +1,4 @@
1
- import { DEFAULT_DENSITY, DEFAULT_FONT, STYLE_SETS } from "@cueplusplus/tokens";
1
+ import { DEFAULT_DENSITY, DEFAULT_FONT, PAINTS, STYLE_SETS } from "@cueplusplus/tokens";
2
2
  import { DENSITIES, FONTS, THEME_NAME_PATTERN, resolveDensities, resolveFonts } from "@cueplusplus/theme-base";
3
3
  //#region src/system/vocabulary.ts
4
4
  /**
@@ -82,6 +82,18 @@ function vocabulary(themes) {
82
82
  function isStyleSet(value) {
83
83
  return typeof value === "string" && STYLE_SETS.includes(value);
84
84
  }
85
+ /**
86
+ * Whether a value is one of the look packs.
87
+ *
88
+ * Standalone for exactly the reason {@link isStyleSet} is, and the reason reads
89
+ * the same one axis over: no theme can add a pack. The vocabulary is emitted by
90
+ * `@cueplusplus/tokens`, no manifest field describes it, so there is nothing
91
+ * per-theme to ask and a per-theme signature would be parameters pretending to
92
+ * be a rule.
93
+ */
94
+ function isPaint(value) {
95
+ return typeof value === "string" && PAINTS.includes(value);
96
+ }
85
97
  /** Derive the context value. Pure; the provider memoises it on `themes` and the active name. */
86
98
  function buildRegistry(themes, active) {
87
99
  return {
@@ -122,4 +134,4 @@ function noteOnce(message) {
122
134
  console.info(`[cue] ${message}`);
123
135
  }
124
136
  //#endregion
125
- export { buildRegistry, isStyleSet, noteOnce, vocabulary, warnOnce };
137
+ export { buildRegistry, isPaint, isStyleSet, noteOnce, vocabulary, warnOnce };
@@ -174,6 +174,17 @@
174
174
  "--cue-fg-subtle",
175
175
  "--cue-font-mono",
176
176
  "--cue-leading-ui",
177
+ "--cue-paint-rim-width",
178
+ "--cue-paint-shade-far",
179
+ "--cue-paint-shade-hairline",
180
+ "--cue-paint-shade-near",
181
+ "--cue-paint-shadow-scale",
182
+ "--cue-paint-shadow-spread",
183
+ "--cue-paint-sheen-ink",
184
+ "--cue-paint-stroke-angle",
185
+ "--cue-paint-stroke-from",
186
+ "--cue-paint-stroke-to",
187
+ "--cue-paint-stroke-width",
177
188
  "--cue-radius-control",
178
189
  "--cue-radius-overlay",
179
190
  "--cue-scrim",
@@ -185,7 +196,8 @@
185
196
  "--cue-surface-2",
186
197
  "--cue-text-emphasis",
187
198
  "--cue-text-label",
188
- "--cue-text-ui"
199
+ "--cue-text-ui",
200
+ "--cue-tracking-caps"
189
201
  ],
190
202
  "summary": "A modal that asks one question with two answers, for anything irreversible.",
191
203
  "examples": [
@@ -232,6 +232,10 @@
232
232
  "--cue-fg-muted",
233
233
  "--cue-font-mono",
234
234
  "--cue-icon-sm",
235
+ "--cue-paint-fade-length",
236
+ "--cue-paint-glass-fallback-ink",
237
+ "--cue-paint-glass-filter",
238
+ "--cue-paint-glass-ink",
235
239
  "--cue-space-3",
236
240
  "--cue-space-4",
237
241
  "--cue-space-5",
@@ -219,6 +219,17 @@
219
219
  "--cue-font-mono",
220
220
  "--cue-icon-sm",
221
221
  "--cue-leading-ui",
222
+ "--cue-paint-rim-width",
223
+ "--cue-paint-shade-far",
224
+ "--cue-paint-shade-hairline",
225
+ "--cue-paint-shade-near",
226
+ "--cue-paint-shadow-scale",
227
+ "--cue-paint-shadow-spread",
228
+ "--cue-paint-sheen-ink",
229
+ "--cue-paint-stroke-angle",
230
+ "--cue-paint-stroke-from",
231
+ "--cue-paint-stroke-to",
232
+ "--cue-paint-stroke-width",
222
233
  "--cue-radius-control",
223
234
  "--cue-radius-overlay",
224
235
  "--cue-scrim",
@@ -232,7 +243,8 @@
232
243
  "--cue-text-body",
233
244
  "--cue-text-emphasis",
234
245
  "--cue-text-label",
235
- "--cue-text-ui"
246
+ "--cue-text-ui",
247
+ "--cue-tracking-caps"
236
248
  ],
237
249
  "summary": "A text field that suggests as you type — and accepts what you typed anyway.",
238
250
  "examples": [