feat(data-table): add column visibility storage functionality for API keys, channels, and usage logs
This commit is contained in:
@@ -55,6 +55,7 @@ type DataTableStateOptions = {
|
||||
sorting?: SortingState
|
||||
onSortingChange?: OnChangeFn<SortingState>
|
||||
initialColumnVisibility?: VisibilityState
|
||||
columnVisibilityStorageKey?: string | false
|
||||
columnVisibility?: VisibilityState
|
||||
onColumnVisibilityChange?: OnChangeFn<VisibilityState>
|
||||
initialRowSelection?: RowSelectionState
|
||||
@@ -122,6 +123,32 @@ function useControllableTableState<TValue>(
|
||||
return [value, setValue]
|
||||
}
|
||||
|
||||
function readColumnVisibility(storageKey: string | undefined): VisibilityState {
|
||||
if (!storageKey || typeof window === 'undefined') return {}
|
||||
|
||||
try {
|
||||
const raw = window.localStorage.getItem(storageKey)
|
||||
if (!raw) return {}
|
||||
|
||||
const parsed = JSON.parse(raw) as unknown
|
||||
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return Object.entries(parsed).reduce<VisibilityState>(
|
||||
(visibility, [key, value]) => {
|
||||
if (typeof value === 'boolean') {
|
||||
visibility[key] = value
|
||||
}
|
||||
return visibility
|
||||
},
|
||||
{}
|
||||
)
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
const {
|
||||
data,
|
||||
@@ -144,6 +171,18 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
withExpandedRowModel = false,
|
||||
} = options
|
||||
|
||||
const columnVisibilityStorageKey =
|
||||
typeof options.columnVisibilityStorageKey === 'string'
|
||||
? options.columnVisibilityStorageKey
|
||||
: undefined
|
||||
const resolvedInitialColumnVisibility = React.useMemo(
|
||||
() => ({
|
||||
...initialColumnVisibility,
|
||||
...readColumnVisibility(columnVisibilityStorageKey),
|
||||
}),
|
||||
[columnVisibilityStorageKey, initialColumnVisibility]
|
||||
)
|
||||
|
||||
const [sorting, onSortingChange] = useControllableTableState(
|
||||
options.sorting,
|
||||
initialSorting,
|
||||
@@ -152,9 +191,13 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
const [columnVisibility, onColumnVisibilityChange] =
|
||||
useControllableTableState(
|
||||
options.columnVisibility,
|
||||
initialColumnVisibility,
|
||||
resolvedInitialColumnVisibility,
|
||||
options.onColumnVisibilityChange
|
||||
)
|
||||
const hydratedColumnVisibilityStorageKeyRef = React.useRef(
|
||||
columnVisibilityStorageKey
|
||||
)
|
||||
const skipNextColumnVisibilityPersistRef = React.useRef(false)
|
||||
const [rowSelection, onRowSelectionChange] = useControllableTableState(
|
||||
options.rowSelection,
|
||||
initialRowSelection,
|
||||
@@ -228,6 +271,43 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
ensurePageInRange?.(actualPageCount)
|
||||
}, [actualPageCount, ensurePageInRange])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (
|
||||
options.columnVisibility !== undefined ||
|
||||
columnVisibilityStorageKey ===
|
||||
hydratedColumnVisibilityStorageKeyRef.current
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
hydratedColumnVisibilityStorageKeyRef.current = columnVisibilityStorageKey
|
||||
skipNextColumnVisibilityPersistRef.current = true
|
||||
onColumnVisibilityChange(() => resolvedInitialColumnVisibility)
|
||||
}, [
|
||||
columnVisibilityStorageKey,
|
||||
onColumnVisibilityChange,
|
||||
options.columnVisibility,
|
||||
resolvedInitialColumnVisibility,
|
||||
])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!columnVisibilityStorageKey || typeof window === 'undefined') return
|
||||
|
||||
if (skipNextColumnVisibilityPersistRef.current) {
|
||||
skipNextColumnVisibilityPersistRef.current = false
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
window.localStorage.setItem(
|
||||
columnVisibilityStorageKey,
|
||||
JSON.stringify(columnVisibility)
|
||||
)
|
||||
} catch {
|
||||
// Storage can be unavailable in private mode; table controls still work.
|
||||
}
|
||||
}, [columnVisibility, columnVisibilityStorageKey])
|
||||
|
||||
return {
|
||||
table,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user