@atlaskit/editor-plugin-card
Version:
Card plugin for @atlaskit/editor-core
298 lines (293 loc) • 15.5 kB
JavaScript
import _get from "@babel/runtime/helpers/get";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(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; })(); }
/**
* @jsxRuntime classic
* @jsx jsx
*/
import React from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
import { jsx } from '@emotion/react';
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
import { DATASOURCE_INNER_CONTAINER_CLASSNAME, SmartCardSharedCssClassName } from '@atlaskit/editor-common/styles';
import { UnsupportedInline } from '@atlaskit/editor-common/ui';
import { calcBreakoutWidth } from '@atlaskit/editor-common/utils';
import { DatasourceTableView } from '@atlaskit/link-datasource';
import { EditorSmartCardProvider, EditorSmartCardProviderValueGuard } from '@atlaskit/link-provider';
import { DATASOURCE_DEFAULT_LAYOUT } from '@atlaskit/linking-common';
import { DatasourceErrorBoundary } from '../ui/datasourceErrorBoundary';
import { EditorAnalyticsContext } from '../ui/EditorAnalyticsContext';
var getPosSafely = function getPosSafely(pos) {
if (!pos || typeof pos === 'boolean') {
return;
}
try {
return pos();
} catch (e) {
// Can blow up in rare cases, when node has been removed.
}
};
// eslint-disable-next-line @repo/internal/react/no-class-components
export var DatasourceComponent = /*#__PURE__*/function (_React$PureComponent) {
function DatasourceComponent(props) {
var _this;
_classCallCheck(this, DatasourceComponent);
_this = _callSuper(this, DatasourceComponent, [props]);
_defineProperty(_this, "getDatasource", function () {
return _this.props.node.attrs.datasource;
});
_defineProperty(_this, "getTableView", function () {
var views = _this.getDatasource().views;
return views.find(function (view) {
return view.type === 'table';
}) || undefined;
});
_defineProperty(_this, "handleColumnChange", function (columnKeys) {
var _this$getColumnsInfo = _this.getColumnsInfo(),
_this$getColumnsInfo$ = _this$getColumnsInfo.wrappedColumnKeys,
wrappedColumnKeys = _this$getColumnsInfo$ === void 0 ? [] : _this$getColumnsInfo$,
_this$getColumnsInfo$2 = _this$getColumnsInfo.columnCustomSizes,
columnCustomSizes = _this$getColumnsInfo$2 === void 0 ? {} : _this$getColumnsInfo$2;
_this.updateTableProperties(columnKeys, columnCustomSizes, wrappedColumnKeys);
});
_defineProperty(_this, "handleColumnResize", function (key, width) {
var _this$getColumnsInfo2 = _this.getColumnsInfo(),
_this$getColumnsInfo3 = _this$getColumnsInfo2.wrappedColumnKeys,
wrappedColumnKeys = _this$getColumnsInfo3 === void 0 ? [] : _this$getColumnsInfo3,
_this$getColumnsInfo4 = _this$getColumnsInfo2.columnCustomSizes,
columnCustomSizes = _this$getColumnsInfo4 === void 0 ? {} : _this$getColumnsInfo4,
_this$getColumnsInfo5 = _this$getColumnsInfo2.visibleColumnKeys,
visibleColumnKeys = _this$getColumnsInfo5 === void 0 ? [] : _this$getColumnsInfo5;
var newColumnCustomSizes = _objectSpread(_objectSpread({}, columnCustomSizes), {}, _defineProperty({}, key, width));
_this.updateTableProperties(visibleColumnKeys, newColumnCustomSizes, wrappedColumnKeys);
});
_defineProperty(_this, "handleWrappedColumnChange", function (key, shouldWrap) {
var _this$getColumnsInfo6 = _this.getColumnsInfo(),
_this$getColumnsInfo7 = _this$getColumnsInfo6.wrappedColumnKeys,
wrappedColumnKeys = _this$getColumnsInfo7 === void 0 ? [] : _this$getColumnsInfo7,
_this$getColumnsInfo8 = _this$getColumnsInfo6.columnCustomSizes,
columnCustomSizes = _this$getColumnsInfo8 === void 0 ? {} : _this$getColumnsInfo8,
_this$getColumnsInfo9 = _this$getColumnsInfo6.visibleColumnKeys,
visibleColumnKeys = _this$getColumnsInfo9 === void 0 ? [] : _this$getColumnsInfo9;
var wrappedColumnKeysSet = new Set(wrappedColumnKeys);
if (shouldWrap) {
wrappedColumnKeysSet.add(key);
} else {
wrappedColumnKeysSet.delete(key);
}
_this.updateTableProperties(visibleColumnKeys, columnCustomSizes, Array.from(wrappedColumnKeysSet));
});
_defineProperty(_this, "onError", function (_ref) {
var err = _ref.err;
if (err) {
throw err;
}
});
return _this;
}
_inherits(DatasourceComponent, _React$PureComponent);
return _createClass(DatasourceComponent, [{
key: "updateTableProperties",
value: function updateTableProperties(columnKeysArg, columnCustomSizes, wrappedColumnKeys) {
var _this$props$view = this.props.view,
state = _this$props$view.state,
dispatch = _this$props$view.dispatch;
var pos = getPosSafely(this.props.getPos);
if (pos === undefined) {
return;
}
// In case for some reason there are no visible keys stored in ADF, we take them
// from incoming sets of attributes like column sizes and wrapped column keys
// columnKeys are needed to update ADF (
// since attributes (like custom width and wrapped state) only make sense for a visible column )
// So this part effectively adds a visible column if it wasn't there but attributes were given.
var columnKeys = columnKeysArg.length > 0 ? columnKeysArg : Array.from(new Set([].concat(_toConsumableArray(Object.keys(columnCustomSizes)), _toConsumableArray(wrappedColumnKeys))));
var views = [{
type: 'table',
properties: {
columns: columnKeys.map(function (key) {
var width = columnCustomSizes[key];
var isWrapped = wrappedColumnKeys.includes(key);
return _objectSpread(_objectSpread({
key: key
}, width ? {
width: width
} : {}), isWrapped ? {
isWrapped: isWrapped
} : {});
})
}
}];
var attrs = this.props.node.attrs;
var tr = state.tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, attrs), {}, {
datasource: _objectSpread(_objectSpread({}, attrs.datasource), {}, {
views: views
})
}));
// Ensures dispatch does not contribute to undo history (otherwise user requires three undo's to revert table)
tr.setMeta('addToHistory', false);
tr.setMeta('scrollIntoView', false);
dispatch(tr);
}
}, {
key: "getColumnsInfo",
value: function getColumnsInfo() {
var _tableView$properties;
var tableView = this.getTableView();
var columnsProp = tableView === null || tableView === void 0 || (_tableView$properties = tableView.properties) === null || _tableView$properties === void 0 ? void 0 : _tableView$properties.columns;
var visibleColumnKeys = columnsProp === null || columnsProp === void 0 ? void 0 : columnsProp.map(function (_ref2) {
var key = _ref2.key;
return key;
});
var columnCustomSizes;
var columnsWithWidth = columnsProp === null || columnsProp === void 0 ? void 0 : columnsProp.filter(function (c) {
return !!c.width;
});
if (columnsWithWidth) {
var keyWidthPairs = columnsWithWidth.map(function (c) {
return [c.key, c.width];
});
columnCustomSizes = Object.fromEntries(keyWidthPairs);
}
var wrappedColumnKeys = columnsProp === null || columnsProp === void 0 ? void 0 : columnsProp.filter(function (c) {
return c.isWrapped;
}).map(function (c) {
return c.key;
});
return {
visibleColumnKeys: visibleColumnKeys,
columnCustomSizes: columnCustomSizes,
wrappedColumnKeys: wrappedColumnKeys
};
}
}, {
key: "render",
value: function render() {
var datasource = this.getDatasource();
var attrs = this.props.node.attrs;
var tableView = this.getTableView();
if (tableView) {
var _this$getColumnsInfo0 = this.getColumnsInfo(),
visibleColumnKeys = _this$getColumnsInfo0.visibleColumnKeys,
columnCustomSizes = _this$getColumnsInfo0.columnCustomSizes,
wrappedColumnKeys = _this$getColumnsInfo0.wrappedColumnKeys;
return jsx(EditorSmartCardProviderValueGuard, null, jsx(EditorAnalyticsContext, {
editorView: this.props.view
}, jsx(EditorSmartCardProvider, null, jsx(DatasourceTableView, {
datasourceId: datasource.id,
parameters: datasource.parameters,
visibleColumnKeys: visibleColumnKeys,
onVisibleColumnKeysChange: this.handleColumnChange,
url: attrs === null || attrs === void 0 ? void 0 : attrs.url,
onColumnResize: this.handleColumnResize,
columnCustomSizes: columnCustomSizes,
onWrappedColumnChange: this.handleWrappedColumnChange,
wrappedColumnKeys: wrappedColumnKeys
}))));
}
return null;
}
}]);
}(React.PureComponent);
export var Datasource = /*#__PURE__*/function (_ReactNodeView) {
function Datasource(props) {
var _props$pluginInjectio, _sharedState$currentS;
var _this2;
_classCallCheck(this, Datasource);
_this2 = _callSuper(this, Datasource, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
var sharedState = props === null || props === void 0 || (_props$pluginInjectio = props.pluginInjectionApi) === null || _props$pluginInjectio === void 0 || (_props$pluginInjectio = _props$pluginInjectio.width) === null || _props$pluginInjectio === void 0 ? void 0 : _props$pluginInjectio.sharedState;
_this2.tableWidth = sharedState === null || sharedState === void 0 || (_sharedState$currentS = sharedState.currentState()) === null || _sharedState$currentS === void 0 ? void 0 : _sharedState$currentS.width;
_this2.isNodeNested = props.isNodeNested;
sharedState === null || sharedState === void 0 || sharedState.onChange(function (_ref3) {
var nextSharedState = _ref3.nextSharedState;
if (nextSharedState !== null && nextSharedState !== void 0 && nextSharedState.width && _this2.tableWidth !== (nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width)) {
_this2.tableWidth = nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.width;
_this2.update(_this2.node, []); // required to update the width when page is resized.
}
});
return _this2;
}
// Need this function to check if the datasource attribute was added or not to a blockCard.
// If not, we return false so we can get the node to re-render properly as a block node instead.
// Otherwise, the node view will still consider the node as a Datasource and render a such.
_inherits(Datasource, _ReactNodeView);
return _createClass(Datasource, [{
key: "validUpdate",
value: function validUpdate(_, newNode) {
var _newNode$attrs;
return !!((_newNode$attrs = newNode.attrs) !== null && _newNode$attrs !== void 0 && _newNode$attrs.datasource);
}
}, {
key: "update",
value: function update(node, decorations, _innerDecorations) {
return _superPropGet(Datasource, "update", this, 3)([node, decorations, _innerDecorations, this.validUpdate]);
}
}, {
key: "createDomRef",
value: function createDomRef() {
var domRef = document.createElement('div');
domRef.setAttribute('contenteditable', 'true');
domRef.classList.add(SmartCardSharedCssClassName.DATASOURCE_CONTAINER);
return domRef;
}
/**
* Node views may render interactive elements that should not have their events reach editor
*
* We should the stop editor from handling events from following elements:
* - typing in input
* - activating buttons via spacebar
*
* Can be used to prevent the editor view from trying to handle some or all DOM events that bubble up from the node view.
* Events for which this returns true are not handled by the editor.
* @see {@link https://prosemirror.net/docs/ref/#view.NodeView.stopEvent}
*/
}, {
key: "stopEvent",
value: function stopEvent(event) {
var isFormElement = [HTMLButtonElement, HTMLInputElement].some(function (element) {
return event.target instanceof element;
});
if (isFormElement) {
return true;
}
return false;
}
}, {
key: "render",
value: function render() {
var _this$domRef, _attrs$datasource;
var attrs = this.node.attrs;
// EDM-10607: Workaround to remove datasource table draggable attribute
// @ts-ignore TS2341: Property domRef is private
(_this$domRef = this.domRef) === null || _this$domRef === void 0 || _this$domRef.setAttribute('draggable', 'false');
return jsx(DatasourceErrorBoundary, {
unsupportedComponent: UnsupportedInline,
view: this.view,
url: attrs.url,
datasourceId: attrs === null || attrs === void 0 || (_attrs$datasource = attrs.datasource) === null || _attrs$datasource === void 0 ? void 0 : _attrs$datasource.id
}, jsx("div", {
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
className: DATASOURCE_INNER_CONTAINER_CLASSNAME,
style: {
minWidth: this.isNodeNested ? '100%' :
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
calcBreakoutWidth(attrs.layout || DATASOURCE_DEFAULT_LAYOUT, this.tableWidth)
}
}, jsx(DatasourceComponent, {
node: this.node,
view: this.view,
getPos: this.getPos
})));
}
}]);
}(ReactNodeView);