From acbcc991fffe09dbfb80f113b1f10374485cabdd Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 11 Aug 2022 21:02:49 +0300 Subject: [PATCH 1/2] update floating-ui + fix --- package-lock.json | 48 ++++++------ packages/components/package.json | 2 +- packages/components/src/popover/index.js | 98 ++++++++++++++++++++---- 3 files changed, 108 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d7947ac5abc54..fb90270d8051c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2836,28 +2836,6 @@ } } }, - "@floating-ui/core": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.6.2.tgz", - "integrity": "sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg==" - }, - "@floating-ui/dom": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.4.5.tgz", - "integrity": "sha512-b+prvQgJt8pieaKYMSJBXHxX/DYwdLsAWxKYqnO5dO2V4oo/TYBZJAUQCVNjTWWsrs6o4VDrNcP9+E70HAhJdw==", - "requires": { - "@floating-ui/core": "^0.6.2" - } - }, - "@floating-ui/react-dom": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-0.6.3.tgz", - "integrity": "sha512-hC+pS5D6AgS2wWjbmSQ6UR6Kpy+drvWGJIri6e1EDGADTPsCaa4KzCgmCczHrQeInx9tqs81EyDmbKJYY2swKg==", - "requires": { - "@floating-ui/dom": "^0.4.5", - "use-isomorphic-layout-effect": "^1.1.1" - } - }, "@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -16684,7 +16662,7 @@ "@emotion/serialize": "^1.0.2", "@emotion/styled": "^11.6.0", "@emotion/utils": "1.0.0", - "@floating-ui/react-dom": "0.6.3", + "@floating-ui/react-dom": "1.0.0", "@use-gesture/react": "^10.2.6", "@wordpress/a11y": "file:packages/a11y", "@wordpress/compose": "file:packages/compose", @@ -16731,6 +16709,27 @@ "csstype": "^3.0.2" } }, + "@floating-ui/core": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.1.tgz", + "integrity": "sha512-bO37brCPfteXQfFY0DyNDGB3+IMe4j150KFQcgJ5aBP295p9nBGeHEs/p0czrRbtlHq4Px/yoPXO/+dOCcF4uA==" + }, + "@floating-ui/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-wBDiLUKWU8QNPNOTAFHiIAkBv1KlHauG2AhqjSeh2H+wR8PX+AArXfz8NkRexH5PgMJMmSOS70YS89AbWYh5dA==", + "requires": { + "@floating-ui/core": "^1.0.1" + } + }, + "@floating-ui/react-dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-1.0.0.tgz", + "integrity": "sha512-uiOalFKPG937UCLm42RxjESTWUVpbbatvlphQAU6bsv+ence6IoVG8JOUZcy8eW81NkU+Idiwvx10WFLmR4MIg==", + "requires": { + "@floating-ui/dom": "^1.0.0" + } + }, "colord": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz", @@ -58025,7 +58024,8 @@ "use-isomorphic-layout-effect": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", - "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" + "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", + "dev": true }, "use-latest": { "version": "1.2.0", diff --git a/packages/components/package.json b/packages/components/package.json index ce3dc7133c8ed1..65c8d5a11b7477 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -36,7 +36,7 @@ "@emotion/serialize": "^1.0.2", "@emotion/styled": "^11.6.0", "@emotion/utils": "1.0.0", - "@floating-ui/react-dom": "0.6.3", + "@floating-ui/react-dom": "1.0.0", "@use-gesture/react": "^10.2.6", "@wordpress/a11y": "file:../a11y", "@wordpress/compose": "file:../compose", diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 0dac37685281d9..979cb61eb232a0 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -118,6 +118,13 @@ const placementToAnimationOrigin = ( placement ) => { return x + ' ' + y; }; +const isTopBottomPlacement = ( placement ) => + placement.trim().startsWith( 'top' ) || + placement.trim().startsWith( 'bottom' ); +const hasBeforePlacement = ( placement ) => + placement.trim().startsWith( 'top' ) || + placement.trim().startsWith( 'left' ); + const Popover = ( { range, @@ -202,33 +209,53 @@ const Popover = ( const middleware = [ frameOffset || offset - ? offsetMiddleware( ( { placement: currentPlacement } ) => { + ? offsetMiddleware( ( middlewareArguments ) => { if ( ! frameOffset ) { return offset; } - - const isTopBottomPlacement = - currentPlacement.includes( 'top' ) || - currentPlacement.includes( 'bottom' ); - + const { + placement: currentPlacement, + rects: { + reference: referenceRect, + floating: floatingRect, + }, + } = middlewareArguments; // The main axis should represent the gap between the // floating element and the reference element. The cross // axis is always perpendicular to the main axis. - const mainAxis = isTopBottomPlacement ? 'y' : 'x'; + const mainAxis = isTopBottomPlacement( currentPlacement ) + ? 'y' + : 'x'; const crossAxis = mainAxis === 'x' ? 'y' : 'x'; // When the popover is before the reference, subtract the offset, // of the main axis else add it. - const hasBeforePlacement = - currentPlacement.includes( 'top' ) || - currentPlacement.includes( 'left' ); - const mainAxisModifier = hasBeforePlacement ? -1 : 1; + const mainAxisModifier = hasBeforePlacement( + currentPlacement + ) + ? -1 + : 1; const normalizedOffset = offset ? offset : 0; + let totalOffset = + frameOffset[ mainAxis ] + normalizedOffset; + const mainDimension = mainAxis === 'y' ? 'height' : 'width'; + if ( + // If the reference has no height we don't need to do anything. + referenceRect[ mainDimension ] && + referenceRect[ mainAxis ] < 0 && + ownerDocument.documentElement.scrollTop <= + referenceRect[ mainAxis ] + + normalizedOffset + + frameOffset[ mainAxis ] + ) { + totalOffset += + referenceRect[ mainDimension ] + + floatingRect[ mainDimension ]; + } + return { - mainAxis: - normalizedOffset + - frameOffset[ mainAxis ] * mainAxisModifier, + mainAxis: mainAxisModifier * totalOffset, crossAxis: frameOffset[ crossAxis ], }; } ) @@ -250,7 +277,48 @@ const Popover = ( __unstableShift ? shift( { crossAxis: true, - limiter: limitShift(), + limiter: limitShift( { + offset: ( middlewareArguments ) => { + // The following calculations are aimed at allowing the floating + // element to shift fully below the reference element, when the + // reference element is in a different document (i.e. an iFrame). + if ( ownerDocument === document ) { + return 0; + } + const { + placement: currentPlacement, + rects: { reference: referenceRect }, + } = middlewareArguments; + + // The main axis (according to floating UI's docs) is the "x" axis + // for 'top' and 'bottom' placements, and the "y" axis for 'left' + // and 'right' placements. + const mainAxis = isTopBottomPlacement( + currentPlacement + ) + ? 'x' + : 'y'; + const crossAxis = mainAxis === 'x' ? 'y' : 'x'; + + const crossAxisModifier = hasBeforePlacement( + currentPlacement + ) + ? -1 + : 1; + + return { + mainAxis: -Math.min( + frameOffset[ mainAxis ], + middlewareArguments[ mainAxis ] - + referenceRect[ mainAxis ] - + frameOffset[ mainAxis ] + ), + crossAxis: + crossAxisModifier * + frameOffset[ crossAxis ], + }; + }, + } ), padding: 1, // Necessary to avoid flickering at the edge of the viewport. } ) : undefined, From 3c923a9a467211de5863ba290ac805ca6b6f20f0 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 11 Aug 2022 21:44:07 +0300 Subject: [PATCH 2/2] only check `top` popovers --- packages/components/src/popover/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 979cb61eb232a0..0538c172728dad 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -241,6 +241,8 @@ const Popover = ( frameOffset[ mainAxis ] + normalizedOffset; const mainDimension = mainAxis === 'y' ? 'height' : 'width'; if ( + // TODO: does this make sense only for top positioned popovers? + currentPlacement.startsWith( 'top' ) && // If the reference has no height we don't need to do anything. referenceRect[ mainDimension ] && referenceRect[ mainAxis ] < 0 &&