sprawlify 0.0.99 → 0.0.101
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/dist/index.mjs +315 -31
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { existsSync } from "fs";
|
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
import { faker } from "@faker-js/faker";
|
|
10
10
|
//#region package.json
|
|
11
|
-
var version = "0.0.
|
|
11
|
+
var version = "0.0.101";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/utils/file-helper.ts
|
|
14
14
|
const FILE_BACKUP_SUFFIX = ".bak";
|
|
@@ -197,18 +197,199 @@ const METAFRAMEWORKS = {
|
|
|
197
197
|
const PRESETS = {
|
|
198
198
|
clay: {
|
|
199
199
|
name: "Clay",
|
|
200
|
-
frameworks:
|
|
200
|
+
frameworks: { react: {} }
|
|
201
201
|
},
|
|
202
202
|
monochrome: {
|
|
203
203
|
name: "Monochrome",
|
|
204
|
-
frameworks:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
frameworks: {
|
|
205
|
+
react: {
|
|
206
|
+
dependencies: {
|
|
207
|
+
"@sprawlify/react": "^0.0.100",
|
|
208
|
+
"class-variance-authority": "^0.7.1",
|
|
209
|
+
clsx: "^2.1.1",
|
|
210
|
+
react: "^18.2.0",
|
|
211
|
+
"tailwind-merge": "^3.3.1"
|
|
212
|
+
},
|
|
213
|
+
devDependencies: {},
|
|
214
|
+
items: [
|
|
215
|
+
{
|
|
216
|
+
name: "alert",
|
|
217
|
+
dependencies: [
|
|
218
|
+
"react",
|
|
219
|
+
"class-variance-authority",
|
|
220
|
+
"@/lib/utils",
|
|
221
|
+
"@sprawlify/react"
|
|
222
|
+
],
|
|
223
|
+
files: [{
|
|
224
|
+
content: "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nconst alertVariants = cva(\n \"grid gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<typeof sprawlify.div> & VariantProps<typeof alertVariants>) {\n return (\n <sprawlify.div\n data-scope=\"alert\"\n data-part=\"root\"\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"alert\"\n data-part=\"title\"\n data-slot=\"alert-title\"\n className={cn(\n \"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AlertDescription({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"alert\"\n data-part=\"description\"\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AlertAction({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"alert\"\n data-part=\"action\"\n data-slot=\"alert-action\"\n className={cn(\"absolute top-2 right-2\", className)}\n {...props}\n />\n );\n}\n\nexport { Alert, AlertTitle, AlertDescription, AlertAction };\n",
|
|
225
|
+
type: "registry:ui",
|
|
226
|
+
path: "alert.tsx"
|
|
227
|
+
}]
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: "aspect-ratio",
|
|
231
|
+
dependencies: ["@sprawlify/react"],
|
|
232
|
+
files: [{
|
|
233
|
+
content: "import { AspectRatio as AspectRatioPrimitive } from \"@sprawlify/react/aspect-ratio\";\n\nfunction AspectRatio({\n children,\n ...props\n}: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {\n return (\n <AspectRatioPrimitive.Root data-slot=\"aspect-ratio\" {...props}>\n <AspectRatioPrimitive.Content data-slot=\"aspect-ratio-content\">\n {children}\n </AspectRatioPrimitive.Content>\n </AspectRatioPrimitive.Root>\n );\n}\n\nexport { AspectRatio };\n",
|
|
234
|
+
type: "registry:ui",
|
|
235
|
+
path: "aspect-ratio.tsx"
|
|
236
|
+
}]
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: "avatar",
|
|
240
|
+
dependencies: [
|
|
241
|
+
"react",
|
|
242
|
+
"@sprawlify/react",
|
|
243
|
+
"@/lib"
|
|
244
|
+
],
|
|
245
|
+
files: [{
|
|
246
|
+
content: "import * as React from \"react\";\nimport { Avatar as AvatarPrimitive } from \"@sprawlify/react/avatar\";\nimport { cn } from \"@/lib/utils\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nfunction Avatar({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root> & {\n size?: \"default\" | \"sm\" | \"lg\";\n}) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"group/avatar relative flex size-8 shrink-0 rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square rounded-[inherit] size-full overflow-hidden\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"rounded-[inherit] overflow-hidden bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<typeof sprawlify.span>) {\n return (\n <sprawlify.span\n data-scope=\"avatar\"\n data-part=\"badge\"\n data-slot=\"avatar-badge\"\n className={cn(\n \"bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full ring-2 select-none\",\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"avatar\"\n data-paert=\"group\"\n data-slot=\"avatar-group\"\n className={cn(\n \"*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarGroupCount({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"avatar\"\n data-paert=\"group-count\"\n data-slot=\"avatar-group-count\"\n className={cn(\n \"bg-muted text-muted-foreground ring-background relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup, AvatarGroupCount };\n",
|
|
247
|
+
type: "registry:ui",
|
|
248
|
+
path: "avatar.tsx"
|
|
249
|
+
}]
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "badge",
|
|
253
|
+
dependencies: [
|
|
254
|
+
"react",
|
|
255
|
+
"class-variance-authority",
|
|
256
|
+
"@/lib/utils",
|
|
257
|
+
"@sprawlify/react"
|
|
258
|
+
],
|
|
259
|
+
files: [{
|
|
260
|
+
content: "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary: \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof sprawlify.span> & VariantProps<typeof badgeVariants>) {\n return (\n <sprawlify.span\n data-scope=\"badge\"\n data-part=\"root\"\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nexport { Badge, badgeVariants };\n",
|
|
261
|
+
type: "registry:ui",
|
|
262
|
+
path: "badge.tsx"
|
|
263
|
+
}]
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "button-group",
|
|
267
|
+
type: "registry:ui",
|
|
268
|
+
dependencies: [
|
|
269
|
+
"class-variance-authority",
|
|
270
|
+
"@/lib/utils",
|
|
271
|
+
"@/components/ui/separator",
|
|
272
|
+
"@sprawlify/react"
|
|
273
|
+
],
|
|
274
|
+
files: [{
|
|
275
|
+
content: "import { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nconst buttonGroupVariants = cva(\n \"has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg flex w-fit items-stretch *:focus-visible:z-10 *:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1\",\n {\n variants: {\n orientation: {\n horizontal:\n \"[&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-lg! [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\",\n vertical:\n \"[&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-lg! flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n },\n },\n);\n\nfunction ButtonGroup({\n className,\n orientation,\n ...props\n}: React.ComponentProps<typeof sprawlify.div> & VariantProps<typeof buttonGroupVariants>) {\n return (\n <sprawlify.div\n data-scope=\"button-group\"\n data-part=\"root\"\n role=\"group\"\n data-slot=\"button-group\"\n data-orientation={orientation}\n className={cn(buttonGroupVariants({ orientation, className }))}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupText({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n className={cn(\n \"bg-muted gap-2 rounded-lg border px-2.5 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ButtonGroupSeparator({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-scope=\"button-group\"\n data-part=\"separator\"\n data-slot=\"button-group-separator\"\n orientation={orientation}\n className={cn(\n \"bg-input relative self-stretch data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants };\n",
|
|
276
|
+
type: "registry:ui",
|
|
277
|
+
path: "button-group.tsx"
|
|
278
|
+
}]
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
name: "button",
|
|
282
|
+
dependencies: [
|
|
283
|
+
"react",
|
|
284
|
+
"class-variance-authority",
|
|
285
|
+
"@/lib/utils",
|
|
286
|
+
"@sprawlify/react"
|
|
287
|
+
],
|
|
288
|
+
files: [{
|
|
289
|
+
content: "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nconst buttonVariants = cva(\n \"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground\",\n destructive:\n \"bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof sprawlify.button> & VariantProps<typeof buttonVariants>) {\n return (\n <sprawlify.button\n data-scope=\"button\"\n data-part=\"root\"\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n",
|
|
290
|
+
type: "registry:ui",
|
|
291
|
+
path: "button.tsx"
|
|
292
|
+
}]
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "card",
|
|
296
|
+
dependencies: [
|
|
297
|
+
"react",
|
|
298
|
+
"@/lib/utils",
|
|
299
|
+
"@sprawlify/react"
|
|
300
|
+
],
|
|
301
|
+
files: [{
|
|
302
|
+
content: "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { sprawlify } from \"@sprawlify/react\";\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof sprawlify.div> & { size?: \"default\" | \"sm\" }) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"root\"\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"header\"\n data-slot=\"card-header\"\n className={cn(\n \"gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"title\"\n data-slot=\"card-title\"\n className={cn(\n \"text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"description\"\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"action\"\n data-slot=\"card-action\"\n className={cn(\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\", className)}\n {...props}\n />\n );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"content\"\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n );\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<typeof sprawlify.div>) {\n return (\n <sprawlify.div\n data-scope=\"card\"\n data-part=\"footer\"\n data-slot=\"card-footer\"\n className={cn(\n \"bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };\n",
|
|
303
|
+
type: "registry:ui",
|
|
304
|
+
path: "card.tsx"
|
|
305
|
+
}]
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: "checkbox",
|
|
309
|
+
dependencies: [
|
|
310
|
+
"react",
|
|
311
|
+
"@sprawlify/react",
|
|
312
|
+
"@/lib/utils",
|
|
313
|
+
"lucide-react"
|
|
314
|
+
],
|
|
315
|
+
files: [{
|
|
316
|
+
content: "import * as React from \"react\";\nimport { Checkbox as CheckboxPrimitive } from \"@sprawlify/react/checkbox\";\nimport { cn } from \"@/lib/utils\";\nimport { CheckIcon } from \"lucide-react\";\n\nfunction Checkbox({ className, ...props }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"[&>svg]:size-3.5 grid place-content-center text-current transition-none\"\n >\n <CheckIcon />\n </CheckboxPrimitive.Indicator>\n <CheckboxPrimitive.HiddenInput />\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n",
|
|
317
|
+
type: "registry:ui",
|
|
318
|
+
path: "checkbox.tsx"
|
|
319
|
+
}]
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
name: "utils",
|
|
323
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
324
|
+
files: [{
|
|
325
|
+
content: "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
|
326
|
+
type: "registry:utils",
|
|
327
|
+
path: "utils.ts"
|
|
328
|
+
}]
|
|
329
|
+
}
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
solid: {
|
|
333
|
+
dependencies: {
|
|
334
|
+
"class-variance-authority": "^0.7.1",
|
|
335
|
+
clsx: "^2.1.1",
|
|
336
|
+
"tailwind-merge": "^3.3.1"
|
|
337
|
+
},
|
|
338
|
+
devDependencies: {},
|
|
339
|
+
items: [{
|
|
340
|
+
name: "utils",
|
|
341
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
342
|
+
files: [{
|
|
343
|
+
content: "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
|
344
|
+
type: "registry:utils",
|
|
345
|
+
path: "utils.ts"
|
|
346
|
+
}]
|
|
347
|
+
}]
|
|
348
|
+
},
|
|
349
|
+
svelte: {
|
|
350
|
+
dependencies: {
|
|
351
|
+
"class-variance-authority": "^0.7.1",
|
|
352
|
+
clsx: "^2.1.1",
|
|
353
|
+
"tailwind-merge": "^3.3.1"
|
|
354
|
+
},
|
|
355
|
+
devDependencies: {},
|
|
356
|
+
items: [{
|
|
357
|
+
name: "utils",
|
|
358
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
359
|
+
files: [{
|
|
360
|
+
content: "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
|
361
|
+
type: "registry:utils",
|
|
362
|
+
path: "utils.ts"
|
|
363
|
+
}]
|
|
364
|
+
}]
|
|
365
|
+
},
|
|
366
|
+
vue: {
|
|
367
|
+
dependencies: {
|
|
368
|
+
"class-variance-authority": "^0.7.1",
|
|
369
|
+
clsx: "^2.1.1",
|
|
370
|
+
"tailwind-merge": "^3.3.1"
|
|
371
|
+
},
|
|
372
|
+
devDependencies: {},
|
|
373
|
+
items: [{
|
|
374
|
+
name: "utils",
|
|
375
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
376
|
+
files: [{
|
|
377
|
+
content: "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
|
378
|
+
type: "registry:utils",
|
|
379
|
+
path: "utils.ts"
|
|
380
|
+
}]
|
|
381
|
+
}]
|
|
382
|
+
}
|
|
383
|
+
}
|
|
210
384
|
}
|
|
211
385
|
};
|
|
386
|
+
function getPresetItems(presetName, frameworkName) {
|
|
387
|
+
return getFrameworkPreset(presetName, frameworkName)?.items ?? [];
|
|
388
|
+
}
|
|
389
|
+
function getFrameworkPreset(presetName, frameworkName) {
|
|
390
|
+
if (!presetName || !frameworkName) return;
|
|
391
|
+
return PRESETS[presetName]?.frameworks?.[frameworkName];
|
|
392
|
+
}
|
|
212
393
|
//#endregion
|
|
213
394
|
//#region src/commands/init/options.ts
|
|
214
395
|
const initOptionsSchema = z.object({
|
|
@@ -295,7 +476,7 @@ async function promptForMissingSelections(options) {
|
|
|
295
476
|
choices: Object.entries(PRESETS).map(([key, preset]) => ({
|
|
296
477
|
title: preset.name,
|
|
297
478
|
value: key,
|
|
298
|
-
disabled: !preset.frameworks.includes(options.framework)
|
|
479
|
+
disabled: !Object.keys(preset.frameworks).includes(options.framework)
|
|
299
480
|
})),
|
|
300
481
|
initial: 0
|
|
301
482
|
});
|
|
@@ -427,19 +608,21 @@ dist-ssr
|
|
|
427
608
|
"preview": "vite preview"
|
|
428
609
|
},
|
|
429
610
|
"dependencies": {
|
|
611
|
+
"@sprawlify/primitives": "^0.0.100",
|
|
612
|
+
"@sprawlify/react": "^0.0.100",
|
|
430
613
|
"react": "^19.2.4",
|
|
431
614
|
"react-dom": "^19.2.4"
|
|
432
615
|
},
|
|
433
616
|
"devDependencies": {
|
|
434
|
-
"@tailwindcss/vite": "^4.2.
|
|
617
|
+
"@tailwindcss/vite": "^4.2.2",
|
|
435
618
|
"@types/node": "^24.12.0",
|
|
436
619
|
"@types/react": "^19.2.14",
|
|
437
620
|
"@types/react-dom": "^19.2.3",
|
|
438
621
|
"@vitejs/plugin-react": "^6.0.1",
|
|
439
622
|
"globals": "^17.4.0",
|
|
440
|
-
"tailwindcss": "^4.2.
|
|
441
|
-
"typescript": "
|
|
442
|
-
"vite": "^8.0.
|
|
623
|
+
"tailwindcss": "^4.2.2",
|
|
624
|
+
"typescript": "^5.9.3",
|
|
625
|
+
"vite": "^8.0.1"
|
|
443
626
|
}
|
|
444
627
|
}`
|
|
445
628
|
},
|
|
@@ -598,14 +781,16 @@ dist-ssr
|
|
|
598
781
|
"preview": "vite preview"
|
|
599
782
|
},
|
|
600
783
|
"dependencies": {
|
|
784
|
+
"@sprawlify/primitives": "^0.0.100",
|
|
785
|
+
"@sprawlify/solid": "^0.0.100",
|
|
601
786
|
"solid-js": "^1.9.11"
|
|
602
787
|
},
|
|
603
788
|
"devDependencies": {
|
|
604
|
-
"@tailwindcss/vite": "^4.2.
|
|
789
|
+
"@tailwindcss/vite": "^4.2.2",
|
|
605
790
|
"@types/node": "^24.12.0",
|
|
606
|
-
"tailwindcss": "^4.2.
|
|
607
|
-
"typescript": "
|
|
608
|
-
"vite": "^8.0.
|
|
791
|
+
"tailwindcss": "^4.2.2",
|
|
792
|
+
"typescript": "^5.9.3",
|
|
793
|
+
"vite": "^8.0.1",
|
|
609
794
|
"vite-plugin-solid": "^2.11.11"
|
|
610
795
|
}
|
|
611
796
|
}`
|
|
@@ -762,16 +947,20 @@ dist-ssr
|
|
|
762
947
|
"preview": "vite preview",
|
|
763
948
|
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json"
|
|
764
949
|
},
|
|
950
|
+
"dependencies": {
|
|
951
|
+
"@sprawlify/primitives": "^0.0.100",
|
|
952
|
+
"@sprawlify/svelte": "^0.0.100"
|
|
953
|
+
},
|
|
765
954
|
"devDependencies": {
|
|
766
955
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
767
|
-
"@tailwindcss/vite": "^4.2.
|
|
956
|
+
"@tailwindcss/vite": "^4.2.2",
|
|
768
957
|
"@tsconfig/svelte": "^5.0.8",
|
|
769
958
|
"@types/node": "^24.12.0",
|
|
770
959
|
"svelte": "^5.54.0",
|
|
771
960
|
"svelte-check": "^4.4.5",
|
|
772
|
-
"tailwindcss": "^4.2.
|
|
773
|
-
"typescript": "
|
|
774
|
-
"vite": "^8.0.
|
|
961
|
+
"tailwindcss": "^4.2.2",
|
|
962
|
+
"typescript": "^5.9.3",
|
|
963
|
+
"vite": "^8.0.1"
|
|
775
964
|
}
|
|
776
965
|
}`
|
|
777
966
|
},
|
|
@@ -918,16 +1107,18 @@ dist-ssr
|
|
|
918
1107
|
"preview": "vite preview"
|
|
919
1108
|
},
|
|
920
1109
|
"dependencies": {
|
|
1110
|
+
"@sprawlify/primitives": "^0.0.100",
|
|
1111
|
+
"@sprawlify/vue": "^0.0.100",
|
|
921
1112
|
"vue": "^3.5.30"
|
|
922
1113
|
},
|
|
923
1114
|
"devDependencies": {
|
|
924
|
-
"@tailwindcss/vite": "^4.2.
|
|
1115
|
+
"@tailwindcss/vite": "^4.2.2",
|
|
925
1116
|
"@types/node": "^24.12.0",
|
|
926
1117
|
"@vitejs/plugin-vue": "^6.0.5",
|
|
927
1118
|
"@vue/tsconfig": "^0.9.0",
|
|
928
|
-
"tailwindcss": "^4.2.
|
|
929
|
-
"typescript": "
|
|
930
|
-
"vite": "^8.0.
|
|
1119
|
+
"tailwindcss": "^4.2.2",
|
|
1120
|
+
"typescript": "^5.9.3",
|
|
1121
|
+
"vite": "^8.0.1",
|
|
931
1122
|
"vue-tsc": "^3.2.6"
|
|
932
1123
|
}
|
|
933
1124
|
}`
|
|
@@ -1001,6 +1192,85 @@ export default defineConfig({
|
|
|
1001
1192
|
};
|
|
1002
1193
|
//#endregion
|
|
1003
1194
|
//#region src/commands/init/run-init.ts
|
|
1195
|
+
function resolvePresetFilePath(cwd, file) {
|
|
1196
|
+
const srcPath = path.resolve(cwd, "src");
|
|
1197
|
+
const appPath = path.resolve(cwd, "app");
|
|
1198
|
+
if (file.type === "registry:utils") {
|
|
1199
|
+
if (fsExtra.existsSync(srcPath)) return path.resolve(srcPath, "lib", file.path);
|
|
1200
|
+
if (fsExtra.existsSync(appPath)) return path.resolve(appPath, "lib", file.path);
|
|
1201
|
+
return path.resolve(srcPath, "lib", file.path);
|
|
1202
|
+
}
|
|
1203
|
+
if (file.type === "registry:ui") {
|
|
1204
|
+
if (fsExtra.existsSync(srcPath)) return path.resolve(srcPath, "components", "ui", file.path);
|
|
1205
|
+
if (fsExtra.existsSync(appPath)) return path.resolve(appPath, "components", "ui", file.path);
|
|
1206
|
+
return path.resolve(srcPath, "components", "ui", file.path);
|
|
1207
|
+
}
|
|
1208
|
+
return path.resolve(cwd, file.path);
|
|
1209
|
+
}
|
|
1210
|
+
function resolveItemsToApply(presetItems, requestedComponents) {
|
|
1211
|
+
const presetItemsByName = new Map(presetItems.map((item) => [item.name, item]));
|
|
1212
|
+
const itemNamesToApply = /* @__PURE__ */ new Set();
|
|
1213
|
+
const packageNames = /* @__PURE__ */ new Set();
|
|
1214
|
+
const unresolvedNames = /* @__PURE__ */ new Set();
|
|
1215
|
+
const queue = requestedComponents.size === 0 ? presetItems.map((item) => item.name) : [...requestedComponents];
|
|
1216
|
+
while (queue.length > 0) {
|
|
1217
|
+
const dependencyName = queue.shift();
|
|
1218
|
+
if (!dependencyName) continue;
|
|
1219
|
+
const matchingItem = presetItemsByName.get(dependencyName);
|
|
1220
|
+
if (matchingItem) {
|
|
1221
|
+
if (itemNamesToApply.has(matchingItem.name)) continue;
|
|
1222
|
+
itemNamesToApply.add(matchingItem.name);
|
|
1223
|
+
for (const nestedDependency of matchingItem.dependencies ?? []) queue.push(nestedDependency);
|
|
1224
|
+
continue;
|
|
1225
|
+
}
|
|
1226
|
+
packageNames.add(dependencyName);
|
|
1227
|
+
}
|
|
1228
|
+
if (requestedComponents.size > 0) {
|
|
1229
|
+
for (const componentName of requestedComponents) if (!presetItemsByName.has(componentName)) unresolvedNames.add(componentName);
|
|
1230
|
+
}
|
|
1231
|
+
return {
|
|
1232
|
+
itemsToApply: [...itemNamesToApply].map((itemName) => presetItemsByName.get(itemName)).filter((item) => Boolean(item)),
|
|
1233
|
+
packageNames,
|
|
1234
|
+
unresolvedNames
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
async function applyPresetPackageDependencies(cwd, frameworkPreset, packageNames) {
|
|
1238
|
+
if (!frameworkPreset || packageNames.size === 0) return;
|
|
1239
|
+
const packageJsonPath = path.resolve(cwd, "package.json");
|
|
1240
|
+
if (!fsExtra.existsSync(packageJsonPath)) {
|
|
1241
|
+
logger.warn("Skipping preset package dependencies because package.json was not found.");
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
const packageJson = await fsExtra.readJson(packageJsonPath);
|
|
1245
|
+
let didChange = false;
|
|
1246
|
+
const missingPackages = [];
|
|
1247
|
+
packageJson.dependencies ??= {};
|
|
1248
|
+
packageJson.devDependencies ??= {};
|
|
1249
|
+
for (const packageName of packageNames) {
|
|
1250
|
+
const dependencyVersion = frameworkPreset.dependencies?.[packageName];
|
|
1251
|
+
if (dependencyVersion) {
|
|
1252
|
+
if (!packageJson.dependencies[packageName]) {
|
|
1253
|
+
packageJson.dependencies[packageName] = dependencyVersion;
|
|
1254
|
+
didChange = true;
|
|
1255
|
+
}
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
const devDependencyVersion = frameworkPreset.devDependencies?.[packageName];
|
|
1259
|
+
if (devDependencyVersion) {
|
|
1260
|
+
if (!packageJson.devDependencies[packageName]) {
|
|
1261
|
+
packageJson.devDependencies[packageName] = devDependencyVersion;
|
|
1262
|
+
didChange = true;
|
|
1263
|
+
}
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
missingPackages.push(packageName);
|
|
1267
|
+
}
|
|
1268
|
+
if (didChange) {
|
|
1269
|
+
await fsExtra.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
1270
|
+
logger.success("Updated package.json with preset package dependencies.");
|
|
1271
|
+
}
|
|
1272
|
+
if (missingPackages.length > 0) logger.warn(`Skipping unresolved preset packages: ${missingPackages.map((packageName) => highlighter.info(packageName)).join(", ")}.`);
|
|
1273
|
+
}
|
|
1004
1274
|
async function runInit(options) {
|
|
1005
1275
|
let cwd = options.cwd;
|
|
1006
1276
|
if (options.name && options.name !== ".") {
|
|
@@ -1026,12 +1296,7 @@ async function runInit(options) {
|
|
|
1026
1296
|
$schema: "https://ui.primitives.com/schema.json",
|
|
1027
1297
|
framework: options.framework,
|
|
1028
1298
|
preset: options.preset,
|
|
1029
|
-
metaframework: options.metaframework
|
|
1030
|
-
aliases: {
|
|
1031
|
-
components: "@/components",
|
|
1032
|
-
ui: "@/components/ui",
|
|
1033
|
-
utils: "@/lib/utils"
|
|
1034
|
-
}
|
|
1299
|
+
metaframework: options.metaframework
|
|
1035
1300
|
};
|
|
1036
1301
|
let backupPath = null;
|
|
1037
1302
|
if (fsExtra.existsSync(componentsJsonPath)) {
|
|
@@ -1052,6 +1317,25 @@ async function runInit(options) {
|
|
|
1052
1317
|
}
|
|
1053
1318
|
throw error;
|
|
1054
1319
|
}
|
|
1320
|
+
const frameworkPreset = getFrameworkPreset(options.preset, options.framework);
|
|
1321
|
+
const { itemsToApply, packageNames, unresolvedNames } = resolveItemsToApply(getPresetItems(options.preset, options.framework), new Set(options.components ?? []));
|
|
1322
|
+
if (unresolvedNames.size > 0) logger.warn(`Skipping unknown preset component options: ${[...unresolvedNames].map((componentName) => highlighter.info(componentName)).join(", ")}.`);
|
|
1323
|
+
if (itemsToApply.length === 0) {
|
|
1324
|
+
await applyPresetPackageDependencies(cwd, frameworkPreset, packageNames);
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
await applyPresetPackageDependencies(cwd, frameworkPreset, packageNames);
|
|
1328
|
+
logger.info(`Applying preset components: ${itemsToApply.map((item) => highlighter.info(item.name)).join(", ")}.`);
|
|
1329
|
+
for (const item of itemsToApply) for (const file of item.files ?? []) {
|
|
1330
|
+
const targetPath = resolvePresetFilePath(cwd, file);
|
|
1331
|
+
if (fsExtra.existsSync(targetPath) && !options.override) {
|
|
1332
|
+
logger.warn(`Skipping ${highlighter.info(path.relative(cwd, targetPath))} because it already exists. Use ${highlighter.info("--override")} to replace it.`);
|
|
1333
|
+
continue;
|
|
1334
|
+
}
|
|
1335
|
+
await fsExtra.ensureDir(path.dirname(targetPath));
|
|
1336
|
+
await fsExtra.writeFile(targetPath, file.content, "utf8");
|
|
1337
|
+
logger.success(`Created ${highlighter.info(path.relative(cwd, targetPath))} from preset component ${highlighter.info(item.name)}.`);
|
|
1338
|
+
}
|
|
1055
1339
|
}
|
|
1056
1340
|
//#endregion
|
|
1057
1341
|
//#region src/commands/init.ts
|