rnwind 0.0.10 → 0.0.12

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 (98) hide show
  1. package/lib/cjs/core/normalize-classname.cjs +3 -1
  2. package/lib/cjs/core/normalize-classname.cjs.map +1 -1
  3. package/lib/cjs/core/parser/border-dispatcher.cjs +20 -10
  4. package/lib/cjs/core/parser/border-dispatcher.cjs.map +1 -1
  5. package/lib/cjs/core/parser/color-properties-dispatcher.cjs +7 -5
  6. package/lib/cjs/core/parser/color-properties-dispatcher.cjs.map +1 -1
  7. package/lib/cjs/core/parser/color.cjs +194 -10
  8. package/lib/cjs/core/parser/color.cjs.map +1 -1
  9. package/lib/cjs/core/parser/color.d.ts +18 -3
  10. package/lib/cjs/core/parser/declaration.cjs +62 -4
  11. package/lib/cjs/core/parser/declaration.cjs.map +1 -1
  12. package/lib/cjs/core/parser/layout-dispatcher.cjs +32 -2
  13. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
  14. package/lib/cjs/core/parser/shorthand.cjs +10 -3
  15. package/lib/cjs/core/parser/shorthand.cjs.map +1 -1
  16. package/lib/cjs/core/parser/tokens.cjs +9 -0
  17. package/lib/cjs/core/parser/tokens.cjs.map +1 -1
  18. package/lib/cjs/core/parser/tw-parser.cjs +89 -2
  19. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  20. package/lib/cjs/core/parser/tw-parser.d.ts +2 -0
  21. package/lib/cjs/core/parser/typography-dispatcher.cjs +15 -8
  22. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  23. package/lib/cjs/core/style-builder/union-builder.cjs +81 -2
  24. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  25. package/lib/cjs/core/style-builder/union-builder.d.ts +28 -0
  26. package/lib/cjs/metro/state.cjs +74 -13
  27. package/lib/cjs/metro/state.cjs.map +1 -1
  28. package/lib/cjs/metro/state.d.ts +18 -0
  29. package/lib/cjs/metro/transformer.cjs +10 -4
  30. package/lib/cjs/metro/transformer.cjs.map +1 -1
  31. package/lib/cjs/metro/with-config.cjs +57 -0
  32. package/lib/cjs/metro/with-config.cjs.map +1 -1
  33. package/lib/cjs/metro/with-config.d.ts +12 -0
  34. package/lib/cjs/metro/wrap-imports.cjs +36 -1
  35. package/lib/cjs/metro/wrap-imports.cjs.map +1 -1
  36. package/lib/cjs/runtime/hooks/use-scheme.cjs +14 -7
  37. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  38. package/lib/cjs/runtime/resolve.cjs +6 -2
  39. package/lib/cjs/runtime/resolve.cjs.map +1 -1
  40. package/lib/cjs/runtime/resolve.d.ts +5 -1
  41. package/lib/esm/core/normalize-classname.mjs +3 -1
  42. package/lib/esm/core/normalize-classname.mjs.map +1 -1
  43. package/lib/esm/core/parser/border-dispatcher.mjs +21 -11
  44. package/lib/esm/core/parser/border-dispatcher.mjs.map +1 -1
  45. package/lib/esm/core/parser/color-properties-dispatcher.mjs +8 -6
  46. package/lib/esm/core/parser/color-properties-dispatcher.mjs.map +1 -1
  47. package/lib/esm/core/parser/color.d.ts +18 -3
  48. package/lib/esm/core/parser/color.mjs +195 -12
  49. package/lib/esm/core/parser/color.mjs.map +1 -1
  50. package/lib/esm/core/parser/declaration.mjs +63 -5
  51. package/lib/esm/core/parser/declaration.mjs.map +1 -1
  52. package/lib/esm/core/parser/layout-dispatcher.mjs +32 -2
  53. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  54. package/lib/esm/core/parser/shorthand.mjs +11 -4
  55. package/lib/esm/core/parser/shorthand.mjs.map +1 -1
  56. package/lib/esm/core/parser/tokens.mjs +10 -1
  57. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  58. package/lib/esm/core/parser/tw-parser.d.ts +2 -0
  59. package/lib/esm/core/parser/tw-parser.mjs +69 -0
  60. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  61. package/lib/esm/core/parser/typography-dispatcher.mjs +15 -8
  62. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  63. package/lib/esm/core/style-builder/union-builder.d.ts +28 -0
  64. package/lib/esm/core/style-builder/union-builder.mjs +82 -3
  65. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  66. package/lib/esm/metro/state.d.ts +18 -0
  67. package/lib/esm/metro/state.mjs +75 -14
  68. package/lib/esm/metro/state.mjs.map +1 -1
  69. package/lib/esm/metro/transformer.mjs +10 -4
  70. package/lib/esm/metro/transformer.mjs.map +1 -1
  71. package/lib/esm/metro/with-config.d.ts +12 -0
  72. package/lib/esm/metro/with-config.mjs +58 -2
  73. package/lib/esm/metro/with-config.mjs.map +1 -1
  74. package/lib/esm/metro/wrap-imports.mjs +36 -1
  75. package/lib/esm/metro/wrap-imports.mjs.map +1 -1
  76. package/lib/esm/runtime/hooks/use-scheme.mjs +14 -7
  77. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  78. package/lib/esm/runtime/resolve.d.ts +5 -1
  79. package/lib/esm/runtime/resolve.mjs +6 -2
  80. package/lib/esm/runtime/resolve.mjs.map +1 -1
  81. package/package.json +1 -1
  82. package/src/core/normalize-classname.ts +4 -1
  83. package/src/core/parser/border-dispatcher.ts +22 -11
  84. package/src/core/parser/color-properties-dispatcher.ts +7 -5
  85. package/src/core/parser/color.ts +182 -11
  86. package/src/core/parser/declaration.ts +61 -5
  87. package/src/core/parser/layout-dispatcher.ts +34 -2
  88. package/src/core/parser/shorthand.ts +9 -3
  89. package/src/core/parser/tokens.ts +10 -1
  90. package/src/core/parser/tw-parser.ts +71 -1
  91. package/src/core/parser/typography-dispatcher.ts +15 -6
  92. package/src/core/style-builder/union-builder.ts +83 -3
  93. package/src/metro/state.ts +117 -12
  94. package/src/metro/transformer.ts +9 -4
  95. package/src/metro/with-config.ts +59 -1
  96. package/src/metro/wrap-imports.ts +36 -1
  97. package/src/runtime/hooks/use-scheme.ts +13 -6
  98. package/src/runtime/resolve.ts +6 -2
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ /** Whitespace run splitter — hoisted so the runtime hot path doesn't recreate it per call. */
4
+ const WHITESPACE = /\s+/;
3
5
  /**
4
6
  * Normalize a className for molecule keying: trim, collapse runs of
5
7
  * whitespace, and drop exact-duplicate tokens — but PRESERVE ORDER.
@@ -12,7 +14,7 @@
12
14
  function normalizeClassName(className) {
13
15
  const seen = new Set();
14
16
  const out = [];
15
- for (const token of className.trim().split(/\s+/)) {
17
+ for (const token of className.trim().split(WHITESPACE)) {
16
18
  if (token.length === 0 || seen.has(token))
17
19
  continue;
18
20
  seen.add(token);
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-classname.cjs","sources":["../../../../src/core/normalize-classname.ts"],"sourcesContent":["/**\n * Normalize a className for molecule keying: trim, collapse runs of\n * whitespace, and drop exact-duplicate tokens — but PRESERVE ORDER.\n * Tailwind is last-wins for conflicting utilities (`p-4 p-2` ≠ `p-2 p-4`),\n * so sorting would corrupt the merge. Build-time (molecule keys) and\n * runtime (lookup) call the identical function so their keys always match.\n * @param className Raw className string.\n * @returns Normalized, order-preserving className.\n */\nexport function normalizeClassName(className: string): string {\n const seen = new Set<string>()\n const out: string[] = []\n for (const token of className.trim().split(/\\s+/)) {\n if (token.length === 0 || seen.has(token)) continue\n seen.add(token)\n out.push(token)\n }\n return out.join(' ')\n}\n"],"names":[],"mappings":";;AAAA;;;;;;;;AAQG;AACG,SAAU,kBAAkB,CAAC,SAAiB,EAAA;AAClD,IAAA,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU;IAC9B,MAAM,GAAG,GAAa,EAAE;AACxB,IAAA,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE;AAC3C,QAAA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACf,QAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;IACjB;AACA,IAAA,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AACtB;;;;"}
1
+ {"version":3,"file":"normalize-classname.cjs","sources":["../../../../src/core/normalize-classname.ts"],"sourcesContent":["/** Whitespace run splitter — hoisted so the runtime hot path doesn't recreate it per call. */\nconst WHITESPACE = /\\s+/\n\n/**\n * Normalize a className for molecule keying: trim, collapse runs of\n * whitespace, and drop exact-duplicate tokens — but PRESERVE ORDER.\n * Tailwind is last-wins for conflicting utilities (`p-4 p-2` ≠ `p-2 p-4`),\n * so sorting would corrupt the merge. Build-time (molecule keys) and\n * runtime (lookup) call the identical function so their keys always match.\n * @param className Raw className string.\n * @returns Normalized, order-preserving className.\n */\nexport function normalizeClassName(className: string): string {\n const seen = new Set<string>()\n const out: string[] = []\n for (const token of className.trim().split(WHITESPACE)) {\n if (token.length === 0 || seen.has(token)) continue\n seen.add(token)\n out.push(token)\n }\n return out.join(' ')\n}\n"],"names":[],"mappings":";;AAAA;AACA,MAAM,UAAU,GAAG,KAAK;AAExB;;;;;;;;AAQG;AACG,SAAU,kBAAkB,CAAC,SAAiB,EAAA;AAClD,IAAA,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU;IAC9B,MAAM,GAAG,GAAa,EAAE;AACxB,IAAA,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;QACtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE;AAC3C,QAAA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACf,QAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;IACjB;AACA,IAAA,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AACtB;;;;"}
@@ -4,18 +4,28 @@ var caseConvert = require('./case-convert.cjs');
4
4
  var color = require('./color.cjs');
5
5
 
6
6
  /**
7
- * Build an inline-color pair from a `{start, end}`-shaped value.
7
+ * Build a single border-side color entry, dropping CSS-wide cascade keywords
8
+ * (`currentColor`, `inherit`, …) — RN has no color cascade, so the keyword
9
+ * would reach the native view manager as an invalid color.
10
+ * @param key RN side key (e.g. `borderLeftColor`).
11
+ * @param value Typed `CssColor` value.
12
+ * @returns One RN entry, or empty when the value is a cascade keyword.
13
+ */
14
+ function colorSide(key, value) {
15
+ const color$1 = color.cssColorToString(value);
16
+ return color.isCssWideColorKeyword(color$1) ? [] : [[key, color$1]];
17
+ }
18
+ /**
19
+ * Build an inline-color pair from a `{start, end}`-shaped value. Each side
20
+ * drops independently when it resolves to a CSS-wide cascade keyword.
8
21
  * @param leftKey RN key for the start side.
9
22
  * @param rightKey RN key for the end side.
10
23
  * @param value Typed `{start, end}` color value.
11
- * @returns Two RN entries.
24
+ * @returns Up to two RN entries (cascade-keyword sides omitted).
12
25
  */
