tableColumnResizeContext.tsx
TLDR
This file tableColumnResizeContext.tsx
is a TypeScript module that provides functionality for resizing columns in a table. It exports a context and a provider component that can be used to manage column resizing.
Methods
useColumnResize
This is a custom hook that can be used to access the column resize context. It returns an object with several functions and properties related to column resizing.
columnWidth
This is a utility function that calculates the width of a column based on its current width, offset, and a minimum column width constant.
Classes
None
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {createContext, ReactElement, ReactNode, useCallback, useContext, useMemo} from 'react'
import {Constants} from '../../constants'
export type ColumnResizeContextType = {
updateRef: (cardId: string, columnId: string, element: HTMLDivElement | null) => void
cellRef: (columnId: string) => HTMLDivElement | undefined
width: (columnId: string) => number
updateOffset: (columnId: string, offset: number) => void
updateWidth: (columnId: string, width: number) => void
}
const ColumnResizeContext = createContext<ColumnResizeContextType | null>(null)
export function useColumnResize(): ColumnResizeContextType {
const context = useContext(ColumnResizeContext)
if (!context) {
throw new Error('ColumnResizeContext is not available!')
}
return context
}
export type ColumnResizeProviderProps = {
children: ReactNode
columnWidths: Record<string, number>
onResizeColumn: (columnId: string, width: number) => void
}
const columnWidth = (columnId: string, columnWidths: Record<string, number>, offset: number): string => {
return `${Math.max(Constants.minColumnWidth, (columnWidths[columnId] || 0) + offset)}px`
}
export const ColumnResizeProvider = (props: ColumnResizeProviderProps): ReactElement => {
const {children, columnWidths, onResizeColumn} = props
type ElementsMap = Map<string, HTMLDivElement>
const columns = useMemo(() => new Map<string, ElementsMap>(), [])
const updateWidth = useCallback((columnId: string, elements: ElementsMap, offset: number) => {
const width = columnWidth(columnId, columnWidths, offset)
for (const element of elements.values()) {
element.style.width = width
}
}, [columnWidths])
const contextValue = useMemo((): ColumnResizeContextType => ({
updateRef: (cardId, columnId, element) => {
let elements = columns.get(columnId)
if (element) {
if (!elements) {
elements = new Map()
columns.set(columnId, elements)
}
elements.set(cardId, element)
} else if (elements) {
elements.delete(cardId)
}
},
cellRef: (columnId): HTMLDivElement | undefined => {
const iter = columns.get(columnId)?.values()
if (iter) {
const {value, done} = iter.next()
return done ? value : iter.next().value
}
return undefined
},
width: (columnId) => {
return Math.max(Constants.minColumnWidth, (columnWidths[columnId] || 0))
},
updateOffset: (columnId, offset) => {
const elements = columns.get(columnId)
if (elements) {
updateWidth(columnId, elements, offset)
}
},
updateWidth: (columnId, width) => {
onResizeColumn(columnId, width)
},
}), [columnWidths, onResizeColumn])
return (
<ColumnResizeContext.Provider value={contextValue}>
{children}
</ColumnResizeContext.Provider>
)
}