@lobehub/lobehub 2.0.0-next.188 → 2.0.0-next.189

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/e2e/CLAUDE.md +109 -2
  4. package/e2e/docs/llm-mock.md +68 -0
  5. package/e2e/docs/local-setup.md +354 -0
  6. package/e2e/docs/testing-tips.md +94 -0
  7. package/e2e/src/features/journeys/agent/agent-conversation.feature +0 -32
  8. package/e2e/src/mocks/llm/index.ts +6 -6
  9. package/e2e/src/steps/agent/conversation.steps.ts +3 -471
  10. package/package.json +2 -2
  11. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Actions.tsx +4 -13
  12. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/index.tsx +23 -29
  13. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/useDropdownMenu.tsx +3 -3
  14. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Actions.tsx +4 -13
  15. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/index.tsx +10 -18
  16. package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/useDropdownMenu.tsx +3 -3
  17. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Sidebar/ActionButton/AddAgent.tsx +47 -27
  18. package/src/app/[variants]/(main)/community/(detail)/user/features/UserAgentCard.tsx +4 -3
  19. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/Actions.tsx +4 -13
  20. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/index.tsx +23 -29
  21. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/useDropdownMenu.tsx +3 -3
  22. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/Actions.tsx +4 -13
  23. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/index.tsx +10 -18
  24. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/TopicListContent/ThreadList/ThreadItem/useDropdownMenu.tsx +3 -3
  25. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/TopicSelector.tsx +18 -20
  26. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +19 -25
  27. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/index.tsx +21 -26
  28. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Item/Actions.tsx +4 -13
  29. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/Item/useDropdownMenu.tsx +3 -3
  30. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/Actions.tsx +4 -13
  31. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/Item.tsx +8 -15
  32. package/src/app/[variants]/(main)/home/_layout/Body/Project/List/useDropdownMenu.tsx +3 -3
  33. package/src/app/[variants]/(main)/home/_layout/Header/components/AddButton.tsx +3 -4
  34. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Actions.tsx +4 -13
  35. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/index.tsx +13 -20
  36. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/useDropdownMenu.tsx +3 -3
  37. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/Actions.tsx +4 -13
  38. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/index.tsx +16 -23
  39. package/src/app/[variants]/(main)/resource/(home)/_layout/Body/LibraryList/List/Item/useDropdownMenu.tsx +3 -3
  40. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +4 -6
  41. package/src/features/AgentBuilder/TopicSelector.tsx +18 -17
  42. package/src/features/Conversation/ChatItem/style.ts +7 -0
  43. package/src/features/Conversation/Messages/Assistant/Actions/Error.tsx +1 -3
  44. package/src/features/Conversation/Messages/Assistant/Actions/index.tsx +37 -16
  45. package/src/features/Conversation/Messages/AssistantGroup/Actions/index.tsx +36 -17
  46. package/src/features/Conversation/Messages/Supervisor/Actions/index.tsx +36 -17
  47. package/src/features/Conversation/Messages/Task/Actions/Error.tsx +1 -3
  48. package/src/features/Conversation/Messages/Task/Actions/index.tsx +31 -15
  49. package/src/features/Conversation/Messages/User/Actions/index.tsx +1 -1
  50. package/src/features/Conversation/Messages/index.tsx +8 -59
  51. package/src/features/Conversation/components/ShareMessageModal/index.tsx +1 -1
  52. package/src/features/Conversation/hooks/useChatItemContextMenu.tsx +313 -83
  53. package/src/features/NavPanel/components/NavItem.tsx +33 -3
  54. package/src/features/PageEditor/Copilot/TopicSelector/Actions.tsx +6 -14
  55. package/src/features/PageEditor/Copilot/TopicSelector/TopicItem.tsx +1 -0
  56. package/src/features/PageEditor/Copilot/TopicSelector/useDropdownMenu.tsx +6 -3
  57. package/src/features/ResourceManager/components/Explorer/ItemDropdown/DropdownMenu.tsx +12 -35
  58. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +4 -8
  59. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +162 -160
  60. package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/index.tsx +16 -8
  61. package/src/features/ResourceManager/components/Explorer/ToolBar/ActionIconWithChevron.tsx +4 -3
  62. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +6 -12
  63. package/src/features/ResourceManager/components/Explorer/ToolBar/SortDropdown.tsx +8 -8
  64. package/src/features/ResourceManager/components/Explorer/ToolBar/ViewSwitcher.tsx +8 -11
  65. package/src/features/ResourceManager/components/Tree/index.tsx +121 -122
  66. package/src/layout/GlobalProvider/index.tsx +5 -2
  67. package/src/styles/global.ts +6 -0
  68. package/src/features/Conversation/components/ContextMenu.tsx +0 -418
