React
usePicker, renderSlots, and two-way binding.
The adapter is a subpath of the same package. Nothing extra to install.
import { usePicker } from 'loopem/react'
export function Gallery({ photos }) {
const { containerRef, selectedItem, renderSlots } = usePicker({
items: photos,
layout: 'arc',
radius: 900,
})
return (
<>
<img src={selectedItem?.full} alt="" />
<div className="picker" ref={containerRef}>
{renderSlots((photo) => (
<button className="thumb">
<img src={photo.thumb} alt="" />
</button>
))}
</div>
</>
)
}renderSlots portals your nodes into the slots the picker owns and positions.
Your components are ordinary React; loopem never renders their contents.
What you get back
containerRef · activeIndex · activeItem · selectedIndex ·
selectedItem · scrollTo · next · previous · select · seek ·
play · pause · renderSlots
Bind cheap things to activeItem and expensive ones to selectedItem. There is
no update, because the items option drives it.
Two-way binding
Pass selectedIndex and onSelect and the picker is controlled, exactly the way
value and onChange control an <input>:
const [chosen, setChosen] = useState(0)
const { containerRef, renderSlots } = usePicker({
items: dates,
selectedIndex: chosen,
onSelect: setChosen,
})selectedIndex decides where the track starts and the track follows it on
every change, so setting state from a link, a saved booking or a server response
moves the picker. Omit it and the picker owns its own selection from
initialIndex.
Notes
containerRefis typed structurally, not as React’sRefObject, because that is spelled differently across major versions. It is assignable torefin 18 and 19 alike.- Preact needs nothing:
loopem/reactworks underpreact/compat. - Working code: the React gallery and the date picker.