@teacss/classes 0.3.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 ADDED
@@ -0,0 +1,22 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/antfu>
4
+ Copyright (c) 2026-PRESENT Billgo <hi@billgo.me>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,394 @@
1
+ # @teacss/classes
2
+
3
+ **Typed class composition and semantic merging for TeaCSS.**
4
+
5
+ ## Purpose
6
+
7
+ This package joins nested class-value inputs and removes earlier TeaCSS tokens
8
+ that are overridden by later tokens under the same condition sequence. The
9
+ algorithm is independent of CSS generation and ships with no runtime
10
+ dependencies: callers provide vocabulary-specific conflict metadata and optional
11
+ merger plugins.
12
+
13
+ It is the low-level package for custom integration and merger authors.
14
+ Applications and component libraries built on the official vocabulary use the
15
+ pre-bound `cn` and `recipe` exports from `teacss`. This package does not
16
+ generate CSS, validate whether a class value is supported, or own the Standard
17
+ and icon vocabularies.
18
+
19
+ ## Recipe composition
20
+
21
+ Most applications should use `recipe` from `teacss`. It is pre-bound to
22
+ the official standard-and-icon `cn`, so conflicts are resolved inside each
23
+ recipe output.
24
+
25
+ Use a primitive string for `styles` when a recipe styles one element. Variant
26
+ choices and compound outputs are strings, and calling the recipe returns the
27
+ merged string directly. The call also accepts `className`:
28
+
29
+ ```ts
30
+ import { recipe, type ClassProp, type VariantProps } from "teacss";
31
+
32
+ const badge = recipe({
33
+ styles: "d:inline-flex align-items:center radius:full p-x:2",
34
+ variants: {
35
+ tone: {
36
+ neutral: "bg-color:gray-100 text-color:gray-900",
37
+ accent: "bg-color:blue-500 text-color:white",
38
+ },
39
+ },
40
+ compoundVariants: [
41
+ {
42
+ tone: "accent",
43
+ className: "font-weight:700",
44
+ },
45
+ ],
46
+ });
47
+
48
+ badge({
49
+ tone: "accent",
50
+ className: "p-x:3",
51
+ }); // "d:inline-flex align-items:center radius:full bg-color:blue-500 text-color:white font-weight:700 p-x:3"
52
+
53
+ type BadgeProps = VariantProps<typeof badge> & ClassProp;
54
+
55
+ function badgeClassName({ className, ...variants }: BadgeProps) {
56
+ return badge({ ...variants, className });
57
+ }
58
+ ```
59
+
60
+ Use a non-empty object for `styles` when a recipe has multiple elements. There
61
+ is no distinguished or required `root` key: every declared key is an ordinary
62
+ style name and becomes a resolver in the result. Variant choices target those
63
+ names with maps; compounds support a targeted map or a shared broadcast:
64
+
65
+ ```ts
66
+ const button = recipe({
67
+ styles: {
68
+ container: "d:inline-flex align-items:center p:2 p:4@md",
69
+ icon: "inline-size:4x",
70
+ label: "",
71
+ },
72
+ variants: {
73
+ size: {
74
+ small: {
75
+ container: "p:2",
76
+ icon: "inline-size:3x",
77
+ },
78
+ large: {
79
+ container: "p:4",
80
+ icon: "inline-size:5x",
81
+ },
82
+ },
83
+ disabled: {
84
+ true: {
85
+ container: "opacity:50 pointer-events:none",
86
+ },
87
+ },
88
+ },
89
+ defaultVariants: {
90
+ size: "small",
91
+ disabled: false,
92
+ },
93
+ compoundVariants: [
94
+ {
95
+ size: "large",
96
+ disabled: true,
97
+ className: {
98
+ container: "font-weight:700",
99
+ icon: "inline-size:6x",
100
+ },
101
+ },
102
+ {
103
+ disabled: true,
104
+ parts: ["container", "icon"],
105
+ className: "opacity:80",
106
+ },
107
+ ],
108
+ });
109
+
110
+ const large = button({
111
+ size: "large",
112
+ });
113
+
114
+ large.container({
115
+ disabled: true,
116
+ className: "p:6",
117
+ });
118
+ large.icon();
119
+ large.label();
120
+
121
+ type ButtonProps = VariantProps<typeof button> & ClassProp;
122
+
123
+ function buttonClassName({ className, ...variants }: ButtonProps) {
124
+ const styles = button(variants);
125
+ return styles.container({ className });
126
+ }
127
+ ```
128
+
129
+ For an object-style recipe, the recipe call accepts only shared variant
130
+ selections. Each resolver accepts all recipe selections plus `ClassProp`; its
131
+ local selections and `className` apply only to that resolver invocation.
132
+ Compounds are re-evaluated against that local selection without mutating the
133
+ captured recipe result or sibling resolvers. A string-style recipe has no
134
+ resolver layer, so its recipe call accepts `className` and returns a string.
135
+
136
+ Multi-element variant choices are always style-target maps. Each compound uses
137
+ exactly one of two forms: a non-empty `className` target map, or a
138
+ primitive-string `className` paired with a non-empty `parts` array that
139
+ broadcasts the class to every listed effective style. `parts` may contain
140
+ declared or inherited style names and must be dense, duplicate-free, and free
141
+ of unknown names. Matching entries contribute to the selected styles in
142
+ compound declaration order. The two forms cannot be combined, and `parts` is
143
+ reserved as a variant name.
144
+
145
+ The one-sided `disabled` variant above is boolean-capable. `true` is
146
+ branch-backed and emits its fragment; boolean `false` is a distinct branchless
147
+ state that emits no variant fragment but remains available to defaults,
148
+ resolver-local selections, and compound matching. The undeclared string
149
+ `"false"` is not an alias for that branchless state.
150
+
151
+ Responsive and stateful behavior stays in static TeaCSS class values using
152
+ suffix conditions such as `p:4@md` and `bg-color:blue-600@hover`; recipe props
153
+ do not introduce responsive objects.
154
+
155
+ Recipes extend one parent created by the exact same definer. An extending child
156
+ may omit `styles` to inherit the parent's string or object mode, base fragments,
157
+ and existing named styles. If a child declares `styles`, it must preserve that
158
+ mode; an object child may add new names:
159
+
160
+ ```ts
161
+ const primaryButton = recipe({
162
+ extend: button,
163
+ variants: {
164
+ emphasis: {
165
+ strong: {
166
+ container: "font-weight:700",
167
+ },
168
+ },
169
+ },
170
+ });
171
+
172
+ const strongBadge = recipe({
173
+ extend: badge,
174
+ styles: "font-weight:700",
175
+ });
176
+ ```
177
+
178
+ Typed definitions require one finite, statically stable schema. Optional,
179
+ union-valued, or open index-signature key sets for object `styles`, `variants`,
180
+ or variant choices are rejected because they could promise resolvers or
181
+ selections absent from the runtime branch. A `string | object` styles value and
182
+ a union-typed `extend` parent must be narrowed before calling `recipe()`. Finite
183
+ required named interfaces are accepted without an artificial string index
184
+ signature. `__proto__` is reserved as a statically unsafe schema name because
185
+ ordinary object-literal syntax does not create a predictable own property for
186
+ it; an explicitly constructed null-prototype runtime record can still carry
187
+ that own name safely.
188
+
189
+ Every definition without `extend` requires its own `styles` field. An explicitly
190
+ declared object `styles` value must contain at least one key. The superseded
191
+ top-level definition field `parts` is not accepted as a compatibility alias;
192
+ it is distinct from supported nested `compoundVariants[].parts`.
193
+
194
+ ### Definer creation
195
+
196
+ `@teacss/classes` exports the `createDefiner` factory and no pre-bound
197
+ definer. Each integration binds its own merger once and exports the
198
+ result under the name appropriate for that integration:
199
+
200
+ ```ts
201
+ import { createDefiner, createMerger } from "@teacss/classes";
202
+
203
+ export const merge = createMerger({ conflicts, plugins });
204
+ export const recipe = createDefiner({ merge });
205
+
206
+ export const libraryButton = recipe({
207
+ styles: "p:2",
208
+ });
209
+ ```
210
+
211
+ `createDefiner` accepts the required `merge` field; there is no default merger
212
+ and no `merger` alias. Extension identity belongs to the exact definer function,
213
+ not merely to the merger. Its return type is the type-only `RecipeDefiner`
214
+ export, so an integration can re-export its definer without inlining the
215
+ complete generic recipe contract into generated declarations.
216
+
217
+ Libraries that export official recipes for downstream extension peer-depend on
218
+ and externalize `teacss`, which owns the official definer. A custom integration
219
+ peer-depends on `@teacss/classes` and exports the exact definer used to create
220
+ its parents. Consumers deduplicate that owning integration. Recreating a
221
+ definer, loading another physical or versioned runtime, or loading the parent
222
+ and definer from different provider-package instances breaks extension
223
+ identity even when declarations and merger behavior match. Deduplicating only
224
+ `@teacss/classes` does not repair a duplicated custom-definer provider.
225
+ `VariantProps` extraction is type-only and needs no runtime identity; only
226
+ `extend` has this exact-identity requirement.
227
+
228
+ ## Class merging
229
+
230
+ ```sh
231
+ bun add @teacss/classes
232
+ ```
233
+
234
+ ```ts
235
+ import { createMerger } from "@teacss/classes";
236
+
237
+ const cn = createMerger({
238
+ conflicts: {
239
+ keywords: {
240
+ flex: "display",
241
+ hidden: "display",
242
+ },
243
+ overlaps: {
244
+ p: ["padding-top", "padding-right", "padding-bottom", "padding-left"],
245
+ "p-x": ["padding-left", "padding-right"],
246
+ },
247
+ },
248
+ });
249
+
250
+ cn("p:4 flex", "p:8"); // "flex p:8"
251
+ cn("p:4", "p-x:8"); // "p:4 p-x:8"
252
+ cn("p:4", "p-x:8!"); // "p:4 p-x:8!"
253
+ cn('content:["hello world"]', 'content:["good bye"]'); // 'content:["good bye"]'
254
+ ```
255
+
256
+ Attached `[]` literal regions keep their internal whitespace in one token and
257
+ protect braces and semicolons from group expansion. Braces inside attached
258
+ `()` CSS functions are likewise not mistaken for groups. Top-level
259
+ `{p:4;m:2}@hover` group syntax still expands normally.
260
+
261
+ For the standard TeaCSS vocabulary, use the pre-bound merger instead:
262
+
263
+ ```ts
264
+ import { cn } from "@teacss/preset-standard/merge";
265
+ ```
266
+
267
+ ## Merger API
268
+
269
+ `createMerger(options?)` returns a callable `Merger` that accepts strings,
270
+ mutable or readonly nested arrays and tuples, conditional class dictionaries,
271
+ falsy values, numbers, and tagged templates. It preserves the order of
272
+ surviving tokens; it does not sort them. Finite named interfaces are valid
273
+ class dictionaries and conflict tables; runtime protocol validation still
274
+ checks every supplied conflict atom.
275
+
276
+ Tagged-template literal segments and resolved expressions concatenate exactly.
277
+ Put whitespace in the template wherever two class tokens need a boundary:
278
+
279
+ ```ts
280
+ cn`p:${0}`; // "p:0"
281
+ cn`p:4@${"hover"}`; // "p:4@hover"
282
+ cn`${"p:4"} ${"m:2"}`; // "p:4 m:2"
283
+ ```
284
+
285
+ Options:
286
+
287
+ - `conflicts`: keyword and shorthand/longhand conflict footprints.
288
+ - `overlap`: `"precise"` by default, or `"symmetric"` for last-intersection
289
+ wins between equal-importance tokens. Differing importance still requires
290
+ full winner coverage.
291
+ - `plugins`: ordered, uniquely named plugins with optional static `conflicts`,
292
+ token transforms, dynamic groups, drop-only finalizers, and pair resolvers.
293
+ - `cache`: one input LRU shared by normal and tagged-template calls, or `false`
294
+ to disable caching. `cache.max` defaults to `1500` and must be a finite
295
+ non-negative integer; `0` disables caching.
296
+
297
+ Each static conflict value is one atom or a readonly atom array. Static metadata
298
+ is composed once from top-level options and then plugins. Identical atom sets
299
+ deduplicate; a different set for the same keyword or declaration key is a
300
+ protocol error. Keyword and declaration keys are separate namespaces.
301
+ Shared CSS atoms use CSS property names; a third-party private atom must begin
302
+ with that plugin's unique name.
303
+
304
+ ```ts
305
+ import {
306
+ createMerger,
307
+ MERGE_OPAQUE,
308
+ type MergerPlugin,
309
+ } from "@teacss/classes";
310
+
311
+ const plugin: MergerPlugin = {
312
+ name: "example-icons",
313
+ conflicts: {
314
+ keywords: {},
315
+ overlaps: { icon: "example-icons:icon" },
316
+ },
317
+ group(token) {
318
+ if (token.keyword || token.prefix !== "icon") return null;
319
+ return token.value?.includes("-") ? null : MERGE_OPAQUE;
320
+ },
321
+ };
322
+
323
+ const cn = createMerger({ plugins: [plugin] });
324
+ ```
325
+
326
+ `MERGE_OPAQUE` is terminal classification. Different opaque raw strings survive;
327
+ an exact duplicate keeps only its last occurrence and never enters finalizers or
328
+ pair resolution. Import and return the named marker rather than raw `false`.
329
+
330
+ Token transforms receive a readonly token list and a run-local `viewToken()`
331
+ function. Their result must be an array of individual non-empty class tokens;
332
+ whitespace is valid only inside an attached `[]` literal region. Transform
333
+ output is not split or group-expanded again. Dynamic
334
+ `group()` hooks return atoms, `MERGE_OPAQUE`, or `null`. `finalize()` receives
335
+ current non-opaque occurrences with stable ids and may only return ids to drop;
336
+ `null` and `[]` both drop nothing. Every returned id must be an integer, unique,
337
+ and present in that exact input. Core validates the whole result before applying
338
+ any drop. `resolve()` may return `"earlier"`, `"later"`, `"none"`, or `null`.
339
+ Its context reports real full coverage in both directions through `covers`
340
+ (later over earlier) and `earlierCoversLater`, independently of symmetric mode.
341
+
342
+ A resolver is global by default. A plugin may add `resolveFamily(token)` to
343
+ scope it: the family hook runs once per non-opaque occurrence, and `resolve()`
344
+ is considered only when both tokens return the same non-empty family. A
345
+ `resolveFamily` hook requires a `resolve` hook. Use this metadata whenever a
346
+ resolver owns a finite semantic family. A run made entirely of one unowned
347
+ static prefix, such as standard `p:*`, can then use the linear winner path;
348
+ dynamic groups and resolver-owned families still use pair resolution.
349
+
350
+ The package exports the `MergerProtocolError` class and the
351
+ `MergerProtocolErrorCode` type. Errors expose `code` plus optional `plugin` and
352
+ `hook` fields. Stable codes distinguish malformed options, cache bounds,
353
+ conflict metadata, plugin names and hooks, static conflicts, and invalid
354
+ transform, group, finalizer, resolver-family, or resolver results. Hook
355
+ exceptions are propagated unchanged. A failed run writes no input-LRU entry.
356
+
357
+ Only own option, cache, conflict-shape, plugin-name, and plugin-hook fields are
358
+ used; inherited prototype fields cannot alter a merger. Plugin arrays, own hook
359
+ references, static records, and atom arrays are snapshotted when
360
+ `createMerger()` runs. Array-shaped protocol results are validated from a fixed
361
+ length and own numeric indexes; custom iterators and inherited sparse entries
362
+ are not trusted. Every accepted array length must be an integer from `0` through
363
+ `4294967294`; malformed plugin, metadata, and hook arrays retain their
364
+ surface-specific protocol codes, while malformed class-value and tagged-template
365
+ arrays report `INVALID_ARRAY_LENGTH`. Hooks are called with
366
+ `this === undefined` and should be pure. If a hook closes over mutable state,
367
+ use `cache: false`.
368
+
369
+ ## Conflict Semantics
370
+
371
+ Only tokens with the same ordered condition sequence and intersecting atom
372
+ footprints are candidates. When importance differs, the important token removes
373
+ the non-important token only when its footprint fully covers the token being
374
+ removed; partial overlaps survive so unrelated declarations are not lost. With
375
+ equal importance, precise mode drops an earlier token only when the later
376
+ footprint covers it; symmetric mode treats any intersection as coverage.
377
+ Surviving tokens keep their original order. A custom `resolve()` hook remains an
378
+ explicit override of the default verdict.
379
+
380
+ Merge never validates TeaCSS or CSS values. A structurally parsed declaration
381
+ uses its declared or fallback footprint even when the value is unsupported or
382
+ empty:
383
+
384
+ ```ts
385
+ cn("p:4", "p:invalid"); // "p:invalid"
386
+ cn("p:4", "p:"); // "p:"
387
+ ```
388
+
389
+ Run `bun run bench:merger` from the workspace root to measure the uncached
390
+ standard static-prefix `p:*` path at 500, 1,000, 2,000, and 4,000 tokens.
391
+
392
+ ## Status
393
+
394
+ Pre-1.0. Public recipe and merge APIs may change before the stable release.
@@ -0,0 +1,255 @@
1
+ //#region src/merge.d.ts
2
+ type ClassDict = Record<string, any>;
3
+ type ClassValue = string | number | bigint | null | undefined | boolean | readonly ClassValue[] | ClassDict;
4
+ type ConflictAtoms = string | readonly string[];
5
+ type ConflictTable = Readonly<Record<string, ConflictAtoms>>;
6
+ type IsAny$1<Value> = 0 extends 1 & Value ? true : false;
7
+ type NonRecordObject = readonly unknown[] | ((...args: any[]) => any) | (abstract new (...args: any[]) => any);
8
+ type ValidateConflictTable<Table extends object> = Table extends NonRecordObject ? never : { readonly [Key in keyof Table]: IsAny$1<Table[Key]> extends true ? Table[Key] : Table[Key] extends ConflictAtoms ? Table[Key] : never; };
9
+ interface ConflictMeta<Keywords extends object = ConflictTable, Overlaps extends object = ConflictTable> {
10
+ readonly keywords: ValidateConflictTable<Keywords>;
11
+ readonly overlaps: ValidateConflictTable<Overlaps>;
12
+ }
13
+ interface MergerTokenView {
14
+ readonly raw: string;
15
+ readonly prefix: string;
16
+ readonly body: string;
17
+ readonly value?: string;
18
+ readonly keyword: boolean;
19
+ readonly conditions: readonly string[];
20
+ readonly important: boolean;
21
+ }
22
+ interface MergerTokenOccurrence {
23
+ /** Zero-based ordinal in the final transformed raw list and stable run-local id. */
24
+ readonly id: number;
25
+ readonly view: MergerTokenView;
26
+ readonly atoms: readonly string[];
27
+ }
28
+ type ResolveVerdict = "earlier" | "later" | "none";
29
+ /** Dedicated, allocation-free classification result. */
30
+ declare const MERGE_OPAQUE: false;
31
+ interface MergerPlugin<Keywords extends object = ConflictTable, Overlaps extends object = ConflictTable> {
32
+ readonly name: string;
33
+ readonly conflicts?: ConflictMeta<Keywords, Overlaps>;
34
+ readonly tokens?: (this: void, tokens: readonly string[], context: {
35
+ readonly viewToken: (raw: string) => MergerTokenView;
36
+ }) => readonly string[];
37
+ readonly group?: (this: void, token: MergerTokenView) => ConflictAtoms | typeof MERGE_OPAQUE | null;
38
+ readonly finalize?: (this: void, tokens: readonly MergerTokenOccurrence[]) => readonly number[] | null;
39
+ /**
40
+ * Optionally scope this plugin's resolver. The resolver is considered only
41
+ * when both tokens return the same non-empty family.
42
+ */
43
+ readonly resolveFamily?: (this: void, token: MergerTokenView) => string | null;
44
+ readonly resolve?: (this: void, earlier: MergerTokenView, later: MergerTokenView, context: {
45
+ /** Whether the later footprint fully covers the earlier footprint. */
46
+ readonly covers: boolean;
47
+ /** Whether the earlier footprint fully covers the later footprint. */
48
+ readonly earlierCoversLater: boolean;
49
+ readonly defaultDrop: ResolveVerdict;
50
+ }) => ResolveVerdict | null;
51
+ }
52
+ type OverlapMode = "precise" | "symmetric";
53
+ interface MergerOptions<Keywords extends object = ConflictTable, Overlaps extends object = ConflictTable> {
54
+ /** Keyword + overlap tables. Absent means generic same-prefix merging only. */
55
+ readonly conflicts?: ConflictMeta<Keywords, Overlaps>;
56
+ /** Equal-importance overlap rule. Default `"precise"` (asymmetric containment). */
57
+ readonly overlap?: OverlapMode;
58
+ readonly plugins?: readonly MergerPlugin[];
59
+ /** Shared input-LRU bound. `max` is a finite non-negative integer; default 1500. */
60
+ readonly cache?: {
61
+ readonly max?: number;
62
+ } | false;
63
+ }
64
+ type ConflictMetaCarrier = {
65
+ readonly keywords: Readonly<Record<string, any>>;
66
+ readonly overlaps: Readonly<Record<string, any>>;
67
+ };
68
+ type MergerPluginCarrier = {
69
+ readonly name: string;
70
+ readonly conflicts?: ConflictMetaCarrier;
71
+ readonly tokens?: MergerPlugin["tokens"];
72
+ readonly group?: MergerPlugin["group"];
73
+ readonly finalize?: MergerPlugin["finalize"];
74
+ readonly resolveFamily?: MergerPlugin["resolveFamily"];
75
+ readonly resolve?: MergerPlugin["resolve"];
76
+ };
77
+ type MergerOptionsCarrier = {
78
+ readonly conflicts?: ConflictMetaCarrier;
79
+ readonly overlap?: OverlapMode;
80
+ readonly plugins?: readonly MergerPluginCarrier[];
81
+ readonly cache?: {
82
+ readonly max?: number;
83
+ } | false;
84
+ };
85
+ type InvalidConflictTable<Table> = IsAny$1<Table> extends true ? never : Table extends NonRecordObject ? "invalid conflict table" : Table extends object ? { readonly [Key in Extract<keyof Table, string | number>]-?: IsAny$1<Table[Key]> extends true ? never : Table[Key] extends ConflictAtoms ? never : Key; }[Extract<keyof Table, string | number>] : "invalid conflict table";
86
+ type InvalidConflictMeta<Meta> = IsAny$1<Meta> extends true ? never : Meta extends {
87
+ readonly keywords: infer Keywords;
88
+ readonly overlaps: infer Overlaps;
89
+ } ? Exclude<Extract<keyof Meta, string | number>, "keywords" | "overlaps"> | InvalidConflictTable<Keywords> | InvalidConflictTable<Overlaps> : "invalid conflict metadata";
90
+ type InvalidPlugin<Plugin> = Plugin extends unknown ? IsAny$1<Plugin> extends true ? never : Plugin extends MergerPluginCarrier ? Exclude<Extract<keyof Plugin, string | number>, Extract<keyof MergerPluginCarrier, string | number>> | ("conflicts" extends keyof Plugin ? InvalidConflictMeta<Exclude<Plugin["conflicts"], undefined>> : never) : "invalid plugin" : never;
91
+ type InvalidPlugins<Plugins> = Plugins extends readonly (infer Plugin)[] ? InvalidPlugin<Plugin> : "invalid plugins";
92
+ type InvalidMergerOptions<Options> = IsAny$1<Options> extends true ? never : Options extends MergerOptionsCarrier ? Exclude<Extract<keyof Options, string | number>, Extract<keyof MergerOptionsCarrier, string | number>> | ("conflicts" extends keyof Options ? InvalidConflictMeta<Exclude<Options["conflicts"], undefined>> : never) | ("plugins" extends keyof Options ? InvalidPlugins<Exclude<Options["plugins"], undefined>> : never) : "invalid merger options";
93
+ interface Merger {
94
+ (strings: TemplateStringsArray, ...expressions: ClassValue[]): string;
95
+ (...inputs: ClassValue[]): string;
96
+ }
97
+ type MergerProtocolErrorCode = "INVALID_ARRAY_LENGTH" | "INVALID_OPTIONS" | "INVALID_CACHE_OPTIONS" | "INVALID_CONFLICT_META" | "INVALID_PLUGIN_NAME" | "DUPLICATE_PLUGIN_NAME" | "INVALID_PLUGIN_HOOK" | "INVALID_STATIC_CONFLICT" | "STATIC_CONFLICT_COLLISION" | "INVALID_TOKEN_TRANSFORM_RESULT" | "INVALID_GROUP_RESULT" | "INVALID_FINALIZER_RESULT" | "INVALID_RESOLVE_FAMILY_RESULT" | "INVALID_RESOLVE_RESULT";
98
+ declare class MergerProtocolError extends TypeError {
99
+ readonly name: "MergerProtocolError";
100
+ readonly code: MergerProtocolErrorCode;
101
+ readonly plugin?: string;
102
+ readonly hook?: "tokens" | "group" | "finalize" | "resolveFamily" | "resolve";
103
+ constructor(code: MergerProtocolErrorCode, detail: string, plugin?: string, hook?: "tokens" | "group" | "finalize" | "resolveFamily" | "resolve");
104
+ }
105
+ /** Build a merger bound to static footprints, overlap mode, plugins, and cache. */
106
+ declare function createMerger<const Options extends MergerOptionsCarrier = {}>(options?: MergerOptionsCarrier & Options & (InvalidMergerOptions<Options> extends never ? unknown : never)): Merger;
107
+ declare function createMerger(options?: MergerOptions): Merger;
108
+ //#endregion
109
+ //#region src/recipe.d.ts
110
+ type ClassProp = {
111
+ className?: ClassValue;
112
+ };
113
+ type RecipeMerger = (this: void, ...inputs: ClassValue[]) => string;
114
+ type RecipeDefinerOptions = {
115
+ readonly apply?: never;
116
+ readonly bind?: never;
117
+ readonly call?: never;
118
+ readonly length?: never;
119
+ readonly merge: RecipeMerger;
120
+ readonly prototype?: never;
121
+ };
122
+ type ReservedPartName = "class" | "className" | "then" | "toJSON" | "toString" | "valueOf";
123
+ type ReservedVariantName = "class" | "className" | "parts";
124
+ type StaticallyUnsafeSchemaName = "__proto__";
125
+ type CanonicalKey<Key> = Key extends string ? Key : Key extends number ? `${Key}` : never;
126
+ type CanonicalKeys<Value> = CanonicalKey<Extract<keyof Value, string | number>>;
127
+ type SchemaWhitespace = "\t" | "\v" | "\f" | " " | " " | " " | " " | " " | " " | " " | " " | " " | " " | " " | " " | " " | " " | "
" | "
" | " " | " " | " " | "" | "\n" | "\r";
128
+ type StripLeadingWhitespace<Value extends string> = Value extends `${SchemaWhitespace}${infer Rest}` ? StripLeadingWhitespace<Rest> : Value;
129
+ type WhitespaceOnlyName<Name extends string> = Name extends unknown ? (StripLeadingWhitespace<Name> extends "" ? Name : never) : never;
130
+ type NumericChoiceInput<Key extends string> = Key extends `${infer Numeric extends number}` ? (number extends Numeric ? never : `${Numeric}` extends Key ? Numeric : never) : never;
131
+ type ChoiceInput<Choices extends string> = Choices | NumericChoiceInput<Choices> | (Extract<Choices, "true" | "false"> extends never ? never : boolean);
132
+ type VariantSelection<Choices extends string> = ChoiceInput<Choices> | null;
133
+ type VariantSchema = Readonly<Record<string, string>>;
134
+ type RecordInput = Readonly<Record<string, any>>;
135
+ type NonRecordInput = readonly unknown[] | ((...args: any[]) => any) | (abstract new (...args: any[]) => any);
136
+ type VariantSelections<Variants extends VariantSchema> = keyof Variants extends never ? Readonly<Record<symbol, unknown>> : { readonly [Name in keyof Variants]?: VariantSelection<Extract<Variants[Name], string>> | undefined; };
137
+ type DefinitionVariantSelections<Variants extends VariantSchema> = VariantSelections<Variants> & Readonly<Record<symbol, unknown>>;
138
+ type RecipeCarrier = {
139
+ readonly [Symbol.unscopables]: never;
140
+ };
141
+ type IsAny<Value> = 0 extends 1 & Value ? true : false;
142
+ type IsUnion<Value, Whole = Value> = IsAny<Value> extends true ? false : Value extends Whole ? ([Whole] extends [Value] ? false : true) : never;
143
+ type InvalidRecordShape<Value> = Value extends unknown ? (Value extends NonRecordInput ? true : false) : never;
144
+ type OptionalSchemaKeys<Value> = Value extends unknown ? { [Key in Extract<keyof Value, string | number>]-?: {} extends Pick<Value, Key> ? Key : never; }[Extract<keyof Value, string | number>] : never;
145
+ type OpenSchemaKeys<Value> = string extends keyof Value ? string : number extends keyof Value ? number : never;
146
+ type ValidateStableSchema<Value> = IsAny<Value> extends true ? unknown : true extends IsUnion<Value> ? never : true extends InvalidRecordShape<Value> ? never : OpenSchemaKeys<Value> extends never ? (OptionalSchemaKeys<Value> extends never ? unknown : never) : never;
147
+ type ValidateNonUnion<Value> = IsAny<Value> extends true ? unknown : true extends IsUnion<Value> ? never : unknown;
148
+ type ValidateRecordShape<Value> = IsAny<Value> extends true ? unknown : true extends InvalidRecordShape<Value> ? never : unknown;
149
+ type ValidateKnownKeys<Value, Keys extends PropertyKey> = IsAny<Value> extends true ? unknown : Exclude<Extract<keyof Value, string | number>, Keys> extends never ? unknown : never;
150
+ type ValidatePropsInput<Input, Props> = IsAny<Input> extends true ? unknown : true extends InvalidRecordShape<Exclude<Input, undefined>> ? never : Exclude<CanonicalKeys<Exclude<Input, undefined>>, CanonicalKeys<Props>> extends never ? unknown : never;
151
+ type PartProps<Variants extends VariantSchema> = keyof Variants extends never ? ClassProp : VariantSelections<Variants> & ClassProp;
152
+ type SingleRecipeProps<Variants extends VariantSchema> = VariantSelections<Variants> & ClassProp;
153
+ type RecipeResult<Parts extends string, Variants extends VariantSchema> = { readonly [Part in Parts]: <const Input>(props?: Input & PartProps<Variants> & NoInfer<ValidatePropsInput<Input, PartProps<Variants>>>) => string; };
154
+ type TeaRecipeResult<Parts extends string, Variants extends VariantSchema> = RecipeResult<Parts, Variants>;
155
+ type TeaSingleRecipe<Variants extends VariantSchema> = (<const Input>(props?: Input & SingleRecipeProps<Variants> & NoInfer<ValidatePropsInput<Input, SingleRecipeProps<Variants>>>) => string) & RecipeCarrier;
156
+ type TeaMultipartRecipe<Parts extends string, Variants extends VariantSchema> = (<const Input>(props?: Input & VariantSelections<Variants> & NoInfer<ValidatePropsInput<Input, VariantSelections<Variants>>>) => TeaRecipeResult<Parts, Variants>) & RecipeCarrier;
157
+ type BrandedRecipe = Function & RecipeCarrier;
158
+ type SingleBrandedRecipe = BrandedRecipe & ((props?: any) => string);
159
+ type MultipartBrandedRecipe = BrandedRecipe & ((props?: any) => Readonly<Record<string, (props?: any) => string>>);
160
+ type SchemaFromSelections<Selections> = { readonly [Name in Exclude<Extract<keyof NonNullable<Selections>, string>, keyof ClassProp>]: Extract<NonNullable<Selections>[Name], string>; };
161
+ type ParentSchema<Parent> = [Parent] extends [RecipeCarrier & ((props?: infer Selections) => infer Result)] ? {
162
+ readonly styles: Result extends string ? never : Extract<keyof Result, string>;
163
+ readonly variants: SchemaFromSelections<Selections>;
164
+ } : {
165
+ readonly styles: never;
166
+ readonly variants: {};
167
+ };
168
+ type ParentStyles<Parent> = Extract<ParentSchema<Parent>["styles"], string>;
169
+ type ParentVariants<Parent> = ParentSchema<Parent>["variants"] extends (infer Variants extends VariantSchema) ? Variants : {};
170
+ type StylesInput = RecordInput;
171
+ type PartNames<Styles> = CanonicalKeys<Styles>;
172
+ type EffectiveParts<Parent, Styles> = ParentStyles<Parent> | PartNames<Styles>;
173
+ type PartTargetMap<Parts extends string> = Readonly<Partial<Record<Parts, ClassValue>>>;
174
+ type VariantsInput = RecordInput;
175
+ type OwnVariantSchema<Variants> = [Variants] extends [VariantsInput] ? { readonly [Name in keyof Variants as CanonicalKey<Name>]: CanonicalKeys<Variants[Name]>; } : {};
176
+ type VariantChoicesAt<Schema, Name extends PropertyKey> = Extract<Schema extends Readonly<Record<Name, infer Choices>> ? Choices : never, string>;
177
+ type MergeVariantSchemas<Parent, Child> = { readonly [Name in Extract<keyof Parent | keyof Child, string>]: VariantChoicesAt<Parent, Name> | VariantChoicesAt<Child, Name>; };
178
+ type EffectiveVariants<Parent, Variants> = MergeVariantSchemas<ParentVariants<Parent>, OwnVariantSchema<Variants>>;
179
+ type CompoundConditions<Variants extends VariantSchema> = { readonly [Name in keyof Variants]?: VariantSelection<Extract<Variants[Name], string>> | readonly [VariantSelection<Extract<Variants[Name], string>>, ...VariantSelection<Extract<Variants[Name], string>>[]]; };
180
+ type SingleCompoundDefinition<Variants extends VariantSchema> = {
181
+ readonly className: string;
182
+ } & CompoundConditions<Variants>;
183
+ type MultipartCompoundDefinition<Parts extends string, Variants extends VariantSchema> = ({
184
+ readonly className: PartTargetMap<NoInfer<Parts>>;
185
+ readonly parts?: never;
186
+ } | {
187
+ readonly className: string;
188
+ readonly parts: readonly [NoInfer<Parts>, ...NoInfer<Parts>[]];
189
+ }) & CompoundConditions<Variants>;
190
+ type InvalidPartNames<Styles> = Extract<PartNames<Styles>, ReservedPartName | StaticallyUnsafeSchemaName> | WhitespaceOnlyName<PartNames<Styles>>;
191
+ type InvalidVariantNames<Variants> = Extract<CanonicalKeys<NonNullable<Variants>>, ReservedVariantName | StaticallyUnsafeSchemaName> | WhitespaceOnlyName<CanonicalKeys<NonNullable<Variants>>>;
192
+ type InvalidChoiceNames<Choices> = Extract<CanonicalKeys<Choices>, StaticallyUnsafeSchemaName>;
193
+ type AllowedPartNames<Styles> = InvalidPartNames<Styles> extends never ? unknown : never;
194
+ type AllowedVariantNames<Variants> = InvalidVariantNames<Variants> extends never ? unknown : never;
195
+ type ValidateStyles<Styles> = PartNames<Styles> extends never ? never : Styles extends Readonly<Record<Extract<keyof Styles, string | number>, ClassValue>> ? unknown : never;
196
+ type PartTargetNames<Targets> = Targets extends unknown ? CanonicalKeys<Targets> : never;
197
+ type ValidatePartTargetValues<Targets> = Targets extends RecordInput ? { readonly [Name in keyof Targets]: Name extends symbol ? Targets[Name] : Targets[Name] extends ClassValue ? Targets[Name] : never; } : never;
198
+ type InvalidPartTargetValueNames<Targets> = Targets extends RecordInput ? { readonly [Name in Extract<keyof Targets, string | number>]-?: IsAny<Targets[Name]> extends true ? never : Targets[Name] extends ClassValue ? never : Name; }[Extract<keyof Targets, string | number>] : never;
199
+ type ValidatePartTargets<Targets, Parts extends string> = IsAny<Targets> extends true ? unknown : true extends InvalidRecordShape<Targets> ? never : [Targets] extends [RecordInput] ? (Exclude<PartTargetNames<Targets>, Parts> extends never ? (InvalidPartTargetValueNames<Targets> extends never ? ValidatePartTargetValues<Targets> : never) : never) : never;
200
+ type ValidateSingleChoices<Choices> = ValidateStableSchema<Choices> extends never ? never : InvalidChoiceNames<Choices> extends never ? CanonicalKeys<Choices> extends never ? never : Choices extends RecordInput ? { readonly [Name in keyof Choices]: Name extends symbol ? Choices[Name] : IsAny<Choices[Name]> extends true ? unknown : [Choices[Name]] extends [string] ? Choices[Name] : never; } : never : never;
201
+ type ValidateMultipartChoices<Choices, Parts extends string> = ValidateStableSchema<Choices> extends never ? never : InvalidChoiceNames<Choices> extends never ? CanonicalKeys<Choices> extends never ? never : Choices extends RecordInput ? { readonly [Name in keyof Choices]: ValidatePartTargets<Choices[Name], Parts>; } : never : never;
202
+ type ValidateSingleVariants<Variants> = [Variants] extends [VariantsInput] ? { readonly [Name in keyof Variants]: ValidateSingleChoices<Variants[Name]>; } : unknown;
203
+ type ValidateMultipartVariants<Variants, Parts extends string> = [Variants] extends [VariantsInput] ? { readonly [Name in keyof Variants]: ValidateMultipartChoices<Variants[Name], Parts>; } : unknown;
204
+ type ValidateCompoundCondition<Condition> = undefined extends Condition ? never : Condition extends readonly [] ? never : Condition;
205
+ type ValidateSingleCompoundOutput<Output> = IsAny<Output> extends true ? unknown : [Output] extends [string] ? Output : never;
206
+ type ValidateMultipartCompoundOutput<Output, Parts extends string> = PartTargetNames<Output> extends never ? never : ValidatePartTargets<Output, Parts>;
207
+ type ValidateCompoundParts<Targets, Parts extends string> = IsAny<Targets> extends true ? unknown : Targets extends readonly [unknown, ...unknown[]] ? (Exclude<Targets[number], Parts> extends never ? Targets : never) : never;
208
+ type ValidateSingleCompoundEntry<Entry, Variants extends VariantSchema> = true extends InvalidRecordShape<Entry> ? never : Entry extends RecordInput ? { readonly [Name in keyof Entry]: Name extends symbol ? Entry[Name] : Name extends "className" ? ValidateSingleCompoundOutput<Entry[Name]> : Name extends string | number ? (CanonicalKey<Name> extends keyof Variants ? ValidateCompoundCondition<Entry[Name]> : never) : never; } : never;
209
+ type ValidateMultipartCompoundEntry<Entry, Parts extends string, Variants extends VariantSchema> = true extends InvalidRecordShape<Entry> ? never : Entry extends RecordInput ? "parts" extends OptionalSchemaKeys<Entry> ? never : { readonly [Name in keyof Entry]: Name extends symbol ? Entry[Name] : Name extends "className" ? "parts" extends keyof Entry ? ValidateSingleCompoundOutput<Entry[Name]> : ValidateMultipartCompoundOutput<Entry[Name], Parts> : Name extends "parts" ? ValidateCompoundParts<Entry[Name], Parts> : Name extends string | number ? CanonicalKey<Name> extends keyof Variants ? ValidateCompoundCondition<Entry[Name]> : never : never; } : never;
210
+ type ValidateSingleCompounds<Compounds, Variants extends VariantSchema> = Compounds extends readonly unknown[] ? { readonly [Index in keyof Compounds]: ValidateSingleCompoundEntry<Compounds[Index], Variants>; } : unknown;
211
+ type ValidateMultipartCompounds<Compounds, Parts extends string, Variants extends VariantSchema> = Compounds extends readonly unknown[] ? { readonly [Index in keyof Compounds]: ValidateMultipartCompoundEntry<Compounds[Index], Parts, Variants>; } : unknown;
212
+ type SingleRecipeDefinition<Style extends string, Parent extends SingleBrandedRecipe | undefined, Variants extends VariantsInput | undefined, Compounds extends readonly SingleCompoundDefinition<EffectiveVariants<Parent, Variants>>[] | undefined> = {
213
+ readonly styles: Style;
214
+ readonly variants?: (Variants & ValidateStableSchema<Exclude<Variants, undefined>> & AllowedVariantNames<Variants> & ValidateSingleVariants<Variants>) | undefined;
215
+ readonly defaultVariants?: DefinitionVariantSelections<NoInfer<EffectiveVariants<Parent, Variants>>> | undefined;
216
+ readonly compoundVariants?: (Compounds & ValidateSingleCompounds<Compounds, EffectiveVariants<Parent, Variants>>) | undefined;
217
+ readonly extend?: (Parent & ValidateNonUnion<Parent>) | undefined;
218
+ };
219
+ type MultipartRecipeDefinition<Styles extends StylesInput, Parent extends MultipartBrandedRecipe | undefined, Variants extends VariantsInput | undefined, Compounds extends readonly MultipartCompoundDefinition<EffectiveParts<Parent, Styles>, EffectiveVariants<Parent, Variants>>[] | undefined> = {
220
+ readonly styles: Styles & ValidateStyles<Styles> & ValidateStableSchema<Styles> & AllowedPartNames<Styles>;
221
+ readonly variants?: (Variants & ValidateStableSchema<Exclude<Variants, undefined>> & AllowedVariantNames<Variants> & ValidateMultipartVariants<Variants, EffectiveParts<Parent, Styles>>) | undefined;
222
+ readonly defaultVariants?: DefinitionVariantSelections<NoInfer<EffectiveVariants<Parent, Variants>>> | undefined;
223
+ readonly compoundVariants?: (Compounds & ValidateMultipartCompounds<Compounds, EffectiveParts<Parent, Styles>, EffectiveVariants<Parent, Variants>>) | undefined;
224
+ readonly extend?: (Parent & ValidateNonUnion<Parent>) | undefined;
225
+ };
226
+ type RecipeInference<Styles, Parent, Variants, Compounds> = {
227
+ readonly styles: Styles;
228
+ readonly variants?: Variants | undefined;
229
+ readonly compoundVariants?: Compounds | undefined;
230
+ readonly extend?: Parent;
231
+ };
232
+ type ExtendedRecipeInference<Styles, Parent, Variants, Compounds> = Omit<RecipeInference<Styles, Parent, Variants, Compounds>, "extend"> & {
233
+ readonly extend: Parent;
234
+ };
235
+ type InheritedRecipeInference<Parent, Variants, Compounds> = Omit<ExtendedRecipeInference<never, Parent, Variants, Compounds>, "styles">;
236
+ type InheritedSingleRecipeDefinition<Parent extends SingleBrandedRecipe, Variants extends VariantsInput | undefined, Compounds extends readonly SingleCompoundDefinition<EffectiveVariants<Parent, Variants>>[] | undefined> = Omit<SingleRecipeDefinition<string, Parent, Variants, Compounds>, "styles">;
237
+ type InheritedMultipartRecipeDefinition<Parent extends MultipartBrandedRecipe, Variants extends VariantsInput | undefined, Compounds extends readonly MultipartCompoundDefinition<ParentStyles<Parent>, EffectiveVariants<Parent, Variants>>[] | undefined> = Omit<MultipartRecipeDefinition<{}, Parent, Variants, Compounds>, "styles">;
238
+ type RecipeDefinitionField = "compoundVariants" | "defaultVariants" | "extend" | "styles" | "variants";
239
+ type ValidateDefinitionInput<Definition> = ValidateRecordShape<Definition> & ValidateKnownKeys<Definition, RecipeDefinitionField>;
240
+ type ValidateInheritedDefinitionInput<Definition> = ValidateRecordShape<Definition> & ValidateKnownKeys<Definition, Exclude<RecipeDefinitionField, "styles">>;
241
+ type RecipeDefiner = {
242
+ <const Style extends string, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly SingleCompoundDefinition<EffectiveVariants<undefined, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: RecipeInference<Style, undefined, Variants, Compounds> & Definition & NoInfer<SingleRecipeDefinition<Style, undefined, Variants, Compounds>> & NoInfer<ValidateDefinitionInput<Definition>>): TeaSingleRecipe<EffectiveVariants<undefined, Variants>>;
243
+ <const Parent extends SingleBrandedRecipe, const Style extends string, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly SingleCompoundDefinition<EffectiveVariants<Parent, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: ExtendedRecipeInference<Style, Parent, Variants, Compounds> & Definition & NoInfer<SingleRecipeDefinition<Style, Parent, Variants, Compounds>> & NoInfer<ValidateDefinitionInput<Definition>>): TeaSingleRecipe<EffectiveVariants<Parent, Variants>>;
244
+ <const Parent extends SingleBrandedRecipe, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly SingleCompoundDefinition<EffectiveVariants<Parent, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: InheritedRecipeInference<Parent, Variants, Compounds> & Definition & NoInfer<InheritedSingleRecipeDefinition<Parent, Variants, Compounds>> & NoInfer<ValidateInheritedDefinitionInput<Definition>>): TeaSingleRecipe<EffectiveVariants<Parent, Variants>>;
245
+ <const Styles extends StylesInput, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly MultipartCompoundDefinition<EffectiveParts<undefined, Styles>, EffectiveVariants<undefined, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: RecipeInference<Styles, undefined, Variants, Compounds> & Definition & NoInfer<MultipartRecipeDefinition<Styles, undefined, Variants, Compounds>> & NoInfer<ValidateDefinitionInput<Definition>>): TeaMultipartRecipe<EffectiveParts<undefined, Styles>, EffectiveVariants<undefined, Variants>>;
246
+ <const Parent extends MultipartBrandedRecipe, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly MultipartCompoundDefinition<ParentStyles<Parent>, EffectiveVariants<Parent, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: InheritedRecipeInference<Parent, Variants, Compounds> & Definition & NoInfer<InheritedMultipartRecipeDefinition<Parent, Variants, Compounds>> & NoInfer<ValidateInheritedDefinitionInput<Definition>>): TeaMultipartRecipe<ParentStyles<Parent>, EffectiveVariants<Parent, Variants>>;
247
+ <const Parent extends MultipartBrandedRecipe, const Styles extends StylesInput, const Variants extends VariantsInput | undefined = undefined, const Compounds extends readonly MultipartCompoundDefinition<EffectiveParts<Parent, Styles>, EffectiveVariants<Parent, Variants>>[] | undefined = undefined, const Definition = unknown>(definition: ExtendedRecipeInference<Styles, Parent, Variants, Compounds> & Definition & NoInfer<MultipartRecipeDefinition<Styles, Parent, Variants, Compounds>> & NoInfer<ValidateDefinitionInput<Definition>>): TeaMultipartRecipe<EffectiveParts<Parent, Styles>, EffectiveVariants<Parent, Variants>>;
248
+ };
249
+ type VariantProps<Recipe> = Recipe extends RecipeCarrier & ((props?: infer Props) => unknown) ? VariantSelections<SchemaFromSelections<Props>> : never;
250
+ declare function createDefiner<const Options = unknown>(options: {
251
+ readonly merge: RecipeMerger;
252
+ } & Options & NoInfer<ValidateRecordShape<Options> & ValidateKnownKeys<Options, "merge">>): RecipeDefiner;
253
+ declare function createDefiner(options: RecipeDefinerOptions): RecipeDefiner;
254
+ //#endregion
255
+ export { type ClassDict, type ClassProp, type ClassValue, type ConflictAtoms, type ConflictMeta, MERGE_OPAQUE, type Merger, type MergerOptions, type MergerPlugin, MergerProtocolError, type MergerProtocolErrorCode, type MergerTokenOccurrence, type MergerTokenView, type OverlapMode, type RecipeDefiner, type ResolveVerdict, type VariantProps, createDefiner, createMerger };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ function e(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0})}function t(t,n){let r=t.length;r in t?e(t,r,n):t[r]=n}function n(e){let n=``,r,i=-1,a=-1,o=-1,s=[];for(let c=0;c<e.length;c++){let l=e[c];if(r){l===`\\`?c++:l===r&&(r=void 0);continue}if(n.length>0&&l===`\\`){c++;continue}if(n.length>0&&(l===`"`||l===`'`)){r=l;continue}if(n.length>0&&l===`/`&&e[c+1]===`*`){let t=e.indexOf(`*/`,c+2);if(t<0)break;c=t+1;continue}l===`(`||l===`[`?n+=l===`(`?`)`:`]`:l===n.at(-1)?n=n.slice(0,-1):n.length===0&&(l===`@`?(a===-1&&(a=c),t(s,c)):a===-1&&(l===`:`&&i===-1?i=c:l===`!`&&(o=c)))}let c=a===-1?e.length:a,l=e.slice(0,c),u=!1;o===c-1&&(u=!0,l=l.slice(0,-1));let d=[];for(let n=0;n<s.length;n++){let r=s[n]+1,i=n+1<s.length?s[n+1]:e.length;t(d,e.slice(r,i))}return i!==-1&&i<c?{raw:e,body:l,property:e.slice(0,i),value:l.slice(i+1),keyword:!1,important:u,conditions:d}:{raw:e,body:l,keyword:!0,important:u,conditions:d}}function r(e,t){let n=e.length;n in e?Object.defineProperty(e,n,{configurable:!0,enumerable:!0,value:t,writable:!0}):e[n]=t}function i(e){let t=[],n=[],i=new Map,a=!1,o,s;for(let c=0;c<e.length;c++){let l=e[c];if(n.length===0){l===`\\`?(/\s/.test(e[c+1]??``)&&(o=void 0),c++):/\s/.test(l)?o=void 0:l===`"`||l===`'`?o=o===l?void 0:o??l:!o&&l===`[`&&r(n,c);continue}if((s||a)&&l===`[`&&/[:@\s]/.test(e[c-1])){r(n,c),i.set(c,s??a),a=!1,s=void 0;continue}if(a){l===`*`&&e[c+1]===`/`&&(a=!1,c++);continue}if(s){l===`\\`?c++:l===s&&(s=void 0);continue}if(l===`/`&&e[c+1]===`*`)a=!0,c++;else if(l===`"`||l===`'`)s=l;else if(l===`\\`)c++;else if(l===`[`)r(n,c);else if(l===`]`){let o=n.pop(),l=i.get(o);(/[:@]/.test(e[o-1])||e[c+1]===`:`)&&r(t,{end:c+1,start:o}),l===!0?a=!0:l&&(s=l)}}let c=[];for(let e of t.sort((e,t)=>e.start-t.start||t.end-e.end))(!c.length||e.start>=c.at(-1).end)&&r(c,e);return c}function a(e,t,n){let r=e[t];if(n.blockComment)return r===`*`&&e[t+1]===`/`?(n.blockComment=!1,t+1):t;if(n.quote)return r===`\\`?t+1:(r===n.quote&&(n.quote=void 0),t);if(n.closers.length>0&&r===`/`&&e[t+1]===`*`)return n.blockComment=!0,t+1;if(n.closers.length>0&&(r===`"`||r===`'`))return n.quote=r,t;if(n.closers.length>0&&r===`\\`)return t+1;if(r===`(`||r===`[`)return u(n.closers,r===`(`?`)`:`]`),t;if(r===n.closers.at(-1))return n.closers.pop(),t}function o(e,t,n=e.length){let r={closers:[]};for(let i=t+1;i<n;i++){let t=e[i],n=a(e,i,r);if(n!==void 0){i=n;continue}if(r.closers.length===0){if(t===`}`)return{index:i,kind:`close`};if(t===`{`)return{index:i,kind:`open`}}}return{index:n,kind:`limit`}}const s=/[\s'"`;{},\])]/;function c(e,t,n=e.length){if(e[t]!==`@`)return{conds:``,end:t};let r={closers:[]},i=t;for(;i<n;i++){let t=e[i],n=a(e,i,r);if(n!==void 0){i=n;continue}if(t===`/`&&(e[i+1]===`/`||e[i+1]===`*`)&&r.closers.length===0||s.test(t)&&r.closers.length===0)break}return{conds:e.slice(t,i),end:i}}function l(e){let t=[],n={closers:[]},r=0;for(let i=0;i<e.length;i++){let o=e[i],s=a(e,i,n);if(s!==void 0){i=s;continue}o===`;`&&n.closers.length===0&&(u(t,e.slice(r,i)),r=i+1)}return u(t,e.slice(r)),t.map(e=>e.trim()).filter(Boolean)}function u(e,t){Object.defineProperty(e,e.length,{configurable:!0,enumerable:!0,value:t,writable:!0})}const d=/^(?:--?[\w-]+|[A-Z_$][\w$-]*|@teacss-skip-bracket-[\da-z]{6})$/i;function f(e,t){let n=t;for(;n>0&&/[\w-]/.test(e[n-1]);)n--;if(n===t||e[n-1]!==`:`)return!1;let r=n-1,i=r;for(;i>0&&/[\w$@-]/.test(e[i-1]);)i--;if(!d.test(e.slice(i,r)))return!1;let a=i-1;for(;a>=0&&/\s/.test(e[a]);)a--;return a<0||!`{,?`.includes(e[a])}function p(e){let t=[],n=[],r=[],i=!1,a;for(let o=0;o<e.length;o++){let s=e[o],c=e[o+1];if(n.length===0){s===`(`&&f(e,o)&&u(n,{attached:!0,start:o});continue}if(i)s===`*`&&c===`/`&&(i=!1,o++);else if(a)s===`\\`?o++:s===a&&(a=void 0);else if(s===`\\`)o++;else if(s===`/`&&c===`*`)i=!0,o++;else if(s===`'`||s===`"`||s==="`")a=s;else if(r.length>0)s===`[`||s===`(`?u(r,s===`[`?`]`:`)`):s===r.at(-1)&&r.pop();else if(s===`[`)u(r,`]`);else if(s===`(`)u(n,{attached:f(e,o),start:o});else if(s===`)`){let e=n.pop();e.attached&&u(t,{end:o+1,start:e.start})}}let o=[];for(let e of t.sort((e,t)=>e.start-t.start||t.end-e.end))(o.length===0||e.start>=o.at(-1).end)&&u(o,e);return o}function m(e){if(!e.includes(`{`))return e;let t=``,n=0,r=-1,s=0,u=0,d=e.includes(`[`)?i(e):[],f=e.includes(`(`)?p(e):[],m={closers:[]};for(;n<e.length;){for(;s<d.length&&d[s].end<=n;)s++;for(;u<f.length&&f[u].end<=n;)u++;let i=s<d.length?d[s]:void 0,p=u<f.length?f[u]:void 0,h=i?.start===n?i:p?.start===n?p:void 0;if(h&&m.blockComment!==!0&&m.quote===void 0){t+=e.slice(n,h.end),n=h.end;continue}m.closers.length>0&&/\s/.test(e[n])&&(m.blockComment=!1,m.closers.length=0,m.quote=void 0);let g=a(e,n,m);if(g!==void 0){t+=e.slice(n,g+1),n=g+1;continue}let _=e[n];if(m.closers.length>0||_!==`{`){t+=_,n++;continue}let v=o(e,n);if(v.kind!==`close`){t+=e.slice(n,v.index),n=v.index;continue}let y=v.index,b=e.slice(n+1,y),{conds:x,end:S}=c(e,y+1),C=l(b);if(C.length===0){t+=_,n++;continue}r===n&&t.length>0&&!/\s/.test(t.at(-1))&&(t+=` `),t+=C.map(e=>`${e}${x}`).join(` `),r=S,n=S}return t}function h(e){let t=e.split(/\s+/);return t[0]===``&&t.shift(),t.at(-1)===``&&t.pop(),t}function g(e){if(!e.includes(`[`))return h(e);let t=i(e);if(t.length===0)return h(e);let n=[],a=0,o=-1;for(let i=0;i<e.length;i++){let s=t[a];if(s&&i===s.start){o<0&&(o=i),i=s.end-1,a++;continue}/\s/.test(e[i])?(o>=0&&r(n,e.slice(o,i)),o=-1):o<0&&(o=i)}return o>=0&&r(n,e.slice(o)),n}const _=!1;var v=class extends TypeError{name=`MergerProtocolError`;code;plugin;hook;constructor(e,t,n,r){super(`[TeaCSS merge:${e}] ${t}`),this.code=e,n!==void 0&&(this.plugin=n),r!==void 0&&(this.hook=r)}};function y(){return Object.create(null)}const b=`must have an integer length from 0 through 4294967294`,x=Symbol(`missing-own-value`);function S(e,t){return`value`in t?t.value:t.get===void 0?void 0:Reflect.apply(t.get,e,[])}function C(e,t){let n=Reflect.getOwnPropertyDescriptor(e,t);return n===void 0?x:S(e,n)}function w(e,t){let n=C(e,t);return n===x?void 0:n}function ee(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0})}function T(e,t){let n=e.length;n in e?ee(e,n,t):e[n]=t}function E(e){let t=C(e,`length`);return typeof t==`number`&&Number.isInteger(t)&&t>=0&&t<4294967295?t:null}function te(e){let t=``,n=E(e);if(n===null)throw new v(`INVALID_ARRAY_LENGTH`,`class-value array ${b}`);for(let r=0;r<n;r++){let n=C(e,r);if(n===x)continue;let i=ne(n);i&&(t+=(t&&` `)+i)}return t}function ne(e){if(!e)return``;if(typeof e==`string`)return e;if(typeof e==`number`||typeof e==`bigint`)return String(e);if(Array.isArray(e))return te(e);if(typeof e==`object`){let t=e,n=``;for(let e of Reflect.ownKeys(t)){if(typeof e!=`string`)continue;let r=Reflect.getOwnPropertyDescriptor(t,e);r===void 0||!r.enumerable||S(t,r)&&(n+=(n&&` `)+e)}return n}return``}function re(e,t){let n=e;for(let e of t){let t=n.children??=new Map,r=t.get(e);r===void 0&&(r=y(),t.set(e,r)),n=r}return n}function ie(e,t,n){let r=re(e,t);return n?r.keywords??=new Map:r.declarations??=new Map}function ae(e){if(e.length===0)return``;if(e.length===1){let t=C(e,0);return t===x?``:t??``}let t=y(),r=new Uint8Array(e.length),i=new Uint8Array(e.length);for(let a=0;a<e.length;a++){let o=n(e[a]),s=ie(t,o.conditions,o.keyword),c=o.property??o.body,l=s.get(c);r[a]=+!!o.important,l===void 0?s.set(c,a):r[l]!==0&&r[a]===0?i[a]=1:(i[l]=1,s.set(c,a))}let a=[];for(let t=0;t<e.length;t++)i[t]===0&&T(a,e[t]);return a.join(` `)}function oe(e,t){if(typeof e==`string`)return e.length===0?null:[e];if(!Array.isArray(e))return null;let n=E(e);if(n===null||n===0)return null;let r=[],i=null;for(let a=0;a<n;a++){let n=C(e,a);if(n===x||typeof n!=`string`||n.length===0)return null;(i===null?r.includes(n):i.has(n))||(T(r,n),i===null?r.length===(t?64:4)&&(i=new Set(r)):i.add(n))}return t&&r.length>1&&r.sort(),r}function se(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function D(e,t,n,r,i){for(let a of Reflect.ownKeys(t)){if(typeof a!=`string`)continue;let o=Reflect.getOwnPropertyDescriptor(t,a);if(o===void 0||!o.enumerable)continue;let s=oe(S(t,o),!0);if(s===null)throw new v(`INVALID_STATIC_CONFLICT`,`"${r}" ${n} "${a}" must contain at least one non-empty atom`,i);let c=e.get(a);if(c===void 0){e.set(a,{atoms:s,atomSet:s.length>4?new Set(s):null,source:r});continue}if(!se(c.atoms,s))throw new v(`STATIC_CONFLICT_COLLISION`,`static ${n} "${a}" has conflicting atom sets from "${c.source}" and "${r}"`,i)}}function O(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function k(e){if(!O(e))return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}function ce(e,t,n){if(!O(e))throw new v(`INVALID_CONFLICT_META`,`"${t}" conflicts must be an object`,n);let r=w(e,`keywords`);if(!k(r))throw new v(`INVALID_CONFLICT_META`,`"${t}" keywords must be a record`,n);let i=w(e,`overlaps`);if(!k(i))throw new v(`INVALID_CONFLICT_META`,`"${t}" overlaps must be a record`,n);return{keywords:r,overlaps:i}}function A(e,t,n,r){if(n!==void 0){if(typeof n!=`function`)throw new v(`INVALID_PLUGIN_HOOK`,`plugin "${e}" ${t} must be a function`,e,r);return n}}function le(e){let t=[],n=[],r=[],i=[],a=[],o=new Set,s=E(e);if(s===null)throw new v(`INVALID_OPTIONS`,`options.plugins must be an array with an integer length from 0 through 4294967294`);for(let c=0;c<s;c++){let s=C(e,c),l=s===x?void 0:s;if(!O(l))throw new v(`INVALID_PLUGIN_NAME`,`plugin at index ${c} must have a non-empty name`);let u=w(l,`name`);if(typeof u!=`string`||u.length===0)throw new v(`INVALID_PLUGIN_NAME`,`plugin at index ${c} must have a non-empty name`);if(o.has(u))throw new v(`DUPLICATE_PLUGIN_NAME`,`duplicate plugin name "${u}"`,u);o.add(u);let d=w(l,`conflicts`),f=A(u,`tokens`,w(l,`tokens`),`tokens`),p=A(u,`group`,w(l,`group`),`group`),m=A(u,`finalize`,w(l,`finalize`),`finalize`),h=A(u,`resolveFamily`,w(l,`resolveFamily`),`resolveFamily`),g=A(u,`resolve`,w(l,`resolve`),`resolve`);if(h!==void 0&&g===void 0)throw new v(`INVALID_PLUGIN_HOOK`,`plugin "${u}" resolveFamily requires resolve`,u,`resolveFamily`);T(t,{name:u,conflicts:d===void 0?void 0:ce(d,u,u)}),f!==void 0&&T(n,{name:u,hook:f}),p!==void 0&&T(r,{name:u,hook:p}),m!==void 0&&T(i,{name:u,hook:m}),g!==void 0&&T(a,{name:u,hook:g,family:h})}return{metadata:t,tokens:n,groups:r,finalizers:i,resolvers:a}}function ue(e,t){let n=new Map,r=new Map;e!==void 0&&(D(n,e.keywords,`keyword`,`<options.conflicts>`),D(r,e.overlaps,`declaration`,`<options.conflicts>`));for(let e of t)e.conflicts!==void 0&&(D(n,e.conflicts.keywords,`keyword`,e.name,e.name),D(r,e.conflicts.overlaps,`declaration`,e.name,e.name));return{keywords:n,overlaps:r}}function de(e){let t=n(e);return{raw:e,prefix:t.property??t.body,body:t.body,value:t.value,keyword:t.keyword,conditions:t.conditions,important:t.important}}function fe(){let e=new Map;return t=>{let n=e.get(t);if(n!==void 0)return n;let r=de(t);return e.set(t,r),r}}function pe(e,t,n){if(t.length===0)return e;let r=e,i={viewToken:n};for(let e of t){let t=e.hook,n=t(r,i),a=`plugin "${e.name}" tokens() must return an array of individual non-empty class tokens`;if(!Array.isArray(n))throw new v(`INVALID_TOKEN_TRANSFORM_RESULT`,a,e.name,`tokens`);let o=[],s=E(n);if(s===null)throw new v(`INVALID_TOKEN_TRANSFORM_RESULT`,a,e.name,`tokens`);for(let t=0;t<s;t++){let r=C(n,t);if(r===x||typeof r!=`string`||r.length===0)throw new v(`INVALID_TOKEN_TRANSFORM_RESULT`,a,e.name,`tokens`);let i=g(r);if(i.length!==1||i[0]!==r)throw new v(`INVALID_TOKEN_TRANSFORM_RESULT`,a,e.name,`tokens`);T(o,r)}r=o}return r}function j(e,t){let n=null;for(let r=0;r<t.length;r++){let i=t[r];if(i.family===void 0)continue;let a=i.family,o=a(e);if(o!==null&&(typeof o!=`string`||o.length===0))throw new v(`INVALID_RESOLVE_FAMILY_RESULT`,`plugin "${i.name}" resolveFamily() must return null or a non-empty string`,i.name,`resolveFamily`);o!==null&&((n??=Array.from({length:t.length},()=>null))[r]=o)}return n}function me(e,t,n,r,i,a){let o=a(e),s;for(let e of n){let n=e.hook,i=n(o);if(i===null)continue;if(i===!1)return s={id:t,view:o,atoms:[],atomSet:null,dynamic:!0,opaque:!0},{...s,resolverFamilies:null};let a=oe(i,!1);if(a===null)throw new v(`INVALID_GROUP_RESULT`,`plugin "${e.name}" group() must return null, MERGE_OPAQUE, or at least one non-empty atom`,e.name,`group`);return s={id:t,view:o,atoms:a,atomSet:a.length>4?new Set(a):null,dynamic:!0,opaque:!1},{...s,resolverFamilies:j(o,r)}}let c=o.keyword?i.keywords.get(o.prefix):i.overlaps.get(o.prefix);return c===void 0?(s={id:t,view:o,atoms:[o.keyword?`@teacss/classes:keyword:${o.prefix}`:`@teacss/classes:declaration:${o.prefix}`],atomSet:null,opaque:!1},{...s,resolverFamilies:j(o,r)}):(s={id:t,view:o,atoms:c.atoms,atomSet:c.atomSet,opaque:!1},{...s,resolverFamilies:j(o,r)})}function he(e,t){let n=new Map;for(let r of e){if(!r.opaque)continue;let e=n.get(r.view.raw);e!==void 0&&(t[e]=1),n.set(r.view.raw,r.id)}}function M(e,t){return new v(`INVALID_FINALIZER_RESULT`,`plugin "${e}" finalize() returned invalid occurrence id ${typeof t==`bigint`?`${t}n`:typeof t==`number`||typeof t==`boolean`||t==null?String(t):typeof t}`,e,`finalize`)}function ge(e,t){let n=[];for(let r of e)!r.opaque&&t[r.id]===0&&T(n,r);return n}function _e(e,t,n,r){let i=!1,a=r;for(let r of t){let t=r.hook,o=t(a?ge(e,n):e.slice());if(o===null)continue;if(!Array.isArray(o))throw M(r.name,o);let s=E(o);if(s===null)throw new v(`INVALID_FINALIZER_RESULT`,`plugin "${r.name}" finalize() result ${b}`,r.name,`finalize`);if(s===0)continue;let c=new Set;for(let t=0;t<s;t++){let i=C(o,t);if(i===x)throw M(r.name,void 0);let a=i;if(!Number.isInteger(a))throw M(r.name,a);let s=a,l=e[s];if(l===void 0||l.opaque||n[s]!==0||c.has(s))throw M(r.name,a);c.add(s)}for(let e of c)n[e]=1;c.size!==0&&(i=!0,a=!0)}return i}function ve(e,t){return e.atomSet?.has(t)??e.atoms.includes(t)}function ye(e,t){return e.dynamic!==!0&&t.dynamic!==!0&&e.view.keyword===t.view.keyword&&e.view.prefix===t.view.prefix}function be(e,t){if(ye(e,t))return!0;if(e.atoms.length<t.atoms.length)return!1;for(let n of t.atoms)if(!ve(e,n))return!1;return!0}function xe(e,t){if(e.atomSet!==null){for(let n of t.atoms)if(e.atomSet.has(n))return!0;return!1}if(t.atomSet!==null){for(let n of e.atoms)if(t.atomSet.has(n))return!0;return!1}for(let n of t.atoms)if(e.atoms.includes(n))return!0;return!1}function Se(e,t){let n=re(e,t);return n.winners??=new Map}function Ce(e,t,n){let r=y();for(let i of e){if(i.opaque||t[i.id]!==0)continue;let a=Se(r,i.view.conditions),o=n?`${i.view.keyword?`keyword`:`declaration`}:${i.view.prefix}`:i.atoms[0],s=a.get(o);if(s===void 0){a.set(o,i.id);continue}e[s].view.important&&!i.view.important?t[i.id]=1:(t[s]=1,a.set(o,i.id))}}function we(e,t,n,r,i){return e.view.important===t.view.important?n||i===`symmetric`?`earlier`:`none`:t.view.important?n?`earlier`:`none`:r?`later`:`none`}function Te(e,t,n,r){let i=be(t,e),a=be(e,t),o=we(e,t,i,a,n);for(let n=0;n<r.length;n++){let s=r[n];if(s.family!==void 0){let r=e.resolverFamilies?.[n]??null,i=t.resolverFamilies?.[n]??null;if(r===null||r!==i)continue}let c=s.hook,l=c(e.view,t.view,{covers:i,earlierCoversLater:a,defaultDrop:o});if(l!==null){if(l===`earlier`||l===`later`||l===`none`)return l;throw new v(`INVALID_RESOLVE_RESULT`,`plugin "${s.name}" resolve() must return null, "earlier", "later", or "none"`,s.name,`resolve`)}}return o}function N(e,t,n,r,i){let a=Te(e,t,n,r);a===`earlier`?i[e.id]=1:a===`later`&&(i[t.id]=1)}function Ee(e,t,n,r,i){let a=t[e];for(let o=e+1;o<t.length;o++){let e=t[o];se(a.view.conditions,e.view.conditions)&&(!ye(a,e)&&!xe(a,e)||N(a,e,n,r,i))}}function De(e,t){let n=re(e,t);return n.postings??=new Map}function Oe(e){let t=y(),n=[],r=[],i=e.length*(e.length-1)/2,a=0;for(let o=0;o<e.length;o++){let s=e[o],c=De(t,s.view.conditions),l=[];T(n,c),T(r,l);for(let e of s.atoms){let t=c.get(e);if(t===void 0&&(t=[],c.set(e,t)),a+=t.length,a>i)return null;T(l,t.length),T(t,o)}}return{postingMaps:n,positions:r,postingPairVisits:a}}function ke(e,t,n,r){for(let i=0;i<e.length;i++)Ee(i,e,t,n,r)}function Ae(e,t,n,r,i,a){if(a!==null){Ce(e,r,a===`static-prefix`);return}let o=e;if(i){let t=[];for(let n of e)!n.opaque&&r[n.id]===0&&T(t,n);o=t}if(o.length<16){ke(o,t,n,r);return}let s=Oe(o);if(s===null){ke(o,t,n,r);return}if(s.postingPairVisits===0)return;let c=new Uint32Array(o.length),l=[];for(let e=0;e<o.length;e++){let i=o[e],a=s.postingMaps[e],u=s.positions[e];if(i.atoms.length===1){let e=a.get(i.atoms[0]);for(let a=u[0]+1;a<e.length;a++)N(i,o[e[a]],t,n,r);continue}let d=0;for(let e=0;e<i.atoms.length;e++){let t=a.get(i.atoms[e]);d+=t.length-u[e]-1}if(d>=o.length-e-1){Ee(e,o,t,n,r);continue}l.length=0;let f=!0,p=e+1;for(let e=0;e<i.atoms.length;e++){let t=a.get(i.atoms[e]);for(let n=u[e]+1;n<t.length;n++){let e=t[n];c[e]!==p&&(c[e]=p,l.length!==0&&e<l[l.length-1]&&(f=!1),T(l,e))}}f||l.sort((e,t)=>e-t);for(let e of l)N(i,o[e],t,n,r)}}function je(e,t,n,r,i){let a=pe(e,r.tokens,i);if(a.length<2&&r.groups.length===0&&r.finalizers.length===0&&r.resolvers.length===0){if(a.length===0)return``;let e=C(a,0);return e===x?``:e??``}let o=[],s=!1,c=a.length>=16&&r.resolvers.every(e=>e.family!==void 0),l=c,u=c,d,f,p=0;for(let e=0;e<a.length;e++){let n=me(a[e],e,r.groups,r.resolvers,t,i);if(n.opaque)s=!0;else if(p++,n.atoms.length!==1&&(l=!1),n.dynamic===!0?u=!1:d===void 0?(d=n.view.prefix,f=n.view.keyword):(n.view.prefix!==d||n.view.keyword!==f)&&(u=!1),n.resolverFamilies!==null){for(let e of n.resolverFamilies)if(e!==null){l=!1,u=!1;break}}T(o,n)}let m=new Uint8Array(o.length);s&&he(o,m);let h=_e(o,r.finalizers,m,s),g=p<16?null:l?`singleton`:u?`static-prefix`:null;Ae(o,n,r.resolvers,m,s||h,g);let _=[];for(let e of o)m[e.id]===0&&T(_,e.view.raw);return _.join(` `)}function Me(e,t,n){let r=C(e,n);if(r===x)return``;if(typeof r==`string`)return r;if(Array.isArray(t)){let e=C(t,n);if(typeof e==`string`)return e}return``}function Ne(e){return typeof e==`number`||typeof e==`bigint`?String(e):ne(e)}function Pe(e,t,n){let r=``,i=E(e);if(i===null)throw new v(`INVALID_ARRAY_LENGTH`,`tagged-template strings ${b}`);for(let a=0;a<i;a++)if(r+=Me(e,t,a),a+1<i&&a+1<n.length){let e=Ne(n[a+1]);r+=e}return r}function Fe(e={}){if(!k(e))throw new v(`INVALID_OPTIONS`,`options must be an object`);let t=w(e,`conflicts`),n=w(e,`overlap`),r=w(e,`plugins`),i=w(e,`cache`);if(n!==void 0&&n!==`precise`&&n!==`symmetric`)throw new v(`INVALID_OPTIONS`,`options.overlap must be "precise" or "symmetric"`);if(r!==void 0&&!Array.isArray(r))throw new v(`INVALID_OPTIONS`,`options.plugins must be an array`);let a=le(r===void 0?[]:r),o=ue(t===void 0?void 0:ce(t,`<options.conflicts>`),a.metadata),s=a.tokens.length!==0||a.groups.length!==0||a.finalizers.length!==0||a.resolvers.length!==0,c=!s&&o.keywords.size===0&&o.overlaps.size===0,l=n??`precise`,u=1500;if(i===!1)u=0;else if(i!==void 0){if(!k(i))throw new v(`INVALID_CACHE_OPTIONS`,`options.cache must be false or an object`);let e=w(i,`max`);if(e!==void 0){if(typeof e!=`number`||!Number.isFinite(e)||!Number.isInteger(e)||e<0)throw new v(`INVALID_CACHE_OPTIONS`,`options.cache.max must be a finite non-negative integer`);u=e}}let d=u>0?new Map:null;function f(e){if(d!==null){let t=d.get(e);if(t!==void 0)return d.delete(e),d.set(e,t),t}let t=g(m(e).trim()),n=c?ae(t):je(t,o,l,a,s?fe():de);return d!==null&&(d.set(e,n),d.size>u&&d.delete(d.keys().next().value)),n}function p(...e){let t=e[0],n=Array.isArray(t)?C(t,`raw`):x;return f(Array.isArray(n)?Pe(t,n,e):te(e))}return p}const P=Object.prototype.propertyIsEnumerable,F=`definition.styles`,I=`definition.variants`,L=`definition.defaultVariants`,R=`definition.compoundVariants`,z=`createDefiner options`,B=`${z}.merge`,V=`recipe props`,H=`className`,Ie=`parts`,Le=`null is not allowed`,Re=`required own enumerable field`,ze=new Set([`styles`,`variants`,`defaultVariants`,`compoundVariants`,`extend`]),Be=new Set([`class`,`className`,`then`,`toJSON`,`toString`,`valueOf`]),Ve=new Set([`class`,`className`,`parts`]);function U(e){return e.length>16?new Set(e):void 0}function W(e,t,n){return t?.has(n)??e.includes(n)}function G(e,t){return TypeError(`[TeaCSS recipe] ${e}: ${t}`)}function K(e,t){if(typeof e!=`object`||!e||Array.isArray(e))throw G(t,`expected a plain record`);let n=Object.getPrototypeOf(e);if(n!==Object.prototype&&n!==null)throw G(t,`expected Object.prototype or null prototype`);return Object.keys(e)}function He(e,t){if(typeof e!=`object`||!e||Array.isArray(e))throw G(t,`expected a non-null, non-array object`);return Object.keys(e)}function q(e,t,n){let r=Reflect.getOwnPropertyDescriptor(e,t);if(r===void 0||!r.enumerable)throw G(n,`expected an own enumerable field`);return`value`in r?r.value:r.get===void 0?void 0:Reflect.apply(r.get,e,[])}function Ue(e,t){let n=Reflect.getOwnPropertyDescriptor(e,`length`),r=n!==void 0&&`value`in n?n.value:void 0;if(typeof r!=`number`||!Number.isInteger(r)||r<0||r>=4294967295)throw G(t,`expected an array with a valid own length`);return r}function We(e,t,n){if(!Array.isArray(e))throw G(t,`expected an array`);let r=Object.keys(e),i=Ue(e,t);if(!n&&i===0)throw G(t,`expected a non-empty array`);if(r.length!==i)throw G(t,`expected a dense own-indexed array`);for(let e of r){let n=Number(e);if(!Number.isInteger(n)||n<0||n>=i||String(n)!==e)throw G(t,`expected a dense own-indexed array`)}let a=Z(i);for(let n=0;n<i;n++)a[n]=q(e,n,`${t}[${n}]`);return a}function Ge(e,t){if(e.trim().length===0)throw G(t,`name must contain a non-whitespace character`)}function J(e){let t=te([e]);return t.length===0?void 0:t}function Y(e,t,n){if(n===void 0)return;let r=P.call(e,t)?e[t]:void 0;e[t]=r===void 0?[n]:[...r,n]}function Ke(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0})}function X(e,t){let n=e.length;n in e?Ke(e,n,t):e[n]=t}function Z(e){return Array.from({length:e},()=>void 0)}function qe(){return[void 0,void 0,void 0,void 0,void 0,void 0,void 0,void 0]}const Je=qe().length;function Ye(e,t,n){t<Je||!(t in e)?e[t]=n:Ke(e,t,n)}function Q(e,t=e.length){let n=Z(t),r=Math.min(e.length,t);for(let t=0;t<r;t++){if(!P.call(e,t))continue;let r=e[t];r!==void 0&&(n[t]=[...r])}return n}function Xe(e,t){return e.map(e=>{let n=Object.create(null);for(let r of Object.keys(e.choices))n[r]={fragmentsByPart:Q(e.choices[r].fragmentsByPart,t)};return{name:e.name,choices:n,booleanCapable:e.booleanCapable}})}function $(e,t,n){if(e===null)return null;if(typeof e==`string`){if(!P.call(t.choices,e))throw G(n,`unknown choice ${JSON.stringify(e)}`);return e}if(typeof e==`number`){if(!Number.isFinite(e))throw G(n,`expected a finite numeric choice`);let r=String(e);if(!P.call(t.choices,r))throw G(n,`unknown choice ${JSON.stringify(r)}`);return r}if(typeof e==`boolean`){if(!t.booleanCapable)throw G(n,`boolean selection requires a true or false choice`);return String(e)}throw G(n,`expected null, a declared string or finite numeric choice, or a supported boolean state`)}function Ze(e,t,n){if(n&&(e=t.partNames.length===0?``:{}),typeof e==`string`){if(t!==void 0&&t.partNames.length>0)throw G(F,`must be a record when extending a multi-element recipe`);let n=t===void 0?Z(1):Q(t.baseFragmentsByPart,1);return Y(n,0,J(e)),{names:[],indexes:Object.create(null),baseFragments:n}}let r=K(e,F);if(t!==void 0&&t.partNames.length===0)throw G(F,`must be a string when extending a single-element recipe`);if(!n&&r.length===0)throw G(F,`expected at least one named style`);for(let e of r){let t=`${F}.${e}`;if(Ge(e,t),Be.has(e))throw G(t,`reserved style name`)}let i=t===void 0?[]:[...t.partNames],a=Object.create(null);for(let e=0;e<i.length;e++)a[i[e]]=e;let o=t===void 0?[]:Q(t.baseFragmentsByPart),s=e;for(let e of r){let t=a[e];t===void 0&&(t=i.length,X(i,e),a[e]=t,X(o,void 0)),Y(o,t,J(q(s,e,`${F}.${e}`)))}return{names:i,indexes:a,baseFragments:o}}function Qe(e,t,n,r,i,a){if(n){if(typeof t!=`string`)throw G(i,`expected a primitive string`);Y(e,0,J(t));return}let o=K(t,i);if(a&&o.length===0)throw G(i,`expected at least one style target`);let s=t;for(let t of o){let n=r[t];if(n===void 0)throw G(`${i}.${t}`,`unknown style target`);Y(e,n,J(q(s,t,`${i}.${t}`)))}}function $e(e,t,n,r,i){let a=t===void 0?[]:Xe(t.variants,i),o=Object.create(null);for(let e=0;e<a.length;e++)o[a[e].name]=e;if(e===void 0)return{variants:a,indexes:o};if(e===null)throw G(I,Le);let s=K(e,I),c=e;for(let e of s){let t=`${I}.${e}`;if(Ge(e,t),Ve.has(e))throw G(t,`reserved variant name`);let s=q(c,e,t),l=K(s,t);if(l.length===0)throw G(t,`expected at least one choice`);let u=s,d=o[e],f;d===void 0?(d=a.length,o[e]=d,f=Object.create(null),X(a,{name:e,choices:f,booleanCapable:!1})):f=a[d].choices;for(let e of l){let a=`${t}.${e}`,o=q(u,e,a),s=f[e],c=s===void 0?Z(i):Q(s.fragmentsByPart,i);Qe(c,o,n,r,a,!1),f[e]={fragmentsByPart:c}}a[d]={name:e,choices:f,booleanCapable:P.call(f,`true`)||P.call(f,`false`)}}return{variants:a,indexes:o}}function et(e,t,n,r){let i=Z(n.length);if(t!==void 0){let e=Math.min(t.defaultStates.length,n.length);for(let n=0;n<e;n++)P.call(t.defaultStates,n)&&(i[n]=t.defaultStates[n])}if(e===void 0)return i;if(e===null)throw G(L,Le);let a=K(e,L),o=U(a);for(let e of a)if(r[e]===void 0)throw G(`${L}.${e}`,`unknown variant`);let s=e;for(let e=0;e<n.length;e++){let t=n[e];if(!W(a,o,t.name))continue;let r=`${L}.${t.name}`,c=q(s,t.name,r);c!==void 0&&(i[e]=$(c,t,r))}return i}function tt(e,t,n){if(!Array.isArray(e)){if(e===void 0)throw G(n,`undefined is not a condition`);return[$(e,t,n)]}let r=We(e,n,!1),i=[];for(let e=0;e<r.length;e++){let a=r[e];if(a===void 0)throw G(`${n}[${e}]`,`undefined is not a condition`);X(i,$(a,t,`${n}[${e}]`))}return i}function nt(e,t,n,r,i,a,o){let s=t===void 0?[]:t.compounds.map(e=>({conditions:e.conditions,fragmentsByPart:Q(e.fragmentsByPart,i)}));if(e===void 0)return s;if(e===null)throw G(R,Le);let c=We(e,R,!0);for(let e=0;e<c.length;e++){let t=c[e],l=`${R}[${e}]`,u=K(t,l),d=U(u),f=W(u,d,Ie);if(!W(u,d,H))throw G(`${l}.className`,n||f?`required own enumerable string`:`required own enumerable style map`);for(let e of u)if(e!==H&&e!==Ie&&o[e]===void 0)throw G(`${l}.${e}`,`unknown variant condition`);let p=t,m=[];for(let e=0;e<a.length;e++){let t=a[e];if(!W(u,d,t.name))continue;let n=`${l}.${t.name}`;X(m,{variantIndex:e,states:tt(q(p,t.name,n),t,n)})}let h=`${l}.className`,g=q(p,H,h),_=Z(i);if(f){let e=`${l}.parts`;if(n)throw G(e,`only valid for multi-element recipes`);if(typeof g!=`string`)throw G(h,`expected a primitive string when parts is present`);let t=We(q(p,Ie,e),e,!1),i=J(g);for(let n=0;n<t.length;n++){let a=t[n],o=`${e}[${n}]`;if(typeof a!=`string`)throw G(o,`expected a declared style name`);let s=r[a];if(s===void 0)throw G(o,`unknown style target`);if(t.indexOf(a)!==n)throw G(o,`duplicate style target ${JSON.stringify(a)}`);Y(_,s,i)}}else Qe(_,g,n,r,h,!0);X(s,{conditions:m,fragmentsByPart:_})}return s}function rt(e,t){let n=K(e,`definition`);for(let e of n)if(!ze.has(e))throw G(`definition.${e}`,`unknown field`);let r=e,i;if(n.includes(`extend`)){let e=q(r,`extend`,`definition.extend`);if(e!==void 0&&(typeof e!=`function`||(i=t.get(e))===void 0))throw G(`definition.extend`,`expected a recipe from this exact definer`)}let a=n.includes(`styles`);if(!a&&i===void 0)throw G(F,Re);let o=Ze(a?q(r,`styles`,F):void 0,i,!a),s=o.baseFragments.length,c=o.names.length===0,l=$e(n.includes(`variants`)?q(r,`variants`,I):void 0,i,c,o.indexes,s),u=et(n.includes(`defaultVariants`)?q(r,`defaultVariants`,L):void 0,i,l.variants,l.indexes),d=nt(n.includes(`compoundVariants`)?q(r,`compoundVariants`,R):void 0,i,c,o.indexes,s,l.variants,l.indexes),f=Z(s);for(let e of d)for(let t=0;t<s;t++)e.fragmentsByPart[t]!==void 0&&X(f[t]??=[],e);return{partNames:o.names,baseFragmentsByPart:o.baseFragments,variants:l.variants,defaultStates:u,compounds:d,compoundsByPart:f}}function it(e,t){if(e===void 0)return t.defaultStates;let n=He(e,V),r=U(n);if(W(n,r,`class`))throw G(`${V}.class`,`reserved field`);if(W(n,r,H))throw G(`${V}.className`,`caller classes belong to a style resolver`);let i=e,a;for(let e=0;e<t.variants.length;e++){let o=t.variants[e];if(!W(n,r,o.name))continue;let s=`${V}.${o.name}`,c=q(i,o.name,s);c!==void 0&&(a??=[...t.defaultStates],a[e]=$(c,o,s))}return a??t.defaultStates}function at(e,t,n){if(t!==void 0){let e=n<Je||P.call(t,n)?t[n]:void 0;if(e!==void 0)return e}return e[n]}function ot(e,t,n){for(let r of e.conditions){let e=at(t,n,r.variantIndex),i=!1;for(let t of r.states)if(e===t){i=!0;break}if(!i)return!1}return!0}function st(e,t,n){if(n===void 0)return t;for(let r of n)Ye(e,t,r),t++;return t}function ct(e,t,n,r,i,a,o){let s,c;if(r!==void 0){let t=He(r,a),n=U(t);if(W(t,n,`class`))throw G(`${a}.class`,`reserved field`);let i=r;for(let r=0;r<e.variants.length;r++){let o=e.variants[r];if(!W(t,n,o.name))continue;let c=`${a}.${o.name}`,l=q(i,o.name,c);l!==void 0&&(s??=qe(),Ye(s,r,$(l,o,c)))}W(t,n,`className`)&&(c=q(i,`className`,`${a}.className`))}let l=qe(),u=st(l,0,e.baseFragmentsByPart[t]);for(let r=0;r<e.variants.length;r++){let i=at(n,s,r);if(i==null)continue;let a=e.variants[r].choices[i];a!==void 0&&(u=st(l,u,a.fragmentsByPart[t]))}for(let r of e.compoundsByPart[t]??[])ot(r,n,s)&&(u=st(l,u,r.fragmentsByPart[t]));c!==void 0&&(Ye(l,u,c),u++),l.length=u;let d=Reflect.apply(i,void 0,l);if(typeof d!=`string`)throw G(o,`merger must return a primitive string`);return d}function lt(e,t){return e.partNames.length===0?(n=>ct(e,0,e.defaultStates,n,t,V,`recipe result`)):(n=>{let r=it(n,e),i=Object.create(null);for(let n=0;n<e.partNames.length;n++){let a=e.partNames[n];i[a]=i=>ct(e,n,r,i,t,`style props.${a}`,`style result.${a}`)}return i})}function ut(e){let t=K(e,z);for(let e of t)if(e!==`merge`)throw G(z,`unknown field ${JSON.stringify(e)}`);if(!t.includes(`merge`))throw G(B,Re);let n=q(e,`merge`,B);if(typeof n!=`function`)throw G(B,`expected a callable merger`);let r=n,i=new WeakMap;return(e=>{let t=rt(e,i),n=lt(t,r);return i.set(n,t),n})}export{_ as MERGE_OPAQUE,v as MergerProtocolError,ut as createDefiner,Fe as createMerger};
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@teacss/classes",
3
+ "version": "0.3.0",
4
+ "description": "TeaCSS class composition — typed recipes, nested class-value joining, and semantic conflict resolution.",
5
+ "homepage": "https://css.teasim.com",
6
+ "funding": "https://github.com/sponsors/billgo",
7
+ "license": "MIT",
8
+ "author": "Billgo <hi@billgo.me>",
9
+ "sideEffects": false,
10
+ "type": "module",
11
+ "exports": {
12
+ ".": "./dist/index.js",
13
+ "./package.json": "./package.json"
14
+ },
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "bunx rimraf dist && bunx tsdown --config tsdown.config.mts",
22
+ "dev": "tsdown --watch"
23
+ },
24
+ "devDependencies": {
25
+ "@teacss/core": "0.3.0"
26
+ },
27
+ "engines": {
28
+ "node": ">=22.12.0"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ }
33
+ }