From 979104cce30c6c93c157a45150166dd4c39b8f02 Mon Sep 17 00:00:00 2001
From: hextion <100ishundred@gmail.com>
Date: Thu, 19 Sep 2024 22:27:14 +0300
Subject: [PATCH] fix(popover): migrated to floating-ui
---
package.json | 1 +
.../src/__snapshots__/Component.test.tsx.snap | 6 -
packages/popover/package.json | 2 +-
packages/popover/src/Component.tsx | 170 +++++-------------
.../src/__snapshots__/Component.test.tsx.snap | 8 +-
.../popover/src/docs/Component.stories.mdx | 5 +-
packages/popover/src/index.module.css | 2 +
.../src/__snapshots__/component.test.tsx.snap | 8 +-
.../src/__snapshots__/Component.test.tsx.snap | 12 +-
yarn.lock | 27 +++
10 files changed, 89 insertions(+), 152 deletions(-)
diff --git a/package.json b/package.json
index f772ed4092..417da39007 100644
--- a/package.json
+++ b/package.json
@@ -65,6 +65,7 @@
"@alfalab/utils": "^1.15.2",
"@dnd-kit/core": "^6.0.7",
"@dnd-kit/sortable": "^7.0.2",
+ "@floating-ui/react-dom": "^2.1.2",
"@juggle/resize-observer": "^3.3.1",
"@maskito/core": "^1.7.0",
"@maskito/react": "^1.7.0",
diff --git a/packages/custom-picker-button/src/__snapshots__/Component.test.tsx.snap b/packages/custom-picker-button/src/__snapshots__/Component.test.tsx.snap
index f72dbce519..69a9fa7923 100644
--- a/packages/custom-picker-button/src/__snapshots__/Component.test.tsx.snap
+++ b/packages/custom-picker-button/src/__snapshots__/Component.test.tsx.snap
@@ -218,9 +218,7 @@ exports[`Snapshots tests should display opened correctly 2`] = `
>
void) | undefined>;
@@ -157,39 +155,12 @@ const CSS_TRANSITION_CLASS_NAMES = {
exitActive: styles.exitActive,
};
-const availableHieghtModifier = {
- name: 'availableHeight',
- enabled: true,
- phase: 'beforeWrite',
- requires: ['maxSize'],
- fn({
- state: {
- modifiersData,
- elements: { popper },
- },
- }: ModifierArguments
) {
- const { height } = modifiersData.maxSize;
-
- const content = popper.querySelector(`.${styles.scrollableContent}`) as HTMLElement;
-
- if (content && !content.style.maxHeight) {
- content.style.maxHeight = `${height}px`;
- }
- },
-};
-
-const DEFAULT_OFFSET = [0, 0];
+const DEFAULT_OFFSET: [number, number] = [0, 0];
// Минимальное расстояние стрелки до края поповера
const MIN_DISTANCE_TO_EDGE = 24;
-function getArrowPadding({
- placement,
-}: {
- popper: { height: number; width: number };
- reference: { height: number; width: number };
- placement: Position;
-}) {
+function getArrowPadding(placement: Position) {
if (placement === 'right-end' || placement === 'left-end') {
return { top: MIN_DISTANCE_TO_EDGE, right: 0, bottom: 0, left: 0 };
}
@@ -216,7 +187,7 @@ export const Popover = forwardRef(
getPortalContainer,
transition = DEFAULT_TRANSITION,
anchorElement: referenceElement,
- useAnchorWidth,
+ useAnchorWidth = false,
offset = DEFAULT_OFFSET,
withArrow = false,
withTransition = true,
@@ -235,103 +206,53 @@ export const Popover = forwardRef(
},
ref,
) => {
- const [popperElement, setPopperElement] = useState(null);
- const [arrowElement, setArrowElement] = useState(null);
- const resizeObserverRef = useRef(null);
-
- const updatePopperRef = useRef<(() => void) | null>(null);
-
+ const [arrowElement, setArrowElement] = useState(null);
const popperRef = useRef(null);
- const popperModifiers = useMemo(() => {
- const modifiers: PopperModifier[] = [{ name: 'offset', options: { offset } }];
+ const floatingMiddlewares = useMemo(() => {
+ const [crossAxis, mainAxis] = offset;
+ const middlewares = [offsetMiddleware({ mainAxis, crossAxis })];
if (withArrow) {
- modifiers.push({
- name: 'arrow',
- options: {
- element: arrowElement,
- padding: getArrowPadding,
- },
- });
+ middlewares.push(
+ arrow(
+ (state) => ({
+ element: arrowElement,
+ padding: getArrowPadding(state.placement),
+ }),
+ [arrowElement],
+ ),
+ );
}
- if (preventFlip) {
- modifiers.push({ name: 'flip', options: { fallbackPlacements: [] } });
+ if (preventFlip || fallbackPlacements || preventOverflow) {
+ middlewares.push(
+ flip({ flipAlignment: preventFlip, fallbackPlacements, mainAxis: false }),
+ );
}
- if (fallbackPlacements) {
- modifiers.push({ name: 'flip', options: { fallbackPlacements } });
- }
-
- if (preventOverflow) {
- modifiers.push({ name: 'preventOverflow', options: { mainAxis: false } });
- }
+ return middlewares;
+ }, [offset, withArrow, preventFlip, fallbackPlacements, preventOverflow, arrowElement]);
- if (availableHeight) {
- modifiers.push({ ...maxSize, options: {} });
- modifiers.push({ ...availableHieghtModifier, options: {} });
- }
-
- return modifiers;
- }, [
- offset,
- withArrow,
- preventFlip,
- fallbackPlacements,
- preventOverflow,
- availableHeight,
- arrowElement,
- ]);
-
- const {
- styles: popperStyles,
- attributes,
- update: updatePopper,
- } = usePopper(referenceElement, popperElement, {
+ const { floatingStyles, refs, middlewareData, placement } = useFloating({
placement: position,
- modifiers: popperModifiers,
+ elements: { reference: referenceElement },
+ whileElementsMounted: autoUpdate,
+ middleware: floatingMiddlewares,
});
- if (!(updatePopperRef.current === updatePopper)) {
- updatePopperRef.current = updatePopper;
- }
-
- if (isClient() && fnUtils.isNil(resizeObserverRef.current)) {
- const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
- const updatePopperCallback = () => {
- updatePopperRef.current?.();
- };
-
- resizeObserverRef.current = new ResizeObserver(updatePopperCallback);
- }
-
- useEffect(() => {
- if (fnUtils.isNil(popperElement)) return fnUtils.noop;
- resizeObserverRef.current?.observe(popperElement);
-
- return () => resizeObserverRef.current?.unobserve(popperElement);
- }, [popperElement]);
-
- useEffect(() => {
- if (!useAnchorWidth || fnUtils.isNil(referenceElement)) return fnUtils.noop;
- resizeObserverRef.current?.observe(referenceElement);
-
- return () => resizeObserverRef.current?.unobserve(referenceElement);
- }, [referenceElement, useAnchorWidth]);
-
const renderContent = (computedZIndex: number) => (
(
{children}
-
{withArrow && (
)}
diff --git a/packages/popover/src/__snapshots__/Component.test.tsx.snap b/packages/popover/src/__snapshots__/Component.test.tsx.snap
index 41c0b13d4c..5c09a87eaf 100644
--- a/packages/popover/src/__snapshots__/Component.test.tsx.snap
+++ b/packages/popover/src/__snapshots__/Component.test.tsx.snap
@@ -10,10 +10,8 @@ Object {
>
0;
+ const buttonLabel = text('buttonLabel', 'Popover');
return (
) : (
)}
diff --git a/packages/popover/src/index.module.css b/packages/popover/src/index.module.css
index eb2b9ae671..0a6c1ac1b2 100644
--- a/packages/popover/src/index.module.css
+++ b/packages/popover/src/index.module.css
@@ -26,6 +26,8 @@
.arrow {
z-index: 1;
+ position: absolute;
+ bottom: 100%;
}
.arrow:after {
diff --git a/packages/toast/src/__snapshots__/component.test.tsx.snap b/packages/toast/src/__snapshots__/component.test.tsx.snap
index fed0f19033..079d53f3d5 100644
--- a/packages/toast/src/__snapshots__/component.test.tsx.snap
+++ b/packages/toast/src/__snapshots__/component.test.tsx.snap
@@ -55,10 +55,8 @@ exports[`Toast Snapshots tests should math snapshot when prop \`anchorElement\`
>
@@ -197,10 +195,8 @@ Object {
>
diff --git a/yarn.lock b/yarn.lock
index 7aedd03ed6..12456a5e31 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2201,6 +2201,21 @@
dependencies:
"@floating-ui/utils" "^0.1.1"
+"@floating-ui/core@^1.6.0":
+ version "1.6.5"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.5.tgz#102335cac0d22035b04d70ca5ff092d2d1a26f2b"
+ integrity sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==
+ dependencies:
+ "@floating-ui/utils" "^0.2.5"
+
+"@floating-ui/dom@^1.0.0":
+ version "1.6.8"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.8.tgz#45e20532b6d8a061b356a4fb336022cf2609754d"
+ integrity sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.5"
+
"@floating-ui/dom@^1.0.1", "@floating-ui/dom@^1.3.0":
version "1.5.1"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.1.tgz#88b70defd002fe851f17b4a25efb2d3c04d7a8d7"
@@ -2216,11 +2231,23 @@
dependencies:
"@floating-ui/dom" "^1.3.0"
+"@floating-ui/react-dom@^2.1.2":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
+ integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
+ dependencies:
+ "@floating-ui/dom" "^1.0.0"
+
"@floating-ui/utils@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.1.tgz#1a5b1959a528e374e8037c4396c3e825d6cf4a83"
integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==
+"@floating-ui/utils@^0.2.5":
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.5.tgz#105c37d9d9620ce69b7f692a20c821bf1ad2cbf9"
+ integrity sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==
+
"@gar/promisify@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"