@oslokommune/punkt-react
Version:
React komponentbibliotek til Punkt, et designsystem laget av Oslo Origo
55 lines (48 loc) • 2.14 kB
text/typescript
import { useCallback, useMemo } from 'react'
import { FileItem, TFileAttributes, TFileId, TFileItemList, TQueueOperationContext } from '../types'
/**
* Build accessors that let queue-item operations read and write per-file
* attributes without ever mutating the current `value` list. All changes are
* propagated via `onFileUpdated`, so controlled parents stay authoritative.
*/
export const useFileAttributes = (
value: TFileItemList,
onFileUpdated: (fileId: TFileId, updates: Partial<FileItem>) => void,
) => {
const getAttributeForFile = useCallback(
<T>(fileId: TFileId, attributeName: string): T | undefined => {
const fileItem = value.find((file) => file.fileId === fileId)
return fileItem?.attributes?.[attributeName] as T | undefined
},
[value],
)
const setAttributeForFile = useCallback(
(fileId: TFileId, attributeName: string, attributeValue: unknown) => {
const fileItem = value.find((file) => file.fileId === fileId)
if (!fileItem) return
const nextAttributes = { ...fileItem.attributes, [attributeName]: attributeValue }
if (attributeValue === undefined) {
delete nextAttributes[attributeName]
}
onFileUpdated(fileId, { attributes: nextAttributes as FileItem['attributes'] })
},
[onFileUpdated, value],
)
const fileAttributes: TFileAttributes = useMemo(
() =>
<T>(attributeName: string) => ({
get: (fileId: TFileId) => getAttributeForFile<T>(fileId, attributeName),
set: (fileId: TFileId, attributeValue: T | undefined) =>
setAttributeForFile(fileId, attributeName, attributeValue),
}),
[getAttributeForFile, setAttributeForFile],
)
const buildAttributeAccessors = useCallback(
(fileId: TFileId): Pick<TQueueOperationContext, 'getAttribute' | 'setAttribute'> => ({
getAttribute: <T>(name: string) => getAttributeForFile<T>(fileId, name),
setAttribute: (name, attributeValue) => setAttributeForFile(fileId, name, attributeValue),
}),
[getAttributeForFile, setAttributeForFile],
)
return { fileAttributes, buildAttributeAccessors } as const
}