@atlaskit/editor-core 201.2.0 → 201.2.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/composable-editor/core-editor.js +8 -6
  3. package/dist/cjs/composable-editor/editor-internal.js +1 -1
  4. package/dist/cjs/create-editor/ReactEditorView/useDispatchTransaction.js +0 -1
  5. package/dist/cjs/create-editor/ReactEditorView/usePluginPerformanceObserver.js +7 -6
  6. package/dist/cjs/create-editor/ReactEditorView.js +3 -3
  7. package/dist/cjs/create-editor/ReactEditorViewNext.js +56 -45
  8. package/dist/cjs/create-editor/create-plugins-list.js +1 -1
  9. package/dist/cjs/create-editor/create-universal-preset.js +1 -1
  10. package/dist/cjs/create-editor/feature-flags-from-props.js +9 -11
  11. package/dist/cjs/version-wrapper.js +1 -1
  12. package/dist/es2019/composable-editor/core-editor.js +5 -1
  13. package/dist/es2019/composable-editor/editor-internal.js +1 -1
  14. package/dist/es2019/create-editor/ReactEditorView/useDispatchTransaction.js +0 -1
  15. package/dist/es2019/create-editor/ReactEditorView/usePluginPerformanceObserver.js +11 -8
  16. package/dist/es2019/create-editor/ReactEditorView.js +3 -3
  17. package/dist/es2019/create-editor/ReactEditorViewNext.js +47 -42
  18. package/dist/es2019/create-editor/create-plugins-list.js +1 -1
  19. package/dist/es2019/create-editor/create-universal-preset.js +1 -1
  20. package/dist/es2019/create-editor/feature-flags-from-props.js +9 -11
  21. package/dist/es2019/version-wrapper.js +1 -1
  22. package/dist/esm/composable-editor/core-editor.js +7 -1
  23. package/dist/esm/composable-editor/editor-internal.js +1 -1
  24. package/dist/esm/create-editor/ReactEditorView/useDispatchTransaction.js +0 -1
  25. package/dist/esm/create-editor/ReactEditorView/usePluginPerformanceObserver.js +7 -6
  26. package/dist/esm/create-editor/ReactEditorView.js +3 -3
  27. package/dist/esm/create-editor/ReactEditorViewNext.js +56 -45
  28. package/dist/esm/create-editor/create-plugins-list.js +1 -1
  29. package/dist/esm/create-editor/create-universal-preset.js +1 -1
  30. package/dist/esm/create-editor/feature-flags-from-props.js +9 -11
  31. package/dist/esm/version-wrapper.js +1 -1
  32. package/dist/types/create-editor/ReactEditorView/useDispatchTransaction.d.ts +2 -2
  33. package/dist/types/create-editor/ReactEditorView/usePluginPerformanceObserver.d.ts +1 -1
  34. package/dist/types/create-editor/feature-flags-from-props.d.ts +1 -1
  35. package/dist/types-ts4.5/create-editor/ReactEditorView/useDispatchTransaction.d.ts +2 -2
  36. package/dist/types-ts4.5/create-editor/ReactEditorView/usePluginPerformanceObserver.d.ts +1 -1
  37. package/dist/types-ts4.5/create-editor/feature-flags-from-props.d.ts +1 -1
  38. package/package.json +7 -3
@@ -37,7 +37,10 @@ function ReactEditorView(props) {
37
37
  preset,
38
38
  editorProps: {
39
39
  appearance: nextAppearance,
40
- disabled
40
+ disabled,
41
+ featureFlags: editorPropFeatureFlags,
42
+ errorReporterHandler,
43
+ defaultValue
41
44
  }
42
45
  } = props;
43
46
  const [editorAPI, setEditorAPI] = useState(undefined);
@@ -60,14 +63,14 @@ function ReactEditorView(props) {
60
63
  onEditorViewStateUpdatedCallbacks: []
61
64
  });
62
65
  const contentTransformer = useRef(undefined);
