@theme-registry/refract 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.
- package/LICENSE +21 -0
- package/dist/_createTheme-255ff48e.esm.js +2 -0
- package/dist/_createTheme-255ff48e.esm.js.map +1 -0
- package/dist/_createTheme-41c01033.cjs.js +2 -0
- package/dist/_createTheme-41c01033.cjs.js.map +1 -0
- package/dist/_errors-be768b25.cjs.js +2 -0
- package/dist/_errors-be768b25.cjs.js.map +1 -0
- package/dist/_errors-d75a5c74.esm.js +2 -0
- package/dist/_errors-d75a5c74.esm.js.map +1 -0
- package/dist/adapter-kit.cjs.js +2 -0
- package/dist/adapter-kit.cjs.js.map +1 -0
- package/dist/adapter-kit.d.ts +88 -0
- package/dist/adapter-kit.esm.js +2 -0
- package/dist/adapter-kit.esm.js.map +1 -0
- package/dist/build/auditCommand.d.ts +19 -0
- package/dist/build/buildCommand.d.ts +23 -0
- package/dist/build/cli.d.ts +2 -0
- package/dist/build/config.d.ts +58 -0
- package/dist/build/diff.d.ts +56 -0
- package/dist/build/diffCommand.d.ts +29 -0
- package/dist/build/emit.d.ts +20 -0
- package/dist/build/emitTheme.d.ts +39 -0
- package/dist/build/guide.d.ts +34 -0
- package/dist/build/importCommand.d.ts +42 -0
- package/dist/build/index.d.ts +33 -0
- package/dist/build/init.d.ts +32 -0
- package/dist/build/paths.d.ts +42 -0
- package/dist/build/skillsCommand.d.ts +53 -0
- package/dist/build/tokensCommand.d.ts +17 -0
- package/dist/build/vendor.d.ts +39 -0
- package/dist/build.cjs.js +2 -0
- package/dist/build.cjs.js.map +1 -0
- package/dist/build.esm.js +2 -0
- package/dist/build.esm.js.map +1 -0
- package/dist/cli.js +8250 -0
- package/dist/cli.js.map +1 -0
- package/dist/color-math.cjs.js +2 -0
- package/dist/color-math.cjs.js.map +1 -0
- package/dist/color-math.esm.js +2 -0
- package/dist/color-math.esm.js.map +1 -0
- package/dist/core/ThemeAdapter.d.ts +234 -0
- package/dist/core/createTheme.d.ts +96 -0
- package/dist/core/cssProperties.d.ts +8 -0
- package/dist/core/defineAdapter.d.ts +25 -0
- package/dist/core/derive/crossProperty.d.ts +31 -0
- package/dist/core/derive/index.d.ts +11 -0
- package/dist/core/derive/resolveTokens.d.ts +27 -0
- package/dist/core/errors.d.ts +24 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/media/containers.d.ts +20 -0
- package/dist/core/media/defaults.d.ts +3 -0
- package/dist/core/media/descriptors.d.ts +12 -0
- package/dist/core/media/index.d.ts +11 -0
- package/dist/core/media/queries.d.ts +20 -0
- package/dist/core/model/buildModel.d.ts +116 -0
- package/dist/core/model/index.d.ts +14 -0
- package/dist/core/model/interpreted.d.ts +37 -0
- package/dist/core/model/mergeRuleSet.d.ts +68 -0
- package/dist/core/model/model.d.ts +260 -0
- package/dist/core/noopAdapter.d.ts +26 -0
- package/dist/core/normalize/index.d.ts +15 -0
- package/dist/core/normalize/properties.d.ts +20 -0
- package/dist/core/normalize/recipeResolver.d.ts +19 -0
- package/dist/core/normalize/recipes.d.ts +38 -0
- package/dist/core/normalize/responsive.d.ts +40 -0
- package/dist/core/normalize/types.d.ts +261 -0
- package/dist/core/rawTheme.d.ts +53 -0
- package/dist/core/ref.d.ts +13 -0
- package/dist/core/subsystem.d.ts +115 -0
- package/dist/core/types.d.ts +31 -0
- package/dist/core/units.d.ts +93 -0
- package/dist/dtcg/export.d.ts +48 -0
- package/dist/dtcg/import.d.ts +43 -0
- package/dist/dtcg/index.d.ts +21 -0
- package/dist/dtcg/parse.d.ts +6 -0
- package/dist/dtcg/types.d.ts +69 -0
- package/dist/dtcg.cjs.js +2 -0
- package/dist/dtcg.cjs.js.map +1 -0
- package/dist/dtcg.esm.js +2 -0
- package/dist/dtcg.esm.js.map +1 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/subsystems/animation/index.d.ts +13 -0
- package/dist/subsystems/animation/recipes.d.ts +20 -0
- package/dist/subsystems/animation/types.d.ts +52 -0
- package/dist/subsystems/borders/index.d.ts +10 -0
- package/dist/subsystems/borders/recipes.d.ts +29 -0
- package/dist/subsystems/borders/types.d.ts +50 -0
- package/dist/subsystems/colors/audit.d.ts +67 -0
- package/dist/subsystems/colors/colorInput.d.ts +17 -0
- package/dist/subsystems/colors/index.d.ts +12 -0
- package/dist/subsystems/colors/keywords.d.ts +9 -0
- package/dist/subsystems/colors/normalize.d.ts +26 -0
- package/dist/subsystems/colors/recipes.d.ts +21 -0
- package/dist/subsystems/colors/types.d.ts +98 -0
- package/dist/subsystems/colors/utils.d.ts +104 -0
- package/dist/subsystems/components/index.d.ts +13 -0
- package/dist/subsystems/components/recipes.d.ts +22 -0
- package/dist/subsystems/components/types.d.ts +46 -0
- package/dist/subsystems/effects/index.d.ts +9 -0
- package/dist/subsystems/effects/recipes.d.ts +24 -0
- package/dist/subsystems/effects/types.d.ts +63 -0
- package/dist/subsystems/effects/utils.d.ts +57 -0
- package/dist/subsystems/globals/index.d.ts +21 -0
- package/dist/subsystems/globals/presets.d.ts +33 -0
- package/dist/subsystems/globals/types.d.ts +48 -0
- package/dist/subsystems/index.d.ts +21 -0
- package/dist/subsystems/layout/index.d.ts +14 -0
- package/dist/subsystems/layout/normalize.d.ts +35 -0
- package/dist/subsystems/layout/recipes.d.ts +16 -0
- package/dist/subsystems/layout/structural.d.ts +37 -0
- package/dist/subsystems/layout/types.d.ts +154 -0
- package/dist/subsystems/typography/index.d.ts +9 -0
- package/dist/subsystems/typography/normalize.d.ts +17 -0
- package/dist/subsystems/typography/recipes.d.ts +21 -0
- package/dist/subsystems/typography/types.d.ts +49 -0
- package/package.json +83 -0
- package/skills/adapter-scaffold/SKILL.md +85 -0
- package/skills/adapter-usage/SKILL.md +75 -0
- package/skills/build-config/SKILL.md +77 -0
- package/skills/colors/SKILL.md +134 -0
- package/skills/consuming-the-output/SKILL.md +62 -0
- package/skills/dtcg-import/SKILL.md +76 -0
- package/skills/layout/SKILL.md +65 -0
- package/skills/overrides-and-child-themes/SKILL.md +70 -0
- package/skills/recipes-and-composition/SKILL.md +110 -0
- package/skills/theme-authoring/SKILL.md +107 -0
- package/skills/theme-foundations/SKILL.md +127 -0
- package/skills/troubleshooting/SKILL.md +97 -0
- package/skills/typography/SKILL.md +66 -0
- package/skills/visual-effects/SKILL.md +96 -0
- package/src/subsystems/colors/utils.ts +299 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { DerivationModifier, ExternalProperty, ModeOverride, NormalizedPropertyValue, RecipeBlock, ResponsiveOverride } from "../../core/normalize";
|
|
2
|
+
import type { RGBTuple } from "./utils";
|
|
3
|
+
export type { AdjustDials } from "./utils";
|
|
4
|
+
/**
|
|
5
|
+
* A colour's authored **base** value — a hex string (`"#4dabf7"` / `"#4af"`), an `[r, g, b]` tuple
|
|
6
|
+
* (0–255), or any CSS colour string: `oklch()`, `hsl()/hsla()`, `rgb()/rgba()`, or a named keyword
|
|
7
|
+
* (`"rebeccapurple"`). All are normalized to the canonical `rgb()` form at build (derivation runs in
|
|
8
|
+
* OKLCH). A `var(--…)` is **rejected** — it can't be tonally derived at build time; borrow an external
|
|
9
|
+
* token instead (`{ external: … }`). Tuple/keyword/function forms are coerced at normalize time.
|
|
10
|
+
*/
|
|
11
|
+
export type ColorInput = string | RGBTuple;
|
|
12
|
+
/**
|
|
13
|
+
* A **derivation spec** variant (§13.3, §20.4, dec.2) — a named variant derived from a source colour
|
|
14
|
+
* by an ordered `modifiers` chain of single-key `{ [fn]: args }` dials (`darken`/`lighten`/`alpha`/
|
|
15
|
+
* `adjust`/`setL`/`rotateHue`): `value = modifiers.reduce((v, {fn,arg}) => fn(v, arg), resolve(ref))`.
|
|
16
|
+
* `ref` names the source token (defaults to the property's own base; may point to another variant/step).
|
|
17
|
+
* `darken`/`lighten` shift OKLCH lightness by N points (alpha preserved); `alpha` sets absolute opacity
|
|
18
|
+
* (`{ alpha: 40 }` ⇒ 40% opaque); `adjust` places an absolute lightness and/or scales chroma and/or
|
|
19
|
+
* rotates hue in one shot (see {@link AdjustDials}).
|
|
20
|
+
*/
|
|
21
|
+
export type PaletteDerivationSpec = {
|
|
22
|
+
ref?: string;
|
|
23
|
+
modifiers: DerivationModifier[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* A built-in colour-harmony scheme — rotations of the base's hue around the perceptual wheel, each
|
|
27
|
+
* generated variant holding the base's lightness and chroma (only the hue turns).
|
|
28
|
+
*/
|
|
29
|
+
export type HarmonyScheme = "complement" | "analogous" | "split-complement" | "triadic" | "tetradic";
|
|
30
|
+
/**
|
|
31
|
+
* The palette-level `harmony` option (§20.5). The **string** form uses each scheme's default member
|
|
32
|
+
* names (`"triadic"` → `triadic1` / `triadic2`); the **object** form renames them positionally
|
|
33
|
+
* (`{ triadic: ["mint", "coral"] }` → `mint` / `coral`). Exactly one scheme per colour.
|
|
34
|
+
*/
|
|
35
|
+
export type HarmonyOption = HarmonyScheme | Partial<Record<HarmonyScheme, string[]>>;
|
|
36
|
+
/**
|
|
37
|
+
* One authored variant value — a literal colour, a {@link PaletteDerivationSpec}, or the extended
|
|
38
|
+
* `{ base, …extra }` form (for literal variants carrying siblings like `text`).
|
|
39
|
+
*/
|
|
40
|
+
export type PaletteVariantInput = ColorInput | PaletteDerivationSpec | ({
|
|
41
|
+
base: ColorInput;
|
|
42
|
+
} & Record<string, unknown>);
|
|
43
|
+
/**
|
|
44
|
+
* Colors' property extras — the palette-synthesis config that rides alongside a colour value.
|
|
45
|
+
* `steps` is **numeric only** and defines an absolute OKLCH lightness ladder (§20.2): each
|
|
46
|
+
* Tailwind-style label maps to a fixed lightness via `L = (1000 − label) / 10` (low = light, high =
|
|
47
|
+
* dark), so the same label reads at the same lightness across every palette. Named tonal variants
|
|
48
|
+
* (`light`/`lighter`/`dark`/`darker`) are auto-generated when no `steps` are declared; they stay
|
|
49
|
+
* relative, compounding `lightenBy`/`darkenBy` as OKLCH ΔL points (which do NOT apply to numeric
|
|
50
|
+
* steps). (`variants` is NOT here — it's a first-class key on {@link PaletteExtendedProperty},
|
|
51
|
+
* widened to accept derivation specs.)
|
|
52
|
+
*/
|
|
53
|
+
export type PalettePropertyExtras = {
|
|
54
|
+
text?: ColorInput;
|
|
55
|
+
steps?: number[];
|
|
56
|
+
lightenBy?: number;
|
|
57
|
+
darkenBy?: number;
|
|
58
|
+
harmony?: HarmonyOption;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Colors' extended-property authoring shape — mirrors core's `ExtendedProperty` but with a
|
|
62
|
+
* {@link ColorInput} base (hex string or `[r,g,b]` tuple) and a `variants` map widened to accept
|
|
63
|
+
* {@link PaletteVariantInput} (literal colours, derivation specs, or extended literals). Coerced to
|
|
64
|
+
* the canonical core shape (`base: string`) at normalize time.
|
|
65
|
+
*/
|
|
66
|
+
export type PaletteExtendedProperty = {
|
|
67
|
+
base: ColorInput;
|
|
68
|
+
responsive?: ResponsiveOverride<ColorInput, PalettePropertyExtras>[];
|
|
69
|
+
variants?: Record<string, PaletteVariantInput>;
|
|
70
|
+
modes?: ModeOverride<ColorInput, PalettePropertyExtras>[];
|
|
71
|
+
} & PalettePropertyExtras;
|
|
72
|
+
export type PalettePropertyValue = ColorInput | PaletteExtendedProperty | ExternalProperty;
|
|
73
|
+
export type NormalizedPaletteValue = NormalizedPropertyValue<string, PalettePropertyExtras>;
|
|
74
|
+
/**
|
|
75
|
+
* The palette recipe declaration shape — colour-bearing CSS properties whose values
|
|
76
|
+
* name a palette reference (`"primary"`, `"primary.text"`, `"neutral.light"`) or a
|
|
77
|
+
* literal. Any additional style property is allowed (passed through as a literal).
|
|
78
|
+
*/
|
|
79
|
+
export type PaletteRecipeValue = string | number;
|
|
80
|
+
export type PaletteRecipeProps = {
|
|
81
|
+
background?: PaletteRecipeValue;
|
|
82
|
+
backgroundColor?: PaletteRecipeValue;
|
|
83
|
+
color?: PaletteRecipeValue;
|
|
84
|
+
borderColor?: PaletteRecipeValue;
|
|
85
|
+
outlineColor?: PaletteRecipeValue;
|
|
86
|
+
[property: string]: PaletteRecipeValue | undefined;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* The authored `raw.colors` slice (§8a). An **open** map: keys are arbitrary palette names
|
|
90
|
+
* (`primary`, `neutral`, …), each a {@link PalettePropertyValue} — a bare hex/ref string, an
|
|
91
|
+
* `[r,g,b]` tuple, or a full `ExtendedProperty` with `text` / `steps` / `variants` / `responsive`.
|
|
92
|
+
* The reserved `recipes` key is a {@link RecipeBlock} of palette recipes. Authoring type only —
|
|
93
|
+
* the spine still consumes the slice as `Record<string, unknown>`.
|
|
94
|
+
*/
|
|
95
|
+
export interface ColorsRaw {
|
|
96
|
+
recipes?: RecipeBlock<PaletteRecipeProps>;
|
|
97
|
+
[palette: string]: PalettePropertyValue | RecipeBlock<PaletteRecipeProps> | undefined;
|
|
98
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure colour math for palette step + variant synthesis.
|
|
3
|
+
*
|
|
4
|
+
* Lightness / hue / chroma work runs in **OKLCH** (a perceptual space) via Björn Ottosson's
|
|
5
|
+
* public-domain matrices — parse → sRGB → linear → OKLab → OKLCH → apply → gamut-map → linear →
|
|
6
|
+
* sRGB → quantize → serialize — so equal lightness steps look even and one lightness reads the same
|
|
7
|
+
* across hues. hex / `rgba()` strings are only touched at the boundary (`parseColor` in,
|
|
8
|
+
* `serializeColor` out). `lighten` / `darken` shift OKLCH lightness by ΔL points; `setL` places an
|
|
9
|
+
* absolute lightness; `rotateHue` / `complement` turn the hue; `alpha` sets opacity. All are
|
|
10
|
+
* string-in / string-out so the same fns run at normalize time (baking the cached value) and later
|
|
11
|
+
* in the derivation registry — AND are vendored to consumers (see `build/vendor.ts`) so a value
|
|
12
|
+
* computed live in the app matches the emitted CSS variable. Kept dependency-free for that vendoring.
|
|
13
|
+
*/
|
|
14
|
+
/** An `[r, g, b]` channel triple, each `0–255`. */
|
|
15
|
+
export type RGBTuple = readonly [number, number, number];
|
|
16
|
+
/** An `[r, g, b, a]` quad — channels `0–255`, alpha `0–1`. */
|
|
17
|
+
export type RGBATuple = readonly [number, number, number, number];
|
|
18
|
+
/** A colour authored/worked as a tuple — opaque `[r,g,b]` or translucent `[r,g,b,a]`. */
|
|
19
|
+
export type ColorTuple = RGBTuple | RGBATuple;
|
|
20
|
+
/** Parse a 3- or 6-digit hex string (with or without `#`) into an `[r, g, b]` tuple. */
|
|
21
|
+
export declare const convertHexToRGB: (hex: string) => RGBTuple;
|
|
22
|
+
/** Serialize an `[r, g, b]` tuple back to a `#rrggbb` string, clamping each channel to `0–255`. */
|
|
23
|
+
export declare const convertRgbToHex: (rgb: RGBTuple) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Parse any canonical colour string this subsystem produces — a 3/6-digit hex **or** an
|
|
26
|
+
* `rgb()` / `rgba()` string — into `{ rgb, a }` (alpha defaults to `1`). This is the boundary
|
|
27
|
+
* gate; a value that isn't parseable rgb (e.g. a bare CSS keyword or `var(--…)`) throws, so
|
|
28
|
+
* callers can surface a friendly "this colour can't be derived from" error.
|
|
29
|
+
*/
|
|
30
|
+
export declare const parseColor: (value: string) => {
|
|
31
|
+
rgb: RGBTuple;
|
|
32
|
+
a: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Serialize `[r, g, b]` (+ optional alpha) to the canonical CSS string — always `rgb(r, g, b)`
|
|
36
|
+
* when fully opaque, else `rgba(r, g, b, a)`. The single serialization point for the subsystem, so
|
|
37
|
+
* the Model (and every adapter + `resolveToken`) always carries one canonical `rgb()/rgba()` form
|
|
38
|
+
* per colour — never hex. (`convertRgbToHex` remains for the vendored consumer helper + input parsing.)
|
|
39
|
+
*/
|
|
40
|
+
export declare const serializeColor: (rgb: RGBTuple, a?: number) => string;
|
|
41
|
+
/** Whether a string is a 3- or 6-digit `#`-prefixed hex colour. */
|
|
42
|
+
export declare const isHexColor: (value: string) => boolean;
|
|
43
|
+
/** An OKLCH colour — perceptual lightness `L` (0–100), chroma `C` (≥ 0), hue `h` (degrees, 0–360). */
|
|
44
|
+
export type OKLCH = {
|
|
45
|
+
L: number;
|
|
46
|
+
C: number;
|
|
47
|
+
h: number;
|
|
48
|
+
};
|
|
49
|
+
/** Convert an sRGB `[r, g, b]` (0–255) triple to OKLCH (`L` on a 0–100 scale). */
|
|
50
|
+
export declare const rgbToOklch: (rgb: RGBTuple) => OKLCH;
|
|
51
|
+
/**
|
|
52
|
+
* Convert OKLCH back to an sRGB `[r, g, b]` triple (**unquantized** 0–255 floats). Holds `L` and
|
|
53
|
+
* `h`; when the requested chroma is outside sRGB it binary-searches `C` downward — fixed iterations,
|
|
54
|
+
* no data-dependent early exit, so build- and runtime-computed values agree (§20.8) — until the
|
|
55
|
+
* linear result is in `[0, 1]`. Lightness and hue are never adjusted, so a synthesized ramp keeps
|
|
56
|
+
* its hue and even lightness spacing; only saturation gives way at the gamut boundary. The floats
|
|
57
|
+
* are quantized exactly once, later, by `serializeColor`, so the 0–255 channel clamp never fires.
|
|
58
|
+
*/
|
|
59
|
+
export declare const oklchToRgb: (color: OKLCH) => RGBTuple;
|
|
60
|
+
/** Lighten a colour by `delta` OKLCH lightness points (0–100 scale); hue, chroma, alpha preserved. */
|
|
61
|
+
export declare const lighten: (value: string, delta: number) => string;
|
|
62
|
+
/** Darken a colour by `delta` OKLCH lightness points (0–100 scale); hue, chroma, alpha preserved. */
|
|
63
|
+
export declare const darken: (value: string, delta: number) => string;
|
|
64
|
+
/** Set a colour's absolute OKLCH lightness to `L` (0–100); hue, chroma, alpha preserved. */
|
|
65
|
+
export declare const setL: (value: string, L: number) => string;
|
|
66
|
+
/** Rotate a colour's OKLCH hue by `deg` (signed) around the perceptual wheel; L, C, alpha preserved. */
|
|
67
|
+
export declare const rotateHue: (value: string, deg: number) => string;
|
|
68
|
+
/** The perceptual complement — a 180° hue rotation at the same lightness and chroma. */
|
|
69
|
+
export declare const complement: (value: string) => string;
|
|
70
|
+
/**
|
|
71
|
+
* An `adjust` dial set — any subset. `l` = **absolute** OKLCH lightness target (0–100, raw L, the
|
|
72
|
+
* opposite direction from a numeric-`steps` label); `c` = chroma **multiplier** (`1` keep, `0` grey,
|
|
73
|
+
* `>1` more saturated where the gamut allows); `h` = **signed** hue rotation in degrees. Numbers
|
|
74
|
+
* only — keeps the vendored math string-free.
|
|
75
|
+
*/
|
|
76
|
+
export type AdjustDials = {
|
|
77
|
+
l?: number;
|
|
78
|
+
c?: number;
|
|
79
|
+
h?: number;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* One-shot OKLCH placement — set an absolute lightness, scale chroma, and/or rotate hue in a single
|
|
83
|
+
* derivation (each dial optional; an omitted dial leaves that component untouched). Alpha preserved.
|
|
84
|
+
*/
|
|
85
|
+
export declare const adjust: (value: string, dials: AdjustDials) => string;
|
|
86
|
+
/**
|
|
87
|
+
* Convert any canonical colour string (the subsystem's `rgb()` / `rgba()` form, or a hex string)
|
|
88
|
+
* to hex — 6-digit `#rrggbb` when opaque, 8-digit `#rrggbbaa` when translucent. Used by the DTCG
|
|
89
|
+
* exporter, whose `color` token type is conventionally hex (every other output stays `rgb()`).
|
|
90
|
+
*/
|
|
91
|
+
export declare const toHexColor: (value: string) => string;
|
|
92
|
+
/**
|
|
93
|
+
* Convert any canonical colour string (the subsystem's `rgb()` / `rgba()` form, or a hex string) to
|
|
94
|
+
* a CSS Color 4 `oklch(L% C H)` string — `oklch(L% C H / a)` when translucent. `L` is a percentage
|
|
95
|
+
* (0–100), `C` the absolute chroma, `H` in degrees, derived from the stored (quantized) rgb. Used by
|
|
96
|
+
* the CSS adapter's `colorFormat: "oklch"` output; the colour is identical to the `rgb()` form.
|
|
97
|
+
*/
|
|
98
|
+
export declare const toOklchColor: (value: string) => string;
|
|
99
|
+
/**
|
|
100
|
+
* Set a colour's opacity to `percent` (0–100) — an **absolute** alpha, not a relative fade
|
|
101
|
+
* (`alpha(x, 40)` ⇒ 40% opaque). The rgb channels are untouched; only the alpha channel is
|
|
102
|
+
* replaced. Result serializes to `rgba(…)` (or hex when `percent` is 100).
|
|
103
|
+
*/
|
|
104
|
+
export declare const alpha: (value: string, percent: number) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The components (composition) subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Owns **no primitive properties** (the property pipeline never runs — `normalizeProperties`
|
|
5
|
+
* returns empty). It contributes only recipes that reference other subsystems' recipes plus an
|
|
6
|
+
* own `css` delta. The generic recipe path drives `interpretRecipe` (own delta → refs) and, via
|
|
7
|
+
* the `extractReferences` hook, keeps each variant's cross-subsystem references as Model pointers
|
|
8
|
+
* (`"colors:solid.primary"`) so the referenced recipe's states ride along on its shared class.
|
|
9
|
+
* It grows a hook, never the spine.
|
|
10
|
+
*/
|
|
11
|
+
import type { Subsystem } from "../../core/subsystem";
|
|
12
|
+
export declare const componentsSubsystem: Subsystem;
|
|
13
|
+
export type { ComponentsRecipeProps, ResolvedComponentClass, ComponentsRaw } from "./types";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Components' `interpretRecipe` hook — the composition interpreter.
|
|
3
|
+
*
|
|
4
|
+
* A component variant carries cross-subsystem references (`colors: "solid.primary"`) that are
|
|
5
|
+
* NOT declarations (they're extracted separately as Model `references` pointers) plus an own
|
|
6
|
+
* `css` delta. This interpreter emits ONLY the own-delta declarations, each a format-neutral
|
|
7
|
+
* {@link Ref}. The delta is **literal-first**: a bare string / number value is a raw CSS literal
|
|
8
|
+
* → `{ value }`; a `ref("…")` / `{ ref: "…" }` marker is a token path → `{ ref }` (the adapter lowers
|
|
9
|
+
* it to `var(--…)` against the global token union). The
|
|
10
|
+
* referenced recipes' own states ride along on their shared classes (via the `references`
|
|
11
|
+
* pointers), so the component only emits its own delta + own states — which win at equal
|
|
12
|
+
* specificity by later source order.
|
|
13
|
+
*/
|
|
14
|
+
import type { InterpretedRecipeVariant } from "../../core/model";
|
|
15
|
+
import type { NormalizedRecipeVariant } from "../../core/normalize";
|
|
16
|
+
import type { RecipeInterpretContext } from "../../core/subsystem";
|
|
17
|
+
import type { ComponentsRecipeProps } from "./types";
|
|
18
|
+
/**
|
|
19
|
+
* Interpret one component variant into base + state/responsive override declarations from its
|
|
20
|
+
* `css` delta. Cross-subsystem references are handled by `extractComponentReferences`, not here.
|
|
21
|
+
*/
|
|
22
|
+
export declare const interpretComponentsRecipeVariant: (_variantName: string, variant: NormalizedRecipeVariant<ComponentsRecipeProps, string>, _ctx: RecipeInterpretContext) => InterpretedRecipeVariant<string>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Components (composition) subsystem types.
|
|
3
|
+
*
|
|
4
|
+
* A component recipe variant references other subsystems' recipes (`colors: "solid.primary"`,
|
|
5
|
+
* `layout: "padding.button-lg"`, …) and may add its own `css` delta (+ grouped `states` /
|
|
6
|
+
* `responsive`). It owns **no primitive properties** — the property pipeline never runs for it.
|
|
7
|
+
*/
|
|
8
|
+
import type { RecipeBlock } from "../../core/normalize";
|
|
9
|
+
/**
|
|
10
|
+
* One value in a component `css` delta. **Literal-first**: a bare `string` is a raw CSS value
|
|
11
|
+
* (`display: "flex"`), a `number` is a literal, and a token **reference** uses `ref("colors.on-primary")`
|
|
12
|
+
* (the {@link ref} helper) or the JSON-safe object form `{ ref: "colors.on-primary" }` → `var(--…)`.
|
|
13
|
+
* (This differs from the sibling composition fields — `colors: "solid.primary"` — where a bare string is
|
|
14
|
+
* always a reference: those compose tokens, the `css` block is raw CSS.)
|
|
15
|
+
*/
|
|
16
|
+
export type CssDeltaValue = string | number | {
|
|
17
|
+
ref: string;
|
|
18
|
+
};
|
|
19
|
+
/** One component recipe variant: cross-subsystem references + an own `css` delta. */
|
|
20
|
+
export type ComponentsRecipeProps = {
|
|
21
|
+
colors?: string;
|
|
22
|
+
typography?: string;
|
|
23
|
+
layout?: string;
|
|
24
|
+
effects?: string;
|
|
25
|
+
borders?: string;
|
|
26
|
+
css?: Record<string, CssDeltaValue>;
|
|
27
|
+
[subsystem: string]: string | Record<string, CssDeltaValue> | undefined;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* The authored `raw.components` slice (§8a). **Closed** and recipes-only — components own no
|
|
31
|
+
* primitive properties (the property pipeline never runs); they contribute only composition
|
|
32
|
+
* recipes referencing other subsystems' recipes plus an own `css` delta. Authoring type only.
|
|
33
|
+
*/
|
|
34
|
+
export interface ComponentsRaw {
|
|
35
|
+
recipes?: RecipeBlock<ComponentsRecipeProps>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The resolved class surface for one component variant — the referenced recipe classes (which
|
|
39
|
+
* carry their own `:hover` etc. on the shared class) followed by the component's own delta class.
|
|
40
|
+
* `className` is the space-joined list. Mirrors the OLD `ResolvedComponentClass` shape (`classes`
|
|
41
|
+
* renamed `classList`).
|
|
42
|
+
*/
|
|
43
|
+
export type ResolvedComponentClass = {
|
|
44
|
+
className: string;
|
|
45
|
+
classList: string[];
|
|
46
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The effects subsystem — a "regular" subsystem with no property finalize hook (values
|
|
3
|
+
* pass straight through the shared normalize). Iterates `raw.effects` (skipping the
|
|
4
|
+
* reserved `recipes` key) and interprets recipes into token-path refs (incl. the `blur`
|
|
5
|
+
* compound as a `{ ref, wrap: "blur" }` ref). It grows a hook, never the spine.
|
|
6
|
+
*/
|
|
7
|
+
import type { Subsystem } from "../../core/subsystem";
|
|
8
|
+
export declare const effectsSubsystem: Subsystem;
|
|
9
|
+
export type { EffectsRaw, EffectsPropertyValue } from "./types";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effects' `interpretRecipe` hook â resolves recipe declarations to token-path Refs.
|
|
3
|
+
*
|
|
4
|
+
* An effects recipe prop names a **variant** of the matching property, but the recipe key
|
|
5
|
+
* differs from the token key (`boxShadow` â `shadow`, `transition` â `transitions`) â the
|
|
6
|
+
* resolve-key map bridges them. Each declaration lowers to a format-neutral {@link Ref}
|
|
7
|
+
* carrying the canonical token path (`effects.shadow.lg`, `effects.shadow` for the base) â
|
|
8
|
+
* **no `var(--â¦)` strings**; the CSS adapter maps the path to a `var(--â¦)` at render time.
|
|
9
|
+
*
|
|
10
|
+
* The `blur` compound is the notable reshape: the old `effects/recipes.ts` baked
|
|
11
|
+
* `filter: blur(var(--â¦))` as a `{ value }` literal that **embedded** `var()` â not format-
|
|
12
|
+
* neutral. Here it emits `{ ref: "effects.blur", wrap: "blur" }`; the adapter's `refToStyleValue`
|
|
13
|
+
* renders `ref.wrap` â `blur(var(--â¦))`, so the wrap lives in the adapter, not the Model.
|
|
14
|
+
*/
|
|
15
|
+
import type { InterpretedRecipeVariant } from "../../core/model";
|
|
16
|
+
import type { NormalizedRecipeVariant } from "../../core/normalize";
|
|
17
|
+
import type { RecipeInterpretContext } from "../../core/subsystem";
|
|
18
|
+
import type { EffectsRecipeProps } from "./types";
|
|
19
|
+
/**
|
|
20
|
+
* Interpret one effects recipe variant into base + responsive/state override declarations,
|
|
21
|
+
* each a token-path {@link Ref}. A responsive `variant:` swap inherits the sibling's base
|
|
22
|
+
* declarations (via `ctx.resolveRecipeVariant`).
|
|
23
|
+
*/
|
|
24
|
+
export declare const interpretEffectsRecipeVariant: (variantName: string, variant: NormalizedRecipeVariant<EffectsRecipeProps, string>, ctx: RecipeInterpretContext) => InterpretedRecipeVariant<string>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { PropertyValue, RecipeBlock } from "../../core/normalize";
|
|
2
|
+
import type { ShadowInput, ShadowLayerInput, TransitionInput, TransitionPartInput } from "./utils";
|
|
3
|
+
/**
|
|
4
|
+
* Effects' property + recipe types. A "regular" subsystem — plain property values
|
|
5
|
+
* (no palette-style synthesis). Ported from the old `subsystems/effects/types.ts`,
|
|
6
|
+
* trimmed to the normalize / recipe surface the clean-room pipeline needs.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A structured object-leaf property (§15, structured-only per the 2026-07-16 amendment). The FLAT
|
|
10
|
+
* authoring shape: the leaf fields (`TLeaf`) sit at the property top level and ARE the (single-layer)
|
|
11
|
+
* base; `variants` / `responsive` / `modes` hold full leaf values (`TInput` = a flat leaf, an array
|
|
12
|
+
* of leaves for a multi-layer variant/mode, or the `"none"` keyword). **No `base` key** — the base is
|
|
13
|
+
* the top-level leaves (or `"none"` when none are authored); there is no multi-layer BASE. A bare
|
|
14
|
+
* `"none"` is also accepted (no shadow / no transition at all). Raw CSS strings are rejected at coerce.
|
|
15
|
+
*/
|
|
16
|
+
export type StructuredProperty<TInput, TLeaf> = "none" | (TLeaf & {
|
|
17
|
+
variants?: Record<string, TInput>;
|
|
18
|
+
responsive?: Array<{
|
|
19
|
+
breakpoint: string;
|
|
20
|
+
query?: "min" | "max" | "exact";
|
|
21
|
+
variant?: string;
|
|
22
|
+
target?: string;
|
|
23
|
+
orientation?: "landscape" | "portrait";
|
|
24
|
+
} & TLeaf>;
|
|
25
|
+
modes?: Record<string, TInput>;
|
|
26
|
+
});
|
|
27
|
+
/** Authored box-shadow property (§15) — structured single-layer base + structured variants/modes. */
|
|
28
|
+
export type ShadowValue = StructuredProperty<ShadowInput, ShadowLayerInput>;
|
|
29
|
+
/** Authored transition property (§15) — structured single-part base + structured variants/modes. */
|
|
30
|
+
export type TransitionValue = StructuredProperty<TransitionInput, TransitionPartInput>;
|
|
31
|
+
export type BlurValue = PropertyValue<number | string>;
|
|
32
|
+
export type ZIndexValue = PropertyValue<number>;
|
|
33
|
+
export type OpacityValue = PropertyValue<number>;
|
|
34
|
+
/**
|
|
35
|
+
* An effects recipe declaration block. Each value names a **variant** of the matching
|
|
36
|
+
* effects property; the recipe prop key differs from the token key (`boxShadow` → `shadow`,
|
|
37
|
+
* `transition` → `transitions`) — the interpreter maps it via its resolve-key map. `blur` is
|
|
38
|
+
* a compound: it lowers to `filter: blur(var(--…))` via a `{ ref, wrap: "blur" }` ref.
|
|
39
|
+
*/
|
|
40
|
+
export type EffectsRecipeProps = {
|
|
41
|
+
boxShadow?: string;
|
|
42
|
+
opacity?: string;
|
|
43
|
+
blur?: string;
|
|
44
|
+
transition?: string;
|
|
45
|
+
zIndex?: string;
|
|
46
|
+
[property: string]: string | undefined;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* An effects property value (§8a, §15). Effects properties span plain scalars (`blur`
|
|
50
|
+
* `number | string`, `opacity`/`zIndex` numbers) AND the structured object-leaf properties
|
|
51
|
+
* `shadow` / `transitions`. An **open** authoring union — the `EffectsRaw` index signature keys
|
|
52
|
+
* every property to it; runtime coercion (`effects/utils.ts`) validates the concrete shape per key.
|
|
53
|
+
*/
|
|
54
|
+
export type EffectsPropertyValue = PropertyValue<string | number> | ShadowValue | TransitionValue;
|
|
55
|
+
/**
|
|
56
|
+
* The authored `raw.effects` slice (§8a). An **open** map: keys are effects property names
|
|
57
|
+
* (`shadow`, `blur`, `transitions`, …), each an {@link EffectsPropertyValue}; the reserved
|
|
58
|
+
* `recipes` key is a {@link RecipeBlock} of effects recipes. Authoring type only.
|
|
59
|
+
*/
|
|
60
|
+
export interface EffectsRaw {
|
|
61
|
+
recipes?: RecipeBlock<EffectsRecipeProps>;
|
|
62
|
+
[property: string]: EffectsPropertyValue | RecipeBlock<EffectsRecipeProps> | undefined;
|
|
63
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effects value coercion (§15) — parse/validate authored shadow / transition leaves into the
|
|
3
|
+
* canonical, **format-neutral** Model form.
|
|
4
|
+
*
|
|
5
|
+
* Modeled on `colors/utils.ts`: a single boundary that runs at normalize time (via the subsystem's
|
|
6
|
+
* `coerceValue`) and turns the ergonomic authoring shapes — a flat single leaf or an array of leaves
|
|
7
|
+
* — into ONE canonical representation the Model carries on `Ref.struct`:
|
|
8
|
+
*
|
|
9
|
+
* - **shadow** → {@link ShadowLayer}`[]` (always an array, even single-layer); `color` kept as its
|
|
10
|
+
* `colors.*` token-path string (never an embedded `rgba()` — §15.1), resolved late by the adapter.
|
|
11
|
+
* A translucent shadow references a translucent colour (an `alpha` colour variant — §13.3).
|
|
12
|
+
* - **transitions** → {@link TransitionPart}`[]`; `duration`/`delay` in ms.
|
|
13
|
+
*
|
|
14
|
+
* **Structured-only (§15.2, amended 2026-07-16):** raw CSS strings are REJECTED — the ONLY accepted
|
|
15
|
+
* string is the keyword `"none"` (no shadow / no transition). Every other string throws a path-labelled
|
|
16
|
+
* error. Serialization to CSS text stays in the adapter; this module holds structure, not format. Its
|
|
17
|
+
* only core dependency is the shared length parser (`parseLength`, §21) — so a pinned geometry string
|
|
18
|
+
* (`offsetY: "1px"`) is parsed by the same grammar every length uses, rather than a duplicate here.
|
|
19
|
+
*/
|
|
20
|
+
import type { ShadowLayer, TransitionPart } from "../../core/model";
|
|
21
|
+
/** A single authored shadow layer (flat leaf object) — geometry as a bare number (deferred, resolved by
|
|
22
|
+
* the §21 unit pass) or a pinned length string (`"1px"`, `"0.5rem"`) + a `colors.*` color ref
|
|
23
|
+
* (translucency comes from an `alpha` colour variant, not a shadow field). */
|
|
24
|
+
export type ShadowLayerInput = {
|
|
25
|
+
offsetX?: number | string;
|
|
26
|
+
offsetY?: number | string;
|
|
27
|
+
blur?: number | string;
|
|
28
|
+
spread?: number | string;
|
|
29
|
+
color?: string;
|
|
30
|
+
inset?: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** An authored shadow value: a flat single layer, an array of layers, or the `"none"` keyword. */
|
|
33
|
+
export type ShadowInput = "none" | ShadowLayerInput | ShadowLayerInput[];
|
|
34
|
+
/** A single authored transition part — `property` (required) + ms durations + timing keyword. */
|
|
35
|
+
export type TransitionPartInput = {
|
|
36
|
+
property?: string;
|
|
37
|
+
duration?: number;
|
|
38
|
+
timingFunction?: string;
|
|
39
|
+
delay?: number;
|
|
40
|
+
};
|
|
41
|
+
/** An authored transition value: a flat single part, an array of parts, or the `"none"` keyword. */
|
|
42
|
+
export type TransitionInput = "none" | TransitionPartInput | TransitionPartInput[];
|
|
43
|
+
/** The canonical Model form of a shadow value — an array of layers, or the `"none"` keyword. */
|
|
44
|
+
export type ShadowCanonical = "none" | ShadowLayer[];
|
|
45
|
+
/** The canonical Model form of a transition value — an array of parts, or the `"none"` keyword. */
|
|
46
|
+
export type TransitionCanonical = "none" | TransitionPart[];
|
|
47
|
+
/**
|
|
48
|
+
* Coerce an authored shadow value into its canonical Model form. A string passes through (escape
|
|
49
|
+
* hatch); a flat leaf becomes a one-element `ShadowLayer[]`; an array becomes a multi-layer
|
|
50
|
+
* `ShadowLayer[]`. `label` is the property path for friendly errors.
|
|
51
|
+
*/
|
|
52
|
+
export declare const coerceShadowValue: (input: ShadowInput, label?: string) => ShadowCanonical;
|
|
53
|
+
/**
|
|
54
|
+
* Coerce an authored transition value into its canonical Model form. A string passes through; a flat
|
|
55
|
+
* part becomes a one-element `TransitionPart[]`; an array becomes a multi-part `TransitionPart[]`.
|
|
56
|
+
*/
|
|
57
|
+
export declare const coerceTransitionValue: (input: TransitionInput, label?: string) => TransitionCanonical;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The globals subsystem (§9 — formerly `reset`).
|
|
3
|
+
*
|
|
4
|
+
* Owns **no primitive properties** and **no minted-class recipes** — it fills the Model with two
|
|
5
|
+
* kinds of selector-targeting rule-set:
|
|
6
|
+
*
|
|
7
|
+
* - **preset layers** (`static` + default `defaults`) — `kind:"reset"`, literal/opportunistic
|
|
8
|
+
* normalization the adapters render at specificity-0 (`:where(sel)`). Unchanged from `reset`.
|
|
9
|
+
* - **themed elements** (`elements`) — `kind:"globals"`, one rule-set per selector, carrying base
|
|
10
|
+
* declarations + `states`/`responsive` overrides + delta-only `variants`. The adapters render
|
|
11
|
+
* these at a higher tier (bare `a { }`, variant `a.subtle` / nested `&.subtle`).
|
|
12
|
+
*
|
|
13
|
+
* Element rules reuse the shared recipe normalization (`normalizeRecipeGroup`) for the genuinely
|
|
14
|
+
* common part — flattening `states` + `responsive` into one `overrides` list — but stay *structural*
|
|
15
|
+
* (a base selector + a named-variant map), not §7A recipe-sibling classes: they're elements, not
|
|
16
|
+
* recipes. Their token refs resolve late in each adapter and are validated up-front in `createTheme`
|
|
17
|
+
* (`validateGlobalsRefs`), like `components`. It grows a hook, never the spine.
|
|
18
|
+
*/
|
|
19
|
+
import type { Subsystem } from "../../core/subsystem";
|
|
20
|
+
export declare const globalsSubsystem: Subsystem;
|
|
21
|
+
export type { GlobalsRaw, GlobalsPreset, GlobalsDeclValue, GlobalsDeclarations, GlobalsElement } from "./types";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The globals preset library (§9, formerly §10.1 reset) — the single, format-neutral source for the
|
|
3
|
+
* static normalization rule-sets and the default `h1`–`h6` → type-scale map.
|
|
4
|
+
*
|
|
5
|
+
* These produce Model {@link RuleSet}s (declarations are `{ value }` literals for the static
|
|
6
|
+
* layer, `{ ref }` token paths for the default heading map), so every web adapter shares one
|
|
7
|
+
* source (à la `color-math`) and lowers them itself. No CSS strings here — the adapter wraps
|
|
8
|
+
* each `selector` in `:where(…)` (specificity-0) and orders reset ahead of recipes.
|
|
9
|
+
*
|
|
10
|
+
* Layers:
|
|
11
|
+
* - **static** — literal-declaration rule-sets that strip UA opinions (box model, margins,
|
|
12
|
+
* heading sizing, list markers, form typography, media block/max-width, anchor colour).
|
|
13
|
+
* - **default headings** — themed rule-sets binding `h1`–`h6` to typography's ratio-generated
|
|
14
|
+
* `fontSize` scale variants (`typography.fontSize.4xl` …). Opportunistic: the adapter drops a
|
|
15
|
+
* heading whose scale step wasn't generated (a theme with a ratio-less `fontSize`).
|
|
16
|
+
*/
|
|
17
|
+
import type { RuleSetGroup } from "../../core/model";
|
|
18
|
+
import type { GlobalsPreset } from "./types";
|
|
19
|
+
/** The default `h1`–`h6` themed group — each binds `font-size` to `typography.fontSize.<step>`. */
|
|
20
|
+
export declare const buildDefaultHeadingGroup: () => RuleSetGroup;
|
|
21
|
+
/** The recommended default preset (what `refract init` scaffolds). */
|
|
22
|
+
export declare const DEFAULT_GLOBALS_PRESET: Exclude<GlobalsPreset, false>;
|
|
23
|
+
/** The known preset names — for validation / error messages. */
|
|
24
|
+
export declare const GLOBALS_PRESET_NAMES: ReadonlyArray<Exclude<GlobalsPreset, false>>;
|
|
25
|
+
/**
|
|
26
|
+
* Expand a preset name into its `{ static, defaults? }` rule-set groups. `false` yields no groups
|
|
27
|
+
* (elements-only). An unknown name throws (typo detection). The default heading group is included
|
|
28
|
+
* only when the preset opts into it (`preflight` / `reset`, not `normalize`).
|
|
29
|
+
*/
|
|
30
|
+
export declare const expandPreset: (preset: GlobalsPreset) => {
|
|
31
|
+
static?: RuleSetGroup;
|
|
32
|
+
defaults?: RuleSetGroup;
|
|
33
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The globals subsystem's authoring types (§9).
|
|
3
|
+
*
|
|
4
|
+
* `globals` owns the bare-element layer: a **preset** (opinionated static normalization + a default
|
|
5
|
+
* `h1`–`h6` map bound to the type scale) plus **themed element rules** (`elements`) bound to raw
|
|
6
|
+
* selectors. An element rule is a recipe *item* (declarations + `states` / `responsive` / `variants`),
|
|
7
|
+
* not a two-level recipe group — the selector IS the leaf. Authoring type only; the subsystem lowers
|
|
8
|
+
* it to Model rule-sets (`kind:"reset"` for the preset layer, `kind:"globals"` for elements) that each
|
|
9
|
+
* web adapter renders.
|
|
10
|
+
*/
|
|
11
|
+
import type { RecipeVariantDefinition, GlobalsElementVariantModifier } from "../../core/normalize";
|
|
12
|
+
/** The built-in normalization preset names. `false` disables the static + default layers (elements only). */
|
|
13
|
+
export type GlobalsPreset = "preflight" | "normalize" | "reset" | false;
|
|
14
|
+
/**
|
|
15
|
+
* One themed-element declaration value (§9) — components' `CssDeltaValue`, minus cross-subsystem
|
|
16
|
+
* composition refs. **Literal-first**: a bare `string` is a raw CSS value (`textDecoration: "underline"`),
|
|
17
|
+
* a `number` is a literal, and a token **reference** uses `ref("colors.link")` or the JSON-safe object
|
|
18
|
+
* form `{ ref: "colors.link" }` → `var(--…)`. Flat leaves bound to a selector, never the class-list
|
|
19
|
+
* composition of `components`.
|
|
20
|
+
*/
|
|
21
|
+
export type GlobalsDeclValue = string | number | {
|
|
22
|
+
ref: string;
|
|
23
|
+
};
|
|
24
|
+
/** The flat declaration map a globals element instantiates the recipe-item shape's `TProps` with. */
|
|
25
|
+
export type GlobalsDeclarations = Record<string, GlobalsDeclValue>;
|
|
26
|
+
/**
|
|
27
|
+
* One themed element rule (§9) — the recipe-item shape ({@link RecipeVariantDefinition}) instantiated
|
|
28
|
+
* with flat globals leaves: base declarations plus the three condition axes `states` / `responsive` /
|
|
29
|
+
* `variants`. There is **no `modes` axis** — light/dark rides the referenced token's own modes. Each
|
|
30
|
+
* `variants` entry is a delta-only modifier the adapters render as a higher-specificity variant of the
|
|
31
|
+
* element (CSS `a.subtle`, styled-components / SCSS nested `&.subtle`).
|
|
32
|
+
*/
|
|
33
|
+
export type GlobalsElement = RecipeVariantDefinition<GlobalsDeclarations, string, GlobalsElementVariantModifier<GlobalsDeclarations, string>>;
|
|
34
|
+
/**
|
|
35
|
+
* The authored `rawTheme.globals` slice (§9).
|
|
36
|
+
*
|
|
37
|
+
* - `preset` — the normalization base (`"preflight" | "normalize" | "reset" | false`). The key is
|
|
38
|
+
* `preset` (not `reset`) because a `reset: "reset"` collides with the `"reset"` value. There is **no
|
|
39
|
+
* bare-string shorthand** — the one form is `globals: { preset }`. The preset expands the static
|
|
40
|
+
* layer (+ a default `h1`–`h6` heading map for `preflight` / `reset`); it must be explicit for those
|
|
41
|
+
* layers to emit, so a bare `{ elements }` (no `preset` key) emits only the themed element rules and
|
|
42
|
+
* an `override({ globals: { elements } })` inherits the parent's preset.
|
|
43
|
+
* - `elements` — selector → themed element rule.
|
|
44
|
+
*/
|
|
45
|
+
export interface GlobalsRaw {
|
|
46
|
+
preset?: GlobalsPreset;
|
|
47
|
+
elements?: Record<string, GlobalsElement>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Subsystems: colors · typography · layout · effects · borders · animation · components · globals. Wired in Steps 1–4 / §10.2 / §14 / §9. */
|
|
2
|
+
export { colorsSubsystem } from "./colors";
|
|
3
|
+
/** Contrast audit (WCAG 2 + advisory APCA) — reads a built theme, reports/strict-throws. */
|
|
4
|
+
export { audit } from "./colors";
|
|
5
|
+
export type { AuditResult, AuditOptions, PairingScore, PairingKind, WcagLevel } from "./colors";
|
|
6
|
+
export { typographySubsystem } from "./typography";
|
|
7
|
+
export { layoutSubsystem } from "./layout";
|
|
8
|
+
export { effectsSubsystem } from "./effects";
|
|
9
|
+
export { bordersSubsystem } from "./borders";
|
|
10
|
+
export { animationSubsystem } from "./animation";
|
|
11
|
+
export { componentsSubsystem } from "./components";
|
|
12
|
+
export { globalsSubsystem } from "./globals";
|
|
13
|
+
/** Per-subsystem raw authoring-input types (§8a) — composed into `RawTheme`. */
|
|
14
|
+
export type { ColorsRaw } from "./colors";
|
|
15
|
+
export type { TypographyRaw, TypographyPropertyValue } from "./typography";
|
|
16
|
+
export type { EffectsRaw, EffectsPropertyValue } from "./effects";
|
|
17
|
+
export type { BordersRaw, BordersPropertyValue } from "./borders";
|
|
18
|
+
export type { AnimationRaw } from "./animation";
|
|
19
|
+
export type { LayoutRaw, ContainerRaw, ContainerVariantRaw } from "./layout";
|
|
20
|
+
export type { ComponentsRaw } from "./components";
|
|
21
|
+
export type { GlobalsRaw, GlobalsPreset, GlobalsDeclValue, GlobalsDeclarations, GlobalsElement } from "./globals";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The layout subsystem — the biggest one, with three parts:
|
|
3
|
+
* 1. Regular property tokens (`spacing` / `gutters` / `aspectRatio`) — like typography/effects,
|
|
4
|
+
* plus the forced `none` variant on spacing/gutters (`finalizeLayoutNormalization`).
|
|
5
|
+
* 2. Recipes (`padding` / `section`) — ordinary token-path recipes (`interpretRecipe`).
|
|
6
|
+
* 3. Structural generators (`columns` / `grids` / `stacks` / `container`) — emitted as native
|
|
7
|
+
* Model rule-sets via the `buildStructural` hook (see `structural.ts`), with the columns/
|
|
8
|
+
* container config knobs riding along as `configProperties` (Model `extraProperties`).
|
|
9
|
+
*
|
|
10
|
+
* It grows the spine's hooks (`interpretRecipe`, `buildStructural`), never the spine's control flow.
|
|
11
|
+
*/
|
|
12
|
+
import type { Subsystem } from "../../core/subsystem";
|
|
13
|
+
export declare const layoutSubsystem: Subsystem;
|
|
14
|
+
export type { LayoutRaw, ContainerRaw, ContainerVariantRaw } from "./types";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout's `normalizeProperty` hook — numeric scale synthesis (§10.6) + the forced `none` variant.
|
|
3
|
+
*
|
|
4
|
+
* `spacing` / `gutters` / `sizes` can synthesize their variant ramp from a base + a curve, the same
|
|
5
|
+
* way colors generates tonal steps and typography the type scale:
|
|
6
|
+
* - **geometric** (`ratio`) — `base × ratio^n`, `steps` an ordered name array (index = exponent);
|
|
7
|
+
* - **linear** (`step`) — `step × n`, `steps` a name→multiplier map (the 4/8-pt grid).
|
|
8
|
+
*
|
|
9
|
+
* Each synthesized step is stored as a **derived** variant (`{ base, derive:{ ref, fn:"scaleStep",
|
|
10
|
+
* arg } }`) so the Model carries it as a re-resolving `Ref` — `override()` of the base re-synthesizes
|
|
11
|
+
* every step (mirror colors, NOT typography's frozen literals). A ramp entry inside a property's
|
|
12
|
+
* `responsive` list (D6) regenerates the WHOLE named scale at that breakpoint, expanding into one
|
|
13
|
+
* `target` override per step — the already-existing responsive channel, no new Model member.
|
|
14
|
+
*
|
|
15
|
+
* Synthesis is **opt-in + additive**: absent a `ratio`/`step`, behaviour is byte-identical to before
|
|
16
|
+
* (spacing/gutters still get the forced `none`; sizes/aspectRatio pass through). Authored `variants`
|
|
17
|
+
* always win over synthesized ones — the way sizes' semantic caps (`prose`) and pinned values
|
|
18
|
+
* (`full: "100%"`, no magnitude → never synthesized) coexist with the ramp.
|
|
19
|
+
*/
|
|
20
|
+
import type { NormalizedPropertyValue } from "../../core/normalize";
|
|
21
|
+
import type { Literal } from "../../core/model";
|
|
22
|
+
/**
|
|
23
|
+
* The `scaleStep` derivation fn (registered by the layout subsystem). Re-derives a synthesized step
|
|
24
|
+
* from its curve config: **geometric** `base × ratio^exp` (from the resolved base token, so an
|
|
25
|
+
* `override()` of the base rescales it), **linear** `step × mult` (a fixed grid, self-contained in
|
|
26
|
+
* `arg`). A responsive ramp step with an explicit breakpoint base carries it on `arg.base`, so it
|
|
27
|
+
* derives from its own breakpoint base (precedent: colors' appearance modes). Mirrors the way the
|
|
28
|
+
* derivation registry hands every fn `(resolvedValue, arg)`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const scaleStep: (value: Literal, arg?: unknown) => Literal;
|
|
31
|
+
/**
|
|
32
|
+
* @param propertyKey The layout property being normalized.
|
|
33
|
+
* @param normalized The property after the shared property normalize pass.
|
|
34
|
+
*/
|
|
35
|
+
export declare const finalizeLayoutNormalization: (propertyKey: string, normalized: NormalizedPropertyValue<unknown>) => NormalizedPropertyValue<unknown>;
|