one-design-next 0.0.53 → 0.0.55

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.
@@ -75,6 +75,8 @@ export interface PreviewTab {
75
75
  name: string;
76
76
  content: string;
77
77
  type: string;
78
+ /** 业务方自定义数据,组件本身不消费,仅透传回回调函数(如 onDownload、onOpenInBrowser 等) */
79
+ data?: unknown;
78
80
  }
79
81
  /**
80
82
  * 内联引用状态:
@@ -205,7 +205,8 @@ export function ChatItem(_ref2) {
205
205
  var labelRef = useRef(null);
206
206
  var titleRef = useRef(null);
207
207
  var trailingRef = useRef(null);
208
- var showStatus = Boolean(status && !active);
208
+ // active 时隐藏 waiting/unread/error;generating 仍展示(当前会话仍在生成)
209
+ var showStatus = Boolean(status && (!active || status === 'generating'));
209
210
  var showTypeIcon = type === 'human';
210
211
  var fitTitle = showTypeIcon || showStatus;
211
212
  var displayTitle = useFittedTitle(title, fitTitle, labelRef, titleRef, trailingRef);
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export interface AutoHeightProps extends React.HTMLAttributes<HTMLDivElement> {
3
+ /**
4
+ * `bottom`:高度变化时底边锚定(Dock 贴 Composer 上方用)。
5
+ * `top`:默认,消息流内 Card 用。
6
+ */
7
+ anchor?: 'top' | 'bottom';
8
+ /**
9
+ * 内容身份键(如翻页 page)。
10
+ * 变化时走旧题渐隐 → 新题渐现;有高度差时同步高度。
11
+ */
12
+ contentKey?: React.Key;
13
+ }
14
+ /**
15
+ * 只动画「题面内容」的高度与透明度;卡面描边应由外层稳定承载,勿把整卡塞进来做 opacity。
16
+ */
17
+ export declare function AutoHeight({ children, anchor, contentKey, style, ...props }: AutoHeightProps): React.JSX.Element;
@@ -0,0 +1,225 @@
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
+ var _excluded = ["children", "anchor", "contentKey", "style"];
3
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4
+ 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; }
5
+ 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; }
6
+ 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; }
7
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
8
+ 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); }
9
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
10
+ 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."); }
11
+ 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); }
12
+ 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; }
13
+ 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; } }
14
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
15
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
16
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
17
+ import React, { useLayoutEffect, useRef, useState } from 'react';
18
+
19
+ /**
20
+ * 翻页(contentKey 变化):
21
+ * 旧题渐隐 → 新题渐现(不交叉,避免半透明叠字)
22
+ * 有高度差时,高度与整段同起同止;等高则只做显隐。
23
+ */
24
+ var FADE_OUT_MS = 140;
25
+ var FADE_IN_MS = 180;
26
+ var HEIGHT_MS = FADE_OUT_MS + FADE_IN_MS;
27
+ var FADE_IN_DELAY_MS = FADE_OUT_MS;
28
+ var TOTAL_MS = HEIGHT_MS;
29
+ var HEIGHT_EPS = 0.5;
30
+ var EASING = 'ease-in-out';
31
+ /**
32
+ * 只动画「题面内容」的高度与透明度;卡面描边应由外层稳定承载,勿把整卡塞进来做 opacity。
33
+ */
34
+ export function AutoHeight(_ref) {
35
+ var children = _ref.children,
36
+ _ref$anchor = _ref.anchor,
37
+ anchor = _ref$anchor === void 0 ? 'top' : _ref$anchor,
38
+ contentKey = _ref.contentKey,
39
+ style = _ref.style,
40
+ props = _objectWithoutProperties(_ref, _excluded);
41
+ var outerRef = useRef(null);
42
+ var currentRef = useRef(null);
43
+ var outgoingRef = useRef(null);
44
+ var readyRef = useRef(false);
45
+ var animatingRef = useRef(false);
46
+ var heightRef = useRef(0);
47
+ var prevKeyRef = useRef(contentKey);
48
+ var prevChildrenRef = useRef(children);
49
+ var _useState = useState(null),
50
+ _useState2 = _slicedToArray(_useState, 2),
51
+ outgoing = _useState2[0],
52
+ setOutgoing = _useState2[1];
53
+ var finishHeight = function finishHeight(outer, h) {
54
+ heightRef.current = h;
55
+ outer.style.transition = '';
56
+ outer.style.height = "".concat(h, "px");
57
+ };
58
+ var runHeightOnly = function runHeightOnly(outer, start, target) {
59
+ if (Math.abs(start - target) < HEIGHT_EPS) {
60
+ animatingRef.current = false;
61
+ finishHeight(outer, target);
62
+ return;
63
+ }
64
+ animatingRef.current = true;
65
+ outer.style.transition = '';
66
+ outer.style.height = "".concat(start, "px");
67
+ void outer.offsetHeight;
68
+ outer.style.transition = "height ".concat(HEIGHT_MS, "ms ").concat(EASING);
69
+ outer.style.height = "".concat(target, "px");
70
+ };
71
+ useLayoutEffect(function () {
72
+ var outer = outerRef.current;
73
+ var current = currentRef.current;
74
+ if (!outer || !current) return;
75
+ var measure = function measure() {
76
+ return current.getBoundingClientRect().height;
77
+ };
78
+ var onTransitionEnd = function onTransitionEnd(e) {
79
+ if (e.target !== outer || e.propertyName !== 'height') return;
80
+ if (outgoing != null) return;
81
+ animatingRef.current = false;
82
+ finishHeight(outer, measure());
83
+ };
84
+ outer.addEventListener('transitionend', onTransitionEnd);
85
+ if (!readyRef.current) {
86
+ var h = measure();
87
+ outer.style.height = "".concat(h, "px");
88
+ heightRef.current = h;
89
+ readyRef.current = true;
90
+ prevKeyRef.current = contentKey;
91
+ prevChildrenRef.current = children;
92
+ return function () {
93
+ return outer.removeEventListener('transitionend', onTransitionEnd);
94
+ };
95
+ }
96
+ var keyChanged = contentKey !== undefined && prevKeyRef.current !== contentKey;
97
+ if (keyChanged) {
98
+ var oldChildren = prevChildrenRef.current;
99
+ prevKeyRef.current = contentKey;
100
+ prevChildrenRef.current = children;
101
+ /* 等高 / 不等高都走渐隐渐现;高度差在 outgoing 阶段再处理 */
102
+ setOutgoing(oldChildren);
103
+ return function () {
104
+ return outer.removeEventListener('transitionend', onTransitionEnd);
105
+ };
106
+ }
107
+ prevChildrenRef.current = children;
108
+ if (outgoing != null || animatingRef.current) {
109
+ return function () {
110
+ return outer.removeEventListener('transitionend', onTransitionEnd);
111
+ };
112
+ }
113
+ runHeightOnly(outer, heightRef.current, measure());
114
+ return function () {
115
+ return outer.removeEventListener('transitionend', onTransitionEnd);
116
+ };
117
+ }, [children, contentKey, outgoing]);
118
+
119
+ /**
120
+ * 旧题先隐尽,再显新题——中间不交叉半透明,避免叠字鬼影。
121
+ * 有高度差时高度整段同步;等高只做显隐。旧层用不透明底盖住下层。
122
+ */
123
+ useLayoutEffect(function () {
124
+ if (outgoing == null) return;
125
+ var outer = outerRef.current;
126
+ var current = currentRef.current;
127
+ var outEl = outgoingRef.current;
128
+ if (!outer || !current) return;
129
+ var start = heightRef.current;
130
+ var target = current.getBoundingClientRect().height;
131
+ var heightChanged = Math.abs(start - target) >= HEIGHT_EPS;
132
+ animatingRef.current = true;
133
+ outer.style.transition = '';
134
+ outer.style.height = "".concat(start, "px");
135
+ current.style.transition = 'none';
136
+ current.style.opacity = '0';
137
+ if (outEl) {
138
+ outEl.style.transition = 'none';
139
+ outEl.style.opacity = '1';
140
+ }
141
+ void outer.offsetHeight;
142
+ if (heightChanged) {
143
+ outer.style.transition = "height ".concat(HEIGHT_MS, "ms ").concat(EASING);
144
+ outer.style.height = "".concat(target, "px");
145
+ }
146
+ if (outEl) {
147
+ outEl.style.transition = "opacity ".concat(FADE_OUT_MS, "ms ").concat(EASING);
148
+ outEl.style.opacity = '0';
149
+ }
150
+ var fadeInTimer = window.setTimeout(function () {
151
+ if (outEl) {
152
+ outEl.style.visibility = 'hidden';
153
+ }
154
+ current.style.transition = "opacity ".concat(FADE_IN_MS, "ms ").concat(EASING);
155
+ current.style.opacity = '1';
156
+ }, FADE_IN_DELAY_MS);
157
+ var doneTimer = window.setTimeout(function () {
158
+ setOutgoing(null);
159
+ animatingRef.current = false;
160
+ finishHeight(outer, current.getBoundingClientRect().height);
161
+ current.style.transition = '';
162
+ current.style.opacity = '1';
163
+ if (outEl) {
164
+ outEl.style.transition = '';
165
+ outEl.style.opacity = '';
166
+ outEl.style.visibility = '';
167
+ }
168
+ }, TOTAL_MS);
169
+ return function () {
170
+ window.clearTimeout(fadeInTimer);
171
+ window.clearTimeout(doneTimer);
172
+ };
173
+ }, [outgoing]);
174
+ useLayoutEffect(function () {
175
+ var current = currentRef.current;
176
+ var outer = outerRef.current;
177
+ if (!current || !outer || typeof ResizeObserver === 'undefined') return;
178
+ var onTransitionEnd = function onTransitionEnd(e) {
179
+ if (e.target !== outer || e.propertyName !== 'height') return;
180
+ if (outgoing != null) return;
181
+ animatingRef.current = false;
182
+ finishHeight(outer, current.getBoundingClientRect().height);
183
+ };
184
+ outer.addEventListener('transitionend', onTransitionEnd);
185
+ var ro = new ResizeObserver(function () {
186
+ if (animatingRef.current || outgoing != null) return;
187
+ if (!readyRef.current) return;
188
+ var target = current.getBoundingClientRect().height;
189
+ var start = heightRef.current;
190
+ if (Math.abs(start - target) < HEIGHT_EPS) return;
191
+ runHeightOnly(outer, start, target);
192
+ });
193
+ ro.observe(current);
194
+ return function () {
195
+ ro.disconnect();
196
+ outer.removeEventListener('transitionend', onTransitionEnd);
197
+ };
198
+ }, [outgoing]);
199
+ var pin = anchor === 'bottom' ? 'bottom' : 'top';
200
+ return /*#__PURE__*/React.createElement("div", _extends({
201
+ ref: outerRef,
202
+ "data-odn-clarify-auto-height": true,
203
+ "data-anchor": anchor,
204
+ style: _objectSpread({
205
+ overflow: 'hidden',
206
+ position: 'relative',
207
+ display: 'flex',
208
+ flexDirection: 'column',
209
+ justifyContent: anchor === 'bottom' ? 'flex-end' : 'flex-start',
210
+ background: 'transparent'
211
+ }, style)
212
+ }, props), outgoing != null ? /*#__PURE__*/React.createElement("div", {
213
+ ref: outgoingRef,
214
+ "data-odn-clarify-auto-height-outgoing": true,
215
+ "aria-hidden": true,
216
+ style: _defineProperty(_defineProperty(_defineProperty(_defineProperty({
217
+ position: 'absolute',
218
+ left: 0,
219
+ right: 0
220
+ }, pin, 0), "pointerEvents", 'none'), "background", 'var(--odn-color-bg-elevated)'), "zIndex", 1)
221
+ }, outgoing) : null, /*#__PURE__*/React.createElement("div", {
222
+ ref: currentRef,
223
+ "data-odn-clarify-auto-height-inner": true
224
+ }, children));
225
+ }
@@ -1,12 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import type { ClarifyInput } from './types';
3
3
  import './style';