63
- const featureFlags = useRef(createFeatureFlagsFromProps(props.editorProps));
66
+ const featureFlags = useMemo(() => createFeatureFlagsFromProps(editorPropFeatureFlags), [editorPropFeatureFlags]);
64
67
  const getEditorState = useCallback(() => {
65
68
  var _viewRef$current;
66
69
  return (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
67
70
  }, []);
68
71
  const getEditorView = useCallback(() => viewRef.current, []);
69
72
  const dispatch = useMemo(() => createDispatch(eventDispatcher), [eventDispatcher]);
70
- const errorReporter = useRef(createErrorReporter(props.editorProps.errorReporterHandler));
73
+ const errorReporter = useMemo(() => createErrorReporter(errorReporterHandler), [errorReporterHandler]);
71
74
  const handleAnalyticsEvent = useCallback(payload => {
72
75
  fireAnalyticsEvent(props.createAnalyticsEvent)(payload);
73
76
  }, [props.createAnalyticsEvent]);
@@ -84,22 +87,6 @@ function ReactEditorView(props) {
84
87
  useLayoutEffect(() => {
85
88
  setEditorAPI(pluginInjectionAPI.current.api());
86
89
  }, []);
87
- const blur = useCallback(() => {
88
- if (!viewRef.current) {
89
- return;
90
- }
91
- if (viewRef.current.dom instanceof HTMLElement && viewRef.current.hasFocus()) {
92
- viewRef.current.dom.blur();
93
- }
94
-
95
- // The selectionToDOM method uses the document selection to determine currently selected node
96
- // We need to mimic blurring this as it seems doing the above is not enough.
97
- // @ts-expect-error
98
- const sel = viewRef.current.root.getSelection();
99
- if (sel) {
100
- sel.removeAllRanges();
101
- }
102
- }, []);
103
90
  const createEditorState = useCallback(options => {
104
91
  var _api$editorViewMode;
105
92
  let schema;
@@ -133,14 +120,14 @@ function ReactEditorView(props) {
133
120
  const plugins = createPMPlugins({
134
121
  schema,
135
122
  dispatch: dispatch,
136
- errorReporter: errorReporter.current,
123
+ errorReporter: errorReporter,
137
124
  editorConfig: config.current,
138
125
  eventDispatcher: eventDispatcher,
139
126
  providerFactory: options.props.providerFactory,
140
127
  portalProviderAPI: props.portalProviderAPI,
141
128
  nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
142
129
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
143
- featureFlags: featureFlags.current,
130
+ featureFlags,
144
131
  getIntl: () => props.intl
145
132
  });
146
133
  contentTransformer.current = contentTransformerProvider ? contentTransformerProvider(schema) : undefined;
@@ -180,7 +167,36 @@ function ReactEditorView(props) {
180
167
  doc,
181
168
  selection: patchedSelection
182
169
  });
183
- }, [props.intl, props.portalProviderAPI, props.nodeViewPortalProviderAPI, props.editorProps, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
170
+ }, [errorReporter, featureFlags, props.intl, props.portalProviderAPI, props.nodeViewPortalProviderAPI, props.editorProps, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
171
+ const initialEditorState = useMemo(() => createEditorState({
172
+ props,
173
+ doc: defaultValue,
174
+ // ED-4759: Don't set selection at end for full-page editor - should be at start.
175
+ selectionAtStart: isFullPage(nextAppearance)
176
+ }),
177
+ // This is only used for the initial state - afterwards we will have `viewRef` available for use
178
+ // eslint-disable-next-line react-hooks/exhaustive-deps
179
+ []);
180
+ const getCurrentEditorState = useCallback(() => {
181
+ var _viewRef$current$stat, _viewRef$current2;
182
+ return (_viewRef$current$stat = (_viewRef$current2 = viewRef.current) === null || _viewRef$current2 === void 0 ? void 0 : _viewRef$current2.state) !== null && _viewRef$current$stat !== void 0 ? _viewRef$current$stat : initialEditorState;
183
+ }, [initialEditorState]);
184
+ const blur = useCallback(() => {
185
+ if (!viewRef.current) {
186
+ return;
187
+ }
188
+ if (viewRef.current.dom instanceof HTMLElement && viewRef.current.hasFocus()) {
189
+ viewRef.current.dom.blur();
190
+ }
191
+
192
+ // The selectionToDOM method uses the document selection to determine currently selected node
193
+ // We need to mimic blurring this as it seems doing the above is not enough.
194
+ // @ts-expect-error
195
+ const sel = viewRef.current.root.getSelection();
196
+ if (sel) {
197
+ sel.removeAllRanges();
198
+ }
199
+ }, []);
184
200
  const resetEditorState = useCallback(({
185
201
  doc,
186
202
  shouldScrollToBottom
@@ -194,14 +210,12 @@ function ReactEditorView(props) {
194
210
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
195
211
  // nodes that haven't been re-rendered to the document yet.
196
212
  blur();
197
- featureFlags.current = createFeatureFlagsFromProps(props.editorProps);
198
213
  const newEditorState = createEditorState({
199
214
  props: props,
200
215
  doc: doc,
201
216
  resetting: true,
202
217
  selectionAtStart: !shouldScrollToBottom
203
218
  });
204
- editorState.current = newEditorState;
205
219
  viewRef.current.updateState(newEditorState);
206
220
  (_props$editorProps$on = (_props$editorProps = props.editorProps).onChange) === null || _props$editorProps$on === void 0 ? void 0 : _props$editorProps$on.call(_props$editorProps, viewRef.current, {
207
221
  source: 'local'
@@ -216,7 +230,7 @@ function ReactEditorView(props) {
216
230
  actionSubject: ACTION_SUBJECT.EDITOR,
217
231
  attributes: {
218
232
  platform: PLATFORMS.WEB,
219
- featureFlags: featureFlags.current ? getEnabledFeatureFlagKeys(featureFlags.current) : []
233
+ featureFlags: featureFlags ? getEnabledFeatureFlagKeys(featureFlags) : []
220
234
  },
221
235
  eventType: EVENT_TYPE.UI
222
236
  });
@@ -266,18 +280,18 @@ function ReactEditorView(props) {
266
280
  blur();
267
281
  const editorPlugins = createPluginsList(props.preset, props.editorProps, pluginInjectionAPI.current);
268
282
  config.current = processPluginsList(editorPlugins);
269
- const state = editorState.current;
283
+ const state = viewRef.current.state;
270
284
  const plugins = createPMPlugins({
271
285
  schema: state.schema,
272
286
  dispatch: dispatch,
273
- errorReporter: errorReporter.current,
287
+ errorReporter: errorReporter,
274
288
  editorConfig: config.current,
275
289
  eventDispatcher: eventDispatcher,
276
290
  providerFactory: props.providerFactory,
277
291
  portalProviderAPI: props.portalProviderAPI,
278
292
  nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
279
293
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
280
- featureFlags: createFeatureFlagsFromProps(props.editorProps),
294
+ featureFlags,
281
295
  getIntl: () => props.intl
282
296
  });
283
297
  const newState = state.reconfigure({
@@ -291,7 +305,7 @@ function ReactEditorView(props) {
291
305
  ...viewRef.current.props,
292
306
  state: newState
293
307
  });
294
- }, [blur, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
308
+ }, [blur, dispatchAnalyticsEvent, eventDispatcher, dispatch, errorReporter, featureFlags]);
295
309
  const onEditorViewUpdated = useCallback(({
296
310
  originalTransaction,
297
311
  transactions,
@@ -334,16 +348,13 @@ function ReactEditorView(props) {
334
348
  });
335
349
  const getDirectEditorProps = useCallback(state => {
336
350
  return {
337
- state: state || editorState.current,
351
+ state: state !== null && state !== void 0 ? state : getCurrentEditorState(),
338
352
  dispatchTransaction: tr => {
339
353
  // Block stale transactions:
340
354
  // Prevent runtime exeptions from async transactions that would attempt to
341
355
  // update the DOM after React has unmounted the Editor.
342
356
  if (canDispatchTransactions.current) {
343
- const newState = dispatchTransaction(viewRef.current, tr);
344
- if (newState) {
345
- editorState.current = newState;
346
- }
357
+ dispatchTransaction(viewRef.current, tr);
347
358
  }
348
359
  },
349
360
  // Disables the contentEditable attribute of the editor if the editor is disabled
@@ -352,7 +363,7 @@ function ReactEditorView(props) {
352
363
  'data-gramm': 'false'
353
364
  }
354
365
  };
355
- }, [dispatchTransaction, disabled]);
366
+ }, [dispatchTransaction, disabled, getCurrentEditorState]);
356
367
  const createEditorView = useCallback(node => {
357
368
  measureRender(measurements.PROSEMIRROR_RENDERED, ({
358
369
  duration,
@@ -479,13 +490,7 @@ function ReactEditorView(props) {
479
490
  }
480
491
  }, [disabled, shouldFocus, previousDisabledState]);
481
492
  useFireFullWidthEvent(nextAppearance, dispatchAnalyticsEvent);
482
- const editorState = useRef(createEditorState({
483
- props,
484
- doc: props.editorProps.defaultValue,
485
- // ED-4759: Don't set selection at end for full-page editor - should be at start.
486
- selectionAtStart: isFullPage(props.editorProps.appearance)
487
- }));
488
- usePluginPerformanceObserver(editorState, pluginInjectionAPI, dispatchAnalyticsEvent);
493
+ usePluginPerformanceObserver(getCurrentEditorState, pluginInjectionAPI, dispatchAnalyticsEvent);
489
494
  const editor = useMemo(() => createEditor(props.editorProps.assistiveLabel, props.editorProps.assistiveDescribedBy),
490
495
  // `createEditor` changes a little too frequently - we don't want to recreate the editor view in this case
491
496
  // We should follow-up
@@ -28,7 +28,7 @@ export function getDefaultPresetOptionsFromEditorProps(props, createAnalyticsEve
28
28
  typeAhead: {
29
29
  isMobile: false
30
30
  },
31
- featureFlags: createFeatureFlagsFromProps(props),
31
+ featureFlags: createFeatureFlagsFromProps(props.featureFlags),
32
32
  paste: {
33
33
  cardOptions,
34
34
  sanitizePrivateContent: props.sanitizePrivateContent
@@ -14,7 +14,7 @@ export function createUniversalPreset({
14
14
  appearance: props.appearance,
15
15
  props: getDefaultPresetOptionsFromEditorProps(props),
16
16
  initialPluginConfiguration: initialPluginConfiguration,
17
- featureFlags: createFeatureFlagsFromProps(props),
17
+ featureFlags: createFeatureFlagsFromProps(props.featureFlags),
18
18
  prevAppearance: prevProps === null || prevProps === void 0 ? void 0 : prevProps.appearance
19
19
  });
20
20
  return withDangerouslyAppendPlugins(preset)((_props$dangerouslyApp = props.dangerouslyAppendPlugins) === null || _props$dangerouslyApp === void 0 ? void 0 : _props$dangerouslyApp.__plugins);
@@ -20,19 +20,17 @@ function getSpellCheck(featureFlags) {
20
20
  * Transforms EditorProps to an FeatureFlags object,
21
21
  * which is used by both current and archv3 editors.
22
22
  */
23
- export function createFeatureFlagsFromProps(props) {
24
- var _props$featureFlags, _props$featureFlags2, _props$featureFlags3, _props$featureFlags4, _props$featureFlags5, _props$featureFlags6, _props$featureFlags7, _props$featureFlags8, _props$featureFlags9, _props$featureFlags10, _props$featureFlags11, _props$featureFlags12, _props$collabEdit, _props$collabEdit2;
25
- const normalizedFeatureFlags = normalizeFeatureFlags(props.featureFlags);
23
+ export function createFeatureFlagsFromProps(featureFlags) {
24
+ const normalizedFeatureFlags = normalizeFeatureFlags(featureFlags);
26
25
  return {
27
26
  ...normalizedFeatureFlags,
28
27
  catchAllTracking: false,
29
- showAvatarGroupAsPlugin: Boolean(typeof ((_props$featureFlags = props.featureFlags) === null || _props$featureFlags === void 0 ? void 0 : _props$featureFlags.showAvatarGroupAsPlugin) === 'boolean' ? !!((_props$featureFlags2 = props.featureFlags) !== null && _props$featureFlags2 !== void 0 && _props$featureFlags2.showAvatarGroupAsPlugin) : false),
30
- errorBoundaryDocStructure: Boolean(typeof ((_props$featureFlags3 = props.featureFlags) === null || _props$featureFlags3 === void 0 ? void 0 : _props$featureFlags3.useErrorBoundaryDocStructure) === 'boolean' ? !!((_props$featureFlags4 = props.featureFlags) !== null && _props$featureFlags4 !== void 0 && _props$featureFlags4.useErrorBoundaryDocStructure) : false),
31
- synchronyErrorDocStructure: Boolean(typeof ((_props$featureFlags5 = props.featureFlags) === null || _props$featureFlags5 === void 0 ? void 0 : _props$featureFlags5.synchronyErrorDocStructure) === 'boolean' ? !!((_props$featureFlags6 = props.featureFlags) !== null && _props$featureFlags6 !== void 0 && _props$featureFlags6.synchronyErrorDocStructure) : false),
32
- enableViewUpdateSubscription: Boolean(typeof ((_props$featureFlags7 = props.featureFlags) === null || _props$featureFlags7 === void 0 ? void 0 : _props$featureFlags7.enableViewUpdateSubscription) === 'boolean' ? !!((_props$featureFlags8 = props.featureFlags) !== null && _props$featureFlags8 !== void 0 && _props$featureFlags8.enableViewUpdateSubscription) : false),
33
- collabAvatarScroll: Boolean(typeof ((_props$featureFlags9 = props.featureFlags) === null || _props$featureFlags9 === void 0 ? void 0 : _props$featureFlags9.collabAvatarScroll) === 'boolean' ? !!((_props$featureFlags10 = props.featureFlags) !== null && _props$featureFlags10 !== void 0 && _props$featureFlags10.collabAvatarScroll) : false),
34
- twoLineEditorToolbar: Boolean(typeof ((_props$featureFlags11 = props.featureFlags) === null || _props$featureFlags11 === void 0 ? void 0 : _props$featureFlags11.twoLineEditorToolbar) === 'boolean' ? !!((_props$featureFlags12 = props.featureFlags) !== null && _props$featureFlags12 !== void 0 && _props$featureFlags12.twoLineEditorToolbar) : false),
35
- useNativeCollabPlugin: Boolean(typeof ((_props$collabEdit = props.collabEdit) === null || _props$collabEdit === void 0 ? void 0 : _props$collabEdit.useNativePlugin) === 'boolean' ? !!((_props$collabEdit2 = props.collabEdit) !== null && _props$collabEdit2 !== void 0 && _props$collabEdit2.useNativePlugin) : false),
36
- disableSpellcheckByBrowser: getSpellCheck(props.featureFlags)
28
+ showAvatarGroupAsPlugin: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.showAvatarGroupAsPlugin) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.showAvatarGroupAsPlugin) : false),
29
+ errorBoundaryDocStructure: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.useErrorBoundaryDocStructure) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.useErrorBoundaryDocStructure) : false),
30
+ synchronyErrorDocStructure: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.synchronyErrorDocStructure) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.synchronyErrorDocStructure) : false),
31
+ enableViewUpdateSubscription: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.enableViewUpdateSubscription) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.enableViewUpdateSubscription) : false),
32
+ collabAvatarScroll: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.collabAvatarScroll) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.collabAvatarScroll) : false),
33
+ twoLineEditorToolbar: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.twoLineEditorToolbar) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.twoLineEditorToolbar) : false),
34
+ disableSpellcheckByBrowser: getSpellCheck(featureFlags)
37
35
  };
