@tamagui/static 3.0.0-beta.831.1 → 3.0.0-beta.889.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 +148 -39
  3. package/dist/cjs/componentDiscovery.cjs +94 -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 +146 -40
  11. package/dist/esm/compilerHost.mjs.map +1 -1
  12. package/dist/esm/componentDiscovery.mjs +69 -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 +262 -74
  24. package/src/componentDiscovery.ts +105 -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,
@@ -851,6 +892,10 @@ function createTamaguiCompilerHost(options) {
851
892
  };
852
893
  const styledStaticConfig = (definition) => {
853
894
  if (!definition || definition.options.kind !== "static") return null;
895
+ const staticConfig = definition.staticConfig;
896
+ if (staticConfig && (staticConfig.kind !== "static" || !staticObject(staticConfig.value))) {
897
+ return null;
898
+ }
854
899
  const base = directStaticConfig({
855
900
  kind: "element",
856
901
  form: "jsx",
@@ -865,30 +910,33 @@ function createTamaguiCompilerHost(options) {
865
910
  if (!base || !staticObject(definition.options.value)) return null;
866
911
  const { variants, defaultVariants, displayName, context, contextProps, ...defaultProps } = definition.options.value;
867
912
  const baseClassName = definition.baseClassName?.kind === "static" && typeof definition.baseClassName.value === "string" ? definition.baseClassName.value : void 0;
913
+ const localStaticConfig = {
914
+ ...base.staticConfig,
915
+ ...staticConfig?.value,
916
+ variants: {
917
+ ...base.staticConfig.variants,
918
+ ...variants
919
+ },
920
+ defaultProps: {
921
+ ...base.staticConfig.defaultProps,
922
+ ...defaultProps,
923
+ ...defaultVariants
924
+ },
925
+ defaultVariants,
926
+ baseClassName: [base.staticConfig.baseClassName, baseClassName].filter(Boolean).join(" "),
927
+ context: context ?? base.staticConfig.context,
928
+ contextProps: context ? contextProps : contextProps ?? base.staticConfig.contextProps
929
+ };
930
+ localStaticConfig.variantStyleResolver = compilerVariantStyleResolver;
868
931
  return {
869
932
  key: componentKey(definition.id, definition.name),
870
933
  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
- })
934
+ staticConfig: normalizeStaticConfig(localStaticConfig)
887
935
  };
888
936
  };
889
937
  const resolve = (element, styledDefinition) => {
890
938
  const dom = domStaticConfig(element);
891
- const resolved = dom ?? styledStaticConfig(styledDefinition) ?? directStaticConfig(element);
939
+ const resolved = dom ?? directStaticConfig(element) ?? styledStaticConfig(styledDefinition);
892
940
  if (!resolved) return null;
893
941
  const defaultProps = resolved.staticConfig.defaultProps ?? {};
894
942
  return {
@@ -918,8 +966,8 @@ function createTamaguiCompilerHost(options) {
918
966
  const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && !runtimeOnlyStyleProps.has(name);
919
967
  const isInvalidHostStyleProp = (name, component) => {
920
968
  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);
969
+ const validStyles = staticConfig.validStyles || (staticConfig.isInput ? import_helpers.stylePropsInput : staticConfig.isText ? import_helpers.stylePropsText : import_helpers.validStyles);
970
+ return name in import_helpers.stylePropsAll && !(0, import_web.isValidStyleKey)(name, validStyles);
923
971
  };
924
972
  const directStyleName = (name, component) => {
925
973
  if (compilerStyleProps.has(name) || name === "style") {
@@ -941,6 +989,7 @@ function createTamaguiCompilerHost(options) {
941
989
  process.env.TAMAGUI_TARGET = platform;
942
990
  try {
943
991
  return core.getSplitStyles(props, staticConfig, theme, firstThemeName, componentState, {
992
+ isStatic: true,
944
993
  resolveValues: platform === "native" ? "except-theme" : "variable",
945
994
  noClass: platform === "native",
946
995
  isAnimated: false,
@@ -1063,6 +1112,9 @@ function createTamaguiCompilerHost(options) {
1063
1112
  if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
1064
1113
  return true;
1065
1114
  }
1115
+ if (component.staticConfig.resolvers?.length) {
1116
+ return false;
1117
+ }
1066
1118
  return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
1067
1119
  },
1068
1120
  developmentDebugInstrumentation,
@@ -1093,9 +1145,30 @@ function createTamaguiCompilerHost(options) {
1093
1145
  props[entry.name] = entry.value.value;
1094
1146
  }
1095
1147
  }
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);
1148
+ if (component.staticConfig.resolvers?.length) {
1149
+ const unresolvedProps = input.element.entries.filter((entry) => entry.kind === "prop" && entry.value.kind !== "static");
1150
+ const onlyStaticBranchConditional = unresolvedProps.length === 1 && unresolvedProps[0]?.kind === "prop" && unresolvedProps[0].value.kind === "conditional" && canLowerConditionalStyleProp(unresolvedProps[0].name, component);
1151
+ const unresolvedProp = onlyStaticBranchConditional ? void 0 : unresolvedProps[0];
1152
+ if (unresolvedProp?.kind === "prop") {
1153
+ return bailout(input, "local/dynamic-style-value", `Component resolver prop ${unresolvedProp.name} could not be evaluated`, unresolvedProp.span, void 0, unresolvedProp.name);
1154
+ }
1155
+ }
1156
+ const componentOnlyProp = (name) => {
1157
+ let span;
1158
+ let unknown = false;
1159
+ for (const entry of input.element.entries) {
1160
+ if (entry.kind !== "prop" || entry.name !== name) continue;
1161
+ span = entry.span;
1162
+ if (entry.value.kind !== "static") unknown = true;
1163
+ }
1164
+ return {
1165
+ unknown,
1166
+ span
1167
+ };
1168
+ };
1169
+ const disableOptimization = componentOnlyProp("disableOptimization");
1170
+ if (disableOptimization.unknown || props.disableOptimization) {
1171
+ return bailout(input, "local/unsupported-target", "disableOptimization keeps the component on the runtime path", disableOptimization.span);
1099
1172
  }
1100
1173
  if (component.domTag && props.hidden) props.display = "none";
1101
1174
  if (component.domTag && platform === "native") {
@@ -1162,7 +1235,7 @@ function createTamaguiCompilerHost(options) {
1162
1235
  const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1163
1236
  if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1164
1237
  property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1165
- } else if (entry.value.kind === "bailout" && owners.size === 1 && owners.has(name)) {
1238
+ } else if (entry.value.kind === "bailout" && owners.has(name)) {
1166
1239
  const dynamic = entry.value.dynamic;
1167
1240
  if (dynamic?.type === "number") {
1168
1241
  property = `${JSON.stringify(name)}: (${expression})`;
@@ -1200,16 +1273,19 @@ function createTamaguiCompilerHost(options) {
1200
1273
  }
1201
1274
  }
1202
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));
1203
- if ("theme" in props || "themeInverse" in props) {
1204
- const themeProp = "theme" in props ? "theme" : "themeInverse";
1276
+ const themeEntry = componentOnlyProp("theme");
1277
+ const themeInverseEntry = componentOnlyProp("themeInverse");
1278
+ const themeBoundary = themeEntry.unknown || "theme" in props;
1279
+ if (themeBoundary || themeInverseEntry.unknown || props.themeInverse) {
1280
+ const themeProp = themeBoundary ? "theme" : "themeInverse";
1205
1281
  return bailout(input, "local/unsupported-target", "Theme boundary candidates remain on the runtime path", input.element.span, {
1206
1282
  rule: 4,
1207
1283
  message: (0, import_compiler_core.zeroThemeBoundaryMessage)(input.element.component.name, themeProp)
1208
1284
  });
1209
1285
  }
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);
1286
+ const asChild = componentOnlyProp("asChild");
1287
+ if (asChild.unknown || props.asChild) {
1288
+ return bailout(input, "local/unsupported-target", "asChild renders a Slot, not a host view", asChild.span);
1213
1289
  }
1214
1290
  if (platform === "native" && ("group" in props || "container" in props || "containerName" in props || "containerType" in props)) {
1215
1291
  return bailout(input, "local/unsupported-target", "Native group and container providers remain on the runtime path");
@@ -1308,12 +1384,17 @@ function createTamaguiCompilerHost(options) {
1308
1384
  const entry = dynamicStyleEntries[0];
1309
1385
  return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
1310
1386
  }
1311
- const staticDefaultProps = component.staticConfig.defaultProps ?? {};
1387
+ const resolvedStyleStaticConfig = core.getStyleStaticConfig(component.staticConfig, core.getConfig());
1388
+ const staticDefaultProps = resolvedStyleStaticConfig.defaultProps ?? {};
1312
1389
  const defaultProps = platform === "web" && !component.staticConfig.isText && options.tamaguiConfig.settings.defaultPosition === "relative" && staticDefaultProps.position === void 0 ? core.mergeProps({ position: "relative" }, staticDefaultProps) : staticDefaultProps;
1313
1390
  let completeProps = core.mergeProps(defaultProps, props);
1314
1391
  if (platform === "native" && component.domTag && props.display === "flex") {
1315
1392
  completeProps = core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), props);
1316
1393
  }
1394
+ const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
1395
+ if (platform === "native" && !component.domTag && domStyleProgram) {
1396
+ return bailout(input, "local/unsupported-target", "Native style() pieces remain on the runtime path");
1397
+ }
1317
1398
  const propsForConditional = (target, value) => {
1318
1399
  const branchProps = {};
1319
1400
  for (const entry of input.element.entries) {
@@ -1341,6 +1422,14 @@ function createTamaguiCompilerHost(options) {
1341
1422
  }
1342
1423
  }
1343
1424
  const branchCompleteProps = platform === "native" && component.domTag && branchProps.display === "flex" ? core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), branchProps) : core.mergeProps(defaultProps, branchProps);
1425
+ if (platform === "native") {
1426
+ for (const [name, value2] of Object.entries(branchCompleteProps)) {
1427
+ const clause = isStyleProp(name, component) ? nativeClauseValue(value2) : null;
1428
+ if (clause === null || clause === "live") continue;
1429
+ if (clause.matched) branchCompleteProps[name] = clause.payload;
1430
+ else delete branchCompleteProps[name];
1431
+ }
1432
+ }
1344
1433
  return {
1345
1434
  branchProps,
1346
1435
  branchCompleteProps
@@ -1349,10 +1438,30 @@ function createTamaguiCompilerHost(options) {
1349
1438
  if (platform === "native") {
1350
1439
  const isClauseValue = (name, value) => isStyleProp(name, component) && (typeof value === "string" && flatClausePattern.test(value) || isClauseObjectValue(value));
1351
1440
  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) {
1441
+ 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))));
1442
+ if (definitionCarriesClause) {
1354
1443
  return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1355
1444
  }
1445
+ const reducedProps = {};
1446
+ for (const [name, value] of Object.entries(completeProps)) {
1447
+ const clause = isStyleProp(name, component) ? nativeClauseValue(value) : null;
1448
+ if (clause === "live") {
1449
+ return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1450
+ }
1451
+ if (clause === null) {
1452
+ reducedProps[name] = value;
1453
+ continue;
1454
+ }
1455
+ if (clause.matched) reducedProps[name] = clause.payload;
1456
+ }
1457
+ completeProps = reducedProps;
1458
+ for (const entry of dynamicStyleEntries) {
1459
+ if (entry.value.kind !== "conditional") continue;
1460
+ for (const leaf of (0, import_compiler_core.collectLeaves)(entry.value.tree)) {
1461
+ if (nativeClauseValue(leaf.value) !== "live") continue;
1462
+ return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1463
+ }
1464
+ }
1356
1465
  }
1357
1466
  const split = resolveSplitStyles(completeProps, component.staticConfig, cssAnimationDriver, component.displayName);
1358
1467
  if (!split) {
@@ -1364,7 +1473,6 @@ function createTamaguiCompilerHost(options) {
1364
1473
  message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `an enter or exit style program on ${input.element.component.name}` })
1365
1474
  });
