@constela/ui 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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -0
  3. package/components/alert/alert.constela.json +22 -0
  4. package/components/alert/alert.styles.json +14 -0
  5. package/components/alert/alert.test.ts +173 -0
  6. package/components/avatar/avatar.constela.json +32 -0
  7. package/components/avatar/avatar.styles.json +15 -0
  8. package/components/avatar/avatar.test.ts +197 -0
  9. package/components/badge/badge.constela.json +19 -0
  10. package/components/badge/badge.styles.json +16 -0
  11. package/components/badge/badge.test.ts +135 -0
  12. package/components/breadcrumb/breadcrumb.constela.json +17 -0
  13. package/components/breadcrumb/breadcrumb.styles.json +5 -0
  14. package/components/breadcrumb/breadcrumb.test.ts +149 -0
  15. package/components/button/README.md +164 -0
  16. package/components/button/button.constela.json +27 -0
  17. package/components/button/button.styles.json +25 -0
  18. package/components/button/button.test.ts +233 -0
  19. package/components/card/card.constela.json +21 -0
  20. package/components/card/card.styles.json +14 -0
  21. package/components/card/card.test.ts +154 -0
  22. package/components/checkbox/checkbox.constela.json +33 -0
  23. package/components/checkbox/checkbox.styles.json +15 -0
  24. package/components/checkbox/checkbox.test.ts +275 -0
  25. package/components/container/container.constela.json +21 -0
  26. package/components/container/container.styles.json +18 -0
  27. package/components/container/container.test.ts +164 -0
  28. package/components/dialog/dialog.constela.json +19 -0
  29. package/components/dialog/dialog.styles.json +5 -0
  30. package/components/dialog/dialog.test.ts +139 -0
  31. package/components/grid/grid.constela.json +23 -0
  32. package/components/grid/grid.styles.json +25 -0
  33. package/components/grid/grid.test.ts +193 -0
  34. package/components/input/input.constela.json +34 -0
  35. package/components/input/input.styles.json +19 -0
  36. package/components/input/input.test.ts +301 -0
  37. package/components/pagination/pagination.constela.json +22 -0
  38. package/components/pagination/pagination.styles.json +15 -0
  39. package/components/pagination/pagination.test.ts +170 -0
  40. package/components/popover/popover.constela.json +20 -0
  41. package/components/popover/popover.styles.json +16 -0
  42. package/components/popover/popover.test.ts +165 -0
  43. package/components/radio/radio.constela.json +31 -0
  44. package/components/radio/radio.styles.json +15 -0
  45. package/components/radio/radio.test.ts +253 -0
  46. package/components/select/select.constela.json +32 -0
  47. package/components/select/select.styles.json +15 -0
  48. package/components/select/select.test.ts +257 -0
  49. package/components/skeleton/skeleton.constela.json +24 -0
  50. package/components/skeleton/skeleton.styles.json +5 -0
  51. package/components/skeleton/skeleton.test.ts +164 -0
  52. package/components/stack/stack.constela.json +27 -0
  53. package/components/stack/stack.styles.json +33 -0
  54. package/components/stack/stack.test.ts +261 -0
  55. package/components/switch/switch.constela.json +29 -0
  56. package/components/switch/switch.styles.json +15 -0
  57. package/components/switch/switch.test.ts +224 -0
  58. package/components/tabs/tabs.constela.json +21 -0
  59. package/components/tabs/tabs.styles.json +14 -0
  60. package/components/tabs/tabs.test.ts +163 -0
  61. package/components/textarea/textarea.constela.json +34 -0
  62. package/components/textarea/textarea.styles.json +15 -0
  63. package/components/textarea/textarea.test.ts +290 -0
  64. package/components/toast/toast.constela.json +23 -0
  65. package/components/toast/toast.styles.json +17 -0
  66. package/components/toast/toast.test.ts +183 -0
  67. package/components/tooltip/tooltip.constela.json +21 -0
  68. package/components/tooltip/tooltip.styles.json +16 -0
  69. package/components/tooltip/tooltip.test.ts +164 -0
  70. package/dist/index.d.ts +54 -0
  71. package/dist/index.js +83 -0
  72. package/package.json +39 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Test suite for Grid component
