UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

644 lines (638 loc) 30.5 kB
import _get from "@babel/runtime/helpers/get"; import _extends from "@babel/runtime/helpers/extends"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized"; import _inherits from "@babel/runtime/helpers/inherits"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _regeneratorRuntime from "@babel/runtime/regenerator"; 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; } 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; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /** @jsx jsx */ import React, { Component } from 'react'; import { jsx } from '@emotion/react'; import { useSharedPluginState } from '@atlaskit/editor-common/hooks'; import { calcMediaSinglePixelWidth, DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH, getMaxWidthForNestedNode, MEDIA_SINGLE_GUTTER_SIZE } from '@atlaskit/editor-common/media-single'; import { WithProviders } from '@atlaskit/editor-common/provider-factory'; import ReactNodeView from '@atlaskit/editor-common/react-node-view'; import { MediaSingle } from '@atlaskit/editor-common/ui'; import { browser, isNodeSelectedOrInRange, setNodeSelection, setTextSelection } from '@atlaskit/editor-common/utils'; import { NodeSelection } from '@atlaskit/editor-prosemirror/state'; import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils'; import { CellSelection } from '@atlaskit/editor-tables/cell-selection'; import { getAttrsFromUrl } from '@atlaskit/media-client'; import { getBooleanFF } from '@atlaskit/platform-feature-flags'; import { insertAndSelectCaptionFromMediaSinglePos } from '../commands/captions'; import { MEDIA_CONTENT_WRAP_CLASS_NAME } from '../pm-plugins/main'; import CaptionPlaceholder from '../ui/CaptionPlaceholder'; import ResizableMediaSingle from '../ui/ResizableMediaSingle'; import ResizableMediaSingleNext from '../ui/ResizableMediaSingle/ResizableMediaSingleNext'; import { isMediaBlobUrlFromAttrs } from '../utils/media-common'; import { hasPrivateAttrsChanged } from './helpers'; import { MediaNodeUpdater } from './mediaNodeUpdater'; import { figureWrapper, MediaSingleNodeSelector } from './styles'; // eslint-disable-next-line @repo/internal/react/no-class-components var MediaSingleNode = /*#__PURE__*/function (_Component) { _inherits(MediaSingleNode, _Component); var _super = _createSuper(MediaSingleNode); function MediaSingleNode() { var _this; _classCallCheck(this, MediaSingleNode); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); _defineProperty(_assertThisInitialized(_this), "mediaNodeUpdater", null); _defineProperty(_assertThisInitialized(_this), "state", { width: undefined, height: undefined, viewMediaClientConfig: undefined, isCopying: false }); _defineProperty(_assertThisInitialized(_this), "mediaSingleWrapperRef", /*#__PURE__*/React.createRef()); _defineProperty(_assertThisInitialized(_this), "captionPlaceHolderRef", /*#__PURE__*/React.createRef()); _defineProperty(_assertThisInitialized(_this), "createOrUpdateMediaNodeUpdater", function (props) { var node = _this.props.node.firstChild; var updaterProps = _objectSpread(_objectSpread({}, props), {}, { isMediaSingle: true, node: node ? node : _this.props.node, dispatchAnalyticsEvent: _this.props.dispatchAnalyticsEvent }); if (!_this.mediaNodeUpdater) { _this.mediaNodeUpdater = new MediaNodeUpdater(updaterProps); } else { var _this$mediaNodeUpdate; (_this$mediaNodeUpdate = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate === void 0 || _this$mediaNodeUpdate.setProps(updaterProps); } }); _defineProperty(_assertThisInitialized(_this), "setViewMediaClientConfig", /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(props) { var mediaProvider, viewMediaClientConfig; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.next = 2; return props.mediaProvider; case 2: mediaProvider = _context.sent; if (mediaProvider) { viewMediaClientConfig = mediaProvider.viewMediaClientConfig; _this.setState({ viewMediaClientConfig: viewMediaClientConfig }); } case 4: case "end": return _context.stop(); } }, _callee); })); return function (_x) { return _ref.apply(this, arguments); }; }()); _defineProperty(_assertThisInitialized(_this), "updateMediaNodeAttributes", /*#__PURE__*/function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(props) { var _this$mediaNodeUpdate2, _this$props$node$firs, _this$mediaNodeUpdate4, _this$mediaNodeUpdate6; var addPendingTask, node, updatedDimensions, currentAttrs, _this$mediaNodeUpdate3, updatingNode, contextId, _this$mediaNodeUpdate5, hasDifferentContextId, copyNode; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: _this.createOrUpdateMediaNodeUpdater(props); addPendingTask = _this.props.mediaPluginState.addPendingTask; // we want the first child of MediaSingle (type "media") node = _this.props.node.firstChild; if (node) { _context2.next = 5; break; } return _context2.abrupt("return"); case 5: _context2.next = 7; return (_this$mediaNodeUpdate2 = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate2 === void 0 ? void 0 : _this$mediaNodeUpdate2.getRemoteDimensions(); case 7: updatedDimensions = _context2.sent; currentAttrs = (_this$props$node$firs = _this.props.node.firstChild) === null || _this$props$node$firs === void 0 ? void 0 : _this$props$node$firs.attrs; if (updatedDimensions && ((currentAttrs === null || currentAttrs === void 0 ? void 0 : currentAttrs.width) !== updatedDimensions.width || (currentAttrs === null || currentAttrs === void 0 ? void 0 : currentAttrs.height) !== updatedDimensions.height)) { (_this$mediaNodeUpdate3 = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate3 === void 0 || _this$mediaNodeUpdate3.updateDimensions(updatedDimensions); } if (!(node.attrs.type === 'external' && node.attrs.__external)) { _context2.next = 16; break; } updatingNode = _this.mediaNodeUpdater.handleExternalMedia(_this.props.getPos); addPendingTask(updatingNode); _context2.next = 15; return updatingNode; case 15: return _context2.abrupt("return"); case 16: contextId = (_this$mediaNodeUpdate4 = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate4 === void 0 ? void 0 : _this$mediaNodeUpdate4.getNodeContextId(); if (contextId) { _context2.next = 20; break; } _context2.next = 20; return (_this$mediaNodeUpdate5 = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate5 === void 0 ? void 0 : _this$mediaNodeUpdate5.updateContextId(); case 20: _context2.next = 22; return (_this$mediaNodeUpdate6 = _this.mediaNodeUpdater) === null || _this$mediaNodeUpdate6 === void 0 ? void 0 : _this$mediaNodeUpdate6.hasDifferentContextId(); case 22: hasDifferentContextId = _context2.sent; if (!hasDifferentContextId) { _context2.next = 35; break; } _this.setState({ isCopying: true }); _context2.prev = 25; copyNode = _this.mediaNodeUpdater.copyNode({ traceId: node.attrs.__mediaTraceId }); addPendingTask(copyNode); _context2.next = 30; return copyNode; case 30: _context2.next = 35; break; case 32: _context2.prev = 32; _context2.t0 = _context2["catch"](25); // if copyNode fails, let's set isCopying false so we can show the eventual error _this.setState({ isCopying: false }); case 35: case "end": return _context2.stop(); } }, _callee2, null, [[25, 32]]); })); return function (_x2) { return _ref2.apply(this, arguments); }; }()); _defineProperty(_assertThisInitialized(_this), "selectMediaSingle", function (_ref3) { var event = _ref3.event; var propPos = _this.props.getPos(); if (typeof propPos !== 'number') { return; } // We need to call "stopPropagation" here in order to prevent the browser from navigating to // another URL if the media node is wrapped in a link mark. event.stopPropagation(); var state = _this.props.view.state; if (event.shiftKey) { // don't select text if there is current selection in a table (as this would override selected cells) if (state.selection instanceof CellSelection) { return; } setTextSelection(_this.props.view, state.selection.from < propPos ? state.selection.from : propPos, // + 3 needed for offset of the media inside mediaSingle and cursor to make whole mediaSingle selected state.selection.to > propPos ? state.selection.to : propPos + 3); } else { setNodeSelection(_this.props.view, propPos); } }); _defineProperty(_assertThisInitialized(_this), "updateSize", function (width, layout) { var _this$props$view = _this.props.view, state = _this$props$view.state, dispatch = _this$props$view.dispatch; var pos = _this.props.getPos(); if (typeof pos === 'undefined') { return; } var tr = state.tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, _this.props.node.attrs), {}, { layout: layout, width: width, widthType: 'pixel' })); tr.setMeta('scrollIntoView', false); /** * Any changes to attributes of a node count the node as "recreated" in Prosemirror[1] * This makes it so Prosemirror resets the selection to the child i.e. "media" instead of "media-single" * The recommended fix is to reset the selection.[2] * * [1] https://discuss.prosemirror.net/t/setnodemarkup-loses-current-nodeselection/976 * [2] https://discuss.prosemirror.net/t/setnodemarkup-and-deselect/3673 */ tr.setSelection(NodeSelection.create(tr.doc, pos)); return dispatch(tr); }); // Workaround for iOS 16 Caption selection issue // @see https://product-fabric.atlassian.net/browse/MEX-2012 _defineProperty(_assertThisInitialized(_this), "onMediaSingleClicked", function (event) { var _this$captionPlaceHol; if (!browser.ios) { return; } if (_this.mediaSingleWrapperRef.current !== event.target) { return; } (_this$captionPlaceHol = _this.captionPlaceHolderRef.current) === null || _this$captionPlaceHol === void 0 || _this$captionPlaceHol.click(); }); _defineProperty(_assertThisInitialized(_this), "clickPlaceholder", function () { var _pluginInjectionApi$a; var _this$props = _this.props, view = _this$props.view, getPos = _this$props.getPos, node = _this$props.node, pluginInjectionApi = _this$props.pluginInjectionApi; if (typeof getPos === 'boolean') { return; } insertAndSelectCaptionFromMediaSinglePos(pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions)(getPos(), node)(view.state, view.dispatch); }); return _this; } _createClass(MediaSingleNode, [{ key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { if (!this.mediaNodeUpdater) { this.createOrUpdateMediaNodeUpdater(nextProps); } if (nextProps.mediaProvider !== this.props.mediaProvider) { this.setViewMediaClientConfig(nextProps); } // Forced updates not required on mobile if (nextProps.isCopyPasteEnabled === false) { return; } if (nextProps.mediaProvider !== this.props.mediaProvider) { var _this$mediaNodeUpdate7; this.createOrUpdateMediaNodeUpdater(nextProps); (_this$mediaNodeUpdate7 = this.mediaNodeUpdater) === null || _this$mediaNodeUpdate7 === void 0 || _this$mediaNodeUpdate7.updateMediaSingleFileAttrs(); } else if (nextProps.node.firstChild && this.props.node.firstChild) { var attrsChanged = hasPrivateAttrsChanged(this.props.node.firstChild.attrs, nextProps.node.firstChild.attrs); if (attrsChanged) { var _this$mediaNodeUpdate8; this.createOrUpdateMediaNodeUpdater(nextProps); // We need to call this method on any prop change since attrs can get removed with collab editing (_this$mediaNodeUpdate8 = this.mediaNodeUpdater) === null || _this$mediaNodeUpdate8 === void 0 || _this$mediaNodeUpdate8.updateMediaSingleFileAttrs(); } } } }, { key: "componentDidMount", value: function () { var _componentDidMount = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() { var contextIdentifierProvider; return _regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: contextIdentifierProvider = this.props.contextIdentifierProvider; this.createOrUpdateMediaNodeUpdater(this.props); _context3.next = 4; return Promise.all([this.setViewMediaClientConfig(this.props), this.updateMediaNodeAttributes(this.props)]); case 4: _context3.t0 = this; _context3.next = 7; return contextIdentifierProvider; case 7: _context3.t1 = _context3.sent; _context3.t2 = { contextIdentifierProvider: _context3.t1 }; _context3.t0.setState.call(_context3.t0, _context3.t2); case 10: case "end": return _context3.stop(); } }, _callee3, this); })); function componentDidMount() { return _componentDidMount.apply(this, arguments); } return componentDidMount; }() }, { key: "render", value: function render() { var _pluginInjectionApi$m; var _this$props2 = this.props, selected = _this$props2.selected, getPos = _this$props2.getPos, node = _this$props2.node, mediaOptions = _this$props2.mediaOptions, fullWidthMode = _this$props2.fullWidthMode, state = _this$props2.view.state, view = _this$props2.view, pluginInjectionApi = _this$props2.pluginInjectionApi, containerWidth = _this$props2.width, lineLength = _this$props2.lineLength, dispatchAnalyticsEvent = _this$props2.dispatchAnalyticsEvent; var _ref4 = node.attrs, layout = _ref4.layout, widthType = _ref4.widthType, mediaSingleWidthAttribute = _ref4.width; var childNode = node.firstChild; var attrs = (childNode === null || childNode === void 0 ? void 0 : childNode.attrs) || {}; // original width and height of child media node (scaled) var width = attrs.width, height = attrs.height; if (attrs.type === 'external') { if (isMediaBlobUrlFromAttrs(attrs)) { var urlAttrs = getAttrsFromUrl(attrs.url); if (urlAttrs) { var urlWidth = urlAttrs.width, urlHeight = urlAttrs.height; width = width || urlWidth; height = height || urlHeight; } } var _this$state = this.state, stateWidth = _this$state.width, stateHeight = _this$state.height; if (width === null) { width = stateWidth || DEFAULT_IMAGE_WIDTH; } if (height === null) { height = stateHeight || DEFAULT_IMAGE_HEIGHT; } } if (!width || !height) { width = DEFAULT_IMAGE_WIDTH; height = DEFAULT_IMAGE_HEIGHT; } var isSelected = selected(); var currentMaxWidth = isSelected ? pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$m = pluginInjectionApi.media.sharedState.currentState()) === null || _pluginInjectionApi$m === void 0 ? void 0 : _pluginInjectionApi$m.currentMaxWidth : undefined; var contentWidthForLegacyExperience = getMaxWidthForNestedNode(view, getPos()) || lineLength; var contentWidth = currentMaxWidth || lineLength; var mediaSingleProps = { layout: layout, width: width, height: height, containerWidth: containerWidth, lineLength: contentWidth, fullWidthMode: fullWidthMode, hasFallbackContainer: false, mediaSingleWidth: calcMediaSinglePixelWidth({ width: mediaSingleWidthAttribute, widthType: widthType, origWidth: width, layout: layout, // This will only be used when calculating legacy media single width // thus we use the legacy value (exclude table as container node) contentWidth: contentWidthForLegacyExperience, containerWidth: containerWidth, gutterOffset: MEDIA_SINGLE_GUTTER_SIZE }), allowCaptions: mediaOptions.allowCaptions }; var resizableMediaSingleProps = _objectSpread({ view: view, getPos: getPos, updateSize: this.updateSize, gridSize: 12, viewMediaClientConfig: this.state.viewMediaClientConfig, allowBreakoutSnapPoints: mediaOptions && mediaOptions.allowBreakoutSnapPoints, selected: isSelected, dispatchAnalyticsEvent: dispatchAnalyticsEvent, pluginInjectionApi: pluginInjectionApi }, mediaSingleProps); var canResize = !!this.props.mediaOptions.allowResizing; if (!this.props.mediaOptions.allowResizingInTables) { // If resizing not allowed in tables, check parents for tables var pos = getPos(); if (pos) { var $pos = state.doc.resolve(pos); var table = state.schema.nodes.table; var disabledNode = !!findParentNodeOfTypeClosestToPos($pos, [table]); canResize = canResize && !disabledNode; } } var shouldShowPlaceholder = mediaOptions.allowCaptions && node.childCount !== 2 && isSelected && state.selection instanceof NodeSelection; var MediaChildren = jsx("figure", { ref: this.mediaSingleWrapperRef, css: [figureWrapper], className: MediaSingleNodeSelector, onClick: this.onMediaSingleClicked }, jsx("div", { ref: this.props.forwardRef }), shouldShowPlaceholder && jsx(CaptionPlaceholder, { ref: this.captionPlaceHolderRef, onClick: this.clickPlaceholder })); return canResize ? getBooleanFF('platform.editor.media.extended-resize-experience') ? jsx(ResizableMediaSingleNext, _extends({}, resizableMediaSingleProps, { showLegacyNotification: widthType !== 'pixel' }), MediaChildren) : jsx(ResizableMediaSingle, _extends({}, resizableMediaSingleProps, { lineLength: contentWidthForLegacyExperience, pctWidth: mediaSingleWidthAttribute }), MediaChildren) : jsx(MediaSingle, _extends({}, mediaSingleProps, { pctWidth: mediaSingleWidthAttribute }), MediaChildren); } }]); return MediaSingleNode; }(Component); _defineProperty(MediaSingleNode, "defaultProps", { mediaOptions: {} }); _defineProperty(MediaSingleNode, "displayName", 'MediaSingleNode'); export { MediaSingleNode as default }; var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(_ref5) { var pluginInjectionApi = _ref5.pluginInjectionApi, mediaProvider = _ref5.mediaProvider, contextIdentifierProvider = _ref5.contextIdentifierProvider, node = _ref5.node, getPos = _ref5.getPos, mediaOptions = _ref5.mediaOptions, view = _ref5.view, fullWidthMode = _ref5.fullWidthMode, selected = _ref5.selected, eventDispatcher = _ref5.eventDispatcher, dispatchAnalyticsEvent = _ref5.dispatchAnalyticsEvent, forwardRef = _ref5.forwardRef; var _useSharedPluginState = useSharedPluginState(pluginInjectionApi, ['width', 'media']), widthState = _useSharedPluginState.widthState, mediaState = _useSharedPluginState.mediaState; return jsx(MediaSingleNode, { width: widthState.width, lineLength: widthState.lineLength, node: node, getPos: getPos, mediaProvider: mediaProvider, contextIdentifierProvider: contextIdentifierProvider, mediaOptions: mediaOptions, view: view, fullWidthMode: fullWidthMode, selected: selected, eventDispatcher: eventDispatcher, mediaPluginState: mediaState !== null && mediaState !== void 0 ? mediaState : undefined, dispatchAnalyticsEvent: dispatchAnalyticsEvent, forwardRef: forwardRef, pluginInjectionApi: pluginInjectionApi }); }; var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) { _inherits(MediaSingleNodeView, _ReactNodeView); var _super2 = _createSuper(MediaSingleNodeView); function MediaSingleNodeView() { var _this2; _classCallCheck(this, MediaSingleNodeView); for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } _this2 = _super2.call.apply(_super2, [this].concat(args)); _defineProperty(_assertThisInitialized(_this2), "lastOffsetLeft", 0); _defineProperty(_assertThisInitialized(_this2), "forceViewUpdate", false); _defineProperty(_assertThisInitialized(_this2), "selectionType", null); _defineProperty(_assertThisInitialized(_this2), "checkAndUpdateSelectionType", function () { var getPos = _this2.getPos; var selection = _this2.view.state.selection; /** * ED-19831 * There is a getPos issue coming from this code. We need to apply this workaround for now and apply a patch * directly to confluence since this bug is now in production. */ var pos; try { pos = getPos ? getPos() : undefined; } catch (e) { pos = undefined; } var isNodeSelected = isNodeSelectedOrInRange(selection.$anchor.pos, selection.$head.pos, pos, _this2.node.nodeSize); _this2.selectionType = isNodeSelected; return isNodeSelected; }); _defineProperty(_assertThisInitialized(_this2), "isNodeSelected", function () { _this2.checkAndUpdateSelectionType(); return _this2.selectionType !== null; }); return _this2; } _createClass(MediaSingleNodeView, [{ key: "createDomRef", value: function createDomRef() { var domRef = document.createElement('div'); if (this.reactComponentProps.mediaOptions && this.reactComponentProps.mediaOptions.allowMediaSingleEditable) { // workaround Chrome bug in https://product-fabric.atlassian.net/browse/ED-5379 // see also: https://github.com/ProseMirror/prosemirror/issues/884 domRef.contentEditable = 'true'; } if (getBooleanFF('platform.editor.media.extended-resize-experience')) { domRef.classList.add('media-extended-resize-experience'); } return domRef; } }, { key: "getContentDOM", value: function getContentDOM() { var dom = document.createElement('div'); dom.classList.add(MEDIA_CONTENT_WRAP_CLASS_NAME); return { dom: dom }; } }, { key: "viewShouldUpdate", value: function viewShouldUpdate(nextNode) { if (this.forceViewUpdate) { this.forceViewUpdate = false; return true; } if (this.node.attrs !== nextNode.attrs) { return true; } if (this.selectionType !== this.checkAndUpdateSelectionType()) { return true; } if (this.node.childCount !== nextNode.childCount) { return true; } return _get(_getPrototypeOf(MediaSingleNodeView.prototype), "viewShouldUpdate", this).call(this, nextNode); } }, { key: "getNodeMediaId", value: function getNodeMediaId(node) { if (node.firstChild) { return node.firstChild.attrs.id; } return undefined; } }, { key: "update", value: function update(node, decorations, _innerDecorations, isValidUpdate) { var _this3 = this; if (!isValidUpdate) { isValidUpdate = function isValidUpdate(currentNode, newNode) { return _this3.getNodeMediaId(currentNode) === _this3.getNodeMediaId(newNode); }; } return _get(_getPrototypeOf(MediaSingleNodeView.prototype), "update", this).call(this, node, decorations, _innerDecorations, isValidUpdate); } }, { key: "render", value: function render(props, forwardRef) { var _this4 = this; var _this$reactComponentP = this.reactComponentProps, eventDispatcher = _this$reactComponentP.eventDispatcher, fullWidthMode = _this$reactComponentP.fullWidthMode, providerFactory = _this$reactComponentP.providerFactory, mediaOptions = _this$reactComponentP.mediaOptions, dispatchAnalyticsEvent = _this$reactComponentP.dispatchAnalyticsEvent, pluginInjectionApi = _this$reactComponentP.pluginInjectionApi; // getPos is a boolean for marks, since this is a node we know it must be a function var getPos = this.getPos; return jsx(WithProviders, { providers: ['mediaProvider', 'contextIdentifierProvider'], providerFactory: providerFactory, renderNode: function renderNode(_ref6) { var mediaProvider = _ref6.mediaProvider, contextIdentifierProvider = _ref6.contextIdentifierProvider; return jsx(MediaSingleNodeWrapper, { pluginInjectionApi: pluginInjectionApi, mediaProvider: mediaProvider, contextIdentifierProvider: contextIdentifierProvider, node: _this4.node, getPos: getPos, mediaOptions: mediaOptions, view: _this4.view, fullWidthMode: fullWidthMode, selected: _this4.isNodeSelected, eventDispatcher: eventDispatcher, dispatchAnalyticsEvent: dispatchAnalyticsEvent, forwardRef: forwardRef }); } }); } }, { key: "ignoreMutation", value: function ignoreMutation() { // DOM has changed; recalculate if we need to re-render if (this.dom) { var offsetLeft = this.dom.offsetLeft; if (offsetLeft !== this.lastOffsetLeft) { this.lastOffsetLeft = offsetLeft; this.forceViewUpdate = true; this.update(this.node, [], undefined, function () { return true; }); } } return true; } }]); return MediaSingleNodeView; }(ReactNodeView); export var ReactMediaSingleNode = function ReactMediaSingleNode(portalProviderAPI, eventDispatcher, providerFactory, pluginInjectionApi, dispatchAnalyticsEvent) { var mediaOptions = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; return function (node, view, getPos) { var hasIntlContext = true; return new MediaSingleNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, { eventDispatcher: eventDispatcher, fullWidthMode: mediaOptions.fullWidthEnabled, providerFactory: providerFactory, mediaOptions: mediaOptions, dispatchAnalyticsEvent: dispatchAnalyticsEvent, isCopyPasteEnabled: mediaOptions.isCopyPasteEnabled, pluginInjectionApi: pluginInjectionApi }, undefined, undefined, undefined, hasIntlContext).init(); }; };