[MM-60261] Replace "useTooltip" of "components/common/hooks/useTooltip" to WithTooltip (#28037)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
15c9b15f67
Коммит
58d92742b4
@@ -1,148 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import {useHover, useInteractions, useFloating, arrow, offset, autoPlacement} from '@floating-ui/react';
|
|
||||||
import type {Strategy, Placement, ReferenceType} from '@floating-ui/react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import type {ReactNode, HTMLProps} from 'react';
|
|
||||||
import React, {useState, useRef} from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
|
|
||||||
import {Constants} from 'utils/constants';
|
|
||||||
|
|
||||||
interface TooltipOptions {
|
|
||||||
message: ReactNode;
|
|
||||||
strategy?: Strategy;
|
|
||||||
placement: Placement;
|
|
||||||
allowedPlacements?: Placement[];
|
|
||||||
hoverDelay?: Exclude<Parameters<typeof useHover>[1], undefined>['delay'];
|
|
||||||
zIndex?: number;
|
|
||||||
mountPoint?: string | Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultOptions: Required<Pick<TooltipOptions, 'strategy' | 'hoverDelay' | 'zIndex' | 'mountPoint'>> = {
|
|
||||||
strategy: 'fixed',
|
|
||||||
hoverDelay: {
|
|
||||||
open: Constants.OVERLAY_TIME_DELAY,
|
|
||||||
close: 0,
|
|
||||||
},
|
|
||||||
zIndex: 1,
|
|
||||||
mountPoint: 'root',
|
|
||||||
};
|
|
||||||
|
|
||||||
const transitionTime = 150;
|
|
||||||
|
|
||||||
interface TooltipReturn {
|
|
||||||
setReference: (node: ReferenceType | null) => void;
|
|
||||||
getReferenceProps: (userProps?: HTMLProps<Element>) => Record<string, unknown>;
|
|
||||||
tooltip: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function useTooltip(options: TooltipOptions): TooltipReturn {
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const transition = useRef<NodeJS.Timeout>(null);
|
|
||||||
const arrowRef = useRef(null);
|
|
||||||
const effectiveStrategy = options.strategy || defaultOptions.strategy;
|
|
||||||
const effectiveMountpoint = options.mountPoint || defaultOptions.mountPoint;
|
|
||||||
const effectiveAllowedPlacements = options.allowedPlacements ?? [options.placement];
|
|
||||||
const {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
strategy,
|
|
||||||
placement,
|
|
||||||
refs: {
|
|
||||||
setReference,
|
|
||||||
setFloating,
|
|
||||||
},
|
|
||||||
middlewareData: {
|
|
||||||
arrow: {
|
|
||||||
x: arrowX,
|
|
||||||
y: arrowY,
|
|
||||||
} = {},
|
|
||||||
},
|
|
||||||
context,
|
|
||||||
} = useFloating({
|
|
||||||
open,
|
|
||||||
onOpenChange: (nowOpen) => {
|
|
||||||
if (transition.current) {
|
|
||||||
clearTimeout(transition.current);
|
|
||||||
}
|
|
||||||
if (nowOpen) {
|
|
||||||
setOpen(nowOpen);
|
|
||||||
setVisible(true);
|
|
||||||
} else {
|
|
||||||
setVisible(false);
|
|
||||||
setTimeout(() => {
|
|
||||||
setOpen(nowOpen);
|
|
||||||
}, transitionTime);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
middleware: [
|
|
||||||
autoPlacement({
|
|
||||||
allowedPlacements: effectiveAllowedPlacements,
|
|
||||||
autoAlignment: false,
|
|
||||||
}),
|
|
||||||
offset(10),
|
|
||||||
arrow({
|
|
||||||
element: arrowRef,
|
|
||||||
padding: 4,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
placement: options.placement,
|
|
||||||
strategy: effectiveStrategy,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {getReferenceProps, getFloatingProps} = useInteractions([
|
|
||||||
useHover(
|
|
||||||
context,
|
|
||||||
{
|
|
||||||
delay: options.hoverDelay || defaultOptions.hoverDelay,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const content = (
|
|
||||||
<div
|
|
||||||
{...getFloatingProps({
|
|
||||||
ref: setFloating,
|
|
||||||
className: classNames(
|
|
||||||
'floating-ui-tooltip',
|
|
||||||
{
|
|
||||||
'floating-ui-tooltip--visible': visible,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
style: {
|
|
||||||
position: strategy,
|
|
||||||
top: y ?? 0,
|
|
||||||
left: x ?? 0,
|
|
||||||
zIndex: typeof options.zIndex === 'number' ? options.zIndex : defaultOptions.zIndex,
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{options.message}
|
|
||||||
<div
|
|
||||||
ref={arrowRef}
|
|
||||||
className='floating-ui-tooltip-arrow'
|
|
||||||
style={placement === 'top' ? {left: arrowX, top: arrowY} : {left: '-4px', top: arrowY}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
let tooltip: ReactNode = false;
|
|
||||||
|
|
||||||
if (open) {
|
|
||||||
if (effectiveStrategy === 'fixed') {
|
|
||||||
tooltip = ReactDOM.createPortal(
|
|
||||||
content,
|
|
||||||
typeof effectiveMountpoint === 'string' ? document.getElementById(effectiveMountpoint) as Element : effectiveMountpoint,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setReference,
|
|
||||||
getReferenceProps,
|
|
||||||
tooltip,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -10,6 +10,7 @@ import {asGBString} from 'utils/limits';
|
|||||||
|
|
||||||
export default function ArchivedTooltip() {
|
export default function ArchivedTooltip() {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='post-image__archived-tooltip-title'>
|
<div className='post-image__archived-tooltip-title'>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import type {FileInfo} from '@mattermost/types/files';
|
|||||||
|
|
||||||
import {getFileThumbnailUrl, getFileUrl} from 'mattermost-redux/utils/file_utils';
|
import {getFileThumbnailUrl, getFileUrl} from 'mattermost-redux/utils/file_utils';
|
||||||
|
|
||||||
import useTooltip from 'components/common/hooks/useTooltip';
|
|
||||||
import GetPublicModal from 'components/get_public_link_modal';
|
import GetPublicModal from 'components/get_public_link_modal';
|
||||||
import Menu from 'components/widgets/menu/menu';
|
import Menu from 'components/widgets/menu/menu';
|
||||||
import MenuWrapper from 'components/widgets/menu/menu_wrapper';
|
import MenuWrapper from 'components/widgets/menu/menu_wrapper';
|
||||||
@@ -65,16 +64,6 @@ export default function FileAttachment(props: Props) {
|
|||||||
const [keepOpen, setKeepOpen] = useState(false);
|
const [keepOpen, setKeepOpen] = useState(false);
|
||||||
const [openUp, setOpenUp] = useState(false);
|
const [openUp, setOpenUp] = useState(false);
|
||||||
|
|
||||||
const {
|
|
||||||
setReference,
|
|
||||||
getReferenceProps,
|
|
||||||
tooltip: archivedTooltip,
|
|
||||||
} = useTooltip({
|
|
||||||
message: <ArchivedTooltip/>,
|
|
||||||
placement: 'right',
|
|
||||||
allowedPlacements: ['right', 'top'],
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonRef = useRef<HTMLButtonElement | null>(null);
|
const buttonRef = useRef<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
const handleImageLoaded = () => {
|
const handleImageLoaded = () => {
|
||||||
@@ -368,18 +357,19 @@ export default function FileAttachment(props: Props) {
|
|||||||
</span>);
|
</span>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content =
|
return (
|
||||||
(
|
<WithTooltip
|
||||||
|
id='fileAttachmentArchivedTooltip'
|
||||||
|
placement='top'
|
||||||
|
title={<ArchivedTooltip/>}
|
||||||
|
disabled={!fileInfo.archived}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
ref={fileInfo.archived ? setReference : undefined}
|
className={classNames([
|
||||||
{...(fileInfo.archived ? getReferenceProps() : {})}
|
'post-image__column',
|
||||||
className={
|
{'keep-open': keepOpen},
|
||||||
classNames([
|
{'post-image__column--archived': fileInfo.archived},
|
||||||
'post-image__column',
|
])}
|
||||||
{'keep-open': keepOpen},
|
|
||||||
{'post-image__column--archived': fileInfo.archived},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{fileThumbnail}
|
{fileThumbnail}
|
||||||
<div className='post-image__details'>
|
<div className='post-image__details'>
|
||||||
@@ -388,15 +378,6 @@ export default function FileAttachment(props: Props) {
|
|||||||
{filenameOverlay}
|
{filenameOverlay}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
</WithTooltip>
|
||||||
|
);
|
||||||
if (fileInfo.archived) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{content}
|
|
||||||
{archivedTooltip}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {AlertCircleOutlineIcon} from '@mattermost/compass-icons/components';
|
|||||||
import type {PostPriorityMetadata} from '@mattermost/types/posts';
|
import type {PostPriorityMetadata} from '@mattermost/types/posts';
|
||||||
|
|
||||||
import {IconContainer} from 'components/advanced_text_editor/formatting_bar/formatting_icon';
|
import {IconContainer} from 'components/advanced_text_editor/formatting_bar/formatting_icon';
|
||||||
import useTooltip from 'components/common/hooks/useTooltip';
|
import WithTooltip from 'components/with_tooltip';
|
||||||
|
|
||||||
import PostPriorityPicker from './post_priority_picker';
|
import PostPriorityPicker from './post_priority_picker';
|
||||||
|
|
||||||
@@ -42,16 +42,6 @@ function PostPriorityPickerOverlay({
|
|||||||
const [pickerOpen, setPickerOpen] = useState(false);
|
const [pickerOpen, setPickerOpen] = useState(false);
|
||||||
const {formatMessage} = useIntl();
|
const {formatMessage} = useIntl();
|
||||||
|
|
||||||
const messagePriority = formatMessage({id: 'shortcuts.msgs.formatting_bar.post_priority', defaultMessage: 'Message priority'});
|
|
||||||
const {
|
|
||||||
setReference: setTooltipRef,
|
|
||||||
getReferenceProps: getTooltipReferenceProps,
|
|
||||||
tooltip,
|
|
||||||
} = useTooltip({
|
|
||||||
placement: 'top',
|
|
||||||
message: messagePriority,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
setPickerOpen(false);
|
setPickerOpen(false);
|
||||||
onClose();
|
onClose();
|
||||||
@@ -91,11 +81,14 @@ function PostPriorityPickerOverlay({
|
|||||||
useRole(pickerContext),
|
useRole(pickerContext),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const messagePriority = formatMessage({id: 'shortcuts.msgs.formatting_bar.post_priority', defaultMessage: 'Message priority'});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<WithTooltip
|
||||||
ref={setTooltipRef}
|
id='postPriorityPickerOverlayTooltip'
|
||||||
{...getTooltipReferenceProps()}
|
placement='top'
|
||||||
|
title={messagePriority}
|
||||||
>
|
>
|
||||||
<IconContainer
|
<IconContainer
|
||||||
id='messagePriority'
|
id='messagePriority'
|
||||||
@@ -111,7 +104,7 @@ function PostPriorityPickerOverlay({
|
|||||||
color='currentColor'
|
color='currentColor'
|
||||||
/>
|
/>
|
||||||
</IconContainer>
|
</IconContainer>
|
||||||
</div>
|
</WithTooltip>
|
||||||
<FloatingPortal id='root-portal'>
|
<FloatingPortal id='root-portal'>
|
||||||
{pickerOpen && (
|
{pickerOpen && (
|
||||||
<FloatingFocusManager
|
<FloatingFocusManager
|
||||||
@@ -140,7 +133,6 @@ function PostPriorityPickerOverlay({
|
|||||||
</FloatingFocusManager>
|
</FloatingFocusManager>
|
||||||
)}
|
)}
|
||||||
</FloatingPortal>
|
</FloatingPortal>
|
||||||
{!pickerOpen && tooltip}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user