@animus-ui/system 0.1.1-beta.2 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -4
- package/dist/Animus.d.ts +2 -3
- package/dist/Animus.d.ts.map +1 -1
- package/dist/AnimusExtended.d.ts +2 -3
- package/dist/AnimusExtended.d.ts.map +1 -1
- package/dist/SystemBuilder.d.ts +27 -8
- package/dist/SystemBuilder.d.ts.map +1 -1
- package/dist/appearance/index.d.ts +75 -0
- package/dist/appearance/index.d.ts.map +1 -0
- package/dist/appearance/index.js +179 -0
- package/dist/bootstrap/createAppearanceBootstrap.d.ts +71 -0
- package/dist/bootstrap/createAppearanceBootstrap.d.ts.map +1 -0
- package/dist/bootstrap/index.d.ts +2 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +98 -0
- package/dist/composeWithContext.d.ts.map +1 -1
- package/dist/composeWithContext.js +43 -22
- package/dist/conditions.d.ts +163 -0
- package/dist/conditions.d.ts.map +1 -0
- package/dist/{createComposedFamily-DSE2ZuRE.js → createComposedFamily-DJ2aqfqN.js} +141 -67
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +645 -23
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/resolveClasses.d.ts.map +1 -1
- package/dist/runtime-entry.js +1 -1
- package/dist/selectors.d.ts +22 -0
- package/dist/selectors.d.ts.map +1 -1
- package/dist/theme/createTheme.d.ts +47 -4
- package/dist/theme/createTheme.d.ts.map +1 -1
- package/dist/types/component.d.ts +27 -10
- package/dist/types/component.d.ts.map +1 -1
- package/dist/types/config.d.ts +124 -11
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/props.d.ts +0 -4
- package/dist/types/props.d.ts.map +1 -1
- package/dist/types/theme.d.ts +132 -0
- package/dist/types/theme.d.ts.map +1 -1
- package/dist/utils/deepMerge.d.ts +0 -3
- package/dist/utils/deepMerge.d.ts.map +1 -1
- package/package.json +12 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAppearanceBootstrap.d.ts","sourceRoot":"","sources":["../../src/bootstrap/createAppearanceBootstrap.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE;QACR,2DAA2D;QAC3D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,wBAAwB,EAC/B,OAAO,GAAE,0BAA+B,GACvC,2BAA2B,CAsE7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
//#region src/bootstrap/createAppearanceBootstrap.ts
|
|
3
|
+
/**
|
|
4
|
+
* Appearance bootstrap generator — build-tooling surface ONLY.
|
|
5
|
+
*
|
|
6
|
+
* This module is reachable exclusively from the `@animus-ui/system/bootstrap`
|
|
7
|
+
* subpath. It is never imported by the component/runtime entries, so no part of
|
|
8
|
+
* it (including the storage keys below) can reach an extracted application
|
|
9
|
+
* bundle.
|
|
10
|
+
*/
|
|
11
|
+
/** The single versioned appearance record key. */
|
|
12
|
+
const DEFAULT_STORAGE_KEY = "animus:appearance";
|
|
13
|
+
/**
|
|
14
|
+
* Pre-record key read once, only when the record is absent. Never written —
|
|
15
|
+
* migration is read-only by contract.
|
|
16
|
+
*/
|
|
17
|
+
const LEGACY_STORAGE_KEY = "color-mode";
|
|
18
|
+
/** The mode axis attribute. Its ABSENCE means "follow the OS" (D4). */
|
|
19
|
+
const MODE_ATTRIBUTE = "data-color-mode";
|
|
20
|
+
/**
|
|
21
|
+
* Reserved mode name. `system` is modeled as attribute absence and can never be
|
|
22
|
+
* a declared mode, so it must never enter the generated allowlist.
|
|
23
|
+
*/
|
|
24
|
+
const RESERVED_MODE_NAME = "system";
|
|
25
|
+
/** The only appearance-record version this generation of the snippet reads. */
|
|
26
|
+
const RECORD_VERSION = 1;
|
|
27
|
+
/**
|
|
28
|
+
* Renders a string as a JS literal that is also safe inside an inline
|
|
29
|
+
* `<script>` and inside a consumer's own string context:
|
|
30
|
+
* - `<` is escaped, so an embedded value can never open a closing tag or an
|
|
31
|
+
* HTML comment;
|
|
32
|
+
* - U+2028/U+2029 are escaped, so `code` survives being nested in string
|
|
33
|
+
* contexts that still treat them as line terminators.
|
|
34
|
+
*
|
|
35
|
+
* Character-wise on purpose: this file stays pure ASCII, so no invisible
|
|
36
|
+
* separator can hide in it.
|
|
37
|
+
*/
|
|
38
|
+
function inlineLiteral(value) {
|
|
39
|
+
let out = "";
|
|
40
|
+
for (const char of JSON.stringify(value)) {
|
|
41
|
+
if (char === "<") {
|
|
42
|
+
out += "\\u003c";
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const code = char.codePointAt(0);
|
|
46
|
+
if (code === 8232 || code === 8233) {
|
|
47
|
+
out += `\\u${code.toString(16)}`;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
out += char;
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Builds the inline appearance-restoration script for a built theme.
|
|
56
|
+
*
|
|
57
|
+
* The generated snippet, before first paint:
|
|
58
|
+
* 1. reads the appearance record from `storageKey`, falling back to the legacy
|
|
59
|
+
* `color-mode` key ONLY when the record is absent (missing key, or an empty
|
|
60
|
+
* string, which is not a record);
|
|
61
|
+
* 2. accepts the record only at version `1` — a future or absent version is
|
|
62
|
+
* treated as NO record, because an older snippet cannot interpret a newer
|
|
63
|
+
* record and absence is the neutral fail-safe;
|
|
64
|
+
* 3. sets `data-color-mode` when the resulting name is a declared mode;
|
|
65
|
+
* 4. removes the attribute for `system`, no record, an unreadable store, or an
|
|
66
|
+
* unknown mode — absence is how "follow the OS" is represented, so later OS
|
|
67
|
+
* changes apply with no script running.
|
|
68
|
+
*
|
|
69
|
+
* The failure semantics are deliberately asymmetric:
|
|
70
|
+
* - storage that THROWS on read (private browsing, blocked storage) means "no
|
|
71
|
+
* knowledge", so the attribute is REMOVED and the media-query fallback takes
|
|
72
|
+
* over; freezing a server-rendered mode would defeat that fallback;
|
|
73
|
+
* - a record that is PRESENT but unparseable means "storage is telling us
|
|
74
|
+
* something we cannot read", so the snippet exits leaving the server-rendered
|
|
75
|
+
* markup exactly as it was.
|
|
76
|
+
*
|
|
77
|
+
* It never writes storage, never calls `matchMedia`, and ignores the record's
|
|
78
|
+
* `theme` axis. Identical inputs always yield byte-identical output.
|
|
79
|
+
*
|
|
80
|
+
* @throws if the theme declares no color modes (a bootstrap without a mode
|
|
81
|
+
* allowlist could not validate anything), declares the reserved name
|
|
82
|
+
* `system`, or declares a blank mode name.
|
|
83
|
+
*/
|
|
84
|
+
function createAppearanceBootstrap(theme, options = {}) {
|
|
85
|
+
const { storageKey = DEFAULT_STORAGE_KEY } = options;
|
|
86
|
+
if (typeof storageKey !== "string" || storageKey === "") throw new Error("createAppearanceBootstrap: storageKey must be a non-empty string.");
|
|
87
|
+
const modeNames = Object.keys(theme?.manifest?.modes ?? {}).sort();
|
|
88
|
+
if (modeNames.length === 0) throw new Error("createAppearanceBootstrap: the theme declares no color modes — call addColorModes() before generating a bootstrap.");
|
|
89
|
+
if (modeNames.includes(RESERVED_MODE_NAME)) throw new Error(`createAppearanceBootstrap: '${RESERVED_MODE_NAME}' is a reserved mode name — the OS preference is represented by the absence of the ${MODE_ATTRIBUTE} attribute, never by a declared mode.`);
|
|
90
|
+
if (modeNames.some((name) => name.trim() === "")) throw new Error("createAppearanceBootstrap: a declared mode name is empty or whitespace-only — such a name matches no mode block and would suppress the system fallback.");
|
|
91
|
+
const code = `(function(){try{var m=${`[${modeNames.map(inlineLiteral).join(",")}]`};var r=document.documentElement;var v=null;try{v=localStorage.getItem(${inlineLiteral(storageKey)});}catch(e){v=null;}var n=null;if(typeof v==="string"&&v!==""){var p;try{p=JSON.parse(v);}catch(e){return;}n=p&&typeof p==="object"&&p.v===${RECORD_VERSION}?p.mode:null;}else{try{n=localStorage.getItem(${inlineLiteral(LEGACY_STORAGE_KEY)});}catch(e){n=null;}}if(typeof n==="string"&&m.indexOf(n)!==-1){r.setAttribute(${inlineLiteral(MODE_ATTRIBUTE)},n);}else{r.removeAttribute(${inlineLiteral(MODE_ATTRIBUTE)});}}catch(e){}})();`;
|
|
92
|
+
return {
|
|
93
|
+
code,
|
|
94
|
+
cspHash: `sha256-${createHash("sha256").update(code, "utf8").digest("base64")}`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { createAppearanceBootstrap };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composeWithContext.d.ts","sourceRoot":"","sources":["../src/composeWithContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,yBAAyB,EAI/B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACjD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"composeWithContext.d.ts","sourceRoot":"","sources":["../src/composeWithContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,yBAAyB,EAI/B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACjD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,KAAK,CAAC,EAExC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAAC,KAAK,CAAC,CAmEvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,EACrD,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAC7C,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,CA+DhD"}
|
|
@@ -18,18 +18,28 @@ function composeWithContext(slots, options) {
|
|
|
18
18
|
const result = {};
|
|
19
19
|
for (const [name, SourceComponent] of Object.entries(slots)) {
|
|
20
20
|
let Wrapper;
|
|
21
|
-
if (name === "Root")
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
if (name === "Root") {
|
|
22
|
+
const rootDefaults = SourceComponent.variantDefaults;
|
|
23
|
+
Wrapper = forwardRef((props, ref) => {
|
|
24
|
+
const shared = {};
|
|
25
|
+
for (const key of sharedKeySet) {
|
|
26
|
+
const value = props[key] ?? rootDefaults?.[key];
|
|
27
|
+
if (value != null) shared[key] = value;
|
|
28
|
+
}
|
|
29
|
+
return createElement(SourceComponent, {
|
|
30
|
+
...props,
|
|
31
|
+
ref
|
|
32
|
+
}, createElement(FamilyCtx.Provider, { value: shared }, props.children));
|
|
33
|
+
});
|
|
34
|
+
} else Wrapper = forwardRef((props, ref) => {
|
|
35
|
+
const inherited = useContext(FamilyCtx);
|
|
36
|
+
const merged = {
|
|
37
|
+
...inherited,
|
|
38
|
+
...props
|
|
39
|
+
};
|
|
40
|
+
for (const key of sharedKeySet) if (props[key] == null && key in inherited) merged[key] = inherited[key];
|
|
30
41
|
return createElement(SourceComponent, {
|
|
31
|
-
...
|
|
32
|
-
...props,
|
|
42
|
+
...merged,
|
|
33
43
|
ref
|
|
34
44
|
});
|
|
35
45
|
});
|
|
@@ -55,24 +65,35 @@ function createComposedFamilyWithContext(slots, config) {
|
|
|
55
65
|
const result = {};
|
|
56
66
|
for (const [slotName, SourceComponent] of Object.entries(slots)) {
|
|
57
67
|
let Wrapper;
|
|
58
|
-
if (slotName === "Root")
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
if (slotName === "Root") {
|
|
69
|
+
const rootDefaults = SourceComponent.variantDefaults;
|
|
70
|
+
Wrapper = forwardRef((props, ref) => {
|
|
71
|
+
const shared = {};
|
|
72
|
+
for (const key of keySet) {
|
|
73
|
+
const value = props[key] ?? rootDefaults?.[key];
|
|
74
|
+
if (value != null) shared[key] = value;
|
|
75
|
+
}
|
|
76
|
+
return createElement(SourceComponent, {
|
|
77
|
+
...props,
|
|
78
|
+
ref
|
|
79
|
+
}, createElement(Ctx.Provider, { value: shared }, props.children));
|
|
80
|
+
});
|
|
81
|
+
} else Wrapper = forwardRef((props, ref) => {
|
|
82
|
+
const inherited = useContext(Ctx);
|
|
83
|
+
const merged = {
|
|
84
|
+
...inherited,
|
|
85
|
+
...props
|
|
86
|
+
};
|
|
87
|
+
for (const key of keySet) if (props[key] == null && key in inherited) merged[key] = inherited[key];
|
|
67
88
|
return createElement(SourceComponent, {
|
|
68
|
-
...
|
|
69
|
-
...props,
|
|
89
|
+
...merged,
|
|
70
90
|
ref
|
|
71
91
|
});
|
|
72
92
|
});
|
|
73
93
|
Wrapper.displayName = `${name}.${slotName}`;
|
|
74
94
|
result[slotName] = Wrapper;
|
|
75
95
|
}
|
|
96
|
+
if (!("Root" in result)) throw new Error("createComposedFamilyWithContext(): No \"Root\" slot found. The root slot key must be exactly \"Root\" (PascalCase).");
|
|
76
97
|
return result;
|
|
77
98
|
}
|
|
78
99
|
//#endregion
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Condition alias registry — maps `_`-prefixed alias keys to at-rule condition
|
|
3
|
+
* strings (`@media` / `@container` / `@supports`). Parallel in shape to the
|
|
4
|
+
* selector alias registry (`selectors.ts`): alias → `{ value, order, kind }`.
|
|
5
|
+
*
|
|
6
|
+
* `order` determines cascade precedence within a layer (aliased conditions emit
|
|
7
|
+
* in registry order, per design D4). `kind` is inferred from the at-rule prefix
|
|
8
|
+
* of `value` (design D3) and drives which at-rule the extractor wraps the block
|
|
9
|
+
* in. Serialized into the manifest as the NEW `conditionAliases` field, leaving
|
|
10
|
+
* `selectorAliases` byte-for-byte unchanged.
|
|
11
|
+
*
|
|
12
|
+
* This module hosts BOTH the runtime registry and the authoring TYPE surface
|
|
13
|
+
* (inc 04): the augmentable `Conditions`/`Selectors` publication, the
|
|
14
|
+
* `ConditionsOf`/`SelectorsOf` extractors, the branded rejection types
|
|
15
|
+
* (`UnknownConditionAlias`/`UnknownAtRule`), and the shallow `RawAtRuleKey`
|
|
16
|
+
* shapes consumed by `ThemedCSSProps`' kind-dispatched arms. `addConditions()`
|
|
17
|
+
* constrains values to `@media`/`@container`/`@supports`-prefixed strings at
|
|
18
|
+
* the type level; `inferConditionKind` remains the runtime fail-loud check.
|
|
19
|
+
*/
|
|
20
|
+
/** The three condition kinds, inferred from the at-rule prefix of the value. */
|
|
21
|
+
export type ConditionKind = 'media' | 'container' | 'supports';
|
|
22
|
+
/**
|
|
23
|
+
* Augmentable registry of registered condition alias keys. Empty by default;
|
|
24
|
+
* a consumer publishes its registrations with:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* declare module '@animus-ui/system' {
|
|
28
|
+
* interface Conditions extends Record<ConditionsOf<typeof ds>, true> {}
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* When this interface is empty (no publication), `ThemedCSSProps` keeps
|
|
33
|
+
* `_`-prefixed block keys permissive — the same graceful degradation the
|
|
34
|
+
* augmentable `Theme` uses (empty theme ⇒ raw CSS values). Once populated, the
|
|
35
|
+
* validating arms engage: unknown `_` keys resolve to `UnknownConditionAlias`.
|
|
36
|
+
*
|
|
37
|
+
* JOINT NAMESPACE (inc-04 F8/F9): condition and selector aliases share the one
|
|
38
|
+
* `_` block-key namespace, so publishing EITHER `Conditions` OR `Selectors`
|
|
39
|
+
* flips BOTH namespaces from permissive to validating (see `KnownUnderscoreKey`
|
|
40
|
+
* in `types/config.ts`, whose gate reads `keyof Conditions | keyof Selectors`).
|
|
41
|
+
*
|
|
42
|
+
* Built-in condition aliases (`BUILT_IN_CONDITIONS`, design D8) are NOT members
|
|
43
|
+
* of this interface — they live in the static `BuiltInConditionAlias` union
|
|
44
|
+
* (`types/config.ts`), mirroring `BuiltInSelectorAlias`. Defaulting members here
|
|
45
|
+
* would make publication permanently non-empty and destroy the degradation
|
|
46
|
+
* contract above (a non-augmenting consumer with custom aliases would flip from
|
|
47
|
+
* permissive to branded-rejection the day built-ins shipped).
|
|
48
|
+
*/
|
|
49
|
+
export interface Conditions {
|
|
50
|
+
}
|
|
51
|
+
declare const CONDS_BRAND: unique symbol;
|
|
52
|
+
declare const SELS_BRAND: unique symbol;
|
|
53
|
+
/**
|
|
54
|
+
* Phantom brand carried on `build()`'s system output, threading the accumulated
|
|
55
|
+
* registered condition (`C`) and custom selector (`S`) alias-key unions to the
|
|
56
|
+
* consumer's augmentation site. Type-only — never present at runtime.
|
|
57
|
+
*/
|
|
58
|
+
export interface RegistryBrand<C extends string = never, S extends string = never> {
|
|
59
|
+
readonly [CONDS_BRAND]?: C;
|
|
60
|
+
readonly [SELS_BRAND]?: S;
|
|
61
|
+
}
|
|
62
|
+
/** Extract the registered condition alias keys from a built system. */
|
|
63
|
+
export type ConditionsOf<Sys> = Sys extends RegistryBrand<infer C, string> ? C : never;
|
|
64
|
+
/** Extract the registered custom selector alias keys from a built system. */
|
|
65
|
+
export type SelectorsOf<Sys> = Sys extends RegistryBrand<string, infer S> ? S : never;
|
|
66
|
+
/**
|
|
67
|
+
* Branded rejection for a `_`-prefixed block key that is neither a registered
|
|
68
|
+
* condition alias, a registered selector alias, a built-in selector alias,
|
|
69
|
+
* nor a built-in condition alias.
|
|
70
|
+
* The type name carries the offending key; the `hint` states the remedy. Never
|
|
71
|
+
* a bare `never` arm — `never` produces a misleading "not assignable to
|
|
72
|
+
* 'undefined'" (design D9, measured).
|
|
73
|
+
*/
|
|
74
|
+
export interface UnknownConditionAlias<K extends string> {
|
|
75
|
+
readonly __unknownConditionAlias: K;
|
|
76
|
+
readonly hint: `"${K}" is not a registered condition or selector alias. Register it with .addConditions() / .addSelectors(), or use a raw "&…" selector or "@media|@container|@supports (…)" key.`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Branded rejection for an `@`-prefixed block key that does not match an
|
|
80
|
+
* accepted at-rule shape (`@media …` / `@container …` / `@supports …`). The
|
|
81
|
+
* type name carries the offending key; the `hint` states the remedy.
|
|
82
|
+
*/
|
|
83
|
+
export interface UnknownAtRule<K extends string> {
|
|
84
|
+
readonly __unknownAtRule: K;
|
|
85
|
+
readonly hint: `"${K}" is not a valid at-rule block key. At-rule keys must begin with "@media ", "@container ", or "@supports " followed by a parenthesized/feature tail.`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* SHALLOW at-rule key shapes (design D9): prefix + tail only. Deep query-grammar
|
|
89
|
+
* template literals are the repo's one known TS2589 zone (string-embedded
|
|
90
|
+
* unions) and stay out — Rust validates queries for real; the type layer stops
|
|
91
|
+
* at the prefix. The trailing space after each at-rule name is load-bearing: it
|
|
92
|
+
* rejects prefix typos (`@containr …`, `@medi …`) without a closed grammar.
|
|
93
|
+
*/
|
|
94
|
+
export type RawAtRuleKey = `@media ${string}` | `@container ${string}` | `@supports ${string}`;
|
|
95
|
+
export interface ConditionAlias {
|
|
96
|
+
/** Full at-rule condition string, e.g. `@media (prefers-reduced-motion: reduce)`. */
|
|
97
|
+
value: string;
|
|
98
|
+
/** Sort index for cascade ordering within a layer. */
|
|
99
|
+
order: number;
|
|
100
|
+
/** Condition kind, inferred from the at-rule prefix of `value`. */
|
|
101
|
+
kind: ConditionKind;
|
|
102
|
+
}
|
|
103
|
+
export type ConditionAliasMap = Record<string, ConditionAlias>;
|
|
104
|
+
/**
|
|
105
|
+
* Built-in condition aliases (design D8, increment 06).
|
|
106
|
+
*
|
|
107
|
+
* The Panda-compatible media-feature set: motion, print, orientation, contrast,
|
|
108
|
+
* and OS color-scheme preferences. Every alias is a pure `@media` feature query
|
|
109
|
+
* (`kind: 'media'`). Color-mode aliases (`_dark` / `_light`) are DELIBERATELY
|
|
110
|
+
* excluded — they are selector-kind (`[data-color-mode]`) surface owned by the
|
|
111
|
+
* `system-color-scheme` change, not media features.
|
|
112
|
+
*
|
|
113
|
+
* ORDER BAND (inc-03 full-pass): built-ins occupy a reserved band BELOW the user
|
|
114
|
+
* band — one slot of 10 per alias in table row order, 300–380. The user band
|
|
115
|
+
* starts at 500 (`mergeConditions` floors allocation at 490 → first user alias
|
|
116
|
+
* is 500), so built-ins and user registrations never interleave on collision.
|
|
117
|
+
* This mirrors the selector registry's real layout (built-ins 10–440, users
|
|
118
|
+
* 500+).
|
|
119
|
+
*
|
|
120
|
+
* The static type-level mirror is `BuiltInConditionAlias` in `types/config.ts`
|
|
121
|
+
* (added to `KnownUnderscoreKey`'s VALIDATING branch, exactly like
|
|
122
|
+
* `BuiltInSelectorAlias`). Built-ins are NOT members of the augmentable
|
|
123
|
+
* `Conditions` interface: interface members would make publication permanently
|
|
124
|
+
* non-empty, killing inc-04's graceful-degradation contract. The
|
|
125
|
+
* `types.test-d.tsx` drift positives keep the two in sync.
|
|
126
|
+
*/
|
|
127
|
+
export declare const BUILT_IN_CONDITIONS: ConditionAliasMap;
|
|
128
|
+
/**
|
|
129
|
+
* Infer the condition kind from an at-rule value's prefix (design D3).
|
|
130
|
+
* Throws (fail-loud, build time) when the value does not begin with a
|
|
131
|
+
* supported at-rule name. The compile-time complement is `addConditions()`'s
|
|
132
|
+
* value constraint (`@media`/`@container`/`@supports`-prefixed template
|
|
133
|
+
* literals); this runtime throw remains the backstop for untyped callers.
|
|
134
|
+
*/
|
|
135
|
+
export declare function inferConditionKind(value: string): ConditionKind;
|
|
136
|
+
/**
|
|
137
|
+
* Merge user-provided condition aliases with a base map.
|
|
138
|
+
*
|
|
139
|
+
* - User aliases override built-ins of the same name, preserving the existing
|
|
140
|
+
* order (mirrors `mergeSelectors`).
|
|
141
|
+
* - New aliases allocate orders CONTINUING from the highest existing order
|
|
142
|
+
* (floored at 490, so the first user alias lands at 500) rather than
|
|
143
|
+
* restarting at 500 each call — chained `.addConditions()` calls must not
|
|
144
|
+
* collide on order 500.
|
|
145
|
+
* - Fails loud when a condition alias name is already reserved by the SELECTOR
|
|
146
|
+
* alias registry (`reservedSelectorNames`): the two registries share the `_`
|
|
147
|
+
* namespace at the call site and their names MUST be disjoint, else a block
|
|
148
|
+
* key would be ambiguous. The error names the offending alias and both
|
|
149
|
+
* registries.
|
|
150
|
+
*/
|
|
151
|
+
export declare function mergeConditions(base: ConditionAliasMap, custom: Record<string, string>, reservedSelectorNames?: ReadonlySet<string>): ConditionAliasMap;
|
|
152
|
+
/** Get the sorted alias keys for deterministic cascade ordering. */
|
|
153
|
+
export declare function getSortedConditionKeys(map: ConditionAliasMap): string[];
|
|
154
|
+
/**
|
|
155
|
+
* Serialize the condition map for the extraction pipeline.
|
|
156
|
+
* Emits `alias → { value, order, kind }` in registry (cascade) order so the
|
|
157
|
+
* JSON is deterministic. Distinct in SHAPE from the selector map (which
|
|
158
|
+
* flattens to `alias → selector`) — the object entry is forward-compatible
|
|
159
|
+
* with a future multi-valued `values: string[]` property (design D3).
|
|
160
|
+
*/
|
|
161
|
+
export declare function serializeConditionMap(map: ConditionAliasMap): Record<string, ConditionAlias>;
|
|
162
|
+
export {};
|
|
163
|
+
//# sourceMappingURL=conditions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditions.d.ts","sourceRoot":"","sources":["../src/conditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,gFAAgF;AAChF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC;AAY/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,UAAU;CAAG;AAE9B,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AACzC,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AAExC;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAC5B,CAAC,SAAS,MAAM,GAAG,KAAK,EACxB,CAAC,SAAS,MAAM,GAAG,KAAK;IAExB,QAAQ,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3B,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;CAC3B;AAED,uEAAuE;AACvE,MAAM,MAAM,YAAY,CAAC,GAAG,IAC1B,GAAG,SAAS,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEzD,6EAA6E;AAC7E,MAAM,MAAM,WAAW,CAAC,GAAG,IACzB,GAAG,SAAS,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,MAAM;IACrD,QAAQ,CAAC,uBAAuB,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,8KAA8K,CAAC;CACpM;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM;IAC7C,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,sJAAsJ,CAAC;CAC5K;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB,UAAU,MAAM,EAAE,GAClB,cAAc,MAAM,EAAE,GACtB,aAAa,MAAM,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,mBAAmB,EAAE,iBA0CjC,CAAC;AAUF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAS/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,qBAAqB,GAAE,WAAW,CAAC,MAAM,CAAqB,GAC7D,iBAAiB,CA0BnB;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAEvE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,iBAAiB,GACrB,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAMhC"}
|
|
@@ -57,13 +57,14 @@ function warnDroppedValue(baseClassName, propName, serializedValue) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
60
|
+
* Apply variant classes in declaration order, recording a static witness per
|
|
61
|
+
* resolved variant. When a value comes from a defaultVariant fallback (prop not
|
|
62
|
+
* passed), emit --{prop}-default instead of --{prop}-{value} so the compose
|
|
63
|
+
* override rule cannot match, allowing inheritance from the parent to win.
|
|
62
64
|
*/
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (config.variants) for (const [prop, vc] of Object.entries(config.variants)) {
|
|
65
|
+
function applyVariantClasses(classes, baseClassName, props, config) {
|
|
66
|
+
if (!config.variants) return;
|
|
67
|
+
for (const [prop, vc] of Object.entries(config.variants)) {
|
|
67
68
|
const value = props[prop] ?? vc.default;
|
|
68
69
|
if (value != null) {
|
|
69
70
|
const isDefault = !(prop in props) && vc.default != null;
|
|
@@ -71,7 +72,14 @@ function resolveClasses(baseClassName, props, config, systemPropMap, dynamicProp
|
|
|
71
72
|
recordWitness(baseClassName, prop, value, "static");
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Apply compound classes: push each compound's className when every condition
|
|
78
|
+
* matches (against the prop value or its variant default). No witness records.
|
|
79
|
+
*/
|
|
80
|
+
function applyCompoundClasses(classes, props, config) {
|
|
81
|
+
if (!config.compounds) return;
|
|
82
|
+
for (const compound of config.compounds) {
|
|
75
83
|
let match = true;
|
|
76
84
|
for (const [prop, expected] of Object.entries(compound.conditions)) {
|
|
77
85
|
const current = props[prop] ?? config.variants?.[prop]?.default;
|
|
@@ -82,14 +90,54 @@ function resolveClasses(baseClassName, props, config, systemPropMap, dynamicProp
|
|
|
82
90
|
}
|
|
83
91
|
if (match) classes.push(compound.className);
|
|
84
92
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Apply state classes and track active states for data-attribute passthrough,
|
|
96
|
+
* recording a static witness per active state.
|
|
97
|
+
*/
|
|
98
|
+
function applyStateClasses(classes, baseClassName, props, config, activeStates) {
|
|
99
|
+
if (!config.states) return;
|
|
100
|
+
for (const state of config.states) if (props[state]) {
|
|
101
|
+
classes.push(`${baseClassName}--${state}`);
|
|
102
|
+
activeStates.push(state);
|
|
103
|
+
recordWitness(baseClassName, state, "true", "static");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Expand a resolved dynamic prop into slot classes and CSS-variable style
|
|
108
|
+
* entries. Responsive objects expand per breakpoint: the `_` base breakpoint
|
|
109
|
+
* uses the bare slotClass and varName; named breakpoints suffix both
|
|
110
|
+
* (`${slotClass}-${bp}` and `${varName}-${bp}`). Scalar values push the bare
|
|
111
|
+
* slotClass and set varName directly. Mutates `classes` (push order preserved)
|
|
112
|
+
* and `dynStyle` in place; the caller records the dynamic witness beforehand.
|
|
113
|
+
*/
|
|
114
|
+
function applyDynamicProp(classes, dynStyle, propValue, dc) {
|
|
115
|
+
if (typeof propValue === "object" && propValue !== null && !Array.isArray(propValue)) for (const [bp, bpVal] of Object.entries(propValue)) {
|
|
116
|
+
if (bpVal == null) continue;
|
|
117
|
+
if (bp === "_") {
|
|
118
|
+
classes.push(dc.slotClass);
|
|
119
|
+
dynStyle[dc.varName] = resolveValue(bpVal, dc);
|
|
120
|
+
} else {
|
|
121
|
+
classes.push(`${dc.slotClass}-${bp}`);
|
|
122
|
+
dynStyle[`${dc.varName}-${bp}`] = resolveValue(bpVal, dc);
|
|
91
123
|
}
|
|
92
124
|
}
|
|
125
|
+
else {
|
|
126
|
+
classes.push(dc.slotClass);
|
|
127
|
+
dynStyle[dc.varName] = resolveValue(propValue, dc);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Resolve className parts from props, using extracted configuration.
|
|
132
|
+
* This is the shared logic between createComponent and createClassResolver.
|
|
133
|
+
*/
|
|
134
|
+
function resolveClasses(baseClassName, props, config, systemPropMap, dynamicPropConfig) {
|
|
135
|
+
const classes = [baseClassName];
|
|
136
|
+
let dynStyle;
|
|
137
|
+
applyVariantClasses(classes, baseClassName, props, config);
|
|
138
|
+
applyCompoundClasses(classes, props, config);
|
|
139
|
+
const activeStates = [];
|
|
140
|
+
applyStateClasses(classes, baseClassName, props, config, activeStates);
|
|
93
141
|
const systemPropNames = config.systemPropNames || [];
|
|
94
142
|
if (systemPropNames.length > 0) {
|
|
95
143
|
const { customPropMap, customDynamicConfig } = config;
|
|
@@ -107,24 +155,7 @@ function resolveClasses(baseClassName, props, config, systemPropMap, dynamicProp
|
|
|
107
155
|
if (dc) {
|
|
108
156
|
recordWitness(baseClassName, propName, key, "dynamic");
|
|
109
157
|
if (!dynStyle) dynStyle = {};
|
|
110
|
-
|
|
111
|
-
if (bpVal == null) continue;
|
|
112
|
-
if (bp === "_") {
|
|
113
|
-
classes.push(dc.slotClass);
|
|
114
|
-
const finalVal = resolveValue(bpVal, dc);
|
|
115
|
-
dynStyle[dc.varName] = finalVal;
|
|
116
|
-
} else {
|
|
117
|
-
classes.push(`${dc.slotClass}-${bp}`);
|
|
118
|
-
const varName = `${dc.varName}-${bp}`;
|
|
119
|
-
const finalVal = resolveValue(bpVal, dc);
|
|
120
|
-
dynStyle[varName] = finalVal;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
classes.push(dc.slotClass);
|
|
125
|
-
const finalVal = resolveValue(propValue, dc);
|
|
126
|
-
dynStyle[dc.varName] = finalVal;
|
|
127
|
-
}
|
|
158
|
+
applyDynamicProp(classes, dynStyle, propValue, dc);
|
|
128
159
|
} else {
|
|
129
160
|
warnDroppedValue(baseClassName, propName, key);
|
|
130
161
|
recordWitness(baseClassName, propName, key, "drop");
|
|
@@ -152,6 +183,74 @@ function composeRefs(...refs) {
|
|
|
152
183
|
};
|
|
153
184
|
}
|
|
154
185
|
/**
|
|
186
|
+
* Forward props to the underlying element, filtering out Animus-managed props.
|
|
187
|
+
*
|
|
188
|
+
* data-* and aria-* attributes always pass through to the DOM, even when used
|
|
189
|
+
* as variant/state keys. This enables headless UI interop: the attribute is
|
|
190
|
+
* consumed for styling AND forwarded to the element so external frameworks
|
|
191
|
+
* (Radix, Ark-UI) see it.
|
|
192
|
+
*
|
|
193
|
+
* filterProps covers all Animus props, so unknown props pass through: for DOM
|
|
194
|
+
* elements React handles any unknown-attribute warnings in dev mode, and for
|
|
195
|
+
* component elements all non-filtered props are forwarded to the component.
|
|
196
|
+
*/
|
|
197
|
+
function forwardProps(props, filterProps, domProps) {
|
|
198
|
+
for (const [key, value] of Object.entries(props)) {
|
|
199
|
+
if (key === "className") continue;
|
|
200
|
+
if (!(key.startsWith("data-") || key.startsWith("aria-")) && filterProps.has(key)) continue;
|
|
201
|
+
domProps[key] = value;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* asChild render path: don't render our own element — merge the resolved
|
|
206
|
+
* className/ref/style onto the single child element, plus the parent's own
|
|
207
|
+
* forwardable props (event handlers, role, aria-*, data-*, id, tabIndex).
|
|
208
|
+
*
|
|
209
|
+
* Conflict rule is child-wins: the parent's props are spread UNDER the child's
|
|
210
|
+
* own, so a handler or attribute declared on the child replaces the parent's
|
|
211
|
+
* rather than chaining with it.
|
|
212
|
+
*/
|
|
213
|
+
function renderAsChild(className, filterProps, props, ref, classes, dynamicStyle) {
|
|
214
|
+
const child = Children.only(props.children);
|
|
215
|
+
if (!isValidElement(child)) throw new Error(`${className}: asChild requires a single React element as children`);
|
|
216
|
+
const childRef = child.ref;
|
|
217
|
+
const mergedClassName = [classes.join(" "), child.props.className].filter(Boolean).join(" ");
|
|
218
|
+
const mergedStyle = dynamicStyle || props.style || child.props.style ? {
|
|
219
|
+
...props.style,
|
|
220
|
+
...child.props.style,
|
|
221
|
+
...dynamicStyle
|
|
222
|
+
} : void 0;
|
|
223
|
+
const parentProps = {};
|
|
224
|
+
forwardProps(props, filterProps, parentProps);
|
|
225
|
+
delete parentProps.children;
|
|
226
|
+
delete parentProps.style;
|
|
227
|
+
delete parentProps.ref;
|
|
228
|
+
return cloneElement(child, {
|
|
229
|
+
...parentProps,
|
|
230
|
+
...child.props,
|
|
231
|
+
ref: composeRefs(ref, childRef),
|
|
232
|
+
className: mergedClassName,
|
|
233
|
+
...mergedStyle ? { style: mergedStyle } : {}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Normal render path: render our own element (or the `as` override), forwarding
|
|
238
|
+
* filtered props and applying any dynamic CSS-variable style.
|
|
239
|
+
*/
|
|
240
|
+
function renderElement(element, filterProps, props, ref, classes, dynamicStyle) {
|
|
241
|
+
const target = props.as || element;
|
|
242
|
+
const domProps = {
|
|
243
|
+
ref,
|
|
244
|
+
className: classes.join(" ")
|
|
245
|
+
};
|
|
246
|
+
forwardProps(props, filterProps, domProps);
|
|
247
|
+
if (dynamicStyle) domProps.style = props.style ? {
|
|
248
|
+
...props.style,
|
|
249
|
+
...dynamicStyle
|
|
250
|
+
} : dynamicStyle;
|
|
251
|
+
return createElement(target, domProps);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
155
254
|
* Create a lightweight component that applies extracted CSS class names.
|
|
156
255
|
* Replaces Emotion's styled() for extracted components.
|
|
157
256
|
*
|
|
@@ -180,44 +279,19 @@ function createComponent(element, className, config, systemPropMap, dynamicPropC
|
|
|
180
279
|
const Component = forwardRef((props, ref) => {
|
|
181
280
|
const { classes, dynamicStyle } = resolveClasses(className, props, config, systemPropMap, dynamicPropConfig);
|
|
182
281
|
if (props.className) classes.push(props.className);
|
|
183
|
-
|
|
184
|
-
const child = Children.only(props.children);
|
|
185
|
-
if (!isValidElement(child)) throw new Error(`${className}: asChild requires a single React element as children`);
|
|
186
|
-
const childRef = child.ref;
|
|
187
|
-
const mergedClassName = [classes.join(" "), child.props.className].filter(Boolean).join(" ");
|
|
188
|
-
const mergedStyle = dynamicStyle || props.style || child.props.style ? {
|
|
189
|
-
...props.style,
|
|
190
|
-
...child.props.style,
|
|
191
|
-
...dynamicStyle
|
|
192
|
-
} : void 0;
|
|
193
|
-
return cloneElement(child, {
|
|
194
|
-
ref: composeRefs(ref, childRef),
|
|
195
|
-
className: mergedClassName,
|
|
196
|
-
...mergedStyle ? { style: mergedStyle } : {}
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
const renderElement = props.as || element;
|
|
200
|
-
const isComponentElement = typeof renderElement !== "string";
|
|
201
|
-
const domProps = {
|
|
202
|
-
ref,
|
|
203
|
-
className: classes.join(" ")
|
|
204
|
-
};
|
|
205
|
-
for (const [key, value] of Object.entries(props)) {
|
|
206
|
-
if (key === "className") continue;
|
|
207
|
-
if (!(key.startsWith("data-") || key.startsWith("aria-")) && filterProps.has(key)) continue;
|
|
208
|
-
if (!isComponentElement) {}
|
|
209
|
-
domProps[key] = value;
|
|
210
|
-
}
|
|
211
|
-
if (dynamicStyle) domProps.style = props.style ? {
|
|
212
|
-
...props.style,
|
|
213
|
-
...dynamicStyle
|
|
214
|
-
} : dynamicStyle;
|
|
215
|
-
return createElement(renderElement, domProps);
|
|
282
|
+
return props.asChild ? renderAsChild(className, filterProps, props, ref, classes, dynamicStyle) : renderElement(element, filterProps, props, ref, classes, dynamicStyle);
|
|
216
283
|
});
|
|
217
284
|
Component.displayName = className;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
285
|
+
const variantDefaults = {};
|
|
286
|
+
if (config.variants) {
|
|
287
|
+
for (const [prop, vc] of Object.entries(config.variants)) if (vc.default != null) variantDefaults[prop] = vc.default;
|
|
288
|
+
}
|
|
289
|
+
return Object.assign(Component, {
|
|
290
|
+
variantDefaults: Object.freeze(variantDefaults),
|
|
291
|
+
extend: () => {
|
|
292
|
+
throw new Error(`Cannot extend extracted component "${className}" at runtime. Extensions must be authored in source code using the builder API (e.g. import the original component and call .extend() there) so the extraction pipeline can resolve them at build time.`);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
221
295
|
}
|
|
222
296
|
//#endregion
|
|
223
297
|
//#region src/runtime/createClassResolver.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export { createComposedFamily } from './runtime/createComposedFamily';
|
|
|
8
8
|
export type { CreateKeyframesFactory, GlobalStyleBlock, GlobalStyleMap, GlobalStylesFactory, SerializedConfig, SystemInstance, } from './SystemBuilder';
|
|
9
9
|
export { createSystem, SystemBuilder } from './SystemBuilder';
|
|
10
10
|
export { createScale, numericOrStringScale, numericScale, stringScale, } from './scales/createScale';
|
|
11
|
-
export {
|
|
11
|
+
export { BUILT_IN_CONDITIONS, type ConditionAlias, type ConditionAliasMap, type ConditionKind, type Conditions, type ConditionsOf, type RawAtRuleKey, type RegistryBrand, type SelectorsOf, type UnknownAtRule, type UnknownConditionAlias, } from './conditions.js';
|
|
12
|
+
export { BUILT_IN_SELECTORS, type SelectorAlias, type SelectorAliasMap, type Selectors, } from './selectors';
|
|
12
13
|
export type { Assign, AssignValueIfUnmergable, ColorModeConfig, FindPath, KeyAsVariable, LiteralPaths, Mergable, Merge, MergeTheme, Path, PathToLiteral, PathValue, PrivateThemeKeys, SanitizeKey, } from './theme';
|
|
13
14
|
export { createTheme, ThemeBuilder } from './theme';
|
|
14
15
|
export { borderShorthand } from './transforms/border';
|
|
@@ -16,9 +17,9 @@ export { createTransform, type NamedTransform, type TransformFn, } from './trans
|
|
|
16
17
|
export { gridItem, gridItemRatio } from './transforms/grid';
|
|
17
18
|
export { percentageOrAbsolute, size } from './transforms/size';
|
|
18
19
|
export type { AnimusComponent, AnimusWrappedComponent, AnyBrandedComponent, ComposedFamily, SharedConfig, VariantPropsOf, } from './types/component';
|
|
19
|
-
export type { AbstractParser, BuiltInSelectorAlias, CompoundEntry, CSSPropMap, CSSProps, CustomPropConfig, Parser, ParserProps, Prop, PropertyValues, Scale, ScaleValue, SelectorAliasProps, SystemProps, ThemedCSSPropMap, ThemedCSSProps, ThemedScale, ThemedScaleValue, VariantConfig, } from './types/config';
|
|
20
|
+
export type { AbstractParser, BuiltInConditionAlias, BuiltInSelectorAlias, CompoundEntry, CSSPropMap, CSSProps, CustomPropConfig, Parser, ParserProps, Prop, PropertyValues, Scale, ScaleValue, SelectorAliasProps, SystemProps, ThemedCSSPropMap, ThemedCSSProps, ThemedScale, ThemedScaleValue, VariantConfig, } from './types/config';
|
|
20
21
|
export type { AbstractProps, MediaQueryMap, ResponsiveProp, ThemeProps, } from './types/props';
|
|
21
22
|
export type { ArrayScale, MapScale } from './types/scales';
|
|
22
23
|
export type { CSSObject } from './types/shared';
|
|
23
|
-
export type { AbstractTheme, BaseTheme, ColorTokenRef, CSSColorValue, EmittedScales, EmittedTokenPaths, ScaleTokenRef, SerializedTheme, Theme, ThemeManifest, TokenScales, } from './types/theme';
|
|
24
|
+
export type { AbstractTheme, BaseTheme, BrowserColorSchemeConfig, ColorModeOptions, ColorTokenRef, ContextualVarRegistration, CSSColorValue, EmittedScales, EmittedTokenPaths, ScaleTokenRef, SerializedTheme, SystemPreferenceConfig, Theme, ThemeManifest, TokenScales, } from './types/theme';
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|