@atlaskit/editor-plugin-card 35.0.1 → 35.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cjs/actions/cardRegistry.js +65 -0
  3. package/dist/cjs/actions/useCardRegistry.js +19 -0
  4. package/dist/cjs/cardPlugin.js +6 -0
  5. package/dist/cjs/nodeviews/blockCard.js +45 -21
  6. package/dist/cjs/nodeviews/embedCard.js +50 -26
  7. package/dist/cjs/nodeviews/inlineCardBase.js +41 -20
  8. package/dist/cjs/nodeviews/inlineCardWithAwareness.js +14 -10
  9. package/dist/cjs/pm-plugins/doc.js +1 -1
  10. package/dist/cjs/pm-plugins/main.js +11 -9
  11. package/dist/cjs/pm-plugins/utils.js +19 -7
  12. package/dist/cjs/ui/EditLinkToolbar.js +5 -3
  13. package/dist/cjs/ui/PasteDisplayAsMenu.js +15 -4
  14. package/dist/cjs/ui/toolbar.js +37 -21
  15. package/dist/es2019/actions/cardRegistry.js +58 -0
  16. package/dist/es2019/actions/useCardRegistry.js +9 -0
  17. package/dist/es2019/cardPlugin.js +6 -0
  18. package/dist/es2019/nodeviews/blockCard.js +42 -16
  19. package/dist/es2019/nodeviews/embedCard.js +42 -16
  20. package/dist/es2019/nodeviews/inlineCardBase.js +43 -22
  21. package/dist/es2019/nodeviews/inlineCardWithAwareness.js +12 -8
  22. package/dist/es2019/pm-plugins/doc.js +1 -1
  23. package/dist/es2019/pm-plugins/main.js +11 -9
  24. package/dist/es2019/pm-plugins/utils.js +15 -5
  25. package/dist/es2019/ui/EditLinkToolbar.js +5 -3
  26. package/dist/es2019/ui/PasteDisplayAsMenu.js +11 -4
  27. package/dist/es2019/ui/toolbar.js +35 -19
  28. package/dist/esm/actions/cardRegistry.js +58 -0
  29. package/dist/esm/actions/useCardRegistry.js +13 -0
  30. package/dist/esm/cardPlugin.js +6 -0
  31. package/dist/esm/nodeviews/blockCard.js +45 -21
  32. package/dist/esm/nodeviews/embedCard.js +50 -26
  33. package/dist/esm/nodeviews/inlineCardBase.js +41 -20
  34. package/dist/esm/nodeviews/inlineCardWithAwareness.js +14 -10
  35. package/dist/esm/pm-plugins/doc.js +1 -1
  36. package/dist/esm/pm-plugins/main.js +11 -9
  37. package/dist/esm/pm-plugins/utils.js +19 -7
  38. package/dist/esm/ui/EditLinkToolbar.js +5 -3
  39. package/dist/esm/ui/PasteDisplayAsMenu.js +15 -4
  40. package/dist/esm/ui/toolbar.js +37 -21
  41. package/dist/types/actions/cardRegistry.d.ts +37 -0
  42. package/dist/types/actions/useCardRegistry.d.ts +3 -0
  43. package/dist/types/nodeviews/blockCard.d.ts +2 -2
  44. package/dist/types/nodeviews/embedCard.d.ts +2 -2
  45. package/dist/types/nodeviews/genericCard.d.ts +2 -4
  46. package/dist/types/pm-plugins/utils.d.ts +2 -1
  47. package/package.json +8 -5
@@ -20,10 +20,13 @@ import SmartLinkCardIcon from '@atlaskit/icon/core/smart-link-card';
20
20
  import SmartLinkEmbedIcon from '@atlaskit/icon/core/smart-link-embed';
21
21
  import SmartLinkInlineIcon from '@atlaskit/icon/core/smart-link-inline';
22
22
  import { useSmartCardContext } from '@atlaskit/link-provider/use-smart-card-context';
23
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
24
+ import { conditionalHooksFactory } from '@atlaskit/platform-feature-flags-react/conditional-hooks-factory/conditional-hooks-factory';
23
25
  import { Box } from '@atlaskit/primitives/compiled/box';
24
26
  import { Flex } from '@atlaskit/primitives/compiled/flex';
25
27
  import { Pressable } from '@atlaskit/primitives/compiled/pressable';
26
28
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
29
+ import { useCardRegistry } from '../actions/useCardRegistry';
27
30
  import { changeSelectedCardToLink, setSelectedCardAppearance } from '../pm-plugins/doc';
28
31
  import { getSingleSmartLinkUrlFromSlice } from './currentPastedSmartLink';
29
32
  import { changeNativeEmbedAppearance, getNativeEmbedUrl, isNativeEmbedAppearanceSupported } from './nativeEmbedNode';
