@ship-it-ui/ui 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3266,7 +3266,8 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
3266
3266
  });
3267
3267
  const viewportRef = (0, import_react52.useRef)(null);
3268
3268
  const internalScrollRef = (0, import_react52.useRef)(false);
3269
- const wrapInProgressRef = (0, import_react52.useRef)(false);
3269
+ const goToInProgressRef = (0, import_react52.useRef)(false);
3270
+ const wrapInFlightRef = (0, import_react52.useRef)(null);
3270
3271
  const activeIdx = active ?? 0;
3271
3272
  const domIndexFor = (0, import_react52.useCallback)((real) => isLooping ? real + 1 : real, [isLooping]);
3272
3273
  const goTo = (0, import_react52.useCallback)(
@@ -3275,13 +3276,31 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
3275
3276
  setActive(next);
3276
3277
  const node = viewportRef.current;
3277
3278
  if (node) {
3279
+ const width = node.clientWidth;
3280
+ if (isLooping && wrapInFlightRef.current !== null && width > 0) {
3281
+ const rebaseTarget = wrapInFlightRef.current === N + 1 ? 0 : wrapInFlightRef.current === 0 ? N + 1 : null;
3282
+ if (rebaseTarget !== null) {
3283
+ const rebaseSlide = node.children[rebaseTarget];
3284
+ if (rebaseSlide) {
3285
+ internalScrollRef.current = true;
3286
+ rebaseSlide.scrollIntoView({
3287
+ behavior: "instant",
3288
+ block: "nearest",
3289
+ inline: "start"
3290
+ });
3291
+ }
3292
+ }
3293
+ wrapInFlightRef.current = null;
3294
+ }
3278
3295
  const isNextWrap = loopMode === "circular" && activeIdx === N - 1 && i === activeIdx + 1;
3279
3296
  const isPrevWrap = loopMode === "circular" && activeIdx === 0 && i === activeIdx - 1;
3280
3297
  const targetDom = isNextWrap ? N + 1 : isPrevWrap ? 0 : domIndexFor(next);
3281
3298
  const slide = node.children[targetDom];
3282
3299
  if (slide) {
3283
3300
  internalScrollRef.current = true;
3284
- if (isNextWrap || isPrevWrap) wrapInProgressRef.current = true;
3301
+ goToInProgressRef.current = true;
3302
+ if (isNextWrap) wrapInFlightRef.current = N + 1;
3303
+ else if (isPrevWrap) wrapInFlightRef.current = 0;
3285
3304
  slide.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start" });
3286
3305
  }
3287
3306
  }
@@ -3296,37 +3315,54 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
3296
3315
  if (width === 0) return;
3297
3316
  const domIdx = Math.round(node.scrollLeft / width);
3298
3317
  if (!isLooping) {
3318
+ if (goToInProgressRef.current) {
3319
+ if (domIdx === activeIdx) goToInProgressRef.current = false;
3320
+ return;
3321
+ }
3299
3322
  if (domIdx !== activeIdx) setActive(domIdx);
3300
3323
  return;
3301
3324
  }
3302
3325
  if (domIdx === 0) {
3303
- if (wrapInProgressRef.current && node.scrollLeft > 1) return;
3326
+ if (goToInProgressRef.current && node.scrollLeft > 1) return;
3304
3327
  const realTwin = node.children[N];
3305
3328
  if (realTwin) {
3306
3329
  internalScrollRef.current = true;
3307
3330
  realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
3308
3331
  }
3309
3332
  if (activeIdx !== N - 1) setActive(N - 1);
3310
- wrapInProgressRef.current = false;
3333
+ goToInProgressRef.current = false;
3334
+ wrapInFlightRef.current = null;
3311
3335
  return;
3312
3336
  }
3313
3337
  if (domIdx === N + 1) {
3314
- if (wrapInProgressRef.current && node.scrollLeft < (N + 1) * width - 1) return;
3338
+ if (goToInProgressRef.current && node.scrollLeft < (N + 1) * width - 1) return;
3315
3339
  const realTwin = node.children[1];
3316
3340
  if (realTwin) {
3317
3341
  internalScrollRef.current = true;
3318
3342
  realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
3319
3343
  }
3320
3344
  if (activeIdx !== 0) setActive(0);
3321
- wrapInProgressRef.current = false;
3345
+ goToInProgressRef.current = false;
3346
+ wrapInFlightRef.current = null;
3322
3347
  return;
3323
3348
  }
3324
- if (wrapInProgressRef.current) return;
3325
3349
  const realIdx = domIdx - 1;
3350
+ if (goToInProgressRef.current) {
3351
+ if (realIdx === activeIdx) goToInProgressRef.current = false;
3352
+ return;
3353
+ }
3326
3354
  if (realIdx !== activeIdx) setActive(realIdx);
3327
3355
  };
3356
+ const onPointerDown = () => {
3357
+ goToInProgressRef.current = false;
3358
+ wrapInFlightRef.current = null;
3359
+ };
3328
3360
  node.addEventListener("scroll", onScroll, { passive: true });
3329
- return () => node.removeEventListener("scroll", onScroll);
3361
+ node.addEventListener("pointerdown", onPointerDown, { passive: true });
3362
+ return () => {
3363
+ node.removeEventListener("scroll", onScroll);
3364
+ node.removeEventListener("pointerdown", onPointerDown);
3365
+ };
3330
3366
  }, [activeIdx, isLooping, N, setActive]);
3331
3367
  (0, import_react52.useEffect)(() => {
3332
3368
  if (internalScrollRef.current) {
@@ -3462,19 +3498,32 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
3462
3498
  }
3463
3499
  )
3464
3500
  ] }),
3465
- renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "mt-2 flex gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3466
- "button",
3467
- {
3468
- type: "button",
3469
- "aria-label": `Show slide ${i + 1}`,
3470
- onClick: () => goTo(i),
3471
- className: cn(
3472
- "shrink-0 cursor-pointer overflow-hidden rounded transition-opacity",
3473
- i === activeIdx ? "ring-accent opacity-100 ring-2" : "opacity-60 hover:opacity-100"
3474
- ),
3475
- children: renderThumbnail(item, i)
3476
- },
3477
- i
3501
+ renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "-mx-0.5 mt-1.5 flex gap-2 overflow-x-auto p-0.5 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: items.map((item, i) => (
3502
+ // The active ring is applied to the rendered thumbnail (the
3503
+ // button's first child) rather than the button itself, so it
3504
+ // traces whatever border-radius the consumer's thumbnail
3505
+ // already has. Picking a fixed radius here would always be
3506
+ // wrong for one consumer or another — `rounded-lg` thumbs got
3507
+ // a 4px-radius ring; future thumbs could be circular or
3508
+ // square. `box-shadow` (what `ring-2` compiles to) follows
3509
+ // the child's `border-radius` automatically, so this is
3510
+ // self-adjusting.
3511
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3512
+ "button",
3513
+ {
3514
+ type: "button",
3515
+ "aria-label": `Show slide ${i + 1}`,
3516
+ onClick: () => goTo(i),
3517
+ "data-active": i === activeIdx ? "true" : void 0,
3518
+ className: cn(
3519
+ "shrink-0 cursor-pointer transition-opacity",
3520
+ "[&[data-active]>*]:ring-accent [&[data-active]>*]:ring-2",
3521
+ i === activeIdx ? "opacity-100" : "opacity-60 hover:opacity-100"
3522
+ ),
3523
+ children: renderThumbnail(item, i)
3524
+ },
3525
+ i
3526
+ )
3478
3527
  )) })
3479
3528
  ]
3480
3529
  }