@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/src/migrate.ts CHANGED
@@ -308,9 +308,19 @@ Keep importing regular Tamagui components from \`tamagui\` or
308
308
  \`@tamagui/core\`. Do not mix utility classes and Tamagui style props on the
309
309
  same component; choose the import whose styling language that component uses.
310
310
 
311
+ ### Required API follow-ups
312
+
313
+ - 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.
314
+ - 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.
315
+ - 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.
316
+ - Remove top-level \`createTamagui({ defaultProps })\`. Put default styles in \`styled()\` definitions and inherited non-style defaults in \`Component.Props\`.
317
+ - 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.
318
+ - Replace \`ThemeableStack\` and \`SizableStack\` with \`YStack\` or \`XStack\` plus explicit styles; use \`elevation\` for elevation and border width/color for borders.
319
+ - 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.
320
+
311
321
  ### 15. Verification
312
322
 
313
- - Run \`npx tamagui check\`.
323
+ - Run \`npx tamagui check --strict\`.
314
324
  - Run typecheck and build.
315
325
  - Start the app and manually test screens using Sheet, Dialog, Popover, Select, FocusScope, icons, and ScrollView.
316
326
  - Test Adapt breakpoints where popovers/selects/dialogs become sheets.
@@ -1,15 +1,68 @@
1
- // The agent brief for setting Tamagui up in a project that has never had it.
1
+ // the agent brief for setting tamagui up in a project that has never had it.
2
2
  // `tamagui migrate --from v2` is the sibling for projects that already run v2.
3
3
  //
4
- // Both are printed by the CLI rather than kept only in docs so that whatever
4
+ // both are printed by the cli rather than kept only in docs so that whatever
5
5
  // version a user installs describes itself, instead of an agent reading a docs
6
6
  // page written against a different release.
7
7
 
8
- export function printSetupPrompt() {
9
- process.stdout.write(getSetupPrompt())
8
+ import prompts from 'prompts'
9
+
10
+ export async function resolveStyleValueSyntax(
11
+ setting?: 'string' | 'object' | 'both'
12
+ ): Promise<'string' | 'object' | 'both'> {
13
+ if (setting === 'string' || setting === 'object' || setting === 'both') {
14
+ return setting
15
+ }
16
+ if (!process.stdin.isTTY) {
17
+ return 'both'
18
+ }
19
+ const response = await prompts({
20
+ type: 'select',
21
+ name: 'syntax',
22
+ message: 'Which style value syntax would you like to document?',
23
+ choices: [
24
+ { title: 'both - document both string and object syntax', value: 'both' },
25
+ { title: 'string - e.g. bg="red hover:blue"', value: 'string' },
26
+ { title: 'object - e.g. bg={{ default: "red", hover: "blue" }}', value: 'object' },
27
+ ],
28
+ initial: 0,
29
+ })
30
+ return response.syntax || 'both'
10
31
  }
11
32
 
12
- export function getSetupPrompt() {
33
+ export async function setupPrompt(options?: any) {
34
+ const { generatePrompt } = require('./generate-prompt')
35
+ return await generatePrompt(options)
36
+ }
37
+
38
+ export function printSetupPrompt(syntax?: 'string' | 'object' | 'both') {
39
+ if (syntax) {
40
+ process.stdout.write(getSetupPrompt(syntax))
41
+ return
42
+ }
43
+ if (!process.stdin.isTTY) {
44
+ process.stdout.write(getSetupPrompt('both'))
45
+ return
46
+ }
47
+ resolveStyleValueSyntax().then((chosen) => {
48
+ process.stdout.write(getSetupPrompt(chosen))
49
+ })
50
+ }
51
+
52
+ export function getSetupPrompt(syntax: 'string' | 'object' | 'both' = 'both') {
53
+ const styleExample =
54
+ syntax === 'string'
55
+ ? '```tsx\n<View bg="background hover:background-hover" p="4 sm:6" />\n```'
56
+ : syntax === 'object'
57
+ ? "```tsx\n<View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />\n```"
58
+ : `\`\`\`tsx
59
+ // string form
60
+ <View bg="background hover:background-hover" p="4 sm:6" />
61
+
62
+ // object form
63
+ <View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />
64
+ \`\`\``
65
+
13
66
  return `You are adding Tamagui v3 to a project that does not use it yet.
14
67
 
15
68
  Work like a careful coding agent:
@@ -50,8 +103,10 @@ import { createTamagui } from 'tamagui'
50
103
 
51
104
  export const config = createTamagui(defaultConfig)
52
105
 
106
+ type AppConfig = typeof config
107
+
53
108
  declare module 'tamagui' {
54
- interface TamaguiCustomConfig extends typeof config {}
109
+ interface TamaguiCustomConfig extends AppConfig {}
55
110
  }
56
111
  \`\`\`
57
112
 
@@ -69,7 +124,7 @@ import { config } from './tamagui.config'
69
124
  export default function App() {
70
125
  return (
71
126
  <TamaguiProvider config={config} defaultTheme="light">
72
- <View width={200} height={200} bg="background" />
127
+ <View w={200} h={200} bg="background" />
73
128
  </TamaguiProvider>
74
129
  )
75
130
  }
@@ -95,15 +150,13 @@ first.
95
150
  This is the part most likely to be written as if it were v2. In v3, token and
96
151
  theme names are bare, and conditions are flat clauses inside the value:
97
152
 
98
- \`\`\`tsx
99
- <View bg="background hover:background-hover" p="4 sm:6" />
100
- \`\`\`
153
+ ${styleExample}
101
154
 
102
155
  - No \`$\` sigils: \`bg="background"\`, not \`bg="$background"\`.
103
156
  - No condition objects: there is no \`hoverStyle={{ ... }}\` and no \`$sm={{ ... }}\`.
104
157
  - Modifiers chain left to right and read as prefixes: \`hover:sm:small\`.
105
158
  - Clauses work on variant props too, not just style props, so
106
- \`size="large sm:small"\` selects a different variant value per condition.
159
+ \`size="lg sm:sm"\` selects a different variant value per condition.
107
160
  - When two clauses both apply, the winner is decided by specificity, not by
108
161
  source order: first by platform (\`ios:\` beats \`native:\` beats unprefixed),
109
162
  then by how many conditions the clause carries, then by category
@@ -114,15 +167,15 @@ theme names are bare, and conditions are flat clauses inside the value:
114
167
  ## 7. Verify before reporting success
115
168
 
116
169
  \`\`\`bash
117
- npx tamagui check
170
+ npx tamagui check --strict
118
171
  \`\`\`
119
172
 
120
- \`tamagui check\` reports version mismatches, duplicate installs, lockfile
173
+ \`tamagui check --strict\` reports version mismatches, duplicate installs, lockfile
121
174
  problems, a missing config, and any v2 style syntax left in source. Then run the
122
175
  project's own typecheck and build, and start the app and confirm a Tamagui
123
176
  component renders with its styles applied. A passing typecheck is not sufficient:
124
- flat values are strings, so a misspelled token compiles cleanly and only shows up
125
- at runtime.
177
+ single-token values are checked when \`settings.allowedStyleValues\` is enabled,
178
+ but conditional payloads also need the strict checker.
126
179
 
127
180
  ## 8. Give the agent the project's own vocabulary
128
181
 
package/src/upgrade.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk'
2
- import { execSync } from 'node:child_process'
2
+ import { execFileSync } from 'node:child_process'
3
+ import { globSync } from 'glob'
3
4
  import { existsSync, readFileSync, writeFileSync } from 'node:fs'
4
5
  import { join } from 'node:path'
5
6
 
@@ -66,38 +67,16 @@ function parseVersionSpecifier(version: string): {
66
67
  return { specifier: '', cleanVersion: version }
67
68
  }
68
69
 
69
- /**
70
- * Find all package.json files in the workspace
71
- */
72
- function findPackageJsonFiles(root: string): string[] {
73
- const files: string[] = []
74
-
75
- // Check root package.json
76
- const rootPkgPath = join(root, 'package.json')
77
- if (existsSync(rootPkgPath)) {
78
- files.push(rootPkgPath)
79
- }
80
-
81
- // Use find command to locate all package.json files
82
- try {
83
- const result = execSync(
84
- `find "${root}" -name "package.json" -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null`,
85
- { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
86
- )
87
- const foundFiles = result.trim().split('\n').filter(Boolean)
88
- files.push(...foundFiles.filter((f) => !files.includes(f)))
89
- } catch {
90
- // Fallback: just use root
91
- }
92
-
93
- return files
94
- }
95
-
96
70
  /**
97
71
  * Find all tamagui packages in the workspace
98
72
  */
99
73
  function findTamaguiPackages(root: string): PackageInfo[] {
100
- const packageJsonFiles = findPackageJsonFiles(root)
74
+ const packageJsonFiles = globSync('**/package.json', {
75
+ cwd: root,
76
+ absolute: true,
77
+ nodir: true,
78
+ ignore: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**'],
79
+ })
101
80
  const packages: PackageInfo[] = []
102
81
 
103
82
  for (const filePath of packageJsonFiles) {
@@ -141,7 +120,9 @@ function findTamaguiPackages(root: string): PackageInfo[] {
141
120
  */
142
121
  async function getLatestVersion(): Promise<string> {
143
122
  try {
144
- const result = execSync('npm view tamagui version', { encoding: 'utf-8' })
123
+ const result = execFileSync('npm', ['view', 'tamagui', 'version'], {
124
+ encoding: 'utf-8',
125
+ })
145
126
  return result.trim()
146
127
  } catch (err) {
147
128
  throw new Error('Failed to fetch latest tamagui version from npm')
@@ -222,7 +203,7 @@ function getChangelogFromGit(
222
203
  try {
223
204
  // Try to fetch tags first
224
205
  try {
225
- execSync('git fetch --tags 2>/dev/null', { encoding: 'utf-8', stdio: 'pipe' })
206
+ execFileSync('git', ['fetch', '--tags'], { encoding: 'utf-8', stdio: 'pipe' })
226
207
  } catch {
227
208
  // Ignore fetch errors
228
209
  }
@@ -237,8 +218,15 @@ function getChangelogFromGit(
237
218
 
238
219
  let result: string
239
220
  try {
240
- result = execSync(
241
- `git log ${fromTag}..${toTag} --pretty=format:"%H|%ad|%s" --date=short 2>/dev/null`,
221
+ result = execFileSync(
222
+ 'git',
223
+ [
224
+ 'log',
225
+ `${fromTag}..${toTag}`,
226
+ '--pretty=format:%H|%ad|%s',
227
+ '--date=short',
228
+ '--',
229
+ ],
242
230
  { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
243
231
  )
244
232
  } catch {
@@ -530,6 +518,15 @@ export async function upgrade(options: UpgradeOptions = {}): Promise<void> {
530
518
  console.log(chalk.gray(` Target version: ${chalk.white(toVersion)}`))
531
519
  console.log('')
532
520
 
521
+ if (fromVersion.startsWith('2.') && toVersion.startsWith('3.')) {
522
+ console.log(
523
+ chalk.yellow(
524
+ 'Run `tamagui migrate --from v2` for the required API and configuration migration.'
525
+ )
526
+ )
527
+ console.log('')
528
+ }
529
+
533
530
  // Show package summary (unless changelog only with no packages)
534
531
  if (packages.length > 0 && !changelogOnly) {
535
532
  displayPackageSummary(packages)
@@ -1,7 +1,11 @@
1
1
  import type { CLIResolvedOptions } from '@tamagui/types';
2
- interface GeneratePromptOptions extends CLIResolvedOptions {
2
+ export interface GeneratePromptOptions extends CLIResolvedOptions {
3
3
  output?: string;
4
+ styleValueSyntax?: 'string' | 'object' | 'both';
4
5
  }
5
6
  export declare function generatePrompt(options: GeneratePromptOptions): Promise<void>;
6
- export {};
7
+ export interface GenerateMarkdownOptions {
8
+ styleValueSyntax?: 'string' | 'object' | 'both';
9
+ }
10
+ export declare function generateMarkdown(config: any, options?: GenerateMarkdownOptions): string;
7
11
  //# sourceMappingURL=generate-prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-prompt.d.ts","sourceRoot":"","sources":["../src/generate-prompt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,UAAU,qBAAsB,SAAQ,kBAAkB;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,iBA8BlE"}
1
+ {"version":3,"file":"generate-prompt.d.ts","sourceRoot":"","sources":["../src/generate-prompt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;CAChD;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,iBAoClE;AAED,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;CAChD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAmjBvF"}
@@ -1,3 +1,5 @@
1
- export declare function printSetupPrompt(): void;
2
- export declare function getSetupPrompt(): string;
1
+ export declare function resolveStyleValueSyntax(setting?: 'string' | 'object' | 'both'): Promise<'string' | 'object' | 'both'>;
2
+ export declare function setupPrompt(options?: any): Promise<any>;
3
+ export declare function printSetupPrompt(syntax?: 'string' | 'object' | 'both'): void;
4
+ export declare function getSetupPrompt(syntax?: 'string' | 'object' | 'both'): string;
3
5
  //# sourceMappingURL=setup-prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup-prompt.d.ts","sourceRoot":"","sources":["../src/setup-prompt.ts"],"names":[],"mappings":"AAOA,wBAAgB,gBAAgB,SAE/B;AAED,wBAAgB,cAAc,WA+H7B"}
1
+ {"version":3,"file":"setup-prompt.d.ts","sourceRoot":"","sources":["../src/setup-prompt.ts"],"names":[],"mappings":"AASA,wBAAsB,uBAAuB,CAC3C,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GACrC,OAAO,CAAC,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,CAmBvC;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,gBAG9C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,QAYrE;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,QAAQ,GAAG,QAAQ,GAAG,MAAe,UA4I3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAaA,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAidD;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoHzE"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAcA,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAocD;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6HzE"}