@tamagui/static 3.0.0-beta.831.1 → 3.0.0-beta.881.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.
Files changed (41) hide show
  1. package/dist/cjs/compiler.cjs +17 -5
  2. package/dist/cjs/compilerHost.cjs +142 -38
  3. package/dist/cjs/componentDiscovery.cjs +90 -0
  4. package/dist/cjs/domStructuralPass.cjs +12 -2
  5. package/dist/cjs/exports.cjs +4 -1
  6. package/dist/cjs/extractor/bundleConfig.cjs +23 -0
  7. package/dist/cjs/zero/theme.cjs +5 -20
  8. package/dist/esm/compiler.mjs +18 -6
  9. package/dist/esm/compiler.mjs.map +1 -1
  10. package/dist/esm/compilerHost.mjs +140 -39
  11. package/dist/esm/compilerHost.mjs.map +1 -1
  12. package/dist/esm/componentDiscovery.mjs +65 -0
  13. package/dist/esm/componentDiscovery.mjs.map +1 -0
  14. package/dist/esm/domStructuralPass.mjs +12 -2
  15. package/dist/esm/domStructuralPass.mjs.map +1 -1
  16. package/dist/esm/exports.mjs +4 -1
  17. package/dist/esm/extractor/bundleConfig.mjs +23 -1
  18. package/dist/esm/extractor/bundleConfig.mjs.map +1 -1
  19. package/dist/esm/zero/theme.mjs +5 -20
  20. package/dist/esm/zero/theme.mjs.map +1 -1
  21. package/package.json +17 -17
  22. package/src/compiler.ts +27 -5
  23. package/src/compilerHost.ts +250 -73
  24. package/src/componentDiscovery.ts +95 -0
  25. package/src/domStructuralPass.ts +22 -2
  26. package/src/exports.ts +2 -0
  27. package/src/extractor/bundleConfig.ts +34 -0
  28. package/src/zero/theme.ts +12 -21
  29. package/types/compiler.d.ts +13 -0
  30. package/types/compiler.d.ts.map +1 -1
  31. package/types/compilerHost.d.ts +13 -0
  32. package/types/compilerHost.d.ts.map +1 -1
  33. package/types/componentDiscovery.d.ts +27 -0
  34. package/types/componentDiscovery.d.ts.map +1 -0
  35. package/types/domStructuralPass.d.ts.map +1 -1
  36. package/types/exports.d.ts +2 -0
  37. package/types/exports.d.ts.map +1 -1
  38. package/types/extractor/bundleConfig.d.ts +7 -0
  39. package/types/extractor/bundleConfig.d.ts.map +1 -1
  40. package/types/zero/theme.d.ts +0 -1
  41. package/types/zero/theme.d.ts.map +1 -1
@@ -35,6 +35,7 @@ var import_compiler_core = require("@tamagui/compiler-core");
35
35
  var import_node_fs = require("node:fs");
36
36
  var import_node_module = require("node:module");
37
37
  var import_node_path = __toESM(require("node:path"), 1);
38
+ var import_componentDiscovery = require("./componentDiscovery.cjs");
38
39
  var import_compilerHost = require("./compilerHost.cjs");
39
40
  var import_domStructuralPass = require("./domStructuralPass.cjs");
40
41
  var import_loadTamagui = require("./extractor/loadTamagui.cjs");
