mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-27 05:00:48 +08:00
fix(popover): can't be nested with other pop-able components, closes #872
This commit is contained in:
parent
587ea809bb
commit
9b059bcd5d
@ -29,6 +29,7 @@
|
|||||||
- Fix `n-date-picker`'s `date` type of `action` validate error.
|
- Fix `n-date-picker`'s `date` type of `action` validate error.
|
||||||
- Fix `n-data-table` throws error when using `selection` and `summary` together, closes [#1276](https://github.com/TuSimple/naive-ui/issues/1276).
|
- Fix `n-data-table` throws error when using `selection` and `summary` together, closes [#1276](https://github.com/TuSimple/naive-ui/issues/1276).
|
||||||
- Fix `n-data-table` selection column's width is collapsed when it is set to fixed, closes [#1283](https://github.com/TuSimple/naive-ui/issues/1283).
|
- Fix `n-data-table` selection column's width is collapsed when it is set to fixed, closes [#1283](https://github.com/TuSimple/naive-ui/issues/1283).
|
||||||
|
- Fix `n-popconfirm` can't be nested in `n-tooltip`, closes [#872](https://github.com/TuSimple/naive-ui/issues/872).
|
||||||
|
|
||||||
## 2.19.3 (2021-09-28)
|
## 2.19.3 (2021-09-28)
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
- 修复 `n-date-picker` 的 `date` 类型的 `action` 验证错误
|
- 修复 `n-date-picker` 的 `date` 类型的 `action` 验证错误
|
||||||
- 修复 `n-data-table` 在 `selection` 和 `summary` 一起使用时报错,关闭 [#1276](https://github.com/TuSimple/naive-ui/issues/1276)
|
- 修复 `n-data-table` 在 `selection` 和 `summary` 一起使用时报错,关闭 [#1276](https://github.com/TuSimple/naive-ui/issues/1276)
|
||||||
- 修复 `n-data-table` 勾选列的宽度在设为 fixed 时候塌陷,关闭 [#1283](https://github.com/TuSimple/naive-ui/issues/1283)
|
- 修复 `n-data-table` 勾选列的宽度在设为 fixed 时候塌陷,关闭 [#1283](https://github.com/TuSimple/naive-ui/issues/1283)
|
||||||
|
- 修复 `n-popconfirm` 不能被嵌套于 `n-tooltip` 内,关闭 [#872](https://github.com/TuSimple/naive-ui/issues/872).
|
||||||
|
|
||||||
## 2.19.3 (2021-09-28)
|
## 2.19.3 (2021-09-28)
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@
|
|||||||
"vdirs": "^0.1.4",
|
"vdirs": "^0.1.4",
|
||||||
"vfonts": "^0.1.0",
|
"vfonts": "^0.1.0",
|
||||||
"vooks": "^0.2.6",
|
"vooks": "^0.2.6",
|
||||||
"vueuc": "^0.4.12"
|
"vueuc": "^0.4.13"
|
||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"homepage": "https://www.naiveui.com",
|
"homepage": "https://www.naiveui.com",
|
||||||
|
@ -37,6 +37,7 @@ export type PopconfirmProps = ExtractPublicPropTypes<typeof popconfirmProps>
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Popconfirm',
|
name: 'Popconfirm',
|
||||||
props: popconfirmProps,
|
props: popconfirmProps,
|
||||||
|
__popover__: true,
|
||||||
setup (props) {
|
setup (props) {
|
||||||
const { mergedClsPrefixRef } = useConfig()
|
const { mergedClsPrefixRef } = useConfig()
|
||||||
const themeRef = useTheme(
|
const themeRef = useTheme(
|
||||||
|
@ -20,6 +20,7 @@ manual-position
|
|||||||
header
|
header
|
||||||
hoist-debug
|
hoist-debug
|
||||||
nested-debug
|
nested-debug
|
||||||
|
nested2-debug
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
27
src/popover/demos/zhCN/nested2-debug.demo.md
Normal file
27
src/popover/demos/zhCN/nested2-debug.demo.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Nested Debug
|
||||||
|
|
||||||
|
```html
|
||||||
|
<n-tooltip placement="bottom">
|
||||||
|
<template #trigger>
|
||||||
|
<n-popover trigger="click">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button>Test</n-button>
|
||||||
|
</template>
|
||||||
|
Popover
|
||||||
|
</n-popover>
|
||||||
|
</template>
|
||||||
|
Tooltip
|
||||||
|
</n-tooltip>
|
||||||
|
|
||||||
|
<n-tooltip trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<n-popconfirm>
|
||||||
|
<template #trigger>
|
||||||
|
<n-button>tooltip内嵌popconfirm</n-button>
|
||||||
|
</template>
|
||||||
|
一切都将一去杳然,任何人都无法将其捕获。
|
||||||
|
</n-popconfirm>
|
||||||
|
</template>
|
||||||
|
如果它长得像鸭子,走起来像鸭子,叫起来也像鸭子,那它一定是个鸭子。
|
||||||
|
</n-tooltip>
|
||||||
|
```
|
@ -14,7 +14,7 @@ import {
|
|||||||
cloneVNode,
|
cloneVNode,
|
||||||
watchEffect
|
watchEffect
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { VBinder, VTarget, FollowerPlacement } from 'vueuc'
|
import { VBinder, VTarget, FollowerPlacement, BinderInst } from 'vueuc'
|
||||||
import { useMergedState, useCompitable, useIsMounted, useMemo } from 'vooks'
|
import { useMergedState, useCompitable, useIsMounted, useMemo } from 'vooks'
|
||||||
import { call, keep, getFirstSlotVNode, warnOnce } from '../../_utils'
|
import { call, keep, getFirstSlotVNode, warnOnce } from '../../_utils'
|
||||||
import type {
|
import type {
|
||||||
@ -36,19 +36,22 @@ const triggerEventMap = {
|
|||||||
focus: ['onFocus', 'onBlur'],
|
focus: ['onFocus', 'onBlur'],
|
||||||
click: ['onClick'],
|
click: ['onClick'],
|
||||||
hover: ['onMouseenter', 'onMouseleave'],
|
hover: ['onMouseenter', 'onMouseleave'],
|
||||||
manual: []
|
manual: [],
|
||||||
|
nested: ['onFocus', 'onBlur', 'onMouseenter', 'onMouseleave', 'onClick']
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
export interface TriggerEventHandlers {
|
||||||
|
onClick: (e: MouseEvent) => void
|
||||||
|
onMouseenter: (e: MouseEvent) => void
|
||||||
|
onMouseleave: (e: MouseEvent) => void
|
||||||
|
onFocus: (e: FocusEvent) => void
|
||||||
|
onBlur: (e: FocusEvent) => void
|
||||||
|
}
|
||||||
|
|
||||||
function appendEvents (
|
function appendEvents (
|
||||||
vNode: VNode,
|
vNode: VNode,
|
||||||
trigger: PopoverTrigger,
|
trigger: PopoverTrigger | 'nested',
|
||||||
events: {
|
events: TriggerEventHandlers
|
||||||
onClick: (e: MouseEvent) => void
|
|
||||||
onMouseenter: (e: MouseEvent) => void
|
|
||||||
onMouseleave: (e: MouseEvent) => void
|
|
||||||
onFocus: (e: FocusEvent) => void
|
|
||||||
onBlur: (e: FocusEvent) => void
|
|
||||||
}
|
|
||||||
): void {
|
): void {
|
||||||
triggerEventMap[trigger].forEach((eventName) => {
|
triggerEventMap[trigger].forEach((eventName) => {
|
||||||
if (!vNode.props) vNode.props = {}
|
if (!vNode.props) vNode.props = {}
|
||||||
@ -151,6 +154,11 @@ export const popoverBaseProps = {
|
|||||||
MaybeArray<(value: boolean) => void>
|
MaybeArray<(value: boolean) => void>
|
||||||
>,
|
>,
|
||||||
zIndex: Number,
|
zIndex: Number,
|
||||||
|
internalSyncTargetWithParent: Boolean,
|
||||||
|
internalInheritedEventHandlers: {
|
||||||
|
type: Array as PropType<TriggerEventHandlers[]>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
onShow: [Function, Array] as PropType<
|
onShow: [Function, Array] as PropType<
|
||||||
MaybeArray<(value: boolean) => void> | undefined
|
MaybeArray<(value: boolean) => void> | undefined
|
||||||
@ -183,6 +191,7 @@ export default defineComponent({
|
|||||||
name: 'Popover',
|
name: 'Popover',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: popoverProps,
|
props: popoverProps,
|
||||||
|
__popover__: true,
|
||||||
setup (props) {
|
setup (props) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
@ -219,6 +228,7 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const isMountedRef = useIsMounted()
|
const isMountedRef = useIsMounted()
|
||||||
|
const binderInstRef = ref<BinderInst | null>(null)
|
||||||
// setup show
|
// setup show
|
||||||
const controlledShowRef = computed(() => props.show)
|
const controlledShowRef = computed(() => props.show)
|
||||||
const uncontrolledShowRef = ref(props.defaultShow)
|
const uncontrolledShowRef = ref(props.defaultShow)
|
||||||
@ -246,8 +256,6 @@ export default defineComponent({
|
|||||||
if (props.overlap) return false
|
if (props.overlap) return false
|
||||||
return compatibleShowArrowRef.value
|
return compatibleShowArrowRef.value
|
||||||
})
|
})
|
||||||
// trigger
|
|
||||||
let triggerVNode: VNode | null = null
|
|
||||||
// bodyInstance
|
// bodyInstance
|
||||||
let bodyInstance: BodyInstance | null = null
|
let bodyInstance: BodyInstance | null = null
|
||||||
const showTimerIdRef = ref<number | null>(null)
|
const showTimerIdRef = ref<number | null>(null)
|
||||||
@ -372,7 +380,7 @@ export default defineComponent({
|
|||||||
uncontrolledShowRef.value = value
|
uncontrolledShowRef.value = value
|
||||||
}
|
}
|
||||||
function getTriggerElement (): HTMLElement {
|
function getTriggerElement (): HTMLElement {
|
||||||
return triggerVNode?.el as HTMLElement
|
return binderInstRef.value?.targetRef as HTMLElement
|
||||||
}
|
}
|
||||||
function setBodyInstance (value: BodyInstance | null): void {
|
function setBodyInstance (value: BodyInstance | null): void {
|
||||||
bodyInstance = value
|
bodyInstance = value
|
||||||
@ -391,6 +399,7 @@ export default defineComponent({
|
|||||||
internalRenderBodyRef: toRef(props, 'internalRenderBody')
|
internalRenderBodyRef: toRef(props, 'internalRenderBody')
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
binderInstRef,
|
||||||
positionManually: positionManuallyRef,
|
positionManually: positionManuallyRef,
|
||||||
mergedShowConsideringDisabledProp: mergedShowConsideringDisabledPropRef,
|
mergedShowConsideringDisabledProp: mergedShowConsideringDisabledPropRef,
|
||||||
// if to show popover body
|
// if to show popover body
|
||||||
@ -403,65 +412,127 @@ export default defineComponent({
|
|||||||
handleMouseLeave,
|
handleMouseLeave,
|
||||||
handleFocus,
|
handleFocus,
|
||||||
handleBlur,
|
handleBlur,
|
||||||
setTriggerVNode (v: VNode | null) {
|
|
||||||
triggerVNode = v
|
|
||||||
},
|
|
||||||
syncPosition
|
syncPosition
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
return h(VBinder, null, {
|
const { positionManually, $slots: slots } = this
|
||||||
default: () => {
|
let triggerVNode: VNode | null
|
||||||
const { positionManually, $slots: slots } = this
|
let popoverInside = false
|
||||||
let triggerVNode: VNode | null
|
if (!positionManually) {
|
||||||
if (!positionManually) {
|
if (slots.activator) {
|
||||||
if (slots.activator) {
|
triggerVNode = getFirstSlotVNode(slots, 'activator')
|
||||||
triggerVNode = getFirstSlotVNode(slots, 'activator')
|
} else {
|
||||||
} else {
|
triggerVNode = getFirstSlotVNode(slots, 'trigger')
|
||||||
triggerVNode = getFirstSlotVNode(slots, 'trigger')
|
|
||||||
}
|
|
||||||
if (triggerVNode) {
|
|
||||||
triggerVNode = cloneVNode(triggerVNode)
|
|
||||||
triggerVNode =
|
|
||||||
triggerVNode.type === textVNodeType
|
|
||||||
? h('span', [triggerVNode])
|
|
||||||
: triggerVNode
|
|
||||||
appendEvents(
|
|
||||||
triggerVNode,
|
|
||||||
positionManually ? 'manual' : this.trigger,
|
|
||||||
{
|
|
||||||
onClick: this.handleClick,
|
|
||||||
onMouseenter: this.handleMouseEnter,
|
|
||||||
onMouseleave: this.handleMouseLeave,
|
|
||||||
onFocus: this.handleFocus,
|
|
||||||
onBlur: this.handleBlur
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
this.setTriggerVNode(triggerVNode)
|
|
||||||
}
|
|
||||||
// We need to subscribe it. Sometimes rerender won't ge triggered.
|
|
||||||
// `mergedShowConsideringDisabledProp` is not the final disabled status.
|
|
||||||
// In ellpisis it's dynamic.
|
|
||||||
void this.mergedShowConsideringDisabledProp
|
|
||||||
const mergedShow = this.getMergedShow()
|
|
||||||
return [
|
|
||||||
positionManually
|
|
||||||
? null
|
|
||||||
: h(VTarget, null, {
|
|
||||||
default: () => triggerVNode
|
|
||||||
}),
|
|
||||||
h(
|
|
||||||
NPopoverBody,
|
|
||||||
keep(this.$props, bodyPropKeys, {
|
|
||||||
...this.$attrs,
|
|
||||||
showArrow: this.mergedShowArrow,
|
|
||||||
show: mergedShow
|
|
||||||
}),
|
|
||||||
slots
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
})
|
if (triggerVNode) {
|
||||||
|
triggerVNode = cloneVNode(triggerVNode)
|
||||||
|
triggerVNode =
|
||||||
|
triggerVNode.type === textVNodeType
|
||||||
|
? h('span', [triggerVNode])
|
||||||
|
: triggerVNode
|
||||||
|
const handlers = {
|
||||||
|
onClick: this.handleClick,
|
||||||
|
onMouseenter: this.handleMouseEnter,
|
||||||
|
onMouseleave: this.handleMouseLeave,
|
||||||
|
onFocus: this.handleFocus,
|
||||||
|
onBlur: this.handleBlur
|
||||||
|
}
|
||||||
|
if ((triggerVNode.type as any)?.__popover__) {
|
||||||
|
popoverInside = true
|
||||||
|
// We assume that there's no DOM event handlers on popover element
|
||||||
|
if (!triggerVNode.props) {
|
||||||
|
triggerVNode.props = {
|
||||||
|
internalSyncTargetWithParent: true,
|
||||||
|
internalInheritedEventHandlers: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
triggerVNode.props.internalSyncTargetWithParent = true
|
||||||
|
if (!triggerVNode.props.internalInheritedEventHandlers) {
|
||||||
|
triggerVNode.props.internalInheritedEventHandlers = [handlers]
|
||||||
|
} else {
|
||||||
|
triggerVNode.props.internalInheritedEventHandlers = [
|
||||||
|
handlers,
|
||||||
|
...triggerVNode.props.internalInheritedEventHandlers
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const { internalInheritedEventHandlers } = this
|
||||||
|
const ascendantAndCurrentHandlers: TriggerEventHandlers[] = [
|
||||||
|
handlers,
|
||||||
|
...internalInheritedEventHandlers
|
||||||
|
]
|
||||||
|
const mergedHandlers: TriggerEventHandlers = {
|
||||||
|
onBlur: (e: FocusEvent) => {
|
||||||
|
ascendantAndCurrentHandlers.forEach((_handlers) => {
|
||||||
|
_handlers.onBlur(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onFocus: (e: FocusEvent) => {
|
||||||
|
ascendantAndCurrentHandlers.forEach((_handlers) => {
|
||||||
|
_handlers.onBlur(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onClick: (e: MouseEvent) => {
|
||||||
|
ascendantAndCurrentHandlers.forEach((_handlers) => {
|
||||||
|
_handlers.onClick(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onMouseenter: (e: MouseEvent) => {
|
||||||
|
ascendantAndCurrentHandlers.forEach((_handlers) => {
|
||||||
|
_handlers.onMouseenter(e)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onMouseleave: (e: MouseEvent) => {
|
||||||
|
ascendantAndCurrentHandlers.forEach((_handlers) => {
|
||||||
|
_handlers.onMouseleave(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendEvents(
|
||||||
|
triggerVNode,
|
||||||
|
internalInheritedEventHandlers
|
||||||
|
? 'nested'
|
||||||
|
: positionManually
|
||||||
|
? 'manual'
|
||||||
|
: this.trigger,
|
||||||
|
mergedHandlers
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<VBinder
|
||||||
|
ref="binderInstRef"
|
||||||
|
syncTarget={!popoverInside}
|
||||||
|
syncTargetWithParent={this.internalSyncTargetWithParent}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => {
|
||||||
|
// We need to subscribe it. Sometimes rerender won't ge triggered.
|
||||||
|
// `mergedShowConsideringDisabledProp` is not the final disabled status.
|
||||||
|
// In ellpisis it's dynamic.
|
||||||
|
void this.mergedShowConsideringDisabledProp
|
||||||
|
const mergedShow = this.getMergedShow()
|
||||||
|
return [
|
||||||
|
positionManually
|
||||||
|
? null
|
||||||
|
: h(VTarget, null, {
|
||||||
|
default: () => triggerVNode
|
||||||
|
}),
|
||||||
|
h(
|
||||||
|
NPopoverBody,
|
||||||
|
keep(this.$props, bodyPropKeys, {
|
||||||
|
...this.$attrs,
|
||||||
|
showArrow: this.mergedShowArrow,
|
||||||
|
show: mergedShow
|
||||||
|
}),
|
||||||
|
slots
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</VBinder>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -32,6 +32,7 @@ export type PopselectProps = ExtractPublicPropTypes<typeof popselectProps>
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Popselect',
|
name: 'Popselect',
|
||||||
props: popselectProps,
|
props: popselectProps,
|
||||||
|
__popover__: true,
|
||||||
setup (props) {
|
setup (props) {
|
||||||
const themeRef = useTheme(
|
const themeRef = useTheme(
|
||||||
'Popselect',
|
'Popselect',
|
||||||
|
@ -21,6 +21,7 @@ export type TooltipProps = ExtractPublicPropTypes<typeof tooltipProps>
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Tooltip',
|
name: 'Tooltip',
|
||||||
props: tooltipProps,
|
props: tooltipProps,
|
||||||
|
__popover__: true,
|
||||||
setup (props) {
|
setup (props) {
|
||||||
const themeRef = useTheme(
|
const themeRef = useTheme(
|
||||||
'Tooltip',
|
'Tooltip',
|
||||||
|
Loading…
Reference in New Issue
Block a user