UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

282 lines (281 loc) • 12.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.mediaDropSelection = exports.findMediaDropReplacement = exports.findMediaDropPosition = exports.MediaDropTargets = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _selection = require("@atlaskit/editor-common/selection/gap-cursor/selection"); var _model = require("@atlaskit/editor-prosemirror/model"); var _state = require("@atlaskit/editor-prosemirror/state"); var _transform = require("@atlaskit/editor-prosemirror/transform"); var _mediaInline = require("./utils/media-inline"); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } 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) { (0, _defineProperty2.default)(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; } /** Keeps a media insertion point collapsed so a drop never replaces the current selection. */ var mediaDropSelection = exports.mediaDropSelection = function mediaDropSelection(doc, pos) { var $pos = doc.resolve(pos); return $pos.parent.inlineContent ? _state.TextSelection.create(doc, pos) : new _selection.GapCursorSelection($pos); }; var findMediaDropPosition = exports.findMediaDropPosition = function findMediaDropPosition(view, coords, fileTypes, mediaOptions) { if (!view.editable || view.dragging || fileTypes.length === 0) { return; } var rect = view.dom.getBoundingClientRect(); var hit = view.posAtCoords({ left: Math.max(rect.left + 1, Math.min(coords.left, rect.right - 1)), top: Math.max(rect.top + 1, Math.min(coords.top, rect.bottom - 1)) }); if (!hit) { return; } var _view$state = view.state, doc = _view$state.doc, schema = _view$state.schema; var targetState = _state.EditorState.create({ doc: doc, schema: schema, selection: mediaDropSelection(doc, hit.pos) }); var supportedOptions = schema.nodes.mediaInline ? mediaOptions : _objectSpread(_objectSpread({}, mediaOptions), {}, { featureFlags: _objectSpread(_objectSpread({}, mediaOptions === null || mediaOptions === void 0 ? void 0 : mediaOptions.featureFlags), {}, { mediaInline: false }) }); var insertionTypes = new Set(Array.from(new Set(fileTypes), function (fileType) { return (0, _mediaInline.getMediaNodeInsertionType)(targetState, supportedOptions, fileType); })); var slices = Array.from(insertionTypes).flatMap(function (insertionType) { var node; if (insertionType === 'inline') { node = schema.nodes.mediaInline.create(); } else { var container = insertionType === 'block' ? schema.nodes.mediaSingle : schema.nodes.mediaGroup; if (!container || !schema.nodes.media) { return []; } node = container.create(null, schema.nodes.media.create({ type: 'file' })); } return new _model.Slice(_model.Fragment.from(node), 0, 0); }); if (slices.length !== insertionTypes.size) { return; } var _iterator = _createForOfIteratorHelper(slices), _step; try { var _loop = function _loop() { var slice = _step.value; var pos = (0, _transform.dropPoint)(doc, hit.pos, slice); if (pos !== null && slices.every(function (content) { var alreadyValidated = content === slice && pos === hit.pos; return alreadyValidated || (0, _transform.dropPoint)(doc, pos, content) === pos; })) { return { v: pos }; } }, _ret; for (_iterator.s(); !(_step = _iterator.n()).done;) { _ret = _loop(); if (_ret) return _ret.v; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return; }; /** Only a single image over a media card can replace it; captions and surrounding space insert. */ var findMediaDropReplacement = exports.findMediaDropReplacement = function findMediaDropReplacement(view, event, fileTypes) { var _mediaDom$querySelect; if (!view.editable || view.dragging || fileTypes.length !== 1 || !fileTypes[0].startsWith('image/')) { return; } if (!(event.target instanceof Element)) { return; } var mediaDom = event.target.closest('[data-prosemirror-node-name="media"], [data-node-type="media"]'); if (!mediaDom || !view.dom.contains(mediaDom)) { return; } var card = (_mediaDom$querySelect = mediaDom.querySelector('.media-card-wrapper')) !== null && _mediaDom$querySelect !== void 0 ? _mediaDom$querySelect : mediaDom; var rect = card.getBoundingClientRect(); if (event.clientX < rect.left || event.clientX >= rect.right || event.clientY < rect.top || event.clientY >= rect.bottom) { return; } var $pos = view.state.doc.resolve(view.posAtDOM(mediaDom, 0)); if ($pos.parent.type !== view.state.schema.nodes.mediaSingle) { return; } var media = $pos.parent.firstChild; if (!media || media.type !== view.state.schema.nodes.media) { return; } var mimeType = media.attrs.__fileMimeType; var hasImagePreview = !!card.querySelector('img[data-fileid], img[data-testid="media-image"], img[data-testid="media-card-svg"]') && !card.querySelector('video, [data-testid="media-card-play-button-wrapper"]'); var isImage = mimeType ? mimeType.startsWith('image/') : media.attrs.type === 'external' || hasImagePreview; return isImage ? { pos: $pos.before(), media: media } : undefined; }; var mapReplacement = function mapReplacement(replacement, mapping) { if (!replacement) { return; } var mapped = mapping.mapResult(replacement.pos, 1); return mapped.deleted ? undefined : _objectSpread(_objectSpread({}, replacement), {}, { pos: mapped.pos }); }; var currentReplacement = function currentReplacement(replacement, doc) { if (!replacement) { return; } var node = doc.nodeAt(replacement.pos); var media = node === null || node === void 0 ? void 0 : node.firstChild; var original = replacement.media; if ((node === null || node === void 0 ? void 0 : node.type.name) === 'mediaSingle' && (media === null || media === void 0 ? void 0 : media.type) === original.type && media.attrs.id === original.attrs.id && media.attrs.collection === original.attrs.collection && media.attrs.type === original.attrs.type && media.attrs.url === original.attrs.url) { return replacement; } return; }; /** Retains drop locations while uploads prepare and other edits change document positions. */ var MediaDropTargets = exports.MediaDropTargets = /*#__PURE__*/function () { function MediaDropTargets() { (0, _classCallCheck2.default)(this, MediaDropTargets); (0, _defineProperty2.default)(this, "batches", new Map()); (0, _defineProperty2.default)(this, "files", new Map()); } return (0, _createClass2.default)(MediaDropTargets, [{ key: "start", value: function start(traceId, pos, replacement) { var _this = this; var batch = { pos: pos, replacement: replacement, files: new Set(), prepared: false }; this.batches.set(traceId, batch); return function () { batch.prepared = true; _this.prune(); }; } }, { key: "register", value: function register(traceId, fileIds) { var batch = this.batches.get(traceId); if (!batch) { return; } var _iterator2 = _createForOfIteratorHelper(fileIds), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var id = _step2.value; batch.files.add(id); this.files.set(id, batch); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } }, { key: "positionFor", value: function positionFor(fileId) { var _this$files$get; return (_this$files$get = this.files.get(fileId)) === null || _this$files$get === void 0 ? void 0 : _this$files$get.pos; } }, { key: "replacementFor", value: function replacementFor(fileId, doc) { var _this$files$get2; return currentReplacement((_this$files$get2 = this.files.get(fileId)) === null || _this$files$get2 === void 0 ? void 0 : _this$files$get2.replacement, doc); } }, { key: "hoverReplacementFor", value: function hoverReplacementFor(doc) { return currentReplacement(this.hoverReplacement, doc); } }, { key: "clearHover", value: function clearHover() { this.hover = undefined; this.hoverReplacement = undefined; } }, { key: "inserted", value: function inserted(fileId) { var _this$files$get3; (_this$files$get3 = this.files.get(fileId)) === null || _this$files$get3 === void 0 || _this$files$get3.files.delete(fileId); this.files.delete(fileId); this.prune(); } }, { key: "map", value: function map(mapping) { if (mapping.maps.length === 0) { return; } if (this.hover !== undefined) { this.hover = mapping.map(this.hover, 1); } this.hoverReplacement = mapReplacement(this.hoverReplacement, mapping); var _iterator3 = _createForOfIteratorHelper(this.batches.values()), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var batch = _step3.value; batch.pos = mapping.map(batch.pos, 1); batch.replacement = mapReplacement(batch.replacement, mapping); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } }, { key: "clear", value: function clear() { this.clearHover(); this.batches.clear(); this.files.clear(); } }, { key: "prune", value: function prune() { var _iterator4 = _createForOfIteratorHelper(this.batches), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _step4$value = (0, _slicedToArray2.default)(_step4.value, 2), id = _step4$value[0], batch = _step4$value[1]; if (batch.prepared && batch.files.size === 0) { this.batches.delete(id); } } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } } }]); }();