refactor: change the shadcn-ui directory and remove rarely used components (#4626)

This commit is contained in:
Vben
2024-10-13 10:58:09 +08:00
committed by GitHub
parent 1b65254383
commit 0ea0f204cb
210 changed files with 75 additions and 410 deletions

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
AccordionRoot,
type AccordionRootEmits,
type AccordionRootProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<AccordionRootProps>();
const emits = defineEmits<AccordionRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<AccordionRoot v-bind="forwarded">
<slot></slot>
</AccordionRoot>
</template>

View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { AccordionContent, type AccordionContentProps } from 'radix-vue';
const props = defineProps<{ class?: any } & AccordionContentProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<AccordionContent
v-bind="delegatedProps"
class="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
>
<div :class="cn('pb-4 pt-0', props.class)">
<slot></slot>
</div>
</AccordionContent>
</template>

View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
AccordionItem,
type AccordionItemProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<{ class?: any } & AccordionItemProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<AccordionItem v-bind="forwardedProps" :class="cn('border-b', props.class)">
<slot></slot>
</AccordionItem>
</template>

View File

@@ -0,0 +1,41 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ChevronDown } from 'lucide-vue-next';
import {
AccordionHeader,
AccordionTrigger,
type AccordionTriggerProps,
} from 'radix-vue';
const props = defineProps<{ class?: any } & AccordionTriggerProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<AccordionHeader class="flex">
<AccordionTrigger
v-bind="delegatedProps"
:class="
cn(
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
props.class,
)
"
>
<slot></slot>
<slot name="icon">
<ChevronDown
class="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200"
/>
</slot>
</AccordionTrigger>
</AccordionHeader>
</template>

View File

@@ -0,0 +1,4 @@
export { default as Accordion } from './Accordion.vue';
export { default as AccordionContent } from './AccordionContent.vue';
export { default as AccordionItem } from './AccordionItem.vue';
export { default as AccordionTrigger } from './AccordionTrigger.vue';

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
import { AvatarRoot } from 'radix-vue';
import { avatarVariant, type AvatarVariants } from './avatar';
const props = withDefaults(
defineProps<{
class?: any;
shape?: AvatarVariants['shape'];
size?: AvatarVariants['size'];
}>(),
{
shape: 'circle',
size: 'sm',
},
);
</script>
<template>
<AvatarRoot :class="cn(avatarVariant({ size, shape }), props.class)">
<slot></slot>
</AvatarRoot>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { AvatarFallback, type AvatarFallbackProps } from 'radix-vue';
const props = defineProps<AvatarFallbackProps>();
</script>
<template>
<AvatarFallback v-bind="props">
<slot></slot>
</AvatarFallback>
</template>

View File

@@ -0,0 +1,9 @@
<script setup lang="ts">
import { AvatarImage, type AvatarImageProps } from 'radix-vue';
const props = defineProps<AvatarImageProps>();
</script>
<template>
<AvatarImage v-bind="props" class="h-full w-full object-cover" />
</template>

View File

@@ -0,0 +1,20 @@
import { cva, type VariantProps } from 'class-variance-authority';
export const avatarVariant = cva(
'inline-flex items-center justify-center font-normal text-foreground select-none shrink-0 bg-secondary overflow-hidden',
{
variants: {
shape: {
circle: 'rounded-full',
square: 'rounded-md',
},
size: {
base: 'h-16 w-16 text-2xl',
lg: 'h-32 w-32 text-5xl',
sm: 'h-10 w-10 text-xs',
},
},
},
);
export type AvatarVariants = VariantProps<typeof avatarVariant>;

View File

@@ -0,0 +1,4 @@
export * from './avatar';
export { default as Avatar } from './Avatar.vue';
export { default as AvatarFallback } from './AvatarFallback.vue';
export { default as AvatarImage } from './AvatarImage.vue';

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
import { type BadgeVariants, badgeVariants } from './badge';
const props = defineProps<{
class?: any;
variant?: BadgeVariants['variant'];
}>();
</script>
<template>
<div :class="cn(badgeVariants({ variant }), props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,23 @@
import { cva, type VariantProps } from 'class-variance-authority';
export const badgeVariants = cva(
'inline-flex items-center rounded-md border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
defaultVariants: {
variant: 'default',
},
variants: {
variant: {
default:
'border-transparent bg-accent hover:bg-accent text-primary-foreground shadow',
destructive:
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive-hover',
outline: 'text-foreground',
secondary:
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
},
},
},
);
export type BadgeVariants = VariantProps<typeof badgeVariants>;

View File

@@ -0,0 +1,3 @@
export * from './badge';
export { default as Badge } from './Badge.vue';

View File

@@ -0,0 +1,11 @@
<script lang="ts" setup>
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<nav :class="props.class" aria-label="breadcrumb" role="navigation">
<slot></slot>
</nav>
</template>

View File

