one-design-next 0.0.48 → 0.0.50

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.
@@ -0,0 +1,795 @@
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); }
7
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
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."); }
9
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
10
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
11
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
12
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
13
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(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(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+ function _arrayLikeToArray(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; }
15
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
16
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
+ import * as React from 'react';
18
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
19
+ import Button from "../button";
20
+ import DatePicker from "../date-picker";
21
+ import DateRangePicker from "../date-range-picker";
22
+ import HoverFill from "../hover-fill";
23
+ import Icon from "../icon";
24
+ import Input from "../input";
25
+ import Pagination from "../pagination";
26
+ import { toISODate } from "./types";
27
+ import "./style";
28
+
29
+ /* ------------------------------------------------------------------ */
30
+ /* ClarifyDock */
31
+ /* ------------------------------------------------------------------ */
32
+ /*
33
+ * 真实形态:Trigger 在 AI 消息正文里,Panel 通过 Host 的 dock slot 吸附在
34
+ * Composer 上方——而不是 Trigger + Panel 同框。
35
+ *
36
+ * 导出三件套:
37
+ * - <ClarifyDockTrigger />:Approval 式锁态卡(折叠 + 展开题→答)
38
+ * - <ClarifyDockPanel />:多题分页 form 面板
39
+ * - useClarifyDockState(messages):派生 pending / answered
40
+ *
41
+ * 多题节奏:一次只问一题;底栏左 Pagination simple(仅页码),右「上一题 / 下一题|确认」。
42
+ * 全部必答。单选 / 多选末项「其他」由 allowOther 注入。
43
+ */
44
+
45
+ /** 整卷提交:自然语言摘要 + 结构化 data + 锁态小票行。 */
46
+
47
+ /** Host 消息最小形状——hook 只认 assistant + clarify-dock instance。 */
48
+
49
+ /* ================================================================== */
50
+ /* Trigger · Approval 式锁态卡(折叠默认 + 展开题→答) */
51
+ /* ================================================================== */
52
+
53
+ /** 题面「?」→「:」后与答案拼成一行,如「需要拆解哪些维度:素材」。 */
54
+ function formatLockedLine(label, answer) {
55
+ var stem = label.replace(/[??]\s*$/, '');
56
+ return "".concat(stem, "\uFF1A").concat(answer);
57
+ }
58
+ export function ClarifyDockTrigger(_ref) {
59
+ var items = _ref.items;
60
+ var _useState = useState(false),
61
+ _useState2 = _slicedToArray(_useState, 2),
62
+ expanded = _useState2[0],
63
+ setExpanded = _useState2[1];
64
+ /* 收合动画结束后再卸掉 panel 占位(对齐 Approval summaryCollapsedSettled) */
65
+ var _useState3 = useState(true),
66
+ _useState4 = _slicedToArray(_useState3, 2),
67
+ collapsedSettled = _useState4[0],
68
+ setCollapsedSettled = _useState4[1];
69
+ useEffect(function () {
70
+ if (expanded) {
71
+ setCollapsedSettled(false);
72
+ return;
73
+ }
74
+ var id = window.setTimeout(function () {
75
+ return setCollapsedSettled(true);
76
+ }, 230);
77
+ return function () {
78
+ return window.clearTimeout(id);
79
+ };
80
+ }, [expanded]);
81
+ if (!items || items.length === 0) return null;
82
+ var multi = items.length > 1;
83
+ var mainLabel = multi ? "\u5DF2\u786E\u8BA4 ".concat(items.length, " \u9898") : formatLockedLine(items[0].label, items[0].answer);
84
+ var handleToggle = function handleToggle() {
85
+ if (expanded) {
86
+ setExpanded(false);
87
+ return;
88
+ }
89
+ setCollapsedSettled(false);
90
+ requestAnimationFrame(function () {
91
+ return setExpanded(true);
92
+ });
93
+ };
94
+ return /*#__PURE__*/React.createElement("div", {
95
+ "data-odn-clarify-dock-locked": true,
96
+ "data-resolved": true,
97
+ "data-summary-expanded": expanded ? '' : undefined
98
+ }, /*#__PURE__*/React.createElement("div", {
99
+ "data-odn-clarify-dock-locked-body": true
100
+ }, /*#__PURE__*/React.createElement("div", {
101
+ "data-odn-clarify-dock-locked-heading": true
102
+ }, /*#__PURE__*/React.createElement("div", {
103
+ "data-odn-clarify-dock-locked-title-row": true
104
+ }, /*#__PURE__*/React.createElement("p", {
105
+ "data-odn-clarify-dock-locked-text": true
106
+ }, /*#__PURE__*/React.createElement(Icon, {
107
+ name: "check",
108
+ size: 14,
109
+ "data-odn-clarify-dock-locked-icon": true
110
+ }), /*#__PURE__*/React.createElement("span", {
111
+ "data-odn-clarify-dock-locked-main": true
112
+ }, mainLabel)), multi ? /*#__PURE__*/React.createElement("button", {
113
+ type: "button",
114
+ "data-odn-clarify-dock-locked-toggle": true,
115
+ "aria-expanded": expanded,
116
+ onClick: handleToggle
117
+ }, /*#__PURE__*/React.createElement("span", null, expanded ? '收起' : '展开'), /*#__PURE__*/React.createElement(Icon, {
118
+ name: "chevron-down",
119
+ size: 14,
120
+ "data-odn-clarify-dock-locked-chevron": true
121
+ })) : null)), multi ? /*#__PURE__*/React.createElement("div", {
122
+ "data-odn-clarify-dock-locked-panel": true,
123
+ "data-open": expanded ? 'true' : 'false',
124
+ "data-collapsed-settled": collapsedSettled ? '' : undefined,
125
+ "aria-hidden": !expanded
126
+ }, /*#__PURE__*/React.createElement("div", {
127
+ "data-odn-clarify-dock-locked-panel-inner": true
128
+ }, /*#__PURE__*/React.createElement("div", {
129
+ "data-odn-clarify-dock-locked-receipt": true
130
+ }, items.map(function (item) {
131
+ return /*#__PURE__*/React.createElement("p", {
132
+ key: item.key,
133
+ "data-odn-clarify-dock-locked-line": true
134
+ }, formatLockedLine(item.label, item.answer));
135
+ })))) : null));
136
+ }
137
+
138
+ /* ================================================================== */
139
+ /* Panel · 多题分页 */
140
+ /* ================================================================== */
141
+
142
+ /** 单题暂存答案。 */
143
+
144
+ var OTHER_VALUE = '__other__';
145
+
146
+ /** 多选已选 8% 底上的 hover 增量(叠后约 12% brand)——供 HoverFill 位移层使用 */
147
+ var MULTI_SELECTED_HOVER_FILL = 'rgba(41, 107, 239, 0.04)';
148
+ var MULTI_UNSELECTED_HOVER_FILL = 'rgba(33, 34, 38, 0.05)';
149
+ var MULTI_UNSELECTED_ACTIVE_FILL = 'rgba(33, 34, 38, 0.08)';
150
+
151
+ /**
152
+ * 单题选项上限(含「其他」),与 A–E 徽标一一对应。
153
+ * 超过时截断业务选项,优先保留末位「其他」。
154
+ */
155
+ export var CLARIFY_DOCK_MAX_OPTIONS = 5;
156
+ var LETTER_BADGES = ['A', 'B', 'C', 'D', 'E'];
157
+ export function ClarifyDockPanel(_ref2) {
158
+ var msgId = _ref2.msgId,
159
+ spec = _ref2.spec,
160
+ onResolve = _ref2.onResolve;
161
+ var total = spec.questions.length;
162
+ var _useState5 = useState(0),
163
+ _useState6 = _slicedToArray(_useState5, 2),
164
+ page = _useState6[0],
165
+ setPage = _useState6[1];
166
+ var _useState7 = useState(function () {
167
+ return new Array(total).fill(undefined);
168
+ }),
169
+ _useState8 = _slicedToArray(_useState7, 2),
170
+ answers = _useState8[0],
171
+ setAnswers = _useState8[1];
172
+ var _useState9 = useState(''),
173
+ _useState10 = _slicedToArray(_useState9, 2),
174
+ otherDraft = _useState10[0],
175
+ setOtherDraft = _useState10[1];
176
+ var _useState11 = useState(null),
177
+ _useState12 = _slicedToArray(_useState11, 2),
178
+ dateDraft = _useState12[0],
179
+ setDateDraft = _useState12[1];
180
+ var _useState13 = useState(null),
181
+ _useState14 = _slicedToArray(_useState13, 2),
182
+ dateRangeDraft = _useState14[0],
183
+ setDateRangeDraft = _useState14[1];
184
+ var question = spec.questions[page];
185
+ var answer = answers[page];
186
+ var input = question.input;
187
+
188
+ /* 切页:回显 other / date / date-range 草稿 */
189
+ useEffect(function () {
190
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options' || (answer === null || answer === void 0 ? void 0 : answer.kind) === 'options-multi') {
191
+ var _answer$otherText;
192
+ setOtherDraft((_answer$otherText = answer.otherText) !== null && _answer$otherText !== void 0 ? _answer$otherText : '');
193
+ } else {
194
+ setOtherDraft('');
195
+ }
196
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'date') {
197
+ setDateDraft(answer.value ? new Date("".concat(answer.value, "T00:00:00")) : null);
198
+ } else {
199
+ setDateDraft(null);
200
+ }
201
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'date-range') {
202
+ setDateRangeDraft(answer.start && answer.end ? [new Date("".concat(answer.start, "T00:00:00")), new Date("".concat(answer.end, "T00:00:00"))] : null);
203
+ } else {
204
+ setDateRangeDraft(null);
205
+ }
206
+ }, [page, answer]);
207
+ var setAnswerForPage = function setAnswerForPage(next) {
208
+ setAnswers(function (prev) {
209
+ var copy = _toConsumableArray(prev);
210
+ copy[page] = next;
211
+ return copy;
212
+ });
213
+ };
214
+ var canAdvance = useMemo(function () {
215
+ if (!answer) return false;
216
+ switch (answer.kind) {
217
+ case 'options':
218
+ if (answer.value === OTHER_VALUE) return otherDraft.trim().length > 0;
219
+ return true;
220
+ case 'options-multi':
221
+ {
222
+ var hasRegular = answer.values.some(function (v) {
223
+ return v !== OTHER_VALUE;
224
+ });
225
+ var hasOther = answer.values.includes(OTHER_VALUE);
226
+ if (hasOther && otherDraft.trim().length === 0) return false;
227
+ return hasRegular || hasOther;
228
+ }
229
+ case 'date':
230
+ return answer.value.trim().length > 0;
231
+ case 'date-range':
232
+ return answer.start.trim().length > 0 && answer.end.trim().length > 0;
233
+ default:
234
+ return false;
235
+ }
236
+ }, [answer, otherDraft]);
237
+ var isLastPage = page === total - 1;
238
+ var isFirstPage = page === 0;
239
+ var formatAnswer = function formatAnswer(q, ans) {
240
+ if (!ans) return '(未答)';
241
+ switch (ans.kind) {
242
+ case 'options':
243
+ {
244
+ var _ans$otherText;
245
+ if (ans.value === OTHER_VALUE) return (_ans$otherText = ans.otherText) !== null && _ans$otherText !== void 0 ? _ans$otherText : '其他';
246
+ if (q.input.kind === 'options') {
247
+ var _q$input$options$find, _q$input$options$find2;
248
+ return (_q$input$options$find = (_q$input$options$find2 = q.input.options.find(function (o) {
249
+ return o.value === ans.value;
250
+ })) === null || _q$input$options$find2 === void 0 ? void 0 : _q$input$options$find2.label) !== null && _q$input$options$find !== void 0 ? _q$input$options$find : ans.value;
251
+ }
252
+ return ans.value;
253
+ }
254
+ case 'options-multi':
255
+ {
256
+ if (q.input.kind !== 'options-multi') return ans.values.join('、');
257
+ var opts = q.input.options;
258
+ var labels = ans.values.filter(function (v) {
259
+ return v !== OTHER_VALUE;
260
+ }).map(function (v) {
261
+ var _opts$find$label, _opts$find;
262
+ return (_opts$find$label = (_opts$find = opts.find(function (o) {
263
+ return o.value === v;
264
+ })) === null || _opts$find === void 0 ? void 0 : _opts$find.label) !== null && _opts$find$label !== void 0 ? _opts$find$label : v;
265
+ });
266
+ if (ans.values.includes(OTHER_VALUE) && ans.otherText) {
267
+ labels.push(ans.otherText);
268
+ }
269
+ return labels.join('、');
270
+ }
271
+ case 'date':
272
+ return ans.value;
273
+ case 'date-range':
274
+ return "".concat(ans.start, " \u81F3 ").concat(ans.end);
275
+ default:
276
+ return '(未答)';
277
+ }
278
+ };
279
+ var syncCurrentDraftIntoAnswers = function syncCurrentDraftIntoAnswers() {
280
+ return answers.map(function (a, i) {
281
+ if (i !== page || !a) return a;
282
+ if (a.kind === 'options' && a.value === OTHER_VALUE) {
283
+ return _objectSpread(_objectSpread({}, a), {}, {
284
+ otherText: otherDraft
285
+ });
286
+ }
287
+ if (a.kind === 'options-multi' && a.values.includes(OTHER_VALUE)) {
288
+ return _objectSpread(_objectSpread({}, a), {}, {
289
+ otherText: otherDraft
290
+ });
291
+ }
292
+ if (a.kind === 'date' && dateDraft) {
293
+ return {
294
+ kind: 'date',
295
+ value: toISODate(dateDraft)
296
+ };
297
+ }
298
+ if (a.kind === 'date-range' && dateRangeDraft) {
299
+ return {
300
+ kind: 'date-range',
301
+ start: toISODate(dateRangeDraft[0]),
302
+ end: toISODate(dateRangeDraft[1])
303
+ };
304
+ }
305
+ return a;
306
+ });
307
+ };
308
+ var submit = function submit(finalAnswers) {
309
+ var data = {};
310
+ spec.questions.forEach(function (q, i) {
311
+ var _a$otherText;
312
+ var a = finalAnswers[i];
313
+ if (!a) return;
314
+ switch (a.kind) {
315
+ case 'options':
316
+ data[q.key] = a.value === OTHER_VALUE ? ((_a$otherText = a.otherText) !== null && _a$otherText !== void 0 ? _a$otherText : otherDraft).trim() : a.value;
317
+ break;
318
+ case 'options-multi':
319
+ {
320
+ var values = a.values.filter(function (v) {
321
+ return v !== OTHER_VALUE;
322
+ });
323
+ if (a.values.includes(OTHER_VALUE)) {
324
+ var _a$otherText2;
325
+ var t = ((_a$otherText2 = a.otherText) !== null && _a$otherText2 !== void 0 ? _a$otherText2 : otherDraft).trim();
326
+ if (t) values.push(t);
327
+ }
328
+ data[q.key] = values;
329
+ break;
330
+ }
331
+ case 'date':
332
+ data[q.key] = a.value;
333
+ break;
334
+ case 'date-range':
335
+ data[q.key] = "".concat(a.start, "~").concat(a.end);
336
+ break;
337
+ }
338
+ });
339
+ var items = spec.questions.map(function (q, i) {
340
+ return {
341
+ key: q.key,
342
+ label: q.label,
343
+ answer: formatAnswer(q, finalAnswers[i])
344
+ };
345
+ });
346
+ var text = items.map(function (it) {
347
+ return formatLockedLine(it.label, it.answer);
348
+ }).join(';');
349
+ onResolve({
350
+ text: text,
351
+ data: data,
352
+ items: items
353
+ });
354
+ };
355
+ var handleContinue = function handleContinue() {
356
+ if (!canAdvance) return;
357
+ var synced = syncCurrentDraftIntoAnswers();
358
+ setAnswers(synced);
359
+ if (isLastPage) submit(synced);else setPage(function (p) {
360
+ return Math.min(p + 1, total - 1);
361
+ });
362
+ };
363
+ var handlePrev = function handlePrev() {
364
+ if (isFirstPage) return;
365
+ var synced = syncCurrentDraftIntoAnswers();
366
+ setAnswers(synced);
367
+ setPage(function (p) {
368
+ return Math.max(0, p - 1);
369
+ });
370
+ };
371
+ return /*#__PURE__*/React.createElement("div", {
372
+ "data-odn-clarify-dock": true,
373
+ "data-odn-clarify-msg-id": msgId,
374
+ "aria-label": "\u6F84\u6E05\u95EE\u9898 ".concat(page + 1, " / ").concat(total)
375
+ }, /*#__PURE__*/React.createElement("div", {
376
+ "data-odn-clarify-dock-body": true
377
+ }, spec.title ? /*#__PURE__*/React.createElement("div", {
378
+ "data-odn-clarify-dock-heading": true
379
+ }, /*#__PURE__*/React.createElement("div", {
380
+ "data-odn-clarify-dock-title-row": true
381
+ }, /*#__PURE__*/React.createElement("p", {
382
+ "data-odn-clarify-dock-title": true
383
+ }, spec.title))) : null, /*#__PURE__*/React.createElement("div", {
384
+ "data-odn-clarify-dock-content": true
385
+ }, /*#__PURE__*/React.createElement("div", {
386
+ "data-odn-clarify-dock-q-row": true
387
+ }, /*#__PURE__*/React.createElement("div", {
388
+ "data-odn-clarify-dock-q": true
389
+ }, question.label), input.kind === 'options' ? /*#__PURE__*/React.createElement("span", {
390
+ "data-odn-clarify-dock-q-hint": true
391
+ }, "\u5355\u9009") : input.kind === 'options-multi' ? /*#__PURE__*/React.createElement("span", {
392
+ "data-odn-clarify-dock-q-hint": true
393
+ }, "\u53EF\u591A\u9009") : null), /*#__PURE__*/React.createElement(QuestionInput, {
394
+ input: input,
395
+ answer: answer,
396
+ otherDraft: otherDraft,
397
+ dateDraft: dateDraft,
398
+ dateRangeDraft: dateRangeDraft,
399
+ onOtherDraftChange: function onOtherDraftChange(v) {
400
+ setOtherDraft(v);
401
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options' && answer.value === OTHER_VALUE) {
402
+ setAnswerForPage({
403
+ kind: 'options',
404
+ value: OTHER_VALUE,
405
+ otherText: v
406
+ });
407
+ } else if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options-multi') {
408
+ setAnswerForPage({
409
+ kind: 'options-multi',
410
+ values: answer.values,
411
+ otherText: v
412
+ });
413
+ }
414
+ },
415
+ onDateChange: function onDateChange(d) {
416
+ setDateDraft(d);
417
+ setAnswerForPage(d ? {
418
+ kind: 'date',
419
+ value: toISODate(d)
420
+ } : undefined);
421
+ },
422
+ onDateRangeChange: function onDateRangeChange(range) {
423
+ setDateRangeDraft(range);
424
+ setAnswerForPage(range ? {
425
+ kind: 'date-range',
426
+ start: toISODate(range[0]),
427
+ end: toISODate(range[1])
428
+ } : undefined);
429
+ },
430
+ onPickSingle: function onPickSingle(opt) {
431
+ if (opt.value === OTHER_VALUE) {
432
+ setAnswerForPage({
433
+ kind: 'options',
434
+ value: OTHER_VALUE,
435
+ otherText: otherDraft
436
+ });
437
+ } else if (!((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options' && answer.value === opt.value)) {
438
+ setAnswerForPage({
439
+ kind: 'options',
440
+ value: opt.value
441
+ });
442
+ }
443
+ },
444
+ onToggleMulti: function onToggleMulti(opt) {
445
+ var prev = (answer === null || answer === void 0 ? void 0 : answer.kind) === 'options-multi' ? answer.values : [];
446
+ var has = prev.includes(opt.value);
447
+ var next = has ? prev.filter(function (v) {
448
+ return v !== opt.value;
449
+ }) : [].concat(_toConsumableArray(prev), [opt.value]);
450
+ setAnswerForPage({
451
+ kind: 'options-multi',
452
+ values: next,
453
+ otherText: otherDraft
454
+ });
455
+ }
456
+ }))), /*#__PURE__*/React.createElement("div", {
457
+ "data-odn-clarify-dock-actions": true
458
+ }, total > 1 ? /*#__PURE__*/React.createElement(Pagination, {
459
+ type: "simple",
460
+ value: page + 1,
461
+ totalSize: total,
462
+ pageSize: 1,
463
+ showPrevNext: false,
464
+ showFirstLast: false,
465
+ "data-odn-clarify-dock-page-indicator": true
466
+ }) : /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("div", {
467
+ "data-odn-clarify-dock-actions-right": true
468
+ }, !isFirstPage ? /*#__PURE__*/React.createElement(Button, {
469
+ size: "small",
470
+ intent: "normal",
471
+ onClick: handlePrev
472
+ }, "\u4E0A\u4E00\u9898") : null, /*#__PURE__*/React.createElement(Button, {
473
+ intent: "primary",
474
+ size: "small",
475
+ onClick: handleContinue,
476
+ disabled: !canAdvance,
477
+ "data-odn-clarify-dock-continue": true
478
+ }, isLastPage ? '确认' : '下一题'))));
479
+ }
480
+
481
+ /* ================================================================== */
482
+ /* 单题输入区 */
483
+ /* ================================================================== */
484
+
485
+ /**
486
+ * 组装选项列表并强制 ≤ CLARIFY_DOCK_MAX_OPTIONS。
487
+ * allowOther 时末位固定为「其他」,业务选项占前 N-1 席。
488
+ */
489
+ function withOtherOption(options, allowOther) {
490
+ if (allowOther) {
491
+ var withoutDup = options.filter(function (o) {
492
+ return o.value !== OTHER_VALUE;
493
+ });
494
+ var capped = withoutDup.slice(0, CLARIFY_DOCK_MAX_OPTIONS - 1);
495
+ return [].concat(_toConsumableArray(capped), [{
496
+ value: OTHER_VALUE,
497
+ label: '其他'
498
+ }]);
499
+ }
500
+ return options.slice(0, CLARIFY_DOCK_MAX_OPTIONS);
501
+ }
502
+
503
+ /**
504
+ * 按 input.kind 适配录入组件:
505
+ * options / options-multi → 选项列表;date → DatePicker;
506
+ * date-range → DateRangePicker。自由文本走自然语言 + Composer,不在此渲染。
507
+ */
508
+ function QuestionInput(_ref3) {
509
+ var input = _ref3.input,
510
+ answer = _ref3.answer,
511
+ otherDraft = _ref3.otherDraft,
512
+ dateDraft = _ref3.dateDraft,
513
+ dateRangeDraft = _ref3.dateRangeDraft,
514
+ onOtherDraftChange = _ref3.onOtherDraftChange,
515
+ onDateChange = _ref3.onDateChange,
516
+ onDateRangeChange = _ref3.onDateRangeChange,
517
+ onPickSingle = _ref3.onPickSingle,
518
+ onToggleMulti = _ref3.onToggleMulti;
519
+ if (input.kind === 'options' || input.kind === 'options-multi') {
520
+ return /*#__PURE__*/React.createElement(OptionsList, {
521
+ options: withOtherOption(input.options, input.allowOther),
522
+ multi: input.kind === 'options-multi',
523
+ answer: answer,
524
+ otherDraft: otherDraft,
525
+ otherPlaceholder: input.otherPlaceholder,
526
+ onOtherDraftChange: onOtherDraftChange,
527
+ onPickSingle: onPickSingle,
528
+ onToggleMulti: onToggleMulti
529
+ });
530
+ }
531
+ if (input.kind === 'date') {
532
+ return /*#__PURE__*/React.createElement("div", {
533
+ "data-odn-clarify-dock-input-row": true
534
+ }, /*#__PURE__*/React.createElement(DatePicker, {
535
+ value: dateDraft,
536
+ onChange: function onChange(d) {
537
+ return onDateChange(d);
538
+ }
539
+ }));
540
+ }
541
+ if (input.kind === 'date-range') {
542
+ return /*#__PURE__*/React.createElement("div", {
543
+ "data-odn-clarify-dock-input-row": true
544
+ }, /*#__PURE__*/React.createElement(DateRangePicker, {
545
+ value: dateRangeDraft,
546
+ onChange: function onChange(range) {
547
+ return onDateRangeChange(range);
548
+ }
549
+ }));
550
+ }
551
+ return /*#__PURE__*/React.createElement("div", {
552
+ "data-odn-clarify-dock-hint": true
553
+ }, "\u6682\u4E0D\u652F\u6301\u7684\u8F93\u5165\u7C7B\u578B\uFF1A", input.kind);
554
+ }
555
+
556
+ /* ------------------------------------------------------------------ */
557
+ /* OptionsList · A–E 徽标 + ↑↓ 框选(焦点隔离,不抢 Composer) */
558
+ /* ------------------------------------------------------------------ */
559
+
560
+ function OptionsList(_ref4) {
561
+ var options = _ref4.options,
562
+ multi = _ref4.multi,
563
+ answer = _ref4.answer,
564
+ otherDraft = _ref4.otherDraft,
565
+ otherPlaceholder = _ref4.otherPlaceholder,
566
+ onOtherDraftChange = _ref4.onOtherDraftChange,
567
+ onPickSingle = _ref4.onPickSingle,
568
+ onToggleMulti = _ref4.onToggleMulti;
569
+ var optionRefs = useRef([]);
570
+ var optionKey = options.map(function (o) {
571
+ return o.value;
572
+ }).join('|');
573
+
574
+ /* 切题时把焦点放到首项/已选项,便于立刻 ↑↓ */
575
+ useEffect(function () {
576
+ var selectedIdx = options.findIndex(function (o) {
577
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options') return answer.value === o.value;
578
+ if ((answer === null || answer === void 0 ? void 0 : answer.kind) === 'options-multi') return answer.values.includes(o.value);
579
+ return false;
580
+ });
581
+ var focusIdx = selectedIdx >= 0 ? selectedIdx : 0;
582
+ var id = window.requestAnimationFrame(function () {
583
+ var _optionRefs$current$f;
584
+ (_optionRefs$current$f = optionRefs.current[focusIdx]) === null || _optionRefs$current$f === void 0 || _optionRefs$current$f.focus();
585
+ });
586
+ return function () {
587
+ return window.cancelAnimationFrame(id);
588
+ };
589
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- 只在选项集切换时重聚焦
590
+ }, [optionKey]);
591
+ var focusAt = function focusAt(idx) {
592
+ var _optionRefs$current$n;
593
+ var next = Math.max(0, Math.min(options.length - 1, idx));
594
+ (_optionRefs$current$n = optionRefs.current[next]) === null || _optionRefs$current$n === void 0 || _optionRefs$current$n.focus();
595
+ };
596
+ var handleOptionKeyDown = function handleOptionKeyDown(idx, opt) {
597
+ return function (e) {
598
+ if (e.key === 'ArrowDown') {
599
+ e.preventDefault();
600
+ e.stopPropagation();
601
+ var next = (idx + 1) % options.length;
602
+ focusAt(next);
603
+ if (!multi) onPickSingle(options[next]);
604
+ return;
605
+ }
606
+ if (e.key === 'ArrowUp') {
607
+ e.preventDefault();
608
+ e.stopPropagation();
609
+ var _next = (idx - 1 + options.length) % options.length;
610
+ focusAt(_next);
611
+ if (!multi) onPickSingle(options[_next]);
612
+ return;
613
+ }
614
+ if (e.key === 'Enter' || e.key === ' ') {
615
+ e.preventDefault();
616
+ e.stopPropagation();
617
+ if (multi) onToggleMulti(opt);else onPickSingle(opt);
618
+ }
619
+ };
620
+ };
621
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
622
+ "data-odn-clarify-dock-options": true,
623
+ "data-multi": multi || undefined,
624
+ role: multi ? 'group' : 'radiogroup',
625
+ "aria-label": "\u6F84\u6E05\u9009\u9879"
626
+ }, options.map(function (opt, idx) {
627
+ var _LETTER_BADGES$idx;
628
+ var active = (answer === null || answer === void 0 ? void 0 : answer.kind) === 'options' ? answer.value === opt.value : (answer === null || answer === void 0 ? void 0 : answer.kind) === 'options-multi' ? answer.values.includes(opt.value) : false;
629
+ var isOther = opt.value === OTHER_VALUE;
630
+ var letter = (_LETTER_BADGES$idx = LETTER_BADGES[idx]) !== null && _LETTER_BADGES$idx !== void 0 ? _LETTER_BADGES$idx : '';
631
+ if (isOther && active) {
632
+ var editingRow = /*#__PURE__*/React.createElement("div", {
633
+ "data-odn-clarify-dock-option": true,
634
+ "data-active": true,
635
+ "data-other": true,
636
+ "data-editing": true
637
+ }, multi ? /*#__PURE__*/React.createElement("span", {
638
+ role: "button",
639
+ tabIndex: 0,
640
+ "data-odn-clarify-dock-option-letter": true,
641
+ "data-odn-clarify-dock-option-toggle": true,
642
+ "aria-label": "\u53D6\u6D88\u9009\u62E9\u5176\u4ED6",
643
+ onClick: function onClick() {
644
+ return onToggleMulti(opt);
645
+ },
646
+ onKeyDown: function onKeyDown(e) {
647
+ if (e.key === 'Enter' || e.key === ' ') {
648
+ e.preventDefault();
649
+ onToggleMulti(opt);
650
+ }
651
+ }
652
+ }, letter) : /*#__PURE__*/React.createElement("span", {
653
+ "data-odn-clarify-dock-option-letter": true,
654
+ "aria-hidden": true
655
+ }, letter), /*#__PURE__*/React.createElement(Input, {
656
+ value: otherDraft,
657
+ onChange: function onChange(_, value) {
658
+ return onOtherDraftChange(value);
659
+ },
660
+ onKeyDown: function onKeyDown(e) {
661
+ if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
662
+ e.preventDefault();
663
+ var otherIdx = options.findIndex(function (o) {
664
+ return o.value === OTHER_VALUE;
665
+ });
666
+ var next = e.key === 'ArrowDown' ? (otherIdx + 1) % options.length : (otherIdx - 1 + options.length) % options.length;
667
+ if (!multi) {
668
+ onPickSingle(options[next]);
669
+ }
670
+ requestAnimationFrame(function () {
671
+ return focusAt(next);
672
+ });
673
+ }
674
+ if (multi && e.key === 'Escape') {
675
+ e.preventDefault();
676
+ onToggleMulti(opt);
677
+ }
678
+ },
679
+ placeholder: otherPlaceholder !== null && otherPlaceholder !== void 0 ? otherPlaceholder : '请描述你的情况…',
680
+ size: "small",
681
+ light: true,
682
+ autoFocus: true
683
+ }));
684
+ if (multi) {
685
+ return /*#__PURE__*/React.createElement(HoverFill, {
686
+ key: opt.value,
687
+ hoverColor: MULTI_SELECTED_HOVER_FILL,
688
+ activeColor: MULTI_SELECTED_HOVER_FILL,
689
+ "data-odn-clarify-dock-option-fill": true
690
+ }, editingRow);
691
+ }
692
+ return /*#__PURE__*/React.createElement(React.Fragment, {
693
+ key: opt.value
694
+ }, editingRow);
695
+ }
696
+ var optionContent = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
697
+ "data-odn-clarify-dock-option-letter": true,
698
+ "aria-hidden": true
699
+ }, letter), /*#__PURE__*/React.createElement("span", {
700
+ "data-odn-clarify-dock-option-label": true
701
+ }, opt.label));
702
+
703
+ /* 不用 data-odn-button:避免 Button small 固定 height 把通栏选项撑坏 */
704
+ if (active && !multi) {
705
+ return /*#__PURE__*/React.createElement("button", {
706
+ key: opt.value,
707
+ type: "button",
708
+ ref: function ref(el) {
709
+ optionRefs.current[idx] = el;
710
+ },
711
+ role: "radio",
712
+ "aria-checked": true,
713
+ tabIndex: idx === 0 ? 0 : -1,
714
+ onClick: function onClick() {
715
+ return onPickSingle(opt);
716
+ },
717
+ onKeyDown: handleOptionKeyDown(idx, opt),
718
+ "data-odn-clarify-dock-option": true,
719
+ "data-active": true,
720
+ "data-other": isOther || undefined
721
+ }, optionContent);
722
+ }
723
+ return /*#__PURE__*/React.createElement(HoverFill, {
724
+ key: opt.value,
725
+ hoverColor: multi ? active ? MULTI_SELECTED_HOVER_FILL : MULTI_UNSELECTED_HOVER_FILL : MULTI_UNSELECTED_HOVER_FILL,
726
+ activeColor: multi ? active ? MULTI_SELECTED_HOVER_FILL : MULTI_UNSELECTED_ACTIVE_FILL : MULTI_UNSELECTED_ACTIVE_FILL,
727
+ "data-odn-clarify-dock-option-fill": true
728
+ }, /*#__PURE__*/React.createElement("button", {
729
+ type: "button",
730
+ ref: function ref(el) {
731
+ optionRefs.current[idx] = el;
732
+ },
733
+ role: multi ? 'checkbox' : 'radio',
734
+ "aria-checked": active,
735
+ tabIndex: idx === 0 ? 0 : -1,
736
+ onClick: function onClick() {
737
+ return multi ? onToggleMulti(opt) : onPickSingle(opt);
738
+ },
739
+ onKeyDown: handleOptionKeyDown(idx, opt),
740
+ "data-odn-clarify-dock-option": true,
741
+ "data-active": active || undefined,
742
+ "data-other": isOther || undefined
743
+ }, optionContent));
744
+ })));
745
+ }
746
+
747
+ /* ================================================================== */
748
+ /* Hook · 派生 dock 状态 */
749
+ /* ================================================================== */
750
+
751
+ /**
752
+ * 收 ClarifyDock 的派生态:
753
+ * - thread 最后一条 assistant 带 clarify-dock 且未答 → pending
754
+ * - recordAnswer 后 Panel 消失,Trigger 切 Approval 式锁态卡
755
+ */
756
+ export function useClarifyDockState(messages, sessionKey, resetVer) {
757
+ var _useState15 = useState({}),
758
+ _useState16 = _slicedToArray(_useState15, 2),
759
+ answers = _useState16[0],
760
+ setAnswers = _useState16[1];
761
+
762
+ /* 切换会话或点「重置」时清空已答标记,避免 Panel / Trigger 状态脱节 */
763
+ useEffect(function () {
764
+ setAnswers({});
765
+ }, [sessionKey, resetVer]);
766
+ var latest = useMemo(function () {
767
+ var _last$instance;
768
+ if (messages.length === 0) return null;
769
+ var last = messages[messages.length - 1];
770
+ if (last.role !== 'assistant') return null;
771
+ if (((_last$instance = last.instance) === null || _last$instance === void 0 ? void 0 : _last$instance.type) !== 'clarify-dock') return null;
772
+ return {
773
+ msgId: last.id,
774
+ spec: last.instance.spec
775
+ };
776
+ }, [messages]);
777
+ var pending = latest && !(latest.msgId in answers) ? latest : null;
778
+ var getMessageState = useCallback(function (msgId) {
779
+ return {
780
+ items: answers[msgId]
781
+ };
782
+ }, [answers]);
783
+ var recordAnswer = useCallback(function (msgId, items) {
784
+ setAnswers(function (m) {
785
+ return _objectSpread(_objectSpread({}, m), {}, _defineProperty({}, msgId, items));
786
+ });
787
+ }, []);
788
+ return {
789
+ pending: pending,
790
+ getMessageState: getMessageState,
791
+ recordAnswer: recordAnswer
792
+ };
793
+ }
794
+ ClarifyDockTrigger.displayName = 'ClarifyDockTrigger';
795
+ ClarifyDockPanel.displayName = 'ClarifyDockPanel';