UNPKG

@atlaskit/editor-plugin-card

Version:

Card plugin for @atlaskit/editor-core

275 lines (272 loc) 12.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _react2 = require("@emotion/react"); var _debounce = _interopRequireDefault(require("lodash/debounce")); var _reactIntlNext = require("react-intl-next"); var _messages = require("@atlaskit/editor-common/messages"); var _whitespace = require("@atlaskit/editor-common/whitespace"); var _customize = _interopRequireDefault(require("@atlaskit/icon/core/customize")); var _utils = require("./utils"); var _excluded = ["children", "isSelected", "isVisible", "testId", "url"]; /* eslint-disable @atlaskit/design-system/no-nested-styles */ /* eslint-disable @atlaskit/design-system/prefer-primitives */ /** * @jsxRuntime classic * @jsx jsx */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } var DEBOUNCE_IN_MS = 5; var ESTIMATED_MIN_WIDTH_IN_PX = 16; var PADDING_IN_PX = 4; var ICON_WIDTH_IN_PX = 14; var ICON_AND_LABEL_CLASSNAME = 'ak-editor-card-overlay-icon-and-label'; var OVERLAY_LABEL_CLASSNAME = 'ak-editor-card-overlay-label'; var OVERLAY_GRADIENT_CLASSNAME = 'ak-editor-card-overlay-gradient'; var OVERLAY_MARKER_CLASSNAME = 'ak-editor-card-overlay-marker'; var TEXT_NODE_SELECTOR = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].join(','); var SMART_LINK_BACKGROUND_COLOR = "var(--ds-surface-raised, #FFFFFF)"; var SMART_LINK_ACTIVE_COLOR = "var(--ds-background-selected, #E9F2FE)"; var getGradientWithColor = function getGradientWithColor(color) { return "linear-gradient(270deg, ".concat(color, " 0%, rgba(255, 255, 255, 0.00) 100%)"); }; var containerStyles = (0, _react2.css)({ position: 'relative', // eslint-disable-next-line @atlaskit/design-system/use-tokens-typography lineHeight: 'normal', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-selectors -- Ignored via go/DSP-18766 ':active': (0, _defineProperty2.default)((0, _defineProperty2.default)({}, ".".concat(ICON_AND_LABEL_CLASSNAME), { background: SMART_LINK_ACTIVE_COLOR }), ".".concat(OVERLAY_GRADIENT_CLASSNAME), { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 background: getGradientWithColor(SMART_LINK_ACTIVE_COLOR) }) }); var overlayStyles = (0, _react2.css)({ // Set default styling to be invisible but available in dom for width calculation. visibility: 'hidden', position: 'absolute', display: 'inline-flex', justifyContent: 'flex-end', alignItems: 'center', verticalAlign: 'text-top', height: '1lh', '@supports not (height: 1lh)': { height: '1.2em' }, overflow: 'hidden', // EDM-1717: box-shadow Safari fix bring load wrapper zIndex to 1 zIndex: 2, pointerEvents: 'none' }); var showOverlayStyles = (0, _react2.css)({ position: 'relative', visibility: 'visible' }); var iconStyles = (0, _react2.css)({ // Position icon in the middle // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766 span: { display: 'flex' } }); var labelStyles = (0, _react2.css)({ font: "var(--ds-font-body, normal 400 14px/20px \"Atlassian Sans\", ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)", fontWeight: "var(--ds-font-weight-semibold, 600)", width: 'max-content' }); var iconAndLabelStyles = (0, _react2.css)({ display: 'flex', alignItems: 'center', height: '100%', gap: "var(--ds-space-050, 4px)", paddingRight: "var(--ds-space-050, 4px)", // Margin to avoid the background covering the link border marginRight: "var(--ds-space-025, 2px)", background: SMART_LINK_BACKGROUND_COLOR, color: "var(--ds-text-subtlest, #6B6E76)" }); var overflowingContainerStyles = (0, _react2.css)({ display: 'flex', flexDirection: 'row-reverse', alignItems: 'center', width: 'max-content', height: '100%' }); var gradientStyles = (0, _react2.css)({ width: '2.5rem', height: '100%', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- Ignored via go/DSP-18766 background: getGradientWithColor(SMART_LINK_BACKGROUND_COLOR) }); var InlineCardOverlay = function InlineCardOverlay(_ref) { var children = _ref.children, _ref$isSelected = _ref.isSelected, isSelected = _ref$isSelected === void 0 ? false : _ref$isSelected, _ref$isVisible = _ref.isVisible, isVisible = _ref$isVisible === void 0 ? false : _ref$isVisible, _ref$testId = _ref.testId, testId = _ref$testId === void 0 ? 'inline-card-overlay' : _ref$testId, url = _ref.url, props = (0, _objectWithoutProperties2.default)(_ref, _excluded); var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), showOverlay = _useState2[0], setShowOverlay = _useState2[1]; var _useState3 = (0, _react.useState)(true), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), showLabel = _useState4[0], setShowLabel = _useState4[1]; var _useState5 = (0, _react.useState)(undefined), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), availableWidth = _useState6[0], setAvailableWidth = _useState6[1]; var maxOverlayWidth = (0, _react.useRef)(0); var minOverlayWidth = (0, _react.useRef)(ESTIMATED_MIN_WIDTH_IN_PX); var parentWidth = (0, _react.useRef)(0); var containerRef = (0, _react.useRef)(null); var setVisibility = (0, _react.useCallback)(function () { if (!containerRef.current || !maxOverlayWidth.current) { return; } var marker = (0, _utils.getChildElement)(containerRef, ".".concat(OVERLAY_MARKER_CLASSNAME)); if (!marker) { return; } try { var oneLine = (0, _utils.isOneLine)(containerRef.current, marker); // Get the width of the available space to display overlay. // This is the width of the inline link itself. If the inline // is wrapped to the next line, this is width of the last line. var _availableWidth = (0, _utils.getInlineCardAvailableWidth)(containerRef.current, marker) - PADDING_IN_PX - ( // Always leave at least the icon visible oneLine ? ICON_WIDTH_IN_PX + PADDING_IN_PX : 0); setAvailableWidth(_availableWidth); var canShowLabel = _availableWidth > maxOverlayWidth.current; setShowLabel(canShowLabel); var canShowOverlay = _availableWidth > minOverlayWidth.current && !isSelected; setShowOverlay(canShowOverlay); } catch (_unused) { // If something goes wrong, hide the overlay all together. setShowOverlay(false); } }, [isSelected]); (0, _react.useLayoutEffect)(function () { // Using useLayoutEffect here. // 1) We want all to be able to determine whether to display label before // the overlay becomes visible. // 2) We need to wait for the refs to be assigned to be able to do determine // the width of the overlay. if (!containerRef.current) { return; } // This should run only once if (!maxOverlayWidth.current) { var iconAndLabel = (0, _utils.getChildElement)(containerRef, ".".concat(ICON_AND_LABEL_CLASSNAME)); var _label = (0, _utils.getChildElement)(containerRef, ".".concat(OVERLAY_LABEL_CLASSNAME)); if (iconAndLabel && _label) { // Set overlay max (label + icon) and min (icon only) width. var _getOverlayWidths = (0, _utils.getOverlayWidths)(iconAndLabel, _label), max = _getOverlayWidths.max, min = _getOverlayWidths.min; maxOverlayWidth.current = max; minOverlayWidth.current = min; } } if (isVisible) { setVisibility(); } }, [setVisibility, isVisible]); (0, _react.useEffect)(function () { var _containerRef$current; // Find the closest block parent to observe size change var parent = containerRef === null || containerRef === void 0 || (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.closest(TEXT_NODE_SELECTOR); if (!parent) { return; } var updateOverlay = (0, _debounce.default)(function (entries) { var _entries$; if (!isVisible) { return; } var size = entries === null || entries === void 0 || (_entries$ = entries[0]) === null || _entries$ === void 0 || (_entries$ = _entries$.contentBoxSize) === null || _entries$ === void 0 || (_entries$ = _entries$[0]) === null || _entries$ === void 0 ? void 0 : _entries$.inlineSize; if (!size) { return; } if (!parentWidth.current) { parentWidth.current = size; } if (parentWidth.current === size) { return; } parentWidth.current = size; setVisibility(); }, DEBOUNCE_IN_MS); var observer = new ResizeObserver(updateOverlay); observer.observe(parent); return function () { observer.disconnect(); }; }, [isVisible, setVisibility]); var intl = (0, _reactIntlNext.useIntl)(); var label = intl.formatMessage(_messages.cardMessages.inlineOverlay); return ( // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading (0, _react2.jsx)("span", (0, _extends2.default)({}, props, { css: containerStyles, ref: containerRef }), children, isVisible && (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("span", { "aria-hidden": "true", className: OVERLAY_MARKER_CLASSNAME }, _whitespace.ZERO_WIDTH_JOINER), (0, _react2.jsx)("a", { css: [overlayStyles, showOverlay && showOverlayStyles], style: { // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview marginLeft: availableWidth && -availableWidth, width: availableWidth }, "data-testid": testId, href: url, onClick: function onClick(e) { return e.preventDefault(); }, tabIndex: -1 }, (0, _react2.jsx)("span", { css: overflowingContainerStyles }, (0, _react2.jsx)("span", { css: iconAndLabelStyles // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: ICON_AND_LABEL_CLASSNAME }, (0, _react2.jsx)("span", { css: iconStyles }, (0, _react2.jsx)(_customize.default, { label: label, testId: "".concat(testId, "-icon") })), showLabel && (0, _react2.jsx)("span", { css: labelStyles // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: OVERLAY_LABEL_CLASSNAME, "data-testid": "".concat(testId, "-label") }, label)), (0, _react2.jsx)("span", { css: gradientStyles // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: OVERLAY_GRADIENT_CLASSNAME, "data-testid": "".concat(testId, "-gradient") }))))) ); }; var _default = exports.default = InlineCardOverlay;