@atlaskit/editor-plugin-selection-extension 4.0.0 → 4.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 (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/pm-plugins/utils/index.js +23 -0
  3. package/dist/cjs/selectionExtensionPlugin.js +15 -5
  4. package/dist/cjs/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
  5. package/dist/cjs/ui/toolbar-components/MenuItem.js +57 -0
  6. package/dist/cjs/ui/toolbar-components/ToolbarButton.js +29 -0
  7. package/dist/cjs/ui/toolbar-components/ToolbarMenu.js +30 -0
  8. package/dist/cjs/ui/toolbar-components/register-inline-toolbar.js +114 -0
  9. package/dist/cjs/ui/toolbar-components.js +80 -0
  10. package/dist/cjs/ui/utils/migrate-selection-extention.js +52 -0
  11. package/dist/es2019/pm-plugins/utils/index.js +25 -0
  12. package/dist/es2019/selectionExtensionPlugin.js +12 -2
  13. package/dist/es2019/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
  14. package/dist/es2019/ui/toolbar-components/MenuItem.js +52 -0
  15. package/dist/es2019/ui/toolbar-components/ToolbarButton.js +23 -0
  16. package/dist/es2019/ui/toolbar-components/ToolbarMenu.js +24 -0
  17. package/dist/es2019/ui/toolbar-components/register-inline-toolbar.js +110 -0
  18. package/dist/es2019/ui/toolbar-components.js +67 -0
  19. package/dist/es2019/ui/utils/migrate-selection-extention.js +46 -0
  20. package/dist/esm/pm-plugins/utils/index.js +22 -0
  21. package/dist/esm/selectionExtensionPlugin.js +15 -5
  22. package/dist/esm/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
  23. package/dist/esm/ui/toolbar-components/MenuItem.js +50 -0
  24. package/dist/esm/ui/toolbar-components/ToolbarButton.js +22 -0
  25. package/dist/esm/ui/toolbar-components/ToolbarMenu.js +23 -0
  26. package/dist/esm/ui/toolbar-components/register-inline-toolbar.js +107 -0
  27. package/dist/esm/ui/toolbar-components.js +73 -0
  28. package/dist/esm/ui/utils/migrate-selection-extention.js +46 -0
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/pm-plugins/utils/index.d.ts +2 -1
  31. package/dist/types/selectionExtensionPluginType.d.ts +4 -2
  32. package/dist/types/ui/toolbar-components/MenuItem.d.ts +10 -0
  33. package/dist/types/ui/toolbar-components/ToolbarButton.d.ts +10 -0
  34. package/dist/types/ui/toolbar-components/ToolbarMenu.d.ts +10 -0
  35. package/dist/types/ui/toolbar-components/register-inline-toolbar.d.ts +11 -0
  36. package/dist/types/ui/toolbar-components.d.ts +11 -0
  37. package/dist/types/ui/utils/migrate-selection-extention.d.ts +14 -0
  38. package/dist/types-ts4.5/index.d.ts +1 -1
  39. package/dist/types-ts4.5/pm-plugins/utils/index.d.ts +2 -1
  40. package/dist/types-ts4.5/selectionExtensionPluginType.d.ts +4 -2
  41. package/dist/types-ts4.5/ui/toolbar-components/MenuItem.d.ts +10 -0
  42. package/dist/types-ts4.5/ui/toolbar-components/ToolbarButton.d.ts +10 -0
  43. package/dist/types-ts4.5/ui/toolbar-components/ToolbarMenu.d.ts +10 -0
  44. package/dist/types-ts4.5/ui/toolbar-components/register-inline-toolbar.d.ts +11 -0
  45. package/dist/types-ts4.5/ui/toolbar-components.d.ts +11 -0
  46. package/dist/types-ts4.5/ui/utils/migrate-selection-extention.d.ts +14 -0
  47. package/package.json +5 -4
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarTooltip, ToolbarButton as BaseToolbarButton } from '@atlaskit/editor-toolbar';
4
+ export const ToolbarButton = ({
5
+ api,
6
+ config
7
+ }) => {
8
+ const dockingPreference = useSharedPluginStateSelector(api, 'userPreferences.preferences.toolbarDockingPosition');
9
+ const isDockedAtTop = dockingPreference === 'top';
10
+ if (isDockedAtTop) {
11
+ return null;
12
+ }
13
+ const Icon = config.icon;
14
+ return /*#__PURE__*/React.createElement(ToolbarTooltip, {
15
+ content: config.tooltip
16
+ }, /*#__PURE__*/React.createElement(BaseToolbarButton, {
17
+ iconBefore: /*#__PURE__*/React.createElement(Icon, {
18
+ label: ""
19
+ }),
20
+ isDisabled: config.isDisabled,
21
+ onClick: config.onClick
22
+ }, config.label));
23
+ };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarTooltip, ToolbarDropdownMenu } from '@atlaskit/editor-toolbar';
4
+ export const ToolbarMenu = ({
5
+ api,
6
+ config,
7
+ children
8
+ }) => {
9
+ const dockingPreference = useSharedPluginStateSelector(api, 'userPreferences.preferences.toolbarDockingPosition');
10
+ const isDockedAtTop = dockingPreference === 'top';
11
+ if (isDockedAtTop) {
12
+ return null;
13
+ }
14
+ const Icon = config.icon;
15
+ return /*#__PURE__*/React.createElement(ToolbarTooltip, {
16
+ content: config.tooltip
17
+ }, /*#__PURE__*/React.createElement(ToolbarDropdownMenu, {
18
+ iconBefore: /*#__PURE__*/React.createElement(Icon, {
19
+ label: ""
20
+ }),
21
+ isDisabled: config.isDisabled,
22
+ onClick: config.onClick
23
+ }, children));
24
+ };
@@ -0,0 +1,110 @@
1
+ import React from 'react';
2
+ import { SELECTION_EXTENSION_MENU_SECTION, APPS_SECTION } from '@atlaskit/editor-common/toolbar';
3
+ import { MenuItem } from './MenuItem';
4
+ import { ToolbarButton } from './ToolbarButton';
5
+ import { ToolbarMenu } from './ToolbarMenu';
6
+ const EXTENSION_RANK_MULTIPLIER = 100;
7
+ export const registerInlineToolbar = ({
8
+ api,
9
+ extension,
10
+ index
11
+ }) => {
12
+ const {
13
+ key,
14
+ inlineToolbar
15
+ } = extension;
16
+ const baseKey = `selection-extension-${key}`;
17
+ const components = [];
18
+ if (!inlineToolbar) {
19
+ return components;
20
+ }
21
+ const {
22
+ getToolbarItem,
23
+ getMenuItems
24
+ } = inlineToolbar;
25
+ const groupKey = `${baseKey}-toolbar-group`;
26
+ const toolbarItemKey = `${baseKey}-toolbar-${getMenuItems ? 'menu' : 'button'}`;
27
+ const menuSectionKey = `${baseKey}-toolbar-menu-section`;
28
+ if (getToolbarItem) {
29
+ // first we register the group for the button or menu to be added to
30
+ components.push({
31
+ type: 'group',
32
+ key: groupKey,
33
+ parents: [{
34
+ type: APPS_SECTION.type,
35
+ key: APPS_SECTION.key,
36
+ rank: (index + 1) * EXTENSION_RANK_MULTIPLIER
37
+ }]
38
+ });
39
+ const toolbarItemConfig = getToolbarItem();
40
+
41
+ // if toolbar item has menu items, assume it's a menu
42
+ if (getMenuItems) {
43
+ components.push({
44
+ type: 'menu',
45
+ key: toolbarItemKey,
46
+ parents: [{
47
+ type: 'group',
48
+ key: groupKey,
49
+ rank: EXTENSION_RANK_MULTIPLIER
50
+ }],
51
+ component: () => {
52
+ return /*#__PURE__*/React.createElement(ToolbarMenu, {
53
+ api: api,
54
+ config: toolbarItemConfig
55
+ });
56
+ }
57
+ });
58
+ } else {
59
+ // else just regsiter a button
60
+ components.push({
61
+ type: 'button',
62
+ key: toolbarItemKey,
63
+ parents: [{
64
+ type: 'group',
65
+ key: groupKey,
66
+ rank: EXTENSION_RANK_MULTIPLIER
67
+ }],
68
+ component: () => {
69
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
70
+ api: api,
71
+ config: toolbarItemConfig
72
+ });
73
+ }
74
+ });
75
+ }
76
+ }
77
+ if (getMenuItems) {
78
+ if (getToolbarItem) {
79
+ components.push({
80
+ type: 'menu-section',
81
+ key: menuSectionKey,
82
+ parents: [{
83
+ type: 'menu',
84
+ key: toolbarItemKey,
85
+ rank: EXTENSION_RANK_MULTIPLIER
86
+ }]
87
+ });
88
+ }
89
+
90
+ // Remove ExtensionMenuSectionConfiguration - only care about items
91
+ const menuItems = getMenuItems().filter(item => 'label' in item && 'icon' in item);
92
+ components.push({
93
+ type: 'menu-item',
94
+ key,
95
+ parents: [{
96
+ type: 'menu-section',
97
+ // if we have a custom menu, place items in there, otherwise in the overflow menu
98
+ key: getToolbarItem ? menuSectionKey : SELECTION_EXTENSION_MENU_SECTION.key,
99
+ rank: (index + 1) * EXTENSION_RANK_MULTIPLIER
100
+ }],
101
+ component: () => {
102
+ return /*#__PURE__*/React.createElement(MenuItem, {
103
+ api: api,
104
+ extensionMenuItems: menuItems
105
+ });
106
+ }
107
+ });
108
+ }
109
+ return components;
110
+ };
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import { APPS_SECTION, OVERFLOW_MENU, OVERFLOW_MENU_RANK, SELECTION_EXTENSION_MENU_SECTION, TOOLBAR_RANK, TOOLBARS } from '@atlaskit/editor-common/toolbar';
3
+ import { MenuItem } from './toolbar-components/MenuItem';
4
+ import { registerInlineToolbar } from './toolbar-components/register-inline-toolbar';
5
+ import { migrateSelectionExtensionToMenuItem } from './utils/migrate-selection-extention';
6
+ export const getToolbarComponents = ({
7
+ api,
8
+ config
9
+ }) => {
10
+ var _config$extensionList, _config$extensions, _config$extensions$fi;
11
+ const extensionToolbarComponents = (config === null || config === void 0 ? void 0 : (_config$extensionList = config.extensionList) === null || _config$extensionList === void 0 ? void 0 : _config$extensionList.flatMap((extension, index) => registerInlineToolbar({
12
+ api,
13
+ extension,
14
+ index
15
+ }))) || [];
16
+
17
+ /**
18
+ * Continue to support firstParty apps for now as some apps haven't migrated yet, this simply converts apps to new ExtensionMenuItemConfiguration type
19
+ * to process easier. extensionList and extensions?.firstParty will most likely be mutually exclusive.
20
+ *
21
+ * **Warning:** This is called on every selection change to ensure calls to api?.selectionExtension.actions.getSelectionAdf() are
22
+ * fresh and up to date.
23
+ */
24
+ const firstPartyExtensions = (config === null || config === void 0 ? void 0 : (_config$extensions = config.extensions) === null || _config$extensions === void 0 ? void 0 : (_config$extensions$fi = _config$extensions.firstParty) === null || _config$extensions$fi === void 0 ? void 0 : _config$extensions$fi.map(extension => migrateSelectionExtensionToMenuItem(extension, api)).filter(extension => extension !== undefined)) || [];
25
+ return [{
26
+ type: APPS_SECTION.type,
27
+ key: APPS_SECTION.key,
28
+ parents: [{
29
+ type: 'toolbar',
30
+ key: TOOLBARS.INLINE_TEXT_TOOLBAR,
31
+ rank: TOOLBAR_RANK[APPS_SECTION.key]
32
+ }, {
33
+ type: 'toolbar',
34
+ key: TOOLBARS.PRIMARY_TOOLBAR,
35
+ rank: TOOLBAR_RANK[APPS_SECTION.key]
36
+ }]
37
+ },
38
+ // also register a section inside the overflow menu for extensions which only have menu items
39
+ {
40
+ type: SELECTION_EXTENSION_MENU_SECTION.type,
41
+ key: SELECTION_EXTENSION_MENU_SECTION.key,
42
+ parents: [{
43
+ key: OVERFLOW_MENU.key,
44
+ type: OVERFLOW_MENU.type,
45
+ rank: OVERFLOW_MENU_RANK[SELECTION_EXTENSION_MENU_SECTION.key]
46
+ }]
47
+ }, ...extensionToolbarComponents, ...registerFirstPartyExtensions(api, firstPartyExtensions)];
48
+ };
49
+ const registerFirstPartyExtensions = (api, extensions) => {
50
+ const components = [];
51
+ components.push({
52
+ type: 'menu-item',
53
+ key: 'first-party-extensions-menu-item',
54
+ parents: [{
55
+ type: 'menu-section',
56
+ key: SELECTION_EXTENSION_MENU_SECTION.key,
57
+ rank: 100
58
+ }],
59
+ component: () => {
60
+ return /*#__PURE__*/React.createElement(MenuItem, {
61
+ api: api,
62
+ extensionMenuItems: extensions
63
+ });
64
+ }
65
+ });
66
+ return components;
67
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ *
3
+ * TODO: ED-29157 - remove once Confluence migrates to `extensionList`API
4
+ *
5
+ * NOTES:
6
+ * - This is temporary until we deprecate SelectionExtension and DynamicSelectionExtension.
7
+ * - Only supporing SelectionExtension as DynamicSelectionExtension is not being used and will be deprecated.
8
+ *
9
+ * Converts a SelectionExtension -> ExtensionMenuItemConfiguration. This allows existing extensions to appear in the new toolbar.
10
+ */
11
+ export const migrateSelectionExtensionToMenuItem = (extension, api) => {
12
+ if (!extension.icon) {
13
+ return undefined;
14
+ }
15
+
16
+ // Warning! These are inlined because the onClick handler must have up to date references to selection (which is awkwaradly set during extension.onClick invocation).
17
+ const getSelection = () => {
18
+ var _sharedState$activeEx;
19
+ const sharedState = api === null || api === void 0 ? void 0 : api.selectionExtension.sharedState.currentState();
20
+ return sharedState === null || sharedState === void 0 ? void 0 : (_sharedState$activeEx = sharedState.activeExtension) === null || _sharedState$activeEx === void 0 ? void 0 : _sharedState$activeEx.selection;
21
+ };
22
+ return {
23
+ label: extension.name,
24
+ icon: extension.icon,
25
+ isDisabled: extension.isDisabled && extension.isDisabled({
26
+ selection: getSelection(),
27
+ // pass undefined as no consumers use this
28
+ selectedNodeAdf: undefined,
29
+ selectionRanges: undefined
30
+ }),
31
+ /**
32
+ * SelectionExtension supports passing through selection, selectionAdf, and selectionRanges.
33
+ *
34
+ * To support backwards compatibility wrap the onClick with these parameters here and let MenuItem invoke onClick using its expected signature.
35
+ */
36
+ onClick: () => {
37
+ const selectionAdf = api === null || api === void 0 ? void 0 : api.selectionExtension.actions.getSelectionAdf();
38
+ extension.onClick && extension.onClick({
39
+ selection: getSelection(),
40
+ selectedNodeAdf: selectionAdf === null || selectionAdf === void 0 ? void 0 : selectionAdf.selectedNodeAdf,
41
+ selectionRanges: selectionAdf === null || selectionAdf === void 0 ? void 0 : selectionAdf.selectionRanges
42
+ });
43
+ },
44
+ contentComponent: extension.component
45
+ };
46
+ };
@@ -122,4 +122,26 @@ export function getSelectionAdfInfo(state) {
122
122
  return _objectSpread(_objectSpread({}, selectionInfo), {}, {
123
123
  selectedNodeAdf: selectedNodeAdf
124
124
  });
125
+ }
126
+ export function getSelectionAdfInfoNew(selection) {
127
+ var selectionInfo = {
128
+ selectedNode: selection.$from.node(),
129
+ nodePos: selection.$from.depth > 0 ? selection.$from.before() : selection.from
130
+ };
131
+ if (selection instanceof TextSelection) {
132
+ var $from = selection.$from,
133
+ $to = selection.$to;
134
+ if ($from.parent === $to.parent) {
135
+ selectionInfo = getSelectionInfoFromSameNode(selection);
136
+ } else {
137
+ // TODO: ED-28405 - when selection spans multiple nodes including nested node, we need to iterate through the nodes
138
+ }
139
+ } else if (selection instanceof CellSelection) {
140
+ selectionInfo = getSelectionInfoFromCellSelection(selection);
141
+ }
142
+ var serializer = new JSONTransformer();
143
+ var selectedNodeAdf = serializer.encodeNode(selectionInfo.selectedNode);
144
+ return _objectSpread(_objectSpread({}, selectionInfo), {}, {
145
+ selectedNodeAdf: selectedNodeAdf
146
+ });
125
147
  }
@@ -4,6 +4,7 @@ import { selectionExtensionMessages } from '@atlaskit/editor-common/messages';
4
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
5
5
  import { usePluginStateEffect } from '@atlaskit/editor-common/use-plugin-state-effect';
6
6
  import { fg } from '@atlaskit/platform-feature-flags';
7
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
8
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
8
9
  import { insertAdfAtEndOfDoc as _insertAdfAtEndOfDoc } from './pm-plugins/actions/insertAdfAtEndOfDoc';
9
10
  import { replaceWithAdf as _replaceWithAdf } from './pm-plugins/actions/replaceWithAdf';
@@ -13,7 +14,8 @@ import { SelectionExtensionActionTypes } from './types';
13
14
  import { SelectionExtensionComponentWrapper } from './ui/extension/SelectionExtensionComponentWrapper';
14
15
  import { getMenuItemExtensions, getToolbarItemExtensions } from './ui/extensions';
15
16
  import { LegacyPrimaryToolbarComponent } from './ui/LegacyToolbarComponent';
16
- import { selectionToolbar as _selectionToolbar } from './ui/selectionToolbar';
17
+ import { selectionToolbar } from './ui/selectionToolbar';
18
+ import { getToolbarComponents } from './ui/toolbar-components';
17
19
  import { registerBlockMenuItems } from './ui/utils/registerBlockMenuItems';
18
20
  export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
19
21
  var api = _ref.api,
@@ -23,6 +25,7 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
23
25
  };
