@atlaskit/editor-common 125.0.0 → 125.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cjs/element-browser/components/ElementBrowserLoader.js +31 -8
  3. package/dist/cjs/extensibility/Extension.js +4 -2
  4. package/dist/cjs/extensibility/ExtensionComponent.js +3 -1
  5. package/dist/cjs/extensibility/ExtensionNodeWrapper.js +3 -0
  6. package/dist/cjs/extensibility/GeneratedContentReveal.js +18 -20
  7. package/dist/cjs/extensibility/extensionNodeView.js +61 -24
  8. package/dist/cjs/extensions/extension-handlers.js +96 -17
  9. package/dist/cjs/floating-toolbar/DropdownMenuExtensionItems.js +25 -4
  10. package/dist/cjs/icons/index.js +33 -10
  11. package/dist/cjs/messages/find-replace.js +5 -0
  12. package/dist/cjs/monitoring/error.js +1 -1
  13. package/dist/cjs/quick-insert/assets/index.js +888 -257
  14. package/dist/cjs/ui/DropList/index.js +1 -1
  15. package/dist/cjs/ui/Mention/mention-with-profilecard.js +30 -11
  16. package/dist/es2019/element-browser/components/ElementBrowserLoader.js +16 -2
  17. package/dist/es2019/extensibility/Extension.js +4 -2
  18. package/dist/es2019/extensibility/ExtensionComponent.js +3 -1
  19. package/dist/es2019/extensibility/ExtensionNodeWrapper.js +2 -0
  20. package/dist/es2019/extensibility/GeneratedContentReveal.js +11 -16
  21. package/dist/es2019/extensibility/extensionNodeView.js +51 -23
  22. package/dist/es2019/extensions/extension-handlers.js +70 -15
  23. package/dist/es2019/floating-toolbar/DropdownMenuExtensionItems.js +16 -2
  24. package/dist/es2019/icons/index.js +17 -3
  25. package/dist/es2019/messages/find-replace.js +5 -0
  26. package/dist/es2019/monitoring/error.js +1 -1
  27. package/dist/es2019/quick-insert/assets/index.js +386 -66
  28. package/dist/es2019/ui/DropList/index.js +1 -1
  29. package/dist/es2019/ui/Mention/mention-with-profilecard.js +15 -4
  30. package/dist/esm/element-browser/components/ElementBrowserLoader.js +28 -6
  31. package/dist/esm/extensibility/Extension.js +4 -2
  32. package/dist/esm/extensibility/ExtensionComponent.js +3 -1
  33. package/dist/esm/extensibility/ExtensionNodeWrapper.js +3 -0
  34. package/dist/esm/extensibility/GeneratedContentReveal.js +18 -20
  35. package/dist/esm/extensibility/extensionNodeView.js +56 -23
  36. package/dist/esm/extensions/extension-handlers.js +97 -17
  37. package/dist/esm/floating-toolbar/DropdownMenuExtensionItems.js +24 -4
  38. package/dist/esm/icons/index.js +29 -7
  39. package/dist/esm/messages/find-replace.js +5 -0
  40. package/dist/esm/monitoring/error.js +1 -1
  41. package/dist/esm/quick-insert/assets/index.js +764 -194
  42. package/dist/esm/ui/DropList/index.js +1 -1
  43. package/dist/esm/ui/Mention/mention-with-profilecard.js +25 -8
  44. package/dist/types/analytics/types/ai-suggestions-events.d.ts +4 -6
  45. package/dist/types/analytics/types/find-replace-events.d.ts +2 -0
  46. package/dist/types/extensibility/Extension.d.ts +2 -0
  47. package/dist/types/extensibility/ExtensionComponent.d.ts +2 -0
  48. package/dist/types/extensibility/ExtensionNodeWrapper.d.ts +3 -1
  49. package/dist/types/extensibility/GeneratedContentReveal.d.ts +3 -1
  50. package/dist/types/extensibility/extensionNodeView.d.ts +13 -12
  51. package/dist/types/icons/index.d.ts +5 -3
  52. package/dist/types/messages/find-replace.d.ts +27 -22
  53. package/dist/types/quick-insert/assets/index.d.ts +34 -32
  54. package/package.json +5 -4
  55. package/dist/cjs/extensibility/useNativeEmbedSettled.js +0 -56
  56. package/dist/es2019/extensibility/useNativeEmbedSettled.js +0 -49
  57. package/dist/esm/extensibility/useNativeEmbedSettled.js +0 -51
  58. package/dist/types/extensibility/useNativeEmbedSettled.d.ts +0 -12
