diff --git a/src/renderer/src/components/DraggableList/__tests__/DraggableList.test.tsx b/src/renderer/src/components/DraggableList/__tests__/DraggableList.test.tsx index 2d61583787..87765a504b 100644 --- a/src/renderer/src/components/DraggableList/__tests__/DraggableList.test.tsx +++ b/src/renderer/src/components/DraggableList/__tests__/DraggableList.test.tsx @@ -71,8 +71,9 @@ describe('DraggableList', () => { }) it('should render nothing when list is empty', () => { + const emptyList: Array<{ id: string; name: string }> = [] render( - {}}> + {}}> {(item) =>
{item.name}
}
) diff --git a/src/renderer/src/components/DraggableList/__tests__/useDraggableReorder.test.ts b/src/renderer/src/components/DraggableList/__tests__/useDraggableReorder.test.ts index f2d2fe837f..a9ffd3d889 100644 --- a/src/renderer/src/components/DraggableList/__tests__/useDraggableReorder.test.ts +++ b/src/renderer/src/components/DraggableList/__tests__/useDraggableReorder.test.ts @@ -33,7 +33,7 @@ describe('useDraggableReorder', () => { originalList: mockOriginalList, filteredList: mockOriginalList, // 列表未过滤 onUpdate, - idKey: 'id' + itemKey: 'id' }) ) @@ -61,7 +61,7 @@ describe('useDraggableReorder', () => { originalList: mockOriginalList, filteredList, onUpdate, - idKey: 'id' + itemKey: 'id' }) ) @@ -89,7 +89,7 @@ describe('useDraggableReorder', () => { originalList: mockOriginalList, filteredList: mockOriginalList, onUpdate, - idKey: 'id' + itemKey: 'id' }) ) @@ -110,7 +110,7 @@ describe('useDraggableReorder', () => { originalList: mockOriginalList, filteredList: mockOriginalList, onUpdate, - idKey: 'id' + itemKey: 'id' }) ) @@ -136,7 +136,7 @@ describe('useDraggableReorder', () => { originalList: mockOriginalList, filteredList, onUpdate, - idKey: 'id' + itemKey: 'id' }) ) diff --git a/src/renderer/src/components/DraggableList/list.tsx b/src/renderer/src/components/DraggableList/list.tsx index b0e87bd2d2..fbb5f29762 100644 --- a/src/renderer/src/components/DraggableList/list.tsx +++ b/src/renderer/src/components/DraggableList/list.tsx @@ -9,7 +9,7 @@ import { ResponderProvided } from '@hello-pangea/dnd' import { droppableReorder } from '@renderer/utils' -import { FC, HTMLAttributes } from 'react' +import { HTMLAttributes, Key, useCallback } from 'react' interface Props { list: T[] @@ -17,23 +17,25 @@ interface Props { listStyle?: React.CSSProperties listProps?: HTMLAttributes children: (item: T, index: number) => React.ReactNode + itemKey?: keyof T | ((item: T) => Key) onUpdate: (list: T[]) => void onDragStart?: OnDragStartResponder onDragEnd?: OnDragEndResponder droppableProps?: Partial } -const DraggableList: FC> = ({ +function DraggableList({ children, list, style, listStyle, listProps, + itemKey, droppableProps, onDragStart, onUpdate, onDragEnd -}) => { +}: Props) { const _onDragEnd = (result: DropResult, provided: ResponderProvided) => { onDragEnd?.(result, provided) if (result.destination) { @@ -46,6 +48,17 @@ const DraggableList: FC> = ({ } } + const getId = useCallback( + (item: T) => { + if (typeof itemKey === 'function') return itemKey(item) + if (itemKey) return item[itemKey] as Key + if (typeof item === 'string') return item as Key + if (item && typeof item === 'object' && 'id' in item) return item.id as Key + return undefined + }, + [itemKey] + ) + return ( @@ -53,9 +66,9 @@ const DraggableList: FC> = ({
{list.map((item, index) => { - const id = item.id || item + const draggableId = String(getId(item) ?? index) return ( - + {(provided) => (
{ /** 用于更新原始列表状态的函数 */ onUpdate: (newList: T[]) => void /** 用于从列表项中获取唯一ID的属性名或函数 */ - idKey: keyof T | ((item: T) => Key) + itemKey: keyof T | ((item: T) => Key) } /** @@ -19,8 +19,16 @@ interface UseDraggableReorderParams { * @param params - { originalList, filteredList, onUpdate, idKey } * @returns 返回可以直接传递给 DraggableVirtualList 的 props: { onDragEnd, itemKey } */ -export function useDraggableReorder({ originalList, filteredList, onUpdate, idKey }: UseDraggableReorderParams) { - const getId = useCallback((item: T) => (typeof idKey === 'function' ? idKey(item) : (item[idKey] as Key)), [idKey]) +export function useDraggableReorder({ + originalList, + filteredList, + onUpdate, + itemKey +}: UseDraggableReorderParams) { + const getId = useCallback( + (item: T) => (typeof itemKey === 'function' ? itemKey(item) : (item[itemKey] as Key)), + [itemKey] + ) // 创建从 item ID 到其在 *原始列表* 中索引的映射 const itemIndexMap = useMemo(() => { diff --git a/src/renderer/src/components/DraggableList/virtual-list.tsx b/src/renderer/src/components/DraggableList/virtual-list.tsx index e915eec1fe..b2efe7c247 100644 --- a/src/renderer/src/components/DraggableList/virtual-list.tsx +++ b/src/renderer/src/components/DraggableList/virtual-list.tsx @@ -208,7 +208,7 @@ const VirtualRow = memo( const draggableId = String(virtualItem.key) return ( diff --git a/src/renderer/src/components/dnd/useDndReorder.ts b/src/renderer/src/components/dnd/useDndReorder.ts index 1b91507cb5..60beaf925a 100644 --- a/src/renderer/src/components/dnd/useDndReorder.ts +++ b/src/renderer/src/components/dnd/useDndReorder.ts @@ -8,7 +8,7 @@ interface UseDndReorderParams { /** 用于更新原始列表状态的函数 */ onUpdate: (newList: T[]) => void /** 用于从列表项中获取唯一ID的属性名或函数 */ - idKey: keyof T | ((item: T) => Key) + itemKey: keyof T | ((item: T) => Key) } /** @@ -18,8 +18,11 @@ interface UseDndReorderParams { * @param params - { originalList, filteredList, onUpdate, idKey } * @returns 返回可以直接传递给 Sortable 的 onSortEnd 回调 */ -export function useDndReorder({ originalList, filteredList, onUpdate, idKey }: UseDndReorderParams) { - const getId = useCallback((item: T) => (typeof idKey === 'function' ? idKey(item) : (item[idKey] as Key)), [idKey]) +export function useDndReorder({ originalList, filteredList, onUpdate, itemKey }: UseDndReorderParams) { + const getId = useCallback( + (item: T) => (typeof itemKey === 'function' ? itemKey(item) : (item[itemKey] as Key)), + [itemKey] + ) // 创建从 item ID 到其在 *原始列表* 中索引的映射 const itemIndexMap = useMemo(() => { diff --git a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx index f9f98476d9..bbd108a26b 100644 --- a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx +++ b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx @@ -55,7 +55,7 @@ const McpServersList: FC = () => { originalList: mcpServers, filteredList: filteredMcpServers, onUpdate: updateMcpServers, - idKey: 'id' + itemKey: 'id' }) const scrollRef = useRef(null) diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx index a5f2b0139e..f04f62def6 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderList.tsx @@ -321,7 +321,7 @@ const ProviderList: FC = () => { originalList: providers, filteredList: filteredProviders, onUpdate: updateProviders, - idKey: 'id' + itemKey: 'id' }) const handleDragStart = useCallback(() => {