@watt42/a2ui-component-catalog 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +33 -0
  2. package/catalog.json +817 -0
  3. package/dist/catalogCompatibility.d.ts +8 -0
  4. package/dist/catalogCompatibility.d.ts.map +1 -0
  5. package/dist/catalogCompatibility.js +24 -0
  6. package/dist/catalogCompatibility.js.map +1 -0
  7. package/dist/catalogTypes.d.ts +35 -0
  8. package/dist/catalogTypes.d.ts.map +1 -0
  9. package/dist/catalogTypes.js +4 -0
  10. package/dist/catalogTypes.js.map +1 -0
  11. package/dist/contract/index.d.ts +3 -0
  12. package/dist/contract/index.d.ts.map +1 -0
  13. package/dist/contract/index.js +2 -0
  14. package/dist/contract/index.js.map +1 -0
  15. package/dist/contract/sharedSchemas.d.ts +6 -0
  16. package/dist/contract/sharedSchemas.d.ts.map +1 -0
  17. package/dist/contract/sharedSchemas.js +38 -0
  18. package/dist/contract/sharedSchemas.js.map +1 -0
  19. package/dist/contract/types.d.ts +57 -0
  20. package/dist/contract/types.d.ts.map +1 -0
  21. package/dist/contract/types.js +3 -0
  22. package/dist/contract/types.js.map +1 -0
  23. package/dist/contract/validateManifest.d.ts +5 -0
  24. package/dist/contract/validateManifest.d.ts.map +1 -0
  25. package/dist/contract/validateManifest.js +107 -0
  26. package/dist/contract/validateManifest.js.map +1 -0
  27. package/dist/generateCatalog.d.ts +9 -0
  28. package/dist/generateCatalog.d.ts.map +1 -0
  29. package/dist/generateCatalog.js +76 -0
  30. package/dist/generateCatalog.js.map +1 -0
  31. package/dist/index.d.ts +14 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +27 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/validate.d.ts +3 -0
  36. package/dist/validate.d.ts.map +1 -0
  37. package/dist/validate.js +17 -0
  38. package/dist/validate.js.map +1 -0
  39. package/dist/validateProps.d.ts +3 -0
  40. package/dist/validateProps.d.ts.map +1 -0
  41. package/dist/validateProps.js +101 -0
  42. package/dist/validateProps.js.map +1 -0
  43. package/package.json +33 -0
