@tamagui/static 3.0.0-beta.807.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 (45) hide show
  1. package/dist/cjs/compiler.cjs +17 -5
  2. package/dist/cjs/compilerHost.cjs +164 -50
  3. package/dist/cjs/componentDiscovery.cjs +90 -0
  4. package/dist/cjs/domStructuralPass.cjs +16 -6
  5. package/dist/cjs/exports.cjs +4 -1
  6. package/dist/cjs/extractor/bundleConfig.cjs +23 -0
  7. package/dist/cjs/staticEvaluationIgnoredModules.cjs +1 -1
  8. package/dist/cjs/zero/theme.cjs +5 -20
  9. package/dist/esm/compiler.mjs +18 -6
  10. package/dist/esm/compiler.mjs.map +1 -1
  11. package/dist/esm/compilerHost.mjs +162 -51
  12. package/dist/esm/compilerHost.mjs.map +1 -1
  13. package/dist/esm/componentDiscovery.mjs +65 -0
  14. package/dist/esm/componentDiscovery.mjs.map +1 -0
  15. package/dist/esm/domStructuralPass.mjs +16 -6
  16. package/dist/esm/domStructuralPass.mjs.map +1 -1
  17. package/dist/esm/exports.mjs +4 -1
  18. package/dist/esm/extractor/bundleConfig.mjs +23 -1
  19. package/dist/esm/extractor/bundleConfig.mjs.map +1 -1
  20. package/dist/esm/staticEvaluationIgnoredModules.mjs +1 -1
  21. package/dist/esm/staticEvaluationIgnoredModules.mjs.map +1 -1
  22. package/dist/esm/zero/theme.mjs +5 -20
  23. package/dist/esm/zero/theme.mjs.map +1 -1
  24. package/package.json +17 -17
  25. package/src/compiler.ts +27 -5
  26. package/src/compilerHost.ts +274 -105
  27. package/src/componentDiscovery.ts +95 -0
  28. package/src/domStructuralPass.ts +26 -6
  29. package/src/exports.ts +2 -0
  30. package/src/extractor/bundleConfig.ts +34 -0
  31. package/src/staticEvaluationIgnoredModules.ts +1 -1
  32. package/src/zero/theme.ts +12 -21
  33. package/types/compiler.d.ts +13 -0
  34. package/types/compiler.d.ts.map +1 -1
  35. package/types/compilerHost.d.ts +13 -0
  36. package/types/compilerHost.d.ts.map +1 -1
  37. package/types/componentDiscovery.d.ts +27 -0
  38. package/types/componentDiscovery.d.ts.map +1 -0
  39. package/types/domStructuralPass.d.ts.map +1 -1
  40. package/types/exports.d.ts +2 -0
  41. package/types/exports.d.ts.map +1 -1
  42. package/types/extractor/bundleConfig.d.ts +7 -0
  43. package/types/extractor/bundleConfig.d.ts.map +1 -1
  44. package/types/zero/theme.d.ts +0 -1
  45. 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",
