@caddis/cli 0.0.0 → 0.1.0

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 (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -1
  3. package/bundles/antigravity-plugin/agents/code-reviewer.md +47 -0
  4. package/bundles/antigravity-plugin/agents/preflight.md +53 -0
  5. package/bundles/antigravity-plugin/guard_agy.py +338 -0
  6. package/bundles/antigravity-plugin/hooks.json +36 -0
  7. package/bundles/antigravity-plugin/mcp_config.json +8 -0
  8. package/bundles/antigravity-plugin/mcp_ping_server.py +55 -0
  9. package/bundles/antigravity-plugin/plugin.json +5 -0
  10. package/bundles/antigravity-plugin/session_end_agy.py +57 -0
  11. package/bundles/antigravity-plugin/skills/_registry.md +115 -0
  12. package/bundles/antigravity-plugin/skills/add-rules/SKILL.md +45 -0
  13. package/bundles/antigravity-plugin/skills/api-design/SKILL.md +249 -0
  14. package/bundles/antigravity-plugin/skills/backend-development/SKILL.md +305 -0
  15. package/bundles/antigravity-plugin/skills/best-practices/SKILL.md +500 -0
  16. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +263 -0
  17. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +326 -0
  18. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +245 -0
  19. package/bundles/antigravity-plugin/skills/best-practices/references/anti-patterns.md +571 -0
  20. package/bundles/antigravity-plugin/skills/best-practices/references/before-after-examples.md +1114 -0
  21. package/bundles/antigravity-plugin/skills/best-practices/references/best-practices-guide.md +513 -0
  22. package/bundles/antigravity-plugin/skills/best-practices/references/common-workflows.md +692 -0
  23. package/bundles/antigravity-plugin/skills/best-practices/references/prompt-patterns.md +547 -0
  24. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +57 -0
  25. package/bundles/antigravity-plugin/skills/ci-cd-pipeline/SKILL.md +315 -0
  26. package/bundles/antigravity-plugin/skills/code-documentation/SKILL.md +271 -0
  27. package/bundles/antigravity-plugin/skills/code-review/SKILL.md +122 -0
  28. package/bundles/antigravity-plugin/skills/codebase-audit/SKILL.md +204 -0
  29. package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +157 -0
  30. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +40 -0
  31. package/bundles/antigravity-plugin/skills/css-architecture/SKILL.md +305 -0
  32. package/bundles/antigravity-plugin/skills/css-architecture/references/RESPONSIVE-DESIGN.md +604 -0
  33. package/bundles/antigravity-plugin/skills/database-design/SKILL.md +177 -0
  34. package/bundles/antigravity-plugin/skills/db-diagram/SKILL.md +148 -0
  35. package/bundles/antigravity-plugin/skills/db-diagram/scripts/sql_to_graph.py +1212 -0
  36. package/bundles/antigravity-plugin/skills/digress/SKILL.md +61 -0
  37. package/bundles/antigravity-plugin/skills/draw-io/SKILL.md +162 -0
  38. package/bundles/antigravity-plugin/skills/draw-io/references/aws-icons.md +677 -0
  39. package/bundles/antigravity-plugin/skills/draw-io/references/layout-guidelines.md +142 -0
  40. package/bundles/antigravity-plugin/skills/draw-io/references/troubleshooting.md +118 -0
  41. package/bundles/antigravity-plugin/skills/draw-io/references/workflows.md +103 -0
  42. package/bundles/antigravity-plugin/skills/draw-io/scripts/convert-drawio-to-png.sh +25 -0
  43. package/bundles/antigravity-plugin/skills/draw-io/scripts/find_aws_icon.py +79 -0
  44. package/bundles/antigravity-plugin/skills/error-handling/SKILL.md +260 -0
  45. package/bundles/antigravity-plugin/skills/excalidraw-db/SKILL.md +38 -0
  46. package/bundles/antigravity-plugin/skills/fastapi-dev/SKILL.md +300 -0
  47. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +198 -0
  48. package/bundles/antigravity-plugin/skills/frontend-design/SKILL.md +193 -0
  49. package/bundles/antigravity-plugin/skills/frontend-design/references/my-tech-stack.md +127 -0
  50. package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +195 -0
  51. package/bundles/antigravity-plugin/skills/git-commit/SKILL.md +285 -0
  52. package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +577 -0
  53. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +100 -0
  54. package/bundles/antigravity-plugin/skills/implement/SKILL.md +114 -0
  55. package/bundles/antigravity-plugin/skills/javascript-typescript/SKILL.md +142 -0
  56. package/bundles/antigravity-plugin/skills/kb/SKILL.md +60 -0
  57. package/bundles/antigravity-plugin/skills/mermaid-db/SKILL.md +33 -0
  58. package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +236 -0
  59. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/ENHANCEMENTS.md +264 -0
  60. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/MERMAID-SUMMARY.md +137 -0
  61. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/advanced-features.md +556 -0
  62. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/architecture-diagrams.md +192 -0
  63. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/c4-diagrams.md +410 -0
  64. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/class-diagrams.md +361 -0
  65. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/erd-diagrams.md +510 -0
  66. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/flowcharts.md +450 -0
  67. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/sequence-diagrams.md +394 -0
  68. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/troubleshooting.md +335 -0
  69. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/workflows.md +418 -0
  70. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +68 -0
  71. package/bundles/antigravity-plugin/skills/mockup/SKILL.md +242 -0
  72. package/bundles/antigravity-plugin/skills/particle-art/SKILL.md +243 -0
  73. package/bundles/antigravity-plugin/skills/particle-art/references/canvas-utils.ts +171 -0
  74. package/bundles/antigravity-plugin/skills/particle-art/references/dot-field.template.tsx +203 -0
  75. package/bundles/antigravity-plugin/skills/particle-art/references/flow-field.template.tsx +263 -0
  76. package/bundles/antigravity-plugin/skills/particle-art/references/node-shape.template.tsx +261 -0
  77. package/bundles/antigravity-plugin/skills/particle-art/references/shape-sampler.ts +281 -0
  78. package/bundles/antigravity-plugin/skills/particle-art/references/stipple-morph.template.tsx +167 -0
  79. package/bundles/antigravity-plugin/skills/particle-art/references/stipple.template.tsx +175 -0
  80. package/bundles/antigravity-plugin/skills/particle-art/references/trail-ghost.template.tsx +266 -0
  81. package/bundles/antigravity-plugin/skills/particle-art/references/usage-examples.md +320 -0
  82. package/bundles/antigravity-plugin/skills/playwright/API_REFERENCE.md +653 -0
  83. package/bundles/antigravity-plugin/skills/playwright/SKILL.md +454 -0
  84. package/bundles/antigravity-plugin/skills/playwright/lib/helpers.js +441 -0
  85. package/bundles/antigravity-plugin/skills/playwright/package.json +26 -0
  86. package/bundles/antigravity-plugin/skills/playwright/run.js +228 -0
  87. package/bundles/antigravity-plugin/skills/prd/SKILL.md +107 -0
  88. package/bundles/antigravity-plugin/skills/preflight/SKILL.md +435 -0
  89. package/bundles/antigravity-plugin/skills/python/SKILL.md +388 -0
  90. package/bundles/antigravity-plugin/skills/react-best-practices/SKILL.md +269 -0
  91. package/bundles/antigravity-plugin/skills/react-dev/README.md +404 -0
  92. package/bundles/antigravity-plugin/skills/react-dev/SKILL.md +459 -0
  93. package/bundles/antigravity-plugin/skills/react-dev/examples/generic-components.md +579 -0
  94. package/bundles/antigravity-plugin/skills/react-dev/examples/server-components.md +579 -0
  95. package/bundles/antigravity-plugin/skills/react-dev/references/event-handlers.md +574 -0
  96. package/bundles/antigravity-plugin/skills/react-dev/references/hooks.md +456 -0
  97. package/bundles/antigravity-plugin/skills/react-dev/references/react-19-patterns.md +638 -0
  98. package/bundles/antigravity-plugin/skills/react-dev/references/react-router.md +1002 -0
  99. package/bundles/antigravity-plugin/skills/react-dev/references/tanstack-router.md +587 -0
  100. package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +486 -0
  101. package/bundles/antigravity-plugin/skills/resume/SKILL.md +36 -0
  102. package/bundles/antigravity-plugin/skills/security-review/SKILL.md +196 -0
  103. package/bundles/antigravity-plugin/skills/setup-project-ai/SKILL.md +61 -0
  104. package/bundles/antigravity-plugin/skills/ship/SKILL.md +107 -0
  105. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +103 -0
  106. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +102 -0
  107. package/bundles/antigravity-plugin/skills/skill-creator/LICENSE.txt +202 -0
  108. package/bundles/antigravity-plugin/skills/skill-creator/SKILL.md +491 -0
  109. package/bundles/antigravity-plugin/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/bundles/antigravity-plugin/skills/skill-creator/agents/comparator.md +202 -0
  111. package/bundles/antigravity-plugin/skills/skill-creator/agents/grader.md +223 -0
  112. package/bundles/antigravity-plugin/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/bundles/antigravity-plugin/skills/skill-creator/references/schemas.md +430 -0
  116. package/bundles/antigravity-plugin/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/bundles/antigravity-plugin/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/bundles/antigravity-plugin/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/bundles/antigravity-plugin/skills/skill-creator/scripts/improve_description.py +247 -0
  120. package/bundles/antigravity-plugin/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/bundles/antigravity-plugin/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_loop.py +328 -0
  124. package/bundles/antigravity-plugin/skills/skill-creator/scripts/utils.py +47 -0
  125. package/bundles/antigravity-plugin/skills/sql/SKILL.md +321 -0
  126. package/bundles/antigravity-plugin/skills/tdd/SKILL.md +37 -0
  127. package/bundles/antigravity-plugin/skills/tdd-workflow/SKILL.md +188 -0
  128. package/bundles/antigravity-plugin/skills/technical-writing/SKILL.md +286 -0
  129. package/bundles/antigravity-plugin/skills/test-strategy/SKILL.md +155 -0
  130. package/bundles/antigravity-plugin/skills/ui-brief/SKILL.md +84 -0
  131. package/bundles/antigravity-plugin/skills/ui-review/SKILL.md +176 -0
  132. package/bundles/antigravity-plugin/skills/ui-review/references/framework-fixes.md +471 -0
  133. package/bundles/antigravity-plugin/skills/ui-review/references/visual-checklist.md +236 -0
  134. package/bundles/antigravity-plugin/skills/usage-review/SKILL.md +77 -0
  135. package/bundles/antigravity-plugin/skills/use-model/SKILL.md +64 -0
  136. package/bundles/antigravity-plugin/skills/using-git-worktrees/SKILL.md +217 -0
  137. package/bundles/antigravity-plugin/skills/version/SKILL.md +18 -0
  138. package/bundles/antigravity-plugin/skills/warm-editorial-ui/DESIGN_TOKENS.md +487 -0
  139. package/bundles/antigravity-plugin/skills/warm-editorial-ui/IMPLEMENTATION_GUIDE.md +177 -0
  140. package/bundles/antigravity-plugin/skills/warm-editorial-ui/SKILL.md +732 -0
  141. package/bundles/antigravity-plugin/skills/webapp-testing/LICENSE.txt +202 -0
  142. package/bundles/antigravity-plugin/skills/webapp-testing/SKILL.md +97 -0
  143. package/bundles/antigravity-plugin/skills/webapp-testing/examples/console_logging.py +35 -0
  144. package/bundles/antigravity-plugin/skills/webapp-testing/examples/element_discovery.py +40 -0
  145. package/bundles/antigravity-plugin/skills/webapp-testing/examples/static_html_automation.py +33 -0
  146. package/bundles/antigravity-plugin/skills/webapp-testing/scripts/with_server.py +106 -0
  147. package/bundles/antigravity-plugin/skills/windows-deployment/SKILL.md +880 -0
  148. package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +384 -0
  149. package/bundles/antigravity-plugin/statusline-command-agy.sh +91 -0
  150. package/bundles/antigravity-plugin/warm_start_agy.py +149 -0
  151. package/bundles/manifest.json +6 -0
  152. package/dist/cli.js +5363 -0
  153. package/package.json +61 -4
@@ -0,0 +1,638 @@
1
+ # React 19 TypeScript Patterns
2
+
3
+ React 19 introduces breaking changes and new APIs requiring updated TypeScript patterns.
4
+
5
+ ## ref as Prop (No More forwardRef)
6
+
7
+ React 19 allows ref as regular prop — forwardRef deprecated but still works.
8
+
9
+ ```typescript
10
+ // ✅ React 19 - ref as prop
11
+ type InputProps = {
12
+ ref?: React.Ref<HTMLInputElement>;
13
+ label: string;
14
+ } & React.ComponentPropsWithoutRef<'input'>;
15
+
16
+ export function Input({ ref, label, ...props }: InputProps) {
17
+ return (
18
+ <div>
19
+ <label>{label}</label>
20
+ <input ref={ref} {...props} />
21
+ </div>
22
+ );
23
+ }
24
+
25
+ // Usage
26
+ function Form() {
27
+ const inputRef = useRef<HTMLInputElement>(null);
28
+
29
+ return (
30
+ <form>
31
+ <Input ref={inputRef} label="Name" />
32
+ <button onClick={() => inputRef.current?.focus()}>Focus</button>
33
+ </form>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ```typescript
39
+ // ❌ Old pattern (still works, but unnecessary)
40
+ import { forwardRef } from 'react';
41
+
42
+ type InputProps = {
43
+ label: string;
44
+ } & React.ComponentPropsWithoutRef<'input'>;
45
+
46
+ export const Input = forwardRef<HTMLInputElement, InputProps>(
47
+ ({ label, ...props }, ref) => {
48
+ return (
49
+ <div>
50
+ <label>{label}</label>
51
+ <input ref={ref} {...props} />
52
+ </div>
53
+ );
54
+ }
55
+ );
56
+
57
+ Input.displayName = 'Input';
58
+ ```
59
+
60
+ ### Generic Components with ref
61
+
62
+ ```typescript
63
+ type SelectProps<T> = {
64
+ ref?: React.Ref<HTMLSelectElement>;
65
+ options: T[];
66
+ value: T;
67
+ onChange: (value: T) => void;
68
+ getLabel: (option: T) => string;
69
+ };
70
+
71
+ export function Select<T>({ ref, options, value, onChange, getLabel }: SelectProps<T>) {
72
+ return (
73
+ <select
74
+ ref={ref}
75
+ value={getLabel(value)}
76
+ onChange={(e) => {
77
+ const selected = options.find((opt) => getLabel(opt) === e.target.value);
78
+ if (selected) onChange(selected);
79
+ }}
80
+ >
81
+ {options.map((opt) => (
82
+ <option key={getLabel(opt)} value={getLabel(opt)}>
83
+ {getLabel(opt)}
84
+ </option>
85
+ ))}
86
+ </select>
87
+ );
88
+ }
89
+ ```
90
+
91
+ ### Combining ref with Other Props
92
+
93
+ ```typescript
94
+ type ButtonProps = {
95
+ ref?: React.Ref<HTMLButtonElement>;
96
+ variant?: 'primary' | 'secondary';
97
+ size?: 'sm' | 'md' | 'lg';
98
+ } & React.ComponentPropsWithoutRef<'button'>;
99
+
100
+ export function Button({
101
+ ref,
102
+ variant = 'primary',
103
+ size = 'md',
104
+ className,
105
+ children,
106
+ ...props
107
+ }: ButtonProps) {
108
+ return (
109
+ <button
110
+ ref={ref}
111
+ className={`btn btn-${variant} btn-${size} ${className || ''}`}
112
+ {...props}
113
+ >
114
+ {children}
115
+ </button>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ## useActionState - Form State Management
121
+
122
+ Replaces useFormState — manages form submission state with Server Actions.
123
+
124
+ ```typescript
125
+ 'use client';
126
+
127
+ import { useActionState } from 'react';
128
+
129
+ type FormState = {
130
+ success?: boolean;
131
+ errors?: Record<string, string[]>;
132
+ message?: string;
133
+ };
134
+
135
+ type FormData = {
136
+ email: string;
137
+ password: string;
138
+ };
139
+
140
+ // Server Action
141
+ async function login(
142
+ prevState: FormState,
143
+ formData: FormData
144
+ ): Promise<FormState> {
145
+ 'use server';
146
+
147
+ const email = formData.get('email');
148
+ const password = formData.get('password');
149
+
150
+ if (!email || typeof email !== 'string') {
151
+ return {
152
+ success: false,
153
+ errors: { email: ['Email is required'] },
154
+ };
155
+ }
156
+
157
+ if (!password || typeof password !== 'string') {
158
+ return {
159
+ success: false,
160
+ errors: { password: ['Password is required'] },
161
+ };
162
+ }
163
+
164
+ try {
165
+ await signIn(email, password);
166
+ return { success: true, message: 'Logged in successfully' };
167
+ } catch (error) {
168
+ return {
169
+ success: false,
170
+ message: 'Invalid credentials',
171
+ };
172
+ }
173
+ }
174
+
175
+ // Client Component
176
+ export function LoginForm() {
177
+ const [state, formAction, isPending] = useActionState<FormState, FormData>(
178
+ login,
179
+ {} // Initial state
180
+ );
181
+
182
+ return (
183
+ <form action={formAction}>
184
+ <div>
185
+ <label htmlFor="email">Email</label>
186
+ <input
187
+ id="email"
188
+ name="email"
189
+ type="email"
190
+ required
191
+ aria-invalid={!!state.errors?.email}
192
+ />
193
+ {state.errors?.email?.map((error) => (
194
+ <p key={error} className="error">{error}</p>
195
+ ))}
196
+ </div>
197
+
198
+ <div>
199
+ <label htmlFor="password">Password</label>
200
+ <input
201
+ id="password"
202
+ name="password"
203
+ type="password"
204
+ required
205
+ aria-invalid={!!state.errors?.password}
206
+ />
207
+ {state.errors?.password?.map((error) => (
208
+ <p key={error} className="error">{error}</p>
209
+ ))}
210
+ </div>
211
+
212
+ {state.message && (
213
+ <div className={state.success ? 'success' : 'error'}>
214
+ {state.message}
215
+ </div>
216
+ )}
217
+
218
+ <button type="submit" disabled={isPending}>
219
+ {isPending ? 'Logging in...' : 'Log In'}
220
+ </button>
221
+ </form>
222
+ );
223
+ }
224
+ ```
225
+
226
+ ### useActionState with Optimistic Updates
227
+
228
+ ```typescript
229
+ 'use client';
230
+
231
+ import { useActionState, useOptimistic } from 'react';
232
+
233
+ type Todo = { id: string; title: string; completed: boolean };
234
+
235
+ async function toggleTodo(
236
+ prevState: { todos: Todo[] },
237
+ formData: FormData
238
+ ): Promise<{ todos: Todo[] }> {
239
+ 'use server';
240
+
241
+ const todoId = formData.get('todoId') as string;
242
+ await db.todo.update({
243
+ where: { id: todoId },
244
+ data: { completed: { toggle: true } },
245
+ });
246
+
247
+ const todos = await db.todo.findMany();
248
+ return { todos };
249
+ }
250
+
251
+ export function TodoList({ initialTodos }: { initialTodos: Todo[] }) {
252
+ const [state, formAction] = useActionState(
253
+ toggleTodo,
254
+ { todos: initialTodos }
255
+ );
256
+
257
+ const [optimisticTodos, setOptimisticTodos] = useOptimistic(
258
+ state.todos,
259
+ (currentTodos, todoId: string) =>
260
+ currentTodos.map((todo) =>
261
+ todo.id === todoId ? { ...todo, completed: !todo.completed } : todo
262
+ )
263
+ );
264
+
265
+ return (
266
+ <ul>
267
+ {optimisticTodos.map((todo) => (
268
+ <li key={todo.id}>
269
+ <form
270
+ action={(formData) => {
271
+ setOptimisticTodos(todo.id);
272
+ formAction(formData);
273
+ }}
274
+ >
275
+ <input type="hidden" name="todoId" value={todo.id} />
276
+ <button type="submit">
277
+ {todo.completed ? '✓' : '○'} {todo.title}
278
+ </button>
279
+ </form>
280
+ </li>
281
+ ))}
282
+ </ul>
283
+ );
284
+ }
285
+ ```
286
+
287
+ ## use() Hook - Unwrapping Resources
288
+
289
+ use() unwraps promises and context — enables new patterns for data fetching.
290
+
291
+ ### use() with Promises
292
+
293
+ ```typescript
294
+ // Server Component
295
+ async function UserPage({ params }: { params: { id: string } }) {
296
+ // Pass promise without awaiting
297
+ const userPromise = fetchUser(params.id);
298
+
299
+ return (
300
+ <Suspense fallback={<UserSkeleton />}>
301
+ <UserProfile userPromise={userPromise} />
302
+ </Suspense>
303
+ );
304
+ }
305
+
306
+ // Client Component
307
+ 'use client';
308
+
309
+ import { use } from 'react';
310
+
311
+ type UserProfileProps = {
312
+ userPromise: Promise<User>;
313
+ };
314
+
315
+ export function UserProfile({ userPromise }: UserProfileProps) {
316
+ // Suspends until resolved
317
+ const user = use(userPromise);
318
+
319
+ return (
320
+ <div>
321
+ <h1>{user.name}</h1>
322
+ <p>{user.email}</p>
323
+ </div>
324
+ );
325
+ }
326
+ ```
327
+
328
+ ### Conditional use()
329
+
330
+ use() can be called conditionally — unlike hooks.
331
+
332
+ ```typescript
333
+ 'use client';
334
+
335
+ import { use } from 'react';
336
+
337
+ type Props = {
338
+ userPromise?: Promise<User>;
339
+ userId?: string;
340
+ };
341
+
342
+ export function UserDisplay({ userPromise, userId }: Props) {
343
+ let user: User | undefined;
344
+
345
+ if (userPromise) {
346
+ user = use(userPromise); // Conditional use() - allowed!
347
+ } else if (userId) {
348
+ // Fetch inline
349
+ user = use(fetchUser(userId));
350
+ }
351
+
352
+ if (!user) return <div>No user data</div>;
353
+
354
+ return <div>{user.name}</div>;
355
+ }
356
+ ```
357
+
358
+ ### use() in Loops
359
+
360
+ ```typescript
361
+ 'use client';
362
+
363
+ import { use } from 'react';
364
+
365
+ type Props = {
366
+ userPromises: Promise<User>[];
367
+ };
368
+
369
+ export function UserList({ userPromises }: Props) {
370
+ return (
371
+ <ul>
372
+ {userPromises.map((promise, index) => {
373
+ const user = use(promise); // use() in loop - allowed!
374
+ return <li key={user.id}>{user.name}</li>;
375
+ })}
376
+ </ul>
377
+ );
378
+ }
379
+ ```
380
+
381
+ ### use() with Context
382
+
383
+ Alternative to useContext — can be called conditionally.
384
+
385
+ ```typescript
386
+ import { createContext, use } from 'react';
387
+
388
+ type Theme = 'light' | 'dark';
389
+ const ThemeContext = createContext<Theme>('light');
390
+
391
+ export function ThemedComponent({ override }: { override?: Theme }) {
392
+ let theme: Theme;
393
+
394
+ if (override) {
395
+ theme = override;
396
+ } else {
397
+ theme = use(ThemeContext); // Conditional context access
398
+ }
399
+
400
+ return <div className={theme}>Content</div>;
401
+ }
402
+ ```
403
+
404
+ ## useOptimistic - Optimistic UI Updates
405
+
406
+ Show immediate UI feedback before server confirms.
407
+
408
+ ```typescript
409
+ 'use client';
410
+
411
+ import { useOptimistic } from 'react';
412
+
413
+ type Message = { id: string; text: string; sending?: boolean };
414
+
415
+ export function MessageThread({ messages }: { messages: Message[] }) {
416
+ const [optimisticMessages, addOptimisticMessage] = useOptimistic(
417
+ messages,
418
+ (state, newMessage: Message) => [...state, newMessage]
419
+ );
420
+
421
+ async function sendMessage(formData: FormData) {
422
+ const text = formData.get('message') as string;
423
+
424
+ // Add optimistic message immediately
425
+ addOptimisticMessage({ id: 'temp', text, sending: true });
426
+
427
+ // Send to server
428
+ await fetch('/api/messages', {
429
+ method: 'POST',
430
+ body: JSON.stringify({ text }),
431
+ });
432
+ }
433
+
434
+ return (
435
+ <div>
436
+ <ul>
437
+ {optimisticMessages.map((msg) => (
438
+ <li key={msg.id} className={msg.sending ? 'opacity-50' : ''}>
439
+ {msg.text}
440
+ </li>
441
+ ))}
442
+ </ul>
443
+
444
+ <form action={sendMessage}>
445
+ <input name="message" required />
446
+ <button type="submit">Send</button>
447
+ </form>
448
+ </div>
449
+ );
450
+ }
451
+ ```
452
+
453
+ ### useOptimistic with State Updates
454
+
455
+ ```typescript
456
+ 'use client';
457
+
458
+ import { useOptimistic, useState, useTransition } from 'react';
459
+
460
+ type Item = { id: string; name: string; quantity: number };
461
+
462
+ export function ShoppingCart({ items: initialItems }: { items: Item[] }) {
463
+ const [items, setItems] = useState(initialItems);
464
+ const [isPending, startTransition] = useTransition();
465
+
466
+ const [optimisticItems, updateOptimistic] = useOptimistic(
467
+ items,
468
+ (state, { id, quantity }: { id: string; quantity: number }) =>
469
+ state.map((item) =>
470
+ item.id === id ? { ...item, quantity } : item
471
+ )
472
+ );
473
+
474
+ async function updateQuantity(id: string, quantity: number) {
475
+ // Optimistic update
476
+ updateOptimistic({ id, quantity });
477
+
478
+ // Server update
479
+ startTransition(async () => {
480
+ const updated = await fetch(`/api/cart/${id}`, {
481
+ method: 'PATCH',
482
+ body: JSON.stringify({ quantity }),
483
+ }).then((r) => r.json());
484
+
485
+ setItems(updated);
486
+ });
487
+ }
488
+
489
+ return (
490
+ <ul>
491
+ {optimisticItems.map((item) => (
492
+ <li key={item.id}>
493
+ {item.name}
494
+ <button onClick={() => updateQuantity(item.id, item.quantity - 1)}>
495
+ -
496
+ </button>
497
+ <span>{item.quantity}</span>
498
+ <button onClick={() => updateQuantity(item.id, item.quantity + 1)}>
499
+ +
500
+ </button>
501
+ </li>
502
+ ))}
503
+ </ul>
504
+ );
505
+ }
506
+ ```
507
+
508
+ ## useTransition - Non-Blocking Updates
509
+
510
+ Mark state updates as non-urgent — UI stays responsive.
511
+
512
+ ```typescript
513
+ 'use client';
514
+
515
+ import { useTransition, useState } from 'react';
516
+
517
+ export function SearchResults() {
518
+ const [query, setQuery] = useState('');
519
+ const [results, setResults] = useState<string[]>([]);
520
+ const [isPending, startTransition] = useTransition();
521
+
522
+ function handleSearch(value: string) {
523
+ setQuery(value); // Urgent - update input immediately
524
+
525
+ startTransition(() => {
526
+ // Non-urgent - can be interrupted
527
+ const filtered = hugeDataset.filter((item) =>
528
+ item.toLowerCase().includes(value.toLowerCase())
529
+ );
530
+ setResults(filtered);
531
+ });
532
+ }
533
+
534
+ return (
535
+ <div>
536
+ <input
537
+ type="text"
538
+ value={query}
539
+ onChange={(e) => handleSearch(e.target.value)}
540
+ placeholder="Search..."
541
+ />
542
+
543
+ {isPending && <div>Searching...</div>}
544
+
545
+ <ul>
546
+ {results.map((result) => (
547
+ <li key={result}>{result}</li>
548
+ ))}
549
+ </ul>
550
+ </div>
551
+ );
552
+ }
553
+ ```
554
+
555
+ ### useTransition with Server Actions
556
+
557
+ ```typescript
558
+ 'use client';
559
+
560
+ import { useTransition } from 'react';
561
+ import { deletePost } from '@/actions/posts';
562
+
563
+ export function DeleteButton({ postId }: { postId: string }) {
564
+ const [isPending, startTransition] = useTransition();
565
+
566
+ function handleDelete() {
567
+ startTransition(async () => {
568
+ await deletePost(postId);
569
+ // UI stays responsive during deletion
570
+ });
571
+ }
572
+
573
+ return (
574
+ <button onClick={handleDelete} disabled={isPending}>
575
+ {isPending ? 'Deleting...' : 'Delete'}
576
+ </button>
577
+ );
578
+ }
579
+ ```
580
+
581
+ ## useDeferredValue - Deferred Rendering
582
+
583
+ Defer expensive re-renders while keeping UI responsive.
584
+
585
+ ```typescript
586
+ 'use client';
587
+
588
+ import { useDeferredValue, useState } from 'react';
589
+
590
+ export function ProductSearch() {
591
+ const [query, setQuery] = useState('');
592
+ const deferredQuery = useDeferredValue(query);
593
+
594
+ return (
595
+ <div>
596
+ <input
597
+ type="text"
598
+ value={query}
599
+ onChange={(e) => setQuery(e.target.value)}
600
+ placeholder="Search products..."
601
+ />
602
+
603
+ {/* Uses deferred value - won't block input */}
604
+ <ExpensiveResults query={deferredQuery} />
605
+ </div>
606
+ );
607
+ }
608
+
609
+ function ExpensiveResults({ query }: { query: string }) {
610
+ const results = useMemo(() => {
611
+ // Expensive filtering/sorting
612
+ return products.filter((p) => p.name.includes(query));
613
+ }, [query]);
614
+
615
+ return (
616
+ <ul>
617
+ {results.map((result) => (
618
+ <li key={result.id}>{result.name}</li>
619
+ ))}
620
+ </ul>
621
+ );
622
+ }
623
+ ```
624
+
625
+ ## Migration Checklist
626
+
627
+ Updating from React 18 to React 19:
628
+
629
+ - [ ] Replace forwardRef with ref as prop
630
+ - [ ] Replace useFormState with useActionState
631
+ - [ ] Update Server Action types to include prevState parameter
632
+ - [ ] Use use() for promises in Server Components
633
+ - [ ] Add 'use server' directive to Server Actions
634
+ - [ ] Add 'use client' directive to Client Components
635
+ - [ ] Update TypeScript to 5.0+ for better React 19 support
636
+ - [ ] Update @types/react to 19.x
637
+ - [ ] Test all forms with useActionState
638
+ - [ ] Verify ref forwarding works without forwardRef