@atlaskit/editor-plugin-breakout 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.eslintrc.js +18 -0
  2. package/CHANGELOG.md +1 -0
  3. package/LICENSE.md +13 -0
  4. package/README.md +30 -0
  5. package/dist/cjs/commands/remove-breakout.js +30 -0
  6. package/dist/cjs/commands/set-breakout-mode.js +29 -0
  7. package/dist/cjs/index.js +12 -0
  8. package/dist/cjs/plugin-key.js +11 -0
  9. package/dist/cjs/plugin.js +218 -0
  10. package/dist/cjs/types.js +5 -0
  11. package/dist/cjs/ui/LayoutButton.js +114 -0
  12. package/dist/cjs/utils/find-breakout-node.js +42 -0
  13. package/dist/cjs/utils/get-breakout-mode.js +24 -0
  14. package/dist/cjs/utils/is-breakout-mark-allowed.js +27 -0
  15. package/dist/cjs/utils/is-supported-node.js +15 -0
  16. package/dist/es2019/commands/remove-breakout.js +22 -0
  17. package/dist/es2019/commands/set-breakout-mode.js +23 -0
  18. package/dist/es2019/index.js +1 -0
  19. package/dist/es2019/plugin-key.js +3 -0
  20. package/dist/es2019/plugin.js +208 -0
  21. package/dist/es2019/types.js +1 -0
  22. package/dist/es2019/ui/LayoutButton.js +111 -0
  23. package/dist/es2019/utils/find-breakout-node.js +37 -0
  24. package/dist/es2019/utils/get-breakout-mode.js +17 -0
  25. package/dist/es2019/utils/is-breakout-mark-allowed.js +22 -0
  26. package/dist/es2019/utils/is-supported-node.js +9 -0
  27. package/dist/esm/commands/remove-breakout.js +24 -0
  28. package/dist/esm/commands/set-breakout-mode.js +23 -0
  29. package/dist/esm/index.js +1 -0
  30. package/dist/esm/plugin-key.js +5 -0
  31. package/dist/esm/plugin.js +211 -0
  32. package/dist/esm/types.js +1 -0
  33. package/dist/esm/ui/LayoutButton.js +106 -0
  34. package/dist/esm/utils/find-breakout-node.js +37 -0
  35. package/dist/esm/utils/get-breakout-mode.js +19 -0
  36. package/dist/esm/utils/is-breakout-mark-allowed.js +22 -0
  37. package/dist/esm/utils/is-supported-node.js +9 -0
  38. package/dist/types/commands/remove-breakout.d.ts +2 -0
  39. package/dist/types/commands/set-breakout-mode.d.ts +2 -0
  40. package/dist/types/index.d.ts +2 -0
  41. package/dist/types/plugin-key.d.ts +5 -0
  42. package/dist/types/plugin.d.ts +13 -0
  43. package/dist/types/types.d.ts +4 -0
  44. package/dist/types/ui/LayoutButton.d.ts +16 -0
  45. package/dist/types/utils/find-breakout-node.d.ts +9 -0
  46. package/dist/types/utils/get-breakout-mode.d.ts +7 -0
  47. package/dist/types/utils/is-breakout-mark-allowed.d.ts +9 -0
  48. package/dist/types/utils/is-supported-node.d.ts +6 -0
  49. package/dist/types-ts4.5/commands/remove-breakout.d.ts +2 -0
  50. package/dist/types-ts4.5/commands/set-breakout-mode.d.ts +2 -0
  51. package/dist/types-ts4.5/index.d.ts +2 -0
  52. package/dist/types-ts4.5/plugin-key.d.ts +5 -0
  53. package/dist/types-ts4.5/plugin.d.ts +15 -0
  54. package/dist/types-ts4.5/types.d.ts +4 -0
  55. package/dist/types-ts4.5/ui/LayoutButton.d.ts +16 -0
  56. package/dist/types-ts4.5/utils/find-breakout-node.d.ts +9 -0
  57. package/dist/types-ts4.5/utils/get-breakout-mode.d.ts +7 -0
  58. package/dist/types-ts4.5/utils/is-breakout-mark-allowed.d.ts +9 -0
  59. package/dist/types-ts4.5/utils/is-supported-node.d.ts +6 -0
  60. package/package.json +100 -0
