File Upload Staging Area
moumenlab/file-upload-stagingFreeComponent
Per-tile interruptible upload state machines with capped concurrency and a layout-glide grid reflow.
Live preview
live · rendered by the registry
Rendered by moumenlab on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://lab.moumen.dev/r/file-upload-staging.jsonSource
1"use client";23import { useEffect, useImperativeHandle, useRef, useState, type Ref } from "react";4import { MotionConfig, motion } from "motion/react";56// File upload staging area - a pipeline expressed through motion.7//8// Three hard problems, none of them the dropzone:9//10// · A reflowing GRID that never jump-cuts. Tiles are motion.li with `layout`:11// removing a tile mid-grid makes every later tile glide up and across, and12// entering tiles scale + unblur in. Exits stay subtler than enters - here,13// instant.14// · An interruptible state machine PER TILE: queued → uploading → done, or15// → error frozen at the failure percent. Retry RESUMES from that percent16// (the arc never lies by rewinding), removal works in any state, and a17// freed slot immediately promotes the next queued tile - concurrency is18// capped at 2 so the pipeline is visible instead of everything blasting19// to 100% at once.20// · Honest jittered progress. One shared ticker advances every uploading21// tile by a random 0.6-4% with a 12% chance to stall a beat - variable22// like a real network - but progress NEVER moves backwards and 100% is23// the only way to complete. Failures are decided up front (a hidden24// failAt percent), not rolled per frame.25//26// TWO MODES, one pipeline:27//28// · No `upload` prop → the built-in simulation (nothing leaves the page).29// Works out of the box; `failRate` shapes the demo.30// · An `upload` adapter → REAL uploads. The component keeps owning the queue,31// concurrency, retry and removal; your adapter owns the network:32//33// <UploadStaging34// upload={async ({ file, name }, { onProgress, signal }) => {35// await api.upload(file!, { signal, onProgress }); // report 0-10036// }}37// />38//39// Resolve → done. Throw → error, frozen at the last reported percent.40// Removing a tile mid-flight aborts via the AbortSignal. Retry re-invokes41// the adapter; the arc still never rewinds (progress is forward-only, so a42// restarted transfer catches up to the frozen percent before it moves).43//44// Real drag-and-drop and the file picker both work (the original File rides45// along for the adapter); stage files programmatically through the ref handle:46//47// const staging = useRef<UploadStagingHandle>(null);48// staging.current?.addFiles([{ name: "report.pdf", size: 842_000 }]);49//50// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from moumenlab
All 14 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Caret-Anchored Mention Popovercaret-mention-popover | moumenlab | Components | Free | 1 dep | |
| Command Palette with Argument Chipscommand-palette | moumenlab | Components | Free | 1 dep | |
| Drag-to-Reorder Listdrag-to-reorder-list | moumenlab | Components | Free | 1 dep | |
| Hover-Expand Icon Striphover-expand-icon-strip | moumenlab | Components | Free | 1 dep | |
| Inertial Wheel Listinertial-wheel-list | moumenlab | Components | Free | 1 dep | |
| Morphing Checkout Flowmorphing-checkout | moumenlab | Components | Free | 1 dep | |
| OTP Segmented Inputotp-segmented-input | moumenlab | Components | Free | 1 dep | |
| Schedule Builderschedule-builder | moumenlab | Components | Free | 1 dep |