@@ -24,7 +24,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
24
24
  * @jsx jsx
25
25
  */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
26
26
  var packageName = "@atlaskit/editor-common";
27
- var packageVersion = "124.0.0";
27
+ var packageVersion = "125.1.0";
28
28
  var halfFocusRing = 1;
29
29
  var dropOffset = '0, 8';
30
30
  var fadeIn = (0, _react2.keyframes)({
@@ -8,6 +8,7 @@ exports.default = MentionWithProfileCard;
8
8
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _reactLoadable = _interopRequireDefault(require("react-loadable"));
11
+ var _reactLooselyLazy = require("react-loosely-lazy");
11
12
  var _resourcedMention = _interopRequireDefault(require("@atlaskit/mention/resourced-mention"));
12
13
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
13
14
  var _fg = require("@atlaskit/platform-feature-flags/fg");
@@ -15,24 +16,42 @@ var _anchor = require("@atlaskit/primitives/anchor");
15
16
  var _profileCardTrigger = _interopRequireDefault(require("@atlaskit/profilecard/profile-card-trigger"));
16
17
  var _navigateToTeamsApp2 = require("@atlaskit/teams-app-config/utils/teams-app-navigation/navigate-to-teams-app");
17
18
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
18
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != (0, _typeof2.default)(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } // eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- TODO: migrate to @atlaskit/primitives/compiled
19
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != (0, _typeof2.default)(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } // oxlint-disable-next-line @atlassian/no-restricted-imports
20
+ // eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- TODO: migrate to @atlaskit/primitives/compiled
19
21
  // Lazy-loaded so the agent profile card chunk (and its `@atlaskit/rovo-agent-components`
20
22
  // dependency) stays off the critical path — it is only fetched when an agent mention
21
23
  // (`userType === 'APP'`) actually renders, never for person mentions.
22
- // Uses react-loadable to match editor-common's code-splitting factory (see src/icons/index.ts).
23
- var AgentProfileCardTrigger = (0, _reactLoadable.default)({
24
- loader: function loader() {
25
- return Promise.resolve().then(function () {
26
- return _interopRequireWildcard(require( /* webpackChunkName: "@atlaskit-internal_profilecard/agent-profile-card-trigger" */
27
- '@atlaskit/profilecard/agent-profile-card-trigger'));
28
- }).then(function (mod) {
29
- return mod.AgentProfileCardTrigger;
30
- });
31
- },
24
+ var loadAgentProfileCardTrigger = function loadAgentProfileCardTrigger() {
25
+ return Promise.resolve().then(function () {
26
+ return _interopRequireWildcard(require( /* webpackChunkName: "@atlaskit-internal_profilecard/agent-profile-card-trigger" */
27
+ '@atlaskit/profilecard/agent-profile-card-trigger'));
28
+ }).then(function (mod) {
29
+ return mod.AgentProfileCardTrigger;
30
+ });
31
+ };
32
+ var AgentProfileCardTriggerLazy = (0, _reactLooselyLazy.lazy)(function () {
33
+ return Promise.resolve().then(function () {
34
+ return _interopRequireWildcard(require( /* webpackChunkName: "@atlaskit-internal_profilecard/agent-profile-card-trigger" */
35
+ '@atlaskit/profilecard/agent-profile-card-trigger'));
36
+ }).then(function (mod) {
37
+ return mod.AgentProfileCardTrigger;
38
+ });
39
+ });
40
+ AgentProfileCardTriggerLazy.displayName = 'lazy(AgentProfileCardTrigger)';
41
+ var AgentProfileCardTriggerLoadable = (0, _reactLoadable.default)({
42
+ loader: loadAgentProfileCardTrigger,
32
43
  loading: function loading() {
33
44
  return null;
34
45
  }
35
46
  });
47
+ var AgentProfileCardTrigger = function AgentProfileCardTrigger(props) {
48
+ return (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_loosely_lazy_migration') ? /*#__PURE__*/_react.default.createElement(_reactLooselyLazy.LazySuspense, {
49
+ fallback: null
50
+ }, /*#__PURE__*/_react.default.createElement(AgentProfileCardTriggerLazy, props)) :
51
+ /*#__PURE__*/
52
+ // eslint-disable-next-line react/jsx-props-no-spreading
53
+ _react.default.createElement(AgentProfileCardTriggerLoadable, props);
54
+ };
36
55
 
37
56
  // Ignored via go/ees005
38
57
  // eslint-disable-next-line require-unicode-regexp
@@ -7,6 +7,11 @@ import React from 'react';
7
7
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
8
8
  import { css, jsx } from '@emotion/react';
9
9
  import Loadable from 'react-loadable';
10
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
11
+ import { lazy, LazySuspense } from 'react-loosely-lazy';
12
+
13
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
14
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
10
15
  import Spinner from '@atlaskit/spinner/spinner';
11
16
  const spinnerContainer = css({
12
17
  display: 'flex',
@@ -15,8 +20,11 @@ const spinnerContainer = css({
15
20
  height: '100%',
16
21
  width: '100%'
17
22
  });
18
- const ElementBrowserLoader = Loadable({
19
- loader: () => import( /* webpackChunkName: "@atlaskit-internal_editor-element-browser" */'../ElementBrowser').then(module => module.default),
23
+ const loadElementBrowser = () => import( /* webpackChunkName: "@atlaskit-internal_editor-element-browser" */'../ElementBrowser').then(module => module.default);
24
+ const ElementBrowserLazy = lazy(() => import( /* webpackChunkName: "@atlaskit-internal_editor-element-browser" */'../ElementBrowser').then(module => module.default));
25
+ ElementBrowserLazy.displayName = 'lazy(ElementBrowser)';
26
+ const ElementBrowserLoadable = Loadable({
27
+ loader: loadElementBrowser,
20
28
  loading: () => jsx("div", {
21
29
  css: spinnerContainer
22
30
  }, jsx(Spinner, {
@@ -24,4 +32,10 @@ const ElementBrowserLoader = Loadable({
24
32
  interactionName: "element-browser-spinner"
25
33
  }))
26
34
  });
35
+ const ElementBrowserLoader = props => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? jsx(LazySuspense, {
36
+ fallback: null
37
+ }, jsx(ElementBrowserLazy, props)) :
38
+ // eslint-disable-next-line react/jsx-props-no-spreading
39
+ jsx(ElementBrowserLoadable, props);
40
+ ElementBrowserLoader.preload = () => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? ElementBrowserLazy.preload() : ElementBrowserLoadable.preload();
27
41
  export default ElementBrowserLoader;
@@ -25,7 +25,8 @@ export class Extension extends Component {
25
25
  macroInteractionDesignFeatureFlags,
26
26
  showLivePagesBodiedMacrosRendererView,
27
27
  showUpdatedLivePages1PBodiedExtensionUI,
28
- rendererExtensionHandlers
28
+ rendererExtensionHandlers,
29
+ onContentReady
29
30
  } = this.props;
30
31
 
31
32
  // Extensions are not yet using the new plugin architecture, and the use of the pluginInjectionApi
@@ -53,7 +54,8 @@ export class Extension extends Component {
53
54
  showLivePagesBodiedMacrosRendererView: showLivePagesBodiedMacrosRendererView,
54
55
  showUpdatedLivePages1PBodiedExtensionUI: showUpdatedLivePages1PBodiedExtensionUI,
55
56
  rendererExtensionHandlers: rendererExtensionHandlers,
56
- isLivePageViewMode: isLivePageViewMode
57
+ isLivePageViewMode: isLivePageViewMode,
58
+ onContentReady: onContentReady
57
59
  });
58
60
  });
59
61
  this.providerFactory = props.providerFactory || new ProviderFactory();
@@ -181,7 +181,8 @@ class ExtensionComponentInner extends Component {
181
181
  extensionLoadingHandlers,
182
182
  editorView,
183
183
  showBodiedExtensionRendererView,
184
- rendererExtensionHandlers
184
+ rendererExtensionHandlers,
185
+ onContentReady
185
186
  } = this.props;
186
187
  const {
187
188
  extensionType,
@@ -238,6 +239,7 @@ class ExtensionComponentInner extends Component {
238
239
  references: this.props.references,
239
240
  isSelected: isSelected,
240
241
  loadingFallback: loadingFallback,
242
+ onContentReady: onContentReady,
241
243
  showUnknownMacroPlaceholder: true
242
244
  });
243
245
  }
@@ -67,6 +67,7 @@ export const ExtensionNodeWrapper = ({
67
67
  nodeType,
68
68
  macroInteractionDesignFeatureFlags,
69
69
  generatedContentMotion = false,
70
+ contentReady = false,
70
71
  intl
71
72
  }) => {
72
73
  const {
@@ -76,6 +77,7 @@ export const ExtensionNodeWrapper = ({
76
77
  // Fixed for the node view's lifetime: switching would remount the subtree and reload the embed.
77
78
  if (generatedContentMotion) {
78
79
  return jsx(GeneratedContentReveal, {
80
+ contentReady: contentReady,
79
81
  intl: intl,
80
82
  showMacroInteractionDesignUpdates: showMacroInteractionDesignUpdates
81
83
  }, children);
@@ -3,14 +3,13 @@ import "./GeneratedContentReveal.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
4
  import React, { useCallback, useEffect, useState } from 'react';
5
5
  import { ExtensionSSRReactContextsProvider } from './ExtensionSSRReactContextsProvider';
6
- import { useNativeEmbedSettled } from './useNativeEmbedSettled';
7
6
 
8
7
  /*
9
8
  * Animates a native embed into the document once it has loaded.
10
9
  *
11
10
  * 1. `collapsed` — clipped to zero height and `inert`. The embed loads behind it, full size but
12
11
  * unseen, with its own loading overlay hidden.
13
- * 2. `useNativeEmbedSettled` calls back once the embed has finished loading.
12
+ * 2. The extension reports its content ready through `contentReady`.
14
13
  * 3. `revealing` — the node animates open to its content height (400ms).
15
14
  * 4. The embed fades in (200ms), delayed so it follows the opening instead of overlapping it.
16
15
  * 5. `open` — on `animationend`, when the content first becomes visible, `inert` is dropped.
@@ -55,32 +54,28 @@ const embedContentEnteringStyles = null;
55
54
 
56
55
  export const GeneratedContentReveal = ({
57
56
  children,
57
+ contentReady,
58
58
  intl,
59
59
  showMacroInteractionDesignUpdates
60
60
  }) => {
61
- // Held in state so the effects below run once the span exists.
61
+ // Held in state so the effect below runs once the span exists.
62
62
  const [wrapperElement, setWrapperElement] = useState(null);
63
- const [state, setState] = useState('collapsed');
63
+ const [readyTimedOut, setReadyTimedOut] = useState(false);
64
+ const [opened, setOpened] = useState(false);
64
65
 
65
- // Only a collapsed node opens, so whichever of the readiness signal and the fail-safe timer
66
- // comes second changes nothing.
67
- const startRevealing = useCallback(() => {
68
- setState(current => current === 'collapsed' ? 'revealing' : current);
69
- }, []);
70
-
71
- // Step 2 → 3.
72
- useNativeEmbedSettled(wrapperElement, startRevealing);
66
+ // Derived, so the two ways a node opens need no ordering between them.
67
+ const state = opened ? 'open' : contentReady || readyTimedOut ? 'revealing' : 'collapsed';
73
68
 
74
69
  // One timer, set on mount, so the deadline never moves.
75
70
  useEffect(() => {
76
- const timer = setTimeout(startRevealing, READY_TIMEOUT_MS);
71
+ const timer = setTimeout(() => setReadyTimedOut(true), READY_TIMEOUT_MS);
77
72
  return () => clearTimeout(timer);
78
- }, [startRevealing]);
73
+ }, []);
79
74
  useEffect(() => {
80
75
  if (state !== 'revealing') {
81
76
  return;
82
77
  }
83
- const timer = setTimeout(() => setState('open'), REVEAL_TIMEOUT_MS);
78
+ const timer = setTimeout(() => setOpened(true), REVEAL_TIMEOUT_MS);
84
79
  return () => clearTimeout(timer);
85
80
  }, [state]);
86
81
 
@@ -92,7 +87,7 @@ export const GeneratedContentReveal = ({
92
87
  const onAnimationEnd = useCallback(event => {
93
88
  // The extension's own content animates too, and those events bubble.
94
89
  if (event.target === event.currentTarget) {
95
- setState('open');
90
+ setOpened(true);
96
91
  }
97
92
  }, []);
98
93
  return /*#__PURE__*/React.createElement(ExtensionSSRReactContextsProvider, {
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- import React from 'react';
2
+ import React, { useCallback, useState } from 'react';
3
3
  import { fg } from '@atlaskit/platform-feature-flags/fg';
4
4
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
5
  import { isSSR } from '../core-utils';
@@ -264,22 +264,14 @@ export class ExtensionNode extends ReactNodeView {
264
264
  };
265
265
  }
266
266
  render(props, forwardRef) {
267
- var _props$extensionNodeV, _props$extensionNodeV2;
268
267
  // While sitting on SSR DOM, skip the React portal — see {@link didReuseSsrDom}.
269
268
  if (this.didReuseSsrDom) {
270
269
  return null;
271
270
  }
272
- return /*#__PURE__*/React.createElement(ExtensionNodeWrapper, {
273
- intl: props.intl,
274
- nodeType: this.node.type.name,
275
- macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags
276
- // Only native embeds animate in; the reveal waits on the embed's own loading state.
277
- ,
278
- generatedContentMotion: !!((_props$extensionNodeV = props.extensionNodeViewOptions) !== null && _props$extensionNodeV !== void 0 && _props$extensionNodeV.allowAIGeneratedContentMotion) && isNativeEmbedExtension(this.node)
279
- }, /*#__PURE__*/React.createElement(Extension, {
271
+ return /*#__PURE__*/React.createElement(ExtensionNodeRender, {
280
272
  editorView: this.view,
281
- node: this.node,
282
- eventDispatcher: this.eventDispatcher
273
+ eventDispatcher: this.eventDispatcher,
274
+ forwardRef: forwardRef
283
275
  // The getPos arg is always a function when used with nodes
284
276
  // the version of the types we use has a union with the type
285
277
  // for marks.
@@ -288,19 +280,55 @@ export class ExtensionNode extends ReactNodeView {
288
280
  // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57384
289
281
  ,
290
282
  getPos: this.getPos,
291
- providerFactory: props.providerFactory,
292
- handleContentDOMRef: forwardRef,
293
- extensionHandlers: props.extensionHandlers,
294
- extensionLoadingHandlers: props.extensionLoadingHandlers,
295
- editorAppearance: (_props$extensionNodeV2 = props.extensionNodeViewOptions) === null || _props$extensionNodeV2 === void 0 ? void 0 : _props$extensionNodeV2.appearance,
296
- pluginInjectionApi: props.pluginInjectionApi,
297
- macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags,
298
- showLivePagesBodiedMacrosRendererView: props.showLivePagesBodiedMacrosRendererView,
299
- showUpdatedLivePages1PBodiedExtensionUI: props.showUpdatedLivePages1PBodiedExtensionUI,
300
- rendererExtensionHandlers: props.rendererExtensionHandlers
301
- }));
283
+ node: this.node,
284
+ renderProps: props
285
+ });
302
286
  }
303
287
  }
288
+ /**
289
+ * Wraps the extension in its node wrapper. A component rather than part of the node view's `render`,
290
+ * so `contentReady` can be React state: the extension reports its content ready from inside the
291
+ * wrapper, and the wrapper animates the node in once it has.
292
+ */
293
+ function ExtensionNodeRender({
294
+ editorView,
295
+ eventDispatcher,
296
+ forwardRef,
297
+ getPos,
298
+ node,
299
+ renderProps
300
+ }) {
301
+ var _renderProps$extensio, _renderProps$extensio2;
302
+ const [contentReady, setContentReady] = useState(false);
303
+ const onContentReady = useCallback(() => setContentReady(true), []);
304
+
305
+ // Only native embeds animate in; every other extension type renders as it does without the
306
+ // option, so nothing waits on a signal it does not send.
307
+ const generatedContentMotion = !!((_renderProps$extensio = renderProps.extensionNodeViewOptions) !== null && _renderProps$extensio !== void 0 && _renderProps$extensio.allowAIGeneratedContentMotion) && isNativeEmbedExtension(node);
308
+ return /*#__PURE__*/React.createElement(ExtensionNodeWrapper, {
309
+ intl: renderProps.intl,
310
+ nodeType: node.type.name,
311
+ macroInteractionDesignFeatureFlags: renderProps.macroInteractionDesignFeatureFlags,
312
+ generatedContentMotion: generatedContentMotion,
313
+ contentReady: contentReady
314
+ }, /*#__PURE__*/React.createElement(Extension, {
315
+ editorView: editorView,
316
+ node: node,
317
+ eventDispatcher: eventDispatcher,
318
+ getPos: getPos,
319
+ providerFactory: renderProps.providerFactory,
320
+ handleContentDOMRef: forwardRef,
321
+ extensionHandlers: renderProps.extensionHandlers,
322
+ extensionLoadingHandlers: renderProps.extensionLoadingHandlers,
323
+ editorAppearance: (_renderProps$extensio2 = renderProps.extensionNodeViewOptions) === null || _renderProps$extensio2 === void 0 ? void 0 : _renderProps$extensio2.appearance,
324
+ pluginInjectionApi: renderProps.pluginInjectionApi,
325
+ macroInteractionDesignFeatureFlags: renderProps.macroInteractionDesignFeatureFlags,
326
+ showLivePagesBodiedMacrosRendererView: renderProps.showLivePagesBodiedMacrosRendererView,
327
+ showUpdatedLivePages1PBodiedExtensionUI: renderProps.showUpdatedLivePages1PBodiedExtensionUI,
328
+ rendererExtensionHandlers: renderProps.rendererExtensionHandlers,
329
+ onContentReady: generatedContentMotion ? onContentReady : undefined
330
+ }));
331
+ }
304
332
 
305
333
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
306
334
  export default function ExtensionNodeView(portalProviderAPI, eventDispatcher, providerFactory, extensionHandlers, extensionLoadingHandlers, extensionNodeViewOptions, pluginInjectionApi, macroInteractionDesignFeatureFlags, showLivePagesBodiedMacrosRendererView, showUpdatedLivePages1PBodiedExtensionUI, rendererExtensionHandlers, intl) {
@@ -1,6 +1,11 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
3
  import React from 'react';
2
4
  import { useIntl } from 'react-intl';
3
5
  import Loadable from 'react-loadable';
6
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
7
+ import { lazy, LazySuspense } from 'react-loosely-lazy';
8
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
4
9
  import { getExtensionKeyAndNodeKey, resolveImport } from './manifest-helpers';
5
10
  import { messages } from './messages';
6
11
  import { resolveImportSync } from './resolveImportSync';
@@ -59,6 +64,38 @@ function isUnknownConfluenceMacroWithBody(extensionNode) {
59
64
  var _extensionNode$parame, _extensionNode$parame2, _extensionNode$parame3;
60
65
  return extensionNode !== null && extensionNode.type === 'extension' && extensionNode.extensionType === 'com.atlassian.confluence.macro.core' && !!((_extensionNode$parame = extensionNode.parameters) !== null && _extensionNode$parame !== void 0 && (_extensionNode$parame2 = _extensionNode$parame.macroParams) !== null && _extensionNode$parame2 !== void 0 && (_extensionNode$parame3 = _extensionNode$parame2.__bodyContent) !== null && _extensionNode$parame3 !== void 0 && _extensionNode$parame3.value);
61
66
  }
67
+ // eslint-disable-next-line @repo/internal/react/no-class-components -- error boundaries require a class component
68
+ class ExtensionRendererErrorBoundary extends React.Component {
69
+ constructor(...args) {
70
+ super(...args);
71
+ _defineProperty(this, "state", {});
72
+ }
73
+ static getDerivedStateFromError(error) {
74
+ return {
75
+ error
76
+ };
77
+ }
78
+ componentDidCatch(error) {
79
+ // eslint-disable-next-line no-console
80
+ console.error('Error rendering extension', error);
81
+ }
82
+ render() {
83
+ return this.state.error ? renderExtensionLoadingError(this.state.error, this.props.fallbackProps) : this.props.children;
84
+ }
85
+ }
86
+ const noop = () => {};
87
+ function renderExtensionLoadingError(error, props) {
88
+ // Needed because the old react-loadable (older code-splitting library) error handling behaviour might be relied on by extensions.
89
+ // https://unpkg.com/react-loadable@5.2.2/lib/index.js
90
+ return /*#__PURE__*/React.createElement(ExtensionLoading, _extends({
91
+ isLoading: false,
92
+ pastDelay: true,
93
+ timedOut: false,
94
+ error: error,
95
+ retry: noop
96
+ // eslint-disable-next-line react/jsx-props-no-spreading
97
+ }, props));
98
+ }
62
99
  function ExtensionLoading(props) {
63
100
  const intl = useIntl();
64
101
  const extensionNode = props.node;
@@ -81,27 +118,45 @@ function ExtensionLoading(props) {
81
118
 
82
119
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
83
120
  export function getNodeRenderer(extensionProvider, extensionType, extensionKey) {
84
- return Loadable({
85
- loader: () => {
86
- const maybePromise = getExtensionModuleNodeMaybePreloaded(extensionProvider, extensionType, extensionKey);
87
- if (maybePromise instanceof Promise) {
88
- return maybePromise.then(node => resolveImport(node.render()));
89
- } else {
90
- var _renderSync, _ref;
91
- const preloaded = maybePromise === null || maybePromise === void 0 ? void 0 : (_renderSync = (_ref = maybePromise).renderSync) === null || _renderSync === void 0 ? void 0 : _renderSync.call(_ref);
92
- // Only product implemented preloading will return sync result
93
- // However the out-of-box won't handle this. Confluence uses a custom implementation
94
- return preloaded ?
95
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
- resolveImportSync(preloaded) : resolveImport(maybePromise.render());
97
- }
98
- },
121
+ const loadNodeRenderer = () => {
122
+ var _renderSync, _ref;
123
+ const maybePromise = getExtensionModuleNodeMaybePreloaded(extensionProvider, extensionType, extensionKey);
124
+ if (maybePromise instanceof Promise) {
125
+ return maybePromise.then(node => resolveImport(node.render()));
126
+ }
127
+ const preloaded = maybePromise === null || maybePromise === void 0 ? void 0 : (_renderSync = (_ref = maybePromise).renderSync) === null || _renderSync === void 0 ? void 0 : _renderSync.call(_ref);
128
+ // Only product implemented preloading will return sync result
129
+ // However the out-of-box won't handle this. Confluence uses a custom implementation
130
+ return preloaded ?
131
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
+ resolveImportSync(preloaded) : resolveImport(maybePromise.render());
133
+ };
134
+ const LazyNodeRenderer = lazy(() => loadNodeRenderer());
135
+ LazyNodeRenderer.displayName = 'lazy(NodeRenderer)';
136
+ // Ignored via go/ees005
137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ const LoadableNodeRenderer = Loadable({
139
+ loader: loadNodeRenderer,
99
140
  // react-loadable passes all props from <NodeRenderer> to the loading component at runtime,
100
141
  // but its TypeScript types only expect LoadingComponentProps. We cast here because
101
142
  // ExtensionLoading accepts additional props (node, showUnknownMacroPlaceholder) that
102
143
  // react-loadable will pass through but doesn't know about in its type definitions.
103
144
  loading: ExtensionLoading
104
145
  });
146
+ const NodeRenderer = props => {
147
+ var _props$loadingFallbac;
148
+ if (!isExperimentEnabled('platform_editor_loosely_lazy_migration')) {
149
+ // eslint-disable-next-line react/jsx-props-no-spreading
150
+ return /*#__PURE__*/React.createElement(LoadableNodeRenderer, props);
151
+ }
152
+ return /*#__PURE__*/React.createElement(ExtensionRendererErrorBoundary, {
153
+ fallbackProps: props
154
+ }, /*#__PURE__*/React.createElement(LazySuspense, {
155
+ fallback: (_props$loadingFallbac = props.loadingFallback) !== null && _props$loadingFallbac !== void 0 ? _props$loadingFallbac : null
156
+ }, /*#__PURE__*/React.createElement(LazyNodeRenderer, props)));
157
+ };
158
+ NodeRenderer.preload = () => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? LazyNodeRenderer.preload() : LoadableNodeRenderer.preload();
159
+ return NodeRenderer;
105
160
  }
106
161
  // eslint-disable-next-line @atlaskit/editor/no-re-export
107
162
  export { getExtensionManifest } from './getExtensionManifest';
@@ -1,5 +1,8 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import Loadable from 'react-loadable';
3
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
4
+ import { lazy, LazySuspense } from 'react-loosely-lazy';
5
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
3
6
  import { getContextualToolbarItemsFromModule } from '../extensions';
4
7
  import { nodeToJSON } from '../utils';
5
8
  import { DropdownMenuItem } from './DropdownMenuItem';
@@ -62,10 +65,21 @@ const DropdownMenuExtensionItem = ({
62
65
  // Use ref to keep icon component stable across renders
63
66
  const iconRef = useRef(null);
64
67
  if (!iconRef.current && item.icon) {
65
- iconRef.current = Loadable({
66
- loader: () => resolveExtensionIcon(item.icon),
68
+ const loadIcon = () => resolveExtensionIcon(item.icon);
69
+ const IconLazy = lazy(() => resolveExtensionIcon(item.icon));
70
+ IconLazy.displayName = 'lazy(ExtensionIcon)';
71
+ const IconLoadable = Loadable({
72
+ loader: loadIcon,
67
73
  loading: noop
68
74
  });
75
+ const Icon = props => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? /*#__PURE__*/React.createElement(LazySuspense, {
76
+ fallback: null
77
+ }, /*#__PURE__*/React.createElement(IconLazy, props)) :
78
+ /*#__PURE__*/
79
+ // eslint-disable-next-line react/jsx-props-no-spreading -- pass icon props to the legacy component
80
+ React.createElement(IconLoadable, props);
81
+ Icon.preload = () => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? IconLazy.preload() : IconLoadable.preload();
82
+ iconRef.current = Icon;
69
83
  }
70
84
  const dropdownItem = convertExtensionToDropdownMenuItem({
71
85
  item,
@@ -1,7 +1,11 @@
1
1
  // Disable no-re-export rule for entry point files
2
2
  /* eslint-disable @atlaskit/editor/no-re-export */
3
3
 
4
+ import React from 'react';
4
5
  import Loadable from 'react-loadable';
6
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
7
+ import { lazy, LazySuspense } from 'react-loosely-lazy';
8
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
5
9
  export { PanelInfoIcon } from './shared/PanelInfoIcon';
6
10
  export { PanelWarningIcon } from './shared/PanelWarningIcon';
7
11
  export { PanelErrorIcon } from './shared/PanelErrorIcon';
@@ -10,7 +14,17 @@ export { PanelNoteIcon } from './shared/PanelNoteIcon';
10
14
  export { BorderIcon } from './shared/BorderIcon';
11
15
  export { SteppedRainbowIconDecoration, rainbow, disabledRainbow } from './shared/SteppedRainbowIconDecoration';
12
16
  export { DynamicStrokeIconDecoration } from './shared/DynamicStrokeIconDecoration';
13
- export const IconTable = Loadable({
14
- loader: () => import( /* webpackChunkName: "@atlaskit-internal_editor-icon-table" */'../icons/shared/table').then(module => module.default),
17
+ const loadIconTable = () => import( /* webpackChunkName: "@atlaskit-internal_editor-icon-table" */'../icons/shared/table').then(module => module.default);
18
+ const IconTableLazy = lazy(() => import( /* webpackChunkName: "@atlaskit-internal_editor-icon-table" */'../icons/shared/table').then(module => module.default));
19
+ IconTableLazy.displayName = 'lazy(IconTable)';
20
+ const IconTableLoadable = Loadable({
21
+ loader: loadIconTable,
15
22
  loading: () => null
16
- });
23
+ });
24
+ export const IconTable = props => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? /*#__PURE__*/React.createElement(LazySuspense, {
25
+ fallback: null
26
+ }, /*#__PURE__*/React.createElement(IconTableLazy, props)) :
27
+ /*#__PURE__*/
28
+ // eslint-disable-next-line react/jsx-props-no-spreading -- pass icon props to the legacy component
29
+ React.createElement(IconTableLoadable, props);
30
+ IconTable.preload = () => isExperimentEnabled('platform_editor_loosely_lazy_migration') ? IconTableLazy.preload() : IconTableLoadable.preload();
@@ -25,6 +25,11 @@ export const findReplaceMessages = defineMessages({
25
25
  defaultMessage: 'Find and Replace',
26
26
  description: 'Aria label for the "Find and Replace" dialog'
27
27
  },
28
+ findDialogAriaLabel: {
29
+ id: 'fabric.editor.findDialogAriaLabel',
30
+ defaultMessage: 'Find',
31
+ description: 'Aria label for the "Find" dialog, used where the dialog offers find without replace'
32
+ },
28
33
  closeFindReplaceDialog: {
29
34
  id: 'fabric.editor.closeFindReplaceDialog',
30
35
  defaultMessage: 'Close',
@@ -13,7 +13,7 @@ const NETWORK_FAILURE_REGEX = /^network failure/i;
13
13
  const RESIZE_OBSERVER_LOOP_REGEX = /ResizeObserver loop completed with undelivered notifications/;
14
14
  const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
15
15
  const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
16
- const packageVersion = "124.0.0";
16
+ const packageVersion = "125.1.0";
17
17
  const sanitiseSentryEvents = (data, _hint) => {
18
18
  // Remove URL as it has UGC
19
19
  // Ignored via go/ees007