# Carousel

A scroll-snap strip with drag, loop and autoplay, built on your own markup.

Package: @reuse-sh/carousel

## Principles

These are the rules to keep when you adapt this library. The code is one way to keep them. An adaptation on any framework must keep every one.

- Let the browser scroll. Touch and trackpads scroll natively with CSS scroll snap, and every move from code is a scroll too.

- Never let a drag click. A mouse drag never opens the link under it, an ordinary click still works, and touch stays native.

- Repeat without clones. The loop moves the original slides, so ids, links and buttons stay unique, and it turns on only when the slides can cover the viewport.

- Let autoplay wait for people. Autoplay pauses for hover, focus, dragging, hidden pages, offscreen strips and reduced motion.

- Keep keys local. Arrow keys act only inside the focused strip and swap sides in right-to-left layouts.

- Put back what it moved. Destroy cancels timers and restores the styles, transforms and listeners it added.

## Install

```bash
npm install @reuse-sh/carousel
```

## Integration notes

- The loop needs enough slides to cover the viewport plus the widest slide. With fewer, isLooping is false and the strip scrolls normally.

- That check runs again after a resize or a content change.

- Autoplay pauses for hover, focus, dragging, hidden pages, offscreen strips and reduced motion.

## API

- `createCarousel(viewport, options?)`: Binds a scroll-snap strip. Options: slides, align, loop, drag, group, autoplay, releaseMotion, releaseDuration, onChange.

- `releaseMotion`: How a released mouse drag travels to its slide. "spring" starts at the drag speed and eases in; "native" uses the browser's smooth scroll. Both pick the same slide. "spring" by default; reduced motion jumps.

- `releaseDuration`: How long the spring glide takes, in milliseconds. 260 by default.

- `next(), prev(), goTo(index, behavior?)`: Moves by one group or to a slide. goTo takes an optional scroll behavior.

- `getState(), subscribe(listener)`: Index, count, progress, canPrev, canNext, and whether it is playing, dragging or looping.

- `play(), pause()`: Starts and stops autoplay. It also waits for hover, focus, drag and hidden tabs on its own.

- `setEnabled(enabled)`: Turns scrolling and dragging off and back on, keeping the current position.

- `refresh()`: Measures again after slides are added or removed.

- `destroy()`: Removes listeners and restores the viewport.

- `syncCarousels(...carousels)`: Keeps several carousels on the same index. Returns a function that stops it.

## Browser JavaScript

```js
import { createCarousel } from "@reuse-sh/carousel";
import "@reuse-sh/carousel/styles.css";

const viewport = document.querySelector(".reuse-carousel");
const carousel = createCarousel(viewport, { loop: true, align: "start" });

const render = (state) => {
  counter.textContent = state.index + 1 + " / " + state.count;
};
carousel.subscribe(render);
render(carousel.getState());

// Later, when the strip leaves the page
carousel.destroy();
```

## React

```tsx
import { useCarousel } from "@reuse-sh/carousel/react";
import "@reuse-sh/carousel/styles.css";

export function Strip({ photos }) {
  const { ref, carousel } = useCarousel({ loop: true });
  return (
    <div>
      <div ref={ref} className="reuse-carousel">
        {photos.map((photo) => (
          <img key={photo.src} src={photo.src} alt={photo.alt} data-carousel-slide />
        ))}
      </div>
      <button onClick={() => carousel?.next()}>Next</button>
    </div>
  );
}
```

## Agent workflow

1. Inspect the project and read the installed package's types and stylesheet.

2. Reuse the native controller. Use the React adapter only in a React surface.

3. Adapt styles and data connections to the project. Keep every principle above. Do not recreate the gesture or state engine.

4. Connect destroy and unsubscribe callbacks to the owner lifecycle.

5. Verify keyboard access, pointer/touch behavior, resize, empty/one-item states, errors, reduced motion, and teardown where applicable.

6. Report the actual checks and remaining browser/device limits.

## Source

https://github.com/reuse-sh/reuse/tree/main/packages/carousel/src

License: MIT for original library code. Preserve dependency and asset license notices.
