@atlaskit/editor-core 219.5.0 → 219.6.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.
- package/CHANGELOG.md +27 -0
- package/dist/cjs/create-editor/ReactEditorView.js +45 -0
- package/dist/cjs/create-editor/create-editor.js +6 -1
- package/dist/cjs/create-editor/filter-plugins-for-reconfigure.js +49 -0
- package/dist/cjs/test-utils.js +3 -1
- package/dist/cjs/ui/Appearance/FullPage/FullPageToolbarNext.js +6 -49
- package/dist/cjs/ui/EditorContentContainer/EditorContentContainer-compiled.compiled.css +198 -1
- package/dist/cjs/ui/EditorContentContainer/EditorContentContainer-compiled.js +19 -14
- package/dist/cjs/ui/PluginSlot/mount-plugin-hooks.js +10 -3
- package/dist/cjs/version-wrapper.js +1 -1
- package/dist/es2019/create-editor/ReactEditorView.js +43 -1
- package/dist/es2019/create-editor/create-editor.js +6 -1
- package/dist/es2019/create-editor/filter-plugins-for-reconfigure.js +35 -0
- package/dist/es2019/test-utils.js +3 -1
- package/dist/es2019/ui/Appearance/FullPage/FullPageToolbarNext.js +4 -46
- package/dist/es2019/ui/EditorContentContainer/EditorContentContainer-compiled.compiled.css +198 -1
- package/dist/es2019/ui/EditorContentContainer/EditorContentContainer-compiled.js +21 -16
- package/dist/es2019/ui/PluginSlot/mount-plugin-hooks.js +18 -9
- package/dist/es2019/version-wrapper.js +1 -1
- package/dist/esm/create-editor/ReactEditorView.js +45 -0
- package/dist/esm/create-editor/create-editor.js +6 -1
- package/dist/esm/create-editor/filter-plugins-for-reconfigure.js +43 -0
- package/dist/esm/test-utils.js +3 -1
- package/dist/esm/ui/Appearance/FullPage/FullPageToolbarNext.js +6 -49
- package/dist/esm/ui/EditorContentContainer/EditorContentContainer-compiled.compiled.css +198 -1
- package/dist/esm/ui/EditorContentContainer/EditorContentContainer-compiled.js +21 -16
- package/dist/esm/ui/PluginSlot/mount-plugin-hooks.js +10 -3
- package/dist/esm/version-wrapper.js +1 -1
- package/dist/types/create-editor/filter-plugins-for-reconfigure.d.ts +19 -0
- package/dist/types/ui/PluginSlot/mount-plugin-hooks.d.ts +2 -2
- package/dist/types-ts4.5/create-editor/filter-plugins-for-reconfigure.d.ts +19 -0
- package/dist/types-ts4.5/ui/PluginSlot/mount-plugin-hooks.d.ts +2 -2
- package/package.json +13 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @atlaskit/editor-core
|
|
2
2
|
|
|
3
|
+
## 219.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`80e6f41ddfce4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/80e6f41ddfce4) -
|
|
8
|
+
Reconcile editor plugin set on reconfigureState across preset switches: drop plugins whose schema
|
|
9
|
+
nodes/marks aren't in the current schema, and evict plugins from the injection API that aren't
|
|
10
|
+
part of the new preset. Behind feature gate `platform_editor_reconfigure_filter_plugins`.
|
|
11
|
+
|
|
12
|
+
Adds the `NamedReactHookFactory` type to `@atlaskit/editor-common/types` and annotates each
|
|
13
|
+
plugin's `usePluginHook` with its plugin name in `processPluginsList` so `MountPluginHooks` can
|
|
14
|
+
key React fibers stably per plugin. The shape of `EditorConfig.pluginHooks` is unchanged
|
|
15
|
+
(`ReactHookFactory[]`); the annotation is a non-breaking additive property on the function value
|
|
16
|
+
that falls back to the array index when absent.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
22
|
+
## 219.5.1
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- [`8db6f0336d199`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8db6f0336d199) -
|
|
27
|
+
Cleans up experiment platform_editor_toolbar_two_stage_hydration
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
|
|
3
30
|
## 219.5.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
|
@@ -49,6 +49,7 @@ var _consts = require("./consts");
|
|
|
49
49
|
var _createEditor = require("./create-editor");
|
|
50
50
|
var _createPluginsList = _interopRequireDefault(require("./create-plugins-list"));
|
|
51
51
|
var _createSchema = require("./create-schema");
|
|
52
|
+
var _filterPluginsForReconfigure = require("./filter-plugins-for-reconfigure");
|
|
52
53
|
var _messages = require("./messages");
|
|
53
54
|
var _focusEditorElement = require("./ReactEditorView/focusEditorElement");
|
|
54
55
|
var _getUAPrefix = require("./ReactEditorView/getUAPrefix");
|
|
@@ -362,6 +363,10 @@ function ReactEditorView(props) {
|
|
|
362
363
|
var _useState = (0, _react.useState)(0),
|
|
363
364
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
364
365
|
bumpConfigVersion = _useState2[1];
|
|
366
|
+
|
|
367
|
+
// Preset reference last processed by the schema/API reconciliation below.
|
|
368
|
+
// Used to skip that work when reconfigure is called with the same preset.
|
|
369
|
+
var lastFilteredPresetRef = (0, _react.useRef)(null);
|
|
365
370
|
var reconfigureState = (0, _react.useCallback)(function (props) {
|
|
366
371
|
if (!viewRef.current) {
|
|
367
372
|
return;
|
|
@@ -371,7 +376,47 @@ function ReactEditorView(props) {
|
|
|
371
376
|
// so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
|
|
372
377
|
// nodes that haven't been re-rendered to the document yet.
|
|
373
378
|
blur();
|
|
379
|
+
|
|
380
|
+
// Snapshot plugin names registered before createPluginsList runs, so
|
|
381
|
+
// we can tell which plugins are newly added by the new preset vs.
|
|
382
|
+
// which ones already coexisted with the current schema.
|
|
383
|
+
var previousPluginNames = new Set(pluginInjectionAPI.current.getRegisteredPluginNames());
|
|
374
384
|
var editorPlugins = (0, _createPluginsList.default)(props.preset, 'allowBlockType' in props.editorProps ? props.editorProps : {}, pluginInjectionAPI.current);
|
|
385
|
+
|
|
386
|
+
// `state.reconfigure` keeps the original schema, so switching presets
|
|
387
|
+
// can leave the editor inconsistent in two ways:
|
|
388
|
+
// 1. The new preset may add plugins that reference schema nodes or
|
|
389
|
+
// marks the original schema doesn't have.
|
|
390
|
+
// 2. Plugins registered by a previous preset can linger in the
|
|
391
|
+
// injection API even when the new preset doesn't re-register
|
|
392
|
+
// them, so listeners still fire against a state that no longer
|
|
393
|
+
// has their pmPlugin.
|
|
394
|
+
if (lastFilteredPresetRef.current !== props.preset && (0, _platformFeatureFlags.fg)('platform_editor_reconfigure_filter_plugins')) {
|
|
395
|
+
var _filterPluginsForReco = (0, _filterPluginsForReconfigure.filterPluginsForReconfigure)(editorPlugins, viewRef.current.state.schema, previousPluginNames),
|
|
396
|
+
kept = _filterPluginsForReco.kept,
|
|
397
|
+
dropped = _filterPluginsForReco.dropped;
|
|
398
|
+
editorPlugins = kept;
|
|
399
|
+
|
|
400
|
+
// Reconcile the injection API with the post-filter plugin set.
|
|
401
|
+
// This evicts both the plugins we just dropped above (re-registered
|
|
402
|
+
// by createPluginsList but no longer in editorPlugins) AND any
|
|
403
|
+
// plugin from a previous preset that the new preset doesn't
|
|
404
|
+
// re-register.
|
|
405
|
+
var keptPluginNames = new Set(editorPlugins.map(function (p) {
|
|
406
|
+
return p === null || p === void 0 ? void 0 : p.name;
|
|
407
|
+
}).filter(function (n) {
|
|
408
|
+
return Boolean(n);
|
|
409
|
+
}));
|
|
410
|
+
var evictedFromApi = pluginInjectionAPI.current.retainPlugins(keptPluginNames);
|
|
411
|
+
if (dropped.length > 0 || evictedFromApi.length > 0) {
|
|
412
|
+
// eslint-disable-next-line no-console
|
|
413
|
+
console.warn('[reconfigureState] Cleanup summary:', {
|
|
414
|
+
dropped: dropped,
|
|
415
|
+
evictedFromApi: evictedFromApi
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
lastFilteredPresetRef.current = props.preset;
|
|
419
|
+
}
|
|
375
420
|
config.current = (0, _createEditor.processPluginsList)(editorPlugins);
|
|
376
421
|
if ((0, _expValEquals.expValEquals)('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
377
422
|
var _config$current$pmPlu2;
|
|
@@ -72,7 +72,12 @@ function processPluginsList(plugins) {
|
|
|
72
72
|
acc.contentComponents.push(plugin.contentComponent);
|
|
73
73
|
}
|
|
74
74
|
if (plugin.usePluginHook) {
|
|
75
|
-
|
|
75
|
+
// Wrap with .bind(null) so we can annotate the function with the
|
|
76
|
+
// plugin name without mutating the plugin's original hook reference.
|
|
77
|
+
// MountPluginHooks reads `pluginName` to derive a stable React key.
|
|
78
|
+
var named = plugin.usePluginHook.bind(null);
|
|
79
|
+
named.pluginName = plugin.name;
|
|
80
|
+
acc.pluginHooks.push(named);
|
|
76
81
|
}
|
|
77
82
|
if (plugin.primaryToolbarComponent) {
|
|
78
83
|
acc.primaryToolbarComponents.push(plugin.primaryToolbarComponent);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.filterPluginsForReconfigure = filterPluginsForReconfigure;
|
|
7
|
+
/**
|
|
8
|
+
* Used by `reconfigureState` to drop plugins from a freshly-built preset that
|
|
9
|
+
* declare schema nodes/marks the current schema doesn't have. Plugins already
|
|
10
|
+
* present before this reconfigure are kept untouched: they have demonstrably
|
|
11
|
+
* coexisted with the schema (e.g. tests that mock a stripped-down schema), so
|
|
12
|
+
* removing them now would be a regression.
|
|
13
|
+
*/
|
|
14
|
+
function filterPluginsForReconfigure(editorPlugins, schema, previousPluginNames) {
|
|
15
|
+
var availableNodeNames = new Set(Object.keys(schema.nodes));
|
|
16
|
+
var availableMarkNames = new Set(Object.keys(schema.marks));
|
|
17
|
+
var dropped = [];
|
|
18
|
+
var kept = editorPlugins.filter(function (plugin) {
|
|
19
|
+
if (!plugin) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (previousPluginNames.has(plugin.name)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
var missingNodes = plugin.nodes ? plugin.nodes().map(function (n) {
|
|
26
|
+
return n.name;
|
|
27
|
+
}).filter(function (n) {
|
|
28
|
+
return !availableNodeNames.has(n);
|
|
29
|
+
}) : [];
|
|
30
|
+
var missingMarks = plugin.marks ? plugin.marks().map(function (m) {
|
|
31
|
+
return m.name;
|
|
32
|
+
}).filter(function (m) {
|
|
33
|
+
return !availableMarkNames.has(m);
|
|
34
|
+
}) : [];
|
|
35
|
+
if (missingNodes.length > 0 || missingMarks.length > 0) {
|
|
36
|
+
dropped.push({
|
|
37
|
+
name: plugin.name,
|
|
38
|
+
missingNodes: missingNodes,
|
|
39
|
+
missingMarks: missingMarks
|
|
40
|
+
});
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
kept: kept,
|
|
47
|
+
dropped: dropped
|
|
48
|
+
};
|
|
49
|
+
}
|
package/dist/cjs/test-utils.js
CHANGED
|
@@ -56,7 +56,9 @@ function lightProcessPluginsList(editorPlugins) {
|
|
|
56
56
|
acc.contentComponents.push(editorPlugin.contentComponent);
|
|
57
57
|
}
|
|
58
58
|
if (editorPlugin.usePluginHook) {
|
|
59
|
-
|
|
59
|
+
var named = editorPlugin.usePluginHook.bind(null);
|
|
60
|
+
named.pluginName = editorPlugin.name;
|
|
61
|
+
acc.pluginHooks.push(named);
|
|
60
62
|
}
|
|
61
63
|
if (editorPlugin.onEditorViewStateUpdated) {
|
|
62
64
|
acc.onEditorViewStateUpdatedCallbacks.push(editorPlugin.onEditorViewStateUpdated);
|
|
@@ -61,17 +61,6 @@ var SecondChildWrapper = function SecondChildWrapper(_ref3) {
|
|
|
61
61
|
className: (0, _runtime.ax)([styles.secondChildWrapperOneLine])
|
|
62
62
|
}, children);
|
|
63
63
|
};
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Placeholder component that reserves the toolbar's space during hydration
|
|
67
|
-
* to prevent layout shift when the actual toolbar renders.
|
|
68
|
-
*/
|
|
69
|
-
var ToolbarPlaceholder = function ToolbarPlaceholder() {
|
|
70
|
-
return /*#__PURE__*/_react.default.createElement("div", {
|
|
71
|
-
"data-testid": "ak-editor-main-toolbar-placeholder",
|
|
72
|
-
className: (0, _runtime.ax)([styles.toolbarPlaceholder])
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
64
|
var shouldShowToolbarContainer = function shouldShowToolbarContainer(toolbar, customPrimaryToolbarComponents) {
|
|
76
65
|
return !!toolbar || !!customPrimaryToolbarComponents;
|
|
77
66
|
};
|
|
@@ -125,41 +114,9 @@ var FullPageToolbarNext = exports.FullPageToolbarNext = function FullPageToolbar
|
|
|
125
114
|
if (!shouldShowToolbarContainer(toolbar, customPrimaryToolbarComponents)) {
|
|
126
115
|
return /*#__PURE__*/_react.default.createElement(ToolbarPortal, null, null);
|
|
127
116
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return /*#__PURE__*/_react.default.createElement(_uiMenu.ToolbarArrowKeyNavigationProvider, {
|
|
132
|
-
editorView: editorView,
|
|
133
|
-
childComponentSelector: "[data-testid='ak-editor-main-toolbar']",
|
|
134
|
-
isShortcutToFocusToolbar: isShortcutToFocusToolbar,
|
|
135
|
-
handleEscape: handleEscape,
|
|
136
|
-
intl: intl
|
|
137
|
-
}, /*#__PURE__*/_react.default.createElement(ToolbarPortal, null, /*#__PURE__*/_react.default.createElement(MainToolbarWrapper, {
|
|
138
|
-
testId: "ak-editor-main-toolbar",
|
|
139
|
-
showKeyline: showKeyline || ContextPanelWidth > 0
|
|
140
|
-
}, beforeIcon && /*#__PURE__*/_react.default.createElement("div", {
|
|
141
|
-
className: (0, _runtime.ax)([styles.mainToolbarIconBefore, styles.mainToolbarIconBeforeNew])
|
|
142
|
-
}, beforeIcon), /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(FirstChildWrapper, null, /*#__PURE__*/_react.default.createElement(_ExcludeFromHydration.default, null, primaryToolbarDockingConfigEnabled && components && (0, _toolbar2.isToolbar)(toolbar) && editorView && !(0, _coreUtils.isSSR)() && /*#__PURE__*/_react.default.createElement(_Toolbar.ToolbarNext, {
|
|
143
|
-
toolbar: toolbar,
|
|
144
|
-
components: components,
|
|
145
|
-
editorView: editorView,
|
|
146
|
-
editorAPI: editorAPI,
|
|
147
|
-
popupsMountPoint: mountPoint,
|
|
148
|
-
editorAppearance: "full-page",
|
|
149
|
-
isDisabled: disabled
|
|
150
|
-
}))), /*#__PURE__*/_react.default.createElement(SecondChildWrapper, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
151
|
-
className: (0, _runtime.ax)([styles.customToolbarWrapperStyle])
|
|
152
|
-
}, !!customPrimaryToolbarComponents && 'before' in customPrimaryToolbarComponents && /*#__PURE__*/_react.default.createElement("div", {
|
|
153
|
-
"data-testid": 'before-primary-toolbar-components-plugin',
|
|
154
|
-
className: (0, _runtime.ax)([styles.beforePrimaryToolbarComponents])
|
|
155
|
-
}, customPrimaryToolbarComponents.before), !!customPrimaryToolbarComponents && 'after' in customPrimaryToolbarComponents ? customPrimaryToolbarComponents.after : customPrimaryToolbarComponents)), /*#__PURE__*/_react.default.createElement(_ToolbarPortal.ToolbarPortalMountPoint, null)))));
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
return /*#__PURE__*/_react.default.createElement(_contextPanel.ContextPanelConsumer, null, function (_ref7) {
|
|
159
|
-
var ContextPanelWidth = _ref7.width;
|
|
160
|
-
return /*#__PURE__*/_react.default.createElement(_ExcludeFromHydration.default, {
|
|
161
|
-
fallback: /*#__PURE__*/_react.default.createElement(ToolbarPlaceholder, null)
|
|
162
|
-
}, /*#__PURE__*/_react.default.createElement(_uiMenu.ToolbarArrowKeyNavigationProvider, {
|
|
117
|
+
return /*#__PURE__*/_react.default.createElement(_contextPanel.ContextPanelConsumer, null, function (_ref6) {
|
|
118
|
+
var ContextPanelWidth = _ref6.width;
|
|
119
|
+
return /*#__PURE__*/_react.default.createElement(_uiMenu.ToolbarArrowKeyNavigationProvider, {
|
|
163
120
|
editorView: editorView,
|
|
164
121
|
childComponentSelector: "[data-testid='ak-editor-main-toolbar']",
|
|
165
122
|
isShortcutToFocusToolbar: isShortcutToFocusToolbar,
|
|
@@ -170,7 +127,7 @@ var FullPageToolbarNext = exports.FullPageToolbarNext = function FullPageToolbar
|
|
|
170
127
|
showKeyline: showKeyline || ContextPanelWidth > 0
|
|
171
128
|
}, beforeIcon && /*#__PURE__*/_react.default.createElement("div", {
|
|
172
129
|
className: (0, _runtime.ax)([styles.mainToolbarIconBefore, styles.mainToolbarIconBeforeNew])
|
|
173
|
-
}, beforeIcon), /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(FirstChildWrapper, null, primaryToolbarDockingConfigEnabled && components && (0, _toolbar2.isToolbar)(toolbar) && editorView && !(0, _coreUtils.isSSR)() && /*#__PURE__*/_react.default.createElement(_Toolbar.ToolbarNext, {
|
|
130
|
+
}, beforeIcon), /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(FirstChildWrapper, null, /*#__PURE__*/_react.default.createElement(_ExcludeFromHydration.default, null, primaryToolbarDockingConfigEnabled && components && (0, _toolbar2.isToolbar)(toolbar) && editorView && !(0, _coreUtils.isSSR)() && /*#__PURE__*/_react.default.createElement(_Toolbar.ToolbarNext, {
|
|
174
131
|
toolbar: toolbar,
|
|
175
132
|
components: components,
|
|
176
133
|
editorView: editorView,
|
|
@@ -178,11 +135,11 @@ var FullPageToolbarNext = exports.FullPageToolbarNext = function FullPageToolbar
|
|
|
178
135
|
popupsMountPoint: mountPoint,
|
|
179
136
|
editorAppearance: "full-page",
|
|
180
137
|
isDisabled: disabled
|
|
181
|
-
})), /*#__PURE__*/_react.default.createElement(SecondChildWrapper, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
138
|
+
}))), /*#__PURE__*/_react.default.createElement(SecondChildWrapper, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
182
139
|
className: (0, _runtime.ax)([styles.customToolbarWrapperStyle])
|
|
183
140
|
}, !!customPrimaryToolbarComponents && 'before' in customPrimaryToolbarComponents && /*#__PURE__*/_react.default.createElement("div", {
|
|
184
141
|
"data-testid": 'before-primary-toolbar-components-plugin',
|
|
185
142
|
className: (0, _runtime.ax)([styles.beforePrimaryToolbarComponents])
|
|
186
|
-
}, customPrimaryToolbarComponents.before), !!customPrimaryToolbarComponents && 'after' in customPrimaryToolbarComponents ? customPrimaryToolbarComponents.after : customPrimaryToolbarComponents)), /*#__PURE__*/_react.default.createElement(_ToolbarPortal.ToolbarPortalMountPoint, null)))))
|
|
143
|
+
}, customPrimaryToolbarComponents.before), !!customPrimaryToolbarComponents && 'after' in customPrimaryToolbarComponents ? customPrimaryToolbarComponents.after : customPrimaryToolbarComponents)), /*#__PURE__*/_react.default.createElement(_ToolbarPortal.ToolbarPortalMountPoint, null)))));
|
|
187
144
|
});
|
|
188
145
|
};
|