@atlaskit/editor-plugin-media-insert 2.1.2 → 2.3.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 (38) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cjs/plugin.js +48 -4
  3. package/dist/cjs/ui/LocalMedia.js +143 -0
  4. package/dist/cjs/ui/{FromURL.js → MediaFromURL.js} +50 -27
  5. package/dist/cjs/ui/MediaInsertContent.js +14 -6
  6. package/dist/cjs/ui/MediaInsertPicker.js +6 -2
  7. package/dist/cjs/ui/useAnalyticsEvents.js +26 -10
  8. package/dist/es2019/plugin.js +49 -3
  9. package/dist/es2019/ui/LocalMedia.js +137 -0
  10. package/dist/es2019/ui/{FromURL.js → MediaFromURL.js} +39 -16
  11. package/dist/es2019/ui/MediaInsertContent.js +14 -6
  12. package/dist/es2019/ui/MediaInsertPicker.js +6 -2
  13. package/dist/es2019/ui/useAnalyticsEvents.js +26 -10
  14. package/dist/esm/plugin.js +48 -4
  15. package/dist/esm/ui/LocalMedia.js +136 -0
  16. package/dist/esm/ui/{FromURL.js → MediaFromURL.js} +50 -27
  17. package/dist/esm/ui/MediaInsertContent.js +14 -6
  18. package/dist/esm/ui/MediaInsertPicker.js +6 -2
  19. package/dist/esm/ui/useAnalyticsEvents.js +26 -10
  20. package/dist/types/types.d.ts +13 -0
  21. package/dist/types/ui/LocalMedia.d.ts +12 -0
  22. package/dist/types/ui/MediaCard.d.ts +1 -1
  23. package/dist/types/ui/MediaFromURL.d.ts +13 -0
  24. package/dist/types/ui/MediaInsertContent.d.ts +8 -3
  25. package/dist/types/ui/MediaInsertPicker.d.ts +1 -1
  26. package/dist/types/ui/types.d.ts +3 -2
  27. package/dist/types/ui/useAnalyticsEvents.d.ts +6 -3
  28. package/dist/types-ts4.5/types.d.ts +13 -0
  29. package/dist/types-ts4.5/ui/LocalMedia.d.ts +12 -0
  30. package/dist/types-ts4.5/ui/MediaCard.d.ts +1 -1
  31. package/dist/types-ts4.5/ui/MediaFromURL.d.ts +13 -0
  32. package/dist/types-ts4.5/ui/MediaInsertContent.d.ts +8 -3
  33. package/dist/types-ts4.5/ui/MediaInsertPicker.d.ts +1 -1
  34. package/dist/types-ts4.5/ui/types.d.ts +3 -2
  35. package/dist/types-ts4.5/ui/useAnalyticsEvents.d.ts +6 -3
  36. package/package.json +6 -5
  37. package/dist/types/ui/FromURL.d.ts +0 -13
  38. package/dist/types-ts4.5/ui/FromURL.d.ts +0 -13
