ui-thing 0.1.19 → 0.1.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui-thing",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "CLI used to add Nuxt 3 components to a project",
5
5
  "keywords": [
6
6
  "cli",
@@ -39,33 +39,33 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "axios": "^1.7.2",
42
- "boxen": "^7.1.1",
42
+ "boxen": "^8.0.0",
43
43
  "build": "^0.1.4",
44
- "c12": "^1.10.0",
44
+ "c12": "^1.11.1",
45
45
  "commander": "^12.1.0",
46
46
  "defu": "^6.1.4",
47
- "execa": "^9.2.0",
47
+ "execa": "^9.3.0",
48
48
  "figlet": "^1.7.0",
49
49
  "fs-extra": "^11.2.0",
50
50
  "kleur": "^4.1.5",
51
51
  "lodash": "^4.17.21",
52
- "nypm": "^0.3.8",
52
+ "nypm": "^0.3.9",
53
53
  "ora": "^8.0.1",
54
54
  "prompts": "^2.4.2"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@gmrchk/cli-testing-library": "^0.1.2",
58
- "@ianvs/prettier-plugin-sort-imports": "^4.2.1",
58
+ "@ianvs/prettier-plugin-sort-imports": "^4.3.1",
59
59
  "@types/figlet": "^1.5.8",
60
60
  "@types/fs-extra": "^11.0.4",
61
- "@types/lodash": "^4.17.4",
62
- "@types/node": "^20.14.2",
61
+ "@types/lodash": "^4.17.6",
62
+ "@types/node": "^20.14.10",
63
63
  "@types/prompts": "^2.4.9",
64
- "@vitest/coverage-v8": "^1.6.0",
64
+ "@vitest/coverage-v8": "^2.0.2",
65
65
  "magicast": "^0.3.4",
66
66
  "tsup": "^8.1.0",
67
- "typescript": "^5.4.5",
68
- "vitest": "^1.6.0"
67
+ "typescript": "^5.5.3",
68
+ "vitest": "^2.0.2"
69
69
  },
