@tamagui/cli 3.0.0-beta.1093.1 → 3.0.0-beta.1097.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.
package/dist/migrate.cjs CHANGED
@@ -324,9 +324,19 @@ Keep importing regular Tamagui components from \`tamagui\` or
324
324
  \`@tamagui/core\`. Do not mix utility classes and Tamagui style props on the
325
325
  same component; choose the import whose styling language that component uses.
326
326
 
327
+ ### Required API follow-ups
328
+
329
+ - Transition values: replace arrays with \`{ preset: 'quick', opacity: 'lazy' }\`, rename the transition object's \`default\` to \`preset\`, and place physics under \`spring\`. Move \`animateOnly\` into \`transition.properties\`. Read the upgrade guide's transition section before converting driver-specific options.
330
+ - Groups and containers: \`group="card"\` enables \`group-hover/card:\` and other group states. Size queries require \`container="card"\` and use \`@sm/card:\`; a group alone no longer enables container measurement.
331
+ - Control sizes: Config v6 uses \`xs | sm | md | lg | xl\` (default \`md\`). Keep numeric token keys while retaining Config v5, then map control sizes when separately adopting v6. Shape and icon geometry still uses size tokens or numbers.
332
+ - Remove top-level \`createTamagui({ defaultProps })\`. Put default styles in \`styled()\` definitions and inherited non-style defaults in \`Component.Props\`.
333
+ - Toast: replace \`useToastController().show(title, { message })\` with \`toast(title, { description: message })\`. Import \`Toast\` and \`toast\` from \`tamagui/toast\`; mount \`Toast.Root\` and \`Toast.List\` with the desired parts once in the app. The old provider/controller API is removed.
334
+ - Replace \`ThemeableStack\` and \`SizableStack\` with \`YStack\` or \`XStack\` plus explicit styles; use \`elevation\` for elevation and border width/color for borders.
335
+ - Checked/selected states: Checkbox, Switch, Tabs and ToggleGroup read \`background-press\`; customize \`activeStyle\` to override it per instance. Audit the resulting active background against the previous app and customize its theme or skin where needed.
336
+
327
337
  ### 15. Verification
328
338
 
329
- - Run \`npx tamagui check\`.
339
+ - Run \`npx tamagui check --strict\`.
330
340
  - Run typecheck and build.
331
341
  - Start the app and manually test screens using Sheet, Dialog, Popover, Select, FocusScope, icons, and ScrollView.
332
342
  - Test Adapt breakpoints where popovers/selects/dialogs become sheets.
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __export = (target, all) => {
6
8
  for (var name in all) __defProp(target, name, {
@@ -17,17 +19,74 @@ var __copyProps = (to, from, except, desc) => {
17
19
  }
18
20
  return to;
19
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));
20
26
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
27
  var setup_prompt_exports = {};
22
28
  __export(setup_prompt_exports, {
23
29
  getSetupPrompt: () => getSetupPrompt,
24
- printSetupPrompt: () => printSetupPrompt
30
+ printSetupPrompt: () => printSetupPrompt,
31
+ resolveStyleValueSyntax: () => resolveStyleValueSyntax,
32
+ setupPrompt: () => setupPrompt
25
33
  });
26
34
  module.exports = __toCommonJS(setup_prompt_exports);
27
- function printSetupPrompt() {
28
- process.stdout.write(getSetupPrompt());
35
+ var import_prompts = __toESM(require("prompts"));
36
+ async function resolveStyleValueSyntax(setting) {
37
+ if (setting === "string" || setting === "object" || setting === "both") {
38
+ return setting;
39
+ }
40
+ if (!process.stdin.isTTY) {
41
+ return "both";
42
+ }
43
+ const response = await (0, import_prompts.default)({
44
+ type: "select",
45
+ name: "syntax",
46
+ message: "Which style value syntax would you like to document?",
47
+ choices: [
48
+ {
49
+ title: "both - document both string and object syntax",
50
+ value: "both"
51
+ },
52
+ {
53
+ title: "string - e.g. bg=\"red hover:blue\"",
54
+ value: "string"
55
+ },
56
+ {
57
+ title: "object - e.g. bg={{ default: \"red\", hover: \"blue\" }}",
58
+ value: "object"
59
+ }
60
+ ],
61
+ initial: 0
62
+ });
63
+ return response.syntax || "both";
64
+ }
65
+ async function setupPrompt(options) {
66
+ const { generatePrompt } = require("./generate-prompt.cjs");
67
+ return await generatePrompt(options);
68
+ }
69
+ function printSetupPrompt(syntax) {
70
+ if (syntax) {
71
+ process.stdout.write(getSetupPrompt(syntax));
72
+ return;
73
+ }
74
+ if (!process.stdin.isTTY) {
75
+ process.stdout.write(getSetupPrompt("both"));
76
+ return;
77
+ }
78
+ resolveStyleValueSyntax().then((chosen) => {
79
+ process.stdout.write(getSetupPrompt(chosen));
80
+ });
29
81
  }
30
- function getSetupPrompt() {
82
+ function getSetupPrompt(syntax = "both") {
83
+ const styleExample = syntax === "string" ? "```tsx\n<View bg=\"background hover:background-hover\" p=\"4 sm:6\" />\n```" : syntax === "object" ? "```tsx\n<View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />\n```" : `\`\`\`tsx
84
+ // string form
85
+ <View bg="background hover:background-hover" p="4 sm:6" />
86
+
87
+ // object form
88
+ <View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />
89
+ \`\`\``;
31
90
  return `You are adding Tamagui v3 to a project that does not use it yet.
32
91
 
33
92
  Work like a careful coding agent:
@@ -68,8 +127,10 @@ import { createTamagui } from 'tamagui'
68
127
 
69
128
  export const config = createTamagui(defaultConfig)
70
129
 
130
+ type AppConfig = typeof config
131
+
71
132
  declare module 'tamagui' {
72
- interface TamaguiCustomConfig extends typeof config {}
133
+ interface TamaguiCustomConfig extends AppConfig {}
73
134
  }
74
135
  \`\`\`
75
136
 
@@ -87,7 +148,7 @@ import { config } from './tamagui.config'
87
148
  export default function App() {
88
149
  return (
89
150
  <TamaguiProvider config={config} defaultTheme="light">
90
- <View width={200} height={200} bg="background" />
151
+ <View w={200} h={200} bg="background" />
91
152
  </TamaguiProvider>
92
153
  )
93
154
  }
@@ -113,15 +174,13 @@ first.
113
174
  This is the part most likely to be written as if it were v2. In v3, token and
114
175
  theme names are bare, and conditions are flat clauses inside the value:
115
176
 
116
- \`\`\`tsx
117
- <View bg="background hover:background-hover" p="4 sm:6" />
118
- \`\`\`
177
+ ${styleExample}
119
178
 
120
179
  - No \`$\` sigils: \`bg="background"\`, not \`bg="$background"\`.
121
180
  - No condition objects: there is no \`hoverStyle={{ ... }}\` and no \`$sm={{ ... }}\`.
122
181
  - Modifiers chain left to right and read as prefixes: \`hover:sm:small\`.
123
182
  - Clauses work on variant props too, not just style props, so
124
- \`size="large sm:small"\` selects a different variant value per condition.
183
+ \`size="lg sm:sm"\` selects a different variant value per condition.
125
184
  - When two clauses both apply, the winner is decided by specificity, not by
126
185
  source order: first by platform (\`ios:\` beats \`native:\` beats unprefixed),
127
186
  then by how many conditions the clause carries, then by category
@@ -132,15 +191,15 @@ theme names are bare, and conditions are flat clauses inside the value:
132
191
  ## 7. Verify before reporting success
133
192
 
134
193
  \`\`\`bash
135
- npx tamagui check
194
+ npx tamagui check --strict
136
195
  \`\`\`
137
196
 
138
- \`tamagui check\` reports version mismatches, duplicate installs, lockfile
197
+ \`tamagui check --strict\` reports version mismatches, duplicate installs, lockfile
139
198
  problems, a missing config, and any v2 style syntax left in source. Then run the
140
199
  project's own typecheck and build, and start the app and confirm a Tamagui
141
200
  component renders with its styles applied. A passing typecheck is not sufficient:
142
- flat values are strings, so a misspelled token compiles cleanly and only shows up
143
- at runtime.
201
+ single-token values are checked when \`settings.allowedStyleValues\` is enabled,
202
+ but conditional payloads also need the strict checker.
144
203
 
145
204
  ## 8. Give the agent the project's own vocabulary
146
205
 
package/dist/upgrade.cjs CHANGED
@@ -29,8 +29,8 @@ __export(upgrade_exports, { upgrade: () => upgrade });
29
29
  module.exports = __toCommonJS(upgrade_exports);
30
30
  var import_chalk = __toESM(require("chalk"));
31
31
  var import_node_child_process = require("node:child_process");
32
+ var import_glob = require("glob");
32
33
  var import_node_fs = require("node:fs");
33
- var import_node_path = require("node:path");
34
34
  const TAMAGUI_PACKAGES_PATTERN = /^(@tamagui\/|tamagui$)/;
35
35
  const COMMIT_TYPE_ORDER = [
36
36
  "feat",
@@ -78,24 +78,18 @@ function parseVersionSpecifier(version) {
78
78
  cleanVersion: version
79
79
  };
80
80
  }
81
- function findPackageJsonFiles(root) {
82
- const files = [];
83
- const rootPkgPath = (0, import_node_path.join)(root, "package.json");
84
- if ((0, import_node_fs.existsSync)(rootPkgPath)) {
85
- files.push(rootPkgPath);
86
- }
87
- try {
88
- const result = (0, import_node_child_process.execSync)(`find "${root}" -name "package.json" -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null`, {
89
- encoding: "utf-8",
90
- maxBuffer: 10 * 1024 * 1024
91
- });
92
- const foundFiles = result.trim().split("\n").filter(Boolean);
93
- files.push(...foundFiles.filter((f) => !files.includes(f)));
94
- } catch {}
95
- return files;
96
- }
97
81
  function findTamaguiPackages(root) {
98
- const packageJsonFiles = findPackageJsonFiles(root);
82
+ const packageJsonFiles = (0, import_glob.globSync)("**/package.json", {
83
+ cwd: root,
84
+ absolute: true,
85
+ nodir: true,
86
+ ignore: [
87
+ "**/node_modules/**",
88
+ "**/.git/**",
89
+ "**/dist/**",
90
+ "**/build/**"
91
+ ]
92
+ });
99
93
  const packages = [];
100
94
  for (const filePath of packageJsonFiles) {
101
95
  try {
@@ -129,7 +123,11 @@ function findTamaguiPackages(root) {
129
123
  }
130
124
  async function getLatestVersion() {
131
125
  try {
132
- const result = (0, import_node_child_process.execSync)("npm view tamagui version", { encoding: "utf-8" });
126
+ const result = (0, import_node_child_process.execFileSync)("npm", [
127
+ "view",
128
+ "tamagui",
129
+ "version"
130
+ ], { encoding: "utf-8" });
133
131
  return result.trim();
134
132
  } catch (err) {
135
133
  throw new Error("Failed to fetch latest tamagui version from npm");
@@ -180,7 +178,7 @@ function getChangelogFromGit(fromVersion, toVersion, debug) {
180
178
  const commits = [];
181
179
  try {
182
180
  try {
183
- (0, import_node_child_process.execSync)("git fetch --tags 2>/dev/null", {
181
+ (0, import_node_child_process.execFileSync)("git", ["fetch", "--tags"], {
184
182
  encoding: "utf-8",
185
183
  stdio: "pipe"
186
184
  });
@@ -192,7 +190,13 @@ function getChangelogFromGit(fromVersion, toVersion, debug) {
192
190
  }
193
191
  let result;
194
192
  try {
195
- result = (0, import_node_child_process.execSync)(`git log ${fromTag}..${toTag} --pretty=format:"%H|%ad|%s" --date=short 2>/dev/null`, {
193
+ result = (0, import_node_child_process.execFileSync)("git", [
194
+ "log",
195
+ `${fromTag}..${toTag}`,
196
+ "--pretty=format:%H|%ad|%s",
197
+ "--date=short",
198
+ "--"
199
+ ], {
196
200
  encoding: "utf-8",
197
201
  maxBuffer: 10 * 1024 * 1024
198
202
  });
@@ -395,6 +399,10 @@ async function upgrade(options = {}) {
395
399
  console.log(import_chalk.default.gray(` Current version: ${import_chalk.default.white(fromVersion)}`));
396
400
  console.log(import_chalk.default.gray(` Target version: ${import_chalk.default.white(toVersion)}`));
397
401
  console.log("");
402
+ if (fromVersion.startsWith("2.") && toVersion.startsWith("3.")) {
403
+ console.log(import_chalk.default.yellow("Run `tamagui migrate --from v2` for the required API and configuration migration."));
404
+ console.log("");
405
+ }
398
406
  if (packages.length > 0 && !changelogOnly) {
399
407
  displayPackageSummary(packages);
400
408
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/cli",
3
- "version": "3.0.0-beta.1093.1",
3
+ "version": "3.0.0-beta.1097.1",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "tama": "dist/index.cjs",
@@ -52,12 +52,12 @@
52
52
  "test:web": "bun run test"
53
53
  },
54
54
  "dependencies": {
55
- "@tamagui/generate-themes": "3.0.0-beta.1093.1",
56
- "@tamagui/metro-plugin": "3.0.0-beta.1093.1",
57
- "@tamagui/static": "3.0.0-beta.1093.1",
58
- "@tamagui/to-tailwind": "3.0.0-beta.1093.1",
59
- "@tamagui/types": "3.0.0-beta.1093.1",
60
- "@tamagui/vite-plugin": "3.0.0-beta.1093.1",
55
+ "@tamagui/generate-themes": "3.0.0-beta.1097.1",
56
+ "@tamagui/metro-plugin": "3.0.0-beta.1097.1",
57
+ "@tamagui/static": "3.0.0-beta.1097.1",
58
+ "@tamagui/to-tailwind": "3.0.0-beta.1097.1",
59
+ "@tamagui/types": "3.0.0-beta.1097.1",
60
+ "@tamagui/vite-plugin": "3.0.0-beta.1097.1",
61
61
  "arg": "^5.0.2",
62
62
  "chalk": "^4.1.2",
63
63
  "change-case": "^4.1.2",
@@ -76,10 +76,10 @@
76
76
  "ts-morph": "^28.0.0",
77
77
  "typescript": "~6.0.3",
78
78
  "url": "^0.11.0",
79
- "@tamagui/language-service": "3.0.0-beta.1093.1"
79
+ "@tamagui/language-service": "3.0.0-beta.1097.1"
80
80
  },
81
81
  "devDependencies": {
82
- "@tamagui/build": "3.0.0-beta.1093.1",
82
+ "@tamagui/build": "3.0.0-beta.1097.1",
83
83
  "@types/chokidar": "^2.1.3",
84
84
  "@types/marked": "^5.0.0",
85
85
  "vitest": "4.1.0"
package/src/cli.ts CHANGED
@@ -15,28 +15,45 @@ const COMMAND_MAP = {
15
15
  '--verbose': Boolean,
16
16
  '--styles-only': Boolean,
17
17
  '--deps-only': Boolean,
18
+ '--strict': Boolean,
18
19
  },
19
20
  async run() {
20
21
  const { _, ...flags } = arg(this.flags)
21
22
  const options = await getOptions({
22
23
  debug: flags['--debug'] ? (flags['--verbose'] ? 'verbose' : true) : false,
24
+ loadTamaguiOptions: flags['--strict'] && !flags['--deps-only'],
23
25
  })
24
26
  if (!flags['--styles-only']) {
25
27
  const { checkDeps } = require('@tamagui/static/checkDeps')
26
28
  await checkDeps(options.paths.root)
27
29
  }
28
30
  if (flags['--deps-only']) return
31
+ if (flags['--strict']) {
32
+ if (!options.tamaguiOptions.config) {
33
+ throw new Error('Strict style checking requires a Tamagui config.')
34
+ }
35
+ const { loadTamagui } = require('@tamagui/static/loadTamagui')
36
+ process.env.TAMAGUI_KEEP_THEMES = '1'
37
+ const loaded = await loadTamagui(
38
+ { ...options.tamaguiOptions, platform: 'web' },
39
+ true
40
+ )
41
+ if (!loaded?.tamaguiConfig) {
42
+ throw new Error('Unable to load the Tamagui config for strict style checking.')
43
+ }
44
+ }
29
45
  const { checkStyleFiles, formatCheckResults, MissingConfigArtifactError } =
30
46
  require('@tamagui/language-service/check') as typeof import('@tamagui/language-service/check')
31
47
  try {
32
48
  const result = checkStyleFiles({
33
49
  root: options.paths.root,
34
50
  configPath: options.paths.conf,
51
+ strict: flags['--strict'],
35
52
  })
36
53
  console.info(formatCheckResults(result))
37
54
  if (result.diagnosticCount > 0) process.exitCode = 1
38
55
  } catch (error) {
39
- if (error instanceof MissingConfigArtifactError) {
56
+ if (error instanceof MissingConfigArtifactError && !flags['--strict']) {
40
57
  console.warn(chalk.yellow(`skipping flat value check: ${error.message}`))
41
58
  return
42
59
  }