Merge remote-tracking branch 'origin/dev' into refactor/update-tailwind-classes
# Conflicts: # apps/www/src/public/registry/styles/default/calendar.json # apps/www/src/public/registry/styles/default/select.json # apps/www/src/public/registry/styles/new-york/calendar.json # apps/www/src/public/registry/styles/new-york/select.json
This commit is contained in:
commit
90dcb7aaa7
|
|
@ -359,6 +359,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/DatePickerWithRange.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/DatePickerWithRange.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/DatePickerWithRange.vue'],
|
files: ['../src/lib/registry/default/example/DatePickerWithRange.vue'],
|
||||||
},
|
},
|
||||||
|
DateTimePickerDemo: {
|
||||||
|
name: 'DateTimePickerDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/DateTimePickerDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/DateTimePickerDemo.vue'],
|
||||||
|
},
|
||||||
DialogCustomCloseButton: {
|
DialogCustomCloseButton: {
|
||||||
name: 'DialogCustomCloseButton',
|
name: 'DialogCustomCloseButton',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1194,6 +1201,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/DatePickerWithRange.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/DatePickerWithRange.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/DatePickerWithRange.vue'],
|
files: ['../src/lib/registry/new-york/example/DatePickerWithRange.vue'],
|
||||||
},
|
},
|
||||||
|
DateTimePickerDemo: {
|
||||||
|
name: 'DateTimePickerDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/DateTimePickerDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/DateTimePickerDemo.vue'],
|
||||||
|
},
|
||||||
DialogCustomCloseButton: {
|
DialogCustomCloseButton: {
|
||||||
name: 'DialogCustomCloseButton',
|
name: 'DialogCustomCloseButton',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "www",
|
"name": "www",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.6",
|
"version": "0.8.7",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,10 @@ const date = ref<Date>()
|
||||||
|
|
||||||
<ComponentPreview name="DatePickerWithRange" />
|
<ComponentPreview name="DatePickerWithRange" />
|
||||||
|
|
||||||
|
### Date Time Picker
|
||||||
|
|
||||||
|
<ComponentPreview name="DateTimePickerDemo" />
|
||||||
|
|
||||||
### With Presets
|
### With Presets
|
||||||
|
|
||||||
<ComponentPreview name="DatePickerWithPresets" />
|
<ComponentPreview name="DatePickerWithPresets" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { format } from 'date-fns'
|
||||||
|
import { Calendar as CalendarIcon } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import { Calendar } from '@/lib/registry/default/ui/calendar'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/popover'
|
||||||
|
|
||||||
|
const date = ref<Date>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
:variant="'outline'"
|
||||||
|
:class="cn(
|
||||||
|
'w-[280px] justify-start text-left font-normal',
|
||||||
|
!date && 'text-muted-foreground',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
|
<span>{{ date ? format(date, 'PPP - hh:mm') : "Pick a date" }}</span>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-auto p-0">
|
||||||
|
<Calendar v-model="date" mode="datetime" />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
|
@ -1,15 +1,20 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { VariantProps } from 'class-variance-authority'
|
||||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||||
import { buttonVariants } from '.'
|
import { buttonVariants } from '.'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
interface ButtonVariantProps extends VariantProps<typeof buttonVariants> {}
|
||||||
|
|
||||||
interface Props extends PrimitiveProps {
|
interface Props extends PrimitiveProps {
|
||||||
variant?: NonNullable<Parameters<typeof buttonVariants>[0]>['variant']
|
variant?: ButtonVariantProps['variant']
|
||||||
size?: NonNullable<Parameters<typeof buttonVariants>[0]>['size']
|
size?: ButtonVariantProps['size']
|
||||||
as?: string
|
as?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
as: 'button',
|
as: 'button',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { cva } from 'class-variance-authority'
|
||||||
export { default as Button } from './Button.vue'
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
export const buttonVariants = cva(
|
export const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
'inline-flex items-center justify-center rounded-md whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|
|
||||||
|
|
@ -236,4 +236,49 @@ onMounted(async () => {
|
||||||
-webkit-transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
-webkit-transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
||||||
transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Timepicker styles
|
||||||
|
*/
|
||||||
|
.vc-time-picker {
|
||||||
|
@apply flex flex-col items-center p-2;
|
||||||
|
}
|
||||||
|
.vc-time-picker.vc-invalid {
|
||||||
|
@apply pointer-events-none opacity-50;
|
||||||
|
}
|
||||||
|
.vc-time-picker.vc-attached {
|
||||||
|
@apply border-t border-solid border-secondary mt-2;
|
||||||
|
}
|
||||||
|
.vc-time-picker > * + * {
|
||||||
|
@apply mt-1;
|
||||||
|
}
|
||||||
|
.vc-time-header {
|
||||||
|
@apply flex items-center text-sm font-semibold uppercase mt-1 px-1 leading-6;
|
||||||
|
}
|
||||||
|
.vc-time-select-group {
|
||||||
|
@apply inline-flex items-center px-1 rounded-md bg-primary-foreground border border-solid border-secondary;
|
||||||
|
}
|
||||||
|
.vc-time-select-group .vc-base-icon {
|
||||||
|
@apply mr-1 text-primary stroke-primary;
|
||||||
|
}
|
||||||
|
.vc-time-select-group select {
|
||||||
|
@apply bg-primary-foreground p-1 appearance-none outline-none text-center;
|
||||||
|
}
|
||||||
|
.vc-time-weekday {
|
||||||
|
@apply text-muted-foreground tracking-wide;
|
||||||
|
}
|
||||||
|
.vc-time-month {
|
||||||
|
@apply text-primary ml-2;
|
||||||
|
}
|
||||||
|
.vc-time-day {
|
||||||
|
@apply text-primary ml-1;
|
||||||
|
}
|
||||||
|
.vc-time-year {
|
||||||
|
@apply text-muted-foreground ml-2;
|
||||||
|
}
|
||||||
|
.vc-time-colon {
|
||||||
|
@apply mb-0.5;
|
||||||
|
}
|
||||||
|
.vc-time-decimal {
|
||||||
|
@apply ml-0.5;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const props = withDefaults(
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
:class="[
|
:class="[
|
||||||
cn(
|
cn(
|
||||||
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 whitespace-nowrap [&>span]:truncate [&>span]:min-w-0',
|
||||||
props.class,
|
props.class,
|
||||||
),
|
),
|
||||||
props.invalid
|
props.invalid
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { format } from 'date-fns'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { CalendarIcon } from '@radix-icons/vue'
|
||||||
|
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
import { Calendar } from '@/lib/registry/new-york/ui/calendar'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/lib/registry/new-york/ui/popover'
|
||||||
|
|
||||||
|
const date = ref<Date>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
:variant="'outline'"
|
||||||
|
:class="cn(
|
||||||
|
'w-[280px] justify-start text-left font-normal',
|
||||||
|
!date && 'text-muted-foreground',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
|
<span>{{ date ? format(date, 'PPP - hh:mm') : "Pick a date" }}</span>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-auto p-0">
|
||||||
|
<Calendar v-model="date" mode="datetime" />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
|
@ -1,15 +1,20 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { VariantProps } from 'class-variance-authority'
|
||||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||||
import { buttonVariants } from '.'
|
import { buttonVariants } from '.'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
interface ButtonVariantProps extends VariantProps<typeof buttonVariants> {}
|
||||||
|
|
||||||
interface Props extends PrimitiveProps {
|
interface Props extends PrimitiveProps {
|
||||||
variant?: NonNullable<Parameters<typeof buttonVariants>[0]>['variant']
|
variant?: ButtonVariantProps['variant']
|
||||||
size?: NonNullable<Parameters<typeof buttonVariants>[0]>['size']
|
size?: ButtonVariantProps['size']
|
||||||
as?: string
|
as?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
as: 'button',
|
as: 'button',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { cva } from 'class-variance-authority'
|
||||||
export { default as Button } from './Button.vue'
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
export const buttonVariants = cva(
|
export const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
'inline-flex items-center justify-center rounded-md whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|
|
||||||
|
|
@ -242,4 +242,49 @@ onMounted(async () => {
|
||||||
-webkit-transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
-webkit-transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
||||||
transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
transform: translateY(calc(-1 * var(--vc-slide-translate)));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Timepicker styles
|
||||||
|
*/
|
||||||
|
.vc-time-picker {
|
||||||
|
@apply flex flex-col items-center p-2;
|
||||||
|
}
|
||||||
|
.vc-time-picker.vc-invalid {
|
||||||
|
@apply pointer-events-none opacity-50;
|
||||||
|
}
|
||||||
|
.vc-time-picker.vc-attached {
|
||||||
|
@apply border-t border-solid border-secondary mt-2;
|
||||||
|
}
|
||||||
|
.vc-time-picker > * + * {
|
||||||
|
@apply mt-1;
|
||||||
|
}
|
||||||
|
.vc-time-header {
|
||||||
|
@apply flex items-center text-sm font-semibold uppercase mt-1 px-1 leading-6;
|
||||||
|
}
|
||||||
|
.vc-time-select-group {
|
||||||
|
@apply inline-flex items-center px-1 rounded-md bg-primary-foreground border border-solid border-secondary;
|
||||||
|
}
|
||||||
|
.vc-time-select-group .vc-base-icon {
|
||||||
|
@apply mr-1 text-primary stroke-primary;
|
||||||
|
}
|
||||||
|
.vc-time-select-group select {
|
||||||
|
@apply bg-primary-foreground p-1 appearance-none outline-none text-center;
|
||||||
|
}
|
||||||
|
.vc-time-weekday {
|
||||||
|
@apply text-muted-foreground tracking-wide;
|
||||||
|
}
|
||||||
|
.vc-time-month {
|
||||||
|
@apply text-primary ml-2;
|
||||||
|
}
|
||||||
|
.vc-time-day {
|
||||||
|
@apply text-primary ml-1;
|
||||||
|
}
|
||||||
|
.vc-time-year {
|
||||||
|
@apply text-muted-foreground ml-2;
|
||||||
|
}
|
||||||
|
.vc-time-colon {
|
||||||
|
@apply mb-0.5;
|
||||||
|
}
|
||||||
|
.vc-time-decimal {
|
||||||
|
@apply ml-0.5;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const props = withDefaults(
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
:class="[
|
:class="[
|
||||||
cn(
|
cn(
|
||||||
'flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
|
'flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 whitespace-nowrap [&>span]:truncate [&>span]:min-w-0',
|
||||||
props.class,
|
props.class,
|
||||||
),
|
),
|
||||||
props.invalid
|
props.invalid
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -11,7 +11,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SelectContent.vue",
|
"name": "SelectContent.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport {\n SelectContent,\n type SelectContentEmits,\n type SelectContentProps,\n SelectPortal,\n SelectViewport,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(\n defineProps<SelectContentProps & { class?: string }>(), {\n position: 'popper',\n sideOffset: 4,\n },\n)\nconst emits = defineEmits<SelectContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <SelectPortal>\n <SelectContent\n v-bind=\"{ ...forwarded, ...$attrs }\"\n :class=\"\n cn(\n 'relative z-50 min-w-40 overflow-hidden rounded-md bg-background border border-border text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-[--radix-popper-available-height]',\n position === 'popper'\n && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n props.class,\n )\n \"\n >\n <SelectViewport\n :class=\"\n cn('p-1',\n position === 'popper'\n && 'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]')\"\n >\n <slot />\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n</template>\n"
|
"content": "<script setup lang=\"ts\">\nimport {\n SelectContent,\n type SelectContentEmits,\n type SelectContentProps,\n SelectPortal,\n SelectViewport,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(\n defineProps<SelectContentProps & { class?: string }>(), {\n position: 'popper',\n sideOffset: 4,\n },\n)\nconst emits = defineEmits<SelectContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <SelectPortal>\n <SelectContent\n v-bind=\"{ ...forwarded, ...$attrs }\"\n :class=\"\n cn(\n 'relative z-50 min-w-[10rem] overflow-hidden rounded-md bg-background border border-border text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-[--radix-popper-available-height]',\n position === 'popper'\n && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n props.class,\n )\n \"\n >\n <SelectViewport\n :class=\"\n cn('p-1',\n position === 'popper'\n && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]')\"\n >\n <slot />\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SelectGroup.vue",
|
"name": "SelectGroup.vue",
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -11,7 +11,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SelectContent.vue",
|
"name": "SelectContent.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport {\n SelectContent,\n type SelectContentEmits,\n type SelectContentProps,\n SelectPortal,\n SelectViewport,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(\n defineProps<SelectContentProps & { class?: string }>(), {\n position: 'popper',\n sideOffset: 4,\n },\n)\nconst emits = defineEmits<SelectContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <SelectPortal>\n <SelectContent\n v-bind=\"{ ...forwarded, ...$attrs }\"\n :class=\"\n cn(\n 'relative z-50 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-[--radix-popper-available-height]',\n position === 'popper'\n && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n props.class,\n )\n \"\n >\n <SelectViewport\n :class=\"\n cn('p-0',\n position === 'popper'\n && 'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]')\"\n >\n <slot />\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n</template>\n"
|
"content": "<script setup lang=\"ts\">\nimport {\n SelectContent,\n type SelectContentEmits,\n type SelectContentProps,\n SelectPortal,\n SelectViewport,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(\n defineProps<SelectContentProps & { class?: string }>(), {\n position: 'popper',\n sideOffset: 4,\n },\n)\nconst emits = defineEmits<SelectContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <SelectPortal>\n <SelectContent\n v-bind=\"{ ...forwarded, ...$attrs }\"\n :class=\"\n cn(\n 'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-[--radix-popper-available-height]',\n position === 'popper'\n && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n props.class,\n )\n \"\n >\n <SelectViewport\n :class=\"\n cn('p-0',\n position === 'popper'\n && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]')\"\n >\n <slot />\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n</template>\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SelectGroup.vue",
|
"name": "SelectGroup.vue",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "shadcn-vue",
|
"name": "shadcn-vue",
|
||||||
"version": "0.8.6",
|
"version": "0.8.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@8.10.2",
|
"packageManager": "pnpm@8.10.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "shadcn-vue",
|
"name": "shadcn-vue",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.6",
|
"version": "0.8.7",
|
||||||
"description": "Add components to your apps.",
|
"description": "Add components to your apps.",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "shadcn-nuxt",
|
"name": "shadcn-nuxt",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.6",
|
"version": "0.8.7",
|
||||||
"description": "Add shadcn-vue module to Nuxt",
|
"description": "Add shadcn-vue module to Nuxt",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
|
@ -36,8 +36,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/kit": "^3.8.2",
|
"@nuxt/kit": "^3.8.2",
|
||||||
"recast": "^0.23.4",
|
"oxc-parser": "^0.2.0"
|
||||||
"ts-morph": "^19.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/devtools": "latest",
|
"@nuxt/devtools": "latest",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useProvideCarousel } from './useCarousel'
|
||||||
|
import type { CarouselEmits, CarouselProps, WithClassAsProps } from './interface'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<CarouselProps & WithClassAsProps>(), {
|
||||||
|
orientation: 'horizontal',
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits<CarouselEmits>()
|
||||||
|
|
||||||
|
const carouselArgs = useProvideCarousel(props, emits)
|
||||||
|
|
||||||
|
defineExpose(carouselArgs)
|
||||||
|
|
||||||
|
function onKeyDown(event: KeyboardEvent) {
|
||||||
|
const prevKey = props.orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft'
|
||||||
|
const nextKey = props.orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight'
|
||||||
|
|
||||||
|
if (event.key === prevKey) {
|
||||||
|
event.preventDefault()
|
||||||
|
carouselArgs.scrollPrev()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === nextKey) {
|
||||||
|
event.preventDefault()
|
||||||
|
carouselArgs.scrollNext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="cn('relative', props.class)"
|
||||||
|
role="region"
|
||||||
|
aria-roledescription="carousel"
|
||||||
|
tabindex="0"
|
||||||
|
@keydown="onKeyDown"
|
||||||
|
>
|
||||||
|
<slot v-bind="carouselArgs" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { WithClassAsProps } from './interface'
|
||||||
|
import { useCarousel } from './useCarousel'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps<WithClassAsProps>()
|
||||||
|
|
||||||
|
const { carouselRef, orientation } = useCarousel()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="carouselRef" class="overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex',
|
||||||
|
orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
v-bind="$attrs"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { WithClassAsProps } from './interface'
|
||||||
|
import { useCarousel } from './useCarousel'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<WithClassAsProps>()
|
||||||
|
|
||||||
|
const { orientation } = useCarousel()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
role="group"
|
||||||
|
aria-roledescription="slide"
|
||||||
|
:class="cn(
|
||||||
|
'min-w-0 shrink-0 grow-0 basis-full',
|
||||||
|
orientation === 'horizontal' ? 'pl-4' : 'pt-4',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronRight } from 'lucide-vue-next'
|
||||||
|
import { useCarousel } from './useCarousel'
|
||||||
|
import type { WithClassAsProps } from './interface'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
|
||||||
|
const props = defineProps<WithClassAsProps>()
|
||||||
|
|
||||||
|
const { orientation, canScrollNext, scrollNext } = useCarousel()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Button
|
||||||
|
:disabled="!canScrollNext"
|
||||||
|
:class="cn(
|
||||||
|
'absolute h-10 w-10 rounded-full p-0',
|
||||||
|
orientation === 'horizontal'
|
||||||
|
? '-right-12 top-1/2 -translate-y-1/2'
|
||||||
|
: '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
variant="outline"
|
||||||
|
@click="scrollNext"
|
||||||
|
>
|
||||||
|
<slot>
|
||||||
|
<ChevronRight class="h-4 w-4 text-current" />
|
||||||
|
</slot>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ChevronLeft } from 'lucide-vue-next'
|
||||||
|
import { useCarousel } from './useCarousel'
|
||||||
|
import type { WithClassAsProps } from './interface'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
|
||||||
|
const props = defineProps<WithClassAsProps>()
|
||||||
|
|
||||||
|
const { orientation, canScrollPrev, scrollPrev } = useCarousel()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Button
|
||||||
|
:disabled="!canScrollPrev"
|
||||||
|
:class="cn(
|
||||||
|
'absolute h-10 w-10 rounded-full p-0',
|
||||||
|
orientation === 'horizontal'
|
||||||
|
? '-left-12 top-1/2 -translate-y-1/2'
|
||||||
|
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
variant="outline"
|
||||||
|
@click="scrollPrev"
|
||||||
|
>
|
||||||
|
<slot>
|
||||||
|
<ChevronLeft class="h-4 w-4 text-current" />
|
||||||
|
</slot>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
10
packages/module/playground/components/ui/carousel/index.ts
Normal file
10
packages/module/playground/components/ui/carousel/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export { default as Carousel } from './Carousel.vue'
|
||||||
|
export { default as CarouselContent } from './CarouselContent.vue'
|
||||||
|
export { default as CarouselItem } from './CarouselItem.vue'
|
||||||
|
export { default as CarouselPrevious } from './CarouselPrevious.vue'
|
||||||
|
export { default as CarouselNext } from './CarouselNext.vue'
|
||||||
|
export { useCarousel } from './useCarousel'
|
||||||
|
|
||||||
|
export type {
|
||||||
|
EmblaCarouselType as CarouselApi,
|
||||||
|
} from 'embla-carousel'
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type {
|
||||||
|
EmblaCarouselType as CarouselApi,
|
||||||
|
EmblaOptionsType as CarouselOptions,
|
||||||
|
EmblaPluginType as CarouselPlugin,
|
||||||
|
} from 'embla-carousel'
|
||||||
|
import type { HTMLAttributes, Ref } from 'vue'
|
||||||
|
|
||||||
|
export interface CarouselProps {
|
||||||
|
opts?: CarouselOptions | Ref<CarouselOptions>
|
||||||
|
plugins?: CarouselPlugin[] | Ref<CarouselPlugin[]>
|
||||||
|
orientation?: 'horizontal' | 'vertical'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CarouselEmits {
|
||||||
|
(e: 'init-api', payload: CarouselApi): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithClassAsProps {
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { createInjectionState } from '@vueuse/core'
|
||||||
|
import emblaCarouselVue from 'embla-carousel-vue'
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import type {
|
||||||
|
EmblaCarouselType as CarouselApi,
|
||||||
|
} from 'embla-carousel'
|
||||||
|
import type { CarouselEmits, CarouselProps } from './interface'
|
||||||
|
|
||||||
|
const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
||||||
|
({
|
||||||
|
opts, orientation, plugins,
|
||||||
|
}: CarouselProps, emits: CarouselEmits) => {
|
||||||
|
const [emblaNode, emblaApi] = emblaCarouselVue({
|
||||||
|
...opts,
|
||||||
|
axis: orientation === 'horizontal' ? 'x' : 'y',
|
||||||
|
}, plugins)
|
||||||
|
|
||||||
|
function scrollPrev() {
|
||||||
|
emblaApi.value?.scrollPrev()
|
||||||
|
}
|
||||||
|
function scrollNext() {
|
||||||
|
emblaApi.value?.scrollNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
const canScrollNext = ref(true)
|
||||||
|
const canScrollPrev = ref(true)
|
||||||
|
|
||||||
|
function onSelect(api: CarouselApi) {
|
||||||
|
canScrollNext.value = api.canScrollNext()
|
||||||
|
canScrollPrev.value = api.canScrollPrev()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!emblaApi.value)
|
||||||
|
return
|
||||||
|
|
||||||
|
emblaApi.value?.on('init', onSelect)
|
||||||
|
emblaApi.value?.on('reInit', onSelect)
|
||||||
|
emblaApi.value?.on('select', onSelect)
|
||||||
|
|
||||||
|
emits('init-api', emblaApi.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
function useCarousel() {
|
||||||
|
const carouselState = useInjectCarousel()
|
||||||
|
|
||||||
|
if (!carouselState)
|
||||||
|
throw new Error('useCarousel must be used within a <Carousel />')
|
||||||
|
|
||||||
|
return carouselState
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useCarousel, useProvideCarousel }
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
"@nuxtjs/tailwindcss": "^6.10.1",
|
"@nuxtjs/tailwindcss": "^6.10.1",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
|
"embla-carousel": "8.0.0-rc19",
|
||||||
|
"embla-carousel-vue": "8.0.0-rc19",
|
||||||
"lucide-vue-next": "^0.276.0",
|
"lucide-vue-next": "^0.276.0",
|
||||||
"radix-vue": "^1.3.0",
|
"radix-vue": "^1.3.0",
|
||||||
"tailwind-merge": "^2.0.0",
|
"tailwind-merge": "^2.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { readFileSync, readdirSync } from 'node:fs'
|
import { readFileSync, readdirSync } from 'node:fs'
|
||||||
import { join } from 'node:path'
|
import { join } from 'node:path'
|
||||||
import { addComponent, createResolver, defineNuxtModule } from '@nuxt/kit'
|
import { addComponent, createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||||
import { parse } from 'recast'
|
import oxc from 'oxc-parser'
|
||||||
|
|
||||||
|
// TODO: add test to make sure all registry is being parse correctly
|
||||||
// Module options TypeScript interface definition
|
// Module options TypeScript interface definition
|
||||||
export interface ModuleOptions {
|
export interface ModuleOptions {
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,24 +41,34 @@ export default defineNuxtModule<ModuleOptions>({
|
||||||
try {
|
try {
|
||||||
readdirSync(resolve(COMPONENT_DIR_PATH))
|
readdirSync(resolve(COMPONENT_DIR_PATH))
|
||||||
.forEach(async (dir) => {
|
.forEach(async (dir) => {
|
||||||
const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, 'index'), { extensions: ['.ts', '.js'] })
|
try {
|
||||||
const content = readFileSync(filePath, { encoding: 'utf8' })
|
const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, 'index'), { extensions: ['.ts', '.js'] })
|
||||||
const ast = parse(content)
|
const content = readFileSync(filePath, { encoding: 'utf8' })
|
||||||
|
const ast = oxc.parseSync(content, {
|
||||||
const exportedKeys: string[] = ast.program.body
|
sourceType: 'module',
|
||||||
// @ts-expect-error parse return any
|
sourceFilename: filePath,
|
||||||
.filter(node => node.type === 'ExportNamedDeclaration')
|
|
||||||
// @ts-expect-error parse return any
|
|
||||||
.flatMap(node => node.specifiers.map(specifier => specifier.exported.name))
|
|
||||||
.filter((key: string) => /^[A-Z]/.test(key))
|
|
||||||
|
|
||||||
exportedKeys.forEach((key) => {
|
|
||||||
addComponent({
|
|
||||||
name: `${prefix}${key}`, // name of the component to be used in vue templates
|
|
||||||
export: key, // (optional) if the component is a named (rather than default) export
|
|
||||||
filePath: resolve(filePath),
|
|
||||||
})
|
})
|
||||||
})
|
const program = JSON.parse(ast.program)
|
||||||
|
|
||||||
|
const exportedKeys: string[] = program.body
|
||||||
|
// @ts-expect-error parse return any
|
||||||
|
.filter(node => node.type === 'ExportNamedDeclaration')
|
||||||
|
// @ts-expect-error parse return any
|
||||||
|
.flatMap(node => node.specifiers.map(specifier => specifier.exported.name))
|
||||||
|
.filter((key: string) => /^[A-Z]/.test(key))
|
||||||
|
|
||||||
|
exportedKeys.forEach((key) => {
|
||||||
|
addComponent({
|
||||||
|
name: `${prefix}${key}`, // name of the component to be used in vue templates
|
||||||
|
export: key, // (optional) if the component is a named (rather than default) export
|
||||||
|
filePath: resolve(filePath),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err instanceof Error)
|
||||||
|
console.warn('Module error: ', err.message)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
|
|
||||||
587
pnpm-lock.yaml
587
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user