UNPKG

@atlaskit/editor-plugin-card

Version:

Card plugin for @atlaskit/editor-core

305 lines (303 loc) • 18.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.InlineCardWithAwareness = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _enums = require("@atlaskit/editor-common/analytics/types/enums"); var _HoverLinkOverlay = _interopRequireDefault(require("@atlaskit/editor-common/HoverLinkOverlay")); var _useSharedPluginStateWithSelector = require("@atlaskit/editor-common/useSharedPluginStateWithSelector"); var _state = require("@atlaskit/editor-prosemirror/state"); var _extractSmartLinkEmbed = require("@atlaskit/link-extractors/extract-smart-link-embed"); var _isWithinPreviewPanelIframe = require("@atlaskit/linking-common/utils/is-within-preview-panel-iframe"); var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled"); var _smartCard = require("@atlaskit/smart-card"); var _useSmartLinkDestinationUrl = require("@atlaskit/smart-card/hook/use-smart-link-destination-url"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _actions = require("../pm-plugins/actions"); var _pluginKey = require("../pm-plugins/plugin-key"); var _AwarenessWrapper = require("../ui/AwarenessWrapper"); var _PreviewInvoker = require("../ui/preview/PreviewInvoker"); var _inlineCardBase = require("./inlineCardBase"); 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); } // Module scope so the stored callback's closure chain cannot reach the // component scope (getPos, node, view) via V8 context sharing. var createRemoveOverlay = function createRemoveOverlay(setIsInsertedRef) { return function () { var _setIsInsertedRef$cur; return (_setIsInsertedRef$cur = setIsInsertedRef.current) === null || _setIsInsertedRef$cur === void 0 ? void 0 : _setIsInsertedRef$cur.call(setIsInsertedRef, false); }; }; var selector = function selector(states) { var _states$editorViewMod, _states$selectionStat; return { mode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode, selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection }; }; var InlineCardWithAwareness = exports.InlineCardWithAwareness = /*#__PURE__*/(0, _react.memo)(function (_ref) { var _pluginInjectionApi$c; var node = _ref.node, cardContext = _ref.cardContext, actionOptions = _ref.actionOptions, useAlternativePreloader = _ref.useAlternativePreloader, view = _ref.view, getPos = _ref.getPos, pluginInjectionApi = _ref.pluginInjectionApi, onClick = _ref.onClick, isPulseEnabled = _ref.isPulseEnabled, isOverlayEnabled = _ref.isOverlayEnabled, isSelected = _ref.isSelected, isPageSSRed = _ref.isPageSSRed, provider = _ref.provider, appearance = _ref.appearance; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), isHovered = _useState2[0], setIsHovered = _useState2[1]; var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), isInserted = _useState4[0], setIsInserted = _useState4[1]; var setIsInsertedRef = (0, _react.useRef)(setIsInserted); (0, _react.useEffect)(function () { return function () { if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_reduce_memory_leaks')) { setIsInsertedRef.current = undefined; } }; }, []); var _useState5 = (0, _react.useState)(false), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), isResolvedViewRendered = _useState6[0], setIsResolvedViewRendered = _useState6[1]; var editorAppearance = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c = pluginInjectionApi.card.sharedState.currentState()) === null || _pluginInjectionApi$c === void 0 ? void 0 : _pluginInjectionApi$c.editorAppearance; var destinationUrl = (0, _useSmartLinkDestinationUrl.useSmartLinkDestinationUrl)(node.attrs.url); // Remove tr: Transaction | undefined parameter with platform_editor_reduce_forced_layout_2 cleanup. var onResolve = (0, _react.useCallback)(function (tr, title) { if (tr) { var metadata = tr.getMeta(_pluginKey.pluginKey); var removeOverlay = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_reduce_memory_leaks') ? createRemoveOverlay(setIsInsertedRef) : function () { return setIsInserted(false); }; if (metadata && metadata.type === 'REGISTER') { (0, _actions.registerRemoveOverlay)(removeOverlay, metadata.info)(tr); } else { (0, _actions.registerRemoveOverlay)(removeOverlay)(tr); } } if (title) { setIsResolvedViewRendered(true); } }, []); var markMostRecentlyInsertedLink = (0, _react.useCallback)(function (isLinkMostRecentlyInserted) { if (isOverlayEnabled && !(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_reduce_forced_layout_2')) { setIsInserted(isLinkMostRecentlyInserted); } }, [(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_reduce_forced_layout_2') ? undefined : isOverlayEnabled]); var setOverlayHoveredStyles = (0, _react.useCallback)(function (isHovered) { if (isOverlayEnabled) { setIsHovered(isHovered); } }, [isOverlayEnabled]); var _useSharedPluginState = (0, _useSharedPluginStateWithSelector.useSharedPluginStateWithSelector)(pluginInjectionApi, ['selection', 'editorViewMode'], selector), mode = _useSharedPluginState.mode, selection = _useSharedPluginState.selection; var floatingToolbarNode = selection instanceof _state.NodeSelection && selection.node; // This is a prop to show Hover card, Hover card should be shown only in Live View and Classic Renderer (note when only Editor controls enabled we don't show in Live view) var showHoverPreview = floatingToolbarNode !== node; var innerCardWithOpenButtonOverlay = (0, _react.useMemo)(function () { var _pluginInjectionApi$a; return /*#__PURE__*/_react.default.createElement(_HoverLinkOverlay.default, { isVisible: isResolvedViewRendered, url: node.attrs.url, destinationUrl: destinationUrl, compactPadding: editorAppearance === 'comment' || editorAppearance === 'chromeless', editorAnalyticsApi: pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions, view: view }, /*#__PURE__*/_react.default.createElement(_inlineCardBase.InlineCard, { node: node, view: view, getPos: getPos, useAlternativePreloader: useAlternativePreloader, actionOptions: actionOptions, onResolve: onResolve, onClick: onClick, cardContext: cardContext, isHovered: isHovered, isPageSSRed: isPageSSRed, provider: provider, pluginInjectionApi: pluginInjectionApi, disablePreviewPanel: true })); }, [isResolvedViewRendered, node, editorAppearance, view, getPos, useAlternativePreloader, actionOptions, onResolve, onClick, cardContext, isHovered, isPageSSRed, provider, pluginInjectionApi, destinationUrl]); var innerCardOriginal = (0, _react.useMemo)(function () { return /*#__PURE__*/_react.default.createElement(_inlineCardBase.InlineCard, { node: node, view: view, getPos: getPos, useAlternativePreloader: useAlternativePreloader, actionOptions: actionOptions, onResolve: onResolve, onClick: onClick, cardContext: cardContext, isHovered: isHovered, isPageSSRed: isPageSSRed, provider: provider, pluginInjectionApi: pluginInjectionApi, showHoverPreview: false }); }, [actionOptions, cardContext, getPos, isHovered, node, onClick, onResolve, useAlternativePreloader, view, isPageSSRed, provider, pluginInjectionApi]); var shouldShowOpenButtonOverlay = (0, _react.useMemo)(function () { var shouldShowOpenButtonOverlayInChomeless = editorAppearance === 'chromeless'; return mode === 'edit' || editorAppearance === 'comment' || shouldShowOpenButtonOverlayInChomeless; }, [mode, editorAppearance]); var innerCard = shouldShowOpenButtonOverlay ? innerCardWithOpenButtonOverlay : innerCardOriginal; if (mode === 'view') { var _cardContext$value; var url = node.attrs.url; var cardState = cardContext === null || cardContext === void 0 || (_cardContext$value = cardContext.value) === null || _cardContext$value === void 0 || (_cardContext$value = _cardContext$value.store) === null || _cardContext$value === void 0 ? void 0 : _cardContext$value.getState()[url]; if (cardState) { var _cardContext$value2, _cardContext$value2$i, _cardContext$value3; var ari = (0, _smartCard.getObjectAri)(cardState.details); var name = (0, _smartCard.getObjectName)(cardState.details); var iconUrl = (0, _smartCard.getObjectIconUrl)(cardState.details); var isPanelAvailable = ari && (cardContext === null || cardContext === void 0 || (_cardContext$value2 = cardContext.value) === null || _cardContext$value2 === void 0 || (_cardContext$value2$i = _cardContext$value2.isPreviewPanelAvailable) === null || _cardContext$value2$i === void 0 ? void 0 : _cardContext$value2$i.call(_cardContext$value2, { ari: ari })); var openPreviewPanel = cardContext === null || cardContext === void 0 || (_cardContext$value3 = cardContext.value) === null || _cardContext$value3 === void 0 ? void 0 : _cardContext$value3.openPreviewPanel; var isPreviewPanelAvailable = Boolean(openPreviewPanel && isPanelAvailable); var firePreviewPanelClickEvent = function firePreviewPanelClickEvent(_ref2) { var _cardContext$value4, _pluginInjectionApi$a2; var previewType = _ref2.previewType; var store = cardContext === null || cardContext === void 0 || (_cardContext$value4 = cardContext.value) === null || _cardContext$value4 === void 0 ? void 0 : _cardContext$value4.store; var urlState = store === null || store === void 0 ? void 0 : store.getState()[url || '']; if (pluginInjectionApi !== null && pluginInjectionApi !== void 0 && (_pluginInjectionApi$a2 = pluginInjectionApi.analytics) !== null && _pluginInjectionApi$a2 !== void 0 && _pluginInjectionApi$a2.actions) { var _pluginInjectionApi$a3, _urlState$details$met, _urlState$details, _urlState$details$met2, _urlState$details2; pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a3 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a3 === void 0 || (_pluginInjectionApi$a3 = _pluginInjectionApi$a3.actions) === null || _pluginInjectionApi$a3 === void 0 || _pluginInjectionApi$a3.fireAnalyticsEvent({ action: _enums.ACTION.CLICKED, actionSubject: _enums.ACTION_SUBJECT.SMART_LINK, actionSubjectId: _enums.ACTION_SUBJECT_ID.HOVER_LABEL, eventType: _enums.EVENT_TYPE.UI, attributes: { previewType: previewType, destinationProduct: (_urlState$details$met = urlState === null || urlState === void 0 || (_urlState$details = urlState.details) === null || _urlState$details === void 0 || (_urlState$details = _urlState$details.meta) === null || _urlState$details === void 0 ? void 0 : _urlState$details.product) !== null && _urlState$details$met !== void 0 ? _urlState$details$met : null, destinationSubproduct: (_urlState$details$met2 = urlState === null || urlState === void 0 || (_urlState$details2 = urlState.details) === null || _urlState$details2 === void 0 || (_urlState$details2 = _urlState$details2.meta) === null || _urlState$details2 === void 0 ? void 0 : _urlState$details2.subproduct) !== null && _urlState$details$met2 !== void 0 ? _urlState$details$met2 : null } }); } }; var innerCardWithPanelButtonOverlay = /*#__PURE__*/_react.default.createElement(_PreviewInvoker.PreviewInvoker, { url: url, appearance: "inline" }, function (_ref3) { var canPreview = _ref3.canPreview, invokePreview = _ref3.invokePreview; var isPreviewModalAvailable = Boolean(canPreview && invokePreview); // In view mode we show HoverLinkOverlay only with if preview mode or panel is available // otherwise a use can click on smartlink itself to open the link in a new tab. var isPreviewAvailable = isPreviewPanelAvailable || isPreviewModalAvailable; // When inside preview panel iframe, hide the overlay button var isInPreviewPanel = (0, _isWithinPreviewPanelIframe.isWithinPreviewPanelIFrame)(); var showPanelButton = isInPreviewPanel ? isPreviewPanelAvailable : isPreviewAvailable; if (isPreviewAvailable) { var _pluginInjectionApi$a4; return /*#__PURE__*/_react.default.createElement(_HoverLinkOverlay.default, { isVisible: isResolvedViewRendered, url: url, destinationUrl: destinationUrl, compactPadding: editorAppearance === 'comment' || editorAppearance === 'chromeless', editorAnalyticsApi: pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a4 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a4 === void 0 ? void 0 : _pluginInjectionApi$a4.actions, view: view, showPanelButton: showPanelButton, showPanelButtonIcon: isPreviewAvailable && isPreviewPanelAvailable ? 'panel' : 'modal' // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onClick: function onClick(event) { if (isPreviewPanelAvailable) { var _extractSmartLinkEmbe; event.preventDefault(); openPreviewPanel === null || openPreviewPanel === void 0 || openPreviewPanel({ url: url, ari: ari || '', name: name || '', iconUrl: iconUrl, panelData: { embedUrl: (0, _expValEquals.expValEquals)('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe = (0, _extractSmartLinkEmbed.extractSmartLinkEmbed)(cardState === null || cardState === void 0 ? void 0 : cardState.details)) === null || _extractSmartLinkEmbe === void 0 ? void 0 : _extractSmartLinkEmbe.src : undefined } }); firePreviewPanelClickEvent({ previewType: 'panel' }); } else if (isPreviewModalAvailable) { event.preventDefault(); invokePreview === null || invokePreview === void 0 || invokePreview(); firePreviewPanelClickEvent({ previewType: 'modal' }); } } }, /*#__PURE__*/_react.default.createElement(_inlineCardBase.InlineCard, { node: node, view: view, getPos: getPos, useAlternativePreloader: useAlternativePreloader, actionOptions: actionOptions, onResolve: onResolve, onClick: onClick, cardContext: cardContext, isHovered: isHovered, isPageSSRed: isPageSSRed, provider: provider, pluginInjectionApi: pluginInjectionApi, showHoverPreview: mode === 'view' && showHoverPreview, disablePreviewPanel: true })); } else { return /*#__PURE__*/_react.default.createElement(_inlineCardBase.InlineCard, { node: node, view: view, getPos: getPos, useAlternativePreloader: useAlternativePreloader, actionOptions: actionOptions, onResolve: onResolve, onClick: onClick, cardContext: cardContext, isHovered: isHovered, isPageSSRed: isPageSSRed, provider: provider, pluginInjectionApi: pluginInjectionApi, showHoverPreview: mode === 'view' && showHoverPreview }); } }); innerCard = innerCardWithPanelButtonOverlay; } } var getPosFunction = typeof getPos === 'function' ? getPos : undefined; var placeholderUniqId = (getPosFunction === null || getPosFunction === void 0 ? void 0 : getPosFunction()) || 0; return isOverlayEnabled || isPulseEnabled ? /*#__PURE__*/_react.default.createElement(_AwarenessWrapper.AwarenessWrapper, { isOverlayEnabled: isOverlayEnabled, isPulseEnabled: isPulseEnabled, cardContext: cardContext, getPos: getPos, isHovered: isHovered, isInserted: isInserted, url: node.attrs.url, isSelected: isSelected, isResolvedViewRendered: isResolvedViewRendered, markMostRecentlyInsertedLink: markMostRecentlyInsertedLink, pluginInjectionApi: pluginInjectionApi, setOverlayHoveredStyles: setOverlayHoveredStyles, appearance: appearance }, innerCard) : /*#__PURE__*/_react.default.createElement("span", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: "card", "data-vc": "editor-plugin-inline-card", "data-ssr-placeholder": "editor-plugin-inline-card-".concat(placeholderUniqId), "data-ssr-placeholder-replace": "editor-plugin-inline-card-".concat(placeholderUniqId) }, innerCard); });