@atlaskit/editor-plugin-media 1.43.13 → 1.44.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 (45) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/nodeviews/mediaGroup.js +4 -4
  3. package/dist/cjs/nodeviews/mediaGroupNext.js +4 -4
  4. package/dist/cjs/nodeviews/mediaInline.js +8 -8
  5. package/dist/cjs/nodeviews/mediaNodeUpdater.js +254 -177
  6. package/dist/cjs/nodeviews/mediaSingle.js +4 -4
  7. package/dist/cjs/nodeviews/mediaSingleNext.js +4 -4
  8. package/dist/cjs/pm-plugins/alt-text/ui/AltTextEdit.js +4 -0
  9. package/dist/cjs/pm-plugins/main.js +41 -13
  10. package/dist/cjs/pm-plugins/utils/media-single.js +43 -25
  11. package/dist/cjs/ui/MediaLinkingToolbar.js +1 -0
  12. package/dist/cjs/ui/toolbar/mediaInline.js +3 -3
  13. package/dist/es2019/nodeviews/mediaGroup.js +2 -2
  14. package/dist/es2019/nodeviews/mediaGroupNext.js +2 -2
  15. package/dist/es2019/nodeviews/mediaInline.js +5 -5
  16. package/dist/es2019/nodeviews/mediaNodeUpdater.js +78 -27
  17. package/dist/es2019/nodeviews/mediaSingle.js +2 -2
  18. package/dist/es2019/nodeviews/mediaSingleNext.js +2 -2
  19. package/dist/es2019/pm-plugins/alt-text/ui/AltTextEdit.js +4 -0
  20. package/dist/es2019/pm-plugins/main.js +42 -12
  21. package/dist/es2019/pm-plugins/utils/media-single.js +40 -18
  22. package/dist/es2019/ui/MediaLinkingToolbar.js +1 -0
  23. package/dist/es2019/ui/toolbar/mediaInline.js +3 -3
  24. package/dist/esm/nodeviews/mediaGroup.js +4 -4
  25. package/dist/esm/nodeviews/mediaGroupNext.js +4 -4
  26. package/dist/esm/nodeviews/mediaInline.js +8 -8
  27. package/dist/esm/nodeviews/mediaNodeUpdater.js +254 -177
  28. package/dist/esm/nodeviews/mediaSingle.js +4 -4
  29. package/dist/esm/nodeviews/mediaSingleNext.js +4 -4
  30. package/dist/esm/pm-plugins/alt-text/ui/AltTextEdit.js +4 -0
  31. package/dist/esm/pm-plugins/main.js +42 -14
  32. package/dist/esm/pm-plugins/utils/media-single.js +43 -25
  33. package/dist/esm/ui/MediaLinkingToolbar.js +1 -0
  34. package/dist/esm/ui/toolbar/mediaInline.js +3 -3
  35. package/dist/types/nodeviews/__mocks__/mediaNodeUpdater.d.ts +1 -0
  36. package/dist/types/nodeviews/mediaNodeUpdater.d.ts +4 -1
  37. package/dist/types/pm-plugins/main.d.ts +4 -1
  38. package/dist/types/pm-plugins/types.d.ts +2 -0
  39. package/dist/types/types/index.d.ts +2 -0
  40. package/dist/types-ts4.5/nodeviews/__mocks__/mediaNodeUpdater.d.ts +1 -0
  41. package/dist/types-ts4.5/nodeviews/mediaNodeUpdater.d.ts +4 -1
  42. package/dist/types-ts4.5/pm-plugins/main.d.ts +4 -1
  43. package/dist/types-ts4.5/pm-plugins/types.d.ts +2 -0
  44. package/dist/types-ts4.5/types/index.d.ts +2 -0
  45. package/package.json +13 -7
@@ -21,7 +21,7 @@ import { updateMediaNodeAttrs } from '../pm-plugins/commands/helpers';
21
21
  // Ignored via go/ees005
22
22
  // eslint-disable-next-line import/no-namespace
23
23
  import * as helpers from '../pm-plugins/commands/helpers';
24
- import { getMediaFromSupportedMediaNodesFromSelection, isNodeDoubleClickSupportedInLivePagesViewMode, removeMediaNode, splitMediaGroup } from '../pm-plugins/utils/media-common';
24
+ import { getIdentifier, getMediaFromSupportedMediaNodesFromSelection, isNodeDoubleClickSupportedInLivePagesViewMode, removeMediaNode, splitMediaGroup } from '../pm-plugins/utils/media-common';
25
25
  import { insertMediaGroupNode, insertMediaInlineNode } from '../pm-plugins/utils/media-files';
