refactor: migrate to @dnd-kit/react and simplify sortable components (#7819)

* refactor: migrate to @dnd-kit/react and simplify sortable components

* chore: enable css formatting in biome.json

* refactor(profile): simplify icon rendering logic and add alt text

* style(profiles): add overflow hidden to profile grid container

* refactor(profile): add radix for parseInt and improve type safety in profiles

* docs: update changelog with drag-and-drop styling improvements

* refactor(profile): move hasValidName function out of ProxiesEditorViewer

* refactor(proxy): refactor proxy chain into sortable components

* feat(proxy): add drop state styling and arrow animations to proxy chain

* style(profiles): reduce horizontal padding in profile grid

* feat(profile): add vertical margin to editor viewer items

* chore: refresh pnpm lockfile

* fix: preserve drag and drop behavior

---------

Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
This commit is contained in:
oomeow
2026-08-28 08:17:02 +00:00
committed by GitHub
co-authored by Tunglies
parent 181dfb87a4
commit b6de05ffe4
22 changed files with 1105 additions and 1115 deletions
+1
View File
@@ -17,3 +17,4 @@ export {
StickyVirtualList,
type StickyVirtualListHandle,
} from './sticky-virtual-list'
export { SortableItem } from './sortable-item'
+60
View File
@@ -0,0 +1,60 @@
import { useSortable } from '@dnd-kit/react/sortable'
import { useTheme } from '@mui/material'
import { type CSSProperties, type ReactNode, useCallback } from 'react'
export interface SortableItemRenderProps {
ref: (element: HTMLElement | null) => void
handleRef: (element: HTMLElement | null) => void
style: CSSProperties
}
interface SortableItemProps {
id: string
index: number
group?: string
disabled?: boolean
style?: CSSProperties
children: ReactNode | ((props: SortableItemRenderProps) => ReactNode)
}
export const SortableItem = (props: SortableItemProps) => {
const { id, index, group, disabled, children, style } = props
const { ref, handleRef, sortable, isDragging } = useSortable({
id,
index,
group,
disabled,
})
const theme = useTheme()
const setRef = useCallback(
(element: HTMLDivElement | null) => {
handleRef(element?.querySelector('[data-sortable-handle]') ?? null)
ref(element)
},
[handleRef, ref],
)
const mergedStyle: CSSProperties = {
position: 'relative',
borderRadius: 8,
...style,
...(sortable.transition && {
transition: `${sortable.transition.duration ?? 300}ms ${sortable.transition.easing ?? 'ease'} transform`,
}),
...(isDragging && {
zIndex: 100,
// 拖拽中的元素置为不透明背景,避免半透明卡片透出下层内容。 投影由全局 [data-dnd-dragging] 规则统一施加。
backgroundColor: theme.palette.background.paper,
}),
}
if (typeof children === 'function') {
return children({ ref, handleRef, style: mergedStyle })
}
return (
<div ref={setRef} style={mergedStyle}>
{children}
</div>
)
}