@@ -551,8 +571,8 @@ function nativeDOMProps(input, tag) {
551
571
  const consume = (entry) => consumed.push(entry);
552
572
  for (const entry of entries) {
553
573
  const value = entrySource(input, entry);
554
- const attribute = (Object.hasOwn(import_dom.ATTRIBUTES, entry.name) ? import_dom.ATTRIBUTES[entry.name] : void 0) ?? (entry.name.startsWith("data-") ? import_dom.ATTRIBUTES["data-*"] : void 0);
555
- const event = Object.hasOwn(import_dom.EVENTS, entry.name) ? import_dom.EVENTS[entry.name] : void 0;
574
+ const attribute = (entry.name in import_dom.ATTRIBUTES ? import_dom.ATTRIBUTES[entry.name] : void 0) ?? (entry.name.startsWith("data-") ? import_dom.ATTRIBUTES["data-*"] : void 0);
575
+ const event = entry.name in import_dom.EVENTS ? import_dom.EVENTS[entry.name] : void 0;
556
576
  if (event) {
557
577
  if (event.native === "none") {
558
578
  return {
@@ -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,9 +825,21 @@ 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]));
788
- const normalizeStaticConfig = (staticConfig) => staticConfig.styleFrontend?.normalizeStaticConfig?.(staticConfig, options.tamaguiConfig) ?? staticConfig;
828
+ const { modulesById, componentsByModule } = options.registry ?? createComponentRegistry(options.components, options.componentModules);
829
+ const normalizedStyleConfigs = /* @__PURE__ */ new WeakMap();
830
+ const normalizeStaticConfig = (staticConfig) => {
831
+ if (!staticConfig.styleFrontend) return staticConfig;
832
+ const normalized = core.getStyleStaticConfig(staticConfig, options.tamaguiConfig);
833
+ const result = {
834
+ ...staticConfig,
835
+ baseStyle: normalized.baseStyle,
836
+ defaultProps: normalized.defaultProps,
837
+ variants: normalized.variants,
838
+ passthroughClassName: normalized.passthroughClassName
839
+ };
840
+ normalizedStyleConfigs.set(result, normalized);
841
+ return result;
842
+ };
789
843
  const directStaticConfig = (element) => {
790
844
  const identity = element.component.provenance;
791
845
  if (!identity) return null;
@@ -801,7 +855,7 @@ function createTamaguiCompilerHost(options) {
801
855
  const domStaticConfig = (element) => {
802
856
  const identity = element.component.provenance;
803
857
  const tag = element.component.name;
804
- if (identity?.importedName !== "html" || !DOM_FRONTENDS.has(identity.specifier) || !Object.hasOwn(import_dom.TAGS, tag)) {
858
+ if (identity?.importedName !== "html" || !DOM_FRONTENDS.has(identity.specifier) || !(tag in import_dom.TAGS)) {
805
859
  return null;
806
860
  }
807
861
  const row = import_dom.TAGS[tag];
@@ -827,7 +881,7 @@ function createTamaguiCompilerHost(options) {
827
881
  isInput: row.backing === "textinput",
828
882
  validStyles: {
829
883
  ...import_helpers.validStyles,
830
- ...import_helpers.stylePropsText
884
+ ...row.backing === "textinput" ? import_helpers.stylePropsInput : import_helpers.stylePropsText
831
885
  },
832
886
  defaultProps: {
833
887
  ...base.defaultProps,
@@ -850,42 +904,43 @@ function createTamaguiCompilerHost(options) {
850
904
  bailouts: []
851
905
  });
852
906
  if (!base || !staticObject(definition.options.value)) return null;
853
- const { variants, defaultVariants, compoundVariants, displayName, context, contextProps, ...defaultProps } = definition.options.value;
907
+ const { variants, defaultVariants, displayName, context, contextProps, ...defaultProps } = definition.options.value;
854
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;
855
926
  return {
856
927
  key: componentKey(definition.id, definition.name),
857
928
  displayName: displayName || base.displayName,
858
- staticConfig: normalizeStaticConfig({
859
- ...base.staticConfig,
860
- variants: {
861
- ...base.staticConfig.variants,
862
- ...variants
863
- },
864
- compoundVariants: [...base.staticConfig.compoundVariants ?? [], ...compoundVariants ?? []],
865
- defaultProps: {
866
- ...base.staticConfig.defaultProps,
867
- ...defaultProps,
868
- ...defaultVariants
869
- },
870
- defaultVariants,
871
- baseClassName: [base.staticConfig.baseClassName, baseClassName].filter(Boolean).join(" "),
872
- context: context ?? base.staticConfig.context,
873
- contextProps: context ? contextProps : contextProps ?? base.staticConfig.contextProps
874
- })
929
+ staticConfig: normalizeStaticConfig(localStaticConfig)
875
930
  };
876
931
  };
877
932
  const resolve = (element, styledDefinition) => {
878
933
  const dom = domStaticConfig(element);
879
934
  const resolved = dom ?? styledStaticConfig(styledDefinition) ?? directStaticConfig(element);
880
935
  if (!resolved) return null;
881
- const defaultProps = core.getDefaultProps(resolved.staticConfig) ?? {};
936
+ const defaultProps = resolved.staticConfig.defaultProps ?? {};
882
937
  return {
883
938
  key: resolved.key,
884
939
  canFlatten: resolved.staticConfig.acceptsClassName !== false && !resolved.staticConfig.neverFlatten && !resolved.staticConfig.context,
885
940
  staticConfig: resolved.staticConfig,
886
941
  displayName: resolved.displayName,
887
942
  ...dom && { domTag: dom.tag },
888
- partialRuntimeSafe: !dom && !styledDefinition && Object.keys(defaultProps).length === 0 && !resolved.staticConfig.defaultVariants && !resolved.staticConfig.baseClassName && !resolved.staticConfig.baseStyle && (resolved.staticConfig.compoundVariants?.length ?? 0) === 0
943
+ partialRuntimeSafe: !dom && !styledDefinition && Object.keys(defaultProps).length === 0 && !resolved.staticConfig.defaultVariants && !resolved.staticConfig.baseClassName && !resolved.staticConfig.baseStyle
889
944
  };
890
945
  };
891
946
  const isStyleProp = (name, component) => {
@@ -906,8 +961,8 @@ function createTamaguiCompilerHost(options) {
906
961
  const canLowerConditionalStyleProp = (name, component) => isStyleProp(name, component) && !runtimeOnlyStyleProps.has(name);
907
962
  const isInvalidHostStyleProp = (name, component) => {
908
963
  const staticConfig = component.staticConfig;
909
- const validStyles = staticConfig.validStyles || (staticConfig.isText || staticConfig.isInput ? import_helpers.stylePropsText : import_helpers.validStyles);
910
- 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);
911
966
  };
912
967
  const directStyleName = (name, component) => {
913
968
  if (compilerStyleProps.has(name) || name === "style") {
@@ -928,13 +983,13 @@ function createTamaguiCompilerHost(options) {
928
983
  }
929
984
  process.env.TAMAGUI_TARGET = platform;
930
985
  try {
931
- core.prepareStyleStaticConfig(staticConfig);
932
986
  return core.getSplitStyles(props, staticConfig, theme, firstThemeName, componentState, {
987
+ isStatic: true,
933
988
  resolveValues: platform === "native" ? "except-theme" : "variable",
934
989
  noClass: platform === "native",
935
990
  isAnimated: false,
936
991
  displayName
937
- }, void 0, void 0, void 0, void 0, void 0, void 0, animationDriver);
992
+ }, void 0, void 0, void 0, void 0, void 0, void 0, animationDriver, normalizedStyleConfigs.get(staticConfig));
938
993
  } finally {
939
994
  if (previousStatic === void 0) delete process.env.IS_STATIC;
940
995
  else process.env.IS_STATIC = previousStatic;
@@ -947,7 +1002,6 @@ function createTamaguiCompilerHost(options) {
947
1002
  baseStyle: void 0,
948
1003
  defaultProps: {},
949
1004
  defaultVariants: void 0,
950
- compoundVariants: [],
951
1005
  variants: {}
952
1006
  });
953
1007
  const styleOwners = (name, value, staticConfig) => {
@@ -1053,6 +1107,9 @@ function createTamaguiCompilerHost(options) {
1053
1107
  if (!options.disablePartialExtraction && valueKind === "conditional" && canLowerConditionalStyleProp(name, component)) {
1054
1108
  return true;
1055
1109
  }
1110
+ if (component.staticConfig.resolvers?.length) {
1111
+ return false;
1112
+ }
1056
1113
  return !options.disablePartialExtraction && (platform === "web" && !!directStyleName(name, component) || platform === "native" && directStyleName(name, component) === "opacity");
1057
1114
  },
1058
1115
  developmentDebugInstrumentation,
@@ -1083,9 +1140,30 @@ function createTamaguiCompilerHost(options) {
1083
1140
  props[entry.name] = entry.value.value;
1084
1141
  }
1085
1142
  }
1086
- const disableOptimizationEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "disableOptimization");
1087
- if (disableOptimizationEntry || Object.hasOwn(props, "disableOptimization")) {
1088
- 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);
1089
1167
  }
1090
1168
  if (component.domTag && props.hidden) props.display = "none";
1091
1169
  if (component.domTag && platform === "native") {
@@ -1108,7 +1186,7 @@ function createTamaguiCompilerHost(options) {
1108
1186
  return bailout(input, "local/unsupported-target", `${runtimeEvent} requires Tamagui runtime event mapping`);
1109
1187
  }
1110
1188
  }
1111
- const animationDefaultProps = core.getDefaultProps(component.staticConfig) ?? {};
1189
+ const animationDefaultProps = component.staticConfig.defaultProps ?? {};
1112
1190
  const animationProps = core.mergeProps(animationDefaultProps, props);
1113
1191
  const animationNames = /* @__PURE__ */ new Set([...input.element.entries.flatMap((entry) => entry.kind === "prop" && runtimeAnimationProps.has(entry.name) ? [entry.name] : []), ...Object.keys(animationProps).filter((name) => runtimeAnimationProps.has(name) && animationProps[name] !== void 0)]);
1114
1192
  const animateOnlyEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "animateOnly");
@@ -1152,7 +1230,7 @@ function createTamaguiCompilerHost(options) {
1152
1230
  const expression = input.source.slice(entry.value.span.start, entry.value.span.end);
1153
1231
  if (resolvedCssTransition !== null && (name === "opacity" || name === "scale")) {
1154
1232
  property = name === "opacity" ? `opacity: (${expression})` : `transform: "scale(" + (${expression}) + ")"`;
1155
- } else if (entry.value.kind === "bailout" && owners.size === 1 && owners.has(name)) {
1233
+ } else if (entry.value.kind === "bailout" && owners.has(name)) {
1156
1234
  const dynamic = entry.value.dynamic;
1157
1235
  if (dynamic?.type === "number") {
1158
1236
  property = `${JSON.stringify(name)}: (${expression})`;
@@ -1190,16 +1268,19 @@ function createTamaguiCompilerHost(options) {
1190
1268
  }
1191
1269
  }
1192
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));
1193
- if ("theme" in props || "themeInverse" in props) {
1194
- 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";
1195
1276
  return bailout(input, "local/unsupported-target", "Theme boundary candidates remain on the runtime path", input.element.span, {
1196
1277
  rule: 4,
1197
1278
  message: (0, import_compiler_core.zeroThemeBoundaryMessage)(input.element.component.name, themeProp)
1198
1279
  });
1199
1280
  }
1200
- const asChildEntry = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "asChild");
1201
- if (asChildEntry || Object.hasOwn(props, "asChild")) {
1202
- 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);
1203
1284
  }
1204
1285
  if (platform === "native" && ("group" in props || "container" in props || "containerName" in props || "containerType" in props)) {
1205
1286
  return bailout(input, "local/unsupported-target", "Native group and container providers remain on the runtime path");
@@ -1298,12 +1379,17 @@ function createTamaguiCompilerHost(options) {
1298
1379
  const entry = dynamicStyleEntries[0];
1299
1380
  return bailout(input, "local/dynamic-style-value", `Style prop ${entry.kind === "prop" ? entry.name : "unknown"} could not be safely extracted`, entry.span);
1300
1381
  }
1301
- const staticDefaultProps = core.getDefaultProps(component.staticConfig) ?? {};
1382
+ const resolvedStyleStaticConfig = core.getStyleStaticConfig(component.staticConfig, core.getConfig());
1383
+ const staticDefaultProps = resolvedStyleStaticConfig.defaultProps ?? {};
1302
1384
  const defaultProps = platform === "web" && !component.staticConfig.isText && options.tamaguiConfig.settings.defaultPosition === "relative" && staticDefaultProps.position === void 0 ? core.mergeProps({ position: "relative" }, staticDefaultProps) : staticDefaultProps;
1303
1385
  let completeProps = core.mergeProps(defaultProps, props);
1304
1386
  if (platform === "native" && component.domTag && props.display === "flex") {
1305
1387
  completeProps = core.mergeProps(core.mergeProps(defaultProps, import_dom.NATIVE_FLEX_DEFAULTS), props);
1306
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
+ }
1307
1393
  const propsForConditional = (target, value) => {
1308
1394
  const branchProps = {};
1309
1395
  for (const entry of input.element.entries) {
@@ -1331,6 +1417,14 @@ function createTamaguiCompilerHost(options) {
1331
1417
  }
1332
1418
  }
1333
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
+ }
1334
1428
  return {
1335
1429
  branchProps,
1336
1430
  branchCompleteProps
@@ -1339,10 +1433,30 @@ function createTamaguiCompilerHost(options) {
1339
1433
  if (platform === "native") {
1340
1434
  const isClauseValue = (name, value) => isStyleProp(name, component) && (typeof value === "string" && flatClausePattern.test(value) || isClauseObjectValue(value));
1341
1435
  const defaultVariants = component.staticConfig.defaultVariants ?? {};
1342
- 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)))) || (component.staticConfig.compoundVariants ?? []).some((compound) => staticObject(compound) && staticObject(compound.style) && Object.entries(compound.style).some(([name, value]) => isClauseValue(name, value)));
1343
- 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) {
1344
1438
  return bailout(input, "local/unsupported-target", "Native conditional value programs remain on the runtime path");
1345
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
+ }
1346
1460
  }
