@oxcide-ui/schema 0.0.3
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.
- package/.turbo/turbo-build.log +58 -0
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs +436 -0
- package/dist/index.d.cts +884 -0
- package/dist/index.d.ts +884 -0
- package/dist/index.js +381 -0
- package/package.json +43 -0
- package/scripts/sync-types.ts +105 -0
- package/src/components/badge.ts +31 -0
- package/src/components/box.ts +18 -0
- package/src/components/button.ts +1333 -0
- package/src/components/checkbox.ts +715 -0
- package/src/components/dialog.ts +720 -0
- package/src/components/icon.ts +665 -0
- package/src/components/index.ts +12 -0
- package/src/components/input.ts +1330 -0
- package/src/components/radiobutton.ts +67 -0
- package/src/components/stack.ts +38 -0
- package/src/components/switch.ts +1326 -0
- package/src/components/tag.ts +670 -0
- package/src/components/toast.ts +69 -0
- package/src/index.ts +2 -0
- package/src/registry.ts +52 -0
- package/tsconfig.json +7 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// src/components/badge.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var badgePropsSchema = z.object({
|
|
4
|
+
/** Severity / semantic color */
|
|
5
|
+
severity: z.enum(["primary", "secondary", "success", "info", "warning", "danger", "help", "contrast"]).default("primary"),
|
|
6
|
+
/** Size */
|
|
7
|
+
size: z.enum(["xs", "sm", "md", "lg", "xl"]).default("md"),
|
|
8
|
+
/** Value to display */
|
|
9
|
+
value: z.union([z.string(), z.number()]).optional()
|
|
10
|
+
});
|
|
11
|
+
function getBadgeDefaults(props = {}) {
|
|
12
|
+
return badgePropsSchema.parse(props);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/components/box.ts
|
|
16
|
+
import { z as z2 } from "zod";
|
|
17
|
+
var boxPropsSchema = z2.object({
|
|
18
|
+
as: z2.string().default("div")
|
|
19
|
+
});
|
|
20
|
+
function getBoxDefaults(props = {}) {
|
|
21
|
+
return boxPropsSchema.parse(props);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/components/button.ts
|
|
25
|
+
import { z as z3 } from "zod";
|
|
26
|
+
var buttonPropsSchema = z3.object({
|
|
27
|
+
/** Visual variant */
|
|
28
|
+
variant: z3.enum(["solid", "outline", "ghost", "link"]).default("solid"),
|
|
29
|
+
/** Size */
|
|
30
|
+
size: z3.enum(["xs", "sm", "md", "lg", "xl"]).default("md"),
|
|
31
|
+
/** Severity / semantic color */
|
|
32
|
+
severity: z3.enum(["primary", "secondary", "success", "info", "warning", "danger", "help", "contrast"]).default("primary"),
|
|
33
|
+
/** Disabled state */
|
|
34
|
+
disabled: z3.boolean().default(false),
|
|
35
|
+
/** Loading state */
|
|
36
|
+
loading: z3.boolean().default(false),
|
|
37
|
+
/** Icon name from the library */
|
|
38
|
+
icon: z3.string().optional(),
|
|
39
|
+
/** Icon position relative to label */
|
|
40
|
+
iconPos: z3.enum(["left", "right"]).default("left"),
|
|
41
|
+
/** Loading icon name */
|
|
42
|
+
loadingIcon: z3.string().optional().default("spinner"),
|
|
43
|
+
/** Button label text */
|
|
44
|
+
label: z3.string().optional(),
|
|
45
|
+
/** Render as rounded pill */
|
|
46
|
+
rounded: z3.boolean().default(false),
|
|
47
|
+
/** Render as text-only (no background/border) */
|
|
48
|
+
text: z3.boolean().default(false),
|
|
49
|
+
/** Render as raised with shadow */
|
|
50
|
+
raised: z3.boolean().default(false)
|
|
51
|
+
});
|
|
52
|
+
function getButtonDefaults(props = {}) {
|
|
53
|
+
return buttonPropsSchema.parse(props);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/components/checkbox.ts
|
|
57
|
+
import { z as z4 } from "zod";
|
|
58
|
+
var checkboxPropsSchema = z4.object({
|
|
59
|
+
/** V-model value */
|
|
60
|
+
modelValue: z4.any().optional(),
|
|
61
|
+
/** Value for array-based checkboxes */
|
|
62
|
+
value: z4.any().optional(),
|
|
63
|
+
/** Value when checked */
|
|
64
|
+
onValue: z4.any().default(true),
|
|
65
|
+
/** Value when unchecked */
|
|
66
|
+
offValue: z4.any().default(false),
|
|
67
|
+
/** Treat modelValue as boolean regardless of value or switch to boolean mode */
|
|
68
|
+
binary: z4.boolean().default(false),
|
|
69
|
+
/** Disabled state */
|
|
70
|
+
disabled: z4.boolean().default(false),
|
|
71
|
+
/** Invalid / Error state */
|
|
72
|
+
invalid: z4.boolean().default(false),
|
|
73
|
+
/** Readonly state */
|
|
74
|
+
readonly: z4.boolean().default(false),
|
|
75
|
+
/** Label text (next to checkbox) */
|
|
76
|
+
label: z4.string().optional(),
|
|
77
|
+
/** Position of the label */
|
|
78
|
+
labelPosition: z4.enum(["left", "right"]).default("right"),
|
|
79
|
+
/** Custom icon when checked */
|
|
80
|
+
icon: z4.string().optional(),
|
|
81
|
+
/** Indeterminate state */
|
|
82
|
+
indeterminate: z4.boolean().default(false),
|
|
83
|
+
/** Size */
|
|
84
|
+
size: z4.enum(["sm", "md", "lg"]).default("md"),
|
|
85
|
+
/** Severity */
|
|
86
|
+
severity: z4.enum(["primary", "secondary", "success", "info", "warning", "danger", "help", "contrast"]).default("primary"),
|
|
87
|
+
/** Native name attribute */
|
|
88
|
+
name: z4.string().optional(),
|
|
89
|
+
/** Native id attribute */
|
|
90
|
+
id: z4.string().optional()
|
|
91
|
+
});
|
|
92
|
+
function getCheckboxDefaults(props = {}) {
|
|
93
|
+
return checkboxPropsSchema.parse(props);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/components/dialog.ts
|
|
97
|
+
import { z as z5 } from "zod";
|
|
98
|
+
var dialogPropsSchema = z5.object({
|
|
99
|
+
/** Modal visibility */
|
|
100
|
+
visible: z5.boolean().default(false),
|
|
101
|
+
/** Header text */
|
|
102
|
+
header: z5.string().optional(),
|
|
103
|
+
/** Footer text */
|
|
104
|
+
footer: z5.string().optional(),
|
|
105
|
+
/** Whether the dialog can be closed */
|
|
106
|
+
closable: z5.boolean().default(true),
|
|
107
|
+
/** Custom icon for the close button */
|
|
108
|
+
closeIcon: z5.string().default("times"),
|
|
109
|
+
/** Whether clicking the mask closes the dialog */
|
|
110
|
+
dismissableMask: z5.boolean().default(false),
|
|
111
|
+
/** Whether to close on Escape key */
|
|
112
|
+
closeOnEscape: z5.boolean().default(true),
|
|
113
|
+
/** Teleport target selector or element */
|
|
114
|
+
appendTo: z5.any().default("#teleports"),
|
|
115
|
+
/** Style class for the mask */
|
|
116
|
+
maskClass: z5.string().optional(),
|
|
117
|
+
/** Modal state */
|
|
118
|
+
modal: z5.boolean().default(true),
|
|
119
|
+
/** Whether to show the header */
|
|
120
|
+
showHeader: z5.boolean().default(true),
|
|
121
|
+
/** Custom style object */
|
|
122
|
+
style: z5.any().optional(),
|
|
123
|
+
/** Custom class name */
|
|
124
|
+
class: z5.any().optional(),
|
|
125
|
+
/** Dialog position */
|
|
126
|
+
position: z5.enum(["center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right"]).default("center"),
|
|
127
|
+
/** Native id attribute */
|
|
128
|
+
id: z5.string().optional()
|
|
129
|
+
});
|
|
130
|
+
function getDialogDefaults(props = {}) {
|
|
131
|
+
return dialogPropsSchema.parse(props);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/components/icon.ts
|
|
135
|
+
import { z as z6 } from "zod";
|
|
136
|
+
var iconPropsSchema = z6.object({
|
|
137
|
+
/** Icon name from the library */
|
|
138
|
+
name: z6.string().default(""),
|
|
139
|
+
/** Icon size (CSS value) */
|
|
140
|
+
size: z6.union([z6.string(), z6.number()]).optional().default("1em"),
|
|
141
|
+
/** Icon color (CSS value) */
|
|
142
|
+
color: z6.string().optional(),
|
|
143
|
+
/** Whether the icon should spin */
|
|
144
|
+
spin: z6.boolean().optional().default(false)
|
|
145
|
+
});
|
|
146
|
+
function getIconDefaults(props = {}) {
|
|
147
|
+
return iconPropsSchema.parse(props);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/components/input.ts
|
|
151
|
+
import { z as z7 } from "zod";
|
|
152
|
+
var inputPropsSchema = z7.object({
|
|
153
|
+
/** Input value */
|
|
154
|
+
modelValue: z7.string().optional(),
|
|
155
|
+
/** Size */
|
|
156
|
+
size: z7.enum(["sm", "md", "lg"]).default("md"),
|
|
157
|
+
/** Disabled state */
|
|
158
|
+
disabled: z7.boolean().default(false),
|
|
159
|
+
/** Readonly state */
|
|
160
|
+
readonly: z7.boolean().default(false),
|
|
161
|
+
/** Invalid / Error state */
|
|
162
|
+
invalid: z7.boolean().default(false),
|
|
163
|
+
/** Width 100% */
|
|
164
|
+
fluid: z7.boolean().default(false),
|
|
165
|
+
/** Icon to display on the left */
|
|
166
|
+
iconLeft: z7.string().optional(),
|
|
167
|
+
/** Icon to display on the right */
|
|
168
|
+
iconRight: z7.string().optional(),
|
|
169
|
+
/** Whether the input is clearable */
|
|
170
|
+
clearable: z7.boolean().default(false),
|
|
171
|
+
/** Placeholder text */
|
|
172
|
+
placeholder: z7.string().optional(),
|
|
173
|
+
/** Native type attribute */
|
|
174
|
+
type: z7.string().default("text"),
|
|
175
|
+
/** Native name attribute */
|
|
176
|
+
name: z7.string().optional(),
|
|
177
|
+
/** Native id attribute */
|
|
178
|
+
id: z7.string().optional()
|
|
179
|
+
});
|
|
180
|
+
function getInputDefaults(props = {}) {
|
|
181
|
+
return inputPropsSchema.parse(props);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/components/radiobutton.ts
|
|
185
|
+
import { z as z8 } from "zod";
|
|
186
|
+
var radioButtonPropsSchema = z8.object({
|
|
187
|
+
/** V-model selected value */
|
|
188
|
+
modelValue: z8.any().optional(),
|
|
189
|
+
/** Value representing this specific radio button */
|
|
190
|
+
value: z8.any().optional(),
|
|
191
|
+
/** Disabled state */
|
|
192
|
+
disabled: z8.boolean().default(false),
|
|
193
|
+
/** Invalid / Error state */
|
|
194
|
+
invalid: z8.boolean().default(false),
|
|
195
|
+
/** Readonly state */
|
|
196
|
+
readonly: z8.boolean().default(false),
|
|
197
|
+
/** Size */
|
|
198
|
+
size: z8.enum(["sm", "md", "lg"]).default("md"),
|
|
199
|
+
/** Severity */
|
|
200
|
+
severity: z8.enum(["primary", "secondary", "success", "info", "warning", "danger", "help", "contrast"]).default("primary"),
|
|
201
|
+
/** Variant */
|
|
202
|
+
variant: z8.enum(["filled", "outlined"]).default("filled"),
|
|
203
|
+
/** Label for accessibility and grouping */
|
|
204
|
+
label: z8.string().optional(),
|
|
205
|
+
/** Position of the label */
|
|
206
|
+
labelPosition: z8.enum(["left", "right"]).default("right"),
|
|
207
|
+
/** Group name for radios */
|
|
208
|
+
name: z8.string().optional(),
|
|
209
|
+
/** Native id attribute */
|
|
210
|
+
id: z8.string().optional()
|
|
211
|
+
});
|
|
212
|
+
function getRadioButtonDefaults(props = {}) {
|
|
213
|
+
return radioButtonPropsSchema.parse(props);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/components/stack.ts
|
|
217
|
+
import { z as z9 } from "zod";
|
|
218
|
+
var stackPropsSchema = z9.object({
|
|
219
|
+
as: z9.string().default("div"),
|
|
220
|
+
direction: z9.enum(["row", "column", "row-reverse", "column-reverse"]).default("column"),
|
|
221
|
+
gap: z9.enum(["none", "xs", "sm", "md", "lg", "xl", "2xl"]).default("md"),
|
|
222
|
+
align: z9.enum(["start", "center", "end", "stretch", "baseline"]).default("stretch"),
|
|
223
|
+
justify: z9.enum(["start", "center", "end", "between", "around", "evenly"]).default("start"),
|
|
224
|
+
wrap: z9.enum(["nowrap", "wrap", "wrap-reverse"]).default("nowrap"),
|
|
225
|
+
fluid: z9.boolean().default(false)
|
|
226
|
+
});
|
|
227
|
+
function getStackDefaults(props = {}) {
|
|
228
|
+
return stackPropsSchema.parse(props);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/components/switch.ts
|
|
232
|
+
import { z as z10 } from "zod";
|
|
233
|
+
var switchPropsSchema = z10.object({
|
|
234
|
+
/** V-model value */
|
|
235
|
+
modelValue: z10.any().optional(),
|
|
236
|
+
/** Value for 'on' state */
|
|
237
|
+
onValue: z10.any().default(true),
|
|
238
|
+
/** Value for 'off' state */
|
|
239
|
+
offValue: z10.any().default(false),
|
|
240
|
+
/** Disabled state */
|
|
241
|
+
disabled: z10.boolean().default(false),
|
|
242
|
+
/** Invalid / Error state */
|
|
243
|
+
invalid: z10.boolean().default(false),
|
|
244
|
+
/** Readonly state */
|
|
245
|
+
readonly: z10.boolean().default(false),
|
|
246
|
+
/** Label (next to the switch) */
|
|
247
|
+
label: z10.string().optional(),
|
|
248
|
+
/** Position of the label */
|
|
249
|
+
labelPosition: z10.enum(["left", "right"]).default("right"),
|
|
250
|
+
/** Icon to display when switch is on */
|
|
251
|
+
trueIcon: z10.string().optional(),
|
|
252
|
+
/** Icon to display when switch is off */
|
|
253
|
+
falseIcon: z10.string().optional(),
|
|
254
|
+
/** Size of the switch */
|
|
255
|
+
size: z10.enum(["sm", "md", "lg"]).default("md"),
|
|
256
|
+
/** Native id attribute */
|
|
257
|
+
id: z10.string().optional()
|
|
258
|
+
});
|
|
259
|
+
function getSwitchDefaults(props = {}) {
|
|
260
|
+
return switchPropsSchema.parse(props);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/components/tag.ts
|
|
264
|
+
import { z as z11 } from "zod";
|
|
265
|
+
var tagPropsSchema = z11.object({
|
|
266
|
+
/** Tag label / content */
|
|
267
|
+
value: z11.string().optional(),
|
|
268
|
+
/** Severity / semantic color */
|
|
269
|
+
severity: z11.enum(["primary", "secondary", "success", "info", "warning", "danger", "help", "contrast"]).default("primary"),
|
|
270
|
+
/** Rounded / pill shape */
|
|
271
|
+
rounded: z11.boolean().default(false),
|
|
272
|
+
/** Icon name from the library */
|
|
273
|
+
icon: z11.string().optional(),
|
|
274
|
+
/** Show close icon */
|
|
275
|
+
closable: z11.boolean().default(false)
|
|
276
|
+
});
|
|
277
|
+
function getTagDefaults(props = {}) {
|
|
278
|
+
return tagPropsSchema.parse(props);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/components/toast.ts
|
|
282
|
+
import { z as z12 } from "zod";
|
|
283
|
+
var toastSeveritySchema = z12.enum([
|
|
284
|
+
"success",
|
|
285
|
+
"info",
|
|
286
|
+
"warning",
|
|
287
|
+
"danger",
|
|
288
|
+
"secondary",
|
|
289
|
+
"help",
|
|
290
|
+
"contrast",
|
|
291
|
+
"primary"
|
|
292
|
+
]);
|
|
293
|
+
var toastMessageSchema = z12.object({
|
|
294
|
+
id: z12.string().optional(),
|
|
295
|
+
severity: toastSeveritySchema.default("info"),
|
|
296
|
+
summary: z12.string().optional(),
|
|
297
|
+
detail: z12.string().optional(),
|
|
298
|
+
life: z12.number().optional().default(3e3),
|
|
299
|
+
sticky: z12.boolean().optional().default(false),
|
|
300
|
+
closable: z12.boolean().optional().default(true),
|
|
301
|
+
icon: z12.string().optional(),
|
|
302
|
+
group: z12.string().optional()
|
|
303
|
+
});
|
|
304
|
+
var toastPropsSchema = z12.object({
|
|
305
|
+
position: z12.enum(["top-left", "top-center", "top-right", "bottom-left", "bottom-center", "bottom-right", "center"]).default("top-right"),
|
|
306
|
+
group: z12.string().optional(),
|
|
307
|
+
baseZIndex: z12.number().optional().default(0),
|
|
308
|
+
autoZIndex: z12.boolean().optional().default(true),
|
|
309
|
+
/** Teleport target selector or element */
|
|
310
|
+
appendTo: z12.any().default("#teleports")
|
|
311
|
+
});
|
|
312
|
+
function getToastDefaults(props = {}) {
|
|
313
|
+
return toastPropsSchema.parse(props);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/registry.ts
|
|
317
|
+
import { z as z13 } from "zod";
|
|
318
|
+
var registryItemFileSchema = z13.object({
|
|
319
|
+
/** Relative file path */
|
|
320
|
+
path: z13.string(),
|
|
321
|
+
/** File content as string */
|
|
322
|
+
content: z13.string(),
|
|
323
|
+
/** File type hint */
|
|
324
|
+
type: z13.enum(["component", "style", "schema", "composable", "util"]).optional()
|
|
325
|
+
});
|
|
326
|
+
var registryItemSchema = z13.object({
|
|
327
|
+
/** Component name (kebab-case) */
|
|
328
|
+
name: z13.string(),
|
|
329
|
+
/** Component type */
|
|
330
|
+
type: z13.enum(["component", "primitive", "composable", "util"]).default("component"),
|
|
331
|
+
/** Human-readable description */
|
|
332
|
+
description: z13.string().optional(),
|
|
333
|
+
/** Source files */
|
|
334
|
+
files: z13.array(registryItemFileSchema),
|
|
335
|
+
/** npm dependencies required by this component */
|
|
336
|
+
dependencies: z13.array(z13.string()).default([]),
|
|
337
|
+
/** Other registry components this one depends on */
|
|
338
|
+
registryDependencies: z13.array(z13.string()).default([]),
|
|
339
|
+
/** CSS file paths (if separately bundled) */
|
|
340
|
+
cssFiles: z13.array(z13.string()).default([])
|
|
341
|
+
});
|
|
342
|
+
var registryIndexSchema = z13.array(
|
|
343
|
+
z13.object({
|
|
344
|
+
name: z13.string(),
|
|
345
|
+
type: z13.string(),
|
|
346
|
+
description: z13.string().optional(),
|
|
347
|
+
dependencies: z13.array(z13.string()).default([]),
|
|
348
|
+
registryDependencies: z13.array(z13.string()).default([])
|
|
349
|
+
})
|
|
350
|
+
);
|
|
351
|
+
export {
|
|
352
|
+
badgePropsSchema,
|
|
353
|
+
boxPropsSchema,
|
|
354
|
+
buttonPropsSchema,
|
|
355
|
+
checkboxPropsSchema,
|
|
356
|
+
dialogPropsSchema,
|
|
357
|
+
getBadgeDefaults,
|
|
358
|
+
getBoxDefaults,
|
|
359
|
+
getButtonDefaults,
|
|
360
|
+
getCheckboxDefaults,
|
|
361
|
+
getDialogDefaults,
|
|
362
|
+
getIconDefaults,
|
|
363
|
+
getInputDefaults,
|
|
364
|
+
getRadioButtonDefaults,
|
|
365
|
+
getStackDefaults,
|
|
366
|
+
getSwitchDefaults,
|
|
367
|
+
getTagDefaults,
|
|
368
|
+
getToastDefaults,
|
|
369
|
+
iconPropsSchema,
|
|
370
|
+
inputPropsSchema,
|
|
371
|
+
radioButtonPropsSchema,
|
|
372
|
+
registryIndexSchema,
|
|
373
|
+
registryItemFileSchema,
|
|
374
|
+
registryItemSchema,
|
|
375
|
+
stackPropsSchema,
|
|
376
|
+
switchPropsSchema,
|
|
377
|
+
tagPropsSchema,
|
|
378
|
+
toastMessageSchema,
|
|
379
|
+
toastPropsSchema,
|
|
380
|
+
toastSeveritySchema
|
|
381
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oxcide-ui/schema",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"require": "./dist/index.cjs"
|
|
10
|
+
},
|
|
11
|
+
"./components": {
|
|
12
|
+
"types": "./dist/components/index.d.ts",
|
|
13
|
+
"import": "./dist/components/index.js",
|
|
14
|
+
"require": "./dist/components/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"zod": "3.25.76",
|
|
22
|
+
"@oxcide-ui/icons": "0.0.3"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@biomejs/biome": "^2.3.13",
|
|
26
|
+
"picocolors": "1.1.1",
|
|
27
|
+
"ts-morph": "^27.0.2",
|
|
28
|
+
"tsup": "^8.5.0",
|
|
29
|
+
"tsx": "^4.19.3",
|
|
30
|
+
"typescript": "^5.8.2"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "pnpm type-sync && tsup src/index.ts --format esm,cjs --dts --clean",
|
|
37
|
+
"dev": "pnpm type-sync && tsup src/index.ts --format esm,cjs --dts --watch",
|
|
38
|
+
"type-check": "tsc --noEmit",
|
|
39
|
+
"type-sync": "tsx scripts/sync-types.ts && pnpm lint:fix",
|
|
40
|
+
"lint": "biome check .",
|
|
41
|
+
"lint:fix": "biome check --write ."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Project } from 'ts-morph'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import pc from 'picocolors'
|
|
5
|
+
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
7
|
+
const rootPath = path.resolve(__dirname, '../src/components')
|
|
8
|
+
|
|
9
|
+
async function syncTypes() {
|
|
10
|
+
console.log(pc.cyan('\n🚀 Starting type synchronization (Direct Mode)...\n'))
|
|
11
|
+
|
|
12
|
+
const project = new Project({
|
|
13
|
+
tsConfigFilePath: path.resolve(__dirname, '../tsconfig.json'),
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const files = project.getSourceFiles(path.join(rootPath, '*.ts'))
|
|
17
|
+
let updatedCount = 0
|
|
18
|
+
|
|
19
|
+
for (const sourceFile of files) {
|
|
20
|
+
const filePath = sourceFile.getFilePath()
|
|
21
|
+
const fileName = path.basename(filePath)
|
|
22
|
+
|
|
23
|
+
if (fileName === 'index.ts' || fileName.endsWith('.d.ts')) continue
|
|
24
|
+
|
|
25
|
+
// Find the schema name (e.g., buttonPropsSchema)
|
|
26
|
+
const schemaVar = sourceFile.getVariableDeclaration((v) => v.getName().endsWith('PropsSchema'))
|
|
27
|
+
if (!schemaVar) {
|
|
28
|
+
if (!fileName.includes('types')) {
|
|
29
|
+
console.warn(pc.yellow(`⚠️ Could not find a variable ending with 'PropsSchema' in ${fileName}. Skipping.`))
|
|
30
|
+
}
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const schemaName = schemaVar.getName()
|
|
35
|
+
const baseName = schemaName.replace('PropsSchema', '')
|
|
36
|
+
const capitalizedBaseName = baseName.charAt(0).toUpperCase() + baseName.slice(1)
|
|
37
|
+
|
|
38
|
+
console.log(`${pc.blue('⏳')} Syncing ${pc.bold(pc.white(fileName))}...`)
|
|
39
|
+
|
|
40
|
+
let content = sourceFile.getFullText()
|
|
41
|
+
|
|
42
|
+
// 1. Detect existing sync block
|
|
43
|
+
const syncBlockRegex = new RegExp(
|
|
44
|
+
`\\/\\* @oxcide-sync:source[\\s\\S]*?@oxcide-sync:end \\*\\/[\\s\\S]*?(?=export function|$)`,
|
|
45
|
+
'g',
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
// 2. Detect original Zod inference lines
|
|
49
|
+
const originalRegex = new RegExp(
|
|
50
|
+
`export type ${capitalizedBaseName}Props = z\\.input<typeof ${schemaName}>;?\\s+` +
|
|
51
|
+
`export type ${capitalizedBaseName}ResolvedProps = z\\.infer<typeof ${schemaName}>;?`,
|
|
52
|
+
'g',
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Create temporary types to resolve the expansion
|
|
56
|
+
const tempInputType = sourceFile.addTypeAlias({
|
|
57
|
+
name: `__Temp${capitalizedBaseName}Input`,
|
|
58
|
+
type: `z.input<typeof ${schemaName}>`,
|
|
59
|
+
})
|
|
60
|
+
const tempResolvedType = sourceFile.addTypeAlias({
|
|
61
|
+
name: `__Temp${capitalizedBaseName}Resolved`,
|
|
62
|
+
type: `z.infer<typeof ${schemaName}>`,
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const inputTypeText = tempInputType.getType().getApparentType().getText(tempInputType)
|
|
66
|
+
const resolvedTypeText = tempResolvedType.getType().getApparentType().getText(tempResolvedType)
|
|
67
|
+
|
|
68
|
+
tempInputType.remove()
|
|
69
|
+
tempResolvedType.remove()
|
|
70
|
+
|
|
71
|
+
const newSyncBlock = [
|
|
72
|
+
`/* @oxcide-sync:source`,
|
|
73
|
+
`export type ${capitalizedBaseName}Props = z.input<typeof ${schemaName}>`,
|
|
74
|
+
`export type ${capitalizedBaseName}ResolvedProps = z.infer<typeof ${schemaName}>`,
|
|
75
|
+
`@oxcide-sync:end */`,
|
|
76
|
+
`export interface ${capitalizedBaseName}Props ${inputTypeText}`,
|
|
77
|
+
`export type ${capitalizedBaseName}ResolvedProps = ${resolvedTypeText}`,
|
|
78
|
+
'\n',
|
|
79
|
+
].join('\n')
|
|
80
|
+
|
|
81
|
+
let newContent = ''
|
|
82
|
+
if (syncBlockRegex.test(content)) {
|
|
83
|
+
newContent = content.replace(syncBlockRegex, newSyncBlock)
|
|
84
|
+
} else if (originalRegex.test(content)) {
|
|
85
|
+
newContent = content.replace(originalRegex, newSyncBlock)
|
|
86
|
+
} else {
|
|
87
|
+
// If none found, find the schema and append after it
|
|
88
|
+
console.warn(pc.yellow(`❓ Could not find target declarations in ${fileName}. Appending.`))
|
|
89
|
+
newContent = content + '\n' + newSyncBlock
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
sourceFile.replaceWithText(newContent)
|
|
93
|
+
sourceFile.formatText({ indentSize: 2 })
|
|
94
|
+
await sourceFile.save()
|
|
95
|
+
console.log(pc.green(`✅ Successfully synced ${pc.bold(fileName)}`))
|
|
96
|
+
updatedCount++
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(pc.cyan(`\n✨ Type synchronization complete! Updated ${pc.bold(updatedCount)} files.\n`))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
syncTypes().catch((error) => {
|
|
103
|
+
console.error(pc.red(`\n❌ Type sync failed: ${error.message}\n`))
|
|
104
|
+
process.exit(1)
|
|
105
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export const badgePropsSchema = z.object({
|
|
4
|
+
/** Severity / semantic color */
|
|
5
|
+
severity: z
|
|
6
|
+
.enum(['primary', 'secondary', 'success', 'info', 'warning', 'danger', 'help', 'contrast'])
|
|
7
|
+
.default('primary'),
|
|
8
|
+
/** Size */
|
|
9
|
+
size: z.enum(['xs', 'sm', 'md', 'lg', 'xl']).default('md'),
|
|
10
|
+
/** Value to display */
|
|
11
|
+
value: z.union([z.string(), z.number()]).optional()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
/* @oxcide-sync:source
|
|
15
|
+
export type BadgeProps = z.input<typeof badgePropsSchema>
|
|
16
|
+
export type BadgeResolvedProps = z.infer<typeof badgePropsSchema>
|
|
17
|
+
@oxcide-sync:end */
|
|
18
|
+
export interface BadgeProps {
|
|
19
|
+
severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' | 'help' | 'contrast' | undefined
|
|
20
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | undefined
|
|
21
|
+
value?: string | number | undefined
|
|
22
|
+
}
|
|
23
|
+
export type BadgeResolvedProps = {
|
|
24
|
+
severity: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' | 'help' | 'contrast'
|
|
25
|
+
size: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
26
|
+
value?: string | number | undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getBadgeDefaults(props: BadgeProps = {}): BadgeResolvedProps {
|
|
30
|
+
return badgePropsSchema.parse(props)
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export const boxPropsSchema = z.object({
|
|
4
|
+
as: z.string().default('div')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
export function getBoxDefaults(props: BoxProps = {}): BoxResolvedProps {
|
|
8
|
+
return boxPropsSchema.parse(props)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* @oxcide-sync:source
|
|
12
|
+
export type BoxProps = z.input<typeof boxPropsSchema>
|
|
13
|
+
export type BoxResolvedProps = z.infer<typeof boxPropsSchema>
|
|
14
|
+
@oxcide-sync:end */
|
|
15
|
+
export interface BoxProps {
|
|
16
|
+
as?: string | undefined
|
|
17
|
+
}
|
|
18
|
+
export type BoxResolvedProps = { as: string }
|