@@ -0,0 +1,22 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { MoreHorizontal } from 'lucide-vue-next';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<span
:class="cn('flex h-9 w-9 items-center justify-center', props.class)"
aria-hidden="true"
role="presentation"
>
<slot>
<MoreHorizontal class="h-4 w-4" />
</slot>
<span class="sr-only">More</span>
</span>
</template>

View File

@@ -0,0 +1,17 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<li
:class="
cn('hover:text-foreground inline-flex items-center gap-1.5', props.class)
"
>
<slot></slot>
</li>
</template>

View File

@@ -0,0 +1,19 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { Primitive, type PrimitiveProps } from 'radix-vue';
const props = withDefaults(defineProps<{ class?: any } & PrimitiveProps>(), {
as: 'a',
});
</script>
<template>
<Primitive
:as="as"
:as-child="asChild"
:class="cn('hover:text-foreground transition-colors', props.class)"
>
<slot></slot>
</Primitive>
</template>

View File

@@ -0,0 +1,20 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<ol
:class="
cn(
'text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5',
props.class,
)
"
>
<slot></slot>
</ol>
</template>

View File

@@ -0,0 +1,18 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<span
:class="cn('text-foreground font-normal', props.class)"
aria-current="page"
aria-disabled="true"
role="link"
>
<slot></slot>
</span>
</template>

View File

@@ -0,0 +1,21 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { ChevronRight } from 'lucide-vue-next';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<li
:class="cn('[&>svg]:size-3.5', props.class)"
aria-hidden="true"
role="presentation"
>
<slot>
<ChevronRight />
</slot>
</li>
</template>

View File

@@ -0,0 +1,7 @@
export { default as Breadcrumb } from './Breadcrumb.vue';
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue';
export { default as BreadcrumbItem } from './BreadcrumbItem.vue';
export { default as BreadcrumbLink } from './BreadcrumbLink.vue';
export { default as BreadcrumbList } from './BreadcrumbList.vue';
export { default as BreadcrumbPage } from './BreadcrumbPage.vue';
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue';

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import type { ButtonVariants, ButtonVariantSize } from './types';
import { cn } from '@vben-core/shared/utils';
import { Primitive, type PrimitiveProps } from 'radix-vue';
import { buttonVariants } from './button';
interface Props extends PrimitiveProps {
class?: any;
size?: ButtonVariantSize;
variant?: ButtonVariants;
}
const props = withDefaults(defineProps<Props>(), {
as: 'button',
class: '',
});
</script>
<template>
<Primitive
:as="as"
:as-child="asChild"
:class="cn(buttonVariants({ variant, size }), props.class)"
>
<slot></slot>
</Primitive>
</template>

View File

@@ -0,0 +1,34 @@
import { cva } from 'class-variance-authority';
export const buttonVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap 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:cursor-not-allowed disabled:opacity-50',
{
defaultVariants: {
size: 'default',
variant: 'default',
},
variants: {
size: {
default: 'h-9 px-4 py-2',
icon: 'h-8 w-8 rounded-sm px-1 text-lg',
lg: 'h-10 rounded-md px-8',
sm: 'h-8 rounded-md px-3 text-xs',
xs: 'h-8 w-8 rounded-sm px-1 text-xs',
},
variant: {
default:
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
destructive:
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive-hover',
ghost: 'hover:bg-accent hover:text-accent-foreground',
heavy: 'hover:bg-heavy hover:text-heavy-foreground',
icon: 'hover:bg-accent hover:text-accent-foreground text-foreground/80',
link: 'text-primary underline-offset-4 hover:underline',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
},
},
},
);

View File

@@ -0,0 +1,5 @@
export * from './button';
export { default as Button } from './Button.vue';
export type * from './types';

View File

@@ -0,0 +1,20 @@
export type ButtonVariantSize =
| 'default'
| 'icon'
| 'lg'
| 'sm'
| 'xs'
| null
| undefined;
export type ButtonVariants =
| 'default'
| 'destructive'
| 'ghost'
| 'heavy'
| 'icon'
| 'link'
| 'outline'
| 'secondary'
| null
| undefined;

View File

