@theme-registry/refract 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -187,13 +187,24 @@ stylesheets by default, so the page is one self-contained file that survives bei
187
187
  { name: "css", adapter: createCssAdapter(), outDir: "dist/theme", preview: true }
188
188
  ```
189
189
 
190
- Token plates colours, the type ramp, spacing, radii, shadows, breakpoints render from the
191
- format-neutral token export, so **every** adapter gets them. Live recipe plates additionally need
192
- output a browser can load as-is, which today means CSS; an SCSS/styled-components/JSON target still
193
- renders every token and names every recipe, and says why it can't render them live. (For a live
194
- design-review page from an SC or SCSS theme, add a CSS target to the same config — same recipes,
195
- same core.) The page follows the target's `emit` mode, and gains a light/dark toggle when the theme
196
- declares modes plus frame-width buttons when it declares breakpoints. Off by default.
190
+ It reads as a style guide, not a token dump: a sticky section rail, colour families as contiguous
191
+ ladders with live WCAG contrast readouts on each `text` pairing, the type ramp set in its own sizes,
192
+ spacing shown as a measure *and* as an applied inset, a **state matrix** per recipe, and a
193
+ copy-on-click identifier beside every specimen. Sections appear only when the theme has tokens of
194
+ that kind.
195
+
196
+ Token plates render from the format-neutral token export, so **every** adapter gets them. Live
197
+ recipe plates additionally need output a browser can load as-is, which today means CSS; an
198
+ SCSS/styled-components/JSON target still renders every token and names every recipe, and says why it
199
+ can't render them live. (For a live design-review page from an SC or SCSS theme, add a CSS target to
200
+ the same config — same recipes, same core.)
201
+
202
+ Three things only a compiler's specimen sheet can show: **states** side by side (a CSS pseudo-class
203
+ can't be triggered from markup, so the adapter emits a parallel pinnable rule that is inlined into
204
+ the page and never added to the stylesheet you ship), an **appearance-mode diff** of the tokens that
205
+ actually carry an override, and **composition** broken into its parts — each class in a component's
206
+ identity attributed to the recipe it came from. Bare elements themed by the `globals` subsystem get
207
+ their own prose specimen, since they carry no class at all. Off by default.
197
208
 
198
209
  Its machine-facing sibling is `guide: true`, which writes an `llms.txt` + `manifest.json`
199
210
  consumption guide into the same folder.
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Human-facing preview (Node-only) — render a single `preview.html` specimen of a built theme.
2
+ * Human-facing preview (Node-only) — render a single `preview.html` **style-guide specimen** of a
3
+ * built theme.
3
4
  *
4
5
  * The audience-flipped sibling of `guide.ts`: that one writes `llms.txt` + `manifest.json` for a
5
6
  * downstream *agent*; this one writes a page a person opens, forwards, or hands a designer to answer
@@ -11,18 +12,28 @@
11
12
  * - **Token plates (universal).** Rendered from the format-neutral DTCG export — the same document
12
13
  * `guide` embeds — so they depend on nothing the adapter emitted. Every adapter, including a
13
14
  * third-party one that has never heard of previews, gets these on day one. The walk is generic
14
- * over `$type`, so a new subsystem's tokens show up without touching this file.
15
+ * over `$type` with per-group specimen overrides, so a new subsystem's tokens still appear (in a
16
+ * catch-all section) without touching this file.
15
17
  *
16
18
  * - **Recipe plates (live).** Require the emitted artifacts to be browser-loadable as-is, which the
17
19
  * adapter alone can answer — see {@link PreviewDescriptor}. Today that means CSS; SCSS needs
18
20
  * compiling, styled-components emits JS modules, JSON has no rendered form. Those adapters say so
19
21
  * in their own words and the page degrades to tokens-only rather than rendering unstyled boxes.
20
22
  *
23
+ * Two rules the layout is built on, both learned the hard way:
24
+ *
25
+ * 1. **The chrome is chromatically silent.** The theme owns every saturated pixel; the tool around
26
+ * it is neutral, and specimen geometry uses a dedicated mid-tone (`--rfp-spec`) rather than the
27
+ * nearest neutral to hand. Filling a swatch with the page ground makes it vanish the moment the
28
+ * ground and the stage converge — which is exactly what happens in dark mode.
29
+ * 2. **Never assume the theme is light.** The emitted stylesheet is inlined, so a theme with a
30
+ * `dark` mode restyles itself under the toggle; the chrome has to survive both, and the page
31
+ * must not hard-code a light ground under it.
32
+ *
21
33
  * Distribution convention deliberately INVERTS `guide`'s: the page **inlines** its stylesheets by
22
34
  * default (`inline: false` opts out). `guide` is machine-facing and lives next to the code it
23
35
  * documents, so relative references are right there; a preview gets moved, attached, and forwarded,
24
- * and has to keep working. `inline: false` serves the dev loop, where the page should reflect a
25
- * rebuilt stylesheet on refresh.
36
+ * and has to keep working.
26
37
  */
27
38
  import type { ThemeModel } from "../core/model/model";
28
39
  import type { NormalizedEmit, PreviewDescriptor, UsageDescriptor } from "../core/ThemeAdapter";
@@ -36,15 +47,15 @@ export type PreviewConfig = {
36
47
  * reflects a rebuilt stylesheet on refresh.
37
48
  */
38
49
  readonly inline?: boolean;
39
- /** Page heading + `<title>` (default `"<format> theme preview"`). */
50
+ /** Page heading + `<title>` (default the theme name, else `"<format> theme"`). */
40
51
  readonly title?: string;
41
52
  };
42
53
  export interface PreviewOptions extends PreviewConfig {
43
54
  /** The file names actually written for this target — the guard against referencing a missing artifact. */
44
55
  readonly files: readonly string[];
45
- /** Emitted file contents by name, for inlining. A name missing here falls back to a `<link>`. */
56
+ /** Emitted file contents by name, for inlining + the byte counts in the masthead. */
46
57
  readonly contents?: Readonly<Record<string, string>>;
47
- /** The normalized emit plan — reported in the header and used for layout semantics only. */
58
+ /** The normalized emit plan — reported in the masthead and used for layout semantics only. */
48
59
  readonly plan: NormalizedEmit;
49
60
  }
50
61
  export interface PreviewOutput {
@@ -58,16 +69,9 @@ export interface PreviewSource {
58
69
  readonly preview?: PreviewDescriptor;
59
70
  /** A DTCG document (from `toDTCG`) — the token-plate source. */
60
71
  readonly tokens: unknown;
61
- /** The built model — supplies appearance modes and breakpoints for the page controls. */
72
+ /** The built model — supplies appearance modes, breakpoints, and the globals element selectors. */
62
73
  readonly model: ThemeModel;
63
74
  }
64
75
  /** Distinct appearance modes across every property's `modes` list, in first-appearance order. */
65
76
  export declare function collectModes(model: ThemeModel): string[];
66
- /**
67
- * Build the preview artifact. Pure — returns `filename → contents` for the build layer to write.
68
- *
69
- * The adapter's declared `stylesheets` are intersected with `options.files` (what was actually
70
- * written), so a descriptor that drifts from `emit()` degrades to tokens-only instead of producing a
71
- * page that silently references a file that isn't there.
72
- */
73
77
  export declare function buildPreview(source: PreviewSource, options: PreviewOptions): PreviewOutput;