Something went wrong. Try again.
slices images for the bsky.app photo carousel (min 5 images)
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455// carousel.js — pure carousel-swipe and crop-nudge logic (plan Step 5 +// red-team D4). The simulator component wires pointer events through these// so the swipe threshold, clamping, and keyboard nudge are unit-testable.
import { clampCropRect } from './cropViewport';
/** * Clamp a slide index into [0, n-1]. */export function clampIndex(index, n) { if (!Number.isInteger(n) || n < 1) return 0;
return Math.min(Math.max(index, 0), n - 1);}
/** * Resolve the slide index after a horizontal drag. * * @param {number} index current slide index * @param {number} dragDeltaX total pointer delta in px (positive = dragged * right / finger moved right) * @param {number} threshold px distance that triggers a slide change * @param {number} n total slides * @returns {number} new clamped index * * Dragging LEFT (deltaX < 0) reveals the NEXT slide (index+1); dragging * RIGHT (deltaX > 0) goes back (index-1). Sub-threshold drags stay put. */export function resolveIndex(index, dragDeltaX, threshold, n) { const base = clampIndex(index, n);
if (dragDeltaX <= -threshold) return clampIndex(base + 1, n);
if (dragDeltaX >= threshold) return clampIndex(base - 1, n);
return base;}
/** * Nudge a crop rect by whole pixels (red-team D4 keyboard positioning). * Delegates clamping to clampCropRect so the crop can never leave the * source. step lets Shift-arrow move in larger increments. */export function nudgeCrop(crop, dx, dy, imgW, imgH, step = 1) { return clampCropRect( { ...crop, x: crop.x + dx * step, y: crop.y + dy * step, }, imgW, imgH );}