@tamagui/static 3.0.0-beta.765.1 → 3.0.0-beta.804.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.
- package/dist/cjs/compiler.cjs +12 -1
- package/dist/cjs/compilerHost.cjs +642 -315
- package/dist/cjs/extractor/bundle.cjs +41 -17
- package/dist/cjs/extractor/getTamaguiConfigPathFromOptionsConfig.cjs +6 -1
- package/dist/cjs/extractor/loadTamagui.cjs +115 -64
- package/dist/esm/compiler.mjs +12 -1
- package/dist/esm/compiler.mjs.map +1 -1
- package/dist/esm/compilerHost.mjs +644 -316
- package/dist/esm/compilerHost.mjs.map +1 -1
- package/dist/esm/extractor/bundle.mjs +39 -16
- package/dist/esm/extractor/bundle.mjs.map +1 -1
- package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs +6 -1
- package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs.map +1 -1
- package/dist/esm/extractor/loadTamagui.mjs +115 -64
- package/dist/esm/extractor/loadTamagui.mjs.map +1 -1
- package/package.json +19 -19
- package/src/compiler.ts +16 -1
- package/src/compilerHost.ts +282 -93
- package/src/extractor/bundle.ts +7 -1
- package/src/extractor/getTamaguiConfigPathFromOptionsConfig.ts +9 -2
- package/types/compiler.d.ts.map +1 -1
- package/types/compilerHost.d.ts.map +1 -1
- package/types/extractor/bundle.d.ts.map +1 -1
- package/types/extractor/getTamaguiConfigPathFromOptionsConfig.d.ts.map +1 -1
|
@@ -102,7 +102,9 @@ function extractedStyleArtifacts(split, props, config, includeRuntimeBase = true
|
|
|
102
102
|
media: []
|
|
103
103
|
};
|
|
104
104
|
const classKeys = /* @__PURE__ */ new Map();
|
|
105
|
-
for (const [key, identifier] of Object.entries(split.classNames ?? {}))
|
|
105
|
+
for (const [key, identifier] of Object.entries(split.classNames ?? {})) {
|
|
106
|
+
if (typeof identifier === "string") classKeys.set(identifier, key);
|
|
107
|
+
}
|
|
106
108
|
const identifiers = /* @__PURE__ */ new Set([...classKeys.keys(), ...Object.values(rules).flatMap((styleObject) => {
|
|
107
109
|
const identifier = styleObject?.[import_helpers.StyleObjectIdentifier];
|
|
108
110
|
return typeof identifier === "string" ? [identifier] : [];
|
|
@@ -110,11 +112,17 @@ function extractedStyleArtifacts(split, props, config, includeRuntimeBase = true
|
|
|
110
112
|
for (const identifier of identifiers) {
|
|
111
113
|
const key = classKeys.get(identifier) ?? "";
|
|
112
114
|
const css2 = cssFromRules(Object.fromEntries(Object.entries(rules).filter(([, styleObject]) => styleObject?.[import_helpers.StyleObjectIdentifier] === identifier))).join("");
|
|
113
|
-
if (identifier.startsWith("t_group_"))
|
|
114
|
-
|
|
115
|
-
else if (
|
|
116
|
-
|
|
117
|
-
else
|
|
115
|
+
if (identifier.startsWith("t_group_")) {
|
|
116
|
+
buckets.group.push(identifier);
|
|
117
|
+
} else if (pseudoNames.some((name) => key.endsWith(`-${name}`))) {
|
|
118
|
+
buckets.pseudo.push(identifier);
|
|
119
|
+
} else if (css2.includes(".t_")) {
|
|
120
|
+
buckets.theme.push(identifier);
|
|
121
|
+
} else if ([...mediaNames].some((name) => key.endsWith(`-${name}`))) {
|
|
122
|
+
buckets.media.push(identifier);
|
|
123
|
+
} else {
|
|
124
|
+
buckets.normal.push(identifier);
|
|
125
|
+
}
|
|
118
126
|
}
|
|
119
127
|
const orderedIdentifiers = [
|
|
120
128
|
...buckets.group,
|
|
@@ -134,17 +142,28 @@ function extractedStyleArtifacts(split, props, config, includeRuntimeBase = true
|
|
|
134
142
|
css
|
|
135
143
|
};
|
|
136
144
|
}
|
|
137
|
-
function
|
|
145
|
+
function spreadNonStyleReplacement(form, entry, isPropIgnored, rewriteProp) {
|
|
146
|
+
if (entry.kind !== "spread" || entry.value.kind !== "static" || !staticObject(entry.value.value)) {
|
|
147
|
+
return "";
|
|
148
|
+
}
|
|
149
|
+
const nonStyleEntries = Object.entries(entry.value.value).filter(([key]) => !isPropIgnored(key)).map(([key, value]) => rewriteProp(key, value));
|
|
150
|
+
if (nonStyleEntries.length === 0) return "";
|
|
151
|
+
const objectSource = `{ ${nonStyleEntries.map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`).join(", ")} }`;
|
|
152
|
+
return form === "jsx" ? `{...${objectSource}}` : `...${objectSource}`;
|
|
153
|
+
}
|
|
154
|
+
function compiledPropsEdits(input, styleEntries, replacement, spreadReplacement) {
|
|
138
155
|
const propsSpan = input.element.propsSpan;
|
|
139
156
|
if (!propsSpan) return null;
|
|
140
157
|
const original = input.source.slice(propsSpan.start, propsSpan.end);
|
|
141
158
|
const trimmed = original.trim();
|
|
142
|
-
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {
|
|
160
|
+
return [{
|
|
161
|
+
start: propsSpan.start,
|
|
162
|
+
end: propsSpan.end,
|
|
163
|
+
content: `{ ${replacement} }`,
|
|
164
|
+
origin: propsSpan
|
|
165
|
+
}];
|
|
166
|
+
}
|
|
148
167
|
if (styleEntries.length === 0) {
|
|
149
168
|
const close = original.lastIndexOf("}");
|
|
150
169
|
const separator = original.slice(1, close).trim() ? ", " : " ";
|
|
@@ -160,19 +179,22 @@ function compiledPropsEdits(input, styleEntries, replacement) {
|
|
|
160
179
|
for (const [index, entry] of styleEntries.entries()) {
|
|
161
180
|
let start = entry.span.start;
|
|
162
181
|
let end = entry.span.end;
|
|
182
|
+
const nonStyle = spreadReplacement?.(entry) ?? "";
|
|
163
183
|
if (index === 0) {
|
|
184
|
+
const content = [replacement, nonStyle].filter(Boolean).join(", ");
|
|
164
185
|
edits.push({
|
|
165
186
|
start,
|
|
166
187
|
end,
|
|
167
|
-
content
|
|
188
|
+
content,
|
|
168
189
|
origin: entry.span
|
|
169
190
|
});
|
|
170
191
|
continue;
|
|
171
192
|
}
|
|
172
193
|
let cursor = end - propsSpan.start;
|
|
173
194
|
while (cursor < original.length - 1 && /\s/.test(original[cursor])) cursor++;
|
|
174
|
-
if (original[cursor] === ",")
|
|
175
|
-
|
|
195
|
+
if (original[cursor] === ",") {
|
|
196
|
+
end = propsSpan.start + cursor + 1;
|
|
197
|
+
} else {
|
|
176
198
|
cursor = start - propsSpan.start - 1;
|
|
177
199
|
while (cursor > 0 && /\s/.test(original[cursor])) cursor--;
|
|
178
200
|
if (original[cursor] === ",") start = propsSpan.start + cursor;
|
|
@@ -180,15 +202,18 @@ function compiledPropsEdits(input, styleEntries, replacement) {
|
|
|
180
202
|
edits.push({
|
|
181
203
|
start,
|
|
182
204
|
end,
|
|
183
|
-
content:
|
|
205
|
+
content: nonStyle,
|
|
184
206
|
origin: entry.span
|
|
185
207
|
});
|
|
186
208
|
}
|
|
187
209
|
const merged = [];
|
|
188
210
|
for (const edit of edits.sort((left, right) => left.start - right.start)) {
|
|
189
211
|
const previous = merged.at(-1);
|
|
190
|
-
if (previous && edit.start <= previous.end && !previous.content && !edit.content)
|
|
191
|
-
|
|
212
|
+
if (previous && edit.start <= previous.end && !previous.content && !edit.content) {
|
|
213
|
+
previous.end = Math.max(previous.end, edit.end);
|
|
214
|
+
} else {
|
|
215
|
+
merged.push(edit);
|
|
216
|
+
}
|
|
192
217
|
}
|
|
193
218
|
return merged;
|
|
194
219
|
}
|
|
@@ -443,7 +468,13 @@ const cssConflictFamilies = [
|
|
|
443
468
|
])
|
|
444
469
|
];
|
|
445
470
|
function cssOwnersConflict(left, right) {
|
|
446
|
-
for (const leftOwner of left)
|
|
471
|
+
for (const leftOwner of left) {
|
|
472
|
+
for (const rightOwner of right) {
|
|
473
|
+
if (leftOwner === rightOwner || cssShorthandConflicts[leftOwner]?.includes(rightOwner) || cssShorthandConflicts[rightOwner]?.includes(leftOwner) || cssConflictFamilies.some((family) => family.has(leftOwner) && family.has(rightOwner))) {
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
447
478
|
return false;
|
|
448
479
|
}
|
|
449
480
|
const runtimeEventProps = /* @__PURE__ */ new Set([
|
|
@@ -464,7 +495,9 @@ const nativePointerEventProps = /* @__PURE__ */ new Set([
|
|
|
464
495
|
"onPointerUp"
|
|
465
496
|
]);
|
|
466
497
|
function isSerializableNativeStyle(value) {
|
|
467
|
-
if (value == null || typeof value === "number" || typeof value === "boolean")
|
|
498
|
+
if (value == null || typeof value === "number" || typeof value === "boolean") {
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
468
501
|
if (typeof value === "string") return true;
|
|
469
502
|
if (Array.isArray(value)) return value.every(isSerializableNativeStyle);
|
|
470
503
|
if (!staticObject(value)) return false;
|
|
@@ -475,7 +508,9 @@ function isSerializableNativeStyle(value) {
|
|
|
475
508
|
function unusedIdentifier(source, base) {
|
|
476
509
|
let candidate = base;
|
|
477
510
|
let suffix = 0;
|
|
478
|
-
while (new RegExp(`\\b${candidate}\\b`).test(source))
|
|
511
|
+
while (new RegExp(`\\b${candidate}\\b`).test(source)) {
|
|
512
|
+
candidate = `${base}${++suffix}`;
|
|
513
|
+
}
|
|
479
514
|
return candidate;
|
|
480
515
|
}
|
|
481
516
|
const VIEW_WRAPPER_PROPS = /^(aria-|accessibilityState$|accessibilityValue$|id$|tabIndex$|nativeID$)/;
|
|
@@ -509,7 +544,9 @@ function nativeDOMProps(input, tag) {
|
|
|
509
544
|
const entries = input.element.entries.filter((entry) => entry.kind === "prop");
|
|
510
545
|
const names = new Set(entries.map((entry) => entry.name));
|
|
511
546
|
if (names.has("ref") || tag === "br") additions.push(["__tag", JSON.stringify(tag)]);
|
|
512
|
-
if (import_dom.TAGS[tag].backing === "text" || import_dom.TAGS[tag].backing === "textinput")
|
|
547
|
+
if (import_dom.TAGS[tag].backing === "text" || import_dom.TAGS[tag].backing === "textinput") {
|
|
548
|
+
additions.push(["__inherit", "true"]);
|
|
549
|
+
}
|
|
513
550
|
const add = (name, value) => additions.push([name, value]);
|
|
514
551
|
const consume = (entry) => consumed.push(entry);
|
|
515
552
|
for (const entry of entries) {
|
|
@@ -517,20 +554,24 @@ function nativeDOMProps(input, tag) {
|
|
|
517
554
|
const attribute = (Object.hasOwn(import_dom.ATTRIBUTES, entry.name) ? import_dom.ATTRIBUTES[entry.name] : void 0) ?? (entry.name.startsWith("data-") ? import_dom.ATTRIBUTES["data-*"] : void 0);
|
|
518
555
|
const event = Object.hasOwn(import_dom.EVENTS, entry.name) ? import_dom.EVENTS[entry.name] : void 0;
|
|
519
556
|
if (event) {
|
|
520
|
-
if (event.native === "none")
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
557
|
+
if (event.native === "none") {
|
|
558
|
+
return {
|
|
559
|
+
consumed,
|
|
560
|
+
edits,
|
|
561
|
+
additions,
|
|
562
|
+
diagnostic: `${entry.name} has no native DOM event equivalent`,
|
|
563
|
+
diagnosticSpan: entry.span
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
if (entry.name === "onKeyDown" && tag !== "input" && tag !== "textarea") {
|
|
567
|
+
return {
|
|
568
|
+
consumed,
|
|
569
|
+
edits,
|
|
570
|
+
additions,
|
|
571
|
+
diagnostic: `onKeyDown requires a native text-entry control`,
|
|
572
|
+
diagnosticSpan: entry.span
|
|
573
|
+
};
|
|
574
|
+
}
|
|
534
575
|
if ([
|
|
535
576
|
"onClick",
|
|
536
577
|
"onLoad",
|
|
@@ -538,7 +579,9 @@ function nativeDOMProps(input, tag) {
|
|
|
538
579
|
"onChange",
|
|
539
580
|
"onInput",
|
|
540
581
|
"onKeyDown"
|
|
541
|
-
].includes(entry.name))
|
|
582
|
+
].includes(entry.name)) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
542
585
|
if (event.nativeProp) {
|
|
543
586
|
const edit2 = renamedPropEdit(input, entry, event.nativeProp);
|
|
544
587
|
if (edit2) edits.push(edit2);
|
|
@@ -547,24 +590,28 @@ function nativeDOMProps(input, tag) {
|
|
|
547
590
|
}
|
|
548
591
|
if (!attribute || attribute.native === "none" || entry.name === "style") continue;
|
|
549
592
|
if (DOM_STYLE_ATTRIBUTES.has(entry.name)) {
|
|
550
|
-
if (entry.value.kind !== "static")
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
593
|
+
if (entry.value.kind !== "static") {
|
|
594
|
+
return {
|
|
595
|
+
consumed,
|
|
596
|
+
edits,
|
|
597
|
+
additions,
|
|
598
|
+
diagnostic: `html.${tag} ${entry.name} must be statically known for native lowering`,
|
|
599
|
+
diagnosticSpan: entry.span
|
|
600
|
+
};
|
|
601
|
+
}
|
|
557
602
|
consume(entry);
|
|
558
603
|
continue;
|
|
559
604
|
}
|
|
560
605
|
if (entry.name === "hidden") {
|
|
561
|
-
if (entry.value.kind !== "static")
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
606
|
+
if (entry.value.kind !== "static") {
|
|
607
|
+
return {
|
|
608
|
+
consumed,
|
|
609
|
+
edits,
|
|
610
|
+
additions,
|
|
611
|
+
diagnostic: `html.${tag} hidden must be statically known for native lowering`,
|
|
612
|
+
diagnosticSpan: entry.span
|
|
613
|
+
};
|
|
614
|
+
}
|
|
568
615
|
consume(entry);
|
|
569
616
|
continue;
|
|
570
617
|
}
|
|
@@ -590,18 +637,22 @@ function nativeDOMProps(input, tag) {
|
|
|
590
637
|
}
|
|
591
638
|
if (entry.name === "type") {
|
|
592
639
|
consume(entry);
|
|
593
|
-
if (tag === "input" && entry.value.kind !== "static")
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
640
|
+
if (tag === "input" && entry.value.kind !== "static") {
|
|
641
|
+
return {
|
|
642
|
+
consumed,
|
|
643
|
+
edits,
|
|
644
|
+
additions,
|
|
645
|
+
diagnostic: `html.input type must be statically known for native lowering`,
|
|
646
|
+
diagnosticSpan: entry.span
|
|
647
|
+
};
|
|
648
|
+
}
|
|
600
649
|
if (tag === "input" && entry.value.kind === "static") {
|
|
601
650
|
const type = entry.value.value;
|
|
602
651
|
if (type === "password") add("secureTextEntry", "true");
|
|
603
652
|
else if (typeof type === "string" && type !== "text" && import_dom.NATIVE_INPUT_TYPES.includes(type)) {
|
|
604
|
-
if (!names.has("inputMode"))
|
|
653
|
+
if (!names.has("inputMode")) {
|
|
654
|
+
add("inputMode", JSON.stringify(type === "number" ? "numeric" : type));
|
|
655
|
+
}
|
|
605
656
|
}
|
|
606
657
|
}
|
|
607
658
|
continue;
|
|
@@ -630,7 +681,9 @@ function nativeDOMProps(input, tag) {
|
|
|
630
681
|
const edit = renamedPropEdit(input, entry, nativeProp);
|
|
631
682
|
if (edit) edits.push(edit);
|
|
632
683
|
}
|
|
633
|
-
for (const [name, values] of nested)
|
|
684
|
+
for (const [name, values] of nested) {
|
|
685
|
+
add(name, `{ ${values.map(([key, value]) => `${key}: ${value}`).join(", ")} }`);
|
|
686
|
+
}
|
|
634
687
|
if (!names.has("role") && import_dom.TAGS[tag].role) add("role", JSON.stringify(import_dom.TAGS[tag].role));
|
|
635
688
|
if (tag === "textarea") add("multiline", "true");
|
|
636
689
|
return {
|
|
@@ -649,15 +702,19 @@ function webDOMProps(input, tag) {
|
|
|
649
702
|
const edit = renamedPropEdit(input, entry, "htmlFor");
|
|
650
703
|
if (edit) edits.push(edit);
|
|
651
704
|
}
|
|
652
|
-
if (entry.name === "role" && entry.value.kind === "static" && entry.value.value === "none")
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
705
|
+
if (entry.name === "role" && entry.value.kind === "static" && entry.value.value === "none") {
|
|
706
|
+
edits.push({
|
|
707
|
+
start: entry.value.span.start,
|
|
708
|
+
end: entry.value.span.end,
|
|
709
|
+
content: JSON.stringify("presentation"),
|
|
710
|
+
origin: entry.value.span
|
|
711
|
+
});
|
|
712
|
+
}
|
|
658
713
|
}
|
|
659
714
|
if (tag === "button" && !names.has("type")) additions.push(["type", "\"button\""]);
|
|
660
|
-
if ((tag === "input" || tag === "textarea") && !names.has("dir"))
|
|
715
|
+
if ((tag === "input" || tag === "textarea") && !names.has("dir")) {
|
|
716
|
+
additions.push(["dir", "\"auto\""]);
|
|
717
|
+
}
|
|
661
718
|
return {
|
|
662
719
|
edits,
|
|
663
720
|
additions
|
|
@@ -667,7 +724,8 @@ function createTamaguiCompilerHost(options) {
|
|
|
667
724
|
const platform = options.target === "native" ? "native" : "web";
|
|
668
725
|
const core = (0, import_requireTamaguiCore.requireTamaguiCore)(platform);
|
|
669
726
|
const firstThemeName = Object.keys(options.tamaguiConfig.themes ?? {})[0] ?? "";
|
|
670
|
-
const
|
|
727
|
+
const firstTheme = options.tamaguiConfig.themes?.[firstThemeName] ?? {};
|
|
728
|
+
const theme = firstTheme;
|
|
671
729
|
const modifierRegistry = (0, import_tooling.createModifierRegistry)({
|
|
672
730
|
mediaNames: options.tamaguiConfig.media ?? {},
|
|
673
731
|
themeNames: options.tamaguiConfig.themes ?? {}
|
|
@@ -704,17 +762,25 @@ function createTamaguiCompilerHost(options) {
|
|
|
704
762
|
resolvedPayloads.push(payload);
|
|
705
763
|
continue;
|
|
706
764
|
}
|
|
707
|
-
if (transition.value.entries.length !== 1 || transition.value.entries[0].timing.type !== "preset")
|
|
765
|
+
if (transition.value.entries.length !== 1 || transition.value.entries[0].timing.type !== "preset") {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
708
768
|
const preset = transitionPresets[transition.value.entries[0].timing.name];
|
|
709
769
|
if (typeof preset !== "string") return null;
|
|
710
770
|
const parsedPreset = (0, import_tooling.parseTransition)(preset);
|
|
711
|
-
if (!parsedPreset.ok || parsedPreset.value.kind !== "transition" || parsedPreset.value.entries.length !== 1 || parsedPreset.value.entries[0].property !== "all" || parsedPreset.value.entries[0].timing.type !== "css")
|
|
771
|
+
if (!parsedPreset.ok || parsedPreset.value.kind !== "transition" || parsedPreset.value.entries.length !== 1 || parsedPreset.value.entries[0].property !== "all" || parsedPreset.value.entries[0].timing.type !== "css") {
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
712
774
|
resolvedPayloads.push(`all ${preset}`);
|
|
713
775
|
}
|
|
714
776
|
let payloadIndex = 0;
|
|
715
777
|
const resolved = [];
|
|
716
|
-
if (program.value.base !== null)
|
|
717
|
-
|
|
778
|
+
if (program.value.base !== null) {
|
|
779
|
+
resolved.push(resolvedPayloads[payloadIndex++]);
|
|
780
|
+
}
|
|
781
|
+
for (const clause of program.value.clauses) {
|
|
782
|
+
resolved.push(`${clause.modifiers.join(":")}:${resolvedPayloads[payloadIndex++]}`);
|
|
783
|
+
}
|
|
718
784
|
return resolved.join(" ");
|
|
719
785
|
};
|
|
720
786
|
const modulesById = new Map(options.componentModules.map((module2) => [module2.resolvedId, module2.moduleName]));
|
|
@@ -724,7 +790,8 @@ function createTamaguiCompilerHost(options) {
|
|
|
724
790
|
const identity = element.component.provenance;
|
|
725
791
|
if (!identity) return null;
|
|
726
792
|
const moduleName = modulesById.get(identity.resolvedId);
|
|
727
|
-
const
|
|
793
|
+
const component = moduleName ? componentsByModule.get(moduleName) : void 0;
|
|
794
|
+
const info = component?.nameToInfo[identity.importedName];
|
|
728
795
|
return info ? {
|
|
729
796
|
key: componentKey(identity.resolvedId, identity.importedName),
|
|
730
797
|
staticConfig: normalizeStaticConfig(info.staticConfig),
|
|
@@ -734,9 +801,12 @@ function createTamaguiCompilerHost(options) {
|
|
|
734
801
|
const domStaticConfig = (element) => {
|
|
735
802
|
const identity = element.component.provenance;
|
|
736
803
|
const tag = element.component.name;
|
|
737
|
-
if (identity?.importedName !== "html" || !DOM_FRONTENDS.has(identity.specifier) || !Object.hasOwn(import_dom.TAGS, tag))
|
|
804
|
+
if (identity?.importedName !== "html" || !DOM_FRONTENDS.has(identity.specifier) || !Object.hasOwn(import_dom.TAGS, tag)) {
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
738
807
|
const row = import_dom.TAGS[tag];
|
|
739
|
-
const
|
|
808
|
+
const textLike = row.backing === "text" || row.backing === "textinput";
|
|
809
|
+
const base = (textLike ? core.Text : core.View)?.staticConfig;
|
|
740
810
|
if (!base) return null;
|
|
741
811
|
const platformDefaults = platform === "web" ? {
|
|
742
812
|
...import_dom.DISPLAY_WEB_RESET[row.display],
|
|
@@ -840,7 +910,9 @@ function createTamaguiCompilerHost(options) {
|
|
|
840
910
|
return name in import_helpers.stylePropsAll && !(0, import_web.isValidStyleKey)(name, validStyles, staticConfig.accept);
|
|
841
911
|
};
|
|
842
912
|
const directStyleName = (name, component) => {
|
|
843
|
-
if (compilerStyleProps.has(name) || name === "style")
|
|
913
|
+
if (compilerStyleProps.has(name) || name === "style") {
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
844
916
|
const staticConfig = component.staticConfig;
|
|
845
917
|
if (staticConfig.variants?.[name]) return null;
|
|
846
918
|
const expanded = options.tamaguiConfig.shorthands?.[name] ?? name;
|
|
@@ -848,11 +920,15 @@ function createTamaguiCompilerHost(options) {
|
|
|
848
920
|
};
|
|
849
921
|
const resolveSplitStyles = (props, staticConfig, animationDriver, displayName) => {
|
|
850
922
|
const previousStatic = process.env.IS_STATIC;
|
|
851
|
-
const previousTarget =
|
|
852
|
-
if (platform === "native")
|
|
853
|
-
|
|
923
|
+
const previousTarget = process.env.TAMAGUI_TARGET;
|
|
924
|
+
if (platform === "native") {
|
|
925
|
+
process.env.IS_STATIC = "is_static";
|
|
926
|
+
} else {
|
|
927
|
+
delete process.env.IS_STATIC;
|
|
928
|
+
}
|
|
854
929
|
process.env.TAMAGUI_TARGET = platform;
|
|
855
930
|
try {
|
|
931
|
+
core.prepareStyleStaticConfig(staticConfig);
|
|
856
932
|
return core.getSplitStyles(props, staticConfig, theme, firstThemeName, componentState, {
|
|
857
933
|
resolveValues: platform === "native" ? "except-theme" : "variable",
|
|
858
934
|
noClass: platform === "native",
|
|
@@ -862,7 +938,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
862
938
|
} finally {
|
|
863
939
|
if (previousStatic === void 0) delete process.env.IS_STATIC;
|
|
864
940
|
else process.env.IS_STATIC = previousStatic;
|
|
865
|
-
if (previousTarget === void 0) delete
|
|
941
|
+
if (previousTarget === void 0) delete process.env.TAMAGUI_TARGET;
|
|
866
942
|
else process.env.TAMAGUI_TARGET = previousTarget;
|
|
867
943
|
}
|
|
868
944
|
};
|
|
@@ -878,7 +954,9 @@ function createTamaguiCompilerHost(options) {
|
|
|
878
954
|
const split = resolveSplitStyles({ [name]: value }, partialStaticConfig(staticConfig));
|
|
879
955
|
if (!split) return null;
|
|
880
956
|
const inlineStyle = split.viewProps?.style;
|
|
881
|
-
if (staticObject(inlineStyle) &&
|
|
957
|
+
if (staticObject(inlineStyle) && Object.keys(inlineStyle).length > 0) {
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
882
960
|
const owners = new Set(Object.keys(split.classNames ?? {}));
|
|
883
961
|
for (const styleObject of Object.values(split.rulesToInsert ?? {})) {
|
|
884
962
|
const property = styleObject?.[import_helpers.StyleObjectProperty];
|
|
@@ -887,7 +965,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
887
965
|
return owners.size > 0 ? owners : null;
|
|
888
966
|
};
|
|
889
967
|
const dynamicStyleOwners = (name, staticConfig) => {
|
|
890
|
-
const
|
|
968
|
+
const probeValue = name === "transform" ? [{ scale: 1 }] : name === "transformMatrix" ? [
|
|
891
969
|
1,
|
|
892
970
|
0,
|
|
893
971
|
0,
|
|
@@ -897,7 +975,8 @@ function createTamaguiCompilerHost(options) {
|
|
|
897
975
|
] : name === "shadowOffset" ? {
|
|
898
976
|
width: 0,
|
|
899
977
|
height: 0
|
|
900
|
-
} : name === "shadowColor" ? "black" : name === "border" || name === "outline" ? "0 solid transparent" : name === "position" ? "relative" : name === "objectFit" ? "contain" : 0
|
|
978
|
+
} : name === "shadowColor" ? "black" : name === "border" || name === "outline" ? "0 solid transparent" : name === "position" ? "relative" : name === "objectFit" ? "contain" : 0;
|
|
979
|
+
const owners = styleOwners(name, probeValue, staticConfig);
|
|
901
980
|
if (!owners || name !== "flex") return owners;
|
|
902
981
|
const shorthandOwners = styleOwners(name, "0 1 auto", staticConfig);
|
|
903
982
|
if (!shorthandOwners) return null;
|
|
@@ -918,28 +997,35 @@ function createTamaguiCompilerHost(options) {
|
|
|
918
997
|
] : ["bailed"];
|
|
919
998
|
const why = result.ok ? flattened ? "Static styles were lowered and the component was flattened to a host element." : "Static styles were lowered while the Tamagui component remained at runtime." : result.bailout.message;
|
|
920
999
|
const styles = styleEntries.map((entry) => {
|
|
921
|
-
if (!result.ok)
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1000
|
+
if (!result.ok) {
|
|
1001
|
+
return {
|
|
1002
|
+
prop: entry.name,
|
|
1003
|
+
tier: "bailed",
|
|
1004
|
+
runtime: true,
|
|
1005
|
+
why: `${result.bailout.message}. The Tamagui runtime resolved this prop.`
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
927
1008
|
const edited = result.edits.some((edit) => edit.start < entry.span.end && edit.end > entry.span.start);
|
|
928
|
-
if (!flattened && !edited)
|
|
929
|
-
|
|
930
|
-
tier: "bailed",
|
|
931
|
-
runtime: true,
|
|
932
|
-
why: "This prop remained for Tamagui runtime resolution."
|
|
933
|
-
};
|
|
934
|
-
if (entry.value.kind === "static") {
|
|
935
|
-
const split = resolveSplitStyles({ [entry.name]: entry.value.value }, partialStaticConfig(component.staticConfig));
|
|
936
|
-
if (!Boolean(split && (Object.keys(split.classNames ?? {}).length > 0 || Object.keys(split.rulesToInsert ?? {}).length > 0 || staticObject(split.style) && Object.keys(split.style).length > 0 || staticObject(split.viewProps?.style) && Object.keys(split.viewProps.style).length > 0))) return {
|
|
1009
|
+
if (!flattened && !edited) {
|
|
1010
|
+
return {
|
|
937
1011
|
prop: entry.name,
|
|
938
|
-
tier:
|
|
939
|
-
|
|
940
|
-
why:
|
|
1012
|
+
tier: "bailed",
|
|
1013
|
+
runtime: true,
|
|
1014
|
+
why: "This prop remained for Tamagui runtime resolution."
|
|
941
1015
|
};
|
|
942
1016
|
}
|
|
1017
|
+
if (entry.value.kind === "static") {
|
|
1018
|
+
const split = resolveSplitStyles({ [entry.name]: entry.value.value }, partialStaticConfig(component.staticConfig));
|
|
1019
|
+
const hasOutput = Boolean(split && (Object.keys(split.classNames ?? {}).length > 0 || Object.keys(split.rulesToInsert ?? {}).length > 0 || staticObject(split.style) && Object.keys(split.style).length > 0 || staticObject(split.viewProps?.style) && Object.keys(split.viewProps.style).length > 0));
|
|
1020
|
+
if (!hasOutput) {
|
|
1021
|
+
return {
|
|
1022
|
+
prop: entry.name,
|
|
1023
|
+
tier: flattened ? "flattened" : "lowered",
|
|
1024
|
+
dropped: true,
|
|
1025
|
+
why: `No ${platform} style output was produced for this prop.`
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
943
1029
|
return {
|
|
944
1030
|
prop: entry.name,
|
|
945
1031
|
tier: flattened ? "flattened" : "lowered",
|
|
@@ -964,68 +1050,94 @@ function createTamaguiCompilerHost(options) {
|
|
|
964
1050
|
resolveComponent: resolve,
|
|
965
1051
|
isStyleProp,
|
|
966
1052
|
canLowerDynamicStyleProp(name, component, valueKind) {
|
|
967
|
-
if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component))
|
|
1053
|
+
if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
|
|
1054
|
+
return true;
|
|
1055
|
+
}
|
|
968
1056
|
return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
|
|
969
1057
|
},
|
|
970
1058
|
developmentDebugInstrumentation,
|
|
971
1059
|
lowerCandidate(input) {
|
|
972
1060
|
const component = input.component;
|
|
973
|
-
if (!component.canFlatten)
|
|
1061
|
+
if (!component.canFlatten) {
|
|
1062
|
+
const reason = component.staticConfig.acceptsClassName === false ? `${component.key} does not accept className` : component.staticConfig.neverFlatten ? `${component.key} is never flattened (behavior HOC)` : `${component.key} provides a styled context`;
|
|
1063
|
+
return bailout(input, "local/unsupported-target", reason, input.element.span, { rule: 6 });
|
|
1064
|
+
}
|
|
974
1065
|
if (options.zeroRuntime) {
|
|
975
1066
|
const spread = input.element.entries.find((entry) => entry.kind === "spread");
|
|
976
|
-
if (spread)
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1067
|
+
if (spread) {
|
|
1068
|
+
return bailout(input, "local/unsafe-style-spread", "Zero-runtime rejects prop spreads", spread.span, {
|
|
1069
|
+
rule: 1,
|
|
1070
|
+
message: (0, import_compiler_core.zeroRuleMessage)(1, { component: input.element.component.name })
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
980
1073
|
}
|
|
981
1074
|
const props = {};
|
|
982
1075
|
for (const entry of input.element.entries) {
|
|
983
1076
|
if (entry.kind === "child" || entry.value.kind !== "static") continue;
|
|
984
1077
|
if (entry.kind === "spread") {
|
|
985
|
-
if (!staticObject(entry.value.value))
|
|
1078
|
+
if (!staticObject(entry.value.value)) {
|
|
1079
|
+
return bailout(input, "local/unsafe-style-spread", "Static spread did not materialize to an object", entry.span);
|
|
1080
|
+
}
|
|
986
1081
|
Object.assign(props, entry.value.value);
|
|
987
|
-
} else
|
|
1082
|
+
} else {
|
|
1083
|
+
props[entry.name] = entry.value.value;
|
|
1084
|
+
}
|
|
988
1085
|
}
|
|
989
1086
|
const disableOptimizationEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "disableOptimization");
|
|
990
|
-
if (disableOptimizationEntry || Object.hasOwn(props, "disableOptimization"))
|
|
1087
|
+
if (disableOptimizationEntry || Object.hasOwn(props, "disableOptimization")) {
|
|
1088
|
+
return bailout(input, "local/unsupported-target", "disableOptimization keeps the component on the runtime path", disableOptimizationEntry?.span);
|
|
1089
|
+
}
|
|
991
1090
|
if (component.domTag && props.hidden) props.display = "none";
|
|
992
1091
|
if (component.domTag && platform === "native") {
|
|
993
|
-
for (const [name, styleKey] of DOM_STYLE_ATTRIBUTES)
|
|
994
|
-
|
|
995
|
-
|
|
1092
|
+
for (const [name, styleKey] of DOM_STYLE_ATTRIBUTES) {
|
|
1093
|
+
if (name in props) {
|
|
1094
|
+
props[styleKey] = props[name];
|
|
1095
|
+
delete props[name];
|
|
1096
|
+
}
|
|
996
1097
|
}
|
|
997
1098
|
}
|
|
998
|
-
if (platform === "native" && component.domTag === "input" && typeof props.type === "string" && !import_dom.NATIVE_INPUT_TYPES.includes(props.type))
|
|
1099
|
+
if (platform === "native" && component.domTag === "input" && typeof props.type === "string" && !import_dom.NATIVE_INPUT_TYPES.includes(props.type)) {
|
|
1100
|
+
return bailout(input, "local/unsupported-target", `input type ${props.type} has no native text-entry control`);
|
|
1101
|
+
}
|
|
999
1102
|
const dynamicStyleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && (entry.value.kind === "bailout" || entry.value.kind === "conditional") && isStyleProp(entry.name, component));
|
|
1000
1103
|
{
|
|
1001
1104
|
const needsRuntimeMapping = (name) => runtimeEventProps.has(name) || platform === "native" && !component.domTag && nativePointerEventProps.has(name);
|
|
1002
1105
|
const directRuntimeEvent = input.element.entries.find((entry) => entry.kind === "prop" && needsRuntimeMapping(entry.name));
|
|
1003
1106
|
const runtimeEvent = directRuntimeEvent?.kind === "prop" ? directRuntimeEvent.name : Object.keys(props).find(needsRuntimeMapping);
|
|
1004
|
-
if (runtimeEvent)
|
|
1107
|
+
if (runtimeEvent) {
|
|
1108
|
+
return bailout(input, "local/unsupported-target", `${runtimeEvent} requires Tamagui runtime event mapping`);
|
|
1109
|
+
}
|
|
1005
1110
|
}
|
|
1006
1111
|
const animationDefaultProps = core.getDefaultProps(component.staticConfig) ?? {};
|
|
1007
1112
|
const animationProps = core.mergeProps(animationDefaultProps, props);
|
|
1008
1113
|
const animationNames = /* @__PURE__ */ new Set([...input.element.entries.flatMap((entry) => entry.kind === "prop" && runtimeAnimationProps.has(entry.name) ? [entry.name] : []), ...Object.keys(animationProps).filter((name) => runtimeAnimationProps.has(name) && animationProps[name] !== void 0)]);
|
|
1009
1114
|
const animateOnlyEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "animateOnly");
|
|
1010
|
-
if (animationNames.has("animateOnly"))
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1115
|
+
if (animationNames.has("animateOnly")) {
|
|
1116
|
+
return bailout(input, "local/unsupported-target", "Animated candidates remain on the runtime path", animateOnlyEntry?.span, {
|
|
1117
|
+
rule: 5,
|
|
1118
|
+
message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: animateOnlyEntry ? `animateOnly on ${input.element.component.name}` : `animateOnly in the styled() definition of ${input.element.component.name}` })
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1014
1121
|
const transitionEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "transition");
|
|
1015
1122
|
const animatedBy = typeof animationProps.animatedBy === "string" ? animationProps.animatedBy.trim() : null;
|
|
1016
1123
|
const namedAnimationDriver = animatedBy === null ? null : options.tamaguiConfig.animationDrivers?.[animatedBy];
|
|
1017
|
-
const
|
|
1124
|
+
const namedCssAnimationDriver = platform === "web" && namedAnimationDriver && !namedAnimationDriver.isStub && namedAnimationDriver.outputStyle === "css" ? namedAnimationDriver : null;
|
|
1125
|
+
const cssAnimationDriver = namedCssAnimationDriver ?? (animatedBy === null || animatedBy === "default" ? configuredCssAnimationDriver : null);
|
|
1018
1126
|
const resolvedCssTransition = animationNames.has("transition") && cssAnimationDriver ? resolveStaticCssTransition(animationProps.transition, cssAnimationDriver.animations ?? {}) : null;
|
|
1019
|
-
if (resolvedCssTransition !== null)
|
|
1127
|
+
if (resolvedCssTransition !== null) {
|
|
1128
|
+
props.transition = resolvedCssTransition;
|
|
1129
|
+
}
|
|
1020
1130
|
const animatedByNeedsRuntime = animationNames.has("animatedBy") && !animationNames.has("transition") && (dynamicStyleEntries.length > 0 || Object.keys(animationProps).some((name) => name !== "animatedBy" && (isStyleProp(name, component) && typeof animationProps[name] === "string" && animationProps[name].includes(":") || name === "animationConfig" || name === "forceStyle" || name === "onTransition")));
|
|
1021
1131
|
const runtimeAnimationRequired = animationNames.has("transition") && resolvedCssTransition === null || [...animationNames].some((name) => name !== "transition" && name !== "animatedBy" && name !== "animateOnly") || animatedByNeedsRuntime;
|
|
1022
1132
|
let dynamicHostStyleProperties = null;
|
|
1023
|
-
if (platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && dynamicStyleEntries.length > 0 && !input.element.entries.some((entry) => entry.kind === "spread")) {
|
|
1133
|
+
if (platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && dynamicStyleEntries.length > 0 && !input.element.entries.some((entry) => entry.kind === "spread" && entry.value.kind !== "static")) {
|
|
1024
1134
|
const seen = /* @__PURE__ */ new Set();
|
|
1025
1135
|
const properties = [];
|
|
1026
1136
|
const dynamicOwners = /* @__PURE__ */ new Set();
|
|
1027
1137
|
for (const entry of dynamicStyleEntries) {
|
|
1028
|
-
if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional")
|
|
1138
|
+
if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional") {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1029
1141
|
const name = directStyleName(entry.name, component);
|
|
1030
1142
|
if (!name || seen.has(name)) {
|
|
1031
1143
|
properties.length = 0;
|
|
@@ -1038,11 +1150,13 @@ function createTamaguiCompilerHost(options) {
|
|
|
1038
1150
|
}
|
|
1039
1151
|
let property = null;
|
|
1040
1152
|
const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
|
|
1041
|
-
if (resolvedCssTransition !== null && (name === "opacity" || name === "scale"))
|
|
1042
|
-
|
|
1153
|
+
if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
|
|
1154
|
+
property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
|
|
1155
|
+
} else if (entry.value.kind === "bailout" && owners.size === 1 && owners.has(name)) {
|
|
1043
1156
|
const dynamic = entry.value.dynamic;
|
|
1044
|
-
if (dynamic?.type === "number")
|
|
1045
|
-
|
|
1157
|
+
if (dynamic?.type === "number") {
|
|
1158
|
+
property = `${JSON.stringify(name)}: (${expression})`;
|
|
1159
|
+
} else if (dynamic?.type === "string" && dynamic.values?.length) {
|
|
1046
1160
|
let valuesStayLiteral = true;
|
|
1047
1161
|
for (const value of dynamic.values) {
|
|
1048
1162
|
const split2 = resolveSplitStyles({ [entry.name]: value }, partialStaticConfig(component.staticConfig));
|
|
@@ -1052,7 +1166,9 @@ function createTamaguiCompilerHost(options) {
|
|
|
1052
1166
|
break;
|
|
1053
1167
|
}
|
|
1054
1168
|
}
|
|
1055
|
-
if (valuesStayLiteral)
|
|
1169
|
+
if (valuesStayLiteral) {
|
|
1170
|
+
property = `${JSON.stringify(name)}: (${expression})`;
|
|
1171
|
+
}
|
|
1056
1172
|
}
|
|
1057
1173
|
}
|
|
1058
1174
|
if (!property) {
|
|
@@ -1069,9 +1185,11 @@ function createTamaguiCompilerHost(options) {
|
|
|
1069
1185
|
if (!name) return false;
|
|
1070
1186
|
const owners = styleOwners(name, entry.value.value, component.staticConfig);
|
|
1071
1187
|
return !!owners && cssOwnersConflict(owners, dynamicOwners);
|
|
1072
|
-
}))
|
|
1188
|
+
})) {
|
|
1189
|
+
dynamicHostStyleProperties = properties;
|
|
1190
|
+
}
|
|
1073
1191
|
}
|
|
1074
|
-
const supportsWebConditionalClasses = platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && dynamicHostStyleProperties === null && dynamicStyleEntries.length
|
|
1192
|
+
const supportsWebConditionalClasses = platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && dynamicHostStyleProperties === null && dynamicStyleEntries.length > 0 && dynamicStyleEntries.every((entry) => entry.kind === "prop" && entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component));
|
|
1075
1193
|
if ("theme" in props || "themeInverse" in props) {
|
|
1076
1194
|
const themeProp = "theme" in props ? "theme" : "themeInverse";
|
|
1077
1195
|
return bailout(input, "local/unsupported-target", "Theme boundary candidates remain on the runtime path", input.element.span, {
|
|
@@ -1080,14 +1198,20 @@ function createTamaguiCompilerHost(options) {
|
|
|
1080
1198
|
});
|
|
1081
1199
|
}
|
|
1082
1200
|
const asChildEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "asChild");
|
|
1083
|
-
if (asChildEntry || Object.hasOwn(props, "asChild"))
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1201
|
+
if (asChildEntry || Object.hasOwn(props, "asChild")) {
|
|
1202
|
+
return bailout(input, "local/unsupported-target", "asChild renders a Slot, not a host view", asChildEntry?.span);
|
|
1203
|
+
}
|
|
1204
|
+
if (platform === "native" && ("group" in props || "container" in props || "containerName" in props || "containerType" in props)) {
|
|
1205
|
+
return bailout(input, "local/unsupported-target", "Native group and container providers remain on the runtime path");
|
|
1206
|
+
}
|
|
1207
|
+
if (runtimeAnimationRequired && !cssAnimationDriver) {
|
|
1208
|
+
return bailout(input, "local/unsupported-target", "Animated candidates remain on the runtime path", transitionEntry?.span, {
|
|
1209
|
+
rule: 5,
|
|
1210
|
+
message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `the animation configured on ${input.element.component.name}` })
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1089
1213
|
if (platform === "web" && (dynamicStyleEntries.length > 0 || runtimeAnimationRequired) && dynamicHostStyleProperties === null && !supportsWebConditionalClasses && component.partialRuntimeSafe) {
|
|
1090
|
-
const hasSpread = input.element.entries.some((entry) => entry.kind === "spread");
|
|
1214
|
+
const hasSpread = input.element.entries.some((entry) => entry.kind === "spread" && entry.value.kind !== "static");
|
|
1091
1215
|
const unsupportedRuntimeStyle = input.element.entries.find((entry) => entry.kind === "prop" && isStyleProp(entry.name, component) && !runtimeAnimationProps.has(entry.name) && !directStyleName(entry.name, component));
|
|
1092
1216
|
if (!hasSpread && !unsupportedRuntimeStyle) {
|
|
1093
1217
|
const dynamicOwners = /* @__PURE__ */ new Set();
|
|
@@ -1116,49 +1240,59 @@ function createTamaguiCompilerHost(options) {
|
|
|
1116
1240
|
}) : [];
|
|
1117
1241
|
if (staticStyleEntries.length > 0) {
|
|
1118
1242
|
const partialProps = {};
|
|
1119
|
-
for (const entry of staticStyleEntries)
|
|
1243
|
+
for (const entry of staticStyleEntries) {
|
|
1244
|
+
if (entry.kind === "prop" && entry.value.kind === "static") {
|
|
1245
|
+
partialProps[entry.name] = entry.value.value;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1120
1248
|
const partialSplit = resolveSplitStyles(partialProps, partialStaticConfig(component.staticConfig));
|
|
1121
1249
|
const partialInlineStyle = partialSplit?.viewProps?.style;
|
|
1122
|
-
const hasPartialInlineStyle = staticObject(partialInlineStyle) &&
|
|
1250
|
+
const hasPartialInlineStyle = staticObject(partialInlineStyle) && Object.keys(partialInlineStyle).length > 0;
|
|
1123
1251
|
if (partialSplit && !hasPartialInlineStyle) {
|
|
1124
1252
|
const artifacts2 = extractedStyleArtifacts(partialSplit, partialProps, options.tamaguiConfig, false);
|
|
1125
|
-
if (artifacts2.className)
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1253
|
+
if (artifacts2.className) {
|
|
1254
|
+
if (input.element.form !== "jsx") {
|
|
1255
|
+
const propsEdits = compiledPropsEdits(input, staticStyleEntries, objectClassName(artifacts2.className));
|
|
1256
|
+
if (propsEdits) {
|
|
1257
|
+
return {
|
|
1258
|
+
ok: true,
|
|
1259
|
+
edits: propsEdits,
|
|
1260
|
+
css: artifacts2.css,
|
|
1261
|
+
imports: [],
|
|
1262
|
+
flattened: false
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
} else {
|
|
1266
|
+
const [first2, ...rest2] = staticStyleEntries;
|
|
1267
|
+
return {
|
|
1268
|
+
ok: true,
|
|
1269
|
+
edits: [{
|
|
1270
|
+
start: first2.span.start,
|
|
1271
|
+
end: first2.span.end,
|
|
1272
|
+
content: jsxClassName(artifacts2.className),
|
|
1273
|
+
origin: first2.span
|
|
1274
|
+
}, ...rest2.map((entry) => ({
|
|
1275
|
+
start: entry.span.start,
|
|
1276
|
+
end: entry.span.end,
|
|
1277
|
+
content: "",
|
|
1278
|
+
origin: entry.span
|
|
1279
|
+
}))],
|
|
1280
|
+
css: artifacts2.css,
|
|
1281
|
+
imports: [],
|
|
1282
|
+
flattened: false
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1153
1285
|
}
|
|
1154
1286
|
}
|
|
1155
1287
|
}
|
|
1156
1288
|
}
|
|
1157
1289
|
}
|
|
1158
|
-
if (runtimeAnimationRequired)
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1290
|
+
if (runtimeAnimationRequired) {
|
|
1291
|
+
return bailout(input, "local/unsupported-target", "Animated candidates remain on the runtime path", transitionEntry?.span, {
|
|
1292
|
+
rule: 5,
|
|
1293
|
+
message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `the animation configured on ${input.element.component.name}` })
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1162
1296
|
const supportsNativeDynamicStyles = platform === "native" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && dynamicStyleEntries.every((entry) => entry.kind === "prop" && (directStyleName(entry.name, component) === "opacity" || entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component)));
|
|
1163
1297
|
if (dynamicStyleEntries.length > 0 && dynamicHostStyleProperties === null && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
|
|
1164
1298
|
const entry = dynamicStyleEntries[0];
|
|
@@ -1167,18 +1301,59 @@ function createTamaguiCompilerHost(options) {
|
|
|
1167
1301
|
const staticDefaultProps = core.getDefaultProps(component.staticConfig) ?? {};
|
|
1168
1302
|
const defaultProps = platform === "web" && !component.staticConfig.isText && options.tamaguiConfig.settings.defaultPosition === "relative" && staticDefaultProps.position === void 0 ? core.mergeProps({ position: "relative" }, staticDefaultProps) : staticDefaultProps;
|
|
1169
1303
|
let completeProps = core.mergeProps(defaultProps, props);
|
|
1170
|
-
if (platform === "native" && component.domTag && props.display === "flex")
|
|
1304
|
+
if (platform === "native" && component.domTag && props.display === "flex") {
|
|
1305
|
+
completeProps = core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), props);
|
|
1306
|
+
}
|
|
1307
|
+
const propsForConditional = (target, value) => {
|
|
1308
|
+
const branchProps = {};
|
|
1309
|
+
for (const entry of input.element.entries) {
|
|
1310
|
+
if (entry === target) {
|
|
1311
|
+
branchProps[target.name] = value;
|
|
1312
|
+
continue;
|
|
1313
|
+
}
|
|
1314
|
+
if (entry.kind === "child" || entry.value.kind !== "static") continue;
|
|
1315
|
+
if (entry.kind === "spread") {
|
|
1316
|
+
if (staticObject(entry.value.value)) Object.assign(branchProps, entry.value.value);
|
|
1317
|
+
} else {
|
|
1318
|
+
branchProps[entry.name] = entry.value.value;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
if (component.domTag && branchProps.hidden) branchProps.display = "none";
|
|
1322
|
+
if (resolvedCssTransition !== null) {
|
|
1323
|
+
branchProps.transition = resolvedCssTransition;
|
|
1324
|
+
}
|
|
1325
|
+
if (component.domTag && platform === "native") {
|
|
1326
|
+
for (const [name, styleKey] of DOM_STYLE_ATTRIBUTES) {
|
|
1327
|
+
if (name in branchProps) {
|
|
1328
|
+
branchProps[styleKey] = branchProps[name];
|
|
1329
|
+
delete branchProps[name];
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
const branchCompleteProps = platform === "native" && component.domTag && branchProps.display === "flex" ? core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), branchProps) : core.mergeProps(defaultProps, branchProps);
|
|
1334
|
+
return {
|
|
1335
|
+
branchProps,
|
|
1336
|
+
branchCompleteProps
|
|
1337
|
+
};
|
|
1338
|
+
};
|
|
1171
1339
|
if (platform === "native") {
|
|
1172
1340
|
const isClauseValue = (name, value) => isStyleProp(name, component) && (typeof value === "string" && flatClausePattern.test(value) || isClauseObjectValue(value));
|
|
1173
1341
|
const defaultVariants = component.staticConfig.defaultVariants ?? {};
|
|
1174
|
-
|
|
1342
|
+
const carriesClause = Object.entries(completeProps).some(([name, value]) => isClauseValue(name, value)) || Object.entries(component.staticConfig.variants ?? {}).some(([variantName, definitions]) => (completeProps[variantName] !== void 0 || defaultVariants[variantName] !== void 0) && staticObject(definitions) && Object.values(definitions).some((definition) => staticObject(definition) && Object.entries(definition).some(([name, value]) => isClauseValue(name, value)))) || (component.staticConfig.compoundVariants ?? []).some((compound) => staticObject(compound) && staticObject(compound.style) && Object.entries(compound.style).some(([name, value]) => isClauseValue(name, value)));
|
|
1343
|
+
if (carriesClause) {
|
|
1344
|
+
return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
|
|
1345
|
+
}
|
|
1175
1346
|
}
|
|
1176
1347
|
const split = resolveSplitStyles(completeProps, component.staticConfig, cssAnimationDriver, component.displayName);
|
|
1177
|
-
if (!split)
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1348
|
+
if (!split) {
|
|
1349
|
+
return bailout(input, "local/style-resolution-failed", "getSplitStyles returned no static result");
|
|
1350
|
+
}
|
|
1351
|
+
if (split.programLifecycleStyleKeys?.enter?.size || split.programLifecycleStyleKeys?.exit?.size) {
|
|
1352
|
+
return bailout(input, "local/unsupported-target", "Lifecycle value programs remain on the runtime path", input.element.span, {
|
|
1353
|
+
rule: 5,
|
|
1354
|
+
message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `an enter or exit style program on ${input.element.component.name}` })
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1182
1357
|
const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
|
|
1183
1358
|
const flatTag = component.domTag ?? (typeof props.render === "string" ? props.render : typeof defaultProps.render === "string" ? defaultProps.render : component.staticConfig.isText ? "span" : "div");
|
|
1184
1359
|
const tagEdits = [input.element.component.span, input.element.component.closingSpan].filter((span) => !!span).map((span) => ({
|
|
@@ -1187,7 +1362,17 @@ function createTamaguiCompilerHost(options) {
|
|
|
1187
1362
|
content: input.element.form === "jsx" ? flatTag : JSON.stringify(flatTag),
|
|
1188
1363
|
origin: span
|
|
1189
1364
|
}));
|
|
1190
|
-
|
|
1365
|
+
const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component);
|
|
1366
|
+
const spreadReplacement = (form, entry) => spreadNonStyleReplacement(form, entry, isPropIgnored, (name, value) => {
|
|
1367
|
+
if (platform !== "web") return [name, value];
|
|
1368
|
+
if (name === "testID") return ["data-testid", value];
|
|
1369
|
+
if (component.domTag && name === "for") return ["htmlFor", value];
|
|
1370
|
+
if (component.domTag && name === "role" && value === "none") {
|
|
1371
|
+
return ["role", "presentation"];
|
|
1372
|
+
}
|
|
1373
|
+
return [name, value];
|
|
1374
|
+
});
|
|
1375
|
+
let styleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && (isStyleProp(entry.name, component) || isInvalidHostStyleProp(entry.name, component)) || entry.kind === "spread" && entry.value.kind === "static" && staticObject(entry.value.value) && Object.keys(entry.value.value).some((name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component)));
|
|
1191
1376
|
let invalidHostStyle;
|
|
1192
1377
|
for (const entry of input.element.entries) {
|
|
1193
1378
|
if (entry.kind === "prop") {
|
|
@@ -1211,7 +1396,15 @@ function createTamaguiCompilerHost(options) {
|
|
|
1211
1396
|
}
|
|
1212
1397
|
}
|
|
1213
1398
|
}
|
|
1214
|
-
if (invalidHostStyle)
|
|
1399
|
+
if (invalidHostStyle) {
|
|
1400
|
+
return bailout(input, "local/unsupported-target", `"${invalidHostStyle.name}" is a text style prop and this component is not text. Use a Text-based component, or html.* for raw web elements.`, invalidHostStyle.entry.span);
|
|
1401
|
+
}
|
|
1402
|
+
if (platform === "native" && component.domTag) {
|
|
1403
|
+
const mixedSpread = styleEntries.find((entry) => entry.kind === "spread" && entry.value.kind === "static" && staticObject(entry.value.value) && Object.keys(entry.value.value).some((name) => !isPropIgnored(name)));
|
|
1404
|
+
if (mixedSpread) {
|
|
1405
|
+
return bailout(input, "local/unsafe-style-spread", "Native DOM prop mapping requires non-style spread props to remain on the runtime path", mixedSpread.span);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1215
1408
|
const webPropEdits = platform === "web" ? input.element.entries.flatMap((entry) => {
|
|
1216
1409
|
if (entry.kind !== "prop" || entry.name !== "testID") return [];
|
|
1217
1410
|
const content = input.source.slice(entry.span.start, entry.span.end);
|
|
@@ -1220,7 +1413,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1220
1413
|
const alreadyQuoted = content[nameOffset - 1] === "\"" || content[nameOffset - 1] === "'";
|
|
1221
1414
|
return [{
|
|
1222
1415
|
start: entry.span.start + nameOffset,
|
|
1223
|
-
end: entry.span.start + nameOffset +
|
|
1416
|
+
end: entry.span.start + nameOffset + "testID".length,
|
|
1224
1417
|
content: input.element.form === "jsx" || alreadyQuoted ? "data-testid" : `'data-testid'`,
|
|
1225
1418
|
origin: entry.span
|
|
1226
1419
|
}];
|
|
@@ -1230,8 +1423,6 @@ function createTamaguiCompilerHost(options) {
|
|
|
1230
1423
|
additions: []
|
|
1231
1424
|
};
|
|
1232
1425
|
webPropEdits.push(...webDOMResult.edits);
|
|
1233
|
-
const unsafeSpread = input.element.entries.find((entry) => entry.kind === "spread" && !styleEntries.includes(entry) && entry.value.kind === "static" && staticObject(entry.value.value) && Object.keys(entry.value.value).some((name) => isStyleProp(name, component)));
|
|
1234
|
-
if (unsafeSpread) return bailout(input, "local/unsafe-style-spread", "A mixed style/non-style spread cannot be removed transactionally", unsafeSpread.span);
|
|
1235
1426
|
if (platform === "native") {
|
|
1236
1427
|
const nativeStyleResolved = split.viewProps?.style;
|
|
1237
1428
|
let themedStyleKeys = null;
|
|
@@ -1240,16 +1431,25 @@ function createTamaguiCompilerHost(options) {
|
|
|
1240
1431
|
for (const [styleKey, styleValue] of Object.entries(nativeStyleResolved)) {
|
|
1241
1432
|
if (!core.containsThemeRef(styleValue)) continue;
|
|
1242
1433
|
const themeKey = core.themeRefKey(styleValue);
|
|
1243
|
-
if (!themeKey)
|
|
1434
|
+
if (!themeKey) {
|
|
1435
|
+
return bailout(input, "local/dynamic-style-value", `Style ${styleKey} uses a theme value in a compound or modified position that compiled output cannot represent`);
|
|
1436
|
+
}
|
|
1437
|
+
;
|
|
1244
1438
|
(themedStyleKeys ||= {})[styleKey] = themeKey;
|
|
1245
1439
|
}
|
|
1246
1440
|
if (themedStyleKeys) {
|
|
1247
1441
|
const plain = {};
|
|
1248
|
-
for (const [styleKey, styleValue] of Object.entries(nativeStyleResolved))
|
|
1442
|
+
for (const [styleKey, styleValue] of Object.entries(nativeStyleResolved)) {
|
|
1443
|
+
if (!(styleKey in themedStyleKeys)) plain[styleKey] = styleValue;
|
|
1444
|
+
}
|
|
1249
1445
|
nativeStyle = plain;
|
|
1250
1446
|
}
|
|
1251
|
-
} else if (core.containsThemeRef(nativeStyleResolved))
|
|
1252
|
-
|
|
1447
|
+
} else if (core.containsThemeRef(nativeStyleResolved)) {
|
|
1448
|
+
return bailout(input, "local/dynamic-style-value", "Theme values inside non-object native style output stay on the runtime path");
|
|
1449
|
+
}
|
|
1450
|
+
if (!isSerializableNativeStyle(nativeStyle)) {
|
|
1451
|
+
return bailout(input, "local/unsupported-target", "Native style output is not a static serializable value");
|
|
1452
|
+
}
|
|
1253
1453
|
const nativeStyleLocal = unusedIdentifier(input.source, `__TamaguiNativeStyle${input.element.span.start}`);
|
|
1254
1454
|
const nativeStyleImports = [{
|
|
1255
1455
|
content: `
|
|
@@ -1270,12 +1470,16 @@ const ${mappingLocal} = ${JSON.stringify(themedStyleKeys)};`,
|
|
|
1270
1470
|
};
|
|
1271
1471
|
}
|
|
1272
1472
|
if (component.domTag) {
|
|
1273
|
-
if (themedStyleKeys)
|
|
1473
|
+
if (themedStyleKeys) {
|
|
1474
|
+
return bailout(input, "local/unsupported-target", "Theme values on DOM-tag native output stay on the runtime path");
|
|
1475
|
+
}
|
|
1274
1476
|
const row = import_dom.TAGS[component.domTag];
|
|
1275
1477
|
const basePrimitive = import_dom.NATIVE_BACKING[row.backing].primitive;
|
|
1276
1478
|
let primitive = basePrimitive;
|
|
1277
1479
|
const propsResult = nativeDOMProps(input, component.domTag);
|
|
1278
|
-
if (propsResult.diagnostic)
|
|
1480
|
+
if (propsResult.diagnostic) {
|
|
1481
|
+
return bailout(input, "local/unsupported-target", propsResult.diagnostic, propsResult.diagnosticSpan);
|
|
1482
|
+
}
|
|
1279
1483
|
styleEntries = [.../* @__PURE__ */ new Set([...styleEntries, ...propsResult.consumed])];
|
|
1280
1484
|
let nativeDOMStyleSource = nativeStyleSource;
|
|
1281
1485
|
let runtimeStyleSource = null;
|
|
@@ -1283,22 +1487,32 @@ const ${mappingLocal} = ${JSON.stringify(themedStyleKeys)};`,
|
|
|
1283
1487
|
const needsRuntime = domStyleProgram.value.items.some((item) => item.value.kind === "static" && staticObject(item.value.value) && (Object.keys(item.value.value).some((property) => nativeRuntimeOnlyStyleProperties.has(property)) || Object.values(item.value.value).some((value) => typeof value === "string" && (flatClausePattern.test(value) || nativeInheritedKeywordPattern.test(value)) || isClauseObjectValue(value))));
|
|
1284
1488
|
const itemSources = [];
|
|
1285
1489
|
for (const item of domStyleProgram.value.items) {
|
|
1286
|
-
if (item.value.kind !== "static" || !staticObject(item.value.value))
|
|
1287
|
-
|
|
1490
|
+
if (item.value.kind !== "static" || !staticObject(item.value.value)) {
|
|
1491
|
+
return bailout(input, "local/dynamic-style-value", "Every style() handle in a style array must be statically evaluable", item.value.span);
|
|
1492
|
+
}
|
|
1493
|
+
if (Object.values(item.value.value).some((value2) => typeof value2 === "string" && nativeInitialKeywordPattern.test(value2))) {
|
|
1494
|
+
return bailout(input, "local/unsupported-target", "Native DOM style() does not support the CSS initial keyword, matching the pinned upstream limitation", item.value.span);
|
|
1495
|
+
}
|
|
1288
1496
|
let value;
|
|
1289
|
-
if (needsRuntime)
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1497
|
+
if (needsRuntime) {
|
|
1498
|
+
value = JSON.stringify(item.value.value);
|
|
1499
|
+
} else {
|
|
1500
|
+
const itemSplit = resolveSplitStyles(item.value.value, partialStaticConfig(component.staticConfig));
|
|
1501
|
+
const itemStyle = itemSplit?.viewProps?.style;
|
|
1502
|
+
if (!isSerializableNativeStyle(itemStyle) || core.containsThemeRef(itemStyle)) {
|
|
1503
|
+
return bailout(input, "local/unsupported-target", "Native style() output is not serializable", item.value.span);
|
|
1504
|
+
}
|
|
1293
1505
|
value = JSON.stringify(itemStyle ?? {});
|
|
1294
1506
|
}
|
|
1295
1507
|
const condition = item.condition ? input.source.slice(item.condition.start, item.condition.end) : null;
|
|
1296
1508
|
itemSources.push(condition ? `(${condition}) && ${value}` : value);
|
|
1297
1509
|
}
|
|
1298
1510
|
if (needsRuntime) {
|
|
1299
|
-
primitive = `DOMRuntime${basePrimitive.slice(
|
|
1511
|
+
primitive = `DOMRuntime${basePrimitive.slice("DOM".length)}`;
|
|
1300
1512
|
runtimeStyleSource = `[${itemSources.join(", ")}]`;
|
|
1301
|
-
} else
|
|
1513
|
+
} else {
|
|
1514
|
+
nativeDOMStyleSource = `[${[nativeDOMStyleSource, ...itemSources].join(", ")}]`;
|
|
1515
|
+
}
|
|
1302
1516
|
}
|
|
1303
1517
|
const nativeLocal2 = unusedIdentifier(input.source, `__Tamagui${primitive}`);
|
|
1304
1518
|
const propertyContent = [
|
|
@@ -1326,17 +1540,22 @@ import { ${primitive} as ${nativeLocal2} } from ${JSON.stringify(import_dom.NATI
|
|
|
1326
1540
|
let needsCreateElement = false;
|
|
1327
1541
|
for (const entry of input.element.entries) {
|
|
1328
1542
|
if (entry.kind !== "child") continue;
|
|
1329
|
-
if (entry.value.kind === "empty" || entry.value.kind === "element" || entry.value.kind === "static" && (entry.value.value === null || typeof entry.value.value === "boolean"))
|
|
1330
|
-
|
|
1543
|
+
if (entry.value.kind === "empty" || entry.value.kind === "element" || entry.value.kind === "static" && (entry.value.value === null || typeof entry.value.value === "boolean")) {
|
|
1544
|
+
continue;
|
|
1545
|
+
}
|
|
1546
|
+
if (entry.value.kind !== "static" || entry.value.literalOrigin !== true || typeof entry.value.value !== "string" && typeof entry.value.value !== "number") {
|
|
1547
|
+
return bailout(input, "local/unsupported-child", `html.${component.domTag} has a direct child that may render unwrapped native text; write a literal as JSX text or wrap the child in html.span`, entry.span);
|
|
1548
|
+
}
|
|
1331
1549
|
needsText = true;
|
|
1332
1550
|
const child = input.source.slice(entry.span.start, entry.span.end);
|
|
1333
|
-
if (input.element.form === "jsx")
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1551
|
+
if (input.element.form === "jsx") {
|
|
1552
|
+
literalEdits.push({
|
|
1553
|
+
start: entry.span.start,
|
|
1554
|
+
end: entry.span.end,
|
|
1555
|
+
content: `<${textLocal} __inherit>${child}</${textLocal}>`,
|
|
1556
|
+
origin: entry.span
|
|
1557
|
+
});
|
|
1558
|
+
} else {
|
|
1340
1559
|
needsCreateElement = true;
|
|
1341
1560
|
literalEdits.push({
|
|
1342
1561
|
start: entry.span.start,
|
|
@@ -1346,36 +1565,44 @@ import { ${primitive} as ${nativeLocal2} } from ${JSON.stringify(import_dom.NATI
|
|
|
1346
1565
|
});
|
|
1347
1566
|
}
|
|
1348
1567
|
}
|
|
1349
|
-
if (needsText)
|
|
1350
|
-
|
|
1568
|
+
if (needsText) {
|
|
1569
|
+
imports.push({
|
|
1570
|
+
content: `
|
|
1351
1571
|
import { DOMText as ${textLocal} } from ${JSON.stringify(import_dom.NATIVE_PRIMITIVE_MODULE)}
|
|
1352
1572
|
`,
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1573
|
+
origin: input.element.component.span
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
if (needsCreateElement) {
|
|
1577
|
+
imports.push({
|
|
1578
|
+
content: `
|
|
1357
1579
|
import { createElement as ${createElementLocal} } from "react"
|
|
1358
1580
|
`,
|
|
1359
|
-
|
|
1360
|
-
|
|
1581
|
+
origin: input.element.component.span
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1361
1584
|
}
|
|
1585
|
+
const [first3, ...rest3] = styleEntries;
|
|
1586
|
+
const firstNonStyle3 = first3 ? spreadReplacement("jsx", first3) : "";
|
|
1362
1587
|
const propsEdits = input.element.form === "jsx" ? styleEntries.length === 0 ? [{
|
|
1363
1588
|
start: input.element.component.span.end,
|
|
1364
1589
|
end: input.element.component.span.end,
|
|
1365
1590
|
content: ` ${propertyContent}`,
|
|
1366
1591
|
origin: input.element.component.span
|
|
1367
1592
|
}] : [{
|
|
1368
|
-
start:
|
|
1369
|
-
end:
|
|
1370
|
-
content: propertyContent,
|
|
1371
|
-
origin:
|
|
1372
|
-
}, ...
|
|
1593
|
+
start: first3.span.start,
|
|
1594
|
+
end: first3.span.end,
|
|
1595
|
+
content: [propertyContent, firstNonStyle3].filter(Boolean).join(" "),
|
|
1596
|
+
origin: first3.span
|
|
1597
|
+
}, ...rest3.map((entry) => ({
|
|
1373
1598
|
start: entry.span.start,
|
|
1374
1599
|
end: entry.span.end,
|
|
1375
|
-
content: "",
|
|
1600
|
+
content: spreadReplacement("jsx", entry),
|
|
1376
1601
|
origin: entry.span
|
|
1377
|
-
}))] : compiledPropsEdits(input, styleEntries, propertyContent);
|
|
1378
|
-
if (!propsEdits)
|
|
1602
|
+
}))] : compiledPropsEdits(input, styleEntries, propertyContent, (entry) => spreadReplacement(input.element.form, entry));
|
|
1603
|
+
if (!propsEdits) {
|
|
1604
|
+
return bailout(input, "local/unsupported-target", `Compiled ${input.element.form} call has no editable props argument`);
|
|
1605
|
+
}
|
|
1379
1606
|
return {
|
|
1380
1607
|
ok: true,
|
|
1381
1608
|
edits: [
|
|
@@ -1393,7 +1620,9 @@ import { createElement as ${createElementLocal} } from "react"
|
|
|
1393
1620
|
const useHostView = options.experimentalNativeFastPath && nativeName === "View" && isBareHostView(input.element);
|
|
1394
1621
|
const nativeExport = useHostView ? "unstable_NativeView" : nativeName;
|
|
1395
1622
|
const nativeLocal = unusedIdentifier(input.source, `__TamaguiNative${useHostView ? "HostView" : nativeName}`);
|
|
1396
|
-
if (themedStyleKeys && options.disablePartialExtraction)
|
|
1623
|
+
if (themedStyleKeys && options.disablePartialExtraction) {
|
|
1624
|
+
return bailout(input, "local/dynamic-style-value", "Theme values require partial extraction, which is disabled");
|
|
1625
|
+
}
|
|
1397
1626
|
if (dynamicStyleEntries.length > 0 || themedStyleKeys) {
|
|
1398
1627
|
if (nativeFastPath) {
|
|
1399
1628
|
const fastLocal = `__TamaguiNativeFast${nativeName}${input.element.span.start}`;
|
|
@@ -1415,7 +1644,9 @@ import { createElement as ${createElementLocal} } from "react"
|
|
|
1415
1644
|
content: "",
|
|
1416
1645
|
origin: entry.span
|
|
1417
1646
|
}))] : compiledPropsEdits(input, styleEntries, `_expressions: []`);
|
|
1418
|
-
if (!styleEdits)
|
|
1647
|
+
if (!styleEdits) {
|
|
1648
|
+
return bailout(input, "local/unsupported-target", `Compiled ${input.element.form} call has no editable props argument`);
|
|
1649
|
+
}
|
|
1419
1650
|
return {
|
|
1420
1651
|
ok: true,
|
|
1421
1652
|
edits: [...tagEdits4, ...styleEdits],
|
|
@@ -1443,34 +1674,63 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1443
1674
|
const conditionalParts = [];
|
|
1444
1675
|
const conditionalKeys = /* @__PURE__ */ new Set();
|
|
1445
1676
|
const baseStyleForDiff = staticObject(nativeStyleResolved) ? nativeStyleResolved : {};
|
|
1446
|
-
for (const entry of dynamicStyleEntries)
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1677
|
+
for (const entry of dynamicStyleEntries) {
|
|
1678
|
+
if (entry.value.kind === "conditional" && directStyleName(entry.name, component) !== "opacity") {
|
|
1679
|
+
let serializeNativeTree = function(node) {
|
|
1680
|
+
if (node.kind === "leaf") {
|
|
1681
|
+
const diff = leafDiffs.get(node) ?? {};
|
|
1682
|
+
return JSON.stringify(diff);
|
|
1683
|
+
}
|
|
1684
|
+
const index = expressions.length;
|
|
1685
|
+
expressions.push(input.source.slice(node.test.start, node.test.end));
|
|
1686
|
+
return `expressions[${index}] ? ${serializeNativeTree(node.whenTrue)} : ${serializeNativeTree(node.whenFalse)}`;
|
|
1687
|
+
};
|
|
1688
|
+
const tree = entry.value.tree;
|
|
1689
|
+
const leaves = (0, import_compiler_core.collectLeaves)(tree);
|
|
1690
|
+
const leafDiffs = /* @__PURE__ */ new Map();
|
|
1691
|
+
for (const leaf of leaves) {
|
|
1692
|
+
const { branchCompleteProps } = propsForConditional(entry, leaf.value);
|
|
1693
|
+
const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
|
|
1694
|
+
const branchStyle = branchSplit?.viewProps?.style ?? {};
|
|
1695
|
+
if (!staticObject(branchStyle)) {
|
|
1696
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch did not resolve to a static native style`, entry.value.span);
|
|
1697
|
+
}
|
|
1698
|
+
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit?.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1699
|
+
if (viewPropsKey === "style") continue;
|
|
1700
|
+
if (JSON.stringify(branchSplit?.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1701
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch changes ${viewPropsKey}, which the compiled style array cannot express`, entry.value.span);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
for (const key of Object.keys(baseStyleForDiff)) {
|
|
1705
|
+
if (!(key in branchStyle)) {
|
|
1706
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch removes ${key}, which an additive style array cannot express`, entry.value.span);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
const diff = {};
|
|
1710
|
+
for (const [key, value] of Object.entries(branchStyle)) {
|
|
1711
|
+
if (JSON.stringify(baseStyleForDiff[key]) !== JSON.stringify(value)) {
|
|
1712
|
+
diff[key] = value;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
if (!isSerializableNativeStyle(diff) || core.containsThemeRef(diff)) {
|
|
1716
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch style is not statically representable`, entry.value.span);
|
|
1717
|
+
}
|
|
1718
|
+
for (const key of Object.keys(diff)) {
|
|
1719
|
+
if (conditionalKeys.has(key)) {
|
|
1720
|
+
return bailout(input, "local/dynamic-style-value", `Multiple conditionals contribute ${key}; their interaction cannot be resolved per-branch`, entry.value.span);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
leafDiffs.set(leaf, diff);
|
|
1724
|
+
}
|
|
1725
|
+
for (const diff of leafDiffs.values()) {
|
|
1726
|
+
for (const key of Object.keys(diff)) conditionalKeys.add(key);
|
|
1458
1727
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
branchDiffs.push(diff);
|
|
1728
|
+
conditionalParts.push(serializeNativeTree(tree));
|
|
1729
|
+
} else {
|
|
1730
|
+
const index = expressions.length;
|
|
1731
|
+
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
1732
|
+
plainDynamicParts.push(`${JSON.stringify(directStyleName(entry.name, component))}: expressions[${index}]`);
|
|
1465
1733
|
}
|
|
1466
|
-
for (const diff of branchDiffs) for (const key of Object.keys(diff)) conditionalKeys.add(key);
|
|
1467
|
-
const index = expressions.length;
|
|
1468
|
-
expressions.push(input.source.slice(entry.value.test.start, entry.value.test.end));
|
|
1469
|
-
conditionalParts.push(`expressions[${index}] ? ${JSON.stringify(branchDiffs[0])} : ${JSON.stringify(branchDiffs[1])}`);
|
|
1470
|
-
} else {
|
|
1471
|
-
const index = expressions.length;
|
|
1472
|
-
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
1473
|
-
plainDynamicParts.push(`${JSON.stringify(directStyleName(entry.name, component))}: expressions[${index}]`);
|
|
1474
1734
|
}
|
|
1475
1735
|
const dynamicStyle = plainDynamicParts.join(", ");
|
|
1476
1736
|
const themedStyle = themedStyleKeys ? Object.entries(themedStyleKeys).map(([styleKey, themeKey]) => `${JSON.stringify(styleKey)}: _theme[${JSON.stringify(themeKey)}]?.get()`).join(", ") : null;
|
|
@@ -1487,18 +1747,21 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1487
1747
|
origin: span
|
|
1488
1748
|
}));
|
|
1489
1749
|
const [first3, ...rest3] = styleEntries;
|
|
1750
|
+
const firstNonStyle3 = first3 ? spreadReplacement("jsx", first3) : "";
|
|
1490
1751
|
const expressionEdits = styleEntries.length === 0 ? [] : input.element.form === "jsx" ? [{
|
|
1491
1752
|
start: first3.span.start,
|
|
1492
1753
|
end: first3.span.end,
|
|
1493
|
-
content: expressions.length > 0 ? `_expressions={[${expressions.join(", ")}]}` : "",
|
|
1754
|
+
content: [expressions.length > 0 ? `_expressions={[${expressions.join(", ")}]}` : "", firstNonStyle3].filter(Boolean).join(" "),
|
|
1494
1755
|
origin: first3.span
|
|
1495
1756
|
}, ...rest3.map((entry) => ({
|
|
1496
1757
|
start: entry.span.start,
|
|
1497
1758
|
end: entry.span.end,
|
|
1498
|
-
content: "",
|
|
1759
|
+
content: spreadReplacement("jsx", entry),
|
|
1499
1760
|
origin: entry.span
|
|
1500
|
-
}))] : compiledPropsEdits(input, styleEntries, `_expressions: [${expressions.join(", ")}]
|
|
1501
|
-
if (!expressionEdits)
|
|
1761
|
+
}))] : compiledPropsEdits(input, styleEntries, `_expressions: [${expressions.join(", ")}]`, (entry) => spreadReplacement(input.element.form, entry));
|
|
1762
|
+
if (!expressionEdits) {
|
|
1763
|
+
return bailout(input, "local/unsupported-target", `Compiled ${input.element.form} call has no editable props argument`);
|
|
1764
|
+
}
|
|
1502
1765
|
return {
|
|
1503
1766
|
ok: true,
|
|
1504
1767
|
edits: [...tagEdits3, ...expressionEdits],
|
|
@@ -1527,8 +1790,10 @@ const ${stableLocal} = require('@tamagui/core')._withStableStyle(${nativeLocal},
|
|
|
1527
1790
|
origin: span
|
|
1528
1791
|
}));
|
|
1529
1792
|
if (input.element.form !== "jsx") {
|
|
1530
|
-
const propsEdits = compiledPropsEdits(input, styleEntries, styleContent);
|
|
1531
|
-
if (!propsEdits)
|
|
1793
|
+
const propsEdits = compiledPropsEdits(input, styleEntries, styleContent, (entry) => spreadReplacement(input.element.form, entry));
|
|
1794
|
+
if (!propsEdits) {
|
|
1795
|
+
return bailout(input, "local/unsupported-target", `Compiled ${input.element.form} call has no editable props argument`);
|
|
1796
|
+
}
|
|
1532
1797
|
return {
|
|
1533
1798
|
ok: true,
|
|
1534
1799
|
edits: [...tagEdits2, ...propsEdits],
|
|
@@ -1541,23 +1806,26 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1541
1806
|
flattened: true
|
|
1542
1807
|
};
|
|
1543
1808
|
}
|
|
1544
|
-
if (styleEntries.length === 0)
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1809
|
+
if (styleEntries.length === 0) {
|
|
1810
|
+
return {
|
|
1811
|
+
ok: true,
|
|
1812
|
+
edits: [...tagEdits2, {
|
|
1813
|
+
start: input.element.component.span.end,
|
|
1814
|
+
end: input.element.component.span.end,
|
|
1815
|
+
content: ` style={${nativeStyleSource}}`,
|
|
1816
|
+
origin: input.element.component.span
|
|
1817
|
+
}],
|
|
1818
|
+
css: [],
|
|
1819
|
+
imports: [...nativeStyleImports, {
|
|
1820
|
+
content: `
|
|
1555
1821
|
const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1822
|
+
origin: input.element.component.span
|
|
1823
|
+
}],
|
|
1824
|
+
flattened: true
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1560
1827
|
const [first2, ...rest2] = styleEntries;
|
|
1828
|
+
const firstNonStyle2 = first2 ? spreadReplacement("jsx", first2) : "";
|
|
1561
1829
|
return {
|
|
1562
1830
|
ok: true,
|
|
1563
1831
|
edits: [
|
|
@@ -1566,13 +1834,13 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1566
1834
|
{
|
|
1567
1835
|
start: first2.span.start,
|
|
1568
1836
|
end: first2.span.end,
|
|
1569
|
-
content: `style={${nativeStyleSource}}`,
|
|
1837
|
+
content: [`style={${nativeStyleSource}}`, firstNonStyle2].filter(Boolean).join(" "),
|
|
1570
1838
|
origin: first2.span
|
|
1571
1839
|
},
|
|
1572
1840
|
...rest2.map((entry) => ({
|
|
1573
1841
|
start: entry.span.start,
|
|
1574
1842
|
end: entry.span.end,
|
|
1575
|
-
content: "",
|
|
1843
|
+
content: spreadReplacement("jsx", entry),
|
|
1576
1844
|
origin: entry.span
|
|
1577
1845
|
}))
|
|
1578
1846
|
],
|
|
@@ -1588,60 +1856,112 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1588
1856
|
const artifacts = extractedStyleArtifacts(split, props, options.tamaguiConfig, !component.domTag, Boolean(component.staticConfig.styleFrontend));
|
|
1589
1857
|
const className = artifacts.className;
|
|
1590
1858
|
const rawInlineStyle = split.viewProps?.style;
|
|
1591
|
-
const inlineStyle = staticObject(rawInlineStyle) &&
|
|
1592
|
-
if (rawInlineStyle && !inlineStyle && !isSerializableNativeStyle(rawInlineStyle))
|
|
1859
|
+
const inlineStyle = staticObject(rawInlineStyle) && Object.keys(rawInlineStyle).length > 0 ? rawInlineStyle : null;
|
|
1860
|
+
if (rawInlineStyle && !inlineStyle && !isSerializableNativeStyle(rawInlineStyle)) {
|
|
1861
|
+
return bailout(input, "local/unsupported-target", "Web inline style output is not a static serializable value");
|
|
1862
|
+
}
|
|
1593
1863
|
const programCSS = [];
|
|
1594
1864
|
const programClassSources = [];
|
|
1595
|
-
if (domStyleProgram?.kind === "prop" && domStyleProgram.value.kind === "dom-style")
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1865
|
+
if (domStyleProgram?.kind === "prop" && domStyleProgram.value.kind === "dom-style") {
|
|
1866
|
+
for (const item of domStyleProgram.value.items) {
|
|
1867
|
+
if (item.value.kind !== "static" || !staticObject(item.value.value)) {
|
|
1868
|
+
return bailout(input, "local/dynamic-style-value", "Every style() handle in a style array must be statically evaluable", item.value.span);
|
|
1869
|
+
}
|
|
1870
|
+
const itemSplit = resolveSplitStyles(item.value.value, partialStaticConfig(component.staticConfig));
|
|
1871
|
+
if (!itemSplit) {
|
|
1872
|
+
return bailout(input, "local/style-resolution-failed", "A style() handle could not be resolved", item.value.span);
|
|
1873
|
+
}
|
|
1874
|
+
const itemInline = itemSplit.viewProps?.style;
|
|
1875
|
+
if (staticObject(itemInline) && Object.keys(itemInline).length > 0) {
|
|
1876
|
+
return bailout(input, "local/unsupported-target", "Conditional web style() handles must lower to CSS classes", item.value.span);
|
|
1877
|
+
}
|
|
1878
|
+
const itemArtifacts = extractedStyleArtifacts(itemSplit, item.value.value, options.tamaguiConfig, false);
|
|
1879
|
+
programCSS.push(...itemArtifacts.css);
|
|
1880
|
+
if (itemArtifacts.className) {
|
|
1881
|
+
const condition = item.condition ? input.source.slice(item.condition.start, item.condition.end) : null;
|
|
1882
|
+
programClassSources.push(condition ? `(${condition}) && ${JSON.stringify(itemArtifacts.className)}` : JSON.stringify(itemArtifacts.className));
|
|
1883
|
+
}
|
|
1606
1884
|
}
|
|
1607
1885
|
}
|
|
1608
|
-
|
|
1886
|
+
const baseStaticClasses = new Set(className.split(" ").filter(Boolean));
|
|
1887
|
+
const staticClasses = new Set(baseStaticClasses);
|
|
1609
1888
|
const webConditionalCSS = [];
|
|
1889
|
+
const webConditionalKeys = /* @__PURE__ */ new Set();
|
|
1610
1890
|
const webConditionalEntries = supportsWebConditionalClasses ? dynamicStyleEntries.filter((entry) => entry.value.kind === "conditional") : [];
|
|
1611
1891
|
for (const entry of webConditionalEntries) {
|
|
1892
|
+
let serializeWebTree = function(node) {
|
|
1893
|
+
if (node.kind === "leaf") {
|
|
1894
|
+
const artifacts2 = leafArtifactsMap.get(node);
|
|
1895
|
+
const only = artifacts2 ? artifacts2.classes.filter((item) => !sharedInConditional.has(item)) : [];
|
|
1896
|
+
return JSON.stringify(only.join(" "));
|
|
1897
|
+
}
|
|
1898
|
+
const test = input.source.slice(node.test.start, node.test.end);
|
|
1899
|
+
const truePart = serializeWebTree(node.whenTrue);
|
|
1900
|
+
const falsePart = serializeWebTree(node.whenFalse);
|
|
1901
|
+
return `(${test}) ? ${truePart} : ${falsePart}`;
|
|
1902
|
+
};
|
|
1612
1903
|
if (entry.value.kind !== "conditional") continue;
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1904
|
+
const tree = entry.value.tree;
|
|
1905
|
+
const leaves = (0, import_compiler_core.collectLeaves)(tree);
|
|
1906
|
+
const leafArtifactsMap = /* @__PURE__ */ new Map();
|
|
1907
|
+
const entryConditionalKeys = /* @__PURE__ */ new Set();
|
|
1908
|
+
for (const leaf of leaves) {
|
|
1909
|
+
const { branchProps, branchCompleteProps } = propsForConditional(entry, leaf.value);
|
|
1910
|
+
const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
|
|
1911
|
+
if (!branchSplit) {
|
|
1912
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch could not be resolved`, entry.value.span);
|
|
1913
|
+
}
|
|
1620
1914
|
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1621
1915
|
if (viewPropsKey === "className") continue;
|
|
1622
|
-
if (JSON.stringify(branchSplit.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey]))
|
|
1916
|
+
if (JSON.stringify(branchSplit.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1917
|
+
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch changes ${viewPropsKey}, which conditional classes cannot express`, entry.value.span);
|
|
1918
|
+
}
|
|
1623
1919
|
}
|
|
1624
|
-
const
|
|
1625
|
-
|
|
1626
|
-
[
|
|
1627
|
-
|
|
1628
|
-
|
|
1920
|
+
const changedKeys = /* @__PURE__ */ new Set();
|
|
1921
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(branchSplit.classNames ?? {}), ...Object.keys(split.classNames ?? {})])) {
|
|
1922
|
+
if (JSON.stringify(branchSplit.classNames?.[key]) !== JSON.stringify(split.classNames?.[key])) {
|
|
1923
|
+
changedKeys.add(key);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
const branchStyle = branchSplit.viewProps?.style;
|
|
1927
|
+
const baseStyle = split.viewProps?.style;
|
|
1928
|
+
if (staticObject(branchStyle) || staticObject(baseStyle)) {
|
|
1929
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(staticObject(branchStyle) ? branchStyle : {}), ...Object.keys(staticObject(baseStyle) ? baseStyle : {})])) {
|
|
1930
|
+
if (JSON.stringify(staticObject(branchStyle) ? branchStyle[key] : void 0) !== JSON.stringify(staticObject(baseStyle) ? baseStyle[key] : void 0)) {
|
|
1931
|
+
changedKeys.add(key);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
for (const key of changedKeys) {
|
|
1936
|
+
if (webConditionalKeys.has(key)) {
|
|
1937
|
+
return bailout(input, "local/dynamic-style-value", `Multiple conditionals contribute ${key}; their interaction cannot be resolved per-branch`, entry.value.span);
|
|
1938
|
+
}
|
|
1939
|
+
entryConditionalKeys.add(key);
|
|
1940
|
+
}
|
|
1941
|
+
const branchArtifacts = extractedStyleArtifacts(branchSplit, branchProps, options.tamaguiConfig, !component.domTag, Boolean(component.staticConfig.styleFrontend));
|
|
1942
|
+
leafArtifactsMap.set(leaf, {
|
|
1629
1943
|
classes: branchArtifacts.className.split(" ").filter(Boolean),
|
|
1630
1944
|
css: branchArtifacts.css
|
|
1631
1945
|
});
|
|
1632
1946
|
}
|
|
1633
|
-
const
|
|
1634
|
-
const
|
|
1635
|
-
|
|
1636
|
-
const falseOnly = whenFalse.classes.filter((item) => !shared.has(item));
|
|
1637
|
-
webClassName = [...shared].join(" ");
|
|
1638
|
-
webConditionalCSS.push(...whenTrue.css, ...whenFalse.css);
|
|
1639
|
-
if (trueOnly.length > 0 || falseOnly.length > 0) {
|
|
1640
|
-
const test = input.source.slice(entry.value.test.start, entry.value.test.end);
|
|
1641
|
-
programClassSources.push(`(${test}) ? ${JSON.stringify(trueOnly.join(" "))} : ${JSON.stringify(falseOnly.join(" "))}`);
|
|
1947
|
+
for (const key of entryConditionalKeys) webConditionalKeys.add(key);
|
|
1948
|
+
for (const artifacts2 of leafArtifactsMap.values()) {
|
|
1949
|
+
webConditionalCSS.push(...artifacts2.css);
|
|
1642
1950
|
}
|
|
1951
|
+
const allLeafArtifacts = leaves.map((l) => leafArtifactsMap.get(l));
|
|
1952
|
+
const sharedInConditional = new Set(allLeafArtifacts[0]?.classes.filter((c) => allLeafArtifacts.every((a) => a.classes.includes(c))) ?? []);
|
|
1953
|
+
for (const cls of baseStaticClasses) {
|
|
1954
|
+
if (!sharedInConditional.has(cls)) staticClasses.delete(cls);
|
|
1955
|
+
}
|
|
1956
|
+
for (const cls of sharedInConditional) {
|
|
1957
|
+
if (!baseStaticClasses.has(cls)) staticClasses.add(cls);
|
|
1958
|
+
}
|
|
1959
|
+
const classExpr = serializeWebTree(tree);
|
|
1960
|
+
programClassSources.push(classExpr);
|
|
1643
1961
|
}
|
|
1644
|
-
const
|
|
1962
|
+
const webClassName = [...staticClasses].join(" ");
|
|
1963
|
+
const hasStyleProgram = programClassSources.length > 0;
|
|
1964
|
+
const classNameExpression = hasStyleProgram ? `[${[JSON.stringify(webClassName), ...programClassSources].join(", ")}].filter(Boolean).join(" ")` : null;
|
|
1645
1965
|
const serializedInlineStyle = serializedStyle(inlineStyle, dynamicHostStyleProperties ?? []);
|
|
1646
1966
|
const jsxWebStyle = classNameExpression ? [`className={${classNameExpression}}`, serializedInlineStyle ? `style={${serializedInlineStyle}}` : ""].filter(Boolean).join(" ") : jsxStyleAttributes(webClassName, inlineStyle, dynamicHostStyleProperties ?? []);
|
|
1647
1967
|
const objectWebStyle = classNameExpression ? [`className: ${classNameExpression}`, serializedInlineStyle ? `style: ${serializedInlineStyle}` : ""].filter(Boolean).join(", ") : objectStyleProperties(webClassName, inlineStyle, dynamicHostStyleProperties ?? []);
|
|
@@ -1653,8 +1973,10 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1653
1973
|
const webExtraProps = serializedProps(input.element.form, webDOMResult.additions);
|
|
1654
1974
|
if (input.element.form !== "jsx") {
|
|
1655
1975
|
const replacement = [objectWebStyle, webExtraProps].filter(Boolean).join(", ");
|
|
1656
|
-
const propsEdits = compiledPropsEdits(input, styleEntries, replacement);
|
|
1657
|
-
if (!propsEdits)
|
|
1976
|
+
const propsEdits = compiledPropsEdits(input, styleEntries, replacement, (entry) => spreadReplacement(input.element.form, entry));
|
|
1977
|
+
if (!propsEdits) {
|
|
1978
|
+
return bailout(input, "local/unsupported-target", `Compiled ${input.element.form} call has no editable props argument`);
|
|
1979
|
+
}
|
|
1658
1980
|
return {
|
|
1659
1981
|
ok: true,
|
|
1660
1982
|
edits: [
|
|
@@ -1687,7 +2009,12 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1687
2009
|
};
|
|
1688
2010
|
}
|
|
1689
2011
|
const [first, ...rest] = styleEntries;
|
|
1690
|
-
const
|
|
2012
|
+
const firstNonStyle = first ? spreadReplacement("jsx", first) : "";
|
|
2013
|
+
const attributes = [
|
|
2014
|
+
jsxWebStyle,
|
|
2015
|
+
webExtraProps,
|
|
2016
|
+
firstNonStyle
|
|
2017
|
+
].filter(Boolean).join(" ");
|
|
1691
2018
|
return {
|
|
1692
2019
|
ok: true,
|
|
1693
2020
|
edits: [
|
|
@@ -1702,7 +2029,7 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
|
|
|
1702
2029
|
...rest.map((entry) => ({
|
|
1703
2030
|
start: entry.span.start,
|
|
1704
2031
|
end: entry.span.end,
|
|
1705
|
-
content: "",
|
|
2032
|
+
content: spreadReplacement("jsx", entry),
|
|
1706
2033
|
origin: entry.span
|
|
1707
2034
|
}))
|
|
1708
2035
|
],
|