@atlaskit/editor-plugin-breakout
Version:
Breakout plugin for @atlaskit/editor-core
278 lines (276 loc) • 14.1 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.breakoutPlugin = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _react = _interopRequireWildcard(require("react"));
var _adfSchema = require("@atlaskit/adf-schema");
var _hooks = require("@atlaskit/editor-common/hooks");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _styles = require("@atlaskit/editor-common/styles");
var _usePluginStateEffect = require("@atlaskit/editor-common/use-plugin-state-effect");
var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _pluginKey = require("./pm-plugins/plugin-key");
var _resizingPlugin = require("./pm-plugins/resizing-plugin");
var _findBreakoutNode = require("./pm-plugins/utils/find-breakout-node");
var _getBreakoutMode = require("./pm-plugins/utils/get-breakout-mode");
var _GuidelineLabel = require("./ui/GuidelineLabel");
var _LayoutButton = _interopRequireDefault(require("./ui/LayoutButton"));
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 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) { (0, _defineProperty2.default)(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; }
var BreakoutView = /*#__PURE__*/(0, _createClass2.default)(function BreakoutView(
/**
* Note: this is actually a PMMark -- however our version
* of the prosemirror and prosemirror types mean using PMNode
* is not problematic.
*/
mark, view, appearance) {
(0, _classCallCheck2.default)(this, BreakoutView);
var dom = document.createElement('div');
var contentDOM = document.createElement('div');
contentDOM.className = _styles.BreakoutCssClassName.BREAKOUT_MARK_DOM;
contentDOM.setAttribute('data-testid', 'ak-editor-breakout-mark-dom');
dom.className = _styles.BreakoutCssClassName.BREAKOUT_MARK;
dom.setAttribute('data-layout', mark.attrs.mode);
dom.setAttribute('data-testid', 'ak-editor-breakout-mark');
dom.appendChild(contentDOM);
dom.style.transform = 'none';
dom.style.display = 'flex';
dom.style.justifyContent = 'center';
contentDOM.style.transition = "min-width 0.5s ".concat(_editorSharedStyles.akEditorSwoopCubicBezier);
if ((0, _experiments.editorExperiment)('advanced_layouts', true)) {
if (mark.attrs.width) {
contentDOM.style.minWidth = "min(".concat(mark.attrs.width, "px, calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding)))");
} else {
// original breakout algorithm is in calcBreakoutWidth from platform/packages/editor/editor-common/src/utils/breakout.ts
if (mark.attrs.mode === 'full-width') {
contentDOM.style.minWidth = "max(var(--ak-editor--line-length), min(var(--ak-editor--full-width-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))";
}
if (mark.attrs.mode === 'wide') {
if (appearance && appearance === 'full-width' && (0, _experiments.editorExperiment)('single_column_layouts', true) && true) {
contentDOM.style.minWidth = "min(var(--ak-editor--breakout-wide-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding)))";
} else {
contentDOM.style.minWidth = "max(var(--ak-editor--line-length), min(var(--ak-editor--breakout-wide-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))";
}
}
}
} else {
// original breakout algorithm is in calcBreakoutWidth from platform/packages/editor/editor-common/src/utils/breakout.ts
if (mark.attrs.mode === 'full-width') {
contentDOM.style.minWidth = "max(var(--ak-editor--line-length), min(var(--ak-editor--full-width-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))";
}
if (mark.attrs.mode === 'wide') {
contentDOM.style.minWidth = "max(var(--ak-editor--line-length), min(var(--ak-editor--breakout-wide-layout-width), calc(100cqw - var(--ak-editor--breakout-full-page-guttering-padding))))";
}
}
this.dom = dom;
this.mark = mark;
this.view = view;
this.contentDOM = contentDOM;
});
function shouldPluginStateUpdate(newBreakoutNode, currentBreakoutNode) {
if (newBreakoutNode && currentBreakoutNode) {
return newBreakoutNode !== currentBreakoutNode;
}
return newBreakoutNode || currentBreakoutNode ? true : false;
}
function createPlugin(api, _ref, appearance) {
var dispatch = _ref.dispatch;
return new _safePlugin.SafePlugin({
state: {
init: function init() {
return {
breakoutNode: undefined,
activeGuidelineKey: undefined
};
},
apply: function apply(tr, pluginState) {
var breakoutNode = (0, _findBreakoutNode.findSupportedNodeForBreakout)(tr.selection);
if (shouldPluginStateUpdate(breakoutNode, pluginState.breakoutNode)) {
var nextPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
breakoutNode: breakoutNode
});
dispatch(_pluginKey.pluginKey, nextPluginState);
return nextPluginState;
}
return pluginState;
}
},
key: _pluginKey.pluginKey,
props: {
nodeViews: {
// Note: When we upgrade to prosemirror 1.27.2 -- we should
// move this to markViews.
// See the following link for more details:
// https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews.
breakout: function breakout(mark, view) {
return new BreakoutView(mark, view, appearance);
}
}
}
});
}
var LayoutButtonWrapper = function LayoutButtonWrapper(_ref2) {
var api = _ref2.api,
editorView = _ref2.editorView,
boundariesElement = _ref2.boundariesElement,
scrollableElement = _ref2.scrollableElement,
mountPoint = _ref2.mountPoint;
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['editorViewMode', 'editorDisabled', 'blockControls'], function (states) {
var _states$blockControls, _states$blockControls2, _states$editorViewMod, _states$editorDisable;
return {
isDragging: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isDragging,
isPMDragging: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.isPMDragging,
mode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode,
editorDisabled: (_states$editorDisable = states.editorDisabledState) === null || _states$editorDisable === void 0 ? void 0 : _states$editorDisable.editorDisabled
};
}),
editorDisabled = _useSharedPluginState.editorDisabled,
isDragging = _useSharedPluginState.isDragging,
isPMDragging = _useSharedPluginState.isPMDragging,
mode = _useSharedPluginState.mode;
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
breakoutNodePresent = _useState2[0],
setBreakoutNodePresent = _useState2[1];
var _useState3 = (0, _react.useState)((0, _expValEquals.expValEquals)('platform_editor_hydratable_ui', 'isEnabled', true) && !editorView ? undefined :
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(0, _getBreakoutMode.getBreakoutMode)(editorView.state)),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
breakoutMode = _useState4[0],
setBreakoutMode = _useState4[1];
(0, _usePluginStateEffect.usePluginStateEffect)(api, ['breakout'], function (_ref3) {
var breakoutState = _ref3.breakoutState;
if ((0, _expValEquals.expValEquals)('platform_editor_hydratable_ui', 'isEnabled', true) && !editorView) {
return;
}
if (breakoutState !== null && breakoutState !== void 0 && breakoutState.breakoutNode && !breakoutNodePresent) {
setBreakoutNodePresent(true);
}
if (!(breakoutState !== null && breakoutState !== void 0 && breakoutState.breakoutNode) && breakoutNodePresent) {
setBreakoutNodePresent(false);
}
// Remove ! during platform_editor_hydratable_ui cleanup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var nextBreakoutMode = (0, _getBreakoutMode.getBreakoutMode)(editorView.state);
if (nextBreakoutMode !== breakoutMode) {
setBreakoutMode(nextBreakoutMode);
}
});
var interactionState = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'interaction.interactionState');
if (interactionState === 'hasNotHadInteraction') {
return null;
}
if (isDragging || isPMDragging) {
if ((0, _experiments.editorExperiment)('advanced_layouts', true)) {
return null;
}
}
var isViewMode = mode === 'view';
var isEditMode = mode === 'edit';
return !isViewMode && editorDisabled === false ? /*#__PURE__*/_react.default.createElement(_LayoutButton.default, {
editorView: editorView,
mountPoint: mountPoint,
boundariesElement: boundariesElement,
scrollableElement: scrollableElement,
isLivePage: isEditMode,
isBreakoutNodePresent: breakoutNodePresent,
breakoutMode: breakoutMode,
api: api
}) : null;
};
var breakoutPlugin = exports.breakoutPlugin = function breakoutPlugin(_ref4) {
var options = _ref4.config,
api = _ref4.api;
return {
name: 'breakout',
pmPlugins: function pmPlugins() {
if ((0, _expValEquals.expValEquals)('platform_editor_breakout_resizing', 'isEnabled', true)) {
return [{
name: 'breakout-resizing',
plugin: function plugin(_ref5) {
var getIntl = _ref5.getIntl,
nodeViewPortalProviderAPI = _ref5.nodeViewPortalProviderAPI;
return (0, _resizingPlugin.createResizingPlugin)(api, getIntl, nodeViewPortalProviderAPI, options);
}
}];
}
return [{
name: 'breakout',
plugin: function plugin(props) {
return createPlugin(api, props, options === null || options === void 0 ? void 0 : options.appearance);
}
}];
},
marks: function marks() {
return [{
name: 'breakout',
mark: _adfSchema.breakout
}];
},
getSharedState: function getSharedState(editorState) {
if (!editorState) {
return {
breakoutNode: undefined
};
}
if ((0, _expValEquals.expValEquals)('platform_editor_breakout_resizing', 'isEnabled', true)) {
var resizingPluginState = _resizingPlugin.resizingPluginKey.getState(editorState);
if (!resizingPluginState) {
return {
breakoutNode: undefined,
activeGuidelineKey: undefined
};
}
return resizingPluginState;
}
var pluginState = _pluginKey.pluginKey.getState(editorState);
if (!pluginState) {
return {
breakoutNode: undefined
};
}
return pluginState;
},
contentComponent: function contentComponent(_ref6) {
var editorView = _ref6.editorView,
popupsMountPoint = _ref6.popupsMountPoint,
popupsBoundariesElement = _ref6.popupsBoundariesElement,
popupsScrollableElement = _ref6.popupsScrollableElement;
if (!editorView) {
return null;
}
if ((0, _expValEquals.expValEquals)('platform_editor_breakout_resizing', 'isEnabled', true)) {
return /*#__PURE__*/_react.default.createElement(_GuidelineLabel.GuidelineLabel, {
api: api,
editorView: editorView,
mountPoint: popupsMountPoint,
boundariesElement: popupsBoundariesElement,
scrollableElement: popupsScrollableElement
});
}
// This is a bit crappy, but should be resolved once we move to a static schema.
if (options && !options.allowBreakoutButton) {
return null;
}
return /*#__PURE__*/_react.default.createElement(LayoutButtonWrapper, {
api: api,
mountPoint: popupsMountPoint,
editorView: editorView,
boundariesElement: popupsBoundariesElement,
scrollableElement: popupsScrollableElement
});
}
};
};