@atlaskit/editor-plugin-media 1.35.0 → 1.36.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.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/nodeviews/mediaNodeUpdater.js +7 -1
- package/dist/cjs/nodeviews/mediaSingle.js +27 -0
- package/dist/cjs/nodeviews/mediaSingleNext.js +583 -0
- package/dist/cjs/plugin.js +70 -43
- package/dist/cjs/pm-plugins/actions.js +10 -0
- package/dist/cjs/pm-plugins/commands.js +28 -0
- package/dist/cjs/pm-plugins/main.js +14 -0
- package/dist/cjs/toolbar/filePreviewItem.js +3 -2
- package/dist/cjs/toolbar/index.js +46 -12
- package/dist/cjs/toolbar/mediaInline.js +14 -1
- package/dist/es2019/nodeviews/mediaNodeUpdater.js +7 -0
- package/dist/es2019/nodeviews/mediaSingle.js +27 -0
- package/dist/es2019/nodeviews/mediaSingleNext.js +543 -0
- package/dist/es2019/plugin.js +31 -2
- package/dist/es2019/pm-plugins/actions.js +4 -0
- package/dist/es2019/pm-plugins/commands.js +22 -0
- package/dist/es2019/pm-plugins/main.js +14 -0
- package/dist/es2019/toolbar/filePreviewItem.js +3 -2
- package/dist/es2019/toolbar/index.js +40 -5
- package/dist/es2019/toolbar/mediaInline.js +15 -2
- package/dist/esm/nodeviews/mediaNodeUpdater.js +6 -0
- package/dist/esm/nodeviews/mediaSingle.js +27 -0
- package/dist/esm/nodeviews/mediaSingleNext.js +576 -0
- package/dist/esm/plugin.js +70 -43
- package/dist/esm/pm-plugins/actions.js +4 -0
- package/dist/esm/pm-plugins/commands.js +22 -0
- package/dist/esm/pm-plugins/main.js +14 -0
- package/dist/esm/toolbar/filePreviewItem.js +3 -2
- package/dist/esm/toolbar/index.js +46 -12
- package/dist/esm/toolbar/mediaInline.js +15 -2
- package/dist/types/next-plugin-type.d.ts +6 -1
- package/dist/types/nodeviews/mediaNodeUpdater.d.ts +1 -0
- package/dist/types/nodeviews/mediaSingle.d.ts +1 -1
- package/dist/types/nodeviews/mediaSingleNext.d.ts +35 -0
- package/dist/types/pm-plugins/actions.d.ts +4 -0
- package/dist/types/pm-plugins/commands.d.ts +4 -0
- package/dist/types/pm-plugins/types.d.ts +3 -1
- package/dist/types/toolbar/index.d.ts +4 -0
- package/dist/types-ts4.5/next-plugin-type.d.ts +6 -1
- package/dist/types-ts4.5/nodeviews/mediaNodeUpdater.d.ts +1 -0
- package/dist/types-ts4.5/nodeviews/mediaSingle.d.ts +1 -1
- package/dist/types-ts4.5/nodeviews/mediaSingleNext.d.ts +35 -0
- package/dist/types-ts4.5/pm-plugins/actions.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/commands.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/types.d.ts +3 -1
- package/dist/types-ts4.5/toolbar/index.d.ts +4 -0
- package/package.json +13 -7
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
|
+
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; }
|
|
6
|
+
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; }
|
|
7
|
+
/**
|
|
8
|
+
* @jsxRuntime classic
|
|
9
|
+
* @jsx jsx
|
|
10
|
+
* @jsxFrag
|
|
11
|
+
*/
|
|
12
|
+
import React, { Fragment } from 'react';
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
15
|
+
import { css, jsx } from '@emotion/react';
|
|
16
|
+
import { usePreviousState } from '@atlaskit/editor-common/hooks';
|
|
17
|
+
import { calcMediaSinglePixelWidth, DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH, ExternalImageBadge, getMaxWidthForNestedNode, MEDIA_SINGLE_GUTTER_SIZE, MediaBadges } from '@atlaskit/editor-common/media-single';
|
|
18
|
+
import { MediaSingle } from '@atlaskit/editor-common/ui';
|
|
19
|
+
import { browser } from '@atlaskit/editor-common/utils';
|
|
20
|
+
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
21
|
+
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
22
|
+
import { getAttrsFromUrl } from '@atlaskit/media-client';
|
|
23
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
24
|
+
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
25
|
+
import { insertAndSelectCaptionFromMediaSinglePos } from '../commands/captions';
|
|
26
|
+
import { CaptionPlaceholder, CaptionPlaceholderButton } from '../ui/CaptionPlaceholder';
|
|
27
|
+
import { CommentBadge, CommentBadgeNextWrapper } from '../ui/CommentBadge';
|
|
28
|
+
import ResizableMediaSingle from '../ui/ResizableMediaSingle';
|
|
29
|
+
import ResizableMediaSingleNext from '../ui/ResizableMediaSingle/ResizableMediaSingleNext';
|
|
30
|
+
import { isMediaBlobUrlFromAttrs } from '../utils/media-common';
|
|
31
|
+
import { hasPrivateAttrsChanged } from './helpers';
|
|
32
|
+
import { createMediaNodeUpdater } from './mediaNodeUpdater';
|
|
33
|
+
import { MediaSingleNodeSelector } from './styles';
|
|
34
|
+
var figureWrapperStyles = css({
|
|
35
|
+
margin: 0
|
|
36
|
+
});
|
|
37
|
+
var useMediaNodeUpdater = function useMediaNodeUpdater(_ref) {
|
|
38
|
+
var mediaProvider = _ref.mediaProvider,
|
|
39
|
+
mediaNode = _ref.mediaNode,
|
|
40
|
+
dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
|
|
41
|
+
mediaSingleNodeProps = _ref.mediaSingleNodeProps;
|
|
42
|
+
var previousMediaProvider = usePreviousState(mediaProvider);
|
|
43
|
+
var previousMediaNode = usePreviousState(mediaNode);
|
|
44
|
+
var mediaNodeUpdaterRef = React.useRef(null);
|
|
45
|
+
var createOrUpdateMediaNodeUpdater = React.useCallback(function (props) {
|
|
46
|
+
var mediaChildNode = mediaNode.firstChild;
|
|
47
|
+
var updaterProps = _objectSpread(_objectSpread({}, props), {}, {
|
|
48
|
+
isMediaSingle: true,
|
|
49
|
+
node: mediaChildNode ? mediaChildNode : mediaNode,
|
|
50
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent
|
|
51
|
+
});
|
|
52
|
+
if (!mediaNodeUpdaterRef.current) {
|
|
53
|
+
mediaNodeUpdaterRef.current = createMediaNodeUpdater(updaterProps);
|
|
54
|
+
} else {
|
|
55
|
+
mediaNodeUpdaterRef.current.setProps(updaterProps);
|
|
56
|
+
}
|
|
57
|
+
}, [mediaNode, dispatchAnalyticsEvent]);
|
|
58
|
+
React.useEffect(function () {
|
|
59
|
+
// Forced updates not required on mobile
|
|
60
|
+
if (mediaSingleNodeProps.isCopyPasteEnabled === false) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!mediaNodeUpdaterRef.current || previousMediaProvider !== mediaProvider) {
|
|
64
|
+
var _mediaNodeUpdaterRef$;
|
|
65
|
+
createOrUpdateMediaNodeUpdater(mediaSingleNodeProps);
|
|
66
|
+
(_mediaNodeUpdaterRef$ = mediaNodeUpdaterRef.current) === null || _mediaNodeUpdaterRef$ === void 0 || _mediaNodeUpdaterRef$.updateMediaSingleFileAttrs();
|
|
67
|
+
} else if (mediaNode.firstChild && previousMediaNode !== null && previousMediaNode !== void 0 && previousMediaNode.firstChild && mediaNode.firstChild !== (previousMediaNode === null || previousMediaNode === void 0 ? void 0 : previousMediaNode.firstChild)) {
|
|
68
|
+
var attrsChanged = hasPrivateAttrsChanged(previousMediaNode.firstChild.attrs, mediaNode.firstChild.attrs);
|
|
69
|
+
if (attrsChanged) {
|
|
70
|
+
var _mediaNodeUpdaterRef$2;
|
|
71
|
+
createOrUpdateMediaNodeUpdater(mediaSingleNodeProps);
|
|
72
|
+
// We need to call this method on any prop change since attrs can get removed with collab editing
|
|
73
|
+
(_mediaNodeUpdaterRef$2 = mediaNodeUpdaterRef.current) === null || _mediaNodeUpdaterRef$2 === void 0 || _mediaNodeUpdaterRef$2.updateMediaSingleFileAttrs();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}, [createOrUpdateMediaNodeUpdater, mediaNode, mediaProvider, mediaSingleNodeProps, previousMediaNode, previousMediaProvider]);
|
|
77
|
+
return mediaNodeUpdaterRef.current;
|
|
78
|
+
};
|
|
79
|
+
var mediaAsyncOperations = /*#__PURE__*/function () {
|
|
80
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(props) {
|
|
81
|
+
var updatedDimensions, currentAttrs, updatingNode, contextId, hasDifferentContextId, copyNode;
|
|
82
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
83
|
+
while (1) switch (_context.prev = _context.next) {
|
|
84
|
+
case 0:
|
|
85
|
+
_context.next = 2;
|
|
86
|
+
return props.updater.getRemoteDimensions();
|
|
87
|
+
case 2:
|
|
88
|
+
updatedDimensions = _context.sent;
|
|
89
|
+
currentAttrs = props.mediaChildNode.attrs;
|
|
90
|
+
if (updatedDimensions && ((currentAttrs === null || currentAttrs === void 0 ? void 0 : currentAttrs.width) !== updatedDimensions.width || (currentAttrs === null || currentAttrs === void 0 ? void 0 : currentAttrs.height) !== updatedDimensions.height)) {
|
|
91
|
+
props.updater.updateDimensions(updatedDimensions);
|
|
92
|
+
}
|
|
93
|
+
if (!(props.mediaChildNode.attrs.type === 'external' && props.mediaChildNode.attrs.__external)) {
|
|
94
|
+
_context.next = 11;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
updatingNode = props.updater.handleExternalMedia(props.getPos);
|
|
98
|
+
props.addPendingTask(updatingNode);
|
|
99
|
+
_context.next = 10;
|
|
100
|
+
return updatingNode;
|
|
101
|
+
case 10:
|
|
102
|
+
return _context.abrupt("return");
|
|
103
|
+
case 11:
|
|
104
|
+
contextId = props.updater.getNodeContextId();
|
|
105
|
+
if (contextId) {
|
|
106
|
+
_context.next = 15;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
_context.next = 15;
|
|
110
|
+
return props.updater.updateContextId();
|
|
111
|
+
case 15:
|
|
112
|
+
_context.next = 17;
|
|
113
|
+
return props.updater.hasDifferentContextId();
|
|
114
|
+
case 17:
|
|
115
|
+
hasDifferentContextId = _context.sent;
|
|
116
|
+
if (!hasDifferentContextId) {
|
|
117
|
+
_context.next = 28;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
_context.prev = 19;
|
|
121
|
+
copyNode = props.updater.copyNode({
|
|
122
|
+
traceId: props.mediaNode.attrs.__mediaTraceId
|
|
123
|
+
});
|
|
124
|
+
props.addPendingTask(copyNode);
|
|
125
|
+
_context.next = 24;
|
|
126
|
+
return copyNode;
|
|
127
|
+
case 24:
|
|
128
|
+
_context.next = 28;
|
|
129
|
+
break;
|
|
130
|
+
case 26:
|
|
131
|
+
_context.prev = 26;
|
|
132
|
+
_context.t0 = _context["catch"](19);
|
|
133
|
+
case 28:
|
|
134
|
+
case "end":
|
|
135
|
+
return _context.stop();
|
|
136
|
+
}
|
|
137
|
+
}, _callee, null, [[19, 26]]);
|
|
138
|
+
}));
|
|
139
|
+
return function mediaAsyncOperations(_x) {
|
|
140
|
+
return _ref2.apply(this, arguments);
|
|
141
|
+
};
|
|
142
|
+
}();
|
|
143
|
+
var useMediaAsyncOperations = function useMediaAsyncOperations(_ref3) {
|
|
144
|
+
var mediaNode = _ref3.mediaNode,
|
|
145
|
+
mediaNodeUpdater = _ref3.mediaNodeUpdater,
|
|
146
|
+
addPendingTask = _ref3.addPendingTask,
|
|
147
|
+
getPos = _ref3.getPos;
|
|
148
|
+
React.useEffect(function () {
|
|
149
|
+
if (!mediaNodeUpdater) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// we want the first child of MediaSingle (type "media")
|
|
153
|
+
var childNode = mediaNode.firstChild;
|
|
154
|
+
if (!childNode) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
mediaAsyncOperations({
|
|
158
|
+
mediaChildNode: childNode,
|
|
159
|
+
updater: mediaNodeUpdater,
|
|
160
|
+
getPos: getPos,
|
|
161
|
+
mediaNode: mediaNode,
|
|
162
|
+
addPendingTask: addPendingTask
|
|
163
|
+
});
|
|
164
|
+
}, [mediaNode, addPendingTask, mediaNodeUpdater, getPos]);
|
|
165
|
+
};
|
|
166
|
+
var noop = function noop() {};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Keep returning the same ProseMirror Node, unless the node content changed.
|
|
170
|
+
*
|
|
171
|
+
* React uses shallow comparation with `Object.is`,
|
|
172
|
+
* but that can cause multiple re-renders when the same node is given in a different instance.
|
|
173
|
+
*
|
|
174
|
+
* To avoid unnecessary re-renders, this hook uses the `Node.eq` from ProseMirror API to compare
|
|
175
|
+
* previous and new values.
|
|
176
|
+
*/
|
|
177
|
+
var useLatestMediaNode = function useLatestMediaNode(nextMediaNode) {
|
|
178
|
+
var previousMediaNode = usePreviousState(nextMediaNode);
|
|
179
|
+
var _React$useState = React.useState(nextMediaNode),
|
|
180
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
181
|
+
mediaNode = _React$useState2[0],
|
|
182
|
+
setMediaNode = _React$useState2[1];
|
|
183
|
+
React.useEffect(function () {
|
|
184
|
+
if (!previousMediaNode) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (!previousMediaNode.eq(nextMediaNode)) {
|
|
188
|
+
setMediaNode(nextMediaNode);
|
|
189
|
+
}
|
|
190
|
+
}, [previousMediaNode, nextMediaNode]);
|
|
191
|
+
return mediaNode;
|
|
192
|
+
};
|
|
193
|
+
var useMediaDimensionsLogic = function useMediaDimensionsLogic(_ref4) {
|
|
194
|
+
var childMediaNodeAttrs = _ref4.childMediaNodeAttrs;
|
|
195
|
+
var originalWidth = childMediaNodeAttrs.width,
|
|
196
|
+
originalHeight = childMediaNodeAttrs.height;
|
|
197
|
+
var isExternalMedia = childMediaNodeAttrs.type === 'external';
|
|
198
|
+
var hasMediaUrlBlob = isExternalMedia && typeof childMediaNodeAttrs.url === 'string' && isMediaBlobUrlFromAttrs(childMediaNodeAttrs);
|
|
199
|
+
var urlBlobAttrs = React.useMemo(function () {
|
|
200
|
+
if (!hasMediaUrlBlob) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
return getAttrsFromUrl(childMediaNodeAttrs.url);
|
|
204
|
+
}, [hasMediaUrlBlob, childMediaNodeAttrs]);
|
|
205
|
+
var _React$useMemo = React.useMemo(function () {
|
|
206
|
+
// original width and height of child media node (scaled)
|
|
207
|
+
var width = originalWidth;
|
|
208
|
+
var height = originalHeight;
|
|
209
|
+
if (isExternalMedia) {
|
|
210
|
+
if (urlBlobAttrs) {
|
|
211
|
+
if (urlBlobAttrs) {
|
|
212
|
+
var urlWidth = urlBlobAttrs.width,
|
|
213
|
+
urlHeight = urlBlobAttrs.height;
|
|
214
|
+
width = width || urlWidth;
|
|
215
|
+
height = height || urlHeight;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (width === null) {
|
|
219
|
+
width = DEFAULT_IMAGE_WIDTH;
|
|
220
|
+
}
|
|
221
|
+
if (height === null) {
|
|
222
|
+
height = DEFAULT_IMAGE_HEIGHT;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!width || !height) {
|
|
226
|
+
width = DEFAULT_IMAGE_WIDTH;
|
|
227
|
+
height = DEFAULT_IMAGE_HEIGHT;
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
width: width,
|
|
231
|
+
height: height
|
|
232
|
+
};
|
|
233
|
+
}, [originalWidth, originalHeight, isExternalMedia, urlBlobAttrs]),
|
|
234
|
+
width = _React$useMemo.width,
|
|
235
|
+
height = _React$useMemo.height;
|
|
236
|
+
return {
|
|
237
|
+
width: width,
|
|
238
|
+
height: height
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
var useUpdateSizeCallback = function useUpdateSizeCallback(_ref5) {
|
|
242
|
+
var mediaNode = _ref5.mediaNode,
|
|
243
|
+
view = _ref5.view,
|
|
244
|
+
getPos = _ref5.getPos;
|
|
245
|
+
var updateSize = React.useCallback(function (width, layout) {
|
|
246
|
+
var state = view.state,
|
|
247
|
+
dispatch = view.dispatch;
|
|
248
|
+
var pos = getPos();
|
|
249
|
+
if (typeof pos === 'undefined') {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
var tr = state.tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, mediaNode.attrs), {}, {
|
|
253
|
+
layout: layout,
|
|
254
|
+
width: width,
|
|
255
|
+
widthType: 'pixel'
|
|
256
|
+
}));
|
|
257
|
+
tr.setMeta('scrollIntoView', false);
|
|
258
|
+
/**
|
|
259
|
+
* Any changes to attributes of a node count the node as "recreated" in Prosemirror[1]
|
|
260
|
+
* This makes it so Prosemirror resets the selection to the child i.e. "media" instead of "media-single"
|
|
261
|
+
* The recommended fix is to reset the selection.[2]
|
|
262
|
+
*
|
|
263
|
+
* [1] https://discuss.prosemirror.net/t/setnodemarkup-loses-current-nodeselection/976
|
|
264
|
+
* [2] https://discuss.prosemirror.net/t/setnodemarkup-and-deselect/3673
|
|
265
|
+
*/
|
|
266
|
+
tr.setSelection(NodeSelection.create(tr.doc, pos));
|
|
267
|
+
return dispatch(tr);
|
|
268
|
+
}, [view, getPos, mediaNode]);
|
|
269
|
+
return updateSize;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* This value is used to fallback when widthState is undefined.
|
|
274
|
+
*
|
|
275
|
+
* Previously, the old MediaSingle was ignoring the undefined situation:
|
|
276
|
+
*
|
|
277
|
+
* <MediaSingleNode
|
|
278
|
+
* width={widthState!.width}
|
|
279
|
+
* lineLength={widthState!.lineLength}
|
|
280
|
+
*/
|
|
281
|
+
var FALLBACK_MOST_COMMON_WIDTH = 760;
|
|
282
|
+
export var MediaSingleNodeNext = function MediaSingleNodeNext(mediaSingleNodeNextProps) {
|
|
283
|
+
var _mediaOptions$getEdit, _pluginInjectionApi$m, _mediaNode$firstChild2;
|
|
284
|
+
var selected = mediaSingleNodeNextProps.selected,
|
|
285
|
+
getPos = mediaSingleNodeNextProps.getPos,
|
|
286
|
+
nextMediaNode = mediaSingleNodeNextProps.node,
|
|
287
|
+
mediaOptions = mediaSingleNodeNextProps.mediaOptions,
|
|
288
|
+
fullWidthMode = mediaSingleNodeNextProps.fullWidthMode,
|
|
289
|
+
view = mediaSingleNodeNextProps.view,
|
|
290
|
+
pluginInjectionApi = mediaSingleNodeNextProps.pluginInjectionApi,
|
|
291
|
+
containerWidth = mediaSingleNodeNextProps.width,
|
|
292
|
+
lineLength = mediaSingleNodeNextProps.lineLength,
|
|
293
|
+
dispatchAnalyticsEvent = mediaSingleNodeNextProps.dispatchAnalyticsEvent,
|
|
294
|
+
editorViewMode = mediaSingleNodeNextProps.editorViewMode,
|
|
295
|
+
editorDisabled = mediaSingleNodeNextProps.editorDisabled,
|
|
296
|
+
annotationPluginState = mediaSingleNodeNextProps.annotationPluginState,
|
|
297
|
+
editorAppearance = mediaSingleNodeNextProps.editorAppearance,
|
|
298
|
+
mediaProviderPromise = mediaSingleNodeNextProps.mediaProvider,
|
|
299
|
+
forwardRef = mediaSingleNodeNextProps.forwardRef,
|
|
300
|
+
contextIdentifierProviderPromise = mediaSingleNodeNextProps.contextIdentifierProvider,
|
|
301
|
+
mediaPluginState = mediaSingleNodeNextProps.mediaPluginState;
|
|
302
|
+
var _ref6 = (mediaOptions === null || mediaOptions === void 0 || (_mediaOptions$getEdit = mediaOptions.getEditorFeatureFlags) === null || _mediaOptions$getEdit === void 0 ? void 0 : _mediaOptions$getEdit.call(mediaOptions)) || {},
|
|
303
|
+
_ref6$commentsOnMedia = _ref6.commentsOnMedia,
|
|
304
|
+
commentsOnMedia = _ref6$commentsOnMedia === void 0 ? false : _ref6$commentsOnMedia;
|
|
305
|
+
var _React$useState3 = React.useState(null),
|
|
306
|
+
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
307
|
+
mediaProvider = _React$useState4[0],
|
|
308
|
+
setMediaProvider = _React$useState4[1];
|
|
309
|
+
var _React$useState5 = React.useState(null),
|
|
310
|
+
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
311
|
+
_contextIdentifierProvider = _React$useState6[0],
|
|
312
|
+
setContextIdentifierProvider = _React$useState6[1];
|
|
313
|
+
var _React$useState7 = React.useState(),
|
|
314
|
+
_React$useState8 = _slicedToArray(_React$useState7, 2),
|
|
315
|
+
viewMediaClientConfig = _React$useState8[0],
|
|
316
|
+
setViewMediaClientConfig = _React$useState8[1];
|
|
317
|
+
var mountedRef = React.useRef(true);
|
|
318
|
+
var pos = getPos();
|
|
319
|
+
var isSelected = selected();
|
|
320
|
+
var contentWidthForLegacyExperience = getMaxWidthForNestedNode(view, getPos()) || lineLength;
|
|
321
|
+
var mediaNode = useLatestMediaNode(nextMediaNode);
|
|
322
|
+
var mediaNodeUpdater = useMediaNodeUpdater({
|
|
323
|
+
mediaNode: mediaNode,
|
|
324
|
+
mediaSingleNodeProps: mediaSingleNodeNextProps,
|
|
325
|
+
mediaProvider: mediaProvider,
|
|
326
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent
|
|
327
|
+
});
|
|
328
|
+
useMediaAsyncOperations({
|
|
329
|
+
mediaNodeUpdater: mediaNodeUpdater,
|
|
330
|
+
getPos: getPos,
|
|
331
|
+
mediaNode: mediaNode,
|
|
332
|
+
addPendingTask: (mediaPluginState === null || mediaPluginState === void 0 ? void 0 : mediaPluginState.addPendingTask) || noop
|
|
333
|
+
});
|
|
334
|
+
React.useLayoutEffect(function () {
|
|
335
|
+
mountedRef.current = true;
|
|
336
|
+
return function () {
|
|
337
|
+
mountedRef.current = false;
|
|
338
|
+
};
|
|
339
|
+
}, []);
|
|
340
|
+
React.useLayoutEffect(function () {
|
|
341
|
+
if (!mediaProviderPromise) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
mediaProviderPromise.then(function (resolvedProvider) {
|
|
345
|
+
var viewMediaClientConfig = resolvedProvider.viewMediaClientConfig;
|
|
346
|
+
if (mountedRef.current) {
|
|
347
|
+
setViewMediaClientConfig(viewMediaClientConfig);
|
|
348
|
+
setMediaProvider(resolvedProvider);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}, [mediaProviderPromise]);
|
|
352
|
+
React.useEffect(function () {
|
|
353
|
+
if (!contextIdentifierProviderPromise) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
contextIdentifierProviderPromise.then(function (provider) {
|
|
357
|
+
if (mountedRef.current) {
|
|
358
|
+
setContextIdentifierProvider(provider);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}, [contextIdentifierProviderPromise]);
|
|
362
|
+
React.useEffect(function () {
|
|
363
|
+
var _mediaNode$firstChild;
|
|
364
|
+
// No-op but logging an exposure when an external image is rendered
|
|
365
|
+
// Remove this block when cleaning up platform_editor_add_media_from_url
|
|
366
|
+
if (((_mediaNode$firstChild = mediaNode.firstChild) === null || _mediaNode$firstChild === void 0 ? void 0 : _mediaNode$firstChild.attrs.type) === 'external') {
|
|
367
|
+
if (editorExperiment('add-media-from-url', true)) {
|
|
368
|
+
editorExperiment('add-media-from-url', true, {
|
|
369
|
+
exposure: true
|
|
370
|
+
});
|
|
371
|
+
} else {
|
|
372
|
+
editorExperiment('add-media-from-url', false, {
|
|
373
|
+
exposure: true
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}, [mediaNode]);
|
|
378
|
+
var _ref7 = mediaNode.attrs,
|
|
379
|
+
layout = _ref7.layout,
|
|
380
|
+
widthType = _ref7.widthType,
|
|
381
|
+
mediaSingleWidthAttribute = _ref7.width;
|
|
382
|
+
var childNode = mediaNode.firstChild;
|
|
383
|
+
var childMediaNodeAttrs = React.useMemo(function () {
|
|
384
|
+
return (childNode === null || childNode === void 0 ? void 0 : childNode.attrs) || {};
|
|
385
|
+
}, [childNode]);
|
|
386
|
+
var _useMediaDimensionsLo = useMediaDimensionsLogic({
|
|
387
|
+
childMediaNodeAttrs: childMediaNodeAttrs
|
|
388
|
+
}),
|
|
389
|
+
width = _useMediaDimensionsLo.width,
|
|
390
|
+
height = _useMediaDimensionsLo.height;
|
|
391
|
+
var updateSize = useUpdateSizeCallback({
|
|
392
|
+
view: view,
|
|
393
|
+
getPos: getPos,
|
|
394
|
+
mediaNode: mediaNode
|
|
395
|
+
});
|
|
396
|
+
var canResize = React.useMemo(function () {
|
|
397
|
+
if (typeof pos !== 'number') {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
var result = Boolean(!!mediaOptions.allowResizing && !editorDisabled && !editorViewMode);
|
|
401
|
+
if (mediaOptions.allowResizingInTables) {
|
|
402
|
+
return result;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// If resizing not allowed in tables, check parents for tables
|
|
406
|
+
var $pos = view.state.doc.resolve(pos);
|
|
407
|
+
var table = view.state.schema.nodes.table;
|
|
408
|
+
var disabledNode = !!findParentNodeOfTypeClosestToPos($pos, [table]);
|
|
409
|
+
return Boolean(result && !disabledNode);
|
|
410
|
+
}, [mediaOptions, pos, view, editorDisabled, editorViewMode]);
|
|
411
|
+
var badgeOffsetRight = React.useMemo(function () {
|
|
412
|
+
if (typeof pos !== 'number') {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
var $pos = view.state.doc.resolve(pos);
|
|
416
|
+
var table = view.state.schema.nodes.table;
|
|
417
|
+
var foundTableNode = findParentNodeOfTypeClosestToPos($pos, [table]);
|
|
418
|
+
return foundTableNode ? '2px' : '14px';
|
|
419
|
+
}, [pos, view]);
|
|
420
|
+
var shouldShowPlaceholder = React.useMemo(function () {
|
|
421
|
+
var result = mediaOptions.allowCaptions && mediaNode.childCount !== 2 && isSelected && view.state.selection instanceof NodeSelection;
|
|
422
|
+
return !editorDisabled && result;
|
|
423
|
+
}, [editorDisabled, mediaOptions.allowCaptions, mediaNode, view, isSelected]);
|
|
424
|
+
var isInsideTable = React.useMemo(function () {
|
|
425
|
+
if (typeof pos !== 'number') {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
return findParentNodeOfTypeClosestToPos(view.state.doc.resolve(pos), [view.state.schema.nodes.table]);
|
|
429
|
+
}, [pos, view]);
|
|
430
|
+
var currentMediaElement = React.useCallback(function () {
|
|
431
|
+
if (typeof pos !== 'number') {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
var mediaNode = view.domAtPos(pos + 1).node;
|
|
435
|
+
return mediaNode instanceof HTMLElement ? mediaNode : null;
|
|
436
|
+
}, [view, pos]);
|
|
437
|
+
var mediaSingleWidth = React.useMemo(function () {
|
|
438
|
+
return calcMediaSinglePixelWidth({
|
|
439
|
+
width: mediaSingleWidthAttribute,
|
|
440
|
+
widthType: widthType,
|
|
441
|
+
origWidth: width,
|
|
442
|
+
layout: layout,
|
|
443
|
+
// This will only be used when calculating legacy media single width
|
|
444
|
+
// thus we use the legacy value (exclude table as container node)
|
|
445
|
+
contentWidth: contentWidthForLegacyExperience,
|
|
446
|
+
containerWidth: containerWidth,
|
|
447
|
+
gutterOffset: MEDIA_SINGLE_GUTTER_SIZE
|
|
448
|
+
});
|
|
449
|
+
}, [mediaSingleWidthAttribute, widthType, width, layout, contentWidthForLegacyExperience, containerWidth]);
|
|
450
|
+
var currentMaxWidth = isSelected ? pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$m = pluginInjectionApi.media) === null || _pluginInjectionApi$m === void 0 || (_pluginInjectionApi$m = _pluginInjectionApi$m.sharedState.currentState()) === null || _pluginInjectionApi$m === void 0 ? void 0 : _pluginInjectionApi$m.currentMaxWidth : undefined;
|
|
451
|
+
var contentWidth = currentMaxWidth || lineLength;
|
|
452
|
+
var isCurrentNodeDrafting = Boolean((annotationPluginState === null || annotationPluginState === void 0 ? void 0 : annotationPluginState.isDrafting) && (annotationPluginState === null || annotationPluginState === void 0 ? void 0 : annotationPluginState.targetNodeId) === (mediaNode === null || mediaNode === void 0 || (_mediaNode$firstChild2 = mediaNode.firstChild) === null || _mediaNode$firstChild2 === void 0 ? void 0 : _mediaNode$firstChild2.attrs.id));
|
|
453
|
+
var shouldShowExternalMediaBadge = childMediaNodeAttrs.type === 'external';
|
|
454
|
+
var mediaSingleWrapperRef = /*#__PURE__*/React.createRef();
|
|
455
|
+
var captionPlaceHolderRef = /*#__PURE__*/React.createRef();
|
|
456
|
+
var onMediaSingleClicked = React.useCallback(function (event) {
|
|
457
|
+
var _captionPlaceHolderRe;
|
|
458
|
+
// Workaround for iOS 16 Caption selection issue
|
|
459
|
+
// @see https://product-fabric.atlassian.net/browse/MEX-2012
|
|
460
|
+
if (!browser.ios) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (mediaSingleWrapperRef.current !== event.target) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
(_captionPlaceHolderRe = captionPlaceHolderRef.current) === null || _captionPlaceHolderRe === void 0 || _captionPlaceHolderRe.click();
|
|
467
|
+
}, [mediaSingleWrapperRef, captionPlaceHolderRef]);
|
|
468
|
+
var clickPlaceholder = React.useCallback(function () {
|
|
469
|
+
var _pluginInjectionApi$a;
|
|
470
|
+
if (typeof getPos === 'boolean') {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
insertAndSelectCaptionFromMediaSinglePos(pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions)(getPos(), mediaNode)(view.state, view.dispatch);
|
|
474
|
+
}, [view, getPos, mediaNode, pluginInjectionApi]);
|
|
475
|
+
var legacySize = React.useMemo(function () {
|
|
476
|
+
return {
|
|
477
|
+
width: mediaSingleWidthAttribute,
|
|
478
|
+
widthType: widthType
|
|
479
|
+
};
|
|
480
|
+
}, [widthType, mediaSingleWidthAttribute]);
|
|
481
|
+
var MediaChildren = jsx("figure", {
|
|
482
|
+
ref: mediaSingleWrapperRef,
|
|
483
|
+
css: figureWrapperStyles
|
|
484
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
|
|
485
|
+
,
|
|
486
|
+
className: MediaSingleNodeSelector,
|
|
487
|
+
onClick: onMediaSingleClicked
|
|
488
|
+
}, editorExperiment('add-media-from-url', true) && jsx(MediaBadges, {
|
|
489
|
+
mediaElement: currentMediaElement(),
|
|
490
|
+
mediaHeight: height,
|
|
491
|
+
mediaWidth: width,
|
|
492
|
+
extendedResizeOffset: fg('platform.editor.media.extended-resize-experience') && !isInsideTable
|
|
493
|
+
}, function (_ref8) {
|
|
494
|
+
var badgeSize = _ref8.badgeSize;
|
|
495
|
+
return jsx(React.Fragment, null, shouldShowExternalMediaBadge && jsx(ExternalImageBadge, {
|
|
496
|
+
badgeSize: badgeSize
|
|
497
|
+
}), commentsOnMedia && jsx(CommentBadgeNextWrapper, {
|
|
498
|
+
view: view,
|
|
499
|
+
api: pluginInjectionApi,
|
|
500
|
+
mediaNode: mediaNode === null || mediaNode === void 0 ? void 0 : mediaNode.firstChild,
|
|
501
|
+
getPos: getPos,
|
|
502
|
+
isDrafting: isCurrentNodeDrafting,
|
|
503
|
+
badgeSize: badgeSize
|
|
504
|
+
}));
|
|
505
|
+
}), !editorExperiment('add-media-from-url', true) && commentsOnMedia && jsx(CommentBadge, {
|
|
506
|
+
view: view,
|
|
507
|
+
api: pluginInjectionApi,
|
|
508
|
+
mediaNode: mediaNode === null || mediaNode === void 0 ? void 0 : mediaNode.firstChild,
|
|
509
|
+
badgeOffsetRight: badgeOffsetRight,
|
|
510
|
+
getPos: getPos,
|
|
511
|
+
isDrafting: isCurrentNodeDrafting
|
|
512
|
+
}), jsx("div", {
|
|
513
|
+
ref: forwardRef
|
|
514
|
+
}), shouldShowPlaceholder && (editorExperiment('typography_migration_ugc', true) ? jsx(CaptionPlaceholderButton
|
|
515
|
+
// platform_editor_typography_migration_ugc clean up
|
|
516
|
+
// remove typecasting
|
|
517
|
+
, {
|
|
518
|
+
ref: captionPlaceHolderRef,
|
|
519
|
+
onClick: clickPlaceholder
|
|
520
|
+
}) : jsx(CaptionPlaceholder, {
|
|
521
|
+
ref: captionPlaceHolderRef,
|
|
522
|
+
onClick: clickPlaceholder
|
|
523
|
+
})));
|
|
524
|
+
return jsx(Fragment, null, canResize ? fg('platform.editor.media.extended-resize-experience') ? jsx(ResizableMediaSingleNext, {
|
|
525
|
+
view: view,
|
|
526
|
+
getPos: getPos,
|
|
527
|
+
updateSize: updateSize,
|
|
528
|
+
gridSize: 12,
|
|
529
|
+
viewMediaClientConfig: viewMediaClientConfig,
|
|
530
|
+
allowBreakoutSnapPoints: mediaOptions && mediaOptions.allowBreakoutSnapPoints,
|
|
531
|
+
selected: isSelected,
|
|
532
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
533
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
534
|
+
layout: layout,
|
|
535
|
+
width: width,
|
|
536
|
+
height: height,
|
|
537
|
+
containerWidth: containerWidth,
|
|
538
|
+
lineLength: contentWidth || FALLBACK_MOST_COMMON_WIDTH,
|
|
539
|
+
fullWidthMode: fullWidthMode,
|
|
540
|
+
hasFallbackContainer: false,
|
|
541
|
+
mediaSingleWidth: mediaSingleWidth,
|
|
542
|
+
editorAppearance: editorAppearance,
|
|
543
|
+
showLegacyNotification: widthType !== 'pixel'
|
|
544
|
+
}, MediaChildren) : jsx(ResizableMediaSingle, {
|
|
545
|
+
view: view,
|
|
546
|
+
getPos: getPos,
|
|
547
|
+
updateSize: updateSize,
|
|
548
|
+
gridSize: 12,
|
|
549
|
+
viewMediaClientConfig: viewMediaClientConfig,
|
|
550
|
+
allowBreakoutSnapPoints: mediaOptions && mediaOptions.allowBreakoutSnapPoints,
|
|
551
|
+
selected: isSelected,
|
|
552
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
553
|
+
pluginInjectionApi: pluginInjectionApi,
|
|
554
|
+
layout: layout,
|
|
555
|
+
width: width,
|
|
556
|
+
height: height,
|
|
557
|
+
containerWidth: containerWidth,
|
|
558
|
+
fullWidthMode: fullWidthMode,
|
|
559
|
+
hasFallbackContainer: false,
|
|
560
|
+
mediaSingleWidth: mediaSingleWidth,
|
|
561
|
+
editorAppearance: editorAppearance,
|
|
562
|
+
lineLength: contentWidthForLegacyExperience || FALLBACK_MOST_COMMON_WIDTH,
|
|
563
|
+
pctWidth: mediaSingleWidthAttribute
|
|
564
|
+
}, MediaChildren) : jsx(MediaSingle, {
|
|
565
|
+
layout: layout,
|
|
566
|
+
width: width,
|
|
567
|
+
height: height,
|
|
568
|
+
containerWidth: containerWidth,
|
|
569
|
+
fullWidthMode: fullWidthMode,
|
|
570
|
+
hasFallbackContainer: false,
|
|
571
|
+
editorAppearance: editorAppearance,
|
|
572
|
+
pctWidth: mediaSingleWidthAttribute,
|
|
573
|
+
lineLength: lineLength || FALLBACK_MOST_COMMON_WIDTH,
|
|
574
|
+
size: legacySize
|
|
575
|
+
}, MediaChildren));
|
|
576
|
+
};
|