@@ -0,0 +1,20 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div
:class="
cn(
'bg-card text-card-foreground border-border rounded-xl border',
props.class,
)
"
>
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div :class="cn('p-6 pt-0', props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<p :class="cn('text-muted-foreground text-sm', props.class)">
<slot></slot>
</p>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div :class="cn('flex items-center p-6 pt-0', props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div :class="cn('flex flex-col gap-y-1.5 p-5', props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<h3 :class="cn('font-semibold leading-none tracking-tight', props.class)">
<slot></slot>
</h3>
</template>

View File

@@ -0,0 +1,6 @@
export { default as Card } from './Card.vue';
export { default as CardContent } from './CardContent.vue';
export { default as CardDescription } from './CardDescription.vue';
export { default as CardFooter } from './CardFooter.vue';
export { default as CardHeader } from './CardHeader.vue';
export { default as CardTitle } from './CardTitle.vue';

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue';
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Check } from 'lucide-vue-next';
import {
CheckboxIndicator,
CheckboxRoot,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & CheckboxRootProps>();
const emits = defineEmits<CheckboxRootEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<CheckboxRoot
v-bind="forwarded"
:class="
cn(
'focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground border-border peer h-4 w-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
props.class,
)
"
>
<CheckboxIndicator
class="flex h-full w-full items-center justify-center text-current"
>
<slot>
<Check class="h-4 w-4" />
</slot>
</CheckboxIndicator>
</CheckboxRoot>
</template>

View File

@@ -0,0 +1 @@
export { default as Checkbox } from './Checkbox.vue';

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import type { ContextMenuRootEmits, ContextMenuRootProps } from 'radix-vue';
import { ContextMenuRoot, useForwardPropsEmits } from 'radix-vue';
const props = withDefaults(defineProps<ContextMenuRootProps>(), {
modal: false,
});
const emits = defineEmits<ContextMenuRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<ContextMenuRoot v-bind="forwarded">
<slot></slot>
</ContextMenuRoot>
</template>

View File

@@ -0,0 +1,44 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Check } from 'lucide-vue-next';
import {
ContextMenuCheckboxItem,
type ContextMenuCheckboxItemEmits,
type ContextMenuCheckboxItemProps,
ContextMenuItemIndicator,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & ContextMenuCheckboxItemProps>();
const emits = defineEmits<ContextMenuCheckboxItemEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<ContextMenuCheckboxItem
v-bind="forwarded"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)
"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator>
<Check class="h-4 w-4" />
</ContextMenuItemIndicator>
</span>
<slot></slot>
</ContextMenuCheckboxItem>
</template>

View File

@@ -0,0 +1,40 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
ContextMenuContent,
type ContextMenuContentEmits,
type ContextMenuContentProps,
ContextMenuPortal,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & ContextMenuContentProps>();
const emits = defineEmits<ContextMenuContentEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<ContextMenuPortal>
<ContextMenuContent
v-bind="forwarded"
:class="
cn(
'bg-popover text-popover-foreground 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 border-border z-[1000] min-w-32 overflow-hidden rounded-md border p-1 shadow-md',
props.class,
)
"
>
<slot></slot>
</ContextMenuContent>
</ContextMenuPortal>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ContextMenuGroup, type ContextMenuGroupProps } from 'radix-vue';
const props = defineProps<ContextMenuGroupProps>();
</script>
<template>
<ContextMenuGroup v-bind="props">
<slot></slot>
</ContextMenuGroup>
</template>

View File

@@ -0,0 +1,40 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
ContextMenuItem,
type ContextMenuItemEmits,
type ContextMenuItemProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<
{ class?: any; inset?: boolean } & ContextMenuItemProps
>();
const emits = defineEmits<ContextMenuItemEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<ContextMenuItem
v-bind="forwarded"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
props.class,
)
"
>
<slot></slot>
</ContextMenuItem>
</template>

View File

@@ -0,0 +1,32 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue';
const props = defineProps<
{ class?: any; inset?: boolean } & ContextMenuLabelProps
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<ContextMenuLabel
v-bind="delegatedProps"
:class="
cn(
'text-foreground px-2 py-1.5 text-sm font-semibold',
inset && 'pl-8',
props.class,
)
"
>
<slot></slot>
</ContextMenuLabel>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ContextMenuPortal, type ContextMenuPortalProps } from 'radix-vue';
const props = defineProps<ContextMenuPortalProps>();
</script>
<template>
<ContextMenuPortal v-bind="props">
<slot></slot>
</ContextMenuPortal>
</template>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
ContextMenuRadioGroup,
type ContextMenuRadioGroupEmits,
type ContextMenuRadioGroupProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<ContextMenuRadioGroupProps>();
const emits = defineEmits<ContextMenuRadioGroupEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<ContextMenuRadioGroup v-bind="forwarded">
<slot></slot>
</ContextMenuRadioGroup>
</template>

View File

@@ -0,0 +1,44 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Circle } from 'lucide-vue-next';
import {
ContextMenuItemIndicator,
ContextMenuRadioItem,
type ContextMenuRadioItemEmits,
type ContextMenuRadioItemProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & ContextMenuRadioItemProps>();
const emits = defineEmits<ContextMenuRadioItemEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<ContextMenuRadioItem
v-bind="forwarded"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)
"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator>
<Circle class="h-2 w-2 fill-current" />
</ContextMenuItemIndicator>
</span>
<slot></slot>
</ContextMenuRadioItem>
</template>

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
ContextMenuSeparator,
type ContextMenuSeparatorProps,
} from 'radix-vue';
const props = defineProps<{ class?: any } & ContextMenuSeparatorProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<ContextMenuSeparator
v-bind="delegatedProps"
:class="cn('bg-border -mx-1 my-1 h-px', props.class)"
/>
</template>

