mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 08:36:19 +08:00
feat: add preset alert, confirm, prompt components that can be simple called (#5843)
* feat: add preset alert, confirm, prompt components that can be simple called * fix: type define
This commit is contained in:
@@ -3,7 +3,7 @@ import type { Component, PropType } from 'vue';
|
||||
|
||||
import { defineComponent, h } from 'vue';
|
||||
|
||||
import { isFunction, isObject } from '@vben-core/shared/utils';
|
||||
import { isFunction, isObject, isString } from '@vben-core/shared/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RenderContent',
|
||||
@@ -14,6 +14,10 @@ export default defineComponent({
|
||||
| undefined,
|
||||
type: [Object, String, Function],
|
||||
},
|
||||
renderBr: {
|
||||
default: false,
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(props, { attrs, slots }) {
|
||||
return () => {
|
||||
@@ -24,7 +28,20 @@ export default defineComponent({
|
||||
(isObject(props.content) || isFunction(props.content)) &&
|
||||
props.content !== null;
|
||||
if (!isComponent) {
|
||||
return props.content;
|
||||
if (props.renderBr && isString(props.content)) {
|
||||
const lines = props.content.split('\n');
|
||||
const result = [];
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
result.push(h('span', { key: i }, line));
|
||||
if (i < lines.length - 1) {
|
||||
result.push(h('br'));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return props.content;
|
||||
}
|
||||
}
|
||||
return h(props.content as never, {
|
||||
...attrs,
|
||||
|
@@ -0,0 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { AlertDialogEmits, AlertDialogProps } from 'radix-vue';
|
||||
|
||||
import { AlertDialogRoot, useForwardPropsEmits } from 'radix-vue';
|
||||
|
||||
const props = defineProps<AlertDialogProps>();
|
||||
const emits = defineEmits<AlertDialogEmits>();
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogRoot v-bind="forwarded">
|
||||
<slot></slot>
|
||||
</AlertDialogRoot>
|
||||
</template>
|
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { AlertDialogActionProps } from 'radix-vue';
|
||||
|
||||
import { AlertDialogAction } from 'radix-vue';
|
||||
|
||||
const props = defineProps<AlertDialogActionProps>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogAction v-bind="props">
|
||||
<slot></slot>
|
||||
</AlertDialogAction>
|
||||
</template>
|
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type { AlertDialogCancelProps } from 'radix-vue';
|
||||
|
||||
import { AlertDialogCancel } from 'radix-vue';
|
||||
|
||||
const props = defineProps<AlertDialogCancelProps>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogCancel v-bind="props">
|
||||
<slot></slot>
|
||||
</AlertDialogCancel>
|
||||
</template>
|
@@ -0,0 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
AlertDialogContentEmits,
|
||||
AlertDialogContentProps,
|
||||
} from 'radix-vue';
|
||||
|
||||
import type { ClassType } from '@vben-core/typings';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import {
|
||||
AlertDialogContent,
|
||||
AlertDialogPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue';
|
||||
|
||||
import AlertDialogOverlay from './AlertDialogOverlay.vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<
|
||||
AlertDialogContentProps & {
|
||||
centered?: boolean;
|
||||
class?: ClassType;
|
||||
modal?: boolean;
|
||||
open?: boolean;
|
||||
overlayBlur?: number;
|
||||
zIndex?: number;
|
||||
}
|
||||
>(),
|
||||
{ modal: true },
|
||||
);
|
||||
const emits = defineEmits<
|
||||
AlertDialogContentEmits & { close: []; closed: []; opened: [] }
|
||||
>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, modal: _modal, open: _open, ...delegated } = props;
|
||||
|
||||
return delegated;
|
||||
});
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
|
||||
const contentRef = ref<InstanceType<typeof AlertDialogContent> | null>(null);
|
||||
function onAnimationEnd(event: AnimationEvent) {
|
||||
// 只有在 contentRef 的动画结束时才触发 opened/closed 事件
|
||||
if (event.target === contentRef.value?.$el) {
|
||||
if (props.open) {
|
||||
emits('opened');
|
||||
} else {
|
||||
emits('closed');
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
getContentRef: () => contentRef.value,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogPortal>
|
||||
<Transition name="fade">
|
||||
<AlertDialogOverlay
|
||||
v-if="open && modal"
|
||||
:style="{
|
||||
...(zIndex ? { zIndex } : {}),
|
||||
position: 'fixed',
|
||||
backdropFilter:
|
||||
overlayBlur && overlayBlur > 0 ? `blur(${overlayBlur}px)` : 'none',
|
||||
}"
|
||||
@click="() => emits('close')"
|
||||
/>
|
||||
</Transition>
|
||||
<AlertDialogContent
|
||||
ref="contentRef"
|
||||
:style="{ ...(zIndex ? { zIndex } : {}), position: 'fixed' }"
|
||||
@animationend="onAnimationEnd"
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
cn(
|
||||
'z-popup 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%] w-full p-6 shadow-lg outline-none sm:rounded-xl',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot></slot>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</template>
|
@@ -0,0 +1,28 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AlertDialogDescriptionProps } from 'radix-vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { AlertDialogDescription, useForwardProps } from 'radix-vue';
|
||||
|
||||
const props = defineProps<AlertDialogDescriptionProps & { class?: any }>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
|
||||
return delegated;
|
||||
});
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogDescription
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('text-muted-foreground text-sm', props.class)"
|
||||
>
|
||||
<slot></slot>
|
||||
</AlertDialogDescription>
|
||||
</template>
|
@@ -0,0 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { useScrollLock } from '@vben-core/composables';
|
||||
|
||||
useScrollLock();
|
||||
</script>
|
||||
<template>
|
||||
<div class="bg-overlay z-popup inset-0"></div>
|
||||
</template>
|
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import type { AlertDialogTitleProps } from 'radix-vue';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { AlertDialogTitle, useForwardProps } from 'radix-vue';
|
||||
|
||||
const props = defineProps<AlertDialogTitleProps & { class?: any }>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
|
||||
return delegated;
|
||||
});
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogTitle
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn('text-lg font-semibold leading-none tracking-tight', props.class)
|
||||
"
|
||||
>
|
||||
<slot></slot>
|
||||
</AlertDialogTitle>
|
||||
</template>
|
@@ -0,0 +1,6 @@
|
||||
export { default as AlertDialog } from './AlertDialog.vue';
|
||||
export { default as AlertDialogAction } from './AlertDialogAction.vue';
|
||||
export { default as AlertDialogCancel } from './AlertDialogCancel.vue';
|
||||
export { default as AlertDialogContent } from './AlertDialogContent.vue';
|
||||
export { default as AlertDialogDescription } from './AlertDialogDescription.vue';
|
||||
export { default as AlertDialogTitle } from './AlertDialogTitle.vue';
|
@@ -1,4 +1,5 @@
|
||||
export * from './accordion';
|
||||
export * from './alert-dialog';
|
||||
export * from './avatar';
|
||||
export * from './badge';
|
||||
export * from './breadcrumb';
|
||||
|
Reference in New Issue
Block a user