@@ -0,0 +1,137 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl-next';
3
+ import Button from '@atlaskit/button/new';
4
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
+ import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
6
+ import UploadIcon from '@atlaskit/icon/glyph/upload';
7
+ import { Browser } from '@atlaskit/media-picker';
8
+ import { Stack } from '@atlaskit/primitives';
9
+ import SectionMessage from '@atlaskit/section-message';
10
+ import { useAnalyticsEvents } from './useAnalyticsEvents';
11
+ const INITIAL_UPLOAD_STATE = Object.freeze({
12
+ isOpen: false,
13
+ error: null
14
+ });
15
+ const uploadReducer = (state, action) => {
16
+ switch (action.type) {
17
+ case 'open':
18
+ return {
19
+ ...INITIAL_UPLOAD_STATE,
20
+ isOpen: true
21
+ };
22
+ case 'close':
23
+ // This is the only case where we don't reset state. This is because
24
+ // onClose gets called for cancel _and_ upload, so we don't want to
25
+ // reset any loading or error states that may have occured
26
+ return {
27
+ ...state,
28
+ isOpen: false
29
+ };
30
+ case 'error':
31
+ return {
32
+ ...INITIAL_UPLOAD_STATE,
33
+ error: action.error
34
+ };
35
+ case 'reset':
36
+ return INITIAL_UPLOAD_STATE;
37
+ }
38
+ };
39
+ const isImagePreview = preview => {
40
+ return 'dimensions' in preview;
41
+ };
42
+ export const LocalMedia = ({
43
+ mediaProvider,
44
+ onInsert,
45
+ dispatchAnalyticsEvent
46
+ }) => {
47
+ const intl = useIntl();
48
+ const strings = {
49
+ upload: intl.formatMessage(mediaInsertMessages.upload),
50
+ networkError: intl.formatMessage(mediaInsertMessages.localFileNetworkErrorMessage),
51
+ genericError: intl.formatMessage(mediaInsertMessages.localFileErrorMessage)
52
+ };
53
+ const {
54
+ onUploadButtonClickedAnalytics,
55
+ onUploadCommencedAnalytics,
56
+ onUploadSuccessAnalytics,
57
+ onUploadFailureAnalytics
58
+ } = useAnalyticsEvents(dispatchAnalyticsEvent);
59
+ const [uploadState, dispatch] = React.useReducer(uploadReducer, INITIAL_UPLOAD_STATE);
60
+ const onUpload = ({
61
+ file,
62
+ preview
63
+ }) => {
64
+ var _mediaProvider$upload;
65
+ onUploadSuccessAnalytics('local');
66
+ const mediaState = {
67
+ id: file.id,
68
+ collection: (_mediaProvider$upload = mediaProvider.uploadParams) === null || _mediaProvider$upload === void 0 ? void 0 : _mediaProvider$upload.collection,
69
+ fileMimeType: file.type,
70
+ fileSize: file.size,
71
+ fileName: file.name,
72
+ dimensions: undefined
73
+ };
74
+ if (isImagePreview(preview)) {
75
+ mediaState.dimensions = {
76
+ width: preview.dimensions.width,
77
+ height: preview.dimensions.height
78
+ };
79
+ }
80
+ onInsert({
81
+ mediaState,
82
+ inputMethod: INPUT_METHOD.MEDIA_PICKER
83
+ });
84
+
85
+ // Probably not needed but I guess it _could_ fail to close for some reason
86
+ dispatch({
87
+ type: 'reset'
88
+ });
89
+ };
90
+ const {
91
+ uploadParams,
92
+ uploadMediaClientConfig
93
+ } = mediaProvider;
94
+ return /*#__PURE__*/React.createElement(Stack, {
95
+ grow: "fill",
96
+ space: "space.200"
97
+ }, uploadState.error && /*#__PURE__*/React.createElement(SectionMessage, {
98
+ appearance: "error"
99
+ }, uploadState.error === 'upload_fail' ? strings.networkError : strings.genericError), /*#__PURE__*/React.createElement(Button, {
100
+ iconBefore: UploadIcon,
101
+ shouldFitContainer: true,
102
+ isDisabled: !uploadMediaClientConfig || !uploadParams,
103
+ onClick: () => {
104
+ onUploadButtonClickedAnalytics();
105
+ dispatch({
106
+ type: 'open'
107
+ });
108
+ },
109
+ autoFocus: true
110
+ }, strings.upload), uploadMediaClientConfig && uploadParams && /*#__PURE__*/React.createElement(Browser, {
111
+ isOpen: uploadState.isOpen,
112
+ config: {
113
+ uploadParams: uploadParams
114
+ },
115
+ mediaClientConfig: uploadMediaClientConfig,
116
+ onUploadsStart: () => {
117
+ onUploadCommencedAnalytics('local');
118
+ },
119
+ onPreviewUpdate: onUpload
120
+ // NOTE: this will fire for some errors like network failures, but not
121
+ // for others like empty files. Those have their own feedback toast
122
+ // owned by media.
123
+ ,
124
+ onError: payload => {
125
+ onUploadFailureAnalytics(payload.error.name, 'local');
126
+ dispatch({
127
+ type: 'error',
128
+ error: payload.error.name
129
+ });
130
+ },
131
+ onClose: () => {
132
+ dispatch({
133
+ type: 'close'
134
+ });
135
+ }
136
+ }));
137
+ };
@@ -63,10 +63,10 @@ const previewStateReducer = (state, action) => {
63
63
  };