View File

@@ -0,0 +1,17 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<span
:class="
cn('text-muted-foreground ml-auto text-xs tracking-widest', props.class)
"
>
<slot></slot>
</span>
</template>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
ContextMenuSub,
type ContextMenuSubEmits,
type ContextMenuSubProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<ContextMenuSubProps>();
const emits = defineEmits<ContextMenuSubEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<ContextMenuSub v-bind="forwarded">
<slot></slot>
</ContextMenuSub>
</template>

View File

@@ -0,0 +1,37 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
ContextMenuSubContent,
type DropdownMenuSubContentEmits,
type DropdownMenuSubContentProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DropdownMenuSubContentProps>();
const emits = defineEmits<DropdownMenuSubContentEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<ContextMenuSubContent
v-bind="forwarded"
:class="
cn(
'bg-popover text-popover-foreground 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 border-border z-50 min-w-32 overflow-hidden rounded-md border p-1 shadow-lg',
props.class,
)
"
>
<slot></slot>
</ContextMenuSubContent>
</template>

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ChevronRight } from 'lucide-vue-next';
import {
ContextMenuSubTrigger,
type ContextMenuSubTriggerProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<
{
class?: any;
inset?: boolean;
} & ContextMenuSubTriggerProps
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<ContextMenuSubTrigger
v-bind="forwardedProps"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
inset && 'pl-8',
props.class,
)
"
>
<slot></slot>
<ChevronRight class="ml-auto h-4 w-4" />
</ContextMenuSubTrigger>
</template>

View File

