eco-vue-js 0.11.14 → 0.11.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Input/WInput.vue.d.ts.map +1 -1
- package/dist/components/Input/WInput.vue.js +10 -6
- package/dist/components/Input/components/ContentEditable.vue.d.ts.map +1 -1
- package/dist/components/Input/components/ContentEditable.vue2.js +19 -48
- package/dist/components/Input/components/InputToolbar.vue.d.ts +1 -0
- package/dist/components/Input/components/InputToolbar.vue.d.ts.map +1 -1
- package/dist/components/Input/components/InputToolbar.vue2.js +17 -14
- package/dist/components/Input/models/utils.d.ts +1 -0
- package/dist/components/Input/models/utils.d.ts.map +1 -1
- package/dist/components/Input/models/utils.js +49 -7
- package/package.json +1 -1
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"WInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/Input/WInput.vue"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"WInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/Input/WInput.vue"],"names":[],"mappings":"AAoPA;AAqiBA,OAAO,KAAK,EAAC,UAAU,EAAE,aAAa,EAAC,MAAM,SAAS,CAAA;AAatD,OAAO,EAAC,KAAK,WAAW,EAAC,MAAM,gBAAgB,CAAA;yBAE9B,IAAI,SAAS,SAAS,GAAG,MAAM,EAC/C,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,eAAe,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EACjE;WAwyBO,mBAAmB,CAAC,oCAAkE,CAAC,4BAA2B;oBACzG,OAAO,KAAK,EAAE,gBAAgB;qBA5mB7B,IAAI;oBAOL,IAAI;+BAiCS,aAAa;0BAzKlB,MAAM,QAAQ,MAAM,KAAG,IAAI;wBAN/B,WAAW;;;oBAyBf,IAAI;oBAgBJ,IAAI;MA0sBgD,GAAG,IAAI;WACpE,GAAG;;uBAhEgB,GAAG;0BACA,GAAG;wBACJ,GAAG;;;YAEH,GAAG;;mCAzgBF,aAAa;YAwgBb,GAAG;;;YAEJ,GAAG;uBACJ,GAAG;wBACF,GAAG;uBACJ,GAAG;uBACH,GAAG;wBACF,GAAG;;;YAztB1B,oBAAoB,SAAS,4CAAa,SAAS,GAAG,IAAI;YAC1D,gBAAgB,SAAS,aAAa,GAAG,IAAI;YAC7C,aAAa,SAAS,aAAa,GAAG,IAAI;YAC1C,eAAe,SAAS,aAAa,GAAG,IAAI;YAC5C,iBAAiB,SAAS,aAAa,GAAG,IAAI;YAC9C,oBAAoB,SAAS,aAAa,GAAG,IAAI;YACjD,aAAa,GAAG,IAAI;YACpB,OAAO,SAAS,UAAU,GAAG,SAAS,GAAG,IAAI;YAC7C,MAAM,SAAS,UAAU,GAAG,IAAI;YAChC,OAAO,SAAS,UAAU,GAAG,IAAI;YACjC,WAAW,SAAS,UAAU,GAAG,IAAI;YACrC,cAAc,SAAS,UAAU,GAAG,IAAI;YACxC,cAAc,SAAS,KAAK,GAAG,IAAI;YACnC,OAAO,GAAG,IAAI;;EAswBhB,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,WAAW,CAAC,CAAA;CAAE;AAnzBzE,wBAmzB4E;AAC5E,KAAK,mBAAmB,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC"}
|
@@ -6,7 +6,6 @@ import { useComponentStates } from '../../utils/useComponentStates.js';
|
|
6
6
|
import { checkPermissionPaste } from '../../utils/useCopy.js';
|
7
7
|
import { debounce } from '../../utils/utils.js';
|
8
8
|
import _sfc_main$2 from './components/InputActions.vue.js';
|
9
|
-
import { getCaretOffset } from './models/utils.js';
|
10
9
|
|
11
10
|
const _hoisted_1 = { class: "relative flex min-h-full flex-1" };
|
12
11
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
@@ -81,7 +80,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
81
80
|
const getCaret = () => {
|
82
81
|
if (!inputRef.value) return { start: 0, end: 0 };
|
83
82
|
if ("getCaret" in inputRef.value) return inputRef.value.getCaret();
|
84
|
-
return
|
83
|
+
return { start: inputRef.value.selectionStart ?? 0, end: inputRef.value.selectionEnd ?? 0 };
|
85
84
|
};
|
86
85
|
const setCaret = (start, end) => {
|
87
86
|
if (!inputRef.value) return;
|
@@ -100,8 +99,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
100
99
|
}, 500);
|
101
100
|
const undo = () => {
|
102
101
|
if (props.loading || isDisabled.value || isReadonly.value || props.unclickable || props.textSecure) return;
|
103
|
-
if (historyPosition.value
|
102
|
+
if (historyPosition.value <= 0) {
|
104
103
|
fieldWrapperRef.value?.showMessage("No Undo");
|
104
|
+
historyPosition.value = history.value.length ? 0 : -1;
|
105
105
|
return;
|
106
106
|
}
|
107
107
|
fieldWrapperRef.value?.showMessage("Undo");
|
@@ -113,8 +113,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
113
113
|
};
|
114
114
|
const redo = () => {
|
115
115
|
if (props.loading || isDisabled.value || isReadonly.value || props.unclickable || props.textSecure) return;
|
116
|
-
if (historyPosition.value
|
116
|
+
if (historyPosition.value >= history.value.length - 1) {
|
117
117
|
fieldWrapperRef.value?.showMessage("No Redo");
|
118
|
+
historyPosition.value = history.value.length - 1;
|
118
119
|
return;
|
119
120
|
}
|
120
121
|
fieldWrapperRef.value?.showMessage("Redo");
|
@@ -324,6 +325,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
324
325
|
rich: _ctx.rich === true,
|
325
326
|
"is-undo": historyPosition.value !== 0,
|
326
327
|
"is-redo": historyPosition.value !== history.value.length - 1,
|
328
|
+
"text-secure": _ctx.textSecure ?? false,
|
327
329
|
onWrapSelection: wrapSelection,
|
328
330
|
onUndo: undo,
|
329
331
|
onRedo: redo
|
@@ -332,7 +334,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
332
334
|
renderSlot(_ctx.$slots, "toolbar", normalizeProps(guardReactiveProps({ wrapSelection })))
|
333
335
|
]),
|
334
336
|
_: 3
|
335
|
-
}, 8, ["list", "rich", "is-undo", "is-redo"])) : createCommentVNode("", true),
|
337
|
+
}, 8, ["list", "rich", "is-undo", "is-redo", "text-secure"])) : createCommentVNode("", true),
|
336
338
|
_ctx.icon ? (openBlock(), createElementBlock("div", {
|
337
339
|
key: 1,
|
338
340
|
class: normalizeClass(["flex h-full w-[--w-input-height,2.75rem] select-none items-center justify-center", {
|
@@ -472,9 +474,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
472
474
|
]),
|
473
475
|
key: "4"
|
474
476
|
} : void 0,
|
475
|
-
_ctx.$slots.bottom ? {
|
477
|
+
_ctx.$slots.bottom || true ? {
|
476
478
|
name: "bottom",
|
477
479
|
fn: withCtx(() => [
|
480
|
+
createElementVNode("pre", null, toDisplayString(historyPosition.value), 1),
|
481
|
+
createElementVNode("pre", null, toDisplayString(history.value), 1),
|
478
482
|
renderSlot(_ctx.$slots, "bottom")
|
479
483
|
]),
|
480
484
|
key: "5"
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ContentEditable.vue.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/components/ContentEditable.vue"],"names":[],"mappings":"AAiBA;
|
1
|
+
{"version":3,"file":"ContentEditable.vue.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/components/ContentEditable.vue"],"names":[],"mappings":"AAiBA;AAyUA,OAAO,KAAK,EAAC,QAAQ,EAAG,aAAa,EAAC,MAAM,UAAU,CAAA;AAStD,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAA;CAClC,CAAC;;;;2BAsK4B,aAAa,KAAG,IAAI;2BATpB,MAAM,aAAa,MAAM;;;;;;;;;;;;;;;;AAsNvD,wBAUG"}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { defineComponent, useTemplateRef, ref, watch, onMounted, createElementBlock, openBlock, nextTick } from 'vue';
|
2
2
|
import { WrapSelectionType } from '../../../utils/utils.js';
|
3
3
|
import { preserveIndentation } from '../models/toolbarActions.js';
|
4
|
-
import { getCaretOffset } from '../models/utils.js';
|
4
|
+
import { getCaretOffset, setCaretOffset } from '../models/utils.js';
|
5
5
|
|
6
6
|
const _hoisted_1 = ["placeholder"];
|
7
7
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
@@ -21,39 +21,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
21
21
|
const updateTextParts = () => {
|
22
22
|
if (!elementRef.value || !props.textParts) return;
|
23
23
|
const offsets = getCaret();
|
24
|
-
const existingNodes = Array.from(elementRef.value.childNodes);
|
25
24
|
let nodeIndex = 0;
|
26
25
|
for (const item of props.textParts) {
|
27
|
-
const existingNode =
|
26
|
+
const existingNode = elementRef.value.childNodes[nodeIndex] ?? null;
|
28
27
|
if (typeof item === "string") {
|
29
28
|
const displayText = item.replace(/\n$/g, "\n ");
|
30
|
-
if (existingNode
|
31
|
-
if (existingNode.textContent !== displayText)
|
32
|
-
existingNode.textContent = displayText;
|
33
|
-
}
|
29
|
+
if (existingNode instanceof Text) {
|
30
|
+
if (existingNode.textContent !== displayText) existingNode.textContent = displayText;
|
34
31
|
} else {
|
35
32
|
const textNode = document.createTextNode(displayText);
|
36
|
-
elementRef.value.insertBefore(textNode, existingNode
|
33
|
+
elementRef.value.insertBefore(textNode, existingNode);
|
37
34
|
}
|
38
35
|
} else {
|
39
|
-
if (existingNode
|
40
|
-
|
41
|
-
if (
|
42
|
-
element.textContent = item.value;
|
43
|
-
}
|
36
|
+
if (existingNode instanceof HTMLElement && existingNode.tagName.toLowerCase() === item.tag.toLowerCase()) {
|
37
|
+
if (existingNode.textContent !== item.value) existingNode.textContent = item.value;
|
38
|
+
if (existingNode.className !== (item.class || "")) existingNode.className = item.class || "";
|
44
39
|
const contentEditable = item.edit ? "plaintext-only" : "false";
|
45
|
-
if (
|
46
|
-
|
47
|
-
}
|
48
|
-
if (element.className !== (item.class || "")) {
|
49
|
-
element.className = item.class || "";
|
40
|
+
if (existingNode.getAttribute("contenteditable") !== contentEditable) {
|
41
|
+
existingNode.setAttribute("contenteditable", contentEditable);
|
50
42
|
}
|
51
43
|
} else {
|
52
44
|
const element = document.createElement(item.tag);
|
53
45
|
element.textContent = item.value;
|
54
46
|
element.setAttribute("contenteditable", item.edit ? "plaintext-only" : "false");
|
55
47
|
if (item.class) element.className = item.class;
|
56
|
-
elementRef.value.insertBefore(element, existingNode
|
48
|
+
elementRef.value.insertBefore(element, existingNode);
|
57
49
|
}
|
58
50
|
}
|
59
51
|
nodeIndex++;
|
@@ -62,7 +54,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
62
54
|
const nodeToRemove = elementRef.value.childNodes[props.textParts.length];
|
63
55
|
elementRef.value.removeChild(nodeToRemove);
|
64
56
|
}
|
65
|
-
if (focused.value) setCaret(offsets.start, offsets.end !== offsets.start ? void 0 : offsets.end);
|
57
|
+
if (focused.value && !isSetCaretNext) setCaret(offsets.start, offsets.end !== offsets.start ? void 0 : offsets.end);
|
66
58
|
};
|
67
59
|
watch(() => props.textParts, updateTextParts, { immediate: true });
|
68
60
|
const updateTextValue = (value) => {
|
@@ -127,38 +119,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
127
119
|
nextTick(() => setCaret(props.maxLength ? Math.min(caretAfter, props.maxLength) : caretAfter));
|
128
120
|
};
|
129
121
|
const getCaret = () => getCaretOffset(elementRef.value);
|
130
|
-
|
131
|
-
if (!elementRef.value || index === void 0) return void 0;
|
132
|
-
if (!elementRef.value.firstChild) elementRef.value.appendChild(document.createTextNode(""));
|
133
|
-
const walker = document.createTreeWalker(elementRef.value, NodeFilter.SHOW_TEXT, null);
|
134
|
-
let node, offset = index;
|
135
|
-
while (node = walker.nextNode()) {
|
136
|
-
const len = node.nodeValue?.length ?? 0;
|
137
|
-
if (offset <= len) return { node, offset };
|
138
|
-
offset -= len;
|
139
|
-
}
|
140
|
-
const last = elementRef.value.lastChild;
|
141
|
-
if (!last) return void 0;
|
142
|
-
return { node: last, offset: last.nodeType === Node.TEXT_NODE && last.nodeValue ? last.nodeValue.length : last.childNodes.length };
|
143
|
-
};
|
122
|
+
let isSetCaretNext = false;
|
144
123
|
const setCaret = (indexStart, indexEnd) => {
|
145
|
-
|
146
|
-
|
147
|
-
const range = document.createRange();
|
148
|
-
range.setStart(start.node, start.offset);
|
149
|
-
const end = getNodeOffset(indexEnd);
|
150
|
-
if (end !== void 0) range.setEnd(end.node, end.offset);
|
151
|
-
else range.collapse(true);
|
152
|
-
const selection = window.getSelection();
|
153
|
-
selection?.removeAllRanges();
|
154
|
-
selection?.addRange(range);
|
124
|
+
isSetCaretNext = false;
|
125
|
+
setCaretOffset(elementRef.value, indexStart, indexEnd);
|
155
126
|
};
|
156
127
|
const collapseList = [" ", "\n"];
|
157
128
|
let offsetsOld = null;
|
158
129
|
const wrapSelection = (value) => {
|
159
|
-
|
160
|
-
|
161
|
-
else offsets = offsetsOld;
|
130
|
+
if (focused.value || !offsetsOld) offsetsOld = getCaret();
|
131
|
+
const offsets = offsetsOld;
|
162
132
|
const currentText = getCurrentText() ?? "";
|
163
133
|
let newText = "";
|
164
134
|
let newCursorStart = offsets.start;
|
@@ -240,8 +210,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
240
210
|
}
|
241
211
|
break;
|
242
212
|
}
|
213
|
+
isSetCaretNext = true;
|
243
214
|
emit("update:model-value", newText);
|
244
|
-
|
215
|
+
requestAnimationFrame(() => setCaret(newCursorStart, newCursorEnd));
|
245
216
|
};
|
246
217
|
const focus = () => {
|
247
218
|
elementRef.value?.focus();
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"InputToolbar.vue.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/components/InputToolbar.vue"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"InputToolbar.vue.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/components/InputToolbar.vue"],"names":[],"mappings":"AA2CA;AA2EA,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAC,MAAM,0BAA0B,CAAA;AAU1E,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,aAAa,EAAE,GAAG,SAAS,CAAA;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB,CAAC;AAiBF,iBAAS,cAAc;WA4HT,OAAO,IAA6B;;yBAVrB,GAAG;;;;EAe/B;AAeD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;;;;6FAQnB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAQpG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { defineComponent, createElementBlock, openBlock, withModifiers, renderSlot, createCommentVNode,
|
1
|
+
import { defineComponent, createElementBlock, openBlock, withModifiers, renderSlot, createCommentVNode, Fragment, renderList, createBlock, mergeProps, unref, createVNode, markRaw } from 'vue';
|
2
2
|
import IconRedo from '../../../assets/icons/IconRedo.svg.js';
|
3
3
|
import IconUndo from '../../../assets/icons/IconUndo.svg.js';
|
4
4
|
import _sfc_main$1 from '../WInputToolbarButton.vue.js';
|
@@ -10,7 +10,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
10
10
|
list: {},
|
11
11
|
rich: { type: Boolean },
|
12
12
|
isUndo: { type: Boolean },
|
13
|
-
isRedo: { type: Boolean }
|
13
|
+
isRedo: { type: Boolean },
|
14
|
+
textSecure: { type: Boolean }
|
14
15
|
},
|
15
16
|
emits: ["wrap-selection", "undo", "redo"],
|
16
17
|
setup(__props, { emit: __emit }) {
|
@@ -42,18 +43,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
42
43
|
onClick: ($event) => wrapSelection(action, $event)
|
43
44
|
}), null, 16, ["onClick"]);
|
44
45
|
}), 128)) : createCommentVNode("", true),
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
46
|
+
!_ctx.textSecure ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
47
|
+
createVNode(_sfc_main$1, {
|
48
|
+
tooltip: "Undo",
|
49
|
+
icon: markRaw(unref(IconUndo)),
|
50
|
+
disabled: !_ctx.isUndo,
|
51
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("undo"))
|
52
|
+
}, null, 8, ["icon", "disabled"]),
|
53
|
+
createVNode(_sfc_main$1, {
|
54
|
+
tooltip: "Redo",
|
55
|
+
icon: markRaw(unref(IconRedo)),
|
56
|
+
disabled: !_ctx.isRedo,
|
57
|
+
onClick: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("redo"))
|
58
|
+
}, null, 8, ["icon", "disabled"])
|
59
|
+
], 64)) : createCommentVNode("", true)
|
57
60
|
], 32);
|
58
61
|
};
|
59
62
|
}
|
@@ -2,5 +2,6 @@ export type CaretOffset = {
|
|
2
2
|
start: number;
|
3
3
|
end: number;
|
4
4
|
};
|
5
|
+
export declare const setCaretOffset: (parent: Element | null | undefined, indexStart: number, indexEnd: number | undefined) => void;
|
5
6
|
export declare const getCaretOffset: (parent: Element | null | undefined) => CaretOffset;
|
6
7
|
//# sourceMappingURL=utils.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/models/utils.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/Input/models/utils.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,WAAW,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAA;AAEtD,eAAO,MAAM,cAAc,GAAI,QAAQ,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,YAAY,MAAM,EAAE,UAAU,MAAM,GAAG,SAAS,SAelH,CAAA;AAqBD,eAAO,MAAM,cAAc,GAAI,QAAQ,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,WAUnE,CAAA"}
|
@@ -1,14 +1,56 @@
|
|
1
|
+
const getNodeOffset = (parent, index) => {
|
2
|
+
if (!parent || index === void 0) return void 0;
|
3
|
+
if (!parent.firstChild) parent.appendChild(document.createTextNode(""));
|
4
|
+
const walker = document.createTreeWalker(parent, NodeFilter.SHOW_TEXT, null);
|
5
|
+
let node, offset = index;
|
6
|
+
while (node = walker.nextNode()) {
|
7
|
+
const len = node.nodeValue?.length ?? 0;
|
8
|
+
if (offset <= len && node.parentElement?.contentEditable !== "false") return { node, offset: Math.max(offset, 0) };
|
9
|
+
offset -= len;
|
10
|
+
}
|
11
|
+
const last = parent.lastChild;
|
12
|
+
if (!last) return void 0;
|
13
|
+
if (last.nodeType === Node.TEXT_NODE) {
|
14
|
+
return { node: last, offset: last.nodeValue?.length ?? 0 };
|
15
|
+
}
|
16
|
+
const textNode = document.createTextNode("");
|
17
|
+
parent.appendChild(textNode);
|
18
|
+
return { node: textNode, offset: 0 };
|
19
|
+
};
|
20
|
+
const setCaretOffset = (parent, indexStart, indexEnd) => {
|
21
|
+
const start = getNodeOffset(parent, indexStart);
|
22
|
+
if (start === void 0) return;
|
23
|
+
const range = document.createRange();
|
24
|
+
range.setStart(start.node, start.offset);
|
25
|
+
const end = getNodeOffset(parent, indexEnd);
|
26
|
+
if (end !== void 0) range.setEnd(end.node, end.offset);
|
27
|
+
else range.collapse(true);
|
28
|
+
const selection = window.getSelection();
|
29
|
+
selection?.removeAllRanges();
|
30
|
+
selection?.addRange(range);
|
31
|
+
};
|
32
|
+
const getOffsetFromNode = (parent, targetNode, targetOffset, isStart) => {
|
33
|
+
if (!parent.firstChild) parent.appendChild(document.createTextNode(""));
|
34
|
+
const walker = document.createTreeWalker(parent, NodeFilter.SHOW_TEXT, null);
|
35
|
+
let node, offset = 0;
|
36
|
+
while (node = walker.nextNode()) {
|
37
|
+
if (node.parentElement?.contentEditable === "false") {
|
38
|
+
if (isStart && node === targetNode) return offset;
|
39
|
+
} else if (node === targetNode) {
|
40
|
+
return offset + targetOffset;
|
41
|
+
}
|
42
|
+
offset += node.nodeValue?.length ?? 0;
|
43
|
+
}
|
44
|
+
return offset;
|
45
|
+
};
|
1
46
|
const getCaretOffset = (parent) => {
|
2
47
|
if (!parent) return { start: 0, end: 0 };
|
3
48
|
const selection = window.getSelection();
|
4
49
|
if (!selection || selection.rangeCount === 0) return { start: 0, end: 0 };
|
5
50
|
const range = selection.getRangeAt(0);
|
6
|
-
const
|
7
|
-
|
8
|
-
|
9
|
-
const start = pre.toString().length;
|
10
|
-
const selected = range.toString().length;
|
11
|
-
return { start, end: start + selected };
|
51
|
+
const start = getOffsetFromNode(parent, range.startContainer, range.startOffset, true);
|
52
|
+
const end = range.startOffset !== range.endOffset ? getOffsetFromNode(parent, range.endContainer, range.endOffset, false) : start;
|
53
|
+
return { start, end };
|
12
54
|
};
|
13
55
|
|
14
|
-
export { getCaretOffset };
|
56
|
+
export { getCaretOffset, setCaretOffset };
|