UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

328 lines (323 loc) 16.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ReactMediaSingleNode = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = require("react"); var _react2 = require("@emotion/react"); var _hooks = require("@atlaskit/editor-common/hooks"); var _providerFactory = require("@atlaskit/editor-common/provider-factory"); var _reactNodeView = _interopRequireDefault(require("@atlaskit/editor-common/react-node-view")); var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector"); var _utils = require("@atlaskit/editor-common/utils"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _main = require("../pm-plugins/main"); var _mediaSingleNext = require("./mediaSingleNext"); function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; } /** * @jsxRuntime classic * @jsx jsx * @jsxFrag */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports // eslint-disable-next-line @typescript-eslint/consistent-type-imports var selector = function selector(states) { var _states$mediaState, _states$mediaState2, _states$annotationSta, _states$annotationSta2, _states$widthState, _states$widthState2, _states$editorDisable, _states$editorViewMod; return { mediaProviderPromise: (_states$mediaState = states.mediaState) === null || _states$mediaState === void 0 ? void 0 : _states$mediaState.mediaProvider, addPendingTask: (_states$mediaState2 = states.mediaState) === null || _states$mediaState2 === void 0 ? void 0 : _states$mediaState2.addPendingTask, isDrafting: (_states$annotationSta = states.annotationState) === null || _states$annotationSta === void 0 ? void 0 : _states$annotationSta.isDrafting, targetNodeId: (_states$annotationSta2 = states.annotationState) === null || _states$annotationSta2 === void 0 ? void 0 : _states$annotationSta2.targetNodeId, width: (_states$widthState = states.widthState) === null || _states$widthState === void 0 ? void 0 : _states$widthState.width, lineLength: (_states$widthState2 = states.widthState) === null || _states$widthState2 === void 0 ? void 0 : _states$widthState2.lineLength, editorDisabled: (_states$editorDisable = states.editorDisabledState) === null || _states$editorDisable === void 0 ? void 0 : _states$editorDisable.editorDisabled, viewMode: (_states$editorViewMod = states.editorViewModeState) === null || _states$editorViewMod === void 0 ? void 0 : _states$editorViewMod.mode }; }; var MediaSingleNodeWrapper = function MediaSingleNodeWrapper(_ref) { var pluginInjectionApi = _ref.pluginInjectionApi, contextIdentifierProvider = _ref.contextIdentifierProvider, node = _ref.node, getPos = _ref.getPos, mediaOptions = _ref.mediaOptions, view = _ref.view, fullWidthMode = _ref.fullWidthMode, selected = _ref.selected, eventDispatcher = _ref.eventDispatcher, dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent, forwardRef = _ref.forwardRef, editorAppearance = _ref.editorAppearance; var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(pluginInjectionApi, ['width', 'media', 'annotation', 'editorDisabled', 'editorViewMode'], selector), mediaProviderPromise = _useSharedPluginState.mediaProviderPromise, addPendingTask = _useSharedPluginState.addPendingTask, isDrafting = _useSharedPluginState.isDrafting, targetNodeId = _useSharedPluginState.targetNodeId, width = _useSharedPluginState.width, lineLength = _useSharedPluginState.lineLength, editorDisabled = _useSharedPluginState.editorDisabled, viewMode = _useSharedPluginState.viewMode; var interactionState = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(pluginInjectionApi, 'interaction.interactionState'); var mediaProvider = (0, _react.useMemo)(function () { return mediaProviderPromise ? Promise.resolve(mediaProviderPromise) : undefined; }, [mediaProviderPromise]); var isSelectedAndInteracted = (0, _react.useCallback)(function () { return Boolean(selected() && interactionState !== 'hasNotHadInteraction'); }, [interactionState, selected]); return (0, _react2.jsx)(_mediaSingleNext.MediaSingleNodeNext, { width: width || 0, lineLength: lineLength || 0, node: node, getPos: getPos, mediaProvider: mediaProvider, contextIdentifierProvider: contextIdentifierProvider, mediaOptions: mediaOptions, view: view, fullWidthMode: fullWidthMode, selected: isSelectedAndInteracted, eventDispatcher: eventDispatcher, addPendingTask: addPendingTask, isDrafting: isDrafting, targetNodeId: targetNodeId, dispatchAnalyticsEvent: dispatchAnalyticsEvent, forwardRef: forwardRef, pluginInjectionApi: pluginInjectionApi, editorDisabled: editorDisabled, editorViewMode: viewMode === 'view', editorAppearance: editorAppearance }); }; var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) { function MediaSingleNodeView() { var _this; (0, _classCallCheck2.default)(this, MediaSingleNodeView); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, MediaSingleNodeView, [].concat(args)); (0, _defineProperty2.default)(_this, "lastOffsetLeft", 0); (0, _defineProperty2.default)(_this, "forceViewUpdate", false); (0, _defineProperty2.default)(_this, "selectionType", null); (0, _defineProperty2.default)(_this, "hasResized", false); (0, _defineProperty2.default)(_this, "checkAndUpdateSelectionType", function () { var getPos = _this.getPos; var selection = _this.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 (_unused) { pos = undefined; } var isNodeSelected = (0, _utils.isNodeSelectedOrInRange)(selection.$anchor.pos, selection.$head.pos, pos, _this.node.nodeSize); _this.selectionType = isNodeSelected; return isNodeSelected; }); (0, _defineProperty2.default)(_this, "isNodeSelected", function () { _this.checkAndUpdateSelectionType(); return _this.selectionType !== null; }); return _this; } (0, _inherits2.default)(MediaSingleNodeView, _ReactNodeView); return (0, _createClass2.default)(MediaSingleNodeView, [{ key: "createDomRef", value: function createDomRef() { var _this$reactComponentP, _this$reactComponentP2; var domRef = document.createElement('div'); // control the domRef contentEditable attribute based on the editor view mode this.unsubscribeToViewModeChange = this.subscribeToViewModeChange(domRef); var initialViewMode = (_this$reactComponentP = this.reactComponentProps.pluginInjectionApi) === null || _this$reactComponentP === void 0 || (_this$reactComponentP = _this$reactComponentP.editorViewMode) === null || _this$reactComponentP === void 0 || (_this$reactComponentP = _this$reactComponentP.sharedState.currentState()) === null || _this$reactComponentP === void 0 ? void 0 : _this$reactComponentP.mode; this.updateDomRefContentEditable(domRef, initialViewMode); if ((_this$reactComponentP2 = this.reactComponentProps.mediaOptions) !== null && _this$reactComponentP2 !== void 0 && _this$reactComponentP2.allowPixelResizing) { domRef.classList.add('media-extended-resize-experience'); } domRef.setAttribute('data-media-vc-wrapper', 'true'); return domRef; } }, { key: "getContentDOM", value: function getContentDOM() { var dom = document.createElement('div'); dom.classList.add(_main.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 _superPropGet(MediaSingleNodeView, "viewShouldUpdate", this, 3)([nextNode]); } }, { key: "subscribeToViewModeChange", value: function subscribeToViewModeChange(domRef) { var _this$reactComponentP3, _this2 = this; return (_this$reactComponentP3 = this.reactComponentProps.pluginInjectionApi) === null || _this$reactComponentP3 === void 0 || (_this$reactComponentP3 = _this$reactComponentP3.editorViewMode) === null || _this$reactComponentP3 === void 0 ? void 0 : _this$reactComponentP3.sharedState.onChange(function (viewModeState) { var _viewModeState$nextSh; _this2.updateDomRefContentEditable(domRef, (_viewModeState$nextSh = viewModeState.nextSharedState) === null || _viewModeState$nextSh === void 0 ? void 0 : _viewModeState$nextSh.mode); }); } }, { key: "updateDomRefContentEditable", value: function updateDomRefContentEditable(domRef, editorViewMode) { var _this$reactComponentP4; // if the editor is in view mode, we should not allow editing if (editorViewMode === 'view') { domRef.contentEditable = 'false'; return; } // if the editor is in edit mode, we should allow editing if the media options allow it if ((_this$reactComponentP4 = this.reactComponentProps.mediaOptions) !== null && _this$reactComponentP4 !== void 0 && _this$reactComponentP4.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'; } } }, { key: "getNodeMediaId", value: function getNodeMediaId(node) { if (node.firstChild) { return node.firstChild.attrs.id; } return undefined; } }, { key: "stopEvent", value: function stopEvent(event) { if (this.isNodeSelected() && event instanceof KeyboardEvent && (event === null || event === void 0 ? void 0 : event.target) instanceof HTMLElement) { var targetType = event.target.type; if (event.key === 'Enter' && targetType === 'button') { return true; } } return false; } }, { 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); }; } // Detect mediaSingle width attribute changes and signal child media node to update if (!this.hasResized && this.node.attrs.width !== node.attrs.width && (0, _expValEquals.expValEquals)('platform_editor_media_vc_fixes', 'isEnabled', true)) { var target = this.dom.querySelector('div[data-prosemirror-node-name="media"]'); target === null || target === void 0 || target.dispatchEvent(new CustomEvent('resized')); } return _superPropGet(MediaSingleNodeView, "update", this, 3)([node, decorations, _innerDecorations, isValidUpdate]); } }, { key: "render", value: function render(props, forwardRef) { var _this4 = this; var _this$reactComponentP5 = this.reactComponentProps, eventDispatcher = _this$reactComponentP5.eventDispatcher, fullWidthMode = _this$reactComponentP5.fullWidthMode, providerFactory = _this$reactComponentP5.providerFactory, mediaOptions = _this$reactComponentP5.mediaOptions, dispatchAnalyticsEvent = _this$reactComponentP5.dispatchAnalyticsEvent, pluginInjectionApi = _this$reactComponentP5.pluginInjectionApi, editorAppearance = _this$reactComponentP5.editorAppearance; // getPos is a boolean for marks, since this is a node we know it must be a function var getPos = this.getPos; return (0, _react2.jsx)(_providerFactory.WithProviders // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , { providers: ['contextIdentifierProvider'], providerFactory: providerFactory // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , renderNode: function renderNode(_ref2) { var contextIdentifierProvider = _ref2.contextIdentifierProvider; return (0, _react2.jsx)(MediaSingleNodeWrapper, { pluginInjectionApi: pluginInjectionApi, contextIdentifierProvider: contextIdentifierProvider, node: _this4.node, getPos: getPos, mediaOptions: mediaOptions, view: _this4.view, fullWidthMode: fullWidthMode, selected: _this4.isNodeSelected, eventDispatcher: eventDispatcher // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , dispatchAnalyticsEvent: dispatchAnalyticsEvent // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion , forwardRef: forwardRef, editorAppearance: editorAppearance }); } }); } }, { key: "ignoreMutation", value: function ignoreMutation() { // DOM has changed; recalculate if we need to re-render if (this.dom) { // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting 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; } }, { key: "destroy", value: function destroy() { var _this$unsubscribeToVi; (_this$unsubscribeToVi = this.unsubscribeToViewModeChange) === null || _this$unsubscribeToVi === void 0 || _this$unsubscribeToVi.call(this); } }]); }(_reactNodeView.default); var ReactMediaSingleNode = exports.ReactMediaSingleNode = function ReactMediaSingleNode(portalProviderAPI, eventDispatcher, providerFactory, pluginInjectionApi, dispatchAnalyticsEvent) { var mediaOptions = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; return function (node, view, getPos) { return new MediaSingleNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, { eventDispatcher: eventDispatcher, fullWidthMode: mediaOptions.fullWidthEnabled, providerFactory: providerFactory, mediaOptions: mediaOptions, dispatchAnalyticsEvent: dispatchAnalyticsEvent, isCopyPasteEnabled: mediaOptions.isCopyPasteEnabled, pluginInjectionApi: pluginInjectionApi, editorAppearance: mediaOptions.editorAppearance }).init(); }; };