@@ -1,25 +1,16 @@
1
- import { ActionIcon, Dropdown, type MenuProps } from '@lobehub/ui';
1
+ import { ActionIcon, type DropdownItem, DropdownMenu } from '@lobehub/ui';
2
2
  import { MoreHorizontalIcon } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
 
5
5
  interface ActionProps {
6
- dropdownMenu: MenuProps['items'];
6
+ dropdownMenu: DropdownItem[] | (() => DropdownItem[]);
7
7
  }
8
8
 
9
9
  const Actions = memo<ActionProps>(({ dropdownMenu }) => {
10
10
  return (
11
- <Dropdown
12
- arrow={false}
13
- menu={{
14
- items: dropdownMenu,
15
- onClick: ({ domEvent }) => {
16
- domEvent.stopPropagation();
17
- },
18
- }}
19
- trigger={['click']}
20
- >
11
+ <DropdownMenu items={dropdownMenu}>
21
12
  <ActionIcon icon={MoreHorizontalIcon} size={'small'} />
22
- </Dropdown>
13
+ </DropdownMenu>
23
14
  );
24
15
  });
25
16
 
@@ -1,5 +1,5 @@
1
1
  import { type MenuProps } from '@lobehub/ui';
2
- import { useMemo } from 'react';
2
+ import { useCallback } from 'react';
3
3
 
4
4
  import { useSessionItemMenuItems } from '../../../../hooks';
5
5
 