13
26
  function colorPair(leftKey, rightKey, value) {
14
27
  const tagged = value;
15
- return [
16
- [leftKey, color.cssColorToString(tagged.start)],
17
- [rightKey, color.cssColorToString(tagged.end)],
18
- ];
28
+ return [...colorSide(leftKey, tagged.start), ...colorSide(rightKey, tagged.end)];
19
29
  }
20
30
  /**
21
31
  * Coerce a border-width-shaped length to a pixel number. Drops
@@ -113,16 +123,16 @@ function dispatchBorderDeclaration(decl) {
113
123
  return colorPair('borderTopColor', 'borderBottomColor', decl.value);
114
124
  }
115
125
  case 'border-inline-start-color': {
116
- return [['borderLeftColor', color.cssColorToString(decl.value)]];
126
+ return colorSide('borderLeftColor', decl.value);
117
127
  }
118
128
  case 'border-inline-end-color': {
119
- return [['borderRightColor', color.cssColorToString(decl.value)]];
129
+ return colorSide('borderRightColor', decl.value);
120
130
  }
121
131
  case 'border-block-start-color': {
122
- return [['borderTopColor', color.cssColorToString(decl.value)]];
132
+ return colorSide('borderTopColor', decl.value);
123
133
  }
124
134
  case 'border-block-end-color': {
125
- return [['borderBottomColor', color.cssColorToString(decl.value)]];
135
+ return colorSide('borderBottomColor', decl.value);
126
136
  }
127
137
  case 'border-width': {
128
138
  return borderWidthShorthand(decl.value);
@@ -1 +1 @@
1
- {"version":3,"file":"border-dispatcher.cjs","sources":["../../../../../src/core/parser/border-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { kebabToCamel } from './case-convert'\nimport { cssColorToString } from './color'\nimport type { RNEntry } from './types'\n\n/**\n * Build an inline-color pair from a `{start, end}`-shaped value.\n * @param leftKey RN key for the start side.\n * @param rightKey RN key for the end side.\n * @param value Typed `{start, end}` color value.\n * @returns Two RN entries.\n */\nfunction colorPair(leftKey: string, rightKey: string, value: unknown): readonly RNEntry[] {\n const tagged = value as { start?: unknown; end?: unknown }\n return [\n [leftKey, cssColorToString(tagged.start as never)],\n [rightKey, cssColorToString(tagged.end as never)],\n ]\n}\n\n/**\n * Coerce a border-width-shaped length to a pixel number. Drops\n * percentages — RN borders don't accept them.\n * @param value Typed length value (`{type: 'length', value: {unit, value}}`).\n * @returns Pixel number, or null when unrepresentable.\n */\nfunction lengthToPxValue(value: unknown): number | null {\n if (typeof value !== 'object' || value === null) return null\n const tagged = value as {\n type?: string\n value?: { type?: string; value?: { unit?: string; value?: number } } | { unit?: string; value?: number }\n }\n const inner =\n tagged.type === 'length'\n ? (tagged.value as { type?: string; value?: { unit?: string; value?: number } })?.value\n : tagged.value\n if (!inner || typeof (inner as { value?: number }).value !== 'number') return null\n const dim = inner as { unit?: string; value: number }\n if (dim.unit === 'px') return dim.value\n if (dim.unit === 'rem' || dim.unit === 'em') return dim.value * 16\n return dim.value\n}\n\n/**\n * Build an inline-width pair from a `{start, end}`-shaped value.\n * @param leftKey RN key for the start side.\n * @param rightKey RN key for the end side.\n * @param value Typed `{start, end}` length value.\n * @returns Two RN entries, or empty when either side is unrepresentable.\n */\nfunction widthPair(leftKey: string, rightKey: string, value: unknown): readonly RNEntry[] {\n const tagged = value as { start?: unknown; end?: unknown }\n const start = lengthToPxValue(tagged.start)\n const end = lengthToPxValue(tagged.end)\n if (start === null || end === null) return []\n return [\n [leftKey, start],\n [rightKey, end],\n ]\n}\n\n/**\n * Expand a `border-width` shorthand to RN longhands. Collapses to the\n * `borderWidth` shorthand when all four sides match.\n * @param value Typed border-width value with `{top, right, bottom, left}`.\n * @returns RN entries.\n */\nfunction borderWidthShorthand(value: unknown): readonly RNEntry[] {\n const tagged = value as { top?: unknown; right?: unknown; bottom?: unknown; left?: unknown }\n const top = lengthToPxValue(tagged.top)\n const right = lengthToPxValue(tagged.right)\n const bottom = lengthToPxValue(tagged.bottom)\n const left = lengthToPxValue(tagged.left)\n if (top === null || right === null || bottom === null || left === null) return []\n if (top === right && right === bottom && bottom === left) return [['borderWidth', top]]\n return [\n ['borderTopWidth', top],\n ['borderRightWidth', right],\n ['borderBottomWidth', bottom],\n ['borderLeftWidth', left],\n ]\n}\n\n/**\n * Map CSS `border-style` keywords to the strings RN accepts. RN\n * supports only `solid` / `dashed` / `dotted` / `none` — fall back to\n * `solid` for everything else.\n * @param css CSS border-style keyword.\n * @returns RN border-style.\n */\nfunction mapBorderStyle(css: string): string {\n if (css === 'dashed' || css === 'dotted' || css === 'none') return css\n return 'solid'\n}\n\n/**\n * Dispatch border-* longhands and their logical-direction variants to\n * RN style entries. Returns `null` for any property the dispatcher\n * doesn't handle so the caller can fall through.\n *\n * Logical-direction inputs (`border-inline-*`, `border-block-*`,\n * `border-inline-start-*`, …) lower to RN's physical pairs\n * (`borderLeft*` / `borderRight*` / `borderTop*` / `borderBottom*`)\n * since RN doesn't honor logical directions at the style level.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchBorderDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'border-inline-color': {\n return colorPair('borderLeftColor', 'borderRightColor', decl.value)\n }\n case 'border-block-color': {\n return colorPair('borderTopColor', 'borderBottomColor', decl.value)\n }\n case 'border-inline-start-color': {\n return [['borderLeftColor', cssColorToString(decl.value)]]\n }\n case 'border-inline-end-color': {\n return [['borderRightColor', cssColorToString(decl.value)]]\n }\n case 'border-block-start-color': {\n return [['borderTopColor', cssColorToString(decl.value)]]\n }\n case 'border-block-end-color': {\n return [['borderBottomColor', cssColorToString(decl.value)]]\n }\n case 'border-width': {\n return borderWidthShorthand(decl.value)\n }\n case 'border-top-width':\n case 'border-right-width':\n case 'border-bottom-width':\n case 'border-left-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [[kebabToCamel(decl.property), v]]\n }\n case 'border-inline-width': {\n return widthPair('borderLeftWidth', 'borderRightWidth', decl.value)\n }\n case 'border-block-width': {\n return widthPair('borderTopWidth', 'borderBottomWidth', decl.value)\n }\n case 'border-inline-start-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderLeftWidth', v]]\n }\n case 'border-inline-end-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderRightWidth', v]]\n }\n case 'border-block-start-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderTopWidth', v]]\n }\n case 'border-block-end-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderBottomWidth', v]]\n }\n case 'border-style': {\n const styleValue = (decl.value as { top?: string }).top\n if (typeof styleValue !== 'string') return []\n return [['borderStyle', mapBorderStyle(styleValue)]]\n }\n case 'border-top-style':\n case 'border-right-style':\n case 'border-bottom-style':\n case 'border-left-style': {\n if (typeof decl.value !== 'string') return []\n return [['borderStyle', mapBorderStyle(decl.value)]]\n }\n default: {\n return null\n }\n }\n}\n"],"names":["cssColorToString","kebabToCamel"],"mappings":"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"}
1
+ {"version":3,"file":"border-dispatcher.cjs","sources":["../../../../../src/core/parser/border-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { kebabToCamel } from './case-convert'\nimport { cssColorToString, isCssWideColorKeyword } from './color'\nimport type { RNEntry } from './types'\n\n/**\n * Build a single border-side color entry, dropping CSS-wide cascade keywords\n * (`currentColor`, `inherit`, …) — RN has no color cascade, so the keyword\n * would reach the native view manager as an invalid color.\n * @param key RN side key (e.g. `borderLeftColor`).\n * @param value Typed `CssColor` value.\n * @returns One RN entry, or empty when the value is a cascade keyword.\n */\nfunction colorSide(key: string, value: unknown): readonly RNEntry[] {\n const color = cssColorToString(value as never)\n return isCssWideColorKeyword(color) ? [] : [[key, color]]\n}\n\n/**\n * Build an inline-color pair from a `{start, end}`-shaped value. Each side\n * drops independently when it resolves to a CSS-wide cascade keyword.\n * @param leftKey RN key for the start side.\n * @param rightKey RN key for the end side.\n * @param value Typed `{start, end}` color value.\n * @returns Up to two RN entries (cascade-keyword sides omitted).\n */\nfunction colorPair(leftKey: string, rightKey: string, value: unknown): readonly RNEntry[] {\n const tagged = value as { start?: unknown; end?: unknown }\n return [...colorSide(leftKey, tagged.start), ...colorSide(rightKey, tagged.end)]\n}\n\n/**\n * Coerce a border-width-shaped length to a pixel number. Drops\n * percentages — RN borders don't accept them.\n * @param value Typed length value (`{type: 'length', value: {unit, value}}`).\n * @returns Pixel number, or null when unrepresentable.\n */\nfunction lengthToPxValue(value: unknown): number | null {\n if (typeof value !== 'object' || value === null) return null\n const tagged = value as {\n type?: string\n value?: { type?: string; value?: { unit?: string; value?: number } } | { unit?: string; value?: number }\n }\n const inner =\n tagged.type === 'length'\n ? (tagged.value as { type?: string; value?: { unit?: string; value?: number } })?.value\n : tagged.value\n if (!inner || typeof (inner as { value?: number }).value !== 'number') return null\n const dim = inner as { unit?: string; value: number }\n if (dim.unit === 'px') return dim.value\n if (dim.unit === 'rem' || dim.unit === 'em') return dim.value * 16\n return dim.value\n}\n\n/**\n * Build an inline-width pair from a `{start, end}`-shaped value.\n * @param leftKey RN key for the start side.\n * @param rightKey RN key for the end side.\n * @param value Typed `{start, end}` length value.\n * @returns Two RN entries, or empty when either side is unrepresentable.\n */\nfunction widthPair(leftKey: string, rightKey: string, value: unknown): readonly RNEntry[] {\n const tagged = value as { start?: unknown; end?: unknown }\n const start = lengthToPxValue(tagged.start)\n const end = lengthToPxValue(tagged.end)\n if (start === null || end === null) return []\n return [\n [leftKey, start],\n [rightKey, end],\n ]\n}\n\n/**\n * Expand a `border-width` shorthand to RN longhands. Collapses to the\n * `borderWidth` shorthand when all four sides match.\n * @param value Typed border-width value with `{top, right, bottom, left}`.\n * @returns RN entries.\n */\nfunction borderWidthShorthand(value: unknown): readonly RNEntry[] {\n const tagged = value as { top?: unknown; right?: unknown; bottom?: unknown; left?: unknown }\n const top = lengthToPxValue(tagged.top)\n const right = lengthToPxValue(tagged.right)\n const bottom = lengthToPxValue(tagged.bottom)\n const left = lengthToPxValue(tagged.left)\n if (top === null || right === null || bottom === null || left === null) return []\n if (top === right && right === bottom && bottom === left) return [['borderWidth', top]]\n return [\n ['borderTopWidth', top],\n ['borderRightWidth', right],\n ['borderBottomWidth', bottom],\n ['borderLeftWidth', left],\n ]\n}\n\n/**\n * Map CSS `border-style` keywords to the strings RN accepts. RN\n * supports only `solid` / `dashed` / `dotted` / `none` — fall back to\n * `solid` for everything else.\n * @param css CSS border-style keyword.\n * @returns RN border-style.\n */\nfunction mapBorderStyle(css: string): string {\n if (css === 'dashed' || css === 'dotted' || css === 'none') return css\n return 'solid'\n}\n\n/**\n * Dispatch border-* longhands and their logical-direction variants to\n * RN style entries. Returns `null` for any property the dispatcher\n * doesn't handle so the caller can fall through.\n *\n * Logical-direction inputs (`border-inline-*`, `border-block-*`,\n * `border-inline-start-*`, …) lower to RN's physical pairs\n * (`borderLeft*` / `borderRight*` / `borderTop*` / `borderBottom*`)\n * since RN doesn't honor logical directions at the style level.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchBorderDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'border-inline-color': {\n return colorPair('borderLeftColor', 'borderRightColor', decl.value)\n }\n case 'border-block-color': {\n return colorPair('borderTopColor', 'borderBottomColor', decl.value)\n }\n case 'border-inline-start-color': {\n return colorSide('borderLeftColor', decl.value)\n }\n case 'border-inline-end-color': {\n return colorSide('borderRightColor', decl.value)\n }\n case 'border-block-start-color': {\n return colorSide('borderTopColor', decl.value)\n }\n case 'border-block-end-color': {\n return colorSide('borderBottomColor', decl.value)\n }\n case 'border-width': {\n return borderWidthShorthand(decl.value)\n }\n case 'border-top-width':\n case 'border-right-width':\n case 'border-bottom-width':\n case 'border-left-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [[kebabToCamel(decl.property), v]]\n }\n case 'border-inline-width': {\n return widthPair('borderLeftWidth', 'borderRightWidth', decl.value)\n }\n case 'border-block-width': {\n return widthPair('borderTopWidth', 'borderBottomWidth', decl.value)\n }\n case 'border-inline-start-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderLeftWidth', v]]\n }\n case 'border-inline-end-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderRightWidth', v]]\n }\n case 'border-block-start-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderTopWidth', v]]\n }\n case 'border-block-end-width': {\n const v = lengthToPxValue(decl.value)\n return v === null ? [] : [['borderBottomWidth', v]]\n }\n case 'border-style': {\n const styleValue = (decl.value as { top?: string }).top\n if (typeof styleValue !== 'string') return []\n return [['borderStyle', mapBorderStyle(styleValue)]]\n }\n case 'border-top-style':\n case 'border-right-style':\n case 'border-bottom-style':\n case 'border-left-style': {\n if (typeof decl.value !== 'string') return []\n return [['borderStyle', mapBorderStyle(decl.value)]]\n }\n default: {\n return null\n }\n }\n}\n"],"names":["color","cssColorToString","isCssWideColorKeyword","kebabToCamel"],"mappings":"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"}
@@ -3,8 +3,10 @@
3
3
  var color = require('./color.cjs');
4
4
 
5
5
  /**
6
- * Build a `[key, hex]` entry from a typed CssColor. Drops keyword colors
7
- * (e.g. `'currentcolor'` strings — RN can't render them).
6
+ * Build a `[key, hex]` entry from a typed CssColor. Drops CSS-wide cascade
7
+ * keywords (`currentColor`, `inherit`, `initial`, `unset`, `revert`,
8
+ * `revert-layer`) — RN has no color cascade, so those reach the native view
9
+ * manager as invalid color strings.
8
10
  * @param key RN style key (camelCase).
9
11
  * @param value Typed `CssColor`-shaped value.
10
12
  * @returns Single-entry list or empty.
@@ -13,10 +15,10 @@ function colorEntry(key, value) {
13
15
  if (value === null || value === undefined)
14
16
  return [];
15
17
  if (typeof value === 'string')
16
- return [[key, value]];
18
+ return color.isCssWideColorKeyword(value) ? [] : [[key, value]];
17
19
  const hex = color.cssColorToString(value);
18
- if (!hex || hex === 'transparent' || hex === 'currentColor')
19
- return [[key, hex]];
20
+ if (color.isCssWideColorKeyword(hex))
21
+ return [];
20
22
  return [[key, hex]];
21
23
  }
22
24
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"color-properties-dispatcher.cjs","sources":["../../../../../src/core/parser/color-properties-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { cssColorToString } from './color'\nimport type { RNEntry } from './types'\n\n/**\n * Build a `[key, hex]` entry from a typed CssColor. Drops keyword colors\n * (e.g. `'currentcolor'` strings — RN can't render them).\n * @param key RN style key (camelCase).\n * @param value Typed `CssColor`-shaped value.\n * @returns Single-entry list or empty.\n */\nfunction colorEntry(key: string, value: unknown): readonly RNEntry[] {\n if (value === null || value === undefined) return []\n if (typeof value === 'string') return [[key, value]]\n const hex = cssColorToString(value as never)\n if (!hex || hex === 'transparent' || hex === 'currentColor') return [[key, hex]]\n return [[key, hex]]\n}\n\n/**\n * Several typed color properties wrap their `CssColor` payload inside a\n * `{type: 'color', value: CssColor}` envelope. Unwrap so the inner color\n * reaches {@link cssColorToString}.\n * @param value Either a `CssColor` directly or a `{type: 'color', value}` wrapper.\n * @returns Unwrapped `CssColor` (or the input untouched).\n */\nfunction unwrapTaggedColor(value: unknown): unknown {\n if (typeof value !== 'object' || value === null) return value\n const tagged = value as { type?: string; value?: unknown }\n if (tagged.type === 'color') return tagged.value\n return value\n}\n\n/**\n * Dispatch color-typed CSS properties (text-decoration-color, fill,\n * stroke, caret-color, outline-color, …) to RN-compatible style entries.\n *\n * lightningcss emits two shapes for color properties:\n * - bare `CssColor` value (e.g. `text-decoration-color`, `outline-color`)\n * - wrapped `{type: 'color', value: CssColor}` (e.g. `fill`, `stroke`,\n * `caret-color`, `accent-color`)\n * We unwrap both and run them through {@link cssColorToString} to land\n * at hex/rgba.\n *\n * Returns `null` for any property the dispatcher doesn't handle so the\n * caller can fall through to the next dispatcher.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchColorPropertyDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'text-decoration-color': {\n return colorEntry('textDecorationColor', decl.value)\n }\n case 'caret-color': {\n return colorEntry('caretColor', unwrapTaggedColor(decl.value))\n }\n case 'fill': {\n return colorEntry('fill', unwrapTaggedColor(decl.value))\n }\n case 'stroke': {\n return colorEntry('stroke', unwrapTaggedColor(decl.value))\n }\n case 'outline-color': {\n // RN doesn't render outlines, but tooling like react-native-web /\n // a11y overlays read it — keep so cross-platform code carries the\n // value through.\n return colorEntry('outlineColor', decl.value)\n }\n case 'accent-color': {\n // RN has no native accent color; skip silently.\n return []\n }\n default: {\n return null\n }\n }\n}\n"],"names":["cssColorToString"],"mappings":";;;;AAIA;;;;;;AAMG;AACH,SAAS,UAAU,CAAC,GAAW,EAAE,KAAc,EAAA;AAC7C,IAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;AAAE,QAAA,OAAO,EAAE;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACpD,IAAA,MAAM,GAAG,GAAGA,sBAAgB,CAAC,KAAc,CAAC;IAC5C,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,cAAc;AAAE,QAAA,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAChF,IAAA,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACrB;AAEA;;;;;;AAMG;AACH,SAAS,iBAAiB,CAAC,KAAc,EAAA;AACvC,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;AAAE,QAAA,OAAO,KAAK;IAC7D,MAAM,MAAM,GAAG,KAA2C;AAC1D,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC,KAAK;AAChD,IAAA,OAAO,KAAK;AACd;AAEA;;;;;;;;;;;;;;;AAeG;AACG,SAAU,gCAAgC,CAAC,IAAmB,EAAA;AAClE,IAAA,QAAQ,IAAI,CAAC,QAAQ;QACnB,KAAK,uBAAuB,EAAE;YAC5B,OAAO,UAAU,CAAC,qBAAqB,EAAE,IAAI,CAAC,KAAK,CAAC;QACtD;QACA,KAAK,aAAa,EAAE;YAClB,OAAO,UAAU,CAAC,YAAY,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE;QACA,KAAK,MAAM,EAAE;YACX,OAAO,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D;QACA,KAAK,QAAQ,EAAE;YACb,OAAO,UAAU,CAAC,QAAQ,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D;QACA,KAAK,eAAe,EAAE;;;;YAIpB,OAAO,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC;QAC/C;QACA,KAAK,cAAc,EAAE;;AAEnB,YAAA,OAAO,EAAE;QACX;QACA,SAAS;AACP,YAAA,OAAO,IAAI;QACb;;AAEJ;;;;"}
1
+ {"version":3,"file":"color-properties-dispatcher.cjs","sources":["../../../../../src/core/parser/color-properties-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { cssColorToString, isCssWideColorKeyword } from './color'\nimport type { RNEntry } from './types'\n\n/**\n * Build a `[key, hex]` entry from a typed CssColor. Drops CSS-wide cascade\n * keywords (`currentColor`, `inherit`, `initial`, `unset`, `revert`,\n * `revert-layer`) — RN has no color cascade, so those reach the native view\n * manager as invalid color strings.\n * @param key RN style key (camelCase).\n * @param value Typed `CssColor`-shaped value.\n * @returns Single-entry list or empty.\n */\nfunction colorEntry(key: string, value: unknown): readonly RNEntry[] {\n if (value === null || value === undefined) return []\n if (typeof value === 'string') return isCssWideColorKeyword(value) ? [] : [[key, value]]\n const hex = cssColorToString(value as never)\n if (isCssWideColorKeyword(hex)) return []\n return [[key, hex]]\n}\n\n/**\n * Several typed color properties wrap their `CssColor` payload inside a\n * `{type: 'color', value: CssColor}` envelope. Unwrap so the inner color\n * reaches {@link cssColorToString}.\n * @param value Either a `CssColor` directly or a `{type: 'color', value}` wrapper.\n * @returns Unwrapped `CssColor` (or the input untouched).\n */\nfunction unwrapTaggedColor(value: unknown): unknown {\n if (typeof value !== 'object' || value === null) return value\n const tagged = value as { type?: string; value?: unknown }\n if (tagged.type === 'color') return tagged.value\n return value\n}\n\n/**\n * Dispatch color-typed CSS properties (text-decoration-color, fill,\n * stroke, caret-color, outline-color, …) to RN-compatible style entries.\n *\n * lightningcss emits two shapes for color properties:\n * - bare `CssColor` value (e.g. `text-decoration-color`, `outline-color`)\n * - wrapped `{type: 'color', value: CssColor}` (e.g. `fill`, `stroke`,\n * `caret-color`, `accent-color`)\n * We unwrap both and run them through {@link cssColorToString} to land\n * at hex/rgba.\n *\n * Returns `null` for any property the dispatcher doesn't handle so the\n * caller can fall through to the next dispatcher.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchColorPropertyDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'text-decoration-color': {\n return colorEntry('textDecorationColor', decl.value)\n }\n case 'caret-color': {\n return colorEntry('caretColor', unwrapTaggedColor(decl.value))\n }\n case 'fill': {\n return colorEntry('fill', unwrapTaggedColor(decl.value))\n }\n case 'stroke': {\n return colorEntry('stroke', unwrapTaggedColor(decl.value))\n }\n case 'outline-color': {\n // RN doesn't render outlines, but tooling like react-native-web /\n // a11y overlays read it — keep so cross-platform code carries the\n // value through.\n return colorEntry('outlineColor', decl.value)\n }\n case 'accent-color': {\n // RN has no native accent color; skip silently.\n return []\n }\n default: {\n return null\n }\n }\n}\n"],"names":["isCssWideColorKeyword","cssColorToString"],"mappings":";;;;AAIA;;;;;;;;AAQG;AACH,SAAS,UAAU,CAAC,GAAW,EAAE,KAAc,EAAA;AAC7C,IAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;AAAE,QAAA,OAAO,EAAE;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAOA,2BAAqB,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxF,IAAA,MAAM,GAAG,GAAGC,sBAAgB,CAAC,KAAc,CAAC;IAC5C,IAAID,2BAAqB,CAAC,GAAG,CAAC;AAAE,QAAA,OAAO,EAAE;AACzC,IAAA,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACrB;AAEA;;;;;;AAMG;AACH,SAAS,iBAAiB,CAAC,KAAc,EAAA;AACvC,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;AAAE,QAAA,OAAO,KAAK;IAC7D,MAAM,MAAM,GAAG,KAA2C;AAC1D,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC,KAAK;AAChD,IAAA,OAAO,KAAK;AACd;AAEA;;;;;;;;;;;;;;;AAeG;AACG,SAAU,gCAAgC,CAAC,IAAmB,EAAA;AAClE,IAAA,QAAQ,IAAI,CAAC,QAAQ;QACnB,KAAK,uBAAuB,EAAE;YAC5B,OAAO,UAAU,CAAC,qBAAqB,EAAE,IAAI,CAAC,KAAK,CAAC;QACtD;QACA,KAAK,aAAa,EAAE;YAClB,OAAO,UAAU,CAAC,YAAY,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE;QACA,KAAK,MAAM,EAAE;YACX,OAAO,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D;QACA,KAAK,QAAQ,EAAE;YACb,OAAO,UAAU,CAAC,QAAQ,EAAE,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D;QACA,KAAK,eAAe,EAAE;;;;YAIpB,OAAO,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC;QAC/C;QACA,KAAK,cAAc,EAAE;;AAEnB,YAAA,OAAO,EAAE;QACX;QACA,SAAS;AACP,YAAA,OAAO,IAAI;QACb;;AAEJ;;;;"}
@@ -134,35 +134,208 @@ function xyzToHex(color) {
134
134
  const mode = color.type === 'xyz-d50' ? 'xyz50' : 'xyz65';
135
135
  return withAlpha(culori.formatHex({ mode, x: color.x, y: color.y, z: color.z }) ?? null, color.alpha);
136
136
  }
137
+ /**
138
+ * Map a CSS `color-mix(in <space>, …)` interpolation space to the culori mode
139
+ * key culori's {@link interpolate} understands. `srgb` is culori's `rgb`;
140
+ * `srgb-linear` is `lrgb`; the lab/lch/oklab/oklch/hsl/hwb spaces share their
141
+ * CSS name. Unknown spaces fall back to `rgb` so a mix still resolves to a
142
+ * concrete color rather than leaking the raw expression.
143
+ * @param space Lowercased interpolation-space token (after `in `).
144
+ * @returns culori interpolation mode key.
145
+ */
146
+ function colorMixModeFor(space) {
147
+ if (space === 'srgb')
148
+ return 'rgb';
149
+ if (space === 'srgb-linear')
150
+ return 'lrgb';
151
+ const known = new Set(['oklab', 'oklch', 'lab', 'lch', 'hsl', 'hwb', 'xyz', 'xyz-d50', 'xyz-d65']);
152
+ return known.has(space) ? space : 'rgb';
153
+ }
154
+ /**
155
+ * Split a `color-mix()` argument list at top-level commas (parens-aware) so a
156
+ * nested `rgb(0, 0, 0)` color slot doesn't fragment the split.
157
+ * @param body Text between the outer `color-mix(` parentheses.
158
+ * @returns Comma-separated argument fragments (trimmed).
159
+ */
160
+ function splitColorMixArgs(body) {
161
+ const parts = [];
162
+ let depth = 0;
163
+ let start = 0;
164
+ for (let index = 0; index < body.length; index += 1) {
165
+ const ch = body[index];
166
+ if (ch === '(')
167
+ depth += 1;
168
+ else if (ch === ')')
169
+ depth -= 1;
170
+ else if (ch === ',' && depth === 0) {
171
+ parts.push(body.slice(start, index).trim());
172
+ start = index + 1;
173
+ }
174
+ }
175
+ parts.push(body.slice(start).trim());
176
+ return parts;
177
+ }
178
+ /**
179
+ * Peel an optional trailing `<num>%` weight off a `color-mix()` color slot.
180
+ * `#ff0000 50%` → `{ color: '#ff0000', weight: 0.5 }`; a bare color → weight
181
+ * `null` (caller fills the complement / defaults to 50/50).
182
+ * @param slot One color argument (color text, optionally suffixed with a percentage).
183
+ * @returns Color text plus its 0–1 weight, or null weight when unspecified.
184
+ */
185
+ function parseColorMixSlot(slot) {
186
+ const trimmed = slot.trim();
187
+ if (!trimmed.endsWith('%'))
188
+ return { color: trimmed, weight: null };
189
+ // End-anchored `<num>%` matcher (no leading `.*?` — avoids the super-linear
190
+ // backtracking ESLint flags). Split the color off at the last whitespace
191
+ // before the percentage token.
192
+ const pct = COLOR_MIX_SLOT_PCT.exec(trimmed);
193
+ if (!pct)
194
+ return { color: trimmed, weight: null };
195
+ const color = trimmed.slice(0, pct.index).trim();
196
+ if (color.length === 0)
197
+ return { color: trimmed, weight: null };
198
+ const weight = Number(pct[1]) / 100;
199
+ return { color, weight: Number.isFinite(weight) ? weight : null };
200
+ }
201
+ /** End-anchored `<num>%` matcher for slicing a color-mix slot's weight off its right edge. No backtracking. */
202
+ const COLOR_MIX_SLOT_PCT = /\s(-?\d+(?:\.\d+)?)%$/;
203
+ /**
204
+ * Resolve a two-color CSS `color-mix(in <space>, A [p1%], B [p2%])` to a
205
+ * concrete sRGB color via culori's {@link interpolate}. CSS weight rules:
206
+ * with one percentage the other fills the complement; with none it is 50/50;
207
+ * with both, the interpolation point is `p2 / (p1 + p2)`. RN can't evaluate
208
+ * `color-mix()` at paint time, so this is the only path that lowers it.
209
+ * @param text Trimmed CSS value beginning with `color-mix(`.
210
+ * @returns sRGB hex/rgba string, or null when the shape/colors can't resolve.
211
+ */
212
+ function resolveColorMix(text) {
213
+ if (!text.endsWith(')'))
214
+ return null;
215
+ const open = text.indexOf('(');
216
+ if (open === -1)
217
+ return null;
218
+ const args = splitColorMixArgs(text.slice(open + 1, -1));
219
+ if (args.length !== 3)
220
+ return null;
221
+ const spaceClause = args[0].toLowerCase();
222
+ if (!spaceClause.startsWith('in '))
223
+ return null;
224
+ const mode = colorMixModeFor(spaceClause.slice(3).trim());
225
+ const first = parseColorMixSlot(args[1]);
226
+ const second = parseColorMixSlot(args[2]);
227
+ if (first.color.length === 0 || second.color.length === 0)
228
+ return null;
229
+ const point = colorMixPoint(first.weight, second.weight);
230
+ if (point === null)
231
+ return null;
232
+ try {
233
+ const mixed = culori.interpolate([first.color, second.color], mode)(point);
234
+ if (!mixed)
235
+ return null;
236
+ const back = culori.rgb(mixed);
237
+ if (!back || ![back.r, back.g, back.b].every((v) => typeof v === 'number' && Number.isFinite(v)))
238
+ return null;
239
+ const alpha = typeof back.alpha === 'number' ? back.alpha : 1;
240
+ return rgbIntsToString(clampByte(back.r * 255), clampByte(back.g * 255), clampByte(back.b * 255), alpha);
241
+ }
242
+ catch {
243
+ // culori threw on an unparseable color slot — drop rather than leak the raw string.
244
+ return null;
245
+ }
246
+ }
247
+ /**
248
+ * Compute the 0–1 interpolation point (weight of the SECOND color) from the
249
+ * two optional `color-mix()` weights, applying CSS normalization.
250
+ * @param firstWeight 0–1 weight of color A, or null when unspecified.
251
+ * @param secondWeight 0–1 weight of color B, or null when unspecified.
252
+ * @returns Interpolation point in `[0, 1]`, or null when both weights are 0.
253
+ */
254
+ function colorMixPoint(firstWeight, secondWeight) {
255
+ if (firstWeight === null && secondWeight === null)
256
+ return 0.5;
257
+ if (firstWeight !== null && secondWeight === null)
258
+ return 1 - firstWeight;
259
+ if (firstWeight === null && secondWeight !== null)
260
+ return secondWeight;
261
+ const sum = firstWeight + secondWeight;
262
+ if (sum === 0)
263
+ return null;
264
+ return secondWeight / sum;
265
+ }
266
+ /**
267
+ * CSS-wide cascade keywords that resolve a property against the inherited /
268
+ * initial / previous-layer value at paint time. React Native has NO color
269
+ * cascade — there is no inherited `color` for an arbitrary style prop and no
270
+ * cascade layers — so as a `color` / `backgroundColor` / `borderColor` value
271
+ * every one of these reaches RN as an invalid color string. `currentColor`
272
+ * belongs here too: it resolves to the element's inherited `color`, which RN
273
+ * never threads into other color props. The color path must DROP these (omit
274
+ * the key) rather than leak the keyword. NOTE: `transparent` is NOT here — it
275
+ * is a real color that {@link cssColorToString} / {@link normalizeColorString}
276
+ * lower to `rgba(0, 0, 0, 0)`, which RN paints correctly.
277
+ */
278
+ const CSS_WIDE_COLOR_KEYWORDS = new Set([
279
+ 'currentcolor',
280
+ 'inherit',
281
+ 'initial',
282
+ 'unset',
283
+ 'revert',
284
+ 'revert-layer',
285
+ ]);
137
286
  /**
138
287
  * Modern CSS color functions RN's native view manager can't paint —
139
288
  * everything else (hex, `rgb()`/`rgba()`, `hsl()`/`hsla()`, named colors,
140
- * `transparent`, `currentColor`) RN reads directly and must pass through
141
- * untouched. Custom `@theme` tokens reach the parser as `var(--color-x)`
142
- * (only the default palette is `theme(inline)`-d), so they flow through the
143
- * unparsed-string path where the typed {@link cssColorToString} never runs
144
- * this is the one place that lowers their wide-gamut values to sRGB.
289
+ * `transparent`) RN reads directly and must pass through untouched. The
290
+ * CSS-wide cascade keywords (`currentColor`, `inherit`, …) are NOT readable
291
+ * they have no RN equivalent and are dropped via {@link isCssWideColorKeyword}.
292
+ * Custom `@theme` tokens reach the parser as `var(--color-x)` (only the default
293
+ * palette is `theme(inline)`-d), so they flow through the unparsed-string path
294
+ * where the typed {@link cssColorToString} never runs — this is the one place
295
+ * that lowers their wide-gamut values to sRGB. `color-mix(` is in the list too,
296
+ * but it takes the dedicated {@link resolveColorMix} path — culori's `rgb()`
297
+ * parser can't read it.
145
298
  */
