@thesage/mcp 0.6.0 → 0.7.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.
@@ -0,0 +1,2195 @@
1
+ // src/registry.ts
2
+ var COMPONENT_CATEGORIES = {
3
+ actions: {
4
+ label: "Actions",
5
+ description: "Interactive elements that trigger behaviors",
6
+ count: 5
7
+ },
8
+ forms: {
9
+ label: "Forms",
10
+ description: "Input controls for data collection",
11
+ count: 18
12
+ },
13
+ navigation: {
14
+ label: "Navigation",
15
+ description: "Moving through content and hierarchy",
16
+ count: 10
17
+ },
18
+ overlays: {
19
+ label: "Overlays",
20
+ description: "Contextual content that appears above the main UI",
21
+ count: 11
22
+ },
23
+ feedback: {
24
+ label: "Feedback",
25
+ description: "Communicating system state and user action results",
26
+ count: 7
27
+ },
28
+ "data-display": {
29
+ label: "Data Display",
30
+ description: "Presenting information in structured formats",
31
+ count: 16
32
+ },
33
+ layout: {
34
+ label: "Layout",
35
+ description: "Spatial organization and structural elements",
36
+ count: 17
37
+ },
38
+ backgrounds: {
39
+ label: "Backgrounds",
40
+ description: "Animated background effects and decorative elements",
41
+ count: 3
42
+ },
43
+ cursor: {
44
+ label: "Cursor",
45
+ description: "Custom cursor effects and interactions",
46
+ count: 2
47
+ },
48
+ motion: {
49
+ label: "Motion",
50
+ description: "Animation components and motion effects",
51
+ count: 1
52
+ },
53
+ blocks: {
54
+ label: "Blocks",
55
+ description: "Composed page sections and layouts",
56
+ count: 2
57
+ }
58
+ };
59
+ var COMPONENT_REGISTRY = {
60
+ // ============================================================================
61
+ // ACTIONS (3)
62
+ // ============================================================================
63
+ button: {
64
+ name: "Button",
65
+ category: "actions",
66
+ description: "Primary interaction element with multiple variants for different use cases",
67
+ keywords: ["button", "click", "action", "submit", "cta", "interactive"],
68
+ useCases: [
69
+ "Form submission",
70
+ "Navigation triggers",
71
+ "Action confirmation",
72
+ "Call-to-action elements"
73
+ ],
74
+ dependencies: ["@radix-ui/react-slot"],
75
+ radixPrimitive: "@radix-ui/react-slot",
76
+ props: {
77
+ variant: { type: "'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'", default: "'default'", description: "Visual style variant" },
78
+ size: { type: "'sm' | 'default' | 'lg' | 'icon'", default: "'default'", description: "Size variant" },
79
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" },
80
+ asChild: { type: "boolean", default: "false", description: "Render as child element via Radix Slot" }
81
+ },
82
+ example: `<Button variant="outline" size="sm" onClick={handleClick}>Click Me</Button>`
83
+ },
84
+ toggle: {
85
+ name: "Toggle",
86
+ category: "actions",
87
+ description: "Binary state toggle with pressed/unpressed states",
88
+ keywords: ["toggle", "switch", "binary", "on-off", "state"],
89
+ useCases: [
90
+ "Toolbar buttons",
91
+ "Feature toggles",
92
+ "View mode switches",
93
+ "Filter activation"
94
+ ],
95
+ dependencies: ["@radix-ui/react-toggle"],
96
+ radixPrimitive: "@radix-ui/react-toggle",
97
+ props: {
98
+ pressed: { type: "boolean", description: "Controlled pressed state" },
99
+ onPressedChange: { type: "(pressed: boolean) => void", description: "Callback on press change" },
100
+ variant: { type: "'default' | 'outline'", default: "'default'", description: "Visual variant" },
101
+ size: { type: "'sm' | 'default' | 'lg'", default: "'default'", description: "Size variant" },
102
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" }
103
+ },
104
+ example: `<Toggle pressed={isBold} onPressedChange={setIsBold}><Bold className="h-4 w-4" /></Toggle>`
105
+ },
106
+ "toggle-group": {
107
+ name: "ToggleGroup",
108
+ category: "actions",
109
+ description: "Multiple toggles with single or multi-select modes",
110
+ keywords: ["toggle", "group", "selection", "multi-select", "options"],
111
+ useCases: [
112
+ "Text formatting toolbars",
113
+ "View mode selection",
114
+ "Filter groups",
115
+ "Option selection"
116
+ ],
117
+ dependencies: ["@radix-ui/react-toggle-group"],
118
+ radixPrimitive: "@radix-ui/react-toggle-group",
119
+ props: {
120
+ type: { type: "'single' | 'multiple'", description: "Selection mode", required: true },
121
+ value: { type: "string | string[]", description: "Selected value(s)" },
122
+ onValueChange: { type: "(value) => void", description: "Callback on value change" },
123
+ variant: { type: "'default' | 'outline'", default: "'default'", description: "Visual variant" },
124
+ size: { type: "'sm' | 'default' | 'lg'", default: "'default'", description: "Size variant" }
125
+ },
126
+ subComponents: ["ToggleGroupItem"],
127
+ example: `<ToggleGroup type="single" value={align} onValueChange={setAlign}>
128
+ <ToggleGroupItem value="left">Left</ToggleGroupItem>
129
+ <ToggleGroupItem value="center">Center</ToggleGroupItem>
130
+ </ToggleGroup>`
131
+ },
132
+ // ============================================================================
133
+ // FORMS (11)
134
+ // ============================================================================
135
+ checkbox: {
136
+ name: "Checkbox",
137
+ category: "forms",
138
+ description: "Boolean selection control for single or grouped choices",
139
+ keywords: ["checkbox", "selection", "boolean", "multi-select", "form"],
140
+ useCases: [
141
+ "Multi-select options",
142
+ "Terms acceptance",
143
+ "Feature preferences",
144
+ "Bulk actions"
145
+ ],
146
+ dependencies: ["@radix-ui/react-checkbox"],
147
+ radixPrimitive: "@radix-ui/react-checkbox",
148
+ props: {
149
+ checked: { type: "boolean | 'indeterminate'", description: "Checked state" },
150
+ onCheckedChange: { type: "(checked: boolean) => void", description: "Callback on check change" },
151
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" }
152
+ },
153
+ example: `<div className="flex items-center gap-2">
154
+ <Checkbox id="terms" checked={accepted} onCheckedChange={setAccepted} />
155
+ <Label htmlFor="terms">Accept terms</Label>
156
+ </div>`
157
+ },
158
+ combobox: {
159
+ name: "Combobox",
160
+ category: "forms",
161
+ description: "Searchable select component with autocomplete functionality",
162
+ keywords: ["combobox", "autocomplete", "search", "select", "dropdown", "filter"],
163
+ useCases: [
164
+ "Country/state selection",
165
+ "Tag selection",
166
+ "User mention",
167
+ "Large option lists"
168
+ ],
169
+ dependencies: ["cmdk", "@radix-ui/react-popover"],
170
+ radixPrimitive: "@radix-ui/react-popover",
171
+ props: {
172
+ options: { type: "{ value: string; label: string }[]", description: "List of options", required: true },
173
+ value: { type: "string", description: "Selected value" },
174
+ onValueChange: { type: "(value: string) => void", description: "Callback on selection" },
175
+ placeholder: { type: "string", description: "Trigger placeholder text" },
176
+ searchPlaceholder: { type: "string", description: "Search input placeholder" },
177
+ emptyText: { type: "string", description: "Text when no results found" }
178
+ },
179
+ example: `<Combobox
180
+ options={[{ value: 'react', label: 'React' }, { value: 'vue', label: 'Vue' }]}
181
+ value={framework}
182
+ onValueChange={setFramework}
183
+ placeholder="Select framework"
184
+ />`
185
+ },
186
+ form: {
187
+ name: "Form",
188
+ category: "forms",
189
+ description: "Form wrapper with react-hook-form and zod validation integration",
190
+ keywords: ["form", "validation", "zod", "react-hook-form", "schema"],
191
+ useCases: [
192
+ "User registration",
193
+ "Settings forms",
194
+ "Data entry",
195
+ "Multi-step forms"
196
+ ],
197
+ dependencies: ["react-hook-form", "@hookform/resolvers", "zod"],
198
+ props: {
199
+ "...form": { type: "UseFormReturn", description: "Spread react-hook-form useForm() return value", required: true }
200
+ },
201
+ subComponents: ["FormControl", "FormDescription", "FormField", "FormItem", "FormLabel", "FormMessage"],
202
+ example: `<Form {...form}>
203
+ <form onSubmit={form.handleSubmit(onSubmit)}>
204
+ <FormField control={form.control} name="email" render={({ field }) => (
205
+ <FormItem>
206
+ <FormLabel>Email</FormLabel>
207
+ <FormControl><Input {...field} /></FormControl>
208
+ <FormMessage />
209
+ </FormItem>
210
+ )} />
211
+ <Button type="submit">Submit</Button>
212
+ </form>
213
+ </Form>`
214
+ },
215
+ input: {
216
+ name: "Input",
217
+ category: "forms",
218
+ description: "Text input field supporting various types (text, email, password, number)",
219
+ keywords: ["input", "text", "field", "form", "email", "password"],
220
+ useCases: [
221
+ "Text entry",
222
+ "Email addresses",
223
+ "Passwords",
224
+ "Numeric input"
225
+ ],
226
+ dependencies: [],
227
+ props: {
228
+ type: { type: "string", default: "'text'", description: "HTML input type" },
229
+ placeholder: { type: "string", description: "Placeholder text" },
230
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" }
231
+ },
232
+ example: `<Input type="email" placeholder="Enter email" />`
233
+ },
234
+ "input-otp": {
235
+ name: "InputOTP",
236
+ category: "forms",
237
+ description: "One-time password input with individual character slots",
238
+ keywords: ["otp", "verification", "security", "authentication", "2fa", "code"],
239
+ useCases: [
240
+ "Two-factor authentication",
241
+ "Email verification",
242
+ "Phone verification",
243
+ "Security codes"
244
+ ],
245
+ dependencies: ["input-otp"],
246
+ props: {
247
+ maxLength: { type: "number", default: "6", description: "Maximum number of characters" },
248
+ value: { type: "string", description: "Controlled input value" },
249
+ onChange: { type: "(value: string) => void", description: "Callback on value change" }
250
+ },
251
+ subComponents: ["InputOTPGroup", "InputOTPSlot", "InputOTPSeparator"],
252
+ example: `<InputOTP maxLength={6}>
253
+ <InputOTPGroup>
254
+ <InputOTPSlot index={0} />
255
+ <InputOTPSlot index={1} />
256
+ <InputOTPSlot index={2} />
257
+ </InputOTPGroup>
258
+ <InputOTPSeparator />
259
+ <InputOTPGroup>
260
+ <InputOTPSlot index={3} />
261
+ <InputOTPSlot index={4} />
262
+ <InputOTPSlot index={5} />
263
+ </InputOTPGroup>
264
+ </InputOTP>`
265
+ },
266
+ label: {
267
+ name: "Label",
268
+ category: "forms",
269
+ description: "Form field labels with proper accessibility associations",
270
+ keywords: ["label", "form", "accessibility", "field-label"],
271
+ useCases: [
272
+ "Form field labels",
273
+ "Input descriptions",
274
+ "Accessible forms"
275
+ ],
276
+ dependencies: ["@radix-ui/react-label"],
277
+ radixPrimitive: "@radix-ui/react-label",
278
+ props: {
279
+ htmlFor: { type: "string", description: "ID of the associated form control" }
280
+ },
281
+ example: `<Label htmlFor="email">Email Address</Label>
282
+ <Input id="email" type="email" />`
283
+ },
284
+ "radio-group": {
285
+ name: "RadioGroup",
286
+ category: "forms",
287
+ description: "Exclusive selection control for choosing one option from multiple",
288
+ keywords: ["radio", "selection", "exclusive", "single-select", "options"],
289
+ useCases: [
290
+ "Single option selection",
291
+ "Survey questions",
292
+ "Payment methods",
293
+ "Shipping options"
294
+ ],
295
+ dependencies: ["@radix-ui/react-radio-group"],
296
+ radixPrimitive: "@radix-ui/react-radio-group",
297
+ props: {
298
+ value: { type: "string", description: "Controlled selected value" },
299
+ onValueChange: { type: "(value: string) => void", description: "Callback on selection" },
300
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" }
301
+ },
302
+ subComponents: ["RadioGroupItem"],
303
+ example: `<RadioGroup value={plan} onValueChange={setPlan}>
304
+ <div className="flex items-center gap-2">
305
+ <RadioGroupItem value="free" id="free" />
306
+ <Label htmlFor="free">Free</Label>
307
+ </div>
308
+ </RadioGroup>`
309
+ },
310
+ select: {
311
+ name: "Select",
312
+ category: "forms",
313
+ description: "Dropdown selection component for choosing from a list of options",
314
+ keywords: ["select", "dropdown", "options", "picker", "choice"],
315
+ useCases: [
316
+ "Option selection",
317
+ "Category filtering",
318
+ "Settings choice",
319
+ "Data sorting"
320
+ ],
321
+ dependencies: ["@radix-ui/react-select"],
322
+ radixPrimitive: "@radix-ui/react-select",
323
+ props: {
324
+ value: { type: "string", description: "Controlled selected value" },
325
+ onValueChange: { type: "(value: string) => void", description: "Callback on selection" },
326
+ defaultValue: { type: "string", description: "Default selected value" }
327
+ },
328
+ subComponents: ["SelectTrigger", "SelectValue", "SelectContent", "SelectItem", "SelectGroup", "SelectLabel", "SelectSeparator"],
329
+ example: `<Select value={theme} onValueChange={setTheme}>
330
+ <SelectTrigger className="w-[180px]">
331
+ <SelectValue placeholder="Select theme" />
332
+ </SelectTrigger>
333
+ <SelectContent>
334
+ <SelectItem value="light">Light</SelectItem>
335
+ <SelectItem value="dark">Dark</SelectItem>
336
+ </SelectContent>
337
+ </Select>`
338
+ },
339
+ slider: {
340
+ name: "Slider",
341
+ category: "forms",
342
+ description: "Numeric input control via dragging for range selection",
343
+ keywords: ["slider", "range", "numeric", "volume", "adjustment"],
344
+ useCases: [
345
+ "Volume control",
346
+ "Price ranges",
347
+ "Numeric settings",
348
+ "Zoom level"
349
+ ],
350
+ dependencies: ["@radix-ui/react-slider"],
351
+ radixPrimitive: "@radix-ui/react-slider",
352
+ props: {
353
+ value: { type: "number[]", description: "Current value(s)" },
354
+ onValueChange: { type: "(value: number[]) => void", description: "Callback on value change" },
355
+ min: { type: "number", default: "0", description: "Minimum value" },
356
+ max: { type: "number", default: "100", description: "Maximum value" },
357
+ step: { type: "number", default: "1", description: "Step increment" },
358
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" }
359
+ },
360
+ example: `<Slider value={[volume]} onValueChange={(v) => setVolume(v[0])} max={100} step={1} />`
361
+ },
362
+ switch: {
363
+ name: "Switch",
364
+ category: "forms",
365
+ description: "Toggle switch for binary state changes in forms",
366
+ keywords: ["switch", "toggle", "boolean", "on-off", "settings"],
367
+ useCases: [
368
+ "Feature toggles",
369
+ "Notification settings",
370
+ "Privacy options",
371
+ "Mode switches"
372
+ ],
373
+ dependencies: ["@radix-ui/react-switch"],
374
+ radixPrimitive: "@radix-ui/react-switch",
375
+ props: {
376
+ checked: { type: "boolean", description: "Controlled checked state" },
377
+ onCheckedChange: { type: "(checked: boolean) => void", description: "Callback on toggle" },
378
+ size: { type: "'sm' | 'md' | 'lg'", default: "'md'", description: "Size variant" },
379
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" },
380
+ label: { type: "string", description: "Optional label text" }
381
+ },
382
+ example: `<Switch checked={enabled} onCheckedChange={setEnabled} size="md" />`
383
+ },
384
+ textarea: {
385
+ name: "Textarea",
386
+ category: "forms",
387
+ description: "Multi-line text input for longer content",
388
+ keywords: ["textarea", "text", "multiline", "input", "comment", "description"],
389
+ useCases: [
390
+ "Comment fields",
391
+ "Message composition",
392
+ "Descriptions",
393
+ "Long-form text"
394
+ ],
395
+ dependencies: [],
396
+ props: {
397
+ placeholder: { type: "string", description: "Placeholder text" },
398
+ disabled: { type: "boolean", default: "false", description: "Disable interaction" },
399
+ rows: { type: "number", description: "Number of visible rows" }
400
+ },
401
+ example: `<Textarea placeholder="Write your message..." rows={4} />`
402
+ },
403
+ // ============================================================================
404
+ // NAVIGATION (6)
405
+ // ============================================================================
406
+ breadcrumb: {
407
+ name: "Breadcrumb",
408
+ category: "navigation",
409
+ description: "Hierarchical location indicator showing navigation path",
410
+ keywords: ["breadcrumb", "navigation", "path", "hierarchy", "location"],
411
+ useCases: [
412
+ "Page hierarchy",
413
+ "Multi-level navigation",
414
+ "Location context",
415
+ "Back navigation"
416
+ ],
417
+ dependencies: [],
418
+ subComponents: ["BreadcrumbList", "BreadcrumbItem", "BreadcrumbLink", "BreadcrumbPage", "BreadcrumbSeparator", "BreadcrumbEllipsis"],
419
+ example: `<Breadcrumb>
420
+ <BreadcrumbList>
421
+ <BreadcrumbItem><BreadcrumbLink href="/">Home</BreadcrumbLink></BreadcrumbItem>
422
+ <BreadcrumbSeparator />
423
+ <BreadcrumbItem><BreadcrumbLink href="/docs">Docs</BreadcrumbLink></BreadcrumbItem>
424
+ <BreadcrumbSeparator />
425
+ <BreadcrumbItem><BreadcrumbPage>Current</BreadcrumbPage></BreadcrumbItem>
426
+ </BreadcrumbList>
427
+ </Breadcrumb>`
428
+ },
429
+ command: {
430
+ name: "Command",
431
+ category: "navigation",
432
+ description: "Command palette interface for searchable actions and navigation",
433
+ keywords: ["command", "palette", "search", "shortcuts", "keyboard", "cmdk"],
434
+ useCases: [
435
+ "Quick navigation",
436
+ "Action search",
437
+ "Keyboard shortcuts",
438
+ "Power user features"
439
+ ],
440
+ dependencies: ["cmdk"],
441
+ subComponents: ["CommandInput", "CommandList", "CommandEmpty", "CommandGroup", "CommandItem", "CommandSeparator", "CommandShortcut", "CommandDialog"],
442
+ example: `<Command>
443
+ <CommandInput placeholder="Type a command..." />
444
+ <CommandList>
445
+ <CommandEmpty>No results found.</CommandEmpty>
446
+ <CommandGroup heading="Actions">
447
+ <CommandItem>Search</CommandItem>
448
+ <CommandItem>Settings</CommandItem>
449
+ </CommandGroup>
450
+ </CommandList>
451
+ </Command>`
452
+ },
453
+ menubar: {
454
+ name: "Menubar",
455
+ category: "navigation",
456
+ description: "Desktop-style horizontal menu bar with dropdown menus",
457
+ keywords: ["menubar", "menu", "navigation", "desktop", "toolbar"],
458
+ useCases: [
459
+ "Application menus",
460
+ "Desktop-style navigation",
461
+ "Action menus",
462
+ "Editor toolbars"
463
+ ],
464
+ dependencies: ["@radix-ui/react-menubar"],
465
+ radixPrimitive: "@radix-ui/react-menubar",
466
+ subComponents: ["MenubarMenu", "MenubarTrigger", "MenubarContent", "MenubarItem", "MenubarSeparator", "MenubarLabel", "MenubarCheckboxItem", "MenubarRadioGroup", "MenubarRadioItem", "MenubarSub", "MenubarSubTrigger", "MenubarSubContent", "MenubarShortcut"],
467
+ example: `<Menubar>
468
+ <MenubarMenu>
469
+ <MenubarTrigger>File</MenubarTrigger>
470
+ <MenubarContent>
471
+ <MenubarItem>New <MenubarShortcut>\u2318N</MenubarShortcut></MenubarItem>
472
+ <MenubarItem>Open <MenubarShortcut>\u2318O</MenubarShortcut></MenubarItem>
473
+ <MenubarSeparator />
474
+ <MenubarItem>Exit</MenubarItem>
475
+ </MenubarContent>
476
+ </MenubarMenu>
477
+ </Menubar>`
478
+ },
479
+ "navigation-menu": {
480
+ name: "NavigationMenu",
481
+ category: "navigation",
482
+ description: "Complex header navigation with nested dropdown menus",
483
+ keywords: ["navigation", "menu", "header", "navbar", "dropdown", "mega-menu"],
484
+ useCases: [
485
+ "Site navigation",
486
+ "Header menus",
487
+ "Mega menus",
488
+ "Multi-level navigation"
489
+ ],
490
+ dependencies: ["@radix-ui/react-navigation-menu"],
491
+ radixPrimitive: "@radix-ui/react-navigation-menu",
492
+ subComponents: ["NavigationMenuList", "NavigationMenuItem", "NavigationMenuTrigger", "NavigationMenuContent", "NavigationMenuLink", "NavigationMenuIndicator", "NavigationMenuViewport"],
493
+ example: `<NavigationMenu>
494
+ <NavigationMenuList>
495
+ <NavigationMenuItem>
496
+ <NavigationMenuTrigger>Getting Started</NavigationMenuTrigger>
497
+ <NavigationMenuContent>
498
+ <NavigationMenuLink href="/docs">Documentation</NavigationMenuLink>
499
+ </NavigationMenuContent>
500
+ </NavigationMenuItem>
501
+ </NavigationMenuList>
502
+ </NavigationMenu>`
503
+ },
504
+ pagination: {
505
+ name: "Pagination",
506
+ category: "navigation",
507
+ description: "Multi-page navigation control for paginated content",
508
+ keywords: ["pagination", "pages", "navigation", "paging", "next", "previous"],
509
+ useCases: [
510
+ "Table pagination",
511
+ "Search results",
512
+ "Content lists",
513
+ "Multi-page forms"
514
+ ],
515
+ dependencies: [],
516
+ subComponents: ["PaginationContent", "PaginationItem", "PaginationLink", "PaginationPrevious", "PaginationNext", "PaginationEllipsis"],
517
+ example: `<Pagination>
518
+ <PaginationContent>
519
+ <PaginationItem><PaginationPrevious href="#" /></PaginationItem>
520
+ <PaginationItem><PaginationLink href="#">1</PaginationLink></PaginationItem>
521
+ <PaginationItem><PaginationLink href="#" isActive>2</PaginationLink></PaginationItem>
522
+ <PaginationItem><PaginationLink href="#">3</PaginationLink></PaginationItem>
523
+ <PaginationItem><PaginationNext href="#" /></PaginationItem>
524
+ </PaginationContent>
525
+ </Pagination>`
526
+ },
527
+ tabs: {
528
+ name: "Tabs",
529
+ category: "navigation",
530
+ description: "Tabbed interface for organizing content into switchable panels",
531
+ keywords: ["tabs", "tabbed", "navigation", "panels", "switching"],
532
+ useCases: [
533
+ "Settings panels",
534
+ "Content organization",
535
+ "Multi-view interfaces",
536
+ "Dashboard sections"
537
+ ],
538
+ dependencies: ["@radix-ui/react-tabs"],
539
+ radixPrimitive: "@radix-ui/react-tabs",
540
+ props: {
541
+ defaultValue: { type: "string", description: "Default active tab value" },
542
+ value: { type: "string", description: "Controlled active tab value" },
543
+ onValueChange: { type: "(value: string) => void", description: "Callback on tab change" }
544
+ },
545
+ subComponents: ["TabsList", "TabsTrigger", "TabsContent"],
546
+ example: `<Tabs defaultValue="account">
547
+ <TabsList>
548
+ <TabsTrigger value="account">Account</TabsTrigger>
549
+ <TabsTrigger value="password">Password</TabsTrigger>
550
+ </TabsList>
551
+ <TabsContent value="account">Account settings here.</TabsContent>
552
+ <TabsContent value="password">Password settings here.</TabsContent>
553
+ </Tabs>`
554
+ },
555
+ // ============================================================================
556
+ // OVERLAYS (9)
557
+ // ============================================================================
558
+ "alert-dialog": {
559
+ name: "AlertDialog",
560
+ category: "overlays",
561
+ description: "Modal dialog for critical confirmations with cancel/confirm actions",
562
+ keywords: ["alert", "dialog", "modal", "confirmation", "warning", "destructive"],
563
+ useCases: [
564
+ "Delete confirmations",
565
+ "Destructive actions",
566
+ "Critical warnings",
567
+ "Irreversible operations"
568
+ ],
569
+ dependencies: ["@radix-ui/react-alert-dialog"],
570
+ radixPrimitive: "@radix-ui/react-alert-dialog",
571
+ props: {
572
+ open: { type: "boolean", description: "Controlled open state" },
573
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
574
+ },
575
+ subComponents: ["AlertDialogTrigger", "AlertDialogContent", "AlertDialogHeader", "AlertDialogTitle", "AlertDialogDescription", "AlertDialogFooter", "AlertDialogAction", "AlertDialogCancel"],
576
+ example: `<AlertDialog>
577
+ <AlertDialogTrigger asChild><Button variant="destructive">Delete</Button></AlertDialogTrigger>
578
+ <AlertDialogContent>
579
+ <AlertDialogHeader>
580
+ <AlertDialogTitle>Are you sure?</AlertDialogTitle>
581
+ <AlertDialogDescription>This cannot be undone.</AlertDialogDescription>
582
+ </AlertDialogHeader>
583
+ <AlertDialogFooter>
584
+ <AlertDialogCancel>Cancel</AlertDialogCancel>
585
+ <AlertDialogAction>Delete</AlertDialogAction>
586
+ </AlertDialogFooter>
587
+ </AlertDialogContent>
588
+ </AlertDialog>`
589
+ },
590
+ "context-menu": {
591
+ name: "ContextMenu",
592
+ category: "overlays",
593
+ description: "Right-click context menu for contextual actions",
594
+ keywords: ["context-menu", "right-click", "menu", "actions", "contextual"],
595
+ useCases: [
596
+ "Right-click actions",
597
+ "Contextual operations",
598
+ "File operations",
599
+ "Item actions"
600
+ ],
601
+ dependencies: ["@radix-ui/react-context-menu"],
602
+ radixPrimitive: "@radix-ui/react-context-menu",
603
+ subComponents: ["ContextMenuTrigger", "ContextMenuContent", "ContextMenuItem", "ContextMenuCheckboxItem", "ContextMenuRadioItem", "ContextMenuLabel", "ContextMenuSeparator", "ContextMenuShortcut", "ContextMenuSub", "ContextMenuSubTrigger", "ContextMenuSubContent", "ContextMenuRadioGroup"],
604
+ example: `<ContextMenu>
605
+ <ContextMenuTrigger>Right click here</ContextMenuTrigger>
606
+ <ContextMenuContent>
607
+ <ContextMenuItem>Edit</ContextMenuItem>
608
+ <ContextMenuItem>Duplicate</ContextMenuItem>
609
+ <ContextMenuSeparator />
610
+ <ContextMenuItem>Delete</ContextMenuItem>
611
+ </ContextMenuContent>
612
+ </ContextMenu>`
613
+ },
614
+ dialog: {
615
+ name: "Dialog",
616
+ category: "overlays",
617
+ description: "Modal dialog for focused interactions and forms",
618
+ keywords: ["dialog", "modal", "popup", "overlay", "form"],
619
+ useCases: [
620
+ "Form modals",
621
+ "Detail views",
622
+ "Focused tasks",
623
+ "User input"
624
+ ],
625
+ dependencies: ["@radix-ui/react-dialog"],
626
+ radixPrimitive: "@radix-ui/react-dialog",
627
+ props: {
628
+ open: { type: "boolean", description: "Controlled open state" },
629
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
630
+ },
631
+ subComponents: ["DialogTrigger", "DialogContent", "DialogHeader", "DialogTitle", "DialogDescription", "DialogFooter", "DialogClose"],
632
+ example: `<Dialog>
633
+ <DialogTrigger asChild><Button>Open</Button></DialogTrigger>
634
+ <DialogContent>
635
+ <DialogHeader>
636
+ <DialogTitle>Title</DialogTitle>
637
+ <DialogDescription>Description here.</DialogDescription>
638
+ </DialogHeader>
639
+ <DialogFooter>
640
+ <Button variant="outline">Cancel</Button>
641
+ <Button>Confirm</Button>
642
+ </DialogFooter>
643
+ </DialogContent>
644
+ </Dialog>`
645
+ },
646
+ drawer: {
647
+ name: "Drawer",
648
+ category: "overlays",
649
+ description: "Mobile-friendly bottom drawer that slides up from screen bottom",
650
+ keywords: ["drawer", "bottom-sheet", "mobile", "slide-up", "panel"],
651
+ useCases: [
652
+ "Mobile actions",
653
+ "Mobile forms",
654
+ "Bottom sheets",
655
+ "Mobile menus"
656
+ ],
657
+ dependencies: ["vaul"],
658
+ props: {
659
+ open: { type: "boolean", description: "Controlled open state" },
660
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
661
+ },
662
+ subComponents: ["DrawerTrigger", "DrawerContent", "DrawerHeader", "DrawerTitle", "DrawerDescription", "DrawerFooter", "DrawerClose"],
663
+ example: `<Drawer>
664
+ <DrawerTrigger asChild><Button>Open Drawer</Button></DrawerTrigger>
665
+ <DrawerContent>
666
+ <DrawerHeader>
667
+ <DrawerTitle>Settings</DrawerTitle>
668
+ <DrawerDescription>Adjust preferences.</DrawerDescription>
669
+ </DrawerHeader>
670
+ <div className="p-4">Content here.</div>
671
+ <DrawerFooter>
672
+ <Button>Save</Button>
673
+ <DrawerClose asChild><Button variant="outline">Cancel</Button></DrawerClose>
674
+ </DrawerFooter>
675
+ </DrawerContent>
676
+ </Drawer>`
677
+ },
678
+ "dropdown-menu": {
679
+ name: "DropdownMenu",
680
+ category: "overlays",
681
+ description: "Dropdown menu for actions and navigation options",
682
+ keywords: ["dropdown", "menu", "actions", "options", "popover"],
683
+ useCases: [
684
+ "Action menus",
685
+ "User menus",
686
+ "Item options",
687
+ "Overflow menus"
688
+ ],
689
+ dependencies: ["@radix-ui/react-dropdown-menu"],
690
+ radixPrimitive: "@radix-ui/react-dropdown-menu",
691
+ props: {
692
+ open: { type: "boolean", description: "Controlled open state" },
693
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
694
+ },
695
+ subComponents: ["DropdownMenuTrigger", "DropdownMenuContent", "DropdownMenuItem", "DropdownMenuLabel", "DropdownMenuSeparator", "DropdownMenuCheckboxItem", "DropdownMenuRadioGroup", "DropdownMenuRadioItem", "DropdownMenuSub", "DropdownMenuSubTrigger", "DropdownMenuSubContent"],
696
+ example: `<DropdownMenu>
697
+ <DropdownMenuTrigger asChild><Button variant="ghost">Options</Button></DropdownMenuTrigger>
698
+ <DropdownMenuContent>
699
+ <DropdownMenuLabel>Actions</DropdownMenuLabel>
700
+ <DropdownMenuSeparator />
701
+ <DropdownMenuItem>Edit</DropdownMenuItem>
702
+ <DropdownMenuItem>Delete</DropdownMenuItem>
703
+ </DropdownMenuContent>
704
+ </DropdownMenu>`
705
+ },
706
+ "hover-card": {
707
+ name: "HoverCard",
708
+ category: "overlays",
709
+ description: "Rich preview card that appears on hover",
710
+ keywords: ["hover-card", "preview", "popover", "tooltip", "hover"],
711
+ useCases: [
712
+ "User previews",
713
+ "Link previews",
714
+ "Rich tooltips",
715
+ "Additional context"
716
+ ],
717
+ dependencies: ["@radix-ui/react-hover-card"],
718
+ radixPrimitive: "@radix-ui/react-hover-card",
719
+ props: {
720
+ openDelay: { type: "number", default: "700", description: "Delay in ms before opening" },
721
+ closeDelay: { type: "number", default: "300", description: "Delay in ms before closing" }
722
+ },
723
+ subComponents: ["HoverCardTrigger", "HoverCardContent"],
724
+ example: `<HoverCard>
725
+ <HoverCardTrigger asChild><Link href="#">@username</Link></HoverCardTrigger>
726
+ <HoverCardContent className="w-80">
727
+ <div className="flex gap-4">
728
+ <Avatar />
729
+ <div><p className="text-sm font-semibold">Username</p><p className="text-sm text-muted-foreground">Bio here.</p></div>
730
+ </div>
731
+ </HoverCardContent>
732
+ </HoverCard>`
733
+ },
734
+ popover: {
735
+ name: "Popover",
736
+ category: "overlays",
737
+ description: "Floating content panel anchored to a trigger element",
738
+ keywords: ["popover", "floating", "tooltip", "overlay", "panel"],
739
+ useCases: [
740
+ "Additional info",
741
+ "Form helpers",
742
+ "Contextual content",
743
+ "Inline editors"
744
+ ],
745
+ dependencies: ["@radix-ui/react-popover"],
746
+ radixPrimitive: "@radix-ui/react-popover",
747
+ props: {
748
+ open: { type: "boolean", description: "Controlled open state" },
749
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
750
+ },
751
+ subComponents: ["PopoverTrigger", "PopoverContent", "PopoverAnchor"],
752
+ example: `<Popover>
753
+ <PopoverTrigger asChild><Button variant="outline">Open</Button></PopoverTrigger>
754
+ <PopoverContent className="w-80">Content here.</PopoverContent>
755
+ </Popover>`
756
+ },
757
+ sheet: {
758
+ name: "Sheet",
759
+ category: "overlays",
760
+ description: "Slide-in panel from screen edges for supplementary content",
761
+ keywords: ["sheet", "sidebar", "slide-in", "panel", "drawer"],
762
+ useCases: [
763
+ "Mobile navigation",
764
+ "Sidebar panels",
765
+ "Settings panels",
766
+ "Detail views"
767
+ ],
768
+ dependencies: ["@radix-ui/react-dialog"],
769
+ radixPrimitive: "@radix-ui/react-dialog",
770
+ props: {
771
+ open: { type: "boolean", description: "Controlled open state" },
772
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
773
+ },
774
+ subComponents: ["SheetTrigger", "SheetContent", "SheetHeader", "SheetTitle", "SheetDescription", "SheetClose"],
775
+ example: `<Sheet>
776
+ <SheetTrigger asChild><Button>Open</Button></SheetTrigger>
777
+ <SheetContent side="right">
778
+ <SheetHeader><SheetTitle>Settings</SheetTitle></SheetHeader>
779
+ <div className="p-4">Content here.</div>
780
+ </SheetContent>
781
+ </Sheet>`
782
+ },
783
+ tooltip: {
784
+ name: "Tooltip",
785
+ category: "overlays",
786
+ description: "Contextual hints and additional information on hover",
787
+ keywords: ["tooltip", "hint", "help", "hover", "info"],
788
+ useCases: [
789
+ "Icon explanations",
790
+ "Additional context",
791
+ "Help text",
792
+ "Keyboard shortcuts"
793
+ ],
794
+ dependencies: ["@radix-ui/react-tooltip"],
795
+ radixPrimitive: "@radix-ui/react-tooltip",
796
+ subComponents: ["TooltipTrigger", "TooltipContent", "TooltipProvider"],
797
+ example: `<Tooltip>
798
+ <TooltipTrigger asChild><Button variant="ghost" size="icon"><Info /></Button></TooltipTrigger>
799
+ <TooltipContent><p>Helpful information</p></TooltipContent>
800
+ </Tooltip>`
801
+ },
802
+ // ============================================================================
803
+ // FEEDBACK (5)
804
+ // ============================================================================
805
+ alert: {
806
+ name: "Alert",
807
+ category: "feedback",
808
+ description: "Prominent message component for important information",
809
+ keywords: ["alert", "message", "notification", "warning", "info", "error", "success"],
810
+ useCases: [
811
+ "Status messages",
812
+ "Warnings",
813
+ "Errors",
814
+ "Success confirmations"
815
+ ],
816
+ dependencies: [],
817
+ props: {
818
+ variant: { type: "'default' | 'destructive'", default: "'default'", description: "Visual variant" }
819
+ },
820
+ subComponents: ["AlertTitle", "AlertDescription"],
821
+ example: `<Alert variant="destructive">
822
+ <AlertTitle>Error</AlertTitle>
823
+ <AlertDescription>Your session has expired.</AlertDescription>
824
+ </Alert>`
825
+ },
826
+ progress: {
827
+ name: "Progress",
828
+ category: "feedback",
829
+ description: "Visual indicator for progress and completion status",
830
+ keywords: ["progress", "loading", "bar", "percentage", "completion"],
831
+ useCases: [
832
+ "Upload progress",
833
+ "Task completion",
834
+ "Loading states",
835
+ "Multi-step forms"
836
+ ],
837
+ dependencies: ["@radix-ui/react-progress"],
838
+ radixPrimitive: "@radix-ui/react-progress",
839
+ props: {
840
+ value: { type: "number", default: "0", description: "Progress value (0-100)" },
841
+ max: { type: "number", default: "100", description: "Maximum value" }
842
+ },
843
+ example: `<Progress value={60} />`
844
+ },
845
+ skeleton: {
846
+ name: "Skeleton",
847
+ category: "feedback",
848
+ description: "Loading placeholder that mimics content structure",
849
+ keywords: ["skeleton", "loading", "placeholder", "shimmer", "spinner"],
850
+ useCases: [
851
+ "Content loading",
852
+ "Data fetching",
853
+ "Initial load",
854
+ "Lazy loading"
855
+ ],
856
+ dependencies: [],
857
+ props: {
858
+ variant: { type: "'default' | 'circular' | 'rectangular' | 'text'", default: "'default'", description: "Shape variant" },
859
+ width: { type: "string", default: "'100%'", description: "Width (CSS value)" },
860
+ height: { type: "string", default: "'20px'", description: "Height (CSS value)" }
861
+ },
862
+ example: `<div className="space-y-2">
863
+ <Skeleton className="h-12 w-12 rounded-full" />
864
+ <Skeleton className="h-4 w-[250px]" />
865
+ <Skeleton className="h-4 w-[200px]" />
866
+ </div>`
867
+ },
868
+ sonner: {
869
+ name: "Sonner",
870
+ category: "feedback",
871
+ description: "Toast notification system with queuing and positioning. Use Toaster component in layout, call toast() to trigger.",
872
+ keywords: ["toast", "notification", "sonner", "message", "alert"],
873
+ useCases: [
874
+ "Success messages",
875
+ "Error notifications",
876
+ "Action feedback",
877
+ "System messages"
878
+ ],
879
+ dependencies: ["sonner"],
880
+ subComponents: ["Toaster"],
881
+ example: `// In layout: <Toaster />
882
+ // To trigger:
883
+ import { toast } from 'sonner'
884
+ toast.success('Saved successfully')
885
+ toast.error('Something went wrong')
886
+ toast('Default notification')`
887
+ },
888
+ toast: {
889
+ name: "Toast",
890
+ category: "feedback",
891
+ description: "Temporary notification messages that appear briefly",
892
+ keywords: ["toast", "notification", "message", "snackbar", "alert"],
893
+ useCases: [
894
+ "Quick feedback",
895
+ "Status updates",
896
+ "Non-critical notifications",
897
+ "Confirmation messages"
898
+ ],
899
+ dependencies: ["@radix-ui/react-toast"],
900
+ radixPrimitive: "@radix-ui/react-toast",
901
+ subComponents: ["ToastAction", "ToastClose", "ToastDescription", "ToastProvider", "ToastTitle", "ToastViewport"],
902
+ example: `// Prefer using Sonner (Toaster + toast()) for new projects.
903
+ // This is the Radix-based alternative.
904
+ import { useToast } from '@thesage/ui'
905
+ const { toast } = useToast()
906
+ toast({ title: 'Success', description: 'Item saved.' })`
907
+ },
908
+ // ============================================================================
909
+ // DATA DISPLAY (6)
910
+ // ============================================================================
911
+ avatar: {
912
+ name: "Avatar",
913
+ category: "data-display",
914
+ description: "User profile image with fallback initials",
915
+ keywords: ["avatar", "profile", "image", "user", "picture"],
916
+ useCases: [
917
+ "User profiles",
918
+ "Comment authors",
919
+ "Team members",
920
+ "Chat participants"
921
+ ],
922
+ dependencies: ["@radix-ui/react-avatar"],
923
+ radixPrimitive: "@radix-ui/react-avatar",
924
+ subComponents: ["AvatarImage", "AvatarFallback"],
925
+ example: `<Avatar>
926
+ <AvatarImage src="/avatar.jpg" alt="User" />
927
+ <AvatarFallback>JD</AvatarFallback>
928
+ </Avatar>`
929
+ },
930
+ badge: {
931
+ name: "Badge",
932
+ category: "data-display",
933
+ description: "Status indicators and labels for categorization",
934
+ keywords: ["badge", "tag", "label", "status", "chip", "pill"],
935
+ useCases: [
936
+ "Status indicators",
937
+ "Tags",
938
+ "Categories",
939
+ "Notification counts"
940
+ ],
941
+ dependencies: [],
942
+ props: {
943
+ variant: { type: "'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning' | 'error' | 'info'", default: "'default'", description: "Visual variant" },
944
+ size: { type: "'sm' | 'md' | 'lg'", default: "'md'", description: "Size variant" },
945
+ dot: { type: "boolean", default: "false", description: "Show animated indicator dot" }
946
+ },
947
+ example: `<Badge variant="success" dot>Active</Badge>`
948
+ },
949
+ calendar: {
950
+ name: "Calendar",
951
+ category: "data-display",
952
+ description: "Date selection calendar with month/year navigation",
953
+ keywords: ["calendar", "date", "picker", "month", "day"],
954
+ useCases: [
955
+ "Date selection",
956
+ "Event scheduling",
957
+ "Booking systems",
958
+ "Date ranges"
959
+ ],
960
+ dependencies: ["react-day-picker", "date-fns"],
961
+ props: {
962
+ mode: { type: "'single' | 'multiple' | 'range'", default: "'single'", description: "Selection mode" },
963
+ selected: { type: "Date | Date[] | DateRange", description: "Selected date(s)" },
964
+ onSelect: { type: "(date) => void", description: "Callback on date selection" },
965
+ showOutsideDays: { type: "boolean", default: "true", description: "Show days from adjacent months" },
966
+ disabled: { type: "Matcher | Matcher[]", description: "Dates to disable" }
967
+ },
968
+ example: `<Calendar mode="single" selected={date} onSelect={setDate} />`
969
+ },
970
+ card: {
971
+ name: "Card",
972
+ category: "data-display",
973
+ description: "Container for grouping related content with optional header and footer",
974
+ keywords: ["card", "container", "box", "panel", "content"],
975
+ useCases: [
976
+ "Content grouping",
977
+ "Product cards",
978
+ "Information panels",
979
+ "Dashboard widgets"
980
+ ],
981
+ dependencies: [],
982
+ props: {
983
+ variant: { type: "'default' | 'glass' | 'outline'", default: "'default'", description: "Visual variant" },
984
+ hoverEffect: { type: "boolean", default: "false", description: "Enable hover lift and shadow" }
985
+ },
986
+ subComponents: ["CardHeader", "CardTitle", "CardDescription", "CardContent", "CardFooter"],
987
+ example: `<Card>
988
+ <CardHeader>
989
+ <CardTitle>Notifications</CardTitle>
990
+ <CardDescription>You have 3 unread messages.</CardDescription>
991
+ </CardHeader>
992
+ <CardContent><p>Content here.</p></CardContent>
993
+ <CardFooter><Button>View All</Button></CardFooter>
994
+ </Card>`
995
+ },
996
+ "data-table": {
997
+ name: "DataTable",
998
+ category: "data-display",
999
+ description: "Enhanced table with sorting, filtering, and pagination",
1000
+ keywords: ["table", "data", "grid", "sorting", "filtering", "pagination", "tanstack"],
1001
+ useCases: [
1002
+ "Data grids",
1003
+ "Admin tables",
1004
+ "Reports",
1005
+ "List management"
1006
+ ],
1007
+ dependencies: ["@tanstack/react-table"],
1008
+ props: {
1009
+ columns: { type: "ColumnDef<TData, TValue>[]", description: "Column definitions from @tanstack/react-table", required: true },
1010
+ data: { type: "TData[]", description: "Array of row data", required: true }
1011
+ },
1012
+ example: `import { DataTable } from '@thesage/ui/tables'
1013
+ const columns = [
1014
+ { accessorKey: 'name', header: 'Name' },
1015
+ { accessorKey: 'email', header: 'Email' },
1016
+ ]
1017
+ <DataTable columns={columns} data={users} />`
1018
+ },
1019
+ table: {
1020
+ name: "Table",
1021
+ category: "data-display",
1022
+ description: "Basic table component for tabular data display",
1023
+ keywords: ["table", "data", "rows", "columns", "grid"],
1024
+ useCases: [
1025
+ "Simple tables",
1026
+ "Data display",
1027
+ "Comparison tables",
1028
+ "Pricing tables"
1029
+ ],
1030
+ dependencies: [],
1031
+ subComponents: ["TableHeader", "TableBody", "TableFooter", "TableRow", "TableHead", "TableCell", "TableCaption"],
1032
+ example: `<Table>
1033
+ <TableHeader>
1034
+ <TableRow>
1035
+ <TableHead>Name</TableHead>
1036
+ <TableHead>Status</TableHead>
1037
+ </TableRow>
1038
+ </TableHeader>
1039
+ <TableBody>
1040
+ <TableRow>
1041
+ <TableCell>John</TableCell>
1042
+ <TableCell>Active</TableCell>
1043
+ </TableRow>
1044
+ </TableBody>
1045
+ </Table>`
1046
+ },
1047
+ heading: {
1048
+ name: "Heading",
1049
+ category: "data-display",
1050
+ description: "Semantic heading with automatic token-based styling and responsive sizes",
1051
+ keywords: ["heading", "title", "h1", "h2", "h3", "h4", "h5", "h6", "typography"],
1052
+ useCases: [
1053
+ "Page titles",
1054
+ "Section headings",
1055
+ "Content hierarchy",
1056
+ "Semantic HTML structure"
1057
+ ],
1058
+ dependencies: [],
1059
+ props: {
1060
+ level: { type: "1 | 2 | 3 | 4 | 5 | 6", default: "2", description: "Heading level (renders h1-h6)" },
1061
+ as: { type: "'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'", description: "Override rendered HTML element" }
1062
+ },
1063
+ example: `<Heading level={1}>Page Title</Heading>
1064
+ <Heading level={2}>Section Title</Heading>`
1065
+ },
1066
+ text: {
1067
+ name: "Text",
1068
+ category: "data-display",
1069
+ description: "Semantic text component with variants for primary, secondary, and muted styles",
1070
+ keywords: ["text", "paragraph", "body", "typography", "content", "p", "span"],
1071
+ useCases: [
1072
+ "Body text",
1073
+ "Descriptions",
1074
+ "Helper text",
1075
+ "Labels and captions"
1076
+ ],
1077
+ dependencies: [],
1078
+ props: {
1079
+ variant: { type: "'default' | 'secondary' | 'muted' | 'lead'", default: "'default'", description: "Text style variant" },
1080
+ as: { type: "'p' | 'span' | 'div'", default: "'p'", description: "HTML element to render" },
1081
+ size: { type: "'sm' | 'base' | 'lg'", default: "'base'", description: "Font size" }
1082
+ },
1083
+ example: `<Text variant="lead">Important introductory text.</Text>
1084
+ <Text variant="muted" size="sm">Helper text below an input.</Text>`
1085
+ },
1086
+ code: {
1087
+ name: "Code",
1088
+ category: "data-display",
1089
+ description: "Code display with syntax highlighting for inline and block code",
1090
+ keywords: ["code", "syntax", "highlighting", "programming", "snippet", "pre"],
1091
+ useCases: [
1092
+ "Code snippets",
1093
+ "API documentation",
1094
+ "Technical content",
1095
+ "Inline code references"
1096
+ ],
1097
+ dependencies: [],
1098
+ props: {
1099
+ inline: { type: "boolean", default: "false", description: "Render as inline code (true) or block (false)" },
1100
+ showCopy: { type: "boolean", default: "true", description: "Show copy button for block code" }
1101
+ },
1102
+ example: `// Inline
1103
+ <Code inline>npm install @thesage/ui</Code>
1104
+
1105
+ // Block
1106
+ <Code>{\`const x = 1;
1107
+ const y = 2;\`}</Code>`
1108
+ },
1109
+ "collapsible-code-block": {
1110
+ name: "CollapsibleCodeBlock",
1111
+ category: "data-display",
1112
+ description: "Expandable code block with syntax highlighting, preview mode, and copy functionality",
1113
+ keywords: ["code", "collapsible", "expandable", "syntax", "copy", "preview"],
1114
+ useCases: [
1115
+ "Long code examples",
1116
+ "Documentation code blocks",
1117
+ "Tutorial code snippets",
1118
+ "API examples"
1119
+ ],
1120
+ dependencies: ["@thesage/tokens"],
1121
+ props: {
1122
+ code: { type: "string", description: "Source code string", required: true },
1123
+ language: { type: "'tsx' | 'typescript' | 'javascript' | 'jsx' | 'css' | 'html' | 'json' | 'bash'", default: "'tsx'", description: "Language for syntax highlighting" },
1124
+ title: { type: "string", description: "Optional title above the code block" },
1125
+ maxLines: { type: "number", default: "10", description: "Lines to show before collapsing" },
1126
+ defaultExpanded: { type: "boolean", default: "false", description: "Start in expanded state" }
1127
+ },
1128
+ example: `<CollapsibleCodeBlock
1129
+ code="const Button = () => <button>Click</button>"
1130
+ language="tsx"
1131
+ title="Button.tsx"
1132
+ maxLines={5}
1133
+ />`
1134
+ },
1135
+ "description-list": {
1136
+ name: "DescriptionList",
1137
+ category: "data-display",
1138
+ description: "Key-value pair list for displaying labeled data in row or column layout",
1139
+ keywords: ["description", "list", "key-value", "definition", "dl", "dt", "dd"],
1140
+ useCases: [
1141
+ "Product specifications",
1142
+ "User profile details",
1143
+ "Metadata display",
1144
+ "Settings summaries"
1145
+ ],
1146
+ dependencies: [],
1147
+ props: {
1148
+ items: { type: "{ label: string; value: ReactNode }[]", description: "Array of label-value pairs", required: true },
1149
+ layout: { type: "'row' | 'column'", default: "'row'", description: "Layout direction for label/value pairs" }
1150
+ },
1151
+ example: `<DescriptionList items={[
1152
+ { label: 'Name', value: 'John Doe' },
1153
+ { label: 'Email', value: 'john@example.com' },
1154
+ { label: 'Role', value: <Badge>Admin</Badge> },
1155
+ ]} />`
1156
+ },
1157
+ // ============================================================================
1158
+ // LAYOUT (8)
1159
+ // ============================================================================
1160
+ accordion: {
1161
+ name: "Accordion",
1162
+ category: "layout",
1163
+ description: "Collapsible content sections with expand/collapse functionality",
1164
+ keywords: ["accordion", "collapsible", "expandable", "faq", "sections"],
1165
+ useCases: [
1166
+ "FAQ sections",
1167
+ "Content organization",
1168
+ "Settings panels",
1169
+ "Information disclosure"
1170
+ ],
1171
+ dependencies: ["@radix-ui/react-accordion"],
1172
+ radixPrimitive: "@radix-ui/react-accordion",
1173
+ props: {
1174
+ type: { type: "'single' | 'multiple'", description: "Allow single or multiple open items", required: true },
1175
+ collapsible: { type: "boolean", default: "false", description: 'Allow closing all items (type="single" only)' }
1176
+ },
1177
+ subComponents: ["AccordionItem", "AccordionTrigger", "AccordionContent"],
1178
+ example: `<Accordion type="single" collapsible>
1179
+ <AccordionItem value="item-1">
1180
+ <AccordionTrigger>Is it accessible?</AccordionTrigger>
1181
+ <AccordionContent>Yes. It follows WAI-ARIA patterns.</AccordionContent>
1182
+ </AccordionItem>
1183
+ </Accordion>`
1184
+ },
1185
+ "aspect-ratio": {
1186
+ name: "AspectRatio",
1187
+ category: "layout",
1188
+ description: "Container that maintains specific width-to-height ratio",
1189
+ keywords: ["aspect-ratio", "ratio", "responsive", "media", "image"],
1190
+ useCases: [
1191
+ "Responsive images",
1192
+ "Video embeds",
1193
+ "Media containers",
1194
+ "Card images"
1195
+ ],
1196
+ dependencies: ["@radix-ui/react-aspect-ratio"],
1197
+ radixPrimitive: "@radix-ui/react-aspect-ratio",
1198
+ props: {
1199
+ ratio: { type: "number", default: "1", description: "Aspect ratio as a number (e.g. 16/9)" }
1200
+ },
1201
+ example: `<AspectRatio ratio={16 / 9}>
1202
+ <img src="/image.jpg" alt="Photo" className="rounded-md object-cover w-full h-full" />
1203
+ </AspectRatio>`
1204
+ },
1205
+ carousel: {
1206
+ name: "Carousel",
1207
+ category: "layout",
1208
+ description: "Scrollable content slider with navigation controls",
1209
+ keywords: ["carousel", "slider", "slideshow", "gallery", "swipe"],
1210
+ useCases: [
1211
+ "Image galleries",
1212
+ "Product showcases",
1213
+ "Content sliders",
1214
+ "Testimonials"
1215
+ ],
1216
+ dependencies: ["embla-carousel-react"],
1217
+ props: {
1218
+ orientation: { type: "'horizontal' | 'vertical'", default: "'horizontal'", description: "Scroll direction" },
1219
+ opts: { type: "CarouselOptions", description: "Embla Carousel options (loop, align, etc.)" },
1220
+ plugins: { type: "CarouselPlugin", description: "Embla Carousel plugins (autoplay, etc.)" },
1221
+ setApi: { type: "(api: CarouselApi) => void", description: "Callback to get carousel API ref" }
1222
+ },
1223
+ subComponents: ["CarouselContent", "CarouselItem", "CarouselPrevious", "CarouselNext"],
1224
+ example: `<Carousel>
1225
+ <CarouselContent>
1226
+ <CarouselItem>Slide 1</CarouselItem>
1227
+ <CarouselItem>Slide 2</CarouselItem>
1228
+ <CarouselItem>Slide 3</CarouselItem>
1229
+ </CarouselContent>
1230
+ <CarouselPrevious />
1231
+ <CarouselNext />
1232
+ </Carousel>`
1233
+ },
1234
+ collapsible: {
1235
+ name: "Collapsible",
1236
+ category: "layout",
1237
+ description: "Simple show/hide content container",
1238
+ keywords: ["collapsible", "expandable", "toggle", "show-hide", "disclosure"],
1239
+ useCases: [
1240
+ "Sidebar sections",
1241
+ "Content reveals",
1242
+ "Advanced options",
1243
+ "Details disclosure"
1244
+ ],
1245
+ dependencies: ["@radix-ui/react-collapsible"],
1246
+ radixPrimitive: "@radix-ui/react-collapsible",
1247
+ props: {
1248
+ open: { type: "boolean", description: "Controlled open state" },
1249
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" },
1250
+ defaultOpen: { type: "boolean", default: "false", description: "Default open state" }
1251
+ },
1252
+ subComponents: ["CollapsibleTrigger", "CollapsibleContent"],
1253
+ example: `<Collapsible>
1254
+ <CollapsibleTrigger asChild><Button variant="ghost">Toggle</Button></CollapsibleTrigger>
1255
+ <CollapsibleContent>
1256
+ <p>Hidden content revealed on click.</p>
1257
+ </CollapsibleContent>
1258
+ </Collapsible>`
1259
+ },
1260
+ "date-picker": {
1261
+ name: "DatePicker",
1262
+ category: "layout",
1263
+ description: "Calendar date picker combined with popover trigger",
1264
+ keywords: ["date-picker", "calendar", "date", "popover", "input"],
1265
+ useCases: [
1266
+ "Date selection",
1267
+ "Form dates",
1268
+ "Scheduling",
1269
+ "Filters"
1270
+ ],
1271
+ dependencies: ["react-day-picker", "date-fns", "@radix-ui/react-popover"],
1272
+ props: {
1273
+ date: { type: "Date", description: "Selected date" },
1274
+ onDateChange: { type: "(date: Date | undefined) => void", description: "Callback on date change" },
1275
+ placeholder: { type: "string", default: "'Pick a date'", description: "Placeholder text" },
1276
+ disabled: { type: "boolean", default: "false", description: "Disable the date picker" }
1277
+ },
1278
+ example: `<DatePicker date={date} onDateChange={setDate} placeholder="Select date" />`
1279
+ },
1280
+ resizable: {
1281
+ name: "Resizable",
1282
+ category: "layout",
1283
+ description: "User-resizable panel containers with drag handles",
1284
+ keywords: ["resizable", "panels", "split", "drag", "resize"],
1285
+ useCases: [
1286
+ "Split views",
1287
+ "IDE panels",
1288
+ "Dashboard layouts",
1289
+ "Adjustable sidebars"
1290
+ ],
1291
+ dependencies: ["react-resizable-panels"],
1292
+ props: {
1293
+ direction: { type: "'horizontal' | 'vertical'", default: "'horizontal'", description: "Panel layout direction" }
1294
+ },
1295
+ subComponents: ["ResizablePanelGroup", "ResizablePanel", "ResizableHandle"],
1296
+ example: `<ResizablePanelGroup direction="horizontal">
1297
+ <ResizablePanel defaultSize={50}>Left panel</ResizablePanel>
1298
+ <ResizableHandle />
1299
+ <ResizablePanel defaultSize={50}>Right panel</ResizablePanel>
1300
+ </ResizablePanelGroup>`
1301
+ },
1302
+ "scroll-area": {
1303
+ name: "ScrollArea",
1304
+ category: "layout",
1305
+ description: "Custom scrollbar styling for overflow content",
1306
+ keywords: ["scroll", "scrollbar", "overflow", "custom-scroll"],
1307
+ useCases: [
1308
+ "Content overflow",
1309
+ "Scrollable lists",
1310
+ "Chat windows",
1311
+ "Code displays"
1312
+ ],
1313
+ dependencies: ["@radix-ui/react-scroll-area"],
1314
+ radixPrimitive: "@radix-ui/react-scroll-area",
1315
+ subComponents: ["ScrollBar"],
1316
+ example: `<ScrollArea className="h-[200px] w-full rounded-md border p-4">
1317
+ <div>Long scrollable content here...</div>
1318
+ </ScrollArea>`
1319
+ },
1320
+ separator: {
1321
+ name: "Separator",
1322
+ category: "layout",
1323
+ description: "Visual divider for separating content sections",
1324
+ keywords: ["separator", "divider", "line", "hr", "border"],
1325
+ useCases: [
1326
+ "Content separation",
1327
+ "Menu dividers",
1328
+ "Section breaks",
1329
+ "Visual hierarchy"
1330
+ ],
1331
+ dependencies: ["@radix-ui/react-separator"],
1332
+ radixPrimitive: "@radix-ui/react-separator",
1333
+ props: {
1334
+ orientation: { type: "'horizontal' | 'vertical'", default: "'horizontal'", description: "Orientation" }
1335
+ },
1336
+ example: `<Separator orientation="horizontal" />`
1337
+ },
1338
+ grid: {
1339
+ name: "Grid",
1340
+ category: "layout",
1341
+ description: "Responsive CSS grid with column and gap configuration",
1342
+ keywords: ["grid", "layout", "columns", "responsive", "css-grid"],
1343
+ useCases: [
1344
+ "Card grids",
1345
+ "Gallery layouts",
1346
+ "Dashboard layouts",
1347
+ "Responsive content grids"
1348
+ ],
1349
+ dependencies: [],
1350
+ props: {
1351
+ columns: { type: "number | { sm?: number; md?: number; lg?: number }", default: "3", description: "Number of grid columns (responsive object supported)" },
1352
+ gap: { type: "number | string", default: "4", description: "Gap between grid items (Tailwind spacing scale)" }
1353
+ },
1354
+ example: `<Grid columns={{ sm: 1, md: 2, lg: 3 }} gap={4}>
1355
+ <Card>Item 1</Card>
1356
+ <Card>Item 2</Card>
1357
+ <Card>Item 3</Card>
1358
+ </Grid>`
1359
+ },
1360
+ container: {
1361
+ name: "Container",
1362
+ category: "layout",
1363
+ description: "Content wrapper with consistent max-width and padding variants",
1364
+ keywords: ["container", "wrapper", "max-width", "centered", "layout"],
1365
+ useCases: [
1366
+ "Page content wrapper",
1367
+ "Centered layouts",
1368
+ "Responsive widths",
1369
+ "Content alignment"
1370
+ ],
1371
+ dependencies: [],
1372
+ props: {
1373
+ size: { type: "'sm' | 'md' | 'lg' | 'xl' | 'full'", default: "'lg'", description: "Max-width variant" },
1374
+ padding: { type: "boolean", default: "true", description: "Apply horizontal padding" }
1375
+ },
1376
+ example: `<Container size="lg">
1377
+ <Heading level={1}>Page Title</Heading>
1378
+ <Text>Content within max-width container.</Text>
1379
+ </Container>`
1380
+ },
1381
+ stack: {
1382
+ name: "Stack",
1383
+ category: "layout",
1384
+ description: "Flexbox layout for vertical or horizontal stacking with gap control",
1385
+ keywords: ["stack", "flex", "vertical", "horizontal", "spacing", "layout"],
1386
+ useCases: [
1387
+ "Vertical layouts",
1388
+ "Horizontal layouts",
1389
+ "Form layouts",
1390
+ "Button groups"
1391
+ ],
1392
+ dependencies: [],
1393
+ props: {
1394
+ direction: { type: "'vertical' | 'horizontal'", default: "'vertical'", description: "Stack direction" },
1395
+ gap: { type: "number | string", default: "4", description: "Gap between items (Tailwind spacing scale)" },
1396
+ align: { type: "'start' | 'center' | 'end' | 'stretch'", default: "'stretch'", description: "Cross-axis alignment" },
1397
+ justify: { type: "'start' | 'center' | 'end' | 'between'", description: "Main-axis alignment" }
1398
+ },
1399
+ example: `<Stack direction="horizontal" gap={2} align="center">
1400
+ <Button>Save</Button>
1401
+ <Button variant="outline">Cancel</Button>
1402
+ </Stack>`
1403
+ },
1404
+ sidebar: {
1405
+ name: "Sidebar",
1406
+ category: "layout",
1407
+ description: "Navigation sidebar with header, content, footer sections and mobile overlay",
1408
+ keywords: ["sidebar", "navigation", "panel", "drawer", "menu"],
1409
+ useCases: [
1410
+ "App navigation",
1411
+ "Dashboard sidebars",
1412
+ "Settings panels",
1413
+ "Mobile menus"
1414
+ ],
1415
+ dependencies: ["@radix-ui/react-slot"],
1416
+ radixPrimitive: "@radix-ui/react-slot",
1417
+ props: {
1418
+ isOpen: { type: "boolean", default: "true", description: "Whether sidebar is visible/expanded" }
1419
+ },
1420
+ subComponents: ["SidebarHeader", "SidebarContent", "SidebarFooter", "SidebarItem"],
1421
+ example: `<Sidebar>
1422
+ <SidebarHeader><h2>My App</h2></SidebarHeader>
1423
+ <SidebarContent>
1424
+ <SidebarItem icon={<Home />} isActive>Dashboard</SidebarItem>
1425
+ <SidebarItem icon={<Settings />}>Settings</SidebarItem>
1426
+ </SidebarContent>
1427
+ <SidebarFooter>
1428
+ <SidebarItem icon={<LogOut />}>Logout</SidebarItem>
1429
+ </SidebarFooter>
1430
+ </Sidebar>`
1431
+ },
1432
+ header: {
1433
+ name: "Header",
1434
+ category: "layout",
1435
+ description: "Page header with sticky positioning, glass morphism, and mobile menu",
1436
+ keywords: ["header", "navbar", "navigation", "sticky", "mobile-menu"],
1437
+ useCases: [
1438
+ "Site headers",
1439
+ "App navigation bars",
1440
+ "Sticky headers",
1441
+ "Mobile-friendly navigation"
1442
+ ],
1443
+ dependencies: ["lucide-react"],
1444
+ props: {
1445
+ logo: { type: "ReactNode", description: "Logo element for header" },
1446
+ links: { type: "{ label: string; href: string }[]", description: "Navigation links" },
1447
+ sticky: { type: "boolean", default: "true", description: "Stick to top on scroll" },
1448
+ transparent: { type: "boolean", default: "false", description: "Transparent background (for hero sections)" }
1449
+ },
1450
+ example: `<Header
1451
+ logo={<Brand />}
1452
+ links={[
1453
+ { label: 'Home', href: '/' },
1454
+ { label: 'About', href: '/about' },
1455
+ ]}
1456
+ />`
1457
+ },
1458
+ footer: {
1459
+ name: "Footer",
1460
+ category: "layout",
1461
+ description: "Page footer with multi-column layout, social links, and copyright",
1462
+ keywords: ["footer", "navigation", "links", "copyright", "social"],
1463
+ useCases: [
1464
+ "Site footers",
1465
+ "Navigation sections",
1466
+ "Contact information",
1467
+ "Copyright notices"
1468
+ ],
1469
+ dependencies: [],
1470
+ props: {
1471
+ columns: { type: "{ title: string; links: { label: string; href: string }[] }[]", description: "Footer navigation columns" },
1472
+ copyright: { type: "string", description: "Copyright text" },
1473
+ socialLinks: { type: "{ icon: ReactNode; href: string }[]", description: "Social media links" }
1474
+ },
1475
+ example: `<Footer
1476
+ columns={[{ title: 'Product', links: [{ label: 'Docs', href: '/docs' }] }]}
1477
+ copyright="\xA9 2026 My Company"
1478
+ />`
1479
+ },
1480
+ "customizer-panel": {
1481
+ name: "CustomizerPanel",
1482
+ category: "layout",
1483
+ description: "Floating panel for theme, mode, and motion customization. Reads from ThemeProvider context.",
1484
+ keywords: ["customizer", "theme", "settings", "preferences", "dark-mode"],
1485
+ useCases: [
1486
+ "Theme selection",
1487
+ "Dark mode toggle",
1488
+ "Motion preferences",
1489
+ "User experience customization"
1490
+ ],
1491
+ dependencies: ["lucide-react", "@thesage/tokens"],
1492
+ example: `// Place in your layout. It reads theme state from ThemeProvider.
1493
+ <CustomizerPanel />`
1494
+ },
1495
+ "page-layout": {
1496
+ name: "PageLayout",
1497
+ category: "layout",
1498
+ description: "Flexible page layout with header, nav stacks, breadcrumbs, and footer",
1499
+ keywords: ["layout", "page", "template", "structure", "swiss-grid"],
1500
+ useCases: [
1501
+ "Page structure",
1502
+ "Content layouts",
1503
+ "Documentation pages",
1504
+ "Dashboard layouts"
1505
+ ],
1506
+ dependencies: [],
1507
+ props: {
1508
+ header: { type: "ReactNode", description: "Header element" },
1509
+ footer: { type: "ReactNode", description: "Footer element" },
1510
+ sidebar: { type: "ReactNode", description: "Optional sidebar" },
1511
+ breadcrumbs: { type: "ReactNode", description: "Breadcrumb navigation" }
1512
+ },
1513
+ example: `<PageLayout
1514
+ header={<Header />}
1515
+ footer={<Footer />}
1516
+ >
1517
+ <main>Page content</main>
1518
+ </PageLayout>`
1519
+ },
1520
+ "page-template": {
1521
+ name: "PageTemplate",
1522
+ category: "layout",
1523
+ description: "Opinionated page template with Swiss Grid design and customizer",
1524
+ keywords: ["template", "page", "swiss-grid", "layout", "documentation"],
1525
+ useCases: [
1526
+ "Blog pages",
1527
+ "Documentation pages",
1528
+ "Standard app pages",
1529
+ "Content-focused layouts"
1530
+ ],
1531
+ dependencies: [],
1532
+ props: {
1533
+ title: { type: "string", description: "Page title" },
1534
+ description: { type: "string", description: "Page description" },
1535
+ showCustomizer: { type: "boolean", default: "true", description: "Show customizer panel" }
1536
+ },
1537
+ example: `<PageTemplate title="Documentation" description="Learn the design system.">
1538
+ <div>Content here.</div>
1539
+ </PageTemplate>`
1540
+ },
1541
+ // ============================================================================
1542
+ // ACTIONS - Additional (2 more)
1543
+ // ============================================================================
1544
+ link: {
1545
+ name: "Link",
1546
+ category: "actions",
1547
+ description: "Styled anchor element with theme-aware colors and hover states",
1548
+ keywords: ["link", "anchor", "href", "navigation", "a", "url"],
1549
+ useCases: [
1550
+ "Text links",
1551
+ "Navigation links",
1552
+ "External references",
1553
+ "Inline actions"
1554
+ ],
1555
+ dependencies: [],
1556
+ props: {
1557
+ href: { type: "string", description: "Link URL", required: true },
1558
+ variant: { type: "'default' | 'inline'", default: "'default'", description: "Default for standalone links, inline for text links" },
1559
+ hoverEffect: { type: "boolean", default: "true", description: "Enable hover effect" }
1560
+ },
1561
+ example: `<Link href="/about" variant="inline">Learn More</Link>`
1562
+ },
1563
+ magnetic: {
1564
+ name: "Magnetic",
1565
+ category: "actions",
1566
+ description: "Magnetic hover effect that attracts elements toward cursor",
1567
+ keywords: ["magnetic", "hover", "effect", "cursor", "animation", "interactive"],
1568
+ useCases: [
1569
+ "Interactive buttons",
1570
+ "Hover effects",
1571
+ "Playful interactions",
1572
+ "Cursor attraction"
1573
+ ],
1574
+ dependencies: ["framer-motion"],
1575
+ props: {
1576
+ children: { type: "ReactNode", description: "Element to apply magnetic effect to", required: true },
1577
+ strength: { type: "number", default: "0.5", description: "Magnetic pull strength (0-1)" }
1578
+ },
1579
+ example: `<Magnetic strength={0.5}>
1580
+ <Button>Hover me</Button>
1581
+ </Magnetic>`
1582
+ },
1583
+ // ============================================================================
1584
+ // FORMS - Additional (7 more)
1585
+ // ============================================================================
1586
+ "search-bar": {
1587
+ name: "SearchBar",
1588
+ category: "forms",
1589
+ description: "Search input with icon, clear button, and keyboard shortcuts",
1590
+ keywords: ["search", "input", "find", "query", "filter", "bar"],
1591
+ useCases: [
1592
+ "Site search",
1593
+ "Content filtering",
1594
+ "Command palette trigger",
1595
+ "Data filtering"
1596
+ ],
1597
+ dependencies: ["lucide-react"],
1598
+ props: {
1599
+ value: { type: "string", description: "Controlled search value" },
1600
+ onChange: { type: "(value: string) => void", description: "Callback on value change" },
1601
+ placeholder: { type: "string", default: "'Search...'", description: "Placeholder text" },
1602
+ onClear: { type: "() => void", description: "Callback on clear button click" }
1603
+ },
1604
+ example: `<SearchBar value={query} onChange={setQuery} placeholder="Search components..." />`
1605
+ },
1606
+ "filter-button": {
1607
+ name: "FilterButton",
1608
+ category: "forms",
1609
+ description: "Button for filtering content with active/inactive states",
1610
+ keywords: ["filter", "button", "toggle", "category", "selection"],
1611
+ useCases: [
1612
+ "Category filters",
1613
+ "Tag selection",
1614
+ "Content filtering",
1615
+ "Quick filters"
1616
+ ],
1617
+ dependencies: [],
1618
+ props: {
1619
+ active: { type: "boolean", default: "false", description: "Whether filter is active" },
1620
+ onClick: { type: "() => void", description: "Click handler" },
1621
+ children: { type: "ReactNode", description: "Filter label", required: true }
1622
+ },
1623
+ example: `<FilterButton active={category === 'all'} onClick={() => setCategory('all')}>All</FilterButton>`
1624
+ },
1625
+ "theme-switcher": {
1626
+ name: "ThemeSwitcher",
1627
+ category: "forms",
1628
+ description: "Multi-theme selector for switching between Studio, Terra, and Volt. Reads/writes to ThemeProvider context.",
1629
+ keywords: ["theme", "switcher", "selector", "studio", "terra", "volt"],
1630
+ useCases: [
1631
+ "Theme selection",
1632
+ "Brand customization",
1633
+ "User preferences",
1634
+ "Design switching"
1635
+ ],
1636
+ dependencies: [],
1637
+ example: `// Reads from ThemeProvider context, no props needed.
1638
+ <ThemeSwitcher />`
1639
+ },
1640
+ "theme-toggle": {
1641
+ name: "ThemeToggle",
1642
+ category: "forms",
1643
+ description: "Light/dark mode toggle with smooth transitions. Reads/writes to ThemeProvider context.",
1644
+ keywords: ["theme", "toggle", "dark-mode", "light-mode", "mode"],
1645
+ useCases: [
1646
+ "Dark mode switch",
1647
+ "Light mode switch",
1648
+ "Theme mode control",
1649
+ "Accessibility preference"
1650
+ ],
1651
+ dependencies: ["lucide-react"],
1652
+ example: `// Reads from ThemeProvider context, no props needed.
1653
+ <ThemeToggle />`
1654
+ },
1655
+ "color-picker": {
1656
+ name: "ColorPicker",
1657
+ category: "forms",
1658
+ description: "Color selection input with preset swatches and custom color support",
1659
+ keywords: ["color", "picker", "palette", "swatch", "hex", "customization"],
1660
+ useCases: [
1661
+ "Brand color selection",
1662
+ "Theme customization",
1663
+ "Design tools",
1664
+ "User preferences"
1665
+ ],
1666
+ dependencies: [],
1667
+ props: {
1668
+ value: { type: "string", description: "Selected color (hex string)" },
1669
+ onChange: { type: "(color: string) => void", description: "Callback on color change" },
1670
+ presets: { type: "string[]", description: "Preset color swatches (hex values)" }
1671
+ },
1672
+ example: `<ColorPicker value={color} onChange={setColor} presets={['#ef4444', '#3b82f6', '#22c55e']} />`
1673
+ },
1674
+ "drag-drop": {
1675
+ name: "DragDrop",
1676
+ category: "forms",
1677
+ description: "Drag and drop file upload zone with preview support",
1678
+ keywords: ["drag", "drop", "upload", "file", "dropzone", "input"],
1679
+ useCases: [
1680
+ "File uploads",
1681
+ "Image uploads",
1682
+ "Document uploads",
1683
+ "Bulk imports"
1684
+ ],
1685
+ dependencies: [],
1686
+ props: {
1687
+ onDrop: { type: "(files: File[]) => void", description: "Callback when files are dropped", required: true },
1688
+ accept: { type: "string", description: 'Accepted file types (e.g. "image/*")' },
1689
+ maxSize: { type: "number", description: "Max file size in bytes" },
1690
+ multiple: { type: "boolean", default: "true", description: "Allow multiple files" }
1691
+ },
1692
+ example: `<DragDrop onDrop={(files) => handleUpload(files)} accept="image/*" maxSize={5242880} />`
1693
+ },
1694
+ "text-field": {
1695
+ name: "TextField",
1696
+ category: "forms",
1697
+ description: "Complete text input with label, helper text, and error states",
1698
+ keywords: ["text", "field", "input", "label", "form", "validation"],
1699
+ useCases: [
1700
+ "Form fields",
1701
+ "Labeled inputs",
1702
+ "Validated inputs",
1703
+ "Complete form controls"
1704
+ ],
1705
+ dependencies: [],
1706
+ props: {
1707
+ label: { type: "string", description: "Field label text" },
1708
+ helperText: { type: "string", description: "Helper text below input" },
1709
+ error: { type: "string", description: "Error message (shows error state when set)" },
1710
+ required: { type: "boolean", default: "false", description: "Mark as required" }
1711
+ },
1712
+ example: `<TextField label="Email" helperText="We'll never share your email." error={errors.email} required />`
1713
+ },
1714
+ // ============================================================================
1715
+ // NAVIGATION - Additional (4 more)
1716
+ // ============================================================================
1717
+ "nav-link": {
1718
+ name: "NavLink",
1719
+ category: "navigation",
1720
+ description: "Navigation link with active state indicators and variants",
1721
+ keywords: ["nav", "link", "navigation", "active", "menu", "item"],
1722
+ useCases: [
1723
+ "Navigation menus",
1724
+ "Sidebar links",
1725
+ "Header navigation",
1726
+ "Active page indicators"
1727
+ ],
1728
+ dependencies: [],
1729
+ props: {
1730
+ href: { type: "string", description: "Link URL", required: true },
1731
+ isActive: { type: "boolean", default: "false", description: "Active state indicator" },
1732
+ variant: { type: "'default' | 'subtle'", default: "'default'", description: "Visual variant" }
1733
+ },
1734
+ example: `<NavLink href="/dashboard" isActive>Dashboard</NavLink>`
1735
+ },
1736
+ "secondary-nav": {
1737
+ name: "SecondaryNav",
1738
+ category: "navigation",
1739
+ description: "Horizontal secondary navigation bar for section switching",
1740
+ keywords: ["secondary", "navigation", "tabs", "sections", "subnav"],
1741
+ useCases: [
1742
+ "Section navigation",
1743
+ "Page subsections",
1744
+ "Tab-like navigation",
1745
+ "Category switching"
1746
+ ],
1747
+ dependencies: [],
1748
+ props: {
1749
+ items: { type: "{ label: string; href: string; isActive?: boolean }[]", description: "Navigation items", required: true }
1750
+ },
1751
+ example: `<SecondaryNav items={[
1752
+ { label: 'Overview', href: '/overview', isActive: true },
1753
+ { label: 'Settings', href: '/settings' },
1754
+ ]} />`
1755
+ },
1756
+ "tertiary-nav": {
1757
+ name: "TertiaryNav",
1758
+ category: "navigation",
1759
+ description: "Third-level navigation for deep content hierarchies",
1760
+ keywords: ["tertiary", "navigation", "deep", "hierarchy", "subnav"],
1761
+ useCases: [
1762
+ "Deep navigation",
1763
+ "Documentation sections",
1764
+ "Multi-level content",
1765
+ "Nested categories"
1766
+ ],
1767
+ dependencies: [],
1768
+ props: {
1769
+ items: { type: "{ label: string; href: string; isActive?: boolean }[]", description: "Navigation items", required: true }
1770
+ },
1771
+ example: `<TertiaryNav items={[
1772
+ { label: 'Props', href: '#props', isActive: true },
1773
+ { label: 'Examples', href: '#examples' },
1774
+ ]} />`
1775
+ },
1776
+ breadcrumbs: {
1777
+ name: "Breadcrumbs",
1778
+ category: "navigation",
1779
+ description: "Breadcrumb navigation with home icon and variants",
1780
+ keywords: ["breadcrumbs", "navigation", "path", "trail", "hierarchy"],
1781
+ useCases: [
1782
+ "Page location",
1783
+ "Navigation trail",
1784
+ "Hierarchical navigation",
1785
+ "Back navigation"
1786
+ ],
1787
+ dependencies: ["lucide-react"],
1788
+ props: {
1789
+ items: { type: "{ label: string; href?: string }[]", description: "Breadcrumb trail items (last item is current page)", required: true },
1790
+ showHome: { type: "boolean", default: "true", description: "Show home icon as first item" }
1791
+ },
1792
+ example: `<Breadcrumbs items={[
1793
+ { label: 'Home', href: '/' },
1794
+ { label: 'Components', href: '/components' },
1795
+ { label: 'Button' },
1796
+ ]} />`
1797
+ },
1798
+ // ============================================================================
1799
+ // OVERLAYS - Additional (2 more)
1800
+ // ============================================================================
1801
+ modal: {
1802
+ name: "Modal",
1803
+ category: "overlays",
1804
+ description: "Simple modal wrapper around Dialog with common patterns",
1805
+ keywords: ["modal", "dialog", "popup", "overlay", "window"],
1806
+ useCases: [
1807
+ "Simple modals",
1808
+ "Confirmation dialogs",
1809
+ "Form modals",
1810
+ "Content overlays"
1811
+ ],
1812
+ dependencies: ["@radix-ui/react-dialog"],
1813
+ radixPrimitive: "@radix-ui/react-dialog",
1814
+ props: {
1815
+ open: { type: "boolean", description: "Controlled open state" },
1816
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" },
1817
+ title: { type: "string", description: "Modal title" },
1818
+ description: { type: "string", description: "Modal description" }
1819
+ },
1820
+ example: `<Modal open={isOpen} onOpenChange={setIsOpen} title="Confirm" description="Are you sure?">
1821
+ <div className="flex gap-2 justify-end">
1822
+ <Button variant="outline" onClick={() => setIsOpen(false)}>Cancel</Button>
1823
+ <Button onClick={handleConfirm}>Confirm</Button>
1824
+ </div>
1825
+ </Modal>`
1826
+ },
1827
+ dropdown: {
1828
+ name: "Dropdown",
1829
+ category: "overlays",
1830
+ description: "Simple dropdown wrapper for common dropdown patterns",
1831
+ keywords: ["dropdown", "menu", "select", "options", "popover"],
1832
+ useCases: [
1833
+ "Action menus",
1834
+ "User menus",
1835
+ "Quick selections",
1836
+ "Option lists"
1837
+ ],
1838
+ dependencies: ["@radix-ui/react-dropdown-menu"],
1839
+ radixPrimitive: "@radix-ui/react-dropdown-menu",
1840
+ props: {
1841
+ open: { type: "boolean", description: "Controlled open state" },
1842
+ onOpenChange: { type: "(open: boolean) => void", description: "Callback on open/close" }
1843
+ },
1844
+ example: `// For most cases, use DropdownMenu directly. This is a simplified wrapper.`
1845
+ },
1846
+ // ============================================================================
1847
+ // FEEDBACK - Additional (2 more)
1848
+ // ============================================================================
1849
+ spinner: {
1850
+ name: "Spinner",
1851
+ category: "feedback",
1852
+ description: "Animated loading spinner with size variants",
1853
+ keywords: ["spinner", "loading", "loader", "progress", "waiting"],
1854
+ useCases: [
1855
+ "Loading states",
1856
+ "Button loading",
1857
+ "Data fetching",
1858
+ "Async operations"
1859
+ ],
1860
+ dependencies: [],
1861
+ props: {
1862
+ size: { type: "'xs' | 'sm' | 'md' | 'lg' | 'xl'", default: "'md'", description: "Spinner size" },
1863
+ variant: { type: "'primary' | 'secondary' | 'inherit'", default: "'primary'", description: "Color variant" }
1864
+ },
1865
+ example: `<Spinner size="md" />
1866
+ <Button disabled><Spinner size="xs" variant="inherit" /> Loading...</Button>`
1867
+ },
1868
+ "progress-bar": {
1869
+ name: "ProgressBar",
1870
+ category: "feedback",
1871
+ description: "Horizontal progress bar with percentage display",
1872
+ keywords: ["progress", "bar", "loading", "percentage", "completion"],
1873
+ useCases: [
1874
+ "File uploads",
1875
+ "Task progress",
1876
+ "Loading indicators",
1877
+ "Step completion"
1878
+ ],
1879
+ dependencies: [],
1880
+ props: {
1881
+ value: { type: "number", default: "0", description: "Progress value (0-100)" },
1882
+ variant: { type: "'primary' | 'success' | 'warning' | 'error' | 'info'", default: "'primary'", description: "Color variant" },
1883
+ size: { type: "'sm' | 'md' | 'lg'", default: "'md'", description: "Bar height" },
1884
+ showLabel: { type: "boolean", default: "false", description: "Show percentage label" }
1885
+ },
1886
+ example: `<ProgressBar value={75} variant="success" showLabel />`
1887
+ },
1888
+ // ============================================================================
1889
+ // DATA DISPLAY - Additional (5 more)
1890
+ // ============================================================================
1891
+ brand: {
1892
+ name: "Brand",
1893
+ category: "data-display",
1894
+ description: "Theme-aware brand/logo component with size variants and link support",
1895
+ keywords: ["brand", "logo", "identity", "header", "company"],
1896
+ useCases: [
1897
+ "Site logos",
1898
+ "Header branding",
1899
+ "Footer branding",
1900
+ "App identity"
1901
+ ],
1902
+ dependencies: [],
1903
+ props: {
1904
+ variant: { type: "'default' | 'mark'", default: "'default'", description: "Full logo or mark only" },
1905
+ size: { type: "'sm' | 'md' | 'lg'", default: "'md'", description: "Logo size" },
1906
+ href: { type: "string", description: "Optional link URL (wraps in anchor)" }
1907
+ },
1908
+ example: `<Brand size="md" href="/" />`
1909
+ },
1910
+ "aspect-image": {
1911
+ name: "AspectImage",
1912
+ category: "data-display",
1913
+ description: "Image with configurable aspect ratio, rounded corners, and captions",
1914
+ keywords: ["image", "aspect", "ratio", "figure", "caption", "media"],
1915
+ useCases: [
1916
+ "Gallery images",
1917
+ "Article images",
1918
+ "Product images",
1919
+ "Thumbnails with captions"
1920
+ ],
1921
+ dependencies: [],
1922
+ props: {
1923
+ src: { type: "string", description: "Image source URL", required: true },
1924
+ alt: { type: "string", description: "Alt text for accessibility", required: true },
1925
+ ratio: { type: "number", default: "16/9", description: "Aspect ratio" },
1926
+ rounded: { type: "'none' | 'sm' | 'md' | 'lg' | 'full'", default: "'md'", description: "Border radius" },
1927
+ caption: { type: "string", description: "Optional caption text below image" }
1928
+ },
1929
+ example: `<AspectImage src="/photo.jpg" alt="Team photo" ratio={4/3} caption="Our team" />`
1930
+ },
1931
+ "variable-weight-text": {
1932
+ name: "VariableWeightText",
1933
+ category: "data-display",
1934
+ description: "Animated text with breathing font-weight effect using variable fonts",
1935
+ keywords: ["variable", "font", "weight", "animation", "breathing", "motion"],
1936
+ useCases: [
1937
+ "Hero text",
1938
+ "Emphasis text",
1939
+ "Attention grabbing",
1940
+ "Variable font showcase"
1941
+ ],
1942
+ dependencies: ["framer-motion"],
1943
+ props: {
1944
+ children: { type: "string", description: "Text content", required: true },
1945
+ speed: { type: "number", default: "2", description: "Animation speed in seconds" },
1946
+ minWeight: { type: "number", default: "100", description: "Minimum font weight" },
1947
+ maxWeight: { type: "number", default: "900", description: "Maximum font weight" }
1948
+ },
1949
+ example: `<VariableWeightText speed={2} minWeight={200} maxWeight={800}>Design</VariableWeightText>`
1950
+ },
1951
+ typewriter: {
1952
+ name: "Typewriter",
1953
+ category: "data-display",
1954
+ description: "Typewriter text animation with cursor and loop support",
1955
+ keywords: ["typewriter", "typing", "animation", "cursor", "text", "effect"],
1956
+ useCases: [
1957
+ "Hero taglines",
1958
+ "Terminal effects",
1959
+ "Dynamic headings",
1960
+ "Attention text"
1961
+ ],
1962
+ dependencies: ["framer-motion"],
1963
+ props: {
1964
+ words: { type: "string[]", description: "Words to cycle through", required: true },
1965
+ speed: { type: "number", default: "100", description: "Typing speed in ms per character" },
1966
+ loop: { type: "boolean", default: "true", description: "Loop through words continuously" },
1967
+ cursor: { type: "boolean", default: "true", description: "Show blinking cursor" }
1968
+ },
1969
+ example: `<Typewriter words={['Developer', 'Designer', 'Creator']} speed={80} />`
1970
+ },
1971
+ "github-icon": {
1972
+ name: "GitHubIcon",
1973
+ category: "data-display",
1974
+ description: "GitHub logo icon that inherits text color for theme support",
1975
+ keywords: ["github", "icon", "social", "logo", "svg"],
1976
+ useCases: [
1977
+ "Social links",
1978
+ "Footer icons",
1979
+ "Repository links",
1980
+ "Open source badges"
1981
+ ],
1982
+ dependencies: [],
1983
+ props: {
1984
+ size: { type: "number", default: "24", description: "Icon size in pixels" }
1985
+ },
1986
+ example: `<a href="https://github.com/you"><GitHubIcon size={20} /></a>`
1987
+ },
1988
+ // ============================================================================
1989
+ // SPECIALTY - Backgrounds (3)
1990
+ // ============================================================================
1991
+ "warp-background": {
1992
+ name: "WarpBackground",
1993
+ category: "backgrounds",
1994
+ description: "Animated warp speed star field background effect",
1995
+ keywords: ["warp", "stars", "background", "animation", "space", "effect"],
1996
+ useCases: [
1997
+ "Hero backgrounds",
1998
+ "Landing pages",
1999
+ "Loading screens",
2000
+ "Sci-fi themes"
2001
+ ],
2002
+ dependencies: ["framer-motion"],
2003
+ props: {
2004
+ speed: { type: "number", default: "1", description: "Warp speed multiplier" },
2005
+ density: { type: "number", default: "200", description: "Number of stars" },
2006
+ color: { type: "string", default: "'white'", description: "Star color" }
2007
+ },
2008
+ example: `<WarpBackground speed={1.5} density={300}>
2009
+ <div className="relative z-10">Content over stars</div>
2010
+ </WarpBackground>`
2011
+ },
2012
+ "faulty-terminal": {
2013
+ name: "FaultyTerminal",
2014
+ category: "backgrounds",
2015
+ description: "Glitchy terminal background with flickering and scan lines",
2016
+ keywords: ["terminal", "glitch", "background", "retro", "crt", "effect"],
2017
+ useCases: [
2018
+ "Retro themes",
2019
+ "Hacker aesthetics",
2020
+ "Error pages",
2021
+ "Terminal UIs"
2022
+ ],
2023
+ dependencies: [],
2024
+ props: {
2025
+ children: { type: "ReactNode", description: "Content to render inside terminal" }
2026
+ },
2027
+ example: `<FaultyTerminal>
2028
+ <p>$ system initializing...</p>
2029
+ </FaultyTerminal>`
2030
+ },
2031
+ "orb-background": {
2032
+ name: "OrbBackground",
2033
+ category: "backgrounds",
2034
+ description: "Animated floating orb with gradient blur effect",
2035
+ keywords: ["orb", "gradient", "background", "animation", "blur", "ambient"],
2036
+ useCases: [
2037
+ "Landing pages",
2038
+ "Hero sections",
2039
+ "Ambient backgrounds",
2040
+ "Modern aesthetics"
2041
+ ],
2042
+ dependencies: ["framer-motion"],
2043
+ props: {
2044
+ color: { type: "string", description: "Primary orb color" },
2045
+ size: { type: "number", default: "400", description: "Orb diameter in pixels" }
2046
+ },
2047
+ example: `<OrbBackground color="var(--color-primary)" size={500}>
2048
+ <div className="relative z-10">Content</div>
2049
+ </OrbBackground>`
2050
+ },
2051
+ // ============================================================================
2052
+ // SPECIALTY - Cursor (2)
2053
+ // ============================================================================
2054
+ "splash-cursor": {
2055
+ name: "SplashCursor",
2056
+ category: "cursor",
2057
+ description: "Custom cursor with splash/ripple effect on click. WebGL-based fluid simulation.",
2058
+ keywords: ["cursor", "splash", "ripple", "click", "effect", "interactive"],
2059
+ useCases: [
2060
+ "Interactive experiences",
2061
+ "Creative portfolios",
2062
+ "Playful interfaces",
2063
+ "Click feedback"
2064
+ ],
2065
+ dependencies: [],
2066
+ example: `// Place once in layout. Replaces default cursor globally.
2067
+ <SplashCursor />`
2068
+ },
2069
+ "target-cursor": {
2070
+ name: "TargetCursor",
2071
+ category: "cursor",
2072
+ description: "Custom cursor with target/crosshair appearance",
2073
+ keywords: ["cursor", "target", "crosshair", "pointer", "custom"],
2074
+ useCases: [
2075
+ "Gaming interfaces",
2076
+ "Precision tools",
2077
+ "Interactive elements",
2078
+ "Custom pointers"
2079
+ ],
2080
+ dependencies: [],
2081
+ example: `// Place once in layout. Replaces default cursor globally.
2082
+ <TargetCursor />`
2083
+ },
2084
+ // ============================================================================
2085
+ // SPECIALTY - Motion (1)
2086
+ // ============================================================================
2087
+ "animated-beam": {
2088
+ name: "AnimatedBeam",
2089
+ category: "motion",
2090
+ description: "Animated beam/line connecting two elements",
2091
+ keywords: ["beam", "animation", "connection", "line", "flow", "motion"],
2092
+ useCases: [
2093
+ "Connecting elements",
2094
+ "Data flow visualization",
2095
+ "Architecture diagrams",
2096
+ "Interactive connections"
2097
+ ],
2098
+ dependencies: ["framer-motion"],
2099
+ props: {
2100
+ fromRef: { type: "RefObject<HTMLElement>", description: "Ref to source element", required: true },
2101
+ toRef: { type: "RefObject<HTMLElement>", description: "Ref to target element", required: true },
2102
+ duration: { type: "number", default: "3", description: "Animation duration in seconds" }
2103
+ },
2104
+ example: `const fromRef = useRef(null)
2105
+ const toRef = useRef(null)
2106
+ <div ref={fromRef}>Source</div>
2107
+ <div ref={toRef}>Target</div>
2108
+ <AnimatedBeam fromRef={fromRef} toRef={toRef} />`
2109
+ },
2110
+ // ============================================================================
2111
+ // SPECIALTY - Blocks (2)
2112
+ // ============================================================================
2113
+ hero: {
2114
+ name: "Hero",
2115
+ category: "blocks",
2116
+ description: "Full-width hero section with title, subtitle, and CTA",
2117
+ keywords: ["hero", "banner", "header", "landing", "cta", "section"],
2118
+ useCases: [
2119
+ "Landing pages",
2120
+ "Page headers",
2121
+ "Marketing sections",
2122
+ "Feature highlights"
2123
+ ],
2124
+ dependencies: [],
2125
+ props: {
2126
+ title: { type: "string", description: "Main heading text", required: true },
2127
+ subtitle: { type: "string", description: "Subtitle or tagline" },
2128
+ cta: { type: "ReactNode", description: "Call-to-action element (Button, etc.)" },
2129
+ background: { type: "ReactNode", description: "Optional background element (WarpBackground, OrbBackground, etc.)" }
2130
+ },
2131
+ example: `<Hero
2132
+ title="Build Something Beautiful"
2133
+ subtitle="A design system that brings joy."
2134
+ cta={<Button size="lg">Get Started</Button>}
2135
+ />`
2136
+ },
2137
+ "open-graph-card": {
2138
+ name: "OpenGraphCard",
2139
+ category: "blocks",
2140
+ description: "Social media preview card for Open Graph metadata. Use in opengraph-image.tsx.",
2141
+ keywords: ["open-graph", "social", "preview", "card", "meta", "share"],
2142
+ useCases: [
2143
+ "Social sharing previews",
2144
+ "Link previews",
2145
+ "Meta card generation",
2146
+ "Marketing previews"
2147
+ ],
2148
+ dependencies: [],
2149
+ props: {
2150
+ title: { type: "string", default: "'Sage Design Engine'", description: "Main title text" },
2151
+ description: { type: "string", description: "Subtitle text" },
2152
+ variant: { type: "'primary' | 'secondary' | 'accent' | 'sage' | 'emerald' | 'gradient'", default: "'sage'", description: "Visual style variant" },
2153
+ icon: { type: "ReactNode", description: "Custom logo or icon element" },
2154
+ gradient: { type: "{ type: string; angle: number; colors: string[] }", description: 'Custom gradient config (variant="gradient")' },
2155
+ primaryColor: { type: "string", description: "Override primary color (hex)" },
2156
+ secondaryColor: { type: "string", description: "Override secondary color (hex)" },
2157
+ accentColor: { type: "string", description: "Override accent color (hex)" }
2158
+ },
2159
+ example: `// In opengraph-image.tsx:
2160
+ export default function OGImage() {
2161
+ return <OpenGraphCard title="My Page" description="A great description" variant="primary" />
2162
+ }`
2163
+ }
2164
+ };
2165
+ function getComponentsByCategory(category) {
2166
+ return Object.values(COMPONENT_REGISTRY).filter(
2167
+ (component) => component.category === category
2168
+ );
2169
+ }
2170
+ function searchComponents(query) {
2171
+ const lowerQuery = query.toLowerCase();
2172
+ return Object.values(COMPONENT_REGISTRY).filter((component) => {
2173
+ return component.name.toLowerCase().includes(lowerQuery) || component.description.toLowerCase().includes(lowerQuery) || component.keywords.some((keyword) => keyword.toLowerCase().includes(lowerQuery)) || component.useCases.some((useCase) => useCase.toLowerCase().includes(lowerQuery));
2174
+ });
2175
+ }
2176
+ function getComponent(name) {
2177
+ const kebabName = name.toLowerCase().replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
2178
+ return COMPONENT_REGISTRY[kebabName];
2179
+ }
2180
+ function getAllComponentNames() {
2181
+ return Object.keys(COMPONENT_REGISTRY);
2182
+ }
2183
+ function getComponentCount() {
2184
+ return Object.keys(COMPONENT_REGISTRY).length;
2185
+ }
2186
+
2187
+ export {
2188
+ COMPONENT_CATEGORIES,
2189
+ COMPONENT_REGISTRY,
2190
+ getComponentsByCategory,
2191
+ searchComponents,
2192
+ getComponent,
2193
+ getAllComponentNames,
2194
+ getComponentCount
2195
+ };