@cssxio/react-native 0.3.4 → 0.5.1

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.
@@ -1,5 +1,111 @@
1
- // src/index.ts
2
- import { compileStyleRecords, describeUtilityRecipe, parseTheme } from "@cssxio/compiler";
1
+ // src/create.ts
2
+ import { compileStyleRecords, parseTheme } from "@cssxio/compiler";
3
+
4
+ // src/compile-candidates.ts
5
+ import { describeUtilityRecipe } from "@cssxio/compiler";
6
+
7
+ // src/oklch-to-srgb-hex.ts
8
+ function oklchToSrgbHex(value) {
9
+ const match = /^oklch\(([\d.]+)%(?:\s|_)+([\d.]+)(?:\s|_)+([\d.]+)\)$/.exec(value);
10
+ if (!match) {
11
+ return null;
12
+ }
13
+ const lightness = Number(match[1]) / 100;
14
+ const chroma = Number(match[2]);
15
+ const hue = Number(match[3]) * Math.PI / 180;
16
+ const a = chroma * Math.cos(hue);
17
+ const b = chroma * Math.sin(hue);
18
+ const l = (lightness + 0.3963377774 * a + 0.2158037574 * b) ** 3;
19
+ const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;
20
+ const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;
21
+ const channels = [
22
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
23
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
24
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
25
+ ];
26
+ return `#${channels.map((channel) => {
27
+ const bounded = Math.max(0, Math.min(1, channel));
28
+ const srgb = bounded <= 31308e-7 ? 12.92 * bounded : 1.055 * bounded ** (1 / 2.4) - 0.055;
29
+ return Math.round(srgb * 255).toString(16).padStart(2, "0");
30
+ }).join("")}`;
31
+ }
32
+
33
+ // src/native-values.ts
34
+ function nativeValue(value, candidate) {
35
+ const important = value.endsWith(" !important") ? value.slice(0, -11) : value;
36
+ const calculation = /^calc\((-?[\d.]+)rem \* (-?[\d.]+)\)$/.exec(important);
37
+ if (calculation) {
38
+ return Number(calculation[1]) * 16 * Number(calculation[2]);
39
+ }
40
+ const rem = /^(-?[\d.]+)rem$/.exec(important);
41
+ if (rem) {
42
+ return Number(rem[1]) * 16;
43
+ }
44
+ const pixels = /^(-?[\d.]+)px$/.exec(important);
45
+ if (pixels) {
46
+ return Number(pixels[1]);
47
+ }
48
+ if (/^-?[\d.]+$/.test(important)) {
49
+ return Number(important);
50
+ }
51
+ if (/^(?:#|rgb|rgba|hsl|hsla|hwb|transparent|black|white)/.test(important) || important.endsWith("%")) {
52
+ return important;
53
+ }
54
+ const oklch = oklchToSrgbHex(important);
55
+ if (oklch) {
56
+ return oklch;
57
+ }
58
+ if (important.startsWith("var(") || important.startsWith("color-mix(") || important.startsWith("oklch(")) {
59
+ throw new Error(`CSSX React Native requires "${candidate}" to resolve to a native color or value at build time.`);
60
+ }
61
+ return important;
62
+ }
63
+
64
+ // src/append-custom-transform.ts
65
+ function appendCustomTransform(style, property, value, candidate) {
66
+ const transformProperty = {
67
+ "--cssx-rotate": "rotate",
68
+ "--cssx-scale-x": "scaleX",
69
+ "--cssx-scale-y": "scaleY",
70
+ "--cssx-translate-x": "translateX",
71
+ "--cssx-translate-y": "translateY"
72
+ };
73
+ const nativeProperty = transformProperty[property];
74
+ if (!nativeProperty) {
75
+ return false;
76
+ }
77
+ style.transform = [
78
+ ...style.transform ?? [],
79
+ { [nativeProperty]: nativeValue(value, candidate) }
80
+ ];
81
+ return true;
82
+ }
83
+
84
+ // src/append-transform.ts
85
+ function appendTransform(style, property, value) {
86
+ if ((property === "translate" || property === "rotate" || property === "scale") && value.includes("var(")) {
87
+ return true;
88
+ }
89
+ let transforms;
90
+ if (property === "translate") {
91
+ const x = value.split(" ", 1).join("");
92
+ const [y = "0"] = value.split(" ").slice(1);
93
+ transforms = [{ translateX: nativeValue(x, "translate") }, { translateY: nativeValue(y, "translate") }];
94
+ } else if (property === "rotate") {
95
+ transforms = [{ rotate: value }];
96
+ } else if (property === "scale") {
97
+ const x = value.split(" ", 1).join("");
98
+ const [y = x] = value.split(" ").slice(1);
99
+ transforms = [{ scaleX: Number(x) }, { scaleY: Number(y) }];
100
+ }
101
+ if (!transforms) {
102
+ return false;
103
+ }
104
+ style.transform = [...style.transform ?? [], ...transforms];
105
+ return true;
106
+ }
107
+
108
+ // src/native-properties.ts
3
109
  var propertyNames = {
4
110
  "align-content": "alignContent",
5
111
  "align-items": "alignItems",
@@ -72,89 +178,8 @@ var logicalProperties = {
72
178
  "padding-block": ["paddingTop", "paddingBottom"],
73
179
  "padding-inline": ["paddingLeft", "paddingRight"]
74
180
  };
75
- function create(styles, options = {}) {
76
- const records = compileStyleRecords(styles, { theme: options.theme });
77
- const theme = parseTheme(options.theme);
78
- return Object.fromEntries(
79
- Object.entries(records.candidates).map(([name, candidates]) => [
80
- name,
81
- { $$cssx: 3, style: compileCandidates(candidates, theme, options.platform) }
82
- ])
83
- );
84
- }
85
- function props(...inputs) {
86
- const styles = [];
87
- visitStyles(inputs, styles);
88
- return { style: mergeStyles(styles) };
89
- }
90
- function sx(...inputs) {
91
- const styles = [];
92
- for (const input of inputs) {
93
- if (typeof input === "string") {
94
- styles.push(create({ value: input }).value.style);
95
- } else {
96
- visitStyles([input], styles);
97
- }
98
- }
99
- return mergeStyles(styles);
100
- }
101
- function visitStyles(inputs, output) {
102
- for (const input of inputs) {
103
- if (!input) {
104
- continue;
105
- }
106
- if (isNativeStyleArray(input)) {
107
- visitStyles(input, output);
108
- continue;
109
- }
110
- if (typeof input !== "object" || input.$$cssx !== 3) {
111
- throw new Error("cssx.props() received an object that was not compiled by CSSX for React Native.");
112
- }
113
- output.push(input.style);
114
- }
115
- }
116
- function isNativeStyleArray(input) {
117
- return Array.isArray(input);
118
- }
119
- function mergeStyles(styles) {
120
- const output = {};
121
- for (const style of styles) {
122
- for (const [property, value] of Object.entries(style)) {
123
- if (property === "transform" && Array.isArray(output.transform) && Array.isArray(value)) {
124
- output.transform = [...output.transform, ...value];
125
- } else {
126
- output[property] = value;
127
- }
128
- }
129
- }
130
- return output;
131
- }
132
- function compileCandidates(candidates, theme, platform) {
133
- const style = {};
134
- for (const source of candidates) {
135
- const candidate = platformCandidate(source, platform);
136
- if (candidate === null) {
137
- continue;
138
- }
139
- const recipe = describeUtilityRecipe(candidate, theme);
140
- for (const atom of recipe.atoms) {
141
- for (const declaration of atom) {
142
- appendDeclaration(style, candidate, declaration);
143
- }
144
- }
145
- }
146
- return style;
147
- }
148
- function platformCandidate(source, platform) {
149
- const match = /^(ios|android):(.*)$/.exec(source);
150
- if (match) {
151
- return match[1] === platform ? match[2] : null;
152
- }
153
- if (!source.startsWith("[") && source.includes(":")) {
154
- throw new Error(`CSSX React Native cannot represent the variant in "${source}".`);
155
- }
156
- return source;
157
- }
181
+
182
+ // src/append-declaration.ts
158
183
  function appendDeclaration(style, candidate, declaration) {
159
184
  if (declaration.selectorSuffix || declaration.atRule) {
160
185
  throw new Error(`CSSX React Native cannot represent browser-only utility "${candidate}".`);
@@ -186,104 +211,105 @@ function appendDeclaration(style, candidate, declaration) {
186
211
  if (property === "overflow" && value !== "visible" && value !== "hidden") {
187
212
  throw new Error(`CSSX React Native cannot represent overflow value "${String(value)}" from "${candidate}".`);
188
213
  }
189
- if (property === "flex" && typeof value === "string") {
190
- style[property] = Number.parseFloat(value);
191
- return;
192
- }
193
- style[property] = value;
214
+ style[property] = property === "flex" && typeof value === "string" ? Number.parseFloat(value) : value;
194
215
  }
195
- function appendTransform(style, property, value) {
196
- if ((property === "translate" || property === "rotate" || property === "scale") && value.includes("var(")) {
197
- return true;
198
- }
199
- let transforms;
200
- if (property === "translate") {
201
- const [x = "0", y = "0"] = value.split(" ");
202
- transforms = [{ translateX: nativeValue(x, "translate") }, { translateY: nativeValue(y, "translate") }];
203
- } else if (property === "rotate") {
204
- transforms = [{ rotate: value }];
205
- } else if (property === "scale") {
206
- const [x = "1", y = x] = value.split(" ");
207
- transforms = [{ scaleX: Number(x) }, { scaleY: Number(y) }];
216
+
217
+ // src/platform-candidate.ts
218
+ function platformCandidate(source, platform) {
219
+ const match = /^(ios|android):(.*)$/.exec(source);
220
+ if (match) {
221
+ return match[1] === platform ? match[2] : null;
208
222
  }
209
- if (!transforms) {
210
- return false;
223
+ if (!source.startsWith("[") && source.includes(":")) {
224
+ throw new Error(`CSSX React Native cannot represent the variant in "${source}".`);
211
225
  }
212
- style.transform = [...style.transform ?? [], ...transforms];
213
- return true;
226
+ return source;
214
227
  }
215
- function appendCustomTransform(style, property, value, candidate) {
216
- const transformProperty = {
217
- "--cssx-rotate": "rotate",
218
- "--cssx-scale-x": "scaleX",
219
- "--cssx-scale-y": "scaleY",
220
- "--cssx-translate-x": "translateX",
221
- "--cssx-translate-y": "translateY"
222
- };
223
- const nativeProperty = transformProperty[property];
224
- if (!nativeProperty) {
225
- return false;
228
+
229
+ // src/compile-candidates.ts
230
+ function compileCandidates(candidates, theme, platform) {
231
+ const style = {};
232
+ for (const source of candidates) {
233
+ const candidate = platformCandidate(source, platform);
234
+ if (candidate === null) {
235
+ continue;
236
+ }
237
+ for (const atom of describeUtilityRecipe(candidate, theme).atoms) {
238
+ for (const declaration of atom) {
239
+ appendDeclaration(style, candidate, declaration);
240
+ }
241
+ }
226
242
  }
227
- const native = nativeValue(value, candidate);
228
- style.transform = [
229
- ...style.transform ?? [],
230
- { [nativeProperty]: native }
231
- ];
232
- return true;
243
+ return style;
233
244
  }
234
- function nativeValue(value, candidate) {
235
- const important = value.endsWith(" !important") ? value.slice(0, -11) : value;
236
- const calculation = /^calc\((-?[\d.]+)rem \* (-?[\d.]+)\)$/.exec(important);
237
- if (calculation) {
238
- return Number(calculation[1]) * 16 * Number(calculation[2]);
239
- }
240
- const rem = /^(-?[\d.]+)rem$/.exec(important);
241
- if (rem) {
242
- return Number(rem[1]) * 16;
243
- }
244
- const pixels = /^(-?[\d.]+)px$/.exec(important);
245
- if (pixels) {
246
- return Number(pixels[1]);
247
- }
248
- if (/^-?[\d.]+$/.test(important)) {
249
- return Number(important);
250
- }
251
- if (/^(?:#|rgb|rgba|hsl|hsla|hwb|transparent|black|white)/.test(important) || important.endsWith("%")) {
252
- return important;
253
- }
254
- const oklch = oklchToSrgbHex(important);
255
- if (oklch) {
256
- return oklch;
245
+
246
+ // src/create.ts
247
+ function create(styles, options = {}) {
248
+ const records = compileStyleRecords(styles, { theme: options.theme });
249
+ const theme = parseTheme(options.theme);
250
+ return Object.fromEntries(
251
+ Object.entries(records.candidates).map(([name, candidates]) => [
252
+ name,
253
+ { $$cssx: 3, style: compileCandidates(candidates, theme, options.platform) }
254
+ ])
255
+ );
256
+ }
257
+
258
+ // src/merge-styles.ts
259
+ function mergeStyles(styles) {
260
+ const output = {};
261
+ for (const style of styles) {
262
+ for (const [property, value] of Object.entries(style)) {
263
+ if (property === "transform" && Array.isArray(output.transform) && Array.isArray(value)) {
264
+ output.transform = [...output.transform, ...value];
265
+ } else {
266
+ output[property] = value;
267
+ }
268
+ }
257
269
  }
258
- if (important.startsWith("var(") || important.startsWith("color-mix(") || important.startsWith("oklch(")) {
259
- throw new Error(`CSSX React Native requires "${candidate}" to resolve to a native color or value at build time.`);
270
+ return output;
271
+ }
272
+
273
+ // src/is-native-style-array.ts
274
+ function isNativeStyleArray(input) {
275
+ return Array.isArray(input);
276
+ }
277
+
278
+ // src/visit-styles.ts
279
+ function visitStyles(inputs, output) {
280
+ for (const input of inputs) {
281
+ if (!input) {
282
+ continue;
283
+ }
284
+ if (isNativeStyleArray(input)) {
285
+ visitStyles(input, output);
286
+ continue;
287
+ }
288
+ if (typeof input !== "object" || input.$$cssx !== 3) {
289
+ throw new Error("cssx.props() received an object that was not compiled by CSSX for React Native.");
290
+ }
291
+ output.push(input.style);
260
292
  }
261
- return important;
262
293
  }
263
- function oklchToSrgbHex(value) {
264
- const match = /^oklch\(([\d.]+)%(?:\s|_)+([\d.]+)(?:\s|_)+([\d.]+)\)$/.exec(value);
265
- if (!match) {
266
- return null;
294
+
295
+ // src/props.ts
296
+ function props(...inputs) {
297
+ const styles = [];
298
+ visitStyles(inputs, styles);
299
+ return { style: mergeStyles(styles) };
300
+ }
301
+
302
+ // src/sx.ts
303
+ function sx(...inputs) {
304
+ const styles = [];
305
+ for (const input of inputs) {
306
+ if (typeof input === "string") {
307
+ styles.push(create({ value: input }).value.style);
308
+ } else {
309
+ visitStyles([input], styles);
310
+ }
267
311
  }
268
- const lightness = Number(match[1]) / 100;
269
- const chroma = Number(match[2]);
270
- const hue = Number(match[3]) * Math.PI / 180;
271
- const a = chroma * Math.cos(hue);
272
- const b = chroma * Math.sin(hue);
273
- const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;
274
- const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;
275
- const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;
276
- const channels = [
277
- 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
278
- -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
279
- -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
280
- ];
281
- const hex = channels.map((channel) => {
282
- const bounded = Math.max(0, Math.min(1, channel));
283
- const srgb = bounded <= 31308e-7 ? 12.92 * bounded : 1.055 * bounded ** (1 / 2.4) - 0.055;
284
- return Math.round(srgb * 255).toString(16).padStart(2, "0");
285
- }).join("");
286
- return `#${hex}`;
312
+ return mergeStyles(styles);
287
313
  }
288
314
 
289
315
  export {