146
- const RN_UNREADABLE_COLOR_PREFIXES = ['oklch(', 'oklab(', 'lab(', 'lch(', 'color(', 'hwb('];
299
+ const RN_UNREADABLE_COLOR_PREFIXES = ['oklch(', 'oklab(', 'lab(', 'lch(', 'color(', 'hwb(', 'color-mix('];
147
300
  /**
148
301
  * Lower a wide-gamut / modern CSS color STRING (`oklch(…)`, `lab(…)`,
149
- * `color(display-p3 …)`, …) to an sRGB hex/rgba string RN can paint. Returns
150
- * `null` for anything RN already understands (hex, rgb, hsl, named) so the
151
- * caller keeps the original text — only the unrepresentable forms convert.
302
+ * `color(display-p3 …)`, `color-mix(…)`) to an sRGB hex/rgba string RN can
303
+ * paint. Returns `null` for anything RN already understands (hex, rgb, hsl,
304
+ * named) so the caller keeps the original text — only the unrepresentable
305
+ * forms convert. `color-mix()` is resolved via culori's interpolator; when it
306
+ * (or any other modern form) can't resolve, returns null so the caller DROPS
307
+ * the value rather than leaking the raw, RN-unreadable string.
152
308
  * Mirrors {@link cssColorToString}'s culori lowering for the string path.
153
309
  * @param text Resolved CSS color text (post theme-var substitution).
154
310
  * @returns sRGB color string, or `null` when no conversion is needed/possible.
155
311
  */
