@constela/ui 0.2.4 → 0.3.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 (39) hide show
  1. package/components/accordion/accordion-content.constela.json +20 -0
  2. package/components/accordion/accordion-item.constela.json +20 -0
  3. package/components/accordion/accordion-trigger.constela.json +21 -0
  4. package/components/accordion/accordion.constela.json +18 -0
  5. package/components/accordion/accordion.styles.json +54 -0
  6. package/components/accordion/accordion.test.ts +608 -0
  7. package/components/calendar/calendar.constela.json +195 -0
  8. package/components/calendar/calendar.styles.json +33 -0
  9. package/components/calendar/calendar.test.ts +458 -0
  10. package/components/chart/area-chart.constela.json +482 -0
  11. package/components/chart/bar-chart.constela.json +342 -0
  12. package/components/chart/chart-axis.constela.json +224 -0
  13. package/components/chart/chart-legend.constela.json +82 -0
  14. package/components/chart/chart-tooltip.constela.json +61 -0
  15. package/components/chart/chart.styles.json +183 -0
  16. package/components/chart/chart.test.ts +3260 -0
  17. package/components/chart/donut-chart.constela.json +369 -0
  18. package/components/chart/line-chart.constela.json +380 -0
  19. package/components/chart/pie-chart.constela.json +259 -0
  20. package/components/chart/radar-chart.constela.json +297 -0
  21. package/components/chart/scatter-chart.constela.json +300 -0
  22. package/components/data-table/data-table-cell.constela.json +22 -0
  23. package/components/data-table/data-table-header.constela.json +30 -0
  24. package/components/data-table/data-table-pagination.constela.json +19 -0
  25. package/components/data-table/data-table-row.constela.json +30 -0
  26. package/components/data-table/data-table.constela.json +32 -0
  27. package/components/data-table/data-table.styles.json +84 -0
  28. package/components/data-table/data-table.test.ts +873 -0
  29. package/components/datepicker/datepicker.constela.json +128 -0
  30. package/components/datepicker/datepicker.styles.json +47 -0
  31. package/components/datepicker/datepicker.test.ts +540 -0
  32. package/components/tree/tree-node.constela.json +26 -0
  33. package/components/tree/tree.constela.json +24 -0
  34. package/components/tree/tree.styles.json +50 -0
  35. package/components/tree/tree.test.ts +542 -0
  36. package/components/virtual-scroll/virtual-scroll.constela.json +27 -0
  37. package/components/virtual-scroll/virtual-scroll.styles.json +17 -0
  38. package/components/virtual-scroll/virtual-scroll.test.ts +345 -0
  39. package/package.json +2 -2