24
26
  var cachedSelection;
25
27
  var cachedOverflowMenuOptions;
28
+ var isToolbarAIFCEnabled = expValEquals('platform_editor_toolbar_aifc', 'isEnabled', true);
26
29
  var _ref2 = config || {},
27
30
  _ref2$extensionList = _ref2.extensionList,
28
31
  extensionList = _ref2$extensionList === void 0 ? [] : _ref2$extensionList,
@@ -33,7 +36,7 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
33
36
  firstParty = _ref3$firstParty === void 0 ? [] : _ref3$firstParty,
34
37
  _ref3$external = _ref3.external,
35
38
  external = _ref3$external === void 0 ? [] : _ref3$external;
36
- if (fg('platform_editor_selection_extension_api_v2')) {
39
+ if (!isToolbarAIFCEnabled && fg('platform_editor_selection_extension_api_v2')) {
37
40
  var primaryToolbarItemExtensions = getToolbarItemExtensions(extensionList, 'primaryToolbar');
38
41
  if (primaryToolbarItemExtensions !== null && primaryToolbarItemExtensions !== void 0 && primaryToolbarItemExtensions.length) {
39
42
  var _api$primaryToolbar;
@@ -128,6 +131,13 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
128
131
  if ((userIntentState === null || userIntentState === void 0 ? void 0 : userIntentState.currentUserIntent) === 'blockMenuOpen' && expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
129
132
  registerBlockMenuItems(extensionList, api);
130
133
  }
134
+ if (isToolbarAIFCEnabled && expValEquals('platform_editor_toolbar_aifc_selection_extension', 'isEnabled', true)) {
135
+ var _api$toolbar;
136
+ api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents(getToolbarComponents({
137
+ api: api,
138
+ config: config
139
+ }), true);
140
+ }
131
141
  });
132
142
  },
