@cueplusplus/ui 0.15.0 → 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.
- package/CHANGELOG.md +258 -0
- package/README.md +26 -0
- package/dist/chat/message-list.js +2 -1
- package/dist/chrome/_tabs-scroll.d.ts +17 -1
- package/dist/chrome/_tabs-scroll.js +20 -3
- package/dist/chrome/app-bar.js +2 -1
- package/dist/chrome/band.js +3 -1
- package/dist/chrome/panel.js +2 -1
- package/dist/color/color-field.d.ts +2 -1
- package/dist/color/color-picker.d.ts +2 -1
- package/dist/date/date-field.d.ts +2 -1
- package/dist/date/date-picker.d.ts +2 -1
- package/dist/date/date-range-picker.d.ts +2 -1
- package/dist/date/time-field.d.ts +2 -1
- package/dist/forms/_chassis-size.d.ts +22 -0
- package/dist/forms/_chassis.d.ts +3 -10
- package/dist/forms/_chassis.js +2 -1
- package/dist/forms/autocomplete.d.ts +2 -1
- package/dist/forms/combobox.d.ts +2 -1
- package/dist/forms/env-var-input.d.ts +2 -1
- package/dist/forms/index.d.ts +2 -1
- package/dist/forms/input-group.d.ts +2 -1
- package/dist/forms/input.d.ts +2 -1
- package/dist/forms/multi-select.d.ts +2 -1
- package/dist/forms/otp-field.d.ts +2 -1
- package/dist/forms/password-input.d.ts +2 -1
- package/dist/forms/scrub-input.d.ts +2 -1
- package/dist/forms/search-input.d.ts +2 -1
- package/dist/forms/select.d.ts +2 -1
- package/dist/forms/select.js +2 -1
- package/dist/forms/tags-input.d.ts +2 -1
- package/dist/forms/toggle-group.d.ts +1 -1
- package/dist/forms/toggle.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/instruments/log-viewer.js +2 -1
- package/dist/layout/card.js +3 -1
- package/dist/midi/musical-time-input.d.ts +2 -1
- package/dist/overlays/_surface.d.ts +1 -1
- package/dist/overlays/_surface.js +3 -1
- package/dist/primitives/button.js +2 -1
- package/dist/primitives/chip.d.ts +1 -1
- package/dist/system/_paint-elevation.js +9 -0
- package/dist/system/_paint-glass.js +46 -0
- package/dist/system/_paint-glow.js +32 -0
- package/dist/system/_paint-ground-pattern.js +30 -0
- package/dist/system/_paint-rim.js +41 -0
- package/dist/system/_paint-stroke-sunken.js +19 -0
- package/dist/system/_paint-stroke-surface-1.js +19 -0
- package/dist/system/_paint-stroke-surface-2.js +27 -0
- package/dist/system/_paint-texture.js +53 -0
- package/dist/system/theme-provider.d.ts +47 -36
- package/dist/system/theme-provider.js +13 -6
- package/manifest/components/alert-dialog.json +11 -0
- package/manifest/components/app-bar.json +4 -0
- package/manifest/components/autocomplete.json +11 -0
- package/manifest/components/band.json +8 -1
- package/manifest/components/button.json +4 -0
- package/manifest/components/card.json +6 -0
- package/manifest/components/channel-matrix.json +11 -0
- package/manifest/components/chart-tooltip-content.json +11 -0
- package/manifest/components/color-field.json +4 -0
- package/manifest/components/color-picker.json +4 -0
- package/manifest/components/combobox.json +11 -0
- package/manifest/components/command-palette.json +11 -0
- package/manifest/components/composer.json +4 -0
- package/manifest/components/context-menu.json +11 -0
- package/manifest/components/date-field.json +4 -0
- package/manifest/components/date-picker.json +4 -0
- package/manifest/components/date-range-picker.json +4 -0
- package/manifest/components/density.json +8 -2
- package/manifest/components/dialog.json +11 -0
- package/manifest/components/dmx-bar.json +11 -0
- package/manifest/components/dmx-strip.json +11 -0
- package/manifest/components/drawer.json +11 -0
- package/manifest/components/dropdown-menu.json +11 -0
- package/manifest/components/env-var-input.json +4 -0
- package/manifest/components/hover-card.json +11 -0
- package/manifest/components/input-group.json +4 -0
- package/manifest/components/input.json +4 -0
- package/manifest/components/log-viewer.json +7 -0
- package/manifest/components/menubar.json +11 -0
- package/manifest/components/message-list.json +7 -0
- package/manifest/components/multi-select.json +11 -0
- package/manifest/components/musical-time-input.json +4 -0
- package/manifest/components/navigation-menu.json +11 -0
- package/manifest/components/number-field.json +4 -0
- package/manifest/components/otp-field.json +4 -0
- package/manifest/components/panel-header.json +2 -0
- package/manifest/components/panel.json +2 -0
- package/manifest/components/password-input.json +4 -0
- package/manifest/components/popover.json +11 -0
- package/manifest/components/preview.json +8 -2
- package/manifest/components/scrollable-tabs-list.json +1 -0
- package/manifest/components/scrub-input.json +4 -0
- package/manifest/components/search-input.json +4 -0
- package/manifest/components/segmented-control.json +1 -0
- package/manifest/components/select.json +11 -0
- package/manifest/components/sheet.json +11 -0
- package/manifest/components/tabs.json +1 -0
- package/manifest/components/tags-input.json +11 -0
- package/manifest/components/textarea.json +4 -0
- package/manifest/components/theme-configurator.json +11 -0
- package/manifest/components/theme-provider.json +9 -3
- package/manifest/components/time-field.json +4 -0
- package/manifest/components/toast.json +11 -0
- package/manifest/components/toggle-group.json +1 -19
- package/manifest/components/toggle.json +0 -6
- package/manifest/components/toolbar.json +1 -0
- package/manifest/components/tooltip.json +11 -0
- package/manifest/manifest.json +59 -59
- package/manifest/tokens.json +21 -2
- package/package.json +5 -5
package/dist/forms/select.d.ts
CHANGED
package/dist/forms/select.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { controlVariants } from "./_chassis.js";
|
|
4
|
+
import { ELEVATION_2 } from "../system/_paint-elevation.js";
|
|
4
5
|
import { useCuePortalProps } from "../system/portal.js";
|
|
5
6
|
import { CaretGlyph, TickGlyph } from "./_glyphs.js";
|
|
6
7
|
import * as React from "react";
|
|
@@ -65,7 +66,7 @@ const Select$1 = React.forwardRef(function Select$2({ items, value, defaultValue
|
|
|
65
66
|
alignItemWithTrigger: false,
|
|
66
67
|
children: /* @__PURE__ */ jsx(Select.Popup, {
|
|
67
68
|
"data-slot": "select-popup",
|
|
68
|
-
className: cn(
|
|
69
|
+
className: cn(`min-w-(--anchor-width) origin-(--transform-origin) overflow-hidden rounded-(--radius-overlay) border border-border-overlay bg-surface-2 py-(--cue-space-1) ${ELEVATION_2} outline-none`, "transition-[opacity,scale] duration-100 ease-out motion-reduce:transition-none", "data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0", "data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0", popupClassName),
|
|
69
70
|
children: /* @__PURE__ */ jsx(Select.List, {
|
|
70
71
|
className: "max-h-(--available-height) overflow-y-auto",
|
|
71
72
|
children: items.map((item) => /* @__PURE__ */ jsxs(Select.Item, {
|
package/dist/forms/toggle.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -34,7 +34,8 @@ import { TitleBar, TitleBarProps } from "./chrome/title-bar.js";
|
|
|
34
34
|
import { Tree, TreeProps, TreeVisibility, TreeVisibilityToggle, TreeVisibilityToggleProps } from "./chrome/tree.js";
|
|
35
35
|
import { Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarRootProps, ToolbarSeparatorProps } from "./chrome/toolbar.js";
|
|
36
36
|
import "./chrome/index.js";
|
|
37
|
-
import {
|
|
37
|
+
import { FormControlSize } from "./forms/_chassis-size.js";
|
|
38
|
+
import { ControlVariantProps, bareControlClasses, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants } from "./forms/_chassis.js";
|
|
38
39
|
import { TokenOverrides, isSafeTokenValue } from "./system/overrides.js";
|
|
39
40
|
import { FontFamilies, ResolvedMode, ThemeContextValue, ThemeProvider, ThemeProviderProps } from "./system/theme-provider.js";
|
|
40
41
|
import { Autocomplete, AutocompleteProps } from "./forms/autocomplete.js";
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { Chip } from "../primitives/chip.js";
|
|
4
4
|
import { useIsomorphicLayoutEffect } from "../system/use-isomorphic-layout-effect.js";
|
|
5
|
+
import { ELEVATION_2 } from "../system/_paint-elevation.js";
|
|
5
6
|
import { toRem } from "./_rem.js";
|
|
6
7
|
import { useControlHeight } from "../system/use-density.js";
|
|
7
8
|
import { ansiSpans } from "./_ansi.js";
|
|
@@ -204,7 +205,7 @@ const LogViewer = React.forwardRef(function LogViewer({ className, lines, follow
|
|
|
204
205
|
pending > 0 ? /* @__PURE__ */ jsx("button", {
|
|
205
206
|
type: "button",
|
|
206
207
|
"data-slot": "log-viewer-jump",
|
|
207
|
-
className:
|
|
208
|
+
className: `absolute bottom-(--cue-space-4) left-1/2 -translate-x-1/2 cursor-pointer rounded-(--radius-control) border border-border-overlay bg-surface-2 px-(--cue-space-4) py-(--cue-space-2) font-mono text-(length:--cue-text-label) text-fg ${ELEVATION_2} outline-none hover:border-accent hover:text-accent focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent`,
|
|
208
209
|
onClick: jumpToBottom,
|
|
209
210
|
children: newLinesLabel(pending)
|
|
210
211
|
}) : null
|
package/dist/layout/card.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { cn } from "../lib/cn.js";
|
|
2
|
+
import { RIM_INSET } from "../system/_paint-rim.js";
|
|
3
|
+
import { STROKE_SURFACE_1 } from "../system/_paint-stroke-surface-1.js";
|
|
2
4
|
import * as React from "react";
|
|
3
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
6
|
/**
|
|
@@ -19,7 +21,7 @@ const Card = {
|
|
|
19
21
|
ref,
|
|
20
22
|
"data-slot": "card",
|
|
21
23
|
"data-seam": seam ? "" : void 0,
|
|
22
|
-
className: cn("group/card flex flex-col overflow-hidden rounded-(--radius-surface)
|
|
24
|
+
className: cn("group/card flex flex-col overflow-hidden rounded-(--radius-surface)", seam ? "border border-border gap-px bg-border" : `${STROKE_SURFACE_1} ${RIM_INSET}`, className),
|
|
23
25
|
...elementProps
|
|
24
26
|
});
|
|
25
27
|
}),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { FormControlSize } from "../forms/_chassis.js";
|
|
1
|
+
import { FormControlSize } from "../forms/_chassis-size.js";
|
|
2
|
+
import "../forms/_chassis.js";
|
|
2
3
|
import { TimeSignature } from "./_time.js";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
//#region src/midi/musical-time-input.d.ts
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @example
|
|
19
19
|
* <Popover.Popup className={cn(overlaySurfaceClasses, className)} />
|
|
20
20
|
*/
|
|
21
|
-
declare const overlaySurfaceClasses = "
|
|
21
|
+
declare const overlaySurfaceClasses = "rounded-(--radius-overlay) border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-surface-2),var(--cue-surface-2)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border-overlay)),var(--cue-paint-stroke-to,var(--cue-border-overlay)))] bg-origin-border [background-clip:padding-box,border-box] shadow-[0_0_0_var(--cue-paint-rim-width)_var(--cue-paint-shade-hairline,transparent),0_calc(2px*var(--cue-paint-shadow-scale))_calc(6px*var(--cue-paint-shadow-scale))_var(--cue-paint-shadow-spread)_var(--cue-paint-shade-near,transparent),0_calc(8px*var(--cue-paint-shadow-scale))_calc(24px*var(--cue-paint-shadow-scale))_var(--cue-paint-shadow-spread)_var(--cue-paint-shade-far,rgba(0,0,0,0.4)),inset_0_1px_0_0_var(--cue-paint-sheen-ink,transparent)]";
|
|
22
22
|
/**
|
|
23
23
|
* The full-viewport dim behind a modal surface. `--cue-scrim` is theme-owned —
|
|
24
24
|
* dusk and hivehub tune their own — so the value is never hard-coded here.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ELEVATION_2 } from "../system/_paint-elevation.js";
|
|
2
|
+
import { STROKE_SURFACE_2 } from "../system/_paint-stroke-surface-2.js";
|
|
1
3
|
//#region src/overlays/_surface.ts
|
|
2
4
|
/**
|
|
3
5
|
* The conventions every floating surface in this system shares.
|
|
@@ -18,7 +20,7 @@
|
|
|
18
20
|
* @example
|
|
19
21
|
* <Popover.Popup className={cn(overlaySurfaceClasses, className)} />
|
|
20
22
|
*/
|
|
21
|
-
const overlaySurfaceClasses =
|
|
23
|
+
const overlaySurfaceClasses = `rounded-(--radius-overlay) ${STROKE_SURFACE_2} ${ELEVATION_2}`;
|
|
22
24
|
/**
|
|
23
25
|
* The full-viewport dim behind a modal surface. `--cue-scrim` is theme-owned —
|
|
24
26
|
* dusk and hivehub tune their own — so the value is never hard-coded here.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
3
|
import { cva } from "../lib/cva.js";
|
|
4
|
+
import { GLOW_CLASSES } from "../system/_paint-glow.js";
|
|
4
5
|
import * as React from "react";
|
|
5
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { useRender } from "@base-ui/react/use-render";
|
|
@@ -39,7 +40,7 @@ const buttonChassis = "inline-flex select-none items-center justify-center gap-[
|
|
|
39
40
|
* @internal Not part of the public API; imported by `icon-button.tsx`.
|
|
40
41
|
*/
|
|
41
42
|
const buttonTones = {
|
|
42
|
-
primary:
|
|
43
|
+
primary: `bg-accent text-accent-fg hover:bg-accent-hover border border-transparent ${GLOW_CLASSES}`,
|
|
43
44
|
secondary: "border border-border text-fg-muted hover:border-border-strong hover:text-fg bg-surface-2",
|
|
44
45
|
ghost: "text-fg-muted hover:text-fg hover:bg-surface-2 border border-transparent",
|
|
45
46
|
outline: "border border-border text-fg hover:border-accent hover:text-accent bg-transparent",
|
|
@@ -30,7 +30,7 @@ import * as React from "react";
|
|
|
30
30
|
* <span className={chipVariants({ variant: "tag" })}>mcp</span>
|
|
31
31
|
*/
|
|
32
32
|
declare const chipVariants: (props?: ({
|
|
33
|
-
tone?: "
|
|
33
|
+
tone?: "danger" | "info" | "warn" | "accent" | "ok" | "busy" | "neutral" | null | undefined;
|
|
34
34
|
variant?: "outline" | "tinted" | "tag" | null | undefined;
|
|
35
35
|
interactive?: boolean | null | undefined;
|
|
36
36
|
} & ClassProp) | undefined) => string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/system/_paint-elevation.ts
|
|
2
|
+
/**
|
|
3
|
+
* An overlay. Its default MUST render `0 8px 24px rgba(0,0,0,0.4)` — the literal
|
|
4
|
+
* at four call sites — which is why `--cue-paint-shade-far` is the one
|
|
5
|
+
* non-transparent shadow ink. Measured pixel-identical to it.
|
|
6
|
+
*/
|
|
7
|
+
const ELEVATION_2 = "shadow-[0_0_0_var(--cue-paint-rim-width)_var(--cue-paint-shade-hairline,transparent),0_calc(2px*var(--cue-paint-shadow-scale))_calc(6px*var(--cue-paint-shadow-scale))_var(--cue-paint-shadow-spread)_var(--cue-paint-shade-near,transparent),0_calc(8px*var(--cue-paint-shadow-scale))_calc(24px*var(--cue-paint-shadow-scale))_var(--cue-paint-shadow-spread)_var(--cue-paint-shade-far,rgba(0,0,0,0.4)),inset_0_1px_0_0_var(--cue-paint-sheen-ink,transparent)]";
|
|
8
|
+
//#endregion
|
|
9
|
+
export { ELEVATION_2 };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/system/_paint-glass.ts
|
|
2
|
+
/**
|
|
3
|
+
* Translucency, with the opaque twin every glass rule needs.
|
|
4
|
+
*
|
|
5
|
+
* **Why this writes `--tw-backdrop-blur` instead of `backdrop-filter`.** Spec
|
|
6
|
+
* §13.5, decided on measurements. Tailwind composes every backdrop utility into
|
|
7
|
+
* ONE declaration — `backdrop-filter: var(--tw-backdrop-blur,)
|
|
8
|
+
* var(--tw-backdrop-brightness,) …` — so a raw `[backdrop-filter:var(…)]` here
|
|
9
|
+
* is a second, competing declaration. Measured: a consumer passing
|
|
10
|
+
* `backdrop-brightness-50` through `className` then computes
|
|
11
|
+
* `brightness(0.5)` and **no blur at all**. The glass does not narrow, it
|
|
12
|
+
* disappears, silently.
|
|
13
|
+
*
|
|
14
|
+
* Filling Tailwind's own slot keeps the composition: the default computes
|
|
15
|
+
* `blur(8px)`, a consumer's brightness composes onto it, and a pack's
|
|
16
|
+
* `blur(12px) saturate(1.4)` survives whole — which a length-valued
|
|
17
|
+
* `backdrop-blur-(--name)` could not express at all.
|
|
18
|
+
*
|
|
19
|
+
* **`backdrop-saturate-100` is there to make the composed declaration exist**,
|
|
20
|
+
* and the choice of utility is load-bearing. Filling a slot paints nothing
|
|
21
|
+
* unless something emits the `backdrop-filter` that reads the slots, and only a
|
|
22
|
+
* backdrop utility emits it. `backdrop-blur-none` would have done that — and it
|
|
23
|
+
* writes `--tw-backdrop-blur` itself, so whichever of the two came later in the
|
|
24
|
+
* stylesheet won: measured, with `blur-none` last the glass computes `none` and
|
|
25
|
+
* disappears. `backdrop-saturate-100` writes a different slot, so the two cannot
|
|
26
|
+
* race, and `saturate(1)` is the identity filter.
|
|
27
|
+
*
|
|
28
|
+
* **The cost is naming an internal, and it is pinned rather than accepted.**
|
|
29
|
+
* `test/system/paint-glass.test.ts` asks the Tailwind compiler what
|
|
30
|
+
* `backdrop-blur` emits and asserts the variable name against that answer, so a
|
|
31
|
+
* rename fails loudly instead of the glass quietly ceasing to compose.
|
|
32
|
+
*
|
|
33
|
+
* **The fill is an explicit `background-color`, not `bg-(--name)`.** The
|
|
34
|
+
* shorthand has nowhere to put the `var()` fallback an ink requires, and an ink
|
|
35
|
+
* spent without one leaves the declaration invalid and CSS drops it in silence.
|
|
36
|
+
*
|
|
37
|
+
* **The `@supports` twin is not decoration.** A browser without
|
|
38
|
+
* `backdrop-filter` paints the translucent fill over whatever is behind it and
|
|
39
|
+
* the bar becomes unreadable; the fallback ink is the opaque surface it would
|
|
40
|
+
* have had.
|
|
41
|
+
*
|
|
42
|
+
* @internal Not part of the public API.
|
|
43
|
+
*/
|
|
44
|
+
const GLASS_CLASSES = "[--tw-backdrop-blur:var(--cue-paint-glass-filter,blur(8px))] backdrop-saturate-100 [background-color:var(--cue-paint-glass-ink,color-mix(in_oklch,var(--cue-surface-1)_95%,transparent))] [@supports_not_(backdrop-filter:blur(0px))]:[background-color:var(--cue-paint-glass-fallback-ink,var(--cue-surface-1))]";
|
|
45
|
+
//#endregion
|
|
46
|
+
export { GLASS_CLASSES };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/system/_paint-glow.ts
|
|
2
|
+
/**
|
|
3
|
+
* The halo: two offsetless stops at rest, two more on hover.
|
|
4
|
+
*
|
|
5
|
+
* **Offsetless is the rule that keeps this name from being `elevation` twice.**
|
|
6
|
+
* A drop shadow has a y-offset and reads as light from above; a halo has none
|
|
7
|
+
* and reads as the element emitting. The build refuses a glow value with an
|
|
8
|
+
* offset for that reason, with a positive control that must throw.
|
|
9
|
+
*
|
|
10
|
+
* **A separate rest and hover ink, not a `calc()` on one.** The corpus doubles
|
|
11
|
+
* the alpha on hover — railway `0.25`→`0.50`, aceternity `0.2`→`0.4` — and one
|
|
12
|
+
* site's three-layer white halo exists *only* on hover. A single ink with a
|
|
13
|
+
* multiplier cannot express the last of those at all.
|
|
14
|
+
*
|
|
15
|
+
* **Its own module**, because `@repo/docgen` attributes a token by the file its
|
|
16
|
+
* class string lives in, including through a type-only import. One device per
|
|
17
|
+
* file; the two ways that bit are recorded in `_paint-elevation.ts`.
|
|
18
|
+
*
|
|
19
|
+
* **Every ink carries its default as a `var()` fallback**, without exception: an
|
|
20
|
+
* ink is declared in no stylesheet, so a spend without one leaves the whole
|
|
21
|
+
* `box-shadow` invalid and CSS drops it in silence — measured, and the reason
|
|
22
|
+
* the elevation rungs and the stroke recipe carry theirs.
|
|
23
|
+
*
|
|
24
|
+
* **Nothing wearing this may also carry a `shadow-` literal**: `twMerge` keeps
|
|
25
|
+
* one of two `shadow-` utilities on the same element. `buttonTones` carries none
|
|
26
|
+
* on any tone, which is what makes the adoption additive.
|
|
27
|
+
*
|
|
28
|
+
* @internal Not part of the public API.
|
|
29
|
+
*/
|
|
30
|
+
const GLOW_CLASSES = "shadow-[0_0_var(--cue-paint-glow-blur)_var(--cue-paint-glow-ink,transparent),0_0_var(--cue-paint-glow-blur-far)_var(--cue-paint-glow-ink,transparent)] hover:shadow-[0_0_var(--cue-paint-glow-blur)_var(--cue-paint-glow-ink-hover,transparent),0_0_var(--cue-paint-glow-blur-far)_var(--cue-paint-glow-ink-hover,transparent)]";
|
|
31
|
+
//#endregion
|
|
32
|
+
export { GLOW_CLASSES };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/system/_paint-ground-pattern.ts
|
|
2
|
+
/**
|
|
3
|
+
* A repeating pattern on a page-level ground.
|
|
4
|
+
*
|
|
5
|
+
* **Distinct from a texture, and the difference is the layer.** A texture is
|
|
6
|
+
* noise on a pseudo-element *over* the host (`_paint-texture.ts`); a ground
|
|
7
|
+
* pattern is a repeating geometry painted as the host's own `background-image`,
|
|
8
|
+
* beneath its content and beside its `background-color`. A page can carry both:
|
|
9
|
+
* a hatch under a grain.
|
|
10
|
+
*
|
|
11
|
+
* **It sets `background-image`, so a host that paints its own image cannot take
|
|
12
|
+
* it.** The two adopting surfaces paint a `background-color` only.
|
|
13
|
+
*
|
|
14
|
+
* **Its own module**, because `@repo/docgen` attributes a token by the file its
|
|
15
|
+
* class string lives in, including through a type-only import.
|
|
16
|
+
*
|
|
17
|
+
* **The ink is spent by the pack's own image, not here.** A pattern is a whole
|
|
18
|
+
* CSS `<image>` a pack writes, and `--cue-paint-ground-pattern-ink` is the name
|
|
19
|
+
* that image references — which is why §4 documents these four image slots as
|
|
20
|
+
* freezing their ink at the element the pack block sits on, and why they are
|
|
21
|
+
* page-level devices where that costs nothing measurable.
|
|
22
|
+
*
|
|
23
|
+
* At the default `--cue-paint-ground-pattern` is `none`, so the host paints
|
|
24
|
+
* exactly what it painted before.
|
|
25
|
+
*
|
|
26
|
+
* @internal Not part of the public API.
|
|
27
|
+
*/
|
|
28
|
+
const GROUND_PATTERN_CLASSES = "bg-[image:var(--cue-paint-ground-pattern)] bg-[length:var(--cue-paint-ground-pattern-size)]";
|
|
29
|
+
//#endregion
|
|
30
|
+
export { GROUND_PATTERN_CLASSES };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/system/_paint-rim.ts
|
|
2
|
+
/**
|
|
3
|
+
* An inset ring on a surface that carries no shadow of its own.
|
|
4
|
+
*
|
|
5
|
+
* **A ring, not a border.** It is drawn as an inset `box-shadow`, outside the
|
|
6
|
+
* box model, so it costs no layout and sits inside the surface's radius. That
|
|
7
|
+
* is what lets a pack put a hairline of light on a panel without moving a
|
|
8
|
+
* single pixel of content.
|
|
9
|
+
*
|
|
10
|
+
* **NOT the recessed control chassis**, and that is an accessibility rule
|
|
11
|
+
* rather than a preference. `forced-colors: active` discards `box-shadow`
|
|
12
|
+
* entirely and repaints outlines in the user's own highlight colour, so a ring
|
|
13
|
+
* drawn as a shadow vanishes for exactly the people who most need it — and a
|
|
14
|
+
* form control's ring is a focus indicator. `forms/chassis.test.ts` asserts
|
|
15
|
+
* `controlSurface` contains no `shadow` at all, and it is right to.
|
|
16
|
+
* §22's inventory lists `_chassis.ts:101` as a rim site; it is wrong, and the
|
|
17
|
+
* guard predates it.
|
|
18
|
+
*
|
|
19
|
+
* A panel's or a card's rim is decorative, so the same loss is cosmetic there.
|
|
20
|
+
*
|
|
21
|
+
* **Nothing already carrying a `shadow-` utility may take this**, because
|
|
22
|
+
* `twMerge` keeps one of two on the same element. The three adopting surfaces
|
|
23
|
+
* were checked and carry none; an elevated surface gets its ring as the
|
|
24
|
+
* hairline *layer* of `ELEVATION_*` instead, which is what that layer is for.
|
|
25
|
+
*
|
|
26
|
+
* **Its own module**, because `@repo/docgen` attributes a token by the file its
|
|
27
|
+
* class string lives in, including through a type-only import.
|
|
28
|
+
*
|
|
29
|
+
* **The ink carries its default as a `var()` fallback**: an ink is declared in
|
|
30
|
+
* no stylesheet, so a spend without one leaves the whole `box-shadow` invalid
|
|
31
|
+
* and CSS drops it in silence — measured twice in earlier slices, once costing
|
|
32
|
+
* an element its border and its fill together.
|
|
33
|
+
*
|
|
34
|
+
* At the defaults `--cue-paint-rim-width` is `0px` and the ink is
|
|
35
|
+
* `transparent`, so the ring is a no-op twice over.
|
|
36
|
+
*
|
|
37
|
+
* @internal Not part of the public API.
|
|
38
|
+
*/
|
|
39
|
+
const RIM_INSET = "shadow-[inset_0_0_0_var(--cue-paint-rim-width)_var(--cue-paint-rim-ink,transparent)]";
|
|
40
|
+
//#endregion
|
|
41
|
+
export { RIM_INSET };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/system/_paint-stroke-sunken.ts
|
|
2
|
+
/**
|
|
3
|
+
* The gradient-stroke recipe for a recessed control — the `--cue-sunken` fill.
|
|
4
|
+
*
|
|
5
|
+
* **One fill per module, and that is the point of the file.** `@repo/docgen`
|
|
6
|
+
* attributes a token to a component by the FILE the class string lives in, so a
|
|
7
|
+
* single `_paint.ts` holding all three fills gave every adopting component all
|
|
8
|
+
* three tokens: `card.json` claimed `--cue-sunken` and `--cue-surface-2`, which
|
|
9
|
+
* `Card` does not paint. Measured on the first manifest regeneration of Slice 2;
|
|
10
|
+
* the spec's own risk register predicted it and named this split as the remedy.
|
|
11
|
+
*
|
|
12
|
+
* The recipe itself, and why its off state is a flat gradient rather than
|
|
13
|
+
* `none`, is documented once in `./_paint`.
|
|
14
|
+
*
|
|
15
|
+
* @internal Not part of the public API.
|
|
16
|
+
*/
|
|
17
|
+
const STROKE_SUNKEN = "border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-sunken),var(--cue-sunken)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] bg-origin-border [background-clip:padding-box,border-box]";
|
|
18
|
+
//#endregion
|
|
19
|
+
export { STROKE_SUNKEN };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/system/_paint-stroke-surface-1.ts
|
|
2
|
+
/**
|
|
3
|
+
* The gradient-stroke recipe for a card or panel — the `--cue-surface-1` fill.
|
|
4
|
+
*
|
|
5
|
+
* **One fill per module, and that is the point of the file.** `@repo/docgen`
|
|
6
|
+
* attributes a token to a component by the FILE the class string lives in, so a
|
|
7
|
+
* single `_paint.ts` holding all three fills gave every adopting component all
|
|
8
|
+
* three tokens: `card.json` claimed `--cue-sunken` and `--cue-surface-2`, which
|
|
9
|
+
* `Card` does not paint. Measured on the first manifest regeneration of Slice 2;
|
|
10
|
+
* the spec's own risk register predicted it and named this split as the remedy.
|
|
11
|
+
*
|
|
12
|
+
* The recipe itself, and why its off state is a flat gradient rather than
|
|
13
|
+
* `none`, is documented once in `./_paint`.
|
|
14
|
+
*
|
|
15
|
+
* @internal Not part of the public API.
|
|
16
|
+
*/
|
|
17
|
+
const STROKE_SURFACE_1 = "border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-surface-1),var(--cue-surface-1)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border)),var(--cue-paint-stroke-to,var(--cue-border)))] bg-origin-border [background-clip:padding-box,border-box]";
|
|
18
|
+
//#endregion
|
|
19
|
+
export { STROKE_SURFACE_1 };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/system/_paint-stroke-surface-2.ts
|
|
2
|
+
/**
|
|
3
|
+
* The gradient-stroke recipe for an overlay — the `--cue-surface-2` fill.
|
|
4
|
+
*
|
|
5
|
+
* **One fill per module, and that is the point of the file.** `@repo/docgen`
|
|
6
|
+
* attributes a token to a component by the FILE the class string lives in, so a
|
|
7
|
+
* single `_paint.ts` holding all three fills gave every adopting component all
|
|
8
|
+
* three tokens: `card.json` claimed `--cue-sunken` and `--cue-surface-2`, which
|
|
9
|
+
* `Card` does not paint. Measured on the first manifest regeneration of Slice 2;
|
|
10
|
+
* the spec's own risk register predicted it and named this split as the remedy.
|
|
11
|
+
*
|
|
12
|
+
* **Its stops fall back to `--cue-border-overlay`, not `--cue-border`**, and
|
|
13
|
+
* that is the one place the three fills differ. An overlay has always drawn its
|
|
14
|
+
* rim in `border-overlay`: a distinct token that some themes — venu — match to
|
|
15
|
+
* the surface deliberately so the rim vanishes. Falling back to `--cue-border`
|
|
16
|
+
* here would repaint every dialog, menu, popover and toast in a colour the
|
|
17
|
+
* theme did not choose for them. Caught by the manifest, which showed 22
|
|
18
|
+
* components losing `--cue-border-overlay` the moment this fill was adopted.
|
|
19
|
+
*
|
|
20
|
+
* The recipe itself, and why its off state is a flat gradient rather than
|
|
21
|
+
* `none`, is documented once in `./_paint`.
|
|
22
|
+
*
|
|
23
|
+
* @internal Not part of the public API.
|
|
24
|
+
*/
|
|
25
|
+
const STROKE_SURFACE_2 = "border-transparent border-(length:--cue-paint-stroke-width) bg-[linear-gradient(var(--cue-surface-2),var(--cue-surface-2)),linear-gradient(var(--cue-paint-stroke-angle),var(--cue-paint-stroke-from,var(--cue-border-overlay)),var(--cue-paint-stroke-to,var(--cue-border-overlay)))] bg-origin-border [background-clip:padding-box,border-box]";
|
|
26
|
+
//#endregion
|
|
27
|
+
export { STROKE_SURFACE_2 };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/system/_paint-texture.ts
|
|
2
|
+
/**
|
|
3
|
+
* A grain or pattern overlay, riding a pseudo-element.
|
|
4
|
+
*
|
|
5
|
+
* **Why `::before` and not the element's own background.** A texture sits *over*
|
|
6
|
+
* whatever the host already paints — a band's ground, a shell's fill — and a
|
|
7
|
+
* component's `background-image` is not free to take. The overlay is
|
|
8
|
+
* `pointer-events-none` and `inset-0`, so it covers the host exactly and
|
|
9
|
+
* intercepts nothing.
|
|
10
|
+
*
|
|
11
|
+
* **Its own module**, because `@repo/docgen` attributes a token by the file its
|
|
12
|
+
* class string lives in, including through a type-only import. One device per
|
|
13
|
+
* file; the two ways that bit are recorded in `_paint-elevation.ts`.
|
|
14
|
+
*
|
|
15
|
+
* **`isolate` and `before:-z-10` together, and neither works alone.** An
|
|
16
|
+
* absolutely-positioned `::before` paints ABOVE its host's in-flow content, so
|
|
17
|
+
* without them the texture covers the band's own text — measured, the white
|
|
18
|
+
* text's brightest pixel drops 255 to 204 under a 60% overlay. `-z-10` alone
|
|
19
|
+
* does not fix it: with no stacking context on the host the pseudo-element
|
|
20
|
+
* falls behind the band's own background and the texture becomes invisible
|
|
21
|
+
* entirely (measured: the ground pixel does not move). `isolate` gives the host
|
|
22
|
+
* a stacking context, and inside one a negative-z child paints above the
|
|
23
|
+
* background and below the content — which is exactly the layer a texture wants.
|
|
24
|
+
* Found in review; the first gate could not see it because its test band had no
|
|
25
|
+
* content in it.
|
|
26
|
+
*
|
|
27
|
+
* **The mask carries its `-webkit-` prefix**, which is the library's
|
|
28
|
+
* convention rather than a guess: `elements/clamp.tsx:223` and
|
|
29
|
+
* `chrome/_edge-scroller.tsx:73` are the only other mask users here and both
|
|
30
|
+
* prefix it. Measured for completeness — Playwright's WebKit honours the
|
|
31
|
+
* unprefixed property, identically to Chromium — so this is for the Safari
|
|
32
|
+
* versions that engine is not, and it matches what the two existing sites
|
|
33
|
+
* already decided. Found in review.
|
|
34
|
+
*
|
|
35
|
+
* **Nothing else in the library may take this pseudo-element on the same
|
|
36
|
+
* element.** §6.5 note 2 is about that, and it is why the host was checked
|
|
37
|
+
* before adopting: neither `Band` nor `AppShell` uses `::before` today.
|
|
38
|
+
*
|
|
39
|
+
* **No ink here, so no fallback rule to keep.** Every name this spends is a
|
|
40
|
+
* declared pack name with a `:root` default — `texture` is `none`,
|
|
41
|
+
* `texture-size` `auto`, `texture-opacity` `1`, `texture-blend` `normal`, and
|
|
42
|
+
* `fade` (Slice 7's) `none`. Measured: at those defaults the overlay renders
|
|
43
|
+
* identically to the same host with no pseudo-element at all.
|
|
44
|
+
*
|
|
45
|
+
* **The token layer ships no binary.** `--cue-paint-texture` takes a `data:`
|
|
46
|
+
* URI a pack file holds inline, or an absolute `https://` URL a consumer's own
|
|
47
|
+
* CDN serves — `PAINT_VALUES` enforces exactly those two and says why.
|
|
48
|
+
*
|
|
49
|
+
* @internal Not part of the public API.
|
|
50
|
+
*/
|
|
51
|
+
const TEXTURE_CLASSES = "relative isolate before:pointer-events-none before:absolute before:inset-0 before:-z-10 before:content-[''] before:bg-[image:var(--cue-paint-texture)] before:bg-[length:var(--cue-paint-texture-size)] before:opacity-(--cue-paint-texture-opacity) before:[mix-blend-mode:var(--cue-paint-texture-blend)] before:[mask-image:var(--cue-paint-fade)] before:[-webkit-mask-image:var(--cue-paint-fade)]";
|
|
52
|
+
//#endregion
|
|
53
|
+
export { TEXTURE_CLASSES };
|
|
@@ -252,48 +252,59 @@ interface ThemeProviderProps {
|
|
|
252
252
|
/** Restore and write root preferences in localStorage. Defaults to `true`. */
|
|
253
253
|
persistPreferences?: boolean;
|
|
254
254
|
/**
|
|
255
|
-
* The Content-Security-Policy nonce
|
|
256
|
-
*
|
|
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>`.
|
|
257
262
|
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
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`.
|
|
264
269
|
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* `
|
|
272
|
-
*
|
|
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.
|
|
273
278
|
*
|
|
274
279
|
* `prepaintScript()` returns a *string* the application renders in a
|
|
275
|
-
* `<script>` of its own
|
|
276
|
-
* nonce, and between it and this prop a strict policy needs nothing else
|
|
277
|
-
* from here.
|
|
280
|
+
* `<script>` of its own, so put the same nonce on that element yourself.
|
|
278
281
|
*
|
|
279
|
-
* **
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* `
|
|
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.
|
|
290
297
|
*
|
|
291
|
-
* **A nonce cannot rescue a style ATTRIBUTE
|
|
292
|
-
* one
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* a
|
|
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.
|
|
297
308
|
*/
|
|
298
309
|
nonce?: string;
|
|
299
310
|
/** Stamp the single child element instead of rendering a wrapper `<div>`. */
|
|
@@ -556,18 +556,25 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
|
|
|
556
556
|
children: overridesStyle
|
|
557
557
|
});
|
|
558
558
|
/**
|
|
559
|
-
* Base UI's own style elements, which this provider's nonce also
|
|
559
|
+
* Base UI's own style and script elements, which this provider's nonce also
|
|
560
|
+
* has to reach.
|
|
560
561
|
*
|
|
561
562
|
* `@base-ui/react` renders one style element — a hoisted
|
|
562
563
|
* `<style precedence>` carrying `.base-ui-disable-scrollbar` — from
|
|
563
564
|
* `utils/styles.mjs`. `ScrollAreaRoot` and `SelectPopup` pass it a nonce they
|
|
564
565
|
* read from Base UI's own `CSPContext`, and nothing fills that context unless
|
|
565
566
|
* a `CSPProvider` is rendered above them. Without one it ships bare and a
|
|
566
|
-
* `style-src-elem` policy refuses it
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
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.
|
|
571
578
|
*
|
|
572
579
|
* Rendered **only when a nonce was given**, and that is not tidiness. A
|
|
573
580
|
* consumer that wraps its own application in `CSPProvider` is the case this
|
|
@@ -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",
|