BucketFilePickerState.tsx 2.7 KB

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