1347
1461
  const split = resolveSplitStyles(completeProps, component.staticConfig, cssAnimationDriver, component.displayName);
1348
1462
  if (!split) {
@@ -1354,7 +1468,6 @@ function createTamaguiCompilerHost(options) {
1354
1468
  message: (0, import_compiler_core.zeroRuleMessage)(5, { detail: `an enter or exit style program on ${input.element.component.name}` })
1355
1469
  });
1356
1470
  }
1357
- const domStyleProgram = input.element.entries.find((entry) => entry.kind === "prop" && entry.name === "style" && entry.value.kind === "dom-style");
1358
1471
  const flatTag = component.domTag ?? (typeof props.render === "string" ? props.render : typeof defaultProps.render === "string" ? defaultProps.render : component.staticConfig.isText ? "span" : "div");
1359
1472
  const tagEdits = [input.element.component.span, input.element.component.closingSpan].filter((span) => !!span).map((span) => ({
1360
1473
  start: span.start,
@@ -1362,7 +1475,7 @@ function createTamaguiCompilerHost(options) {
1362
1475
  content: input.element.form === "jsx" ? flatTag : JSON.stringify(flatTag),
1363
1476
  origin: span
1364
1477
  }));
1365
- const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component);
1478
+ const isPropIgnored = (name) => isStyleProp(name, component) || isInvalidHostStyleProp(name, component) || componentOnlyProps.has(name);
1366
1479
  const spreadReplacement = (form, entry) => spreadNonStyleReplacement(form, entry, isPropIgnored, (name, value) => {
1367
1480
  if (platform !== "web") return [name, value];
1368
1481
  if (name === "testID") return ["data-testid", value];
@@ -1372,7 +1485,7 @@ function createTamaguiCompilerHost(options) {
1372
1485
  }
1373
1486
  return [name, value];
1374
1487
  });
