typestyles 0.1.0 → 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/dist/{chunk-PFDN4Y4C.js → chunk-BB7C47TQ.js} +14 -3
- package/dist/chunk-BB7C47TQ.js.map +1 -0
- package/dist/{hmr-CSDtaPpU.d.cts → hmr-BACAnP4Y.d.cts} +16 -1
- package/dist/{hmr-CSDtaPpU.d.ts → hmr-BACAnP4Y.d.ts} +16 -1
- package/dist/hmr.d.cts +1 -1
- package/dist/hmr.d.ts +1 -1
- package/dist/hmr.js +1 -1
- package/dist/index.cjs +66 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -3
- package/dist/index.d.ts +81 -3
- package/dist/index.js +41 -10
- package/dist/index.js.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-PFDN4Y4C.js.map +0 -1
|
@@ -91,6 +91,17 @@ function startCollection() {
|
|
|
91
91
|
function getRegisteredCss() {
|
|
92
92
|
return allRules.join("\n");
|
|
93
93
|
}
|
|
94
|
+
function reset() {
|
|
95
|
+
insertedRules.clear();
|
|
96
|
+
pendingRules = [];
|
|
97
|
+
allRules.length = 0;
|
|
98
|
+
flushScheduled = false;
|
|
99
|
+
ssrBuffer = null;
|
|
100
|
+
if (isBrowser && styleElement) {
|
|
101
|
+
styleElement.remove();
|
|
102
|
+
styleElement = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
94
105
|
function flushSync() {
|
|
95
106
|
flush();
|
|
96
107
|
}
|
|
@@ -190,6 +201,6 @@ function ruleMatchesKey(cssText, key) {
|
|
|
190
201
|
return false;
|
|
191
202
|
}
|
|
192
203
|
|
|
193
|
-
export { __export, flushSync, getRegisteredCss, insertRule, insertRules, invalidateKeys, invalidatePrefix, startCollection };
|
|
194
|
-
//# sourceMappingURL=chunk-
|
|
195
|
-
//# sourceMappingURL=chunk-
|
|
204
|
+
export { __export, flushSync, getRegisteredCss, insertRule, insertRules, invalidateKeys, invalidatePrefix, reset, startCollection };
|
|
205
|
+
//# sourceMappingURL=chunk-BB7C47TQ.js.map
|
|
206
|
+
//# sourceMappingURL=chunk-BB7C47TQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sheet.ts"],"names":[],"mappings":"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","file":"chunk-BB7C47TQ.js","sourcesContent":["const STYLE_ELEMENT_ID = 'typestyles';\n\n/**\n * Tracks which CSS rules have been inserted to avoid duplicates.\n */\nconst insertedRules = new Set<string>();\n\n/**\n * Buffer of CSS rules waiting to be flushed.\n */\nlet pendingRules: string[] = [];\n\n/**\n * All CSS rules ever registered (for SSR extraction).\n * Unlike pendingRules (which is cleared on flush), this retains every rule\n * so getRegisteredCss() can return the full stylesheet at any point.\n */\nconst allRules: string[] = [];\n\n/**\n * Whether a flush is scheduled.\n */\nlet flushScheduled = false;\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * When in SSR collection mode, CSS is captured here instead of injected.\n */\nlet ssrBuffer: string[] | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\nfunction getStyleElement(): HTMLStyleElement {\n if (styleElement) return styleElement;\n\n // Check for an existing element (e.g., from SSR)\n const existing = document.getElementById(\n STYLE_ELEMENT_ID\n ) as HTMLStyleElement | null;\n if (existing) {\n styleElement = existing;\n return styleElement;\n }\n\n // Create a new one\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n return styleElement;\n}\n\nfunction flush(): void {\n flushScheduled = false;\n if (pendingRules.length === 0) return;\n\n const rules = pendingRules;\n pendingRules = [];\n\n if (ssrBuffer) {\n ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n\n if (sheet) {\n for (const rule of rules) {\n try {\n sheet.insertRule(rule, sheet.cssRules.length);\n } catch {\n // Fallback: append as text (handles edge cases with certain selectors)\n el.appendChild(document.createTextNode(rule));\n }\n }\n } else {\n // Sheet not available yet, append as text\n el.appendChild(document.createTextNode(rules.join('\\n')));\n }\n}\n\nfunction scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n\n if (ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n scheduleFlush();\n}\n\n/**\n * Insert multiple CSS rules at once.\n */\nexport function insertRules(rules: Array<{ key: string; css: string }>): void {\n let added = false;\n for (const { key, css } of rules) {\n if (insertedRules.has(key)) continue;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n added = true;\n }\n if (added) scheduleFlush();\n}\n\n/**\n * Replace a CSS rule (used for HMR). Removes the old rule and inserts the new one.\n */\nexport function replaceRule(key: string, css: string): void {\n if (!isBrowser) return;\n\n insertedRules.delete(key);\n\n // Remove existing rule from the sheet if possible\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n // We can't reliably match by key in CSSOM, so for HMR we fall back to\n // clearing and re-inserting. This is fine since HMR is dev-only.\n }\n }\n\n insertRule(key, css);\n}\n\n/**\n * Start collecting CSS for SSR. Returns a function to stop collection and get the CSS.\n */\nexport function startCollection(): () => string {\n ssrBuffer = [];\n return () => {\n const css = ssrBuffer ? ssrBuffer.join('\\n') : '';\n ssrBuffer = null;\n return css;\n };\n}\n\n/**\n * Return all registered CSS as a string.\n *\n * Unlike `collectStyles`, this doesn't require wrapping a render function.\n * It simply returns every CSS rule that has been registered via\n * `styles.create`, `tokens.create`, `keyframes.create`, etc.\n *\n * Ideal for SSR frameworks that need the CSS separately from the render\n * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links).\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles/server';\n *\n * // In a route's head/meta function:\n * export const head = () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * });\n * ```\n */\nexport function getRegisteredCss(): string {\n return allRules.join('\\n');\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n insertedRules.clear();\n pendingRules = [];\n allRules.length = 0;\n flushScheduled = false;\n ssrBuffer = null;\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n}\n\n/**\n * Flush all pending rules synchronously. Used for SSR and testing.\n */\nexport function flushSync(): void {\n flush();\n}\n\n/**\n * Invalidate all dedup keys that start with the given prefix.\n * Also removes matching rules from the live stylesheet.\n * Used for HMR — allows modules to re-register their styles after editing.\n */\nexport function invalidatePrefix(prefix: string): void {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n if (ruleMatchesPrefix(rule, prefix)) {\n sheet.deleteRule(i);\n }\n }\n}\n\n/**\n * Invalidate a list of exact keys or prefixes.\n * Each entry in `keys` is treated as an exact key match.\n * Each entry in `prefixes` is treated as a prefix match.\n * Used for HMR to invalidate all styles from a module at once.\n */\nexport function invalidateKeys(keys: string[], prefixes: string[]): void {\n for (const key of keys) {\n insertedRules.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n const keySet = new Set(keys);\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n let shouldRemove = false;\n\n for (const prefix of prefixes) {\n if (ruleMatchesPrefix(rule, prefix)) {\n shouldRemove = true;\n break;\n }\n }\n\n if (!shouldRemove) {\n // Check exact key matches — for tokens/themes/keyframes,\n // we match based on rule content patterns\n const ruleText = rule.cssText;\n for (const key of keySet) {\n if (ruleMatchesKey(ruleText, key)) {\n shouldRemove = true;\n break;\n }\n }\n }\n\n if (shouldRemove) {\n sheet.deleteRule(i);\n }\n }\n}\n\nfunction ruleMatchesPrefix(rule: CSSRule, prefix: string): boolean {\n if (prefix.startsWith('font-face:')) {\n const family = prefix.slice('font-face:'.length).split(':')[0];\n // CSSFontFaceRule has type 5 and cssText contains @font-face\n if (rule.cssText.includes('@font-face')) {\n return (\n rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`)\n );\n }\n return false;\n }\n if ('selectorText' in rule) {\n return (rule as CSSStyleRule).selectorText.startsWith(prefix);\n }\n if ('name' in rule && prefix.startsWith('keyframes:')) {\n return (rule as CSSKeyframesRule).name === prefix.slice('keyframes:'.length);\n }\n // For at-rules wrapping style rules, check inner rules\n if ('cssRules' in rule) {\n const innerRules = (rule as CSSGroupingRule).cssRules;\n for (let i = 0; i < innerRules.length; i++) {\n if (ruleMatchesPrefix(innerRules[i], prefix)) return true;\n }\n }\n return false;\n}\n\nfunction ruleMatchesKey(cssText: string, key: string): boolean {\n if (key.startsWith('tokens:')) {\n // tokens:color -> :root rule with --color- custom properties\n const namespace = key.slice('tokens:'.length);\n return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`);\n }\n if (key.startsWith('theme:')) {\n // theme:dark -> .theme-dark selector\n const name = key.slice('theme:'.length);\n return cssText.includes(`.theme-${name}`);\n }\n if (key.startsWith('keyframes:')) {\n const name = key.slice('keyframes:'.length);\n return cssText.includes(`@keyframes ${name}`);\n }\n return false;\n}\n"]}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insert multiple CSS rules at once.
|
|
3
|
+
*/
|
|
4
|
+
declare function insertRules(rules: Array<{
|
|
5
|
+
key: string;
|
|
6
|
+
css: string;
|
|
7
|
+
}>): void;
|
|
1
8
|
/**
|
|
2
9
|
* Return all registered CSS as a string.
|
|
3
10
|
*
|
|
@@ -19,6 +26,14 @@
|
|
|
19
26
|
* ```
|
|
20
27
|
*/
|
|
21
28
|
declare function getRegisteredCss(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Reset all state (useful for testing).
|
|
31
|
+
*/
|
|
32
|
+
declare function reset(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Flush all pending rules synchronously. Used for SSR and testing.
|
|
35
|
+
*/
|
|
36
|
+
declare function flushSync(): void;
|
|
22
37
|
/**
|
|
23
38
|
* Invalidate all dedup keys that start with the given prefix.
|
|
24
39
|
* Also removes matching rules from the live stylesheet.
|
|
@@ -33,4 +48,4 @@ declare function invalidatePrefix(prefix: string): void;
|
|
|
33
48
|
*/
|
|
34
49
|
declare function invalidateKeys(keys: string[], prefixes: string[]): void;
|
|
35
50
|
|
|
36
|
-
export {
|
|
51
|
+
export { invalidateKeys as a, invalidatePrefix as b, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r };
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insert multiple CSS rules at once.
|
|
3
|
+
*/
|
|
4
|
+
declare function insertRules(rules: Array<{
|
|
5
|
+
key: string;
|
|
6
|
+
css: string;
|
|
7
|
+
}>): void;
|
|
1
8
|
/**
|
|
2
9
|
* Return all registered CSS as a string.
|
|
3
10
|
*
|
|
@@ -19,6 +26,14 @@
|
|
|
19
26
|
* ```
|
|
20
27
|
*/
|
|
21
28
|
declare function getRegisteredCss(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Reset all state (useful for testing).
|
|
31
|
+
*/
|
|
32
|
+
declare function reset(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Flush all pending rules synchronously. Used for SSR and testing.
|
|
35
|
+
*/
|
|
36
|
+
declare function flushSync(): void;
|
|
22
37
|
/**
|
|
23
38
|
* Invalidate all dedup keys that start with the given prefix.
|
|
24
39
|
* Also removes matching rules from the live stylesheet.
|
|
@@ -33,4 +48,4 @@ declare function invalidatePrefix(prefix: string): void;
|
|
|
33
48
|
*/
|
|
34
49
|
declare function invalidateKeys(keys: string[], prefixes: string[]): void;
|
|
35
50
|
|
|
36
|
-
export {
|
|
51
|
+
export { invalidateKeys as a, invalidatePrefix as b, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r };
|
package/dist/hmr.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a as invalidateKeys, b as invalidatePrefix } from './hmr-BACAnP4Y.cjs';
|
package/dist/hmr.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a as invalidateKeys, b as invalidatePrefix } from './hmr-BACAnP4Y.js';
|
package/dist/hmr.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -69,9 +69,10 @@ function serializeStyle(selector, properties) {
|
|
|
69
69
|
if (value == null) continue;
|
|
70
70
|
if (prop.startsWith("&")) {
|
|
71
71
|
const nestedSelector = prop.replace(/&/g, selector);
|
|
72
|
-
rules.push(
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
rules.push(...serializeStyle(nestedSelector, value));
|
|
73
|
+
} else if (prop.startsWith("[")) {
|
|
74
|
+
const attrSelector = selector + prop;
|
|
75
|
+
rules.push(...serializeStyle(attrSelector, value));
|
|
75
76
|
} else if (prop.startsWith("@")) {
|
|
76
77
|
const innerRules = serializeStyle(selector, value);
|
|
77
78
|
for (const inner of innerRules) {
|
|
@@ -82,9 +83,7 @@ function serializeStyle(selector, properties) {
|
|
|
82
83
|
}
|
|
83
84
|
} else {
|
|
84
85
|
const kebabProp = toKebabCase(prop);
|
|
85
|
-
declarations.push(
|
|
86
|
-
`${kebabProp}: ${serializeValue(prop, value)}`
|
|
87
|
-
);
|
|
86
|
+
declarations.push(`${kebabProp}: ${serializeValue(prop, value)}`);
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
if (declarations.length > 0) {
|
|
@@ -103,6 +102,7 @@ var pendingRules = [];
|
|
|
103
102
|
var allRules = [];
|
|
104
103
|
var flushScheduled = false;
|
|
105
104
|
var styleElement = null;
|
|
105
|
+
var ssrBuffer = null;
|
|
106
106
|
var isBrowser = typeof document !== "undefined" && typeof window !== "undefined";
|
|
107
107
|
function getStyleElement() {
|
|
108
108
|
if (styleElement) return styleElement;
|
|
@@ -123,6 +123,10 @@ function flush() {
|
|
|
123
123
|
if (pendingRules.length === 0) return;
|
|
124
124
|
const rules = pendingRules;
|
|
125
125
|
pendingRules = [];
|
|
126
|
+
if (ssrBuffer) {
|
|
127
|
+
ssrBuffer.push(...rules);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
126
130
|
if (!isBrowser) return;
|
|
127
131
|
const el = getStyleElement();
|
|
128
132
|
const sheet = el.sheet;
|
|
@@ -141,6 +145,10 @@ function flush() {
|
|
|
141
145
|
function scheduleFlush() {
|
|
142
146
|
if (flushScheduled) return;
|
|
143
147
|
flushScheduled = true;
|
|
148
|
+
if (ssrBuffer) {
|
|
149
|
+
flush();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
144
152
|
if (isBrowser) {
|
|
145
153
|
queueMicrotask(flush);
|
|
146
154
|
}
|
|
@@ -166,6 +174,20 @@ function insertRules(rules) {
|
|
|
166
174
|
function getRegisteredCss() {
|
|
167
175
|
return allRules.join("\n");
|
|
168
176
|
}
|
|
177
|
+
function reset() {
|
|
178
|
+
insertedRules.clear();
|
|
179
|
+
pendingRules = [];
|
|
180
|
+
allRules.length = 0;
|
|
181
|
+
flushScheduled = false;
|
|
182
|
+
ssrBuffer = null;
|
|
183
|
+
if (isBrowser && styleElement) {
|
|
184
|
+
styleElement.remove();
|
|
185
|
+
styleElement = null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function flushSync() {
|
|
189
|
+
flush();
|
|
190
|
+
}
|
|
169
191
|
|
|
170
192
|
// src/registry.ts
|
|
171
193
|
var registeredNamespaces = /* @__PURE__ */ new Set();
|
|
@@ -193,6 +215,21 @@ function createStyles(namespace, definitions) {
|
|
|
193
215
|
};
|
|
194
216
|
return selectorFn;
|
|
195
217
|
}
|
|
218
|
+
function compose(...selectors) {
|
|
219
|
+
const validSelectors = selectors.filter(Boolean);
|
|
220
|
+
return (...args) => {
|
|
221
|
+
const classNames = [];
|
|
222
|
+
for (const selector of validSelectors) {
|
|
223
|
+
if (typeof selector === "string") {
|
|
224
|
+
classNames.push(selector);
|
|
225
|
+
} else {
|
|
226
|
+
const result = selector(...args);
|
|
227
|
+
if (result) classNames.push(result);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return classNames.join(" ");
|
|
231
|
+
};
|
|
232
|
+
}
|
|
196
233
|
|
|
197
234
|
// src/tokens.ts
|
|
198
235
|
var registeredNamespaces2 = /* @__PURE__ */ new Set();
|
|
@@ -378,10 +415,27 @@ function globalFontFace(family, props) {
|
|
|
378
415
|
insertRule(`font-face:${family}:${props.src}`, css);
|
|
379
416
|
}
|
|
380
417
|
|
|
418
|
+
// src/vars.ts
|
|
419
|
+
var counter = 0;
|
|
420
|
+
function createVar() {
|
|
421
|
+
const name = `--ts-${++counter}`;
|
|
422
|
+
return `var(${name})`;
|
|
423
|
+
}
|
|
424
|
+
function assignVars(vars) {
|
|
425
|
+
const result = {};
|
|
426
|
+
for (const [varRef, value] of Object.entries(vars)) {
|
|
427
|
+
if (value == null) continue;
|
|
428
|
+
const match = varRef.match(/^var\((--[^)]+)\)$/);
|
|
429
|
+
if (match) result[match[1]] = value;
|
|
430
|
+
}
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
|
|
381
434
|
// src/index.ts
|
|
382
435
|
var styles = {
|
|
383
436
|
create: createStyles,
|
|
384
|
-
component: createComponent
|
|
437
|
+
component: createComponent,
|
|
438
|
+
compose
|
|
385
439
|
};
|
|
386
440
|
var global = {
|
|
387
441
|
style: globalStyle,
|
|
@@ -397,10 +451,15 @@ var keyframes = {
|
|
|
397
451
|
};
|
|
398
452
|
var color = color_exports;
|
|
399
453
|
|
|
454
|
+
exports.assignVars = assignVars;
|
|
400
455
|
exports.color = color;
|
|
456
|
+
exports.createVar = createVar;
|
|
457
|
+
exports.flushSync = flushSync;
|
|
401
458
|
exports.getRegisteredCss = getRegisteredCss;
|
|
402
459
|
exports.global = global;
|
|
460
|
+
exports.insertRules = insertRules;
|
|
403
461
|
exports.keyframes = keyframes;
|
|
462
|
+
exports.reset = reset;
|
|
404
463
|
exports.styles = styles;
|
|
405
464
|
exports.tokens = tokens;
|
|
406
465
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/css.ts","../src/sheet.ts","../src/registry.ts","../src/styles.ts","../src/tokens.ts","../src/keyframes.ts","../src/color.ts","../src/component.ts","../src/global.ts","../src/index.ts"],"names":["registeredNamespaces","alpha"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { CSSProperties } from './types.js';\n\n/**\n * Convert a camelCase CSS property name to kebab-case.\n * Handles vendor prefixes (ms, webkit, moz) correctly.\n */\nexport function toKebabCase(prop: string): string {\n // Handle ms- prefix specially (no leading dash in camelCase)\n if (prop.startsWith('ms')) {\n return '-' + prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n }\n return prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n}\n\n/**\n * Serialize a single CSS value. Numbers are treated as px for most properties.\n */\nfunction serializeValue(prop: string, value: string | number): string {\n if (typeof value === 'number') {\n if (value === 0) return '0';\n // Unitless properties that shouldn't get 'px'\n if (unitlessProperties.has(prop)) return String(value);\n return value + 'px';\n }\n return value;\n}\n\nconst unitlessProperties = new Set([\n 'animationIterationCount',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'flex',\n 'flexGrow',\n 'flexPositive',\n 'flexShrink',\n 'flexNegative',\n 'flexOrder',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnSpan',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowSpan',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n 'fillOpacity',\n 'floodOpacity',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n]);\n\n/**\n * Represents a generated CSS rule.\n */\nexport interface CSSRule {\n /** Unique key for deduplication */\n key: string;\n /** The CSS rule string */\n css: string;\n}\n\n/**\n * Serialize a style definition object into CSS rule(s) for a given selector.\n */\nexport function serializeStyle(\n selector: string,\n properties: CSSProperties\n): CSSRule[] {\n const rules: CSSRule[] = [];\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n\n if (prop.startsWith('&')) {\n // Nested selector: replace & with the parent selector\n const nestedSelector = prop.replace(/&/g, selector);\n rules.push(\n ...serializeStyle(nestedSelector, value as CSSProperties)\n );\n } else if (prop.startsWith('@')) {\n // At-rule: wrap the serialized content in the at-rule\n const innerRules = serializeStyle(selector, value as CSSProperties);\n for (const inner of innerRules) {\n rules.push({\n key: `${prop}:${inner.key}`,\n css: `${prop} { ${inner.css} }`,\n });\n }\n } else {\n // Regular CSS property\n const kebabProp = toKebabCase(prop);\n declarations.push(\n `${kebabProp}: ${serializeValue(prop, value as string | number)}`\n );\n }\n }\n\n // Add the base rule with all plain declarations\n if (declarations.length > 0) {\n rules.unshift({\n key: selector,\n css: `${selector} { ${declarations.join('; ')}; }`,\n });\n }\n\n return rules;\n}\n","const STYLE_ELEMENT_ID = 'typestyles';\n\n/**\n * Tracks which CSS rules have been inserted to avoid duplicates.\n */\nconst insertedRules = new Set<string>();\n\n/**\n * Buffer of CSS rules waiting to be flushed.\n */\nlet pendingRules: string[] = [];\n\n/**\n * All CSS rules ever registered (for SSR extraction).\n * Unlike pendingRules (which is cleared on flush), this retains every rule\n * so getRegisteredCss() can return the full stylesheet at any point.\n */\nconst allRules: string[] = [];\n\n/**\n * Whether a flush is scheduled.\n */\nlet flushScheduled = false;\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * When in SSR collection mode, CSS is captured here instead of injected.\n */\nlet ssrBuffer: string[] | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\nfunction getStyleElement(): HTMLStyleElement {\n if (styleElement) return styleElement;\n\n // Check for an existing element (e.g., from SSR)\n const existing = document.getElementById(\n STYLE_ELEMENT_ID\n ) as HTMLStyleElement | null;\n if (existing) {\n styleElement = existing;\n return styleElement;\n }\n\n // Create a new one\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n return styleElement;\n}\n\nfunction flush(): void {\n flushScheduled = false;\n if (pendingRules.length === 0) return;\n\n const rules = pendingRules;\n pendingRules = [];\n\n if (ssrBuffer) {\n ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n\n if (sheet) {\n for (const rule of rules) {\n try {\n sheet.insertRule(rule, sheet.cssRules.length);\n } catch {\n // Fallback: append as text (handles edge cases with certain selectors)\n el.appendChild(document.createTextNode(rule));\n }\n }\n } else {\n // Sheet not available yet, append as text\n el.appendChild(document.createTextNode(rules.join('\\n')));\n }\n}\n\nfunction scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n\n if (ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n scheduleFlush();\n}\n\n/**\n * Insert multiple CSS rules at once.\n */\nexport function insertRules(rules: Array<{ key: string; css: string }>): void {\n let added = false;\n for (const { key, css } of rules) {\n if (insertedRules.has(key)) continue;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n added = true;\n }\n if (added) scheduleFlush();\n}\n\n/**\n * Replace a CSS rule (used for HMR). Removes the old rule and inserts the new one.\n */\nexport function replaceRule(key: string, css: string): void {\n if (!isBrowser) return;\n\n insertedRules.delete(key);\n\n // Remove existing rule from the sheet if possible\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n // We can't reliably match by key in CSSOM, so for HMR we fall back to\n // clearing and re-inserting. This is fine since HMR is dev-only.\n }\n }\n\n insertRule(key, css);\n}\n\n/**\n * Start collecting CSS for SSR. Returns a function to stop collection and get the CSS.\n */\nexport function startCollection(): () => string {\n ssrBuffer = [];\n return () => {\n const css = ssrBuffer ? ssrBuffer.join('\\n') : '';\n ssrBuffer = null;\n return css;\n };\n}\n\n/**\n * Return all registered CSS as a string.\n *\n * Unlike `collectStyles`, this doesn't require wrapping a render function.\n * It simply returns every CSS rule that has been registered via\n * `styles.create`, `tokens.create`, `keyframes.create`, etc.\n *\n * Ideal for SSR frameworks that need the CSS separately from the render\n * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links).\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles/server';\n *\n * // In a route's head/meta function:\n * export const head = () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * });\n * ```\n */\nexport function getRegisteredCss(): string {\n return allRules.join('\\n');\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n insertedRules.clear();\n pendingRules = [];\n allRules.length = 0;\n flushScheduled = false;\n ssrBuffer = null;\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n}\n\n/**\n * Flush all pending rules synchronously. Used for SSR and testing.\n */\nexport function flushSync(): void {\n flush();\n}\n\n/**\n * Invalidate all dedup keys that start with the given prefix.\n * Also removes matching rules from the live stylesheet.\n * Used for HMR — allows modules to re-register their styles after editing.\n */\nexport function invalidatePrefix(prefix: string): void {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n if (ruleMatchesPrefix(rule, prefix)) {\n sheet.deleteRule(i);\n }\n }\n}\n\n/**\n * Invalidate a list of exact keys or prefixes.\n * Each entry in `keys` is treated as an exact key match.\n * Each entry in `prefixes` is treated as a prefix match.\n * Used for HMR to invalidate all styles from a module at once.\n */\nexport function invalidateKeys(keys: string[], prefixes: string[]): void {\n for (const key of keys) {\n insertedRules.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n const keySet = new Set(keys);\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n let shouldRemove = false;\n\n for (const prefix of prefixes) {\n if (ruleMatchesPrefix(rule, prefix)) {\n shouldRemove = true;\n break;\n }\n }\n\n if (!shouldRemove) {\n // Check exact key matches — for tokens/themes/keyframes,\n // we match based on rule content patterns\n const ruleText = rule.cssText;\n for (const key of keySet) {\n if (ruleMatchesKey(ruleText, key)) {\n shouldRemove = true;\n break;\n }\n }\n }\n\n if (shouldRemove) {\n sheet.deleteRule(i);\n }\n }\n}\n\nfunction ruleMatchesPrefix(rule: CSSRule, prefix: string): boolean {\n if (prefix.startsWith('font-face:')) {\n const family = prefix.slice('font-face:'.length).split(':')[0];\n // CSSFontFaceRule has type 5 and cssText contains @font-face\n if (rule.cssText.includes('@font-face')) {\n return (\n rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`)\n );\n }\n return false;\n }\n if ('selectorText' in rule) {\n return (rule as CSSStyleRule).selectorText.startsWith(prefix);\n }\n if ('name' in rule && prefix.startsWith('keyframes:')) {\n return (rule as CSSKeyframesRule).name === prefix.slice('keyframes:'.length);\n }\n // For at-rules wrapping style rules, check inner rules\n if ('cssRules' in rule) {\n const innerRules = (rule as CSSGroupingRule).cssRules;\n for (let i = 0; i < innerRules.length; i++) {\n if (ruleMatchesPrefix(innerRules[i], prefix)) return true;\n }\n }\n return false;\n}\n\nfunction ruleMatchesKey(cssText: string, key: string): boolean {\n if (key.startsWith('tokens:')) {\n // tokens:color -> :root rule with --color- custom properties\n const namespace = key.slice('tokens:'.length);\n return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`);\n }\n if (key.startsWith('theme:')) {\n // theme:dark -> .theme-dark selector\n const name = key.slice('theme:'.length);\n return cssText.includes(`.theme-${name}`);\n }\n if (key.startsWith('keyframes:')) {\n const name = key.slice('keyframes:'.length);\n return cssText.includes(`@keyframes ${name}`);\n }\n return false;\n}\n","/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n","import type { CSSProperties, SelectorFunction, StyleDefinitions } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a style group and return a selector function.\n *\n * The selector function accepts variant names and returns a composed\n * class name string. Class names are deterministic and human-readable:\n * `{namespace}-{variant}`.\n *\n * @example\n * ```ts\n * const button = createStyles('button', {\n * base: { padding: '8px 16px', fontSize: '14px' },\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * large: { padding: '12px 24px', fontSize: '16px' },\n * });\n *\n * button('base', 'primary') // \"button-base button-primary\"\n * button('base', isLarge && 'large') // conditional application\n * ```\n */\nexport function createStyles<K extends string>(\n namespace: string,\n definitions: StyleDefinitions & Record<K, CSSProperties>\n): SelectorFunction<K> {\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.create('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n // Generate and inject CSS for all variants\n const rules: Array<{ key: string; css: string }> = [];\n\n for (const [variant, properties] of Object.entries(definitions)) {\n const className = `${namespace}-${variant}`;\n const selector = `.${className}`;\n const variantRules = serializeStyle(selector, properties as CSSProperties);\n rules.push(...variantRules);\n }\n\n insertRules(rules);\n\n // Return the selector function\n const selectorFn = (...variants: (K | false | null | undefined)[]): string => {\n return variants\n .filter(Boolean)\n .map((v) => `${namespace}-${v as string}`)\n .join(' ');\n };\n\n return selectorFn as SelectorFunction<K>;\n}\n","import type { TokenValues, TokenRef, ThemeOverrides } from './types.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * Registry tracking which token namespaces have been created,\n * so tokens.use() can provide warnings in development.\n */\nconst registeredNamespaces = new Set<string>();\n\n/**\n * Create a proxy-based token reference for a namespace.\n * Property access returns var(--{namespace}-{key}).\n */\nfunction createTokenProxy<T extends TokenValues>(namespace: string): TokenRef<T> {\n return new Proxy({} as TokenRef<T>, {\n get(_target, prop: string) {\n return `var(--${namespace}-${prop})`;\n },\n });\n}\n\n/**\n * Create design tokens as CSS custom properties.\n *\n * Generates a :root rule with the custom properties and returns\n * a typed object where property access yields var() references.\n *\n * @example\n * ```ts\n * const color = createTokens('color', {\n * primary: '#0066ff',\n * secondary: '#6b7280',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function createTokens<T extends TokenValues>(\n namespace: string,\n values: T\n): TokenRef<T> {\n registeredNamespaces.add(namespace);\n\n // Generate CSS custom property declarations\n const declarations = Object.entries(values)\n .map(([key, value]) => `--${namespace}-${key}: ${value}`)\n .join('; ');\n\n const css = `:root { ${declarations}; }`;\n insertRule(`tokens:${namespace}`, css);\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Reference tokens defined elsewhere without injecting CSS.\n *\n * Returns a typed proxy that produces var() references.\n * Useful for consuming shared tokens from a different module.\n *\n * @example\n * ```ts\n * const color = useTokens('color');\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function useTokens<T extends TokenValues = TokenValues>(\n namespace: string\n): TokenRef<T> {\n if (\n process.env.NODE_ENV !== 'production' &&\n registeredNamespaces.size > 0 &&\n !registeredNamespaces.has(namespace)\n ) {\n console.warn(\n `[typestyles] tokens.use('${namespace}') references a namespace that hasn't been created yet. ` +\n `Make sure tokens.create('${namespace}', ...) is called before using these tokens.`\n );\n }\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Create a theme class that overrides token values.\n *\n * Returns a class name string. Apply it to any element to override\n * token values for that subtree via CSS custom property cascading.\n *\n * @example\n * ```ts\n * const dark = createTheme('dark', {\n * color: { primary: '#66b3ff', surface: '#1a1a2e' },\n * });\n *\n * <div className={dark}> // class=\"theme-dark\"\n * ```\n */\nexport function createTheme(name: string, overrides: ThemeOverrides): string {\n const className = `theme-${name}`;\n\n const declarations: string[] = [];\n for (const [namespace, values] of Object.entries(overrides)) {\n for (const [key, value] of Object.entries(values)) {\n if (value != null) {\n declarations.push(`--${namespace}-${key}: ${value}`);\n }\n }\n }\n\n const css = `.${className} { ${declarations.join('; ')}; }`;\n insertRule(`theme:${name}`, css);\n\n return className;\n}\n","import type { CSSProperties } from './types.js';\nimport { toKebabCase } from './css.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * A keyframe stop is either 'from', 'to', or a percentage like '50%'.\n */\nexport type KeyframeStops = Record<string, CSSProperties>;\n\n/**\n * Serialize CSS declarations for a single keyframe stop (no nesting/at-rules).\n */\nfunction serializeDeclarations(properties: CSSProperties): string {\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n // Keyframe stops only contain plain properties — skip nested selectors/at-rules\n if (prop.startsWith('&') || prop.startsWith('@')) continue;\n\n const kebabProp = toKebabCase(prop);\n const serialized =\n typeof value === 'number' ? (value === 0 ? '0' : value + 'px') : value;\n declarations.push(`${kebabProp}: ${serialized}`);\n }\n\n return declarations.join('; ');\n}\n\n/**\n * Create a CSS @keyframes animation and return its name.\n *\n * The returned string is the animation name — use it directly in\n * `animation` shorthand or `animationName`.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n *\n * @example\n * ```ts\n * const bounce = keyframes.create('bounce', {\n * '0%': { transform: 'translateY(0)' },\n * '50%': { transform: 'translateY(-20px)' },\n * '100%': { transform: 'translateY(0)' },\n * });\n * ```\n */\nexport function createKeyframes(name: string, stops: KeyframeStops): string {\n const stopsCSS = Object.entries(stops)\n .map(([stop, properties]) => {\n const decls = serializeDeclarations(properties as CSSProperties);\n return `${stop} { ${decls}; }`;\n })\n .join(' ');\n\n const css = `@keyframes ${name} { ${stopsCSS} }`;\n insertRule(`keyframes:${name}`, css);\n\n return name;\n}\n","/**\n * Type-safe helpers for CSS color functions.\n *\n * Each function returns a plain CSS string — no runtime color math.\n * Works naturally with token references since tokens are strings too.\n */\n\ntype ColorValue = string | number;\n\n/** Color spaces supported by color-mix(). */\nexport type ColorMixSpace =\n | 'srgb'\n | 'srgb-linear'\n | 'display-p3'\n | 'a98-rgb'\n | 'prophoto-rgb'\n | 'rec2020'\n | 'lab'\n | 'oklab'\n | 'xyz'\n | 'xyz-d50'\n | 'xyz-d65'\n | 'hsl'\n | 'hwb'\n | 'lch'\n | 'oklch';\n\n/**\n * `rgb(r g b)` or `rgb(r g b / a)`\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.rgb(0, 102, 255, 0.5) // \"rgb(0 102 255 / 0.5)\"\n * ```\n */\nexport function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `rgb(${r} ${g} ${b} / ${alpha})`;\n return `rgb(${r} ${g} ${b})`;\n}\n\n/**\n * `hsl(h s l)` or `hsl(h s l / a)`\n *\n * @example\n * ```ts\n * color.hsl(220, '100%', '50%') // \"hsl(220 100% 50%)\"\n * color.hsl(220, '100%', '50%', 0.8) // \"hsl(220 100% 50% / 0.8)\"\n * ```\n */\nexport function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hsl(${h} ${s} ${l} / ${alpha})`;\n return `hsl(${h} ${s} ${l})`;\n}\n\n/**\n * `oklch(L C h)` or `oklch(L C h / a)`\n *\n * @example\n * ```ts\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.oklch(0.7, 0.15, 250, 0.5) // \"oklch(0.7 0.15 250 / 0.5)\"\n * ```\n */\nexport function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklch(${l} ${c} ${h} / ${alpha})`;\n return `oklch(${l} ${c} ${h})`;\n}\n\n/**\n * `oklab(L a b)` or `oklab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.oklab(0.7, -0.1, -0.1) // \"oklab(0.7 -0.1 -0.1)\"\n * color.oklab(0.7, -0.1, -0.1, 0.5) // \"oklab(0.7 -0.1 -0.1 / 0.5)\"\n * ```\n */\nexport function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklab(${l} ${a} ${b} / ${alpha})`;\n return `oklab(${l} ${a} ${b})`;\n}\n\n/**\n * `lab(L a b)` or `lab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.lab('50%', 40, -20) // \"lab(50% 40 -20)\"\n * ```\n */\nexport function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lab(${l} ${a} ${b} / ${alpha})`;\n return `lab(${l} ${a} ${b})`;\n}\n\n/**\n * `lch(L C h)` or `lch(L C h / alpha)`\n *\n * @example\n * ```ts\n * color.lch('50%', 80, 250) // \"lch(50% 80 250)\"\n * ```\n */\nexport function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lch(${l} ${c} ${h} / ${alpha})`;\n return `lch(${l} ${c} ${h})`;\n}\n\n/**\n * `hwb(h w b)` or `hwb(h w b / alpha)`\n *\n * @example\n * ```ts\n * color.hwb(220, '10%', '0%') // \"hwb(220 10% 0%)\"\n * ```\n */\nexport function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hwb(${h} ${w} ${b} / ${alpha})`;\n return `hwb(${h} ${w} ${b})`;\n}\n\n/**\n * `color-mix(in colorspace, color1 p1%, color2 p2%)`\n *\n * Mixes two colors in the given color space. Percentages are optional.\n *\n * @example\n * ```ts\n * color.mix('red', 'blue') // \"color-mix(in srgb, red, blue)\"\n * color.mix('red', 'blue', 30) // \"color-mix(in srgb, red 30%, blue)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.mix('red', 'blue', 50, 'oklch') // \"color-mix(in oklch, red 50%, blue)\"\n * ```\n */\nexport function mix(\n color1: string,\n color2: string,\n percentage?: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const c1 = percentage != null ? `${color1} ${percentage}%` : color1;\n return `color-mix(in ${colorSpace}, ${c1}, ${color2})`;\n}\n\n/**\n * `light-dark(lightColor, darkColor)`\n *\n * Uses the `light-dark()` CSS function that resolves based on\n * the computed `color-scheme` of the element.\n *\n * @example\n * ```ts\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * color.lightDark(theme.textLight, theme.textDark) // \"light-dark(var(--theme-textLight), var(--theme-textDark))\"\n * ```\n */\nexport function lightDark(lightColor: string, darkColor: string): string {\n return `light-dark(${lightColor}, ${darkColor})`;\n}\n\n/**\n * Adjust the alpha/opacity of any color using `color-mix()`.\n *\n * This is a common pattern: mixing a color with transparent to change opacity.\n * Works with any color value including token references.\n *\n * @example\n * ```ts\n * color.alpha('red', 0.5) // \"color-mix(in srgb, red 50%, transparent)\"\n * color.alpha(theme.primary, 0.2) // \"color-mix(in srgb, var(--theme-primary) 20%, transparent)\"\n * color.alpha('#0066ff', 0.8, 'oklch') // \"color-mix(in oklch, #0066ff 80%, transparent)\"\n * ```\n */\nexport function alpha(\n colorValue: string,\n opacity: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const percentage = Math.round(opacity * 100);\n return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`;\n}\n","import type { CSSProperties, VariantDefinitions, ComponentConfig, ComponentFunction } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a multi-variant component style and return a selector function.\n *\n * Class naming convention:\n * base → `{namespace}-base`\n * variants.intent.primary → `{namespace}-intent-primary`\n * compoundVariants[0] → `{namespace}-compound-0`\n *\n * @example\n * ```ts\n * const button = styles.component('button', {\n * base: { padding: '8px 16px' },\n * variants: {\n * intent: {\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * ghost: { backgroundColor: 'transparent', border: '1px solid currentColor' },\n * },\n * size: {\n * sm: { fontSize: '12px' },\n * lg: { fontSize: '18px' },\n * },\n * },\n * compoundVariants: [\n * { variants: { intent: 'primary', size: 'lg' }, style: { fontWeight: 700 } },\n * ],\n * defaultVariants: { intent: 'primary', size: 'sm' },\n * });\n *\n * button() // \"button-base button-intent-primary button-size-sm\"\n * button({ intent: 'ghost' }) // \"button-base button-intent-ghost button-size-sm\"\n * button({ intent: 'primary', size: 'lg' }) // includes compound class\n * ```\n */\nexport function createComponent<V extends VariantDefinitions>(\n namespace: string,\n config: ComponentConfig<V>\n): ComponentFunction<V> {\n const { base, variants = {} as V, compoundVariants = [], defaultVariants = {} } = config;\n\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.component('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n const rules: Array<{ key: string; css: string }> = [];\n\n // 1. Inject CSS for base\n if (base) {\n rules.push(...serializeStyle(`.${namespace}-base`, base));\n }\n\n // 2. Inject CSS for each variant option\n for (const [dimension, options] of Object.entries(variants)) {\n for (const [option, properties] of Object.entries(options as Record<string, CSSProperties>)) {\n const className = `.${namespace}-${dimension}-${option}`;\n rules.push(...serializeStyle(className, properties));\n }\n }\n\n // 3. Inject CSS for each compound variant\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const className = `.${namespace}-compound-${index}`;\n rules.push(...serializeStyle(className, cv.style));\n }\n );\n\n insertRules(rules);\n\n // 4. Return the selector function\n return ((selections: Record<string, unknown> = {}) => {\n const classes: string[] = [];\n\n if (base) classes.push(`${namespace}-base`);\n\n // Resolve final selections (explicit overrides defaultVariants)\n const resolvedSelections: Record<string, unknown> = {};\n for (const dimension of Object.keys(variants)) {\n resolvedSelections[dimension] =\n selections[dimension] ?? (defaultVariants as Record<string, unknown>)[dimension];\n }\n\n // Apply variant classes\n for (const dimension of Object.keys(variants)) {\n const selected = resolvedSelections[dimension];\n if (selected != null && selected !== false) {\n classes.push(`${namespace}-${dimension}-${String(selected)}`);\n }\n }\n\n // Apply compound variant classes\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const matches = Object.entries(cv.variants).every(\n ([k, v]) => resolvedSelections[k] === v\n );\n if (matches) classes.push(`${namespace}-compound-${index}`);\n }\n );\n\n return classes.join(' ');\n }) as ComponentFunction<V>;\n}\n","import type { CSSProperties, FontFaceProps } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRule, insertRules } from './sheet.js';\n\n/**\n * Apply styles to an arbitrary CSS selector.\n *\n * Use for CSS resets, body/root defaults, third-party elements, or any\n * selector that isn't tied to a specific component class.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0, fontFamily: 'sans-serif' });\n * global.style('a:hover', { textDecoration: 'underline' });\n * global.style('*, *::before, *::after', { boxSizing: 'border-box' });\n * ```\n */\nexport function globalStyle(selector: string, properties: CSSProperties): void {\n const rules = serializeStyle(selector, properties);\n insertRules(rules);\n}\n\n/**\n * Declare a `@font-face` rule to load a custom font.\n *\n * Multiple weights/styles of the same family can be registered by calling\n * this function multiple times with different `src` values — each call is\n * deduplicated by `family + src`.\n *\n * @example\n * ```ts\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Regular.woff2') format('woff2')\",\n * fontWeight: 400,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n *\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Bold.woff2') format('woff2')\",\n * fontWeight: 700,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n * ```\n */\nexport function globalFontFace(family: string, props: FontFaceProps): void {\n const decls: string[] = [`font-family: \"${family}\"`, `src: ${props.src}`];\n if (props.fontWeight != null) decls.push(`font-weight: ${props.fontWeight}`);\n if (props.fontStyle) decls.push(`font-style: ${props.fontStyle}`);\n if (props.fontDisplay) decls.push(`font-display: ${props.fontDisplay}`);\n if (props.fontStretch) decls.push(`font-stretch: ${props.fontStretch}`);\n if (props.unicodeRange) decls.push(`unicode-range: ${props.unicodeRange}`);\n const css = `@font-face { ${decls.join('; ')}; }`;\n // Key includes src for uniqueness (multiple weights per family)\n insertRule(`font-face:${family}:${props.src}`, css);\n}\n","import { createStyles } from './styles.js';\nimport { createTokens, useTokens, createTheme } from './tokens.js';\nimport { createKeyframes } from './keyframes.js';\nimport * as colorFns from './color.js';\nimport { getRegisteredCss } from './sheet.js';\nimport { createComponent } from './component.js';\nimport { globalStyle, globalFontFace } from './global.js';\n\nexport type {\n CSSProperties,\n CSSValue,\n StyleDefinitions,\n SelectorFunction,\n TokenValues,\n TokenRef,\n ThemeOverrides,\n KeyframeStops,\n VariantDefinitions,\n ComponentConfig,\n ComponentFunction,\n FontFaceProps,\n} from './types.js';\n\nexport type { ColorMixSpace } from './color.js';\n\n/**\n * Style creation API.\n *\n * @example\n * ```ts\n * const button = styles.create('button', {\n * base: { padding: '8px 16px' },\n * primary: { backgroundColor: '#0066ff' },\n * });\n *\n * <button className={button('base', 'primary')}>\n * ```\n */\nexport const styles = {\n create: createStyles,\n component: createComponent,\n} as const;\n\n/**\n * Global CSS API for arbitrary selectors and font-face declarations.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0 });\n * global.fontFace('Inter', { src: \"url('/Inter.woff2') format('woff2')\", fontWeight: 400 });\n * ```\n */\nexport const global = {\n style: globalStyle,\n fontFace: globalFontFace,\n} as const;\n\n/**\n * Design token API using CSS custom properties.\n *\n * @example\n * ```ts\n * const color = tokens.create('color', {\n * primary: '#0066ff',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport const tokens = {\n create: createTokens,\n use: useTokens,\n createTheme,\n} as const;\n\n/**\n * Keyframe animation API.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n */\nexport const keyframes = {\n create: createKeyframes,\n} as const;\n\n/**\n * Type-safe CSS color function helpers.\n *\n * Each function returns a plain CSS color string — no runtime color math.\n * Composes naturally with token references.\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.alpha(theme.primary, 0.5) // \"color-mix(in srgb, var(--theme-primary) 50%, transparent)\"\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * ```\n */\nexport const color = colorFns;\n\n/**\n * Return all registered CSS as a string (for SSR).\n *\n * Returns every CSS rule registered via `styles.create`, `tokens.create`,\n * `keyframes.create`, etc. Use this in your SSR head/meta function to\n * inject styles into the document.\n *\n * This is safe to import on the client — it has no server-specific\n * dependencies and will simply return whatever CSS has been registered.\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles';\n *\n * // In a route's head function (e.g. TanStack Start):\n * export const Route = createRootRoute({\n * head: () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * }),\n * });\n * ```\n */\nexport { getRegisteredCss };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/css.ts","../src/sheet.ts","../src/registry.ts","../src/styles.ts","../src/tokens.ts","../src/keyframes.ts","../src/color.ts","../src/component.ts","../src/global.ts","../src/vars.ts","../src/index.ts"],"names":["registeredNamespaces","alpha"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { CSSProperties } from './types.js';\n\n/**\n * Convert a camelCase CSS property name to kebab-case.\n * Handles vendor prefixes (ms, webkit, moz) correctly.\n */\nexport function toKebabCase(prop: string): string {\n // Handle ms- prefix specially (no leading dash in camelCase)\n if (prop.startsWith('ms')) {\n return '-' + prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n }\n return prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n}\n\n/**\n * Serialize a single CSS value. Numbers are treated as px for most properties.\n */\nfunction serializeValue(prop: string, value: string | number): string {\n if (typeof value === 'number') {\n if (value === 0) return '0';\n // Unitless properties that shouldn't get 'px'\n if (unitlessProperties.has(prop)) return String(value);\n return value + 'px';\n }\n return value;\n}\n\nconst unitlessProperties = new Set([\n 'animationIterationCount',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'flex',\n 'flexGrow',\n 'flexPositive',\n 'flexShrink',\n 'flexNegative',\n 'flexOrder',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnSpan',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowSpan',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n 'fillOpacity',\n 'floodOpacity',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n]);\n\n/**\n * Represents a generated CSS rule.\n */\nexport interface CSSRule {\n /** Unique key for deduplication */\n key: string;\n /** The CSS rule string */\n css: string;\n}\n\n/**\n * Serialize a style definition object into CSS rule(s) for a given selector.\n */\nexport function serializeStyle(selector: string, properties: CSSProperties): CSSRule[] {\n const rules: CSSRule[] = [];\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n\n if (prop.startsWith('&')) {\n // Nested selector: replace & with the parent selector\n const nestedSelector = prop.replace(/&/g, selector);\n rules.push(...serializeStyle(nestedSelector, value as CSSProperties));\n } else if (prop.startsWith('[')) {\n // Attribute selector: combine with parent selector\n const attrSelector = selector + prop;\n rules.push(...serializeStyle(attrSelector, value as CSSProperties));\n } else if (prop.startsWith('@')) {\n // At-rule: wrap the serialized content in the at-rule\n const innerRules = serializeStyle(selector, value as CSSProperties);\n for (const inner of innerRules) {\n rules.push({\n key: `${prop}:${inner.key}`,\n css: `${prop} { ${inner.css} }`,\n });\n }\n } else {\n // Regular CSS property\n const kebabProp = toKebabCase(prop);\n declarations.push(`${kebabProp}: ${serializeValue(prop, value as string | number)}`);\n }\n }\n\n // Add the base rule with all plain declarations\n if (declarations.length > 0) {\n rules.unshift({\n key: selector,\n css: `${selector} { ${declarations.join('; ')}; }`,\n });\n }\n\n return rules;\n}\n","const STYLE_ELEMENT_ID = 'typestyles';\n\n/**\n * Tracks which CSS rules have been inserted to avoid duplicates.\n */\nconst insertedRules = new Set<string>();\n\n/**\n * Buffer of CSS rules waiting to be flushed.\n */\nlet pendingRules: string[] = [];\n\n/**\n * All CSS rules ever registered (for SSR extraction).\n * Unlike pendingRules (which is cleared on flush), this retains every rule\n * so getRegisteredCss() can return the full stylesheet at any point.\n */\nconst allRules: string[] = [];\n\n/**\n * Whether a flush is scheduled.\n */\nlet flushScheduled = false;\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * When in SSR collection mode, CSS is captured here instead of injected.\n */\nlet ssrBuffer: string[] | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\nfunction getStyleElement(): HTMLStyleElement {\n if (styleElement) return styleElement;\n\n // Check for an existing element (e.g., from SSR)\n const existing = document.getElementById(\n STYLE_ELEMENT_ID\n ) as HTMLStyleElement | null;\n if (existing) {\n styleElement = existing;\n return styleElement;\n }\n\n // Create a new one\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n return styleElement;\n}\n\nfunction flush(): void {\n flushScheduled = false;\n if (pendingRules.length === 0) return;\n\n const rules = pendingRules;\n pendingRules = [];\n\n if (ssrBuffer) {\n ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n\n if (sheet) {\n for (const rule of rules) {\n try {\n sheet.insertRule(rule, sheet.cssRules.length);\n } catch {\n // Fallback: append as text (handles edge cases with certain selectors)\n el.appendChild(document.createTextNode(rule));\n }\n }\n } else {\n // Sheet not available yet, append as text\n el.appendChild(document.createTextNode(rules.join('\\n')));\n }\n}\n\nfunction scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n\n if (ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n scheduleFlush();\n}\n\n/**\n * Insert multiple CSS rules at once.\n */\nexport function insertRules(rules: Array<{ key: string; css: string }>): void {\n let added = false;\n for (const { key, css } of rules) {\n if (insertedRules.has(key)) continue;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n added = true;\n }\n if (added) scheduleFlush();\n}\n\n/**\n * Replace a CSS rule (used for HMR). Removes the old rule and inserts the new one.\n */\nexport function replaceRule(key: string, css: string): void {\n if (!isBrowser) return;\n\n insertedRules.delete(key);\n\n // Remove existing rule from the sheet if possible\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n // We can't reliably match by key in CSSOM, so for HMR we fall back to\n // clearing and re-inserting. This is fine since HMR is dev-only.\n }\n }\n\n insertRule(key, css);\n}\n\n/**\n * Start collecting CSS for SSR. Returns a function to stop collection and get the CSS.\n */\nexport function startCollection(): () => string {\n ssrBuffer = [];\n return () => {\n const css = ssrBuffer ? ssrBuffer.join('\\n') : '';\n ssrBuffer = null;\n return css;\n };\n}\n\n/**\n * Return all registered CSS as a string.\n *\n * Unlike `collectStyles`, this doesn't require wrapping a render function.\n * It simply returns every CSS rule that has been registered via\n * `styles.create`, `tokens.create`, `keyframes.create`, etc.\n *\n * Ideal for SSR frameworks that need the CSS separately from the render\n * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links).\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles/server';\n *\n * // In a route's head/meta function:\n * export const head = () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * });\n * ```\n */\nexport function getRegisteredCss(): string {\n return allRules.join('\\n');\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n insertedRules.clear();\n pendingRules = [];\n allRules.length = 0;\n flushScheduled = false;\n ssrBuffer = null;\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n}\n\n/**\n * Flush all pending rules synchronously. Used for SSR and testing.\n */\nexport function flushSync(): void {\n flush();\n}\n\n/**\n * Invalidate all dedup keys that start with the given prefix.\n * Also removes matching rules from the live stylesheet.\n * Used for HMR — allows modules to re-register their styles after editing.\n */\nexport function invalidatePrefix(prefix: string): void {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n if (ruleMatchesPrefix(rule, prefix)) {\n sheet.deleteRule(i);\n }\n }\n}\n\n/**\n * Invalidate a list of exact keys or prefixes.\n * Each entry in `keys` is treated as an exact key match.\n * Each entry in `prefixes` is treated as a prefix match.\n * Used for HMR to invalidate all styles from a module at once.\n */\nexport function invalidateKeys(keys: string[], prefixes: string[]): void {\n for (const key of keys) {\n insertedRules.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n const keySet = new Set(keys);\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n let shouldRemove = false;\n\n for (const prefix of prefixes) {\n if (ruleMatchesPrefix(rule, prefix)) {\n shouldRemove = true;\n break;\n }\n }\n\n if (!shouldRemove) {\n // Check exact key matches — for tokens/themes/keyframes,\n // we match based on rule content patterns\n const ruleText = rule.cssText;\n for (const key of keySet) {\n if (ruleMatchesKey(ruleText, key)) {\n shouldRemove = true;\n break;\n }\n }\n }\n\n if (shouldRemove) {\n sheet.deleteRule(i);\n }\n }\n}\n\nfunction ruleMatchesPrefix(rule: CSSRule, prefix: string): boolean {\n if (prefix.startsWith('font-face:')) {\n const family = prefix.slice('font-face:'.length).split(':')[0];\n // CSSFontFaceRule has type 5 and cssText contains @font-face\n if (rule.cssText.includes('@font-face')) {\n return (\n rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`)\n );\n }\n return false;\n }\n if ('selectorText' in rule) {\n return (rule as CSSStyleRule).selectorText.startsWith(prefix);\n }\n if ('name' in rule && prefix.startsWith('keyframes:')) {\n return (rule as CSSKeyframesRule).name === prefix.slice('keyframes:'.length);\n }\n // For at-rules wrapping style rules, check inner rules\n if ('cssRules' in rule) {\n const innerRules = (rule as CSSGroupingRule).cssRules;\n for (let i = 0; i < innerRules.length; i++) {\n if (ruleMatchesPrefix(innerRules[i], prefix)) return true;\n }\n }\n return false;\n}\n\nfunction ruleMatchesKey(cssText: string, key: string): boolean {\n if (key.startsWith('tokens:')) {\n // tokens:color -> :root rule with --color- custom properties\n const namespace = key.slice('tokens:'.length);\n return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`);\n }\n if (key.startsWith('theme:')) {\n // theme:dark -> .theme-dark selector\n const name = key.slice('theme:'.length);\n return cssText.includes(`.theme-${name}`);\n }\n if (key.startsWith('keyframes:')) {\n const name = key.slice('keyframes:'.length);\n return cssText.includes(`@keyframes ${name}`);\n }\n return false;\n}\n","/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n","import type { CSSProperties, SelectorFunction, StyleDefinitions } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a style group and return a selector function.\n *\n * The selector function accepts variant names and returns a composed\n * class name string. Class names are deterministic and human-readable:\n * `{namespace}-{variant}`.\n *\n * @example\n * ```ts\n * const button = createStyles('button', {\n * base: { padding: '8px 16px', fontSize: '14px' },\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * large: { padding: '12px 24px', fontSize: '16px' },\n * });\n *\n * button('base', 'primary') // \"button-base button-primary\"\n * button('base', isLarge && 'large') // conditional application\n * ```\n */\nexport function createStyles<K extends string>(\n namespace: string,\n definitions: StyleDefinitions & Record<K, CSSProperties>,\n): SelectorFunction<K> {\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.create('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`,\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n // Generate and inject CSS for all variants\n const rules: Array<{ key: string; css: string }> = [];\n\n for (const [variant, properties] of Object.entries(definitions)) {\n const className = `${namespace}-${variant}`;\n const selector = `.${className}`;\n const variantRules = serializeStyle(selector, properties as CSSProperties);\n rules.push(...variantRules);\n }\n\n insertRules(rules);\n\n // Return the selector function\n const selectorFn = (...variants: (K | false | null | undefined)[]): string => {\n return variants\n .filter(Boolean)\n .map((v) => `${namespace}-${v as string}`)\n .join(' ');\n };\n\n return selectorFn as SelectorFunction<K>;\n}\n\n/**\n * Compose multiple selector functions or class strings into one.\n * Returns a new SelectorFunction that calls all inputs and joins results.\n *\n * @example\n * ```ts\n * const base = styles.create('base', { padding: '8px' });\n * const primary = styles.create('primary', { color: 'blue' });\n * const button = styles.compose(base, primary);\n *\n * button('padding', 'color'); // \"base-padding primary-color\"\n * ```\n */\ntype AnySelectorFunction = {\n (...args: unknown[]): string;\n};\n\nexport function compose(\n ...selectors: Array<AnySelectorFunction | string | false | null | undefined>\n): AnySelectorFunction {\n const validSelectors = selectors.filter(Boolean) as Array<AnySelectorFunction | string>;\n\n return (...args: unknown[]): string => {\n const classNames: string[] = [];\n\n for (const selector of validSelectors) {\n if (typeof selector === 'string') {\n classNames.push(selector);\n } else {\n const result = selector(...args);\n if (result) classNames.push(result);\n }\n }\n\n return classNames.join(' ');\n };\n}\n","import type { TokenValues, TokenRef, ThemeOverrides } from './types.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * Registry tracking which token namespaces have been created,\n * so tokens.use() can provide warnings in development.\n */\nconst registeredNamespaces = new Set<string>();\n\n/**\n * Create a proxy-based token reference for a namespace.\n * Property access returns var(--{namespace}-{key}).\n */\nfunction createTokenProxy<T extends TokenValues>(namespace: string): TokenRef<T> {\n return new Proxy({} as TokenRef<T>, {\n get(_target, prop: string) {\n return `var(--${namespace}-${prop})`;\n },\n });\n}\n\n/**\n * Create design tokens as CSS custom properties.\n *\n * Generates a :root rule with the custom properties and returns\n * a typed object where property access yields var() references.\n *\n * @example\n * ```ts\n * const color = createTokens('color', {\n * primary: '#0066ff',\n * secondary: '#6b7280',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function createTokens<T extends TokenValues>(\n namespace: string,\n values: T\n): TokenRef<T> {\n registeredNamespaces.add(namespace);\n\n // Generate CSS custom property declarations\n const declarations = Object.entries(values)\n .map(([key, value]) => `--${namespace}-${key}: ${value}`)\n .join('; ');\n\n const css = `:root { ${declarations}; }`;\n insertRule(`tokens:${namespace}`, css);\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Reference tokens defined elsewhere without injecting CSS.\n *\n * Returns a typed proxy that produces var() references.\n * Useful for consuming shared tokens from a different module.\n *\n * @example\n * ```ts\n * const color = useTokens('color');\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function useTokens<T extends TokenValues = TokenValues>(\n namespace: string\n): TokenRef<T> {\n if (\n process.env.NODE_ENV !== 'production' &&\n registeredNamespaces.size > 0 &&\n !registeredNamespaces.has(namespace)\n ) {\n console.warn(\n `[typestyles] tokens.use('${namespace}') references a namespace that hasn't been created yet. ` +\n `Make sure tokens.create('${namespace}', ...) is called before using these tokens.`\n );\n }\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Create a theme class that overrides token values.\n *\n * Returns a class name string. Apply it to any element to override\n * token values for that subtree via CSS custom property cascading.\n *\n * @example\n * ```ts\n * const dark = createTheme('dark', {\n * color: { primary: '#66b3ff', surface: '#1a1a2e' },\n * });\n *\n * <div className={dark}> // class=\"theme-dark\"\n * ```\n */\nexport function createTheme(name: string, overrides: ThemeOverrides): string {\n const className = `theme-${name}`;\n\n const declarations: string[] = [];\n for (const [namespace, values] of Object.entries(overrides)) {\n for (const [key, value] of Object.entries(values)) {\n if (value != null) {\n declarations.push(`--${namespace}-${key}: ${value}`);\n }\n }\n }\n\n const css = `.${className} { ${declarations.join('; ')}; }`;\n insertRule(`theme:${name}`, css);\n\n return className;\n}\n","import type { CSSProperties } from './types.js';\nimport { toKebabCase } from './css.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * A keyframe stop is either 'from', 'to', or a percentage like '50%'.\n */\nexport type KeyframeStops = Record<string, CSSProperties>;\n\n/**\n * Serialize CSS declarations for a single keyframe stop (no nesting/at-rules).\n */\nfunction serializeDeclarations(properties: CSSProperties): string {\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n // Keyframe stops only contain plain properties — skip nested selectors/at-rules\n if (prop.startsWith('&') || prop.startsWith('@')) continue;\n\n const kebabProp = toKebabCase(prop);\n const serialized =\n typeof value === 'number' ? (value === 0 ? '0' : value + 'px') : value;\n declarations.push(`${kebabProp}: ${serialized}`);\n }\n\n return declarations.join('; ');\n}\n\n/**\n * Create a CSS @keyframes animation and return its name.\n *\n * The returned string is the animation name — use it directly in\n * `animation` shorthand or `animationName`.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n *\n * @example\n * ```ts\n * const bounce = keyframes.create('bounce', {\n * '0%': { transform: 'translateY(0)' },\n * '50%': { transform: 'translateY(-20px)' },\n * '100%': { transform: 'translateY(0)' },\n * });\n * ```\n */\nexport function createKeyframes(name: string, stops: KeyframeStops): string {\n const stopsCSS = Object.entries(stops)\n .map(([stop, properties]) => {\n const decls = serializeDeclarations(properties as CSSProperties);\n return `${stop} { ${decls}; }`;\n })\n .join(' ');\n\n const css = `@keyframes ${name} { ${stopsCSS} }`;\n insertRule(`keyframes:${name}`, css);\n\n return name;\n}\n","/**\n * Type-safe helpers for CSS color functions.\n *\n * Each function returns a plain CSS string — no runtime color math.\n * Works naturally with token references since tokens are strings too.\n */\n\ntype ColorValue = string | number;\n\n/** Color spaces supported by color-mix(). */\nexport type ColorMixSpace =\n | 'srgb'\n | 'srgb-linear'\n | 'display-p3'\n | 'a98-rgb'\n | 'prophoto-rgb'\n | 'rec2020'\n | 'lab'\n | 'oklab'\n | 'xyz'\n | 'xyz-d50'\n | 'xyz-d65'\n | 'hsl'\n | 'hwb'\n | 'lch'\n | 'oklch';\n\n/**\n * `rgb(r g b)` or `rgb(r g b / a)`\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.rgb(0, 102, 255, 0.5) // \"rgb(0 102 255 / 0.5)\"\n * ```\n */\nexport function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `rgb(${r} ${g} ${b} / ${alpha})`;\n return `rgb(${r} ${g} ${b})`;\n}\n\n/**\n * `hsl(h s l)` or `hsl(h s l / a)`\n *\n * @example\n * ```ts\n * color.hsl(220, '100%', '50%') // \"hsl(220 100% 50%)\"\n * color.hsl(220, '100%', '50%', 0.8) // \"hsl(220 100% 50% / 0.8)\"\n * ```\n */\nexport function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hsl(${h} ${s} ${l} / ${alpha})`;\n return `hsl(${h} ${s} ${l})`;\n}\n\n/**\n * `oklch(L C h)` or `oklch(L C h / a)`\n *\n * @example\n * ```ts\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.oklch(0.7, 0.15, 250, 0.5) // \"oklch(0.7 0.15 250 / 0.5)\"\n * ```\n */\nexport function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklch(${l} ${c} ${h} / ${alpha})`;\n return `oklch(${l} ${c} ${h})`;\n}\n\n/**\n * `oklab(L a b)` or `oklab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.oklab(0.7, -0.1, -0.1) // \"oklab(0.7 -0.1 -0.1)\"\n * color.oklab(0.7, -0.1, -0.1, 0.5) // \"oklab(0.7 -0.1 -0.1 / 0.5)\"\n * ```\n */\nexport function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklab(${l} ${a} ${b} / ${alpha})`;\n return `oklab(${l} ${a} ${b})`;\n}\n\n/**\n * `lab(L a b)` or `lab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.lab('50%', 40, -20) // \"lab(50% 40 -20)\"\n * ```\n */\nexport function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lab(${l} ${a} ${b} / ${alpha})`;\n return `lab(${l} ${a} ${b})`;\n}\n\n/**\n * `lch(L C h)` or `lch(L C h / alpha)`\n *\n * @example\n * ```ts\n * color.lch('50%', 80, 250) // \"lch(50% 80 250)\"\n * ```\n */\nexport function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lch(${l} ${c} ${h} / ${alpha})`;\n return `lch(${l} ${c} ${h})`;\n}\n\n/**\n * `hwb(h w b)` or `hwb(h w b / alpha)`\n *\n * @example\n * ```ts\n * color.hwb(220, '10%', '0%') // \"hwb(220 10% 0%)\"\n * ```\n */\nexport function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hwb(${h} ${w} ${b} / ${alpha})`;\n return `hwb(${h} ${w} ${b})`;\n}\n\n/**\n * `color-mix(in colorspace, color1 p1%, color2 p2%)`\n *\n * Mixes two colors in the given color space. Percentages are optional.\n *\n * @example\n * ```ts\n * color.mix('red', 'blue') // \"color-mix(in srgb, red, blue)\"\n * color.mix('red', 'blue', 30) // \"color-mix(in srgb, red 30%, blue)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.mix('red', 'blue', 50, 'oklch') // \"color-mix(in oklch, red 50%, blue)\"\n * ```\n */\nexport function mix(\n color1: string,\n color2: string,\n percentage?: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const c1 = percentage != null ? `${color1} ${percentage}%` : color1;\n return `color-mix(in ${colorSpace}, ${c1}, ${color2})`;\n}\n\n/**\n * `light-dark(lightColor, darkColor)`\n *\n * Uses the `light-dark()` CSS function that resolves based on\n * the computed `color-scheme` of the element.\n *\n * @example\n * ```ts\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * color.lightDark(theme.textLight, theme.textDark) // \"light-dark(var(--theme-textLight), var(--theme-textDark))\"\n * ```\n */\nexport function lightDark(lightColor: string, darkColor: string): string {\n return `light-dark(${lightColor}, ${darkColor})`;\n}\n\n/**\n * Adjust the alpha/opacity of any color using `color-mix()`.\n *\n * This is a common pattern: mixing a color with transparent to change opacity.\n * Works with any color value including token references.\n *\n * @example\n * ```ts\n * color.alpha('red', 0.5) // \"color-mix(in srgb, red 50%, transparent)\"\n * color.alpha(theme.primary, 0.2) // \"color-mix(in srgb, var(--theme-primary) 20%, transparent)\"\n * color.alpha('#0066ff', 0.8, 'oklch') // \"color-mix(in oklch, #0066ff 80%, transparent)\"\n * ```\n */\nexport function alpha(\n colorValue: string,\n opacity: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const percentage = Math.round(opacity * 100);\n return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`;\n}\n","import type { CSSProperties, VariantDefinitions, ComponentConfig, ComponentFunction } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a multi-variant component style and return a selector function.\n *\n * Class naming convention:\n * base → `{namespace}-base`\n * variants.intent.primary → `{namespace}-intent-primary`\n * compoundVariants[0] → `{namespace}-compound-0`\n *\n * @example\n * ```ts\n * const button = styles.component('button', {\n * base: { padding: '8px 16px' },\n * variants: {\n * intent: {\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * ghost: { backgroundColor: 'transparent', border: '1px solid currentColor' },\n * },\n * size: {\n * sm: { fontSize: '12px' },\n * lg: { fontSize: '18px' },\n * },\n * },\n * compoundVariants: [\n * { variants: { intent: 'primary', size: 'lg' }, style: { fontWeight: 700 } },\n * ],\n * defaultVariants: { intent: 'primary', size: 'sm' },\n * });\n *\n * button() // \"button-base button-intent-primary button-size-sm\"\n * button({ intent: 'ghost' }) // \"button-base button-intent-ghost button-size-sm\"\n * button({ intent: 'primary', size: 'lg' }) // includes compound class\n * ```\n */\nexport function createComponent<V extends VariantDefinitions>(\n namespace: string,\n config: ComponentConfig<V>\n): ComponentFunction<V> {\n const { base, variants = {} as V, compoundVariants = [], defaultVariants = {} } = config;\n\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.component('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n const rules: Array<{ key: string; css: string }> = [];\n\n // 1. Inject CSS for base\n if (base) {\n rules.push(...serializeStyle(`.${namespace}-base`, base));\n }\n\n // 2. Inject CSS for each variant option\n for (const [dimension, options] of Object.entries(variants)) {\n for (const [option, properties] of Object.entries(options as Record<string, CSSProperties>)) {\n const className = `.${namespace}-${dimension}-${option}`;\n rules.push(...serializeStyle(className, properties));\n }\n }\n\n // 3. Inject CSS for each compound variant\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const className = `.${namespace}-compound-${index}`;\n rules.push(...serializeStyle(className, cv.style));\n }\n );\n\n insertRules(rules);\n\n // 4. Return the selector function\n return ((selections: Record<string, unknown> = {}) => {\n const classes: string[] = [];\n\n if (base) classes.push(`${namespace}-base`);\n\n // Resolve final selections (explicit overrides defaultVariants)\n const resolvedSelections: Record<string, unknown> = {};\n for (const dimension of Object.keys(variants)) {\n resolvedSelections[dimension] =\n selections[dimension] ?? (defaultVariants as Record<string, unknown>)[dimension];\n }\n\n // Apply variant classes\n for (const dimension of Object.keys(variants)) {\n const selected = resolvedSelections[dimension];\n if (selected != null && selected !== false) {\n classes.push(`${namespace}-${dimension}-${String(selected)}`);\n }\n }\n\n // Apply compound variant classes\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const matches = Object.entries(cv.variants).every(\n ([k, v]) => resolvedSelections[k] === v\n );\n if (matches) classes.push(`${namespace}-compound-${index}`);\n }\n );\n\n return classes.join(' ');\n }) as ComponentFunction<V>;\n}\n","import type { CSSProperties, FontFaceProps } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRule, insertRules } from './sheet.js';\n\n/**\n * Apply styles to an arbitrary CSS selector.\n *\n * Use for CSS resets, body/root defaults, third-party elements, or any\n * selector that isn't tied to a specific component class.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0, fontFamily: 'sans-serif' });\n * global.style('a:hover', { textDecoration: 'underline' });\n * global.style('*, *::before, *::after', { boxSizing: 'border-box' });\n * ```\n */\nexport function globalStyle(selector: string, properties: CSSProperties): void {\n const rules = serializeStyle(selector, properties);\n insertRules(rules);\n}\n\n/**\n * Declare a `@font-face` rule to load a custom font.\n *\n * Multiple weights/styles of the same family can be registered by calling\n * this function multiple times with different `src` values — each call is\n * deduplicated by `family + src`.\n *\n * @example\n * ```ts\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Regular.woff2') format('woff2')\",\n * fontWeight: 400,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n *\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Bold.woff2') format('woff2')\",\n * fontWeight: 700,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n * ```\n */\nexport function globalFontFace(family: string, props: FontFaceProps): void {\n const decls: string[] = [`font-family: \"${family}\"`, `src: ${props.src}`];\n if (props.fontWeight != null) decls.push(`font-weight: ${props.fontWeight}`);\n if (props.fontStyle) decls.push(`font-style: ${props.fontStyle}`);\n if (props.fontDisplay) decls.push(`font-display: ${props.fontDisplay}`);\n if (props.fontStretch) decls.push(`font-stretch: ${props.fontStretch}`);\n if (props.unicodeRange) decls.push(`unicode-range: ${props.unicodeRange}`);\n const css = `@font-face { ${decls.join('; ')}; }`;\n // Key includes src for uniqueness (multiple weights per family)\n insertRule(`font-face:${family}:${props.src}`, css);\n}\n","import type { CSSVarRef } from './types.js';\n\nlet counter = 0;\n\n/** Reset the counter. Used in tests only. */\nexport function __resetVarCounter(): void {\n counter = 0;\n}\n\n/**\n * Create a unique CSS custom property reference.\n *\n * Returns a `var(--ts-N)` string that can be used anywhere a CSS value is\n * accepted. Use assignVars() to set its value per element via inline styles.\n *\n * @example\n * ```ts\n * const cardBg = createVar();\n *\n * const card = styles.create('card', {\n * base: { background: cardBg, padding: '16px' },\n * });\n *\n * // Consumer sets the variable per instance:\n * <div className={card('base')} style={assignVars({ [cardBg]: '#ff0099' })} />\n * ```\n */\nexport function createVar(): CSSVarRef {\n const name = `--ts-${++counter}`;\n return `var(${name})` as CSSVarRef;\n}\n\n/**\n * Build a CSS custom property assignment map from var refs to values.\n *\n * The returned object is safe to spread into a React (or any framework)\n * inline `style` prop.\n *\n * @example\n * ```ts\n * assignVars({ [cardBg]: '#ff0099' })\n * // → { '--ts-1': '#ff0099' }\n * ```\n */\nexport function assignVars(\n vars: Partial<Record<CSSVarRef, string>>\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [varRef, value] of Object.entries(vars)) {\n if (value == null) continue;\n // Strip \"var(\" prefix and \")\" suffix to get the raw property name\n const match = varRef.match(/^var\\((--[^)]+)\\)$/);\n if (match) result[match[1]] = value;\n }\n return result;\n}\n","import { createStyles, compose } from './styles.js';\nimport { createTokens, useTokens, createTheme } from './tokens.js';\nimport { createKeyframes } from './keyframes.js';\nimport * as colorFns from './color.js';\nimport { getRegisteredCss, insertRules, reset, flushSync } from './sheet.js';\nimport { createComponent } from './component.js';\nimport { globalStyle, globalFontFace } from './global.js';\nimport { createVar, assignVars } from './vars.js';\n\nexport type {\n CSSProperties,\n CSSValue,\n StyleDefinitions,\n SelectorFunction,\n TokenValues,\n TokenRef,\n ThemeOverrides,\n KeyframeStops,\n VariantDefinitions,\n ComponentConfig,\n ComponentFunction,\n FontFaceProps,\n CSSVarRef,\n RecipeVariants,\n} from './types.js';\n\nexport { createVar, assignVars };\n\nexport type { ColorMixSpace } from './color.js';\n\n/**\n * Style creation API.\n *\n * @example\n * ```ts\n * const button = styles.create('button', {\n * base: { padding: '8px 16px' },\n * primary: { backgroundColor: '#0066ff' },\n * });\n *\n * <button className={button('base', 'primary')}>\n * ```\n */\nexport const styles = {\n create: createStyles,\n component: createComponent,\n compose,\n} as const;\n\n/**\n * Global CSS API for arbitrary selectors and font-face declarations.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0 });\n * global.fontFace('Inter', { src: \"url('/Inter.woff2') format('woff2')\", fontWeight: 400 });\n * ```\n */\nexport const global = {\n style: globalStyle,\n fontFace: globalFontFace,\n} as const;\n\n/**\n * Design token API using CSS custom properties.\n *\n * @example\n * ```ts\n * const color = tokens.create('color', {\n * primary: '#0066ff',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport const tokens = {\n create: createTokens,\n use: useTokens,\n createTheme,\n} as const;\n\n/**\n * Keyframe animation API.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n */\nexport const keyframes = {\n create: createKeyframes,\n} as const;\n\n/**\n * Type-safe CSS color function helpers.\n *\n * Each function returns a plain CSS color string — no runtime color math.\n * Composes naturally with token references.\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.alpha(theme.primary, 0.5) // \"color-mix(in srgb, var(--theme-primary) 50%, transparent)\"\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * ```\n */\nexport const color = colorFns;\n\n/**\n * Return all registered CSS as a string (for SSR).\n *\n * Returns every CSS rule registered via `styles.create`, `tokens.create`,\n * `keyframes.create`, etc. Use this in your SSR head/meta function to\n * inject styles into the document.\n *\n * This is safe to import on the client — it has no server-specific\n * dependencies and will simply return whatever CSS has been registered.\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles';\n *\n * // In a route's head function (e.g. TanStack Start):\n * export const Route = createRootRoute({\n * head: () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * }),\n * });\n * ```\n */\nexport { getRegisteredCss };\n\n/**\n * Insert multiple CSS rules into the stylesheet.\n *\n * This is a low-level API used internally by typestyles and by packages\n * like @typestyles/props. You typically won't need to use this directly.\n *\n * @example\n * ```ts\n * import { insertRules } from 'typestyles';\n *\n * insertRules([\n * { key: '.my-class', css: '.my-class { color: red; }' },\n * { key: '.another', css: '.another { padding: 8px; }' },\n * ]);\n * ```\n */\nexport { insertRules };\n\n/**\n * Testing utilities for clearing the stylesheet and flushing pending rules.\n * These are primarily intended for use in tests.\n *\n * @example\n * ```ts\n * import { reset, flushSync } from 'typestyles';\n *\n * // In a test beforeEach:\n * beforeEach(() => {\n * reset(); // Clear all registered CSS\n * });\n *\n * // To synchronously flush pending rules:\n * flushSync();\n * ```\n */\nexport { reset, flushSync };\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as CSS from 'csstype';
|
|
2
|
-
export { g as getRegisteredCss } from './hmr-
|
|
2
|
+
export { f as flushSync, g as getRegisteredCss, i as insertRules, r as reset } from './hmr-BACAnP4Y.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A CSS value that can be a standard value or a token reference (var() string).
|
|
@@ -10,8 +10,10 @@ type CSSValue = string | number;
|
|
|
10
10
|
* Extends csstype's Properties with nesting capabilities.
|
|
11
11
|
*/
|
|
12
12
|
interface CSSProperties extends CSS.Properties<CSSValue> {
|
|
13
|
-
/** Nested selector (e.g., '&:hover', '& .child', '&::before') */
|
|
13
|
+
/** Nested selector (e.g., '&:hover', '& .child', '&::before', '&[data-variant]') */
|
|
14
14
|
[selector: `&${string}`]: CSSProperties;
|
|
15
|
+
/** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */
|
|
16
|
+
[attribute: `[${string}`]: CSSProperties;
|
|
15
17
|
/** At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports') */
|
|
16
18
|
[atRule: `@${string}`]: CSSProperties;
|
|
17
19
|
}
|
|
@@ -71,6 +73,31 @@ type ComponentConfig<V extends VariantDefinitions> = {
|
|
|
71
73
|
type ComponentFunction<V extends VariantDefinitions> = (selections?: {
|
|
72
74
|
[K in keyof V]?: keyof V[K] | false | null | undefined;
|
|
73
75
|
}) => string;
|
|
76
|
+
/**
|
|
77
|
+
* A reference to a CSS custom property created by createVar().
|
|
78
|
+
* The string value is `var(--ts-N)` and can be used directly as a CSS value.
|
|
79
|
+
* Template literal type provides type safety without a brand.
|
|
80
|
+
*/
|
|
81
|
+
type CSSVarRef = `var(--${string})`;
|
|
82
|
+
/**
|
|
83
|
+
* Extract the variant prop types from a ComponentFunction.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const button = styles.component('button', {
|
|
88
|
+
* variants: {
|
|
89
|
+
* intent: { primary: {...}, ghost: {...} },
|
|
90
|
+
* size: { sm: {...}, lg: {...} },
|
|
91
|
+
* },
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* type ButtonProps = RecipeVariants<typeof button>;
|
|
95
|
+
* // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' }
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
type RecipeVariants<T> = T extends ComponentFunction<infer V> ? {
|
|
99
|
+
[K in keyof V]?: keyof V[K];
|
|
100
|
+
} : never;
|
|
74
101
|
/**
|
|
75
102
|
* Font face property declarations.
|
|
76
103
|
*/
|
|
@@ -103,6 +130,23 @@ type FontFaceProps = {
|
|
|
103
130
|
* ```
|
|
104
131
|
*/
|
|
105
132
|
declare function createStyles<K extends string>(namespace: string, definitions: StyleDefinitions & Record<K, CSSProperties>): SelectorFunction<K>;
|
|
133
|
+
/**
|
|
134
|
+
* Compose multiple selector functions or class strings into one.
|
|
135
|
+
* Returns a new SelectorFunction that calls all inputs and joins results.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const base = styles.create('base', { padding: '8px' });
|
|
140
|
+
* const primary = styles.create('primary', { color: 'blue' });
|
|
141
|
+
* const button = styles.compose(base, primary);
|
|
142
|
+
*
|
|
143
|
+
* button('padding', 'color'); // "base-padding primary-color"
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
type AnySelectorFunction = {
|
|
147
|
+
(...args: unknown[]): string;
|
|
148
|
+
};
|
|
149
|
+
declare function compose(...selectors: Array<AnySelectorFunction | string | false | null | undefined>): AnySelectorFunction;
|
|
106
150
|
|
|
107
151
|
/**
|
|
108
152
|
* Create design tokens as CSS custom properties.
|
|
@@ -392,6 +436,39 @@ declare function globalStyle(selector: string, properties: CSSProperties): void;
|
|
|
392
436
|
*/
|
|
393
437
|
declare function globalFontFace(family: string, props: FontFaceProps): void;
|
|
394
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Create a unique CSS custom property reference.
|
|
441
|
+
*
|
|
442
|
+
* Returns a `var(--ts-N)` string that can be used anywhere a CSS value is
|
|
443
|
+
* accepted. Use assignVars() to set its value per element via inline styles.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* ```ts
|
|
447
|
+
* const cardBg = createVar();
|
|
448
|
+
*
|
|
449
|
+
* const card = styles.create('card', {
|
|
450
|
+
* base: { background: cardBg, padding: '16px' },
|
|
451
|
+
* });
|
|
452
|
+
*
|
|
453
|
+
* // Consumer sets the variable per instance:
|
|
454
|
+
* <div className={card('base')} style={assignVars({ [cardBg]: '#ff0099' })} />
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
declare function createVar(): CSSVarRef;
|
|
458
|
+
/**
|
|
459
|
+
* Build a CSS custom property assignment map from var refs to values.
|
|
460
|
+
*
|
|
461
|
+
* The returned object is safe to spread into a React (or any framework)
|
|
462
|
+
* inline `style` prop.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* assignVars({ [cardBg]: '#ff0099' })
|
|
467
|
+
* // → { '--ts-1': '#ff0099' }
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
declare function assignVars(vars: Partial<Record<CSSVarRef, string>>): Record<string, string>;
|
|
471
|
+
|
|
395
472
|
/**
|
|
396
473
|
* Style creation API.
|
|
397
474
|
*
|
|
@@ -408,6 +485,7 @@ declare function globalFontFace(family: string, props: FontFaceProps): void;
|
|
|
408
485
|
declare const styles: {
|
|
409
486
|
readonly create: typeof createStyles;
|
|
410
487
|
readonly component: typeof createComponent;
|
|
488
|
+
readonly compose: typeof compose;
|
|
411
489
|
};
|
|
412
490
|
/**
|
|
413
491
|
* Global CSS API for arbitrary selectors and font-face declarations.
|
|
@@ -474,4 +552,4 @@ declare const keyframes: {
|
|
|
474
552
|
*/
|
|
475
553
|
declare const color: typeof colorFns;
|
|
476
554
|
|
|
477
|
-
export { type CSSProperties, type CSSValue, type ColorMixSpace, type ComponentConfig, type ComponentFunction, type FontFaceProps, type KeyframeStops$1 as KeyframeStops, type SelectorFunction, type StyleDefinitions, type ThemeOverrides, type TokenRef, type TokenValues, type VariantDefinitions, color, global, keyframes, styles, tokens };
|
|
555
|
+
export { type CSSProperties, type CSSValue, type CSSVarRef, type ColorMixSpace, type ComponentConfig, type ComponentFunction, type FontFaceProps, type KeyframeStops$1 as KeyframeStops, type RecipeVariants, type SelectorFunction, type StyleDefinitions, type ThemeOverrides, type TokenRef, type TokenValues, type VariantDefinitions, assignVars, color, createVar, global, keyframes, styles, tokens };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as CSS from 'csstype';
|
|
2
|
-
export { g as getRegisteredCss } from './hmr-
|
|
2
|
+
export { f as flushSync, g as getRegisteredCss, i as insertRules, r as reset } from './hmr-BACAnP4Y.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A CSS value that can be a standard value or a token reference (var() string).
|
|
@@ -10,8 +10,10 @@ type CSSValue = string | number;
|
|
|
10
10
|
* Extends csstype's Properties with nesting capabilities.
|
|
11
11
|
*/
|
|
12
12
|
interface CSSProperties extends CSS.Properties<CSSValue> {
|
|
13
|
-
/** Nested selector (e.g., '&:hover', '& .child', '&::before') */
|
|
13
|
+
/** Nested selector (e.g., '&:hover', '& .child', '&::before', '&[data-variant]') */
|
|
14
14
|
[selector: `&${string}`]: CSSProperties;
|
|
15
|
+
/** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */
|
|
16
|
+
[attribute: `[${string}`]: CSSProperties;
|
|
15
17
|
/** At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports') */
|
|
16
18
|
[atRule: `@${string}`]: CSSProperties;
|
|
17
19
|
}
|
|
@@ -71,6 +73,31 @@ type ComponentConfig<V extends VariantDefinitions> = {
|
|
|
71
73
|
type ComponentFunction<V extends VariantDefinitions> = (selections?: {
|
|
72
74
|
[K in keyof V]?: keyof V[K] | false | null | undefined;
|
|
73
75
|
}) => string;
|
|
76
|
+
/**
|
|
77
|
+
* A reference to a CSS custom property created by createVar().
|
|
78
|
+
* The string value is `var(--ts-N)` and can be used directly as a CSS value.
|
|
79
|
+
* Template literal type provides type safety without a brand.
|
|
80
|
+
*/
|
|
81
|
+
type CSSVarRef = `var(--${string})`;
|
|
82
|
+
/**
|
|
83
|
+
* Extract the variant prop types from a ComponentFunction.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const button = styles.component('button', {
|
|
88
|
+
* variants: {
|
|
89
|
+
* intent: { primary: {...}, ghost: {...} },
|
|
90
|
+
* size: { sm: {...}, lg: {...} },
|
|
91
|
+
* },
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* type ButtonProps = RecipeVariants<typeof button>;
|
|
95
|
+
* // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' }
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
type RecipeVariants<T> = T extends ComponentFunction<infer V> ? {
|
|
99
|
+
[K in keyof V]?: keyof V[K];
|
|
100
|
+
} : never;
|
|
74
101
|
/**
|
|
75
102
|
* Font face property declarations.
|
|
76
103
|
*/
|
|
@@ -103,6 +130,23 @@ type FontFaceProps = {
|
|
|
103
130
|
* ```
|
|
104
131
|
*/
|
|
105
132
|
declare function createStyles<K extends string>(namespace: string, definitions: StyleDefinitions & Record<K, CSSProperties>): SelectorFunction<K>;
|
|
133
|
+
/**
|
|
134
|
+
* Compose multiple selector functions or class strings into one.
|
|
135
|
+
* Returns a new SelectorFunction that calls all inputs and joins results.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const base = styles.create('base', { padding: '8px' });
|
|
140
|
+
* const primary = styles.create('primary', { color: 'blue' });
|
|
141
|
+
* const button = styles.compose(base, primary);
|
|
142
|
+
*
|
|
143
|
+
* button('padding', 'color'); // "base-padding primary-color"
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
type AnySelectorFunction = {
|
|
147
|
+
(...args: unknown[]): string;
|
|
148
|
+
};
|
|
149
|
+
declare function compose(...selectors: Array<AnySelectorFunction | string | false | null | undefined>): AnySelectorFunction;
|
|
106
150
|
|
|
107
151
|
/**
|
|
108
152
|
* Create design tokens as CSS custom properties.
|
|
@@ -392,6 +436,39 @@ declare function globalStyle(selector: string, properties: CSSProperties): void;
|
|
|
392
436
|
*/
|
|
393
437
|
declare function globalFontFace(family: string, props: FontFaceProps): void;
|
|
394
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Create a unique CSS custom property reference.
|
|
441
|
+
*
|
|
442
|
+
* Returns a `var(--ts-N)` string that can be used anywhere a CSS value is
|
|
443
|
+
* accepted. Use assignVars() to set its value per element via inline styles.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* ```ts
|
|
447
|
+
* const cardBg = createVar();
|
|
448
|
+
*
|
|
449
|
+
* const card = styles.create('card', {
|
|
450
|
+
* base: { background: cardBg, padding: '16px' },
|
|
451
|
+
* });
|
|
452
|
+
*
|
|
453
|
+
* // Consumer sets the variable per instance:
|
|
454
|
+
* <div className={card('base')} style={assignVars({ [cardBg]: '#ff0099' })} />
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
declare function createVar(): CSSVarRef;
|
|
458
|
+
/**
|
|
459
|
+
* Build a CSS custom property assignment map from var refs to values.
|
|
460
|
+
*
|
|
461
|
+
* The returned object is safe to spread into a React (or any framework)
|
|
462
|
+
* inline `style` prop.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* assignVars({ [cardBg]: '#ff0099' })
|
|
467
|
+
* // → { '--ts-1': '#ff0099' }
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
declare function assignVars(vars: Partial<Record<CSSVarRef, string>>): Record<string, string>;
|
|
471
|
+
|
|
395
472
|
/**
|
|
396
473
|
* Style creation API.
|
|
397
474
|
*
|
|
@@ -408,6 +485,7 @@ declare function globalFontFace(family: string, props: FontFaceProps): void;
|
|
|
408
485
|
declare const styles: {
|
|
409
486
|
readonly create: typeof createStyles;
|
|
410
487
|
readonly component: typeof createComponent;
|
|
488
|
+
readonly compose: typeof compose;
|
|
411
489
|
};
|
|
412
490
|
/**
|
|
413
491
|
* Global CSS API for arbitrary selectors and font-face declarations.
|
|
@@ -474,4 +552,4 @@ declare const keyframes: {
|
|
|
474
552
|
*/
|
|
475
553
|
declare const color: typeof colorFns;
|
|
476
554
|
|
|
477
|
-
export { type CSSProperties, type CSSValue, type ColorMixSpace, type ComponentConfig, type ComponentFunction, type FontFaceProps, type KeyframeStops$1 as KeyframeStops, type SelectorFunction, type StyleDefinitions, type ThemeOverrides, type TokenRef, type TokenValues, type VariantDefinitions, color, global, keyframes, styles, tokens };
|
|
555
|
+
export { type CSSProperties, type CSSValue, type CSSVarRef, type ColorMixSpace, type ComponentConfig, type ComponentFunction, type FontFaceProps, type KeyframeStops$1 as KeyframeStops, type RecipeVariants, type SelectorFunction, type StyleDefinitions, type ThemeOverrides, type TokenRef, type TokenValues, type VariantDefinitions, assignVars, color, createVar, global, keyframes, styles, tokens };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __export, insertRules, insertRule } from './chunk-
|
|
2
|
-
export { getRegisteredCss } from './chunk-
|
|
1
|
+
import { __export, insertRules, insertRule } from './chunk-BB7C47TQ.js';
|
|
2
|
+
export { flushSync, getRegisteredCss, insertRules, reset } from './chunk-BB7C47TQ.js';
|
|
3
3
|
|
|
4
4
|
// src/css.ts
|
|
5
5
|
function toKebabCase(prop) {
|
|
@@ -64,9 +64,10 @@ function serializeStyle(selector, properties) {
|
|
|
64
64
|
if (value == null) continue;
|
|
65
65
|
if (prop.startsWith("&")) {
|
|
66
66
|
const nestedSelector = prop.replace(/&/g, selector);
|
|
67
|
-
rules.push(
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
rules.push(...serializeStyle(nestedSelector, value));
|
|
68
|
+
} else if (prop.startsWith("[")) {
|
|
69
|
+
const attrSelector = selector + prop;
|
|
70
|
+
rules.push(...serializeStyle(attrSelector, value));
|
|
70
71
|
} else if (prop.startsWith("@")) {
|
|
71
72
|
const innerRules = serializeStyle(selector, value);
|
|
72
73
|
for (const inner of innerRules) {
|
|
@@ -77,9 +78,7 @@ function serializeStyle(selector, properties) {
|
|
|
77
78
|
}
|
|
78
79
|
} else {
|
|
79
80
|
const kebabProp = toKebabCase(prop);
|
|
80
|
-
declarations.push(
|
|
81
|
-
`${kebabProp}: ${serializeValue(prop, value)}`
|
|
82
|
-
);
|
|
81
|
+
declarations.push(`${kebabProp}: ${serializeValue(prop, value)}`);
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
if (declarations.length > 0) {
|
|
@@ -117,6 +116,21 @@ function createStyles(namespace, definitions) {
|
|
|
117
116
|
};
|
|
118
117
|
return selectorFn;
|
|
119
118
|
}
|
|
119
|
+
function compose(...selectors) {
|
|
120
|
+
const validSelectors = selectors.filter(Boolean);
|
|
121
|
+
return (...args) => {
|
|
122
|
+
const classNames = [];
|
|
123
|
+
for (const selector of validSelectors) {
|
|
124
|
+
if (typeof selector === "string") {
|
|
125
|
+
classNames.push(selector);
|
|
126
|
+
} else {
|
|
127
|
+
const result = selector(...args);
|
|
128
|
+
if (result) classNames.push(result);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return classNames.join(" ");
|
|
132
|
+
};
|
|
133
|
+
}
|
|
120
134
|
|
|
121
135
|
// src/tokens.ts
|
|
122
136
|
var registeredNamespaces2 = /* @__PURE__ */ new Set();
|
|
@@ -302,10 +316,27 @@ function globalFontFace(family, props) {
|
|
|
302
316
|
insertRule(`font-face:${family}:${props.src}`, css);
|
|
303
317
|
}
|
|
304
318
|
|
|
319
|
+
// src/vars.ts
|
|
320
|
+
var counter = 0;
|
|
321
|
+
function createVar() {
|
|
322
|
+
const name = `--ts-${++counter}`;
|
|
323
|
+
return `var(${name})`;
|
|
324
|
+
}
|
|
325
|
+
function assignVars(vars) {
|
|
326
|
+
const result = {};
|
|
327
|
+
for (const [varRef, value] of Object.entries(vars)) {
|
|
328
|
+
if (value == null) continue;
|
|
329
|
+
const match = varRef.match(/^var\((--[^)]+)\)$/);
|
|
330
|
+
if (match) result[match[1]] = value;
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
|
|
305
335
|
// src/index.ts
|
|
306
336
|
var styles = {
|
|
307
337
|
create: createStyles,
|
|
308
|
-
component: createComponent
|
|
338
|
+
component: createComponent,
|
|
339
|
+
compose
|
|
309
340
|
};
|
|
310
341
|
var global = {
|
|
311
342
|
style: globalStyle,
|
|
@@ -321,6 +352,6 @@ var keyframes = {
|
|
|
321
352
|
};
|
|
322
353
|
var color = color_exports;
|
|
323
354
|
|
|
324
|
-
export { color, global, keyframes, styles, tokens };
|
|
355
|
+
export { assignVars, color, createVar, global, keyframes, styles, tokens };
|
|
325
356
|
//# sourceMappingURL=index.js.map
|
|
326
357
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/css.ts","../src/registry.ts","../src/styles.ts","../src/tokens.ts","../src/keyframes.ts","../src/color.ts","../src/component.ts","../src/global.ts","../src/index.ts"],"names":["registeredNamespaces","alpha"],"mappings":"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","file":"index.js","sourcesContent":["import type { CSSProperties } from './types.js';\n\n/**\n * Convert a camelCase CSS property name to kebab-case.\n * Handles vendor prefixes (ms, webkit, moz) correctly.\n */\nexport function toKebabCase(prop: string): string {\n // Handle ms- prefix specially (no leading dash in camelCase)\n if (prop.startsWith('ms')) {\n return '-' + prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n }\n return prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n}\n\n/**\n * Serialize a single CSS value. Numbers are treated as px for most properties.\n */\nfunction serializeValue(prop: string, value: string | number): string {\n if (typeof value === 'number') {\n if (value === 0) return '0';\n // Unitless properties that shouldn't get 'px'\n if (unitlessProperties.has(prop)) return String(value);\n return value + 'px';\n }\n return value;\n}\n\nconst unitlessProperties = new Set([\n 'animationIterationCount',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'flex',\n 'flexGrow',\n 'flexPositive',\n 'flexShrink',\n 'flexNegative',\n 'flexOrder',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnSpan',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowSpan',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n 'fillOpacity',\n 'floodOpacity',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n]);\n\n/**\n * Represents a generated CSS rule.\n */\nexport interface CSSRule {\n /** Unique key for deduplication */\n key: string;\n /** The CSS rule string */\n css: string;\n}\n\n/**\n * Serialize a style definition object into CSS rule(s) for a given selector.\n */\nexport function serializeStyle(\n selector: string,\n properties: CSSProperties\n): CSSRule[] {\n const rules: CSSRule[] = [];\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n\n if (prop.startsWith('&')) {\n // Nested selector: replace & with the parent selector\n const nestedSelector = prop.replace(/&/g, selector);\n rules.push(\n ...serializeStyle(nestedSelector, value as CSSProperties)\n );\n } else if (prop.startsWith('@')) {\n // At-rule: wrap the serialized content in the at-rule\n const innerRules = serializeStyle(selector, value as CSSProperties);\n for (const inner of innerRules) {\n rules.push({\n key: `${prop}:${inner.key}`,\n css: `${prop} { ${inner.css} }`,\n });\n }\n } else {\n // Regular CSS property\n const kebabProp = toKebabCase(prop);\n declarations.push(\n `${kebabProp}: ${serializeValue(prop, value as string | number)}`\n );\n }\n }\n\n // Add the base rule with all plain declarations\n if (declarations.length > 0) {\n rules.unshift({\n key: selector,\n css: `${selector} { ${declarations.join('; ')}; }`,\n });\n }\n\n return rules;\n}\n","/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n","import type { CSSProperties, SelectorFunction, StyleDefinitions } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a style group and return a selector function.\n *\n * The selector function accepts variant names and returns a composed\n * class name string. Class names are deterministic and human-readable:\n * `{namespace}-{variant}`.\n *\n * @example\n * ```ts\n * const button = createStyles('button', {\n * base: { padding: '8px 16px', fontSize: '14px' },\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * large: { padding: '12px 24px', fontSize: '16px' },\n * });\n *\n * button('base', 'primary') // \"button-base button-primary\"\n * button('base', isLarge && 'large') // conditional application\n * ```\n */\nexport function createStyles<K extends string>(\n namespace: string,\n definitions: StyleDefinitions & Record<K, CSSProperties>\n): SelectorFunction<K> {\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.create('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n // Generate and inject CSS for all variants\n const rules: Array<{ key: string; css: string }> = [];\n\n for (const [variant, properties] of Object.entries(definitions)) {\n const className = `${namespace}-${variant}`;\n const selector = `.${className}`;\n const variantRules = serializeStyle(selector, properties as CSSProperties);\n rules.push(...variantRules);\n }\n\n insertRules(rules);\n\n // Return the selector function\n const selectorFn = (...variants: (K | false | null | undefined)[]): string => {\n return variants\n .filter(Boolean)\n .map((v) => `${namespace}-${v as string}`)\n .join(' ');\n };\n\n return selectorFn as SelectorFunction<K>;\n}\n","import type { TokenValues, TokenRef, ThemeOverrides } from './types.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * Registry tracking which token namespaces have been created,\n * so tokens.use() can provide warnings in development.\n */\nconst registeredNamespaces = new Set<string>();\n\n/**\n * Create a proxy-based token reference for a namespace.\n * Property access returns var(--{namespace}-{key}).\n */\nfunction createTokenProxy<T extends TokenValues>(namespace: string): TokenRef<T> {\n return new Proxy({} as TokenRef<T>, {\n get(_target, prop: string) {\n return `var(--${namespace}-${prop})`;\n },\n });\n}\n\n/**\n * Create design tokens as CSS custom properties.\n *\n * Generates a :root rule with the custom properties and returns\n * a typed object where property access yields var() references.\n *\n * @example\n * ```ts\n * const color = createTokens('color', {\n * primary: '#0066ff',\n * secondary: '#6b7280',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function createTokens<T extends TokenValues>(\n namespace: string,\n values: T\n): TokenRef<T> {\n registeredNamespaces.add(namespace);\n\n // Generate CSS custom property declarations\n const declarations = Object.entries(values)\n .map(([key, value]) => `--${namespace}-${key}: ${value}`)\n .join('; ');\n\n const css = `:root { ${declarations}; }`;\n insertRule(`tokens:${namespace}`, css);\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Reference tokens defined elsewhere without injecting CSS.\n *\n * Returns a typed proxy that produces var() references.\n * Useful for consuming shared tokens from a different module.\n *\n * @example\n * ```ts\n * const color = useTokens('color');\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function useTokens<T extends TokenValues = TokenValues>(\n namespace: string\n): TokenRef<T> {\n if (\n process.env.NODE_ENV !== 'production' &&\n registeredNamespaces.size > 0 &&\n !registeredNamespaces.has(namespace)\n ) {\n console.warn(\n `[typestyles] tokens.use('${namespace}') references a namespace that hasn't been created yet. ` +\n `Make sure tokens.create('${namespace}', ...) is called before using these tokens.`\n );\n }\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Create a theme class that overrides token values.\n *\n * Returns a class name string. Apply it to any element to override\n * token values for that subtree via CSS custom property cascading.\n *\n * @example\n * ```ts\n * const dark = createTheme('dark', {\n * color: { primary: '#66b3ff', surface: '#1a1a2e' },\n * });\n *\n * <div className={dark}> // class=\"theme-dark\"\n * ```\n */\nexport function createTheme(name: string, overrides: ThemeOverrides): string {\n const className = `theme-${name}`;\n\n const declarations: string[] = [];\n for (const [namespace, values] of Object.entries(overrides)) {\n for (const [key, value] of Object.entries(values)) {\n if (value != null) {\n declarations.push(`--${namespace}-${key}: ${value}`);\n }\n }\n }\n\n const css = `.${className} { ${declarations.join('; ')}; }`;\n insertRule(`theme:${name}`, css);\n\n return className;\n}\n","import type { CSSProperties } from './types.js';\nimport { toKebabCase } from './css.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * A keyframe stop is either 'from', 'to', or a percentage like '50%'.\n */\nexport type KeyframeStops = Record<string, CSSProperties>;\n\n/**\n * Serialize CSS declarations for a single keyframe stop (no nesting/at-rules).\n */\nfunction serializeDeclarations(properties: CSSProperties): string {\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n // Keyframe stops only contain plain properties — skip nested selectors/at-rules\n if (prop.startsWith('&') || prop.startsWith('@')) continue;\n\n const kebabProp = toKebabCase(prop);\n const serialized =\n typeof value === 'number' ? (value === 0 ? '0' : value + 'px') : value;\n declarations.push(`${kebabProp}: ${serialized}`);\n }\n\n return declarations.join('; ');\n}\n\n/**\n * Create a CSS @keyframes animation and return its name.\n *\n * The returned string is the animation name — use it directly in\n * `animation` shorthand or `animationName`.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n *\n * @example\n * ```ts\n * const bounce = keyframes.create('bounce', {\n * '0%': { transform: 'translateY(0)' },\n * '50%': { transform: 'translateY(-20px)' },\n * '100%': { transform: 'translateY(0)' },\n * });\n * ```\n */\nexport function createKeyframes(name: string, stops: KeyframeStops): string {\n const stopsCSS = Object.entries(stops)\n .map(([stop, properties]) => {\n const decls = serializeDeclarations(properties as CSSProperties);\n return `${stop} { ${decls}; }`;\n })\n .join(' ');\n\n const css = `@keyframes ${name} { ${stopsCSS} }`;\n insertRule(`keyframes:${name}`, css);\n\n return name;\n}\n","/**\n * Type-safe helpers for CSS color functions.\n *\n * Each function returns a plain CSS string — no runtime color math.\n * Works naturally with token references since tokens are strings too.\n */\n\ntype ColorValue = string | number;\n\n/** Color spaces supported by color-mix(). */\nexport type ColorMixSpace =\n | 'srgb'\n | 'srgb-linear'\n | 'display-p3'\n | 'a98-rgb'\n | 'prophoto-rgb'\n | 'rec2020'\n | 'lab'\n | 'oklab'\n | 'xyz'\n | 'xyz-d50'\n | 'xyz-d65'\n | 'hsl'\n | 'hwb'\n | 'lch'\n | 'oklch';\n\n/**\n * `rgb(r g b)` or `rgb(r g b / a)`\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.rgb(0, 102, 255, 0.5) // \"rgb(0 102 255 / 0.5)\"\n * ```\n */\nexport function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `rgb(${r} ${g} ${b} / ${alpha})`;\n return `rgb(${r} ${g} ${b})`;\n}\n\n/**\n * `hsl(h s l)` or `hsl(h s l / a)`\n *\n * @example\n * ```ts\n * color.hsl(220, '100%', '50%') // \"hsl(220 100% 50%)\"\n * color.hsl(220, '100%', '50%', 0.8) // \"hsl(220 100% 50% / 0.8)\"\n * ```\n */\nexport function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hsl(${h} ${s} ${l} / ${alpha})`;\n return `hsl(${h} ${s} ${l})`;\n}\n\n/**\n * `oklch(L C h)` or `oklch(L C h / a)`\n *\n * @example\n * ```ts\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.oklch(0.7, 0.15, 250, 0.5) // \"oklch(0.7 0.15 250 / 0.5)\"\n * ```\n */\nexport function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklch(${l} ${c} ${h} / ${alpha})`;\n return `oklch(${l} ${c} ${h})`;\n}\n\n/**\n * `oklab(L a b)` or `oklab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.oklab(0.7, -0.1, -0.1) // \"oklab(0.7 -0.1 -0.1)\"\n * color.oklab(0.7, -0.1, -0.1, 0.5) // \"oklab(0.7 -0.1 -0.1 / 0.5)\"\n * ```\n */\nexport function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklab(${l} ${a} ${b} / ${alpha})`;\n return `oklab(${l} ${a} ${b})`;\n}\n\n/**\n * `lab(L a b)` or `lab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.lab('50%', 40, -20) // \"lab(50% 40 -20)\"\n * ```\n */\nexport function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lab(${l} ${a} ${b} / ${alpha})`;\n return `lab(${l} ${a} ${b})`;\n}\n\n/**\n * `lch(L C h)` or `lch(L C h / alpha)`\n *\n * @example\n * ```ts\n * color.lch('50%', 80, 250) // \"lch(50% 80 250)\"\n * ```\n */\nexport function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lch(${l} ${c} ${h} / ${alpha})`;\n return `lch(${l} ${c} ${h})`;\n}\n\n/**\n * `hwb(h w b)` or `hwb(h w b / alpha)`\n *\n * @example\n * ```ts\n * color.hwb(220, '10%', '0%') // \"hwb(220 10% 0%)\"\n * ```\n */\nexport function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hwb(${h} ${w} ${b} / ${alpha})`;\n return `hwb(${h} ${w} ${b})`;\n}\n\n/**\n * `color-mix(in colorspace, color1 p1%, color2 p2%)`\n *\n * Mixes two colors in the given color space. Percentages are optional.\n *\n * @example\n * ```ts\n * color.mix('red', 'blue') // \"color-mix(in srgb, red, blue)\"\n * color.mix('red', 'blue', 30) // \"color-mix(in srgb, red 30%, blue)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.mix('red', 'blue', 50, 'oklch') // \"color-mix(in oklch, red 50%, blue)\"\n * ```\n */\nexport function mix(\n color1: string,\n color2: string,\n percentage?: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const c1 = percentage != null ? `${color1} ${percentage}%` : color1;\n return `color-mix(in ${colorSpace}, ${c1}, ${color2})`;\n}\n\n/**\n * `light-dark(lightColor, darkColor)`\n *\n * Uses the `light-dark()` CSS function that resolves based on\n * the computed `color-scheme` of the element.\n *\n * @example\n * ```ts\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * color.lightDark(theme.textLight, theme.textDark) // \"light-dark(var(--theme-textLight), var(--theme-textDark))\"\n * ```\n */\nexport function lightDark(lightColor: string, darkColor: string): string {\n return `light-dark(${lightColor}, ${darkColor})`;\n}\n\n/**\n * Adjust the alpha/opacity of any color using `color-mix()`.\n *\n * This is a common pattern: mixing a color with transparent to change opacity.\n * Works with any color value including token references.\n *\n * @example\n * ```ts\n * color.alpha('red', 0.5) // \"color-mix(in srgb, red 50%, transparent)\"\n * color.alpha(theme.primary, 0.2) // \"color-mix(in srgb, var(--theme-primary) 20%, transparent)\"\n * color.alpha('#0066ff', 0.8, 'oklch') // \"color-mix(in oklch, #0066ff 80%, transparent)\"\n * ```\n */\nexport function alpha(\n colorValue: string,\n opacity: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const percentage = Math.round(opacity * 100);\n return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`;\n}\n","import type { CSSProperties, VariantDefinitions, ComponentConfig, ComponentFunction } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a multi-variant component style and return a selector function.\n *\n * Class naming convention:\n * base → `{namespace}-base`\n * variants.intent.primary → `{namespace}-intent-primary`\n * compoundVariants[0] → `{namespace}-compound-0`\n *\n * @example\n * ```ts\n * const button = styles.component('button', {\n * base: { padding: '8px 16px' },\n * variants: {\n * intent: {\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * ghost: { backgroundColor: 'transparent', border: '1px solid currentColor' },\n * },\n * size: {\n * sm: { fontSize: '12px' },\n * lg: { fontSize: '18px' },\n * },\n * },\n * compoundVariants: [\n * { variants: { intent: 'primary', size: 'lg' }, style: { fontWeight: 700 } },\n * ],\n * defaultVariants: { intent: 'primary', size: 'sm' },\n * });\n *\n * button() // \"button-base button-intent-primary button-size-sm\"\n * button({ intent: 'ghost' }) // \"button-base button-intent-ghost button-size-sm\"\n * button({ intent: 'primary', size: 'lg' }) // includes compound class\n * ```\n */\nexport function createComponent<V extends VariantDefinitions>(\n namespace: string,\n config: ComponentConfig<V>\n): ComponentFunction<V> {\n const { base, variants = {} as V, compoundVariants = [], defaultVariants = {} } = config;\n\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.component('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n const rules: Array<{ key: string; css: string }> = [];\n\n // 1. Inject CSS for base\n if (base) {\n rules.push(...serializeStyle(`.${namespace}-base`, base));\n }\n\n // 2. Inject CSS for each variant option\n for (const [dimension, options] of Object.entries(variants)) {\n for (const [option, properties] of Object.entries(options as Record<string, CSSProperties>)) {\n const className = `.${namespace}-${dimension}-${option}`;\n rules.push(...serializeStyle(className, properties));\n }\n }\n\n // 3. Inject CSS for each compound variant\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const className = `.${namespace}-compound-${index}`;\n rules.push(...serializeStyle(className, cv.style));\n }\n );\n\n insertRules(rules);\n\n // 4. Return the selector function\n return ((selections: Record<string, unknown> = {}) => {\n const classes: string[] = [];\n\n if (base) classes.push(`${namespace}-base`);\n\n // Resolve final selections (explicit overrides defaultVariants)\n const resolvedSelections: Record<string, unknown> = {};\n for (const dimension of Object.keys(variants)) {\n resolvedSelections[dimension] =\n selections[dimension] ?? (defaultVariants as Record<string, unknown>)[dimension];\n }\n\n // Apply variant classes\n for (const dimension of Object.keys(variants)) {\n const selected = resolvedSelections[dimension];\n if (selected != null && selected !== false) {\n classes.push(`${namespace}-${dimension}-${String(selected)}`);\n }\n }\n\n // Apply compound variant classes\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const matches = Object.entries(cv.variants).every(\n ([k, v]) => resolvedSelections[k] === v\n );\n if (matches) classes.push(`${namespace}-compound-${index}`);\n }\n );\n\n return classes.join(' ');\n }) as ComponentFunction<V>;\n}\n","import type { CSSProperties, FontFaceProps } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRule, insertRules } from './sheet.js';\n\n/**\n * Apply styles to an arbitrary CSS selector.\n *\n * Use for CSS resets, body/root defaults, third-party elements, or any\n * selector that isn't tied to a specific component class.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0, fontFamily: 'sans-serif' });\n * global.style('a:hover', { textDecoration: 'underline' });\n * global.style('*, *::before, *::after', { boxSizing: 'border-box' });\n * ```\n */\nexport function globalStyle(selector: string, properties: CSSProperties): void {\n const rules = serializeStyle(selector, properties);\n insertRules(rules);\n}\n\n/**\n * Declare a `@font-face` rule to load a custom font.\n *\n * Multiple weights/styles of the same family can be registered by calling\n * this function multiple times with different `src` values — each call is\n * deduplicated by `family + src`.\n *\n * @example\n * ```ts\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Regular.woff2') format('woff2')\",\n * fontWeight: 400,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n *\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Bold.woff2') format('woff2')\",\n * fontWeight: 700,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n * ```\n */\nexport function globalFontFace(family: string, props: FontFaceProps): void {\n const decls: string[] = [`font-family: \"${family}\"`, `src: ${props.src}`];\n if (props.fontWeight != null) decls.push(`font-weight: ${props.fontWeight}`);\n if (props.fontStyle) decls.push(`font-style: ${props.fontStyle}`);\n if (props.fontDisplay) decls.push(`font-display: ${props.fontDisplay}`);\n if (props.fontStretch) decls.push(`font-stretch: ${props.fontStretch}`);\n if (props.unicodeRange) decls.push(`unicode-range: ${props.unicodeRange}`);\n const css = `@font-face { ${decls.join('; ')}; }`;\n // Key includes src for uniqueness (multiple weights per family)\n insertRule(`font-face:${family}:${props.src}`, css);\n}\n","import { createStyles } from './styles.js';\nimport { createTokens, useTokens, createTheme } from './tokens.js';\nimport { createKeyframes } from './keyframes.js';\nimport * as colorFns from './color.js';\nimport { getRegisteredCss } from './sheet.js';\nimport { createComponent } from './component.js';\nimport { globalStyle, globalFontFace } from './global.js';\n\nexport type {\n CSSProperties,\n CSSValue,\n StyleDefinitions,\n SelectorFunction,\n TokenValues,\n TokenRef,\n ThemeOverrides,\n KeyframeStops,\n VariantDefinitions,\n ComponentConfig,\n ComponentFunction,\n FontFaceProps,\n} from './types.js';\n\nexport type { ColorMixSpace } from './color.js';\n\n/**\n * Style creation API.\n *\n * @example\n * ```ts\n * const button = styles.create('button', {\n * base: { padding: '8px 16px' },\n * primary: { backgroundColor: '#0066ff' },\n * });\n *\n * <button className={button('base', 'primary')}>\n * ```\n */\nexport const styles = {\n create: createStyles,\n component: createComponent,\n} as const;\n\n/**\n * Global CSS API for arbitrary selectors and font-face declarations.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0 });\n * global.fontFace('Inter', { src: \"url('/Inter.woff2') format('woff2')\", fontWeight: 400 });\n * ```\n */\nexport const global = {\n style: globalStyle,\n fontFace: globalFontFace,\n} as const;\n\n/**\n * Design token API using CSS custom properties.\n *\n * @example\n * ```ts\n * const color = tokens.create('color', {\n * primary: '#0066ff',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport const tokens = {\n create: createTokens,\n use: useTokens,\n createTheme,\n} as const;\n\n/**\n * Keyframe animation API.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n */\nexport const keyframes = {\n create: createKeyframes,\n} as const;\n\n/**\n * Type-safe CSS color function helpers.\n *\n * Each function returns a plain CSS color string — no runtime color math.\n * Composes naturally with token references.\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.alpha(theme.primary, 0.5) // \"color-mix(in srgb, var(--theme-primary) 50%, transparent)\"\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * ```\n */\nexport const color = colorFns;\n\n/**\n * Return all registered CSS as a string (for SSR).\n *\n * Returns every CSS rule registered via `styles.create`, `tokens.create`,\n * `keyframes.create`, etc. Use this in your SSR head/meta function to\n * inject styles into the document.\n *\n * This is safe to import on the client — it has no server-specific\n * dependencies and will simply return whatever CSS has been registered.\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles';\n *\n * // In a route's head function (e.g. TanStack Start):\n * export const Route = createRootRoute({\n * head: () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * }),\n * });\n * ```\n */\nexport { getRegisteredCss };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/css.ts","../src/registry.ts","../src/styles.ts","../src/tokens.ts","../src/keyframes.ts","../src/color.ts","../src/component.ts","../src/global.ts","../src/vars.ts","../src/index.ts"],"names":["registeredNamespaces","alpha"],"mappings":"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","file":"index.js","sourcesContent":["import type { CSSProperties } from './types.js';\n\n/**\n * Convert a camelCase CSS property name to kebab-case.\n * Handles vendor prefixes (ms, webkit, moz) correctly.\n */\nexport function toKebabCase(prop: string): string {\n // Handle ms- prefix specially (no leading dash in camelCase)\n if (prop.startsWith('ms')) {\n return '-' + prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n }\n return prop.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());\n}\n\n/**\n * Serialize a single CSS value. Numbers are treated as px for most properties.\n */\nfunction serializeValue(prop: string, value: string | number): string {\n if (typeof value === 'number') {\n if (value === 0) return '0';\n // Unitless properties that shouldn't get 'px'\n if (unitlessProperties.has(prop)) return String(value);\n return value + 'px';\n }\n return value;\n}\n\nconst unitlessProperties = new Set([\n 'animationIterationCount',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'flex',\n 'flexGrow',\n 'flexPositive',\n 'flexShrink',\n 'flexNegative',\n 'flexOrder',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnSpan',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowSpan',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n 'fillOpacity',\n 'floodOpacity',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n]);\n\n/**\n * Represents a generated CSS rule.\n */\nexport interface CSSRule {\n /** Unique key for deduplication */\n key: string;\n /** The CSS rule string */\n css: string;\n}\n\n/**\n * Serialize a style definition object into CSS rule(s) for a given selector.\n */\nexport function serializeStyle(selector: string, properties: CSSProperties): CSSRule[] {\n const rules: CSSRule[] = [];\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n\n if (prop.startsWith('&')) {\n // Nested selector: replace & with the parent selector\n const nestedSelector = prop.replace(/&/g, selector);\n rules.push(...serializeStyle(nestedSelector, value as CSSProperties));\n } else if (prop.startsWith('[')) {\n // Attribute selector: combine with parent selector\n const attrSelector = selector + prop;\n rules.push(...serializeStyle(attrSelector, value as CSSProperties));\n } else if (prop.startsWith('@')) {\n // At-rule: wrap the serialized content in the at-rule\n const innerRules = serializeStyle(selector, value as CSSProperties);\n for (const inner of innerRules) {\n rules.push({\n key: `${prop}:${inner.key}`,\n css: `${prop} { ${inner.css} }`,\n });\n }\n } else {\n // Regular CSS property\n const kebabProp = toKebabCase(prop);\n declarations.push(`${kebabProp}: ${serializeValue(prop, value as string | number)}`);\n }\n }\n\n // Add the base rule with all plain declarations\n if (declarations.length > 0) {\n rules.unshift({\n key: selector,\n css: `${selector} { ${declarations.join('; ')}; }`,\n });\n }\n\n return rules;\n}\n","/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n","import type { CSSProperties, SelectorFunction, StyleDefinitions } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a style group and return a selector function.\n *\n * The selector function accepts variant names and returns a composed\n * class name string. Class names are deterministic and human-readable:\n * `{namespace}-{variant}`.\n *\n * @example\n * ```ts\n * const button = createStyles('button', {\n * base: { padding: '8px 16px', fontSize: '14px' },\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * large: { padding: '12px 24px', fontSize: '16px' },\n * });\n *\n * button('base', 'primary') // \"button-base button-primary\"\n * button('base', isLarge && 'large') // conditional application\n * ```\n */\nexport function createStyles<K extends string>(\n namespace: string,\n definitions: StyleDefinitions & Record<K, CSSProperties>,\n): SelectorFunction<K> {\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.create('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`,\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n // Generate and inject CSS for all variants\n const rules: Array<{ key: string; css: string }> = [];\n\n for (const [variant, properties] of Object.entries(definitions)) {\n const className = `${namespace}-${variant}`;\n const selector = `.${className}`;\n const variantRules = serializeStyle(selector, properties as CSSProperties);\n rules.push(...variantRules);\n }\n\n insertRules(rules);\n\n // Return the selector function\n const selectorFn = (...variants: (K | false | null | undefined)[]): string => {\n return variants\n .filter(Boolean)\n .map((v) => `${namespace}-${v as string}`)\n .join(' ');\n };\n\n return selectorFn as SelectorFunction<K>;\n}\n\n/**\n * Compose multiple selector functions or class strings into one.\n * Returns a new SelectorFunction that calls all inputs and joins results.\n *\n * @example\n * ```ts\n * const base = styles.create('base', { padding: '8px' });\n * const primary = styles.create('primary', { color: 'blue' });\n * const button = styles.compose(base, primary);\n *\n * button('padding', 'color'); // \"base-padding primary-color\"\n * ```\n */\ntype AnySelectorFunction = {\n (...args: unknown[]): string;\n};\n\nexport function compose(\n ...selectors: Array<AnySelectorFunction | string | false | null | undefined>\n): AnySelectorFunction {\n const validSelectors = selectors.filter(Boolean) as Array<AnySelectorFunction | string>;\n\n return (...args: unknown[]): string => {\n const classNames: string[] = [];\n\n for (const selector of validSelectors) {\n if (typeof selector === 'string') {\n classNames.push(selector);\n } else {\n const result = selector(...args);\n if (result) classNames.push(result);\n }\n }\n\n return classNames.join(' ');\n };\n}\n","import type { TokenValues, TokenRef, ThemeOverrides } from './types.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * Registry tracking which token namespaces have been created,\n * so tokens.use() can provide warnings in development.\n */\nconst registeredNamespaces = new Set<string>();\n\n/**\n * Create a proxy-based token reference for a namespace.\n * Property access returns var(--{namespace}-{key}).\n */\nfunction createTokenProxy<T extends TokenValues>(namespace: string): TokenRef<T> {\n return new Proxy({} as TokenRef<T>, {\n get(_target, prop: string) {\n return `var(--${namespace}-${prop})`;\n },\n });\n}\n\n/**\n * Create design tokens as CSS custom properties.\n *\n * Generates a :root rule with the custom properties and returns\n * a typed object where property access yields var() references.\n *\n * @example\n * ```ts\n * const color = createTokens('color', {\n * primary: '#0066ff',\n * secondary: '#6b7280',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function createTokens<T extends TokenValues>(\n namespace: string,\n values: T\n): TokenRef<T> {\n registeredNamespaces.add(namespace);\n\n // Generate CSS custom property declarations\n const declarations = Object.entries(values)\n .map(([key, value]) => `--${namespace}-${key}: ${value}`)\n .join('; ');\n\n const css = `:root { ${declarations}; }`;\n insertRule(`tokens:${namespace}`, css);\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Reference tokens defined elsewhere without injecting CSS.\n *\n * Returns a typed proxy that produces var() references.\n * Useful for consuming shared tokens from a different module.\n *\n * @example\n * ```ts\n * const color = useTokens('color');\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport function useTokens<T extends TokenValues = TokenValues>(\n namespace: string\n): TokenRef<T> {\n if (\n process.env.NODE_ENV !== 'production' &&\n registeredNamespaces.size > 0 &&\n !registeredNamespaces.has(namespace)\n ) {\n console.warn(\n `[typestyles] tokens.use('${namespace}') references a namespace that hasn't been created yet. ` +\n `Make sure tokens.create('${namespace}', ...) is called before using these tokens.`\n );\n }\n\n return createTokenProxy<T>(namespace);\n}\n\n/**\n * Create a theme class that overrides token values.\n *\n * Returns a class name string. Apply it to any element to override\n * token values for that subtree via CSS custom property cascading.\n *\n * @example\n * ```ts\n * const dark = createTheme('dark', {\n * color: { primary: '#66b3ff', surface: '#1a1a2e' },\n * });\n *\n * <div className={dark}> // class=\"theme-dark\"\n * ```\n */\nexport function createTheme(name: string, overrides: ThemeOverrides): string {\n const className = `theme-${name}`;\n\n const declarations: string[] = [];\n for (const [namespace, values] of Object.entries(overrides)) {\n for (const [key, value] of Object.entries(values)) {\n if (value != null) {\n declarations.push(`--${namespace}-${key}: ${value}`);\n }\n }\n }\n\n const css = `.${className} { ${declarations.join('; ')}; }`;\n insertRule(`theme:${name}`, css);\n\n return className;\n}\n","import type { CSSProperties } from './types.js';\nimport { toKebabCase } from './css.js';\nimport { insertRule } from './sheet.js';\n\n/**\n * A keyframe stop is either 'from', 'to', or a percentage like '50%'.\n */\nexport type KeyframeStops = Record<string, CSSProperties>;\n\n/**\n * Serialize CSS declarations for a single keyframe stop (no nesting/at-rules).\n */\nfunction serializeDeclarations(properties: CSSProperties): string {\n const declarations: string[] = [];\n\n for (const [prop, value] of Object.entries(properties)) {\n if (value == null) continue;\n // Keyframe stops only contain plain properties — skip nested selectors/at-rules\n if (prop.startsWith('&') || prop.startsWith('@')) continue;\n\n const kebabProp = toKebabCase(prop);\n const serialized =\n typeof value === 'number' ? (value === 0 ? '0' : value + 'px') : value;\n declarations.push(`${kebabProp}: ${serialized}`);\n }\n\n return declarations.join('; ');\n}\n\n/**\n * Create a CSS @keyframes animation and return its name.\n *\n * The returned string is the animation name — use it directly in\n * `animation` shorthand or `animationName`.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n *\n * @example\n * ```ts\n * const bounce = keyframes.create('bounce', {\n * '0%': { transform: 'translateY(0)' },\n * '50%': { transform: 'translateY(-20px)' },\n * '100%': { transform: 'translateY(0)' },\n * });\n * ```\n */\nexport function createKeyframes(name: string, stops: KeyframeStops): string {\n const stopsCSS = Object.entries(stops)\n .map(([stop, properties]) => {\n const decls = serializeDeclarations(properties as CSSProperties);\n return `${stop} { ${decls}; }`;\n })\n .join(' ');\n\n const css = `@keyframes ${name} { ${stopsCSS} }`;\n insertRule(`keyframes:${name}`, css);\n\n return name;\n}\n","/**\n * Type-safe helpers for CSS color functions.\n *\n * Each function returns a plain CSS string — no runtime color math.\n * Works naturally with token references since tokens are strings too.\n */\n\ntype ColorValue = string | number;\n\n/** Color spaces supported by color-mix(). */\nexport type ColorMixSpace =\n | 'srgb'\n | 'srgb-linear'\n | 'display-p3'\n | 'a98-rgb'\n | 'prophoto-rgb'\n | 'rec2020'\n | 'lab'\n | 'oklab'\n | 'xyz'\n | 'xyz-d50'\n | 'xyz-d65'\n | 'hsl'\n | 'hwb'\n | 'lch'\n | 'oklch';\n\n/**\n * `rgb(r g b)` or `rgb(r g b / a)`\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.rgb(0, 102, 255, 0.5) // \"rgb(0 102 255 / 0.5)\"\n * ```\n */\nexport function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `rgb(${r} ${g} ${b} / ${alpha})`;\n return `rgb(${r} ${g} ${b})`;\n}\n\n/**\n * `hsl(h s l)` or `hsl(h s l / a)`\n *\n * @example\n * ```ts\n * color.hsl(220, '100%', '50%') // \"hsl(220 100% 50%)\"\n * color.hsl(220, '100%', '50%', 0.8) // \"hsl(220 100% 50% / 0.8)\"\n * ```\n */\nexport function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hsl(${h} ${s} ${l} / ${alpha})`;\n return `hsl(${h} ${s} ${l})`;\n}\n\n/**\n * `oklch(L C h)` or `oklch(L C h / a)`\n *\n * @example\n * ```ts\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.oklch(0.7, 0.15, 250, 0.5) // \"oklch(0.7 0.15 250 / 0.5)\"\n * ```\n */\nexport function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklch(${l} ${c} ${h} / ${alpha})`;\n return `oklch(${l} ${c} ${h})`;\n}\n\n/**\n * `oklab(L a b)` or `oklab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.oklab(0.7, -0.1, -0.1) // \"oklab(0.7 -0.1 -0.1)\"\n * color.oklab(0.7, -0.1, -0.1, 0.5) // \"oklab(0.7 -0.1 -0.1 / 0.5)\"\n * ```\n */\nexport function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `oklab(${l} ${a} ${b} / ${alpha})`;\n return `oklab(${l} ${a} ${b})`;\n}\n\n/**\n * `lab(L a b)` or `lab(L a b / alpha)`\n *\n * @example\n * ```ts\n * color.lab('50%', 40, -20) // \"lab(50% 40 -20)\"\n * ```\n */\nexport function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lab(${l} ${a} ${b} / ${alpha})`;\n return `lab(${l} ${a} ${b})`;\n}\n\n/**\n * `lch(L C h)` or `lch(L C h / alpha)`\n *\n * @example\n * ```ts\n * color.lch('50%', 80, 250) // \"lch(50% 80 250)\"\n * ```\n */\nexport function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `lch(${l} ${c} ${h} / ${alpha})`;\n return `lch(${l} ${c} ${h})`;\n}\n\n/**\n * `hwb(h w b)` or `hwb(h w b / alpha)`\n *\n * @example\n * ```ts\n * color.hwb(220, '10%', '0%') // \"hwb(220 10% 0%)\"\n * ```\n */\nexport function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string {\n if (alpha != null) return `hwb(${h} ${w} ${b} / ${alpha})`;\n return `hwb(${h} ${w} ${b})`;\n}\n\n/**\n * `color-mix(in colorspace, color1 p1%, color2 p2%)`\n *\n * Mixes two colors in the given color space. Percentages are optional.\n *\n * @example\n * ```ts\n * color.mix('red', 'blue') // \"color-mix(in srgb, red, blue)\"\n * color.mix('red', 'blue', 30) // \"color-mix(in srgb, red 30%, blue)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.mix('red', 'blue', 50, 'oklch') // \"color-mix(in oklch, red 50%, blue)\"\n * ```\n */\nexport function mix(\n color1: string,\n color2: string,\n percentage?: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const c1 = percentage != null ? `${color1} ${percentage}%` : color1;\n return `color-mix(in ${colorSpace}, ${c1}, ${color2})`;\n}\n\n/**\n * `light-dark(lightColor, darkColor)`\n *\n * Uses the `light-dark()` CSS function that resolves based on\n * the computed `color-scheme` of the element.\n *\n * @example\n * ```ts\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * color.lightDark(theme.textLight, theme.textDark) // \"light-dark(var(--theme-textLight), var(--theme-textDark))\"\n * ```\n */\nexport function lightDark(lightColor: string, darkColor: string): string {\n return `light-dark(${lightColor}, ${darkColor})`;\n}\n\n/**\n * Adjust the alpha/opacity of any color using `color-mix()`.\n *\n * This is a common pattern: mixing a color with transparent to change opacity.\n * Works with any color value including token references.\n *\n * @example\n * ```ts\n * color.alpha('red', 0.5) // \"color-mix(in srgb, red 50%, transparent)\"\n * color.alpha(theme.primary, 0.2) // \"color-mix(in srgb, var(--theme-primary) 20%, transparent)\"\n * color.alpha('#0066ff', 0.8, 'oklch') // \"color-mix(in oklch, #0066ff 80%, transparent)\"\n * ```\n */\nexport function alpha(\n colorValue: string,\n opacity: number,\n colorSpace: ColorMixSpace = 'srgb'\n): string {\n const percentage = Math.round(opacity * 100);\n return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`;\n}\n","import type { CSSProperties, VariantDefinitions, ComponentConfig, ComponentFunction } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRules } from './sheet.js';\nimport { registeredNamespaces } from './registry.js';\n\n/**\n * Create a multi-variant component style and return a selector function.\n *\n * Class naming convention:\n * base → `{namespace}-base`\n * variants.intent.primary → `{namespace}-intent-primary`\n * compoundVariants[0] → `{namespace}-compound-0`\n *\n * @example\n * ```ts\n * const button = styles.component('button', {\n * base: { padding: '8px 16px' },\n * variants: {\n * intent: {\n * primary: { backgroundColor: '#0066ff', color: '#fff' },\n * ghost: { backgroundColor: 'transparent', border: '1px solid currentColor' },\n * },\n * size: {\n * sm: { fontSize: '12px' },\n * lg: { fontSize: '18px' },\n * },\n * },\n * compoundVariants: [\n * { variants: { intent: 'primary', size: 'lg' }, style: { fontWeight: 700 } },\n * ],\n * defaultVariants: { intent: 'primary', size: 'sm' },\n * });\n *\n * button() // \"button-base button-intent-primary button-size-sm\"\n * button({ intent: 'ghost' }) // \"button-base button-intent-ghost button-size-sm\"\n * button({ intent: 'primary', size: 'lg' }) // includes compound class\n * ```\n */\nexport function createComponent<V extends VariantDefinitions>(\n namespace: string,\n config: ComponentConfig<V>\n): ComponentFunction<V> {\n const { base, variants = {} as V, compoundVariants = [], defaultVariants = {} } = config;\n\n // Development-mode duplicate detection\n if (process.env.NODE_ENV !== 'production') {\n if (registeredNamespaces.has(namespace)) {\n console.warn(\n `[typestyles] styles.component('${namespace}', ...) called more than once. ` +\n `This will cause class name collisions. Each namespace should be unique.`\n );\n }\n }\n registeredNamespaces.add(namespace);\n\n const rules: Array<{ key: string; css: string }> = [];\n\n // 1. Inject CSS for base\n if (base) {\n rules.push(...serializeStyle(`.${namespace}-base`, base));\n }\n\n // 2. Inject CSS for each variant option\n for (const [dimension, options] of Object.entries(variants)) {\n for (const [option, properties] of Object.entries(options as Record<string, CSSProperties>)) {\n const className = `.${namespace}-${dimension}-${option}`;\n rules.push(...serializeStyle(className, properties));\n }\n }\n\n // 3. Inject CSS for each compound variant\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const className = `.${namespace}-compound-${index}`;\n rules.push(...serializeStyle(className, cv.style));\n }\n );\n\n insertRules(rules);\n\n // 4. Return the selector function\n return ((selections: Record<string, unknown> = {}) => {\n const classes: string[] = [];\n\n if (base) classes.push(`${namespace}-base`);\n\n // Resolve final selections (explicit overrides defaultVariants)\n const resolvedSelections: Record<string, unknown> = {};\n for (const dimension of Object.keys(variants)) {\n resolvedSelections[dimension] =\n selections[dimension] ?? (defaultVariants as Record<string, unknown>)[dimension];\n }\n\n // Apply variant classes\n for (const dimension of Object.keys(variants)) {\n const selected = resolvedSelections[dimension];\n if (selected != null && selected !== false) {\n classes.push(`${namespace}-${dimension}-${String(selected)}`);\n }\n }\n\n // Apply compound variant classes\n (compoundVariants as Array<{ variants: Record<string, unknown>; style: CSSProperties }>).forEach(\n (cv, index) => {\n const matches = Object.entries(cv.variants).every(\n ([k, v]) => resolvedSelections[k] === v\n );\n if (matches) classes.push(`${namespace}-compound-${index}`);\n }\n );\n\n return classes.join(' ');\n }) as ComponentFunction<V>;\n}\n","import type { CSSProperties, FontFaceProps } from './types.js';\nimport { serializeStyle } from './css.js';\nimport { insertRule, insertRules } from './sheet.js';\n\n/**\n * Apply styles to an arbitrary CSS selector.\n *\n * Use for CSS resets, body/root defaults, third-party elements, or any\n * selector that isn't tied to a specific component class.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0, fontFamily: 'sans-serif' });\n * global.style('a:hover', { textDecoration: 'underline' });\n * global.style('*, *::before, *::after', { boxSizing: 'border-box' });\n * ```\n */\nexport function globalStyle(selector: string, properties: CSSProperties): void {\n const rules = serializeStyle(selector, properties);\n insertRules(rules);\n}\n\n/**\n * Declare a `@font-face` rule to load a custom font.\n *\n * Multiple weights/styles of the same family can be registered by calling\n * this function multiple times with different `src` values — each call is\n * deduplicated by `family + src`.\n *\n * @example\n * ```ts\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Regular.woff2') format('woff2')\",\n * fontWeight: 400,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n *\n * global.fontFace('Inter', {\n * src: \"url('/fonts/Inter-Bold.woff2') format('woff2')\",\n * fontWeight: 700,\n * fontStyle: 'normal',\n * fontDisplay: 'swap',\n * });\n * ```\n */\nexport function globalFontFace(family: string, props: FontFaceProps): void {\n const decls: string[] = [`font-family: \"${family}\"`, `src: ${props.src}`];\n if (props.fontWeight != null) decls.push(`font-weight: ${props.fontWeight}`);\n if (props.fontStyle) decls.push(`font-style: ${props.fontStyle}`);\n if (props.fontDisplay) decls.push(`font-display: ${props.fontDisplay}`);\n if (props.fontStretch) decls.push(`font-stretch: ${props.fontStretch}`);\n if (props.unicodeRange) decls.push(`unicode-range: ${props.unicodeRange}`);\n const css = `@font-face { ${decls.join('; ')}; }`;\n // Key includes src for uniqueness (multiple weights per family)\n insertRule(`font-face:${family}:${props.src}`, css);\n}\n","import type { CSSVarRef } from './types.js';\n\nlet counter = 0;\n\n/** Reset the counter. Used in tests only. */\nexport function __resetVarCounter(): void {\n counter = 0;\n}\n\n/**\n * Create a unique CSS custom property reference.\n *\n * Returns a `var(--ts-N)` string that can be used anywhere a CSS value is\n * accepted. Use assignVars() to set its value per element via inline styles.\n *\n * @example\n * ```ts\n * const cardBg = createVar();\n *\n * const card = styles.create('card', {\n * base: { background: cardBg, padding: '16px' },\n * });\n *\n * // Consumer sets the variable per instance:\n * <div className={card('base')} style={assignVars({ [cardBg]: '#ff0099' })} />\n * ```\n */\nexport function createVar(): CSSVarRef {\n const name = `--ts-${++counter}`;\n return `var(${name})` as CSSVarRef;\n}\n\n/**\n * Build a CSS custom property assignment map from var refs to values.\n *\n * The returned object is safe to spread into a React (or any framework)\n * inline `style` prop.\n *\n * @example\n * ```ts\n * assignVars({ [cardBg]: '#ff0099' })\n * // → { '--ts-1': '#ff0099' }\n * ```\n */\nexport function assignVars(\n vars: Partial<Record<CSSVarRef, string>>\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [varRef, value] of Object.entries(vars)) {\n if (value == null) continue;\n // Strip \"var(\" prefix and \")\" suffix to get the raw property name\n const match = varRef.match(/^var\\((--[^)]+)\\)$/);\n if (match) result[match[1]] = value;\n }\n return result;\n}\n","import { createStyles, compose } from './styles.js';\nimport { createTokens, useTokens, createTheme } from './tokens.js';\nimport { createKeyframes } from './keyframes.js';\nimport * as colorFns from './color.js';\nimport { getRegisteredCss, insertRules, reset, flushSync } from './sheet.js';\nimport { createComponent } from './component.js';\nimport { globalStyle, globalFontFace } from './global.js';\nimport { createVar, assignVars } from './vars.js';\n\nexport type {\n CSSProperties,\n CSSValue,\n StyleDefinitions,\n SelectorFunction,\n TokenValues,\n TokenRef,\n ThemeOverrides,\n KeyframeStops,\n VariantDefinitions,\n ComponentConfig,\n ComponentFunction,\n FontFaceProps,\n CSSVarRef,\n RecipeVariants,\n} from './types.js';\n\nexport { createVar, assignVars };\n\nexport type { ColorMixSpace } from './color.js';\n\n/**\n * Style creation API.\n *\n * @example\n * ```ts\n * const button = styles.create('button', {\n * base: { padding: '8px 16px' },\n * primary: { backgroundColor: '#0066ff' },\n * });\n *\n * <button className={button('base', 'primary')}>\n * ```\n */\nexport const styles = {\n create: createStyles,\n component: createComponent,\n compose,\n} as const;\n\n/**\n * Global CSS API for arbitrary selectors and font-face declarations.\n *\n * @example\n * ```ts\n * global.style('body', { margin: 0 });\n * global.fontFace('Inter', { src: \"url('/Inter.woff2') format('woff2')\", fontWeight: 400 });\n * ```\n */\nexport const global = {\n style: globalStyle,\n fontFace: globalFontFace,\n} as const;\n\n/**\n * Design token API using CSS custom properties.\n *\n * @example\n * ```ts\n * const color = tokens.create('color', {\n * primary: '#0066ff',\n * });\n *\n * color.primary // \"var(--color-primary)\"\n * ```\n */\nexport const tokens = {\n create: createTokens,\n use: useTokens,\n createTheme,\n} as const;\n\n/**\n * Keyframe animation API.\n *\n * @example\n * ```ts\n * const fadeIn = keyframes.create('fadeIn', {\n * from: { opacity: 0 },\n * to: { opacity: 1 },\n * });\n *\n * const card = styles.create('card', {\n * base: { animation: `${fadeIn} 300ms ease` },\n * });\n * ```\n */\nexport const keyframes = {\n create: createKeyframes,\n} as const;\n\n/**\n * Type-safe CSS color function helpers.\n *\n * Each function returns a plain CSS color string — no runtime color math.\n * Composes naturally with token references.\n *\n * @example\n * ```ts\n * color.rgb(0, 102, 255) // \"rgb(0 102 255)\"\n * color.oklch(0.7, 0.15, 250) // \"oklch(0.7 0.15 250)\"\n * color.mix(theme.primary, 'white', 20) // \"color-mix(in srgb, var(--theme-primary) 20%, white)\"\n * color.alpha(theme.primary, 0.5) // \"color-mix(in srgb, var(--theme-primary) 50%, transparent)\"\n * color.lightDark('#111', '#eee') // \"light-dark(#111, #eee)\"\n * ```\n */\nexport const color = colorFns;\n\n/**\n * Return all registered CSS as a string (for SSR).\n *\n * Returns every CSS rule registered via `styles.create`, `tokens.create`,\n * `keyframes.create`, etc. Use this in your SSR head/meta function to\n * inject styles into the document.\n *\n * This is safe to import on the client — it has no server-specific\n * dependencies and will simply return whatever CSS has been registered.\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles';\n *\n * // In a route's head function (e.g. TanStack Start):\n * export const Route = createRootRoute({\n * head: () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * }),\n * });\n * ```\n */\nexport { getRegisteredCss };\n\n/**\n * Insert multiple CSS rules into the stylesheet.\n *\n * This is a low-level API used internally by typestyles and by packages\n * like @typestyles/props. You typically won't need to use this directly.\n *\n * @example\n * ```ts\n * import { insertRules } from 'typestyles';\n *\n * insertRules([\n * { key: '.my-class', css: '.my-class { color: red; }' },\n * { key: '.another', css: '.another { padding: 8px; }' },\n * ]);\n * ```\n */\nexport { insertRules };\n\n/**\n * Testing utilities for clearing the stylesheet and flushing pending rules.\n * These are primarily intended for use in tests.\n *\n * @example\n * ```ts\n * import { reset, flushSync } from 'typestyles';\n *\n * // In a test beforeEach:\n * beforeEach(() => {\n * reset(); // Clear all registered CSS\n * });\n *\n * // To synchronously flush pending rules:\n * flushSync();\n * ```\n */\nexport { reset, flushSync };\n"]}
|
package/dist/server.d.cts
CHANGED
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { startCollection, flushSync } from './chunk-
|
|
2
|
-
export { getRegisteredCss } from './chunk-
|
|
1
|
+
import { startCollection, flushSync } from './chunk-BB7C47TQ.js';
|
|
2
|
+
export { getRegisteredCss } from './chunk-BB7C47TQ.js';
|
|
3
3
|
|
|
4
4
|
// src/server.ts
|
|
5
5
|
function collectStyles(renderFn) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typestyles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CSS-in-TypeScript that embraces CSS instead of hiding from it",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"design-tokens",
|
|
51
51
|
"css-custom-properties"
|
|
52
52
|
],
|
|
53
|
-
"license": "
|
|
53
|
+
"license": "Apache-2.0",
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|
|
56
|
-
"url": "https://github.com/
|
|
56
|
+
"url": "https://github.com/dbanksdesign/typestyles",
|
|
57
57
|
"directory": "packages/typestyles"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sheet.ts"],"names":[],"mappings":"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","file":"chunk-PFDN4Y4C.js","sourcesContent":["const STYLE_ELEMENT_ID = 'typestyles';\n\n/**\n * Tracks which CSS rules have been inserted to avoid duplicates.\n */\nconst insertedRules = new Set<string>();\n\n/**\n * Buffer of CSS rules waiting to be flushed.\n */\nlet pendingRules: string[] = [];\n\n/**\n * All CSS rules ever registered (for SSR extraction).\n * Unlike pendingRules (which is cleared on flush), this retains every rule\n * so getRegisteredCss() can return the full stylesheet at any point.\n */\nconst allRules: string[] = [];\n\n/**\n * Whether a flush is scheduled.\n */\nlet flushScheduled = false;\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * When in SSR collection mode, CSS is captured here instead of injected.\n */\nlet ssrBuffer: string[] | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser =\n typeof document !== 'undefined' && typeof window !== 'undefined';\n\nfunction getStyleElement(): HTMLStyleElement {\n if (styleElement) return styleElement;\n\n // Check for an existing element (e.g., from SSR)\n const existing = document.getElementById(\n STYLE_ELEMENT_ID\n ) as HTMLStyleElement | null;\n if (existing) {\n styleElement = existing;\n return styleElement;\n }\n\n // Create a new one\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n return styleElement;\n}\n\nfunction flush(): void {\n flushScheduled = false;\n if (pendingRules.length === 0) return;\n\n const rules = pendingRules;\n pendingRules = [];\n\n if (ssrBuffer) {\n ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n\n if (sheet) {\n for (const rule of rules) {\n try {\n sheet.insertRule(rule, sheet.cssRules.length);\n } catch {\n // Fallback: append as text (handles edge cases with certain selectors)\n el.appendChild(document.createTextNode(rule));\n }\n }\n } else {\n // Sheet not available yet, append as text\n el.appendChild(document.createTextNode(rules.join('\\n')));\n }\n}\n\nfunction scheduleFlush(): void {\n if (flushScheduled) return;\n flushScheduled = true;\n\n if (ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n scheduleFlush();\n}\n\n/**\n * Insert multiple CSS rules at once.\n */\nexport function insertRules(rules: Array<{ key: string; css: string }>): void {\n let added = false;\n for (const { key, css } of rules) {\n if (insertedRules.has(key)) continue;\n insertedRules.add(key);\n pendingRules.push(css);\n allRules.push(css);\n added = true;\n }\n if (added) scheduleFlush();\n}\n\n/**\n * Replace a CSS rule (used for HMR). Removes the old rule and inserts the new one.\n */\nexport function replaceRule(key: string, css: string): void {\n if (!isBrowser) return;\n\n insertedRules.delete(key);\n\n // Remove existing rule from the sheet if possible\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n // We can't reliably match by key in CSSOM, so for HMR we fall back to\n // clearing and re-inserting. This is fine since HMR is dev-only.\n }\n }\n\n insertRule(key, css);\n}\n\n/**\n * Start collecting CSS for SSR. Returns a function to stop collection and get the CSS.\n */\nexport function startCollection(): () => string {\n ssrBuffer = [];\n return () => {\n const css = ssrBuffer ? ssrBuffer.join('\\n') : '';\n ssrBuffer = null;\n return css;\n };\n}\n\n/**\n * Return all registered CSS as a string.\n *\n * Unlike `collectStyles`, this doesn't require wrapping a render function.\n * It simply returns every CSS rule that has been registered via\n * `styles.create`, `tokens.create`, `keyframes.create`, etc.\n *\n * Ideal for SSR frameworks that need the CSS separately from the render\n * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links).\n *\n * @example\n * ```ts\n * import { getRegisteredCss } from 'typestyles/server';\n *\n * // In a route's head/meta function:\n * export const head = () => ({\n * styles: [{ id: 'typestyles', children: getRegisteredCss() }],\n * });\n * ```\n */\nexport function getRegisteredCss(): string {\n return allRules.join('\\n');\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n insertedRules.clear();\n pendingRules = [];\n allRules.length = 0;\n flushScheduled = false;\n ssrBuffer = null;\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n}\n\n/**\n * Flush all pending rules synchronously. Used for SSR and testing.\n */\nexport function flushSync(): void {\n flush();\n}\n\n/**\n * Invalidate all dedup keys that start with the given prefix.\n * Also removes matching rules from the live stylesheet.\n * Used for HMR — allows modules to re-register their styles after editing.\n */\nexport function invalidatePrefix(prefix: string): void {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n if (ruleMatchesPrefix(rule, prefix)) {\n sheet.deleteRule(i);\n }\n }\n}\n\n/**\n * Invalidate a list of exact keys or prefixes.\n * Each entry in `keys` is treated as an exact key match.\n * Each entry in `prefixes` is treated as a prefix match.\n * Used for HMR to invalidate all styles from a module at once.\n */\nexport function invalidateKeys(keys: string[], prefixes: string[]): void {\n for (const key of keys) {\n insertedRules.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of insertedRules) {\n if (key.startsWith(prefix)) {\n insertedRules.delete(key);\n }\n }\n }\n\n if (!isBrowser) return;\n\n const el = styleElement;\n if (!el) return;\n const sheet = el.sheet;\n if (!sheet) return;\n\n const keySet = new Set(keys);\n for (let i = sheet.cssRules.length - 1; i >= 0; i--) {\n const rule = sheet.cssRules[i];\n let shouldRemove = false;\n\n for (const prefix of prefixes) {\n if (ruleMatchesPrefix(rule, prefix)) {\n shouldRemove = true;\n break;\n }\n }\n\n if (!shouldRemove) {\n // Check exact key matches — for tokens/themes/keyframes,\n // we match based on rule content patterns\n const ruleText = rule.cssText;\n for (const key of keySet) {\n if (ruleMatchesKey(ruleText, key)) {\n shouldRemove = true;\n break;\n }\n }\n }\n\n if (shouldRemove) {\n sheet.deleteRule(i);\n }\n }\n}\n\nfunction ruleMatchesPrefix(rule: CSSRule, prefix: string): boolean {\n if (prefix.startsWith('font-face:')) {\n const family = prefix.slice('font-face:'.length).split(':')[0];\n // CSSFontFaceRule has type 5 and cssText contains @font-face\n if (rule.cssText.includes('@font-face')) {\n return (\n rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`)\n );\n }\n return false;\n }\n if ('selectorText' in rule) {\n return (rule as CSSStyleRule).selectorText.startsWith(prefix);\n }\n if ('name' in rule && prefix.startsWith('keyframes:')) {\n return (rule as CSSKeyframesRule).name === prefix.slice('keyframes:'.length);\n }\n // For at-rules wrapping style rules, check inner rules\n if ('cssRules' in rule) {\n const innerRules = (rule as CSSGroupingRule).cssRules;\n for (let i = 0; i < innerRules.length; i++) {\n if (ruleMatchesPrefix(innerRules[i], prefix)) return true;\n }\n }\n return false;\n}\n\nfunction ruleMatchesKey(cssText: string, key: string): boolean {\n if (key.startsWith('tokens:')) {\n // tokens:color -> :root rule with --color- custom properties\n const namespace = key.slice('tokens:'.length);\n return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`);\n }\n if (key.startsWith('theme:')) {\n // theme:dark -> .theme-dark selector\n const name = key.slice('theme:'.length);\n return cssText.includes(`.theme-${name}`);\n }\n if (key.startsWith('keyframes:')) {\n const name = key.slice('keyframes:'.length);\n return cssText.includes(`@keyframes ${name}`);\n }\n return false;\n}\n"]}
|