@tenphi/tasty 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +117 -28
  2. package/dist/config.d.ts +13 -1
  3. package/dist/config.js +5 -1
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/index.d.ts +5 -3
  6. package/dist/core/index.js +4 -3
  7. package/dist/debug.d.ts +26 -141
  8. package/dist/debug.js +356 -635
  9. package/dist/debug.js.map +1 -1
  10. package/dist/index.d.ts +5 -3
  11. package/dist/index.js +4 -3
  12. package/dist/parser/classify.js +2 -1
  13. package/dist/parser/classify.js.map +1 -1
  14. package/dist/parser/parser.js +1 -1
  15. package/dist/plugins/okhsl-plugin.js +2 -275
  16. package/dist/plugins/okhsl-plugin.js.map +1 -1
  17. package/dist/plugins/types.d.ts +1 -1
  18. package/dist/properties/index.js +2 -15
  19. package/dist/properties/index.js.map +1 -1
  20. package/dist/ssr/format-property.js +9 -7
  21. package/dist/ssr/format-property.js.map +1 -1
  22. package/dist/styles/color.js +9 -5
  23. package/dist/styles/color.js.map +1 -1
  24. package/dist/styles/createStyle.js +24 -21
  25. package/dist/styles/createStyle.js.map +1 -1
  26. package/dist/styles/index.js +1 -1
  27. package/dist/styles/predefined.js +1 -1
  28. package/dist/styles/predefined.js.map +1 -1
  29. package/dist/styles/types.d.ts +1 -1
  30. package/dist/tasty.d.ts +6 -6
  31. package/dist/tasty.js +1 -1
  32. package/dist/types.d.ts +1 -1
  33. package/dist/utils/color-math.d.ts +46 -0
  34. package/dist/utils/color-math.js +749 -0
  35. package/dist/utils/color-math.js.map +1 -0
  36. package/dist/utils/color-space.d.ts +5 -0
  37. package/dist/utils/color-space.js +229 -0
  38. package/dist/utils/color-space.js.map +1 -0
  39. package/dist/utils/colors.js +3 -1
  40. package/dist/utils/colors.js.map +1 -1
  41. package/dist/utils/mod-attrs.js +1 -1
  42. package/dist/utils/mod-attrs.js.map +1 -1
  43. package/dist/utils/process-tokens.d.ts +3 -13
  44. package/dist/utils/process-tokens.js +18 -98
  45. package/dist/utils/process-tokens.js.map +1 -1
  46. package/dist/utils/styles.d.ts +2 -15
  47. package/dist/utils/styles.js +22 -217
  48. package/dist/utils/styles.js.map +1 -1
  49. package/docs/PIPELINE.md +519 -0
  50. package/docs/README.md +30 -0
  51. package/docs/adoption.md +10 -2
  52. package/docs/comparison.md +11 -6
  53. package/docs/configuration.md +26 -3
  54. package/docs/debug.md +152 -339
  55. package/docs/dsl.md +3 -1
  56. package/docs/getting-started.md +21 -7
  57. package/docs/injector.md +2 -2
  58. package/docs/runtime.md +59 -9
  59. package/docs/ssr.md +2 -2
  60. package/docs/styles.md +1 -1
  61. package/docs/tasty-static.md +13 -2
  62. package/package.json +4 -3
  63. package/dist/utils/hsl-to-rgb.js +0 -38
  64. package/dist/utils/hsl-to-rgb.js.map +0 -1
  65. package/dist/utils/okhsl-to-rgb.js +0 -296
  66. package/dist/utils/okhsl-to-rgb.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-math.js","names":[],"sources":["../../src/utils/color-math.ts"],"sourcesContent":["/**\n * Consolidated color conversion math.\n *\n * Single source of truth for all color space conversions used across the\n * library: sRGB gamma, HSL, OKLab, OKLCH, OKHSL, hex parsing, named\n * colors, and CSS string converters.\n *\n * This module has zero internal imports — it is a leaf dependency.\n *\n * Reference: https://bottosson.github.io/posts/oklab/\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type Vec3 = [number, number, number];\n\n// ============================================================================\n// Conversion Matrices\n// ============================================================================\n\nconst OKLab_to_LMS_M: Vec3[] = [\n [1.0, 0.3963377773761749, 0.2158037573099136],\n [1.0, -0.1055613458156586, -0.0638541728258133],\n [1.0, -0.0894841775298119, -1.2914855480194092],\n];\n\nconst LMS_to_linear_sRGB_M: Vec3[] = [\n [4.076741636075959, -3.307711539258062, 0.2309699031821041],\n [-1.2684379732850313, 2.6097573492876878, -0.3413193760026569],\n [-0.004196076138675526, -0.703418617935936, 1.7076146940746113],\n];\n\nconst OKLab_to_linear_sRGB_coefficients: [\n [[number, number], number[]],\n [[number, number], number[]],\n [[number, number], number[]],\n] = [\n [\n [-1.8817030993265873, -0.8093650129914302],\n [1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245],\n ],\n [\n [1.8144407988010998, -1.194452667805235],\n [0.73956515, -0.45954404, 0.08285427, 0.1254107, 0.14503204],\n ],\n [\n [0.13110757611180954, 1.813339709266608],\n [1.35733652, -0.00915799, -1.1513021, -0.50559606, 0.00692167],\n ],\n];\n\n// ============================================================================\n// Linear Algebra Helpers\n// ============================================================================\n\nconst dotXY = (a: [number, number], b: [number, number]): number =>\n a[0] * b[0] + a[1] * b[1];\n\n// ============================================================================\n// sRGB Gamma <-> Linear\n// ============================================================================\n\nexport function srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nconst INV_GAMMA = 1 / 2.4;\n\nexport function srgbLinearToGamma(val: number): number {\n const sign = val < 0 ? -1 : 1;\n const abs = Math.abs(val);\n return abs > 0.0031308\n ? sign * (1.055 * abs ** INV_GAMMA - 0.055)\n : 12.92 * val;\n}\n\n// ============================================================================\n// OKHSL Constants & Helpers\n// ============================================================================\n\nconst TAU = 2 * Math.PI;\nconst K1 = 0.206;\nconst K2 = 0.03;\nconst K3 = (1.0 + K1) / (1.0 + K2);\nconst EPSILON = 1e-10;\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.max(Math.min(value, max), min);\n\nconst constrainAngle = (angle: number): number => ((angle % 360) + 360) % 360;\n\nconst toe = (x: number): number =>\n 0.5 *\n (K3 * x - K1 + Math.sqrt((K3 * x - K1) * (K3 * x - K1) + 4 * K2 * K3 * x));\n\nconst toeInv = (x: number): number => (x ** 2 + K1 * x) / (K3 * (x + K2));\n\n// ============================================================================\n// OKLab <-> Linear sRGB\n// ============================================================================\n\nconst oklabToLinearSrgb = (lab: Vec3): Vec3 => {\n const L = lab[0];\n const a = lab[1];\n const b = lab[2];\n\n // OKLab -> LMS (inlined OKLab_to_LMS_M multiply)\n const l_ = L + 0.3963377773761749 * a + 0.2158037573099136 * b;\n const m_ = L - 0.1055613458156586 * a - 0.0638541728258133 * b;\n const s_ = L - 0.0894841775298119 * a - 1.2914855480194092 * b;\n\n // Cube\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n // LMS -> linear sRGB (inlined LMS_to_linear_sRGB_M multiply)\n return [\n 4.076741636075959 * l - 3.307711539258062 * m + 0.2309699031821041 * s,\n -1.2684379732850313 * l + 2.6097573492876878 * m - 0.3413193760026569 * s,\n -0.004196076138675526 * l - 0.703418617935936 * m + 1.7076146940746113 * s,\n ];\n};\n\nconst linearSrgbToOklab = (rgb: Vec3): Vec3 => {\n const r = rgb[0];\n const g = rgb[1];\n const b = rgb[2];\n\n // linear sRGB -> LMS (inlined linear_sRGB_to_LMS_M multiply)\n const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;\n const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;\n const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;\n\n // Cube root\n const l_ = Math.cbrt(l);\n const m_ = Math.cbrt(m);\n const s_ = Math.cbrt(s);\n\n // LMS -> OKLab (inlined LMS_to_OKLab_M multiply)\n return [\n 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,\n 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,\n 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,\n ];\n};\n\n// ============================================================================\n// OKHSL Gamut-Mapping Internals\n// ============================================================================\n\nconst computeMaxSaturationOKLC = (a: number, b: number): number => {\n const okCoeff = OKLab_to_linear_sRGB_coefficients;\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp2: [number, number] = [a, b];\n const tmp3: Vec3 = [0, a, b];\n\n let chnlCoeff: number[];\n let chnlLMS: Vec3;\n\n if (dotXY(okCoeff[0][0], tmp2) > 1) {\n chnlCoeff = okCoeff[0][1];\n chnlLMS = lmsToRgb[0];\n } else if (dotXY(okCoeff[1][0], tmp2) > 1) {\n chnlCoeff = okCoeff[1][1];\n chnlLMS = lmsToRgb[1];\n } else {\n chnlCoeff = okCoeff[2][1];\n chnlLMS = lmsToRgb[2];\n }\n\n const [k0, k1, k2, k3, k4] = chnlCoeff;\n const [wl, wm, ws] = chnlLMS;\n\n let sat = k0 + k1 * a + k2 * b + k3 * (a * a) + k4 * a * b;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const l_ = 1.0 + sat * kl;\n const m_ = 1.0 + sat * km;\n const s_ = 1.0 + sat * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const lds = 3.0 * kl * (l_ * l_);\n const mds = 3.0 * km * (m_ * m_);\n const sds = 3.0 * ks * (s_ * s_);\n\n const lds2 = 6.0 * (kl * kl) * l_;\n const mds2 = 6.0 * (km * km) * m_;\n const sds2 = 6.0 * (ks * ks) * s_;\n\n const f = wl * l + wm * m + ws * s;\n const f1 = wl * lds + wm * mds + ws * sds;\n const f2 = wl * lds2 + wm * mds2 + ws * sds2;\n\n sat = sat - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n\n return sat;\n};\n\nconst findCuspOKLCH = (a: number, b: number): [number, number] => {\n const S_cusp = computeMaxSaturationOKLC(a, b);\n const lab: Vec3 = [1, S_cusp * a, S_cusp * b];\n const rgb_at_max = oklabToLinearSrgb(lab);\n const L_cusp = Math.cbrt(\n 1 /\n Math.max(\n Math.max(rgb_at_max[0], rgb_at_max[1]),\n Math.max(rgb_at_max[2], 0.0),\n ),\n );\n return [L_cusp, L_cusp * S_cusp];\n};\n\nconst findGamutIntersectionOKLCH = (\n a: number,\n b: number,\n l1: number,\n c1: number,\n l0: number,\n cusp: [number, number],\n): number => {\n const lmsToRgb = LMS_to_linear_sRGB_M;\n const tmp3: Vec3 = [0, a, b];\n const floatMax = Number.MAX_VALUE;\n\n let t: number;\n\n const dotYZ = (mat: Vec3, vec: Vec3): number =>\n mat[1] * vec[1] + mat[2] * vec[2];\n const dotXYZ = (vec: Vec3, x: number, y: number, z: number): number =>\n vec[0] * x + vec[1] * y + vec[2] * z;\n\n if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0.0) {\n const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * l0) / denom;\n } else {\n const denom = c1 * (cusp[0] - 1.0) + cusp[1] * (l0 - l1);\n t = denom === 0 ? 0 : (cusp[1] * (l0 - 1.0)) / denom;\n\n const dl = l1 - l0;\n const dc = c1;\n\n const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);\n const km = dotYZ(OKLab_to_LMS_M[1], tmp3);\n const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);\n\n const ldt_ = dl + dc * kl;\n const mdt_ = dl + dc * km;\n const sdt_ = dl + dc * ks;\n\n const L = l0 * (1.0 - t) + t * l1;\n const C = t * c1;\n\n const l_ = L + C * kl;\n const m_ = L + C * km;\n const s_ = L + C * ks;\n\n const l = l_ ** 3;\n const m = m_ ** 3;\n const s = s_ ** 3;\n\n const ldt = 3 * ldt_ * l_ * l_;\n const mdt = 3 * mdt_ * m_ * m_;\n const sdt = 3 * sdt_ * s_ * s_;\n\n const ldt2 = 6 * ldt_ * ldt_ * l_;\n const mdt2 = 6 * mdt_ * mdt_ * m_;\n const sdt2 = 6 * sdt_ * sdt_ * s_;\n\n const r_ = dotXYZ(lmsToRgb[0], l, m, s) - 1;\n const r1 = dotXYZ(lmsToRgb[0], ldt, mdt, sdt);\n const r2 = dotXYZ(lmsToRgb[0], ldt2, mdt2, sdt2);\n\n const ur = r1 / (r1 * r1 - 0.5 * r_ * r2);\n let tr = -r_ * ur;\n\n const g_ = dotXYZ(lmsToRgb[1], l, m, s) - 1;\n const g1 = dotXYZ(lmsToRgb[1], ldt, mdt, sdt);\n const g2 = dotXYZ(lmsToRgb[1], ldt2, mdt2, sdt2);\n\n const ug = g1 / (g1 * g1 - 0.5 * g_ * g2);\n let tg = -g_ * ug;\n\n const b_ = dotXYZ(lmsToRgb[2], l, m, s) - 1;\n const b1 = dotXYZ(lmsToRgb[2], ldt, mdt, sdt);\n const b2 = dotXYZ(lmsToRgb[2], ldt2, mdt2, sdt2);\n\n const ub = b1 / (b1 * b1 - 0.5 * b_ * b2);\n let tb = -b_ * ub;\n\n tr = ur >= 0.0 ? tr : floatMax;\n tg = ug >= 0.0 ? tg : floatMax;\n tb = ub >= 0.0 ? tb : floatMax;\n\n t += Math.min(tr, Math.min(tg, tb));\n }\n\n return t;\n};\n\nconst computeSt = (cusp: [number, number]): [number, number] => [\n cusp[1] / cusp[0],\n cusp[1] / (1 - cusp[0]),\n];\n\nconst computeStMid = (a: number, b: number): [number, number] => [\n 0.11516993 +\n 1.0 /\n (7.4477897 +\n 4.1590124 * b +\n a *\n (-2.19557347 +\n 1.75198401 * b +\n a *\n (-2.13704948 -\n 10.02301043 * b +\n a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a)))),\n 0.11239642 +\n 1.0 /\n (1.6132032 -\n 0.68124379 * b +\n a *\n (0.40370612 +\n 0.90148123 * b +\n a *\n (-0.27087943 +\n 0.6122399 * b +\n a * (0.00299215 - 0.45399568 * b - 0.14661872 * a)))),\n];\n\nconst getCs = (\n L: number,\n a: number,\n b: number,\n cusp: [number, number],\n): [number, number, number] => {\n const cMax = findGamutIntersectionOKLCH(a, b, L, 1, L, cusp);\n const stMax = computeSt(cusp);\n const k = cMax / Math.min(L * stMax[0], (1 - L) * stMax[1]);\n const stMid = computeStMid(a, b);\n let ca = L * stMid[0];\n let cb = (1.0 - L) * stMid[1];\n const cMid =\n 0.9 * k * Math.sqrt(Math.sqrt(1.0 / (1.0 / ca ** 4 + 1.0 / cb ** 4)));\n ca = L * 0.4;\n cb = (1.0 - L) * 0.8;\n const c0 = Math.sqrt(1.0 / (1.0 / ca ** 2 + 1.0 / cb ** 2));\n return [c0, cMid, cMax];\n};\n\nconst okhslToOklab = (hsl: Vec3): Vec3 => {\n let h = hsl[0];\n const s = hsl[1];\n const l = hsl[2];\n\n const L = toeInv(l);\n let a = 0;\n let b = 0;\n\n h = constrainAngle(h) / 360.0;\n\n if (L !== 0.0 && L !== 1.0 && s !== 0) {\n const a_ = Math.cos(TAU * h);\n const b_ = Math.sin(TAU * h);\n\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n let t: number, k0: number, k1: number, k2: number;\n\n if (s < mid) {\n t = midInv * s;\n k0 = 0.0;\n k1 = mid * c0;\n k2 = 1.0 - k1 / cMid;\n } else {\n t = 5 * (s - 0.8);\n k0 = cMid;\n k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n k2 = 1.0 - k1 / (cMax - cMid);\n }\n\n const c = k0 + (t * k1) / (1.0 - k2 * t);\n a = c * a_;\n b = c * b_;\n }\n\n return [L, a, b];\n};\n\nconst oklabToOkhsl = (lab: Vec3): Vec3 => {\n const L = lab[0];\n const a = lab[1];\n const b = lab[2];\n\n const C = Math.sqrt(a * a + b * b);\n\n if (C < EPSILON) {\n return [0, 0, toe(L)];\n }\n\n const a_ = a / C;\n const b_ = b / C;\n\n let h = Math.atan2(b, a) * (180 / Math.PI);\n h = constrainAngle(h);\n\n const cusp = findCuspOKLCH(a_, b_);\n const Cs = getCs(L, a_, b_, cusp);\n const [c0, cMid, cMax] = Cs;\n\n const mid = 0.8;\n const midInv = 1.25;\n\n let s: number;\n\n if (C < cMid) {\n const k1 = mid * c0;\n const k2 = 1.0 - k1 / cMid;\n const t = C / (k1 + C * k2);\n s = t / midInv;\n } else {\n const k0 = cMid;\n const k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n const k2 = 1.0 - k1 / (cMax - cMid);\n const cDiff = C - k0;\n const t = cDiff / (k1 + cDiff * k2);\n s = mid + t / 5;\n }\n\n const l = toe(L);\n\n return [h, clamp(s, 0, 1), clamp(l, 0, 1)];\n};\n\n// ============================================================================\n// Public Conversions — Pure Math (Vec3 in / Vec3 out)\n// ============================================================================\n\n/**\n * HSL to RGB.\n * Algorithm from CSS Color 4 spec.\n *\n * @param h - Hue in degrees (0-360)\n * @param s - Saturation (0-1)\n * @param l - Lightness (0-1)\n * @returns RGB values in 0-255 range (may have fractional values)\n */\nexport function hslToRgbValues(h: number, s: number, l: number): Vec3 {\n const a = s * Math.min(l, 1 - l);\n\n const f = (n: number): number => {\n const k = (n + h / 30) % 12;\n return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));\n };\n\n return [f(0) * 255, f(8) * 255, f(4) * 255];\n}\n\n/**\n * RGB (0-255) to HSL.\n * @returns [h (0-360), s (0-1), l (0-1)]\n */\nexport function rgbToHsl(r: number, g: number, b: number): Vec3 {\n r /= 255;\n g /= 255;\n b /= 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n\n if (max === min) {\n return [0, 0, l];\n }\n\n const d = max - min;\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n let h: number;\n if (max === r) {\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n } else if (max === g) {\n h = ((b - r) / d + 2) / 6;\n } else {\n h = ((r - g) / d + 4) / 6;\n }\n\n return [h * 360, s, l];\n}\n\n/**\n * RGB (0-255) to OKLCH via sRGB -> linear sRGB -> OKLab -> OKLCH.\n * @returns [L, C, H] where H is in degrees (0-360)\n */\nexport function rgbToOklch(r: number, g: number, b: number): Vec3 {\n const lr = srgbToLinear(r / 255);\n const lg = srgbToLinear(g / 255);\n const lb = srgbToLinear(b / 255);\n\n const linear: Vec3 = [lr, lg, lb];\n const lab = linearSrgbToOklab(linear);\n\n const [L, a, bLab] = lab;\n const C = Math.sqrt(a * a + bLab * bLab);\n let H = (Math.atan2(bLab, a) * 180) / Math.PI;\n if (H < 0) H += 360;\n\n return [L, C, H];\n}\n\n/**\n * OKHSL to sRGB (0-1 range).\n * @param h - Hue in degrees (0-360)\n * @param s - Saturation (0-1)\n * @param l - Lightness (0-1)\n * @returns sRGB values in 0-1 range, clamped to gamut\n */\nexport function okhslToSrgb(h: number, s: number, l: number): Vec3 {\n const oklab = okhslToOklab([h, s, l]);\n const linearRGB = oklabToLinearSrgb(oklab);\n\n return [\n clamp(srgbLinearToGamma(linearRGB[0]), 0, 1),\n clamp(srgbLinearToGamma(linearRGB[1]), 0, 1),\n clamp(srgbLinearToGamma(linearRGB[2]), 0, 1),\n ];\n}\n\n/**\n * OKLCH to sRGB (0-255 range).\n * @param L - Lightness (0-1)\n * @param C - Chroma (typically 0-0.4)\n * @param H - Hue in degrees (0-360)\n * @returns RGB values in 0-255 range, clamped to gamut\n */\nexport function oklchToRgbValues(L: number, C: number, H: number): Vec3 {\n const hRad = (H * Math.PI) / 180;\n const a = C * Math.cos(hRad);\n const b = C * Math.sin(hRad);\n const linear = oklabToLinearSrgb([L, a, b]);\n\n return [\n clamp(srgbLinearToGamma(linear[0]), 0, 1) * 255,\n clamp(srgbLinearToGamma(linear[1]), 0, 1) * 255,\n clamp(srgbLinearToGamma(linear[2]), 0, 1) * 255,\n ];\n}\n\n/**\n * sRGB (0-1 range) to OKHSL.\n * @returns [H (0-360), S (0-1), L (0-1)]\n */\nexport function srgbToOkhsl(rgb: Vec3): Vec3 {\n const linear: Vec3 = [\n srgbToLinear(rgb[0]),\n srgbToLinear(rgb[1]),\n srgbToLinear(rgb[2]),\n ];\n const oklab = linearSrgbToOklab(linear);\n return oklabToOkhsl(oklab);\n}\n\n// ============================================================================\n// Named CSS Colors\n// ============================================================================\n\nlet _namedColorHex: Map<string, string> | null = null;\n\nexport function getNamedColorHex(): Map<string, string> {\n if (_namedColorHex) return _namedColorHex;\n _namedColorHex = new Map([\n ['aliceblue', '#f0f8ff'],\n ['antiquewhite', '#faebd7'],\n ['aqua', '#00ffff'],\n ['aquamarine', '#7fffd4'],\n ['azure', '#f0ffff'],\n ['beige', '#f5f5dc'],\n ['bisque', '#ffe4c4'],\n ['black', '#000000'],\n ['blanchedalmond', '#ffebcd'],\n ['blue', '#0000ff'],\n ['blueviolet', '#8a2be2'],\n ['brown', '#a52a2a'],\n ['burlywood', '#deb887'],\n ['cadetblue', '#5f9ea0'],\n ['chartreuse', '#7fff00'],\n ['chocolate', '#d2691e'],\n ['coral', '#ff7f50'],\n ['cornflowerblue', '#6495ed'],\n ['cornsilk', '#fff8dc'],\n ['crimson', '#dc143c'],\n ['cyan', '#00ffff'],\n ['darkblue', '#00008b'],\n ['darkcyan', '#008b8b'],\n ['darkgoldenrod', '#b8860b'],\n ['darkgray', '#a9a9a9'],\n ['darkgreen', '#006400'],\n ['darkgrey', '#a9a9a9'],\n ['darkkhaki', '#bdb76b'],\n ['darkmagenta', '#8b008b'],\n ['darkolivegreen', '#556b2f'],\n ['darkorange', '#ff8c00'],\n ['darkorchid', '#9932cc'],\n ['darkred', '#8b0000'],\n ['darksalmon', '#e9967a'],\n ['darkseagreen', '#8fbc8f'],\n ['darkslateblue', '#483d8b'],\n ['darkslategray', '#2f4f4f'],\n ['darkslategrey', '#2f4f4f'],\n ['darkturquoise', '#00ced1'],\n ['darkviolet', '#9400d3'],\n ['deeppink', '#ff1493'],\n ['deepskyblue', '#00bfff'],\n ['dimgray', '#696969'],\n ['dimgrey', '#696969'],\n ['dodgerblue', '#1e90ff'],\n ['firebrick', '#b22222'],\n ['floralwhite', '#fffaf0'],\n ['forestgreen', '#228b22'],\n ['fuchsia', '#ff00ff'],\n ['gainsboro', '#dcdcdc'],\n ['ghostwhite', '#f8f8ff'],\n ['gold', '#ffd700'],\n ['goldenrod', '#daa520'],\n ['gray', '#808080'],\n ['green', '#008000'],\n ['greenyellow', '#adff2f'],\n ['grey', '#808080'],\n ['honeydew', '#f0fff0'],\n ['hotpink', '#ff69b4'],\n ['indianred', '#cd5c5c'],\n ['indigo', '#4b0082'],\n ['ivory', '#fffff0'],\n ['khaki', '#f0e68c'],\n ['lavender', '#e6e6fa'],\n ['lavenderblush', '#fff0f5'],\n ['lawngreen', '#7cfc00'],\n ['lemonchiffon', '#fffacd'],\n ['lightblue', '#add8e6'],\n ['lightcoral', '#f08080'],\n ['lightcyan', '#e0ffff'],\n ['lightgoldenrodyellow', '#fafad2'],\n ['lightgray', '#d3d3d3'],\n ['lightgreen', '#90ee90'],\n ['lightgrey', '#d3d3d3'],\n ['lightpink', '#ffb6c1'],\n ['lightsalmon', '#ffa07a'],\n ['lightseagreen', '#20b2aa'],\n ['lightskyblue', '#87cefa'],\n ['lightslategray', '#778899'],\n ['lightslategrey', '#778899'],\n ['lightsteelblue', '#b0c4de'],\n ['lightyellow', '#ffffe0'],\n ['lime', '#00ff00'],\n ['limegreen', '#32cd32'],\n ['linen', '#faf0e6'],\n ['magenta', '#ff00ff'],\n ['maroon', '#800000'],\n ['mediumaquamarine', '#66cdaa'],\n ['mediumblue', '#0000cd'],\n ['mediumorchid', '#ba55d3'],\n ['mediumpurple', '#9370db'],\n ['mediumseagreen', '#3cb371'],\n ['mediumslateblue', '#7b68ee'],\n ['mediumspringgreen', '#00fa9a'],\n ['mediumturquoise', '#48d1cc'],\n ['mediumvioletred', '#c71585'],\n ['midnightblue', '#191970'],\n ['mintcream', '#f5fffa'],\n ['mistyrose', '#ffe4e1'],\n ['moccasin', '#ffe4b5'],\n ['navajowhite', '#ffdead'],\n ['navy', '#000080'],\n ['oldlace', '#fdf5e6'],\n ['olive', '#808000'],\n ['olivedrab', '#6b8e23'],\n ['orange', '#ffa500'],\n ['orangered', '#ff4500'],\n ['orchid', '#da70d6'],\n ['palegoldenrod', '#eee8aa'],\n ['palegreen', '#98fb98'],\n ['paleturquoise', '#afeeee'],\n ['palevioletred', '#db7093'],\n ['papayawhip', '#ffefd5'],\n ['peachpuff', '#ffdab9'],\n ['peru', '#cd853f'],\n ['pink', '#ffc0cb'],\n ['plum', '#dda0dd'],\n ['powderblue', '#b0e0e6'],\n ['purple', '#800080'],\n ['rebeccapurple', '#663399'],\n ['red', '#ff0000'],\n ['rosybrown', '#bc8f8f'],\n ['royalblue', '#4169e1'],\n ['saddlebrown', '#8b4513'],\n ['salmon', '#fa8072'],\n ['sandybrown', '#f4a460'],\n ['seagreen', '#2e8b57'],\n ['seashell', '#fff5ee'],\n ['sienna', '#a0522d'],\n ['silver', '#c0c0c0'],\n ['skyblue', '#87ceeb'],\n ['slateblue', '#6a5acd'],\n ['slategray', '#708090'],\n ['slategrey', '#708090'],\n ['snow', '#fffafa'],\n ['springgreen', '#00ff7f'],\n ['steelblue', '#4682b4'],\n ['tan', '#d2b48c'],\n ['teal', '#008080'],\n ['thistle', '#d8bfd8'],\n ['tomato', '#ff6347'],\n ['turquoise', '#40e0d0'],\n ['violet', '#ee82ee'],\n ['wheat', '#f5deb3'],\n ['white', '#ffffff'],\n ['whitesmoke', '#f5f5f5'],\n ['yellow', '#ffff00'],\n ['yellowgreen', '#9acd32'],\n ]);\n return _namedColorHex;\n}\n\n// ============================================================================\n// String Converters\n// ============================================================================\n\nconst hexCharToNum = (c: number): number => {\n if (c >= 48 && c <= 57) return c - 48; // 0-9\n if (c >= 65 && c <= 70) return c - 55; // A-F\n if (c >= 97 && c <= 102) return c - 87; // a-f\n return -1;\n};\n\n/**\n * Parse a hex color string directly to RGB 0-255 values.\n * Supports 3, 4, 6, and 8 character hex values (with or without `#`).\n * Returns null for invalid input.\n */\nexport function hexToRgbValues(hex: string): Vec3 | null {\n let start = 0;\n if (hex.charCodeAt(0) === 35) start = 1; // '#'\n const len = hex.length - start;\n\n if (len === 3 || len === 4) {\n const r = hexCharToNum(hex.charCodeAt(start));\n const g = hexCharToNum(hex.charCodeAt(start + 1));\n const b = hexCharToNum(hex.charCodeAt(start + 2));\n if (r < 0 || g < 0 || b < 0) return null;\n return [r * 17, g * 17, b * 17];\n }\n\n if (len === 6 || len === 8) {\n const r1 = hexCharToNum(hex.charCodeAt(start));\n const r2 = hexCharToNum(hex.charCodeAt(start + 1));\n const g1 = hexCharToNum(hex.charCodeAt(start + 2));\n const g2 = hexCharToNum(hex.charCodeAt(start + 3));\n const b1 = hexCharToNum(hex.charCodeAt(start + 4));\n const b2 = hexCharToNum(hex.charCodeAt(start + 5));\n if (r1 < 0 || r2 < 0 || g1 < 0 || g2 < 0 || b1 < 0 || b2 < 0) return null;\n return [r1 * 16 + r2, g1 * 16 + g2, b1 * 16 + b2];\n }\n\n return null;\n}\n\n/**\n * Parse a hex color string to RGBA values (RGB 0-255, alpha 0-1).\n * Supports 3, 4, 6, and 8 character hex values (with or without `#`).\n * For 3/6-char hex (no alpha channel), alpha defaults to 1.\n */\nexport function hexToRgbaValues(\n hex: string,\n): [number, number, number, number] | null {\n let start = 0;\n if (hex.charCodeAt(0) === 35) start = 1; // '#'\n const len = hex.length - start;\n\n if (len === 3) {\n const r = hexCharToNum(hex.charCodeAt(start));\n const g = hexCharToNum(hex.charCodeAt(start + 1));\n const b = hexCharToNum(hex.charCodeAt(start + 2));\n if (r < 0 || g < 0 || b < 0) return null;\n return [r * 17, g * 17, b * 17, 1];\n }\n\n if (len === 4) {\n const r = hexCharToNum(hex.charCodeAt(start));\n const g = hexCharToNum(hex.charCodeAt(start + 1));\n const b = hexCharToNum(hex.charCodeAt(start + 2));\n const a = hexCharToNum(hex.charCodeAt(start + 3));\n if (r < 0 || g < 0 || b < 0 || a < 0) return null;\n return [r * 17, g * 17, b * 17, (a * 17) / 255];\n }\n\n if (len === 6) {\n const r1 = hexCharToNum(hex.charCodeAt(start));\n const r2 = hexCharToNum(hex.charCodeAt(start + 1));\n const g1 = hexCharToNum(hex.charCodeAt(start + 2));\n const g2 = hexCharToNum(hex.charCodeAt(start + 3));\n const b1 = hexCharToNum(hex.charCodeAt(start + 4));\n const b2 = hexCharToNum(hex.charCodeAt(start + 5));\n if (r1 < 0 || r2 < 0 || g1 < 0 || g2 < 0 || b1 < 0 || b2 < 0) return null;\n return [r1 * 16 + r2, g1 * 16 + g2, b1 * 16 + b2, 1];\n }\n\n if (len === 8) {\n const r1 = hexCharToNum(hex.charCodeAt(start));\n const r2 = hexCharToNum(hex.charCodeAt(start + 1));\n const g1 = hexCharToNum(hex.charCodeAt(start + 2));\n const g2 = hexCharToNum(hex.charCodeAt(start + 3));\n const b1 = hexCharToNum(hex.charCodeAt(start + 4));\n const b2 = hexCharToNum(hex.charCodeAt(start + 5));\n const a1 = hexCharToNum(hex.charCodeAt(start + 6));\n const a2 = hexCharToNum(hex.charCodeAt(start + 7));\n if (\n r1 < 0 ||\n r2 < 0 ||\n g1 < 0 ||\n g2 < 0 ||\n b1 < 0 ||\n b2 < 0 ||\n a1 < 0 ||\n a2 < 0\n )\n return null;\n return [r1 * 16 + r2, g1 * 16 + g2, b1 * 16 + b2, (a1 * 16 + a2) / 255];\n }\n\n return null;\n}\n\n/**\n * Convert hex color string to `rgb()` CSS string.\n * Supports 3, 4, 6, and 8 character hex values (with or without `#`).\n */\nexport function hexToRgb(hex: string): string | null {\n const matched = hex\n .replace(\n /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i,\n (_m: string, r: string, g: string, b: string) =>\n '#' + r + r + g + g + b + b,\n )\n .substring(1)\n .match(/.{2}/g);\n\n if (!matched) return null;\n\n const rgba = matched.map(\n (x: string, i: number) => parseInt(x, 16) * (i === 3 ? 1 / 255 : 1),\n );\n\n if (rgba.some((v) => Number.isNaN(v))) {\n return null;\n }\n\n if (rgba.length >= 3) {\n return `rgb(${rgba.slice(0, 3).join(' ')}${rgba.length > 3 ? ` / ${rgba[3]}` : ''})`;\n }\n\n return null;\n}\n\n/**\n * Extract RGB values from an `rgb()`/`rgba()` string.\n * Supports comma-separated, space-separated, fractional, percentage,\n * and slash alpha notation.\n *\n * @returns Array of RGB values (0-255 range), converting percentages as needed.\n */\nexport function getRgbValuesFromRgbaString(str: string): number[] {\n const match = str.match(/rgba?\\(([^)]+)\\)/i);\n if (!match) return [];\n\n const inner = match[1].trim();\n const [colorPart] = inner.split('/');\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n return parts.slice(0, 3).map((part) => {\n part = part.trim();\n if (part.endsWith('%')) {\n return (parseFloat(part) / 100) * 255;\n }\n return parseFloat(part);\n });\n}\n\n/**\n * Convert any recognized color string to an `rgb()` CSS string.\n * Handles hex, `okhsl()`, `hsl()`/`hsla()`, named CSS colors,\n * and `rgb()`/`rgba()` pass-through.\n */\nexport function strToRgb(\n color: string,\n _ignoreAlpha = false,\n): string | null | undefined {\n if (!color) return undefined;\n\n if (color.startsWith('rgb')) return color;\n if (color.startsWith('#')) return hexToRgb(color);\n if (color.startsWith('oklch(')) return oklchStringToRgb(color);\n if (color.startsWith('okhsl(')) return okhslStringToRgb(color);\n if (color.startsWith('hsl')) return hslStringToRgb(color);\n\n const namedHex = getNamedColorHex().get(color.toLowerCase());\n if (namedHex) return hexToRgb(namedHex);\n\n return null;\n}\n\n/**\n * Convert an HSL/HSLA color string to an `rgb()`/`rgba()` CSS string.\n * Supports modern space-separated and legacy comma-separated syntax,\n * deg/turn/rad hue units, and slash alpha notation.\n */\nexport function hslStringToRgb(hslStr: string): string | null {\n const match = hslStr.match(/hsla?\\(([^)]+)\\)/i);\n if (!match) return null;\n\n const inner = match[1].trim();\n const [colorPart, slashAlpha] = inner.split('/');\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n if (parts.length < 3) return null;\n\n const alphaPart = slashAlpha?.trim() || (parts.length >= 4 ? parts[3] : null);\n\n let h = parseFloat(parts[0]);\n const hueStr = parts[0].toLowerCase();\n if (hueStr.endsWith('turn')) h = parseFloat(hueStr) * 360;\n else if (hueStr.endsWith('rad')) h = (parseFloat(hueStr) * 180) / Math.PI;\n h = ((h % 360) + 360) % 360;\n\n const parsePercent = (val: string): number => {\n const num = parseFloat(val);\n return val.includes('%') ? num / 100 : num;\n };\n const s = Math.max(0, Math.min(1, parsePercent(parts[1])));\n const l = Math.max(0, Math.min(1, parsePercent(parts[2])));\n\n const [r, g, b] = hslToRgbValues(h, s, l);\n\n if (alphaPart) {\n const alpha = parseFloat(alphaPart.trim());\n return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${alpha})`;\n }\n\n return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)})`;\n}\n\n/**\n * Convert an `okhsl()` color string to an `rgb()`/`rgba()` CSS string.\n * Supports deg/turn/rad hue units and percentage saturation/lightness.\n */\nexport function okhslStringToRgb(okhslStr: string): string | null {\n const match = okhslStr.match(/okhsl\\(([^)]+)\\)/i);\n if (!match) return null;\n\n const inner = match[1].trim();\n const [colorPart, alphaPart] = inner.split('/');\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n if (parts.length < 3) return null;\n\n let h = parseFloat(parts[0]);\n const hueStr = parts[0].toLowerCase();\n if (hueStr.endsWith('turn')) h = parseFloat(hueStr) * 360;\n else if (hueStr.endsWith('rad')) h = (parseFloat(hueStr) * 180) / Math.PI;\n else if (hueStr.endsWith('deg')) h = parseFloat(hueStr);\n\n const parsePercent = (val: string): number => {\n const num = parseFloat(val);\n return val.includes('%') ? num / 100 : num;\n };\n const s = Math.max(0, Math.min(1, parsePercent(parts[1])));\n const l = Math.max(0, Math.min(1, parsePercent(parts[2])));\n\n const [r, g, b] = okhslToSrgb(h, s, l);\n\n const r255 = Math.round(Math.max(0, Math.min(1, r)) * 255);\n const g255 = Math.round(Math.max(0, Math.min(1, g)) * 255);\n const b255 = Math.round(Math.max(0, Math.min(1, b)) * 255);\n\n if (alphaPart) {\n const alpha = parseFloat(alphaPart.trim());\n return `rgba(${r255}, ${g255}, ${b255}, ${alpha})`;\n }\n\n return `rgb(${r255} ${g255} ${b255})`;\n}\n\n/**\n * Convert an `oklch()` color string to an `rgb()`/`rgba()` CSS string.\n * Supports deg/turn/rad hue units and percentage lightness.\n */\nexport function oklchStringToRgb(oklchStr: string): string | null {\n const match = oklchStr.match(/oklch\\(([^)]+)\\)/i);\n if (!match) return null;\n\n const inner = match[1].trim();\n const [colorPart, alphaPart] = inner.split('/');\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n if (parts.length < 3) return null;\n\n const parsePercent = (val: string): number => {\n const num = parseFloat(val);\n return val.includes('%') ? num / 100 : num;\n };\n const L = Math.max(0, Math.min(1, parsePercent(parts[0])));\n const C = Math.max(0, parseFloat(parts[1]));\n\n let H = parseFloat(parts[2]);\n const hueStr = parts[2].toLowerCase();\n if (hueStr.endsWith('turn')) H = parseFloat(hueStr) * 360;\n else if (hueStr.endsWith('rad')) H = (parseFloat(hueStr) * 180) / Math.PI;\n else if (hueStr.endsWith('deg')) H = parseFloat(hueStr);\n\n const [r, g, b] = oklchToRgbValues(L, C, H);\n\n if (alphaPart) {\n const alpha = parseFloat(alphaPart.trim());\n return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${alpha})`;\n }\n\n return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)})`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region src/utils/color-space.d.ts
