@poupe/theme-builder
Version:
Design token management and theme generation system for Poupe UI framework
1 lines • 38.6 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["origColord"],"sources":["../../src/core/utils.ts","../../src/core/default-colors.ts","../../src/core/types.ts","../../src/core/colors.ts","../../src/core/formatter.ts","../../src/core/mix.ts","../../src/core/palettes.ts","../../src/core/states.ts","../../src/core/index.ts"],"sourcesContent":["/* re-export */\nexport {\n kebabCase,\n keys,\n pairs,\n unsafeKeys,\n} from '@poupe/css';\n\n/** Converts a number to an unsigned 32-bit integer */\nexport const uint32 = (n: number) => n >>> 0;\n\n/** Converts a number to an unsigned 8-bit integer */\nexport const uint8 = (n: number) => (n >>> 0) & 0xFF;\n\nexport const alphaFromArgb = (argb: number) => uint8(uint32(argb) >> 24);\nexport const redFromArgb = (argb: number) => uint8(uint32(argb) >> 16);\nexport const greenFromArgb = (argb: number) => uint8(uint32(argb) >> 8);\nexport const blueFromArgb = (argb: number) => uint8(uint32(argb));\n","import { type Color } from './types';\n\n/**\n * Complete collection of CSS named colors as defined in the CSS Color Module specifications.\n *\n * This object contains all standard CSS named colors organized by color family,\n * providing a comprehensive palette for color operations and conversions.\n *\n * @remarks\n * - All values are in hexadecimal format (#rrggbb or #rrggbbaa for transparent)\n * - Colors are grouped by visual similarity for easier navigation\n * - Includes all 147 CSS named colors from the CSS Color Module Level 4 specification\n * - Includes the transparent keyword for complete color support\n * - Some colors appear multiple times (e.g., cyan/aqua, fuchsia/magenta) as they represent the same color\n *\n * @example\n * ```typescript\n * const redColor = defaultColors.red; // '#ff0000'\n * const blueColor = defaultColors.blue; // '#0000ff'\n * ```\n */\nexport const defaultColors = {\n // Reds\n indianred: '#cd5c5c',\n lightcoral: '#f08080',\n salmon: '#fa8072',\n darksalmon: '#e9967a',\n crimson: '#dc143c',\n red: '#ff0000',\n firebrick: '#b22222',\n darkred: '#8b0000',\n\n // Pinks\n pink: '#ffc0cb',\n lightpink: '#ffb6c1',\n hotpink: '#ff69b4',\n deeppink: '#ff1493',\n mediumvioletred: '#c71585',\n palevioletred: '#db7093',\n\n // Oranges\n lightsalmon: '#ffa07a',\n coral: '#ff7f50',\n tomato: '#ff6347',\n orangered: '#ff4500',\n darkorange: '#ff8c00',\n orange: '#ffa500',\n\n // Yellows\n gold: '#ffd700',\n yellow: '#ffff00',\n lightyellow: '#ffffe0',\n lemonchiffon: '#fffacd',\n lightgoldenrodyellow: '#fafad2',\n papayawhip: '#ffefd5',\n moccasin: '#ffe4b5',\n peachpuff: '#ffdab9',\n palegoldenrod: '#eee8aa',\n khaki: '#f0e68c',\n darkkhaki: '#bdb76b',\n\n // Purples\n lavender: '#e6e6fa',\n thistle: '#d8bfd8',\n plum: '#dda0dd',\n violet: '#ee82ee',\n orchid: '#da70d6',\n fuchsia: '#ff00ff',\n magenta: '#ff00ff',\n mediumorchid: '#ba55d3',\n mediumpurple: '#9370db',\n rebeccapurple: '#663399',\n blueviolet: '#8a2be2',\n darkviolet: '#9400d3',\n darkorchid: '#9932cc',\n darkmagenta: '#8b008b',\n purple: '#800080',\n indigo: '#4b0082',\n slateblue: '#6a5acd',\n darkslateblue: '#483d8b',\n mediumslateblue: '#7b68ee',\n\n // Greens\n greenyellow: '#adff2f',\n chartreuse: '#7fff00',\n lawngreen: '#7cfc00',\n lime: '#00ff00',\n limegreen: '#32cd32',\n palegreen: '#98fb98',\n lightgreen: '#90ee90',\n mediumspringgreen: '#00fa9a',\n springgreen: '#00ff7f',\n mediumseagreen: '#3cb371',\n seagreen: '#2e8b57',\n forestgreen: '#228b22',\n green: '#008000',\n darkgreen: '#006400',\n yellowgreen: '#9acd32',\n olivedrab: '#6b8e23',\n olive: '#808000',\n darkolivegreen: '#556b2f',\n mediumaquamarine: '#66cdaa',\n darkseagreen: '#8fbc8f',\n lightseagreen: '#20b2aa',\n darkcyan: '#008b8b',\n teal: '#008080',\n\n // Blues/Cyans\n aqua: '#00ffff',\n cyan: '#00ffff',\n lightcyan: '#e0ffff',\n paleturquoise: '#afeeee',\n aquamarine: '#7fffd4',\n turquoise: '#40e0d0',\n mediumturquoise: '#48d1cc',\n darkturquoise: '#00ced1',\n cadetblue: '#5f9ea0',\n steelblue: '#4682b4',\n lightsteelblue: '#b0c4de',\n powderblue: '#b0e0e6',\n lightblue: '#add8e6',\n skyblue: '#87ceeb',\n lightskyblue: '#87cefa',\n deepskyblue: '#00bfff',\n dodgerblue: '#1e90ff',\n cornflowerblue: '#6495ed',\n royalblue: '#4169e1',\n blue: '#0000ff',\n mediumblue: '#0000cd',\n darkblue: '#00008b',\n navy: '#000080',\n midnightblue: '#191970',\n\n // Browns\n cornsilk: '#fff8dc',\n blanchedalmond: '#ffebcd',\n bisque: '#ffe4c4',\n navajowhite: '#ffdead',\n wheat: '#f5deb3',\n burlywood: '#deb887',\n tan: '#d2b48c',\n rosybrown: '#bc8f8f',\n sandybrown: '#f4a460',\n goldenrod: '#daa520',\n darkgoldenrod: '#b8860b',\n peru: '#cd853f',\n chocolate: '#d2691e',\n saddlebrown: '#8b4513',\n sienna: '#a0522d',\n brown: '#a52a2a',\n maroon: '#800000',\n\n // Whites\n white: '#ffffff',\n snow: '#fffafa',\n honeydew: '#f0fff0',\n mintcream: '#f5fffa',\n azure: '#f0ffff',\n aliceblue: '#f0f8ff',\n ghostwhite: '#f8f8ff',\n whitesmoke: '#f5f5f5',\n seashell: '#fff5ee',\n beige: '#f5f5dc',\n oldlace: '#fdf5e6',\n floralwhite: '#fffaf0',\n ivory: '#fffff0',\n antiquewhite: '#faebd7',\n linen: '#faf0e6',\n lavenderblush: '#fff0f5',\n mistyrose: '#ffe4e1',\n\n // Grays\n gainsboro: '#dcdcdc',\n lightgray: '#d3d3d3',\n lightgrey: '#d3d3d3',\n silver: '#c0c0c0',\n darkgray: '#a9a9a9',\n darkgrey: '#a9a9a9',\n gray: '#808080',\n grey: '#808080',\n dimgray: '#696969',\n dimgrey: '#696969',\n lightslategray: '#778899',\n lightslategrey: '#778899',\n slategray: '#708090',\n slategrey: '#708090',\n darkslategray: '#2f4f4f',\n darkslategrey: '#2f4f4f',\n black: '#000000',\n\n // Special colors\n transparent: '#00000000',\n};\n\n/**\n * Converts CSS named color strings to their hexadecimal equivalents.\n *\n * @param c - The color value to process. Can be any valid Color type.\n * @returns The hexadecimal color value if the input is a known CSS named color,\n * otherwise returns the original input unchanged.\n *\n * @example\n * ```typescript\n * withKnownColor('red'); // '#ff0000'\n * withKnownColor('blue'); // '#0000ff'\n * withKnownColor('#abc123'); // '#abc123' (unchanged)\n * withKnownColor('unknown'); // 'unknown' (unchanged)\n * ```\n *\n * @remarks\n * Only processes strings that contain only letters (both uppercase and lowercase).\n * Case-insensitive matching is performed by converting input to lowercase.\n */\nexport function withKnownColor(c: string): string;\nexport function withKnownColor(c: number): number;\nexport function withKnownColor(c: Color): Color;\nexport function withKnownColor(c: Color): Color {\n if (typeof c !== 'string' || !reOnlyLetters.test(c)) {\n return c;\n }\n\n const name = c.toLowerCase();\n if (name in defaultColors) {\n return defaultColors[name as keyof typeof defaultColors];\n }\n\n return c;\n};\n\n/**\n * Regular expression that matches strings containing only letters (uppercase and lowercase).\n * Used to identify potential CSS named color candidates.\n */\nconst reOnlyLetters = /^[a-zA-Z]+$/;\n","import {\n Hct,\n TonalPalette,\n} from '@poupe/material-color-utilities';\n\nimport {\n type AnyColor,\n Colord,\n type RgbColor,\n} from 'colord';\n\nexport {\n DynamicScheme,\n Hct,\n TonalPalette,\n Variant,\n} from '@poupe/material-color-utilities';\n\nexport {\n type AnyColor,\n Colord,\n type HslaColor,\n type HslColor,\n type RgbColor,\n} from 'colord';\n\nexport type ColorMap<K extends string> = Record<K, Hct>;\n\nexport type HexColor = `#${string}`;\n\n/** {@link RgbColor} variant with optional alpha value */\nexport type RgbaColor = RgbColor & { a?: number };\n\n/** destructured {@link Hct} color with optional alpha value */\nexport interface HctColor {\n a?: number\n c: number\n h: number\n t: number\n}\n\n/** ObjectColor represents a destructured Color object */\nexport type ObjectColor = Exclude<AnyColor, string> | HctColor;\n\n/** Color is any accepted color representation */\nexport type Color = Colord | Hct | number | ObjectColor | string;\n\n/**\n * Core Material Design 3 palettes for DynamicSchemeOptions.\n * Contains tonal palettes for the standard Material Design color roles.\n */\nexport type CorePalettes = {\n error?: TonalPalette\n neutral?: TonalPalette\n neutralVariant?: TonalPalette\n primary: TonalPalette\n secondary?: TonalPalette\n tertiary?: TonalPalette\n};\n\n/**\n * Type representing the valid keys for core palettes in the Material Design 3 color system.\n * Derived from the keys of the {@link CorePalettes} type, representing standard color roles.\n */\nexport type CorePaletteKey = keyof CorePalettes;\n\n/**\n * Readonly array of core palette keys used in Material Design 3 color system.\n * Represents the standard color roles that can be defined in a dynamic color scheme.\n */\nexport const corePaletteKeys: Readonly<CorePaletteKey[]> = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'neutral',\n 'neutralVariant',\n 'error',\n];\n\n/**\n * Represents a custom color definition with tones and color groups for light and dark schemes\n * @param name - Optional name for the custom color\n * @param tones - Readonly tonal palette defining color variations\n * @param light - Color group representing the light scheme variant\n * @param dark - Color group representing the dark scheme variant\n */\nexport type CustomColor = {\n dark: Readonly<ColorGroup>\n light: Readonly<ColorGroup>\n name?: string\n tones: TonalPalette\n};\n\n/**\n * Represents a color group with specific color roles in a color scheme.\n * Defines the color and its on-color variants for different contexts and containers.\n * @param color - The custom color\n * @param onColor - The color used for content on top of the custom color\n * @param colorContainer - The container variant of the custom color\n * @param onColorContainer - The color used for content on the color container\n */\nexport type ColorGroup = {\n color: Hct\n colorContainer: Hct\n onColor: Hct\n onColorContainer: Hct\n};\n","import {\n uint8,\n uint32,\n\n alphaFromArgb,\n blueFromArgb,\n greenFromArgb,\n redFromArgb,\n} from './utils';\n\nimport { withKnownColor } from './default-colors';\n\nimport {\n type Color,\n Colord,\n Hct,\n type HctColor,\n type HexColor,\n type HslaColor,\n type ObjectColor,\n type RgbaColor,\n} from './types';\n\n/*\n * colord\n */\nimport {\n extend,\n colord as origColord,\n} from 'colord';\n\n// extend colord with the mix plugin\nimport mixPlugin from 'colord/plugins/mix';\nextend([mixPlugin]);\n\n/**\n * Determines if the given value is an {@link ObjectColor}\n *\n * @param c - The value to check for color object characteristics\n * @returns A boolean indicating whether the input is a color object\n */\nexport const isObjectColor = (c: unknown): boolean => {\n if (c === null || typeof c !== 'object')\n return false;\n else if (c instanceof Hct || c instanceof Colord)\n return false;\n else if (('r' in c && 'g' in c && 'b' in c) ||\n ('h' in c && 'c' in c && 't' in c) ||\n ('h' in c && 's' in c && 'l' in c) ||\n ('h' in c && 's' in c && 'v' in c) ||\n ('h' in c && 'w' in c && 'b' in c) ||\n ('x' in c && 'y' in c && 'z' in c) ||\n ('l' in c && 'a' in c && 'b' in c) ||\n ('l' in c && 'c' in c && 'h' in c) ||\n ('c' in c && 'm' in c && 'y' in c && 'k' in c)\n )\n return true;\n else\n return false;\n};\n\n/**\n * Normalizes an alpha value to a consistent representation between 0 and 1.\n * @param a - Optional alpha value to normalize\n * @returns Normalized alpha value or undefined if input is undefined\n */\nexport function normalizeAlpha(a: number): number;\nexport function normalizeAlpha(a?: number): number | undefined;\nexport function normalizeAlpha(a?: number): number | undefined {\n if (a === undefined) {\n return undefined;\n }\n // Convert 0..255 to 0..1\n const n = a > 1 ? a / 255 : a;\n // Ensure the value is in range [0, 1]\n return Math.min(Math.max(n, 0), 1);\n}\n\n/**\n * Normalizes the alpha value of an object color if present.\n *\n * @param c - The color object to potentially normalize\n * @returns A new color object with a normalized alpha value, or the original object if no alpha is present\n */\nexport function withNormalizedAlpha(c: ObjectColor): ObjectColor {\n if ('a' in c && c.a !== undefined) {\n const a = normalizeAlpha(c.a);\n return {\n ...c,\n a,\n };\n }\n\n return c;\n}\n\n/*\n * RGB factories\n */\n\n/** @returns the RGB number corresponding to the given {@link RgbaColor} */\nexport const rgbFromRgbaColor = (c: RgbaColor): number => {\n const r255 = uint8(c.r);\n const g255 = uint8(c.g);\n const b255 = uint8(c.b);\n\n return uint32(r255 << 16 | g255 << 8 | b255);\n};\n\n/** @returns the decomposed {@link RgbaColor} corresponding to the given {@link HctColor} */\nexport const rgbaFromHctColor = (c: HctColor): RgbaColor => splitArgb(argbFromHctColor(c));\n\n/** @returns the decomposed {@link RgbaColor} corresponding to the given color */\n/**\n * Returns the decomposed RGBA components for any color type.\n * @param c - The color to decompose\n * @returns The RGBA color object with r, g, b, and optional a components\n */\nexport const rgba = (c: Color): RgbaColor => splitArgb(argb(c));\n\n/*\n * ARGB factories\n */\n\n/** @returns the ARGB number corresponding to the given {@link Hct} */\nexport const argbFromHct = (c: Hct) => c.toInt();\n\n/** @returns the ARGB number corresponding to the given {@link RgbaColor} */\nexport const argbFromRgbaColor = (c: RgbaColor): number => {\n const a = normalizeAlpha(c.a) ?? 1;\n const a255 = uint8(Math.round(a * 255));\n\n return uint32(a255 << 24 | rgbFromRgbaColor(c));\n};\n\n/** @returns the ARGB number corresponding to the given {@link HctColor} */\nexport const argbFromHctColor = (c: HctColor): number => {\n const argb = argbFromHct(Hct.from(c.h, c.c, c.t));\n if (c.a === undefined) {\n return argb;\n }\n\n const a = normalizeAlpha(c.a);\n const a255 = uint8(Math.round(a * 255));\n return uint32(a255 << 24 | (argb & 0xFF_FF_FF));\n};\n\n/** @returns the ARGB number corresponding to the given {@link Colord} */\nexport const argbFromColord = (c: Colord) => {\n if (!c.isValid()) {\n throw new Error('Invalid color');\n }\n return argbFromRgbaColor(c.rgba);\n};\n\n/** @returns the ARGB number corresponding to the color string */\nexport const argbFromString = (s: string) => argbFromColord(colordFromString(s));\n\n/** @returns the the decomposed {@link RgbaColor} corresponding to the given ARGB number */\nexport const splitArgb = (argb: number): RgbaColor => {\n const a255 = alphaFromArgb(argb);\n return {\n r: redFromArgb(argb),\n g: greenFromArgb(argb),\n b: blueFromArgb(argb),\n ...(a255 > 0 ? { a: a255 / 255 } : {}),\n };\n};\n\n/** @returns ARGB representation of the given {@link Color}. */\nexport const argb = (c: Color): number => {\n if (c instanceof Hct) {\n return argbFromHct(c);\n } else if (c instanceof Colord) {\n return argbFromRgbaColor(c.rgba);\n } else if (typeof c === 'number') {\n return c;\n } else if (typeof c === 'string') {\n return argbFromString(c);\n } else if ('h' in c && 'c' in c && 't' in c) {\n return argbFromHctColor(c);\n } else {\n return argbFromColord(colord(c));\n }\n};\n\n/*\n * Colord factories\n */\n\n/** @returns {@link Colord} from an ARGB number */\nexport const colordFromArgb = (argb: number) => origColord(splitArgb(argb));\n\n/** @returns {@link Colord} from a {@link Hct} color */\nexport const colordFromHct = (c: Hct) => colordFromArgb(argbFromHct(c));\n\n/** @returns {@link Colord} from a {@link HctColor} */\nexport const colordFromHctColor = (c: HctColor) => colordFromArgb(argbFromHctColor(c));\n\n/** @returns {@link Colord} from a color string, handling known color names */\nexport const colordFromString = (c: string) => {\n const c1 = origColord(withKnownColor(c) as string);\n if (!c1.isValid()) {\n throw new Error(`Invalid color '${c}'`);\n }\n return c1;\n};\n\n/** @returns {@link Colord} from the given {@link Color}. */\nexport const colord = (c: Color): Colord => {\n if (c instanceof Colord) {\n return c;\n } else if (c instanceof Hct) {\n return colordFromHct(c);\n } else if (typeof c === 'number') {\n return colordFromArgb(c);\n } else if (typeof c === 'string') {\n return colordFromString(c);\n } else if ('h' in c && 'c' in c && 't' in c) {\n return colordFromHctColor(c);\n } else if (!isObjectColor(c)) {\n throw new Error('Invalid color');\n } else if ('a' in c && c.a !== undefined) {\n const a = normalizeAlpha(c.a);\n return origColord({ ...c, a });\n } else {\n return origColord(c);\n }\n};\n\n/*\n * Hct factories\n */\n\n/** @returns {@link Hct} from an ARGB number */\nexport const hctFromArgb = (argb: number) => Hct.fromInt(argb);\n\n/** @returns {@link Hct} from an {@link RgbaColor} object */\nexport const hctFromRgbaColor = (c: RgbaColor): Hct => Hct.fromInt(argbFromRgbaColor(c));\n\n/** @returns {@link Hct} from a {@link Colord} object */\nexport const hctFromColord = (c: Colord): Hct => {\n if (!c.isValid()) {\n throw new Error('Invalid color');\n }\n return hctFromRgbaColor(c.rgba);\n};\n\n/** @returns {@link Hct} from a valid CSS color string */\nexport const hctFromString = (s: string): Hct => hctFromColord(colordFromString(s));\n\n/** @returns {@link HctColor} decomposing the given {@link Hct} color. */\nexport const splitHct = (c: Hct): HctColor => {\n return { h: c.hue, c: c.chroma, t: c.tone };\n};\n\n/** @returns {@link Hct} representation of the given {@link Color}. */\nexport const hct = (c: Color): Hct => {\n if (c instanceof Hct) {\n return c;\n } else if (c instanceof Colord) {\n return hctFromColord(c);\n } else if (typeof c === 'number') {\n return hctFromArgb(c);\n } else if (typeof c === 'string') {\n return hctFromString(c);\n } else if ('h' in c && 'c' in c && 't' in c) {\n return Hct.from(c.h, c.c, c.t);\n } else {\n return hctFromColord(colord(c));\n }\n};\n\n/*\n * HSL factories\n */\n\n/** @returns the {@link HslaColor} for the given {@link Colord} */\nexport const hslFromColord = (c: Colord): HslaColor => {\n if (!c.isValid()) {\n throw new Error('Invalid color');\n }\n return c.toHsl();\n};\n\n/** @returns the {@link HslaColor} for the given ARGB number */\nexport const hslFromArgb = (argb: number) => hslFromColord(colord(splitArgb(argb)));\n\n/** @returns the {@link HslaColor} for the given {@link Hct} */\nexport const hslFromHct = (c: Hct): HslaColor => hslFromArgb(argbFromHct(c));\n\n/** @returns the {@link HslaColor} for the given {@link HctColor} */\nexport const hslFromHctColor = (c: HctColor): HslaColor => hslFromColord(colord(rgbaFromHctColor(c)));\n\n/** @returns the {@link HslaColor} for the given CSS color string */\nexport const hslFromString = (s: string): HslaColor => hslFromColord(colordFromString(s));\n\n/** @returns the {@link HslaColor} for the given {@link Color} */\nexport const hsl = (c: Color): HslaColor => {\n if (c instanceof Hct) {\n return hslFromHct(c);\n } else if (c instanceof Colord) {\n return hslFromColord(c);\n } else if (typeof c === 'number') {\n return hslFromArgb(c);\n } else if (typeof c === 'string') {\n return hslFromString(c);\n } else if ('h' in c && 'c' in c && 't' in c) {\n return hslFromHctColor(c);\n } else {\n return hslFromColord(colord(c));\n }\n};\n\n/*\n * Hex factories\n */\n\n/** @returns the Hex RGB Color string for the given {@link Colord} */\nexport const hexFromColord = (c: Colord): HexColor => {\n if (!c.isValid()) {\n throw new Error('Invalid color');\n }\n return c.toHex() as HexColor;\n};\n\n/** @returns the Hex RGB Color string for the given ARGB number */\nexport const hexFromArgb = (argb: number) => hexFromColord(colord(splitArgb(argb)));\n\n/** @returns the Hex RGB Color string for the given {@link Hct} */\nexport const hexFromHct = (c: Hct) => hexFromArgb(argbFromHct(c));\n\n/** @returns the Hex RGB Color string for the given {@link HctColor} */\nexport const hexFromHctColor = (c: HctColor): HexColor => hexFromColord(origColord(rgbaFromHctColor(c)));\n","import {\n type Color,\n Hct,\n type HexColor,\n} from './types';\n\nimport {\n colord,\n rgba,\n\n hexFromArgb,\n hexFromColord,\n hexFromHct,\n} from './colors';\n\n/**\n * Defines the possible color format types for conversion.\n *\n * @remarks\n * Supports predefined formats like 'numbers', 'rgb', 'hsl', 'hex',\n * or a custom formatting function that takes an Hct color and returns a string.\n */\nexport type ColorFormat = 'hex' | 'hsl' | 'numbers' | 'rgb' | ((c: Hct) => string);\n\n/**\n * Converts an HCT color to a specified format.\n *\n * @param v - The color format to convert to. Can be 'numbers', 'rgb', 'hsl', 'hex', or a custom formatting function.\n * @returns A function that converts an HCT color to the specified string format.\n *\n * @remarks defaults to `'rgb'`\n */\nexport function colorFormatter(v: ColorFormat = 'rgb'): ((c: Hct) => string) {\n if (typeof v === 'function') return v;\n\n if (v === 'numbers') {\n return (c: Hct): string => {\n const { r, g, b } = rgba(c);\n return `${r} ${g} ${b}`;\n };\n }\n\n if (v === 'hsl') return hslString;\n if (v === 'hex') return hexString;\n return rgbaString;\n}\n\n/** @returns the Hex RGB Color string for the given {@link Color} */\nexport const hexString = (c: Color): HexColor => {\n if (c instanceof Hct) {\n return hexFromHct(c);\n } else if (typeof c === 'number') {\n return hexFromArgb(c);\n }\n const c1 = colord(c);\n if (!c1.isValid) {\n throw new Error('Invalid color');\n }\n\n return hexFromColord(c1);\n};\n\n/** @returns the HSL or HSLA color string representation of the given {@link Color}, with optional alpha control */\nexport function hslString(c: Color, alpha: boolean = true): string {\n const c1 = colord(c);\n if (!c1.isValid) {\n throw new Error('Invalid color');\n }\n\n const { h, s, l, a: a0 } = c1.toHsl();\n const a = alpha === false ? 1 : a0;\n\n if (a < 1) {\n return `hsla(${h}, ${s}%, ${l}%, ${a})`;\n }\n return `hsl(${h}, ${s}%, ${l}%)`;\n}\n\n/**\n * Converts a color to an RGB or RGBA string representation.\n * @param c - The color to convert\n * @param alpha - Whether to include alpha channel (defaults to true)\n * @returns A CSS-compatible RGB or RGBA string\n */\nexport const rgbaString = (c: Color, alpha: boolean = true): string => {\n const { r, g, b, a: a0 = 1 } = rgba(c);\n const a = alpha === false ? 1 : a0;\n\n if (a < 1) {\n return `rgb(${r} ${g} ${b} / ${a.toFixed(2)})`;\n }\n return `rgb(${r} ${g} ${b})`;\n};\n","import {\n unsafeKeys,\n} from '@poupe/css';\n\nimport {\n type Color,\n Hct,\n} from './types';\n\nimport {\n colord,\n hctFromColord,\n} from './colors';\n\n/** @returns the result of mixing two colors in given ratios */\nexport function makeColorMix(base: Color, other: Color, ratios: number): Hct;\nexport function makeColorMix(base: Color, other: Color, ratios: Array<number>): Hct[];\nexport function makeColorMix<K extends string>(base: Color, other: Color, ratios: Record<K, number>): Record<K, Hct>;\nexport function makeColorMix<K extends string>(base: Color, other: Color, ratios: Array<number> | number | Record<K, number>): Hct | Hct[] | Record<K, Hct> {\n const c0 = colord(base);\n const c1 = colord(other);\n\n if (typeof ratios === 'number') {\n // single value\n const c = c0.mix(c1, ratios);\n return hctFromColord(c);\n }\n\n if (Array.isArray(ratios)) {\n // array\n const out: Hct[] = [];\n for (const r of ratios) {\n const c = c0.mix(c1, r);\n out.push(hctFromColord(c));\n }\n return out;\n }\n\n // named\n const out = {} as Record<K, Hct>;\n for (const k of unsafeKeys(ratios)) {\n const c = c0.mix(c1, ratios[k]);\n out[k] = hctFromColord(c);\n }\n\n return out;\n}\n","import {\n Blend,\n} from '@poupe/material-color-utilities';\n\nimport {\n type Color,\n type CustomColor,\n Hct,\n TonalPalette,\n} from './types';\n\nimport {\n hct,\n} from './colors';\n\n/**\n * Creates a tonal palette from a color with optional harmonization\n *\n * @param color - The base color to create the palette from\n * @param harmonizeTo - Optional target color to harmonize towards.\n * Harmonization shifts the hue of the base color\n * towards the target color while preserving tone.\n * @param isKeyColor - Whether to preserve the exact tone from the input\n * color (true) as key color or derive a tone\n * algorithmically (false).\n * @defaultValue `true`\n * @returns A TonalPalette instance handling tones from 0-100\n */\nexport function makeTonalPalette(color: Color, harmonizeTo?: Hct, isKeyColor: boolean = true): TonalPalette {\n let c = hct(color);\n if (harmonizeTo) {\n const c1 = Blend.harmonize(c.toInt(), harmonizeTo.toInt());\n c = hct(c1);\n }\n\n if (isKeyColor)\n return TonalPalette.fromHct(c);\n\n return TonalPalette.fromHueAndChroma(c.hue, c.chroma);\n}\n\n/**\n * Generates a custom color optionally harmonized to a target color\n *\n * @param color - The base color to transform into a custom color\n * @param harmonizeTo - Optional target color to harmonize towards.\n * Harmonization blends the hue of the base color\n * with the target while maintaining lightness.\n * @param name - Optional name identifier for the custom color\n * @param isKeyColor - Whether to preserve exact tone from input color\n * as key color. @defaultValue `true`.\n * @returns A CustomColor object with light and dark theme variations,\n * including primary color, on-color, container, and\n * on-container variants for each theme\n */\nexport function makeCustomColor(color: Color, harmonizeTo?: Hct, name?: string, isKeyColor: boolean = true): CustomColor {\n const tones = makeTonalPalette(color, harmonizeTo, isKeyColor);\n\n return makeCustomColorFromPalette(tones, name);\n}\n\n/**\n * Generates a custom color from a given tonal palette with predefined\n * light and dark color variations.\n *\n * Light theme uses tones: 40 (color), 100 (onColor), 90 (container),\n * 10 (onContainer). Dark theme uses tones: 80 (color), 20 (onColor),\n * 30 (container), 90 (onContainer). These follow Material Design 3\n * color system guidelines for optimal contrast and accessibility.\n *\n * @param tones - The tonal palette (0-100 tone range) used to derive\n * color variations\n * @param name - Optional name identifier for the custom color\n * @returns A CustomColor object with light and dark color configurations\n * containing color, onColor, colorContainer, and onColorContainer\n * properties for each theme mode\n */\nexport function makeCustomColorFromPalette(tones: TonalPalette, name?: string): CustomColor {\n return {\n name,\n tones,\n light: {\n color: tones.getHct(40),\n onColor: tones.getHct(100),\n colorContainer: tones.getHct(90),\n onColorContainer: tones.getHct(10),\n },\n dark: {\n color: tones.getHct(80),\n onColor: tones.getHct(20),\n colorContainer: tones.getHct(30),\n onColorContainer: tones.getHct(90),\n },\n };\n}\n","import type { Color, Hct } from './types';\nimport { hct } from './colors';\nimport { makeColorMix } from './mix';\n\n/**\n * Material Design 3 state layer opacity values\n * @see https://m3.material.io/foundations/interaction/states/state-layers\n */\nexport const stateLayerOpacities = {\n hover: 0.08,\n focus: 0.12,\n pressed: 0.12,\n dragged: 0.16,\n disabled: 0.12,\n onDisabled: 0.38,\n} as const;\n\nexport type StateLayerOpacity = typeof stateLayerOpacities;\nexport type InteractionState = keyof Omit<StateLayerOpacity, 'disabled' | 'onDisabled'>;\nexport type StateVariants<T extends string> = {\n [K in T as `${K}-disabled` | `${K}-dragged` | `${K}-focus` | `${K}-hover` | `${K}-pressed`]: Hct;\n} & {\n [K in T as `on-${K}-disabled`]: Hct;\n};\n\n/**\n * State color mix parameters for CSS color-mix() function\n */\nexport interface StateColorMixParams {\n /** The base color CSS variable name */\n baseColor: string\n /** The on-color CSS variable name */\n onColor: string\n /** The opacity percentage for mixing (0-100) */\n opacityPercent: number\n /** The state type */\n state: keyof typeof stateLayerOpacities\n}\n\n/**\n * Get CSS color-mix parameters for creating state colors\n * @param colorName - The base color name (e.g., 'primary', 'secondary')\n * @param state - The state type\n * @param prefix - Optional CSS variable prefix (defaults to empty string)\n * @returns Parameters for creating CSS color-mix\n */\nexport function getStateColorMixParams(\n colorName: string,\n state: keyof Omit<StateLayerOpacity, 'onDisabled'>,\n prefix = '',\n): StateColorMixParams {\n const opacity = stateLayerOpacities[state];\n const isOnColor = colorName.startsWith('on-');\n\n // For disabled state on \"on-colors\", we use different opacity\n const actualOpacity = state === 'disabled' && isOnColor ? stateLayerOpacities.onDisabled : opacity;\n\n // Determine base and on-color names\n let baseColor: string;\n let onColor: string;\n\n if (isOnColor) {\n // For on-colors (e.g., 'on-primary'), the base is the color without 'on-' prefix\n baseColor = colorName.replace('on-', '');\n onColor = colorName;\n } else {\n // For base colors (e.g., 'primary'), we mix with the on-color\n baseColor = colorName;\n onColor = `on-${colorName}`;\n }\n\n return {\n state,\n baseColor: prefix ? `${prefix}${baseColor}` : baseColor,\n onColor: prefix ? `${prefix}${onColor}` : onColor,\n opacityPercent: Math.round(actualOpacity * 100),\n };\n}\n\n/**\n * Creates state layer colors by mixing the on-color with the base color at specified opacities\n * Following Material Design 3 state layer principles\n *\n * @param baseColor - The base/background color\n * @param onColor - The on-color (content color that goes on top of the base)\n * @returns Object with state layer colors for each interaction state\n */\nexport function makeStateLayerColors(baseColor: Color, onColor: Color) {\n const base = hct(baseColor);\n const on = hct(onColor);\n\n return makeColorMix(base, on, {\n hover: stateLayerOpacities.hover,\n focus: stateLayerOpacities.focus,\n pressed: stateLayerOpacities.pressed,\n dragged: stateLayerOpacities.dragged,\n disabled: stateLayerOpacities.disabled,\n onDisabled: stateLayerOpacities.onDisabled,\n });\n}\n\n/**\n * Generates state variants for a set of color pairs\n * Each color should have a corresponding on-color\n *\n * @param colors - Object with base colors and their on-colors\n * @returns Object with state variants for each color\n */\nexport function makeStateVariants<K extends string>(\n colors: Record<K, Color>,\n onColors: Record<`on-${K}`, Color>,\n): StateVariants<K> {\n const result: Record<string, Hct> = {};\n\n for (const colorName in colors) {\n const baseColor = colors[colorName];\n const onColorKey = `on-${colorName}` as `on-${K}`;\n const onColor = onColors[onColorKey];\n\n if (!onColor) {\n throw new Error(`Missing on-color for ${colorName}. Expected key: ${onColorKey}`);\n }\n\n const states = makeStateLayerColors(baseColor, onColor);\n\n result[`${colorName}-hover`] = states.hover;\n result[`${colorName}-focus`] = states.focus;\n result[`${colorName}-pressed`] = states.pressed;\n result[`${colorName}-dragged`] = states.dragged;\n result[`${colorName}-disabled`] = states.disabled;\n result[`on-${colorName}-disabled`] = states.onDisabled;\n }\n\n return result as StateVariants<K>;\n}\n","export * from './colors';\n\nexport * from './default-colors';\nexport * from './formatter';\nexport * from './mix';\nexport * from './palettes';\nexport * from './states';\nexport * from './types';\n// re-export\n//\nexport {\n formatCSSRules,\n formatCSSRulesArray,\n generateCSSRules,\n generateCSSRulesArray,\n} from '@poupe/css';\n\n// tools\n//\nexport const hexColorPattern = /^#([\\da-f]{3}|[\\da-f]{6}|[\\da-f]{8})$/i;\nexport const isHexColor = (s: string = '') => !!hexColorPattern.test(s || '');\n"],"mappings":"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"}