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.
Files changed (113) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +1 -1
  3. package/desktop/build.rs +83 -0
  4. package/desktop/icon.rs +106 -0
  5. package/desktop/lib.rs +2 -0
  6. package/desktop/main.rs +235 -0
  7. package/desktop/native_main.rs +128 -0
  8. package/desktop/native_renderer/action_widgets.rs +184 -0
  9. package/desktop/native_renderer/app_models.rs +171 -0
  10. package/desktop/native_renderer/app_runtime.rs +140 -0
  11. package/desktop/native_renderer/container_rendering.rs +610 -0
  12. package/desktop/native_renderer/content_widgets.rs +634 -0
  13. package/desktop/native_renderer/css_models.rs +371 -0
  14. package/desktop/native_renderer/embedded_surfaces.rs +414 -0
  15. package/desktop/native_renderer/form_controls.rs +516 -0
  16. package/desktop/native_renderer/interaction_dispatch.rs +89 -0
  17. package/desktop/native_renderer/runtime_support.rs +135 -0
  18. package/desktop/native_renderer/utilities.rs +495 -0
  19. package/desktop/native_renderer/vector_drawing.rs +491 -0
  20. package/desktop/native_renderer.rs +4122 -0
  21. package/desktop/runtime/external.rs +422 -0
  22. package/desktop/runtime/mod.rs +67 -0
  23. package/desktop/runtime/quickjs.rs +106 -0
  24. package/desktop/window.rs +383 -0
  25. package/package.json +6 -3
  26. package/dist/build.d.mts +0 -20
  27. package/dist/chokidar.d.mts +0 -134
  28. package/dist/cli.d.mts +0 -81
  29. package/dist/config.d.mts +0 -254
  30. package/dist/coverage.d.mts +0 -85
  31. package/dist/database.d.mts +0 -52
  32. package/dist/desktop.d.mts +0 -68
  33. package/dist/dom.d.mts +0 -87
  34. package/dist/el.d.mts +0 -208
  35. package/dist/fs.d.mts +0 -255
  36. package/dist/hmr.d.mts +0 -38
  37. package/dist/http.d.mts +0 -169
  38. package/dist/https.d.mts +0 -108
  39. package/dist/index.d.mts +0 -13
  40. package/dist/mime-types.d.mts +0 -48
  41. package/dist/native.d.mts +0 -136
  42. package/dist/path.d.mts +0 -163
  43. package/dist/router.d.mts +0 -49
  44. package/dist/runtime.d.mts +0 -97
  45. package/dist/server-D0Dp4R5z.d.mts +0 -449
  46. package/dist/server.d.mts +0 -7
  47. package/dist/state.d.mts +0 -117
  48. package/dist/style.d.mts +0 -232
  49. package/dist/test-reporter.d.mts +0 -77
  50. package/dist/test-runtime.d.mts +0 -122
  51. package/dist/test.d.mts +0 -39
  52. package/dist/types.d.mts +0 -586
  53. package/dist/universal.d.mts +0 -21
  54. package/dist/ws.d.mts +0 -200
  55. package/dist/wss.d.mts +0 -108
  56. package/src/build.ts +0 -362
  57. package/src/chokidar.ts +0 -427
  58. package/src/cli.ts +0 -1162
  59. package/src/config.ts +0 -509
  60. package/src/coverage.ts +0 -1479
  61. package/src/database.ts +0 -1410
  62. package/src/desktop-auto-render.ts +0 -317
  63. package/src/desktop-cli.ts +0 -1533
  64. package/src/desktop.ts +0 -99
  65. package/src/dev-build.ts +0 -340
  66. package/src/dom.ts +0 -901
  67. package/src/el.ts +0 -183
  68. package/src/fs.ts +0 -609
  69. package/src/hmr.ts +0 -149
  70. package/src/http.ts +0 -856
  71. package/src/https.ts +0 -411
  72. package/src/index.ts +0 -16
  73. package/src/mime-types.ts +0 -222
  74. package/src/mobile-cli.ts +0 -2313
  75. package/src/native-background.ts +0 -444
  76. package/src/native-border.ts +0 -343
  77. package/src/native-canvas.ts +0 -260
  78. package/src/native-cli.ts +0 -414
  79. package/src/native-color.ts +0 -904
  80. package/src/native-estimation.ts +0 -194
  81. package/src/native-grid.ts +0 -590
  82. package/src/native-interaction.ts +0 -1289
  83. package/src/native-layout.ts +0 -568
  84. package/src/native-link.ts +0 -76
  85. package/src/native-render-support.ts +0 -361
  86. package/src/native-spacing.ts +0 -231
  87. package/src/native-state.ts +0 -318
  88. package/src/native-strings.ts +0 -46
  89. package/src/native-transform.ts +0 -120
  90. package/src/native-types.ts +0 -439
  91. package/src/native-typography.ts +0 -254
  92. package/src/native-units.ts +0 -441
  93. package/src/native-vector.ts +0 -910
  94. package/src/native.ts +0 -5606
  95. package/src/path.ts +0 -493
  96. package/src/pm-cli.ts +0 -2498
  97. package/src/preview-build.ts +0 -294
  98. package/src/render-context.ts +0 -138
  99. package/src/router.ts +0 -260
  100. package/src/runtime.ts +0 -97
  101. package/src/server.ts +0 -2294
  102. package/src/state.ts +0 -556
  103. package/src/style.ts +0 -1790
  104. package/src/test-globals.d.ts +0 -184
  105. package/src/test-reporter.ts +0 -609
  106. package/src/test-runtime.ts +0 -1359
  107. package/src/test.ts +0 -368
  108. package/src/types.ts +0 -381
  109. package/src/universal.ts +0 -81
  110. package/src/wapk-cli.ts +0 -3213
  111. package/src/workspace-package.ts +0 -102
  112. package/src/ws.ts +0 -648
  113. package/src/wss.ts +0 -241
