@designtools/docs 0.0.0-stage → 0.1.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 (167) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +133 -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 +38 -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 +14 -0
  21. package/dist/imagery.d.ts +6 -0
  22. package/dist/imagery.js +17 -0
  23. package/dist/index.d.ts +34 -0
  24. package/dist/index.js +33 -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/lookup.d.ts +35 -0
  36. package/dist/lib/lookup.js +41 -0
  37. package/dist/lib/manifest-types.d.ts +253 -0
  38. package/dist/lib/manifest-types.js +14 -0
  39. package/dist/lib/manifest.d.ts +98 -0
  40. package/dist/lib/manifest.js +173 -0
  41. package/dist/lib/markdown.d.ts +50 -0
  42. package/dist/lib/markdown.js +286 -0
  43. package/dist/lib/measure.d.ts +12 -0
  44. package/dist/lib/measure.js +62 -0
  45. package/dist/lib/pseudo.d.ts +11 -0
  46. package/dist/lib/pseudo.js +71 -0
  47. package/dist/lib/registry.d.ts +21 -0
  48. package/dist/lib/registry.js +11 -0
  49. package/dist/lib/search.d.ts +44 -0
  50. package/dist/lib/search.js +62 -0
  51. package/dist/lib/standards.d.ts +17 -0
  52. package/dist/lib/standards.js +81 -0
  53. package/dist/lib/status.d.ts +7 -0
  54. package/dist/lib/status.js +17 -0
  55. package/dist/lib/text.d.ts +8 -0
  56. package/dist/lib/text.js +9 -0
  57. package/dist/lib/ui.d.ts +100 -0
  58. package/dist/lib/ui.js +89 -0
  59. package/dist/lib/vision.d.ts +18 -0
  60. package/dist/lib/vision.js +27 -0
  61. package/dist/logo-usage.d.ts +14 -0
  62. package/dist/logo-usage.js +45 -0
  63. package/dist/next/config.d.ts +85 -0
  64. package/dist/next/config.js +1 -0
  65. package/dist/next/index.d.ts +62 -0
  66. package/dist/next/index.js +63 -0
  67. package/dist/next/markdown.d.ts +20 -0
  68. package/dist/next/markdown.js +95 -0
  69. package/dist/next/pages.d.ts +6 -0
  70. package/dist/next/pages.js +122 -0
  71. package/dist/next/prose.d.ts +9 -0
  72. package/dist/next/prose.js +37 -0
  73. package/dist/next/proxy.d.ts +19 -0
  74. package/dist/next/proxy.js +56 -0
  75. package/dist/next/site.d.ts +53 -0
  76. package/dist/next/site.js +136 -0
  77. package/dist/page-actions.d.ts +9 -0
  78. package/dist/page-actions.js +32 -0
  79. package/dist/pattern.d.ts +8 -0
  80. package/dist/pattern.js +19 -0
  81. package/dist/playground.d.ts +62 -0
  82. package/dist/playground.js +111 -0
  83. package/dist/preview-frame.d.ts +31 -0
  84. package/dist/preview-frame.js +63 -0
  85. package/dist/props-table.d.ts +10 -0
  86. package/dist/props-table.js +45 -0
  87. package/dist/rule.d.ts +12 -0
  88. package/dist/rule.js +32 -0
  89. package/dist/scale.d.ts +9 -0
  90. package/dist/scale.js +58 -0
  91. package/dist/search.d.ts +16 -0
  92. package/dist/search.js +46 -0
  93. package/dist/shell.d.ts +89 -0
  94. package/dist/shell.js +199 -0
  95. package/dist/standards.d.ts +13 -0
  96. package/dist/standards.js +19 -0
  97. package/dist/styles.css +3519 -0
  98. package/dist/swatches.d.ts +28 -0
  99. package/dist/swatches.js +94 -0
  100. package/dist/theme-switch.d.ts +20 -0
  101. package/dist/theme-switch.js +68 -0
  102. package/dist/type-ramp.d.ts +10 -0
  103. package/dist/type-ramp.js +31 -0
  104. package/dist/usage.d.ts +13 -0
  105. package/dist/usage.js +55 -0
  106. package/dist/variant-matrix.d.ts +15 -0
  107. package/dist/variant-matrix.js +53 -0
  108. package/dist/voice-terms.d.ts +5 -0
  109. package/dist/voice-terms.js +13 -0
  110. package/dist/workbench.d.ts +33 -0
  111. package/dist/workbench.js +273 -0
  112. package/package.json +107 -3
  113. package/src/a11y-panel.tsx +297 -0
  114. package/src/adherence-summary.tsx +134 -0
  115. package/src/agent-view.tsx +54 -0
  116. package/src/anatomy.tsx +114 -0
  117. package/src/ask-claude.tsx +90 -0
  118. package/src/code-view.tsx +112 -0
  119. package/src/css.d.ts +1 -0
  120. package/src/examples.tsx +141 -0
  121. package/src/glossary.tsx +71 -0
  122. package/src/imagery.tsx +64 -0
  123. package/src/index.ts +34 -0
  124. package/src/lib/adherence-types.ts +181 -0
  125. package/src/lib/boundary.tsx +21 -0
  126. package/src/lib/contrast.ts +44 -0
  127. package/src/lib/cx.ts +30 -0
  128. package/src/lib/jsx.ts +29 -0
  129. package/src/lib/lookup.tsx +49 -0
  130. package/src/lib/manifest-types.ts +284 -0
  131. package/src/lib/manifest.ts +228 -0
  132. package/src/lib/markdown.ts +288 -0
  133. package/src/lib/measure.tsx +101 -0
  134. package/src/lib/pseudo.ts +74 -0
  135. package/src/lib/registry.tsx +29 -0
  136. package/src/lib/search.ts +99 -0
  137. package/src/lib/standards.ts +82 -0
  138. package/src/lib/status.tsx +32 -0
  139. package/src/lib/text.tsx +27 -0
  140. package/src/lib/ui.tsx +291 -0
  141. package/src/lib/vision.tsx +44 -0
  142. package/src/logo-usage.tsx +140 -0
  143. package/src/next/config.ts +80 -0
  144. package/src/next/index.tsx +100 -0
  145. package/src/next/markdown.ts +119 -0
  146. package/src/next/pages.tsx +370 -0
  147. package/src/next/prose.tsx +87 -0
  148. package/src/next/proxy.ts +55 -0
  149. package/src/next/site.ts +173 -0
  150. package/src/page-actions.tsx +92 -0
  151. package/src/pattern.tsx +67 -0
  152. package/src/playground.tsx +352 -0
  153. package/src/preview-frame.tsx +131 -0
  154. package/src/props-table.tsx +154 -0
  155. package/src/rule.tsx +116 -0
  156. package/src/scale.tsx +175 -0
  157. package/src/search.tsx +155 -0
  158. package/src/shell.tsx +555 -0
  159. package/src/standards.tsx +58 -0
  160. package/src/styles.css +155 -0
  161. package/src/swatches.tsx +287 -0
  162. package/src/theme-switch.tsx +90 -0
  163. package/src/type-ramp.tsx +150 -0
  164. package/src/usage.tsx +148 -0
  165. package/src/variant-matrix.tsx +195 -0
  166. package/src/voice-terms.tsx +46 -0
  167. package/src/workbench.tsx +584 -0
