@designtools/docs 0.0.0-stage → 0.2.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 (173) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +155 -2
  4. package/dist/a11y-panel.d.ts +58 -0
  5. package/dist/a11y-panel.js +75 -0
  6. package/dist/adherence-summary.d.ts +9 -0
  7. package/dist/adherence-summary.js +27 -0
  8. package/dist/agent-view.d.ts +19 -0
  9. package/dist/agent-view.js +23 -0
  10. package/dist/anatomy.d.ts +12 -0
  11. package/dist/anatomy.js +39 -0
  12. package/dist/ask-claude.d.ts +14 -0
  13. package/dist/ask-claude.js +40 -0
  14. package/dist/cli.js +322 -0
  15. package/dist/code-view.d.ts +17 -0
  16. package/dist/code-view.js +42 -0
  17. package/dist/examples.d.ts +25 -0
  18. package/dist/examples.js +48 -0
  19. package/dist/glossary.d.ts +5 -0
  20. package/dist/glossary.js +21 -0
  21. package/dist/imagery.d.ts +6 -0
  22. package/dist/imagery.js +17 -0
  23. package/dist/index.d.ts +35 -0
  24. package/dist/index.js +34 -0
  25. package/dist/lib/adherence-types.d.ts +168 -0
  26. package/dist/lib/adherence-types.js +13 -0
  27. package/dist/lib/boundary.d.ts +16 -0
  28. package/dist/lib/boundary.js +15 -0
  29. package/dist/lib/contrast.d.ts +8 -0
  30. package/dist/lib/contrast.js +42 -0
  31. package/dist/lib/cx.d.ts +24 -0
  32. package/dist/lib/cx.js +26 -0
  33. package/dist/lib/jsx.d.ts +6 -0
  34. package/dist/lib/jsx.js +29 -0
  35. package/dist/lib/live.d.ts +10 -0
  36. package/dist/lib/live.js +10 -0
  37. package/dist/lib/lookup.d.ts +35 -0
  38. package/dist/lib/lookup.js +42 -0
  39. package/dist/lib/manifest-types.d.ts +253 -0
  40. package/dist/lib/manifest-types.js +14 -0
  41. package/dist/lib/manifest.d.ts +98 -0
  42. package/dist/lib/manifest.js +173 -0
  43. package/dist/lib/markdown.d.ts +50 -0
  44. package/dist/lib/markdown.js +286 -0
  45. package/dist/lib/measure.d.ts +12 -0
  46. package/dist/lib/measure.js +62 -0
  47. package/dist/lib/pseudo.d.ts +11 -0
  48. package/dist/lib/pseudo.js +71 -0
  49. package/dist/lib/registry.d.ts +21 -0
  50. package/dist/lib/registry.js +11 -0
  51. package/dist/lib/search.d.ts +44 -0
  52. package/dist/lib/search.js +62 -0
  53. package/dist/lib/standards.d.ts +17 -0
  54. package/dist/lib/standards.js +81 -0
  55. package/dist/lib/status.d.ts +6 -0
  56. package/dist/lib/status.js +17 -0
  57. package/dist/lib/terms.d.ts +15 -0
  58. package/dist/lib/terms.js +20 -0
  59. package/dist/lib/text.d.ts +8 -0
  60. package/dist/lib/text.js +9 -0
  61. package/dist/lib/ui.d.ts +100 -0
  62. package/dist/lib/ui.js +89 -0
  63. package/dist/lib/vision.d.ts +18 -0
  64. package/dist/lib/vision.js +27 -0
  65. package/dist/logo-usage.d.ts +14 -0
  66. package/dist/logo-usage.js +45 -0
  67. package/dist/next/config.d.ts +105 -0
  68. package/dist/next/config.js +1 -0
  69. package/dist/next/index.d.ts +65 -0
  70. package/dist/next/index.js +66 -0
  71. package/dist/next/markdown.d.ts +20 -0
  72. package/dist/next/markdown.js +95 -0
  73. package/dist/next/pages.d.ts +6 -0
  74. package/dist/next/pages.js +188 -0
  75. package/dist/next/prose.d.ts +9 -0
  76. package/dist/next/prose.js +39 -0
  77. package/dist/next/proxy.d.ts +19 -0
  78. package/dist/next/proxy.js +56 -0
  79. package/dist/next/site.d.ts +53 -0
  80. package/dist/next/site.js +136 -0
  81. package/dist/page-actions.d.ts +9 -0
  82. package/dist/page-actions.js +32 -0
  83. package/dist/pattern.d.ts +11 -0
  84. package/dist/pattern.js +22 -0
  85. package/dist/playground.d.ts +62 -0
  86. package/dist/playground.js +111 -0
  87. package/dist/preview-frame.d.ts +31 -0
  88. package/dist/preview-frame.js +63 -0
  89. package/dist/props-table.d.ts +10 -0
  90. package/dist/props-table.js +45 -0
  91. package/dist/rule.d.ts +16 -0
  92. package/dist/rule.js +37 -0
  93. package/dist/scale.d.ts +9 -0
  94. package/dist/scale.js +58 -0
  95. package/dist/search.d.ts +16 -0
  96. package/dist/search.js +46 -0
  97. package/dist/shell.d.ts +92 -0
  98. package/dist/shell.js +201 -0
  99. package/dist/standards.d.ts +13 -0
  100. package/dist/standards.js +19 -0
  101. package/dist/styles.css +3708 -0
  102. package/dist/swatches.d.ts +28 -0
  103. package/dist/swatches.js +100 -0
  104. package/dist/theme-switch.d.ts +20 -0
  105. package/dist/theme-switch.js +68 -0
  106. package/dist/type-ramp.d.ts +10 -0
  107. package/dist/type-ramp.js +31 -0
  108. package/dist/usage.d.ts +13 -0
  109. package/dist/usage.js +55 -0
  110. package/dist/variant-matrix.d.ts +15 -0
  111. package/dist/variant-matrix.js +58 -0
  112. package/dist/voice-terms.d.ts +5 -0
  113. package/dist/voice-terms.js +14 -0
  114. package/dist/workbench.d.ts +33 -0
  115. package/dist/workbench.js +274 -0
  116. package/package.json +107 -3
  117. package/src/a11y-panel.tsx +297 -0
  118. package/src/adherence-summary.tsx +134 -0
  119. package/src/agent-view.tsx +54 -0
  120. package/src/anatomy.tsx +119 -0
  121. package/src/ask-claude.tsx +90 -0
  122. package/src/code-view.tsx +112 -0
  123. package/src/css.d.ts +1 -0
  124. package/src/examples.tsx +141 -0
  125. package/src/glossary.tsx +70 -0
  126. package/src/imagery.tsx +64 -0
  127. package/src/index.ts +35 -0
  128. package/src/lib/adherence-types.ts +181 -0
  129. package/src/lib/boundary.tsx +21 -0
  130. package/src/lib/contrast.ts +44 -0
  131. package/src/lib/cx.ts +30 -0
  132. package/src/lib/jsx.ts +29 -0
  133. package/src/lib/live.tsx +15 -0
  134. package/src/lib/lookup.tsx +50 -0
  135. package/src/lib/manifest-types.ts +284 -0
  136. package/src/lib/manifest.ts +228 -0
  137. package/src/lib/markdown.ts +288 -0
  138. package/src/lib/measure.tsx +101 -0
  139. package/src/lib/pseudo.ts +74 -0
  140. package/src/lib/registry.tsx +29 -0
  141. package/src/lib/search.ts +99 -0
  142. package/src/lib/standards.ts +82 -0
  143. package/src/lib/status.tsx +32 -0
  144. package/src/lib/terms.tsx +53 -0
  145. package/src/lib/text.tsx +27 -0
  146. package/src/lib/ui.tsx +291 -0
  147. package/src/lib/vision.tsx +44 -0
  148. package/src/logo-usage.tsx +140 -0
  149. package/src/next/config.ts +101 -0
  150. package/src/next/index.tsx +103 -0
  151. package/src/next/markdown.ts +119 -0
  152. package/src/next/pages.tsx +483 -0
  153. package/src/next/prose.tsx +97 -0
  154. package/src/next/proxy.ts +55 -0
  155. package/src/next/site.ts +173 -0
  156. package/src/page-actions.tsx +92 -0
  157. package/src/pattern.tsx +72 -0
  158. package/src/playground.tsx +357 -0
  159. package/src/preview-frame.tsx +131 -0
  160. package/src/props-table.tsx +154 -0
  161. package/src/rule.tsx +165 -0
  162. package/src/scale.tsx +175 -0
  163. package/src/search.tsx +155 -0
  164. package/src/shell.tsx +569 -0
  165. package/src/standards.tsx +58 -0
  166. package/src/styles.css +157 -0
  167. package/src/swatches.tsx +298 -0
  168. package/src/theme-switch.tsx +90 -0
  169. package/src/type-ramp.tsx +150 -0
  170. package/src/usage.tsx +148 -0
  171. package/src/variant-matrix.tsx +178 -0
  172. package/src/voice-terms.tsx +37 -0
  173. package/src/workbench.tsx +587 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The baselines a project records (`.mxa/stack.json` `baselines`), as a person
