ui-thing 0.0.10 → 0.0.12

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.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "CLI used to add Nuxt 3 components to a project",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -40,6 +40,7 @@
40
40
  },
41
41
  "license": "MIT",
42
42
  "dependencies": {
43
+ "axios": "^1.6.2",
43
44
  "boxen": "^7.1.1",
44
45
  "build": "^0.1.4",
45
46
  "c12": "^1.5.1",
@@ -5,7 +5,8 @@ import kleur from "kleur";
5
5
  import _ from "lodash";
6
6
  import prompts from "prompts";
7
7
 
8
- import allComponents from "../comp";
8
+ import allComponents from "../comps";
9
+ import { Component } from "../types";
9
10
  import { compareUIConfig } from "../utils/compareUIConfig";
10
11
  import { addModuleToConfig, getNuxtConfig, getUIConfig, updateConfig } from "../utils/config";
11
12
  import { fileExists } from "../utils/fileExists";
@@ -65,7 +66,7 @@ export const add = new Command()
65
66
  }
66
67
 
67
68
  // store the components that are found
68
- let found: typeof allComponents = [];
69
+ let found: Component[] = [];
69
70
  componentNames.forEach((c) => {
70
71
  if (findComponent(c)) {
71
72
  found.push(findComponent(c)!);
@@ -2120,25 +2120,19 @@ export default [
2120
2120
  plugins: [],
2121
2121
  },
2122
2122
  {
2123
- name: "VeeMultiSelect",
2124
- value: "vee-multi-select",
2125
- deps: [
2126
- "@vee-validate/nuxt",
2127
- "radix-vue",
2128
- "@morev/vue-transitions",
2129
- "tailwind-variants",
2130
- "@vueform/multiselect",
2131
- ],
2123
+ name: "VeeCheckbox",
2124
+ value: "vee-checkbox",
2125
+ deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2132
2126
  askValidator: true,
2133
2127
  devDeps: ["nuxt-icon"],
2134
2128
  nuxtModules: ["@vee-validate/nuxt", "@morev/vue-transitions/nuxt", "nuxt-icon"],
2135
- components: ["label"],
2129
+ components: ["checkbox", "label"],
2136
2130
  files: [
2137
2131
  {
2138
- fileName: "Vee/MultiSelect.vue",
2132
+ fileName: "Vee/Checkbox.vue",
2139
2133
  dirPath: "components/UI",
2140
2134
  fileContent:
2141
- '<template>\n <div class="w-full">\n <UILabel\n :for="inputId"\n v-if="formLabel"\n :class="[disabled && \'text-muted-foreground\', errorMessage && \'text-destructive\', \'mb-2\']"\n >{{ formLabel }}</UILabel\n >\n <Multiselect\n ref="multiselect"\n :attrs="{\n id: inputId,\n }"\n :disabled="disabled"\n v-bind="$attrs"\n :id="inputId"\n v-model="value"\n :name="name"\n :required="required"\n :classes="{\n containerActive: \'ring-2 ring-ring ring-offset-2 ring-offset-background transition\',\n }"\n >\n <template v-for="(_, name) in $slots" v-slot:[name]="scope">\n <slot :name="name" v-bind="scope"></slot>\n </template>\n <template #clear="{ clear }">\n <button @click="clear" class="mr-2 flex items-center justify-center">\n <Icon name="heroicons:x-mark" size="16" class="text-muted-foreground" />\n </button>\n </template>\n </Multiselect>\n <TransitionSlide group tag="div">\n <p key="hint" class="mt-1.5 text-sm text-muted-foreground" v-if="hint && !errorMessage">\n {{ hint }}\n </p>\n\n <p key="errorMessage" class="mt-1.5 text-sm text-destructive" v-if="errorMessage">\n {{ errorMessage }}\n </p>\n </TransitionSlide>\n </div>\n</template>\n\n<script setup lang="ts">\n import Multiselect from "@vueform/multiselect";\n import { useId } from "radix-vue";\n\n const multiselect = shallowRef<InstanceType<typeof Multiselect> | null>(null);\n\n interface Props\n extends /* @vue-ignore */ Partial<Omit<InstanceType<typeof Multiselect>, "$emit">> {}\n\n const props = defineProps<\n {\n modelValue?: any;\n formLabel?: string;\n required?: boolean;\n id?: string;\n hint?: string;\n disabled?: boolean;\n rules?: any;\n validateOnMount?: boolean;\n name?: string;\n } & Props\n >();\n\n const emit = defineEmits([\n "paste",\n "open",\n "close",\n "select",\n "deselect",\n "input",\n "search-change",\n "tag",\n "option",\n "update:modelValue",\n "change",\n "clear",\n "keydown",\n "keyup",\n "max",\n "create",\n "ready",\n ]);\n\n defineOptions({ inheritAttrs: false });\n\n const inputId = useId(props.id);\n\n const { errorMessage, value } = useField(() => props.name || inputId, props.rules, {\n initialValue: props.modelValue,\n label: props.label,\n validateOnMount: props.validateOnMount,\n syncVModel: true,\n });\n\n onMounted(() => {\n nextTick(() => {\n emit("ready", multiselect.value);\n });\n });\n</script>\n\n<style src="@vueform/multiselect/themes/default.css"></style>\n<style>\n :root {\n --ms-font-size: theme("fontSize.sm");\n --ms-line-height: 1.5;\n --ms-bg: theme("colors.background");\n --ms-bg-disabled: transparent;\n --ms-border-color: theme("colors.input");\n --ms-border-width: 1px;\n --ms-border-color-active: theme("colors.input");\n --ms-border-width-active: 1px;\n --ms-radius: theme("borderRadius.md");\n --ms-py: theme("padding.2");\n --ms-px: theme("padding.3");\n --ms-ring-width: 0px;\n --ms-ring-color: theme("colors.ring");\n --ms-placeholder-color: theme("colors.muted.foreground");\n --ms-max-height: theme("height.52");\n\n --ms-spinner-color: theme("colors.muted.foreground");\n --ms-caret-color: theme("colors.muted.foreground");\n --ms-clear-color: theme("colors.muted.foreground");\n --ms-clear-color-hover: theme("colors.primary.DEFAULT");\n\n --ms-tag-font-size: theme("fontSize.sm");\n --ms-tag-line-height: 1.25rem;\n --ms-tag-font-weight: 500;\n --ms-tag-bg: theme("colors.primary.DEFAULT");\n --ms-tag-bg-disabled: transparent;\n --ms-tag-color: theme("colors.primary.foreground");\n --ms-tag-color-disabled: theme("colors.muted.foreground");\n --ms-tag-radius: theme("borderRadius.DEFAULT");\n --ms-tag-py: theme("padding[0.5]");\n\n --ms-dropdown-bg: theme("colors.background");\n --ms-dropdown-border-color: theme("colors.border");\n --ms-dropdown-border-width: 1px;\n --ms-dropdown-radius: theme("borderRadius.md");\n\n --ms-group-label-bg: theme("colors.muted.DEFAULT");\n --ms-group-label-color: theme("colors.muted.foreground");\n --ms-group-label-bg-pointed: theme("colors.primary.DEFAULT");\n --ms-group-label-color-pointed: theme("colors.primary.foreground");\n --ms-group-label-bg-disabled: theme("colors.muted.DEFAULT / 50%");\n --ms-group-label-color-disabled: theme("colors.muted.foreground / 50%");\n --ms-group-label-bg-selected: theme("colors.primary.DEFAULT");\n --ms-group-label-color-selected: theme("colors.primary.foreground");\n --ms-group-label-bg-selected-pointed: theme("colors.primary.DEFAULT");\n --ms-group-label-color-selected-pointed: theme("colors.primary.foreground");\n --ms-group-label-bg-selected-disabled: theme("colors.muted.DEFAULT / 50%");\n --ms-group-label-color-selected-disabled: theme("colors.muted.foreground / 50%");\n\n --ms-option-font-size: theme("fontSize.sm");\n --ms-option-bg-pointed: theme("colors.primary.DEFAULT");\n --ms-option-color-pointed: theme("colors.primary.foreground");\n --ms-option-bg-selected: theme("colors.primary.DEFAULT");\n --ms-option-color-selected: theme("colors.primary.foreground");\n --ms-option-bg-disabled: transparent;\n --ms-option-color-disabled: theme("colors.muted.foreground / 50%");\n --ms-option-bg-selected-pointed: theme("colors.primary.DEFAULT");\n --ms-option-color-selected-pointed: theme("colors.primary.foreground");\n --ms-option-bg-selected-disabled: theme("colors.muted.DEFAULT");\n --ms-option-color-selected-disabled: theme("colors.muted.foreground");\n\n --ms-empty-color: theme("colors.muted.foreground");\n }\n</style>\n',
2135
+ '<template>\n <div :class="styles({ class: props.class })">\n <UICheckbox\n :id="inputId"\n v-bind="$attrs"\n :icon="icon"\n :value="value"\n :name="name"\n :required="required"\n :disabled="disabled"\n :checked="checked"\n @update:checked="handleChange"\n />\n <div class="flex flex-col gap-1.5">\n <slot name="label" :errorMessage="errorMessage" :checked="checked">\n <UILabel\n :for="inputId"\n v-if="label"\n class="leading-none"\n :class="[errorMessage && \'text-destructive\']"\n >{{ label }}</UILabel\n >\n </slot>\n <TransitionSlide tag="div" group>\n <slot name="hint" :errorMessage="errorMessage" :checked="checked">\n <p\n key="hint"\n class="text-sm leading-none text-muted-foreground"\n v-if="hint && !errorMessage"\n >\n {{ hint }}\n </p>\n </slot>\n <slot name="errorMessage" :errorMessage="errorMessage" :checked="checked">\n <p key="errorMessage" class="text-sm leading-none text-destructive" v-if="errorMessage">\n {{ errorMessage }}\n </p>\n </slot>\n </TransitionSlide>\n </div>\n </div>\n</template>\n\n<script lang="ts" setup>\n import { useId } from "radix-vue";\n\n const props = defineProps<{\n label?: string;\n icon?: string;\n hint?: string;\n modelValue?: string;\n name?: string;\n id?: string;\n rules?: any;\n validateOnMount?: boolean;\n type?: string;\n placeholder?: string;\n value?: any;\n required?: boolean;\n disabled?: boolean;\n class?: any;\n }>();\n const styles = tv({\n base: "flex gap-3",\n });\n\n defineOptions({ inheritAttrs: false });\n\n const inputId = useId(props.id);\n\n const { errorMessage, checked, handleChange } = useField(\n () => props.name || inputId,\n props.rules,\n {\n initialValue: props.modelValue,\n label: props.label,\n validateOnMount: props.validateOnMount,\n type: "checkbox",\n checkedValue: props.value || true,\n syncVModel: true,\n }\n );\n</script>\n',
2142
2136
  },
2143
2137
  ],
2144
2138
  utils: [],
@@ -2146,19 +2140,19 @@ export default [
2146
2140
  plugins: [],
2147
2141
  },
2148
2142
  {
2149
- name: "VeeCheckbox",
2150
- value: "vue-checkbox",
2143
+ name: "VeeDatepicker",
2144
+ value: "vee-datepicker",
2151
2145
  deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2152
2146
  askValidator: true,
2153
2147
  devDeps: ["nuxt-icon"],
2154
2148
  nuxtModules: ["@vee-validate/nuxt", "@morev/vue-transitions/nuxt", "nuxt-icon"],
2155
- components: ["checkbox", "label"],
2149
+ components: ["datepicker", "label", "input"],
2156
2150
  files: [
2157
2151
  {
2158
- fileName: "Vee/Checkbox.vue",
2152
+ fileName: "Vee/Datepicker.vue",
2159
2153
  dirPath: "components/UI",
2160
2154
  fileContent:
2161
- '<template>\n <div :class="styles({ class: props.class })">\n <UICheckbox\n :id="inputId"\n v-bind="$attrs"\n :icon="icon"\n :value="value"\n :name="name"\n :required="required"\n :disabled="disabled"\n :checked="checked"\n @update:checked="handleChange"\n />\n <div class="flex flex-col gap-1.5">\n <slot name="label" :errorMessage="errorMessage" :checked="checked">\n <UILabel\n :for="inputId"\n v-if="label"\n class="leading-none"\n :class="[errorMessage && \'text-destructive\']"\n >{{ label }}</UILabel\n >\n </slot>\n <TransitionSlide tag="div" group>\n <slot name="hint" :errorMessage="errorMessage" :checked="checked">\n <p\n key="hint"\n class="text-sm leading-none text-muted-foreground"\n v-if="hint && !errorMessage"\n >\n {{ hint }}\n </p>\n </slot>\n <slot name="errorMessage" :errorMessage="errorMessage" :checked="checked">\n <p key="errorMessage" class="text-sm leading-none text-destructive" v-if="errorMessage">\n {{ errorMessage }}\n </p>\n </slot>\n </TransitionSlide>\n </div>\n </div>\n</template>\n\n<script lang="ts" setup>\n import { useId } from "radix-vue";\n\n const props = defineProps<{\n label?: string;\n icon?: string;\n hint?: string;\n modelValue?: string;\n name?: string;\n id?: string;\n rules?: any;\n validateOnMount?: boolean;\n type?: string;\n placeholder?: string;\n value?: any;\n required?: boolean;\n disabled?: boolean;\n class?: any;\n }>();\n const styles = tv({\n base: "flex gap-3",\n });\n\n defineOptions({ inheritAttrs: false });\n\n const inputId = useId(props.id);\n\n const { errorMessage, checked, handleChange } = useField(\n () => props.name || inputId,\n props.rules,\n {\n initialValue: props.modelValue,\n label: props.label,\n validateOnMount: props.validateOnMount,\n type: "checkbox",\n checkedValue: props.value || true,\n syncVModel: true,\n }\n );\n</script>\n',
2155
+ '<template>\r\n <div class="w-full">\r\n <UILabel\r\n :for="inputId"\r\n v-if="label"\r\n :class="[disabled && \'text-muted-foreground\', errorMessage && \'text-destructive\', \'mb-2\']"\r\n >{{ label }}</UILabel\r\n >\r\n <div class="relative">\r\n <slot name="icon">\r\n <span v-if="hasIcon" class="absolute inset-y-0 left-3 flex items-center justify-center">\r\n <Icon :name="icon" v-if="icon" class="h-4 w-4 text-muted-foreground/70" />\r\n </span>\r\n </slot>\r\n <UIDatepicker v-bind="datePickerProps" v-model="value">\r\n <template #header-title="{ title }">\r\n <div class="inline-flex items-center gap-1">\r\n {{ title }} <Icon name="lucide:chevron-down" class="h-4 w-4" />\r\n </div>\r\n </template>\r\n <template #default="{ inputValue, inputEvents }">\r\n <UIInput\r\n :readonly="readonly"\r\n :model-value="inputValue"\r\n v-on="inputEvents"\r\n :id="inputId"\r\n :name="name"\r\n :disabled="disabled"\r\n v-bind="$attrs"\r\n :class="[hasIcon && \'pl-9\']"\r\n :placeholder="placeholder"\r\n />\r\n </template>\r\n </UIDatepicker>\r\n </div>\r\n <TransitionSlide group tag="div">\r\n <p key="hint" class="mt-1.5 text-sm text-muted-foreground" v-if="hint && !errorMessage">\r\n {{ hint }}\r\n </p>\r\n\r\n <p key="errorMessage" class="mt-1.5 text-sm text-destructive" v-if="errorMessage">\r\n {{ errorMessage }}\r\n </p>\r\n </TransitionSlide>\r\n </div>\r\n</template>\r\n\r\n<script lang="ts" setup>\r\n import { useId } from "radix-vue";\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n label?: string;\r\n icon?: string;\r\n hint?: string;\r\n disabled?: boolean;\r\n modelValue?: any;\r\n name?: string;\r\n id?: string;\r\n rules?: any;\r\n validateOnMount?: boolean;\r\n placeholder?: string;\r\n readonly?: boolean;\r\n datePickerProps?: any;\r\n }>(),\r\n {\r\n icon: "lucide:calendar-days",\r\n }\r\n );\r\n\r\n defineOptions({ inheritAttrs: false });\r\n\r\n const inputId = useId(props.id);\r\n\r\n const hasIcon = computed(() => Boolean(props.icon) || Boolean(useSlots().icon));\r\n\r\n const { errorMessage, value } = useField(() => props.name || inputId, props.rules, {\r\n initialValue: props.modelValue,\r\n label: props.label,\r\n validateOnMount: props.validateOnMount,\r\n syncVModel: true,\r\n });\r\n</script>\r\n',
2162
2156
  },
2163
2157
  ],
2164
2158
  utils: [],
@@ -2167,7 +2161,7 @@ export default [
2167
2161
  },
2168
2162
  {
2169
2163
  name: "VeeFileInput",
2170
- value: "vue-file-input",
2164
+ value: "vee-file-input",
2171
2165
  deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2172
2166
  askValidator: true,
2173
2167
  devDeps: ["nuxt-icon"],
@@ -2187,7 +2181,7 @@ export default [
2187
2181
  },
2188
2182
  {
2189
2183
  name: "VeeInput",
2190
- value: "vue-input",
2184
+ value: "vee-input",
2191
2185
  deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2192
2186
  askValidator: true,
2193
2187
  devDeps: ["nuxt-icon"],
@@ -2205,9 +2199,35 @@ export default [
2205
2199
  composables: [],
2206
2200
  plugins: [],
2207
2201
  },
2202
+ {
2203
+ name: "VeeMultiSelect",
2204
+ value: "vee-multi-select",
2205
+ deps: [
2206
+ "@vee-validate/nuxt",
2207
+ "radix-vue",
2208
+ "@morev/vue-transitions",
2209
+ "tailwind-variants",
2210
+ "@vueform/multiselect",
2211
+ ],
2212
+ askValidator: true,
2213
+ devDeps: ["nuxt-icon"],
2214
+ nuxtModules: ["@vee-validate/nuxt", "@morev/vue-transitions/nuxt", "nuxt-icon"],
2215
+ components: ["label"],
2216
+ files: [
2217
+ {
2218
+ fileName: "Vee/MultiSelect.vue",
2219
+ dirPath: "components/UI",
2220
+ fileContent:
2221
+ '<template>\n <div class="w-full">\n <UILabel\n :for="inputId"\n v-if="formLabel"\n :class="[disabled && \'text-muted-foreground\', errorMessage && \'text-destructive\', \'mb-2\']"\n >{{ formLabel }}</UILabel\n >\n <Multiselect\n ref="multiselect"\n :attrs="{\n id: inputId,\n }"\n :disabled="disabled"\n v-bind="$attrs"\n :id="inputId"\n v-model="value"\n :name="name"\n :required="required"\n :classes="{\n containerActive: \'ring-2 ring-ring ring-offset-2 ring-offset-background transition\',\n }"\n >\n <template v-for="(_, name) in $slots" v-slot:[name]="scope">\n <slot :name="name" v-bind="scope"></slot>\n </template>\n <template #clear="{ clear }">\n <button @click="clear" class="mr-2 flex items-center justify-center">\n <Icon name="heroicons:x-mark" size="16" class="text-muted-foreground" />\n </button>\n </template>\n </Multiselect>\n <TransitionSlide group tag="div">\n <p key="hint" class="mt-1.5 text-sm text-muted-foreground" v-if="hint && !errorMessage">\n {{ hint }}\n </p>\n\n <p key="errorMessage" class="mt-1.5 text-sm text-destructive" v-if="errorMessage">\n {{ errorMessage }}\n </p>\n </TransitionSlide>\n </div>\n</template>\n\n<script setup lang="ts">\n import Multiselect from "@vueform/multiselect";\n import { useId } from "radix-vue";\n\n const multiselect = shallowRef<InstanceType<typeof Multiselect> | null>(null);\n\n interface Props\n extends /* @vue-ignore */ Partial<Omit<InstanceType<typeof Multiselect>, "$emit">> {}\n\n const props = defineProps<\n {\n modelValue?: any;\n formLabel?: string;\n required?: boolean;\n id?: string;\n hint?: string;\n disabled?: boolean;\n rules?: any;\n validateOnMount?: boolean;\n name?: string;\n } & Props\n >();\n\n const emit = defineEmits([\n "paste",\n "open",\n "close",\n "select",\n "deselect",\n "input",\n "search-change",\n "tag",\n "option",\n "update:modelValue",\n "change",\n "clear",\n "keydown",\n "keyup",\n "max",\n "create",\n "ready",\n ]);\n\n defineOptions({ inheritAttrs: false });\n\n const inputId = useId(props.id);\n\n const { errorMessage, value } = useField(() => props.name || inputId, props.rules, {\n initialValue: props.modelValue,\n label: props.label,\n validateOnMount: props.validateOnMount,\n syncVModel: true,\n });\n\n onMounted(() => {\n nextTick(() => {\n emit("ready", multiselect.value);\n });\n });\n</script>\n\n<style src="@vueform/multiselect/themes/default.css"></style>\n<style>\n :root {\n --ms-font-size: theme("fontSize.sm");\n --ms-line-height: 1.5;\n --ms-bg: theme("colors.background");\n --ms-bg-disabled: transparent;\n --ms-border-color: theme("colors.input");\n --ms-border-width: 1px;\n --ms-border-color-active: theme("colors.input");\n --ms-border-width-active: 1px;\n --ms-radius: theme("borderRadius.md");\n --ms-py: theme("padding.2");\n --ms-px: theme("padding.3");\n --ms-ring-width: 0px;\n --ms-ring-color: theme("colors.ring");\n --ms-placeholder-color: theme("colors.muted.foreground");\n --ms-max-height: theme("height.52");\n\n --ms-spinner-color: theme("colors.muted.foreground");\n --ms-caret-color: theme("colors.muted.foreground");\n --ms-clear-color: theme("colors.muted.foreground");\n --ms-clear-color-hover: theme("colors.primary.DEFAULT");\n\n --ms-tag-font-size: theme("fontSize.sm");\n --ms-tag-line-height: 1.25rem;\n --ms-tag-font-weight: 500;\n --ms-tag-bg: theme("colors.primary.DEFAULT");\n --ms-tag-bg-disabled: transparent;\n --ms-tag-color: theme("colors.primary.foreground");\n --ms-tag-color-disabled: theme("colors.muted.foreground");\n --ms-tag-radius: theme("borderRadius.DEFAULT");\n --ms-tag-py: theme("padding[0.5]");\n\n --ms-dropdown-bg: theme("colors.background");\n --ms-dropdown-border-color: theme("colors.border");\n --ms-dropdown-border-width: 1px;\n --ms-dropdown-radius: theme("borderRadius.md");\n\n --ms-group-label-bg: theme("colors.muted.DEFAULT");\n --ms-group-label-color: theme("colors.muted.foreground");\n --ms-group-label-bg-pointed: theme("colors.primary.DEFAULT");\n --ms-group-label-color-pointed: theme("colors.primary.foreground");\n --ms-group-label-bg-disabled: theme("colors.muted.DEFAULT / 50%");\n --ms-group-label-color-disabled: theme("colors.muted.foreground / 50%");\n --ms-group-label-bg-selected: theme("colors.primary.DEFAULT");\n --ms-group-label-color-selected: theme("colors.primary.foreground");\n --ms-group-label-bg-selected-pointed: theme("colors.primary.DEFAULT");\n --ms-group-label-color-selected-pointed: theme("colors.primary.foreground");\n --ms-group-label-bg-selected-disabled: theme("colors.muted.DEFAULT / 50%");\n --ms-group-label-color-selected-disabled: theme("colors.muted.foreground / 50%");\n\n --ms-option-font-size: theme("fontSize.sm");\n --ms-option-bg-pointed: theme("colors.primary.DEFAULT");\n --ms-option-color-pointed: theme("colors.primary.foreground");\n --ms-option-bg-selected: theme("colors.primary.DEFAULT");\n --ms-option-color-selected: theme("colors.primary.foreground");\n --ms-option-bg-disabled: transparent;\n --ms-option-color-disabled: theme("colors.muted.foreground / 50%");\n --ms-option-bg-selected-pointed: theme("colors.primary.DEFAULT");\n --ms-option-color-selected-pointed: theme("colors.primary.foreground");\n --ms-option-bg-selected-disabled: theme("colors.muted.DEFAULT");\n --ms-option-color-selected-disabled: theme("colors.muted.foreground");\n\n --ms-empty-color: theme("colors.muted.foreground");\n }\n</style>\n',
2222
+ },
2223
+ ],
2224
+ utils: [],
2225
+ composables: [],
2226
+ plugins: [],
2227
+ },
2208
2228
  {
2209
2229
  name: "VeeRadioGroup",
2210
- value: "vue-radio-group",
2230
+ value: "vee-radio-group",
2211
2231
  deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2212
2232
  askValidator: true,
2213
2233
  devDeps: ["nuxt-icon"],
@@ -2227,7 +2247,7 @@ export default [
2227
2247
  },
2228
2248
  {
2229
2249
  name: "VeeSelect",
2230
- value: "vue-select",
2250
+ value: "vee-select",
2231
2251
  deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2232
2252
  askValidator: true,
2233
2253
  devDeps: ["nuxt-icon"],
@@ -2246,18 +2266,19 @@ export default [
2246
2266
  plugins: [],
2247
2267
  },
2248
2268
  {
2249
- name: "Vue Sonner",
2250
- value: "vue-sonner",
2251
- deps: ["vue-sonner"],
2252
- devDeps: [],
2253
- nuxtModules: [],
2254
- instructions: ["Remember to add the <UIVueSonner /> tag to your app.vue/layout file."],
2269
+ name: "VeeTextarea",
2270
+ value: "vee-textarea",
2271
+ deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2272
+ askValidator: true,
2273
+ devDeps: ["nuxt-icon"],
2274
+ nuxtModules: ["@vee-validate/nuxt", "@morev/vue-transitions/nuxt", "nuxt-icon"],
2275
+ components: ["textarea", "label"],
2255
2276
  files: [
2256
2277
  {
2257
- fileName: "VueSonner.client.vue",
2278
+ fileName: "Vee/Textarea.vue",
2258
2279
  dirPath: "components/UI",
2259
2280
  fileContent:
2260
- '<template>\r\n <Toaster\r\n position="top-right"\r\n :visible-toasts="5"\r\n rich-colors\r\n :duration="7000"\r\n close-button\r\n :theme="$colorMode.value == \'dark\' ? \'dark\' : \'light\'"\r\n />\r\n</template>\r\n\r\n<script lang="ts" setup>\r\n import { Toaster } from "vue-sonner";\r\n</script>\r\n<style scoped>\r\n :deep([data-sonner-toaster][data-theme="dark"]),\r\n :deep([data-sonner-toaster][data-theme="light"]) {\r\n --normal-bg: theme("colors.popover.DEFAULT");\r\n --normal-border: theme("colors.border");\r\n --normal-text: theme("colors.popover.foreground");\r\n --border-radius: theme("borderRadius.md");\r\n }\r\n :deep([data-sonner-toaster]) {\r\n @apply font-sans;\r\n }\r\n :deep([data-sonner-toast][data-styled="true"]) {\r\n @apply items-start;\r\n }\r\n :deep([data-sonner-toast] [data-icon]) {\r\n @apply mt-0.5;\r\n }\r\n :deep([data-sonner-toast] [data-title]) {\r\n @apply text-sm font-semibold;\r\n }\r\n :deep([data-sonner-toast] [data-description]) {\r\n @apply text-sm;\r\n }\r\n :deep([data-sonner-toast] [data-close-button]) {\r\n @apply border border-border bg-background text-foreground hover:border-inherit hover:bg-inherit hover:text-accent-foreground;\r\n }\r\n :deep([data-sonner-toast] [data-button]) {\r\n @apply bg-primary text-primary-foreground transition hover:opacity-90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background;\r\n }\r\n :deep(.sonner-loading-bar) {\r\n @apply bg-muted-foreground;\r\n }\r\n</style>\r\n',
2281
+ '<template>\r\n <div class="w-full">\r\n <UILabel :for="inputId" v-if="label" :class="[errorMessage && \'text-destructive\', \'mb-2\']">{{\r\n label\r\n }}</UILabel>\r\n <div class="relative">\r\n <slot name="icon">\r\n <span v-if="hasIcon" class="absolute left-3 top-3 flex items-center justify-center">\r\n <Icon :name="icon" v-if="icon" class="h-4 w-4 text-muted-foreground/70" />\r\n </span>\r\n </slot>\r\n <UITextarea\r\n :rows="rows"\r\n v-model="value"\r\n @blur="handleBlur"\r\n :id="inputId"\r\n :name="name"\r\n v-bind="$attrs"\r\n :class="[hasIcon && \'pl-9\']"\r\n :placeholder="placeholder"\r\n />\r\n </div>\r\n <TransitionSlide group tag="div">\r\n <p key="hint" class="mt-1.5 text-sm text-muted-foreground" v-if="hint && !errorMessage">\r\n {{ hint }}\r\n </p>\r\n\r\n <p key="errorMessage" class="mt-1.5 text-sm text-destructive" v-if="errorMessage">\r\n {{ errorMessage }}\r\n </p>\r\n </TransitionSlide>\r\n </div>\r\n</template>\r\n\r\n<script lang="ts" setup>\r\n import { useId } from "radix-vue";\r\n\r\n const props = defineProps<{\r\n label?: string;\r\n icon?: string;\r\n hint?: string;\r\n modelValue?: string;\r\n name?: string;\r\n id?: string;\r\n rules?: any;\r\n validateOnMount?: boolean;\r\n placeholder?: string;\r\n rows?: number;\r\n }>();\r\n\r\n defineOptions({ inheritAttrs: false });\r\n\r\n const inputId = useId(props.id);\r\n\r\n const hasIcon = computed(() => Boolean(props.icon) || Boolean(useSlots().icon));\r\n\r\n const { errorMessage, value, handleBlur } = useField(() => props.name || inputId, props.rules, {\r\n initialValue: props.modelValue,\r\n label: props.label,\r\n validateOnMount: props.validateOnMount,\r\n syncVModel: true,\r\n });\r\n</script>\r\n',
2261
2282
  },
2262
2283
  ],
2263
2284
  utils: [],
@@ -2265,19 +2286,18 @@ export default [
2265
2286
  plugins: [],
2266
2287
  },
2267
2288
  {
2268
- name: "VeeTextarea",
2269
- value: "vue-textarea",
2270
- deps: ["@vee-validate/nuxt", "radix-vue", "@morev/vue-transitions", "tailwind-variants"],
2271
- askValidator: true,
2272
- devDeps: ["nuxt-icon"],
2273
- nuxtModules: ["@vee-validate/nuxt", "@morev/vue-transitions/nuxt", "nuxt-icon"],
2274
- components: ["textarea", "label"],
2289
+ name: "Vue Sonner",
2290
+ value: "vue-sonner",
2291
+ deps: ["vue-sonner"],
2292
+ devDeps: [],
2293
+ nuxtModules: [],
2294
+ instructions: ["Remember to add the <UIVueSonner /> tag to your app.vue/layout file."],
2275
2295
  files: [
2276
2296
  {
2277
- fileName: "Vee/Textarea.vue",
2297
+ fileName: "VueSonner.client.vue",
2278
2298
  dirPath: "components/UI",
2279
2299
  fileContent:
2280
- '<template>\r\n <div class="w-full">\r\n <UILabel :for="inputId" v-if="label" :class="[errorMessage && \'text-destructive\', \'mb-2\']">{{\r\n label\r\n }}</UILabel>\r\n <div class="relative">\r\n <slot name="icon">\r\n <span v-if="hasIcon" class="absolute left-3 top-3 flex items-center justify-center">\r\n <Icon :name="icon" v-if="icon" class="h-4 w-4 text-muted-foreground/70" />\r\n </span>\r\n </slot>\r\n <UITextarea\r\n :rows="rows"\r\n v-model="value"\r\n @blur="handleBlur"\r\n :id="inputId"\r\n :name="name"\r\n v-bind="$attrs"\r\n :class="[hasIcon && \'pl-9\']"\r\n :placeholder="placeholder"\r\n />\r\n </div>\r\n <TransitionSlide group tag="div">\r\n <p key="hint" class="mt-1.5 text-sm text-muted-foreground" v-if="hint && !errorMessage">\r\n {{ hint }}\r\n </p>\r\n\r\n <p key="errorMessage" class="mt-1.5 text-sm text-destructive" v-if="errorMessage">\r\n {{ errorMessage }}\r\n </p>\r\n </TransitionSlide>\r\n </div>\r\n</template>\r\n\r\n<script lang="ts" setup>\r\n import { useId } from "radix-vue";\r\n\r\n const props = defineProps<{\r\n label?: string;\r\n icon?: string;\r\n hint?: string;\r\n modelValue?: string;\r\n name?: string;\r\n id?: string;\r\n rules?: any;\r\n validateOnMount?: boolean;\r\n placeholder?: string;\r\n rows?: number;\r\n }>();\r\n\r\n defineOptions({ inheritAttrs: false });\r\n\r\n const inputId = useId(props.id);\r\n\r\n const hasIcon = computed(() => Boolean(props.icon) || Boolean(useSlots().icon));\r\n\r\n const { errorMessage, value, handleBlur } = useField(() => props.name || inputId, props.rules, {\r\n initialValue: props.modelValue,\r\n label: props.label,\r\n validateOnMount: props.validateOnMount,\r\n syncVModel: true,\r\n });\r\n</script>\r\n',
2300
+ '<template>\r\n <Toaster\r\n position="top-right"\r\n :visible-toasts="5"\r\n rich-colors\r\n :duration="7000"\r\n close-button\r\n :theme="$colorMode.value == \'dark\' ? \'dark\' : \'light\'"\r\n />\r\n</template>\r\n\r\n<script lang="ts" setup>\r\n import { Toaster } from "vue-sonner";\r\n</script>\r\n<style scoped>\r\n :deep([data-sonner-toaster][data-theme="dark"]),\r\n :deep([data-sonner-toaster][data-theme="light"]) {\r\n --normal-bg: theme("colors.popover.DEFAULT");\r\n --normal-border: theme("colors.border");\r\n --normal-text: theme("colors.popover.foreground");\r\n --border-radius: theme("borderRadius.md");\r\n }\r\n :deep([data-sonner-toaster]) {\r\n @apply font-sans;\r\n }\r\n :deep([data-sonner-toast][data-styled="true"]) {\r\n @apply items-start;\r\n }\r\n :deep([data-sonner-toast] [data-icon]) {\r\n @apply mt-0.5;\r\n }\r\n :deep([data-sonner-toast] [data-title]) {\r\n @apply text-sm font-semibold;\r\n }\r\n :deep([data-sonner-toast] [data-description]) {\r\n @apply text-sm;\r\n }\r\n :deep([data-sonner-toast] [data-close-button]) {\r\n @apply border border-border bg-background text-foreground hover:border-inherit hover:bg-inherit hover:text-accent-foreground;\r\n }\r\n :deep([data-sonner-toast] [data-button]) {\r\n @apply bg-primary text-primary-foreground transition hover:opacity-90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background;\r\n }\r\n :deep(.sonner-loading-bar) {\r\n @apply bg-muted-foreground;\r\n }\r\n</style>\r\n',
2281
2301
  },
2282
2302
  ],
2283
2303
  utils: [],
package/src/types.ts CHANGED
@@ -22,6 +22,7 @@ export type Component = {
22
22
  files: Composable[];
23
23
  utils: Composable[];
24
24
  composables: Composable[];
25
+ plugins: Composable[];
25
26
  components?: string[];
26
27
  askValidator?: boolean;
27
28
  };
@@ -0,0 +1,8 @@
1
+ import axios from "axios";
2
+
3
+ import { Component } from "../types";
4
+
5
+ export const fetchComponents = async () => {
6
+ const { data } = await axios.get<Component[]>("https://ui-thing.behonbaker.com/api/components");
7
+ return data;
8
+ };
@@ -1,13 +1,19 @@
1
+ import ora from "ora";
1
2
  import prompts from "prompts";
2
3
 
3
- import allComponents from "../comp";
4
+ import { Component } from "../types";
5
+ import { fetchComponents } from "./fetchComponents";
4
6
 
5
7
  export const promptUserForComponents = async (): Promise<string[]> => {
8
+ // get comps from API
9
+ const compsSpinner = ora("Fetching components...").start();
10
+ const allComponents = await fetchComponents();
11
+ compsSpinner.succeed("Fetched components");
6
12
  const { components } = await prompts({
7
13
  type: "autocompleteMultiselect",
8
14
  name: "components",
9
15
  message: "Select the components you want to add",
10
- choices: allComponents.map((c) => ({ title: c.name, value: c.value })),
16
+ choices: allComponents.map((c: Component) => ({ title: c.name, value: c.value })),
11
17
  onRender(kleur) {
12
18
  // @ts-ignore
13
19
  this.msg = kleur.bgCyan(" Choose components ") + " Select the components you want to add";