one-design-next 0.0.13 → 0.0.14
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/composer/editor.js +31 -9
- package/dist/composer/utils.d.ts +13 -0
- package/dist/composer/utils.js +78 -1
- package/package.json +1 -1
package/dist/composer/editor.js
CHANGED
|
@@ -34,7 +34,7 @@ import { createPortal } from 'react-dom';
|
|
|
34
34
|
import { buildClipboardPayload, COMPOSER_CLIPBOARD_MIME, parseClipboardPayload, plainTextFromClipboardPayload, remapClipboardPayload } from "./clipboard";
|
|
35
35
|
import { useChipManager } from "./hooks/useChipManager";
|
|
36
36
|
import { useChipSelectionMarker } from "./hooks/useChipSelectionMarker";
|
|
37
|
-
import { findChipHostBeforeCaret, getPlainText, isEditorEmpty, probeTrigger, resolveCaretJumpAroundChip, ZWSP } from "./utils";
|
|
37
|
+
import { findChipHostAfterCaret, findChipHostBeforeCaret, getPlainText, getVisibleTextBeforeHost, isEditorEmpty, moveCaretBeforeChip, normalizeEditorDom, probeTrigger, resolveCaretJumpAroundChip, stripInvisibleChars, ZWSP } from "./utils";
|
|
38
38
|
import { ComposerInlineRef } from "./inline-ref";
|
|
39
39
|
import ScrollArea from "../scroll-area";
|
|
40
40
|
|
|
@@ -176,6 +176,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
176
176
|
var fireChange = useCallback(function () {
|
|
177
177
|
var el = editorRef.current;
|
|
178
178
|
if (!el) return;
|
|
179
|
+
normalizeEditorDom(el);
|
|
179
180
|
setEmpty(isEditorEmpty(el));
|
|
180
181
|
onChange === null || onChange === void 0 || onChange(getPlainText(el));
|
|
181
182
|
// editor.height 锁定时 RO 不触发,主动同步一次,确保升格判定能拿到 scrollHeight
|
|
@@ -390,7 +391,10 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
390
391
|
* ───────────────────────────────────── */
|
|
391
392
|
var handleInput = useCallback(function () {
|
|
392
393
|
var el = editorRef.current;
|
|
393
|
-
if (el)
|
|
394
|
+
if (el) {
|
|
395
|
+
normalizeEditorDom(el);
|
|
396
|
+
setEmpty(isEditorEmpty(el));
|
|
397
|
+
}
|
|
394
398
|
requestScrollCaretIntoView();
|
|
395
399
|
if (isComposingRef.current) return;
|
|
396
400
|
fireChange();
|
|
@@ -442,17 +446,35 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
442
446
|
if (onTriggerKeyDown(e) === true) return;
|
|
443
447
|
}
|
|
444
448
|
|
|
445
|
-
// Backspace
|
|
449
|
+
// Backspace:chip 边界——空 text 在 chip 后先退回 chip 前;chip 前无正文再整块删
|
|
446
450
|
if (e.key === 'Backspace') {
|
|
451
|
+
var el = editorRef.current;
|
|
447
452
|
var sel = window.getSelection();
|
|
448
|
-
if (sel && sel.rangeCount > 0) {
|
|
453
|
+
if (el && sel && sel.rangeCount > 0) {
|
|
449
454
|
var range = sel.getRangeAt(0);
|
|
450
|
-
if (range.collapsed) {
|
|
451
|
-
var
|
|
452
|
-
|
|
453
|
-
|
|
455
|
+
if (range.collapsed && el.contains(range.startContainer)) {
|
|
456
|
+
var hostBefore = findChipHostBeforeCaret(range);
|
|
457
|
+
if (hostBefore !== null && hostBefore !== void 0 && hostBefore.dataset.mentionId) {
|
|
458
|
+
var _node$textContent;
|
|
459
|
+
var node = range.startContainer,
|
|
460
|
+
offset = range.startOffset;
|
|
461
|
+
if (node.nodeType === Node.TEXT_NODE && offset === 0 && node.previousSibling === hostBefore && stripInvisibleChars((_node$textContent = node.textContent) !== null && _node$textContent !== void 0 ? _node$textContent : '') === '') {
|
|
462
|
+
e.preventDefault();
|
|
463
|
+
moveCaretBeforeChip(hostBefore, {
|
|
464
|
+
removeTrailingEmptyText: true,
|
|
465
|
+
trailingText: node
|
|
466
|
+
});
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
e.preventDefault();
|
|
470
|
+
removeChip(hostBefore.dataset.mentionId);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
var hostAfter = findChipHostAfterCaret(range);
|
|
474
|
+
var idAfter = hostAfter === null || hostAfter === void 0 ? void 0 : hostAfter.dataset.mentionId;
|
|
475
|
+
if (idAfter && getVisibleTextBeforeHost(el, hostAfter).trim() === '') {
|
|
454
476
|
e.preventDefault();
|
|
455
|
-
removeChip(
|
|
477
|
+
removeChip(idAfter);
|
|
456
478
|
return;
|
|
457
479
|
}
|
|
458
480
|
}
|
package/dist/composer/utils.d.ts
CHANGED
|
@@ -86,6 +86,19 @@ export declare function resolveCaretJumpAroundChip(range: Range, direction: 'lef
|
|
|
86
86
|
node: Node;
|
|
87
87
|
offset: number;
|
|
88
88
|
} | null;
|
|
89
|
+
export declare function childIndex(node: Node): number;
|
|
90
|
+
/** chip 之前的可见纯文本(不含 marker / 不可见字符)。 */
|
|
91
|
+
export declare function getVisibleTextBeforeHost(editor: HTMLElement, host: HTMLElement, chipIdAttr?: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* 清理 contenteditable 删字后的幽灵节点:空 text、仅 chip 时的占位 <br>。
|
|
94
|
+
* 避免「文字 + invocation」删光文字后出现多余换行,以及 caret 卡在 chip 后误删 invocation。
|
|
95
|
+
*/
|
|
96
|
+
export declare function normalizeEditorDom(editor: HTMLElement, _chipIdAttr?: string): void;
|
|
97
|
+
/** caret 落在 chip 后空 text 时,挪到 chip 前(不删 chip)。 */
|
|
98
|
+
export declare function moveCaretBeforeChip(host: HTMLElement, opts?: {
|
|
99
|
+
removeTrailingEmptyText?: boolean;
|
|
100
|
+
trailingText?: Text | null;
|
|
101
|
+
}): void;
|
|
89
102
|
export interface TriggerProbe {
|
|
90
103
|
/** 触发字符 */
|
|
91
104
|
trigger: string;
|
package/dist/composer/utils.js
CHANGED
|
@@ -328,7 +328,7 @@ export function resolveCaretJumpAroundChip(range, direction) {
|
|
|
328
328
|
offset: childIndex(chip) + 1
|
|
329
329
|
};
|
|
330
330
|
}
|
|
331
|
-
function childIndex(node) {
|
|
331
|
+
export function childIndex(node) {
|
|
332
332
|
var i = 0;
|
|
333
333
|
var cur = node.previousSibling;
|
|
334
334
|
while (cur) {
|
|
@@ -338,6 +338,83 @@ function childIndex(node) {
|
|
|
338
338
|
return i;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
/** chip 之前的可见纯文本(不含 marker / 不可见字符)。 */
|
|
342
|
+
export function getVisibleTextBeforeHost(editor, host) {
|
|
343
|
+
var chipIdAttr = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'mentionId';
|
|
344
|
+
var r = document.createRange();
|
|
345
|
+
r.selectNodeContents(editor);
|
|
346
|
+
r.setEndBefore(host);
|
|
347
|
+
var tmp = document.createElement('div');
|
|
348
|
+
tmp.appendChild(r.cloneContents());
|
|
349
|
+
return stripInvisibleChars(stripMarkers(getPlainText(tmp))).replace(/\n/g, '');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* 清理 contenteditable 删字后的幽灵节点:空 text、仅 chip 时的占位 <br>。
|
|
354
|
+
* 避免「文字 + invocation」删光文字后出现多余换行,以及 caret 卡在 chip 后误删 invocation。
|
|
355
|
+
*/
|
|
356
|
+
export function normalizeEditorDom(editor) {
|
|
357
|
+
var _chipIdAttr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'mentionId';
|
|
358
|
+
var emptyTexts = [];
|
|
359
|
+
var walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT);
|
|
360
|
+
var n;
|
|
361
|
+
while (n = walker.nextNode()) {
|
|
362
|
+
var _t$textContent;
|
|
363
|
+
var t = n;
|
|
364
|
+
if (stripInvisibleChars((_t$textContent = t.textContent) !== null && _t$textContent !== void 0 ? _t$textContent : '') === '') {
|
|
365
|
+
emptyTexts.push(t);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
emptyTexts.forEach(function (t) {
|
|
369
|
+
return t.remove();
|
|
370
|
+
});
|
|
371
|
+
var plain = stripInvisibleChars(stripMarkers(getPlainText(editor))).replace(/\n/g, '');
|
|
372
|
+
var hasChip = !!editor.querySelector('[data-odn-composer-chip-host]');
|
|
373
|
+
if (hasChip && plain === '') {
|
|
374
|
+
editor.querySelectorAll('br').forEach(function (br) {
|
|
375
|
+
return br.remove();
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
editor.querySelectorAll('[data-odn-composer-chip-host]').forEach(function (hostEl) {
|
|
379
|
+
var host = hostEl;
|
|
380
|
+
var prev = host.previousSibling;
|
|
381
|
+
while (prev) {
|
|
382
|
+
if (prev.nodeType === Node.TEXT_NODE) {
|
|
383
|
+
var _prev$textContent;
|
|
384
|
+
var _t = stripInvisibleChars((_prev$textContent = prev.textContent) !== null && _prev$textContent !== void 0 ? _prev$textContent : '');
|
|
385
|
+
if (_t !== '') break;
|
|
386
|
+
var rm = prev;
|
|
387
|
+
prev = prev.previousSibling;
|
|
388
|
+
rm.remove();
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (prev.nodeType === Node.ELEMENT_NODE && prev.tagName === 'BR') {
|
|
392
|
+
var _rm = prev;
|
|
393
|
+
prev = prev.previousSibling;
|
|
394
|
+
_rm.remove();
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** caret 落在 chip 后空 text 时,挪到 chip 前(不删 chip)。 */
|
|
403
|
+
export function moveCaretBeforeChip(host, opts) {
|
|
404
|
+
var parent = host.parentNode;
|
|
405
|
+
if (!parent) return;
|
|
406
|
+
var sel = window.getSelection();
|
|
407
|
+
if (!sel) return;
|
|
408
|
+
var r = document.createRange();
|
|
409
|
+
r.setStart(parent, childIndex(host));
|
|
410
|
+
r.collapse(true);
|
|
411
|
+
sel.removeAllRanges();
|
|
412
|
+
sel.addRange(r);
|
|
413
|
+
if (opts !== null && opts !== void 0 && opts.removeTrailingEmptyText && opts.trailingText) {
|
|
414
|
+
opts.trailingText.remove();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
341
418
|
/* ────────────────────────────────────────────────────────────────────
|
|
342
419
|
* Trigger probe · @ / / 触发态判定
|
|
343
420
|
*
|