one-design-next 0.0.32 → 0.0.33

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.
@@ -8,45 +8,150 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
8
8
  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; }
9
9
  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; } }
10
10
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
11
- import { useState, useRef, useEffect } from 'react';
11
+ import { useState, useRef, useEffect, useId } from 'react';
12
12
  import HoverFill from "../hover-fill";
13
13
  import Icon from "../icon";
14
14
  import Dialog from "../dialog";
15
15
  import Dropdown from "../dropdown";
16
16
  import "./style";
17
- export function ChatItem(_ref) {
18
- var id = _ref.id,
19
- title = _ref.title,
20
- active = _ref.active,
21
- status = _ref.status,
22
- _onClick = _ref.onClick,
23
- onRename = _ref.onRename,
24
- onDelete = _ref.onDelete,
25
- actionMenuZIndex = _ref.actionMenuZIndex;
26
- var _useState = useState(false),
17
+ var STATUS_ARIA_LABEL = {
18
+ generating: '生成中',
19
+ unread: '未读更新',
20
+ error: '生成出错'
21
+ };
22
+ function ChatItemGeneratingJelly(_ref) {
23
+ var _ref$size = _ref.size,
24
+ size = _ref$size === void 0 ? 14 : _ref$size,
25
+ _ref$speed = _ref.speed,
26
+ speed = _ref$speed === void 0 ? 1.75 : _ref$speed;
27
+ var rawId = useId();
28
+ var filterId = "odn-chat-item-jelly-ooze-".concat(rawId.replace(/:/g, ''));
29
+ var style = {
30
+ '--uib-size': "".concat(size, "px"),
31
+ '--uib-color': 'currentColor',
32
+ '--uib-speed': "".concat(speed, "s"),
33
+ filter: "url('#".concat(filterId, "')")
34
+ };
35
+ return /*#__PURE__*/React.createElement("span", {
36
+ "data-odn-chat-item-jelly": true,
37
+ style: style,
38
+ "aria-hidden": "true"
39
+ }, /*#__PURE__*/React.createElement("span", {
40
+ "data-odn-chat-item-jelly-dot": true
41
+ }), /*#__PURE__*/React.createElement("span", {
42
+ "data-odn-chat-item-jelly-traveler": true
43
+ }), /*#__PURE__*/React.createElement("svg", {
44
+ width: "0",
45
+ height: "0",
46
+ style: {
47
+ position: 'absolute'
48
+ }
49
+ }, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("filter", {
50
+ id: filterId
51
+ }, /*#__PURE__*/React.createElement("feGaussianBlur", {
52
+ in: "SourceGraphic",
53
+ stdDeviation: size / 9,
54
+ result: "blur"
55
+ }), /*#__PURE__*/React.createElement("feColorMatrix", {
56
+ in: "blur",
57
+ mode: "matrix",
58
+ values: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7",
59
+ result: "ooze"
60
+ }), /*#__PURE__*/React.createElement("feBlend", {
61
+ in: "SourceGraphic",
62
+ in2: "ooze"
63
+ })))));
64
+ }
65
+ function ChatItemStatus(_ref2) {
66
+ var status = _ref2.status;
67
+ var label = STATUS_ARIA_LABEL[status];
68
+ if (status === 'generating') {
69
+ return /*#__PURE__*/React.createElement("span", {
70
+ "data-odn-chat-item-status": true,
71
+ "data-odn-chat-item-status-generating": true,
72
+ "aria-label": label,
73
+ role: "status"
74
+ }, /*#__PURE__*/React.createElement(ChatItemGeneratingJelly, null));
75
+ }
76
+ if (status === 'error') {
77
+ return /*#__PURE__*/React.createElement("span", {
78
+ "data-odn-chat-item-status": true,
79
+ "data-odn-chat-item-status-error": true,
80
+ "aria-label": label,
81
+ role: "status"
82
+ }, /*#__PURE__*/React.createElement(Icon, {
83
+ name: "alert-circle-filled",
84
+ size: 12
85
+ }));
86
+ }
87
+ return /*#__PURE__*/React.createElement("span", {
88
+ "data-odn-chat-item-status": true,
89
+ "data-odn-chat-item-status-unread": true,
90
+ "aria-label": label,
91
+ role: "status"
92
+ }, /*#__PURE__*/React.createElement("span", {
93
+ "data-odn-chat-item-status-unread-dot": true
94
+ }));
95
+ }
96
+ function useControllableState(controlled, defaultValue, onChange) {
97
+ var _useState = useState(defaultValue),
27
98
  _useState2 = _slicedToArray(_useState, 2),
28
- renaming = _useState2[0],
29
- setRenaming = _useState2[1];
99
+ internal = _useState2[0],
100
+ setInternal = _useState2[1];
101
+ var value = controlled !== null && controlled !== void 0 ? controlled : internal;
102
+ var setValue = function setValue(next) {
103
+ onChange === null || onChange === void 0 || onChange(next);
104
+ if (controlled === undefined) setInternal(next);
105
+ };
106
+ return [value, setValue];
107
+ }
108
+ export function ChatItem(_ref3) {
109
+ var id = _ref3.id,
110
+ title = _ref3.title,
111
+ active = _ref3.active,
112
+ status = _ref3.status,
113
+ _onClick = _ref3.onClick,
114
+ onRename = _ref3.onRename,
115
+ onDelete = _ref3.onDelete,
116
+ actionMenuZIndex = _ref3.actionMenuZIndex,
117
+ renamingProp = _ref3.renaming,
118
+ _ref3$defaultRenaming = _ref3.defaultRenaming,
119
+ defaultRenaming = _ref3$defaultRenaming === void 0 ? false : _ref3$defaultRenaming,
120
+ onRenamingChange = _ref3.onRenamingChange,
121
+ menuOpenProp = _ref3.menuOpen,
122
+ _ref3$defaultMenuOpen = _ref3.defaultMenuOpen,
123
+ defaultMenuOpen = _ref3$defaultMenuOpen === void 0 ? false : _ref3$defaultMenuOpen,
124
+ onMenuOpenChange = _ref3.onMenuOpenChange,
125
+ deleteOpenProp = _ref3.deleteOpen,
126
+ _ref3$defaultDeleteOp = _ref3.defaultDeleteOpen,
127
+ defaultDeleteOpen = _ref3$defaultDeleteOp === void 0 ? false : _ref3$defaultDeleteOp,
128
+ onDeleteOpenChange = _ref3.onDeleteOpenChange;
129
+ var _useControllableState = useControllableState(renamingProp, defaultRenaming, onRenamingChange),
130
+ _useControllableState2 = _slicedToArray(_useControllableState, 2),
131
+ renaming = _useControllableState2[0],
132
+ setRenaming = _useControllableState2[1];
30
133
  var _useState3 = useState(title),
31
134
  _useState4 = _slicedToArray(_useState3, 2),
32
135
  draft = _useState4[0],
33
136
  setDraft = _useState4[1];
34
- var _useState5 = useState(false),
35
- _useState6 = _slicedToArray(_useState5, 2),
36
- deleteOpen = _useState6[0],
37
- setDeleteOpen = _useState6[1];
38
- var _useState7 = useState(false),
39
- _useState8 = _slicedToArray(_useState7, 2),
40
- menuOpen = _useState8[0],
41
- setMenuOpen = _useState8[1];
137
+ var _useControllableState3 = useControllableState(deleteOpenProp, defaultDeleteOpen, onDeleteOpenChange),
138
+ _useControllableState4 = _slicedToArray(_useControllableState3, 2),
139
+ deleteOpen = _useControllableState4[0],
140
+ setDeleteOpen = _useControllableState4[1];
141
+ var _useControllableState5 = useControllableState(menuOpenProp, defaultMenuOpen, onMenuOpenChange),
142
+ _useControllableState6 = _slicedToArray(_useControllableState5, 2),
143
+ menuOpen = _useControllableState6[0],
144
+ setMenuOpen = _useControllableState6[1];
42
145
  var inputRef = useRef(null);
146
+ useEffect(function () {
147
+ if (!renaming) setDraft(title);
148
+ }, [title, renaming]);
43
149
  useEffect(function () {
44
150
  if (renaming) {
45
151
  var el = inputRef.current;
46
152
  if (!el) return;
47
153
  el.focus();
48
154
  el.select();
49
- // 长文本默认会滚到末尾;强制从第一个字开始展示
50
155
  el.scrollLeft = 0;
51
156
  }
52
157
  }, [renaming]);
@@ -54,8 +159,6 @@ export function ChatItem(_ref) {
54
159
  var _inputRef$current;
55
160
  var trimmed = draft.trim();
56
161
  if (trimmed && trimmed !== title) onRename === null || onRename === void 0 || onRename(id, trimmed);
57
- // 先卸下焦点,避免 input 卸载后焦点被转移到切回来的 <button>
58
- // 引发 :focus-visible 触发出 focus 环
59
162
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.blur();
60
163
  setRenaming(false);
61
164
  };
@@ -104,9 +207,8 @@ export function ChatItem(_ref) {
104
207
  }, /*#__PURE__*/React.createElement("span", {
105
208
  "data-odn-chat-item-title": true,
106
209
  "data-odn-chat-item-title-bold": active ? '' : undefined
107
- }, title), status && !active && /*#__PURE__*/React.createElement("span", {
108
- "data-odn-chat-item-status": true,
109
- "data-odn-chat-item-status-generating": status === 'generating' ? '' : undefined
210
+ }, title), status && !active && /*#__PURE__*/React.createElement(ChatItemStatus, {
211
+ status: status
110
212
  }))), /*#__PURE__*/React.createElement(Dropdown, {
111
213
  trigger: "click",
112
214
  placement: "bottomRight",
@@ -127,8 +229,12 @@ export function ChatItem(_ref) {
127
229
  if (value === 'rename') {
128
230
  setDraft(title);
129
231
  setRenaming(true);
232
+ setMenuOpen(false);
233
+ }
234
+ if (value === 'delete') {
235
+ setDeleteOpen(true);
236
+ setMenuOpen(false);
130
237
  }
131
- if (value === 'delete') setDeleteOpen(true);
132
238
  }
133
239
  }, /*#__PURE__*/React.createElement("button", {
134
240
  type: "button",
@@ -1,12 +1,4 @@
1
1
  @charset "UTF-8";
2
- @keyframes odn-chat-item-pulse {
3
- 0%, 100% {
4
- opacity: 1;
5
- }
6
- 50% {
7
- opacity: 0.5;
8
- }
9
- }
10
2
  [data-odn-chat-item]:hover [data-odn-chat-item-menu-trigger], [data-odn-chat-item]:has(:focus-visible) [data-odn-chat-item-menu-trigger] {
11
3
  opacity: 1;
12
4
  pointer-events: auto;
@@ -111,6 +103,8 @@
111
103
  }
112
104
 
113
105
  [data-odn-chat-item-title] {
106
+ flex: 1 1 auto;
107
+ min-width: 0;
114
108
  font-size: 14px;
115
109
  overflow: hidden;
116
110
  text-overflow: ellipsis;
@@ -122,16 +116,27 @@
122
116
  }
123
117
 
124
118
  [data-odn-chat-item-status] {
119
+ flex-shrink: 0;
120
+ width: 14px;
121
+ height: 14px;
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ }
126
+
127
+ [data-odn-chat-item-status-unread] [data-odn-chat-item-status-unread-dot] {
125
128
  width: 6px;
126
129
  height: 6px;
127
130
  border-radius: 50%;
128
131
  background: var(--odn-color-brand-6);
129
- flex-shrink: 0;
130
132
  }
131
133
 
132
134
  [data-odn-chat-item-status-generating] {
133
- opacity: 0.5;
134
- animation: odn-chat-item-pulse 2s ease-in-out infinite;
135
+ color: var(--odn-color-black-8);
136
+ }
137
+
138
+ [data-odn-chat-item-status-error] {
139
+ color: var(--odn-color-error);
135
140
  }
136
141
 
137
142
  [data-odn-chat-item-menu-trigger] {
@@ -186,6 +191,72 @@
186
191
  }
187
192
 
188
193
  /* ChatItem 的 Dropdown 面板:宽度根据内容自适应(hug),不使用默认 128px */
194
+ [data-odn-chat-item-jelly] {
195
+ position: relative;
196
+ display: inline-flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ flex-shrink: 0;
200
+ width: var(--uib-size);
201
+ height: var(--uib-size);
202
+ }
203
+ [data-odn-chat-item-jelly]::before, [data-odn-chat-item-jelly]::after,
204
+ [data-odn-chat-item-jelly] [data-odn-chat-item-jelly-dot] {
205
+ content: "";
206
+ position: absolute;
207
+ width: 33%;
208
+ height: 33%;
209
+ background-color: var(--uib-color);
210
+ border-radius: 100%;
211
+ will-change: transform;
212
+ }
213
+ [data-odn-chat-item-jelly]::before {
214
+ right: 0;
215
+ bottom: 6%;
216
+ animation: odn-chat-item-jelly-grow var(--uib-speed) ease calc(var(--uib-speed) * -0.666) infinite;
217
+ }
218
+ [data-odn-chat-item-jelly]::after {
219
+ left: 0;
220
+ bottom: 6%;
221
+ animation: odn-chat-item-jelly-grow var(--uib-speed) ease calc(var(--uib-speed) * -0.333) infinite;
222
+ }
223
+
224
+ [data-odn-chat-item-jelly-dot] {
225
+ top: 6%;
226
+ left: 30%;
227
+ animation: odn-chat-item-jelly-grow var(--uib-speed) ease infinite;
228
+ }
229
+
230
+ [data-odn-chat-item-jelly-traveler] {
231
+ position: absolute;
232
+ top: 6%;
233
+ left: 30%;
234
+ width: 33%;
235
+ height: 33%;
236
+ background-color: var(--uib-color);
237
+ border-radius: 100%;
238
+ animation: odn-chat-item-jelly-triangulate var(--uib-speed) ease infinite;
239
+ }
240
+
241
+ @keyframes odn-chat-item-jelly-grow {
242
+ 0%, 85%, 100% {
243
+ transform: scale(1.5);
244
+ }
245
+ 50%, 60% {
246
+ transform: scale(0);
247
+ }
248
+ }
249
+ @keyframes odn-chat-item-jelly-triangulate {
250
+ 0%, 100% {
251
+ transform: none;
252
+ }
253
+ 33.333% {
254
+ transform: translate(120%, 175%);
255
+ }
256
+ 66.666% {
257
+ transform: translate(-95%, 175%);
258
+ }
259
+ }
189
260
  [data-odn-dropdown-content].odn-chat-item-action-menu {
190
261
  min-width: 0;
191
262
  width: max-content;
@@ -157,6 +157,11 @@ export interface ComposerProps {
157
157
  * 避免业务方从前后两次 `attachments` 数组里 diff 出被删项。
158
158
  */
159
159
  onAttachmentRemove?: (index: number, attachment: Attachment) => void;
160
+ /**
161
+ * 附件失败重试回调(status='error' 生效)。
162
+ * 组件只负责交互事件,重试所需 File 引用由业务方保管。
163
+ */
164
+ onAttachmentRetry?: (index: number, attachment: Attachment) => void;
160
165
  /**
161
166
  * 关闭新附件入口:附件工具按钮置灰、拖入不再高亮、粘贴入文件被忽略。
162
167
  * 已存在的附件仍可由用户点击 × 删除。
@@ -173,6 +178,15 @@ export interface ComposerProps {
173
178
  * @default 20 * 1024 * 1024(20MB)
174
179
  */
175
180
  maxFileSize?: number;
181
+ /**
182
+ * 单次总文件体积上限(字节)。不传表示不限。
183
+ */
184
+ maxTotalSize?: number;
185
+ /**
186
+ * 文件白名单规则(与原生 input accept 一致),同时作用于按钮选择 / 拖拽 / 粘贴。
187
+ * @default image/*,.pdf,...,.7z
188
+ */
189
+ accept?: string;
176
190
  /**
177
191
  * 参数面板内容渲染。提供后 invocation chip 可点击打开面板;
178
192
  * `SkillItem.initialState='pending'` 插入后会自动打开。