UNPKG

@coveord/plasma-mantine

Version:

A Plasma flavoured Mantine theme

266 lines (265 loc) 8.45 kB
import { useDidUpdate } from '@mantine/hooks'; import defaultsDeep from 'lodash.defaultsdeep'; import { useCallback, useMemo, useState } from 'react'; import { useUrlSyncedState } from './use-url-synced-state'; const defaultOptions = { enableRowSelection: true, enableMultiRowSelection: false, forceSelection: false, syncWithUrl: false }; const defaultState = { pagination: { pageIndex: 0, pageSize: 50 }, totalEntries: null, sorting: [], globalFilter: '', predicates: {}, layout: null, dateRange: [ null, null ], rowSelection: {}, columnVisibility: {} }; const serialization = (input)=>Object.freeze(input); const PAGINATION_SERIALIZATION = serialization({ serializer: ({ pageIndex, pageSize })=>[ [ 'page', (pageIndex + 1).toString() ], [ 'pageSize', pageSize.toString() ] ], deserializer: (params, initialState)=>defaultsDeep({ pageIndex: params.get('page') ? Math.max(1, parseInt(params.get('page'), 10)) - 1 : undefined, pageSize: params.get('pageSize') ? parseInt(params.get('pageSize'), 10) : undefined }, initialState) }); const SORTING_SERIALIZATION = serialization({ serializer: (sorting)=>[ [ 'sortBy', sorting.map(({ id, desc })=>`${id}.${desc ? 'desc' : 'asc'}`).join(',') ] ], deserializer: (params, initialState)=>{ if (!params.has('sortBy')) { return initialState; } const sorts = params.get('sortBy')?.split(',') ?? []; return sorts.map((sort)=>{ const [id, order] = sort.split('.'); return { id, desc: order === 'desc' }; }); } }); const GLOBAL_FILTER_SERIALIZATION = serialization({ serializer: (filter)=>[ [ 'filter', filter ] ], deserializer: (params, initialState)=>params.get('filter') ?? initialState }); const PREDICATES_SERIALIZATION = serialization({ serializer: (predicates)=>Object.entries(predicates), deserializer: (params, initialState)=>Object.keys(initialState).reduce((acc, predicateKey)=>{ acc[predicateKey] = params.get(predicateKey) ?? initialState[predicateKey]; return acc; }, {}) }); const LAYOUT_SERIALIZATION = serialization({ serializer: (_layout)=>[ [ 'layout', _layout ] ], deserializer: (params, initialState)=>params.get('layout') ?? initialState }); const DATE_RANGE_SERIALIZATION = serialization({ serializer: ([from, to])=>[ [ 'from', from?.toISOString() ?? '', true ], [ 'to', to?.toISOString() ?? '', true ] ], deserializer: (params, initial)=>[ params.get('from') ? new Date(params.get('from')) : initial[0], params.get('to') ? new Date(params.get('to')) : initial[1] ] }); const COLUMN_VISIBILITY_SERIALIZATION = serialization({ serializer: (columns)=>[ [ 'show', Object.entries(columns).filter(([, visible])=>visible === true).map(([columnName])=>columnName).join(',') ], [ 'hide', Object.entries(columns).filter(([, visible])=>visible === false).map(([columnName])=>columnName).join(',') ] ], deserializer: (params, initial)=>{ if (!params.has('show') && !params.has('hide')) { return initial; } const visible = params.get('show')?.split(',') ?? []; const invisible = params.get('hide')?.split(',') ?? []; const columns = {}; visible.forEach((column)=>{ columns[column] = true; }); invisible.forEach((column)=>{ columns[column] = false; }); return columns; } }); export const useTable = (userOptions = {})=>{ const options = defaultsDeep({}, userOptions, defaultOptions); const initialState = defaultsDeep({}, options.initialState, defaultState); /** * The `useUrlSyncedState` hook defaults to synchronize, but the table wants to default to not synchronize, * so always pass the sync option as a resolved boolean value. */ const sync = !!options.syncWithUrl; // (Optionally) synced with url const [pagination, setPagination] = useUrlSyncedState({ ...PAGINATION_SERIALIZATION, initialState: initialState.pagination, sync }); const [sorting, setSorting] = useUrlSyncedState({ ...SORTING_SERIALIZATION, initialState: initialState.sorting, sync }); const [globalFilter, setGlobalFilter] = useUrlSyncedState({ ...GLOBAL_FILTER_SERIALIZATION, initialState: initialState.globalFilter, sync }); const [predicates, setPredicates] = useUrlSyncedState({ ...PREDICATES_SERIALIZATION, initialState: initialState.predicates, sync }); const [layout, setLayout] = useUrlSyncedState({ ...LAYOUT_SERIALIZATION, initialState: initialState.layout, sync }); const [dateRange, setDateRange] = useUrlSyncedState({ ...DATE_RANGE_SERIALIZATION, initialState: initialState.dateRange, sync }); const [columnVisibility, setColumnVisibility] = useUrlSyncedState({ ...COLUMN_VISIBILITY_SERIALIZATION, initialState: initialState.columnVisibility, sync }); // unsynced const [totalEntries, _setTotalEntries] = useState(initialState.totalEntries); const [unfilteredTotalEntries, setUnfilteredTotalEntries] = useState(initialState.totalEntries); const [expanded, setExpanded] = useState(initialState.expanded); const [rowSelection, setRowSelection] = useState(initialState.rowSelection); const isFiltered = !!globalFilter || Object.keys(predicates).some((predicate)=>!!predicates[predicate]) || !!dateRange?.[0] || !!dateRange?.[1]; const isVacant = unfilteredTotalEntries === 0; const setTotalEntries = useCallback((updater)=>{ _setTotalEntries((old)=>{ const newTotalEntries = updater instanceof Function ? updater(old) : updater; if (!isFiltered) { setUnfilteredTotalEntries(newTotalEntries); } return newTotalEntries; }); }, [ isFiltered ]); const clearFilters = useCallback(()=>{ setPredicates(initialState.predicates); setGlobalFilter(''); }, []); const clearRowSelection = useCallback(()=>{ setRowSelection({}); }, []); const getSelectedRows = useCallback(()=>Object.values(rowSelection), [ rowSelection ]); const getSelectedRow = ()=>getSelectedRows()[0] ?? null; useDidUpdate(()=>{ if (!options.enableMultiRowSelection) { clearRowSelection(); } }, [ globalFilter, pagination, sorting, dateRange, predicates ]); const state = useMemo(()=>({ pagination, totalEntries, sorting, globalFilter, expanded, predicates, layout, dateRange, rowSelection, columnVisibility }), [ pagination, totalEntries, sorting, globalFilter, expanded, predicates, layout, dateRange, rowSelection, columnVisibility ]); return { state, setPagination, setTotalEntries, setSorting, setGlobalFilter, setExpanded, setPredicates, setLayout, setDateRange, setRowSelection, setColumnVisibility, isFiltered, isVacant, clearFilters, clearRowSelection, getSelectedRows, getSelectedRow, rowSelectionEnabled: options.enableRowSelection, rowSelectionForced: options.forceSelection, multiRowSelectionEnabled: options.enableMultiRowSelection }; }; //# sourceMappingURL=use-table.js.map