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