3
+ * reads them: titled sections, labelled rows, notes as sentences, and nothing
4
+ * shown for a value nobody has set. One shape, so the page and its markdown agree.
5
+ */
6
+ const TITLES = {
7
+ a11y: "Accessibility",
8
+ performance: "Performance budgets",
9
+ support: "Support",
10
+ seo: "Search and discovery",
11
+ licences: "Licences allowed",
12
+ textSize: "Text size",
13
+ touchTargets: "Touch targets",
14
+ };
15
+ const LABELS = {
16
+ browsers: "Browsers",
17
+ devices: "Devices",
18
+ viewports: "Viewports",
19
+ LCP: "Largest contentful paint",
20
+ CLS: "Cumulative layout shift",
21
+ TBT: "Total blocking time",
22
+ INP: "Interaction to next paint",
23
+ lighthouse: "Lighthouse score",
24
+ aiCrawlable: "Readable by AI crawlers",
25
+ };
26
+ const UNITS = { viewports: "px" };
27
+ /** `textSize` to "Text size", `aiCrawlable` to "Ai crawlable": a fallback, never as good as a title. */
28
+ export function humanise(key) {
29
+ const words = key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").toLowerCase();
30
+ return words.charAt(0).toUpperCase() + words.slice(1);
31
+ }
32
+ function shown(key, value) {
33
+ if (value === null || value === undefined || value === "")
34
+ return undefined;
35
+ if (typeof value === "boolean")
36
+ return value ? "yes" : "no";
37
+ if (Array.isArray(value))
38
+ return value.length ? value.join(", ") + (UNITS[key] ? ` ${UNITS[key]}` : "") : "not agreed yet";
39
+ if (typeof value === "object")
40
+ return undefined;
41
+ return String(value);
42
+ }
43
+ export function standardsSections(baselines) {
44
+ const keys = Object.keys(baselines).filter((k) => !k.startsWith("$"));
45
+ // `a11yNotes` is the note on `a11y`, not a section of its own
46
+ const noteOf = (k) => (/Notes?$/.test(k) && keys.includes(k.replace(/Notes?$/, "")) ? k.replace(/Notes?$/, "") : undefined);
47
+ const out = [];
48
+ for (const key of keys) {
49
+ if (noteOf(key))
50
+ continue;
51
+ const value = baselines[key];
52
+ const section = { key, title: TITLES[key] ?? humanise(key), rows: [], notes: [] };
53
+ if (value && typeof value === "object" && !Array.isArray(value)) {
54
+ for (const [k, v] of Object.entries(value)) {
55
+ if (k.startsWith("$"))
56
+ continue;
57
+ if (/^notes?$/i.test(k)) {
58
+ if (typeof v === "string" && v)
59
+ section.notes.push(v);
60
+ continue;
61
+ }
62
+ const text = shown(k, v);
63
+ if (text !== undefined)
64
+ section.rows.push({ label: LABELS[k] ?? humanise(k), value: text });
65
+ }
66
+ }
67
+ else {
68
+ const text = shown(key, value);
69
+ if (text !== undefined)
70
+ section.rows.push({ label: "", value: text });
71
+ }
72
+ for (const k of keys) {
73
+ const v = baselines[k];
74
+ if (noteOf(k) === key && typeof v === "string" && v)
75
+ section.notes.push(v);
76
+ }
77
+ if (section.rows.length || section.notes.length)
78
+ out.push(section);
79
+ }
80
+ return out;
81
+ }
@@ -0,0 +1,6 @@
1
+ export type Status = "stable" | "emerging" | "deprecated" | "confirmed" | "assumption" | "measured" | "draft" | "published";
2
+ /** A status, everywhere one is shown: components, patterns, rules and editorial pages. Unset says so. */
3
+ export declare function StatusBadge({ status, className }: {
4
+ status?: Status;
5
+ className?: string;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cx } from "./cx.js";
3
+ const LOOK = {
4
+ stable: "bg-success-subdued text-success-subdued-foreground",
5
+ confirmed: "bg-success-subdued text-success-subdued-foreground",
6
+ published: "bg-success-subdued text-success-subdued-foreground",
7
+ emerging: "bg-warning-subdued text-warning-subdued-foreground",
8
+ assumption: "bg-warning-subdued text-warning-subdued-foreground",
9
+ // generated from the tokens: a fact, not a decision, so neither settled nor pending
10
+ measured: "bg-muted text-muted-foreground",
11
+ draft: "bg-warning-subdued text-warning-subdued-foreground",
12
+ deprecated: "bg-destructive-subdued text-destructive-subdued-foreground",
13
+ };
14
+ /** A status, everywhere one is shown: components, patterns, rules and editorial pages. Unset says so. */
15
+ export function StatusBadge({ status, className }) {
16
+ return (_jsx("span", { "data-slot": "status-badge", "data-status": status ?? "unset", className: cx("inline-flex h-6 items-center rounded-full px-2.5 text-xs font-medium", status ? LOOK[status] : "border border-dashed border-border text-muted-foreground", className), children: status ?? "status not set" }));
17
+ }
@@ -0,0 +1,15 @@
1
+ import type { TermEntry } from "./manifest-types.js";
2
+ /** The wrong forms of a term: quiet chips, each with a cross, so "not this" reads without shouting. */
3
+ export declare function WrongForms({ wrong }: {
4
+ wrong?: string[];
5
+ }): import("react").JSX.Element;
6
+ /**
7
+ * One term on one row: the word to use, the words not to, and why. Three columns on a wide screen, under
8
+ * the labels `TermHead` draws; stacked on a phone.
9
+ */
10
+ export declare function TermRow({ term, kind }: {
11
+ term: TermEntry;
12
+ kind?: boolean;
13
+ }): import("react").JSX.Element;
14
+ /** The column labels over a list of `TermRow`s, on a wide screen. */
15
+ export declare function TermHead(): import("react").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { X } from "lucide-react";
3
+ import { inline } from "./text.js";
4
+ /** The wrong forms of a term: quiet chips, each with a cross, so "not this" reads without shouting. */
5
+ export function WrongForms({ wrong }) {
6
+ if (!wrong?.length)
7
+ return _jsx("span", { className: "text-sm text-muted-foreground", children: "None" });
8
+ return (_jsxs("span", { className: "flex flex-wrap gap-1.5", children: [_jsx("span", { className: "sr-only", children: "Not " }), wrong.map((w) => (_jsxs("span", { "data-slot": "term-wrong", className: "inline-flex min-h-7 items-center gap-1 rounded-md bg-muted px-2 text-sm text-muted-foreground", children: [_jsx(X, { "aria-hidden": true, className: "size-3 shrink-0" }), _jsx("span", { className: "line-through decoration-current/40", children: w })] }, w)))] }));
9
+ }
10
+ /**
11
+ * One term on one row: the word to use, the words not to, and why. Three columns on a wide screen, under
12
+ * the labels `TermHead` draws; stacked on a phone.
13
+ */
14
+ export function TermRow({ term, kind }) {
15
+ return (_jsxs("div", { "data-slot": "term", className: "grid gap-x-8 gap-y-2 border-t border-border py-5 md:grid-cols-[minmax(10rem,14rem)_minmax(0,1fr)_minmax(0,1.3fr)] md:items-baseline", children: [_jsxs("dt", { className: "flex items-baseline gap-2", children: [_jsx("span", { className: "text-xl leading-snug tracking-tight", children: term.name }), kind && _jsx("span", { className: "font-mono text-xs text-muted-foreground", children: term.kind }), _jsx("span", { className: "sr-only", children: ", say this" })] }), _jsx("dd", { children: _jsx(WrongForms, { wrong: term.wrong }) }), _jsxs("dd", { className: "text-sm leading-relaxed text-muted-foreground", children: [term.note ? inline(term.note) : term.kind !== "product" ? `The ${term.kind}'s name in the code.` : null, term.ref && _jsx("code", { className: "ml-1 font-mono text-xs", children: term.ref })] })] }));
16
+ }
17
+ /** The column labels over a list of `TermRow`s, on a wide screen. */
18
+ export function TermHead() {
19
+ return (_jsxs("div", { "aria-hidden": true, className: "hidden gap-x-8 pb-3 text-xs font-medium text-muted-foreground md:grid md:grid-cols-[minmax(10rem,14rem)_minmax(0,1fr)_minmax(0,1.3fr)]", children: [_jsx("span", { children: "Say" }), _jsx("span", { children: "Not" }), _jsx("span", { children: "Why" })] }));
20
+ }
@@ -0,0 +1,8 @@
1
+ import type { ReactNode } from "react";
2
+ /** JSDoc prose: paragraphs split on blank lines, `code` spans set as code. Nothing else is interpreted. */
3
+ export declare function Prose({ text, className }: {
4
+ text: string;
5
+ className?: string;
6
+ }): import("react").JSX.Element;
7
+ /** One line of prose with its `code` spans. */
8
+ export declare function inline(text: string): ReactNode[];
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /** JSDoc prose: paragraphs split on blank lines, `code` spans set as code. Nothing else is interpreted. */
3
+ export function Prose({ text, className }) {
4
+ return (_jsx(_Fragment, { children: text.split(/\n{2,}/).map((p, i) => (_jsx("p", { className: className, children: inline(p) }, i))) }));
5
+ }
6
+ /** One line of prose with its `code` spans. */
7
+ export function inline(text) {
8
+ return text.split(/(`[^`]+`)/).map((part, i) => /^`[^`]+`$/.test(part) ? (_jsx("code", { className: "rounded-sm bg-muted px-1 font-mono text-[0.9em]", children: part.slice(1, -1) }, i)) : (part));
9
+ }
@@ -0,0 +1,100 @@
1
+ import { type LucideIcon } from "lucide-react";
2
+ import { type ComponentProps, type ReactNode } from "react";
3
+ /**
4
+ * The pieces every block is built from, so the docs read as one thing: the stage a
5
+ * component is shown on, the frame around a stage, small icon buttons, a segmented
6
+ * control and a copy button. All drawn from the semantic tokens.
7
+ */
8
+ /**
9
+ * Where a component is shown: the page's canvas with a faint dot grid, so the
10
+ * component reads as an object on a surface rather than more page. `theme` renders
11
+ * it in one mode whatever the page is in; `width` narrows it to a phone.
12
+ */
13
+ export declare function Stage({ theme, width, className, children, ...props }: {
14
+ theme?: "light" | "dark";
15
+ width?: number;
16
+ className?: string;
17
+ children: ReactNode;
18
+ } & Omit<ComponentProps<"div">, "className">): import("react").JSX.Element;
19
+ /** A rounded card that frames a stage and its toolbar: every example, playground and preview sits in one. */
20
+ export declare function Frame({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
21
+ /** The bar along the top of a frame. */
22
+ export declare function Toolbar({ className, children }: {
23
+ className?: string;
24
+ children: ReactNode;
25
+ }): import("react").JSX.Element;
26
+ /**
27
+ * A small icon button: drawn at 32px, pressed at the docs' target size (44px by
28
+ * default) through a transparent ring, so a toolbar stays tight and every button
29
+ * is still easy to hit.
30
+ */
31
+ export declare function IconButton({ icon: Icon, label, pressed, className, ...props }: {
32
+ icon: LucideIcon;
33
+ label: string;
34
+ pressed?: boolean;
35
+ } & Omit<ComponentProps<"button">, "children">): import("react").JSX.Element;
36
+ /** An `IconButton` that goes somewhere: opening an example on its own, a source file. */
37
+ export declare function IconLink({ icon: Icon, label, className, ...props }: {
38
+ icon: LucideIcon;
39
+ label: string;
40
+ } & Omit<ComponentProps<"a">, "children">): import("react").JSX.Element;
41
+ /** Copies text, and says so: an icon button, or a labelled one with `withLabel`. */
42
+ export declare function CopyButton({ text, label, withLabel, className }: {
43
+ text: string;
44
+ label?: string;
45
+ withLabel?: boolean;
46
+ className?: string;
47
+ }): import("react").JSX.Element;
48
+ /**
49
+ * Two to four views of one thing, as a pill track with the chosen one raised.
50
+ * Tabs underneath, so arrow keys move between them and each panel is labelled by
51
+ * its tab. Put a `SegmentedList` where the switch belongs and a `SegmentedPanel`
52
+ * for each view.
53
+ */
54
+ export declare function Segmented({ defaultValue, className, children }: {
55
+ defaultValue: string;
56
+ className?: string;
57
+ children: ReactNode;
58
+ }): import("react").JSX.Element;
59
+ /** The track of a `Segmented`: put it where the switch belongs, usually a toolbar. */
60
+ export declare function SegmentedList({ items, label }: {
61
+ items: {
62
+ value: string;
63
+ label: string;
64
+ icon?: LucideIcon;
65
+ }[];
66
+ label: string;
67
+ }): import("react").JSX.Element;
68
+ export declare function SegmentedPanel({ value, className, children }: {
69
+ value: string;
70
+ className?: string;
71
+ children: ReactNode;
72
+ }): import("react").JSX.Element;
73
+ /** A small label above a group of controls or a column. */
74
+ export declare function Eyebrow({ className, children }: {
75
+ className?: string;
76
+ children: ReactNode;
77
+ }): import("react").JSX.Element;
78
+ /**
79
+ * A toolbar menu for one setting: the trigger shows an icon and, when the setting
80
+ * is not at its default, its current value; the menu lists every option with the
81
+ * chosen one checked. For viewport, background, colour vision and the like.
82
+ */
83
+ export declare function ToolbarMenu<T extends string>({ icon: Icon, label, value, fallback, options, onChange, swatch, }: {
84
+ icon: LucideIcon;
85
+ /** What the setting is, for the trigger's name and the menu's heading. */
86
+ label: string;
87
+ value: T;
88
+ /** The default: while chosen, the trigger shows only its icon. */
89
+ fallback: T;
90
+ options: {
91
+ value: T;
92
+ label: string;
93
+ note?: string;
94
+ }[];
95
+ onChange: (value: T) => void;
96
+ /** A colour to paint beside each option: for backgrounds. */
97
+ swatch?: (value: T) => string | undefined;
98
+ }): import("react").JSX.Element;
99
+ /** A thin upright rule between groups of toolbar controls. */
100
+ export declare function ToolbarDivider(): import("react").JSX.Element;
package/dist/lib/ui.js ADDED
@@ -0,0 +1,89 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Menu } from "@base-ui/react/menu";
4
+ import { Tabs } from "@base-ui/react/tabs";
5
+ import { Check, ChevronDown, Copy } from "lucide-react";
6
+ import { useState } from "react";
7
+ import { cx } from "./cx.js";
8
+ /**
9
+ * The pieces every block is built from, so the docs read as one thing: the stage a
10
+ * component is shown on, the frame around a stage, small icon buttons, a segmented
11
+ * control and a copy button. All drawn from the semantic tokens.
12
+ */
13
+ /**
14
+ * Where a component is shown: the page's canvas with a faint dot grid, so the
15
+ * component reads as an object on a surface rather than more page. `theme` renders
16
+ * it in one mode whatever the page is in; `width` narrows it to a phone.
17
+ */
18
+ export function Stage({ theme, width, className, children, ...props }) {
19
+ return (_jsx("div", { "data-slot": "stage", "data-docs-stage": "", "data-theme": theme, className: cx("relative flex min-w-0 items-center justify-center overflow-auto bg-canvas p-8 text-canvas-foreground sm:p-10", "bg-[radial-gradient(color-mix(in_oklch,var(--border)_85%,transparent)_1px,transparent_1px)] [background-size:14px_14px]", className), ...props, children: width ? (_jsx("div", { className: "w-full rounded-lg border border-dashed border-border p-4", style: { maxWidth: width }, children: children })) : (children) }));
20
+ }
21
+ /** A rounded card that frames a stage and its toolbar: every example, playground and preview sits in one. */
22
+ export function Frame({ className, children, ...props }) {
23
+ return (_jsx("div", { "data-slot": "frame", className: cx("flex min-w-0 flex-col overflow-hidden rounded-xl border border-border bg-surface text-surface-foreground shadow-xs", className), ...props, children: children }));
24
+ }
25
+ /** The bar along the top of a frame. */
26
+ export function Toolbar({ className, children }) {
27
+ return (_jsx("div", { "data-slot": "frame-toolbar", className: cx("flex min-h-12 flex-wrap items-center justify-between gap-2 border-b border-border px-2 py-1.5", className), children: children }));
28
+ }
29
+ /**
30
+ * A small icon button: drawn at 32px, pressed at the docs' target size (44px by
31
+ * default) through a transparent ring, so a toolbar stays tight and every button
32
+ * is still easy to hit.
33
+ */
34
+ export function IconButton({ icon: Icon, label, pressed, className, ...props }) {
35
+ return (_jsx("button", { type: "button", "aria-label": label, title: label, "aria-pressed": pressed, className: cx("relative inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors duration-(--dt-duration-fast)", "after:absolute after:-inset-[calc((var(--docs-target,2.75rem)-2rem)/2)] after:content-['']", "hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-ring aria-pressed:bg-muted aria-pressed:text-canvas-foreground", className), ...props, children: _jsx(Icon, { "aria-hidden": true, className: "size-(--dt-size-xs)" }) }));
36
+ }
37
+ /** An `IconButton` that goes somewhere: opening an example on its own, a source file. */
38
+ export function IconLink({ icon: Icon, label, className, ...props }) {
39
+ return (_jsx("a", { "aria-label": label, title: label, className: cx("relative inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors duration-(--dt-duration-fast)", "after:absolute after:-inset-[calc((var(--docs-target,2.75rem)-2rem)/2)] after:content-['']", "hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-ring", className), ...props, children: _jsx(Icon, { "aria-hidden": true, className: "size-(--dt-size-xs)" }) }));
40
+ }
41
+ /** Copies text, and says so: an icon button, or a labelled one with `withLabel`. */
42
+ export function CopyButton({ text, label = "Copy", withLabel, className }) {
43
+ const [copied, setCopied] = useState(false);
44
+ const copy = async () => {
45
+ try {
46
+ await navigator.clipboard.writeText(text);
47
+ setCopied(true);
48
+ setTimeout(() => setCopied(false), 1500);
49
+ }
50
+ catch {
51
+ // clipboard refused (an insecure origin, a denied permission): nothing changes
52
+ }
53
+ };
54
+ return (_jsxs(_Fragment, { children: [withLabel ? (_jsxs("button", { type: "button", onClick: copy, className: cx("inline-flex min-h-(--docs-target,2.75rem) cursor-pointer items-center gap-2 rounded-md border border-border bg-surface px-3 text-sm font-medium text-surface-foreground shadow-xs hover:bg-muted focus-visible:outline-2 focus-visible:outline-ring", className), children: [copied ? _jsx(Check, { "aria-hidden": true, className: "size-(--dt-size-xs)" }) : _jsx(Copy, { "aria-hidden": true, className: "size-(--dt-size-xs) text-muted-foreground" }), copied ? "Copied" : label] })) : (_jsx(IconButton, { icon: copied ? Check : Copy, label: copied ? "Copied" : label, onClick: copy, className: className })), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? "Copied" : "" })] }));
55
+ }
56
+ /**
57
+ * Two to four views of one thing, as a pill track with the chosen one raised.
58
+ * Tabs underneath, so arrow keys move between them and each panel is labelled by
59
+ * its tab. Put a `SegmentedList` where the switch belongs and a `SegmentedPanel`
60
+ * for each view.
61
+ */
62
+ export function Segmented({ defaultValue, className, children }) {
63
+ return (_jsx(Tabs.Root, { "data-slot": "segmented", defaultValue: defaultValue, className: cx("flex min-w-0 flex-col", className), children: children }));
64
+ }
65
+ /** The track of a `Segmented`: put it where the switch belongs, usually a toolbar. */
66
+ export function SegmentedList({ items, label }) {
67
+ return (_jsx(Tabs.List, { "aria-label": label, "data-slot": "segmented-list", className: "relative flex items-center gap-0.5 rounded-lg border border-border p-0.5", children: items.map(({ value, label: text, icon: Icon }) => (_jsxs(Tabs.Tab, { value: value, className: cx("relative inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground transition-colors duration-(--dt-duration-fast)", "after:absolute after:inset-x-0 after:-inset-y-[calc((var(--docs-target,2.75rem)-1.75rem)/2)] after:content-['']", "hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-ring data-active:bg-muted data-active:text-canvas-foreground"), children: [Icon && _jsx(Icon, { "aria-hidden": true, className: "size-(--dt-size-xs)" }), text] }, value))) }));
68
+ }
69
+ export function SegmentedPanel({ value, className, children }) {
70
+ return (_jsx(Tabs.Panel, { value: value, className: cx("min-w-0 outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring", className), children: children }));
71
+ }
72
+ /** A small label above a group of controls or a column. */
73
+ export function Eyebrow({ className, children }) {
74
+ return _jsx("p", { className: cx("text-xs font-medium tracking-wide text-muted-foreground uppercase", className), children: children });
75
+ }
76
+ /**
77
+ * A toolbar menu for one setting: the trigger shows an icon and, when the setting
78
+ * is not at its default, its current value; the menu lists every option with the
79
+ * chosen one checked. For viewport, background, colour vision and the like.
80
+ */
81
+ export function ToolbarMenu({ icon: Icon, label, value, fallback, options, onChange, swatch, }) {
82
+ const current = options.find((o) => o.value === value);
83
+ const changed = value !== fallback;
84
+ return (_jsxs(Menu.Root, { children: [_jsxs(Menu.Trigger, { "aria-label": `${label}: ${current?.label ?? value}`, title: label, className: cx("relative inline-flex h-8 shrink-0 cursor-pointer items-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground transition-colors duration-(--dt-duration-fast)", "after:absolute after:inset-x-0 after:-inset-y-[calc((var(--docs-target,2.75rem)-2rem)/2)] after:content-['']", "hover:bg-muted hover:text-canvas-foreground focus-visible:outline-2 focus-visible:outline-ring data-popup-open:bg-muted data-popup-open:text-canvas-foreground", changed && "bg-muted text-canvas-foreground"), children: [swatch && swatch(value) ? (_jsx("span", { "aria-hidden": true, className: "size-3.5 rounded-full ring-1 ring-border", style: { background: swatch(value) } })) : (_jsx(Icon, { "aria-hidden": true, className: "size-(--dt-size-xs)" })), changed && _jsx("span", { className: "max-w-28 truncate", children: current?.label ?? value }), _jsx(ChevronDown, { "aria-hidden": true, className: "size-3 opacity-60" })] }), _jsx(Menu.Portal, { children: _jsx(Menu.Positioner, { "data-designtools": "", sideOffset: 6, align: "start", className: "z-50", children: _jsx(Menu.Popup, { className: "min-w-56 rounded-xl border border-border bg-overlay p-1.5 text-overlay-foreground shadow-lg transition-[opacity,scale] duration-(--dt-duration-fast) data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0", children: _jsxs(Menu.Group, { children: [_jsx(Menu.GroupLabel, { className: "px-3 pt-1.5 pb-1 text-xs text-muted-foreground", children: label }), _jsx(Menu.RadioGroup, { value: value, onValueChange: (v) => onChange(v), children: options.map((o) => (_jsxs(Menu.RadioItem, { value: o.value, closeOnClick: true, className: "grid min-h-(--docs-target,2.75rem) cursor-pointer grid-cols-[1rem_1fr] items-center gap-3 rounded-md px-3 text-sm outline-none select-none data-highlighted:bg-muted", children: [_jsx(Menu.RadioItemIndicator, { keepMounted: true, className: "flex items-center justify-center data-unchecked:invisible", children: _jsx(Check, { "aria-hidden": true, className: "size-4" }) }), _jsxs("span", { className: "flex items-center gap-2.5", children: [swatch?.(o.value) && _jsx("span", { "aria-hidden": true, className: "size-4 shrink-0 rounded-full ring-1 ring-border", style: { background: swatch(o.value) } }), _jsxs("span", { className: "flex flex-col", children: [o.label, o.note && _jsx("span", { className: "text-xs text-muted-foreground", children: o.note })] })] })] }, o.value))) })] }) }) }) })] }));
85
+ }
86
+ /** A thin upright rule between groups of toolbar controls. */
87
+ export function ToolbarDivider() {
88
+ return _jsx("span", { "aria-hidden": true, className: "mx-1 h-5 w-px shrink-0 bg-border" });
89
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * How the preview looks to people who see colour differently, or less sharply.
3
+ * SVG colour matrices for the three common colour-vision deficiencies and for no
4
+ * colour at all, from Machado, Oliveira and Fernandes (2009) at full severity, and
5
+ * a blur for low acuity. A simulation is a prompt to look again, not a test.
6
+ */
7
+ export type Vision = "typical" | "protanopia" | "deuteranopia" | "tritanopia" | "achromatopsia" | "blurred";
8
+ export declare const VISIONS: {
9
+ value: Vision;
10
+ label: string;
11
+ note: string;
12
+ }[];
13
+ /** The filters, once per page; `filterFor` points an element at one. */
14
+ export declare function VisionFilters({ id }: {
15
+ id: string;
16
+ }): import("react").JSX.Element;
17
+ /** The CSS `filter` for a vision, given the id the filters were rendered with. */
18
+ export declare function filterFor(vision: Vision, id: string): string | undefined;
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const VISIONS = [
3
+ { value: "typical", label: "Typical", note: "No simulation" },
4
+ { value: "protanopia", label: "Protanopia", note: "No red cones, about 1% of men" },
5
+ { value: "deuteranopia", label: "Deuteranopia", note: "No green cones, about 1% of men" },
6
+ { value: "tritanopia", label: "Tritanopia", note: "No blue cones, rare" },
7
+ { value: "achromatopsia", label: "Achromatopsia", note: "No colour at all" },
8
+ { value: "blurred", label: "Blurred", note: "Low acuity, or a screen far away" },
9
+ ];
10
+ const MATRICES = {
11
+ protanopia: "0.152 1.053 -0.205 0 0 0.115 0.786 0.099 0 0 -0.004 -0.048 1.052 0 0 0 0 0 1 0",
12
+ deuteranopia: "0.367 0.861 -0.228 0 0 0.280 0.673 0.047 0 0 -0.012 0.043 0.969 0 0 0 0 0 1 0",
13
+ tritanopia: "1.256 -0.077 -0.179 0 0 -0.078 0.931 0.148 0 0 0.005 0.691 0.304 0 0 0 0 0 1 0",
14
+ achromatopsia: "0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0 0 0 1 0",
15
+ };
16
+ /** The filters, once per page; `filterFor` points an element at one. */
17
+ export function VisionFilters({ id }) {
18
+ return (_jsx("svg", { "aria-hidden": true, width: "0", height: "0", className: "absolute", children: Object.entries(MATRICES).map(([name, values]) => (_jsx("filter", { id: `${id}-${name}`, colorInterpolationFilters: "linearRGB", children: _jsx("feColorMatrix", { type: "matrix", values: values }) }, name))) }));
19
+ }
20
+ /** The CSS `filter` for a vision, given the id the filters were rendered with. */
21
+ export function filterFor(vision, id) {
22
+ if (vision === "typical")
23
+ return undefined;
24
+ if (vision === "blurred")
25
+ return "blur(1.5px)";
26
+ return `url(#${id}-${vision})`;
27
+ }
@@ -0,0 +1,14 @@
1
+ import type { AssetEntry, RuleEntry } from "./lib/manifest-types.js";
2
+ /**
3
+ * Each logo on the surfaces it may sit on, at its minimum size, with its clear
4
+ * space drawn, and the brand rules that govern it: rules for every logo once,
5
+ * above them, and a rule naming one logo under that logo. Surfaces are semantic
6
+ * colour names painted from the light-mode tokens whatever the docs' mode, because a
7
+ * brand book's surfaces are fixed colours (white, the brand colour, an off-white),
8
+ * and dark mode would otherwise show the logo on a surface the brand forbids.
9
+ */
10
+ export declare function LogoUsage({ assets, rules, rulesHref }: {
11
+ assets: AssetEntry[];
12
+ rules?: RuleEntry[];
13
+ rulesHref?: string;
14
+ }): import("react").JSX.Element;
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Scale } from "lucide-react";
4
+ import { useLookup } from "./lib/lookup.js";
5
+ import { StatusBadge } from "./lib/status.js";
6
+ import { inline } from "./lib/text.js";
7
+ const LENGTH = /^\s*(\d+(?:\.\d+)?)(px|rem|em)\b/;
8
+ /**
9
+ * Each logo on the surfaces it may sit on, at its minimum size, with its clear
10
+ * space drawn, and the brand rules that govern it: rules for every logo once,
11
+ * above them, and a rule naming one logo under that logo. Surfaces are semantic
12
+ * colour names painted from the light-mode tokens whatever the docs' mode, because a
13
+ * brand book's surfaces are fixed colours (white, the brand colour, an off-white),
14
+ * and dark mode would otherwise show the logo on a surface the brand forbids.
15
+ */
16
+ export function LogoUsage({ assets, rules = [], rulesHref }) {
17
+ const lookup = useLookup();
18
+ const logos = assets.filter((a) => a.kind === "logo");
19
+ if (logos.length === 0)
20
+ return _jsx("p", { className: "text-sm text-muted-foreground", children: "No logos in the brand folder yet." });
21
+ const brand = rules.filter((r) => r.kind === "brand");
22
+ const general = brand.filter((r) => (r.appliesTo ?? []).some((x) => ["logo", "logos"].includes(x.toLowerCase())));
23
+ return (_jsxs("div", { "data-slot": "logo-usage", className: "flex flex-col gap-16", children: [general.length > 0 && _jsx(RuleList, { rules: general, rulesHref: rulesHref }), logos.map((logo) => {
24
+ const src = lookup.assetUrl(logo);
25
+ const names = new Set([logo.name.toLowerCase(), logo.file.toLowerCase()]);
26
+ const own = brand.filter((r) => !general.includes(r) && (r.appliesTo ?? []).some((x) => names.has(x.toLowerCase())));
27
+ const clear = LENGTH.exec(logo.clearSpace ?? "");
28
+ const min = LENGTH.exec(logo.minSize ?? "");
29
+ const surfaces = logo.surfaces?.length ? logo.surfaces : ["canvas"];
30
+ const paint = (surface) => ({ background: `var(--${surface})`, color: `var(--${surface}-foreground, var(--canvas-foreground))` });
31
+ const facts = [
32
+ [
33
+ "Minimum size",
34
+ _jsxs("span", { className: "flex flex-wrap items-center gap-3", children: [logo.minSize ?? "not set", src && min && (_jsx("span", { "data-slot": "logo-min-size", "data-theme": "light", className: "inline-flex rounded-md border border-border p-2", style: paint(surfaces[0]), children: _jsx("img", { src: src, alt: "", "aria-hidden": true, className: "block w-auto", style: { height: `${min[1]}${min[2]}` } }) }))] }, "m"),
35
+ ],
36
+ ["Clear space", logo.clearSpace ?? "not set"],
37
+ ];
38
+ if (logo.width && logo.height)
39
+ facts.push(["Proportions", _jsxs("span", { className: "font-mono text-xs", children: [logo.width, " \u00D7 ", logo.height] }, "p")]);
40
+ return (_jsxs("section", { "data-slot": "logo", className: "flex flex-col gap-5", children: [_jsxs("header", { className: "flex flex-col gap-1.5", children: [_jsx("h3", { className: "text-3xl tracking-tight", children: logo.name }), logo.usage && _jsx("p", { className: "max-w-2xl text-base text-muted-foreground", children: inline(logo.usage) })] }), _jsxs("div", { className: "grid gap-3 lg:grid-cols-[minmax(0,2fr)_minmax(0,1fr)]", children: [_jsxs("div", { "data-slot": "logo-surface", "data-theme": "light", className: "relative flex min-h-72 items-center justify-center overflow-hidden rounded-2xl border border-border p-10", style: paint(surfaces[0]), children: [_jsx("span", { className: "absolute top-4 left-4 font-mono text-xs opacity-70", children: surfaces[0] }), _jsxs("span", { className: "relative inline-flex", children: [_jsx("span", { "data-slot": "logo-clear-space", className: "inline-flex border border-dashed", style: { padding: clear ? `calc(${clear[1]}${clear[2]} * 2)` : "1.5rem", borderColor: "color-mix(in oklch, currentColor 45%, transparent)" }, title: `Clear space: ${logo.clearSpace ?? "not set"}`, children: src ? _jsx("img", { src: src, alt: logo.alt ?? logo.name, className: "block h-16 w-auto sm:h-20" }) : _jsx("span", { className: "text-xs", children: logo.file }) }), clear && (_jsx("span", { className: "absolute -bottom-6 left-1/2 -translate-x-1/2 font-mono text-xs whitespace-nowrap opacity-70", children: "clear space, shown at 2\u00D7" }))] })] }), _jsxs("ul", { className: "grid grid-cols-2 gap-3 lg:grid-cols-1 lg:grid-rows-3", children: [surfaces.slice(1).map((surface) => (_jsxs("li", { "data-slot": "logo-surface", "data-theme": "light", className: "relative flex min-h-28 items-center justify-center rounded-2xl border border-border p-6", style: paint(surface), children: [_jsx("span", { className: "absolute top-3 left-3 font-mono text-xs opacity-70", children: surface }), src && _jsx("img", { src: src, alt: "", "aria-hidden": true, className: "block h-9 w-auto" })] }, surface))), surfaces.length === 1 && (_jsxs("li", { className: "col-span-2 flex items-center rounded-2xl border border-dashed border-border p-6 text-sm text-muted-foreground lg:col-span-1 lg:row-span-3", children: ["Only on ", surfaces[0], "."] }))] })] }), _jsx("dl", { className: "grid gap-x-10 gap-y-5 sm:grid-cols-3", children: facts.map(([term, detail]) => (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("dt", { className: "text-xs font-medium text-muted-foreground", children: term }), _jsx("dd", { className: "text-sm", children: detail })] }, term))) }), own.length > 0 && _jsx(RuleList, { rules: own, rulesHref: rulesHref })] }, logo.file));
41
+ })] }));
42
+ }
43
+ function RuleList({ rules, rulesHref }) {
44
+ return (_jsx("ul", { "data-slot": "logo-rules", className: "grid gap-x-12 sm:grid-cols-2", children: rules.map((r) => (_jsx("li", { className: "border-t border-border", children: _jsxs("a", { href: rulesHref ? `${rulesHref}#${r.id}` : `#${r.id}`, className: "group flex h-full flex-col gap-1.5 py-4 text-sm focus-visible:outline-2 focus-visible:outline-ring", children: [_jsxs("span", { className: "flex items-center justify-between gap-2", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-medium group-hover:underline group-hover:underline-offset-4", children: [_jsx(Scale, { "aria-hidden": true, className: "size-(--dt-size-xs) text-muted-foreground" }), r.title] }), _jsx(StatusBadge, { status: r.status })] }), _jsx("span", { className: "text-muted-foreground", children: inline(r.statement) })] }) }, r.id))) }));
45
+ }
@@ -0,0 +1,105 @@
1
+ import type { ComponentType, ReactElement, ReactNode } from "react";
2
+ import type { AdherenceReport } from "../lib/adherence-types.js";
3
+ /** A page people write: brand, principles, a design language, with its author and how settled it is. */
4
+ export type EditorialPage = EditorialBase & ({
5
+ /** Markdown: `##` and `###` sections, paragraphs, bullet lists, bold, code and links; a list whose items open in bold is a set of principles. */
6
+ body: string;
7
+ markdown?: undefined;
8
+ } | {
9
+ /**
10
+ * The page as React: real components from the project's system beside the docs' own `DocsSection`
11
+ * and `Prose`, for a page that has to show rather than tell. Rendered as is, under the page header.
12
+ */
13
+ body: ReactNode;
14
+ /** What agents read instead, at the page's `.md`: the same page, in words. */
15
+ markdown: string;
16
+ });
17
+ interface EditorialBase {
18
+ /** Its path under the docs, e.g. `brand` or `brand/accessibility`. */
19
+ slug: string;
20
+ title: string;
21
+ lead?: string;
22
+ by: {
23
+ author: string;
24
+ reviewer?: string;
25
+ reviewed: string;
26
+ status: "draft" | "published";
27
+ };
28
+ /** The navigation group it sits in. Default: brand. */
29
+ section?: "brand" | "foundations" | "standards";
30
+ /** Its label in the navigation, when shorter than its title. */
31
+ nav?: string;
32
+ }
33
+ /** What a component needs to render on its workbench. */
34
+ export interface WorkbenchSetup {
35
+ /** Starting props: what it needs to render at all (a Select's options). */
36
+ props?: Record<string, unknown>;
37
+ /** Text inside it. "" for a component that takes none. */
38
+ children?: string;
39
+ /** Children richer than text: a Card's parts, a Tabs' list and panels. */
40
+ content?: ReactNode;
41
+ /** What it must sit inside to work: a provider, the root a part belongs to. */
42
+ wrap?: ReactElement<{
43
+ children?: ReactNode;
44
+ }>;
45
+ }
46
+ /** The built-in generated pages, each of which can be turned off. */
47
+ export type BuiltInPage = "logo" | "imagery" | "voice" | "colour" | "type" | "scale" | "rules" | "patterns" | "components" | "standards" | "vocabulary";
48
+ /**
49
+ * Everything one site of docs needs: the manifest it renders, the registry that
50
+ * reaches the project's components, the brand around it, and what each part
51
+ * says. The pages, their order, the navigation, search and the markdown for
52
+ * agents all come from this.
53
+ */
54
+ export interface DocsConfig {
55
+ title: string;
56
+ /** Where the docs are served. Default: `/design/system`. */
57
+ basePath?: string;
58
+ /** The client's logo, beside the title in the navigation. */
59
+ logo?: ReactNode;
60
+ /** A full-bleed introduction across the top of the overview. Without one the overview has a plain header. */
61
+ hero?: ReactNode;
62
+ /** The overview's lead, when there is no hero. */
63
+ lead?: string;
64
+ /**
65
+ * The overview after its hero or header: `agentic: false` drops "Why this is agentic", and `agenticLead`
66
+ * replaces the line that opens it.
67
+ */
68
+ overview?: {
69
+ agentic?: boolean;
70
+ agenticLead?: string;
71
+ };
72
+ /** The generated registry (`designtools-docs map`): a provider for the project's components, examples and assets. */
73
+ registry: ComponentType<{
74
+ children: ReactNode;
75
+ }>;
76
+ /** The manifest, as `designtools-manifest build` writes it. */
77
+ manifest: {
78
+ components: unknown;
79
+ tokens: unknown;
80
+ rules?: unknown;
81
+ patterns?: unknown;
82
+ taxonomy?: unknown;
83
+ assets?: unknown;
84
+ };
85
+ /** `.mxa/stack.json`'s baselines, for the standards page. */
86
+ baselines?: Record<string, unknown>;
87
+ /** `designtools-manifest provenance`'s line: the version and commit the docs were built from. */
88
+ provenance?: string;
89
+ /** `designtools-adherence --json`, for the standards page. */
90
+ adherence?: AdherenceReport;
91
+ /** Pages people write, in the order they appear. */
92
+ editorial?: EditorialPage[];
93
+ /** Built-in pages to leave out. */
94
+ hide?: BuiltInPage[];
95
+ /** Per component, by name: what it needs on its workbench. */
96
+ workbench?: Record<string, WorkbenchSetup>;
97
+ /** Per rule, by id: a demonstration shown on its card, for a rule that needs persuading. */
98
+ demonstrations?: Record<string, ReactNode>;
99
+ /**
100
+ * Blocks replaced by the project's own, by name: `{ Usage: LocalUsage }`.
101
+ * `designtools-docs eject <block>` copies one into the project to start from.
102
+ */
103
+ blocks?: Partial<Record<string, ComponentType<any>>>;
104
+ }
105
+ export {};
@@ -0,0 +1 @@
1
+ export {};