@atlaskit/renderer
Version:
Renderer component
401 lines (396 loc) • 20.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
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 _react = require("react");
var _react2 = require("@emotion/react");
var _linkProvider = require("@atlaskit/link-provider");
var _smartCard = require("@atlaskit/smart-card");
var _utils = require("@atlaskit/linking-common/utils");
var _hooks = require("@atlaskit/smart-card/hooks");
var _ssr = require("@atlaskit/smart-card/ssr");
var _ui = require("@atlaskit/editor-common/ui");
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _analyticsNext = require("@atlaskit/analytics-next");
var _platformFeatureFlagsReact = require("@atlaskit/platform-feature-flags-react");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _analytics = require("@atlaskit/editor-common/analytics");
var _editorSmartLinkDraggable = require("@atlaskit/editor-smart-link-draggable");
var _providerFactory = require("@atlaskit/editor-common/provider-factory");
var _fallback = require("./fallback");
var _SmartCardStorage = require("../../ui/SmartCardStorage");
var _getCardClickHandler = require("../utils/getCardClickHandler");
var _useInlineAnnotationProps = require("../../ui/annotations/element/useInlineAnnotationProps");
var _PortalContext = require("../../ui/Renderer/PortalContext");
var _linkExtractors = require("@atlaskit/link-extractors");
/**
* @jsxRuntime classic
* @jsx jsx
*/
/* eslint-disable jsdoc/check-tag-names */
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
var HoverLinkOverlayNoop = function HoverLinkOverlayNoop(props) {
return (0, _react2.jsx)(_react.Fragment, null, props.children);
};
var HoverLinkOverlayWithCondition = (0, _platformFeatureFlagsReact.componentWithCondition)(function () {
return (0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true, {
exposure: true
});
}, _ui.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 = (0, _linkProvider.useSmartCardContext)();
// Note: useSmartLinkActions throws without smart card context. Using it here is safe
// because we checked cardContext availability in the parent component
var actions = (0, _hooks.useSmartLinkActions)({
url: url,
appearance: 'inline'
});
var preview = (0, _react.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: _analytics.ACTION.CLICKED,
actionSubject: _analytics.ACTION_SUBJECT.SMART_LINK,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.HOVER_LABEL,
eventType: _analytics.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 = (0, _smartCard.getObjectAri)(cardState === null || cardState === void 0 ? void 0 : cardState.details);
var name = (0, _smartCard.getObjectName)(cardState === null || cardState === void 0 ? void 0 : cardState.details);
var iconUrl = (0, _smartCard.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 ((0, _expValEquals.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 = (0, _utils.isWithinPreviewPanelIFrame)();
var showPanelButton = isInPreviewPanel ? isPreviewPanelAvailable : isPreviewAvailable;
var Overlay = isPreviewAvailable ? HoverLinkOverlayWithCondition : HoverLinkOverlayNoop;
return (0, _react2.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: (0, _expValEquals.expValEquals)('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe = (0, _linkExtractors.extractSmartLinkEmbed)(cardState === null || cardState === void 0 ? void 0 : cardState.details)) === null || _extractSmartLinkEmbe === void 0 ? void 0 : _extractSmartLinkEmbe.src : undefined
}
});
(0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true, {
exposure: true
}) && fireHoverLabelAEP('panel');
} else if (isPreviewModalAvailable) {
event.preventDefault();
if (preview) {
preview.invoke();
}
(0, _experiments.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 = (0, _PortalContext.usePortal)(props);
var cardContext = (0, _linkProvider.useSmartCardContext)();
var provider = (0, _providerFactory.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 (0, _react2.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 = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
isResolvedViewRendered = _useState2[0],
setIsResolvedViewRendered = _useState2[1];
var cardState = getSmartlinkState === null || getSmartlinkState === void 0 ? void 0 : getSmartlinkState()[url || ''];
var onClick = (0, _getCardClickHandler.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 = (0, _useInlineAnnotationProps.useInlineAnnotationProps)(props);
var CompetitorPrompt = smartLinks === null || smartLinks === void 0 ? void 0 : smartLinks.CompetitorPrompt;
var CompetitorPromptComponent = CompetitorPrompt && url ? (0, _react2.jsx)(CompetitorPrompt, {
sourceUrl: url,
linkType: "inline"
}) : null;
var onError = function onError(_ref4) {
var err = _ref4.err;
if (err) {
throw err;
}
};
(0, _react.useEffect)(function () {
if ((0, _expValEquals.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 && (0, _expValEquals.expValEquals)('platform_editor_smartlink_local_cache', 'isEnabled', true)) && url && !(0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true, {
exposure: true
})) {
if (
// eslint-disable-next-line @atlaskit/platform/no-invalid-feature-flag-usage
(0, _platformFeatureFlags.fg)('editor_inline_comments_on_inline_nodes')) {
return (0, _react2.jsx)(_editorSmartLinkDraggable.SmartLinkDraggable, {
url: url,
appearance: _editorSmartLinkDraggable.SMART_LINK_APPEARANCE.INLINE,
source: _editorSmartLinkDraggable.SMART_LINK_DRAG_TYPES.RENDERER
}, (0, _react2.jsx)("span", (0, _extends2.default)({
"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), (0, _react2.jsx)(_analyticsNext.AnalyticsContext, {
data: analyticsData
}, wrapWithSuspense((0, _react2.jsx)(_ssr.CardSSR, {
appearance: "inline",
url: url,
showHoverPreview: !hideHoverPreview,
actionOptions: actionOptions,
onClick: onClick,
resolvingPlaceholder: resolvingPlaceholder
})))));
}
return (0, _react2.jsx)(_editorSmartLinkDraggable.SmartLinkDraggable, {
url: url,
appearance: _editorSmartLinkDraggable.SMART_LINK_APPEARANCE.INLINE,
source: _editorSmartLinkDraggable.SMART_LINK_DRAG_TYPES.RENDERER
}, (0, _react2.jsx)(_analyticsNext.AnalyticsContext, {
data: analyticsData
}, wrapWithSuspense((0, _react2.jsx)(_ssr.CardSSR, {
appearance: "inline",
url: url,
showHoverPreview: !hideHoverPreview,
actionOptions: actionOptions,
onClick: onClick,
resolvingPlaceholder: resolvingPlaceholder
})), CompetitorPromptComponent));
} else if ((ssr || cardState && (0, _expValEquals.expValEquals)('platform_editor_smartlink_local_cache', 'isEnabled', true)) && url && (0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true, {
exposure: true
})) {
if (
// eslint-disable-next-line @atlaskit/platform/no-invalid-feature-flag-usage
(0, _platformFeatureFlags.fg)('editor_inline_comments_on_inline_nodes')) {
return (0, _react2.jsx)(_editorSmartLinkDraggable.SmartLinkDraggable, {
url: url,
appearance: _editorSmartLinkDraggable.SMART_LINK_APPEARANCE.INLINE,
source: _editorSmartLinkDraggable.SMART_LINK_DRAG_TYPES.RENDERER
}, (0, _react2.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']
}, (0, _react2.jsx)(_analyticsNext.AnalyticsContext, {
data: analyticsData
}, (0, _react2.jsx)(MaybeOverlay, {
url: url || '',
rendererAppearance: rendererAppearance,
isResolvedViewRendered: isResolvedViewRendered,
fireAnalyticsEvent: fireAnalyticsEvent
}, wrapWithSuspense((0, _react2.jsx)(_ssr.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 (0, _react2.jsx)(_editorSmartLinkDraggable.SmartLinkDraggable, {
url: url,
appearance: _editorSmartLinkDraggable.SMART_LINK_APPEARANCE.INLINE,
source: _editorSmartLinkDraggable.SMART_LINK_DRAG_TYPES.RENDERER
}, (0, _react2.jsx)(_analyticsNext.AnalyticsContext, {
data: analyticsData
}, (0, _react2.jsx)(MaybeOverlay, {
url: url || '',
rendererAppearance: rendererAppearance,
isResolvedViewRendered: isResolvedViewRendered,
fireAnalyticsEvent: fireAnalyticsEvent
}, wrapWithSuspense((0, _react2.jsx)(_ssr.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 (0, _react2.jsx)(_editorSmartLinkDraggable.SmartLinkDraggable, {
url: url || '',
appearance: _editorSmartLinkDraggable.SMART_LINK_APPEARANCE.INLINE,
source: _editorSmartLinkDraggable.SMART_LINK_DRAG_TYPES.RENDERER
}, (0, _react2.jsx)(_analyticsNext.AnalyticsContext, {
data: analyticsData
}, (0, _react2.jsx)("span", (0, _extends2.default)({
"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), (0, _react2.jsx)(_fallback.CardErrorBoundary, (0, _extends2.default)({
unsupportedComponent: _ui.UnsupportedInline
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
}, cardProps, {
onSetLinkTarget: onSetLinkTarget
}), (0, _react2.jsx)(MaybeOverlay, {
url: url || '',
rendererAppearance: rendererAppearance,
isResolvedViewRendered: isResolvedViewRendered,
fireAnalyticsEvent: fireAnalyticsEvent
}, wrapWithSuspense((0, _react2.jsx)(_smartCard.Card, (0, _extends2.default)({
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: (0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true, {
exposure: true
})
})))), CompetitorPromptComponent))));
};
var _default_1 = (0, _SmartCardStorage.withSmartCardStorage)(InlineCard);
var _default = exports.default = _default_1;