BucketFilePickerState.tsx86 lines · main
1import { createContext, PropsWithChildren, useContext, useMemo } from 'react'
2import { proxy, useSnapshot } from 'valtio'
3
4import { StorageItemWithColumn } from '@/components/interfaces/Storage/Storage.types'
5import type { Bucket } from '@/data/storage/buckets-query'
6
7function createBucketFilePickerState({
8 bucket,
9 maxFiles,
10 acceptedFileExtensions,
11}: {
12 bucket: Bucket
13 maxFiles: number
14 acceptedFileExtensions?: string[]
15}) {
16 const state = proxy({
17 bucket: bucket,
18 maxFiles: maxFiles,
19 acceptedFileExtensions: acceptedFileExtensions,
20
21 columns: [] as string[],
22 popColumn: () => {
23 const lastColumnIndex = state.columns.length - 1
24 state.columns = state.columns.slice(0, lastColumnIndex)
25 },
26 popColumnAtIndex: (index: number) => {
27 state.columns = state.columns.slice(0, index)
28 },
29 pushColumnAtIndex: (column: string, index: number) => {
30 state.columns = state.columns.slice(0, index).concat([column])
31 },
32
33 selectedItems: [] as StorageItemWithColumn[],
34 setSelectedItems: (items: StorageItemWithColumn[]) => (state.selectedItems = items),
35 clearSelectedItems: (columnIndex?: number) => {
36 if (columnIndex !== undefined) {
37 state.selectedItems = state.selectedItems.filter((item) => item.columnIndex !== columnIndex)
38 } else {
39 state.selectedItems = []
40 }
41 },
42
43 itemSearchString: '',
44 setItemSearchString: (value: string) => (state.itemSearchString = value),
45
46 selectedFilePreview: undefined as StorageItemWithColumn | undefined,
47 setSelectedFilePreview: (file?: StorageItemWithColumn) => (state.selectedFilePreview = file),
48 })
49
50 return state
51}
52
53export type BucketFilePickerState = ReturnType<typeof createBucketFilePickerState>
54
55const DEFAULT_STATE_CONFIG = {
56 bucket: {} as Bucket,
57 maxFiles: 1 as const,
58}
59
60const BucketFilePickerStateContext = createContext<BucketFilePickerState>(
61 createBucketFilePickerState(DEFAULT_STATE_CONFIG)
62)
63
64export const BucketFilePickerStateContextProvider = ({
65 bucket,
66 maxFiles,
67 acceptedFileExtensions,
68 children,
69}: PropsWithChildren<{ bucket: Bucket; maxFiles: number; acceptedFileExtensions?: string[] }>) => {
70 const state = useMemo(
71 () => createBucketFilePickerState({ bucket, maxFiles, acceptedFileExtensions }),
72 // eslint-disable-next-line react-hooks/exhaustive-deps
73 [bucket, maxFiles, acceptedFileExtensions?.join(',')]
74 )
75
76 return (
77 <BucketFilePickerStateContext.Provider value={state}>
78 {children}
79 </BucketFilePickerStateContext.Provider>
80 )
81}
82
83export function useBucketFilePickerStateSnapshot(options?: Parameters<typeof useSnapshot>[1]) {
84 const state = useContext(BucketFilePickerStateContext)
85 return useSnapshot(state, options) as BucketFilePickerState
86}