main

mattermost/focalboard

Last updated at: 29/12/2023 09:44

sortable.tsx

TLDR

The sortable.tsx file in the Demo Projects project contains several custom hooks (useSortable, useSortableWithGrip) that provide functionality for implementing draggable and sortable items in a React application. These hooks use the react-dnd library for drag and drop functionality.

Methods

No methods in this file.

Classes

No classes in this file.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useRef} from 'react'
import {useDrag, useDrop, DragElementWrapper, DragSourceOptions, DragPreviewOptions} from 'react-dnd'

import {IContentBlockWithCords} from '../blocks/contentBlock'
import {Block} from '../blocks/block'
interface ISortableWithGripItem {
    block: Block | Block[]
    cords: {x: number, y?: number, z?: number}
}

function useSortableBase<T>(itemType: string, item: T, enabled: boolean, handler: (src: T, st: T) => void): [boolean, boolean, DragElementWrapper<DragSourceOptions>, DragElementWrapper<DragSourceOptions>, DragElementWrapper<DragPreviewOptions>] {
    const [{isDragging}, drag, preview] = useDrag(() => ({
        type: itemType,
        item,
        collect: (monitor) => ({
            isDragging: monitor.isDragging(),
        }),
        canDrag: () => enabled,
    }), [itemType, item, enabled])
    const [{isOver}, drop] = useDrop(() => ({
        accept: itemType,
        collect: (monitor) => ({
            isOver: monitor.isOver(),
        }),
        drop: (dragItem: T) => {
            handler(dragItem, item)
        },
        canDrop: () => enabled,
    }), [item, handler, enabled])

    return [isDragging, isOver, drag, drop, preview]
}

export function useSortable<T>(itemType: string, item: T, enabled: boolean, handler: (src: T, st: T) => void): [boolean, boolean, React.RefObject<HTMLDivElement>] {
    const ref = useRef<HTMLDivElement>(null)
    const [isDragging, isOver, drag, drop] = useSortableBase(itemType, item, enabled, handler)
    drop(drag(ref))
    return [isDragging, isOver, ref]
}

export function useSortableWithGrip(itemType: string, item: ISortableWithGripItem, enabled: boolean, handler: (src: IContentBlockWithCords, st: IContentBlockWithCords) => void): [boolean, boolean, React.RefObject<HTMLDivElement>, React.RefObject<HTMLDivElement>] {
    const ref = useRef<HTMLDivElement>(null)
    const previewRef = useRef<HTMLDivElement>(null)
    const [isDragging, isOver, drag, drop, preview] = useSortableBase(itemType, item as IContentBlockWithCords, enabled, handler)
    drag(ref)
    drop(preview(previewRef))
    return [isDragging, isOver, ref, previewRef]
}