@ship-it-ui/ui 0.0.11 → 0.0.12
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 +14 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -13
- package/dist/index.d.ts +23 -13
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1242,11 +1242,21 @@ interface CarouselProps<T = unknown> extends Omit<HTMLAttributes<HTMLDivElement>
|
|
|
1242
1242
|
showArrows?: boolean;
|
|
1243
1243
|
/**
|
|
1244
1244
|
* Wrap arrows / dots / native swipe past the boundaries. Default `false`.
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
* `
|
|
1245
|
+
*
|
|
1246
|
+
* Variants:
|
|
1247
|
+
* - `"circular"` (or `true`): boundary arrow clicks smooth-scroll a
|
|
1248
|
+
* single slide width through a hidden clone of the opposite end, then
|
|
1249
|
+
* invisibly snap to the real twin. Feels like an endless reel — the
|
|
1250
|
+
* motion is always one slide, regardless of strip length.
|
|
1251
|
+
* - `"sweep"`: boundary arrow clicks smooth-scroll the full distance
|
|
1252
|
+
* across the strip back to the real first / last slide. The
|
|
1253
|
+
* transition reads as a wide arc across every item between.
|
|
1254
|
+
*
|
|
1255
|
+
* Native swipe past the edge always uses the clone-snap (independent of
|
|
1256
|
+
* variant). `onIndexChange` only emits real indices in
|
|
1257
|
+
* `0..items.length - 1`.
|
|
1248
1258
|
*/
|
|
1249
|
-
loop?: boolean;
|
|
1259
|
+
loop?: boolean | 'circular' | 'sweep';
|
|
1250
1260
|
/** Accessible label for the carousel region. */
|
|
1251
1261
|
'aria-label'?: string;
|
|
1252
1262
|
}
|
|
@@ -1583,13 +1593,13 @@ interface ListingCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'childre
|
|
|
1583
1593
|
* browsing expects looping. Pass `false` to restore stop-at-end.
|
|
1584
1594
|
*/
|
|
1585
1595
|
loop?: boolean;
|
|
1586
|
-
/** Listing title — e.g. "
|
|
1596
|
+
/** Listing title — e.g. "Sun-soaked cabin in Marin". */
|
|
1587
1597
|
title: ReactNode;
|
|
1588
|
-
/** Optional eyebrow text above the title (location,
|
|
1598
|
+
/** Optional eyebrow text above the title (location, listing type). */
|
|
1589
1599
|
eyebrow?: ReactNode;
|
|
1590
|
-
/** Headline price (e.g. `
|
|
1600
|
+
/** Headline price (e.g. `189`). */
|
|
1591
1601
|
price: ReactNode;
|
|
1592
|
-
/** Price unit suffix (e.g. `/
|
|
1602
|
+
/** Price unit suffix (e.g. `/night`). */
|
|
1593
1603
|
priceUnit?: ReactNode;
|
|
1594
1604
|
/** Original price for sale strike-through. */
|
|
1595
1605
|
originalPrice?: ReactNode;
|
|
@@ -1681,7 +1691,7 @@ interface ListingCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'childre
|
|
|
1681
1691
|
footer: string;
|
|
1682
1692
|
/** Price text. */
|
|
1683
1693
|
price: string;
|
|
1684
|
-
/** Price unit (e.g. `/
|
|
1694
|
+
/** Price unit (e.g. `/night`). */
|
|
1685
1695
|
priceUnit: string;
|
|
1686
1696
|
/** CTA button (spec variant). */
|
|
1687
1697
|
cta: string;
|
|
@@ -1744,9 +1754,9 @@ interface ListingDetailProps {
|
|
|
1744
1754
|
* drives both surfaces.
|
|
1745
1755
|
*/
|
|
1746
1756
|
loop?: boolean;
|
|
1747
|
-
/** Listing title — e.g. "
|
|
1757
|
+
/** Listing title — e.g. "Sun-soaked cabin in Marin". */
|
|
1748
1758
|
title: ReactNode;
|
|
1749
|
-
/** Optional eyebrow above the title —
|
|
1759
|
+
/** Optional eyebrow above the title — listing type, location. */
|
|
1750
1760
|
eyebrow?: ReactNode;
|
|
1751
1761
|
/** Long-form description body. */
|
|
1752
1762
|
description?: ReactNode;
|
|
@@ -1754,9 +1764,9 @@ interface ListingDetailProps {
|
|
|
1754
1764
|
rating?: number;
|
|
1755
1765
|
/** Total review count, shown next to the rating. */
|
|
1756
1766
|
reviewCount?: number;
|
|
1757
|
-
/** Headline price (e.g. `$
|
|
1767
|
+
/** Headline price (e.g. `$189`). */
|
|
1758
1768
|
price: ReactNode;
|
|
1759
|
-
/** Suffix after the price (e.g. `/
|
|
1769
|
+
/** Suffix after the price (e.g. `/night`). */
|
|
1760
1770
|
priceUnit?: ReactNode;
|
|
1761
1771
|
/** Original price for a strike-through; renders only when set. */
|
|
1762
1772
|
originalPrice?: ReactNode;
|
package/dist/index.d.ts
CHANGED
|
@@ -1242,11 +1242,21 @@ interface CarouselProps<T = unknown> extends Omit<HTMLAttributes<HTMLDivElement>
|
|
|
1242
1242
|
showArrows?: boolean;
|
|
1243
1243
|
/**
|
|
1244
1244
|
* Wrap arrows / dots / native swipe past the boundaries. Default `false`.
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
* `
|
|
1245
|
+
*
|
|
1246
|
+
* Variants:
|
|
1247
|
+
* - `"circular"` (or `true`): boundary arrow clicks smooth-scroll a
|
|
1248
|
+
* single slide width through a hidden clone of the opposite end, then
|
|
1249
|
+
* invisibly snap to the real twin. Feels like an endless reel — the
|
|
1250
|
+
* motion is always one slide, regardless of strip length.
|
|
1251
|
+
* - `"sweep"`: boundary arrow clicks smooth-scroll the full distance
|
|
1252
|
+
* across the strip back to the real first / last slide. The
|
|
1253
|
+
* transition reads as a wide arc across every item between.
|
|
1254
|
+
*
|
|
1255
|
+
* Native swipe past the edge always uses the clone-snap (independent of
|
|
1256
|
+
* variant). `onIndexChange` only emits real indices in
|
|
1257
|
+
* `0..items.length - 1`.
|
|
1248
1258
|
*/
|
|
1249
|
-
loop?: boolean;
|
|
1259
|
+
loop?: boolean | 'circular' | 'sweep';
|
|
1250
1260
|
/** Accessible label for the carousel region. */
|
|
1251
1261
|
'aria-label'?: string;
|
|
1252
1262
|
}
|
|
@@ -1583,13 +1593,13 @@ interface ListingCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'childre
|
|
|
1583
1593
|
* browsing expects looping. Pass `false` to restore stop-at-end.
|
|
1584
1594
|
*/
|
|
1585
1595
|
loop?: boolean;
|
|
1586
|
-
/** Listing title — e.g. "
|
|
1596
|
+
/** Listing title — e.g. "Sun-soaked cabin in Marin". */
|
|
1587
1597
|
title: ReactNode;
|
|
1588
|
-
/** Optional eyebrow text above the title (location,
|
|
1598
|
+
/** Optional eyebrow text above the title (location, listing type). */
|
|
1589
1599
|
eyebrow?: ReactNode;
|
|
1590
|
-
/** Headline price (e.g. `
|
|
1600
|
+
/** Headline price (e.g. `189`). */
|
|
1591
1601
|
price: ReactNode;
|
|
1592
|
-
/** Price unit suffix (e.g. `/
|
|
1602
|
+
/** Price unit suffix (e.g. `/night`). */
|
|
1593
1603
|
priceUnit?: ReactNode;
|
|
1594
1604
|
/** Original price for sale strike-through. */
|
|
1595
1605
|
originalPrice?: ReactNode;
|
|
@@ -1681,7 +1691,7 @@ interface ListingCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'childre
|
|
|
1681
1691
|
footer: string;
|
|
1682
1692
|
/** Price text. */
|
|
1683
1693
|
price: string;
|
|
1684
|
-
/** Price unit (e.g. `/
|
|
1694
|
+
/** Price unit (e.g. `/night`). */
|
|
1685
1695
|
priceUnit: string;
|
|
1686
1696
|
/** CTA button (spec variant). */
|
|
1687
1697
|
cta: string;
|
|
@@ -1744,9 +1754,9 @@ interface ListingDetailProps {
|
|
|
1744
1754
|
* drives both surfaces.
|
|
1745
1755
|
*/
|
|
1746
1756
|
loop?: boolean;
|
|
1747
|
-
/** Listing title — e.g. "
|
|
1757
|
+
/** Listing title — e.g. "Sun-soaked cabin in Marin". */
|
|
1748
1758
|
title: ReactNode;
|
|
1749
|
-
/** Optional eyebrow above the title —
|
|
1759
|
+
/** Optional eyebrow above the title — listing type, location. */
|
|
1750
1760
|
eyebrow?: ReactNode;
|
|
1751
1761
|
/** Long-form description body. */
|
|
1752
1762
|
description?: ReactNode;
|
|
@@ -1754,9 +1764,9 @@ interface ListingDetailProps {
|
|
|
1754
1764
|
rating?: number;
|
|
1755
1765
|
/** Total review count, shown next to the rating. */
|
|
1756
1766
|
reviewCount?: number;
|
|
1757
|
-
/** Headline price (e.g. `$
|
|
1767
|
+
/** Headline price (e.g. `$189`). */
|
|
1758
1768
|
price: ReactNode;
|
|
1759
|
-
/** Suffix after the price (e.g. `/
|
|
1769
|
+
/** Suffix after the price (e.g. `/night`). */
|
|
1760
1770
|
priceUnit?: ReactNode;
|
|
1761
1771
|
/** Original price for a strike-through; renders only when set. */
|
|
1762
1772
|
originalPrice?: ReactNode;
|
package/dist/index.js
CHANGED
|
@@ -3100,7 +3100,8 @@ var Carousel = forwardRef44(function Carousel2({
|
|
|
3100
3100
|
...props
|
|
3101
3101
|
}, ref) {
|
|
3102
3102
|
const N = items.length;
|
|
3103
|
-
const
|
|
3103
|
+
const loopMode = !loop ? null : loop === true ? "circular" : loop;
|
|
3104
|
+
const isLooping = loopMode !== null && N > 1;
|
|
3104
3105
|
const [active, setActive] = useControllableState({
|
|
3105
3106
|
value: indexProp,
|
|
3106
3107
|
defaultValue: defaultIndex ?? 0,
|
|
@@ -3108,6 +3109,7 @@ var Carousel = forwardRef44(function Carousel2({
|
|
|
3108
3109
|
});
|
|
3109
3110
|
const viewportRef = useRef8(null);
|
|
3110
3111
|
const internalScrollRef = useRef8(false);
|
|
3112
|
+
const wrapInProgressRef = useRef8(false);
|
|
3111
3113
|
const activeIdx = active ?? 0;
|
|
3112
3114
|
const domIndexFor = useCallback9((real) => isLooping ? real + 1 : real, [isLooping]);
|
|
3113
3115
|
const goTo = useCallback9(
|
|
@@ -3116,14 +3118,18 @@ var Carousel = forwardRef44(function Carousel2({
|
|
|
3116
3118
|
setActive(next);
|
|
3117
3119
|
const node = viewportRef.current;
|
|
3118
3120
|
if (node) {
|
|
3119
|
-
const
|
|
3121
|
+
const isNextWrap = loopMode === "circular" && activeIdx === N - 1 && i === activeIdx + 1;
|
|
3122
|
+
const isPrevWrap = loopMode === "circular" && activeIdx === 0 && i === activeIdx - 1;
|
|
3123
|
+
const targetDom = isNextWrap ? N + 1 : isPrevWrap ? 0 : domIndexFor(next);
|
|
3124
|
+
const slide = node.children[targetDom];
|
|
3120
3125
|
if (slide) {
|
|
3121
3126
|
internalScrollRef.current = true;
|
|
3127
|
+
if (isNextWrap || isPrevWrap) wrapInProgressRef.current = true;
|
|
3122
3128
|
slide.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "start" });
|
|
3123
3129
|
}
|
|
3124
3130
|
}
|
|
3125
3131
|
},
|
|
3126
|
-
[N, isLooping, domIndexFor, setActive]
|
|
3132
|
+
[N, isLooping, loopMode, domIndexFor, setActive, activeIdx]
|
|
3127
3133
|
);
|
|
3128
3134
|
useEffect8(() => {
|
|
3129
3135
|
const node = viewportRef.current;
|
|
@@ -3137,23 +3143,28 @@ var Carousel = forwardRef44(function Carousel2({
|
|
|
3137
3143
|
return;
|
|
3138
3144
|
}
|
|
3139
3145
|
if (domIdx === 0) {
|
|
3146
|
+
if (wrapInProgressRef.current && node.scrollLeft > 1) return;
|
|
3140
3147
|
const realTwin = node.children[N];
|
|
3141
3148
|
if (realTwin) {
|
|
3142
3149
|
internalScrollRef.current = true;
|
|
3143
3150
|
realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3144
3151
|
}
|
|
3145
3152
|
if (activeIdx !== N - 1) setActive(N - 1);
|
|
3153
|
+
wrapInProgressRef.current = false;
|
|
3146
3154
|
return;
|
|
3147
3155
|
}
|
|
3148
3156
|
if (domIdx === N + 1) {
|
|
3157
|
+
if (wrapInProgressRef.current && node.scrollLeft < (N + 1) * width - 1) return;
|
|
3149
3158
|
const realTwin = node.children[1];
|
|
3150
3159
|
if (realTwin) {
|
|
3151
3160
|
internalScrollRef.current = true;
|
|
3152
3161
|
realTwin.scrollIntoView({ behavior: "instant", block: "nearest", inline: "start" });
|
|
3153
3162
|
}
|
|
3154
3163
|
if (activeIdx !== 0) setActive(0);
|
|
3164
|
+
wrapInProgressRef.current = false;
|
|
3155
3165
|
return;
|
|
3156
3166
|
}
|
|
3167
|
+
if (wrapInProgressRef.current) return;
|
|
3157
3168
|
const realIdx = domIdx - 1;
|
|
3158
3169
|
if (realIdx !== activeIdx) setActive(realIdx);
|
|
3159
3170
|
};
|