UNPKG

@textbus/platform-browser

Version:

Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.

1,242 lines (1,235 loc) 169 kB
import { Slot, Textbus, Adapter, Controller, Selection, RootComponentRef, Scheduler, ContentType, Event, invokeListener, Keyboard, Commander, NativeSelectionBridge, FocusManager, makeError, Registry, Component } from '@textbus/core'; import { Subject, filter, fromEvent, delay, Subscription, distinctUntilChanged, merge, map, Observable } from '@tanbo/stream'; import { InjectionToken, Injectable, Inject, Optional } from '@viewfly/core'; /** * 选区焦点可视位置 */ function _array_like_to_array$4(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; return arr2; } function _array_without_holes$3(arr) { if (Array.isArray(arr)) return _array_like_to_array$4(arr); } function _instanceof$4(left, right) { "@swc/helpers - instanceof"; if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _iterable_to_array$3(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _non_iterable_spread$3() { throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _to_consumable_array$3(arr) { return _array_without_holes$3(arr) || _iterable_to_array$3(arr) || _unsupported_iterable_to_array$4(arr) || _non_iterable_spread$3(); } function _unsupported_iterable_to_array$4(o, minLen) { if (!o) return; if (typeof o === "string") return _array_like_to_array$4(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$4(o, minLen); } var OVERFLOW_CLIP_VALUES = new Set([ 'auto', 'hidden', 'scroll', 'clip' ]); function rectRight(r) { return r.left + r.width; } function rectBottom(r) { return r.top + r.height; } function isOverflowClipAxis(value) { return OVERFLOW_CLIP_VALUES.has(value); } function readOverflowClipAxes(style) { var overflow = style.overflow; var overflowX = style.overflowX; var overflowY = style.overflowY; if (!isOverflowClipAxis(overflow) && !isOverflowClipAxis(overflowX) && !isOverflowClipAxis(overflowY)) { return null; } return { clipX: isOverflowClipAxis(overflowX) || isOverflowClipAxis(overflow), clipY: isOverflowClipAxis(overflowY) || isOverflowClipAxis(overflow) }; } /** * 一次遍历祖先链:缓存 overflow 轴信息,并收集滚动监听目标。 */ function getOverflowClipContext(anchor, extraRoot) { var _ref, _ref1; var _clipAncestors_; var clipAncestors = []; var scrollContainers = new Set(); var node = anchor.nodeType === Node.ELEMENT_NODE ? anchor : anchor.parentNode; while(node){ var _node_ownerDocument; if (_instanceof$4(node, Element)) { var flags = readOverflowClipAxes(getComputedStyle(node)); if (flags) { clipAncestors.push({ element: node, clipX: flags.clipX, clipY: flags.clipY }); scrollContainers.add(node); } } if (node === ((_node_ownerDocument = node.ownerDocument) === null || _node_ownerDocument === void 0 ? void 0 : _node_ownerDocument.documentElement)) { break; } node = node.parentNode; } var doc = anchor.ownerDocument; var documentElement = (_ref = doc === null || doc === void 0 ? void 0 : doc.documentElement) !== null && _ref !== void 0 ? _ref : document.documentElement; scrollContainers.add(documentElement); if (extraRoot) { scrollContainers.add(extraRoot); } return { clipAncestors: clipAncestors, scrollContainers: _to_consumable_array$3(scrollContainers), firstScrollContainer: (_ref1 = (_clipAncestors_ = clipAncestors[0]) === null || _clipAncestors_ === void 0 ? void 0 : _clipAncestors_.element) !== null && _ref1 !== void 0 ? _ref1 : documentElement }; } function intersectRect(a, b) { var left = Math.max(a.left, b.left); var top = Math.max(a.top, b.top); var right = Math.min(rectRight(a), rectRight(b)); var bottom = Math.min(rectBottom(a), rectBottom(b)); if (left >= right || top >= bottom) { return null; } return { left: left, top: top, width: right - left, height: bottom - top }; } function rectContainsPoint(rect, x, y) { return x >= rect.left && x <= rectRight(rect) && y >= rect.top && y <= rectBottom(rect); } function intersectRectWithClipAncestor(ancestor, visible) { var el = ancestor.element; var border = el.getBoundingClientRect(); var left = visible.left; var top = visible.top; var right = rectRight(visible); var bottom = rectBottom(visible); if (ancestor.clipX) { var clipLeft = border.left + el.clientLeft; var clipRight = clipLeft + el.clientWidth; left = Math.max(left, clipLeft); right = Math.min(right, clipRight); } if (ancestor.clipY) { var clipTop = border.top + el.clientTop; var clipBottom = clipTop + el.clientHeight; top = Math.max(top, clipTop); bottom = Math.min(bottom, clipBottom); } if (left >= right || top >= bottom) { return null; } return { left: left, top: top, width: right - left, height: bottom - top }; } function getVisibleRectInOverflowClipsFromAncestors(rect, clipAncestors) { var visible = rect; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; try { for(var _iterator = clipAncestors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){ var ancestor = _step.value; var next = intersectRectWithClipAncestor(ancestor, visible); if (!next) { return null; } visible = next; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally{ try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally{ if (_didIteratorError) { throw _iteratorError; } } } return visible; } /** 锚点是否被 CSS 隐藏(opacity / visibility 等);不做点命中,避免 mask 层挡住误判 */ function isCaretAnchorCssVisible(anchor) { var anchorEl = anchor.nodeType === Node.ELEMENT_NODE ? anchor : anchor.parentElement; if (!(anchorEl === null || anchorEl === void 0 ? void 0 : anchorEl.isConnected)) { return false; } if (typeof anchorEl.checkVisibility === 'function') { return anchorEl.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }); } return true; } var CLIP_INSET_EPSILON = 0.5; function clipPathInsetFromVisibleRegion(elRect, visible) { var top = Math.max(0, visible.top - elRect.top); var left = Math.max(0, visible.left - elRect.left); var bottom = Math.max(0, rectBottom(elRect) - rectBottom(visible)); var right = Math.max(0, rectRight(elRect) - rectRight(visible)); if (top < CLIP_INSET_EPSILON && left < CLIP_INSET_EPSILON && bottom < CLIP_INSET_EPSILON && right < CLIP_INSET_EPSILON) { return 'none'; } return "inset(".concat(top, "px ").concat(right, "px ").concat(bottom, "px ").concat(left, "px)"); } /** 根据行高与内容矩形计算光标盒高度与顶部(视口坐标) */ function measureCaretBoxLayout(contentRect, style) { var fontSize = style.fontSize, lineHeight = style.lineHeight; var height; if (isNaN(+lineHeight)) { var f = parseFloat(lineHeight); height = isNaN(f) ? parseFloat(fontSize) : f; } else { height = parseFloat(fontSize) * parseFloat(lineHeight); } var boxHeight = Math.max(Math.floor(Math.max(height, contentRect.height)), 12); var rectTop = contentRect.top; if (contentRect.height < height) { rectTop -= (height - contentRect.height) / 2; } return { boxHeight: boxHeight, rectTop: Math.floor(rectTop) }; } /** 测量行内旋转角度(writing-mode 继承) */ function measureInlineCaretRotate(node, initialRotate, writingMode) { var rotate = initialRotate; if (rotate !== 0) { var hackEle = document.createElement('span'); hackEle.style.cssText = 'display: inline-block; width: 10px; height: 10px; position: relative; contain: layout style size; writing-mode: inherit'; var pointEle = document.createElement('span'); pointEle.style.cssText = 'position: absolute; left: 0; top: 0; width:0;height:0'; hackEle.append(pointEle); node.append(hackEle); var p1 = pointEle.getBoundingClientRect(); pointEle.style.right = '0'; pointEle.style.left = ''; var p2 = pointEle.getBoundingClientRect(); rotate = Math.atan2(p1.y - p2.y, p1.x - p2.x) * 180 / Math.PI; hackEle.remove(); } if (writingMode === 'vertical-lr' || writingMode === 'vertical-rl') { rotate += 90; } return rotate; } /** * 在 element 样式已写入后调用:计算裁剪、是否移出视口及对外事件数据。 */ function computeCaretPresentation(options) { var anchor = options.anchor, maskRect = options.maskRect, clipAncestors = options.clipAncestors, maskLeft = options.maskLeft, maskTop = options.maskTop, boxHeight = options.boxHeight, rectTop = options.rectTop, contentRect = options.contentRect, fontSize = options.fontSize, color = options.color, measureElementRect = options.measureElementRect; var caretCenterX = contentRect.left + contentRect.width / 2; var caretCenterY = rectTop + boxHeight / 2; var layoutElRect = { left: maskRect.left + maskLeft, top: maskRect.top + maskTop, width: 2, height: boxHeight }; var visibleRect = getVisibleRectInOverflowClipsFromAncestors(layoutElRect, clipAncestors); visibleRect = visibleRect ? intersectRect(visibleRect, maskRect) : null; var inClipBounds = !!visibleRect && rectContainsPoint(visibleRect, caretCenterX, caretCenterY); var outOfView = !inClipBounds || !isCaretAnchorCssVisible(anchor); var clipPath = 'none'; if (!outOfView && visibleRect) { clipPath = clipPathInsetFromVisibleRegion(measureElementRect(), visibleRect); } return { outOfView: outOfView, clipPath: clipPath, layoutElRect: layoutElRect, position: { left: maskLeft, top: rectTop, height: boxHeight }, caretColor: color === 'rgba(0, 0, 0, 0)' ? '#000' : color, style: { height: boxHeight + 'px', lineHeight: boxHeight + 'px', fontSize: fontSize } }; } function createElement(tagName) { var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}; var el = document.createElement(tagName); if (options.classes) { var _el_classList; (_el_classList = el.classList).add.apply(_el_classList, _to_consumable_array$3(options.classes)); } if (options.attrs) { Object.keys(options.attrs).forEach(function(key) { el.setAttribute(key, options.attrs[key]); }); } if (options.props) { Object.keys(options.props).forEach(function(key) { el[key] = options.props[key]; }); } if (options.styles) { Object.assign(el.style, options.styles); } if (options.children) { options.children.filter(function(i) { return i; }).forEach(function(item) { el.appendChild(item); }); } if (options.on) { Object.keys(options.on).forEach(function(key) { el.addEventListener(key, options.on[key]); }); } return el; } function getLayoutRectByRange(range) { var startContainer = range.startContainer, startOffset = range.startOffset; if (startContainer.nodeType === Node.TEXT_NODE) { if (startOffset > 0) { return range.getBoundingClientRect(); } var parentNode = startContainer.parentNode; startOffset = Array.from(parentNode.childNodes).indexOf(startContainer); startContainer = parentNode; } var beforeNode = startContainer.childNodes[startOffset - 1]; if (beforeNode) { if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') { var rect = beforeNode.getBoundingClientRect(); return { left: rect.right, top: rect.top, width: range.collapsed ? 1 : rect.width, height: rect.height }; } else if (beforeNode.nodeType === Node.TEXT_NODE) { var range2 = document.createRange(); range2.setStart(beforeNode, beforeNode.textContent.length); range2.setEnd(beforeNode, beforeNode.textContent.length); var rect1 = range2.getBoundingClientRect(); return { left: rect1.right, top: rect1.top, width: range.collapsed ? 1 : rect1.width, height: rect1.height }; } } var offsetNode = startContainer.childNodes[startOffset]; var isInsertBefore = false; if (!offsetNode) { var lastChild = startContainer.lastChild; if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) { var rect2 = lastChild.getBoundingClientRect(); return { left: rect2.right, top: rect2.top, width: range.collapsed ? 1 : rect2.width, height: rect2.height }; } } if (offsetNode) { if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') { var rect3 = offsetNode.getBoundingClientRect(); return { left: rect3.left, top: rect3.top, width: range.collapsed ? 1 : rect3.width, height: rect3.height }; } isInsertBefore = true; } var span = startContainer.ownerDocument.createElement('span'); span.innerText = '\u200b'; span.style.display = 'inline-block'; if (isInsertBefore) { startContainer.insertBefore(span, offsetNode); } else { startContainer.appendChild(span); } var rect4 = span.getBoundingClientRect(); startContainer.removeChild(span); return { left: rect4.left, top: rect4.top, width: range.collapsed ? 1 : rect4.width, height: rect4.height }; } var isWindows = function isWindows() { return /win(dows|32|64)/i.test(navigator.userAgent); }; var isMac = function isMac() { return /mac os/i.test(navigator.userAgent); }; var isSafari = function isSafari() { return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); }; var isFirefox = function isFirefox() { return /Firefox/.test(navigator.userAgent); }; var isMobileBrowser = function isMobileBrowser() { return /Android|iPhone|iPad/.test(navigator.userAgent); }; /** * 编辑器可选项依赖注入 token */ var EDITOR_OPTIONS = new InjectionToken('EDITOR_OPTIONS'); /** * 编辑器容器依赖注入 token */ var VIEW_CONTAINER = new InjectionToken('VIEW_CONTAINER'); /** * 编辑器容器依赖注入 token */ var VIEW_DOCUMENT = new InjectionToken('VIEW_DOCUMENT'); /** * 编辑器容器遮罩层 token */ var VIEW_MASK = new InjectionToken('VIEW_MASK'); function _array_like_to_array$3(arr, len) { if (len == null || len > arr.length) len = arr.length; for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; return arr2; } function _array_without_holes$2(arr) { if (Array.isArray(arr)) return _array_like_to_array$3(arr); } function _class_call_check$7(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties$5(target, props) { for(var i = 0; i < props.length; i++){ var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _create_class$5(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$5(Constructor.prototype, protoProps); if (staticProps) _defineProperties$5(Constructor, staticProps); return Constructor; } function _define_property$6(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _instanceof$3(left, right) { "@swc/helpers - instanceof"; if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _iterable_to_array$2(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _non_iterable_spread$2() { throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _to_consumable_array$2(arr) { return _array_without_holes$2(arr) || _iterable_to_array$2(arr) || _unsupported_iterable_to_array$3(arr) || _non_iterable_spread$2(); } function _unsupported_iterable_to_array$3(o, minLen) { if (!o) return; if (typeof o === "string") return _array_like_to_array$3(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$3(o, minLen); } function _ts_decorate$4(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function _ts_metadata$4(k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); } function _ts_param$2(paramIndex, decorator) { return function(target, key) { decorator(target, key, paramIndex); }; } var Parser = /*#__PURE__*/ function() { function Parser(options, textbus) { _class_call_check$7(this, Parser); _define_property$6(this, "textbus", void 0); _define_property$6(this, "componentLoaders", void 0); _define_property$6(this, "formatLoaders", void 0); _define_property$6(this, "attributeLoaders", void 0); this.textbus = textbus; var componentLoaders = _to_consumable_array$2(options.componentLoaders || []); var formatLoaders = _to_consumable_array$2(options.formatLoaders || []); var attributeLoaders = _to_consumable_array$2(options.attributeLoaders || []); // options.imports?.forEach(i => { // componentLoaders.push(...(i.componentLoaders || [])) // formatLoaders.push(...(i.formatLoaders || [])) // }) this.componentLoaders = componentLoaders; this.formatLoaders = formatLoaders; this.attributeLoaders = attributeLoaders; } _create_class$5(Parser, [ { /** * 使用指定的组件加载器解析一段 HTML 字符串或 DOM 元素 * @param html * @param rootComponentLoader */ key: "parseDoc", value: function parseDoc(html, rootComponentLoader) { var _this = this; var element = typeof html === 'string' ? Parser.parseHTML(html) : html; return rootComponentLoader.read(element, this.textbus, function(childSlot, slotRootElement) { var slotContentHostElement = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : slotRootElement; return _this.readSlot(childSlot, slotRootElement, slotContentHostElement); }); } }, { /** * 将一段 HTML 或 DOM 元素解析到指定插槽 * @param html * @param rootSlot */ key: "parse", value: function parse(html, rootSlot) { var element = typeof html === 'string' ? Parser.parseHTML(html) : html; return this.readFormats(element, rootSlot); } }, { key: "readComponent", value: function readComponent(el, slot) { if (el.nodeType === Node.ELEMENT_NODE) { if (el.tagName === 'BR') { slot.insert('\n'); return; } var schema = _to_consumable_array$2(slot.schema); var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; try { for(var _iterator = this.componentLoaders[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){ var t = _step.value; if (t.match(el, schema)) { var _this = this; var result = t.read(el, this.textbus, function(childSlot, slotRootElement) { var slotContentHostElement = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : slotRootElement; return _this.readSlot(childSlot, slotRootElement, slotContentHostElement); }); if (!result) { return; } if (_instanceof$3(result, Slot)) { result.toDelta().forEach(function(i) { return slot.insert(i.insert, i.formats); }); return; } slot.insert(result); return; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally{ try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally{ if (_didIteratorError) { throw _iteratorError; } } } this.readFormats(el, slot); } else if (el.nodeType === Node.TEXT_NODE) { this.readText(slot, el); } } }, { key: "readText", value: function readText(slot, el) { var textContent = el.textContent; if (/^\s*[\r\n\u200b]+\s*$/.test(textContent)) { return; } slot.insert(textContent); } }, { key: "readFormats", value: function readFormats(el, slot) { var formats = this.formatLoaders.filter(function(f) { return f.match(el); }).map(function(f) { return f.read(el); }); var startIndex = slot.index; var startNode = el.firstChild; while(startNode){ this.readComponent(startNode, slot); startNode = startNode.nextSibling; } var endIndex = slot.index; this.applyFormats(slot, formats.map(function(i) { return { formatter: i.formatter, value: i.value, startIndex: startIndex, endIndex: endIndex }; })); slot.retain(endIndex); return slot; } }, { key: "readSlot", value: function readSlot(childSlot, slotRootElement, slotContentElement) { if (slotRootElement.nodeType === Node.ELEMENT_NODE) { this.attributeLoaders.filter(function(a) { return a.match(slotRootElement); }).forEach(function(a) { var r = a.read(slotRootElement); childSlot.setAttribute(r.attribute, r.value); }); } if (slotContentElement.nodeType === Node.ELEMENT_NODE) { this.readFormats(slotContentElement, childSlot); } else { this.readText(childSlot, slotContentElement); } return childSlot; } }, { key: "applyFormats", value: function applyFormats(slot, formatItems) { slot.background(function() { formatItems.forEach(function(i) { slot.retain(i.startIndex); slot.retain(i.endIndex - i.startIndex, i.formatter, i.value); }); }); } } ], [ { key: "parseHTML", value: function parseHTML(html) { return new DOMParser().parseFromString(html, 'text/html').body; } } ]); return Parser; }(); Parser = _ts_decorate$4([ Injectable(), _ts_param$2(0, Inject(EDITOR_OPTIONS)), _ts_metadata$4("design:type", Function), _ts_metadata$4("design:paramtypes", [ typeof ViewOptions === "undefined" ? Object : ViewOptions, typeof Textbus === "undefined" ? Object : Textbus ]) ], Parser); function _class_call_check$6(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function caretPositionEqual(a, b) { if (a === b) { return true; } if (a === null || b === null) { return false; } return a.left === b.left && a.top === b.top && a.height === b.height; } var Input = function Input() { _class_call_check$6(this, Input); }; function _assert_this_initialized$2(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _call_super$2(_this, derived, args) { derived = _get_prototype_of$2(derived); return _possible_constructor_return$2(_this, _is_native_reflect_construct$2() ? Reflect.construct(derived, args || [], _get_prototype_of$2(_this).constructor) : derived.apply(_this, args)); } function _class_call_check$5(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _define_property$5(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _get_prototype_of$2(o) { _get_prototype_of$2 = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _get_prototype_of$2(o); } function _inherits$2(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _set_prototype_of$2(subClass, superClass); } function _possible_constructor_return$2(self, call) { if (call && (_type_of$2(call) === "object" || typeof call === "function")) { return call; } return _assert_this_initialized$2(self); } function _set_prototype_of$2(o, p) { _set_prototype_of$2 = Object.setPrototypeOf || function setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _set_prototype_of$2(o, p); } function _type_of$2(obj) { "@swc/helpers - typeof"; return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; } function _is_native_reflect_construct$2() { try { var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {})); } catch (_) {} return (_is_native_reflect_construct$2 = function() { return !!result; })(); } var DomAdapter = /*#__PURE__*/ function(Adapter) { _inherits$2(DomAdapter, Adapter); function DomAdapter() { _class_call_check$5(this, DomAdapter); var _this; _this = _call_super$2(this, DomAdapter, arguments), _define_property$5(_this, "onViewUpdated", new Subject()), _define_property$5(_this, "host", createElement('div', { styles: { cursor: 'text', overflowWrap: 'break-word', boxSizing: 'border-box', flex: 1, outline: 'none' }, attrs: { 'data-textbus-view': VIEW_DOCUMENT }, props: { id: 'textbus-' + Number((Math.random() + '').substring(2)).toString(16) } })); return _this; } return DomAdapter; }(Adapter); function _class_call_check$4(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties$4(target, props) { for(var i = 0; i < props.length; i++){ var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _create_class$4(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$4(Constructor.prototype, protoProps); return Constructor; } function _define_property$4(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _instanceof$2(left, right) { "@swc/helpers - instanceof"; if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } function _ts_decorate$3(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function _ts_metadata$3(k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); } function _ts_param$1(paramIndex, decorator) { return function(target, key) { decorator(target, key, paramIndex); }; } var SelectionBridge = /*#__PURE__*/ function() { function SelectionBridge(config, textbus, controller, selection, rootComponentRef, input, scheduler, domAdapter) { var _this = this; _class_call_check$4(this, SelectionBridge); _define_property$4(this, "config", void 0); _define_property$4(this, "selection", void 0); _define_property$4(this, "rootComponentRef", void 0); _define_property$4(this, "input", void 0); _define_property$4(this, "scheduler", void 0); _define_property$4(this, "domAdapter", void 0); _define_property$4(this, "onSelectionChange", void 0); _define_property$4(this, "nativeSelection", void 0); _define_property$4(this, "syncSelectionFromNativeSelectionChange", void 0); _define_property$4(this, "selectionChangeEvent", void 0); _define_property$4(this, "subs", void 0); _define_property$4(this, "sub", void 0); _define_property$4(this, "connector", void 0); _define_property$4(this, "ignoreSelectionChange", void 0); _define_property$4(this, "changeFromUser", void 0); _define_property$4(this, "docContainer", void 0); _define_property$4(this, "cacheCaretPositionTimer", void 0); _define_property$4(this, "oldCaretPosition", void 0); this.config = config; this.selection = selection; this.rootComponentRef = rootComponentRef; this.input = input; this.scheduler = scheduler; this.domAdapter = domAdapter; this.nativeSelection = document.getSelection(); this.syncSelectionFromNativeSelectionChange = true; this.selectionChangeEvent = new Subject(); this.subs = []; this.connector = null; this.ignoreSelectionChange = false; this.changeFromUser = false; this.docContainer = textbus.get(VIEW_DOCUMENT); this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(function() { return !controller.readonly; })); this.sub = this.onSelectionChange.subscribe(function(r) { if (r) { input.focus(r, _this.changeFromUser); } else { input.blur(); } }); this.sub.add(fromEvent(document, 'focusin').subscribe(function(ev) { var target = ev.target; if (/^(input|textarea|select)$/i.test(target.nodeName)) { if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test(target.type)) { return; } _this.ignoreSelectionChange = true; return; } if (!config.useContentEditable) { while(target){ if (target.contentEditable === 'true') { _this.ignoreSelectionChange = true; return; } target = target.parentNode; } } })); this.sub.add(fromEvent(document, 'focusout').subscribe(function() { _this.ignoreSelectionChange = false; })); } _create_class$4(SelectionBridge, [ { key: "connect", value: function connect(connector) { this.disConnect(); this.connector = connector; this.syncSelection(connector); this.listen(connector); } }, { key: "disConnect", value: function disConnect() { this.connector = null; this.unListen(); } }, { key: "getRect", value: function getRect(location) { var _this_getPositionByRange = this.getPositionByRange({ focusOffset: location.offset, anchorOffset: location.offset, focusSlot: location.slot, anchorSlot: location.slot }), focus = _this_getPositionByRange.focus, anchor = _this_getPositionByRange.anchor; if (!focus || !anchor) { return null; } var nativeRange = document.createRange(); nativeRange.setStart(focus.node, focus.offset); nativeRange.collapse(); return getLayoutRectByRange(nativeRange); } }, { key: "restore", value: function restore(abstractSelection, fromLocal) { var _this = this; this.changeFromUser = fromLocal; if (this.ignoreSelectionChange || !this.connector) { return; } this.unListen(); if (!abstractSelection) { this.nativeSelection.removeAllRanges(); this.selectionChangeEvent.next(null); this.listen(this.connector); return; } var _this_getPositionByRange = this.getPositionByRange(abstractSelection), focus = _this_getPositionByRange.focus, anchor = _this_getPositionByRange.anchor; if (!focus || !anchor) { this.nativeSelection.removeAllRanges(); this.selectionChangeEvent.next(null); this.listen(this.connector); return; } function tryOffset(position) { if (!position.node) { return; } if (position.node.nodeType === Node.TEXT_NODE) { var len = position.node.textContent.length; if (position.offset > len) { position.offset = len; } } else if (position.node.nodeType === Node.ELEMENT_NODE) { var len1 = position.node.childNodes.length; if (position.offset > len1) { position.offset = len1; } } } try { tryOffset(focus); tryOffset(anchor); this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset); } catch (e) { setTimeout(function() { throw e; }); } if (this.nativeSelection.rangeCount) { var nativeRange = this.nativeSelection.getRangeAt(0); this.selectionChangeEvent.next(nativeRange); } else { this.selectionChangeEvent.next(null); } // hack start 浏览器会触发上面选区更改事件 var bind = function bind() { if (_this.connector) { _this.listen(_this.connector); } }; if (fromLocal) { Promise.resolve().then(bind); return; } if (typeof requestIdleCallback === 'function') { requestIdleCallback(bind); } else { setTimeout(bind, 30); } // hack end } }, { key: "destroy", value: function destroy() { this.subs.forEach(function(i) { return i.unsubscribe(); }); this.sub.unsubscribe(); } }, { key: "getPositionByRange", value: function getPositionByRange(abstractSelection) { var focus; var anchor; try { focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot, abstractSelection.focusOffset); anchor = focus; if (abstractSelection.anchorSlot !== abstractSelection.focusSlot || abstractSelection.anchorOffset !== abstractSelection.focusOffset) { anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot, abstractSelection.anchorOffset); } return { focus: focus, anchor: anchor }; } catch (e) { return { focus: null, anchor: null }; } } }, { key: "getPreviousLinePositionByCurrent", value: function getPreviousLinePositionByCurrent(position) { return this.getLinePosition(position, false); } }, { key: "getNextLinePositionByCurrent", value: function getNextLinePositionByCurrent(position) { return this.getLinePosition(position, true); } }, { key: "getLinePosition", value: function getLinePosition(currentPosition, toNext) { var _this = this; clearTimeout(this.cacheCaretPositionTimer); if (!this.oldCaretPosition) { this.oldCaretPosition = this.getRect(currentPosition); } var p = this.getVerticalMovePosition(currentPosition, this.oldCaretPosition.left, toNext); this.cacheCaretPositionTimer = setTimeout(function() { _this.oldCaretPosition = null; }, 3000); return p; } }, { key: "getVerticalMovePosition", value: /** * 通过遍历模型位置 + 视觉 rect 判断换行,计算光标到下一行或上一行的位置。 * 不使用 Selection.modify(),避免复杂布局中的死循环。 */ function getVerticalMovePosition(currentPosition, startLeft, toNext) { var _this = this; var startRect = this.getRect(currentPosition); if (!startRect) return currentPosition; var startTop = startRect.top; var startBottom = startTop + startRect.height; var step = toNext ? function(pos) { return _this.selection.getNextPositionByPosition(pos.slot, pos.offset); } : function(pos) { return _this.selection.getPreviousPositionByPosition(pos.slot, pos.offset); }; var cur = currentPosition; while(true){ var next = step(cur); if (next.slot === cur.slot && next.offset === cur.offset) break; var rect = this.getRect(next); if (!rect) break; cur = next; if (this.isDifferentLine(startTop, startBottom, rect, toNext)) { return this.refineXOnLine(cur, startLeft, rect); } } return this.getDocumentBoundary(toNext); } }, { key: "isDifferentLine", value: /** 目标位置是否已离开起始行 */ function isDifferentLine(startTop, startBottom, targetRect, toNext) { if (toNext) { return targetRect.top >= startBottom; } return targetRect.top + targetRect.height <= startTop; } }, { key: "refineXOnLine", value: /** * 沿目标行微调位置。 * 起点在 targetX 右侧 → 向左找到离 targetX 最近的右侧位置; * 起点在 targetX 左侧 → 向右找到第一个右侧位置。 */ function refineXOnLine(position, targetX, lineRect) { var startRect = this.getRect(position); var startLeft = startRect.left; var lineTop = lineRect.top; var lineBottom = lineTop + Math.max(lineRect.height, 12); if (startLeft === targetX) return position; var cur = position; if (startLeft > targetX) { var rightSide = position; while(true){ var prev = this.selection.getPreviousPositionByPosition(cur.slot, cur.offset); if (prev.slot === cur.slot && prev.offset === cur.offset) break; var rect = this.getRect(prev); if (!rect) break; if (rect.top >= lineBottom || rect.top + rect.height <= lineTop) break; cur = prev; if (rect.left === targetX) return prev; if (rect.left < targetX) return rightSide; rightSide = prev; } return rightSide; } while(true){ var next = this.selection.getNextPositionByPosition(cur.slot, cur.offset); if (next.slot === cur.slot && next.offset === cur.offset) break; var rect1 = this.getRect(next); if (!rect1) break; if (rect1.top >= lineBottom || rect1.top + rect1.height <= lineTop) break; cur = next; if (rect1.left === targetX) return cur; if (rect1.left > targetX) return cur; } return cur; } }, { key: "getDocumentBoundary", value: /** 跳转到文档开头或结尾 */ function getDocumentBoundary(toNext) { var slots = this.rootComponentRef.component.slots; if (toNext) { var lastSlot = slots[slots.length - 1]; return { slot: lastSlot, offset: lastSlot.length }; } var firstSlot = slots[0]; return { slot: firstSlot, offset: 0 }; } }, { key: "caretPositionFromPoint", value: function caretPositionFromPoint(x, rect) { var _document_caretPositionFromPoint, _document; return (_document_caretPositionFromPoint = (_document = document).caretPositionFromPoint) === null || _document_caretPositionFromPoint === void 0 ? void 0 : _document_caretPositionFromPoint.call(_document, x, rect.top + rect.height / 2); } }, { key: "unListen", value: function unListen() { this.subs.forEach(function(i) { return i.unsubscribe(); }); this.subs = []; } }, { key: "listen", value: function listen(connector) { var _this = this; if (!this.config.useContentEditable) { var selection = this.nativeSelection; this.subs.push(fromEvent(this.docContainer, 'mousedown').subscribe(function(ev) { if (_this.ignoreSelectionChange || ev.button === 2) { return; } if (!ev.shiftKey) { selection.removeAllRanges(); } })); } var isUpdating = false; this.subs.push(this.scheduler.onDocChange.subscribe(function() { isUpdating = true; }), this.scheduler.onDocChanged.pipe(delay()).subscribe(function() { isUpdating = false; }), fromEvent(document, 'selectionchange').subscribe(function() { if (isUpdating) { return; } if (_this.syncSelectionFromNativeSelectionChange) { _this.syncSelection(connector); } })); } }, { key: "syncSelection", value: function syncSelection(connector) { var _nativeRange_commonAncestorContainer; var selection = this.nativeSelection; this.changeFromUser = true; if (this.ignoreSelectionChange || this.input.composition || selection.rangeCount === 0 || !this.docContainer.contains(selection.anchorNode) || this.rootComponentRef.component.slots.length === 0) { return; } var rawRange = selection.getRangeAt(0); var nativeRange = rawRange.cloneRange(); var isFocusEnd = selection.focusN