70
70
  "publishConfig": {
71
71
  "access": "public"
@@ -233,7 +233,11 @@ export const add = new Command()
233
233
  // add plugins attached to the component
234
234
  loop5: for (let j = 0; j < component.plugins.length; j++) {
235
235
  const plugin = component.plugins[j];
236
- const filePath = path.join(currentDirectory, plugin.dirPath, plugin.fileName);
236
+ const filePath = path.join(
237
+ currentDirectory,
238
+ uiConfig.pluginsLocation ?? plugin.dirPath,
239
+ plugin.fileName
240
+ );
237
241
  // Check if the file exists
238
242
  const exists = await fileExists(filePath);
239
243
  if (exists && !uiConfig.force) {
package/src/comps.ts CHANGED
@@ -388,7 +388,7 @@ export default [
388
388
  fileName: "Card/Footer.vue",
389
389
  dirPath: "components/UI",
390
390
  fileContent:
391
- '<template>\n <Primitive :class="styles({ class: props.class })" :as="as" :as-child="asChild">\n <slot />\n </Primitive>\n</template>\n\n<script lang="ts" setup>\n import { Primitive } from "radix-vue";\n import type { PrimitiveProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n PrimitiveProps & {\n /** Custom class(es) to add to the element */\n class?: any;\n }\n >(),\n { as: "div" }\n );\n\n const styles = tv({\n base: "flex items-center p-6 ",\n });\n</script>\n',
391
+ '<template>\n <Primitive :class="styles({ class: props.class })" :as="as" :as-child="asChild">\n <slot />\n </Primitive>\n</template>\n\n<script lang="ts" setup>\n import { Primitive } from "radix-vue";\n import type { PrimitiveProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n PrimitiveProps & {\n /** Custom class(es) to add to the element */\n class?: any;\n }\n >(),\n { as: "div" }\n );\n\n const styles = tv({\n base: "flex items-center p-6",\n });\n</script>\n',
392
392
  },
393
393
  {
394
394
  fileName: "Card/Header.vue",
@@ -1030,7 +1030,7 @@ export default [
1030
1030
  fileName: "FancyIcon.vue",
1031
1031
  dirPath: "components/UI",
1032
1032
  fileContent:
1033
- '<template>\n <div :class="styles().base({ class: props.class, color, type, size, circle })">\n <slot :styles="styles().icon({ color, type, size, circle })">\n <Icon :name="icon" :class="styles().icon({ color, type, size, circle })" />\n </slot>\n </div>\n</template>\n\n<script lang="ts" setup>\n const props = withDefaults(\n defineProps<{\n class?: any;\n icon: string;\n color?: VariantProps<typeof styles>["color"];\n type?: VariantProps<typeof styles>["type"];\n size?: VariantProps<typeof styles>["size"];\n circle?: boolean;\n }>(),\n {\n color: "primary",\n type: "modern",\n size: "lg",\n circle: false,\n }\n );\n\n const styles = tv({\n slots: {\n base: "flex shrink-0 items-center justify-center",\n icon: "",\n },\n\n variants: {\n color: {\n primary: {\n base: "",\n icon: "",\n },\n success: {\n base: "",\n icon: "",\n },\n warning: {\n base: "",\n icon: "",\n },\n error: {\n base: "",\n icon: "",\n },\n info: {\n base: "",\n icon: "",\n },\n },\n type: {\n light: {\n base: "",\n icon: "",\n },\n dark: {\n base: "",\n icon: "",\n },\n modern: {\n base: "",\n icon: "",\n },\n },\n size: {\n sm: {\n base: "size-8",\n icon: "size-4",\n },\n md: {\n base: "size-10",\n icon: "size-5",\n },\n lg: {\n base: "size-12",\n icon: "size-6",\n },\n xl: {\n base: "size-14",\n icon: "size-7",\n },\n },\n circle: {\n true: {\n base: "rounded-full",\n },\n false: {\n base: "rounded-lg",\n },\n },\n },\n compoundVariants: [\n {\n color: "primary",\n type: "light",\n class: { base: "bg-primary/5 ", icon: "text-primary" },\n },\n {\n color: "success",\n type: "light",\n class: {\n base: "bg-green-500/10",\n icon: "text-green-600",\n },\n },\n {\n color: "warning",\n type: "light",\n class: { base: "bg-amber-500/10", icon: "text-amber-600" },\n },\n {\n color: "error",\n type: "light",\n class: { base: "bg-destructive/10", icon: "text-destructive" },\n },\n {\n color: "info",\n type: "light",\n class: { base: "bg-blue-500/10", icon: "text-blue-600" },\n },\n // Dark\n {\n color: "primary",\n type: "dark",\n class: { base: "bg-primary", icon: "text-primary-foreground" },\n },\n {\n color: "success",\n type: "dark",\n class: { base: "bg-green-600", icon: "text-green-50" },\n },\n {\n color: "warning",\n type: "dark",\n class: { base: "bg-amber-600", icon: "text-amber-50" },\n },\n {\n color: "error",\n type: "dark",\n class: { base: "bg-destructive", icon: "text-destructive-foreground" },\n },\n {\n color: "info",\n type: "dark",\n class: { base: "bg-blue-500", icon: "text-blue-50" },\n },\n // Modern\n {\n type: "modern",\n class: { base: "border bg-background", icon: "text-muted-foreground" },\n },\n ],\n defaultVariants: {\n color: "primary",\n type: "modern",\n size: "lg",\n circle: false,\n },\n });\n</script>\n',
1033
+ '<template>\n <div :class="styles().base({ class: props.class, color, type, size, circle })">\n <slot :styles="styles().icon({ color, type, size, circle })">\n <Icon :name="icon" :class="styles().icon({ color, type, size, circle })" />\n </slot>\n </div>\n</template>\n\n<script lang="ts" setup>\n const props = withDefaults(\n defineProps<{\n class?: any;\n icon: string;\n color?: VariantProps<typeof styles>["color"];\n type?: VariantProps<typeof styles>["type"];\n size?: VariantProps<typeof styles>["size"];\n circle?: boolean;\n }>(),\n {\n color: "primary",\n type: "modern",\n size: "lg",\n circle: false,\n }\n );\n\n const styles = tv({\n slots: {\n base: "flex shrink-0 items-center justify-center",\n icon: "",\n },\n\n variants: {\n color: {\n primary: {\n base: "",\n icon: "",\n },\n success: {\n base: "",\n icon: "",\n },\n warning: {\n base: "",\n icon: "",\n },\n error: {\n base: "",\n icon: "",\n },\n info: {\n base: "",\n icon: "",\n },\n },\n type: {\n light: {\n base: "",\n icon: "",\n },\n dark: {\n base: "",\n icon: "",\n },\n modern: {\n base: "",\n icon: "",\n },\n },\n size: {\n sm: {\n base: "size-8",\n icon: "size-4",\n },\n md: {\n base: "size-10",\n icon: "size-5",\n },\n lg: {\n base: "size-12",\n icon: "size-6",\n },\n xl: {\n base: "size-14",\n icon: "size-7",\n },\n },\n circle: {\n true: {\n base: "rounded-full",\n },\n false: {\n base: "rounded-lg",\n },\n },\n },\n compoundVariants: [\n {\n color: "primary",\n type: "light",\n class: { base: "bg-primary/5", icon: "text-primary" },\n },\n {\n color: "success",\n type: "light",\n class: {\n base: "bg-green-500/10",\n icon: "text-green-600",\n },\n },\n {\n color: "warning",\n type: "light",\n class: { base: "bg-amber-500/10", icon: "text-amber-600" },\n },\n {\n color: "error",\n type: "light",\n class: { base: "bg-destructive/10", icon: "text-destructive" },\n },\n {\n color: "info",\n type: "light",\n class: { base: "bg-blue-500/10", icon: "text-blue-600" },\n },\n // Dark\n {\n color: "primary",\n type: "dark",\n class: { base: "bg-primary", icon: "text-primary-foreground" },\n },\n {\n color: "success",\n type: "dark",\n class: { base: "bg-green-600", icon: "text-green-50" },\n },\n {\n color: "warning",\n type: "dark",\n class: { base: "bg-amber-600", icon: "text-amber-50" },\n },\n {\n color: "error",\n type: "dark",\n class: { base: "bg-destructive", icon: "text-destructive-foreground" },\n },\n {\n color: "info",\n type: "dark",\n class: { base: "bg-blue-500", icon: "text-blue-50" },\n },\n // Modern\n {\n type: "modern",\n class: { base: "border bg-background", icon: "text-muted-foreground" },\n },\n ],\n defaultVariants: {\n color: "primary",\n type: "modern",\n size: "lg",\n circle: false,\n },\n });\n</script>\n',
1034
1034
  },
1035
1035
  ],
1036
1036
  utils: [],
@@ -1108,7 +1108,7 @@ export default [
1108
1108
  fileName: "HoverCard/Arrow.vue",
1109
1109
  dirPath: "components/UI",
1110
1110
  fileContent:
1111
- '<template>\n <HoverCardArrow :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')" />\n</template>\n\n<script lang="ts" setup>\n import { HoverCardArrow } from "radix-vue";\n import type { HoverCardArrowProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n HoverCardArrowProps & {\n /** Custom class(es) to add to the parent */\n class?: any;\n }\n >(),\n {\n height: 5,\n width: 10,\n }\n );\n\n const styles = tv({\n base: " fill-popover",\n });\n</script>\n',
1111
+ '<template>\n <HoverCardArrow :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')" />\n</template>\n\n<script lang="ts" setup>\n import { HoverCardArrow } from "radix-vue";\n import type { HoverCardArrowProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n HoverCardArrowProps & {\n /** Custom class(es) to add to the parent */\n class?: any;\n }\n >(),\n {\n height: 5,\n width: 10,\n }\n );\n\n const styles = tv({\n base: "fill-popover",\n });\n</script>\n',
1112
1112
  },
1113
1113
  {
1114
1114
  fileName: "HoverCard/Content.vue",
@@ -1407,7 +1407,7 @@ export default [
1407
1407
  fileName: "NativeSelect.vue",
1408
1408
  dirPath: "components/UI",
1409
1409
  fileContent:
1410
- '<template>\n <div class="relative">\n <select\n :id="id"\n ref="select"\n v-model="localModel"\n :multiple="multiple"\n :name="name"\n :size="size"\n :placeholder="placeholder"\n :disabled="disabled"\n :required="required"\n :class="styles({ class: props.class })"\n >\n <slot />\n </select>\n <span class="pointer-events-none absolute inset-y-0 right-3 flex items-center justify-center">\n <slot name="trailingIcon">\n <Icon\n :name="trailingIcon || \'lucide:chevrons-up-down\'"\n class="h-4 w-4 text-muted-foreground"\n />\n </slot>\n </span>\n </div>\n</template>\n\n<script lang="ts" setup>\n const props = defineProps<{\n class?: any;\n id?: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n required?: boolean;\n modelValue?: any;\n multiple?: boolean;\n size?: number;\n autofocus?: boolean;\n trailingIcon?: string;\n }>();\n const styles = tv({\n base: "h-10 w-full appearance-none rounded-md border border-input bg-background px-3 py-2 pr-10 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm",\n });\n\n const select = ref<HTMLSelectElement | null>(null);\n const emits = defineEmits<{\n "update:modelValue": [value: any];\n }>();\n\n const localModel = useVModel(props, "modelValue", emits);\n\n onMounted(() => {\n if (props.autofocus) {\n select.value?.focus();\n }\n });\n</script>\n',
1410
+ '<template>\n <div class="relative">\n <select\n :id="id"\n ref="select"\n v-model="localModel"\n :multiple="multiple"\n :name="name"\n :size="size"\n :placeholder="placeholder"\n :disabled="disabled"\n :required="required"\n :class="styles({ class: props.class })"\n >\n <slot />\n </select>\n <span class="pointer-events-none absolute inset-y-0 right-3 flex items-center justify-center">\n <slot name="trailingIcon">\n <Icon\n :name="trailingIcon || \'lucide:chevrons-up-down\'"\n class="h-4 w-4 text-muted-foreground"\n />\n </slot>\n </span>\n </div>\n</template>\n\n<script lang="ts" setup>\n const props = defineProps<{\n class?: any;\n id?: string;\n name?: string;\n placeholder?: string;\n disabled?: boolean;\n required?: boolean;\n modelValue?: any;\n multiple?: boolean;\n size?: number;\n autofocus?: boolean;\n trailingIcon?: string;\n }>();\n const styles = tv({\n base: "h-10 w-full appearance-none rounded-md border border-input bg-background px-3 py-2 pr-10 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm",\n });\n\n const select = ref<HTMLSelectElement | null>(null);\n const emits = defineEmits<{\n "update:modelValue": [value: any];\n }>();\n\n const localModel = useVModel(props, "modelValue", emits);\n\n onMounted(() => {\n if (props.autofocus) {\n select.value?.focus();\n }\n });\n</script>\n',
1411
1411
  },
1412
1412
  ],
1413
1413
  utils: [],
@@ -1882,7 +1882,7 @@ export default [
1882
1882
  fileName: "Sheet/Content.vue",
1883
1883
  dirPath: "components/UI",
1884
1884
  fileContent:
1885
- '<template>\n <UiSheetPortal :to="to">\n <slot name="overlay">\n <UiSheetOverlay />\n </slot>\n <DialogContent\n :class="styles({ side, class: props.class })"\n v-bind="{ ...forwarded, ...$attrs }"\n >\n <slot>\n <slot name="header">\n <UiSheetHeader>\n <slot name="title">\n <UiSheetTitle v-if="title" :title="title" />\n </slot>\n <slot name="description">\n <UiSheetDescription v-if="description" :description="description" />\n </slot>\n </UiSheetHeader>\n </slot>\n <slot name="content" />\n <slot name="footer" />\n </slot>\n <slot name="close">\n <UiSheetClose :icon="icon" />\n </slot>\n </DialogContent>\n </UiSheetPortal>\n</template>\n\n<script lang="ts" setup>\n import { DialogContent, useForwardPropsEmits } from "radix-vue";\n import type { DialogContentEmits, DialogContentProps } from "radix-vue";\n\n defineOptions({ inheritAttrs: false });\n\n const props = defineProps<\n DialogContentProps & {\n icon?: string;\n title?: string;\n description?: string;\n class?: any;\n side?: VariantProps<typeof styles>["side"];\n to?: string | HTMLElement;\n }\n >();\n const emits = defineEmits<DialogContentEmits>();\n const forwarded = useForwardPropsEmits(\n reactiveOmit(props, "icon", "title", "description", "class", "to", "side"),\n emits\n );\n\n const styles = tv({\n base: "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",\n variants: {\n side: {\n top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",\n bottom:\n "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",\n left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",\n right:\n "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",\n },\n },\n defaultVariants: {\n side: "left",\n },\n });\n</script>\n',
1885
+ '<template>\n <UiSheetPortal :to="to">\n <slot name="overlay">\n <UiSheetOverlay />\n </slot>\n <DialogContent\n :class="styles({ side, class: props.class })"\n v-bind="{ ...forwarded, ...$attrs }"\n >\n <slot>\n <slot name="header">\n <UiSheetHeader>\n <slot name="title">\n <UiSheetTitle v-if="title" :title="title" />\n </slot>\n <slot name="description">\n <UiSheetDescription v-if="description" :description="description" />\n </slot>\n </UiSheetHeader>\n </slot>\n <slot name="content" />\n <slot name="footer" />\n </slot>\n <slot name="close">\n <UiSheetClose :icon="icon" />\n </slot>\n </DialogContent>\n </UiSheetPortal>\n</template>\n\n<script lang="ts" setup>\n import { DialogContent, useForwardPropsEmits } from "radix-vue";\n import type { DialogContentEmits, DialogContentProps } from "radix-vue";\n\n defineOptions({ inheritAttrs: false });\n\n const props = defineProps<\n DialogContentProps & {\n icon?: string;\n title?: string;\n description?: string;\n class?: any;\n side?: VariantProps<typeof styles>["side"];\n to?: string | HTMLElement;\n }\n >();\n const emits = defineEmits<DialogContentEmits>();\n const forwarded = useForwardPropsEmits(\n reactiveOmit(props, "icon", "title", "description", "class", "to", "side"),\n emits\n );\n\n const styles = tv({\n base: "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",\n variants: {\n side: {\n top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",\n bottom:\n "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",\n left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",\n right:\n "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",\n },\n },\n defaultVariants: {\n side: "left",\n },\n });\n</script>\n',
1886
1886
  },
1887
1887
  {
1888
1888
  fileName: "Sheet/Description.vue",
@@ -2018,6 +2018,57 @@ export default [
2018
2018
  composables: [],
2019
2019
  plugins: [],
2020
2020
  },
2021
+ {
2022
+ name: "Stepper",
2023
+ value: "stepper",
2024
+ files: [
2025
+ {
2026
+ fileName: "Stepper/Description.vue",
2027
+ dirPath: "components/UI",
2028
+ fileContent:
2029
+ '<template>\n <StepperDescription v-slot="slotProps" v-bind="props">\n <slot v-bind="slotProps" />\n </StepperDescription>\n</template>\n\n<script lang="ts" setup>\n import { StepperDescription } from "radix-vue";\n import type { StepperDescriptionProps } from "radix-vue";\n\n const props = defineProps<StepperDescriptionProps>();\n</script>\n',
2030
+ },
2031
+ {
2032
+ fileName: "Stepper/Indicator.vue",
2033
+ dirPath: "components/UI",
2034
+ fileContent:
2035
+ '<template>\n <StepperIndicator v-bind="props">\n <slot />\n </StepperIndicator>\n</template>\n\n<script lang="ts" setup>\n import { StepperIndicator } from "radix-vue";\n import type { StepperIndicatorProps } from "radix-vue";\n\n const props = defineProps<StepperIndicatorProps>();\n</script>\n',
2036
+ },
2037
+ {
2038
+ fileName: "Stepper/Item.vue",
2039
+ dirPath: "components/UI",
2040
+ fileContent:
2041
+ '<template>\n <StepperItem v-slot="slotProps" v-bind="props">\n <slot v-bind="slotProps" />\n </StepperItem>\n</template>\n\n<script lang="ts" setup>\n import { StepperItem } from "radix-vue";\n import type { StepperItemProps } from "radix-vue";\n\n const props = defineProps<StepperItemProps>();\n</script>\n',
2042
+ },
2043
+ {
2044
+ fileName: "Stepper/Separator.vue",
2045
+ dirPath: "components/UI",
2046
+ fileContent:
2047
+ '<template>\n <StepperSeparator v-bind="props">\n <slot />\n </StepperSeparator>\n</template>\n\n<script lang="ts" setup>\n import { StepperSeparator } from "radix-vue";\n import type { StepperSeparatorProps } from "radix-vue";\n\n const props = defineProps<StepperSeparatorProps>();\n</script>\n',
2048
+ },
2049
+ {
2050
+ fileName: "Stepper/Stepper.vue",
2051
+ dirPath: "components/UI",
2052
+ fileContent:
2053
+ '<template>\n <StepperRoot v-slot="slotProps" v-bind="forwarded">\n <slot v-bind="slotProps" />\n </StepperRoot>\n</template>\n\n<script lang="ts" setup>\n import { StepperRoot, useForwardPropsEmits } from "radix-vue";\n import type { StepperRootEmits, StepperRootProps } from "radix-vue";\n\n const props = defineProps<StepperRootProps>();\n const emit = defineEmits<StepperRootEmits>();\n const forwarded = useForwardPropsEmits(props, emit);\n</script>\n',
2054
+ },
2055
+ {
2056
+ fileName: "Stepper/Title.vue",
2057
+ dirPath: "components/UI",
2058
+ fileContent:
2059
+ '<template>\n <StepperTitle v-bind="props">\n <slot />\n </StepperTitle>\n</template>\n\n<script lang="ts" setup>\n import { StepperTitle } from "radix-vue";\n import type { StepperTitleProps } from "radix-vue";\n\n const props = defineProps<StepperTitleProps>();\n</script>\n',
2060
+ },
2061
+ {
2062
+ fileName: "Stepper/Trigger.vue",
2063
+ dirPath: "components/UI",
2064
+ fileContent:
2065
+ '<template>\n <StepperTrigger v-bind="props">\n <slot />\n </StepperTrigger>\n</template>\n\n<script lang="ts" setup>\n import { StepperTrigger } from "radix-vue";\n import type { StepperTriggerProps } from "radix-vue";\n\n const props = defineProps<StepperTriggerProps>();\n</script>\n',
2066
+ },
2067
+ ],
2068
+ utils: [],
2069
+ composables: [],
2070
+ plugins: [],
2071
+ },
2021
2072
  {
2022
2073
  name: "Switch",
2023
2074
  value: "switch",
@@ -2122,7 +2173,7 @@ export default [
2122
2173
  fileName: "Tabs/List.vue",
2123
2174
  dirPath: "components/UI",
2124
2175
  fileContent:
2125
- '<template>\n <TabsList :class="styles({ pill, class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </TabsList>\n</template>\n\n<script lang="ts" setup>\n import { TabsList } from "radix-vue";\n import type { TabsListProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n TabsListProps & {\n /** Custom class(es) to add to parent element */\n class?: any;\n pill?: boolean;\n }\n >(),\n { pill: true }\n );\n\n const styles = tv({\n base: "inline-flex h-10 items-center justify-center rounded-md p-1 text-muted-foreground",\n variants: {\n pill: {\n true: "bg-muted",\n false: "",\n },\n },\n });\n</script>\n',
2176
+ '<template>\n <TabsList :class="styles({ pill, class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </TabsList>\n</template>\n\n<script lang="ts" setup>\n import { TabsList } from "radix-vue";\n import type { TabsListProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n TabsListProps & {\n /** Custom class(es) to add to parent element */\n class?: any;\n pill?: boolean;\n }\n >(),\n { pill: true }\n );\n\n const styles = tv({\n base: "inline-flex h-10 items-center justify-center rounded-md p-1 text-muted-foreground",\n variants: {\n pill: {\n true: "bg-muted",\n false: "",\n },\n },\n });\n</script>\n',
2126
2177
  },
2127
2178
  {
2128
2179
  fileName: "Tabs/Tabs.vue",
@@ -2134,7 +2185,7 @@ export default [
2134
2185
  fileName: "Tabs/Trigger.vue",
2135
2186
  dirPath: "components/UI",
2136
2187
  fileContent:
2137
- '<template>\n <TabsTrigger v-bind="reactiveOmit(props, \'class\')" :class="styles({ pill, class: props.class })">\n <slot />\n </TabsTrigger>\n</template>\n\n<script lang="ts" setup>\n import { TabsTrigger } from "radix-vue";\n import type { TabsTriggerProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n TabsTriggerProps & {\n /** Custom class(es) to add to parent element */\n class?: any;\n /** Whether the trigger should be pill-shaped */\n pill?: boolean;\n }\n >(),\n {\n pill: true,\n }\n );\n\n const styles = tv({\n base: "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ",\n variants: {\n pill: {\n true: "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",\n false:\n "data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none",\n },\n },\n });\n</script>\n',
2188
+ '<template>\n <TabsTrigger v-bind="reactiveOmit(props, \'class\')" :class="styles({ pill, class: props.class })">\n <slot />\n </TabsTrigger>\n</template>\n\n<script lang="ts" setup>\n import { TabsTrigger } from "radix-vue";\n import type { TabsTriggerProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n TabsTriggerProps & {\n /** Custom class(es) to add to parent element */\n class?: any;\n /** Whether the trigger should be pill-shaped */\n pill?: boolean;\n }\n >(),\n {\n pill: true,\n }\n );\n\n const styles = tv({\n base: "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",\n variants: {\n pill: {\n true: "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",\n false:\n "data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none",\n },\n },\n });\n</script>\n',
2138
2189
  },
2139
2190
  ],
2140
2191
  utils: [],
@@ -2236,13 +2287,13 @@ export default [
2236
2287
  fileName: "Toast/Action.vue",
2237
2288
  dirPath: "components/UI",
2238
2289
  fileContent:
2239
- '<template>\n <ToastAction :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </ToastAction>\n</template>\n\n<script lang="ts" setup>\n import { ToastAction } from "radix-vue";\n import type { ToastActionProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n ToastActionProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n }\n >(),\n {\n altText: "Action button",\n }\n );\n\n const styles = tv({\n base: "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-xs font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",\n });\n</script>\n',
2290
+ '<template>\n <ToastAction :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </ToastAction>\n</template>\n\n<script lang="ts" setup>\n import { ToastAction } from "radix-vue";\n import type { ToastActionProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n ToastActionProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n }\n >(),\n {\n altText: "Action button",\n }\n );\n\n const styles = tv({\n base: "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-xs font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",\n });\n</script>\n',
2240
2291
  },
2241
2292
  {
2242
2293
  fileName: "Toast/Close.vue",
2243
2294
  dirPath: "components/UI",
2244
2295
  fileContent:
2245
- '<template>\n <ToastClose :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\', \'icon\')">\n <slot>\n <Icon :name="icon || \'lucide:x\'" class="h-4 w-4" />\n </slot>\n </ToastClose>\n</template>\n\n<script lang="ts" setup>\n import { ToastClose } from "radix-vue";\n import type { ToastCloseProps } from "radix-vue";\n\n const props = defineProps<\n ToastCloseProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n /**\n * The icon to render.\n */\n icon?: string;\n }\n >();\n\n const styles = tv({\n base: "absolute right-2 top-2 inline-flex items-center justify-center rounded-md p-1 text-foreground/50 opacity-50 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 focus-visible:ring-ring group-hover:opacity-100",\n });\n</script>\n',
2296
+ '<template>\n <ToastClose :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\', \'icon\')">\n <slot>\n <Icon :name="icon || \'lucide:x\'" class="h-4 w-4" />\n </slot>\n </ToastClose>\n</template>\n\n<script lang="ts" setup>\n import { ToastClose } from "radix-vue";\n import type { ToastCloseProps } from "radix-vue";\n\n const props = defineProps<\n ToastCloseProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n /**\n * The icon to render.\n */\n icon?: string;\n }\n >();\n\n const styles = tv({\n base: "absolute right-2 top-2 inline-flex items-center justify-center rounded-md p-1 text-foreground/50 opacity-50 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 focus-visible:ring-ring group-hover:opacity-100",\n });\n</script>\n',
2246
2297
  },
2247
2298
  {
2248
2299
  fileName: "Toast/Description.vue",
@@ -2278,7 +2329,7 @@ export default [
2278
2329
  fileName: "Toast/Viewport.vue",
2279
2330
  dirPath: "components/UI",
2280
2331
  fileContent:
2281
- '<template>\n <ToastViewport :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </ToastViewport>\n</template>\n\n<script lang="ts" setup>\n import { ToastViewport } from "radix-vue";\n import type { ToastViewportProps } from "radix-vue";\n\n const props = defineProps<\n ToastViewportProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n }\n >();\n\n const styles = tv({\n base: "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse gap-2 p-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring sm:bottom-auto sm:right-0 sm:flex-col md:max-w-[420px]",\n });\n</script>\n\n<style>\n [aria-label~="Notifications"] {\n display: grid;\n }\n</style>\n',
2332
+ '<template>\n <ToastViewport :class="styles({ class: props.class })" v-bind="reactiveOmit(props, \'class\')">\n <slot />\n </ToastViewport>\n</template>\n\n<script lang="ts" setup>\n import { ToastViewport } from "radix-vue";\n import type { ToastViewportProps } from "radix-vue";\n\n const props = defineProps<\n ToastViewportProps & {\n /**\n * Custom class names to add to the button.\n */\n class?: any;\n }\n >();\n\n const styles = tv({\n base: "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse gap-2 p-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring sm:bottom-auto sm:right-0 sm:flex-col md:max-w-[420px]",\n });\n</script>\n\n<style>\n [aria-label~="Notifications"] {\n display: grid;\n }\n</style>\n',
2282
2333
  },
2283
2334
  ],
2284
2335
  utils: [],
@@ -2365,6 +2416,33 @@ export default [
2365
2416
  composables: [],
2366
2417
  plugins: [],
2367
2418
  },
2419
+ {
2420
+ name: "Tree",
2421
+ value: "tree",
2422
+ files: [
2423
+ {
2424
+ fileName: "Tree/Item.vue",
2425
+ dirPath: "components/UI",
2426
+ fileContent:
2427
+ '<template>\n <TreeItem v-slot="slotProps" v-bind="forwarded">\n <slot v-bind="slotProps" />\n </TreeItem>\n</template>\n\n<script lang="ts" setup generic="T extends Record<string, any>">\n import { TreeItem, useForwardPropsEmits } from "radix-vue";\n import type { TreeItemProps } from "radix-vue";\n\n // Remove this when the type is properly exported from radix-vue\n type TreeItemEmits = {\n /**\n * Event handler called when the selecting item.\n *\n * It can be prevented by calling `event.preventDefault`.\n */\n select: [event: any];\n /**\n * Event handler called when the selecting item.\n *\n * It can be prevented by calling `event.preventDefault`.\n */\n toggle: [event: any];\n };\n\n const props = defineProps<TreeItemProps<T>>();\n\n const emit = defineEmits<TreeItemEmits>();\n\n const forwarded = useForwardPropsEmits(props, emit);\n</script>\n',
2428
+ },
2429
+ {
2430
+ fileName: "Tree/Tree.vue",
2431
+ dirPath: "components/UI",
2432
+ fileContent:
2433
+ '<template>\n <TreeRoot v-slot="slotProps" v-bind="forwarded">\n <slot v-bind="slotProps" />\n </TreeRoot>\n</template>\n\n<script lang="ts" setup>\n import { TreeRoot, useForwardPropsEmits } from "radix-vue";\n import type { TreeRootEmits, TreeRootProps } from "radix-vue";\n\n const props = defineProps<TreeRootProps>();\n const emit = defineEmits<TreeRootEmits>();\n\n const forwarded = useForwardPropsEmits(props, emit);\n</script>\n',
2434
+ },
2435
+ {
2436
+ fileName: "Tree/Virtualizer.vue",
2437
+ dirPath: "components/UI",
2438
+ fileContent:
2439
+ '<template>\n <TreeVirtualizer v-slot="slotProps" v-bind="forwarded">\n <slot v-bind="slotProps" />\n </TreeVirtualizer>\n</template>\n\n<script lang="ts" setup>\n import { TreeVirtualizer, useForwardPropsEmits } from "radix-vue";\n import type { TreeVirtualizerProps } from "radix-vue";\n\n const props = defineProps<TreeVirtualizerProps>();\n\n const forwarded = useForwardPropsEmits(props);\n</script>\n',
2440
+ },
2441
+ ],
2442
+ utils: [],
2443
+ composables: [],
2444
+ plugins: [],
2445
+ },
2368
2446
  {
2369
2447
  name: "VeeCheckbox",
2370
2448
  value: "vee-checkbox",
package/src/types.ts CHANGED
@@ -4,6 +4,7 @@ export type UIConfig = {
4
4
  tailwindConfigLocation: string;
5
5
  componentsLocation: string;
6
6
  composablesLocation: string;
7
+ pluginsLocation?: string;
7
8
  utilsLocation: string;
8
9
  force: boolean;
9
10
  useDefaultFilename: boolean;
@@ -18,6 +18,7 @@ const defaultConfig = {
18
18
  tailwindConfigLocation: "tailwind.config.js",
19
19
  componentsLocation: "components/Ui",
20
20
  composablesLocation: "composables",
21
+ pluginsLocation: "plugins",
21
22
  utilsLocation: "utils",
22
23
  force: true,
23
24
  useDefaultFilename: true,
@@ -81,6 +82,7 @@ export const getUIConfig = async (options?: InitOptions) => {
81
82
  export const createConfigPaths = (uiConfig: UIConfig) => {
82
83
  // Esnure files exists
83
84
  if (uiConfig.tailwindCSSLocation) fse.ensureFileSync(uiConfig.tailwindConfigLocation);
85
+ if (uiConfig.pluginsLocation) fse.ensureDirSync(uiConfig.pluginsLocation);
84
86
  if (uiConfig.tailwindConfigLocation) fse.ensureFileSync(uiConfig.tailwindCSSLocation);
85
87
  if (uiConfig.componentsLocation) fse.ensureDirSync(uiConfig.componentsLocation);
86
88
  if (uiConfig.composablesLocation) fse.ensureDirSync(uiConfig.composablesLocation);
@@ -35,6 +35,12 @@ export const initPrompts = async () => {
35
35
  message: "Where should your composables be stored?",
36
36
  initial: "composables",
37
37
  },
38
+ {
39
+ name: "pluginsLocation",
40
+ type: "text",
41
+ message: "Where should your plugins be stored?",
42
+ initial: "plugins",
43
+ },
38
44
  {
39
45
  name: "utilsLocation",
40
46
  type: "text",