feat: add swap component (#4149)
This commit is contained in:
@@ -22,6 +22,7 @@ export * from './scrollbar';
|
||||
export * from './segmented';
|
||||
export * from './sheet';
|
||||
export * from './spinner';
|
||||
export * from './swap';
|
||||
export * from './tooltip';
|
||||
export * from './ui/alert-dialog';
|
||||
export * from './ui/avatar';
|
||||
|
@@ -1 +1 @@
|
||||
export { default as Spinner } from './spinner.vue';
|
||||
export { default as VbenSpinner } from './spinner.vue';
|
||||
|
@@ -0,0 +1 @@
|
||||
export { default as VbenSwap } from './swap.vue';
|
126
packages/@core/ui-kit/shadcn-ui/src/components/swap/swap.vue
Normal file
126
packages/@core/ui-kit/shadcn-ui/src/components/swap/swap.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
/**
|
||||
* @zh_CN 交换模式
|
||||
*/
|
||||
mode?: 'flip' | 'rotate';
|
||||
/**
|
||||
* @zh_CN 开启时的样式
|
||||
*/
|
||||
offClass?: string;
|
||||
/**
|
||||
* @zh_CN 关闭时的样式
|
||||
*/
|
||||
onClass?: string;
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'Swap',
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
mode: 'rotate',
|
||||
onClass: '',
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label
|
||||
:class="{
|
||||
'swap-flip': mode === 'flip',
|
||||
'swap-rotate': mode === 'rotate',
|
||||
}"
|
||||
class="swap"
|
||||
>
|
||||
<input class="hidden" type="checkbox" />
|
||||
|
||||
<div :class="onClass" class="swap-on">
|
||||
<slot name="swap-on"></slot>
|
||||
</div>
|
||||
|
||||
<div :class="offClass" class="swap-off">
|
||||
<slot name="swap-off"></slot>
|
||||
</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.swap {
|
||||
@apply relative inline-grid cursor-pointer select-none place-content-center;
|
||||
}
|
||||
|
||||
.swap > * {
|
||||
@apply col-start-1 row-start-1 duration-300 ease-out;
|
||||
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.swap-rotate .swap-on,
|
||||
.swap-rotate .swap-indeterminate,
|
||||
.swap-rotate input:indeterminate ~ .swap-on {
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
.swap-rotate input:checked ~ .swap-off,
|
||||
.swap-active:where(.swap-rotate) .swap-off,
|
||||
.swap-rotate input:indeterminate ~ .swap-off {
|
||||
@apply -rotate-45;
|
||||
}
|
||||
|
||||
.swap-rotate input:checked ~ .swap-on,
|
||||
.swap-active:where(.swap-rotate) .swap-on,
|
||||
.swap-rotate input:indeterminate ~ .swap-indeterminate {
|
||||
@apply rotate-0;
|
||||
}
|
||||
|
||||
.swap-flip {
|
||||
transform-style: preserve-3d;
|
||||
perspective: 16em;
|
||||
}
|
||||
|
||||
.swap-flip .swap-on,
|
||||
.swap-flip .swap-indeterminate,
|
||||
.swap-flip input:indeterminate ~ .swap-on {
|
||||
@apply opacity-100;
|
||||
|
||||
transform: rotateY(180deg);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.swap-flip input:checked ~ .swap-off,
|
||||
.swap-active:where(.swap-flip) .swap-off,
|
||||
.swap-flip input:indeterminate ~ .swap-off {
|
||||
@apply opacity-100;
|
||||
|
||||
transform: rotateY(-180deg);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.swap-flip input:checked ~ .swap-on,
|
||||
.swap-active:where(.swap-flip) .swap-on,
|
||||
.swap-flip input:indeterminate ~ .swap-indeterminate {
|
||||
transform: rotateY(0deg);
|
||||
}
|
||||
|
||||
.swap input {
|
||||
@apply appearance-none;
|
||||
}
|
||||
|
||||
.swap .swap-on,
|
||||
.swap .swap-indeterminate,
|
||||
.swap input:indeterminate ~ .swap-on {
|
||||
@apply opacity-0;
|
||||
}
|
||||
|
||||
.swap input:checked ~ .swap-off,
|
||||
.swap-active .swap-off,
|
||||
.swap input:indeterminate ~ .swap-off {
|
||||
@apply opacity-0;
|
||||
}
|
||||
|
||||
.swap input:checked ~ .swap-on,
|
||||
.swap-active .swap-on,
|
||||
.swap input:indeterminate ~ .swap-indeterminate {
|
||||
@apply opacity-100;
|
||||
}
|
||||
</style>
|
@@ -30,7 +30,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
<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 bg-black/80"
|
||||
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="
|
||||
|
@@ -9,10 +9,10 @@ export const sheetVariants = cva(
|
||||
variants: {
|
||||
side: {
|
||||
bottom:
|
||||
'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
||||
'inset-x-0 bottom-0 border-t border-border data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
||||
left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
|
||||
right:
|
||||
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
|
||||
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
|
||||
top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
|
||||
},
|
||||
},
|
||||
|
@@ -5,7 +5,7 @@ import type { HTMLAttributes } from 'vue';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
export const toastVariants = cva(
|
||||
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
|
||||
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border border-border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
|
||||
{
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
|
@@ -41,7 +41,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
:class="
|
||||
cn(
|
||||
'bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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] overflow-hidden rounded-sm px-4 py-2 text-xs shadow-md',
|
||||
'bg-accent text-accent-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 shadow-float z-[1000] overflow-hidden rounded-sm border px-4 py-2 text-xs',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
Reference in New Issue
Block a user