fix: dragging works correctly

This commit is contained in:
Aarnav Tale 2024-03-28 19:40:06 -04:00
parent 358629a93b
commit 5df9be1b8e
No known key found for this signature in database
3 changed files with 113 additions and 105 deletions

View File

@ -1,13 +1,13 @@
/* eslint-disable unicorn/no-keyword-prefix */ /* eslint-disable unicorn/no-keyword-prefix */
import { import {
closestCenter, closestCorners,
DndContext, DndContext,
DragOverlay, DragOverlay
PointerSensor,
TouchSensor,
useSensor,
useSensors
} from '@dnd-kit/core' } from '@dnd-kit/core'
import {
restrictToParentElement,
restrictToVerticalAxis
} from '@dnd-kit/modifiers'
import { import {
arrayMove, arrayMove,
SortableContext, SortableContext,
@ -16,9 +16,9 @@ import {
} from '@dnd-kit/sortable' } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities' import { CSS } from '@dnd-kit/utilities'
import { Bars3Icon } from '@heroicons/react/24/outline' import { Bars3Icon } from '@heroicons/react/24/outline'
import { useFetcher, useRevalidator } from '@remix-run/react' import { useFetcher } from '@remix-run/react'
import clsx from 'clsx' import clsx from 'clsx'
import { useState } from 'react' import { useEffect, useState } from 'react'
type Properties = { type Properties = {
readonly baseDomain?: string; readonly baseDomain?: string;
@ -31,12 +31,10 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
const [localDomains, setLocalDomains] = useState(searchDomains) const [localDomains, setLocalDomains] = useState(searchDomains)
const [newDomain, setNewDomain] = useState('') const [newDomain, setNewDomain] = useState('')
const fetcher = useFetcher({ key: 'search-domains' }) const fetcher = useFetcher({ key: 'search-domains' })
const revalidator = useRevalidator()
const sensors = useSensors( useEffect(() => {
useSensor(PointerSensor), setLocalDomains(searchDomains)
useSensor(TouchSensor) }, [searchDomains])
)
return ( return (
<div className='flex flex-col w-2/3'> <div className='flex flex-col w-2/3'>
@ -45,21 +43,9 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
Set custom DNS search domains for your Tailnet. Set custom DNS search domains for your Tailnet.
When using Magic DNS, your tailnet domain is used as the first search domain. When using Magic DNS, your tailnet domain is used as the first search domain.
</p> </p>
<div className='border border-gray-200 rounded-lg bg-gray-50 overflow-clip'>
{baseDomain ? (
<div
key='magic-dns-sd'
className={clsx(
'flex items-center justify-between px-3 py-2',
'border-b border-gray-200 last:border-b-0'
)}
>
<p className='font-mono text-sm'>{baseDomain}</p>
</div>
) : undefined}
<DndContext <DndContext
sensors={sensors} modifiers={[restrictToVerticalAxis, restrictToParentElement]}
collisionDetection={closestCenter} collisionDetection={closestCorners}
onDragStart={event => { onDragStart={event => {
setActiveId(event.active.id) setActiveId(event.active.id)
}} }}
@ -86,6 +72,18 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
} }
}} }}
> >
<div className='border border-gray-200 rounded-lg bg-gray-50 overflow-clip'>
{baseDomain ? (
<div
key='magic-dns-sd'
className={clsx(
'flex items-center justify-between px-3 py-2',
'border-b border-gray-200 last:border-b-0'
)}
>
<p className='font-mono text-sm'>{baseDomain}</p>
</div>
) : undefined}
<SortableContext <SortableContext
items={localDomains} items={localDomains}
strategy={verticalListSortingStrategy} strategy={verticalListSortingStrategy}
@ -94,7 +92,6 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
// eslint-disable-next-line react/no-array-index-key // eslint-disable-next-line react/no-array-index-key
<Domain key={index} domain={sd} id={index + 1} localDomains={localDomains}/> <Domain key={index} domain={sd} id={index + 1} localDomains={localDomains}/>
))} ))}
</SortableContext>
<DragOverlay adjustScale> <DragOverlay adjustScale>
{activeId ? <Domain {activeId ? <Domain
isDrag isDrag
@ -103,7 +100,7 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
id={activeId as number - 1} id={activeId as number - 1}
/> : undefined} /> : undefined}
</DragOverlay> </DragOverlay>
</DndContext> </SortableContext>
<div <div
key='add-sd' key='add-sd'
className={clsx( className={clsx(
@ -134,15 +131,13 @@ export default function Domains({ baseDomain, searchDomains }: Properties) {
}) })
setNewDomain('') setNewDomain('')
if (revalidator.state === 'idle') {
revalidator.revalidate()
}
}} }}
> >
Add Add
</button> </button>
</div> </div>
</div> </div>
</DndContext>
</div> </div>
) )
} }
@ -156,7 +151,6 @@ type DomainProperties = {
function Domain({ domain, id, localDomains, isDrag }: DomainProperties) { function Domain({ domain, id, localDomains, isDrag }: DomainProperties) {
const fetcher = useFetcher({ key: 'individual-domain' }) const fetcher = useFetcher({ key: 'individual-domain' })
const revalidator = useRevalidator()
const { const {
attributes, attributes,
@ -174,17 +168,19 @@ function Domain({ domain, id, localDomains, isDrag }: DomainProperties) {
'flex items-center justify-between px-3 py-2', 'flex items-center justify-between px-3 py-2',
'border-b border-gray-200 last:border-b-0', 'border-b border-gray-200 last:border-b-0',
isDragging ? 'text-gray-400' : 'bg-gray-50', isDragging ? 'text-gray-400' : 'bg-gray-50',
isDrag ? 'outline outline-1 outline-gray-500 rounded-md' : undefined isDrag ? 'outline outline-1 outline-gray-500' : undefined
)} )}
style={{ style={{
transform: CSS.Transform.toString(transform), transform: CSS.Transform.toString(transform),
transition transition
}} }}
{...attributes}
{...listeners}
> >
<p className='font-mono text-sm flex items-center gap-4'> <p className='font-mono text-sm flex items-center gap-4'>
<Bars3Icon className='h-4 w-4 text-gray-400'/> <Bars3Icon
className='h-4 w-4 text-gray-400 focus:outline-none'
{...attributes}
{...listeners}
/>
{domain} {domain}
</p> </p>
{isDrag ? undefined : ( {isDrag ? undefined : (
@ -199,10 +195,6 @@ function Domain({ domain, id, localDomains, isDrag }: DomainProperties) {
method: 'PATCH', method: 'PATCH',
encType: 'application/json' encType: 'application/json'
}) })
if (revalidator.state === 'idle') {
revalidator.revalidate()
}
}} }}
> >
Remove Remove