@@ -0,0 +1,17 @@
<script setup lang="ts">
import {
ContextMenuTrigger,
type ContextMenuTriggerProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<ContextMenuTriggerProps>();
const forwardedProps = useForwardProps(props);
</script>
<template>
<ContextMenuTrigger v-bind="forwardedProps">
<slot></slot>
</ContextMenuTrigger>
</template>

View File

@@ -0,0 +1,14 @@
export { default as ContextMenu } from './ContextMenu.vue';
export { default as ContextMenuCheckboxItem } from './ContextMenuCheckboxItem.vue';
export { default as ContextMenuContent } from './ContextMenuContent.vue';
export { default as ContextMenuGroup } from './ContextMenuGroup.vue';
export { default as ContextMenuItem } from './ContextMenuItem.vue';
export { default as ContextMenuLabel } from './ContextMenuLabel.vue';
export { default as ContextMenuRadioGroup } from './ContextMenuRadioGroup.vue';
export { default as ContextMenuRadioItem } from './ContextMenuRadioItem.vue';
export { default as ContextMenuSeparator } from './ContextMenuSeparator.vue';
export { default as ContextMenuShortcut } from './ContextMenuShortcut.vue';
export { default as ContextMenuSub } from './ContextMenuSub.vue';
export { default as ContextMenuSubContent } from './ContextMenuSubContent.vue';
export { default as ContextMenuSubTrigger } from './ContextMenuSubTrigger.vue';
export { default as ContextMenuTrigger } from './ContextMenuTrigger.vue';

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
DialogRoot,
type DialogRootEmits,
type DialogRootProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<DialogRootProps>();
const emits = defineEmits<DialogRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<DialogRoot v-bind="forwarded">
<slot></slot>
</DialogRoot>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { DialogClose, type DialogCloseProps } from 'radix-vue';
const props = defineProps<DialogCloseProps>();
</script>
<template>
<DialogClose v-bind="props">
<slot></slot>
</DialogClose>
</template>

View File

@@ -0,0 +1,84 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { X } from 'lucide-vue-next';
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue';
import DialogOverlay from './DialogOverlay.vue';
const props = withDefaults(
defineProps<
{
class?: any;
closeClass?: any;
modal?: boolean;
open?: boolean;
showClose?: boolean;
} & DialogContentProps
>(),
{ showClose: true },
);
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
const delegatedProps = computed(() => {
const {
class: _,
modal: _modal,
open: _open,
showClose: __,
...delegated
} = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
const contentRef = ref<InstanceType<typeof DialogContent> | null>(null);
defineExpose({
getContentRef: () => contentRef.value,
});
</script>
<template>
<DialogPortal>
<Transition name="fade">
<DialogOverlay v-if="open && modal" @click="() => emits('close')" />
</Transition>
<DialogContent
ref="contentRef"
v-bind="forwarded"
:class="
cn(
'bg-background 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-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-top-[48%] fixed z-[1000] w-full p-6 shadow-lg outline-none sm:rounded-xl',
props.class,
)
"
>
<slot></slot>
<DialogClose
v-if="showClose"
:class="
cn(
'data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:bg-accent hover:text-accent-foreground text-foreground/80 flex-center absolute right-3 top-3 h-6 w-6 rounded-full px-1 text-lg opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none',
props.closeClass,
)
"
@click="() => emits('close')"
>
<X class="h-4 w-4" />
</DialogClose>
</DialogContent>
</DialogPortal>
</template>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DialogDescription,
type DialogDescriptionProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DialogDescriptionProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<DialogDescription
v-bind="forwardedProps"
:class="cn('text-muted-foreground text-sm', props.class)"
>
<slot></slot>
</DialogDescription>
</template>

View File

@@ -0,0 +1,18 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{ class?: any }>();
</script>
<template>
<div
:class="
cn(
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
props.class,
)
"
>
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,15 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div
:class="cn('flex flex-col gap-y-1.5 text-center sm:text-left', props.class)"
>
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,14 @@
<script setup lang="ts">
import { inject } from 'vue';
import { useScrollLock } from '@vben-core/composables';
useScrollLock();
const id = inject('DISMISSABLE_MODAL_ID');
</script>
<template>
<div
:data-dismissable-modal="id"
class="bg-overlay fixed inset-0 z-[1000]"
></div>
</template>

View File

@@ -0,0 +1,66 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { X } from 'lucide-vue-next';
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DialogContentProps>();
const emits = defineEmits<DialogContentEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DialogPortal>
<DialogOverlay
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 border-border fixed inset-0 z-[1000] grid place-items-center overflow-y-auto border bg-black/80"
>
<DialogContent
:class="
cn(
'border-border bg-background relative z-50 my-8 grid w-full max-w-lg gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
props.class,
)
"
v-bind="forwarded"
@pointer-down-outside="
(event) => {
const originalEvent = event.detail.originalEvent;
const target = originalEvent.target as HTMLElement;
if (
originalEvent.offsetX > target.clientWidth ||
originalEvent.offsetY > target.clientHeight
) {
event.preventDefault();
}
}
"
>
<slot></slot>
<DialogClose
class="hover:bg-secondary absolute right-4 top-4 rounded-md p-0.5 transition-colors"
>
<X class="h-4 w-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContent>
</DialogOverlay>
</DialogPortal>
</template>

View File

@@ -0,0 +1,28 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue';
const props = defineProps<{ class?: any } & DialogTitleProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<DialogTitle
v-bind="forwardedProps"
:class="
cn('text-lg font-semibold leading-none tracking-tight', props.class)
"
>
<slot></slot>
</DialogTitle>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { DialogTrigger, type DialogTriggerProps } from 'radix-vue';
const props = defineProps<DialogTriggerProps>();
</script>
<template>
<DialogTrigger v-bind="props">
<slot></slot>
</DialogTrigger>
</template>

View File

@@ -0,0 +1,9 @@
export { default as Dialog } from './Dialog.vue';
export { default as DialogClose } from './DialogClose.vue';
export { default as DialogContent } from './DialogContent.vue';
export { default as DialogDescription } from './DialogDescription.vue';
export { default as DialogFooter } from './DialogFooter.vue';
export { default as DialogHeader } from './DialogHeader.vue';
export { default as DialogScrollContent } from './DialogScrollContent.vue';
export { default as DialogTitle } from './DialogTitle.vue';
export { default as DialogTrigger } from './DialogTrigger.vue';

View File

@@ -0,0 +1,21 @@
<script setup lang="ts">
import {
DropdownMenuRoot,
type DropdownMenuRootEmits,
type DropdownMenuRootProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = withDefaults(defineProps<DropdownMenuRootProps>(), {
modal: false,
});
const emits = defineEmits<DropdownMenuRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<DropdownMenuRoot v-bind="forwarded">
<slot></slot>
</DropdownMenuRoot>
</template>

View File

@@ -0,0 +1,44 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Check } from 'lucide-vue-next';
import {
DropdownMenuCheckboxItem,
type DropdownMenuCheckboxItemEmits,
type DropdownMenuCheckboxItemProps,
DropdownMenuItemIndicator,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DropdownMenuCheckboxItemProps>();
const emits = defineEmits<DropdownMenuCheckboxItemEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DropdownMenuCheckboxItem
v-bind="forwarded"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)
"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<Check class="h-4 w-4" />
</DropdownMenuItemIndicator>
</span>
<slot></slot>
</DropdownMenuCheckboxItem>
</template>

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DropdownMenuContent,
type DropdownMenuContentEmits,
type DropdownMenuContentProps,
DropdownMenuPortal,
useForwardPropsEmits,
} from 'radix-vue';
const props = withDefaults(
defineProps<{ class?: any } & DropdownMenuContentProps>(),
{
sideOffset: 4,
},
);
const emits = defineEmits<DropdownMenuContentEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DropdownMenuPortal>
<DropdownMenuContent
v-bind="forwarded"
:class="
cn(
'bg-popover text-popover-foreground 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 border-border z-[1000] min-w-32 overflow-hidden rounded-md border p-1 shadow-md',
props.class,
)
"
>
<slot></slot>
</DropdownMenuContent>
</DropdownMenuPortal>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { DropdownMenuGroup, type DropdownMenuGroupProps } from 'radix-vue';
const props = defineProps<DropdownMenuGroupProps>();
</script>
<template>
<DropdownMenuGroup v-bind="props">
<slot></slot>
</DropdownMenuGroup>
</template>

View File

@@ -0,0 +1,38 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DropdownMenuItem,
type DropdownMenuItemProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<
{ class?: any; inset?: boolean } & DropdownMenuItemProps
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<DropdownMenuItem
v-bind="forwardedProps"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
props.class,
)
"
>
<slot></slot>
</DropdownMenuItem>
</template>

View File

@@ -0,0 +1,34 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DropdownMenuLabel,
type DropdownMenuLabelProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<
{ class?: any; inset?: boolean } & DropdownMenuLabelProps
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<DropdownMenuLabel
v-bind="forwardedProps"
:class="
cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)
"
>
<slot></slot>
</DropdownMenuLabel>
</template>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
DropdownMenuRadioGroup,
type DropdownMenuRadioGroupEmits,
type DropdownMenuRadioGroupProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<DropdownMenuRadioGroupProps>();
const emits = defineEmits<DropdownMenuRadioGroupEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<DropdownMenuRadioGroup v-bind="forwarded">
<slot></slot>
</DropdownMenuRadioGroup>
</template>

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Circle } from 'lucide-vue-next';
import {
DropdownMenuItemIndicator,
DropdownMenuRadioItem,
type DropdownMenuRadioItemEmits,
type DropdownMenuRadioItemProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DropdownMenuRadioItemProps>();
const emits = defineEmits<DropdownMenuRadioItemEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DropdownMenuRadioItem
v-bind="forwarded"
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)
"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<Circle class="h-2 w-2 fill-current" />
</DropdownMenuItemIndicator>
</span>
<slot></slot>
</DropdownMenuRadioItem>
</template>

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DropdownMenuSeparator,
type DropdownMenuSeparatorProps,
} from 'radix-vue';
const props = defineProps<
{
class?: any;
} & DropdownMenuSeparatorProps
>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<DropdownMenuSeparator
v-bind="delegatedProps"
:class="cn('bg-border -mx-1 my-1 h-px', props.class)"
/>
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<span :class="cn('ml-auto text-xs tracking-widest opacity-60', props.class)">
<slot></slot>
</span>
</template>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
DropdownMenuSub,
type DropdownMenuSubEmits,
type DropdownMenuSubProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<DropdownMenuSubProps>();
const emits = defineEmits<DropdownMenuSubEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<DropdownMenuSub v-bind="forwarded">
<slot></slot>
</DropdownMenuSub>
</template>

