@cloudstreamsoftware/claude-tools 1.0.0 → 1.2.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 (190) hide show
  1. package/README.md +152 -37
  2. package/agents/INDEX.md +183 -0
  3. package/agents/architect.md +247 -0
  4. package/agents/build-error-resolver.md +555 -0
  5. package/agents/catalyst-deployer.md +132 -0
  6. package/agents/code-reviewer.md +121 -0
  7. package/agents/compliance-auditor.md +148 -0
  8. package/agents/creator-architect.md +395 -0
  9. package/agents/deluge-reviewer.md +98 -0
  10. package/agents/doc-updater.md +471 -0
  11. package/agents/e2e-runner.md +711 -0
  12. package/agents/planner.md +122 -0
  13. package/agents/refactor-cleaner.md +309 -0
  14. package/agents/security-reviewer.md +582 -0
  15. package/agents/tdd-guide.md +302 -0
  16. package/bin/cloudstream-setup.js +16 -6
  17. package/config/versions.json +63 -0
  18. package/dist/hooks/hooks.json +209 -0
  19. package/dist/index.js +47 -0
  20. package/dist/lib/asset-value.js +609 -0
  21. package/dist/lib/client-manager.js +300 -0
  22. package/dist/lib/command-matcher.js +242 -0
  23. package/dist/lib/cross-session-patterns.js +754 -0
  24. package/dist/lib/intent-classifier.js +1075 -0
  25. package/dist/lib/package-manager.js +374 -0
  26. package/dist/lib/recommendation-engine.js +597 -0
  27. package/dist/lib/session-memory.js +489 -0
  28. package/dist/lib/skill-effectiveness.js +486 -0
  29. package/dist/lib/skill-matcher.js +595 -0
  30. package/dist/lib/tutorial-metrics.js +242 -0
  31. package/dist/lib/tutorial-progress.js +209 -0
  32. package/dist/lib/tutorial-renderer.js +431 -0
  33. package/dist/lib/utils.js +380 -0
  34. package/dist/lib/verify-formatter.js +143 -0
  35. package/dist/lib/workflow-state.js +249 -0
  36. package/hooks/hooks.json +209 -0
  37. package/package.json +5 -1
  38. package/scripts/aggregate-sessions.js +290 -0
  39. package/scripts/branch-name-validator.js +291 -0
  40. package/scripts/build.js +101 -0
  41. package/scripts/commands/client-switch.js +231 -0
  42. package/scripts/deprecate-skill.js +610 -0
  43. package/scripts/diagnose.js +324 -0
  44. package/scripts/doc-freshness.js +168 -0
  45. package/scripts/generate-weekly-digest.js +393 -0
  46. package/scripts/health-check.js +270 -0
  47. package/scripts/hooks/credential-check.js +101 -0
  48. package/scripts/hooks/evaluate-session.js +81 -0
  49. package/scripts/hooks/pre-compact.js +66 -0
  50. package/scripts/hooks/prompt-analyzer.js +276 -0
  51. package/scripts/hooks/prompt-router.js +422 -0
  52. package/scripts/hooks/quality-gate-enforcer.js +371 -0
  53. package/scripts/hooks/session-end.js +156 -0
  54. package/scripts/hooks/session-start.js +195 -0
  55. package/scripts/hooks/skill-injector.js +333 -0
  56. package/scripts/hooks/suggest-compact.js +58 -0
  57. package/scripts/lib/asset-value.js +609 -0
  58. package/scripts/lib/client-manager.js +300 -0
  59. package/scripts/lib/command-matcher.js +242 -0
  60. package/scripts/lib/cross-session-patterns.js +754 -0
  61. package/scripts/lib/intent-classifier.js +1075 -0
  62. package/scripts/lib/package-manager.js +374 -0
  63. package/scripts/lib/recommendation-engine.js +597 -0
  64. package/scripts/lib/session-memory.js +489 -0
  65. package/scripts/lib/skill-effectiveness.js +486 -0
  66. package/scripts/lib/skill-matcher.js +595 -0
  67. package/scripts/lib/tutorial-metrics.js +242 -0
  68. package/scripts/lib/tutorial-progress.js +209 -0
  69. package/scripts/lib/tutorial-renderer.js +431 -0
  70. package/scripts/lib/utils.js +380 -0
  71. package/scripts/lib/verify-formatter.js +143 -0
  72. package/scripts/lib/workflow-state.js +249 -0
  73. package/scripts/onboard.js +363 -0
  74. package/scripts/quarterly-report.js +692 -0
  75. package/scripts/setup-package-manager.js +204 -0
  76. package/scripts/sync-upstream.js +391 -0
  77. package/scripts/test.js +108 -0
  78. package/scripts/tutorial-runner.js +351 -0
  79. package/scripts/validate-all.js +201 -0
  80. package/scripts/verifiers/agents.js +245 -0
  81. package/scripts/verifiers/config.js +186 -0
  82. package/scripts/verifiers/environment.js +123 -0
  83. package/scripts/verifiers/hooks.js +188 -0
  84. package/scripts/verifiers/index.js +38 -0
  85. package/scripts/verifiers/persistence.js +140 -0
  86. package/scripts/verifiers/plugin.js +215 -0
  87. package/scripts/verifiers/skills.js +209 -0
  88. package/scripts/verify-setup.js +164 -0
  89. package/skills/INDEX.md +157 -0
  90. package/skills/backend-patterns/SKILL.md +586 -0
  91. package/skills/backend-patterns/catalyst-patterns.md +128 -0
  92. package/skills/bigquery-patterns/SKILL.md +27 -0
  93. package/skills/bigquery-patterns/performance-optimization.md +518 -0
  94. package/skills/bigquery-patterns/query-patterns.md +372 -0
  95. package/skills/bigquery-patterns/schema-design.md +78 -0
  96. package/skills/cloudstream-project-template/SKILL.md +20 -0
  97. package/skills/cloudstream-project-template/structure.md +65 -0
  98. package/skills/coding-standards/SKILL.md +524 -0
  99. package/skills/coding-standards/deluge-standards.md +83 -0
  100. package/skills/compliance-patterns/SKILL.md +28 -0
  101. package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
  102. package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
  103. package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
  104. package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
  105. package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
  106. package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
  107. package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
  108. package/skills/compliance-patterns/soc2/access-controls.md +344 -0
  109. package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
  110. package/skills/compliance-patterns/soc2/change-management.md +403 -0
  111. package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
  112. package/skills/consultancy-workflows/SKILL.md +19 -0
  113. package/skills/consultancy-workflows/client-isolation.md +21 -0
  114. package/skills/consultancy-workflows/documentation-automation.md +454 -0
  115. package/skills/consultancy-workflows/handoff-procedures.md +257 -0
  116. package/skills/consultancy-workflows/knowledge-capture.md +513 -0
  117. package/skills/consultancy-workflows/time-tracking.md +26 -0
  118. package/skills/continuous-learning/SKILL.md +84 -0
  119. package/skills/continuous-learning/config.json +18 -0
  120. package/skills/continuous-learning/evaluate-session.sh +60 -0
  121. package/skills/continuous-learning-v2/SKILL.md +126 -0
  122. package/skills/continuous-learning-v2/config.json +61 -0
  123. package/skills/frontend-patterns/SKILL.md +635 -0
  124. package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
  125. package/skills/gcp-data-engineering/SKILL.md +36 -0
  126. package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
  127. package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
  128. package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
  129. package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
  130. package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
  131. package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
  132. package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
  133. package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
  134. package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
  135. package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
  136. package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
  137. package/skills/security-review/SKILL.md +498 -0
  138. package/skills/security-review/compliance-checklist.md +53 -0
  139. package/skills/strategic-compact/SKILL.md +67 -0
  140. package/skills/tdd-workflow/SKILL.md +413 -0
  141. package/skills/tdd-workflow/zoho-testing.md +124 -0
  142. package/skills/tutorial/SKILL.md +249 -0
  143. package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
  144. package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
  145. package/skills/tutorial/lessons/01-basics.md +81 -0
  146. package/skills/tutorial/lessons/02-training.md +86 -0
  147. package/skills/tutorial/lessons/03-commands.md +109 -0
  148. package/skills/tutorial/lessons/04-workflows.md +115 -0
  149. package/skills/tutorial/lessons/05-compliance.md +116 -0
  150. package/skills/tutorial/lessons/06-zoho.md +121 -0
  151. package/skills/tutorial/lessons/07-hooks-system.md +277 -0
  152. package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
  153. package/skills/tutorial/lessons/09-client-management.md +215 -0
  154. package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
  155. package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
  156. package/skills/tutorial/lessons/12-rules-system.md +326 -0
  157. package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
  158. package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
  159. package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
  160. package/skills/tutorial/tracks/accelerated/README.md +134 -0
  161. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
  162. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
  163. package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
  164. package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
  165. package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
  166. package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
  167. package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
  168. package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
  169. package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
  170. package/skills/zoho-patterns/CHANGELOG.md +108 -0
  171. package/skills/zoho-patterns/SKILL.md +446 -0
  172. package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
  173. package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
  174. package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
  175. package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
  176. package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
  177. package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
  178. package/skills/zoho-patterns/creator/form-design.md +304 -0
  179. package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
  180. package/skills/zoho-patterns/creator/widget-integration.md +306 -0
  181. package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
  182. package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
  183. package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
  184. package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
  185. package/skills/zoho-patterns/deluge/error-handling.md +423 -0
  186. package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
  187. package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
  188. package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
  189. package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
  190. package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
