overlapping-cards-scroll 0.1.6 → 0.1.7
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 +207 -167
- package/dist/index.js +208 -168
- package/dist/react-native-web.cjs +207 -167
- package/dist/react-native-web.js +208 -168
- package/dist/react-native.cjs +155 -112
- package/dist/react-native.js +156 -113
- package/dist/styles.css +31 -0
- package/dist/types/lib/OverlappingCardsScroll.d.ts +8 -3
- package/dist/types/lib/index.d.ts +1 -1
- package/dist/types/rn/OverlappingCardsScrollRN.native.d.ts +1 -1
- package/dist/types/rn/OverlappingCardsScrollRN.types.d.ts +4 -1
- package/package.json +1 -1
- package/src/lib/OverlappingCardsScroll.css +39 -0
- package/src/lib/OverlappingCardsScroll.tsx +243 -170
- package/src/lib/index.ts +3 -0
- package/src/rn/OverlappingCardsScrollRN.native.tsx +203 -136
- package/src/rn/OverlappingCardsScrollRN.types.ts +5 -1
package/dist/react-native.cjs
CHANGED
|
@@ -28,9 +28,25 @@ var import_react_native = require("react-native");
|
|
|
28
28
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
29
|
var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
30
30
|
var PAGE_DOT_POSITIONS = /* @__PURE__ */ new Set(["above", "below", "overlay"]);
|
|
31
|
-
var
|
|
31
|
+
var TABS_POSITION_MAP = {
|
|
32
|
+
"top-left": { side: "top", align: "start", orientation: "horizontal" },
|
|
33
|
+
"top-center": { side: "top", align: "center", orientation: "horizontal" },
|
|
34
|
+
"top-right": { side: "top", align: "end", orientation: "horizontal" },
|
|
35
|
+
"bottom-left": { side: "bottom", align: "start", orientation: "horizontal" },
|
|
36
|
+
"bottom-center": { side: "bottom", align: "center", orientation: "horizontal" },
|
|
37
|
+
"bottom-right": { side: "bottom", align: "end", orientation: "horizontal" },
|
|
38
|
+
"left-top": { side: "left", align: "start", orientation: "vertical" },
|
|
39
|
+
"left-center": { side: "left", align: "center", orientation: "vertical" },
|
|
40
|
+
"left-bottom": { side: "left", align: "end", orientation: "vertical" },
|
|
41
|
+
"right-top": { side: "right", align: "start", orientation: "vertical" },
|
|
42
|
+
"right-center": { side: "right", align: "center", orientation: "vertical" },
|
|
43
|
+
"right-bottom": { side: "right", align: "end", orientation: "vertical" },
|
|
44
|
+
"above": { side: "top", align: "center", orientation: "horizontal" },
|
|
45
|
+
"below": { side: "bottom", align: "center", orientation: "horizontal" }
|
|
46
|
+
};
|
|
47
|
+
var DEFAULT_TABS_POSITION = { side: "top", align: "center", orientation: "horizontal" };
|
|
48
|
+
var parseTabsPosition = (value) => value && TABS_POSITION_MAP[value] || DEFAULT_TABS_POSITION;
|
|
32
49
|
var normalizePageDotsPosition = (value) => PAGE_DOT_POSITIONS.has(value) ? value : "below";
|
|
33
|
-
var normalizeTabsPosition = (value) => TAB_POSITIONS.has(value) ? value : "above";
|
|
34
50
|
var toNumericOffset = (value, fallback = 0) => {
|
|
35
51
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
36
52
|
return value;
|
|
@@ -244,7 +260,8 @@ function OverlappingCardsScrollRN(props) {
|
|
|
244
260
|
return null;
|
|
245
261
|
}, [itemsProp]);
|
|
246
262
|
const cardCount = cards.length;
|
|
247
|
-
const
|
|
263
|
+
const parsedTabsPosition = parseTabsPosition(tabsPosition);
|
|
264
|
+
const isVerticalTabs = parsedTabsPosition.orientation === "vertical";
|
|
248
265
|
const showNavigationTabs = showTabs && cardCount > 1 && cardNames !== null;
|
|
249
266
|
const resolvedPageDotsOffset = toNumericOffset(pageDotsOffset, 10);
|
|
250
267
|
const resolvedTabsOffset = toNumericOffset(tabsOffset, 10);
|
|
@@ -534,16 +551,21 @@ function OverlappingCardsScrollRN(props) {
|
|
|
534
551
|
}
|
|
535
552
|
);
|
|
536
553
|
};
|
|
537
|
-
const renderTabs = (
|
|
538
|
-
if (!showNavigationTabs ||
|
|
554
|
+
const renderTabs = () => {
|
|
555
|
+
if (!showNavigationTabs || cardNames === null) {
|
|
539
556
|
return null;
|
|
540
557
|
}
|
|
541
|
-
const
|
|
558
|
+
const { side, align, orientation } = parsedTabsPosition;
|
|
559
|
+
const isVertical = orientation === "vertical";
|
|
560
|
+
const justifyContent = align === "start" ? "flex-start" : align === "end" ? "flex-end" : "center";
|
|
561
|
+
const baseStyle = isVertical ? styles.tabsColumn : styles.tabsRow;
|
|
562
|
+
const containerStyle = side === "top" ? [baseStyle, { justifyContent, marginBottom: resolvedTabsOffset }] : side === "bottom" ? [baseStyle, { justifyContent, marginTop: resolvedTabsOffset }] : side === "left" ? [baseStyle, { justifyContent, marginRight: resolvedTabsOffset }] : [baseStyle, { justifyContent, marginLeft: resolvedTabsOffset }];
|
|
542
563
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
543
564
|
TabsContainerComponent,
|
|
544
565
|
{
|
|
545
|
-
position,
|
|
546
|
-
|
|
566
|
+
position: side,
|
|
567
|
+
align,
|
|
568
|
+
className: `rn-ocs-tabs rn-ocs-tabs--${side}`,
|
|
547
569
|
style: containerStyle,
|
|
548
570
|
ariaLabel: "Card tabs",
|
|
549
571
|
cardNames,
|
|
@@ -564,7 +586,8 @@ function OverlappingCardsScrollRN(props) {
|
|
|
564
586
|
{
|
|
565
587
|
name,
|
|
566
588
|
index,
|
|
567
|
-
position,
|
|
589
|
+
position: side,
|
|
590
|
+
align,
|
|
568
591
|
isPrincipal,
|
|
569
592
|
influence,
|
|
570
593
|
animate,
|
|
@@ -578,121 +601,126 @@ function OverlappingCardsScrollRN(props) {
|
|
|
578
601
|
onPress: pressTab,
|
|
579
602
|
onClick: pressTab
|
|
580
603
|
},
|
|
581
|
-
`rn-ocs-tab-${
|
|
604
|
+
`rn-ocs-tab-${side}-${index}`
|
|
582
605
|
);
|
|
583
606
|
})
|
|
584
607
|
}
|
|
585
608
|
);
|
|
586
609
|
};
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
610
|
+
const tabsBeforeStage = parsedTabsPosition.side === "top" || parsedTabsPosition.side === "left";
|
|
611
|
+
const stageAndDots = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
612
|
+
renderPageDots("above"),
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
614
|
+
import_react_native.View,
|
|
615
|
+
{
|
|
616
|
+
style: [styles.root, { height: resolvedCardHeight }],
|
|
617
|
+
onLayout: (event) => {
|
|
618
|
+
const width = event.nativeEvent.layout.width || 1;
|
|
619
|
+
setViewportWidth(Math.max(1, width));
|
|
620
|
+
},
|
|
621
|
+
children: [
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
623
|
+
import_react_native.Animated.ScrollView,
|
|
624
|
+
{
|
|
625
|
+
ref: scrollRef,
|
|
626
|
+
horizontal: true,
|
|
627
|
+
style: [styles.scrollRegion, { height: resolvedCardHeight }],
|
|
628
|
+
contentContainerStyle: {
|
|
629
|
+
width: layout.trackWidth,
|
|
630
|
+
height: resolvedCardHeight
|
|
631
|
+
},
|
|
632
|
+
onScroll,
|
|
633
|
+
onScrollBeginDrag: cancelFocusTransition,
|
|
634
|
+
onMomentumScrollBegin: cancelFocusTransition,
|
|
635
|
+
scrollEventThrottle: 16,
|
|
636
|
+
showsHorizontalScrollIndicator,
|
|
637
|
+
snapToInterval: shouldSnapToCard ? layout.stepDistance : void 0,
|
|
638
|
+
snapToAlignment: shouldSnapToCard ? "start" : void 0,
|
|
639
|
+
decelerationRate: shouldSnapToCard ? snapDecelerationRate : "normal",
|
|
640
|
+
disableIntervalMomentum: shouldSnapToCard ? snapDisableIntervalMomentum : false,
|
|
641
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
642
|
+
import_react_native.View,
|
|
605
643
|
{
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
644
|
+
style: [
|
|
645
|
+
styles.track,
|
|
646
|
+
{ width: layout.trackWidth, height: resolvedCardHeight }
|
|
647
|
+
],
|
|
648
|
+
children: cards.map((card, index) => {
|
|
649
|
+
var _a;
|
|
650
|
+
const restingRightX = index === 0 ? 0 : (index - 1) * layout.peek + layout.cardWidth;
|
|
651
|
+
const restingLeftX = index * layout.peek;
|
|
652
|
+
const cardXDuringNormalScroll = index === 0 ? 0 : scrollX.interpolate({
|
|
653
|
+
inputRange: index === 1 ? [0, layout.stepDistance] : [
|
|
654
|
+
(index - 1) * layout.stepDistance,
|
|
655
|
+
index * layout.stepDistance
|
|
656
|
+
],
|
|
657
|
+
outputRange: [restingRightX, restingLeftX],
|
|
658
|
+
extrapolate: "clamp"
|
|
659
|
+
});
|
|
660
|
+
const cardXDuringFocusTransition = focusTransition ? focusTransitionProgress.interpolate({
|
|
661
|
+
inputRange: [0, 1],
|
|
662
|
+
outputRange: [
|
|
663
|
+
resolveCardXAtProgress(
|
|
664
|
+
index,
|
|
665
|
+
focusTransition.fromProgress,
|
|
666
|
+
layout
|
|
667
|
+
),
|
|
668
|
+
resolveCardXAtProgress(
|
|
669
|
+
index,
|
|
670
|
+
focusTransition.toProgress,
|
|
671
|
+
layout
|
|
672
|
+
)
|
|
628
673
|
],
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
outputRange: [restingRightX, restingLeftX],
|
|
639
|
-
extrapolate: "clamp"
|
|
640
|
-
});
|
|
641
|
-
const cardXDuringFocusTransition = focusTransition ? focusTransitionProgress.interpolate({
|
|
642
|
-
inputRange: [0, 1],
|
|
643
|
-
outputRange: [
|
|
644
|
-
resolveCardXAtProgress(
|
|
645
|
-
index,
|
|
646
|
-
focusTransition.fromProgress,
|
|
647
|
-
layout
|
|
648
|
-
),
|
|
649
|
-
resolveCardXAtProgress(
|
|
650
|
-
index,
|
|
651
|
-
focusTransition.toProgress,
|
|
652
|
-
layout
|
|
653
|
-
)
|
|
654
|
-
],
|
|
655
|
-
extrapolate: "clamp"
|
|
656
|
-
}) : null;
|
|
657
|
-
const animatedCardX = cardXDuringFocusTransition != null ? cardXDuringFocusTransition : cardXDuringNormalScroll;
|
|
658
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
659
|
-
import_react_native.Animated.View,
|
|
674
|
+
extrapolate: "clamp"
|
|
675
|
+
}) : null;
|
|
676
|
+
const animatedCardX = cardXDuringFocusTransition != null ? cardXDuringFocusTransition : cardXDuringNormalScroll;
|
|
677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
678
|
+
import_react_native.Animated.View,
|
|
679
|
+
{
|
|
680
|
+
pointerEvents: "box-none",
|
|
681
|
+
style: [
|
|
682
|
+
styles.card,
|
|
660
683
|
{
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
684
|
+
width: layout.cardWidth,
|
|
685
|
+
height: resolvedCardHeight,
|
|
686
|
+
transform: [
|
|
664
687
|
{
|
|
665
|
-
|
|
666
|
-
height: resolvedCardHeight,
|
|
667
|
-
transform: [
|
|
668
|
-
{
|
|
669
|
-
translateX: import_react_native.Animated.add(scrollX, animatedCardX)
|
|
670
|
-
}
|
|
671
|
-
]
|
|
672
|
-
},
|
|
673
|
-
cardContainerStyle
|
|
674
|
-
],
|
|
675
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { pointerEvents: "auto", style: styles.cardContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
676
|
-
OverlappingCardsScrollRNCardIndexContext.Provider,
|
|
677
|
-
{
|
|
678
|
-
value: index,
|
|
679
|
-
children: card
|
|
688
|
+
translateX: import_react_native.Animated.add(scrollX, animatedCardX)
|
|
680
689
|
}
|
|
681
|
-
|
|
690
|
+
]
|
|
682
691
|
},
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
692
|
+
cardContainerStyle
|
|
693
|
+
],
|
|
694
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { pointerEvents: "auto", style: styles.cardContent, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
695
|
+
OverlappingCardsScrollRNCardIndexContext.Provider,
|
|
696
|
+
{
|
|
697
|
+
value: index,
|
|
698
|
+
children: card
|
|
699
|
+
}
|
|
700
|
+
) })
|
|
701
|
+
},
|
|
702
|
+
(_a = card.key) != null ? _a : `rn-ocs-card-${index}`
|
|
703
|
+
);
|
|
704
|
+
})
|
|
688
705
|
}
|
|
689
|
-
)
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
706
|
+
)
|
|
707
|
+
}
|
|
708
|
+
),
|
|
709
|
+
renderPageDots("overlay")
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
),
|
|
713
|
+
renderPageDots("below")
|
|
714
|
+
] });
|
|
715
|
+
const stageContent = isVerticalTabs ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: styles.mainColumn, children: stageAndDots }) : stageAndDots;
|
|
716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
717
|
+
OverlappingCardsScrollRNControllerContext.Provider,
|
|
718
|
+
{
|
|
719
|
+
value: controllerContextValue,
|
|
720
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: [isVerticalTabs ? styles.shellRow : styles.shell, style], children: [
|
|
721
|
+
tabsBeforeStage ? renderTabs() : null,
|
|
722
|
+
stageContent,
|
|
723
|
+
!tabsBeforeStage ? renderTabs() : null
|
|
696
724
|
] })
|
|
697
725
|
}
|
|
698
726
|
);
|
|
@@ -702,6 +730,15 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
702
730
|
width: "100%",
|
|
703
731
|
minWidth: 0
|
|
704
732
|
},
|
|
733
|
+
shellRow: {
|
|
734
|
+
width: "100%",
|
|
735
|
+
minWidth: 0,
|
|
736
|
+
flexDirection: "row"
|
|
737
|
+
},
|
|
738
|
+
mainColumn: {
|
|
739
|
+
flex: 1,
|
|
740
|
+
minWidth: 0
|
|
741
|
+
},
|
|
705
742
|
root: {
|
|
706
743
|
width: "100%",
|
|
707
744
|
minWidth: 0,
|
|
@@ -757,6 +794,12 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
757
794
|
flexWrap: "wrap",
|
|
758
795
|
zIndex: 6
|
|
759
796
|
},
|
|
797
|
+
tabsColumn: {
|
|
798
|
+
flexDirection: "column",
|
|
799
|
+
alignItems: "center",
|
|
800
|
+
justifyContent: "center",
|
|
801
|
+
zIndex: 6
|
|
802
|
+
},
|
|
760
803
|
tab: {
|
|
761
804
|
borderRadius: 999,
|
|
762
805
|
borderWidth: 1,
|