View File

@@ -0,0 +1,37 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
DropdownMenuSubContent,
type DropdownMenuSubContentEmits,
type DropdownMenuSubContentProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DropdownMenuSubContentProps>();
const emits = defineEmits<DropdownMenuSubContentEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<DropdownMenuSubContent
v-bind="forwarded"
:class="
cn(
'bg-popover text-popover-foreground 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 border-border z-50 min-w-32 overflow-hidden rounded-md border p-1 shadow-lg',
props.class,
)
"
>
<slot></slot>
</DropdownMenuSubContent>
</template>

View File

@@ -0,0 +1,37 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ChevronRight } from 'lucide-vue-next';
import {
DropdownMenuSubTrigger,
type DropdownMenuSubTriggerProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<{ class?: any } & DropdownMenuSubTriggerProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<DropdownMenuSubTrigger
v-bind="forwardedProps"
:class="
cn(
'focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
props.class,
)
"
>
<slot></slot>
<ChevronRight class="ml-auto h-4 w-4" />
</DropdownMenuSubTrigger>
</template>

View File

@@ -0,0 +1,17 @@
<script setup lang="ts">
import {
DropdownMenuTrigger,
type DropdownMenuTriggerProps,
useForwardProps,
} from 'radix-vue';
const props = defineProps<DropdownMenuTriggerProps>();
const forwardedProps = useForwardProps(props);
</script>
<template>
<DropdownMenuTrigger class="outline-none" v-bind="forwardedProps">
<slot></slot>
</DropdownMenuTrigger>
</template>

View File

@@ -0,0 +1,16 @@
export { default as DropdownMenu } from './DropdownMenu.vue';
export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue';
export { default as DropdownMenuContent } from './DropdownMenuContent.vue';
export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue';
export { default as DropdownMenuItem } from './DropdownMenuItem.vue';
export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue';
export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue';
export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue';
export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue';
export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue';
export { default as DropdownMenuSub } from './DropdownMenuSub.vue';
export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue';
export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue';
export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue';
export { DropdownMenuPortal } from 'radix-vue';

View File

@@ -0,0 +1,19 @@
<script lang="ts" setup>
import { Slot } from 'radix-vue';
import { useFormField } from './useFormField';
const { error, formDescriptionId, formItemId, formMessageId } = useFormField();
</script>
<template>
<Slot
:id="formItemId"
:aria-describedby="
!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`
"
:aria-invalid="!!error"
>
<slot></slot>
</Slot>
</template>

View File

@@ -0,0 +1,20 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { useFormField } from './useFormField';
const props = defineProps<{
class?: any;
}>();
const { formDescriptionId } = useFormField();
</script>
<template>
<p
:id="formDescriptionId"
:class="cn('text-muted-foreground text-sm', props.class)"
>
<slot></slot>
</p>
</template>

View File

@@ -0,0 +1,20 @@
<script lang="ts" setup>
import { provide, useId } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys';
const props = defineProps<{
class?: any;
}>();
const id = useId() as string;
provide(FORM_ITEM_INJECTION_KEY, id);
</script>
<template>
<div :class="cn(props.class)">
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,18 @@
<script lang="ts" setup>
import type { LabelProps } from 'radix-vue';
import { cn } from '@vben-core/shared/utils';
import { Label } from '../label';
import { useFormField } from './useFormField';
const props = defineProps<{ class?: any } & LabelProps>();
const { formItemId } = useFormField();
</script>
<template>
<Label :class="cn(props.class)" :for="formItemId">
<slot></slot>
</Label>
</template>

View File

@@ -0,0 +1,18 @@
<script lang="ts" setup>
import { toValue } from 'vue';
import { ErrorMessage } from 'vee-validate';
import { useFormField } from './useFormField';
const { formMessageId, name } = useFormField();
</script>
<template>
<ErrorMessage
:id="formMessageId"
:name="toValue(name)"
as="p"
class="text-destructive text-[0.8rem]"
/>
</template>

View File

@@ -0,0 +1,11 @@
export { default as FormControl } from './FormControl.vue';
export { default as FormDescription } from './FormDescription.vue';
export { default as FormItem } from './FormItem.vue';
export { default as FormLabel } from './FormLabel.vue';
export { default as FormMessage } from './FormMessage.vue';
export { FORM_ITEM_INJECTION_KEY } from './injectionKeys';
export {
Field as FormField,
FieldArray as FormFieldArray,
Form,
} from 'vee-validate';

View File

@@ -0,0 +1,4 @@
import type { InjectionKey } from 'vue';
// eslint-disable-next-line symbol-description
export const FORM_ITEM_INJECTION_KEY = Symbol() as InjectionKey<string>;

View File

@@ -0,0 +1,38 @@
import { inject } from 'vue';
import {
FieldContextKey,
useFieldError,
useIsFieldDirty,
useIsFieldTouched,
useIsFieldValid,
} from 'vee-validate';
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys';
export function useFormField() {
const fieldContext = inject(FieldContextKey);
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY);
if (!fieldContext)
throw new Error('useFormField should be used within <FormField>');
const { name } = fieldContext;
const id = fieldItemContext;
const fieldState = {
error: useFieldError(name),
isDirty: useIsFieldDirty(name),
isTouched: useIsFieldTouched(name),
valid: useIsFieldValid(name),
};
return {
formDescriptionId: `${id}-form-item-description`,
formItemId: `${id}-form-item`,
formMessageId: `${id}-form-item-message`,
id,
name,
...fieldState,
};
}

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import {
HoverCardRoot,
type HoverCardRootEmits,
type HoverCardRootProps,
useForwardPropsEmits,
} from 'radix-vue';
const props = defineProps<HoverCardRootProps>();
const emits = defineEmits<HoverCardRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>
<template>
<HoverCardRoot v-bind="forwarded">
<slot></slot>
</HoverCardRoot>
</template>

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import {
HoverCardContent,
type HoverCardContentProps,
HoverCardPortal,
useForwardProps,
} from 'radix-vue';
const props = withDefaults(
defineProps<{ class?: any } & HoverCardContentProps>(),
{
sideOffset: 4,
},
);
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwardedProps = useForwardProps(delegatedProps);
</script>
<template>
<HoverCardPortal>
<HoverCardContent
v-bind="forwardedProps"
:class="
cn(
'bg-popover text-popover-foreground 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 border-border z-[1000] w-64 rounded-md border p-4 shadow-md outline-none',
props.class,
)
"
>
<slot></slot>
</HoverCardContent>
</HoverCardPortal>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { HoverCardTrigger, type HoverCardTriggerProps } from 'radix-vue';
const props = defineProps<HoverCardTriggerProps>();
</script>
<template>
<HoverCardTrigger v-bind="props">
<slot></slot>
</HoverCardTrigger>
</template>

View File

@@ -0,0 +1,3 @@
export { default as HoverCard } from './HoverCard.vue';
export { default as HoverCardContent } from './HoverCardContent.vue';
export { default as HoverCardTrigger } from './HoverCardTrigger.vue';

View File

@@ -0,0 +1,29 @@
export * from './accordion';
export * from './avatar';
export * from './badge';
export * from './breadcrumb';
export * from './button';
export * from './card';
export * from './checkbox';
export * from './dialog';
export * from './dropdown-menu';
export * from './form';
export * from './hover-card';
export * from './input';
export * from './label';
export * from './number-field';
export * from './pagination';
export * from './pin-input';
export * from './popover';
export * from './radio-group';
export * from './scroll-area';
export * from './select';
export * from './separator';
export * from './sheet';
export * from './switch';
export * from './tabs';
export * from './textarea';
export * from './toast';
export * from './toggle';
export * from './toggle-group';
export * from './tooltip';

View File

@@ -0,0 +1,32 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
import { useVModel } from '@vueuse/core';
const props = defineProps<{
class?: any;
defaultValue?: number | string;
modelValue?: number | string;
}>();
const emits = defineEmits<{
(e: 'update:modelValue', payload: number | string): void;
}>();
const modelValue = useVModel(props, 'modelValue', emits, {
defaultValue: props.defaultValue,
passive: true,
});
</script>
<template>
<input
v-model="modelValue"
:class="
cn(
'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
props.class,
)
"
/>
</template>

View File

@@ -0,0 +1 @@
export { default as Input } from './Input.vue';

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Label, type LabelProps } from 'radix-vue';
const props = defineProps<{ class?: any } & LabelProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<Label
v-bind="delegatedProps"
:class="
cn(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
props.class,
)
"
>
<slot></slot>
</Label>
</template>

View File

@@ -0,0 +1 @@
export { default as Label } from './Label.vue';

View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
import type { NumberFieldRootEmits, NumberFieldRootProps } from 'radix-vue';
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue';
const props = defineProps<{ class?: any } & NumberFieldRootProps>();
const emits = defineEmits<NumberFieldRootEmits>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
<template>
<NumberFieldRoot v-bind="forwarded" :class="cn('grid gap-1.5', props.class)">
<slot></slot>
</NumberFieldRoot>
</template>

View File

@@ -0,0 +1,20 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
const props = defineProps<{
class?: any;
}>();
</script>
<template>
<div
:class="
cn(
'relative [&>[data-slot=input]]:has-[[data-slot=decrement]]:pl-5 [&>[data-slot=input]]:has-[[data-slot=increment]]:pr-5',
props.class,
)
"
>
<slot></slot>
</div>
</template>

View File

@@ -0,0 +1,37 @@
<script setup lang="ts">
import type { NumberFieldDecrementProps } from 'radix-vue';
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Minus } from 'lucide-vue-next';
import { NumberFieldDecrement, useForwardProps } from 'radix-vue';
const props = defineProps<{ class?: any } & NumberFieldDecrementProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardProps(delegatedProps);
</script>
<template>
<NumberFieldDecrement
data-slot="decrement"
v-bind="forwarded"
:class="
cn(
'absolute left-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20',
props.class,
)
"
>
<slot>
<Minus class="h-4 w-4" />
</slot>
</NumberFieldDecrement>
</template>

View File

@@ -0,0 +1,37 @@
<script setup lang="ts">
import type { NumberFieldIncrementProps } from 'radix-vue';
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Plus } from 'lucide-vue-next';
import { NumberFieldIncrement, useForwardProps } from 'radix-vue';
const props = defineProps<{ class?: any } & NumberFieldIncrementProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
const forwarded = useForwardProps(delegatedProps);
</script>
<template>
<NumberFieldIncrement
data-slot="increment"
v-bind="forwarded"
:class="
cn(
'absolute right-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20',
props.class,
)
"
>
<slot>
<Plus class="h-4 w-4" />
</slot>
</NumberFieldIncrement>
</template>

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { cn } from '@vben-core/shared/utils';
import { NumberFieldInput } from 'radix-vue';
</script>
<template>
<NumberFieldInput
:class="
cn(
'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent py-1 text-center text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50',
)
"
data-slot="input"
/>
</template>

View File

@@ -0,0 +1,5 @@
export { default as NumberField } from './NumberField.vue';
export { default as NumberFieldContent } from './NumberFieldContent.vue';
export { default as NumberFieldDecrement } from './NumberFieldDecrement.vue';
export { default as NumberFieldIncrement } from './NumberFieldIncrement.vue';
export { default as NumberFieldInput } from './NumberFieldInput.vue';

View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { MoreHorizontal } from 'lucide-vue-next';
import { PaginationEllipsis, type PaginationEllipsisProps } from 'radix-vue';
const props = defineProps<{ class?: any } & PaginationEllipsisProps>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>
<template>
<PaginationEllipsis
v-bind="delegatedProps"
:class="cn('flex size-8 items-center justify-center', props.class)"
>
<slot>
<MoreHorizontal class="size-4" />
</slot>
</PaginationEllipsis>
</template>

Some files were not shown because too many files have changed in this diff Show More