@ship-it-ui/ui 0.0.10 → 0.0.11
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 +128 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +129 -38
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3251,27 +3251,36 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
|
|
|
3251
3251
|
aspectRatio = 16 / 10,
|
|
3252
3252
|
showDots = true,
|
|
3253
3253
|
showArrows = true,
|
|
3254
|
+
loop = false,
|
|
3254
3255
|
className,
|
|
3255
3256
|
"aria-label": ariaLabel = "Carousel",
|
|
3256
3257
|
...props
|
|
3257
3258
|
}, ref) {
|
|
3259
|
+
const N = items.length;
|
|
3260
|
+
const isLooping = loop && N > 1;
|
|
3258
3261
|
const [active, setActive] = useControllableState({
|
|
3259
3262
|
value: indexProp,
|
|
3260
3263
|
defaultValue: defaultIndex ?? 0,
|
|
3261
3264
|
onChange: onIndexChange
|
|
3262
3265
|
});
|
|
3263
3266
|
const viewportRef = (0, import_react52.useRef)(null);
|
|
3267
|
+
const internalScrollRef = (0, import_react52.useRef)(false);
|
|
3268
|
+
const activeIdx = active ?? 0;
|
|
3269
|
+
const domIndexFor = (0, import_react52.useCallback)((real) => isLooping ? real + 1 : real, [isLooping]);
|
|
3264
3270
|
const goTo = (0, import_react52.useCallback)(
|
|
3265
3271
|
(i) => {
|
|
3266
|
-
const
|
|
3267
|
-
setActive(
|
|
3272
|
+
const next = isLooping ? (i % N + N) % N : Math.max(0, Math.min(N - 1, i));
|
|
3273
|
+
setActive(next);
|
|
3268
3274
|
const node = viewportRef.current;
|
|
3269
3275
|
if (node) {
|
|
3270
|
-
const slide = node.children[
|
|
3271
|
-
slide
|
|
3276
|
+
const slide = node.children[domIndexFor(next)];
|
|
3277
|
+
if (slide) {
|
|
3278
|
+
internalScrollRef.current = true;
|
|
3279
|
+
slide.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start" });
|
|
3280
|
+
}
|
|
3272
3281
|
}
|
|
3273
3282
|
},
|
|
3274
|
-
[
|
|
3283
|
+
[N, isLooping, domIndexFor, setActive]
|
|
3275
3284
|
);
|
|
3276
3285
|
(0, import_react52.useEffect)(() => {
|
|
3277
3286
|
const node = viewportRef.current;
|
|
@@ -3279,13 +3288,59 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
|
|
|
3279
3288
|
const onScroll = () => {
|
|
3280
3289
|
const width = node.clientWidth;
|
|
3281
3290
|
if (width === 0) return;
|
|
3282
|
-
const
|
|
3283
|
-
if (
|
|
3291
|
+
const domIdx = Math.round(node.scrollLeft / width);
|
|
3292
|
+
if (!isLooping) {
|
|
3293
|
+
if (domIdx !== activeIdx) setActive(domIdx);
|
|
3294
|
+
return;
|
|
3295
|
+
}
|
|
3296
|
+
if (domIdx === 0) {
|
|
3297
|
+
const realTwin = node.children[N];
|
|
3298
|
+
if (realTwin) {
|
|
3299
|
+
internalScrollRef.current = true;
|
|
3300
|
+
realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3301
|
+
}
|
|
3302
|
+
if (activeIdx !== N - 1) setActive(N - 1);
|
|
3303
|
+
return;
|
|
3304
|
+
}
|
|
3305
|
+
if (domIdx === N + 1) {
|
|
3306
|
+
const realTwin = node.children[1];
|
|
3307
|
+
if (realTwin) {
|
|
3308
|
+
internalScrollRef.current = true;
|
|
3309
|
+
realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3310
|
+
}
|
|
3311
|
+
if (activeIdx !== 0) setActive(0);
|
|
3312
|
+
return;
|
|
3313
|
+
}
|
|
3314
|
+
const realIdx = domIdx - 1;
|
|
3315
|
+
if (realIdx !== activeIdx) setActive(realIdx);
|
|
3284
3316
|
};
|
|
3285
3317
|
node.addEventListener("scroll", onScroll, { passive: true });
|
|
3286
3318
|
return () => node.removeEventListener("scroll", onScroll);
|
|
3287
|
-
}, [
|
|
3288
|
-
|
|
3319
|
+
}, [activeIdx, isLooping, N, setActive]);
|
|
3320
|
+
(0, import_react52.useEffect)(() => {
|
|
3321
|
+
if (internalScrollRef.current) {
|
|
3322
|
+
internalScrollRef.current = false;
|
|
3323
|
+
return;
|
|
3324
|
+
}
|
|
3325
|
+
const node = viewportRef.current;
|
|
3326
|
+
if (!node) return;
|
|
3327
|
+
const width = node.clientWidth;
|
|
3328
|
+
if (width === 0) return;
|
|
3329
|
+
const targetDom = domIndexFor(activeIdx);
|
|
3330
|
+
const currentDom = Math.round(node.scrollLeft / width);
|
|
3331
|
+
if (currentDom === targetDom) return;
|
|
3332
|
+
const slide = node.children[targetDom];
|
|
3333
|
+
slide?.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3334
|
+
}, [activeIdx, domIndexFor]);
|
|
3335
|
+
(0, import_react52.useLayoutEffect)(() => {
|
|
3336
|
+
if (!isLooping) return;
|
|
3337
|
+
const node = viewportRef.current;
|
|
3338
|
+
if (!node) return;
|
|
3339
|
+
const slide = node.children[domIndexFor(activeIdx)];
|
|
3340
|
+
if (!slide) return;
|
|
3341
|
+
internalScrollRef.current = true;
|
|
3342
|
+
slide.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3343
|
+
}, [isLooping]);
|
|
3289
3344
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3290
3345
|
"div",
|
|
3291
3346
|
{
|
|
@@ -3297,34 +3352,58 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
|
|
|
3297
3352
|
...props,
|
|
3298
3353
|
children: [
|
|
3299
3354
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "relative overflow-hidden rounded-md", children: [
|
|
3300
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3301
3356
|
"div",
|
|
3302
3357
|
{
|
|
3303
3358
|
ref: viewportRef,
|
|
3304
3359
|
className: "flex w-full snap-x snap-mandatory overflow-x-auto scroll-smooth [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
3305
3360
|
"aria-live": "polite",
|
|
3306
|
-
children:
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3361
|
+
children: [
|
|
3362
|
+
isLooping && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3363
|
+
"div",
|
|
3364
|
+
{
|
|
3365
|
+
"aria-hidden": "true",
|
|
3366
|
+
tabIndex: -1,
|
|
3367
|
+
className: "w-full shrink-0 snap-start",
|
|
3368
|
+
style: { aspectRatio: String(aspectRatio) },
|
|
3369
|
+
children: renderItem(items[N - 1], N - 1)
|
|
3370
|
+
},
|
|
3371
|
+
"clone-start"
|
|
3372
|
+
),
|
|
3373
|
+
items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3374
|
+
"div",
|
|
3375
|
+
{
|
|
3376
|
+
className: "w-full shrink-0 snap-start",
|
|
3377
|
+
style: { aspectRatio: String(aspectRatio) },
|
|
3378
|
+
role: "group",
|
|
3379
|
+
"aria-roledescription": "slide",
|
|
3380
|
+
"aria-label": `${i + 1} of ${N}`,
|
|
3381
|
+
children: renderItem(item, i)
|
|
3382
|
+
},
|
|
3383
|
+
i
|
|
3384
|
+
)),
|
|
3385
|
+
isLooping && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3386
|
+
"div",
|
|
3387
|
+
{
|
|
3388
|
+
"aria-hidden": "true",
|
|
3389
|
+
tabIndex: -1,
|
|
3390
|
+
className: "w-full shrink-0 snap-start",
|
|
3391
|
+
style: { aspectRatio: String(aspectRatio) },
|
|
3392
|
+
children: renderItem(items[0], 0)
|
|
3393
|
+
},
|
|
3394
|
+
"clone-end"
|
|
3395
|
+
)
|
|
3396
|
+
]
|
|
3318
3397
|
}
|
|
3319
3398
|
),
|
|
3320
|
-
showArrows &&
|
|
3399
|
+
showArrows && N > 1 && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
|
|
3321
3400
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3322
3401
|
"button",
|
|
3323
3402
|
{
|
|
3324
3403
|
type: "button",
|
|
3325
3404
|
"aria-label": "Previous slide",
|
|
3326
3405
|
onClick: () => goTo(activeIdx - 1),
|
|
3327
|
-
disabled: activeIdx === 0,
|
|
3406
|
+
disabled: !isLooping && activeIdx === 0,
|
|
3328
3407
|
className: "bg-panel/85 border-border text-text hover:bg-panel absolute top-1/2 left-2 inline-grid h-9 w-9 -translate-y-1/2 cursor-pointer place-items-center rounded-full border shadow-md backdrop-blur disabled:cursor-not-allowed disabled:opacity-40",
|
|
3329
3408
|
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_icons5.IconGlyph, { name: "caretLeft", size: 16 })
|
|
3330
3409
|
}
|
|
@@ -3335,13 +3414,13 @@ var Carousel = (0, import_react52.forwardRef)(function Carousel2({
|
|
|
3335
3414
|
type: "button",
|
|
3336
3415
|
"aria-label": "Next slide",
|
|
3337
3416
|
onClick: () => goTo(activeIdx + 1),
|
|
3338
|
-
disabled: activeIdx ===
|
|
3417
|
+
disabled: !isLooping && activeIdx === N - 1,
|
|
3339
3418
|
className: "bg-panel/85 border-border text-text hover:bg-panel absolute top-1/2 right-2 inline-grid h-9 w-9 -translate-y-1/2 cursor-pointer place-items-center rounded-full border shadow-md backdrop-blur disabled:cursor-not-allowed disabled:opacity-40",
|
|
3340
3419
|
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_icons5.IconGlyph, { name: "caretRight", size: 16 })
|
|
3341
3420
|
}
|
|
3342
3421
|
)
|
|
3343
3422
|
] }),
|
|
3344
|
-
showDots &&
|
|
3423
|
+
showDots && N > 1 && /*
|
|
3345
3424
|
* Plain `<button>` + `aria-current` rather than the tabs pattern
|
|
3346
3425
|
* (`role="tablist" / "tab"`). The APG carousel pattern recommends
|
|
3347
3426
|
* this lighter semantic; the viewport's `aria-live="polite"`
|
|
@@ -4401,19 +4480,28 @@ var Lightbox = (0, import_react59.forwardRef)(function Lightbox2({
|
|
|
4401
4480
|
index,
|
|
4402
4481
|
defaultIndex,
|
|
4403
4482
|
onIndexChange,
|
|
4483
|
+
loop = false,
|
|
4404
4484
|
title = "Photo viewer"
|
|
4405
4485
|
}, ref) {
|
|
4486
|
+
const N = items.length;
|
|
4487
|
+
const isLooping = loop && N > 1;
|
|
4406
4488
|
const [active, setActive] = useControllableState({
|
|
4407
4489
|
value: index,
|
|
4408
4490
|
defaultValue: defaultIndex ?? 0,
|
|
4409
4491
|
onChange: onIndexChange
|
|
4410
4492
|
});
|
|
4411
4493
|
const goPrev = (0, import_react59.useCallback)(() => {
|
|
4412
|
-
setActive((prev) =>
|
|
4413
|
-
|
|
4494
|
+
setActive((prev) => {
|
|
4495
|
+
const p = prev ?? 0;
|
|
4496
|
+
return isLooping ? (p - 1 + N) % N : Math.max(0, p - 1);
|
|
4497
|
+
});
|
|
4498
|
+
}, [setActive, isLooping, N]);
|
|
4414
4499
|
const goNext = (0, import_react59.useCallback)(() => {
|
|
4415
|
-
setActive((prev) =>
|
|
4416
|
-
|
|
4500
|
+
setActive((prev) => {
|
|
4501
|
+
const p = prev ?? 0;
|
|
4502
|
+
return isLooping ? (p + 1) % N : Math.min(N - 1, p + 1);
|
|
4503
|
+
});
|
|
4504
|
+
}, [setActive, isLooping, N]);
|
|
4417
4505
|
const onKey = (0, import_react59.useCallback)(
|
|
4418
4506
|
(e) => {
|
|
4419
4507
|
if (e.key === "ArrowLeft") {
|
|
@@ -4453,7 +4541,7 @@ var Lightbox = (0, import_react59.forwardRef)(function Lightbox2({
|
|
|
4453
4541
|
type: "button",
|
|
4454
4542
|
"aria-label": "Previous photo",
|
|
4455
4543
|
onClick: goPrev,
|
|
4456
|
-
disabled: activeIdx === 0,
|
|
4544
|
+
disabled: !isLooping && activeIdx === 0,
|
|
4457
4545
|
className: "absolute top-1/2 left-4 inline-grid h-11 w-11 -translate-y-1/2 cursor-pointer place-items-center rounded-full bg-white/10 text-white hover:bg-white/20 disabled:cursor-not-allowed disabled:opacity-40",
|
|
4458
4546
|
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_icons7.IconGlyph, { name: "caretLeft", size: 20 })
|
|
4459
4547
|
}
|
|
@@ -4464,7 +4552,7 @@ var Lightbox = (0, import_react59.forwardRef)(function Lightbox2({
|
|
|
4464
4552
|
type: "button",
|
|
4465
4553
|
"aria-label": "Next photo",
|
|
4466
4554
|
onClick: goNext,
|
|
4467
|
-
disabled: activeIdx ===
|
|
4555
|
+
disabled: !isLooping && activeIdx === N - 1,
|
|
4468
4556
|
className: "absolute top-1/2 right-4 inline-grid h-11 w-11 -translate-y-1/2 cursor-pointer place-items-center rounded-full bg-white/10 text-white hover:bg-white/20 disabled:cursor-not-allowed disabled:opacity-40",
|
|
4469
4557
|
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_icons7.IconGlyph, { name: "caretRight", size: 20 })
|
|
4470
4558
|
}
|
|
@@ -4517,6 +4605,7 @@ var ListingCard = (0, import_react60.forwardRef)(function ListingCard2({
|
|
|
4517
4605
|
variant = "default",
|
|
4518
4606
|
photos,
|
|
4519
4607
|
renderPhoto,
|
|
4608
|
+
loop = true,
|
|
4520
4609
|
onClick,
|
|
4521
4610
|
hoverEffect,
|
|
4522
4611
|
title,
|
|
@@ -4563,6 +4652,7 @@ var ListingCard = (0, import_react60.forwardRef)(function ListingCard2({
|
|
|
4563
4652
|
Carousel,
|
|
4564
4653
|
{
|
|
4565
4654
|
items: photos,
|
|
4655
|
+
loop,
|
|
4566
4656
|
...isSpec ? {
|
|
4567
4657
|
index: photoIndex,
|
|
4568
4658
|
onIndexChange: setPhotoIndex,
|
|
@@ -4803,6 +4893,7 @@ var ListingDetail = (0, import_react61.forwardRef)(function ListingDetail2({
|
|
|
4803
4893
|
onOpenChange,
|
|
4804
4894
|
photos,
|
|
4805
4895
|
renderPhoto,
|
|
4896
|
+
loop = true,
|
|
4806
4897
|
title,
|
|
4807
4898
|
eyebrow,
|
|
4808
4899
|
description,
|
|
@@ -4872,6 +4963,7 @@ var ListingDetail = (0, import_react61.forwardRef)(function ListingDetail2({
|
|
|
4872
4963
|
items: photos,
|
|
4873
4964
|
index: galleryIndex,
|
|
4874
4965
|
onIndexChange: setGalleryIndex,
|
|
4966
|
+
loop,
|
|
4875
4967
|
...isSpec ? { showDots: false } : {},
|
|
4876
4968
|
"aria-label": typeof title === "string" ? `${title} photos` : "Listing photos",
|
|
4877
4969
|
renderItem: (src, i) => renderPhoto ? renderPhoto(src, i, "gallery") : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
@@ -5117,6 +5209,7 @@ var ListingDetail = (0, import_react61.forwardRef)(function ListingDetail2({
|
|
|
5117
5209
|
items: photos,
|
|
5118
5210
|
index: galleryIndex,
|
|
5119
5211
|
onIndexChange: setGalleryIndex,
|
|
5212
|
+
loop,
|
|
5120
5213
|
title: lightboxTitle,
|
|
5121
5214
|
renderItem: (src, i) => renderPhoto ? renderPhoto(src, i, "lightbox") : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src, alt: "", className: "max-h-[88vh] max-w-[92vw] object-contain" })
|
|
5122
5215
|
}
|
|
@@ -7408,11 +7501,9 @@ var Tree = (0, import_react88.forwardRef)(function Tree2({
|
|
|
7408
7501
|
return out;
|
|
7409
7502
|
}, [items, expandedSet]);
|
|
7410
7503
|
const [activeId, setActiveId] = (0, import_react88.useState)(null);
|
|
7411
|
-
(
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
}
|
|
7415
|
-
}, [activeId, flatVisible]);
|
|
7504
|
+
if (activeId && !flatVisible.some((f) => f.id === activeId)) {
|
|
7505
|
+
setActiveId(null);
|
|
7506
|
+
}
|
|
7416
7507
|
const tabStopId = (0, import_react88.useMemo)(() => {
|
|
7417
7508
|
if (activeId && flatVisible.some((f) => f.id === activeId)) return activeId;
|
|
7418
7509
|
if (value && flatVisible.some((f) => f.id === value)) return value;
|