@atlaskit/editor-plugin-extension 5.0.3 → 5.0.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-extension
2
2
 
3
+ ## 5.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 5.0.4
10
+
11
+ ### Patch Changes
12
+
13
+ - [#123536](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/123536)
14
+ [`1e9dc41a004aa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1e9dc41a004aa) -
15
+ [ux] Moved width options to dropdown for extensions toolbar
16
+ - Updated dependencies
17
+
3
18
  ## 5.0.3
4
19
 
5
20
  ### Patch Changes
@@ -66,7 +66,7 @@ var isLayoutSupported = function isLayoutSupported(state, selectedExtNode) {
66
66
  // and not inside a layoutSection
67
67
  return !!((isMultiBodiedExtension || isNonEmbeddedBodiedExtension || isNonEmbeddedExtension) && !(0, _utils2.hasParentNodeOfType)([layoutSection])(selection));
68
68
  };
69
- var breakoutOptions = function breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
69
+ var breakoutButtonListOptions = function breakoutButtonListOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
70
70
  var nodeWithPos = (0, _utils3.getSelectedExtension)(state, true);
71
71
 
72
72
  // we should only return breakout options when breakouts are enabled and the node supports them
@@ -100,11 +100,85 @@ var breakoutOptions = function breakoutOptions(state, formatMessage, extensionSt
100
100
  }
101
101
  return [];
102
102
  };
103
+ var breakoutDropdownOptions = function breakoutDropdownOptions(state, formatMessage, breakoutEnabled, editorAnalyticsAPI) {
104
+ var nodeWithPos = (0, _utils3.getSelectedExtension)(state, true);
105
+
106
+ // we should only return breakout options when breakouts are enabled and the node supports them
107
+ if (!nodeWithPos || !breakoutEnabled || !isLayoutSupported(state, nodeWithPos) || isNestedNBM(state, nodeWithPos)) {
108
+ return [];
109
+ }
110
+ var layout = nodeWithPos.node.attrs.layout;
111
+ var title = '';
112
+ var IconComponent;
113
+ switch (layout) {
114
+ case 'wide':
115
+ title = formatMessage(_messages.default.layoutStateWide);
116
+ IconComponent = _contentWidthWide.default;
117
+ break;
118
+ case 'full-width':
119
+ title = formatMessage(_messages.default.layoutStateFullWidth);
120
+ IconComponent = _expandHorizontal.default;
121
+ break;
122
+ case 'default':
123
+ default:
124
+ title = formatMessage(_messages.default.layoutStateFixedWidth);
125
+ IconComponent = _contentWidthNarrow.default;
126
+ break;
127
+ }
128
+ var options = [{
129
+ id: 'editor.extensions.width.default',
130
+ title: formatMessage(_messages.default.layoutFixedWidth),
131
+ onClick: (0, _commands.updateExtensionLayout)('default', editorAnalyticsAPI),
132
+ selected: layout === 'default',
133
+ icon: /*#__PURE__*/_react.default.createElement(_contentWidthNarrow.default, {
134
+ color: "currentColor",
135
+ spacing: "spacious",
136
+ label: formatMessage(_messages.default.layoutFixedWidth)
137
+ })
138
+ }, {
139
+ id: 'editor.extensions.width.wide',
140
+ title: formatMessage(_messages.default.layoutWide),
141
+ onClick: (0, _commands.updateExtensionLayout)('wide', editorAnalyticsAPI),
142
+ selected: layout === 'wide',
143
+ icon: /*#__PURE__*/_react.default.createElement(_contentWidthWide.default, {
144
+ color: "currentColor",
145
+ spacing: "spacious",
146
+ label: formatMessage(_messages.default.layoutWide)
147
+ })
148
+ }, {
149
+ id: 'editor.extensions.width.full-width',
150
+ title: formatMessage(_messages.default.layoutFullWidth),
151
+ onClick: (0, _commands.updateExtensionLayout)('full-width', editorAnalyticsAPI),
152
+ selected: layout === 'full-width',
153
+ icon: /*#__PURE__*/_react.default.createElement(_expandHorizontal.default, {
154
+ color: "currentColor",
155
+ spacing: "spacious",
156
+ label: formatMessage(_messages.default.layoutFullWidth)
157
+ })
158
+ }];
159
+ return [{
160
+ id: 'extensions-width-options-toolbar-item',
161
+ testId: 'extensions-width-options-toolbar-dropdown',
162
+ type: 'dropdown',
163
+ options: options,
164
+ title: title,
165
+ iconBefore: function iconBefore() {
166
+ return /*#__PURE__*/_react.default.createElement(IconComponent, {
167
+ color: "currentColor",
168
+ spacing: "spacious",
169
+ label: title
170
+ });
171
+ }
172
+ }];
173
+ };
174
+ var breakoutOptions = function breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
175
+ return (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1') ? breakoutDropdownOptions(state, formatMessage, breakoutEnabled, editorAnalyticsAPI) : breakoutButtonListOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
176
+ };
103
177
  var editButton = function editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI) {
104
178
  if (!extensionState.showEditButton) {
105
179
  return [];
106
180
  }
107
- return [{
181
+ var editButtonItems = [{
108
182
  id: 'editor.extension.edit',
109
183
  type: 'button',
110
184
  icon: _edit.default,
@@ -122,6 +196,55 @@ var editButton = function editButton(formatMessage, extensionState, applyChangeT
122
196
  tabIndex: null,
123
197
  focusEditoronEnter: true
124
198
  }];
199
+ if ((0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
200
+ editButtonItems.push({
201
+ type: 'separator',
202
+ fullHeight: true
203
+ });
204
+ }
205
+ return editButtonItems;
206
+ };
207
+
208
+ /**
209
+ * Calculates the position for the toolbar when dealing with nested extensions
210
+ */
211
+ var calculateToolbarPosition = function calculateToolbarPosition(editorView, nextPos, state, extensionNode) {
212
+ var _editorView$state = editorView.state,
213
+ schema = _editorView$state.schema,
214
+ selection = _editorView$state.selection;
215
+ var possibleMbeParent = (0, _utils2.findParentNodeOfType)(schema.nodes.extensionFrame)(selection);
216
+ // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
217
+ var isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
218
+ var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
219
+ if ((0, _platformFeatureFlags.fg)('platform_editor_legacy_content_macro')) {
220
+ if (!extensionNode) {
221
+ return nextPos;
222
+ }
223
+ var isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
224
+ if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
225
+ return nextPos;
226
+ }
227
+ if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
228
+ // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
229
+
230
+ scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
231
+ }
232
+ } else {
233
+ if (!isBodiedExtensionInsideMBE) {
234
+ return nextPos;
235
+ }
236
+ }
237
+
238
+ // Ignored via go/ees005
239
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
240
+ var nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
241
+ var nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
242
+ var wrapperBounds = scrollWrapper.getBoundingClientRect();
243
+ var toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + _styles.BODIED_EXT_MBE_MARGIN_TOP;
244
+ return {
245
+ top: toolbarTopPos,
246
+ left: nextPos.left
247
+ };
125
248
  };
126
249
  var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(_ref) {
127
250
  var _ref$breakoutEnabled = _ref.breakoutEnabled,
@@ -131,6 +254,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(_ref
131
254
  editorAnalyticsAPI = _ref.editorAnalyticsAPI,
132
255
  extensionApi = _ref.extensionApi;
133
256
  return function (state, intl) {
257
+ var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
134
258
  var formatMessage = intl.formatMessage;
135
259
  var extensionState = (0, _pluginFactory.getPluginState)(state);
136
260
  if ((0, _platformFeatureFlags.fg)('platform_editor_legacy_content_macro')) {
@@ -140,141 +264,104 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(_ref
140
264
  applyChangeToContextPanel = extensionApi === null || extensionApi === void 0 || (_extensionApi$context = extensionApi.contextPanel) === null || _extensionApi$context === void 0 ? void 0 : _extensionApi$context.actions.applyChange;
141
265
  editorAnalyticsAPI = extensionApi === null || extensionApi === void 0 || (_extensionApi$analyti = extensionApi.analytics) === null || _extensionApi$analyti === void 0 ? void 0 : _extensionApi$analyti.actions;
142
266
  }
143
- if (extensionState && !extensionState.showContextPanel && extensionState.element) {
144
- var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
145
- var nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
146
- var editButtonArray = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
147
- var breakoutButtonArray = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
148
- var extensionObj = (0, _utils3.getSelectedExtension)(state, true);
149
-
150
- // Check if we need to show confirm dialog for delete button
151
- var confirmDialog;
152
- if ((0, _utils.isReferencedSource)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
153
- confirmDialog = function confirmDialog() {
154
- var localSourceName = formatMessage(_extensions.messages.unnamedSource);
155
- return {
156
- title: formatMessage(_extensions.messages.deleteElementTitle),
157
- okButtonLabel: formatMessage(_extensions.messages.confirmDeleteLinkedModalOKButton),
158
- message: formatMessage(_extensions.messages.confirmDeleteLinkedModalMessage, {
159
- nodeName: (0, _utils.getNodeName)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
160
- }),
161
- isReferentialityDialog: true,
162
- getChildrenInfo: function getChildrenInfo() {
163
- return (0, _utils.getChildrenInfo)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
164
- },
165
- checkboxLabel: formatMessage(_extensions.messages.confirmModalCheckboxLabel),
166
- onConfirm: function onConfirm() {
167
- var isChecked = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
168
- return clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
169
- }
170
- };
171
- };
172
- }
173
- return {
174
- title: 'Extension floating controls',
175
- // Ignored via go/ees005
176
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
177
- getDomRef: function getDomRef() {
178
- return extensionState.element.parentElement || undefined;
179
- },
180
- nodeType: nodeType,
181
- onPositionCalculated: function onPositionCalculated(editorView, nextPos) {
182
- var _editorView$state = editorView.state,
183
- schema = _editorView$state.schema,
184
- selection = _editorView$state.selection;
185
- var extensionNode = (0, _utils3.getSelectedExtension)(state, true);
186
- var possibleMbeParent = (0, _utils2.findParentNodeOfType)(schema.nodes.extensionFrame)(selection);
187
- // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
188
- var isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
189
- var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
190
- if ((0, _platformFeatureFlags.fg)('platform_editor_legacy_content_macro')) {
191
- if (!extensionNode) {
192
- return nextPos;
193
- }
194
- var isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
195
- if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
196
- return nextPos;
197
- }
198
- if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
199
- // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
267
+ if (!extensionState || extensionState.showContextPanel || !extensionState.element) {
268
+ return;
269
+ }
270
+ var nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
271
+ var editButtonItems = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
272
+ var breakoutItems = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
273
+ var extensionObj = (0, _utils3.getSelectedExtension)(state, true);
200
274
 
201
- scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
202
- }
203
- } else {
204
- if (!isBodiedExtensionInsideMBE) {
205
- return nextPos;
206
- }
275
+ // Check if we need to show confirm dialog for delete button
276
+ var confirmDialog;
277
+ if ((0, _utils.isReferencedSource)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
278
+ confirmDialog = function confirmDialog() {
279
+ var localSourceName = formatMessage(_extensions.messages.unnamedSource);
280
+ return {
281
+ title: formatMessage(_extensions.messages.deleteElementTitle),
282
+ okButtonLabel: formatMessage(_extensions.messages.confirmDeleteLinkedModalOKButton),
283
+ message: formatMessage(_extensions.messages.confirmDeleteLinkedModalMessage, {
284
+ nodeName: (0, _utils.getNodeName)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
285
+ }),
286
+ isReferentialityDialog: true,
287
+ getChildrenInfo: function getChildrenInfo() {
288
+ return (0, _utils.getChildrenInfo)(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
289
+ },
290
+ checkboxLabel: formatMessage(_extensions.messages.confirmModalCheckboxLabel),
291
+ onConfirm: function onConfirm() {
292
+ var isChecked = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
293
+ return clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
207
294
  }
208
-
209
- // Ignored via go/ees005
210
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
211
- var nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
212
- var nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
213
- var wrapperBounds = scrollWrapper.getBoundingClientRect();
214
- var toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + _styles.BODIED_EXT_MBE_MARGIN_TOP;
215
- return {
216
- top: toolbarTopPos,
217
- left: nextPos.left
218
- };
219
- },
220
- items: [].concat((0, _toConsumableArray2.default)(editButtonArray), (0, _toConsumableArray2.default)(breakoutButtonArray), (0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('platform_editor_controls', 'control') ? [{
221
- type: 'separator',
222
- hidden: editButtonArray.length === 0 && breakoutButtonArray.length === 0
223
- }, {
224
- type: 'extensions-placeholder',
225
- separator: 'end'
226
- }, {
227
- type: 'copy-button',
228
- items: [{
229
- state: state,
230
- formatMessage: intl.formatMessage,
231
- nodeType: nodeType
232
- }]
233
- }, {
234
- type: 'separator'
235
- }, {
236
- id: 'editor.extension.delete',
237
- type: 'button',
238
- icon: _delete.default,
239
- iconFallback: _remove.default,
240
- appearance: 'danger',
241
- onClick: (0, _commands.removeExtension)(editorAnalyticsAPI),
242
- onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
243
- onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
244
- onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
245
- onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
246
- focusEditoronEnter: true,
247
- title: formatMessage(_messages.default.remove),
248
- tabIndex: null,
249
- confirmDialog: confirmDialog
250
- }] : [{
251
- type: 'separator',
252
- fullHeight: true
253
- }, {
254
- type: 'overflow-dropdown',
255
- options: [{
256
- title: 'Copy',
257
- onClick: function onClick() {
258
- var _extensionApi$core, _extensionApi$floatin;
259
- extensionApi === null || extensionApi === void 0 || (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 || _extensionApi$core.actions.execute( // @ts-ignore
260
- extensionApi === null || extensionApi === void 0 || (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
261
- return true;
262
- },
263
- icon: /*#__PURE__*/_react.default.createElement(_copy.default, {
264
- label: "Copy"
265
- })
266
- }, {
267
- title: 'Delete',
268
- onClick: (0, _commands.removeExtension)(editorAnalyticsAPI),
269
- icon: /*#__PURE__*/_react.default.createElement(_delete.default, {
270
- label: "Delete"
271
- })
272
- }]
273
- }])),
274
- scrollable: true
295
+ };
275
296
  };
276
297
  }
277
- return;
298
+ return {
299
+ title: 'Extension floating controls',
300
+ // Ignored via go/ees005
301
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
302
+ getDomRef: function getDomRef() {
303
+ return extensionState.element.parentElement || undefined;
304
+ },
305
+ nodeType: nodeType,
306
+ onPositionCalculated: function onPositionCalculated(editorView, nextPos) {
307
+ return calculateToolbarPosition(editorView, nextPos, state, extensionObj);
308
+ },
309
+ items: [].concat((0, _toConsumableArray2.default)(editButtonItems), (0, _toConsumableArray2.default)(breakoutItems), (0, _toConsumableArray2.default)((0, _experiments.editorExperiment)('platform_editor_controls', 'control') ? [{
310
+ type: 'separator',
311
+ hidden: editButtonItems.length === 0 && breakoutItems.length === 0
312
+ }, {
313
+ type: 'extensions-placeholder',
314
+ separator: 'end'
315
+ }, {
316
+ type: 'copy-button',
317
+ items: [{
318
+ state: state,
319
+ formatMessage: intl.formatMessage,
320
+ nodeType: nodeType
321
+ }]
322
+ }, {
323
+ type: 'separator'
324
+ }, {
325
+ id: 'editor.extension.delete',
326
+ type: 'button',
327
+ icon: _delete.default,
328
+ iconFallback: _remove.default,
329
+ appearance: 'danger',
330
+ onClick: (0, _commands.removeExtension)(editorAnalyticsAPI),
331
+ onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
332
+ onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
333
+ onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
334
+ onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
335
+ focusEditoronEnter: true,
336
+ title: formatMessage(_messages.default.remove),
337
+ tabIndex: null,
338
+ confirmDialog: confirmDialog
339
+ }] : [{
340
+ type: 'separator',
341
+ fullHeight: true
342
+ }, {
343
+ type: 'overflow-dropdown',
344
+ options: [{
345
+ title: 'Copy',
346
+ onClick: function onClick() {
347
+ var _extensionApi$core, _extensionApi$floatin;
348
+ extensionApi === null || extensionApi === void 0 || (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 || _extensionApi$core.actions.execute( // @ts-ignore
349
+ extensionApi === null || extensionApi === void 0 || (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
350
+ return true;
351
+ },
352
+ icon: /*#__PURE__*/_react.default.createElement(_copy.default, {
353
+ label: "Copy"
354
+ })
355
+ }, {
356
+ title: 'Delete',
357
+ onClick: (0, _commands.removeExtension)(editorAnalyticsAPI),
358
+ icon: /*#__PURE__*/_react.default.createElement(_delete.default, {
359
+ label: "Delete"
360
+ })
361
+ }]
362
+ }])),
363
+ scrollable: true
364
+ };
278
365
  };
279
366
  };
280
367
  var clickWithCheckboxHandler = function clickWithCheckboxHandler(isChecked, node) {
@@ -68,7 +68,7 @@ const isLayoutSupported = (state, selectedExtNode) => {
68
68
  // and not inside a layoutSection
69
69
  return !!((isMultiBodiedExtension || isNonEmbeddedBodiedExtension || isNonEmbeddedExtension) && !hasParentNodeOfType([layoutSection])(selection));
70
70
  };
71
- const breakoutOptions = (state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) => {
71
+ const breakoutButtonListOptions = (state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) => {
72
72
  const nodeWithPos = getSelectedExtension(state, true);
73
73
 
74
74
  // we should only return breakout options when breakouts are enabled and the node supports them
@@ -104,11 +104,85 @@ const breakoutOptions = (state, formatMessage, extensionState, breakoutEnabled,
104
104
  }
105
105
  return [];
106
106
  };
107
+ const breakoutDropdownOptions = (state, formatMessage, breakoutEnabled, editorAnalyticsAPI) => {
108
+ const nodeWithPos = getSelectedExtension(state, true);
109
+
110
+ // we should only return breakout options when breakouts are enabled and the node supports them
111
+ if (!nodeWithPos || !breakoutEnabled || !isLayoutSupported(state, nodeWithPos) || isNestedNBM(state, nodeWithPos)) {
112
+ return [];
113
+ }
114
+ const {
115
+ layout
116
+ } = nodeWithPos.node.attrs;
117
+ let title = '';
118
+ let IconComponent;
119
+ switch (layout) {
120
+ case 'wide':
121
+ title = formatMessage(commonMessages.layoutStateWide);
122
+ IconComponent = ContentWidthWideIcon;
123
+ break;
124
+ case 'full-width':
125
+ title = formatMessage(commonMessages.layoutStateFullWidth);
126
+ IconComponent = ExpandHorizontalIcon;
127
+ break;
128
+ case 'default':
129
+ default:
130
+ title = formatMessage(commonMessages.layoutStateFixedWidth);
131
+ IconComponent = ContentWidthNarrowIcon;
132
+ break;
133
+ }
134
+ const options = [{
135
+ id: 'editor.extensions.width.default',
136
+ title: formatMessage(commonMessages.layoutFixedWidth),
137
+ onClick: updateExtensionLayout('default', editorAnalyticsAPI),
138
+ selected: layout === 'default',
139
+ icon: /*#__PURE__*/React.createElement(ContentWidthNarrowIcon, {
140
+ color: "currentColor",
141
+ spacing: "spacious",
142
+ label: formatMessage(commonMessages.layoutFixedWidth)
143
+ })
144
+ }, {
145
+ id: 'editor.extensions.width.wide',
146
+ title: formatMessage(commonMessages.layoutWide),
147
+ onClick: updateExtensionLayout('wide', editorAnalyticsAPI),
148
+ selected: layout === 'wide',
149
+ icon: /*#__PURE__*/React.createElement(ContentWidthWideIcon, {
150
+ color: "currentColor",
151
+ spacing: "spacious",
152
+ label: formatMessage(commonMessages.layoutWide)
153
+ })
154
+ }, {
155
+ id: 'editor.extensions.width.full-width',
156
+ title: formatMessage(commonMessages.layoutFullWidth),
157
+ onClick: updateExtensionLayout('full-width', editorAnalyticsAPI),
158
+ selected: layout === 'full-width',
159
+ icon: /*#__PURE__*/React.createElement(ExpandHorizontalIcon, {
160
+ color: "currentColor",
161
+ spacing: "spacious",
162
+ label: formatMessage(commonMessages.layoutFullWidth)
163
+ })
164
+ }];
165
+ return [{
166
+ id: 'extensions-width-options-toolbar-item',
167
+ testId: 'extensions-width-options-toolbar-dropdown',
168
+ type: 'dropdown',
169
+ options: options,
170
+ title,
171
+ iconBefore: () => /*#__PURE__*/React.createElement(IconComponent, {
172
+ color: "currentColor",
173
+ spacing: "spacious",
174
+ label: title
175
+ })
176
+ }];
177
+ };
178
+ const breakoutOptions = (state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) => {
179
+ return editorExperiment('platform_editor_controls', 'variant1') ? breakoutDropdownOptions(state, formatMessage, breakoutEnabled, editorAnalyticsAPI) : breakoutButtonListOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
180
+ };
107
181
  const editButton = (formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI) => {
108
182
  if (!extensionState.showEditButton) {
109
183
  return [];
110
184
  }
111
- return [{
185
+ const editButtonItems = [{
112
186
  id: 'editor.extension.edit',
113
187
  type: 'button',
114
188
  icon: EditIcon,
@@ -127,6 +201,58 @@ const editButton = (formatMessage, extensionState, applyChangeToContextPanel, ed
127
201
  tabIndex: null,
128
202
  focusEditoronEnter: true
129
203
  }];
204
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
205
+ editButtonItems.push({
206
+ type: 'separator',
207
+ fullHeight: true
208
+ });
209
+ }
210
+ return editButtonItems;
211
+ };
212
+
213
+ /**
214
+ * Calculates the position for the toolbar when dealing with nested extensions
215
+ */
216
+ const calculateToolbarPosition = (editorView, nextPos, state, extensionNode) => {
217
+ const {
218
+ state: {
219
+ schema,
220
+ selection
221
+ }
222
+ } = editorView;
223
+ const possibleMbeParent = findParentNodeOfType(schema.nodes.extensionFrame)(selection);
224
+ // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
225
+ const isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
226
+ let scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
227
+ if (fg('platform_editor_legacy_content_macro')) {
228
+ if (!extensionNode) {
229
+ return nextPos;
230
+ }
231
+ const isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
232
+ if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
233
+ return nextPos;
234
+ }
235
+ if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
236
+ // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
237
+
238
+ scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
239
+ }
240
+ } else {
241
+ if (!isBodiedExtensionInsideMBE) {
242
+ return nextPos;
243
+ }
244
+ }
245
+
246
+ // Ignored via go/ees005
247
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
248
+ const nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
249
+ const nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
250
+ const wrapperBounds = scrollWrapper.getBoundingClientRect();
251
+ const toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + BODIED_EXT_MBE_MARGIN_TOP;
252
+ return {
253
+ top: toolbarTopPos,
254
+ left: nextPos.left
255
+ };
130
256
  };
131
257
  export const getToolbarConfig = ({
132
258
  breakoutEnabled = true,
@@ -135,6 +261,7 @@ export const getToolbarConfig = ({
135
261
  editorAnalyticsAPI,
136
262
  extensionApi
137
263
  }) => (state, intl) => {
264
+ var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
138
265
  const {
139
266
  formatMessage
140
267
  } = intl;
@@ -146,137 +273,95 @@ export const getToolbarConfig = ({
146
273
  applyChangeToContextPanel = extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$context = extensionApi.contextPanel) === null || _extensionApi$context === void 0 ? void 0 : _extensionApi$context.actions.applyChange;
147
274
  editorAnalyticsAPI = extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$analyti = extensionApi.analytics) === null || _extensionApi$analyti === void 0 ? void 0 : _extensionApi$analyti.actions;
148
275
  }
149
- if (extensionState && !extensionState.showContextPanel && extensionState.element) {
150
- var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
151
- const nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
152
- const editButtonArray = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
153
- const breakoutButtonArray = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
154
- const extensionObj = getSelectedExtension(state, true);
276
+ if (!extensionState || extensionState.showContextPanel || !extensionState.element) {
277
+ return;
278
+ }
279
+ const nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
280
+ const editButtonItems = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
281
+ const breakoutItems = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
282
+ const extensionObj = getSelectedExtension(state, true);
155
283
 
156
- // Check if we need to show confirm dialog for delete button
157
- let confirmDialog;
158
- if (isReferencedSource(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
159
- confirmDialog = () => {
160
- const localSourceName = formatMessage(messages.unnamedSource);
161
- return {
162
- title: formatMessage(messages.deleteElementTitle),
163
- okButtonLabel: formatMessage(messages.confirmDeleteLinkedModalOKButton),
164
- message: formatMessage(messages.confirmDeleteLinkedModalMessage, {
165
- nodeName: getNodeName(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
166
- }),
167
- isReferentialityDialog: true,
168
- getChildrenInfo: () => getChildrenInfo(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node),
169
- checkboxLabel: formatMessage(messages.confirmModalCheckboxLabel),
170
- onConfirm: (isChecked = false) => clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)
171
- };
284
+ // Check if we need to show confirm dialog for delete button
285
+ let confirmDialog;
286
+ if (isReferencedSource(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
287
+ confirmDialog = () => {
288
+ const localSourceName = formatMessage(messages.unnamedSource);
289
+ return {
290
+ title: formatMessage(messages.deleteElementTitle),
291
+ okButtonLabel: formatMessage(messages.confirmDeleteLinkedModalOKButton),
292
+ message: formatMessage(messages.confirmDeleteLinkedModalMessage, {
293
+ nodeName: getNodeName(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
294
+ }),
295
+ isReferentialityDialog: true,
296
+ getChildrenInfo: () => getChildrenInfo(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node),
297
+ checkboxLabel: formatMessage(messages.confirmModalCheckboxLabel),
298
+ onConfirm: (isChecked = false) => clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)
172
299
  };
173
- }
174
- return {
175
- title: 'Extension floating controls',
176
- // Ignored via go/ees005
177
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
178
- getDomRef: () => extensionState.element.parentElement || undefined,
179
- nodeType,
180
- onPositionCalculated: (editorView, nextPos) => {
181
- const {
182
- state: {
183
- schema,
184
- selection
185
- }
186
- } = editorView;
187
- const extensionNode = getSelectedExtension(state, true);
188
- const possibleMbeParent = findParentNodeOfType(schema.nodes.extensionFrame)(selection);
189
- // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
190
- const isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
191
- let scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
192
- if (fg('platform_editor_legacy_content_macro')) {
193
- if (!extensionNode) {
194
- return nextPos;
195
- }
196
- const isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
197
- if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
198
- return nextPos;
199
- }
200
- if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
201
- // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
202
-
203
- scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
204
- }
205
- } else {
206
- if (!isBodiedExtensionInsideMBE) {
207
- return nextPos;
208
- }
209
- }
210
-
211
- // Ignored via go/ees005
212
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
213
- const nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
214
- const nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
215
- const wrapperBounds = scrollWrapper.getBoundingClientRect();
216
- const toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + BODIED_EXT_MBE_MARGIN_TOP;
217
- return {
218
- top: toolbarTopPos,
219
- left: nextPos.left
220
- };
221
- },
222
- items: [...editButtonArray, ...breakoutButtonArray, ...(editorExperiment('platform_editor_controls', 'control') ? [{
223
- type: 'separator',
224
- hidden: editButtonArray.length === 0 && breakoutButtonArray.length === 0
225
- }, {
226
- type: 'extensions-placeholder',
227
- separator: 'end'
228
- }, {
229
- type: 'copy-button',
230
- items: [{
231
- state,
232
- formatMessage: intl.formatMessage,
233
- nodeType
234
- }]
235
- }, {
236
- type: 'separator'
237
- }, {
238
- id: 'editor.extension.delete',
239
- type: 'button',
240
- icon: DeleteIcon,
241
- iconFallback: RemoveIcon,
242
- appearance: 'danger',
243
- onClick: removeExtension(editorAnalyticsAPI),
244
- onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
245
- onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
246
- onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
247
- onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
248
- focusEditoronEnter: true,
249
- title: formatMessage(commonMessages.remove),
250
- tabIndex: null,
251
- confirmDialog
252
- }] : [{
253
- type: 'separator',
254
- fullHeight: true
255
- }, {
256
- type: 'overflow-dropdown',
257
- options: [{
258
- title: 'Copy',
259
- onClick: () => {
260
- var _extensionApi$core, _extensionApi$floatin;
261
- extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 ? void 0 : _extensionApi$core.actions.execute( // @ts-ignore
262
- extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
263
- return true;
264
- },
265
- icon: /*#__PURE__*/React.createElement(CopyIcon, {
266
- label: "Copy"
267
- })
268
- }, {
269
- title: 'Delete',
270
- onClick: removeExtension(editorAnalyticsAPI),
271
- icon: /*#__PURE__*/React.createElement(DeleteIcon, {
272
- label: "Delete"
273
- })
274
- }]
275
- }])],
276
- scrollable: true
277
300
  };
278
301
  }
279
- return;
302
+ return {
303
+ title: 'Extension floating controls',
304
+ // Ignored via go/ees005
305
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
306
+ getDomRef: () => extensionState.element.parentElement || undefined,
307
+ nodeType,
308
+ onPositionCalculated: (editorView, nextPos) => calculateToolbarPosition(editorView, nextPos, state, extensionObj),
309
+ items: [...editButtonItems, ...breakoutItems, ...(editorExperiment('platform_editor_controls', 'control') ? [{
310
+ type: 'separator',
311
+ hidden: editButtonItems.length === 0 && breakoutItems.length === 0
312
+ }, {
313
+ type: 'extensions-placeholder',
314
+ separator: 'end'
315
+ }, {
316
+ type: 'copy-button',
317
+ items: [{
318
+ state,
319
+ formatMessage: intl.formatMessage,
320
+ nodeType
321
+ }]
322
+ }, {
323
+ type: 'separator'
324
+ }, {
325
+ id: 'editor.extension.delete',
326
+ type: 'button',
327
+ icon: DeleteIcon,
328
+ iconFallback: RemoveIcon,
329
+ appearance: 'danger',
330
+ onClick: removeExtension(editorAnalyticsAPI),
331
+ onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
332
+ onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
333
+ onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
334
+ onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
335
+ focusEditoronEnter: true,
336
+ title: formatMessage(commonMessages.remove),
337
+ tabIndex: null,
338
+ confirmDialog
339
+ }] : [{
340
+ type: 'separator',
341
+ fullHeight: true
342
+ }, {
343
+ type: 'overflow-dropdown',
344
+ options: [{
345
+ title: 'Copy',
346
+ onClick: () => {
347
+ var _extensionApi$core, _extensionApi$floatin;
348
+ extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 ? void 0 : _extensionApi$core.actions.execute( // @ts-ignore
349
+ extensionApi === null || extensionApi === void 0 ? void 0 : (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
350
+ return true;
351
+ },
352
+ icon: /*#__PURE__*/React.createElement(CopyIcon, {
353
+ label: "Copy"
354
+ })
355
+ }, {
356
+ title: 'Delete',
357
+ onClick: removeExtension(editorAnalyticsAPI),
358
+ icon: /*#__PURE__*/React.createElement(DeleteIcon, {
359
+ label: "Delete"
360
+ })
361
+ }]
362
+ }])],
363
+ scrollable: true
364
+ };
280
365
  };
281
366
  const clickWithCheckboxHandler = (isChecked, node) => (state, dispatch) => {
282
367
  if (!node) {
@@ -59,7 +59,7 @@ var isLayoutSupported = function isLayoutSupported(state, selectedExtNode) {
59
59
  // and not inside a layoutSection
60
60
  return !!((isMultiBodiedExtension || isNonEmbeddedBodiedExtension || isNonEmbeddedExtension) && !hasParentNodeOfType([layoutSection])(selection));
61
61
  };
62
- var breakoutOptions = function breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
62
+ var breakoutButtonListOptions = function breakoutButtonListOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
63
63
  var nodeWithPos = getSelectedExtension(state, true);
64
64
 
65
65
  // we should only return breakout options when breakouts are enabled and the node supports them
@@ -93,11 +93,85 @@ var breakoutOptions = function breakoutOptions(state, formatMessage, extensionSt
93
93
  }
94
94
  return [];
95
95
  };
96
+ var breakoutDropdownOptions = function breakoutDropdownOptions(state, formatMessage, breakoutEnabled, editorAnalyticsAPI) {
97
+ var nodeWithPos = getSelectedExtension(state, true);
98
+
99
+ // we should only return breakout options when breakouts are enabled and the node supports them
100
+ if (!nodeWithPos || !breakoutEnabled || !isLayoutSupported(state, nodeWithPos) || isNestedNBM(state, nodeWithPos)) {
101
+ return [];
102
+ }
103
+ var layout = nodeWithPos.node.attrs.layout;
104
+ var title = '';
105
+ var IconComponent;
106
+ switch (layout) {
107
+ case 'wide':
108
+ title = formatMessage(commonMessages.layoutStateWide);
109
+ IconComponent = ContentWidthWideIcon;
110
+ break;
111
+ case 'full-width':
112
+ title = formatMessage(commonMessages.layoutStateFullWidth);
113
+ IconComponent = ExpandHorizontalIcon;
114
+ break;
115
+ case 'default':
116
+ default:
117
+ title = formatMessage(commonMessages.layoutStateFixedWidth);
118
+ IconComponent = ContentWidthNarrowIcon;
119
+ break;
120
+ }
121
+ var options = [{
122
+ id: 'editor.extensions.width.default',
123
+ title: formatMessage(commonMessages.layoutFixedWidth),
124
+ onClick: updateExtensionLayout('default', editorAnalyticsAPI),
125
+ selected: layout === 'default',
126
+ icon: /*#__PURE__*/React.createElement(ContentWidthNarrowIcon, {
127
+ color: "currentColor",
128
+ spacing: "spacious",
129
+ label: formatMessage(commonMessages.layoutFixedWidth)
130
+ })
131
+ }, {
132
+ id: 'editor.extensions.width.wide',
133
+ title: formatMessage(commonMessages.layoutWide),
134
+ onClick: updateExtensionLayout('wide', editorAnalyticsAPI),
135
+ selected: layout === 'wide',
136
+ icon: /*#__PURE__*/React.createElement(ContentWidthWideIcon, {
137
+ color: "currentColor",
138
+ spacing: "spacious",
139
+ label: formatMessage(commonMessages.layoutWide)
140
+ })
141
+ }, {
142
+ id: 'editor.extensions.width.full-width',
143
+ title: formatMessage(commonMessages.layoutFullWidth),
144
+ onClick: updateExtensionLayout('full-width', editorAnalyticsAPI),
145
+ selected: layout === 'full-width',
146
+ icon: /*#__PURE__*/React.createElement(ExpandHorizontalIcon, {
147
+ color: "currentColor",
148
+ spacing: "spacious",
149
+ label: formatMessage(commonMessages.layoutFullWidth)
150
+ })
151
+ }];
152
+ return [{
153
+ id: 'extensions-width-options-toolbar-item',
154
+ testId: 'extensions-width-options-toolbar-dropdown',
155
+ type: 'dropdown',
156
+ options: options,
157
+ title: title,
158
+ iconBefore: function iconBefore() {
159
+ return /*#__PURE__*/React.createElement(IconComponent, {
160
+ color: "currentColor",
161
+ spacing: "spacious",
162
+ label: title
163
+ });
164
+ }
165
+ }];
166
+ };
167
+ var breakoutOptions = function breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI) {
168
+ return editorExperiment('platform_editor_controls', 'variant1') ? breakoutDropdownOptions(state, formatMessage, breakoutEnabled, editorAnalyticsAPI) : breakoutButtonListOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
169
+ };
96
170
  var editButton = function editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI) {
97
171
  if (!extensionState.showEditButton) {
98
172
  return [];
99
173
  }
100
- return [{
174
+ var editButtonItems = [{
101
175
  id: 'editor.extension.edit',
102
176
  type: 'button',
103
177
  icon: EditIcon,
@@ -115,6 +189,55 @@ var editButton = function editButton(formatMessage, extensionState, applyChangeT
115
189
  tabIndex: null,
116
190
  focusEditoronEnter: true
117
191
  }];
192
+ if (editorExperiment('platform_editor_controls', 'variant1')) {
193
+ editButtonItems.push({
194
+ type: 'separator',
195
+ fullHeight: true
196
+ });
197
+ }
198
+ return editButtonItems;
199
+ };
200
+
201
+ /**
202
+ * Calculates the position for the toolbar when dealing with nested extensions
203
+ */
204
+ var calculateToolbarPosition = function calculateToolbarPosition(editorView, nextPos, state, extensionNode) {
205
+ var _editorView$state = editorView.state,
206
+ schema = _editorView$state.schema,
207
+ selection = _editorView$state.selection;
208
+ var possibleMbeParent = findParentNodeOfType(schema.nodes.extensionFrame)(selection);
209
+ // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
210
+ var isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
211
+ var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
212
+ if (fg('platform_editor_legacy_content_macro')) {
213
+ if (!extensionNode) {
214
+ return nextPos;
215
+ }
216
+ var isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
217
+ if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
218
+ return nextPos;
219
+ }
220
+ if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
221
+ // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
222
+
223
+ scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
224
+ }
225
+ } else {
226
+ if (!isBodiedExtensionInsideMBE) {
227
+ return nextPos;
228
+ }
229
+ }
230
+
231
+ // Ignored via go/ees005
232
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
233
+ var nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
234
+ var nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
235
+ var wrapperBounds = scrollWrapper.getBoundingClientRect();
236
+ var toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + BODIED_EXT_MBE_MARGIN_TOP;
237
+ return {
238
+ top: toolbarTopPos,
239
+ left: nextPos.left
240
+ };
118
241
  };
119
242
  export var getToolbarConfig = function getToolbarConfig(_ref) {
120
243
  var _ref$breakoutEnabled = _ref.breakoutEnabled,
@@ -124,6 +247,7 @@ export var getToolbarConfig = function getToolbarConfig(_ref) {
124
247
  editorAnalyticsAPI = _ref.editorAnalyticsAPI,
125
248
  extensionApi = _ref.extensionApi;
126
249
  return function (state, intl) {
250
+ var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
127
251
  var formatMessage = intl.formatMessage;
128
252
  var extensionState = getPluginState(state);
129
253
  if (fg('platform_editor_legacy_content_macro')) {
@@ -133,141 +257,104 @@ export var getToolbarConfig = function getToolbarConfig(_ref) {
133
257
  applyChangeToContextPanel = extensionApi === null || extensionApi === void 0 || (_extensionApi$context = extensionApi.contextPanel) === null || _extensionApi$context === void 0 ? void 0 : _extensionApi$context.actions.applyChange;
134
258
  editorAnalyticsAPI = extensionApi === null || extensionApi === void 0 || (_extensionApi$analyti = extensionApi.analytics) === null || _extensionApi$analyti === void 0 ? void 0 : _extensionApi$analyti.actions;
135
259
  }
136
- if (extensionState && !extensionState.showContextPanel && extensionState.element) {
137
- var _hoverDecoration, _hoverDecoration2, _hoverDecoration3, _hoverDecoration4;
138
- var nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
139
- var editButtonArray = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
140
- var breakoutButtonArray = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
141
- var extensionObj = getSelectedExtension(state, true);
142
-
143
- // Check if we need to show confirm dialog for delete button
144
- var confirmDialog;
145
- if (isReferencedSource(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
146
- confirmDialog = function confirmDialog() {
147
- var localSourceName = formatMessage(messages.unnamedSource);
148
- return {
149
- title: formatMessage(messages.deleteElementTitle),
150
- okButtonLabel: formatMessage(messages.confirmDeleteLinkedModalOKButton),
151
- message: formatMessage(messages.confirmDeleteLinkedModalMessage, {
152
- nodeName: getNodeName(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
153
- }),
154
- isReferentialityDialog: true,
155
- getChildrenInfo: function getChildrenInfo() {
156
- return _getChildrenInfo(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
157
- },
158
- checkboxLabel: formatMessage(messages.confirmModalCheckboxLabel),
159
- onConfirm: function onConfirm() {
160
- var isChecked = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
161
- return clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
162
- }
163
- };
164
- };
165
- }
166
- return {
167
- title: 'Extension floating controls',
168
- // Ignored via go/ees005
169
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
170
- getDomRef: function getDomRef() {
171
- return extensionState.element.parentElement || undefined;
172
- },
173
- nodeType: nodeType,
174
- onPositionCalculated: function onPositionCalculated(editorView, nextPos) {
175
- var _editorView$state = editorView.state,
176
- schema = _editorView$state.schema,
177
- selection = _editorView$state.selection;
178
- var extensionNode = getSelectedExtension(state, true);
179
- var possibleMbeParent = findParentNodeOfType(schema.nodes.extensionFrame)(selection);
180
- // We only want to use calculated position in case of a bodiedExtension present inside an MBE node
181
- var isBodiedExtensionInsideMBE = possibleMbeParent && (extensionNode === null || extensionNode === void 0 ? void 0 : extensionNode.node.type.name) === 'bodiedExtension';
182
- var scrollWrapper = editorView.dom.closest('.fabric-editor-popup-scroll-parent') || document.body;
183
- if (fg('platform_editor_legacy_content_macro')) {
184
- if (!extensionNode) {
185
- return nextPos;
186
- }
187
- var isInsideEditableExtensionArea = !!editorView.dom.closest('.extension-editable-area');
188
- if (!isBodiedExtensionInsideMBE && !isInsideEditableExtensionArea) {
189
- return nextPos;
190
- }
191
- if (isInsideEditableExtensionArea && scrollWrapper.parentElement) {
192
- // The editable extension area may have its own scroll wrapper, so we want to keep searching up the tree for the page level scroll wrapper.
260
+ if (!extensionState || extensionState.showContextPanel || !extensionState.element) {
261
+ return;
262
+ }
263
+ var nodeType = [state.schema.nodes.extension, state.schema.nodes.inlineExtension, state.schema.nodes.bodiedExtension, state.schema.nodes.multiBodiedExtension];
264
+ var editButtonItems = editButton(formatMessage, extensionState, applyChangeToContextPanel, editorAnalyticsAPI);
265
+ var breakoutItems = breakoutOptions(state, formatMessage, extensionState, breakoutEnabled, editorAnalyticsAPI);
266
+ var extensionObj = getSelectedExtension(state, true);
193
267
 
194
- scrollWrapper = scrollWrapper.parentElement.closest('.fabric-editor-popup-scroll-parent') || scrollWrapper;
195
- }
196
- } else {
197
- if (!isBodiedExtensionInsideMBE) {
198
- return nextPos;
199
- }
268
+ // Check if we need to show confirm dialog for delete button
269
+ var confirmDialog;
270
+ if (isReferencedSource(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node)) {
271
+ confirmDialog = function confirmDialog() {
272
+ var localSourceName = formatMessage(messages.unnamedSource);
273
+ return {
274
+ title: formatMessage(messages.deleteElementTitle),
275
+ okButtonLabel: formatMessage(messages.confirmDeleteLinkedModalOKButton),
276
+ message: formatMessage(messages.confirmDeleteLinkedModalMessage, {
277
+ nodeName: getNodeName(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node) || localSourceName
278
+ }),
279
+ isReferentialityDialog: true,
280
+ getChildrenInfo: function getChildrenInfo() {
281
+ return _getChildrenInfo(state, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
282
+ },
283
+ checkboxLabel: formatMessage(messages.confirmModalCheckboxLabel),
284
+ onConfirm: function onConfirm() {
285
+ var isChecked = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
286
+ return clickWithCheckboxHandler(isChecked, extensionObj === null || extensionObj === void 0 ? void 0 : extensionObj.node);
200
287
  }
201
-
202
- // Ignored via go/ees005
203
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
204
- var nestedBodiedExtensionDomElement = editorView.nodeDOM(extensionNode.pos);
205
- var nestedBodiedExtensionRect = nestedBodiedExtensionDomElement === null || nestedBodiedExtensionDomElement === void 0 ? void 0 : nestedBodiedExtensionDomElement.getBoundingClientRect();
206
- var wrapperBounds = scrollWrapper.getBoundingClientRect();
207
- var toolbarTopPos = nestedBodiedExtensionRect.bottom - wrapperBounds.top + scrollWrapper.scrollTop + BODIED_EXT_MBE_MARGIN_TOP;
208
- return {
209
- top: toolbarTopPos,
210
- left: nextPos.left
211
- };
212
- },
213
- items: [].concat(_toConsumableArray(editButtonArray), _toConsumableArray(breakoutButtonArray), _toConsumableArray(editorExperiment('platform_editor_controls', 'control') ? [{
214
- type: 'separator',
215
- hidden: editButtonArray.length === 0 && breakoutButtonArray.length === 0
216
- }, {
217
- type: 'extensions-placeholder',
218
- separator: 'end'
219
- }, {
220
- type: 'copy-button',
221
- items: [{
222
- state: state,
223
- formatMessage: intl.formatMessage,
224
- nodeType: nodeType
225
- }]
226
- }, {
227
- type: 'separator'
228
- }, {
229
- id: 'editor.extension.delete',
230
- type: 'button',
231
- icon: DeleteIcon,
232
- iconFallback: RemoveIcon,
233
- appearance: 'danger',
234
- onClick: removeExtension(editorAnalyticsAPI),
235
- onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
236
- onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
237
- onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
238
- onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
239
- focusEditoronEnter: true,
240
- title: formatMessage(commonMessages.remove),
241
- tabIndex: null,
242
- confirmDialog: confirmDialog
243
- }] : [{
244
- type: 'separator',
245
- fullHeight: true
246
- }, {
247
- type: 'overflow-dropdown',
248
- options: [{
249
- title: 'Copy',
250
- onClick: function onClick() {
251
- var _extensionApi$core, _extensionApi$floatin;
252
- extensionApi === null || extensionApi === void 0 || (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 || _extensionApi$core.actions.execute( // @ts-ignore
253
- extensionApi === null || extensionApi === void 0 || (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
254
- return true;
255
- },
256
- icon: /*#__PURE__*/React.createElement(CopyIcon, {
257
- label: "Copy"
258
- })
259
- }, {
260
- title: 'Delete',
261
- onClick: removeExtension(editorAnalyticsAPI),
262
- icon: /*#__PURE__*/React.createElement(DeleteIcon, {
263
- label: "Delete"
264
- })
265
- }]
266
- }])),
267
- scrollable: true
288
+ };
268
289
  };
269
290
  }
270
- return;
291
+ return {
292
+ title: 'Extension floating controls',
293
+ // Ignored via go/ees005
294
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
295
+ getDomRef: function getDomRef() {
296
+ return extensionState.element.parentElement || undefined;
297
+ },
298
+ nodeType: nodeType,
299
+ onPositionCalculated: function onPositionCalculated(editorView, nextPos) {
300
+ return calculateToolbarPosition(editorView, nextPos, state, extensionObj);
301
+ },
302
+ items: [].concat(_toConsumableArray(editButtonItems), _toConsumableArray(breakoutItems), _toConsumableArray(editorExperiment('platform_editor_controls', 'control') ? [{
303
+ type: 'separator',
304
+ hidden: editButtonItems.length === 0 && breakoutItems.length === 0
305
+ }, {
306
+ type: 'extensions-placeholder',
307
+ separator: 'end'
308
+ }, {
309
+ type: 'copy-button',
310
+ items: [{
311
+ state: state,
312
+ formatMessage: intl.formatMessage,
313
+ nodeType: nodeType
314
+ }]
315
+ }, {
316
+ type: 'separator'
317
+ }, {
318
+ id: 'editor.extension.delete',
319
+ type: 'button',
320
+ icon: DeleteIcon,
321
+ iconFallback: RemoveIcon,
322
+ appearance: 'danger',
323
+ onClick: removeExtension(editorAnalyticsAPI),
324
+ onMouseEnter: (_hoverDecoration = hoverDecoration) === null || _hoverDecoration === void 0 ? void 0 : _hoverDecoration(nodeType, true),
325
+ onMouseLeave: (_hoverDecoration2 = hoverDecoration) === null || _hoverDecoration2 === void 0 ? void 0 : _hoverDecoration2(nodeType, false),
326
+ onFocus: (_hoverDecoration3 = hoverDecoration) === null || _hoverDecoration3 === void 0 ? void 0 : _hoverDecoration3(nodeType, true),
327
+ onBlur: (_hoverDecoration4 = hoverDecoration) === null || _hoverDecoration4 === void 0 ? void 0 : _hoverDecoration4(nodeType, false),
328
+ focusEditoronEnter: true,
329
+ title: formatMessage(commonMessages.remove),
330
+ tabIndex: null,
331
+ confirmDialog: confirmDialog
332
+ }] : [{
333
+ type: 'separator',
334
+ fullHeight: true
335
+ }, {
336
+ type: 'overflow-dropdown',
337
+ options: [{
338
+ title: 'Copy',
339
+ onClick: function onClick() {
340
+ var _extensionApi$core, _extensionApi$floatin;
341
+ extensionApi === null || extensionApi === void 0 || (_extensionApi$core = extensionApi.core) === null || _extensionApi$core === void 0 || _extensionApi$core.actions.execute( // @ts-ignore
342
+ extensionApi === null || extensionApi === void 0 || (_extensionApi$floatin = extensionApi.floatingToolbar) === null || _extensionApi$floatin === void 0 ? void 0 : _extensionApi$floatin.commands.copyNode(nodeType));
343
+ return true;
344
+ },
345
+ icon: /*#__PURE__*/React.createElement(CopyIcon, {
346
+ label: "Copy"
347
+ })
348
+ }, {
349
+ title: 'Delete',
350
+ onClick: removeExtension(editorAnalyticsAPI),
351
+ icon: /*#__PURE__*/React.createElement(DeleteIcon, {
352
+ label: "Delete"
353
+ })
354
+ }]
355
+ }])),
356
+ scrollable: true
357
+ };
271
358
  };
272
359
  };
273
360
  var clickWithCheckboxHandler = function clickWithCheckboxHandler(isChecked, node) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-extension",
3
- "version": "5.0.3",
3
+ "version": "5.0.5",
4
4
  "description": "editor-plugin-extension plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -32,7 +32,7 @@
32
32
  "@atlaskit/button": "^21.1.0",
33
33
  "@atlaskit/checkbox": "^17.0.0",
34
34
  "@atlaskit/datetime-picker": "^16.1.0",
35
- "@atlaskit/editor-common": "^102.3.0",
35
+ "@atlaskit/editor-common": "^102.4.0",
36
36
  "@atlaskit/editor-json-transformer": "^8.24.0",
37
37
  "@atlaskit/editor-plugin-analytics": "^2.1.0",
38
38
  "@atlaskit/editor-plugin-context-identifier": "^2.0.0",
@@ -46,7 +46,7 @@
46
46
  "@atlaskit/empty-state": "^9.0.0",
47
47
  "@atlaskit/form": "^12.0.0",
48
48
  "@atlaskit/heading": "^5.1.0",
49
- "@atlaskit/icon": "^24.1.0",
49
+ "@atlaskit/icon": "^25.0.0",
50
50
  "@atlaskit/platform-feature-flags": "^1.1.0",
51
51
  "@atlaskit/primitives": "^14.1.0",
52
52
  "@atlaskit/radio": "^8.0.0",
@@ -58,7 +58,7 @@
58
58
  "@atlaskit/textarea": "^8.0.0",
59
59
  "@atlaskit/textfield": "^8.0.0",
60
60
  "@atlaskit/theme": "^18.0.0",
61
- "@atlaskit/tmp-editor-statsig": "^3.5.0",
61
+ "@atlaskit/tmp-editor-statsig": "^3.6.0",
62
62
  "@atlaskit/toggle": "^15.0.0",
63
63
  "@atlaskit/tokens": "^4.4.0",
64
64
  "@atlaskit/tooltip": "^20.0.0",