@@ -123,6 +124,7 @@ var CompilerFrontend = class {
123
124
  planCaches = /* @__PURE__ */ new Map();
124
125
  moduleRecords = /* @__PURE__ */ new Map();
125
126
  moduleContext = null;
127
+ discovery = new import_componentDiscovery.ComponentDiscovery();
126
128
  /**
127
129
  * One cache per project root and platform. Absent when the project produced
128
130
  * no content stamp, in which case plans are never persisted rather than
@@ -216,14 +218,18 @@ var CompilerFrontend = class {
216
218
  if (!projectInfo.tamaguiConfig || !projectInfo.components) {
217
219
  throw new Error("The compiler requires evaluated Tamagui config and components");
218
220
  }
221
+ const componentModules = input.project.componentModules.map((component) => ({
222
+ moduleName: component.moduleName,
223
+ resolvedId: cleanId(component.id)
224
+ }));
225
+ const registry = (0, import_compilerHost.createComponentRegistry)(projectInfo.components, componentModules);
226
+ this.discovery.seed(registry);
219
227
  const host = (0, import_compilerHost.createTamaguiCompilerHost)({
220
228
  target: input.target,
221
229
  tamaguiConfig: projectInfo.tamaguiConfig,
222
230
  components: projectInfo.components,
223
- componentModules: input.project.componentModules.map((component) => ({
224
- moduleName: component.moduleName,
225
- resolvedId: cleanId(component.id)
226
- })),
231
+ componentModules,
232
+ registry,
227
233
  disablePartialExtraction: input.project.disablePartialExtraction,
228
234
  experimentalNativeFastPath: input.project.experimentalNativeFastPath,
229
235
  zeroRuntime: input.project.zeroRuntime
@@ -237,7 +243,8 @@ var CompilerFrontend = class {
237
243
  planCache: this.planCacheFor(input),
238
244
  async load(id) {
239
245
  return modules.get(id) ?? null;
240
- }
246
+ },
247
+ prepare: (module2) => this.discovery.prepare(module2, registry, input.evaluate)
241
248
  },
242
249
  structuralPass: import_domStructuralPass.domStructuralPass
243
250
  });
@@ -248,10 +255,15 @@ var CompilerFrontend = class {
248
255
  invalidatedIds: [...invalidated].sort()
249
256
  };
250
257
  }
258
+ /** host-resolved ids of every module discovery found components in */
259
+ discoveredModuleIds() {
260
+ return this.discovery.ids();
261
+ }
251
262
  async buildTree(input) {
252
263
  const moduleContext = compilerContext(input);
253
264
  if (this.moduleContext !== moduleContext) {
254
265
  this.moduleRecords.clear();
266
+ this.discovery.clear();
255
267
  this.moduleContext = moduleContext;
256
268
  }
257
269
  const componentBySpecifier = new Map(input.project.componentModules.map((component) => [component.moduleName, (0, import_compiler_core.resolvedModuleId)(cleanId(component.id))]));
@@ -19,7 +19,10 @@ var __copyProps = (to, from, except, desc) => {
19
19
  };
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
  var compilerHost_exports = {};
22
- __export(compilerHost_exports, { createTamaguiCompilerHost: () => createTamaguiCompilerHost });
22
+ __export(compilerHost_exports, {
23
+ createComponentRegistry: () => createComponentRegistry,
24
+ createTamaguiCompilerHost: () => createTamaguiCompilerHost
25
+ });
23
26
  module.exports = __toCommonJS(compilerHost_exports);
24
27
  var import_compiler_core = require("@tamagui/compiler-core");
25
28
  var import_helpers = require("@tamagui/helpers");
@@ -28,6 +31,12 @@ var import_tooling = require("@tamagui/style-grammar/tooling");
28
31
  var import_web = require("@tamagui/web");
29
32
  var import_concatClassName = require("./extractor/concatClassName.cjs");
30
33
  var import_requireTamaguiCore = require("./helpers/requireTamaguiCore.cjs");
34
+ function createComponentRegistry(components, componentModules) {
35
+ return {
36
+ modulesById: new Map(componentModules.map((module2) => [module2.resolvedId, module2.moduleName])),
37
+ componentsByModule: new Map(components.map((component) => [component.moduleName, component]))
38
+ };
39
+ }
31
40
  const DOM_FRONTENDS = /* @__PURE__ */ new Set([
32
41
  "tamagui",
33
42
  "tamagui/dom",
@@ -236,6 +245,11 @@ const runtimeAnimationProps = /* @__PURE__ */ new Set([
236
245
  "animatePresence",
237
246
  "animatedBy"
238
247
  ]);
248
+ const componentOnlyProps = /* @__PURE__ */ new Set([
249
+ "asChild",
250
+ "disableOptimization",
251
+ "themeInverse"
252
+ ]);
239
253
  const cssShorthandConflicts = {
240
254
  background: [
241
255
  "backgroundAttachment",
@@ -412,6 +426,12 @@ const cssShorthandConflicts = {
412
426
  ]
413
427
  };
414
428
  const cssConflictFamilies = [
429
+ /* @__PURE__ */ new Set(["width", "inlineSize"]),
430
+ /* @__PURE__ */ new Set(["minWidth", "minInlineSize"]),
431
+ /* @__PURE__ */ new Set(["maxWidth", "maxInlineSize"]),
432
+ /* @__PURE__ */ new Set(["height", "blockSize"]),
433
+ /* @__PURE__ */ new Set(["minHeight", "minBlockSize"]),
434
+ /* @__PURE__ */ new Set(["maxHeight", "maxBlockSize"]),
415
435
  /* @__PURE__ */ new Set([
416
436
  "marginInline",
417
437
  "marginInlineEnd",
@@ -723,6 +743,7 @@ function webDOMProps(input, tag) {
723
743
  function createTamaguiCompilerHost(options) {
724
744
  const platform = options.target === "native" ? "native" : "web";
725
745
  const core = (0, import_requireTamaguiCore.requireTamaguiCore)(platform);
746
+ const compilerVariantStyleResolver = core.styled(core.View, {}).staticConfig.variantStyleResolver;
726
747
  const firstThemeName = Object.keys(options.tamaguiConfig.themes ?? {})[0] ?? "";
727
748
  const firstTheme = options.tamaguiConfig.themes?.[firstThemeName] ?? {};
728
749
  const theme = firstTheme;
@@ -745,6 +766,27 @@ function createTamaguiCompilerHost(options) {
745
766
  }
746
767
  return false;
747
768
  };
769
+ const platformModifiersRegistered = modifierRegistry.get("web") === "platform" && modifierRegistry.get("native") === "platform";
770
+ const nativeClauseValue = (value) => {
771
+ if (typeof value !== "string" || !flatClausePattern.test(value)) {
772
+ return isClauseObjectValue(value) ? "live" : null;
773
+ }
774
+ if (!platformModifiersRegistered) return "live";
775
+ const parsed = (0, import_tooling.parseValue)(value, modifierRegistry);
776
+ if (!parsed.ok || parsed.value.clauses.length === 0) return "live";
777
+ let payload = parsed.value.base;
778
+ let matched = parsed.value.base !== null;
779
+ for (const clause of parsed.value.clauses) {
780
+ if (clause.modifiers.includes("web")) continue;
781
+ if (clause.modifiers.length !== 1 || clause.modifiers[0] !== "native") return "live";
782
+ payload = clause.payload;
783
+ matched = true;
784
+ }
785
+ return {
786
+ payload,
787
+ matched
788
+ };
789
+ };
748
790
  const configuredAnimationDriver = options.tamaguiConfig.animations;
749
791
  const configuredCssAnimationDriver = platform === "web" && configuredAnimationDriver?.outputStyle === "css" && !options.tamaguiConfig.animationDrivers ? configuredAnimationDriver : null;
750
792
  const resolveStaticCssTransition = (value, transitionPresets) => {
@@ -783,8 +825,7 @@ function createTamaguiCompilerHost(options) {
783
825
  }
784
826
  return resolved.join(" ");
785
827
  };
786
- const modulesById = new Map(options.componentModules.map((module2) => [module2.resolvedId, module2.moduleName]));
787
- const componentsByModule = new Map(options.components.map((component) => [component.moduleName, component]));
828
+ const { modulesById, componentsByModule } = options.registry ?? createComponentRegistry(options.components, options.componentModules);
788
829
  const normalizedStyleConfigs = /* @__PURE__ */ new WeakMap();
789
830
  const normalizeStaticConfig = (staticConfig) => {
790
831
  if (!staticConfig.styleFrontend) return staticConfig;
@@ -840,7 +881,7 @@ function createTamaguiCompilerHost(options) {
840
881
  isInput: row.backing === "textinput",
841
882
  validStyles: {
842
883
  ...import_helpers.validStyles,
843
- ...import_helpers.stylePropsText
884
+ ...row.backing === "textinput" ? import_helpers.stylePropsInput : import_helpers.stylePropsText
844
885
  },
845
886
  defaultProps: {
846
887
  ...base.defaultProps,
@@ -865,25 +906,27 @@ function createTamaguiCompilerHost(options) {
865
906
  if (!base || !staticObject(definition.options.value)) return null;
866
907
  const { variants, defaultVariants, displayName, context, contextProps, ...defaultProps } = definition.options.value;
867
908
  const baseClassName = definition.baseClassName?.kind === "static" && typeof definition.baseClassName.value === "string" ? definition.baseClassName.value : void 0;
909
+ const localStaticConfig = {
910
+ ...base.staticConfig,
911
+ variants: {
912
+ ...base.staticConfig.variants,
913
+ ...variants
914
+ },
915
+ defaultProps: {
916
+ ...base.staticConfig.defaultProps,
917
+ ...defaultProps,
918
+ ...defaultVariants
919
+ },
920
+ defaultVariants,
921
+ baseClassName: [base.staticConfig.baseClassName, baseClassName].filter(Boolean).join(" "),
922
+ context: context ?? base.staticConfig.context,
923
+ contextProps: context ? contextProps : contextProps ?? base.staticConfig.contextProps
924
+ };
925
+ localStaticConfig.variantStyleResolver = compilerVariantStyleResolver;
868
926
  return {
869
927
  key: componentKey(definition.id, definition.name),
870
928
  displayName: displayName || base.displayName,
871
- staticConfig: normalizeStaticConfig({
872
- ...base.staticConfig,
873
- variants: {
874
- ...base.staticConfig.variants,
875
- ...variants
876
- },
877
- defaultProps: {
878
- ...base.staticConfig.defaultProps,
879
- ...defaultProps,
880
- ...defaultVariants
881
- },
882
- defaultVariants,
883
- baseClassName: [base.staticConfig.baseClassName, baseClassName].filter(Boolean).join(" "),
884
- context: context ?? base.staticConfig.context,
885
- contextProps: context ? contextProps : contextProps ?? base.staticConfig.contextProps
886
- })
929
+ staticConfig: normalizeStaticConfig(localStaticConfig)
887
930
  };
888
931
  };
889
932
  const resolve = (element, styledDefinition) => {
@@ -918,8 +961,8 @@ function createTamaguiCompilerHost(options) {
918
961
  const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && !runtimeOnlyStyleProps.has(name);
919
962
  const isInvalidHostStyleProp = (name, component) => {
920
963
  const staticConfig = component.staticConfig;
921
- const validStyles = staticConfig.validStyles || (staticConfig.isText || staticConfig.isInput ? import_helpers.stylePropsText : import_helpers.validStyles);
922
- return name in import_helpers.stylePropsAll && !(0, import_web.isValidStyleKey)(name, validStyles, staticConfig.accept);
964
+ const validStyles = staticConfig.validStyles || (staticConfig.isInput ? import_helpers.stylePropsInput : staticConfig.isText ? import_helpers.stylePropsText : import_helpers.validStyles);
965
+ return name in import_helpers.stylePropsAll && !(0, import_web.isValidStyleKey)(name, validStyles);
923
966
  };
924
967
  const directStyleName = (name, component) => {
925
968
  if (compilerStyleProps.has(name) || name === "style") {
@@ -941,6 +984,7 @@ function createTamaguiCompilerHost(options) {
941
984
  process.env.TAMAGUI_TARGET = platform;
942
985
  try {
943
986
  return core.getSplitStyles(props, staticConfig, theme, firstThemeName, componentState, {
987
+ isStatic: true,
944
988
  resolveValues: platform === "native" ? "except-theme" : "variable",
945
989
  noClass: platform === "native",
946
990
  isAnimated: false,
@@ -1063,6 +1107,9 @@ function createTamaguiCompilerHost(options) {
1063
1107
  if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
1064
1108
  return true;
1065
1109
  }
1110
+ if (component.staticConfig.resolvers?.length) {
1111
+ return false;
1112
+ }
1066
1113
  return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
1067
1114
  },
1068
1115
  developmentDebugInstrumentation,
@@ -1093,9 +1140,30 @@ function createTamaguiCompilerHost(options) {
1093
1140
  props[entry.name] = entry.value.value;
1094
1141
  }
1095
1142
  }
1096
- const disableOptimizationEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "disableOptimization");
1097
- if (disableOptimizationEntry || "disableOptimization" in props) {
1098
- return bailout(input, "local/unsupported-target", "disableOptimization keeps the component on the runtime path", disableOptimizationEntry?.span);
1143
+ if (component.staticConfig.resolvers?.length) {
1144
+ const unresolvedProps = input.element.entries.filter((entry) => entry.kind === "prop" && entry.value.kind !== "static");
1145
+ const onlyStaticBranchConditional = unresolvedProps.length === 1 && unresolvedProps[0]?.kind === "prop" && unresolvedProps[0].value.kind === "conditional" && canLowerConditionalStyleProp(unresolvedProps[0].name, component);
1146
+ const unresolvedProp = onlyStaticBranchConditional ? void 0 : unresolvedProps[0];
1147
+ if (unresolvedProp?.kind === "prop") {
1148
+ return bailout(input, "local/dynamic-style-value", `Component resolver prop ${unresolvedProp.name} could not be evaluated`, unresolvedProp.span, void 0, unresolvedProp.name);
1149
+ }
1150
+ }
1151
+ const componentOnlyProp = (name) => {
1152
+ let span;
1153
+ let unknown = false;
1154
+ for (const entry of input.element.entries) {
1155
+ if (entry.kind !== "prop" || entry.name !== name) continue;
1156
+ span = entry.span;
1157
+ if (entry.value.kind !== "static") unknown = true;
1158
+ }
1159
+ return {
1160
+ unknown,
1161
+ span
1162
+ };
1163
+ };
1164
+ const disableOptimization = componentOnlyProp("disableOptimization");
1165
+ if (disableOptimization.unknown || props.disableOptimization) {
1166
+ return bailout(input, "local/unsupported-target", "disableOptimization keeps the component on the runtime path", disableOptimization.span);
1099
1167
  }
1100
1168
  if (component.domTag && props.hidden) props.display = "none";
1101
1169
  if (component.domTag && platform === "native") {
@@ -1162,7 +1230,7 @@ function createTamaguiCompilerHost(options) {
1162
1230
  const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1163
1231
  if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1164
1232
  property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1165
- } else if (entry.value.kind === "bailout" && owners.size === 1 && owners.has(name)) {
1233
+ } else if (entry.value.kind === "bailout" && owners.has(name)) {
1166
1234
  const dynamic = entry.value.dynamic;
1167
1235
  if (dynamic?.type === "number") {
1168
1236
  property = `${JSON.stringify(name)}: (${expression})`;
@@ -1200,16 +1268,19 @@ function createTamaguiCompilerHost(options) {
1200
1268
  }
1201
1269
  }
1202
1270
  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));
1203
- if ("theme" in props || "themeInverse" in props) {
1204
- const themeProp = "theme" in props ? "theme" : "themeInverse";
1271
+ const themeEntry = componentOnlyProp("theme");
1272
+ const themeInverseEntry = componentOnlyProp("themeInverse");
1273
+ const themeBoundary = themeEntry.unknown || "theme" in props;
1274
+ if (themeBoundary || themeInverseEntry.unknown || props.themeInverse) {
1275
+ const themeProp = themeBoundary ? "theme" : "themeInverse";
1205
1276
  return bailout(input, "local/unsupported-target", "Theme boundary candidates remain on the runtime path", input.element.span, {
1206
1277
  rule: 4,
1207
1278
  message: (0, import_compiler_core.zeroThemeBoundaryMessage)(input.element.component.name, themeProp)
1208
1279
  });
1209
1280
  }
1210
- const asChildEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "asChild");
1211
- if (asChildEntry || "asChild" in props) {
1212
- return bailout(input, "local/unsupported-target", "asChild renders a Slot, not a host view", asChildEntry?.span);
1281
+ const asChild = componentOnlyProp("asChild");
1282
+ if (asChild.unknown || props.asChild) {
1283
+ return bailout(input, "local/unsupported-target", "asChild renders a Slot, not a host view", asChild.span);
1213
1284
  }
1214
1285
  if (platform === "native" && ("group" in props || "container" in props || "containerName" in props || "containerType" in props)) {
1215
1286
  return bailout(input, "local/unsupported-target", "Native group and container providers remain on the runtime path");
@@ -1308,12 +1379,17 @@ function createTamaguiCompilerHost(options) {
1308
1379
  const entry = dynamicStyleEntries[0];
1309
1380
  return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
1310
1381
  }
1311
- const staticDefaultProps = component.staticConfig.defaultProps ?? {};
1382
+ const resolvedStyleStaticConfig = core.getStyleStaticConfig(component.staticConfig, core.getConfig());
1383
+ const staticDefaultProps = resolvedStyleStaticConfig.defaultProps ?? {};
1312
1384
  const defaultProps = platform === "web" && !component.staticConfig.isText && options.tamaguiConfig.settings.defaultPosition === "relative" && staticDefaultProps.position === void 0 ? core.mergeProps({ position: "relative" }, staticDefaultProps) : staticDefaultProps;
1313
1385
  let completeProps = core.mergeProps(defaultProps, props);
1314
1386
  if (platform === "native" && component.domTag && props.display === "flex") {
1315
1387
  completeProps = core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), props);
1316
1388
  }
1389
+ const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
1390
+ if (platform === "native" && !component.domTag && domStyleProgram) {
1391
+ return bailout(input, "local/unsupported-target", "Native style() pieces remain on the runtime path");
1392
+ }
1317
1393
  const propsForConditional = (target, value) => {
1318
1394
  const branchProps = {};
1319
1395
  for (const entry of input.element.entries) {
@@ -1341,6 +1417,14 @@ function createTamaguiCompilerHost(options) {
1341
1417
  }
1342
1418
  }
1343
1419
  const branchCompleteProps = platform === "native" && component.domTag && branchProps.display === "flex" ? core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), branchProps) : core.mergeProps(defaultProps, branchProps);
1420
+ if (platform === "native") {
1421
+ for (const [name, value2] of Object.entries(branchCompleteProps)) {
1422
+ const clause = isStyleProp(name, component) ? nativeClauseValue(value2) : null;
1423
+ if (clause === null || clause === "live") continue;
1424
+ if (clause.matched) branchCompleteProps[name] = clause.payload;
1425
+ else delete branchCompleteProps[name];
1426
+ }
1427
+ }
1344
1428
  return {
1345
1429
  branchProps,
1346
1430
  branchCompleteProps
@@ -1349,10 +1433,30 @@ function createTamaguiCompilerHost(options) {
1349
1433
  if (platform === "native") {
1350
1434
  const isClauseValue = (name, value) => isStyleProp(name, component) && (typeof value === "string" && flatClausePattern.test(value) || isClauseObjectValue(value));
1351
1435
  const defaultVariants = component.staticConfig.defaultVariants ?? {};
1352
- const carriesClause = Object.entries(completeProps).some(([name, value]) => isClauseValue(name, value)) || Object.entries(component.staticConfig.variants ?? {}).some(([variantName, definitions]) => (completeProps[variantName] !== void 0 || defaultVariants[variantName] !== void 0) && staticObject(definitions) && Object.values(definitions).some((definition) => staticObject(definition) && Object.entries(definition).some(([name, value]) => isClauseValue(name, value))));
1353
- if (carriesClause) {
1436
+ const definitionCarriesClause = Object.entries(resolvedStyleStaticConfig.baseStyle ?? {}).some(([name, value]) => isClauseValue(name, value)) || Object.entries(component.staticConfig.variants ?? {}).some(([variantName, definitions]) => (completeProps[variantName] !== void 0 || defaultVariants[variantName] !== void 0) && staticObject(definitions) && Object.values(definitions).some((definition) => staticObject(definition) && Object.entries(definition).some(([name, value]) => isClauseValue(name, value))));
1437
+ if (definitionCarriesClause) {
1354
1438
  return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1355
1439
  }
1440
+ const reducedProps = {};
1441
+ for (const [name, value] of Object.entries(completeProps)) {
1442
+ const clause = isStyleProp(name, component) ? nativeClauseValue(value) : null;
1443
+ if (clause === "live") {
1444
+ return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1445
+ }
1446
+ if (clause === null) {
1447
+ reducedProps[name] = value;
1448
+ continue;
1449
+ }
1450
+ if (clause.matched) reducedProps[name] = clause.payload;
1451
+ }
1452
+ completeProps = reducedProps;
1453
+ for (const entry of dynamicStyleEntries) {
1454
+ if (entry.value.kind !== "conditional") continue;
1455
+ for (const leaf of (0, import_compiler_core.collectLeaves)(entry.value.tree)) {
1456
+ if (nativeClauseValue(leaf.value) !== "live") continue;
1457
+ return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1458
+ }
1459
+ }
1356
1460
  }
1357
1461
  const split = resolveSplitStyles(completeProps, component.staticConfig, cssAnimationDriver, component.displayName);
1358
1462
  if (!split) {
@@ -1364,7 +1468,6 @@ function createTamaguiCompilerHost(options) {
1364
1468
  message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `an enter or exit style program on ${input.element.component.name}` })
1365
1469
  });
1366
1470
  }
1367
- const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
1368
1471
  const flatTag = component.domTag ?? (typeof props.render === "string" ? props.render : typeof defaultProps.render === "string" ? defaultProps.render : component.staticConfig.isText ? "span" : "div");
1369
1472
  const tagEdits = [input.element.component.span, input.element.component.closingSpan].filter((span) => !!span).map((span) => ({
1370
1473
  start: span.start,
@@ -1372,7 +1475,7 @@ function createTamaguiCompilerHost(options) {
1372
1475
  content: input.element.form === "jsx" ? flatTag : JSON.stringify(flatTag),
1373
1476
  origin: span
1374
1477
  }));
1375
- const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component);
1478
+ const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component) || componentOnlyProps.has(name);
1376
1479
  const spreadReplacement = (form, entry) => spreadNonStyleReplacement(form, entry, isPropIgnored, (name, value) => {
1377
1480
  if (platform !== "web") return [name, value];
1378
1481
  if (name === "testID") return ["data-testid", value];
@@ -1382,7 +1485,7 @@ function createTamaguiCompilerHost(options) {
1382
1485
  }
1383
1486
  return [name, value];
1384
1487
  });
1385
- let styleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && (isStyleProp(entry.name, component) || isInvalidHostStyleProp(entry.name, component)) || entry.kind === "spread" && entry.value.kind === "static" && staticObject(entry.value.value) && Object.keys(entry.value.value).some((name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component)));
1488
+ let styleEntries = input.element.entries.filter((entry) => entry.kind === "prop" && isPropIgnored(entry.name) || entry.kind === "spread" && entry.value.kind === "static" && staticObject(entry.value.value) && Object.keys(entry.value.value).some(isPropIgnored));
1386
1489
  let invalidHostStyle;
1387
1490
  for (const entry of input.element.entries) {
1388
1491
  if (entry.kind === "prop") {
@@ -2050,7 +2153,7 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2050
2153
  }
2051
2154
  };
2052
2155
  }
2053
- function bailout(input, code, message, span = input.element.span, zero) {
2156
+ function bailout(input, code, message, span = input.element.span, zero, prop) {
2054
2157
  return {
2055
2158
  ok: false,
2056
2159
  bailout: {
@@ -2059,6 +2162,7 @@ function bailout(input, code, message, span = input.element.span, zero) {
2059
2162
  message,
2060
2163
  span,
2061
2164
  component: input.element.component.name,
2165
+ ...prop && { prop },
2062
2166
  ...zero && {
2063
2167
  zeroRule: zero.rule,
2064
2168
  zeroMessage: zero.message
@@ -0,0 +1,90 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: () => from[key],
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var componentDiscovery_exports = {};
28
+ __export(componentDiscovery_exports, { ComponentDiscovery: () => ComponentDiscovery });
29
+ module.exports = __toCommonJS(componentDiscovery_exports);
30
+ var import_node_path = __toESM(require("node:path"), 1);
31
+ var import_bundleConfig = require("./extractor/bundleConfig.cjs");
32
+ var ComponentDiscovery = class {
33
+ /** null records a module that had no components or could not evaluate */
34
+ #discovered = /* @__PURE__ */ new Map();
35
+ clear() {
36
+ this.#discovered.clear();
37
+ }
38
+ /** host-resolved ids of every module discovery found components in */
39
+ ids() {
40
+ return [...this.#discovered].filter(([, loaded]) => loaded !== null).map(([id]) => id).sort();
41
+ }
42
+ /** re-register everything found so far into a freshly built registry */
43
+ seed(registry) {
44
+ for (const [id, loaded] of this.#discovered) {
45
+ if (!loaded) continue;
46
+ registry.modulesById.set(id, id);
47
+ registry.componentsByModule.set(id, loaded);
48
+ }
49
+ }
50
+ async prepare(module2, registry, evaluate) {
51
+ if (!evaluate) return;
52
+ const seen = /* @__PURE__ */ new Set();
53
+ const provenances = [...module2.elements.map((element) => element.component.provenance), ...module2.styledDefinitions.map((definition) => definition.base.provenance)];
54
+ for (const provenance of provenances) {
55
+ if (!provenance) continue;
56
+ const id = provenance.resolvedId.split(/[?#]/, 1)[0];
57
+ if (seen.has(id) || registry.modulesById.has(id) || this.#discovered.has(id)) {
58
+ continue;
59
+ }
60
+ seen.add(id);
61
+ if (!import_node_path.default.isAbsolute(id)) {
62
+ this.#discovered.set(id, null);
63
+ continue;
64
+ }
65
+ let loaded = null;
66
+ try {
67
+ const exports = await evaluate({
68
+ id,
69
+ specifier: provenance.specifier
70
+ });
71
+ if (exports) {
72
+ const nameToInfo = (0, import_bundleConfig.getComponentStaticConfigByName)(id, exports.default ?? exports);
73
+ if (Object.keys(nameToInfo).length) loaded = {
74
+ moduleName: id,
75
+ nameToInfo
76
+ };
77
+ }
78
+ } catch (error) {
79
+ if (process.env.DEBUG === "tamagui") {
80
+ console.info(`[tamagui] component discovery skipped ${id}:`, error);
81
+ }
82
+ }
83
+ this.#discovered.set(id, loaded);
84
+ if (loaded) {
85
+ registry.modulesById.set(id, id);
86
+ registry.componentsByModule.set(id, loaded);
87
+ }
88
+ }
89
+ }
90
+ };
@@ -31,6 +31,11 @@ const DOM_FRONTENDS = /* @__PURE__ */ new Set([
31
31
  "@tamagui/core/dom",
32
32
  "@tamagui/tailwind"
33
33
  ]);
34
+ const RUNTIME_STYLE_FRONTENDS = /* @__PURE__ */ new Set([
35
+ "tamagui",
36
+ "@tamagui/core",
37
+ "@tamagui/web"
38
+ ]);
34
39
  const acceptsTag = (accepted, tag) => accepted === "*" || accepted.includes(tag);
35
40
  function isDOMElement(element) {
36
41
  const provenance = element.component.provenance;
@@ -43,7 +48,7 @@ const versionHash = (0, import_node_crypto.createHash)("sha256").update(JSON.str
43
48
  TAGS: import_dom.TAGS
44
49
  })).digest("hex");
45
50
  const domStructuralPass = {
46
- versionHash: `dom-structural-v3-${versionHash}`,
51
+ versionHash: `dom-structural-v4-${versionHash}`,
47
52
  transform({ module: module2, source, target }) {
48
53
  const edits = [];
49
54
  const diagnostics = [];
@@ -92,10 +97,15 @@ const domStructuralPass = {
92
97
  diagnostics.push((0, import_compiler_core.localBailout)("local/dynamic-style-value", definition.value.span, `style() definition ${definition.name} must be statically evaluable`));
93
98
  continue;
94
99
  }
100
+ const isRuntimeStyle = RUNTIME_STYLE_FRONTENDS.has(definition.factory.specifier);
101
+ if (isRuntimeStyle && (!definition.value.value || typeof definition.value.value !== "object" || Array.isArray(definition.value.value))) {
102
+ diagnostics.push((0, import_compiler_core.localBailout)("local/dynamic-style-value", definition.value.span, `style() definition ${definition.name} must be an object literal`));
103
+ continue;
104
+ }
95
105
  edits.push({
96
106
  start: definition.span.start,
97
107
  end: definition.span.end,
98
- content: "undefined",
108
+ content: isRuntimeStyle ? `({ className: "", [Symbol.for("tamagui.stylePiece")]: { byKey: {}, styleObject: ${JSON.stringify(definition.value.value)} } })` : "undefined",
99
109
  origin: definition.span
100
110
  });
101
111
  }
@@ -23,7 +23,8 @@ var exports_exports = {};
23
23
  __export(exports_exports, {
24
24
  clearFormatCache: () => import_detectModuleFormat.clearFormatCache,
25
25
  detectModuleFormat: () => import_detectModuleFormat.detectModuleFormat,
26
- esbundleTamaguiConfig: () => import_bundle.esbundleTamaguiConfig
26
+ esbundleTamaguiConfig: () => import_bundle.esbundleTamaguiConfig,
27
+ evaluateComponentModule: () => import_bundleConfig.evaluateComponentModule
27
28
  });
28
29
  module.exports = __toCommonJS(exports_exports);
29
30
  __reExport(exports_exports, require("./checkDeps.cjs"), module.exports);
@@ -33,6 +34,8 @@ __reExport(exports_exports, require("./types.cjs"), module.exports);
33
34
  __reExport(exports_exports, require("./constants.cjs"), module.exports);
34
35
  __reExport(exports_exports, require("./extractor/concatClassName.cjs"), module.exports);
35
36
  __reExport(exports_exports, require("./extractor/loadTamagui.cjs"), module.exports);
37
+ var import_bundleConfig = require("./extractor/bundleConfig.cjs");
38
+ __reExport(exports_exports, require("./componentDiscovery.cjs"), module.exports);
36
39
  __reExport(exports_exports, require("./extractor/watchTamaguiConfig.cjs"), module.exports);
37
40
  __reExport(exports_exports, require("./registerRequire.cjs"), module.exports);
38
41
  var import_detectModuleFormat = require("./extractor/detectModuleFormat.cjs");
@@ -29,6 +29,7 @@ __export(bundleConfig_exports, {
29
29
  bundleConfig: () => bundleConfig,
30
30
  esbuildOptions: () => esbuildOptions,
31
31
  esbuildOptionsWithPlugins: () => esbuildOptionsWithPlugins,
32
+ evaluateComponentModule: () => evaluateComponentModule,
32
33
  getBundledConfig: () => getBundledConfig,
33
34
  getComponentStaticConfigByName: () => getComponentStaticConfigByName,
34
35
  getLoadedConfig: () => getLoadedConfig,
@@ -483,6 +484,28 @@ async function loadComponents(props, forceExports = false) {
483
484
  const otherComponents = await loadComponentsInner(props, forceExports);
484
485
  return [...coreComponents, ...otherComponents];
485
486
  }
487
+ async function evaluateComponentModule(props, id) {
488
+ const previousIsStatic = process.env.IS_STATIC;
489
+ const previousIsServer = process.env.TAMAGUI_IS_SERVER;
490
+ process.env.IS_STATIC = "is_static";
491
+ process.env.TAMAGUI_IS_SERVER = "true";
492
+ const { unregister } = (0, import_registerRequire.registerRequire)(props.platform || "web", { ignoredModules: props.dangerouslyIgnoreStaticEvaluationModules });
493
+ try {
494
+ try {
495
+ return nodeRequire(id);
496
+ } catch (error) {
497
+ const code = error?.code;
498
+ if (code !== "ERR_REQUIRE_ESM" && code !== "ERR_REQUIRE_ASYNC_MODULE") throw error;
499
+ }
500
+ } finally {
501
+ unregister();
502
+ if (previousIsStatic === void 0) delete process.env.IS_STATIC;
503
+ else process.env.IS_STATIC = previousIsStatic;
504
+ if (previousIsServer === void 0) delete process.env.TAMAGUI_IS_SERVER;
505
+ else process.env.TAMAGUI_IS_SERVER = previousIsServer;
506
+ }
507
+ return import(`${(0, import_node_url.pathToFileURL)(id).href}?v=${import_fs_extra.default.statSync(id).mtimeMs}`);
508
+ }
486
509
  function loadComponentsSync(props, forceExports = false) {
487
510
  const coreComponents = getCoreComponentsSync(props);
488
511
  const otherComponents = loadComponentsInnerSync(props, forceExports);