38
36
  }
@@ -1,2 +1,2 @@
1
1
  export const name = "@atlaskit/editor-core";
2
- export const version = "201.2.0";
2
+ export const version = "201.2.1";
@@ -1,4 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  /**
3
6
  * @jsxRuntime classic
4
7
  * @jsx jsx
@@ -45,7 +48,10 @@ function Editor(passedProps) {
45
48
  fireAnalyticsEvent(createAnalyticsEvent)(data);
46
49
  }, [createAnalyticsEvent]);
47
50
  var getFeatureFlagsFromRef = useCallback(function () {
48
- return createFeatureFlagsFromProps(propsRef.current);
51
+ var _propsRef$current$col, _propsRef$current$col2;
52
+ return _objectSpread(_objectSpread({}, createFeatureFlagsFromProps(propsRef.current.featureFlags)), {}, {
53
+ useNativeCollabPlugin: Boolean(typeof ((_propsRef$current$col = propsRef.current.collabEdit) === null || _propsRef$current$col === void 0 ? void 0 : _propsRef$current$col.useNativePlugin) === 'boolean' ? !!((_propsRef$current$col2 = propsRef.current.collabEdit) !== null && _propsRef$current$col2 !== void 0 && _propsRef$current$col2.useNativePlugin) : false)
54
+ });
49
55
  }, []);
50
56
  var onEditorCreated = useCallback(function (instance) {
51
57
  var _propsRef$current = propsRef.current,
@@ -51,7 +51,7 @@ export var EditorInternal = /*#__PURE__*/memo(function (_ref) {
51
51
  // noop all analytic events, even if a handler is still passed.
52
52
  analyticsHandler: undefined
53
53
  });
