mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
194 lines
4.3 KiB
JavaScript
194 lines
4.3 KiB
JavaScript
import React from 'react'
|
|
|
|
import {
|
|
actions,
|
|
reducerHandlers,
|
|
defaultColumn,
|
|
getFirstDefined,
|
|
mergeProps,
|
|
applyPropHooks,
|
|
} from '../utils'
|
|
|
|
const pluginName = 'useResizeColumns'
|
|
|
|
// Default Column
|
|
defaultColumn.canResize = true
|
|
|
|
// Actions
|
|
actions.columnStartResizing = 'columnStartResizing'
|
|
actions.columnResizing = 'columnResizing'
|
|
actions.columnDoneResizing = 'columnDoneResizing'
|
|
|
|
// Reducer
|
|
reducerHandlers[pluginName] = (state, action) => {
|
|
if (action.type === actions.init) {
|
|
return {
|
|
columnResizing: {
|
|
columnWidths: {},
|
|
},
|
|
...state,
|
|
}
|
|
}
|
|
|
|
if (action.type === actions.columnStartResizing) {
|
|
const { clientX, columnId, columnWidth, headerIdWidths } = action
|
|
|
|
return {
|
|
...state,
|
|
columnResizing: {
|
|
...state.columnResizing,
|
|
startX: clientX,
|
|
headerIdWidths,
|
|
columnWidth,
|
|
isResizingColumn: columnId,
|
|
},
|
|
}
|
|
}
|
|
|
|
if (action.type === actions.columnResizing) {
|
|
const { clientX } = action
|
|
const { startX, columnWidth, headerIdWidths } = state.columnResizing
|
|
|
|
const deltaX = clientX - startX
|
|
const percentageDeltaX = deltaX / columnWidth
|
|
|
|
const newColumnWidths = {}
|
|
|
|
headerIdWidths.forEach(([headerId, headerWidth]) => {
|
|
newColumnWidths[headerId] = Math.max(
|
|
headerWidth + headerWidth * percentageDeltaX,
|
|
0
|
|
)
|
|
})
|
|
|
|
return {
|
|
...state,
|
|
columnResizing: {
|
|
...state.columnResizing,
|
|
columnWidths: {
|
|
...state.columnResizing.columnWidths,
|
|
...newColumnWidths,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
if (action.type === actions.columnDoneResizing) {
|
|
return {
|
|
...state,
|
|
columnResizing: {
|
|
...state.columnResizing,
|
|
startX: null,
|
|
isResizingColumn: null,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
export const useResizeColumns = hooks => {
|
|
hooks.useInstanceBeforeDimensions.push(useInstanceBeforeDimensions)
|
|
}
|
|
|
|
useResizeColumns.pluginName = pluginName
|
|
|
|
const useInstanceBeforeDimensions = instance => {
|
|
instance.hooks.getResizerProps = []
|
|
|
|
const {
|
|
flatHeaders,
|
|
disableResizing,
|
|
hooks: { getHeaderProps },
|
|
state: { columnResizing },
|
|
dispatch,
|
|
} = instance
|
|
|
|
getHeaderProps.push(() => {
|
|
return {
|
|
style: {
|
|
position: 'relative',
|
|
},
|
|
}
|
|
})
|
|
|
|
const onMouseDown = (e, header) => {
|
|
const headersToResize = getLeafHeaders(header)
|
|
const headerIdWidths = headersToResize.map(d => [d.id, d.totalWidth])
|
|
|
|
const clientX = e.clientX
|
|
|
|
const onMouseMove = e => {
|
|
const clientX = e.clientX
|
|
|
|
dispatch({ type: actions.columnResizing, clientX })
|
|
}
|
|
|
|
const onMouseUp = e => {
|
|
document.removeEventListener('mousemove', onMouseMove)
|
|
document.removeEventListener('mouseup', onMouseUp)
|
|
|
|
dispatch({ type: actions.columnDoneResizing })
|
|
}
|
|
|
|
document.addEventListener('mousemove', onMouseMove)
|
|
document.addEventListener('mouseup', onMouseUp)
|
|
|
|
dispatch({
|
|
type: actions.columnStartResizing,
|
|
columnId: header.id,
|
|
columnWidth: header.totalWidth,
|
|
headerIdWidths,
|
|
clientX,
|
|
})
|
|
}
|
|
|
|
// use reference to avoid memory leak in #1608
|
|
const instanceRef = React.useRef()
|
|
instanceRef.current = instance
|
|
|
|
flatHeaders.forEach(header => {
|
|
const canResize = getFirstDefined(
|
|
header.disableResizing === true ? false : undefined,
|
|
disableResizing === true ? false : undefined,
|
|
true
|
|
)
|
|
|
|
header.canResize = canResize
|
|
header.width = columnResizing.columnWidths[header.id] || header.width
|
|
header.isResizing = columnResizing.isResizingColumn === header.id
|
|
|
|
if (canResize) {
|
|
header.getResizerProps = userProps => {
|
|
return mergeProps(
|
|
{
|
|
onMouseDown: e => e.persist() || onMouseDown(e, header),
|
|
style: {
|
|
cursor: 'ew-resize',
|
|
},
|
|
draggable: false,
|
|
},
|
|
applyPropHooks(
|
|
instanceRef.current.hooks.getResizerProps,
|
|
header,
|
|
instanceRef.current
|
|
),
|
|
userProps
|
|
)
|
|
}
|
|
}
|
|
})
|
|
|
|
return instance
|
|
}
|
|
|
|
function getLeafHeaders(header) {
|
|
const leafHeaders = []
|
|
const recurseHeader = header => {
|
|
if (header.columns && header.columns.length) {
|
|
header.columns.map(recurseHeader)
|
|
}
|
|
leafHeaders.push(header)
|
|
}
|
|
recurseHeader(header)
|
|
return leafHeaders
|
|
}
|