@@ -0,0 +1,540 @@
1
+ /**
2
+ * Test suite for DatePicker component
3
+ *
4
+ * @constela/ui DatePicker component tests following TDD methodology.
5
+ * These tests verify the DatePicker component structure, params, styles, and integration.
6
+ *
7
+ * Coverage:
8
+ * - Component structure validation (input + popover + calendar integration)
9
+ * - Params definition validation
10
+ * - Style preset validation (container, input, icon)
11
+ * - Input display and formatting
12
+ * - Calendar popover integration
13
+ * - Form integration
14
+ * - Disabled state handling
15
+ * - Accessibility attributes
16
+ */
17
+
18
+ import { describe, it, expect, beforeAll } from 'vitest';
19
+ import {
20
+ loadComponentForTesting,
21
+ assertValidComponent,
22
+ assertValidStylePreset,
23
+ hasParams,
24
+ isOptionalParam,
25
+ hasParamType,
26
+ getRootTag,
27
+ hasVariants,
28
+ hasVariantOptions,
29
+ hasDefaultVariants,
30
+ findPropInView,
31
+ hasAriaAttribute,
32
+ type ComponentTestContext,
33
+ } from '../../tests/helpers/test-utils.js';
34
+
35
+ describe('DatePicker Component', () => {
36
+ let ctx: ComponentTestContext;
37
+
38
+ beforeAll(() => {
39
+ ctx = loadComponentForTesting('datepicker');
40
+ });
41
+
42
+ // ==================== Component Structure Tests ====================
43
+
44
+ describe('Component Structure', () => {
45
+ it('should have valid component structure', () => {
46
+ assertValidComponent(ctx.component);
47
+ });
48
+
49
+ it('should have div as root element', () => {
50
+ const rootTag = getRootTag(ctx.component);
51
+ expect(rootTag).toBe('div');
52
+ });
53
+
54
+ it('should have className using StyleExpr with datepickerStyles preset', () => {
55
+ const className = findPropInView(ctx.component.view, 'className');
56
+ expect(className).not.toBeNull();
57
+ expect(className).toMatchObject({
58
+ expr: 'style',
59
+ preset: 'datepickerStyles',
60
+ });
61
+ });
62
+
63
+ it('should contain input element for displaying selected date', () => {
64
+ const view = ctx.component.view;
65
+ expect(view.kind).toBe('element');
66
+ if (view.kind === 'element') {
67
+ expect(view.children).toBeDefined();
68
+ // Should have at least input and popover/calendar structure
69
+ expect(view.children!.length).toBeGreaterThan(0);
70
+ }
71
+ });
72
+
73
+ it('should contain hidden input for form submission', () => {
74
+ // Hidden input with name attribute for form data
75
+ const view = ctx.component.view;
76
+ expect(view).toBeDefined();
77
+ });
78
+
79
+ it('should have aria-label for accessibility', () => {
80
+ expect(hasAriaAttribute(ctx.component.view, 'label')).toBe(true);
81
+ });
82
+ });
83
+
84
+ // ==================== Params Validation Tests ====================
85
+
86
+ describe('Params Validation', () => {
87
+ const expectedParams = [
88
+ 'value',
89
+ 'placeholder',
90
+ 'format',
91
+ 'min',
92
+ 'max',
93
+ 'disabled',
94
+ 'required',
95
+ 'name',
96
+ 'id',
97
+ 'locale',
98
+ ];
99
+
100
+ it('should have all expected params', () => {
101
+ expect(hasParams(ctx.component, expectedParams)).toBe(true);
102
+ });
103
+
104
+ describe('param: value', () => {
105
+ it('should be optional', () => {
106
+ expect(isOptionalParam(ctx.component, 'value')).toBe(true);
107
+ });
108
+
109
+ it('should have type string', () => {
110
+ expect(hasParamType(ctx.component, 'value', 'string')).toBe(true);
111
+ });
112
+ });
113
+
114
+ describe('param: placeholder', () => {
115
+ it('should be optional', () => {
116
+ expect(isOptionalParam(ctx.component, 'placeholder')).toBe(true);
117
+ });
118
+
119
+ it('should have type string', () => {
120
+ expect(hasParamType(ctx.component, 'placeholder', 'string')).toBe(true);
121
+ });
122
+ });
123
+
124
+ describe('param: format', () => {
125
+ it('should be optional', () => {
126
+ expect(isOptionalParam(ctx.component, 'format')).toBe(true);
127
+ });
128
+
129
+ it('should have type string', () => {
130
+ expect(hasParamType(ctx.component, 'format', 'string')).toBe(true);
131
+ });
132
+ });
133
+
134
+ describe('param: min', () => {
135
+ it('should be optional', () => {
136
+ expect(isOptionalParam(ctx.component, 'min')).toBe(true);
137
+ });
138
+
139
+ it('should have type string', () => {
140
+ expect(hasParamType(ctx.component, 'min', 'string')).toBe(true);
141
+ });
142
+ });
143
+
144
+ describe('param: max', () => {
145
+ it('should be optional', () => {
146
+ expect(isOptionalParam(ctx.component, 'max')).toBe(true);
147
+ });
148
+
149
+ it('should have type string', () => {
150
+ expect(hasParamType(ctx.component, 'max', 'string')).toBe(true);
151
+ });
152
+ });
153
+
154
+ describe('param: disabled', () => {
155
+ it('should be optional', () => {
156
+ expect(isOptionalParam(ctx.component, 'disabled')).toBe(true);
157
+ });
158
+
159
+ it('should have type boolean', () => {
160
+ expect(hasParamType(ctx.component, 'disabled', 'boolean')).toBe(true);
161
+ });
162
+ });
163
+
164
+ describe('param: required', () => {
165
+ it('should be optional', () => {
166
+ expect(isOptionalParam(ctx.component, 'required')).toBe(true);
167
+ });
168
+
169
+ it('should have type boolean', () => {
170
+ expect(hasParamType(ctx.component, 'required', 'boolean')).toBe(true);
171
+ });
172
+ });
173
+
174
+ describe('param: name', () => {
175
+ it('should be optional', () => {
176
+ expect(isOptionalParam(ctx.component, 'name')).toBe(true);
177
+ });
178
+
179
+ it('should have type string', () => {
180
+ expect(hasParamType(ctx.component, 'name', 'string')).toBe(true);
181
+ });
182
+ });
183
+
184
+ describe('param: id', () => {
185
+ it('should be optional', () => {
186
+ expect(isOptionalParam(ctx.component, 'id')).toBe(true);
187
+ });
188
+
189
+ it('should have type string', () => {
190
+ expect(hasParamType(ctx.component, 'id', 'string')).toBe(true);
191
+ });
192
+ });
193
+
194
+ describe('param: locale', () => {
195
+ it('should be optional', () => {
196
+ expect(isOptionalParam(ctx.component, 'locale')).toBe(true);
197
+ });
198
+
199
+ it('should have type string', () => {
200
+ expect(hasParamType(ctx.component, 'locale', 'string')).toBe(true);
201
+ });
202
+ });
203
+ });
204
+
205
+ // ==================== Style Preset Tests: datepickerStyles ====================
206
+
207
+ describe('Style Preset: datepickerStyles', () => {
208
+ it('should have valid style preset structure', () => {
209
+ const datepickerStyles = ctx.styles['datepickerStyles'];
210
+ expect(datepickerStyles).toBeDefined();
211
+ assertValidStylePreset(datepickerStyles);
212
+ });
213
+
214
+ it('should have base classes for container', () => {
215
+ const datepickerStyles = ctx.styles['datepickerStyles'];
216
+ expect(datepickerStyles.base).toBeDefined();
217
+ expect(typeof datepickerStyles.base).toBe('string');
218
+ expect(datepickerStyles.base.length).toBeGreaterThan(0);
219
+ });
220
+
221
+ it('should include relative positioning for popover anchor', () => {
222
+ const datepickerStyles = ctx.styles['datepickerStyles'];
223
+ expect(datepickerStyles.base).toContain('relative');
224
+ });
225
+
226
+ describe('size variants', () => {
227
+ const sizeOptions = ['default', 'sm', 'lg'];
228
+
229
+ it('should have size variants', () => {
230
+ const datepickerStyles = ctx.styles['datepickerStyles'];
231
+ expect(hasVariants(datepickerStyles, ['size'])).toBe(true);
232
+ });
233
+
234
+ it.each(sizeOptions)('should have %s size option', (option) => {
235
+ const datepickerStyles = ctx.styles['datepickerStyles'];
236
+ expect(hasVariantOptions(datepickerStyles, 'size', [option])).toBe(true);
237
+ });
238
+ });
239
+
240
+ describe('default variants', () => {
241
+ it('should have default size set to default', () => {
242
+ const datepickerStyles = ctx.styles['datepickerStyles'];
243
+ expect(hasDefaultVariants(datepickerStyles, { size: 'default' })).toBe(true);
244
+ });
245
+ });
246
+ });
247
+
248
+ // ==================== Style Preset Tests: datepickerInputStyles ====================
249
+
250
+ describe('Style Preset: datepickerInputStyles', () => {
251
+ it('should have datepickerInputStyles preset', () => {
252
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
253
+ expect(datepickerInputStyles).toBeDefined();
254
+ assertValidStylePreset(datepickerInputStyles);
255
+ });
256
+
257
+ it('should have base classes for input field', () => {
258
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
259
+ expect(datepickerInputStyles.base).toBeDefined();
260
+ expect(typeof datepickerInputStyles.base).toBe('string');
261
+ expect(datepickerInputStyles.base.length).toBeGreaterThan(0);
262
+ });
263
+
264
+ it('should include padding for icon space', () => {
265
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
266
+ // Should have right padding for calendar icon
267
+ expect(datepickerInputStyles.base).toMatch(/pr-\d+/);
268
+ });
269
+
270
+ describe('state variants', () => {
271
+ const stateOptions = ['default', 'focused', 'disabled', 'error'];
272
+
273
+ it('should have state variants', () => {
274
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
275
+ expect(hasVariants(datepickerInputStyles, ['state'])).toBe(true);
276
+ });
277
+
278
+ it.each(stateOptions)('should have %s state option', (option) => {
279
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
280
+ expect(hasVariantOptions(datepickerInputStyles, 'state', [option])).toBe(true);
281
+ });
282
+ });
283
+
284
+ describe('size variants', () => {
285
+ const sizeOptions = ['default', 'sm', 'lg'];
286
+
287
+ it('should have size variants', () => {
288
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
289
+ expect(hasVariants(datepickerInputStyles, ['size'])).toBe(true);
290
+ });
291
+
292
+ it.each(sizeOptions)('should have %s size option', (option) => {
293
+ const datepickerInputStyles = ctx.styles['datepickerInputStyles'];
294
+ expect(hasVariantOptions(datepickerInputStyles, 'size', [option])).toBe(true);
295
+ });
296
+ });
297
+ });
298
+
299
+ // ==================== Style Preset Tests: datepickerIconStyles ====================
300
+
301
+ describe('Style Preset: datepickerIconStyles', () => {
302
+ it('should have datepickerIconStyles preset', () => {
303
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
304
+ expect(datepickerIconStyles).toBeDefined();
305
+ assertValidStylePreset(datepickerIconStyles);
306
+ });
307
+
308
+ it('should have base classes for calendar icon', () => {
309
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
310
+ expect(datepickerIconStyles.base).toBeDefined();
311
+ expect(typeof datepickerIconStyles.base).toBe('string');
312
+ expect(datepickerIconStyles.base.length).toBeGreaterThan(0);
313
+ });
314
+
315
+ it('should include absolute positioning', () => {
316
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
317
+ expect(datepickerIconStyles.base).toContain('absolute');
318
+ });
319
+
320
+ it('should include right alignment', () => {
321
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
322
+ expect(datepickerIconStyles.base).toMatch(/right-\d+/);
323
+ });
324
+
325
+ it('should include pointer cursor for clickable icon', () => {
326
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
327
+ expect(datepickerIconStyles.base).toContain('cursor-pointer');
328
+ });
329
+
330
+ describe('state variants', () => {
331
+ const stateOptions = ['default', 'disabled'];
332
+
333
+ it('should have state variants', () => {
334
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
335
+ expect(hasVariants(datepickerIconStyles, ['state'])).toBe(true);
336
+ });
337
+
338
+ it.each(stateOptions)('should have %s state option', (option) => {
339
+ const datepickerIconStyles = ctx.styles['datepickerIconStyles'];
340
+ expect(hasVariantOptions(datepickerIconStyles, 'state', [option])).toBe(true);
341
+ });
342
+ });
343
+ });
344
+
345
+ // ==================== Input Display Tests ====================
346
+
347
+ describe('Input Display', () => {
348
+ it('should show placeholder when no value is set', () => {
349
+ const placeholderParam = ctx.component.params?.['placeholder'];
350
+ expect(placeholderParam).toBeDefined();
351
+ expect(placeholderParam?.type).toBe('string');
352
+ });
353
+
354
+ it('should support format param for date display', () => {
355
+ const formatParam = ctx.component.params?.['format'];
356
+ expect(formatParam).toBeDefined();
357
+ expect(formatParam?.type).toBe('string');
358
+ });
359
+
360
+ it('should support locale param for localized display', () => {
361
+ const localeParam = ctx.component.params?.['locale'];
362
+ expect(localeParam).toBeDefined();
363
+ expect(localeParam?.type).toBe('string');
364
+ });
365
+
366
+ it('should display value when set', () => {
367
+ const valueParam = ctx.component.params?.['value'];
368
+ expect(valueParam).toBeDefined();
369
+ // value should be used to display formatted date in input
370
+ });
371
+
372
+ it('should make input read-only (date selection via calendar only)', () => {
373
+ // Input should be readonly to prevent manual text entry
374
+ const view = ctx.component.view;
375
+ expect(view).toBeDefined();
376
+ });
377
+ });
378
+
379
+ // ==================== Calendar Popover Integration Tests ====================
380
+
381
+ describe('Calendar Popover Integration', () => {
382
+ it('should integrate with popover component', () => {
383
+ // Should contain popover element or component reference
384
+ const view = ctx.component.view;
385
+ expect(view).toBeDefined();
386
+ });
387
+
388
+ it('should integrate with calendar component', () => {
389
+ // Should contain calendar element or component reference
390
+ const view = ctx.component.view;
391
+ expect(view).toBeDefined();
392
+ });
393
+
394
+ it('should pass min prop to calendar', () => {
395
+ const minParam = ctx.component.params?.['min'];
396
+ expect(minParam).toBeDefined();
397
+ });
398
+
399
+ it('should pass max prop to calendar', () => {
400
+ const maxParam = ctx.component.params?.['max'];
401
+ expect(maxParam).toBeDefined();
402
+ });
403
+
404
+ it('should pass locale prop to calendar', () => {
405
+ const localeParam = ctx.component.params?.['locale'];
406
+ expect(localeParam).toBeDefined();
407
+ });
408
+
409
+ it('should have internal state for calendar open/close', () => {
410
+ // Component should manage open state for popover
411
+ const view = ctx.component.view;
412
+ expect(view).toBeDefined();
413
+ });
414
+ });
415
+
416
+ // ==================== Form Integration Tests ====================
417
+
418
+ describe('Form Integration', () => {
419
+ it('should support name param for form submission', () => {
420
+ const nameParam = ctx.component.params?.['name'];
421
+ expect(nameParam).toBeDefined();
422
+ expect(nameParam?.type).toBe('string');
423
+ });
424
+
425
+ it('should support required param', () => {
426
+ const requiredParam = ctx.component.params?.['required'];
427
+ expect(requiredParam).toBeDefined();
428
+ expect(requiredParam?.type).toBe('boolean');
429
+ });
430
+
431
+ it('should support id param', () => {
432
+ const idParam = ctx.component.params?.['id'];
433
+ expect(idParam).toBeDefined();
434
+ expect(idParam?.type).toBe('string');
435
+ });
436
+
437
+ it('should have hidden input with ISO format value for form data', () => {
438
+ // Hidden input should always contain YYYY-MM-DD format
439
+ const view = ctx.component.view;
440
+ expect(view).toBeDefined();
441
+ });
442
+ });
443
+
444
+ // ==================== Disabled State Tests ====================
445
+
446
+ describe('Disabled State', () => {
447
+ it('should support disabled param', () => {
448
+ const disabledParam = ctx.component.params?.['disabled'];
449
+ expect(disabledParam).toBeDefined();
450
+ expect(disabledParam?.type).toBe('boolean');
451
+ });
452
+
453
+ it('should apply disabled styling when disabled is true', () => {
454
+ // Input and icon should reflect disabled state
455
+ const view = ctx.component.view;
456
+ expect(view).toBeDefined();
457
+ });
458
+
459
+ it('should prevent calendar opening when disabled', () => {
460
+ // Click handlers should check disabled state
461
+ const view = ctx.component.view;
462
+ expect(view).toBeDefined();
463
+ });
464
+ });
465
+
466
+ // ==================== Accessibility Tests ====================
467
+
468
+ describe('Accessibility', () => {
469
+ it('should have aria-label for date picker', () => {
470
+ expect(hasAriaAttribute(ctx.component.view, 'label')).toBe(true);
471
+ });
472
+
473
+ it('should have aria-haspopup attribute', () => {
474
+ // Input should indicate it opens a popup
475
+ expect(hasAriaAttribute(ctx.component.view, 'haspopup')).toBe(true);
476
+ });
477
+
478
+ it('should have aria-expanded attribute', () => {
479
+ // Should reflect whether calendar is open
480
+ expect(hasAriaAttribute(ctx.component.view, 'expanded')).toBe(true);
481
+ });
482
+
483
+ it('should support keyboard navigation', () => {
484
+ // Should be focusable and support Enter/Space to open
485
+ const view = ctx.component.view;
486
+ expect(view).toBeDefined();
487
+ });
488
+ });
489
+
490
+ // ==================== View Props Tests ====================
491
+
492
+ describe('View Props', () => {
493
+ it('should pass value to component', () => {
494
+ const params = ctx.component.params;
495
+ expect(params?.['value']).toBeDefined();
496
+ });
497
+
498
+ it('should pass placeholder to input', () => {
499
+ const params = ctx.component.params;
500
+ expect(params?.['placeholder']).toBeDefined();
501
+ });
502
+
503
+ it('should pass disabled to component', () => {
504
+ const params = ctx.component.params;
505
+ expect(params?.['disabled']).toBeDefined();
506
+ });
507
+
508
+ it('should pass format to component', () => {
509
+ const params = ctx.component.params;
510
+ expect(params?.['format']).toBeDefined();
511
+ });
512
+
513
+ it('should pass locale to component', () => {
514
+ const params = ctx.component.params;
515
+ expect(params?.['locale']).toBeDefined();
516
+ });
517
+ });
518
+
519
+ // ==================== Events Tests ====================
520
+
521
+ describe('Events', () => {
522
+ it('should emit @change event when date is selected', () => {
523
+ // Component should have event handler for date selection
524
+ const view = ctx.component.view;
525
+ expect(view).toBeDefined();
526
+ });
527
+
528
+ it('should emit @open event when calendar opens', () => {
529
+ // Component should emit event on popover open
530
+ const view = ctx.component.view;
531
+ expect(view).toBeDefined();
532
+ });
533
+
534
+ it('should emit @close event when calendar closes', () => {
535
+ // Component should emit event on popover close
536
+ const view = ctx.component.view;
537
+ expect(view).toBeDefined();
538
+ });
539
+ });
540
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "params": {
3
+ "node": { "type": "object", "required": true },
4
+ "level": { "type": "number", "required": true },
5
+ "expandedNodes": { "type": "list", "required": true },
6
+ "selectedNodes": { "type": "list", "required": true },
7
+ "expanded": { "type": "boolean", "required": false },
8
+ "selected": { "type": "boolean", "required": false },
9
+ "selectable": { "type": "boolean", "required": false }
10
+ },
11
+ "view": {
12
+ "kind": "element",
13
+ "tag": "li",
14
+ "props": {
15
+ "role": { "expr": "lit", "value": "treeitem" },
16
+ "aria-expanded": { "expr": "param", "name": "expanded" },
17
+ "aria-selected": { "expr": "param", "name": "selected" },
18
+ "aria-level": { "expr": "param", "name": "level" },
19
+ "className": {
20
+ "expr": "style",
21
+ "preset": "treeNodeStyles"
22
+ }
23
+ },
24
+ "children": [{ "kind": "slot" }]
25
+ }
26
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "params": {
3
+ "items": { "type": "list", "required": true },
4
+ "selectable": { "type": "boolean", "required": false },
5
+ "multiSelect": { "type": "boolean", "required": false }
6
+ },
7
+ "localState": {
8
+ "expandedNodes": { "type": "list", "initial": [] },
9
+ "selectedNodes": { "type": "list", "initial": [] }
10
+ },
11
+ "view": {
12
+ "kind": "element",
13
+ "tag": "ul",
14
+ "props": {
15
+ "role": { "expr": "lit", "value": "tree" },
16
+ "aria-multiselectable": { "expr": "param", "name": "multiSelect" },
17
+ "className": {
18
+ "expr": "style",
19
+ "preset": "treeStyles"
20
+ }
21
+ },
22
+ "children": [{ "kind": "slot" }]
23
+ }
24
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "treeStyles": {
3
+ "base": "list-none space-y-1"
4
+ },
5
+ "treeNodeStyles": {
6
+ "base": "relative"
7
+ },
8
+ "treeNodeContentStyles": {
9
+ "base": "flex items-center gap-1 rounded-md px-2 py-1",
10
+ "variants": {
11
+ "selected": {
12
+ "true": "bg-accent text-accent-foreground",
13
+ "false": ""
14
+ }
15
+ },
16
+ "defaultVariants": {
17
+ "selected": "false"
18
+ }
19
+ },
20
+ "treeToggleStyles": {
21
+ "base": "inline-flex h-4 w-4 items-center justify-center"
22
+ },
23
+ "treeChevronStyles": {
24
+ "base": "h-4 w-4 shrink-0 transition-transform",
25
+ "variants": {
26
+ "expanded": {
27
+ "true": "rotate-90",
28
+ "false": "rotate-0"
29
+ }
30
+ },
31
+ "defaultVariants": {
32
+ "expanded": "false"
33
+ }
34
+ },
35
+ "treeLabelStyles": {
36
+ "base": "flex-1 truncate",
37
+ "variants": {
38
+ "selected": {
39
+ "true": "font-medium",
40
+ "false": ""
41
+ }
42
+ },
43
+ "defaultVariants": {
44
+ "selected": "false"
45
+ }
46
+ },
47
+ "treeGroupStyles": {
48
+ "base": "pl-4"
49
+ }
50
+ }