@atlaskit/editor-plugin-card
Version:
Card plugin for @atlaskit/editor-core
195 lines (190 loc) • 9.78 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Card = Card;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _adfSchema = require("@atlaskit/adf-schema");
var _analyticsNext = require("@atlaskit/analytics-next");
var _hooks = require("@atlaskit/editor-common/hooks");
var _utils = require("@atlaskit/editor-common/utils");
var _link = _interopRequireDefault(require("@atlaskit/link"));
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _doc = require("../pm-plugins/doc");
var _state = require("../pm-plugins/util/state");
var _utils2 = require("../pm-plugins/utils");
var _WithCardContext = require("../ui/WithCardContext");
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); }
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
var fatalErrorPositionMap = new Map();
var WithClickHandler = function WithClickHandler(_ref) {
var pluginInjectionApi = _ref.pluginInjectionApi,
url = _ref.url,
onClickCallback = _ref.onClickCallback,
children = _ref.children;
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(pluginInjectionApi, ['editorViewMode'], function (states) {
var _states$editorViewMod;
return {
mode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode
};
}),
mode = _useSharedPluginState.mode;
var onClick = (0, _react.useCallback)(function (event) {
if (typeof onClickCallback === 'function') {
try {
onClickCallback({
event: event,
url: url
});
} catch (_unused) {}
}
}, [url, onClickCallback]);
// Setting `onClick` to `undefined` ensures clicks on smartcards navigate to the URL.
// If in view mode and not overriding with onClickCallback option, then allow smartlinks to navigate on click.
var allowNavigation = mode === 'view' && !onClickCallback;
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children({
onClick: allowNavigation ? undefined : onClick
}));
};
/**
*
* @param SmartCardComponent
* @param UnsupportedComponent
* @example
*/
function Card(SmartCardComponent, UnsupportedComponent) {
return /*#__PURE__*/function (_React$Component) {
function _class() {
var _this;
(0, _classCallCheck2.default)(this, _class);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _callSuper(this, _class, [].concat(args));
(0, _defineProperty2.default)(_this, "state", {
isError: false
});
return _this;
}
(0, _inherits2.default)(_class, _React$Component);
return (0, _createClass2.default)(_class, [{
key: "render",
value: function render() {
var _getPluginState,
_this2 = this;
var _this$props = this.props,
pluginInjectionApi = _this$props.pluginInjectionApi,
onClickCallback = _this$props.onClickCallback;
var _titleUrlPairFromNode = (0, _utils2.titleUrlPairFromNode)(this.props.node),
url = _titleUrlPairFromNode.url;
if (url && !(0, _adfSchema.isSafeUrl)(url)) {
return /*#__PURE__*/_react.default.createElement(UnsupportedComponent, null);
}
if (this.state.isError) {
if (url) {
return (0, _platformFeatureFlags.fg)('dst-a11y__replace-anchor-with-link__linking-platfo') ? /*#__PURE__*/_react.default.createElement(_link.default, {
href: url
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
,
onClick: function onClick(e) {
e.preventDefault();
}
}, url) :
/*#__PURE__*/
// eslint-disable-next-line @atlaskit/design-system/no-html-anchor
_react.default.createElement("a", {
href: url,
onClick: function onClick(e) {
e.preventDefault();
}
}, url);
} else {
return /*#__PURE__*/_react.default.createElement(UnsupportedComponent, null);
}
}
var editorAppearance = (_getPluginState = (0, _state.getPluginState)(this.props.view.state)) === null || _getPluginState === void 0 ? void 0 : _getPluginState.editorAppearance;
var analyticsEditorAppearance = (0, _utils.getAnalyticsEditorAppearance)(editorAppearance);
return /*#__PURE__*/_react.default.createElement(_analyticsNext.AnalyticsContext
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
, {
data: {
attributes: {
location: analyticsEditorAppearance
},
// Below is added for the future implementation of Linking Platform namespaced analytics context
location: analyticsEditorAppearance
}
}, /*#__PURE__*/_react.default.createElement(WithClickHandler, {
pluginInjectionApi: pluginInjectionApi,
onClickCallback: onClickCallback,
url: url
}, function (_ref2) {
var onClick = _ref2.onClick;
return /*#__PURE__*/_react.default.createElement(_WithCardContext.WithCardContext, null, function (cardContext) {
return /*#__PURE__*/_react.default.createElement(SmartCardComponent, (0, _extends2.default)({
key: url,
cardContext: cardContext
// Ignored via go/ees005
// eslint-disable-next-line react/jsx-props-no-spreading
}, _this2.props, {
onClick: onClick
}));
});
}));
}
}, {
key: "componentDidCatch",
value: function componentDidCatch(error) {
var maybeAPIError = error;
// NB: errors received in this component are propagated by the `@atlaskit/smart-card` component.
// Depending on the kind of error, the expectation for this component is to either:
// (1) Render a blue link whilst retaining `inlineCard` in the ADF (non-fatal errs);
// (2) Render a blue link whilst downgrading to `link` in the ADF (fatal errs).
if (maybeAPIError.kind && maybeAPIError.kind === 'fatal') {
var _pluginInjectionApi$a;
this.setState({
isError: true
});
var _this$props2 = this.props,
view = _this$props2.view,
node = _this$props2.node,
getPos = _this$props2.getPos,
pluginInjectionApi = _this$props2.pluginInjectionApi;
var _titleUrlPairFromNode2 = (0, _utils2.titleUrlPairFromNode)(node),
url = _titleUrlPairFromNode2.url;
if (!getPos || typeof getPos === 'boolean') {
return;
}
var pos = getPos();
/**
* We cache fatal errors by position to avoid retrying the same errors
* on the same links at the same position.
*/
if (url && pos && fatalErrorPositionMap.get(url) === pos) {
return null;
}
(0, _doc.changeSelectedCardToLinkFallback)(undefined, url, true, node, getPos(), pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions)(view.state, view.dispatch);
if (url && pos) {
fatalErrorPositionMap.set(url, pos);
}
return null;
} else {
// Otherwise, render a blue link as fallback (above in render()).
this.setState({
isError: true
});
}
}
}]);
}(_react.default.Component);
}