From beeced29a47942222ecf4d31ebdbf841ff2376c2 Mon Sep 17 00:00:00 2001 From: sallerli1 Date: Thu, 10 Aug 2023 19:25:55 +0800 Subject: [PATCH] fix(cdk:popper): reference is hidden when ancestors are not visible --- .../popper/src/middlewares/refenceHidden.ts | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/cdk/popper/src/middlewares/refenceHidden.ts b/packages/cdk/popper/src/middlewares/refenceHidden.ts index 2975dce54..f275450c9 100644 --- a/packages/cdk/popper/src/middlewares/refenceHidden.ts +++ b/packages/cdk/popper/src/middlewares/refenceHidden.ts @@ -5,7 +5,9 @@ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE */ -import { type Middleware, type Side, type SideObject, hide } from '@floating-ui/dom' +import { type Middleware, type ReferenceElement, type Side, type SideObject, hide } from '@floating-ui/dom' + +import { isVisibleElement } from '@idux/cdk/utils' export const referenceHiddenMiddlewareName = 'IDUX_referenceHidden' export interface ReferenceHiddenData { @@ -23,19 +25,26 @@ export function referenceHidden(): Middleware { name: referenceHiddenMiddlewareName, async fn(middlewareArguments) { const { - elements: { floating }, + elements: { floating, reference }, } = middlewareArguments const res = (await hideFn(middlewareArguments)) as { data: ReferenceHiddenData } const { - data: { referenceHiddenOffsets }, + data: { referenceHidden, referenceHiddenOffsets }, } = res - const referenceHidden = sides.some(side => referenceHiddenOffsets[side] > 0) + const shouldHideReference = + referenceHidden && + !( + reference instanceof HTMLElement && + getComputedStyle(reference).display === 'none' && + sides.some(side => referenceHiddenOffsets[side] === 0) && + checkParentsVisible(reference) + ) - if (sides.some(side => referenceHiddenOffsets[side] > 0)) { + if (shouldHideReference) { floating.setAttribute('data-popper-reference-hidden', '') } else { floating.removeAttribute('data-popper-reference-hidden') @@ -45,9 +54,26 @@ export function referenceHidden(): Middleware { ...res, data: { ...res.data, - referenceHidden, + referenceHidden: shouldHideReference, }, } }, } } + +function checkParentsVisible(el: ReferenceElement): boolean { + if (!(el instanceof HTMLElement)) { + return true + } + + let parent = el.parentElement + while (parent) { + if (!isVisibleElement(parent)) { + return false + } + + parent = parent.parentElement + } + + return true +}