@atlaskit/editor-plugin-media 0.2.0 → 0.3.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.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/commands/captions.js +59 -0
- package/dist/cjs/commands/helpers.js +127 -0
- package/dist/cjs/commands/index.js +24 -0
- package/dist/cjs/commands/linking.js +181 -0
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/media-plugin-options.js +5 -0
- package/dist/cjs/next-plugin-type.js +5 -0
- package/dist/cjs/nodeviews/mediaGroup.js +376 -0
- package/dist/cjs/nodeviews/mediaInline.js +288 -0
- package/dist/cjs/nodeviews/mediaNodeUpdater.js +739 -0
- package/dist/cjs/nodeviews/mediaNodeView/index.js +177 -0
- package/dist/cjs/nodeviews/mediaNodeView/media.js +242 -0
- package/dist/cjs/nodeviews/mediaSingle.js +629 -0
- package/dist/cjs/nodeviews/messages.js +14 -0
- package/dist/cjs/nodeviews/styles.js +46 -0
- package/dist/cjs/nodeviews/types.js +5 -0
- package/dist/cjs/picker-facade.js +192 -0
- package/dist/cjs/plugin.js +293 -0
- package/dist/cjs/pm-plugins/alt-text/actions.js +5 -0
- package/dist/cjs/pm-plugins/alt-text/commands.js +59 -0
- package/dist/cjs/pm-plugins/alt-text/index.js +36 -0
- package/dist/cjs/pm-plugins/alt-text/keymap.js +15 -0
- package/dist/cjs/pm-plugins/alt-text/messages.js +44 -0
- package/dist/cjs/pm-plugins/alt-text/reducer.js +32 -0
- package/dist/cjs/pm-plugins/alt-text/types.js +5 -0
- package/dist/cjs/pm-plugins/alt-text/ui/AltTextEdit.js +209 -0
- package/dist/cjs/pm-plugins/keymap-media-single.js +163 -0
- package/dist/cjs/pm-plugins/keymap.js +88 -0
- package/dist/cjs/pm-plugins/linking/actions.js +13 -0
- package/dist/cjs/pm-plugins/linking/index.js +65 -0
- package/dist/cjs/pm-plugins/linking/keymap.js +14 -0
- package/dist/cjs/pm-plugins/linking/reducer.js +43 -0
- package/dist/cjs/pm-plugins/linking/types.js +5 -0
- package/dist/cjs/pm-plugins/main.js +813 -0
- package/dist/cjs/pm-plugins/media-editor-plugin-factory.js +8 -0
- package/dist/cjs/pm-plugins/mediaTaskManager.js +101 -0
- package/dist/cjs/pm-plugins/plugin-key.js +8 -0
- package/dist/cjs/pm-plugins/types.js +5 -0
- package/dist/cjs/toolbar/alt-text.js +80 -0
- package/dist/cjs/toolbar/commands.js +236 -0
- package/dist/cjs/toolbar/filePreviewItem.js +66 -0
- package/dist/cjs/toolbar/imageBorder.js +20 -0
- package/dist/cjs/toolbar/index.js +523 -0
- package/dist/cjs/toolbar/linking-toolbar-appearance.js +100 -0
- package/dist/cjs/toolbar/linking.js +96 -0
- package/dist/cjs/toolbar/utils.js +110 -0
- package/dist/cjs/ui/CaptionPlaceholder/index.js +27 -0
- package/dist/cjs/ui/CaptionPlaceholder/messages.js +14 -0
- package/dist/cjs/ui/ImageBorder/index.js +226 -0
- package/dist/cjs/ui/ImageBorder/messages.js +49 -0
- package/dist/cjs/ui/ImageBorder/styles.js +52 -0
- package/dist/cjs/ui/Media/DropPlaceholder.js +38 -0
- package/dist/cjs/ui/Media/drop-placeholder-messages.js +14 -0
- package/dist/cjs/ui/MediaLinkingToolbar.js +196 -0
- package/dist/cjs/ui/MediaPicker/BrowserWrapper.js +40 -0
- package/dist/cjs/ui/MediaPicker/ClipboardWrapper.js +39 -0
- package/dist/cjs/ui/MediaPicker/DropzoneWrapper.js +51 -0
- package/dist/cjs/ui/MediaPicker/PickerFacadeProvider.js +151 -0
- package/dist/cjs/ui/MediaPicker/index.js +103 -0
- package/dist/cjs/ui/PixelEntry/constants.js +7 -0
- package/dist/cjs/ui/PixelEntry/index.js +185 -0
- package/dist/cjs/ui/PixelEntry/messages.js +54 -0
- package/dist/cjs/ui/PixelEntry/styles.js +19 -0
- package/dist/cjs/ui/PixelEntry/types.js +5 -0
- package/dist/cjs/ui/ResizableMediaSingle/ResizableMediaMigrationNotification.js +16 -0
- package/dist/cjs/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +541 -0
- package/dist/cjs/ui/ResizableMediaSingle/index.js +422 -0
- package/dist/cjs/ui/ResizableMediaSingle/styled.js +14 -0
- package/dist/cjs/ui/ResizableMediaSingle/styles.js +17 -0
- package/dist/cjs/ui/ResizableMediaSingle/types.js +5 -0
- package/dist/cjs/ui/ToolbarMedia/index.js +42 -0
- package/dist/cjs/ui/ToolbarMedia/toolbar-media-messages.js +14 -0
- package/dist/cjs/ui/media-linking-toolbar-messages.js +14 -0
- package/dist/cjs/utils/analytics.js +53 -0
- package/dist/cjs/utils/check-media-type.js +56 -0
- package/dist/cjs/utils/current-media-node.js +41 -0
- package/dist/cjs/utils/is-image.js +9 -0
- package/dist/cjs/utils/media-common.js +181 -0
- package/dist/cjs/utils/media-files.js +297 -0
- package/dist/cjs/utils/media-single.js +181 -0
- package/dist/es2019/commands/captions.js +47 -0
- package/dist/es2019/commands/helpers.js +113 -0
- package/dist/es2019/commands/index.js +1 -0
- package/dist/es2019/commands/linking.js +169 -0
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/media-plugin-options.js +1 -0
- package/dist/es2019/next-plugin-type.js +1 -0
- package/dist/es2019/nodeviews/mediaGroup.js +314 -0
- package/dist/es2019/nodeviews/mediaInline.js +201 -0
- package/dist/es2019/nodeviews/mediaNodeUpdater.js +384 -0
- package/dist/es2019/nodeviews/mediaNodeView/index.js +149 -0
- package/dist/es2019/nodeviews/mediaNodeView/media.js +182 -0
- package/dist/es2019/nodeviews/mediaSingle.js +511 -0
- package/dist/es2019/nodeviews/messages.js +8 -0
- package/dist/es2019/nodeviews/styles.js +46 -0
- package/dist/es2019/nodeviews/types.js +1 -0
- package/dist/es2019/picker-facade.js +146 -0
- package/dist/es2019/plugin.js +284 -0
- package/dist/es2019/pm-plugins/alt-text/actions.js +1 -0
- package/dist/es2019/pm-plugins/alt-text/commands.js +42 -0
- package/dist/es2019/pm-plugins/alt-text/index.js +33 -0
- package/dist/es2019/pm-plugins/alt-text/keymap.js +9 -0
- package/dist/es2019/pm-plugins/alt-text/messages.js +38 -0
- package/dist/es2019/pm-plugins/alt-text/reducer.js +26 -0
- package/dist/es2019/pm-plugins/alt-text/types.js +1 -0
- package/dist/es2019/pm-plugins/alt-text/ui/AltTextEdit.js +228 -0
- package/dist/es2019/pm-plugins/keymap-media-single.js +172 -0
- package/dist/es2019/pm-plugins/keymap.js +84 -0
- package/dist/es2019/pm-plugins/linking/actions.js +7 -0
- package/dist/es2019/pm-plugins/linking/index.js +56 -0
- package/dist/es2019/pm-plugins/linking/keymap.js +8 -0
- package/dist/es2019/pm-plugins/linking/reducer.js +37 -0
- package/dist/es2019/pm-plugins/linking/types.js +1 -0
- package/dist/es2019/pm-plugins/main.js +695 -0
- package/dist/es2019/pm-plugins/media-editor-plugin-factory.js +2 -0
- package/dist/es2019/pm-plugins/mediaTaskManager.js +64 -0
- package/dist/es2019/pm-plugins/plugin-key.js +2 -0
- package/dist/es2019/pm-plugins/types.js +1 -0
- package/dist/es2019/toolbar/alt-text.js +72 -0
- package/dist/es2019/toolbar/commands.js +212 -0
- package/dist/es2019/toolbar/filePreviewItem.js +54 -0
- package/dist/es2019/toolbar/imageBorder.js +15 -0
- package/dist/es2019/toolbar/index.js +538 -0
- package/dist/es2019/toolbar/linking-toolbar-appearance.js +90 -0
- package/dist/es2019/toolbar/linking.js +98 -0
- package/dist/es2019/toolbar/utils.js +86 -0
- package/dist/es2019/ui/CaptionPlaceholder/index.js +25 -0
- package/dist/es2019/ui/CaptionPlaceholder/messages.js +8 -0
- package/dist/es2019/ui/ImageBorder/index.js +213 -0
- package/dist/es2019/ui/ImageBorder/messages.js +43 -0
- package/dist/es2019/ui/ImageBorder/styles.js +126 -0
- package/dist/es2019/ui/Media/DropPlaceholder.js +47 -0
- package/dist/es2019/ui/Media/drop-placeholder-messages.js +8 -0
- package/dist/es2019/ui/MediaLinkingToolbar.js +190 -0
- package/dist/es2019/ui/MediaPicker/BrowserWrapper.js +31 -0
- package/dist/es2019/ui/MediaPicker/ClipboardWrapper.js +32 -0
- package/dist/es2019/ui/MediaPicker/DropzoneWrapper.js +42 -0
- package/dist/es2019/ui/MediaPicker/PickerFacadeProvider.js +85 -0
- package/dist/es2019/ui/MediaPicker/index.js +82 -0
- package/dist/es2019/ui/PixelEntry/constants.js +1 -0
- package/dist/es2019/ui/PixelEntry/index.js +170 -0
- package/dist/es2019/ui/PixelEntry/messages.js +48 -0
- package/dist/es2019/ui/PixelEntry/styles.js +51 -0
- package/dist/es2019/ui/PixelEntry/types.js +1 -0
- package/dist/es2019/ui/ResizableMediaSingle/ResizableMediaMigrationNotification.js +9 -0
- package/dist/es2019/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +454 -0
- package/dist/es2019/ui/ResizableMediaSingle/index.js +344 -0
- package/dist/es2019/ui/ResizableMediaSingle/styled.js +9 -0
- package/dist/es2019/ui/ResizableMediaSingle/styles.js +14 -0
- package/dist/es2019/ui/ResizableMediaSingle/types.js +1 -0
- package/dist/es2019/ui/ToolbarMedia/index.js +37 -0
- package/dist/es2019/ui/ToolbarMedia/toolbar-media-messages.js +8 -0
- package/dist/es2019/ui/media-linking-toolbar-messages.js +8 -0
- package/dist/es2019/utils/analytics.js +51 -0
- package/dist/es2019/utils/check-media-type.js +19 -0
- package/dist/es2019/utils/current-media-node.js +35 -0
- package/dist/es2019/utils/is-image.js +3 -0
- package/dist/es2019/utils/media-common.js +189 -0
- package/dist/es2019/utils/media-files.js +321 -0
- package/dist/es2019/utils/media-single.js +176 -0
- package/dist/esm/commands/captions.js +53 -0
- package/dist/esm/commands/helpers.js +120 -0
- package/dist/esm/commands/index.js +1 -0
- package/dist/esm/commands/linking.js +174 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/media-plugin-options.js +1 -0
- package/dist/esm/next-plugin-type.js +1 -0
- package/dist/esm/nodeviews/mediaGroup.js +369 -0
- package/dist/esm/nodeviews/mediaInline.js +278 -0
- package/dist/esm/nodeviews/mediaNodeUpdater.js +732 -0
- package/dist/esm/nodeviews/mediaNodeView/index.js +170 -0
- package/dist/esm/nodeviews/mediaNodeView/media.js +233 -0
- package/dist/esm/nodeviews/mediaSingle.js +622 -0
- package/dist/esm/nodeviews/messages.js +8 -0
- package/dist/esm/nodeviews/styles.js +39 -0
- package/dist/esm/nodeviews/types.js +1 -0
- package/dist/esm/picker-facade.js +186 -0
- package/dist/esm/plugin.js +282 -0
- package/dist/esm/pm-plugins/alt-text/actions.js +1 -0
- package/dist/esm/pm-plugins/alt-text/commands.js +52 -0
- package/dist/esm/pm-plugins/alt-text/index.js +31 -0
- package/dist/esm/pm-plugins/alt-text/keymap.js +9 -0
- package/dist/esm/pm-plugins/alt-text/messages.js +38 -0
- package/dist/esm/pm-plugins/alt-text/reducer.js +25 -0
- package/dist/esm/pm-plugins/alt-text/types.js +1 -0
- package/dist/esm/pm-plugins/alt-text/ui/AltTextEdit.js +206 -0
- package/dist/esm/pm-plugins/keymap-media-single.js +158 -0
- package/dist/esm/pm-plugins/keymap.js +81 -0
- package/dist/esm/pm-plugins/linking/actions.js +7 -0
- package/dist/esm/pm-plugins/linking/index.js +59 -0
- package/dist/esm/pm-plugins/linking/keymap.js +8 -0
- package/dist/esm/pm-plugins/linking/reducer.js +36 -0
- package/dist/esm/pm-plugins/linking/types.js +1 -0
- package/dist/esm/pm-plugins/main.js +798 -0
- package/dist/esm/pm-plugins/media-editor-plugin-factory.js +2 -0
- package/dist/esm/pm-plugins/mediaTaskManager.js +94 -0
- package/dist/esm/pm-plugins/plugin-key.js +2 -0
- package/dist/esm/pm-plugins/types.js +1 -0
- package/dist/esm/toolbar/alt-text.js +70 -0
- package/dist/esm/toolbar/commands.js +229 -0
- package/dist/esm/toolbar/filePreviewItem.js +56 -0
- package/dist/esm/toolbar/imageBorder.js +14 -0
- package/dist/esm/toolbar/index.js +513 -0
- package/dist/esm/toolbar/linking-toolbar-appearance.js +91 -0
- package/dist/esm/toolbar/linking.js +88 -0
- package/dist/esm/toolbar/utils.js +103 -0
- package/dist/esm/ui/CaptionPlaceholder/index.js +20 -0
- package/dist/esm/ui/CaptionPlaceholder/messages.js +8 -0
- package/dist/esm/ui/ImageBorder/index.js +218 -0
- package/dist/esm/ui/ImageBorder/messages.js +43 -0
- package/dist/esm/ui/ImageBorder/styles.js +42 -0
- package/dist/esm/ui/Media/DropPlaceholder.js +31 -0
- package/dist/esm/ui/Media/drop-placeholder-messages.js +8 -0
- package/dist/esm/ui/MediaLinkingToolbar.js +188 -0
- package/dist/esm/ui/MediaPicker/BrowserWrapper.js +33 -0
- package/dist/esm/ui/MediaPicker/ClipboardWrapper.js +32 -0
- package/dist/esm/ui/MediaPicker/DropzoneWrapper.js +44 -0
- package/dist/esm/ui/MediaPicker/PickerFacadeProvider.js +145 -0
- package/dist/esm/ui/MediaPicker/index.js +96 -0
- package/dist/esm/ui/PixelEntry/constants.js +1 -0
- package/dist/esm/ui/PixelEntry/index.js +174 -0
- package/dist/esm/ui/PixelEntry/messages.js +48 -0
- package/dist/esm/ui/PixelEntry/styles.js +12 -0
- package/dist/esm/ui/PixelEntry/types.js +1 -0
- package/dist/esm/ui/ResizableMediaSingle/ResizableMediaMigrationNotification.js +9 -0
- package/dist/esm/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +535 -0
- package/dist/esm/ui/ResizableMediaSingle/index.js +417 -0
- package/dist/esm/ui/ResizableMediaSingle/styled.js +7 -0
- package/dist/esm/ui/ResizableMediaSingle/styles.js +7 -0
- package/dist/esm/ui/ResizableMediaSingle/types.js +1 -0
- package/dist/esm/ui/ToolbarMedia/index.js +35 -0
- package/dist/esm/ui/ToolbarMedia/toolbar-media-messages.js +8 -0
- package/dist/esm/ui/media-linking-toolbar-messages.js +8 -0
- package/dist/esm/utils/analytics.js +47 -0
- package/dist/esm/utils/check-media-type.js +49 -0
- package/dist/esm/utils/current-media-node.js +35 -0
- package/dist/esm/utils/is-image.js +3 -0
- package/dist/esm/utils/media-common.js +175 -0
- package/dist/esm/utils/media-files.js +291 -0
- package/dist/esm/utils/media-single.js +172 -0
- package/dist/types/commands/captions.d.ts +5 -0
- package/dist/types/commands/helpers.d.ts +15 -0
- package/dist/types/commands/index.d.ts +1 -0
- package/dist/types/commands/linking.d.ts +9 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/media-plugin-options.d.ts +17 -0
- package/dist/types/next-plugin-type.d.ts +33 -0
- package/dist/types/nodeviews/__mocks__/mediaNodeUpdater.d.ts +24 -0
- package/dist/types/nodeviews/mediaGroup.d.ts +33 -0
- package/dist/types/nodeviews/mediaInline.d.ts +50 -0
- package/dist/types/nodeviews/mediaNodeUpdater.d.ts +45 -0
- package/dist/types/nodeviews/mediaNodeView/index.d.ts +28 -0
- package/dist/types/nodeviews/mediaNodeView/media.d.ts +44 -0
- package/dist/types/nodeviews/mediaSingle.d.ts +62 -0
- package/dist/types/nodeviews/messages.d.ts +7 -0
- package/dist/types/nodeviews/styles.d.ts +16 -0
- package/dist/types/nodeviews/types.d.ts +42 -0
- package/dist/types/picker-facade.d.ts +44 -0
- package/dist/types/plugin.d.ts +7 -0
- package/dist/types/pm-plugins/alt-text/actions.d.ts +10 -0
- package/dist/types/pm-plugins/alt-text/commands.d.ts +4 -0
- package/dist/types/pm-plugins/alt-text/index.d.ts +7 -0
- package/dist/types/pm-plugins/alt-text/keymap.d.ts +4 -0
- package/dist/types/pm-plugins/alt-text/messages.d.ts +37 -0
- package/dist/types/pm-plugins/alt-text/reducer.d.ts +4 -0
- package/dist/types/pm-plugins/alt-text/types.d.ts +3 -0
- package/dist/types/pm-plugins/alt-text/ui/AltTextEdit.d.ts +41 -0
- package/dist/types/pm-plugins/keymap-media-single.d.ts +3 -0
- package/dist/types/pm-plugins/keymap.d.ts +6 -0
- package/dist/types/pm-plugins/linking/actions.d.ts +20 -0
- package/dist/types/pm-plugins/linking/index.d.ts +10 -0
- package/dist/types/pm-plugins/linking/keymap.d.ts +3 -0
- package/dist/types/pm-plugins/linking/reducer.d.ts +4 -0
- package/dist/types/pm-plugins/linking/types.d.ts +12 -0
- package/dist/types/pm-plugins/main.d.ts +120 -0
- package/dist/types/pm-plugins/media-editor-plugin-factory.d.ts +3 -0
- package/dist/types/pm-plugins/mediaTaskManager.d.ts +9 -0
- package/dist/types/pm-plugins/plugin-key.d.ts +3 -0
- package/dist/types/pm-plugins/types.d.ts +65 -0
- package/dist/types/toolbar/alt-text.d.ts +13 -0
- package/dist/types/toolbar/commands.d.ts +12 -0
- package/dist/types/toolbar/filePreviewItem.d.ts +9 -0
- package/dist/types/toolbar/imageBorder.d.ts +2 -0
- package/dist/types/toolbar/index.d.ts +6 -0
- package/dist/types/toolbar/linking-toolbar-appearance.d.ts +14 -0
- package/dist/types/toolbar/linking.d.ts +10 -0
- package/dist/types/toolbar/utils.d.ts +11 -0
- package/dist/types/types.d.ts +2 -1
- package/dist/types/ui/CaptionPlaceholder/index.d.ts +6 -0
- package/dist/types/ui/CaptionPlaceholder/messages.d.ts +7 -0
- package/dist/types/ui/ImageBorder/index.d.ts +11 -0
- package/dist/types/ui/ImageBorder/messages.d.ts +42 -0
- package/dist/types/ui/ImageBorder/styles.d.ts +15 -0
- package/dist/types/ui/Media/DropPlaceholder.d.ts +8 -0
- package/dist/types/ui/Media/drop-placeholder-messages.d.ts +7 -0
- package/dist/types/ui/MediaLinkingToolbar.d.ts +35 -0
- package/dist/types/ui/MediaPicker/BrowserWrapper.d.ts +11 -0
- package/dist/types/ui/MediaPicker/ClipboardWrapper.d.ts +10 -0
- package/dist/types/ui/MediaPicker/DropzoneWrapper.d.ts +13 -0
- package/dist/types/ui/MediaPicker/PickerFacadeProvider.d.ts +28 -0
- package/dist/types/ui/MediaPicker/index.d.ts +23 -0
- package/dist/types/ui/PixelEntry/constants.d.ts +1 -0
- package/dist/types/ui/PixelEntry/index.d.ts +8 -0
- package/dist/types/ui/PixelEntry/messages.d.ts +47 -0
- package/dist/types/ui/PixelEntry/styles.d.ts +8 -0
- package/dist/types/ui/PixelEntry/types.d.ts +58 -0
- package/dist/types/ui/ResizableMediaSingle/ResizableMediaMigrationNotification.d.ts +3 -0
- package/dist/types/ui/ResizableMediaSingle/ResizableMediaSingleNext.d.ts +59 -0
- package/dist/types/ui/ResizableMediaSingle/index.d.ts +45 -0
- package/dist/types/ui/ResizableMediaSingle/styled.d.ts +2 -0
- package/dist/types/ui/ResizableMediaSingle/styles.d.ts +1 -0
- package/dist/types/ui/ResizableMediaSingle/types.d.ts +27 -0
- package/dist/types/ui/ToolbarMedia/index.d.ts +13 -0
- package/dist/types/ui/ToolbarMedia/toolbar-media-messages.d.ts +7 -0
- package/dist/types/ui/media-linking-toolbar-messages.d.ts +7 -0
- package/dist/types/utils/analytics.d.ts +3 -0
- package/dist/types/utils/check-media-type.d.ts +4 -0
- package/dist/types/utils/current-media-node.d.ts +9 -0
- package/dist/types/utils/is-image.d.ts +1 -0
- package/dist/types/utils/media-common.d.ts +20 -0
- package/dist/types/utils/media-files.d.ts +30 -0
- package/dist/types/utils/media-single.d.ts +20 -0
- package/package.json +32 -20
- package/report.api.md +430 -0
- package/dist/types-ts4.5/index.d.ts +0 -1
- package/dist/types-ts4.5/types.d.ts +0 -118
- package/tmp/api-report-tmp.d.ts +0 -9
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import assert from 'assert';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import ReactDOM from 'react-dom';
|
|
5
|
+
import { RawIntlProvider } from 'react-intl-next';
|
|
6
|
+
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
7
|
+
import { CAPTION_PLACEHOLDER_ID, getMaxWidthForNestedNodeNext } from '@atlaskit/editor-common/media-single';
|
|
8
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
9
|
+
import { browser, ErrorReporter, isInEmptyLine, isInListItem } from '@atlaskit/editor-common/utils';
|
|
10
|
+
import { AllSelection, NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
11
|
+
import { insertPoint } from '@atlaskit/editor-prosemirror/transform';
|
|
12
|
+
import { findDomRefAtPos, findParentNodeOfType, findSelectedNodeOfType, isNodeSelection } from '@atlaskit/editor-prosemirror/utils';
|
|
13
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
14
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
15
|
+
import { getMediaFeatureFlag } from '@atlaskit/media-common';
|
|
16
|
+
import * as helpers from '../commands/helpers';
|
|
17
|
+
import { updateMediaSingleNodeAttrs } from '../commands/helpers';
|
|
18
|
+
import PickerFacade from '../picker-facade';
|
|
19
|
+
import DropPlaceholder from '../ui/Media/DropPlaceholder';
|
|
20
|
+
import { isInsidePotentialEmptyParagraph, removeMediaNode, splitMediaGroup } from '../utils/media-common';
|
|
21
|
+
import { canInsertMediaInline, insertMediaGroupNode, insertMediaInlineNode } from '../utils/media-files';
|
|
22
|
+
import { insertMediaSingleNode, isMediaSingle } from '../utils/media-single';
|
|
23
|
+
import { MediaTaskManager } from './mediaTaskManager';
|
|
24
|
+
import { stateKey } from './plugin-key';
|
|
25
|
+
export { stateKey } from './plugin-key';
|
|
26
|
+
export const MEDIA_CONTENT_WRAP_CLASS_NAME = 'media-content-wrap';
|
|
27
|
+
export const MEDIA_PLUGIN_IS_RESIZING_KEY = 'mediaSinglePlugin.isResizing';
|
|
28
|
+
export const MEDIA_PLUGIN_RESIZING_WIDTH_KEY = 'mediaSinglePlugin.resizing-width';
|
|
29
|
+
const createDropPlaceholder = (intl, allowDropLine) => {
|
|
30
|
+
const dropPlaceholder = document.createElement('div');
|
|
31
|
+
const createElement = React.createElement;
|
|
32
|
+
if (allowDropLine) {
|
|
33
|
+
ReactDOM.render(createElement(RawIntlProvider, {
|
|
34
|
+
value: intl
|
|
35
|
+
}, createElement(DropPlaceholder, {
|
|
36
|
+
type: 'single'
|
|
37
|
+
})), dropPlaceholder);
|
|
38
|
+
} else {
|
|
39
|
+
ReactDOM.render(createElement(RawIntlProvider, {
|
|
40
|
+
value: intl
|
|
41
|
+
}, createElement(DropPlaceholder)), dropPlaceholder);
|
|
42
|
+
}
|
|
43
|
+
return dropPlaceholder;
|
|
44
|
+
};
|
|
45
|
+
const MEDIA_RESOLVED_STATES = ['ready', 'error', 'cancelled'];
|
|
46
|
+
export class MediaPluginStateImplementation {
|
|
47
|
+
constructor(_state, options, mediaOptions, newInsertionBehaviour, _dispatch, pluginInjectionApi) {
|
|
48
|
+
_defineProperty(this, "allowsUploads", false);
|
|
49
|
+
_defineProperty(this, "ignoreLinks", false);
|
|
50
|
+
_defineProperty(this, "waitForMediaUpload", true);
|
|
51
|
+
_defineProperty(this, "allUploadsFinished", true);
|
|
52
|
+
_defineProperty(this, "showDropzone", false);
|
|
53
|
+
_defineProperty(this, "isFullscreen", false);
|
|
54
|
+
_defineProperty(this, "layout", 'center');
|
|
55
|
+
_defineProperty(this, "mediaNodes", []);
|
|
56
|
+
_defineProperty(this, "isResizing", false);
|
|
57
|
+
_defineProperty(this, "resizingWidth", 0);
|
|
58
|
+
_defineProperty(this, "destroyed", false);
|
|
59
|
+
_defineProperty(this, "removeOnCloseListener", () => {});
|
|
60
|
+
_defineProperty(this, "onPopupToggleCallback", () => {});
|
|
61
|
+
_defineProperty(this, "nodeCount", new Map());
|
|
62
|
+
_defineProperty(this, "taskManager", new MediaTaskManager());
|
|
63
|
+
_defineProperty(this, "pickers", []);
|
|
64
|
+
_defineProperty(this, "pickerPromises", []);
|
|
65
|
+
_defineProperty(this, "onContextIdentifierProvider", async (_name, provider) => {
|
|
66
|
+
if (provider) {
|
|
67
|
+
this.contextIdentifierProvider = await provider;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
_defineProperty(this, "setMediaProvider", async mediaProvider => {
|
|
71
|
+
if (!mediaProvider) {
|
|
72
|
+
this.destroyPickers();
|
|
73
|
+
this.allowsUploads = false;
|
|
74
|
+
if (!this.destroyed) {
|
|
75
|
+
this.view.dispatch(this.view.state.tr.setMeta(stateKey, {
|
|
76
|
+
allowsUploads: this.allowsUploads
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// TODO disable (not destroy!) pickers until mediaProvider is resolved
|
|
83
|
+
try {
|
|
84
|
+
this.mediaProvider = await mediaProvider;
|
|
85
|
+
|
|
86
|
+
// TODO [MS-2038]: remove once context api is removed
|
|
87
|
+
// We want to re assign the view and upload configs if they are missing for backwards compatibility
|
|
88
|
+
// as currently integrators can pass context || mediaClientConfig
|
|
89
|
+
if (!this.mediaProvider.viewMediaClientConfig) {
|
|
90
|
+
const viewMediaClientConfig = this.mediaProvider.viewMediaClientConfig;
|
|
91
|
+
if (viewMediaClientConfig) {
|
|
92
|
+
this.mediaProvider.viewMediaClientConfig = viewMediaClientConfig;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
assert(this.mediaProvider.viewMediaClientConfig, `MediaProvider promise did not resolve to a valid instance of MediaProvider - ${this.mediaProvider}`);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
const wrappedError = new Error(`Media functionality disabled due to rejected provider: ${err instanceof Error ? err.message : String(err)}`);
|
|
98
|
+
this.errorReporter.captureException(wrappedError);
|
|
99
|
+
this.destroyPickers();
|
|
100
|
+
this.allowsUploads = false;
|
|
101
|
+
if (!this.destroyed) {
|
|
102
|
+
this.view.dispatch(this.view.state.tr.setMeta(stateKey, {
|
|
103
|
+
allowsUploads: this.allowsUploads
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.mediaClientConfig = this.mediaProvider.viewMediaClientConfig;
|
|
109
|
+
this.allowsUploads = !!this.mediaProvider.uploadMediaClientConfig;
|
|
110
|
+
const {
|
|
111
|
+
view,
|
|
112
|
+
allowsUploads
|
|
113
|
+
} = this;
|
|
114
|
+
// make sure editable DOM node is mounted
|
|
115
|
+
if (!this.destroyed && view && view.dom.parentNode) {
|
|
116
|
+
// make PM plugin aware of the state change to update UI during 'apply' hook
|
|
117
|
+
view.dispatch(view.state.tr.setMeta(stateKey, {
|
|
118
|
+
allowsUploads
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
if (this.allowsUploads) {
|
|
122
|
+
this.uploadMediaClientConfig = this.mediaProvider.uploadMediaClientConfig;
|
|
123
|
+
if (this.mediaProvider.uploadParams && this.uploadMediaClientConfig) {
|
|
124
|
+
await this.initPickers(this.mediaProvider.uploadParams, PickerFacade);
|
|
125
|
+
} else {
|
|
126
|
+
this.destroyPickers();
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
this.destroyPickers();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
_defineProperty(this, "getMediaOptions", () => this.options);
|
|
133
|
+
_defineProperty(this, "isMediaSchemaNode", ({
|
|
134
|
+
type
|
|
135
|
+
}) => {
|
|
136
|
+
var _this$mediaOptions;
|
|
137
|
+
const {
|
|
138
|
+
mediaInline,
|
|
139
|
+
mediaSingle,
|
|
140
|
+
media
|
|
141
|
+
} = this.view.state.schema.nodes;
|
|
142
|
+
if (getMediaFeatureFlag('mediaInline', (_this$mediaOptions = this.mediaOptions) === null || _this$mediaOptions === void 0 ? void 0 : _this$mediaOptions.featureFlags)) {
|
|
143
|
+
return type === mediaSingle || type === media || type === mediaInline;
|
|
144
|
+
}
|
|
145
|
+
return type === mediaSingle;
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* we insert a new file by inserting a initial state for that file.
|
|
149
|
+
*
|
|
150
|
+
* called when we insert a new file via the picker (connected via pickerfacade)
|
|
151
|
+
*/
|
|
152
|
+
_defineProperty(this, "insertFile", (mediaState, onMediaStateChanged, pickerType) => {
|
|
153
|
+
var _this$pluginInjection, _this$pluginInjection2, _mediaState$collectio, _this$mediaOptions2;
|
|
154
|
+
const {
|
|
155
|
+
state
|
|
156
|
+
} = this.view;
|
|
157
|
+
const editorAnalyticsAPI = (_this$pluginInjection = this.pluginInjectionApi) === null || _this$pluginInjection === void 0 ? void 0 : (_this$pluginInjection2 = _this$pluginInjection.analytics) === null || _this$pluginInjection2 === void 0 ? void 0 : _this$pluginInjection2.actions;
|
|
158
|
+
const mediaStateWithContext = {
|
|
159
|
+
...mediaState,
|
|
160
|
+
contextId: this.contextIdentifierProvider ? this.contextIdentifierProvider.objectId : undefined
|
|
161
|
+
};
|
|
162
|
+
const collection = (_mediaState$collectio = mediaState.collection) !== null && _mediaState$collectio !== void 0 ? _mediaState$collectio : this.collectionFromProvider();
|
|
163
|
+
if (collection === undefined) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// We need to dispatch the change to event dispatcher only for successful files
|
|
168
|
+
if (mediaState.status !== 'error') {
|
|
169
|
+
this.updateAndDispatch({
|
|
170
|
+
allUploadsFinished: false
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (isMediaSingle(state.schema, mediaStateWithContext.fileMimeType)) {
|
|
174
|
+
var _this$pluginInjection3;
|
|
175
|
+
// read width state right before inserting to get up-to-date and define values
|
|
176
|
+
const widthPluginState = (_this$pluginInjection3 = this.pluginInjectionApi) === null || _this$pluginInjection3 === void 0 ? void 0 : _this$pluginInjection3.width.sharedState.currentState();
|
|
177
|
+
insertMediaSingleNode(this.view, mediaStateWithContext, this.getInputMethod(pickerType), collection, this.mediaOptions && this.mediaOptions.alignLeftOnInsert, this.newInsertionBehaviour, widthPluginState, editorAnalyticsAPI);
|
|
178
|
+
} else if (getMediaFeatureFlag('mediaInline', (_this$mediaOptions2 = this.mediaOptions) === null || _this$mediaOptions2 === void 0 ? void 0 : _this$mediaOptions2.featureFlags) && !isInEmptyLine(state) && (!isInsidePotentialEmptyParagraph(state) || isInListItem(state)) && canInsertMediaInline(state)) {
|
|
179
|
+
insertMediaInlineNode(editorAnalyticsAPI)(this.view, mediaStateWithContext, collection, this.getInputMethod(pickerType));
|
|
180
|
+
} else {
|
|
181
|
+
insertMediaGroupNode(editorAnalyticsAPI)(this.view, [mediaStateWithContext], collection, this.getInputMethod(pickerType));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// do events when media state changes
|
|
185
|
+
onMediaStateChanged(this.handleMediaState);
|
|
186
|
+
|
|
187
|
+
// handle waiting for upload complete
|
|
188
|
+
const isEndState = state => state.status && MEDIA_RESOLVED_STATES.indexOf(state.status) !== -1;
|
|
189
|
+
if (!isEndState(mediaStateWithContext)) {
|
|
190
|
+
const uploadingPromise = new Promise(resolve => {
|
|
191
|
+
onMediaStateChanged(newState => {
|
|
192
|
+
// When media item reaches its final state, remove listener and resolve
|
|
193
|
+
if (isEndState(newState)) {
|
|
194
|
+
resolve(newState);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
this.taskManager.addPendingTask(uploadingPromise, mediaStateWithContext.id).then(() => {
|
|
199
|
+
this.updateAndDispatch({
|
|
200
|
+
allUploadsFinished: true
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// refocus the view
|
|
206
|
+
const {
|
|
207
|
+
view
|
|
208
|
+
} = this;
|
|
209
|
+
if (!view.hasFocus()) {
|
|
210
|
+
view.focus();
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
_defineProperty(this, "addPendingTask", task => {
|
|
214
|
+
this.taskManager.addPendingTask(task);
|
|
215
|
+
});
|
|
216
|
+
_defineProperty(this, "splitMediaGroup", () => splitMediaGroup(this.view));
|
|
217
|
+
_defineProperty(this, "onPopupPickerClose", () => {
|
|
218
|
+
this.onPopupToggleCallback(false);
|
|
219
|
+
});
|
|
220
|
+
_defineProperty(this, "showMediaPicker", () => {
|
|
221
|
+
if (this.openMediaPickerBrowser) {
|
|
222
|
+
return this.openMediaPickerBrowser();
|
|
223
|
+
}
|
|
224
|
+
this.onPopupToggleCallback(true);
|
|
225
|
+
});
|
|
226
|
+
_defineProperty(this, "setBrowseFn", browseFn => {
|
|
227
|
+
this.openMediaPickerBrowser = browseFn;
|
|
228
|
+
});
|
|
229
|
+
_defineProperty(this, "onPopupToggle", onPopupToggleCallback => {
|
|
230
|
+
this.onPopupToggleCallback = onPopupToggleCallback;
|
|
231
|
+
});
|
|
232
|
+
/**
|
|
233
|
+
* Returns a promise that is resolved after all pending operations have been finished.
|
|
234
|
+
* An optional timeout will cause the promise to reject if the operation takes too long
|
|
235
|
+
*
|
|
236
|
+
* NOTE: The promise will resolve even if some of the media have failed to process.
|
|
237
|
+
*/
|
|
238
|
+
_defineProperty(this, "waitForPendingTasks", this.taskManager.waitForPendingTasks);
|
|
239
|
+
/**
|
|
240
|
+
* Called from React UI Component when user clicks on "Delete" icon
|
|
241
|
+
* inside of it
|
|
242
|
+
*/
|
|
243
|
+
_defineProperty(this, "handleMediaNodeRemoval", (node, getPos) => {
|
|
244
|
+
let getNode = node;
|
|
245
|
+
if (!getNode) {
|
|
246
|
+
const pos = getPos();
|
|
247
|
+
if (typeof pos !== 'number') {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
getNode = this.view.state.doc.nodeAt(pos);
|
|
251
|
+
}
|
|
252
|
+
removeMediaNode(this.view, getNode, getPos);
|
|
253
|
+
});
|
|
254
|
+
_defineProperty(this, "trackMediaNodeAddition", node => {
|
|
255
|
+
var _this$nodeCount$get;
|
|
256
|
+
const id = node.attrs.id;
|
|
257
|
+
const count = (_this$nodeCount$get = this.nodeCount.get(id)) !== null && _this$nodeCount$get !== void 0 ? _this$nodeCount$get : 0;
|
|
258
|
+
if (count === 0) {
|
|
259
|
+
this.taskManager.resumePendingTask(id);
|
|
260
|
+
}
|
|
261
|
+
this.nodeCount.set(id, count + 1);
|
|
262
|
+
});
|
|
263
|
+
_defineProperty(this, "trackMediaNodeRemoval", node => {
|
|
264
|
+
var _this$nodeCount$get2;
|
|
265
|
+
const id = node.attrs.id;
|
|
266
|
+
const count = (_this$nodeCount$get2 = this.nodeCount.get(id)) !== null && _this$nodeCount$get2 !== void 0 ? _this$nodeCount$get2 : 0;
|
|
267
|
+
if (count === 1) {
|
|
268
|
+
this.taskManager.cancelPendingTask(id);
|
|
269
|
+
}
|
|
270
|
+
this.nodeCount.set(id, count - 1);
|
|
271
|
+
});
|
|
272
|
+
/**
|
|
273
|
+
* Called from React UI Component on componentDidMount
|
|
274
|
+
*/
|
|
275
|
+
_defineProperty(this, "handleMediaNodeMount", (node, getPos) => {
|
|
276
|
+
this.trackMediaNodeAddition(node);
|
|
277
|
+
this.mediaNodes.unshift({
|
|
278
|
+
node,
|
|
279
|
+
getPos
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
/**
|
|
283
|
+
* Called from React UI Component on componentWillUnmount and UNSAFE_componentWillReceiveProps
|
|
284
|
+
* when React component's underlying node property is replaced with a new node
|
|
285
|
+
*/
|
|
286
|
+
_defineProperty(this, "handleMediaNodeUnmount", oldNode => {
|
|
287
|
+
this.trackMediaNodeRemoval(oldNode);
|
|
288
|
+
this.mediaNodes = this.mediaNodes.filter(({
|
|
289
|
+
node
|
|
290
|
+
}) => oldNode !== node);
|
|
291
|
+
});
|
|
292
|
+
_defineProperty(this, "handleMediaGroupUpdate", (oldNodes, newNodes) => {
|
|
293
|
+
const addedNodes = newNodes.filter(node => oldNodes.every(oldNode => oldNode.attrs.id !== node.attrs.id));
|
|
294
|
+
const removedNodes = oldNodes.filter(node => newNodes.every(newNode => newNode.attrs.id !== node.attrs.id));
|
|
295
|
+
addedNodes.forEach(node => {
|
|
296
|
+
this.trackMediaNodeAddition(node);
|
|
297
|
+
});
|
|
298
|
+
removedNodes.forEach(oldNode => {
|
|
299
|
+
this.trackMediaNodeRemoval(oldNode);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
_defineProperty(this, "findMediaNode", id => {
|
|
303
|
+
return helpers.findMediaSingleNode(this, id);
|
|
304
|
+
});
|
|
305
|
+
_defineProperty(this, "destroyAllPickers", pickers => {
|
|
306
|
+
pickers.forEach(picker => picker.destroy());
|
|
307
|
+
this.pickers.splice(0, this.pickers.length);
|
|
308
|
+
});
|
|
309
|
+
_defineProperty(this, "destroyPickers", () => {
|
|
310
|
+
const {
|
|
311
|
+
pickers,
|
|
312
|
+
pickerPromises
|
|
313
|
+
} = this;
|
|
314
|
+
|
|
315
|
+
// If pickerPromises and pickers are the same length
|
|
316
|
+
// All pickers have resolved and we safely destroy them
|
|
317
|
+
// Otherwise wait for them to resolve then destroy.
|
|
318
|
+
if (pickerPromises.length === pickers.length) {
|
|
319
|
+
this.destroyAllPickers(this.pickers);
|
|
320
|
+
} else {
|
|
321
|
+
Promise.all(pickerPromises).then(resolvedPickers => this.destroyAllPickers(resolvedPickers));
|
|
322
|
+
}
|
|
323
|
+
this.customPicker = undefined;
|
|
324
|
+
});
|
|
325
|
+
_defineProperty(this, "getInputMethod", pickerType => {
|
|
326
|
+
switch (pickerType) {
|
|
327
|
+
case 'clipboard':
|
|
328
|
+
return INPUT_METHOD.CLIPBOARD;
|
|
329
|
+
case 'dropzone':
|
|
330
|
+
return INPUT_METHOD.DRAG_AND_DROP;
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
});
|
|
334
|
+
_defineProperty(this, "updateMediaSingleNodeAttrs", (id, attrs) => {
|
|
335
|
+
const {
|
|
336
|
+
view
|
|
337
|
+
} = this;
|
|
338
|
+
if (!view) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
return updateMediaSingleNodeAttrs(id, attrs)(view.state, view.dispatch);
|
|
342
|
+
});
|
|
343
|
+
_defineProperty(this, "handleMediaState", state => {
|
|
344
|
+
switch (state.status) {
|
|
345
|
+
case 'error':
|
|
346
|
+
const {
|
|
347
|
+
uploadErrorHandler
|
|
348
|
+
} = this.options;
|
|
349
|
+
if (uploadErrorHandler) {
|
|
350
|
+
uploadErrorHandler(state);
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
_defineProperty(this, "removeSelectedMediaContainer", () => {
|
|
356
|
+
const {
|
|
357
|
+
view
|
|
358
|
+
} = this;
|
|
359
|
+
const selectedNode = this.selectedMediaContainerNode();
|
|
360
|
+
if (!selectedNode) {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
let {
|
|
364
|
+
from
|
|
365
|
+
} = view.state.selection;
|
|
366
|
+
removeMediaNode(view, selectedNode.firstChild, () => from + 1);
|
|
367
|
+
return true;
|
|
368
|
+
});
|
|
369
|
+
_defineProperty(this, "selectedMediaContainerNode", () => {
|
|
370
|
+
const {
|
|
371
|
+
selection
|
|
372
|
+
} = this.view.state;
|
|
373
|
+
if (selection instanceof NodeSelection && this.isMediaSchemaNode(selection.node)) {
|
|
374
|
+
return selection.node;
|
|
375
|
+
}
|
|
376
|
+
return;
|
|
377
|
+
});
|
|
378
|
+
_defineProperty(this, "handleDrag", dragState => {
|
|
379
|
+
const isActive = dragState === 'enter';
|
|
380
|
+
if (this.showDropzone === isActive) {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
this.showDropzone = isActive;
|
|
384
|
+
const {
|
|
385
|
+
dispatch,
|
|
386
|
+
state
|
|
387
|
+
} = this.view;
|
|
388
|
+
const {
|
|
389
|
+
tr,
|
|
390
|
+
selection,
|
|
391
|
+
doc
|
|
392
|
+
} = state;
|
|
393
|
+
const {
|
|
394
|
+
media,
|
|
395
|
+
mediaGroup
|
|
396
|
+
} = state.schema.nodes;
|
|
397
|
+
|
|
398
|
+
// Workaround for wrong upload position
|
|
399
|
+
// @see https://product-fabric.atlassian.net/browse/MEX-2457
|
|
400
|
+
// If the media node is the last selectable item in the current cursor position and it is located within a mediaGroup,
|
|
401
|
+
// we relocate the cursor to the first child of the mediaGroup.
|
|
402
|
+
const sel = Selection.findFrom(doc.resolve(selection.$from.pos - 1), -1);
|
|
403
|
+
if (sel && findSelectedNodeOfType(media)(sel)) {
|
|
404
|
+
const parent = findParentNodeOfType(mediaGroup)(sel);
|
|
405
|
+
if (parent) {
|
|
406
|
+
tr.setSelection(NodeSelection.create(tr.doc, parent.start));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Trigger state change to be able to pick it up in the decorations handler
|
|
411
|
+
dispatch(tr);
|
|
412
|
+
});
|
|
413
|
+
this.options = options;
|
|
414
|
+
this.mediaOptions = mediaOptions;
|
|
415
|
+
this.newInsertionBehaviour = newInsertionBehaviour;
|
|
416
|
+
this.dispatch = _dispatch;
|
|
417
|
+
this.pluginInjectionApi = pluginInjectionApi;
|
|
418
|
+
this.waitForMediaUpload = options.waitForMediaUpload === undefined ? true : options.waitForMediaUpload;
|
|
419
|
+
const {
|
|
420
|
+
nodes
|
|
421
|
+
} = _state.schema;
|
|
422
|
+
assert(nodes.media && (nodes.mediaGroup || nodes.mediaSingle), 'Editor: unable to init media plugin - media or mediaGroup/mediaSingle node absent in schema');
|
|
423
|
+
options.providerFactory.subscribe('mediaProvider', (_name, provider) => this.setMediaProvider(provider));
|
|
424
|
+
options.providerFactory.subscribe('contextIdentifierProvider', this.onContextIdentifierProvider);
|
|
425
|
+
this.errorReporter = options.errorReporter || new ErrorReporter();
|
|
426
|
+
this.singletonCreatedAt = (performance || Date).now();
|
|
427
|
+
}
|
|
428
|
+
clone() {
|
|
429
|
+
const clonedAt = (performance || Date).now();
|
|
430
|
+
return new Proxy(this, {
|
|
431
|
+
get(target, prop, receiver) {
|
|
432
|
+
if (prop === 'singletonCreatedAt') {
|
|
433
|
+
return clonedAt;
|
|
434
|
+
}
|
|
435
|
+
return Reflect.get(target, prop, receiver);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
setIsResizing(isResizing) {
|
|
440
|
+
this.isResizing = isResizing;
|
|
441
|
+
}
|
|
442
|
+
setResizingWidth(width) {
|
|
443
|
+
this.resizingWidth = width;
|
|
444
|
+
}
|
|
445
|
+
updateElement() {
|
|
446
|
+
let newElement;
|
|
447
|
+
const selectedContainer = this.selectedMediaContainerNode();
|
|
448
|
+
if (selectedContainer && this.isMediaSchemaNode(selectedContainer)) {
|
|
449
|
+
newElement = this.getDomElement(this.view.domAtPos.bind(this.view));
|
|
450
|
+
if (selectedContainer.type === this.view.state.schema.nodes.mediaSingle) {
|
|
451
|
+
this.currentMaxWidth = getMaxWidthForNestedNodeNext(this.view, this.view.state.selection.$anchor.pos) || undefined;
|
|
452
|
+
} else {
|
|
453
|
+
this.currentMaxWidth = undefined;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
if (this.element !== newElement) {
|
|
457
|
+
this.element = newElement;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
getDomElement(domAtPos) {
|
|
461
|
+
const {
|
|
462
|
+
selection
|
|
463
|
+
} = this.view.state;
|
|
464
|
+
if (!(selection instanceof NodeSelection)) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (!this.isMediaSchemaNode(selection.node)) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const node = findDomRefAtPos(selection.from, domAtPos);
|
|
471
|
+
if (node) {
|
|
472
|
+
if (!node.childNodes.length) {
|
|
473
|
+
return node.parentNode;
|
|
474
|
+
}
|
|
475
|
+
return node;
|
|
476
|
+
}
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
setView(view) {
|
|
480
|
+
this.view = view;
|
|
481
|
+
}
|
|
482
|
+
destroy() {
|
|
483
|
+
if (this.destroyed) {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
this.destroyed = true;
|
|
487
|
+
const {
|
|
488
|
+
mediaNodes
|
|
489
|
+
} = this;
|
|
490
|
+
mediaNodes.splice(0, mediaNodes.length);
|
|
491
|
+
this.removeOnCloseListener();
|
|
492
|
+
this.destroyPickers();
|
|
493
|
+
}
|
|
494
|
+
async initPickers(uploadParams, Picker) {
|
|
495
|
+
if (this.destroyed || !this.uploadMediaClientConfig) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const {
|
|
499
|
+
errorReporter,
|
|
500
|
+
pickers,
|
|
501
|
+
pickerPromises
|
|
502
|
+
} = this;
|
|
503
|
+
// create pickers if they don't exist, re-use otherwise
|
|
504
|
+
if (!pickers.length) {
|
|
505
|
+
const pickerFacadeConfig = {
|
|
506
|
+
mediaClientConfig: this.uploadMediaClientConfig,
|
|
507
|
+
errorReporter
|
|
508
|
+
};
|
|
509
|
+
if (this.options.customMediaPicker) {
|
|
510
|
+
const customPicker = new Picker('customMediaPicker', pickerFacadeConfig, this.options.customMediaPicker).init();
|
|
511
|
+
pickerPromises.push(customPicker);
|
|
512
|
+
pickers.push(this.customPicker = await customPicker);
|
|
513
|
+
}
|
|
514
|
+
pickers.forEach(picker => {
|
|
515
|
+
picker.onNewMedia(this.insertFile);
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// set new upload params for the pickers
|
|
520
|
+
pickers.forEach(picker => picker.setUploadParams(uploadParams));
|
|
521
|
+
}
|
|
522
|
+
collectionFromProvider() {
|
|
523
|
+
return this.mediaProvider && this.mediaProvider.uploadParams && this.mediaProvider.uploadParams.collection;
|
|
524
|
+
}
|
|
525
|
+
updateAndDispatch(props) {
|
|
526
|
+
// update plugin state
|
|
527
|
+
Object.keys(props).forEach(_key => {
|
|
528
|
+
const key = _key;
|
|
529
|
+
const value = props[key];
|
|
530
|
+
if (value !== undefined) {
|
|
531
|
+
this[key] = value;
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
if (this.dispatch) {
|
|
535
|
+
this.dispatch(stateKey, {
|
|
536
|
+
...this
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
export const getMediaPluginState = state => stateKey.getState(state);
|
|
542
|
+
export const createPlugin = (_schema, options, reactContext, getIntl, pluginInjectionApi, dispatch, mediaOptions, newInsertionBehaviour) => {
|
|
543
|
+
const intl = getIntl();
|
|
544
|
+
const dropPlaceholder = createDropPlaceholder(intl, mediaOptions && mediaOptions.allowDropzoneDropLine);
|
|
545
|
+
return new SafePlugin({
|
|
546
|
+
state: {
|
|
547
|
+
init(_config, state) {
|
|
548
|
+
return new MediaPluginStateImplementation(state, options, mediaOptions, newInsertionBehaviour, dispatch, pluginInjectionApi);
|
|
549
|
+
},
|
|
550
|
+
apply(tr, pluginState) {
|
|
551
|
+
const isResizing = tr.getMeta(MEDIA_PLUGIN_IS_RESIZING_KEY);
|
|
552
|
+
const resizingWidth = tr.getMeta(MEDIA_PLUGIN_RESIZING_WIDTH_KEY);
|
|
553
|
+
// Yes, I agree with you; this approach, using the clone() fuction, below is horrifying.
|
|
554
|
+
// However, we needed to implement this workaround to solve the singleton Media PluginState.
|
|
555
|
+
// The entire PluginInjectionAPI relies on the following axiom: "A PluginState that reflects a new EditorState.". We can not have the mutable singleton instance for all EditorState.
|
|
556
|
+
// Unfortunately, we can't implement a proper fix for this media state situation. So, we are faking a new object using a Proxy instance.
|
|
557
|
+
let nextPluginState = pluginState;
|
|
558
|
+
if (isResizing !== undefined) {
|
|
559
|
+
pluginState.setIsResizing(isResizing);
|
|
560
|
+
nextPluginState = nextPluginState.clone();
|
|
561
|
+
}
|
|
562
|
+
if (resizingWidth) {
|
|
563
|
+
pluginState.setResizingWidth(resizingWidth);
|
|
564
|
+
nextPluginState = nextPluginState.clone();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// remap editing media single position if we're in collab
|
|
568
|
+
if (typeof pluginState.editingMediaSinglePos === 'number') {
|
|
569
|
+
pluginState.editingMediaSinglePos = tr.mapping.map(pluginState.editingMediaSinglePos);
|
|
570
|
+
nextPluginState = nextPluginState.clone();
|
|
571
|
+
}
|
|
572
|
+
const meta = tr.getMeta(stateKey);
|
|
573
|
+
if (meta) {
|
|
574
|
+
const {
|
|
575
|
+
allowsUploads
|
|
576
|
+
} = meta;
|
|
577
|
+
pluginState.updateAndDispatch({
|
|
578
|
+
allowsUploads: typeof allowsUploads === 'undefined' ? pluginState.allowsUploads : allowsUploads
|
|
579
|
+
});
|
|
580
|
+
nextPluginState = nextPluginState.clone();
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// NOTE: We're not calling passing new state to the Editor, because we depend on the view.state reference
|
|
584
|
+
// throughout the lifetime of view. We injected the view into the plugin state, because we dispatch()
|
|
585
|
+
// transformations from within the plugin state (i.e. when adding a new file).
|
|
586
|
+
return nextPluginState;
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
appendTransaction(transactions, _oldState, newState) {
|
|
590
|
+
for (const transaction of transactions) {
|
|
591
|
+
const isSelectionOnMediaInsideMediaSingle = transaction.selectionSet && isNodeSelection(transaction.selection) && transaction.selection.node.type === newState.schema.nodes.media && transaction.selection.$anchor.parent.type === newState.schema.nodes.mediaSingle;
|
|
592
|
+
|
|
593
|
+
// Note: this causes an additional transaction when selecting a media node
|
|
594
|
+
// through clicking on it with the cursor.
|
|
595
|
+
if (isSelectionOnMediaInsideMediaSingle) {
|
|
596
|
+
// If a selection has been placed on a media inside a media single,
|
|
597
|
+
// we shift it to the media single parent as other code is opinionated about
|
|
598
|
+
// the selection landing there. In particular the caption insertion and selection
|
|
599
|
+
// action.
|
|
600
|
+
return newState.tr.setSelection(NodeSelection.create(newState.doc, transaction.selection.$from.pos - 1));
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return;
|
|
604
|
+
},
|
|
605
|
+
key: stateKey,
|
|
606
|
+
view: view => {
|
|
607
|
+
const pluginState = getMediaPluginState(view.state);
|
|
608
|
+
pluginState.setView(view);
|
|
609
|
+
pluginState.updateElement();
|
|
610
|
+
return {
|
|
611
|
+
update: () => {
|
|
612
|
+
pluginState.updateElement();
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
},
|
|
616
|
+
props: {
|
|
617
|
+
decorations: state => {
|
|
618
|
+
// Use this to indicate that the media node is selected
|
|
619
|
+
const mediaNodes = [];
|
|
620
|
+
const {
|
|
621
|
+
schema,
|
|
622
|
+
selection: {
|
|
623
|
+
$anchor
|
|
624
|
+
},
|
|
625
|
+
doc
|
|
626
|
+
} = state;
|
|
627
|
+
|
|
628
|
+
// Find any media nodes in the current selection
|
|
629
|
+
if (state.selection instanceof TextSelection || state.selection instanceof AllSelection || state.selection instanceof NodeSelection || state.selection instanceof CellSelection) {
|
|
630
|
+
doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
|
|
631
|
+
if (node.type === schema.nodes.media) {
|
|
632
|
+
mediaNodes.push(Decoration.node(pos, pos + node.nodeSize, {}, {
|
|
633
|
+
type: 'media',
|
|
634
|
+
selected: true
|
|
635
|
+
}));
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
return true;
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
const pluginState = getMediaPluginState(state);
|
|
642
|
+
if (!pluginState.showDropzone) {
|
|
643
|
+
return DecorationSet.create(state.doc, mediaNodes);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// When a media is already selected
|
|
647
|
+
if (state.selection instanceof NodeSelection) {
|
|
648
|
+
const node = state.selection.node;
|
|
649
|
+
if (node.type === schema.nodes.mediaSingle) {
|
|
650
|
+
const deco = Decoration.node(state.selection.from, state.selection.to, {
|
|
651
|
+
class: 'richMedia-selected'
|
|
652
|
+
});
|
|
653
|
+
return DecorationSet.create(state.doc, [deco, ...mediaNodes]);
|
|
654
|
+
}
|
|
655
|
+
return DecorationSet.create(state.doc, mediaNodes);
|
|
656
|
+
}
|
|
657
|
+
let pos = $anchor.pos;
|
|
658
|
+
if ($anchor.parent.type !== schema.nodes.paragraph && $anchor.parent.type !== schema.nodes.codeBlock) {
|
|
659
|
+
pos = insertPoint(state.doc, pos, schema.nodes.mediaGroup);
|
|
660
|
+
}
|
|
661
|
+
if (pos === null || pos === undefined) {
|
|
662
|
+
return DecorationSet.create(state.doc, mediaNodes);
|
|
663
|
+
}
|
|
664
|
+
const dropPlaceholders = [Decoration.widget(pos, dropPlaceholder, {
|
|
665
|
+
key: 'drop-placeholder'
|
|
666
|
+
}), ...mediaNodes];
|
|
667
|
+
return DecorationSet.create(state.doc, dropPlaceholders);
|
|
668
|
+
},
|
|
669
|
+
nodeViews: options.nodeViews,
|
|
670
|
+
handleTextInput(view) {
|
|
671
|
+
getMediaPluginState(view.state).splitMediaGroup();
|
|
672
|
+
return false;
|
|
673
|
+
},
|
|
674
|
+
handleClick: (_editorView, _pos, event) => {
|
|
675
|
+
var _event$target;
|
|
676
|
+
const clickedInsideCaptionPlaceholder = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.closest(`[data-id="${CAPTION_PLACEHOLDER_ID}"]`);
|
|
677
|
+
|
|
678
|
+
// Workaround for Chrome given a regression introduced in prosemirror-view@1.18.6
|
|
679
|
+
// Returning true prevents that updateSelection() is getting called in the commit below:
|
|
680
|
+
// @see https://github.com/ProseMirror/prosemirror-view/compare/1.18.5...1.18.6
|
|
681
|
+
if ((browser.chrome || browser.safari) && clickedInsideCaptionPlaceholder) {
|
|
682
|
+
return true;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Workaound for iOS 16 Caption selection issue
|
|
686
|
+
// @see https://product-fabric.atlassian.net/browse/MEX-2012
|
|
687
|
+
if (browser.ios) {
|
|
688
|
+
var _event$target2;
|
|
689
|
+
return !!((_event$target2 = event.target) !== null && _event$target2 !== void 0 && _event$target2.closest(`[class="${MEDIA_CONTENT_WRAP_CLASS_NAME}"]`));
|
|
690
|
+
}
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
};
|