@@ -21,7 +21,7 @@ export const useDropdownMenu = ({
21
21
  pinned,
22
22
  sessionType,
23
23
  toggleEditing,
24
- }: ActionProps): MenuProps['items'] => {
24
+ }: ActionProps): (() => MenuProps['items']) => {
25
25
  const {
26
26
  pinMenuItem,
27
27
  renameMenuItem,
@@ -31,7 +31,7 @@ export const useDropdownMenu = ({
31
31
  deleteMenuItem,
32
32
  } = useSessionItemMenuItems();
33
33
 
34
- return useMemo(
34
+ return useCallback(
35
35
  () =>
36
36
  [
37
37
  pinMenuItem(id, pinned, parentType),
@@ -1,25 +1,16 @@
1
- import { ActionIcon, Dropdown, type MenuProps } from '@lobehub/ui';
1
+ import { ActionIcon, type DropdownItem, DropdownMenu } from '@lobehub/ui';
2
2
  import { MoreHorizontalIcon } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
 
5
5
  interface ActionsProps {
6
- dropdownMenu: MenuProps['items'];
6
+ dropdownMenu: DropdownItem[] | (() => DropdownItem[]);
7
7
  }
8
8
 
9
9
  const Actions = memo<ActionsProps>(({ dropdownMenu }) => {
10
10
  return (
11
- <Dropdown
12
- arrow={false}
13
- menu={{
14
- items: dropdownMenu,
15
- onClick: ({ domEvent }) => {
16
- domEvent.stopPropagation();
17
- },
18
- }}
19
- trigger={['click']}
20
- >
11
+ <DropdownMenu items={dropdownMenu}>
21
12
  <ActionIcon icon={MoreHorizontalIcon} size={'small'} />
22
- </Dropdown>
13
+ </DropdownMenu>
23
14
  );
24
15
  });
25
16
 
@@ -1,4 +1,3 @@
1
- import { Dropdown } from '@lobehub/ui';
2
1
  import { BoxIcon } from 'lucide-react';
3
2
  import { memo, useCallback } from 'react';
4
3
 
@@ -39,20 +38,14 @@ const ProjectItem = memo<ProjectItemProps>(({ id, name }) => {
39
38
 
40
39
  return (
41
40
  <>
42
- <Dropdown
43
- menu={{
44
- items: dropdownMenu,
45
- }}
46
- trigger={['contextMenu']}
47
- >
48
- <NavItem
49
- actions={<Actions dropdownMenu={dropdownMenu} />}
50
- disabled={editing || isUpdating}
51
- icon={BoxIcon}
52
- loading={isLoading || isUpdating}
53
- title={name}
54
- />
55
- </Dropdown>
41
+ <NavItem
42
+ actions={<Actions dropdownMenu={dropdownMenu} />}
43
+ contextMenuItems={dropdownMenu}
44
+ disabled={editing || isUpdating}
45
+ icon={BoxIcon}
46
+ loading={isLoading || isUpdating}
47
+ title={name}
48
+ />
56
49
  <Editing id={id} name={name} toggleEditing={toggleEditing} />
57
50
  </>
58
51
  );
@@ -1,7 +1,7 @@
1
1
  import { Icon, type MenuProps } from '@lobehub/ui';
2
2
  import { App } from 'antd';
3
3
  import { PencilLine, Trash } from 'lucide-react';
4
- import { useMemo } from 'react';
4
+ import { useCallback } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { useKnowledgeBaseStore } from '@/store/knowledgeBase';
@@ -14,12 +14,12 @@ interface ProjectItemDropdownMenuProps {
14
14
  export const useProjectItemDropdownMenu = ({
15
15
  id,
16
16
  toggleEditing,
17
- }: ProjectItemDropdownMenuProps): MenuProps['items'] => {
17
+ }: ProjectItemDropdownMenuProps): (() => MenuProps['items']) => {
18
18
  const { t } = useTranslation(['home', 'common']);
19
19
  const [removeKnowledgeBase] = useKnowledgeBaseStore((s) => [s.removeKnowledgeBase]);
20
20
  const { modal } = App.useApp();
21
21
 
22
- return useMemo<MenuProps['items']>(
22
+ return useCallback(
23
23
  () => [
24
24
  {
25
25
  icon: <Icon icon={PencilLine} />,
@@ -1,6 +1,5 @@
1
- import { ActionIcon, Flexbox } from '@lobehub/ui';
1
+ import { ActionIcon, DropdownMenu, Flexbox } from '@lobehub/ui';
2
2
  import { CreateBotIcon } from '@lobehub/ui/icons';
3
- import { Dropdown } from 'antd';
4
3
  import { cssVar } from 'antd-style';
5
4
  import { ChevronDownIcon } from 'lucide-react';
6
5
  import React, { memo, useCallback, useMemo } from 'react';
@@ -45,7 +44,7 @@ const AddButton = memo(() => {
45
44
  size={DESKTOP_HEADER_ICON_SIZE}
46
45
  title={tChat('newAgent')}
47
46
  />
48
- <Dropdown menu={{ items: dropdownItems || [] }}>
47
+ <DropdownMenu items={dropdownItems}>
49
48
  <ActionIcon
50
49
  color={cssVar.colorTextQuaternary}
51
50
  icon={ChevronDownIcon}
@@ -54,7 +53,7 @@ const AddButton = memo(() => {
54
53
  width: 16,
55
54
  }}
56
55
  />
57
- </Dropdown>
56
+ </DropdownMenu>
58
57
  </Flexbox>
59
58
  );
60
59
  });
@@ -1,25 +1,16 @@
1
- import { ActionIcon, Dropdown, type MenuProps } from '@lobehub/ui';
1
+ import { ActionIcon, type DropdownItem, DropdownMenu } from '@lobehub/ui';
2
2
  import { MoreHorizontalIcon } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
 
5
5
  interface ActionProps {
6
- dropdownMenu: MenuProps['items'];
6
+ dropdownMenu: DropdownItem[] | (() => DropdownItem[]);
7
7
  }
8
8
 
9
9
  const Actions = memo<ActionProps>(({ dropdownMenu }) => {
10
10
  return (
11
- <Dropdown
12
- arrow={false}
13
- menu={{
14
- items: dropdownMenu,
15
- onClick: ({ domEvent }) => {
16
- domEvent.stopPropagation();
17
- },
18
- }}
19
- trigger={['click']}
20
- >
11
+ <DropdownMenu items={dropdownMenu}>
21
12
  <ActionIcon icon={MoreHorizontalIcon} size={'small'} />
22
- </Dropdown>
13
+ </DropdownMenu>
23
14
  );
24
15
  });
25
16
 
@@ -1,5 +1,4 @@
1
- import { Avatar, type MenuProps } from '@lobehub/ui';
2
- import { Dropdown } from '@lobehub/ui';
1
+ import { Avatar } from '@lobehub/ui';
3
2
  import { FileTextIcon } from 'lucide-react';
4
3
  import { memo, useCallback, useMemo } from 'react';
5
4
  import { useTranslation } from 'react-i18next';
@@ -56,7 +55,7 @@ const PageListItem = memo<DocumentItemProps>(({ pageId, className }) => {
56
55
  return FileTextIcon;
57
56
  }, [emoji]);
58
57
 
59
- const dropdownMenu: MenuProps['items'] = useDropdownMenu({
58
+ const dropdownMenu = useDropdownMenu({
60
59
  documentContent: document?.content || undefined,
61
60
  pageId,
62
61
  toggleEditing,
@@ -64,23 +63,17 @@ const PageListItem = memo<DocumentItemProps>(({ pageId, className }) => {
64
63
 
65
64
  return (
66
65
  <>
67
- <Dropdown
68
- menu={{
69
- items: dropdownMenu,
70
- }}
71
- trigger={['contextMenu']}
72
- >
73
- <NavItem
74
- actions={<Actions dropdownMenu={dropdownMenu} />}
75
- active={active}
76
- className={className}
77
- disabled={editing}
78
- icon={icon}
79
- key={pageId}
80
- onClick={handleClick}
81
- title={title}
82
- />
83
- </Dropdown>
66
+ <NavItem
67
+ actions={<Actions dropdownMenu={dropdownMenu} />}
68
+ active={active}
69
+ className={className}
70
+ contextMenuItems={dropdownMenu}
71
+ disabled={editing}
72
+ icon={icon}
73
+ key={pageId}
74
+ onClick={handleClick}
75
+ title={title}
76
+ />
84
77
  <Editing
85
78
  currentEmoji={emoji}
86
79
  documentId={pageId}
@@ -1,7 +1,7 @@
1
1
  import { Icon, type MenuProps } from '@lobehub/ui';
2
2
  import { App } from 'antd';
3
3
  import { Copy, CopyPlus, Pencil, Trash2 } from 'lucide-react';
4
- import { useMemo } from 'react';
4
+ import { useCallback } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { useFileStore } from '@/store/file';
@@ -16,7 +16,7 @@ export const useDropdownMenu = ({
16
16
  documentContent,
17
17
  pageId,
18
18
  toggleEditing,
19
- }: ActionProps): MenuProps['items'] => {
19
+ }: ActionProps): (() => MenuProps['items']) => {
20
20
  const { t } = useTranslation(['common', 'file']);
21
21
  const { message, modal } = App.useApp();
22
22
  const removeDocument = useFileStore((s) => s.removeDocument);
@@ -59,7 +59,7 @@ export const useDropdownMenu = ({
59
59
  }
60
60
  };
61
61
 
62
- return useMemo(
62
+ return useCallback(
63
63
  () =>
64
64
  [
65
65
  {
@@ -1,25 +1,16 @@
1
- import { ActionIcon, Dropdown, type MenuProps } from '@lobehub/ui';
1
+ import { ActionIcon, type DropdownItem, DropdownMenu } from '@lobehub/ui';
2
2
  import { MoreHorizontalIcon } from 'lucide-react';
3
3
  import { memo } from 'react';
4
4
 
5
5
  interface ActionProps {
6
- dropdownMenu: MenuProps['items'];
6
+ dropdownMenu: DropdownItem[] | (() => DropdownItem[]);
7
7
  }
8
8
 
9
9
  const Actions = memo<ActionProps>(({ dropdownMenu }) => {
10
10
  return (
11
- <Dropdown
12
- arrow={false}
13
- menu={{
14
- items: dropdownMenu,
15
- onClick: ({ domEvent }) => {
16
- domEvent.stopPropagation();
17
- },
18
- }}
19
- trigger={['click']}
20
- >
11
+ <DropdownMenu items={dropdownMenu}>
21
12
  <ActionIcon icon={MoreHorizontalIcon} size={'small'} />
22
- </Dropdown>
13
+ </DropdownMenu>
23
14
  );
24
15
  });
25
16
 
@@ -1,5 +1,4 @@
1
- import { Icon, type MenuProps } from '@lobehub/ui';
2
- import { Dropdown } from '@lobehub/ui';
1
+ import { Icon } from '@lobehub/ui';
3
2
  import { cssVar } from 'antd-style';
4
3
  import { Loader2Icon } from 'lucide-react';
5
4
  import React, { type CSSProperties, memo, useCallback, useMemo } from 'react';
@@ -66,33 +65,27 @@ const KnowledgeBaseItem = memo<KnowledgeBaseItemProps>(({ id, name, active, styl
66
65
  return <RepoIcon size={18} />;
67
66
  }, [isLoading]);
68
67
 
69
- const dropdownMenu: MenuProps['items'] = useDropdownMenu({
68
+ const dropdownMenu = useDropdownMenu({
70
69
  id,
71
70
  toggleEditing,
72
71
  });
73
72
 
74
73
  return (
75
74
  <>
76
- <Dropdown
77
- menu={{
78
- items: dropdownMenu,
79
- }}
80
- trigger={['contextMenu']}
81
- >
82
- <NavItem
83
- actions={<Actions dropdownMenu={dropdownMenu} />}
84
- active={active}
85
- className={className}
86
- disabled={editing}
87
- icon={icon}
88
- key={id}
89
- loading={isLoading}
90
- onClick={handleClick}
91
- onDoubleClick={handleDoubleClick}
92
- style={style}
93
- title={name}
94
- />
95
- </Dropdown>
75
+ <NavItem
76
+ actions={<Actions dropdownMenu={dropdownMenu} />}
77
+ active={active}
78
+ className={className}
79
+ contextMenuItems={dropdownMenu}
80
+ disabled={editing}
81
+ icon={icon}
82
+ key={id}
83
+ loading={isLoading}
84
+ onClick={handleClick}
85
+ onDoubleClick={handleDoubleClick}
86
+ style={style}
87
+ title={name}
88
+ />
96
89
  <Editing id={id} name={name} toggleEditing={toggleEditing} />
97
90
  </>
98
91
  );
@@ -1,7 +1,7 @@
1
1
  import { Icon, type MenuProps } from '@lobehub/ui';
2
2
  import { App } from 'antd';
3
3
  import { PencilLine, Trash } from 'lucide-react';
4
- import { useMemo } from 'react';
4
+ import { useCallback } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { useKnowledgeBaseStore } from '@/store/knowledgeBase';
@@ -11,7 +11,7 @@ interface ActionProps {
11
11
  toggleEditing: (visible?: boolean) => void;
12
12
  }
13
13
 
14
- export const useDropdownMenu = ({ id, toggleEditing }: ActionProps): MenuProps['items'] => {
14
+ export const useDropdownMenu = ({ id, toggleEditing }: ActionProps): (() => MenuProps['items']) => {
15
15
  const { t } = useTranslation(['file', 'common']);
16
16
  const { modal } = App.useApp();
17
17
  const removeKnowledgeBase = useKnowledgeBaseStore((s) => s.removeKnowledgeBase);
@@ -29,7 +29,7 @@ export const useDropdownMenu = ({ id, toggleEditing }: ActionProps): MenuProps['
29
29
  });
30
30
  };
31
31
 
32
- return useMemo(
32
+ return useCallback(
33
33
  () =>
34
34
  [
35
35
  {
@@ -1,9 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useDroppable } from '@dnd-kit/core';
4
- import { Center, Flexbox, Skeleton, Text } from '@lobehub/ui';
5
- import { Dropdown } from 'antd';
6
- import type { MenuProps } from 'antd';
4
+ import { Center, type DropdownItem, DropdownMenu, Flexbox, Skeleton, Text } from '@lobehub/ui';
7
5
  import { createStaticStyles, cx } from 'antd-style';
8
6
  import { ChevronsUpDown } from 'lucide-react';
9
7
  import { memo, useCallback, useMemo } from 'react';
@@ -81,7 +79,7 @@ const Head = memo<{ id: string }>(({ id }) => {
81
79
  [navigate, setMode],
82
80
  );
83
81
 
84
- const menuItems: MenuProps['items'] = useMemo(() => {
82
+ const menuItems = useMemo<DropdownItem[]>(() => {
85
83
  if (!libraries) return [];
86
84
 
87
85
  return libraries.map((library) => ({
@@ -120,14 +118,14 @@ const Head = memo<{ id: string }>(({ id }) => {
120
118
  </Flexbox>
121
119
  )}
122
120
  {name && (
123
- <Dropdown menu={{ items: menuItems }} placement="bottomRight" trigger={['click']}>
121
+ <DropdownMenu items={menuItems} placement="bottomRight">
124
122
  <ChevronsUpDown
125
123
  className={styles.icon}
126
124
  onClick={(e) => e.stopPropagation()}
127
125
  size={16}
128
126
  style={{ cursor: 'pointer', flex: 'none' }}
129
127
  />
130
- </Dropdown>
128
+ </DropdownMenu>
131
129
  )}
132
130
  </Flexbox>
133
131
  );
@@ -1,7 +1,5 @@
1
- import { ActionIcon, Flexbox } from '@lobehub/ui';
2
- import { Dropdown } from 'antd';
1
+ import { ActionIcon, DropdownMenu, type DropdownMenuCheckboxItem, Flexbox } from '@lobehub/ui';
3
2
  import { createStaticStyles } from 'antd-style';
4
- import type { ItemType } from 'antd/es/menu/interface';
5
3
  import dayjs from 'dayjs';
6
4
  import relativeTime from 'dayjs/plugin/relativeTime';
7
5
  import { Clock3Icon, PlusIcon } from 'lucide-react';
@@ -53,7 +51,7 @@ const TopicSelector = memo<TopicSelectorProps>(({ agentId }) => {
53
51
  [topics, activeTopicId],
54
52
  );
55
53
 
56
- const items = useMemo<ItemType[]>(
54
+ const items = useMemo<DropdownMenuCheckboxItem[]>(
57
55
  () =>
58
56
  (topics || []).map((topic) => {
59
57
  const displayTime =
@@ -62,6 +60,8 @@ const TopicSelector = memo<TopicSelectorProps>(({ agentId }) => {
62
60
  : dayjs(topic.updatedAt).format('YYYY-MM-DD');
63
61
 
64
62
  return {
63
+ checked: topic.id === activeTopicId,
64
+ closeOnClick: true,
65
65
  key: topic.id,
66
66
  label: (
67
67
  <Flexbox align="center" gap={4} horizontal justify="space-between" width="100%">
@@ -69,11 +69,17 @@ const TopicSelector = memo<TopicSelectorProps>(({ agentId }) => {
69
69
  <span className={styles.time}>{displayTime}</span>
70
70
  </Flexbox>
71
71
  ),
72
- onClick: () => switchTopic(topic.id),
72
+ onCheckedChange: (checked) => {
73
+ if (checked) {
74
+ switchTopic(topic.id);
75
+ }
76
+ },
77
+ type: 'checkbox',
73
78
  };
74
79
  }),
75
- [topics, switchTopic, styles],
80
+ [topics, switchTopic, styles, activeTopicId],
76
81
  );
82
+ const isEmpty = !topics || topics.length === 0;
77
83
 
78
84
  return (
79
85
  <NavHeader
@@ -88,19 +94,14 @@ const TopicSelector = memo<TopicSelectorProps>(({ agentId }) => {
88
94
  size={DESKTOP_HEADER_ICON_SIZE}
89
95
  title={t('actions.addNewTopic')}
90
96
  />
91
- <Dropdown
92
- disabled={!topics || topics.length === 0}
93
- menu={{
94
- items,
95
- selectedKeys: activeTopicId ? [activeTopicId] : [],
96
- style: { maxHeight: 400, overflowY: 'auto' },
97
- }}
98
- overlayStyle={{ minWidth: 280 }}
97
+ <DropdownMenu
98
+ items={items}
99
99
  placement="bottomRight"
100
- trigger={['click']}
100
+ popupProps={{ style: { maxHeight: 400, minWidth: 280, overflowY: 'auto' } }}
101
+ triggerProps={{ disabled: isEmpty }}
101
102
  >
102
- <ActionIcon disabled={!topics || topics.length === 0} icon={Clock3Icon} />
103
- </Dropdown>
103
+ <ActionIcon disabled={isEmpty} icon={Clock3Icon} />
104
+ </DropdownMenu>
104
105
  </>
105
106
  }
106
107
  showTogglePanelButton={false}
@@ -22,6 +22,13 @@ export const styles = createStaticStyles(({ css, cssVar }) => {
22
22
  display: flex;
23
23
  }
24
24
 
25
+ &:has([data-popup-open]) {
26
+ div[role='menubar'] {
27
+ pointer-events: unset;
28
+ opacity: 1;
29
+ }
30
+ }
31
+
25
32
  &:hover {
26
33
  time,
27
34
  div[role='menubar'] {
@@ -15,9 +15,7 @@ export const ErrorActionsBar = memo<ErrorActionsBarProps>(({ actions, onActionCl
15
15
  return (
16
16
  <ActionIconGroup
17
17
  items={[regenerate, del]}
18
- menu={{
19
- items: [edit, copy, divider, del],
20
- }}
18
+ menu={[edit, copy, divider, del]}
21
19
  onActionClick={onActionClick}
22
20
  />
23
21
  );
@@ -1,10 +1,16 @@
1
1
  import { type UIChatMessage } from '@lobechat/types';
2
- import { ActionIconGroup } from '@lobehub/ui';
2
+ import { ActionIconGroup, createRawModal } from '@lobehub/ui';
3
3
  import type { ActionIconGroupEvent, ActionIconGroupItemType } from '@lobehub/ui';
4
- import { memo, useCallback, useMemo, useState } from 'react';
5
-
6
- import ShareMessageModal from '../../../components/ShareMessageModal';
7
- import { messageStateSelectors, useConversationStore } from '../../../store';
4
+ import { memo, useCallback, useMemo } from 'react';
5
+
6
+ import ShareMessageModal, { type ShareModalProps } from '../../../components/ShareMessageModal';
7
+ import {
8
+ Provider,
9
+ createStore,
10
+ messageStateSelectors,
11
+ useConversationStore,
12
+ useConversationStoreApi,
13
+ } from '../../../store';
8
14
  import type {
9
15
  MessageActionItem,
10
16
  MessageActionItemOrDivider,
@@ -57,7 +63,30 @@ interface AssistantActionsBarProps {
57
63
  export const AssistantActionsBar = memo<AssistantActionsBarProps>(
58
64
  ({ actionsConfig, id, data, index }) => {
59
65
  const { error, tools } = data;
60
- const [showShareModal, setShareModal] = useState(false);
66
+ const store = useConversationStoreApi();
67
+
68
+ const handleOpenShareModal = useCallback(() => {
69
+ createRawModal(
70
+ (props: ShareModalProps) => (
71
+ <Provider
72
+ createStore={() => {
73
+ const state = store.getState();
74
+ return createStore({
75
+ context: state.context,
76
+ hooks: state.hooks,
77
+ skipFetch: state.skipFetch,
78
+ });
79
+ }}
80
+ >
81
+ <ShareMessageModal {...props} />
82
+ </Provider>
83
+ ),
84
+ {
85
+ message: data,
86
+ },
87
+ { onCloseKey: 'onCancel', openKey: 'open' },
88
+ );
89
+ }, [data, store]);
61
90
 
62
91
  const isCollapsed = useConversationStore(messageStateSelectors.isMessageCollapsed(id));
63
92
 
@@ -65,7 +94,7 @@ export const AssistantActionsBar = memo<AssistantActionsBarProps>(
65
94
  data,
66
95
  id,
67
96
  index,
68
- onOpenShareModal: () => setShareModal(true),
97
+ onOpenShareModal: handleOpenShareModal,
69
98
  });
70
99
 
71
100
  const hasTools = !!tools;
@@ -174,17 +203,9 @@ export const AssistantActionsBar = memo<AssistantActionsBarProps>(
174
203
  [allActions],
175
204
  );
176
205
 
177
- const shareOnCancel = useCallback(() => {
178
- setShareModal(false);
179
- }, []);
180
206
  if (error) return <ErrorActionsBar actions={defaultActions} onActionClick={handleAction} />;
181
207
 
182
- return (
183
- <>
184
- <ActionIconGroup items={items} menu={{ items: menu }} onActionClick={handleAction} />
185
- <ShareMessageModal message={data} onCancel={shareOnCancel} open={showShareModal} />
186
- </>
187
- );
208
+ return <ActionIconGroup items={items} menu={menu} onActionClick={handleAction} />;
188
209
  },
189
210
  );
190
211