All Downloads are FREE. Search and download functionalities are using the official Maven repository.

components.Table.provider.ToolbarOverlay.tsx Maven / Gradle / Ivy

The newest version!
/* eslint-disable @typescript-eslint/no-explicit-any */
import { createContext, useContext } from 'use-context-selector'
import React, {
    FC,
    MouseEvent,
    useCallback,
    useMemo,
    useRef,
    useState,
    RefObject,
} from 'react'
import { createPortal } from 'react-dom'

import useClickOutside from '../../../core/hooks/useClickOutside'

type OverlayContext = {
    onShowOverlay?(event: MouseEvent, model: any): void
    onHideOverlay?(): void
}
type OverlayProps = {
    overlay?: {
        className?: string
        toolbar: Array<{
            id: string
            buttons: Array<{
                component: FC
                id: string
                [x: string]: any
            }>
        }>
    }
    refContainerElem: RefObject
    onClickActionButton(data: any): void
}

const overlayContext = createContext({})

const WithOverlay: FC> = ({
    children,
    overlay,
    refContainerElem,
    onClickActionButton,
}) => {
    const { toolbar, className } = overlay
    const isDisabledToggleFunc = useRef(false)
    const rowElem = useRef()
    const model = useRef({})
    const [isVisibleOverlay, setIsVisibleOverlay] = useState(false)
    const overlayContainerRef = useRef(null)

    const methods = useMemo(() => ({
        onShowOverlay(event: MouseEvent, data: any) {
            const overlay = overlayContainerRef.current
            const container = refContainerElem.current

            if (!overlay || !container || isDisabledToggleFunc.current) {
                return
            }

            const row = event.currentTarget
            const rowParam = row.getBoundingClientRect()
            const tableContainerParam = container.getBoundingClientRect()

            rowElem.current = row
            setIsVisibleOverlay(true)
            model.current = data
            overlay.style.display = 'flex'
            overlay.style.top = `${rowParam.top + rowParam.height}px`
            overlay.style.left = `${tableContainerParam.left}px`
            overlay.style.width = `${tableContainerParam.width}px`
        },
        onHideOverlay() {
            const overlay = overlayContainerRef.current

            if (!overlay || isDisabledToggleFunc.current) {
                return
            }

            if (rowElem.current) {
                rowElem.current.dataset.overlayHovered = 'false'
            }

            setIsVisibleOverlay(false)
        },
    }), [refContainerElem])

    const onPinOverlay = () => {
        isDisabledToggleFunc.current = true
    }

    const continueShowOverlay = () => {
        const overlay = overlayContainerRef.current

        if (!overlay) {
            return
        }

        if (rowElem.current) {
            rowElem.current.dataset.overlayHovered = 'true'
        }

        overlay.style.display = 'flex'
        setIsVisibleOverlay(true)
    }

    const unPinOverlay = useCallback(() => {
        isDisabledToggleFunc.current = false
    }, [])

    const onOutsideClick = useCallback(() => {
        unPinOverlay()
        methods.onHideOverlay()
    }, [methods, unPinOverlay])

    const onClickActionButtonCallback = useCallback(() => {
        unPinOverlay()
        onClickActionButton(model.current)
    }, [onClickActionButton, unPinOverlay])

    useClickOutside(onOutsideClick, [overlayContainerRef])

    return (
        
            {children}
            {createPortal(
                (
                    
{isVisibleOverlay ? (
{toolbar.map(({ id, buttons }) => ( {buttons.map(({ component: ButtonComponent, id, ...props }) => ( ))} ))}
) : null}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion ), document.querySelector('#n2o')!, )}
) } export const ToolbarOverlay: FC = ({ children, overlay, ...props }) => ( // eslint-disable-next-line react/jsx-no-useless-fragment <> {overlay ? ( {children} ) : children} ) ToolbarOverlay.displayName = 'ToolbarOverlay' export const useToolbarOverlay = () => useContext(overlayContext)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy