@tamagui/static 3.0.0-beta.1473.1 → 3.0.0-beta.1537.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/compilerHost.cjs +159 -36
- package/dist/esm/compilerHost.mjs +159 -36
- package/dist/esm/compilerHost.mjs.map +1 -1
- package/package.json +18 -18
- package/src/compilerHost.ts +224 -79
- package/types/compilerHost.d.ts.map +1 -1
|
@@ -515,6 +515,77 @@ const nativePointerEventProps = /* @__PURE__ */ new Set([
|
|
|
515
515
|
"onPointerMove",
|
|
516
516
|
"onPointerUp"
|
|
517
517
|
]);
|
|
518
|
+
const nativeShorthandFamilies = [
|
|
519
|
+
[
|
|
520
|
+
"padding",
|
|
521
|
+
[
|
|
522
|
+
"paddingTop",
|
|
523
|
+
"paddingRight",
|
|
524
|
+
"paddingBottom",
|
|
525
|
+
"paddingLeft"
|
|
526
|
+
],
|
|
527
|
+
/^padding/
|
|
528
|
+
],
|
|
529
|
+
[
|
|
530
|
+
"margin",
|
|
531
|
+
[
|
|
532
|
+
"marginTop",
|
|
533
|
+
"marginRight",
|
|
534
|
+
"marginBottom",
|
|
535
|
+
"marginLeft"
|
|
536
|
+
],
|
|
537
|
+
/^margin/
|
|
538
|
+
],
|
|
539
|
+
[
|
|
540
|
+
"borderWidth",
|
|
541
|
+
[
|
|
542
|
+
"borderTopWidth",
|
|
543
|
+
"borderRightWidth",
|
|
544
|
+
"borderBottomWidth",
|
|
545
|
+
"borderLeftWidth"
|
|
546
|
+
],
|
|
547
|
+
/^border.*Width$/
|
|
548
|
+
],
|
|
549
|
+
[
|
|
550
|
+
"borderColor",
|
|
551
|
+
[
|
|
552
|
+
"borderTopColor",
|
|
553
|
+
"borderRightColor",
|
|
554
|
+
"borderBottomColor",
|
|
555
|
+
"borderLeftColor"
|
|
556
|
+
],
|
|
557
|
+
/^border.*Color$/
|
|
558
|
+
],
|
|
559
|
+
[
|
|
560
|
+
"borderRadius",
|
|
561
|
+
[
|
|
562
|
+
"borderTopLeftRadius",
|
|
563
|
+
"borderTopRightRadius",
|
|
564
|
+
"borderBottomRightRadius",
|
|
565
|
+
"borderBottomLeftRadius"
|
|
566
|
+
],
|
|
567
|
+
/^border.*Radius$/
|
|
568
|
+
]
|
|
569
|
+
];
|
|
570
|
+
function collapseNativeShorthands(style) {
|
|
571
|
+
if (!staticObject(style)) return style;
|
|
572
|
+
const keys = Object.keys(style);
|
|
573
|
+
const collapsed = /* @__PURE__ */ new Map();
|
|
574
|
+
for (const [shorthand, sides, family] of nativeShorthandFamilies) {
|
|
575
|
+
const value = style[sides[0]];
|
|
576
|
+
if (value !== void 0 && !(shorthand in style) && sides.every((side) => style[side] === value) && keys.filter((key) => family.test(key)).length === sides.length) {
|
|
577
|
+
for (const side of sides) collapsed.set(side, shorthand);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (!collapsed.size) return style;
|
|
581
|
+
const out = {};
|
|
582
|
+
for (const key of keys) {
|
|
583
|
+
const shorthand = collapsed.get(key);
|
|
584
|
+
if (!shorthand) out[key] = style[key];
|
|
585
|
+
else if (!(shorthand in out)) out[shorthand] = style[key];
|
|
586
|
+
}
|
|
587
|
+
return out;
|
|
588
|
+
}
|
|
518
589
|
function isSerializableNativeStyle(value) {
|
|
519
590
|
if (value == null || typeof value === "number" || typeof value === "boolean") {
|
|
520
591
|
return true;
|
|
@@ -1002,6 +1073,12 @@ function createTamaguiCompilerHost(options) {
|
|
|
1002
1073
|
if (dynamic?.type !== "string" || !dynamic.values?.length) return null;
|
|
1003
1074
|
return dynamic.values.map(String);
|
|
1004
1075
|
};
|
|
1076
|
+
const nativeDynamicShape = (name, component, dynamic) => {
|
|
1077
|
+
if (!dynamic || !canLowerConditionalStyleProp(name, component)) return null;
|
|
1078
|
+
if (dynamic.values?.length) return "domain";
|
|
1079
|
+
if (dynamic.type === "number" && directStyleName(name, component)) return "number";
|
|
1080
|
+
return null;
|
|
1081
|
+
};
|
|
1005
1082
|
const conditionalClassEntry = (entry, component) => entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component) || frontendClassDomain(entry, component) !== null;
|
|
1006
1083
|
const isInvalidHostStyleProp = (name, component) => {
|
|
1007
1084
|
const staticConfig = component.staticConfig;
|
|
@@ -1147,7 +1224,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1147
1224
|
return {
|
|
1148
1225
|
resolveComponent: resolve,
|
|
1149
1226
|
isStyleProp,
|
|
1150
|
-
canLowerDynamicStyleProp(name, component, valueKind) {
|
|
1227
|
+
canLowerDynamicStyleProp(name, component, valueKind, dynamic) {
|
|
1151
1228
|
if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
|
|
1152
1229
|
return true;
|
|
1153
1230
|
}
|
|
@@ -1157,7 +1234,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1157
1234
|
if (!options.disablePartialExtraction && platform === "web" && isFrontendClassName(name, component)) {
|
|
1158
1235
|
return true;
|
|
1159
1236
|
}
|
|
1160
|
-
return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
|
|
1237
|
+
return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && (directStyleName(name, component) === "opacity" || valueKind === "bailout" && nativeDynamicShape(name, component, dynamic) !== null));
|
|
1161
1238
|
},
|
|
1162
1239
|
developmentDebugInstrumentation,
|
|
1163
1240
|
lowerCandidate(input) {
|
|
@@ -1466,7 +1543,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1466
1543
|
message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `the animation configured on ${input.element.component.name}` })
|
|
1467
1544
|
});
|
|
1468
1545
|
}
|
|
1469
|
-
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)));
|
|
1546
|
+
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) || entry.value.kind === "bailout" && nativeDynamicShape(entry.name, component, entry.value.dynamic) !== null));
|
|
1470
1547
|
if (dynamicStyleEntries.length > 0 && !laneACoversAll && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
|
|
1471
1548
|
const entry = dynamicStyleEntries[0];
|
|
1472
1549
|
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
|
|
@@ -1678,14 +1755,15 @@ function createTamaguiCompilerHost(options) {
|
|
|
1678
1755
|
return bailout(input, "local/unsupported-target", "Native style output is not a static serializable value");
|
|
1679
1756
|
}
|
|
1680
1757
|
const nativeStyleLocal = unusedIdentifier(input.source, `__TamaguiNativeStyle${input.element.span.start}`);
|
|
1758
|
+
const usesNativeFastPath = !!themedStyleKeys && !!options.experimentalNativeFastPath && dynamicStyleEntries.length === 0 && !input.element.entries.some((entry) => entry.kind === "spread");
|
|
1681
1759
|
const nativeStyleImports = [{
|
|
1682
1760
|
content: `
|
|
1683
|
-
function ${nativeStyleLocal}() { return ${nativeStyleLocal}._ ?? (${nativeStyleLocal}._ = ${JSON.stringify(nativeStyle ?? {})}); } ${nativeStyleLocal}();`,
|
|
1761
|
+
function ${nativeStyleLocal}() { return ${nativeStyleLocal}._ ?? (${nativeStyleLocal}._ = ${JSON.stringify((usesNativeFastPath ? nativeStyle : collapseNativeShorthands(nativeStyle)) ?? {})}); } ${nativeStyleLocal}();`,
|
|
1684
1762
|
origin: input.element.component.span
|
|
1685
1763
|
}];
|
|
1686
1764
|
const nativeStyleSource = `${nativeStyleLocal}._ ?? ${nativeStyleLocal}()`;
|
|
1687
1765
|
let nativeFastPath;
|
|
1688
|
-
if (
|
|
1766
|
+
if (usesNativeFastPath) {
|
|
1689
1767
|
const mappingLocal = unusedIdentifier(input.source, `__TamaguiNativeMapping${input.element.span.start}`);
|
|
1690
1768
|
nativeFastPath = {
|
|
1691
1769
|
mappingLocal,
|
|
@@ -1904,7 +1982,45 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1904
1982
|
const conditionalParts = [];
|
|
1905
1983
|
const conditionalKeys = /* @__PURE__ */ new Set();
|
|
1906
1984
|
const baseStyleForDiff = staticObject(nativeStyleResolved) ? nativeStyleResolved : {};
|
|
1985
|
+
const valueDiff = (entry, value, what) => {
|
|
1986
|
+
const { branchCompleteProps } = propsForConditional(entry, value);
|
|
1987
|
+
const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
|
|
1988
|
+
const branchStyle = branchSplit?.viewProps?.style ?? {};
|
|
1989
|
+
if (!staticObject(branchStyle)) {
|
|
1990
|
+
return `${what} did not resolve to a static native style`;
|
|
1991
|
+
}
|
|
1992
|
+
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit?.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1993
|
+
if (viewPropsKey === "style") continue;
|
|
1994
|
+
if (JSON.stringify(branchSplit?.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1995
|
+
return `${what} changes ${viewPropsKey}, which the compiled style array cannot express`;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
for (const key of Object.keys(baseStyleForDiff)) {
|
|
1999
|
+
if (!(key in branchStyle)) {
|
|
2000
|
+
return `${what} removes ${key}, which an additive style array cannot express`;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
const diff = {};
|
|
2004
|
+
for (const [key, value2] of Object.entries(branchStyle)) {
|
|
2005
|
+
if (JSON.stringify(baseStyleForDiff[key]) !== JSON.stringify(value2)) {
|
|
2006
|
+
diff[key] = value2;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
if (!isSerializableNativeStyle(diff) || core.containsThemeRef(diff)) {
|
|
2010
|
+
return `${what} style is not statically representable`;
|
|
2011
|
+
}
|
|
2012
|
+
return diff;
|
|
2013
|
+
};
|
|
2014
|
+
const claimKeys = (entry, keys) => {
|
|
2015
|
+
for (const key of keys) {
|
|
2016
|
+
if (conditionalKeys.has(key)) {
|
|
2017
|
+
return bailout(input, "local/dynamic-style-value", `Multiple dynamic props contribute ${key}; their interaction cannot be resolved at compile time`, entry.value.span);
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
return null;
|
|
2021
|
+
};
|
|
1907
2022
|
for (const entry of dynamicStyleEntries) {
|
|
2023
|
+
const shape = entry.value.kind === "bailout" ? nativeDynamicShape(entry.name, component, entry.value.dynamic) : null;
|
|
1908
2024
|
if (entry.value.kind === "conditional" && directStyleName(entry.name, component) !== "opacity") {
|
|
1909
2025
|
let serializeNativeTree = function(node) {
|
|
1910
2026
|
if (node.kind === "leaf") {
|
|
@@ -1919,47 +2035,54 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1919
2035
|
const leaves = (0, import_compiler_core.collectLeaves)(tree);
|
|
1920
2036
|
const leafDiffs = /* @__PURE__ */ new Map();
|
|
1921
2037
|
for (const leaf of leaves) {
|
|
1922
|
-
const
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (!staticObject(branchStyle)) {
|
|
1926
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch did not resolve to a static native style`, entry.value.span);
|
|
1927
|
-
}
|
|
1928
|
-
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit?.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1929
|
-
if (viewPropsKey === "style") continue;
|
|
1930
|
-
if (JSON.stringify(branchSplit?.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1931
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch changes ${viewPropsKey}, which the compiled style array cannot express`, entry.value.span);
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
for (const key of Object.keys(baseStyleForDiff)) {
|
|
1935
|
-
if (!(key in branchStyle)) {
|
|
1936
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch removes ${key}, which an additive style array cannot express`, entry.value.span);
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
const diff = {};
|
|
1940
|
-
for (const [key, value] of Object.entries(branchStyle)) {
|
|
1941
|
-
if (JSON.stringify(baseStyleForDiff[key]) !== JSON.stringify(value)) {
|
|
1942
|
-
diff[key] = value;
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
if (!isSerializableNativeStyle(diff) || core.containsThemeRef(diff)) {
|
|
1946
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch style is not statically representable`, entry.value.span);
|
|
1947
|
-
}
|
|
1948
|
-
for (const key of Object.keys(diff)) {
|
|
1949
|
-
if (conditionalKeys.has(key)) {
|
|
1950
|
-
return bailout(input, "local/dynamic-style-value", `Multiple conditionals contribute ${key}; their interaction cannot be resolved per-branch`, entry.value.span);
|
|
1951
|
-
}
|
|
2038
|
+
const diff = valueDiff(entry, leaf.value, `Conditional ${entry.name} branch`);
|
|
2039
|
+
if (typeof diff === "string") {
|
|
2040
|
+
return bailout(input, "local/dynamic-style-value", diff, entry.value.span);
|
|
1952
2041
|
}
|
|
2042
|
+
const conflict = claimKeys(entry, Object.keys(diff));
|
|
2043
|
+
if (conflict) return conflict;
|
|
1953
2044
|
leafDiffs.set(leaf, diff);
|
|
1954
2045
|
}
|
|
1955
2046
|
for (const diff of leafDiffs.values()) {
|
|
1956
2047
|
for (const key of Object.keys(diff)) conditionalKeys.add(key);
|
|
1957
2048
|
}
|
|
1958
2049
|
conditionalParts.push(serializeNativeTree(tree));
|
|
2050
|
+
} else if (shape === "domain" && entry.value.kind === "bailout") {
|
|
2051
|
+
const lookup = [];
|
|
2052
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2053
|
+
for (const value of entry.value.dynamic.values) {
|
|
2054
|
+
const diff = valueDiff(entry, value, `${entry.name} value ${JSON.stringify(value)}`);
|
|
2055
|
+
if (typeof diff === "string") {
|
|
2056
|
+
return bailout(input, "local/dynamic-style-value", diff, entry.value.span);
|
|
2057
|
+
}
|
|
2058
|
+
for (const key of Object.keys(diff)) keys.add(key);
|
|
2059
|
+
lookup.push(`${JSON.stringify(String(value))}: ${JSON.stringify(diff)}`);
|
|
2060
|
+
}
|
|
2061
|
+
const conflict = claimKeys(entry, keys);
|
|
2062
|
+
if (conflict) return conflict;
|
|
2063
|
+
for (const key of keys) conditionalKeys.add(key);
|
|
2064
|
+
const index = expressions.length;
|
|
2065
|
+
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
2066
|
+
conditionalParts.push(`({ ${lookup.join(", ")} })[expressions[${index}]]`);
|
|
1959
2067
|
} else {
|
|
2068
|
+
const key = directStyleName(entry.name, component);
|
|
2069
|
+
if (shape === "number") {
|
|
2070
|
+
for (const probe of [7.25, 1031]) {
|
|
2071
|
+
const diff = valueDiff(entry, probe, `${entry.name} number`);
|
|
2072
|
+
if (typeof diff === "string" || JSON.stringify(diff) !== JSON.stringify({ [key]: probe })) {
|
|
2073
|
+
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.name} transforms numbers on native, so its runtime value cannot pass through`, entry.value.span);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
if (key in baseStyleForDiff) {
|
|
2077
|
+
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.name} overlaps a static ${key}`, entry.value.span);
|
|
2078
|
+
}
|
|
2079
|
+
const conflict = claimKeys(entry, [key]);
|
|
2080
|
+
if (conflict) return conflict;
|
|
2081
|
+
conditionalKeys.add(key);
|
|
2082
|
+
}
|
|
1960
2083
|
const index = expressions.length;
|
|
1961
2084
|
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
1962
|
-
plainDynamicParts.push(`${JSON.stringify(
|
|
2085
|
+
plainDynamicParts.push(`${JSON.stringify(key)}: expressions[${index}]`);
|
|
1963
2086
|
}
|
|
1964
2087
|
}
|
|
1965
2088
|
const dynamicStyle = plainDynamicParts.join(", ");
|
|
@@ -490,6 +490,77 @@ const nativePointerEventProps = /* @__PURE__ */ new Set([
|
|
|
490
490
|
"onPointerMove",
|
|
491
491
|
"onPointerUp"
|
|
492
492
|
]);
|
|
493
|
+
const nativeShorthandFamilies = [
|
|
494
|
+
[
|
|
495
|
+
"padding",
|
|
496
|
+
[
|
|
497
|
+
"paddingTop",
|
|
498
|
+
"paddingRight",
|
|
499
|
+
"paddingBottom",
|
|
500
|
+
"paddingLeft"
|
|
501
|
+
],
|
|
502
|
+
/^padding/
|
|
503
|
+
],
|
|
504
|
+
[
|
|
505
|
+
"margin",
|
|
506
|
+
[
|
|
507
|
+
"marginTop",
|
|
508
|
+
"marginRight",
|
|
509
|
+
"marginBottom",
|
|
510
|
+
"marginLeft"
|
|
511
|
+
],
|
|
512
|
+
/^margin/
|
|
513
|
+
],
|
|
514
|
+
[
|
|
515
|
+
"borderWidth",
|
|
516
|
+
[
|
|
517
|
+
"borderTopWidth",
|
|
518
|
+
"borderRightWidth",
|
|
519
|
+
"borderBottomWidth",
|
|
520
|
+
"borderLeftWidth"
|
|
521
|
+
],
|
|
522
|
+
/^border.*Width$/
|
|
523
|
+
],
|
|
524
|
+
[
|
|
525
|
+
"borderColor",
|
|
526
|
+
[
|
|
527
|
+
"borderTopColor",
|
|
528
|
+
"borderRightColor",
|
|
529
|
+
"borderBottomColor",
|
|
530
|
+
"borderLeftColor"
|
|
531
|
+
],
|
|
532
|
+
/^border.*Color$/
|
|
533
|
+
],
|
|
534
|
+
[
|
|
535
|
+
"borderRadius",
|
|
536
|
+
[
|
|
537
|
+
"borderTopLeftRadius",
|
|
538
|
+
"borderTopRightRadius",
|
|
539
|
+
"borderBottomRightRadius",
|
|
540
|
+
"borderBottomLeftRadius"
|
|
541
|
+
],
|
|
542
|
+
/^border.*Radius$/
|
|
543
|
+
]
|
|
544
|
+
];
|
|
545
|
+
function collapseNativeShorthands(style) {
|
|
546
|
+
if (!staticObject(style)) return style;
|
|
547
|
+
const keys = Object.keys(style);
|
|
548
|
+
const collapsed = /* @__PURE__ */ new Map();
|
|
549
|
+
for (const [shorthand, sides, family] of nativeShorthandFamilies) {
|
|
550
|
+
const value = style[sides[0]];
|
|
551
|
+
if (value !== void 0 && !(shorthand in style) && sides.every((side) => style[side] === value) && keys.filter((key) => family.test(key)).length === sides.length) {
|
|
552
|
+
for (const side of sides) collapsed.set(side, shorthand);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (!collapsed.size) return style;
|
|
556
|
+
const out = {};
|
|
557
|
+
for (const key of keys) {
|
|
558
|
+
const shorthand = collapsed.get(key);
|
|
559
|
+
if (!shorthand) out[key] = style[key];
|
|
560
|
+
else if (!(shorthand in out)) out[shorthand] = style[key];
|
|
561
|
+
}
|
|
562
|
+
return out;
|
|
563
|
+
}
|
|
493
564
|
function isSerializableNativeStyle(value) {
|
|
494
565
|
if (value == null || typeof value === "number" || typeof value === "boolean") {
|
|
495
566
|
return true;
|
|
@@ -977,6 +1048,12 @@ function createTamaguiCompilerHost(options) {
|
|
|
977
1048
|
if (dynamic?.type !== "string" || !dynamic.values?.length) return null;
|
|
978
1049
|
return dynamic.values.map(String);
|
|
979
1050
|
};
|
|
1051
|
+
const nativeDynamicShape = (name, component, dynamic) => {
|
|
1052
|
+
if (!dynamic || !canLowerConditionalStyleProp(name, component)) return null;
|
|
1053
|
+
if (dynamic.values?.length) return "domain";
|
|
1054
|
+
if (dynamic.type === "number" && directStyleName(name, component)) return "number";
|
|
1055
|
+
return null;
|
|
1056
|
+
};
|
|
980
1057
|
const conditionalClassEntry = (entry, component) => entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component) || frontendClassDomain(entry, component) !== null;
|
|
981
1058
|
const isInvalidHostStyleProp = (name, component) => {
|
|
982
1059
|
const staticConfig = component.staticConfig;
|
|
@@ -1122,7 +1199,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1122
1199
|
return {
|
|
1123
1200
|
resolveComponent: resolve,
|
|
1124
1201
|
isStyleProp,
|
|
1125
|
-
canLowerDynamicStyleProp(name, component, valueKind) {
|
|
1202
|
+
canLowerDynamicStyleProp(name, component, valueKind, dynamic) {
|
|
1126
1203
|
if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
|
|
1127
1204
|
return true;
|
|
1128
1205
|
}
|
|
@@ -1132,7 +1209,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1132
1209
|
if (!options.disablePartialExtraction && platform === "web" && isFrontendClassName(name, component)) {
|
|
1133
1210
|
return true;
|
|
1134
1211
|
}
|
|
1135
|
-
return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
|
|
1212
|
+
return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && (directStyleName(name, component) === "opacity" || valueKind === "bailout" && nativeDynamicShape(name, component, dynamic) !== null));
|
|
1136
1213
|
},
|
|
1137
1214
|
developmentDebugInstrumentation,
|
|
1138
1215
|
lowerCandidate(input) {
|
|
@@ -1441,7 +1518,7 @@ function createTamaguiCompilerHost(options) {
|
|
|
1441
1518
|
message: zeroRuleMessage(5, { detail: `the animation configured on ${input.element.component.name}` })
|
|
1442
1519
|
});
|
|
1443
1520
|
}
|
|
1444
|
-
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)));
|
|
1521
|
+
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) || entry.value.kind === "bailout" && nativeDynamicShape(entry.name, component, entry.value.dynamic) !== null));
|
|
1445
1522
|
if (dynamicStyleEntries.length > 0 && !laneACoversAll && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
|
|
1446
1523
|
const entry = dynamicStyleEntries[0];
|
|
1447
1524
|
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
|
|
@@ -1653,14 +1730,15 @@ function createTamaguiCompilerHost(options) {
|
|
|
1653
1730
|
return bailout(input, "local/unsupported-target", "Native style output is not a static serializable value");
|
|
1654
1731
|
}
|
|
1655
1732
|
const nativeStyleLocal = unusedIdentifier(input.source, `__TamaguiNativeStyle${input.element.span.start}`);
|
|
1733
|
+
const usesNativeFastPath = !!themedStyleKeys && !!options.experimentalNativeFastPath && dynamicStyleEntries.length === 0 && !input.element.entries.some((entry) => entry.kind === "spread");
|
|
1656
1734
|
const nativeStyleImports = [{
|
|
1657
1735
|
content: `
|
|
1658
|
-
function ${nativeStyleLocal}() { return ${nativeStyleLocal}._ ?? (${nativeStyleLocal}._ = ${JSON.stringify(nativeStyle ?? {})}); } ${nativeStyleLocal}();`,
|
|
1736
|
+
function ${nativeStyleLocal}() { return ${nativeStyleLocal}._ ?? (${nativeStyleLocal}._ = ${JSON.stringify((usesNativeFastPath ? nativeStyle : collapseNativeShorthands(nativeStyle)) ?? {})}); } ${nativeStyleLocal}();`,
|
|
1659
1737
|
origin: input.element.component.span
|
|
1660
1738
|
}];
|
|
1661
1739
|
const nativeStyleSource = `${nativeStyleLocal}._ ?? ${nativeStyleLocal}()`;
|
|
1662
1740
|
let nativeFastPath;
|
|
1663
|
-
if (
|
|
1741
|
+
if (usesNativeFastPath) {
|
|
1664
1742
|
const mappingLocal = unusedIdentifier(input.source, `__TamaguiNativeMapping${input.element.span.start}`);
|
|
1665
1743
|
nativeFastPath = {
|
|
1666
1744
|
mappingLocal,
|
|
@@ -1879,7 +1957,45 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1879
1957
|
const conditionalParts = [];
|
|
1880
1958
|
const conditionalKeys = /* @__PURE__ */ new Set();
|
|
1881
1959
|
const baseStyleForDiff = staticObject(nativeStyleResolved) ? nativeStyleResolved : {};
|
|
1960
|
+
const valueDiff = (entry, value, what) => {
|
|
1961
|
+
const { branchCompleteProps } = propsForConditional(entry, value);
|
|
1962
|
+
const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
|
|
1963
|
+
const branchStyle = branchSplit?.viewProps?.style ?? {};
|
|
1964
|
+
if (!staticObject(branchStyle)) {
|
|
1965
|
+
return `${what} did not resolve to a static native style`;
|
|
1966
|
+
}
|
|
1967
|
+
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit?.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1968
|
+
if (viewPropsKey === "style") continue;
|
|
1969
|
+
if (JSON.stringify(branchSplit?.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1970
|
+
return `${what} changes ${viewPropsKey}, which the compiled style array cannot express`;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
for (const key of Object.keys(baseStyleForDiff)) {
|
|
1974
|
+
if (!(key in branchStyle)) {
|
|
1975
|
+
return `${what} removes ${key}, which an additive style array cannot express`;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
const diff = {};
|
|
1979
|
+
for (const [key, value2] of Object.entries(branchStyle)) {
|
|
1980
|
+
if (JSON.stringify(baseStyleForDiff[key]) !== JSON.stringify(value2)) {
|
|
1981
|
+
diff[key] = value2;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
if (!isSerializableNativeStyle(diff) || core.containsThemeRef(diff)) {
|
|
1985
|
+
return `${what} style is not statically representable`;
|
|
1986
|
+
}
|
|
1987
|
+
return diff;
|
|
1988
|
+
};
|
|
1989
|
+
const claimKeys = (entry, keys) => {
|
|
1990
|
+
for (const key of keys) {
|
|
1991
|
+
if (conditionalKeys.has(key)) {
|
|
1992
|
+
return bailout(input, "local/dynamic-style-value", `Multiple dynamic props contribute ${key}; their interaction cannot be resolved at compile time`, entry.value.span);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
return null;
|
|
1996
|
+
};
|
|
1882
1997
|
for (const entry of dynamicStyleEntries) {
|
|
1998
|
+
const shape = entry.value.kind === "bailout" ? nativeDynamicShape(entry.name, component, entry.value.dynamic) : null;
|
|
1883
1999
|
if (entry.value.kind === "conditional" && directStyleName(entry.name, component) !== "opacity") {
|
|
1884
2000
|
let serializeNativeTree = function(node) {
|
|
1885
2001
|
if (node.kind === "leaf") {
|
|
@@ -1894,47 +2010,54 @@ const ${fastLocal} = require('@tamagui/core')._withNativeStyle(${nativeLocal}, $
|
|
|
1894
2010
|
const leaves = collectLeaves(tree);
|
|
1895
2011
|
const leafDiffs = /* @__PURE__ */ new Map();
|
|
1896
2012
|
for (const leaf of leaves) {
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
if (!staticObject(branchStyle)) {
|
|
1901
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch did not resolve to a static native style`, entry.value.span);
|
|
1902
|
-
}
|
|
1903
|
-
for (const viewPropsKey of /* @__PURE__ */ new Set([...Object.keys(branchSplit?.viewProps ?? {}), ...Object.keys(split.viewProps ?? {})])) {
|
|
1904
|
-
if (viewPropsKey === "style") continue;
|
|
1905
|
-
if (JSON.stringify(branchSplit?.viewProps?.[viewPropsKey]) !== JSON.stringify(split.viewProps?.[viewPropsKey])) {
|
|
1906
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch changes ${viewPropsKey}, which the compiled style array cannot express`, entry.value.span);
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
for (const key of Object.keys(baseStyleForDiff)) {
|
|
1910
|
-
if (!(key in branchStyle)) {
|
|
1911
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch removes ${key}, which an additive style array cannot express`, entry.value.span);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
const diff = {};
|
|
1915
|
-
for (const [key, value] of Object.entries(branchStyle)) {
|
|
1916
|
-
if (JSON.stringify(baseStyleForDiff[key]) !== JSON.stringify(value)) {
|
|
1917
|
-
diff[key] = value;
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
if (!isSerializableNativeStyle(diff) || core.containsThemeRef(diff)) {
|
|
1921
|
-
return bailout(input, "local/dynamic-style-value", `Conditional ${entry.name} branch style is not statically representable`, entry.value.span);
|
|
1922
|
-
}
|
|
1923
|
-
for (const key of Object.keys(diff)) {
|
|
1924
|
-
if (conditionalKeys.has(key)) {
|
|
1925
|
-
return bailout(input, "local/dynamic-style-value", `Multiple conditionals contribute ${key}; their interaction cannot be resolved per-branch`, entry.value.span);
|
|
1926
|
-
}
|
|
2013
|
+
const diff = valueDiff(entry, leaf.value, `Conditional ${entry.name} branch`);
|
|
2014
|
+
if (typeof diff === "string") {
|
|
2015
|
+
return bailout(input, "local/dynamic-style-value", diff, entry.value.span);
|
|
1927
2016
|
}
|
|
2017
|
+
const conflict = claimKeys(entry, Object.keys(diff));
|
|
2018
|
+
if (conflict) return conflict;
|
|
1928
2019
|
leafDiffs.set(leaf, diff);
|
|
1929
2020
|
}
|
|
1930
2021
|
for (const diff of leafDiffs.values()) {
|
|
1931
2022
|
for (const key of Object.keys(diff)) conditionalKeys.add(key);
|
|
1932
2023
|
}
|
|
1933
2024
|
conditionalParts.push(serializeNativeTree(tree));
|
|
2025
|
+
} else if (shape === "domain" && entry.value.kind === "bailout") {
|
|
2026
|
+
const lookup = [];
|
|
2027
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2028
|
+
for (const value of entry.value.dynamic.values) {
|
|
2029
|
+
const diff = valueDiff(entry, value, `${entry.name} value ${JSON.stringify(value)}`);
|
|
2030
|
+
if (typeof diff === "string") {
|
|
2031
|
+
return bailout(input, "local/dynamic-style-value", diff, entry.value.span);
|
|
2032
|
+
}
|
|
2033
|
+
for (const key of Object.keys(diff)) keys.add(key);
|
|
2034
|
+
lookup.push(`${JSON.stringify(String(value))}: ${JSON.stringify(diff)}`);
|
|
2035
|
+
}
|
|
2036
|
+
const conflict = claimKeys(entry, keys);
|
|
2037
|
+
if (conflict) return conflict;
|
|
2038
|
+
for (const key of keys) conditionalKeys.add(key);
|
|
2039
|
+
const index = expressions.length;
|
|
2040
|
+
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
2041
|
+
conditionalParts.push(`({ ${lookup.join(", ")} })[expressions[${index}]]`);
|
|
1934
2042
|
} else {
|
|
2043
|
+
const key = directStyleName(entry.name, component);
|
|
2044
|
+
if (shape === "number") {
|
|
2045
|
+
for (const probe of [7.25, 1031]) {
|
|
2046
|
+
const diff = valueDiff(entry, probe, `${entry.name} number`);
|
|
2047
|
+
if (typeof diff === "string" || JSON.stringify(diff) !== JSON.stringify({ [key]: probe })) {
|
|
2048
|
+
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.name} transforms numbers on native, so its runtime value cannot pass through`, entry.value.span);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
if (key in baseStyleForDiff) {
|
|
2052
|
+
return bailout(input, "local/dynamic-style-value", `Style prop ${entry.name} overlaps a static ${key}`, entry.value.span);
|
|
2053
|
+
}
|
|
2054
|
+
const conflict = claimKeys(entry, [key]);
|
|
2055
|
+
if (conflict) return conflict;
|
|
2056
|
+
conditionalKeys.add(key);
|
|
2057
|
+
}
|
|
1935
2058
|
const index = expressions.length;
|
|
1936
2059
|
expressions.push(input.source.slice(entry.value.span.start, entry.value.span.end));
|
|
1937
|
-
plainDynamicParts.push(`${JSON.stringify(
|
|
2060
|
+
plainDynamicParts.push(`${JSON.stringify(key)}: expressions[${index}]`);
|
|
1938
2061
|
}
|
|
1939
2062
|
}
|
|
1940
2063
|
const dynamicStyle = plainDynamicParts.join(", ");
|