@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
JavaScript
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