@@ -1,568 +0,0 @@
1
- import { type NativeStyleResolveOptions } from './style';
2
- import type { NativeContentStackAlignment, NativeGridItemAlignment, NativePropValue, NativeRenderHints, NativeStyleScope } from './native-types';
3
- import { isFillValue } from './native-color';
4
- import { getNativeStyleResolveOptions, resolveAxisUnitNumber, toDpLiteral, toPointLiteral } from './native-units';
5
-
6
- function resolveNativeContentStackAlignmentKeyword(value: NativePropValue | undefined): NativeContentStackAlignment | undefined {
7
- if (typeof value !== 'string') {
8
- return undefined;
9
- }
10
-
11
- switch (value.trim().toLowerCase()) {
12
- case 'flex-start':
13
- case 'start':
14
- case 'top':
15
- return 'start';
16
- case 'center':
17
- return 'center';
18
- case 'flex-end':
19
- case 'end':
20
- case 'bottom':
21
- return 'end';
22
- case 'normal':
23
- case 'stretch':
24
- return 'stretch';
25
- case 'space-between':
26
- return 'space-between';
27
- case 'space-around':
28
- return 'space-around';
29
- case 'space-evenly':
30
- return 'space-evenly';
31
- default:
32
- return undefined;
33
- }
34
- }
35
-
36
- function resolveNativePlaceContent(
37
- value: NativePropValue | undefined,
38
- ): { align?: NativeContentStackAlignment; justify?: string } | undefined {
39
- if (typeof value !== 'string') {
40
- return undefined;
41
- }
42
-
43
- const tokens = value.trim().toLowerCase().split(/\s+/).filter(Boolean);
44
- if (tokens.length === 0) {
45
- return undefined;
46
- }
47
-
48
- const align = resolveNativeContentStackAlignmentKeyword(tokens[0]);
49
- const justify = tokens[1] ?? tokens[0];
50
-
51
- return align || justify
52
- ? {
53
- ...(align ? { align } : {}),
54
- ...(justify ? { justify } : {}),
55
- }
56
- : undefined;
57
- }
58
-
59
- export function resolveNativeAlignContent(style: Record<string, NativePropValue> | undefined): NativeContentStackAlignment | undefined {
60
- const direct = resolveNativeContentStackAlignmentKeyword(style?.alignContent);
61
- if (direct) {
62
- return direct;
63
- }
64
-
65
- return resolveNativePlaceContent(style?.placeContent)?.align;
66
- }
67
-
68
- function resolveNativeJustifyContent(style: Record<string, NativePropValue> | undefined): string | undefined {
69
- if (!style) {
70
- return undefined;
71
- }
72
-
73
- if (typeof style.justifyContent === 'string' && style.justifyContent.trim()) {
74
- return style.justifyContent.trim().toLowerCase();
75
- }
76
-
77
- return resolveNativePlaceContent(style.placeContent)?.justify;
78
- }
79
-
80
- export function resolvePositionMode(value: NativePropValue | undefined): 'relative' | 'absolute' | 'fixed' | undefined {
81
- if (typeof value !== 'string') {
82
- return undefined;
83
- }
84
-
85
- const normalized = value.trim().toLowerCase();
86
- return normalized === 'relative' || normalized === 'absolute' || normalized === 'fixed'
87
- ? normalized
88
- : undefined;
89
- }
90
-
91
- export function hasExplicitNativeWidthStyle(style: Record<string, NativePropValue> | undefined): boolean {
92
- return Boolean(style && (style.width !== undefined || style.minWidth !== undefined || style.maxWidth !== undefined));
93
- }
94
-
95
- export function hasExplicitNativeHeightStyle(style: Record<string, NativePropValue> | undefined): boolean {
96
- return Boolean(style && (style.height !== undefined || style.minHeight !== undefined || style.maxHeight !== undefined));
97
- }
98
-
99
- export function hasNativeTableLayoutSourceTag(sourceTag: string | undefined): boolean {
100
- return sourceTag === 'table'
101
- || sourceTag === 'thead'
102
- || sourceTag === 'tbody'
103
- || sourceTag === 'tfoot'
104
- || sourceTag === 'tr'
105
- || sourceTag === 'td'
106
- || sourceTag === 'th';
107
- }
108
-
109
- export function resolvePositionInsets(
110
- style: Record<string, NativePropValue> | undefined,
111
- hints: NativeRenderHints | undefined,
112
- styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
113
- ): { top?: number; right?: number; bottom?: number; left?: number } {
114
- return {
115
- top: resolveAxisUnitNumber(style?.top, 'vertical', hints, styleResolveOptions),
116
- right: resolveAxisUnitNumber(style?.right, 'horizontal', hints, styleResolveOptions),
117
- bottom: resolveAxisUnitNumber(style?.bottom, 'vertical', hints, styleResolveOptions),
118
- left: resolveAxisUnitNumber(style?.left, 'horizontal', hints, styleResolveOptions),
119
- };
120
- }
121
-
122
- function resolveNativeContainerNames(style: Record<string, NativePropValue> | undefined): string[] {
123
- if (!style || typeof style.containerName !== 'string') {
124
- return [];
125
- }
126
-
127
- return style.containerName
128
- .split(/\s+/)
129
- .map((containerName) => containerName.trim().toLowerCase())
130
- .filter((containerName) => containerName.length > 0 && containerName !== 'none');
131
- }
132
-
133
- function resolveNativeContainerWidth(
134
- style: Record<string, NativePropValue> | undefined,
135
- options: NativeStyleResolveOptions,
136
- ): number | undefined {
137
- if (!style) {
138
- return undefined;
139
- }
140
-
141
- if (isFillValue(style.width)) {
142
- return options.viewportWidth ?? 390;
143
- }
144
-
145
- return resolveAxisUnitNumber(style.width, 'horizontal', undefined, options)
146
- ?? resolveAxisUnitNumber(style.maxWidth, 'horizontal', undefined, options)
147
- ?? resolveAxisUnitNumber(style.minWidth, 'horizontal', undefined, options)
148
- ?? (options.viewportWidth ?? 390);
149
- }
150
-
151
- export function resolveNativeContainerScope(
152
- style: Record<string, NativePropValue> | undefined,
153
- options: NativeStyleResolveOptions,
154
- ): Pick<NativeStyleScope, 'containerNames' | 'containerWidth' | 'isContainer'> {
155
- const containerNames = resolveNativeContainerNames(style);
156
- const containerType = typeof style?.containerType === 'string'
157
- ? style.containerType.trim().toLowerCase()
158
- : undefined;
159
- const isContainer = Boolean(containerType && containerType !== 'normal') || containerNames.length > 0;
160
-
161
- return isContainer
162
- ? {
163
- containerNames,
164
- containerWidth: resolveNativeContainerWidth(style, options),
165
- isContainer: true,
166
- }
167
- : {};
168
- }
169
-
170
- export function resolveCrossAlignmentKeyword(
171
- value: NativePropValue | undefined,
172
- ): 'start' | 'center' | 'end' | 'stretch' | 'baseline' | undefined {
173
- if (typeof value !== 'string') {
174
- return undefined;
175
- }
176
-
177
- const normalized = value.trim().toLowerCase();
178
- switch (normalized) {
179
- case 'flex-start':
180
- case 'start':
181
- case 'left':
182
- case 'top':
183
- case 'self-start':
184
- return 'start';
185
- case 'center':
186
- return 'center';
187
- case 'flex-end':
188
- case 'end':
189
- case 'right':
190
- case 'bottom':
191
- case 'self-end':
192
- return 'end';
193
- case 'normal':
194
- case 'stretch':
195
- return 'stretch';
196
- case 'baseline':
197
- case 'first baseline':
198
- case 'last baseline':
199
- return 'baseline';
200
- default:
201
- return undefined;
202
- }
203
- }
204
-
205
- export function resolveBaselineAlignmentKeyword(value: NativePropValue | undefined): 'first' | 'last' | undefined {
206
- if (typeof value !== 'string') {
207
- return undefined;
208
- }
209
-
210
- const normalized = value.trim().toLowerCase();
211
- if (normalized === 'last baseline') {
212
- return 'last';
213
- }
214
-
215
- if (normalized === 'baseline' || normalized === 'first baseline') {
216
- return 'first';
217
- }
218
-
219
- return undefined;
220
- }
221
-
222
- export function resolveSelfAlignmentKeyword(value: NativePropValue | undefined): 'start' | 'center' | 'end' | 'stretch' | undefined {
223
- const alignment = resolveCrossAlignmentKeyword(value);
224
- return alignment === 'baseline' ? undefined : alignment;
225
- }
226
-
227
- export function resolveComposeSelfAlignmentCall(
228
- parentFlexLayout: 'Row' | 'Column' | undefined,
229
- style: Record<string, NativePropValue> | undefined,
230
- ): string | undefined {
231
- const alignSelf = resolveSelfAlignmentKeyword(style?.alignSelf);
232
- if (!alignSelf || !parentFlexLayout) {
233
- return undefined;
234
- }
235
-
236
- if (alignSelf === 'stretch') {
237
- if (parentFlexLayout === 'Row') {
238
- return style?.height === undefined && style?.minHeight === undefined && style?.maxHeight === undefined
239
- ? 'fillMaxHeight()'
240
- : undefined;
241
- }
242
-
243
- return style?.width === undefined && style?.minWidth === undefined && style?.maxWidth === undefined
244
- ? 'fillMaxWidth()'
245
- : undefined;
246
- }
247
-
248
- if (parentFlexLayout === 'Row') {
249
- switch (alignSelf) {
250
- case 'center':
251
- return 'align(Alignment.CenterVertically)';
252
- case 'end':
253
- return 'align(Alignment.Bottom)';
254
- default:
255
- return 'align(Alignment.Top)';
256
- }
257
- }
258
-
259
- switch (alignSelf) {
260
- case 'center':
261
- return 'align(Alignment.CenterHorizontally)';
262
- case 'end':
263
- return 'align(Alignment.End)';
264
- default:
265
- return 'align(Alignment.Start)';
266
- }
267
- }
268
-
269
- export function resolveSwiftSelfAlignmentModifier(
270
- parentFlexLayout: 'Row' | 'Column' | undefined,
271
- style: Record<string, NativePropValue> | undefined,
272
- ): string | undefined {
273
- const alignSelf = resolveSelfAlignmentKeyword(style?.alignSelf);
274
- if (!alignSelf || !parentFlexLayout) {
275
- return undefined;
276
- }
277
-
278
- if (alignSelf === 'stretch') {
279
- if (parentFlexLayout === 'Row') {
280
- return style?.height === undefined && style?.minHeight === undefined && style?.maxHeight === undefined
281
- ? '.frame(maxHeight: .infinity, alignment: .topLeading)'
282
- : undefined;
283
- }
284
-
285
- return style?.width === undefined && style?.minWidth === undefined && style?.maxWidth === undefined
286
- ? '.frame(maxWidth: .infinity, alignment: .leading)'
287
- : undefined;
288
- }
289
-
290
- if (parentFlexLayout === 'Row') {
291
- switch (alignSelf) {
292
- case 'center':
293
- return '.frame(maxHeight: .infinity, alignment: .center)';
294
- case 'end':
295
- return '.frame(maxHeight: .infinity, alignment: .bottomLeading)';
296
- default:
297
- return '.frame(maxHeight: .infinity, alignment: .topLeading)';
298
- }
299
- }
300
-
301
- switch (alignSelf) {
302
- case 'center':
303
- return '.frame(maxWidth: .infinity, alignment: .center)';
304
- case 'end':
305
- return '.frame(maxWidth: .infinity, alignment: .trailing)';
306
- default:
307
- return '.frame(maxWidth: .infinity, alignment: .leading)';
308
- }
309
- }
310
-
311
- export function resolveSwiftColumnAlignment(style: Record<string, NativePropValue> | undefined): string {
312
- const align = typeof style?.alignItems === 'string' ? style.alignItems.trim().toLowerCase() : undefined;
313
- return align === 'center'
314
- ? '.center'
315
- : align === 'flex-end' || align === 'end' || align === 'right'
316
- ? '.trailing'
317
- : '.leading';
318
- }
319
-
320
- export function resolveSwiftRowAlignmentFromStyle(
321
- style: Record<string, NativePropValue> | undefined,
322
- selfBaselineAlignment?: 'first' | 'last',
323
- ): string {
324
- const baselineAlignment = resolveBaselineAlignmentKeyword(style?.alignItems);
325
- if (baselineAlignment === 'last' || selfBaselineAlignment === 'last') {
326
- return '.lastTextBaseline';
327
- }
328
-
329
- if (baselineAlignment === 'first' || selfBaselineAlignment === 'first') {
330
- return '.firstTextBaseline';
331
- }
332
-
333
- const align = typeof style?.alignItems === 'string' ? style.alignItems.trim().toLowerCase() : undefined;
334
- return align === 'center'
335
- ? '.center'
336
- : align === 'flex-end' || align === 'end' || align === 'bottom'
337
- ? '.bottom'
338
- : '.top';
339
- }
340
-
341
- export function resolveRowBaselineAlignmentValues(values: Array<NativePropValue | undefined>): 'first' | 'last' | undefined {
342
- let hasFirstBaseline = false;
343
-
344
- for (const value of values) {
345
- const baselineAlignment = resolveBaselineAlignmentKeyword(value);
346
- if (baselineAlignment === 'last') {
347
- return 'last';
348
- }
349
-
350
- if (baselineAlignment === 'first') {
351
- hasFirstBaseline = true;
352
- }
353
- }
354
-
355
- return hasFirstBaseline ? 'first' : undefined;
356
- }
357
-
358
- function resolveNativeGridItemAlignmentKeyword(value: NativePropValue | undefined): NativeGridItemAlignment | undefined {
359
- const alignment = resolveCrossAlignmentKeyword(value);
360
- return alignment === 'baseline' ? undefined : alignment;
361
- }
362
-
363
- function resolveNativePlaceAlignment(value: NativePropValue | undefined): { align?: NativeGridItemAlignment; justify?: NativeGridItemAlignment } | undefined {
364
- if (typeof value !== 'string') {
365
- return undefined;
366
- }
367
-
368
- const tokens = value.trim().split(/\s+/).filter(Boolean);
369
- if (tokens.length === 0) {
370
- return undefined;
371
- }
372
-
373
- const align = resolveNativeGridItemAlignmentKeyword(tokens[0]);
374
- const justify = resolveNativeGridItemAlignmentKeyword(tokens[1] ?? tokens[0]);
375
- return align || justify
376
- ? {
377
- ...(align ? { align } : {}),
378
- ...(justify ? { justify } : {}),
379
- }
380
- : undefined;
381
- }
382
-
383
- export function resolveNativeGridItemHorizontalAlignment(
384
- style: Record<string, NativePropValue> | undefined,
385
- containerStyle: Record<string, NativePropValue> | undefined,
386
- ): NativeGridItemAlignment | undefined {
387
- const selfPlaceAlignment = resolveNativePlaceAlignment(style?.placeSelf);
388
- const containerPlaceAlignment = resolveNativePlaceAlignment(containerStyle?.placeItems);
389
-
390
- return resolveNativeGridItemAlignmentKeyword(style?.justifySelf)
391
- ?? selfPlaceAlignment?.justify
392
- ?? resolveNativeGridItemAlignmentKeyword(containerStyle?.justifyItems)
393
- ?? containerPlaceAlignment?.justify;
394
- }
395
-
396
- export function resolveNativeGridItemVerticalAlignment(
397
- style: Record<string, NativePropValue> | undefined,
398
- containerStyle: Record<string, NativePropValue> | undefined,
399
- ): NativeGridItemAlignment | undefined {
400
- const selfPlaceAlignment = resolveNativePlaceAlignment(style?.placeSelf);
401
- const containerPlaceAlignment = resolveNativePlaceAlignment(containerStyle?.placeItems);
402
-
403
- return resolveSelfAlignmentKeyword(style?.alignSelf)
404
- ?? selfPlaceAlignment?.align
405
- ?? resolveSelfAlignmentKeyword(containerStyle?.alignItems)
406
- ?? containerPlaceAlignment?.align;
407
- }
408
-
409
- export function resolveNativeGridCellAlignmentFromStyle(
410
- style: Record<string, NativePropValue> | undefined,
411
- containerStyle: Record<string, NativePropValue> | undefined,
412
- ): { horizontal?: NativeGridItemAlignment; vertical?: NativeGridItemAlignment } {
413
- const horizontal = resolveNativeGridItemHorizontalAlignment(style, containerStyle);
414
- const vertical = resolveNativeGridItemVerticalAlignment(style, containerStyle);
415
-
416
- return {
417
- ...(horizontal ? { horizontal } : {}),
418
- ...(vertical ? { vertical } : {}),
419
- };
420
- }
421
-
422
- export function resolveLayoutDirection(style: Record<string, NativePropValue> | undefined): 'Row' | 'Column' | undefined {
423
- if (!style) return undefined;
424
-
425
- if (typeof style.flexDirection === 'string') {
426
- return style.flexDirection.trim().toLowerCase() === 'row' ? 'Row' : 'Column';
427
- }
428
-
429
- if (typeof style.display === 'string') {
430
- const display = style.display.trim().toLowerCase();
431
- if (display === 'flex' || display === 'inline-flex') {
432
- return 'Row';
433
- }
434
- if (display === 'grid' || display === 'inline-grid') {
435
- return 'Column';
436
- }
437
- }
438
-
439
- return undefined;
440
- }
441
-
442
- export function resolveComposeLayoutFromStyle(
443
- component: string,
444
- style: Record<string, NativePropValue> | undefined,
445
- ): 'Row' | 'Column' {
446
- const styleLayout = resolveLayoutDirection(style);
447
- if (styleLayout) {
448
- return styleLayout;
449
- }
450
-
451
- return component === 'Row' || component === 'ListItem' ? 'Row' : 'Column';
452
- }
453
-
454
- export function resolveSwiftUILayoutFromStyle(
455
- component: string,
456
- style: Record<string, NativePropValue> | undefined,
457
- ): 'HStack' | 'VStack' {
458
- return resolveComposeLayoutFromStyle(component, style) === 'Row' ? 'HStack' : 'VStack';
459
- }
460
-
461
- export function buildComposeLayoutArgumentsFromStyle(
462
- layout: 'Row' | 'Column',
463
- modifier: string,
464
- style: Record<string, NativePropValue> | undefined,
465
- styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
466
- ): string {
467
- const args = [`modifier = ${modifier}`];
468
- const arrangement = buildComposeArrangement(layout, style, styleResolveOptions);
469
- const alignment = buildComposeCrossAlignment(layout, style);
470
-
471
- if (layout === 'Row') {
472
- if (arrangement) args.push(`horizontalArrangement = ${arrangement}`);
473
- if (alignment) args.push(`verticalAlignment = ${alignment}`);
474
- } else {
475
- if (arrangement) args.push(`verticalArrangement = ${arrangement}`);
476
- if (alignment) args.push(`horizontalAlignment = ${alignment}`);
477
- }
478
-
479
- return args.join(', ');
480
- }
481
-
482
- export function buildSwiftUILayoutFromStyle(
483
- layout: 'HStack' | 'VStack',
484
- sourceTag: string,
485
- style: Record<string, NativePropValue> | undefined,
486
- rowAlignment: string,
487
- styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
488
- ): string {
489
- const spacing = toPointLiteral(style?.gap ?? (layout === 'HStack' ? style?.columnGap : style?.rowGap) ?? style?.gap, styleResolveOptions)
490
- ?? (hasNativeTableLayoutSourceTag(sourceTag) ? '0' : '12');
491
-
492
- if (layout === 'HStack') {
493
- return `HStack(alignment: ${rowAlignment}, spacing: ${spacing})`;
494
- }
495
-
496
- return `VStack(alignment: ${resolveSwiftColumnAlignment(style)}, spacing: ${spacing})`;
497
- }
498
-
499
- export function buildComposeArrangement(
500
- layout: 'Row' | 'Column',
501
- style: Record<string, NativePropValue> | undefined,
502
- styleResolveOptions: NativeStyleResolveOptions = getNativeStyleResolveOptions('generic'),
503
- gapOverride?: string,
504
- ): string | undefined {
505
- if (!style) return undefined;
506
-
507
- const justify = resolveNativeJustifyContent(style);
508
- const gap = gapOverride ?? toDpLiteral(style.gap ?? (layout === 'Row' ? style.columnGap : style.rowGap) ?? style.gap, styleResolveOptions);
509
-
510
- if (layout === 'Row') {
511
- switch (justify) {
512
- case 'center': return 'Arrangement.Center';
513
- case 'flex-end':
514
- case 'end':
515
- case 'right':
516
- return 'Arrangement.End';
517
- case 'space-between': return 'Arrangement.SpaceBetween';
518
- case 'space-around': return 'Arrangement.SpaceAround';
519
- case 'space-evenly': return 'Arrangement.SpaceEvenly';
520
- default:
521
- return gap ? `Arrangement.spacedBy(${gap})` : undefined;
522
- }
523
- }
524
-
525
- switch (justify) {
526
- case 'center': return 'Arrangement.Center';
527
- case 'flex-end':
528
- case 'end':
529
- case 'bottom':
530
- return 'Arrangement.Bottom';
531
- case 'space-between': return 'Arrangement.SpaceBetween';
532
- case 'space-around': return 'Arrangement.SpaceAround';
533
- case 'space-evenly': return 'Arrangement.SpaceEvenly';
534
- default:
535
- return gap ? `Arrangement.spacedBy(${gap})` : undefined;
536
- }
537
- }
538
-
539
- export function buildComposeCrossAlignment(layout: 'Row' | 'Column', style: Record<string, NativePropValue> | undefined): string | undefined {
540
- if (!style || typeof style.alignItems !== 'string') return undefined;
541
-
542
- if (layout === 'Row' && resolveBaselineAlignmentKeyword(style.alignItems)) {
543
- return undefined;
544
- }
545
-
546
- const align = style.alignItems.trim().toLowerCase();
547
- if (layout === 'Row') {
548
- switch (align) {
549
- case 'center': return 'Alignment.CenterVertically';
550
- case 'flex-end':
551
- case 'end':
552
- case 'bottom':
553
- return 'Alignment.Bottom';
554
- default:
555
- return 'Alignment.Top';
556
- }
557
- }
558
-
559
- switch (align) {
560
- case 'center': return 'Alignment.CenterHorizontally';
561
- case 'flex-end':
562
- case 'end':
563
- case 'right':
564
- return 'Alignment.End';
565
- default:
566
- return 'Alignment.Start';
567
- }
568
- }
@@ -1,76 +0,0 @@
1
- import type { NativeElementNode, NativePropValue } from './native-types';
2
-
3
- export function isExternalDestination(value: NativePropValue | undefined): value is string {
4
- return typeof value === 'string' && /^[a-zA-Z][a-zA-Z\d+.-]*:/.test(value);
5
- }
6
-
7
- export function resolveNativeLinkTarget(node: NativeElementNode): string | undefined {
8
- return node.component === 'Link' && typeof node.props.target === 'string' && node.props.target.trim()
9
- ? node.props.target.trim().toLowerCase()
10
- : undefined;
11
- }
12
-
13
- export function resolveNativeLinkRelTokens(node: NativeElementNode): string[] {
14
- if (node.component !== 'Link' || typeof node.props.rel !== 'string') {
15
- return [];
16
- }
17
-
18
- return node.props.rel
19
- .split(/\s+/)
20
- .map((token) => token.trim().toLowerCase())
21
- .filter(Boolean);
22
- }
23
-
24
- function canNativeDownloadDestination(destination: string): boolean {
25
- return /^https?:/i.test(destination);
26
- }
27
-
28
- export function shouldNativeDownloadLink(node: NativeElementNode): boolean {
29
- if (node.component !== 'Link' || node.props.download === undefined) {
30
- return false;
31
- }
32
-
33
- const destination = typeof node.props.destination === 'string' ? node.props.destination : undefined;
34
- return Boolean(destination && canNativeDownloadDestination(destination));
35
- }
36
-
37
- export function resolveNativeDownloadSuggestedName(node: NativeElementNode): string | undefined {
38
- if (!shouldNativeDownloadLink(node)) {
39
- return undefined;
40
- }
41
-
42
- if (typeof node.props.download === 'string' && node.props.download.trim()) {
43
- return node.props.download.trim();
44
- }
45
-
46
- const destination = typeof node.props.destination === 'string' ? node.props.destination : undefined;
47
- if (!destination) {
48
- return undefined;
49
- }
50
-
51
- const normalized = destination.split(/[?#]/, 1)[0];
52
- const segments = normalized.split('/').filter(Boolean);
53
- const tail = segments[segments.length - 1];
54
- return tail && !tail.includes(':') ? tail : undefined;
55
- }
56
-
57
- export function resolveNativeLinkHint(node: NativeElementNode): string | undefined {
58
- if (node.component !== 'Link') {
59
- return undefined;
60
- }
61
-
62
- const parts: string[] = [];
63
- const destination = typeof node.props.destination === 'string' ? node.props.destination : undefined;
64
- const target = resolveNativeLinkTarget(node);
65
- const relTokens = resolveNativeLinkRelTokens(node);
66
-
67
- if (shouldNativeDownloadLink(node)) {
68
- parts.push('Downloads file');
69
- }
70
-
71
- if (destination && (isExternalDestination(destination) || target === '_blank' || target === '_system' || relTokens.includes('external'))) {
72
- parts.push('Opens externally');
73
- }
74
-
75
- return parts.length > 0 ? parts.join(', ') : undefined;
76
- }