View File

@ -12,6 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@dnd-kit/core": "^6.1.0", "@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0", "@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2", "@dnd-kit/utilities": "^3.2.2",
"@headlessui/react": "^1.7.18", "@headlessui/react": "^1.7.18",

15
pnpm-lock.yaml generated
View File

@ -8,6 +8,9 @@ dependencies:
'@dnd-kit/core': '@dnd-kit/core':
specifier: ^6.1.0 specifier: ^6.1.0
version: 6.1.0(react-dom@18.2.0)(react@18.2.0) version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
'@dnd-kit/modifiers':
specifier: ^7.0.0
version: 7.0.0(@dnd-kit/core@6.1.0)(react@18.2.0)
'@dnd-kit/sortable': '@dnd-kit/sortable':
specifier: ^8.0.0 specifier: ^8.0.0
version: 8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0) version: 8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0)
@ -462,6 +465,18 @@ packages:
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/@dnd-kit/modifiers@7.0.0(@dnd-kit/core@6.1.0)(react@18.2.0):
resolution: {integrity: sha512-BG/ETy3eBjFap7+zIti53f0PCLGDzNXyTmn6fSdrudORf+OH04MxrW4p5+mPu4mgMk9kM41iYONjc3DOUWTcfg==}
peerDependencies:
'@dnd-kit/core': ^6.1.0
react: '>=16.8.0'
dependencies:
'@dnd-kit/core': 6.1.0(react-dom@18.2.0)(react@18.2.0)
'@dnd-kit/utilities': 3.2.2(react@18.2.0)
react: 18.2.0
tslib: 2.6.2
dev: false
/@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0): /@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0)(react@18.2.0):
resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==} resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==}
peerDependencies: peerDependencies: