overlapping-cards-scroll 0.1.1 → 0.1.2

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.
@@ -1,6 +1,7 @@
1
1
  // src/rn/OverlappingCardsScrollRN.native.tsx
2
2
  import {
3
3
  Children,
4
+ Fragment,
4
5
  createContext,
5
6
  useCallback,
6
7
  useContext,
@@ -13,7 +14,43 @@ import { Animated, Easing, Platform, Pressable, StyleSheet, Text, View } from "r
13
14
  import { jsx, jsxs } from "react/jsx-runtime";
14
15
  var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
15
16
  var PAGE_DOT_POSITIONS = /* @__PURE__ */ new Set(["above", "below", "overlay"]);
17
+ var TAB_POSITIONS = /* @__PURE__ */ new Set(["above", "below"]);
16
18
  var normalizePageDotsPosition = (value) => PAGE_DOT_POSITIONS.has(value) ? value : "below";
19
+ var normalizeTabsPosition = (value) => TAB_POSITIONS.has(value) ? value : "above";
20
+ var toNumericOffset = (value, fallback = 0) => {
21
+ if (typeof value === "number" && Number.isFinite(value)) {
22
+ return value;
23
+ }
24
+ if (typeof value === "string") {
25
+ const parsed = Number.parseFloat(value.trim());
26
+ if (Number.isFinite(parsed)) {
27
+ return parsed;
28
+ }
29
+ }
30
+ return fallback;
31
+ };
32
+ var toNativeDimension = (value, fallback = 0) => {
33
+ if (typeof value === "number" && Number.isFinite(value)) {
34
+ return value;
35
+ }
36
+ if (typeof value === "string") {
37
+ const trimmed = value.trim();
38
+ if (trimmed === "auto") {
39
+ return "auto";
40
+ }
41
+ if (trimmed.endsWith("%")) {
42
+ const percent = Number.parseFloat(trimmed.slice(0, -1));
43
+ if (Number.isFinite(percent)) {
44
+ return `${percent}%`;
45
+ }
46
+ }
47
+ const numeric = Number.parseFloat(trimmed);
48
+ if (Number.isFinite(numeric)) {
49
+ return numeric;
50
+ }
51
+ }
52
+ return fallback;
53
+ };
17
54
  var resolveCardXAtProgress = (index, progress, layout) => {
18
55
  const principalIndex = Math.floor(progress);
19
56
  const transitionProgress = progress - principalIndex;
@@ -51,26 +88,69 @@ function OverlappingCardsScrollRNFocusTrigger({
51
88
  children = "Make principal",
52
89
  style = void 0,
53
90
  textStyle = void 0,
91
+ behavior = "smooth",
54
92
  transitionMode = "swoop",
93
+ disabled = false,
94
+ accessibilityLabel = void 0,
95
+ testID = void 0,
55
96
  onPress = void 0,
97
+ onClick = void 0,
56
98
  ...pressableProps
57
99
  }) {
58
100
  const { canFocus, focusCard } = useOverlappingCardsScrollRNCardControl();
59
101
  const handlePress = (event) => {
102
+ onClick == null ? void 0 : onClick(event);
60
103
  onPress == null ? void 0 : onPress(event);
61
- focusCard({ animated: true, transitionMode });
104
+ focusCard({
105
+ animated: behavior !== "auto",
106
+ transitionMode
107
+ });
62
108
  };
63
109
  return /* @__PURE__ */ jsx(
64
110
  Pressable,
65
111
  {
66
112
  style: ({ pressed }) => [styles.focusTrigger, pressed && styles.focusTriggerPressed, style],
67
- disabled: !canFocus,
113
+ disabled: disabled || !canFocus,
114
+ accessibilityLabel,
115
+ testID,
68
116
  onPress: handlePress,
69
117
  ...pressableProps,
70
118
  children: /* @__PURE__ */ jsx(Text, { style: [styles.focusTriggerText, textStyle], children })
71
119
  }
72
120
  );
73
121
  }
122
+ function DefaultTabsContainerComponent({
123
+ children,
124
+ style,
125
+ ariaLabel
126
+ }) {
127
+ return /* @__PURE__ */ jsx(View, { accessibilityRole: "tablist", accessibilityLabel: ariaLabel, style, children });
128
+ }
129
+ function DefaultTabsComponent({
130
+ name,
131
+ style,
132
+ textStyle,
133
+ accessibilityLabel,
134
+ accessibilityState,
135
+ onPress,
136
+ onClick
137
+ }) {
138
+ const handlePress = () => {
139
+ onClick();
140
+ onPress();
141
+ };
142
+ return /* @__PURE__ */ jsx(
143
+ Pressable,
144
+ {
145
+ accessibilityRole: "tab",
146
+ accessibilityLabel,
147
+ accessibilityState,
148
+ onPress: handlePress,
149
+ style: ({ pressed }) => [styles.tab, pressed && styles.tabPressed, style],
150
+ children: /* @__PURE__ */ jsx(Text, { style: [styles.tabText, textStyle], children: name })
151
+ }
152
+ );
153
+ }
74
154
  var resolveCardWidth = (cardWidth, viewportWidth, fallbackRatio) => {
75
155
  if (typeof cardWidth === "number" && Number.isFinite(cardWidth) && cardWidth > 0) {
76
156
  return cardWidth;
@@ -90,26 +170,66 @@ var resolveCardWidth = (cardWidth, viewportWidth, fallbackRatio) => {
90
170
  }
91
171
  return viewportWidth * fallbackRatio;
92
172
  };
93
- function OverlappingCardsScrollRN({
94
- children,
95
- style = void 0,
96
- cardHeight = 300,
97
- cardWidth = void 0,
98
- cardWidthRatio = 1 / 3,
99
- basePeek = 64,
100
- minPeek = 10,
101
- maxPeek = 84,
102
- showsHorizontalScrollIndicator = true,
103
- snapToCardOnRelease = true,
104
- snapDecelerationRate = "normal",
105
- snapDisableIntervalMomentum = false,
106
- showPageDots = false,
107
- pageDotsPosition = "below",
108
- pageDotsOffset = 10,
109
- focusTransitionDuration = 420
110
- }) {
111
- const cards = useMemo(() => Children.toArray(children), [children]);
173
+ function OverlappingCardsScrollRN(props) {
174
+ const {
175
+ style = void 0,
176
+ cardHeight = 300,
177
+ cardWidth = void 0,
178
+ cardWidthRatio = 1 / 3,
179
+ basePeek = 64,
180
+ minPeek = 10,
181
+ maxPeek = 84,
182
+ showsHorizontalScrollIndicator = true,
183
+ snapToCardOnRelease = true,
184
+ snapDecelerationRate = "normal",
185
+ snapDisableIntervalMomentum = false,
186
+ showPageDots = false,
187
+ pageDotsPosition = "below",
188
+ pageDotsOffset = 10,
189
+ focusTransitionDuration = 420,
190
+ cardContainerStyle = void 0,
191
+ showTabs = false,
192
+ tabsPosition = "above",
193
+ tabsOffset = 10,
194
+ tabsComponent: TabsComponent = DefaultTabsComponent,
195
+ tabsContainerComponent: TabsContainerComponent = DefaultTabsContainerComponent
196
+ } = props;
197
+ const hasItems = "items" in props && Array.isArray(props.items);
198
+ const hasChildren = "children" in props && props.children != null;
199
+ useEffect(() => {
200
+ if (hasItems && hasChildren) {
201
+ console.warn(
202
+ "OverlappingCardsScrollRN: Both `items` and `children` were provided. `items` takes precedence."
203
+ );
204
+ }
205
+ }, [hasItems, hasChildren]);
206
+ const itemsProp = hasItems ? props.items : null;
207
+ const childrenProp = hasChildren ? props.children : null;
208
+ const cards = useMemo(() => {
209
+ if (itemsProp) {
210
+ return itemsProp.map((item) => /* @__PURE__ */ jsx(Fragment, { children: item.jsx }, item.id));
211
+ }
212
+ return Children.toArray(childrenProp);
213
+ }, [childrenProp, itemsProp]);
214
+ const cardNames = useMemo(() => {
215
+ if (itemsProp) {
216
+ return itemsProp.map((item) => item.name);
217
+ }
218
+ return null;
219
+ }, [itemsProp]);
112
220
  const cardCount = cards.length;
221
+ const resolvedTabsPosition = normalizeTabsPosition(tabsPosition);
222
+ const showNavigationTabs = showTabs && cardCount > 1 && cardNames !== null;
223
+ const resolvedPageDotsOffset = toNumericOffset(pageDotsOffset, 10);
224
+ const resolvedTabsOffset = toNumericOffset(tabsOffset, 10);
225
+ const resolvedCardHeight = toNativeDimension(cardHeight, 300);
226
+ useEffect(() => {
227
+ if (showTabs && cardNames === null) {
228
+ console.warn(
229
+ "OverlappingCardsScrollRN: `showTabs` requires the `items` prop to provide card names. Tabs will not render."
230
+ );
231
+ }
232
+ }, [cardNames, showTabs]);
113
233
  const scrollRef = useRef(null);
114
234
  const scrollX = useRef(new Animated.Value(0)).current;
115
235
  const scrollXValueRef = useRef(0);
@@ -118,6 +238,7 @@ function OverlappingCardsScrollRN({
118
238
  const focusTransitionIdRef = useRef(0);
119
239
  const [viewportWidth, setViewportWidth] = useState(1);
120
240
  const [focusTransition, setFocusTransition] = useState(null);
241
+ const [scrollProgress, setScrollProgress] = useState(0);
121
242
  const layout = useMemo(() => {
122
243
  const safeWidth = Math.max(1, viewportWidth);
123
244
  const safeRatio = clamp(cardWidthRatio, 0.2, 0.95);
@@ -160,11 +281,26 @@ function OverlappingCardsScrollRN({
160
281
  useEffect(() => {
161
282
  const id = scrollX.addListener(({ value }) => {
162
283
  scrollXValueRef.current = value;
284
+ if (!showNavigationTabs) {
285
+ return;
286
+ }
287
+ const nextProgress = cardCount > 1 ? clamp(value / layout.stepDistance, 0, cardCount - 1) : 0;
288
+ setScrollProgress(
289
+ (currentProgress) => Math.abs(currentProgress - nextProgress) < 1e-3 ? currentProgress : nextProgress
290
+ );
163
291
  });
164
292
  return () => {
165
293
  scrollX.removeListener(id);
166
294
  };
167
- }, [scrollX]);
295
+ }, [cardCount, layout.stepDistance, scrollX, showNavigationTabs]);
296
+ useEffect(() => {
297
+ if (!showNavigationTabs) {
298
+ setScrollProgress(0);
299
+ return;
300
+ }
301
+ const nextProgress = cardCount > 1 ? clamp(scrollXValueRef.current / layout.stepDistance, 0, cardCount - 1) : 0;
302
+ setScrollProgress(nextProgress);
303
+ }, [cardCount, layout.stepDistance, showNavigationTabs]);
168
304
  useEffect(() => () => stopFocusTransitionAnimation(), [stopFocusTransitionAnimation]);
169
305
  useEffect(() => {
170
306
  if (cardCount > 1) {
@@ -199,6 +335,9 @@ function OverlappingCardsScrollRN({
199
335
  const nextScrollLeft = clamp(safeIndex * layout.stepDistance, 0, layout.scrollRange);
200
336
  const transitionMode = (_a = options.transitionMode) != null ? _a : "swoop";
201
337
  if (transitionMode === "swoop" && cardCount > 1) {
338
+ if (showNavigationTabs) {
339
+ setScrollProgress(safeIndex);
340
+ }
202
341
  const fromProgress = clamp(
203
342
  scrollXValueRef.current / layout.stepDistance,
204
343
  0,
@@ -255,6 +394,9 @@ function OverlappingCardsScrollRN({
255
394
  if (((_c = options.animated) != null ? _c : true) === false) {
256
395
  scrollX.setValue(nextScrollLeft);
257
396
  scrollXValueRef.current = nextScrollLeft;
397
+ if (showNavigationTabs) {
398
+ setScrollProgress(safeIndex);
399
+ }
258
400
  }
259
401
  },
260
402
  [
@@ -265,6 +407,7 @@ function OverlappingCardsScrollRN({
265
407
  layout.scrollRange,
266
408
  layout.stepDistance,
267
409
  scrollX,
410
+ showNavigationTabs,
268
411
  stopFocusTransitionAnimation
269
412
  ]
270
413
  );
@@ -289,11 +432,13 @@ function OverlappingCardsScrollRN({
289
432
  extrapolate: "clamp"
290
433
  });
291
434
  }, [focusTransition, focusTransitionProgress, layout.stepDistance, scrollX]);
435
+ const progress = showNavigationTabs ? scrollProgress : 0;
436
+ const activeIndex = Math.floor(progress);
292
437
  const renderPageDots = (placement) => {
293
438
  if (!showNavigationDots || resolvedPageDotsPosition !== placement) {
294
439
  return null;
295
440
  }
296
- const rowStyle = placement === "above" ? [styles.pageDotsRow, { marginBottom: pageDotsOffset }] : placement === "below" ? [styles.pageDotsRow, { marginTop: pageDotsOffset }] : [styles.pageDotsRow, styles.pageDotsOverlay, { bottom: pageDotsOffset }];
441
+ const rowStyle = placement === "above" ? [styles.pageDotsRow, { marginBottom: resolvedPageDotsOffset }] : placement === "below" ? [styles.pageDotsRow, { marginTop: resolvedPageDotsOffset }] : [styles.pageDotsRow, styles.pageDotsOverlay, { bottom: resolvedPageDotsOffset }];
297
442
  return /* @__PURE__ */ jsx(
298
443
  View,
299
444
  {
@@ -329,12 +474,63 @@ function OverlappingCardsScrollRN({
329
474
  }
330
475
  );
331
476
  };
477
+ const renderTabs = (position) => {
478
+ if (!showNavigationTabs || resolvedTabsPosition !== position || cardNames === null) {
479
+ return null;
480
+ }
481
+ const containerStyle = position === "above" ? [styles.tabsRow, { marginBottom: resolvedTabsOffset }] : [styles.tabsRow, { marginTop: resolvedTabsOffset }];
482
+ return /* @__PURE__ */ jsx(
483
+ TabsContainerComponent,
484
+ {
485
+ position,
486
+ className: `rn-ocs-tabs rn-ocs-tabs--${position}`,
487
+ style: containerStyle,
488
+ ariaLabel: "Card tabs",
489
+ cardNames,
490
+ activeIndex,
491
+ progress,
492
+ children: cardNames.map((name, index) => {
493
+ const influence = clamp(1 - Math.abs(progress - index), 0, 1);
494
+ const isPrincipal = influence > 0.98;
495
+ const animate = {
496
+ opacity: 0.45 + influence * 0.55
497
+ };
498
+ const pressTab = () => focusCard(index, {
499
+ animated: true,
500
+ transitionMode: "swoop"
501
+ });
502
+ return /* @__PURE__ */ jsx(
503
+ TabsComponent,
504
+ {
505
+ name,
506
+ index,
507
+ position,
508
+ isPrincipal,
509
+ influence,
510
+ animate,
511
+ className: isPrincipal ? "rn-ocs-tab rn-ocs-tab--active" : "rn-ocs-tab",
512
+ style: { opacity: animate.opacity },
513
+ textStyle: isPrincipal ? styles.tabTextActive : void 0,
514
+ ariaLabel: `Go to ${name}`,
515
+ ariaCurrent: isPrincipal ? "page" : void 0,
516
+ accessibilityLabel: `Go to ${name}`,
517
+ accessibilityState: { selected: isPrincipal },
518
+ onPress: pressTab,
519
+ onClick: pressTab
520
+ },
521
+ `rn-ocs-tab-${position}-${index}`
522
+ );
523
+ })
524
+ }
525
+ );
526
+ };
332
527
  return /* @__PURE__ */ jsx(OverlappingCardsScrollRNControllerContext.Provider, { value: controllerContextValue, children: /* @__PURE__ */ jsxs(View, { style: [styles.shell, style], children: [
528
+ renderTabs("above"),
333
529
  renderPageDots("above"),
334
530
  /* @__PURE__ */ jsxs(
335
531
  View,
336
532
  {
337
- style: [styles.root, { height: cardHeight }],
533
+ style: [styles.root, { height: resolvedCardHeight }],
338
534
  onLayout: (event) => {
339
535
  const width = event.nativeEvent.layout.width || 1;
340
536
  setViewportWidth(Math.max(1, width));
@@ -345,8 +541,8 @@ function OverlappingCardsScrollRN({
345
541
  {
346
542
  ref: scrollRef,
347
543
  horizontal: true,
348
- style: [styles.scrollRegion, { height: cardHeight }],
349
- contentContainerStyle: { width: layout.trackWidth, height: cardHeight },
544
+ style: [styles.scrollRegion, { height: resolvedCardHeight }],
545
+ contentContainerStyle: { width: layout.trackWidth, height: resolvedCardHeight },
350
546
  onScroll,
351
547
  onScrollBeginDrag: cancelFocusTransition,
352
548
  onMomentumScrollBegin: cancelFocusTransition,
@@ -356,7 +552,7 @@ function OverlappingCardsScrollRN({
356
552
  snapToAlignment: shouldSnapToCard ? "start" : void 0,
357
553
  decelerationRate: shouldSnapToCard ? snapDecelerationRate : "normal",
358
554
  disableIntervalMomentum: shouldSnapToCard ? snapDisableIntervalMomentum : false,
359
- children: /* @__PURE__ */ jsx(View, { style: [styles.track, { width: layout.trackWidth, height: cardHeight }], children: cards.map((card, index) => {
555
+ children: /* @__PURE__ */ jsx(View, { style: [styles.track, { width: layout.trackWidth, height: resolvedCardHeight }], children: cards.map((card, index) => {
360
556
  var _a;
361
557
  const restingRightX = index === 0 ? 0 : (index - 1) * layout.peek + layout.cardWidth;
362
558
  const restingLeftX = index * layout.peek;
@@ -381,13 +577,14 @@ function OverlappingCardsScrollRN({
381
577
  styles.card,
382
578
  {
383
579
  width: layout.cardWidth,
384
- height: cardHeight,
580
+ height: resolvedCardHeight,
385
581
  transform: [
386
582
  {
387
583
  translateX: Animated.add(scrollX, animatedCardX)
388
584
  }
389
585
  ]
390
- }
586
+ },
587
+ cardContainerStyle
391
588
  ],
392
589
  children: /* @__PURE__ */ jsx(OverlappingCardsScrollRNCardIndexContext.Provider, { value: index, children: card })
393
590
  },
@@ -400,7 +597,8 @@ function OverlappingCardsScrollRN({
400
597
  ]
401
598
  }
402
599
  ),
403
- renderPageDots("below")
600
+ renderPageDots("below"),
601
+ renderTabs("below")
404
602
  ] }) });
405
603
  }
406
604
  var styles = StyleSheet.create({
@@ -451,6 +649,36 @@ var styles = StyleSheet.create({
451
649
  borderRadius: 999,
452
650
  backgroundColor: "#1f4666"
453
651
  },
652
+ tabsRow: {
653
+ width: "100%",
654
+ flexDirection: "row",
655
+ alignItems: "center",
656
+ justifyContent: "center",
657
+ flexWrap: "wrap",
658
+ zIndex: 6
659
+ },
660
+ tab: {
661
+ borderRadius: 999,
662
+ borderWidth: 1,
663
+ borderColor: "rgba(30, 67, 99, 0.2)",
664
+ backgroundColor: "#eef5ff",
665
+ paddingHorizontal: 12,
666
+ paddingVertical: 6,
667
+ marginHorizontal: 4,
668
+ marginVertical: 4
669
+ },
670
+ tabPressed: {
671
+ opacity: 0.85
672
+ },
673
+ tabText: {
674
+ color: "#275070",
675
+ fontSize: 12,
676
+ fontWeight: "700",
677
+ letterSpacing: 0.2
678
+ },
679
+ tabTextActive: {
680
+ color: "#173047"
681
+ },
454
682
  focusTrigger: {
455
683
  alignSelf: "flex-start",
456
684
  borderRadius: 99,
@@ -1,26 +1,4 @@
1
- export declare function OverlappingCardsScrollRNFocusTrigger({ children, style, textStyle, transitionMode, onPress, ...pressableProps }: {
2
- [x: string]: any;
3
- children?: string;
4
- style?: any;
5
- textStyle?: any;
6
- transitionMode?: string;
7
- onPress?: any;
8
- }): import("react/jsx-runtime").JSX.Element;
9
- export declare function OverlappingCardsScrollRN({ children, style, cardHeight, cardWidth, cardWidthRatio, basePeek, minPeek, maxPeek, showsHorizontalScrollIndicator, snapToCardOnRelease, snapDecelerationRate, snapDisableIntervalMomentum, showPageDots, pageDotsPosition, pageDotsOffset, focusTransitionDuration, }: {
10
- children: any;
11
- style?: any;
12
- cardHeight?: number;
13
- cardWidth?: any;
14
- cardWidthRatio?: number;
15
- basePeek?: number;
16
- minPeek?: number;
17
- maxPeek?: number;
18
- showsHorizontalScrollIndicator?: boolean;
19
- snapToCardOnRelease?: boolean;
20
- snapDecelerationRate?: string;
21
- snapDisableIntervalMomentum?: boolean;
22
- showPageDots?: boolean;
23
- pageDotsPosition?: string;
24
- pageDotsOffset?: number;
25
- focusTransitionDuration?: number;
26
- }): import("react/jsx-runtime").JSX.Element;
1
+ import type { OverlappingCardsScrollRNFocusTriggerProps, OverlappingCardsScrollRNProps } from './OverlappingCardsScrollRN.types';
2
+ export type { OverlappingCardsScrollRNFocusTransitionMode, OverlappingCardsScrollRNFocusTriggerBehavior, OverlappingCardsScrollRNFocusTriggerProps, OverlappingCardsScrollRNItem, OverlappingCardsScrollRNPageDotsPosition, OverlappingCardsScrollRNProps, OverlappingCardsScrollRNSnapDecelerationRate, OverlappingCardsScrollRNTabsContainerProps, OverlappingCardsScrollRNTabProps, OverlappingCardsScrollRNTabsPosition, } from './OverlappingCardsScrollRN.types';
3
+ export declare function OverlappingCardsScrollRNFocusTrigger({ children, style, textStyle, behavior, transitionMode, disabled, accessibilityLabel, testID, onPress, onClick, ...pressableProps }: OverlappingCardsScrollRNFocusTriggerProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function OverlappingCardsScrollRN(props: OverlappingCardsScrollRNProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,74 @@
1
+ import type { ComponentProps, ComponentType, ReactNode } from 'react';
2
+ import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
3
+ import type { CardItem as OverlappingCardsScrollWebCardItem, OverlappingCardsScroll, OverlappingCardsScrollFocusTriggerProps as OverlappingCardsScrollWebFocusTriggerProps } from '../lib/OverlappingCardsScroll';
4
+ type OverlappingCardsScrollWebProps = ComponentProps<typeof OverlappingCardsScroll>;
5
+ type OverlappingCardsScrollRNSharedProps = Omit<OverlappingCardsScrollWebProps, 'children' | 'items' | 'cardContainerStyle' | 'tabsComponent' | 'tabsContainerComponent'>;
6
+ export type OverlappingCardsScrollRNPageDotsPosition = NonNullable<OverlappingCardsScrollWebProps['pageDotsPosition']>;
7
+ export type OverlappingCardsScrollRNFocusTriggerBehavior = OverlappingCardsScrollWebFocusTriggerProps['behavior'];
8
+ export type OverlappingCardsScrollRNFocusTransitionMode = NonNullable<OverlappingCardsScrollWebFocusTriggerProps['transitionMode']>;
9
+ export type OverlappingCardsScrollRNSnapDecelerationRate = 'normal' | 'fast' | number;
10
+ export type OverlappingCardsScrollRNItem = OverlappingCardsScrollWebCardItem;
11
+ export type OverlappingCardsScrollRNTabsPosition = 'above' | 'below';
12
+ export interface OverlappingCardsScrollRNTabProps {
13
+ name: string;
14
+ index: number;
15
+ position: OverlappingCardsScrollRNTabsPosition;
16
+ isPrincipal: boolean;
17
+ influence: number;
18
+ animate: {
19
+ opacity: number;
20
+ };
21
+ className: string;
22
+ style: StyleProp<ViewStyle>;
23
+ textStyle: StyleProp<TextStyle>;
24
+ ariaLabel: string;
25
+ ariaCurrent?: 'page';
26
+ accessibilityLabel: string;
27
+ accessibilityState?: {
28
+ selected?: boolean;
29
+ };
30
+ onPress: () => void;
31
+ onClick: () => void;
32
+ }
33
+ export interface OverlappingCardsScrollRNTabsContainerProps {
34
+ children: ReactNode;
35
+ position: OverlappingCardsScrollRNTabsPosition;
36
+ className: string;
37
+ style: StyleProp<ViewStyle>;
38
+ ariaLabel: string;
39
+ cardNames: string[];
40
+ activeIndex: number;
41
+ progress: number;
42
+ }
43
+ type OverlappingCardsScrollRNWithChildren = OverlappingCardsScrollRNSharedProps & {
44
+ children: ReactNode;
45
+ items?: never;
46
+ };
47
+ type OverlappingCardsScrollRNWithItems = OverlappingCardsScrollRNSharedProps & {
48
+ items: OverlappingCardsScrollRNItem[];
49
+ children?: never;
50
+ };
51
+ type OverlappingCardsScrollRNContentProps = OverlappingCardsScrollRNWithChildren | OverlappingCardsScrollRNWithItems;
52
+ export type OverlappingCardsScrollRNProps = OverlappingCardsScrollRNContentProps & {
53
+ style?: StyleProp<ViewStyle>;
54
+ cardContainerStyle?: StyleProp<ViewStyle>;
55
+ tabsComponent?: ComponentType<OverlappingCardsScrollRNTabProps>;
56
+ tabsContainerComponent?: ComponentType<OverlappingCardsScrollRNTabsContainerProps>;
57
+ showsHorizontalScrollIndicator?: boolean;
58
+ snapDecelerationRate?: OverlappingCardsScrollRNSnapDecelerationRate;
59
+ snapDisableIntervalMomentum?: boolean;
60
+ };
61
+ export interface OverlappingCardsScrollRNFocusTriggerProps {
62
+ children?: ReactNode;
63
+ className?: string;
64
+ style?: StyleProp<ViewStyle>;
65
+ textStyle?: StyleProp<TextStyle>;
66
+ behavior?: OverlappingCardsScrollRNFocusTriggerBehavior;
67
+ transitionMode?: OverlappingCardsScrollRNFocusTransitionMode;
68
+ disabled?: boolean;
69
+ accessibilityLabel?: string;
70
+ testID?: string;
71
+ onPress?: (event: unknown) => void;
72
+ onClick?: (event: unknown) => void;
73
+ }
74
+ export {};
@@ -1,18 +1,4 @@
1
- import type { ComponentProps, ReactNode } from 'react';
2
- import type { StyleProp, ViewStyle } from 'react-native';
3
- import { OverlappingCardsScroll } from '../lib/OverlappingCardsScroll';
4
- interface OverlappingCardsScrollRNFocusTriggerProps extends Omit<ComponentProps<'button'>, 'onClick'> {
5
- children?: ReactNode;
6
- className?: string;
7
- onPress?: (event: unknown) => void;
8
- onClick?: (event: unknown) => void;
9
- }
10
- export declare function OverlappingCardsScrollRNFocusTrigger({ children, className, onPress, onClick, ...buttonProps }: OverlappingCardsScrollRNFocusTriggerProps): import("react/jsx-runtime").JSX.Element;
11
- type OverlappingCardsScrollRNProps = Omit<ComponentProps<typeof OverlappingCardsScroll>, 'items'> & {
12
- style?: StyleProp<ViewStyle>;
13
- showsHorizontalScrollIndicator?: boolean;
14
- snapDecelerationRate?: string;
15
- snapDisableIntervalMomentum?: boolean;
16
- };
17
- export declare function OverlappingCardsScrollRN({ children, style, showsHorizontalScrollIndicator, snapDecelerationRate, snapDisableIntervalMomentum, ...overlappingCardsScrollProps }: OverlappingCardsScrollRNProps): import("react/jsx-runtime").JSX.Element;
18
- export {};
1
+ import type { OverlappingCardsScrollRNFocusTriggerProps, OverlappingCardsScrollRNProps } from './OverlappingCardsScrollRN.types';
2
+ export type { OverlappingCardsScrollRNFocusTransitionMode, OverlappingCardsScrollRNFocusTriggerBehavior, OverlappingCardsScrollRNFocusTriggerProps, OverlappingCardsScrollRNItem, OverlappingCardsScrollRNPageDotsPosition, OverlappingCardsScrollRNProps, OverlappingCardsScrollRNSnapDecelerationRate, OverlappingCardsScrollRNTabsContainerProps, OverlappingCardsScrollRNTabProps, OverlappingCardsScrollRNTabsPosition, } from './OverlappingCardsScrollRN.types';
3
+ export declare function OverlappingCardsScrollRNFocusTrigger({ children, className, style, textStyle, behavior, transitionMode, disabled, accessibilityLabel, testID, onPress, onClick, ...buttonProps }: OverlappingCardsScrollRNFocusTriggerProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function OverlappingCardsScrollRN({ style, showsHorizontalScrollIndicator, snapDecelerationRate, snapDisableIntervalMomentum, ...overlappingCardsScrollProps }: OverlappingCardsScrollRNProps): import("react/jsx-runtime").JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlapping-cards-scroll",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Overlapping cards scroll component for React, React Native, and React Native Web.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -40,6 +40,8 @@
40
40
  },
41
41
  "files": [
42
42
  "dist",
43
+ "src/lib",
44
+ "src/rn",
43
45
  "README.md",
44
46
  "LICENSE"
45
47
  ],
@@ -67,7 +69,7 @@
67
69
  },
68
70
  "scripts": {
69
71
  "dev": "vite",
70
- "dev:expo": "expo start",
72
+ "dev:expo": "node ./node_modules/expo/bin/cli start ./expo-demo",
71
73
  "build": "npm run build:package",
72
74
  "build:package": "node ./scripts/build-package.mjs && npm run build:types",
73
75
  "build:types": "tsc -p tsconfig.package.json",
@@ -75,7 +77,10 @@
75
77
  "typecheck": "tsc --noEmit",
76
78
  "lint": "eslint .",
77
79
  "preview": "vite preview --outDir web-build",
78
- "prepack": "npm run build:package"
80
+ "prepack": "npm run build:package",
81
+ "patch": "npm version patch",
82
+ "publish": "npm publish --access public",
83
+ "npmlogin": "npm login"
79
84
  },
80
85
  "peerDependencies": {
81
86
  "react": "^18.0.0 || ^19.0.0",