Skip to content

Commit

Permalink
feat: add support for setting uniqueId in Dialog to prevent duplicate…
Browse files Browse the repository at this point in the history
… creation

Signed-off-by: Ryan Wang <i@ryanc.cc>
  • Loading branch information
ruibaby committed Sep 30, 2024
1 parent 56804c9 commit 52bc650
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 56 deletions.
10 changes: 6 additions & 4 deletions ui/packages/components/src/components/dialog/Dialog.stories.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/vue3";

import { VDialog } from ".";
import { Dialog, VDialog } from ".";
import { VButton } from "../button";

const meta: Meta<typeof VDialog> = {
Expand All @@ -12,8 +12,11 @@ const meta: Meta<typeof VDialog> = {
height: 400,
setup() {
const showDialog = () => {
// @ts-ignore
args.visible = true;
Dialog.success({
title: "Hi",
// @ts-ignore
type: args.type,
});
};

return {
Expand All @@ -24,7 +27,6 @@ const meta: Meta<typeof VDialog> = {
template: `
<div style="height: 400px">
<VButton @click="showDialog" >点击显示Dialog</VButton>
<VDialog v-bind="args" @onCancel="args.visible = false" />
</div>
`,
}),
Expand Down
50 changes: 18 additions & 32 deletions ui/packages/components/src/components/dialog/Dialog.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script lang="ts" setup>
import type { Type as ButtonType } from "@/components/button/interface";
import type { Type } from "@/components/dialog/interface";
import type { DialogProps, Type } from "@/components/dialog/interface";
import { markRaw, ref, type Component, type Raw } from "vue";
import {
IconCheckboxCircle,
Expand All @@ -12,36 +11,22 @@ import {
import { VButton } from "../button";
import { VModal } from "../modal";
const props = withDefaults(
defineProps<{
type?: Type;
title?: string;
description?: string;
confirmText?: string;
confirmType?: ButtonType;
showCancel?: boolean;
cancelText?: string;
visible?: boolean;
onConfirm?: () => void;
onCancel?: () => void;
}>(),
{
type: "info",
title: "提示",
description: "",
confirmText: "确定",
confirmType: "primary",
showCancel: true,
cancelText: "取消",
visible: false,
onConfirm: () => {
return;
},
onCancel: () => {
return;
},
}
);
const props = withDefaults(defineProps<DialogProps>(), {
type: "info",
title: "提示",
description: "",
confirmText: "确定",
confirmType: "primary",
showCancel: true,
cancelText: "取消",
visible: false,
onConfirm: () => {
return;
},
onCancel: () => {
return;
},
});
const emit = defineEmits<{
(event: "update:visible", visible: boolean): void;
Expand Down Expand Up @@ -102,6 +87,7 @@ const handleClose = () => {
:visible="visible"
:width="450"
:layer-closable="true"
:data-unique-id="uniqueId"
@close="handleCancel()"
>
<div class="flex justify-between items-start py-2 mb-2">
Expand Down
43 changes: 30 additions & 13 deletions ui/packages/components/src/components/dialog/dialog-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,54 @@ const defaultProps: DialogProps = {
visible: false,
};

const DIALOG_CONTAINER_CLASS = ".dialog-container";
const MODAL_WRAPPER_CLASS = ".modal-wrapper";

function getOrCreateContainer() {
let container = document.body.querySelector(DIALOG_CONTAINER_CLASS);
if (!container) {
container = document.createElement("div");
container.className = "dialog-container";
document.body.appendChild(container);
}
return container;
}

const dialog: DialogEntry = (userProps: DialogProps) => {
const props = {
...defaultProps,
...userProps,
};

let container = document.body.querySelector(".dialog-container");
if (!container) {
container = document.createElement("div");
container.className = "dialog-container";
document.body.appendChild(container);
const container = getOrCreateContainer();

if (
props.uniqueId &&
container.querySelector(`[data-unique-id="${props.uniqueId}"]`)
) {
return;
}

const { vnode, container: hostContainer } = createVNodeComponent(
DialogComponent,
props
);

if (hostContainer.firstElementChild) {
hostContainer.firstElementChild &&
container.appendChild(hostContainer.firstElementChild);
}

if (vnode.component?.props) {
vnode.component.props.visible = true;
}
vnode.component?.props && (vnode.component.props.visible = true);

if (vnode?.props) {
// close emit

vnode.props.onClose = () => {
container?.remove();
const modals = container.querySelectorAll(MODAL_WRAPPER_CLASS);

if (modals.length > 1) {
hostContainer.firstElementChild?.remove();
} else {
container.remove();
}

render(null, hostContainer);
};
}
Expand Down
8 changes: 1 addition & 7 deletions ui/packages/components/src/components/dialog/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@ export interface DialogProps {
showCancel?: boolean;
confirmText?: string;
cancelText?: string;
uniqueId?: string;
onConfirm?: () => void;
onCancel?: () => void;
}

type useDialogOptions = Omit<DialogProps, "visible" | "title"> & {
visible: boolean;
title: string;
};

export type useDialogUserOptions = Omit<useDialogOptions, "type" | "visible">;
1 change: 1 addition & 0 deletions ui/packages/components/src/components/modal/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ watch(
class="modal-wrapper"
role="dialog"
tabindex="0"
v-bind="$attrs"
@keyup.esc.stop="handleClose()"
>
<transition
Expand Down

0 comments on commit 52bc650

Please sign in to comment.