@tamagui/static 3.0.0-beta.889.1 → 3.0.0-beta.901.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.
@@ -963,7 +963,17 @@ function createTamaguiCompilerHost(options) {
963
963
  "animatedBy",
964
964
  "render"
965
965
  ]);
966
- const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && !runtimeOnlyStyleProps.has(name);
966
+ const isFrontendClassName = (name, component) => name === "className" && !!component.staticConfig.styleFrontend;
967
+ const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && (!runtimeOnlyStyleProps.has(name) || isFrontendClassName(name, component));
968
+ const frontendClassDomain = (entry, component) => {
969
+ if (entry.kind !== "prop" || entry.value.kind !== "bailout" || !isFrontendClassName(entry.name, component)) {
970
+ return null;
971
+ }
972
+ const dynamic = entry.value.dynamic;
973
+ if (dynamic?.type !== "string" || !dynamic.values?.length) return null;
974
+ return dynamic.values.map(String);
975
+ };
976
+ const conditionalClassEntry = (entry, component) => entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component) || frontendClassDomain(entry, component) !== null;
967
977
  const isInvalidHostStyleProp = (name, component) => {
968
978
  const staticConfig = component.staticConfig;
969
979
  const validStyles = staticConfig.validStyles || (staticConfig.isInput ? import_helpers.stylePropsInput : staticConfig.isText ? import_helpers.stylePropsText : import_helpers.validStyles);
@@ -1115,6 +1125,9 @@ function createTamaguiCompilerHost(options) {
1115
1125
  if (component.staticConfig.resolvers?.length) {
1116
1126
  return false;
1117
1127
  }
1128
+ if (!options.disablePartialExtraction && platform === "web" && isFrontendClassName(name, component)) {
1129
+ return true;
1130
+ }
1118
1131
  return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
1119
1132
  },
1120
1133
  developmentDebugInstrumentation,
@@ -1182,7 +1195,33 @@ function createTamaguiCompilerHost(options) {
1182
1195
  if (platform === "native" && component.domTag === "input" && typeof props.type === "string" && !import_dom.NATIVE_INPUT_TYPES.includes(props.type)) {
1183
1196
  return bailout(input, "local/unsupported-target", `input type ${props.type} has no native text-entry control`);
1184
1197
  }
1185
- const dynamicStyleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && (entry.value.kind === "bailout" || entry.value.kind === "conditional") && isStyleProp(entry.name, component));
1198
+ let styleObjectStatic = null;
1199
+ const styleMemberEntries = [];
1200
+ for (const entry of input.element.entries) {
1201
+ if (entry.kind !== "prop" || entry.name !== "style" || entry.value.kind !== "object") {
1202
+ continue;
1203
+ }
1204
+ styleObjectStatic = {};
1205
+ for (const member of entry.value.members) {
1206
+ if (member.value.kind === "static") {
1207
+ styleObjectStatic[member.name] = member.value.value;
1208
+ continue;
1209
+ }
1210
+ if (!isStyleProp(member.name, component)) {
1211
+ return bailout(input, "local/dynamic-style-value", `Style prop ${member.name} could not be evaluated`, member.span);
1212
+ }
1213
+ styleMemberEntries.push({
1214
+ kind: "prop",
1215
+ name: member.name,
1216
+ span: member.span,
1217
+ value: member.value,
1218
+ styleMember: true
1219
+ });
1220
+ }
1221
+ if (Object.keys(styleObjectStatic).length === 0) styleObjectStatic = null;
1222
+ }
1223
+ if (styleObjectStatic) props.style = styleObjectStatic;
1224
+ const dynamicStyleEntries = [...input.element.entries.filter((entry) => entry.kind === "prop" && (entry.value.kind === "bailout" || entry.value.kind === "conditional") && isStyleProp(entry.name, component)), ...styleMemberEntries];
1186
1225
  {
1187
1226
  const needsRuntimeMapping = (name) => runtimeEventProps.has(name) || platform === "native" && !component.domTag && nativePointerEventProps.has(name);
1188
1227
  const directRuntimeEvent = input.element.entries.find((entry) => entry.kind === "prop" && needsRuntimeMapping(entry.name));
@@ -1213,66 +1252,92 @@ function createTamaguiCompilerHost(options) {
1213
1252
  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")));
1214
1253
  const runtimeAnimationRequired = animationNames.has("transition") && resolvedCssTransition === null || [...animationNames].some((name) => name !== "transition" && name !== "animatedBy" && name !== "animateOnly") || animatedByNeedsRuntime;
1215
1254
  let dynamicHostStyleProperties = null;
1255
+ let laneAEntries = [];
1256
+ const laneAOwners = /* @__PURE__ */ new Set();
1257
+ const laneAMemberOwners = /* @__PURE__ */ new Set();
1258
+ const conflictsWithInline = (owners, dynamicOwners, memberOwners) => [...owners].some((owner) => !memberOwners.has(owner) && cssOwnersConflict(/* @__PURE__ */ new Set([owner]), dynamicOwners));
1259
+ const laneAAttempts = [dynamicStyleEntries];
1260
+ {
1261
+ const rest2 = dynamicStyleEntries.filter((entry) => !conditionalClassEntry(entry, component));
1262
+ if (rest2.length > 0 && rest2.length < dynamicStyleEntries.length) {
1263
+ laneAAttempts.push(rest2);
1264
+ }
1265
+ }
1216
1266
  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")) {
1217
- const seen = /* @__PURE__ */ new Set();
1218
- const properties = [];
1219
- const dynamicOwners = /* @__PURE__ */ new Set();
1220
- for (const entry of dynamicStyleEntries) {
1221
- if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional") {
1222
- continue;
1223
- }
1224
- const name = directStyleName(entry.name, component);
1225
- if (!name || seen.has(name)) {
1226
- properties.length = 0;
1227
- break;
1228
- }
1229
- const owners = dynamicStyleOwners(name, component.staticConfig);
1230
- if (!owners) {
1231
- properties.length = 0;
1232
- break;
1233
- }
1234
- let property = null;
1235
- const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1236
- if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1237
- property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1238
- } else if (entry.value.kind === "bailout" && owners.has(name)) {
1239
- const dynamic = entry.value.dynamic;
1240
- if (dynamic?.type === "number") {
1241
- property = `${JSON.stringify(name)}: (${expression})`;
1242
- } else if (dynamic?.type === "string" && dynamic.values?.length) {
1243
- let valuesStayLiteral = true;
1244
- for (const value of dynamic.values) {
1245
- const split2 = resolveSplitStyles({ [entry.name]: value }, partialStaticConfig(component.staticConfig));
1246
- const atomics = Object.values(split2?.rulesToInsert ?? {});
1247
- if (atomics.length !== 1 || atomics[0]?.[import_helpers.StyleObjectProperty] !== name || atomics[0]?.[import_helpers.StyleObjectValue] !== value) {
1248
- valuesStayLiteral = false;
1249
- break;
1250
- }
1251
- }
1252
- if (valuesStayLiteral) {
1267
+ for (const attempt of laneAAttempts) {
1268
+ const seen = /* @__PURE__ */ new Set();
1269
+ const properties = [];
1270
+ const dynamicOwners = /* @__PURE__ */ new Set();
1271
+ const memberOwners = /* @__PURE__ */ new Set();
1272
+ for (const entry of attempt) {
1273
+ if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional") {
1274
+ continue;
1275
+ }
1276
+ const name = directStyleName(entry.name, component);
1277
+ if (!name || seen.has(name)) {
1278
+ properties.length = 0;
1279
+ break;
1280
+ }
1281
+ const owners = dynamicStyleOwners(name, component.staticConfig);
1282
+ if (!owners) {
1283
+ properties.length = 0;
1284
+ break;
1285
+ }
1286
+ let property = null;
1287
+ const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1288
+ if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1289
+ property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1290
+ } else if (entry.value.kind === "bailout" && owners.has(name)) {
1291
+ const dynamic = entry.value.dynamic;
1292
+ if (dynamic?.type === "number") {
1253
1293
  property = `${JSON.stringify(name)}: (${expression})`;
1294
+ } else if (dynamic?.type === "string" && dynamic.values?.length) {
1295
+ let valuesStayLiteral = true;
1296
+ for (const value of dynamic.values) {
1297
+ const split2 = resolveSplitStyles({ [entry.name]: value }, partialStaticConfig(component.staticConfig));
1298
+ const atomics = Object.values(split2?.rulesToInsert ?? {});
1299
+ if (atomics.length !== 1 || atomics[0]?.[import_helpers.StyleObjectProperty] !== name || atomics[0]?.[import_helpers.StyleObjectValue] !== value) {
1300
+ valuesStayLiteral = false;
1301
+ break;
1302
+ }
1303
+ }
1304
+ if (valuesStayLiteral) {
1305
+ property = `${JSON.stringify(name)}: (${expression})`;
1306
+ }
1254
1307
  }
1255
1308
  }
1309
+ if (!property) {
1310
+ properties.length = 0;
1311
+ break;
1312
+ }
1313
+ seen.add(name);
1314
+ for (const owner of owners) {
1315
+ dynamicOwners.add(owner);
1316
+ if (entry.styleMember) memberOwners.add(owner);
1317
+ }
1318
+ properties.push(property);
1256
1319
  }
1257
- if (!property) {
1258
- properties.length = 0;
1320
+ if (properties.length === attempt.length && !input.element.entries.some((entry) => {
1321
+ if (entry.kind !== "prop" || entry.value.kind !== "static") return false;
1322
+ const name = directStyleName(entry.name, component);
1323
+ if (!name) return false;
1324
+ const owners = styleOwners(name, entry.value.value, component.staticConfig);
1325
+ return !!owners && conflictsWithInline(owners, dynamicOwners, memberOwners);
1326
+ }) && !Object.entries(staticObject(props.style) ? props.style : {}).some(([name, value]) => {
1327
+ const owners = styleOwners(name, value, component.staticConfig);
1328
+ return !!owners && cssOwnersConflict(owners, dynamicOwners);
1329
+ })) {
1330
+ dynamicHostStyleProperties = properties;
1331
+ laneAEntries = attempt;
1332
+ for (const owner of dynamicOwners) laneAOwners.add(owner);
1333
+ for (const owner of memberOwners) laneAMemberOwners.add(owner);
1259
1334
  break;
1260
1335
  }
1261
- seen.add(name);
1262
- for (const owner of owners) dynamicOwners.add(owner);
1263
- properties.push(property);
1264
- }
1265
- if (properties.length === dynamicStyleEntries.length && !input.element.entries.some((entry) => {
1266
- if (entry.kind !== "prop" || entry.value.kind !== "static") return false;
1267
- const name = directStyleName(entry.name, component);
1268
- if (!name) return false;
1269
- const owners = styleOwners(name, entry.value.value, component.staticConfig);
1270
- return !!owners && cssOwnersConflict(owners, dynamicOwners);
1271
- })) {
1272
- dynamicHostStyleProperties = properties;
1273
1336
  }
1274
1337
  }
1275
- 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));
1338
+ const laneACoversAll = dynamicHostStyleProperties !== null && laneAEntries.length === dynamicStyleEntries.length;
1339
+ const webClassEntries = dynamicHostStyleProperties === null ? dynamicStyleEntries : dynamicStyleEntries.filter((entry) => !laneAEntries.includes(entry));
1340
+ const supportsWebConditionalClasses = platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && !laneACoversAll && webClassEntries.length > 0 && webClassEntries.every((entry) => conditionalClassEntry(entry, component));
1276
1341
  const themeEntry = componentOnlyProp("theme");
1277
1342
  const themeInverseEntry = componentOnlyProp("themeInverse");
1278
1343
  const themeBoundary = themeEntry.unknown || "theme" in props;
@@ -1296,7 +1361,7 @@ function createTamaguiCompilerHost(options) {
1296
1361
  message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `the animation configured on ${input.element.component.name}` })
