@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.
@@ -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 (themedStyleKeys && options.experimentalNativeFastPath && dynamicStyleEntries.length === 0 && !input.element.entries.some((entry) => entry.kind === "spread")) {
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 { branchCompleteProps } = propsForConditional(entry, leaf.value);
1923
- const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
1924
- const branchStyle = branchSplit?.viewProps?.style ?? {};
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(directStyleName(entry.name, component))}: expressions[${index}]`);
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 (themedStyleKeys && options.experimentalNativeFastPath && dynamicStyleEntries.length === 0 && !input.element.entries.some((entry) => entry.kind === "spread")) {
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 { branchCompleteProps } = propsForConditional(entry, leaf.value);
1898
- const branchSplit = resolveSplitStyles(branchCompleteProps, component.staticConfig, cssAnimationDriver, component.displayName);
1899
- const branchStyle = branchSplit?.viewProps?.style ?? {};
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(directStyleName(entry.name, component))}: expressions[${index}]`);
2060
+ plainDynamicParts.push(`${JSON.stringify(key)}: expressions[${index}]`);
1938
2061
  }
1939
2062
  }
1940
2063
  const dynamicStyle = plainDynamicParts.join(", ");