1375
- 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));
1376
1489
  let invalidHostStyle;
1377
1490
  for (const entry of input.element.entries) {
1378
1491
  if (entry.kind === "prop") {
@@ -2040,7 +2153,7 @@ const ${nativeLocal} = require('react-native').${nativeExport};`,
2040
2153
  }
2041
2154
  };
2042
2155
  }
2043
- function bailout(input, code, message, span = input.element.span, zero) {
2156
+ function bailout(input, code, message, span = input.element.span, zero, prop) {
2044
2157
  return {
2045
2158
  ok: false,
2046
2159
  bailout: {
@@ -2049,6 +2162,7 @@ function bailout(input, code, message, span = input.element.span, zero) {
2049
2162
  message,
2050
2163
  span,
2051
2164
  component: input.element.component.name,
2165
+ ...prop && { prop },
2052
2166
  ...zero && {
2053
2167
  zeroRule: zero.rule,
2054
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,16 +48,16 @@ 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 = [];
50
55
  const domElements = module2.elements.filter(isDOMElement);
51
- const supportedDOMElements = domElements.filter((element) => Object.hasOwn(import_dom.TAGS, element.component.name));
56
+ const supportedDOMElements = domElements.filter((element) => element.component.name in import_dom.TAGS);
52
57
  const domBySpan = new Map(supportedDOMElements.map((element) => [`${element.span.start}:${element.span.end}`, element]));
53
58
  for (const element of domElements) {
54
59
  const tagName = element.component.name;
55
- if (!Object.hasOwn(import_dom.TAGS, tagName)) {
60
+ if (!(tagName in import_dom.TAGS)) {
56
61
  diagnostics.push((0, import_compiler_core.localBailout)("local/unsupported-target", element.component.span, `html.${element.component.name} is not part of the Tamagui DOM contract`));
57
62
  continue;
58
63
  }
@@ -63,8 +68,8 @@ const domStructuralPass = {
63
68
  }
64
69
  for (const entry of element.entries) {
65
70
  if (entry.kind !== "prop") continue;
66
- const attribute = (Object.hasOwn(import_dom.ATTRIBUTES, entry.name) ? import_dom.ATTRIBUTES[entry.name] : void 0) ?? (entry.name.startsWith("data-") ? import_dom.ATTRIBUTES["data-*"] : void 0);
67
- const event = Object.hasOwn(import_dom.EVENTS, entry.name) ? import_dom.EVENTS[entry.name] : void 0;
71
+ const attribute = (entry.name in import_dom.ATTRIBUTES ? import_dom.ATTRIBUTES[entry.name] : void 0) ?? (entry.name.startsWith("data-") ? import_dom.ATTRIBUTES["data-*"] : void 0);
72
+ const event = entry.name in import_dom.EVENTS ? import_dom.EVENTS[entry.name] : void 0;
68
73
  const row = attribute ?? event;
69
74
  if (!row) continue;
70
75
  if (!acceptsTag(row.tags, tagName)) {
@@ -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
  }