1297
1362
  });
1298
1363
  }
1299
- if (platform === "web" && (dynamicStyleEntries.length > 0 || runtimeAnimationRequired) && dynamicHostStyleProperties === null && !supportsWebConditionalClasses && component.partialRuntimeSafe) {
1364
+ if (platform === "web" && (dynamicStyleEntries.length > 0 || runtimeAnimationRequired) && !laneACoversAll && !supportsWebConditionalClasses && component.partialRuntimeSafe) {
1300
1365
  const hasSpread = input.element.entries.some((entry) => entry.kind === "spread" && entry.value.kind !== "static");
1301
1366
  const unsupportedRuntimeStyle = input.element.entries.find((entry) => entry.kind === "prop" && isStyleProp(entry.name, component) && !runtimeAnimationProps.has(entry.name) && !directStyleName(entry.name, component));
1302
1367
  if (!hasSpread && !unsupportedRuntimeStyle) {
@@ -1380,7 +1445,7 @@ function createTamaguiCompilerHost(options) {
1380
1445
  });
1381
1446
  }
1382
1447
  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)));
1383
- if (dynamicStyleEntries.length > 0 && dynamicHostStyleProperties === null && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
1448
+ if (dynamicStyleEntries.length > 0 && !laneACoversAll && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
1384
1449
  const entry = dynamicStyleEntries[0];
1385
1450
  return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
1386
1451
  }
@@ -1397,6 +1462,13 @@ function createTamaguiCompilerHost(options) {
1397
1462
  }
1398
1463
  const propsForConditional = (target, value) => {
1399
1464
  const branchProps = {};
1465
+ if (styleObjectStatic) branchProps.style = styleObjectStatic;
1466
+ if (target.styleMember) {
1467
+ branchProps.style = {
1468
+ ...styleObjectStatic,
1469
+ [target.name]: value
1470
+ };
1471
+ }
1400
1472
  for (const entry of input.element.entries) {
1401
1473
  if (entry === target) {
1402
1474
  branchProps[target.name] = value;
@@ -2005,22 +2077,22 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2005
2077
  const staticClasses = new Set(baseStaticClasses);
2006
2078
  const webConditionalCSS = [];
2007
2079
  const webConditionalKeys = /* @__PURE__ */ new Set();
2008
- const webConditionalEntries = supportsWebConditionalClasses ? dynamicStyleEntries.filter((entry) => entry.value.kind === "conditional") : [];
2080
+ const webConditionalEntries = supportsWebConditionalClasses ? webClassEntries : [];
2009
2081
  for (const entry of webConditionalEntries) {
2010
2082
  let serializeWebTree = function(node) {
2011
- if (node.kind === "leaf") {
2012
- const artifacts2 = leafArtifactsMap.get(node);
2013
- const only = artifacts2 ? artifacts2.classes.filter((item) => !sharedInConditional.has(item)) : [];
2014
- return JSON.stringify(only.join(" "));
2015
- }
2083
+ if (node.kind === "leaf") return JSON.stringify(leafClasses(node));
2016
2084
  const test = input.source.slice(node.test.start, node.test.end);
2017
2085
  const truePart = serializeWebTree(node.whenTrue);
2018
2086
  const falsePart = serializeWebTree(node.whenFalse);
2019
2087
  return `(${test}) ? ${truePart} : ${falsePart}`;
2020
2088
  };
2021
- if (entry.value.kind !== "conditional") continue;
2022
- const tree = entry.value.tree;
2023
- const leaves = (0, import_compiler_core.collectLeaves)(tree);
2089
+ const tree = entry.value.kind === "conditional" ? entry.value.tree : null;
2090
+ const domain = frontendClassDomain(entry, component);
2091
+ if (!tree && !domain) continue;
2092
+ const leaves = tree ? (0, import_compiler_core.collectLeaves)(tree) : domain.map((value) => ({
2093
+ value,
2094
+ dependencies: []
2095
+ }));
2024
2096
  const leafArtifactsMap = /* @__PURE__ */ new Map();
2025
2097
  const entryConditionalKeys = /* @__PURE__ */ new Set();
2026
2098
  for (const leaf of leaves) {
@@ -2056,6 +2128,9 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2056
2128
  }
2057
2129
  entryConditionalKeys.add(key);
2058
2130
  }
2131
+ if (conflictsWithInline(changedKeys, laneAOwners, laneAMemberOwners)) {
2132
+ return bailout(input, "local/dynamic-style-value", `${entry.name} and an inline dynamic style both contribute a CSS property; their precedence cannot be resolved per-branch`, entry.value.span);
2133
+ }
2059
2134
  const branchArtifacts = extractedStyleArtifacts(branchSplit, branchProps, options.tamaguiConfig, !component.domTag, Boolean(component.staticConfig.styleFrontend));
2060
2135
  leafArtifactsMap.set(leaf, {
2061
2136
  classes: branchArtifacts.className.split(" ").filter(Boolean),
@@ -2074,8 +2149,18 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2074
2149
  for (const cls of sharedInConditional) {
2075
2150
  if (!baseStaticClasses.has(cls)) staticClasses.add(cls);
2076
2151
  }
2077
- const classExpr = serializeWebTree(tree);
2078
- programClassSources.push(classExpr);
2152
+ const leafClasses = (leaf) => {
2153
+ const artifacts2 = leafArtifactsMap.get(leaf);
2154
+ const only = artifacts2 ? artifacts2.classes.filter((item) => !sharedInConditional.has(item)) : [];
2155
+ return only.join(" ");
2156
+ };
2157
+ if (tree) {
2158
+ programClassSources.push(serializeWebTree(tree));
2159
+ } else {
2160
+ const table = Object.fromEntries(leaves.map((leaf) => [leaf.value, leafClasses(leaf)]));
2161
+ const key = input.source.slice(entry.value.span.start, entry.value.span.end);
2162
+ programClassSources.push(`(${JSON.stringify(table)})[${key}]`);
2163
+ }
2079
2164
  }
2080
2165
  const webClassName = [...staticClasses].join(" ");
2081
2166
  const hasStyleProgram = programClassSources.length > 0;
@@ -938,7 +938,17 @@ function createTamaguiCompilerHost(options) {
938
938
  "animatedBy",
939
939
  "render"
940
940
  ]);
941
- const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && !runtimeOnlyStyleProps.has(name);
941
+ const isFrontendClassName = (name, component) => name === "className" && !!component.staticConfig.styleFrontend;
942
+ const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && (!runtimeOnlyStyleProps.has(name) || isFrontendClassName(name, component));
943
+ const frontendClassDomain = (entry, component) => {
944
+ if (entry.kind !== "prop" || entry.value.kind !== "bailout" || !isFrontendClassName(entry.name, component)) {
945
+ return null;
946
+ }
947
+ const dynamic = entry.value.dynamic;
948
+ if (dynamic?.type !== "string" || !dynamic.values?.length) return null;
949
+ return dynamic.values.map(String);
950
+ };
951
+ const conditionalClassEntry = (entry, component) => entry.value.kind === "conditional" && canLowerConditionalStyleProp(entry.name, component) || frontendClassDomain(entry, component) !== null;
942
952
  const isInvalidHostStyleProp = (name, component) => {
943
953
  const staticConfig = component.staticConfig;
944
954
  const validStyles$1 = staticConfig.validStyles || (staticConfig.isInput ? stylePropsInput : staticConfig.isText ? stylePropsText : validStyles);
@@ -1090,6 +1100,9 @@ function createTamaguiCompilerHost(options) {
1090
1100
  if (component.staticConfig.resolvers?.length) {
1091
1101
  return false;
1092
1102
  }
1103
+ if (!options.disablePartialExtraction && platform === "web" && isFrontendClassName(name, component)) {
1104
+ return true;
1105
+ }
1093
1106
  return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
1094
1107
  },
1095
1108
  developmentDebugInstrumentation,
@@ -1157,7 +1170,33 @@ function createTamaguiCompilerHost(options) {
1157
1170
  if (platform === "native" && component.domTag === "input" && typeof props.type === "string" && !NATIVE_INPUT_TYPES.includes(props.type)) {
1158
1171
  return bailout(input, "local/unsupported-target", `input type ${props.type} has no native text-entry control`);
1159
1172
  }
1160
- const dynamicStyleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && (entry.value.kind === "bailout" || entry.value.kind === "conditional") && isStyleProp(entry.name, component));
1173
+ let styleObjectStatic = null;
1174
+ const styleMemberEntries = [];
1175
+ for (const entry of input.element.entries) {
1176
+ if (entry.kind !== "prop" || entry.name !== "style" || entry.value.kind !== "object") {
1177
+ continue;
1178
+ }
1179
+ styleObjectStatic = {};
1180
+ for (const member of entry.value.members) {
1181
+ if (member.value.kind === "static") {
1182
+ styleObjectStatic[member.name] = member.value.value;
1183
+ continue;
1184
+ }
1185
+ if (!isStyleProp(member.name, component)) {
1186
+ return bailout(input, "local/dynamic-style-value", `Style prop ${member.name} could not be evaluated`, member.span);
1187
+ }
1188
+ styleMemberEntries.push({
1189
+ kind: "prop",
1190
+ name: member.name,
1191
+ span: member.span,
1192
+ value: member.value,
1193
+ styleMember: true
1194
+ });
1195
+ }
1196
+ if (Object.keys(styleObjectStatic).length === 0) styleObjectStatic = null;
1197
+ }
1198
+ if (styleObjectStatic) props.style = styleObjectStatic;
1199
+ const dynamicStyleEntries = [...input.element.entries.filter((entry) => entry.kind === "prop" && (entry.value.kind === "bailout" || entry.value.kind === "conditional") && isStyleProp(entry.name, component)), ...styleMemberEntries];
1161
1200
  {
1162
1201
  const needsRuntimeMapping = (name) => runtimeEventProps.has(name) || platform === "native" && !component.domTag && nativePointerEventProps.has(name);
1163
1202
  const directRuntimeEvent = input.element.entries.find((entry) => entry.kind === "prop" && needsRuntimeMapping(entry.name));
@@ -1188,66 +1227,92 @@ function createTamaguiCompilerHost(options) {
1188
1227
  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")));
1189
1228
  const runtimeAnimationRequired = animationNames.has("transition") && resolvedCssTransition === null || [...animationNames].some((name) => name !== "transition" && name !== "animatedBy" && name !== "animateOnly") || animatedByNeedsRuntime;
1190
1229
  let dynamicHostStyleProperties = null;
1230
+ let laneAEntries = [];
1231
+ const laneAOwners = /* @__PURE__ */ new Set();
1232
+ const laneAMemberOwners = /* @__PURE__ */ new Set();
1233
+ const conflictsWithInline = (owners, dynamicOwners, memberOwners) => [...owners].some((owner) => !memberOwners.has(owner) && cssOwnersConflict(/* @__PURE__ */ new Set([owner]), dynamicOwners));
1234
+ const laneAAttempts = [dynamicStyleEntries];
1235
+ {
1236
+ const rest2 = dynamicStyleEntries.filter((entry) => !conditionalClassEntry(entry, component));
1237
+ if (rest2.length > 0 && rest2.length < dynamicStyleEntries.length) {
1238
+ laneAAttempts.push(rest2);
1239
+ }
1240
+ }
1191
1241
  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")) {
1192
- const seen = /* @__PURE__ */ new Set();
1193
- const properties = [];
1194
- const dynamicOwners = /* @__PURE__ */ new Set();
1195
- for (const entry of dynamicStyleEntries) {
1196
- if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional") {
1197
- continue;
1198
- }
1199
- const name = directStyleName(entry.name, component);
1200
- if (!name || seen.has(name)) {
1201
- properties.length = 0;
1202
- break;
1203
- }
1204
- const owners = dynamicStyleOwners(name, component.staticConfig);
1205
- if (!owners) {
1206
- properties.length = 0;
1207
- break;
1208
- }
1209
- let property = null;
1210
- const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1211
- if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1212
- property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1213
- } else if (entry.value.kind === "bailout" && owners.has(name)) {
1214
- const dynamic = entry.value.dynamic;
1215
- if (dynamic?.type === "number") {
1216
- property = `${JSON.stringify(name)}: (${expression})`;
1217
- } else if (dynamic?.type === "string" && dynamic.values?.length) {
1218
- let valuesStayLiteral = true;
1219
- for (const value of dynamic.values) {
1220
- const split2 = resolveSplitStyles({ [entry.name]: value }, partialStaticConfig(component.staticConfig));
1221
- const atomics = Object.values(split2?.rulesToInsert ?? {});
1222
- if (atomics.length !== 1 || atomics[0]?.[StyleObjectProperty] !== name || atomics[0]?.[StyleObjectValue] !== value) {
1223
- valuesStayLiteral = false;
1224
- break;
1225
- }
1226
- }
1227
- if (valuesStayLiteral) {
1242
+ for (const attempt of laneAAttempts) {
1243
+ const seen = /* @__PURE__ */ new Set();
1244
+ const properties = [];
1245
+ const dynamicOwners = /* @__PURE__ */ new Set();
1246
+ const memberOwners = /* @__PURE__ */ new Set();
1247
+ for (const entry of attempt) {
1248
+ if (entry.kind !== "prop" || entry.value.kind !== "bailout" && entry.value.kind !== "conditional") {
1249
+ continue;
1250
+ }
1251
+ const name = directStyleName(entry.name, component);
1252
+ if (!name || seen.has(name)) {
1253
+ properties.length = 0;
1254
+ break;
1255
+ }
1256
+ const owners = dynamicStyleOwners(name, component.staticConfig);
1257
+ if (!owners) {
1258
+ properties.length = 0;
1259
+ break;
1260
+ }
1261
+ let property = null;
1262
+ const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1263
+ if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1264
+ property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1265
+ } else if (entry.value.kind === "bailout" && owners.has(name)) {
1266
+ const dynamic = entry.value.dynamic;
1267
+ if (dynamic?.type === "number") {
1228
1268
  property = `${JSON.stringify(name)}: (${expression})`;
1269
+ } else if (dynamic?.type === "string" && dynamic.values?.length) {
1270
+ let valuesStayLiteral = true;
1271
+ for (const value of dynamic.values) {
1272
+ const split2 = resolveSplitStyles({ [entry.name]: value }, partialStaticConfig(component.staticConfig));
1273
+ const atomics = Object.values(split2?.rulesToInsert ?? {});
1274
+ if (atomics.length !== 1 || atomics[0]?.[StyleObjectProperty] !== name || atomics[0]?.[StyleObjectValue] !== value) {
1275
+ valuesStayLiteral = false;
1276
+ break;
1277
+ }
1278
+ }
1279
+ if (valuesStayLiteral) {
1280
+ property = `${JSON.stringify(name)}: (${expression})`;
1281
+ }
1229
1282
  }
1230
1283
  }
1284
+ if (!property) {
1285
+ properties.length = 0;
1286
+ break;
1287
+ }
1288
+ seen.add(name);
1289
+ for (const owner of owners) {
1290
+ dynamicOwners.add(owner);
1291
+ if (entry.styleMember) memberOwners.add(owner);
1292
+ }
1293
+ properties.push(property);
1231
1294
  }
1232
- if (!property) {
1233
- properties.length = 0;
1295
+ if (properties.length === attempt.length && !input.element.entries.some((entry) => {
1296
+ if (entry.kind !== "prop" || entry.value.kind !== "static") return false;
1297
+ const name = directStyleName(entry.name, component);
1298
+ if (!name) return false;
1299
+ const owners = styleOwners(name, entry.value.value, component.staticConfig);
1300
+ return !!owners && conflictsWithInline(owners, dynamicOwners, memberOwners);
1301
+ }) && !Object.entries(staticObject(props.style) ? props.style : {}).some(([name, value]) => {
1302
+ const owners = styleOwners(name, value, component.staticConfig);
1303
+ return !!owners && cssOwnersConflict(owners, dynamicOwners);
1304
+ })) {
1305
+ dynamicHostStyleProperties = properties;
1306
+ laneAEntries = attempt;
1307
+ for (const owner of dynamicOwners) laneAOwners.add(owner);
1308
+ for (const owner of memberOwners) laneAMemberOwners.add(owner);
1234
1309
  break;
1235
1310
  }
1236
- seen.add(name);
1237
- for (const owner of owners) dynamicOwners.add(owner);
1238
- properties.push(property);
1239
- }
1240
- if (properties.length === dynamicStyleEntries.length && !input.element.entries.some((entry) => {
1241
- if (entry.kind !== "prop" || entry.value.kind !== "static") return false;
1242
- const name = directStyleName(entry.name, component);
1243
- if (!name) return false;
1244
- const owners = styleOwners(name, entry.value.value, component.staticConfig);
1245
- return !!owners && cssOwnersConflict(owners, dynamicOwners);
1246
- })) {
1247
- dynamicHostStyleProperties = properties;
1248
1311
  }
1249
1312
  }
1250
- 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));
1313
+ const laneACoversAll = dynamicHostStyleProperties !== null && laneAEntries.length === dynamicStyleEntries.length;
1314
+ const webClassEntries = dynamicHostStyleProperties === null ? dynamicStyleEntries : dynamicStyleEntries.filter((entry) => !laneAEntries.includes(entry));
1315
+ const supportsWebConditionalClasses = platform === "web" && !options.disablePartialExtraction && (input.element.form === "jsx" || input.element.propsSpan !== null) && !laneACoversAll && webClassEntries.length > 0 && webClassEntries.every((entry) => conditionalClassEntry(entry, component));
1251
1316
  const themeEntry = componentOnlyProp("theme");
1252
1317
  const themeInverseEntry = componentOnlyProp("themeInverse");
1253
1318
  const themeBoundary = themeEntry.unknown || "theme" in props;
@@ -1271,7 +1336,7 @@ function createTamaguiCompilerHost(options) {
1271
1336
  message: zeroRuleMessage(5, { detail: `the animation configured on ${input.element.component.name}` })
1272
1337
  });
1273
1338
  }
1274
- if (platform === "web" && (dynamicStyleEntries.length > 0 || runtimeAnimationRequired) && dynamicHostStyleProperties === null && !supportsWebConditionalClasses && component.partialRuntimeSafe) {
1339
+ if (platform === "web" && (dynamicStyleEntries.length > 0 || runtimeAnimationRequired) && !laneACoversAll && !supportsWebConditionalClasses && component.partialRuntimeSafe) {
1275
1340
  const hasSpread = input.element.entries.some((entry) => entry.kind === "spread" && entry.value.kind !== "static");
1276
1341
  const unsupportedRuntimeStyle = input.element.entries.find((entry) => entry.kind === "prop" && isStyleProp(entry.name, component) && !runtimeAnimationProps.has(entry.name) && !directStyleName(entry.name, component));
1277
1342
  if (!hasSpread && !unsupportedRuntimeStyle) {
@@ -1355,7 +1420,7 @@ function createTamaguiCompilerHost(options) {
1355
1420
  });
1356
1421
  }
1357
1422
  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)));
1358
- if (dynamicStyleEntries.length > 0 && dynamicHostStyleProperties === null && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
1423
+ if (dynamicStyleEntries.length > 0 && !laneACoversAll && !supportsNativeDynamicStyles && !supportsWebConditionalClasses) {
1359
1424
  const entry = dynamicStyleEntries[0];
1360
1425
  return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
1361
1426
  }
@@ -1372,6 +1437,13 @@ function createTamaguiCompilerHost(options) {
1372
1437
  }
1373
1438
  const propsForConditional = (target, value) => {
1374
1439
  const branchProps = {};
1440
+ if (styleObjectStatic) branchProps.style = styleObjectStatic;
1441
+ if (target.styleMember) {
1442
+ branchProps.style = {
1443
+ ...styleObjectStatic,
1444
+ [target.name]: value
1445
+ };
1446
+ }
1375
1447
  for (const entry of input.element.entries) {
1376
1448
  if (entry === target) {
1377
1449
  branchProps[target.name] = value;
@@ -1980,22 +2052,22 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
1980
2052
  const staticClasses = new Set(baseStaticClasses);
1981
2053
  const webConditionalCSS = [];
1982
2054
  const webConditionalKeys = /* @__PURE__ */ new Set();
1983
- const webConditionalEntries = supportsWebConditionalClasses ? dynamicStyleEntries.filter((entry) => entry.value.kind === "conditional") : [];
2055
+ const webConditionalEntries = supportsWebConditionalClasses ? webClassEntries : [];
1984
2056
  for (const entry of webConditionalEntries) {
1985
2057
  let serializeWebTree = function(node) {
1986
- if (node.kind === "leaf") {
1987
- const artifacts2 = leafArtifactsMap.get(node);
1988
- const only = artifacts2 ? artifacts2.classes.filter((item) => !sharedInConditional.has(item)) : [];
1989
- return JSON.stringify(only.join(" "));
1990
- }
2058
+ if (node.kind === "leaf") return JSON.stringify(leafClasses(node));
1991
2059
  const test = input.source.slice(node.test.start, node.test.end);
1992
2060
  const truePart = serializeWebTree(node.whenTrue);
1993
2061
  const falsePart = serializeWebTree(node.whenFalse);
1994
2062
  return `(${test}) ? ${truePart} : ${falsePart}`;
1995
2063
  };
1996
- if (entry.value.kind !== "conditional") continue;
1997
- const tree = entry.value.tree;
1998
- const leaves = collectLeaves(tree);
2064
+ const tree = entry.value.kind === "conditional" ? entry.value.tree : null;
2065
+ const domain = frontendClassDomain(entry, component);
2066
+ if (!tree && !domain) continue;
2067
+ const leaves = tree ? collectLeaves(tree) : domain.map((value) => ({
2068
+ value,
2069
+ dependencies: []
2070
+ }));
1999
2071
  const leafArtifactsMap = /* @__PURE__ */ new Map();
2000
2072
  const entryConditionalKeys = /* @__PURE__ */ new Set();
2001
2073
  for (const leaf of leaves) {
@@ -2031,6 +2103,9 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2031
2103
  }
2032
2104
  entryConditionalKeys.add(key);
2033
2105
  }
2106
+ if (conflictsWithInline(changedKeys, laneAOwners, laneAMemberOwners)) {
2107
+ return bailout(input, "local/dynamic-style-value", `${entry.name} and an inline dynamic style both contribute a CSS property; their precedence cannot be resolved per-branch`, entry.value.span);
2108
+ }
2034
2109
  const branchArtifacts = extractedStyleArtifacts(branchSplit, branchProps, options.tamaguiConfig, !component.domTag, Boolean(component.staticConfig.styleFrontend));
2035
2110
  leafArtifactsMap.set(leaf, {
2036
2111
  classes: branchArtifacts.className.split(" ").filter(Boolean),
@@ -2049,8 +2124,18 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2049
2124
  for (const cls of sharedInConditional) {
2050
2125
  if (!baseStaticClasses.has(cls)) staticClasses.add(cls);
2051
2126
  }
2052
- const classExpr = serializeWebTree(tree);
2053
- programClassSources.push(classExpr);
2127
+ const leafClasses = (leaf) => {
2128
+ const artifacts2 = leafArtifactsMap.get(leaf);
2129
+ const only = artifacts2 ? artifacts2.classes.filter((item) => !sharedInConditional.has(item)) : [];
2130
+ return only.join(" ");
2131
+ };
2132
+ if (tree) {
2133
+ programClassSources.push(serializeWebTree(tree));
2134
+ } else {
2135
+ const table = Object.fromEntries(leaves.map((leaf) => [leaf.value, leafClasses(leaf)]));
2136
+ const key = input.source.slice(entry.value.span.start, entry.value.span.end);
2137
+ programClassSources.push(`(${JSON.stringify(table)})[${key}]`);
2138
+ }
2054
2139
  }
2055
2140
  const webClassName = [...staticClasses].join(" ");
2056
2141
  const hasStyleProgram = programClassSources.length > 0;