@@ -198,6 +201,13 @@ export const normalizeSelectionToLinkRangeForUrlAppearance = ({
198
201
  const linkRangeSelectionTr = editorView.state.tr.setSelection(TextSelection.create(editorView.state.doc, firstLinkRange.from, firstLinkRange.to));
199
202
  editorView.dispatch(linkRangeSelectionTr);
200
203
  };
204
+ // Remove with platform_editor_reduce_forced_layout_2 cleanup; call useCardRegistry(api?.card?.actions) directly.
205
+ const useCardState = conditionalHooksFactory(() => isExperimentEnabled('platform_editor_reduce_forced_layout_2'), function useRegisteredCardState(api) {
206
+ var _api$card;
207
+ return useCardRegistry(api === null || api === void 0 ? void 0 : (_api$card = api.card) === null || _api$card === void 0 ? void 0 : _api$card.actions);
208
+ }, function useLegacyCardState(api) {
209
+ return useSharedPluginStateWithSelector(api, ['card'], states => states.cardState);
210
+ });
201
211
  const PasteDisplayAsMenuHorizontalView = ({
202
212
  api,
203
213
  allowBlockCards,
@@ -220,10 +230,7 @@ const PasteDisplayAsMenuHorizontalView = ({
220
230
  pasteStartPos: pluginState.pasteStartPos
221
231
  } : undefined;
222
232
  });
223
- // Subscribe to card state so the menu re-renders when resolved card metadata updates.
224
- useSharedPluginStateWithSelector(api, ['card'], states => {
225
- return states.cardState;
226
- });
233
+ useCardState(api);
227
234
  const pastedLinkUrlFromSlice = getSingleSmartLinkUrlFromSlice(getCurrentPastedSlice(api));
228
235
  const pastedLinkUrlFromCard = editorView && pasteRange ? getCardUrlAtPasteRange({
229
236
  editorView,
@@ -25,6 +25,7 @@ import EditIcon from '@atlaskit/icon/core/edit';
25
25
  import LinkBrokenIcon from '@atlaskit/icon/core/link-broken';
26
26
  import LinkExternalIcon from '@atlaskit/icon/core/link-external';
27
27
  import CogIcon from '@atlaskit/icon/core/settings';
28
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
28
29
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
29
30
  import { changeSelectedCardToText } from '../pm-plugins/doc';
30
31
  import { pluginKey } from '../pm-plugins/plugin-key';
@@ -121,6 +122,7 @@ export const openLinkSettings = editorAnalyticsApi => (state, dispatch) => {
121
122
  };
122
123
  export const floatingToolbar = (cardOptions, lpLinkPicker, linkPickerOptions, pluginInjectionApi, disableFloatingToolbar) => {
123
124
  return (state, intl, providerFactory) => {
125
+ var _pluginInjectionApi$c;
124
126
  if (disableFloatingToolbar) {
125
127
  return;
126
128
  }
@@ -150,6 +152,10 @@ export const floatingToolbar = (cardOptions, lpLinkPicker, linkPickerOptions, pl
150
152
  const isLinkPickerEnabled = !!lpLinkPicker;
151
153
  return {
152
154
  title: intl.formatMessage(messages.card),
155
+ externalStore: isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c = pluginInjectionApi.card) === null || _pluginInjectionApi$c === void 0 ? void 0 : _pluginInjectionApi$c.actions) && {
156
+ getSnapshot: pluginInjectionApi.card.actions.getCardRegistrations,
157
+ subscribe: pluginInjectionApi.card.actions.subscribeToCardRegistry
158
+ } : undefined,
153
159
  className,
154
160
  nodeType,
155
161
  preventPopupOverflow: isLinkPickerEnabled,
@@ -182,15 +188,25 @@ export const floatingToolbar = (cardOptions, lpLinkPicker, linkPickerOptions, pl
182
188
  };
183
189
  };
184
190
  };
185
- const unlinkCard = (node, state, editorAnalyticsApi) => {
186
- const displayInfo = displayInfoForCard(node, findCardInfo(state));
187
- const text = displayInfo.title || displayInfo.url;
188
- if (text) {
189
- return commandWithMetadata(changeSelectedCardToText(text, editorAnalyticsApi), {
190
- action: ACTION.UNLINK
191
- });
191
+ const unlinkCard = (node, state, editorAnalyticsApi, pluginInjectionApi) => {
192
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
193
+ return (currentState, dispatch, view) => {
194
+ const displayInfo = displayInfoForCard(node, findCardInfo(currentState, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.card.actions));
195
+ const text = displayInfo.title || displayInfo.url;
196
+ return text ? commandWithMetadata(changeSelectedCardToText(text, editorAnalyticsApi), {
197
+ action: ACTION.UNLINK
198
+ })(currentState, dispatch, view) : false;
199
+ };
200
+ } else {
201
+ const displayInfo = displayInfoForCard(node, findCardInfo(state, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.card.actions));
202
+ const text = displayInfo.title || displayInfo.url;
203
+ if (text) {
204
+ return commandWithMetadata(changeSelectedCardToText(text, editorAnalyticsApi), {
205
+ action: ACTION.UNLINK
206
+ });
207
+ }
208
+ return () => false;
192
209
  }
193
- return () => false;
194
210
  };
195
211
  const buildAlignmentOptions = (state, intl, widthPluginDependencyApi, analyticsApi, cardOptions, areAnyNewToolbarFlagsEnabled) => {
196
212
  if (areAnyNewToolbarFlagsEnabled) {
@@ -230,7 +246,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
230
246
  } else {
231
247
  const {
232
248
  title
233
- } = displayInfoForCard(node, findCardInfo(state));
249
+ } = displayInfoForCard(node, findCardInfo(state, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.card.actions));
234
250
  metadata = {
235
251
  url: url,
236
252
  title: title
@@ -280,7 +296,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
280
296
  } else if (shouldRenderDatasourceToolbar) {
281
297
  return getDatasourceButtonGroup(metadata, intl, editorAnalyticsApi, node, hoverDecoration, node.attrs.datasource.id, state, cardOptions, currentAppearance, pluginInjectionApi);
282
298
  } else {
283
- var _pluginInjectionApi$c, _pluginInjectionApi$c2, _pluginInjectionApi$c3, _pluginState$resolved;
299
+ var _pluginInjectionApi$c2, _pluginInjectionApi$c3, _pluginInjectionApi$c4, _pluginState$resolved;
284
300
  const {
285
301
  inlineCard
286
302
  } = state.schema.nodes;
@@ -318,7 +334,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
318
334
  title: intl.formatMessage(annotationMessages.createComment),
319
335
  showTitle: editorExperiment('platform_editor_controls', 'control') ? undefined : true,
320
336
  onClick: onCommentButtonClick,
321
- disabled: isOfflineMode(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c = pluginInjectionApi.connectivity) === null || _pluginInjectionApi$c === void 0 ? void 0 : (_pluginInjectionApi$c2 = _pluginInjectionApi$c.sharedState) === null || _pluginInjectionApi$c2 === void 0 ? void 0 : (_pluginInjectionApi$c3 = _pluginInjectionApi$c2.currentState()) === null || _pluginInjectionApi$c3 === void 0 ? void 0 : _pluginInjectionApi$c3.mode)
337
+ disabled: isOfflineMode(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c2 = pluginInjectionApi.connectivity) === null || _pluginInjectionApi$c2 === void 0 ? void 0 : (_pluginInjectionApi$c3 = _pluginInjectionApi$c2.sharedState) === null || _pluginInjectionApi$c3 === void 0 ? void 0 : (_pluginInjectionApi$c4 = _pluginInjectionApi$c3.currentState()) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.mode)
322
338
  }, {
323
339
  type: 'separator'
324
340
  }] : [];
@@ -382,7 +398,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
382
398
  };
383
399
  const toolbarItems = areAllNewToolbarFlagsDisabled ? [...editItems, ...commentItems, ...openPreviewPanelItems, openLinkToolbarItem, {
384
400
  type: 'separator'
385
- }, ...getUnlinkButtonGroup(state, intl, node, inlineCard, editorAnalyticsApi, !areAllNewToolbarFlagsDisabled), {
401
+ }, ...getUnlinkButtonGroup(state, intl, node, inlineCard, editorAnalyticsApi, !areAllNewToolbarFlagsDisabled, pluginInjectionApi), {
386
402
  type: 'copy-button',
387
403
  items: [{
388
404
  state,
@@ -406,7 +422,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
406
422
  onBlur: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, false),
407
423
  title: intl.formatMessage(commonMessages.remove),
408
424
  onClick: withToolbarMetadata(removeCard(editorAnalyticsApi))
409
- }] : [...editButtonItems, ...[...getUnlinkButtonGroup(state, intl, node, inlineCard, editorAnalyticsApi, !areAllNewToolbarFlagsDisabled), {
425
+ }] : [...editButtonItems, ...[...getUnlinkButtonGroup(state, intl, node, inlineCard, editorAnalyticsApi, !areAllNewToolbarFlagsDisabled, pluginInjectionApi), {
410
426
  type: 'separator',
411
427
  fullHeight: true
412
428
  }], ...openPreviewPanelItems, openLinkToolbarItem, ...(commentItems.length > 1 ? [{
@@ -497,8 +513,8 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
497
513
  options: [{
498
514
  title: intl.formatMessage(commonMessages.copyToClipboard),
499
515
  onClick: () => {
500
- var _pluginInjectionApi$c4, _pluginInjectionApi$f;
501
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c4 = pluginInjectionApi.core) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f = pluginInjectionApi.floatingToolbar) === null || _pluginInjectionApi$f === void 0 ? void 0 : _pluginInjectionApi$f.commands.copyNode(node.type, INPUT_METHOD.FLOATING_TB));
516
+ var _pluginInjectionApi$c5, _pluginInjectionApi$f;
517
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c5 = pluginInjectionApi.core) === null || _pluginInjectionApi$c5 === void 0 ? void 0 : _pluginInjectionApi$c5.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f = pluginInjectionApi.floatingToolbar) === null || _pluginInjectionApi$f === void 0 ? void 0 : _pluginInjectionApi$f.commands.copyNode(node.type, INPUT_METHOD.FLOATING_TB));
502
518
  return true;
503
519
  },
504
520
  icon: /*#__PURE__*/React.createElement(CopyIcon, {
@@ -519,7 +535,7 @@ const generateToolbarItems = (state, intl, providerFactory, cardOptions, lpLinkP
519
535
  return toolbarItems;
520
536
  }
521
537
  };
522
- const getUnlinkButtonGroup = (state, intl, node, inlineCard, editorAnalyticsApi, areAnyNewToolbarFlagsEnabled) => {
538
+ const getUnlinkButtonGroup = (state, intl, node, inlineCard, editorAnalyticsApi, areAnyNewToolbarFlagsEnabled, pluginInjectionApi) => {
523
539
  return node.type === inlineCard ? [{
524
540
  id: 'editor.link.unlink',
525
541
  focusEditoronEnter: true,
@@ -527,7 +543,7 @@ const getUnlinkButtonGroup = (state, intl, node, inlineCard, editorAnalyticsApi,
527
543
  title: intl.formatMessage(linkToolbarMessages.unlink),
528
544
  icon: LinkBrokenIcon,
529
545
  iconFallback: LinkBrokenIcon,
530
- onClick: withToolbarMetadata(unlinkCard(node, state, editorAnalyticsApi))
546
+ onClick: withToolbarMetadata(unlinkCard(node, state, editorAnalyticsApi, pluginInjectionApi))
531
547
  }, ...(areAnyNewToolbarFlagsEnabled ? [] : [{
532
548
  type: 'separator'
533
549
  }])] : [];
@@ -727,8 +743,8 @@ const getDatasourceButtonGroup = (metadata, intl, editorAnalyticsApi, node, hove
727
743
  options: [{
728
744
  title: intl.formatMessage(commonMessages.copyToClipboard),
729
745
  onClick: () => {
730
- var _pluginInjectionApi$c5, _pluginInjectionApi$f2;
731
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c5 = pluginInjectionApi.core) === null || _pluginInjectionApi$c5 === void 0 ? void 0 : _pluginInjectionApi$c5.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f2 = pluginInjectionApi.floatingToolbar) === null || _pluginInjectionApi$f2 === void 0 ? void 0 : _pluginInjectionApi$f2.commands.copyNode(node.type, INPUT_METHOD.FLOATING_TB));
746
+ var _pluginInjectionApi$c6, _pluginInjectionApi$f2;
747
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c6 = pluginInjectionApi.core) === null || _pluginInjectionApi$c6 === void 0 ? void 0 : _pluginInjectionApi$c6.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$f2 = pluginInjectionApi.floatingToolbar) === null || _pluginInjectionApi$f2 === void 0 ? void 0 : _pluginInjectionApi$f2.commands.copyNode(node.type, INPUT_METHOD.FLOATING_TB));
732
748
  return true;
733
749
  },
734
750
  onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(node.type, true, akEditorSelectedNodeClassName),
@@ -0,0 +1,58 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ 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; }
3
+ 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; }
4
+ /**
5
+ * Creates a registry of resolved cards, for use with editor actions.
6
+ * Registration changes (insertion, deletion, and id/title/url updates) notify subscribers; live position changes do not.
7
+ *
8
+ * @returns A registry object with the following methods:
9
+ * - `getCardRegistrations`: Returns the current registrations, keyed by card ID.
10
+ * - `registerCard`: Adds or updates a card.
11
+ * - `removeCard`: Removes a card by ID.
12
+ * - `subscribe`: Registers a change listener and returns an unsubscribe function.
13
+ */
14
+ export var createCardRegistry = function createCardRegistry() {
15
+ // Replace registrations on each change to notify subscribers and trigger React updates.
16
+ var registrations = {};
17
+ var listeners = new Set();
18
+ var getCardRegistrations = function getCardRegistrations() {
19
+ return registrations;
20
+ };
21
+ var notify = function notify() {
22
+ Array.from(listeners).forEach(function (listener) {
23
+ return listener();
24
+ });
25
+ };
26
+ var registerCard = function registerCard(info) {
27
+ if (info.getPos() === undefined) {
28
+ return;
29
+ }
30
+ var previous = registrations[info.id];
31
+ if (previous && previous.getPos === info.getPos && previous.title === info.title && previous.url === info.url) {
32
+ return; // Don't mutate registrations if no change
33
+ }
34
+ registrations = _objectSpread(_objectSpread({}, registrations), {}, _defineProperty({}, info.id, _objectSpread({}, info)));
35
+ notify();
36
+ };
37
+ var removeCard = function removeCard(id) {
38
+ if (!registrations[id]) {
39
+ return;
40
+ }
41
+ var next = _objectSpread({}, registrations);
42
+ delete next[id];
43
+ registrations = next;
44
+ notify();
45
+ };
46
+ var subscribe = function subscribe(listener) {
47
+ listeners.add(listener);
48
+ return function () {
49
+ listeners.delete(listener);
50
+ };
51
+ };
52
+ return {
53
+ registerCard: registerCard,
54
+ removeCard: removeCard,
55
+ subscribe: subscribe,
56
+ getCardRegistrations: getCardRegistrations
57
+ };
58
+ };
@@ -0,0 +1,13 @@
1
+ import { useSyncExternalStore } from 'react';
2
+ var emptySnapshot = function emptySnapshot() {
3
+ return undefined;
4
+ };
5
+ var emptySubscription = function emptySubscription() {
6
+ return function () {};
7
+ };
8
+
9
+ /** Subscribe to resolved card metadata without observing every editor transaction. */
10
+ export var useCardRegistry = function useCardRegistry(actions) {
11
+ var _actions$subscribeToC, _actions$getCardRegis;
12
+ return useSyncExternalStore((_actions$subscribeToC = actions === null || actions === void 0 ? void 0 : actions.subscribeToCardRegistry) !== null && _actions$subscribeToC !== void 0 ? _actions$subscribeToC : emptySubscription, (_actions$getCardRegis = actions === null || actions === void 0 ? void 0 : actions.getCardRegistrations) !== null && _actions$getCardRegis !== void 0 ? _actions$getCardRegis : emptySnapshot, emptySnapshot);
13
+ };
@@ -14,6 +14,7 @@ import { SmartCardContext } from '@atlaskit/link-provider/context';
14
14
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
15
15
  import { fg } from '@atlaskit/platform-feature-flags/fg';
16
16
  import { expValNoExposure } from '@atlaskit/tmp-editor-statsig/expVal';
17
+ import { createCardRegistry } from './actions/cardRegistry';
17
18
  import { blockCardSpecWithFixedToDOM } from './nodeviews/toDOM-fixes/blockCard';
18
19
  import { embedCardSpecWithFixedToDOM } from './nodeviews/toDOM-fixes/embedCard';
19
20
  import { inlineCardSpecWithFixedToDOM } from './nodeviews/toDOM-fixes/inlineCard';
@@ -49,6 +50,7 @@ export var cardPlugin = function cardPlugin(_ref2) {
49
50
  var _ref2$config = _ref2.config,
50
51
  options = _ref2$config === void 0 ? {} : _ref2$config,
51
52
  api = _ref2.api;
53
+ var cardRegistry = createCardRegistry();
52
54
  var previousCardProvider;
53
55
  var cardPluginEvents = createEventsQueue();
54
56
  var isRegisteredSlashCommandEnabled = isExperimentEnabled('platform_editor_slash_command');
@@ -207,6 +209,10 @@ export var cardPlugin = function cardPlugin(_ref2) {
207
209
  }
208
210
  },
209
211
  actions: {
212
+ registerCard: cardRegistry.registerCard,
213
+ removeRegisteredCard: cardRegistry.removeCard,
214
+ getCardRegistrations: cardRegistry.getCardRegistrations,
215
+ subscribeToCardRegistry: cardRegistry.subscribe,
210
216
  setProvider: function () {
211
217
  var _setProvider2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(providerPromise) {
212
218
  var _api$core$actions$exe;
@@ -47,16 +47,32 @@ export var BlockCardComponent = /*#__PURE__*/function (_React$PureComponent) {
47
47
  // don't dispatch immediately since we might be in the middle of
48
48
  // rendering a nodeview
49
49
  var scheduleRegisterCard = rafSchedule(function () {
50
- var pos = getPos();
51
- if (typeof pos !== 'number') {
52
- return;
50
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
51
+ var _pluginInjectionApi$c;
52
+ if (_this.removeCardDispatched || getPos() === undefined) {
53
+ return;
54
+ }
55
+ var _this$props2 = _this.props,
56
+ pluginInjectionApi = _this$props2.pluginInjectionApi,
57
+ id = _this$props2.id;
58
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c = pluginInjectionApi.card.actions) === null || _pluginInjectionApi$c === void 0 || _pluginInjectionApi$c.registerCard({
59
+ id: id,
60
+ title: title,
61
+ url: url,
62
+ getPos: getPos
63
+ });
64
+ } else {
65
+ var pos = getPos();
66
+ if (typeof pos !== 'number') {
67
+ return;
68
+ }
69
+ view.dispatch(registerCard({
70
+ title: title,
71
+ url: url,
72
+ pos: pos,
73
+ id: _this.props.id
74
+ })(view.state.tr));
53
75
  }
54
- view.dispatch(registerCard({
55
- title: title,
56
- url: url,
57
- pos: pos,
58
- id: _this.props.id
59
- })(view.state.tr));
60
76
  });
61
77
  if (isExperimentEnabled('platform_editor_reduce_memory_leaks')) {
62
78
  _this.pendingRegisterCard = scheduleRegisterCard;
@@ -107,22 +123,30 @@ export var BlockCardComponent = /*#__PURE__*/function (_React$PureComponent) {
107
123
  return;
108
124
  }
109
125
  this.removeCardDispatched = true;
110
- var tr = this.props.view.state.tr;
111
- _removeCard({
112
- id: this.props.id
113
- })(tr);
114
- this.props.view.dispatch(tr);
126
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
127
+ var _pluginInjectionApi$c2;
128
+ var _this$props3 = this.props,
129
+ pluginInjectionApi = _this$props3.pluginInjectionApi,
130
+ id = _this$props3.id;
131
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c2 = pluginInjectionApi.card.actions) === null || _pluginInjectionApi$c2 === void 0 || _pluginInjectionApi$c2.removeRegisteredCard(id);
132
+ } else {
133
+ var tr = this.props.view.state.tr;
134
+ _removeCard({
135
+ id: this.props.id
136
+ })(tr);
137
+ this.props.view.dispatch(tr);
138
+ }
115
139
  }
116
140
  }, {
117
141
  key: "render",
118
142
  value: function render() {
119
- var _this$props2 = this.props,
120
- node = _this$props2.node,
121
- cardContext = _this$props2.cardContext,
122
- actionOptions = _this$props2.actionOptions,
123
- onClick = _this$props2.onClick,
124
- CompetitorPrompt = _this$props2.CompetitorPrompt,
125
- isPageSSRed = _this$props2.isPageSSRed;
143
+ var _this$props4 = this.props,
144
+ node = _this$props4.node,
145
+ cardContext = _this$props4.cardContext,
146
+ actionOptions = _this$props4.actionOptions,
147
+ onClick = _this$props4.onClick,
148
+ CompetitorPrompt = _this$props4.CompetitorPrompt,
149
+ isPageSSRed = _this$props4.isPageSSRed;
126
150
  var _node$attrs = node.attrs,
127
151
  url = _node$attrs.url,
128
152
  data = _node$attrs.data;
@@ -182,16 +182,32 @@ export var EmbedCardComponent = /*#__PURE__*/function (_React$PureComponent) {
182
182
  // don't dispatch immediately since we might be in the middle of
183
183
  // rendering a nodeview
184
184
  rafSchedule(function () {
185
- var pos = _this.getPosSafely();
186
- if (pos === undefined) {
187
- return;
185
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
186
+ var _pluginInjectionApi$c;
187
+ if (_this.removeCardDispatched || _this.getPosSafely() === undefined) {
188
+ return;
189
+ }
190
+ var _this$props = _this.props,
191
+ pluginInjectionApi = _this$props.pluginInjectionApi,
192
+ id = _this$props.id;
193
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c = pluginInjectionApi.card.actions) === null || _pluginInjectionApi$c === void 0 || _pluginInjectionApi$c.registerCard({
194
+ id: id,
195
+ title: title,
196
+ url: url,
197
+ getPos: _this.getPosSafely
198
+ });
199
+ } else {
200
+ var pos = _this.getPosSafely();
201
+ if (pos === undefined) {
202
+ return;
203
+ }
204
+ return view.dispatch(registerCard({
205
+ title: title,
206
+ url: url,
207
+ pos: pos,
208
+ id: _this.props.id
209
+ })(view.state.tr));
188
210
  }
189
- return view.dispatch(registerCard({
190
- title: title,
191
- url: url,
192
- pos: pos,
193
- id: _this.props.id
194
- })(view.state.tr));
195
211
  })();
196
212
  try {
197
213
  var _this$props$cardConte, _this$props$cardConte2;
@@ -326,27 +342,35 @@ export var EmbedCardComponent = /*#__PURE__*/function (_React$PureComponent) {
326
342
  return;
327
343
  }
328
344
  this.removeCardDispatched = true;
329
- var tr = this.props.view.state.tr;
330
- _removeCard({
331
- id: this.props.id
332
- })(tr);
333
- this.props.view.dispatch(tr);
345
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
346
+ var _pluginInjectionApi$c2;
347
+ var _this$props2 = this.props,
348
+ pluginInjectionApi = _this$props2.pluginInjectionApi,
349
+ id = _this$props2.id;
350
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c2 = pluginInjectionApi.card.actions) === null || _pluginInjectionApi$c2 === void 0 || _pluginInjectionApi$c2.removeRegisteredCard(id);
351
+ } else {
352
+ var tr = this.props.view.state.tr;
353
+ _removeCard({
354
+ id: this.props.id
355
+ })(tr);
356
+ this.props.view.dispatch(tr);
357
+ }
334
358
  }
335
359
  }, {
336
360
  key: "render",
337
361
  value: function render() {
338
- var _this$props = this.props,
339
- node = _this$props.node,
340
- allowResizing = _this$props.allowResizing,
341
- fullWidthMode = _this$props.fullWidthMode,
342
- view = _this$props.view,
343
- dispatchAnalyticsEvent = _this$props.dispatchAnalyticsEvent,
344
- getPos = _this$props.getPos,
345
- pluginInjectionApi = _this$props.pluginInjectionApi,
346
- actionOptions = _this$props.actionOptions,
347
- onClick = _this$props.onClick,
348
- CompetitorPrompt = _this$props.CompetitorPrompt,
349
- isPageSSRed = _this$props.isPageSSRed;
362
+ var _this$props3 = this.props,
363
+ node = _this$props3.node,
364
+ allowResizing = _this$props3.allowResizing,
365
+ fullWidthMode = _this$props3.fullWidthMode,
366
+ view = _this$props3.view,
367
+ dispatchAnalyticsEvent = _this$props3.dispatchAnalyticsEvent,
368
+ getPos = _this$props3.getPos,
369
+ pluginInjectionApi = _this$props3.pluginInjectionApi,
370
+ actionOptions = _this$props3.actionOptions,
371
+ onClick = _this$props3.onClick,
372
+ CompetitorPrompt = _this$props3.CompetitorPrompt,
373
+ isPageSSRed = _this$props3.isPageSSRed;
350
374
  var _node$attrs = node.attrs,
351
375
  url = _node$attrs.url,
352
376
  pctWidth = _node$attrs.width,
@@ -43,6 +43,9 @@ export var InlineCard = /*#__PURE__*/memo(function (_ref) {
43
43
  }
44
44
  };
45
45
  }, []);
46
+ var cardActions = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.card.actions;
47
+ var registerResolvedCard = cardActions === null || cardActions === void 0 ? void 0 : cardActions.registerCard;
48
+ var removeRegisteredCard = cardActions === null || cardActions === void 0 ? void 0 : cardActions.removeRegisteredCard;
46
49
  var _ref2 = (cardContext === null || cardContext === void 0 || (_cardContext$value = cardContext.value) === null || _cardContext$value === void 0 ? void 0 : _cardContext$value.store) || {},
47
50
  getSmartlinkState = _ref2.getState;
48
51
  var cardState = getSmartlinkState === null || getSmartlinkState === void 0 ? void 0 : getSmartlinkState()[url || ''];
@@ -54,13 +57,17 @@ export var InlineCard = /*#__PURE__*/memo(function (_ref) {
54
57
  return;
55
58
  }
56
59
  removeCardDispatched.current = true;
57
- var tr = view.state.tr;
58
- removeCard({
59
- id: id
60
- })(tr);
61
- view.dispatch(tr);
60
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
61
+ removeRegisteredCard === null || removeRegisteredCard === void 0 || removeRegisteredCard(id);
62
+ } else {
63
+ var tr = view.state.tr;
64
+ removeCard({
65
+ id: id
66
+ })(tr);
67
+ view.dispatch(tr);
68
+ }
62
69
  };
63
- }, [getPos, view]);
70
+ }, [getPos, isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? undefined : view, isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? removeRegisteredCard : undefined]);
64
71
  var scrollContainer = useMemo(function () {
65
72
  return isExperimentEnabled('platform_editor_reduce_forced_layout_2') && isIntersectionObserverSupported() ? undefined :
66
73
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
@@ -75,26 +82,40 @@ export var InlineCard = /*#__PURE__*/memo(function (_ref) {
75
82
  // don't dispatch immediately since we might be in the middle of
76
83
  // rendering a nodeview
77
84
  var scheduleRegisterCard = rafSchedule(function () {
78
- // prosemirror-bump-fix
79
- var pos = getPos();
80
- if (typeof pos !== 'number') {
81
- return;
85
+ if (isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
86
+ if (removeCardDispatched.current || getPos() === undefined) {
87
+ return;
88
+ }
89
+ var id = refId.current;
90
+ registerResolvedCard === null || registerResolvedCard === void 0 || registerResolvedCard({
91
+ id: id,
92
+ title: title,
93
+ url: url,
94
+ getPos: getPos
95
+ });
96
+ onRes === null || onRes === void 0 || onRes(undefined, title);
97
+ } else {
98
+ // prosemirror-bump-fix
99
+ var pos = getPos();
100
+ if (typeof pos !== 'number') {
101
+ return;
102
+ }
103
+ var tr = view.state.tr;
104
+ registerCard({
105
+ title: title,
106
+ url: url,
107
+ pos: pos,
108
+ id: refId.current
109
+ })(tr);
110
+ onRes === null || onRes === void 0 || onRes(tr, title);
111
+ view.dispatch(tr);
82
112
  }
83
- var tr = view.state.tr;
84
- registerCard({
85
- title: title,
86
- url: url,
87
- pos: pos,
88
- id: refId.current
89
- })(tr);
90
- onRes === null || onRes === void 0 || onRes(tr, title);
91
- view.dispatch(tr);
92
113
  });
93
114
  if (isExperimentEnabled('platform_editor_reduce_memory_leaks')) {
94
115
  pendingRegisterCard.current = scheduleRegisterCard;
95
116
  }
96
117
  scheduleRegisterCard();
97
- }, [getPos, view, onRes]);
118
+ }, [getPos, isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? undefined : view, onRes, isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? registerResolvedCard : undefined]);
98
119
  var onError = useCallback(function (data) {
99
120
  var url = data.url,
100
121
  err = data.err;
@@ -68,25 +68,29 @@ export var InlineCardWithAwareness = /*#__PURE__*/memo(function (_ref) {
68
68
  setIsResolvedViewRendered = _useState6[1];
69
69
  var editorAppearance = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$c = pluginInjectionApi.card.sharedState.currentState()) === null || _pluginInjectionApi$c === void 0 ? void 0 : _pluginInjectionApi$c.editorAppearance;
70
70
  var destinationUrl = useSmartLinkDestinationUrl(node.attrs.url);
71
+
72
+ // Remove tr: Transaction | undefined parameter with platform_editor_reduce_forced_layout_2 cleanup.
71
73
  var onResolve = useCallback(function (tr, title) {
72
- var metadata = tr.getMeta(pluginKey);
73
- var removeOverlay = isExperimentEnabled('platform_editor_reduce_memory_leaks') ? createRemoveOverlay(setIsInsertedRef) : function () {
74
- return setIsInserted(false);
75
- };
76
- if (metadata && metadata.type === 'REGISTER') {
77
- registerRemoveOverlay(removeOverlay, metadata.info)(tr);
78
- } else {
79
- registerRemoveOverlay(removeOverlay)(tr);
74
+ if (tr) {
75
+ var metadata = tr.getMeta(pluginKey);
76
+ var removeOverlay = isExperimentEnabled('platform_editor_reduce_memory_leaks') ? createRemoveOverlay(setIsInsertedRef) : function () {
77
+ return setIsInserted(false);
78
+ };
79
+ if (metadata && metadata.type === 'REGISTER') {
80
+ registerRemoveOverlay(removeOverlay, metadata.info)(tr);
81
+ } else {
82
+ registerRemoveOverlay(removeOverlay)(tr);
83
+ }
80
84
  }
81
85
  if (title) {
82
86
  setIsResolvedViewRendered(true);
83
87
  }
84
88
  }, []);
85
89
  var markMostRecentlyInsertedLink = useCallback(function (isLinkMostRecentlyInserted) {
86
- if (isOverlayEnabled) {
90
+ if (isOverlayEnabled && !isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
87
91
  setIsInserted(isLinkMostRecentlyInserted);
88
92
  }
89
- }, [isOverlayEnabled]);
93
+ }, [isExperimentEnabled('platform_editor_reduce_forced_layout_2') ? undefined : isOverlayEnabled]);
90
94
  var setOverlayHoveredStyles = useCallback(function (isHovered) {
91
95
  if (isOverlayEnabled) {
92
96
  setIsHovered(isHovered);
@@ -79,7 +79,7 @@ export var replaceQueuedUrlWithCard = function replaceQueuedUrlWithCard(url, car
79
79
 
80
80
  // If an embed card transformer is provided and the resolved card is an embedCard,
81
81
  // attempt to transform it into an alternative node representation first.
82
- if (cardData.type === 'embedCard' && embedCardNodeTransformer && fg('platform_native_embeds_rollout_non_maui_experience')) {
82
+ if (cardData.type === 'embedCard' && embedCardNodeTransformer && (fg('platform_native_embeds_rollout_non_maui_experience') || fg('platform_native_embeds_rollout_all_products'))) {
83
83
  var transformResult = embedCardNodeTransformer(schema, cardData.attrs);
84
84
  // The transformer may return a Promise for async transformations (e.g. short-link expansion).
85
85
  // When async, we snapshot the current requests and positions now (before any dispatch),
@@ -28,14 +28,16 @@ var LOCAL_STORAGE_DISCOVERY_KEY_SMART_LINK = 'smart-link-upgrade-pulse';
28
28
  // Only the first resolved inline smart link is needed for PO spotlight targeting
29
29
  var MAX_RESOLVED_INLINE_SMART_LINKS = 1;
30
30
  var handleAwarenessOverlay = function handleAwarenessOverlay(view) {
31
- var currentState = getPluginState(view.state);
32
- var overlayCandidatePos = currentState === null || currentState === void 0 ? void 0 : currentState.overlayCandidatePosition;
33
- if (overlayCandidatePos) {
34
- var _currentState$removeO;
35
- (_currentState$removeO = currentState.removeOverlay) === null || _currentState$removeO === void 0 || _currentState$removeO.call(currentState);
36
- var tr = view.state.tr;
37
- clearOverlayCandidate(tr);
38
- view.dispatch(tr);
31
+ if (!isExperimentEnabled('platform_editor_reduce_forced_layout_2')) {
32
+ var currentState = getPluginState(view.state);
33
+ var overlayCandidatePos = currentState === null || currentState === void 0 ? void 0 : currentState.overlayCandidatePosition;
34
+ if (overlayCandidatePos) {
35
+ var _currentState$removeO;
36
+ (_currentState$removeO = currentState.removeOverlay) === null || _currentState$removeO === void 0 || _currentState$removeO.call(currentState);
37
+ var tr = view.state.tr;
38
+ clearOverlayCandidate(tr);
39
+ view.dispatch(tr);
40
+ }
39
41
  }
40
42
  };
41
43
  export var createPlugin = function createPlugin(options, pluginInjectionApi) {
@@ -151,7 +153,7 @@ export var createPlugin = function createPlugin(options, pluginInjectionApi) {
151
153
  var linkPosition = pluginState.requests[0].pos;
152
154
  var canBeUpgradedToBlock = allowBlockCards && isBlockSupportedAtPosition(linkPosition, prevEditorState, 'inline');
153
155
  var canBeUpgradedToEmbed = allowEmbeds && isEmbedSupportedAtPosition(linkPosition, prevEditorState, 'inline');
154
- if (canBeUpgradedToBlock || canBeUpgradedToEmbed) {
156
+ if (!isExperimentEnabled('platform_editor_reduce_forced_layout_2') && (canBeUpgradedToBlock || canBeUpgradedToEmbed)) {
155
157
  newState.overlayCandidatePosition = linkPosition;
156
158
  }
157
159
  if (!isSmartLinkPulseDiscovered && canBeUpgradedToEmbed) {