one-design-next 0.0.13 → 0.0.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/_genui-types.d.ts +72 -27
- package/dist/action-bar/style/index.css +2 -2
- package/dist/agent-step/style/index.css +1 -1
- package/dist/attachments/style/index.css +5 -5
- package/dist/chat-item/style/index.css +2 -2
- package/dist/composer/clipboard.d.ts +1 -1
- package/dist/composer/editor.d.ts +10 -2
- package/dist/composer/editor.js +199 -35
- package/dist/composer/hooks/useChipManager.d.ts +8 -3
- package/dist/composer/hooks/useChipManager.js +105 -10
- package/dist/composer/index.d.ts +17 -2
- package/dist/composer/index.js +136 -65
- package/dist/composer/inline-ref.d.ts +6 -2
- package/dist/composer/inline-ref.js +10 -3
- package/dist/composer/param-panel.d.ts +14 -0
- package/dist/composer/param-panel.js +1 -0
- package/dist/composer/segments.d.ts +29 -0
- package/dist/composer/segments.js +83 -0
- package/dist/composer/send-meta.d.ts +7 -4
- package/dist/composer/send-meta.js +12 -52
- package/dist/composer/style/index.css +27 -8
- package/dist/composer/utils.d.ts +35 -1
- package/dist/composer/utils.js +281 -36
- package/dist/fab/style/index.css +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/invocation/index.d.ts +7 -2
- package/dist/invocation/index.js +14 -8
- package/dist/invocation/param-popover.d.ts +21 -0
- package/dist/invocation/param-popover.js +113 -0
- package/dist/invocation/style/index.css +33 -9
- package/dist/mention/index.d.ts +1 -6
- package/dist/mention/index.js +11 -8
- package/dist/mention/style/index.css +30 -9
- package/dist/preview-panel/index.js +11 -1
- package/dist/preview-panel/style/index.css +11 -0
- package/dist/skill-slot/index.js +5 -5
- package/dist/skill-slot/style/index.css +51 -27
- package/dist/suggestions/index.js +1 -5
- package/dist/suggestions/style/index.css +6 -7
- package/dist/user-bubble/index.js +9 -4
- package/dist/user-bubble/render-segments.d.ts +9 -0
- package/dist/user-bubble/render-segments.js +42 -0
- package/dist/user-bubble/style/index.css +9 -0
- package/dist/welcome/style/index.css +1 -1
- package/package.json +4 -4
- package/dist/composer/chip.d.ts +0 -36
- package/dist/composer/chip.js +0 -49
package/dist/composer/editor.js
CHANGED
|
@@ -25,7 +25,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
25
25
|
*
|
|
26
26
|
* chip 模型(hybrid):
|
|
27
27
|
* - DOM 由 contenteditable 自治:每个 chip 是 contentEditable=false 的 span(host),带 data-mention-id
|
|
28
|
-
* - 视觉由 React Portal 注入到 host 内:
|
|
28
|
+
* - 视觉由 React Portal 注入到 host 内:ComposerInlineRef 负责
|
|
29
29
|
* - chip 状态(id ↔ host)由 useChipManager 维护
|
|
30
30
|
*/
|
|
31
31
|
|
|
@@ -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,
|
|
37
|
+
import { ensureTextAnchorAt, findChipHostAfterCaret, findChipHostBeforeCaret, getPlainText, getVisibleTextBeforeHost, isEditorEmpty, moveCaretBeforeChip, normalizeComposerEditorDom, normalizeEditorDom, probeTrigger, resolveCaretJumpAroundChip, stripInvisibleChars, CARET_SPACER } from "./utils";
|
|
38
38
|
import { ComposerInlineRef } from "./inline-ref";
|
|
39
39
|
import ScrollArea from "../scroll-area";
|
|
40
40
|
|
|
@@ -102,6 +102,9 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
102
102
|
onHeightChange = _ref.onHeightChange,
|
|
103
103
|
onPasteFiles = _ref.onPasteFiles,
|
|
104
104
|
onCopyChips = _ref.onCopyChips,
|
|
105
|
+
_ref$paramEditChipId = _ref.paramEditChipId,
|
|
106
|
+
paramEditChipId = _ref$paramEditChipId === void 0 ? null : _ref$paramEditChipId,
|
|
107
|
+
onInlineRefClick = _ref.onInlineRefClick,
|
|
105
108
|
_ref$disabled = _ref.disabled,
|
|
106
109
|
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
107
110
|
className = _ref.className,
|
|
@@ -122,18 +125,29 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
122
125
|
|
|
123
126
|
/** 当前活动 trigger probe;null 表示无触发态。 */
|
|
124
127
|
var triggerRef = useRef(null);
|
|
128
|
+
/** 最近一次落在 editor 内的 selection(菜单点击导致 blur 后用于恢复插入点)。 */
|
|
129
|
+
var lastEditorRangeRef = useRef(null);
|
|
130
|
+
/** 抑制换行后短窗口内的 selection 二次校正,避免首次 chip 后换行闪烁。 */
|
|
131
|
+
var suppressSelectionNormalizeCountRef = useRef(0);
|
|
132
|
+
/** 用户刚执行“主动换行”时,允许 empty 判定在一次变更内保持非空。 */
|
|
133
|
+
var forceNonEmptyOnceRef = useRef(false);
|
|
125
134
|
|
|
126
135
|
/** 派生:编辑器是否完全空(无文本 + 无 chip),驱动 placeholder。 */
|
|
127
136
|
var _useState = useState(true),
|
|
128
137
|
_useState2 = _slicedToArray(_useState, 2),
|
|
129
138
|
empty = _useState2[0],
|
|
130
139
|
setEmpty = _useState2[1];
|
|
140
|
+
/** 输入模态:键盘操作时置为 keyboard,用于抑制“鼠标隐藏但 hover 仍生效”的视觉残留。 */
|
|
141
|
+
var _useState3 = useState('pointer'),
|
|
142
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
143
|
+
inputModality = _useState4[0],
|
|
144
|
+
setInputModality = _useState4[1];
|
|
131
145
|
|
|
132
146
|
/** ScrollArea root 显式高度。Base UI viewport=100%,root 必须有确定 height。 */
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
scrollHeight =
|
|
136
|
-
setScrollHeight =
|
|
147
|
+
var _useState5 = useState(null),
|
|
148
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
149
|
+
scrollHeight = _useState6[0],
|
|
150
|
+
setScrollHeight = _useState6[1];
|
|
137
151
|
|
|
138
152
|
/** onHeightChange 用 ref 稳定,避免 ResizeObserver effect 反复 cleanup/重建。 */
|
|
139
153
|
var onHeightChangeRef = useRef(onHeightChange);
|
|
@@ -173,14 +187,27 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
173
187
|
});
|
|
174
188
|
(_onHeightChangeRef$cu = onHeightChangeRef.current) === null || _onHeightChangeRef$cu === void 0 || _onHeightChangeRef$cu.call(onHeightChangeRef, natural, overflow);
|
|
175
189
|
}, [minHeightPx, maxHeightPx]);
|
|
190
|
+
var shouldShowPlaceholder = useCallback(function (el) {
|
|
191
|
+
if (!isEditorEmpty(el)) return false;
|
|
192
|
+
// placeholder 仅在“单行且空内容”展示
|
|
193
|
+
var lineCount = el.querySelectorAll('br').length + 1;
|
|
194
|
+
return lineCount <= 1;
|
|
195
|
+
}, []);
|
|
176
196
|
var fireChange = useCallback(function () {
|
|
177
197
|
var el = editorRef.current;
|
|
178
198
|
if (!el) return;
|
|
179
|
-
|
|
199
|
+
normalizeEditorDom(el);
|
|
200
|
+
var showPlaceholder = shouldShowPlaceholder(el);
|
|
201
|
+
if (forceNonEmptyOnceRef.current && showPlaceholder) {
|
|
202
|
+
setEmpty(false);
|
|
203
|
+
} else {
|
|
204
|
+
setEmpty(showPlaceholder);
|
|
205
|
+
}
|
|
206
|
+
forceNonEmptyOnceRef.current = false;
|
|
180
207
|
onChange === null || onChange === void 0 || onChange(getPlainText(el));
|
|
181
208
|
// editor.height 锁定时 RO 不触发,主动同步一次,确保升格判定能拿到 scrollHeight
|
|
182
209
|
syncHeight();
|
|
183
|
-
}, [onChange, syncHeight]);
|
|
210
|
+
}, [onChange, shouldShowPlaceholder, syncHeight]);
|
|
184
211
|
|
|
185
212
|
/* ─────────────────────────────────────
|
|
186
213
|
* chip 管理
|
|
@@ -194,6 +221,8 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
194
221
|
insertSerializedAtRange = _useChipManager.insertSerializedAtRange,
|
|
195
222
|
syncChipsAfterDomMutation = _useChipManager.syncChipsAfterDomMutation,
|
|
196
223
|
removeChip = _useChipManager.removeChip,
|
|
224
|
+
updateChipData = _useChipManager.updateChipData,
|
|
225
|
+
getChipHost = _useChipManager.getChipHost,
|
|
197
226
|
resetChips = _useChipManager.resetChips;
|
|
198
227
|
useChipSelectionMarker(editorRef, chips);
|
|
199
228
|
|
|
@@ -253,7 +282,17 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
253
282
|
insertChip: function insertChip(data) {
|
|
254
283
|
var el = editorRef.current;
|
|
255
284
|
if (!el) return;
|
|
256
|
-
|
|
285
|
+
// 优先恢复缓存光标到真实 selection;菜单点击时 selection 已经离开 editor,
|
|
286
|
+
// 直接走 useChipManager 的 fallback 会落到 editor 末尾,导致“飞到第一/末行”。
|
|
287
|
+
var cached = lastEditorRangeRef.current;
|
|
288
|
+
if (cached && cached.startContainer.isConnected && cached.endContainer.isConnected && el.contains(cached.startContainer) && el.contains(cached.endContainer)) {
|
|
289
|
+
var sel = window.getSelection();
|
|
290
|
+
if (sel) {
|
|
291
|
+
sel.removeAllRanges();
|
|
292
|
+
sel.addRange(cached.cloneRange());
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
_insertChip(data, el, cached);
|
|
257
296
|
},
|
|
258
297
|
removeChip: removeChip,
|
|
259
298
|
replaceTriggerWithChip: function replaceTriggerWithChip(data) {
|
|
@@ -261,8 +300,8 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
261
300
|
if (!el) return;
|
|
262
301
|
var probe = triggerRef.current;
|
|
263
302
|
if (!probe) {
|
|
264
|
-
// 无活动 trigger
|
|
265
|
-
_insertChip(data, el);
|
|
303
|
+
// 无活动 trigger,退化为最近光标处插入
|
|
304
|
+
_insertChip(data, el, lastEditorRangeRef.current);
|
|
266
305
|
return;
|
|
267
306
|
}
|
|
268
307
|
// 选中 trigger + query 整段,删掉再插 chip
|
|
@@ -299,11 +338,13 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
299
338
|
return c.data;
|
|
300
339
|
});
|
|
301
340
|
},
|
|
341
|
+
updateChipData: updateChipData,
|
|
342
|
+
getChipHost: getChipHost,
|
|
302
343
|
get nativeElement() {
|
|
303
344
|
return editorRef.current;
|
|
304
345
|
}
|
|
305
346
|
};
|
|
306
|
-
}, [onChange, _insertChip, removeChip, resetChips, onTriggerChange, chips]);
|
|
347
|
+
}, [onChange, _insertChip, removeChip, resetChips, onTriggerChange, chips, updateChipData, getChipHost]);
|
|
307
348
|
|
|
308
349
|
/* ─────────────────────────────────────
|
|
309
350
|
* 监听 selection 变化:方向键 / 鼠标点击移位都要重算 trigger
|
|
@@ -323,6 +364,28 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
323
364
|
}
|
|
324
365
|
return;
|
|
325
366
|
}
|
|
367
|
+
var range = sel.getRangeAt(0);
|
|
368
|
+
// 先缓存 editor 内真实光标;即便本次走 suppress 提前 return,也不能丢失插入锚点
|
|
369
|
+
lastEditorRangeRef.current = range.cloneRange();
|
|
370
|
+
if (suppressSelectionNormalizeCountRef.current > 0) {
|
|
371
|
+
suppressSelectionNormalizeCountRef.current -= 1;
|
|
372
|
+
recomputeTrigger();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (range.collapsed && range.startContainer.nodeType === Node.ELEMENT_NODE) {
|
|
376
|
+
var hostBefore = findChipHostBeforeCaret(range);
|
|
377
|
+
var hostAfter = findChipHostAfterCaret(range);
|
|
378
|
+
if (hostBefore || hostAfter) {
|
|
379
|
+
var _anchor = ensureTextAnchorAt(range.startContainer, range.startOffset);
|
|
380
|
+
if (_anchor) {
|
|
381
|
+
var r = document.createRange();
|
|
382
|
+
r.setStart(_anchor.node, _anchor.offset);
|
|
383
|
+
r.collapse(true);
|
|
384
|
+
sel.removeAllRanges();
|
|
385
|
+
sel.addRange(r);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
326
389
|
recomputeTrigger();
|
|
327
390
|
};
|
|
328
391
|
document.addEventListener('selectionchange', handler);
|
|
@@ -373,7 +436,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
373
436
|
if (valueProp !== current) {
|
|
374
437
|
el.textContent = valueProp !== null && valueProp !== void 0 ? valueProp : '';
|
|
375
438
|
resetChips();
|
|
376
|
-
setEmpty(
|
|
439
|
+
setEmpty(shouldShowPlaceholder(el));
|
|
377
440
|
if (triggerRef.current) {
|
|
378
441
|
triggerRef.current = null;
|
|
379
442
|
onTriggerChange === null || onTriggerChange === void 0 || onTriggerChange(null);
|
|
@@ -390,9 +453,15 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
390
453
|
* ───────────────────────────────────── */
|
|
391
454
|
var handleInput = useCallback(function () {
|
|
392
455
|
var el = editorRef.current;
|
|
393
|
-
if (el)
|
|
456
|
+
if (el && !isComposingRef.current) {
|
|
457
|
+
normalizeComposerEditorDom(el);
|
|
458
|
+
}
|
|
394
459
|
requestScrollCaretIntoView();
|
|
395
|
-
if (isComposingRef.current)
|
|
460
|
+
if (isComposingRef.current) {
|
|
461
|
+
// 合成期只负责隐藏 placeholder,不触发归一化提交链路
|
|
462
|
+
setEmpty(false);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
396
465
|
fireChange();
|
|
397
466
|
recomputeTrigger();
|
|
398
467
|
}, [fireChange, recomputeTrigger, requestScrollCaretIntoView]);
|
|
@@ -403,6 +472,8 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
403
472
|
}, []);
|
|
404
473
|
var handleCompositionEnd = useCallback(function () {
|
|
405
474
|
isComposingRef.current = false;
|
|
475
|
+
var el = editorRef.current;
|
|
476
|
+
if (el) normalizeComposerEditorDom(el);
|
|
406
477
|
fireChange();
|
|
407
478
|
recomputeTrigger();
|
|
408
479
|
requestScrollCaretIntoView();
|
|
@@ -414,18 +485,25 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
414
485
|
* - 默认行为 = 自插 <br>(替代浏览器默认的 <div> 包裹,避免破坏 inline 流)
|
|
415
486
|
* ───────────────────────────────────── */
|
|
416
487
|
var insertLineBreak = useCallback(function () {
|
|
417
|
-
var _br$parentNode;
|
|
488
|
+
var _br$parentNode, _tail$textContent;
|
|
418
489
|
var sel = window.getSelection();
|
|
419
490
|
if (!sel || sel.rangeCount === 0) return;
|
|
420
491
|
var range = sel.getRangeAt(0);
|
|
421
492
|
range.deleteContents();
|
|
422
493
|
var br = document.createElement('br');
|
|
494
|
+
br.setAttribute('data-odn-composer-user-break', 'true');
|
|
423
495
|
range.insertNode(br);
|
|
424
|
-
//
|
|
425
|
-
|
|
496
|
+
// 用户主动换行后应立即收起 placeholder
|
|
497
|
+
setEmpty(false);
|
|
498
|
+
forceNonEmptyOnceRef.current = true;
|
|
499
|
+
// 本次主动设 range 会触发 selectionchange,短窗口内跳过二次 caret 校正避免闪烁
|
|
500
|
+
suppressSelectionNormalizeCountRef.current = 2;
|
|
501
|
+
// webkit:行尾插 br 时需要 spacer 让 caret 落点可见
|
|
502
|
+
var tail = document.createTextNode(CARET_SPACER);
|
|
426
503
|
(_br$parentNode = br.parentNode) === null || _br$parentNode === void 0 || _br$parentNode.insertBefore(tail, br.nextSibling);
|
|
427
504
|
var newRange = document.createRange();
|
|
428
|
-
|
|
505
|
+
// 直接落在 spacer 文本内部,避免 element-boundary caret 在首拍被二次改写
|
|
506
|
+
newRange.setStart(tail, ((_tail$textContent = tail.textContent) !== null && _tail$textContent !== void 0 ? _tail$textContent : '').length);
|
|
429
507
|
newRange.collapse(true);
|
|
430
508
|
sel.removeAllRanges();
|
|
431
509
|
sel.addRange(newRange);
|
|
@@ -433,26 +511,101 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
433
511
|
requestScrollCaretIntoView();
|
|
434
512
|
}, [fireChange, requestScrollCaretIntoView]);
|
|
435
513
|
var handleKeyDown = useCallback(function (e) {
|
|
514
|
+
if (inputModality !== 'keyboard') setInputModality('keyboard');
|
|
436
515
|
if (isComposingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
437
516
|
|
|
438
517
|
/* 触发态优先:activeTrigger 时把导航键先吐给父组件(驱动浮层选择)。
|
|
439
518
|
* 父返回 true 表示已处理,editor 直接结束本次 keydown,不再走任何
|
|
440
519
|
* 自身逻辑(避免 Enter 又触发 onPressEnter / 插换行)。 */
|
|
441
|
-
if (triggerRef.current && onTriggerKeyDown && (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === 'Escape' || e.key === 'Tab')) {
|
|
520
|
+
if (triggerRef.current && onTriggerKeyDown && (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' && !e.shiftKey || e.key === 'Escape' || e.key === 'Tab')) {
|
|
442
521
|
if (onTriggerKeyDown(e) === true) return;
|
|
443
522
|
}
|
|
444
523
|
|
|
445
|
-
// Backspace
|
|
524
|
+
// Backspace:chip 边界——空 text 在 chip 后先退回 chip 前;chip 前无正文再整块删
|
|
446
525
|
if (e.key === 'Backspace') {
|
|
526
|
+
var el = editorRef.current;
|
|
447
527
|
var sel = window.getSelection();
|
|
448
|
-
if (sel && sel.rangeCount > 0) {
|
|
528
|
+
if (el && sel && sel.rangeCount > 0) {
|
|
449
529
|
var range = sel.getRangeAt(0);
|
|
450
|
-
if (range.collapsed) {
|
|
451
|
-
var
|
|
452
|
-
|
|
453
|
-
|
|
530
|
+
if (range.collapsed && el.contains(range.startContainer)) {
|
|
531
|
+
var node = range.startContainer,
|
|
532
|
+
offset = range.startOffset;
|
|
533
|
+
|
|
534
|
+
// 用户换行生成的 "<br> + CARET_SPACER":一次 Backspace 应合并删除,避免看起来“卡一下”
|
|
535
|
+
{
|
|
536
|
+
var spacerText = null;
|
|
537
|
+
var br = null;
|
|
538
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
539
|
+
var _t$textContent;
|
|
540
|
+
var t = node;
|
|
541
|
+
var s = (_t$textContent = t.textContent) !== null && _t$textContent !== void 0 ? _t$textContent : '';
|
|
542
|
+
if (s.startsWith(CARET_SPACER) && offset <= 1 && t.previousSibling instanceof HTMLBRElement) {
|
|
543
|
+
spacerText = t;
|
|
544
|
+
br = t.previousSibling;
|
|
545
|
+
}
|
|
546
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
547
|
+
var _elNode$childNodes, _elNode$childNodes$of, _textContent, _textContent2;
|
|
548
|
+
var elNode = node;
|
|
549
|
+
var prev = (_elNode$childNodes = elNode.childNodes[offset - 1]) !== null && _elNode$childNodes !== void 0 ? _elNode$childNodes : null;
|
|
550
|
+
var at = (_elNode$childNodes$of = elNode.childNodes[offset]) !== null && _elNode$childNodes$of !== void 0 ? _elNode$childNodes$of : null;
|
|
551
|
+
if (prev && prev.nodeType === Node.TEXT_NODE && ((_textContent = prev.textContent) !== null && _textContent !== void 0 ? _textContent : '').startsWith(CARET_SPACER) && prev.previousSibling instanceof HTMLBRElement) {
|
|
552
|
+
spacerText = prev;
|
|
553
|
+
br = prev.previousSibling;
|
|
554
|
+
} else if (prev instanceof HTMLBRElement && at && at.nodeType === Node.TEXT_NODE && ((_textContent2 = at.textContent) !== null && _textContent2 !== void 0 ? _textContent2 : '').startsWith(CARET_SPACER)) {
|
|
555
|
+
spacerText = at;
|
|
556
|
+
br = prev;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (spacerText && br) {
|
|
560
|
+
e.preventDefault();
|
|
561
|
+
var parent = br.parentNode;
|
|
562
|
+
if (parent) {
|
|
563
|
+
var _spacerText$textConte;
|
|
564
|
+
var idx = Array.from(parent.childNodes).indexOf(br);
|
|
565
|
+
var text = (_spacerText$textConte = spacerText.textContent) !== null && _spacerText$textConte !== void 0 ? _spacerText$textConte : '';
|
|
566
|
+
if (text === CARET_SPACER) {
|
|
567
|
+
spacerText.remove();
|
|
568
|
+
} else {
|
|
569
|
+
spacerText.textContent = text.slice(1);
|
|
570
|
+
}
|
|
571
|
+
br.remove();
|
|
572
|
+
var r = document.createRange();
|
|
573
|
+
if (spacerText.isConnected) {
|
|
574
|
+
r.setStart(spacerText, 0);
|
|
575
|
+
} else {
|
|
576
|
+
r.setStart(parent, Math.max(0, idx));
|
|
577
|
+
}
|
|
578
|
+
r.collapse(true);
|
|
579
|
+
sel.removeAllRanges();
|
|
580
|
+
sel.addRange(r);
|
|
581
|
+
fireChange();
|
|
582
|
+
recomputeTrigger();
|
|
583
|
+
}
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
var hostBefore = findChipHostBeforeCaret(range);
|
|
588
|
+
if (hostBefore !== null && hostBefore !== void 0 && hostBefore.dataset.mentionId) {
|
|
589
|
+
var _node$textContent;
|
|
590
|
+
var _node = range.startContainer,
|
|
591
|
+
_offset = range.startOffset;
|
|
592
|
+
if (_node.nodeType === Node.TEXT_NODE && _offset === 0 && _node.previousSibling === hostBefore && stripInvisibleChars((_node$textContent = _node.textContent) !== null && _node$textContent !== void 0 ? _node$textContent : '') === '') {
|
|
593
|
+
e.preventDefault();
|
|
594
|
+
moveCaretBeforeChip(hostBefore, {
|
|
595
|
+
removeTrailingEmptyText: true,
|
|
596
|
+
trailingText: _node
|
|
597
|
+
});
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
454
600
|
e.preventDefault();
|
|
455
|
-
removeChip(
|
|
601
|
+
removeChip(hostBefore.dataset.mentionId);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
var hostAfter = findChipHostAfterCaret(range);
|
|
605
|
+
var idAfter = hostAfter === null || hostAfter === void 0 ? void 0 : hostAfter.dataset.mentionId;
|
|
606
|
+
if (idAfter && getVisibleTextBeforeHost(el, hostAfter).trim() === '') {
|
|
607
|
+
e.preventDefault();
|
|
608
|
+
removeChip(idAfter);
|
|
456
609
|
return;
|
|
457
610
|
}
|
|
458
611
|
}
|
|
@@ -469,11 +622,11 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
469
622
|
var target = resolveCaretJumpAroundChip(_range, e.key === 'ArrowLeft' ? 'left' : 'right');
|
|
470
623
|
if (target) {
|
|
471
624
|
e.preventDefault();
|
|
472
|
-
var
|
|
473
|
-
|
|
474
|
-
|
|
625
|
+
var _r = document.createRange();
|
|
626
|
+
_r.setStart(target.node, target.offset);
|
|
627
|
+
_r.collapse(true);
|
|
475
628
|
_sel.removeAllRanges();
|
|
476
|
-
_sel.addRange(
|
|
629
|
+
_sel.addRange(_r);
|
|
477
630
|
return;
|
|
478
631
|
}
|
|
479
632
|
}
|
|
@@ -481,15 +634,18 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
481
634
|
}
|
|
482
635
|
if (e.key === 'Enter') {
|
|
483
636
|
if (onPressEnter) {
|
|
484
|
-
var
|
|
485
|
-
if (
|
|
637
|
+
var _r2 = onPressEnter(e);
|
|
638
|
+
if (_r2 === false) return;
|
|
486
639
|
}
|
|
487
640
|
// 外部(如浮层)已经 preventDefault → 不再插换行
|
|
488
641
|
if (e.defaultPrevented) return;
|
|
489
642
|
e.preventDefault();
|
|
490
643
|
insertLineBreak();
|
|
491
644
|
}
|
|
492
|
-
}, [onPressEnter, insertLineBreak, removeChip, onTriggerKeyDown]);
|
|
645
|
+
}, [inputModality, onPressEnter, insertLineBreak, removeChip, onTriggerKeyDown, fireChange, recomputeTrigger]);
|
|
646
|
+
var handlePointerInput = useCallback(function () {
|
|
647
|
+
if (inputModality !== 'pointer') setInputModality('pointer');
|
|
648
|
+
}, [inputModality]);
|
|
493
649
|
var writeClipboardPayload = useCallback(function (e, payload) {
|
|
494
650
|
if (!payload) return false;
|
|
495
651
|
e.clipboardData.setData(COMPOSER_CLIPBOARD_MIME, JSON.stringify(payload));
|
|
@@ -600,6 +756,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
600
756
|
"aria-disabled": disabled || undefined,
|
|
601
757
|
"data-odn-composer-editor": true,
|
|
602
758
|
"data-odn-composer-editor-disabled": disabled || undefined,
|
|
759
|
+
"data-odn-input-modality": inputModality,
|
|
603
760
|
"data-empty": empty || undefined,
|
|
604
761
|
"data-placeholder": placeholder,
|
|
605
762
|
className: className,
|
|
@@ -607,12 +764,19 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
607
764
|
onCompositionStart: handleCompositionStart,
|
|
608
765
|
onCompositionEnd: handleCompositionEnd,
|
|
609
766
|
onKeyDown: handleKeyDown,
|
|
767
|
+
onMouseMove: handlePointerInput,
|
|
768
|
+
onMouseDown: handlePointerInput,
|
|
769
|
+
onPointerMove: handlePointerInput,
|
|
610
770
|
onCopy: handleCopy,
|
|
611
771
|
onCut: handleCut,
|
|
612
772
|
onPaste: handlePaste
|
|
613
773
|
})), chips.map(function (chip) {
|
|
614
774
|
return /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(ComposerInlineRef, {
|
|
615
|
-
data: chip.data
|
|
775
|
+
data: chip.data,
|
|
776
|
+
active: paramEditChipId === chip.data.id,
|
|
777
|
+
onClick: onInlineRefClick ? function (anchor) {
|
|
778
|
+
return onInlineRefClick(chip.data.id, anchor);
|
|
779
|
+
} : undefined
|
|
616
780
|
}), chip.host, chip.data.id);
|
|
617
781
|
}));
|
|
618
782
|
});
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* - DOM 与 React state 的"双向"维护:DOM 由 contenteditable 自治、视觉由 Portal 注入
|
|
8
8
|
*
|
|
9
9
|
* 不负责:
|
|
10
|
-
* - chip 视觉渲染(
|
|
10
|
+
* - chip 视觉渲染(inline-ref → Invocation / Mention)
|
|
11
11
|
* - 触发判定(useTriggerMenu,step 4 加)
|
|
12
12
|
* - onChange 抛出(由调用方 onAfterMutate 回调中处理)
|
|
13
13
|
*/
|
|
14
|
-
import type { ChipData } from '
|
|
14
|
+
import type { ChipData } from '../../_genui-types';
|
|
15
15
|
/** chip 在 React 状态中的形态:data + 对应的 DOM host。 */
|
|
16
16
|
export interface ManagedChip {
|
|
17
17
|
data: ChipData;
|
|
@@ -22,10 +22,11 @@ export interface UseChipManagerReturn {
|
|
|
22
22
|
chips: ManagedChip[];
|
|
23
23
|
/**
|
|
24
24
|
* 在编辑器当前光标位置插入 chip:
|
|
25
|
+
* - 优先使用 preferredRange(菜单点击时缓存的最近编辑器 selection)
|
|
25
26
|
* - selection 在编辑器内 → 插入光标处
|
|
26
27
|
* - selection 在编辑器外 / 无 selection → fallback 到末尾
|
|
27
28
|
*/
|
|
28
|
-
insertChip: (data: ChipData, editor: HTMLElement) => void;
|
|
29
|
+
insertChip: (data: ChipData, editor: HTMLElement, preferredRange?: Range | null) => void;
|
|
29
30
|
/** 在指定 range 处插入 chip(调用方负责 deleteContents)。 */
|
|
30
31
|
insertChipAtRange: (data: ChipData, range: Range, editor: HTMLElement) => HTMLSpanElement;
|
|
31
32
|
/** 将含 marker 的 raw value + chips 插入 range(粘贴用)。 */
|
|
@@ -34,6 +35,10 @@ export interface UseChipManagerReturn {
|
|
|
34
35
|
syncChipsAfterDomMutation: (editor: HTMLElement) => void;
|
|
35
36
|
/** 按 chip id 移除(同时清理伴随的 ZWSP 锚点)。 */
|
|
36
37
|
removeChip: (id: string) => void;
|
|
38
|
+
/** 更新 chip 数据(参数面板关闭保存等)。 */
|
|
39
|
+
updateChipData: (id: string, patch: Partial<ChipData>) => void;
|
|
40
|
+
/** 按 id 取 chip host(参数面板 anchor)。 */
|
|
41
|
+
getChipHost: (id: string) => HTMLSpanElement | null;
|
|
37
42
|
/** 清空所有 chip 的 React 状态(DOM 由调用方 editor.innerHTML='' 一并处理)。 */
|
|
38
43
|
resetChips: () => void;
|
|
39
44
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
1
7
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
2
8
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
9
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
@@ -17,13 +23,13 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
17
23
|
* - DOM 与 React state 的"双向"维护:DOM 由 contenteditable 自治、视觉由 Portal 注入
|
|
18
24
|
*
|
|
19
25
|
* 不负责:
|
|
20
|
-
* - chip 视觉渲染(
|
|
26
|
+
* - chip 视觉渲染(inline-ref → Invocation / Mention)
|
|
21
27
|
* - 触发判定(useTriggerMenu,step 4 加)
|
|
22
28
|
* - onChange 抛出(由调用方 onAfterMutate 回调中处理)
|
|
23
29
|
*/
|
|
24
30
|
|
|
25
31
|
import { useCallback, useRef, useState } from 'react';
|
|
26
|
-
import { forEachMarkerSegment } from "../utils";
|
|
32
|
+
import { attachCaretSpacerAfter, CARET_SPACER, detachCaretSpacerAfter, ensureTextAnchorAt, forEachMarkerSegment, normalizeComposerEditorDom, ZWSP } from "../utils";
|
|
27
33
|
|
|
28
34
|
/** chip 在 React 状态中的形态:data + 对应的 DOM host。 */
|
|
29
35
|
|
|
@@ -42,9 +48,11 @@ onAfterMutate) {
|
|
|
42
48
|
setChips = _useState2[1];
|
|
43
49
|
var chipsRef = useRef(chips);
|
|
44
50
|
chipsRef.current = chips;
|
|
45
|
-
var insertChipAtRange = useCallback(function (data, range,
|
|
51
|
+
var insertChipAtRange = useCallback(function (data, range, editor) {
|
|
46
52
|
var host = createChipHost(data);
|
|
47
53
|
range.insertNode(host);
|
|
54
|
+
attachCaretSpacerAfter(host);
|
|
55
|
+
normalizeComposerEditorDom(editor);
|
|
48
56
|
var next = [].concat(_toConsumableArray(chipsRef.current), [{
|
|
49
57
|
data: data,
|
|
50
58
|
host: host
|
|
@@ -53,26 +61,33 @@ onAfterMutate) {
|
|
|
53
61
|
setChips(next);
|
|
54
62
|
return host;
|
|
55
63
|
}, []);
|
|
56
|
-
var insertChip = useCallback(function (data, editor) {
|
|
64
|
+
var insertChip = useCallback(function (data, editor, preferredRange) {
|
|
57
65
|
var sel = window.getSelection();
|
|
58
66
|
var range = null;
|
|
59
|
-
if (
|
|
67
|
+
if (preferredRange && preferredRange.startContainer.isConnected && preferredRange.endContainer.isConnected && editor.contains(preferredRange.startContainer) && editor.contains(preferredRange.endContainer)) {
|
|
68
|
+
range = preferredRange.cloneRange();
|
|
69
|
+
} else if (sel && sel.rangeCount > 0 && editor.contains(sel.anchorNode)) {
|
|
60
70
|
range = sel.getRangeAt(0);
|
|
61
71
|
} else {
|
|
62
|
-
var _sel, _sel2;
|
|
63
72
|
editor.focus();
|
|
64
73
|
range = document.createRange();
|
|
65
74
|
range.selectNodeContents(editor);
|
|
66
75
|
range.collapse(false);
|
|
67
|
-
sel = window.getSelection();
|
|
68
|
-
(_sel = sel) === null || _sel === void 0 || _sel.removeAllRanges();
|
|
69
|
-
(_sel2 = sel) === null || _sel2 === void 0 || _sel2.addRange(range);
|
|
70
76
|
}
|
|
77
|
+
sel = window.getSelection();
|
|
71
78
|
if (!range || !sel) return;
|
|
79
|
+
sel.removeAllRanges();
|
|
80
|
+
sel.addRange(range);
|
|
72
81
|
range.deleteContents();
|
|
73
82
|
var host = insertChipAtRange(data, range, editor);
|
|
83
|
+
var spacer = host.nextSibling;
|
|
74
84
|
var newRange = document.createRange();
|
|
75
|
-
|
|
85
|
+
if ((spacer === null || spacer === void 0 ? void 0 : spacer.nodeType) === Node.TEXT_NODE && (spacer.textContent === CARET_SPACER || spacer.textContent === ZWSP)) {
|
|
86
|
+
newRange.setStart(spacer, 1);
|
|
87
|
+
} else {
|
|
88
|
+
var ensured = attachCaretSpacerAfter(host);
|
|
89
|
+
newRange.setStart(ensured, 1);
|
|
90
|
+
}
|
|
76
91
|
newRange.collapse(true);
|
|
77
92
|
sel.removeAllRanges();
|
|
78
93
|
sel.addRange(newRange);
|
|
@@ -96,6 +111,7 @@ onAfterMutate) {
|
|
|
96
111
|
if (!data) return;
|
|
97
112
|
var host = createChipHost(data);
|
|
98
113
|
frag.appendChild(host);
|
|
114
|
+
frag.appendChild(document.createTextNode(CARET_SPACER));
|
|
99
115
|
inserted.push({
|
|
100
116
|
data: data,
|
|
101
117
|
host: host
|
|
@@ -103,6 +119,7 @@ onAfterMutate) {
|
|
|
103
119
|
});
|
|
104
120
|
range.insertNode(frag);
|
|
105
121
|
range.collapse(false);
|
|
122
|
+
normalizeComposerEditorDom(editor);
|
|
106
123
|
if (inserted.length > 0) {
|
|
107
124
|
var next = [].concat(_toConsumableArray(chipsRef.current), inserted);
|
|
108
125
|
chipsRef.current = next;
|
|
@@ -133,14 +150,90 @@ onAfterMutate) {
|
|
|
133
150
|
return c.data.id === id;
|
|
134
151
|
});
|
|
135
152
|
if (!target) return;
|
|
153
|
+
var editor = target.host.parentElement;
|
|
154
|
+
var parent = target.host.parentNode;
|
|
155
|
+
var hostIndexInParent = parent ? Array.prototype.indexOf.call(parent.childNodes, target.host) : -1;
|
|
156
|
+
|
|
157
|
+
// 主锚点:chip 左侧文本尾(跳过尾部 ZWSP)
|
|
158
|
+
var prev = target.host.previousSibling;
|
|
159
|
+
var textAnchor = prev && prev.nodeType === Node.TEXT_NODE ? function (_prev$textContent) {
|
|
160
|
+
var raw = (_prev$textContent = prev.textContent) !== null && _prev$textContent !== void 0 ? _prev$textContent : '';
|
|
161
|
+
var len = raw.length;
|
|
162
|
+
while (len > 0 && (raw[len - 1] === CARET_SPACER || raw[len - 1] === ZWSP)) len--;
|
|
163
|
+
return {
|
|
164
|
+
node: prev,
|
|
165
|
+
offset: len
|
|
166
|
+
};
|
|
167
|
+
}() : null;
|
|
168
|
+
|
|
169
|
+
// 结构锚点:chip 在父节点中的原位置(删后即为“被删 chip 左侧”)
|
|
170
|
+
var treeAnchor = parent && hostIndexInParent >= 0 ? {
|
|
171
|
+
parent: parent,
|
|
172
|
+
offset: hostIndexInParent
|
|
173
|
+
} : null;
|
|
174
|
+
detachCaretSpacerAfter(target.host);
|
|
136
175
|
target.host.remove();
|
|
176
|
+
if (editor instanceof HTMLElement) {
|
|
177
|
+
normalizeComposerEditorDom(editor);
|
|
178
|
+
}
|
|
137
179
|
var next = chipsRef.current.filter(function (c) {
|
|
138
180
|
return c.data.id !== id;
|
|
139
181
|
});
|
|
140
182
|
chipsRef.current = next;
|
|
141
183
|
setChips(next);
|
|
142
184
|
onAfterMutate === null || onAfterMutate === void 0 || onAfterMutate();
|
|
185
|
+
|
|
186
|
+
// 关键:在 onAfterMutate(含 fireChange/normalizeEditorDom)之后再恢复 selection
|
|
187
|
+
requestAnimationFrame(function () {
|
|
188
|
+
var _treeAnchor$parent;
|
|
189
|
+
var sel = window.getSelection();
|
|
190
|
+
if (!sel) return;
|
|
191
|
+
var applyAnchor = function applyAnchor(anchor) {
|
|
192
|
+
var _anchor$node$textCont;
|
|
193
|
+
if (!anchor || !anchor.node.isConnected) return false;
|
|
194
|
+
var r = document.createRange();
|
|
195
|
+
var safeOffset = anchor.node.nodeType === Node.TEXT_NODE ? Math.min(anchor.offset, ((_anchor$node$textCont = anchor.node.textContent) !== null && _anchor$node$textCont !== void 0 ? _anchor$node$textCont : '').length) : Math.min(anchor.offset, anchor.node.childNodes.length);
|
|
196
|
+
r.setStart(anchor.node, safeOffset);
|
|
197
|
+
r.collapse(true);
|
|
198
|
+
sel.removeAllRanges();
|
|
199
|
+
sel.addRange(r);
|
|
200
|
+
return true;
|
|
201
|
+
};
|
|
202
|
+
if (applyAnchor(textAnchor)) return;
|
|
203
|
+
if (treeAnchor !== null && treeAnchor !== void 0 && (_treeAnchor$parent = treeAnchor.parent) !== null && _treeAnchor$parent !== void 0 && _treeAnchor$parent.isConnected) {
|
|
204
|
+
var textTreeAnchor = ensureTextAnchorAt(treeAnchor.parent, treeAnchor.offset);
|
|
205
|
+
if (applyAnchor(textTreeAnchor)) return;
|
|
206
|
+
}
|
|
207
|
+
if (editor instanceof HTMLElement) {
|
|
208
|
+
var fallback = ensureTextAnchorAt(editor, 0);
|
|
209
|
+
if (fallback && applyAnchor(fallback)) return;
|
|
210
|
+
var r = document.createRange();
|
|
211
|
+
r.selectNodeContents(editor);
|
|
212
|
+
r.collapse(true);
|
|
213
|
+
sel.removeAllRanges();
|
|
214
|
+
sel.addRange(r);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}, [onAfterMutate]);
|
|
218
|
+
var updateChipData = useCallback(function (id, patch) {
|
|
219
|
+
var idx = chipsRef.current.findIndex(function (c) {
|
|
220
|
+
return c.data.id === id;
|
|
221
|
+
});
|
|
222
|
+
if (idx === -1) return;
|
|
223
|
+
var next = _toConsumableArray(chipsRef.current);
|
|
224
|
+
next[idx] = _objectSpread(_objectSpread({}, next[idx]), {}, {
|
|
225
|
+
data: _objectSpread(_objectSpread({}, next[idx].data), patch)
|
|
226
|
+
});
|
|
227
|
+
chipsRef.current = next;
|
|
228
|
+
setChips(next);
|
|
229
|
+
onAfterMutate === null || onAfterMutate === void 0 || onAfterMutate();
|
|
143
230
|
}, [onAfterMutate]);
|
|
231
|
+
var getChipHost = useCallback(function (id) {
|
|
232
|
+
var _chipsRef$current$fin, _chipsRef$current$fin2;
|
|
233
|
+
return (_chipsRef$current$fin = (_chipsRef$current$fin2 = chipsRef.current.find(function (c) {
|
|
234
|
+
return c.data.id === id;
|
|
235
|
+
})) === null || _chipsRef$current$fin2 === void 0 ? void 0 : _chipsRef$current$fin2.host) !== null && _chipsRef$current$fin !== void 0 ? _chipsRef$current$fin : null;
|
|
236
|
+
}, []);
|
|
144
237
|
var resetChips = useCallback(function () {
|
|
145
238
|
setChips([]);
|
|
146
239
|
chipsRef.current = [];
|
|
@@ -152,6 +245,8 @@ onAfterMutate) {
|
|
|
152
245
|
insertSerializedAtRange: insertSerializedAtRange,
|
|
153
246
|
syncChipsAfterDomMutation: syncChipsAfterDomMutation,
|
|
154
247
|
removeChip: removeChip,
|
|
248
|
+
updateChipData: updateChipData,
|
|
249
|
+
getChipHost: getChipHost,
|
|
155
250
|
resetChips: resetChips
|
|
156
251
|
};
|
|
157
252
|
}
|