one-design-next 0.0.97 → 0.0.98

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.
@@ -1,11 +1,53 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import _extends from "@babel/runtime/helpers/esm/extends";
3
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
1
4
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
5
  import clsx from 'clsx';
3
- import { useMemo, useState } from 'react';
6
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
7
+ import ChatGroup, { CHAT_GROUP_PREVIEW_LIMIT } from "../chat-group";
8
+ import { PresenceSlots } from "../chat-group/presence-list";
4
9
  import ChatItem from "../chat-item";
10
+ import Dialog from "../dialog";
5
11
  import Dropdown from "../dropdown";
12
+ import HoverFill from "../hover-fill";
6
13
  import Icon from "../icon";
7
14
  import "./style";
8
15
 
16
+ /** 系统「未分组」默认 id;不在「分组」模块内渲染。 */
17
+ export var CHAT_LIST_UNGROUPED_ID = 'ungrouped';
18
+ var CHAT_ITEM_ROW_FALLBACK = 40;
19
+ var UNGROUPED_EXPAND_SCROLL_MS = 320;
20
+ function findScrollParent(el) {
21
+ var node = el;
22
+ while (node) {
23
+ var _getComputedStyle = getComputedStyle(node),
24
+ overflowY = _getComputedStyle.overflowY;
25
+ if (overflowY === 'auto' || overflowY === 'scroll') {
26
+ return node;
27
+ }
28
+ node = node.parentElement;
29
+ }
30
+ return el;
31
+ }
32
+ function chatItemRowStep(root) {
33
+ var item = root.querySelector('[data-odn-chat-item]');
34
+ var height = item instanceof HTMLElement ? item.getBoundingClientRect().height : 0;
35
+ return height > 0 ? height + 2 : CHAT_ITEM_ROW_FALLBACK;
36
+ }
37
+ function scrollUpByChatItems(scroller, count) {
38
+ var delta = chatItemRowStep(scroller) * count;
39
+ var max = Math.max(0, scroller.scrollHeight - scroller.clientHeight);
40
+ var top = Math.min(scroller.scrollTop + delta, max);
41
+ if (typeof scroller.scrollTo === 'function') {
42
+ scroller.scrollTo({
43
+ top: top,
44
+ behavior: 'smooth'
45
+ });
46
+ return;
47
+ }
48
+ scroller.scrollTop = top;
49
+ }
50
+
9
51
  /** 按会话时间筛选(面板不含时间组;`filterTime` 仅受控 API)。 */
10
52
 
11
53
  /** 按会话类型筛选:全部 / AI 任务 / 人工客服。 */
@@ -88,6 +130,9 @@ function useControllable(controlled, defaultValue, onChange) {
88
130
  function defaultRenderItem(item, node) {
89
131
  return node;
90
132
  }
133
+ function createGroupId() {
134
+ return "group-".concat(Date.now().toString(36), "-").concat(Math.random().toString(36).slice(2, 6));
135
+ }
91
136
  function filterOptionLabel(label, selected) {
92
137
  return /*#__PURE__*/React.createElement("span", {
93
138
  "data-odn-chat-list-filter-option": true
@@ -126,40 +171,87 @@ function buildFilterMenu(filterType, filterStatus) {
126
171
  })
127
172
  }];
128
173
  }