3
+ *
4
+ * @constela/ui Grid component tests following TDD methodology.
5
+ * These tests verify the Grid component structure, params, and styles.
6
+ *
7
+ * Coverage:
8
+ * - Component structure validation
9
+ * - Params definition validation
10
+ * - Style preset validation
11
+ */
12
+
13
+ import { describe, it, expect, beforeAll } from 'vitest';
14
+ import {
15
+ loadComponentForTesting,
16
+ assertValidComponent,
17
+ assertValidStylePreset,
18
+ hasParams,
19
+ isOptionalParam,
20
+ hasParamType,
21
+ getRootTag,
22
+ hasVariants,
23
+ hasVariantOptions,
24
+ hasDefaultVariants,
25
+ hasSlot,
26
+ findPropInView,
27
+ type ComponentTestContext,
28
+ } from '../../tests/helpers/test-utils.js';
29
+
30
+ describe('Grid Component', () => {
31
+ let ctx: ComponentTestContext;
32
+
33
+ beforeAll(() => {
34
+ ctx = loadComponentForTesting('grid');
35
+ });
36
+
37
+ // ==================== Component Structure Tests ====================
38
+
39
+ describe('Component Structure', () => {
40
+ it('should have valid component structure', () => {
41
+ assertValidComponent(ctx.component);
42
+ });
43
+
44
+ it('should have div as root element', () => {
45
+ const rootTag = getRootTag(ctx.component);
46
+ expect(rootTag).toBe('div');
47
+ });
48
+
49
+ it('should contain a slot for grid items', () => {
50
+ expect(hasSlot(ctx.component.view)).toBe(true);
51
+ });
52
+
53
+ it('should have className using StyleExpr with gridStyles preset', () => {
54
+ const className = findPropInView(ctx.component.view, 'className');
55
+ expect(className).not.toBeNull();
56
+ expect(className).toMatchObject({
57
+ expr: 'style',
58
+ preset: 'gridStyles',
59
+ });
60
+ });
61
+ });
62
+
63
+ // ==================== Params Validation Tests ====================
64
+
65
+ describe('Params Validation', () => {
66
+ const expectedParams = ['cols', 'gap', 'className'];
67
+
68
+ it('should have all expected params', () => {
69
+ expect(hasParams(ctx.component, expectedParams)).toBe(true);
70
+ });
71
+
72
+ describe('param: cols', () => {
73
+ it('should be optional', () => {
74
+ expect(isOptionalParam(ctx.component, 'cols')).toBe(true);
75
+ });
76
+
77
+ it('should have type string', () => {
78
+ expect(hasParamType(ctx.component, 'cols', 'string')).toBe(true);
79
+ });
80
+ });
81
+
82
+ describe('param: gap', () => {
83
+ it('should be optional', () => {
84
+ expect(isOptionalParam(ctx.component, 'gap')).toBe(true);
85
+ });
86
+
87
+ it('should have type string', () => {
88
+ expect(hasParamType(ctx.component, 'gap', 'string')).toBe(true);
89
+ });
90
+ });
91
+
92
+ describe('param: className', () => {
93
+ it('should be optional', () => {
94
+ expect(isOptionalParam(ctx.component, 'className')).toBe(true);
95
+ });
96
+
97
+ it('should have type string', () => {
98
+ expect(hasParamType(ctx.component, 'className', 'string')).toBe(true);
99
+ });
100
+ });
101
+ });
102
+
103
+ // ==================== Style Preset Tests ====================
104
+
105
+ describe('Style Preset', () => {
106
+ it('should have valid style preset structure', () => {
107
+ const gridStyles = ctx.styles['gridStyles'];
108
+ expect(gridStyles).toBeDefined();
109
+ assertValidStylePreset(gridStyles);
110
+ });
111
+
112
+ it('should have base classes for common grid styles', () => {
113
+ const gridStyles = ctx.styles['gridStyles'];
114
+ expect(gridStyles.base).toBeDefined();
115
+ expect(typeof gridStyles.base).toBe('string');
116
+ expect(gridStyles.base.length).toBeGreaterThan(0);
117
+ });
118
+
119
+ describe('cols variant options', () => {
120
+ const colsOptions = ['1', '2', '3', '4', '6', '12'];
121
+
122
+ it('should have cols variant', () => {
123
+ const gridStyles = ctx.styles['gridStyles'];
124
+ expect(hasVariants(gridStyles, ['cols'])).toBe(true);
125
+ });
126
+
127
+ it.each(colsOptions)('should have %s cols option', (option) => {
128
+ const gridStyles = ctx.styles['gridStyles'];
129
+ expect(hasVariantOptions(gridStyles, 'cols', [option])).toBe(true);
130
+ });
131
+ });
132
+
133
+ describe('gap variant options', () => {
134
+ const gapOptions = ['none', 'sm', 'md', 'lg'];
135
+
136
+ it('should have gap variant', () => {
137
+ const gridStyles = ctx.styles['gridStyles'];
138
+ expect(hasVariants(gridStyles, ['gap'])).toBe(true);
139
+ });
140
+
141
+ it.each(gapOptions)('should have %s gap option', (option) => {
142
+ const gridStyles = ctx.styles['gridStyles'];
143
+ expect(hasVariantOptions(gridStyles, 'gap', [option])).toBe(true);
144
+ });
145
+ });
146
+
147
+ describe('default variants', () => {
148
+ it('should have default cols set to "1"', () => {
149
+ const gridStyles = ctx.styles['gridStyles'];
150
+ expect(hasDefaultVariants(gridStyles, { cols: '1' })).toBe(true);
151
+ });
152
+
153
+ it('should have default gap set to "md"', () => {
154
+ const gridStyles = ctx.styles['gridStyles'];
155
+ expect(hasDefaultVariants(gridStyles, { gap: 'md' })).toBe(true);
156
+ });
157
+ });
158
+ });
159
+
160
+ // ==================== View Props Tests ====================
161
+
162
+ describe('View Props', () => {
163
+ it('should pass cols to StyleExpr', () => {
164
+ const className = findPropInView(ctx.component.view, 'className');
165
+ expect(className).toMatchObject({
166
+ expr: 'style',
167
+ props: expect.objectContaining({
168
+ cols: expect.objectContaining({ expr: 'param', name: 'cols' }),
169
+ }),
170
+ });
171
+ });
172
+
173
+ it('should pass gap to StyleExpr', () => {
174
+ const className = findPropInView(ctx.component.view, 'className');
175
+ expect(className).toMatchObject({
176
+ expr: 'style',
177
+ props: expect.objectContaining({
178
+ gap: expect.objectContaining({ expr: 'param', name: 'gap' }),
179
+ }),
180
+ });
181
+ });
182
+
183
+ it('should pass className to StyleExpr', () => {
184
+ const className = findPropInView(ctx.component.view, 'className');
185
+ expect(className).toMatchObject({
186
+ expr: 'style',
187
+ props: expect.objectContaining({
188
+ className: expect.objectContaining({ expr: 'param', name: 'className' }),
189
+ }),
190
+ });
191
+ });
192
+ });
193
+ });
@@ -0,0 +1,34 @@
1
+ {
2
+ "params": {
3
+ "value": { "type": "string", "required": false },
4
+ "placeholder": { "type": "string", "required": false },
5
+ "disabled": { "type": "boolean", "required": false },
6
+ "required": { "type": "boolean", "required": false },
7
+ "type": { "type": "string", "required": false },
8
+ "name": { "type": "string", "required": false },
9
+ "id": { "type": "string", "required": false },
10
+ "ariaLabel": { "type": "string", "required": false },
11
+ "size": { "type": "string", "required": false }
12
+ },
13
+ "view": {
14
+ "kind": "element",
15
+ "tag": "input",
16
+ "props": {
17
+ "className": {
18
+ "expr": "style",
19
+ "preset": "inputStyles",
20
+ "props": {
21
+ "size": { "expr": "param", "name": "size" }
22
+ }
23
+ },
24
+ "value": { "expr": "param", "name": "value" },
25
+ "placeholder": { "expr": "param", "name": "placeholder" },
26
+ "disabled": { "expr": "param", "name": "disabled" },
27
+ "required": { "expr": "param", "name": "required" },
28
+ "type": { "expr": "param", "name": "type" },
29
+ "name": { "expr": "param", "name": "name" },
30
+ "id": { "expr": "param", "name": "id" },
31
+ "aria-label": { "expr": "param", "name": "ariaLabel" }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "inputStyles": {
3
+ "base": "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4
+ "variants": {
5
+ "variant": {
6
+ "default": ""
7
+ },
8
+ "size": {
9
+ "default": "h-10",
10
+ "sm": "h-9 text-xs",
11
+ "lg": "h-11 text-base"
12
+ }
13
+ },
14
+ "defaultVariants": {
15
+ "variant": "default",
16
+ "size": "default"
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Test suite for Input component
3
+ *
4
+ * @constela/ui Input component tests following TDD methodology.
5
+ * These tests verify the Input component structure, params, styles, and accessibility.
6
+ *
7
+ * Coverage:
8
+ * - Component structure validation
9
+ * - Params definition validation
10
+ * - Style preset validation
11
+ * - Accessibility attributes
12
+ */
13
+
14
+ import { describe, it, expect, beforeAll } from 'vitest';
15
+ import {
16
+ loadComponentForTesting,
17
+ assertValidComponent,
18
+ assertValidStylePreset,
19
+ hasParams,
20
+ isOptionalParam,
21
+ hasParamType,
22
+ getRootTag,
23
+ hasVariants,
24
+ hasVariantOptions,
25
+ hasDefaultVariants,
26
+ hasSlot,
27
+ findPropInView,
28
+ type ComponentTestContext,
29
+ } from '../../tests/helpers/test-utils.js';
30
+
31
+ describe('Input Component', () => {
32
+ let ctx: ComponentTestContext;
33
+
34
+ beforeAll(() => {
35
+ ctx = loadComponentForTesting('input');
36
+ });
37
+
38
+ // ==================== Component Structure Tests ====================
39
+
40
+ describe('Component Structure', () => {
41
+ it('should have valid component structure', () => {
42
+ assertValidComponent(ctx.component);
43
+ });
44
+
45
+ it('should have input as root element', () => {
46
+ const rootTag = getRootTag(ctx.component);
47
+ expect(rootTag).toBe('input');
48
+ });
49
+
50
+ it('should NOT contain a slot (input is self-closing)', () => {
51
+ expect(hasSlot(ctx.component.view)).toBe(false);
52
+ });
53
+
54
+ it('should have className using StyleExpr', () => {
55
+ const className = findPropInView(ctx.component.view, 'className');
56
+ expect(className).not.toBeNull();
57
+ // StyleExpr should have expr: 'style' and preset reference
58
+ expect(className).toMatchObject({
59
+ expr: 'style',
60
+ preset: 'inputStyles',
61
+ });
62
+ });
63
+ });
64
+
65
+ // ==================== Params Validation Tests ====================
66
+
67
+ describe('Params Validation', () => {
68
+ const expectedParams = [
69
+ 'value',
70
+ 'placeholder',
71
+ 'disabled',
72
+ 'required',
73
+ 'type',
74
+ 'name',
75
+ 'id',
76
+ 'ariaLabel',
77
+ ];
78
+
79
+ it('should have all expected params', () => {
80
+ expect(hasParams(ctx.component, expectedParams)).toBe(true);
81
+ });
82
+
83
+ describe('param: value', () => {
84
+ it('should be optional', () => {
85
+ expect(isOptionalParam(ctx.component, 'value')).toBe(true);
86
+ });
87
+
88
+ it('should have type string', () => {
89
+ expect(hasParamType(ctx.component, 'value', 'string')).toBe(true);
90
+ });
91
+ });
92
+
93
+ describe('param: placeholder', () => {
94
+ it('should be optional', () => {
95
+ expect(isOptionalParam(ctx.component, 'placeholder')).toBe(true);
96
+ });
97
+
98
+ it('should have type string', () => {
99
+ expect(hasParamType(ctx.component, 'placeholder', 'string')).toBe(true);
100
+ });
101
+ });
102
+
103
+ describe('param: disabled', () => {
104
+ it('should be optional', () => {
105
+ expect(isOptionalParam(ctx.component, 'disabled')).toBe(true);
106
+ });
107
+
108
+ it('should have type boolean', () => {
109
+ expect(hasParamType(ctx.component, 'disabled', 'boolean')).toBe(true);
110
+ });
111
+ });
112
+
113
+ describe('param: required', () => {
114
+ it('should be optional', () => {
115
+ expect(isOptionalParam(ctx.component, 'required')).toBe(true);
116
+ });
117
+
118
+ it('should have type boolean', () => {
119
+ expect(hasParamType(ctx.component, 'required', 'boolean')).toBe(true);
120
+ });
121
+ });
122
+
123
+ describe('param: type', () => {
124
+ it('should be optional', () => {
125
+ expect(isOptionalParam(ctx.component, 'type')).toBe(true);
126
+ });
127
+
128
+ it('should have type string', () => {
129
+ expect(hasParamType(ctx.component, 'type', 'string')).toBe(true);
130
+ });
131
+ });
132
+
133
+ describe('param: name', () => {
134
+ it('should be optional', () => {
135
+ expect(isOptionalParam(ctx.component, 'name')).toBe(true);
136
+ });
137
+
138
+ it('should have type string', () => {
139
+ expect(hasParamType(ctx.component, 'name', 'string')).toBe(true);
140
+ });
141
+ });
142
+
143
+ describe('param: id', () => {
144
+ it('should be optional', () => {
145
+ expect(isOptionalParam(ctx.component, 'id')).toBe(true);
146
+ });
147
+
148
+ it('should have type string', () => {
149
+ expect(hasParamType(ctx.component, 'id', 'string')).toBe(true);
150
+ });
151
+ });
152
+
153
+ describe('param: ariaLabel', () => {
154
+ it('should be optional', () => {
155
+ expect(isOptionalParam(ctx.component, 'ariaLabel')).toBe(true);
156
+ });
157
+
158
+ it('should have type string', () => {
159
+ expect(hasParamType(ctx.component, 'ariaLabel', 'string')).toBe(true);
160
+ });
161
+ });
162
+ });
163
+
164
+ // ==================== Style Preset Tests ====================
165
+
166
+ describe('Style Preset', () => {
167
+ it('should have valid style preset structure', () => {
168
+ const inputStyles = ctx.styles['inputStyles'];
169
+ expect(inputStyles).toBeDefined();
170
+ assertValidStylePreset(inputStyles);
171
+ });
172
+
173
+ it('should have base classes', () => {
174
+ const inputStyles = ctx.styles['inputStyles'];
175
+ expect(inputStyles.base).toBeDefined();
176
+ expect(typeof inputStyles.base).toBe('string');
177
+ expect(inputStyles.base.length).toBeGreaterThan(0);
178
+ });
179
+
180
+ describe('variant options', () => {
181
+ it('should have variant variants', () => {
182
+ const inputStyles = ctx.styles['inputStyles'];
183
+ expect(hasVariants(inputStyles, ['variant'])).toBe(true);
184
+ });
185
+
186
+ it('should have default variant option', () => {
187
+ const inputStyles = ctx.styles['inputStyles'];
188
+ expect(hasVariantOptions(inputStyles, 'variant', ['default'])).toBe(true);
189
+ });
190
+ });
191
+
192
+ describe('size options', () => {
193
+ const sizeOptions = ['default', 'sm', 'lg'];
194
+
195
+ it('should have size variants', () => {
196
+ const inputStyles = ctx.styles['inputStyles'];
197
+ expect(hasVariants(inputStyles, ['size'])).toBe(true);
198
+ });
199
+
200
+ it.each(sizeOptions)('should have %s size option', (option) => {
201
+ const inputStyles = ctx.styles['inputStyles'];
202
+ expect(hasVariantOptions(inputStyles, 'size', [option])).toBe(true);
203
+ });
204
+ });
205
+
206
+ describe('default variants', () => {
207
+ it('should have default variant set to default', () => {
208
+ const inputStyles = ctx.styles['inputStyles'];
209
+ expect(hasDefaultVariants(inputStyles, { variant: 'default' })).toBe(true);
210
+ });
211
+
212
+ it('should have default size set to default', () => {
213
+ const inputStyles = ctx.styles['inputStyles'];
214
+ expect(hasDefaultVariants(inputStyles, { size: 'default' })).toBe(true);
215
+ });
216
+ });
217
+ });
218
+
219
+ // ==================== Accessibility Tests ====================
220
+
221
+ describe('Accessibility', () => {
222
+ it('should support aria-label attribute', () => {
223
+ const ariaLabel = findPropInView(ctx.component.view, 'aria-label');
224
+ expect(ariaLabel).not.toBeNull();
225
+ // Should reference the ariaLabel param
226
+ expect(ariaLabel).toMatchObject({
227
+ expr: 'param',
228
+ name: 'ariaLabel',
229
+ });
230
+ });
231
+
232
+ it('should support disabled attribute', () => {
233
+ const disabled = findPropInView(ctx.component.view, 'disabled');
234
+ expect(disabled).not.toBeNull();
235
+ // Should reference the disabled param
236
+ expect(disabled).toMatchObject({
237
+ expr: 'param',
238
+ name: 'disabled',
239
+ });
240
+ });
241
+
242
+ it('should support required attribute', () => {
243
+ const required = findPropInView(ctx.component.view, 'required');
244
+ expect(required).not.toBeNull();
245
+ // Should reference the required param
246
+ expect(required).toMatchObject({
247
+ expr: 'param',
248
+ name: 'required',
249
+ });
250
+ });
251
+ });
252
+
253
+ // ==================== View Props Tests ====================
254
+
255
+ describe('View Props', () => {
256
+ it('should pass value to input', () => {
257
+ const value = findPropInView(ctx.component.view, 'value');
258
+ expect(value).not.toBeNull();
259
+ expect(value).toMatchObject({
260
+ expr: 'param',
261
+ name: 'value',
262
+ });
263
+ });
264
+
265
+ it('should pass placeholder to input', () => {
266
+ const placeholder = findPropInView(ctx.component.view, 'placeholder');
267
+ expect(placeholder).not.toBeNull();
268
+ expect(placeholder).toMatchObject({
269
+ expr: 'param',
270
+ name: 'placeholder',
271
+ });
272
+ });
273
+
274
+ it('should pass type to input', () => {
275
+ const type = findPropInView(ctx.component.view, 'type');
276
+ expect(type).not.toBeNull();
277
+ expect(type).toMatchObject({
278
+ expr: 'param',
279
+ name: 'type',
280
+ });
281
+ });
282
+
283
+ it('should pass name to input', () => {
284
+ const name = findPropInView(ctx.component.view, 'name');
285
+ expect(name).not.toBeNull();
286
+ expect(name).toMatchObject({
287
+ expr: 'param',
288
+ name: 'name',
289
+ });
290
+ });
291
+
292
+ it('should pass id to input', () => {
293
+ const id = findPropInView(ctx.component.view, 'id');
294
+ expect(id).not.toBeNull();
295
+ expect(id).toMatchObject({
296
+ expr: 'param',
297
+ name: 'id',
298
+ });
299
+ });
300
+ });
301
+ });
@@ -0,0 +1,22 @@
1
+ {
2
+ "params": {
3
+ "currentPage": { "type": "number", "required": false },
4
+ "totalPages": { "type": "number", "required": false },
5
+ "size": { "type": "string", "required": false }
6
+ },
7
+ "view": {
8
+ "kind": "element",
9
+ "tag": "nav",
10
+ "props": {
11
+ "aria-label": { "expr": "lit", "value": "Pagination" },
12
+ "className": {
13
+ "expr": "style",
14
+ "preset": "paginationStyles",
15
+ "props": {
16
+ "size": { "expr": "param", "name": "size" }
17
+ }
18
+ }
19
+ },
20
+ "children": [{ "kind": "slot" }]
21
+ }
22
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "paginationStyles": {
3
+ "base": "mx-auto flex w-full justify-center",
4
+ "variants": {
5
+ "size": {
6
+ "default": "",
7
+ "sm": "text-sm",
8
+ "lg": "text-lg"
9
+ }
10
+ },
11
+ "defaultVariants": {
12
+ "size": "default"
13
+ }
14
+ }
15
+ }