4
+ /** @deprecated 仅兼容旧 Host;上移 morph 已改为 FLIP,不再需要 layoutId / LayoutGroup。 */
5
+ export declare function clarifyDockLayoutId(msgId: string): string;
4
6
  export type { ClarifyInput, ClarifyOption } from './types';
5
7
  export interface ClarifyDockQuestion {
6
8
  key: string;
7
9
  /** 题面文案。 */
8
10
  label: string;
9
11
  input: ClarifyInput;
12
+ /**
13
+ * 是否允许跳过;默认 true。
14
+ * 跳过后由 AI 按默认继续,UI 不展示具体默认值。
15
+ */
16
+ skippable?: boolean;
10
17
  }
11
18
  export interface ClarifyDockSpec {
12
19
  title?: string;
@@ -22,9 +29,14 @@ export interface ClarifyDockAnswerItem {
22
29
  }
23
30
  export interface ClarifyDockResolvePayload {
24
31
  text: string;
32
+ /** 跳过题的值为 {@link CLARIFY_DOCK_SKIPPED_VALUE},由 Host/模型填默认。 */
25
33
  data: Record<string, string | string[]>;
26
34
  items: ClarifyDockAnswerItem[];
27
35
  }
36
+ /** 锁态 / 回看提示:跳过题统一文案(不展示 AI 默认选项)。 */
37
+ export declare const CLARIFY_DOCK_SKIPPED_LABEL = "\u5DF2\u8DF3\u8FC7\uFF0C\u6309\u9ED8\u8BA4\u9009\u9879\u7EE7\u7EED";
38
+ /** data[key] 哨兵:表示本题跳过,默认由模型侧决定。 */
39
+ export declare const CLARIFY_DOCK_SKIPPED_VALUE = "__skipped__";
28
40
  /** Host 消息最小形状——hook 只认 assistant + clarify-dock instance。 */
29
41
  export interface ClarifyDockHostMessage {
30
42
  id: string;
@@ -37,8 +49,15 @@ export interface ClarifyDockHostMessage {
37
49
  export interface ClarifyDockTriggerProps {
38
50
  /** 已确认的题→答列表;有值则进入锁态。 */
39
51
  items?: ClarifyDockAnswerItem[];
52
+ /**
53
+ * 传 `false` 关闭 dock→锁态上移 morph。
54
+ * 字符串值已忽略(morph 按 msgId FLIP,不再使用 Motion layoutId)。
55
+ */
56
+ layoutId?: string | false;
57
+ /** 与 Panel 的 msgId 对齐,用于领取提交瞬间 stash 的矩形。 */
58
+ msgId?: string;
40
59
  }
41
- export declare function ClarifyDockTrigger({ items }: ClarifyDockTriggerProps): React.JSX.Element | null;
60
+ export declare function ClarifyDockTrigger({ items, layoutId: layoutIdProp, msgId, }: ClarifyDockTriggerProps): React.JSX.Element | null;
42
61
  export declare namespace ClarifyDockTrigger {
43
62
  var displayName: string;
44
63
  }
@@ -51,8 +70,13 @@ export interface ClarifyDockPanelProps {
51
70
  msgId: string;
52
71
  spec: ClarifyDockSpec;
53
72
  onResolve: (payload: ClarifyDockResolvePayload) => void;
73
+ /**
74
+ * 传 `false` 关闭 dock→锁态上移 morph。
75
+ * 字符串值已忽略(按 msgId stash 矩形,不再使用 Motion layoutId)。
76
+ */
77
+ layoutId?: string | false;
54
78
  }
55
- export declare function ClarifyDockPanel({ msgId, spec, onResolve }: ClarifyDockPanelProps): React.JSX.Element;
79
+ export declare function ClarifyDockPanel({ msgId, spec, onResolve, layoutId: layoutIdProp, }: ClarifyDockPanelProps): React.JSX.Element;
56
80
  export declare namespace ClarifyDockPanel {
57
81
  var displayName: string;
58
82
  }
@@ -14,8 +14,9 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
14
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
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
16
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
+ import { useReducedMotion } from 'motion/react';
17
18
  import * as React from 'react';
18
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
19
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
19
20
  import Button from "../button";
20
21
  import DatePicker from "../date-picker";
21
22
  import DateRangePicker from "../date-range-picker";
@@ -23,9 +24,18 @@ import HoverFill from "../hover-fill";
23
24
  import Icon from "../icon";
24
25
  import Input from "../input";
25
26
  import Pagination from "../pagination";
27
+ import { AutoHeight } from "./auto-height";
28
+ import { discardClarifyDockMorph, stashClarifyDockMorph, takeClarifyDockMorph } from "./morph-handoff";
26
29
  import { toISODate } from "./types";
27
30
  import "./style";
28
31
 
32
+ /** @deprecated 仅兼容旧 Host;上移 morph 已改为 FLIP,不再需要 layoutId / LayoutGroup。 */
33
+ export function clarifyDockLayoutId(msgId) {
34
+ return "clarify-dock-".concat(msgId);
35
+ }
36
+ var MORPH_MS = 320;
37
+ var MORPH_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)';
38
+
29
39
  /* ------------------------------------------------------------------ */
30
40
  /* ClarifyDock */
31
41
  /* ------------------------------------------------------------------ */
@@ -38,12 +48,19 @@ import "./style";
38
48
  * - <ClarifyDockPanel />:多题分页 form 面板
39
49
  * - useClarifyDockState(messages):派生 pending / answered
40
50
  *
41
- * 多题节奏:一次只问一题;底栏左 Pagination simple(仅页码),右「上一题 / 下一题|确认」。
42
- * 全部必答。单选 / 多选末项「其他」由 allowOther 注入。
51
+ * 多题节奏:一次只问一题;底栏左 Pagination simple(含翻页),右「跳过本题 / 下一题|确认」。
52
+ * 每题必答或跳过;跳过由 AI 侧填默认,UI 不展示默认值。单选 / 多选末项「其他」由 allowOther 注入。
53
+ * 提交锁态:Panel 提交前 stash 视口矩形,Trigger 挂载时 FLIP 上移(不碰 layoutId,避免弄坏翻页/展开)。
43
54
  */
44
55
 
45
56
  /** 整卷提交:自然语言摘要 + 结构化 data + 锁态小票行。 */
46
57
 
58
+ /** 锁态 / 回看提示:跳过题统一文案(不展示 AI 默认选项)。 */
59
+ export var CLARIFY_DOCK_SKIPPED_LABEL = '已跳过,按默认选项继续';
60
+
61
+ /** data[key] 哨兵:表示本题跳过,默认由模型侧决定。 */
62
+ export var CLARIFY_DOCK_SKIPPED_VALUE = '__skipped__';
63
+
47
64
  /** Host 消息最小形状——hook 只认 assistant + clarify-dock instance。 */
48
65
 
49
66
  /* ================================================================== */
@@ -56,7 +73,14 @@ function formatLockedLine(label, answer) {
56
73
  return "".concat(stem, "\uFF1A").concat(answer);
57
74
  }
58
75
  export function ClarifyDockTrigger(_ref) {
59
- var items = _ref.items;
76
+ var items = _ref.items,
77
+ layoutIdProp = _ref.layoutId,
78
+ msgId = _ref.msgId;
79
+ var reduceMotion = useReducedMotion();
80
+ var rootRef = useRef(null);
81
+ /* Strict Mode 双调用时保留第一次 take 的矩形 */
82
+ var morphFromRef = useRef(undefined);
83
+ var morphDisabled = layoutIdProp === false;
60
84
  var _useState = useState(false),
61
85
  _useState2 = _slicedToArray(_useState, 2),
62
86
  expanded = _useState2[0],
@@ -78,6 +102,51 @@ export function ClarifyDockTrigger(_ref) {
78
102
  return window.clearTimeout(id);
79
103
  };
80
104
  }, [expanded]);
105
+
106
+ /* dock→锁态:用提交前 stash 的视口矩形做 FLIP,不影响展开/收合 CSS */
107
+ useLayoutEffect(function () {
108
+ if (!msgId || !(items !== null && items !== void 0 && items.length)) return;
109
+ if (morphDisabled || reduceMotion) {
110
+ discardClarifyDockMorph(msgId);
111
+ morphFromRef.current = null;
112
+ return;
113
+ }
114
+ var el = rootRef.current;
115
+ /* 必须先有 DOM 再 take,避免锁态未挂载时把 stash 吃掉 */
116
+ if (!el) return;
117
+ if (morphFromRef.current === undefined) {
118
+ morphFromRef.current = takeClarifyDockMorph(msgId);
119
+ }
120
+ var from = morphFromRef.current;
121
+ if (!from) return;
122
+ var to = el.getBoundingClientRect();
123
+ /* 只平移,绝不 scale——避免文字/控件被挤压拉伸 */
124
+ var dx = from.left + from.width / 2 - (to.left + to.width / 2);
125
+ var dy = from.top - to.top;
126
+ if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5) return;
127
+ el.style.zIndex = '30';
128
+ el.style.willChange = 'transform';
129
+ var anim = el.animate([{
130
+ transform: "translate(".concat(dx, "px, ").concat(dy, "px)")
131
+ }, {
132
+ transform: 'translate(0px, 0px)'
133
+ }], {
134
+ duration: MORPH_MS,
135
+ easing: MORPH_EASING,
136
+ fill: 'both'
137
+ });
138
+ var clear = function clear() {
139
+ el.style.zIndex = '';
140
+ el.style.willChange = '';
141
+ el.style.transform = '';
142
+ };
143
+ anim.addEventListener('finish', clear);
144
+ anim.addEventListener('cancel', clear);
145
+ return function () {
146
+ anim.cancel();
147
+ clear();
148
+ };
149
+ }, [msgId, morphDisabled, reduceMotion, items]);
81
150
  if (!items || items.length === 0) return null;
