mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 18:22:40 +00:00
Change dialog to multi-window mode (#1695)
Fixed Dropdown's z-index being below the dialog
This commit is contained in:
@@ -1,61 +1,51 @@
|
|||||||
<!-- The main global dialog to show various things -->
|
<!-- The main global dialog to show various things -->
|
||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
v-model:visible="dialogStore.isVisible"
|
v-for="(item, index) in dialogStore.dialogStack"
|
||||||
|
:key="item.key"
|
||||||
|
v-model:visible="item.visible"
|
||||||
class="global-dialog"
|
class="global-dialog"
|
||||||
modal
|
v-bind="item.dialogComponentProps"
|
||||||
closable
|
:auto-z-index="false"
|
||||||
closeOnEscape
|
:pt:mask:style="{ zIndex: baseZIndex + index + 1 }"
|
||||||
dismissableMask
|
:aria-labelledby="item.key"
|
||||||
:maximizable="maximizable"
|
|
||||||
:maximized="maximized"
|
|
||||||
@hide="dialogStore.closeDialog"
|
|
||||||
@maximize="onMaximize"
|
|
||||||
@unmaximize="onUnmaximize"
|
|
||||||
:aria-labelledby="headerId"
|
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<component
|
<component
|
||||||
v-if="dialogStore.headerComponent"
|
v-if="item.headerComponent"
|
||||||
:is="dialogStore.headerComponent"
|
:is="item.headerComponent"
|
||||||
:id="headerId"
|
:id="item.key"
|
||||||
/>
|
/>
|
||||||
<h3 v-else :id="headerId">{{ dialogStore.title || ' ' }}</h3>
|
<h3 v-else :id="item.key">{{ item.title || ' ' }}</h3>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<component :is="dialogStore.component" v-bind="contentProps" />
|
<component
|
||||||
|
:is="item.component"
|
||||||
|
v-bind="item.contentProps"
|
||||||
|
:maximized="item.dialogComponentProps.maximized"
|
||||||
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
|
import { ZIndex } from '@primeuix/utils/zindex'
|
||||||
|
import { usePrimeVue } from '@primevue/core'
|
||||||
import { useDialogStore } from '@/stores/dialogStore'
|
import { useDialogStore } from '@/stores/dialogStore'
|
||||||
import Dialog from 'primevue/dialog'
|
import Dialog from 'primevue/dialog'
|
||||||
|
|
||||||
const dialogStore = useDialogStore()
|
const dialogStore = useDialogStore()
|
||||||
const maximizable = computed(
|
|
||||||
() => dialogStore.dialogComponentProps.maximizable ?? false
|
|
||||||
)
|
|
||||||
const maximized = ref(false)
|
|
||||||
|
|
||||||
const onMaximize = () => {
|
const primevue = usePrimeVue()
|
||||||
maximized.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const onUnmaximize = () => {
|
const baseZIndex = computed(() => {
|
||||||
maximized.value = false
|
return primevue?.config?.zIndex?.modal ?? 1100
|
||||||
}
|
})
|
||||||
|
|
||||||
const contentProps = computed(() =>
|
onMounted(() => {
|
||||||
maximizable.value
|
const mask = document.createElement('div')
|
||||||
? {
|
ZIndex.set('model', mask, baseZIndex.value)
|
||||||
...dialogStore.props,
|
})
|
||||||
maximized: maximized.value
|
|
||||||
}
|
|
||||||
: dialogStore.props
|
|
||||||
)
|
|
||||||
|
|
||||||
const headerId = `dialog-${Math.random().toString(36).substr(2, 9)}`
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -2,52 +2,126 @@
|
|||||||
// Currently we need to bridge between legacy app code and Vue app with a Pinia store.
|
// Currently we need to bridge between legacy app code and Vue app with a Pinia store.
|
||||||
|
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref, shallowRef, type Component, markRaw } from 'vue'
|
import { ref, type Component, markRaw } from 'vue'
|
||||||
|
|
||||||
interface DialogComponentProps {
|
interface DialogComponentProps {
|
||||||
maximizable?: boolean
|
maximizable?: boolean
|
||||||
onClose?: () => void
|
onClose?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDialogStore = defineStore('dialog', () => {
|
interface DialogInstance {
|
||||||
const isVisible = ref(false)
|
key: string
|
||||||
const title = ref('')
|
visible: boolean
|
||||||
const headerComponent = shallowRef<Component | null>(null)
|
title?: string
|
||||||
const component = shallowRef<Component | null>(null)
|
headerComponent?: Component
|
||||||
const props = ref<Record<string, any>>({})
|
component: Component
|
||||||
const dialogComponentProps = ref<DialogComponentProps>({})
|
contentProps: Record<string, any>
|
||||||
|
dialogComponentProps: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
function showDialog(options: {
|
export const useDialogStore = defineStore('dialog', () => {
|
||||||
|
const dialogStack = ref<DialogInstance[]>([])
|
||||||
|
|
||||||
|
const genDialogKey = () => `dialog-${Math.random().toString(36).slice(2, 9)}`
|
||||||
|
|
||||||
|
function riseDialog(options: { key: string }) {
|
||||||
|
const dialogKey = options.key
|
||||||
|
|
||||||
|
const index = dialogStack.value.findIndex((d) => d.key === dialogKey)
|
||||||
|
if (index !== -1) {
|
||||||
|
const dialogs = dialogStack.value.splice(index, 1)
|
||||||
|
dialogStack.value.push(...dialogs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDialog(options?: { key: string }) {
|
||||||
|
if (!options) {
|
||||||
|
dialogStack.value.pop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogKey = options.key
|
||||||
|
|
||||||
|
const index = dialogStack.value.findIndex((d) => d.key === dialogKey)
|
||||||
|
if (index === -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dialogStack.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDialog(options: {
|
||||||
|
key: string
|
||||||
title?: string
|
title?: string
|
||||||
headerComponent?: Component
|
headerComponent?: Component
|
||||||
component: Component
|
component: Component
|
||||||
props?: Record<string, any>
|
props?: Record<string, any>
|
||||||
dialogComponentProps?: DialogComponentProps
|
dialogComponentProps?: DialogComponentProps
|
||||||
}) {
|
}) {
|
||||||
isVisible.value = true
|
const dialog = {
|
||||||
title.value = options.title ?? ''
|
key: options.key,
|
||||||
headerComponent.value = options.headerComponent
|
visible: true,
|
||||||
? markRaw(options.headerComponent)
|
title: options.title,
|
||||||
: null
|
headerComponent: options.headerComponent
|
||||||
component.value = markRaw(options.component)
|
? markRaw(options.headerComponent)
|
||||||
props.value = options.props || {}
|
: undefined,
|
||||||
dialogComponentProps.value = options.dialogComponentProps || {}
|
component: markRaw(options.component),
|
||||||
|
contentProps: { ...options.props },
|
||||||
|
dialogComponentProps: {
|
||||||
|
maximizable: false,
|
||||||
|
modal: true,
|
||||||
|
closable: true,
|
||||||
|
closeOnEscape: true,
|
||||||
|
dismissableMask: true,
|
||||||
|
...options.dialogComponentProps,
|
||||||
|
maximized: false,
|
||||||
|
onMaximize: () => {
|
||||||
|
dialog.dialogComponentProps.maximized = true
|
||||||
|
},
|
||||||
|
onUnmaximize: () => {
|
||||||
|
dialog.dialogComponentProps.maximized = false
|
||||||
|
},
|
||||||
|
onAfterHide: () => {
|
||||||
|
options.dialogComponentProps?.onClose?.()
|
||||||
|
closeDialog(dialog)
|
||||||
|
},
|
||||||
|
pt: {
|
||||||
|
root: {
|
||||||
|
onMousedown: () => {
|
||||||
|
riseDialog(dialog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialogStack.value.push(dialog)
|
||||||
|
|
||||||
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDialog() {
|
function showDialog(options: {
|
||||||
if (dialogComponentProps.value.onClose) {
|
key?: string
|
||||||
dialogComponentProps.value.onClose()
|
title?: string
|
||||||
|
headerComponent?: Component
|
||||||
|
component: Component
|
||||||
|
props?: Record<string, any>
|
||||||
|
dialogComponentProps?: DialogComponentProps
|
||||||
|
}) {
|
||||||
|
const dialogKey = options.key || genDialogKey()
|
||||||
|
|
||||||
|
let dialog = dialogStack.value.find((d) => d.key === dialogKey)
|
||||||
|
|
||||||
|
if (dialog) {
|
||||||
|
dialog.visible = true
|
||||||
|
riseDialog(dialog)
|
||||||
|
} else {
|
||||||
|
dialog = createDialog({ ...options, key: dialogKey })
|
||||||
}
|
}
|
||||||
isVisible.value = false
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isVisible,
|
dialogStack,
|
||||||
title,
|
riseDialog,
|
||||||
headerComponent,
|
|
||||||
component,
|
|
||||||
props,
|
|
||||||
dialogComponentProps,
|
|
||||||
showDialog,
|
showDialog,
|
||||||
closeDialog
|
closeDialog
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user