2
+ type ColorSpace = 'rgb' | 'hsl' | 'oklch';
3
+ //#endregion
4
+ export { ColorSpace };
5
+ //# sourceMappingURL=color-space.d.ts.map
@@ -0,0 +1,229 @@
1
+ import { Lru } from "../parser/lru.js";
2
+ import { getRgbValuesFromRgbaString, hexToRgbaValues, hslToRgbValues, okhslToSrgb, oklchToRgbValues, rgbToHsl, rgbToOklch, strToRgb } from "./color-math.js";
3
+
4
+ //#region src/utils/color-space.ts
5
+ let currentColorSpace = "oklch";
6
+ const colorSpaceCache = new Lru(500);
7
+ const componentsCache = new Lru(500);
8
+ function clearColorCaches() {
9
+ colorSpaceCache.clear();
10
+ componentsCache.clear();
11
+ }
12
+ function setColorSpace(space) {
13
+ currentColorSpace = space;
14
+ clearColorCaches();
15
+ }
16
+ function resetColorSpace() {
17
+ currentColorSpace = "oklch";
18
+ clearColorCaches();
19
+ }
20
+ function getColorSpaceSuffix() {
21
+ return currentColorSpace;
22
+ }
23
+ function getColorSpaceFunc() {
24
+ return currentColorSpace;
25
+ }
26
+ function formatNum(n, precision) {
27
+ return parseFloat(n.toFixed(precision)).toString();
28
+ }
29
+ function formatRgbComponent(n) {
30
+ return parseFloat(n.toFixed(1)).toString();
31
+ }
32
+ function formatAlpha(a) {
33
+ if (a === 0) return "0";
34
+ return parseFloat(a.toFixed(4)).toString();
35
+ }
36
+ function rgbValuesToColorString(r, g, b, space, alpha) {
37
+ const alphaSuffix = alpha != null && alpha < 1 ? ` / ${formatAlpha(alpha)}` : "";
38
+ switch (space) {
39
+ case "rgb": return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)}${alphaSuffix})`;
40
+ case "hsl": {
41
+ const [h, s, l] = rgbToHsl(r, g, b);
42
+ return `hsl(${formatNum(h, 2)} ${formatNum(s * 100, 2)}% ${formatNum(l * 100, 2)}%${alphaSuffix})`;
43
+ }
44
+ case "oklch": {
45
+ const [L, C, H] = rgbToOklch(r, g, b);
46
+ return `oklch(${formatNum(L, 5)} ${formatNum(C, 5)} ${formatNum(H, 2)}${alphaSuffix})`;
47
+ }
48
+ }
49
+ }
50
+ function rgbValuesToComponents(r, g, b, space) {
51
+ switch (space) {
52
+ case "rgb": return `${formatRgbComponent(r)} ${formatRgbComponent(g)} ${formatRgbComponent(b)}`;
53
+ case "hsl": {
54
+ const [h, s, l] = rgbToHsl(r, g, b);
55
+ return `${formatNum(h, 2)} ${formatNum(s * 100, 2)}% ${formatNum(l * 100, 2)}%`;
56
+ }
57
+ case "oklch": {
58
+ const [L, C, H] = rgbToOklch(r, g, b);
59
+ return `${formatNum(L, 5)} ${formatNum(C, 5)} ${formatNum(H, 2)}`;
60
+ }
61
+ }
62
+ }
63
+ const parseColorFuncArgs = (str, prefix) => {
64
+ const start = str.indexOf("(", prefix.length - 1);
65
+ const end = str.lastIndexOf(")");
66
+ if (start < 0 || end < 0) return null;
67
+ const inner = str.slice(start + 1, end).trim();
68
+ const slashIdx = inner.indexOf("/");
69
+ let colorPart;
70
+ let alpha = 1;
71
+ if (slashIdx >= 0) {
72
+ colorPart = inner.slice(0, slashIdx);
73
+ const alphaStr = inner.slice(slashIdx + 1).trim();
74
+ if (alphaStr) {
75
+ alpha = alphaStr.endsWith("%") ? parseFloat(alphaStr) / 100 : parseFloat(alphaStr);
76
+ if (Number.isNaN(alpha)) alpha = 1;
77
+ }
78
+ } else colorPart = inner;
79
+ const parts = colorPart.trim().split(/[,\s]+/).filter(Boolean);
80
+ if (parts.length < 3) return null;
81
+ if (parts.length >= 4 && slashIdx < 0) {
82
+ const legacyAlpha = parseFloat(parts[3]);
83
+ if (!Number.isNaN(legacyAlpha)) alpha = legacyAlpha;
84
+ }
85
+ return {
86
+ parts,
87
+ alpha
88
+ };
89
+ };
90
+ const parseHue = (hueStr) => {
91
+ let h = parseFloat(hueStr);
92
+ const lower = hueStr.toLowerCase();
93
+ if (lower.endsWith("turn")) h = parseFloat(lower) * 360;
94
+ else if (lower.endsWith("rad")) h = parseFloat(lower) * 180 / Math.PI;
95
+ return (h % 360 + 360) % 360;
96
+ };
97
+ const parsePercent = (val) => {
98
+ const num = parseFloat(val);
99
+ return val.includes("%") ? num / 100 : num;
100
+ };
101
+ const clamp01 = (n) => Math.max(0, Math.min(1, n));
102
+ function resolveToRgbaValues(color) {
103
+ const trimmed = color.trim().toLowerCase();
104
+ if (trimmed.startsWith("rgb")) {
105
+ const parsed = parseColorFuncArgs(trimmed, "rgb");
106
+ if (!parsed || parsed.parts.length < 3) return null;
107
+ return [
108
+ parsed.parts[0].endsWith("%") ? parseFloat(parsed.parts[0]) / 100 * 255 : parseFloat(parsed.parts[0]),
109
+ parsed.parts[1].endsWith("%") ? parseFloat(parsed.parts[1]) / 100 * 255 : parseFloat(parsed.parts[1]),
110
+ parsed.parts[2].endsWith("%") ? parseFloat(parsed.parts[2]) / 100 * 255 : parseFloat(parsed.parts[2]),
111
+ parsed.alpha
112
+ ];
113
+ }
114
+ if (trimmed.startsWith("#")) return hexToRgbaValues(trimmed);
115
+ if (trimmed.startsWith("hsl")) {
116
+ const parsed = parseColorFuncArgs(trimmed, "hsl");
117
+ if (!parsed) return null;
118
+ const [r, g, b] = hslToRgbValues(parseHue(parsed.parts[0]), clamp01(parsePercent(parsed.parts[1])), clamp01(parsePercent(parsed.parts[2])));
119
+ return [
120
+ r,
121
+ g,
122
+ b,
123
+ parsed.alpha
124
+ ];
125
+ }
126
+ if (trimmed.startsWith("oklch(")) {
127
+ const parsed = parseColorFuncArgs(trimmed, "oklch");
128
+ if (!parsed) return null;
129
+ const [r, g, b] = oklchToRgbValues(clamp01(parsePercent(parsed.parts[0])), Math.max(0, parseFloat(parsed.parts[1])), parseHue(parsed.parts[2]));
130
+ return [
131
+ r,
132
+ g,
133
+ b,
134
+ parsed.alpha
135
+ ];
136
+ }
137
+ if (trimmed.startsWith("okhsl(")) {
138
+ const parsed = parseColorFuncArgs(trimmed, "okhsl");
139
+ if (!parsed) return null;
140
+ const [r, g, b] = okhslToSrgb(parseHue(parsed.parts[0]), clamp01(parsePercent(parsed.parts[1])), clamp01(parsePercent(parsed.parts[2])));
141
+ return [
142
+ clamp01(r) * 255,
143
+ clamp01(g) * 255,
144
+ clamp01(b) * 255,
145
+ parsed.alpha
146
+ ];
147
+ }
148
+ const fallback = strToRgb(trimmed);
149
+ if (fallback) {
150
+ if (fallback !== trimmed) return resolveToRgbaValues(fallback);
151
+ const vals = getRgbValuesFromRgbaString(fallback);
152
+ if (vals.length >= 3) return [
153
+ vals[0],
154
+ vals[1],
155
+ vals[2],
156
+ 1
157
+ ];
158
+ }
159
+ return null;
160
+ }
161
+ /**
162
+ * Convert any supported color string to the configured color space CSS format.
163
+ * Preserves alpha channel when present in the input.
164
+ * Returns null if the input cannot be parsed.
165
+ */
166
+ function strToColorSpace(color) {
167
+ if (!color) return void 0;
168
+ const cached = colorSpaceCache.get(color);
169
+ if (cached !== void 0) return cached;
170
+ const rgba = resolveToRgbaValues(color);
171
+ if (!rgba) {
172
+ colorSpaceCache.set(color, null);
173
+ return null;
174
+ }
175
+ const result = rgbValuesToColorString(rgba[0], rgba[1], rgba[2], currentColorSpace, rgba[3]);
176
+ colorSpaceCache.set(color, result);
177
+ return result;
178
+ }
179
+ /**
180
+ * Extract the decomposed components of a color in the configured color space.
181
+ * Returns a space-separated string of components without the wrapping function.
182
+ * Alpha is NOT included — components are used for alpha composition via `/ alpha`.
183
+ */
184
+ function getColorSpaceComponents(color) {
185
+ const cached = componentsCache.get(color);
186
+ if (cached !== void 0) return cached;
187
+ const rgba = resolveToRgbaValues(color);
188
+ if (!rgba) return color;
189
+ const result = rgbValuesToComponents(rgba[0], rgba[1], rgba[2], currentColorSpace);
190
+ componentsCache.set(color, result);
191
+ return result;
192
+ }
193
+ /**
194
+ * Convert a color initial value (from @property definitions) to components
195
+ * in the configured color space.
196
+ */
197
+ function colorInitialValueToComponents(initialValue) {
198
+ if (initialValue == null) return getDefaultComponents();
199
+ const val = String(initialValue).trim().toLowerCase();
200
+ if (val === "transparent" || val === "rgba(0,0,0,0)" || val === "") return getDefaultComponents();
201
+ if (val === "white") return rgbValuesToComponents(255, 255, 255, currentColorSpace);
202
+ if (val === "black") return rgbValuesToComponents(0, 0, 0, currentColorSpace);
203
+ const rgbMatch = val.match(/^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);
204
+ if (rgbMatch) return rgbValuesToComponents(parseInt(rgbMatch[1]), parseInt(rgbMatch[2]), parseInt(rgbMatch[3]), currentColorSpace);
205
+ return getDefaultComponents();
206
+ }
207
+ function getDefaultComponents() {
208
+ switch (currentColorSpace) {
209
+ case "rgb": return "0 0 0";
210
+ case "hsl": return "0 0% 0%";
211
+ case "oklch": return "0 0 0";
212
+ }
213
+ }
214
+ /**
215
+ * Get the CSS @property syntax for the companion components variable.
216
+ * RGB and OKLCH components are all plain numbers, so `<number>+` works.
217
+ * HSL includes percentages (`h s% l%`), so `*` is the only safe choice.
218
+ */
219
+ function getComponentPropertySyntax() {
220
+ switch (currentColorSpace) {
221
+ case "rgb":
222
+ case "oklch": return "<number>+";
223
+ default: return "*";
224
+ }
225
+ }
226
+
227
+ //#endregion
228
+ export { colorInitialValueToComponents, getColorSpaceComponents, getColorSpaceFunc, getColorSpaceSuffix, getComponentPropertySyntax, resetColorSpace, setColorSpace, strToColorSpace };
229
+ //# sourceMappingURL=color-space.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-space.js","names":[],"sources":["../../src/utils/color-space.ts"],"sourcesContent":["import { Lru } from '../parser/lru';\n\nimport {\n getRgbValuesFromRgbaString,\n hexToRgbaValues,\n hslToRgbValues,\n okhslToSrgb,\n oklchToRgbValues,\n rgbToHsl,\n rgbToOklch,\n strToRgb,\n} from './color-math';\n\nexport type ColorSpace = 'rgb' | 'hsl' | 'oklch';\n\nlet currentColorSpace: ColorSpace = 'oklch';\n\nconst colorSpaceCache = new Lru<string, string | null>(500);\nconst componentsCache = new Lru<string, string>(500);\n\nfunction clearColorCaches(): void {\n colorSpaceCache.clear();\n componentsCache.clear();\n}\n\nexport function getColorSpace(): ColorSpace {\n return currentColorSpace;\n}\n\nexport function setColorSpace(space: ColorSpace): void {\n currentColorSpace = space;\n clearColorCaches();\n}\n\nexport function resetColorSpace(): void {\n currentColorSpace = 'oklch';\n clearColorCaches();\n}\n\nexport function getColorSpaceSuffix(): string {\n return currentColorSpace;\n}\n\nexport function getColorSpaceFunc(): string {\n return currentColorSpace;\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction formatNum(n: number, precision: number): string {\n return parseFloat(n.toFixed(precision)).toString();\n}\n\nfunction formatRgbComponent(n: number): string {\n return parseFloat(n.toFixed(1)).toString();\n}\n\n// ---------------------------------------------------------------------------\n// Convert RGB 0-255 values to the configured color space CSS string\n// ---------------------------------------------------------------------------\n\nfunction formatAlpha(a: number): string {\n if (a === 0) return '0';\n const s = parseFloat(a.toFixed(4)).toString();\n return s;\n}\n\nfunction rgbValuesToColorString(\n r: number,\n g: number,\n b: number,\n space: ColorSpace,\n alpha?: number,\n): string {\n const alphaSuffix =\n alpha != null && alpha < 1 ? ` / ${formatAlpha(alpha)}` : '';\n\n switch (space) {\n case 'rgb':\n return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)}${alphaSuffix})`;\n case 'hsl': {\n const [h, s, l] = rgbToHsl(r, g, b);\n return `hsl(${formatNum(h, 2)} ${formatNum(s * 100, 2)}% ${formatNum(l * 100, 2)}%${alphaSuffix})`;\n }\n case 'oklch': {\n const [L, C, H] = rgbToOklch(r, g, b);\n return `oklch(${formatNum(L, 5)} ${formatNum(C, 5)} ${formatNum(H, 2)}${alphaSuffix})`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Extract decomposed components string (no wrapping function)\n// ---------------------------------------------------------------------------\n\nfunction rgbValuesToComponents(\n r: number,\n g: number,\n b: number,\n space: ColorSpace,\n): string {\n switch (space) {\n case 'rgb':\n return `${formatRgbComponent(r)} ${formatRgbComponent(g)} ${formatRgbComponent(b)}`;\n case 'hsl': {\n const [h, s, l] = rgbToHsl(r, g, b);\n return `${formatNum(h, 2)} ${formatNum(s * 100, 2)}% ${formatNum(l * 100, 2)}%`;\n }\n case 'oklch': {\n const [L, C, H] = rgbToOklch(r, g, b);\n return `${formatNum(L, 5)} ${formatNum(C, 5)} ${formatNum(H, 2)}`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Resolve any color input to 0-255 RGB values + optional alpha\n// ---------------------------------------------------------------------------\n\ntype RgbaResult = [number, number, number, number];\n\nconst parseColorFuncArgs = (\n str: string,\n prefix: string,\n): { parts: string[]; alpha: number } | null => {\n const start = str.indexOf('(', prefix.length - 1);\n const end = str.lastIndexOf(')');\n if (start < 0 || end < 0) return null;\n const inner = str.slice(start + 1, end).trim();\n const slashIdx = inner.indexOf('/');\n\n let colorPart: string;\n let alpha = 1;\n\n if (slashIdx >= 0) {\n colorPart = inner.slice(0, slashIdx);\n const alphaStr = inner.slice(slashIdx + 1).trim();\n if (alphaStr) {\n alpha = alphaStr.endsWith('%')\n ? parseFloat(alphaStr) / 100\n : parseFloat(alphaStr);\n if (Number.isNaN(alpha)) alpha = 1;\n }\n } else {\n colorPart = inner;\n }\n\n const parts = colorPart\n .trim()\n .split(/[,\\s]+/)\n .filter(Boolean);\n\n if (parts.length < 3) return null;\n\n // Legacy comma-separated rgba(r, g, b, a) — 4th value is alpha\n if (parts.length >= 4 && slashIdx < 0) {\n const legacyAlpha = parseFloat(parts[3]);\n if (!Number.isNaN(legacyAlpha)) {\n alpha = legacyAlpha;\n }\n }\n\n return { parts, alpha };\n};\n\nconst parseHue = (hueStr: string): number => {\n let h = parseFloat(hueStr);\n const lower = hueStr.toLowerCase();\n if (lower.endsWith('turn')) h = parseFloat(lower) * 360;\n else if (lower.endsWith('rad')) h = (parseFloat(lower) * 180) / Math.PI;\n return ((h % 360) + 360) % 360;\n};\n\nconst parsePercent = (val: string): number => {\n const num = parseFloat(val);\n return val.includes('%') ? num / 100 : num;\n};\n\nconst clamp01 = (n: number): number => Math.max(0, Math.min(1, n));\n\nfunction resolveToRgbaValues(color: string): RgbaResult | null {\n const trimmed = color.trim().toLowerCase();\n\n if (trimmed.startsWith('rgb')) {\n const parsed = parseColorFuncArgs(trimmed, 'rgb');\n if (!parsed || parsed.parts.length < 3) return null;\n const r = parsed.parts[0].endsWith('%')\n ? (parseFloat(parsed.parts[0]) / 100) * 255\n : parseFloat(parsed.parts[0]);\n const g = parsed.parts[1].endsWith('%')\n ? (parseFloat(parsed.parts[1]) / 100) * 255\n : parseFloat(parsed.parts[1]);\n const b = parsed.parts[2].endsWith('%')\n ? (parseFloat(parsed.parts[2]) / 100) * 255\n : parseFloat(parsed.parts[2]);\n return [r, g, b, parsed.alpha];\n }\n\n if (trimmed.startsWith('#')) {\n return hexToRgbaValues(trimmed);\n }\n\n if (trimmed.startsWith('hsl')) {\n const parsed = parseColorFuncArgs(trimmed, 'hsl');\n if (!parsed) return null;\n const h = parseHue(parsed.parts[0]);\n const s = clamp01(parsePercent(parsed.parts[1]));\n const l = clamp01(parsePercent(parsed.parts[2]));\n const [r, g, b] = hslToRgbValues(h, s, l);\n return [r, g, b, parsed.alpha];\n }\n\n if (trimmed.startsWith('oklch(')) {\n const parsed = parseColorFuncArgs(trimmed, 'oklch');\n if (!parsed) return null;\n const L = clamp01(parsePercent(parsed.parts[0]));\n const C = Math.max(0, parseFloat(parsed.parts[1]));\n const H = parseHue(parsed.parts[2]);\n const [r, g, b] = oklchToRgbValues(L, C, H);\n return [r, g, b, parsed.alpha];\n }\n\n if (trimmed.startsWith('okhsl(')) {\n const parsed = parseColorFuncArgs(trimmed, 'okhsl');\n if (!parsed) return null;\n const h = parseHue(parsed.parts[0]);\n const s = clamp01(parsePercent(parsed.parts[1]));\n const l = clamp01(parsePercent(parsed.parts[2]));\n const [r, g, b] = okhslToSrgb(h, s, l);\n return [clamp01(r) * 255, clamp01(g) * 255, clamp01(b) * 255, parsed.alpha];\n }\n\n // Fallback: named colors and other formats go through string conversion\n const fallback = strToRgb(trimmed);\n if (fallback) {\n // Recurse so the rgb(...) string is parsed with alpha extraction\n if (fallback !== trimmed) return resolveToRgbaValues(fallback);\n const vals = getRgbValuesFromRgbaString(fallback);\n if (vals.length >= 3) return [vals[0], vals[1], vals[2], 1];\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert any supported color string to the configured color space CSS format.\n * Preserves alpha channel when present in the input.\n * Returns null if the input cannot be parsed.\n */\nexport function strToColorSpace(color: string): string | null | undefined {\n if (!color) return undefined;\n\n const cached = colorSpaceCache.get(color);\n if (cached !== undefined) return cached;\n\n const rgba = resolveToRgbaValues(color);\n if (!rgba) {\n colorSpaceCache.set(color, null);\n return null;\n }\n\n const result = rgbValuesToColorString(\n rgba[0],\n rgba[1],\n rgba[2],\n currentColorSpace,\n rgba[3],\n );\n colorSpaceCache.set(color, result);\n return result;\n}\n\n/**\n * Extract the decomposed components of a color in the configured color space.\n * Returns a space-separated string of components without the wrapping function.\n * Alpha is NOT included — components are used for alpha composition via `/ alpha`.\n */\nexport function getColorSpaceComponents(color: string): string {\n const cached = componentsCache.get(color);\n if (cached !== undefined) return cached;\n\n const rgba = resolveToRgbaValues(color);\n if (!rgba) return color;\n\n const result = rgbValuesToComponents(\n rgba[0],\n rgba[1],\n rgba[2],\n currentColorSpace,\n );\n componentsCache.set(color, result);\n return result;\n}\n\n/**\n * Convert a color initial value (from @property definitions) to components\n * in the configured color space.\n */\nexport function colorInitialValueToComponents(\n initialValue: string | number | undefined,\n): string {\n if (initialValue == null) return getDefaultComponents();\n\n const val = String(initialValue).trim().toLowerCase();\n\n if (val === 'transparent' || val === 'rgba(0,0,0,0)' || val === '') {\n return getDefaultComponents();\n }\n\n if (val === 'white') {\n return rgbValuesToComponents(255, 255, 255, currentColorSpace);\n }\n if (val === 'black') {\n return rgbValuesToComponents(0, 0, 0, currentColorSpace);\n }\n\n const rgbMatch = val.match(/^rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/);\n if (rgbMatch) {\n return rgbValuesToComponents(\n parseInt(rgbMatch[1]),\n parseInt(rgbMatch[2]),\n parseInt(rgbMatch[3]),\n currentColorSpace,\n );\n }\n\n return getDefaultComponents();\n}\n\nfunction getDefaultComponents(): string {\n switch (currentColorSpace) {\n case 'rgb':\n return '0 0 0';\n case 'hsl':\n return '0 0% 0%';\n case 'oklch':\n return '0 0 0';\n }\n}\n\n/**\n * Get the CSS @property syntax for the companion components variable.\n * RGB and OKLCH components are all plain numbers, so `<number>+` works.\n * HSL includes percentages (`h s% l%`), so `*` is the only safe choice.\n */\nexport function getComponentPropertySyntax(): string {\n switch (currentColorSpace) {\n case 'rgb':\n case 'oklch':\n return '<number>+';\n default:\n return '*';\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,8 @@
1
+ import { getColorSpaceFunc, getColorSpaceSuffix } from "./color-space.js";
2
+
1
3
  //#region src/utils/colors.ts
2
4
  function color(name, opacity = 1) {
3
- if (opacity !== 1) return `rgb(var(--${name}-color-rgb) / ${opacity})`;
5
+ if (opacity !== 1) return `${getColorSpaceFunc()}(var(--${name}-color-${getColorSpaceSuffix()}) / ${opacity})`;
4
6
  return `var(--${name}-color)`;
5
7
  }
6
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"colors.js","names":[],"sources":["../../src/utils/colors.ts"],"sourcesContent":["export function color(name: string, opacity = 1) {\n if (opacity !== 1) {\n return `rgb(var(--${name}-color-rgb) / ${opacity})`;\n }\n\n return `var(--${name}-color)`;\n}\n"],"mappings":";AAAA,SAAgB,MAAM,MAAc,UAAU,GAAG;AAC/C,KAAI,YAAY,EACd,QAAO,aAAa,KAAK,gBAAgB,QAAQ;AAGnD,QAAO,SAAS,KAAK"}
1
+ {"version":3,"file":"colors.js","names":[],"sources":["../../src/utils/colors.ts"],"sourcesContent":["import { getColorSpaceFunc, getColorSpaceSuffix } from './color-space';\n\nexport function color(name: string, opacity = 1) {\n if (opacity !== 1) {\n return `${getColorSpaceFunc()}(var(--${name}-color-${getColorSpaceSuffix()}) / ${opacity})`;\n }\n\n return `var(--${name}-color)`;\n}\n"],"mappings":";;;AAEA,SAAgB,MAAM,MAAc,UAAU,GAAG;AAC/C,KAAI,YAAY,EACd,QAAO,GAAG,mBAAmB,CAAC,SAAS,KAAK,SAAS,qBAAqB,CAAC,MAAM,QAAQ;AAG3F,QAAO,SAAS,KAAK"}
@@ -10,7 +10,7 @@ function modAttrs(map) {
10
10
  if (value === true) attrs[attrName] = "";
11
11
  else if (typeof value === "string") attrs[attrName] = value;
12
12
  else if (typeof value === "number") attrs[attrName] = String(value);
13
- else console.warn(`CubeUIKit: Invalid mod value for "${key}". Expected boolean, string, or number, got ${typeof value}`);
13
+ else console.warn(`Tasty: Invalid mod value for "${key}". Expected boolean, string, or number, got ${typeof value}`);
14
14
  return attrs;
15
15
  }, {}) : null;
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mod-attrs.js","names":[],"sources":["../../src/utils/mod-attrs.ts"],"sourcesContent":["/**\n * Generate data DOM attributes from modifier map.\n */\nimport type { AllBaseProps } from '../types';\n\nimport { cacheWrapper } from './cache-wrapper';\nimport { camelToKebab } from './case-converter';\n\nfunction modAttrs(map: AllBaseProps['mods']): Record<string, string> | null {\n return map\n ? Object.keys(map).reduce(\n (attrs, key) => {\n const value = map[key];\n\n // Skip null, undefined, false\n if (value == null || value === false) {\n return attrs;\n }\n\n const attrName = `data-${camelToKebab(key)}`;\n\n if (value === true) {\n // Boolean true: data-{name}=\"\"\n attrs[attrName] = '';\n } else if (typeof value === 'string') {\n // String value: data-{name}=\"value\"\n attrs[attrName] = value;\n } else if (typeof value === 'number') {\n // Number: convert to string\n attrs[attrName] = String(value);\n } else {\n // Reject other types (objects, arrays, functions)\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `CubeUIKit: Invalid mod value for \"${key}\". Expected boolean, string, or number, got ${typeof value}`,\n );\n }\n }\n\n return attrs;\n },\n {} as Record<string, string>,\n )\n : null;\n}\n\nconst _modAttrs = cacheWrapper(modAttrs);\n\nexport { _modAttrs as modAttrs };\n"],"mappings":";;;;AAQA,SAAS,SAAS,KAA0D;AAC1E,QAAO,MACH,OAAO,KAAK,IAAI,CAAC,QACd,OAAO,QAAQ;EACd,MAAM,QAAQ,IAAI;AAGlB,MAAI,SAAS,QAAQ,UAAU,MAC7B,QAAO;EAGT,MAAM,WAAW,QAAQ,aAAa,IAAI;AAE1C,MAAI,UAAU,KAEZ,OAAM,YAAY;WACT,OAAO,UAAU,SAE1B,OAAM,YAAY;WACT,OAAO,UAAU,SAE1B,OAAM,YAAY,OAAO,MAAM;MAI7B,SAAQ,KACN,qCAAqC,IAAI,8CAA8C,OAAO,QAC/F;AAIL,SAAO;IAET,EAAE,CACH,GACD;;AAGN,MAAM,YAAY,aAAa,SAAS"}
1
+ {"version":3,"file":"mod-attrs.js","names":[],"sources":["../../src/utils/mod-attrs.ts"],"sourcesContent":["/**\n * Generate data DOM attributes from modifier map.\n */\nimport type { AllBaseProps } from '../types';\n\nimport { cacheWrapper } from './cache-wrapper';\nimport { camelToKebab } from './case-converter';\n\nfunction modAttrs(map: AllBaseProps['mods']): Record<string, string> | null {\n return map\n ? Object.keys(map).reduce(\n (attrs, key) => {\n const value = map[key];\n\n // Skip null, undefined, false\n if (value == null || value === false) {\n return attrs;\n }\n\n const attrName = `data-${camelToKebab(key)}`;\n\n if (value === true) {\n // Boolean true: data-{name}=\"\"\n attrs[attrName] = '';\n } else if (typeof value === 'string') {\n // String value: data-{name}=\"value\"\n attrs[attrName] = value;\n } else if (typeof value === 'number') {\n // Number: convert to string\n attrs[attrName] = String(value);\n } else {\n // Reject other types (objects, arrays, functions)\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Tasty: Invalid mod value for \"${key}\". Expected boolean, string, or number, got ${typeof value}`,\n );\n }\n }\n\n return attrs;\n },\n {} as Record<string, string>,\n )\n : null;\n}\n\nconst _modAttrs = cacheWrapper(modAttrs);\n\nexport { _modAttrs as modAttrs };\n"],"mappings":";;;;AAQA,SAAS,SAAS,KAA0D;AAC1E,QAAO,MACH,OAAO,KAAK,IAAI,CAAC,QACd,OAAO,QAAQ;EACd,MAAM,QAAQ,IAAI;AAGlB,MAAI,SAAS,QAAQ,UAAU,MAC7B,QAAO;EAGT,MAAM,WAAW,QAAQ,aAAa,IAAI;AAE1C,MAAI,UAAU,KAEZ,OAAM,YAAY;WACT,OAAO,UAAU,SAE1B,OAAM,YAAY;WACT,OAAO,UAAU,SAE1B,OAAM,YAAY,OAAO,MAAM;MAI7B,SAAQ,KACN,iCAAiC,IAAI,8CAA8C,OAAO,QAC3F;AAIL,SAAO;IAET,EAAE,CACH,GACD;;AAGN,MAAM,YAAY,aAAa,SAAS"}
@@ -1,22 +1,12 @@
1
1
  import { CSSProperties } from "./css-types.js";
2
+ import { hslToRgbValues } from "./color-math.js";
2
3
  import { Tokens } from "../types.js";
3
4
 
4
5
  //#region src/utils/process-tokens.d.ts
5
- /**
6
- * Convert HSL to RGB (sRGB).
7
- * Algorithm from: https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
8
- * Same as used in CSS Color 4 spec.
9
- *
10
- * @param h - Hue in degrees (0-360)
11
- * @param s - Saturation (0-1)
12
- * @param l - Lightness (0-1)
13
- * @returns RGB values in 0-255 range (may have fractional values)
14
- */
15
- declare function hslToRgbValues(h: number, s: number, l: number): [number, number, number];
16
6
  /**
17
7
  * Process tokens object into inline style properties.
18
8
  * - $name -> --name with parsed value
19
- * - #name -> --name-color AND --name-color-rgb with parsed values
9
+ * - #name -> --name-color AND --name-color-{colorSpace} with parsed values
20
10
  *
21
11
  * @param tokens - The tokens object to process
22
12
  * @returns CSSProperties object or undefined if no tokens to process
@@ -27,5 +17,5 @@ declare function processTokens(tokens: Tokens | undefined): CSSProperties | unde
27
17
  */
28
18
  declare function stringifyTokens(tokens: Tokens | undefined): string;
29
19
  //#endregion
30
- export { hslToRgbValues, processTokens, stringifyTokens };
20
+ export { processTokens, stringifyTokens };
31
21
  //# sourceMappingURL=process-tokens.d.ts.map
@@ -1,102 +1,21 @@
1
- import { okhslToRgb } from "./okhsl-to-rgb.js";
2
- import { getRgbValuesFromRgbaString, hexToRgb, normalizeColorTokenValue, parseStyle } from "./styles.js";
1
+ import { hslToRgbValues } from "./color-math.js";
2
+ import { getColorSpaceComponents, getColorSpaceSuffix } from "./color-space.js";
3
+ import { normalizeColorTokenValue, parseStyle } from "./styles.js";
3
4
 
4
5
  //#region src/utils/process-tokens.ts
5
6
  /**
6
- * Parse HSL values from an hsl()/hsla() string.
7
- * Supports both comma-separated (legacy) and space-separated (modern) syntax:
8
- * hsl(200, 40%, 50%)
9
- * hsl(200 40% 50%)
10
- * hsl(200 40% 50% / 0.5)
11
- *
12
- * Returns [h, s, l] where h is 0-360, s and l are 0-1, or null if parsing fails.
13
- */
14
- function parseHslValues(str) {
15
- const match = str.match(/hsla?\(([^)]+)\)/i);
16
- if (!match) return null;
17
- const [colorPart] = match[1].trim().split("/");
18
- const parts = colorPart.trim().split(/[,\s]+/).filter(Boolean);
19
- if (parts.length < 3) return null;
20
- let h = parseFloat(parts[0]);
21
- const hueStr = parts[0].toLowerCase();
22
- if (hueStr.endsWith("turn")) h = parseFloat(hueStr) * 360;
23
- else if (hueStr.endsWith("rad")) h = parseFloat(hueStr) * 180 / Math.PI;
24
- else if (hueStr.endsWith("grad")) h = parseFloat(hueStr) * .9;
25
- h = h % 360;
26
- if (h < 0) h += 360;
27
- const parsePercent = (val) => {
28
- const num = parseFloat(val);
29
- return val.includes("%") ? num / 100 : num;
30
- };
31
- const s = Math.max(0, Math.min(1, parsePercent(parts[1])));
32
- const l = Math.max(0, Math.min(1, parsePercent(parts[2])));
33
- return [
34
- h,
35
- s,
36
- l
37
- ];
38
- }
39
- /**
40
- * Convert HSL to RGB (sRGB).
41
- * Algorithm from: https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
42
- * Same as used in CSS Color 4 spec.
43
- *
44
- * @param h - Hue in degrees (0-360)
45
- * @param s - Saturation (0-1)
46
- * @param l - Lightness (0-1)
47
- * @returns RGB values in 0-255 range (may have fractional values)
48
- */
49
- function hslToRgbValues(h, s, l) {
50
- const a = s * Math.min(l, 1 - l);
51
- const f = (n) => {
52
- const k = (n + h / 30) % 12;
53
- return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
54
- };
55
- return [
56
- f(0) * 255,
57
- f(8) * 255,
58
- f(4) * 255
59
- ];
60
- }
61
- /**
62
- * Format a number to a string with up to 1 decimal place, removing trailing zeros.
63
- */
64
- function formatRgbComponent(n) {
65
- return parseFloat(n.toFixed(1)).toString();
66
- }
67
- /**
68
- * Extract RGB triplet from a color value.
69
- * Returns the RGB values as a space-separated string (e.g., "255 128 0")
70
- * or a CSS variable reference for token colors.
7
+ * Extract color components in the configured color space.
8
+ * Returns a CSS variable reference for token colors, or decomposed
9
+ * components as a space-separated string.
71
10
  */
72
- function extractRgbValue(colorValue, parsedOutput) {
11
+ function extractColorSpaceValue(colorValue, parsedOutput) {
12
+ const suffix = getColorSpaceSuffix();
73
13
  const varMatch = parsedOutput.match(/var\(--([a-z0-9-]+)-color\)/);
74
- if (varMatch) return `var(--${varMatch[1]}-color-rgb)`;
75
- if (parsedOutput.startsWith("rgb(")) {
76
- const rgbValues = getRgbValuesFromRgbaString(parsedOutput);
77
- if (rgbValues && rgbValues.length >= 3) return rgbValues.join(" ");
78
- }
79
- if (parsedOutput.startsWith("hsl(") || parsedOutput.startsWith("hsla(") || colorValue.startsWith("hsl(") || colorValue.startsWith("hsla(")) {
80
- const hslValues = parseHslValues(parsedOutput) || parseHslValues(colorValue);
81
- if (hslValues) {
82
- const [r, g, b] = hslToRgbValues(hslValues[0], hslValues[1], hslValues[2]);
83
- return `${formatRgbComponent(r)} ${formatRgbComponent(g)} ${formatRgbComponent(b)}`;
84
- }
85
- }
86
- if (parsedOutput.startsWith("okhsl(") || colorValue.startsWith("okhsl(")) {
87
- const rgbResult = okhslToRgb(parsedOutput) || okhslToRgb(colorValue);
88
- if (rgbResult) {
89
- const rgbValues = getRgbValuesFromRgbaString(rgbResult);
90
- if (rgbValues && rgbValues.length >= 3) return rgbValues.join(" ");
91
- }
92
- }
93
- if (colorValue.startsWith("#") && /^#[0-9a-fA-F]{3,8}$/.test(colorValue)) {
94
- const rgbResult = hexToRgb(colorValue);
95
- if (rgbResult) {
96
- const rgbValues = getRgbValuesFromRgbaString(rgbResult);
97
- if (rgbValues && rgbValues.length >= 3) return rgbValues.join(" ");
98
- }
99
- }
14
+ if (varMatch) return `var(--${varMatch[1]}-color-${suffix})`;
15
+ const components = getColorSpaceComponents(colorValue);
16
+ if (components !== colorValue) return components;
17
+ const componentsFromParsed = getColorSpaceComponents(parsedOutput);
18
+ if (componentsFromParsed !== parsedOutput) return componentsFromParsed;
100
19
  return parsedOutput;
101
20
  }
102
21
  /**
@@ -106,7 +25,7 @@ function extractRgbValue(colorValue, parsedOutput) {
106
25
  function isValidTokenValue(value) {
107
26
  if (value === void 0 || value === null || value === false) return false;
108
27
  if (typeof value === "object") {
109
- console.warn("CubeUIKit: Object values are not allowed in tokens prop. Tokens do not support state-based styling. Use a primitive value instead.");
28
+ console.warn("Tasty: Object values are not allowed in tokens prop. Tokens do not support state-based styling. Use a primitive value instead.");
110
29
  return false;
111
30
  }
112
31
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
@@ -125,7 +44,7 @@ function processTokenValue(value) {
125
44
  /**
126
45
  * Process tokens object into inline style properties.
127
46
  * - $name -> --name with parsed value
128
- * - #name -> --name-color AND --name-color-rgb with parsed values
47
+ * - #name -> --name-color AND --name-color-{colorSpace} with parsed values
129
48
  *
130
49
  * @param tokens - The tokens object to process
131
50
  * @returns CSSProperties object or undefined if no tokens to process
@@ -145,6 +64,7 @@ function processTokens(tokens) {
145
64
  result[propName] = processedValue;
146
65
  } else if (key.startsWith("#")) {
147
66
  const colorName = key.slice(1);
67
+ const suffix = getColorSpaceSuffix();
148
68
  const effectiveValue = normalizeColorTokenValue(value);
149
69
  if (effectiveValue === null) continue;
150
70
  const originalValue = typeof effectiveValue === "number" ? String(effectiveValue) : effectiveValue;
@@ -153,7 +73,7 @@ function processTokens(tokens) {
153
73
  if (!result) result = {};
154
74
  result[`--${colorName}-color`] = processedValue;
155
75
  if (/^#current(?:\.|$)/i.test(lowerValue)) continue;
156
- result[`--${colorName}-color-rgb`] = extractRgbValue(originalValue, processedValue);
76
+ result[`--${colorName}-color-${suffix}`] = extractColorSpaceValue(originalValue, processedValue);
157
77
  }
158
78
  }
159
79
  return result;
@@ -167,5 +87,5 @@ function stringifyTokens(tokens) {
167
87
  }
168
88
 
169
89
  //#endregion
170
- export { hslToRgbValues, processTokens, stringifyTokens };
90
+ export { processTokens, stringifyTokens };
171
91
  //# sourceMappingURL=process-tokens.js.map