KQ-1110 · FLING/SORT
Fling Sort
A sorting tray you throw things into: grab the top chip of the inbox or of any bin and it lifts 1:1 under the finger; let go and it flies with the hand's speed on a real trajectory with gravity, air drag and spin, bouncing off rims, walls and the frame until it lands in the bin it reaches. The landing is heard, counted and reported on the frame the chip touches down with too little rebound to leave, then it docks into its pile on springs.glide carrying its landing speed, and the count rolls in on springs.snap. Number keys throw the focused box's top chip into that bin on a solved arc and 0 throws it back to the inbox.
Number keys 1 to 3 throw the top item into that bin; 0 throws it back to the inbox.
0 of 6 filed · throw a receipt into a bin
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/fling-sort
Props
- items
- FlingSortItem[]
- default —
- Everything to sort: { id, label, detail? }. Keep labels to a word; detail is a short second line such as an amount.
- categories
- FlingSortCategory[]
- default —
- The bins, in order: { id, label }. The first `bins` of them stand on the floor.
- bins
- number
- default 3
- How many of categories are open, 2 to 4. Items filed under a bin that is not shown sit in the inbox.
- value / defaultValue
- Record<string, string>
- default {}
- The filing, item id to category id; an item that is absent is in the inbox. Controlled or uncontrolled.
- onValueChange
- (value: Record<string, string>, change: { item: string; bin: string | null }) => void
- default —
- Fires on the frame a throw is decided, with the whole filing and what changed (bin null: back to the inbox). A controlled chip docks wherever the host's value says once it settles, so a refused change flies home.
- label
- string
- default —
- The tray's accessible name.
- gravity
- number
- default 2000
- Downward pull in px/s², 800 to 3200: low values float long, lazy arcs; high ones drop the chip fast and short.
- bounce
- number
- default 0.4
- Restitution off the floor, rims and walls, 0 to 0.8: dead-stop landings at 0, lively rebounds near 0.8.
- drag
- number
- default 0.8
- Air drag per second, 0 to 3: at 0 a throw carries far, at 3 it dies in the air and drops short.
- height
- number
- default 200
- Tray height in px.
- sound
- boolean
- default false
- Play the throw's synthesised sounds: a paper rustle on pickup, a whoosh by speed on release, a rim clang, a thunk on a bin landing and a thud on the floor. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the tray and blocks throws and keys.
- className
- string
- default —
- Merged onto the tray's classes.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | FlingSortItem[] | — | Everything to sort: { id, label, detail? }. Keep labels to a word; detail is a short second line such as an amount. |
| categories | FlingSortCategory[] | — | The bins, in order: { id, label }. The first `bins` of them stand on the floor. |
| bins | number | 3 | How many of categories are open, 2 to 4. Items filed under a bin that is not shown sit in the inbox. |
| value / defaultValue | Record<string, string> | {} | The filing, item id to category id; an item that is absent is in the inbox. Controlled or uncontrolled. |
| onValueChange | (value: Record<string, string>, change: { item: string; bin: string | null }) => void | — | Fires on the frame a throw is decided, with the whole filing and what changed (bin null: back to the inbox). A controlled chip docks wherever the host's value says once it settles, so a refused change flies home. |
| label | string | — | The tray's accessible name. |
| gravity | number | 2000 | Downward pull in px/s², 800 to 3200: low values float long, lazy arcs; high ones drop the chip fast and short. |
| bounce | number | 0.4 | Restitution off the floor, rims and walls, 0 to 0.8: dead-stop landings at 0, lively rebounds near 0.8. |
| drag | number | 0.8 | Air drag per second, 0 to 3: at 0 a throw carries far, at 3 it dies in the air and drops short. |
| height | number | 200 | Tray height in px. |
| sound | boolean | false | Play the throw's synthesised sounds: a paper rustle on pickup, a whoosh by speed on release, a rim clang, a thunk on a bin landing and a thud on the floor. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the tray and blocks throws and keys. |
| className | string | — | Merged onto the tray's classes. |