129
- export function ChatList(_ref) {
130
- var items = _ref.items,
131
- _ref$title = _ref.title,
132
- title = _ref$title === void 0 ? '对话' : _ref$title,
133
- _ref$pinnedSectionTit = _ref.pinnedSectionTitle,
134
- pinnedSectionTitle = _ref$pinnedSectionTit === void 0 ? '置顶' : _ref$pinnedSectionTit,
135
- _ref$recentSectionTit = _ref.recentSectionTitle,
136
- recentSectionTitle = _ref$recentSectionTit === void 0 ? '最近' : _ref$recentSectionTit,
137
- filterTimeProp = _ref.filterTime,
138
- _ref$defaultFilterTim = _ref.defaultFilterTime,
139
- defaultFilterTime = _ref$defaultFilterTim === void 0 ? 'all' : _ref$defaultFilterTim,
140
- filterTypeProp = _ref.filterType,
141
- _ref$defaultFilterTyp = _ref.defaultFilterType,
142
- defaultFilterType = _ref$defaultFilterTyp === void 0 ? 'all' : _ref$defaultFilterTyp,
143
- onFilterTypeChange = _ref.onFilterTypeChange,
144
- filterStatusProp = _ref.filterStatus,
145
- _ref$defaultFilterSta = _ref.defaultFilterStatus,
146
- defaultFilterStatus = _ref$defaultFilterSta === void 0 ? 'all' : _ref$defaultFilterSta,
147
- onFilterStatusChange = _ref.onFilterStatusChange,
148
- filterOpenProp = _ref.filterOpen,
149
- _ref$defaultFilterOpe = _ref.defaultFilterOpen,
150
- defaultFilterOpen = _ref$defaultFilterOpe === void 0 ? false : _ref$defaultFilterOpe,
151
- onFilterOpenChange = _ref.onFilterOpenChange,
152
- empty = _ref.empty,
153
- actionMenuZIndex = _ref.actionMenuZIndex,
154
- filterMenuZIndex = _ref.filterMenuZIndex,
155
- className = _ref.className,
156
- onItemClick = _ref.onItemClick,
157
- onRename = _ref.onRename,
158
- onPin = _ref.onPin,
159
- onDelete = _ref.onDelete,
160
- _ref$renderItem = _ref.renderItem,
161
- renderItem = _ref$renderItem === void 0 ? defaultRenderItem : _ref$renderItem,
162
- renderRestScroll = _ref.renderRestScroll;
174
+ function IconActionButton(_ref) {
175
+ var label = _ref.label,
176
+ _onClick = _ref.onClick,
177
+ children = _ref.children,
178
+ attr = _ref.attr;
179
+ return /*#__PURE__*/React.createElement("button", _extends({
180
+ type: "button",
181
+ "data-odn-chat-list-icon-btn": true
182
+ }, attr ? _defineProperty({}, attr, '') : {}, {
183
+ "aria-label": label,
184
+ title: label,
185
+ onMouseDown: function onMouseDown(e) {
186
+ return e.preventDefault();
187
+ },
188
+ onClick: function onClick(e) {
189
+ e.stopPropagation();
190
+ _onClick === null || _onClick === void 0 || _onClick(e);
191
+ }
192
+ }), children);
193
+ }
194
+ export function ChatList(_ref3) {
195
+ var items = _ref3.items,
196
+ _ref3$title = _ref3.title,
197
+ title = _ref3$title === void 0 ? '对话' : _ref3$title,
198
+ groups = _ref3.groups,
199
+ pinnedSectionTitle = _ref3.pinnedSectionTitle,
200
+ _ref3$recentSectionTi = _ref3.recentSectionTitle,
201
+ recentSectionTitle = _ref3$recentSectionTi === void 0 ? '最近' : _ref3$recentSectionTi,
202
+ _ref3$groupsSectionTi = _ref3.groupsSectionTitle,
203
+ groupsSectionTitle = _ref3$groupsSectionTi === void 0 ? '分组' : _ref3$groupsSectionTi,
204
+ _ref3$ungroupedTitle = _ref3.ungroupedTitle,
205
+ ungroupedTitle = _ref3$ungroupedTitle === void 0 ? '未分组' : _ref3$ungroupedTitle,
206
+ _ref3$ungroupedGroupI = _ref3.ungroupedGroupId,
207
+ ungroupedGroupId = _ref3$ungroupedGroupI === void 0 ? CHAT_LIST_UNGROUPED_ID : _ref3$ungroupedGroupI,
208
+ filterTimeProp = _ref3.filterTime,
209
+ _ref3$defaultFilterTi = _ref3.defaultFilterTime,
210
+ defaultFilterTime = _ref3$defaultFilterTi === void 0 ? 'all' : _ref3$defaultFilterTi,
211
+ filterTypeProp = _ref3.filterType,
212
+ _ref3$defaultFilterTy = _ref3.defaultFilterType,
213
+ defaultFilterType = _ref3$defaultFilterTy === void 0 ? 'all' : _ref3$defaultFilterTy,
214
+ onFilterTypeChange = _ref3.onFilterTypeChange,
215
+ filterStatusProp = _ref3.filterStatus,
216
+ _ref3$defaultFilterSt = _ref3.defaultFilterStatus,
217
+ defaultFilterStatus = _ref3$defaultFilterSt === void 0 ? 'all' : _ref3$defaultFilterSt,
218
+ onFilterStatusChange = _ref3.onFilterStatusChange,
219
+ searchProp = _ref3.search,
220
+ _ref3$defaultSearch = _ref3.defaultSearch,
221
+ defaultSearch = _ref3$defaultSearch === void 0 ? '' : _ref3$defaultSearch,
222
+ onSearchChange = _ref3.onSearchChange,
223
+ _ref3$showSearch = _ref3.showSearch,
224
+ showSearch = _ref3$showSearch === void 0 ? false : _ref3$showSearch,
225
+ filterOpenProp = _ref3.filterOpen,
226
+ _ref3$defaultFilterOp = _ref3.defaultFilterOpen,
227
+ defaultFilterOpen = _ref3$defaultFilterOp === void 0 ? false : _ref3$defaultFilterOp,
228
+ onFilterOpenChange = _ref3.onFilterOpenChange,
229
+ _ref3$showEmptyGroups = _ref3.showEmptyGroups,
230
+ showEmptyGroups = _ref3$showEmptyGroups === void 0 ? true : _ref3$showEmptyGroups,
231
+ empty = _ref3.empty,
232
+ actionMenuZIndex = _ref3.actionMenuZIndex,
233
+ filterMenuZIndex = _ref3.filterMenuZIndex,
234
+ className = _ref3.className,
235
+ onItemClick = _ref3.onItemClick,
236
+ onRename = _ref3.onRename,
237
+ onPin = _ref3.onPin,
238
+ onMoveToGroup = _ref3.onMoveToGroup,
239
+ onDelete = _ref3.onDelete,
240
+ onAddGroup = _ref3.onAddGroup,
241
+ onRenameGroup = _ref3.onRenameGroup,
242
+ onPinGroup = _ref3.onPinGroup,
243
+ onDeleteGroup = _ref3.onDeleteGroup,
244
+ onCreateConversation = _ref3.onCreateConversation,
245
+ _ref3$renderItem = _ref3.renderItem,
246
+ renderItem = _ref3$renderItem === void 0 ? defaultRenderItem : _ref3$renderItem,
247
+ renderGroupHeader = _ref3.renderGroupHeader,
248
+ collapsedProp = _ref3.collapsedGroupIds,
249
+ _ref3$defaultCollapse = _ref3.defaultCollapsedGroupIds,
250
+ defaultCollapsedGroupIds = _ref3$defaultCollapse === void 0 ? [] : _ref3$defaultCollapse,
251
+ onCollapsedGroupIdsChange = _ref3.onCollapsedGroupIdsChange,
252
+ renderRestScroll = _ref3.renderRestScroll;
253
+ var grouped = Array.isArray(groups);
254
+ var resolvedPinnedTitle = pinnedSectionTitle !== undefined ? pinnedSectionTitle : grouped ? null : '置顶';
163
255
  var filterTime = filterTimeProp !== null && filterTimeProp !== void 0 ? filterTimeProp : defaultFilterTime;
164
256
  var _useControllable = useControllable(filterTypeProp, defaultFilterType, onFilterTypeChange),
165
257
  _useControllable2 = _slicedToArray(_useControllable, 2),
@@ -173,11 +265,116 @@ export function ChatList(_ref) {
173
265
  _useControllable6 = _slicedToArray(_useControllable5, 2),
174
266
  filterOpen = _useControllable6[0],
175
267
  setFilterOpen = _useControllable6[1];
268
+ var _useControllable7 = useControllable(searchProp, defaultSearch, onSearchChange),
269
+ _useControllable8 = _slicedToArray(_useControllable7, 2),
270
+ search = _useControllable8[0],
271
+ setSearch = _useControllable8[1];
272
+ var _useState3 = useState(Boolean(defaultSearch)),
273
+ _useState4 = _slicedToArray(_useState3, 2),
274
+ searchOpen = _useState4[0],
275
+ setSearchOpen = _useState4[1];
276
+ var _useControllable9 = useControllable(collapsedProp, defaultCollapsedGroupIds, onCollapsedGroupIdsChange),
277
+ _useControllable10 = _slicedToArray(_useControllable9, 2),
278
+ collapsedIds = _useControllable10[0],
279
+ setCollapsedIds = _useControllable10[1];
280
+ var _useState5 = useState(null),
281
+ _useState6 = _slicedToArray(_useState5, 2),
282
+ renamingGroupId = _useState6[0],
283
+ setRenamingGroupId = _useState6[1];
284
+ var _useState7 = useState(null),
285
+ _useState8 = _slicedToArray(_useState7, 2),
286
+ groupMenuOpenId = _useState8[0],
287
+ setGroupMenuOpenId = _useState8[1];
288
+ var _useState9 = useState(null),
289
+ _useState10 = _slicedToArray(_useState9, 2),
290
+ deletingGroup = _useState10[0],
291
+ setDeletingGroup = _useState10[1];
292
+ var searchInputRef = useRef(null);
293
+ var listBodyRef = useRef(null);
294
+ var revealUngroupedRef = useRef(false);
295
+ var _useState11 = useState({
296
+ top: false,
297
+ bottom: false
298
+ }),
299
+ _useState12 = _slicedToArray(_useState11, 2),
300
+ edgeFade = _useState12[0],
301
+ setEdgeFade = _useState12[1];
302
+ var updateEdgeFade = useCallback(function () {
303
+ var el = listBodyRef.current;
304
+ if (!el) {
305
+ setEdgeFade(function (prev) {
306
+ return prev.top || prev.bottom ? {
307
+ top: false,
308
+ bottom: false
309
+ } : prev;
310
+ });
311
+ return;
312
+ }
313
+ var top = el.scrollTop > 1;
314
+ var bottom = el.scrollHeight - el.scrollTop - el.clientHeight > 1;
315
+ setEdgeFade(function (prev) {
316
+ return prev.top === top && prev.bottom === bottom ? prev : {
317
+ top: top,
318
+ bottom: bottom
319
+ };
320
+ });
321
+ }, []);
322
+ useEffect(function () {
323
+ if (searchOpen) {
324
+ var _searchInputRef$curre, _searchInputRef$curre2;
325
+ (_searchInputRef$curre = searchInputRef.current) === null || _searchInputRef$curre === void 0 || _searchInputRef$curre.focus();
326
+ (_searchInputRef$curre2 = searchInputRef.current) === null || _searchInputRef$curre2 === void 0 || _searchInputRef$curre2.select();
327
+ }
328
+ }, [searchOpen]);
329
+ useLayoutEffect(function () {
330
+ if (!revealUngroupedRef.current) {
331
+ return;
332
+ }
333
+ var scroller = findScrollParent(listBodyRef.current);
334
+ if (!scroller) {
335
+ revealUngroupedRef.current = false;
336
+ return;
337
+ }
338
+ var collapse = scroller.querySelector('[data-odn-chat-group-section] [data-odn-chat-group-collapse]');
339
+ var finished = false;
340
+ var timer = 0;
341
+ var onEnd;
342
+ var finish = function finish() {
343
+ if (finished) {
344
+ return;
345
+ }
346
+ finished = true;
347
+ revealUngroupedRef.current = false;
348
+ if (onEnd) {
349
+ collapse === null || collapse === void 0 || collapse.removeEventListener('transitionend', onEnd);
350
+ }
351
+ window.clearTimeout(timer);
352
+ scrollUpByChatItems(scroller, CHAT_GROUP_PREVIEW_LIMIT);
353
+ };
354
+ onEnd = function onEnd(event) {
355
+ if (event instanceof TransitionEvent && event.propertyName && event.propertyName !== 'grid-template-rows') {
356
+ return;
357
+ }
358
+ finish();
359
+ };
360
+ collapse === null || collapse === void 0 || collapse.addEventListener('transitionend', onEnd);
361
+ timer = window.setTimeout(finish, UNGROUPED_EXPAND_SCROLL_MS);
362
+ return function () {
363
+ collapse === null || collapse === void 0 || collapse.removeEventListener('transitionend', onEnd);
364
+ window.clearTimeout(timer);
365
+ };
366
+ }, [collapsedIds]);
367
+ var highlightQuery = grouped && (showSearch || searchProp !== undefined) ? search.trim() : '';
176
368
  var filteredItems = useMemo(function () {
369
+ var q = highlightQuery.toLowerCase();
177
370
  return items.filter(function (item) {
178
- return matchChatListFilterTime(item.time, filterTime) && matchChatListFilterType(item.type, filterType) && matchChatListFilterStatus(item.status, filterStatus);
371
+ if (!matchChatListFilterTime(item.time, filterTime) || !matchChatListFilterType(item.type, filterType) || !matchChatListFilterStatus(item.status, filterStatus)) {
372
+ return false;
373
+ }
374
+ if (!q) return true;
375
+ return item.title.toLowerCase().includes(q);
179
376
  });
180
- }, [items, filterTime, filterType, filterStatus]);
377
+ }, [items, filterTime, filterType, filterStatus, highlightQuery]);
181
378
  var pinnedItems = useMemo(function () {
182
379
  return filteredItems.filter(function (item) {
183
380
  return item.pinned;
@@ -188,10 +385,65 @@ export function ChatList(_ref) {
188
385
  return !item.pinned;
189
386
  });
190
387
  }, [filteredItems]);
388
+ var _useMemo = useMemo(function () {
389
+ var _system$title;
390
+ var list = groups !== null && groups !== void 0 ? groups : [];
391
+ var system = list.find(function (g) {
392
+ return g.id === ungroupedGroupId;
393
+ });
394
+ var custom = list.filter(function (g) {
395
+ return g.id !== ungroupedGroupId;
396
+ });
397
+ var pinned = custom.filter(function (g) {
398
+ return g.pinned;
399
+ });
400
+ var rest = custom.filter(function (g) {
401
+ return !g.pinned;
402
+ });
403
+ return {
404
+ customGroups: [].concat(_toConsumableArray(pinned), _toConsumableArray(rest)),
405
+ resolvedUngroupedTitle: (_system$title = system === null || system === void 0 ? void 0 : system.title) !== null && _system$title !== void 0 ? _system$title : ungroupedTitle
406
+ };
407
+ }, [groups, ungroupedGroupId, ungroupedTitle]),
408
+ customGroups = _useMemo.customGroups,
409
+ resolvedUngroupedTitle = _useMemo.resolvedUngroupedTitle;
410
+ var groupOptions = useMemo(function () {
411
+ return [].concat(_toConsumableArray(customGroups.map(function (g) {
412
+ return {
413
+ id: g.id,
414
+ title: g.title
415
+ };
416
+ })), [{
417
+ id: ungroupedGroupId,
418
+ title: resolvedUngroupedTitle
419
+ }]);
420
+ }, [customGroups, ungroupedGroupId, resolvedUngroupedTitle]);
421
+ var isSearching = Boolean(highlightQuery);
422
+ var customSections = useMemo(function () {
423
+ return customGroups.map(function (group) {
424
+ return {
425
+ group: group,
426
+ items: filteredItems.filter(function (item) {
427
+ var _item$groupId;
428
+ return !item.pinned && ((_item$groupId = item.groupId) !== null && _item$groupId !== void 0 ? _item$groupId : '') === group.id;
429
+ })
430
+ };
431
+ }).filter(function (section) {
432
+ return isSearching ? section.items.length > 0 : showEmptyGroups || section.items.length > 0;
433
+ });
434
+ }, [customGroups, filteredItems, showEmptyGroups, isSearching]);
435
+ var ungroupedItems = useMemo(function () {
436
+ return filteredItems.filter(function (item) {
437
+ var _item$groupId2;
438
+ return !item.pinned && ((_item$groupId2 = item.groupId) !== null && _item$groupId2 !== void 0 ? _item$groupId2 : ungroupedGroupId) === ungroupedGroupId;
439
+ });
440
+ }, [filteredItems, ungroupedGroupId]);
441
+ var showUngrouped = grouped ? isSearching ? ungroupedItems.length > 0 : showEmptyGroups || ungroupedItems.length > 0 : false;
191
442
  var filterMenu = useMemo(function () {
192
443
  return buildFilterMenu(filterType, filterStatus);
193
444
  }, [filterType, filterStatus]);
194
445
  var renderChatItem = function renderChatItem(item) {
446
+ var _item$groupId3;
195
447
  var node = /*#__PURE__*/React.createElement(ChatItem, {
196
448
  key: item.id,
197
449
  id: item.id,
@@ -201,45 +453,117 @@ export function ChatList(_ref) {
201
453
  status: item.status,
202
454
  pinned: item.pinned,
203
455
  time: item.time,
456
+ groupId: grouped ? (_item$groupId3 = item.groupId) !== null && _item$groupId3 !== void 0 ? _item$groupId3 : ungroupedGroupId : item.groupId,
457
+ groupOptions: grouped ? groupOptions : undefined,
458
+ highlightQuery: highlightQuery || undefined,
204
459
  actionMenuZIndex: actionMenuZIndex,
205
460
  onClick: onItemClick,
206
461
  onRename: onRename,
207
462
  onPin: onPin,
463
+ onMoveToGroup: grouped ? onMoveToGroup : undefined,
208
464
  onDelete: onDelete
209
465
  });
210
- return /*#__PURE__*/React.createElement("div", {
211
- key: item.id
212
- }, renderItem(item, node));
466
+ return renderItem(item, node);
213
467
  };
214
- var hasContent = pinnedItems.length > 0 || restItems.length > 0;
215
- var pinnedSection = pinnedItems.length > 0 ? /*#__PURE__*/React.createElement("div", {
216
- "data-odn-chat-list-pinned": true
217
- }, pinnedSectionTitle !== null && pinnedSectionTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
218
- "data-odn-chat-list-pinned-title": true
219
- }, pinnedSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
220
- "data-odn-chat-list-pinned-body": true
221
- }, pinnedItems.map(renderChatItem))) : null;
222
- var restSection = restItems.length > 0 ? /*#__PURE__*/React.createElement("div", {
223
- "data-odn-chat-list-rest": true
224
- }, pinnedItems.length > 0 && recentSectionTitle !== null && recentSectionTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
225
- "data-odn-chat-list-recent-title": true
226
- }, recentSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
227
- "data-odn-chat-list-rest-body": true
228
- }, restItems.map(renderChatItem))) : null;
229
- return /*#__PURE__*/React.createElement("div", {
230
- "data-odn-chat-list": true,
231
- className: clsx(className)
232
- }, /*#__PURE__*/React.createElement("div", {
233
- "data-odn-chat-list-toolbar": true
234
- }, /*#__PURE__*/React.createElement("div", {
235
- "data-odn-chat-list-title": true
236
- }, title), /*#__PURE__*/React.createElement("div", {
237
- "data-odn-chat-list-toolbar-actions": true
238
- }, /*#__PURE__*/React.createElement(Dropdown, {
468
+ var closeSearch = function closeSearch() {
469
+ setSearch('');
470
+ setSearchOpen(false);
471
+ };
472
+ var handleAddGroup = function handleAddGroup() {
473
+ if (!onAddGroup) return;
474
+ var group = {
475
+ id: createGroupId(),
476
+ title: '新分组'
477
+ };
478
+ onAddGroup(group);
479
+ setRenamingGroupId(group.id);
480
+ setCollapsedIds(collapsedIds.filter(function (id) {
481
+ return id !== group.id;
482
+ }));
483
+ };
484
+ var renderGroupActions = function renderGroupActions(group, options) {
485
+ var _options$showMenu = options.showMenu,
486
+ showMenu = _options$showMenu === void 0 ? false : _options$showMenu,
487
+ _options$showAddConve = options.showAddConversation,
488
+ showAddConversation = _options$showAddConve === void 0 ? false : _options$showAddConve;
489
+ if (!showMenu && !showAddConversation) return null;
490
+ var menuOpen = groupMenuOpenId === group.id;
491
+ var renamable = group.renamable !== false;
492
+ var menu = showMenu ? [].concat(_toConsumableArray(renamable && onRenameGroup ? [{
493
+ value: 'rename',
494
+ label: '修改分组名称',
495
+ icon: 'pencil-line'
496
+ }] : []), _toConsumableArray(onPinGroup ? [{
497
+ value: 'pin',
498
+ label: group.pinned ? '取消置顶分组' : '置顶分组',
499
+ icon: 'arrow-up-to-line'
500
+ }] : []), _toConsumableArray(onDeleteGroup ? [{
501
+ value: 'delete',
502
+ label: '删除分组',
503
+ icon: 'trash-2'
504
+ }] : [])) : [];
505
+ return /*#__PURE__*/React.createElement(React.Fragment, null, menu.length > 0 ? /*#__PURE__*/React.createElement(HoverFill, {
506
+ bgClassName: "odn-chat-list-icon-btn-bg"
507
+ }, /*#__PURE__*/React.createElement(Dropdown, {
508
+ trigger: "click",
509
+ placement: "bottomRight",
510
+ zIndex: actionMenuZIndex,
511
+ popupClassName: "odn-dropdown-compact odn-chat-item-action-menu",
512
+ visible: menuOpen,
513
+ onVisibleChange: function onVisibleChange(open) {
514
+ setGroupMenuOpenId(open ? group.id : null);
515
+ },
516
+ menu: menu,
517
+ onSelect: function onSelect(value) {
518
+ if (value === 'rename') {
519
+ setRenamingGroupId(group.id);
520
+ setGroupMenuOpenId(null);
521
+ return;
522
+ }
523
+ if (value === 'pin') {
524
+ onPinGroup === null || onPinGroup === void 0 || onPinGroup(group.id, !group.pinned);
525
+ setGroupMenuOpenId(null);
526
+ return;
527
+ }
528
+ if (value === 'delete') {
529
+ setDeletingGroup(group);
530
+ setGroupMenuOpenId(null);
531
+ }
532
+ }
533
+ }, /*#__PURE__*/React.createElement("button", {
534
+ type: "button",
535
+ "data-odn-chat-list-icon-btn": true,
536
+ "data-odn-chat-list-group-menu": true,
537
+ "data-odn-chat-list-group-menu-open": menuOpen || undefined,
538
+ "aria-label": "\u5206\u7EC4\u64CD\u4F5C",
539
+ title: "\u5206\u7EC4\u64CD\u4F5C",
540
+ onMouseDown: function onMouseDown(e) {
541
+ return e.preventDefault();
542
+ },
543
+ onClick: function onClick(e) {
544
+ return e.stopPropagation();
545
+ }
546
+ }, /*#__PURE__*/React.createElement(Icon, {
547
+ name: "ellipsis",
548
+ size: 14
549
+ })))) : null, showAddConversation && onCreateConversation ? /*#__PURE__*/React.createElement(HoverFill, {
550
+ bgClassName: "odn-chat-list-icon-btn-bg"
551
+ }, /*#__PURE__*/React.createElement(IconActionButton, {
552
+ label: "\u65B0\u5EFA\u5BF9\u8BDD",
553
+ attr: "data-odn-chat-list-group-add-chat",
554
+ onClick: function onClick() {
555
+ return onCreateConversation(group.id);
556
+ }
557
+ }, /*#__PURE__*/React.createElement(Icon, {
558
+ name: "plus",
559
+ size: 14
560
+ }))) : null);
561
+ };
562
+ var filterTrigger = /*#__PURE__*/React.createElement(Dropdown, {
239
563
  trigger: "click",
240
564
  placement: "bottomRight",
241
565
  zIndex: filterMenuZIndex,
242
- popupClassName: "odn-chat-list-filter-menu",
566
+ popupClassName: "odn-dropdown-compact odn-chat-list-filter-menu",
243
567
  visible: filterOpen,
244
568
  onVisibleChange: setFilterOpen,
245
569
  menu: filterMenu,
@@ -260,15 +584,224 @@ export function ChatList(_ref) {
260
584
  "aria-label": "\u7B5B\u9009",
261
585
  title: "\u7B5B\u9009",
262
586
  "aria-expanded": filterOpen || undefined,
263
- "aria-pressed": filterOpen || undefined
587
+ "aria-pressed": filterOpen || undefined,
588
+ tabIndex: grouped && showSearch && searchOpen ? -1 : 0
264
589
  }, /*#__PURE__*/React.createElement(Icon, {
265
590
  name: "list-filter",
266
591
  size: 16
267
- }))))), !hasContent ? /*#__PURE__*/React.createElement("div", {
592
+ })));
593
+ var hasLeanContent = pinnedItems.length > 0 || restItems.length > 0;
594
+ var hasGroupedContent = pinnedItems.length > 0 || customSections.length > 0 || showUngrouped && ungroupedItems.length > 0 || !isSearching && (customGroups.length > 0 || showEmptyGroups);
595
+ var showGroupsModule = !isSearching || customSections.length > 0;
596
+ var renderListScroll = function renderListScroll(children) {
597
+ return /*#__PURE__*/React.createElement("div", {
598
+ "data-odn-chat-list-scroll": true
599
+ }, /*#__PURE__*/React.createElement("div", {
600
+ ref: listBodyRef,
601
+ "data-odn-chat-list-body": true,
602
+ "data-odn-hover-fill-share": grouped || undefined,
603
+ onScroll: updateEdgeFade
604
+ }, children), /*#__PURE__*/React.createElement("div", {
605
+ "aria-hidden": true,
606
+ "data-odn-chat-list-fade": "top",
607
+ "data-hidden": edgeFade.top ? undefined : ''
608
+ }), /*#__PURE__*/React.createElement("div", {
609
+ "aria-hidden": true,
610
+ "data-odn-chat-list-fade": "bottom",
611
+ "data-hidden": edgeFade.bottom ? undefined : ''
612
+ }));
613
+ };
614
+ useEffect(function () {
615
+ var el = listBodyRef.current;
616
+ if (!el) {
617
+ return;
618
+ }
619
+ updateEdgeFade();
620
+ var ro = new ResizeObserver(updateEdgeFade);
621
+ ro.observe(el);
622
+ if (el.firstElementChild) {
623
+ ro.observe(el.firstElementChild);
624
+ }
625
+ return function () {
626
+ return ro.disconnect();
627
+ };
628
+ }, [updateEdgeFade, grouped, hasGroupedContent, hasLeanContent]);
629
+ var pinnedSection = /*#__PURE__*/React.createElement(PresenceSlots, {
630
+ host: function host(content, occupied) {
631
+ return occupied ? /*#__PURE__*/React.createElement("div", {
632
+ "data-odn-chat-list-pinned": true
633
+ }, resolvedPinnedTitle !== null && resolvedPinnedTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
634
+ "data-odn-chat-list-pinned-title": true
635
+ }, resolvedPinnedTitle) : null, /*#__PURE__*/React.createElement("div", {
636
+ "data-odn-chat-list-pinned-body": true
637
+ }, content)) : null;
638
+ }
639
+ }, pinnedItems.map(renderChatItem));
640
+ var restSection = /*#__PURE__*/React.createElement(PresenceSlots, {
641
+ host: function host(content, occupied) {
642
+ return occupied ? /*#__PURE__*/React.createElement("div", {
643
+ "data-odn-chat-list-rest": true
644
+ }, pinnedItems.length > 0 && recentSectionTitle !== null && recentSectionTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
645
+ "data-odn-chat-list-recent-title": true
646
+ }, recentSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
647
+ "data-odn-chat-list-rest-body": true
648
+ }, content)) : null;
649
+ }
650
+ }, restItems.map(renderChatItem));
651
+ return /*#__PURE__*/React.createElement("div", {
652
+ "data-odn-chat-list": true,
653
+ "data-odn-chat-list-grouped": grouped || undefined,
654
+ className: clsx(className)
655
+ }, grouped && showSearch ? /*#__PURE__*/React.createElement("div", {
656
+ "data-odn-chat-list-toolbar": true,
657
+ "data-odn-chat-list-search-open": searchOpen || undefined
658
+ }, /*#__PURE__*/React.createElement("div", {
659
+ "data-odn-chat-list-toolbar-idle": true,
660
+ "aria-hidden": searchOpen || undefined
661
+ }, /*#__PURE__*/React.createElement("div", {
662
+ "data-odn-chat-list-title": true
663
+ }, title), /*#__PURE__*/React.createElement("div", {
664
+ "data-odn-chat-list-toolbar-actions": true
665
+ }, filterTrigger)), /*#__PURE__*/React.createElement("div", {
666
+ "data-odn-chat-list-search-field": true
667
+ }, /*#__PURE__*/React.createElement("button", {
668
+ type: "button",
669
+ "data-odn-chat-list-search-trigger": true,
670
+ "aria-label": "\u641C\u7D22",
671
+ "aria-expanded": searchOpen,
672
+ onMouseDown: function onMouseDown(e) {
673
+ e.currentTarget.blur();
674
+ if (!searchOpen) {
675
+ e.preventDefault();
676
+ setSearchOpen(true);
677
+ }
678
+ },
679
+ onClick: function onClick() {
680
+ var _searchInputRef$curre3;
681
+ if (searchOpen) (_searchInputRef$curre3 = searchInputRef.current) === null || _searchInputRef$curre3 === void 0 || _searchInputRef$curre3.focus();
682
+ }
683
+ }, /*#__PURE__*/React.createElement(Icon, {
684
+ name: "search",
685
+ size: 16
686
+ })), /*#__PURE__*/React.createElement("input", {
687
+ ref: searchInputRef,
688
+ "data-odn-chat-list-search-input": true,
689
+ value: search,
690
+ placeholder: "\u641C\u7D22",
691
+ tabIndex: searchOpen ? 0 : -1,
692
+ onChange: function onChange(e) {
693
+ return setSearch(e.target.value);
694
+ },
695
+ onKeyDown: function onKeyDown(e) {
696
+ if (e.key === 'Escape') {
697
+ e.preventDefault();
698
+ closeSearch();
699
+ }
700
+ }
701
+ }), /*#__PURE__*/React.createElement("button", {
702
+ type: "button",
703
+ "data-odn-chat-list-search-close": true,
704
+ "aria-label": "\u9000\u51FA\u641C\u7D22",
705
+ title: "\u9000\u51FA\u641C\u7D22",
706
+ tabIndex: searchOpen ? 0 : -1,
707
+ onMouseDown: function onMouseDown(e) {
708
+ return e.preventDefault();
709
+ },
710
+ onClick: closeSearch
711
+ }, /*#__PURE__*/React.createElement(Icon, {
712
+ name: "cancel",
713
+ size: 14
714
+ })))) : /*#__PURE__*/React.createElement("div", {
715
+ "data-odn-chat-list-toolbar": true
716
+ }, /*#__PURE__*/React.createElement("div", {
717
+ "data-odn-chat-list-title": true
718
+ }, title), /*#__PURE__*/React.createElement("div", {
719
+ "data-odn-chat-list-toolbar-actions": true
720
+ }, filterTrigger)), grouped ? !hasGroupedContent ? /*#__PURE__*/React.createElement("div", {
268
721
  "data-odn-chat-list-empty": true
269
- }, empty !== null && empty !== void 0 ? empty : null) : renderRestScroll ? /*#__PURE__*/React.createElement(React.Fragment, null, pinnedSection, restSection ? renderRestScroll(restSection) : null) : /*#__PURE__*/React.createElement("div", {
270
- "data-odn-chat-list-body": true
271
- }, pinnedSection, restSection));
722
+ }, empty !== null && empty !== void 0 ? empty : null) : renderListScroll( /*#__PURE__*/React.createElement(React.Fragment, null, pinnedSection, showGroupsModule ? /*#__PURE__*/React.createElement("div", {
723
+ "data-odn-chat-list-groups": true
724
+ }, /*#__PURE__*/React.createElement("div", {
725
+ "data-odn-chat-list-section-header": true
726
+ }, /*#__PURE__*/React.createElement("span", {
727
+ "data-odn-chat-list-section-title": true
728
+ }, groupsSectionTitle), onAddGroup ? /*#__PURE__*/React.createElement(IconActionButton, {
729
+ label: "\u65B0\u5EFA\u5206\u7EC4",
730
+ attr: "data-odn-chat-list-add-group",
731
+ onClick: handleAddGroup
732
+ }, /*#__PURE__*/React.createElement(Icon, {
733
+ name: "plus",
734
+ size: 14
735
+ })) : null), /*#__PURE__*/React.createElement(PresenceSlots, null, customSections.map(function (_ref4) {
736
+ var group = _ref4.group,
737
+ sectionItems = _ref4.items;
738
+ var collapsed = collapsedIds.includes(group.id);
739
+ var defaultTitle = group.title;
740
+ var groupTitle = renderGroupHeader ? renderGroupHeader(group, defaultTitle) : defaultTitle;
741
+ var renamable = group.renamable !== false && Boolean(onRenameGroup);
742
+ var menuOpen = groupMenuOpenId === group.id;
743
+ return /*#__PURE__*/React.createElement(ChatGroup, {
744
+ key: group.id,
745
+ folderIcon: true,
746
+ title: groupTitle,
747
+ collapsed: collapsed,
748
+ onCollapsedChange: function onCollapsedChange(next) {
749
+ setCollapsedIds(next ? Array.from(new Set([].concat(_toConsumableArray(collapsedIds), [group.id]))) : collapsedIds.filter(function (id) {
750
+ return id !== group.id;
751
+ }));
752
+ },
753
+ renaming: renamingGroupId === group.id,
754
+ onRenamingChange: function onRenamingChange(next) {
755
+ setRenamingGroupId(next ? group.id : null);
756
+ },
757
+ onRename: renamable ? function (nextTitle) {
758
+ return onRenameGroup === null || onRenameGroup === void 0 ? void 0 : onRenameGroup(group.id, nextTitle);
759
+ } : undefined,
760
+ extraVisible: menuOpen,
761
+ extra: renderGroupActions(group, {
762
+ showMenu: Boolean(onRenameGroup || onPinGroup || onDeleteGroup),
763
+ showAddConversation: Boolean(onCreateConversation)
764
+ }),
765
+ previewLimit: isSearching ? false : undefined
766
+ }, sectionItems.map(renderChatItem));
767
+ }))) : null, showUngrouped ? /*#__PURE__*/React.createElement(ChatGroup, {
768
+ title: resolvedUngroupedTitle,
769
+ section: true,
770
+ collapsed: collapsedIds.includes(ungroupedGroupId),
771
+ onCollapsedChange: function onCollapsedChange(next) {
772
+ revealUngroupedRef.current = !next;
773
+ setCollapsedIds(next ? Array.from(new Set([].concat(_toConsumableArray(collapsedIds), [ungroupedGroupId]))) : collapsedIds.filter(function (id) {
774
+ return id !== ungroupedGroupId;
775
+ }));
776
+ },
777
+ extra: renderGroupActions({
778
+ id: ungroupedGroupId,
779
+ title: resolvedUngroupedTitle,
780
+ renamable: false
781
+ }, {
782
+ showAddConversation: Boolean(onCreateConversation)
783
+ }),
784
+ previewLimit: false
785
+ }, ungroupedItems.map(renderChatItem)) : null)) : !hasLeanContent ? /*#__PURE__*/React.createElement("div", {
786
+ "data-odn-chat-list-empty": true
787
+ }, empty !== null && empty !== void 0 ? empty : null) : renderRestScroll ? /*#__PURE__*/React.createElement(React.Fragment, null, pinnedSection, restSection ? renderRestScroll(restSection) : null) : renderListScroll( /*#__PURE__*/React.createElement(React.Fragment, null, pinnedSection, restSection)), /*#__PURE__*/React.createElement(Dialog, {
788
+ visible: Boolean(deletingGroup),
789
+ onVisibleChange: function onVisibleChange(open) {
790
+ if (!open) setDeletingGroup(null);
791
+ },
792
+ contentTitle: "\u786E\u8BA4\u5220\u9664\u5206\u7EC4",
793
+ contentDesc: /*#__PURE__*/React.createElement(React.Fragment, null, "\u786E\u5B9A\u8981\u5220\u9664\u300C", deletingGroup === null || deletingGroup === void 0 ? void 0 : deletingGroup.title, "\u300D\u5417\uFF1F\u7EC4\u5185\u5BF9\u8BDD\u5C06\u79FB\u81F3\u300C", resolvedUngroupedTitle, "\u300D\uFF0C\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002"),
794
+ intent: "danger",
795
+ confirmText: "\u5220\u9664",
796
+ cancelText: "\u53D6\u6D88",
797
+ onConfirm: function onConfirm() {
798
+ if (deletingGroup) onDeleteGroup === null || onDeleteGroup === void 0 || onDeleteGroup(deletingGroup.id);
799
+ setDeletingGroup(null);
800
+ },
801
+ onCancel: function onCancel() {
802
+ return setDeletingGroup(null);
803
+ }
804
+ }));
272
805
  }
273
806
  ChatList.displayName = 'ChatList';
274
807
  export default ChatList;