@letsprogram/ng-oat-mcp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,647 @@
1
+ export const COMPONENTS = [
2
+ // ─── Core Components ───
3
+ {
4
+ name: 'NgOatButton',
5
+ selector: 'ng-oat-button',
6
+ import: "import { NgOatButton } from '@letsprogram/ng-oat';",
7
+ category: 'component',
8
+ description: 'Button with variant, style, and size options. Supports icon-only mode.',
9
+ inputs: [
10
+ { name: 'variant', type: "'default' | 'secondary' | 'danger'", default: "'default'" },
11
+ { name: 'btnStyle', type: "'filled' | 'outline' | 'ghost'", default: "'filled'" },
12
+ { name: 'size', type: "'default' | 'small' | 'large'", default: "'default'" },
13
+ { name: 'icon', type: 'boolean', default: 'false' },
14
+ { name: 'type', type: "'button' | 'submit' | 'reset'", default: "'button'" },
15
+ { name: 'disabled', type: 'boolean', default: 'false' },
16
+ { name: 'ariaLabel', type: 'string', default: "''" },
17
+ ],
18
+ outputs: [{ name: 'clicked', type: 'MouseEvent' }],
19
+ contentSlots: ['default (button label/icon)'],
20
+ example: `<ng-oat-button variant="default" btnStyle="filled" (clicked)="onSave()">Save</ng-oat-button>`,
21
+ },
22
+ {
23
+ name: 'NgOatSplitButton',
24
+ selector: 'ng-oat-split-button',
25
+ import: "import { NgOatSplitButton } from '@letsprogram/ng-oat';",
26
+ category: 'component',
27
+ description: 'Split button with primary action and dropdown menu. Popover-based with keyboard nav.',
28
+ inputs: [
29
+ { name: 'label', type: 'string', default: 'required' },
30
+ { name: 'variant', type: "'default' | 'secondary' | 'danger'", default: "'default'" },
31
+ { name: 'btnStyle', type: "'filled' | 'outline' | 'ghost'", default: "'filled'" },
32
+ { name: 'size', type: "'default' | 'small' | 'large'", default: "'default'" },
33
+ { name: 'disabled', type: 'boolean', default: 'false' },
34
+ ],
35
+ outputs: [{ name: 'clicked', type: 'MouseEvent' }],
36
+ contentSlots: ['[role="menuitem"] elements for dropdown items'],
37
+ example: `<ng-oat-split-button label="Save" (clicked)="onSave()">\n <button role="menuitem">Save as Draft</button>\n <button role="menuitem">Save & Publish</button>\n</ng-oat-split-button>`,
38
+ },
39
+ {
40
+ name: 'NgOatBadge',
41
+ selector: 'ng-oat-badge',
42
+ import: "import { NgOatBadge } from '@letsprogram/ng-oat';",
43
+ category: 'component',
44
+ description: 'Inline badge/tag with variant colors.',
45
+ inputs: [{ name: 'variant', type: "'default' | 'secondary' | 'outline' | 'danger' | 'success'", default: "'default'" }],
46
+ outputs: [],
47
+ contentSlots: ['default (badge text)'],
48
+ example: `<ng-oat-badge variant="success">Active</ng-oat-badge>`,
49
+ },
50
+ {
51
+ name: 'NgOatAlert',
52
+ selector: 'ng-oat-alert',
53
+ import: "import { NgOatAlert } from '@letsprogram/ng-oat';",
54
+ category: 'component',
55
+ description: 'Alert banner with variant, size, and optional dismiss button. Has role="alert".',
56
+ inputs: [
57
+ { name: 'variant', type: "'default' | 'success' | 'danger' | 'warning'", default: "'default'" },
58
+ { name: 'size', type: "'compact' | 'default' | 'comfortable'", default: "'default'" },
59
+ { name: 'dismissible', type: 'boolean', default: 'false' },
60
+ ],
61
+ outputs: [{ name: 'dismissed', type: 'void' }],
62
+ contentSlots: ['default (alert body)'],
63
+ example: `<ng-oat-alert variant="success" [dismissible]="true" (dismissed)="onDismiss()">Changes saved.</ng-oat-alert>`,
64
+ },
65
+ {
66
+ name: 'NgOatCard',
67
+ selector: 'ng-oat-card',
68
+ import: "import { NgOatCard, NgOatCardHeader, NgOatCardFooter } from '@letsprogram/ng-oat';",
69
+ category: 'component',
70
+ description: 'Card container with optional header and footer sub-components.',
71
+ inputs: [],
72
+ outputs: [],
73
+ contentSlots: ['ng-oat-card-header', 'default (body)', 'ng-oat-card-footer'],
74
+ example: `<ng-oat-card>\n <ng-oat-card-header><h3>Title</h3></ng-oat-card-header>\n <p>Body</p>\n <ng-oat-card-footer><ng-oat-button>Action</ng-oat-button></ng-oat-card-footer>\n</ng-oat-card>`,
75
+ },
76
+ {
77
+ name: 'NgOatAccordion',
78
+ selector: 'ng-oat-accordion',
79
+ import: "import { NgOatAccordion } from '@letsprogram/ng-oat';",
80
+ category: 'component',
81
+ description: 'Accordion with collapsible sections. Items: { title, content, open? }.',
82
+ inputs: [
83
+ { name: 'items', type: 'NgOatAccordionItem[]', default: 'required' },
84
+ { name: 'group', type: 'string | undefined', default: 'undefined' },
85
+ ],
86
+ outputs: [{ name: 'toggled', type: '{ item: NgOatAccordionItem; open: boolean }' }],
87
+ example: `<ng-oat-accordion [items]="[{ title: 'FAQ 1', content: 'Answer 1' }]" />`,
88
+ },
89
+ {
90
+ name: 'NgOatTable',
91
+ selector: 'ng-oat-table',
92
+ import: "import { NgOatTable } from '@letsprogram/ng-oat';",
93
+ category: 'component',
94
+ description: 'Data table with columns, optional striping, row click, and scroll support.',
95
+ inputs: [
96
+ { name: 'columns', type: 'NgOatTableColumn[]', default: 'required' },
97
+ { name: 'data', type: 'Record<string, any>[]', default: 'required' },
98
+ { name: 'striped', type: 'boolean', default: 'false' },
99
+ { name: 'clickable', type: 'boolean', default: 'false' },
100
+ { name: 'emptyText', type: 'string', default: "'No data available.'" },
101
+ { name: 'scrollX', type: 'boolean', default: 'false' },
102
+ { name: 'scrollY', type: 'string', default: "''" },
103
+ ],
104
+ outputs: [{ name: 'rowClick', type: 'Record<string, any>' }],
105
+ notes: 'NgOatTableColumn: { key: string; label: string; width?: string; align?: string; render?: (val, row) => string }',
106
+ example: `<ng-oat-table [columns]="cols" [data]="rows" [striped]="true" (rowClick)="onRow($event)" />`,
107
+ },
108
+ {
109
+ name: 'NgOatBreadcrumb',
110
+ selector: 'ng-oat-breadcrumb',
111
+ import: "import { NgOatBreadcrumb, NgOatBreadcrumbIcon } from '@letsprogram/ng-oat';",
112
+ category: 'component',
113
+ description: 'Breadcrumb navigation. Supports content-projected icons via NgOatBreadcrumbIcon directive.',
114
+ inputs: [{ name: 'items', type: 'OatBreadcrumbItem[]', default: 'required' }],
115
+ outputs: [{ name: 'navigate', type: 'OatBreadcrumbItem' }],
116
+ contentSlots: ['ng-template[ngOatBreadcrumbIcon] — template context: $implicit = icon string'],
117
+ notes: 'OatBreadcrumbItem: { label: string; url?: string; icon?: string }',
118
+ example: `<ng-oat-breadcrumb [items]="crumbs" (navigate)="onNav($event)">\n <ng-template ngOatBreadcrumbIcon let-iconKey>\n <lucide-icon [name]="iconKey" [size]="16" />\n </ng-template>\n</ng-oat-breadcrumb>`,
119
+ },
120
+ {
121
+ name: 'NgOatPagination',
122
+ selector: 'ng-oat-pagination',
123
+ import: "import { NgOatPagination } from '@letsprogram/ng-oat';",
124
+ category: 'component',
125
+ description: 'Page navigation with configurable visible page count.',
126
+ inputs: [
127
+ { name: 'totalPages', type: 'number', default: 'required' },
128
+ { name: 'currentPage', type: 'number', default: '1' },
129
+ { name: 'maxVisible', type: 'number', default: '5' },
130
+ ],
131
+ outputs: [{ name: 'pageChange', type: 'number' }],
132
+ example: `<ng-oat-pagination [totalPages]="20" [currentPage]="page" (pageChange)="page = $event" />`,
133
+ },
134
+ {
135
+ name: 'NgOatProgress',
136
+ selector: 'ng-oat-progress',
137
+ import: "import { NgOatProgress } from '@letsprogram/ng-oat';",
138
+ category: 'component',
139
+ description: 'Determinate progress bar.',
140
+ inputs: [
141
+ { name: 'value', type: 'number', default: 'required' },
142
+ { name: 'max', type: 'number', default: '100' },
143
+ ],
144
+ outputs: [],
145
+ example: `<ng-oat-progress [value]="65" />`,
146
+ },
147
+ {
148
+ name: 'NgOatMeter',
149
+ selector: 'ng-oat-meter',
150
+ import: "import { NgOatMeter } from '@letsprogram/ng-oat';",
151
+ category: 'component',
152
+ description: 'Meter gauge for scalar measurements with low/high/optimum ranges.',
153
+ inputs: [
154
+ { name: 'value', type: 'number', default: 'required' },
155
+ { name: 'min', type: 'number', default: '0' },
156
+ { name: 'max', type: 'number', default: '1' },
157
+ { name: 'low', type: 'number | undefined', default: 'undefined' },
158
+ { name: 'high', type: 'number | undefined', default: 'undefined' },
159
+ { name: 'optimum', type: 'number | undefined', default: 'undefined' },
160
+ ],
161
+ outputs: [],
162
+ example: `<ng-oat-meter [value]="0.7" [low]="0.3" [high]="0.8" />`,
163
+ },
164
+ {
165
+ name: 'NgOatSpinner',
166
+ selector: 'ng-oat-spinner',
167
+ import: "import { NgOatSpinner } from '@letsprogram/ng-oat';",
168
+ category: 'component',
169
+ description: 'Loading spinner with optional overlay mode. Has aria-busy="true".',
170
+ inputs: [
171
+ { name: 'size', type: "'small' | 'default' | 'large'", default: "'default'" },
172
+ { name: 'overlay', type: 'boolean', default: 'false' },
173
+ ],
174
+ outputs: [],
175
+ contentSlots: ['default (loading text)'],
176
+ example: `<ng-oat-spinner size="large" />\n<ng-oat-spinner [overlay]="true">Loading...</ng-oat-spinner>`,
177
+ },
178
+ {
179
+ name: 'NgOatSwitch',
180
+ selector: 'ng-oat-switch',
181
+ import: "import { NgOatSwitch } from '@letsprogram/ng-oat';",
182
+ category: 'component',
183
+ description: 'Toggle switch. Implements FormCheckboxControl for Signal Forms.',
184
+ inputs: [
185
+ { name: 'label', type: 'string', default: "''" },
186
+ { name: 'checked', type: 'boolean', default: 'false', kind: 'model' },
187
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
188
+ ],
189
+ outputs: [{ name: 'changed', type: 'boolean' }],
190
+ example: `<ng-oat-switch label="Dark mode" [(checked)]="isDark" />`,
191
+ },
192
+ {
193
+ name: 'NgOatSkeleton',
194
+ selector: 'ng-oat-skeleton',
195
+ import: "import { NgOatSkeleton } from '@letsprogram/ng-oat';",
196
+ category: 'component',
197
+ description: 'Skeleton placeholder for loading states. Line or box type.',
198
+ inputs: [
199
+ { name: 'type', type: "'line' | 'box'", default: "'line'" },
200
+ { name: 'width', type: 'string | undefined', default: 'undefined' },
201
+ ],
202
+ outputs: [],
203
+ example: `<ng-oat-skeleton />\n<ng-oat-skeleton type="box" width="200px" />`,
204
+ },
205
+ {
206
+ name: 'NgOatAvatar',
207
+ selector: 'ng-oat-avatar',
208
+ import: "import { NgOatAvatar } from '@letsprogram/ng-oat';",
209
+ category: 'component',
210
+ description: 'Avatar with image, initials fallback, or placeholder. Auto-generates initials from alt.',
211
+ inputs: [
212
+ { name: 'src', type: 'string', default: "''" },
213
+ { name: 'alt', type: 'string', default: "''" },
214
+ { name: 'initials', type: 'string', default: "''" },
215
+ { name: 'fallback', type: 'string', default: "''" },
216
+ { name: 'size', type: "'sm' | 'default' | 'lg' | 'xl'", default: "'default'" },
217
+ ],
218
+ outputs: [],
219
+ example: `<ng-oat-avatar src="/avatar.jpg" alt="Jane Doe" size="lg" />`,
220
+ },
221
+ {
222
+ name: 'NgOatSeparator',
223
+ selector: 'ng-oat-separator',
224
+ import: "import { NgOatSeparator } from '@letsprogram/ng-oat';",
225
+ category: 'component',
226
+ description: 'Horizontal or vertical divider line, with optional label.',
227
+ inputs: [
228
+ { name: 'orientation', type: "'horizontal' | 'vertical'", default: "'horizontal'" },
229
+ { name: 'label', type: 'string', default: "''" },
230
+ ],
231
+ outputs: [],
232
+ example: `<ng-oat-separator label="OR" />`,
233
+ },
234
+ {
235
+ name: 'NgOatFileUpload',
236
+ selector: 'ng-oat-file-upload',
237
+ import: "import { NgOatFileUpload } from '@letsprogram/ng-oat';",
238
+ category: 'component',
239
+ description: 'Drag-and-drop file upload with click-to-browse fallback.',
240
+ inputs: [
241
+ { name: 'accept', type: 'string', default: "''" },
242
+ { name: 'multiple', type: 'boolean', default: 'false' },
243
+ { name: 'maxSize', type: 'number', default: '0' },
244
+ { name: 'disabled', type: 'boolean', default: 'false' },
245
+ { name: 'label', type: 'string', default: "''" },
246
+ ],
247
+ outputs: [{ name: 'filesSelected', type: 'File[]' }],
248
+ methods: ['openFilePicker()', 'removeFile(index)'],
249
+ example: `<ng-oat-file-upload accept="image/*" [multiple]="true" [maxSize]="5242880" (filesSelected)="onFiles($event)" />`,
250
+ },
251
+ {
252
+ name: 'NgOatInputOtp',
253
+ selector: 'ng-oat-input-otp',
254
+ import: "import { NgOatInputOtp } from '@letsprogram/ng-oat';",
255
+ category: 'component',
256
+ description: 'OTP input with configurable length, separator, and mask. Signal Forms compatible.',
257
+ inputs: [
258
+ { name: 'length', type: 'number', default: '6' },
259
+ { name: 'separator', type: 'number', default: '0' },
260
+ { name: 'mask', type: 'boolean', default: 'false' },
261
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
262
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
263
+ ],
264
+ outputs: [],
265
+ methods: ['focus()'],
266
+ example: `<ng-oat-input-otp [length]="6" [separator]="3" [(value)]="otp" />`,
267
+ },
268
+ {
269
+ name: 'NgOatSearchInput',
270
+ selector: 'ng-oat-search-input',
271
+ import: "import { NgOatSearchInput } from '@letsprogram/ng-oat';",
272
+ category: 'component',
273
+ description: 'Search input with debounce, clear button, and optional keyboard shortcut.',
274
+ inputs: [
275
+ { name: 'placeholder', type: 'string', default: "'Search...'" },
276
+ { name: 'shortcut', type: 'string', default: "''" },
277
+ { name: 'debounceMs', type: 'number', default: '300' },
278
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
279
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
280
+ ],
281
+ outputs: [{ name: 'search', type: 'string' }],
282
+ methods: ['clear()', 'focus()'],
283
+ example: `<ng-oat-search-input placeholder="Search users..." shortcut="⌘K" (search)="onSearch($event)" />`,
284
+ },
285
+ {
286
+ name: 'NgOatCarousel',
287
+ selector: 'ng-oat-carousel',
288
+ import: "import { NgOatCarousel } from '@letsprogram/ng-oat';",
289
+ category: 'component',
290
+ description: 'Image carousel with autoplay, loop, touch/drag, keyboard support.',
291
+ inputs: [
292
+ { name: 'slides', type: 'NgOatCarouselSlide[]', default: '[]' },
293
+ { name: 'autoplay', type: 'boolean', default: 'false' },
294
+ { name: 'interval', type: 'number', default: '5000' },
295
+ { name: 'loop', type: 'boolean', default: 'true' },
296
+ { name: 'showArrows', type: 'boolean', default: 'true' },
297
+ { name: 'showDots', type: 'boolean', default: 'true' },
298
+ { name: 'aspectRatio', type: "'auto' | '16:9' | '4:3' | '1:1'", default: "'auto'" },
299
+ { name: 'activeIndex', type: 'number', default: '0', kind: 'model' },
300
+ ],
301
+ outputs: [{ name: 'slideChange', type: 'number' }],
302
+ methods: ['next()', 'prev()', 'goTo(index)'],
303
+ notes: 'NgOatCarouselSlide: { src: string; alt?: string; caption?: string }',
304
+ example: `<ng-oat-carousel [slides]="slides" [autoplay]="true" aspectRatio="16:9" />`,
305
+ },
306
+ {
307
+ name: 'NgOatCardCarousel',
308
+ selector: 'ng-oat-card-carousel',
309
+ import: "import { NgOatCardCarousel } from '@letsprogram/ng-oat';",
310
+ category: 'component',
311
+ description: 'Horizontal scrollable product card carousel.',
312
+ inputs: [
313
+ { name: 'heading', type: 'string', default: "''" },
314
+ { name: 'ariaLabel', type: 'string', default: "'Product carousel'" },
315
+ { name: 'items', type: 'NgOatProductCard[]', default: '[]' },
316
+ { name: 'showSeeAll', type: 'boolean', default: 'false' },
317
+ ],
318
+ outputs: [
319
+ { name: 'seeAllClick', type: 'void' },
320
+ { name: 'cardClick', type: 'NgOatProductCard' },
321
+ ],
322
+ methods: ['scrollNext()', 'scrollPrev()'],
323
+ notes: 'NgOatProductCard: { title: string; image: string; price?: string; description?: string }',
324
+ example: `<ng-oat-card-carousel heading="Featured" [items]="products" (cardClick)="onCard($event)" />`,
325
+ },
326
+ {
327
+ name: 'NgOatToolbar',
328
+ selector: 'ng-oat-toolbar',
329
+ import: "import { NgOatToolbar, NgOatToolbarRow } from '@letsprogram/ng-oat';",
330
+ category: 'component',
331
+ description: 'App toolbar/header bar with color, density, and fixed positioning.',
332
+ inputs: [
333
+ { name: 'color', type: "'default' | 'primary' | 'accent'", default: "'default'" },
334
+ { name: 'dense', type: 'boolean', default: 'false' },
335
+ { name: 'fixed', type: 'boolean', default: 'true' },
336
+ ],
337
+ outputs: [],
338
+ contentSlots: ['[toolbarStart]', 'default', '[toolbarEnd]', 'ng-oat-toolbar-row (multi-row)'],
339
+ example: `<ng-oat-toolbar color="primary">\n <span toolbarStart>My App</span>\n <ng-oat-button toolbarEnd [icon]="true">☰</ng-oat-button>\n</ng-oat-toolbar>`,
340
+ },
341
+ {
342
+ name: 'NgOatThemeSelector',
343
+ selector: 'ng-oat-theme-selector',
344
+ import: "import { NgOatThemeSelector } from '@letsprogram/ng-oat';",
345
+ category: 'component',
346
+ description: 'Theme switcher (light/dark/system) as dropdown or toggle. Persists to localStorage.',
347
+ inputs: [
348
+ { name: 'mode', type: "'dropdown' | 'toggle'", default: "'dropdown'" },
349
+ { name: 'initialTheme', type: 'NgOatTheme | undefined', default: 'undefined' },
350
+ { name: 'themes', type: 'NgOatThemeOption[]', default: '[light, dark, system]' },
351
+ ],
352
+ outputs: [{ name: 'themeChange', type: "NgOatTheme ('light' | 'dark' | 'system')" }],
353
+ methods: ['setTheme()', 'pick()', 'toggleOpen()'],
354
+ example: `<ng-oat-theme-selector mode="toggle" (themeChange)="onTheme($event)" />`,
355
+ },
356
+ {
357
+ name: 'NgOatToggle',
358
+ selector: 'ng-oat-toggle',
359
+ import: "import { NgOatToggle } from '@letsprogram/ng-oat';",
360
+ category: 'component',
361
+ description: 'Toggle button with pressed state. Standalone or inside ToggleGroup.',
362
+ inputs: [
363
+ { name: 'variant', type: "'default' | 'outline'", default: "'default'" },
364
+ { name: 'size', type: "'sm' | 'default' | 'lg'", default: "'default'" },
365
+ { name: 'disabled', type: 'boolean', default: 'false' },
366
+ { name: 'toggleValue', type: 'string', default: "''" },
367
+ { name: 'pressed', type: 'boolean', default: 'false', kind: 'model' },
368
+ ],
369
+ outputs: [{ name: 'pressedChange', type: 'boolean' }],
370
+ contentSlots: ['default (button label)'],
371
+ example: `<ng-oat-toggle [(pressed)]="isBold">Bold</ng-oat-toggle>`,
372
+ },
373
+ {
374
+ name: 'NgOatToggleGroup',
375
+ selector: 'ng-oat-toggle-group',
376
+ import: "import { NgOatToggleGroup } from '@letsprogram/ng-oat';",
377
+ category: 'component',
378
+ description: 'Group of toggle buttons. Single or multi-select.',
379
+ inputs: [
380
+ { name: 'multiple', type: 'boolean', default: 'false' },
381
+ { name: 'disabled', type: 'boolean', default: 'false' },
382
+ { name: 'variant', type: "'default' | 'outline'", default: "'default'" },
383
+ { name: 'size', type: "'sm' | 'default' | 'lg'", default: "'default'" },
384
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
385
+ ],
386
+ outputs: [],
387
+ contentSlots: ['ng-oat-toggle children'],
388
+ example: `<ng-oat-toggle-group [(value)]="align">\n <ng-oat-toggle toggleValue="left">Left</ng-oat-toggle>\n <ng-oat-toggle toggleValue="center">Center</ng-oat-toggle>\n</ng-oat-toggle-group>`,
389
+ },
390
+ {
391
+ name: 'NgOatChip',
392
+ selector: 'ng-oat-chip',
393
+ import: "import { NgOatChip, NgOatChipGroup, NgOatChipInput } from '@letsprogram/ng-oat';",
394
+ category: 'component',
395
+ description: 'Chip/tag with variants, selectable and removable modes.',
396
+ inputs: [
397
+ { name: 'variant', type: "'default' | 'secondary' | 'outline' | 'success' | 'warning' | 'danger'", default: "'default'" },
398
+ { name: 'size', type: "'sm' | 'default' | 'lg'", default: "'default'" },
399
+ { name: 'removable', type: 'boolean', default: 'false' },
400
+ { name: 'selectable', type: 'boolean', default: 'false' },
401
+ { name: 'chipValue', type: 'string', default: "''" },
402
+ { name: 'label', type: 'string', default: "''" },
403
+ { name: 'selected', type: 'boolean', default: 'false', kind: 'model' },
404
+ ],
405
+ outputs: [
406
+ { name: 'removed', type: 'void' },
407
+ { name: 'selectedChange', type: 'boolean' },
408
+ ],
409
+ contentSlots: ['default (chip text)', '[chipIcon] slot'],
410
+ example: `<ng-oat-chip variant="success" [removable]="true" (removed)="onRemove()">Tag</ng-oat-chip>`,
411
+ },
412
+ {
413
+ name: 'NgOatChipGroup',
414
+ selector: 'ng-oat-chip-group',
415
+ import: "import { NgOatChipGroup } from '@letsprogram/ng-oat';",
416
+ category: 'component',
417
+ description: 'Group of chips with single/multi selection state.',
418
+ inputs: [
419
+ { name: 'multiple', type: 'boolean', default: 'false' },
420
+ { name: 'ariaLabel', type: 'string', default: "''" },
421
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
422
+ ],
423
+ outputs: [{ name: 'chipRemoved', type: 'string' }],
424
+ contentSlots: ['ng-oat-chip children'],
425
+ example: `<ng-oat-chip-group [(value)]="selected">\n <ng-oat-chip chipValue="a" [selectable]="true">A</ng-oat-chip>\n <ng-oat-chip chipValue="b" [selectable]="true">B</ng-oat-chip>\n</ng-oat-chip-group>`,
426
+ },
427
+ {
428
+ name: 'NgOatChipInput',
429
+ selector: 'ng-oat-chip-input',
430
+ import: "import { NgOatChipInput } from '@letsprogram/ng-oat';",
431
+ category: 'component',
432
+ description: 'Input that creates chips on Enter. Supports max count and duplicate control.',
433
+ inputs: [
434
+ { name: 'placeholder', type: 'string', default: "'Add item...'" },
435
+ { name: 'disabled', type: 'boolean', default: 'false' },
436
+ { name: 'variant', type: 'NgOatChipVariant', default: "'default'" },
437
+ { name: 'allowDuplicates', type: 'boolean', default: 'false' },
438
+ { name: 'maxChips', type: 'number', default: 'Infinity' },
439
+ { name: 'chips', type: 'string[]', default: '[]', kind: 'model' },
440
+ ],
441
+ outputs: [
442
+ { name: 'chipAdded', type: 'string' },
443
+ { name: 'chipRemovedEvent', type: 'string' },
444
+ ],
445
+ example: `<ng-oat-chip-input [(chips)]="tags" placeholder="Add tag..." [maxChips]="5" />`,
446
+ },
447
+ // ─── Directive Wrappers ───
448
+ {
449
+ name: 'NgOatDropdownComponent',
450
+ selector: 'ng-oat-dropdown',
451
+ import: "import { NgOatDropdownComponent } from '@letsprogram/ng-oat';",
452
+ category: 'directive-wrapper',
453
+ description: 'Component wrapper for Oat dropdown. Popover-based with keyboard nav.',
454
+ inputs: [],
455
+ outputs: [{ name: 'openChange', type: 'boolean' }],
456
+ methods: ['open()', 'close()', 'toggle()'],
457
+ contentSlots: ['[trigger] button', '[role="menuitem"] items'],
458
+ example: `<ng-oat-dropdown>\n <button trigger>Menu</button>\n <button role="menuitem">Option 1</button>\n</ng-oat-dropdown>`,
459
+ },
460
+ {
461
+ name: 'NgOatTooltipComponent',
462
+ selector: 'ng-oat-tooltip',
463
+ import: "import { NgOatTooltipComponent } from '@letsprogram/ng-oat';",
464
+ category: 'directive-wrapper',
465
+ description: 'Component wrapper for tooltips. Plain text or rich template content.',
466
+ inputs: [
467
+ { name: 'text', type: 'string', default: "''" },
468
+ { name: 'template', type: 'TemplateRef<any> | undefined', default: 'undefined' },
469
+ { name: 'position', type: "'top' | 'bottom' | 'left' | 'right'", default: "'top'" },
470
+ { name: 'delay', type: 'number', default: '700' },
471
+ { name: 'disabled', type: 'boolean', default: 'false' },
472
+ ],
473
+ outputs: [],
474
+ methods: ['show()', 'hide()'],
475
+ contentSlots: ['default (trigger element)'],
476
+ example: `<ng-oat-tooltip text="Hello!">\n <button>Hover me</button>\n</ng-oat-tooltip>`,
477
+ },
478
+ {
479
+ name: 'NgOatSidebarComponent',
480
+ selector: 'ng-oat-sidebar',
481
+ import: "import { NgOatSidebarComponent } from '@letsprogram/ng-oat';",
482
+ category: 'directive-wrapper',
483
+ description: 'Sidebar layout with fixed or overlay mode.',
484
+ inputs: [
485
+ { name: 'mode', type: "'fixed' | 'overlay'", default: "'fixed'" },
486
+ { name: 'scrollLock', type: 'boolean', default: 'true' },
487
+ { name: 'initialOpen', type: 'boolean', default: 'false' },
488
+ ],
489
+ outputs: [{ name: 'openChange', type: 'boolean' }],
490
+ methods: ['open()', 'close()', 'toggle()'],
491
+ contentSlots: ['aside[data-sidebar]', 'main'],
492
+ example: `<ng-oat-sidebar mode="overlay">\n <aside data-sidebar>Nav</aside>\n <main>Content</main>\n</ng-oat-sidebar>`,
493
+ },
494
+ {
495
+ name: 'NgOatTabsComponent',
496
+ selector: 'ng-oat-tabs',
497
+ import: "import { NgOatTabsComponent } from '@letsprogram/ng-oat';",
498
+ category: 'directive-wrapper',
499
+ description: 'Tabbed interface. Pass tab labels, project panel divs as children.',
500
+ inputs: [{ name: 'tabs', type: '(string | NgOatTabItem)[]', default: 'required' }],
501
+ outputs: [{ name: 'tabChange', type: '{ index: number; tab: HTMLElement }' }],
502
+ methods: ['selectTab(index)'],
503
+ contentSlots: ['div children (one per tab panel)'],
504
+ notes: 'NgOatTabItem: { label: string; disabled?: boolean }',
505
+ example: `<ng-oat-tabs [tabs]="['Tab 1', 'Tab 2']">\n <div>Content 1</div>\n <div>Content 2</div>\n</ng-oat-tabs>`,
506
+ },
507
+ {
508
+ name: 'NgOatDialogComponent',
509
+ selector: 'ng-oat-dialog',
510
+ import: "import { NgOatDialogComponent } from '@letsprogram/ng-oat';",
511
+ category: 'directive-wrapper',
512
+ description: 'Modal dialog wrapping native <dialog>. Header/footer slots.',
513
+ inputs: [],
514
+ outputs: [{ name: 'closed', type: 'string' }],
515
+ methods: ['showModal()', 'show()', 'close(returnValue?)'],
516
+ contentSlots: ['[header]', 'default (body)', '[footer]'],
517
+ example: `<ng-oat-dialog #dlg>\n <h2 header>Title</h2>\n <p>Content</p>\n <div footer><ng-oat-button (clicked)="dlg.close()">Close</ng-oat-button></div>\n</ng-oat-dialog>`,
518
+ },
519
+ // ─── Signal Forms Fields ───
520
+ {
521
+ name: 'NgOatInput',
522
+ selector: 'ng-oat-input',
523
+ import: "import { NgOatInput } from '@letsprogram/ng-oat';",
524
+ category: 'form',
525
+ description: 'Text input field for Signal Forms. Supports many HTML input types.',
526
+ inputs: [
527
+ { name: 'label', type: 'string', default: "''" },
528
+ {
529
+ name: 'type',
530
+ type: "'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'datetime-local' | 'time' | 'month' | 'week' | 'color'",
531
+ default: "'text'",
532
+ },
533
+ { name: 'placeholder', type: 'string', default: "''" },
534
+ { name: 'readonly', type: 'boolean', default: 'false' },
535
+ { name: 'required', type: 'boolean', default: 'false' },
536
+ { name: 'invalid', type: 'boolean', default: 'false' },
537
+ { name: 'showErrors', type: 'boolean', default: 'true' },
538
+ { name: 'min', type: 'number | undefined', default: 'undefined' },
539
+ { name: 'max', type: 'number | undefined', default: 'undefined' },
540
+ { name: 'minLength', type: 'number | undefined', default: 'undefined' },
541
+ { name: 'maxLength', type: 'number | undefined', default: 'undefined' },
542
+ { name: 'autocomplete', type: 'string | undefined', default: 'undefined' },
543
+ { name: 'errors', type: 'ValidationError[]', default: '[]' },
544
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
545
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
546
+ { name: 'touched', type: 'boolean', default: 'false', kind: 'model' },
547
+ ],
548
+ outputs: [],
549
+ methods: ['focus()'],
550
+ example: `<ng-oat-input label="Email" type="email" placeholder="you@example.com" [(value)]="email" [required]="true" />`,
551
+ },
552
+ {
553
+ name: 'NgOatTextarea',
554
+ selector: 'ng-oat-textarea',
555
+ import: "import { NgOatTextarea } from '@letsprogram/ng-oat';",
556
+ category: 'form',
557
+ description: 'Multi-line text input for Signal Forms.',
558
+ inputs: [
559
+ { name: 'label', type: 'string', default: "''" },
560
+ { name: 'placeholder', type: 'string', default: "''" },
561
+ { name: 'rows', type: 'number', default: '4' },
562
+ { name: 'readonly', type: 'boolean', default: 'false' },
563
+ { name: 'required', type: 'boolean', default: 'false' },
564
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
565
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
566
+ ],
567
+ outputs: [],
568
+ methods: ['focus()'],
569
+ example: `<ng-oat-textarea label="Bio" [rows]="6" [(value)]="bio" />`,
570
+ },
571
+ {
572
+ name: 'NgOatSelect',
573
+ selector: 'ng-oat-select',
574
+ import: "import { NgOatSelect } from '@letsprogram/ng-oat';",
575
+ category: 'form',
576
+ description: 'Dropdown select for Signal Forms.',
577
+ inputs: [
578
+ { name: 'label', type: 'string', default: "''" },
579
+ { name: 'placeholder', type: 'string', default: "''" },
580
+ { name: 'options', type: 'NgOatSelectOption[]', default: 'required' },
581
+ { name: 'required', type: 'boolean', default: 'false' },
582
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
583
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
584
+ ],
585
+ outputs: [],
586
+ methods: ['focus()'],
587
+ notes: 'NgOatSelectOption: { label: string; value: string; disabled?: boolean }',
588
+ example: `<ng-oat-select label="Country" [options]="countries" [(value)]="country" />`,
589
+ },
590
+ {
591
+ name: 'NgOatCheckbox',
592
+ selector: 'ng-oat-checkbox',
593
+ import: "import { NgOatCheckbox } from '@letsprogram/ng-oat';",
594
+ category: 'form',
595
+ description: 'Checkbox for Signal Forms. Implements FormCheckboxControl.',
596
+ inputs: [
597
+ { name: 'label', type: 'string', default: "''" },
598
+ { name: 'checked', type: 'boolean', default: 'false', kind: 'model' },
599
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
600
+ ],
601
+ outputs: [],
602
+ example: `<ng-oat-checkbox label="Accept terms" [(checked)]="accepted" />`,
603
+ },
604
+ {
605
+ name: 'NgOatRadioGroup',
606
+ selector: 'ng-oat-radio-group',
607
+ import: "import { NgOatRadioGroup } from '@letsprogram/ng-oat';",
608
+ category: 'form',
609
+ description: 'Radio group for Signal Forms. Renders fieldset/legend when label provided.',
610
+ inputs: [
611
+ { name: 'label', type: 'string', default: "''" },
612
+ { name: 'options', type: 'NgOatRadioOption[]', default: 'required' },
613
+ { name: 'required', type: 'boolean', default: 'false' },
614
+ { name: 'value', type: 'string', default: "''", kind: 'model' },
615
+ { name: 'disabled', type: 'boolean', default: 'false', kind: 'model' },
616
+ ],
617
+ outputs: [],
618
+ notes: 'NgOatRadioOption: { label: string; value: string; disabled?: boolean }',
619
+ example: `<ng-oat-radio-group label="Plan" [options]="plans" [(value)]="plan" />`,
620
+ },
621
+ {
622
+ name: 'NgOatFormError',
623
+ selector: 'ng-oat-form-error',
624
+ import: "import { NgOatFormError } from '@letsprogram/ng-oat';",
625
+ category: 'form',
626
+ description: 'Displays validation errors. Use control input for Signal Forms, or errors+show for Reactive Forms.',
627
+ inputs: [
628
+ { name: 'control', type: 'FieldState<unknown> | undefined', default: 'undefined' },
629
+ { name: 'errors', type: 'string[]', default: '[]' },
630
+ { name: 'show', type: 'boolean', default: 'false' },
631
+ ],
632
+ outputs: [],
633
+ example: `<ng-oat-form-error [control]="form.controls.email" />`,
634
+ },
635
+ ];
636
+ /**
637
+ * Fuzzy-match a component by name or selector.
638
+ */
639
+ export function findComponent(query) {
640
+ const q = query.toLowerCase().replace(/[-_\s]/g, '');
641
+ return COMPONENTS.filter((c) => {
642
+ const name = c.name.toLowerCase().replace(/[-_\s]/g, '');
643
+ const sel = c.selector.toLowerCase().replace(/[-_\s]/g, '');
644
+ return name.includes(q) || sel.includes(q) || c.description.toLowerCase().includes(query.toLowerCase());
645
+ });
646
+ }
647
+ //# sourceMappingURL=components.js.map