elit 3.5.6 → 3.5.7
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.
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/desktop/build.rs +83 -0
- package/desktop/icon.rs +106 -0
- package/desktop/lib.rs +2 -0
- package/desktop/main.rs +235 -0
- package/desktop/native_main.rs +128 -0
- package/desktop/native_renderer/action_widgets.rs +184 -0
- package/desktop/native_renderer/app_models.rs +171 -0
- package/desktop/native_renderer/app_runtime.rs +140 -0
- package/desktop/native_renderer/container_rendering.rs +610 -0
- package/desktop/native_renderer/content_widgets.rs +634 -0
- package/desktop/native_renderer/css_models.rs +371 -0
- package/desktop/native_renderer/embedded_surfaces.rs +414 -0
- package/desktop/native_renderer/form_controls.rs +516 -0
- package/desktop/native_renderer/interaction_dispatch.rs +89 -0
- package/desktop/native_renderer/runtime_support.rs +135 -0
- package/desktop/native_renderer/utilities.rs +495 -0
- package/desktop/native_renderer/vector_drawing.rs +491 -0
- package/desktop/native_renderer.rs +4122 -0
- package/desktop/runtime/external.rs +422 -0
- package/desktop/runtime/mod.rs +67 -0
- package/desktop/runtime/quickjs.rs +106 -0
- package/desktop/window.rs +383 -0
- package/package.json +6 -3
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/cli.d.mts +0 -81
- package/dist/config.d.mts +0 -254
- package/dist/coverage.d.mts +0 -85
- package/dist/database.d.mts +0 -52
- package/dist/desktop.d.mts +0 -68
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -208
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -169
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -13
- package/dist/mime-types.d.mts +0 -48
- package/dist/native.d.mts +0 -136
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -49
- package/dist/runtime.d.mts +0 -97
- package/dist/server-D0Dp4R5z.d.mts +0 -449
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -117
- package/dist/style.d.mts +0 -232
- package/dist/test-reporter.d.mts +0 -77
- package/dist/test-runtime.d.mts +0 -122
- package/dist/test.d.mts +0 -39
- package/dist/types.d.mts +0 -586
- package/dist/universal.d.mts +0 -21
- package/dist/ws.d.mts +0 -200
- package/dist/wss.d.mts +0 -108
- package/src/build.ts +0 -362
- package/src/chokidar.ts +0 -427
- package/src/cli.ts +0 -1162
- package/src/config.ts +0 -509
- package/src/coverage.ts +0 -1479
- package/src/database.ts +0 -1410
- package/src/desktop-auto-render.ts +0 -317
- package/src/desktop-cli.ts +0 -1533
- package/src/desktop.ts +0 -99
- package/src/dev-build.ts +0 -340
- package/src/dom.ts +0 -901
- package/src/el.ts +0 -183
- package/src/fs.ts +0 -609
- package/src/hmr.ts +0 -149
- package/src/http.ts +0 -856
- package/src/https.ts +0 -411
- package/src/index.ts +0 -16
- package/src/mime-types.ts +0 -222
- package/src/mobile-cli.ts +0 -2313
- package/src/native-background.ts +0 -444
- package/src/native-border.ts +0 -343
- package/src/native-canvas.ts +0 -260
- package/src/native-cli.ts +0 -414
- package/src/native-color.ts +0 -904
- package/src/native-estimation.ts +0 -194
- package/src/native-grid.ts +0 -590
- package/src/native-interaction.ts +0 -1289
- package/src/native-layout.ts +0 -568
- package/src/native-link.ts +0 -76
- package/src/native-render-support.ts +0 -361
- package/src/native-spacing.ts +0 -231
- package/src/native-state.ts +0 -318
- package/src/native-strings.ts +0 -46
- package/src/native-transform.ts +0 -120
- package/src/native-types.ts +0 -439
- package/src/native-typography.ts +0 -254
- package/src/native-units.ts +0 -441
- package/src/native-vector.ts +0 -910
- package/src/native.ts +0 -5606
- package/src/path.ts +0 -493
- package/src/pm-cli.ts +0 -2498
- package/src/preview-build.ts +0 -294
- package/src/render-context.ts +0 -138
- package/src/router.ts +0 -260
- package/src/runtime.ts +0 -97
- package/src/server.ts +0 -2294
- package/src/state.ts +0 -556
- package/src/style.ts +0 -1790
- package/src/test-globals.d.ts +0 -184
- package/src/test-reporter.ts +0 -609
- package/src/test-runtime.ts +0 -1359
- package/src/test.ts +0 -368
- package/src/types.ts +0 -381
- package/src/universal.ts +0 -81
- package/src/wapk-cli.ts +0 -3213
- package/src/workspace-package.ts +0 -102
- package/src/ws.ts +0 -648
- package/src/wss.ts +0 -241
package/src/native-color.ts
DELETED
|
@@ -1,904 +0,0 @@
|
|
|
1
|
-
import { type NativeStyleResolveOptions } from './style';
|
|
2
|
-
import type { NativeColorValue, NativeGradientDirection, NativeGradientValue, NativeShadowValue, NativePropValue } from './native-types';
|
|
3
|
-
import { splitCssFunctionArguments, toScaledUnitNumber, getNativeStyleResolveOptions, formatFloat } from './native-units';
|
|
4
|
-
export const CSS_NAMED_COLORS: Record<string, NativeColorValue> = {
|
|
5
|
-
transparent: { red: 0, green: 0, blue: 0, alpha: 0 },
|
|
6
|
-
black: { red: 0, green: 0, blue: 0, alpha: 1 },
|
|
7
|
-
silver: { red: 192, green: 192, blue: 192, alpha: 1 },
|
|
8
|
-
gray: { red: 128, green: 128, blue: 128, alpha: 1 },
|
|
9
|
-
grey: { red: 128, green: 128, blue: 128, alpha: 1 },
|
|
10
|
-
white: { red: 255, green: 255, blue: 255, alpha: 1 },
|
|
11
|
-
maroon: { red: 128, green: 0, blue: 0, alpha: 1 },
|
|
12
|
-
red: { red: 255, green: 0, blue: 0, alpha: 1 },
|
|
13
|
-
purple: { red: 128, green: 0, blue: 128, alpha: 1 },
|
|
14
|
-
fuchsia: { red: 255, green: 0, blue: 255, alpha: 1 },
|
|
15
|
-
green: { red: 0, green: 128, blue: 0, alpha: 1 },
|
|
16
|
-
lime: { red: 0, green: 255, blue: 0, alpha: 1 },
|
|
17
|
-
olive: { red: 128, green: 128, blue: 0, alpha: 1 },
|
|
18
|
-
yellow: { red: 255, green: 255, blue: 0, alpha: 1 },
|
|
19
|
-
navy: { red: 0, green: 0, blue: 128, alpha: 1 },
|
|
20
|
-
blue: { red: 0, green: 0, blue: 255, alpha: 1 },
|
|
21
|
-
teal: { red: 0, green: 128, blue: 128, alpha: 1 },
|
|
22
|
-
aqua: { red: 0, green: 255, blue: 255, alpha: 1 },
|
|
23
|
-
orange: { red: 255, green: 165, blue: 0, alpha: 1 },
|
|
24
|
-
pink: { red: 255, green: 192, blue: 203, alpha: 1 },
|
|
25
|
-
brown: { red: 165, green: 42, blue: 42, alpha: 1 },
|
|
26
|
-
cyan: { red: 0, green: 255, blue: 255, alpha: 1 },
|
|
27
|
-
magenta: { red: 255, green: 0, blue: 255, alpha: 1 },
|
|
28
|
-
rebeccapurple: { red: 102, green: 51, blue: 153, alpha: 1 },
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
Object.assign(CSS_NAMED_COLORS, createNativeNamedColorMap({
|
|
32
|
-
aliceblue: '#f0f8ff',
|
|
33
|
-
antiquewhite: '#faebd7',
|
|
34
|
-
aqua: '#00ffff',
|
|
35
|
-
aquamarine: '#7fffd4',
|
|
36
|
-
azure: '#f0ffff',
|
|
37
|
-
beige: '#f5f5dc',
|
|
38
|
-
bisque: '#ffe4c4',
|
|
39
|
-
black: '#000000',
|
|
40
|
-
blanchedalmond: '#ffebcd',
|
|
41
|
-
blue: '#0000ff',
|
|
42
|
-
blueviolet: '#8a2be2',
|
|
43
|
-
brown: '#a52a2a',
|
|
44
|
-
burlywood: '#deb887',
|
|
45
|
-
cadetblue: '#5f9ea0',
|
|
46
|
-
chartreuse: '#7fff00',
|
|
47
|
-
chocolate: '#d2691e',
|
|
48
|
-
coral: '#ff7f50',
|
|
49
|
-
cornflowerblue: '#6495ed',
|
|
50
|
-
cornsilk: '#fff8dc',
|
|
51
|
-
crimson: '#dc143c',
|
|
52
|
-
cyan: '#00ffff',
|
|
53
|
-
darkblue: '#00008b',
|
|
54
|
-
darkcyan: '#008b8b',
|
|
55
|
-
darkgoldenrod: '#b8860b',
|
|
56
|
-
darkgray: '#a9a9a9',
|
|
57
|
-
darkgreen: '#006400',
|
|
58
|
-
darkgrey: '#a9a9a9',
|
|
59
|
-
darkkhaki: '#bdb76b',
|
|
60
|
-
darkmagenta: '#8b008b',
|
|
61
|
-
darkolivegreen: '#556b2f',
|
|
62
|
-
darkorange: '#ff8c00',
|
|
63
|
-
darkorchid: '#9932cc',
|
|
64
|
-
darkred: '#8b0000',
|
|
65
|
-
darksalmon: '#e9967a',
|
|
66
|
-
darkseagreen: '#8fbc8f',
|
|
67
|
-
darkslateblue: '#483d8b',
|
|
68
|
-
darkslategray: '#2f4f4f',
|
|
69
|
-
darkslategrey: '#2f4f4f',
|
|
70
|
-
darkturquoise: '#00ced1',
|
|
71
|
-
darkviolet: '#9400d3',
|
|
72
|
-
deeppink: '#ff1493',
|
|
73
|
-
deepskyblue: '#00bfff',
|
|
74
|
-
dimgray: '#696969',
|
|
75
|
-
dimgrey: '#696969',
|
|
76
|
-
dodgerblue: '#1e90ff',
|
|
77
|
-
firebrick: '#b22222',
|
|
78
|
-
floralwhite: '#fffaf0',
|
|
79
|
-
forestgreen: '#228b22',
|
|
80
|
-
fuchsia: '#ff00ff',
|
|
81
|
-
gainsboro: '#dcdcdc',
|
|
82
|
-
ghostwhite: '#f8f8ff',
|
|
83
|
-
gold: '#ffd700',
|
|
84
|
-
goldenrod: '#daa520',
|
|
85
|
-
gray: '#808080',
|
|
86
|
-
green: '#008000',
|
|
87
|
-
greenyellow: '#adff2f',
|
|
88
|
-
grey: '#808080',
|
|
89
|
-
honeydew: '#f0fff0',
|
|
90
|
-
hotpink: '#ff69b4',
|
|
91
|
-
indianred: '#cd5c5c',
|
|
92
|
-
indigo: '#4b0082',
|
|
93
|
-
ivory: '#fffff0',
|
|
94
|
-
khaki: '#f0e68c',
|
|
95
|
-
lavender: '#e6e6fa',
|
|
96
|
-
lavenderblush: '#fff0f5',
|
|
97
|
-
lawngreen: '#7cfc00',
|
|
98
|
-
lemonchiffon: '#fffacd',
|
|
99
|
-
lightblue: '#add8e6',
|
|
100
|
-
lightcoral: '#f08080',
|
|
101
|
-
lightcyan: '#e0ffff',
|
|
102
|
-
lightgoldenrodyellow: '#fafad2',
|
|
103
|
-
lightgray: '#d3d3d3',
|
|
104
|
-
lightgreen: '#90ee90',
|
|
105
|
-
lightgrey: '#d3d3d3',
|
|
106
|
-
lightpink: '#ffb6c1',
|
|
107
|
-
lightsalmon: '#ffa07a',
|
|
108
|
-
lightseagreen: '#20b2aa',
|
|
109
|
-
lightskyblue: '#87cefa',
|
|
110
|
-
lightslategray: '#778899',
|
|
111
|
-
lightslategrey: '#778899',
|
|
112
|
-
lightsteelblue: '#b0c4de',
|
|
113
|
-
lightyellow: '#ffffe0',
|
|
114
|
-
lime: '#00ff00',
|
|
115
|
-
limegreen: '#32cd32',
|
|
116
|
-
linen: '#faf0e6',
|
|
117
|
-
magenta: '#ff00ff',
|
|
118
|
-
maroon: '#800000',
|
|
119
|
-
mediumaquamarine: '#66cdaa',
|
|
120
|
-
mediumblue: '#0000cd',
|
|
121
|
-
mediumorchid: '#ba55d3',
|
|
122
|
-
mediumpurple: '#9370db',
|
|
123
|
-
mediumseagreen: '#3cb371',
|
|
124
|
-
mediumslateblue: '#7b68ee',
|
|
125
|
-
mediumspringgreen: '#00fa9a',
|
|
126
|
-
mediumturquoise: '#48d1cc',
|
|
127
|
-
mediumvioletred: '#c71585',
|
|
128
|
-
midnightblue: '#191970',
|
|
129
|
-
mintcream: '#f5fffa',
|
|
130
|
-
mistyrose: '#ffe4e1',
|
|
131
|
-
moccasin: '#ffe4b5',
|
|
132
|
-
navajowhite: '#ffdead',
|
|
133
|
-
navy: '#000080',
|
|
134
|
-
oldlace: '#fdf5e6',
|
|
135
|
-
olive: '#808000',
|
|
136
|
-
olivedrab: '#6b8e23',
|
|
137
|
-
orange: '#ffa500',
|
|
138
|
-
orangered: '#ff4500',
|
|
139
|
-
orchid: '#da70d6',
|
|
140
|
-
palegoldenrod: '#eee8aa',
|
|
141
|
-
palegreen: '#98fb98',
|
|
142
|
-
paleturquoise: '#afeeee',
|
|
143
|
-
palevioletred: '#db7093',
|
|
144
|
-
papayawhip: '#ffefd5',
|
|
145
|
-
peachpuff: '#ffdab9',
|
|
146
|
-
peru: '#cd853f',
|
|
147
|
-
pink: '#ffc0cb',
|
|
148
|
-
plum: '#dda0dd',
|
|
149
|
-
powderblue: '#b0e0e6',
|
|
150
|
-
purple: '#800080',
|
|
151
|
-
rebeccapurple: '#663399',
|
|
152
|
-
red: '#ff0000',
|
|
153
|
-
rosybrown: '#bc8f8f',
|
|
154
|
-
royalblue: '#4169e1',
|
|
155
|
-
saddlebrown: '#8b4513',
|
|
156
|
-
salmon: '#fa8072',
|
|
157
|
-
sandybrown: '#f4a460',
|
|
158
|
-
seagreen: '#2e8b57',
|
|
159
|
-
seashell: '#fff5ee',
|
|
160
|
-
sienna: '#a0522d',
|
|
161
|
-
silver: '#c0c0c0',
|
|
162
|
-
skyblue: '#87ceeb',
|
|
163
|
-
slateblue: '#6a5acd',
|
|
164
|
-
slategray: '#708090',
|
|
165
|
-
slategrey: '#708090',
|
|
166
|
-
snow: '#fffafa',
|
|
167
|
-
springgreen: '#00ff7f',
|
|
168
|
-
steelblue: '#4682b4',
|
|
169
|
-
tan: '#d2b48c',
|
|
170
|
-
teal: '#008080',
|
|
171
|
-
thistle: '#d8bfd8',
|
|
172
|
-
tomato: '#ff6347',
|
|
173
|
-
transparent: '#00000000',
|
|
174
|
-
turquoise: '#40e0d0',
|
|
175
|
-
violet: '#ee82ee',
|
|
176
|
-
wheat: '#f5deb3',
|
|
177
|
-
white: '#ffffff',
|
|
178
|
-
whitesmoke: '#f5f5f5',
|
|
179
|
-
yellow: '#ffff00',
|
|
180
|
-
yellowgreen: '#9acd32',
|
|
181
|
-
}));
|
|
182
|
-
|
|
183
|
-
export function nativeColorFromHexLiteral(hex: string): NativeColorValue {
|
|
184
|
-
const normalized = hex.trim().replace(/^#/, '');
|
|
185
|
-
const red = Number.parseInt(normalized.slice(0, 2), 16);
|
|
186
|
-
const green = Number.parseInt(normalized.slice(2, 4), 16);
|
|
187
|
-
const blue = Number.parseInt(normalized.slice(4, 6), 16);
|
|
188
|
-
const alpha = normalized.length >= 8 ? Number.parseInt(normalized.slice(6, 8), 16) / 255 : 1;
|
|
189
|
-
return { red, green, blue, alpha };
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export function createNativeNamedColorMap(colors: Record<string, string>): Record<string, NativeColorValue> {
|
|
193
|
-
return Object.fromEntries(
|
|
194
|
-
Object.entries(colors).map(([name, hex]) => [name, nativeColorFromHexLiteral(hex)])
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export const CURRENT_COLOR_KEYWORD = 'currentcolor';
|
|
199
|
-
|
|
200
|
-
export function cloneNativeColor(color: NativeColorValue | undefined): NativeColorValue | undefined {
|
|
201
|
-
return color ? { ...color } : undefined;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export function getDefaultCurrentColor(): NativeColorValue {
|
|
205
|
-
return cloneNativeColor(CSS_NAMED_COLORS.black) ?? { red: 0, green: 0, blue: 0, alpha: 1 };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function isCurrentColorKeyword(value: NativePropValue | undefined): value is string {
|
|
209
|
-
return typeof value === 'string' && value.trim().toLowerCase() === CURRENT_COLOR_KEYWORD;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export function nativeColorToCssColorLiteral(color: NativeColorValue): string {
|
|
213
|
-
return `rgba(${color.red}, ${color.green}, ${color.blue}, ${Number(color.alpha.toFixed(3))})`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export function resolveStyleCurrentColor(
|
|
217
|
-
style: Record<string, NativePropValue> | undefined,
|
|
218
|
-
inheritedColor?: NativeColorValue,
|
|
219
|
-
): NativeColorValue {
|
|
220
|
-
const fallbackColor = cloneNativeColor(inheritedColor) ?? getDefaultCurrentColor();
|
|
221
|
-
const resolvedColor = parseCssColor(style?.color, fallbackColor);
|
|
222
|
-
return resolvedColor ?? fallbackColor;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export function normalizeResolvedCurrentTextColor(
|
|
226
|
-
style: Record<string, NativePropValue> | undefined,
|
|
227
|
-
inheritedColor?: NativeColorValue,
|
|
228
|
-
): Record<string, NativePropValue> | undefined {
|
|
229
|
-
if (!style || !isCurrentColorKeyword(style.color)) {
|
|
230
|
-
return style;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
...style,
|
|
235
|
-
color: nativeColorToCssColorLiteral(resolveStyleCurrentColor(style, inheritedColor)),
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
export function isFillValue(value: NativePropValue | undefined): boolean {
|
|
241
|
-
return typeof value === 'string' && value.trim() === '100%';
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export function extractColorToken(value: string): string | undefined {
|
|
245
|
-
const trimmed = value.trim();
|
|
246
|
-
const directMatch = trimmed.match(/^((?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\([^()]+\)|#[0-9a-fA-F]{3,8}|currentcolor)$/i);
|
|
247
|
-
if (directMatch) {
|
|
248
|
-
return directMatch[1];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const normalized = trimmed.toLowerCase();
|
|
252
|
-
if (normalized === CURRENT_COLOR_KEYWORD) {
|
|
253
|
-
return normalized;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (CSS_NAMED_COLORS[normalized]) {
|
|
257
|
-
return normalized;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const embeddedMatch = trimmed.match(/((?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\([^()]+\)|#[0-9a-fA-F]{3,8}|currentcolor)/i);
|
|
261
|
-
if (embeddedMatch) {
|
|
262
|
-
return embeddedMatch[1];
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const firstParenIdx = trimmed.indexOf('(');
|
|
266
|
-
if (firstParenIdx > 0) {
|
|
267
|
-
let nameStart = firstParenIdx;
|
|
268
|
-
while (nameStart > 0 && trimmed[nameStart - 1] !== ' ' && trimmed[nameStart - 1] !== '\t') {
|
|
269
|
-
nameStart--;
|
|
270
|
-
}
|
|
271
|
-
const functionName = trimmed.slice(nameStart, firstParenIdx).toLowerCase();
|
|
272
|
-
if (
|
|
273
|
-
functionName !== 'rgb'
|
|
274
|
-
&& functionName !== 'rgba'
|
|
275
|
-
&& functionName !== 'hsl'
|
|
276
|
-
&& functionName !== 'hsla'
|
|
277
|
-
&& functionName !== 'hwb'
|
|
278
|
-
&& functionName !== 'lab'
|
|
279
|
-
&& functionName !== 'lch'
|
|
280
|
-
&& functionName !== 'oklab'
|
|
281
|
-
&& functionName !== 'oklch'
|
|
282
|
-
) {
|
|
283
|
-
return undefined;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return trimmed
|
|
288
|
-
.toLowerCase()
|
|
289
|
-
.split(/[^a-z-]+/)
|
|
290
|
-
.find((token) => token.length > 0 && (token === CURRENT_COLOR_KEYWORD || Boolean(CSS_NAMED_COLORS[token])));
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export function parseCssHue(value: string): number | undefined {
|
|
294
|
-
const match = value.trim().toLowerCase().match(/^(-?(?:\d+(?:\.\d*)?|\.\d+))(deg|grad|rad|turn)?$/);
|
|
295
|
-
if (!match) {
|
|
296
|
-
return undefined;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const numericValue = Number(match[1]);
|
|
300
|
-
if (!Number.isFinite(numericValue)) {
|
|
301
|
-
return undefined;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
switch (match[2] ?? 'deg') {
|
|
305
|
-
case 'turn':
|
|
306
|
-
return numericValue * 360;
|
|
307
|
-
case 'rad':
|
|
308
|
-
return numericValue * (180 / Math.PI);
|
|
309
|
-
case 'grad':
|
|
310
|
-
return numericValue * 0.9;
|
|
311
|
-
default:
|
|
312
|
-
return numericValue;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export function parseCssPercentageChannel(value: string): number | undefined {
|
|
317
|
-
const match = value.trim().match(/^(-?(?:\d+(?:\.\d*)?|\.\d+))%$/);
|
|
318
|
-
if (!match) {
|
|
319
|
-
return undefined;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const numericValue = Number(match[1]);
|
|
323
|
-
return Number.isFinite(numericValue) ? Math.max(0, Math.min(100, numericValue)) / 100 : undefined;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export function parseCssAlphaValue(value: string): number | undefined {
|
|
327
|
-
const trimmed = value.trim();
|
|
328
|
-
if (trimmed.endsWith('%')) {
|
|
329
|
-
const percentage = Number(trimmed.slice(0, -1));
|
|
330
|
-
return Number.isFinite(percentage) ? Math.max(0, Math.min(100, percentage)) / 100 : undefined;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const numericValue = Number(trimmed);
|
|
334
|
-
return Number.isFinite(numericValue) ? Math.max(0, Math.min(1, numericValue)) : undefined;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export function parseCssNumericChannel(value: string): number | undefined {
|
|
338
|
-
const numericValue = Number(value.trim());
|
|
339
|
-
return Number.isFinite(numericValue) ? numericValue : undefined;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export function parseCssNonNegativeNumericChannel(value: string): number | undefined {
|
|
343
|
-
const numericValue = parseCssNumericChannel(value);
|
|
344
|
-
return numericValue !== undefined ? Math.max(0, numericValue) : undefined;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export function parseCssLabLightness(value: string): number | undefined {
|
|
348
|
-
const trimmed = value.trim();
|
|
349
|
-
if (trimmed.endsWith('%')) {
|
|
350
|
-
const percentage = Number(trimmed.slice(0, -1));
|
|
351
|
-
return Number.isFinite(percentage) ? Math.max(0, Math.min(100, percentage)) : undefined;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const numericValue = Number(trimmed);
|
|
355
|
-
return Number.isFinite(numericValue) ? Math.max(0, Math.min(100, numericValue)) : undefined;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export function parseCssOklabLightness(value: string): number | undefined {
|
|
359
|
-
const trimmed = value.trim();
|
|
360
|
-
if (trimmed.endsWith('%')) {
|
|
361
|
-
const percentage = Number(trimmed.slice(0, -1));
|
|
362
|
-
return Number.isFinite(percentage) ? Math.max(0, Math.min(100, percentage)) / 100 : undefined;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const numericValue = Number(trimmed);
|
|
366
|
-
if (!Number.isFinite(numericValue)) {
|
|
367
|
-
return undefined;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const normalized = Math.abs(numericValue) > 1 ? numericValue / 100 : numericValue;
|
|
371
|
-
return Math.max(0, Math.min(1, normalized));
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
export function parseCssColorFunctionArguments(value: string): string[] {
|
|
375
|
-
const trimmed = value.trim();
|
|
376
|
-
if (!trimmed) {
|
|
377
|
-
return [];
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (trimmed.includes(',')) {
|
|
381
|
-
return splitCssFunctionArguments(trimmed).map((part) => part.trim()).filter(Boolean);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const alphaSplit = trimmed.split('/').map((part) => part.trim()).filter(Boolean);
|
|
385
|
-
if (alphaSplit.length === 0 || alphaSplit.length > 2) {
|
|
386
|
-
return [];
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const channels = alphaSplit[0].split(/\s+/).filter(Boolean);
|
|
390
|
-
return alphaSplit[1] ? [...channels, alphaSplit[1]] : channels;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
export function parseCssRgbChannel(value: string): number | undefined {
|
|
394
|
-
const trimmed = value.trim();
|
|
395
|
-
if (trimmed.endsWith('%')) {
|
|
396
|
-
const percentage = Number(trimmed.slice(0, -1));
|
|
397
|
-
return Number.isFinite(percentage)
|
|
398
|
-
? Math.round((Math.max(0, Math.min(100, percentage)) / 100) * 255)
|
|
399
|
-
: undefined;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const numericValue = Number(trimmed);
|
|
403
|
-
return Number.isFinite(numericValue)
|
|
404
|
-
? Math.round(Math.max(0, Math.min(255, numericValue)))
|
|
405
|
-
: undefined;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
export function hslToRgb(hue: number, saturation: number, lightness: number): { red: number; green: number; blue: number } {
|
|
409
|
-
const normalizedHue = ((hue % 360) + 360) % 360;
|
|
410
|
-
const chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation;
|
|
411
|
-
const segment = normalizedHue / 60;
|
|
412
|
-
const x = chroma * (1 - Math.abs((segment % 2) - 1));
|
|
413
|
-
|
|
414
|
-
const [redPrime, greenPrime, bluePrime] = segment < 1
|
|
415
|
-
? [chroma, x, 0]
|
|
416
|
-
: segment < 2
|
|
417
|
-
? [x, chroma, 0]
|
|
418
|
-
: segment < 3
|
|
419
|
-
? [0, chroma, x]
|
|
420
|
-
: segment < 4
|
|
421
|
-
? [0, x, chroma]
|
|
422
|
-
: segment < 5
|
|
423
|
-
? [x, 0, chroma]
|
|
424
|
-
: [chroma, 0, x];
|
|
425
|
-
|
|
426
|
-
const adjustment = lightness - (chroma / 2);
|
|
427
|
-
return {
|
|
428
|
-
red: Math.round((redPrime + adjustment) * 255),
|
|
429
|
-
green: Math.round((greenPrime + adjustment) * 255),
|
|
430
|
-
blue: Math.round((bluePrime + adjustment) * 255),
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
export function hwbToRgb(hue: number, whiteness: number, blackness: number): { red: number; green: number; blue: number } {
|
|
435
|
-
const sum = whiteness + blackness;
|
|
436
|
-
const normalizedWhiteness = sum > 1 ? whiteness / sum : whiteness;
|
|
437
|
-
const normalizedBlackness = sum > 1 ? blackness / sum : blackness;
|
|
438
|
-
const pureHue = hslToRgb(hue, 1, 0.5);
|
|
439
|
-
const factor = Math.max(0, 1 - normalizedWhiteness - normalizedBlackness);
|
|
440
|
-
|
|
441
|
-
return {
|
|
442
|
-
red: Math.round(((pureHue.red / 255) * factor + normalizedWhiteness) * 255),
|
|
443
|
-
green: Math.round(((pureHue.green / 255) * factor + normalizedWhiteness) * 255),
|
|
444
|
-
blue: Math.round(((pureHue.blue / 255) * factor + normalizedWhiteness) * 255),
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
export function linearSrgbChannelToByte(value: number): number {
|
|
449
|
-
const clamped = Math.max(0, Math.min(1, value));
|
|
450
|
-
const gammaCorrected = clamped <= 0.0031308
|
|
451
|
-
? 12.92 * clamped
|
|
452
|
-
: (1.055 * Math.pow(clamped, 1 / 2.4)) - 0.055;
|
|
453
|
-
return Math.round(Math.max(0, Math.min(1, gammaCorrected)) * 255);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
export function linearSrgbToNativeColor(red: number, green: number, blue: number, alpha: number): NativeColorValue {
|
|
457
|
-
return {
|
|
458
|
-
red: linearSrgbChannelToByte(red),
|
|
459
|
-
green: linearSrgbChannelToByte(green),
|
|
460
|
-
blue: linearSrgbChannelToByte(blue),
|
|
461
|
-
alpha,
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
export function d50XyzToLinearSrgb(x: number, y: number, z: number): { red: number; green: number; blue: number } {
|
|
466
|
-
const xD65 = (0.9555766 * x) - (0.0230393 * y) + (0.0631636 * z);
|
|
467
|
-
const yD65 = (-0.0282895 * x) + (1.0099416 * y) + (0.0210077 * z);
|
|
468
|
-
const zD65 = (0.0122982 * x) - (0.020483 * y) + (1.3299098 * z);
|
|
469
|
-
|
|
470
|
-
return {
|
|
471
|
-
red: (3.2404542 * xD65) - (1.5371385 * yD65) - (0.4985314 * zD65),
|
|
472
|
-
green: (-0.969266 * xD65) + (1.8760108 * yD65) + (0.041556 * zD65),
|
|
473
|
-
blue: (0.0556434 * xD65) - (0.2040259 * yD65) + (1.0572252 * zD65),
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
export function labToXyzComponent(value: number): number {
|
|
478
|
-
const epsilon = 216 / 24389;
|
|
479
|
-
const kappa = 24389 / 27;
|
|
480
|
-
const cube = value * value * value;
|
|
481
|
-
return cube > epsilon ? cube : ((116 * value) - 16) / kappa;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
export function labToNativeColor(lightness: number, a: number, b: number, alpha: number): NativeColorValue {
|
|
485
|
-
const fy = (lightness + 16) / 116;
|
|
486
|
-
const fx = fy + (a / 500);
|
|
487
|
-
const fz = fy - (b / 200);
|
|
488
|
-
const x = 0.96422 * labToXyzComponent(fx);
|
|
489
|
-
const y = labToXyzComponent(fy);
|
|
490
|
-
const z = 0.82521 * labToXyzComponent(fz);
|
|
491
|
-
const linearColor = d50XyzToLinearSrgb(x, y, z);
|
|
492
|
-
return linearSrgbToNativeColor(linearColor.red, linearColor.green, linearColor.blue, alpha);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
export function lchToNativeColor(lightness: number, chroma: number, hue: number, alpha: number): NativeColorValue {
|
|
496
|
-
const hueInRadians = (hue * Math.PI) / 180;
|
|
497
|
-
return labToNativeColor(
|
|
498
|
-
lightness,
|
|
499
|
-
chroma * Math.cos(hueInRadians),
|
|
500
|
-
chroma * Math.sin(hueInRadians),
|
|
501
|
-
alpha,
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
export function oklabToNativeColor(lightness: number, a: number, b: number, alpha: number): NativeColorValue {
|
|
506
|
-
const l = Math.pow(lightness + (0.3963377774 * a) + (0.2158037573 * b), 3);
|
|
507
|
-
const m = Math.pow(lightness - (0.1055613458 * a) - (0.0638541728 * b), 3);
|
|
508
|
-
const s = Math.pow(lightness - (0.0894841775 * a) - (1.291485548 * b), 3);
|
|
509
|
-
|
|
510
|
-
return linearSrgbToNativeColor(
|
|
511
|
-
(4.0767416621 * l) - (3.3077115913 * m) + (0.2309699292 * s),
|
|
512
|
-
(-1.2684380046 * l) + (2.6097574011 * m) - (0.3413193965 * s),
|
|
513
|
-
(-0.0041960863 * l) - (0.7034186147 * m) + (1.707614701 * s),
|
|
514
|
-
alpha,
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
export function oklchToNativeColor(lightness: number, chroma: number, hue: number, alpha: number): NativeColorValue {
|
|
519
|
-
const hueInRadians = (hue * Math.PI) / 180;
|
|
520
|
-
return oklabToNativeColor(
|
|
521
|
-
lightness,
|
|
522
|
-
chroma * Math.cos(hueInRadians),
|
|
523
|
-
chroma * Math.sin(hueInRadians),
|
|
524
|
-
alpha,
|
|
525
|
-
);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
export function parseCssColor(value: NativePropValue | undefined, currentColor: NativeColorValue = getDefaultCurrentColor()): NativeColorValue | undefined {
|
|
529
|
-
if (typeof value !== 'string') return undefined;
|
|
530
|
-
|
|
531
|
-
const token = extractColorToken(value);
|
|
532
|
-
if (!token) return undefined;
|
|
533
|
-
|
|
534
|
-
if (token.toLowerCase() === CURRENT_COLOR_KEYWORD) {
|
|
535
|
-
return cloneNativeColor(currentColor) ?? getDefaultCurrentColor();
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const namedColor = CSS_NAMED_COLORS[token.toLowerCase()];
|
|
539
|
-
if (namedColor) {
|
|
540
|
-
return { ...namedColor };
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const hexMatch = token.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/);
|
|
544
|
-
if (hexMatch) {
|
|
545
|
-
const hex = hexMatch[1];
|
|
546
|
-
if (hex.length === 3 || hex.length === 4) {
|
|
547
|
-
const [r, g, b, a = 'f'] = hex.split('');
|
|
548
|
-
return {
|
|
549
|
-
red: parseInt(`${r}${r}`, 16),
|
|
550
|
-
green: parseInt(`${g}${g}`, 16),
|
|
551
|
-
blue: parseInt(`${b}${b}`, 16),
|
|
552
|
-
alpha: parseInt(`${a}${a}`, 16) / 255,
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
const red = parseInt(hex.slice(0, 2), 16);
|
|
557
|
-
const green = parseInt(hex.slice(2, 4), 16);
|
|
558
|
-
const blue = parseInt(hex.slice(4, 6), 16);
|
|
559
|
-
const alpha = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
|
|
560
|
-
return { red, green, blue, alpha };
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const hslMatch = token.match(/^hsla?\(([^()]+)\)$/i);
|
|
564
|
-
if (hslMatch) {
|
|
565
|
-
const parts = parseCssColorFunctionArguments(hslMatch[1]);
|
|
566
|
-
if (parts.length < 3) {
|
|
567
|
-
return undefined;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const hue = parseCssHue(parts[0]);
|
|
571
|
-
const saturation = parseCssPercentageChannel(parts[1]);
|
|
572
|
-
const lightness = parseCssPercentageChannel(parts[2]);
|
|
573
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
574
|
-
if (hue === undefined || saturation === undefined || lightness === undefined || alpha === undefined) {
|
|
575
|
-
return undefined;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
return {
|
|
579
|
-
...hslToRgb(hue, saturation, lightness),
|
|
580
|
-
alpha,
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
const hwbMatch = token.match(/^hwb\(([^()]+)\)$/i);
|
|
585
|
-
if (hwbMatch) {
|
|
586
|
-
const parts = parseCssColorFunctionArguments(hwbMatch[1]);
|
|
587
|
-
if (parts.length < 3) {
|
|
588
|
-
return undefined;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
const hue = parseCssHue(parts[0]);
|
|
592
|
-
const whiteness = parseCssPercentageChannel(parts[1]);
|
|
593
|
-
const blackness = parseCssPercentageChannel(parts[2]);
|
|
594
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
595
|
-
if (hue === undefined || whiteness === undefined || blackness === undefined || alpha === undefined) {
|
|
596
|
-
return undefined;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
return {
|
|
600
|
-
...hwbToRgb(hue, whiteness, blackness),
|
|
601
|
-
alpha,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
const labMatch = token.match(/^lab\(([^()]+)\)$/i);
|
|
606
|
-
if (labMatch) {
|
|
607
|
-
const parts = parseCssColorFunctionArguments(labMatch[1]);
|
|
608
|
-
if (parts.length < 3) {
|
|
609
|
-
return undefined;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
const lightness = parseCssLabLightness(parts[0]);
|
|
613
|
-
const a = parseCssNumericChannel(parts[1]);
|
|
614
|
-
const b = parseCssNumericChannel(parts[2]);
|
|
615
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
616
|
-
if (lightness === undefined || a === undefined || b === undefined || alpha === undefined) {
|
|
617
|
-
return undefined;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
return labToNativeColor(lightness, a, b, alpha);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
const lchMatch = token.match(/^lch\(([^()]+)\)$/i);
|
|
624
|
-
if (lchMatch) {
|
|
625
|
-
const parts = parseCssColorFunctionArguments(lchMatch[1]);
|
|
626
|
-
if (parts.length < 3) {
|
|
627
|
-
return undefined;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
const lightness = parseCssLabLightness(parts[0]);
|
|
631
|
-
const chroma = parseCssNonNegativeNumericChannel(parts[1]);
|
|
632
|
-
const hue = parseCssHue(parts[2]);
|
|
633
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
634
|
-
if (lightness === undefined || chroma === undefined || hue === undefined || alpha === undefined) {
|
|
635
|
-
return undefined;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
return lchToNativeColor(lightness, chroma, hue, alpha);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
const oklabMatch = token.match(/^oklab\(([^()]+)\)$/i);
|
|
642
|
-
if (oklabMatch) {
|
|
643
|
-
const parts = parseCssColorFunctionArguments(oklabMatch[1]);
|
|
644
|
-
if (parts.length < 3) {
|
|
645
|
-
return undefined;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
const lightness = parseCssOklabLightness(parts[0]);
|
|
649
|
-
const a = parseCssNumericChannel(parts[1]);
|
|
650
|
-
const b = parseCssNumericChannel(parts[2]);
|
|
651
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
652
|
-
if (lightness === undefined || a === undefined || b === undefined || alpha === undefined) {
|
|
653
|
-
return undefined;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
return oklabToNativeColor(lightness, a, b, alpha);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
const oklchMatch = token.match(/^oklch\(([^()]+)\)$/i);
|
|
660
|
-
if (oklchMatch) {
|
|
661
|
-
const parts = parseCssColorFunctionArguments(oklchMatch[1]);
|
|
662
|
-
if (parts.length < 3) {
|
|
663
|
-
return undefined;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
const lightness = parseCssOklabLightness(parts[0]);
|
|
667
|
-
const chroma = parseCssNonNegativeNumericChannel(parts[1]);
|
|
668
|
-
const hue = parseCssHue(parts[2]);
|
|
669
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
670
|
-
if (lightness === undefined || chroma === undefined || hue === undefined || alpha === undefined) {
|
|
671
|
-
return undefined;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
return oklchToNativeColor(lightness, chroma, hue, alpha);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
const rgbMatch = token.match(/^rgba?\(([^()]+)\)$/i);
|
|
678
|
-
if (!rgbMatch) return undefined;
|
|
679
|
-
|
|
680
|
-
const parts = parseCssColorFunctionArguments(rgbMatch[1]);
|
|
681
|
-
if (parts.length < 3) return undefined;
|
|
682
|
-
|
|
683
|
-
const red = parseCssRgbChannel(parts[0]);
|
|
684
|
-
const green = parseCssRgbChannel(parts[1]);
|
|
685
|
-
const blue = parseCssRgbChannel(parts[2]);
|
|
686
|
-
const alpha = parts[3] !== undefined ? parseCssAlphaValue(parts[3]) : 1;
|
|
687
|
-
|
|
688
|
-
if (alpha === undefined || red === undefined || green === undefined || blue === undefined) {
|
|
689
|
-
return undefined;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return { red, green, blue, alpha };
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
export function toComposeColorLiteral(color: NativeColorValue): string {
|
|
696
|
-
return `Color(red = ${formatFloat(color.red / 255)}f, green = ${formatFloat(color.green / 255)}f, blue = ${formatFloat(color.blue / 255)}f, alpha = ${formatFloat(color.alpha)}f)`;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
export function toSwiftColorLiteral(color: NativeColorValue): string {
|
|
700
|
-
return `Color(red: ${formatFloat(color.red / 255)}, green: ${formatFloat(color.green / 255)}, blue: ${formatFloat(color.blue / 255)}, opacity: ${formatFloat(color.alpha)})`;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
export function normalizeAngle(angle: number): number {
|
|
704
|
-
const normalized = angle % 360;
|
|
705
|
-
return normalized < 0 ? normalized + 360 : normalized;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
export function resolveGradientDirection(angle: number | undefined): NativeGradientDirection {
|
|
709
|
-
if (angle === undefined || Number.isNaN(angle)) {
|
|
710
|
-
return 'topLeadingToBottomTrailing';
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
const normalized = normalizeAngle(angle);
|
|
714
|
-
if (normalized >= 67.5 && normalized < 112.5) {
|
|
715
|
-
return 'leadingToTrailing';
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
if (normalized >= 157.5 && normalized < 202.5) {
|
|
719
|
-
return 'topToBottom';
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
if (normalized >= 247.5 && normalized < 292.5) {
|
|
723
|
-
return 'trailingToLeading';
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
if (normalized >= 337.5 || normalized < 22.5) {
|
|
727
|
-
return 'bottomToTop';
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
return normalized >= 112.5 && normalized < 247.5
|
|
731
|
-
? 'topLeadingToBottomTrailing'
|
|
732
|
-
: 'bottomTrailingToTopLeading';
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
export function parseLinearGradient(value: NativePropValue | undefined, currentColor: NativeColorValue = getDefaultCurrentColor()): NativeGradientValue | undefined {
|
|
736
|
-
if (typeof value !== 'string') return undefined;
|
|
737
|
-
|
|
738
|
-
const trimmed = value.trim();
|
|
739
|
-
if (!trimmed.toLowerCase().startsWith('linear-gradient(') || !trimmed.endsWith(')')) {
|
|
740
|
-
return undefined;
|
|
741
|
-
}
|
|
742
|
-
const gradientInner = trimmed.slice('linear-gradient('.length, -1);
|
|
743
|
-
|
|
744
|
-
const segments = splitCssFunctionArguments(gradientInner).map((segment) => segment.trim()).filter(Boolean);
|
|
745
|
-
if (segments.length < 2) {
|
|
746
|
-
return undefined;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
const colorSegments = /^(-?\d+(?:\.\d+)?)deg$/i.test(segments[0]) || /^to\s+/i.test(segments[0])
|
|
750
|
-
? segments.slice(1)
|
|
751
|
-
: segments;
|
|
752
|
-
|
|
753
|
-
const colors = colorSegments
|
|
754
|
-
.map((token) => parseCssColor(token, currentColor))
|
|
755
|
-
.filter((color): color is NativeColorValue => Boolean(color));
|
|
756
|
-
if (colors.length < 2) {
|
|
757
|
-
return undefined;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const angleMatch = trimmed.match(/linear-gradient\(\s*(-?\d+(?:\.\d+)?)deg/i);
|
|
761
|
-
const angle = angleMatch ? Number(angleMatch[1]) : undefined;
|
|
762
|
-
|
|
763
|
-
return {
|
|
764
|
-
colors,
|
|
765
|
-
direction: resolveGradientDirection(angle),
|
|
766
|
-
};
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
export function formatComposeGradientColors(colors: NativeColorValue[], reverse = false): string {
|
|
770
|
-
const orderedColors = reverse ? [...colors].reverse() : colors;
|
|
771
|
-
return orderedColors.map((color) => toComposeColorLiteral(color)).join(', ');
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
export function toComposeBrushLiteral(gradient: NativeGradientValue): string {
|
|
775
|
-
switch (gradient.direction) {
|
|
776
|
-
case 'topToBottom':
|
|
777
|
-
return `Brush.verticalGradient(colors = listOf(${formatComposeGradientColors(gradient.colors)}))`;
|
|
778
|
-
case 'bottomToTop':
|
|
779
|
-
return `Brush.verticalGradient(colors = listOf(${formatComposeGradientColors(gradient.colors, true)}))`;
|
|
780
|
-
case 'leadingToTrailing':
|
|
781
|
-
return `Brush.horizontalGradient(colors = listOf(${formatComposeGradientColors(gradient.colors)}))`;
|
|
782
|
-
case 'trailingToLeading':
|
|
783
|
-
return `Brush.horizontalGradient(colors = listOf(${formatComposeGradientColors(gradient.colors, true)}))`;
|
|
784
|
-
case 'bottomTrailingToTopLeading':
|
|
785
|
-
return `Brush.linearGradient(colors = listOf(${formatComposeGradientColors(gradient.colors, true)}))`;
|
|
786
|
-
default:
|
|
787
|
-
return `Brush.linearGradient(colors = listOf(${formatComposeGradientColors(gradient.colors)}))`;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
export function toSwiftGradientLiteral(gradient: NativeGradientValue): string {
|
|
792
|
-
const colors = gradient.colors.map((color) => toSwiftColorLiteral(color)).join(', ');
|
|
793
|
-
const startPoint = gradient.direction === 'topToBottom'
|
|
794
|
-
? '.top'
|
|
795
|
-
: gradient.direction === 'bottomToTop'
|
|
796
|
-
? '.bottom'
|
|
797
|
-
: gradient.direction === 'leadingToTrailing'
|
|
798
|
-
? '.leading'
|
|
799
|
-
: gradient.direction === 'trailingToLeading'
|
|
800
|
-
? '.trailing'
|
|
801
|
-
: gradient.direction === 'bottomTrailingToTopLeading'
|
|
802
|
-
? '.bottomTrailing'
|
|
803
|
-
: '.topLeading';
|
|
804
|
-
const endPoint = gradient.direction === 'topToBottom'
|
|
805
|
-
? '.bottom'
|
|
806
|
-
: gradient.direction === 'bottomToTop'
|
|
807
|
-
? '.top'
|
|
808
|
-
: gradient.direction === 'leadingToTrailing'
|
|
809
|
-
? '.trailing'
|
|
810
|
-
: gradient.direction === 'trailingToLeading'
|
|
811
|
-
? '.leading'
|
|
812
|
-
: gradient.direction === 'bottomTrailingToTopLeading'
|
|
813
|
-
? '.topLeading'
|
|
814
|
-
: '.bottomTrailing';
|
|
815
|
-
|
|
816
|
-
return `LinearGradient(colors: [${colors}], startPoint: ${startPoint}, endPoint: ${endPoint})`;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
export function parseSingleBoxShadow(value: string, currentColor: NativeColorValue = getDefaultCurrentColor()): NativeShadowValue | undefined {
|
|
820
|
-
if (/\binset\b/i.test(value)) {
|
|
821
|
-
return undefined;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
if (typeof value !== 'string') return undefined;
|
|
825
|
-
|
|
826
|
-
const colorToken = extractColorToken(value);
|
|
827
|
-
const color = parseCssColor(colorToken ?? value, currentColor);
|
|
828
|
-
if (!color) {
|
|
829
|
-
return undefined;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
const dimensionSource = colorToken ? value.replace(colorToken, ' ').trim() : value.trim();
|
|
833
|
-
const lengths = dimensionSource.match(/-?\d+(?:\.\d+)?(?:px|dp|pt)?/g) ?? [];
|
|
834
|
-
if (lengths.length < 2) {
|
|
835
|
-
return undefined;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
const offsetX = Number.parseFloat(lengths[0]!);
|
|
839
|
-
const offsetY = Number.parseFloat(lengths[1]!);
|
|
840
|
-
const blur = lengths[2] ? Number.parseFloat(lengths[2]) : Math.max(Math.abs(offsetX), Math.abs(offsetY));
|
|
841
|
-
const spread = lengths[3] ? Number.parseFloat(lengths[3]) : 0;
|
|
842
|
-
|
|
843
|
-
if ([offsetX, offsetY, blur, spread].some((entry) => Number.isNaN(entry))) {
|
|
844
|
-
return undefined;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
return {
|
|
848
|
-
offsetX,
|
|
849
|
-
offsetY,
|
|
850
|
-
blur: Math.max(0, blur + Math.max(0, spread)),
|
|
851
|
-
color,
|
|
852
|
-
};
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
export function parseBoxShadowList(value: NativePropValue | undefined, currentColor: NativeColorValue = getDefaultCurrentColor()): NativeShadowValue[] {
|
|
856
|
-
if (typeof value !== 'string') {
|
|
857
|
-
return [];
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
return splitCssFunctionArguments(value)
|
|
861
|
-
.map((entry) => parseSingleBoxShadow(entry.trim(), currentColor))
|
|
862
|
-
.filter((entry): entry is NativeShadowValue => entry !== undefined);
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
export function toComposeShadowElevation(shadow: NativeShadowValue): string {
|
|
866
|
-
const elevation = Math.max(1, Math.abs(shadow.offsetY), shadow.blur / 4);
|
|
867
|
-
return `${formatFloat(elevation)}.dp`;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
export function toSwiftShadowRadius(shadow: NativeShadowValue): string {
|
|
871
|
-
const radius = Math.max(1, shadow.blur / 2);
|
|
872
|
-
return formatFloat(radius);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
export function parseBlurFilterRadius(
|
|
876
|
-
value: NativePropValue | undefined,
|
|
877
|
-
styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
|
|
878
|
-
): number | undefined {
|
|
879
|
-
if (typeof value !== 'string') {
|
|
880
|
-
return undefined;
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
const match = value.match(/blur\(([^()]*)\)/i);
|
|
884
|
-
if (!match) {
|
|
885
|
-
return undefined;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
const radius = toScaledUnitNumber(match[1].trim(), styleResolveOptions);
|
|
889
|
-
return radius !== undefined && radius > 0 ? radius : undefined;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
export function resolveBackdropBlurRadius(
|
|
893
|
-
style: Record<string, NativePropValue>,
|
|
894
|
-
styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
|
|
895
|
-
): number | undefined {
|
|
896
|
-
return parseBlurFilterRadius(style.backdropFilter, styleResolveOptions);
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
export function liftColorAlpha(color: NativeColorValue, delta: number): NativeColorValue {
|
|
900
|
-
return {
|
|
901
|
-
...color,
|
|
902
|
-
alpha: Math.min(0.96, Math.max(color.alpha, 0) + Math.max(0, delta)),
|
|
903
|
-
};
|
|
904
|
-
}
|