82
151
  var multi = items.length > 1;
83
152
  var mainLabel = multi ? "\u5DF2\u786E\u8BA4 ".concat(items.length, " \u9898") : formatLockedLine(items[0].label, items[0].answer);
@@ -92,6 +161,7 @@ export function ClarifyDockTrigger(_ref) {
92
161
  });
93
162
  };
94
163
  return /*#__PURE__*/React.createElement("div", {
164
+ ref: rootRef,
95
165
  "data-odn-clarify-dock-locked": true,
96
166
  "data-resolved": true,
97
167
  "data-summary-expanded": expanded ? '' : undefined
@@ -157,7 +227,10 @@ var LETTER_BADGES = ['A', 'B', 'C', 'D', 'E'];
157
227
  export function ClarifyDockPanel(_ref2) {
158
228
  var msgId = _ref2.msgId,
159
229
  spec = _ref2.spec,
160
- onResolve = _ref2.onResolve;
230
+ onResolve = _ref2.onResolve,
231
+ layoutIdProp = _ref2.layoutId;
232
+ var reduceMotion = useReducedMotion();
233
+ var rootRef = useRef(null);
161
234
  var total = spec.questions.length;
162
235
  var _useState5 = useState(0),
163
236
  _useState6 = _slicedToArray(_useState5, 2),
@@ -211,8 +284,11 @@ export function ClarifyDockPanel(_ref2) {
211
284
  return copy;
212
285
  });
213
286
  };
287
+ var isSkipped = (answer === null || answer === void 0 ? void 0 : answer.kind) === 'skipped';
288
+ var skippable = question.skippable !== false;
214
289
  var canAdvance = useMemo(function () {
215
290
  if (!answer) return false;
291
+ if (answer.kind === 'skipped') return true;
216
292
  switch (answer.kind) {
217
293
  case 'options':
218
294
  if (answer.value === OTHER_VALUE) return otherDraft.trim().length > 0;
@@ -235,10 +311,19 @@ export function ClarifyDockPanel(_ref2) {
235
311
  }
236
312
  }, [answer, otherDraft]);
237
313
  var isLastPage = page === total - 1;
238
- var isFirstPage = page === 0;
314
+
315
+ /** 末题确认:其余题均已答或已跳。 */
316
+ var canConfirmAll = useMemo(function () {
317
+ if (!canAdvance) return false;
318
+ return answers.every(function (a, i) {
319
+ return i === page ? true : a != null;
320
+ });
321
+ }, [answers, canAdvance, page]);
239
322
  var formatAnswer = function formatAnswer(q, ans) {
240
323
  if (!ans) return '(未答)';
241
324
  switch (ans.kind) {
325
+ case 'skipped':
326
+ return CLARIFY_DOCK_SKIPPED_LABEL;
242
327
  case 'options':
243
328
  {
244
329
  var _ans$otherText;
@@ -334,6 +419,9 @@ export function ClarifyDockPanel(_ref2) {
334
419
  case 'date-range':
335
420
  data[q.key] = "".concat(a.start, "~").concat(a.end);
336
421
  break;
422
+ case 'skipped':
423
+ data[q.key] = CLARIFY_DOCK_SKIPPED_VALUE;
424
+ break;
337
425
  }
338
426
  });
339
427
  var items = spec.questions.map(function (q, i) {
@@ -346,32 +434,82 @@ export function ClarifyDockPanel(_ref2) {
346
434
  var text = items.map(function (it) {
347
435
  return formatLockedLine(it.label, it.answer);
348
436
  }).join(';');
349
- onResolve({
437
+ var payload = {
350
438
  text: text,
351
439
  data: data,
352
440
  items: items
353
- });
441
+ };
442
+ /* 提交前记下 Panel 视口矩形;Trigger 挂载后 FLIP 上移(不走 layoutId) */
443
+ if (layoutIdProp !== false && !reduceMotion && rootRef.current) {
444
+ stashClarifyDockMorph(msgId, rootRef.current);
445
+ }
446
+ onResolve(payload);
447
+ };
448
+ var goToPage = function goToPage(nextPage, nextAnswers) {
449
+ if (nextAnswers) setAnswers(nextAnswers);
450
+ setPage(Math.max(0, Math.min(nextPage, total - 1)));
354
451
  };
355
452
  var handleContinue = function handleContinue() {
356
453
  if (!canAdvance) return;
357
454
  var synced = syncCurrentDraftIntoAnswers();
358
455
  setAnswers(synced);
359
- if (isLastPage) submit(synced);else setPage(function (p) {
360
- return Math.min(p + 1, total - 1);
361
- });
456
+ if (isLastPage) {
457
+ if (!synced.every(function (a) {
458
+ return a != null;
459
+ })) {
460
+ var firstIncomplete = synced.findIndex(function (a) {
461
+ return a == null;
462
+ });
463
+ if (firstIncomplete >= 0) goToPage(firstIncomplete, synced);
464
+ return;
465
+ }
466
+ submit(synced);
467
+ return;
468
+ }
469
+ goToPage(page + 1, synced);
362
470
  };
363
- var handlePrev = function handlePrev() {
364
- if (isFirstPage) return;
471
+ var handleSkip = function handleSkip() {
472
+ if (!skippable || isSkipped) return;
365
473
  var synced = syncCurrentDraftIntoAnswers();
366
- setAnswers(synced);
367
- setPage(function (p) {
368
- return Math.max(0, p - 1);
474
+ var next = _toConsumableArray(synced);
475
+ next[page] = {
476
+ kind: 'skipped'
477
+ };
478
+ setOtherDraft('');
479
+ setDateDraft(null);
480
+ setDateRangeDraft(null);
481
+ /* 不按顺序跳过:任意一题跳过后若已全部有值(含已跳),直接提交 */
482
+ if (next.every(function (a) {
483
+ return a != null;
484
+ })) {
485
+ setAnswers(next);
486
+ submit(next);
487
+ return;
488
+ }
489
+ var firstIncomplete = next.findIndex(function (a) {
490
+ return a == null;
369
491
  });
492
+ goToPage(firstIncomplete >= 0 ? firstIncomplete : page, next);
493
+ };
494
+ var handleResume = function handleResume() {
495
+ if (!isSkipped) return;
496
+ setAnswerForPage(undefined);
497
+ setOtherDraft('');
498
+ setDateDraft(null);
499
+ setDateRangeDraft(null);
500
+ };
501
+ var handlePageChange = function handlePageChange(_e, value) {
502
+ var synced = syncCurrentDraftIntoAnswers();
503
+ goToPage(value - 1, synced);
370
504
  };
371
505
  return /*#__PURE__*/React.createElement("div", {
506
+ ref: rootRef,
372
507
  "data-odn-clarify-dock": true,
373
508
  "data-odn-clarify-msg-id": msgId,
374
509
  "aria-label": "\u6F84\u6E05\u95EE\u9898 ".concat(page + 1, " / ").concat(total)
510
+ }, /*#__PURE__*/React.createElement(AutoHeight, {
511
+ anchor: "bottom",
512
+ contentKey: page
375
513
  }, /*#__PURE__*/React.createElement("div", {
376
514
  "data-odn-clarify-dock-body": true
377
515
  }, spec.title ? /*#__PURE__*/React.createElement("div", {
@@ -390,9 +528,15 @@ export function ClarifyDockPanel(_ref2) {
390
528
  "data-odn-clarify-dock-q-hint": true
391
529
  }, "\u5355\u9009") : input.kind === 'options-multi' ? /*#__PURE__*/React.createElement("span", {
392
530
  "data-odn-clarify-dock-q-hint": true
393
- }, "\u53EF\u591A\u9009") : null), /*#__PURE__*/React.createElement(QuestionInput, {
531
+ }, "\u53EF\u591A\u9009") : null), /*#__PURE__*/React.createElement("div", {
532
+ "data-odn-clarify-dock-input-shell": true,
533
+ "data-skipped": isSkipped ? '' : undefined
534
+ }, /*#__PURE__*/React.createElement("div", {
535
+ "data-odn-clarify-dock-input-layer": true,
536
+ "aria-hidden": isSkipped
537
+ }, /*#__PURE__*/React.createElement(QuestionInput, {
394
538
  input: input,
395
- answer: answer,
539
+ answer: isSkipped ? undefined : answer,
396
540
  otherDraft: otherDraft,
397
541
  dateDraft: dateDraft,
398
542
  dateRangeDraft: dateRangeDraft,
@@ -453,27 +597,38 @@ export function ClarifyDockPanel(_ref2) {
453
597
  otherText: otherDraft
454
598
  });
455
599
  }
456
- }))), /*#__PURE__*/React.createElement("div", {
600
+ })), isSkipped ? /*#__PURE__*/React.createElement("div", {
601
+ "data-odn-clarify-dock-skipped-mask": true
602
+ }, /*#__PURE__*/React.createElement("p", {
603
+ "data-odn-clarify-dock-skipped-label": true
604
+ }, CLARIFY_DOCK_SKIPPED_LABEL), /*#__PURE__*/React.createElement(Button, {
605
+ size: "small",
606
+ intent: "normal",
607
+ onClick: handleResume,
608
+ "data-odn-clarify-dock-resume": true
609
+ }, "\u91CD\u65B0\u56DE\u7B54")) : null)))), /*#__PURE__*/React.createElement("div", {
457
610
  "data-odn-clarify-dock-actions": true
458
611
  }, total > 1 ? /*#__PURE__*/React.createElement(Pagination, {
459
612
  type: "simple",
460
613
  value: page + 1,
461
614
  totalSize: total,
462
615
  pageSize: 1,
463
- showPrevNext: false,
616
+ showPrevNext: true,
464
617
  showFirstLast: false,
618
+ onChange: handlePageChange,
465
619
  "data-odn-clarify-dock-page-indicator": true
466
620
  }) : /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("div", {
467
621
  "data-odn-clarify-dock-actions-right": true
468
- }, !isFirstPage ? /*#__PURE__*/React.createElement(Button, {
622
+ }, skippable && !isSkipped ? /*#__PURE__*/React.createElement(Button, {
469
623
  size: "small",
470
624
  intent: "normal",
471
- onClick: handlePrev
472
- }, "\u4E0A\u4E00\u9898") : null, /*#__PURE__*/React.createElement(Button, {
625
+ onClick: handleSkip,
626
+ "data-odn-clarify-dock-skip": true
627
+ }, "\u8DF3\u8FC7\u672C\u9898") : null, /*#__PURE__*/React.createElement(Button, {
473
628
  intent: "primary",
474
629
  size: "small",
475
630
  onClick: handleContinue,
476
- disabled: !canAdvance,
631
+ disabled: isLastPage ? !canConfirmAll : !canAdvance,
477
632
  "data-odn-clarify-dock-continue": true
478
633
  }, isLastPage ? '确认' : '下一题'))));
479
634
  }
@@ -0,0 +1,10 @@
1
+ /** dock → 锁态 FLIP:提交前把 Panel 视口矩形交给 Trigger,不依赖 Motion layoutId。 */
2
+ export interface ClarifyDockMorphRect {
3
+ top: number;
4
+ left: number;
5
+ width: number;
6
+ height: number;
7
+ }
8
+ export declare function stashClarifyDockMorph(msgId: string, el: Element): void;
9
+ export declare function takeClarifyDockMorph(msgId: string): ClarifyDockMorphRect | null;
10
+ export declare function discardClarifyDockMorph(msgId: string): void;
@@ -0,0 +1,21 @@
1
+ /** dock → 锁态 FLIP:提交前把 Panel 视口矩形交给 Trigger,不依赖 Motion layoutId。 */
2
+
3
+ var pending = new Map();
4
+ export function stashClarifyDockMorph(msgId, el) {
5
+ var r = el.getBoundingClientRect();
6
+ pending.set(msgId, {
7
+ top: r.top,
8
+ left: r.left,
9
+ width: r.width,
10
+ height: r.height
11
+ });
12
+ }
13
+ export function takeClarifyDockMorph(msgId) {
14
+ var _pending$get;
15
+ var r = (_pending$get = pending.get(msgId)) !== null && _pending$get !== void 0 ? _pending$get : null;
16
+ if (r) pending.delete(msgId);
17
+ return r;
18
+ }
19
+ export function discardClarifyDockMorph(msgId) {
20
+ pending.delete(msgId);
21
+ }
@@ -24,8 +24,16 @@ div[data-odn-clarify-dock] {
24
24
  outline: none;
25
25
  }
26
26
 
27
- /* body:标题 + 题面内容(对应 approval-body) */
28
- div[data-odn-clarify-dock] > [data-odn-clarify-dock-body] {
27
+ /*
28
+ * AutoHeight 已 overflow:hidden;补上顶圆角,裁切翻页旧层不透明底,
29
+ * 避免直角白底戳出 Panel 圆角(Panel 本身不能 overflow:hidden,以免裁切 DatePicker)。
30
+ */
31
+ div[data-odn-clarify-dock] > [data-odn-clarify-auto-height] {
32
+ border-radius: 12px 12px 0 0;
33
+ }
34
+
35
+ /* body:标题 + 题面内容(对应 approval-body);中间可隔 AutoHeight */
36
+ div[data-odn-clarify-dock] [data-odn-clarify-dock-body] {
29
37
  display: flex;
30
38
  flex-direction: column;
31
39
  gap: 12px;
@@ -533,4 +541,43 @@ div[data-odn-clarify-dock] > [data-odn-clarify-dock-body] {
533
541
  }
534
542
  [data-odn-clarify-dock-input-row] > [data-odn-button] {
535
543
  flex: 0 0 auto;
544
+ }
545
+
546
+ /* ---------- 跳过态:任意录入形态共用蒙层 +「重新回答」 ---------- */
547
+ [data-odn-clarify-dock-input-shell] {
548
+ position: relative;
549
+ }
550
+
551
+ /* 仅跳过蒙层需要占位;勿抬高 date 等单行录入的底空隙 */
552
+ [data-odn-clarify-dock-input-shell][data-skipped] {
553
+ min-height: 48px;
554
+ }
555
+
556
+ [data-odn-clarify-dock-input-shell][data-skipped] [data-odn-clarify-dock-input-layer] {
557
+ opacity: 0.35;
558
+ pointer-events: none;
559
+ user-select: none;
560
+ }
561
+
562
+ [data-odn-clarify-dock-skipped-mask] {
563
+ position: absolute;
564
+ inset: 0;
565
+ z-index: 1;
566
+ display: flex;
567
+ flex-direction: column;
568
+ align-items: center;
569
+ justify-content: center;
570
+ gap: 8px;
571
+ box-sizing: border-box;
572
+ padding: 12px;
573
+ border-radius: 6px;
574
+ background: color-mix(in srgb, var(--odn-color-white) 58%, transparent);
575
+ }
576
+
577
+ [data-odn-clarify-dock-skipped-label] {
578
+ margin: 0;
579
+ font-size: 12px;
580
+ line-height: 1.5;
581
+ color: var(--odn-color-black-9);
582
+ text-align: center;
536
583
  }
package/dist/index.d.ts CHANGED
@@ -57,7 +57,7 @@ export { default as ActionBar, type ActionBarProps } from './action-bar';
57
57
  export { default as AgentStep, type AgentStepProps, type AgentStepGroupProps } from './agent-step';
58
58
  export { default as AgentThink, type AgentThinkProps } from './agent-think';
59
59
  export { default as Approval, type ApprovalProps, type ApprovalSpec, type ApprovalDecision, type ApprovalResolvePayload, type ApprovalSummaryItem, } from './approval';
60
- export { ClarifyDockPanel, ClarifyDockTrigger, useClarifyDockState, CLARIFY_DOCK_MAX_OPTIONS, type ClarifyDockPanelProps, type ClarifyDockTriggerProps, type ClarifyDockSpec, type ClarifyDockQuestion, type ClarifyDockAnswerItem, type ClarifyDockResolvePayload, type ClarifyDockMessageState, type ClarifyDockState, type ClarifyDockHostMessage, type ClarifyInput, type ClarifyOption, } from './clarify-dock';
60
+ export { ClarifyDockPanel, ClarifyDockTrigger, useClarifyDockState, clarifyDockLayoutId, CLARIFY_DOCK_MAX_OPTIONS, CLARIFY_DOCK_SKIPPED_LABEL, CLARIFY_DOCK_SKIPPED_VALUE, type ClarifyDockPanelProps, type ClarifyDockTriggerProps, type ClarifyDockSpec, type ClarifyDockQuestion, type ClarifyDockAnswerItem, type ClarifyDockResolvePayload, type ClarifyDockMessageState, type ClarifyDockState, type ClarifyDockHostMessage, type ClarifyInput, type ClarifyOption, } from './clarify-dock';
61
61
  export { default as Artifact, type ArtifactProps } from './artifact';
62
62
  export { default as Attachments, type AttachmentsProps } from './attachments';
63
63
  export { default as CodeBlock, type CodeBlockProps } from './code-block';
package/dist/index.js CHANGED
@@ -63,7 +63,7 @@ export { default as ActionBar } from "./action-bar";
63
63
  export { default as AgentStep } from "./agent-step";
64
64
  export { default as AgentThink } from "./agent-think";
65
65
  export { default as Approval } from "./approval";
66
- export { ClarifyDockPanel, ClarifyDockTrigger, useClarifyDockState, CLARIFY_DOCK_MAX_OPTIONS } from "./clarify-dock";
66
+ export { ClarifyDockPanel, ClarifyDockTrigger, useClarifyDockState, clarifyDockLayoutId, CLARIFY_DOCK_MAX_OPTIONS, CLARIFY_DOCK_SKIPPED_LABEL, CLARIFY_DOCK_SKIPPED_VALUE } from "./clarify-dock";
67
67
  export { default as Artifact } from "./artifact";
68
68
  export { default as Attachments } from "./attachments";
69
69
  export { default as CodeBlock } from "./code-block";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "packageManager": "pnpm@11.8.0",
6
6
  "module": "dist/index.js",