@atlaskit/editor-plugin-selection-extension 4.0.0 → 4.1.1
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 +18 -0
- package/dist/cjs/pm-plugins/utils/index.js +23 -0
- package/dist/cjs/selectionExtensionPlugin.js +15 -5
- package/dist/cjs/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
- package/dist/cjs/ui/toolbar-components/MenuItem.js +57 -0
- package/dist/cjs/ui/toolbar-components/ToolbarButton.js +29 -0
- package/dist/cjs/ui/toolbar-components/ToolbarMenu.js +30 -0
- package/dist/cjs/ui/toolbar-components/register-inline-toolbar.js +114 -0
- package/dist/cjs/ui/toolbar-components.js +80 -0
- package/dist/cjs/ui/utils/migrate-selection-extention.js +52 -0
- package/dist/es2019/pm-plugins/utils/index.js +25 -0
- package/dist/es2019/selectionExtensionPlugin.js +12 -2
- package/dist/es2019/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
- package/dist/es2019/ui/toolbar-components/MenuItem.js +52 -0
- package/dist/es2019/ui/toolbar-components/ToolbarButton.js +23 -0
- package/dist/es2019/ui/toolbar-components/ToolbarMenu.js +24 -0
- package/dist/es2019/ui/toolbar-components/register-inline-toolbar.js +110 -0
- package/dist/es2019/ui/toolbar-components.js +67 -0
- package/dist/es2019/ui/utils/migrate-selection-extention.js +46 -0
- package/dist/esm/pm-plugins/utils/index.js +22 -0
- package/dist/esm/selectionExtensionPlugin.js +15 -5
- package/dist/esm/ui/extension/SelectionExtensionComponentWrapper.js +2 -0
- package/dist/esm/ui/toolbar-components/MenuItem.js +50 -0
- package/dist/esm/ui/toolbar-components/ToolbarButton.js +22 -0
- package/dist/esm/ui/toolbar-components/ToolbarMenu.js +23 -0
- package/dist/esm/ui/toolbar-components/register-inline-toolbar.js +107 -0
- package/dist/esm/ui/toolbar-components.js +73 -0
- package/dist/esm/ui/utils/migrate-selection-extention.js +46 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/pm-plugins/utils/index.d.ts +2 -1
- package/dist/types/selectionExtensionPluginType.d.ts +4 -2
- package/dist/types/ui/toolbar-components/MenuItem.d.ts +10 -0
- package/dist/types/ui/toolbar-components/ToolbarButton.d.ts +10 -0
- package/dist/types/ui/toolbar-components/ToolbarMenu.d.ts +10 -0
- package/dist/types/ui/toolbar-components/register-inline-toolbar.d.ts +11 -0
- package/dist/types/ui/toolbar-components.d.ts +11 -0
- package/dist/types/ui/utils/migrate-selection-extention.d.ts +14 -0
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/utils/index.d.ts +2 -1
- package/dist/types-ts4.5/selectionExtensionPluginType.d.ts +4 -2
- package/dist/types-ts4.5/ui/toolbar-components/MenuItem.d.ts +10 -0
- package/dist/types-ts4.5/ui/toolbar-components/ToolbarButton.d.ts +10 -0
- package/dist/types-ts4.5/ui/toolbar-components/ToolbarMenu.d.ts +10 -0
- package/dist/types-ts4.5/ui/toolbar-components/register-inline-toolbar.d.ts +11 -0
- package/dist/types-ts4.5/ui/toolbar-components.d.ts +11 -0
- package/dist/types-ts4.5/ui/utils/migrate-selection-extention.d.ts +14 -0
- package/package.json +6 -5
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
+
};
|