@atlaskit/editor-plugin-media
Version:
Media plugin for @atlaskit/editor-core
328 lines (323 loc) • 16.8 kB
JavaScript
"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();
};
};