typestyles
Advanced tools
| // src/sheet-context.ts | ||
| function createSheetState() { | ||
| return { | ||
| insertedRules: /* @__PURE__ */ new Set(), | ||
| ruleCssByKey: /* @__PURE__ */ new Map(), | ||
| pendingRules: [], | ||
| allRules: [], | ||
| flushScheduled: false, | ||
| ssrBuffer: null | ||
| }; | ||
| } | ||
| function resetSheetState(state) { | ||
| state.insertedRules.clear(); | ||
| state.ruleCssByKey.clear(); | ||
| state.pendingRules = []; | ||
| state.allRules.length = 0; | ||
| state.flushScheduled = false; | ||
| state.ssrBuffer = null; | ||
| } | ||
| var globalSheetState = createSheetState(); | ||
| var getStoreImpl = () => globalSheetState; | ||
| var runIsolatedImpl = (fn) => fn(); | ||
| function configureSheetIsolation(config) { | ||
| getStoreImpl = config.getStore; | ||
| runIsolatedImpl = config.runIsolated; | ||
| } | ||
| function getSheetState() { | ||
| return getStoreImpl(); | ||
| } | ||
| function getGlobalSheetState() { | ||
| return globalSheetState; | ||
| } | ||
| function runWithIsolatedSheet(fn) { | ||
| return runIsolatedImpl(fn); | ||
| } | ||
| // src/registry.ts | ||
| var registeredNamespaces = /* @__PURE__ */ new Set(); | ||
| var emittedClassNameOwners = /* @__PURE__ */ new Map(); | ||
| function isDev() { | ||
| return typeof process === "undefined" || process.env.NODE_ENV !== "production"; | ||
| } | ||
| function trackEmittedClassName(className, ownerKey) { | ||
| if (!isDev()) return; | ||
| const existing = emittedClassNameOwners.get(className); | ||
| if (existing !== void 0 && existing !== ownerKey) { | ||
| console.error( | ||
| `[typestyles] Class name collision: ".${className}" is generated by two different style definitions (${existing} and ${ownerKey}). Their CSS rules will overwrite each other. Use distinct namespaces, or isolate each package/file with createStyles({ scopeId: '\u2026' }) (or fileScopeId(import.meta)).` | ||
| ); | ||
| return; | ||
| } | ||
| emittedClassNameOwners.set(className, ownerKey); | ||
| } | ||
| function resetEmittedClassNameTracking() { | ||
| emittedClassNameOwners.clear(); | ||
| warnedUnscopedNamespaces.clear(); | ||
| } | ||
| var warnedUnscopedNamespaces = /* @__PURE__ */ new Set(); | ||
| function warnUnscopedCollision(namespace, apiName) { | ||
| if (!isDev()) return; | ||
| if (warnedUnscopedNamespaces.has(namespace)) return; | ||
| warnedUnscopedNamespaces.add(namespace); | ||
| console.warn( | ||
| `[typestyles] ${apiName}('${namespace}', \u2026) was registered more than once without a scopeId. Their CSS rules will overwrite each other. Isolate each definition with createStyles({ scopeId: '\u2026' }) or createTypeStyles({ scopeId: '\u2026' }). If this is caused by HMR re-execution, this warning is safe to ignore.` | ||
| ); | ||
| } | ||
| var COLON = ":"; | ||
| function releaseReservedNamespacesForComponentOrClassNames(namespaces) { | ||
| if (namespaces.length === 0) return; | ||
| const wanted = new Set(namespaces); | ||
| const toRemove = []; | ||
| for (const key of registeredNamespaces) { | ||
| const i = key.indexOf(COLON); | ||
| if (i === -1) continue; | ||
| if (wanted.has(key.slice(i + 1))) { | ||
| toRemove.push(key); | ||
| } | ||
| } | ||
| for (const key of toRemove) { | ||
| registeredNamespaces.delete(key); | ||
| } | ||
| } | ||
| function namespacesFromTypestylesHmrPrefixes(prefixes) { | ||
| const out = []; | ||
| for (const p of prefixes) { | ||
| if (p.length >= 2 && p.startsWith(".") && p.endsWith("-")) { | ||
| out.push(p.slice(1, -1)); | ||
| } | ||
| } | ||
| return out; | ||
| } | ||
| // src/sheet.ts | ||
| var TYPESTYLES_STYLE_ID = "typestyles"; | ||
| var TYPESTYLES_FALLBACK_STYLE_ID = "typestyles-fallback"; | ||
| var STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID; | ||
| var FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID; | ||
| function duplicateRuleKeyConflictWarningsEnabled() { | ||
| if (typeof process === "undefined") return true; | ||
| return process.env.NODE_ENV !== "production"; | ||
| } | ||
| function warnIfDuplicateRuleKeyConflict(key, previousCss, ignoredCss) { | ||
| if (!duplicateRuleKeyConflictWarningsEnabled()) return; | ||
| const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}\u2026` : previousCss; | ||
| const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}\u2026` : ignoredCss; | ||
| console.warn( | ||
| `[typestyles] Skipped a rule: dedupe key "${key}" already exists with different CSS. Only the first registration is kept. For globals, merge into one \`global.style\`, or use a distinct selector (e.g. \`html body\` after reset\u2019s \`body\`). | ||
| Existing: ${prevShort} | ||
| Skipped: ${nextShort}` | ||
| ); | ||
| } | ||
| function readNextPublicRuntimeDisabled() { | ||
| if (typeof process === "undefined" || !process.env) return false; | ||
| return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === "true"; | ||
| } | ||
| var RUNTIME_DISABLED = typeof __TYPESTYLES_RUNTIME_DISABLED__ !== "undefined" && __TYPESTYLES_RUNTIME_DISABLED__ === "true" || readNextPublicRuntimeDisabled(); | ||
| var styleElement = null; | ||
| var fallbackStyleElement = null; | ||
| var isBrowser = typeof document !== "undefined" && typeof window !== "undefined"; | ||
| function writeAllRulesToStyleElement(el) { | ||
| const { allRules } = getSheetState(); | ||
| if (RUNTIME_DISABLED || allRules.length === 0) return; | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| for (const css of allRules) { | ||
| try { | ||
| sheet.insertRule(css, sheet.cssRules.length); | ||
| } catch { | ||
| appendFallbackRule(css); | ||
| } | ||
| } | ||
| } else { | ||
| appendFallbackRule(allRules.join("\n")); | ||
| } | ||
| } | ||
| function getStyleElement() { | ||
| let reconnectAfterDetach = false; | ||
| if (styleElement && !styleElement.isConnected) { | ||
| reconnectAfterDetach = true; | ||
| styleElement = null; | ||
| } | ||
| if (styleElement) return styleElement; | ||
| const existing = document.getElementById(STYLE_ELEMENT_ID); | ||
| if (existing?.isConnected) { | ||
| styleElement = existing; | ||
| return styleElement; | ||
| } | ||
| styleElement = document.createElement("style"); | ||
| styleElement.id = STYLE_ELEMENT_ID; | ||
| document.head.appendChild(styleElement); | ||
| if (reconnectAfterDetach && getSheetState().allRules.length > 0) { | ||
| writeAllRulesToStyleElement(styleElement); | ||
| } | ||
| return styleElement; | ||
| } | ||
| function getFallbackStyleElement() { | ||
| if (fallbackStyleElement && !fallbackStyleElement.isConnected) { | ||
| fallbackStyleElement = null; | ||
| } | ||
| if (fallbackStyleElement) return fallbackStyleElement; | ||
| const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID); | ||
| if (existing?.isConnected) { | ||
| fallbackStyleElement = existing; | ||
| return fallbackStyleElement; | ||
| } | ||
| const main = getStyleElement(); | ||
| fallbackStyleElement = document.createElement("style"); | ||
| fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID; | ||
| main.insertAdjacentElement("afterend", fallbackStyleElement); | ||
| return fallbackStyleElement; | ||
| } | ||
| function appendFallbackRule(css) { | ||
| const el = getFallbackStyleElement(); | ||
| el.appendChild(document.createTextNode(`${css} | ||
| `)); | ||
| } | ||
| function ensureDocumentStylesAttached() { | ||
| if (!isBrowser || RUNTIME_DISABLED) return; | ||
| getStyleElement(); | ||
| } | ||
| function flush() { | ||
| const state = getSheetState(); | ||
| state.flushScheduled = false; | ||
| if (state.pendingRules.length === 0) return; | ||
| const rules = state.pendingRules; | ||
| state.pendingRules = []; | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer.push(...rules); | ||
| return; | ||
| } | ||
| if (!isBrowser || RUNTIME_DISABLED) return; | ||
| const el = getStyleElement(); | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| for (const rule of rules) { | ||
| try { | ||
| sheet.insertRule(rule, sheet.cssRules.length); | ||
| } catch { | ||
| appendFallbackRule(rule); | ||
| } | ||
| } | ||
| } else { | ||
| appendFallbackRule(rules.join("\n")); | ||
| } | ||
| } | ||
| function scheduleFlush() { | ||
| const state = getSheetState(); | ||
| if (state.flushScheduled) return; | ||
| state.flushScheduled = true; | ||
| if (state.ssrBuffer) { | ||
| flush(); | ||
| return; | ||
| } | ||
| if (isBrowser && !RUNTIME_DISABLED) { | ||
| queueMicrotask(flush); | ||
| } | ||
| } | ||
| function registerCascadeLayerOrder(preambleKey, css) { | ||
| const state = getSheetState(); | ||
| const key = `typestyles:@layer-order:${preambleKey}`; | ||
| if (state.insertedRules.has(key)) return; | ||
| state.insertedRules.add(key); | ||
| state.allRules.unshift(css); | ||
| notifyRegisteredCssChanged(); | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer.unshift(css); | ||
| return; | ||
| } | ||
| if (RUNTIME_DISABLED) return; | ||
| if (!isBrowser) return; | ||
| const el = getStyleElement(); | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| try { | ||
| sheet.insertRule(css, 0); | ||
| } catch { | ||
| prependFallbackRule(css); | ||
| } | ||
| } else { | ||
| prependFallbackRule(css); | ||
| } | ||
| } | ||
| function prependFallbackRule(css) { | ||
| const el = getFallbackStyleElement(); | ||
| el.insertBefore(document.createTextNode(`${css} | ||
| `), el.firstChild); | ||
| } | ||
| function insertRule(key, css) { | ||
| const state = getSheetState(); | ||
| if (state.insertedRules.has(key)) { | ||
| const prev = state.ruleCssByKey.get(key); | ||
| if (prev != null && prev !== css) { | ||
| warnIfDuplicateRuleKeyConflict(key, prev, css); | ||
| } | ||
| return; | ||
| } | ||
| state.insertedRules.add(key); | ||
| state.ruleCssByKey.set(key, css); | ||
| state.allRules.push(css); | ||
| notifyRegisteredCssChanged(); | ||
| if (RUNTIME_DISABLED && !state.ssrBuffer) return; | ||
| state.pendingRules.push(css); | ||
| scheduleFlush(); | ||
| } | ||
| function insertRules(rules) { | ||
| const state = getSheetState(); | ||
| let added = false; | ||
| let registered = false; | ||
| for (const { key, css } of rules) { | ||
| if (state.insertedRules.has(key)) { | ||
| const prev = state.ruleCssByKey.get(key); | ||
| if (prev != null && prev !== css) { | ||
| warnIfDuplicateRuleKeyConflict(key, prev, css); | ||
| } | ||
| continue; | ||
| } | ||
| state.insertedRules.add(key); | ||
| state.ruleCssByKey.set(key, css); | ||
| state.allRules.push(css); | ||
| registered = true; | ||
| if (!RUNTIME_DISABLED || state.ssrBuffer) { | ||
| state.pendingRules.push(css); | ||
| added = true; | ||
| } | ||
| } | ||
| if (registered) notifyRegisteredCssChanged(); | ||
| if (added) scheduleFlush(); | ||
| } | ||
| function startCollection() { | ||
| const state = getSheetState(); | ||
| state.ssrBuffer = []; | ||
| return () => { | ||
| const css = state.ssrBuffer ? state.ssrBuffer.join("\n") : ""; | ||
| state.ssrBuffer = null; | ||
| return css; | ||
| }; | ||
| } | ||
| function getRegisteredCss() { | ||
| return getSheetState().allRules.join("\n"); | ||
| } | ||
| var registeredCssListeners = /* @__PURE__ */ new Set(); | ||
| function notifyRegisteredCssChanged() { | ||
| for (const listener of registeredCssListeners) { | ||
| listener(); | ||
| } | ||
| } | ||
| function subscribeRegisteredCss(listener) { | ||
| registeredCssListeners.add(listener); | ||
| return () => { | ||
| registeredCssListeners.delete(listener); | ||
| }; | ||
| } | ||
| function reset() { | ||
| resetSheetState(getGlobalSheetState()); | ||
| const active = getSheetState(); | ||
| if (active !== getGlobalSheetState()) { | ||
| resetSheetState(active); | ||
| } | ||
| registeredNamespaces.clear(); | ||
| resetEmittedClassNameTracking(); | ||
| notifyRegisteredCssChanged(); | ||
| if (isBrowser && styleElement) { | ||
| styleElement.remove(); | ||
| styleElement = null; | ||
| } | ||
| if (isBrowser && fallbackStyleElement) { | ||
| fallbackStyleElement.remove(); | ||
| fallbackStyleElement = null; | ||
| } | ||
| } | ||
| function flushSync() { | ||
| flush(); | ||
| } | ||
| function pruneRemovedCss(state, removedCss) { | ||
| if (removedCss.size === 0) return; | ||
| state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css)); | ||
| state.allRules = state.allRules.filter((css) => !removedCss.has(css)); | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css)); | ||
| } | ||
| } | ||
| function invalidatePrefix(prefix) { | ||
| const state = getSheetState(); | ||
| const removedCss = /* @__PURE__ */ new Set(); | ||
| for (const key of state.insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| pruneRemovedCss(state, removedCss); | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix])); | ||
| if (!isBrowser) return; | ||
| const el = styleElement; | ||
| if (!el) return; | ||
| const sheet = el.sheet; | ||
| if (!sheet) return; | ||
| for (let i = sheet.cssRules.length - 1; i >= 0; i--) { | ||
| const rule = sheet.cssRules[i]; | ||
| if (ruleMatchesPrefix(rule, prefix)) { | ||
| sheet.deleteRule(i); | ||
| } | ||
| } | ||
| } | ||
| function invalidateKeys(keys, prefixes) { | ||
| const state = getSheetState(); | ||
| const removedCss = /* @__PURE__ */ new Set(); | ||
| for (const key of keys) { | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| for (const prefix of prefixes) { | ||
| for (const key of state.insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| } | ||
| pruneRemovedCss(state, removedCss); | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes)); | ||
| if (!isBrowser) return; | ||
| const el = styleElement; | ||
| if (!el) return; | ||
| const sheet = el.sheet; | ||
| if (!sheet) return; | ||
| const keySet = new Set(keys); | ||
| for (let i = sheet.cssRules.length - 1; i >= 0; i--) { | ||
| const rule = sheet.cssRules[i]; | ||
| let shouldRemove = false; | ||
| for (const prefix of prefixes) { | ||
| if (ruleMatchesPrefix(rule, prefix)) { | ||
| shouldRemove = true; | ||
| break; | ||
| } | ||
| } | ||
| if (!shouldRemove) { | ||
| const ruleText = rule.cssText; | ||
| for (const key of keySet) { | ||
| if (ruleMatchesKey(ruleText, key)) { | ||
| shouldRemove = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (shouldRemove) { | ||
| sheet.deleteRule(i); | ||
| } | ||
| } | ||
| } | ||
| function invalidateComponentNamespaceForDev(namespace, emittedClassPrefix) { | ||
| const selectorInfix = `.${emittedClassPrefix ?? `${namespace}-`}`; | ||
| const state = getSheetState(); | ||
| const keysToDrop = []; | ||
| for (const k of state.insertedRules) { | ||
| if (k.includes(selectorInfix)) { | ||
| keysToDrop.push(k); | ||
| } | ||
| } | ||
| invalidateKeys(keysToDrop, [selectorInfix]); | ||
| } | ||
| function invalidateClassNamespaceForDev(emittedClassName) { | ||
| if (!emittedClassName) return; | ||
| const selectorInfix = `.${emittedClassName}`; | ||
| const state = getSheetState(); | ||
| const keysToDrop = []; | ||
| for (const k of state.insertedRules) { | ||
| if (k.includes(selectorInfix)) { | ||
| keysToDrop.push(k); | ||
| } | ||
| } | ||
| invalidateKeys(keysToDrop, [selectorInfix]); | ||
| } | ||
| function ruleMatchesPrefix(rule, prefix) { | ||
| if (prefix.startsWith("font-face:")) { | ||
| const family = prefix.slice("font-face:".length).split(":")[0]; | ||
| if (rule.cssText.includes("@font-face")) { | ||
| return rule.cssText.includes(`"${family}"`) || rule.cssText.includes(`'${family}'`); | ||
| } | ||
| return false; | ||
| } | ||
| if ("selectorText" in rule) { | ||
| return rule.selectorText.startsWith(prefix); | ||
| } | ||
| if ("name" in rule && prefix.startsWith("keyframes:")) { | ||
| return rule.name === prefix.slice("keyframes:".length); | ||
| } | ||
| if ("cssRules" in rule) { | ||
| const innerRules = rule.cssRules; | ||
| for (let i = 0; i < innerRules.length; i++) { | ||
| if (ruleMatchesPrefix(innerRules[i], prefix)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| function ruleMatchesKey(cssText, key) { | ||
| if (key.startsWith("tokens:")) { | ||
| const rest = key.slice("tokens:".length); | ||
| const at = rest.lastIndexOf("@"); | ||
| const namespace = at === -1 ? rest : rest.slice(0, at); | ||
| return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`); | ||
| } | ||
| if (key.startsWith("theme:")) { | ||
| const name = key.slice("theme:".length); | ||
| return cssText.includes(`.theme-${name}`); | ||
| } | ||
| if (key.startsWith("keyframes:")) { | ||
| const name = key.slice("keyframes:".length); | ||
| return cssText.includes(`@keyframes ${name}`); | ||
| } | ||
| return false; | ||
| } | ||
| export { TYPESTYLES_STYLE_ID, configureSheetIsolation, createSheetState, ensureDocumentStylesAttached, flushSync, getGlobalSheetState, getRegisteredCss, insertRule, insertRules, invalidateClassNamespaceForDev, invalidateComponentNamespaceForDev, invalidateKeys, invalidatePrefix, registerCascadeLayerOrder, registeredNamespaces, reset, runWithIsolatedSheet, startCollection, subscribeRegisteredCss, trackEmittedClassName, warnUnscopedCollision }; | ||
| //# sourceMappingURL=chunk-5CMEHXCU.js.map | ||
| //# sourceMappingURL=chunk-5CMEHXCU.js.map |
| {"version":3,"sources":["../src/sheet-context.ts","../src/registry.ts","../src/sheet.ts"],"names":[],"mappings":"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","file":"chunk-5CMEHXCU.js","sourcesContent":["export type SheetState = {\n insertedRules: Set<string>;\n ruleCssByKey: Map<string, string>;\n pendingRules: string[];\n allRules: string[];\n flushScheduled: boolean;\n ssrBuffer: string[] | null;\n};\n\nexport function createSheetState(): SheetState {\n return {\n insertedRules: new Set(),\n ruleCssByKey: new Map(),\n pendingRules: [],\n allRules: [],\n flushScheduled: false,\n ssrBuffer: null,\n };\n}\n\nexport function resetSheetState(state: SheetState): void {\n state.insertedRules.clear();\n state.ruleCssByKey.clear();\n state.pendingRules = [];\n state.allRules.length = 0;\n state.flushScheduled = false;\n state.ssrBuffer = null;\n}\n\nconst globalSheetState = createSheetState();\n\nlet getStoreImpl: () => SheetState = () => globalSheetState;\nlet runIsolatedImpl: <T>(fn: () => T) => T = (fn) => fn();\n\n/** Register Node AsyncLocalStorage isolation (see `sheet-node.ts`). */\nexport function configureSheetIsolation(config: {\n getStore: () => SheetState;\n runIsolated: <T>(fn: () => T) => T;\n}): void {\n getStoreImpl = config.getStore;\n runIsolatedImpl = config.runIsolated;\n}\n\nexport function getSheetState(): SheetState {\n return getStoreImpl();\n}\n\nexport function getGlobalSheetState(): SheetState {\n return globalSheetState;\n}\n\n/** Run `fn` with a fresh sheet store on Node (no-op in the browser bundle). */\nexport function runWithIsolatedSheet<T>(fn: () => T): T {\n return runIsolatedImpl(fn);\n}\n","/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n\n/**\n * Development-only map of emitted class name → owner key. Two different owners\n * producing the same class string means rules will overwrite each other —\n * either a cross-scope semantic collision or a hash collision in\n * `hashed`/`compact` mode.\n */\nconst emittedClassNameOwners = new Map<string, string>();\n\nfunction isDev(): boolean {\n return typeof process === 'undefined' || process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Track an emitted class name and warn when the same class string is produced\n * by two different style definitions. Development-only; no-op in production.\n *\n * The owner key identifies the logical definition (`scope:namespace` for\n * `styles.class` / `styles.component`, payload-derived for `styles.hashClass`)\n * so HMR re-registrations of the same definition are not flagged.\n */\nexport function trackEmittedClassName(className: string, ownerKey: string): void {\n if (!isDev()) return;\n const existing = emittedClassNameOwners.get(className);\n if (existing !== undefined && existing !== ownerKey) {\n console.error(\n `[typestyles] Class name collision: \".${className}\" is generated by two different ` +\n `style definitions (${existing} and ${ownerKey}). Their CSS rules will overwrite ` +\n `each other. Use distinct namespaces, or isolate each package/file with ` +\n `createStyles({ scopeId: '…' }) (or fileScopeId(import.meta)).`,\n );\n return;\n }\n emittedClassNameOwners.set(className, ownerKey);\n}\n\n/** Clear collision tracking. Used by `reset()` in tests. */\nexport function resetEmittedClassNameTracking(): void {\n emittedClassNameOwners.clear();\n warnedUnscopedNamespaces.clear();\n}\n\n/**\n * Namespaces that have already emitted an unscoped-collision warning.\n * Prevents duplicate warnings for the same namespace during a session.\n */\nconst warnedUnscopedNamespaces = new Set<string>();\n\n/**\n * Dev-mode warning when the same namespace is registered more than once\n * without a `scopeId`. Two unscoped registrations of the same namespace\n * produce identical class names whose CSS rules silently overwrite each\n * other. Emits once per namespace.\n */\nexport function warnUnscopedCollision(namespace: string, apiName: string): void {\n if (!isDev()) return;\n if (warnedUnscopedNamespaces.has(namespace)) return;\n warnedUnscopedNamespaces.add(namespace);\n console.warn(\n `[typestyles] ${apiName}('${namespace}', …) was registered more than once without a ` +\n `scopeId. Their CSS rules will overwrite each other. Isolate each definition with ` +\n `createStyles({ scopeId: '…' }) or createTypeStyles({ scopeId: '…' }). ` +\n `If this is caused by HMR re-execution, this warning is safe to ignore.`,\n );\n}\n\nconst COLON = ':';\n\n/**\n * Drop reserved `scopeId:namespace` keys so a module can re-register after HMR.\n * `namespace` is the first argument to `styles.component()` / `styles.class()` (not the scope).\n */\nexport function releaseReservedNamespacesForComponentOrClassNames(\n namespaces: readonly string[],\n): void {\n if (namespaces.length === 0) return;\n const wanted = new Set(namespaces);\n const toRemove: string[] = [];\n for (const key of registeredNamespaces) {\n const i = key.indexOf(COLON);\n if (i === -1) continue;\n if (wanted.has(key.slice(i + 1))) {\n toRemove.push(key);\n }\n }\n for (const key of toRemove) {\n registeredNamespaces.delete(key);\n }\n}\n\n/** Vite plugin passes `.${namespace}-` prefixes for `styles.component()` invalidation. */\nexport function namespacesFromTypestylesHmrPrefixes(prefixes: readonly string[]): string[] {\n const out: string[] = [];\n for (const p of prefixes) {\n if (p.length >= 2 && p.startsWith('.') && p.endsWith('-')) {\n out.push(p.slice(1, -1));\n }\n }\n return out;\n}\n","import {\n namespacesFromTypestylesHmrPrefixes,\n registeredNamespaces,\n releaseReservedNamespacesForComponentOrClassNames,\n resetEmittedClassNameTracking,\n} from './registry';\nimport {\n getSheetState,\n getGlobalSheetState,\n resetSheetState,\n type SheetState,\n} from './sheet-context';\n\n/** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */\nexport const TYPESTYLES_STYLE_ID = 'typestyles';\n\n/**\n * Stable id for the text-fallback `<style>` element. Rules the CSSOM rejects\n * via `insertRule` land here as text. They must never be appended as text to\n * the main element: mutating a `<style>` element's text makes the browser\n * re-parse the element from its text content, discarding every rule that was\n * previously added through `insertRule` — one rejected rule would wipe the\n * entire runtime sheet.\n */\nexport const TYPESTYLES_FALLBACK_STYLE_ID = 'typestyles-fallback';\n\nconst STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID;\nconst FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID;\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * The managed text-fallback <style> element, lazily created (see\n * {@link TYPESTYLES_FALLBACK_STYLE_ID}).\n */\nlet fallbackStyleElement: HTMLStyleElement | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n const { allRules } = getSheetState();\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n appendFallbackRule(css);\n }\n }\n } else {\n appendFallbackRule(allRules.join('\\n'));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && getSheetState().allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * The fallback element mirrors the main element's lifecycle: reuse a connected\n * element by id, recover from detachment (doc swaps), and keep a deterministic\n * position immediately after the main element so cascade order stays stable.\n */\nfunction getFallbackStyleElement(): HTMLStyleElement {\n if (fallbackStyleElement && !fallbackStyleElement.isConnected) {\n fallbackStyleElement = null;\n }\n if (fallbackStyleElement) return fallbackStyleElement;\n\n const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n fallbackStyleElement = existing;\n return fallbackStyleElement;\n }\n\n const main = getStyleElement();\n fallbackStyleElement = document.createElement('style');\n fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID;\n main.insertAdjacentElement('afterend', fallbackStyleElement);\n return fallbackStyleElement;\n}\n\n/**\n * Append a rule the CSSOM rejected as text to the fallback element. The\n * fallback element only ever holds text (never `insertRule`), so re-parsing\n * it on append cannot lose rules.\n */\nfunction appendFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.appendChild(document.createTextNode(`${css}\\n`));\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\n}\n\nfunction flush(): void {\n const state = getSheetState();\n state.flushScheduled = false;\n if (state.pendingRules.length === 0) return;\n\n const rules = state.pendingRules;\n state.pendingRules = [];\n\n if (state.ssrBuffer) {\n state.ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser || RUNTIME_DISABLED) 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 on the dedicated fallback element (handles\n // edge cases with certain selectors) — never on `el`, where the text\n // re-parse would discard all previously inserted CSSOM rules.\n appendFallbackRule(rule);\n }\n }\n } else {\n // Sheet not available yet, append as text\n appendFallbackRule(rules.join('\\n'));\n }\n}\n\nfunction scheduleFlush(): void {\n const state = getSheetState();\n if (state.flushScheduled) return;\n state.flushScheduled = true;\n\n if (state.ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const state = getSheetState();\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (state.insertedRules.has(key)) return;\n state.insertedRules.add(key);\n\n state.allRules.unshift(css);\n notifyRegisteredCssChanged();\n\n if (state.ssrBuffer) {\n state.ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n prependFallbackRule(css);\n }\n } else {\n prependFallbackRule(css);\n }\n}\n\n/** Front-insert for the `@layer` order preamble when the CSSOM rejects it. */\nfunction prependFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n const state = getSheetState();\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n notifyRegisteredCssChanged();\n if (RUNTIME_DISABLED && !state.ssrBuffer) return;\n state.pendingRules.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 const state = getSheetState();\n let added = false;\n let registered = false;\n for (const { key, css } of rules) {\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n registered = true;\n if (!RUNTIME_DISABLED || state.ssrBuffer) {\n state.pendingRules.push(css);\n added = true;\n }\n }\n if (registered) notifyRegisteredCssChanged();\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 || RUNTIME_DISABLED) return;\n\n const state = getSheetState();\n state.insertedRules.delete(key);\n state.ruleCssByKey.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 const state = getSheetState();\n state.ssrBuffer = [];\n return () => {\n const css = state.ssrBuffer ? state.ssrBuffer.join('\\n') : '';\n state.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.component`, `styles.class`, `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 getSheetState().allRules.join('\\n');\n}\n\nconst registeredCssListeners = new Set<() => void>();\n\nfunction notifyRegisteredCssChanged(): void {\n for (const listener of registeredCssListeners) {\n listener();\n }\n}\n\n/**\n * Subscribe to changes in the registered CSS (`getRegisteredCss()`).\n * Returns an unsubscribe function. Compatible with `useSyncExternalStore`.\n *\n * @example\n * ```ts\n * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server';\n *\n * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss);\n * ```\n */\nexport function subscribeRegisteredCss(listener: () => void): () => void {\n registeredCssListeners.add(listener);\n return () => {\n registeredCssListeners.delete(listener);\n };\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n resetSheetState(getGlobalSheetState());\n const active = getSheetState();\n if (active !== getGlobalSheetState()) {\n resetSheetState(active);\n }\n registeredNamespaces.clear();\n resetEmittedClassNameTracking();\n notifyRegisteredCssChanged();\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n if (isBrowser && fallbackStyleElement) {\n fallbackStyleElement.remove();\n fallbackStyleElement = 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 * Drop CSS text queued in `pendingRules` / `allRules` / an active `ssrBuffer` for rules whose\n * key was just invalidated. Without this, re-registering a namespace before its first\n * registration has flushed (no intervening `flushSync()` / microtask) leaves the stale CSS\n * sitting in these arrays — `insertedRules` no longer references it, so it's never deduped, and\n * it gets flushed alongside the new CSS as a duplicate, conflicting rule.\n */\nfunction pruneRemovedCss(state: SheetState, removedCss: ReadonlySet<string>): void {\n if (removedCss.size === 0) return;\n state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css));\n state.allRules = state.allRules.filter((css) => !removedCss.has(css));\n if (state.ssrBuffer) {\n state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css));\n }\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of keys) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(\n namespace: string,\n emittedClassPrefix?: string,\n): void {\n const selectorInfix = `.${emittedClassPrefix ?? `${namespace}-`}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\n}\n\n/**\n * Drop every rule key tied to a `styles.class('name', …)` registration — the base selector plus\n * any pseudo/nested/at-rule-wrapped variants — and release the reserved namespace entry. Used for\n * Vite HMR and for dev recovery when a module re-runs before `hot.dispose`, including\n * multi-environment SSR setups (e.g. the Vite Environment API, or RSC frameworks like Waku) that\n * re-evaluate the same source module once per environment within a single process.\n *\n * No-op when `emittedClassName` is `undefined` (hashed/compact/atomic modes derive the class name\n * from the serialized properties, so there's no reliable selector to invalidate ahead of time —\n * same limitation `invalidateComponentNamespaceForDev` has for those modes).\n */\nexport function invalidateClassNamespaceForDev(emittedClassName?: string): void {\n if (!emittedClassName) return;\n const selectorInfix = `.${emittedClassName}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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"]} |
| import { __export } from './chunk-PZ5AY32C.js'; | ||
| // src/color.ts | ||
| var color_exports = {}; | ||
| __export(color_exports, { | ||
| alpha: () => alpha, | ||
| hsl: () => hsl, | ||
| hwb: () => hwb, | ||
| lab: () => lab, | ||
| lch: () => lch, | ||
| lightDark: () => lightDark, | ||
| mix: () => mix, | ||
| oklab: () => oklab, | ||
| oklch: () => oklch, | ||
| rgb: () => rgb | ||
| }); | ||
| function rgb(r, g, b, alpha2) { | ||
| if (alpha2 != null) return `rgb(${r} ${g} ${b} / ${alpha2})`; | ||
| return `rgb(${r} ${g} ${b})`; | ||
| } | ||
| function hsl(h, s, l, alpha2) { | ||
| if (alpha2 != null) return `hsl(${h} ${s} ${l} / ${alpha2})`; | ||
| return `hsl(${h} ${s} ${l})`; | ||
| } | ||
| function oklch(l, c, h, alpha2) { | ||
| if (alpha2 != null) return `oklch(${l} ${c} ${h} / ${alpha2})`; | ||
| return `oklch(${l} ${c} ${h})`; | ||
| } | ||
| function oklab(l, a, b, alpha2) { | ||
| if (alpha2 != null) return `oklab(${l} ${a} ${b} / ${alpha2})`; | ||
| return `oklab(${l} ${a} ${b})`; | ||
| } | ||
| function lab(l, a, b, alpha2) { | ||
| if (alpha2 != null) return `lab(${l} ${a} ${b} / ${alpha2})`; | ||
| return `lab(${l} ${a} ${b})`; | ||
| } | ||
| function lch(l, c, h, alpha2) { | ||
| if (alpha2 != null) return `lch(${l} ${c} ${h} / ${alpha2})`; | ||
| return `lch(${l} ${c} ${h})`; | ||
| } | ||
| function hwb(h, w, b, alpha2) { | ||
| if (alpha2 != null) return `hwb(${h} ${w} ${b} / ${alpha2})`; | ||
| return `hwb(${h} ${w} ${b})`; | ||
| } | ||
| function mix(color1, color2, percentage, colorSpace = "srgb") { | ||
| const c1 = percentage != null ? `${color1} ${percentage}%` : color1; | ||
| return `color-mix(in ${colorSpace}, ${c1}, ${color2})`; | ||
| } | ||
| function lightDark(lightColor, darkColor) { | ||
| return `light-dark(${lightColor}, ${darkColor})`; | ||
| } | ||
| function alpha(colorValue, opacity, colorSpace = "srgb") { | ||
| const percentage = Math.round(opacity * 100); | ||
| return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`; | ||
| } | ||
| export { alpha, color_exports, hsl, hwb, lab, lch, lightDark, mix, oklab, oklch, rgb }; | ||
| //# sourceMappingURL=chunk-U3WMOSLD.js.map | ||
| //# sourceMappingURL=chunk-U3WMOSLD.js.map |
| {"version":3,"sources":["../src/color.ts"],"names":["alpha"],"mappings":"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","file":"chunk-U3WMOSLD.js","sourcesContent":["/**\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 { configureSheetIsolation, createSheetState, getGlobalSheetState } from './chunk-5CMEHXCU.js'; | ||
| import { AsyncLocalStorage } from 'async_hooks'; | ||
| var sheetStorage = new AsyncLocalStorage(); | ||
| configureSheetIsolation({ | ||
| getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(), | ||
| runIsolated: (fn) => sheetStorage.run(createSheetState(), fn) | ||
| }); | ||
| //# sourceMappingURL=chunk-Z4UVRQXZ.js.map | ||
| //# sourceMappingURL=chunk-Z4UVRQXZ.js.map |
| {"version":3,"sources":["../src/sheet-node.ts"],"names":[],"mappings":";;;AAQA,IAAM,YAAA,GAAe,IAAI,iBAAA,EAA8B;AAEvD,uBAAA,CAAwB;AAAA,EACtB,QAAA,EAAU,MAAM,YAAA,CAAa,QAAA,MAAc,mBAAA,EAAoB;AAAA,EAC/D,aAAa,CAAI,EAAA,KAAgB,aAAa,GAAA,CAAI,gBAAA,IAAoB,EAAE;AAC1E,CAAC,CAAA","file":"chunk-Z4UVRQXZ.js","sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n configureSheetIsolation,\n createSheetState,\n getGlobalSheetState,\n type SheetState,\n} from './sheet-context';\n\nconst sheetStorage = new AsyncLocalStorage<SheetState>();\n\nconfigureSheetIsolation({\n getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(),\n runIsolated: <T>(fn: () => T) => sheetStorage.run(createSheetState(), fn),\n});\n"]} |
| 'use strict'; | ||
| // src/color.ts | ||
| function oklch(l, c, h, alpha) { | ||
| return `oklch(${l} ${c} ${h})`; | ||
| } | ||
| // src/color-scale.ts | ||
| var CHROMA_ENVELOPE_10 = [0.14, 0.34, 0.62, 0.86, 1, 1, 0.9, 0.68, 0.48, 0.32]; | ||
| var DEFAULT_STEPS = 10; | ||
| var DEFAULT_LIGHTNESS_RANGE = [22, 97]; | ||
| var SRGB_TO_LMS = [ | ||
| [0.4122214708, 0.5363325363, 0.0514459929], | ||
| [0.2119034982, 0.6806995451, 0.1073969566], | ||
| [0.0883024619, 0.2817188376, 0.6299787005] | ||
| ]; | ||
| var LMS_TO_OKLAB = [ | ||
| [0.2104542553, 0.793617785, -0.0040720468], | ||
| [1.9779984951, -2.428592205, 0.4505937099], | ||
| [0.0259040371, 0.7827717662, -0.808675766] | ||
| ]; | ||
| var OKLAB_TO_LMS = [ | ||
| [1, 0.3963377774, 0.2158037573], | ||
| [1, -0.1055613458, -0.0638541728], | ||
| [1, -0.0894841775, -1.291485548] | ||
| ]; | ||
| var LMS_TO_SRGB = [ | ||
| [4.0767416621, -3.3077115913, 0.2309699292], | ||
| [-1.2684380046, 2.6097574011, -0.3413193965], | ||
| [-0.0041960863, -0.7034186147, 1.707614701] | ||
| ]; | ||
| function linearizeSrgb(channel) { | ||
| return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4; | ||
| } | ||
| function gammaEncodeSrgb(channel) { | ||
| const abs = Math.abs(channel); | ||
| const encoded = abs <= 31308e-7 ? 12.92 * channel : Math.sign(channel) * (1.055 * abs ** (1 / 2.4) - 0.055); | ||
| return Math.min(1, Math.max(0, encoded)); | ||
| } | ||
| function multiplyMatrix(matrix, vector) { | ||
| return [ | ||
| matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2], | ||
| matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2], | ||
| matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2] | ||
| ]; | ||
| } | ||
| function srgbToOklab(r, g, b) { | ||
| const linear = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)]; | ||
| const lms = multiplyMatrix(SRGB_TO_LMS, linear); | ||
| const lmsPrime = [ | ||
| Math.cbrt(lms[0]), | ||
| Math.cbrt(lms[1]), | ||
| Math.cbrt(lms[2]) | ||
| ]; | ||
| const lab = multiplyMatrix(LMS_TO_OKLAB, lmsPrime); | ||
| return { L: lab[0], a: lab[1], b: lab[2] }; | ||
| } | ||
| function oklabToSrgb(L, a, b) { | ||
| const lmsPrime = multiplyMatrix(OKLAB_TO_LMS, [L, a, b]); | ||
| const lms = [lmsPrime[0] ** 3, lmsPrime[1] ** 3, lmsPrime[2] ** 3]; | ||
| const linear = multiplyMatrix(LMS_TO_SRGB, lms); | ||
| return [gammaEncodeSrgb(linear[0]), gammaEncodeSrgb(linear[1]), gammaEncodeSrgb(linear[2])]; | ||
| } | ||
| var ACHROMATIC_CHROMA_EPSILON = 1e-4; | ||
| function oklabToOklch(L, a, b) { | ||
| const c = Math.sqrt(a * a + b * b); | ||
| if (c < ACHROMATIC_CHROMA_EPSILON) { | ||
| return { l: L * 100, c, h: 0 }; | ||
| } | ||
| let h = Math.atan2(b, a) * 180 / Math.PI; | ||
| if (h < 0) h += 360; | ||
| return { l: L * 100, c, h }; | ||
| } | ||
| function oklchToOklab(l, c, h) { | ||
| const hr = h * Math.PI / 180; | ||
| return { L: l / 100, a: c * Math.cos(hr), b: c * Math.sin(hr) }; | ||
| } | ||
| function parseHexColor(input) { | ||
| const hex = input.trim(); | ||
| const match = /^#([0-9a-f]{3,8})$/i.exec(hex); | ||
| if (!match) { | ||
| throw new Error( | ||
| `[typestyles] parseColor: unsupported color format "${input}". Only hex colors are supported today.` | ||
| ); | ||
| } | ||
| let digits = match[1]; | ||
| if (digits.length === 3 || digits.length === 4) { | ||
| digits = digits.split("").map((ch) => ch + ch).join(""); | ||
| } | ||
| if (digits.length !== 6 && digits.length !== 8) { | ||
| throw new Error( | ||
| `[typestyles] parseColor: unsupported color format "${input}". Only hex colors are supported today.` | ||
| ); | ||
| } | ||
| const r = Number.parseInt(digits.slice(0, 2), 16) / 255; | ||
| const g = Number.parseInt(digits.slice(2, 4), 16) / 255; | ||
| const b = Number.parseInt(digits.slice(4, 6), 16) / 255; | ||
| return [r, g, b]; | ||
| } | ||
| function parseOklchString(input) { | ||
| const trimmed = input.trim(); | ||
| const match = /^oklch\(([^)]+)\)$/i.exec(trimmed); | ||
| if (!match) { | ||
| throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got "${input}".`); | ||
| } | ||
| const parts = match[1].split(/\s*\/\s*/).flatMap((segment, index) => index === 0 ? segment.trim().split(/\s+/) : []).filter(Boolean); | ||
| if (parts.length < 3) { | ||
| throw new Error(`[typestyles] contrastRatio: invalid oklch() color "${input}".`); | ||
| } | ||
| const lRaw = parts[0]; | ||
| const l = lRaw.endsWith("%") ? Number.parseFloat(lRaw) : Number.parseFloat(lRaw) * 100; | ||
| const c = Number.parseFloat(parts[1]); | ||
| const h = Number.parseFloat(parts[2]); | ||
| return { l, c, h }; | ||
| } | ||
| function colorToSrgb(input) { | ||
| const trimmed = input.trim(); | ||
| if (trimmed.startsWith("#")) { | ||
| return parseHexColor(trimmed); | ||
| } | ||
| if (trimmed.startsWith("oklch(")) { | ||
| const { l, c, h } = parseOklchString(trimmed); | ||
| const { L, a, b } = oklchToOklab(l, c, h); | ||
| return oklabToSrgb(L, a, b); | ||
| } | ||
| throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got "${input}".`); | ||
| } | ||
| function relativeLuminance(r, g, b) { | ||
| const [lr, lg, lb] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)]; | ||
| return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb; | ||
| } | ||
| function lightnessStops(steps, range) { | ||
| const [lo, hi] = range; | ||
| return Array.from({ length: steps }, (_, i) => hi - i / (steps - 1) * (hi - lo)); | ||
| } | ||
| function genericChromaEnvelope(steps) { | ||
| return Array.from({ length: steps }, (_, i) => { | ||
| const t = steps === 1 ? 0.5 : i / (steps - 1); | ||
| const x = (t - 0.55) / 0.45; | ||
| return Math.max(0.14, 1 - x * x); | ||
| }); | ||
| } | ||
| function chromaEnvelope(steps) { | ||
| if (steps === DEFAULT_STEPS) return CHROMA_ENVELOPE_10; | ||
| return genericChromaEnvelope(steps); | ||
| } | ||
| function parseColor(input) { | ||
| const [r, g, b] = parseHexColor(input); | ||
| const lab = srgbToOklab(r, g, b); | ||
| return oklabToOklch(lab.L, lab.a, lab.b); | ||
| } | ||
| function generateRamp(opts) { | ||
| const steps = opts.steps ?? DEFAULT_STEPS; | ||
| const lightnessRange = opts.lightnessRange ?? DEFAULT_LIGHTNESS_RANGE; | ||
| const envelope = chromaEnvelope(steps); | ||
| const lightness = lightnessStops(steps, lightnessRange); | ||
| return lightness.map((l, i) => { | ||
| const c = opts.chroma * envelope[i]; | ||
| return oklch(`${l.toFixed(2)}%`, Number(c.toFixed(3)), opts.hue); | ||
| }); | ||
| } | ||
| function contrastRatio(colorA, colorB) { | ||
| const [r1, g1, b1] = colorToSrgb(colorA); | ||
| const [r2, g2, b2] = colorToSrgb(colorB); | ||
| const l1 = relativeLuminance(r1, g1, b1); | ||
| const l2 = relativeLuminance(r2, g2, b2); | ||
| const lighter = Math.max(l1, l2); | ||
| const darker = Math.min(l1, l2); | ||
| return (lighter + 0.05) / (darker + 0.05); | ||
| } | ||
| exports.contrastRatio = contrastRatio; | ||
| exports.generateRamp = generateRamp; | ||
| exports.parseColor = parseColor; | ||
| //# sourceMappingURL=color-scale.cjs.map | ||
| //# sourceMappingURL=color-scale.cjs.map |
| {"version":3,"sources":["../src/color.ts","../src/color-scale.ts"],"names":[],"mappings":"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","file":"color-scale.cjs","sourcesContent":["/**\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 { oklch as formatOklch } from './color';\n\n/** Hand-tuned chroma envelope for the default 10-step ramp (see design-system palette). */\nconst CHROMA_ENVELOPE_10 = [0.14, 0.34, 0.62, 0.86, 1, 1, 0.9, 0.68, 0.48, 0.32] as const;\n\nconst DEFAULT_STEPS = 10;\nconst DEFAULT_LIGHTNESS_RANGE: [number, number] = [22, 97];\n\nconst SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\nconst LMS_TO_OKLAB = [\n [0.2104542553, 0.793617785, -0.0040720468],\n [1.9779984951, -2.428592205, 0.4505937099],\n [0.0259040371, 0.7827717662, -0.808675766],\n] as const;\n\nconst OKLAB_TO_LMS = [\n [1.0, 0.3963377774, 0.2158037573],\n [1.0, -0.1055613458, -0.0638541728],\n [1.0, -0.0894841775, -1.291485548],\n] as const;\n\nconst LMS_TO_SRGB = [\n [4.0767416621, -3.3077115913, 0.2309699292],\n [-1.2684380046, 2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, 1.707614701],\n] as const;\n\nexport type OklchColor = { l: number; c: number; h: number };\n\nexport type GenerateRampOptions = {\n hue: number;\n chroma: number;\n steps?: number;\n lightnessRange?: [number, number];\n};\n\nfunction linearizeSrgb(channel: number): number {\n return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;\n}\n\nfunction gammaEncodeSrgb(channel: number): number {\n const abs = Math.abs(channel);\n const encoded =\n abs <= 0.0031308 ? 12.92 * channel : Math.sign(channel) * (1.055 * abs ** (1 / 2.4) - 0.055);\n return Math.min(1, Math.max(0, encoded));\n}\n\nfunction multiplyMatrix(\n matrix: readonly (readonly number[])[],\n vector: readonly [number, number, number],\n): [number, number, number] {\n return [\n matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],\n matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],\n matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2],\n ];\n}\n\nfunction srgbToOklab(r: number, g: number, b: number): { L: number; a: number; b: number } {\n const linear: [number, number, number] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)];\n const lms = multiplyMatrix(SRGB_TO_LMS, linear);\n const lmsPrime: [number, number, number] = [\n Math.cbrt(lms[0]),\n Math.cbrt(lms[1]),\n Math.cbrt(lms[2]),\n ];\n const lab = multiplyMatrix(LMS_TO_OKLAB, lmsPrime);\n return { L: lab[0], a: lab[1], b: lab[2] };\n}\n\nfunction oklabToSrgb(L: number, a: number, b: number): [number, number, number] {\n const lmsPrime = multiplyMatrix(OKLAB_TO_LMS, [L, a, b]);\n const lms: [number, number, number] = [lmsPrime[0] ** 3, lmsPrime[1] ** 3, lmsPrime[2] ** 3];\n const linear = multiplyMatrix(LMS_TO_SRGB, lms);\n return [gammaEncodeSrgb(linear[0]), gammaEncodeSrgb(linear[1]), gammaEncodeSrgb(linear[2])];\n}\n\n/** Below this, a/b are floating-point noise (matrix constants don't sum to exactly 1),\n * so atan2 produces a hue that's arbitrary and unstable across JS engines. */\nconst ACHROMATIC_CHROMA_EPSILON = 1e-4;\n\nfunction oklabToOklch(L: number, a: number, b: number): OklchColor {\n const c = Math.sqrt(a * a + b * b);\n if (c < ACHROMATIC_CHROMA_EPSILON) {\n return { l: L * 100, c, h: 0 };\n }\n let h = (Math.atan2(b, a) * 180) / Math.PI;\n if (h < 0) h += 360;\n return { l: L * 100, c, h };\n}\n\nfunction oklchToOklab(l: number, c: number, h: number): { L: number; a: number; b: number } {\n const hr = (h * Math.PI) / 180;\n return { L: l / 100, a: c * Math.cos(hr), b: c * Math.sin(hr) };\n}\n\nfunction parseHexColor(input: string): [number, number, number] {\n const hex = input.trim();\n const match = /^#([0-9a-f]{3,8})$/i.exec(hex);\n if (!match) {\n throw new Error(\n `[typestyles] parseColor: unsupported color format \"${input}\". Only hex colors are supported today.`,\n );\n }\n\n let digits = match[1];\n if (digits.length === 3 || digits.length === 4) {\n digits = digits\n .split('')\n .map((ch) => ch + ch)\n .join('');\n }\n\n if (digits.length !== 6 && digits.length !== 8) {\n throw new Error(\n `[typestyles] parseColor: unsupported color format \"${input}\". Only hex colors are supported today.`,\n );\n }\n\n const r = Number.parseInt(digits.slice(0, 2), 16) / 255;\n const g = Number.parseInt(digits.slice(2, 4), 16) / 255;\n const b = Number.parseInt(digits.slice(4, 6), 16) / 255;\n return [r, g, b];\n}\n\nfunction parseOklchString(input: string): OklchColor {\n const trimmed = input.trim();\n const match = /^oklch\\(([^)]+)\\)$/i.exec(trimmed);\n if (!match) {\n throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got \"${input}\".`);\n }\n\n const parts = match[1]\n .split(/\\s*\\/\\s*/)\n .flatMap((segment, index) => (index === 0 ? segment.trim().split(/\\s+/) : []))\n .filter(Boolean);\n\n if (parts.length < 3) {\n throw new Error(`[typestyles] contrastRatio: invalid oklch() color \"${input}\".`);\n }\n\n const lRaw = parts[0];\n const l = lRaw.endsWith('%') ? Number.parseFloat(lRaw) : Number.parseFloat(lRaw) * 100;\n const c = Number.parseFloat(parts[1]);\n const h = Number.parseFloat(parts[2]);\n return { l, c, h };\n}\n\nfunction colorToSrgb(input: string): [number, number, number] {\n const trimmed = input.trim();\n if (trimmed.startsWith('#')) {\n return parseHexColor(trimmed);\n }\n if (trimmed.startsWith('oklch(')) {\n const { l, c, h } = parseOklchString(trimmed);\n const { L, a, b } = oklchToOklab(l, c, h);\n return oklabToSrgb(L, a, b);\n }\n throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got \"${input}\".`);\n}\n\nfunction relativeLuminance(r: number, g: number, b: number): number {\n const [lr, lg, lb] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)];\n return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;\n}\n\nfunction lightnessStops(steps: number, range: [number, number]): number[] {\n const [lo, hi] = range;\n return Array.from({ length: steps }, (_, i) => hi - (i / (steps - 1)) * (hi - lo));\n}\n\n/** Best-effort chroma envelope for non-default step counts (un-tuned; prefer `steps: 10`). */\nfunction genericChromaEnvelope(steps: number): number[] {\n return Array.from({ length: steps }, (_, i) => {\n const t = steps === 1 ? 0.5 : i / (steps - 1);\n const x = (t - 0.55) / 0.45;\n return Math.max(0.14, 1 - x * x);\n });\n}\n\nfunction chromaEnvelope(steps: number): readonly number[] {\n if (steps === DEFAULT_STEPS) return CHROMA_ENVELOPE_10;\n return genericChromaEnvelope(steps);\n}\n\n/**\n * Parse a hex color into OKLCH components (`l` as 0–100%, `c` and `h` as CSS oklch units).\n */\nexport function parseColor(input: string): OklchColor {\n const [r, g, b] = parseHexColor(input);\n const lab = srgbToOklab(r, g, b);\n return oklabToOklch(lab.L, lab.a, lab.b);\n}\n\n/**\n * Build a perceptual OKLCH ramp (lightest → darkest).\n * `steps: 10` uses the hand-tuned chroma envelope from the design-system palette.\n */\nexport function generateRamp(opts: GenerateRampOptions): string[] {\n const steps = opts.steps ?? DEFAULT_STEPS;\n const lightnessRange = opts.lightnessRange ?? DEFAULT_LIGHTNESS_RANGE;\n const envelope = chromaEnvelope(steps);\n const lightness = lightnessStops(steps, lightnessRange);\n\n return lightness.map((l, i) => {\n const c = opts.chroma * envelope[i];\n return formatOklch(`${l.toFixed(2)}%`, Number(c.toFixed(3)), opts.hue);\n });\n}\n\n/**\n * WCAG 2.x relative luminance contrast ratio between two colors (hex or oklch() strings).\n */\nexport function contrastRatio(colorA: string, colorB: string): number {\n const [r1, g1, b1] = colorToSrgb(colorA);\n const [r2, g2, b2] = colorToSrgb(colorB);\n const l1 = relativeLuminance(r1, g1, b1);\n const l2 = relativeLuminance(r2, g2, b2);\n const lighter = Math.max(l1, l2);\n const darker = Math.min(l1, l2);\n return (lighter + 0.05) / (darker + 0.05);\n}\n"]} |
| type OklchColor = { | ||
| l: number; | ||
| c: number; | ||
| h: number; | ||
| }; | ||
| type GenerateRampOptions = { | ||
| hue: number; | ||
| chroma: number; | ||
| steps?: number; | ||
| lightnessRange?: [number, number]; | ||
| }; | ||
| /** | ||
| * Parse a hex color into OKLCH components (`l` as 0–100%, `c` and `h` as CSS oklch units). | ||
| */ | ||
| declare function parseColor(input: string): OklchColor; | ||
| /** | ||
| * Build a perceptual OKLCH ramp (lightest → darkest). | ||
| * `steps: 10` uses the hand-tuned chroma envelope from the design-system palette. | ||
| */ | ||
| declare function generateRamp(opts: GenerateRampOptions): string[]; | ||
| /** | ||
| * WCAG 2.x relative luminance contrast ratio between two colors (hex or oklch() strings). | ||
| */ | ||
| declare function contrastRatio(colorA: string, colorB: string): number; | ||
| export { type GenerateRampOptions, type OklchColor, contrastRatio, generateRamp, parseColor }; |
| type OklchColor = { | ||
| l: number; | ||
| c: number; | ||
| h: number; | ||
| }; | ||
| type GenerateRampOptions = { | ||
| hue: number; | ||
| chroma: number; | ||
| steps?: number; | ||
| lightnessRange?: [number, number]; | ||
| }; | ||
| /** | ||
| * Parse a hex color into OKLCH components (`l` as 0–100%, `c` and `h` as CSS oklch units). | ||
| */ | ||
| declare function parseColor(input: string): OklchColor; | ||
| /** | ||
| * Build a perceptual OKLCH ramp (lightest → darkest). | ||
| * `steps: 10` uses the hand-tuned chroma envelope from the design-system palette. | ||
| */ | ||
| declare function generateRamp(opts: GenerateRampOptions): string[]; | ||
| /** | ||
| * WCAG 2.x relative luminance contrast ratio between two colors (hex or oklch() strings). | ||
| */ | ||
| declare function contrastRatio(colorA: string, colorB: string): number; | ||
| export { type GenerateRampOptions, type OklchColor, contrastRatio, generateRamp, parseColor }; |
| import { oklch } from './chunk-U3WMOSLD.js'; | ||
| import './chunk-PZ5AY32C.js'; | ||
| // src/color-scale.ts | ||
| var CHROMA_ENVELOPE_10 = [0.14, 0.34, 0.62, 0.86, 1, 1, 0.9, 0.68, 0.48, 0.32]; | ||
| var DEFAULT_STEPS = 10; | ||
| var DEFAULT_LIGHTNESS_RANGE = [22, 97]; | ||
| var SRGB_TO_LMS = [ | ||
| [0.4122214708, 0.5363325363, 0.0514459929], | ||
| [0.2119034982, 0.6806995451, 0.1073969566], | ||
| [0.0883024619, 0.2817188376, 0.6299787005] | ||
| ]; | ||
| var LMS_TO_OKLAB = [ | ||
| [0.2104542553, 0.793617785, -0.0040720468], | ||
| [1.9779984951, -2.428592205, 0.4505937099], | ||
| [0.0259040371, 0.7827717662, -0.808675766] | ||
| ]; | ||
| var OKLAB_TO_LMS = [ | ||
| [1, 0.3963377774, 0.2158037573], | ||
| [1, -0.1055613458, -0.0638541728], | ||
| [1, -0.0894841775, -1.291485548] | ||
| ]; | ||
| var LMS_TO_SRGB = [ | ||
| [4.0767416621, -3.3077115913, 0.2309699292], | ||
| [-1.2684380046, 2.6097574011, -0.3413193965], | ||
| [-0.0041960863, -0.7034186147, 1.707614701] | ||
| ]; | ||
| function linearizeSrgb(channel) { | ||
| return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4; | ||
| } | ||
| function gammaEncodeSrgb(channel) { | ||
| const abs = Math.abs(channel); | ||
| const encoded = abs <= 31308e-7 ? 12.92 * channel : Math.sign(channel) * (1.055 * abs ** (1 / 2.4) - 0.055); | ||
| return Math.min(1, Math.max(0, encoded)); | ||
| } | ||
| function multiplyMatrix(matrix, vector) { | ||
| return [ | ||
| matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2], | ||
| matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2], | ||
| matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2] | ||
| ]; | ||
| } | ||
| function srgbToOklab(r, g, b) { | ||
| const linear = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)]; | ||
| const lms = multiplyMatrix(SRGB_TO_LMS, linear); | ||
| const lmsPrime = [ | ||
| Math.cbrt(lms[0]), | ||
| Math.cbrt(lms[1]), | ||
| Math.cbrt(lms[2]) | ||
| ]; | ||
| const lab = multiplyMatrix(LMS_TO_OKLAB, lmsPrime); | ||
| return { L: lab[0], a: lab[1], b: lab[2] }; | ||
| } | ||
| function oklabToSrgb(L, a, b) { | ||
| const lmsPrime = multiplyMatrix(OKLAB_TO_LMS, [L, a, b]); | ||
| const lms = [lmsPrime[0] ** 3, lmsPrime[1] ** 3, lmsPrime[2] ** 3]; | ||
| const linear = multiplyMatrix(LMS_TO_SRGB, lms); | ||
| return [gammaEncodeSrgb(linear[0]), gammaEncodeSrgb(linear[1]), gammaEncodeSrgb(linear[2])]; | ||
| } | ||
| var ACHROMATIC_CHROMA_EPSILON = 1e-4; | ||
| function oklabToOklch(L, a, b) { | ||
| const c = Math.sqrt(a * a + b * b); | ||
| if (c < ACHROMATIC_CHROMA_EPSILON) { | ||
| return { l: L * 100, c, h: 0 }; | ||
| } | ||
| let h = Math.atan2(b, a) * 180 / Math.PI; | ||
| if (h < 0) h += 360; | ||
| return { l: L * 100, c, h }; | ||
| } | ||
| function oklchToOklab(l, c, h) { | ||
| const hr = h * Math.PI / 180; | ||
| return { L: l / 100, a: c * Math.cos(hr), b: c * Math.sin(hr) }; | ||
| } | ||
| function parseHexColor(input) { | ||
| const hex = input.trim(); | ||
| const match = /^#([0-9a-f]{3,8})$/i.exec(hex); | ||
| if (!match) { | ||
| throw new Error( | ||
| `[typestyles] parseColor: unsupported color format "${input}". Only hex colors are supported today.` | ||
| ); | ||
| } | ||
| let digits = match[1]; | ||
| if (digits.length === 3 || digits.length === 4) { | ||
| digits = digits.split("").map((ch) => ch + ch).join(""); | ||
| } | ||
| if (digits.length !== 6 && digits.length !== 8) { | ||
| throw new Error( | ||
| `[typestyles] parseColor: unsupported color format "${input}". Only hex colors are supported today.` | ||
| ); | ||
| } | ||
| const r = Number.parseInt(digits.slice(0, 2), 16) / 255; | ||
| const g = Number.parseInt(digits.slice(2, 4), 16) / 255; | ||
| const b = Number.parseInt(digits.slice(4, 6), 16) / 255; | ||
| return [r, g, b]; | ||
| } | ||
| function parseOklchString(input) { | ||
| const trimmed = input.trim(); | ||
| const match = /^oklch\(([^)]+)\)$/i.exec(trimmed); | ||
| if (!match) { | ||
| throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got "${input}".`); | ||
| } | ||
| const parts = match[1].split(/\s*\/\s*/).flatMap((segment, index) => index === 0 ? segment.trim().split(/\s+/) : []).filter(Boolean); | ||
| if (parts.length < 3) { | ||
| throw new Error(`[typestyles] contrastRatio: invalid oklch() color "${input}".`); | ||
| } | ||
| const lRaw = parts[0]; | ||
| const l = lRaw.endsWith("%") ? Number.parseFloat(lRaw) : Number.parseFloat(lRaw) * 100; | ||
| const c = Number.parseFloat(parts[1]); | ||
| const h = Number.parseFloat(parts[2]); | ||
| return { l, c, h }; | ||
| } | ||
| function colorToSrgb(input) { | ||
| const trimmed = input.trim(); | ||
| if (trimmed.startsWith("#")) { | ||
| return parseHexColor(trimmed); | ||
| } | ||
| if (trimmed.startsWith("oklch(")) { | ||
| const { l, c, h } = parseOklchString(trimmed); | ||
| const { L, a, b } = oklchToOklab(l, c, h); | ||
| return oklabToSrgb(L, a, b); | ||
| } | ||
| throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got "${input}".`); | ||
| } | ||
| function relativeLuminance(r, g, b) { | ||
| const [lr, lg, lb] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)]; | ||
| return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb; | ||
| } | ||
| function lightnessStops(steps, range) { | ||
| const [lo, hi] = range; | ||
| return Array.from({ length: steps }, (_, i) => hi - i / (steps - 1) * (hi - lo)); | ||
| } | ||
| function genericChromaEnvelope(steps) { | ||
| return Array.from({ length: steps }, (_, i) => { | ||
| const t = steps === 1 ? 0.5 : i / (steps - 1); | ||
| const x = (t - 0.55) / 0.45; | ||
| return Math.max(0.14, 1 - x * x); | ||
| }); | ||
| } | ||
| function chromaEnvelope(steps) { | ||
| if (steps === DEFAULT_STEPS) return CHROMA_ENVELOPE_10; | ||
| return genericChromaEnvelope(steps); | ||
| } | ||
| function parseColor(input) { | ||
| const [r, g, b] = parseHexColor(input); | ||
| const lab = srgbToOklab(r, g, b); | ||
| return oklabToOklch(lab.L, lab.a, lab.b); | ||
| } | ||
| function generateRamp(opts) { | ||
| const steps = opts.steps ?? DEFAULT_STEPS; | ||
| const lightnessRange = opts.lightnessRange ?? DEFAULT_LIGHTNESS_RANGE; | ||
| const envelope = chromaEnvelope(steps); | ||
| const lightness = lightnessStops(steps, lightnessRange); | ||
| return lightness.map((l, i) => { | ||
| const c = opts.chroma * envelope[i]; | ||
| return oklch(`${l.toFixed(2)}%`, Number(c.toFixed(3)), opts.hue); | ||
| }); | ||
| } | ||
| function contrastRatio(colorA, colorB) { | ||
| const [r1, g1, b1] = colorToSrgb(colorA); | ||
| const [r2, g2, b2] = colorToSrgb(colorB); | ||
| const l1 = relativeLuminance(r1, g1, b1); | ||
| const l2 = relativeLuminance(r2, g2, b2); | ||
| const lighter = Math.max(l1, l2); | ||
| const darker = Math.min(l1, l2); | ||
| return (lighter + 0.05) / (darker + 0.05); | ||
| } | ||
| export { contrastRatio, generateRamp, parseColor }; | ||
| //# sourceMappingURL=color-scale.js.map | ||
| //# sourceMappingURL=color-scale.js.map |
| {"version":3,"sources":["../src/color-scale.ts"],"names":[],"mappings":"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","file":"color-scale.js","sourcesContent":["import { oklch as formatOklch } from './color';\n\n/** Hand-tuned chroma envelope for the default 10-step ramp (see design-system palette). */\nconst CHROMA_ENVELOPE_10 = [0.14, 0.34, 0.62, 0.86, 1, 1, 0.9, 0.68, 0.48, 0.32] as const;\n\nconst DEFAULT_STEPS = 10;\nconst DEFAULT_LIGHTNESS_RANGE: [number, number] = [22, 97];\n\nconst SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\nconst LMS_TO_OKLAB = [\n [0.2104542553, 0.793617785, -0.0040720468],\n [1.9779984951, -2.428592205, 0.4505937099],\n [0.0259040371, 0.7827717662, -0.808675766],\n] as const;\n\nconst OKLAB_TO_LMS = [\n [1.0, 0.3963377774, 0.2158037573],\n [1.0, -0.1055613458, -0.0638541728],\n [1.0, -0.0894841775, -1.291485548],\n] as const;\n\nconst LMS_TO_SRGB = [\n [4.0767416621, -3.3077115913, 0.2309699292],\n [-1.2684380046, 2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, 1.707614701],\n] as const;\n\nexport type OklchColor = { l: number; c: number; h: number };\n\nexport type GenerateRampOptions = {\n hue: number;\n chroma: number;\n steps?: number;\n lightnessRange?: [number, number];\n};\n\nfunction linearizeSrgb(channel: number): number {\n return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;\n}\n\nfunction gammaEncodeSrgb(channel: number): number {\n const abs = Math.abs(channel);\n const encoded =\n abs <= 0.0031308 ? 12.92 * channel : Math.sign(channel) * (1.055 * abs ** (1 / 2.4) - 0.055);\n return Math.min(1, Math.max(0, encoded));\n}\n\nfunction multiplyMatrix(\n matrix: readonly (readonly number[])[],\n vector: readonly [number, number, number],\n): [number, number, number] {\n return [\n matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],\n matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],\n matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2],\n ];\n}\n\nfunction srgbToOklab(r: number, g: number, b: number): { L: number; a: number; b: number } {\n const linear: [number, number, number] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)];\n const lms = multiplyMatrix(SRGB_TO_LMS, linear);\n const lmsPrime: [number, number, number] = [\n Math.cbrt(lms[0]),\n Math.cbrt(lms[1]),\n Math.cbrt(lms[2]),\n ];\n const lab = multiplyMatrix(LMS_TO_OKLAB, lmsPrime);\n return { L: lab[0], a: lab[1], b: lab[2] };\n}\n\nfunction oklabToSrgb(L: number, a: number, b: number): [number, number, number] {\n const lmsPrime = multiplyMatrix(OKLAB_TO_LMS, [L, a, b]);\n const lms: [number, number, number] = [lmsPrime[0] ** 3, lmsPrime[1] ** 3, lmsPrime[2] ** 3];\n const linear = multiplyMatrix(LMS_TO_SRGB, lms);\n return [gammaEncodeSrgb(linear[0]), gammaEncodeSrgb(linear[1]), gammaEncodeSrgb(linear[2])];\n}\n\n/** Below this, a/b are floating-point noise (matrix constants don't sum to exactly 1),\n * so atan2 produces a hue that's arbitrary and unstable across JS engines. */\nconst ACHROMATIC_CHROMA_EPSILON = 1e-4;\n\nfunction oklabToOklch(L: number, a: number, b: number): OklchColor {\n const c = Math.sqrt(a * a + b * b);\n if (c < ACHROMATIC_CHROMA_EPSILON) {\n return { l: L * 100, c, h: 0 };\n }\n let h = (Math.atan2(b, a) * 180) / Math.PI;\n if (h < 0) h += 360;\n return { l: L * 100, c, h };\n}\n\nfunction oklchToOklab(l: number, c: number, h: number): { L: number; a: number; b: number } {\n const hr = (h * Math.PI) / 180;\n return { L: l / 100, a: c * Math.cos(hr), b: c * Math.sin(hr) };\n}\n\nfunction parseHexColor(input: string): [number, number, number] {\n const hex = input.trim();\n const match = /^#([0-9a-f]{3,8})$/i.exec(hex);\n if (!match) {\n throw new Error(\n `[typestyles] parseColor: unsupported color format \"${input}\". Only hex colors are supported today.`,\n );\n }\n\n let digits = match[1];\n if (digits.length === 3 || digits.length === 4) {\n digits = digits\n .split('')\n .map((ch) => ch + ch)\n .join('');\n }\n\n if (digits.length !== 6 && digits.length !== 8) {\n throw new Error(\n `[typestyles] parseColor: unsupported color format \"${input}\". Only hex colors are supported today.`,\n );\n }\n\n const r = Number.parseInt(digits.slice(0, 2), 16) / 255;\n const g = Number.parseInt(digits.slice(2, 4), 16) / 255;\n const b = Number.parseInt(digits.slice(4, 6), 16) / 255;\n return [r, g, b];\n}\n\nfunction parseOklchString(input: string): OklchColor {\n const trimmed = input.trim();\n const match = /^oklch\\(([^)]+)\\)$/i.exec(trimmed);\n if (!match) {\n throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got \"${input}\".`);\n }\n\n const parts = match[1]\n .split(/\\s*\\/\\s*/)\n .flatMap((segment, index) => (index === 0 ? segment.trim().split(/\\s+/) : []))\n .filter(Boolean);\n\n if (parts.length < 3) {\n throw new Error(`[typestyles] contrastRatio: invalid oklch() color \"${input}\".`);\n }\n\n const lRaw = parts[0];\n const l = lRaw.endsWith('%') ? Number.parseFloat(lRaw) : Number.parseFloat(lRaw) * 100;\n const c = Number.parseFloat(parts[1]);\n const h = Number.parseFloat(parts[2]);\n return { l, c, h };\n}\n\nfunction colorToSrgb(input: string): [number, number, number] {\n const trimmed = input.trim();\n if (trimmed.startsWith('#')) {\n return parseHexColor(trimmed);\n }\n if (trimmed.startsWith('oklch(')) {\n const { l, c, h } = parseOklchString(trimmed);\n const { L, a, b } = oklchToOklab(l, c, h);\n return oklabToSrgb(L, a, b);\n }\n throw new Error(`[typestyles] contrastRatio: expected hex or oklch() color, got \"${input}\".`);\n}\n\nfunction relativeLuminance(r: number, g: number, b: number): number {\n const [lr, lg, lb] = [linearizeSrgb(r), linearizeSrgb(g), linearizeSrgb(b)];\n return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;\n}\n\nfunction lightnessStops(steps: number, range: [number, number]): number[] {\n const [lo, hi] = range;\n return Array.from({ length: steps }, (_, i) => hi - (i / (steps - 1)) * (hi - lo));\n}\n\n/** Best-effort chroma envelope for non-default step counts (un-tuned; prefer `steps: 10`). */\nfunction genericChromaEnvelope(steps: number): number[] {\n return Array.from({ length: steps }, (_, i) => {\n const t = steps === 1 ? 0.5 : i / (steps - 1);\n const x = (t - 0.55) / 0.45;\n return Math.max(0.14, 1 - x * x);\n });\n}\n\nfunction chromaEnvelope(steps: number): readonly number[] {\n if (steps === DEFAULT_STEPS) return CHROMA_ENVELOPE_10;\n return genericChromaEnvelope(steps);\n}\n\n/**\n * Parse a hex color into OKLCH components (`l` as 0–100%, `c` and `h` as CSS oklch units).\n */\nexport function parseColor(input: string): OklchColor {\n const [r, g, b] = parseHexColor(input);\n const lab = srgbToOklab(r, g, b);\n return oklabToOklch(lab.L, lab.a, lab.b);\n}\n\n/**\n * Build a perceptual OKLCH ramp (lightest → darkest).\n * `steps: 10` uses the hand-tuned chroma envelope from the design-system palette.\n */\nexport function generateRamp(opts: GenerateRampOptions): string[] {\n const steps = opts.steps ?? DEFAULT_STEPS;\n const lightnessRange = opts.lightnessRange ?? DEFAULT_LIGHTNESS_RANGE;\n const envelope = chromaEnvelope(steps);\n const lightness = lightnessStops(steps, lightnessRange);\n\n return lightness.map((l, i) => {\n const c = opts.chroma * envelope[i];\n return formatOklch(`${l.toFixed(2)}%`, Number(c.toFixed(3)), opts.hue);\n });\n}\n\n/**\n * WCAG 2.x relative luminance contrast ratio between two colors (hex or oklch() strings).\n */\nexport function contrastRatio(colorA: string, colorB: string): number {\n const [r1, g1, b1] = colorToSrgb(colorA);\n const [r2, g2, b2] = colorToSrgb(colorB);\n const l1 = relativeLuminance(r1, g1, b1);\n const l2 = relativeLuminance(r2, g2, b2);\n const lighter = Math.max(l1, l2);\n const darker = Math.min(l1, l2);\n return (lighter + 0.05) / (darker + 0.05);\n}\n"]} |
| 'use strict'; | ||
| var __defProp = Object.defineProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| // src/color.ts | ||
| var color_exports = {}; | ||
| __export(color_exports, { | ||
| alpha: () => alpha, | ||
| hsl: () => hsl, | ||
| hwb: () => hwb, | ||
| lab: () => lab, | ||
| lch: () => lch, | ||
| lightDark: () => lightDark, | ||
| mix: () => mix, | ||
| oklab: () => oklab, | ||
| oklch: () => oklch, | ||
| rgb: () => rgb | ||
| }); | ||
| function rgb(r, g, b, alpha2) { | ||
| if (alpha2 != null) return `rgb(${r} ${g} ${b} / ${alpha2})`; | ||
| return `rgb(${r} ${g} ${b})`; | ||
| } | ||
| function hsl(h, s, l, alpha2) { | ||
| if (alpha2 != null) return `hsl(${h} ${s} ${l} / ${alpha2})`; | ||
| return `hsl(${h} ${s} ${l})`; | ||
| } | ||
| function oklch(l, c, h, alpha2) { | ||
| if (alpha2 != null) return `oklch(${l} ${c} ${h} / ${alpha2})`; | ||
| return `oklch(${l} ${c} ${h})`; | ||
| } | ||
| function oklab(l, a, b, alpha2) { | ||
| if (alpha2 != null) return `oklab(${l} ${a} ${b} / ${alpha2})`; | ||
| return `oklab(${l} ${a} ${b})`; | ||
| } | ||
| function lab(l, a, b, alpha2) { | ||
| if (alpha2 != null) return `lab(${l} ${a} ${b} / ${alpha2})`; | ||
| return `lab(${l} ${a} ${b})`; | ||
| } | ||
| function lch(l, c, h, alpha2) { | ||
| if (alpha2 != null) return `lch(${l} ${c} ${h} / ${alpha2})`; | ||
| return `lch(${l} ${c} ${h})`; | ||
| } | ||
| function hwb(h, w, b, alpha2) { | ||
| if (alpha2 != null) return `hwb(${h} ${w} ${b} / ${alpha2})`; | ||
| return `hwb(${h} ${w} ${b})`; | ||
| } | ||
| function mix(color1, color2, percentage, colorSpace = "srgb") { | ||
| const c1 = percentage != null ? `${color1} ${percentage}%` : color1; | ||
| return `color-mix(in ${colorSpace}, ${c1}, ${color2})`; | ||
| } | ||
| function lightDark(lightColor, darkColor) { | ||
| return `light-dark(${lightColor}, ${darkColor})`; | ||
| } | ||
| function alpha(colorValue, opacity, colorSpace = "srgb") { | ||
| const percentage = Math.round(opacity * 100); | ||
| return `color-mix(in ${colorSpace}, ${colorValue} ${percentage}%, transparent)`; | ||
| } | ||
| // src/color-entry.ts | ||
| var color = color_exports; | ||
| exports.alpha = alpha; | ||
| exports.color = color; | ||
| exports.hsl = hsl; | ||
| exports.hwb = hwb; | ||
| exports.lab = lab; | ||
| exports.lch = lch; | ||
| exports.lightDark = lightDark; | ||
| exports.mix = mix; | ||
| exports.oklab = oklab; | ||
| exports.oklch = oklch; | ||
| exports.rgb = rgb; | ||
| //# sourceMappingURL=color.cjs.map | ||
| //# sourceMappingURL=color.cjs.map |
| {"version":3,"sources":["../src/color.ts","../src/color-entry.ts"],"names":["alpha"],"mappings":"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","file":"color.cjs","sourcesContent":["/**\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","export * from './color';\nimport * as colorFns from './color';\n\n/**\n * Type-safe CSS color function helpers (`rgb`, `oklch`, `mix`, …).\n * Import from `typestyles/color` so the main entry stays lean.\n */\nexport const color = colorFns;\n"]} |
+140
| /** | ||
| * Type-safe helpers for CSS color functions. | ||
| * | ||
| * Each function returns a plain CSS string — no runtime color math. | ||
| * Works naturally with token references since tokens are strings too. | ||
| */ | ||
| type ColorValue = string | number; | ||
| /** Color spaces supported by color-mix(). */ | ||
| type ColorMixSpace = 'srgb' | 'srgb-linear' | 'display-p3' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020' | 'lab' | 'oklab' | 'xyz' | 'xyz-d50' | 'xyz-d65' | 'hsl' | 'hwb' | 'lch' | 'oklch'; | ||
| /** | ||
| * `rgb(r g b)` or `rgb(r g b / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.rgb(0, 102, 255, 0.5) // "rgb(0 102 255 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hsl(h s l)` or `hsl(h s l / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hsl(220, '100%', '50%') // "hsl(220 100% 50%)" | ||
| * color.hsl(220, '100%', '50%', 0.8) // "hsl(220 100% 50% / 0.8)" | ||
| * ``` | ||
| */ | ||
| declare function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklch(L C h)` or `oklch(L C h / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.oklch(0.7, 0.15, 250, 0.5) // "oklch(0.7 0.15 250 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklab(L a b)` or `oklab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklab(0.7, -0.1, -0.1) // "oklab(0.7 -0.1 -0.1)" | ||
| * color.oklab(0.7, -0.1, -0.1, 0.5) // "oklab(0.7 -0.1 -0.1 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lab(L a b)` or `lab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lab('50%', 40, -20) // "lab(50% 40 -20)" | ||
| * ``` | ||
| */ | ||
| declare function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lch(L C h)` or `lch(L C h / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lch('50%', 80, 250) // "lch(50% 80 250)" | ||
| * ``` | ||
| */ | ||
| declare function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hwb(h w b)` or `hwb(h w b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hwb(220, '10%', '0%') // "hwb(220 10% 0%)" | ||
| * ``` | ||
| */ | ||
| declare function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `color-mix(in colorspace, color1 p1%, color2 p2%)` | ||
| * | ||
| * Mixes two colors in the given color space. Percentages are optional. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.mix('red', 'blue') // "color-mix(in srgb, red, blue)" | ||
| * color.mix('red', 'blue', 30) // "color-mix(in srgb, red 30%, blue)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.mix('red', 'blue', 50, 'oklch') // "color-mix(in oklch, red 50%, blue)" | ||
| * ``` | ||
| */ | ||
| declare function mix(color1: string, color2: string, percentage?: number, colorSpace?: ColorMixSpace): string; | ||
| /** | ||
| * `light-dark(lightColor, darkColor)` | ||
| * | ||
| * Uses the `light-dark()` CSS function that resolves based on | ||
| * the computed `color-scheme` of the element. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * color.lightDark(theme.textLight, theme.textDark) // "light-dark(var(--theme-textLight), var(--theme-textDark))" | ||
| * ``` | ||
| */ | ||
| declare function lightDark(lightColor: string, darkColor: string): string; | ||
| /** | ||
| * Adjust the alpha/opacity of any color using `color-mix()`. | ||
| * | ||
| * This is a common pattern: mixing a color with transparent to change opacity. | ||
| * Works with any color value including token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.alpha('red', 0.5) // "color-mix(in srgb, red 50%, transparent)" | ||
| * color.alpha(theme.primary, 0.2) // "color-mix(in srgb, var(--theme-primary) 20%, transparent)" | ||
| * color.alpha('#0066ff', 0.8, 'oklch') // "color-mix(in oklch, #0066ff 80%, transparent)" | ||
| * ``` | ||
| */ | ||
| declare function alpha(colorValue: string, opacity: number, colorSpace?: ColorMixSpace): string; | ||
| type colorFns_ColorMixSpace = ColorMixSpace; | ||
| declare const colorFns_alpha: typeof alpha; | ||
| declare const colorFns_hsl: typeof hsl; | ||
| declare const colorFns_hwb: typeof hwb; | ||
| declare const colorFns_lab: typeof lab; | ||
| declare const colorFns_lch: typeof lch; | ||
| declare const colorFns_lightDark: typeof lightDark; | ||
| declare const colorFns_mix: typeof mix; | ||
| declare const colorFns_oklab: typeof oklab; | ||
| declare const colorFns_oklch: typeof oklch; | ||
| declare const colorFns_rgb: typeof rgb; | ||
| declare namespace colorFns { | ||
| export { type colorFns_ColorMixSpace as ColorMixSpace, colorFns_alpha as alpha, colorFns_hsl as hsl, colorFns_hwb as hwb, colorFns_lab as lab, colorFns_lch as lch, colorFns_lightDark as lightDark, colorFns_mix as mix, colorFns_oklab as oklab, colorFns_oklch as oklch, colorFns_rgb as rgb }; | ||
| } | ||
| /** | ||
| * Type-safe CSS color function helpers (`rgb`, `oklch`, `mix`, …). | ||
| * Import from `typestyles/color` so the main entry stays lean. | ||
| */ | ||
| declare const color: typeof colorFns; | ||
| export { type ColorMixSpace, alpha, color, hsl, hwb, lab, lch, lightDark, mix, oklab, oklch, rgb }; |
+140
| /** | ||
| * Type-safe helpers for CSS color functions. | ||
| * | ||
| * Each function returns a plain CSS string — no runtime color math. | ||
| * Works naturally with token references since tokens are strings too. | ||
| */ | ||
| type ColorValue = string | number; | ||
| /** Color spaces supported by color-mix(). */ | ||
| type ColorMixSpace = 'srgb' | 'srgb-linear' | 'display-p3' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020' | 'lab' | 'oklab' | 'xyz' | 'xyz-d50' | 'xyz-d65' | 'hsl' | 'hwb' | 'lch' | 'oklch'; | ||
| /** | ||
| * `rgb(r g b)` or `rgb(r g b / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.rgb(0, 102, 255, 0.5) // "rgb(0 102 255 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hsl(h s l)` or `hsl(h s l / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hsl(220, '100%', '50%') // "hsl(220 100% 50%)" | ||
| * color.hsl(220, '100%', '50%', 0.8) // "hsl(220 100% 50% / 0.8)" | ||
| * ``` | ||
| */ | ||
| declare function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklch(L C h)` or `oklch(L C h / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.oklch(0.7, 0.15, 250, 0.5) // "oklch(0.7 0.15 250 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklab(L a b)` or `oklab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklab(0.7, -0.1, -0.1) // "oklab(0.7 -0.1 -0.1)" | ||
| * color.oklab(0.7, -0.1, -0.1, 0.5) // "oklab(0.7 -0.1 -0.1 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lab(L a b)` or `lab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lab('50%', 40, -20) // "lab(50% 40 -20)" | ||
| * ``` | ||
| */ | ||
| declare function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lch(L C h)` or `lch(L C h / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lch('50%', 80, 250) // "lch(50% 80 250)" | ||
| * ``` | ||
| */ | ||
| declare function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hwb(h w b)` or `hwb(h w b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hwb(220, '10%', '0%') // "hwb(220 10% 0%)" | ||
| * ``` | ||
| */ | ||
| declare function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `color-mix(in colorspace, color1 p1%, color2 p2%)` | ||
| * | ||
| * Mixes two colors in the given color space. Percentages are optional. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.mix('red', 'blue') // "color-mix(in srgb, red, blue)" | ||
| * color.mix('red', 'blue', 30) // "color-mix(in srgb, red 30%, blue)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.mix('red', 'blue', 50, 'oklch') // "color-mix(in oklch, red 50%, blue)" | ||
| * ``` | ||
| */ | ||
| declare function mix(color1: string, color2: string, percentage?: number, colorSpace?: ColorMixSpace): string; | ||
| /** | ||
| * `light-dark(lightColor, darkColor)` | ||
| * | ||
| * Uses the `light-dark()` CSS function that resolves based on | ||
| * the computed `color-scheme` of the element. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * color.lightDark(theme.textLight, theme.textDark) // "light-dark(var(--theme-textLight), var(--theme-textDark))" | ||
| * ``` | ||
| */ | ||
| declare function lightDark(lightColor: string, darkColor: string): string; | ||
| /** | ||
| * Adjust the alpha/opacity of any color using `color-mix()`. | ||
| * | ||
| * This is a common pattern: mixing a color with transparent to change opacity. | ||
| * Works with any color value including token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.alpha('red', 0.5) // "color-mix(in srgb, red 50%, transparent)" | ||
| * color.alpha(theme.primary, 0.2) // "color-mix(in srgb, var(--theme-primary) 20%, transparent)" | ||
| * color.alpha('#0066ff', 0.8, 'oklch') // "color-mix(in oklch, #0066ff 80%, transparent)" | ||
| * ``` | ||
| */ | ||
| declare function alpha(colorValue: string, opacity: number, colorSpace?: ColorMixSpace): string; | ||
| type colorFns_ColorMixSpace = ColorMixSpace; | ||
| declare const colorFns_alpha: typeof alpha; | ||
| declare const colorFns_hsl: typeof hsl; | ||
| declare const colorFns_hwb: typeof hwb; | ||
| declare const colorFns_lab: typeof lab; | ||
| declare const colorFns_lch: typeof lch; | ||
| declare const colorFns_lightDark: typeof lightDark; | ||
| declare const colorFns_mix: typeof mix; | ||
| declare const colorFns_oklab: typeof oklab; | ||
| declare const colorFns_oklch: typeof oklch; | ||
| declare const colorFns_rgb: typeof rgb; | ||
| declare namespace colorFns { | ||
| export { type colorFns_ColorMixSpace as ColorMixSpace, colorFns_alpha as alpha, colorFns_hsl as hsl, colorFns_hwb as hwb, colorFns_lab as lab, colorFns_lch as lch, colorFns_lightDark as lightDark, colorFns_mix as mix, colorFns_oklab as oklab, colorFns_oklch as oklch, colorFns_rgb as rgb }; | ||
| } | ||
| /** | ||
| * Type-safe CSS color function helpers (`rgb`, `oklch`, `mix`, …). | ||
| * Import from `typestyles/color` so the main entry stays lean. | ||
| */ | ||
| declare const color: typeof colorFns; | ||
| export { type ColorMixSpace, alpha, color, hsl, hwb, lab, lch, lightDark, mix, oklab, oklch, rgb }; |
| import { color_exports } from './chunk-U3WMOSLD.js'; | ||
| export { alpha, hsl, hwb, lab, lch, lightDark, mix, oklab, oklch, rgb } from './chunk-U3WMOSLD.js'; | ||
| import './chunk-PZ5AY32C.js'; | ||
| // src/color-entry.ts | ||
| var color = color_exports; | ||
| export { color }; | ||
| //# sourceMappingURL=color.js.map | ||
| //# sourceMappingURL=color.js.map |
| {"version":3,"sources":["../src/color-entry.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,KAAA,GAAQ","file":"color.js","sourcesContent":["export * from './color';\nimport * as colorFns from './color';\n\n/**\n * Type-safe CSS color function helpers (`rgb`, `oklch`, `mix`, …).\n * Import from `typestyles/color` so the main entry stays lean.\n */\nexport const color = colorFns;\n"]} |
| import * as CSS from 'csstype'; | ||
| /** | ||
| * A CSS value that can be a standard value or a token reference (var() string). | ||
| * | ||
| * Values are emitted verbatim. TypeScript does **not** validate CSS syntax, so a typo in | ||
| * `calc()`, `clamp()`, `min()`, `max()`, `url()`, etc. (for example a missing `)`) can produce | ||
| * invalid CSS that breaks parsing for following rules. Use **`calc`** (tagged template) and | ||
| * **`clamp`** from `typestyles` to keep function parentheses balanced, or small named helpers; | ||
| * see the docs “TypeScript Tips” page. | ||
| */ | ||
| type CSSValue = string | number; | ||
| /** | ||
| * CSS properties with support for nested selectors and at-rules. | ||
| * Extends csstype's Properties with nesting capabilities. | ||
| * | ||
| * For `@…` keys, **`container()`** / **`styles.container()`** infer a **literal** `@container …` template so | ||
| * `[container({ minWidth: 400 })]` mixes with longhands without casting. For **dynamic** `@…` strings, spread | ||
| * **`atRuleBlock` / `styles.atRuleBlock`**. Same idea for **`has` / `is` / `where`**: variadic literals narrow | ||
| * to `&:…` keys; if the key is only known as `string`, spread a one-key object or use `atRuleBlock`. | ||
| * | ||
| * **`@supports`** uses the same `` `@${string}` `` / `atRuleBlock` path; a first-class **`supports()`** helper | ||
| * (mirroring `container()`) would improve literals and authoring ergonomics for feature queries. | ||
| */ | ||
| interface CSSProperties extends CSS.Properties<CSSValue> { | ||
| /** Nested selector (e.g., '&:hover', `has('.x')`, '& .child', '&::before', '&[data-variant]') */ | ||
| [selector: `&${string}`]: CSSProperties; | ||
| /** | ||
| * Ancestor-prefixed selector where `&` is the styled element (e.g. `html[data-mode="dark"] &`, | ||
| * `html:not([data-mode="light"]) &`). Runtime serialization replaces every `&` with the class selector. | ||
| */ | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSProperties; | ||
| /** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */ | ||
| [attribute: `[${string}]`]: CSSProperties; | ||
| /** | ||
| * At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports'). | ||
| * TODO(typestyles): `supports()` helper for @supports (mirror `container()` literals and typing). | ||
| */ | ||
| [atRule: `@${string}`]: CSSProperties; | ||
| } | ||
| /** | ||
| * Utility function map used by `createStyles({ utils })` and `styles.withUtils()`. | ||
| * Each key becomes an extra style property that expands into CSSProperties. | ||
| */ | ||
| type BivariantCallback<Arg, Ret> = { | ||
| bivarianceHack(value: Arg): Ret; | ||
| }['bivarianceHack']; | ||
| type StyleUtils = Record<string, BivariantCallback<unknown, CSSProperties>>; | ||
| type UtilityValue<U extends StyleUtils, K extends keyof U> = U[K] extends (value: infer V) => CSSProperties ? V : never; | ||
| /** | ||
| * CSS properties augmented with user-defined utility keys. | ||
| */ | ||
| type CSSPropertiesWithUtils<U extends StyleUtils> = CSS.Properties<CSSValue> & { | ||
| [K in keyof U]?: UtilityValue<U, K>; | ||
| } & { | ||
| [selector: `&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [attribute: `[${string}]`]: CSSPropertiesWithUtils<U>; | ||
| /** @see {@link CSSProperties} at-rule index signature (TODO: `supports()` helper). */ | ||
| [atRule: `@${string}`]: CSSPropertiesWithUtils<U>; | ||
| }; | ||
| /** | ||
| * A map of style names to utility-aware CSS property definitions. | ||
| */ | ||
| type StyleDefinitionsWithUtils<U extends StyleUtils> = Record<string, CSSPropertiesWithUtils<U>>; | ||
| /** | ||
| * A map of variant names to their CSS property definitions. | ||
| */ | ||
| type StyleDefinitions = Record<string, CSSProperties>; | ||
| /** | ||
| * Opt-in leaf shape for `tokens.create` — registers `@property` when `syntax` is set | ||
| * and returns a `{ name, var, toString }` ref instead of a plain `var(...)` string. | ||
| */ | ||
| type TokenDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * A token value can be a string/number, a typed descriptor leaf, or a nested object. | ||
| * Supports arbitrarily deep nesting for hierarchical token structures. | ||
| */ | ||
| type TokenValues = string | number | TokenDescriptor | { | ||
| [key: string]: TokenValues; | ||
| }; | ||
| /** | ||
| * A flattened key-value pair for CSS custom property generation. | ||
| */ | ||
| type FlatTokenEntry = [key: string, value: string]; | ||
| /** | ||
| * A flattened token path with segment preservation for custom name templates. | ||
| */ | ||
| type FlatTokenPathEntry = { | ||
| path: string; | ||
| segments: readonly string[]; | ||
| value: string; | ||
| }; | ||
| /** | ||
| * Flattens a nested TokenValues object into an array of [key, value] pairs. | ||
| * Deeply nested objects are flattened with keys joined by hyphens. | ||
| * | ||
| * @example | ||
| * flattenTokens({ text: { primary: '#000' } }) | ||
| * // => [['text-primary', '#000']] | ||
| */ | ||
| declare function isTokenDescriptor(value: unknown): value is TokenDescriptor; | ||
| declare function flattenTokenEntries(obj: TokenValues, prefix?: string): FlatTokenEntry[]; | ||
| declare function flattenTokenPaths(obj: TokenValues, prefix?: string, segments?: readonly string[]): FlatTokenPathEntry[]; | ||
| /** | ||
| * Reference to a registered CSS custom property with `.name`, `.var`, and string coercion. | ||
| */ | ||
| type RegisteredPropertyRef = { | ||
| readonly name: string; | ||
| readonly var: CSSVarRef; | ||
| toString(): string; | ||
| valueOf(): string; | ||
| }; | ||
| /** Options for `styles.property(id, options?)`. */ | ||
| type RegisteredPropertyOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| type TokenRefLeaf<V> = V extends TokenDescriptor ? RegisteredPropertyRef : V extends string | number ? string : V extends TokenValues ? TokenRef<V> : string; | ||
| /** | ||
| * A typed token reference object. Property access returns var(--namespace-key) strings | ||
| * or {@link RegisteredPropertyRef} for descriptor leaves. | ||
| * Supports nested access: token.text.primary => var(--namespace-text-primary) | ||
| */ | ||
| type TokenRef<T extends TokenValues> = T extends string | number ? string : T extends TokenDescriptor ? RegisteredPropertyRef : { | ||
| readonly [K in keyof T]: TokenRefLeaf<T[K]>; | ||
| }; | ||
| declare const CreatedTokenBrand: unique symbol; | ||
| /** | ||
| * Return type of `tokens.create()` — a `TokenRef` branded with its value shape and namespace | ||
| * so `tokens.use(created)` can infer types across packages. | ||
| */ | ||
| type CreatedTokenRef<T extends TokenValues = TokenValues, N extends string = string> = TokenRef<T> & { | ||
| readonly [CreatedTokenBrand]: { | ||
| readonly values: T; | ||
| readonly namespace: N; | ||
| }; | ||
| }; | ||
| /** Extract token value shape from a `tokens.create()` return value. */ | ||
| type InferTokenValues<R> = R extends CreatedTokenRef<infer T, string> ? T extends TokenValues ? T : TokenValues : TokenValues; | ||
| /** Extract namespace literal from a `tokens.create()` return value. */ | ||
| type InferTokenNamespace<R> = R extends CreatedTokenRef<TokenValues, infer N> ? (N extends string ? N : string) : string; | ||
| /** Registry of token namespaces to value shapes for `createTokens<Registry>()`. */ | ||
| type TokenRegistry = Record<string, TokenValues>; | ||
| /** | ||
| * Nested token values where any object level may omit keys (for mode layers that | ||
| * only tweak a subtree of `base`). | ||
| */ | ||
| type DeepPartialTokenValues = string | number | { | ||
| [key: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Theme overrides: namespaces map to full or deeply partial token trees. | ||
| * Aligns with `tokens.create` namespaces; mode `overrides` often only set a subset of keys. | ||
| */ | ||
| type ThemeOverrides = { | ||
| [namespace: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Keyframe stops: 'from', 'to', or percentage strings mapped to CSS properties. | ||
| */ | ||
| type KeyframeStops = Record<string, CSSProperties>; | ||
| /** Match a media query (e.g. `(prefers-color-scheme: dark)`). */ | ||
| type ThemeConditionMedia = { | ||
| readonly type: 'media'; | ||
| readonly query: string; | ||
| }; | ||
| /** Match an attribute on the themed element (`self`), an ancestor (`ancestor`), or a descendant of the theme root (`descendant`). */ | ||
| type ThemeConditionAttr = { | ||
| readonly type: 'attr'; | ||
| readonly name: string; | ||
| readonly value: string; | ||
| readonly scope: 'self' | 'ancestor' | 'descendant'; | ||
| }; | ||
| /** Match a class on the themed element (`self`), an ancestor (`ancestor`), or a descendant of the theme root (`descendant`). */ | ||
| type ThemeConditionClass = { | ||
| readonly type: 'class'; | ||
| readonly name: string; | ||
| readonly scope: 'self' | 'ancestor' | 'descendant'; | ||
| }; | ||
| /** Raw selector escape hatch — the selector is used as an ancestor context for the theme class. */ | ||
| type ThemeConditionSelector = { | ||
| readonly type: 'selector'; | ||
| readonly selector: string; | ||
| }; | ||
| /** All child conditions must hold. */ | ||
| type ThemeConditionAnd = { | ||
| readonly type: 'and'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Any child condition must hold (emits separate rules per branch). */ | ||
| type ThemeConditionOr = { | ||
| readonly type: 'or'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Negate a single-branch condition (see `tokens.when.not` JSDoc for limits). */ | ||
| type ThemeConditionNot = { | ||
| readonly type: 'not'; | ||
| readonly condition: ThemeCondition; | ||
| }; | ||
| /** | ||
| * A condition that determines **when** a set of token overrides applies. | ||
| * Conditions compile to media queries, selector prefixes/suffixes, or combinations. | ||
| */ | ||
| type ThemeCondition = ThemeConditionMedia | ThemeConditionAttr | ThemeConditionClass | ThemeConditionSelector | ThemeConditionAnd | ThemeConditionOr | ThemeConditionNot; | ||
| /** | ||
| * A single mode layer within a theme surface. | ||
| * Applies `overrides` when `when` is satisfied. | ||
| */ | ||
| type ThemeModeDefinition = { | ||
| readonly id: string; | ||
| readonly overrides: ThemeOverrides; | ||
| readonly when: ThemeCondition; | ||
| }; | ||
| /** | ||
| * Configuration for `tokens.createTheme()`. | ||
| * Provide `modes` (manual) **or** `colorMode` (preset), not both. | ||
| */ | ||
| type ThemeConfig = { | ||
| /** Base token overrides — emitted as `.theme-{name} { … }`. */ | ||
| base?: ThemeOverrides; | ||
| /** Manual mode layers with explicit conditions. Mutually exclusive with `colorMode`. */ | ||
| modes?: ThemeModeDefinition[]; | ||
| /** Preset mode layers from `tokens.colorMode.*`. Mutually exclusive with `modes`. */ | ||
| colorMode?: ThemeModeDefinition[]; | ||
| }; | ||
| /** | ||
| * The object returned by `tokens.createTheme()`. | ||
| * | ||
| * - `surface.className` — the generated class name (e.g. `"theme-acme"`) | ||
| * - `surface.name` — the theme name (e.g. `"acme"`) | ||
| * - `String(surface)` / template interpolation — coerces to `className` | ||
| */ | ||
| interface ThemeSurface { | ||
| readonly className: string; | ||
| readonly name: string; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * The object returned by calling a `styles.component()` instance created with | ||
| * `mode: 'attribute'`. | ||
| * | ||
| * - `className` — the single base class (no per-option classes exist in attribute mode). | ||
| * - `attrs` — resolved `data-{dimension}` attribute pairs for the current selections. Boolean | ||
| * dimensions (`{ true: {...}, false: {...} }`) are presence-based: `true` → empty-string value, | ||
| * `false` → key omitted. | ||
| * - `props` — `attrs` merged with `className`, ready to spread onto an element. | ||
| * - `String(result)` / template-literal coercion returns `className`, same as `ThemeSurface`. | ||
| */ | ||
| interface ComponentAttrsResult { | ||
| readonly className: string; | ||
| readonly attrs: Readonly<Record<string, string>>; | ||
| readonly props: Readonly<Record<string, string>>; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * Styles for a single variant option (or slot variant block). | ||
| * Union with a permissive record so **`[v.name]: value`** from {@link ComponentInternalVarRef} | ||
| * (custom properties) infers as `{ [key: string]: … }` and still matches — that shape is not | ||
| * assignable to {@link CSSProperties} alone, which would otherwise reject the dimensioned overload | ||
| * and fall through to unrelated `component` overloads. **`Record<string, unknown>`** also covers | ||
| * objects that mix custom-property keys with nested selector blocks like `'&:hover'`. | ||
| */ | ||
| type VariantOptionStyle = CSSProperties | Record<string, unknown>; | ||
| /** | ||
| * A map of variant dimensions to their options (each option is {@link VariantOptionStyle}). | ||
| */ | ||
| type VariantDefinitions = Record<string, Record<string, VariantOptionStyle>>; | ||
| type SlotStyles<S extends string> = Partial<Record<S, VariantOptionStyle>>; | ||
| type SlotVariantDefinitions<S extends string> = Record<string, Record<string, SlotStyles<S>>>; | ||
| type VariantDimensions = Record<string, Record<string, unknown>>; | ||
| type VariantOptionKey<V extends VariantDimensions, K extends keyof V> = Extract<keyof V[K], string>; | ||
| type VariantSelectionValue<OptionKey extends string> = OptionKey | (Extract<OptionKey, 'true'> extends never ? never : true) | (Extract<OptionKey, 'false'> extends never ? never : false); | ||
| type CompoundSelectionValue<OptionKey extends string> = VariantSelectionValue<OptionKey> | readonly VariantSelectionValue<OptionKey>[]; | ||
| type ComponentSelections<V extends VariantDimensions> = { | ||
| [K in keyof V]?: VariantSelectionValue<VariantOptionKey<V, K>> | null | undefined; | ||
| }; | ||
| /** | ||
| * A CSS custom property reference as a `var(--…)` value (tokens, `createVar()`, component internal vars). | ||
| */ | ||
| type CSSVarRef = `var(--${string})` | `var(--${string}, ${string})`; | ||
| /** | ||
| * Leaf shape for `ctx.vars({ … })` — mirrors typed tokens: `value` is the default (merged into `base`); | ||
| * optional `syntax` / `inherits` register `@property` like typed design tokens. | ||
| */ | ||
| type ComponentVarDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Nested map of component internal vars (same nesting as `tokens.create` / theme token trees). | ||
| */ | ||
| type ComponentVarNode = string | number | ComponentVarDescriptor | { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| type ComponentVarDefinitions = { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| /** | ||
| * Options for `ctx.var(id, options?)`. Set `value` to merge a default into `base` and as `@property` initial-value when `syntax` is set. | ||
| */ | ||
| type ComponentVarOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Reference to a component-scoped custom property: `.name` for declaration keys and transitions, `.var` for values. | ||
| */ | ||
| type ComponentInternalVarRef = RegisteredPropertyRef; | ||
| /** | ||
| * Context passed to `styles.component(namespace, (ctx) => { ... })` to declare internal custom properties. | ||
| */ | ||
| /** Proxy tree returned by `ctx.vars({ … })` — leaves are `{ name, var }`, nested objects are sub-trees. */ | ||
| type ComponentVarRefTree<T> = { | ||
| [K in keyof T]: T[K] extends ComponentVarDescriptor | string | number ? ComponentInternalVarRef : ComponentVarRefTree<T[K]>; | ||
| }; | ||
| type ComponentConfigContext = { | ||
| var: (id: string, options?: ComponentVarOptions) => ComponentInternalVarRef; | ||
| vars: <const T extends ComponentVarDefinitions>(definitions: T) => ComponentVarRefTree<T>; | ||
| }; | ||
| /** | ||
| * The full config object passed to styles.component() with dimensioned variants. How `variants` | ||
| * compiles (discrete classes, `&[data-x="y"]` attributes, or BEM modifier classes) is selected by | ||
| * `createStyles({ mode })`, not by anything in this config — see {@link ComponentAttrsReturn} and | ||
| * `specs/attribute-driven-variants.md` / `specs/bem-variant-mode.md`. | ||
| */ | ||
| type ComponentConfig<V extends VariantDefinitions> = { | ||
| base?: CSSProperties; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: VariantOptionStyle; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| /** | ||
| * Config for flat variants: `{ base: {...}, elevated: {...}, compact: {...} }`. | ||
| * Each key besides `base` is a boolean-style variant. | ||
| * | ||
| * **`variants`**, **`defaultVariants`**, **`compoundVariants`**, and **`slots`** are forbidden | ||
| * on this shape so TypeScript does not pick the flat overload for CVA-style or slot configs. | ||
| * Nested variant maps can otherwise satisfy {@link CSSProperties} too loosely (index signatures), | ||
| * which produced wrong callable types for `styles.component(ns, (ctx) => ({ variants: … }), { layer })` | ||
| * when cascade layers are enabled. | ||
| */ | ||
| type FlatComponentConfig<K extends string> = { | ||
| base?: CSSProperties; | ||
| variants?: never; | ||
| defaultVariants?: never; | ||
| compoundVariants?: never; | ||
| slots?: never; | ||
| } & Record<K, CSSProperties>; | ||
| /** | ||
| * Selection object for flat variants: `{ elevated: true, compact: true }`. | ||
| */ | ||
| type FlatComponentSelections<K extends string> = { | ||
| [P in K]?: boolean | null | undefined; | ||
| }; | ||
| /** | ||
| * All possible variant class string keys that can be destructured from a | ||
| * dimensioned component. Includes 'base' plus all `{dimension}-{option}` keys | ||
| * flattened from the variants config. | ||
| */ | ||
| type DimensionedVariantKeys<V extends VariantDefinitions> = { | ||
| [D in keyof V]: keyof V[D] extends string ? `${D & string}-${keyof V[D] & string}` : never; | ||
| }[keyof V]; | ||
| /** | ||
| * The CVA-style return for dimensioned variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type ComponentReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: ComponentSelections<V>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings, keyed as `{dimension}-{option}`. */ | ||
| readonly [K in DimensionedVariantKeys<V>]: string; | ||
| }; | ||
| /** | ||
| * The return for dimensioned variants compiled with `mode: 'attribute'`. | ||
| * Callable, returning a {@link ComponentAttrsResult}. No per-option destructurable keys — there | ||
| * are no discrete option classes in attribute mode, only the single `base` class. | ||
| */ | ||
| type ComponentAttrsReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get the resolved `{ className, attrs, props }` result. */ | ||
| (selections?: ComponentSelections<V>): ComponentAttrsResult; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| }; | ||
| /** | ||
| * The CVA-style return for flat variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type FlatComponentReturn<K extends string> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: FlatComponentSelections<Exclude<K, 'base'>>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings. */ | ||
| readonly [P in Exclude<K, 'base'>]: string; | ||
| }; | ||
| type MultiSlotConfig<Slots extends readonly string[]> = { | ||
| slots: Slots; | ||
| } & Partial<Record<Slots[number], CSSProperties>>; | ||
| type MultiSlotReturn<Slots extends readonly string[]> = { | ||
| (): Record<Slots[number], string>; | ||
| } & { | ||
| readonly [K in Slots[number]]: string; | ||
| }; | ||
| type SlotComponentConfig<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = { | ||
| slots: Slots; | ||
| base?: SlotStyles<Slots[number]>; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: SlotStyles<Slots[number]>; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| type SlotComponentFunction<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = (selections?: ComponentSelections<V>) => Record<Slots[number], string>; | ||
| /** | ||
| * Config for `styles.component` may be a plain object or a function that receives {@link ComponentConfigContext}. | ||
| */ | ||
| type ComponentConfigInput<V extends VariantDefinitions> = ComponentConfig<V> | ((ctx: ComponentConfigContext) => ComponentConfig<V>); | ||
| type FlatComponentConfigInput<K extends string> = FlatComponentConfig<K> | ((ctx: ComponentConfigContext) => FlatComponentConfig<K>); | ||
| type SlotComponentConfigInput<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = SlotComponentConfig<Slots, V> | ((ctx: ComponentConfigContext) => SlotComponentConfig<Slots, V>); | ||
| type MultiSlotConfigInput<Slots extends readonly string[]> = MultiSlotConfig<Slots> | ((ctx: ComponentConfigContext) => MultiSlotConfig<Slots>); | ||
| /** | ||
| * Extract the variant prop types from a ComponentReturn or ComponentFunction. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const button = styles.component('button', { | ||
| * variants: { | ||
| * intent: { primary: {...}, ghost: {...} }, | ||
| * size: { sm: {...}, lg: {...} }, | ||
| * }, | ||
| * }); | ||
| * | ||
| * type ButtonProps = ComponentVariants<typeof button>; | ||
| * // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' } | ||
| * ``` | ||
| */ | ||
| type ComponentVariants<T> = T extends (selections?: ComponentSelections<infer V>) => unknown ? { | ||
| [K in keyof V]?: keyof V[K]; | ||
| } : never; | ||
| /** Input accepted by {@link compose}: component fn, class string, or falsy skip. */ | ||
| type ComposeSelectorInput = string | false | null | undefined | ((selections?: Record<string, unknown>) => string); | ||
| type ComposeSelectorSelections<T> = T extends (selections?: infer S) => string ? S extends undefined ? Record<string, never> : NonNullable<S> : Record<string, never>; | ||
| /** Union of variant selection objects accepted by all composed component functions. */ | ||
| type MergeComposeSelections<Selectors extends readonly unknown[]> = Selectors extends readonly [infer Head, ...infer Tail] ? ComposeSelectorSelections<Head> & MergeComposeSelections<Tail> : Record<string, never>; | ||
| type AnyComposeFn<Selectors extends readonly ComposeSelectorInput[]> = Selectors[number] extends (...args: unknown[]) => string ? true : false; | ||
| /** Return type of {@link compose}: callable with merged variant selections when any input is a function. */ | ||
| type ComposeFn<Selectors extends readonly ComposeSelectorInput[]> = AnyComposeFn<Selectors> extends true ? (selections?: MergeComposeSelections<Selectors>) => string : () => string; | ||
| /** | ||
| * `src` value for {@link FontFaceProps}: a single CSS `src` fragment or multiple | ||
| * fragments joined with commas (same as authoring `url(...), local(...)` by hand). | ||
| */ | ||
| type FontFaceSrc = string | readonly string[]; | ||
| /** | ||
| * Font face property declarations. | ||
| * | ||
| * Maps to standard `@font-face` descriptors. Values are emitted verbatim in CSS. | ||
| */ | ||
| type FontFaceProps = { | ||
| src: FontFaceSrc; | ||
| fontWeight?: string | number; | ||
| fontStyle?: 'normal' | 'italic' | 'oblique' | string; | ||
| fontDisplay?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'; | ||
| fontStretch?: string; | ||
| unicodeRange?: string; | ||
| /** `size-adjust` — fallback tuning and font-size-adjust related metrics. */ | ||
| sizeAdjust?: string; | ||
| /** `ascent-override` */ | ||
| ascentOverride?: string; | ||
| /** `descent-override` */ | ||
| descentOverride?: string; | ||
| /** `line-gap-override` */ | ||
| lineGapOverride?: string; | ||
| }; | ||
| /** | ||
| * Return type of helpers in `typestyles/globals`, passed to `global.style(…)`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * global.style(boxSizing()); | ||
| * global.style(body({ margin: 0 }, { layer: 'components' })); | ||
| * ``` | ||
| */ | ||
| type GlobalStyleTuple = readonly [selector: string, properties: CSSProperties] | readonly [selector: string, properties: CSSProperties, options: { | ||
| layer?: string; | ||
| }]; | ||
| export { type FontFaceSrc as $, type FontFaceProps as A, type CSSVarRef as B, type CSSProperties as C, type CSSValue as D, type ComponentAttrsResult as E, type FlatComponentConfigInput as F, type GlobalStyleTuple as G, type ComponentConfig as H, type ComponentConfigContext as I, type ComponentInternalVarRef as J, type ComponentSelections as K, type ComponentVarDefinitions as L, type MultiSlotConfigInput as M, type ComponentVarDescriptor as N, type ComponentVarNode as O, type ComponentVarOptions as P, type ComponentVarRefTree as Q, type RegisteredPropertyOptions as R, type SlotVariantDefinitions as S, type ThemeConditionMedia as T, type ComponentVariants as U, type VariantDefinitions as V, type DeepPartialTokenValues as W, type FlatComponentConfig as X, type FlatComponentSelections as Y, type FlatTokenEntry as Z, type FlatTokenPathEntry as _, type ThemeConditionAttr as a, type InferTokenNamespace as a0, type InferTokenValues as a1, type KeyframeStops as a2, type MergeComposeSelections as a3, type SlotComponentConfig as a4, type SlotStyles as a5, type StyleDefinitions as a6, type StyleDefinitionsWithUtils as a7, type ThemeConditionNot as a8, type TokenDescriptor as a9, type VariantOptionStyle as aa, flattenTokenEntries as ab, flattenTokenPaths as ac, isTokenDescriptor as ad, type ThemeConditionClass as b, type ThemeConditionSelector as c, type ThemeCondition as d, type ThemeConditionAnd as e, type ThemeConditionOr as f, type ThemeOverrides as g, type ThemeModeDefinition as h, type ThemeSurface as i, type ThemeConfig as j, type TokenRegistry as k, type TokenValues as l, type CreatedTokenRef as m, type TokenRef as n, type ComponentConfigInput as o, type ComponentAttrsReturn as p, type FlatComponentReturn as q, type RegisteredPropertyRef as r, type ComponentReturn as s, type SlotComponentConfigInput as t, type SlotComponentFunction as u, type MultiSlotReturn as v, type StyleUtils as w, type CSSPropertiesWithUtils as x, type ComposeSelectorInput as y, type ComposeFn as z }; |
| import * as CSS from 'csstype'; | ||
| /** | ||
| * A CSS value that can be a standard value or a token reference (var() string). | ||
| * | ||
| * Values are emitted verbatim. TypeScript does **not** validate CSS syntax, so a typo in | ||
| * `calc()`, `clamp()`, `min()`, `max()`, `url()`, etc. (for example a missing `)`) can produce | ||
| * invalid CSS that breaks parsing for following rules. Use **`calc`** (tagged template) and | ||
| * **`clamp`** from `typestyles` to keep function parentheses balanced, or small named helpers; | ||
| * see the docs “TypeScript Tips” page. | ||
| */ | ||
| type CSSValue = string | number; | ||
| /** | ||
| * CSS properties with support for nested selectors and at-rules. | ||
| * Extends csstype's Properties with nesting capabilities. | ||
| * | ||
| * For `@…` keys, **`container()`** / **`styles.container()`** infer a **literal** `@container …` template so | ||
| * `[container({ minWidth: 400 })]` mixes with longhands without casting. For **dynamic** `@…` strings, spread | ||
| * **`atRuleBlock` / `styles.atRuleBlock`**. Same idea for **`has` / `is` / `where`**: variadic literals narrow | ||
| * to `&:…` keys; if the key is only known as `string`, spread a one-key object or use `atRuleBlock`. | ||
| * | ||
| * **`@supports`** uses the same `` `@${string}` `` / `atRuleBlock` path; a first-class **`supports()`** helper | ||
| * (mirroring `container()`) would improve literals and authoring ergonomics for feature queries. | ||
| */ | ||
| interface CSSProperties extends CSS.Properties<CSSValue> { | ||
| /** Nested selector (e.g., '&:hover', `has('.x')`, '& .child', '&::before', '&[data-variant]') */ | ||
| [selector: `&${string}`]: CSSProperties; | ||
| /** | ||
| * Ancestor-prefixed selector where `&` is the styled element (e.g. `html[data-mode="dark"] &`, | ||
| * `html:not([data-mode="light"]) &`). Runtime serialization replaces every `&` with the class selector. | ||
| */ | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSProperties; | ||
| /** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */ | ||
| [attribute: `[${string}]`]: CSSProperties; | ||
| /** | ||
| * At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports'). | ||
| * TODO(typestyles): `supports()` helper for @supports (mirror `container()` literals and typing). | ||
| */ | ||
| [atRule: `@${string}`]: CSSProperties; | ||
| } | ||
| /** | ||
| * Utility function map used by `createStyles({ utils })` and `styles.withUtils()`. | ||
| * Each key becomes an extra style property that expands into CSSProperties. | ||
| */ | ||
| type BivariantCallback<Arg, Ret> = { | ||
| bivarianceHack(value: Arg): Ret; | ||
| }['bivarianceHack']; | ||
| type StyleUtils = Record<string, BivariantCallback<unknown, CSSProperties>>; | ||
| type UtilityValue<U extends StyleUtils, K extends keyof U> = U[K] extends (value: infer V) => CSSProperties ? V : never; | ||
| /** | ||
| * CSS properties augmented with user-defined utility keys. | ||
| */ | ||
| type CSSPropertiesWithUtils<U extends StyleUtils> = CSS.Properties<CSSValue> & { | ||
| [K in keyof U]?: UtilityValue<U, K>; | ||
| } & { | ||
| [selector: `&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [attribute: `[${string}]`]: CSSPropertiesWithUtils<U>; | ||
| /** @see {@link CSSProperties} at-rule index signature (TODO: `supports()` helper). */ | ||
| [atRule: `@${string}`]: CSSPropertiesWithUtils<U>; | ||
| }; | ||
| /** | ||
| * A map of style names to utility-aware CSS property definitions. | ||
| */ | ||
| type StyleDefinitionsWithUtils<U extends StyleUtils> = Record<string, CSSPropertiesWithUtils<U>>; | ||
| /** | ||
| * A map of variant names to their CSS property definitions. | ||
| */ | ||
| type StyleDefinitions = Record<string, CSSProperties>; | ||
| /** | ||
| * Opt-in leaf shape for `tokens.create` — registers `@property` when `syntax` is set | ||
| * and returns a `{ name, var, toString }` ref instead of a plain `var(...)` string. | ||
| */ | ||
| type TokenDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * A token value can be a string/number, a typed descriptor leaf, or a nested object. | ||
| * Supports arbitrarily deep nesting for hierarchical token structures. | ||
| */ | ||
| type TokenValues = string | number | TokenDescriptor | { | ||
| [key: string]: TokenValues; | ||
| }; | ||
| /** | ||
| * A flattened key-value pair for CSS custom property generation. | ||
| */ | ||
| type FlatTokenEntry = [key: string, value: string]; | ||
| /** | ||
| * A flattened token path with segment preservation for custom name templates. | ||
| */ | ||
| type FlatTokenPathEntry = { | ||
| path: string; | ||
| segments: readonly string[]; | ||
| value: string; | ||
| }; | ||
| /** | ||
| * Flattens a nested TokenValues object into an array of [key, value] pairs. | ||
| * Deeply nested objects are flattened with keys joined by hyphens. | ||
| * | ||
| * @example | ||
| * flattenTokens({ text: { primary: '#000' } }) | ||
| * // => [['text-primary', '#000']] | ||
| */ | ||
| declare function isTokenDescriptor(value: unknown): value is TokenDescriptor; | ||
| declare function flattenTokenEntries(obj: TokenValues, prefix?: string): FlatTokenEntry[]; | ||
| declare function flattenTokenPaths(obj: TokenValues, prefix?: string, segments?: readonly string[]): FlatTokenPathEntry[]; | ||
| /** | ||
| * Reference to a registered CSS custom property with `.name`, `.var`, and string coercion. | ||
| */ | ||
| type RegisteredPropertyRef = { | ||
| readonly name: string; | ||
| readonly var: CSSVarRef; | ||
| toString(): string; | ||
| valueOf(): string; | ||
| }; | ||
| /** Options for `styles.property(id, options?)`. */ | ||
| type RegisteredPropertyOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| type TokenRefLeaf<V> = V extends TokenDescriptor ? RegisteredPropertyRef : V extends string | number ? string : V extends TokenValues ? TokenRef<V> : string; | ||
| /** | ||
| * A typed token reference object. Property access returns var(--namespace-key) strings | ||
| * or {@link RegisteredPropertyRef} for descriptor leaves. | ||
| * Supports nested access: token.text.primary => var(--namespace-text-primary) | ||
| */ | ||
| type TokenRef<T extends TokenValues> = T extends string | number ? string : T extends TokenDescriptor ? RegisteredPropertyRef : { | ||
| readonly [K in keyof T]: TokenRefLeaf<T[K]>; | ||
| }; | ||
| declare const CreatedTokenBrand: unique symbol; | ||
| /** | ||
| * Return type of `tokens.create()` — a `TokenRef` branded with its value shape and namespace | ||
| * so `tokens.use(created)` can infer types across packages. | ||
| */ | ||
| type CreatedTokenRef<T extends TokenValues = TokenValues, N extends string = string> = TokenRef<T> & { | ||
| readonly [CreatedTokenBrand]: { | ||
| readonly values: T; | ||
| readonly namespace: N; | ||
| }; | ||
| }; | ||
| /** Extract token value shape from a `tokens.create()` return value. */ | ||
| type InferTokenValues<R> = R extends CreatedTokenRef<infer T, string> ? T extends TokenValues ? T : TokenValues : TokenValues; | ||
| /** Extract namespace literal from a `tokens.create()` return value. */ | ||
| type InferTokenNamespace<R> = R extends CreatedTokenRef<TokenValues, infer N> ? (N extends string ? N : string) : string; | ||
| /** Registry of token namespaces to value shapes for `createTokens<Registry>()`. */ | ||
| type TokenRegistry = Record<string, TokenValues>; | ||
| /** | ||
| * Nested token values where any object level may omit keys (for mode layers that | ||
| * only tweak a subtree of `base`). | ||
| */ | ||
| type DeepPartialTokenValues = string | number | { | ||
| [key: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Theme overrides: namespaces map to full or deeply partial token trees. | ||
| * Aligns with `tokens.create` namespaces; mode `overrides` often only set a subset of keys. | ||
| */ | ||
| type ThemeOverrides = { | ||
| [namespace: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Keyframe stops: 'from', 'to', or percentage strings mapped to CSS properties. | ||
| */ | ||
| type KeyframeStops = Record<string, CSSProperties>; | ||
| /** Match a media query (e.g. `(prefers-color-scheme: dark)`). */ | ||
| type ThemeConditionMedia = { | ||
| readonly type: 'media'; | ||
| readonly query: string; | ||
| }; | ||
| /** Match an attribute on the themed element (`self`), an ancestor (`ancestor`), or a descendant of the theme root (`descendant`). */ | ||
| type ThemeConditionAttr = { | ||
| readonly type: 'attr'; | ||
| readonly name: string; | ||
| readonly value: string; | ||
| readonly scope: 'self' | 'ancestor' | 'descendant'; | ||
| }; | ||
| /** Match a class on the themed element (`self`), an ancestor (`ancestor`), or a descendant of the theme root (`descendant`). */ | ||
| type ThemeConditionClass = { | ||
| readonly type: 'class'; | ||
| readonly name: string; | ||
| readonly scope: 'self' | 'ancestor' | 'descendant'; | ||
| }; | ||
| /** Raw selector escape hatch — the selector is used as an ancestor context for the theme class. */ | ||
| type ThemeConditionSelector = { | ||
| readonly type: 'selector'; | ||
| readonly selector: string; | ||
| }; | ||
| /** All child conditions must hold. */ | ||
| type ThemeConditionAnd = { | ||
| readonly type: 'and'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Any child condition must hold (emits separate rules per branch). */ | ||
| type ThemeConditionOr = { | ||
| readonly type: 'or'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Negate a single-branch condition (see `tokens.when.not` JSDoc for limits). */ | ||
| type ThemeConditionNot = { | ||
| readonly type: 'not'; | ||
| readonly condition: ThemeCondition; | ||
| }; | ||
| /** | ||
| * A condition that determines **when** a set of token overrides applies. | ||
| * Conditions compile to media queries, selector prefixes/suffixes, or combinations. | ||
| */ | ||
| type ThemeCondition = ThemeConditionMedia | ThemeConditionAttr | ThemeConditionClass | ThemeConditionSelector | ThemeConditionAnd | ThemeConditionOr | ThemeConditionNot; | ||
| /** | ||
| * A single mode layer within a theme surface. | ||
| * Applies `overrides` when `when` is satisfied. | ||
| */ | ||
| type ThemeModeDefinition = { | ||
| readonly id: string; | ||
| readonly overrides: ThemeOverrides; | ||
| readonly when: ThemeCondition; | ||
| }; | ||
| /** | ||
| * Configuration for `tokens.createTheme()`. | ||
| * Provide `modes` (manual) **or** `colorMode` (preset), not both. | ||
| */ | ||
| type ThemeConfig = { | ||
| /** Base token overrides — emitted as `.theme-{name} { … }`. */ | ||
| base?: ThemeOverrides; | ||
| /** Manual mode layers with explicit conditions. Mutually exclusive with `colorMode`. */ | ||
| modes?: ThemeModeDefinition[]; | ||
| /** Preset mode layers from `tokens.colorMode.*`. Mutually exclusive with `modes`. */ | ||
| colorMode?: ThemeModeDefinition[]; | ||
| }; | ||
| /** | ||
| * The object returned by `tokens.createTheme()`. | ||
| * | ||
| * - `surface.className` — the generated class name (e.g. `"theme-acme"`) | ||
| * - `surface.name` — the theme name (e.g. `"acme"`) | ||
| * - `String(surface)` / template interpolation — coerces to `className` | ||
| */ | ||
| interface ThemeSurface { | ||
| readonly className: string; | ||
| readonly name: string; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * The object returned by calling a `styles.component()` instance created with | ||
| * `mode: 'attribute'`. | ||
| * | ||
| * - `className` — the single base class (no per-option classes exist in attribute mode). | ||
| * - `attrs` — resolved `data-{dimension}` attribute pairs for the current selections. Boolean | ||
| * dimensions (`{ true: {...}, false: {...} }`) are presence-based: `true` → empty-string value, | ||
| * `false` → key omitted. | ||
| * - `props` — `attrs` merged with `className`, ready to spread onto an element. | ||
| * - `String(result)` / template-literal coercion returns `className`, same as `ThemeSurface`. | ||
| */ | ||
| interface ComponentAttrsResult { | ||
| readonly className: string; | ||
| readonly attrs: Readonly<Record<string, string>>; | ||
| readonly props: Readonly<Record<string, string>>; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * Styles for a single variant option (or slot variant block). | ||
| * Union with a permissive record so **`[v.name]: value`** from {@link ComponentInternalVarRef} | ||
| * (custom properties) infers as `{ [key: string]: … }` and still matches — that shape is not | ||
| * assignable to {@link CSSProperties} alone, which would otherwise reject the dimensioned overload | ||
| * and fall through to unrelated `component` overloads. **`Record<string, unknown>`** also covers | ||
| * objects that mix custom-property keys with nested selector blocks like `'&:hover'`. | ||
| */ | ||
| type VariantOptionStyle = CSSProperties | Record<string, unknown>; | ||
| /** | ||
| * A map of variant dimensions to their options (each option is {@link VariantOptionStyle}). | ||
| */ | ||
| type VariantDefinitions = Record<string, Record<string, VariantOptionStyle>>; | ||
| type SlotStyles<S extends string> = Partial<Record<S, VariantOptionStyle>>; | ||
| type SlotVariantDefinitions<S extends string> = Record<string, Record<string, SlotStyles<S>>>; | ||
| type VariantDimensions = Record<string, Record<string, unknown>>; | ||
| type VariantOptionKey<V extends VariantDimensions, K extends keyof V> = Extract<keyof V[K], string>; | ||
| type VariantSelectionValue<OptionKey extends string> = OptionKey | (Extract<OptionKey, 'true'> extends never ? never : true) | (Extract<OptionKey, 'false'> extends never ? never : false); | ||
| type CompoundSelectionValue<OptionKey extends string> = VariantSelectionValue<OptionKey> | readonly VariantSelectionValue<OptionKey>[]; | ||
| type ComponentSelections<V extends VariantDimensions> = { | ||
| [K in keyof V]?: VariantSelectionValue<VariantOptionKey<V, K>> | null | undefined; | ||
| }; | ||
| /** | ||
| * A CSS custom property reference as a `var(--…)` value (tokens, `createVar()`, component internal vars). | ||
| */ | ||
| type CSSVarRef = `var(--${string})` | `var(--${string}, ${string})`; | ||
| /** | ||
| * Leaf shape for `ctx.vars({ … })` — mirrors typed tokens: `value` is the default (merged into `base`); | ||
| * optional `syntax` / `inherits` register `@property` like typed design tokens. | ||
| */ | ||
| type ComponentVarDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Nested map of component internal vars (same nesting as `tokens.create` / theme token trees). | ||
| */ | ||
| type ComponentVarNode = string | number | ComponentVarDescriptor | { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| type ComponentVarDefinitions = { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| /** | ||
| * Options for `ctx.var(id, options?)`. Set `value` to merge a default into `base` and as `@property` initial-value when `syntax` is set. | ||
| */ | ||
| type ComponentVarOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Reference to a component-scoped custom property: `.name` for declaration keys and transitions, `.var` for values. | ||
| */ | ||
| type ComponentInternalVarRef = RegisteredPropertyRef; | ||
| /** | ||
| * Context passed to `styles.component(namespace, (ctx) => { ... })` to declare internal custom properties. | ||
| */ | ||
| /** Proxy tree returned by `ctx.vars({ … })` — leaves are `{ name, var }`, nested objects are sub-trees. */ | ||
| type ComponentVarRefTree<T> = { | ||
| [K in keyof T]: T[K] extends ComponentVarDescriptor | string | number ? ComponentInternalVarRef : ComponentVarRefTree<T[K]>; | ||
| }; | ||
| type ComponentConfigContext = { | ||
| var: (id: string, options?: ComponentVarOptions) => ComponentInternalVarRef; | ||
| vars: <const T extends ComponentVarDefinitions>(definitions: T) => ComponentVarRefTree<T>; | ||
| }; | ||
| /** | ||
| * The full config object passed to styles.component() with dimensioned variants. How `variants` | ||
| * compiles (discrete classes, `&[data-x="y"]` attributes, or BEM modifier classes) is selected by | ||
| * `createStyles({ mode })`, not by anything in this config — see {@link ComponentAttrsReturn} and | ||
| * `specs/attribute-driven-variants.md` / `specs/bem-variant-mode.md`. | ||
| */ | ||
| type ComponentConfig<V extends VariantDefinitions> = { | ||
| base?: CSSProperties; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: VariantOptionStyle; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| /** | ||
| * Config for flat variants: `{ base: {...}, elevated: {...}, compact: {...} }`. | ||
| * Each key besides `base` is a boolean-style variant. | ||
| * | ||
| * **`variants`**, **`defaultVariants`**, **`compoundVariants`**, and **`slots`** are forbidden | ||
| * on this shape so TypeScript does not pick the flat overload for CVA-style or slot configs. | ||
| * Nested variant maps can otherwise satisfy {@link CSSProperties} too loosely (index signatures), | ||
| * which produced wrong callable types for `styles.component(ns, (ctx) => ({ variants: … }), { layer })` | ||
| * when cascade layers are enabled. | ||
| */ | ||
| type FlatComponentConfig<K extends string> = { | ||
| base?: CSSProperties; | ||
| variants?: never; | ||
| defaultVariants?: never; | ||
| compoundVariants?: never; | ||
| slots?: never; | ||
| } & Record<K, CSSProperties>; | ||
| /** | ||
| * Selection object for flat variants: `{ elevated: true, compact: true }`. | ||
| */ | ||
| type FlatComponentSelections<K extends string> = { | ||
| [P in K]?: boolean | null | undefined; | ||
| }; | ||
| /** | ||
| * All possible variant class string keys that can be destructured from a | ||
| * dimensioned component. Includes 'base' plus all `{dimension}-{option}` keys | ||
| * flattened from the variants config. | ||
| */ | ||
| type DimensionedVariantKeys<V extends VariantDefinitions> = { | ||
| [D in keyof V]: keyof V[D] extends string ? `${D & string}-${keyof V[D] & string}` : never; | ||
| }[keyof V]; | ||
| /** | ||
| * The CVA-style return for dimensioned variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type ComponentReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: ComponentSelections<V>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings, keyed as `{dimension}-{option}`. */ | ||
| readonly [K in DimensionedVariantKeys<V>]: string; | ||
| }; | ||
| /** | ||
| * The return for dimensioned variants compiled with `mode: 'attribute'`. | ||
| * Callable, returning a {@link ComponentAttrsResult}. No per-option destructurable keys — there | ||
| * are no discrete option classes in attribute mode, only the single `base` class. | ||
| */ | ||
| type ComponentAttrsReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get the resolved `{ className, attrs, props }` result. */ | ||
| (selections?: ComponentSelections<V>): ComponentAttrsResult; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| }; | ||
| /** | ||
| * The CVA-style return for flat variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type FlatComponentReturn<K extends string> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: FlatComponentSelections<Exclude<K, 'base'>>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings. */ | ||
| readonly [P in Exclude<K, 'base'>]: string; | ||
| }; | ||
| type MultiSlotConfig<Slots extends readonly string[]> = { | ||
| slots: Slots; | ||
| } & Partial<Record<Slots[number], CSSProperties>>; | ||
| type MultiSlotReturn<Slots extends readonly string[]> = { | ||
| (): Record<Slots[number], string>; | ||
| } & { | ||
| readonly [K in Slots[number]]: string; | ||
| }; | ||
| type SlotComponentConfig<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = { | ||
| slots: Slots; | ||
| base?: SlotStyles<Slots[number]>; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: SlotStyles<Slots[number]>; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| type SlotComponentFunction<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = (selections?: ComponentSelections<V>) => Record<Slots[number], string>; | ||
| /** | ||
| * Config for `styles.component` may be a plain object or a function that receives {@link ComponentConfigContext}. | ||
| */ | ||
| type ComponentConfigInput<V extends VariantDefinitions> = ComponentConfig<V> | ((ctx: ComponentConfigContext) => ComponentConfig<V>); | ||
| type FlatComponentConfigInput<K extends string> = FlatComponentConfig<K> | ((ctx: ComponentConfigContext) => FlatComponentConfig<K>); | ||
| type SlotComponentConfigInput<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = SlotComponentConfig<Slots, V> | ((ctx: ComponentConfigContext) => SlotComponentConfig<Slots, V>); | ||
| type MultiSlotConfigInput<Slots extends readonly string[]> = MultiSlotConfig<Slots> | ((ctx: ComponentConfigContext) => MultiSlotConfig<Slots>); | ||
| /** | ||
| * Extract the variant prop types from a ComponentReturn or ComponentFunction. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const button = styles.component('button', { | ||
| * variants: { | ||
| * intent: { primary: {...}, ghost: {...} }, | ||
| * size: { sm: {...}, lg: {...} }, | ||
| * }, | ||
| * }); | ||
| * | ||
| * type ButtonProps = ComponentVariants<typeof button>; | ||
| * // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' } | ||
| * ``` | ||
| */ | ||
| type ComponentVariants<T> = T extends (selections?: ComponentSelections<infer V>) => unknown ? { | ||
| [K in keyof V]?: keyof V[K]; | ||
| } : never; | ||
| /** Input accepted by {@link compose}: component fn, class string, or falsy skip. */ | ||
| type ComposeSelectorInput = string | false | null | undefined | ((selections?: Record<string, unknown>) => string); | ||
| type ComposeSelectorSelections<T> = T extends (selections?: infer S) => string ? S extends undefined ? Record<string, never> : NonNullable<S> : Record<string, never>; | ||
| /** Union of variant selection objects accepted by all composed component functions. */ | ||
| type MergeComposeSelections<Selectors extends readonly unknown[]> = Selectors extends readonly [infer Head, ...infer Tail] ? ComposeSelectorSelections<Head> & MergeComposeSelections<Tail> : Record<string, never>; | ||
| type AnyComposeFn<Selectors extends readonly ComposeSelectorInput[]> = Selectors[number] extends (...args: unknown[]) => string ? true : false; | ||
| /** Return type of {@link compose}: callable with merged variant selections when any input is a function. */ | ||
| type ComposeFn<Selectors extends readonly ComposeSelectorInput[]> = AnyComposeFn<Selectors> extends true ? (selections?: MergeComposeSelections<Selectors>) => string : () => string; | ||
| /** | ||
| * `src` value for {@link FontFaceProps}: a single CSS `src` fragment or multiple | ||
| * fragments joined with commas (same as authoring `url(...), local(...)` by hand). | ||
| */ | ||
| type FontFaceSrc = string | readonly string[]; | ||
| /** | ||
| * Font face property declarations. | ||
| * | ||
| * Maps to standard `@font-face` descriptors. Values are emitted verbatim in CSS. | ||
| */ | ||
| type FontFaceProps = { | ||
| src: FontFaceSrc; | ||
| fontWeight?: string | number; | ||
| fontStyle?: 'normal' | 'italic' | 'oblique' | string; | ||
| fontDisplay?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'; | ||
| fontStretch?: string; | ||
| unicodeRange?: string; | ||
| /** `size-adjust` — fallback tuning and font-size-adjust related metrics. */ | ||
| sizeAdjust?: string; | ||
| /** `ascent-override` */ | ||
| ascentOverride?: string; | ||
| /** `descent-override` */ | ||
| descentOverride?: string; | ||
| /** `line-gap-override` */ | ||
| lineGapOverride?: string; | ||
| }; | ||
| /** | ||
| * Return type of helpers in `typestyles/globals`, passed to `global.style(…)`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * global.style(boxSizing()); | ||
| * global.style(body({ margin: 0 }, { layer: 'components' })); | ||
| * ``` | ||
| */ | ||
| type GlobalStyleTuple = readonly [selector: string, properties: CSSProperties] | readonly [selector: string, properties: CSSProperties, options: { | ||
| layer?: string; | ||
| }]; | ||
| export { type FontFaceSrc as $, type FontFaceProps as A, type CSSVarRef as B, type CSSProperties as C, type CSSValue as D, type ComponentAttrsResult as E, type FlatComponentConfigInput as F, type GlobalStyleTuple as G, type ComponentConfig as H, type ComponentConfigContext as I, type ComponentInternalVarRef as J, type ComponentSelections as K, type ComponentVarDefinitions as L, type MultiSlotConfigInput as M, type ComponentVarDescriptor as N, type ComponentVarNode as O, type ComponentVarOptions as P, type ComponentVarRefTree as Q, type RegisteredPropertyOptions as R, type SlotVariantDefinitions as S, type ThemeConditionMedia as T, type ComponentVariants as U, type VariantDefinitions as V, type DeepPartialTokenValues as W, type FlatComponentConfig as X, type FlatComponentSelections as Y, type FlatTokenEntry as Z, type FlatTokenPathEntry as _, type ThemeConditionAttr as a, type InferTokenNamespace as a0, type InferTokenValues as a1, type KeyframeStops as a2, type MergeComposeSelections as a3, type SlotComponentConfig as a4, type SlotStyles as a5, type StyleDefinitions as a6, type StyleDefinitionsWithUtils as a7, type ThemeConditionNot as a8, type TokenDescriptor as a9, type VariantOptionStyle as aa, flattenTokenEntries as ab, flattenTokenPaths as ac, isTokenDescriptor as ad, type ThemeConditionClass as b, type ThemeConditionSelector as c, type ThemeCondition as d, type ThemeConditionAnd as e, type ThemeConditionOr as f, type ThemeOverrides as g, type ThemeModeDefinition as h, type ThemeSurface as i, type ThemeConfig as j, type TokenRegistry as k, type TokenValues as l, type CreatedTokenRef as m, type TokenRef as n, type ComponentConfigInput as o, type ComponentAttrsReturn as p, type FlatComponentReturn as q, type RegisteredPropertyRef as r, type ComponentReturn as s, type SlotComponentConfigInput as t, type SlotComponentFunction as u, type MultiSlotReturn as v, type StyleUtils as w, type CSSPropertiesWithUtils as x, type ComposeSelectorInput as y, type ComposeFn as z }; |
| /** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */ | ||
| declare const TYPESTYLES_STYLE_ID = "typestyles"; | ||
| /** | ||
| * Ensure the managed <style id="typestyles"> is attached to the current document and populated. | ||
| * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled. | ||
| */ | ||
| declare function ensureDocumentStylesAttached(): void; | ||
| /** | ||
| * Insert multiple CSS rules at once. | ||
| */ | ||
| declare function insertRules(rules: Array<{ | ||
| key: string; | ||
| css: string; | ||
| }>): void; | ||
| /** | ||
| * Return all registered CSS as a string. | ||
| * | ||
| * Unlike `collectStyles`, this doesn't require wrapping a render function. | ||
| * It simply returns every CSS rule that has been registered via | ||
| * `styles.component`, `styles.class`, `tokens.create`, `keyframes.create`, etc. | ||
| * | ||
| * Ideal for SSR frameworks that need the CSS separately from the render | ||
| * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * // In a route's head/meta function: | ||
| * export const head = () => ({ | ||
| * styles: [{ id: 'typestyles', children: getRegisteredCss() }], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function getRegisteredCss(): string; | ||
| /** | ||
| * Subscribe to changes in the registered CSS (`getRegisteredCss()`). | ||
| * Returns an unsubscribe function. Compatible with `useSyncExternalStore`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss); | ||
| * ``` | ||
| */ | ||
| declare function subscribeRegisteredCss(listener: () => void): () => void; | ||
| /** | ||
| * Reset all state (useful for testing). | ||
| */ | ||
| declare function reset(): void; | ||
| /** | ||
| * Flush all pending rules synchronously. Used for SSR and testing. | ||
| */ | ||
| declare function flushSync(): void; | ||
| /** | ||
| * Invalidate all dedup keys that start with the given prefix. | ||
| * Also removes matching rules from the live stylesheet. | ||
| * Used for HMR — allows modules to re-register their styles after editing. | ||
| */ | ||
| declare function invalidatePrefix(prefix: string): void; | ||
| /** | ||
| * Invalidate a list of exact keys or prefixes. | ||
| * Each entry in `keys` is treated as an exact key match. | ||
| * Each entry in `prefixes` is treated as a prefix match. | ||
| * Used for HMR to invalidate all styles from a module at once. | ||
| */ | ||
| declare function invalidateKeys(keys: string[], prefixes: string[]): void; | ||
| export { TYPESTYLES_STYLE_ID as T, invalidateKeys as a, invalidatePrefix as b, ensureDocumentStylesAttached as e, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r, subscribeRegisteredCss as s }; |
| /** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */ | ||
| declare const TYPESTYLES_STYLE_ID = "typestyles"; | ||
| /** | ||
| * Ensure the managed <style id="typestyles"> is attached to the current document and populated. | ||
| * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled. | ||
| */ | ||
| declare function ensureDocumentStylesAttached(): void; | ||
| /** | ||
| * Insert multiple CSS rules at once. | ||
| */ | ||
| declare function insertRules(rules: Array<{ | ||
| key: string; | ||
| css: string; | ||
| }>): void; | ||
| /** | ||
| * Return all registered CSS as a string. | ||
| * | ||
| * Unlike `collectStyles`, this doesn't require wrapping a render function. | ||
| * It simply returns every CSS rule that has been registered via | ||
| * `styles.component`, `styles.class`, `tokens.create`, `keyframes.create`, etc. | ||
| * | ||
| * Ideal for SSR frameworks that need the CSS separately from the render | ||
| * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * // In a route's head/meta function: | ||
| * export const head = () => ({ | ||
| * styles: [{ id: 'typestyles', children: getRegisteredCss() }], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function getRegisteredCss(): string; | ||
| /** | ||
| * Subscribe to changes in the registered CSS (`getRegisteredCss()`). | ||
| * Returns an unsubscribe function. Compatible with `useSyncExternalStore`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss); | ||
| * ``` | ||
| */ | ||
| declare function subscribeRegisteredCss(listener: () => void): () => void; | ||
| /** | ||
| * Reset all state (useful for testing). | ||
| */ | ||
| declare function reset(): void; | ||
| /** | ||
| * Flush all pending rules synchronously. Used for SSR and testing. | ||
| */ | ||
| declare function flushSync(): void; | ||
| /** | ||
| * Invalidate all dedup keys that start with the given prefix. | ||
| * Also removes matching rules from the live stylesheet. | ||
| * Used for HMR — allows modules to re-register their styles after editing. | ||
| */ | ||
| declare function invalidatePrefix(prefix: string): void; | ||
| /** | ||
| * Invalidate a list of exact keys or prefixes. | ||
| * Each entry in `keys` is treated as an exact key match. | ||
| * Each entry in `prefixes` is treated as a prefix match. | ||
| * Used for HMR to invalidate all styles from a module at once. | ||
| */ | ||
| declare function invalidateKeys(keys: string[], prefixes: string[]): void; | ||
| export { TYPESTYLES_STYLE_ID as T, invalidateKeys as a, invalidatePrefix as b, ensureDocumentStylesAttached as e, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r, subscribeRegisteredCss as s }; |
| 'use strict'; | ||
| // src/token-scale.ts | ||
| function assertFiniteNumber(name, fn, value) { | ||
| if (typeof value !== "number" || !Number.isFinite(value)) { | ||
| throw new Error( | ||
| `[typestyles] ${fn}: \`${name}\` must be a finite number, got ${String(value)}.` | ||
| ); | ||
| } | ||
| } | ||
| function assertPositive(name, fn, value) { | ||
| assertFiniteNumber(name, fn, value); | ||
| if (value <= 0) { | ||
| throw new Error( | ||
| `[typestyles] ${fn}: \`${name}\` must be greater than 0, got ${String(value)}.` | ||
| ); | ||
| } | ||
| } | ||
| function generateGeometricScale(opts) { | ||
| const { base, ratio, steps, round = Math.round } = opts; | ||
| assertFiniteNumber("base", "generateGeometricScale", base); | ||
| assertPositive("ratio", "generateGeometricScale", ratio); | ||
| return steps.map((offset) => { | ||
| if (!Number.isInteger(offset)) { | ||
| throw new Error( | ||
| `[typestyles] generateGeometricScale: \`steps\` must contain signed integer offsets, got ${String(offset)}.` | ||
| ); | ||
| } | ||
| return round(base * ratio ** offset); | ||
| }); | ||
| } | ||
| function generateLinearScale(opts) { | ||
| const { base, multiplier, steps, round = Math.round } = opts; | ||
| assertFiniteNumber("base", "generateLinearScale", base); | ||
| assertFiniteNumber("multiplier", "generateLinearScale", multiplier); | ||
| return steps.map((step) => { | ||
| assertFiniteNumber("steps[]", "generateLinearScale", step); | ||
| return round(base * step * multiplier); | ||
| }); | ||
| } | ||
| function expandDurationBand(opts) { | ||
| const { base, ratio, roundTo = 5 } = opts; | ||
| assertFiniteNumber("base", "expandDurationBand", base); | ||
| assertPositive("ratio", "expandDurationBand", ratio); | ||
| assertPositive("roundTo", "expandDurationBand", roundTo); | ||
| const roundToNearest = (n) => Math.round(n / roundTo) * roundTo; | ||
| return { | ||
| min: roundToNearest(base * ratio), | ||
| base, | ||
| max: roundToNearest(base / ratio) | ||
| }; | ||
| } | ||
| exports.expandDurationBand = expandDurationBand; | ||
| exports.generateGeometricScale = generateGeometricScale; | ||
| exports.generateLinearScale = generateLinearScale; | ||
| //# sourceMappingURL=token-scale.cjs.map | ||
| //# sourceMappingURL=token-scale.cjs.map |
| {"version":3,"sources":["../src/token-scale.ts"],"names":[],"mappings":";;;AAiCA,SAAS,kBAAA,CAAmB,IAAA,EAAc,EAAA,EAAY,KAAA,EAAqB;AACzE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,gCAAA,EAAmC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,KAC/E;AAAA,EACF;AACF;AAEA,SAAS,cAAA,CAAe,IAAA,EAAc,EAAA,EAAY,KAAA,EAAqB;AACrE,EAAA,kBAAA,CAAmB,IAAA,EAAM,IAAI,KAAK,CAAA;AAClC,EAAA,IAAI,SAAS,CAAA,EAAG;AACd,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,+BAAA,EAAkC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,KAC9E;AAAA,EACF;AACF;AAOO,SAAS,uBAAuB,IAAA,EAA+C;AACpF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,OAAO,KAAA,GAAQ,IAAA,CAAK,OAAM,GAAI,IAAA;AACnD,EAAA,kBAAA,CAAmB,MAAA,EAAQ,0BAA0B,IAAI,CAAA;AACzD,EAAA,cAAA,CAAe,OAAA,EAAS,0BAA0B,KAAK,CAAA;AACvD,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,MAAA,KAAW;AAC3B,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,wFAAA,EAA2F,MAAA,CAAO,MAAM,CAAC,CAAA,CAAA;AAAA,OAC3G;AAAA,IACF;AACA,IAAA,OAAO,KAAA,CAAM,IAAA,GAAO,KAAA,IAAS,MAAM,CAAA;AAAA,EACrC,CAAC,CAAA;AACH;AAMO,SAAS,oBAAoB,IAAA,EAA4C;AAC9E,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,OAAO,KAAA,GAAQ,IAAA,CAAK,OAAM,GAAI,IAAA;AACxD,EAAA,kBAAA,CAAmB,MAAA,EAAQ,uBAAuB,IAAI,CAAA;AACtD,EAAA,kBAAA,CAAmB,YAAA,EAAc,uBAAuB,UAAU,CAAA;AAClE,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACzB,IAAA,kBAAA,CAAmB,SAAA,EAAW,uBAAuB,IAAI,CAAA;AACzD,IAAA,OAAO,KAAA,CAAM,IAAA,GAAO,IAAA,GAAO,UAAU,CAAA;AAAA,EACvC,CAAC,CAAA;AACH;AAQO,SAAS,mBAAmB,IAAA,EAA+C;AAChF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,GAAU,GAAE,GAAI,IAAA;AACrC,EAAA,kBAAA,CAAmB,MAAA,EAAQ,sBAAsB,IAAI,CAAA;AACrD,EAAA,cAAA,CAAe,OAAA,EAAS,sBAAsB,KAAK,CAAA;AACnD,EAAA,cAAA,CAAe,SAAA,EAAW,sBAAsB,OAAO,CAAA;AACvD,EAAA,MAAM,iBAAiB,CAAC,CAAA,KAAc,KAAK,KAAA,CAAM,CAAA,GAAI,OAAO,CAAA,GAAI,OAAA;AAChE,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,cAAA,CAAe,IAAA,GAAO,KAAK,CAAA;AAAA,IAChC,IAAA;AAAA,IACA,GAAA,EAAK,cAAA,CAAe,IAAA,GAAO,KAAK;AAAA,GAClC;AACF","file":"token-scale.cjs","sourcesContent":["export type GenerateGeometricScaleOptions = {\n /** Anchor value at offset `0` (unitless — the caller appends px/rem/ms/…). */\n base: number;\n /** Multiplier applied per step offset. Must be a finite number > 0. */\n ratio: number;\n /** Signed integer offsets from the base, e.g. `[-2, -1, 0, 1, 2]`. */\n steps: number[];\n /** Rounding function applied to each value. Defaults to `Math.round`. */\n round?: (n: number) => number;\n};\n\nexport type GenerateLinearScaleOptions = {\n /** Base unit multiplied by each step ordinal (unitless). */\n base: number;\n /** Scaling factor applied on top of `base * step`. `0` is allowed (all zeros). */\n multiplier: number;\n /** Ordinal multipliers, e.g. `[1, 2, 3, 4]`. */\n steps: number[];\n /** Rounding function applied to each value. Defaults to `Math.round`. */\n round?: (n: number) => number;\n};\n\nexport type ExpandDurationBandOptions = {\n /** Anchor duration (unitless, typically ms). Passed through unchanged. */\n base: number;\n /** Band ratio: `min = base * ratio`, `max = base / ratio`. Must be > 0. */\n ratio: number;\n /** Rounding granularity for `min`/`max` (nearest multiple). Defaults to `5`. */\n roundTo?: number;\n};\n\nexport type DurationBand = { min: number; base: number; max: number };\n\nfunction assertFiniteNumber(name: string, fn: string, value: number): void {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `[typestyles] ${fn}: \\`${name}\\` must be a finite number, got ${String(value)}.`,\n );\n }\n}\n\nfunction assertPositive(name: string, fn: string, value: number): void {\n assertFiniteNumber(name, fn, value);\n if (value <= 0) {\n throw new Error(\n `[typestyles] ${fn}: \\`${name}\\` must be greater than 0, got ${String(value)}.`,\n );\n }\n}\n\n/**\n * Geometric (modular) scale: `value(offset) = round(base * ratio ** offset)` for each\n * signed integer offset in `steps`. Returns numbers in the same order as `steps`, with\n * zero naming opinions — zipping names onto steps is the caller's concern.\n */\nexport function generateGeometricScale(opts: GenerateGeometricScaleOptions): number[] {\n const { base, ratio, steps, round = Math.round } = opts;\n assertFiniteNumber('base', 'generateGeometricScale', base);\n assertPositive('ratio', 'generateGeometricScale', ratio);\n return steps.map((offset) => {\n if (!Number.isInteger(offset)) {\n throw new Error(\n `[typestyles] generateGeometricScale: \\`steps\\` must contain signed integer offsets, got ${String(offset)}.`,\n );\n }\n return round(base * ratio ** offset);\n });\n}\n\n/**\n * Linear scale: `value(step) = round(base * step * multiplier)` for each ordinal in\n * `steps`. Deliberately minimal — it exists for a rounding/unit convention, not math.\n */\nexport function generateLinearScale(opts: GenerateLinearScaleOptions): number[] {\n const { base, multiplier, steps, round = Math.round } = opts;\n assertFiniteNumber('base', 'generateLinearScale', base);\n assertFiniteNumber('multiplier', 'generateLinearScale', multiplier);\n return steps.map((step) => {\n assertFiniteNumber('steps[]', 'generateLinearScale', step);\n return round(base * step * multiplier);\n });\n}\n\n/**\n * Expand a single duration anchor into a `{ min, base, max }` band:\n * `min = round(base * ratio, roundTo)`, `max = round(base / ratio, roundTo)`;\n * `base` passes through unchanged. `roundTo` defaults to the nearest 5 (ms) so\n * computed bands stay perceptually clean instead of visibly computed (e.g. 93.75).\n */\nexport function expandDurationBand(opts: ExpandDurationBandOptions): DurationBand {\n const { base, ratio, roundTo = 5 } = opts;\n assertFiniteNumber('base', 'expandDurationBand', base);\n assertPositive('ratio', 'expandDurationBand', ratio);\n assertPositive('roundTo', 'expandDurationBand', roundTo);\n const roundToNearest = (n: number) => Math.round(n / roundTo) * roundTo;\n return {\n min: roundToNearest(base * ratio),\n base,\n max: roundToNearest(base / ratio),\n };\n}\n"]} |
| type GenerateGeometricScaleOptions = { | ||
| /** Anchor value at offset `0` (unitless — the caller appends px/rem/ms/…). */ | ||
| base: number; | ||
| /** Multiplier applied per step offset. Must be a finite number > 0. */ | ||
| ratio: number; | ||
| /** Signed integer offsets from the base, e.g. `[-2, -1, 0, 1, 2]`. */ | ||
| steps: number[]; | ||
| /** Rounding function applied to each value. Defaults to `Math.round`. */ | ||
| round?: (n: number) => number; | ||
| }; | ||
| type GenerateLinearScaleOptions = { | ||
| /** Base unit multiplied by each step ordinal (unitless). */ | ||
| base: number; | ||
| /** Scaling factor applied on top of `base * step`. `0` is allowed (all zeros). */ | ||
| multiplier: number; | ||
| /** Ordinal multipliers, e.g. `[1, 2, 3, 4]`. */ | ||
| steps: number[]; | ||
| /** Rounding function applied to each value. Defaults to `Math.round`. */ | ||
| round?: (n: number) => number; | ||
| }; | ||
| type ExpandDurationBandOptions = { | ||
| /** Anchor duration (unitless, typically ms). Passed through unchanged. */ | ||
| base: number; | ||
| /** Band ratio: `min = base * ratio`, `max = base / ratio`. Must be > 0. */ | ||
| ratio: number; | ||
| /** Rounding granularity for `min`/`max` (nearest multiple). Defaults to `5`. */ | ||
| roundTo?: number; | ||
| }; | ||
| type DurationBand = { | ||
| min: number; | ||
| base: number; | ||
| max: number; | ||
| }; | ||
| /** | ||
| * Geometric (modular) scale: `value(offset) = round(base * ratio ** offset)` for each | ||
| * signed integer offset in `steps`. Returns numbers in the same order as `steps`, with | ||
| * zero naming opinions — zipping names onto steps is the caller's concern. | ||
| */ | ||
| declare function generateGeometricScale(opts: GenerateGeometricScaleOptions): number[]; | ||
| /** | ||
| * Linear scale: `value(step) = round(base * step * multiplier)` for each ordinal in | ||
| * `steps`. Deliberately minimal — it exists for a rounding/unit convention, not math. | ||
| */ | ||
| declare function generateLinearScale(opts: GenerateLinearScaleOptions): number[]; | ||
| /** | ||
| * Expand a single duration anchor into a `{ min, base, max }` band: | ||
| * `min = round(base * ratio, roundTo)`, `max = round(base / ratio, roundTo)`; | ||
| * `base` passes through unchanged. `roundTo` defaults to the nearest 5 (ms) so | ||
| * computed bands stay perceptually clean instead of visibly computed (e.g. 93.75). | ||
| */ | ||
| declare function expandDurationBand(opts: ExpandDurationBandOptions): DurationBand; | ||
| export { type DurationBand, type ExpandDurationBandOptions, type GenerateGeometricScaleOptions, type GenerateLinearScaleOptions, expandDurationBand, generateGeometricScale, generateLinearScale }; |
| type GenerateGeometricScaleOptions = { | ||
| /** Anchor value at offset `0` (unitless — the caller appends px/rem/ms/…). */ | ||
| base: number; | ||
| /** Multiplier applied per step offset. Must be a finite number > 0. */ | ||
| ratio: number; | ||
| /** Signed integer offsets from the base, e.g. `[-2, -1, 0, 1, 2]`. */ | ||
| steps: number[]; | ||
| /** Rounding function applied to each value. Defaults to `Math.round`. */ | ||
| round?: (n: number) => number; | ||
| }; | ||
| type GenerateLinearScaleOptions = { | ||
| /** Base unit multiplied by each step ordinal (unitless). */ | ||
| base: number; | ||
| /** Scaling factor applied on top of `base * step`. `0` is allowed (all zeros). */ | ||
| multiplier: number; | ||
| /** Ordinal multipliers, e.g. `[1, 2, 3, 4]`. */ | ||
| steps: number[]; | ||
| /** Rounding function applied to each value. Defaults to `Math.round`. */ | ||
| round?: (n: number) => number; | ||
| }; | ||
| type ExpandDurationBandOptions = { | ||
| /** Anchor duration (unitless, typically ms). Passed through unchanged. */ | ||
| base: number; | ||
| /** Band ratio: `min = base * ratio`, `max = base / ratio`. Must be > 0. */ | ||
| ratio: number; | ||
| /** Rounding granularity for `min`/`max` (nearest multiple). Defaults to `5`. */ | ||
| roundTo?: number; | ||
| }; | ||
| type DurationBand = { | ||
| min: number; | ||
| base: number; | ||
| max: number; | ||
| }; | ||
| /** | ||
| * Geometric (modular) scale: `value(offset) = round(base * ratio ** offset)` for each | ||
| * signed integer offset in `steps`. Returns numbers in the same order as `steps`, with | ||
| * zero naming opinions — zipping names onto steps is the caller's concern. | ||
| */ | ||
| declare function generateGeometricScale(opts: GenerateGeometricScaleOptions): number[]; | ||
| /** | ||
| * Linear scale: `value(step) = round(base * step * multiplier)` for each ordinal in | ||
| * `steps`. Deliberately minimal — it exists for a rounding/unit convention, not math. | ||
| */ | ||
| declare function generateLinearScale(opts: GenerateLinearScaleOptions): number[]; | ||
| /** | ||
| * Expand a single duration anchor into a `{ min, base, max }` band: | ||
| * `min = round(base * ratio, roundTo)`, `max = round(base / ratio, roundTo)`; | ||
| * `base` passes through unchanged. `roundTo` defaults to the nearest 5 (ms) so | ||
| * computed bands stay perceptually clean instead of visibly computed (e.g. 93.75). | ||
| */ | ||
| declare function expandDurationBand(opts: ExpandDurationBandOptions): DurationBand; | ||
| export { type DurationBand, type ExpandDurationBandOptions, type GenerateGeometricScaleOptions, type GenerateLinearScaleOptions, expandDurationBand, generateGeometricScale, generateLinearScale }; |
| import './chunk-PZ5AY32C.js'; | ||
| // src/token-scale.ts | ||
| function assertFiniteNumber(name, fn, value) { | ||
| if (typeof value !== "number" || !Number.isFinite(value)) { | ||
| throw new Error( | ||
| `[typestyles] ${fn}: \`${name}\` must be a finite number, got ${String(value)}.` | ||
| ); | ||
| } | ||
| } | ||
| function assertPositive(name, fn, value) { | ||
| assertFiniteNumber(name, fn, value); | ||
| if (value <= 0) { | ||
| throw new Error( | ||
| `[typestyles] ${fn}: \`${name}\` must be greater than 0, got ${String(value)}.` | ||
| ); | ||
| } | ||
| } | ||
| function generateGeometricScale(opts) { | ||
| const { base, ratio, steps, round = Math.round } = opts; | ||
| assertFiniteNumber("base", "generateGeometricScale", base); | ||
| assertPositive("ratio", "generateGeometricScale", ratio); | ||
| return steps.map((offset) => { | ||
| if (!Number.isInteger(offset)) { | ||
| throw new Error( | ||
| `[typestyles] generateGeometricScale: \`steps\` must contain signed integer offsets, got ${String(offset)}.` | ||
| ); | ||
| } | ||
| return round(base * ratio ** offset); | ||
| }); | ||
| } | ||
| function generateLinearScale(opts) { | ||
| const { base, multiplier, steps, round = Math.round } = opts; | ||
| assertFiniteNumber("base", "generateLinearScale", base); | ||
| assertFiniteNumber("multiplier", "generateLinearScale", multiplier); | ||
| return steps.map((step) => { | ||
| assertFiniteNumber("steps[]", "generateLinearScale", step); | ||
| return round(base * step * multiplier); | ||
| }); | ||
| } | ||
| function expandDurationBand(opts) { | ||
| const { base, ratio, roundTo = 5 } = opts; | ||
| assertFiniteNumber("base", "expandDurationBand", base); | ||
| assertPositive("ratio", "expandDurationBand", ratio); | ||
| assertPositive("roundTo", "expandDurationBand", roundTo); | ||
| const roundToNearest = (n) => Math.round(n / roundTo) * roundTo; | ||
| return { | ||
| min: roundToNearest(base * ratio), | ||
| base, | ||
| max: roundToNearest(base / ratio) | ||
| }; | ||
| } | ||
| export { expandDurationBand, generateGeometricScale, generateLinearScale }; | ||
| //# sourceMappingURL=token-scale.js.map | ||
| //# sourceMappingURL=token-scale.js.map |
| {"version":3,"sources":["../src/token-scale.ts"],"names":[],"mappings":";;;AAiCA,SAAS,kBAAA,CAAmB,IAAA,EAAc,EAAA,EAAY,KAAA,EAAqB;AACzE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,gCAAA,EAAmC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,KAC/E;AAAA,EACF;AACF;AAEA,SAAS,cAAA,CAAe,IAAA,EAAc,EAAA,EAAY,KAAA,EAAqB;AACrE,EAAA,kBAAA,CAAmB,IAAA,EAAM,IAAI,KAAK,CAAA;AAClC,EAAA,IAAI,SAAS,CAAA,EAAG;AACd,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,EAAE,CAAA,IAAA,EAAO,IAAI,CAAA,+BAAA,EAAkC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAAA,KAC9E;AAAA,EACF;AACF;AAOO,SAAS,uBAAuB,IAAA,EAA+C;AACpF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,OAAO,KAAA,GAAQ,IAAA,CAAK,OAAM,GAAI,IAAA;AACnD,EAAA,kBAAA,CAAmB,MAAA,EAAQ,0BAA0B,IAAI,CAAA;AACzD,EAAA,cAAA,CAAe,OAAA,EAAS,0BAA0B,KAAK,CAAA;AACvD,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,MAAA,KAAW;AAC3B,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,wFAAA,EAA2F,MAAA,CAAO,MAAM,CAAC,CAAA,CAAA;AAAA,OAC3G;AAAA,IACF;AACA,IAAA,OAAO,KAAA,CAAM,IAAA,GAAO,KAAA,IAAS,MAAM,CAAA;AAAA,EACrC,CAAC,CAAA;AACH;AAMO,SAAS,oBAAoB,IAAA,EAA4C;AAC9E,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,OAAO,KAAA,GAAQ,IAAA,CAAK,OAAM,GAAI,IAAA;AACxD,EAAA,kBAAA,CAAmB,MAAA,EAAQ,uBAAuB,IAAI,CAAA;AACtD,EAAA,kBAAA,CAAmB,YAAA,EAAc,uBAAuB,UAAU,CAAA;AAClE,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACzB,IAAA,kBAAA,CAAmB,SAAA,EAAW,uBAAuB,IAAI,CAAA;AACzD,IAAA,OAAO,KAAA,CAAM,IAAA,GAAO,IAAA,GAAO,UAAU,CAAA;AAAA,EACvC,CAAC,CAAA;AACH;AAQO,SAAS,mBAAmB,IAAA,EAA+C;AAChF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,GAAU,GAAE,GAAI,IAAA;AACrC,EAAA,kBAAA,CAAmB,MAAA,EAAQ,sBAAsB,IAAI,CAAA;AACrD,EAAA,cAAA,CAAe,OAAA,EAAS,sBAAsB,KAAK,CAAA;AACnD,EAAA,cAAA,CAAe,SAAA,EAAW,sBAAsB,OAAO,CAAA;AACvD,EAAA,MAAM,iBAAiB,CAAC,CAAA,KAAc,KAAK,KAAA,CAAM,CAAA,GAAI,OAAO,CAAA,GAAI,OAAA;AAChE,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,cAAA,CAAe,IAAA,GAAO,KAAK,CAAA;AAAA,IAChC,IAAA;AAAA,IACA,GAAA,EAAK,cAAA,CAAe,IAAA,GAAO,KAAK;AAAA,GAClC;AACF","file":"token-scale.js","sourcesContent":["export type GenerateGeometricScaleOptions = {\n /** Anchor value at offset `0` (unitless — the caller appends px/rem/ms/…). */\n base: number;\n /** Multiplier applied per step offset. Must be a finite number > 0. */\n ratio: number;\n /** Signed integer offsets from the base, e.g. `[-2, -1, 0, 1, 2]`. */\n steps: number[];\n /** Rounding function applied to each value. Defaults to `Math.round`. */\n round?: (n: number) => number;\n};\n\nexport type GenerateLinearScaleOptions = {\n /** Base unit multiplied by each step ordinal (unitless). */\n base: number;\n /** Scaling factor applied on top of `base * step`. `0` is allowed (all zeros). */\n multiplier: number;\n /** Ordinal multipliers, e.g. `[1, 2, 3, 4]`. */\n steps: number[];\n /** Rounding function applied to each value. Defaults to `Math.round`. */\n round?: (n: number) => number;\n};\n\nexport type ExpandDurationBandOptions = {\n /** Anchor duration (unitless, typically ms). Passed through unchanged. */\n base: number;\n /** Band ratio: `min = base * ratio`, `max = base / ratio`. Must be > 0. */\n ratio: number;\n /** Rounding granularity for `min`/`max` (nearest multiple). Defaults to `5`. */\n roundTo?: number;\n};\n\nexport type DurationBand = { min: number; base: number; max: number };\n\nfunction assertFiniteNumber(name: string, fn: string, value: number): void {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new Error(\n `[typestyles] ${fn}: \\`${name}\\` must be a finite number, got ${String(value)}.`,\n );\n }\n}\n\nfunction assertPositive(name: string, fn: string, value: number): void {\n assertFiniteNumber(name, fn, value);\n if (value <= 0) {\n throw new Error(\n `[typestyles] ${fn}: \\`${name}\\` must be greater than 0, got ${String(value)}.`,\n );\n }\n}\n\n/**\n * Geometric (modular) scale: `value(offset) = round(base * ratio ** offset)` for each\n * signed integer offset in `steps`. Returns numbers in the same order as `steps`, with\n * zero naming opinions — zipping names onto steps is the caller's concern.\n */\nexport function generateGeometricScale(opts: GenerateGeometricScaleOptions): number[] {\n const { base, ratio, steps, round = Math.round } = opts;\n assertFiniteNumber('base', 'generateGeometricScale', base);\n assertPositive('ratio', 'generateGeometricScale', ratio);\n return steps.map((offset) => {\n if (!Number.isInteger(offset)) {\n throw new Error(\n `[typestyles] generateGeometricScale: \\`steps\\` must contain signed integer offsets, got ${String(offset)}.`,\n );\n }\n return round(base * ratio ** offset);\n });\n}\n\n/**\n * Linear scale: `value(step) = round(base * step * multiplier)` for each ordinal in\n * `steps`. Deliberately minimal — it exists for a rounding/unit convention, not math.\n */\nexport function generateLinearScale(opts: GenerateLinearScaleOptions): number[] {\n const { base, multiplier, steps, round = Math.round } = opts;\n assertFiniteNumber('base', 'generateLinearScale', base);\n assertFiniteNumber('multiplier', 'generateLinearScale', multiplier);\n return steps.map((step) => {\n assertFiniteNumber('steps[]', 'generateLinearScale', step);\n return round(base * step * multiplier);\n });\n}\n\n/**\n * Expand a single duration anchor into a `{ min, base, max }` band:\n * `min = round(base * ratio, roundTo)`, `max = round(base / ratio, roundTo)`;\n * `base` passes through unchanged. `roundTo` defaults to the nearest 5 (ms) so\n * computed bands stay perceptually clean instead of visibly computed (e.g. 93.75).\n */\nexport function expandDurationBand(opts: ExpandDurationBandOptions): DurationBand {\n const { base, ratio, roundTo = 5 } = opts;\n assertFiniteNumber('base', 'expandDurationBand', base);\n assertPositive('ratio', 'expandDurationBand', ratio);\n assertPositive('roundTo', 'expandDurationBand', roundTo);\n const roundToNearest = (n: number) => Math.round(n / roundTo) * roundTo;\n return {\n min: roundToNearest(base * ratio),\n base,\n max: roundToNearest(base / ratio),\n };\n}\n"]} |
+204
| Apache License | ||
| Version 2.0, January 2004 | ||
| http://www.apache.org/licenses/ | ||
| Copyright 2026 The TypeStyles Authors | ||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
| 1. Definitions. | ||
| "License" shall mean the terms and conditions for use, reproduction, | ||
| and distribution as defined by Sections 1 through 9 of this document. | ||
| "Licensor" shall mean the copyright owner or entity authorized by | ||
| the copyright owner that is granting the License. | ||
| "Legal Entity" shall mean the union of the acting entity and all | ||
| other entities that control, are controlled by, or are under common | ||
| control with that entity. For the purposes of this definition, | ||
| "control" means (i) the power, direct or indirect, to cause the | ||
| direction or management of such entity, whether by contract or | ||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||
| "You" (or "Your") shall mean an individual or Legal Entity | ||
| exercising permissions granted by this License. | ||
| "Source" form shall mean the preferred form for making modifications, | ||
| including but not limited to software source code, documentation | ||
| source, and configuration files. | ||
| "Object" form shall mean any form resulting from mechanical | ||
| transformation or translation of a Source form, including but | ||
| not limited to compiled object code, generated documentation, | ||
| and conversions to other media types. | ||
| "Work" shall mean the work of authorship, whether in Source or | ||
| Object form, made available under the License, as indicated by a | ||
| copyright notice that is included in or attached to the work | ||
| (an example is provided in the Appendix below). | ||
| "Derivative Works" shall mean any work, whether in Source or Object | ||
| form, that is based on (or derived from) the Work and for which the | ||
| editorial revisions, annotations, elaborations, or other modifications | ||
| represent, as a whole, an original work of authorship. For the purposes | ||
| of this License, Derivative Works shall not include works that remain | ||
| separable from, or merely link (or bind by name) to the interfaces of, | ||
| the Work and Derivative Works thereof. | ||
| "Contribution" shall mean any work of authorship, including | ||
| the original version of the Work and any modifications or additions | ||
| to that Work or Derivative Works thereof, that is intentionally | ||
| submitted to Licensor for inclusion in the Work by the copyright owner | ||
| or by an individual or Legal Entity authorized to submit on behalf of | ||
| the copyright owner. For the purposes of this definition, "submitted" | ||
| means any form of electronic, verbal, or written communication sent | ||
| to the Licensor or its representatives, including but not limited to | ||
| communication on electronic mailing lists, source code control systems, | ||
| and issue tracking systems that are managed by, or on behalf of, the | ||
| Licensor for the purpose of discussing and improving the Work, but | ||
| excluding communication that is conspicuously marked or otherwise | ||
| designated in writing by the copyright owner as "Not a Contribution." | ||
| "Contributor" shall mean Licensor and any individual or Legal Entity | ||
| on behalf of whom a Contribution has been received by Licensor and | ||
| subsequently incorporated within the Work. | ||
| 2. Grant of Copyright License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| copyright license to reproduce, prepare Derivative Works of, | ||
| publicly display, publicly perform, sublicense, and distribute the | ||
| Work and such Derivative Works in Source or Object form. | ||
| 3. Grant of Patent License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| (except as stated in this section) patent license to make, have made, | ||
| use, offer to sell, sell, import, and otherwise transfer the Work, | ||
| where such license applies only to those patent claims licensable | ||
| by such Contributor that are necessarily infringed by their | ||
| Contribution(s) alone or by combination of their Contribution(s) | ||
| with the Work to which such Contribution(s) was submitted. If You | ||
| institute patent litigation against any entity (including a | ||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
| or a Contribution incorporated within the Work constitutes direct | ||
| or contributory patent infringement, then any patent licenses | ||
| granted to You under this License for that Work shall terminate | ||
| as of the date such litigation is filed. | ||
| 4. Redistribution. You may reproduce and distribute copies of the | ||
| Work or Derivative Works thereof in any medium, with or without | ||
| modifications, and in Source or Object form, provided that You | ||
| meet the following conditions: | ||
| (a) You must give any other recipients of the Work or | ||
| Derivative Works a copy of this License; and | ||
| (b) You must cause any modified files to carry prominent notices | ||
| stating that You changed the files; and | ||
| (c) You must retain, in the Source form of any Derivative Works | ||
| that You distribute, all copyright, patent, trademark, and | ||
| attribution notices from the Source form of the Work, | ||
| excluding those notices that do not pertain to any part of | ||
| the Derivative Works; and | ||
| (d) If the Work includes a "NOTICE" text file as part of its | ||
| distribution, then any Derivative Works that You distribute must | ||
| include a readable copy of the attribution notices contained | ||
| within such NOTICE file, excluding those notices that do not | ||
| pertain to any part of the Derivative Works, in at least one | ||
| of the following places: within a NOTICE text file distributed | ||
| as part of the Derivative Works; within the Source form or | ||
| documentation, if provided along with the Derivative Works; or, | ||
| within a display generated by the Derivative Works, if and | ||
| wherever such third-party notices normally appear. The contents | ||
| of the NOTICE file are for informational purposes only and | ||
| do not modify the License. You may add Your own attribution | ||
| notices within Derivative Works that You distribute, alongside | ||
| or as an addendum to the NOTICE text from the Work, provided | ||
| that such additional attribution notices cannot be construed | ||
| as modifying the License. | ||
| You may add Your own copyright statement to Your modifications and | ||
| may provide additional or different license terms and conditions | ||
| for use, reproduction, or distribution of Your modifications, or | ||
| for any such Derivative Works as a whole, provided Your use, | ||
| reproduction, and distribution of the Work otherwise complies with | ||
| the conditions stated in this License. | ||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
| any Contribution intentionally submitted for inclusion in the Work | ||
| by You to the Licensor shall be under the terms and conditions of | ||
| this License, without any additional terms or conditions. | ||
| Notwithstanding the above, nothing herein shall supersede or modify | ||
| the terms of any separate license agreement you may have executed | ||
| with Licensor regarding such Contributions. | ||
| 6. Trademarks. This License does not grant permission to use the trade | ||
| names, trademarks, service marks, or product names of the Licensor, | ||
| except as required for reasonable and customary use in describing the | ||
| origin of the Work and reproducing the content of the NOTICE file. | ||
| 7. Disclaimer of Warranty. Unless required by applicable law or | ||
| agreed to in writing, Licensor provides the Work (and each | ||
| Contributor provides its Contributions) on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
| implied, including, without limitation, any warranties or conditions | ||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
| PARTICULAR PURPOSE. You are solely responsible for determining the | ||
| appropriateness of using or redistributing the Work and assume any | ||
| risks associated with Your exercise of permissions under this License. | ||
| 8. Limitation of Liability. In no event and under no legal theory, | ||
| whether in tort (including negligence), contract, or otherwise, | ||
| unless required by applicable law (such as deliberate and grossly | ||
| negligent acts) or agreed to in writing, shall any Contributor be | ||
| liable to You for damages, including any direct, indirect, special, | ||
| incidental, or consequential damages of any character arising as a | ||
| result of this License or out of the use or inability to use the | ||
| Work (including but not limited to damages for loss of goodwill, | ||
| work stoppage, computer failure or malfunction, or any and all | ||
| other commercial damages or losses), even if such Contributor | ||
| has been advised of the possibility of such damages. | ||
| 9. Accepting Warranty or Additional Liability. While redistributing | ||
| the Work or Derivative Works thereof, You may choose to offer, | ||
| and charge a fee for, acceptance of support, warranty, indemnity, | ||
| or other liability obligations and/or rights consistent with this | ||
| License. However, in accepting such obligations, You may act only | ||
| on Your own behalf and on Your sole responsibility, not on behalf | ||
| of any other Contributor, and only if You agree to indemnify, | ||
| defend, and hold each Contributor harmless for any liability | ||
| incurred by, or claims asserted against, such Contributor by reason | ||
| of your accepting any such warranty or additional liability. | ||
| END OF TERMS AND CONDITIONS | ||
| APPENDIX: How to apply the Apache License to your work. | ||
| To apply the Apache License to your work, attach the following | ||
| boilerplate notice, with the fields enclosed by brackets "[]" | ||
| replaced with your own identifying information. (Don't include | ||
| the brackets!) The text should be enclosed in the appropriate | ||
| comment syntax for the file format. We also recommend that a | ||
| file or class name and description of purpose be included on the | ||
| same "printed page" as the copyright notice for easier | ||
| identification within third-party archives. | ||
| Copyright [yyyy] [name of copyright owner] | ||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. |
+88
| # typestyles — agent reference | ||
| > CSS-in-TypeScript with typed variants, design tokens, and zero-runtime production extraction. | ||
| Full docs: https://typestyles.dev/llms.txt · MCP: https://typestyles.dev/mcp | ||
| ## Install | ||
| ```bash | ||
| pnpm add typestyles @typestyles/vite # Vite + zero-runtime | ||
| # or: npm install typestyles # runtime-only prototyping | ||
| ``` | ||
| ## Core patterns | ||
| ```ts | ||
| import { createTypeStyles, cx } from 'typestyles'; | ||
| export const { styles, tokens } = createTypeStyles({ scopeId: 'app' }); | ||
| const color = tokens.create('color', { | ||
| primary: '#0066ff', | ||
| surface: '#ffffff', | ||
| }); | ||
| export const button = styles.component('button', { | ||
| base: { | ||
| padding: '8px 16px', | ||
| borderRadius: '6px', | ||
| backgroundColor: color.primary, | ||
| color: color.surface, | ||
| '&:hover': { filter: 'brightness(0.9)' }, | ||
| }, | ||
| variants: { | ||
| intent: { | ||
| primary: { backgroundColor: color.primary }, | ||
| ghost: { backgroundColor: 'transparent', color: color.primary }, | ||
| }, | ||
| }, | ||
| defaultVariants: { intent: 'primary' }, | ||
| }); | ||
| // Usage: button({ intent: 'ghost' }) → class string | ||
| ``` | ||
| ## Key APIs | ||
| - `createTypeStyles({ scopeId, mode?, prefix?, layers? })` — scoped `styles` + `tokens` instance | ||
| - `styles.component(namespace, config)` — CVA-style variants (`base`, `variants`, `defaultVariants`, `compoundVariants`) | ||
| - `styles.class(name, properties)` — single class | ||
| - `tokens.create(namespace, values)` — CSS custom properties (`--{scopeId}-…`) | ||
| - `tokens.createTheme(name, config)` — theme class overrides | ||
| - `cx(...classes)` — join class names (handles falsy values) | ||
| - `styles.compose(...fns)` — compose style functions | ||
| Detailed API: https://typestyles.dev/docs/api-reference.md | ||
| ## Zero-runtime | ||
| 1. Add bundler plugin (`@typestyles/vite`, `@typestyles/next`, …) | ||
| 2. Create `typestyles-entry.ts` importing all style modules | ||
| 3. `vite build` emits static `typestyles.css` — no client runtime | ||
| Guide: https://typestyles.dev/docs/zero-runtime.md | ||
| ## Common mistakes | ||
| - **Missing side-effect entry** — build extraction only sees imported style modules | ||
| - **Default unscoped `styles`** in libraries — use `createTypeStyles({ scopeId: 'pkg' })` per package | ||
| - **Dynamic class strings** — use variants or `styles.hashClass`, not template literals for one-off classes | ||
| - **Forgetting `scopeId`** when multiple bundles share a page — token/class collisions | ||
| - **SSR without server helpers** — import from `typestyles/server` for streaming/collection | ||
| ## Subpath exports | ||
| | Import | Use | | ||
| | ------ | --- | | ||
| | `typestyles` | Core runtime | | ||
| | `typestyles/server` | SSR (`collectStyles`, …) | | ||
| | `typestyles/build` | Build stubs when runtime disabled | | ||
| | `typestyles/color` | Color helpers (off main bundle) | | ||
| ## More | ||
| - Getting started: https://typestyles.dev/docs/getting-started.md | ||
| - React: https://typestyles.dev/docs/react-integration.md | ||
| - Tokens: https://typestyles.dev/docs/tokens.md | ||
| - Troubleshooting: https://typestyles.dev/docs/troubleshooting.md |
+95
| # typestyles | ||
| CSS-in-TypeScript that embraces CSS instead of hiding from it. | ||
| Write type-safe styles in TypeScript, get **human-readable class names** in DevTools, use **CSS custom properties** as first-class design tokens, and adopt incrementally alongside plain CSS. No build step required for the runtime path; optional bundler plugins extract static CSS for production. | ||
| Full documentation: [typestyles.dev](https://typestyles.dev) · Monorepo overview: [README](../../README.md) | ||
| **For AI coding agents:** read [`llms.txt`](./llms.txt) in this package (API patterns, common mistakes, doc links) or query the live docs via MCP at [typestyles.dev/mcp](https://typestyles.dev/mcp). | ||
| ## Install | ||
| ```bash | ||
| npm install typestyles | ||
| ``` | ||
| ## Quick start | ||
| ```tsx | ||
| import { styles, tokens, cx } from 'typestyles'; | ||
| const color = tokens.create('color', { | ||
| primary: '#0066ff', | ||
| surface: '#ffffff', | ||
| }); | ||
| const button = styles.component('button', { | ||
| base: { | ||
| padding: '8px 16px', | ||
| borderRadius: '6px', | ||
| backgroundColor: color.primary, | ||
| color: color.surface, | ||
| '&:hover': { filter: 'brightness(0.9)' }, | ||
| }, | ||
| variants: { | ||
| intent: { | ||
| primary: { backgroundColor: color.primary }, | ||
| ghost: { backgroundColor: 'transparent', color: color.primary }, | ||
| }, | ||
| }, | ||
| defaultVariants: { intent: 'primary' }, | ||
| }); | ||
| // Callable + destructurable | ||
| <button className={button({ intent: 'ghost' })} />; | ||
| // → class="button-base button-intent-ghost" | ||
| ``` | ||
| ## Subpath exports | ||
| | Import | Use for | | ||
| | -------------------- | ---------------------------------------------------------------------------------- | | ||
| | `typestyles` | `styles`, `tokens`, `cx`, `createStyles`, `createTokens`, `createVar`, … | | ||
| | `typestyles/server` | `collectStyles`, `getRegisteredCss`, streaming SSR helpers | | ||
| | `typestyles/build` | Build-time stubs when runtime is disabled | | ||
| | `typestyles/hmr` | HMR invalidation (used by `@typestyles/vite`) | | ||
| | `typestyles/color` | Color helpers (`rgb`, `oklch`, `mix`, …) — kept off the main entry for bundle size | | ||
| | `typestyles/globals` | Ambient types for CSS modules and global augmentation | | ||
| ## Runtime vs zero-runtime | ||
| | Mode | How | | ||
| | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | **Runtime (default)** | Styles inject into a managed `<style>` tag on first use (~15 KB gzip main entry; CI enforces a budget) | | ||
| | **Zero-runtime (opt-in)** | `@typestyles/vite`, `@typestyles/rollup`, `@typestyles/esbuild`, `@typestyles/webpack`, or `@typestyles/next/build` extract a static `.css` file | | ||
| Same authoring API in both modes. | ||
| ## SSR | ||
| ```tsx | ||
| import { collectStyles } from 'typestyles/server'; | ||
| const { html, css } = await collectStyles(() => renderToString(<App />)); | ||
| // Inject `css` into <head> | ||
| ``` | ||
| Request-safe collection uses `AsyncLocalStorage` on Node — see [SSR guide](https://typestyles.dev/docs/ssr). | ||
| ## Ecosystem packages | ||
| | Package | Purpose | | ||
| | ----------------------------------------------- | ----------------------------------------- | | ||
| | [`@typestyles/vite`](../vite) | Vite — HMR + extraction | | ||
| | [`@typestyles/next`](../next) | Next.js App/Pages Router | | ||
| | [`@typestyles/props`](../props) | Typed atomic utilities | | ||
| | [`@typestyles/open-props`](../open-props) | Open Props tokens | | ||
| | [`@typestyles/migrate`](../migrate) | Codemods from styled-components / Emotion | | ||
| | [`@typestyles/eslint-plugin`](../eslint-plugin) | ESLint rules for style objects | | ||
| See the [packages index](../../README.md#packages) for bundler plugins and build tooling. | ||
| ## License | ||
| Apache-2.0 |
+90
-23
| 'use strict'; | ||
| var async_hooks = require('async_hooks'); | ||
| // src/sheet-node.ts | ||
| // src/sheet-context.ts | ||
| function createSheetState() { | ||
| return { | ||
| insertedRules: /* @__PURE__ */ new Set(), | ||
| ruleCssByKey: /* @__PURE__ */ new Map(), | ||
| pendingRules: [], | ||
| allRules: [], | ||
| flushScheduled: false, | ||
| ssrBuffer: null | ||
| }; | ||
| } | ||
| var globalSheetState = createSheetState(); | ||
| var getStoreImpl = () => globalSheetState; | ||
| var runIsolatedImpl = (fn) => fn(); | ||
| function configureSheetIsolation(config) { | ||
| getStoreImpl = config.getStore; | ||
| runIsolatedImpl = config.runIsolated; | ||
| } | ||
| function getSheetState() { | ||
| return getStoreImpl(); | ||
| } | ||
| function getGlobalSheetState() { | ||
| return globalSheetState; | ||
| } | ||
| function runWithIsolatedSheet(fn) { | ||
| return runIsolatedImpl(fn); | ||
| } | ||
| // src/sheet-node.ts | ||
| var sheetStorage = new async_hooks.AsyncLocalStorage(); | ||
| configureSheetIsolation({ | ||
| getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(), | ||
| runIsolated: (fn) => sheetStorage.run(createSheetState(), fn) | ||
| }); | ||
| // src/sheet.ts | ||
| var STYLE_ELEMENT_ID = "typestyles"; | ||
| var TYPESTYLES_STYLE_ID = "typestyles"; | ||
| var TYPESTYLES_FALLBACK_STYLE_ID = "typestyles-fallback"; | ||
| var STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID; | ||
| var FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID; | ||
| function readNextPublicRuntimeDisabled() { | ||
@@ -10,8 +52,7 @@ if (typeof process === "undefined" || !process.env) return false; | ||
| var RUNTIME_DISABLED = typeof __TYPESTYLES_RUNTIME_DISABLED__ !== "undefined" && __TYPESTYLES_RUNTIME_DISABLED__ === "true" || readNextPublicRuntimeDisabled(); | ||
| var pendingRules = []; | ||
| var allRules = []; | ||
| var styleElement = null; | ||
| var ssrBuffer = null; | ||
| var fallbackStyleElement = null; | ||
| var isBrowser = typeof document !== "undefined" && typeof window !== "undefined"; | ||
| function writeAllRulesToStyleElement(el) { | ||
| const { allRules } = getSheetState(); | ||
| if (RUNTIME_DISABLED || allRules.length === 0) return; | ||
@@ -24,7 +65,7 @@ const sheet = el.sheet; | ||
| } catch { | ||
| el.appendChild(document.createTextNode(css)); | ||
| appendFallbackRule(css); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(allRules.join("\n"))); | ||
| appendFallbackRule(allRules.join("\n")); | ||
| } | ||
@@ -47,3 +88,3 @@ } | ||
| document.head.appendChild(styleElement); | ||
| if (reconnectAfterDetach && allRules.length > 0) { | ||
| if (reconnectAfterDetach && getSheetState().allRules.length > 0) { | ||
| writeAllRulesToStyleElement(styleElement); | ||
@@ -53,8 +94,31 @@ } | ||
| } | ||
| function getFallbackStyleElement() { | ||
| if (fallbackStyleElement && !fallbackStyleElement.isConnected) { | ||
| fallbackStyleElement = null; | ||
| } | ||
| if (fallbackStyleElement) return fallbackStyleElement; | ||
| const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID); | ||
| if (existing?.isConnected) { | ||
| fallbackStyleElement = existing; | ||
| return fallbackStyleElement; | ||
| } | ||
| const main = getStyleElement(); | ||
| fallbackStyleElement = document.createElement("style"); | ||
| fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID; | ||
| main.insertAdjacentElement("afterend", fallbackStyleElement); | ||
| return fallbackStyleElement; | ||
| } | ||
| function appendFallbackRule(css) { | ||
| const el = getFallbackStyleElement(); | ||
| el.appendChild(document.createTextNode(`${css} | ||
| `)); | ||
| } | ||
| function flush() { | ||
| if (pendingRules.length === 0) return; | ||
| const rules = pendingRules; | ||
| pendingRules = []; | ||
| if (ssrBuffer) { | ||
| ssrBuffer.push(...rules); | ||
| const state = getSheetState(); | ||
| state.flushScheduled = false; | ||
| if (state.pendingRules.length === 0) return; | ||
| const rules = state.pendingRules; | ||
| state.pendingRules = []; | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer.push(...rules); | ||
| return; | ||
@@ -70,14 +134,15 @@ } | ||
| } catch { | ||
| el.appendChild(document.createTextNode(rule)); | ||
| appendFallbackRule(rule); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(rules.join("\n"))); | ||
| appendFallbackRule(rules.join("\n")); | ||
| } | ||
| } | ||
| function startCollection() { | ||
| ssrBuffer = []; | ||
| const state = getSheetState(); | ||
| state.ssrBuffer = []; | ||
| return () => { | ||
| const css = ssrBuffer ? ssrBuffer.join("\n") : ""; | ||
| ssrBuffer = null; | ||
| const css = state.ssrBuffer ? state.ssrBuffer.join("\n") : ""; | ||
| state.ssrBuffer = null; | ||
| return css; | ||
@@ -92,8 +157,10 @@ }; | ||
| async function collectStylesFromModules(loaders) { | ||
| const endCollection = startCollection(); | ||
| for (const load of loaders) { | ||
| await load(); | ||
| } | ||
| flushSync(); | ||
| return endCollection(); | ||
| return runWithIsolatedSheet(async () => { | ||
| const endCollection = startCollection(); | ||
| for (const load of loaders) { | ||
| await load(); | ||
| } | ||
| flushSync(); | ||
| return endCollection(); | ||
| }); | ||
| } | ||
@@ -100,0 +167,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/sheet.ts","../src/build.ts"],"names":[],"mappings":";;;AAKA,IAAM,gBAAA,GAAmB,YAAA;AAkDzB,SAAS,6BAAA,GAAyC;AAChD,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,CAAC,OAAA,CAAQ,KAAK,OAAO,KAAA;AAC3D,EAAA,OAAO,OAAA,CAAQ,IAAI,uCAAA,KAA4C,MAAA;AACjE;AACA,IAAM,mBACH,OAAO,+BAAA,KAAoC,WAAA,IAC1C,+BAAA,KAAoC,UACtC,6BAAA,EAA8B;AAKhC,IAAI,eAAyB,EAAC;AAO9B,IAAM,WAAqB,EAAC;AAU5B,IAAI,YAAA,GAAwC,IAAA;AAK5C,IAAI,SAAA,GAA6B,IAAA;AAKjC,IAAM,SAAA,GAAY,OAAO,QAAA,KAAa,WAAA,IAAe,OAAO,MAAA,KAAW,WAAA;AAMvE,SAAS,4BAA4B,EAAA,EAA4B;AAC/D,EAAA,IAAI,gBAAA,IAAoB,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AAC/C,EAAA,MAAM,QAAQ,EAAA,CAAG,KAAA;AACjB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,UAAA,CAAW,GAAA,EAAK,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AACN,QAAA,EAAA,CAAG,WAAA,CAAY,QAAA,CAAS,cAAA,CAAe,GAAG,CAAC,CAAA;AAAA,MAC7C;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,EAAA,CAAG,YAAY,QAAA,CAAS,cAAA,CAAe,SAAS,IAAA,CAAK,IAAI,CAAC,CAAC,CAAA;AAAA,EAC7D;AACF;AAEA,SAAS,eAAA,GAAoC;AAC3C,EAAA,IAAI,oBAAA,GAAuB,KAAA;AAC3B,EAAA,IAAI,YAAA,IAAgB,CAAC,YAAA,CAAa,WAAA,EAAa;AAC7C,IAAA,oBAAA,GAAuB,IAAA;AACvB,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB;AACA,EAAA,IAAI,cAAc,OAAO,YAAA;AAGzB,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,cAAA,CAAe,gBAAgB,CAAA;AACzD,EAAA,IAAI,UAAU,WAAA,EAAa;AACzB,IAAA,YAAA,GAAe,QAAA;AACf,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,YAAA,GAAe,QAAA,CAAS,cAAc,OAAO,CAAA;AAC7C,EAAA,YAAA,CAAa,EAAA,GAAK,gBAAA;AAClB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,YAAY,CAAA;AAGtC,EAAA,IAAI,oBAAA,IAAwB,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC/C,IAAA,2BAAA,CAA4B,YAAY,CAAA;AAAA,EAC1C;AAEA,EAAA,OAAO,YAAA;AACT;AAWA,SAAS,KAAA,GAAc;AAErB,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAE/B,EAAA,MAAM,KAAA,GAAQ,YAAA;AACd,EAAA,YAAA,GAAe,EAAC;AAEhB,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,SAAA,CAAU,IAAA,CAAK,GAAG,KAAK,CAAA;AACvB,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,aAAa,gBAAA,EAAkB;AAEpC,EAAA,MAAM,KAAK,eAAA,EAAgB;AAC3B,EAAA,MAAM,QAAQ,EAAA,CAAG,KAAA;AAEjB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,UAAA,CAAW,IAAA,EAAM,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAAA,MAC9C,CAAA,CAAA,MAAQ;AAEN,QAAA,EAAA,CAAG,WAAA,CAAY,QAAA,CAAS,cAAA,CAAe,IAAI,CAAC,CAAA;AAAA,MAC9C;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AAEL,IAAA,EAAA,CAAG,YAAY,QAAA,CAAS,cAAA,CAAe,MAAM,IAAA,CAAK,IAAI,CAAC,CAAC,CAAA;AAAA,EAC1D;AACF;AAwHO,SAAS,eAAA,GAAgC;AAC9C,EAAA,SAAA,GAAY,EAAC;AACb,EAAA,OAAO,MAAM;AACX,IAAA,MAAM,GAAA,GAAM,SAAA,GAAY,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA;AAC/C,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AACF;AA6CO,SAAS,SAAA,GAAkB;AAChC,EAAA,KAAA,EAAM;AACR;;;ACjVA,eAAsB,yBACpB,OAAA,EACiB;AACjB,EAAA,MAAM,gBAAgB,eAAA,EAAgB;AAEtC,EAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAK1B,IAAA,MAAM,IAAA,EAAK;AAAA,EACb;AAEA,EAAA,SAAA,EAAU;AACV,EAAA,OAAO,aAAA,EAAc;AACvB","file":"build.cjs","sourcesContent":["import {\n namespacesFromTypestylesHmrPrefixes,\n releaseReservedNamespacesForComponentOrClassNames,\n} from './registry';\n\nconst 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 * Last emitted CSS per dedupe key (see {@link warnIfDuplicateRuleKeyConflict}).\n * Cleared with {@link reset} and kept in sync when keys are invalidated.\n */\nconst ruleCssByKey = new Map<string, string>();\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\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 = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n el.appendChild(document.createTextNode(css));\n }\n }\n } else {\n el.appendChild(document.createTextNode(allRules.join('\\n')));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\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 || RUNTIME_DISABLED) 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 && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n\n allRules.unshift(css);\n\n if (ssrBuffer) {\n ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n }\n } else {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (RUNTIME_DISABLED && !ssrBuffer) return;\n pendingRules.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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (!RUNTIME_DISABLED || ssrBuffer) {\n pendingRules.push(css);\n added = true;\n }\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 || RUNTIME_DISABLED) return;\n\n insertedRules.delete(key);\n ruleCssByKey.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.component`, `styles.class`, `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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(namespace: string): void {\n const selectorInfix = `.${namespace}-`;\n const keysToDrop: string[] = [];\n for (const k of insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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","import { startCollection, flushSync } from './sheet';\n\n/**\n * Collect all CSS generated by executing one or more loader functions.\n *\n * This is a low-level primitive intended for build tools (Vite, Next.js, etc.)\n * to implement a zero-runtime extraction step.\n *\n * Example usage (Vite/Node):\n *\n * ```ts\n * import { collectStylesFromModules } from 'typestyles/build';\n *\n * const css = await collectStylesFromModules([\n * () => import('./src/styles'),\n * () => import('./src/tokens'),\n * ]);\n * ```\n */\nexport async function collectStylesFromModules(\n loaders: Array<() => unknown | Promise<unknown>>,\n): Promise<string> {\n const endCollection = startCollection();\n\n for (const load of loaders) {\n // Each loader can synchronously or asynchronously import modules that\n // register typestyles styles, tokens, keyframes, etc.\n // We await in case a loader returns a promise (e.g. dynamic import).\n // The return value itself is ignored; only the side effects matter.\n await load();\n }\n\n flushSync();\n return endCollection();\n}\n"]} | ||
| {"version":3,"sources":["../src/sheet-context.ts","../src/sheet-node.ts","../src/sheet.ts","../src/build.ts"],"names":["AsyncLocalStorage"],"mappings":"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","file":"build.cjs","sourcesContent":["export type SheetState = {\n insertedRules: Set<string>;\n ruleCssByKey: Map<string, string>;\n pendingRules: string[];\n allRules: string[];\n flushScheduled: boolean;\n ssrBuffer: string[] | null;\n};\n\nexport function createSheetState(): SheetState {\n return {\n insertedRules: new Set(),\n ruleCssByKey: new Map(),\n pendingRules: [],\n allRules: [],\n flushScheduled: false,\n ssrBuffer: null,\n };\n}\n\nexport function resetSheetState(state: SheetState): void {\n state.insertedRules.clear();\n state.ruleCssByKey.clear();\n state.pendingRules = [];\n state.allRules.length = 0;\n state.flushScheduled = false;\n state.ssrBuffer = null;\n}\n\nconst globalSheetState = createSheetState();\n\nlet getStoreImpl: () => SheetState = () => globalSheetState;\nlet runIsolatedImpl: <T>(fn: () => T) => T = (fn) => fn();\n\n/** Register Node AsyncLocalStorage isolation (see `sheet-node.ts`). */\nexport function configureSheetIsolation(config: {\n getStore: () => SheetState;\n runIsolated: <T>(fn: () => T) => T;\n}): void {\n getStoreImpl = config.getStore;\n runIsolatedImpl = config.runIsolated;\n}\n\nexport function getSheetState(): SheetState {\n return getStoreImpl();\n}\n\nexport function getGlobalSheetState(): SheetState {\n return globalSheetState;\n}\n\n/** Run `fn` with a fresh sheet store on Node (no-op in the browser bundle). */\nexport function runWithIsolatedSheet<T>(fn: () => T): T {\n return runIsolatedImpl(fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n configureSheetIsolation,\n createSheetState,\n getGlobalSheetState,\n type SheetState,\n} from './sheet-context';\n\nconst sheetStorage = new AsyncLocalStorage<SheetState>();\n\nconfigureSheetIsolation({\n getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(),\n runIsolated: <T>(fn: () => T) => sheetStorage.run(createSheetState(), fn),\n});\n","import {\n namespacesFromTypestylesHmrPrefixes,\n registeredNamespaces,\n releaseReservedNamespacesForComponentOrClassNames,\n resetEmittedClassNameTracking,\n} from './registry';\nimport {\n getSheetState,\n getGlobalSheetState,\n resetSheetState,\n type SheetState,\n} from './sheet-context';\n\n/** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */\nexport const TYPESTYLES_STYLE_ID = 'typestyles';\n\n/**\n * Stable id for the text-fallback `<style>` element. Rules the CSSOM rejects\n * via `insertRule` land here as text. They must never be appended as text to\n * the main element: mutating a `<style>` element's text makes the browser\n * re-parse the element from its text content, discarding every rule that was\n * previously added through `insertRule` — one rejected rule would wipe the\n * entire runtime sheet.\n */\nexport const TYPESTYLES_FALLBACK_STYLE_ID = 'typestyles-fallback';\n\nconst STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID;\nconst FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID;\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * The managed text-fallback <style> element, lazily created (see\n * {@link TYPESTYLES_FALLBACK_STYLE_ID}).\n */\nlet fallbackStyleElement: HTMLStyleElement | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n const { allRules } = getSheetState();\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n appendFallbackRule(css);\n }\n }\n } else {\n appendFallbackRule(allRules.join('\\n'));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && getSheetState().allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * The fallback element mirrors the main element's lifecycle: reuse a connected\n * element by id, recover from detachment (doc swaps), and keep a deterministic\n * position immediately after the main element so cascade order stays stable.\n */\nfunction getFallbackStyleElement(): HTMLStyleElement {\n if (fallbackStyleElement && !fallbackStyleElement.isConnected) {\n fallbackStyleElement = null;\n }\n if (fallbackStyleElement) return fallbackStyleElement;\n\n const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n fallbackStyleElement = existing;\n return fallbackStyleElement;\n }\n\n const main = getStyleElement();\n fallbackStyleElement = document.createElement('style');\n fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID;\n main.insertAdjacentElement('afterend', fallbackStyleElement);\n return fallbackStyleElement;\n}\n\n/**\n * Append a rule the CSSOM rejected as text to the fallback element. The\n * fallback element only ever holds text (never `insertRule`), so re-parsing\n * it on append cannot lose rules.\n */\nfunction appendFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.appendChild(document.createTextNode(`${css}\\n`));\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\n}\n\nfunction flush(): void {\n const state = getSheetState();\n state.flushScheduled = false;\n if (state.pendingRules.length === 0) return;\n\n const rules = state.pendingRules;\n state.pendingRules = [];\n\n if (state.ssrBuffer) {\n state.ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser || RUNTIME_DISABLED) 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 on the dedicated fallback element (handles\n // edge cases with certain selectors) — never on `el`, where the text\n // re-parse would discard all previously inserted CSSOM rules.\n appendFallbackRule(rule);\n }\n }\n } else {\n // Sheet not available yet, append as text\n appendFallbackRule(rules.join('\\n'));\n }\n}\n\nfunction scheduleFlush(): void {\n const state = getSheetState();\n if (state.flushScheduled) return;\n state.flushScheduled = true;\n\n if (state.ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const state = getSheetState();\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (state.insertedRules.has(key)) return;\n state.insertedRules.add(key);\n\n state.allRules.unshift(css);\n notifyRegisteredCssChanged();\n\n if (state.ssrBuffer) {\n state.ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n prependFallbackRule(css);\n }\n } else {\n prependFallbackRule(css);\n }\n}\n\n/** Front-insert for the `@layer` order preamble when the CSSOM rejects it. */\nfunction prependFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n const state = getSheetState();\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n notifyRegisteredCssChanged();\n if (RUNTIME_DISABLED && !state.ssrBuffer) return;\n state.pendingRules.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 const state = getSheetState();\n let added = false;\n let registered = false;\n for (const { key, css } of rules) {\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n registered = true;\n if (!RUNTIME_DISABLED || state.ssrBuffer) {\n state.pendingRules.push(css);\n added = true;\n }\n }\n if (registered) notifyRegisteredCssChanged();\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 || RUNTIME_DISABLED) return;\n\n const state = getSheetState();\n state.insertedRules.delete(key);\n state.ruleCssByKey.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 const state = getSheetState();\n state.ssrBuffer = [];\n return () => {\n const css = state.ssrBuffer ? state.ssrBuffer.join('\\n') : '';\n state.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.component`, `styles.class`, `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 getSheetState().allRules.join('\\n');\n}\n\nconst registeredCssListeners = new Set<() => void>();\n\nfunction notifyRegisteredCssChanged(): void {\n for (const listener of registeredCssListeners) {\n listener();\n }\n}\n\n/**\n * Subscribe to changes in the registered CSS (`getRegisteredCss()`).\n * Returns an unsubscribe function. Compatible with `useSyncExternalStore`.\n *\n * @example\n * ```ts\n * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server';\n *\n * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss);\n * ```\n */\nexport function subscribeRegisteredCss(listener: () => void): () => void {\n registeredCssListeners.add(listener);\n return () => {\n registeredCssListeners.delete(listener);\n };\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n resetSheetState(getGlobalSheetState());\n const active = getSheetState();\n if (active !== getGlobalSheetState()) {\n resetSheetState(active);\n }\n registeredNamespaces.clear();\n resetEmittedClassNameTracking();\n notifyRegisteredCssChanged();\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n if (isBrowser && fallbackStyleElement) {\n fallbackStyleElement.remove();\n fallbackStyleElement = 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 * Drop CSS text queued in `pendingRules` / `allRules` / an active `ssrBuffer` for rules whose\n * key was just invalidated. Without this, re-registering a namespace before its first\n * registration has flushed (no intervening `flushSync()` / microtask) leaves the stale CSS\n * sitting in these arrays — `insertedRules` no longer references it, so it's never deduped, and\n * it gets flushed alongside the new CSS as a duplicate, conflicting rule.\n */\nfunction pruneRemovedCss(state: SheetState, removedCss: ReadonlySet<string>): void {\n if (removedCss.size === 0) return;\n state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css));\n state.allRules = state.allRules.filter((css) => !removedCss.has(css));\n if (state.ssrBuffer) {\n state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css));\n }\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of keys) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(\n namespace: string,\n emittedClassPrefix?: string,\n): void {\n const selectorInfix = `.${emittedClassPrefix ?? `${namespace}-`}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\n}\n\n/**\n * Drop every rule key tied to a `styles.class('name', …)` registration — the base selector plus\n * any pseudo/nested/at-rule-wrapped variants — and release the reserved namespace entry. Used for\n * Vite HMR and for dev recovery when a module re-runs before `hot.dispose`, including\n * multi-environment SSR setups (e.g. the Vite Environment API, or RSC frameworks like Waku) that\n * re-evaluate the same source module once per environment within a single process.\n *\n * No-op when `emittedClassName` is `undefined` (hashed/compact/atomic modes derive the class name\n * from the serialized properties, so there's no reliable selector to invalidate ahead of time —\n * same limitation `invalidateComponentNamespaceForDev` has for those modes).\n */\nexport function invalidateClassNamespaceForDev(emittedClassName?: string): void {\n if (!emittedClassName) return;\n const selectorInfix = `.${emittedClassName}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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","import './sheet-node';\nimport { startCollection, flushSync } from './sheet';\nimport { runWithIsolatedSheet } from './sheet-context';\n\n/**\n * Collect all CSS generated by executing one or more loader functions.\n *\n * This is a low-level primitive intended for build tools (Vite, Next.js, etc.)\n * to implement a zero-runtime extraction step. On Node, each call uses an\n * isolated sheet store so concurrent extractions do not share state.\n *\n * Example usage (Vite/Node):\n *\n * ```ts\n * import { collectStylesFromModules } from 'typestyles/build';\n *\n * const css = await collectStylesFromModules([\n * () => import('./src/styles'),\n * () => import('./src/tokens'),\n * ]);\n * ```\n */\nexport async function collectStylesFromModules(\n loaders: Array<() => unknown | Promise<unknown>>,\n): Promise<string> {\n return runWithIsolatedSheet(async () => {\n const endCollection = startCollection();\n\n for (const load of loaders) {\n // Each loader can synchronously or asynchronously import modules that\n // register typestyles styles, tokens, keyframes, etc.\n // We await in case a loader returns a promise (e.g. dynamic import).\n // The return value itself is ignored; only the side effects matter.\n await load();\n }\n\n flushSync();\n return endCollection();\n });\n}\n"]} |
+2
-1
@@ -5,3 +5,4 @@ /** | ||
| * This is a low-level primitive intended for build tools (Vite, Next.js, etc.) | ||
| * to implement a zero-runtime extraction step. | ||
| * to implement a zero-runtime extraction step. On Node, each call uses an | ||
| * isolated sheet store so concurrent extractions do not share state. | ||
| * | ||
@@ -8,0 +9,0 @@ * Example usage (Vite/Node): |
+2
-1
@@ -5,3 +5,4 @@ /** | ||
| * This is a low-level primitive intended for build tools (Vite, Next.js, etc.) | ||
| * to implement a zero-runtime extraction step. | ||
| * to implement a zero-runtime extraction step. On Node, each call uses an | ||
| * isolated sheet store so concurrent extractions do not share state. | ||
| * | ||
@@ -8,0 +9,0 @@ * Example usage (Vite/Node): |
+10
-7
@@ -1,2 +0,3 @@ | ||
| import { startCollection, flushSync } from './chunk-G6ATUNEZ.js'; | ||
| import './chunk-Z4UVRQXZ.js'; | ||
| import { runWithIsolatedSheet, startCollection, flushSync } from './chunk-5CMEHXCU.js'; | ||
| import './chunk-PZ5AY32C.js'; | ||
@@ -6,8 +7,10 @@ | ||
| async function collectStylesFromModules(loaders) { | ||
| const endCollection = startCollection(); | ||
| for (const load of loaders) { | ||
| await load(); | ||
| } | ||
| flushSync(); | ||
| return endCollection(); | ||
| return runWithIsolatedSheet(async () => { | ||
| const endCollection = startCollection(); | ||
| for (const load of loaders) { | ||
| await load(); | ||
| } | ||
| flushSync(); | ||
| return endCollection(); | ||
| }); | ||
| } | ||
@@ -14,0 +17,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/build.ts"],"names":[],"mappings":";;;;AAmBA,eAAsB,yBACpB,OAAA,EACiB;AACjB,EAAA,MAAM,gBAAgB,eAAA,EAAgB;AAEtC,EAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAK1B,IAAA,MAAM,IAAA,EAAK;AAAA,EACb;AAEA,EAAA,SAAA,EAAU;AACV,EAAA,OAAO,aAAA,EAAc;AACvB","file":"build.js","sourcesContent":["import { startCollection, flushSync } from './sheet';\n\n/**\n * Collect all CSS generated by executing one or more loader functions.\n *\n * This is a low-level primitive intended for build tools (Vite, Next.js, etc.)\n * to implement a zero-runtime extraction step.\n *\n * Example usage (Vite/Node):\n *\n * ```ts\n * import { collectStylesFromModules } from 'typestyles/build';\n *\n * const css = await collectStylesFromModules([\n * () => import('./src/styles'),\n * () => import('./src/tokens'),\n * ]);\n * ```\n */\nexport async function collectStylesFromModules(\n loaders: Array<() => unknown | Promise<unknown>>,\n): Promise<string> {\n const endCollection = startCollection();\n\n for (const load of loaders) {\n // Each loader can synchronously or asynchronously import modules that\n // register typestyles styles, tokens, keyframes, etc.\n // We await in case a loader returns a promise (e.g. dynamic import).\n // The return value itself is ignored; only the side effects matter.\n await load();\n }\n\n flushSync();\n return endCollection();\n}\n"]} | ||
| {"version":3,"sources":["../src/build.ts"],"names":[],"mappings":";;;;;AAsBA,eAAsB,yBACpB,OAAA,EACiB;AACjB,EAAA,OAAO,qBAAqB,YAAY;AACtC,IAAA,MAAM,gBAAgB,eAAA,EAAgB;AAEtC,IAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAK1B,MAAA,MAAM,IAAA,EAAK;AAAA,IACb;AAEA,IAAA,SAAA,EAAU;AACV,IAAA,OAAO,aAAA,EAAc;AAAA,EACvB,CAAC,CAAA;AACH","file":"build.js","sourcesContent":["import './sheet-node';\nimport { startCollection, flushSync } from './sheet';\nimport { runWithIsolatedSheet } from './sheet-context';\n\n/**\n * Collect all CSS generated by executing one or more loader functions.\n *\n * This is a low-level primitive intended for build tools (Vite, Next.js, etc.)\n * to implement a zero-runtime extraction step. On Node, each call uses an\n * isolated sheet store so concurrent extractions do not share state.\n *\n * Example usage (Vite/Node):\n *\n * ```ts\n * import { collectStylesFromModules } from 'typestyles/build';\n *\n * const css = await collectStylesFromModules([\n * () => import('./src/styles'),\n * () => import('./src/tokens'),\n * ]);\n * ```\n */\nexport async function collectStylesFromModules(\n loaders: Array<() => unknown | Promise<unknown>>,\n): Promise<string> {\n return runWithIsolatedSheet(async () => {\n const endCollection = startCollection();\n\n for (const load of loaders) {\n // Each loader can synchronously or asynchronously import modules that\n // register typestyles styles, tokens, keyframes, etc.\n // We await in case a loader returns a promise (e.g. dynamic import).\n // The return value itself is ignored; only the side effects matter.\n await load();\n }\n\n flushSync();\n return endCollection();\n });\n}\n"]} |
@@ -1,2 +0,2 @@ | ||
| import { C as CSSProperties, G as GlobalStyleTuple } from './global-style-tuple-eE4ncVOt.cjs'; | ||
| import { C as CSSProperties, G as GlobalStyleTuple } from './global-style-tuple-DPvH8JpJ.cjs'; | ||
| import 'csstype'; | ||
@@ -3,0 +3,0 @@ |
@@ -1,2 +0,2 @@ | ||
| import { C as CSSProperties, G as GlobalStyleTuple } from './global-style-tuple-eE4ncVOt.js'; | ||
| import { C as CSSProperties, G as GlobalStyleTuple } from './global-style-tuple-DPvH8JpJ.js'; | ||
| import 'csstype'; | ||
@@ -3,0 +3,0 @@ |
+45
-10
@@ -31,5 +31,20 @@ 'use strict'; | ||
| // src/sheet-context.ts | ||
| function createSheetState() { | ||
| return { | ||
| insertedRules: /* @__PURE__ */ new Set(), | ||
| ruleCssByKey: /* @__PURE__ */ new Map(), | ||
| pendingRules: [], | ||
| allRules: [], | ||
| flushScheduled: false, | ||
| ssrBuffer: null | ||
| }; | ||
| } | ||
| var globalSheetState = createSheetState(); | ||
| var getStoreImpl = () => globalSheetState; | ||
| function getSheetState() { | ||
| return getStoreImpl(); | ||
| } | ||
| // src/sheet.ts | ||
| var insertedRules = /* @__PURE__ */ new Set(); | ||
| var ruleCssByKey = /* @__PURE__ */ new Map(); | ||
| function readNextPublicRuntimeDisabled() { | ||
@@ -41,9 +56,22 @@ if (typeof process === "undefined" || !process.env) return false; | ||
| var isBrowser = typeof document !== "undefined" && typeof window !== "undefined"; | ||
| function pruneRemovedCss(state, removedCss) { | ||
| if (removedCss.size === 0) return; | ||
| state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css)); | ||
| state.allRules = state.allRules.filter((css) => !removedCss.has(css)); | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css)); | ||
| } | ||
| } | ||
| function invalidatePrefix(prefix) { | ||
| for (const key of insertedRules) { | ||
| const state = getSheetState(); | ||
| const removedCss = /* @__PURE__ */ new Set(); | ||
| for (const key of state.insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| pruneRemovedCss(state, removedCss); | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix])); | ||
@@ -54,14 +82,21 @@ if (!isBrowser) return; | ||
| function invalidateKeys(keys, prefixes) { | ||
| const state = getSheetState(); | ||
| const removedCss = /* @__PURE__ */ new Set(); | ||
| for (const key of keys) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| for (const prefix of prefixes) { | ||
| for (const key of insertedRules) { | ||
| for (const key of state.insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| const css = state.ruleCssByKey.get(key); | ||
| if (css != null) removedCss.add(css); | ||
| state.insertedRules.delete(key); | ||
| state.ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| } | ||
| pruneRemovedCss(state, removedCss); | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes)); | ||
@@ -68,0 +103,0 @@ if (!isBrowser) return; |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/registry.ts","../src/sheet.ts"],"names":[],"mappings":"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","file":"hmr.cjs","sourcesContent":["/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n\nconst COLON = ':';\n\n/**\n * Drop reserved `scopeId:namespace` keys so a module can re-register after HMR.\n * `namespace` is the first argument to `styles.component()` / `styles.class()` (not the scope).\n */\nexport function releaseReservedNamespacesForComponentOrClassNames(\n namespaces: readonly string[],\n): void {\n if (namespaces.length === 0) return;\n const wanted = new Set(namespaces);\n const toRemove: string[] = [];\n for (const key of registeredNamespaces) {\n const i = key.indexOf(COLON);\n if (i === -1) continue;\n if (wanted.has(key.slice(i + 1))) {\n toRemove.push(key);\n }\n }\n for (const key of toRemove) {\n registeredNamespaces.delete(key);\n }\n}\n\n/** Vite plugin passes `.${namespace}-` prefixes for `styles.component()` invalidation. */\nexport function namespacesFromTypestylesHmrPrefixes(prefixes: readonly string[]): string[] {\n const out: string[] = [];\n for (const p of prefixes) {\n if (p.length >= 2 && p.startsWith('.') && p.endsWith('-')) {\n out.push(p.slice(1, -1));\n }\n }\n return out;\n}\n","import {\n namespacesFromTypestylesHmrPrefixes,\n releaseReservedNamespacesForComponentOrClassNames,\n} from './registry';\n\nconst 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 * Last emitted CSS per dedupe key (see {@link warnIfDuplicateRuleKeyConflict}).\n * Cleared with {@link reset} and kept in sync when keys are invalidated.\n */\nconst ruleCssByKey = new Map<string, string>();\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\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 = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n el.appendChild(document.createTextNode(css));\n }\n }\n } else {\n el.appendChild(document.createTextNode(allRules.join('\\n')));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\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 || RUNTIME_DISABLED) 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 && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n\n allRules.unshift(css);\n\n if (ssrBuffer) {\n ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n }\n } else {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (RUNTIME_DISABLED && !ssrBuffer) return;\n pendingRules.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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (!RUNTIME_DISABLED || ssrBuffer) {\n pendingRules.push(css);\n added = true;\n }\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 || RUNTIME_DISABLED) return;\n\n insertedRules.delete(key);\n ruleCssByKey.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.component`, `styles.class`, `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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(namespace: string): void {\n const selectorInfix = `.${namespace}-`;\n const keysToDrop: string[] = [];\n for (const k of insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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"]} | ||
| {"version":3,"sources":["../src/registry.ts","../src/sheet-context.ts","../src/sheet.ts"],"names":[],"mappings":"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","file":"hmr.cjs","sourcesContent":["/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n\n/**\n * Development-only map of emitted class name → owner key. Two different owners\n * producing the same class string means rules will overwrite each other —\n * either a cross-scope semantic collision or a hash collision in\n * `hashed`/`compact` mode.\n */\nconst emittedClassNameOwners = new Map<string, string>();\n\nfunction isDev(): boolean {\n return typeof process === 'undefined' || process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Track an emitted class name and warn when the same class string is produced\n * by two different style definitions. Development-only; no-op in production.\n *\n * The owner key identifies the logical definition (`scope:namespace` for\n * `styles.class` / `styles.component`, payload-derived for `styles.hashClass`)\n * so HMR re-registrations of the same definition are not flagged.\n */\nexport function trackEmittedClassName(className: string, ownerKey: string): void {\n if (!isDev()) return;\n const existing = emittedClassNameOwners.get(className);\n if (existing !== undefined && existing !== ownerKey) {\n console.error(\n `[typestyles] Class name collision: \".${className}\" is generated by two different ` +\n `style definitions (${existing} and ${ownerKey}). Their CSS rules will overwrite ` +\n `each other. Use distinct namespaces, or isolate each package/file with ` +\n `createStyles({ scopeId: '…' }) (or fileScopeId(import.meta)).`,\n );\n return;\n }\n emittedClassNameOwners.set(className, ownerKey);\n}\n\n/** Clear collision tracking. Used by `reset()` in tests. */\nexport function resetEmittedClassNameTracking(): void {\n emittedClassNameOwners.clear();\n warnedUnscopedNamespaces.clear();\n}\n\n/**\n * Namespaces that have already emitted an unscoped-collision warning.\n * Prevents duplicate warnings for the same namespace during a session.\n */\nconst warnedUnscopedNamespaces = new Set<string>();\n\n/**\n * Dev-mode warning when the same namespace is registered more than once\n * without a `scopeId`. Two unscoped registrations of the same namespace\n * produce identical class names whose CSS rules silently overwrite each\n * other. Emits once per namespace.\n */\nexport function warnUnscopedCollision(namespace: string, apiName: string): void {\n if (!isDev()) return;\n if (warnedUnscopedNamespaces.has(namespace)) return;\n warnedUnscopedNamespaces.add(namespace);\n console.warn(\n `[typestyles] ${apiName}('${namespace}', …) was registered more than once without a ` +\n `scopeId. Their CSS rules will overwrite each other. Isolate each definition with ` +\n `createStyles({ scopeId: '…' }) or createTypeStyles({ scopeId: '…' }). ` +\n `If this is caused by HMR re-execution, this warning is safe to ignore.`,\n );\n}\n\nconst COLON = ':';\n\n/**\n * Drop reserved `scopeId:namespace` keys so a module can re-register after HMR.\n * `namespace` is the first argument to `styles.component()` / `styles.class()` (not the scope).\n */\nexport function releaseReservedNamespacesForComponentOrClassNames(\n namespaces: readonly string[],\n): void {\n if (namespaces.length === 0) return;\n const wanted = new Set(namespaces);\n const toRemove: string[] = [];\n for (const key of registeredNamespaces) {\n const i = key.indexOf(COLON);\n if (i === -1) continue;\n if (wanted.has(key.slice(i + 1))) {\n toRemove.push(key);\n }\n }\n for (const key of toRemove) {\n registeredNamespaces.delete(key);\n }\n}\n\n/** Vite plugin passes `.${namespace}-` prefixes for `styles.component()` invalidation. */\nexport function namespacesFromTypestylesHmrPrefixes(prefixes: readonly string[]): string[] {\n const out: string[] = [];\n for (const p of prefixes) {\n if (p.length >= 2 && p.startsWith('.') && p.endsWith('-')) {\n out.push(p.slice(1, -1));\n }\n }\n return out;\n}\n","export type SheetState = {\n insertedRules: Set<string>;\n ruleCssByKey: Map<string, string>;\n pendingRules: string[];\n allRules: string[];\n flushScheduled: boolean;\n ssrBuffer: string[] | null;\n};\n\nexport function createSheetState(): SheetState {\n return {\n insertedRules: new Set(),\n ruleCssByKey: new Map(),\n pendingRules: [],\n allRules: [],\n flushScheduled: false,\n ssrBuffer: null,\n };\n}\n\nexport function resetSheetState(state: SheetState): void {\n state.insertedRules.clear();\n state.ruleCssByKey.clear();\n state.pendingRules = [];\n state.allRules.length = 0;\n state.flushScheduled = false;\n state.ssrBuffer = null;\n}\n\nconst globalSheetState = createSheetState();\n\nlet getStoreImpl: () => SheetState = () => globalSheetState;\nlet runIsolatedImpl: <T>(fn: () => T) => T = (fn) => fn();\n\n/** Register Node AsyncLocalStorage isolation (see `sheet-node.ts`). */\nexport function configureSheetIsolation(config: {\n getStore: () => SheetState;\n runIsolated: <T>(fn: () => T) => T;\n}): void {\n getStoreImpl = config.getStore;\n runIsolatedImpl = config.runIsolated;\n}\n\nexport function getSheetState(): SheetState {\n return getStoreImpl();\n}\n\nexport function getGlobalSheetState(): SheetState {\n return globalSheetState;\n}\n\n/** Run `fn` with a fresh sheet store on Node (no-op in the browser bundle). */\nexport function runWithIsolatedSheet<T>(fn: () => T): T {\n return runIsolatedImpl(fn);\n}\n","import {\n namespacesFromTypestylesHmrPrefixes,\n registeredNamespaces,\n releaseReservedNamespacesForComponentOrClassNames,\n resetEmittedClassNameTracking,\n} from './registry';\nimport {\n getSheetState,\n getGlobalSheetState,\n resetSheetState,\n type SheetState,\n} from './sheet-context';\n\n/** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */\nexport const TYPESTYLES_STYLE_ID = 'typestyles';\n\n/**\n * Stable id for the text-fallback `<style>` element. Rules the CSSOM rejects\n * via `insertRule` land here as text. They must never be appended as text to\n * the main element: mutating a `<style>` element's text makes the browser\n * re-parse the element from its text content, discarding every rule that was\n * previously added through `insertRule` — one rejected rule would wipe the\n * entire runtime sheet.\n */\nexport const TYPESTYLES_FALLBACK_STYLE_ID = 'typestyles-fallback';\n\nconst STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID;\nconst FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID;\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * The managed text-fallback <style> element, lazily created (see\n * {@link TYPESTYLES_FALLBACK_STYLE_ID}).\n */\nlet fallbackStyleElement: HTMLStyleElement | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n const { allRules } = getSheetState();\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n appendFallbackRule(css);\n }\n }\n } else {\n appendFallbackRule(allRules.join('\\n'));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && getSheetState().allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * The fallback element mirrors the main element's lifecycle: reuse a connected\n * element by id, recover from detachment (doc swaps), and keep a deterministic\n * position immediately after the main element so cascade order stays stable.\n */\nfunction getFallbackStyleElement(): HTMLStyleElement {\n if (fallbackStyleElement && !fallbackStyleElement.isConnected) {\n fallbackStyleElement = null;\n }\n if (fallbackStyleElement) return fallbackStyleElement;\n\n const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n fallbackStyleElement = existing;\n return fallbackStyleElement;\n }\n\n const main = getStyleElement();\n fallbackStyleElement = document.createElement('style');\n fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID;\n main.insertAdjacentElement('afterend', fallbackStyleElement);\n return fallbackStyleElement;\n}\n\n/**\n * Append a rule the CSSOM rejected as text to the fallback element. The\n * fallback element only ever holds text (never `insertRule`), so re-parsing\n * it on append cannot lose rules.\n */\nfunction appendFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.appendChild(document.createTextNode(`${css}\\n`));\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\n}\n\nfunction flush(): void {\n const state = getSheetState();\n state.flushScheduled = false;\n if (state.pendingRules.length === 0) return;\n\n const rules = state.pendingRules;\n state.pendingRules = [];\n\n if (state.ssrBuffer) {\n state.ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser || RUNTIME_DISABLED) 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 on the dedicated fallback element (handles\n // edge cases with certain selectors) — never on `el`, where the text\n // re-parse would discard all previously inserted CSSOM rules.\n appendFallbackRule(rule);\n }\n }\n } else {\n // Sheet not available yet, append as text\n appendFallbackRule(rules.join('\\n'));\n }\n}\n\nfunction scheduleFlush(): void {\n const state = getSheetState();\n if (state.flushScheduled) return;\n state.flushScheduled = true;\n\n if (state.ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const state = getSheetState();\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (state.insertedRules.has(key)) return;\n state.insertedRules.add(key);\n\n state.allRules.unshift(css);\n notifyRegisteredCssChanged();\n\n if (state.ssrBuffer) {\n state.ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n prependFallbackRule(css);\n }\n } else {\n prependFallbackRule(css);\n }\n}\n\n/** Front-insert for the `@layer` order preamble when the CSSOM rejects it. */\nfunction prependFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n const state = getSheetState();\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n notifyRegisteredCssChanged();\n if (RUNTIME_DISABLED && !state.ssrBuffer) return;\n state.pendingRules.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 const state = getSheetState();\n let added = false;\n let registered = false;\n for (const { key, css } of rules) {\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n registered = true;\n if (!RUNTIME_DISABLED || state.ssrBuffer) {\n state.pendingRules.push(css);\n added = true;\n }\n }\n if (registered) notifyRegisteredCssChanged();\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 || RUNTIME_DISABLED) return;\n\n const state = getSheetState();\n state.insertedRules.delete(key);\n state.ruleCssByKey.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 const state = getSheetState();\n state.ssrBuffer = [];\n return () => {\n const css = state.ssrBuffer ? state.ssrBuffer.join('\\n') : '';\n state.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.component`, `styles.class`, `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 getSheetState().allRules.join('\\n');\n}\n\nconst registeredCssListeners = new Set<() => void>();\n\nfunction notifyRegisteredCssChanged(): void {\n for (const listener of registeredCssListeners) {\n listener();\n }\n}\n\n/**\n * Subscribe to changes in the registered CSS (`getRegisteredCss()`).\n * Returns an unsubscribe function. Compatible with `useSyncExternalStore`.\n *\n * @example\n * ```ts\n * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server';\n *\n * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss);\n * ```\n */\nexport function subscribeRegisteredCss(listener: () => void): () => void {\n registeredCssListeners.add(listener);\n return () => {\n registeredCssListeners.delete(listener);\n };\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n resetSheetState(getGlobalSheetState());\n const active = getSheetState();\n if (active !== getGlobalSheetState()) {\n resetSheetState(active);\n }\n registeredNamespaces.clear();\n resetEmittedClassNameTracking();\n notifyRegisteredCssChanged();\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n if (isBrowser && fallbackStyleElement) {\n fallbackStyleElement.remove();\n fallbackStyleElement = 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 * Drop CSS text queued in `pendingRules` / `allRules` / an active `ssrBuffer` for rules whose\n * key was just invalidated. Without this, re-registering a namespace before its first\n * registration has flushed (no intervening `flushSync()` / microtask) leaves the stale CSS\n * sitting in these arrays — `insertedRules` no longer references it, so it's never deduped, and\n * it gets flushed alongside the new CSS as a duplicate, conflicting rule.\n */\nfunction pruneRemovedCss(state: SheetState, removedCss: ReadonlySet<string>): void {\n if (removedCss.size === 0) return;\n state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css));\n state.allRules = state.allRules.filter((css) => !removedCss.has(css));\n if (state.ssrBuffer) {\n state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css));\n }\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of keys) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(\n namespace: string,\n emittedClassPrefix?: string,\n): void {\n const selectorInfix = `.${emittedClassPrefix ?? `${namespace}-`}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\n}\n\n/**\n * Drop every rule key tied to a `styles.class('name', …)` registration — the base selector plus\n * any pseudo/nested/at-rule-wrapped variants — and release the reserved namespace entry. Used for\n * Vite HMR and for dev recovery when a module re-runs before `hot.dispose`, including\n * multi-environment SSR setups (e.g. the Vite Environment API, or RSC frameworks like Waku) that\n * re-evaluate the same source module once per environment within a single process.\n *\n * No-op when `emittedClassName` is `undefined` (hashed/compact/atomic modes derive the class name\n * from the serialized properties, so there's no reliable selector to invalidate ahead of time —\n * same limitation `invalidateComponentNamespaceForDev` has for those modes).\n */\nexport function invalidateClassNamespaceForDev(emittedClassName?: string): void {\n if (!emittedClassName) return;\n const selectorInfix = `.${emittedClassName}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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
-1
@@ -1,1 +0,1 @@ | ||
| export { a as invalidateKeys, b as invalidatePrefix } from './hmr-D5sXuQgK.cjs'; | ||
| export { a as invalidateKeys, b as invalidatePrefix } from './hmr-DhHxThox.cjs'; |
+1
-1
@@ -1,1 +0,1 @@ | ||
| export { a as invalidateKeys, b as invalidatePrefix } from './hmr-D5sXuQgK.js'; | ||
| export { a as invalidateKeys, b as invalidatePrefix } from './hmr-DhHxThox.js'; |
+1
-1
@@ -1,4 +0,4 @@ | ||
| export { invalidateKeys, invalidatePrefix } from './chunk-G6ATUNEZ.js'; | ||
| export { invalidateKeys, invalidatePrefix } from './chunk-5CMEHXCU.js'; | ||
| import './chunk-PZ5AY32C.js'; | ||
| //# sourceMappingURL=hmr.js.map | ||
| //# sourceMappingURL=hmr.js.map |
+291
-182
@@ -1,6 +0,23 @@ | ||
| import { T as ThemeConditionMedia, a as ThemeConditionAttr, b as ThemeConditionClass, c as ThemeConditionSelector, d as ThemeCondition, e as ThemeConditionAnd, f as ThemeConditionOr, g as ThemeOverrides, h as ThemeModeDefinition, i as ThemeSurface, j as ThemeConfig, k as TokenValues, l as TokenRef, C as CSSProperties, S as StyleUtils, V as VariantDefinitions, m as ComponentConfigInput, n as ComponentReturn, F as FlatComponentConfigInput, o as FlatComponentReturn, p as SlotVariantDefinitions, q as SlotComponentConfigInput, r as SlotComponentFunction, M as MultiSlotConfigInput, s as MultiSlotReturn, t as CSSPropertiesWithUtils, G as GlobalStyleTuple, u as FontFaceProps, v as CSSVarRef } from './global-style-tuple-eE4ncVOt.cjs'; | ||
| export { w as CSSValue, x as ComponentConfig, y as ComponentConfigContext, z as ComponentInternalVarRef, A as ComponentSelections, B as ComponentVarDefinitions, D as ComponentVarDescriptor, E as ComponentVarNode, H as ComponentVarOptions, I as ComponentVarRefTree, J as ComponentVariants, K as DeepPartialTokenValues, L as FlatComponentConfig, N as FlatComponentSelections, O as FlatTokenEntry, P as FontFaceSrc, Q as KeyframeStops, R as SlotComponentConfig, U as SlotStyles, W as StyleDefinitions, X as StyleDefinitionsWithUtils, Y as ThemeConditionNot, Z as VariantOptionStyle, _ as flattenTokenEntries } from './global-style-tuple-eE4ncVOt.cjs'; | ||
| export { e as ensureDocumentStylesAttached, f as flushSync, g as getRegisteredCss, i as insertRules, r as reset } from './hmr-D5sXuQgK.cjs'; | ||
| import { T as ThemeConditionMedia, a as ThemeConditionAttr, b as ThemeConditionClass, c as ThemeConditionSelector, d as ThemeCondition, e as ThemeConditionAnd, f as ThemeConditionOr, g as ThemeOverrides, h as ThemeModeDefinition, i as ThemeSurface, j as ThemeConfig, k as TokenRegistry, l as TokenValues, m as CreatedTokenRef, n as TokenRef, C as CSSProperties, V as VariantDefinitions, o as ComponentConfigInput, p as ComponentAttrsReturn, F as FlatComponentConfigInput, q as FlatComponentReturn, R as RegisteredPropertyOptions, r as RegisteredPropertyRef, s as ComponentReturn, S as SlotVariantDefinitions, t as SlotComponentConfigInput, u as SlotComponentFunction, M as MultiSlotConfigInput, v as MultiSlotReturn, w as StyleUtils, x as CSSPropertiesWithUtils, y as ComposeSelectorInput, z as ComposeFn, G as GlobalStyleTuple, A as FontFaceProps, B as CSSVarRef } from './global-style-tuple-DPvH8JpJ.cjs'; | ||
| export { D as CSSValue, E as ComponentAttrsResult, H as ComponentConfig, I as ComponentConfigContext, J as ComponentInternalVarRef, K as ComponentSelections, L as ComponentVarDefinitions, N as ComponentVarDescriptor, O as ComponentVarNode, P as ComponentVarOptions, Q as ComponentVarRefTree, U as ComponentVariants, W as DeepPartialTokenValues, X as FlatComponentConfig, Y as FlatComponentSelections, Z as FlatTokenEntry, _ as FlatTokenPathEntry, $ as FontFaceSrc, a0 as InferTokenNamespace, a1 as InferTokenValues, a2 as KeyframeStops, a3 as MergeComposeSelections, a4 as SlotComponentConfig, a5 as SlotStyles, a6 as StyleDefinitions, a7 as StyleDefinitionsWithUtils, a8 as ThemeConditionNot, a9 as TokenDescriptor, aa as VariantOptionStyle, ab as flattenTokenEntries, ac as flattenTokenPaths, ad as isTokenDescriptor } from './global-style-tuple-DPvH8JpJ.cjs'; | ||
| export { e as ensureDocumentStylesAttached, f as flushSync, g as getRegisteredCss, i as insertRules, r as reset, s as subscribeRegisteredCss } from './hmr-DhHxThox.cjs'; | ||
| import 'csstype'; | ||
| type TokenNameContext = { | ||
| /** Raw `scopeId` from `createTokens`, trimmed; undefined when unscoped. */ | ||
| scopeId: string | undefined; | ||
| /** Sanitized scope segment used in default naming (`app` from `@acme/ui`). */ | ||
| scope: string; | ||
| /** First argument to `tokens.create('color', …)`. */ | ||
| namespace: string; | ||
| /** Flattened leaf path with default `-` join (`brand-primary`). */ | ||
| path: string; | ||
| /** Path segments before joining (`['brand', 'primary']`). */ | ||
| segments: readonly string[]; | ||
| }; | ||
| type TokenNameTemplate = (ctx: TokenNameContext) => string; | ||
| type ThemeTokenNaming = { | ||
| resolveName(namespace: string, path: string, segments: readonly string[]): string; | ||
| }; | ||
| /** | ||
@@ -35,6 +52,6 @@ * Declare cascade layer order and optionally prepend framework layer names | ||
| declare function condAttr(name: string, value: string, opts: { | ||
| scope: 'self' | 'ancestor'; | ||
| scope: 'self' | 'ancestor' | 'descendant'; | ||
| }): ThemeConditionAttr; | ||
| declare function condClassName(name: string, opts: { | ||
| scope: 'self' | 'ancestor'; | ||
| scope: 'self' | 'ancestor' | 'descendant'; | ||
| }): ThemeConditionClass; | ||
@@ -52,3 +69,3 @@ declare function condSelector(selector: string): ThemeConditionSelector; | ||
| * | ||
| * Not supported: `when.selector`, `when.or`, combined `@media` + selector, or both ancestor and self selector parts on the same branch. Those log a dev warning and emit no rule. | ||
| * Not supported: `when.selector`, `when.or`, `scope: 'descendant'` conditions (a descendant relationship can't collapse into a single `:not()` compound selector), combined `@media` + selector, or both ancestor and self selector parts on the same branch. Those log a dev warning and emit no rule. | ||
| */ | ||
@@ -64,2 +81,3 @@ declare function condNot(condition: ThemeCondition): ThemeCondition; | ||
| * tokens.when.attr('data-color-mode', 'dark', { scope: 'ancestor' }) | ||
| * tokens.when.attr('data-surface', 'dark', { scope: 'descendant' }) | ||
| * tokens.when.or(tokens.when.prefersDark, tokens.when.attr('data-mode', 'dark', { scope: 'self' })) | ||
@@ -167,3 +185,3 @@ * ``` | ||
| */ | ||
| declare function createTheme(name: string, config: ThemeConfig, scopeId?: string, layerContext?: ThemeEmitLayerContext): ThemeSurface; | ||
| declare function createTheme(name: string, config: ThemeConfig, scopeId?: string, layerContext?: ThemeEmitLayerContext, naming?: ThemeTokenNaming): ThemeSurface; | ||
| /** | ||
@@ -180,4 +198,10 @@ * Shorthand: create a theme surface that applies `darkOverrides` under | ||
| */ | ||
| declare function createDarkMode(name: string, darkOverrides: ThemeOverrides, scopeId?: string, layerContext?: ThemeEmitLayerContext): ThemeSurface; | ||
| declare function createDarkMode(name: string, darkOverrides: ThemeOverrides, scopeId?: string, layerContext?: ThemeEmitLayerContext, naming?: ThemeTokenNaming): ThemeSurface; | ||
| /** | ||
| * Read scalar leaf values from a `tokens.create()` ref (e.g. media query conditions). | ||
| * Returns literal strings stored at create time, not `var(--…)` references. | ||
| */ | ||
| declare function getTokenLeafValues(ref: CreatedTokenRef<TokenValues, string>): Record<string, string>; | ||
| type CreateTokensOptions = { | ||
@@ -190,2 +214,7 @@ /** | ||
| /** | ||
| * Default template for emitted `--*` custom property names. Per-namespace override: | ||
| * `tokens.create('color', values, { nameTemplate })`. | ||
| */ | ||
| nameTemplate?: TokenNameTemplate; | ||
| /** | ||
| * When set with **`tokenLayer`**, `:root` custom properties and theme surfaces are wrapped in | ||
@@ -204,9 +233,14 @@ * `@layer tokenLayer { … }`, and a matching `@layer …;` order preamble is registered. | ||
| */ | ||
| type TokensApi = { | ||
| type TokensApi<R extends TokenRegistry = Record<string, never>> = { | ||
| /** Same `scopeId` passed to `createTokens`, if any. */ | ||
| readonly scopeId: string | undefined; | ||
| create: <T extends TokenValues>(namespace: string, values: T, options?: { | ||
| create: <T extends TokenValues, N extends string>(namespace: N, values: T, options?: { | ||
| layer?: string; | ||
| }) => TokenRef<T>; | ||
| use: <T extends TokenValues = TokenValues>(namespace: string) => TokenRef<T>; | ||
| nameTemplate?: TokenNameTemplate; | ||
| }) => CreatedTokenRef<T, N>; | ||
| use: { | ||
| <T extends TokenValues, N extends string>(ref: CreatedTokenRef<T, N>): TokenRef<T>; | ||
| <N extends keyof R & string>(namespace: N): TokenRef<R[N]>; | ||
| <T extends TokenValues = TokenValues>(namespace: string): TokenRef<T>; | ||
| }; | ||
| createTheme: (name: string, config: ThemeConfig) => ThemeSurface; | ||
@@ -229,3 +263,3 @@ createDarkMode: (name: string, darkOverrides: ThemeOverrides) => ThemeSurface; | ||
| */ | ||
| declare function createTokens(options?: CreateTokensOptions): TokensApi; | ||
| declare function createTokens<R extends TokenRegistry = Record<string, never>>(options?: CreateTokensOptions): TokensApi<R>; | ||
@@ -237,15 +271,49 @@ /** | ||
| * - `semantic` — readable names like `button-base`, `button-intent-primary` (default). | ||
| * With `scopeId` set, names are prefixed with the sanitized scope: `my-ui-button-base`. | ||
| * - `hashed` — stable hash from namespace, variant segment, and declarations, with a short namespace slug for debugging. | ||
| * - `atomic` — hash-only names (shortest); same collision properties as `hashed` when `scopeId` differs. | ||
| * - `compact` — hash-only names (shortest) for whole style objects; same collision properties as `hashed` when `scopeId` differs. | ||
| * - `atomic` — one class per CSS declaration; identical declarations dedupe across the codebase. | ||
| * - `attribute` — dimensioned `styles.component()` variants compile to `&[data-{dimension}="{option}"]` | ||
| * selectors under one base class instead of discrete classes; the call returns | ||
| * `{ className, attrs, props }`. See `specs/attribute-driven-variants.md`. Not supported for | ||
| * `slots` or flat configs — `styles.class()` and flat configs behave like `semantic`. | ||
| * - `bem` — dimensioned/slot `styles.component()` variants compile to BEM modifier classes | ||
| * (`block--modifier`, `block__element--modifier`); the base/root class drops the `-base` suffix. | ||
| * See `specs/bem-variant-mode.md`. `styles.class()` and flat configs behave like `semantic`. | ||
| * - `template` — like `bem`, but the block/element/modifier class name is decided by a | ||
| * user-supplied `classNameTemplate: (ctx) => string` instead of a fixed convention. | ||
| * `mode: 'bem'` is itself implemented as a built-in preset of this same mechanism. See | ||
| * `specs/classname-template-mode.md`. `styles.class()` and flat configs behave like `semantic`. | ||
| */ | ||
| type ClassNamingMode = 'semantic' | 'hashed' | 'atomic'; | ||
| type ClassNamingMode = 'semantic' | 'hashed' | 'compact' | 'atomic' | 'attribute' | 'bem' | 'template'; | ||
| /** | ||
| * Passed to `classNameTemplate` for every base/element/modifier class name a `mode: 'bem'` or | ||
| * `mode: 'template'` dimensioned/slot `styles.component()` call needs to emit. One call per | ||
| * class — `dimension`/`modifier` are both `undefined` when naming a base/block/element class | ||
| * itself, both set when naming a modifier class. | ||
| */ | ||
| type ClassNameContext = { | ||
| /** Sanitized scope prefix from `scopeId` (already includes a trailing `-`), `''` when unscoped. */ | ||
| scope: string; | ||
| /** `styles.component()` namespace, e.g. `'button'`. */ | ||
| namespace: string; | ||
| /** Slot name for slot/multi-slot components (`'root'` is passed as `undefined`, matching BEM's root→block rule); `undefined` for non-slot components. */ | ||
| element: string | undefined; | ||
| /** Variant dimension name, e.g. `'intent'`; `undefined` when naming the base/block/element class itself. */ | ||
| dimension: string | undefined; | ||
| /** Variant option value, e.g. `'primary'`; `undefined` when naming the base/block/element class itself. */ | ||
| modifier: string | undefined; | ||
| }; | ||
| type ClassNameTemplate = (ctx: ClassNameContext) => string; | ||
| type ClassNamingConfig = { | ||
| mode: ClassNamingMode; | ||
| /** Prefix for hashed / atomic output and for `hashClass`. Default `ts`. */ | ||
| /** Prefix for hashed / compact / atomic output and for `hashClass`. Default `ts`. */ | ||
| prefix: string; | ||
| /** | ||
| * Package, app, or per-file id: same logical `styles.component` / `styles.class` name under different | ||
| * scopes produces different classes. In development, re-registering the same scope + component name | ||
| * (e.g. HMR) clears prior rules instead of throwing. Use `fileScopeId(import.meta)` for file-local | ||
| * isolation (CSS Modules–style). | ||
| * scopes produces different classes — in `semantic` mode the sanitized scope is prefixed onto the | ||
| * class name (`my-ui-button-base`); in `hashed`/`compact`/`atomic` mode it is mixed into the hash. This matches | ||
| * how `tokens.create` scopes custom property names. In development, re-registering the same | ||
| * scope + component name (e.g. HMR) clears prior rules instead of throwing. Use | ||
| * `fileScopeId(import.meta)` for file-local isolation (CSS Modules–style). | ||
| */ | ||
@@ -258,2 +326,14 @@ scopeId: string; | ||
| cascadeLayers?: ResolvedCascadeLayers; | ||
| /** | ||
| * Breakpoint names → media query conditions (without `@media` wrapper). | ||
| * Enables `{ base, md, lg }` shorthand on CSS property values. | ||
| */ | ||
| breakpoints?: Record<string, string>; | ||
| /** | ||
| * Required when `mode: 'template'`. Decides the class name for every base/element and | ||
| * modifier class a dimensioned or slot `styles.component()` call emits. Not called for | ||
| * `styles.class()` or flat (non-dimensioned) configs — those stay semantic-style. See | ||
| * `ClassNameContext` and `specs/classname-template-mode.md`. | ||
| */ | ||
| classNameTemplate?: ClassNameTemplate; | ||
| }; | ||
@@ -279,3 +359,19 @@ /** Default naming options used by `createStyles()` when no overrides are passed. */ | ||
| type ScopeOptions = { | ||
| /** Scoping root selector, e.g. `.theme-acme` */ | ||
| root: string; | ||
| /** Optional upper bound for `@scope`, e.g. `.theme-acme` */ | ||
| to?: string; | ||
| /** When `createStyles({ layers })` is used, wrap scoped rules in this layer */ | ||
| layer?: string; | ||
| }; | ||
| /** | ||
| * Emit proximity-correct component overrides via CSS `@scope`. | ||
| * Serializes `overrides` with the same `serializeStyle` path as `styles.class` / | ||
| * `styles.component`, registers rules through `insertRules`, and optionally wraps | ||
| * them in a cascade layer when `opts.layer` is set on a layered styles instance. | ||
| */ | ||
| declare function createScope(classNaming: ClassNamingConfig, opts: ScopeOptions, className: string, overrides: CSSProperties): void; | ||
| /** | ||
| * Type-level `Array.prototype.join(', ')` for tuple literals — used by {@link has}, {@link is}, {@link where} | ||
@@ -494,2 +590,15 @@ * so `[builder(…)]` keys stay **specific template literals** (TypeScript otherwise invents a `string` index | ||
| type BreakpointMap = Record<string, string>; | ||
| type BreakpointsFromTokensConfig = { | ||
| fromTokens: CreatedTokenRef<TokenValues, string>; | ||
| } & Partial<BreakpointMap>; | ||
| type BreakpointsConfig = BreakpointMap | BreakpointsFromTokensConfig; | ||
| declare function resolveBreakpoints(config: BreakpointsConfig | undefined): BreakpointMap | undefined; | ||
| type ResponsiveValue<T extends string | number, B extends BreakpointMap> = T | ({ | ||
| base?: T; | ||
| _?: T; | ||
| } & { | ||
| [K in keyof B]?: T; | ||
| }); | ||
| /** | ||
@@ -499,2 +608,5 @@ * Compose multiple component functions or class strings into one. | ||
| * | ||
| * Variant selections are inferred as the intersection of all composed component | ||
| * functions' accepted selection objects. | ||
| * | ||
| * @example | ||
@@ -509,6 +621,3 @@ * ```ts | ||
| */ | ||
| type AnySelectorFunction = { | ||
| (...args: unknown[]): string; | ||
| }; | ||
| declare function compose(...selectors: Array<AnySelectorFunction | string | false | null | undefined>): AnySelectorFunction; | ||
| declare function compose<const S extends readonly ComposeSelectorInput[]>(...selectors: S): ComposeFn<S>; | ||
| type StylesApi = { | ||
@@ -543,2 +652,7 @@ /** Resolved naming config for this instance (useful for debugging). */ | ||
| readonly where: typeof where; | ||
| /** | ||
| * Register a standalone CSS custom property (optionally with `@property` when `syntax` is set). | ||
| * Returns `{ name, var, toString }` for use in style values and variant overrides. | ||
| */ | ||
| property: (id: string, options?: RegisteredPropertyOptions) => RegisteredPropertyRef; | ||
| class: (name: string, properties: CSSProperties) => string; | ||
@@ -554,2 +668,7 @@ hashClass: (properties: CSSProperties, label?: string) => string; | ||
| compose: typeof compose; | ||
| /** | ||
| * Proximity-correct theme overrides via CSS `@scope` for nested theme regions. | ||
| * Prefer component-scoped CSS custom properties (Tier 1) when possible; see theming docs. | ||
| */ | ||
| scope: (opts: ScopeOptions, className: string, overrides: CSSProperties) => void; | ||
| }; | ||
@@ -563,2 +682,7 @@ /** Options argument for styles when `createStyles({ layers })` is used. */ | ||
| /** | ||
| * Breakpoint names mapped to media query conditions (without `@media` wrapper). | ||
| * Enables responsive object values like `{ base: '8px', md: '16px' }` on CSS properties. | ||
| */ | ||
| breakpoints?: BreakpointsConfig; | ||
| /** | ||
| * Only applies when using `createTokens` / `createTypeStyles` for `:root` and theme CSS. | ||
@@ -586,3 +710,6 @@ * Ignored by `createStyles` alone (passing it here avoids repeating the key at the factory). | ||
| }; | ||
| type StylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApi<U>, 'class' | 'hashClass' | 'component'> & { | ||
| type StylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApi<U>, 'class' | 'hashClass' | 'component' | 'scope'> & { | ||
| scope: (opts: ScopeOptions & { | ||
| layer?: L; | ||
| }, className: string, overrides: CSSPropertiesWithUtils<U>) => void; | ||
| class: (name: string, properties: CSSPropertiesWithUtils<U>, options: LayerOption<L>) => string; | ||
@@ -595,3 +722,6 @@ hashClass: (properties: CSSPropertiesWithUtils<U>, options: LayerOption<L> & { | ||
| }; | ||
| type StylesApiWithLayers<L extends string> = Omit<StylesApi, 'class' | 'hashClass' | 'component' | 'withUtils'> & { | ||
| type StylesApiWithLayers<L extends string> = Omit<StylesApi, 'class' | 'hashClass' | 'component' | 'withUtils' | 'scope'> & { | ||
| scope: (opts: ScopeOptions & { | ||
| layer?: L; | ||
| }, className: string, overrides: CSSProperties) => void; | ||
| class: (name: string, properties: CSSProperties, options: LayerOption<L>) => string; | ||
@@ -604,2 +734,31 @@ hashClass: (properties: CSSProperties, options: LayerOption<L> & { | ||
| }; | ||
| declare function createStyles<const L extends readonly string[], U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer?: L[number]; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApiLayered<U, L[number]>; | ||
| declare function createStyles<U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer?: string; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApiLayered<U, string>; | ||
| declare function createStyles<U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApi<U>; | ||
| declare function createStyles<const L extends readonly string[]>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer?: L[number]; | ||
| }): AttributeStylesApiWithLayers<L[number]>; | ||
| declare function createStyles(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer?: string; | ||
| }): AttributeStylesApiWithLayers<string>; | ||
| declare function createStyles(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| }): AttributeStylesApi; | ||
| /** | ||
@@ -656,3 +815,26 @@ * Create a styles API with its own class naming config (scope, mode, prefix). | ||
| compose: typeof compose; | ||
| scope: (opts: ScopeOptions, className: string, overrides: CSSPropertiesWithUtils<U>) => void; | ||
| }; | ||
| type AttributeComponentFn = { | ||
| <const V extends VariantDefinitions>(namespace: string, config: ComponentConfigInput<V>): ComponentAttrsReturn<V>; | ||
| <const K extends string>(namespace: string, config: FlatComponentConfigInput<K>): FlatComponentReturn<K>; | ||
| }; | ||
| type LayeredAttributeComponentFn<L extends string> = { | ||
| <const V extends VariantDefinitions>(namespace: string, config: ComponentConfigInput<V>, options: LayerOption<L>): ComponentAttrsReturn<V>; | ||
| <const K extends string>(namespace: string, config: FlatComponentConfigInput<K>, options: LayerOption<L>): FlatComponentReturn<K>; | ||
| }; | ||
| type AttributeStylesApi = Omit<StylesApi, 'component' | 'withUtils'> & { | ||
| component: AttributeComponentFn; | ||
| withUtils: <U extends StyleUtils>(utils: U) => AttributeStylesWithUtilsApi<U>; | ||
| }; | ||
| type AttributeStylesApiWithLayers<L extends string> = Omit<StylesApiWithLayers<L>, 'component' | 'withUtils'> & { | ||
| component: LayeredAttributeComponentFn<L>; | ||
| withUtils: <U extends StyleUtils>(utils: U) => AttributeStylesWithUtilsApiLayered<U, L>; | ||
| }; | ||
| type AttributeStylesWithUtilsApi<U extends StyleUtils> = Omit<StylesWithUtilsApi<U>, 'component'> & { | ||
| component: AttributeComponentFn; | ||
| }; | ||
| type AttributeStylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApiLayered<U, L>, 'component'> & { | ||
| component: LayeredAttributeComponentFn<L>; | ||
| }; | ||
@@ -666,2 +848,4 @@ type CreateGlobalOptions = { | ||
| scopeId?: string; | ||
| /** Same breakpoint map as `createStyles({ breakpoints })` for responsive global styles. */ | ||
| breakpoints?: BreakpointsConfig; | ||
| }; | ||
@@ -698,3 +882,5 @@ type CreateGlobalWithLayers = CreateGlobalOptions & { | ||
| type NamingPartial = Partial<Omit<ClassNamingConfig, 'cascadeLayers'>>; | ||
| type NamingPartial = Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| breakpoints?: BreakpointsConfig; | ||
| }; | ||
| type GlobalLayerOption<L extends string = string> = { | ||
@@ -710,4 +896,57 @@ /** | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| utils: U; | ||
| }): { | ||
| styles: AttributeStylesWithUtilsApi<U>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiUnlayered; | ||
| }; | ||
| declare function createTypeStyles<const L extends readonly [string, ...string[]], U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer: L[number]; | ||
| utils: U; | ||
| } & GlobalLayerOption<L[number]>): { | ||
| styles: AttributeStylesWithUtilsApiLayered<U, L[number]>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer: string; | ||
| utils: U; | ||
| } & GlobalLayerOption): { | ||
| styles: AttributeStylesWithUtilsApiLayered<U, string>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| }): { | ||
| styles: AttributeStylesApi; | ||
| tokens: TokensApi; | ||
| global: GlobalApiUnlayered; | ||
| }; | ||
| declare function createTypeStyles<const L extends readonly [string, ...string[]]>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer: L[number]; | ||
| } & GlobalLayerOption<L[number]>): { | ||
| styles: AttributeStylesApiWithLayers<L[number]>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer: string; | ||
| } & GlobalLayerOption): { | ||
| styles: AttributeStylesApiWithLayers<string>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| utils: U; | ||
| }): { | ||
| styles: StylesWithUtilsApi<U>; | ||
@@ -791,135 +1030,2 @@ tokens: TokensApi; | ||
| /** | ||
| * Type-safe helpers for CSS color functions. | ||
| * | ||
| * Each function returns a plain CSS string — no runtime color math. | ||
| * Works naturally with token references since tokens are strings too. | ||
| */ | ||
| type ColorValue = string | number; | ||
| /** Color spaces supported by color-mix(). */ | ||
| type ColorMixSpace = 'srgb' | 'srgb-linear' | 'display-p3' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020' | 'lab' | 'oklab' | 'xyz' | 'xyz-d50' | 'xyz-d65' | 'hsl' | 'hwb' | 'lch' | 'oklch'; | ||
| /** | ||
| * `rgb(r g b)` or `rgb(r g b / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.rgb(0, 102, 255, 0.5) // "rgb(0 102 255 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hsl(h s l)` or `hsl(h s l / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hsl(220, '100%', '50%') // "hsl(220 100% 50%)" | ||
| * color.hsl(220, '100%', '50%', 0.8) // "hsl(220 100% 50% / 0.8)" | ||
| * ``` | ||
| */ | ||
| declare function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklch(L C h)` or `oklch(L C h / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.oklch(0.7, 0.15, 250, 0.5) // "oklch(0.7 0.15 250 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklab(L a b)` or `oklab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklab(0.7, -0.1, -0.1) // "oklab(0.7 -0.1 -0.1)" | ||
| * color.oklab(0.7, -0.1, -0.1, 0.5) // "oklab(0.7 -0.1 -0.1 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lab(L a b)` or `lab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lab('50%', 40, -20) // "lab(50% 40 -20)" | ||
| * ``` | ||
| */ | ||
| declare function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lch(L C h)` or `lch(L C h / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lch('50%', 80, 250) // "lch(50% 80 250)" | ||
| * ``` | ||
| */ | ||
| declare function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hwb(h w b)` or `hwb(h w b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hwb(220, '10%', '0%') // "hwb(220 10% 0%)" | ||
| * ``` | ||
| */ | ||
| declare function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `color-mix(in colorspace, color1 p1%, color2 p2%)` | ||
| * | ||
| * Mixes two colors in the given color space. Percentages are optional. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.mix('red', 'blue') // "color-mix(in srgb, red, blue)" | ||
| * color.mix('red', 'blue', 30) // "color-mix(in srgb, red 30%, blue)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.mix('red', 'blue', 50, 'oklch') // "color-mix(in oklch, red 50%, blue)" | ||
| * ``` | ||
| */ | ||
| declare function mix(color1: string, color2: string, percentage?: number, colorSpace?: ColorMixSpace): string; | ||
| /** | ||
| * `light-dark(lightColor, darkColor)` | ||
| * | ||
| * Uses the `light-dark()` CSS function that resolves based on | ||
| * the computed `color-scheme` of the element. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * color.lightDark(theme.textLight, theme.textDark) // "light-dark(var(--theme-textLight), var(--theme-textDark))" | ||
| * ``` | ||
| */ | ||
| declare function lightDark(lightColor: string, darkColor: string): string; | ||
| /** | ||
| * Adjust the alpha/opacity of any color using `color-mix()`. | ||
| * | ||
| * This is a common pattern: mixing a color with transparent to change opacity. | ||
| * Works with any color value including token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.alpha('red', 0.5) // "color-mix(in srgb, red 50%, transparent)" | ||
| * color.alpha(theme.primary, 0.2) // "color-mix(in srgb, var(--theme-primary) 20%, transparent)" | ||
| * color.alpha('#0066ff', 0.8, 'oklch') // "color-mix(in oklch, #0066ff 80%, transparent)" | ||
| * ``` | ||
| */ | ||
| declare function alpha(colorValue: string, opacity: number, colorSpace?: ColorMixSpace): string; | ||
| type colorFns_ColorMixSpace = ColorMixSpace; | ||
| declare const colorFns_alpha: typeof alpha; | ||
| declare const colorFns_hsl: typeof hsl; | ||
| declare const colorFns_hwb: typeof hwb; | ||
| declare const colorFns_lab: typeof lab; | ||
| declare const colorFns_lch: typeof lch; | ||
| declare const colorFns_lightDark: typeof lightDark; | ||
| declare const colorFns_mix: typeof mix; | ||
| declare const colorFns_oklab: typeof oklab; | ||
| declare const colorFns_oklch: typeof oklch; | ||
| declare const colorFns_rgb: typeof rgb; | ||
| declare namespace colorFns { | ||
| export { type colorFns_ColorMixSpace as ColorMixSpace, colorFns_alpha as alpha, colorFns_hsl as hsl, colorFns_hwb as hwb, colorFns_lab as lab, colorFns_lch as lch, colorFns_lightDark as lightDark, colorFns_mix as mix, colorFns_oklab as oklab, colorFns_oklch as oklch, colorFns_rgb as rgb }; | ||
| } | ||
| /** | ||
| * Apply styles to an arbitrary CSS selector. | ||
@@ -1000,8 +1106,12 @@ * | ||
| * | ||
| * Returns a `var(--ts-N)` string that can be used anywhere a CSS value is | ||
| * Returns a `var(--ts-…)` string that can be used anywhere a CSS value is | ||
| * accepted. Use assignVars() to set its value per element via inline styles. | ||
| * | ||
| * Pass a debug name to get readable custom property names in DevTools | ||
| * (e.g. `createVar('cardBg')` → `var(--ts-cardbg)`). Anonymous vars use | ||
| * numeric ids (`--ts-1`, `--ts-2`, …). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const cardBg = createVar(); | ||
| * const cardBg = createVar('cardBg'); | ||
| * | ||
@@ -1016,3 +1126,3 @@ * const card = styles.component('card', { | ||
| */ | ||
| declare function createVar(): CSSVarRef; | ||
| declare function createVar(name?: string, fallback?: string): CSSVarRef; | ||
| /** | ||
@@ -1027,3 +1137,3 @@ * Build a CSS custom property assignment map from var refs to values. | ||
| * assignVars({ [cardBg]: '#ff0099' }) | ||
| * // → { '--ts-1': '#ff0099' } | ||
| * // → { '--ts-cardbg': '#ff0099' } | ||
| * ``` | ||
@@ -1034,2 +1144,10 @@ */ | ||
| /** | ||
| * Anything that coerces to a class string via `toString()`/`Symbol.toPrimitive` — covers | ||
| * `ThemeSurface` (`tokens.createTheme(...)`) and `ComponentAttrsResult` | ||
| * (`createStyles({ mode: 'attribute' })`) alongside plain strings. | ||
| */ | ||
| type Stringable = { | ||
| toString(): string; | ||
| }; | ||
| /** | ||
| * Join class name parts, filtering out falsy values. | ||
@@ -1049,5 +1167,8 @@ * | ||
| * // => "button-base button-primary extra" | ||
| * | ||
| * cx(attrButton({ variant: 'primary' }), 'extra'); | ||
| * // => "button-base extra" — ComponentAttrsResult coerces via toString() | ||
| * ``` | ||
| */ | ||
| declare function cx(...parts: Array<string | undefined | null | false | 0 | ''>): string; | ||
| declare function cx(...parts: Array<string | Stringable | undefined | null | false | 0 | ''>): string; | ||
@@ -1104,2 +1225,6 @@ /** | ||
| type SerializeStyleOptions = { | ||
| breakpoints?: BreakpointMap; | ||
| }; | ||
| /** | ||
@@ -1158,3 +1283,3 @@ * Default style API (semantic class names, empty `scopeId`). Prefer `createStyles({ scopeId, mode, prefix })` | ||
| */ | ||
| declare const tokens: TokensApi; | ||
| declare const tokens: TokensApi<Record<string, never>>; | ||
| /** | ||
@@ -1178,19 +1303,3 @@ * Keyframe animation API. | ||
| }; | ||
| /** | ||
| * Type-safe CSS color function helpers. | ||
| * | ||
| * Each function returns a plain CSS color string — no runtime color math. | ||
| * Composes naturally with token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.alpha(theme.primary, 0.5) // "color-mix(in srgb, var(--theme-primary) 50%, transparent)" | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * ``` | ||
| */ | ||
| declare const color: typeof colorFns; | ||
| export { CSSProperties, CSSPropertiesWithUtils, CSSVarRef, type CascadeLayersInput, type CascadeLayersObjectInput, type ClassNamingConfig, type ClassNamingMode, type ColorMixSpace, ComponentConfigInput, ComponentReturn, type ContainerNameRef, type ContainerObjectKey, type ContainerQueryFeatures, type ContainerQueryKey, type ContainerQueryObject, type CreateContainerRefOptions, type CreateStylesInput, type CreateTokensOptions, type CssMathValue, FlatComponentConfigInput, FlatComponentReturn, FontFaceProps, type GlobalApiLayered, type GlobalApiUnlayered, GlobalStyleTuple, type HasNestedKey, type IsNestedKey, type IsPseudoArg, type LayerOption, type LayeredComponentFn, MultiSlotConfigInput, type ResolvedCascadeLayers, SlotComponentConfigInput, SlotComponentFunction, SlotVariantDefinitions, StyleUtils, type StylesApi, type StylesApiWithLayers, ThemeCondition, ThemeConditionAnd, ThemeConditionAttr, ThemeConditionClass, ThemeConditionMedia, ThemeConditionOr, ThemeConditionSelector, ThemeConfig, type ThemeEmitLayerContext, ThemeModeDefinition, ThemeOverrides, ThemeSurface, TokenRef, TokenValues, type TokensApi, VariantDefinitions, type WhereNestedKey, assignVars, atRuleBlock, calc, clamp, color, colorMode, container, content, createContainerRef, createDarkMode, createGlobal, createStyles, createTheme, createTokens, createTypeStyles, createVar, cx, defaultClassNamingConfig, fileScopeId, global, has, is, keyframes, mergeClassNaming, scopedTokenNamespace, styles, tokens, when, where }; | ||
| export { type AttributeComponentFn, type AttributeStylesApi, type AttributeStylesApiWithLayers, type BreakpointMap, type BreakpointsConfig, CSSProperties, CSSPropertiesWithUtils, CSSVarRef, type CascadeLayersInput, type CascadeLayersObjectInput, type ClassNameContext, type ClassNameTemplate, type ClassNamingConfig, type ClassNamingMode, ComponentAttrsReturn, ComponentConfigInput, ComponentReturn, ComposeFn, ComposeSelectorInput, type ContainerNameRef, type ContainerObjectKey, type ContainerQueryFeatures, type ContainerQueryKey, type ContainerQueryObject, type CreateContainerRefOptions, type CreateStylesInput, type CreateTokensOptions, CreatedTokenRef, type CssMathValue, FlatComponentConfigInput, FlatComponentReturn, FontFaceProps, type GlobalApiLayered, type GlobalApiUnlayered, GlobalStyleTuple, type HasNestedKey, type IsNestedKey, type IsPseudoArg, type LayerOption, type LayeredAttributeComponentFn, type LayeredComponentFn, MultiSlotConfigInput, RegisteredPropertyOptions, RegisteredPropertyRef, type ResolvedCascadeLayers, type ResponsiveValue, type ScopeOptions, type SerializeStyleOptions, SlotComponentConfigInput, SlotComponentFunction, SlotVariantDefinitions, StyleUtils, type StylesApi, type StylesApiWithLayers, ThemeCondition, ThemeConditionAnd, ThemeConditionAttr, ThemeConditionClass, ThemeConditionMedia, ThemeConditionOr, ThemeConditionSelector, ThemeConfig, type ThemeEmitLayerContext, ThemeModeDefinition, ThemeOverrides, ThemeSurface, TokenRef, TokenRegistry, TokenValues, type TokensApi, VariantDefinitions, type WhereNestedKey, assignVars, atRuleBlock, calc, clamp, colorMode, container, content, createContainerRef, createDarkMode, createGlobal, createScope, createStyles, createTheme, createTokens, createTypeStyles, createVar, cx, defaultClassNamingConfig, fileScopeId, getTokenLeafValues, global, has, is, keyframes, mergeClassNaming, resolveBreakpoints, scopedTokenNamespace, styles, tokens, when, where }; |
+291
-182
@@ -1,6 +0,23 @@ | ||
| import { T as ThemeConditionMedia, a as ThemeConditionAttr, b as ThemeConditionClass, c as ThemeConditionSelector, d as ThemeCondition, e as ThemeConditionAnd, f as ThemeConditionOr, g as ThemeOverrides, h as ThemeModeDefinition, i as ThemeSurface, j as ThemeConfig, k as TokenValues, l as TokenRef, C as CSSProperties, S as StyleUtils, V as VariantDefinitions, m as ComponentConfigInput, n as ComponentReturn, F as FlatComponentConfigInput, o as FlatComponentReturn, p as SlotVariantDefinitions, q as SlotComponentConfigInput, r as SlotComponentFunction, M as MultiSlotConfigInput, s as MultiSlotReturn, t as CSSPropertiesWithUtils, G as GlobalStyleTuple, u as FontFaceProps, v as CSSVarRef } from './global-style-tuple-eE4ncVOt.js'; | ||
| export { w as CSSValue, x as ComponentConfig, y as ComponentConfigContext, z as ComponentInternalVarRef, A as ComponentSelections, B as ComponentVarDefinitions, D as ComponentVarDescriptor, E as ComponentVarNode, H as ComponentVarOptions, I as ComponentVarRefTree, J as ComponentVariants, K as DeepPartialTokenValues, L as FlatComponentConfig, N as FlatComponentSelections, O as FlatTokenEntry, P as FontFaceSrc, Q as KeyframeStops, R as SlotComponentConfig, U as SlotStyles, W as StyleDefinitions, X as StyleDefinitionsWithUtils, Y as ThemeConditionNot, Z as VariantOptionStyle, _ as flattenTokenEntries } from './global-style-tuple-eE4ncVOt.js'; | ||
| export { e as ensureDocumentStylesAttached, f as flushSync, g as getRegisteredCss, i as insertRules, r as reset } from './hmr-D5sXuQgK.js'; | ||
| import { T as ThemeConditionMedia, a as ThemeConditionAttr, b as ThemeConditionClass, c as ThemeConditionSelector, d as ThemeCondition, e as ThemeConditionAnd, f as ThemeConditionOr, g as ThemeOverrides, h as ThemeModeDefinition, i as ThemeSurface, j as ThemeConfig, k as TokenRegistry, l as TokenValues, m as CreatedTokenRef, n as TokenRef, C as CSSProperties, V as VariantDefinitions, o as ComponentConfigInput, p as ComponentAttrsReturn, F as FlatComponentConfigInput, q as FlatComponentReturn, R as RegisteredPropertyOptions, r as RegisteredPropertyRef, s as ComponentReturn, S as SlotVariantDefinitions, t as SlotComponentConfigInput, u as SlotComponentFunction, M as MultiSlotConfigInput, v as MultiSlotReturn, w as StyleUtils, x as CSSPropertiesWithUtils, y as ComposeSelectorInput, z as ComposeFn, G as GlobalStyleTuple, A as FontFaceProps, B as CSSVarRef } from './global-style-tuple-DPvH8JpJ.js'; | ||
| export { D as CSSValue, E as ComponentAttrsResult, H as ComponentConfig, I as ComponentConfigContext, J as ComponentInternalVarRef, K as ComponentSelections, L as ComponentVarDefinitions, N as ComponentVarDescriptor, O as ComponentVarNode, P as ComponentVarOptions, Q as ComponentVarRefTree, U as ComponentVariants, W as DeepPartialTokenValues, X as FlatComponentConfig, Y as FlatComponentSelections, Z as FlatTokenEntry, _ as FlatTokenPathEntry, $ as FontFaceSrc, a0 as InferTokenNamespace, a1 as InferTokenValues, a2 as KeyframeStops, a3 as MergeComposeSelections, a4 as SlotComponentConfig, a5 as SlotStyles, a6 as StyleDefinitions, a7 as StyleDefinitionsWithUtils, a8 as ThemeConditionNot, a9 as TokenDescriptor, aa as VariantOptionStyle, ab as flattenTokenEntries, ac as flattenTokenPaths, ad as isTokenDescriptor } from './global-style-tuple-DPvH8JpJ.js'; | ||
| export { e as ensureDocumentStylesAttached, f as flushSync, g as getRegisteredCss, i as insertRules, r as reset, s as subscribeRegisteredCss } from './hmr-DhHxThox.js'; | ||
| import 'csstype'; | ||
| type TokenNameContext = { | ||
| /** Raw `scopeId` from `createTokens`, trimmed; undefined when unscoped. */ | ||
| scopeId: string | undefined; | ||
| /** Sanitized scope segment used in default naming (`app` from `@acme/ui`). */ | ||
| scope: string; | ||
| /** First argument to `tokens.create('color', …)`. */ | ||
| namespace: string; | ||
| /** Flattened leaf path with default `-` join (`brand-primary`). */ | ||
| path: string; | ||
| /** Path segments before joining (`['brand', 'primary']`). */ | ||
| segments: readonly string[]; | ||
| }; | ||
| type TokenNameTemplate = (ctx: TokenNameContext) => string; | ||
| type ThemeTokenNaming = { | ||
| resolveName(namespace: string, path: string, segments: readonly string[]): string; | ||
| }; | ||
| /** | ||
@@ -35,6 +52,6 @@ * Declare cascade layer order and optionally prepend framework layer names | ||
| declare function condAttr(name: string, value: string, opts: { | ||
| scope: 'self' | 'ancestor'; | ||
| scope: 'self' | 'ancestor' | 'descendant'; | ||
| }): ThemeConditionAttr; | ||
| declare function condClassName(name: string, opts: { | ||
| scope: 'self' | 'ancestor'; | ||
| scope: 'self' | 'ancestor' | 'descendant'; | ||
| }): ThemeConditionClass; | ||
@@ -52,3 +69,3 @@ declare function condSelector(selector: string): ThemeConditionSelector; | ||
| * | ||
| * Not supported: `when.selector`, `when.or`, combined `@media` + selector, or both ancestor and self selector parts on the same branch. Those log a dev warning and emit no rule. | ||
| * Not supported: `when.selector`, `when.or`, `scope: 'descendant'` conditions (a descendant relationship can't collapse into a single `:not()` compound selector), combined `@media` + selector, or both ancestor and self selector parts on the same branch. Those log a dev warning and emit no rule. | ||
| */ | ||
@@ -64,2 +81,3 @@ declare function condNot(condition: ThemeCondition): ThemeCondition; | ||
| * tokens.when.attr('data-color-mode', 'dark', { scope: 'ancestor' }) | ||
| * tokens.when.attr('data-surface', 'dark', { scope: 'descendant' }) | ||
| * tokens.when.or(tokens.when.prefersDark, tokens.when.attr('data-mode', 'dark', { scope: 'self' })) | ||
@@ -167,3 +185,3 @@ * ``` | ||
| */ | ||
| declare function createTheme(name: string, config: ThemeConfig, scopeId?: string, layerContext?: ThemeEmitLayerContext): ThemeSurface; | ||
| declare function createTheme(name: string, config: ThemeConfig, scopeId?: string, layerContext?: ThemeEmitLayerContext, naming?: ThemeTokenNaming): ThemeSurface; | ||
| /** | ||
@@ -180,4 +198,10 @@ * Shorthand: create a theme surface that applies `darkOverrides` under | ||
| */ | ||
| declare function createDarkMode(name: string, darkOverrides: ThemeOverrides, scopeId?: string, layerContext?: ThemeEmitLayerContext): ThemeSurface; | ||
| declare function createDarkMode(name: string, darkOverrides: ThemeOverrides, scopeId?: string, layerContext?: ThemeEmitLayerContext, naming?: ThemeTokenNaming): ThemeSurface; | ||
| /** | ||
| * Read scalar leaf values from a `tokens.create()` ref (e.g. media query conditions). | ||
| * Returns literal strings stored at create time, not `var(--…)` references. | ||
| */ | ||
| declare function getTokenLeafValues(ref: CreatedTokenRef<TokenValues, string>): Record<string, string>; | ||
| type CreateTokensOptions = { | ||
@@ -190,2 +214,7 @@ /** | ||
| /** | ||
| * Default template for emitted `--*` custom property names. Per-namespace override: | ||
| * `tokens.create('color', values, { nameTemplate })`. | ||
| */ | ||
| nameTemplate?: TokenNameTemplate; | ||
| /** | ||
| * When set with **`tokenLayer`**, `:root` custom properties and theme surfaces are wrapped in | ||
@@ -204,9 +233,14 @@ * `@layer tokenLayer { … }`, and a matching `@layer …;` order preamble is registered. | ||
| */ | ||
| type TokensApi = { | ||
| type TokensApi<R extends TokenRegistry = Record<string, never>> = { | ||
| /** Same `scopeId` passed to `createTokens`, if any. */ | ||
| readonly scopeId: string | undefined; | ||
| create: <T extends TokenValues>(namespace: string, values: T, options?: { | ||
| create: <T extends TokenValues, N extends string>(namespace: N, values: T, options?: { | ||
| layer?: string; | ||
| }) => TokenRef<T>; | ||
| use: <T extends TokenValues = TokenValues>(namespace: string) => TokenRef<T>; | ||
| nameTemplate?: TokenNameTemplate; | ||
| }) => CreatedTokenRef<T, N>; | ||
| use: { | ||
| <T extends TokenValues, N extends string>(ref: CreatedTokenRef<T, N>): TokenRef<T>; | ||
| <N extends keyof R & string>(namespace: N): TokenRef<R[N]>; | ||
| <T extends TokenValues = TokenValues>(namespace: string): TokenRef<T>; | ||
| }; | ||
| createTheme: (name: string, config: ThemeConfig) => ThemeSurface; | ||
@@ -229,3 +263,3 @@ createDarkMode: (name: string, darkOverrides: ThemeOverrides) => ThemeSurface; | ||
| */ | ||
| declare function createTokens(options?: CreateTokensOptions): TokensApi; | ||
| declare function createTokens<R extends TokenRegistry = Record<string, never>>(options?: CreateTokensOptions): TokensApi<R>; | ||
@@ -237,15 +271,49 @@ /** | ||
| * - `semantic` — readable names like `button-base`, `button-intent-primary` (default). | ||
| * With `scopeId` set, names are prefixed with the sanitized scope: `my-ui-button-base`. | ||
| * - `hashed` — stable hash from namespace, variant segment, and declarations, with a short namespace slug for debugging. | ||
| * - `atomic` — hash-only names (shortest); same collision properties as `hashed` when `scopeId` differs. | ||
| * - `compact` — hash-only names (shortest) for whole style objects; same collision properties as `hashed` when `scopeId` differs. | ||
| * - `atomic` — one class per CSS declaration; identical declarations dedupe across the codebase. | ||
| * - `attribute` — dimensioned `styles.component()` variants compile to `&[data-{dimension}="{option}"]` | ||
| * selectors under one base class instead of discrete classes; the call returns | ||
| * `{ className, attrs, props }`. See `specs/attribute-driven-variants.md`. Not supported for | ||
| * `slots` or flat configs — `styles.class()` and flat configs behave like `semantic`. | ||
| * - `bem` — dimensioned/slot `styles.component()` variants compile to BEM modifier classes | ||
| * (`block--modifier`, `block__element--modifier`); the base/root class drops the `-base` suffix. | ||
| * See `specs/bem-variant-mode.md`. `styles.class()` and flat configs behave like `semantic`. | ||
| * - `template` — like `bem`, but the block/element/modifier class name is decided by a | ||
| * user-supplied `classNameTemplate: (ctx) => string` instead of a fixed convention. | ||
| * `mode: 'bem'` is itself implemented as a built-in preset of this same mechanism. See | ||
| * `specs/classname-template-mode.md`. `styles.class()` and flat configs behave like `semantic`. | ||
| */ | ||
| type ClassNamingMode = 'semantic' | 'hashed' | 'atomic'; | ||
| type ClassNamingMode = 'semantic' | 'hashed' | 'compact' | 'atomic' | 'attribute' | 'bem' | 'template'; | ||
| /** | ||
| * Passed to `classNameTemplate` for every base/element/modifier class name a `mode: 'bem'` or | ||
| * `mode: 'template'` dimensioned/slot `styles.component()` call needs to emit. One call per | ||
| * class — `dimension`/`modifier` are both `undefined` when naming a base/block/element class | ||
| * itself, both set when naming a modifier class. | ||
| */ | ||
| type ClassNameContext = { | ||
| /** Sanitized scope prefix from `scopeId` (already includes a trailing `-`), `''` when unscoped. */ | ||
| scope: string; | ||
| /** `styles.component()` namespace, e.g. `'button'`. */ | ||
| namespace: string; | ||
| /** Slot name for slot/multi-slot components (`'root'` is passed as `undefined`, matching BEM's root→block rule); `undefined` for non-slot components. */ | ||
| element: string | undefined; | ||
| /** Variant dimension name, e.g. `'intent'`; `undefined` when naming the base/block/element class itself. */ | ||
| dimension: string | undefined; | ||
| /** Variant option value, e.g. `'primary'`; `undefined` when naming the base/block/element class itself. */ | ||
| modifier: string | undefined; | ||
| }; | ||
| type ClassNameTemplate = (ctx: ClassNameContext) => string; | ||
| type ClassNamingConfig = { | ||
| mode: ClassNamingMode; | ||
| /** Prefix for hashed / atomic output and for `hashClass`. Default `ts`. */ | ||
| /** Prefix for hashed / compact / atomic output and for `hashClass`. Default `ts`. */ | ||
| prefix: string; | ||
| /** | ||
| * Package, app, or per-file id: same logical `styles.component` / `styles.class` name under different | ||
| * scopes produces different classes. In development, re-registering the same scope + component name | ||
| * (e.g. HMR) clears prior rules instead of throwing. Use `fileScopeId(import.meta)` for file-local | ||
| * isolation (CSS Modules–style). | ||
| * scopes produces different classes — in `semantic` mode the sanitized scope is prefixed onto the | ||
| * class name (`my-ui-button-base`); in `hashed`/`compact`/`atomic` mode it is mixed into the hash. This matches | ||
| * how `tokens.create` scopes custom property names. In development, re-registering the same | ||
| * scope + component name (e.g. HMR) clears prior rules instead of throwing. Use | ||
| * `fileScopeId(import.meta)` for file-local isolation (CSS Modules–style). | ||
| */ | ||
@@ -258,2 +326,14 @@ scopeId: string; | ||
| cascadeLayers?: ResolvedCascadeLayers; | ||
| /** | ||
| * Breakpoint names → media query conditions (without `@media` wrapper). | ||
| * Enables `{ base, md, lg }` shorthand on CSS property values. | ||
| */ | ||
| breakpoints?: Record<string, string>; | ||
| /** | ||
| * Required when `mode: 'template'`. Decides the class name for every base/element and | ||
| * modifier class a dimensioned or slot `styles.component()` call emits. Not called for | ||
| * `styles.class()` or flat (non-dimensioned) configs — those stay semantic-style. See | ||
| * `ClassNameContext` and `specs/classname-template-mode.md`. | ||
| */ | ||
| classNameTemplate?: ClassNameTemplate; | ||
| }; | ||
@@ -279,3 +359,19 @@ /** Default naming options used by `createStyles()` when no overrides are passed. */ | ||
| type ScopeOptions = { | ||
| /** Scoping root selector, e.g. `.theme-acme` */ | ||
| root: string; | ||
| /** Optional upper bound for `@scope`, e.g. `.theme-acme` */ | ||
| to?: string; | ||
| /** When `createStyles({ layers })` is used, wrap scoped rules in this layer */ | ||
| layer?: string; | ||
| }; | ||
| /** | ||
| * Emit proximity-correct component overrides via CSS `@scope`. | ||
| * Serializes `overrides` with the same `serializeStyle` path as `styles.class` / | ||
| * `styles.component`, registers rules through `insertRules`, and optionally wraps | ||
| * them in a cascade layer when `opts.layer` is set on a layered styles instance. | ||
| */ | ||
| declare function createScope(classNaming: ClassNamingConfig, opts: ScopeOptions, className: string, overrides: CSSProperties): void; | ||
| /** | ||
| * Type-level `Array.prototype.join(', ')` for tuple literals — used by {@link has}, {@link is}, {@link where} | ||
@@ -494,2 +590,15 @@ * so `[builder(…)]` keys stay **specific template literals** (TypeScript otherwise invents a `string` index | ||
| type BreakpointMap = Record<string, string>; | ||
| type BreakpointsFromTokensConfig = { | ||
| fromTokens: CreatedTokenRef<TokenValues, string>; | ||
| } & Partial<BreakpointMap>; | ||
| type BreakpointsConfig = BreakpointMap | BreakpointsFromTokensConfig; | ||
| declare function resolveBreakpoints(config: BreakpointsConfig | undefined): BreakpointMap | undefined; | ||
| type ResponsiveValue<T extends string | number, B extends BreakpointMap> = T | ({ | ||
| base?: T; | ||
| _?: T; | ||
| } & { | ||
| [K in keyof B]?: T; | ||
| }); | ||
| /** | ||
@@ -499,2 +608,5 @@ * Compose multiple component functions or class strings into one. | ||
| * | ||
| * Variant selections are inferred as the intersection of all composed component | ||
| * functions' accepted selection objects. | ||
| * | ||
| * @example | ||
@@ -509,6 +621,3 @@ * ```ts | ||
| */ | ||
| type AnySelectorFunction = { | ||
| (...args: unknown[]): string; | ||
| }; | ||
| declare function compose(...selectors: Array<AnySelectorFunction | string | false | null | undefined>): AnySelectorFunction; | ||
| declare function compose<const S extends readonly ComposeSelectorInput[]>(...selectors: S): ComposeFn<S>; | ||
| type StylesApi = { | ||
@@ -543,2 +652,7 @@ /** Resolved naming config for this instance (useful for debugging). */ | ||
| readonly where: typeof where; | ||
| /** | ||
| * Register a standalone CSS custom property (optionally with `@property` when `syntax` is set). | ||
| * Returns `{ name, var, toString }` for use in style values and variant overrides. | ||
| */ | ||
| property: (id: string, options?: RegisteredPropertyOptions) => RegisteredPropertyRef; | ||
| class: (name: string, properties: CSSProperties) => string; | ||
@@ -554,2 +668,7 @@ hashClass: (properties: CSSProperties, label?: string) => string; | ||
| compose: typeof compose; | ||
| /** | ||
| * Proximity-correct theme overrides via CSS `@scope` for nested theme regions. | ||
| * Prefer component-scoped CSS custom properties (Tier 1) when possible; see theming docs. | ||
| */ | ||
| scope: (opts: ScopeOptions, className: string, overrides: CSSProperties) => void; | ||
| }; | ||
@@ -563,2 +682,7 @@ /** Options argument for styles when `createStyles({ layers })` is used. */ | ||
| /** | ||
| * Breakpoint names mapped to media query conditions (without `@media` wrapper). | ||
| * Enables responsive object values like `{ base: '8px', md: '16px' }` on CSS properties. | ||
| */ | ||
| breakpoints?: BreakpointsConfig; | ||
| /** | ||
| * Only applies when using `createTokens` / `createTypeStyles` for `:root` and theme CSS. | ||
@@ -586,3 +710,6 @@ * Ignored by `createStyles` alone (passing it here avoids repeating the key at the factory). | ||
| }; | ||
| type StylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApi<U>, 'class' | 'hashClass' | 'component'> & { | ||
| type StylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApi<U>, 'class' | 'hashClass' | 'component' | 'scope'> & { | ||
| scope: (opts: ScopeOptions & { | ||
| layer?: L; | ||
| }, className: string, overrides: CSSPropertiesWithUtils<U>) => void; | ||
| class: (name: string, properties: CSSPropertiesWithUtils<U>, options: LayerOption<L>) => string; | ||
@@ -595,3 +722,6 @@ hashClass: (properties: CSSPropertiesWithUtils<U>, options: LayerOption<L> & { | ||
| }; | ||
| type StylesApiWithLayers<L extends string> = Omit<StylesApi, 'class' | 'hashClass' | 'component' | 'withUtils'> & { | ||
| type StylesApiWithLayers<L extends string> = Omit<StylesApi, 'class' | 'hashClass' | 'component' | 'withUtils' | 'scope'> & { | ||
| scope: (opts: ScopeOptions & { | ||
| layer?: L; | ||
| }, className: string, overrides: CSSProperties) => void; | ||
| class: (name: string, properties: CSSProperties, options: LayerOption<L>) => string; | ||
@@ -604,2 +734,31 @@ hashClass: (properties: CSSProperties, options: LayerOption<L> & { | ||
| }; | ||
| declare function createStyles<const L extends readonly string[], U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer?: L[number]; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApiLayered<U, L[number]>; | ||
| declare function createStyles<U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer?: string; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApiLayered<U, string>; | ||
| declare function createStyles<U extends StyleUtils>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| utils: U; | ||
| }): AttributeStylesWithUtilsApi<U>; | ||
| declare function createStyles<const L extends readonly string[]>(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer?: L[number]; | ||
| }): AttributeStylesApiWithLayers<L[number]>; | ||
| declare function createStyles(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer?: string; | ||
| }): AttributeStylesApiWithLayers<string>; | ||
| declare function createStyles(options: Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| mode: 'attribute'; | ||
| }): AttributeStylesApi; | ||
| /** | ||
@@ -656,3 +815,26 @@ * Create a styles API with its own class naming config (scope, mode, prefix). | ||
| compose: typeof compose; | ||
| scope: (opts: ScopeOptions, className: string, overrides: CSSPropertiesWithUtils<U>) => void; | ||
| }; | ||
| type AttributeComponentFn = { | ||
| <const V extends VariantDefinitions>(namespace: string, config: ComponentConfigInput<V>): ComponentAttrsReturn<V>; | ||
| <const K extends string>(namespace: string, config: FlatComponentConfigInput<K>): FlatComponentReturn<K>; | ||
| }; | ||
| type LayeredAttributeComponentFn<L extends string> = { | ||
| <const V extends VariantDefinitions>(namespace: string, config: ComponentConfigInput<V>, options: LayerOption<L>): ComponentAttrsReturn<V>; | ||
| <const K extends string>(namespace: string, config: FlatComponentConfigInput<K>, options: LayerOption<L>): FlatComponentReturn<K>; | ||
| }; | ||
| type AttributeStylesApi = Omit<StylesApi, 'component' | 'withUtils'> & { | ||
| component: AttributeComponentFn; | ||
| withUtils: <U extends StyleUtils>(utils: U) => AttributeStylesWithUtilsApi<U>; | ||
| }; | ||
| type AttributeStylesApiWithLayers<L extends string> = Omit<StylesApiWithLayers<L>, 'component' | 'withUtils'> & { | ||
| component: LayeredAttributeComponentFn<L>; | ||
| withUtils: <U extends StyleUtils>(utils: U) => AttributeStylesWithUtilsApiLayered<U, L>; | ||
| }; | ||
| type AttributeStylesWithUtilsApi<U extends StyleUtils> = Omit<StylesWithUtilsApi<U>, 'component'> & { | ||
| component: AttributeComponentFn; | ||
| }; | ||
| type AttributeStylesWithUtilsApiLayered<U extends StyleUtils, L extends string> = Omit<StylesWithUtilsApiLayered<U, L>, 'component'> & { | ||
| component: LayeredAttributeComponentFn<L>; | ||
| }; | ||
@@ -666,2 +848,4 @@ type CreateGlobalOptions = { | ||
| scopeId?: string; | ||
| /** Same breakpoint map as `createStyles({ breakpoints })` for responsive global styles. */ | ||
| breakpoints?: BreakpointsConfig; | ||
| }; | ||
@@ -698,3 +882,5 @@ type CreateGlobalWithLayers = CreateGlobalOptions & { | ||
| type NamingPartial = Partial<Omit<ClassNamingConfig, 'cascadeLayers'>>; | ||
| type NamingPartial = Partial<Omit<ClassNamingConfig, 'cascadeLayers'>> & { | ||
| breakpoints?: BreakpointsConfig; | ||
| }; | ||
| type GlobalLayerOption<L extends string = string> = { | ||
@@ -710,4 +896,57 @@ /** | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| utils: U; | ||
| }): { | ||
| styles: AttributeStylesWithUtilsApi<U>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiUnlayered; | ||
| }; | ||
| declare function createTypeStyles<const L extends readonly [string, ...string[]], U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer: L[number]; | ||
| utils: U; | ||
| } & GlobalLayerOption<L[number]>): { | ||
| styles: AttributeStylesWithUtilsApiLayered<U, L[number]>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer: string; | ||
| utils: U; | ||
| } & GlobalLayerOption): { | ||
| styles: AttributeStylesWithUtilsApiLayered<U, string>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| }): { | ||
| styles: AttributeStylesApi; | ||
| tokens: TokensApi; | ||
| global: GlobalApiUnlayered; | ||
| }; | ||
| declare function createTypeStyles<const L extends readonly [string, ...string[]]>(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: L; | ||
| tokenLayer: L[number]; | ||
| } & GlobalLayerOption<L[number]>): { | ||
| styles: AttributeStylesApiWithLayers<L[number]>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles(options: NamingPartial & { | ||
| mode: 'attribute'; | ||
| layers: CascadeLayersObjectInput; | ||
| tokenLayer: string; | ||
| } & GlobalLayerOption): { | ||
| styles: AttributeStylesApiWithLayers<string>; | ||
| tokens: TokensApi; | ||
| global: GlobalApiLayered; | ||
| }; | ||
| declare function createTypeStyles<U extends StyleUtils>(options: NamingPartial & { | ||
| utils: U; | ||
| }): { | ||
| styles: StylesWithUtilsApi<U>; | ||
@@ -791,135 +1030,2 @@ tokens: TokensApi; | ||
| /** | ||
| * Type-safe helpers for CSS color functions. | ||
| * | ||
| * Each function returns a plain CSS string — no runtime color math. | ||
| * Works naturally with token references since tokens are strings too. | ||
| */ | ||
| type ColorValue = string | number; | ||
| /** Color spaces supported by color-mix(). */ | ||
| type ColorMixSpace = 'srgb' | 'srgb-linear' | 'display-p3' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020' | 'lab' | 'oklab' | 'xyz' | 'xyz-d50' | 'xyz-d65' | 'hsl' | 'hwb' | 'lch' | 'oklch'; | ||
| /** | ||
| * `rgb(r g b)` or `rgb(r g b / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.rgb(0, 102, 255, 0.5) // "rgb(0 102 255 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function rgb(r: ColorValue, g: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hsl(h s l)` or `hsl(h s l / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hsl(220, '100%', '50%') // "hsl(220 100% 50%)" | ||
| * color.hsl(220, '100%', '50%', 0.8) // "hsl(220 100% 50% / 0.8)" | ||
| * ``` | ||
| */ | ||
| declare function hsl(h: ColorValue, s: ColorValue, l: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklch(L C h)` or `oklch(L C h / a)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.oklch(0.7, 0.15, 250, 0.5) // "oklch(0.7 0.15 250 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `oklab(L a b)` or `oklab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.oklab(0.7, -0.1, -0.1) // "oklab(0.7 -0.1 -0.1)" | ||
| * color.oklab(0.7, -0.1, -0.1, 0.5) // "oklab(0.7 -0.1 -0.1 / 0.5)" | ||
| * ``` | ||
| */ | ||
| declare function oklab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lab(L a b)` or `lab(L a b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lab('50%', 40, -20) // "lab(50% 40 -20)" | ||
| * ``` | ||
| */ | ||
| declare function lab(l: ColorValue, a: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `lch(L C h)` or `lch(L C h / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lch('50%', 80, 250) // "lch(50% 80 250)" | ||
| * ``` | ||
| */ | ||
| declare function lch(l: ColorValue, c: ColorValue, h: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `hwb(h w b)` or `hwb(h w b / alpha)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.hwb(220, '10%', '0%') // "hwb(220 10% 0%)" | ||
| * ``` | ||
| */ | ||
| declare function hwb(h: ColorValue, w: ColorValue, b: ColorValue, alpha?: ColorValue): string; | ||
| /** | ||
| * `color-mix(in colorspace, color1 p1%, color2 p2%)` | ||
| * | ||
| * Mixes two colors in the given color space. Percentages are optional. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.mix('red', 'blue') // "color-mix(in srgb, red, blue)" | ||
| * color.mix('red', 'blue', 30) // "color-mix(in srgb, red 30%, blue)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.mix('red', 'blue', 50, 'oklch') // "color-mix(in oklch, red 50%, blue)" | ||
| * ``` | ||
| */ | ||
| declare function mix(color1: string, color2: string, percentage?: number, colorSpace?: ColorMixSpace): string; | ||
| /** | ||
| * `light-dark(lightColor, darkColor)` | ||
| * | ||
| * Uses the `light-dark()` CSS function that resolves based on | ||
| * the computed `color-scheme` of the element. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * color.lightDark(theme.textLight, theme.textDark) // "light-dark(var(--theme-textLight), var(--theme-textDark))" | ||
| * ``` | ||
| */ | ||
| declare function lightDark(lightColor: string, darkColor: string): string; | ||
| /** | ||
| * Adjust the alpha/opacity of any color using `color-mix()`. | ||
| * | ||
| * This is a common pattern: mixing a color with transparent to change opacity. | ||
| * Works with any color value including token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.alpha('red', 0.5) // "color-mix(in srgb, red 50%, transparent)" | ||
| * color.alpha(theme.primary, 0.2) // "color-mix(in srgb, var(--theme-primary) 20%, transparent)" | ||
| * color.alpha('#0066ff', 0.8, 'oklch') // "color-mix(in oklch, #0066ff 80%, transparent)" | ||
| * ``` | ||
| */ | ||
| declare function alpha(colorValue: string, opacity: number, colorSpace?: ColorMixSpace): string; | ||
| type colorFns_ColorMixSpace = ColorMixSpace; | ||
| declare const colorFns_alpha: typeof alpha; | ||
| declare const colorFns_hsl: typeof hsl; | ||
| declare const colorFns_hwb: typeof hwb; | ||
| declare const colorFns_lab: typeof lab; | ||
| declare const colorFns_lch: typeof lch; | ||
| declare const colorFns_lightDark: typeof lightDark; | ||
| declare const colorFns_mix: typeof mix; | ||
| declare const colorFns_oklab: typeof oklab; | ||
| declare const colorFns_oklch: typeof oklch; | ||
| declare const colorFns_rgb: typeof rgb; | ||
| declare namespace colorFns { | ||
| export { type colorFns_ColorMixSpace as ColorMixSpace, colorFns_alpha as alpha, colorFns_hsl as hsl, colorFns_hwb as hwb, colorFns_lab as lab, colorFns_lch as lch, colorFns_lightDark as lightDark, colorFns_mix as mix, colorFns_oklab as oklab, colorFns_oklch as oklch, colorFns_rgb as rgb }; | ||
| } | ||
| /** | ||
| * Apply styles to an arbitrary CSS selector. | ||
@@ -1000,8 +1106,12 @@ * | ||
| * | ||
| * Returns a `var(--ts-N)` string that can be used anywhere a CSS value is | ||
| * Returns a `var(--ts-…)` string that can be used anywhere a CSS value is | ||
| * accepted. Use assignVars() to set its value per element via inline styles. | ||
| * | ||
| * Pass a debug name to get readable custom property names in DevTools | ||
| * (e.g. `createVar('cardBg')` → `var(--ts-cardbg)`). Anonymous vars use | ||
| * numeric ids (`--ts-1`, `--ts-2`, …). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const cardBg = createVar(); | ||
| * const cardBg = createVar('cardBg'); | ||
| * | ||
@@ -1016,3 +1126,3 @@ * const card = styles.component('card', { | ||
| */ | ||
| declare function createVar(): CSSVarRef; | ||
| declare function createVar(name?: string, fallback?: string): CSSVarRef; | ||
| /** | ||
@@ -1027,3 +1137,3 @@ * Build a CSS custom property assignment map from var refs to values. | ||
| * assignVars({ [cardBg]: '#ff0099' }) | ||
| * // → { '--ts-1': '#ff0099' } | ||
| * // → { '--ts-cardbg': '#ff0099' } | ||
| * ``` | ||
@@ -1034,2 +1144,10 @@ */ | ||
| /** | ||
| * Anything that coerces to a class string via `toString()`/`Symbol.toPrimitive` — covers | ||
| * `ThemeSurface` (`tokens.createTheme(...)`) and `ComponentAttrsResult` | ||
| * (`createStyles({ mode: 'attribute' })`) alongside plain strings. | ||
| */ | ||
| type Stringable = { | ||
| toString(): string; | ||
| }; | ||
| /** | ||
| * Join class name parts, filtering out falsy values. | ||
@@ -1049,5 +1167,8 @@ * | ||
| * // => "button-base button-primary extra" | ||
| * | ||
| * cx(attrButton({ variant: 'primary' }), 'extra'); | ||
| * // => "button-base extra" — ComponentAttrsResult coerces via toString() | ||
| * ``` | ||
| */ | ||
| declare function cx(...parts: Array<string | undefined | null | false | 0 | ''>): string; | ||
| declare function cx(...parts: Array<string | Stringable | undefined | null | false | 0 | ''>): string; | ||
@@ -1104,2 +1225,6 @@ /** | ||
| type SerializeStyleOptions = { | ||
| breakpoints?: BreakpointMap; | ||
| }; | ||
| /** | ||
@@ -1158,3 +1283,3 @@ * Default style API (semantic class names, empty `scopeId`). Prefer `createStyles({ scopeId, mode, prefix })` | ||
| */ | ||
| declare const tokens: TokensApi; | ||
| declare const tokens: TokensApi<Record<string, never>>; | ||
| /** | ||
@@ -1178,19 +1303,3 @@ * Keyframe animation API. | ||
| }; | ||
| /** | ||
| * Type-safe CSS color function helpers. | ||
| * | ||
| * Each function returns a plain CSS color string — no runtime color math. | ||
| * Composes naturally with token references. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * color.rgb(0, 102, 255) // "rgb(0 102 255)" | ||
| * color.oklch(0.7, 0.15, 250) // "oklch(0.7 0.15 250)" | ||
| * color.mix(theme.primary, 'white', 20) // "color-mix(in srgb, var(--theme-primary) 20%, white)" | ||
| * color.alpha(theme.primary, 0.5) // "color-mix(in srgb, var(--theme-primary) 50%, transparent)" | ||
| * color.lightDark('#111', '#eee') // "light-dark(#111, #eee)" | ||
| * ``` | ||
| */ | ||
| declare const color: typeof colorFns; | ||
| export { CSSProperties, CSSPropertiesWithUtils, CSSVarRef, type CascadeLayersInput, type CascadeLayersObjectInput, type ClassNamingConfig, type ClassNamingMode, type ColorMixSpace, ComponentConfigInput, ComponentReturn, type ContainerNameRef, type ContainerObjectKey, type ContainerQueryFeatures, type ContainerQueryKey, type ContainerQueryObject, type CreateContainerRefOptions, type CreateStylesInput, type CreateTokensOptions, type CssMathValue, FlatComponentConfigInput, FlatComponentReturn, FontFaceProps, type GlobalApiLayered, type GlobalApiUnlayered, GlobalStyleTuple, type HasNestedKey, type IsNestedKey, type IsPseudoArg, type LayerOption, type LayeredComponentFn, MultiSlotConfigInput, type ResolvedCascadeLayers, SlotComponentConfigInput, SlotComponentFunction, SlotVariantDefinitions, StyleUtils, type StylesApi, type StylesApiWithLayers, ThemeCondition, ThemeConditionAnd, ThemeConditionAttr, ThemeConditionClass, ThemeConditionMedia, ThemeConditionOr, ThemeConditionSelector, ThemeConfig, type ThemeEmitLayerContext, ThemeModeDefinition, ThemeOverrides, ThemeSurface, TokenRef, TokenValues, type TokensApi, VariantDefinitions, type WhereNestedKey, assignVars, atRuleBlock, calc, clamp, color, colorMode, container, content, createContainerRef, createDarkMode, createGlobal, createStyles, createTheme, createTokens, createTypeStyles, createVar, cx, defaultClassNamingConfig, fileScopeId, global, has, is, keyframes, mergeClassNaming, scopedTokenNamespace, styles, tokens, when, where }; | ||
| export { type AttributeComponentFn, type AttributeStylesApi, type AttributeStylesApiWithLayers, type BreakpointMap, type BreakpointsConfig, CSSProperties, CSSPropertiesWithUtils, CSSVarRef, type CascadeLayersInput, type CascadeLayersObjectInput, type ClassNameContext, type ClassNameTemplate, type ClassNamingConfig, type ClassNamingMode, ComponentAttrsReturn, ComponentConfigInput, ComponentReturn, ComposeFn, ComposeSelectorInput, type ContainerNameRef, type ContainerObjectKey, type ContainerQueryFeatures, type ContainerQueryKey, type ContainerQueryObject, type CreateContainerRefOptions, type CreateStylesInput, type CreateTokensOptions, CreatedTokenRef, type CssMathValue, FlatComponentConfigInput, FlatComponentReturn, FontFaceProps, type GlobalApiLayered, type GlobalApiUnlayered, GlobalStyleTuple, type HasNestedKey, type IsNestedKey, type IsPseudoArg, type LayerOption, type LayeredAttributeComponentFn, type LayeredComponentFn, MultiSlotConfigInput, RegisteredPropertyOptions, RegisteredPropertyRef, type ResolvedCascadeLayers, type ResponsiveValue, type ScopeOptions, type SerializeStyleOptions, SlotComponentConfigInput, SlotComponentFunction, SlotVariantDefinitions, StyleUtils, type StylesApi, type StylesApiWithLayers, ThemeCondition, ThemeConditionAnd, ThemeConditionAttr, ThemeConditionClass, ThemeConditionMedia, ThemeConditionOr, ThemeConditionSelector, ThemeConfig, type ThemeEmitLayerContext, ThemeModeDefinition, ThemeOverrides, ThemeSurface, TokenRef, TokenRegistry, TokenValues, type TokensApi, VariantDefinitions, type WhereNestedKey, assignVars, atRuleBlock, calc, clamp, colorMode, container, content, createContainerRef, createDarkMode, createGlobal, createScope, createStyles, createTheme, createTokens, createTypeStyles, createVar, cx, defaultClassNamingConfig, fileScopeId, getTokenLeafValues, global, has, is, keyframes, mergeClassNaming, resolveBreakpoints, scopedTokenNamespace, styles, tokens, when, where }; |
+122
-23
| 'use strict'; | ||
| var async_hooks = require('async_hooks'); | ||
| // src/sheet-node.ts | ||
| // src/sheet-context.ts | ||
| function createSheetState() { | ||
| return { | ||
| insertedRules: /* @__PURE__ */ new Set(), | ||
| ruleCssByKey: /* @__PURE__ */ new Map(), | ||
| pendingRules: [], | ||
| allRules: [], | ||
| flushScheduled: false, | ||
| ssrBuffer: null | ||
| }; | ||
| } | ||
| var globalSheetState = createSheetState(); | ||
| var getStoreImpl = () => globalSheetState; | ||
| var runIsolatedImpl = (fn) => fn(); | ||
| function configureSheetIsolation(config) { | ||
| getStoreImpl = config.getStore; | ||
| runIsolatedImpl = config.runIsolated; | ||
| } | ||
| function getSheetState() { | ||
| return getStoreImpl(); | ||
| } | ||
| function getGlobalSheetState() { | ||
| return globalSheetState; | ||
| } | ||
| function runWithIsolatedSheet(fn) { | ||
| return runIsolatedImpl(fn); | ||
| } | ||
| // src/sheet-node.ts | ||
| var sheetStorage = new async_hooks.AsyncLocalStorage(); | ||
| configureSheetIsolation({ | ||
| getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(), | ||
| runIsolated: (fn) => sheetStorage.run(createSheetState(), fn) | ||
| }); | ||
| // src/sheet.ts | ||
| var STYLE_ELEMENT_ID = "typestyles"; | ||
| var TYPESTYLES_STYLE_ID = "typestyles"; | ||
| var TYPESTYLES_FALLBACK_STYLE_ID = "typestyles-fallback"; | ||
| var STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID; | ||
| var FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID; | ||
| function readNextPublicRuntimeDisabled() { | ||
@@ -10,8 +52,7 @@ if (typeof process === "undefined" || !process.env) return false; | ||
| var RUNTIME_DISABLED = typeof __TYPESTYLES_RUNTIME_DISABLED__ !== "undefined" && __TYPESTYLES_RUNTIME_DISABLED__ === "true" || readNextPublicRuntimeDisabled(); | ||
| var pendingRules = []; | ||
| var allRules = []; | ||
| var styleElement = null; | ||
| var ssrBuffer = null; | ||
| var fallbackStyleElement = null; | ||
| var isBrowser = typeof document !== "undefined" && typeof window !== "undefined"; | ||
| function writeAllRulesToStyleElement(el) { | ||
| const { allRules } = getSheetState(); | ||
| if (RUNTIME_DISABLED || allRules.length === 0) return; | ||
@@ -24,7 +65,7 @@ const sheet = el.sheet; | ||
| } catch { | ||
| el.appendChild(document.createTextNode(css)); | ||
| appendFallbackRule(css); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(allRules.join("\n"))); | ||
| appendFallbackRule(allRules.join("\n")); | ||
| } | ||
@@ -47,3 +88,3 @@ } | ||
| document.head.appendChild(styleElement); | ||
| if (reconnectAfterDetach && allRules.length > 0) { | ||
| if (reconnectAfterDetach && getSheetState().allRules.length > 0) { | ||
| writeAllRulesToStyleElement(styleElement); | ||
@@ -53,8 +94,31 @@ } | ||
| } | ||
| function getFallbackStyleElement() { | ||
| if (fallbackStyleElement && !fallbackStyleElement.isConnected) { | ||
| fallbackStyleElement = null; | ||
| } | ||
| if (fallbackStyleElement) return fallbackStyleElement; | ||
| const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID); | ||
| if (existing?.isConnected) { | ||
| fallbackStyleElement = existing; | ||
| return fallbackStyleElement; | ||
| } | ||
| const main = getStyleElement(); | ||
| fallbackStyleElement = document.createElement("style"); | ||
| fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID; | ||
| main.insertAdjacentElement("afterend", fallbackStyleElement); | ||
| return fallbackStyleElement; | ||
| } | ||
| function appendFallbackRule(css) { | ||
| const el = getFallbackStyleElement(); | ||
| el.appendChild(document.createTextNode(`${css} | ||
| `)); | ||
| } | ||
| function flush() { | ||
| if (pendingRules.length === 0) return; | ||
| const rules = pendingRules; | ||
| pendingRules = []; | ||
| if (ssrBuffer) { | ||
| ssrBuffer.push(...rules); | ||
| const state = getSheetState(); | ||
| state.flushScheduled = false; | ||
| if (state.pendingRules.length === 0) return; | ||
| const rules = state.pendingRules; | ||
| state.pendingRules = []; | ||
| if (state.ssrBuffer) { | ||
| state.ssrBuffer.push(...rules); | ||
| return; | ||
@@ -70,14 +134,15 @@ } | ||
| } catch { | ||
| el.appendChild(document.createTextNode(rule)); | ||
| appendFallbackRule(rule); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(rules.join("\n"))); | ||
| appendFallbackRule(rules.join("\n")); | ||
| } | ||
| } | ||
| function startCollection() { | ||
| ssrBuffer = []; | ||
| const state = getSheetState(); | ||
| state.ssrBuffer = []; | ||
| return () => { | ||
| const css = ssrBuffer ? ssrBuffer.join("\n") : ""; | ||
| ssrBuffer = null; | ||
| const css = state.ssrBuffer ? state.ssrBuffer.join("\n") : ""; | ||
| state.ssrBuffer = null; | ||
| return css; | ||
@@ -87,4 +152,11 @@ }; | ||
| function getRegisteredCss() { | ||
| return allRules.join("\n"); | ||
| return getSheetState().allRules.join("\n"); | ||
| } | ||
| var registeredCssListeners = /* @__PURE__ */ new Set(); | ||
| function subscribeRegisteredCss(listener) { | ||
| registeredCssListeners.add(listener); | ||
| return () => { | ||
| registeredCssListeners.delete(listener); | ||
| }; | ||
| } | ||
| function flushSync() { | ||
@@ -95,13 +167,40 @@ flush(); | ||
| // src/server.ts | ||
| function typestylesStyleHtml(css) { | ||
| if (!css) return ""; | ||
| return `<style id="${TYPESTYLES_STYLE_ID}">${css}</style>`; | ||
| } | ||
| function injectStylesIntoHtml(html, css) { | ||
| const tag = typestylesStyleHtml(css); | ||
| if (!tag) return html; | ||
| if (html.includes("</head>")) { | ||
| return html.replace("</head>", `${tag}</head>`); | ||
| } | ||
| return `${tag}${html}`; | ||
| } | ||
| function streamingDocumentShell(css) { | ||
| return `<!DOCTYPE html><html><head><meta charset="utf-8"/>${typestylesStyleHtml(css)}</head><body>`; | ||
| } | ||
| function collectStyles(renderFn) { | ||
| const endCollection = startCollection(); | ||
| const html = renderFn(); | ||
| flushSync(); | ||
| const css = endCollection(); | ||
| return { html, css }; | ||
| return runWithIsolatedSheet(() => { | ||
| const endCollection = startCollection(); | ||
| const result = renderFn(); | ||
| if (result instanceof Promise) { | ||
| return result.then((html) => { | ||
| flushSync(); | ||
| return { html, css: endCollection() }; | ||
| }); | ||
| } | ||
| flushSync(); | ||
| return { html: result, css: endCollection() }; | ||
| }); | ||
| } | ||
| exports.TYPESTYLES_STYLE_ID = TYPESTYLES_STYLE_ID; | ||
| exports.collectStyles = collectStyles; | ||
| exports.getRegisteredCss = getRegisteredCss; | ||
| exports.injectStylesIntoHtml = injectStylesIntoHtml; | ||
| exports.streamingDocumentShell = streamingDocumentShell; | ||
| exports.subscribeRegisteredCss = subscribeRegisteredCss; | ||
| exports.typestylesStyleHtml = typestylesStyleHtml; | ||
| //# sourceMappingURL=server.cjs.map | ||
| //# sourceMappingURL=server.cjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/sheet.ts","../src/server.ts"],"names":[],"mappings":"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","file":"server.cjs","sourcesContent":["import {\n namespacesFromTypestylesHmrPrefixes,\n releaseReservedNamespacesForComponentOrClassNames,\n} from './registry';\n\nconst 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 * Last emitted CSS per dedupe key (see {@link warnIfDuplicateRuleKeyConflict}).\n * Cleared with {@link reset} and kept in sync when keys are invalidated.\n */\nconst ruleCssByKey = new Map<string, string>();\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\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 = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n el.appendChild(document.createTextNode(css));\n }\n }\n } else {\n el.appendChild(document.createTextNode(allRules.join('\\n')));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\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 || RUNTIME_DISABLED) 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 && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n\n allRules.unshift(css);\n\n if (ssrBuffer) {\n ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n }\n } else {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (RUNTIME_DISABLED && !ssrBuffer) return;\n pendingRules.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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (!RUNTIME_DISABLED || ssrBuffer) {\n pendingRules.push(css);\n added = true;\n }\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 || RUNTIME_DISABLED) return;\n\n insertedRules.delete(key);\n ruleCssByKey.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.component`, `styles.class`, `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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(namespace: string): void {\n const selectorInfix = `.${namespace}-`;\n const keysToDrop: string[] = [];\n for (const k of insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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","import { startCollection, flushSync, getRegisteredCss } from './sheet';\n\nexport { getRegisteredCss };\n\n/**\n * Collect all CSS generated during a render pass (for SSR).\n *\n * Wraps a synchronous render function and captures all CSS that would\n * normally be injected into the DOM. Returns both the render result\n * and the collected CSS string.\n *\n * For frameworks where you need the CSS separately from the render pass\n * (e.g. TanStack Start's `head()`, Next.js metadata), use the simpler\n * `getRegisteredCss()` instead.\n *\n * @example\n * ```ts\n * import { collectStyles } from 'typestyles/server';\n * import { renderToString } from 'react-dom/server';\n *\n * const { html, css } = collectStyles(() => renderToString(<App />));\n *\n * const fullHtml = `\n * <html>\n * <head><style id=\"typestyles\">${css}</style></head>\n * <body>${html}</body>\n * </html>\n * `;\n * ```\n */\nexport function collectStyles<T>(renderFn: () => T): { html: T; css: string } {\n const endCollection = startCollection();\n\n const html = renderFn();\n flushSync();\n const css = endCollection();\n\n return { html, css };\n}\n"]} | ||
| {"version":3,"sources":["../src/sheet-context.ts","../src/sheet-node.ts","../src/sheet.ts","../src/server.ts"],"names":["AsyncLocalStorage"],"mappings":"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","file":"server.cjs","sourcesContent":["export type SheetState = {\n insertedRules: Set<string>;\n ruleCssByKey: Map<string, string>;\n pendingRules: string[];\n allRules: string[];\n flushScheduled: boolean;\n ssrBuffer: string[] | null;\n};\n\nexport function createSheetState(): SheetState {\n return {\n insertedRules: new Set(),\n ruleCssByKey: new Map(),\n pendingRules: [],\n allRules: [],\n flushScheduled: false,\n ssrBuffer: null,\n };\n}\n\nexport function resetSheetState(state: SheetState): void {\n state.insertedRules.clear();\n state.ruleCssByKey.clear();\n state.pendingRules = [];\n state.allRules.length = 0;\n state.flushScheduled = false;\n state.ssrBuffer = null;\n}\n\nconst globalSheetState = createSheetState();\n\nlet getStoreImpl: () => SheetState = () => globalSheetState;\nlet runIsolatedImpl: <T>(fn: () => T) => T = (fn) => fn();\n\n/** Register Node AsyncLocalStorage isolation (see `sheet-node.ts`). */\nexport function configureSheetIsolation(config: {\n getStore: () => SheetState;\n runIsolated: <T>(fn: () => T) => T;\n}): void {\n getStoreImpl = config.getStore;\n runIsolatedImpl = config.runIsolated;\n}\n\nexport function getSheetState(): SheetState {\n return getStoreImpl();\n}\n\nexport function getGlobalSheetState(): SheetState {\n return globalSheetState;\n}\n\n/** Run `fn` with a fresh sheet store on Node (no-op in the browser bundle). */\nexport function runWithIsolatedSheet<T>(fn: () => T): T {\n return runIsolatedImpl(fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n configureSheetIsolation,\n createSheetState,\n getGlobalSheetState,\n type SheetState,\n} from './sheet-context';\n\nconst sheetStorage = new AsyncLocalStorage<SheetState>();\n\nconfigureSheetIsolation({\n getStore: () => sheetStorage.getStore() ?? getGlobalSheetState(),\n runIsolated: <T>(fn: () => T) => sheetStorage.run(createSheetState(), fn),\n});\n","import {\n namespacesFromTypestylesHmrPrefixes,\n registeredNamespaces,\n releaseReservedNamespacesForComponentOrClassNames,\n resetEmittedClassNameTracking,\n} from './registry';\nimport {\n getSheetState,\n getGlobalSheetState,\n resetSheetState,\n type SheetState,\n} from './sheet-context';\n\n/** Stable id for the managed `<style>` element (SSR, hydration, and client runtime). */\nexport const TYPESTYLES_STYLE_ID = 'typestyles';\n\n/**\n * Stable id for the text-fallback `<style>` element. Rules the CSSOM rejects\n * via `insertRule` land here as text. They must never be appended as text to\n * the main element: mutating a `<style>` element's text makes the browser\n * re-parse the element from its text content, discarding every rule that was\n * previously added through `insertRule` — one rejected rule would wipe the\n * entire runtime sheet.\n */\nexport const TYPESTYLES_FALLBACK_STYLE_ID = 'typestyles-fallback';\n\nconst STYLE_ELEMENT_ID = TYPESTYLES_STYLE_ID;\nconst FALLBACK_STYLE_ELEMENT_ID = TYPESTYLES_FALLBACK_STYLE_ID;\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\n\n/**\n * The managed <style> element, lazily created.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * The managed text-fallback <style> element, lazily created (see\n * {@link TYPESTYLES_FALLBACK_STYLE_ID}).\n */\nlet fallbackStyleElement: HTMLStyleElement | null = null;\n\n/**\n * Whether we're running in a browser environment.\n */\nconst isBrowser = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n const { allRules } = getSheetState();\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n appendFallbackRule(css);\n }\n }\n } else {\n appendFallbackRule(allRules.join('\\n'));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && getSheetState().allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * The fallback element mirrors the main element's lifecycle: reuse a connected\n * element by id, recover from detachment (doc swaps), and keep a deterministic\n * position immediately after the main element so cascade order stays stable.\n */\nfunction getFallbackStyleElement(): HTMLStyleElement {\n if (fallbackStyleElement && !fallbackStyleElement.isConnected) {\n fallbackStyleElement = null;\n }\n if (fallbackStyleElement) return fallbackStyleElement;\n\n const existing = document.getElementById(FALLBACK_STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n fallbackStyleElement = existing;\n return fallbackStyleElement;\n }\n\n const main = getStyleElement();\n fallbackStyleElement = document.createElement('style');\n fallbackStyleElement.id = FALLBACK_STYLE_ELEMENT_ID;\n main.insertAdjacentElement('afterend', fallbackStyleElement);\n return fallbackStyleElement;\n}\n\n/**\n * Append a rule the CSSOM rejected as text to the fallback element. The\n * fallback element only ever holds text (never `insertRule`), so re-parsing\n * it on append cannot lose rules.\n */\nfunction appendFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.appendChild(document.createTextNode(`${css}\\n`));\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\n}\n\nfunction flush(): void {\n const state = getSheetState();\n state.flushScheduled = false;\n if (state.pendingRules.length === 0) return;\n\n const rules = state.pendingRules;\n state.pendingRules = [];\n\n if (state.ssrBuffer) {\n state.ssrBuffer.push(...rules);\n return;\n }\n\n if (!isBrowser || RUNTIME_DISABLED) 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 on the dedicated fallback element (handles\n // edge cases with certain selectors) — never on `el`, where the text\n // re-parse would discard all previously inserted CSSOM rules.\n appendFallbackRule(rule);\n }\n }\n } else {\n // Sheet not available yet, append as text\n appendFallbackRule(rules.join('\\n'));\n }\n}\n\nfunction scheduleFlush(): void {\n const state = getSheetState();\n if (state.flushScheduled) return;\n state.flushScheduled = true;\n\n if (state.ssrBuffer) {\n // In SSR mode, flush synchronously\n flush();\n return;\n }\n\n if (isBrowser && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const state = getSheetState();\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (state.insertedRules.has(key)) return;\n state.insertedRules.add(key);\n\n state.allRules.unshift(css);\n notifyRegisteredCssChanged();\n\n if (state.ssrBuffer) {\n state.ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n prependFallbackRule(css);\n }\n } else {\n prependFallbackRule(css);\n }\n}\n\n/** Front-insert for the `@layer` order preamble when the CSSOM rejects it. */\nfunction prependFallbackRule(css: string): void {\n const el = getFallbackStyleElement();\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n}\n\n/**\n * Insert a CSS rule. Deduplicates by rule key.\n */\nexport function insertRule(key: string, css: string): void {\n const state = getSheetState();\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n notifyRegisteredCssChanged();\n if (RUNTIME_DISABLED && !state.ssrBuffer) return;\n state.pendingRules.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 const state = getSheetState();\n let added = false;\n let registered = false;\n for (const { key, css } of rules) {\n if (state.insertedRules.has(key)) {\n const prev = state.ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n state.insertedRules.add(key);\n state.ruleCssByKey.set(key, css);\n state.allRules.push(css);\n registered = true;\n if (!RUNTIME_DISABLED || state.ssrBuffer) {\n state.pendingRules.push(css);\n added = true;\n }\n }\n if (registered) notifyRegisteredCssChanged();\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 || RUNTIME_DISABLED) return;\n\n const state = getSheetState();\n state.insertedRules.delete(key);\n state.ruleCssByKey.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 const state = getSheetState();\n state.ssrBuffer = [];\n return () => {\n const css = state.ssrBuffer ? state.ssrBuffer.join('\\n') : '';\n state.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.component`, `styles.class`, `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 getSheetState().allRules.join('\\n');\n}\n\nconst registeredCssListeners = new Set<() => void>();\n\nfunction notifyRegisteredCssChanged(): void {\n for (const listener of registeredCssListeners) {\n listener();\n }\n}\n\n/**\n * Subscribe to changes in the registered CSS (`getRegisteredCss()`).\n * Returns an unsubscribe function. Compatible with `useSyncExternalStore`.\n *\n * @example\n * ```ts\n * import { subscribeRegisteredCss, getRegisteredCss } from 'typestyles/server';\n *\n * const css = useSyncExternalStore(subscribeRegisteredCss, getRegisteredCss, getRegisteredCss);\n * ```\n */\nexport function subscribeRegisteredCss(listener: () => void): () => void {\n registeredCssListeners.add(listener);\n return () => {\n registeredCssListeners.delete(listener);\n };\n}\n\n/**\n * Reset all state (useful for testing).\n */\nexport function reset(): void {\n resetSheetState(getGlobalSheetState());\n const active = getSheetState();\n if (active !== getGlobalSheetState()) {\n resetSheetState(active);\n }\n registeredNamespaces.clear();\n resetEmittedClassNameTracking();\n notifyRegisteredCssChanged();\n if (isBrowser && styleElement) {\n styleElement.remove();\n styleElement = null;\n }\n if (isBrowser && fallbackStyleElement) {\n fallbackStyleElement.remove();\n fallbackStyleElement = 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 * Drop CSS text queued in `pendingRules` / `allRules` / an active `ssrBuffer` for rules whose\n * key was just invalidated. Without this, re-registering a namespace before its first\n * registration has flushed (no intervening `flushSync()` / microtask) leaves the stale CSS\n * sitting in these arrays — `insertedRules` no longer references it, so it's never deduped, and\n * it gets flushed alongside the new CSS as a duplicate, conflicting rule.\n */\nfunction pruneRemovedCss(state: SheetState, removedCss: ReadonlySet<string>): void {\n if (removedCss.size === 0) return;\n state.pendingRules = state.pendingRules.filter((css) => !removedCss.has(css));\n state.allRules = state.allRules.filter((css) => !removedCss.has(css));\n if (state.ssrBuffer) {\n state.ssrBuffer = state.ssrBuffer.filter((css) => !removedCss.has(css));\n }\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 const state = getSheetState();\n const removedCss = new Set<string>();\n for (const key of keys) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n for (const prefix of prefixes) {\n for (const key of state.insertedRules) {\n if (key.startsWith(prefix)) {\n const css = state.ruleCssByKey.get(key);\n if (css != null) removedCss.add(css);\n state.insertedRules.delete(key);\n state.ruleCssByKey.delete(key);\n }\n }\n }\n pruneRemovedCss(state, removedCss);\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(\n namespace: string,\n emittedClassPrefix?: string,\n): void {\n const selectorInfix = `.${emittedClassPrefix ?? `${namespace}-`}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\n}\n\n/**\n * Drop every rule key tied to a `styles.class('name', …)` registration — the base selector plus\n * any pseudo/nested/at-rule-wrapped variants — and release the reserved namespace entry. Used for\n * Vite HMR and for dev recovery when a module re-runs before `hot.dispose`, including\n * multi-environment SSR setups (e.g. the Vite Environment API, or RSC frameworks like Waku) that\n * re-evaluate the same source module once per environment within a single process.\n *\n * No-op when `emittedClassName` is `undefined` (hashed/compact/atomic modes derive the class name\n * from the serialized properties, so there's no reliable selector to invalidate ahead of time —\n * same limitation `invalidateComponentNamespaceForDev` has for those modes).\n */\nexport function invalidateClassNamespaceForDev(emittedClassName?: string): void {\n if (!emittedClassName) return;\n const selectorInfix = `.${emittedClassName}`;\n const state = getSheetState();\n const keysToDrop: string[] = [];\n for (const k of state.insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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","import './sheet-node';\nimport {\n startCollection,\n flushSync,\n getRegisteredCss,\n subscribeRegisteredCss,\n TYPESTYLES_STYLE_ID,\n} from './sheet';\nimport { runWithIsolatedSheet } from './sheet-context';\n\nexport { getRegisteredCss, subscribeRegisteredCss, TYPESTYLES_STYLE_ID };\n\n/**\n * Render a `<style id=\"typestyles\">` tag for embedding in HTML.\n * Returns an empty string when `css` is empty.\n */\nexport function typestylesStyleHtml(css: string): string {\n if (!css) return '';\n return `<style id=\"${TYPESTYLES_STYLE_ID}\">${css}</style>`;\n}\n\n/**\n * Insert collected CSS before `</head>` in a full or partial HTML document.\n * When no `</head>` is present, prepends the style tag to the string.\n */\nexport function injectStylesIntoHtml(html: string, css: string): string {\n const tag = typestylesStyleHtml(css);\n if (!tag) return html;\n if (html.includes('</head>')) {\n return html.replace('</head>', `${tag}</head>`);\n }\n return `${tag}${html}`;\n}\n\n/**\n * Open an HTML document shell for `renderToPipeableStream`: doctype, `<head>` with\n * charset meta and collected CSS, and `<body>`. Pair with `collectStyles()` for the\n * CSS pass, then close `</body></html>` when the stream finishes.\n */\nexport function streamingDocumentShell(css: string): string {\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"/>${typestylesStyleHtml(css)}</head><body>`;\n}\n\nexport type CollectStylesResult<T> = { html: T; css: string };\n\n/**\n * Collect all CSS generated during a render pass (for SSR).\n *\n * Wraps a render function and captures all CSS registered while it runs.\n * On Node, each call uses an isolated sheet store (`AsyncLocalStorage`) so\n * concurrent SSR requests do not interleave CSS. Sync and async render\n * functions are supported.\n *\n * For frameworks where you need the CSS separately from the render pass\n * (e.g. TanStack Start's `head()`, Next.js metadata), use the simpler\n * `getRegisteredCss()` instead.\n *\n * @example\n * ```ts\n * import { collectStyles } from 'typestyles/server';\n * import { renderToString } from 'react-dom/server';\n *\n * const { html, css } = collectStyles(() => renderToString(<App />));\n *\n * const fullHtml = `\n * <html>\n * <head><style id=\"typestyles\">${css}</style></head>\n * <body>${html}</body>\n * </html>\n * `;\n * ```\n */\nexport function collectStyles<T>(renderFn: () => T): CollectStylesResult<T>;\nexport function collectStyles<T>(renderFn: () => Promise<T>): Promise<CollectStylesResult<T>>;\nexport function collectStyles<T>(\n renderFn: () => T | Promise<T>,\n): CollectStylesResult<T> | Promise<CollectStylesResult<T>> {\n return runWithIsolatedSheet(() => {\n const endCollection = startCollection();\n const result = renderFn();\n if (result instanceof Promise) {\n return result.then((html) => {\n flushSync();\n return { html, css: endCollection() };\n });\n }\n flushSync();\n return { html: result, css: endCollection() };\n });\n}\n"]} |
+28
-9
@@ -1,9 +0,30 @@ | ||
| export { g as getRegisteredCss } from './hmr-D5sXuQgK.cjs'; | ||
| export { T as TYPESTYLES_STYLE_ID, g as getRegisteredCss, s as subscribeRegisteredCss } from './hmr-DhHxThox.cjs'; | ||
| /** | ||
| * Render a `<style id="typestyles">` tag for embedding in HTML. | ||
| * Returns an empty string when `css` is empty. | ||
| */ | ||
| declare function typestylesStyleHtml(css: string): string; | ||
| /** | ||
| * Insert collected CSS before `</head>` in a full or partial HTML document. | ||
| * When no `</head>` is present, prepends the style tag to the string. | ||
| */ | ||
| declare function injectStylesIntoHtml(html: string, css: string): string; | ||
| /** | ||
| * Open an HTML document shell for `renderToPipeableStream`: doctype, `<head>` with | ||
| * charset meta and collected CSS, and `<body>`. Pair with `collectStyles()` for the | ||
| * CSS pass, then close `</body></html>` when the stream finishes. | ||
| */ | ||
| declare function streamingDocumentShell(css: string): string; | ||
| type CollectStylesResult<T> = { | ||
| html: T; | ||
| css: string; | ||
| }; | ||
| /** | ||
| * Collect all CSS generated during a render pass (for SSR). | ||
| * | ||
| * Wraps a synchronous render function and captures all CSS that would | ||
| * normally be injected into the DOM. Returns both the render result | ||
| * and the collected CSS string. | ||
| * Wraps a render function and captures all CSS registered while it runs. | ||
| * On Node, each call uses an isolated sheet store (`AsyncLocalStorage`) so | ||
| * concurrent SSR requests do not interleave CSS. Sync and async render | ||
| * functions are supported. | ||
| * | ||
@@ -29,7 +50,5 @@ * For frameworks where you need the CSS separately from the render pass | ||
| */ | ||
| declare function collectStyles<T>(renderFn: () => T): { | ||
| html: T; | ||
| css: string; | ||
| }; | ||
| declare function collectStyles<T>(renderFn: () => T): CollectStylesResult<T>; | ||
| declare function collectStyles<T>(renderFn: () => Promise<T>): Promise<CollectStylesResult<T>>; | ||
| export { collectStyles }; | ||
| export { type CollectStylesResult, collectStyles, injectStylesIntoHtml, streamingDocumentShell, typestylesStyleHtml }; |
+28
-9
@@ -1,9 +0,30 @@ | ||
| export { g as getRegisteredCss } from './hmr-D5sXuQgK.js'; | ||
| export { T as TYPESTYLES_STYLE_ID, g as getRegisteredCss, s as subscribeRegisteredCss } from './hmr-DhHxThox.js'; | ||
| /** | ||
| * Render a `<style id="typestyles">` tag for embedding in HTML. | ||
| * Returns an empty string when `css` is empty. | ||
| */ | ||
| declare function typestylesStyleHtml(css: string): string; | ||
| /** | ||
| * Insert collected CSS before `</head>` in a full or partial HTML document. | ||
| * When no `</head>` is present, prepends the style tag to the string. | ||
| */ | ||
| declare function injectStylesIntoHtml(html: string, css: string): string; | ||
| /** | ||
| * Open an HTML document shell for `renderToPipeableStream`: doctype, `<head>` with | ||
| * charset meta and collected CSS, and `<body>`. Pair with `collectStyles()` for the | ||
| * CSS pass, then close `</body></html>` when the stream finishes. | ||
| */ | ||
| declare function streamingDocumentShell(css: string): string; | ||
| type CollectStylesResult<T> = { | ||
| html: T; | ||
| css: string; | ||
| }; | ||
| /** | ||
| * Collect all CSS generated during a render pass (for SSR). | ||
| * | ||
| * Wraps a synchronous render function and captures all CSS that would | ||
| * normally be injected into the DOM. Returns both the render result | ||
| * and the collected CSS string. | ||
| * Wraps a render function and captures all CSS registered while it runs. | ||
| * On Node, each call uses an isolated sheet store (`AsyncLocalStorage`) so | ||
| * concurrent SSR requests do not interleave CSS. Sync and async render | ||
| * functions are supported. | ||
| * | ||
@@ -29,7 +50,5 @@ * For frameworks where you need the CSS separately from the render pass | ||
| */ | ||
| declare function collectStyles<T>(renderFn: () => T): { | ||
| html: T; | ||
| css: string; | ||
| }; | ||
| declare function collectStyles<T>(renderFn: () => T): CollectStylesResult<T>; | ||
| declare function collectStyles<T>(renderFn: () => Promise<T>): Promise<CollectStylesResult<T>>; | ||
| export { collectStyles }; | ||
| export { type CollectStylesResult, collectStyles, injectStylesIntoHtml, streamingDocumentShell, typestylesStyleHtml }; |
+31
-8
@@ -1,16 +0,39 @@ | ||
| import { startCollection, flushSync } from './chunk-G6ATUNEZ.js'; | ||
| export { getRegisteredCss } from './chunk-G6ATUNEZ.js'; | ||
| import './chunk-Z4UVRQXZ.js'; | ||
| import { TYPESTYLES_STYLE_ID, runWithIsolatedSheet, startCollection, flushSync } from './chunk-5CMEHXCU.js'; | ||
| export { TYPESTYLES_STYLE_ID, getRegisteredCss, subscribeRegisteredCss } from './chunk-5CMEHXCU.js'; | ||
| import './chunk-PZ5AY32C.js'; | ||
| // src/server.ts | ||
| function typestylesStyleHtml(css) { | ||
| if (!css) return ""; | ||
| return `<style id="${TYPESTYLES_STYLE_ID}">${css}</style>`; | ||
| } | ||
| function injectStylesIntoHtml(html, css) { | ||
| const tag = typestylesStyleHtml(css); | ||
| if (!tag) return html; | ||
| if (html.includes("</head>")) { | ||
| return html.replace("</head>", `${tag}</head>`); | ||
| } | ||
| return `${tag}${html}`; | ||
| } | ||
| function streamingDocumentShell(css) { | ||
| return `<!DOCTYPE html><html><head><meta charset="utf-8"/>${typestylesStyleHtml(css)}</head><body>`; | ||
| } | ||
| function collectStyles(renderFn) { | ||
| const endCollection = startCollection(); | ||
| const html = renderFn(); | ||
| flushSync(); | ||
| const css = endCollection(); | ||
| return { html, css }; | ||
| return runWithIsolatedSheet(() => { | ||
| const endCollection = startCollection(); | ||
| const result = renderFn(); | ||
| if (result instanceof Promise) { | ||
| return result.then((html) => { | ||
| flushSync(); | ||
| return { html, css: endCollection() }; | ||
| }); | ||
| } | ||
| flushSync(); | ||
| return { html: result, css: endCollection() }; | ||
| }); | ||
| } | ||
| export { collectStyles }; | ||
| export { collectStyles, injectStylesIntoHtml, streamingDocumentShell, typestylesStyleHtml }; | ||
| //# sourceMappingURL=server.js.map | ||
| //# sourceMappingURL=server.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/server.ts"],"names":[],"mappings":";;;;;AA8BO,SAAS,cAAiB,QAAA,EAA6C;AAC5E,EAAA,MAAM,gBAAgB,eAAA,EAAgB;AAEtC,EAAA,MAAM,OAAO,QAAA,EAAS;AACtB,EAAA,SAAA,EAAU;AACV,EAAA,MAAM,MAAM,aAAA,EAAc;AAE1B,EAAA,OAAO,EAAE,MAAM,GAAA,EAAI;AACrB","file":"server.js","sourcesContent":["import { startCollection, flushSync, getRegisteredCss } from './sheet';\n\nexport { getRegisteredCss };\n\n/**\n * Collect all CSS generated during a render pass (for SSR).\n *\n * Wraps a synchronous render function and captures all CSS that would\n * normally be injected into the DOM. Returns both the render result\n * and the collected CSS string.\n *\n * For frameworks where you need the CSS separately from the render pass\n * (e.g. TanStack Start's `head()`, Next.js metadata), use the simpler\n * `getRegisteredCss()` instead.\n *\n * @example\n * ```ts\n * import { collectStyles } from 'typestyles/server';\n * import { renderToString } from 'react-dom/server';\n *\n * const { html, css } = collectStyles(() => renderToString(<App />));\n *\n * const fullHtml = `\n * <html>\n * <head><style id=\"typestyles\">${css}</style></head>\n * <body>${html}</body>\n * </html>\n * `;\n * ```\n */\nexport function collectStyles<T>(renderFn: () => T): { html: T; css: string } {\n const endCollection = startCollection();\n\n const html = renderFn();\n flushSync();\n const css = endCollection();\n\n return { html, css };\n}\n"]} | ||
| {"version":3,"sources":["../src/server.ts"],"names":[],"mappings":";;;;;;AAgBO,SAAS,oBAAoB,GAAA,EAAqB;AACvD,EAAA,IAAI,CAAC,KAAK,OAAO,EAAA;AACjB,EAAA,OAAO,CAAA,WAAA,EAAc,mBAAmB,CAAA,EAAA,EAAK,GAAG,CAAA,QAAA,CAAA;AAClD;AAMO,SAAS,oBAAA,CAAqB,MAAc,GAAA,EAAqB;AACtE,EAAA,MAAM,GAAA,GAAM,oBAAoB,GAAG,CAAA;AACnC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,CAAA,EAAG,GAAG,CAAA,OAAA,CAAS,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,IAAI,CAAA,CAAA;AACtB;AAOO,SAAS,uBAAuB,GAAA,EAAqB;AAC1D,EAAA,OAAO,CAAA,kDAAA,EAAqD,mBAAA,CAAoB,GAAG,CAAC,CAAA,aAAA,CAAA;AACtF;AAiCO,SAAS,cACd,QAAA,EAC0D;AAC1D,EAAA,OAAO,qBAAqB,MAAM;AAChC,IAAA,MAAM,gBAAgB,eAAA,EAAgB;AACtC,IAAA,MAAM,SAAS,QAAA,EAAS;AACxB,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,OAAO,MAAA,CAAO,IAAA,CAAK,CAAC,IAAA,KAAS;AAC3B,QAAA,SAAA,EAAU;AACV,QAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,aAAA,EAAc,EAAE;AAAA,MACtC,CAAC,CAAA;AAAA,IACH;AACA,IAAA,SAAA,EAAU;AACV,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAK,eAAc,EAAE;AAAA,EAC9C,CAAC,CAAA;AACH","file":"server.js","sourcesContent":["import './sheet-node';\nimport {\n startCollection,\n flushSync,\n getRegisteredCss,\n subscribeRegisteredCss,\n TYPESTYLES_STYLE_ID,\n} from './sheet';\nimport { runWithIsolatedSheet } from './sheet-context';\n\nexport { getRegisteredCss, subscribeRegisteredCss, TYPESTYLES_STYLE_ID };\n\n/**\n * Render a `<style id=\"typestyles\">` tag for embedding in HTML.\n * Returns an empty string when `css` is empty.\n */\nexport function typestylesStyleHtml(css: string): string {\n if (!css) return '';\n return `<style id=\"${TYPESTYLES_STYLE_ID}\">${css}</style>`;\n}\n\n/**\n * Insert collected CSS before `</head>` in a full or partial HTML document.\n * When no `</head>` is present, prepends the style tag to the string.\n */\nexport function injectStylesIntoHtml(html: string, css: string): string {\n const tag = typestylesStyleHtml(css);\n if (!tag) return html;\n if (html.includes('</head>')) {\n return html.replace('</head>', `${tag}</head>`);\n }\n return `${tag}${html}`;\n}\n\n/**\n * Open an HTML document shell for `renderToPipeableStream`: doctype, `<head>` with\n * charset meta and collected CSS, and `<body>`. Pair with `collectStyles()` for the\n * CSS pass, then close `</body></html>` when the stream finishes.\n */\nexport function streamingDocumentShell(css: string): string {\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"/>${typestylesStyleHtml(css)}</head><body>`;\n}\n\nexport type CollectStylesResult<T> = { html: T; css: string };\n\n/**\n * Collect all CSS generated during a render pass (for SSR).\n *\n * Wraps a render function and captures all CSS registered while it runs.\n * On Node, each call uses an isolated sheet store (`AsyncLocalStorage`) so\n * concurrent SSR requests do not interleave CSS. Sync and async render\n * functions are supported.\n *\n * For frameworks where you need the CSS separately from the render pass\n * (e.g. TanStack Start's `head()`, Next.js metadata), use the simpler\n * `getRegisteredCss()` instead.\n *\n * @example\n * ```ts\n * import { collectStyles } from 'typestyles/server';\n * import { renderToString } from 'react-dom/server';\n *\n * const { html, css } = collectStyles(() => renderToString(<App />));\n *\n * const fullHtml = `\n * <html>\n * <head><style id=\"typestyles\">${css}</style></head>\n * <body>${html}</body>\n * </html>\n * `;\n * ```\n */\nexport function collectStyles<T>(renderFn: () => T): CollectStylesResult<T>;\nexport function collectStyles<T>(renderFn: () => Promise<T>): Promise<CollectStylesResult<T>>;\nexport function collectStyles<T>(\n renderFn: () => T | Promise<T>,\n): CollectStylesResult<T> | Promise<CollectStylesResult<T>> {\n return runWithIsolatedSheet(() => {\n const endCollection = startCollection();\n const result = renderFn();\n if (result instanceof Promise) {\n return result.then((html) => {\n flushSync();\n return { html, css: endCollection() };\n });\n }\n flushSync();\n return { html: result, css: endCollection() };\n });\n}\n"]} |
+35
-3
| { | ||
| "name": "typestyles", | ||
| "version": "0.0.0-unstable.921c88bcff7e", | ||
| "version": "0.0.0-unstable.9cf89f1ce486", | ||
| "description": "CSS-in-TypeScript that embraces CSS instead of hiding from it", | ||
@@ -59,6 +59,37 @@ "type": "module", | ||
| } | ||
| }, | ||
| "./color": { | ||
| "import": { | ||
| "types": "./dist/color.d.ts", | ||
| "default": "./dist/color.js" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/color.d.cts", | ||
| "default": "./dist/color.cjs" | ||
| } | ||
| }, | ||
| "./color-scale": { | ||
| "import": { | ||
| "types": "./dist/color-scale.d.ts", | ||
| "default": "./dist/color-scale.js" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/color-scale.d.cts", | ||
| "default": "./dist/color-scale.cjs" | ||
| } | ||
| }, | ||
| "./token-scale": { | ||
| "import": { | ||
| "types": "./dist/token-scale.d.ts", | ||
| "default": "./dist/token-scale.js" | ||
| }, | ||
| "require": { | ||
| "types": "./dist/token-scale.d.cts", | ||
| "default": "./dist/token-scale.cjs" | ||
| } | ||
| } | ||
| }, | ||
| "files": [ | ||
| "dist" | ||
| "dist", | ||
| "llms.txt" | ||
| ], | ||
@@ -93,3 +124,4 @@ "keywords": [ | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "build": "tsup && node scripts/check-bundle-size.mjs", | ||
| "check:bundle-size": "node scripts/check-bundle-size.mjs", | ||
| "dev": "tsup --watch", | ||
@@ -96,0 +128,0 @@ "test": "vitest run", |
| // src/registry.ts | ||
| var registeredNamespaces = /* @__PURE__ */ new Set(); | ||
| var COLON = ":"; | ||
| function releaseReservedNamespacesForComponentOrClassNames(namespaces) { | ||
| if (namespaces.length === 0) return; | ||
| const wanted = new Set(namespaces); | ||
| const toRemove = []; | ||
| for (const key of registeredNamespaces) { | ||
| const i = key.indexOf(COLON); | ||
| if (i === -1) continue; | ||
| if (wanted.has(key.slice(i + 1))) { | ||
| toRemove.push(key); | ||
| } | ||
| } | ||
| for (const key of toRemove) { | ||
| registeredNamespaces.delete(key); | ||
| } | ||
| } | ||
| function namespacesFromTypestylesHmrPrefixes(prefixes) { | ||
| const out = []; | ||
| for (const p of prefixes) { | ||
| if (p.length >= 2 && p.startsWith(".") && p.endsWith("-")) { | ||
| out.push(p.slice(1, -1)); | ||
| } | ||
| } | ||
| return out; | ||
| } | ||
| // src/sheet.ts | ||
| var STYLE_ELEMENT_ID = "typestyles"; | ||
| var insertedRules = /* @__PURE__ */ new Set(); | ||
| var ruleCssByKey = /* @__PURE__ */ new Map(); | ||
| function duplicateRuleKeyConflictWarningsEnabled() { | ||
| if (typeof process === "undefined") return true; | ||
| return process.env.NODE_ENV !== "production"; | ||
| } | ||
| function warnIfDuplicateRuleKeyConflict(key, previousCss, ignoredCss) { | ||
| if (!duplicateRuleKeyConflictWarningsEnabled()) return; | ||
| const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}\u2026` : previousCss; | ||
| const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}\u2026` : ignoredCss; | ||
| console.warn( | ||
| `[typestyles] Skipped a rule: dedupe key "${key}" already exists with different CSS. Only the first registration is kept. For globals, merge into one \`global.style\`, or use a distinct selector (e.g. \`html body\` after reset\u2019s \`body\`). | ||
| Existing: ${prevShort} | ||
| Skipped: ${nextShort}` | ||
| ); | ||
| } | ||
| function readNextPublicRuntimeDisabled() { | ||
| if (typeof process === "undefined" || !process.env) return false; | ||
| return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === "true"; | ||
| } | ||
| var RUNTIME_DISABLED = typeof __TYPESTYLES_RUNTIME_DISABLED__ !== "undefined" && __TYPESTYLES_RUNTIME_DISABLED__ === "true" || readNextPublicRuntimeDisabled(); | ||
| var pendingRules = []; | ||
| var allRules = []; | ||
| var flushScheduled = false; | ||
| var styleElement = null; | ||
| var ssrBuffer = null; | ||
| var isBrowser = typeof document !== "undefined" && typeof window !== "undefined"; | ||
| function writeAllRulesToStyleElement(el) { | ||
| if (RUNTIME_DISABLED || allRules.length === 0) return; | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| for (const css of allRules) { | ||
| try { | ||
| sheet.insertRule(css, sheet.cssRules.length); | ||
| } catch { | ||
| el.appendChild(document.createTextNode(css)); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(allRules.join("\n"))); | ||
| } | ||
| } | ||
| function getStyleElement() { | ||
| let reconnectAfterDetach = false; | ||
| if (styleElement && !styleElement.isConnected) { | ||
| reconnectAfterDetach = true; | ||
| styleElement = null; | ||
| } | ||
| if (styleElement) return styleElement; | ||
| const existing = document.getElementById(STYLE_ELEMENT_ID); | ||
| if (existing?.isConnected) { | ||
| styleElement = existing; | ||
| return styleElement; | ||
| } | ||
| styleElement = document.createElement("style"); | ||
| styleElement.id = STYLE_ELEMENT_ID; | ||
| document.head.appendChild(styleElement); | ||
| if (reconnectAfterDetach && allRules.length > 0) { | ||
| writeAllRulesToStyleElement(styleElement); | ||
| } | ||
| return styleElement; | ||
| } | ||
| function ensureDocumentStylesAttached() { | ||
| if (!isBrowser || RUNTIME_DISABLED) return; | ||
| getStyleElement(); | ||
| } | ||
| function flush() { | ||
| flushScheduled = false; | ||
| if (pendingRules.length === 0) return; | ||
| const rules = pendingRules; | ||
| pendingRules = []; | ||
| if (ssrBuffer) { | ||
| ssrBuffer.push(...rules); | ||
| return; | ||
| } | ||
| if (!isBrowser || RUNTIME_DISABLED) return; | ||
| const el = getStyleElement(); | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| for (const rule of rules) { | ||
| try { | ||
| sheet.insertRule(rule, sheet.cssRules.length); | ||
| } catch { | ||
| el.appendChild(document.createTextNode(rule)); | ||
| } | ||
| } | ||
| } else { | ||
| el.appendChild(document.createTextNode(rules.join("\n"))); | ||
| } | ||
| } | ||
| function scheduleFlush() { | ||
| if (flushScheduled) return; | ||
| flushScheduled = true; | ||
| if (ssrBuffer) { | ||
| flush(); | ||
| return; | ||
| } | ||
| if (isBrowser && !RUNTIME_DISABLED) { | ||
| queueMicrotask(flush); | ||
| } | ||
| } | ||
| function registerCascadeLayerOrder(preambleKey, css) { | ||
| const key = `typestyles:@layer-order:${preambleKey}`; | ||
| if (insertedRules.has(key)) return; | ||
| insertedRules.add(key); | ||
| allRules.unshift(css); | ||
| if (ssrBuffer) { | ||
| ssrBuffer.unshift(css); | ||
| return; | ||
| } | ||
| if (RUNTIME_DISABLED) return; | ||
| if (!isBrowser) return; | ||
| const el = getStyleElement(); | ||
| const sheet = el.sheet; | ||
| if (sheet) { | ||
| try { | ||
| sheet.insertRule(css, 0); | ||
| } catch { | ||
| el.insertBefore(document.createTextNode(`${css} | ||
| `), el.firstChild); | ||
| } | ||
| } else { | ||
| el.insertBefore(document.createTextNode(`${css} | ||
| `), el.firstChild); | ||
| } | ||
| } | ||
| function insertRule(key, css) { | ||
| if (insertedRules.has(key)) { | ||
| const prev = ruleCssByKey.get(key); | ||
| if (prev != null && prev !== css) { | ||
| warnIfDuplicateRuleKeyConflict(key, prev, css); | ||
| } | ||
| return; | ||
| } | ||
| insertedRules.add(key); | ||
| ruleCssByKey.set(key, css); | ||
| allRules.push(css); | ||
| if (RUNTIME_DISABLED && !ssrBuffer) return; | ||
| pendingRules.push(css); | ||
| scheduleFlush(); | ||
| } | ||
| function insertRules(rules) { | ||
| let added = false; | ||
| for (const { key, css } of rules) { | ||
| if (insertedRules.has(key)) { | ||
| const prev = ruleCssByKey.get(key); | ||
| if (prev != null && prev !== css) { | ||
| warnIfDuplicateRuleKeyConflict(key, prev, css); | ||
| } | ||
| continue; | ||
| } | ||
| insertedRules.add(key); | ||
| ruleCssByKey.set(key, css); | ||
| allRules.push(css); | ||
| if (!RUNTIME_DISABLED || ssrBuffer) { | ||
| pendingRules.push(css); | ||
| added = true; | ||
| } | ||
| } | ||
| if (added) scheduleFlush(); | ||
| } | ||
| function startCollection() { | ||
| ssrBuffer = []; | ||
| return () => { | ||
| const css = ssrBuffer ? ssrBuffer.join("\n") : ""; | ||
| ssrBuffer = null; | ||
| return css; | ||
| }; | ||
| } | ||
| function getRegisteredCss() { | ||
| return allRules.join("\n"); | ||
| } | ||
| function reset() { | ||
| insertedRules.clear(); | ||
| ruleCssByKey.clear(); | ||
| pendingRules = []; | ||
| allRules.length = 0; | ||
| flushScheduled = false; | ||
| ssrBuffer = null; | ||
| if (isBrowser && styleElement) { | ||
| styleElement.remove(); | ||
| styleElement = null; | ||
| } | ||
| } | ||
| function flushSync() { | ||
| flush(); | ||
| } | ||
| function invalidatePrefix(prefix) { | ||
| for (const key of insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix])); | ||
| if (!isBrowser) return; | ||
| const el = styleElement; | ||
| if (!el) return; | ||
| const sheet = el.sheet; | ||
| if (!sheet) return; | ||
| for (let i = sheet.cssRules.length - 1; i >= 0; i--) { | ||
| const rule = sheet.cssRules[i]; | ||
| if (ruleMatchesPrefix(rule, prefix)) { | ||
| sheet.deleteRule(i); | ||
| } | ||
| } | ||
| } | ||
| function invalidateKeys(keys, prefixes) { | ||
| for (const key of keys) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| } | ||
| for (const prefix of prefixes) { | ||
| for (const key of insertedRules) { | ||
| if (key.startsWith(prefix)) { | ||
| insertedRules.delete(key); | ||
| ruleCssByKey.delete(key); | ||
| } | ||
| } | ||
| } | ||
| releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes)); | ||
| if (!isBrowser) return; | ||
| const el = styleElement; | ||
| if (!el) return; | ||
| const sheet = el.sheet; | ||
| if (!sheet) return; | ||
| const keySet = new Set(keys); | ||
| for (let i = sheet.cssRules.length - 1; i >= 0; i--) { | ||
| const rule = sheet.cssRules[i]; | ||
| let shouldRemove = false; | ||
| for (const prefix of prefixes) { | ||
| if (ruleMatchesPrefix(rule, prefix)) { | ||
| shouldRemove = true; | ||
| break; | ||
| } | ||
| } | ||
| if (!shouldRemove) { | ||
| const ruleText = rule.cssText; | ||
| for (const key of keySet) { | ||
| if (ruleMatchesKey(ruleText, key)) { | ||
| shouldRemove = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (shouldRemove) { | ||
| sheet.deleteRule(i); | ||
| } | ||
| } | ||
| } | ||
| function invalidateComponentNamespaceForDev(namespace) { | ||
| const selectorInfix = `.${namespace}-`; | ||
| const keysToDrop = []; | ||
| for (const k of insertedRules) { | ||
| if (k.includes(selectorInfix)) { | ||
| keysToDrop.push(k); | ||
| } | ||
| } | ||
| invalidateKeys(keysToDrop, [selectorInfix]); | ||
| } | ||
| function ruleMatchesPrefix(rule, prefix) { | ||
| if (prefix.startsWith("font-face:")) { | ||
| const family = prefix.slice("font-face:".length).split(":")[0]; | ||
| if (rule.cssText.includes("@font-face")) { | ||
| return rule.cssText.includes(`"${family}"`) || rule.cssText.includes(`'${family}'`); | ||
| } | ||
| return false; | ||
| } | ||
| if ("selectorText" in rule) { | ||
| return rule.selectorText.startsWith(prefix); | ||
| } | ||
| if ("name" in rule && prefix.startsWith("keyframes:")) { | ||
| return rule.name === prefix.slice("keyframes:".length); | ||
| } | ||
| if ("cssRules" in rule) { | ||
| const innerRules = rule.cssRules; | ||
| for (let i = 0; i < innerRules.length; i++) { | ||
| if (ruleMatchesPrefix(innerRules[i], prefix)) return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| function ruleMatchesKey(cssText, key) { | ||
| if (key.startsWith("tokens:")) { | ||
| const rest = key.slice("tokens:".length); | ||
| const at = rest.lastIndexOf("@"); | ||
| const namespace = at === -1 ? rest : rest.slice(0, at); | ||
| return cssText.includes(`:root`) && cssText.includes(`--${namespace}-`); | ||
| } | ||
| if (key.startsWith("theme:")) { | ||
| const name = key.slice("theme:".length); | ||
| return cssText.includes(`.theme-${name}`); | ||
| } | ||
| if (key.startsWith("keyframes:")) { | ||
| const name = key.slice("keyframes:".length); | ||
| return cssText.includes(`@keyframes ${name}`); | ||
| } | ||
| return false; | ||
| } | ||
| export { ensureDocumentStylesAttached, flushSync, getRegisteredCss, insertRule, insertRules, invalidateComponentNamespaceForDev, invalidateKeys, invalidatePrefix, registerCascadeLayerOrder, registeredNamespaces, reset, startCollection }; | ||
| //# sourceMappingURL=chunk-G6ATUNEZ.js.map | ||
| //# sourceMappingURL=chunk-G6ATUNEZ.js.map |
| {"version":3,"sources":["../src/registry.ts","../src/sheet.ts"],"names":[],"mappings":"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","file":"chunk-G6ATUNEZ.js","sourcesContent":["/**\n * Shared registry for detecting duplicate namespace registrations.\n */\nexport const registeredNamespaces = new Set<string>();\n\nconst COLON = ':';\n\n/**\n * Drop reserved `scopeId:namespace` keys so a module can re-register after HMR.\n * `namespace` is the first argument to `styles.component()` / `styles.class()` (not the scope).\n */\nexport function releaseReservedNamespacesForComponentOrClassNames(\n namespaces: readonly string[],\n): void {\n if (namespaces.length === 0) return;\n const wanted = new Set(namespaces);\n const toRemove: string[] = [];\n for (const key of registeredNamespaces) {\n const i = key.indexOf(COLON);\n if (i === -1) continue;\n if (wanted.has(key.slice(i + 1))) {\n toRemove.push(key);\n }\n }\n for (const key of toRemove) {\n registeredNamespaces.delete(key);\n }\n}\n\n/** Vite plugin passes `.${namespace}-` prefixes for `styles.component()` invalidation. */\nexport function namespacesFromTypestylesHmrPrefixes(prefixes: readonly string[]): string[] {\n const out: string[] = [];\n for (const p of prefixes) {\n if (p.length >= 2 && p.startsWith('.') && p.endsWith('-')) {\n out.push(p.slice(1, -1));\n }\n }\n return out;\n}\n","import {\n namespacesFromTypestylesHmrPrefixes,\n releaseReservedNamespacesForComponentOrClassNames,\n} from './registry';\n\nconst 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 * Last emitted CSS per dedupe key (see {@link warnIfDuplicateRuleKeyConflict}).\n * Cleared with {@link reset} and kept in sync when keys are invalidated.\n */\nconst ruleCssByKey = new Map<string, string>();\n\nfunction duplicateRuleKeyConflictWarningsEnabled(): boolean {\n if (typeof process === 'undefined') return true;\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * When the same key is registered again with different CSS, the second rule is skipped\n * (idempotency / HMR). In non-production builds, surface that so overlapping globals\n * (e.g. reset `body` + app `body` in the same scope) are not silent failures.\n */\nfunction warnIfDuplicateRuleKeyConflict(\n key: string,\n previousCss: string,\n ignoredCss: string,\n): void {\n if (!duplicateRuleKeyConflictWarningsEnabled()) return;\n const prevShort = previousCss.length > 220 ? `${previousCss.slice(0, 220)}…` : previousCss;\n const nextShort = ignoredCss.length > 220 ? `${ignoredCss.slice(0, 220)}…` : ignoredCss;\n console.warn(\n `[typestyles] Skipped a rule: dedupe key \"${key}\" already exists with different CSS. ` +\n `Only the first registration is kept. For globals, merge into one \\`global.style\\`, ` +\n `or use a distinct selector (e.g. \\`html body\\` after reset’s \\`body\\`).\\n` +\n ` Existing: ${prevShort}\\n` +\n ` Skipped: ${nextShort}`,\n );\n}\n\n/**\n * Whether runtime DOM insertion is disabled (for build-time/zero-runtime mode).\n * The Vite plugin (mode: 'build') defines __TYPESTYLES_RUNTIME_DISABLED__ as the\n * string \"true\" at build time, so this is true in production and no <style> is created.\n *\n * `@typestyles/next/build` `withTypestylesExtract` sets `NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED`\n * via `next.config` `env` so Turbopack and webpack both inline the flag (DefinePlugin\n * alone does not run under Turbopack).\n */\ndeclare const __TYPESTYLES_RUNTIME_DISABLED__: string | undefined;\nfunction readNextPublicRuntimeDisabled(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env.NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED === 'true';\n}\nconst RUNTIME_DISABLED =\n (typeof __TYPESTYLES_RUNTIME_DISABLED__ !== 'undefined' &&\n __TYPESTYLES_RUNTIME_DISABLED__ === 'true') ||\n readNextPublicRuntimeDisabled();\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 = typeof document !== 'undefined' && typeof window !== 'undefined';\n\n/**\n * Re-insert every registered rule into a (usually fresh) <style> element.\n * Used when the live element was detached (e.g. Astro view transitions replacing <head>).\n */\nfunction writeAllRulesToStyleElement(el: HTMLStyleElement): void {\n if (RUNTIME_DISABLED || allRules.length === 0) return;\n const sheet = el.sheet;\n if (sheet) {\n for (const css of allRules) {\n try {\n sheet.insertRule(css, sheet.cssRules.length);\n } catch {\n el.appendChild(document.createTextNode(css));\n }\n }\n } else {\n el.appendChild(document.createTextNode(allRules.join('\\n')));\n }\n}\n\nfunction getStyleElement(): HTMLStyleElement {\n let reconnectAfterDetach = false;\n if (styleElement && !styleElement.isConnected) {\n reconnectAfterDetach = true;\n styleElement = null;\n }\n if (styleElement) return styleElement;\n\n // Prefer an element actually in the document (SSR or another copy on the page).\n const existing = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (existing?.isConnected) {\n styleElement = existing;\n return styleElement;\n }\n\n styleElement = document.createElement('style');\n styleElement.id = STYLE_ELEMENT_ID;\n document.head.appendChild(styleElement);\n\n // After a doc swap, we have a new empty sheet but insertRule() won't re-queue (deduped keys).\n if (reconnectAfterDetach && allRules.length > 0) {\n writeAllRulesToStyleElement(styleElement);\n }\n\n return styleElement;\n}\n\n/**\n * Ensure the managed <style id=\"typestyles\"> is attached to the current document and populated.\n * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled.\n */\nexport function ensureDocumentStylesAttached(): void {\n if (!isBrowser || RUNTIME_DISABLED) return;\n getStyleElement();\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 || RUNTIME_DISABLED) 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 && !RUNTIME_DISABLED) {\n // Use microtask for fast, batched insertion\n queueMicrotask(flush);\n }\n}\n\n/**\n * Register a single `@layer a, b, c;` preamble so layer **order** is defined before any\n * `@layer name { … }` blocks. Inserts at the front of the virtual sheet and at CSSOM index 0\n * when injecting into the document.\n */\nexport function registerCascadeLayerOrder(preambleKey: string, css: string): void {\n const key = `typestyles:@layer-order:${preambleKey}`;\n if (insertedRules.has(key)) return;\n insertedRules.add(key);\n\n allRules.unshift(css);\n\n if (ssrBuffer) {\n ssrBuffer.unshift(css);\n return;\n }\n\n if (RUNTIME_DISABLED) return;\n\n if (!isBrowser) return;\n\n const el = getStyleElement();\n const sheet = el.sheet;\n if (sheet) {\n try {\n sheet.insertRule(css, 0);\n } catch {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\n }\n } else {\n el.insertBefore(document.createTextNode(`${css}\\n`), el.firstChild);\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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n return;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (RUNTIME_DISABLED && !ssrBuffer) return;\n pendingRules.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)) {\n const prev = ruleCssByKey.get(key);\n if (prev != null && prev !== css) {\n warnIfDuplicateRuleKeyConflict(key, prev, css);\n }\n continue;\n }\n insertedRules.add(key);\n ruleCssByKey.set(key, css);\n allRules.push(css);\n if (!RUNTIME_DISABLED || ssrBuffer) {\n pendingRules.push(css);\n added = true;\n }\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 || RUNTIME_DISABLED) return;\n\n insertedRules.delete(key);\n ruleCssByKey.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.component`, `styles.class`, `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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes([prefix]));\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 ruleCssByKey.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 ruleCssByKey.delete(key);\n }\n }\n }\n\n releaseReservedNamespacesForComponentOrClassNames(namespacesFromTypestylesHmrPrefixes(prefixes));\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\n/**\n * Drop every rule key tied to a `styles.component('namespace', …)` registration, including\n * `@layer`-wrapped keys (`layer:….:.namespace-…`), and release reserved namespace entries.\n * Used for Vite HMR and for dev recovery when a module re-runs before `hot.dispose`.\n */\nexport function invalidateComponentNamespaceForDev(namespace: string): void {\n const selectorInfix = `.${namespace}-`;\n const keysToDrop: string[] = [];\n for (const k of insertedRules) {\n if (k.includes(selectorInfix)) {\n keysToDrop.push(k);\n }\n }\n invalidateKeys(keysToDrop, [selectorInfix]);\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 rule.cssText.includes(`\"${family}\"`) || rule.cssText.includes(`'${family}'`);\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 or tokens:color@layerName -> :root rule with --color- custom properties\n const rest = key.slice('tokens:'.length);\n const at = rest.lastIndexOf('@');\n const namespace = at === -1 ? rest : rest.slice(0, at);\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"]} |
| import * as CSS from 'csstype'; | ||
| /** | ||
| * A CSS value that can be a standard value or a token reference (var() string). | ||
| * | ||
| * Values are emitted verbatim. TypeScript does **not** validate CSS syntax, so a typo in | ||
| * `calc()`, `clamp()`, `min()`, `max()`, `url()`, etc. (for example a missing `)`) can produce | ||
| * invalid CSS that breaks parsing for following rules. Use **`calc`** (tagged template) and | ||
| * **`clamp`** from `typestyles` to keep function parentheses balanced, or small named helpers; | ||
| * see the docs “TypeScript Tips” page. | ||
| */ | ||
| type CSSValue = string | number; | ||
| /** | ||
| * CSS properties with support for nested selectors and at-rules. | ||
| * Extends csstype's Properties with nesting capabilities. | ||
| * | ||
| * For `@…` keys, **`container()`** / **`styles.container()`** infer a **literal** `@container …` template so | ||
| * `[container({ minWidth: 400 })]` mixes with longhands without casting. For **dynamic** `@…` strings, spread | ||
| * **`atRuleBlock` / `styles.atRuleBlock`**. Same idea for **`has` / `is` / `where`**: variadic literals narrow | ||
| * to `&:…` keys; if the key is only known as `string`, spread a one-key object or use `atRuleBlock`. | ||
| * | ||
| * **`@supports`** uses the same `` `@${string}` `` / `atRuleBlock` path; a first-class **`supports()`** helper | ||
| * (mirroring `container()`) would improve literals and authoring ergonomics for feature queries. | ||
| */ | ||
| interface CSSProperties extends CSS.Properties<CSSValue> { | ||
| /** Nested selector (e.g., '&:hover', `has('.x')`, '& .child', '&::before', '&[data-variant]') */ | ||
| [selector: `&${string}`]: CSSProperties; | ||
| /** | ||
| * Ancestor-prefixed selector where `&` is the styled element (e.g. `html[data-mode="dark"] &`, | ||
| * `html:not([data-mode="light"]) &`). Runtime serialization replaces every `&` with the class selector. | ||
| */ | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSProperties; | ||
| /** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */ | ||
| [attribute: `[${string}]`]: CSSProperties; | ||
| /** | ||
| * At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports'). | ||
| * TODO(typestyles): `supports()` helper for @supports (mirror `container()` literals and typing). | ||
| */ | ||
| [atRule: `@${string}`]: CSSProperties; | ||
| } | ||
| /** | ||
| * Utility function map used by `createStyles({ utils })` and `styles.withUtils()`. | ||
| * Each key becomes an extra style property that expands into CSSProperties. | ||
| */ | ||
| type BivariantCallback<Arg, Ret> = { | ||
| bivarianceHack(value: Arg): Ret; | ||
| }['bivarianceHack']; | ||
| type StyleUtils = Record<string, BivariantCallback<unknown, CSSProperties>>; | ||
| type UtilityValue<U extends StyleUtils, K extends keyof U> = U[K] extends (value: infer V) => CSSProperties ? V : never; | ||
| /** | ||
| * CSS properties augmented with user-defined utility keys. | ||
| */ | ||
| type CSSPropertiesWithUtils<U extends StyleUtils> = CSS.Properties<CSSValue> & { | ||
| [K in keyof U]?: UtilityValue<U, K>; | ||
| } & { | ||
| [selector: `&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [attribute: `[${string}]`]: CSSPropertiesWithUtils<U>; | ||
| /** @see {@link CSSProperties} at-rule index signature (TODO: `supports()` helper). */ | ||
| [atRule: `@${string}`]: CSSPropertiesWithUtils<U>; | ||
| }; | ||
| /** | ||
| * A map of style names to utility-aware CSS property definitions. | ||
| */ | ||
| type StyleDefinitionsWithUtils<U extends StyleUtils> = Record<string, CSSPropertiesWithUtils<U>>; | ||
| /** | ||
| * A map of variant names to their CSS property definitions. | ||
| */ | ||
| type StyleDefinitions = Record<string, CSSProperties>; | ||
| /** | ||
| * A token value can be a string/number or a nested object of token values. | ||
| * Supports arbitrarily deep nesting for hierarchical token structures. | ||
| */ | ||
| type TokenValues = string | number | { | ||
| [key: string]: TokenValues; | ||
| }; | ||
| /** | ||
| * A flattened key-value pair for CSS custom property generation. | ||
| */ | ||
| type FlatTokenEntry = [key: string, value: string]; | ||
| /** | ||
| * Flattens a nested TokenValues object into an array of [key, value] pairs. | ||
| * Deeply nested objects are flattened with keys joined by hyphens. | ||
| * | ||
| * @example | ||
| * flattenTokens({ text: { primary: '#000' } }) | ||
| * // => [['text-primary', '#000']] | ||
| */ | ||
| declare function flattenTokenEntries(obj: TokenValues, prefix?: string): FlatTokenEntry[]; | ||
| /** | ||
| * A typed token reference object. Property access returns var(--namespace-key). | ||
| * Supports nested access: token.text.primary => var(--namespace-text-primary) | ||
| */ | ||
| type TokenRef<T extends TokenValues> = T extends string | number ? string : { | ||
| readonly [K in keyof T]: T[K] extends TokenValues ? TokenRef<T[K]> : string; | ||
| }; | ||
| /** | ||
| * Nested token values where any object level may omit keys (for mode layers that | ||
| * only tweak a subtree of `base`). | ||
| */ | ||
| type DeepPartialTokenValues = string | number | { | ||
| [key: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Theme overrides: namespaces map to full or deeply partial token trees. | ||
| * Aligns with `tokens.create` namespaces; mode `overrides` often only set a subset of keys. | ||
| */ | ||
| type ThemeOverrides = { | ||
| [namespace: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Keyframe stops: 'from', 'to', or percentage strings mapped to CSS properties. | ||
| */ | ||
| type KeyframeStops = Record<string, CSSProperties>; | ||
| /** Match a media query (e.g. `(prefers-color-scheme: dark)`). */ | ||
| type ThemeConditionMedia = { | ||
| readonly type: 'media'; | ||
| readonly query: string; | ||
| }; | ||
| /** Match an attribute on the themed element (`self`) or an ancestor (`ancestor`). */ | ||
| type ThemeConditionAttr = { | ||
| readonly type: 'attr'; | ||
| readonly name: string; | ||
| readonly value: string; | ||
| readonly scope: 'self' | 'ancestor'; | ||
| }; | ||
| /** Match a class on the themed element (`self`) or an ancestor (`ancestor`). */ | ||
| type ThemeConditionClass = { | ||
| readonly type: 'class'; | ||
| readonly name: string; | ||
| readonly scope: 'self' | 'ancestor'; | ||
| }; | ||
| /** Raw selector escape hatch — the selector is used as an ancestor context for the theme class. */ | ||
| type ThemeConditionSelector = { | ||
| readonly type: 'selector'; | ||
| readonly selector: string; | ||
| }; | ||
| /** All child conditions must hold. */ | ||
| type ThemeConditionAnd = { | ||
| readonly type: 'and'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Any child condition must hold (emits separate rules per branch). */ | ||
| type ThemeConditionOr = { | ||
| readonly type: 'or'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Negate a single-branch condition (see `tokens.when.not` JSDoc for limits). */ | ||
| type ThemeConditionNot = { | ||
| readonly type: 'not'; | ||
| readonly condition: ThemeCondition; | ||
| }; | ||
| /** | ||
| * A condition that determines **when** a set of token overrides applies. | ||
| * Conditions compile to media queries, selector prefixes/suffixes, or combinations. | ||
| */ | ||
| type ThemeCondition = ThemeConditionMedia | ThemeConditionAttr | ThemeConditionClass | ThemeConditionSelector | ThemeConditionAnd | ThemeConditionOr | ThemeConditionNot; | ||
| /** | ||
| * A single mode layer within a theme surface. | ||
| * Applies `overrides` when `when` is satisfied. | ||
| */ | ||
| type ThemeModeDefinition = { | ||
| readonly id: string; | ||
| readonly overrides: ThemeOverrides; | ||
| readonly when: ThemeCondition; | ||
| }; | ||
| /** | ||
| * Configuration for `tokens.createTheme()`. | ||
| * Provide `modes` (manual) **or** `colorMode` (preset), not both. | ||
| */ | ||
| type ThemeConfig = { | ||
| /** Base token overrides — emitted as `.theme-{name} { … }`. */ | ||
| base?: ThemeOverrides; | ||
| /** Manual mode layers with explicit conditions. Mutually exclusive with `colorMode`. */ | ||
| modes?: ThemeModeDefinition[]; | ||
| /** Preset mode layers from `tokens.colorMode.*`. Mutually exclusive with `modes`. */ | ||
| colorMode?: ThemeModeDefinition[]; | ||
| }; | ||
| /** | ||
| * The object returned by `tokens.createTheme()`. | ||
| * | ||
| * - `surface.className` — the generated class name (e.g. `"theme-acme"`) | ||
| * - `surface.name` — the theme name (e.g. `"acme"`) | ||
| * - `String(surface)` / template interpolation — coerces to `className` | ||
| */ | ||
| interface ThemeSurface { | ||
| readonly className: string; | ||
| readonly name: string; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * Styles for a single variant option (or slot variant block). | ||
| * Union with a permissive record so **`[v.name]: value`** from {@link ComponentInternalVarRef} | ||
| * (custom properties) infers as `{ [key: string]: … }` and still matches — that shape is not | ||
| * assignable to {@link CSSProperties} alone, which would otherwise reject the dimensioned overload | ||
| * and fall through to unrelated `component` overloads. **`Record<string, unknown>`** also covers | ||
| * objects that mix custom-property keys with nested selector blocks like `'&:hover'`. | ||
| */ | ||
| type VariantOptionStyle = CSSProperties | Record<string, unknown>; | ||
| /** | ||
| * A map of variant dimensions to their options (each option is {@link VariantOptionStyle}). | ||
| */ | ||
| type VariantDefinitions = Record<string, Record<string, VariantOptionStyle>>; | ||
| type SlotStyles<S extends string> = Partial<Record<S, VariantOptionStyle>>; | ||
| type SlotVariantDefinitions<S extends string> = Record<string, Record<string, SlotStyles<S>>>; | ||
| type VariantDimensions = Record<string, Record<string, unknown>>; | ||
| type VariantOptionKey<V extends VariantDimensions, K extends keyof V> = Extract<keyof V[K], string>; | ||
| type VariantSelectionValue<OptionKey extends string> = OptionKey | (Extract<OptionKey, 'true'> extends never ? never : true) | (Extract<OptionKey, 'false'> extends never ? never : false); | ||
| type CompoundSelectionValue<OptionKey extends string> = VariantSelectionValue<OptionKey> | readonly VariantSelectionValue<OptionKey>[]; | ||
| type ComponentSelections<V extends VariantDimensions> = { | ||
| [K in keyof V]?: VariantSelectionValue<VariantOptionKey<V, K>> | null | undefined; | ||
| }; | ||
| /** | ||
| * A CSS custom property reference as a `var(--…)` value (tokens, `createVar()`, component internal vars). | ||
| */ | ||
| type CSSVarRef = `var(--${string})`; | ||
| /** | ||
| * Leaf shape for `ctx.vars({ … })` — mirrors typed tokens: `value` is the default (merged into `base`); | ||
| * optional `syntax` / `inherits` register `@property` like typed design tokens. | ||
| */ | ||
| type ComponentVarDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Nested map of component internal vars (same nesting as `tokens.create` / theme token trees). | ||
| */ | ||
| type ComponentVarNode = string | number | ComponentVarDescriptor | { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| type ComponentVarDefinitions = { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| /** | ||
| * Options for `ctx.var(id, options?)`. Set `value` to merge a default into `base` and as `@property` initial-value when `syntax` is set. | ||
| */ | ||
| type ComponentVarOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Reference to a component-scoped custom property: `.name` for declaration keys and transitions, `.var` for values. | ||
| */ | ||
| type ComponentInternalVarRef = { | ||
| readonly name: string; | ||
| readonly var: CSSVarRef; | ||
| }; | ||
| /** | ||
| * Context passed to `styles.component(namespace, (ctx) => { ... })` to declare internal custom properties. | ||
| */ | ||
| /** Proxy tree returned by `ctx.vars({ … })` — leaves are `{ name, var }`, nested objects are sub-trees. */ | ||
| type ComponentVarRefTree<T> = { | ||
| [K in keyof T]: T[K] extends ComponentVarDescriptor | string | number ? ComponentInternalVarRef : ComponentVarRefTree<T[K]>; | ||
| }; | ||
| type ComponentConfigContext = { | ||
| var: (id: string, options?: ComponentVarOptions) => ComponentInternalVarRef; | ||
| vars: <const T extends ComponentVarDefinitions>(definitions: T) => ComponentVarRefTree<T>; | ||
| }; | ||
| /** | ||
| * The full config object passed to styles.component() with dimensioned variants. | ||
| */ | ||
| type ComponentConfig<V extends VariantDefinitions> = { | ||
| base?: CSSProperties; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: VariantOptionStyle; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| /** | ||
| * Config for flat variants: `{ base: {...}, elevated: {...}, compact: {...} }`. | ||
| * Each key besides `base` is a boolean-style variant. | ||
| * | ||
| * **`variants`**, **`defaultVariants`**, **`compoundVariants`**, and **`slots`** are forbidden | ||
| * on this shape so TypeScript does not pick the flat overload for CVA-style or slot configs. | ||
| * Nested variant maps can otherwise satisfy {@link CSSProperties} too loosely (index signatures), | ||
| * which produced wrong callable types for `styles.component(ns, (ctx) => ({ variants: … }), { layer })` | ||
| * when cascade layers are enabled. | ||
| */ | ||
| type FlatComponentConfig<K extends string> = { | ||
| base?: CSSProperties; | ||
| variants?: never; | ||
| defaultVariants?: never; | ||
| compoundVariants?: never; | ||
| slots?: never; | ||
| } & Record<K, CSSProperties>; | ||
| /** | ||
| * Selection object for flat variants: `{ elevated: true, compact: true }`. | ||
| */ | ||
| type FlatComponentSelections<K extends string> = { | ||
| [P in K]?: boolean | null | undefined; | ||
| }; | ||
| /** | ||
| * All possible variant class string keys that can be destructured from a | ||
| * dimensioned component. Includes 'base' plus all `{dimension}-{option}` keys | ||
| * flattened from the variants config. | ||
| */ | ||
| type DimensionedVariantKeys<V extends VariantDefinitions> = { | ||
| [D in keyof V]: keyof V[D] extends string ? `${D & string}-${keyof V[D] & string}` : never; | ||
| }[keyof V]; | ||
| /** | ||
| * The CVA-style return for dimensioned variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type ComponentReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: ComponentSelections<V>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings, keyed as `{dimension}-{option}`. */ | ||
| readonly [K in DimensionedVariantKeys<V>]: string; | ||
| }; | ||
| /** | ||
| * The CVA-style return for flat variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type FlatComponentReturn<K extends string> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: FlatComponentSelections<Exclude<K, 'base'>>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings. */ | ||
| readonly [P in Exclude<K, 'base'>]: string; | ||
| }; | ||
| type MultiSlotConfig<Slots extends readonly string[]> = { | ||
| slots: Slots; | ||
| } & Partial<Record<Slots[number], CSSProperties>>; | ||
| type MultiSlotReturn<Slots extends readonly string[]> = { | ||
| (): Record<Slots[number], string>; | ||
| } & { | ||
| readonly [K in Slots[number]]: string; | ||
| }; | ||
| type SlotComponentConfig<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = { | ||
| slots: Slots; | ||
| base?: SlotStyles<Slots[number]>; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: SlotStyles<Slots[number]>; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| type SlotComponentFunction<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = (selections?: ComponentSelections<V>) => Record<Slots[number], string>; | ||
| /** | ||
| * Config for `styles.component` may be a plain object or a function that receives {@link ComponentConfigContext}. | ||
| */ | ||
| type ComponentConfigInput<V extends VariantDefinitions> = ComponentConfig<V> | ((ctx: ComponentConfigContext) => ComponentConfig<V>); | ||
| type FlatComponentConfigInput<K extends string> = FlatComponentConfig<K> | ((ctx: ComponentConfigContext) => FlatComponentConfig<K>); | ||
| type SlotComponentConfigInput<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = SlotComponentConfig<Slots, V> | ((ctx: ComponentConfigContext) => SlotComponentConfig<Slots, V>); | ||
| type MultiSlotConfigInput<Slots extends readonly string[]> = MultiSlotConfig<Slots> | ((ctx: ComponentConfigContext) => MultiSlotConfig<Slots>); | ||
| /** | ||
| * Extract the variant prop types from a ComponentReturn or ComponentFunction. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const button = styles.component('button', { | ||
| * variants: { | ||
| * intent: { primary: {...}, ghost: {...} }, | ||
| * size: { sm: {...}, lg: {...} }, | ||
| * }, | ||
| * }); | ||
| * | ||
| * type ButtonProps = ComponentVariants<typeof button>; | ||
| * // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' } | ||
| * ``` | ||
| */ | ||
| type ComponentVariants<T> = T extends (selections?: ComponentSelections<infer V>) => unknown ? { | ||
| [K in keyof V]?: keyof V[K]; | ||
| } : never; | ||
| /** | ||
| * `src` value for {@link FontFaceProps}: a single CSS `src` fragment or multiple | ||
| * fragments joined with commas (same as authoring `url(...), local(...)` by hand). | ||
| */ | ||
| type FontFaceSrc = string | readonly string[]; | ||
| /** | ||
| * Font face property declarations. | ||
| * | ||
| * Maps to standard `@font-face` descriptors. Values are emitted verbatim in CSS. | ||
| */ | ||
| type FontFaceProps = { | ||
| src: FontFaceSrc; | ||
| fontWeight?: string | number; | ||
| fontStyle?: 'normal' | 'italic' | 'oblique' | string; | ||
| fontDisplay?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'; | ||
| fontStretch?: string; | ||
| unicodeRange?: string; | ||
| /** `size-adjust` — fallback tuning and font-size-adjust related metrics. */ | ||
| sizeAdjust?: string; | ||
| /** `ascent-override` */ | ||
| ascentOverride?: string; | ||
| /** `descent-override` */ | ||
| descentOverride?: string; | ||
| /** `line-gap-override` */ | ||
| lineGapOverride?: string; | ||
| }; | ||
| /** | ||
| * Return type of helpers in `typestyles/globals`, passed to `global.style(…)`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * global.style(boxSizing()); | ||
| * global.style(body({ margin: 0 }, { layer: 'components' })); | ||
| * ``` | ||
| */ | ||
| type GlobalStyleTuple = readonly [selector: string, properties: CSSProperties] | readonly [selector: string, properties: CSSProperties, options: { | ||
| layer?: string; | ||
| }]; | ||
| export { type ComponentSelections as A, type ComponentVarDefinitions as B, type CSSProperties as C, type ComponentVarDescriptor as D, type ComponentVarNode as E, type FlatComponentConfigInput as F, type GlobalStyleTuple as G, type ComponentVarOptions as H, type ComponentVarRefTree as I, type ComponentVariants as J, type DeepPartialTokenValues as K, type FlatComponentConfig as L, type MultiSlotConfigInput as M, type FlatComponentSelections as N, type FlatTokenEntry as O, type FontFaceSrc as P, type KeyframeStops as Q, type SlotComponentConfig as R, type StyleUtils as S, type ThemeConditionMedia as T, type SlotStyles as U, type VariantDefinitions as V, type StyleDefinitions as W, type StyleDefinitionsWithUtils as X, type ThemeConditionNot as Y, type VariantOptionStyle as Z, flattenTokenEntries as _, type ThemeConditionAttr as a, type ThemeConditionClass as b, type ThemeConditionSelector as c, type ThemeCondition as d, type ThemeConditionAnd as e, type ThemeConditionOr as f, type ThemeOverrides as g, type ThemeModeDefinition as h, type ThemeSurface as i, type ThemeConfig as j, type TokenValues as k, type TokenRef as l, type ComponentConfigInput as m, type ComponentReturn as n, type FlatComponentReturn as o, type SlotVariantDefinitions as p, type SlotComponentConfigInput as q, type SlotComponentFunction as r, type MultiSlotReturn as s, type CSSPropertiesWithUtils as t, type FontFaceProps as u, type CSSVarRef as v, type CSSValue as w, type ComponentConfig as x, type ComponentConfigContext as y, type ComponentInternalVarRef as z }; |
| import * as CSS from 'csstype'; | ||
| /** | ||
| * A CSS value that can be a standard value or a token reference (var() string). | ||
| * | ||
| * Values are emitted verbatim. TypeScript does **not** validate CSS syntax, so a typo in | ||
| * `calc()`, `clamp()`, `min()`, `max()`, `url()`, etc. (for example a missing `)`) can produce | ||
| * invalid CSS that breaks parsing for following rules. Use **`calc`** (tagged template) and | ||
| * **`clamp`** from `typestyles` to keep function parentheses balanced, or small named helpers; | ||
| * see the docs “TypeScript Tips” page. | ||
| */ | ||
| type CSSValue = string | number; | ||
| /** | ||
| * CSS properties with support for nested selectors and at-rules. | ||
| * Extends csstype's Properties with nesting capabilities. | ||
| * | ||
| * For `@…` keys, **`container()`** / **`styles.container()`** infer a **literal** `@container …` template so | ||
| * `[container({ minWidth: 400 })]` mixes with longhands without casting. For **dynamic** `@…` strings, spread | ||
| * **`atRuleBlock` / `styles.atRuleBlock`**. Same idea for **`has` / `is` / `where`**: variadic literals narrow | ||
| * to `&:…` keys; if the key is only known as `string`, spread a one-key object or use `atRuleBlock`. | ||
| * | ||
| * **`@supports`** uses the same `` `@${string}` `` / `atRuleBlock` path; a first-class **`supports()`** helper | ||
| * (mirroring `container()`) would improve literals and authoring ergonomics for feature queries. | ||
| */ | ||
| interface CSSProperties extends CSS.Properties<CSSValue> { | ||
| /** Nested selector (e.g., '&:hover', `has('.x')`, '& .child', '&::before', '&[data-variant]') */ | ||
| [selector: `&${string}`]: CSSProperties; | ||
| /** | ||
| * Ancestor-prefixed selector where `&` is the styled element (e.g. `html[data-mode="dark"] &`, | ||
| * `html:not([data-mode="light"]) &`). Runtime serialization replaces every `&` with the class selector. | ||
| */ | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSProperties; | ||
| /** Attribute selector (e.g., '[data-variant]', '[data-variant="primary"]', '[disabled]') */ | ||
| [attribute: `[${string}]`]: CSSProperties; | ||
| /** | ||
| * At-rule (e.g., '@media (max-width: 768px)', '@container', '@supports'). | ||
| * TODO(typestyles): `supports()` helper for @supports (mirror `container()` literals and typing). | ||
| */ | ||
| [atRule: `@${string}`]: CSSProperties; | ||
| } | ||
| /** | ||
| * Utility function map used by `createStyles({ utils })` and `styles.withUtils()`. | ||
| * Each key becomes an extra style property that expands into CSSProperties. | ||
| */ | ||
| type BivariantCallback<Arg, Ret> = { | ||
| bivarianceHack(value: Arg): Ret; | ||
| }['bivarianceHack']; | ||
| type StyleUtils = Record<string, BivariantCallback<unknown, CSSProperties>>; | ||
| type UtilityValue<U extends StyleUtils, K extends keyof U> = U[K] extends (value: infer V) => CSSProperties ? V : never; | ||
| /** | ||
| * CSS properties augmented with user-defined utility keys. | ||
| */ | ||
| type CSSPropertiesWithUtils<U extends StyleUtils> = CSS.Properties<CSSValue> & { | ||
| [K in keyof U]?: UtilityValue<U, K>; | ||
| } & { | ||
| [selector: `&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [selectorWithAncestor: `${string}&${string}`]: CSSPropertiesWithUtils<U>; | ||
| [attribute: `[${string}]`]: CSSPropertiesWithUtils<U>; | ||
| /** @see {@link CSSProperties} at-rule index signature (TODO: `supports()` helper). */ | ||
| [atRule: `@${string}`]: CSSPropertiesWithUtils<U>; | ||
| }; | ||
| /** | ||
| * A map of style names to utility-aware CSS property definitions. | ||
| */ | ||
| type StyleDefinitionsWithUtils<U extends StyleUtils> = Record<string, CSSPropertiesWithUtils<U>>; | ||
| /** | ||
| * A map of variant names to their CSS property definitions. | ||
| */ | ||
| type StyleDefinitions = Record<string, CSSProperties>; | ||
| /** | ||
| * A token value can be a string/number or a nested object of token values. | ||
| * Supports arbitrarily deep nesting for hierarchical token structures. | ||
| */ | ||
| type TokenValues = string | number | { | ||
| [key: string]: TokenValues; | ||
| }; | ||
| /** | ||
| * A flattened key-value pair for CSS custom property generation. | ||
| */ | ||
| type FlatTokenEntry = [key: string, value: string]; | ||
| /** | ||
| * Flattens a nested TokenValues object into an array of [key, value] pairs. | ||
| * Deeply nested objects are flattened with keys joined by hyphens. | ||
| * | ||
| * @example | ||
| * flattenTokens({ text: { primary: '#000' } }) | ||
| * // => [['text-primary', '#000']] | ||
| */ | ||
| declare function flattenTokenEntries(obj: TokenValues, prefix?: string): FlatTokenEntry[]; | ||
| /** | ||
| * A typed token reference object. Property access returns var(--namespace-key). | ||
| * Supports nested access: token.text.primary => var(--namespace-text-primary) | ||
| */ | ||
| type TokenRef<T extends TokenValues> = T extends string | number ? string : { | ||
| readonly [K in keyof T]: T[K] extends TokenValues ? TokenRef<T[K]> : string; | ||
| }; | ||
| /** | ||
| * Nested token values where any object level may omit keys (for mode layers that | ||
| * only tweak a subtree of `base`). | ||
| */ | ||
| type DeepPartialTokenValues = string | number | { | ||
| [key: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Theme overrides: namespaces map to full or deeply partial token trees. | ||
| * Aligns with `tokens.create` namespaces; mode `overrides` often only set a subset of keys. | ||
| */ | ||
| type ThemeOverrides = { | ||
| [namespace: string]: DeepPartialTokenValues | undefined; | ||
| }; | ||
| /** | ||
| * Keyframe stops: 'from', 'to', or percentage strings mapped to CSS properties. | ||
| */ | ||
| type KeyframeStops = Record<string, CSSProperties>; | ||
| /** Match a media query (e.g. `(prefers-color-scheme: dark)`). */ | ||
| type ThemeConditionMedia = { | ||
| readonly type: 'media'; | ||
| readonly query: string; | ||
| }; | ||
| /** Match an attribute on the themed element (`self`) or an ancestor (`ancestor`). */ | ||
| type ThemeConditionAttr = { | ||
| readonly type: 'attr'; | ||
| readonly name: string; | ||
| readonly value: string; | ||
| readonly scope: 'self' | 'ancestor'; | ||
| }; | ||
| /** Match a class on the themed element (`self`) or an ancestor (`ancestor`). */ | ||
| type ThemeConditionClass = { | ||
| readonly type: 'class'; | ||
| readonly name: string; | ||
| readonly scope: 'self' | 'ancestor'; | ||
| }; | ||
| /** Raw selector escape hatch — the selector is used as an ancestor context for the theme class. */ | ||
| type ThemeConditionSelector = { | ||
| readonly type: 'selector'; | ||
| readonly selector: string; | ||
| }; | ||
| /** All child conditions must hold. */ | ||
| type ThemeConditionAnd = { | ||
| readonly type: 'and'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Any child condition must hold (emits separate rules per branch). */ | ||
| type ThemeConditionOr = { | ||
| readonly type: 'or'; | ||
| readonly conditions: readonly ThemeCondition[]; | ||
| }; | ||
| /** Negate a single-branch condition (see `tokens.when.not` JSDoc for limits). */ | ||
| type ThemeConditionNot = { | ||
| readonly type: 'not'; | ||
| readonly condition: ThemeCondition; | ||
| }; | ||
| /** | ||
| * A condition that determines **when** a set of token overrides applies. | ||
| * Conditions compile to media queries, selector prefixes/suffixes, or combinations. | ||
| */ | ||
| type ThemeCondition = ThemeConditionMedia | ThemeConditionAttr | ThemeConditionClass | ThemeConditionSelector | ThemeConditionAnd | ThemeConditionOr | ThemeConditionNot; | ||
| /** | ||
| * A single mode layer within a theme surface. | ||
| * Applies `overrides` when `when` is satisfied. | ||
| */ | ||
| type ThemeModeDefinition = { | ||
| readonly id: string; | ||
| readonly overrides: ThemeOverrides; | ||
| readonly when: ThemeCondition; | ||
| }; | ||
| /** | ||
| * Configuration for `tokens.createTheme()`. | ||
| * Provide `modes` (manual) **or** `colorMode` (preset), not both. | ||
| */ | ||
| type ThemeConfig = { | ||
| /** Base token overrides — emitted as `.theme-{name} { … }`. */ | ||
| base?: ThemeOverrides; | ||
| /** Manual mode layers with explicit conditions. Mutually exclusive with `colorMode`. */ | ||
| modes?: ThemeModeDefinition[]; | ||
| /** Preset mode layers from `tokens.colorMode.*`. Mutually exclusive with `modes`. */ | ||
| colorMode?: ThemeModeDefinition[]; | ||
| }; | ||
| /** | ||
| * The object returned by `tokens.createTheme()`. | ||
| * | ||
| * - `surface.className` — the generated class name (e.g. `"theme-acme"`) | ||
| * - `surface.name` — the theme name (e.g. `"acme"`) | ||
| * - `String(surface)` / template interpolation — coerces to `className` | ||
| */ | ||
| interface ThemeSurface { | ||
| readonly className: string; | ||
| readonly name: string; | ||
| toString(): string; | ||
| [Symbol.toPrimitive](hint: string): string; | ||
| } | ||
| /** | ||
| * Styles for a single variant option (or slot variant block). | ||
| * Union with a permissive record so **`[v.name]: value`** from {@link ComponentInternalVarRef} | ||
| * (custom properties) infers as `{ [key: string]: … }` and still matches — that shape is not | ||
| * assignable to {@link CSSProperties} alone, which would otherwise reject the dimensioned overload | ||
| * and fall through to unrelated `component` overloads. **`Record<string, unknown>`** also covers | ||
| * objects that mix custom-property keys with nested selector blocks like `'&:hover'`. | ||
| */ | ||
| type VariantOptionStyle = CSSProperties | Record<string, unknown>; | ||
| /** | ||
| * A map of variant dimensions to their options (each option is {@link VariantOptionStyle}). | ||
| */ | ||
| type VariantDefinitions = Record<string, Record<string, VariantOptionStyle>>; | ||
| type SlotStyles<S extends string> = Partial<Record<S, VariantOptionStyle>>; | ||
| type SlotVariantDefinitions<S extends string> = Record<string, Record<string, SlotStyles<S>>>; | ||
| type VariantDimensions = Record<string, Record<string, unknown>>; | ||
| type VariantOptionKey<V extends VariantDimensions, K extends keyof V> = Extract<keyof V[K], string>; | ||
| type VariantSelectionValue<OptionKey extends string> = OptionKey | (Extract<OptionKey, 'true'> extends never ? never : true) | (Extract<OptionKey, 'false'> extends never ? never : false); | ||
| type CompoundSelectionValue<OptionKey extends string> = VariantSelectionValue<OptionKey> | readonly VariantSelectionValue<OptionKey>[]; | ||
| type ComponentSelections<V extends VariantDimensions> = { | ||
| [K in keyof V]?: VariantSelectionValue<VariantOptionKey<V, K>> | null | undefined; | ||
| }; | ||
| /** | ||
| * A CSS custom property reference as a `var(--…)` value (tokens, `createVar()`, component internal vars). | ||
| */ | ||
| type CSSVarRef = `var(--${string})`; | ||
| /** | ||
| * Leaf shape for `ctx.vars({ … })` — mirrors typed tokens: `value` is the default (merged into `base`); | ||
| * optional `syntax` / `inherits` register `@property` like typed design tokens. | ||
| */ | ||
| type ComponentVarDescriptor = { | ||
| value: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Nested map of component internal vars (same nesting as `tokens.create` / theme token trees). | ||
| */ | ||
| type ComponentVarNode = string | number | ComponentVarDescriptor | { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| type ComponentVarDefinitions = { | ||
| [key: string]: ComponentVarNode; | ||
| }; | ||
| /** | ||
| * Options for `ctx.var(id, options?)`. Set `value` to merge a default into `base` and as `@property` initial-value when `syntax` is set. | ||
| */ | ||
| type ComponentVarOptions = { | ||
| value?: string | number; | ||
| syntax?: string; | ||
| inherits?: boolean; | ||
| }; | ||
| /** | ||
| * Reference to a component-scoped custom property: `.name` for declaration keys and transitions, `.var` for values. | ||
| */ | ||
| type ComponentInternalVarRef = { | ||
| readonly name: string; | ||
| readonly var: CSSVarRef; | ||
| }; | ||
| /** | ||
| * Context passed to `styles.component(namespace, (ctx) => { ... })` to declare internal custom properties. | ||
| */ | ||
| /** Proxy tree returned by `ctx.vars({ … })` — leaves are `{ name, var }`, nested objects are sub-trees. */ | ||
| type ComponentVarRefTree<T> = { | ||
| [K in keyof T]: T[K] extends ComponentVarDescriptor | string | number ? ComponentInternalVarRef : ComponentVarRefTree<T[K]>; | ||
| }; | ||
| type ComponentConfigContext = { | ||
| var: (id: string, options?: ComponentVarOptions) => ComponentInternalVarRef; | ||
| vars: <const T extends ComponentVarDefinitions>(definitions: T) => ComponentVarRefTree<T>; | ||
| }; | ||
| /** | ||
| * The full config object passed to styles.component() with dimensioned variants. | ||
| */ | ||
| type ComponentConfig<V extends VariantDefinitions> = { | ||
| base?: CSSProperties; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: VariantOptionStyle; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| /** | ||
| * Config for flat variants: `{ base: {...}, elevated: {...}, compact: {...} }`. | ||
| * Each key besides `base` is a boolean-style variant. | ||
| * | ||
| * **`variants`**, **`defaultVariants`**, **`compoundVariants`**, and **`slots`** are forbidden | ||
| * on this shape so TypeScript does not pick the flat overload for CVA-style or slot configs. | ||
| * Nested variant maps can otherwise satisfy {@link CSSProperties} too loosely (index signatures), | ||
| * which produced wrong callable types for `styles.component(ns, (ctx) => ({ variants: … }), { layer })` | ||
| * when cascade layers are enabled. | ||
| */ | ||
| type FlatComponentConfig<K extends string> = { | ||
| base?: CSSProperties; | ||
| variants?: never; | ||
| defaultVariants?: never; | ||
| compoundVariants?: never; | ||
| slots?: never; | ||
| } & Record<K, CSSProperties>; | ||
| /** | ||
| * Selection object for flat variants: `{ elevated: true, compact: true }`. | ||
| */ | ||
| type FlatComponentSelections<K extends string> = { | ||
| [P in K]?: boolean | null | undefined; | ||
| }; | ||
| /** | ||
| * All possible variant class string keys that can be destructured from a | ||
| * dimensioned component. Includes 'base' plus all `{dimension}-{option}` keys | ||
| * flattened from the variants config. | ||
| */ | ||
| type DimensionedVariantKeys<V extends VariantDefinitions> = { | ||
| [D in keyof V]: keyof V[D] extends string ? `${D & string}-${keyof V[D] & string}` : never; | ||
| }[keyof V]; | ||
| /** | ||
| * The CVA-style return for dimensioned variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type ComponentReturn<V extends VariantDefinitions> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: ComponentSelections<V>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings, keyed as `{dimension}-{option}`. */ | ||
| readonly [K in DimensionedVariantKeys<V>]: string; | ||
| }; | ||
| /** | ||
| * The CVA-style return for flat variants. | ||
| * Callable as a function, destructurable as an object. | ||
| */ | ||
| type FlatComponentReturn<K extends string> = { | ||
| /** Call with variant selections to get composed class string (base always included). */ | ||
| (selections?: FlatComponentSelections<Exclude<K, 'base'>>): string; | ||
| } & { | ||
| /** The base class string. */ | ||
| readonly base: string; | ||
| } & { | ||
| /** Individual variant class strings. */ | ||
| readonly [P in Exclude<K, 'base'>]: string; | ||
| }; | ||
| type MultiSlotConfig<Slots extends readonly string[]> = { | ||
| slots: Slots; | ||
| } & Partial<Record<Slots[number], CSSProperties>>; | ||
| type MultiSlotReturn<Slots extends readonly string[]> = { | ||
| (): Record<Slots[number], string>; | ||
| } & { | ||
| readonly [K in Slots[number]]: string; | ||
| }; | ||
| type SlotComponentConfig<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = { | ||
| slots: Slots; | ||
| base?: SlotStyles<Slots[number]>; | ||
| variants?: V; | ||
| compoundVariants?: Array<{ | ||
| variants: { | ||
| [K in keyof V]?: CompoundSelectionValue<VariantOptionKey<V, K>>; | ||
| }; | ||
| style: SlotStyles<Slots[number]>; | ||
| }>; | ||
| defaultVariants?: ComponentSelections<V>; | ||
| }; | ||
| type SlotComponentFunction<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = (selections?: ComponentSelections<V>) => Record<Slots[number], string>; | ||
| /** | ||
| * Config for `styles.component` may be a plain object or a function that receives {@link ComponentConfigContext}. | ||
| */ | ||
| type ComponentConfigInput<V extends VariantDefinitions> = ComponentConfig<V> | ((ctx: ComponentConfigContext) => ComponentConfig<V>); | ||
| type FlatComponentConfigInput<K extends string> = FlatComponentConfig<K> | ((ctx: ComponentConfigContext) => FlatComponentConfig<K>); | ||
| type SlotComponentConfigInput<Slots extends readonly string[], V extends SlotVariantDefinitions<Slots[number]>> = SlotComponentConfig<Slots, V> | ((ctx: ComponentConfigContext) => SlotComponentConfig<Slots, V>); | ||
| type MultiSlotConfigInput<Slots extends readonly string[]> = MultiSlotConfig<Slots> | ((ctx: ComponentConfigContext) => MultiSlotConfig<Slots>); | ||
| /** | ||
| * Extract the variant prop types from a ComponentReturn or ComponentFunction. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const button = styles.component('button', { | ||
| * variants: { | ||
| * intent: { primary: {...}, ghost: {...} }, | ||
| * size: { sm: {...}, lg: {...} }, | ||
| * }, | ||
| * }); | ||
| * | ||
| * type ButtonProps = ComponentVariants<typeof button>; | ||
| * // { intent?: 'primary' | 'ghost'; size?: 'sm' | 'lg' } | ||
| * ``` | ||
| */ | ||
| type ComponentVariants<T> = T extends (selections?: ComponentSelections<infer V>) => unknown ? { | ||
| [K in keyof V]?: keyof V[K]; | ||
| } : never; | ||
| /** | ||
| * `src` value for {@link FontFaceProps}: a single CSS `src` fragment or multiple | ||
| * fragments joined with commas (same as authoring `url(...), local(...)` by hand). | ||
| */ | ||
| type FontFaceSrc = string | readonly string[]; | ||
| /** | ||
| * Font face property declarations. | ||
| * | ||
| * Maps to standard `@font-face` descriptors. Values are emitted verbatim in CSS. | ||
| */ | ||
| type FontFaceProps = { | ||
| src: FontFaceSrc; | ||
| fontWeight?: string | number; | ||
| fontStyle?: 'normal' | 'italic' | 'oblique' | string; | ||
| fontDisplay?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'; | ||
| fontStretch?: string; | ||
| unicodeRange?: string; | ||
| /** `size-adjust` — fallback tuning and font-size-adjust related metrics. */ | ||
| sizeAdjust?: string; | ||
| /** `ascent-override` */ | ||
| ascentOverride?: string; | ||
| /** `descent-override` */ | ||
| descentOverride?: string; | ||
| /** `line-gap-override` */ | ||
| lineGapOverride?: string; | ||
| }; | ||
| /** | ||
| * Return type of helpers in `typestyles/globals`, passed to `global.style(…)`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * global.style(boxSizing()); | ||
| * global.style(body({ margin: 0 }, { layer: 'components' })); | ||
| * ``` | ||
| */ | ||
| type GlobalStyleTuple = readonly [selector: string, properties: CSSProperties] | readonly [selector: string, properties: CSSProperties, options: { | ||
| layer?: string; | ||
| }]; | ||
| export { type ComponentSelections as A, type ComponentVarDefinitions as B, type CSSProperties as C, type ComponentVarDescriptor as D, type ComponentVarNode as E, type FlatComponentConfigInput as F, type GlobalStyleTuple as G, type ComponentVarOptions as H, type ComponentVarRefTree as I, type ComponentVariants as J, type DeepPartialTokenValues as K, type FlatComponentConfig as L, type MultiSlotConfigInput as M, type FlatComponentSelections as N, type FlatTokenEntry as O, type FontFaceSrc as P, type KeyframeStops as Q, type SlotComponentConfig as R, type StyleUtils as S, type ThemeConditionMedia as T, type SlotStyles as U, type VariantDefinitions as V, type StyleDefinitions as W, type StyleDefinitionsWithUtils as X, type ThemeConditionNot as Y, type VariantOptionStyle as Z, flattenTokenEntries as _, type ThemeConditionAttr as a, type ThemeConditionClass as b, type ThemeConditionSelector as c, type ThemeCondition as d, type ThemeConditionAnd as e, type ThemeConditionOr as f, type ThemeOverrides as g, type ThemeModeDefinition as h, type ThemeSurface as i, type ThemeConfig as j, type TokenValues as k, type TokenRef as l, type ComponentConfigInput as m, type ComponentReturn as n, type FlatComponentReturn as o, type SlotVariantDefinitions as p, type SlotComponentConfigInput as q, type SlotComponentFunction as r, type MultiSlotReturn as s, type CSSPropertiesWithUtils as t, type FontFaceProps as u, type CSSVarRef as v, type CSSValue as w, type ComponentConfig as x, type ComponentConfigContext as y, type ComponentInternalVarRef as z }; |
| /** | ||
| * Ensure the managed <style id="typestyles"> is attached to the current document and populated. | ||
| * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled. | ||
| */ | ||
| declare function ensureDocumentStylesAttached(): void; | ||
| /** | ||
| * Insert multiple CSS rules at once. | ||
| */ | ||
| declare function insertRules(rules: Array<{ | ||
| key: string; | ||
| css: string; | ||
| }>): void; | ||
| /** | ||
| * Return all registered CSS as a string. | ||
| * | ||
| * Unlike `collectStyles`, this doesn't require wrapping a render function. | ||
| * It simply returns every CSS rule that has been registered via | ||
| * `styles.component`, `styles.class`, `tokens.create`, `keyframes.create`, etc. | ||
| * | ||
| * Ideal for SSR frameworks that need the CSS separately from the render | ||
| * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * // In a route's head/meta function: | ||
| * export const head = () => ({ | ||
| * styles: [{ id: 'typestyles', children: getRegisteredCss() }], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function getRegisteredCss(): string; | ||
| /** | ||
| * Reset all state (useful for testing). | ||
| */ | ||
| declare function reset(): void; | ||
| /** | ||
| * Flush all pending rules synchronously. Used for SSR and testing. | ||
| */ | ||
| declare function flushSync(): void; | ||
| /** | ||
| * Invalidate all dedup keys that start with the given prefix. | ||
| * Also removes matching rules from the live stylesheet. | ||
| * Used for HMR — allows modules to re-register their styles after editing. | ||
| */ | ||
| declare function invalidatePrefix(prefix: string): void; | ||
| /** | ||
| * Invalidate a list of exact keys or prefixes. | ||
| * Each entry in `keys` is treated as an exact key match. | ||
| * Each entry in `prefixes` is treated as a prefix match. | ||
| * Used for HMR to invalidate all styles from a module at once. | ||
| */ | ||
| declare function invalidateKeys(keys: string[], prefixes: string[]): void; | ||
| export { invalidateKeys as a, invalidatePrefix as b, ensureDocumentStylesAttached as e, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r }; |
| /** | ||
| * Ensure the managed <style id="typestyles"> is attached to the current document and populated. | ||
| * Call after SPA-style navigation (e.g. Astro `astro:after-swap`) when runtime injection is enabled. | ||
| */ | ||
| declare function ensureDocumentStylesAttached(): void; | ||
| /** | ||
| * Insert multiple CSS rules at once. | ||
| */ | ||
| declare function insertRules(rules: Array<{ | ||
| key: string; | ||
| css: string; | ||
| }>): void; | ||
| /** | ||
| * Return all registered CSS as a string. | ||
| * | ||
| * Unlike `collectStyles`, this doesn't require wrapping a render function. | ||
| * It simply returns every CSS rule that has been registered via | ||
| * `styles.component`, `styles.class`, `tokens.create`, `keyframes.create`, etc. | ||
| * | ||
| * Ideal for SSR frameworks that need the CSS separately from the render | ||
| * pass (e.g. TanStack Start's `head()`, Next.js metadata, Remix links). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { getRegisteredCss } from 'typestyles/server'; | ||
| * | ||
| * // In a route's head/meta function: | ||
| * export const head = () => ({ | ||
| * styles: [{ id: 'typestyles', children: getRegisteredCss() }], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function getRegisteredCss(): string; | ||
| /** | ||
| * Reset all state (useful for testing). | ||
| */ | ||
| declare function reset(): void; | ||
| /** | ||
| * Flush all pending rules synchronously. Used for SSR and testing. | ||
| */ | ||
| declare function flushSync(): void; | ||
| /** | ||
| * Invalidate all dedup keys that start with the given prefix. | ||
| * Also removes matching rules from the live stylesheet. | ||
| * Used for HMR — allows modules to re-register their styles after editing. | ||
| */ | ||
| declare function invalidatePrefix(prefix: string): void; | ||
| /** | ||
| * Invalidate a list of exact keys or prefixes. | ||
| * Each entry in `keys` is treated as an exact key match. | ||
| * Each entry in `prefixes` is treated as a prefix match. | ||
| * Used for HMR to invalidate all styles from a module at once. | ||
| */ | ||
| declare function invalidateKeys(keys: string[], prefixes: string[]): void; | ||
| export { invalidateKeys as a, invalidatePrefix as b, ensureDocumentStylesAttached as e, flushSync as f, getRegisteredCss as g, insertRules as i, reset as r }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
1512725
62.51%64
64.1%10768
57.82%0
-100%96
Infinity%79
51.92%