26
26
  import { getMediaNodeInsertionType } from '../pm-plugins/utils/media-inline';
27
27
  import { insertMediaSingleNode } from '../pm-plugins/utils/media-single';
@@ -92,7 +92,7 @@ export class MediaPluginStateImplementation {
92
92
  _defineProperty(this, "destroyed", false);
93
93
  _defineProperty(this, "removeOnCloseListener", () => {});
94
94
  _defineProperty(this, "onPopupToggleCallback", () => {});
95
- _defineProperty(this, "nodeCount", new Map());
95
+ _defineProperty(this, "identifierCount", new Map());
96
96
  _defineProperty(this, "taskManager", new MediaTaskManager());
97
97
  _defineProperty(this, "pickers", []);
98
98
  _defineProperty(this, "pickerPromises", []);
@@ -247,23 +247,53 @@ export class MediaPluginStateImplementation {
247
247
  }
248
248
  removeMediaNode(this.view, getNode, getPos);
249
249
  });
250
+ _defineProperty(this, "getIdentifierKey", identifier => {
251
+ if (identifier.mediaItemType === "file") {
252
+ return identifier.id;
253
+ } else {
254
+ return identifier.dataURI;
255
+ }
256
+ });
250
257
  _defineProperty(this, "trackMediaNodeAddition", node => {
251
- var _this$nodeCount$get;
252
- const id = node.attrs.id;
253
- const count = (_this$nodeCount$get = this.nodeCount.get(id)) !== null && _this$nodeCount$get !== void 0 ? _this$nodeCount$get : 0;
258
+ var _this$identifierCount;
259
+ const identifier = getIdentifier(node.attrs);
260
+ const key = this.getIdentifierKey(identifier);
261
+ const {
262
+ count
263
+ } = (_this$identifierCount = this.identifierCount.get(key)) !== null && _this$identifierCount !== void 0 ? _this$identifierCount : {
264
+ count: 0
265
+ };
254
266
  if (count === 0) {
255
- this.taskManager.resumePendingTask(id);
267
+ this.taskManager.resumePendingTask(key);
256
268
  }
257
- this.nodeCount.set(id, count + 1);
269
+ this.identifierCount.set(key, {
270
+ identifier,
271
+ count: count + 1
272
+ });
258
273
  });
259
274
  _defineProperty(this, "trackMediaNodeRemoval", node => {
260
- var _this$nodeCount$get2;
261
- const id = node.attrs.id;
262
- const count = (_this$nodeCount$get2 = this.nodeCount.get(id)) !== null && _this$nodeCount$get2 !== void 0 ? _this$nodeCount$get2 : 0;
275
+ var _this$identifierCount2;
276
+ const identifier = getIdentifier(node.attrs);
277
+ const key = this.getIdentifierKey(identifier);
278
+ const {
279
+ count
280
+ } = (_this$identifierCount2 = this.identifierCount.get(key)) !== null && _this$identifierCount2 !== void 0 ? _this$identifierCount2 : {
281
+ count: 0
282
+ };
263
283
  if (count === 1) {
264
- this.taskManager.cancelPendingTask(id);
284
+ this.taskManager.cancelPendingTask(key);
265
285
  }
266
- this.nodeCount.set(id, count - 1);
286
+ this.identifierCount.set(key, {
287
+ identifier,
288
+ count: count - 1
289
+ });
290
+ });
291
+ _defineProperty(this, "isIdentifierInEditorScope", identifier => {
292
+ const key = this.getIdentifierKey(identifier);
293
+
294
+ // rely on has instead of count > 0 because if the user cuts and pastes the same media
295
+ // the count will temporarily be 0 but the media is still in the scope of editor.
296
+ return this.identifierCount.has(key);
267
297
  });
