@atzentis/storage-react
v0.2.0
Published
Atzentis Storage React — hooks and components for api.atzentis.cloud
Maintainers
Readme
@atzentis/storage-react
React provider, hooks, and headless components for api.atzentis.cloud. Built on top of @atzentis/storage-sdk.
Installation
pnpm add @atzentis/storage-react @atzentis/storage-sdkPeer dependencies (provided by your app):
pnpm add react react-dom @tanstack/react-queryProvider
Wrap your tree once:
import { StorageProvider } from "@atzentis/storage-react";
<StorageProvider apiKey={process.env.NEXT_PUBLIC_KEY!} tenantId="t_1">
<App />
</StorageProvider>;The provider:
- Constructs a single
StorageClientper mount (useStateinitializer — SSR safe). - Validates config synchronously; misconfigured props throw
StorageConfigErrorand propagate to the nearest error boundary. - Aborts in-flight requests on unmount.
useStorageClient() returns the typed client; calling it outside a provider throws.
Hooks
| Hook | Purpose |
|---|---|
| useUpload | Single-file upload with progress, drag-drop handlers, abort on unmount |
| useFiles | Paginated file list with refetch + loadMore + filter-driven refetch |
| useFolders | Folder tree + create / move / delete with optimistic updates |
| useSearch | Debounced search with LRU cache (20 entries), hybrid or fulltext mode |
| useAnnotations | List + CRUD + reply with optimistic updates |
| useProcessing | runOcr / runEmbedding / runThumbnail — every job auto-polls; abort() cancels |
| useUsage | Quota + current usage with optional auto-refresh (clamped ≥ 5s) |
Headless components
Each component wraps the matching hook and exposes a children-as-function render prop for full custom UI:
| Component | What it does |
|---|---|
| <FileUploader> | Drag-drop zone with accept / maxSize validation |
| <FileBrowser> | Grid/list view, sort, multi-select (meta + shift), infinite scroll |
| <FolderTree> | Expand/collapse, keyboard nav, move() with self-loop guard |
| <PdfAnnotator> | Pointer-driven highlight/comment/underline tools over consumer's pdfRenderer |
| <SearchBar> | Debounced combobox with autocomplete dropdown (Arrow keys, Enter, Escape) |
Example with custom rendering:
<FileBrowser>
{(state) =>
state.files.map((file) => (
<button key={file.id} onClick={() => state.toggleSelection(file.id)}>
{file.filename}
</button>
))
}
</FileBrowser>SSR
The provider is marked 'use client' and constructs the client synchronously, so it renders cleanly under Next.js App Router and Remix. Hooks return the same instance across re-renders and concurrent callers.
License
MIT — © Atzentis
