UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

448 lines (443 loc) 18.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 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 _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _react2 = require("@emotion/react"); var _mediaSingle = require("@atlaskit/editor-common/media-single"); var _ui = require("@atlaskit/editor-common/ui"); var _utils = require("@atlaskit/editor-common/utils"); var _utils2 = require("@atlaskit/editor-prosemirror/utils"); var _editorSharedStyles = require("@atlaskit/editor-shared-styles"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _checkMediaType = require("../../pm-plugins/utils/check-media-type"); var _styled = require("./styled"); 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; })(); } /** * @jsxRuntime classic * @jsx jsx */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports // eslint-disable-next-line @repo/internal/react/no-class-components var ResizableMediaSingle = exports.default = /*#__PURE__*/function (_React$Component) { function ResizableMediaSingle() { var _this; (0, _classCallCheck2.default)(this, ResizableMediaSingle); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, ResizableMediaSingle, [].concat(args)); (0, _defineProperty2.default)(_this, "hasResized", false); (0, _defineProperty2.default)(_this, "state", { offsetLeft: (0, _mediaSingle.calculateOffsetLeft)(_this.insideInlineLike, _this.insideLayout, _this.props.view.dom, undefined), isVideoFile: false }); (0, _defineProperty2.default)(_this, "displayGrid", function (visible, gridType, highlight) { var _pluginInjectionApi$g; var _this$props = _this.props, pluginInjectionApi = _this$props.pluginInjectionApi, view = _this$props.view; pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$g = pluginInjectionApi.grid) === null || _pluginInjectionApi$g === void 0 || (_pluginInjectionApi$g = _pluginInjectionApi$g.actions) === null || _pluginInjectionApi$g === void 0 || _pluginInjectionApi$g.displayGrid(view)({ visible: visible, gridType: gridType, highlight: highlight }); }); (0, _defineProperty2.default)(_this, "calcNewSize", function (newWidth, stop) { var _this$props2 = _this.props, layout = _this$props2.layout, state = _this$props2.view.state; if (!_this.hasResized && (0, _expValEquals.expValEquals)('platform_editor_media_vc_fixes', 'isEnabled', true)) { var _this$wrapper; var mediaDomEl = (_this$wrapper = _this.wrapper) === null || _this$wrapper === void 0 ? void 0 : _this$wrapper.querySelector('div[data-prosemirror-node-name="media"]'); if (mediaDomEl) { var event = new CustomEvent('resized'); mediaDomEl === null || mediaDomEl === void 0 || mediaDomEl.dispatchEvent(event); } _this.hasResized = true; } var newPct = (0, _ui.calcPctFromPx)(newWidth, _this.props.lineLength) * 100; _this.setState({ resizedPctWidth: newPct }); var newLayout = (0, _utils2.hasParentNodeOfType)(state.schema.nodes.table)(state.selection) ? layout : _this.calcUnwrappedLayout(newPct, newWidth); if (newPct <= 100) { if (_this.wrappedLayout && (stop ? newPct !== 100 : true)) { newLayout = layout; } return { width: newPct, layout: newLayout }; } else { return { width: _this.props.pctWidth || null, layout: newLayout }; } }); (0, _defineProperty2.default)(_this, "calcUnwrappedLayout", function (pct, width) { if (pct <= 100) { return 'center'; } if (width <= _editorSharedStyles.akEditorWideLayoutWidth) { return 'wide'; } return 'full-width'; }); (0, _defineProperty2.default)(_this, "calcColumnLeftOffset", function () { var offsetLeft = _this.state.offsetLeft; return _this.insideInlineLike ? (0, _ui.calcColumnsFromPx)(offsetLeft, _this.props.lineLength, _this.props.gridSize) : 0; }); (0, _defineProperty2.default)(_this, "calcPxWidth", function (useLayout) { var _this$props3 = _this.props, _this$props3$width = _this$props3.width, origWidth = _this$props3$width === void 0 ? 0 : _this$props3$width, origHeight = _this$props3.height, layout = _this$props3.layout, pctWidth = _this$props3.pctWidth, lineLength = _this$props3.lineLength, containerWidth = _this$props3.containerWidth, fullWidthMode = _this$props3.fullWidthMode, getPos = _this$props3.getPos, state = _this$props3.view.state; var resizedPctWidth = _this.state.resizedPctWidth; var pos = typeof getPos === 'function' ? getPos() : undefined; return (0, _ui.calcMediaPxWidth)({ origWidth: origWidth, origHeight: origHeight, pctWidth: pctWidth, state: state, containerWidth: { width: containerWidth, lineLength: lineLength }, isFullWidthModeEnabled: fullWidthMode, layout: useLayout || layout, pos: pos, resizedPctWidth: resizedPctWidth }); }); (0, _defineProperty2.default)(_this, "highlights", function (newWidth, snapPoints) { var snapWidth = (0, _ui.snapTo)(newWidth, snapPoints); var _this$props$view$stat = _this.props.view.state.schema.nodes, layoutColumn = _this$props$view$stat.layoutColumn, table = _this$props$view$stat.table, expand = _this$props$view$stat.expand, nestedExpand = _this$props$view$stat.nestedExpand, panel = _this$props$view$stat.panel; if (_this.$pos && !!(0, _utils2.findParentNodeOfTypeClosestToPos)(_this.$pos, [layoutColumn, table, expand, nestedExpand, panel].filter(Boolean))) { return []; } if (snapWidth > _editorSharedStyles.akEditorWideLayoutWidth) { return ['full-width']; } var _this$props4 = _this.props, layout = _this$props4.layout, lineLength = _this$props4.lineLength, gridSize = _this$props4.gridSize; var columns = (0, _ui.calcColumnsFromPx)(snapWidth, lineLength, gridSize); var columnWidth = Math.round(columns); var highlight = []; if (layout === 'wrap-left' || layout === 'align-start') { highlight.push(0, columnWidth); } else if (layout === 'wrap-right' || layout === 'align-end') { highlight.push(gridSize, gridSize - columnWidth); } else if (_this.insideInlineLike) { highlight.push(Math.round(columns + _this.calcColumnLeftOffset())); } else { highlight.push(Math.floor((gridSize - columnWidth) / 2), Math.ceil((gridSize + columnWidth) / 2)); } return highlight; }); (0, _defineProperty2.default)(_this, "saveWrapper", function (wrapper) { return _this.wrapper = wrapper; }); return _this; } (0, _inherits2.default)(ResizableMediaSingle, _React$Component); return (0, _createClass2.default)(ResizableMediaSingle, [{ key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var offsetLeft = (0, _mediaSingle.calculateOffsetLeft)(this.insideInlineLike, this.insideLayout, this.props.view.dom, this.wrapper); if (offsetLeft !== this.state.offsetLeft && offsetLeft >= 0) { this.setState({ offsetLeft: offsetLeft }); } // Handle undo, when the actual pctWidth changed, // we sync up with the internal state. if (prevProps.pctWidth !== this.props.pctWidth) { this.setState({ resizedPctWidth: this.props.pctWidth }); } return true; } }, { key: "wrappedLayout", get: function get() { return _ui.wrappedLayouts.indexOf(this.props.layout) > -1; } // check if is inside of a table }, { key: "isNestedInTable", value: function isNestedInTable() { var table = this.props.view.state.schema.nodes.table; if (!this.$pos) { return false; } return !!(0, _utils2.findParentNodeOfTypeClosestToPos)(this.$pos, table); } }, { key: "componentDidMount", value: function () { var _componentDidMount = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() { var viewMediaClientConfig; return _regenerator.default.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: viewMediaClientConfig = this.props.viewMediaClientConfig; if (!viewMediaClientConfig) { _context.next = 4; break; } _context.next = 4; return this.checkVideoFile(viewMediaClientConfig); case 4: case "end": return _context.stop(); } }, _callee, this); })); function componentDidMount() { return _componentDidMount.apply(this, arguments); } return componentDidMount; }() }, { key: "UNSAFE_componentWillReceiveProps", value: function UNSAFE_componentWillReceiveProps(nextProps) { if (this.props.viewMediaClientConfig !== nextProps.viewMediaClientConfig) { this.checkVideoFile(nextProps.viewMediaClientConfig); } if (this.props.layout !== nextProps.layout) { this.checkLayout(this.props.layout, nextProps.layout); } } }, { key: "checkVideoFile", value: function () { var _checkVideoFile = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(viewMediaClientConfig) { var $pos, mediaNode, mediaType, isVideoFile; return _regenerator.default.wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: $pos = this.$pos; if (!(!$pos || !viewMediaClientConfig)) { _context2.next = 3; break; } return _context2.abrupt("return"); case 3: mediaNode = this.props.view.state.doc.nodeAt($pos.pos + 1); if (!mediaNode) { _context2.next = 10; break; } _context2.next = 7; return (0, _checkMediaType.checkMediaType)(mediaNode, viewMediaClientConfig); case 7: _context2.t0 = _context2.sent; _context2.next = 11; break; case 10: _context2.t0 = undefined; case 11: mediaType = _context2.t0; isVideoFile = mediaType !== 'external' && mediaType !== 'image'; if (this.state.isVideoFile !== isVideoFile) { this.setState({ isVideoFile: isVideoFile }); } case 14: case "end": return _context2.stop(); } }, _callee2, this); })); function checkVideoFile(_x) { return _checkVideoFile.apply(this, arguments); } return checkVideoFile; }() /** * When returning to center layout from a wrapped/aligned layout, it might actually * be wide or full-width */ }, { key: "checkLayout", value: function checkLayout(oldLayout, newLayout) { var resizedPctWidth = this.state.resizedPctWidth; if (_ui.wrappedLayouts.indexOf(oldLayout) > -1 && newLayout === 'center' && resizedPctWidth) { var layout = this.calcUnwrappedLayout(resizedPctWidth, this.calcPxWidth(newLayout)); this.props.updateSize(resizedPctWidth, layout); } } }, { key: "$pos", get: function get() { if (typeof this.props.getPos !== 'function') { return null; } var pos = this.props.getPos(); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any if (Number.isNaN(pos) || typeof pos !== 'number') { return null; } // need to pass view because we may not get updated props in time return this.props.view.state.doc.resolve(pos); } /** * The maxmimum number of grid columns this node can resize to. */ }, { key: "gridWidth", get: function get() { var gridSize = this.props.gridSize; return !(this.wrappedLayout || this.insideInlineLike) ? gridSize / 2 : gridSize; } }, { key: "insideInlineLike", get: function get() { var $pos = this.$pos; if (!$pos) { return false; } var listItem = this.props.view.state.schema.nodes.listItem; return !!(0, _utils2.findParentNodeOfTypeClosestToPos)($pos, [listItem]); } }, { key: "insideLayout", get: function get() { var $pos = this.$pos; if (!$pos) { return false; } var layoutColumn = this.props.view.state.schema.nodes.layoutColumn; return !!(0, _utils2.findParentNodeOfTypeClosestToPos)($pos, [layoutColumn]); } }, { key: "render", value: function render() { var _this2 = this; var _this$props5 = this.props, origWidth = _this$props5.width, origHeight = _this$props5.height, layout = _this$props5.layout, pctWidth = _this$props5.pctWidth, containerWidth = _this$props5.containerWidth, fullWidthMode = _this$props5.fullWidthMode, selected = _this$props5.selected, children = _this$props5.children; var initialWidth = this.calcPxWidth(); // width with padding var ratio; if (origWidth) { ratio = (origHeight / origWidth * 100).toFixed(3); } var enable = {}; _ui.handleSides.forEach(function (side) { var oppositeSide = side === 'left' ? 'right' : 'left'; if ((0, _expValEquals.expValEquals)('platform_editor_media_vc_fixes', 'isEnabled', true)) { if (_this2.props.disableHandles) { enable[side] = false; return; } } enable[side] = ['full-width', 'wide', 'center'].concat("wrap-".concat(oppositeSide)).concat("align-".concat(_ui.imageAlignmentMap[oppositeSide])).indexOf(layout) > -1; if (side === 'left' && _this2.insideInlineLike) { enable[side] = false; } }); var snapPointsProps = { $pos: this.$pos, akEditorWideLayoutWidth: _editorSharedStyles.akEditorWideLayoutWidth, allowBreakoutSnapPoints: this.props.allowBreakoutSnapPoints, containerWidth: this.props.containerWidth, gridSize: this.props.gridSize, gridWidth: this.gridWidth, insideInlineLike: this.insideInlineLike, insideLayout: this.insideLayout, isVideoFile: this.state.isVideoFile, lineLength: this.props.lineLength, offsetLeft: this.state.offsetLeft, wrappedLayout: this.wrappedLayout }; var nestedInTableHandleStyles = function nestedInTableHandleStyles(isNestedInTable) { if (!isNestedInTable) { return; } return { left: { left: "calc(".concat("var(--ds-space-025, 2px)", " * -0.5)"), paddingLeft: '0px' }, right: { right: "calc(".concat("var(--ds-space-025, 2px)", " * -0.5)"), paddingRight: '0px' } }; }; return (0, _react2.jsx)("div", { ref: this.saveWrapper // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 , css: (0, _styled.wrapperStyle)({ layout: layout, isResized: !!pctWidth, containerWidth: containerWidth || origWidth, fullWidthMode: fullWidthMode, width: origWidth }) }, (0, _react2.jsx)(_ui.Resizer // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , (0, _extends2.default)({}, this.props, { displayGrid: this.displayGrid, ratio: ratio, width: initialWidth, selected: selected, enable: enable, calcNewSize: this.calcNewSize, snapPoints: (0, _utils.calculateSnapPoints)(snapPointsProps), scaleFactor: !this.wrappedLayout && !this.insideInlineLike ? 2 : 1, highlights: this.highlights, nodeType: "media", dispatchAnalyticsEvent: this.props.dispatchAnalyticsEvent // when cursor is located below a media with caption, // press “Up“ key will result cursor focus on an invalid position, (on the resize handler) // This workaround adds an empty div inside the resize handler to prevent the issue. // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleComponentFunc: function handleComponentFunc() { return (0, _react2.jsx)("div", { contentEditable: false }); }, handleStyles: nestedInTableHandleStyles(this.isNestedInTable()) }), children)); } }]); }(_react.default.Component);