268
298
  /**
269
299
  * Called from React UI Component on componentDidMount
@@ -27,10 +27,13 @@ const getInsertMediaAnalytics = (inputMethod, fileExtension, insertMediaVia) =>
27
27
  function shouldAddParagraph(state) {
28
28
  return atTheBeginningOfBlock(state) && !checkNodeDown(state.selection, state.doc, isEmptyParagraph);
29
29
  }
30
-
31
- // Ignored via go/ees005
32
- // eslint-disable-next-line @typescript-eslint/max-params
33
- function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, editorAnalyticsAPI, isNestingInQuoteSupported, insertMediaVia) {
30
+ function insertNodesWithOptionalParagraph({
31
+ nodes,
32
+ analyticsAttributes = {},
33
+ editorAnalyticsAPI,
34
+ isNestingInQuoteSupported,
35
+ insertMediaVia
36
+ }) {
34
37
  return function (state, dispatch) {
35
38
  const {
36
39
  tr,
@@ -46,7 +49,7 @@ function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, edito
46
49
  previousType
47
50
  } = analyticsAttributes;
48
51
  let openEnd = 0;
49
- if (shouldAddParagraph(state)) {
52
+ if (shouldAddParagraph(state) && !fg('platform_editor_axe_leading_paragraph_from_media')) {
50
53
  nodes.push(paragraph.create());
51
54
  openEnd = 1;
52
55
  }
@@ -58,10 +61,12 @@ function insertNodesWithOptionalParagraph(nodes, analyticsAttributes = {}, edito
58
61
  const grandparentEndPos = state.selection.$from.start(-1) + grandParentNode.nodeSize - 1;
59
62
  pmSafeInsert(nodes[0], grandparentEndPos)(tr).scrollIntoView();
60
63
  } else if (state.selection.empty) {
61
- tr.insert(state.selection.from, nodes);
62
- // Set the cursor position at the end of the insertion
64
+ const insertFrom = atTheBeginningOfBlock(state) && fg('platform_editor_axe_leading_paragraph_from_media') ? state.selection.$from.before() : state.selection.from;
65
+ tr.insert(insertFrom, nodes);
63
66
  const endPos = state.selection.from + nodes.reduce((totalSize, currNode) => totalSize + currNode.nodeSize, 0);
64
- tr.setSelection(new TextSelection(tr.doc.resolve(endPos), tr.doc.resolve(endPos)));
67
+ if (!fg('platform_editor_axe_leading_paragraph_from_media')) {
68
+ tr.setSelection(new TextSelection(tr.doc.resolve(endPos), tr.doc.resolve(endPos)));
69
+ }
65
70
  } else {
66
71
  tr.replaceSelection(new Slice(Fragment.from(nodes), 0, openEnd));
67
72
  }
@@ -112,7 +117,13 @@ export const insertMediaAsMediaSingle = (view, node, inputMethod, editorAnalytic
112
117
  inputMethod,
113
118
  fileExtension: node.attrs.__fileMimeType
114
119
  };
115
- return insertNodesWithOptionalParagraph(nodes, analyticsAttributes, editorAnalyticsAPI, isNestingInQuoteSupported, insertMediaVia)(state, dispatch);
120
+ return insertNodesWithOptionalParagraph({
121
+ nodes,
122
+ analyticsAttributes,
123
+ editorAnalyticsAPI,
124
+ isNestingInQuoteSupported,
125
+ insertMediaVia
126
+ })(state, dispatch);
116
127
  };
117
128
  const getFileExtension = fileName => {
118
129
  if (fileName) {
@@ -152,10 +163,16 @@ export const insertMediaSingleNode = (view, mediaState, inputMethod, collection,
152
163
  grandParentNodeType,
153
164
  content: node
154
165
  })) {
155
- insertNodesWithOptionalParagraph([node], {
156
- fileExtension,
157
- inputMethod
158
- }, editorAnalyticsAPI, isNestingInQuoteSupported, insertMediaVia)(state, dispatch);
166
+ insertNodesWithOptionalParagraph({
167
+ nodes: [node],
168
+ analyticsAttributes: {
169
+ fileExtension,
170
+ inputMethod
171
+ },
172
+ editorAnalyticsAPI,
173
+ isNestingInQuoteSupported,
174
+ insertMediaVia
175
+ })(state, dispatch);
159
176
  } else {
160
177
  let tr = null;
161
178
  tr = safeInsert(node, state.selection.from)(state.tr);
@@ -203,11 +220,16 @@ export const changeFromMediaInlineToMediaSingleNode = (view, fromNode, widthPlug
203
220
  grandParentNodeType,
204
221
  content: node
205
222
  })) {
206
- return insertNodesWithOptionalParagraph([node], {
207
- fileExtension,
208
- newType: ACTION_SUBJECT_ID.MEDIA_SINGLE,
209
- previousType: ACTION_SUBJECT_ID.MEDIA_INLINE
210
- }, editorAnalyticsAPI, isNestingInQuoteSupported)(state, dispatch);
223
+ return insertNodesWithOptionalParagraph({
224
+ nodes: [node],
225
+ analyticsAttributes: {
226
+ fileExtension,
227
+ newType: ACTION_SUBJECT_ID.MEDIA_SINGLE,
228
+ previousType: ACTION_SUBJECT_ID.MEDIA_INLINE
229
+ },
230
+ editorAnalyticsAPI,
231
+ isNestingInQuoteSupported
232
+ })(state, dispatch);
211
233
  } else {
212
234
  const nodePos = state.tr.doc.resolve(state.selection.from).end();
213
235
  let tr = null;
@@ -19,6 +19,7 @@ import ChevronLeftLargeIcon from '@atlaskit/icon/glyph/chevron-left-large';
19
19
  import EditorUnlinkIcon from '@atlaskit/icon/glyph/editor/unlink';
20
20
  import { R400 } from '@atlaskit/theme/colors';
21
21
  const validationWrapper = css({
22
+ // eslint-disable-next-line @atlaskit/design-system/use-tokens-typography
22
23
  lineHeight: 0,
23
24
  padding: `${"var(--ds-space-150, 12px)"} ${"var(--ds-space-300, 24px)"} ${"var(--ds-space-150, 12px)"} 0`,
24
25
  margin: `0 ${"var(--ds-space-050, 4px)"} 0 ${"var(--ds-space-400, 32px)"}`,
@@ -4,9 +4,9 @@ import { IconCard, IconEmbed, IconInline } from '@atlaskit/editor-common/card';
4
4
  import commonMessages, { cardMessages, mediaAndEmbedToolbarMessages } from '@atlaskit/editor-common/messages';
5
5
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
6
6
  import DeleteIcon from '@atlaskit/icon/core/delete';
7
- import ExpandIcon from '@atlaskit/icon/core/grow-diagonal';
8
7
  import ImageFullscreenIcon from '@atlaskit/icon/core/image-fullscreen';
9
8
  import ImageInlineIcon from '@atlaskit/icon/core/image-inline';
9
+ import MaximizeIcon from '@atlaskit/icon/core/maximize';
10
10
  import DownloadIcon from '@atlaskit/icon/core/migration/download';
11
11
  import SmartLinkCardIcon from '@atlaskit/icon/core/smart-link-card';
12
12
  import FilePreviewIcon from '@atlaskit/icon/glyph/editor/file-preview';
@@ -69,7 +69,7 @@ export const generateMediaInlineFloatingToolbar = (state, intl, mediaPluginState
69
69
  id: 'editor.media.viewer',
70
70
  testId: 'file-preview-toolbar-button',
71
71
  type: 'button',
72
- icon: ExpandIcon,
72
+ icon: MaximizeIcon,
73
73
  iconFallback: FilePreviewIcon,
74
74
  title: intl.formatMessage(messages.preview),
75
75
  onClick: () => {
@@ -249,7 +249,7 @@ const getMediaInlineImageToolbar = (state, intl, mediaPluginState, hoverDecorati
249
249
  id: 'editor.media.viewer',
250
250
  testId: 'file-preview-toolbar-button',
251
251
  type: 'button',
252
- icon: ExpandIcon,
252
+ icon: MaximizeIcon,
253
253
  iconFallback: FilePreviewIcon,
254
254
  title: intl.formatMessage(messages.preview),
255
255
  onClick: () => {
@@ -193,7 +193,7 @@ var MediaGroup = /*#__PURE__*/function (_React$Component) {
193
193
  this.updateMediaClientConfig();
194
194
  this.mediaNodes.forEach( /*#__PURE__*/function () {
195
195
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(node) {
196
- var _this2$props, view, mediaProvider, contextIdentifierProvider, mediaNodeUpdater, getPos, contextId, hasDifferentContextId;
196
+ var _this2$props, view, mediaProvider, contextIdentifierProvider, mediaNodeUpdater, getPos, contextId, shouldNodeBeDeepCopied;
197
197
  return _regeneratorRuntime.wrap(function _callee$(_context) {
198
198
  while (1) switch (_context.prev = _context.next) {
199
199
  case 0:
@@ -232,10 +232,10 @@ var MediaGroup = /*#__PURE__*/function (_React$Component) {
232
232
  return mediaNodeUpdater.updateNodeContextId(getPos);
233
233
  case 9:
234
234
  _context.next = 11;
235
- return mediaNodeUpdater.hasDifferentContextId();
235
+ return mediaNodeUpdater.shouldNodeBeDeepCopied();
236
236
  case 11:
237
- hasDifferentContextId = _context.sent;
238
- if (!hasDifferentContextId) {
237
+ shouldNodeBeDeepCopied = _context.sent;
238
+ if (!shouldNodeBeDeepCopied) {
239
239
  _context.next = 15;
240
240
  break;
241
241
  }
@@ -117,7 +117,7 @@ var useLatestMediaGroupNode = function useLatestMediaGroupNode(nextMediaNode) {
117
117
  };
118
118
  var runMediaNodeUpdate = /*#__PURE__*/function () {
119
119
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref2) {
120
- var mediaNodeUpdater, getPos, node, updateAttrs, contextId, hasDifferentContextId;
120
+ var mediaNodeUpdater, getPos, node, updateAttrs, contextId, shouldNodeBeDeepCopied;
121
121
  return _regeneratorRuntime.wrap(function _callee$(_context) {
122
122
  while (1) switch (_context.prev = _context.next) {
123
123
  case 0:
@@ -138,10 +138,10 @@ var runMediaNodeUpdate = /*#__PURE__*/function () {
138
138
  return mediaNodeUpdater.updateNodeContextId(getPos);
139
139
  case 8:
140
140
  _context.next = 10;
141
- return mediaNodeUpdater.hasDifferentContextId();
141
+ return mediaNodeUpdater.shouldNodeBeDeepCopied();
142
142
  case 10:
143
- hasDifferentContextId = _context.sent;
144
- if (!hasDifferentContextId) {
143
+ shouldNodeBeDeepCopied = _context.sent;
144
+ if (!shouldNodeBeDeepCopied) {
145
145
  _context.next = 14;
146
146
  break;
147
147
  }
@@ -49,7 +49,7 @@ var createMediaNodeUpdater = function createMediaNodeUpdater(props) {
49
49
  */
50
50
  var updateMediaNodeAttributes = /*#__PURE__*/function () {
51
51
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(props, mediaNodeUpdater) {
52
- var addPendingTask, node, contextId, hasDifferentContextId, copyNode;
52
+ var addPendingTask, node, contextId, shouldNodeBeDeepCopied, copyNode;
53
53
  return _regeneratorRuntime.wrap(function _callee$(_context) {
54
54
  while (1) switch (_context.prev = _context.next) {
55
55
  case 0:
@@ -70,10 +70,10 @@ var updateMediaNodeAttributes = /*#__PURE__*/function () {
70
70
  return mediaNodeUpdater.updateContextId();
71
71
  case 8:
72
72
  _context.next = 10;
73
- return mediaNodeUpdater.hasDifferentContextId();
73
+ return mediaNodeUpdater.shouldNodeBeDeepCopied();
74
74
  case 10:
75
- hasDifferentContextId = _context.sent;
76
- if (!hasDifferentContextId) {
75
+ shouldNodeBeDeepCopied = _context.sent;
76
+ if (!shouldNodeBeDeepCopied) {
77
77
  _context.next = 22;
78
78
  break;
79
79
  }
@@ -120,11 +120,11 @@ export var MediaInline = function MediaInline(props) {
120
120
  setViewMediaClientConfig = _useState2[1];
121
121
  var _useState3 = useState(true),
122
122
  _useState4 = _slicedToArray(_useState3, 2),
123
- isContextIdUnsync = _useState4[0],
124
- setIsContextIdUnsync = _useState4[1];
123
+ isNodeScopeUnsync = _useState4[0],
124
+ setIsNodeScopeUnsync = _useState4[1];
125
125
  useEffect(function () {
126
126
  var mediaNodeUpdater = createMediaNodeUpdater(props);
127
- mediaNodeUpdater.hasDifferentContextId().then(setIsContextIdUnsync);
127
+ mediaNodeUpdater.shouldNodeBeDeepCopied().then(setIsNodeScopeUnsync);
128
128
  handleNewNode(props);
129
129
  updateMediaNodeAttributes(props, mediaNodeUpdater);
130
130
  updateViewMediaClientConfig(props);
@@ -179,7 +179,7 @@ export var MediaInline = function MediaInline(props) {
179
179
  * to prevent calling the media API (in mounting of `MediaInlineCard`)
180
180
  * before the prerequisites meet
181
181
  */
182
- if (!viewMediaClientConfig || isContextIdUnsync) {
182
+ if (!viewMediaClientConfig || isNodeScopeUnsync) {
183
183
  return jsx(MediaInlineCardLoadingView, {
184
184
  message: "",
185
185
  isSelected: false