MM-62382/MM-63615 Remove explicit reference to react-popper and remaining references to popper.js (#30743)

* Replace usage of react-popper in onboarding with floating-ui

* Remove direct dependency on react-popper

Compass components still depend on react-popper, but none of the web app
code does any more.

* Remove direct dependency on popper.js

* Remove unneeded dependency on @types/bootstrap and remaining indirect dependency on popper.js
Этот коммит содержится в:
Harrison Healey
2025-04-22 15:35:21 -04:00
коммит произвёл GitHub
родитель 981d1d869a
Коммит 32ce2f13bb
4 изменённых файлов: 26 добавлений и 57 удалений

Просмотреть файл

@@ -56,7 +56,6 @@
"moment-timezone": "0.5.38", "moment-timezone": "0.5.38",
"p-queue": "7.3.0", "p-queue": "7.3.0",
"pdfjs-dist": "4.4.168", "pdfjs-dist": "4.4.168",
"popper.js": "1.16.1",
"process": "0.11.10", "process": "0.11.10",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "17.0.2", "react": "17.0.2",
@@ -71,7 +70,6 @@
"react-intl": "*", "react-intl": "*",
"react-is": "17.0.2", "react-is": "17.0.2",
"react-overlays": "0.9.3", "react-overlays": "0.9.3",
"react-popper": "2.3.0",
"react-redux": "7.2.4", "react-redux": "7.2.4",
"react-router-dom": "5.3.4", "react-router-dom": "5.3.4",
"react-select": "5.9.0", "react-select": "5.9.0",
@@ -110,7 +108,6 @@
"@testing-library/react": "12.1.4", "@testing-library/react": "12.1.4",
"@testing-library/react-hooks": "8.0.1", "@testing-library/react-hooks": "8.0.1",
"@testing-library/user-event": "13.5.0", "@testing-library/user-event": "13.5.0",
"@types/bootstrap": "4.5.0",
"@types/country-list": "2.1.0", "@types/country-list": "2.1.0",
"@types/enzyme": "3.10.11", "@types/enzyme": "3.10.11",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",

Просмотреть файл

@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useRef, useCallback, useEffect, useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {FormattedMessage, useIntl} from 'react-intl'; import {FormattedMessage, useIntl} from 'react-intl';
import {useDispatch, useSelector} from 'react-redux'; import {useDispatch, useSelector} from 'react-redux';
import styled, {css} from 'styled-components'; import styled, {css} from 'styled-components';
@@ -137,7 +137,7 @@ const OnBoardingTaskList = (): JSX.Element | null => {
}, []); }, []);
const open = useSelector(((state: GlobalState) => getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_OPEN))); const open = useSelector(((state: GlobalState) => getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_TASK_LIST_OPEN)));
const trigger = useRef<HTMLButtonElement>(null); const [trigger, setTrigger] = useState<HTMLButtonElement | null>(null);
const dispatch = useDispatch(); const dispatch = useDispatch();
const currentUserId = useSelector(getCurrentUserId); const currentUserId = useSelector(getCurrentUserId);
const handleTaskTrigger = useHandleOnBoardingTaskTrigger(); const handleTaskTrigger = useHandleOnBoardingTaskTrigger();
@@ -253,7 +253,7 @@ const OnBoardingTaskList = (): JSX.Element | null => {
<CompletedAnimation completed={showAnimation}/> <CompletedAnimation completed={showAnimation}/>
<Button <Button
onClick={toggleTaskList} onClick={toggleTaskList}
ref={trigger} ref={(element) => setTrigger(element)}
open={open} open={open}
data-cy='onboarding-task-list-action-button' data-cy='onboarding-task-list-action-button'
aria-label={formatMessage({id: 'onboardingTask.checklist.start_onboarding_process', defaultMessage: 'Start the onboarding process.'})} aria-label={formatMessage({id: 'onboardingTask.checklist.start_onboarding_process', defaultMessage: 'Start the onboarding process.'})}

Просмотреть файл

@@ -1,10 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import type {Placement} from 'popper.js'; import type {Placement} from '@floating-ui/react-dom';
import React from 'react'; import {useFloating, offset as floatingOffset, autoUpdate} from '@floating-ui/react-dom';
import type {RefObject, CSSProperties} from 'react'; import React, {useLayoutEffect} from 'react';
import {usePopper} from 'react-popper';
import {CSSTransition} from 'react-transition-group'; import {CSSTransition} from 'react-transition-group';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -49,12 +48,12 @@ const Overlay = styled.div`
`; `;
interface TaskListPopoverProps { interface TaskListPopoverProps {
trigger: RefObject<HTMLButtonElement>; trigger: HTMLButtonElement | null;
isVisible: boolean; isVisible: boolean;
placement?: Placement; placement?: Placement;
offset?: [number | null | undefined, number | null | undefined]; offset?: [number, number];
children?: React.ReactNode; children: React.ReactNode;
onClick?: () => void; onClick: () => void;
} }
export const TaskListPopover = ({ export const TaskListPopover = ({
@@ -65,29 +64,26 @@ export const TaskListPopover = ({
children, children,
onClick, onClick,
}: TaskListPopoverProps): JSX.Element | null => { }: TaskListPopoverProps): JSX.Element | null => {
const [popperElement, setPopperElement] = const {x, y, strategy, refs: {setReference, setFloating}} = useFloating({
React.useState<HTMLDivElement | null>(null);
const {
styles: {popper},
attributes,
} = usePopper(trigger.current, popperElement, {
placement, placement,
modifiers: [ middleware: [floatingOffset({
{ mainAxis: offset[1],
name: 'offset', crossAxis: offset[0],
options: { })],
offset, whileElementsMounted: autoUpdate,
},
},
],
}); });
useLayoutEffect(() => {
setReference(trigger);
}, [setReference, trigger]);
const style = { const style = {
container: { container: {
...popper, position: strategy,
top: y ?? 0,
left: x ?? 0,
zIndex: isVisible ? 100 : -1, zIndex: isVisible ? 100 : -1,
position: 'fixed', },
} as CSSProperties,
}; };
return ( return (
<> <>
@@ -103,9 +99,8 @@ export const TaskListPopover = ({
/> />
</CSSTransition> </CSSTransition>
<div <div
ref={setPopperElement} ref={setFloating}
style={style.container} style={style.container}
{...attributes.popper}
> >
{children} {children}
</div> </div>

23
webapp/package-lock.json сгенерированный
Просмотреть файл

@@ -110,7 +110,6 @@
"moment-timezone": "0.5.38", "moment-timezone": "0.5.38",
"p-queue": "7.3.0", "p-queue": "7.3.0",
"pdfjs-dist": "4.4.168", "pdfjs-dist": "4.4.168",
"popper.js": "1.16.1",
"process": "0.11.10", "process": "0.11.10",
"prop-types": "15.8.1", "prop-types": "15.8.1",
"react": "17.0.2", "react": "17.0.2",
@@ -125,7 +124,6 @@
"react-intl": "*", "react-intl": "*",
"react-is": "17.0.2", "react-is": "17.0.2",
"react-overlays": "0.9.3", "react-overlays": "0.9.3",
"react-popper": "2.3.0",
"react-redux": "7.2.4", "react-redux": "7.2.4",
"react-router-dom": "5.3.4", "react-router-dom": "5.3.4",
"react-select": "5.9.0", "react-select": "5.9.0",
@@ -164,7 +162,6 @@
"@testing-library/react": "12.1.4", "@testing-library/react": "12.1.4",
"@testing-library/react-hooks": "8.0.1", "@testing-library/react-hooks": "8.0.1",
"@testing-library/user-event": "13.5.0", "@testing-library/user-event": "13.5.0",
"@types/bootstrap": "4.5.0",
"@types/country-list": "2.1.0", "@types/country-list": "2.1.0",
"@types/enzyme": "3.10.11", "@types/enzyme": "3.10.11",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
@@ -6676,16 +6673,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/bootstrap": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-4.5.0.tgz",
"integrity": "sha512-AWu7D+Cduyic75YptSRiXuCIy1c3SsmYk/9ixS68Ft2eAgg2wRj5U2M+7PK5zpakk4gTgfrWHeGxJqkSjttwyQ==",
"dev": true,
"dependencies": {
"@types/jquery": "*",
"popper.js": "^1.14.1"
}
},
"node_modules/@types/cheerio": { "node_modules/@types/cheerio": {
"version": "0.22.35", "version": "0.22.35",
"resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.35.tgz", "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.35.tgz",
@@ -22486,16 +22473,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/possible-typed-array-names": { "node_modules/possible-typed-array-names": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",