64
64
  export function MediaFromURL({
65
65
  mediaProvider,
66
- onInsert,
67
- onExternalInsert,
68
66
  dispatchAnalyticsEvent,
69
- closeMediaInsertPicker
67
+ closeMediaInsertPicker,
68
+ insertMediaSingle,
69
+ insertExternalMediaSingle
70
70
  }) {
71
71
  const intl = useIntl();
72
72
  const strings = {
@@ -74,18 +74,20 @@ export function MediaFromURL({
74
74
  insert: intl.formatMessage(mediaInsertMessages.insert),
75
75
  pasteLinkToUpload: intl.formatMessage(mediaInsertMessages.pasteLinkToUpload),
76
76
  cancel: intl.formatMessage(mediaInsertMessages.cancel),
77
- errorMessage: intl.formatMessage(mediaInsertMessages.errorMessage),
78
- warning: intl.formatMessage(mediaInsertMessages.warning)
77
+ errorMessage: intl.formatMessage(mediaInsertMessages.fromUrlErrorMessage),
78
+ warning: intl.formatMessage(mediaInsertMessages.fromUrlWarning)
79
79
  };
80
80
  const [inputUrl, setUrl] = React.useState('');
81
81
  const [previewState, dispatch] = React.useReducer(previewStateReducer, INITIAL_PREVIEW_STATE);
82
82
  const pasteFlag = React.useRef(false);
83
83
  const {
84
- onUploadAnalytics,
84
+ onUploadButtonClickedAnalytics,
85
+ onUploadCommencedAnalytics,
85
86
  onUploadSuccessAnalytics,
86
87
  onUploadFailureAnalytics
87
88
  } = useAnalyticsEvents(dispatchAnalyticsEvent);
88
89
  const uploadExternalMedia = React.useCallback(async url => {
90
+ onUploadButtonClickedAnalytics();
89
91
  dispatch({
90
92
  type: 'loading'
91
93
  });
@@ -98,13 +100,14 @@ export function MediaFromURL({
98
100
  }
99
101
  const mediaClient = getMediaClient(uploadMediaClientConfig);
100
102
  const collection = uploadParams === null || uploadParams === void 0 ? void 0 : uploadParams.collection;
101
- onUploadAnalytics();
103
+ onUploadCommencedAnalytics('url');
102
104
  try {
103
105
  const {
104
106
  uploadableFileUpfrontIds,
105
- dimensions
107
+ dimensions,
108
+ mimeType
106
109
  } = await mediaClient.file.uploadExternal(url, collection);
107
- onUploadSuccessAnalytics();
110
+ onUploadSuccessAnalytics('url');
108
111
  dispatch({
109
112
  type: 'success',
110
113
  payload: {
@@ -112,7 +115,8 @@ export function MediaFromURL({
112
115
  collection,
113
116
  height: dimensions.height,
114
117
  width: dimensions.width,
115
- occurrenceKey: uploadableFileUpfrontIds.occurrenceKey
118
+ occurrenceKey: uploadableFileUpfrontIds.occurrenceKey,
119
+ fileMimeType: mimeType
116
120
  }
117
121
  });
118
122
  } catch (e) {
@@ -120,7 +124,7 @@ export function MediaFromURL({
120
124
  // TODO: Make sure this gets good unit test coverage with the actual
121
125
  // media plugin. This hard coded error message could be changed at any
122
126
  // point and we need a unit test to break to stop people changing it.
123
- onUploadFailureAnalytics(e);
127
+ onUploadFailureAnalytics(e, 'url');
124
128
  dispatch({
125
129
  type: 'warning',
126
130
  warning: e,
@@ -128,20 +132,20 @@ export function MediaFromURL({
128
132
  });
129
133
  } else if (e instanceof Error) {
130
134
  const message = 'Image preview fetch failed';
131
- onUploadFailureAnalytics(message);
135
+ onUploadFailureAnalytics(message, 'url');
132
136
  dispatch({
133
137
  type: 'error',
134
138
  error: message
135
139
  });
136
140
  } else {
137
- onUploadFailureAnalytics('Unknown error');
141
+ onUploadFailureAnalytics('Unknown error', 'url');
138
142
  dispatch({
139
143
  type: 'error',
140
144
  error: 'Unknown error'
141
145
  });
142
146
  }
143
147
  }
144
- }, [mediaProvider, onUploadAnalytics, onUploadFailureAnalytics, onUploadSuccessAnalytics, inputUrl]);
148
+ }, [onUploadButtonClickedAnalytics, mediaProvider, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics, inputUrl]);
145
149
  const onURLChange = React.useCallback(e => {
146
150
  const url = e.target.value;
147
151
  setUrl(url);
@@ -164,14 +168,33 @@ export function MediaFromURL({
164
168
  pasteFlag.current = true;
165
169
  }
166
170
  }, [inputUrl]);
171
+ const onInsert = React.useCallback(() => {
172
+ if (previewState.previewInfo) {
173
+ insertMediaSingle({
174
+ mediaState: previewState.previewInfo,
175
+ inputMethod: INPUT_METHOD.MEDIA_PICKER
176
+ });
177
+ }
178
+ closeMediaInsertPicker();
179
+ }, [closeMediaInsertPicker, insertMediaSingle, previewState.previewInfo]);
180
+ const onExternalInsert = React.useCallback(url => {
181
+ if (previewState.warning) {
182
+ insertExternalMediaSingle({
183
+ url,
184
+ alt: url,
185
+ inputMethod: INPUT_METHOD.MEDIA_PICKER
186
+ });
187
+ }
188
+ closeMediaInsertPicker();
189
+ }, [closeMediaInsertPicker, insertExternalMediaSingle, previewState.warning]);
167
190
  const onInsertClick = React.useCallback(() => {
168
191
  if (previewState.previewInfo) {
169
- return onInsert(previewState.previewInfo);
192
+ return onInsert();
170
193
  }
171
194
  if (previewState.warning) {
172
195
  return onExternalInsert(inputUrl);
173
196
  }
174
- }, [onExternalInsert, onInsert, previewState.previewInfo, previewState.warning, inputUrl]);
197
+ }, [previewState.previewInfo, previewState.warning, onInsert, onExternalInsert, inputUrl]);
175
198
  const onInputKeyPress = React.useCallback(event => {
176
199
  if (event && event.key === 'Esc') {
177
200
  if (dispatchAnalyticsEvent) {
@@ -3,22 +3,30 @@ import { useIntl } from 'react-intl-next';
3
3
  import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
4
4
  import { Box } from '@atlaskit/primitives';
5
5
  import Tabs, { Tab, TabList, TabPanel } from '@atlaskit/tabs';
6
- import { MediaFromURL } from './FromURL';
6
+ import { LocalMedia } from './LocalMedia';
7
+ import { MediaFromURL } from './MediaFromURL';
7
8
  export const MediaInsertContent = ({
8
9
  mediaProvider,
9
10
  dispatchAnalyticsEvent,
10
- closeMediaInsertPicker
11
+ closeMediaInsertPicker,
12
+ insertMediaSingle,
13
+ insertExternalMediaSingle
11
14
  }) => {
12
15
  const intl = useIntl();
13
16
  return /*#__PURE__*/React.createElement(Tabs, {
14
17
  id: "media-insert-tab-navigation"
15
18
  }, /*#__PURE__*/React.createElement(Box, {
16
19
  paddingBlockEnd: "space.150"
17
- }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
20
+ }, /*#__PURE__*/React.createElement(TabList, null, /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.fileTabTitle)), /*#__PURE__*/React.createElement(Tab, null, intl.formatMessage(mediaInsertMessages.linkTabTitle)))), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(LocalMedia, {
21
+ mediaProvider: mediaProvider,
22
+ onInsert: insertMediaSingle,
23
+ onClose: closeMediaInsertPicker,
24
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent
25
+ })), /*#__PURE__*/React.createElement(TabPanel, null, /*#__PURE__*/React.createElement(MediaFromURL, {
18
26
  mediaProvider: mediaProvider,
19
- onExternalInsert: () => {},
20
- onInsert: () => {},
21
27
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
22
- closeMediaInsertPicker: closeMediaInsertPicker
28
+ closeMediaInsertPicker: closeMediaInsertPicker,
29
+ insertMediaSingle: insertMediaSingle,
30
+ insertExternalMediaSingle: insertExternalMediaSingle
23
31
  })));
24
32
  };
@@ -40,7 +40,9 @@ export const MediaInsertPicker = ({
40
40
  popupsMountPoint,
41
41
  popupsBoundariesElement,
42
42
  popupsScrollableElement,
43
- closeMediaInsertPicker
43
+ closeMediaInsertPicker,
44
+ insertMediaSingle,
45
+ insertExternalMediaSingle
44
46
  }) => {
45
47
  var _useSharedPluginState, _useSharedPluginState2, _useSharedPluginState3, _useSharedPluginState4;
46
48
  const targetRef = getDomRefFromSelection(editorView, dispatchAnalyticsEvent);
@@ -90,6 +92,8 @@ export const MediaInsertPicker = ({
90
92
  closeMediaInsertPicker: () => {
91
93
  closeMediaInsertPicker();
92
94
  focusEditor();
93
- }
95
+ },
96
+ insertMediaSingle: insertMediaSingle,
97
+ insertExternalMediaSingle: insertExternalMediaSingle
94
98
  })));
95
99
  };
@@ -1,36 +1,52 @@
1
1
  import React from 'react';
2
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  export function useAnalyticsEvents(dispatchAnalyticsEvent) {
4
- const onUploadAnalytics = React.useCallback(() => {
4
+ const onUploadButtonClickedAnalytics = React.useCallback(() => {
5
5
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
6
6
  action: ACTION.CLICKED,
7
7
  actionSubject: ACTION_SUBJECT.BUTTON,
8
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
8
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
9
9
  eventType: EVENT_TYPE.UI
10
10
  });
11
11
  }, [dispatchAnalyticsEvent]);
12
- const onUploadSuccessAnalytics = React.useCallback(() => {
12
+ const onUploadCommencedAnalytics = React.useCallback(mediaUploadSource => {
13
+ dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
14
+ action: ACTION.UPLOAD_COMMENCED,
15
+ actionSubject: ACTION_SUBJECT.MEDIA,
16
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
17
+ eventType: EVENT_TYPE.OPERATIONAL,
18
+ attributes: {
19
+ mediaUploadSource
20
+ }
21
+ });
22
+ }, [dispatchAnalyticsEvent]);
23
+ const onUploadSuccessAnalytics = React.useCallback(mediaUploadSource => {
13
24
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
14
25
  action: ACTION.UPLOAD_SUCCEEDED,
15
26
  actionSubject: ACTION_SUBJECT.MEDIA,
16
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
17
- eventType: EVENT_TYPE.OPERATIONAL
27
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
28
+ eventType: EVENT_TYPE.OPERATIONAL,
29
+ attributes: {
30
+ mediaUploadSource
31
+ }
18
32
  });
19
33
  }, [dispatchAnalyticsEvent]);
20
- const onUploadFailureAnalytics = React.useCallback(reason => {
34
+ const onUploadFailureAnalytics = React.useCallback((reason, mediaUploadSource) => {
21
35
  dispatchAnalyticsEvent === null || dispatchAnalyticsEvent === void 0 ? void 0 : dispatchAnalyticsEvent({
22
36
  action: ACTION.UPLOAD_FAILED,
23
37
  actionSubject: ACTION_SUBJECT.MEDIA,
24
- actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA_FROM_URL,
38
+ actionSubjectId: ACTION_SUBJECT_ID.UPLOAD_MEDIA,
25
39
  eventType: EVENT_TYPE.OPERATIONAL,
26
40
  attributes: {
27
- reason
41
+ reason,
42
+ mediaUploadSource
28
43
  }
29
44
  });
30
45
  }, [dispatchAnalyticsEvent]);
31
46
  return React.useMemo(() => ({
32
- onUploadAnalytics,
47
+ onUploadButtonClickedAnalytics,
48
+ onUploadCommencedAnalytics,
33
49
  onUploadSuccessAnalytics,
34
50
  onUploadFailureAnalytics
35
- }), [onUploadAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
51
+ }), [onUploadButtonClickedAnalytics, onUploadCommencedAnalytics, onUploadSuccessAnalytics, onUploadFailureAnalytics]);
36
52
  }
@@ -36,6 +36,48 @@ export var mediaInsertPlugin = function mediaInsertPlugin(_ref) {
36
36
  popupsMountPoint = _ref3.popupsMountPoint,
37
37
  popupsBoundariesElement = _ref3.popupsBoundariesElement,
38
38
  popupsScrollableElement = _ref3.popupsScrollableElement;
39
+ var insertMediaSingle = function insertMediaSingle(_ref4) {
40
+ var _api$media$actions$in;
41
+ var mediaState = _ref4.mediaState,
42
+ inputMethod = _ref4.inputMethod;
43
+ var id = mediaState.id,
44
+ dimensions = mediaState.dimensions,
45
+ contextId = mediaState.contextId,
46
+ _mediaState$scaleFact = mediaState.scaleFactor,
47
+ scaleFactor = _mediaState$scaleFact === void 0 ? 1 : _mediaState$scaleFact,
48
+ fileName = mediaState.fileName,
49
+ collection = mediaState.collection;
50
+ var _ref5 = dimensions || {
51
+ height: undefined,
52
+ width: undefined
53
+ },
54
+ width = _ref5.width,
55
+ height = _ref5.height;
56
+ var scaledWidth = width && Math.round(width / scaleFactor);
57
+ var node = editorView.state.schema.nodes.media.create({
58
+ id: id,
59
+ type: 'file',
60
+ collection: collection,
61
+ contextId: contextId,
62
+ width: scaledWidth,
63
+ height: height && Math.round(height / scaleFactor),
64
+ alt: fileName,
65
+ __fileMimeType: mediaState.fileMimeType
66
+ });
67
+ return (_api$media$actions$in = api === null || api === void 0 ? void 0 : api.media.actions.insertMediaAsMediaSingle(editorView, node, inputMethod)) !== null && _api$media$actions$in !== void 0 ? _api$media$actions$in : false;
68
+ };
69
+ var insertExternalMediaSingle = function insertExternalMediaSingle(_ref6) {
70
+ var _api$media$actions$in2;
71
+ var url = _ref6.url,
72
+ alt = _ref6.alt,
73
+ inputMethod = _ref6.inputMethod;
74
+ var node = editorView.state.schema.nodes.media.create({
75
+ type: 'external',
76
+ url: url,
77
+ alt: alt
78
+ });
79
+ return (_api$media$actions$in2 = api === null || api === void 0 ? void 0 : api.media.actions.insertMediaAsMediaSingle(editorView, node, inputMethod)) !== null && _api$media$actions$in2 !== void 0 ? _api$media$actions$in2 : false;
80
+ };
39
81
  return /*#__PURE__*/React.createElement(MediaInsertPicker, {
40
82
  api: api,
41
83
  editorView: editorView,
@@ -44,13 +86,15 @@ export var mediaInsertPlugin = function mediaInsertPlugin(_ref) {
44
86
  popupsBoundariesElement: popupsBoundariesElement,
45
87
  popupsScrollableElement: popupsScrollableElement,
46
88
  closeMediaInsertPicker: function closeMediaInsertPicker() {
47
- editorView.dispatch(_closeMediaInsertPicker(editorView.state.tr));
48
- }
89
+ return editorView.dispatch(_closeMediaInsertPicker(editorView.state.tr));
90
+ },
91
+ insertMediaSingle: insertMediaSingle,
92
+ insertExternalMediaSingle: insertExternalMediaSingle
49
93
  });
50
94
  },
51
95
  pluginsOptions: {
52
- quickInsert: function quickInsert(_ref4) {
53
- var formatMessage = _ref4.formatMessage;
96
+ quickInsert: function quickInsert(_ref7) {
97
+ var formatMessage = _ref7.formatMessage;
54
98
  return [{
55
99
  id: 'media-insert',
56
100
  title: formatMessage(messages.insertMediaFromUrl),
@@ -0,0 +1,136 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ import React from 'react';
6
+ import { useIntl } from 'react-intl-next';
7
+ import Button from '@atlaskit/button/new';
8
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
9
+ import { mediaInsertMessages } from '@atlaskit/editor-common/messages';
10
+ import UploadIcon from '@atlaskit/icon/glyph/upload';
11
+ import { Browser } from '@atlaskit/media-picker';
12
+ import { Stack } from '@atlaskit/primitives';
13
+ import SectionMessage from '@atlaskit/section-message';
14
+ import { useAnalyticsEvents } from './useAnalyticsEvents';
15
+ var INITIAL_UPLOAD_STATE = Object.freeze({
16
+ isOpen: false,
17
+ error: null
18
+ });
19
+ var uploadReducer = function uploadReducer(state, action) {
20
+ switch (action.type) {
21
+ case 'open':
22
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
23
+ isOpen: true
24
+ });
25
+ case 'close':
26
+ // This is the only case where we don't reset state. This is because
27
+ // onClose gets called for cancel _and_ upload, so we don't want to
28
+ // reset any loading or error states that may have occured
29
+ return _objectSpread(_objectSpread({}, state), {}, {
30
+ isOpen: false
31
+ });
32
+ case 'error':
33
+ return _objectSpread(_objectSpread({}, INITIAL_UPLOAD_STATE), {}, {
34
+ error: action.error
35
+ });
36
+ case 'reset':
37
+ return INITIAL_UPLOAD_STATE;
38
+ }
39
+ };
40
+ var isImagePreview = function isImagePreview(preview) {
41
+ return 'dimensions' in preview;
42
+ };
43
+ export var LocalMedia = function LocalMedia(_ref) {
44
+ var mediaProvider = _ref.mediaProvider,
45
+ onInsert = _ref.onInsert,
46
+ dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent;
47
+ var intl = useIntl();
48
+ var strings = {
49
+ upload: intl.formatMessage(mediaInsertMessages.upload),
50
+ networkError: intl.formatMessage(mediaInsertMessages.localFileNetworkErrorMessage),
51
+ genericError: intl.formatMessage(mediaInsertMessages.localFileErrorMessage)
52
+ };
53
+ var _useAnalyticsEvents = useAnalyticsEvents(dispatchAnalyticsEvent),
54
+ onUploadButtonClickedAnalytics = _useAnalyticsEvents.onUploadButtonClickedAnalytics,
55
+ onUploadCommencedAnalytics = _useAnalyticsEvents.onUploadCommencedAnalytics,
56
+ onUploadSuccessAnalytics = _useAnalyticsEvents.onUploadSuccessAnalytics,
57
+ onUploadFailureAnalytics = _useAnalyticsEvents.onUploadFailureAnalytics;
58
+ var _React$useReducer = React.useReducer(uploadReducer, INITIAL_UPLOAD_STATE),
59
+ _React$useReducer2 = _slicedToArray(_React$useReducer, 2),
60
+ uploadState = _React$useReducer2[0],
61
+ dispatch = _React$useReducer2[1];
62
+ var onUpload = function onUpload(_ref2) {
63
+ var _mediaProvider$upload;
64
+ var file = _ref2.file,
65
+ preview = _ref2.preview;
66
+ onUploadSuccessAnalytics('local');
67
+ var mediaState = {
68
+ id: file.id,
69
+ collection: (_mediaProvider$upload = mediaProvider.uploadParams) === null || _mediaProvider$upload === void 0 ? void 0 : _mediaProvider$upload.collection,
70
+ fileMimeType: file.type,
71
+ fileSize: file.size,
72
+ fileName: file.name,
73
+ dimensions: undefined
74
+ };
75
+ if (isImagePreview(preview)) {
76
+ mediaState.dimensions = {
77
+ width: preview.dimensions.width,
78
+ height: preview.dimensions.height
79
+ };
80
+ }
81
+ onInsert({
82
+ mediaState: mediaState,
83
+ inputMethod: INPUT_METHOD.MEDIA_PICKER
84
+ });
85
+
86
+ // Probably not needed but I guess it _could_ fail to close for some reason
87
+ dispatch({
88
+ type: 'reset'
89
+ });
90
+ };
91
+ var uploadParams = mediaProvider.uploadParams,
92
+ uploadMediaClientConfig = mediaProvider.uploadMediaClientConfig;
93
+ return /*#__PURE__*/React.createElement(Stack, {
94
+ grow: "fill",
95
+ space: "space.200"
96
+ }, uploadState.error && /*#__PURE__*/React.createElement(SectionMessage, {
97
+ appearance: "error"
98
+ }, uploadState.error === 'upload_fail' ? strings.networkError : strings.genericError), /*#__PURE__*/React.createElement(Button, {
99
+ iconBefore: UploadIcon,
100
+ shouldFitContainer: true,
101
+ isDisabled: !uploadMediaClientConfig || !uploadParams,
102
+ onClick: function onClick() {
103
+ onUploadButtonClickedAnalytics();
104
+ dispatch({
105
+ type: 'open'
106
+ });
107
+ },
108
+ autoFocus: true
109
+ }, strings.upload), uploadMediaClientConfig && uploadParams && /*#__PURE__*/React.createElement(Browser, {
110
+ isOpen: uploadState.isOpen,
111
+ config: {
112
+ uploadParams: uploadParams
113
+ },
114
+ mediaClientConfig: uploadMediaClientConfig,
115
+ onUploadsStart: function onUploadsStart() {
116
+ onUploadCommencedAnalytics('local');
117
+ },
118
+ onPreviewUpdate: onUpload
119
+ // NOTE: this will fire for some errors like network failures, but not
120
+ // for others like empty files. Those have their own feedback toast
121
+ // owned by media.
122
+ ,
123
+ onError: function onError(payload) {
124
+ onUploadFailureAnalytics(payload.error.name, 'local');
125
+ dispatch({
126
+ type: 'error',
127
+ error: payload.error.name
128
+ });
129
+ },
130
+ onClose: function onClose() {
131
+ dispatch({
132
+ type: 'close'
133
+ });
134
+ }
135
+ }));
136
+ };