UNPKG

@atlaskit/renderer

Version:
392 lines (390 loc) • 18.9 kB
import _extends from "@babel/runtime/helpers/extends"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; /** * @jsxRuntime classic * @jsx jsx */ /* eslint-disable jsdoc/check-tag-names */ import { Fragment, useState, useMemo, useEffect } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766 import { jsx } from '@emotion/react'; import { useSmartCardContext } from '@atlaskit/link-provider'; import { Card, getObjectAri, getObjectIconUrl, getObjectName } from '@atlaskit/smart-card'; import { isWithinPreviewPanelIFrame } from '@atlaskit/linking-common/utils'; import { useSmartLinkActions } from '@atlaskit/smart-card/hooks'; import { CardSSR } from '@atlaskit/smart-card/ssr'; import { HoverLinkOverlay, UnsupportedInline } from '@atlaskit/editor-common/ui'; import { fg } from '@atlaskit/platform-feature-flags'; import { AnalyticsContext } from '@atlaskit/analytics-next'; import { componentWithCondition } from '@atlaskit/platform-feature-flags-react'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics'; import { SmartLinkDraggable, SMART_LINK_DRAG_TYPES, SMART_LINK_APPEARANCE } from '@atlaskit/editor-smart-link-draggable'; import { useProvider } from '@atlaskit/editor-common/provider-factory'; import { CardErrorBoundary } from './fallback'; import { withSmartCardStorage } from '../../ui/SmartCardStorage'; import { getCardClickHandler } from '../utils/getCardClickHandler'; import { useInlineAnnotationProps } from '../../ui/annotations/element/useInlineAnnotationProps'; import { usePortal } from '../../ui/Renderer/PortalContext'; import { extractSmartLinkEmbed } from '@atlaskit/link-extractors'; var HoverLinkOverlayNoop = function HoverLinkOverlayNoop(props) { return jsx(Fragment, null, props.children); }; var HoverLinkOverlayWithCondition = componentWithCondition(function () { return editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true }); }, HoverLinkOverlay, HoverLinkOverlayNoop); var OverlayWithCardContext = function OverlayWithCardContext(_ref) { var _cardContext$value2, _cardContext$value3, _cardContext$value3$i, _cardContext$value4; var rendererAppearance = _ref.rendererAppearance, isResolvedViewRendered = _ref.isResolvedViewRendered, url = _ref.url, fireAnalyticsEvent = _ref.fireAnalyticsEvent, children = _ref.children; var cardContext = useSmartCardContext(); // Note: useSmartLinkActions throws without smart card context. Using it here is safe // because we checked cardContext availability in the parent component var actions = useSmartLinkActions({ url: url, appearance: 'inline' }); var preview = useMemo(function () { return actions.find(function (action) { return action.id === 'preview-content'; }); }, [actions]); var fireHoverLabelAEP = function fireHoverLabelAEP(previewType) { if (fireAnalyticsEvent) { var _cardContext$value, _urlState$details$met, _urlState$details, _urlState$details$met2, _urlState$details2; var store = cardContext === null || cardContext === void 0 || (_cardContext$value = cardContext.value) === null || _cardContext$value === void 0 ? void 0 : _cardContext$value.store; var urlState = store === null || store === void 0 ? void 0 : store.getState()[url || '']; fireAnalyticsEvent({ action: ACTION.CLICKED, actionSubject: ACTION_SUBJECT.SMART_LINK, actionSubjectId: ACTION_SUBJECT_ID.HOVER_LABEL, eventType: 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 cardState = cardContext === null || cardContext === void 0 || (_cardContext$value2 = cardContext.value) === null || _cardContext$value2 === void 0 || (_cardContext$value2 = _cardContext$value2.store) === null || _cardContext$value2 === void 0 ? void 0 : _cardContext$value2.getState()[url || '']; var ari = getObjectAri(cardState === null || cardState === void 0 ? void 0 : cardState.details); var name = getObjectName(cardState === null || cardState === void 0 ? void 0 : cardState.details); var iconUrl = getObjectIconUrl(cardState === null || cardState === void 0 ? void 0 : cardState.details); // Get resolved URL from card state, fallback to original URL if not available var resolvedUrl = url; if (expValEquals('platform_hover_card_preview_panel', 'cohort', 'test')) { var _cardState$details; var cardStateUrl = cardState !== null && cardState !== void 0 && (_cardState$details = cardState.details) !== null && _cardState$details !== void 0 && _cardState$details.data && 'url' in cardState.details.data ? cardState.details.data.url : undefined; resolvedUrl = cardStateUrl || url; } var isPanelAvailable = ari && (cardContext === null || cardContext === void 0 || (_cardContext$value3 = cardContext.value) === null || _cardContext$value3 === void 0 || (_cardContext$value3$i = _cardContext$value3.isPreviewPanelAvailable) === null || _cardContext$value3$i === void 0 ? void 0 : _cardContext$value3$i.call(_cardContext$value3, { ari: ari })); var openPreviewPanel = cardContext === null || cardContext === void 0 || (_cardContext$value4 = cardContext.value) === null || _cardContext$value4 === void 0 ? void 0 : _cardContext$value4.openPreviewPanel; var isPreviewPanelAvailable = Boolean(openPreviewPanel && isPanelAvailable); var isPreviewModalAvailable = Boolean(preview); var isPreviewAvailable = isPreviewModalAvailable || isPreviewPanelAvailable; var showPanelButtonIcon = isPreviewPanelAvailable ? 'panel' : isPreviewModalAvailable ? 'modal' : undefined; // When inside preview panel iframe, hide the overlay button var isInPreviewPanel = isWithinPreviewPanelIFrame(); var showPanelButton = isInPreviewPanel ? isPreviewPanelAvailable : isPreviewAvailable; var Overlay = isPreviewAvailable ? HoverLinkOverlayWithCondition : HoverLinkOverlayNoop; return jsx(Overlay, { isVisible: isResolvedViewRendered, url: url, compactPadding: rendererAppearance === 'comment', showPanelButton: showPanelButton, showPanelButtonIcon: showPanelButtonIcon // 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; // Prevent anchor default behaviour(click to open the anchor link) // When glance panel is available, let openPreviewPanel handle it event.preventDefault(); openPreviewPanel === null || openPreviewPanel === void 0 || openPreviewPanel({ url: resolvedUrl || '', ari: ari || '', name: name || '', iconUrl: iconUrl, panelData: { embedUrl: expValEquals('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe = extractSmartLinkEmbed(cardState === null || cardState === void 0 ? void 0 : cardState.details)) === null || _extractSmartLinkEmbe === void 0 ? void 0 : _extractSmartLinkEmbe.src : undefined } }); editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true }) && fireHoverLabelAEP('panel'); } else if (isPreviewModalAvailable) { event.preventDefault(); if (preview) { preview.invoke(); } editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true }) && fireHoverLabelAEP('modal'); } } }, children); }; var InlineCard = function InlineCard(props) { var _cardContext$value5; var url = props.url, data = props.data, eventHandlers = props.eventHandlers, fireAnalyticsEvent = props.fireAnalyticsEvent, smartLinks = props.smartLinks, rendererAppearance = props.rendererAppearance, onSetLinkTarget = props.onSetLinkTarget; var portal = usePortal(props); var cardContext = useSmartCardContext(); var provider = useProvider('cardProvider'); var SuspenseWrapperForUrl = smartLinks === null || smartLinks === void 0 ? void 0 : smartLinks.SuspenseWrapperForUrl; // Helper fn to conditionally wrap cards when suspense boundary is passed in via product var wrapWithSuspense = function wrapWithSuspense(card) { if (SuspenseWrapperForUrl && url) { return jsx(SuspenseWrapperForUrl, { url: url }, card); } return card; }; var _ref2 = (cardContext === null || cardContext === void 0 || (_cardContext$value5 = cardContext.value) === null || _cardContext$value5 === void 0 ? void 0 : _cardContext$value5.store) || {}, getSmartlinkState = _ref2.getState; var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), isResolvedViewRendered = _useState2[0], setIsResolvedViewRendered = _useState2[1]; var cardState = getSmartlinkState === null || getSmartlinkState === void 0 ? void 0 : getSmartlinkState()[url || '']; var onClick = getCardClickHandler(eventHandlers, url); var cardProps = { url: url, data: data, onClick: onClick, container: portal }; var _ref3 = smartLinks || {}, hideHoverPreview = _ref3.hideHoverPreview, actionOptions = _ref3.actionOptions, ssr = _ref3.ssr, getResolvingPlaceholder = _ref3.getResolvingPlaceholder; var resolvingPlaceholder = url && getResolvingPlaceholder ? getResolvingPlaceholder(url) : undefined; var analyticsData = { attributes: { location: 'renderer' }, // Below is added for the future implementation of Linking Platform namespaced analytic context location: 'renderer' }; var inlineAnnotationProps = useInlineAnnotationProps(props); var CompetitorPrompt = smartLinks === null || smartLinks === void 0 ? void 0 : smartLinks.CompetitorPrompt; var CompetitorPromptComponent = CompetitorPrompt && url ? jsx(CompetitorPrompt, { sourceUrl: url, linkType: "inline" }) : null; var onError = function onError(_ref4) { var err = _ref4.err; if (err) { throw err; } }; useEffect(function () { if (expValEquals('platform_editor_smartlink_local_cache', 'isEnabled', true) && url) { // Refresh cache in the background provider === null || provider === void 0 || provider.then(function (providerInstance) { var _refreshCache, _ref5; (_refreshCache = (_ref5 = providerInstance).refreshCache) === null || _refreshCache === void 0 || _refreshCache.call(_ref5, { // It's ok to cast any resourceUrl to inlineCard here, because only URL is important for the request. type: 'inlineCard', attrs: { url: url } }); }); } }, [provider, url]); var MaybeOverlay = cardContext !== null && cardContext !== void 0 && cardContext.value ? OverlayWithCardContext : HoverLinkOverlayNoop; if ((ssr || cardState && expValEquals('platform_editor_smartlink_local_cache', 'isEnabled', true)) && url && !editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true })) { if ( // eslint-disable-next-line @atlaskit/platform/no-invalid-feature-flag-usage fg('editor_inline_comments_on_inline_nodes')) { return jsx(SmartLinkDraggable, { url: url, appearance: SMART_LINK_APPEARANCE.INLINE, source: SMART_LINK_DRAG_TYPES.RENDERER }, jsx("span", _extends({ "data-inline-card": true // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) , "data-card-data": data ? JSON.stringify(data) : undefined, "data-card-url": url // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, inlineAnnotationProps), jsx(AnalyticsContext, { data: analyticsData }, wrapWithSuspense(jsx(CardSSR, { appearance: "inline", url: url, showHoverPreview: !hideHoverPreview, actionOptions: actionOptions, onClick: onClick, resolvingPlaceholder: resolvingPlaceholder }))))); } return jsx(SmartLinkDraggable, { url: url, appearance: SMART_LINK_APPEARANCE.INLINE, source: SMART_LINK_DRAG_TYPES.RENDERER }, jsx(AnalyticsContext, { data: analyticsData }, wrapWithSuspense(jsx(CardSSR, { appearance: "inline", url: url, showHoverPreview: !hideHoverPreview, actionOptions: actionOptions, onClick: onClick, resolvingPlaceholder: resolvingPlaceholder })), CompetitorPromptComponent)); } else if ((ssr || cardState && expValEquals('platform_editor_smartlink_local_cache', 'isEnabled', true)) && url && editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true })) { if ( // eslint-disable-next-line @atlaskit/platform/no-invalid-feature-flag-usage fg('editor_inline_comments_on_inline_nodes')) { return jsx(SmartLinkDraggable, { url: url, appearance: SMART_LINK_APPEARANCE.INLINE, source: SMART_LINK_DRAG_TYPES.RENDERER }, jsx("span", { "data-inline-card": true // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) , "data-card-data": data ? JSON.stringify(data) : undefined, "data-card-url": url, "data-renderer-mark": inlineAnnotationProps['data-renderer-mark'], "data-annotation-draft-mark": inlineAnnotationProps['data-annotation-draft-mark'], "data-annotation-inline-node": inlineAnnotationProps['data-annotation-inline-node'], "data-renderer-start-pos": inlineAnnotationProps['data-renderer-start-pos'], "data-annotation-mark": inlineAnnotationProps['data-annotation-mark'] }, jsx(AnalyticsContext, { data: analyticsData }, jsx(MaybeOverlay, { url: url || '', rendererAppearance: rendererAppearance, isResolvedViewRendered: isResolvedViewRendered, fireAnalyticsEvent: fireAnalyticsEvent }, wrapWithSuspense(jsx(CardSSR, { appearance: "inline", url: url, showHoverPreview: !hideHoverPreview, actionOptions: actionOptions, onClick: onClick, resolvingPlaceholder: resolvingPlaceholder // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onResolve: function onResolve(data) { if (!data.url || !data.title) { return; } props.smartCardStorage.set(data.url, data.title); if (data.title) { setIsResolvedViewRendered(true); } }, onError: onError, disablePreviewPanel: true })))))); } return jsx(SmartLinkDraggable, { url: url, appearance: SMART_LINK_APPEARANCE.INLINE, source: SMART_LINK_DRAG_TYPES.RENDERER }, jsx(AnalyticsContext, { data: analyticsData }, jsx(MaybeOverlay, { url: url || '', rendererAppearance: rendererAppearance, isResolvedViewRendered: isResolvedViewRendered, fireAnalyticsEvent: fireAnalyticsEvent }, wrapWithSuspense(jsx(CardSSR, { appearance: "inline", url: url, showHoverPreview: !hideHoverPreview, actionOptions: actionOptions, onClick: onClick, resolvingPlaceholder: resolvingPlaceholder // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onResolve: function onResolve(data) { if (!data.url || !data.title) { return; } props.smartCardStorage.set(data.url, data.title); if (data.title) { setIsResolvedViewRendered(true); } }, onError: onError, disablePreviewPanel: true }))), CompetitorPromptComponent)); } return jsx(SmartLinkDraggable, { url: url || '', appearance: SMART_LINK_APPEARANCE.INLINE, source: SMART_LINK_DRAG_TYPES.RENDERER }, jsx(AnalyticsContext, { data: analyticsData }, jsx("span", _extends({ "data-inline-card": true // eslint-disable-next-line @atlassian/perf-linting/no-expensive-computations-in-render -- Ignored via go/ees017 (to be fixed) , "data-card-data": data ? JSON.stringify(data) : undefined, "data-card-url": url // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, inlineAnnotationProps), jsx(CardErrorBoundary, _extends({ unsupportedComponent: UnsupportedInline // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, cardProps, { onSetLinkTarget: onSetLinkTarget }), jsx(MaybeOverlay, { url: url || '', rendererAppearance: rendererAppearance, isResolvedViewRendered: isResolvedViewRendered, fireAnalyticsEvent: fireAnalyticsEvent }, wrapWithSuspense(jsx(Card, _extends({ appearance: "inline", showHoverPreview: !hideHoverPreview, actionOptions: actionOptions, resolvingPlaceholder: resolvingPlaceholder // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading }, cardProps, { // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) onResolve: function onResolve(data) { if (!data.url || !data.title) { return; } props.smartCardStorage.set(data.url, data.title); if (data.title) { setIsResolvedViewRendered(true); } }, onError: onError, disablePreviewPanel: editorExperiment('platform_editor_preview_panel_linking_exp', true, { exposure: true }) })))), CompetitorPromptComponent)))); }; var _default_1 = withSmartCardStorage(InlineCard); export default _default_1;