1366
1475
  }
1367
- const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
1368
1476
  const flatTag = component.domTag ?? (typeof props.render === "string" ? props.render : typeof defaultProps.render === "string" ? defaultProps.render : component.staticConfig.isText ? "span" : "div");
1369
1477
  const tagEdits = [input.element.component.span, input.element.component.closingSpan].filter((span) => !!span).map((span) => ({
1370
1478
  start: span.start,
@@ -1372,7 +1480,7 @@ function createTamaguiCompilerHost(options) {
1372
1480
  content: input.element.form === "jsx" ? flatTag : JSON.stringify(flatTag),
1373
1481
  origin: span
1374
1482
  }));
1375
- const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component);
1483
+ const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component) || componentOnlyProps.has(name);
1376
1484
  const spreadReplacement = (form, entry) => spreadNonStyleReplacement(form, entry, isPropIgnored, (name, value) => {
1377
1485
  if (platform !== "web") return [name, value];
1378
1486
  if (name === "testID") return ["data-testid", value];
@@ -1382,7 +1490,7 @@ function createTamaguiCompilerHost(options) {
1382
1490
  }
1383
1491
  return [name, value];
1384
1492
  });
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)));
1493
+ 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
1494
  let invalidHostStyle;
1387
1495
  for (const entry of input.element.entries) {
1388
1496
  if (entry.kind === "prop") {
@@ -2050,7 +2158,7 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2050
2158
  }
2051
2159
  };