@@ -0,0 +1,253 @@
1
+ /**
2
+ * The manifest schema: what `designtools-manifest build` writes to
3
+ * `<system>/manifest/`: components.json, tokens.json, rules.json,
4
+ * patterns.json, taxonomy.json and assets.json.
5
+ *
6
+ * This file has no imports on purpose. @designtools/docs carries a byte-identical
7
+ * copy, so a project's docs read the manifest through the same types the tool
8
+ * wrote it with, and a test in this repo fails if the two drift.
9
+ *
10
+ * Every path is relative to the project root, with forward slashes. Arrays keep
11
+ * source order where order means something (variant axes, fixture states, token
12
+ * ramps); everything else is sorted, so a diff of the files shows only real changes.
13
+ */
14
+ export declare const MANIFEST_SCHEMA = "designtools.manifest/1";
15
+ /** What every manifest file opens with. */
16
+ interface ManifestFile {
17
+ /** `@designtools/manifest@<version>`, so `check` can tell a tool upgrade from an edit. */
18
+ generator: string;
19
+ schema: string;
20
+ }
21
+ /** components.json */
22
+ export interface ComponentsManifest extends ManifestFile {
23
+ /** The system folder the components were read from. */
24
+ system: string;
25
+ /** Sorted by name, then source. */
26
+ components: ComponentEntry[];
27
+ }
28
+ export interface ComponentEntry {
29
+ /** The export name, or `@name` when the JSDoc gives one. */
30
+ name: string;
31
+ /** The exported identifier to import. Equals `name` unless `@name` renamed it. */
32
+ export: string;
33
+ /** The file that exports it. */
34
+ source: string;
35
+ /**
36
+ * The module specifier an app imports it by, through the tsconfig path alias
37
+ * that reaches the system folder (`@ds/button/button`). Absent when no alias does,
38
+ * in which case `source` is the only honest answer.
39
+ */
40
+ import?: string;
41
+ /** The component's JSDoc, or its variant config's when the component has none. */
42
+ description?: string;
43
+ /** `@category`. Blocks group components without one under "Components". */
44
+ category?: string;
45
+ /** `@status`, or `deprecated` from `@deprecated`. Absent until someone decides it. */
46
+ status?: Status;
47
+ /** Why it has that status: the `@deprecated` reason, or text after `@status`. */
48
+ statusNote?: string;
49
+ /** `@use`, `@avoid`, `@instead`: when to reach for it, when not, and what instead. */
50
+ usage?: Usage;
51
+ /** `@example` snippets in the JSDoc, each one JSX. */
52
+ snippets?: string[];
53
+ /** `@see`, each one a link or a component name. */
54
+ see?: string[];
55
+ /** `@primitive`: the primitive it wraps, as a link or a package path. */
56
+ primitive?: string;
57
+ /** `@aria`: the ARIA pattern it follows, usually a link. */
58
+ aria?: string;
59
+ /** `@role` and `@keyboard`: what assistive technology meets, and the keys it answers. */
60
+ a11y?: {
61
+ role?: string;
62
+ keyboard?: string[];
63
+ };
64
+ /** `@replaces`: raw elements this component stands in for, which the adherence report counts. */
65
+ replaces?: string[];
66
+ /**
67
+ * What it also accepts beyond its own props: an intrinsic element (`"span"`)
68
+ * or a wrapped primitive (`"@base-ui/react/select:Root"`).
69
+ */
70
+ inherits?: string[];
71
+ /** Its own props, and those of a primitive it wraps. Inherited DOM props are left out. */
72
+ props: Record<string, PropEntry>;
73
+ /** Absent when it has no variants by any route. */
74
+ variants?: VariantsEntry;
75
+ /** Every `data-slot` it renders, sorted. */
76
+ slots: string[];
77
+ /** Absent when the component has no examples file. */
78
+ examples?: ExamplesEntry;
79
+ }
80
+ export type Status = "stable" | "emerging" | "deprecated";
81
+ export interface Usage {
82
+ use?: string;
83
+ avoid?: string;
84
+ /** Components, or other things, to use instead. */
85
+ instead?: string[];
86
+ }
87
+ export interface PropEntry {
88
+ /** The type as written or resolved, e.g. `string`, `"sm" | "md"`, `(v: string) => void`. */
89
+ type: string;
90
+ /** Present when the type is a union of literals: each value, unquoted. */
91
+ values?: string[];
92
+ required: boolean;
93
+ /** The default, as source text, when the component destructures one. */
94
+ default?: string;
95
+ description?: string;
96
+ deprecated?: string;
97
+ /** The package that declares it, when it comes from a wrapped primitive rather than the project. */
98
+ from?: string;
99
+ }
100
+ export interface VariantsEntry {
101
+ /** Where the axes came from: a `tv()` or `cva()` config, or the props' literal union types. */
102
+ from: "tv" | "cva" | "props";
103
+ /** The config's variable name. Absent when `from` is `"props"`. */
104
+ config?: string;
105
+ /** Source order. */
106
+ axes: VariantAxis[];
107
+ /** Conditions only, without their classes, in source order. */
108
+ compound?: Record<string, string | string[]>[];
109
+ /** A `tv()` config's named parts, in source order. */
110
+ parts?: string[];
111
+ }
112
+ export interface VariantAxis {
113
+ name: string;
114
+ /** Source order. */
115
+ options: VariantOption[];
116
+ default?: string;
117
+ }
118
+ export interface VariantOption {
119
+ name: string;
120
+ description?: string;
121
+ }
122
+ /**
123
+ * A co-located `*.examples.tsx`: `canonical` is the one to copy, `do*` and
124
+ * `dont*` render as pairs in order, anything else is a further example.
125
+ */
126
+ export interface ExamplesEntry {
127
+ source: string;
128
+ canonical?: ExampleRef;
129
+ do: ExampleRef[];
130
+ dont: ExampleRef[];
131
+ other: ExampleRef[];
132
+ }
133
+ export interface ExampleRef {
134
+ /** The export name. */
135
+ name: string;
136
+ /** Its JSDoc: why to do it, or why not. */
137
+ description?: string;
138
+ /** The JSX it returns, as written, for agents and code views. */
139
+ code?: string;
140
+ }
141
+ /** tokens.json */
142
+ export interface TokensManifest extends ManifestFile {
143
+ /** The stylesheets read, in the order given. */
144
+ sources: string[];
145
+ /** Source order: file by file, declaration by declaration. */
146
+ tokens: TokenEntry[];
147
+ }
148
+ export type TokenTier = "color" | "font" | "font-weight" | "text" | "leading" | "tracking" | "spacing" | "size" | "radius" | "shadow" | "ease" | "duration" | "motion" | "breakpoint" | "container" | "other";
149
+ export interface TokenEntry {
150
+ /** The custom property, with its dashes: `--color-primary-500`. */
151
+ name: string;
152
+ tier: TokenTier;
153
+ /**
154
+ * The value in each context it is declared in. `default` is `@theme` or `:root`;
155
+ * `light` and `dark` are the mode blocks; a `p3:` prefix marks the
156
+ * `@media (color-gamut: p3)` layer. Any other selector is kept as written.
157
+ */
158
+ values: Record<string, string>;
159
+ /** The comment above it, or above the run of declarations it belongs to. */
160
+ description?: string;
161
+ /** The stylesheet that first declares it. */
162
+ source: string;
163
+ /** Later stylesheets whose declaration replaced a value, in the order read: an override layer. */
164
+ overriddenIn?: string[];
165
+ }
166
+ /** rules.json: brand and interface rules in one format. */
167
+ export interface RulesManifest extends ManifestFile {
168
+ /** Sorted by id. */
169
+ rules: RuleEntry[];
170
+ }
171
+ export interface RuleEntry {
172
+ /** The file name without `.rule.json`, used as its anchor: `touch-target`. */
173
+ id: string;
174
+ kind: "brand" | "interface";
175
+ title: string;
176
+ /** The rule, in one or two sentences, for people first. */
177
+ statement: string;
178
+ /** Why it exists. */
179
+ rationale?: string;
180
+ /** The measurable line, e.g. `44 × 44 CSS px`. */
181
+ threshold?: string;
182
+ /** Components, elements, assets or pages it governs. */
183
+ appliesTo?: string[];
184
+ exceptions?: string[];
185
+ /** Tokens it rests on, e.g. `--size-2xl`. */
186
+ tokens?: string[];
187
+ /**
188
+ * Confirmed with the client, an assumption still to confirm, or measured: generated from the
189
+ * tokens (where a colour can be text), a fact that changes when they do, not a decision.
190
+ */
191
+ status: "confirmed" | "assumption" | "measured";
192
+ /** How it is proved: a test, a lint rule, an audit, or a person. */
193
+ check?: {
194
+ kind: "test" | "lint" | "audit" | "manual";
195
+ ref?: string;
196
+ description?: string;
197
+ };
198
+ source: string;
199
+ }
200
+ /** patterns.json: the product's recurring screen compositions. */
201
+ export interface PatternsManifest extends ManifestFile {
202
+ /** Sorted by name. */
203
+ patterns: PatternEntry[];
204
+ }
205
+ export interface PatternEntry {
206
+ /** From the file name: `checkout` for `checkout.pattern.tsx`. */
207
+ id: string;
208
+ name: string;
209
+ description?: string;
210
+ status?: Status;
211
+ /** The system components it imports, by name, sorted. */
212
+ components: string[];
213
+ /** Each named export is a composition, in source order. */
214
+ examples: ExampleRef[];
215
+ source: string;
216
+ }
217
+ /** taxonomy.json: one vocabulary, with the wrong forms to avoid. */
218
+ export interface TaxonomyManifest extends ManifestFile {
219
+ /** Sorted by name. */
220
+ terms: TermEntry[];
221
+ }
222
+ export interface TermEntry {
223
+ /** The canonical form. */
224
+ name: string;
225
+ kind: "component" | "variant" | "token" | "pattern" | "rule" | "product";
226
+ /** Known wrong forms: `error` for `destructive`, `Modal` for `Dialog`, "log in" for "sign in". */
227
+ wrong?: string[];
228
+ note?: string;
229
+ /** Where it is defined: a component's source, a token's name, a rule's id. */
230
+ ref?: string;
231
+ }
232
+ /** assets.json: logos, icons and imagery, with how to use them. */
233
+ export interface AssetsManifest extends ManifestFile {
234
+ /** Sorted by file. */
235
+ assets: AssetEntry[];
236
+ }
237
+ export interface AssetEntry {
238
+ file: string;
239
+ kind: "logo" | "icon" | "image" | "other";
240
+ name: string;
241
+ usage?: string;
242
+ /** e.g. `24px tall` */
243
+ minSize?: string;
244
+ /** e.g. `the height of the wordmark's x` or a length */
245
+ clearSpace?: string;
246
+ /** Surfaces it may sit on, as semantic colour names: `canvas`, `primary`. */
247
+ surfaces?: string[];
248
+ alt?: string;
249
+ /** Intrinsic size, read from an SVG's viewBox or a PNG's header. */
250
+ width?: number;
251
+ height?: number;
252
+ }
253
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The manifest schema: what `designtools-manifest build` writes to
3
+ * `<system>/manifest/`: components.json, tokens.json, rules.json,
4
+ * patterns.json, taxonomy.json and assets.json.
5
+ *
6
+ * This file has no imports on purpose. @designtools/docs carries a byte-identical
7
+ * copy, so a project's docs read the manifest through the same types the tool
8
+ * wrote it with, and a test in this repo fails if the two drift.
9
+ *
10
+ * Every path is relative to the project root, with forward slashes. Arrays keep
11
+ * source order where order means something (variant axes, fixture states, token
12
+ * ramps); everything else is sorted, so a diff of the files shows only real changes.
13
+ */
14
+ export const MANIFEST_SCHEMA = "designtools.manifest/1";
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Reading the manifest: grouping components for navigation, and sorting tokens
3
+ * into the shapes the token blocks draw (semantic pairs, ramps, a type scale).
4
+ * Pure functions over the JSON; nothing here touches the DOM.
5
+ */
6
+ import { type ComponentEntry, type ComponentsManifest, type TokenEntry, type TokenTier, type TokensManifest } from "./manifest-types.js";
7
+ /**
8
+ * A `components.json` import, typed and checked. A JSON import is typed by its
9
+ * literal contents, which do not line up with the schema, so read it through here.
10
+ */
11
+ export declare function readComponents(json: unknown): ComponentsManifest;
12
+ /** A `tokens.json` import, typed and checked. */
13
+ export declare function readTokens(json: unknown): TokensManifest;
14
+ /** Where components without `@category` are listed. */
15
+ export declare const DEFAULT_CATEGORY = "Components";
16
+ /** The key the generated registry files a component under: `src/ds/badge/badge.tsx#Badge`. */
17
+ export declare function componentKey(entry: Pick<ComponentEntry, "source" | "export">): string;
18
+ /** `RadioGroup` → `radio-group`, for URLs. */
19
+ /**
20
+ * What an app writes to import it: the alias the manifest found (`@ds/button/button`),
21
+ * or the file's path when no alias reaches the system folder.
22
+ */
23
+ export declare function importOf(entry: Pick<ComponentEntry, "import" | "source">): string;
24
+ export declare function slugOf(entry: Pick<ComponentEntry, "name">): string;
25
+ export declare function findBySlug(manifest: ComponentsManifest, slug: string): ComponentEntry | undefined;
26
+ export interface CategoryGroup {
27
+ category: string;
28
+ components: ComponentEntry[];
29
+ }
30
+ /**
31
+ * Categories in name order, uncategorised last; components by name within each.
32
+ * A part without its own `@category` (CardHeader) joins the category of a
33
+ * component in the same file (Card), so a family stays together.
34
+ */
35
+ export declare function groupByCategory(manifest: ComponentsManifest): CategoryGroup[];
36
+ export interface Family {
37
+ /** The component with the `@category`: Card. */
38
+ head: ComponentEntry;
39
+ /** The rest of its file, which has none of its own: CardHeader, CardTitle. */
40
+ parts: ComponentEntry[];
41
+ }
42
+ /**
43
+ * Each category's components with their parts folded under them, so a reader
44
+ * sees nine components rather than fourteen pages. A part is a component with
45
+ * no `@category` of its own in a file whose first categorised component heads it.
46
+ */
47
+ export declare function groupFamilies(manifest: ComponentsManifest): {
48
+ category: string;
49
+ families: Family[];
50
+ }[];
51
+ export declare function tokensOfTier(manifest: TokensManifest, tier: TokenTier): TokenEntry[];
52
+ export type Mode = "light" | "dark";
53
+ /** A token's value in a mode, falling back to its mode-invariant value. */
54
+ export declare function valueIn(token: TokenEntry, mode: Mode): string | undefined;
55
+ export interface Ramp {
56
+ /** `primary` for `--color-primary-500`. */
57
+ family: string;
58
+ steps: {
59
+ step: string;
60
+ token: TokenEntry;
61
+ }[];
62
+ }
63
+ /** `--color-<family>-<step>` primitives, families in source order, steps as declared. */
64
+ export declare function ramps(manifest: TokensManifest): Ramp[];
65
+ export interface SemanticColour {
66
+ /** `--primary` */
67
+ name: string;
68
+ background: TokenEntry;
69
+ /** `--primary-foreground`, when the generator paired one. */
70
+ foreground?: TokenEntry;
71
+ }
72
+ /**
73
+ * Semantic colours (unprefixed, mode-aware: `--primary`, `--canvas`), each with
74
+ * its foreground when it has one. The `--color-*` bridge that points Tailwind
75
+ * at them is left out: it is the same colour under a second name.
76
+ */
77
+ export declare function semanticColours(manifest: TokensManifest): SemanticColour[];
78
+ export interface TypeStep {
79
+ /** `--text-sm` */
80
+ name: string;
81
+ size: TokenEntry;
82
+ lineHeight?: TokenEntry;
83
+ letterSpacing?: TokenEntry;
84
+ fontWeight?: TokenEntry;
85
+ }
86
+ /** `--text-*` sizes with the `--text-*--line-height` (and tracking, weight) Tailwind pairs with them. */
87
+ export declare function typeScale(manifest: TokensManifest): TypeStep[];
88
+ /** `--radius-md` → `md`; `--spacing` → `spacing`. */
89
+ export declare function shortName(token: Pick<TokenEntry, "name">, prefix?: string): string;
90
+ /**
91
+ * Descriptions run over several tokens (one comment above a group), so show a
92
+ * description only where it changes.
93
+ */
94
+ export declare function withGroupDescriptions<T extends {
95
+ description?: string;
96
+ }>(items: T[]): (T & {
97
+ groupDescription?: string;
98
+ })[];
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Reading the manifest: grouping components for navigation, and sorting tokens
3
+ * into the shapes the token blocks draw (semantic pairs, ramps, a type scale).
4
+ * Pure functions over the JSON; nothing here touches the DOM.
5
+ */
6
+ import { MANIFEST_SCHEMA, } from "./manifest-types.js";
7
+ /**
8
+ * A `components.json` import, typed and checked. A JSON import is typed by its
9
+ * literal contents, which do not line up with the schema, so read it through here.
10
+ */
11
+ export function readComponents(json) {
12
+ checkSchema(json, "components.json");
13
+ return json;
14
+ }
15
+ /** A `tokens.json` import, typed and checked. */
16
+ export function readTokens(json) {
17
+ checkSchema(json, "tokens.json");
18
+ return json;
19
+ }
20
+ function checkSchema(json, file) {
21
+ const schema = json?.schema;
22
+ if (schema !== MANIFEST_SCHEMA) {
23
+ throw new Error(`${file} has schema ${String(schema)}; these blocks read schema ${MANIFEST_SCHEMA}. Rebuild it with a matching @designtools/manifest.`);
24
+ }
25
+ }
26
+ /** Where components without `@category` are listed. */
27
+ export const DEFAULT_CATEGORY = "Components";
28
+ /** The key the generated registry files a component under: `src/ds/badge/badge.tsx#Badge`. */
29
+ export function componentKey(entry) {
30
+ return `${entry.source}#${entry.export}`;
31
+ }
32
+ /** `RadioGroup` → `radio-group`, for URLs. */
33
+ /**
34
+ * What an app writes to import it: the alias the manifest found (`@ds/button/button`),
35
+ * or the file's path when no alias reaches the system folder.
36
+ */
37
+ export function importOf(entry) {
38
+ return entry.import ?? entry.source.replace(/\.(tsx?|jsx?)$/, "");
39
+ }
40
+ export function slugOf(entry) {
41
+ return entry.name
42
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
43
+ .replace(/[^A-Za-z0-9]+/g, "-")
44
+ .replace(/^-|-$/g, "")
45
+ .toLowerCase();
46
+ }
47
+ export function findBySlug(manifest, slug) {
48
+ return manifest.components.find((c) => slugOf(c) === slug);
49
+ }
50
+ /**
51
+ * Categories in name order, uncategorised last; components by name within each.
52
+ * A part without its own `@category` (CardHeader) joins the category of a
53
+ * component in the same file (Card), so a family stays together.
54
+ */
55
+ export function groupByCategory(manifest) {
56
+ const fileCategory = new Map();
57
+ for (const c of manifest.components)
58
+ if (c.category && !fileCategory.has(c.source))
59
+ fileCategory.set(c.source, c.category);
60
+ const groups = new Map();
61
+ for (const c of manifest.components) {
62
+ const key = c.category ?? fileCategory.get(c.source) ?? DEFAULT_CATEGORY;
63
+ groups.set(key, [...(groups.get(key) ?? []), c]);
64
+ }
65
+ return [...groups.entries()]
66
+ .sort(([a], [b]) => (a === DEFAULT_CATEGORY ? 1 : b === DEFAULT_CATEGORY ? -1 : a < b ? -1 : a > b ? 1 : 0))
67
+ .map(([category, components]) => ({ category, components }));
68
+ }
69
+ /**
70
+ * Each category's components with their parts folded under them, so a reader
71
+ * sees nine components rather than fourteen pages. A part is a component with
72
+ * no `@category` of its own in a file whose first categorised component heads it.
73
+ */
74
+ export function groupFamilies(manifest) {
75
+ return groupByCategory(manifest).map(({ category, components }) => {
76
+ const families = [];
77
+ const heads = new Map();
78
+ for (const c of components) {
79
+ const head = heads.get(c.source);
80
+ if (head && !c.category) {
81
+ head.parts.push(c);
82
+ continue;
83
+ }
84
+ const family = { head: c, parts: [] };
85
+ families.push(family);
86
+ if (c.category && !heads.has(c.source))
87
+ heads.set(c.source, family);
88
+ }
89
+ // a part whose name sorts before its head's was listed before the head was known: it joins it now
90
+ const kept = families.filter((f) => {
91
+ const head = heads.get(f.head.source);
92
+ if (!head || head === f || f.head.category)
93
+ return true;
94
+ head.parts.push(f.head);
95
+ return false;
96
+ });
97
+ for (const f of kept)
98
+ f.parts.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
99
+ return { category, families: kept };
100
+ });
101
+ }
102
+ export function tokensOfTier(manifest, tier) {
103
+ return manifest.tokens.filter((t) => t.tier === tier);
104
+ }
105
+ /** A token's value in a mode, falling back to its mode-invariant value. */
106
+ export function valueIn(token, mode) {
107
+ return token.values[mode] ?? token.values.default;
108
+ }
109
+ /** `--color-<family>-<step>` primitives, families in source order, steps as declared. */
110
+ export function ramps(manifest) {
111
+ const out = new Map();
112
+ for (const t of manifest.tokens) {
113
+ const m = /^--color-([a-z][\w-]*?)-(\d+)$/.exec(t.name);
114
+ if (!m)
115
+ continue;
116
+ const ramp = out.get(m[1]) ?? { family: m[1], steps: [] };
117
+ ramp.steps.push({ step: m[2], token: t });
118
+ out.set(m[1], ramp);
119
+ }
120
+ return [...out.values()];
121
+ }
122
+ /**
123
+ * Semantic colours (unprefixed, mode-aware: `--primary`, `--canvas`), each with
124
+ * its foreground when it has one. The `--color-*` bridge that points Tailwind
125
+ * at them is left out: it is the same colour under a second name.
126
+ */
127
+ export function semanticColours(manifest) {
128
+ const colours = manifest.tokens.filter((t) => t.tier === "color" && !t.name.startsWith("--color-"));
129
+ const byName = new Map(colours.map((t) => [t.name, t]));
130
+ return colours
131
+ .filter((t) => !t.name.endsWith("-foreground"))
132
+ .map((background) => {
133
+ const foreground = byName.get(`${background.name}-foreground`);
134
+ return foreground ? { name: background.name, background, foreground } : { name: background.name, background };
135
+ });
136
+ }
137
+ /** `--text-*` sizes with the `--text-*--line-height` (and tracking, weight) Tailwind pairs with them. */
138
+ export function typeScale(manifest) {
139
+ const text = tokensOfTier(manifest, "text");
140
+ const byName = new Map(text.map((t) => [t.name, t]));
141
+ return text
142
+ .filter((t) => !t.name.includes("--", 2) && !/shadow/.test(t.name))
143
+ .map((size) => {
144
+ const step = { name: size.name, size };
145
+ const lh = byName.get(`${size.name}--line-height`);
146
+ const ls = byName.get(`${size.name}--letter-spacing`);
147
+ const fw = byName.get(`${size.name}--font-weight`);
148
+ if (lh)
149
+ step.lineHeight = lh;
150
+ if (ls)
151
+ step.letterSpacing = ls;
152
+ if (fw)
153
+ step.fontWeight = fw;
154
+ return step;
155
+ });
156
+ }
157
+ /** `--radius-md` → `md`; `--spacing` → `spacing`. */
158
+ export function shortName(token, prefix) {
159
+ const name = token.name.replace(/^--/, "");
160
+ return prefix && name.startsWith(`${prefix}-`) ? name.slice(prefix.length + 1) : name;
161
+ }
162
+ /**
163
+ * Descriptions run over several tokens (one comment above a group), so show a
164
+ * description only where it changes.
165
+ */
166
+ export function withGroupDescriptions(items) {
167
+ let last;
168
+ return items.map((item) => {
169
+ const changed = item.description !== last;
170
+ last = item.description;
171
+ return changed && item.description ? { ...item, groupDescription: item.description } : item;
172
+ });
173
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The markdown form of every block, generated from the manifest rather than
3
+ * converted from HTML, so the same manifest always gives the same markdown.
4
+ * A docs page answers `Accept: text/markdown` (or `.md`) with these; the agent
5
+ * tabs show them; copy-page copies them.
6
+ *
7
+ * Structure survives as typed fences (```rule, ```example, ```do, ```dont) so
8
+ * an agent can tell what each part is. Status travels with everything.
9
+ */
10
+ import { slugOf } from "./manifest.js";
11
+ import type { AdherenceReport } from "./adherence-types.js";
12
+ import type { AssetEntry, ComponentEntry, ComponentsManifest, PatternEntry, RuleEntry, TermEntry, TokensManifest } from "./manifest-types.js";
13
+ /** A generated page: the system version and commit it came from. Never a review date, which would be invented. */
14
+ export declare function generatedHeader(provenance: string): string;
15
+ /** An editorial page: who wrote it, when it was last reviewed, and whether it is settled. */
16
+ export declare function editorialHeader({ author, reviewer, reviewed, status }: {
17
+ author: string;
18
+ reviewer?: string;
19
+ reviewed: string;
20
+ status: "draft" | "published";
21
+ }): string;
22
+ /**
23
+ * A component as an agent reads it. `level` is its heading's: 1 when it is the
24
+ * whole page (`/components/button.md`), 2 inside a longer document (`context.md`),
25
+ * so a page never opens with the same heading twice.
26
+ */
27
+ export declare function componentMarkdown(entry: ComponentEntry, level?: 1 | 2): string;
28
+ export declare function coloursMarkdown(tokens: TokensManifest): string;
29
+ export declare function typeMarkdown(tokens: TokensManifest): string;
30
+ export declare function scaleMarkdown(tokens: TokensManifest): string;
31
+ export declare function ruleMarkdown(rule: RuleEntry): string;
32
+ /** A pattern; `level` as for `componentMarkdown`. */
33
+ export declare function patternMarkdown(pattern: PatternEntry, level?: 1 | 2): string;
34
+ export declare function glossaryMarkdown(terms: TermEntry[]): string;
35
+ export declare function assetsMarkdown(assets: AssetEntry[]): string;
36
+ /** `.mxa/stack.json` baselines, or anything shaped like them: a table of name and target. */
37
+ export declare function standardsMarkdown(baselines: Record<string, unknown>): string;
38
+ /** The adherence report, as a page: totals, then routes. It informs; it never blocks. */
39
+ export declare function adherenceMarkdown(report: AdherenceReport): string;
40
+ /** Everything an agent needs, in one file: tokens first, then rules, patterns and components by category. */
41
+ export declare function systemMarkdown(input: {
42
+ components: ComponentsManifest;
43
+ tokens?: TokensManifest;
44
+ rules?: RuleEntry[];
45
+ patterns?: PatternEntry[];
46
+ terms?: TermEntry[];
47
+ }, title?: string, provenance?: string): string;
48
+ /** Links an agent outside the repo can follow to the exact data. */
49
+ export declare function manifestLinks(base: string): string;
50
+ export { slugOf };