package/.eslintrc.js ADDED
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ rules: {
3
+ '@typescript-eslint/no-duplicate-imports': 'error',
4
+ '@typescript-eslint/no-explicit-any': 'error',
5
+ '@typescript-eslint/ban-types': [
6
+ 'error',
7
+ {
8
+ types: {
9
+ 'React.FC':
10
+ 'Please use types directly on props instead, and explicitly define children if required',
11
+ 'React.FunctionalComponent':
12
+ 'Please use types directly on props instead, and explicitly define children if required',
13
+ },
14
+ extendDefaults: false,
15
+ },
16
+ ],
17
+ },
18
+ };
package/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # @atlaskit/editor-plugin-breakout
package/LICENSE.md ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2023 Atlassian Pty Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Editor plugin breakout
2
+
3
+ Breakout plugin for @atlaskit/editor-core
4
+
5
+ **Note:** This component is designed for internal Atlassian development.
6
+ External contributors will be able to use this component but will not be able to submit issues.
7
+
8
+ ## Install
9
+ ---
10
+ - **Install** - *yarn add @atlaskit/editor-plugin-breakout*
11
+ - **npm** - [@atlaskit/editor-plugin-breakout](https://www.npmjs.com/package/@atlaskit/editor-plugin-breakout)
12
+ - **Source** - [Bitbucket](https://bitbucket.org/atlassian/atlassian-frontend/src/master/packages/editor/editor-plugin-breakout)
13
+ - **Bundle** - [unpkg.com](https://unpkg.com/@atlaskit/editor-plugin-breakout/dist/)
14
+
15
+ ## Usage
16
+ ---
17
+ **Internal use only**
18
+
19
+ @atlaskit/editor-plugin-breakout is intended for internal use by the @atlaskit/editor-core and as a plugin dependency of the Editor within your product.
20
+
21
+ Direct use of this component is not supported.
22
+
23
+ Please see [Atlaskit - Editor plugin breakout](https://atlaskit.atlassian.com/packages/editor/editor-plugin-breakout) for documentation and examples for this package.
24
+
25
+ ## Support
26
+ ---
27
+ For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
28
+ ## License
29
+ ---
30
+ Please see [Atlassian Frontend - License](https://hello.atlassian.net/wiki/spaces/AF/pages/2589099144/Documentation#License) for more licensing information.
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.removeBreakout = removeBreakout;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _findBreakoutNode = require("../utils/find-breakout-node");
9
+ function removeBreakout() {
10
+ return function (state, dispatch) {
11
+ var node = (0, _findBreakoutNode.findSupportedNodeForBreakout)(state.selection);
12
+ if (!node) {
13
+ return false;
14
+ }
15
+ var marks = node.node.marks.filter(function (m) {
16
+ return m.type.name !== 'breakout';
17
+ });
18
+ var tr = state.tr.setNodeMarkup(node.pos, node.node.type, node.node.attrs, marks);
19
+ tr.setMeta('scrollIntoView', false);
20
+ if (state.selection instanceof _state.NodeSelection) {
21
+ if (state.selection.$anchor.pos === node.pos) {
22
+ tr.setSelection(_state.NodeSelection.create(tr.doc, node.pos));
23
+ }
24
+ }
25
+ if (dispatch) {
26
+ dispatch(tr);
27
+ }
28
+ return true;
29
+ };
30
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setBreakoutMode = setBreakoutMode;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _findBreakoutNode = require("../utils/find-breakout-node");
9
+ function setBreakoutMode(mode) {
10
+ return function (state, dispatch) {
11
+ var node = (0, _findBreakoutNode.findSupportedNodeForBreakout)(state.selection);
12
+ if (!node) {
13
+ return false;
14
+ }
15
+ var tr = state.tr.setNodeMarkup(node.pos, node.node.type, node.node.attrs, [state.schema.marks.breakout.create({
16
+ mode: mode
17
+ })]);
18
+ tr.setMeta('scrollIntoView', false);
19
+ if (state.selection instanceof _state.NodeSelection) {
20
+ if (state.selection.$anchor.pos === node.pos) {
21
+ tr.setSelection(_state.NodeSelection.create(tr.doc, node.pos));
22
+ }
23
+ }
24
+ if (dispatch) {
25
+ dispatch(tr);
26
+ }
27
+ return true;
28
+ };
29
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "breakoutPlugin", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _plugin.breakoutPlugin;
10
+ }
11
+ });
12
+ var _plugin = require("./plugin");
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.pluginKey = exports.getPluginState = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var pluginKey = exports.pluginKey = new _state.PluginKey('breakoutPlugin');
9
+ var getPluginState = exports.getPluginState = function getPluginState(state) {
10
+ return pluginKey.getState(state) || undefined;
11
+ };
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.breakoutPlugin = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _react = _interopRequireDefault(require("react"));
12
+ var _adfSchema = require("@atlaskit/adf-schema");
13
+ var _hooks = require("@atlaskit/editor-common/hooks");
14
+ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
15
+ var _styles = require("@atlaskit/editor-common/styles");
16
+ var _utils = require("@atlaskit/editor-common/utils");
17
+ var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
18
+ var _pluginKey = require("./plugin-key");
19
+ var _LayoutButton = _interopRequireDefault(require("./ui/LayoutButton"));
20
+ var _findBreakoutNode = require("./utils/find-breakout-node");
21
+ 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; }
22
+ 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; }
23
+ var BreakoutView = /*#__PURE__*/function () {
24
+ function BreakoutView(
25
+ /**
26
+ * Note: this is actually a PMMark -- however our version
27
+ * of the prosemirror and prosemirror types mean using PMNode
28
+ * is not problematic.
29
+ */
30
+ mark, view, pluginInjectionApi) {
31
+ var _this = this;
32
+ (0, _classCallCheck2.default)(this, BreakoutView);
33
+ (0, _defineProperty2.default)(this, "updateWidth", function (widthState) {
34
+ // we skip updating the width of breakout nodes if the editorView dom
35
+ // element was hidden (to avoid breakout width and button thrashing
36
+ // when an editor is hidden, re-rendered and unhidden).
37
+ if (widthState === undefined || widthState.width === 0) {
38
+ return;
39
+ }
40
+ var containerStyle = "";
41
+ var contentStyle = "";
42
+ var breakoutWidthPx = (0, _utils.calcBreakoutWidthPx)(_this.mark.attrs.mode, widthState.width);
43
+ if (widthState.lineLength) {
44
+ if (breakoutWidthPx < widthState.lineLength) {
45
+ breakoutWidthPx = widthState.lineLength;
46
+ }
47
+ containerStyle += "\n transform: none;\n display: flex;\n justify-content: center;\n ";
48
+
49
+ // There is a delay in the animation because widthState is delayed.
50
+ // When the editor goes full width the animation for the editor
51
+ // begins and finishes before widthState can update the new dimensions.
52
+ contentStyle += "\n min-width: ".concat(breakoutWidthPx, "px;\n transition: min-width 0.5s ").concat(_editorSharedStyles.akEditorSwoopCubicBezier, ";\n ");
53
+ } else {
54
+ // fallback method
55
+ // (lineLength is not normally undefined, but might be in e.g. SSR or initial render)
56
+ //
57
+ // this approach doesn't work well with position: fixed, so
58
+ // it breaks things like sticky headers
59
+ containerStyle += "width: ".concat(breakoutWidthPx, "px; transform: translateX(-50%); margin-left: 50%;");
60
+ }
61
+
62
+ // NOTE: This is a hack to ignore mutation since mark NodeView doesn't support
63
+ // `ignoreMutation` life-cycle event. @see ED-9947
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ var viewDomObserver = _this.view.domObserver;
66
+ if (viewDomObserver && _this.view.dom) {
67
+ viewDomObserver.stop();
68
+ setTimeout(function () {
69
+ viewDomObserver.start();
70
+ }, 0);
71
+ }
72
+ if (typeof _this.dom.style.cssText !== 'undefined') {
73
+ _this.dom.style.cssText = containerStyle;
74
+ _this.contentDOM.style.cssText = contentStyle;
75
+ } else {
76
+ _this.dom.setAttribute('style', containerStyle);
77
+ _this.contentDOM.setAttribute('style', contentStyle);
78
+ }
79
+ });
80
+ var contentDOM = document.createElement('div');
81
+ contentDOM.className = _styles.BreakoutCssClassName.BREAKOUT_MARK_DOM;
82
+ var dom = document.createElement('div');
83
+ dom.className = _styles.BreakoutCssClassName.BREAKOUT_MARK;
84
+ dom.setAttribute('data-layout', mark.attrs.mode);
85
+ dom.appendChild(contentDOM);
86
+ this.dom = dom;
87
+ this.mark = mark;
88
+ this.view = view;
89
+ this.contentDOM = contentDOM;
90
+ this.unsubscribe = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.width.sharedState.onChange(function (_ref) {
91
+ var nextSharedState = _ref.nextSharedState;
92
+ return _this.updateWidth(nextSharedState);
93
+ });
94
+ this.updateWidth(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.width.sharedState.currentState());
95
+ }
96
+ (0, _createClass2.default)(BreakoutView, [{
97
+ key: "destroy",
98
+ value:
99
+ // NOTE: Lifecycle events doesn't work for mark NodeView. So currently this is a no-op.
100
+ // @see https://github.com/ProseMirror/prosemirror/issues/1082
101
+ function destroy() {
102
+ var _this$unsubscribe;
103
+ (_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 || _this$unsubscribe.call(this);
104
+ }
105
+ }]);
106
+ return BreakoutView;
107
+ }();
108
+ function shouldPluginStateUpdate(newBreakoutNode, currentBreakoutNode) {
109
+ if (newBreakoutNode && currentBreakoutNode) {
110
+ return newBreakoutNode !== currentBreakoutNode;
111
+ }
112
+ return newBreakoutNode || currentBreakoutNode ? true : false;
113
+ }
114
+ function createPlugin(pluginInjectionApi, _ref2) {
115
+ var dispatch = _ref2.dispatch;
116
+ return new _safePlugin.SafePlugin({
117
+ state: {
118
+ init: function init() {
119
+ return {
120
+ breakoutNode: undefined
121
+ };
122
+ },
123
+ apply: function apply(tr, pluginState) {
124
+ var breakoutNode = (0, _findBreakoutNode.findSupportedNodeForBreakout)(tr.selection);
125
+ if (shouldPluginStateUpdate(breakoutNode, pluginState.breakoutNode)) {
126
+ var nextPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
127
+ breakoutNode: breakoutNode
128
+ });
129
+ dispatch(_pluginKey.pluginKey, nextPluginState);
130
+ return nextPluginState;
131
+ }
132
+ return pluginState;
133
+ }
134
+ },
135
+ key: _pluginKey.pluginKey,
136
+ props: {
137
+ nodeViews: {
138
+ // Note: When we upgrade to prosemirror 1.27.2 -- we should
139
+ // move this to markViews.
140
+ // See the following link for more details:
141
+ // https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews.
142
+ breakout: function breakout(mark, view) {
143
+ return new BreakoutView(mark, view, pluginInjectionApi);
144
+ }
145
+ }
146
+ }
147
+ });
148
+ }
149
+ var LayoutButtonWrapper = function LayoutButtonWrapper(_ref3) {
150
+ var _breakoutState$breako, _breakoutState$breako2;
151
+ var api = _ref3.api,
152
+ editorView = _ref3.editorView,
153
+ boundariesElement = _ref3.boundariesElement,
154
+ scrollableElement = _ref3.scrollableElement,
155
+ mountPoint = _ref3.mountPoint;
156
+ // Re-render with `width` (but don't use state) due to https://bitbucket.org/atlassian/%7Bc8e2f021-38d2-46d0-9b7a-b3f7b428f724%7D/pull-requests/24272
157
+ var _useSharedPluginState = (0, _hooks.useSharedPluginState)(api, ['width', 'breakout']),
158
+ breakoutState = _useSharedPluginState.breakoutState;
159
+ return /*#__PURE__*/_react.default.createElement(_LayoutButton.default, {
160
+ editorView: editorView,
161
+ mountPoint: mountPoint,
162
+ boundariesElement: boundariesElement,
163
+ scrollableElement: scrollableElement,
164
+ node: (_breakoutState$breako = breakoutState === null || breakoutState === void 0 || (_breakoutState$breako2 = breakoutState.breakoutNode) === null || _breakoutState$breako2 === void 0 ? void 0 : _breakoutState$breako2.node) !== null && _breakoutState$breako !== void 0 ? _breakoutState$breako : null
165
+ });
166
+ };
167
+ var breakoutPlugin = exports.breakoutPlugin = function breakoutPlugin(_ref4) {
168
+ var options = _ref4.config,
169
+ api = _ref4.api;
170
+ return {
171
+ name: 'breakout',
172
+ pmPlugins: function pmPlugins() {
173
+ return [{
174
+ name: 'breakout',
175
+ plugin: function plugin(props) {
176
+ return createPlugin(api, props);
177
+ }
178
+ }];
179
+ },
180
+ marks: function marks() {
181
+ return [{
182
+ name: 'breakout',
183
+ mark: _adfSchema.breakout
184
+ }];
185
+ },
186
+ getSharedState: function getSharedState(editorState) {
187
+ if (!editorState) {
188
+ return {
189
+ breakoutNode: undefined
190
+ };
191
+ }
192
+ var pluginState = _pluginKey.pluginKey.getState(editorState);
193
+ if (!pluginState) {
194
+ return {
195
+ breakoutNode: undefined
196
+ };
197
+ }
198
+ return pluginState;
199
+ },
200
+ contentComponent: function contentComponent(_ref5) {
201
+ var editorView = _ref5.editorView,
202
+ popupsMountPoint = _ref5.popupsMountPoint,
203
+ popupsBoundariesElement = _ref5.popupsBoundariesElement,
204
+ popupsScrollableElement = _ref5.popupsScrollableElement;
205
+ // This is a bit crappy, but should be resolved once we move to a static schema.
206
+ if (options && !options.allowBreakoutButton) {
207
+ return null;
208
+ }
209
+ return /*#__PURE__*/_react.default.createElement(LayoutButtonWrapper, {
210
+ api: api,
211
+ mountPoint: popupsMountPoint,
212
+ editorView: editorView,
213
+ boundariesElement: popupsBoundariesElement,
214
+ scrollableElement: popupsScrollableElement
215
+ });
216
+ }
217
+ };
218
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = require("react");
9
+ var _react2 = require("@emotion/react");
10
+ var _reactIntlNext = require("react-intl-next");
11
+ var _styles = require("@atlaskit/editor-common/styles");
12
+ var _ui = require("@atlaskit/editor-common/ui");
13
+ var _uiMenu = require("@atlaskit/editor-common/ui-menu");
14
+ var _utils = require("@atlaskit/editor-common/utils");
15
+ var _state = require("@atlaskit/editor-prosemirror/state");
16
+ var _utils2 = require("@atlaskit/editor-prosemirror/utils");
17
+ var _collapse = _interopRequireDefault(require("@atlaskit/icon/glyph/editor/collapse"));
18
+ var _expand = _interopRequireDefault(require("@atlaskit/icon/glyph/editor/expand"));
19
+ var _colors = require("@atlaskit/theme/colors");
20
+ var _constants = require("@atlaskit/theme/constants");
21
+ var _removeBreakout = require("../commands/remove-breakout");
22
+ var _setBreakoutMode = require("../commands/set-breakout-mode");
23
+ var _pluginKey = require("../plugin-key");
24
+ var _getBreakoutMode = require("../utils/get-breakout-mode");
25
+ var _isBreakoutMarkAllowed = require("../utils/is-breakout-mark-allowed");
26
+ var _isSupportedNode = require("../utils/is-supported-node");
27
+ /** @jsx jsx */
28
+
29
+ var toolbarButtonWrapperStyles = (0, _react2.css)({
30
+ // eslint-disable-next-line @atlaskit/design-system/no-nested-styles
31
+ '&& button': {
32
+ background: "var(--ds-background-neutral, ".concat(_colors.N20A, ")"),
33
+ color: "var(--ds-icon, ".concat(_colors.N300, ")"),
34
+ ':hover': {
35
+ background: "var(--ds-background-neutral-hovered, ".concat(_colors.B300, ")"),
36
+ color: "var(--ds-icon, white)".concat(" !important")
37
+ }
38
+ }
39
+ });
40
+ function getBreakoutNodeElement(pluginState, selection, editorView) {
41
+ if (!pluginState.breakoutNode) {
42
+ return undefined;
43
+ }
44
+ if (selection instanceof _state.NodeSelection && (0, _isSupportedNode.isSupportedNodeForBreakout)(selection.node)) {
45
+ return (0, _utils2.findDomRefAtPos)(selection.from, editorView.domAtPos.bind(editorView));
46
+ }
47
+ return (0, _utils2.findParentDomRefOfType)(pluginState.breakoutNode.node.type, editorView.domAtPos.bind(editorView))(selection);
48
+ }
49
+ var LayoutButton = function LayoutButton(_ref) {
50
+ var formatMessage = _ref.intl.formatMessage,
51
+ mountPoint = _ref.mountPoint,
52
+ boundariesElement = _ref.boundariesElement,
53
+ scrollableElement = _ref.scrollableElement,
54
+ editorView = _ref.editorView,
55
+ node = _ref.node;
56
+ var handleClick = (0, _react.useCallback)(function (breakoutMode) {
57
+ var state = editorView.state,
58
+ dispatch = editorView.dispatch;
59
+ if (['wide', 'full-width'].indexOf(breakoutMode) !== -1) {
60
+ (0, _setBreakoutMode.setBreakoutMode)(breakoutMode)(state, dispatch);
61
+ } else {
62
+ (0, _removeBreakout.removeBreakout)()(state, dispatch);
63
+ }
64
+ }, [editorView]);
65
+ var state = editorView.state;
66
+ if (!node || !(0, _isBreakoutMarkAllowed.isBreakoutMarkAllowed)(state)) {
67
+ return null;
68
+ }
69
+ var breakoutMode = (0, _getBreakoutMode.getBreakoutMode)(editorView.state);
70
+ var titleMessage = (0, _utils.getTitle)(breakoutMode);
71
+ var title = formatMessage(titleMessage);
72
+ var nextBreakoutMode = (0, _utils.getNextBreakoutMode)(breakoutMode);
73
+ var belowOtherPopupsZIndex = _constants.layers.layer() - 1;
74
+ var pluginState = (0, _pluginKey.getPluginState)(state);
75
+ if (!pluginState) {
76
+ return null;
77
+ }
78
+ var element = getBreakoutNodeElement(pluginState, state.selection, editorView);
79
+ if (!element) {
80
+ return null;
81
+ }
82
+ var closestEl = element.querySelector(".".concat(_styles.BreakoutCssClassName.BREAKOUT_MARK_DOM));
83
+ if (closestEl && closestEl.firstChild) {
84
+ element = closestEl.firstChild;
85
+ }
86
+ return (0, _react2.jsx)(_ui.Popup, {
87
+ ariaLabel: title,
88
+ target: element,
89
+ offset: [5, 0],
90
+ alignY: "start",
91
+ alignX: "end",
92
+ mountTo: mountPoint,
93
+ boundariesElement: boundariesElement,
94
+ scrollableElement: scrollableElement,
95
+ stick: true,
96
+ forcePlacement: true,
97
+ zIndex: belowOtherPopupsZIndex
98
+ }, (0, _react2.jsx)("div", {
99
+ css: toolbarButtonWrapperStyles
100
+ }, (0, _react2.jsx)(_uiMenu.ToolbarButton, {
101
+ title: title,
102
+ testId: titleMessage.id,
103
+ onClick: function onClick() {
104
+ return handleClick(nextBreakoutMode);
105
+ },
106
+ iconBefore: breakoutMode === 'full-width' ? (0, _react2.jsx)(_collapse.default, {
107
+ label: title
108
+ }) : (0, _react2.jsx)(_expand.default, {
109
+ label: title
110
+ })
111
+ })));
112
+ };
113
+ LayoutButton.displayName = 'LayoutButton';
114
+ var _default = exports.default = (0, _reactIntlNext.injectIntl)(LayoutButton);
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.findSupportedNodeForBreakout = findSupportedNodeForBreakout;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _utils = require("@atlaskit/editor-prosemirror/utils");
9
+ var _isSupportedNode = require("./is-supported-node");
10
+ /**
11
+ * Find the nearest parent node to the selection that supports breakout, or if the nearest
12
+ * matching parent node is the doc, return undefined.
13
+ * For depth, if a node is selected and supports breakout, return the depth of the node.
14
+ * @param selection Current editor selection
15
+ */
16
+ function findSupportedNodeForBreakout(selection) {
17
+ if (selection instanceof _state.NodeSelection) {
18
+ var supportsBreakout = (0, _isSupportedNode.isSupportedNodeForBreakout)(selection.node);
19
+ if (supportsBreakout) {
20
+ return {
21
+ pos: selection.from,
22
+ start: selection.from,
23
+ node: selection.node,
24
+ // If a selected expand is in a doc, the depth of that expand is 0. Therefore
25
+ // we don't need to subtract 1 or instantly return false if the depth is 0
26
+ depth: selection.$anchor.depth
27
+ };
28
+ }
29
+ }
30
+ var breakoutNode = (0, _utils.findParentNode)(_isSupportedNode.isSupportedNodeForBreakout)(selection);
31
+ if (!breakoutNode || breakoutNode.depth === 0) {
32
+ // If this node doesn't exist or the only supporting node is the document
33
+ // (with depth 0), then we're not inside a node that supports breakout
34
+ return undefined;
35
+ }
36
+ return {
37
+ node: breakoutNode.node,
38
+ start: breakoutNode.start,
39
+ pos: breakoutNode.pos,
40
+ depth: breakoutNode.depth - 1
41
+ };
42
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getBreakoutMode = getBreakoutMode;
7
+ var _findBreakoutNode = require("./find-breakout-node");
8
+ /**
9
+ * Get the current mode of the breakout at the selection
10
+ * @param state Current EditorState
11
+ */
12
+ function getBreakoutMode(state) {
13
+ var node = (0, _findBreakoutNode.findSupportedNodeForBreakout)(state.selection);
14
+ if (!node) {
15
+ return;
16
+ }
17
+ var breakoutMark = node.node.marks.find(function (m) {
18
+ return m.type.name === 'breakout';
19
+ });
20
+ if (!breakoutMark) {
21
+ return;
22
+ }
23
+ return breakoutMark.attrs.mode;
24
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isBreakoutMarkAllowed = isBreakoutMarkAllowed;
7
+ var _findBreakoutNode = require("./find-breakout-node");
8
+ /**
9
+ * Check if breakout should be allowed for the current selection. If a node is selected,
10
+ * can this node be broken out, if text, can the enclosing parent node be broken out.
11
+ *
12
+ * Currently breakout of a node is not possible if it's nested in anything but the document, however
13
+ * this logic supports this changing.
14
+ */
15
+ function isBreakoutMarkAllowed(state) {
16
+ if (!state.schema.marks.breakout) {
17
+ return false;
18
+ }
19
+ var supportedNodeParent = (0, _findBreakoutNode.findSupportedNodeForBreakout)(state.selection);
20
+ if (!supportedNodeParent) {
21
+ return false;
22
+ }
23
+ // At the moment we can only breakout when the depth is 0, ie. doc is the only node
24
+ // that supports breakout. This *could* change though.
25
+ var parent = state.selection.$from.node(supportedNodeParent.depth);
26
+ return parent.type.allowsMarkType(state.schema.marks.breakout);
27
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isSupportedNodeForBreakout = isSupportedNodeForBreakout;
7
+ var supportedNodesForBreakout = ['codeBlock', 'layoutSection', 'expand'];
8
+
9
+ /**
10
+ * Check if breakout can be applied to a node
11
+ * @param node Node to check
12
+ */
13
+ function isSupportedNodeForBreakout(node) {
14
+ return supportedNodesForBreakout.indexOf(node.type.name) !== -1;
15
+ }
@@ -0,0 +1,22 @@
1
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findSupportedNodeForBreakout } from '../utils/find-breakout-node';
3
+ export function removeBreakout() {
4
+ return (state, dispatch) => {
5
+ const node = findSupportedNodeForBreakout(state.selection);
6
+ if (!node) {
7
+ return false;
8
+ }
9
+ const marks = node.node.marks.filter(m => m.type.name !== 'breakout');
10
+ const tr = state.tr.setNodeMarkup(node.pos, node.node.type, node.node.attrs, marks);
11
+ tr.setMeta('scrollIntoView', false);
12
+ if (state.selection instanceof NodeSelection) {
13
+ if (state.selection.$anchor.pos === node.pos) {
14
+ tr.setSelection(NodeSelection.create(tr.doc, node.pos));
15
+ }
16
+ }
17
+ if (dispatch) {
18
+ dispatch(tr);
19
+ }
20
+ return true;
21
+ };
22
+ }
@@ -0,0 +1,23 @@
1
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findSupportedNodeForBreakout } from '../utils/find-breakout-node';
3
+ export function setBreakoutMode(mode) {
4
+ return (state, dispatch) => {
5
+ const node = findSupportedNodeForBreakout(state.selection);
6
+ if (!node) {
7
+ return false;
8
+ }
9
+ const tr = state.tr.setNodeMarkup(node.pos, node.node.type, node.node.attrs, [state.schema.marks.breakout.create({
10
+ mode
11
+ })]);
12
+ tr.setMeta('scrollIntoView', false);
13
+ if (state.selection instanceof NodeSelection) {
14
+ if (state.selection.$anchor.pos === node.pos) {
15
+ tr.setSelection(NodeSelection.create(tr.doc, node.pos));
16
+ }
17
+ }
18
+ if (dispatch) {
19
+ dispatch(tr);
20
+ }
21
+ return true;
22
+ };
23
+ }
@@ -0,0 +1 @@
1
+ export { breakoutPlugin } from './plugin';
@@ -0,0 +1,3 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export const pluginKey = new PluginKey('breakoutPlugin');
3
+ export const getPluginState = state => pluginKey.getState(state) || undefined;