metacubexd/src/components/ConnectionsModal.tsx
2023-09-01 13:39:26 +08:00

109 lines
3.0 KiB
TypeScript

import type {
DragEventHandler,
Draggable,
Droppable,
} from '@thisbeyond/solid-dnd'
import {
DragDropProvider,
DragDropSensors,
DragOverlay,
SortableProvider,
closestCenter,
createSortable,
useDragDropContext,
} from '@thisbeyond/solid-dnd'
import { For, createSignal } from 'solid-js'
import { AccessorKey } from '~/config/connection'
type ColumnVisibility = Partial<Record<AccessorKey, boolean>>
type ColumnOrder = AccessorKey[]
export default (props: {
order: ColumnOrder
visible: ColumnVisibility
onOrderChange: (value: ColumnOrder) => void
onVisibleChange: (value: ColumnVisibility) => void
}) => {
const [activeKey, setActiveKey] = createSignal<AccessorKey | null>(null)
const onDragStart = ({ draggable }: { draggable: Draggable }) =>
setActiveKey(draggable.id as AccessorKey)
const onDragEnd = ({
draggable,
droppable,
}: {
draggable: Draggable
droppable: Droppable
}) => {
if (draggable && droppable) {
const currentItems = props.order
const fromIndex = currentItems.indexOf(draggable.id as AccessorKey)
const toIndex = currentItems.indexOf(droppable.id as AccessorKey)
if (fromIndex !== toIndex) {
const updatedItems = currentItems.slice()
updatedItems.splice(toIndex, 0, ...updatedItems.splice(fromIndex, 1))
props.onOrderChange(updatedItems)
}
}
}
const FormRow = (p: { key: AccessorKey }) => {
const key = p.key
const sortable = createSortable(key)
const [state] = useDragDropContext()!
return (
<div
use:sortable
class="sortable"
classList={{
'opacity-25': sortable.isActiveDraggable,
'transition-transform': !!state.active.draggable,
}}
>
<div class="m-1 flex cursor-grab justify-between p-1">
<span class="select-none">{key}</span>
<input
type="checkbox"
class="toggle"
checked={props.visible[key]}
onChange={(e) => {
props.onVisibleChange({
...props.visible,
[key]: e.target.checked,
})
}}
/>
</div>
</div>
)
}
return (
<>
<input type="checkbox" id="connection-modal" class="modal-toggle" />
<div class="modal">
<div class="modal-box w-80">
<DragDropProvider
onDragStart={onDragStart}
onDragEnd={onDragEnd as DragEventHandler}
collisionDetector={closestCenter}
>
<DragDropSensors />
<div class="column self-stretch">
<SortableProvider ids={props.order}>
<For each={props.order}>{(key) => <FormRow key={key} />}</For>
</SortableProvider>
</div>
<DragOverlay>
<div class="sortable">{activeKey()}</div>
</DragOverlay>
</DragDropProvider>
</div>
<label class="modal-backdrop" for="connection-modal" />
</div>
</>
)
}