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.
Files changed (2) hide show
  1. package/dist/index.mjs +315 -31
  2. 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.99";
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: ["react"]
200
+ frameworks: { react: {} }
201
201
  },
202
202
  monochrome: {
203
203
  name: "Monochrome",
204
- frameworks: [
205
- "react",
206
- "solid",
207
- "svelte",
208
- "vue"
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.1",
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.1",
441
- "typescript": "~5.9.3",
442
- "vite": "^8.0.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.1",
789
+ "@tailwindcss/vite": "^4.2.2",
605
790
  "@types/node": "^24.12.0",
606
- "tailwindcss": "^4.2.1",
607
- "typescript": "~5.9.3",
608
- "vite": "^8.0.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.1",
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.1",
773
- "typescript": "~5.9.3",
774
- "vite": "^8.0.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.1",
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.1",
929
- "typescript": "~5.9.3",
930
- "vite": "^8.0.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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprawlify",
3
- "version": "0.0.99",
3
+ "version": "0.0.101",
4
4
  "type": "module",
5
5
  "description": "A command-line interface for Sprawlify.",
6
6
  "author": "sprawlify <npm@sprawlify.com>",