@momo-kits/carousel 0.165.2-beta.3 → 0.167.1-beta.1
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/animation.ts +62 -0
- package/index.tsx +455 -390
- package/package.json +5 -6
- package/types.ts +48 -123
- package/core/LICENSE +0 -21
- package/core/README.md +0 -16
- package/core/components/Carousel.tsx +0 -28
- package/core/components/CarouselLayout.tsx +0 -231
- package/core/components/ItemLayout.tsx +0 -215
- package/core/components/ItemRenderer.tsx +0 -126
- package/core/components/LazyView.tsx +0 -14
- package/core/components/ScrollViewGesture.tsx +0 -443
- package/core/constants/index.ts +0 -11
- package/core/hooks/useAutoPlay.ts +0 -63
- package/core/hooks/useCarouselController.tsx +0 -295
- package/core/hooks/useCheckMounted.ts +0 -14
- package/core/hooks/useCommonVariables.ts +0 -261
- package/core/hooks/useInitProps.ts +0 -177
- package/core/hooks/useLayoutConfig.ts +0 -35
- package/core/hooks/useOffsetX.ts +0 -81
- package/core/hooks/useOnProgressChange.ts +0 -33
- package/core/hooks/usePanGestureProxy.ts +0 -144
- package/core/hooks/usePropsErrorBoundary.ts +0 -41
- package/core/hooks/useUpdateGestureConfig.ts +0 -17
- package/core/hooks/useVisibleRanges.tsx +0 -141
- package/core/layouts/index.tsx +0 -10
- package/core/layouts/normal.ts +0 -32
- package/core/layouts/parallax.ts +0 -50
- package/core/layouts/stack.ts +0 -266
- package/core/public-types.ts +0 -209
- package/core/store/index.tsx +0 -63
- package/core/types.ts +0 -32
- package/core/utils/carousel-direction.ts +0 -39
- package/core/utils/carousel-math.ts +0 -156
- package/core/utils/compute-gesture-translation.ts +0 -29
- package/core/utils/compute-offset-if-size-changed.ts +0 -14
- package/core/utils/computed-with-auto-fill-data.ts +0 -92
- package/core/utils/deal-with-animation.ts +0 -19
- package/core/utils/log.ts +0 -12
- package/core/utils/sanitize-animation-style.ts +0 -20
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
export function positiveModulo(value: number, divisor: number): number {
|
|
2
|
-
"worklet";
|
|
3
|
-
|
|
4
|
-
if (!Number.isFinite(value) || !Number.isFinite(divisor) || divisor <= 0) return 0;
|
|
5
|
-
|
|
6
|
-
const remainder = value % divisor;
|
|
7
|
-
return remainder < 0 ? remainder + divisor : remainder;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function getLogicalProgress(offset: number, itemSize: number): number {
|
|
11
|
-
"worklet";
|
|
12
|
-
|
|
13
|
-
if (!Number.isFinite(offset) || !Number.isFinite(itemSize) || itemSize <= 0) return 0;
|
|
14
|
-
return -offset / itemSize;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function getOffsetForLogicalPage(page: number, itemSize: number): number {
|
|
18
|
-
"worklet";
|
|
19
|
-
|
|
20
|
-
if (!Number.isFinite(page) || !Number.isFinite(itemSize) || itemSize <= 0) return 0;
|
|
21
|
-
if (page === 0) return 0;
|
|
22
|
-
return -page * itemSize;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getNearestLogicalPage(offset: number, itemSize: number): number {
|
|
26
|
-
"worklet";
|
|
27
|
-
|
|
28
|
-
return Math.round(getLogicalProgress(offset, itemSize));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function getSettledRawIndex(progress: number, count: number): number {
|
|
32
|
-
"worklet";
|
|
33
|
-
|
|
34
|
-
if (!Number.isFinite(count) || count <= 0) return 0;
|
|
35
|
-
return positiveModulo(Math.round(progress), Math.floor(count));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function getNearestLoopPosition(rawIndex: number, progress: number, count: number): number {
|
|
39
|
-
"worklet";
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
!Number.isFinite(rawIndex) ||
|
|
43
|
-
!Number.isFinite(progress) ||
|
|
44
|
-
!Number.isFinite(count) ||
|
|
45
|
-
count <= 0
|
|
46
|
-
) {
|
|
47
|
-
return 0;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const safeCount = Math.floor(count);
|
|
51
|
-
const normalizedIndex = positiveModulo(Math.round(rawIndex), safeCount);
|
|
52
|
-
const lowerCycle = Math.floor((progress - normalizedIndex) / safeCount);
|
|
53
|
-
const lower = normalizedIndex + lowerCycle * safeCount;
|
|
54
|
-
const upper = lower + safeCount;
|
|
55
|
-
const lowerDistance = Math.abs(progress - lower);
|
|
56
|
-
const upperDistance = Math.abs(upper - progress);
|
|
57
|
-
|
|
58
|
-
if (upperDistance < lowerDistance) return upper;
|
|
59
|
-
if (lowerDistance < upperDistance) return lower;
|
|
60
|
-
|
|
61
|
-
// An exact tie resolves in the logical forward direction.
|
|
62
|
-
return upper >= progress ? upper : lower;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function getRelativeProgress(params: {
|
|
66
|
-
rawIndex: number;
|
|
67
|
-
progress: number;
|
|
68
|
-
count: number;
|
|
69
|
-
loop: boolean;
|
|
70
|
-
}): number {
|
|
71
|
-
"worklet";
|
|
72
|
-
|
|
73
|
-
const { rawIndex, progress, count, loop } = params;
|
|
74
|
-
if (!Number.isFinite(progress)) return 0;
|
|
75
|
-
|
|
76
|
-
const itemPosition = loop ? getNearestLoopPosition(rawIndex, progress, count) : rawIndex;
|
|
77
|
-
return itemPosition - progress;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function getBoundedLoopOffset(offset: number, itemSize: number, count: number): number {
|
|
81
|
-
"worklet";
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
!Number.isFinite(offset) ||
|
|
85
|
-
!Number.isFinite(itemSize) ||
|
|
86
|
-
!Number.isFinite(count) ||
|
|
87
|
-
itemSize <= 0 ||
|
|
88
|
-
count <= 0
|
|
89
|
-
) {
|
|
90
|
-
return 0;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const cycleSize = itemSize * Math.floor(count);
|
|
94
|
-
return offset % cycleSize;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function getShortestLoopTargetPage(params: {
|
|
98
|
-
currentPage: number;
|
|
99
|
-
targetIndex: number;
|
|
100
|
-
count: number;
|
|
101
|
-
}): number {
|
|
102
|
-
"worklet";
|
|
103
|
-
|
|
104
|
-
const { currentPage, targetIndex, count } = params;
|
|
105
|
-
if (
|
|
106
|
-
!Number.isFinite(currentPage) ||
|
|
107
|
-
!Number.isInteger(targetIndex) ||
|
|
108
|
-
!Number.isInteger(count) ||
|
|
109
|
-
count <= 0
|
|
110
|
-
) {
|
|
111
|
-
return 0;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const currentRawIndex = positiveModulo(currentPage, count);
|
|
115
|
-
const forwardDistance = positiveModulo(targetIndex - currentRawIndex, count);
|
|
116
|
-
const backwardDistance = forwardDistance - count;
|
|
117
|
-
const distance =
|
|
118
|
-
Math.abs(forwardDistance) <= Math.abs(backwardDistance) ? forwardDistance : backwardDistance;
|
|
119
|
-
|
|
120
|
-
return currentPage + distance;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function reconcileOffsetAfterDataChange(params: {
|
|
124
|
-
offset: number;
|
|
125
|
-
itemSize: number;
|
|
126
|
-
previousCount: number;
|
|
127
|
-
nextCount: number;
|
|
128
|
-
defaultIndex: number;
|
|
129
|
-
loop: boolean;
|
|
130
|
-
retainedIndex?: number | undefined;
|
|
131
|
-
}): number {
|
|
132
|
-
"worklet";
|
|
133
|
-
|
|
134
|
-
const { offset, itemSize, previousCount, nextCount, defaultIndex, loop, retainedIndex } = params;
|
|
135
|
-
if (!Number.isInteger(nextCount) || nextCount <= 0 || itemSize <= 0) return 0;
|
|
136
|
-
|
|
137
|
-
if (!Number.isInteger(previousCount) || previousCount <= 0) {
|
|
138
|
-
const initialIndex = Math.max(0, Math.min(nextCount - 1, defaultIndex));
|
|
139
|
-
return getOffsetForLogicalPage(initialIndex, itemSize);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const currentPage = getNearestLogicalPage(offset, itemSize);
|
|
143
|
-
const previousRawIndex = positiveModulo(currentPage, previousCount);
|
|
144
|
-
const nextRawIndex =
|
|
145
|
-
typeof retainedIndex === "number" &&
|
|
146
|
-
Number.isInteger(retainedIndex) &&
|
|
147
|
-
retainedIndex >= 0 &&
|
|
148
|
-
retainedIndex < nextCount
|
|
149
|
-
? retainedIndex
|
|
150
|
-
: Math.min(previousRawIndex, nextCount - 1);
|
|
151
|
-
const nextPage = loop
|
|
152
|
-
? getNearestLoopPosition(nextRawIndex, currentPage, nextCount)
|
|
153
|
-
: nextRawIndex;
|
|
154
|
-
|
|
155
|
-
return getOffsetForLogicalPage(nextPage, itemSize);
|
|
156
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export function computeGestureTranslation(options: {
|
|
2
|
-
loop: boolean;
|
|
3
|
-
overscrollEnabled: boolean;
|
|
4
|
-
currentTranslation: number;
|
|
5
|
-
panOffset: number;
|
|
6
|
-
panTranslation: number;
|
|
7
|
-
max: number;
|
|
8
|
-
}): number {
|
|
9
|
-
"worklet";
|
|
10
|
-
const { loop, overscrollEnabled, currentTranslation, panOffset, panTranslation, max } = options;
|
|
11
|
-
const raw = panOffset + panTranslation;
|
|
12
|
-
|
|
13
|
-
if (loop) return raw;
|
|
14
|
-
|
|
15
|
-
if (!overscrollEnabled) {
|
|
16
|
-
// In non-loop mode with overscroll disabled, translation must stay in [-max, 0].
|
|
17
|
-
return Math.min(0, Math.max(-max, raw));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Keep resistance behavior only when overscroll is enabled.
|
|
21
|
-
if (currentTranslation > 0 || currentTranslation < -max) {
|
|
22
|
-
const boundary = currentTranslation > 0 ? 0 : -max;
|
|
23
|
-
const fixed = boundary - panOffset;
|
|
24
|
-
const dynamic = panTranslation - fixed;
|
|
25
|
-
return boundary + dynamic * 0.5;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return raw;
|
|
29
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function computeOffsetIfSizeChanged(params: {
|
|
2
|
-
handlerOffset: number;
|
|
3
|
-
prevSize: number;
|
|
4
|
-
size: number;
|
|
5
|
-
}) {
|
|
6
|
-
"worklet";
|
|
7
|
-
const { handlerOffset, prevSize, size } = params;
|
|
8
|
-
|
|
9
|
-
if (!prevSize) {
|
|
10
|
-
return handlerOffset;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return (handlerOffset / prevSize) * size;
|
|
14
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { DATA_LENGTH } from "../constants";
|
|
2
|
-
|
|
3
|
-
const { SINGLE_ITEM, DOUBLE_ITEM } = DATA_LENGTH;
|
|
4
|
-
|
|
5
|
-
function isAutoFillData(params: { autoFillData: boolean; loop: boolean }) {
|
|
6
|
-
"worklet";
|
|
7
|
-
return !!params.loop && !!params.autoFillData;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type BaseParams<T extends object> = {
|
|
11
|
-
autoFillData: boolean;
|
|
12
|
-
loop: boolean;
|
|
13
|
-
} & T;
|
|
14
|
-
|
|
15
|
-
export function convertToSharedIndex(params: BaseParams<{ index: number; rawDataLength: number }>) {
|
|
16
|
-
"worklet";
|
|
17
|
-
const { loop, rawDataLength, index, autoFillData } = params;
|
|
18
|
-
|
|
19
|
-
if (isAutoFillData({ loop, autoFillData })) {
|
|
20
|
-
switch (rawDataLength) {
|
|
21
|
-
case SINGLE_ITEM:
|
|
22
|
-
return 0;
|
|
23
|
-
case DOUBLE_ITEM:
|
|
24
|
-
return index % 2;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return index;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function computedOffsetXValueWithAutoFillData(
|
|
32
|
-
params: BaseParams<{
|
|
33
|
-
rawDataLength: number;
|
|
34
|
-
value: number;
|
|
35
|
-
size: number;
|
|
36
|
-
}>
|
|
37
|
-
) {
|
|
38
|
-
"worklet";
|
|
39
|
-
|
|
40
|
-
const { rawDataLength, value, size, loop, autoFillData } = params;
|
|
41
|
-
|
|
42
|
-
if (isAutoFillData({ loop, autoFillData })) {
|
|
43
|
-
switch (rawDataLength) {
|
|
44
|
-
case SINGLE_ITEM:
|
|
45
|
-
return value % size;
|
|
46
|
-
case DOUBLE_ITEM:
|
|
47
|
-
return value % (size * 2);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function computedRealIndexWithAutoFillData(
|
|
55
|
-
params: BaseParams<{
|
|
56
|
-
index: number;
|
|
57
|
-
dataLength: number;
|
|
58
|
-
}>
|
|
59
|
-
) {
|
|
60
|
-
const { index, dataLength, loop, autoFillData } = params;
|
|
61
|
-
|
|
62
|
-
if (isAutoFillData({ loop, autoFillData })) {
|
|
63
|
-
switch (dataLength) {
|
|
64
|
-
case SINGLE_ITEM:
|
|
65
|
-
return index % 1;
|
|
66
|
-
case DOUBLE_ITEM:
|
|
67
|
-
return index % 2;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return index;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function computedFillDataWithAutoFillData<T>(
|
|
75
|
-
params: BaseParams<{
|
|
76
|
-
data: T[];
|
|
77
|
-
dataLength: number;
|
|
78
|
-
}>
|
|
79
|
-
): T[] {
|
|
80
|
-
const { data, loop, autoFillData, dataLength } = params;
|
|
81
|
-
|
|
82
|
-
if (isAutoFillData({ loop, autoFillData })) {
|
|
83
|
-
switch (dataLength) {
|
|
84
|
-
case SINGLE_ITEM:
|
|
85
|
-
return [data[0]!, data[0]!, data[0]!];
|
|
86
|
-
case DOUBLE_ITEM:
|
|
87
|
-
return [data[0]!, data[1]!, data[0]!, data[1]!];
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return data;
|
|
92
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { withSpring, withTiming } from "react-native-reanimated";
|
|
2
|
-
|
|
3
|
-
import type { CarouselAnimation } from "../types";
|
|
4
|
-
|
|
5
|
-
export function dealWithAnimation(
|
|
6
|
-
animation: CarouselAnimation
|
|
7
|
-
): (value: number, cb: (isFinished: boolean) => void) => number {
|
|
8
|
-
"worklet";
|
|
9
|
-
switch (animation.type) {
|
|
10
|
-
case "spring": {
|
|
11
|
-
const { type: _, ...config } = animation;
|
|
12
|
-
return (value, cb) => withSpring(value, config, (isFinished) => cb(isFinished as boolean));
|
|
13
|
-
}
|
|
14
|
-
case "timing": {
|
|
15
|
-
const { type: _, ...config } = animation;
|
|
16
|
-
return (value, cb) => withTiming(value, config, (isFinished) => cb(isFinished as boolean));
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
package/core/utils/log.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ViewStyle } from "react-native";
|
|
2
|
-
|
|
3
|
-
type MutableViewStyle = ViewStyle & { zIndex?: unknown };
|
|
4
|
-
|
|
5
|
-
export function sanitizeAnimationStyle(style: ViewStyle): ViewStyle {
|
|
6
|
-
"worklet";
|
|
7
|
-
|
|
8
|
-
if (!style || typeof style !== "object") return {};
|
|
9
|
-
|
|
10
|
-
const nextStyle: MutableViewStyle = { ...style };
|
|
11
|
-
const { zIndex, ...restStyle } = nextStyle;
|
|
12
|
-
|
|
13
|
-
if (typeof zIndex === "number") {
|
|
14
|
-
// Native layers are sensitive to invalid/non-integer zIndex values.
|
|
15
|
-
if (Number.isFinite(zIndex)) return { ...restStyle, zIndex: Math.round(zIndex) };
|
|
16
|
-
return restStyle;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return typeof zIndex === "undefined" ? nextStyle : restStyle;
|
|
20
|
-
}
|