ui-thing 0.1.43 → 0.1.45
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/CHANGELOG.md +24 -0
- package/dist/index.js +399 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/add.ts +16 -0
- package/src/comps.ts +47 -0
- package/src/utils/installValidator.ts +35 -0
package/package.json
CHANGED
package/src/commands/add.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { compareUIConfig } from "../utils/compareUIConfig";
|
|
|
11
11
|
import { addModuleToConfig, getNuxtConfig, getUIConfig, updateConfig } from "../utils/config";
|
|
12
12
|
import { fileExists } from "../utils/fileExists";
|
|
13
13
|
import { installPackages } from "../utils/installPackages";
|
|
14
|
+
import { installValidator } from "../utils/installValidator";
|
|
14
15
|
import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
|
|
15
16
|
import { promptUserForComponents } from "../utils/promptForComponents";
|
|
16
17
|
import { writeFile } from "../utils/writeFile";
|
|
@@ -281,6 +282,21 @@ export const add = new Command()
|
|
|
281
282
|
}
|
|
282
283
|
}
|
|
283
284
|
|
|
285
|
+
// check if any of the components has the `askValidator` property set to true
|
|
286
|
+
let shouldAskValidator = false;
|
|
287
|
+
// Check if any component has askValidator set to true
|
|
288
|
+
for (const component of found) {
|
|
289
|
+
if (component.askValidator) {
|
|
290
|
+
shouldAskValidator = true;
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (shouldAskValidator) {
|
|
296
|
+
// Ask the user for their choice of validator
|
|
297
|
+
await installValidator(uiConfig.packageManager);
|
|
298
|
+
}
|
|
299
|
+
|
|
284
300
|
printFancyBoxMessage(
|
|
285
301
|
"All Done!",
|
|
286
302
|
{ title: "Components Added" },
|
package/src/comps.ts
CHANGED
|
@@ -407,6 +407,53 @@ export default [
|
|
|
407
407
|
composables: [],
|
|
408
408
|
plugins: [],
|
|
409
409
|
},
|
|
410
|
+
{
|
|
411
|
+
name: "Carousel",
|
|
412
|
+
value: "carousel",
|
|
413
|
+
files: [
|
|
414
|
+
{
|
|
415
|
+
fileName: "Carousel/Carousel.vue",
|
|
416
|
+
dirPath: "app/components/Ui",
|
|
417
|
+
fileContent:
|
|
418
|
+
'<template>\n <div\n :class="styles({ class: props.class })"\n role="region"\n aria-roledescription="carousel"\n tabindex="0"\n @keydown="onKeyDown"\n >\n <slot\n :can-scroll-next\n :can-scroll-prev\n :carousel-api\n :carousel-ref\n :orientation\n :scroll-next\n :scroll-prev\n />\n </div>\n</template>\n\n<script setup lang="ts">\n import type { CarouselEmits, CarouselProps, WithClassAsProps } from "~/composables/useCarousel";\n\n const styles = tv({\n base: "relative focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border",\n });\n const props = withDefaults(defineProps<CarouselProps & WithClassAsProps>(), {\n orientation: "horizontal",\n });\n const emits = defineEmits<CarouselEmits>();\n\n const {\n canScrollNext,\n canScrollPrev,\n carouselApi,\n carouselRef,\n orientation,\n scrollNext,\n scrollPrev,\n } = useProvideCarousel(props, emits);\n\n defineExpose({\n canScrollNext,\n canScrollPrev,\n carouselApi,\n carouselRef,\n orientation: props.orientation,\n scrollNext,\n scrollPrev,\n });\n\n function onKeyDown(event: KeyboardEvent) {\n const prevKey = props.orientation === "vertical" ? "ArrowUp" : "ArrowLeft";\n const nextKey = props.orientation === "vertical" ? "ArrowDown" : "ArrowRight";\n\n if (event.key === prevKey) {\n event.preventDefault();\n scrollPrev();\n return;\n }\n\n if (event.key === nextKey) {\n event.preventDefault();\n scrollNext();\n }\n }\n</script>\n',
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
fileName: "Carousel/Content.vue",
|
|
422
|
+
dirPath: "app/components/Ui",
|
|
423
|
+
fileContent:
|
|
424
|
+
'<template>\n <div ref="carouselRef" :class="styles().base({ orientation })">\n <div :class="styles().content({ orientation, class: props.class })" v-bind="$attrs">\n <slot />\n </div>\n </div>\n</template>\n\n<script setup lang="ts">\n import type { WithClassAsProps } from "~/composables/useCarousel";\n\n defineOptions({ inheritAttrs: false });\n const props = defineProps<WithClassAsProps>();\n const { carouselRef, orientation } = useCarousel();\n\n const styles = tv({\n slots: {\n base: "overflow-hidden",\n content: "flex",\n },\n variants: {\n orientation: {\n horizontal: { content: "-ml-4" },\n vertical: { content: "-mt-4 flex-col" },\n },\n },\n });\n</script>\n',
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
fileName: "Carousel/Item.vue",
|
|
428
|
+
dirPath: "app/components/Ui",
|
|
429
|
+
fileContent:
|
|
430
|
+
'<template>\n <div\n role="group"\n aria-roledescription="slide"\n :class="styles({ orientation, class: `${props.class} ${grabbingClass}` })"\n @mousedown="isGrabbing = true"\n @mouseup="isGrabbing = false"\n @mouseleave="isGrabbing = false"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang="ts">\n import type { WithClassAsProps } from "~/composables/useCarousel";\n\n const props = defineProps<\n WithClassAsProps & {\n /**\n * Whether to show the grab cursor when hovering over the item.\n * @default false\n */\n grabCursor?: boolean;\n }\n >();\n\n const { orientation } = useCarousel();\n\n const styles = tv({\n base: "min-w-0 shrink-0 grow-0 basis-full",\n variants: {\n orientation: {\n horizontal: "pl-4",\n vertical: "pt-4",\n },\n },\n });\n\n const isGrabbing = ref(false);\n\n const grabbingClass = computed(() => {\n if (!props.grabCursor) return "";\n return isGrabbing.value ? "cursor-grabbing" : "cursor-grab";\n });\n</script>\n',
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
fileName: "Carousel/Next.vue",
|
|
434
|
+
dirPath: "app/components/Ui",
|
|
435
|
+
fileContent:
|
|
436
|
+
'<template>\n <UiButton\n :disabled="!canScrollNext"\n :class="styles().base({ orientation, class: props.class })"\n :variant\n @click="scrollNext"\n >\n <slot>\n <Icon :name="props.icon" :class="styles().icon({ orientation, class: props.iconClass })" />\n <span class="sr-only">{{ props.srText }}</span>\n </slot>\n </UiButton>\n</template>\n\n<script setup lang="ts">\n import type { WithClassAsProps } from "~/composables/useCarousel";\n\n const props = withDefaults(\n defineProps<\n WithClassAsProps & {\n icon?: string;\n srText?: string;\n iconClass?: any;\n variant?: VariantProps<typeof buttonStyles>["variant"];\n }\n >(),\n {\n icon: "lucide:arrow-right",\n srText: "Next Slide",\n variant: "outline",\n }\n );\n\n const { orientation, canScrollNext, scrollNext } = useCarousel();\n\n const styles = tv({\n slots: {\n base: "absolute h-8 w-8 touch-manipulation rounded-full p-0",\n icon: "size-4 text-current",\n },\n variants: {\n orientation: {\n horizontal: { base: "-right-12 top-1/2 -translate-y-1/2" },\n vertical: { base: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90" },\n },\n },\n });\n</script>\n',
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
fileName: "Carousel/Previous.vue",
|
|
440
|
+
dirPath: "app/components/Ui",
|
|
441
|
+
fileContent:
|
|
442
|
+
'<template>\n <UiButton\n :disabled="!canScrollPrev"\n :class="styles().base({ orientation, class: props.class })"\n :variant\n @click="scrollPrev"\n >\n <slot>\n <Icon :name="props.icon" :class="styles().icon({ orientation, class: props.iconClass })" />\n <span class="sr-only">{{ props.srText }}</span>\n </slot>\n </UiButton>\n</template>\n\n<script setup lang="ts">\n import type { WithClassAsProps } from "~/composables/useCarousel";\n\n const props = withDefaults(\n defineProps<\n WithClassAsProps & {\n icon?: string;\n srText?: string;\n iconClass?: any;\n variant?: VariantProps<typeof buttonStyles>["variant"];\n }\n >(),\n {\n icon: "lucide:arrow-left",\n srText: "Previous Slide",\n variant: "outline",\n }\n );\n\n const { orientation, canScrollPrev, scrollPrev } = useCarousel();\n\n const styles = tv({\n slots: {\n base: "absolute h-8 w-8 touch-manipulation rounded-full p-0",\n icon: "size-4 text-current",\n },\n variants: {\n orientation: {\n horizontal: { base: "-left-12 top-1/2 -translate-y-1/2" },\n vertical: { base: "-top-12 left-1/2 -translate-x-1/2 rotate-90" },\n },\n },\n });\n</script>\n',
|
|
443
|
+
},
|
|
444
|
+
],
|
|
445
|
+
deps: ["embla-carousel-vue", "embla-carousel"],
|
|
446
|
+
composables: [
|
|
447
|
+
{
|
|
448
|
+
fileName: "useCarousel.ts",
|
|
449
|
+
dirPath: "composables",
|
|
450
|
+
fileContent:
|
|
451
|
+
'import { createInjectionState } from "@vueuse/core";\nimport emblaCarouselVue from "embla-carousel-vue";\nimport type useEmblaCarousel from "embla-carousel-vue";\nimport type { EmblaCarouselVueType } from "embla-carousel-vue";\nimport type { HTMLAttributes, UnwrapRef } from "vue";\n\ntype CApi = EmblaCarouselVueType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\nexport type CarouselApi = UnwrapRef<CApi>;\n\nexport interface CarouselProps {\n /**\n * The options to be passed to the EmblaCarousel instance\n */\n opts?: CarouselOptions;\n /**\n * The plugins to be passed to the EmblaCarousel instance\n */\n plugins?: CarouselPlugin;\n /**\n * The orientation of the carousel\n * @default "horizontal"\n */\n orientation?: "horizontal" | "vertical";\n}\n\nexport interface CarouselEmits {\n (e: "init-api", payload: CarouselApi): void;\n}\n\nexport interface WithClassAsProps {\n /**\n * The class name to be applied to the root element of the component\n * @default undefined\n */\n class?: HTMLAttributes["class"];\n}\n\nconst [useProvideCarousel, useInjectCarousel] = createInjectionState(\n ({ opts, orientation, plugins }: CarouselProps, emits: CarouselEmits) => {\n const [emblaNode, emblaApi] = emblaCarouselVue(\n {\n ...opts,\n axis: orientation === "horizontal" ? "x" : "y",\n },\n plugins\n );\n\n /**\n * Scroll to the previous slide\n */\n function scrollPrev() {\n emblaApi.value?.scrollPrev();\n }\n /**\n * Scroll to the next slide\n */\n function scrollNext() {\n emblaApi.value?.scrollNext();\n }\n /**\n * Whether the carousel can scroll to the next slide\n */\n const canScrollNext = ref(false);\n /**\n * Whether the carousel can scroll to the previous slide\n */\n const canScrollPrev = ref(false);\n /**\n * Method used to update the canScrollNext and canScrollPrev values\n */\n function onSelect(api: CarouselApi) {\n canScrollNext.value = api?.canScrollNext() || false;\n canScrollPrev.value = api?.canScrollPrev() || false;\n }\n\n onMounted(() => {\n if (!emblaApi.value) return;\n emblaApi.value?.on("init", onSelect);\n emblaApi.value?.on("reInit", onSelect);\n emblaApi.value?.on("select", onSelect);\n\n emits("init-api", emblaApi.value);\n });\n\n return {\n carouselRef: emblaNode,\n carouselApi: emblaApi,\n canScrollPrev,\n canScrollNext,\n scrollPrev,\n scrollNext,\n orientation,\n };\n }\n);\n\n/**\n * A composable function to be used within a <UiCarousel /> component\n */\nfunction useCarousel() {\n const carouselState = useInjectCarousel();\n if (!carouselState) throw new Error("useCarousel must be used within a <UiCarousel />");\n return carouselState;\n}\n\nexport { useCarousel, useProvideCarousel };\n',
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
utils: [],
|
|
455
|
+
plugins: [],
|
|
456
|
+
},
|
|
410
457
|
{
|
|
411
458
|
name: "Chart",
|
|
412
459
|
value: "chart",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
|
|
3
|
+
import { installPackages } from "./installPackages";
|
|
4
|
+
|
|
5
|
+
export const installValidator = async (packageManager: string) => {
|
|
6
|
+
// Depending on the selected validator, install the corresponding packages
|
|
7
|
+
const validatorPackages = {
|
|
8
|
+
yup: ["yup", "@vee-validate/yup"],
|
|
9
|
+
zod: ["zod", "@vee-validate/zod"],
|
|
10
|
+
joi: ["joi", "@vee-validate/joi"],
|
|
11
|
+
valibot: ["valibot", "@vee-validate/valibot"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const { validator }: { validator: keyof typeof validatorPackages } = await prompts({
|
|
15
|
+
type: "select",
|
|
16
|
+
name: "validator",
|
|
17
|
+
message: "Choose the validator package to use with Vee Validate: ",
|
|
18
|
+
choices: [
|
|
19
|
+
{ title: "Yup", value: "yup" },
|
|
20
|
+
{ title: "Zod", value: "zod" },
|
|
21
|
+
{ title: "Joi", value: "joi" },
|
|
22
|
+
{ title: "Valibot", value: "valibot" },
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
if (!validator) {
|
|
26
|
+
console.log("No validator package selected");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log(`Selected ${validator} as the validator package`);
|
|
30
|
+
|
|
31
|
+
if (validatorPackages[validator]) {
|
|
32
|
+
await installPackages(packageManager, validatorPackages[validator]);
|
|
33
|
+
}
|
|
34
|
+
return validator;
|
|
35
|
+
};
|