156
312
  function normalizeColorString(text) {
157
- const lower = text.trim().toLowerCase();
313
+ const trimmed = text.trim();
314
+ const lower = trimmed.toLowerCase();
158
315
  if (!RN_UNREADABLE_COLOR_PREFIXES.some((prefix) => lower.startsWith(prefix)))
159
316
  return null;
317
+ if (lower.startsWith('color-mix('))
318
+ return resolveColorMix(trimmed);
160
319
  const parsed = culori.rgb(text);
161
320
  if (!parsed || ![parsed.r, parsed.g, parsed.b].every((v) => typeof v === 'number' && Number.isFinite(v)))
162
321
  return null;
163
322
  const alpha = typeof parsed.alpha === 'number' ? parsed.alpha : 1;
164
323
  return rgbIntsToString(clampByte(parsed.r * 255), clampByte(parsed.g * 255), clampByte(parsed.b * 255), alpha);
165
324
  }
325
+ /**
326
+ * Whether a resolved color STRING is a CSS-wide cascade keyword
327
+ * (`currentColor`, `inherit`, `initial`, `unset`, `revert`, `revert-layer`)
328
+ * with no React Native equivalent. RN has no color cascade, so the color path
329
+ * must DROP (omit the key) when this is true rather than emit the keyword —
330
+ * RN would otherwise receive an invalid color string and render nothing.
331
+ * `transparent` is NOT a cascade keyword: it is a concrete color the converters
332
+ * lower to `rgba(0, 0, 0, 0)`, so it returns false here and resolves normally.
333
+ * @param text Resolved color text (post theme-var substitution / typed-color stringification).
334
+ * @returns True when the value is an RN-unrepresentable CSS-wide keyword.
335
+ */
336
+ function isCssWideColorKeyword(text) {
337
+ return CSS_WIDE_COLOR_KEYWORDS.has(text.trim().toLowerCase());
338
+ }
166
339
  /**
167
340
  * Convert a lightningcss `CssColor` to an RN-safe color string. RGB
168
341
  * passes through unchanged. LAB / LCH / OKLAB / OKLCH / `color(xyz-…)`
@@ -212,6 +385,16 @@ function cssColorToString(color) {
212
385
  return 'currentColor';
213
386
  }
214
387
  case 'light-dark': {
388
+ // `light-dark(L, D)` is a RUNTIME CSS function — the browser picks the
389
+ // branch from the element's `color-scheme`. rnwind has no runtime CSS
390
+ // evaluation, and the active scheme is NOT threaded into this typed
391
+ // converter (it takes a bare `CssColor`, and every one of its ~15 call
392
+ // sites — border / shorthand / gradient / declaration dispatchers — calls
393
+ // it without a scheme). Scheme resolution instead happens UPSTREAM, at the
394
+ // CSS-block walk (`@custom-variant` + `.dark {}` selectors in
395
+ // theme-vars.ts), which compiles a separate atom + var table per scheme.
396
+ // So the `.light` branch is the correct compile-time default here; the
397
+ // dark value is carried by the scheme-specific atom, not by this function.
215
398
  return cssColorToString(color.light);
216
399
  }
217
400
  default: {
@@ -221,5 +404,6 @@ function cssColorToString(color) {
221
404
  }
222
405
 
223
406
  exports.cssColorToString = cssColorToString;
407
+ exports.isCssWideColorKeyword = isCssWideColorKeyword;
224
408
  exports.normalizeColorString = normalizeColorString;
225
409
  //# sourceMappingURL=color.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"color.cjs","sources":["../../../../../src/core/parser/color.ts"],"sourcesContent":["import type { CssColor, LABColor } from 'lightningcss'\nimport { formatHex, rgb as culoriRgb } from 'culori'\n\n/**\n * Clamp a 0-255 float to the integer byte range RN color strings accept.\n * @param value Unclamped float (may be negative or above 255).\n * @returns Integer in `[0, 255]`.\n */\nfunction clampByte(value: number): number {\n if (value < 0) return 0\n if (value > 255) return 255\n return Math.round(value)\n}\n\n/**\n * Two-digit hex encoding of a 0-255 byte.\n * @param byte Byte value (may be out-of-range — clamped).\n * @returns Zero-padded two-char hex string.\n */\nfunction byteToHex(byte: number): string {\n const hex = clampByte(byte).toString(16)\n return hex.length === 1 ? `0${hex}` : hex\n}\n\n/**\n * Format an integer-RGB triple + alpha as `#rrggbb` or `rgba(r, g, b, a)`.\n * @param r 0-255 red.\n * @param g 0-255 green.\n * @param b 0-255 blue.\n * @param alpha 0-1 alpha.\n * @returns Color string.\n */\nfunction rgbIntsToString(r: number, g: number, b: number, alpha: number): string {\n if (alpha >= 1) return `#${byteToHex(r)}${byteToHex(g)}${byteToHex(b)}`\n // Round the alpha to shed f32 noise (`0.2 → 0.20000000298…`) — RN parses\n // either, but the rounded form keeps generated StyleSheets compact.\n return `rgba(${r}, ${g}, ${b}, ${Math.round(alpha * 10_000) / 10_000})`\n}\n\n/**\n * Format a float-RGB triple + alpha (CSS `color(srgb …)` forms) as\n * hex/rgba.\n * @param r 0-1 red.\n * @param g 0-1 green.\n * @param b 0-1 blue.\n * @param alpha 0-1 alpha.\n * @returns Color string.\n */\nfunction floatRgbToString(r: number, g: number, b: number, alpha: number): string {\n return rgbIntsToString(clampByte(r * 255), clampByte(g * 255), clampByte(b * 255), alpha)\n}\n\n/**\n * Dispatch a LAB-family color through culori's hex formatter.\n * @param color Typed LAB-family color.\n * @returns `#rrggbb` string, or `null` when culori couldn't convert.\n */\nfunction culoriHexFor(color: LABColor): string | null {\n switch (color.type) {\n case 'oklch': {\n return formatHex({ mode: 'oklch', l: color.l, c: color.c, h: color.h }) ?? null\n }\n case 'oklab': {\n return formatHex({ mode: 'oklab', l: color.l, a: color.a, b: color.b }) ?? null\n }\n case 'lab': {\n return formatHex({ mode: 'lab', l: color.l, a: color.a, b: color.b }) ?? null\n }\n case 'lch': {\n return formatHex({ mode: 'lch', l: color.l, c: color.c, h: color.h }) ?? null\n }\n default: {\n return null\n }\n }\n}\n\n/**\n * Composite a culori-produced sRGB hex with the source alpha into the RN\n * color string. Shared tail for every culori-backed conversion (lab\n * family, XYZ, wide-gamut RGB): opaque → the hex as-is; translucent →\n * `rgba(...)` rebuilt from the hex channels.\n * @param hex sRGB hex from culori, or `null` when culori rejected the color.\n * @param alpha Source alpha (0–1).\n * @returns RN color string.\n */\nfunction withAlpha(hex: string | null, alpha: number): string {\n if (!hex) return alpha < 1 ? 'rgba(0, 0, 0, 0)' : 'transparent'\n if (alpha >= 1) return hex\n const back = culoriRgb(hex)\n if (!back) return hex\n return rgbIntsToString(clampByte(back.r * 255), clampByte(back.g * 255), clampByte(back.b * 255), alpha)\n}\n\n/**\n * Convert a LAB / LCH / OKLAB / OKLCH color to sRGB hex via culori. RN\n * can't evaluate these modern color spaces at paint time; compile-time\n * lowering to sRGB is the only portable path.\n * @param color Typed lab-family color.\n * @returns Hex or rgba string in sRGB.\n */\nfunction labFamilyToHex(color: LABColor): string {\n return withAlpha(culoriHexFor(color), color.alpha)\n}\n\n/**\n * Convert a wide-gamut `color(<space> r g b)` triple to sRGB hex via\n * culori. The channels are NOT sRGB — each space (display-p3, rec2020,\n * a98-rgb, prophoto-rgb, srgb-linear) carries its own primaries / transfer\n * function, so a bare `channel * 255` would mis-paint. culori does the\n * gamut + gamma conversion to sRGB.\n * @param mode culori mode key for the source space.\n * @param r Source red (0–1).\n * @param g Source green (0–1).\n * @param b Source blue (0–1).\n * @param alpha Alpha channel (0–1).\n * @returns sRGB color string RN accepts.\n */\nfunction wideGamutToHex(mode: 'lrgb' | 'p3' | 'a98' | 'prophoto' | 'rec2020', r: number, g: number, b: number, alpha: number): string {\n return withAlpha(formatHex({ mode, r, g, b }) ?? null, alpha)\n}\n\n/**\n * Convert a CSS `color(xyz-d50 …)` / `color(xyz-d65 …)` value to sRGB hex\n * via culori.\n * @param color Typed XYZ color (discriminated by `type`).\n * @param color.type Whether the color is in the D50 or D65 XYZ space.\n * @param color.x CIE X component (0–1).\n * @param color.y CIE Y component (0–1).\n * @param color.z CIE Z component (0–1).\n * @param color.alpha Alpha channel (0–1).\n * @returns `#rrggbb` string, or `'transparent'` when culori rejects it.\n */\nfunction xyzToHex(color: { type: 'xyz-d50' | 'xyz-d65'; x: number; y: number; z: number; alpha: number }): string {\n const mode = color.type === 'xyz-d50' ? 'xyz50' : 'xyz65'\n return withAlpha(formatHex({ mode, x: color.x, y: color.y, z: color.z }) ?? null, color.alpha)\n}\n\n/**\n * Modern CSS color functions RN's native view manager can't paint —\n * everything else (hex, `rgb()`/`rgba()`, `hsl()`/`hsla()`, named colors,\n * `transparent`, `currentColor`) RN reads directly and must pass through\n * untouched. Custom `@theme` tokens reach the parser as `var(--color-x)`\n * (only the default palette is `theme(inline)`-d), so they flow through the\n * unparsed-string path where the typed {@link cssColorToString} never runs —\n * this is the one place that lowers their wide-gamut values to sRGB.\n */\nconst RN_UNREADABLE_COLOR_PREFIXES: readonly string[] = ['oklch(', 'oklab(', 'lab(', 'lch(', 'color(', 'hwb(']\n\n/**\n * Lower a wide-gamut / modern CSS color STRING (`oklch(…)`, `lab(…)`,\n * `color(display-p3 …)`, …) to an sRGB hex/rgba string RN can paint. Returns\n * `null` for anything RN already understands (hex, rgb, hsl, named) so the\n * caller keeps the original text — only the unrepresentable forms convert.\n * Mirrors {@link cssColorToString}'s culori lowering for the string path.\n * @param text Resolved CSS color text (post theme-var substitution).\n * @returns sRGB color string, or `null` when no conversion is needed/possible.\n */\nexport function normalizeColorString(text: string): string | null {\n const lower = text.trim().toLowerCase()\n if (!RN_UNREADABLE_COLOR_PREFIXES.some((prefix) => lower.startsWith(prefix))) return null\n const parsed = culoriRgb(text)\n if (!parsed || ![parsed.r, parsed.g, parsed.b].every((v) => typeof v === 'number' && Number.isFinite(v))) return null\n const alpha = typeof parsed.alpha === 'number' ? parsed.alpha : 1\n return rgbIntsToString(clampByte(parsed.r * 255), clampByte(parsed.g * 255), clampByte(parsed.b * 255), alpha)\n}\n\n/**\n * Convert a lightningcss `CssColor` to an RN-safe color string. RGB\n * passes through unchanged. LAB / LCH / OKLAB / OKLCH / `color(xyz-…)`\n * forms go through culori to reach sRGB — RN's native view manager only\n * understands sRGB-family strings. SystemColor keywords (`'background'`,\n * `'canvas'`, …) pass through untouched; they have no RN analog and the\n * runtime ignores unknown color strings gracefully.\n * @param color Typed color value.\n * @returns Color string RN accepts.\n */\nexport function cssColorToString(color: CssColor): string {\n if (typeof color === 'string') return color\n switch (color.type) {\n case 'rgb': {\n return rgbIntsToString(color.r, color.g, color.b, color.alpha)\n }\n case 'lab':\n case 'lch':\n case 'oklab':\n case 'oklch': {\n return labFamilyToHex(color)\n }\n case 'srgb': {\n return floatRgbToString(color.r, color.g, color.b, color.alpha)\n }\n case 'srgb-linear': {\n return wideGamutToHex('lrgb', color.r, color.g, color.b, color.alpha)\n }\n case 'display-p3': {\n return wideGamutToHex('p3', color.r, color.g, color.b, color.alpha)\n }\n case 'a98-rgb': {\n return wideGamutToHex('a98', color.r, color.g, color.b, color.alpha)\n }\n case 'prophoto-rgb': {\n return wideGamutToHex('prophoto', color.r, color.g, color.b, color.alpha)\n }\n case 'rec2020': {\n return wideGamutToHex('rec2020', color.r, color.g, color.b, color.alpha)\n }\n case 'xyz-d50':\n case 'xyz-d65': {\n return xyzToHex(color)\n }\n case 'currentcolor': {\n return 'currentColor'\n }\n case 'light-dark': {\n return cssColorToString(color.light)\n }\n default: {\n return 'transparent'\n }\n }\n}\n"],"names":["formatHex","culoriRgb"],"mappings":";;;;AAGA;;;;AAIG;AACH,SAAS,SAAS,CAAC,KAAa,EAAA;IAC9B,IAAI,KAAK,GAAG,CAAC;AAAE,QAAA,OAAO,CAAC;IACvB,IAAI,KAAK,GAAG,GAAG;AAAE,QAAA,OAAO,GAAG;AAC3B,IAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAC1B;AAEA;;;;AAIG;AACH,SAAS,SAAS,CAAC,IAAY,EAAA;IAC7B,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;AACxC,IAAA,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,GAAG,GAAG;AAC3C;AAEA;;;;;;;AAOG;AACH,SAAS,eAAe,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa,EAAA;IACrE,IAAI,KAAK,IAAI,CAAC;AAAE,QAAA,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE;;;AAGvE,IAAA,OAAO,QAAQ,CAAC,CAAA,EAAA,EAAK,CAAC,CAAA,EAAA,EAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,GAAG;AACzE;AAEA;;;;;;;;AAQG;AACH,SAAS,gBAAgB,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa,EAAA;IACtE,OAAO,eAAe,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC;AAC3F;AAEA;;;;AAIG;AACH,SAAS,YAAY,CAAC,KAAe,EAAA;AACnC,IAAA,QAAQ,KAAK,CAAC,IAAI;QAChB,KAAK,OAAO,EAAE;AACZ,YAAA,OAAOA,gBAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI;QACjF;QACA,KAAK,OAAO,EAAE;AACZ,YAAA,OAAOA,gBAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI;QACjF;QACA,KAAK,KAAK,EAAE;AACV,YAAA,OAAOA,gBAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI;QAC/E;QACA,KAAK,KAAK,EAAE;AACV,YAAA,OAAOA,gBAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI;QAC/E;QACA,SAAS;AACP,YAAA,OAAO,IAAI;QACb;;AAEJ;AAEA;;;;;;;;AAQG;AACH,SAAS,SAAS,CAAC,GAAkB,EAAE,KAAa,EAAA;AAClD,IAAA,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,GAAG,CAAC,GAAG,kBAAkB,GAAG,aAAa;IAC/D,IAAI,KAAK,IAAI,CAAC;AAAE,QAAA,OAAO,GAAG;AAC1B,IAAA,MAAM,IAAI,GAAGC,UAAS,CAAC,GAAG,CAAC;AAC3B,IAAA,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,GAAG;AACrB,IAAA,OAAO,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC;AAC1G;AAEA;;;;;;AAMG;AACH,SAAS,cAAc,CAAC,KAAe,EAAA;IACrC,OAAO,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;AACpD;AAEA;;;;;;;;;;;;AAYG;AACH,SAAS,cAAc,CAAC,IAAoD,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa,EAAA;AAC1H,IAAA,OAAO,SAAS,CAACD,gBAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,KAAK,CAAC;AAC/D;AAEA;;;;;;;;;;AAUG;AACH,SAAS,QAAQ,CAAC,KAAsF,EAAA;AACtG,IAAA,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,GAAG,OAAO,GAAG,OAAO;AACzD,IAAA,OAAO,SAAS,CAACA,gBAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC;AAChG;AAEA;;;;;;;;AAQG;AACH,MAAM,4BAA4B,GAAsB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC;AAE9G;;;;;;;;AAQG;AACG,SAAU,oBAAoB,CAAC,IAAY,EAAA;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;AACvC,IAAA,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAAE,QAAA,OAAO,IAAI;AACzF,IAAA,MAAM,MAAM,GAAGC,UAAS,CAAC,IAAI,CAAC;AAC9B,IAAA,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAAE,QAAA,OAAO,IAAI;AACrH,IAAA,MAAM,KAAK,GAAG,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;AACjE,IAAA,OAAO,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC;AAChH;AAEA;;;;;;;;;AASG;AACG,SAAU,gBAAgB,CAAC,KAAe,EAAA;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,KAAK;AAC3C,IAAA,QAAQ,KAAK,CAAC,IAAI;QAChB,KAAK,KAAK,EAAE;AACV,YAAA,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QAChE;AACA,QAAA,KAAK,KAAK;AACV,QAAA,KAAK,KAAK;AACV,QAAA,KAAK,OAAO;QACZ,KAAK,OAAO,EAAE;AACZ,YAAA,OAAO,cAAc,CAAC,KAAK,CAAC;QAC9B;QACA,KAAK,MAAM,EAAE;AACX,YAAA,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QACjE;QACA,KAAK,aAAa,EAAE;YAClB,OAAO,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QACvE;QACA,KAAK,YAAY,EAAE;YACjB,OAAO,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QACrE;QACA,KAAK,SAAS,EAAE;YACd,OAAO,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QACtE;QACA,KAAK,cAAc,EAAE;YACnB,OAAO,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QAC3E;QACA,KAAK,SAAS,EAAE;YACd,OAAO,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;QAC1E;AACA,QAAA,KAAK,SAAS;QACd,KAAK,SAAS,EAAE;AACd,YAAA,OAAO,QAAQ,CAAC,KAAK,CAAC;QACxB;QACA,KAAK,cAAc,EAAE;AACnB,YAAA,OAAO,cAAc;QACvB;QACA,KAAK,YAAY,EAAE;AACjB,YAAA,OAAO,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC;QACtC;QACA,SAAS;AACP,YAAA,OAAO,aAAa;QACtB;;AAEJ;;;;;"}
1
+ {"version":3,"file":"color.cjs","sources":["../../../../../src/core/parser/color.ts"],"sourcesContent":["import type { CssColor, LABColor } from 'lightningcss'\nimport { formatHex, interpolate, rgb as culoriRgb } from 'culori'\n\n/**\n * Clamp a 0-255 float to the integer byte range RN color strings accept.\n * @param value Unclamped float (may be negative or above 255).\n * @returns Integer in `[0, 255]`.\n */\nfunction clampByte(value: number): number {\n if (value < 0) return 0\n if (value > 255) return 255\n return Math.round(value)\n}\n\n/**\n * Two-digit hex encoding of a 0-255 byte.\n * @param byte Byte value (may be out-of-range — clamped).\n * @returns Zero-padded two-char hex string.\n */\nfunction byteToHex(byte: number): string {\n const hex = clampByte(byte).toString(16)\n return hex.length === 1 ? `0${hex}` : hex\n}\n\n/**\n * Format an integer-RGB triple + alpha as `#rrggbb` or `rgba(r, g, b, a)`.\n * @param r 0-255 red.\n * @param g 0-255 green.\n * @param b 0-255 blue.\n * @param alpha 0-1 alpha.\n * @returns Color string.\n */\nfunction rgbIntsToString(r: number, g: number, b: number, alpha: number): string {\n if (alpha >= 1) return `#${byteToHex(r)}${byteToHex(g)}${byteToHex(b)}`\n // Round the alpha to shed f32 noise (`0.2 → 0.20000000298…`) — RN parses\n // either, but the rounded form keeps generated StyleSheets compact.\n return `rgba(${r}, ${g}, ${b}, ${Math.round(alpha * 10_000) / 10_000})`\n}\n\n/**\n * Format a float-RGB triple + alpha (CSS `color(srgb …)` forms) as\n * hex/rgba.\n * @param r 0-1 red.\n * @param g 0-1 green.\n * @param b 0-1 blue.\n * @param alpha 0-1 alpha.\n * @returns Color string.\n */\nfunction floatRgbToString(r: number, g: number, b: number, alpha: number): string {\n return rgbIntsToString(clampByte(r * 255), clampByte(g * 255), clampByte(b * 255), alpha)\n}\n\n/**\n * Dispatch a LAB-family color through culori's hex formatter.\n * @param color Typed LAB-family color.\n * @returns `#rrggbb` string, or `null` when culori couldn't convert.\n */\nfunction culoriHexFor(color: LABColor): string | null {\n switch (color.type) {\n case 'oklch': {\n return formatHex({ mode: 'oklch', l: color.l, c: color.c, h: color.h }) ?? null\n }\n case 'oklab': {\n return formatHex({ mode: 'oklab', l: color.l, a: color.a, b: color.b }) ?? null\n }\n case 'lab': {\n return formatHex({ mode: 'lab', l: color.l, a: color.a, b: color.b }) ?? null\n }\n case 'lch': {\n return formatHex({ mode: 'lch', l: color.l, c: color.c, h: color.h }) ?? null\n }\n default: {\n return null\n }\n }\n}\n\n/**\n * Composite a culori-produced sRGB hex with the source alpha into the RN\n * color string. Shared tail for every culori-backed conversion (lab\n * family, XYZ, wide-gamut RGB): opaque → the hex as-is; translucent →\n * `rgba(...)` rebuilt from the hex channels.\n * @param hex sRGB hex from culori, or `null` when culori rejected the color.\n * @param alpha Source alpha (0–1).\n * @returns RN color string.\n */\nfunction withAlpha(hex: string | null, alpha: number): string {\n if (!hex) return alpha < 1 ? 'rgba(0, 0, 0, 0)' : 'transparent'\n if (alpha >= 1) return hex\n const back = culoriRgb(hex)\n if (!back) return hex\n return rgbIntsToString(clampByte(back.r * 255), clampByte(back.g * 255), clampByte(back.b * 255), alpha)\n}\n\n/**\n * Convert a LAB / LCH / OKLAB / OKLCH color to sRGB hex via culori. RN\n * can't evaluate these modern color spaces at paint time; compile-time\n * lowering to sRGB is the only portable path.\n * @param color Typed lab-family color.\n * @returns Hex or rgba string in sRGB.\n */\nfunction labFamilyToHex(color: LABColor): string {\n return withAlpha(culoriHexFor(color), color.alpha)\n}\n\n/**\n * Convert a wide-gamut `color(<space> r g b)` triple to sRGB hex via\n * culori. The channels are NOT sRGB — each space (display-p3, rec2020,\n * a98-rgb, prophoto-rgb, srgb-linear) carries its own primaries / transfer\n * function, so a bare `channel * 255` would mis-paint. culori does the\n * gamut + gamma conversion to sRGB.\n * @param mode culori mode key for the source space.\n * @param r Source red (0–1).\n * @param g Source green (0–1).\n * @param b Source blue (0–1).\n * @param alpha Alpha channel (0–1).\n * @returns sRGB color string RN accepts.\n */\nfunction wideGamutToHex(mode: 'lrgb' | 'p3' | 'a98' | 'prophoto' | 'rec2020', r: number, g: number, b: number, alpha: number): string {\n return withAlpha(formatHex({ mode, r, g, b }) ?? null, alpha)\n}\n\n/**\n * Convert a CSS `color(xyz-d50 …)` / `color(xyz-d65 …)` value to sRGB hex\n * via culori.\n * @param color Typed XYZ color (discriminated by `type`).\n * @param color.type Whether the color is in the D50 or D65 XYZ space.\n * @param color.x CIE X component (0–1).\n * @param color.y CIE Y component (0–1).\n * @param color.z CIE Z component (0–1).\n * @param color.alpha Alpha channel (0–1).\n * @returns `#rrggbb` string, or `'transparent'` when culori rejects it.\n */\nfunction xyzToHex(color: { type: 'xyz-d50' | 'xyz-d65'; x: number; y: number; z: number; alpha: number }): string {\n const mode = color.type === 'xyz-d50' ? 'xyz50' : 'xyz65'\n return withAlpha(formatHex({ mode, x: color.x, y: color.y, z: color.z }) ?? null, color.alpha)\n}\n\n/**\n * Map a CSS `color-mix(in <space>, …)` interpolation space to the culori mode\n * key culori's {@link interpolate} understands. `srgb` is culori's `rgb`;\n * `srgb-linear` is `lrgb`; the lab/lch/oklab/oklch/hsl/hwb spaces share their\n * CSS name. Unknown spaces fall back to `rgb` so a mix still resolves to a\n * concrete color rather than leaking the raw expression.\n * @param space Lowercased interpolation-space token (after `in `).\n * @returns culori interpolation mode key.\n */\nfunction colorMixModeFor(space: string): string {\n if (space === 'srgb') return 'rgb'\n if (space === 'srgb-linear') return 'lrgb'\n const known = new Set(['oklab', 'oklch', 'lab', 'lch', 'hsl', 'hwb', 'xyz', 'xyz-d50', 'xyz-d65'])\n return known.has(space) ? space : 'rgb'\n}\n\n/**\n * Split a `color-mix()` argument list at top-level commas (parens-aware) so a\n * nested `rgb(0, 0, 0)` color slot doesn't fragment the split.\n * @param body Text between the outer `color-mix(` parentheses.\n * @returns Comma-separated argument fragments (trimmed).\n */\nfunction splitColorMixArgs(body: string): string[] {\n const parts: string[] = []\n let depth = 0\n let start = 0\n for (let index = 0; index < body.length; index += 1) {\n const ch = body[index]\n if (ch === '(') depth += 1\n else if (ch === ')') depth -= 1\n else if (ch === ',' && depth === 0) {\n parts.push(body.slice(start, index).trim())\n start = index + 1\n }\n }\n parts.push(body.slice(start).trim())\n return parts\n}\n\n/**\n * Peel an optional trailing `<num>%` weight off a `color-mix()` color slot.\n * `#ff0000 50%` → `{ color: '#ff0000', weight: 0.5 }`; a bare color → weight\n * `null` (caller fills the complement / defaults to 50/50).\n * @param slot One color argument (color text, optionally suffixed with a percentage).\n * @returns Color text plus its 0–1 weight, or null weight when unspecified.\n */\nfunction parseColorMixSlot(slot: string): { color: string; weight: number | null } {\n const trimmed = slot.trim()\n if (!trimmed.endsWith('%')) return { color: trimmed, weight: null }\n // End-anchored `<num>%` matcher (no leading `.*?` — avoids the super-linear\n // backtracking ESLint flags). Split the color off at the last whitespace\n // before the percentage token.\n const pct = COLOR_MIX_SLOT_PCT.exec(trimmed)\n if (!pct) return { color: trimmed, weight: null }\n const color = trimmed.slice(0, pct.index).trim()\n if (color.length === 0) return { color: trimmed, weight: null }\n const weight = Number(pct[1]) / 100\n return { color, weight: Number.isFinite(weight) ? weight : null }\n}\n\n/** End-anchored `<num>%` matcher for slicing a color-mix slot's weight off its right edge. No backtracking. */\n \nconst COLOR_MIX_SLOT_PCT = /\\s(-?\\d+(?:\\.\\d+)?)%$/\n\n/**\n * Resolve a two-color CSS `color-mix(in <space>, A [p1%], B [p2%])` to a\n * concrete sRGB color via culori's {@link interpolate}. CSS weight rules:\n * with one percentage the other fills the complement; with none it is 50/50;\n * with both, the interpolation point is `p2 / (p1 + p2)`. RN can't evaluate\n * `color-mix()` at paint time, so this is the only path that lowers it.\n * @param text Trimmed CSS value beginning with `color-mix(`.\n * @returns sRGB hex/rgba string, or null when the shape/colors can't resolve.\n */\nfunction resolveColorMix(text: string): string | null {\n if (!text.endsWith(')')) return null\n const open = text.indexOf('(')\n if (open === -1) return null\n const args = splitColorMixArgs(text.slice(open + 1, -1))\n if (args.length !== 3) return null\n const spaceClause = args[0]!.toLowerCase()\n if (!spaceClause.startsWith('in ')) return null\n const mode = colorMixModeFor(spaceClause.slice(3).trim())\n const first = parseColorMixSlot(args[1]!)\n const second = parseColorMixSlot(args[2]!)\n if (first.color.length === 0 || second.color.length === 0) return null\n const point = colorMixPoint(first.weight, second.weight)\n if (point === null) return null\n try {\n const mixed = interpolate([first.color, second.color], mode as never)(point)\n if (!mixed) return null\n const back = culoriRgb(mixed) as { r?: number; g?: number; b?: number; alpha?: number } | undefined\n if (!back || ![back.r, back.g, back.b].every((v) => typeof v === 'number' && Number.isFinite(v))) return null\n const alpha = typeof back.alpha === 'number' ? back.alpha : 1\n return rgbIntsToString(clampByte(back.r! * 255), clampByte(back.g! * 255), clampByte(back.b! * 255), alpha)\n } catch {\n // culori threw on an unparseable color slot — drop rather than leak the raw string.\n return null\n }\n}\n\n/**\n * Compute the 0–1 interpolation point (weight of the SECOND color) from the\n * two optional `color-mix()` weights, applying CSS normalization.\n * @param firstWeight 0–1 weight of color A, or null when unspecified.\n * @param secondWeight 0–1 weight of color B, or null when unspecified.\n * @returns Interpolation point in `[0, 1]`, or null when both weights are 0.\n */\nfunction colorMixPoint(firstWeight: number | null, secondWeight: number | null): number | null {\n if (firstWeight === null && secondWeight === null) return 0.5\n if (firstWeight !== null && secondWeight === null) return 1 - firstWeight\n if (firstWeight === null && secondWeight !== null) return secondWeight\n const sum = firstWeight! + secondWeight!\n if (sum === 0) return null\n return secondWeight! / sum\n}\n\n/**\n * CSS-wide cascade keywords that resolve a property against the inherited /\n * initial / previous-layer value at paint time. React Native has NO color\n * cascade — there is no inherited `color` for an arbitrary style prop and no\n * cascade layers — so as a `color` / `backgroundColor` / `borderColor` value\n * every one of these reaches RN as an invalid color string. `currentColor`\n * belongs here too: it resolves to the element's inherited `color`, which RN\n * never threads into other color props. The color path must DROP these (omit\n * the key) rather than leak the keyword. NOTE: `transparent` is NOT here — it\n * is a real color that {@link cssColorToString} / {@link normalizeColorString}\n * lower to `rgba(0, 0, 0, 0)`, which RN paints correctly.\n */\nconst CSS_WIDE_COLOR_KEYWORDS: ReadonlySet<string> = new Set([\n 'currentcolor',\n 'inherit',\n 'initial',\n 'unset',\n 'revert',\n 'revert-layer',\n])\n\n/**\n * Modern CSS color functions RN's native view manager can't paint —\n * everything else (hex, `rgb()`/`rgba()`, `hsl()`/`hsla()`, named colors,\n * `transparent`) RN reads directly and must pass through untouched. The\n * CSS-wide cascade keywords (`currentColor`, `inherit`, …) are NOT readable —\n * they have no RN equivalent and are dropped via {@link isCssWideColorKeyword}.\n * Custom `@theme` tokens reach the parser as `var(--color-x)` (only the default\n * palette is `theme(inline)`-d), so they flow through the unparsed-string path\n * where the typed {@link cssColorToString} never runs — this is the one place\n * that lowers their wide-gamut values to sRGB. `color-mix(` is in the list too,\n * but it takes the dedicated {@link resolveColorMix} path — culori's `rgb()`\n * parser can't read it.\n */\nconst RN_UNREADABLE_COLOR_PREFIXES: readonly string[] = ['oklch(', 'oklab(', 'lab(', 'lch(', 'color(', 'hwb(', 'color-mix(']\n\n/**\n * Lower a wide-gamut / modern CSS color STRING (`oklch(…)`, `lab(…)`,\n * `color(display-p3 …)`, `color-mix(…)`) to an sRGB hex/rgba string RN can\n * paint. Returns `null` for anything RN already understands (hex, rgb, hsl,\n * named) so the caller keeps the original text — only the unrepresentable\n * forms convert. `color-mix()` is resolved via culori's interpolator; when it\n * (or any other modern form) can't resolve, returns null so the caller DROPS\n * the value rather than leaking the raw, RN-unreadable string.\n * Mirrors {@link cssColorToString}'s culori lowering for the string path.\n * @param text Resolved CSS color text (post theme-var substitution).\n * @returns sRGB color string, or `null` when no conversion is needed/possible.\n */\nexport function normalizeColorString(text: string): string | null {\n const trimmed = text.trim()\n const lower = trimmed.toLowerCase()\n if (!RN_UNREADABLE_COLOR_PREFIXES.some((prefix) => lower.startsWith(prefix))) return null\n if (lower.startsWith('color-mix(')) return resolveColorMix(trimmed)\n const parsed = culoriRgb(text)\n if (!parsed || ![parsed.r, parsed.g, parsed.b].every((v) => typeof v === 'number' && Number.isFinite(v))) return null\n const alpha = typeof parsed.alpha === 'number' ? parsed.alpha : 1\n return rgbIntsToString(clampByte(parsed.r * 255), clampByte(parsed.g * 255), clampByte(parsed.b * 255), alpha)\n}\n\n/**\n * Whether a resolved color STRING is a CSS-wide cascade keyword\n * (`currentColor`, `inherit`, `initial`, `unset`, `revert`, `revert-layer`)\n * with no React Native equivalent. RN has no color cascade, so the color path\n * must DROP (omit the key) when this is true rather than emit the keyword —\n * RN would otherwise receive an invalid color string and render nothing.\n * `transparent` is NOT a cascade keyword: it is a concrete color the converters\n * lower to `rgba(0, 0, 0, 0)`, so it returns false here and resolves normally.\n * @param text Resolved color text (post theme-var substitution / typed-color stringification).\n * @returns True when the value is an RN-unrepresentable CSS-wide keyword.\n */\nexport function isCssWideColorKeyword(text: string): boolean {\n return CSS_WIDE_COLOR_KEYWORDS.has(text.trim().toLowerCase())\n}\n\n/**\n * Convert a lightningcss `CssColor` to an RN-safe color string. RGB\n * passes through unchanged. LAB / LCH / OKLAB / OKLCH / `color(xyz-…)`\n * forms go through culori to reach sRGB — RN's native view manager only\n * understands sRGB-family strings. SystemColor keywords (`'background'`,\n * `'canvas'`, …) pass through untouched; they have no RN analog and the\n * runtime ignores unknown color strings gracefully.\n * @param color Typed color value.\n * @returns Color string RN accepts.\n */\nexport function cssColorToString(color: CssColor): string {\n if (typeof color === 'string') return color\n switch (color.type) {\n case 'rgb': {\n return rgbIntsToString(color.r, color.g, color.b, color.alpha)\n }\n case 'lab':\n case 'lch':\n case 'oklab':\n case 'oklch': {\n return labFamilyToHex(color)\n }\n case 'srgb': {\n return floatRgbToString(color.r, color.g, color.b, color.alpha)\n }\n case 'srgb-linear': {\n return wideGamutToHex('lrgb', color.r, color.g, color.b, color.alpha)\n }\n case 'display-p3': {\n return wideGamutToHex('p3', color.r, color.g, color.b, color.alpha)\n }\n case 'a98-rgb': {\n return wideGamutToHex('a98', color.r, color.g, color.b, color.alpha)\n }\n case 'prophoto-rgb': {\n return wideGamutToHex('prophoto', color.r, color.g, color.b, color.alpha)\n }\n case 'rec2020': {\n return wideGamutToHex('rec2020', color.r, color.g, color.b, color.alpha)\n }\n case 'xyz-d50':\n case 'xyz-d65': {\n return xyzToHex(color)\n }\n case 'currentcolor': {\n return 'currentColor'\n }\n case 'light-dark': {\n // `light-dark(L, D)` is a RUNTIME CSS function — the browser picks the\n // branch from the element's `color-scheme`. rnwind has no runtime CSS\n // evaluation, and the active scheme is NOT threaded into this typed\n // converter (it takes a bare `CssColor`, and every one of its ~15 call\n // sites — border / shorthand / gradient / declaration dispatchers — calls\n // it without a scheme). Scheme resolution instead happens UPSTREAM, at the\n // CSS-block walk (`@custom-variant` + `.dark {}` selectors in\n // theme-vars.ts), which compiles a separate atom + var table per scheme.\n // So the `.light` branch is the correct compile-time default here; the\n // dark value is carried by the scheme-specific atom, not by this function.\n return cssColorToString(color.light)\n }\n default: {\n return 'transparent'\n }\n }\n}\n"],"names":["formatHex","culoriRgb","interpolate"],"mappings":"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"}
@@ -1,14 +1,29 @@
1
1
  import type { CssColor } from 'lightningcss';
2
2
  /**
3
3
  * Lower a wide-gamut / modern CSS color STRING (`oklch(…)`, `lab(…)`,
4
- * `color(display-p3 …)`, …) to an sRGB hex/rgba string RN can paint. Returns
5
- * `null` for anything RN already understands (hex, rgb, hsl, named) so the
6
- * caller keeps the original text — only the unrepresentable forms convert.
4
+ * `color(display-p3 …)`, `color-mix(…)`) to an sRGB hex/rgba string RN can
5
+ * paint. Returns `null` for anything RN already understands (hex, rgb, hsl,
6
+ * named) so the caller keeps the original text — only the unrepresentable
7
+ * forms convert. `color-mix()` is resolved via culori's interpolator; when it
8
+ * (or any other modern form) can't resolve, returns null so the caller DROPS
9
+ * the value rather than leaking the raw, RN-unreadable string.
7
10
  * Mirrors {@link cssColorToString}'s culori lowering for the string path.
8
11
  * @param text Resolved CSS color text (post theme-var substitution).
9
12
  * @returns sRGB color string, or `null` when no conversion is needed/possible.
10
13
  */
11
14
  export declare function normalizeColorString(text: string): string | null;
15
+ /**
16
+ * Whether a resolved color STRING is a CSS-wide cascade keyword
17
+ * (`currentColor`, `inherit`, `initial`, `unset`, `revert`, `revert-layer`)
18
+ * with no React Native equivalent. RN has no color cascade, so the color path
19
+ * must DROP (omit the key) when this is true rather than emit the keyword —
20
+ * RN would otherwise receive an invalid color string and render nothing.
21
+ * `transparent` is NOT a cascade keyword: it is a concrete color the converters
22
+ * lower to `rgba(0, 0, 0, 0)`, so it returns false here and resolves normally.
23
+ * @param text Resolved color text (post theme-var substitution / typed-color stringification).
24
+ * @returns True when the value is an RN-unrepresentable CSS-wide keyword.
25
+ */
26
+ export declare function isCssWideColorKeyword(text: string): boolean;
12
27
  /**
13
28
  * Convert a lightningcss `CssColor` to an RN-safe color string. RGB
14
29
  * passes through unchanged. LAB / LCH / OKLAB / OKLCH / `color(xyz-…)`