@theme-registry/refract 0.1.6 → 0.1.8
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 +25 -1
- package/dist/build/config.d.ts +9 -0
- package/dist/build/emitTheme.d.ts +3 -0
- package/dist/build/index.d.ts +1 -0
- package/dist/build/preview.d.ts +73 -0
- package/dist/build.cjs.js +1 -1
- package/dist/build.cjs.js.map +1 -1
- package/dist/build.esm.js +1 -1
- package/dist/build.esm.js.map +1 -1
- package/dist/cli.js +403 -8
- package/dist/cli.js.map +1 -1
- package/dist/core/ThemeAdapter.d.ts +58 -0
- package/package.json +2 -2
- package/skills/adapter-scaffold/SKILL.md +10 -0
- package/skills/build-config/SKILL.md +29 -2
- package/skills/consuming-the-output/SKILL.md +5 -0
package/README.md
CHANGED
|
@@ -45,7 +45,10 @@ npm install @theme-registry/refract
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
`styled-components` and `typescript` are **optional** peers — only needed if you use the
|
|
48
|
-
styled-components adapter or the `.ts` build config, respectively.
|
|
48
|
+
styled-components adapter or the `.ts` build config, respectively. Install typescript as
|
|
49
|
+
**`typescript@5`**: a bare `npm i -D typescript` now resolves to 7.x, the native port, whose main
|
|
50
|
+
entry exports only a version string — the compiler API a `.ts` config is transpiled with sits behind
|
|
51
|
+
its `./unstable/*` subpaths. A `.mjs` or `.js` config never loads typescript at all.
|
|
49
52
|
|
|
50
53
|
## Scaffold a theme
|
|
51
54
|
|
|
@@ -174,6 +177,27 @@ Each target's `emit` picks the output shape (CSS adapter):
|
|
|
174
177
|
| `subsystem` | a styles+variables pair per subsystem (`colors.css`, `colors.variables.css`, …) |
|
|
175
178
|
| `components` | each component variant flattened into one self-contained file (`inline: true` bakes values; `inline: false` emits `var(--…)` + a tree-shaken `variables.css`) |
|
|
176
179
|
|
|
180
|
+
### `preview` — see what you built
|
|
181
|
+
|
|
182
|
+
Set `preview: true` on any target and `refract build` also writes a `preview.html` into its
|
|
183
|
+
`outDir`: a rendered specimen you double-click, forward, or hand a designer. It inlines its
|
|
184
|
+
stylesheets by default, so the page is one self-contained file that survives being moved.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
{ name: "css", adapter: createCssAdapter(), outDir: "dist/theme", preview: true }
|
|
188
|
+
```
|
|
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.
|
|
197
|
+
|
|
198
|
+
Its machine-facing sibling is `guide: true`, which writes an `llms.txt` + `manifest.json`
|
|
199
|
+
consumption guide into the same folder.
|
|
200
|
+
|
|
177
201
|
## DTCG round-trip
|
|
178
202
|
|
|
179
203
|
The `./dtcg` subpath reads/writes the W3C Design Token Community Group `tokens.json`
|
package/dist/build/config.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { RawTheme } from "../core/rawTheme";
|
|
|
3
3
|
import type { MediaConfig } from "../core/media";
|
|
4
4
|
import type { UnitsConfig } from "../core/units";
|
|
5
5
|
import type { GuideConfig } from "./emitTheme";
|
|
6
|
+
import type { PreviewConfig } from "./preview";
|
|
6
7
|
/** One emit target: an adapter + where to write it, plus which shared vendored helpers it wants. */
|
|
7
8
|
export interface EmitTarget {
|
|
8
9
|
readonly adapter: ThemeAdapter;
|
|
@@ -19,6 +20,14 @@ export interface EmitTarget {
|
|
|
19
20
|
* file names or adds a `packageName` for a by-specifier import overlay. Off by default.
|
|
20
21
|
*/
|
|
21
22
|
readonly guide?: boolean | GuideConfig;
|
|
23
|
+
/**
|
|
24
|
+
* §20 — emit a human-facing `preview.html` specimen into this target's `outDir`: token plates
|
|
25
|
+
* rendered from the format-neutral export (so every adapter gets them) plus live recipe plates
|
|
26
|
+
* when the adapter's output is browser-loadable (CSS today). The audience-flipped sibling of
|
|
27
|
+
* `guide`. `true` uses defaults; an object tunes the filename/title or opts out of inlining.
|
|
28
|
+
* Off by default.
|
|
29
|
+
*/
|
|
30
|
+
readonly preview?: boolean | PreviewConfig;
|
|
22
31
|
}
|
|
23
32
|
/** The `theme.config` shape: the raw theme + one or more emit targets. */
|
|
24
33
|
export interface ThemeConfig {
|
|
@@ -2,6 +2,7 @@ import type { ThemeAdapter, Emit } from "../core/ThemeAdapter";
|
|
|
2
2
|
import type { RawTheme } from "../core/rawTheme";
|
|
3
3
|
import type { MediaConfig } from "../core/media";
|
|
4
4
|
import type { UnitsConfig } from "../core/units";
|
|
5
|
+
import { type PreviewConfig } from "./preview";
|
|
5
6
|
/** Opt-in self-documenting output config (§C). `true` uses defaults; the object tunes names/overlay. */
|
|
6
7
|
export type GuideConfig = {
|
|
7
8
|
/** Published package specifier — adds a by-specifier import overlay to the guide (else relative-only). */
|
|
@@ -30,6 +31,8 @@ export interface EmitThemeOptions {
|
|
|
30
31
|
readonly baseFontSize?: number;
|
|
31
32
|
/** §C — emit a self-documenting `llms.txt` + `manifest.json` into `outDir`. Off by default. */
|
|
32
33
|
readonly guide?: boolean | GuideConfig;
|
|
34
|
+
/** §20 — emit a human-facing `preview.html` specimen into `outDir`. Off by default. */
|
|
35
|
+
readonly preview?: boolean | PreviewConfig;
|
|
33
36
|
}
|
|
34
37
|
export interface EmitThemeResult {
|
|
35
38
|
readonly outDir: string;
|
package/dist/build/index.d.ts
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-facing preview (Node-only) — render a single `preview.html` specimen of a built theme.
|
|
3
|
+
*
|
|
4
|
+
* The audience-flipped sibling of `guide.ts`: that one writes `llms.txt` + `manifest.json` for a
|
|
5
|
+
* downstream *agent*; this one writes a page a person opens, forwards, or hands a designer to answer
|
|
6
|
+
* "what does this theme actually look like?". Both are opt-in per emit target and land in the same
|
|
7
|
+
* `outDir`, so they travel with any distribution form.
|
|
8
|
+
*
|
|
9
|
+
* Two plate tiers, split by CAPABILITY rather than by adapter name:
|
|
10
|
+
*
|
|
11
|
+
* - **Token plates (universal).** Rendered from the format-neutral DTCG export — the same document
|
|
12
|
+
* `guide` embeds — so they depend on nothing the adapter emitted. Every adapter, including a
|
|
13
|
+
* 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
|
+
*
|
|
16
|
+
* - **Recipe plates (live).** Require the emitted artifacts to be browser-loadable as-is, which the
|
|
17
|
+
* adapter alone can answer — see {@link PreviewDescriptor}. Today that means CSS; SCSS needs
|
|
18
|
+
* compiling, styled-components emits JS modules, JSON has no rendered form. Those adapters say so
|
|
19
|
+
* in their own words and the page degrades to tokens-only rather than rendering unstyled boxes.
|
|
20
|
+
*
|
|
21
|
+
* Distribution convention deliberately INVERTS `guide`'s: the page **inlines** its stylesheets by
|
|
22
|
+
* default (`inline: false` opts out). `guide` is machine-facing and lives next to the code it
|
|
23
|
+
* 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.
|
|
26
|
+
*/
|
|
27
|
+
import type { ThemeModel } from "../core/model/model";
|
|
28
|
+
import type { NormalizedEmit, PreviewDescriptor, UsageDescriptor } from "../core/ThemeAdapter";
|
|
29
|
+
/** Opt-in preview config (`EmitTarget.preview`). `true` uses every default. */
|
|
30
|
+
export type PreviewConfig = {
|
|
31
|
+
/** Output filename (default `"preview.html"`). */
|
|
32
|
+
readonly file?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Inline the emitted stylesheets into the page so it is a single shareable file (default `true`).
|
|
35
|
+
* `false` emits relative `<link>`s instead — the page then only works beside its `outDir`, but it
|
|
36
|
+
* reflects a rebuilt stylesheet on refresh.
|
|
37
|
+
*/
|
|
38
|
+
readonly inline?: boolean;
|
|
39
|
+
/** Page heading + `<title>` (default `"<format> theme preview"`). */
|
|
40
|
+
readonly title?: string;
|
|
41
|
+
};
|
|
42
|
+
export interface PreviewOptions extends PreviewConfig {
|
|
43
|
+
/** The file names actually written for this target — the guard against referencing a missing artifact. */
|
|
44
|
+
readonly files: readonly string[];
|
|
45
|
+
/** Emitted file contents by name, for inlining. A name missing here falls back to a `<link>`. */
|
|
46
|
+
readonly contents?: Readonly<Record<string, string>>;
|
|
47
|
+
/** The normalized emit plan — reported in the header and used for layout semantics only. */
|
|
48
|
+
readonly plan: NormalizedEmit;
|
|
49
|
+
}
|
|
50
|
+
export interface PreviewOutput {
|
|
51
|
+
/** filename → contents, ready for the build layer to write into `outDir`. */
|
|
52
|
+
readonly files: Record<string, string>;
|
|
53
|
+
}
|
|
54
|
+
export interface PreviewSource {
|
|
55
|
+
/** The adapter's usage descriptor — supplies the format id and the real recipe identities. */
|
|
56
|
+
readonly usage: UsageDescriptor;
|
|
57
|
+
/** The adapter's preview descriptor, or `undefined` when it doesn't implement `describePreview`. */
|
|
58
|
+
readonly preview?: PreviewDescriptor;
|
|
59
|
+
/** A DTCG document (from `toDTCG`) — the token-plate source. */
|
|
60
|
+
readonly tokens: unknown;
|
|
61
|
+
/** The built model — supplies appearance modes and breakpoints for the page controls. */
|
|
62
|
+
readonly model: ThemeModel;
|
|
63
|
+
}
|
|
64
|
+
/** Distinct appearance modes across every property's `modes` list, in first-appearance order. */
|
|
65
|
+
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
|
+
export declare function buildPreview(source: PreviewSource, options: PreviewOptions): PreviewOutput;
|