@caqophony/ui 0.3.0 → 0.4.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.
@@ -0,0 +1,125 @@
1
+ import { ReactElement } from 'react';
2
+ import { Tone } from './material-tones.mjs';
3
+
4
+ /**
5
+ * #5962 (epic #5944 step 4) — the art slot's one renderer. A product's art is
6
+ * data, a closed tree a generated app holds as JSON, and this is the only code
7
+ * that turns it into SVG. So there is no art source to police: a script, a
8
+ * handler, an external reference, `foreignObject` or a computed element has no
9
+ * way to be written in the format, and this file has no case for it.
10
+ *
11
+ * Each attribute is written out by name from the node's own fields, so a key the
12
+ * format does not have reaches nothing. An element or a paint outside the format
13
+ * throws here, even if the tree skipped its check: the validator, which is not
14
+ * published, gives the exact errors at build time.
15
+ *
16
+ * Published alone as `@caqophony/ui/material-art`, built with no client directive
17
+ * (`server-entries.json`), so a server component can render art. It imports only
18
+ * the tone tables, and not `cn`: a client chunk here would carry the directive.
19
+ *
20
+ * Held from the authors until step 5, with the rest of `material`.
21
+ *
22
+ * Authored by Caqophony
23
+ */
24
+
25
+ /** A tone, or no paint, or the colour of the surrounding text (a mark in a header). */
26
+ type ArtPaint = Tone | 'none' | 'currentColor';
27
+ type ArtTransform = {
28
+ op: 'translate';
29
+ x: number;
30
+ y: number;
31
+ } | {
32
+ op: 'rotate';
33
+ deg: number;
34
+ cx?: number;
35
+ cy?: number;
36
+ } | {
37
+ op: 'scale';
38
+ by: number;
39
+ };
40
+ /** What every element may say about how it is drawn. */
41
+ interface ArtDrawing {
42
+ stroke?: ArtPaint;
43
+ strokeWidth?: number;
44
+ strokeDasharray?: readonly number[];
45
+ strokeLinecap?: 'butt' | 'round' | 'square';
46
+ strokeLinejoin?: 'miter' | 'round' | 'bevel';
47
+ opacity?: number;
48
+ transform?: readonly ArtTransform[];
49
+ }
50
+ /** A shape with an area. A `line` has none, so it takes no fill. */
51
+ interface ArtFilled extends ArtDrawing {
52
+ fill?: ArtPaint;
53
+ }
54
+ interface ArtGroup extends ArtFilled {
55
+ el: 'g';
56
+ children: readonly ArtNode[];
57
+ }
58
+ interface ArtPath extends ArtFilled {
59
+ el: 'path';
60
+ d: string;
61
+ }
62
+ interface ArtRect extends ArtFilled {
63
+ el: 'rect';
64
+ x?: number;
65
+ y?: number;
66
+ width: number;
67
+ height: number;
68
+ rx?: number;
69
+ ry?: number;
70
+ }
71
+ interface ArtCircle extends ArtFilled {
72
+ el: 'circle';
73
+ cx: number;
74
+ cy: number;
75
+ r: number;
76
+ }
77
+ interface ArtEllipse extends ArtFilled {
78
+ el: 'ellipse';
79
+ cx: number;
80
+ cy: number;
81
+ rx: number;
82
+ ry: number;
83
+ }
84
+ interface ArtLine extends ArtDrawing {
85
+ el: 'line';
86
+ x1: number;
87
+ y1: number;
88
+ x2: number;
89
+ y2: number;
90
+ }
91
+ interface ArtPoly extends ArtFilled {
92
+ el: 'polygon' | 'polyline';
93
+ points: ReadonlyArray<readonly [number, number]>;
94
+ }
95
+ interface ArtText extends ArtFilled {
96
+ el: 'text';
97
+ x: number;
98
+ y: number;
99
+ anchor?: 'start' | 'middle' | 'end';
100
+ fontSize: number;
101
+ fontWeight?: 400 | 500 | 600 | 700;
102
+ /** Words on the page, apart from the drawing: step 5 holds them to the Brief. */
103
+ copy: string;
104
+ }
105
+ type ArtNode = ArtGroup | ArtPath | ArtRect | ArtCircle | ArtEllipse | ArtLine | ArtPoly | ArtText;
106
+ /** One SVG: `0 0 width height`, covering its box. */
107
+ interface ArtFrame {
108
+ width: number;
109
+ height: number;
110
+ /** Which part stays in view when the box's shape differs. */
111
+ anchor: 'top' | 'center' | 'bottom' | 'right';
112
+ /** Show only on a phone or only from `md` up. */
113
+ only?: 'phone' | 'desktop';
114
+ nodes: readonly ArtNode[];
115
+ }
116
+ /** A piece of art: one frame, or a phone frame and a desktop frame. */
117
+ interface ArtTree {
118
+ frames: readonly ArtFrame[];
119
+ }
120
+ /** Draws a piece of art, for a `Figure`'s slot or a mark. */
121
+ declare function Art({ tree }: {
122
+ tree: ArtTree;
123
+ }): ReactElement;
124
+
125
+ export { Art, type ArtCircle, type ArtDrawing, type ArtEllipse, type ArtFilled, type ArtFrame, type ArtGroup, type ArtLine, type ArtNode, type ArtPaint, type ArtPath, type ArtPoly, type ArtRect, type ArtText, type ArtTransform, type ArtTree };
@@ -0,0 +1,204 @@
1
+ // src/material/tones.ts
2
+ var FILL = {
3
+ "night-0": "fill-night-0",
4
+ "night-1": "fill-night-1",
5
+ "night-2": "fill-night-2",
6
+ "sky-0": "fill-sky-0",
7
+ "sky-1": "fill-sky-1",
8
+ "sky-2": "fill-sky-2",
9
+ "sky-3": "fill-sky-3",
10
+ "sky-4": "fill-sky-4",
11
+ glow: "fill-glow",
12
+ "glow-soft": "fill-glow-soft",
13
+ "glow-pale": "fill-glow-pale",
14
+ canvas: "fill-canvas",
15
+ "mist-1": "fill-mist-1",
16
+ "mist-2": "fill-mist-2",
17
+ "mist-3": "fill-mist-3",
18
+ paper: "fill-paper",
19
+ ink: "fill-ink",
20
+ page: "fill-background"
21
+ };
22
+ var STROKE = {
23
+ "night-0": "stroke-night-0",
24
+ "night-1": "stroke-night-1",
25
+ "night-2": "stroke-night-2",
26
+ "sky-0": "stroke-sky-0",
27
+ "sky-1": "stroke-sky-1",
28
+ "sky-2": "stroke-sky-2",
29
+ "sky-3": "stroke-sky-3",
30
+ "sky-4": "stroke-sky-4",
31
+ glow: "stroke-glow",
32
+ "glow-soft": "stroke-glow-soft",
33
+ "glow-pale": "stroke-glow-pale",
34
+ canvas: "stroke-canvas",
35
+ "mist-1": "stroke-mist-1",
36
+ "mist-2": "stroke-mist-2",
37
+ "mist-3": "stroke-mist-3",
38
+ paper: "stroke-paper",
39
+ ink: "stroke-ink",
40
+ page: "stroke-background"
41
+ };
42
+
43
+ // src/material/art.tsx
44
+ import { Fragment, jsx } from "react/jsx-runtime";
45
+ var ANCHOR = {
46
+ top: "xMidYMin slice",
47
+ center: "xMidYMid slice",
48
+ bottom: "xMidYMax slice",
49
+ right: "xMaxYMid slice"
50
+ };
51
+ var SHOWN = {
52
+ phone: "size-full md:hidden",
53
+ desktop: "hidden size-full md:block"
54
+ };
55
+ function classOf(table, paint, attribute) {
56
+ if (!Object.prototype.hasOwnProperty.call(table, paint))
57
+ throw new Error(
58
+ `Art: \`${attribute}\` is ${JSON.stringify(paint)}, which is not a tone`
59
+ );
60
+ return table[paint];
61
+ }
62
+ function painted({ fill, stroke }) {
63
+ const direct = (paint) => paint === "none" || paint === "currentColor" ? paint : void 0;
64
+ const classes = [
65
+ fill === void 0 || direct(fill) ? "" : classOf(FILL, fill, "fill"),
66
+ stroke === void 0 || direct(stroke) ? "" : classOf(STROKE, stroke, "stroke")
67
+ ].filter(Boolean);
68
+ return {
69
+ fill: direct(fill),
70
+ stroke: direct(stroke),
71
+ className: classes.length > 0 ? classes.join(" ") : void 0
72
+ };
73
+ }
74
+ function transformOf(step) {
75
+ switch (step.op) {
76
+ case "translate":
77
+ return `translate(${step.x} ${step.y})`;
78
+ case "scale":
79
+ return `scale(${step.by})`;
80
+ case "rotate":
81
+ return step.cx === void 0 || step.cy === void 0 ? `rotate(${step.deg})` : `rotate(${step.deg} ${step.cx} ${step.cy})`;
82
+ }
83
+ }
84
+ function drawn(node) {
85
+ return {
86
+ ...painted(node),
87
+ strokeWidth: node.strokeWidth,
88
+ strokeDasharray: node.strokeDasharray?.join(" "),
89
+ strokeLinecap: node.strokeLinecap,
90
+ strokeLinejoin: node.strokeLinejoin,
91
+ opacity: node.opacity,
92
+ transform: node.transform?.map(transformOf).join(" ")
93
+ };
94
+ }
95
+ function render(node, key) {
96
+ switch (node.el) {
97
+ case "g":
98
+ return /* @__PURE__ */ jsx("g", { ...drawn(node), children: node.children.map(render) }, key);
99
+ case "path":
100
+ return /* @__PURE__ */ jsx("path", { d: node.d, ...drawn(node) }, key);
101
+ case "rect":
102
+ return /* @__PURE__ */ jsx(
103
+ "rect",
104
+ {
105
+ x: node.x,
106
+ y: node.y,
107
+ width: node.width,
108
+ height: node.height,
109
+ rx: node.rx,
110
+ ry: node.ry,
111
+ ...drawn(node)
112
+ },
113
+ key
114
+ );
115
+ case "circle":
116
+ return /* @__PURE__ */ jsx(
117
+ "circle",
118
+ {
119
+ cx: node.cx,
120
+ cy: node.cy,
121
+ r: node.r,
122
+ ...drawn(node)
123
+ },
124
+ key
125
+ );
126
+ case "ellipse":
127
+ return /* @__PURE__ */ jsx(
128
+ "ellipse",
129
+ {
130
+ cx: node.cx,
131
+ cy: node.cy,
132
+ rx: node.rx,
133
+ ry: node.ry,
134
+ ...drawn(node)
135
+ },
136
+ key
137
+ );
138
+ case "line":
139
+ return /* @__PURE__ */ jsx(
140
+ "line",
141
+ {
142
+ x1: node.x1,
143
+ y1: node.y1,
144
+ x2: node.x2,
145
+ y2: node.y2,
146
+ ...drawn(node)
147
+ },
148
+ key
149
+ );
150
+ case "polygon":
151
+ return /* @__PURE__ */ jsx(
152
+ "polygon",
153
+ {
154
+ points: node.points.map((p) => p.join(",")).join(" "),
155
+ ...drawn(node)
156
+ },
157
+ key
158
+ );
159
+ case "polyline":
160
+ return /* @__PURE__ */ jsx(
161
+ "polyline",
162
+ {
163
+ points: node.points.map((p) => p.join(",")).join(" "),
164
+ ...drawn(node)
165
+ },
166
+ key
167
+ );
168
+ case "text":
169
+ return /* @__PURE__ */ jsx(
170
+ "text",
171
+ {
172
+ x: node.x,
173
+ y: node.y,
174
+ textAnchor: node.anchor,
175
+ fontSize: node.fontSize,
176
+ fontWeight: node.fontWeight,
177
+ ...drawn(node),
178
+ children: node.copy
179
+ },
180
+ key
181
+ );
182
+ default:
183
+ throw new Error(
184
+ `Art: <${String(node.el)}> is not an art element`
185
+ // SAFE: reached only by a tree that skipped its check
186
+ );
187
+ }
188
+ }
189
+ function Art({ tree }) {
190
+ return /* @__PURE__ */ jsx(Fragment, { children: tree.frames.map((frame, i) => /* @__PURE__ */ jsx(
191
+ "svg",
192
+ {
193
+ viewBox: `0 0 ${frame.width} ${frame.height}`,
194
+ preserveAspectRatio: ANCHOR[frame.anchor],
195
+ "aria-hidden": "true",
196
+ className: frame.only ? SHOWN[frame.only] : "size-full",
197
+ children: frame.nodes.map(render)
198
+ },
199
+ i
200
+ )) });
201
+ }
202
+ export {
203
+ Art
204
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * #5956 — the closed tone vocabulary of the material layer. Each tone is a
3
+ * theme token, derived per project from its brand (`deriveMaterialRamp`), so a
4
+ * theme change reaches every band, figure and field. Every class is written
5
+ * out in full so an app's Tailwind scan sees it. `Tone` is held to the ramp's
6
+ * own step list by `material-primitives-5956.test.ts`.
7
+ *
8
+ * `paper` and `ink` hold in dark mode, as a brand step does: art printed on
9
+ * white stays on white. `page` is the page's own surface, in either scheme: the
10
+ * tone for a band that should follow it, such as the one behind a footer.
11
+ *
12
+ * Published alone as `@caqophony/ui/material-tones`, with no client directive
13
+ * (`server-entries.json`), so a server component's art can read `FILL` and
14
+ * `STROKE`. It must import nothing: a shared chunk would carry the directive.
15
+ *
16
+ * Authored by Caqophony
17
+ */
18
+ type Tone = 'night-0' | 'night-1' | 'night-2' | 'sky-0' | 'sky-1' | 'sky-2' | 'sky-3' | 'sky-4' | 'glow' | 'glow-soft' | 'glow-pale' | 'canvas' | 'mist-1' | 'mist-2' | 'mist-3' | 'paper' | 'ink' | 'page';
19
+ declare const FILL: Readonly<Record<Tone, string>>;
20
+ declare const STROKE: Readonly<Record<Tone, string>>;
21
+ declare const BG: Readonly<Record<Tone, string>>;
22
+
23
+ export { BG, FILL, STROKE, type Tone };
@@ -0,0 +1,66 @@
1
+ // src/material/tones.ts
2
+ var FILL = {
3
+ "night-0": "fill-night-0",
4
+ "night-1": "fill-night-1",
5
+ "night-2": "fill-night-2",
6
+ "sky-0": "fill-sky-0",
7
+ "sky-1": "fill-sky-1",
8
+ "sky-2": "fill-sky-2",
9
+ "sky-3": "fill-sky-3",
10
+ "sky-4": "fill-sky-4",
11
+ glow: "fill-glow",
12
+ "glow-soft": "fill-glow-soft",
13
+ "glow-pale": "fill-glow-pale",
14
+ canvas: "fill-canvas",
15
+ "mist-1": "fill-mist-1",
16
+ "mist-2": "fill-mist-2",
17
+ "mist-3": "fill-mist-3",
18
+ paper: "fill-paper",
19
+ ink: "fill-ink",
20
+ page: "fill-background"
21
+ };
22
+ var STROKE = {
23
+ "night-0": "stroke-night-0",
24
+ "night-1": "stroke-night-1",
25
+ "night-2": "stroke-night-2",
26
+ "sky-0": "stroke-sky-0",
27
+ "sky-1": "stroke-sky-1",
28
+ "sky-2": "stroke-sky-2",
29
+ "sky-3": "stroke-sky-3",
30
+ "sky-4": "stroke-sky-4",
31
+ glow: "stroke-glow",
32
+ "glow-soft": "stroke-glow-soft",
33
+ "glow-pale": "stroke-glow-pale",
34
+ canvas: "stroke-canvas",
35
+ "mist-1": "stroke-mist-1",
36
+ "mist-2": "stroke-mist-2",
37
+ "mist-3": "stroke-mist-3",
38
+ paper: "stroke-paper",
39
+ ink: "stroke-ink",
40
+ page: "stroke-background"
41
+ };
42
+ var BG = {
43
+ "night-0": "bg-night-0",
44
+ "night-1": "bg-night-1",
45
+ "night-2": "bg-night-2",
46
+ "sky-0": "bg-sky-0",
47
+ "sky-1": "bg-sky-1",
48
+ "sky-2": "bg-sky-2",
49
+ "sky-3": "bg-sky-3",
50
+ "sky-4": "bg-sky-4",
51
+ glow: "bg-glow",
52
+ "glow-soft": "bg-glow-soft",
53
+ "glow-pale": "bg-glow-pale",
54
+ canvas: "bg-canvas",
55
+ "mist-1": "bg-mist-1",
56
+ "mist-2": "bg-mist-2",
57
+ "mist-3": "bg-mist-3",
58
+ paper: "bg-paper",
59
+ ink: "bg-ink",
60
+ page: "bg-background"
61
+ };
62
+ export {
63
+ BG,
64
+ FILL,
65
+ STROKE
66
+ };
@@ -0,0 +1,279 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ReactElement } from 'react';
3
+ import { I as IconName } from './icon.d-DQqyySj2.mjs';
4
+ import 'lucide-react';
5
+
6
+ /**
7
+ * #5956 — the closed tone vocabulary of the material layer. Each tone is a
8
+ * theme token, derived per project from its brand (`deriveMaterialRamp`), so a
9
+ * theme change reaches every band, figure and field. Every class is written
10
+ * out in full so an app's Tailwind scan sees it. `Tone` is held to the ramp's
11
+ * own step list by `material-primitives-5956.test.ts`.
12
+ *
13
+ * `paper` and `ink` hold in dark mode, as a brand step does: art printed on
14
+ * white stays on white. `page` is the page's own surface, in either scheme: the
15
+ * tone for a band that should follow it, such as the one behind a footer.
16
+ *
17
+ * Published alone as `@caqophony/ui/material-tones`, with no client directive
18
+ * (`server-entries.json`), so a server component's art can read `FILL` and
19
+ * `STROKE`. It must import nothing: a shared chunk would carry the directive.
20
+ *
21
+ * Authored by Caqophony
22
+ */
23
+ type Tone = 'night-0' | 'night-1' | 'night-2' | 'sky-0' | 'sky-1' | 'sky-2' | 'sky-3' | 'sky-4' | 'glow' | 'glow-soft' | 'glow-pale' | 'canvas' | 'mist-1' | 'mist-2' | 'mist-3' | 'paper' | 'ink' | 'page';
24
+
25
+ interface BandEdgeSpec {
26
+ /** A layer of clouds behind this band's own. */
27
+ via?: Tone;
28
+ /** The same seed draws the same edge. */
29
+ seed: number;
30
+ }
31
+ interface BandProps {
32
+ /** The band's ground, a theme tone. */
33
+ tone: Tone;
34
+ /** Re-scope the library's tokens for the subtree: `night` turns every library component inside for a dark ground. */
35
+ surface?: 'day' | 'night';
36
+ /** Vertical rhythm. `none`: the content sets it. */
37
+ pad?: 'none' | 'tight' | 'section' | 'open';
38
+ /** The previous band's `Vignette placement="hang"` hangs over this one's top edge. */
39
+ under?: 'none' | 'overhang';
40
+ /** This band's clouds sit over the seam, so bands meet as layers, not a ruled line. They rise into the band above's bottom padding, up to 108px (58px on a phone). */
41
+ edge?: BandEdgeSpec;
42
+ /** Layered behind the content, clipped to the band, hidden from assistive tech. */
43
+ backdrop?: ReactNode;
44
+ /** Sit above the next band (its hanging `Vignette`). */
45
+ raised?: boolean;
46
+ id?: string;
47
+ children: ReactNode;
48
+ }
49
+ /** A full-bleed page section with a ground, a backdrop and a token surface. */
50
+ declare function Band({ tone, surface, pad, under, edge, backdrop, raised, id, children, }: BandProps): react_jsx_runtime.JSX.Element;
51
+
52
+ /** What a generated bitmap must be when it replaces this slot's stand-in. */
53
+ interface FigureSpec {
54
+ role: string;
55
+ aspect: '16:9' | '8:5' | '4:3' | '3:2' | '1:1' | '4:5' | 'full-bleed';
56
+ /** The theme tones the bitmap must stay inside. */
57
+ palette: readonly Tone[];
58
+ prompt: string;
59
+ }
60
+ interface FigureProps {
61
+ spec: FigureSpec;
62
+ /** Real alt text; empty only for decoration, which hides the content from assistive tech. */
63
+ alt: string;
64
+ /**
65
+ * The art slot: one element of the app's own art, which shows until the bitmap
66
+ * exists and must look finished. An element, not a component: this is a client
67
+ * entry, and a server component cannot pass a function across that boundary.
68
+ * The type pins the shape; `Art`, drawing checked data, pins the content.
69
+ */
70
+ children: ReactElement;
71
+ /** `fill`: stretch to the parent box (a backdrop). */
72
+ fit?: 'aspect' | 'fill';
73
+ }
74
+ /** An image slot that records the spec of the bitmap that will replace it. */
75
+ declare function Figure({ spec, alt, children, fit }: FigureProps): react_jsx_runtime.JSX.Element;
76
+
77
+ declare const GAP: {
78
+ readonly 1: "gap-1";
79
+ readonly 2: "gap-2";
80
+ readonly 3: "gap-3";
81
+ readonly 4: "gap-4";
82
+ readonly 6: "gap-6";
83
+ readonly 8: "gap-8";
84
+ readonly 10: "gap-10";
85
+ readonly 12: "gap-12";
86
+ readonly 16: "gap-16";
87
+ };
88
+ type Gap = keyof typeof GAP;
89
+ interface StackProps {
90
+ gap: Gap;
91
+ align?: 'stretch' | 'start' | 'center';
92
+ children: ReactNode;
93
+ }
94
+ /** A vertical run with one gap. */
95
+ declare function Stack({ gap, align, children }: StackProps): react_jsx_runtime.JSX.Element;
96
+ interface InlineProps {
97
+ gap: Gap;
98
+ justify?: 'start' | 'between' | 'center';
99
+ align?: 'center' | 'start';
100
+ /** Below `sm`, each child takes the full width (a phone's CTA row). */
101
+ fillOnPhone?: boolean;
102
+ children: ReactNode;
103
+ }
104
+ /** A wrapping horizontal run. */
105
+ declare function Inline({ gap, justify, align, fillOnPhone, children, }: InlineProps): react_jsx_runtime.JSX.Element;
106
+ interface ColumnsProps {
107
+ /** The desktop column count. */
108
+ count: 2 | 3 | 4;
109
+ gap: Gap;
110
+ /** On a phone: `stack` one column; `scroll` keep the columns in a side-scrolling row. */
111
+ phone: 'stack' | 'scroll';
112
+ /** A dashed route from each column to the next, level with a 48px marker. */
113
+ connect?: boolean;
114
+ children: ReactNode;
115
+ }
116
+ /** Equal columns that know what they do on a phone. */
117
+ declare function Columns({ count, gap, phone, connect, children, }: ColumnsProps): react_jsx_runtime.JSX.Element;
118
+ interface SplitProps {
119
+ /** How the width divides between the first and second child. */
120
+ ratio: 'even' | 'text-media';
121
+ /** Draw the second child first from `md` up. */
122
+ reverse?: boolean;
123
+ gap: Gap;
124
+ children: readonly [ReactNode, ReactNode];
125
+ }
126
+ /** Text beside media; stacks on a phone with the text first. */
127
+ declare function Split({ ratio, reverse, gap, children }: SplitProps): react_jsx_runtime.JSX.Element;
128
+ interface SpacerProps {
129
+ /** `phone-sky`: room for the backdrop's picture on a phone, nothing from `md` up. */
130
+ size: 'hero' | 'section' | 'phone-sky';
131
+ }
132
+ /** Empty rhythm between two things that are not in one `Stack`. */
133
+ declare function Spacer({ size }: SpacerProps): react_jsx_runtime.JSX.Element;
134
+ interface InsetProps {
135
+ pad: 3 | 4 | 6;
136
+ children: ReactNode;
137
+ }
138
+ /** Padding, for a library `Card` that has none without its header parts. */
139
+ declare function Inset({ pad, children }: InsetProps): react_jsx_runtime.JSX.Element;
140
+
141
+ interface SkyFieldProps {
142
+ width: number;
143
+ height: number;
144
+ /** Which part stays in view when the box's shape differs. */
145
+ anchor: 'top' | 'center' | 'bottom' | 'right';
146
+ /** Show only on a phone or only from `md` up. */
147
+ only?: 'phone' | 'desktop';
148
+ ground: Tone;
149
+ children: ReactNode;
150
+ }
151
+ /** A flat illustration field: an SVG that covers its box. */
152
+ declare function SkyField({ width, height, anchor, only, ground, children, }: SkyFieldProps): react_jsx_runtime.JSX.Element;
153
+ interface HaloProps {
154
+ cx: number;
155
+ cy: number;
156
+ /** Outermost first: each ring steps down the ramp, with no gradient. */
157
+ rings: ReadonlyArray<{
158
+ r: number;
159
+ tone: Tone;
160
+ }>;
161
+ }
162
+ /** Concentric stepped rings: a sun, or any glow, as flat print layers. */
163
+ declare function Halo({ cx, cy, rings }: HaloProps): react_jsx_runtime.JSX.Element;
164
+ interface CloudBankProps {
165
+ /** Field width and height. */
166
+ width: number;
167
+ height: number;
168
+ /** The bank's top line. */
169
+ y: number;
170
+ /** Bump radius range: `min` at least 0.1, `max` no less than `min`, at most 2000 bumps. */
171
+ min: number;
172
+ max: number;
173
+ /** How far the top line climbs from the left edge to the right. */
174
+ climb?: number;
175
+ /** Bumps wander around `y` instead of drifting from it: a long bank stays on its line. */
176
+ level?: boolean;
177
+ seed: number;
178
+ tone: Tone;
179
+ }
180
+ /** A scalloped cloud bank running edge to edge and filled to the field's bottom. */
181
+ declare function CloudBank({ width, height, y, min, max, climb, level, seed, tone, }: CloudBankProps): react_jsx_runtime.JSX.Element;
182
+ interface RidgeProps {
183
+ width: number;
184
+ height: number;
185
+ y: number;
186
+ /** How high the ridge rolls above `y`. */
187
+ rise: number;
188
+ /** The number of swells across the field. */
189
+ swells: number;
190
+ seed: number;
191
+ tone: Tone;
192
+ }
193
+ /** A smooth ridge line, filled to the field's bottom. */
194
+ declare function Ridge({ width, height, y, rise, swells, seed, tone, }: RidgeProps): react_jsx_runtime.JSX.Element;
195
+ interface StarsProps {
196
+ width: number;
197
+ /** The band they scatter in, from the top. */
198
+ height: number;
199
+ count: number;
200
+ seed: number;
201
+ tone: Tone;
202
+ }
203
+ /** A scatter of small dots. */
204
+ declare function Stars({ width, height, count, seed, tone }: StarsProps): react_jsx_runtime.JSX.Element;
205
+ interface RoutePoint {
206
+ x: number;
207
+ y: number;
208
+ label?: string;
209
+ /** Which side of the point its label sits. */
210
+ side?: 'above' | 'below' | 'left' | 'right';
211
+ /** `passed`: filled; `here`: ringed; `ahead`: hollow. */
212
+ state: 'passed' | 'here' | 'ahead';
213
+ }
214
+ interface RouteLineProps {
215
+ /** The waypoints, in order: at least one. */
216
+ points: readonly [RoutePoint, ...RoutePoint[]];
217
+ tone: Tone;
218
+ /** The halo behind a `here` point and the fill of `ahead` points. */
219
+ markTone: Tone;
220
+ /** The label size, in field units. */
221
+ labelSize: number;
222
+ }
223
+ /** A dashed route through waypoints, each marked by its state. */
224
+ declare function RouteLine({ points, tone, markTone, labelSize, }: RouteLineProps): react_jsx_runtime.JSX.Element;
225
+
226
+ interface DisplayProps {
227
+ /** The scale step; `poster` is the page's one largest moment. */
228
+ level: 'poster' | 'headline' | 'title';
229
+ /** The heading element (the document outline, separate from the size). */
230
+ as: 'h1' | 'h2' | 'h3';
231
+ align?: 'start' | 'center';
232
+ /** The line-length cap, in `ch` steps of the scale. */
233
+ measure?: 'narrow' | 'wide' | 'none';
234
+ children: ReactNode;
235
+ }
236
+ /** Display type: the theme's heading face on the display scale. */
237
+ declare function Display({ level, as: Tag, align, measure, children, }: DisplayProps): react_jsx_runtime.JSX.Element;
238
+ interface TextProps {
239
+ size?: 'lede' | 'body' | 'small' | 'micro';
240
+ tone?: 'default' | 'muted' | 'accent';
241
+ weight?: 'normal' | 'medium' | 'bold';
242
+ align?: 'start' | 'center';
243
+ /** Cap the line length for reading. */
244
+ measure?: boolean;
245
+ as?: 'p' | 'span' | 'div';
246
+ children: ReactNode;
247
+ }
248
+ /** Running text on the theme's body face. */
249
+ declare function Text({ size, tone, weight, align, measure, as: Tag, children, }: TextProps): react_jsx_runtime.JSX.Element;
250
+
251
+ interface VignetteProps {
252
+ /** The screen's name in the title bar, as the product calls it. */
253
+ title: string;
254
+ /** The title bar's icon. */
255
+ icon: IconName;
256
+ /** Marks the content as sample; required, a product view never makes a claim. */
257
+ sampleLabel: string;
258
+ /** The token surface inside the frame: the page's own tokens, or the night band's. */
259
+ surface?: 'day' | 'night';
260
+ /** `hang`: pull the frame over the band below it. */
261
+ placement?: 'inline' | 'hang';
262
+ /** `bottom`: cut the view off at a fixed height, fading out, as a crop. */
263
+ crop?: 'none' | 'bottom';
264
+ /** Real library components at their real size. */
265
+ children: ReactNode;
266
+ }
267
+ /** A raised window holding real library components, marked as sample. */
268
+ declare function Vignette({ title, icon, sampleLabel, surface, placement, crop, children, }: VignetteProps): react_jsx_runtime.JSX.Element;
269
+
270
+ interface WordmarkProps {
271
+ name: string;
272
+ /** The product's mark, drawn in `currentColor` in a 24px box. */
273
+ mark: ReactNode;
274
+ href: string;
275
+ }
276
+ /** A product name with its mark. */
277
+ declare function Wordmark({ name, mark, href }: WordmarkProps): react_jsx_runtime.JSX.Element;
278
+
279
+ export { Band, type BandEdgeSpec, type BandProps, CloudBank, type CloudBankProps, Columns, type ColumnsProps, Display, type DisplayProps, Figure, type FigureProps, type FigureSpec, type Gap, Halo, type HaloProps, Inline, type InlineProps, Inset, type InsetProps, Ridge, type RidgeProps, RouteLine, type RouteLineProps, type RoutePoint, SkyField, type SkyFieldProps, Spacer, type SpacerProps, Split, type SplitProps, Stack, type StackProps, Stars, type StarsProps, Text, type TextProps, type Tone, Vignette, type VignetteProps, Wordmark, type WordmarkProps };