@atlaskit/editor-plugin-synced-block 8.2.9 → 8.2.11
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/AGENTS.md +11 -11
- package/CHANGELOG.md +20 -0
- package/dist/cjs/pm-plugins/main.js +25 -6
- package/dist/cjs/pm-plugins/menu-and-toolbar-experiences.js +92 -53
- package/dist/cjs/syncedBlockPlugin.js +76 -25
- package/dist/es2019/pm-plugins/main.js +25 -6
- package/dist/es2019/pm-plugins/menu-and-toolbar-experiences.js +92 -53
- package/dist/es2019/syncedBlockPlugin.js +67 -11
- package/dist/esm/pm-plugins/main.js +25 -6
- package/dist/esm/pm-plugins/menu-and-toolbar-experiences.js +92 -53
- package/dist/esm/syncedBlockPlugin.js +77 -25
- package/package.json +4 -4
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { syncBlock, bodiedSyncBlock } from '@atlaskit/adf-schema';
|
|
3
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
3
4
|
import { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
5
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
6
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
5
7
|
import { flushBodiedSyncBlocks as _flushBodiedSyncBlocks, flushSyncBlocks, discardUnpublishedSyncBlocks as _discardUnpublishedSyncBlocks } from './editor-actions';
|
|
6
8
|
import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
|
|
@@ -14,14 +16,51 @@ import { getToolbarConfig } from './ui/floating-toolbar';
|
|
|
14
16
|
import { getQuickInsertConfig } from './ui/quick-insert';
|
|
15
17
|
import { SyncBlockRefresher } from './ui/SyncBlockRefresher';
|
|
16
18
|
import { getToolbarComponents } from './ui/toolbar-components';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* EDITOR-6929 / PR-G: Guard contentComponent rendering.
|
|
22
|
+
* When `hasSyncedBlocks` is false return null
|
|
23
|
+
* to avoid mounting SyncBlockRefresher, DeleteConfirmationModal, and Flag —
|
|
24
|
+
* their hooks (useSharedPluginStateWithSelector) would execute selectors on
|
|
25
|
+
* every transaction for no benefit on the ~99.98% of pages with zero synced
|
|
26
|
+
* blocks.
|
|
27
|
+
*/
|
|
28
|
+
var LazySyncedBlockUI = function LazySyncedBlockUI(_ref) {
|
|
29
|
+
var syncBlockStoreManager = _ref.syncBlockStore,
|
|
20
30
|
api = _ref.api;
|
|
31
|
+
var hasSyncBlocks = useSharedPluginStateWithSelector(api, ['syncedBlock'], function (states) {
|
|
32
|
+
var _states$syncedBlockSt;
|
|
33
|
+
return (_states$syncedBlockSt = states.syncedBlockState) === null || _states$syncedBlockSt === void 0 ? void 0 : _states$syncedBlockSt.hasSyncedBlocks;
|
|
34
|
+
});
|
|
35
|
+
if (!hasSyncBlocks && expValEquals('editor_synced_block_perf', 'isEnabled', true)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SyncBlockRefresher, {
|
|
39
|
+
syncBlockStoreManager: syncBlockStoreManager,
|
|
40
|
+
api: api
|
|
41
|
+
}), /*#__PURE__*/React.createElement(DeleteConfirmationModal, {
|
|
42
|
+
syncBlockStoreManager: syncBlockStoreManager,
|
|
43
|
+
api: api
|
|
44
|
+
}), /*#__PURE__*/React.createElement(Flag, {
|
|
45
|
+
api: api
|
|
46
|
+
}));
|
|
47
|
+
};
|
|
48
|
+
export var syncedBlockPlugin = function syncedBlockPlugin(_ref2) {
|
|
49
|
+
var _api$editorViewMode, _api$analytics, _api$blockMenu, _config$enableSourceC, _api$toolbar, _config$enableSourceC2;
|
|
50
|
+
var config = _ref2.config,
|
|
51
|
+
api = _ref2.api;
|
|
21
52
|
var refs = {};
|
|
22
53
|
var viewMode = api === null || api === void 0 || (_api$editorViewMode = api.editorViewMode) === null || _api$editorViewMode === void 0 || (_api$editorViewMode = _api$editorViewMode.sharedState.currentState()) === null || _api$editorViewMode === void 0 ? void 0 : _api$editorViewMode.mode;
|
|
23
54
|
var syncBlockStore = new SyncBlockStoreManager(config === null || config === void 0 ? void 0 : config.syncBlockDataProvider, viewMode, config === null || config === void 0 ? void 0 : config.__livePage);
|
|
55
|
+
var isPerfExperimentOn = expValEquals('editor_synced_block_perf', 'isEnabled', true);
|
|
24
56
|
syncBlockStore.setFireAnalyticsEvent(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 ? void 0 : _api$analytics.fireAnalyticsEvent);
|
|
57
|
+
|
|
58
|
+
// --- Memoized getSharedState (EDITOR-6929 / PR-F) ---
|
|
59
|
+
// Cache the last returned shared state object. On each call, perform a
|
|
60
|
+
// shallow comparison of all fields against the cached value. If nothing
|
|
61
|
+
// changed, return the cached reference so SharedStateAPI subscribers
|
|
62
|
+
// (React components) skip re-rendering.
|
|
63
|
+
var cachedSharedState;
|
|
25
64
|
api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents(getBlockMenuComponents(api, (_config$enableSourceC = config === null || config === void 0 ? void 0 : config.enableSourceCreation) !== null && _config$enableSourceC !== void 0 ? _config$enableSourceC : false));
|
|
26
65
|
api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents(getToolbarComponents(api, (_config$enableSourceC2 = config === null || config === void 0 ? void 0 : config.enableSourceCreation) !== null && _config$enableSourceC2 !== void 0 ? _config$enableSourceC2 : false));
|
|
27
66
|
return {
|
|
@@ -63,9 +102,9 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref) {
|
|
|
63
102
|
return copySyncedBlockReferenceToClipboardEditorCommand(syncBlockStore, inputMethod, api);
|
|
64
103
|
},
|
|
65
104
|
insertSyncedBlock: function insertSyncedBlock() {
|
|
66
|
-
return function (
|
|
105
|
+
return function (_ref3) {
|
|
67
106
|
var _api$analytics3;
|
|
68
|
-
var tr =
|
|
107
|
+
var tr = _ref3.tr;
|
|
69
108
|
if (!(config !== null && config !== void 0 && config.enableSourceCreation)) {
|
|
70
109
|
return null;
|
|
71
110
|
}
|
|
@@ -91,38 +130,49 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref) {
|
|
|
91
130
|
pluginsOptions: {
|
|
92
131
|
quickInsert: getQuickInsertConfig(config, api, syncBlockStore),
|
|
93
132
|
floatingToolbar: function floatingToolbar(state, intl) {
|
|
133
|
+
var _syncedBlockPluginKey;
|
|
134
|
+
// When the experiment is ON and the document has no synced blocks,
|
|
135
|
+
// skip the toolbar config entirely to avoid the per-selection-change
|
|
136
|
+
// cost of findSyncBlockOrBodiedSyncBlock (EDITOR-6931).
|
|
137
|
+
// Save the expValEquals('editor_synced_block_perf', 'isEnabled', true) in a const
|
|
138
|
+
// because floatingToolbar is called on every selection change.
|
|
139
|
+
// computing it once at plugin initialisation is more efficient.
|
|
140
|
+
if (!((_syncedBlockPluginKey = syncedBlockPluginKey.getState(state)) !== null && _syncedBlockPluginKey !== void 0 && _syncedBlockPluginKey.hasSyncedBlocks) && isPerfExperimentOn) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
94
143
|
return getToolbarConfig(state, intl, api, syncBlockStore);
|
|
95
144
|
}
|
|
96
145
|
},
|
|
97
|
-
contentComponent: function contentComponent(
|
|
98
|
-
var containerElement =
|
|
99
|
-
wrapperElement =
|
|
100
|
-
popupsMountPoint =
|
|
146
|
+
contentComponent: function contentComponent(_ref4) {
|
|
147
|
+
var containerElement = _ref4.containerElement,
|
|
148
|
+
wrapperElement = _ref4.wrapperElement,
|
|
149
|
+
popupsMountPoint = _ref4.popupsMountPoint;
|
|
101
150
|
refs.containerElement = containerElement || undefined;
|
|
102
151
|
refs.popupsMountPoint = popupsMountPoint || undefined;
|
|
103
152
|
refs.wrapperElement = wrapperElement || undefined;
|
|
104
|
-
return /*#__PURE__*/React.createElement(
|
|
105
|
-
|
|
153
|
+
return /*#__PURE__*/React.createElement(LazySyncedBlockUI, {
|
|
154
|
+
syncBlockStore: syncBlockStore,
|
|
106
155
|
api: api
|
|
107
|
-
})
|
|
108
|
-
syncBlockStoreManager: syncBlockStore,
|
|
109
|
-
api: api
|
|
110
|
-
}), /*#__PURE__*/React.createElement(Flag, {
|
|
111
|
-
api: api
|
|
112
|
-
}));
|
|
156
|
+
});
|
|
113
157
|
},
|
|
114
158
|
getSharedState: function getSharedState(editorState) {
|
|
115
159
|
if (!editorState) {
|
|
116
160
|
return;
|
|
117
161
|
}
|
|
118
|
-
var
|
|
119
|
-
|
|
120
|
-
currentSyncBlockStore =
|
|
121
|
-
bodiedSyncBlockDeletionStatus =
|
|
122
|
-
retryCreationPosMap =
|
|
123
|
-
hasSyncedBlocks =
|
|
124
|
-
hasUnsavedBodiedSyncBlockChanges =
|
|
125
|
-
|
|
162
|
+
var pluginState = syncedBlockPluginKey.getState(editorState);
|
|
163
|
+
var activeFlag = pluginState.activeFlag,
|
|
164
|
+
currentSyncBlockStore = pluginState.syncBlockStore,
|
|
165
|
+
bodiedSyncBlockDeletionStatus = pluginState.bodiedSyncBlockDeletionStatus,
|
|
166
|
+
retryCreationPosMap = pluginState.retryCreationPosMap,
|
|
167
|
+
hasSyncedBlocks = pluginState.hasSyncedBlocks,
|
|
168
|
+
hasUnsavedBodiedSyncBlockChanges = pluginState.hasUnsavedBodiedSyncBlockChanges;
|
|
169
|
+
|
|
170
|
+
// --- EDITOR-6929 / PR-F: return a stable reference when all
|
|
171
|
+
// fields are unchanged to prevent unnecessary React re-renders. ---
|
|
172
|
+
if (cachedSharedState !== undefined && cachedSharedState.activeFlag === activeFlag && cachedSharedState.syncBlockStore === currentSyncBlockStore && cachedSharedState.bodiedSyncBlockDeletionStatus === bodiedSyncBlockDeletionStatus && cachedSharedState.retryCreationPosMap === retryCreationPosMap && cachedSharedState.hasSyncedBlocks === hasSyncedBlocks && cachedSharedState.hasUnsavedBodiedSyncBlockChanges === hasUnsavedBodiedSyncBlockChanges && expValEquals('editor_synced_block_perf', 'isEnabled', true)) {
|
|
173
|
+
return cachedSharedState;
|
|
174
|
+
}
|
|
175
|
+
var nextSharedState = {
|
|
126
176
|
activeFlag: activeFlag,
|
|
127
177
|
syncBlockStore: currentSyncBlockStore,
|
|
128
178
|
bodiedSyncBlockDeletionStatus: bodiedSyncBlockDeletionStatus,
|
|
@@ -130,6 +180,8 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref) {
|
|
|
130
180
|
hasSyncedBlocks: hasSyncedBlocks,
|
|
131
181
|
hasUnsavedBodiedSyncBlockChanges: hasUnsavedBodiedSyncBlockChanges
|
|
132
182
|
};
|
|
183
|
+
cachedSharedState = nextSharedState;
|
|
184
|
+
return nextSharedState;
|
|
133
185
|
}
|
|
134
186
|
};
|
|
135
187
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-synced-block",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.11",
|
|
4
4
|
"description": "SyncedBlock plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
55
55
|
"@atlaskit/primitives": "^19.0.0",
|
|
56
56
|
"@atlaskit/spinner": "19.1.2",
|
|
57
|
-
"@atlaskit/tmp-editor-statsig": "^77.
|
|
58
|
-
"@atlaskit/tokens": "13.0.
|
|
57
|
+
"@atlaskit/tmp-editor-statsig": "^77.3.0",
|
|
58
|
+
"@atlaskit/tokens": "13.0.4",
|
|
59
59
|
"@atlaskit/tooltip": "^22.0.0",
|
|
60
60
|
"@atlaskit/visually-hidden": "^3.1.0",
|
|
61
61
|
"@babel/runtime": "^7.0.0",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"date-fns": "^2.17.0"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@atlaskit/editor-common": "^114.
|
|
67
|
+
"@atlaskit/editor-common": "^114.26.0",
|
|
68
68
|
"react": "^18.2.0",
|
|
69
69
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
70
70
|
},
|