@atlaskit/editor-plugin-synced-block
Version:
SyncedBlock plugin for @atlaskit/editor-core
133 lines • 6.29 kB
JavaScript
/* SyncBlockLabel.tsx generated by @compiled/babel-plugin v3.0.2 */
import "./SyncBlockLabel.compiled.css";
import { ax, ix } from "@compiled/react/runtime";
import React, { useCallback, useMemo, useState } from 'react';
import { useIntl } from 'react-intl';
import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
import { SyncBlockLabelSharedCssClassName } from '@atlaskit/editor-common/sync-block';
import BlockSyncedIcon from '@atlaskit/icon-lab/core/block-synced';
import { Box, Text } from '@atlaskit/primitives/compiled';
import Tooltip from '@atlaskit/tooltip/Tooltip';
import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
import { formatElapsedTime } from './utils/time';
const SyncBlockLabelDataId = 'sync-block-label';
const styles = {
truncatedLabelText: "_11c8wadc _1reo15vq _18m915vq _syazazsu _1ul9idpf _1bto1l2s _o5721q9c",
unpublishedSuffix: "_11c8wadc _syazazsu _1o9zidpf _o5721q9c"
};
const SyncBlockLabelComponent = ({
contentUpdatedAt,
isSource,
localId,
title,
isUnsyncedBlock,
unpublishedInfo
}) => {
const intl = useIntl();
const {
formatMessage
} = intl;
const [tooltipContent, setTooltipContent] = useState(formatMessage(messages.defaultSyncBlockTooltip));
let tooltipMessage = formatMessage(messages.defaultSyncBlockTooltip);
if (title) {
tooltipMessage = formatMessage(messages.referenceSyncBlockTooltip, {
title
});
}
const updateTooltipContent = useCallback(() => {
let tooltipContent = tooltipMessage;
if (contentUpdatedAt) {
const elapsedTime = formatElapsedTime(contentUpdatedAt, intl);
tooltipContent = /*#__PURE__*/React.createElement("div", null, title ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.inverse",
weight: "bold"
}, formatMessage(messages.referenceSyncBlockSyncedFrom)), /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.inverse"
}, ' ', title)) : /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.inverse"
}, tooltipMessage), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.inverse",
weight: "bold"
}, formatMessage(messages.referenceSyncBlockLastEdited)), /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.inverse"
}, ' ', elapsedTime));
}
setTooltipContent(tooltipContent);
}, [contentUpdatedAt, formatMessage, intl, title, tooltipMessage]);
const ariaDescribedById = `sync-block-label-description-${localId}`;
const unpublishedParenthetical = unpublishedInfo ? formatMessage(messages.unpublishedInParentheses) : undefined;
const getLabelContent = useMemo(() => {
// The parenthetical carries a leading space so the accessible name and copied text read as
// "… (unpublished)". Flex trims it visually, and the label's own gap provides the spacing.
const renderUnpublishedLabel = label => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Box, {
as: "span",
xcss: styles.truncatedLabelText
}, label), /*#__PURE__*/React.createElement(Box, {
as: "span",
xcss: styles.unpublishedSuffix
}, ` ${unpublishedParenthetical}`));
const renderPlainLabel = label => unpublishedParenthetical ? renderUnpublishedLabel(label) : /*#__PURE__*/React.createElement(Text, {
size: "small",
color: "color.text.subtle"
}, label);
const renderTruncatingTitle = label => unpublishedParenthetical ? renderUnpublishedLabel(label) : /*#__PURE__*/React.createElement(Text, {
maxLines: 1,
size: "small",
color: "color.text.subtle"
}, label);
if (isUnsyncedBlock) {
return renderPlainLabel(formatMessage(messages.unsyncedBlockLabel));
}
if (isSource) {
return renderPlainLabel(formatMessage(messages.sourceSyncedBlockLabel));
}
if (!title) {
return renderPlainLabel(formatMessage(messages.syncedBlockLabel));
}
return renderTruncatingTitle(title);
}, [formatMessage, isSource, isUnsyncedBlock, title, unpublishedParenthetical]);
const unpublishedTooltipLabel = unpublishedInfo ? formatMessage(unpublishedInfo.variant === 'source' ? messages.unpublishedSourceAvailabilityTooltip : messages.unpublishedLocalReferenceAvailabilityTooltip, {
sourceType: unpublishedInfo.sourceType
}) : undefined;
const primaryLabel = /*#__PURE__*/React.createElement("div", {
"data-testid": SyncBlockLabelDataId
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
,
className: SyncBlockLabelSharedCssClassName.labelClassName,
"aria-describedby": isSource || isUnsyncedBlock ? undefined : ariaDescribedById
}, /*#__PURE__*/React.createElement(BlockSyncedIcon, {
color: "var(--ds-icon-subtle, #505258)",
size: "small",
label: ""
}), getLabelContent);
const referenceDescription = !isSource && !isUnsyncedBlock && /*#__PURE__*/React.createElement(VisuallyHidden, {
id: ariaDescribedById
}, tooltipMessage);
if (unpublishedTooltipLabel) {
return /*#__PURE__*/React.createElement(Tooltip, {
position: "top",
content: unpublishedTooltipLabel
}, primaryLabel, referenceDescription);
}
if (isSource || isUnsyncedBlock) {
return primaryLabel;
}
return /*#__PURE__*/React.createElement(Tooltip, {
position: "top",
content: tooltipContent
// workaround because tooltip adds aria-describedby with a new id every time the tooltip is opened
// this causes an infinite rerender loop because of the forwardRef from the node view we are inside in bodiedSyncBlock
// tooltip content is available for screen readers in visually hidden content after the label
,
isScreenReaderAnnouncementDisabled: true
// using this to ensure that the 'last edited' time is updated when the tooltip is opened
,
onShow: updateTooltipContent
}, primaryLabel, referenceDescription);
};
export const SyncBlockLabel = /*#__PURE__*/React.memo(SyncBlockLabelComponent);