package/catalog.json ADDED
@@ -0,0 +1,817 @@
1
+ {
2
+ "catalogId": "watt42:a2ui:catalog:manifest:v1",
3
+ "catalogVersion": "manifest/2026.08.24.2",
4
+ "uiVersion": "v0.9.1",
5
+ "generated": {
6
+ "source": "manifests",
7
+ "command": "npm run generate:catalog --workspace=@watt42/a2ui-component-catalog"
8
+ },
9
+ "components": [
10
+ {
11
+ "name": "Button",
12
+ "description": "Clickable control that emits an A2UI action when selected.",
13
+ "version": "1.0.0",
14
+ "implementation": {
15
+ "source": "shadcn",
16
+ "base": "base",
17
+ "sourceVersion": "4.17.0"
18
+ },
19
+ "props": {
20
+ "label": {
21
+ "type": "string",
22
+ "required": true,
23
+ "description": "Text shown on the button. Not a React child tree."
24
+ },
25
+ "variant": {
26
+ "type": "string",
27
+ "required": false,
28
+ "default": "default",
29
+ "enum": [
30
+ "default",
31
+ "secondary",
32
+ "destructive",
33
+ "outline",
34
+ "ghost",
35
+ "link"
36
+ ],
37
+ "description": "Visual style (A2UI subset of shadcn Button variants)."
38
+ },
39
+ "size": {
40
+ "type": "string",
41
+ "required": false,
42
+ "default": "default",
43
+ "enum": [
44
+ "default",
45
+ "sm",
46
+ "lg",
47
+ "icon"
48
+ ],
49
+ "description": "Control size."
50
+ },
51
+ "disabled": {
52
+ "type": "boolean",
53
+ "required": false,
54
+ "default": false
55
+ },
56
+ "action": {
57
+ "type": "object",
58
+ "required": false,
59
+ "description": "ActionContract: { name, context }. Not { event: { name, context } }.",
60
+ "properties": {
61
+ "name": {
62
+ "type": "string",
63
+ "required": true,
64
+ "description": "UserActionHandler actionName."
65
+ },
66
+ "context": {
67
+ "type": "object",
68
+ "required": false,
69
+ "description": "Optional payload merged into handler context."
70
+ }
71
+ }
72
+ }
73
+ },
74
+ "allowedChildren": "none",
75
+ "supportedBy": [
76
+ "surface"
77
+ ],
78
+ "actions": {
79
+ "action": {
80
+ "type": "object",
81
+ "description": "Same schema as props.action (ActionContract)."
82
+ }
83
+ },
84
+ "events": [
85
+ {
86
+ "name": "action",
87
+ "description": "Fired on activate with ActionContract name and context."
88
+ }
89
+ ],
90
+ "dataBindings": {},
91
+ "llmGuidance": [
92
+ "Visible Button text is properties.label (required). Do not nest Label children (allowedChildren is none) and do not add a sibling Label that only repeats the same action text.",
93
+ "Actions use ActionContract { name, context } — not { event: { name, context } }.",
94
+ "Button has no hover-description property. For 'button with hover description' / hover help, emit a single HoverCard (triggerText + content) — do not invent properties.hoverDescription and do not emit a Button that repeats the same label."
95
+ ]
96
+ },
97
+ {
98
+ "name": "Card",
99
+ "description": "Container for grouped catalog components in the compiled A2UI tree. In UIIntent, Card accepts only the props listed below; allowedChildren is not a properties.children prop. Use Label for static copy and Carousel for slide navigation.",
100
+ "version": "1.0.0",
101
+ "implementation": {
102
+ "source": "shadcn",
103
+ "base": "base",
104
+ "sourceVersion": "4.17.0"
105
+ },
106
+ "props": {
107
+ "variant": {
108
+ "type": "string",
109
+ "required": false,
110
+ "default": "default",
111
+ "enum": [
112
+ "default",
113
+ "outline"
114
+ ],
115
+ "description": "Visual treatment. outline is an A2UI variant, not a shadcn Card API dump."
116
+ }
117
+ },
118
+ "allowedChildren": "any",
119
+ "supportedBy": [
120
+ "surface"
121
+ ],
122
+ "actions": {},
123
+ "events": [],
124
+ "dataBindings": {},
125
+ "llmGuidance": [
126
+ "Card may include a nested components array of child component specs ({ type, properties, title? }).",
127
+ "Use Card.components for grouped Labels and other catalog children.",
128
+ "Card title is rendered as the first Label.",
129
+ "Do not put nested specs in properties.children on Card."
130
+ ]
131
+ },
132
+ {
133
+ "name": "Carousel",
134
+ "description": "Horizontal slide container for catalog child components. Provide slide content with properties.slides as nested component specs; do not use properties.children.",
135
+ "version": "1.0.0",
136
+ "implementation": {
137
+ "source": "shadcn",
138
+ "base": "base",
139
+ "sourceVersion": "4.17.0"
140
+ },
141
+ "props": {
142
+ "title": {
143
+ "type": "string",
144
+ "required": false,
145
+ "description": "Optional heading above the carousel."
146
+ },
147
+ "showControls": {
148
+ "type": "boolean",
149
+ "required": false,
150
+ "default": true,
151
+ "description": "Show previous/next controls when there is more than one slide."
152
+ },
153
+ "slides": {
154
+ "type": "array",
155
+ "required": true,
156
+ "description": "Nested component specs for each slide: { type, properties, title? }.",
157
+ "items": {
158
+ "type": "object"
159
+ }
160
+ }
161
+ },
162
+ "allowedChildren": "any",
163
+ "supportedBy": [
164
+ "surface"
165
+ ],
166
+ "actions": {},
167
+ "events": [],
168
+ "dataBindings": {},
169
+ "llmGuidance": [
170
+ "Carousel uses properties.slides: a non-empty array of nested component specs ({ type, properties, title? }) — one entry per slide.",
171
+ "Do not use properties.children for Carousel.",
172
+ "Each slide should usually be a Label with properties.text set to the visible copy (title alone is not shown)."
173
+ ],
174
+ "nestedSpecProps": [
175
+ "slides"
176
+ ],
177
+ "defaultNestedTypes": [
178
+ "Label"
179
+ ]
180
+ },
181
+ {
182
+ "name": "Chart",
183
+ "description": "Line, bar, pie, or area chart using user-provided, static, demo, illustrative, or live values. Chart does not require an energy-system service. LLM uses ChartSpec only — never raw ECharts options.",
184
+ "version": "1.0.0",
185
+ "implementation": {
186
+ "source": "echarts",
187
+ "sourceVersion": "5.6.0",
188
+ "specVersion": "1.0.0"
189
+ },
190
+ "props": {
191
+ "chartType": {
192
+ "type": "string",
193
+ "required": true,
194
+ "enum": [
195
+ "line",
196
+ "bar",
197
+ "pie",
198
+ "area"
199
+ ],
200
+ "description": "A2UI chart kind. Maps to ECharts via normalizeChartSpec (renderer adapter, not intent normalize)."
201
+ },
202
+ "title": {
203
+ "type": "string",
204
+ "required": false
205
+ },
206
+ "categories": {
207
+ "type": "array",
208
+ "required": true,
209
+ "description": "Non-empty category labels (x-axis or pie names).",
210
+ "items": {
211
+ "type": "string"
212
+ }
213
+ },
214
+ "series": {
215
+ "type": "array",
216
+ "required": true,
217
+ "description": "Non-empty series. Each entry uses values, not ECharts data.",
218
+ "items": {
219
+ "type": "object",
220
+ "properties": {
221
+ "name": {
222
+ "type": "string",
223
+ "required": true
224
+ },
225
+ "values": {
226
+ "type": "array",
227
+ "required": true,
228
+ "items": {
229
+ "type": "number"
230
+ }
231
+ }
232
+ }
233
+ }
234
+ },
235
+ "xLabel": {
236
+ "type": "string",
237
+ "required": false
238
+ },
239
+ "yLabel": {
240
+ "type": "string",
241
+ "required": false
242
+ },
243
+ "height": {
244
+ "type": "number",
245
+ "required": false,
246
+ "default": 360,
247
+ "description": "Pixel height; renderer clamps to 120–800."
248
+ }
249
+ },
250
+ "allowedChildren": "none",
251
+ "supportedBy": [
252
+ "surface"
253
+ ],
254
+ "actions": {},
255
+ "events": [],
256
+ "dataBindings": {},
257
+ "llmGuidance": [
258
+ "Chart uses ChartSpec only: chartType, categories, series[].values — never ECharts option, properties.type, or series data.",
259
+ "Chart supports user-provided, static, demo, and illustrative values for every catalog chartType, including pie.",
260
+ "Chart does not require a live data source.",
261
+ "Do not claim that Chart is limited to energy-system series.",
262
+ "When the user requests a chart with categories and values, render it without asking for confirmation.",
263
+ "For illustrative or sample chart data, use realistic values and describe the data as illustrative."
264
+ ]
265
+ },
266
+ {
267
+ "name": "DataTable",
268
+ "description": "Read-only tabular data display. Provide columns and rows as declarative data — no sorting, filtering, pagination, or row selection.",
269
+ "version": "1.0.0",
270
+ "implementation": {
271
+ "source": "shadcn",
272
+ "base": "base",
273
+ "sourceVersion": "4.17.0"
274
+ },
275
+ "props": {
276
+ "columns": {
277
+ "type": "array",
278
+ "required": true,
279
+ "description": "Non-empty column definitions.",
280
+ "items": {
281
+ "type": "object",
282
+ "properties": {
283
+ "key": {
284
+ "type": "string",
285
+ "required": true,
286
+ "description": "Row object key for this column."
287
+ },
288
+ "header": {
289
+ "type": "string",
290
+ "required": true,
291
+ "description": "Accessible column header text."
292
+ },
293
+ "align": {
294
+ "type": "string",
295
+ "required": false,
296
+ "enum": [
297
+ "left",
298
+ "center",
299
+ "right"
300
+ ],
301
+ "default": "left",
302
+ "description": "Cell text alignment."
303
+ }
304
+ }
305
+ }
306
+ },
307
+ "rows": {
308
+ "type": "array",
309
+ "required": true,
310
+ "description": "Row objects. Each row must provide a value for every column key.",
311
+ "items": {
312
+ "type": "object"
313
+ }
314
+ },
315
+ "caption": {
316
+ "type": "string",
317
+ "required": false,
318
+ "description": "Accessible table caption."
319
+ },
320
+ "striped": {
321
+ "type": "boolean",
322
+ "required": false,
323
+ "default": true,
324
+ "description": "Zebra striping for row scanability."
325
+ }
326
+ },
327
+ "allowedChildren": "none",
328
+ "supportedBy": [
329
+ "surface"
330
+ ],
331
+ "actions": {},
332
+ "events": [],
333
+ "dataBindings": {},
334
+ "llmGuidance": [
335
+ "Provide rectangular data only. Every row must include a value for every column key.",
336
+ "DataTable is read-only. Do not request sorting, filtering, pagination, or row selection.",
337
+ "Use string or number cell values. Keep column keys stable across rows."
338
+ ]
339
+ },
340
+ {
341
+ "name": "Dialog",
342
+ "description": "Modal dialog for confirmation and decision flows. Body content uses catalog child components; footer actions use ActionContract.",
343
+ "version": "1.0.0",
344
+ "implementation": {
345
+ "source": "shadcn",
346
+ "base": "base",
347
+ "sourceVersion": "4.17.0"
348
+ },
349
+ "props": {
350
+ "title": {
351
+ "type": "string",
352
+ "required": true,
353
+ "description": "Accessible dialog title."
354
+ },
355
+ "description": {
356
+ "type": "string",
357
+ "required": false,
358
+ "description": "Accessible dialog description."
359
+ },
360
+ "primaryAction": {
361
+ "type": "object",
362
+ "required": false,
363
+ "description": "ActionContract for the primary footer action.",
364
+ "properties": {
365
+ "name": {
366
+ "type": "string",
367
+ "required": true,
368
+ "description": "UserActionHandler actionName."
369
+ },
370
+ "context": {
371
+ "type": "object",
372
+ "required": false,
373
+ "description": "Optional payload merged into handler context."
374
+ }
375
+ }
376
+ },
377
+ "primaryLabel": {
378
+ "type": "string",
379
+ "required": false,
380
+ "default": "Confirm",
381
+ "description": "Primary footer button label."
382
+ },
383
+ "secondaryAction": {
384
+ "type": "object",
385
+ "required": false,
386
+ "description": "ActionContract for the secondary/dismiss footer action.",
387
+ "properties": {
388
+ "name": {
389
+ "type": "string",
390
+ "required": true,
391
+ "description": "UserActionHandler actionName."
392
+ },
393
+ "context": {
394
+ "type": "object",
395
+ "required": false,
396
+ "description": "Optional payload merged into handler context."
397
+ }
398
+ }
399
+ },
400
+ "secondaryLabel": {
401
+ "type": "string",
402
+ "required": false,
403
+ "default": "Cancel",
404
+ "description": "Secondary footer button label."
405
+ }
406
+ },
407
+ "allowedChildren": "any",
408
+ "supportedBy": [
409
+ "surface"
410
+ ],
411
+ "actions": {
412
+ "primaryAction": {
413
+ "type": "object",
414
+ "description": "Same schema as props.primaryAction (ActionContract)."
415
+ },
416
+ "secondaryAction": {
417
+ "type": "object",
418
+ "description": "Same schema as props.secondaryAction (ActionContract)."
419
+ }
420
+ },
421
+ "events": [
422
+ {
423
+ "name": "primaryAction",
424
+ "description": "Fired when the primary footer action is activated."
425
+ },
426
+ {
427
+ "name": "secondaryAction",
428
+ "description": "Fired when the secondary footer action is activated."
429
+ }
430
+ ],
431
+ "dataBindings": {},
432
+ "llmGuidance": [
433
+ "Dialog does not expose an open prop. Give Dialog a stable id and pair it with a Button whose action.name is openDialog:<dialogComponentId> to open at runtime.",
434
+ "Use Dialog for confirmation and decision flows with title, optional description, body children, and footer actions.",
435
+ "Place dialog body content as nested catalog children in components[] on the Dialog node (body Label is content; do not duplicate the opener Button label).",
436
+ "Tab titles and Button labels are owned by those components — do not invent a second Label that only repeats the same control text."
437
+ ],
438
+ "defaultNestedTypes": [
439
+ "Label",
440
+ "Button"
441
+ ]
442
+ },
443
+ {
444
+ "name": "HoverCard",
445
+ "description": "Supplementary contextual information revealed on hover or focus. The trigger must remain understandable without the hover panel.",
446
+ "version": "1.0.0",
447
+ "implementation": {
448
+ "source": "shadcn",
449
+ "base": "base",
450
+ "sourceVersion": "4.17.0"
451
+ },
452
+ "props": {
453
+ "triggerText": {
454
+ "type": "string",
455
+ "required": true,
456
+ "description": "Visible, focusable trigger label."
457
+ },
458
+ "title": {
459
+ "type": "string",
460
+ "required": false,
461
+ "description": "Optional card heading."
462
+ },
463
+ "content": {
464
+ "type": "string",
465
+ "required": true,
466
+ "description": "Concise supplementary body text."
467
+ }
468
+ },
469
+ "allowedChildren": "none",
470
+ "supportedBy": [
471
+ "surface"
472
+ ],
473
+ "actions": {},
474
+ "events": [],
475
+ "dataBindings": {},
476
+ "llmGuidance": [
477
+ "HoverCard content is supplementary only. Do not place essential information or the only path to an important action inside the hover panel.",
478
+ "The trigger text must remain understandable on its own without the hover interaction.",
479
+ "For requests like 'button with hover description' or 'Get Started with hover help', emit a single HoverCard (triggerText + content). Do not also emit a Button with the same label — that duplicates controls and breaks layout.",
480
+ "Only add a sibling Button when a real ActionContract click is required AND use a different HoverCard.triggerText (for example 'What's this?'), never the same string as Button.label."
481
+ ]
482
+ },
483
+ {
484
+ "name": "Input",
485
+ "description": "Form field bound to the surface data model. A2UI does not expose the full HTML input API.",
486
+ "version": "1.0.0",
487
+ "implementation": {
488
+ "source": "shadcn",
489
+ "base": "base",
490
+ "sourceVersion": "4.17.0"
491
+ },
492
+ "props": {
493
+ "label": {
494
+ "type": "string",
495
+ "required": false,
496
+ "description": "Accessible field label."
497
+ },
498
+ "placeholder": {
499
+ "type": "string",
500
+ "required": false
501
+ },
502
+ "inputType": {
503
+ "type": "string",
504
+ "required": false,
505
+ "default": "text",
506
+ "enum": [
507
+ "text",
508
+ "number",
509
+ "email",
510
+ "textarea"
511
+ ],
512
+ "description": "A2UI input kinds. textarea is an A2UI convenience, not a separate component."
513
+ },
514
+ "value": {
515
+ "type": "object",
516
+ "required": false,
517
+ "description": "BindingContract: data-model path. Not a literal string in UIIntent.",
518
+ "properties": {
519
+ "path": {
520
+ "type": "string",
521
+ "required": true,
522
+ "description": "Data-model path, e.g. /form/email."
523
+ },
524
+ "mode": {
525
+ "type": "string",
526
+ "required": false,
527
+ "default": "readWrite",
528
+ "enum": [
529
+ "read",
530
+ "write",
531
+ "readWrite"
532
+ ]
533
+ }
534
+ }
535
+ }
536
+ },
537
+ "allowedChildren": "none",
538
+ "supportedBy": [
539
+ "surface"
540
+ ],
541
+ "actions": {},
542
+ "events": [],
543
+ "dataBindings": {
544
+ "value": {
545
+ "type": "object",
546
+ "description": "Same schema as props.value (BindingContract)."
547
+ }
548
+ },
549
+ "llmGuidance": [
550
+ "Field caption and placeholder are properties.label and properties.placeholder. Bind value with BindingContract { path, mode? } — not a literal string.",
551
+ "Do not add a separate Label that only duplicates the Input field name unless using Label.htmlFor for explicit association."
552
+ ]
553
+ },
554
+ {
555
+ "name": "Item",
556
+ "description": "Display row for list and summary content with optional media and trailing action. Primarily a presentation component.",
557
+ "version": "1.0.0",
558
+ "implementation": {
559
+ "source": "shadcn",
560
+ "base": "base",
561
+ "sourceVersion": "4.17.0"
562
+ },
563
+ "props": {
564
+ "title": {
565
+ "type": "string",
566
+ "required": true,
567
+ "description": "Primary heading text: plain string, or BindingContract { path } for a live bound value."
568
+ },
569
+ "description": {
570
+ "type": "string",
571
+ "required": false,
572
+ "description": "Secondary supporting text: plain string, or BindingContract { path } for a live bound value (e.g. Switch checked path)."
573
+ },
574
+ "variant": {
575
+ "type": "string",
576
+ "required": false,
577
+ "default": "default",
578
+ "enum": [
579
+ "default",
580
+ "outline",
581
+ "muted"
582
+ ],
583
+ "description": "Visual treatment."
584
+ },
585
+ "size": {
586
+ "type": "string",
587
+ "required": false,
588
+ "default": "default",
589
+ "enum": [
590
+ "default",
591
+ "sm",
592
+ "xs"
593
+ ],
594
+ "description": "Density."
595
+ },
596
+ "mediaType": {
597
+ "type": "string",
598
+ "required": false,
599
+ "default": "none",
600
+ "enum": [
601
+ "none",
602
+ "initials",
603
+ "image"
604
+ ],
605
+ "description": "Optional leading media. No icon registry."
606
+ },
607
+ "mediaValue": {
608
+ "type": "string",
609
+ "required": false,
610
+ "description": "Initials (1–2 chars) or image URL when mediaType is initials or image."
611
+ },
612
+ "actionLabel": {
613
+ "type": "string",
614
+ "required": false,
615
+ "description": "Trailing action button label. Optional."
616
+ },
617
+ "action": {
618
+ "type": "object",
619
+ "required": false,
620
+ "description": "ActionContract for the optional trailing action.",
621
+ "properties": {
622
+ "name": {
623
+ "type": "string",
624
+ "required": true,
625
+ "description": "UserActionHandler actionName."
626
+ },
627
+ "context": {
628
+ "type": "object",
629
+ "required": false,
630
+ "description": "Optional payload merged into handler context."
631
+ }
632
+ }
633
+ }
634
+ },
635
+ "allowedChildren": "none",
636
+ "supportedBy": [
637
+ "surface"
638
+ ],
639
+ "actions": {
640
+ "action": {
641
+ "type": "object",
642
+ "description": "Same schema as props.action (ActionContract)."
643
+ }
644
+ },
645
+ "events": [
646
+ {
647
+ "name": "action",
648
+ "description": "Fired when the optional trailing action is activated."
649
+ }
650
+ ],
651
+ "dataBindings": {
652
+ "description": {
653
+ "type": "object",
654
+ "description": "Optional BindingContract when description is bound to the data model."
655
+ },
656
+ "title": {
657
+ "type": "object",
658
+ "description": "Optional BindingContract when title is bound to the data model."
659
+ }
660
+ },
661
+ "llmGuidance": [
662
+ "Use Item for list rows and summary entries with title, optional description, and optional trailing action.",
663
+ "Item is primarily a display component; action and actionLabel are optional enhancements, not required for a valid Item.",
664
+ "For a live Switch/Input summary in an Item, bind description (or title) with { path } to the same path as Switch.checked or Input.value — booleans display as ON/OFF.",
665
+ "Do not use Item for form inputs; use Input or Switch instead."
666
+ ]
667
+ },
668
+ {
669
+ "name": "Label",
670
+ "description": "Accessible text for static copy or a live data-model value. Use a plain string for fixed captions, or BindingContract { path } for values that update with Input/Switch edits.",
671
+ "version": "1.0.0",
672
+ "implementation": {
673
+ "source": "shadcn",
674
+ "base": "base",
675
+ "sourceVersion": "4.17.0"
676
+ },
677
+ "props": {
678
+ "text": {
679
+ "type": "string",
680
+ "required": true,
681
+ "description": "Visible text: plain string, or BindingContract { path, mode? } for a live bound value. Not a React child tree."
682
+ },
683
+ "htmlFor": {
684
+ "type": "string",
685
+ "required": false,
686
+ "description": "Optional target control id when associating with another catalog control."
687
+ }
688
+ },
689
+ "allowedChildren": "none",
690
+ "supportedBy": [
691
+ "surface"
692
+ ],
693
+ "actions": {},
694
+ "events": [],
695
+ "dataBindings": {
696
+ "text": {
697
+ "type": "object",
698
+ "description": "Optional BindingContract when text is bound to the data model."
699
+ }
700
+ },
701
+ "llmGuidance": [
702
+ "Static captions use text as a plain string.",
703
+ "For values that should update when Input/Switch change, set text to BindingContract { path } pointing at the same path as the control (e.g. Input value.path or Switch checked.path).",
704
+ "Do not invent template strings like \"Status: {value}\"; use a static Label for the caption and a bound Label for the live value, or rely on Input.label / Switch.label."
705
+ ]
706
+ },
707
+ {
708
+ "name": "Switch",
709
+ "description": "Boolean toggle bound to the surface data model via BindingContract.",
710
+ "version": "1.0.0",
711
+ "implementation": {
712
+ "source": "shadcn",
713
+ "base": "base",
714
+ "sourceVersion": "4.17.0"
715
+ },
716
+ "props": {
717
+ "label": {
718
+ "type": "string",
719
+ "required": true,
720
+ "description": "Accessible label rendered beside the control."
721
+ },
722
+ "checked": {
723
+ "type": "object",
724
+ "required": false,
725
+ "description": "BindingContract: boolean path in the draft store.",
726
+ "properties": {
727
+ "path": {
728
+ "type": "string",
729
+ "required": true,
730
+ "description": "Data-model path, e.g. /settings/notifications."
731
+ },
732
+ "mode": {
733
+ "type": "string",
734
+ "required": false,
735
+ "default": "readWrite",
736
+ "enum": [
737
+ "read",
738
+ "write",
739
+ "readWrite"
740
+ ]
741
+ }
742
+ }
743
+ },
744
+ "disabled": {
745
+ "type": "boolean",
746
+ "required": false,
747
+ "default": false,
748
+ "description": "Disables interaction. Also forced when binding mode is read."
749
+ }
750
+ },
751
+ "allowedChildren": "none",
752
+ "supportedBy": [
753
+ "surface"
754
+ ],
755
+ "actions": {},
756
+ "events": [],
757
+ "dataBindings": {
758
+ "checked": {
759
+ "type": "object",
760
+ "description": "Same schema as props.checked (BindingContract)."
761
+ }
762
+ },
763
+ "llmGuidance": [
764
+ "Switch is the boolean toggle for simple settings. Use checked: { path } to bind to the data model.",
765
+ "Use Input for text entry and Switch for on/off settings on the same surface."
766
+ ]
767
+ },
768
+ {
769
+ "name": "Tabs",
770
+ "description": "Tabbed container that switches between catalog child panels. Each tab links a title to an existing child component id.",
771
+ "version": "1.0.0",
772
+ "implementation": {
773
+ "source": "shadcn",
774
+ "base": "base",
775
+ "sourceVersion": "4.17.0"
776
+ },
777
+ "props": {
778
+ "tabs": {
779
+ "type": "array",
780
+ "required": true,
781
+ "description": "Non-empty array of { title, child } entries. title is visible copy; child is the panel component id.",
782
+ "items": {
783
+ "type": "object"
784
+ }
785
+ },
786
+ "defaultTab": {
787
+ "type": "string",
788
+ "required": false,
789
+ "description": "Child component id for the initially selected tab. Defaults to the first tab entry."
790
+ }
791
+ },
792
+ "allowedChildren": "any",
793
+ "supportedBy": [
794
+ "surface"
795
+ ],
796
+ "actions": {},
797
+ "events": [],
798
+ "dataBindings": {},
799
+ "llmGuidance": [
800
+ "Tabs uses properties.tabs: a non-empty array of { title, child } entries.",
801
+ "Provide one nested panel component per tab in components[] (same order as tabs).",
802
+ "Set each tabs[].child to the panel component id (for example tab1, tab2, tab3).",
803
+ "Use string titles or {\"path\":\"...\"} for dynamic titles bound to the data model — tab trigger text is tabs[].title, not a separate Label control.",
804
+ "Do not use properties.children on Tabs; panel content is referenced by child ids."
805
+ ]
806
+ }
807
+ ],
808
+ "screenTypes": [
809
+ "dashboard",
810
+ "form",
811
+ "summary",
812
+ "confirmation",
813
+ "details",
814
+ "screen",
815
+ "chart"
816
+ ]
817
+ }