UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

118 lines (116 loc) 4.4 kB
'use client'; import { debounce } from '@ui5/webcomponents-react-base/utils'; import { useEffect, useRef } from 'react'; import { getProjectedWidth } from '../hooks/useColumnResizing.js'; /** * Plugin Hook that adds a callback which is fired on column resize. * * @param {event} callback Fired when the column is resized by dragging the "Resizer". * @param {Object=} options Additional options. * @param {number=} options.wait If `liveUpdate` is `true`, the resize function will fire every time the width has changed depending on the `options.wait` delay. * @param {boolean=} options.liveUpdate The number of milliseconds for which the calls are to be delayed. Defaults to `100`. */ export const useOnColumnResize = (callback, options) => { const debouncedEvent = debounce(callback, options?.wait ?? 100); // for liveUpdate mousemove/touchmove listeners have to be added via getResizerProps to fire the callback. Number of calls is defined by debounce value `wait`. const getLiveResizerProps = (props, { instance, header }) => { return { ...props, onMouseDown: e => { props.onMouseDown?.(e); const startClientX = e.clientX; const columnWidth = header.totalWidth; const columnId = header.id; const handleMouseMove = moveEvent => { const deltaX = moveEvent.clientX - startClientX; if (Math.abs(deltaX) < 3) { return; } const projectedWidth = getProjectedWidth(deltaX, columnWidth, instance.state.isRtl); const currentHeader = instance.columns.find(item => item.id === columnId); debouncedEvent({ columnWidth: projectedWidth, header: currentHeader }); }; const handleMouseUp = () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }, onTouchStart: e => { props.onTouchStart?.(e); if (e.touches && e.touches.length > 1) { return; } const startClientX = Math.round(e.touches[0].clientX); const columnWidth = header.totalWidth; const columnId = header.id; const handleTouchMove = moveEvent => { const deltaX = moveEvent.touches[0].clientX - startClientX; if (Math.abs(deltaX) < 3) { return; } const projectedWidth = getProjectedWidth(deltaX, columnWidth, instance.state.isRtl); const currentHeader = instance.columns.find(item => item.id === columnId); debouncedEvent({ columnWidth: projectedWidth, header: currentHeader }); }; const handleTouchEnd = () => { document.removeEventListener('touchmove', handleTouchMove); document.removeEventListener('touchend', handleTouchEnd); }; document.addEventListener('touchmove', handleTouchMove); document.addEventListener('touchend', handleTouchEnd); } }; }; const useInstance = instance => { const { state, columns } = instance; const { columnResizing } = state; const { isResizingColumn, columnWidths } = columnResizing; const prevHeaderIsResizing = useRef(undefined); useEffect(() => { if (options?.liveUpdate) { return () => debouncedEvent.cancel(); } }, []); useEffect(() => { if (!options?.liveUpdate) { const currentHeader = columns.find(item => item.id === prevHeaderIsResizing.current); if (isResizingColumn) { prevHeaderIsResizing.current = isResizingColumn; } if (!isResizingColumn && prevHeaderIsResizing.current) { callback({ columnWidth: columnWidths[prevHeaderIsResizing.current], header: currentHeader }); } } }, [columnResizing, columns, isResizingColumn, columnWidths]); }; const useOnColumnResizeHooks = hooks => { hooks.useFinalInstance.push(useInstance); if (options?.liveUpdate) { hooks.getResizerProps.push(getLiveResizerProps); } }; useOnColumnResizeHooks.pluginName = 'useOnColumnResize'; return useOnColumnResizeHooks; };