feat: implement auto-z-index directive and update z-index values across components

This commit is contained in:
purocean
2024-12-04 08:26:27 +08:00
parent f1b82567e8
commit 3debcd29f2
16 changed files with 82 additions and 60 deletions
+1 -1
View File
@@ -145,7 +145,7 @@ export default defineComponent({
.presentation-exit {
position: fixed;
z-index: 99999;
z-index: 210000000;
bottom: 6px;
left: 6px;
padding: 10px;
+2 -2
View File
@@ -1,5 +1,5 @@
<template>
<XMask transparent :show="items && items.length > 0" @close="hide" :style="{ zIndex: 2147483646 }">
<XMask transparent :show="items && items.length > 0" @close="hide" layer="context-menu">
<ul :class="{menu: true, 'item-focus': itemFocus}" ref="refMenu" @contextmenu.prevent tabindex="-1" v-auto-focus>
<template v-for="(item, i) in items">
<li v-if="item.type === 'separator'" v-show="!item.hidden" :key="i" :class="item.type" />
@@ -175,7 +175,7 @@ export default defineComponent({
border: 1px var(--g-color-84) solid;
border-left: 0;
border-top: 0;
z-index: 2147483647;
z-index: 1000;
color: var(--g-foreground-color);
min-width: 9em;
cursor: default;
+1 -2
View File
@@ -1,6 +1,6 @@
<template>
<teleport to="body">
<div v-if="visible && schema" class="control-center" v-fixed-float="{ onClose: (byClickSelf: any) => !byClickSelf && toggle(false) }">
<div v-if="visible && schema" class="control-center" v-fixed-float="{ onClose: (byClickSelf: any) => !byClickSelf && toggle(false) }" v-auto-z-index="{ layer: 'popup' }">
<div v-for="(row, category) in schema" :key="category" class="row">
<template v-for="(item, i) in row?.items" :key="i">
<div
@@ -82,7 +82,6 @@ onBeforeUnmount(() => {
position: fixed;
right: 14px;
top: 36px;
z-index: 1000;
outline: none;
background: var(--g-color-backdrop);
backdrop-filter: var(--g-backdrop-filter);
+1 -1
View File
@@ -7,6 +7,7 @@
onBlur: (byClickSelf: any) => emits('blur', byClickSelf),
disableAutoFocus: props.disableAutoFocus
}"
v-auto-z-index="{ layer: 'popup' }"
@click.stop
v-bind="$attrs"
:style="{
@@ -56,6 +57,5 @@ const emits = defineEmits<{
border-radius: var(--g-border-radius);
overflow: hidden;
backdrop-filter: var(--g-backdrop-filter);
z-index: 9999999;
}
</style>
@@ -534,7 +534,7 @@ table {
height: 100%;
top: 0;
left: 0;
z-index: 900000;
z-index: 210000000;
display: flex;
flex-direction: column;
align-items: center;
+9 -44
View File
@@ -1,7 +1,7 @@
<template>
<teleport to="body">
<transition name="fade">
<div v-if="show" :class="{'mask-wrapper': true, transparent}" :style="wrapperStyle">
<div v-if="show" :class="{'mask-wrapper': true, transparent}" :style="style" v-auto-z-index="{ layer, onEsc }">
<div class="mask" @click="() => maskCloseable && $emit('close')" @contextmenu.prevent.stop="$emit('close')" />
<div class="content">
<slot></slot>
@@ -12,11 +12,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { registerHook, removeHook } from '@fe/core/hook'
let zIndex = 199998
const maskStack: number[] = []
import { defineComponent } from 'vue'
export default defineComponent({
name: 'x-mask',
@@ -38,50 +34,20 @@ export default defineComponent({
type: [Object, String],
default: () => ({}),
},
layer: {
type: String as () => 'popup' | 'context-menu' | 'max',
default: 'popup'
},
},
emits: ['close'],
setup (props, { emit }) {
const zIndexRef = ref(zIndex++)
function keydownHandler (e: KeyboardEvent) {
if (e.key === 'Escape' && props.show) {
// close top mask
if (!maskStack.includes(zIndexRef.value) || Math.max(...maskStack) !== zIndexRef.value) {
return
}
function onEsc () {
if (props.show) {
props.escCloseable && emit('close')
e.stopPropagation()
}
}
watch(() => props.show, (val) => {
if (val) {
maskStack.push(zIndexRef.value)
} else {
maskStack.splice(maskStack.indexOf(zIndexRef.value), 1)
}
}, { immediate: true, flush: 'post' })
watch(() => props.show, (val) => {
if (val) {
zIndex++
zIndexRef.value = zIndex
}
})
const wrapperStyle = computed(() => (typeof props.style === 'string' ? props.style : { zIndex: zIndexRef.value, ...props.style }))
onMounted(() => {
registerHook('GLOBAL_KEYDOWN', keydownHandler)
})
onBeforeUnmount(() => {
removeHook('GLOBAL_KEYDOWN', keydownHandler)
maskStack.splice(maskStack.indexOf(zIndexRef.value), 1)
})
return { wrapperStyle }
return { onEsc }
},
})
</script>
@@ -93,7 +59,6 @@ export default defineComponent({
left: 0;
width: 100%;
height: 100%;
z-index: 199998;
padding-top: 6em;
}
+1 -1
View File
@@ -283,7 +283,7 @@ export default defineComponent({
particleCount: 150,
spread: 100,
origin: { y: 0.6 },
zIndex: Number.MAX_SAFE_INTEGER,
zIndex: 2.1e8,
})
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ export default defineComponent({
.status-bar-menu {
cursor: pointer;
user-select: none;
z-index: 99999999;
z-index: 300000;
position: relative;
overflow-x: hidden;
font-variant-numeric: tabular-nums;
+1 -1
View File
@@ -252,7 +252,7 @@ export default defineComponent({
-webkit-user-select: none;
-webkit-app-region: drag;
position: relative;
z-index: 199999;
z-index: 8000000;
}
.resizer {
+1 -1
View File
@@ -61,7 +61,7 @@ export default defineComponent({
left: 0;
top: 100px;
padding: 10px 20px;
z-index: 999999;
z-index: 200000000;
right: 0;
margin: auto;
border-radius: 50px;
+56
View File
@@ -0,0 +1,56 @@
import { App } from 'vue'
import { registerHook, removeHook } from '@fe/core/hook'
let globalZIndex = 0
const stack: number[] = []
const layers = {
popup: 2e5,
'context-menu': 9e6,
max: 2e8,
}
export function install (app: App) {
const getKeydownHandler = (zIndex: number, onEsc: () => void) => (e: KeyboardEvent) => {
if (e.key === 'Escape') {
// close top layer
if (!stack.includes(zIndex) || Math.max(...stack) !== zIndex) {
return
}
onEsc()
e.stopPropagation()
}
}
app.directive('auto-z-index', {
mounted (el: HTMLElement, binding) {
const value: { layer: keyof typeof layers, onEsc?: () => void } = binding.value
const layer = value.layer || 'popup'
const baseZIndex = layers[layer] || layers.popup
const zIndex = baseZIndex + globalZIndex++
;(el as any)._autoZIndex = zIndex
stack.push(zIndex)
el.style.zIndex = zIndex.toString()
const globalKeydownHandler = value.onEsc && getKeydownHandler(zIndex, value.onEsc)
if (globalKeydownHandler) {
registerHook('GLOBAL_KEYDOWN', globalKeydownHandler)
;(el as any)._autoZIndexKeydownHandler = globalKeydownHandler
}
},
beforeUnmount: (el: HTMLElement) => {
const zIndex = (el as any)._autoZIndex
const index = stack.indexOf(zIndex)
if (index !== -1) {
stack.splice(index, 1)
}
const keydownHandler = (el as any)._autoZIndexKeydownHandler
if (keydownHandler) {
removeHook('GLOBAL_KEYDOWN', keydownHandler)
}
}
})
}
+3 -1
View File
@@ -5,8 +5,9 @@ import * as placeholder from './placeholder'
import * as upDownHistory from './up-down-history'
import * as fixedFloat from './fixed-float'
import * as textareaOnEnter from './textarea-on-enter'
import * as autoZIndex from './auto-z-index'
export { autoFocus, autoResize, placeholder, upDownHistory, fixedFloat, textareaOnEnter }
export { autoFocus, autoResize, placeholder, upDownHistory, fixedFloat, textareaOnEnter, autoZIndex }
export default function (app: App) {
autoFocus.install(app)
@@ -15,4 +16,5 @@ export default function (app: App) {
upDownHistory.install(app)
fixedFloat.install(app)
textareaOnEnter.install(app)
autoZIndex.install(app)
}
+1 -1
View File
@@ -82,7 +82,7 @@ export default {
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.2);
z-index: 99999999;
z-index: 210000000;
}
`)
}
+1 -1
View File
@@ -87,7 +87,7 @@ export default {
ctx.registerHook('VIEW_MOUNTED', () => {
setTimeout(() => {
const viewer = new Viewer(ctx.view.getViewDom()!, {
zIndex: 299999,
zIndex: 2.11e8,
container: document.body,
transition: false,
toolbar: {
+1 -1
View File
@@ -14,7 +14,7 @@ export default {
particleCount: 150,
spread: 100,
origin: { y: 0.6 },
zIndex: Number.MAX_SAFE_INTEGER,
zIndex: 2.1e8,
})
}
}
+1 -1
View File
@@ -90,7 +90,7 @@ export async function printCurrentDocumentToPDF (opts?: PrintOpts): Promise<Buff
const id = '__export_pdf__' + Date.now()
const url = buildSrc(`
<style> @media screen { html { overflow: hidden; min-width: 16cm; } } </style>
<div class="skip-print" style="position: fixed; left: 0; top: 0; width: 100vw; height: 100%; z-index: 99999; background: #fff; color: #24292f; display: flex; align-items: center; justify-content: center;">Exporting……</div>
<div class="skip-print" style="position: fixed; left: 0; top: 0; width: 100vw; height: 100%; z-index: 210000000; background: #fff; color: #24292f; display: flex; align-items: center; justify-content: center;">Exporting……</div>
<div id="app"></div>
`, 'Export PDF', { id, globalStyle: true })