UNPKG

alouette

Version:

A modern, customizable design system built on top of NativeWind v5 with configurable defaults

1 lines 48.3 kB
{"version":3,"file":"theme-generator-node22.cjs","sources":["../src/theme-generator/paletteSpecs.ts","../src/theme-generator/createColorScale.ts","../src/theme-generator/tokenScaleMap.ts","../src/theme-generator/buildTheme.ts","../src/theme-generator/generateTheme.ts","../src/theme-generator/writeTheme.ts"],"sourcesContent":["/* eslint-disable import-x/extensions */\n// Palette definitions: the single place declaring each accent — its hue\n// parameters (turned into OKLCH color scales by `createColorScale`) and its\n// traits (consumed by `tokenScaleMap.ts` when a token's step depends on the\n// accent). Apps override these via `generateTheme(overrides)` to re-color the\n// same accents while staying on alouette's OKLCH ramp.\n\nimport type { Accent } from \"../core/AlouetteConfig.ts\";\n\nexport type AccentName = Accent | \"grayscale\";\n\nexport interface PaletteSpec {\n type: \"accent\" | \"brightAccent\" | \"grayscale\";\n hue: number;\n // Optional hue ramp keyed on perceptual lightness: `hueHi` applies at the\n // lightest end, `hueLo` at the darkest. Both default to `hue` (no ramp).\n hueHi?: number;\n hueLo?: number;\n // Uniform multiplier on the relative chroma curve (grayscale = 0).\n intensity?: number;\n}\n\n// Insertion order is the order palettes are emitted into the generated scales.\nexport const defaultPaletteSpecs: Record<AccentName, PaletteSpec> = {\n grayscale: { type: \"grayscale\", hue: 0, intensity: 0 },\n brand: { type: \"accent\", hue: 225 },\n // Slightly pinker tints (hueHi 20) matching the old palette's pale reds.\n danger: { type: \"accent\", hue: 27, hueHi: 20 },\n info: { type: \"accent\", hue: 233 },\n success: { type: \"accent\", hue: 145 },\n // Amber ramp: cream tints at the light end, bronze shadows — the classic\n // warning gold rather than lemon yellow.\n warning: { type: \"brightAccent\", hue: 85, hueHi: 95, hueLo: 75 },\n};\n","/* eslint-disable import-x/extensions */\n// OKLCH color-scale generator. Palettes are generated in OKLCH so a single\n// lightness ramp is perceptually uniform across every hue (HSL lightness is not\n// — yellow at HSL L=56 reads far brighter than blue at the same L). Chroma is\n// specified *relative to the target gamut*: each step requests a fraction of the\n// maximum chroma that gamut can render at that step's lightness and hue. The\n// fraction curve is shared by every palette and tiered by usage (muted surface\n// tints, medium highlight mids, near-vivid interactive and text steps), so all\n// hues are equally saturated relative to what's possible — no per-palette chroma\n// table. The same ramp generated against display-p3 instead of sRGB is what the\n// `oklch()` palette ships to web.\n\nimport Color from \"colorjs.io\";\nimport type { PaletteSpec } from \"./paletteSpecs.ts\";\nimport type { Mode, ScaleNum } from \"./tokenScaleMap.ts\";\n\nexport interface OklchColor {\n lightness: number;\n chroma: number;\n hue: number;\n}\n\nexport type ColorScale = Record<ScaleNum, string>;\nexport type OklchScale = Record<ScaleNum, OklchColor>;\n\n// step: 1 2 3 4 5 6 7 8 9 10 11\nconst lightnessRamps = {\n grayscale: {\n dark: [0.18, 0.24, 0.28, 0.32, 0.36, 0.4, 0.45, 0.795, 0.865, 0.96, 1],\n // only diff is on the first 2 values\n light: [1, 0.98, 0.948, 0.89, 0.85, 0.79, 0.61, 0.54, 0.48, 0.42, 0.27],\n },\n accent: {\n dark: [0.18, 0.22, 0.26, 0.3, 0.34, 0.4, 0.5, 0.7, 0.82, 0.865, 0.955],\n light: [\n 0.988, 0.968, 0.948, 0.89, 0.85, 0.79, 0.62, 0.54, 0.48, 0.42, 0.27,\n ],\n },\n brightAccent: {\n dark: [0.28, 0.32, 0.4, 0.45, 0.5, 0.53, 0.56, 0.8, 0.86, 0.9, 0.955],\n light: [0.988, 0.968, 0.948, 0.928, 0.89, 0.82, 0.8, 0.6, 0.56, 0.44, 0.27],\n },\n} as const;\n\n// Fraction of the max in-gamut chroma requested at each step. Usage tiers\n// mirror the old HSL generator's 56/82/96 saturation bands: steps 1-3 pale\n// surfaces, 4-6 highlight/message tints, 7-11 interactive fills and text.\nconst relativeChromaCurve: Record<Mode, number[]> = {\n dark: [0.6, 0.68, 0.72, 0.76, 0.78, 0.84, 0.88, 0.88, 0.85, 0.82, 0.86],\n light: [0.5, 0.52, 0.55, 0.6, 0.75, 0.78, 0.92, 0.97, 0.97, 0.97, 0.95],\n};\n\n/**\n * Which gamut the chroma budget is measured against. `srgb` is what every\n * platform can render (and what the hex output is mapped into); `p3` gives the\n * same lightness ramp more chroma headroom, used by the `oklch()` output that\n * only web consumes.\n */\nexport type Gamut = \"p3\" | \"srgb\";\n\ninterface MaxChromaParams {\n lightness: number;\n hue: number;\n gamut: Gamut;\n}\n\n// Largest OKLCH chroma still inside the given gamut at this lightness/hue.\nexport const maxChroma = ({\n lightness,\n hue,\n gamut,\n}: MaxChromaParams): number => {\n const space = gamut === \"p3\" ? \"p3\" : \"srgb\";\n let low = 0;\n let high = 0.5;\n for (let i = 0; i < 20; i++) {\n const mid = (low + high) / 2;\n if (new Color(\"oklch\", [lightness, mid, hue]).to(space).inGamut()) {\n low = mid;\n } else {\n high = mid;\n }\n }\n return low;\n};\n\nexport const maxSrgbChroma = (lightness: number, hue: number): number =>\n maxChroma({ lightness, hue, gamut: \"srgb\" });\n\nexport const toHex = ({ lightness, chroma, hue }: OklchColor): string => {\n const color = new Color(\"oklch\", [lightness, chroma, hue]).to(\"srgb\");\n const hex = color.toGamut({ method: \"css\" }).toString({ format: \"hex\" });\n // colorjs collapses to 3-digit shorthand (#050); expand so appended alpha\n // suffixes (e.g. selection = step + \"40\") stay valid 8-digit hex.\n const full =\n hex.length === 4 ? hex.replace(/^#(.)(.)(.)$/, \"#$1$1$2$2$3$3\") : hex;\n return full.toUpperCase();\n};\n\nexport const createOklchScale = (\n spec: PaletteSpec,\n mode: Mode,\n gamut: Gamut,\n): OklchScale => {\n const hueHi = spec.hueHi ?? spec.hue;\n const hueLo = spec.hueLo ?? spec.hue;\n const intensity = spec.intensity ?? 1;\n const ramp = lightnessRamps[spec.type][mode];\n const steps = ramp.map((lightness, index): OklchColor => {\n const hue = hueLo + (hueHi - hueLo) * lightness;\n const chroma =\n relativeChromaCurve[mode][index]! *\n intensity *\n maxChroma({ lightness, hue, gamut });\n return { lightness, chroma, hue };\n });\n return Object.fromEntries(\n steps.map((color, index) => [index + 1, color]),\n ) as unknown as OklchScale;\n};\n\nexport const createColorScale = (spec: PaletteSpec, mode: Mode): ColorScale => {\n const scale = createOklchScale(spec, mode, \"srgb\");\n return Object.fromEntries(\n Object.entries(scale).map(([step, color]) => [step, toHex(color)]),\n ) as unknown as ColorScale;\n};\n","/* eslint-disable import-x/extensions */\n// Single source of truth mapping each semantic token to a color-scale step,\n// per mode and accent. Shared by `buildTheme.ts` (emits the CSS variables /\n// themeVariables) and the repo-root `scripts/generate-palette.ts` contrast\n// audit (resolves the steps a token pair actually uses), so the two can never\n// drift. A token resolves to a `{ source, step }` (which palette + which scale\n// step for this mode), a `{ literal }` (a fixed value), or `null` when the\n// token is not emitted for the given accent.\n\nimport type { AccentName } from \"./paletteSpecs.ts\";\n\nexport type { AccentName } from \"./paletteSpecs.ts\";\n\nexport type Mode = \"dark\" | \"light\";\nexport type ScaleNum = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;\n\nexport interface TokenStep {\n source: \"grayscale\" | \"self\";\n step: ScaleNum;\n alpha?: string;\n}\nexport interface TokenLiteral {\n literal: string;\n}\nexport type ResolvedToken = TokenLiteral | TokenStep;\n\nexport interface TokenContext {\n mode: Mode;\n isGrayscale: boolean;\n accent: AccentName;\n}\n\nexport type TokenResolver = (ctx: TokenContext) => ResolvedToken | null;\n\n// `self` reads the accent's own palette; `gray` always reads grayscale (base\n// tokens whose value is fixed regardless of accent, e.g. text-muted/on-accent).\nconst step = (\n source: \"grayscale\" | \"self\",\n dark: ScaleNum,\n light: ScaleNum,\n alpha?: string,\n): TokenResolver => {\n return ({ mode }) => {\n const resolved: TokenStep = {\n source,\n step: mode === \"dark\" ? dark : light,\n };\n if (alpha) resolved.alpha = alpha;\n return resolved;\n };\n};\n\nconst self = (dark: ScaleNum, light: ScaleNum = dark, alpha?: string) =>\n step(\"self\", dark, light, alpha);\nconst gray = (dark: ScaleNum, light: ScaleNum = dark) =>\n step(\"grayscale\", dark, light);\n// Branches on both grayscale/colored and dark/light mode.\nconst selfAdaptive =\n (\n grayscaleDark: ScaleNum,\n coloredDark: ScaleNum,\n grayscaleLight: ScaleNum = grayscaleDark,\n coloredLight: ScaleNum = coloredDark,\n ): TokenResolver =>\n ({ isGrayscale, mode }) => ({\n source: \"self\",\n step: (() => {\n if (mode === \"dark\") return isGrayscale ? grayscaleDark : coloredDark;\n return isGrayscale ? grayscaleLight : coloredLight;\n })(),\n });\n\n// Emitted only in the grayscale theme; colored sub-themes inherit the value\n// through the CSS cascade (they never override it).\nconst grayscaleOnly =\n (resolver: TokenResolver): TokenResolver =>\n (ctx) =>\n ctx.isGrayscale ? resolver(ctx) : null;\n\nconst translucent: Record<Mode, string> = {\n dark: \"#1f1e1e55\",\n light: \"#ffffff66\",\n};\n\n// Insertion order is significant: it is the order tokens are emitted into\n// the palette CSS / themeVariables, with the grayscale-only block first.\nexport const tokenScaleMap: Record<string, TokenResolver> = {\n /* grayscale-only base tokens */\n translucent: grayscaleOnly(({ mode }) => ({ literal: translucent[mode] })),\n\n /* grayscale-only backgrounds */\n screen: grayscaleOnly(self(2, 3)),\n highlight: grayscaleOnly(self(4, 1)),\n\n /* grayscale-only texts */\n \"disabled-sharp\": grayscaleOnly(gray(9, 9)),\n \"disabled-muted\": grayscaleOnly(gray(9, 7)),\n \"disabled-interactive\": grayscaleOnly(gray(7, 6)),\n \"disabled-interactive-muted\": grayscaleOnly(gray(4, 4)),\n sharp: grayscaleOnly(gray(10, 11)),\n muted: grayscaleOnly(gray(9, 10)),\n\n /* grayscale-only unsorted */\n \"form-border-disabled\": grayscaleOnly(gray(7, 6)),\n \"form-placeholder\": grayscaleOnly(gray(8, 9)),\n \"form-disabled-text\": grayscaleOnly(gray(9, 10)),\n \"interactive-contained-disabled\": grayscaleOnly(gray(5, 6)),\n \"interactive-outlined-disabled\": grayscaleOnly(gray(6, 6)),\n \"interactive-accent-outlined-disabled\": grayscaleOnly(gray(6, 6)),\n\n /* backgrounds */\n surface: self(3, 2),\n enabled: self(7, 9),\n \"highlight-accent\": self(4),\n lowered: self(1, 4),\n \"screen-gradient-start\": self(3, 4),\n \"screen-gradient-middle\": self(2, 5),\n \"screen-gradient-end\": self(1, 6),\n\n /* borders */\n \"border-muted\": self(7, 5),\n \"border-sharp\": self(8, 9),\n\n /* interactive */\n \"interactive-contained-pressable\": selfAdaptive(6, 6, 1, 9),\n \"interactive-contained-hover\": selfAdaptive(7, 7, 2, 8),\n \"interactive-contained-focus\": selfAdaptive(7, 7, 2, 8),\n \"interactive-contained-active\": selfAdaptive(7, 7, 3, 7),\n\n \"interactive-outlined-pressable\": self(7, 9),\n \"interactive-outlined-hover\": self(8, 7),\n \"interactive-outlined-focus\": self(8, 7),\n \"interactive-outlined-active\": self(8, 7),\n \"interactive-outlined-outline-focus\": self(8, 7),\n\n \"interactive-active\": self(9),\n \"interactive-pressable\": self(10),\n \"interactive-hover\": self(11),\n\n /* texts */\n accent: selfAdaptive(11, 10),\n \"on-accent\": ({ isGrayscale, mode }) => ({\n source: \"grayscale\",\n step: ((): ScaleNum => {\n if (mode === \"dark\") return 11;\n return isGrayscale ? 11 : 1;\n })(),\n }),\n \"on-accent-muted\": selfAdaptive(10, 10, 9, 4),\n\n /* specials */\n selection: self(10, 10, \"40\"),\n};\n\nexport const resolveToken = (\n token: string,\n ctx: TokenContext,\n): ResolvedToken | null => {\n const resolver = tokenScaleMap[token];\n if (!resolver) throw new Error(`Unknown token: ${token}`);\n return resolver(ctx);\n};\n\n// The value a token actually resolves to in a theme, following grayscale-only\n// base tokens into their inherited grayscale value (used by the contrast audit,\n// where e.g. `text-muted` must resolve even on a colored surface).\nexport const resolveTokenEffective = (\n token: string,\n ctx: TokenContext,\n): ResolvedToken => {\n return (\n resolveToken(token, ctx) ??\n resolveToken(token, {\n mode: ctx.mode,\n isGrayscale: true,\n accent: \"grayscale\",\n })!\n );\n};\n","/* eslint-disable import-x/extensions */\n// Assembles resolved color scales + the semantic tokenScaleMap into the coupled\n// outputs of a theme: the base palette CSS (the `@theme` color defaults that\n// generate bg-*/text-*/border-* utilities plus the twelve `.<theme>`\n// blocks in hex), the optional oklch overlay CSS (the same twelve blocks\n// re-emitted as `oklch()` behind `@supports`) and the resolved `themeVariables`\n// maps (fully merged per theme so a theme can be applied at any depth in JS).\n// Shared by the internal default build (`scripts/build-css.ts`) and the exposed\n// `generateTheme`.\n//\n// The two outputs feed the two halves of `ScopedTheme`: the CSS blocks are what\n// web applies (a `className={theme}` element, resolved by custom-property\n// inheritance), the maps are what native applies (NativeWind's\n// `VariableContextProvider`).\n//\n// Two serializations of the same ramp: sRGB hex is the only format native can\n// consume (`@react-native/normalize-colors` has no oklch parser, and the JS map\n// bypasses the CSS compiler entirely), so it stays the baseline everywhere;\n// `oklch()` carries the display-p3 chroma headroom, is web-only, and ships as a\n// separate file so a project opts into it.\n\nimport Color from \"colorjs.io\";\nimport type { AlouetteTheme } from \"../core/AlouetteConfig.ts\";\nimport type { OklchColor, OklchScale } from \"./createColorScale.ts\";\nimport { toHex } from \"./createColorScale.ts\";\nimport type { AccentName } from \"./paletteSpecs.ts\";\nimport type { Mode, ScaleNum } from \"./tokenScaleMap.ts\";\nimport { tokenScaleMap } from \"./tokenScaleMap.ts\";\n\nexport type ThemeScales = Record<`${AccentName}.${Mode}`, OklchScale>;\n\nexport type ColorFormatName = \"oklch\" | \"srgb\";\n\n// Emit order (grayscale first, then accents) — the order tokens/blocks appear in\n// the generated CSS and themeVariables. Kept explicit so the output is stable\n// regardless of the palette-specs insertion order.\nconst accentEmitOrder: AccentName[] = [\n \"grayscale\",\n \"brand\",\n \"info\",\n \"success\",\n \"warning\",\n \"danger\",\n];\n\ninterface ColorFormat {\n serialize: (color: OklchColor) => string;\n /** `alpha` is the hex suffix the token map is written in, e.g. `\"40\"`. */\n withAlpha: (serialized: string, alpha: string) => string;\n /** Re-express a hex literal from the token map in this format. */\n literal: (hex: string) => string;\n}\n\nconst round = (value: number, digits: number): number =>\n Number(value.toFixed(digits));\n\nconst formatOklch = ({ lightness, chroma, hue }: OklchColor): string =>\n `oklch(${round(lightness, 4)} ${round(chroma, 4)} ${round(hue, 2)})`;\n\nconst hexAlphaToFraction = (alpha: string): number =>\n round(Number.parseInt(alpha, 16) / 255, 3);\n\nconst withOklchAlpha = (serialized: string, alpha: number): string =>\n alpha === 1 ? serialized : `${serialized.slice(0, -1)} / ${alpha})`;\n\nconst colorFormats: Record<ColorFormatName, ColorFormat> = {\n srgb: {\n serialize: toHex,\n withAlpha: (serialized, alpha) => serialized + alpha,\n literal: (hex) => hex,\n },\n oklch: {\n serialize: formatOklch,\n withAlpha: (serialized, alpha) =>\n withOklchAlpha(serialized, hexAlphaToFraction(alpha)),\n literal: (hex) => {\n const { coords, alpha } = new Color(hex).to(\"oklch\");\n const [lightness, chroma, hue] = coords;\n // colorjs leaves missing components null (hue on achromatic colors); 0 is\n // the CSS spelling.\n return withOklchAlpha(\n formatOklch({\n lightness: lightness ?? 0,\n chroma: chroma ?? 0,\n hue: hue || 0,\n }),\n round(alpha, 3),\n );\n },\n },\n};\n\ninterface ColorAtParams {\n scales: ThemeScales;\n mode: Mode;\n accentName: AccentName;\n step: ScaleNum;\n}\n\nconst colorAt = ({\n scales,\n mode,\n accentName,\n step,\n}: ColorAtParams): OklchColor => scales[`${accentName}.${mode}`][step];\n\ninterface BuildThemeVarsParams {\n scales: ThemeScales;\n mode: Mode;\n accentName: AccentName;\n format: ColorFormat;\n}\n\n// Resolve every token's scale step to a concrete color for this mode/accent.\n// Grayscale-only tokens resolve to null on colored accents and are skipped\n// (they inherit through the CSS cascade / the merged themeVariables map).\nconst buildThemeVars = ({\n scales,\n mode,\n accentName,\n format,\n}: BuildThemeVarsParams): Record<string, string> => {\n const isGrayscale = accentName === \"grayscale\";\n const vars: Record<string, string> = {};\n\n for (const [token, resolver] of Object.entries(tokenScaleMap)) {\n const resolved = resolver({ mode, isGrayscale, accent: accentName });\n if (!resolved) continue;\n\n if (\"literal\" in resolved) {\n vars[token] = format.literal(resolved.literal);\n continue;\n }\n\n const serialized = format.serialize(\n colorAt({\n scales,\n mode,\n accentName: resolved.source === \"grayscale\" ? \"grayscale\" : accentName,\n step: resolved.step,\n }),\n );\n vars[token] = resolved.alpha\n ? format.withAlpha(serialized, resolved.alpha)\n : serialized;\n }\n\n return vars;\n};\n\nconst emit = (vars: Record<string, string>, indent: string): string =>\n Object.entries(vars)\n .map(([key, value]) => `${indent}--color-${key}: ${value};`)\n .join(\"\\n\");\n\nconst prefixVars = (\n vars: Record<string, string>,\n): Record<`--color-${string}`, string> =>\n Object.fromEntries(\n Object.entries(vars).map(([key, value]) => [`--color-${key}`, value]),\n );\n\nconst accents = accentEmitOrder.filter((name) => name !== \"grayscale\");\n\ninterface ThemeTarget {\n theme: AlouetteTheme;\n mode: Mode;\n accentName: AccentName;\n}\n\n// Base modes first, then the accent sub-themes — the order the blocks appear in\n// the CSS and the keys in themeVariables.\nconst themeTargets: ThemeTarget[] = [\n ...([\"light\", \"dark\"] as const).map(\n (mode): ThemeTarget => ({\n theme: mode,\n mode,\n accentName: \"grayscale\",\n }),\n ),\n ...([\"light\", \"dark\"] as const).flatMap((mode) =>\n accents.map(\n (accentName): ThemeTarget => ({\n theme: `${mode}_${accentName}` as AlouetteTheme,\n mode,\n accentName,\n }),\n ),\n ),\n];\n\ninterface EmitThemeBlocksParams {\n scales: ThemeScales;\n format: ColorFormat;\n indent: string;\n}\n\n// The twelve `.<theme>` blocks — a web-only mechanism. `ScopedTheme.web.tsx`\n// applies a theme as a className and lets CSS resolve it; native pushes the\n// resolved `themeVariables` map through NativeWind's `VariableContextProvider`\n// and never sets a className, so these blocks are dead weight there. Both\n// callers therefore keep them behind a feature query the native compiler cannot\n// evaluate — {@link webOnly} here, the `oklch()` query in the overlay.\n//\n// Each block declares its variables on the themed element *only*: descendants\n// pick them up by custom-property inheritance, and an element's own declaration\n// always beats an inherited value, so the closest theme class in the tree wins\n// for its whole subtree. A descendant selector (`.<theme> *`) would break that —\n// every themed ancestor would match a nested element at equal specificity in the\n// same layer, making file order, not proximity, decide.\n//\n// Plain class selectors, not `:where()`: the blocks sit in `@layer theme`, so\n// unlayered author rules (Tailwind's utilities, including an arbitrary\n// `[--color-x:…]`) and inline styles override them whatever their specificity.\n// What the specificity does buy is the `:root`/`:host` case — a theme class set\n// on the document element ties with the `@theme` defaults and wins on order.\n//\n// Accent blocks are partial (only the tokens the accent redefines); the rest\n// inherit from the nearest ancestor theme class. `AccentScope` derives the\n// accent theme from the current mode, so that ancestor is the matching base\n// mode. A forced-mode scope (`<AccentScope mode=\"light\">` under a `dark`\n// ancestor) therefore resolves base tokens from the dark ancestor on web, while\n// native's merged `themeVariables` map gives the light ones.\nconst emitThemeBlocks = ({\n scales,\n format,\n indent,\n}: EmitThemeBlocksParams): string =>\n themeTargets\n .map(({ theme, mode, accentName }) => {\n const vars = buildThemeVars({ scales, mode, accentName, format });\n return `${indent}.${theme} {\\n${emit(vars, `${indent} `)}\\n${indent}}`;\n })\n .join(\"\\n\\n\");\n\n// Hides web-only rules from the native compiler, which skips any `@supports`\n// whose condition it cannot evaluate — so the block never reaches the native\n// bundle, while every browser (Vite web and Expo web alike) evaluates it true.\n// `display: contents` is the condition because it is exactly what\n// `ScopedTheme.web.tsx` renders to apply a theme class without affecting layout.\nconst webOnly = (rules: string): string => ` @supports (display: contents) {\n${rules}\n }`;\n\n/**\n * The base palette CSS for a set of sRGB scales: the `@theme` color defaults\n * (light grayscale, which generate the color utilities) and the twelve\n * `.<theme>` selector blocks, all in hex.\n *\n * Hex is the only format native can compile, so this file alone is a complete\n * palette on every platform. Layer {@link buildOklchPaletteCss} after it to opt\n * web into the wide-gamut ramp. Structural CSS (fonts, spacing, keyframes,\n * utilities) lives in `core.css`, not here.\n *\n * Only the `@theme` half compiles on native; the theme blocks are {@link webOnly}.\n * Native must therefore keep the color tokens out of react-native-css's variable\n * inliner — `withAlouetteConfig` (metro.cjs) passes `inlineVariables.exclude`,\n * without which every token collapses to its light value.\n */\nexport const buildPaletteCss = (srgbScales: ThemeScales): string => {\n const srgb = colorFormats.srgb;\n const lightVars = buildThemeVars({\n scales: srgbScales,\n mode: \"light\",\n accentName: \"grayscale\",\n format: srgb,\n });\n\n return `@theme {\n /* color tokens — light theme as defaults, enabling bg-*, text-*, border-*\n color utilities. This block is the whole palette on native, where ScopedTheme\n overrides it at runtime with the themeVariables map fed to NativeWind's\n VariableContextProvider. Web instead resolves the .<theme> blocks below,\n applied as a className (the closest theme class wins, through inheritance). */\n${emit(lightVars, \" \")}\n}\n\n@layer theme {\n${webOnly(emitThemeBlocks({ scales: srgbScales, format: srgb, indent: \" \" }))}\n}\n`;\n};\n\n/**\n * The wide-gamut overlay for a set of display-p3 scales: the same tokens as\n * {@link buildPaletteCss}, re-declared as `oklch()` inside `@supports`. Import\n * it *after* the base palette CSS, and only on projects that want the extra\n * chroma — it is purely additive.\n *\n * The `@supports` rule is what keeps native safe if the overlay is imported in a\n * shared CSS entry: the react-native-css compiler drops feature queries it\n * cannot evaluate, so native keeps the hex from the base palette.\n */\nexport const buildOklchPaletteCss = (p3Scales: ThemeScales): string => {\n const oklch = colorFormats.oklch;\n const lightOklchVars = buildThemeVars({\n scales: p3Scales,\n mode: \"light\",\n accentName: \"grayscale\",\n format: oklch,\n });\n\n return `/* Wide-gamut palette: the same ramp with display-p3 chroma headroom. Web only —\n the native compiler drops this feature query and keeps the base palette hex. */\n@supports (color: oklch(0 0 0)) {\n @layer theme {\n /* overrides the @theme defaults, which cannot host a feature query */\n :root, :host {\n${emit(lightOklchVars, \" \")}\n }\n\n${emitThemeBlocks({ scales: p3Scales, format: oklch, indent: \" \" })}\n }\n}\n`;\n};\n\n/**\n * The fully-resolved CSS-variable map for every theme (base mode tokens + accent\n * overrides merged), keyed `--color-*`. Feeds `ScopedTheme` and `useThemeToken`.\n * Pair `srgb` with sRGB scales (the native-safe map) and `oklch` with p3 scales.\n */\nexport const buildThemeVariables = (\n scales: ThemeScales,\n formatName: ColorFormatName = \"srgb\",\n): Record<AlouetteTheme, Record<`--color-${string}`, string>> => {\n const format = colorFormats[formatName];\n const baseVars = {\n light: buildThemeVars({\n scales,\n mode: \"light\",\n accentName: \"grayscale\",\n format,\n }),\n dark: buildThemeVars({\n scales,\n mode: \"dark\",\n accentName: \"grayscale\",\n format,\n }),\n };\n\n return Object.fromEntries(\n themeTargets.map(({ theme, mode, accentName }) => [\n theme,\n prefixVars(\n accentName === \"grayscale\"\n ? baseVars[mode]\n : {\n ...baseVars[mode],\n ...buildThemeVars({ scales, mode, accentName, format }),\n },\n ),\n ]),\n ) as Record<AlouetteTheme, Record<`--color-${string}`, string>>;\n};\n","/* eslint-disable import-x/extensions */\n// Public entry: turn per-accent hue params into a theme's two coupled outputs.\n\nimport type { AlouetteTheme } from \"../core/AlouetteConfig.ts\";\nimport type { ThemeScales } from \"./buildTheme.ts\";\nimport {\n buildOklchPaletteCss,\n buildPaletteCss,\n buildThemeVariables,\n} from \"./buildTheme.ts\";\nimport type { Gamut } from \"./createColorScale.ts\";\nimport { createOklchScale } from \"./createColorScale.ts\";\nimport type { AccentName, PaletteSpec } from \"./paletteSpecs.ts\";\nimport { defaultPaletteSpecs } from \"./paletteSpecs.ts\";\n\ntype ThemeVariables = Record<\n AlouetteTheme,\n Record<`--color-${string}`, string>\n>;\n\nexport interface GenerateThemeResult {\n /**\n * Base palette CSS to import after `alouette/core.css`: the `@theme` color\n * defaults (which generate the color utilities — bg-, text-, border-) and the\n * twelve `.<theme>` selector blocks, in sRGB hex. Complete on its own,\n * on every platform.\n */\n css: string;\n /**\n * Optional wide-gamut overlay, re-declaring the same tokens as `oklch()`\n * behind `@supports` with display-p3 chroma headroom. Import it after\n * {@link GenerateThemeResult.css} to opt web into the more vivid ramp; skip it\n * to stay on sRGB everywhere.\n */\n oklchCss: string;\n /**\n * Resolved CSS-variable map for every theme in sRGB hex, to pass to\n * `<AlouetteProvider themeVariables={...}>` so JS token reads (gradients,\n * native Switch, placeholder/SVG tint) match the CSS. The only format native\n * can parse — write it to `themeVariables.ts`.\n */\n themeVariables: ThemeVariables;\n /**\n * The same map with display-p3 chroma headroom, serialized as `oklch()`.\n * Web-only material: the web build resolves every token from the palette CSS\n * and ignores this map, so it exists for tooling that needs the oklch values,\n * not for `<AlouetteProvider>`.\n */\n oklchThemeVariables: ThemeVariables;\n}\n\n/**\n * Generate a coherent theme for the alouette accents from hue params. Overrides\n * are merged over {@link defaultPaletteSpecs}, so an app can re-color only the\n * accents it cares about (e.g. `brand`) and inherit the rest.\n */\nexport const generateTheme = (\n overrides?: Partial<Record<AccentName, PaletteSpec>>,\n): GenerateThemeResult => {\n const specs: Record<AccentName, PaletteSpec> = {\n ...defaultPaletteSpecs,\n ...overrides,\n };\n\n const scalesForGamut = (gamut: Gamut): ThemeScales =>\n Object.fromEntries(\n (Object.keys(specs) as AccentName[]).flatMap((name) => [\n [`${name}.light`, createOklchScale(specs[name], \"light\", gamut)],\n [`${name}.dark`, createOklchScale(specs[name], \"dark\", gamut)],\n ]),\n ) as ThemeScales;\n\n const srgbScales = scalesForGamut(\"srgb\");\n const p3Scales = scalesForGamut(\"p3\");\n\n return {\n css: buildPaletteCss(srgbScales),\n oklchCss: buildOklchPaletteCss(p3Scales),\n themeVariables: buildThemeVariables(srgbScales, \"srgb\"),\n oklchThemeVariables: buildThemeVariables(p3Scales, \"oklch\"),\n };\n};\n","/* eslint-disable import-x/extensions */\n// Build-script driver: turn palette params into the two files an app imports.\n// Node-only — call it from a script, never from app code.\n\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { GenerateThemeResult } from \"./generateTheme.ts\";\nimport { generateTheme } from \"./generateTheme.ts\";\nimport type { AccentName, PaletteSpec } from \"./paletteSpecs.ts\";\n\nconst generatedHeader = \"/* Generated by alouette writeTheme. DO NOT EDIT. */\";\n\n// Emitted the way a formatter would leave it — unquoted theme keys (hence the\n// camelcase disable in the file header) and trailing commas — so a generated\n// file never churns the first time the app runs prettier/oxfmt over it.\nconst serializeThemeVariables = (\n themeVariables: GenerateThemeResult[\"themeVariables\"],\n): string =>\n `{\\n${Object.entries(themeVariables)\n .map(([theme, variables]) => {\n const entries = Object.entries(variables)\n .map(([name, value]) => ` \"${name}\": \"${value}\",`)\n .join(\"\\n\");\n return ` ${theme}: {\\n${entries}\\n },`;\n })\n .join(\"\\n\")}\\n}`;\n\nconst themeVariablesModule = (\n themeVariables: GenerateThemeResult[\"themeVariables\"],\n): string =>\n `${generatedHeader}\n/* eslint-disable camelcase */\nimport type { ThemeVariablesMap } from \"alouette\";\n\n/**\n * Resolved CSS-variable maps for every theme, paired with the generated palette\n * CSS. Pass to \\`<AlouetteProvider themeVariables={...}>\\`.\n */\nexport const themeVariables: ThemeVariablesMap = ${serializeThemeVariables(themeVariables)};\n`;\n\nexport interface WriteThemeParams {\n /** Directory the files are written to, created if missing. */\n outDir: string;\n /**\n * Per-accent params merged over the alouette defaults, so only the accents\n * the app re-colors need to be listed. Omit to reproduce the default palette.\n */\n overrides?: Partial<Record<AccentName, PaletteSpec>>;\n /**\n * Skip the `oklch()` overlay entirely and ship sRGB hex on every platform.\n * @default false\n */\n srgbOnly?: boolean;\n cssFileName?: string;\n themeVariablesFileName?: string;\n}\n\nexport interface WriteThemeResult {\n cssPath: string;\n /**\n * The wide-gamut overlay, named after `cssFileName` (`palette-oklch.css`).\n * `undefined` when `srgbOnly` is set.\n */\n oklchCssPath: string | undefined;\n themeVariablesPath: string;\n}\n\n/**\n * Generate an app's palette and write it to disk: the palette CSS to import\n * after `alouette/core.css`, and the `themeVariables` module to pass to\n * `<AlouetteProvider themeVariables={...}>`. Writing them from one call is what\n * keeps the className tokens and the JS token reads on the same colors.\n *\n * - `palette.css` (hex, complete on its own) + `palette-oklch.css`, imported\n * after it only if the app wants display-p3 chroma on web.\n * - `themeVariables.ts` in sRGB hex, the only format native can parse. The map\n * feeds native token reads only — web resolves every token from the CSS — so\n * there is no oklch counterpart.\n */\nexport const writeTheme = ({\n outDir,\n overrides,\n srgbOnly = false,\n cssFileName = \"palette.css\",\n themeVariablesFileName = \"themeVariables.ts\",\n}: WriteThemeParams): WriteThemeResult => {\n const { css, oklchCss, themeVariables } = generateTheme(overrides);\n\n mkdirSync(outDir, { recursive: true });\n\n const cssPath = join(outDir, cssFileName);\n writeFileSync(\n cssPath,\n `${generatedHeader}\n/* App palette. Import after \"alouette/core.css\", instead of\n \"alouette/global.css\" — which carries alouette's default palette. */\n${css}`,\n );\n\n const themeVariablesPath = join(outDir, themeVariablesFileName);\n writeFileSync(themeVariablesPath, themeVariablesModule(themeVariables));\n\n if (srgbOnly) {\n return { cssPath, oklchCssPath: undefined, themeVariablesPath };\n }\n\n const oklchCssPath = join(outDir, cssFileName.replace(/\\.css$/, \"-oklch$&\"));\n writeFileSync(\n oklchCssPath,\n `${generatedHeader}\n/* Wide-gamut half of the app palette. Optional — import after \"${cssFileName}\"\n to opt web into the display-p3 ramp. */\n${oklchCss}`,\n );\n\n return { cssPath, oklchCssPath, themeVariablesPath };\n};\n"],"names":["mkdirSync","join","writeFileSync"],"mappings":"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"}