@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
104 lines • 3.79 kB
JavaScript
/**
* @jsxRuntime classic
* @jsx jsx
*/
import { useCallback, useLayoutEffect, useState } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
import { css, jsx } from '@emotion/react';
import { useIntl } from 'react-intl';
import withAnalyticsContext from '@atlaskit/analytics-next/withAnalyticsContext';
import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
import PreferencesIcon from '@atlaskit/icon/core/customize';
import Tooltip from '@atlaskit/tooltip';
import { cardMessages } from '../../messages';
import Dropdown from './Dropdown';
import { StyledButton } from './StyledButton';
import { useLinkOverlayAnalyticsEvents } from './useLinkOverlayAnalyticsEvents';
const buttonWrapperStyles = css({
position: 'absolute',
zIndex: 100,
display: 'inline-flex',
top: '50%',
transform: 'translateY(-50%)',
background: "var(--ds-surface-raised, #FFFFFF)",
borderRadius: "var(--ds-radius-small, 3px)"
});
const showDropdownThresholdPx = 50;
export const OverlayButton = withAnalyticsContext()(({
editorView,
testId = 'link-configure-overlay-button',
targetElementPos = 0,
onDropdownChange,
onOpenLinkClick
}) => {
var _docNode$nodeSize;
const {
formatMessage
} = useIntl();
const configureLinkLabel = formatMessage(cardMessages.inlineConfigureLink);
const [showDropdown, setShowDropdown] = useState(false);
const {
fireActionClickEvent,
fireLinkClickEvent
} = useLinkOverlayAnalyticsEvents();
useLayoutEffect(() => {
var _domNode;
let domNode = editorView.nodeDOM(targetElementPos);
if (((_domNode = domNode) === null || _domNode === void 0 ? void 0 : _domNode.nodeType) === Node.TEXT_NODE) {
domNode = domNode.parentElement;
}
if (domNode instanceof HTMLElement) {
const {
width
} = domNode.getBoundingClientRect();
if (width < showDropdownThresholdPx) {
setShowDropdown(true);
}
}
}, [editorView, targetElementPos]);
const docNode = editorView.state.doc.nodeAt(targetElementPos);
const nodeEnd = targetElementPos + ((_docNode$nodeSize = docNode === null || docNode === void 0 ? void 0 : docNode.nodeSize) !== null && _docNode$nodeSize !== void 0 ? _docNode$nodeSize : 0);
const isText = docNode === null || docNode === void 0 ? void 0 : docNode.isText;
const handleConfigureClick = useCallback(() => {
const tr = editorView.state.tr;
if (isText) {
tr.setSelection(TextSelection.create(tr.doc, targetElementPos, Math.min(nodeEnd, tr.doc.nodeSize)));
} else {
tr.setSelection(NodeSelection.create(tr.doc, targetElementPos));
}
editorView.dispatch(tr);
}, [editorView, isText, targetElementPos, nodeEnd]);
const handleConfigureClickWithAnalytics = useCallback(() => {
fireActionClickEvent('configureLink');
fireLinkClickEvent();
handleConfigureClick();
}, [fireLinkClickEvent, handleConfigureClick, fireActionClickEvent]);
const {
from,
to
} = editorView.state.selection;
const isSelected = from === targetElementPos && to === nodeEnd;
if (!targetElementPos || isSelected) {
return null;
}
return jsx("span", {
css: buttonWrapperStyles,
"data-testid": testId
}, showDropdown ? jsx(Dropdown, {
testId: testId,
onConfigureClick: handleConfigureClick,
onOpenLinkClick: onOpenLinkClick,
onDropdownChange: onDropdownChange,
editorView: editorView
}) : jsx(Tooltip, {
content: configureLinkLabel,
hideTooltipOnClick: true,
testId: `${testId}-tooltip`
}, jsx(StyledButton, {
onClick: handleConfigureClickWithAnalytics,
iconBefore: jsx(PreferencesIcon, {
label: configureLinkLabel,
testId: `${testId}-configure-icon`
})
})));
});