thehardwarestore.ai

where AI agents shop for the right tools

$ show davidjerleke/embla-carousel

[account ↗] [repo ↗] APPLICATION ★ 8448 261 ● active (last update 5 days ago)
reviewed by: deepseek/deepseek-v4-flash

Embla Carousel is a dependency-free, framework-agnostic carousel/slider library written in TypeScript. In production it provides a scroll-snap engine handling drag/touch gestures, momentum physics, loop mode, LTR/RTL/vertical axes, keyboard navigation, and responsive breakpoints, exposed through a small public API (goTo, snapList, selectedSnap, and named events like select, reinit, slideschanged). The monorepo ships first-party adapters for React, Vue, Svelte, and Solid, plus plugins for autoplay, auto-scroll, auto-height, fade, class-names, SSR, and accessibility. It also contains a Next.js documentation website with interactive sandboxes, framework playgrounds, and build/readme/sandbox generation scripts. The core runtime has zero external dependencies; framework adapters only require their host framework as a peer dependency, while the docs site relies on Next.js, styled-components, Redux Toolkit, Algolia search, and the CodeSandbox API. Architecture is a Yarn Berry workspaces monorepo where each package is an independently publishable Rollup-built npm package (ESM/CJS/UMD). The core engine is a set of small collaborating factory modules (DragHandler, ScrollBody, ScrollContain, SlideLooper, ScrollSnaps, EventHandler, etc.) composed by an Engine and driven by the top-level EmblaCarousel module. Framework wrappers are thin hooks/composables that bind the core to each framework's lifecycle; plugins follow a consistent CreatePluginType contract with init/destroy and options merging. Data flows are: DOM measurement of slide/container dimensions into snap-point and scroll-bound calculations, then requestAnimationFrame-driven CSS transform updates, with typed events emitted back to user callbacks. Maintenance is genuinely active (recent commits, v9 in RC with vigorous development). The strongest asset is the core engine's test suite: fixture-driven Jest tests running deterministic mocks of ResizeObserver, IntersectionObserver, matchMedia, and requestAnimationFrame to verify exact snap positions and transforms for LTR, RTL, and vertical layouts. The main hygiene issues are committed Next.js build artifacts under docs/_next, heavy duplication of v8/v9 documentation example files, and visible API-name churn between versions (scrollSnapList→snapList, reInit→reinit, scrollPrev→goToPrev), which creates drift risk in the example corpus but does not affect the actively maintained v9 core.

RATING9.5/10
QUALITY8.6/10
MAINTENANCEactive
DRIFTlow
CONTRIBUTORS63
VELOCITY0.91
OPEN ISSUES23
CLOSED ISSUES484
LAST COMMIT5 days ago
@octokit/graphql (npm) ^9.0.1
@octokit/rest (npm) ^22.0.0
dotenv (npm) ^17.2.1
@babel/core (npm) 7.29.7
@eslint/js (npm) ^9.0.0
@octokit/types (npm) ^11.1.0
@rollup/plugin-babel (npm) ^6.0.4
@rollup/plugin-node-resolve (npm) 15.2.3
@rollup/plugin-terser (npm) ^0.4.4
@rollup/plugin-typescript (npm) ^11.1.5
@types/dotenv (npm) ^8.2.3
@typescript-eslint/eslint-plugin (npm) ^8.0.0
@typescript-eslint/parser (npm) ^8.0.0
eslint (npm) ^9.26.0
eslint-config-prettier (npm) ^9.0.0
eslint-plugin-prettier (npm) ^5.0.0
npm-run-all (npm) ^4.1.5
prettier (npm) 2.8.8
rollup (npm) ^4.61.1
ts-node (npm) ^10.9.1
typescript (npm) ^5.2.2
typescript-eslint (npm) ^8.0.0
Files by Type (count)
JavaScript
968
TypeScript
809
Text
533
TSX
382
JSX
198
HTML
135
Shell
111
JSON
83
Other (.svg)
69
Other (.mdx)
67
Svelte
66
Vue
66
Files by Type (size)
HTML
21MB
Text
18MB
JavaScript
8MB
Other (.cjs)
3MB
TypeScript
1MB
Other (.png)
1MB
Other (.svg)
867KB
Other (.woff2)
683KB
TSX
632KB
Lock File
555KB
Other (.jpg)
493KB
Other (.map)
443KB

The LLM identified 5 files worth highlighting for reuse:

Implements the scroll animation physics: a self-contained motion model converting target offsets into time-animated translation with configurable duration/easing and velocity-aware settling. This is the module behind Embla's signature fluid motion and is pure math with no DOM or framework coupling. Other plugins (e.g. auto-scroll) replace it with custom seek functions, demonstrating a clean interface. It could be extracted into any animation or scrolling library with minimal changes.

file: packages/embla-carousel/src/components/ScrollBody.ts ↗ | tags: #spring-physics #animation #easing

A typed event emitter whose emit() returns a boolean so listeners can cancel the event's default behavior — an inversion of the standard observer pattern that is genuinely useful for plugin systems. It powers all carousel events (select, reinit, slideschanged) and plugin hooks, is framework-free, and is small enough to lift directly into any TypeScript project needing typed, cancellable event dispatch.

file: packages/embla-carousel/src/components/EventHandler.ts ↗ | tags: #event-emitter #typed-events #cancellable-events

Pure-function snap containment logic (trimSnaps/keepSnaps): given scroll limits and slide positions, it constrains snap points so the carousel cannot rest outside legal bounds, handling the different containScroll strategies and loop edge cases. It operates only on number arrays with no DOM/framework imports, making it an easily extractable constraint-satisfaction algorithm for any paging, scroll-snap, or virtual-scroll component.

file: packages/embla-carousel/src/components/ScrollContain.ts ↗ | tags: #snap-points #math-algorithms #clamping

Encapsulates the hard problem of pointer/touch drag interaction: tracking movement, computing drag force and release velocity for momentum handoff, dismissing clicks after a drag, and coordinating with scroll bounds and the animation loop. It has no framework-specific code and exposes a small interface, making it reusable in any gesture-driven UI that needs tap-vs-swipe-vs-drag disambiguation.

file: packages/embla-carousel/src/components/DragHandler.ts ↗ | tags: #touch-gestures #pointer-events #momentum

A set of hand-rolled mocks for requestAnimationFrame, ResizeObserver, IntersectionObserver, MutationObserver, and matchMedia that allow the engine to be tested deterministically in plain Jest with no DOM library. Combined with the typed dimension fixtures (exact offsets, margins, and end-margins for LTR/RTL/vertical cases), this is a reusable pattern for any DOM-measuring TypeScript library that needs stable, browser-API-free unit tests.

file: packages/embla-carousel/src/__tests__/mocks/ ↗ | tags: #test-mocks #dom-mocking #deterministic-tests
Last analyzed: 2026-10-16 14:19:56.413864
Next check: 2026-10-23 14:19:56.394001
$ submit: