@oxyhq/bloom 0.7.1 → 0.7.3

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 (49) hide show
  1. package/lib/commonjs/portal/index.js +18 -1
  2. package/lib/commonjs/portal/index.js.map +1 -1
  3. package/lib/commonjs/theme/BloomThemeProvider.js +21 -1
  4. package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
  5. package/lib/commonjs/theme/apply-dark-class.js +6 -3
  6. package/lib/commonjs/theme/apply-dark-class.js.map +1 -1
  7. package/lib/commonjs/theme/native-root-vars.js +6 -1
  8. package/lib/commonjs/theme/native-root-vars.js.map +1 -1
  9. package/lib/commonjs/theme/preset-vars.js +67 -1
  10. package/lib/commonjs/theme/preset-vars.js.map +1 -1
  11. package/lib/module/portal/index.js +18 -1
  12. package/lib/module/portal/index.js.map +1 -1
  13. package/lib/module/theme/BloomThemeProvider.js +21 -1
  14. package/lib/module/theme/BloomThemeProvider.js.map +1 -1
  15. package/lib/module/theme/apply-dark-class.js +6 -3
  16. package/lib/module/theme/apply-dark-class.js.map +1 -1
  17. package/lib/module/theme/native-root-vars.js +6 -1
  18. package/lib/module/theme/native-root-vars.js.map +1 -1
  19. package/lib/module/theme/preset-vars.js +66 -1
  20. package/lib/module/theme/preset-vars.js.map +1 -1
  21. package/lib/typescript/commonjs/portal/index.d.ts +10 -0
  22. package/lib/typescript/commonjs/portal/index.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +23 -0
  24. package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
  25. package/lib/typescript/commonjs/theme/apply-dark-class.d.ts +6 -3
  26. package/lib/typescript/commonjs/theme/apply-dark-class.d.ts.map +1 -1
  27. package/lib/typescript/commonjs/theme/native-root-vars.d.ts +6 -1
  28. package/lib/typescript/commonjs/theme/native-root-vars.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/theme/preset-vars.d.ts +35 -2
  30. package/lib/typescript/commonjs/theme/preset-vars.d.ts.map +1 -1
  31. package/lib/typescript/module/portal/index.d.ts +10 -0
  32. package/lib/typescript/module/portal/index.d.ts.map +1 -1
  33. package/lib/typescript/module/theme/BloomThemeProvider.d.ts +23 -0
  34. package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
  35. package/lib/typescript/module/theme/apply-dark-class.d.ts +6 -3
  36. package/lib/typescript/module/theme/apply-dark-class.d.ts.map +1 -1
  37. package/lib/typescript/module/theme/native-root-vars.d.ts +6 -1
  38. package/lib/typescript/module/theme/native-root-vars.d.ts.map +1 -1
  39. package/lib/typescript/module/theme/preset-vars.d.ts +35 -2
  40. package/lib/typescript/module/theme/preset-vars.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/__tests__/native-root-vars.test.ts +4 -2
  43. package/src/__tests__/preset-vars.test.ts +45 -4
  44. package/src/portal/index.tsx +26 -1
  45. package/src/react-native-css.d.ts +3 -2
  46. package/src/theme/BloomThemeProvider.tsx +30 -1
  47. package/src/theme/apply-dark-class.ts +6 -3
  48. package/src/theme/native-root-vars.ts +6 -1
  49. package/src/theme/preset-vars.ts +84 -3
@@ -9,6 +9,80 @@ function extractSat(hslVar: string): number {
9
9
  return parseInt(hslVar.split(' ')[1] ?? '0', 10);
10
10
  }
11
11
 
12
+ /**
13
+ * Convert a shadcn-style HSL triple (`'H S% L%'`, optionally with an alpha tail
14
+ * `'H S% L% / A'`) into an sRGB `rgb(...)` string.
15
+ *
16
+ * Why rgb and not hsl (the native alpha-utility bug this fixes)
17
+ * -------------------------------------------------------------
18
+ * Tailwind v4 compiles an alpha-on-theme-color utility (`bg-primary/10`) into a
19
+ * `color-mix(... var(--color-primary) 10%, transparent)` declaration. On native,
20
+ * react-native-css resolves that `color-mix` at runtime via `colorjs.io/fn`, but
21
+ * its `color-mix` implementation registers ONLY the `sRGB`, `P3`, and `OKLab`
22
+ * color spaces — never `HSL`. So if `--color-primary` resolves to an `hsl(...)`
23
+ * string, `parse('hsl(...)')` throws, the mix is swallowed, and the utility
24
+ * silently produces no color. Emitting the resolved var as `rgb(...)` (a space
25
+ * colorjs.io always has registered) makes the alpha utilities resolve on native,
26
+ * matching web. Full (non-alpha) utilities already worked because React Native's
27
+ * native color parser handles `hsl()` directly; only `color-mix` was affected.
28
+ *
29
+ * Output is space-separated channels (`rgb(31 153 239)`), the modern CSS syntax
30
+ * parsed by both `colorjs.io/fn` (with only sRGB/P3/OKLab registered) and
31
+ * react-native-web / browsers. An alpha tail emits `rgb(r g b / a)`, likewise
32
+ * parsed by both.
33
+ *
34
+ * Pure function — standard HSL→sRGB conversion, channels rounded to integers.
35
+ * Tolerates a `deg` suffix on the hue and `%` suffixes on saturation/lightness.
36
+ */
37
+ export function hslTripletToRgb(triplet: string): string {
38
+ const [colorPart, alphaPart] = triplet.split('/').map((part) => part.trim());
39
+ const channels = (colorPart ?? '').split(/\s+/).filter(Boolean);
40
+
41
+ const hue = parseFloat((channels[0] ?? '0').replace(/deg$/i, ''));
42
+ const sat = parseFloat((channels[1] ?? '0').replace('%', '')) / 100;
43
+ const light = parseFloat((channels[2] ?? '0').replace('%', '')) / 100;
44
+
45
+ const h = Number.isFinite(hue) ? hue : 0;
46
+ const s = Number.isFinite(sat) ? sat : 0;
47
+ const l = Number.isFinite(light) ? light : 0;
48
+
49
+ const chroma = (1 - Math.abs(2 * l - 1)) * s;
50
+ const huePrime = ((((h % 360) + 360) % 360) / 60);
51
+ const second = chroma * (1 - Math.abs((huePrime % 2) - 1));
52
+
53
+ let r = 0;
54
+ let g = 0;
55
+ let b = 0;
56
+ if (huePrime < 1) {
57
+ [r, g, b] = [chroma, second, 0];
58
+ } else if (huePrime < 2) {
59
+ [r, g, b] = [second, chroma, 0];
60
+ } else if (huePrime < 3) {
61
+ [r, g, b] = [0, chroma, second];
62
+ } else if (huePrime < 4) {
63
+ [r, g, b] = [0, second, chroma];
64
+ } else if (huePrime < 5) {
65
+ [r, g, b] = [second, 0, chroma];
66
+ } else {
67
+ [r, g, b] = [chroma, 0, second];
68
+ }
69
+
70
+ const match = l - chroma / 2;
71
+ const red = Math.round((r + match) * 255);
72
+ const green = Math.round((g + match) * 255);
73
+ const blue = Math.round((b + match) * 255);
74
+
75
+ if (alphaPart !== undefined && alphaPart !== '') {
76
+ const alpha = alphaPart.endsWith('%')
77
+ ? parseFloat(alphaPart) / 100
78
+ : parseFloat(alphaPart);
79
+ const safeAlpha = Number.isFinite(alpha) ? alpha : 1;
80
+ return `rgb(${red} ${green} ${blue} / ${safeAlpha})`;
81
+ }
82
+
83
+ return `rgb(${red} ${green} ${blue})`;
84
+ }
85
+
12
86
  const RESOLVED_COLOR_MAP: Record<string, string> = {
13
87
  '--background': '--color-background',
14
88
  '--foreground': '--color-foreground',
@@ -34,11 +108,18 @@ const RESOLVED_COLOR_MAP: Record<string, string> = {
34
108
 
35
109
  export interface PresetVarsOptions {
36
110
  /**
37
- * Also emit Tailwind v4 resolved `--color-*` vars (wrapped in `hsl(...)`)
111
+ * Also emit Tailwind v4 resolved `--color-*` vars (as sRGB `rgb(...)` strings)
38
112
  * alongside the raw HSL triples. Needed when scoping a subtree where
39
113
  * Tailwind's `@theme` block has already precomputed `--color-*` at `:root`,
40
114
  * so overriding `--background` alone wouldn't cascade to `bg-background`.
41
- * Default `false`.
115
+ *
116
+ * The resolved vars are emitted as `rgb(...)` rather than `hsl(...)` so the
117
+ * alpha-on-theme-color utilities (`bg-primary/10`, `text-foreground/50`)
118
+ * resolve on native: Tailwind compiles those to a runtime `color-mix(...)` that
119
+ * react-native-css evaluates via `colorjs.io/fn`, which only registers the
120
+ * sRGB/P3/OKLab spaces (not HSL) — so an `hsl(...)` var would throw and the
121
+ * utility would silently render no color. See `hslTripletToRgb`. Default
122
+ * `false`.
42
123
  */
43
124
  includeResolvedColorVars?: boolean;
44
125
  }
@@ -92,7 +173,7 @@ export function getPresetVars(
92
173
  const resolved: PresetTokens = { ...extended };
93
174
  for (const [rawKey, colorKey] of Object.entries(RESOLVED_COLOR_MAP)) {
94
175
  const value = extended[rawKey];
95
- if (value) resolved[colorKey] = `hsl(${value})`;
176
+ if (value) resolved[colorKey] = hslTripletToRgb(value);
96
177
  }
97
178
  return resolved;
98
179
  }