@@ -0,0 +1,635 @@
1
+ ---
2
+ name: frontend-patterns
3
+ description: Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.
4
+ version: 1.0.0
5
+ status: active
6
+ introduced: 1.0.0
7
+ lastUpdated: 2026-01-25
8
+ ---
9
+
10
+ # Frontend Development Patterns
11
+
12
+ Modern frontend patterns for React, Next.js, and performant user interfaces.
13
+
14
+ ## Component Patterns
15
+
16
+ ### Composition Over Inheritance
17
+
18
+ ```typescript
19
+ // ✅ GOOD: Component composition
20
+ interface CardProps {
21
+ children: React.ReactNode
22
+ variant?: 'default' | 'outlined'
23
+ }
24
+
25
+ export function Card({ children, variant = 'default' }: CardProps) {
26
+ return <div className={`card card-${variant}`}>{children}</div>
27
+ }
28
+
29
+ export function CardHeader({ children }: { children: React.ReactNode }) {
30
+ return <div className="card-header">{children}</div>
31
+ }
32
+
33
+ export function CardBody({ children }: { children: React.ReactNode }) {
34
+ return <div className="card-body">{children}</div>
35
+ }
36
+
37
+ // Usage
38
+ <Card>
39
+ <CardHeader>Title</CardHeader>
40
+ <CardBody>Content</CardBody>
41
+ </Card>
42
+ ```
43
+
44
+ ### Compound Components
45
+
46
+ ```typescript
47
+ interface TabsContextValue {
48
+ activeTab: string
49
+ setActiveTab: (tab: string) => void
50
+ }
51
+
52
+ const TabsContext = createContext<TabsContextValue | undefined>(undefined)
53
+
54
+ export function Tabs({ children, defaultTab }: {
55
+ children: React.ReactNode
56
+ defaultTab: string
57
+ }) {
58
+ const [activeTab, setActiveTab] = useState(defaultTab)
59
+
60
+ return (
61
+ <TabsContext.Provider value={{ activeTab, setActiveTab }}>
62
+ {children}
63
+ </TabsContext.Provider>
64
+ )
65
+ }
66
+
67
+ export function TabList({ children }: { children: React.ReactNode }) {
68
+ return <div className="tab-list">{children}</div>
69
+ }
70
+
71
+ export function Tab({ id, children }: { id: string, children: React.ReactNode }) {
72
+ const context = useContext(TabsContext)
73
+ if (!context) throw new Error('Tab must be used within Tabs')
74
+
75
+ return (
76
+ <button
77
+ className={context.activeTab === id ? 'active' : ''}
78
+ onClick={() => context.setActiveTab(id)}
79
+ >
80
+ {children}
81
+ </button>
82
+ )
83
+ }
84
+
85
+ // Usage
86
+ <Tabs defaultTab="overview">
87
+ <TabList>
88
+ <Tab id="overview">Overview</Tab>
89
+ <Tab id="details">Details</Tab>
90
+ </TabList>
91
+ </Tabs>
92
+ ```
93
+
94
+ ### Render Props Pattern
95
+
96
+ ```typescript
97
+ interface DataLoaderProps<T> {
98
+ url: string
99
+ children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode
100
+ }
101
+
102
+ export function DataLoader<T>({ url, children }: DataLoaderProps<T>) {
103
+ const [data, setData] = useState<T | null>(null)
104
+ const [loading, setLoading] = useState(true)
105
+ const [error, setError] = useState<Error | null>(null)
106
+
107
+ useEffect(() => {
108
+ fetch(url)
109
+ .then(res => res.json())
110
+ .then(setData)
111
+ .catch(setError)
112
+ .finally(() => setLoading(false))
113
+ }, [url])
114
+
115
+ return <>{children(data, loading, error)}</>
116
+ }
117
+
118
+ // Usage
119
+ <DataLoader<Market[]> url="/api/markets">
120
+ {(markets, loading, error) => {
121
+ if (loading) return <Spinner />
122
+ if (error) return <Error error={error} />
123
+ return <MarketList markets={markets!} />
124
+ }}
125
+ </DataLoader>
126
+ ```
127
+
128
+ ## Custom Hooks Patterns
129
+
130
+ ### State Management Hook
131
+
132
+ ```typescript
133
+ export function useToggle(initialValue = false): [boolean, () => void] {
134
+ const [value, setValue] = useState(initialValue)
135
+
136
+ const toggle = useCallback(() => {
137
+ setValue(v => !v)
138
+ }, [])
139
+
140
+ return [value, toggle]
141
+ }
142
+
143
+ // Usage
144
+ const [isOpen, toggleOpen] = useToggle()
145
+ ```
146
+
147
+ ### Async Data Fetching Hook
148
+
149
+ ```typescript
150
+ interface UseQueryOptions<T> {
151
+ onSuccess?: (data: T) => void
152
+ onError?: (error: Error) => void
153
+ enabled?: boolean
154
+ }
155
+
156
+ export function useQuery<T>(
157
+ key: string,
158
+ fetcher: () => Promise<T>,
159
+ options?: UseQueryOptions<T>
160
+ ) {
161
+ const [data, setData] = useState<T | null>(null)
162
+ const [error, setError] = useState<Error | null>(null)
163
+ const [loading, setLoading] = useState(false)
164
+
165
+ const refetch = useCallback(async () => {
166
+ setLoading(true)
167
+ setError(null)
168
+
169
+ try {
170
+ const result = await fetcher()
171
+ setData(result)
172
+ options?.onSuccess?.(result)
173
+ } catch (err) {
174
+ const error = err as Error
175
+ setError(error)
176
+ options?.onError?.(error)
177
+ } finally {
178
+ setLoading(false)
179
+ }
180
+ }, [fetcher, options])
181
+
182
+ useEffect(() => {
183
+ if (options?.enabled !== false) {
184
+ refetch()
185
+ }
186
+ }, [key, refetch, options?.enabled])
187
+
188
+ return { data, error, loading, refetch }
189
+ }
190
+
191
+ // Usage
192
+ const { data: markets, loading, error, refetch } = useQuery(
193
+ 'markets',
194
+ () => fetch('/api/markets').then(r => r.json()),
195
+ {
196
+ onSuccess: data => console.log('Fetched', data.length, 'markets'),
197
+ onError: err => console.error('Failed:', err)
198
+ }
199
+ )
200
+ ```
201
+
202
+ ### Debounce Hook
203
+
204
+ ```typescript
205
+ export function useDebounce<T>(value: T, delay: number): T {
206
+ const [debouncedValue, setDebouncedValue] = useState<T>(value)
207
+
208
+ useEffect(() => {
209
+ const handler = setTimeout(() => {
210
+ setDebouncedValue(value)
211
+ }, delay)
212
+
213
+ return () => clearTimeout(handler)
214
+ }, [value, delay])
215
+
216
+ return debouncedValue
217
+ }
218
+
219
+ // Usage
220
+ const [searchQuery, setSearchQuery] = useState('')
221
+ const debouncedQuery = useDebounce(searchQuery, 500)
222
+
223
+ useEffect(() => {
224
+ if (debouncedQuery) {
225
+ performSearch(debouncedQuery)
226
+ }
227
+ }, [debouncedQuery])
228
+ ```
229
+
230
+ ## State Management Patterns
231
+
232
+ ### Context + Reducer Pattern
233
+
234
+ ```typescript
235
+ interface State {
236
+ markets: Market[]
237
+ selectedMarket: Market | null
238
+ loading: boolean
239
+ }
240
+
241
+ type Action =
242
+ | { type: 'SET_MARKETS'; payload: Market[] }
243
+ | { type: 'SELECT_MARKET'; payload: Market }
244
+ | { type: 'SET_LOADING'; payload: boolean }
245
+
246
+ function reducer(state: State, action: Action): State {
247
+ switch (action.type) {
248
+ case 'SET_MARKETS':
249
+ return { ...state, markets: action.payload }
250
+ case 'SELECT_MARKET':
251
+ return { ...state, selectedMarket: action.payload }
252
+ case 'SET_LOADING':
253
+ return { ...state, loading: action.payload }
254
+ default:
255
+ return state
256
+ }
257
+ }
258
+
259
+ const MarketContext = createContext<{
260
+ state: State
261
+ dispatch: Dispatch<Action>
262
+ } | undefined>(undefined)
263
+
264
+ export function MarketProvider({ children }: { children: React.ReactNode }) {
265
+ const [state, dispatch] = useReducer(reducer, {
266
+ markets: [],
267
+ selectedMarket: null,
268
+ loading: false
269
+ })
270
+
271
+ return (
272
+ <MarketContext.Provider value={{ state, dispatch }}>
273
+ {children}
274
+ </MarketContext.Provider>
275
+ )
276
+ }
277
+
278
+ export function useMarkets() {
279
+ const context = useContext(MarketContext)
280
+ if (!context) throw new Error('useMarkets must be used within MarketProvider')
281
+ return context
282
+ }
283
+ ```
284
+
285
+ ## Performance Optimization
286
+
287
+ ### Memoization
288
+
289
+ ```typescript
290
+ // ✅ useMemo for expensive computations
291
+ const sortedMarkets = useMemo(() => {
292
+ return markets.sort((a, b) => b.volume - a.volume)
293
+ }, [markets])
294
+
295
+ // ✅ useCallback for functions passed to children
296
+ const handleSearch = useCallback((query: string) => {
297
+ setSearchQuery(query)
298
+ }, [])
299
+
300
+ // ✅ React.memo for pure components
301
+ export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
302
+ return (
303
+ <div className="market-card">
304
+ <h3>{market.name}</h3>
305
+ <p>{market.description}</p>
306
+ </div>
307
+ )
308
+ })
309
+ ```
310
+
311
+ ### Code Splitting & Lazy Loading
312
+
313
+ ```typescript
314
+ import { lazy, Suspense } from 'react'
315
+
316
+ // ✅ Lazy load heavy components
317
+ const HeavyChart = lazy(() => import('./HeavyChart'))
318
+ const ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))
319
+
320
+ export function Dashboard() {
321
+ return (
322
+ <div>
323
+ <Suspense fallback={<ChartSkeleton />}>
324
+ <HeavyChart data={data} />
325
+ </Suspense>
326
+
327
+ <Suspense fallback={null}>
328
+ <ThreeJsBackground />
329
+ </Suspense>
330
+ </div>
331
+ )
332
+ }
333
+ ```
334
+
335
+ ### Virtualization for Long Lists
336
+
337
+ ```typescript
338
+ import { useVirtualizer } from '@tanstack/react-virtual'
339
+
340
+ export function VirtualMarketList({ markets }: { markets: Market[] }) {
341
+ const parentRef = useRef<HTMLDivElement>(null)
342
+
343
+ const virtualizer = useVirtualizer({
344
+ count: markets.length,
345
+ getScrollElement: () => parentRef.current,
346
+ estimateSize: () => 100, // Estimated row height
347
+ overscan: 5 // Extra items to render
348
+ })
349
+
350
+ return (
351
+ <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
352
+ <div
353
+ style={{
354
+ height: `${virtualizer.getTotalSize()}px`,
355
+ position: 'relative'
356
+ }}
357
+ >
358
+ {virtualizer.getVirtualItems().map(virtualRow => (
359
+ <div
360
+ key={virtualRow.index}
361
+ style={{
362
+ position: 'absolute',
363
+ top: 0,
364
+ left: 0,
365
+ width: '100%',
366
+ height: `${virtualRow.size}px`,
367
+ transform: `translateY(${virtualRow.start}px)`
368
+ }}
369
+ >
370
+ <MarketCard market={markets[virtualRow.index]} />
371
+ </div>
372
+ ))}
373
+ </div>
374
+ </div>
375
+ )
376
+ }
377
+ ```
378
+
379
+ ## Form Handling Patterns
380
+
381
+ ### Controlled Form with Validation
382
+
383
+ ```typescript
384
+ interface FormData {
385
+ name: string
386
+ description: string
387
+ endDate: string
388
+ }
389
+
390
+ interface FormErrors {
391
+ name?: string
392
+ description?: string
393
+ endDate?: string
394
+ }
395
+
396
+ export function CreateMarketForm() {
397
+ const [formData, setFormData] = useState<FormData>({
398
+ name: '',
399
+ description: '',
400
+ endDate: ''
401
+ })
402
+
403
+ const [errors, setErrors] = useState<FormErrors>({})
404
+
405
+ const validate = (): boolean => {
406
+ const newErrors: FormErrors = {}
407
+
408
+ if (!formData.name.trim()) {
409
+ newErrors.name = 'Name is required'
410
+ } else if (formData.name.length > 200) {
411
+ newErrors.name = 'Name must be under 200 characters'
412
+ }
413
+
414
+ if (!formData.description.trim()) {
415
+ newErrors.description = 'Description is required'
416
+ }
417
+
418
+ if (!formData.endDate) {
419
+ newErrors.endDate = 'End date is required'
420
+ }
421
+
422
+ setErrors(newErrors)
423
+ return Object.keys(newErrors).length === 0
424
+ }
425
+
426
+ const handleSubmit = async (e: React.FormEvent) => {
427
+ e.preventDefault()
428
+
429
+ if (!validate()) return
430
+
431
+ try {
432
+ await createMarket(formData)
433
+ // Success handling
434
+ } catch (error) {
435
+ // Error handling
436
+ }
437
+ }
438
+
439
+ return (
440
+ <form onSubmit={handleSubmit}>
441
+ <input
442
+ value={formData.name}
443
+ onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
444
+ placeholder="Market name"
445
+ />
446
+ {errors.name && <span className="error">{errors.name}</span>}
447
+
448
+ {/* Other fields */}
449
+
450
+ <button type="submit">Create Market</button>
451
+ </form>
452
+ )
453
+ }
454
+ ```
455
+
456
+ ## Error Boundary Pattern
457
+
458
+ ```typescript
459
+ interface ErrorBoundaryState {
460
+ hasError: boolean
461
+ error: Error | null
462
+ }
463
+
464
+ export class ErrorBoundary extends React.Component<
465
+ { children: React.ReactNode },
466
+ ErrorBoundaryState
467
+ > {
468
+ state: ErrorBoundaryState = {
469
+ hasError: false,
470
+ error: null
471
+ }
472
+
473
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
474
+ return { hasError: true, error }
475
+ }
476
+
477
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
478
+ console.error('Error boundary caught:', error, errorInfo)
479
+ }
480
+
481
+ render() {
482
+ if (this.state.hasError) {
483
+ return (
484
+ <div className="error-fallback">
485
+ <h2>Something went wrong</h2>
486
+ <p>{this.state.error?.message}</p>
487
+ <button onClick={() => this.setState({ hasError: false })}>
488
+ Try again
489
+ </button>
490
+ </div>
491
+ )
492
+ }
493
+
494
+ return this.props.children
495
+ }
496
+ }
497
+
498
+ // Usage
499
+ <ErrorBoundary>
500
+ <App />
501
+ </ErrorBoundary>
502
+ ```
503
+
504
+ ## Animation Patterns
505
+
506
+ ### Framer Motion Animations
507
+
508
+ ```typescript
509
+ import { motion, AnimatePresence } from 'framer-motion'
510
+
511
+ // ✅ List animations
512
+ export function AnimatedMarketList({ markets }: { markets: Market[] }) {
513
+ return (
514
+ <AnimatePresence>
515
+ {markets.map(market => (
516
+ <motion.div
517
+ key={market.id}
518
+ initial={{ opacity: 0, y: 20 }}
519
+ animate={{ opacity: 1, y: 0 }}
520
+ exit={{ opacity: 0, y: -20 }}
521
+ transition={{ duration: 0.3 }}
522
+ >
523
+ <MarketCard market={market} />
524
+ </motion.div>
525
+ ))}
526
+ </AnimatePresence>
527
+ )
528
+ }
529
+
530
+ // ✅ Modal animations
531
+ export function Modal({ isOpen, onClose, children }: ModalProps) {
532
+ return (
533
+ <AnimatePresence>
534
+ {isOpen && (
535
+ <>
536
+ <motion.div
537
+ className="modal-overlay"
538
+ initial={{ opacity: 0 }}
539
+ animate={{ opacity: 1 }}
540
+ exit={{ opacity: 0 }}
541
+ onClick={onClose}
542
+ />
543
+ <motion.div
544
+ className="modal-content"
545
+ initial={{ opacity: 0, scale: 0.9, y: 20 }}
546
+ animate={{ opacity: 1, scale: 1, y: 0 }}
547
+ exit={{ opacity: 0, scale: 0.9, y: 20 }}
548
+ >
549
+ {children}
550
+ </motion.div>
551
+ </>
552
+ )}
553
+ </AnimatePresence>
554
+ )
555
+ }
556
+ ```
557
+
558
+ ## Accessibility Patterns
559
+
560
+ ### Keyboard Navigation
561
+
562
+ ```typescript
563
+ export function Dropdown({ options, onSelect }: DropdownProps) {
564
+ const [isOpen, setIsOpen] = useState(false)
565
+ const [activeIndex, setActiveIndex] = useState(0)
566
+
567
+ const handleKeyDown = (e: React.KeyboardEvent) => {
568
+ switch (e.key) {
569
+ case 'ArrowDown':
570
+ e.preventDefault()
571
+ setActiveIndex(i => Math.min(i + 1, options.length - 1))
572
+ break
573
+ case 'ArrowUp':
574
+ e.preventDefault()
575
+ setActiveIndex(i => Math.max(i - 1, 0))
576
+ break
577
+ case 'Enter':
578
+ e.preventDefault()
579
+ onSelect(options[activeIndex])
580
+ setIsOpen(false)
581
+ break
582
+ case 'Escape':
583
+ setIsOpen(false)
584
+ break
585
+ }
586
+ }
587
+
588
+ return (
589
+ <div
590
+ role="combobox"
591
+ aria-expanded={isOpen}
592
+ aria-haspopup="listbox"
593
+ onKeyDown={handleKeyDown}
594
+ >
595
+ {/* Dropdown implementation */}
596
+ </div>
597
+ )
598
+ }
599
+ ```
600
+
601
+ ### Focus Management
602
+
603
+ ```typescript
604
+ export function Modal({ isOpen, onClose, children }: ModalProps) {
605
+ const modalRef = useRef<HTMLDivElement>(null)
606
+ const previousFocusRef = useRef<HTMLElement | null>(null)
607
+
608
+ useEffect(() => {
609
+ if (isOpen) {
610
+ // Save currently focused element
611
+ previousFocusRef.current = document.activeElement as HTMLElement
612
+
613
+ // Focus modal
614
+ modalRef.current?.focus()
615
+ } else {
616
+ // Restore focus when closing
617
+ previousFocusRef.current?.focus()
618
+ }
619
+ }, [isOpen])
620
+
621
+ return isOpen ? (
622
+ <div
623
+ ref={modalRef}
624
+ role="dialog"
625
+ aria-modal="true"
626
+ tabIndex={-1}
627
+ onKeyDown={e => e.key === 'Escape' && onClose()}
628
+ >
629
+ {children}
630
+ </div>
631
+ ) : null
632
+ }
633
+ ```
634
+
635
+ **Remember**: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.