one-design-next 0.0.122 → 0.0.123
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.
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import React from 'react';
|
|
20
20
|
import type { ChipData } from '../_genui-types';
|
|
21
|
+
import { type ComposerSkillHint } from './segments';
|
|
21
22
|
/** Composer editor 触发态对外信号——告诉父组件该弹浮层选 skill 了。 */
|
|
22
23
|
export interface ComposerEditorTriggerInfo {
|
|
23
24
|
/** 触发字符(@ 或 /) */
|
|
@@ -72,6 +73,16 @@ export interface ComposerEditorProps {
|
|
|
72
73
|
defaultValue?: string;
|
|
73
74
|
/** 值变化回调;参数是 raw string,含 marker。 */
|
|
74
75
|
onChange?: (value: string) => void;
|
|
76
|
+
/**
|
|
77
|
+
* 灰字(skill hint)命中状态变化回调:
|
|
78
|
+
* - 灰字出现(最后一个 chip 命中结构谓词)→ 传入命中的 chip / 文案
|
|
79
|
+
* - 灰字消失(后面有内容 / chip 被删 / hint 已关闭)→ 传入 null
|
|
80
|
+
*
|
|
81
|
+
* 只在状态**真的变化**时抛一次;与灰字渲染共用同一份判定(先落 DOM 再抛,
|
|
82
|
+
* 不会各自算一套)。判定成立但灰字被临时摘掉(IME 合成期)时不跟着抖。
|
|
83
|
+
* 挂载时会先同步一次当前状态(空内容即 null),业务侧不必自己猜初始值。
|
|
84
|
+
*/
|
|
85
|
+
onSkillHintChange?: (hint: ComposerSkillHint | null) => void;
|
|
75
86
|
/** 与 defaultValue / 首次受控 value 配套,把 marker 还原成 chip。 */
|
|
76
87
|
defaultChips?: ChipData[];
|
|
77
88
|
placeholder?: string;
|
package/dist/composer/editor.js
CHANGED
|
@@ -326,6 +326,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
326
326
|
defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
|
|
327
327
|
defaultChips = _ref.defaultChips,
|
|
328
328
|
onChange = _ref.onChange,
|
|
329
|
+
onSkillHintChange = _ref.onSkillHintChange,
|
|
329
330
|
placeholder = _ref.placeholder,
|
|
330
331
|
autoSize = _ref.autoSize,
|
|
331
332
|
onPressEnter = _ref.onPressEnter,
|
|
@@ -353,6 +354,9 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
353
354
|
var isComposingRef = useRef(false);
|
|
354
355
|
var onTriggerChangeRef = useRef(onTriggerChange);
|
|
355
356
|
onTriggerChangeRef.current = onTriggerChange;
|
|
357
|
+
/** 灰字状态回调走 ref:调用方常传内联函数,不能让 fireChange / 挂载同步因此反复重建 */
|
|
358
|
+
var onSkillHintChangeRef = useRef(onSkillHintChange);
|
|
359
|
+
onSkillHintChangeRef.current = onSkillHintChange;
|
|
356
360
|
var isControlled = valueProp !== undefined;
|
|
357
361
|
var minRows = (_autoSize$minRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.minRows) !== null && _autoSize$minRows !== void 0 ? _autoSize$minRows : 1;
|
|
358
362
|
var maxRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.maxRows;
|
|
@@ -587,6 +591,33 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
587
591
|
}
|
|
588
592
|
}, [removeHintNode]);
|
|
589
593
|
|
|
594
|
+
/* 灰字状态的**上一帧快照**:回调只在真的变化时抛一次。
|
|
595
|
+
* fireChange 每次输入都会跑,不去重的话业务侧会被同一条状态反复冲刷。
|
|
596
|
+
* `undefined` = 还没抛过(与「抛过 null」区分),保证挂载时一定会同步一次。 */
|
|
597
|
+
var lastSkillHintRef = useRef(undefined);
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* 把「灰字当前状态」通知给业务方(与 syncHintNode 同一份 target,保证同源)。
|
|
601
|
+
*
|
|
602
|
+
* 只在 chipId / refId / 文案任一变化时抛:同一条状态在连续输入里会算很多次。
|
|
603
|
+
*/
|
|
604
|
+
var notifySkillHint = useCallback(function (target, chips) {
|
|
605
|
+
var _chips$find, _onSkillHintChangeRef;
|
|
606
|
+
var next = target ? {
|
|
607
|
+
chipId: target.chipId,
|
|
608
|
+
text: target.text,
|
|
609
|
+
refId: (_chips$find = chips.find(function (chip) {
|
|
610
|
+
return chip.id === target.chipId;
|
|
611
|
+
})) === null || _chips$find === void 0 ? void 0 : _chips$find.refId
|
|
612
|
+
} : null;
|
|
613
|
+
var prev = lastSkillHintRef.current;
|
|
614
|
+
if (prev !== undefined && (prev === null || prev === void 0 ? void 0 : prev.chipId) === (next === null || next === void 0 ? void 0 : next.chipId) && (prev === null || prev === void 0 ? void 0 : prev.text) === (next === null || next === void 0 ? void 0 : next.text) && (prev === null || prev === void 0 ? void 0 : prev.refId) === (next === null || next === void 0 ? void 0 : next.refId)) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
lastSkillHintRef.current = next;
|
|
618
|
+
(_onSkillHintChangeRef = onSkillHintChangeRef.current) === null || _onSkillHintChangeRef === void 0 || _onSkillHintChangeRef.call(onSkillHintChangeRef, next);
|
|
619
|
+
}, []);
|
|
620
|
+
|
|
590
621
|
/** 把 caret 直接落到 hint 之前(= chip 右侧);没有 hint 时不动。 */
|
|
591
622
|
var placeCaretBeforeHint = useCallback(function () {
|
|
592
623
|
var el = editorRef.current;
|
|
@@ -627,7 +658,12 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
627
658
|
* 否则「chip 被删」时残留的 hint 文本会让 placeholder 判定与 lite 升格
|
|
628
659
|
* 判定晚一拍。 */
|
|
629
660
|
closeChipHintsRef.current(resolveHintClosedChipIds(raw, chips));
|
|
630
|
-
|
|
661
|
+
/* 关闭会改写 chips 快照,谓词必须用关闭后的快照重新取;
|
|
662
|
+
* 渲染(syncHintNode)与对外回调(notifySkillHint)共用这一份 target,
|
|
663
|
+
* 业务拿到的是「这一刻灰字该不该在」的同一份判定,不会各算一套。 */
|
|
664
|
+
var hintChips = getChipsRef.current();
|
|
665
|
+
var hintTarget = resolveHintTarget(raw, hintChips);
|
|
666
|
+
syncHintNode(hintTarget);
|
|
631
667
|
var showPlaceholder = shouldShowPlaceholder(el);
|
|
632
668
|
if (forceNonEmptyOnceRef.current && showPlaceholder) {
|
|
633
669
|
setEmpty(false);
|
|
@@ -640,7 +676,23 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
640
676
|
scheduleControlledSync();
|
|
641
677
|
// editor.height 锁定时 RO 不触发,主动同步一次,确保升格判定能拿到 scrollHeight
|
|
642
678
|
syncHeight();
|
|
643
|
-
|
|
679
|
+
/* 对外回调放在所有内部状态更新之后:业务在里面同步 setState 甚至
|
|
680
|
+
* updateChipData 都不会插进「DOM 已落、caret / 高度还没收尾」的中间态。 */
|
|
681
|
+
notifySkillHint(hintTarget, hintChips);
|
|
682
|
+
}, [notifySkillHint, onChange, pullCaretBeforeHint, scheduleControlledSync, shouldShowPlaceholder, syncHeight, syncHintNode]);
|
|
683
|
+
|
|
684
|
+
/* 挂载时同步一次灰字状态。
|
|
685
|
+
*
|
|
686
|
+
* 带 chips 的草稿恢复已经在挂载的 layout effect 里走 fireChange 抛过一次,
|
|
687
|
+
* 这里兜的是「空内容 / 只有纯文本挂载」——否则业务侧上一轮留下的状态没人复位。
|
|
688
|
+
* 放在 passive effect:晚于 chips 还原,且 notifySkillHint 自带去重,
|
|
689
|
+
* 与 fireChange 那一次重复时不会再抛。 */
|
|
690
|
+
useEffect(function () {
|
|
691
|
+
var el = editorRef.current;
|
|
692
|
+
if (!el) return;
|
|
693
|
+
var hintChips = getChipsRef.current();
|
|
694
|
+
notifySkillHint(resolveHintTarget(getPlainText(el), hintChips), hintChips);
|
|
695
|
+
}, [notifySkillHint]);
|
|
644
696
|
|
|
645
697
|
/* ─────────────────────────────────────
|
|
646
698
|
* chip 管理
|
|
@@ -785,6 +837,10 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
785
837
|
onTriggerChange === null || onTriggerChange === void 0 || onTriggerChange(null);
|
|
786
838
|
}
|
|
787
839
|
onChange === null || onChange === void 0 || onChange('');
|
|
840
|
+
/* 这条路不走 fireChange(清空不是「内容变化」链路的一环),
|
|
841
|
+
* 灰字状态要在这里手动同步,否则业务侧会一直以为灰字还显示着。
|
|
842
|
+
* 位置放在 onChange 之后,与 fireChange 的「先 onChange 再灰字」一致。 */
|
|
843
|
+
notifySkillHint(null, []);
|
|
788
844
|
},
|
|
789
845
|
insertChip: function insertChip(data) {
|
|
790
846
|
var el = editorRef.current;
|
|
@@ -881,7 +937,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
881
937
|
return editorRef.current;
|
|
882
938
|
}
|
|
883
939
|
};
|
|
884
|
-
}, [onChange, _insertChip, insertSerializedAtRange, requestScrollCaretIntoView, removeChip, resetChips, onTriggerChange, getChips, updateChipData, getChipHost]);
|
|
940
|
+
}, [onChange, _insertChip, insertSerializedAtRange, notifySkillHint, requestScrollCaretIntoView, removeChip, resetChips, onTriggerChange, getChips, updateChipData, getChipHost]);
|
|
885
941
|
|
|
886
942
|
/* ─────────────────────────────────────
|
|
887
943
|
* 监听 selection 变化:方向键 / 鼠标点击移位都要重算 trigger
|
|
@@ -1037,6 +1093,8 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
1037
1093
|
}
|
|
1038
1094
|
removeHintNode();
|
|
1039
1095
|
resetChips();
|
|
1096
|
+
/* 同 clear():外部改写 value 不走 fireChange,灰字状态在这里手动同步 */
|
|
1097
|
+
notifySkillHint(null, []);
|
|
1040
1098
|
setEmpty(shouldShowPlaceholder(el));
|
|
1041
1099
|
if (triggerRef.current) {
|
|
1042
1100
|
var _onTriggerChangeRef$c;
|
|
@@ -1045,7 +1103,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
1045
1103
|
}
|
|
1046
1104
|
syncHeight();
|
|
1047
1105
|
}
|
|
1048
|
-
}, [controlledSyncTick, valueProp, isControlled, resetChips, shouldShowPlaceholder, syncHeight]);
|
|
1106
|
+
}, [controlledSyncTick, valueProp, isControlled, notifySkillHint, resetChips, shouldShowPlaceholder, syncHeight]);
|
|
1049
1107
|
|
|
1050
1108
|
/* ─────────────────────────────────────
|
|
1051
1109
|
* 输入事件
|
package/dist/composer/index.d.ts
CHANGED
|
@@ -4,9 +4,11 @@ import type { IconName } from '../icon';
|
|
|
4
4
|
import { type SkillSlotProps } from '../skill-slot';
|
|
5
5
|
import { type ComposerInsertOptions, type ComposerInsertPart, type ComposerInsertResult } from './insert';
|
|
6
6
|
import type { ComposerParamPanelContext } from './param-panel';
|
|
7
|
+
import { type ComposerSkillHint } from './segments';
|
|
7
8
|
import './style';
|
|
8
9
|
export type { ComposerInsertOptions, ComposerInsertPart, ComposerInsertResult, } from './insert';
|
|
9
10
|
export type { ComposerParamPanelContext } from './param-panel';
|
|
11
|
+
export type { ComposerHintTarget, ComposerSkillHint } from './segments';
|
|
10
12
|
export type ComposerTool = 'attachment' | 'webSearch' | 'skill';
|
|
11
13
|
export type ComposerVariant = 'full' | 'lite';
|
|
12
14
|
export type SubmitType = 'enter' | 'shiftEnter';
|
|
@@ -105,6 +107,22 @@ export interface ComposerProps {
|
|
|
105
107
|
defaultChips?: ChipData[];
|
|
106
108
|
/** 输入框值变化回调。第二参是当前 chip 快照,旧调用方忽略即可。 */
|
|
107
109
|
onChange?: (value: string, chips?: ChipData[]) => void;
|
|
110
|
+
/**
|
|
111
|
+
* 技能灰字(`SkillItem.hint`)的出现 / 消失回调。
|
|
112
|
+
*
|
|
113
|
+
* 入参与输入框里那行灰字共用**同一份判定**(`resolveHintTarget`):命中时给
|
|
114
|
+
* `{ chipId, text, refId }`,消失时给 `null`。因此业务不需要自己解析
|
|
115
|
+
* value / chips,也不会出现「库里觉得有、业务觉得没有」的分歧。
|
|
116
|
+
*
|
|
117
|
+
* 语义要点:
|
|
118
|
+
* - 只在状态真的变化时抛一次,同一条状态不会因为连续输入重复抛;
|
|
119
|
+
* - 判定成立但灰字被临时摘掉(IME 合成期避开候选串)时不跟着抖;
|
|
120
|
+
* - 挂载时先同步一次当前状态(首屏没有灰字即 `null`),便于业务复位上一轮状态;
|
|
121
|
+
* - 灰字一次性:收起后即使把内容删回空串也不会再抛命中;
|
|
122
|
+
* - 卸载不会再补一次 `null`:需要清理时由业务在自己的卸载路径处理;
|
|
123
|
+
* - 与 `hint`(底部快捷键提示开关)无关。
|
|
124
|
+
*/
|
|
125
|
+
onSkillHintChange?: (hint: ComposerSkillHint | null) => void;
|
|
108
126
|
/**
|
|
109
127
|
* 发送回调。
|
|
110
128
|
*
|
package/dist/composer/index.js
CHANGED
|
@@ -94,6 +94,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
94
94
|
defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
|
|
95
95
|
defaultChips = _ref.defaultChips,
|
|
96
96
|
onChangeProp = _ref.onChange,
|
|
97
|
+
onSkillHintChange = _ref.onSkillHintChange,
|
|
97
98
|
onSend = _ref.onSend,
|
|
98
99
|
onStop = _ref.onStop,
|
|
99
100
|
_ref$isGenerating = _ref.isGenerating,
|
|
@@ -1235,6 +1236,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
1235
1236
|
value: text,
|
|
1236
1237
|
defaultChips: defaultChips,
|
|
1237
1238
|
onChange: updateText,
|
|
1239
|
+
onSkillHintChange: onSkillHintChange,
|
|
1238
1240
|
disabled: disabled,
|
|
1239
1241
|
paramEditChipId: (_paramEdit$chipId = paramEdit === null || paramEdit === void 0 ? void 0 : paramEdit.chipId) !== null && _paramEdit$chipId !== void 0 ? _paramEdit$chipId : null,
|
|
1240
1242
|
onInlineRefClick: renderParamPanel ? handleInlineRefClick : undefined
|
|
@@ -29,6 +29,17 @@ export interface ComposerHintTarget {
|
|
|
29
29
|
/** 提示文本(skill 模板文案,发送时原样作为 hint 段的 data.text) */
|
|
30
30
|
text: string;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 灰字当前状态的对外快照(`ComposerProps.onSkillHintChange` 的入参)。
|
|
34
|
+
*
|
|
35
|
+
* 在 `ComposerHintTarget` 基础上补 chip 的业务标识:业务拿到回调时通常只想
|
|
36
|
+
* 知道「哪一块技能正在展示灰字」,不必再去 onChange 的 chips 快照里反查——
|
|
37
|
+
* 尤其 chip 插入与注册是两条异步链路,反查可能还没就绪。
|
|
38
|
+
*/
|
|
39
|
+
export interface ComposerSkillHint extends ComposerHintTarget {
|
|
40
|
+
/** 命中 chip 的业务侧资源 id(`ChipData.refId`,skill chip 即 `SkillItem.id`);自定义 chip 可能没有 */
|
|
41
|
+
refId?: string;
|
|
42
|
+
}
|
|
32
43
|
/**
|
|
33
44
|
* 判定当前内容是否命中 hint:
|
|
34
45
|
* 1. `value` 里存在 marker(即至少有一个 chip)
|
|
@@ -61,6 +61,14 @@ export var isHintSegment = function isHintSegment(s) {
|
|
|
61
61
|
|
|
62
62
|
/** hint 命中结果。 */
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* 灰字当前状态的对外快照(`ComposerProps.onSkillHintChange` 的入参)。
|
|
66
|
+
*
|
|
67
|
+
* 在 `ComposerHintTarget` 基础上补 chip 的业务标识:业务拿到回调时通常只想
|
|
68
|
+
* 知道「哪一块技能正在展示灰字」,不必再去 onChange 的 chips 快照里反查——
|
|
69
|
+
* 尤其 chip 插入与注册是两条异步链路,反查可能还没就绪。
|
|
70
|
+
*/
|
|
71
|
+
|
|
64
72
|
/**
|
|
65
73
|
* 最后一个 marker 的 chip id 与它之后的尾串;没有 chip 时返回 null。
|
|
66
74
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -83,4 +83,4 @@ export { default as Welcome, type WelcomeProps } from './welcome';
|
|
|
83
83
|
export { ComposerSegmentType } from './_genui-types';
|
|
84
84
|
export type { AgentEvent, Attachment, ChatMessage, ChipData, ComposerHintSegment, ComposerInvocationSegment, ComposerMentionSegment, ComposerSegment, ComposerTextSegment, Conversation, HintData, InlineRefState, InvocationData, MentionData, MessageSnapshot, PreviewTab, PreviewTarget, SendMeta, SkillItem, Source, TextData, ToolCall, ToolStatus, } from './_genui-types';
|
|
85
85
|
export type { InterruptBase, InterruptIntent, InterruptStatus, } from './_interrupt-types';
|
|
86
|
-
export { isHintSegment, isInvocationSegment, isMentionSegment, isTextSegment, rawValueToSegments, resolveHintTarget, segmentsHasContent, segmentsToReadableText, type ComposerHintTarget, type SegmentsToReadableTextOptions, } from './composer/segments';
|
|
86
|
+
export { isHintSegment, isInvocationSegment, isMentionSegment, isTextSegment, rawValueToSegments, resolveHintTarget, segmentsHasContent, segmentsToReadableText, type ComposerHintTarget, type ComposerSkillHint, type SegmentsToReadableTextOptions, } from './composer/segments';
|