@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,12 @@
|
|
|
1
|
+
import type { MediaQueryOptions } from "./queries";
|
|
2
|
+
export declare const BREAKPOINT_EPSILON = 0.02;
|
|
3
|
+
export type MediaVariant = "min" | "max" | "exact";
|
|
4
|
+
export type MediaGroupDescriptor = Record<MediaVariant, string>;
|
|
5
|
+
export type MediaDescriptor<TBreakpoint extends string> = {
|
|
6
|
+
min: (key: TBreakpoint, options?: MediaQueryOptions) => string;
|
|
7
|
+
max: (key: TBreakpoint, options?: MediaQueryOptions) => string;
|
|
8
|
+
exact: (key: TBreakpoint, options?: MediaQueryOptions) => string;
|
|
9
|
+
between: (from: TBreakpoint, to: TBreakpoint, options?: MediaQueryOptions) => string;
|
|
10
|
+
} & Record<TBreakpoint, MediaGroupDescriptor>;
|
|
11
|
+
export declare const sortBreakpointKeys: <T extends string>(breakpoints: Record<T, number>) => T[];
|
|
12
|
+
export declare const buildMediaDescriptor: <TBreakpoint extends string>(breakpoints: Record<TBreakpoint, number>, resolveQuery: (options: MediaQueryOptions) => string) => MediaDescriptor<TBreakpoint>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media types + helpers for the clean-room tree — breakpoints → `@media` builder.
|
|
3
|
+
*
|
|
4
|
+
* Self-contained (no intra-core deps): the numeric-breakpoint machinery core hands
|
|
5
|
+
* to adapters, which decorate it (`wrapMedia`) for their target. Ported from the
|
|
6
|
+
* original `core/media` during the barrel flip (Step 6).
|
|
7
|
+
*/
|
|
8
|
+
export * from "./descriptors";
|
|
9
|
+
export * from "./queries";
|
|
10
|
+
export * from "./defaults";
|
|
11
|
+
export * from "./containers";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type MediaUnit = "px" | "em" | "rem";
|
|
2
|
+
export type MediaConfig = {
|
|
3
|
+
unit?: MediaUnit;
|
|
4
|
+
baseFontSize?: number;
|
|
5
|
+
};
|
|
6
|
+
export type MediaQueryOptions = {
|
|
7
|
+
min?: number;
|
|
8
|
+
max?: number;
|
|
9
|
+
orientation?: "landscape" | "portrait";
|
|
10
|
+
};
|
|
11
|
+
export declare const resolveMediaConfig: (config?: MediaConfig) => Required<MediaConfig>;
|
|
12
|
+
export declare const formatWidth: (value: number, config: Required<MediaConfig>) => string;
|
|
13
|
+
export declare const mediaQueryString: ({ min, max, orientation }: MediaQueryOptions, config: Required<MediaConfig>) => string;
|
|
14
|
+
export declare const mediaQuery: (options: MediaQueryOptions, config?: MediaConfig) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Container-query prelude (§10.5) — the `@container <name> (…)` twin of {@link mediaQueryString}.
|
|
17
|
+
* Shares the width formatting (so container thresholds honor the same px/em/rem unit config), but
|
|
18
|
+
* has no `orientation` clause (invalid under `container-type: inline-size`; rejected in normalize).
|
|
19
|
+
*/
|
|
20
|
+
export declare const containerQueryString: (name: string, { min, max }: Pick<MediaQueryOptions, "min" | "max">, config: Required<MediaConfig>) => string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model builder (clean-room port of `core/common/buildModel.ts`).
|
|
3
|
+
*
|
|
4
|
+
* Pure functions that assemble the format-neutral {@link ThemeModel} from data the
|
|
5
|
+
* pipeline computes — the normalized property collections and the interpreted recipe
|
|
6
|
+
* groups. `buildThemeModel` consumes each subsystem's already-interpreted rule-set
|
|
7
|
+
* groups (see `buildRuleSetGroupFromInterpreted`), whose declarations already carry
|
|
8
|
+
* format-neutral {@link Ref}s (`{ ref: "colors.primary" }` for a token-path reference,
|
|
9
|
+
* `{ value }` for a literal). The builder is a structural copy — it never string-parses
|
|
10
|
+
* `var(--…)`; the interpreter emits canonical token paths directly.
|
|
11
|
+
*
|
|
12
|
+
* `pathify*` rewrites refs via a supplied map (used by later subsystems that still emit
|
|
13
|
+
* var-name refs); `buildTokenMap` flattens the property tokens into a `path -> Ref` map.
|
|
14
|
+
*/
|
|
15
|
+
import type { NormalizedPropertyValue } from "../normalize";
|
|
16
|
+
import type { InterpretedRecipeGroup, InterpretedRecipeVariant } from "./interpreted";
|
|
17
|
+
import type { ContainerModel, Keyframe, PropertyModel, Ref, RuleSet, RuleSetGroup, SubsystemModel, ThemeModel } from "./model";
|
|
18
|
+
/**
|
|
19
|
+
* One normalized property (`{ base, responsive, variants?, ...extras }`) → a
|
|
20
|
+
* {@link PropertyModel}. `base` and each variant become value refs; scalar sibling
|
|
21
|
+
* extras (e.g. colors' `text`) go in `extras`; the responsive list maps entry-for-entry.
|
|
22
|
+
*/
|
|
23
|
+
export declare const buildPropertyModel: (normalized: NormalizedPropertyValue<unknown, Record<string, unknown>>, propertyName?: string) => PropertyModel;
|
|
24
|
+
/** A whole normalized collection (`name → normalized property`) → `name → PropertyModel`. */
|
|
25
|
+
export declare const buildPropertiesModel: (collection: Record<string, NormalizedPropertyValue<unknown, Record<string, unknown>>>) => Record<string, PropertyModel>;
|
|
26
|
+
/**
|
|
27
|
+
* One *interpreted* recipe variant → a {@link RuleSet}. The interpreter has already
|
|
28
|
+
* resolved every declaration to a {@link Ref} (`{ ref }` for token references, `{ value }`
|
|
29
|
+
* for literals) and separated the condition axes from the declarations, so this is a
|
|
30
|
+
* structural copy — **no string-parsing of `var(…)`**. Format-neutral by construction:
|
|
31
|
+
* refs are token paths, not var names.
|
|
32
|
+
*/
|
|
33
|
+
export declare const buildRuleSetFromInterpreted: (variant: InterpretedRecipeVariant<string>) => RuleSet;
|
|
34
|
+
/** An interpreted recipe group (`variant → interpreted`) → a {@link RuleSetGroup} with refs. */
|
|
35
|
+
export declare const buildRuleSetGroupFromInterpreted: (group: InterpretedRecipeGroup<string>) => RuleSetGroup;
|
|
36
|
+
/**
|
|
37
|
+
* Rewrite a rule-set group's declaration refs from CSS var names to canonical **token paths**
|
|
38
|
+
* (e.g. `--dt-color--primary` → `colors.primary`) using `varToPath`. Refs already absent from the
|
|
39
|
+
* map are left untouched (var name preserved). Pure — returns a new group. Applied to the Model
|
|
40
|
+
* copy so `theme.model` is format-neutral; the CSS adapter's own lowering is unaffected.
|
|
41
|
+
*/
|
|
42
|
+
export declare const pathifyRuleSetGroup: (group: RuleSetGroup, varToPath: Record<string, string>) => RuleSetGroup;
|
|
43
|
+
/**
|
|
44
|
+
* Rewrite property tokens' refs from CSS var names to canonical token paths using `varToPath`
|
|
45
|
+
* (base / variants / extras). Refs absent from the map are left untouched. Pure — returns a new
|
|
46
|
+
* map. Used to pathify layout's structural-config `extraProperties` in the Model.
|
|
47
|
+
*/
|
|
48
|
+
export declare const pathifyProperties: (properties: Record<string, PropertyModel>, varToPath: Record<string, string>) => Record<string, PropertyModel>;
|
|
49
|
+
/**
|
|
50
|
+
* Extract `"subsystem:group.variant"` references from a component variant's normalized base, in
|
|
51
|
+
* **authored order** — the order the composition references were written (`{ effects, layout }` →
|
|
52
|
+
* `["effects:…", "layout:…"]`). The CSS adapter renders this ordered list into the className, so the
|
|
53
|
+
* Model `references` array IS the canonical composition order (the referenced recipe classes precede
|
|
54
|
+
* the component's own delta class). Only the cross-subsystem keys are recognised; other base keys
|
|
55
|
+
* (`css`, literals) are skipped.
|
|
56
|
+
*/
|
|
57
|
+
export declare const extractComponentReferences: (rawVariantBase: Record<string, unknown>) => string[];
|
|
58
|
+
/**
|
|
59
|
+
* An interpreted component variant (its `css` delta) + its cross-subsystem `references`
|
|
60
|
+
* → a component {@link RuleSet} (`kind: "recipe"`, own delta declarations carry refs,
|
|
61
|
+
* cross-subsystem pointers kept as `references`).
|
|
62
|
+
*/
|
|
63
|
+
export declare const buildComponentRuleSetFromInterpreted: (variant: InterpretedRecipeVariant<string>, references: string[]) => RuleSet;
|
|
64
|
+
/**
|
|
65
|
+
* One subsystem's Model input. `ruleSetGroups` carries the already-interpreted rule-sets
|
|
66
|
+
* (declarations with refs) that `createTheme` produces.
|
|
67
|
+
*/
|
|
68
|
+
export type SubsystemModelInput = {
|
|
69
|
+
properties?: Record<string, NormalizedPropertyValue<unknown, Record<string, unknown>>>;
|
|
70
|
+
ruleSetGroups?: Record<string, RuleSetGroup>;
|
|
71
|
+
/**
|
|
72
|
+
* Already-built {@link PropertyModel}s to merge into `properties` (after the normalized ones).
|
|
73
|
+
* Layout uses this to carry its structural config knobs (columns/container size, gutter, inset)
|
|
74
|
+
* as tokens — the subsystem's `buildStructural` hook emits them (see `subsystems/layout/structural.ts`).
|
|
75
|
+
*/
|
|
76
|
+
extraProperties?: Record<string, PropertyModel>;
|
|
77
|
+
/**
|
|
78
|
+
* Named keyframe definitions (§10.2) — the animation subsystem's `buildStructural` output. Neither
|
|
79
|
+
* property nor rule-set; attached to {@link SubsystemModel.keyframes} verbatim.
|
|
80
|
+
*/
|
|
81
|
+
keyframes?: Record<string, Keyframe>;
|
|
82
|
+
};
|
|
83
|
+
/** Everything `buildThemeModel` needs — read from `createTheme`'s live caches/sources. */
|
|
84
|
+
export type BuildThemeModelInput = {
|
|
85
|
+
breakpoints: Record<string, number>;
|
|
86
|
+
/** Named query containers (§10.5) — carried onto the Model verbatim. Additive (absent → no field). */
|
|
87
|
+
containers?: Record<string, ContainerModel>;
|
|
88
|
+
colors?: SubsystemModelInput;
|
|
89
|
+
typography?: SubsystemModelInput;
|
|
90
|
+
layout?: SubsystemModelInput;
|
|
91
|
+
effects?: SubsystemModelInput;
|
|
92
|
+
/** Borders (§14): stroke geometry (width/style/offset/radius) + border/outline recipes. */
|
|
93
|
+
borders?: SubsystemModelInput;
|
|
94
|
+
animation?: SubsystemModelInput;
|
|
95
|
+
components?: {
|
|
96
|
+
ruleSetGroups?: Record<string, RuleSetGroup>;
|
|
97
|
+
};
|
|
98
|
+
globals?: SubsystemModelInput;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* One subsystem's Model input → a {@link SubsystemModel} (normalized properties built into
|
|
102
|
+
* {@link PropertyModel}s, `extraProperties` merged in, rule-set groups attached). Returns
|
|
103
|
+
* `undefined` when the slice contributes nothing. Exported so `override` can turn a *partial*
|
|
104
|
+
* subsystem input into a Model fragment with the exact same shape the initial build produces.
|
|
105
|
+
*/
|
|
106
|
+
export declare const buildSubsystemModel: (slice: SubsystemModelInput | undefined) => SubsystemModel | undefined;
|
|
107
|
+
/** Assemble the whole {@link ThemeModel} from the pipeline's normalized data + rule-set groups. */
|
|
108
|
+
export declare const buildThemeModel: (input: BuildThemeModelInput) => ThemeModel;
|
|
109
|
+
/**
|
|
110
|
+
* Flatten a {@link ThemeModel} into one `path -> Ref` map — one entry per property token:
|
|
111
|
+
* `"<subsystem>.<property>"` (base), `"<subsystem>.<property>.<variant>"`, and
|
|
112
|
+
* `"<subsystem>.<property>.<extra>"`. Rule-sets are not tokens and are excluded. Each entry is
|
|
113
|
+
* the Model's own `Ref` — `{ value }` for a literal, `{ ref }` for a reference. Additive source
|
|
114
|
+
* for `theme.tokens`; the flat, format-neutral replacement for the per-subsystem `tokens` shape.
|
|
115
|
+
*/
|
|
116
|
+
export declare const buildTokenMap: (model: ThemeModel) => Record<string, Ref>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model layer for the clean-room tree (Step 0c).
|
|
3
|
+
*
|
|
4
|
+
* The format-neutral {@link ThemeModel} types + the pure builders that assemble it
|
|
5
|
+
* from normalized properties and interpreted rule-set groups. Ported from
|
|
6
|
+
* `core/common/{model,buildModel}.ts`; the interpreted-recipe shape the builders
|
|
7
|
+
* consume lives in `./interpreted`. No CSS lowering here — that's the CSS adapter (step 1).
|
|
8
|
+
*/
|
|
9
|
+
export type { Literal, ShadowLayer, TransitionPart, StructuredValue, Ref, ResponsiveQueryKind, Orientation, PropertyResponsiveOverride, PropertyModel, VariantModel, OverrideCondition, RuleSetOverride, GlobalsVariant, RuleSet, RuleSetGroup, KeyframeStep, Keyframe, ContainerModel, SubsystemModel, ThemeModel, } from "./model";
|
|
10
|
+
export type { RecipeDeclarations, InterpretedRecipeOverride, InterpretedRecipeVariant, InterpretedRecipeGroup, } from "./interpreted";
|
|
11
|
+
export { buildPropertyModel, buildPropertiesModel, buildRuleSetFromInterpreted, buildRuleSetGroupFromInterpreted, pathifyRuleSetGroup, pathifyProperties, extractComponentReferences, buildComponentRuleSetFromInterpreted, buildSubsystemModel, buildThemeModel, buildTokenMap, } from "./buildModel";
|
|
12
|
+
export type { SubsystemModelInput, BuildThemeModelInput, } from "./buildModel";
|
|
13
|
+
export type { MergedResponsiveEntry, MergedRuleSet, RuleSetReference, } from "./mergeRuleSet";
|
|
14
|
+
export { mergeComponentRuleSet, parseRuleSetReference, } from "./mergeRuleSet";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interpreted-recipe shape consumed by the Model builders.
|
|
3
|
+
*
|
|
4
|
+
* A subsystem's `interpretRecipe` resolves each authored recipe declaration to a
|
|
5
|
+
* format-neutral {@link Ref} — a token-path reference (`{ ref: "colors.primary" }`,
|
|
6
|
+
* optionally carrying the resolved literal in `value`) or a plain literal
|
|
7
|
+
* (`{ value: "12px 20px" }`). It emits refs **directly**; the Model builder no longer
|
|
8
|
+
* string-parses `var(--…)` back into refs (that coupling is gone). Serialization to a
|
|
9
|
+
* concrete format (the `var(--…)` string, an `$…`, an inlined value) is the adapter's
|
|
10
|
+
* job (step 1).
|
|
11
|
+
*
|
|
12
|
+
* The two condition axes (state / breakpoint …) are kept **separate** from the
|
|
13
|
+
* declarations, so an override is `{ …condition, declarations }` — no flat object
|
|
14
|
+
* mixing string condition keys with declaration refs.
|
|
15
|
+
*/
|
|
16
|
+
import type { Ref } from "./model";
|
|
17
|
+
/** A recipe variant's declarations after interpretation — property → resolved {@link Ref}. */
|
|
18
|
+
export type RecipeDeclarations = Record<string, Ref>;
|
|
19
|
+
/** One interpreted override: its condition (state and/or breakpoint …) + declaration refs. */
|
|
20
|
+
export type InterpretedRecipeOverride<TBreakpoint extends string> = {
|
|
21
|
+
/** Present for breakpoint-conditioned overrides; absent for pure-state / container overrides. */
|
|
22
|
+
breakpoint?: TBreakpoint;
|
|
23
|
+
query?: "min" | "max" | "exact";
|
|
24
|
+
state?: string;
|
|
25
|
+
variant?: string;
|
|
26
|
+
target?: string;
|
|
27
|
+
orientation?: "landscape" | "portrait";
|
|
28
|
+
/** Container-query axis (§10.5): the named container + its size-name (in place of `breakpoint`). */
|
|
29
|
+
container?: string;
|
|
30
|
+
size?: string;
|
|
31
|
+
declarations: RecipeDeclarations;
|
|
32
|
+
};
|
|
33
|
+
export type InterpretedRecipeVariant<TBreakpoint extends string> = {
|
|
34
|
+
base: RecipeDeclarations;
|
|
35
|
+
responsive: InterpretedRecipeOverride<TBreakpoint>[];
|
|
36
|
+
};
|
|
37
|
+
export type InterpretedRecipeGroup<TBreakpoint extends string> = Record<string, InterpretedRecipeVariant<TBreakpoint>>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-neutral component merge (§9c).
|
|
3
|
+
*
|
|
4
|
+
* `mergeComponentRuleSet` flattens one component variant into a single
|
|
5
|
+
* self-contained rule-set: its referenced recipes' declarations + its own `css`
|
|
6
|
+
* delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s
|
|
7
|
+
* carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or
|
|
8
|
+
* `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.
|
|
9
|
+
*
|
|
10
|
+
* This is the ONLY new machinery the `components` emit mode needs, shared by the CSS
|
|
11
|
+
* and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never
|
|
12
|
+
* materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored
|
|
13
|
+
* `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).
|
|
14
|
+
*
|
|
15
|
+
* Precedence (LOCKED, §9): authored **reference order** first (later refs override
|
|
16
|
+
* earlier per property key), then the component's own declarations **last / highest**
|
|
17
|
+
* (`css` delta wins over subsystem recipes). Same rule per condition bucket.
|
|
18
|
+
*/
|
|
19
|
+
import type { Orientation, Ref, ResponsiveQueryKind, ThemeModel } from "./model";
|
|
20
|
+
/**
|
|
21
|
+
* One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`
|
|
22
|
+
* key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`
|
|
23
|
+
* (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.
|
|
24
|
+
*/
|
|
25
|
+
export type MergedResponsiveEntry = {
|
|
26
|
+
breakpoint?: string;
|
|
27
|
+
query?: ResponsiveQueryKind;
|
|
28
|
+
orientation?: Orientation;
|
|
29
|
+
state?: string;
|
|
30
|
+
container?: string;
|
|
31
|
+
size?: string;
|
|
32
|
+
declarations: Record<string, Ref>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* A component variant flattened into one self-contained rule-set.
|
|
36
|
+
*
|
|
37
|
+
* - `base` — merged no-condition declarations.
|
|
38
|
+
* - `states` — merged declarations keyed by `state` (no breakpoint).
|
|
39
|
+
* - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.
|
|
40
|
+
* - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,
|
|
41
|
+
* first-appearance order. What non-inline rendering tree-shakes the vars file to.
|
|
42
|
+
*/
|
|
43
|
+
export type MergedRuleSet = {
|
|
44
|
+
base: Record<string, Ref>;
|
|
45
|
+
states: Record<string, Record<string, Ref>>;
|
|
46
|
+
responsive: MergedResponsiveEntry[];
|
|
47
|
+
referencedPaths: string[];
|
|
48
|
+
};
|
|
49
|
+
/** The address parts of a component reference (`"colors:solid.primary"`). */
|
|
50
|
+
export type RuleSetReference = {
|
|
51
|
+
subsystem: string;
|
|
52
|
+
group: string;
|
|
53
|
+
variant: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Parse a component reference (`"subsystem:group.variant"`) into its address parts.
|
|
57
|
+
* Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays
|
|
58
|
+
* for the option-C class-list path). Returns `undefined` on a malformed reference.
|
|
59
|
+
*/
|
|
60
|
+
export declare const parseRuleSetReference: (reference: string) => RuleSetReference | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Flatten one component variant into a self-contained {@link MergedRuleSet}.
|
|
63
|
+
*
|
|
64
|
+
* Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`
|
|
65
|
+
* (resolved in authored order), own base `declarations`, and `overrides` — and unions
|
|
66
|
+
* them under the locked precedence. Throws on a missing component or an unresolved reference.
|
|
67
|
+
*/
|
|
68
|
+
export declare const mergeComponentRuleSet: (model: ThemeModel, group: string, variant: string) => MergedRuleSet;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-neutral Model types (clean-room port of `core/common/model.ts`).
|
|
3
|
+
*
|
|
4
|
+
* The representation every subsystem produces. The Model has just two kinds of
|
|
5
|
+
* thing — **tokens** (`PropertyModel`) and **rule-sets** (`RuleSet`) — and one
|
|
6
|
+
* shared reference node (`Ref`) for every leaf. Adapters lower the Model to
|
|
7
|
+
* CSS / SCSS / styled-components / JSON; the Model itself commits to no format.
|
|
8
|
+
*
|
|
9
|
+
* See `.notes/reference/model-first-pipeline-plan.md` for the full design.
|
|
10
|
+
*/
|
|
11
|
+
/** A resolved literal value a `Ref` can carry (unit-less, no `var()` / `$`). */
|
|
12
|
+
export type Literal = string | number;
|
|
13
|
+
export type ResponsiveQueryKind = "min" | "max" | "exact";
|
|
14
|
+
export type Orientation = "landscape" | "portrait";
|
|
15
|
+
import type { Unit, ShadowDimension } from "../units";
|
|
16
|
+
/**
|
|
17
|
+
* A structured box-shadow layer (§15) — geometry as unit-less px numbers, `color` a **token-path
|
|
18
|
+
* ref** (`"colors.shadow"`) the adapter resolves late (CSS `var(--…)`, RN `shadowColor`). Kept
|
|
19
|
+
* structured (not a pre-serialized CSS string) so non-CSS adapters can lower each field; the CSS
|
|
20
|
+
* adapter composes `<offsetX> <offsetY> <blur> <spread> var(--color)`. A box-shadow value is one
|
|
21
|
+
* or more layers ({@link StructuredValue}).
|
|
22
|
+
*/
|
|
23
|
+
export type ShadowLayer = {
|
|
24
|
+
offsetX?: ShadowDimension;
|
|
25
|
+
offsetY?: ShadowDimension;
|
|
26
|
+
blur?: ShadowDimension;
|
|
27
|
+
spread?: ShadowDimension;
|
|
28
|
+
/** Canonical `colors.*` token path (never an embedded literal — §15.1). Translucency comes from
|
|
29
|
+
* the referenced colour itself — an `alpha` colour variant (§13.3) — not a shadow-level field. */
|
|
30
|
+
color?: string;
|
|
31
|
+
inset?: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A structured transition part (§15) — `property` + `duration`/`delay` in **ms** (numbers) +
|
|
35
|
+
* `timingFunction` (keyword or `cubic-bezier(…)` string, not a ref in v1 — §15.5). Kept structured
|
|
36
|
+
* so RN/JSON can lower it; the CSS adapter composes `<property> <duration>ms <timing> <delay>ms`.
|
|
37
|
+
* A transition value is one or more parts ({@link StructuredValue}).
|
|
38
|
+
*/
|
|
39
|
+
export type TransitionPart = {
|
|
40
|
+
property: string;
|
|
41
|
+
duration?: number;
|
|
42
|
+
timingFunction?: string;
|
|
43
|
+
delay?: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* A structured compound leaf value (§15) — the Model's format-neutral carriage for shadow /
|
|
47
|
+
* transition tokens whose value is not a single {@link Literal}. Always an **array** (canonicalized
|
|
48
|
+
* in the owning subsystem's coerce step): a single-layer/part token is a one-element array, so
|
|
49
|
+
* adapters map+join uniformly. Carried on {@link Ref.struct}; `Ref.value` stays a `Literal` cache.
|
|
50
|
+
*/
|
|
51
|
+
export type StructuredValue = ShadowLayer[] | TransitionPart[];
|
|
52
|
+
/**
|
|
53
|
+
* The one shared reference node — every leaf in both the property and rule-set
|
|
54
|
+
* models is a `Ref`. At least one of `ref` / `value` is present.
|
|
55
|
+
*
|
|
56
|
+
* - `ref` — canonical token path in the model namespace, e.g. `"color.primary.dark"`.
|
|
57
|
+
* A property leaf's `ref` is its own address; a rule-set declaration's
|
|
58
|
+
* `ref` points into that namespace. The adapter turns it into
|
|
59
|
+
* `var(--…)` / `$…` / `theme.…` / the inlined value.
|
|
60
|
+
* - `value` — the resolved literal (for inlining, or when there is no token).
|
|
61
|
+
* - `fn` — value-derivation fn name (run by the derivation registry), e.g. `"darken"`:
|
|
62
|
+
* the token's value = `fn(resolve(ref), arg)`. Requires `ref`.
|
|
63
|
+
* - `arg` — argument passed to the derivation `fn` (also where synthesis config is retained).
|
|
64
|
+
* - `wrap` — adapter OUTPUT wrap on a rule-set declaration, e.g. `"blur"` → CSS `blur(<value>)`.
|
|
65
|
+
* Distinct from `fn`; never appears on a token.
|
|
66
|
+
* - `struct`— a structured compound value (§15) for shadow / transition tokens whose value is not a
|
|
67
|
+
* single `Literal` (an array of {@link ShadowLayer} / {@link TransitionPart}). Additive:
|
|
68
|
+
* adapters that understand the structure compose it; `value` remains the `Literal` cache
|
|
69
|
+
* (undefined for a purely-structured token). Never appears on a rule-set declaration ref.
|
|
70
|
+
* - `unit` — the resolved length unit on a length leaf (§21). Present only after unit resolution has
|
|
71
|
+
* tagged this leaf (`{ value: 24, unit: "rem" }`); absent means unit-less (opacity/zIndex)
|
|
72
|
+
* or a raw-string value. Adapters stringify a length leaf as `value + (unit ?? "")`.
|
|
73
|
+
*/
|
|
74
|
+
export type Ref = {
|
|
75
|
+
ref?: string;
|
|
76
|
+
value?: Literal;
|
|
77
|
+
fn?: string;
|
|
78
|
+
arg?: unknown;
|
|
79
|
+
/**
|
|
80
|
+
* dec.2 — an ordered derivation CHAIN applied to the resolved `ref` (folded left-to-right by
|
|
81
|
+
* `resolveToken`: `value = modifiers.reduce((v, {fn,arg}) => registry[fn](v, arg), resolve(ref))`).
|
|
82
|
+
* Set by the `{ ref, modifiers }` authoring grammar; single-step synthesized derivations
|
|
83
|
+
* (tonal steps / harmony) still use the flat `fn`/`arg`. Present ⇒ `fn`/`arg` are absent.
|
|
84
|
+
*/
|
|
85
|
+
modifiers?: Array<{
|
|
86
|
+
fn: string;
|
|
87
|
+
arg?: unknown;
|
|
88
|
+
}>;
|
|
89
|
+
wrap?: string;
|
|
90
|
+
struct?: StructuredValue;
|
|
91
|
+
unit?: Unit;
|
|
92
|
+
/**
|
|
93
|
+
* §W6b — an **external** token: a passthrough to a CSS variable a *parent* theme defines. The
|
|
94
|
+
* string is the literal parent var name (`--dt-colors-brand` / `--mat-sys-bg`). When present the
|
|
95
|
+
* token is never emitted as a definition (the parent owns it); references lower to `var(<external>)`
|
|
96
|
+
* verbatim, `resolveToken` yields that `var(…)` string, and colour synthesis is skipped.
|
|
97
|
+
*/
|
|
98
|
+
external?: string;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* A property (token) after `buildPropertyModel`: resolved values kept as `Ref`s,
|
|
102
|
+
* variants, and responsive as structured data. Subsystem-specific sibling nodes
|
|
103
|
+
* (e.g. colors' `text`) live in `extras`. ({@link PropertyOverride} + {@link OverrideCondition}
|
|
104
|
+
* are defined below, in the shared rule-set section — modes/responsive/states share that spine.)
|
|
105
|
+
*/
|
|
106
|
+
/**
|
|
107
|
+
* dec.3 — one property variant in the Model. `base` is the variant's primary value (a literal or
|
|
108
|
+
* derived `Ref`, or an alias to the property base when the author omitted it — base optional + inherit).
|
|
109
|
+
* `extras` are the variant's own sibling values (e.g. colours' `text`), each lowered to
|
|
110
|
+
* `--<prop>-<variant>-<extra>`, exactly like the property-level {@link PropertyModel.extras}.
|
|
111
|
+
*/
|
|
112
|
+
export type VariantModel = {
|
|
113
|
+
base: Ref;
|
|
114
|
+
extras?: Record<string, Ref>;
|
|
115
|
+
};
|
|
116
|
+
export type PropertyModel = {
|
|
117
|
+
base: Ref;
|
|
118
|
+
variants?: Record<string, VariantModel>;
|
|
119
|
+
/**
|
|
120
|
+
* Appearance-mode overrides (§10.3) — a **list** of {@link PropertyOverride}s, each carrying its
|
|
121
|
+
* `mode` (+ optional `target` to scope into a variant's var) and an `overrides` field-map (`base`
|
|
122
|
+
* + subsystem extras like colours' `text`, each a literal or derived `Ref`). A list (not a
|
|
123
|
+
* `mode → fields` map) so one mode can carry several targeted entries. Adapters group by `mode`
|
|
124
|
+
* and realize each as conditional blocks (CSS: `prefers-color-scheme` media + `[data-theme]`).
|
|
125
|
+
*/
|
|
126
|
+
modes?: PropertyOverride[];
|
|
127
|
+
responsive?: PropertyOverride[];
|
|
128
|
+
extras?: Record<string, Ref>;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* The **shared override spine** — the one condition/target structure every override array entry
|
|
132
|
+
* carries (property `modes` / `responsive`, recipe `states` / `responsive`). Each array fills only
|
|
133
|
+
* the axes meaningful to it; all are optional here. Three axes of intent:
|
|
134
|
+
* - **WHEN** — `mode` (appearance mode) · `state` (recipe pseudo-state) · `breakpoint` (+`query` /
|
|
135
|
+
* `orientation`) · `container` + `size` (container-query, in place of `breakpoint`).
|
|
136
|
+
* - **WHERE** — `target`: scope the override into a variant's var / a `<item>-<variant>` sibling
|
|
137
|
+
* rule (omit → the base var / base rule).
|
|
138
|
+
* - **READ** — `ref` (dec.5 read-source: the destination swaps to this variant's var) · `variant`
|
|
139
|
+
* (recipe swap to a sibling rule-set of the same group).
|
|
140
|
+
* `PropertyOverride` and `RuleSetOverride` extend this with their respective payload record.
|
|
141
|
+
*/
|
|
142
|
+
export type OverrideCondition = {
|
|
143
|
+
/** appearance-mode condition (property modes; property responsive via dec.9). */
|
|
144
|
+
mode?: string;
|
|
145
|
+
/** recipe pseudo-state condition (recipe states + responsive). */
|
|
146
|
+
state?: string;
|
|
147
|
+
breakpoint?: string;
|
|
148
|
+
query?: ResponsiveQueryKind;
|
|
149
|
+
orientation?: Orientation;
|
|
150
|
+
/** Container-query axis (§10.5): the named container this override responds to (in place of `breakpoint`). */
|
|
151
|
+
container?: string;
|
|
152
|
+
/** The size-name in that container's threshold scale (used with `container`). */
|
|
153
|
+
size?: string;
|
|
154
|
+
/** dec.5 READ source: the destination var swaps to this variant's var (`var(--<prop>-<ref>)`). */
|
|
155
|
+
ref?: string;
|
|
156
|
+
/** swap to a sibling rule-set of the same group (recipe responsive). */
|
|
157
|
+
variant?: string;
|
|
158
|
+
/** WHERE — scope the override into a variant's var / a sibling rule-set's rule. */
|
|
159
|
+
target?: string;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* One conditioned override on a **property's tokens** (a `modes` or `responsive` entry). The payload
|
|
163
|
+
* is `field → Ref` (`base` + subsystem extras like colours' `text`), each a literal or derived `Ref`.
|
|
164
|
+
* Shares {@link OverrideCondition} with recipe overrides; a mode entry carries `mode`, a responsive
|
|
165
|
+
* entry carries `breakpoint` (+ optionally `mode`), either may carry `target`.
|
|
166
|
+
*/
|
|
167
|
+
export type PropertyOverride = OverrideCondition & {
|
|
168
|
+
overrides?: Record<string, Ref>;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* @deprecated Use {@link PropertyOverride}. Retained as an alias during the unified-override-array
|
|
172
|
+
* migration; a property `responsive` entry is a `PropertyOverride`.
|
|
173
|
+
*/
|
|
174
|
+
export type PropertyResponsiveOverride = PropertyOverride;
|
|
175
|
+
/** One conditioned override on a rule-set — `state` and/or `breakpoint` + its declarations. */
|
|
176
|
+
export type RuleSetOverride = OverrideCondition & {
|
|
177
|
+
declarations?: Record<string, Ref>;
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* One `globals` element variant (§9) — a named, delta-only modifier on a themed element rule-set.
|
|
181
|
+
* Carries just what it changes (its own `declarations` + condition `overrides`); the cascade
|
|
182
|
+
* supplies the base. Adapters render it as a higher-specificity selector — the CSS adapter as a
|
|
183
|
+
* self-scoped class (`a.subtle`), the styled-components / SCSS adapters as a nested `&.<name>`
|
|
184
|
+
* block. Kept structural (a base selector + this named-variant map) so each adapter builds its own
|
|
185
|
+
* idiom, rather than a pre-joined selector baked into the Model.
|
|
186
|
+
*/
|
|
187
|
+
export type GlobalsVariant = {
|
|
188
|
+
declarations: Record<string, Ref>;
|
|
189
|
+
overrides: RuleSetOverride[];
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* A named `{ declarations, overrides }` block — the one shape for everything on the
|
|
193
|
+
* non-token side. Recipes are the authored flavor; layout grids/stacks/container/columns
|
|
194
|
+
* are presets/generated; reset/base rule-sets target raw element selectors. Keyed by real
|
|
195
|
+
* kebab-case CSS properties (`"box-sizing"`, `"font-size"`).
|
|
196
|
+
*
|
|
197
|
+
* - `kind` — `"recipe"` (composable; default), `"utility"` (apply-in-markup, e.g. columns),
|
|
198
|
+
* `"reset"` (the `globals` normalization preset layer — targets an explicit
|
|
199
|
+
* `selector` at specificity-0 `:where(sel)`), or `"globals"` (a themed element
|
|
200
|
+
* rule — targets a bare `selector` at a higher tier, carrying `variants`).
|
|
201
|
+
* - `selector` — `kind:"reset"` / `kind:"globals"` only: the raw selector this rule-set targets
|
|
202
|
+
* (element `h1` / grouped `h1,h2` / universal `*` / attribute `[hidden]` / pseudo
|
|
203
|
+
* `::placeholder`). `reset` wraps it for specificity-0 (`:where(sel)`); `globals`
|
|
204
|
+
* emits it bare; absent for minted classes.
|
|
205
|
+
* - `references` — components only: `"subsystem:group.variant"` recipe-level refs (composition).
|
|
206
|
+
* - `declarations` — base (no condition).
|
|
207
|
+
* - `overrides` — the unified state/breakpoint condition list.
|
|
208
|
+
* - `variants` — `kind:"globals"` only: named delta modifiers (§9), each an adapter-scoped
|
|
209
|
+
* higher-specificity variant of the element (`a.subtle` / `&.subtle`).
|
|
210
|
+
*/
|
|
211
|
+
export type RuleSet = {
|
|
212
|
+
kind?: "recipe" | "utility" | "reset" | "globals";
|
|
213
|
+
selector?: string;
|
|
214
|
+
references?: string[];
|
|
215
|
+
declarations: Record<string, Ref>;
|
|
216
|
+
overrides: RuleSetOverride[];
|
|
217
|
+
variants?: Record<string, GlobalsVariant>;
|
|
218
|
+
};
|
|
219
|
+
/** A named group of rule-sets: variant/name → `RuleSet` (e.g. `solid`, `grids`, `columns`). */
|
|
220
|
+
export type RuleSetGroup = Record<string, RuleSet>;
|
|
221
|
+
/**
|
|
222
|
+
* One step of a keyframe — its stop position + the declarations at that stop. The `stop` is the
|
|
223
|
+
* authored key kept **verbatim** (`"from"`, `"to"`, `"0%"`, `"50%"`, even a grouped `"0%, 100%"`),
|
|
224
|
+
* so the representation commits to no format — a CSS adapter renders `<stop> { … }`, an SC adapter
|
|
225
|
+
* feeds its `keyframes` helper, an RN adapter maps stops to `Animated` interpolation points.
|
|
226
|
+
* Declarations are `Ref`s: a literal geometric value (`{ value: 0 }`) or a token-path reference
|
|
227
|
+
* (`{ ref: "colors.surface" }`) resolved late by the adapter, so a keyframe can animate a themed value.
|
|
228
|
+
*/
|
|
229
|
+
export type KeyframeStep = {
|
|
230
|
+
stop: string;
|
|
231
|
+
declarations: Record<string, Ref>;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* A named keyframe definition — an **ordered** list of steps (authoring order preserved). The first
|
|
235
|
+
* Model member that is neither a token ({@link PropertyModel}) nor a class/selector rule-set
|
|
236
|
+
* ({@link RuleSet}): an `@keyframes`-shaped at-rule with nested step selectors. Adapters realize it
|
|
237
|
+
* (CSS: an `@keyframes name { … }` at-rule).
|
|
238
|
+
*/
|
|
239
|
+
export type Keyframe = {
|
|
240
|
+
steps: KeyframeStep[];
|
|
241
|
+
};
|
|
242
|
+
/** One subsystem's slice of the Model: its tokens, its rule-set groups, and its keyframes. */
|
|
243
|
+
export type SubsystemModel = {
|
|
244
|
+
properties?: Record<string, PropertyModel>;
|
|
245
|
+
ruleSets?: Record<string, RuleSetGroup>;
|
|
246
|
+
/** Named keyframe definitions (§10.2) — `name → {@link Keyframe}`. Present only for the animation subsystem. */
|
|
247
|
+
keyframes?: Record<string, Keyframe>;
|
|
248
|
+
};
|
|
249
|
+
/** One named query container (§10.5) — its `container-type` + `sizeName → px` threshold scale. */
|
|
250
|
+
export type ContainerModel = {
|
|
251
|
+
type: "inline-size" | "size";
|
|
252
|
+
sizes: Record<string, number>;
|
|
253
|
+
};
|
|
254
|
+
/** The whole theme as format-neutral data — serializable as-is (build-time emit). */
|
|
255
|
+
export type ThemeModel = {
|
|
256
|
+
breakpoints: Record<string, number>;
|
|
257
|
+
/** Named query containers (§10.5) — present only when the theme authors `containers`. Additive. */
|
|
258
|
+
containers?: Record<string, ContainerModel>;
|
|
259
|
+
subsystems: Record<string, SubsystemModel>;
|
|
260
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).
|
|
3
|
+
*
|
|
4
|
+
* `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch
|
|
5
|
+
* adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`
|
|
6
|
+
* / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the
|
|
7
|
+
* breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the
|
|
8
|
+
* contract; the output is discarded.
|
|
9
|
+
*
|
|
10
|
+
* Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder
|
|
11
|
+
* — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo
|
|
12
|
+
* guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null
|
|
13
|
+
* object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`
|
|
14
|
+
* build the Model + token map exactly as any adapter would, and keeps `src/build` free of every
|
|
15
|
+
* adapter package.
|
|
16
|
+
*
|
|
17
|
+
* It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted
|
|
18
|
+
* aggregators for free), just with render primitives that produce empty output.
|
|
19
|
+
*/
|
|
20
|
+
import type { ThemeAdapter } from "./ThemeAdapter";
|
|
21
|
+
/**
|
|
22
|
+
* A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it
|
|
23
|
+
* whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)
|
|
24
|
+
* and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createNoopAdapter(): ThemeAdapter<string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared normalize primitives + the normalize-layer vocabulary (Step 0b).
|
|
3
|
+
*
|
|
4
|
+
* Pure, format-neutral: raw theme config to normalized property / recipe shapes,
|
|
5
|
+
* validating breakpoint / variant / target / state references along the way.
|
|
6
|
+
* Subsystem normalizeProperty hooks (colors steps, typography scale, layout none)
|
|
7
|
+
* live under src/next/subsystems/-star-/normalize.ts and layer on top.
|
|
8
|
+
*/
|
|
9
|
+
export * from "./types";
|
|
10
|
+
export { normalizePropertyValue } from "./properties";
|
|
11
|
+
export { DEFAULT_RESPONSIVE_QUERY, normalizeResponsiveOverrides, validateNormalizedResponsiveRefs, } from "./responsive";
|
|
12
|
+
export { normalizeRecipeGroup } from "./recipes";
|
|
13
|
+
export type { RecipeNormalizationOptions } from "./recipes";
|
|
14
|
+
export { createRecipeVariantResolver } from "./recipeResolver";
|
|
15
|
+
export type { RecipeInterpreter, RecipeVariantResolver, CreateRecipeVariantResolverOptions, } from "./recipeResolver";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property normalization — the entry point that turns any authored property value
|
|
3
|
+
* into the canonical {@link NormalizedPropertyValue} shape.
|
|
4
|
+
*
|
|
5
|
+
* Collapses the three authoring forms (a bare value, or an extended object with
|
|
6
|
+
* `base` / `variants` / `responsive`, plus subsystem `extra` fields) into one shape:
|
|
7
|
+
* a resolved `base`, a normalized `variants` map, and a normalized `responsive` list.
|
|
8
|
+
*/
|
|
9
|
+
import { NormalizedPropertyValue, PropertyNormalizationOptions, PropertyValue } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Normalize any authored property value into the canonical {@link NormalizedPropertyValue}.
|
|
12
|
+
*
|
|
13
|
+
* @param value A bare value or an extended `{ base, variants?, responsive?, …extra }` object.
|
|
14
|
+
* @param options `propertyPath` (error labels), `fallbackBase`, `coerceValue`, and
|
|
15
|
+
* `allowedBreakpoints` (responsive breakpoint validation).
|
|
16
|
+
* @returns `{ base, responsive, variants?, …extra }` — `responsive` always an array,
|
|
17
|
+
* each entry with its `query` defaulted; `variants` normalized or `undefined`.
|
|
18
|
+
* @throws If no base value can be resolved, or a responsive entry fails validation.
|
|
19
|
+
*/
|
|
20
|
+
export declare const normalizePropertyValue: <TValue, TExtra extends Record<string, unknown> = Record<string, never>, TBreakpoint extends string = string>(value: PropertyValue<TValue, TExtra, TBreakpoint>, options?: PropertyNormalizationOptions<TValue, TBreakpoint>) => NormalizedPropertyValue<TValue, TExtra, TBreakpoint>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy, memoized, cycle-safe recipe-variant resolver (clean-room port of
|
|
3
|
+
* `core/common/recipeResolver.ts`).
|
|
4
|
+
*
|
|
5
|
+
* A recipe variant may reference a sibling variant (responsive `variant:` swaps). The
|
|
6
|
+
* resolver interprets each variant on demand, caches the result, and detects cycles
|
|
7
|
+
* (throwing with the offending chain). The interpret callback receives a `resolve`
|
|
8
|
+
* function so it can pull a sibling's already-interpreted form.
|
|
9
|
+
*/
|
|
10
|
+
import type { NormalizedRecipeGroup, NormalizedRecipeVariant } from "./types";
|
|
11
|
+
export type RecipeInterpreter<TProps extends Record<string, unknown>, TBreakpoint extends string, TInterpreted> = (variantName: string, variant: NormalizedRecipeVariant<TProps, TBreakpoint>, resolve: (variantName: string) => TInterpreted) => TInterpreted;
|
|
12
|
+
export type RecipeVariantResolver<TInterpreted> = {
|
|
13
|
+
resolve: (variantName: string) => TInterpreted;
|
|
14
|
+
resolveAll: () => Record<string, TInterpreted>;
|
|
15
|
+
};
|
|
16
|
+
export type CreateRecipeVariantResolverOptions = {
|
|
17
|
+
groupPath?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const createRecipeVariantResolver: <TProps extends Record<string, unknown>, TBreakpoint extends string, TInterpreted>(group: NormalizedRecipeGroup<TProps, TBreakpoint>, interpret: RecipeInterpreter<TProps, TBreakpoint, TInterpreted>, options?: CreateRecipeVariantResolverOptions) => RecipeVariantResolver<TInterpreted>;
|