133
143
  contentComponent: function contentComponent(_ref7) {
@@ -140,7 +150,7 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
140
150
  });
141
151
  },
142
152
  pluginsOptions: {
143
- selectionToolbar: function selectionToolbar(state, intl) {
153
+ selectionToolbar: isToolbarAIFCEnabled ? undefined : function (state, intl) {
144
154
  var _api$editorViewMode;
145
155
  if (!config) {
146
156
  return;
@@ -287,7 +297,7 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
287
297
  // NEXT PR: Make sure we cache the whole generated selection toolbar
288
298
  // also debug this to make sure it's actually preventing unnecessary re-renders / work
289
299
  if (cachedOverflowMenuOptions && state.selection.eq(cachedSelection) && fg('platform_editor_selection_extension_api_v2')) {
290
- return _selectionToolbar({
300
+ return selectionToolbar({
291
301
  overflowOptions: cachedOverflowMenuOptions,
292
302
  extensionList: extensionList
293
303
  });
@@ -301,7 +311,7 @@ export var selectionExtensionPlugin = function selectionExtensionPlugin(_ref) {
301
311
  var groupedExtensionsArray = [].concat(_toConsumableArray(getFirstPartyExtensions(allFirstParty)), _toConsumableArray(getExternalExtensions(allExternal)));
302
312
  cachedOverflowMenuOptions = groupedExtensionsArray;
303
313
  cachedSelection = state.selection;
304
- return _selectionToolbar({
314
+ return selectionToolbar({
305
315
  overflowOptions: cachedOverflowMenuOptions,
306
316
  extensionList: extensionList
307
317
  });
@@ -55,6 +55,8 @@ export var SelectionExtensionComponentWrapper = function SelectionExtensionCompo
55
55
  if (!(activeExtension !== null && activeExtension !== void 0 && activeExtension.extension.component)) {
56
56
  return null;
57
57
  }
58
+
59
+ // TODO: ED-29142 - Currently this only accepts old extensions with `component` instead of `contentComponent`. Need to support ExtensionMenuItemConfiguration as well
58
60
  var ExtensionComponent = activeExtension.extension.component;
59
61
  return /*#__PURE__*/React.createElement(ExtensionComponent, {
60
62
  closeExtension: handleOnClose,
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import { useEditorToolbar } from '@atlaskit/editor-common/toolbar';
3
+ import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
4
+ import { selectionExtensionPluginKey } from '../../pm-plugins/main';
5
+ import { getSelectionAdfInfoNew, getSelectionTextInfo } from '../../pm-plugins/utils';
6
+ import { SelectionExtensionActionTypes } from '../../types';
7
+ export var MenuItem = function MenuItem(_ref) {
8
+ var extensionMenuItems = _ref.extensionMenuItems,
9
+ api = _ref.api;
10
+ var _useEditorToolbar = useEditorToolbar(),
11
+ editorView = _useEditorToolbar.editorView;
12
+ if (!(extensionMenuItems !== null && extensionMenuItems !== void 0 && extensionMenuItems.length) || !editorView || !api) {
13
+ return null;
14
+ }
15
+ var onClickHandle = function onClickHandle(extension) {
16
+ return function () {
17
+ if (extension.contentComponent) {
18
+ var selection = getSelectionTextInfo(editorView, api);
19
+ api.core.actions.execute(api.selectionExtension.commands.setActiveExtension({
20
+ extension: extension,
21
+ selection: selection
22
+ }));
23
+ }
24
+ api.core.actions.execute(function (_ref2) {
25
+ var tr = _ref2.tr;
26
+ var _getSelectionAdfInfoN = getSelectionAdfInfoNew(tr.selection),
27
+ selectedNode = _getSelectionAdfInfoN.selectedNode,
28
+ nodePos = _getSelectionAdfInfoN.nodePos;
29
+ tr.setMeta(selectionExtensionPluginKey, {
30
+ type: SelectionExtensionActionTypes.SET_SELECTED_NODE,
31
+ selectedNode: selectedNode,
32
+ nodePos: nodePos
33
+ });
34
+ return tr;
35
+ });
36
+ extension.onClick && extension.onClick();
37
+ };
38
+ };
39
+ return /*#__PURE__*/React.createElement(React.Fragment, null, extensionMenuItems.map(function (extension) {
40
+ var Icon = extension.icon;
41
+ return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
42
+ key: extension.label,
43
+ elemBefore: /*#__PURE__*/React.createElement(Icon, {
44
+ label: ""
45
+ }),
46
+ onClick: onClickHandle(extension),
47
+ isDisabled: extension.isDisabled
48
+ }, extension.label);
49
+ }));
50
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarTooltip, ToolbarButton as BaseToolbarButton } from '@atlaskit/editor-toolbar';
4
+ export var ToolbarButton = function ToolbarButton(_ref) {
5
+ var api = _ref.api,
6
+ config = _ref.config;
7
+ var dockingPreference = useSharedPluginStateSelector(api, 'userPreferences.preferences.toolbarDockingPosition');
8
+ var isDockedAtTop = dockingPreference === 'top';
9
+ if (isDockedAtTop) {
10
+ return null;
11
+ }
12
+ var Icon = config.icon;
13
+ return /*#__PURE__*/React.createElement(ToolbarTooltip, {
14
+ content: config.tooltip
15
+ }, /*#__PURE__*/React.createElement(BaseToolbarButton, {
16
+ iconBefore: /*#__PURE__*/React.createElement(Icon, {
17
+ label: ""
18
+ }),
19
+ isDisabled: config.isDisabled,
20
+ onClick: config.onClick
21
+ }, config.label));
22
+ };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector';
3
+ import { ToolbarTooltip, ToolbarDropdownMenu } from '@atlaskit/editor-toolbar';
4
+ export var ToolbarMenu = function ToolbarMenu(_ref) {
5
+ var api = _ref.api,
6
+ config = _ref.config,
7
+ children = _ref.children;
8
+ var dockingPreference = useSharedPluginStateSelector(api, 'userPreferences.preferences.toolbarDockingPosition');
9
+ var isDockedAtTop = dockingPreference === 'top';
10
+ if (isDockedAtTop) {
11
+ return null;
12
+ }
13
+ var Icon = config.icon;
14
+ return /*#__PURE__*/React.createElement(ToolbarTooltip, {
15
+ content: config.tooltip
16
+ }, /*#__PURE__*/React.createElement(ToolbarDropdownMenu, {
17
+ iconBefore: /*#__PURE__*/React.createElement(Icon, {
18
+ label: ""
19
+ }),
20
+ isDisabled: config.isDisabled,
21
+ onClick: config.onClick
22
+ }, children));
23
+ };
@@ -0,0 +1,107 @@
1
+ import React from 'react';
2
+ import { SELECTION_EXTENSION_MENU_SECTION, APPS_SECTION } from '@atlaskit/editor-common/toolbar';
3
+ import { MenuItem } from './MenuItem';
4
+ import { ToolbarButton } from './ToolbarButton';
5
+ import { ToolbarMenu } from './ToolbarMenu';
6
+ var EXTENSION_RANK_MULTIPLIER = 100;
7
+ export var registerInlineToolbar = function registerInlineToolbar(_ref) {
8
+ var api = _ref.api,
9
+ extension = _ref.extension,
10
+ index = _ref.index;
11
+ var key = extension.key,
12
+ inlineToolbar = extension.inlineToolbar;
13
+ var baseKey = "selection-extension-".concat(key);
14
+ var components = [];
15
+ if (!inlineToolbar) {
16
+ return components;
17
+ }
18
+ var getToolbarItem = inlineToolbar.getToolbarItem,
19
+ getMenuItems = inlineToolbar.getMenuItems;
20
+ var groupKey = "".concat(baseKey, "-toolbar-group");
21
+ var toolbarItemKey = "".concat(baseKey, "-toolbar-").concat(getMenuItems ? 'menu' : 'button');
22
+ var menuSectionKey = "".concat(baseKey, "-toolbar-menu-section");
23
+ if (getToolbarItem) {
24
+ // first we register the group for the button or menu to be added to
25
+ components.push({
26
+ type: 'group',
27
+ key: groupKey,
28
+ parents: [{
29
+ type: APPS_SECTION.type,
30
+ key: APPS_SECTION.key,
31
+ rank: (index + 1) * EXTENSION_RANK_MULTIPLIER
32
+ }]
33
+ });
34
+ var toolbarItemConfig = getToolbarItem();
35
+
36
+ // if toolbar item has menu items, assume it's a menu
37
+ if (getMenuItems) {
38
+ components.push({
39
+ type: 'menu',
40
+ key: toolbarItemKey,
41
+ parents: [{
42
+ type: 'group',
43
+ key: groupKey,
44
+ rank: EXTENSION_RANK_MULTIPLIER
45
+ }],
46
+ component: function component() {
47
+ return /*#__PURE__*/React.createElement(ToolbarMenu, {
48
+ api: api,
49
+ config: toolbarItemConfig
50
+ });
51
+ }
52
+ });
53
+ } else {
54
+ // else just regsiter a button
55
+ components.push({
56
+ type: 'button',
57
+ key: toolbarItemKey,
58
+ parents: [{
59
+ type: 'group',
60
+ key: groupKey,
61
+ rank: EXTENSION_RANK_MULTIPLIER
62
+ }],
63
+ component: function component() {
64
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
65
+ api: api,
66
+ config: toolbarItemConfig
67
+ });
68
+ }
69
+ });
70
+ }
71
+ }
72
+ if (getMenuItems) {
73
+ if (getToolbarItem) {
74
+ components.push({
75
+ type: 'menu-section',
76
+ key: menuSectionKey,
77
+ parents: [{
78
+ type: 'menu',
79
+ key: toolbarItemKey,
80
+ rank: EXTENSION_RANK_MULTIPLIER
81
+ }]
82
+ });
83
+ }
84
+
85
+ // Remove ExtensionMenuSectionConfiguration - only care about items
86
+ var menuItems = getMenuItems().filter(function (item) {
87
+ return 'label' in item && 'icon' in item;
88
+ });
89
+ components.push({
90
+ type: 'menu-item',
91
+ key: key,
92
+ parents: [{
93
+ type: 'menu-section',
94
+ // if we have a custom menu, place items in there, otherwise in the overflow menu
95
+ key: getToolbarItem ? menuSectionKey : SELECTION_EXTENSION_MENU_SECTION.key,
96
+ rank: (index + 1) * EXTENSION_RANK_MULTIPLIER
97
+ }],
98
+ component: function component() {
99
+ return /*#__PURE__*/React.createElement(MenuItem, {
100
+ api: api,
101
+ extensionMenuItems: menuItems
102
+ });
103
+ }
104
+ });
105
+ }
106
+ return components;
107
+ };
@@ -0,0 +1,73 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import React from 'react';
3
+ import { APPS_SECTION, OVERFLOW_MENU, OVERFLOW_MENU_RANK, SELECTION_EXTENSION_MENU_SECTION, TOOLBAR_RANK, TOOLBARS } from '@atlaskit/editor-common/toolbar';
4
+ import { MenuItem } from './toolbar-components/MenuItem';
5
+ import { registerInlineToolbar } from './toolbar-components/register-inline-toolbar';
6
+ import { migrateSelectionExtensionToMenuItem } from './utils/migrate-selection-extention';
7
+ export var getToolbarComponents = function getToolbarComponents(_ref) {
8
+ var _config$extensionList, _config$extensions;
9
+ var api = _ref.api,
10
+ config = _ref.config;
11
+ var extensionToolbarComponents = (config === null || config === void 0 || (_config$extensionList = config.extensionList) === null || _config$extensionList === void 0 ? void 0 : _config$extensionList.flatMap(function (extension, index) {
12
+ return registerInlineToolbar({
13
+ api: api,
14
+ extension: extension,
15
+ index: index
16
+ });
17
+ })) || [];
18
+
19
+ /**
20
+ * Continue to support firstParty apps for now as some apps haven't migrated yet, this simply converts apps to new ExtensionMenuItemConfiguration type
21
+ * to process easier. extensionList and extensions?.firstParty will most likely be mutually exclusive.
22
+ *
23
+ * **Warning:** This is called on every selection change to ensure calls to api?.selectionExtension.actions.getSelectionAdf() are
24
+ * fresh and up to date.
25
+ */
26
+ var firstPartyExtensions = (config === null || config === void 0 || (_config$extensions = config.extensions) === null || _config$extensions === void 0 || (_config$extensions = _config$extensions.firstParty) === null || _config$extensions === void 0 ? void 0 : _config$extensions.map(function (extension) {
27
+ return migrateSelectionExtensionToMenuItem(extension, api);
28
+ }).filter(function (extension) {
29
+ return extension !== undefined;
30
+ })) || [];
31
+ return [{
32
+ type: APPS_SECTION.type,
33
+ key: APPS_SECTION.key,
34
+ parents: [{
35
+ type: 'toolbar',
36
+ key: TOOLBARS.INLINE_TEXT_TOOLBAR,
37
+ rank: TOOLBAR_RANK[APPS_SECTION.key]
38
+ }, {
39
+ type: 'toolbar',
40
+ key: TOOLBARS.PRIMARY_TOOLBAR,
41
+ rank: TOOLBAR_RANK[APPS_SECTION.key]
42
+ }]
43
+ },
44
+ // also register a section inside the overflow menu for extensions which only have menu items
45
+ {
46
+ type: SELECTION_EXTENSION_MENU_SECTION.type,
47
+ key: SELECTION_EXTENSION_MENU_SECTION.key,
48
+ parents: [{
49
+ key: OVERFLOW_MENU.key,
50
+ type: OVERFLOW_MENU.type,
51
+ rank: OVERFLOW_MENU_RANK[SELECTION_EXTENSION_MENU_SECTION.key]
52
+ }]
53
+ }].concat(_toConsumableArray(extensionToolbarComponents), _toConsumableArray(registerFirstPartyExtensions(api, firstPartyExtensions)));
54
+ };
55
+ var registerFirstPartyExtensions = function registerFirstPartyExtensions(api, extensions) {
56
+ var components = [];
57
+ components.push({
58
+ type: 'menu-item',
59
+ key: 'first-party-extensions-menu-item',
60
+ parents: [{
61
+ type: 'menu-section',
62
+ key: SELECTION_EXTENSION_MENU_SECTION.key,
63
+ rank: 100
64
+ }],
65
+ component: function component() {
66
+ return /*#__PURE__*/React.createElement(MenuItem, {
67
+ api: api,
68
+ extensionMenuItems: extensions
69
+ });
70
+ }
71
+ });
72
+ return components;
73
+ };