54
- var featureFlags = createFeatureFlagsFromProps(props);
54
+ var featureFlags = createFeatureFlagsFromProps(props.featureFlags);
55
55
 
56
56
  // Render tracking is firing too many events in Jira so we are disabling them for now. See - https://product-fabric.atlassian.net/browse/ED-25616
57
57
  var renderTrackingEnabled = !fg('platform_editor_disable_rerender_tracking_jira');
@@ -60,7 +60,6 @@ export var useDispatchTransaction = function useDispatchTransaction(_ref) {
60
60
  });
61
61
  });
62
62
  }
63
- return newEditorState;
64
63
  } else {
65
64
  var invalidNodes = nodes.filter(function (node) {
66
65
  return !validNode(node);
@@ -2,7 +2,7 @@ import { useCallback, useLayoutEffect, useMemo } from 'react';
2
2
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  import { countNodes } from '@atlaskit/editor-common/count-nodes';
4
4
  import { PluginPerformanceObserver } from '../../utils/performance/plugin-performance-observer';
5
- export var usePluginPerformanceObserver = function usePluginPerformanceObserver(editorState, pluginInjectionAPI, dispatchAnalyticsEvent) {
5
+ export var usePluginPerformanceObserver = function usePluginPerformanceObserver(getEditorState, pluginInjectionAPI, dispatchAnalyticsEvent) {
6
6
  var onPluginObservation = useCallback(function (report) {
7
7
  var _pluginInjectionAPI$c;
8
8
  dispatchAnalyticsEvent({
@@ -16,24 +16,25 @@ export var usePluginPerformanceObserver = function usePluginPerformanceObserver(
16
16
  });
17
17
  }, [dispatchAnalyticsEvent, pluginInjectionAPI]);
18
18
  var getPluginNames = useCallback(function () {
19
- var _editorState$current;
19
+ var _getEditorState;
20
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
- return (_editorState$current = editorState.current) === null || _editorState$current === void 0 ? void 0 : _editorState$current.plugins.map(function (p) {
21
+ return (_getEditorState = getEditorState()) === null || _getEditorState === void 0 ? void 0 : _getEditorState.plugins.map(function (p) {
22
22
  return p.key;
23
23
  });
24
- }, [editorState]);
24
+ }, [getEditorState]);
25
25
  var pluginPerformanceObserver = useMemo(function () {
26
+ var state = getEditorState();
26
27
  return new PluginPerformanceObserver(function (report) {
27
28
  return onPluginObservation(report);
28
29
  }).withPlugins(function () {
29
30
  return getPluginNames();
30
31
  }).withNodeCounts(function () {
31
- return editorState.current ? countNodes(editorState.current) : {
32
+ return state ? countNodes(state) : {
32
33
  nodeCount: {},
33
34
  extensionNodeCount: {}
34
35
  };
35
36
  });
36
- }, [onPluginObservation, getPluginNames, editorState]);
37
+ }, [onPluginObservation, getPluginNames, getEditorState]);
37
38
  useLayoutEffect(function () {
38
39
  return function () {
39
40
  pluginPerformanceObserver.disconnect();
@@ -130,7 +130,7 @@ export var ReactEditorView = /*#__PURE__*/function (_React$Component) {
130
130
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
131
131
  // nodes that haven't been re-rendered to the document yet.
132
132
  _this.blur();
133
- _this.featureFlags = createFeatureFlagsFromProps(_this.props.editorProps);
133
+ _this.featureFlags = createFeatureFlagsFromProps(_this.props.editorProps.featureFlags);
134
134
  _this.editorState = _this.createEditorState({
135
135
  props: _this.props,
136
136
  doc: doc,
@@ -470,7 +470,7 @@ export var ReactEditorView = /*#__PURE__*/function (_React$Component) {
470
470
  }).withNodeCounts(function () {
471
471
  return _this.countNodes();
472
472
  });
473
- _this.featureFlags = createFeatureFlagsFromProps(_this.props.editorProps);
473
+ _this.featureFlags = createFeatureFlagsFromProps(_this.props.editorProps.featureFlags);
474
474
  var featureFlagsEnabled = _this.featureFlags ? getEnabledFeatureFlagKeys(_this.featureFlags) : [];
475
475
 
476
476
  // This needs to be before initialising editorState because
@@ -579,7 +579,7 @@ export var ReactEditorView = /*#__PURE__*/function (_React$Component) {
579
579
  portalProviderAPI: props.portalProviderAPI,
580
580
  nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
581
581
  dispatchAnalyticsEvent: this.dispatchAnalyticsEvent,
582
- featureFlags: createFeatureFlagsFromProps(props.editorProps),
582
+ featureFlags: createFeatureFlagsFromProps(props.editorProps.featureFlags),
583
583
  getIntl: function getIntl() {
584
584
  return _this2.props.intl;
585
585
  }
@@ -40,7 +40,10 @@ function ReactEditorView(props) {
40
40
  var preset = props.preset,
41
41
  _props$editorProps = props.editorProps,
42
42
  nextAppearance = _props$editorProps.appearance,
43
- disabled = _props$editorProps.disabled;
43
+ disabled = _props$editorProps.disabled,
44
+ editorPropFeatureFlags = _props$editorProps.featureFlags,
45
+ errorReporterHandler = _props$editorProps.errorReporterHandler,
46
+ defaultValue = _props$editorProps.defaultValue;
44
47
  var _useState = useState(undefined),
45
48
  _useState2 = _slicedToArray(_useState, 2),
46
49
  editorAPI = _useState2[0],
@@ -66,7 +69,9 @@ function ReactEditorView(props) {
66
69
  onEditorViewStateUpdatedCallbacks: []
67
70
  });
68
71
  var contentTransformer = useRef(undefined);
69
- var featureFlags = useRef(createFeatureFlagsFromProps(props.editorProps));
72
+ var featureFlags = useMemo(function () {
73
+ return createFeatureFlagsFromProps(editorPropFeatureFlags);
74
+ }, [editorPropFeatureFlags]);
70
75
  var getEditorState = useCallback(function () {
71
76
  var _viewRef$current;
72
77
  return (_viewRef$current = viewRef.current) === null || _viewRef$current === void 0 ? void 0 : _viewRef$current.state;
@@ -77,7 +82,9 @@ function ReactEditorView(props) {
77
82
  var dispatch = useMemo(function () {
78
83
  return createDispatch(eventDispatcher);
79
84
  }, [eventDispatcher]);
80
- var errorReporter = useRef(createErrorReporter(props.editorProps.errorReporterHandler));
85
+ var errorReporter = useMemo(function () {
86
+ return createErrorReporter(errorReporterHandler);
87
+ }, [errorReporterHandler]);
81
88
  var handleAnalyticsEvent = useCallback(function (payload) {
82
89
  fireAnalyticsEvent(props.createAnalyticsEvent)(payload);
83
90
  }, [props.createAnalyticsEvent]);
@@ -94,22 +101,6 @@ function ReactEditorView(props) {
94
101
  useLayoutEffect(function () {
95
102
  setEditorAPI(pluginInjectionAPI.current.api());
96
103
  }, []);
97
- var blur = useCallback(function () {
98
- if (!viewRef.current) {
99
- return;
100
- }
101
- if (viewRef.current.dom instanceof HTMLElement && viewRef.current.hasFocus()) {
102
- viewRef.current.dom.blur();
103
- }
104
-
105
- // The selectionToDOM method uses the document selection to determine currently selected node
106
- // We need to mimic blurring this as it seems doing the above is not enough.
107
- // @ts-expect-error
108
- var sel = viewRef.current.root.getSelection();
109
- if (sel) {
110
- sel.removeAllRanges();
111
- }
112
- }, []);
113
104
  var createEditorState = useCallback(function (options) {
114
105
  var _api$editorViewMode;
115
106
  var schema;
@@ -141,14 +132,14 @@ function ReactEditorView(props) {
141
132
  var plugins = createPMPlugins({
142
133
  schema: schema,
143
134
  dispatch: dispatch,
144
- errorReporter: errorReporter.current,
135
+ errorReporter: errorReporter,
145
136
  editorConfig: config.current,
146
137
  eventDispatcher: eventDispatcher,
147
138
  providerFactory: options.props.providerFactory,
148
139
  portalProviderAPI: props.portalProviderAPI,
149
140
  nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
150
141
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
151
- featureFlags: featureFlags.current,
142
+ featureFlags: featureFlags,
152
143
  getIntl: function getIntl() {
153
144
  return props.intl;
154
145
  }
@@ -190,7 +181,38 @@ function ReactEditorView(props) {
190
181
  doc: doc,
191
182
  selection: patchedSelection
192
183
  });
193
- }, [props.intl, props.portalProviderAPI, props.nodeViewPortalProviderAPI, props.editorProps, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
184
+ }, [errorReporter, featureFlags, props.intl, props.portalProviderAPI, props.nodeViewPortalProviderAPI, props.editorProps, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
185
+ var initialEditorState = useMemo(function () {
186
+ return createEditorState({
187
+ props: props,
188
+ doc: defaultValue,
189
+ // ED-4759: Don't set selection at end for full-page editor - should be at start.
190
+ selectionAtStart: isFullPage(nextAppearance)
191
+ });
192
+ },
193
+ // This is only used for the initial state - afterwards we will have `viewRef` available for use
194
+ // eslint-disable-next-line react-hooks/exhaustive-deps
195
+ []);
196
+ var getCurrentEditorState = useCallback(function () {
197
+ var _viewRef$current$stat, _viewRef$current2;
198
+ return (_viewRef$current$stat = (_viewRef$current2 = viewRef.current) === null || _viewRef$current2 === void 0 ? void 0 : _viewRef$current2.state) !== null && _viewRef$current$stat !== void 0 ? _viewRef$current$stat : initialEditorState;
199
+ }, [initialEditorState]);
200
+ var blur = useCallback(function () {
201
+ if (!viewRef.current) {
202
+ return;
203
+ }
204
+ if (viewRef.current.dom instanceof HTMLElement && viewRef.current.hasFocus()) {
205
+ viewRef.current.dom.blur();
206
+ }
207
+
208
+ // The selectionToDOM method uses the document selection to determine currently selected node
209
+ // We need to mimic blurring this as it seems doing the above is not enough.
210
+ // @ts-expect-error
211
+ var sel = viewRef.current.root.getSelection();
212
+ if (sel) {
213
+ sel.removeAllRanges();
214
+ }
215
+ }, []);
194
216
  var resetEditorState = useCallback(function (_ref) {
195
217
  var _props$editorProps$on, _props$editorProps2;
196
218
  var doc = _ref.doc,
@@ -203,14 +225,12 @@ function ReactEditorView(props) {
203
225
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
204
226
  // nodes that haven't been re-rendered to the document yet.
205
227
  blur();
206
- featureFlags.current = createFeatureFlagsFromProps(props.editorProps);
207
228
  var newEditorState = createEditorState({
208
229
  props: props,
209
230
  doc: doc,
210
231
  resetting: true,
211
232
  selectionAtStart: !shouldScrollToBottom
212
233
  });
213
- editorState.current = newEditorState;
214
234
  viewRef.current.updateState(newEditorState);
215
235
  (_props$editorProps$on = (_props$editorProps2 = props.editorProps).onChange) === null || _props$editorProps$on === void 0 || _props$editorProps$on.call(_props$editorProps2, viewRef.current, {
216
236
  source: 'local'
@@ -225,7 +245,7 @@ function ReactEditorView(props) {
225
245
  actionSubject: ACTION_SUBJECT.EDITOR,
226
246
  attributes: {
227
247
  platform: PLATFORMS.WEB,
228
- featureFlags: featureFlags.current ? getEnabledFeatureFlagKeys(featureFlags.current) : []
248
+ featureFlags: featureFlags ? getEnabledFeatureFlagKeys(featureFlags) : []
229
249
  },
230
250
  eventType: EVENT_TYPE.UI
231
251
  });
@@ -252,9 +272,9 @@ function ReactEditorView(props) {
252
272
  }
253
273
  if (viewRef.current) {
254
274
  // Destroy the state if the Editor is being unmounted
255
- var _editorState = viewRef.current.state;
256
- _editorState.plugins.forEach(function (plugin) {
257
- var state = plugin.getState(_editorState);
275
+ var editorState = viewRef.current.state;
276
+ editorState.plugins.forEach(function (plugin) {
277
+ var state = plugin.getState(editorState);
258
278
  if (state && state.destroy) {
259
279
  state.destroy();
260
280
  }
@@ -275,18 +295,18 @@ function ReactEditorView(props) {
275
295
  blur();
276
296
  var editorPlugins = createPluginsList(props.preset, props.editorProps, pluginInjectionAPI.current);
277
297
  config.current = processPluginsList(editorPlugins);
278
- var state = editorState.current;
298
+ var state = viewRef.current.state;
279
299
  var plugins = createPMPlugins({
280
300
  schema: state.schema,
281
301
  dispatch: dispatch,
282
- errorReporter: errorReporter.current,
302
+ errorReporter: errorReporter,
283
303
  editorConfig: config.current,
284
304
  eventDispatcher: eventDispatcher,
285
305
  providerFactory: props.providerFactory,
286
306
  portalProviderAPI: props.portalProviderAPI,
287
307
  nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
288
308
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
289
- featureFlags: createFeatureFlagsFromProps(props.editorProps),
309
+ featureFlags: featureFlags,
290
310
  getIntl: function getIntl() {
291
311
  return props.intl;
292
312
  }
@@ -301,7 +321,7 @@ function ReactEditorView(props) {
301
321
  return viewRef.current.update(_objectSpread(_objectSpread({}, viewRef.current.props), {}, {
302
322
  state: newState
303
323
  }));
304
- }, [blur, dispatchAnalyticsEvent, eventDispatcher, dispatch]);
324
+ }, [blur, dispatchAnalyticsEvent, eventDispatcher, dispatch, errorReporter, featureFlags]);
305
325
  var onEditorViewUpdated = useCallback(function (_ref2) {
306
326
  var _config$current;
307
327
  var originalTransaction = _ref2.originalTransaction,
@@ -343,16 +363,13 @@ function ReactEditorView(props) {
343
363
  });
344
364
  var getDirectEditorProps = useCallback(function (state) {
345
365
  return {
346
- state: state || editorState.current,
366
+ state: state !== null && state !== void 0 ? state : getCurrentEditorState(),
347
367
  dispatchTransaction: function dispatchTransaction(tr) {
348
368
  // Block stale transactions:
349
369
  // Prevent runtime exeptions from async transactions that would attempt to
350
370
  // update the DOM after React has unmounted the Editor.
351
371
  if (canDispatchTransactions.current) {
352
- var newState = _dispatchTransaction(viewRef.current, tr);
353
- if (newState) {
354
- editorState.current = newState;
355
- }
372
+ _dispatchTransaction(viewRef.current, tr);
356
373
  }
357
374
  },
358
375
  // Disables the contentEditable attribute of the editor if the editor is disabled
@@ -363,7 +380,7 @@ function ReactEditorView(props) {
363
380
  'data-gramm': 'false'
364
381
  }
365
382
  };
366
- }, [_dispatchTransaction, disabled]);
383
+ }, [_dispatchTransaction, disabled, getCurrentEditorState]);
367
384
  var createEditorView = useCallback(function (node) {
368
385
  measureRender(measurements.PROSEMIRROR_RENDERED, function (_ref3) {
369
386
  var duration = _ref3.duration,
@@ -490,13 +507,7 @@ function ReactEditorView(props) {
490
507
  }
491
508
  }, [disabled, shouldFocus, previousDisabledState]);
492
509
  useFireFullWidthEvent(nextAppearance, dispatchAnalyticsEvent);
493
- var editorState = useRef(createEditorState({
494
- props: props,
495
- doc: props.editorProps.defaultValue,
496
- // ED-4759: Don't set selection at end for full-page editor - should be at start.
497
- selectionAtStart: isFullPage(props.editorProps.appearance)
498
- }));
499
- usePluginPerformanceObserver(editorState, pluginInjectionAPI, dispatchAnalyticsEvent);
510
+ usePluginPerformanceObserver(getCurrentEditorState, pluginInjectionAPI, dispatchAnalyticsEvent);
500
511
  var editor = useMemo(function () {
501
512
  return createEditor(props.editorProps.assistiveLabel, props.editorProps.assistiveDescribedBy);
502
513
  },
@@ -30,7 +30,7 @@ export function getDefaultPresetOptionsFromEditorProps(props, createAnalyticsEve
30
30
  typeAhead: {
31
31
  isMobile: false
32
32
  },
33
- featureFlags: createFeatureFlagsFromProps(props),
33
+ featureFlags: createFeatureFlagsFromProps(props.featureFlags),
34
34
  paste: {
35
35
  cardOptions: cardOptions,
36
36
  sanitizePrivateContent: props.sanitizePrivateContent
@@ -13,7 +13,7 @@ export function createUniversalPreset(_ref) {
13
13
  appearance: props.appearance,
14
14
  props: getDefaultPresetOptionsFromEditorProps(props),
15
15
  initialPluginConfiguration: initialPluginConfiguration,
16
- featureFlags: createFeatureFlagsFromProps(props),
16
+ featureFlags: createFeatureFlagsFromProps(props.featureFlags),
17
17
  prevAppearance: prevProps === null || prevProps === void 0 ? void 0 : prevProps.appearance
18
18
  });
19
19
  return withDangerouslyAppendPlugins(preset)((_props$dangerouslyApp = props.dangerouslyAppendPlugins) === null || _props$dangerouslyApp === void 0 ? void 0 : _props$dangerouslyApp.__plugins);
@@ -24,18 +24,16 @@ function getSpellCheck(featureFlags) {
24
24
  * Transforms EditorProps to an FeatureFlags object,
25
25
  * which is used by both current and archv3 editors.
26
26
  */
27
- export function createFeatureFlagsFromProps(props) {
28
- var _props$featureFlags, _props$featureFlags2, _props$featureFlags3, _props$featureFlags4, _props$featureFlags5, _props$featureFlags6, _props$featureFlags7, _props$featureFlags8, _props$featureFlags9, _props$featureFlags10, _props$featureFlags11, _props$featureFlags12, _props$collabEdit, _props$collabEdit2;
29
- var normalizedFeatureFlags = normalizeFeatureFlags(props.featureFlags);
27
+ export function createFeatureFlagsFromProps(featureFlags) {
28
+ var normalizedFeatureFlags = normalizeFeatureFlags(featureFlags);
30
29
  return _objectSpread(_objectSpread({}, normalizedFeatureFlags), {}, {
31
30
  catchAllTracking: false,
32
- showAvatarGroupAsPlugin: Boolean(typeof ((_props$featureFlags = props.featureFlags) === null || _props$featureFlags === void 0 ? void 0 : _props$featureFlags.showAvatarGroupAsPlugin) === 'boolean' ? !!((_props$featureFlags2 = props.featureFlags) !== null && _props$featureFlags2 !== void 0 && _props$featureFlags2.showAvatarGroupAsPlugin) : false),
33
- errorBoundaryDocStructure: Boolean(typeof ((_props$featureFlags3 = props.featureFlags) === null || _props$featureFlags3 === void 0 ? void 0 : _props$featureFlags3.useErrorBoundaryDocStructure) === 'boolean' ? !!((_props$featureFlags4 = props.featureFlags) !== null && _props$featureFlags4 !== void 0 && _props$featureFlags4.useErrorBoundaryDocStructure) : false),
34
- synchronyErrorDocStructure: Boolean(typeof ((_props$featureFlags5 = props.featureFlags) === null || _props$featureFlags5 === void 0 ? void 0 : _props$featureFlags5.synchronyErrorDocStructure) === 'boolean' ? !!((_props$featureFlags6 = props.featureFlags) !== null && _props$featureFlags6 !== void 0 && _props$featureFlags6.synchronyErrorDocStructure) : false),
35
- enableViewUpdateSubscription: Boolean(typeof ((_props$featureFlags7 = props.featureFlags) === null || _props$featureFlags7 === void 0 ? void 0 : _props$featureFlags7.enableViewUpdateSubscription) === 'boolean' ? !!((_props$featureFlags8 = props.featureFlags) !== null && _props$featureFlags8 !== void 0 && _props$featureFlags8.enableViewUpdateSubscription) : false),
36
- collabAvatarScroll: Boolean(typeof ((_props$featureFlags9 = props.featureFlags) === null || _props$featureFlags9 === void 0 ? void 0 : _props$featureFlags9.collabAvatarScroll) === 'boolean' ? !!((_props$featureFlags10 = props.featureFlags) !== null && _props$featureFlags10 !== void 0 && _props$featureFlags10.collabAvatarScroll) : false),
37
- twoLineEditorToolbar: Boolean(typeof ((_props$featureFlags11 = props.featureFlags) === null || _props$featureFlags11 === void 0 ? void 0 : _props$featureFlags11.twoLineEditorToolbar) === 'boolean' ? !!((_props$featureFlags12 = props.featureFlags) !== null && _props$featureFlags12 !== void 0 && _props$featureFlags12.twoLineEditorToolbar) : false),
38
- useNativeCollabPlugin: Boolean(typeof ((_props$collabEdit = props.collabEdit) === null || _props$collabEdit === void 0 ? void 0 : _props$collabEdit.useNativePlugin) === 'boolean' ? !!((_props$collabEdit2 = props.collabEdit) !== null && _props$collabEdit2 !== void 0 && _props$collabEdit2.useNativePlugin) : false),
39
- disableSpellcheckByBrowser: getSpellCheck(props.featureFlags)
31
+ showAvatarGroupAsPlugin: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.showAvatarGroupAsPlugin) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.showAvatarGroupAsPlugin) : false),
32
+ errorBoundaryDocStructure: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.useErrorBoundaryDocStructure) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.useErrorBoundaryDocStructure) : false),
33
+ synchronyErrorDocStructure: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.synchronyErrorDocStructure) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.synchronyErrorDocStructure) : false),
34
+ enableViewUpdateSubscription: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.enableViewUpdateSubscription) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.enableViewUpdateSubscription) : false),
35
+ collabAvatarScroll: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.collabAvatarScroll) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.collabAvatarScroll) : false),
36
+ twoLineEditorToolbar: Boolean(typeof (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.twoLineEditorToolbar) === 'boolean' ? !!(featureFlags !== null && featureFlags !== void 0 && featureFlags.twoLineEditorToolbar) : false),
37
+ disableSpellcheckByBrowser: getSpellCheck(featureFlags)
40
38
  });
41
39
  }