Skip to content

React

@anil-labs/file-picker-react wraps the core engine in a hook and a component. It ships with a 'use client' banner, so it works in React Server Component setups (Next.js App Router) out of the box.

Install

bash
npm i @anil-labs/file-picker-react

Quick start

The <FilePicker> component renders a ready-made trigger and selected-thumbnails strip. Options are passed as props:

tsx
import { FilePicker } from '@anil-labs/file-picker-react'
import { createMemoryAdapter } from '@anil-labs/file-picker-core'
import '@anil-labs/file-picker-core/styles.css'

const adapter = createMemoryAdapter({ media: [], folders: [] })

export function App() {
  return (
    <FilePicker
      adapter={adapter}
      multiple
      title="Media Library"
      label="Choose media"
      showSelected
      onSelect={(items) => console.log('confirmed', items)}
      onChange={(items) => console.log('selection changed', items)}
      onUpload={(items) => console.log('uploaded', items)}
    />
  )
}

<FilePicker> props

The component spreads all FilePickerOptions (adapter, multiple, title, theme, perPage, …) plus:

PropTypeDefaultDescription
labelstring'Select File'Trigger label (ignored when children is provided).
childrenReactNodeCustom trigger content; clicking it opens the picker.
showSelectedbooleantrueRender the selected-thumbnails strip.
wrapperClassstringClass for the wrapper element.
onSelect(items: MediaItem[]) => voidFires when the user confirms with Done.
onChange(items: MediaItem[]) => voidFires on every selection change.
onUpload(items: MediaItem[]) => voidFires after an upload completes.

Provide children to use your own trigger:

tsx
<FilePicker adapter={adapter} onSelect={handleSelect}>
  <button className="my-btn">Pick an image</button>
</FilePicker>

useFilePicker

For full control, use the hook and render your own UI. It creates the picker on mount (client-only) and destroys it on unmount, mirroring the selection into React state.

tsx
import { useFilePicker } from '@anil-labs/file-picker-react'

function Gallery() {
  const { open, selected, isOpen, setSelected } = useFilePicker({
    adapter,
    multiple: true,
    onSelect: (items) => console.log('confirmed', items),
  })

  return (
    <div>
      <button onClick={open}>Open library {isOpen ? '(open)' : ''}</button>
      <ul>
        {selected.map((item) => (
          <li key={item.id}>{item.filename}</li>
        ))}
      </ul>
      <button onClick={() => setSelected(null)}>Clear</button>
    </div>
  )
}

Returned controller

FieldTypeDescription
pickerFilePicker | nullThe underlying engine (null until mounted on the client).
selectedMediaItem[]The current selection (reactive state).
isOpenbooleanWhether the dialog is open.
open() => voidOpen the dialog.
close() => voidClose the dialog.
setSelected(items: MediaItem[] | MediaItem | null) => voidReplace the selection.

The hook also accepts onSelect, onChange and onUpload callbacks alongside the standard options.

Released under the MIT License.