2052
2160
  }
2053
- function bailout(input, code, message, span = input.element.span, zero) {
2161
+ function bailout(input, code, message, span = input.element.span, zero, prop) {
2054
2162
  return {
2055
2163
  ok: false,
2056
2164
  bailout: {
@@ -2059,6 +2167,7 @@ function bailout(input, code, message, span = input.element.span, zero) {
2059
2167
  message,
2060
2168
  span,
2061
2169
  component: input.element.component.name,
2170
+ ...prop && { prop },
2062
2171
  ...zero && {
2063
2172
  zeroRule: zero.rule,
2064
2173
  zeroMessage: zero.message
@@ -0,0 +1,94 @@
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
+ const packageSpecifier = /^(?:@[^/@\s]+\/)?[^./~@\s][^/\s]*(?:\/|$)/;
33
+ function isPackageSpecifier(specifier) {
34
+ return packageSpecifier.test(specifier);
35
+ }
36
+ var ComponentDiscovery = class {
37
+ /** null records a module that had no components or could not evaluate */
38
+ #discovered = /* @__PURE__ */ new Map();
39
+ clear() {
40
+ this.#discovered.clear();
41
+ }
42
+ /** host-resolved ids of every module discovery found components in */
43
+ ids() {
44
+ return [...this.#discovered].filter(([, loaded]) => loaded !== null).map(([id]) => id).sort();
45
+ }
46
+ /** re-register everything found so far into a freshly built registry */
47
+ seed(registry) {
48
+ for (const [id, loaded] of this.#discovered) {
49
+ if (!loaded) continue;
50
+ registry.modulesById.set(id, id);
51
+ registry.componentsByModule.set(id, loaded);
52
+ }
53
+ }
54
+ async prepare(module2, registry, evaluate) {
55
+ if (!evaluate) return;
56
+ const seen = /* @__PURE__ */ new Set();
57
+ const provenances = [...module2.elements.map((element) => element.component.provenance), ...module2.styledDefinitions.map((definition) => definition.base.provenance)];
58
+ for (const provenance of provenances) {
59
+ if (!provenance || !isPackageSpecifier(provenance.specifier)) continue;
60
+ const id = provenance.resolvedId.split(/[?#]/, 1)[0];
61
+ if (seen.has(id) || registry.modulesById.has(id) || this.#discovered.has(id)) {
62
+ continue;
63
+ }
64
+ seen.add(id);
65
+ if (!import_node_path.default.isAbsolute(id)) {
66
+ this.#discovered.set(id, null);
67
+ continue;
68
+ }
69
+ let loaded = null;
70
+ try {
71
+ const exports = await evaluate({
72
+ id,
73
+ specifier: provenance.specifier
74
+ });
75
+ if (exports) {
76
+ const nameToInfo = (0, import_bundleConfig.getComponentStaticConfigByName)(id, exports.default ?? exports);
77
+ if (Object.keys(nameToInfo).length) loaded = {
78
+ moduleName: id,
79
+ nameToInfo
80
+ };
81
+ }
82
+ } catch (error) {
83
+ if (process.env.DEBUG === "tamagui") {
84
+ console.info(`[tamagui] component discovery skipped ${id}:`, error);
85
+ }
86
+ }
87
+ this.#discovered.set(id, loaded);
88
+ if (loaded) {
89
+ registry.modulesById.set(id, id);
90
+ registry.componentsByModule.set(id, loaded);
91
+ }
92
+ }
93
+ }
94
+ };
@@ -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);