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