@ncdai/react-wheel-picker 1.0.3 → 1.0.4
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.d.mts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -488
- package/dist/index.mjs +1 -481
- package/package.json +16 -5
package/dist/index.d.mts
CHANGED
|
@@ -54,5 +54,4 @@ type WheelPickerWrapperProps = {
|
|
|
54
54
|
declare const WheelPickerWrapper: React$1.FC<WheelPickerWrapperProps>;
|
|
55
55
|
declare const WheelPicker: React$1.FC<WheelPickerProps>;
|
|
56
56
|
|
|
57
|
-
export { WheelPicker, WheelPickerWrapper };
|
|
58
|
-
export type { WheelPickerClassNames, WheelPickerOption };
|
|
57
|
+
export { WheelPicker, type WheelPickerClassNames, type WheelPickerOption, WheelPickerWrapper };
|
package/dist/index.d.ts
CHANGED
|
@@ -54,5 +54,4 @@ type WheelPickerWrapperProps = {
|
|
|
54
54
|
declare const WheelPickerWrapper: React$1.FC<WheelPickerWrapperProps>;
|
|
55
55
|
declare const WheelPicker: React$1.FC<WheelPickerProps>;
|
|
56
56
|
|
|
57
|
-
export { WheelPicker, WheelPickerWrapper };
|
|
58
|
-
export type { WheelPickerClassNames, WheelPickerOption };
|
|
57
|
+
export { WheelPicker, type WheelPickerClassNames, type WheelPickerOption, WheelPickerWrapper };
|
package/dist/index.js
CHANGED
|
@@ -1,488 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
-
|
|
4
|
-
var React = require('react');
|
|
5
|
-
|
|
6
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
-
|
|
8
|
-
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
9
|
-
|
|
10
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */ // This code comes from https://github.com/radix-ui/primitives/blob/main/packages/react/use-controllable-state/src/useControllableState.tsx
|
|
11
|
-
function useCallbackRef(callback) {
|
|
12
|
-
const callbackRef = React__default.default.useRef(callback);
|
|
13
|
-
React__default.default.useEffect(()=>{
|
|
14
|
-
callbackRef.current = callback;
|
|
15
|
-
});
|
|
16
|
-
// https://github.com/facebook/react/issues/19240
|
|
17
|
-
return React__default.default.useMemo(()=>(...args)=>callbackRef.current == null ? void 0 : callbackRef.current.call(callbackRef, ...args), []);
|
|
18
|
-
}
|
|
19
|
-
function useUncontrolledState({ defaultProp, onChange }) {
|
|
20
|
-
const uncontrolledState = React__default.default.useState(defaultProp);
|
|
21
|
-
const [value] = uncontrolledState;
|
|
22
|
-
const prevValueRef = React__default.default.useRef(value);
|
|
23
|
-
const handleChange = useCallbackRef(onChange);
|
|
24
|
-
React__default.default.useEffect(()=>{
|
|
25
|
-
if (prevValueRef.current !== value) {
|
|
26
|
-
handleChange(value);
|
|
27
|
-
prevValueRef.current = value;
|
|
28
|
-
}
|
|
29
|
-
}, [
|
|
30
|
-
value,
|
|
31
|
-
prevValueRef,
|
|
32
|
-
handleChange
|
|
33
|
-
]);
|
|
34
|
-
return uncontrolledState;
|
|
35
|
-
}
|
|
36
|
-
function useControllableState({ prop, defaultProp, onChange = ()=>{} }) {
|
|
37
|
-
const [uncontrolledProp, setUncontrolledProp] = useUncontrolledState({
|
|
38
|
-
defaultProp,
|
|
39
|
-
onChange
|
|
40
|
-
});
|
|
41
|
-
const isControlled = prop !== undefined;
|
|
42
|
-
const value = isControlled ? prop : uncontrolledProp;
|
|
43
|
-
const handleChange = useCallbackRef(onChange);
|
|
44
|
-
const setValue = React__default.default.useCallback((nextValue)=>{
|
|
45
|
-
if (isControlled) {
|
|
46
|
-
const setter = nextValue;
|
|
47
|
-
const value = typeof nextValue === "function" ? setter(prop) : nextValue;
|
|
48
|
-
if (value !== prop) handleChange(value);
|
|
49
|
-
} else {
|
|
50
|
-
setUncontrolledProp(nextValue);
|
|
51
|
-
}
|
|
52
|
-
}, [
|
|
53
|
-
isControlled,
|
|
54
|
-
prop,
|
|
55
|
-
setUncontrolledProp,
|
|
56
|
-
handleChange
|
|
57
|
-
]);
|
|
58
|
-
return [
|
|
59
|
-
value,
|
|
60
|
-
setValue
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const WHEEL_THROTTLE = 150; // ms
|
|
65
|
-
const RESISTANCE = 0.3; // Resistance when scrolling above the top or below the bottom
|
|
66
|
-
const MAX_VELOCITY = 30; // Maximum velocity for the scroll animation
|
|
67
|
-
const easeOutCubic = (p)=>Math.pow(p - 1, 3) + 1;
|
|
68
|
-
const WheelPickerWrapper = ({ className, children })=>{
|
|
69
|
-
return /*#__PURE__*/ React__default.default.createElement("div", {
|
|
70
|
-
className: className,
|
|
71
|
-
"data-rwp-wrapper": true
|
|
72
|
-
}, children);
|
|
73
|
-
};
|
|
74
|
-
const WheelPicker = ({ defaultValue, value: valueProp, onValueChange, options: optionsProp, infinite: infiniteProp = false, visibleCount: countProp = 20, dragSensitivity: dragSensitivityProp = 3, classNames })=>{
|
|
75
|
-
var _optionsProp__value;
|
|
76
|
-
const [value = (()=>{
|
|
77
|
-
var _optionsProp_;
|
|
78
|
-
return (_optionsProp__value = (_optionsProp_ = optionsProp[0]) == null ? void 0 : _optionsProp_.value) != null ? _optionsProp__value : "";
|
|
79
|
-
})(), setValue] = useControllableState({
|
|
80
|
-
defaultProp: defaultValue,
|
|
81
|
-
prop: valueProp,
|
|
82
|
-
onChange: onValueChange
|
|
83
|
-
});
|
|
84
|
-
const options = React.useMemo(()=>{
|
|
85
|
-
if (!infiniteProp) {
|
|
86
|
-
return optionsProp;
|
|
87
|
-
}
|
|
88
|
-
const result = [];
|
|
89
|
-
const halfCount = Math.ceil(countProp / 2);
|
|
90
|
-
if (optionsProp.length === 0) {
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
while(result.length < halfCount){
|
|
94
|
-
result.push(...optionsProp);
|
|
95
|
-
}
|
|
96
|
-
return result;
|
|
97
|
-
}, [
|
|
98
|
-
countProp,
|
|
99
|
-
optionsProp,
|
|
100
|
-
infiniteProp
|
|
101
|
-
]);
|
|
102
|
-
const itemHeight = 28;
|
|
103
|
-
const halfItemHeight = itemHeight * 0.5;
|
|
104
|
-
const itemAngle = 360 / countProp;
|
|
105
|
-
const radius = itemHeight / Math.tan(itemAngle * Math.PI / 180);
|
|
106
|
-
const containerHeight = Math.round(radius * 2 + itemHeight * 0.25);
|
|
107
|
-
const quarterCount = countProp >> 2; // Divide by 4
|
|
108
|
-
const baseDeceleration = dragSensitivityProp * 10;
|
|
109
|
-
const snapBackDeceleration = 10;
|
|
110
|
-
const containerRef = React.useRef(null);
|
|
111
|
-
const wheelItemsRef = React.useRef(null);
|
|
112
|
-
const highlightListRef = React.useRef(null);
|
|
113
|
-
const scrollRef = React.useRef(0);
|
|
114
|
-
const moveId = React.useRef(0);
|
|
115
|
-
const dragingRef = React.useRef(false);
|
|
116
|
-
const lastWheelRef = React.useRef(0);
|
|
117
|
-
const touchDataRef = React.useRef({
|
|
118
|
-
startY: 0,
|
|
119
|
-
yList: []
|
|
120
|
-
});
|
|
121
|
-
const dragControllerRef = React.useRef(null);
|
|
122
|
-
const renderWheelItems = React.useMemo(()=>{
|
|
123
|
-
const renderItem = (item, index, angle)=>/*#__PURE__*/ React__default.default.createElement("li", {
|
|
124
|
-
key: index,
|
|
125
|
-
className: classNames == null ? void 0 : classNames.optionItem,
|
|
126
|
-
"data-rwp-option": true,
|
|
127
|
-
"data-index": index,
|
|
128
|
-
style: {
|
|
129
|
-
top: -14,
|
|
130
|
-
height: itemHeight,
|
|
131
|
-
lineHeight: `${itemHeight}px`,
|
|
132
|
-
transform: `rotateX(${angle}deg) translateZ(${radius}px)`,
|
|
133
|
-
visibility: "hidden"
|
|
134
|
-
}
|
|
135
|
-
}, item.label);
|
|
136
|
-
const items = options.map((option, index)=>renderItem(option, index, -itemAngle * index));
|
|
137
|
-
if (infiniteProp) {
|
|
138
|
-
for(let i = 0; i < quarterCount; ++i){
|
|
139
|
-
const prependIndex = -i - 1;
|
|
140
|
-
const appendIndex = i + options.length;
|
|
141
|
-
items.unshift(renderItem(options[options.length - i - 1], prependIndex, itemAngle * (i + 1)));
|
|
142
|
-
items.push(renderItem(options[i], appendIndex, -itemAngle * appendIndex));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return items;
|
|
146
|
-
}, [
|
|
147
|
-
halfItemHeight,
|
|
148
|
-
infiniteProp,
|
|
149
|
-
itemAngle,
|
|
150
|
-
options,
|
|
151
|
-
quarterCount,
|
|
152
|
-
radius,
|
|
153
|
-
classNames == null ? void 0 : classNames.optionItem
|
|
154
|
-
]);
|
|
155
|
-
const renderHighlightItems = React.useMemo(()=>{
|
|
156
|
-
const renderItem = (item, key)=>/*#__PURE__*/ React__default.default.createElement("li", {
|
|
157
|
-
key: key,
|
|
158
|
-
"data-slot": "highlight-item",
|
|
159
|
-
className: classNames == null ? void 0 : classNames.highlightItem,
|
|
160
|
-
style: {
|
|
161
|
-
height: itemHeight
|
|
162
|
-
}
|
|
163
|
-
}, item.label);
|
|
164
|
-
const items = options.map((option, index)=>renderItem(option, index));
|
|
165
|
-
if (infiniteProp) {
|
|
166
|
-
const firstItem = options[0];
|
|
167
|
-
const lastItem = options[options.length - 1];
|
|
168
|
-
items.unshift(renderItem(lastItem, "infinite-start"));
|
|
169
|
-
items.push(renderItem(firstItem, "infinite-end"));
|
|
170
|
-
}
|
|
171
|
-
return items;
|
|
172
|
-
}, [
|
|
173
|
-
classNames == null ? void 0 : classNames.highlightItem,
|
|
174
|
-
infiniteProp,
|
|
175
|
-
options
|
|
176
|
-
]);
|
|
177
|
-
const normalizeScroll = (scroll)=>(scroll % options.length + options.length) % options.length;
|
|
178
|
-
const scrollTo = (scroll)=>{
|
|
179
|
-
const normalizedScroll = infiniteProp ? normalizeScroll(scroll) : scroll;
|
|
180
|
-
if (wheelItemsRef.current) {
|
|
181
|
-
const transform = `translateZ(${-radius}px) rotateX(${itemAngle * normalizedScroll}deg)`;
|
|
182
|
-
wheelItemsRef.current.style.transform = transform;
|
|
183
|
-
wheelItemsRef.current.childNodes.forEach((node)=>{
|
|
184
|
-
const li = node;
|
|
185
|
-
const distance = Math.abs(Number(li.dataset.index) - normalizedScroll);
|
|
186
|
-
li.style.visibility = distance > quarterCount ? "hidden" : "visible";
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
if (highlightListRef.current) {
|
|
190
|
-
highlightListRef.current.style.transform = `translateY(${-normalizedScroll * itemHeight}px)`;
|
|
191
|
-
}
|
|
192
|
-
return normalizedScroll;
|
|
193
|
-
};
|
|
194
|
-
const cancelAnimation = ()=>{
|
|
195
|
-
cancelAnimationFrame(moveId.current);
|
|
196
|
-
};
|
|
197
|
-
const animateScroll = (startScroll, endScroll, duration, onComplete)=>{
|
|
198
|
-
if (startScroll === endScroll || duration === 0) {
|
|
199
|
-
scrollTo(startScroll);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const startTime = performance.now();
|
|
203
|
-
const totalDistance = endScroll - startScroll;
|
|
204
|
-
const tick = (currentTime)=>{
|
|
205
|
-
const elapsed = (currentTime - startTime) / 1000;
|
|
206
|
-
if (elapsed < duration) {
|
|
207
|
-
const progress = easeOutCubic(elapsed / duration);
|
|
208
|
-
scrollRef.current = scrollTo(startScroll + progress * totalDistance);
|
|
209
|
-
moveId.current = requestAnimationFrame(tick);
|
|
210
|
-
} else {
|
|
211
|
-
cancelAnimation();
|
|
212
|
-
scrollRef.current = scrollTo(endScroll);
|
|
213
|
-
onComplete == null ? void 0 : onComplete();
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
requestAnimationFrame(tick);
|
|
217
|
-
};
|
|
218
|
-
const selectByScroll = (scroll)=>{
|
|
219
|
-
const normalized = normalizeScroll(scroll) | 0;
|
|
220
|
-
const boundedScroll = infiniteProp ? normalized : Math.min(Math.max(normalized, 0), options.length - 1);
|
|
221
|
-
if (!infiniteProp && boundedScroll !== scroll) return;
|
|
222
|
-
scrollRef.current = scrollTo(boundedScroll);
|
|
223
|
-
const selected = options[scrollRef.current];
|
|
224
|
-
setValue(selected.value);
|
|
225
|
-
};
|
|
226
|
-
const selectByValue = (value)=>{
|
|
227
|
-
const index = options.findIndex((opt)=>opt.value === value);
|
|
228
|
-
if (index === -1) {
|
|
229
|
-
console.error("Invalid value selected:", value);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
cancelAnimation();
|
|
233
|
-
selectByScroll(index);
|
|
234
|
-
};
|
|
235
|
-
const updateScrollDuringDrag = (e)=>{
|
|
236
|
-
try {
|
|
237
|
-
var _e_touches_, _e_touches;
|
|
238
|
-
const currentY = (e instanceof MouseEvent ? e.clientY : (_e_touches = e.touches) == null ? void 0 : (_e_touches_ = _e_touches[0]) == null ? void 0 : _e_touches_.clientY) || 0;
|
|
239
|
-
const touchData = touchDataRef.current;
|
|
240
|
-
// Record current Y position with timestamp
|
|
241
|
-
touchData.yList.push([
|
|
242
|
-
currentY,
|
|
243
|
-
Date.now()
|
|
244
|
-
]);
|
|
245
|
-
if (touchData.yList.length > 5) {
|
|
246
|
-
touchData.yList.shift(); // Keep latest 5 points for velocity calc
|
|
247
|
-
}
|
|
248
|
-
// Calculate delta in scroll position based on drag distance
|
|
249
|
-
const dragDelta = (touchData.startY - currentY) / itemHeight;
|
|
250
|
-
let nextScroll = scrollRef.current + dragDelta;
|
|
251
|
-
if (infiniteProp) {
|
|
252
|
-
// Wrap scroll for infinite lists
|
|
253
|
-
nextScroll = normalizeScroll(nextScroll);
|
|
254
|
-
} else {
|
|
255
|
-
const maxIndex = options.length;
|
|
256
|
-
if (nextScroll < 0) {
|
|
257
|
-
// Apply resistance when dragging above top
|
|
258
|
-
nextScroll *= RESISTANCE;
|
|
259
|
-
} else if (nextScroll > maxIndex) {
|
|
260
|
-
// Apply resistance when dragging below bottom
|
|
261
|
-
nextScroll = maxIndex + (nextScroll - maxIndex) * RESISTANCE;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
// Update visual scroll and store position
|
|
265
|
-
touchData.touchScroll = scrollTo(nextScroll);
|
|
266
|
-
} catch (error) {
|
|
267
|
-
console.error("Error in updateScrollDuringDrag:", error);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
const handleDragMoveEvent = (event)=>{
|
|
271
|
-
if (!dragingRef.current && !containerRef.current.contains(event.target) && event.target !== containerRef.current) {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
if (event.cancelable) {
|
|
275
|
-
event.preventDefault();
|
|
276
|
-
}
|
|
277
|
-
if (options.length) {
|
|
278
|
-
updateScrollDuringDrag(event);
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
const initiateDragGesture = (event)=>{
|
|
282
|
-
try {
|
|
283
|
-
var _containerRef_current, _event_touches_, _event_touches;
|
|
284
|
-
dragingRef.current = true;
|
|
285
|
-
const controller = new AbortController();
|
|
286
|
-
const { signal } = controller;
|
|
287
|
-
dragControllerRef.current = controller;
|
|
288
|
-
// Listen to movement events
|
|
289
|
-
const passiveOpts = {
|
|
290
|
-
signal,
|
|
291
|
-
passive: false
|
|
292
|
-
};
|
|
293
|
-
(_containerRef_current = containerRef.current) == null ? void 0 : _containerRef_current.addEventListener("touchmove", handleDragMoveEvent, passiveOpts);
|
|
294
|
-
document.addEventListener("mousemove", handleDragMoveEvent, passiveOpts);
|
|
295
|
-
const startY = (event instanceof MouseEvent ? event.clientY : (_event_touches = event.touches) == null ? void 0 : (_event_touches_ = _event_touches[0]) == null ? void 0 : _event_touches_.clientY) || 0;
|
|
296
|
-
// Initialize touch tracking
|
|
297
|
-
const touchData = touchDataRef.current;
|
|
298
|
-
touchData.startY = startY;
|
|
299
|
-
touchData.yList = [
|
|
300
|
-
[
|
|
301
|
-
startY,
|
|
302
|
-
Date.now()
|
|
303
|
-
]
|
|
304
|
-
];
|
|
305
|
-
touchData.touchScroll = scrollRef.current;
|
|
306
|
-
// Stop any ongoing scroll animation
|
|
307
|
-
cancelAnimation();
|
|
308
|
-
} catch (error) {
|
|
309
|
-
console.error("Error in initiateDragGesture:", error);
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
const handleDragStartEvent = React.useCallback((e)=>{
|
|
313
|
-
const isDragging = dragingRef.current;
|
|
314
|
-
const isTargetValid = containerRef.current.contains(e.target) || e.target === containerRef.current;
|
|
315
|
-
if ((isDragging || isTargetValid) && e.cancelable) {
|
|
316
|
-
e.preventDefault();
|
|
317
|
-
if (options.length) {
|
|
318
|
-
initiateDragGesture(e);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
322
|
-
[
|
|
323
|
-
initiateDragGesture
|
|
324
|
-
]);
|
|
325
|
-
const decelerateAndAnimateScroll = (initialVelocity)=>{
|
|
326
|
-
const currentScroll = scrollRef.current;
|
|
327
|
-
let targetScroll = currentScroll;
|
|
328
|
-
let deceleration = initialVelocity > 0 ? -baseDeceleration : baseDeceleration;
|
|
329
|
-
let duration = 0;
|
|
330
|
-
// Clamp utility to constrain a value within bounds
|
|
331
|
-
const clamp = (value, min, max)=>Math.max(min, Math.min(value, max));
|
|
332
|
-
if (infiniteProp) {
|
|
333
|
-
// Infinite mode: apply uniform deceleration to calculate scroll distance
|
|
334
|
-
duration = Math.abs(initialVelocity / deceleration);
|
|
335
|
-
const scrollDistance = initialVelocity * duration + 0.5 * deceleration * duration * duration;
|
|
336
|
-
targetScroll = Math.round(currentScroll + scrollDistance);
|
|
337
|
-
} else if (currentScroll < 0 || currentScroll > options.length - 1) {
|
|
338
|
-
// Out-of-bounds: snap back to nearest valid scroll index
|
|
339
|
-
const target = clamp(currentScroll, 0, options.length - 1);
|
|
340
|
-
const scrollDistance = currentScroll - target;
|
|
341
|
-
deceleration = snapBackDeceleration;
|
|
342
|
-
duration = Math.sqrt(Math.abs(scrollDistance / deceleration));
|
|
343
|
-
initialVelocity = deceleration * duration;
|
|
344
|
-
initialVelocity = currentScroll > 0 ? -initialVelocity : initialVelocity;
|
|
345
|
-
targetScroll = target;
|
|
346
|
-
} else {
|
|
347
|
-
// Normal decelerated scroll within bounds
|
|
348
|
-
duration = Math.abs(initialVelocity / deceleration);
|
|
349
|
-
const scrollDistance = initialVelocity * duration + 0.5 * deceleration * duration * duration;
|
|
350
|
-
targetScroll = Math.round(currentScroll + scrollDistance);
|
|
351
|
-
targetScroll = clamp(targetScroll, 0, options.length - 1);
|
|
352
|
-
const adjustedDistance = targetScroll - currentScroll;
|
|
353
|
-
duration = Math.sqrt(Math.abs(adjustedDistance / deceleration));
|
|
354
|
-
}
|
|
355
|
-
// Start animation to target scroll position with calculated duration
|
|
356
|
-
animateScroll(currentScroll, targetScroll, duration, ()=>{
|
|
357
|
-
selectByScroll(scrollRef.current); // Ensure selected item updates at end
|
|
358
|
-
});
|
|
359
|
-
// Fallback selection update (in case animation callback fails)
|
|
360
|
-
selectByScroll(scrollRef.current);
|
|
361
|
-
};
|
|
362
|
-
const finalizeDragAndStartInertiaScroll = ()=>{
|
|
363
|
-
try {
|
|
364
|
-
var _dragControllerRef_current;
|
|
365
|
-
(_dragControllerRef_current = dragControllerRef.current) == null ? void 0 : _dragControllerRef_current.abort();
|
|
366
|
-
dragControllerRef.current = null;
|
|
367
|
-
const touchData = touchDataRef.current;
|
|
368
|
-
const yList = touchData.yList;
|
|
369
|
-
let velocity = 0;
|
|
370
|
-
if (yList.length > 1) {
|
|
371
|
-
const len = yList.length;
|
|
372
|
-
var _yList_;
|
|
373
|
-
const [startY, startTime] = (_yList_ = yList[len - 2]) != null ? _yList_ : [
|
|
374
|
-
0,
|
|
375
|
-
0
|
|
376
|
-
];
|
|
377
|
-
var _yList_1;
|
|
378
|
-
const [endY, endTime] = (_yList_1 = yList[len - 1]) != null ? _yList_1 : [
|
|
379
|
-
0,
|
|
380
|
-
0
|
|
381
|
-
];
|
|
382
|
-
const timeDiff = endTime - startTime;
|
|
383
|
-
if (timeDiff > 0) {
|
|
384
|
-
const distance = startY - endY;
|
|
385
|
-
const velocityPerSecond = distance / itemHeight * 1000 / timeDiff;
|
|
386
|
-
const maxVelocity = MAX_VELOCITY;
|
|
387
|
-
const direction = velocityPerSecond > 0 ? 1 : -1;
|
|
388
|
-
const absVelocity = Math.min(Math.abs(velocityPerSecond), maxVelocity);
|
|
389
|
-
velocity = absVelocity * direction;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
var _touchData_touchScroll;
|
|
393
|
-
scrollRef.current = (_touchData_touchScroll = touchData.touchScroll) != null ? _touchData_touchScroll : scrollRef.current;
|
|
394
|
-
decelerateAndAnimateScroll(velocity);
|
|
395
|
-
} catch (error) {
|
|
396
|
-
console.error("Error in finalizeDragAndStartInertiaScroll:", error);
|
|
397
|
-
} finally{
|
|
398
|
-
dragingRef.current = false;
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
const handleDragEndEvent = React.useCallback((event)=>{
|
|
402
|
-
if (!options.length) return;
|
|
403
|
-
const isDragging = dragingRef.current;
|
|
404
|
-
const isTargetValid = containerRef.current.contains(event.target) || event.target === containerRef.current;
|
|
405
|
-
if ((isDragging || isTargetValid) && event.cancelable) {
|
|
406
|
-
event.preventDefault();
|
|
407
|
-
finalizeDragAndStartInertiaScroll();
|
|
408
|
-
}
|
|
409
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
410
|
-
[
|
|
411
|
-
finalizeDragAndStartInertiaScroll
|
|
412
|
-
]);
|
|
413
|
-
const scrollByWheel = (event)=>{
|
|
414
|
-
event.preventDefault();
|
|
415
|
-
const now = Date.now();
|
|
416
|
-
if (now - lastWheelRef.current < WHEEL_THROTTLE) return;
|
|
417
|
-
const direction = Math.sign(event.deltaY);
|
|
418
|
-
if (direction !== 0) {
|
|
419
|
-
selectByScroll(scrollRef.current + direction);
|
|
420
|
-
lastWheelRef.current = now;
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
const handleWheelEvent = React.useCallback((event)=>{
|
|
424
|
-
if (!options.length || !containerRef.current) return;
|
|
425
|
-
const isDragging = dragingRef.current;
|
|
426
|
-
const isTargetValid = containerRef.current.contains(event.target) || event.target === containerRef.current;
|
|
427
|
-
if ((isDragging || isTargetValid) && event.cancelable) {
|
|
428
|
-
event.preventDefault();
|
|
429
|
-
scrollByWheel(event);
|
|
430
|
-
}
|
|
431
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
432
|
-
[
|
|
433
|
-
scrollByWheel
|
|
434
|
-
]);
|
|
435
|
-
React.useEffect(()=>{
|
|
436
|
-
const container = containerRef.current;
|
|
437
|
-
if (!container) return;
|
|
438
|
-
const controller = new AbortController();
|
|
439
|
-
const { signal } = controller;
|
|
440
|
-
const opts = {
|
|
441
|
-
signal,
|
|
442
|
-
passive: false
|
|
443
|
-
};
|
|
444
|
-
container.addEventListener("touchstart", handleDragStartEvent, opts);
|
|
445
|
-
container.addEventListener("touchend", handleDragEndEvent, opts);
|
|
446
|
-
container.addEventListener("wheel", handleWheelEvent, opts);
|
|
447
|
-
document.addEventListener("mousedown", handleDragStartEvent, opts);
|
|
448
|
-
document.addEventListener("mouseup", handleDragEndEvent, opts);
|
|
449
|
-
return ()=>controller.abort();
|
|
450
|
-
}, [
|
|
451
|
-
handleDragEndEvent,
|
|
452
|
-
handleDragStartEvent,
|
|
453
|
-
handleWheelEvent
|
|
454
|
-
]);
|
|
455
|
-
React.useEffect(()=>{
|
|
456
|
-
selectByValue(value);
|
|
457
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
458
|
-
}, [
|
|
459
|
-
value,
|
|
460
|
-
valueProp
|
|
461
|
-
]);
|
|
462
|
-
return /*#__PURE__*/ React__default.default.createElement("div", {
|
|
463
|
-
ref: containerRef,
|
|
464
|
-
"data-rwp": true,
|
|
465
|
-
style: {
|
|
466
|
-
height: containerHeight
|
|
467
|
-
}
|
|
468
|
-
}, /*#__PURE__*/ React__default.default.createElement("ul", {
|
|
469
|
-
ref: wheelItemsRef,
|
|
470
|
-
"data-rwp-options": true
|
|
471
|
-
}, renderWheelItems), /*#__PURE__*/ React__default.default.createElement("div", {
|
|
472
|
-
className: classNames == null ? void 0 : classNames.highlightWrapper,
|
|
473
|
-
"data-rwp-highlight-wrapper": true,
|
|
474
|
-
style: {
|
|
475
|
-
height: itemHeight,
|
|
476
|
-
lineHeight: itemHeight + "px"
|
|
477
|
-
}
|
|
478
|
-
}, /*#__PURE__*/ React__default.default.createElement("ul", {
|
|
479
|
-
ref: highlightListRef,
|
|
480
|
-
"data-rwp-highlight-list": true,
|
|
481
|
-
style: {
|
|
482
|
-
top: infiniteProp ? -28 : undefined
|
|
483
|
-
}
|
|
484
|
-
}, renderHighlightItems)));
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
exports.WheelPicker = WheelPicker;
|
|
488
|
-
exports.WheelPickerWrapper = WheelPickerWrapper;
|
|
1
|
+
"use client";var vt=Object.create;var x=Object.defineProperty;var Et=Object.getOwnPropertyDescriptor;var Tt=Object.getOwnPropertyNames;var Dt=Object.getPrototypeOf,Mt=Object.prototype.hasOwnProperty;var St=(c,l)=>{for(var d in l)x(c,d,{get:l[d],enumerable:!0})},et=(c,l,d,h)=>{if(l&&typeof l=="object"||typeof l=="function")for(let i of Tt(l))!Mt.call(c,i)&&i!==d&&x(c,i,{get:()=>l[i],enumerable:!(h=Et(l,i))||h.enumerable});return c};var nt=(c,l,d)=>(d=c!=null?vt(Dt(c)):{},et(l||!c||!c.__esModule?x(d,"default",{value:c,enumerable:!0}):d,c)),yt=c=>et(x({},"__esModule",{value:!0}),c);var xt={};St(xt,{WheelPicker:()=>kt,WheelPickerWrapper:()=>wt});module.exports=yt(xt);var M=nt(require("react")),u=require("react");var D=nt(require("react"));function rt(c){let l=D.default.useRef(c);return D.default.useEffect(()=>{l.current=c}),D.default.useMemo(()=>(...d)=>{var h;return(h=l.current)==null?void 0:h.call(l,...d)},[])}function Lt({defaultProp:c,onChange:l}){let d=D.default.useState(c),[h]=d,i=D.default.useRef(h),E=rt(l);return D.default.useEffect(()=>{i.current!==h&&(E(h),i.current=h)},[h,i,E]),d}function ot({prop:c,defaultProp:l,onChange:d=()=>{}}){let[h,i]=Lt({defaultProp:l,onChange:d}),E=c!==void 0,A=E?c:h,f=rt(d),W=D.default.useCallback(S=>{if(E){let m=typeof S=="function"?S(c):S;m!==c&&f(m)}else i(S)},[E,c,i,f]);return[A,W]}var It=150,ct=.3,Wt=30,Ct=c=>Math.pow(c-1,3)+1,wt=({className:c,children:l})=>M.default.createElement("div",{className:c,"data-rwp-wrapper":!0},l),kt=({defaultValue:c,value:l,onValueChange:d,options:h,infinite:i=!1,visibleCount:E=20,dragSensitivity:A=3,classNames:f})=>{var Q,V;let[W=(V=(Q=h[0])==null?void 0:Q.value)!=null?V:"",S]=ot({defaultProp:c,prop:l,onChange:d}),s=(0,u.useMemo)(()=>{if(!i)return h;let t=[],e=Math.ceil(E/2);if(h.length===0)return t;for(;t.length<e;)t.push(...h);return t},[E,h,i]),m=28,z=m*.5,y=360/E,C=m/Math.tan(y*Math.PI/180),st=Math.round(C*2+m*.25),Y=E>>2,B=A*10,at=10,b=(0,u.useRef)(null),w=(0,u.useRef)(null),R=(0,u.useRef)(null),v=(0,u.useRef)(0),X=(0,u.useRef)(0),L=(0,u.useRef)(!1),G=(0,u.useRef)(0),H=(0,u.useRef)({startY:0,yList:[]}),O=(0,u.useRef)(null),lt=(0,u.useMemo)(()=>{let t=(n,r,o)=>M.default.createElement("li",{key:r,className:f==null?void 0:f.optionItem,"data-rwp-option":!0,"data-index":r,style:{top:-z,height:m,lineHeight:`${m}px`,transform:`rotateX(${o}deg) translateZ(${C}px)`,visibility:"hidden"}},n.label),e=s.map((n,r)=>t(n,r,-y*r));if(i)for(let n=0;n<Y;++n){let r=-n-1,o=n+s.length;e.unshift(t(s[s.length-n-1],r,y*(n+1))),e.push(t(s[n],o,-y*o))}return e},[z,i,y,s,Y,C,f==null?void 0:f.optionItem]),it=(0,u.useMemo)(()=>{let t=(n,r)=>M.default.createElement("li",{key:r,"data-slot":"highlight-item",className:f==null?void 0:f.highlightItem,style:{height:m}},n.label),e=s.map((n,r)=>t(n,r));if(i){let n=s[0],r=s[s.length-1];e.unshift(t(r,"infinite-start")),e.push(t(n,"infinite-end"))}return e},[f==null?void 0:f.highlightItem,i,s]),F=t=>(t%s.length+s.length)%s.length,I=t=>{let e=i?F(t):t;if(w.current){let n=`translateZ(${-C}px) rotateX(${y*e}deg)`;w.current.style.transform=n,w.current.childNodes.forEach(r=>{let o=r,p=Math.abs(Number(o.dataset.index)-e);o.style.visibility=p>Y?"hidden":"visible"})}return R.current&&(R.current.style.transform=`translateY(${-e*m}px)`),e},P=()=>{cancelAnimationFrame(X.current)},ut=(t,e,n,r)=>{if(t===e||n===0){I(t);return}let o=performance.now(),p=e-t,a=g=>{let T=(g-o)/1e3;if(T<n){let q=Ct(T/n);v.current=I(t+q*p),X.current=requestAnimationFrame(a)}else P(),v.current=I(e),r==null||r()};requestAnimationFrame(a)},k=t=>{let e=F(t)|0,n=i?e:Math.min(Math.max(e,0),s.length-1);if(!i&&n!==t)return;v.current=I(n);let r=s[v.current];S(r.value)},ht=t=>{let e=s.findIndex(n=>n.value===t);if(e===-1){console.error("Invalid value selected:",t);return}P(),k(e)},dt=t=>{var e,n;try{let r=(t instanceof MouseEvent?t.clientY:(n=(e=t.touches)==null?void 0:e[0])==null?void 0:n.clientY)||0,o=H.current;o.yList.push([r,Date.now()]),o.yList.length>5&&o.yList.shift();let p=(o.startY-r)/m,a=v.current+p;if(i)a=F(a);else{let g=s.length;a<0?a*=ct:a>g&&(a=g+(a-g)*ct)}o.touchScroll=I(a)}catch(r){console.error("Error in updateScrollDuringDrag:",r)}},Z=t=>{!L.current&&!b.current.contains(t.target)&&t.target!==b.current||(t.cancelable&&t.preventDefault(),s.length&&dt(t))},_=t=>{var e,n,r;try{L.current=!0;let o=new AbortController,{signal:p}=o;O.current=o;let a={signal:p,passive:!1};(e=b.current)==null||e.addEventListener("touchmove",Z,a),document.addEventListener("mousemove",Z,a);let g=(t instanceof MouseEvent?t.clientY:(r=(n=t.touches)==null?void 0:n[0])==null?void 0:r.clientY)||0,T=H.current;T.startY=g,T.yList=[[g,Date.now()]],T.touchScroll=v.current,P()}catch(o){console.error("Error in initiateDragGesture:",o)}},U=(0,u.useCallback)(t=>{let e=L.current,n=b.current.contains(t.target)||t.target===b.current;(e||n)&&t.cancelable&&(t.preventDefault(),s.length&&_(t))},[_]),ft=t=>{let e=v.current,n=e,r=t>0?-B:B,o=0,p=(a,g,T)=>Math.max(g,Math.min(a,T));if(i){o=Math.abs(t/r);let a=t*o+.5*r*o*o;n=Math.round(e+a)}else if(e<0||e>s.length-1){let a=p(e,0,s.length-1),g=e-a;r=at,o=Math.sqrt(Math.abs(g/r)),t=r*o,t=e>0?-t:t,n=a}else{o=Math.abs(t/r);let a=t*o+.5*r*o*o;n=Math.round(e+a),n=p(n,0,s.length-1);let g=n-e;o=Math.sqrt(Math.abs(g/r))}ut(e,n,o,()=>{k(v.current)}),k(v.current)},j=()=>{var t,e,n,r;try{(t=O.current)==null||t.abort(),O.current=null;let o=H.current,p=o.yList,a=0;if(p.length>1){let g=p.length,[T,q]=(e=p[g-2])!=null?e:[0,0],[gt,mt]=(n=p[g-1])!=null?n:[0,0],N=mt-q;if(N>0){let tt=(T-gt)/m*1e3/N,pt=Wt,bt=tt>0?1:-1;a=Math.min(Math.abs(tt),pt)*bt}}v.current=(r=o.touchScroll)!=null?r:v.current,ft(a)}catch(o){console.error("Error in finalizeDragAndStartInertiaScroll:",o)}finally{L.current=!1}},$=(0,u.useCallback)(t=>{if(!s.length)return;let e=L.current,n=b.current.contains(t.target)||t.target===b.current;(e||n)&&t.cancelable&&(t.preventDefault(),j())},[j]),K=t=>{t.preventDefault();let e=Date.now();if(e-G.current<It)return;let n=Math.sign(t.deltaY);n!==0&&(k(v.current+n),G.current=e)},J=(0,u.useCallback)(t=>{if(!s.length||!b.current)return;let e=L.current,n=b.current.contains(t.target)||t.target===b.current;(e||n)&&t.cancelable&&(t.preventDefault(),K(t))},[K]);return(0,u.useEffect)(()=>{let t=b.current;if(!t)return;let e=new AbortController,{signal:n}=e,r={signal:n,passive:!1};return t.addEventListener("touchstart",U,r),t.addEventListener("touchend",$,r),t.addEventListener("wheel",J,r),document.addEventListener("mousedown",U,r),document.addEventListener("mouseup",$,r),()=>e.abort()},[$,U,J]),(0,u.useEffect)(()=>{ht(W)},[W,l]),M.default.createElement("div",{ref:b,"data-rwp":!0,style:{height:st}},M.default.createElement("ul",{ref:w,"data-rwp-options":!0},lt),M.default.createElement("div",{className:f==null?void 0:f.highlightWrapper,"data-rwp-highlight-wrapper":!0,style:{height:m,lineHeight:m+"px"}},M.default.createElement("ul",{ref:R,"data-rwp-highlight-list":!0,style:{top:i?-m:void 0}},it)))};0&&(module.exports={WheelPicker,WheelPickerWrapper});
|
package/dist/index.mjs
CHANGED
|
@@ -1,481 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import React, { useMemo, useRef, useCallback, useEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */ // This code comes from https://github.com/radix-ui/primitives/blob/main/packages/react/use-controllable-state/src/useControllableState.tsx
|
|
5
|
-
function useCallbackRef(callback) {
|
|
6
|
-
const callbackRef = React.useRef(callback);
|
|
7
|
-
React.useEffect(()=>{
|
|
8
|
-
callbackRef.current = callback;
|
|
9
|
-
});
|
|
10
|
-
// https://github.com/facebook/react/issues/19240
|
|
11
|
-
return React.useMemo(()=>(...args)=>callbackRef.current == null ? void 0 : callbackRef.current.call(callbackRef, ...args), []);
|
|
12
|
-
}
|
|
13
|
-
function useUncontrolledState({ defaultProp, onChange }) {
|
|
14
|
-
const uncontrolledState = React.useState(defaultProp);
|
|
15
|
-
const [value] = uncontrolledState;
|
|
16
|
-
const prevValueRef = React.useRef(value);
|
|
17
|
-
const handleChange = useCallbackRef(onChange);
|
|
18
|
-
React.useEffect(()=>{
|
|
19
|
-
if (prevValueRef.current !== value) {
|
|
20
|
-
handleChange(value);
|
|
21
|
-
prevValueRef.current = value;
|
|
22
|
-
}
|
|
23
|
-
}, [
|
|
24
|
-
value,
|
|
25
|
-
prevValueRef,
|
|
26
|
-
handleChange
|
|
27
|
-
]);
|
|
28
|
-
return uncontrolledState;
|
|
29
|
-
}
|
|
30
|
-
function useControllableState({ prop, defaultProp, onChange = ()=>{} }) {
|
|
31
|
-
const [uncontrolledProp, setUncontrolledProp] = useUncontrolledState({
|
|
32
|
-
defaultProp,
|
|
33
|
-
onChange
|
|
34
|
-
});
|
|
35
|
-
const isControlled = prop !== undefined;
|
|
36
|
-
const value = isControlled ? prop : uncontrolledProp;
|
|
37
|
-
const handleChange = useCallbackRef(onChange);
|
|
38
|
-
const setValue = React.useCallback((nextValue)=>{
|
|
39
|
-
if (isControlled) {
|
|
40
|
-
const setter = nextValue;
|
|
41
|
-
const value = typeof nextValue === "function" ? setter(prop) : nextValue;
|
|
42
|
-
if (value !== prop) handleChange(value);
|
|
43
|
-
} else {
|
|
44
|
-
setUncontrolledProp(nextValue);
|
|
45
|
-
}
|
|
46
|
-
}, [
|
|
47
|
-
isControlled,
|
|
48
|
-
prop,
|
|
49
|
-
setUncontrolledProp,
|
|
50
|
-
handleChange
|
|
51
|
-
]);
|
|
52
|
-
return [
|
|
53
|
-
value,
|
|
54
|
-
setValue
|
|
55
|
-
];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const WHEEL_THROTTLE = 150; // ms
|
|
59
|
-
const RESISTANCE = 0.3; // Resistance when scrolling above the top or below the bottom
|
|
60
|
-
const MAX_VELOCITY = 30; // Maximum velocity for the scroll animation
|
|
61
|
-
const easeOutCubic = (p)=>Math.pow(p - 1, 3) + 1;
|
|
62
|
-
const WheelPickerWrapper = ({ className, children })=>{
|
|
63
|
-
return /*#__PURE__*/ React.createElement("div", {
|
|
64
|
-
className: className,
|
|
65
|
-
"data-rwp-wrapper": true
|
|
66
|
-
}, children);
|
|
67
|
-
};
|
|
68
|
-
const WheelPicker = ({ defaultValue, value: valueProp, onValueChange, options: optionsProp, infinite: infiniteProp = false, visibleCount: countProp = 20, dragSensitivity: dragSensitivityProp = 3, classNames })=>{
|
|
69
|
-
var _optionsProp__value;
|
|
70
|
-
const [value = (()=>{
|
|
71
|
-
var _optionsProp_;
|
|
72
|
-
return (_optionsProp__value = (_optionsProp_ = optionsProp[0]) == null ? void 0 : _optionsProp_.value) != null ? _optionsProp__value : "";
|
|
73
|
-
})(), setValue] = useControllableState({
|
|
74
|
-
defaultProp: defaultValue,
|
|
75
|
-
prop: valueProp,
|
|
76
|
-
onChange: onValueChange
|
|
77
|
-
});
|
|
78
|
-
const options = useMemo(()=>{
|
|
79
|
-
if (!infiniteProp) {
|
|
80
|
-
return optionsProp;
|
|
81
|
-
}
|
|
82
|
-
const result = [];
|
|
83
|
-
const halfCount = Math.ceil(countProp / 2);
|
|
84
|
-
if (optionsProp.length === 0) {
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
while(result.length < halfCount){
|
|
88
|
-
result.push(...optionsProp);
|
|
89
|
-
}
|
|
90
|
-
return result;
|
|
91
|
-
}, [
|
|
92
|
-
countProp,
|
|
93
|
-
optionsProp,
|
|
94
|
-
infiniteProp
|
|
95
|
-
]);
|
|
96
|
-
const itemHeight = 28;
|
|
97
|
-
const halfItemHeight = itemHeight * 0.5;
|
|
98
|
-
const itemAngle = 360 / countProp;
|
|
99
|
-
const radius = itemHeight / Math.tan(itemAngle * Math.PI / 180);
|
|
100
|
-
const containerHeight = Math.round(radius * 2 + itemHeight * 0.25);
|
|
101
|
-
const quarterCount = countProp >> 2; // Divide by 4
|
|
102
|
-
const baseDeceleration = dragSensitivityProp * 10;
|
|
103
|
-
const snapBackDeceleration = 10;
|
|
104
|
-
const containerRef = useRef(null);
|
|
105
|
-
const wheelItemsRef = useRef(null);
|
|
106
|
-
const highlightListRef = useRef(null);
|
|
107
|
-
const scrollRef = useRef(0);
|
|
108
|
-
const moveId = useRef(0);
|
|
109
|
-
const dragingRef = useRef(false);
|
|
110
|
-
const lastWheelRef = useRef(0);
|
|
111
|
-
const touchDataRef = useRef({
|
|
112
|
-
startY: 0,
|
|
113
|
-
yList: []
|
|
114
|
-
});
|
|
115
|
-
const dragControllerRef = useRef(null);
|
|
116
|
-
const renderWheelItems = useMemo(()=>{
|
|
117
|
-
const renderItem = (item, index, angle)=>/*#__PURE__*/ React.createElement("li", {
|
|
118
|
-
key: index,
|
|
119
|
-
className: classNames == null ? void 0 : classNames.optionItem,
|
|
120
|
-
"data-rwp-option": true,
|
|
121
|
-
"data-index": index,
|
|
122
|
-
style: {
|
|
123
|
-
top: -14,
|
|
124
|
-
height: itemHeight,
|
|
125
|
-
lineHeight: `${itemHeight}px`,
|
|
126
|
-
transform: `rotateX(${angle}deg) translateZ(${radius}px)`,
|
|
127
|
-
visibility: "hidden"
|
|
128
|
-
}
|
|
129
|
-
}, item.label);
|
|
130
|
-
const items = options.map((option, index)=>renderItem(option, index, -itemAngle * index));
|
|
131
|
-
if (infiniteProp) {
|
|
132
|
-
for(let i = 0; i < quarterCount; ++i){
|
|
133
|
-
const prependIndex = -i - 1;
|
|
134
|
-
const appendIndex = i + options.length;
|
|
135
|
-
items.unshift(renderItem(options[options.length - i - 1], prependIndex, itemAngle * (i + 1)));
|
|
136
|
-
items.push(renderItem(options[i], appendIndex, -itemAngle * appendIndex));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return items;
|
|
140
|
-
}, [
|
|
141
|
-
halfItemHeight,
|
|
142
|
-
infiniteProp,
|
|
143
|
-
itemAngle,
|
|
144
|
-
options,
|
|
145
|
-
quarterCount,
|
|
146
|
-
radius,
|
|
147
|
-
classNames == null ? void 0 : classNames.optionItem
|
|
148
|
-
]);
|
|
149
|
-
const renderHighlightItems = useMemo(()=>{
|
|
150
|
-
const renderItem = (item, key)=>/*#__PURE__*/ React.createElement("li", {
|
|
151
|
-
key: key,
|
|
152
|
-
"data-slot": "highlight-item",
|
|
153
|
-
className: classNames == null ? void 0 : classNames.highlightItem,
|
|
154
|
-
style: {
|
|
155
|
-
height: itemHeight
|
|
156
|
-
}
|
|
157
|
-
}, item.label);
|
|
158
|
-
const items = options.map((option, index)=>renderItem(option, index));
|
|
159
|
-
if (infiniteProp) {
|
|
160
|
-
const firstItem = options[0];
|
|
161
|
-
const lastItem = options[options.length - 1];
|
|
162
|
-
items.unshift(renderItem(lastItem, "infinite-start"));
|
|
163
|
-
items.push(renderItem(firstItem, "infinite-end"));
|
|
164
|
-
}
|
|
165
|
-
return items;
|
|
166
|
-
}, [
|
|
167
|
-
classNames == null ? void 0 : classNames.highlightItem,
|
|
168
|
-
infiniteProp,
|
|
169
|
-
options
|
|
170
|
-
]);
|
|
171
|
-
const normalizeScroll = (scroll)=>(scroll % options.length + options.length) % options.length;
|
|
172
|
-
const scrollTo = (scroll)=>{
|
|
173
|
-
const normalizedScroll = infiniteProp ? normalizeScroll(scroll) : scroll;
|
|
174
|
-
if (wheelItemsRef.current) {
|
|
175
|
-
const transform = `translateZ(${-radius}px) rotateX(${itemAngle * normalizedScroll}deg)`;
|
|
176
|
-
wheelItemsRef.current.style.transform = transform;
|
|
177
|
-
wheelItemsRef.current.childNodes.forEach((node)=>{
|
|
178
|
-
const li = node;
|
|
179
|
-
const distance = Math.abs(Number(li.dataset.index) - normalizedScroll);
|
|
180
|
-
li.style.visibility = distance > quarterCount ? "hidden" : "visible";
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (highlightListRef.current) {
|
|
184
|
-
highlightListRef.current.style.transform = `translateY(${-normalizedScroll * itemHeight}px)`;
|
|
185
|
-
}
|
|
186
|
-
return normalizedScroll;
|
|
187
|
-
};
|
|
188
|
-
const cancelAnimation = ()=>{
|
|
189
|
-
cancelAnimationFrame(moveId.current);
|
|
190
|
-
};
|
|
191
|
-
const animateScroll = (startScroll, endScroll, duration, onComplete)=>{
|
|
192
|
-
if (startScroll === endScroll || duration === 0) {
|
|
193
|
-
scrollTo(startScroll);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
const startTime = performance.now();
|
|
197
|
-
const totalDistance = endScroll - startScroll;
|
|
198
|
-
const tick = (currentTime)=>{
|
|
199
|
-
const elapsed = (currentTime - startTime) / 1000;
|
|
200
|
-
if (elapsed < duration) {
|
|
201
|
-
const progress = easeOutCubic(elapsed / duration);
|
|
202
|
-
scrollRef.current = scrollTo(startScroll + progress * totalDistance);
|
|
203
|
-
moveId.current = requestAnimationFrame(tick);
|
|
204
|
-
} else {
|
|
205
|
-
cancelAnimation();
|
|
206
|
-
scrollRef.current = scrollTo(endScroll);
|
|
207
|
-
onComplete == null ? void 0 : onComplete();
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
requestAnimationFrame(tick);
|
|
211
|
-
};
|
|
212
|
-
const selectByScroll = (scroll)=>{
|
|
213
|
-
const normalized = normalizeScroll(scroll) | 0;
|
|
214
|
-
const boundedScroll = infiniteProp ? normalized : Math.min(Math.max(normalized, 0), options.length - 1);
|
|
215
|
-
if (!infiniteProp && boundedScroll !== scroll) return;
|
|
216
|
-
scrollRef.current = scrollTo(boundedScroll);
|
|
217
|
-
const selected = options[scrollRef.current];
|
|
218
|
-
setValue(selected.value);
|
|
219
|
-
};
|
|
220
|
-
const selectByValue = (value)=>{
|
|
221
|
-
const index = options.findIndex((opt)=>opt.value === value);
|
|
222
|
-
if (index === -1) {
|
|
223
|
-
console.error("Invalid value selected:", value);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
cancelAnimation();
|
|
227
|
-
selectByScroll(index);
|
|
228
|
-
};
|
|
229
|
-
const updateScrollDuringDrag = (e)=>{
|
|
230
|
-
try {
|
|
231
|
-
var _e_touches_, _e_touches;
|
|
232
|
-
const currentY = (e instanceof MouseEvent ? e.clientY : (_e_touches = e.touches) == null ? void 0 : (_e_touches_ = _e_touches[0]) == null ? void 0 : _e_touches_.clientY) || 0;
|
|
233
|
-
const touchData = touchDataRef.current;
|
|
234
|
-
// Record current Y position with timestamp
|
|
235
|
-
touchData.yList.push([
|
|
236
|
-
currentY,
|
|
237
|
-
Date.now()
|
|
238
|
-
]);
|
|
239
|
-
if (touchData.yList.length > 5) {
|
|
240
|
-
touchData.yList.shift(); // Keep latest 5 points for velocity calc
|
|
241
|
-
}
|
|
242
|
-
// Calculate delta in scroll position based on drag distance
|
|
243
|
-
const dragDelta = (touchData.startY - currentY) / itemHeight;
|
|
244
|
-
let nextScroll = scrollRef.current + dragDelta;
|
|
245
|
-
if (infiniteProp) {
|
|
246
|
-
// Wrap scroll for infinite lists
|
|
247
|
-
nextScroll = normalizeScroll(nextScroll);
|
|
248
|
-
} else {
|
|
249
|
-
const maxIndex = options.length;
|
|
250
|
-
if (nextScroll < 0) {
|
|
251
|
-
// Apply resistance when dragging above top
|
|
252
|
-
nextScroll *= RESISTANCE;
|
|
253
|
-
} else if (nextScroll > maxIndex) {
|
|
254
|
-
// Apply resistance when dragging below bottom
|
|
255
|
-
nextScroll = maxIndex + (nextScroll - maxIndex) * RESISTANCE;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
// Update visual scroll and store position
|
|
259
|
-
touchData.touchScroll = scrollTo(nextScroll);
|
|
260
|
-
} catch (error) {
|
|
261
|
-
console.error("Error in updateScrollDuringDrag:", error);
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
const handleDragMoveEvent = (event)=>{
|
|
265
|
-
if (!dragingRef.current && !containerRef.current.contains(event.target) && event.target !== containerRef.current) {
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
if (event.cancelable) {
|
|
269
|
-
event.preventDefault();
|
|
270
|
-
}
|
|
271
|
-
if (options.length) {
|
|
272
|
-
updateScrollDuringDrag(event);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
const initiateDragGesture = (event)=>{
|
|
276
|
-
try {
|
|
277
|
-
var _containerRef_current, _event_touches_, _event_touches;
|
|
278
|
-
dragingRef.current = true;
|
|
279
|
-
const controller = new AbortController();
|
|
280
|
-
const { signal } = controller;
|
|
281
|
-
dragControllerRef.current = controller;
|
|
282
|
-
// Listen to movement events
|
|
283
|
-
const passiveOpts = {
|
|
284
|
-
signal,
|
|
285
|
-
passive: false
|
|
286
|
-
};
|
|
287
|
-
(_containerRef_current = containerRef.current) == null ? void 0 : _containerRef_current.addEventListener("touchmove", handleDragMoveEvent, passiveOpts);
|
|
288
|
-
document.addEventListener("mousemove", handleDragMoveEvent, passiveOpts);
|
|
289
|
-
const startY = (event instanceof MouseEvent ? event.clientY : (_event_touches = event.touches) == null ? void 0 : (_event_touches_ = _event_touches[0]) == null ? void 0 : _event_touches_.clientY) || 0;
|
|
290
|
-
// Initialize touch tracking
|
|
291
|
-
const touchData = touchDataRef.current;
|
|
292
|
-
touchData.startY = startY;
|
|
293
|
-
touchData.yList = [
|
|
294
|
-
[
|
|
295
|
-
startY,
|
|
296
|
-
Date.now()
|
|
297
|
-
]
|
|
298
|
-
];
|
|
299
|
-
touchData.touchScroll = scrollRef.current;
|
|
300
|
-
// Stop any ongoing scroll animation
|
|
301
|
-
cancelAnimation();
|
|
302
|
-
} catch (error) {
|
|
303
|
-
console.error("Error in initiateDragGesture:", error);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
const handleDragStartEvent = useCallback((e)=>{
|
|
307
|
-
const isDragging = dragingRef.current;
|
|
308
|
-
const isTargetValid = containerRef.current.contains(e.target) || e.target === containerRef.current;
|
|
309
|
-
if ((isDragging || isTargetValid) && e.cancelable) {
|
|
310
|
-
e.preventDefault();
|
|
311
|
-
if (options.length) {
|
|
312
|
-
initiateDragGesture(e);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
316
|
-
[
|
|
317
|
-
initiateDragGesture
|
|
318
|
-
]);
|
|
319
|
-
const decelerateAndAnimateScroll = (initialVelocity)=>{
|
|
320
|
-
const currentScroll = scrollRef.current;
|
|
321
|
-
let targetScroll = currentScroll;
|
|
322
|
-
let deceleration = initialVelocity > 0 ? -baseDeceleration : baseDeceleration;
|
|
323
|
-
let duration = 0;
|
|
324
|
-
// Clamp utility to constrain a value within bounds
|
|
325
|
-
const clamp = (value, min, max)=>Math.max(min, Math.min(value, max));
|
|
326
|
-
if (infiniteProp) {
|
|
327
|
-
// Infinite mode: apply uniform deceleration to calculate scroll distance
|
|
328
|
-
duration = Math.abs(initialVelocity / deceleration);
|
|
329
|
-
const scrollDistance = initialVelocity * duration + 0.5 * deceleration * duration * duration;
|
|
330
|
-
targetScroll = Math.round(currentScroll + scrollDistance);
|
|
331
|
-
} else if (currentScroll < 0 || currentScroll > options.length - 1) {
|
|
332
|
-
// Out-of-bounds: snap back to nearest valid scroll index
|
|
333
|
-
const target = clamp(currentScroll, 0, options.length - 1);
|
|
334
|
-
const scrollDistance = currentScroll - target;
|
|
335
|
-
deceleration = snapBackDeceleration;
|
|
336
|
-
duration = Math.sqrt(Math.abs(scrollDistance / deceleration));
|
|
337
|
-
initialVelocity = deceleration * duration;
|
|
338
|
-
initialVelocity = currentScroll > 0 ? -initialVelocity : initialVelocity;
|
|
339
|
-
targetScroll = target;
|
|
340
|
-
} else {
|
|
341
|
-
// Normal decelerated scroll within bounds
|
|
342
|
-
duration = Math.abs(initialVelocity / deceleration);
|
|
343
|
-
const scrollDistance = initialVelocity * duration + 0.5 * deceleration * duration * duration;
|
|
344
|
-
targetScroll = Math.round(currentScroll + scrollDistance);
|
|
345
|
-
targetScroll = clamp(targetScroll, 0, options.length - 1);
|
|
346
|
-
const adjustedDistance = targetScroll - currentScroll;
|
|
347
|
-
duration = Math.sqrt(Math.abs(adjustedDistance / deceleration));
|
|
348
|
-
}
|
|
349
|
-
// Start animation to target scroll position with calculated duration
|
|
350
|
-
animateScroll(currentScroll, targetScroll, duration, ()=>{
|
|
351
|
-
selectByScroll(scrollRef.current); // Ensure selected item updates at end
|
|
352
|
-
});
|
|
353
|
-
// Fallback selection update (in case animation callback fails)
|
|
354
|
-
selectByScroll(scrollRef.current);
|
|
355
|
-
};
|
|
356
|
-
const finalizeDragAndStartInertiaScroll = ()=>{
|
|
357
|
-
try {
|
|
358
|
-
var _dragControllerRef_current;
|
|
359
|
-
(_dragControllerRef_current = dragControllerRef.current) == null ? void 0 : _dragControllerRef_current.abort();
|
|
360
|
-
dragControllerRef.current = null;
|
|
361
|
-
const touchData = touchDataRef.current;
|
|
362
|
-
const yList = touchData.yList;
|
|
363
|
-
let velocity = 0;
|
|
364
|
-
if (yList.length > 1) {
|
|
365
|
-
const len = yList.length;
|
|
366
|
-
var _yList_;
|
|
367
|
-
const [startY, startTime] = (_yList_ = yList[len - 2]) != null ? _yList_ : [
|
|
368
|
-
0,
|
|
369
|
-
0
|
|
370
|
-
];
|
|
371
|
-
var _yList_1;
|
|
372
|
-
const [endY, endTime] = (_yList_1 = yList[len - 1]) != null ? _yList_1 : [
|
|
373
|
-
0,
|
|
374
|
-
0
|
|
375
|
-
];
|
|
376
|
-
const timeDiff = endTime - startTime;
|
|
377
|
-
if (timeDiff > 0) {
|
|
378
|
-
const distance = startY - endY;
|
|
379
|
-
const velocityPerSecond = distance / itemHeight * 1000 / timeDiff;
|
|
380
|
-
const maxVelocity = MAX_VELOCITY;
|
|
381
|
-
const direction = velocityPerSecond > 0 ? 1 : -1;
|
|
382
|
-
const absVelocity = Math.min(Math.abs(velocityPerSecond), maxVelocity);
|
|
383
|
-
velocity = absVelocity * direction;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
var _touchData_touchScroll;
|
|
387
|
-
scrollRef.current = (_touchData_touchScroll = touchData.touchScroll) != null ? _touchData_touchScroll : scrollRef.current;
|
|
388
|
-
decelerateAndAnimateScroll(velocity);
|
|
389
|
-
} catch (error) {
|
|
390
|
-
console.error("Error in finalizeDragAndStartInertiaScroll:", error);
|
|
391
|
-
} finally{
|
|
392
|
-
dragingRef.current = false;
|
|
393
|
-
}
|
|
394
|
-
};
|
|
395
|
-
const handleDragEndEvent = useCallback((event)=>{
|
|
396
|
-
if (!options.length) return;
|
|
397
|
-
const isDragging = dragingRef.current;
|
|
398
|
-
const isTargetValid = containerRef.current.contains(event.target) || event.target === containerRef.current;
|
|
399
|
-
if ((isDragging || isTargetValid) && event.cancelable) {
|
|
400
|
-
event.preventDefault();
|
|
401
|
-
finalizeDragAndStartInertiaScroll();
|
|
402
|
-
}
|
|
403
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
404
|
-
[
|
|
405
|
-
finalizeDragAndStartInertiaScroll
|
|
406
|
-
]);
|
|
407
|
-
const scrollByWheel = (event)=>{
|
|
408
|
-
event.preventDefault();
|
|
409
|
-
const now = Date.now();
|
|
410
|
-
if (now - lastWheelRef.current < WHEEL_THROTTLE) return;
|
|
411
|
-
const direction = Math.sign(event.deltaY);
|
|
412
|
-
if (direction !== 0) {
|
|
413
|
-
selectByScroll(scrollRef.current + direction);
|
|
414
|
-
lastWheelRef.current = now;
|
|
415
|
-
}
|
|
416
|
-
};
|
|
417
|
-
const handleWheelEvent = useCallback((event)=>{
|
|
418
|
-
if (!options.length || !containerRef.current) return;
|
|
419
|
-
const isDragging = dragingRef.current;
|
|
420
|
-
const isTargetValid = containerRef.current.contains(event.target) || event.target === containerRef.current;
|
|
421
|
-
if ((isDragging || isTargetValid) && event.cancelable) {
|
|
422
|
-
event.preventDefault();
|
|
423
|
-
scrollByWheel(event);
|
|
424
|
-
}
|
|
425
|
-
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
426
|
-
[
|
|
427
|
-
scrollByWheel
|
|
428
|
-
]);
|
|
429
|
-
useEffect(()=>{
|
|
430
|
-
const container = containerRef.current;
|
|
431
|
-
if (!container) return;
|
|
432
|
-
const controller = new AbortController();
|
|
433
|
-
const { signal } = controller;
|
|
434
|
-
const opts = {
|
|
435
|
-
signal,
|
|
436
|
-
passive: false
|
|
437
|
-
};
|
|
438
|
-
container.addEventListener("touchstart", handleDragStartEvent, opts);
|
|
439
|
-
container.addEventListener("touchend", handleDragEndEvent, opts);
|
|
440
|
-
container.addEventListener("wheel", handleWheelEvent, opts);
|
|
441
|
-
document.addEventListener("mousedown", handleDragStartEvent, opts);
|
|
442
|
-
document.addEventListener("mouseup", handleDragEndEvent, opts);
|
|
443
|
-
return ()=>controller.abort();
|
|
444
|
-
}, [
|
|
445
|
-
handleDragEndEvent,
|
|
446
|
-
handleDragStartEvent,
|
|
447
|
-
handleWheelEvent
|
|
448
|
-
]);
|
|
449
|
-
useEffect(()=>{
|
|
450
|
-
selectByValue(value);
|
|
451
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
452
|
-
}, [
|
|
453
|
-
value,
|
|
454
|
-
valueProp
|
|
455
|
-
]);
|
|
456
|
-
return /*#__PURE__*/ React.createElement("div", {
|
|
457
|
-
ref: containerRef,
|
|
458
|
-
"data-rwp": true,
|
|
459
|
-
style: {
|
|
460
|
-
height: containerHeight
|
|
461
|
-
}
|
|
462
|
-
}, /*#__PURE__*/ React.createElement("ul", {
|
|
463
|
-
ref: wheelItemsRef,
|
|
464
|
-
"data-rwp-options": true
|
|
465
|
-
}, renderWheelItems), /*#__PURE__*/ React.createElement("div", {
|
|
466
|
-
className: classNames == null ? void 0 : classNames.highlightWrapper,
|
|
467
|
-
"data-rwp-highlight-wrapper": true,
|
|
468
|
-
style: {
|
|
469
|
-
height: itemHeight,
|
|
470
|
-
lineHeight: itemHeight + "px"
|
|
471
|
-
}
|
|
472
|
-
}, /*#__PURE__*/ React.createElement("ul", {
|
|
473
|
-
ref: highlightListRef,
|
|
474
|
-
"data-rwp-highlight-list": true,
|
|
475
|
-
style: {
|
|
476
|
-
top: infiniteProp ? -28 : undefined
|
|
477
|
-
}
|
|
478
|
-
}, renderHighlightItems)));
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
export { WheelPicker, WheelPickerWrapper };
|
|
1
|
+
"use client";import M from"react";import{useCallback as q,useEffect as ot,useMemo as z,useRef as T}from"react";import D from"react";function nt(u){let g=D.useRef(u);return D.useEffect(()=>{g.current=u}),D.useMemo(()=>(...E)=>{var h;return(h=g.current)==null?void 0:h.call(g,...E)},[])}function vt({defaultProp:u,onChange:g}){let E=D.useState(u),[h]=E,a=D.useRef(h),b=nt(g);return D.useEffect(()=>{a.current!==h&&(b(h),a.current=h)},[h,a,b]),E}function rt({prop:u,defaultProp:g,onChange:E=()=>{}}){let[h,a]=vt({defaultProp:g,onChange:E}),b=u!==void 0,x=b?u:h,l=nt(E),W=D.useCallback(S=>{if(b){let d=typeof S=="function"?S(u):S;d!==u&&l(d)}else a(S)},[b,u,a,l]);return[x,W]}var Et=150,ct=.3,Tt=30,Dt=u=>Math.pow(u-1,3)+1,wt=({className:u,children:g})=>M.createElement("div",{className:u,"data-rwp-wrapper":!0},g),kt=({defaultValue:u,value:g,onValueChange:E,options:h,infinite:a=!1,visibleCount:b=20,dragSensitivity:x=3,classNames:l})=>{var V,N;let[W=(N=(V=h[0])==null?void 0:V.value)!=null?N:"",S]=rt({defaultProp:u,prop:g,onChange:E}),c=z(()=>{if(!a)return h;let t=[],e=Math.ceil(b/2);if(h.length===0)return t;for(;t.length<e;)t.push(...h);return t},[b,h,a]),d=28,B=d*.5,y=360/b,C=d/Math.tan(y*Math.PI/180),st=Math.round(C*2+d*.25),A=b>>2,X=x*10,at=10,m=T(null),w=T(null),Y=T(null),p=T(0),G=T(0),L=T(!1),Z=T(0),R=T({startY:0,yList:[]}),H=T(null),lt=z(()=>{let t=(n,r,o)=>M.createElement("li",{key:r,className:l==null?void 0:l.optionItem,"data-rwp-option":!0,"data-index":r,style:{top:-B,height:d,lineHeight:`${d}px`,transform:`rotateX(${o}deg) translateZ(${C}px)`,visibility:"hidden"}},n.label),e=c.map((n,r)=>t(n,r,-y*r));if(a)for(let n=0;n<A;++n){let r=-n-1,o=n+c.length;e.unshift(t(c[c.length-n-1],r,y*(n+1))),e.push(t(c[n],o,-y*o))}return e},[B,a,y,c,A,C,l==null?void 0:l.optionItem]),it=z(()=>{let t=(n,r)=>M.createElement("li",{key:r,"data-slot":"highlight-item",className:l==null?void 0:l.highlightItem,style:{height:d}},n.label),e=c.map((n,r)=>t(n,r));if(a){let n=c[0],r=c[c.length-1];e.unshift(t(r,"infinite-start")),e.push(t(n,"infinite-end"))}return e},[l==null?void 0:l.highlightItem,a,c]),O=t=>(t%c.length+c.length)%c.length,I=t=>{let e=a?O(t):t;if(w.current){let n=`translateZ(${-C}px) rotateX(${y*e}deg)`;w.current.style.transform=n,w.current.childNodes.forEach(r=>{let o=r,f=Math.abs(Number(o.dataset.index)-e);o.style.visibility=f>A?"hidden":"visible"})}return Y.current&&(Y.current.style.transform=`translateY(${-e*d}px)`),e},F=()=>{cancelAnimationFrame(G.current)},ut=(t,e,n,r)=>{if(t===e||n===0){I(t);return}let o=performance.now(),f=e-t,s=i=>{let v=(i-o)/1e3;if(v<n){let $=Dt(v/n);p.current=I(t+$*f),G.current=requestAnimationFrame(s)}else F(),p.current=I(e),r==null||r()};requestAnimationFrame(s)},k=t=>{let e=O(t)|0,n=a?e:Math.min(Math.max(e,0),c.length-1);if(!a&&n!==t)return;p.current=I(n);let r=c[p.current];S(r.value)},ht=t=>{let e=c.findIndex(n=>n.value===t);if(e===-1){console.error("Invalid value selected:",t);return}F(),k(e)},dt=t=>{var e,n;try{let r=(t instanceof MouseEvent?t.clientY:(n=(e=t.touches)==null?void 0:e[0])==null?void 0:n.clientY)||0,o=R.current;o.yList.push([r,Date.now()]),o.yList.length>5&&o.yList.shift();let f=(o.startY-r)/d,s=p.current+f;if(a)s=O(s);else{let i=c.length;s<0?s*=ct:s>i&&(s=i+(s-i)*ct)}o.touchScroll=I(s)}catch(r){console.error("Error in updateScrollDuringDrag:",r)}},_=t=>{!L.current&&!m.current.contains(t.target)&&t.target!==m.current||(t.cancelable&&t.preventDefault(),c.length&&dt(t))},j=t=>{var e,n,r;try{L.current=!0;let o=new AbortController,{signal:f}=o;H.current=o;let s={signal:f,passive:!1};(e=m.current)==null||e.addEventListener("touchmove",_,s),document.addEventListener("mousemove",_,s);let i=(t instanceof MouseEvent?t.clientY:(r=(n=t.touches)==null?void 0:n[0])==null?void 0:r.clientY)||0,v=R.current;v.startY=i,v.yList=[[i,Date.now()]],v.touchScroll=p.current,F()}catch(o){console.error("Error in initiateDragGesture:",o)}},P=q(t=>{let e=L.current,n=m.current.contains(t.target)||t.target===m.current;(e||n)&&t.cancelable&&(t.preventDefault(),c.length&&j(t))},[j]),ft=t=>{let e=p.current,n=e,r=t>0?-X:X,o=0,f=(s,i,v)=>Math.max(i,Math.min(s,v));if(a){o=Math.abs(t/r);let s=t*o+.5*r*o*o;n=Math.round(e+s)}else if(e<0||e>c.length-1){let s=f(e,0,c.length-1),i=e-s;r=at,o=Math.sqrt(Math.abs(i/r)),t=r*o,t=e>0?-t:t,n=s}else{o=Math.abs(t/r);let s=t*o+.5*r*o*o;n=Math.round(e+s),n=f(n,0,c.length-1);let i=n-e;o=Math.sqrt(Math.abs(i/r))}ut(e,n,o,()=>{k(p.current)}),k(p.current)},K=()=>{var t,e,n,r;try{(t=H.current)==null||t.abort(),H.current=null;let o=R.current,f=o.yList,s=0;if(f.length>1){let i=f.length,[v,$]=(e=f[i-2])!=null?e:[0,0],[gt,mt]=(n=f[i-1])!=null?n:[0,0],tt=mt-$;if(tt>0){let et=(v-gt)/d*1e3/tt,pt=Tt,bt=et>0?1:-1;s=Math.min(Math.abs(et),pt)*bt}}p.current=(r=o.touchScroll)!=null?r:p.current,ft(s)}catch(o){console.error("Error in finalizeDragAndStartInertiaScroll:",o)}finally{L.current=!1}},U=q(t=>{if(!c.length)return;let e=L.current,n=m.current.contains(t.target)||t.target===m.current;(e||n)&&t.cancelable&&(t.preventDefault(),K())},[K]),J=t=>{t.preventDefault();let e=Date.now();if(e-Z.current<Et)return;let n=Math.sign(t.deltaY);n!==0&&(k(p.current+n),Z.current=e)},Q=q(t=>{if(!c.length||!m.current)return;let e=L.current,n=m.current.contains(t.target)||t.target===m.current;(e||n)&&t.cancelable&&(t.preventDefault(),J(t))},[J]);return ot(()=>{let t=m.current;if(!t)return;let e=new AbortController,{signal:n}=e,r={signal:n,passive:!1};return t.addEventListener("touchstart",P,r),t.addEventListener("touchend",U,r),t.addEventListener("wheel",Q,r),document.addEventListener("mousedown",P,r),document.addEventListener("mouseup",U,r),()=>e.abort()},[U,P,Q]),ot(()=>{ht(W)},[W,g]),M.createElement("div",{ref:m,"data-rwp":!0,style:{height:st}},M.createElement("ul",{ref:w,"data-rwp-options":!0},lt),M.createElement("div",{className:l==null?void 0:l.highlightWrapper,"data-rwp-highlight-wrapper":!0,style:{height:d,lineHeight:d+"px"}},M.createElement("ul",{ref:Y,"data-rwp-highlight-list":!0,style:{top:a?-d:void 0}},it)))};export{kt as WheelPicker,wt as WheelPickerWrapper};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ncdai/react-wheel-picker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "iOS-like wheel picker for React with smooth inertia scrolling and infinite loop support.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -21,11 +21,22 @@
|
|
|
21
21
|
},
|
|
22
22
|
"./dist/style.css": "./dist/style.css"
|
|
23
23
|
},
|
|
24
|
+
"tsup": {
|
|
25
|
+
"entry": [
|
|
26
|
+
"src/index.tsx"
|
|
27
|
+
],
|
|
28
|
+
"format": [
|
|
29
|
+
"esm",
|
|
30
|
+
"cjs"
|
|
31
|
+
],
|
|
32
|
+
"dts": true,
|
|
33
|
+
"clean": true,
|
|
34
|
+
"publicDir": "./src/assets"
|
|
35
|
+
},
|
|
24
36
|
"scripts": {
|
|
25
|
-
"dev": "
|
|
26
|
-
"build": "
|
|
37
|
+
"dev": "tsup --watch",
|
|
38
|
+
"build": "tsup --minify",
|
|
27
39
|
"type-check": "tsc --noEmit",
|
|
28
|
-
"copy-assets": "cp -r ./src/style.css ./dist/style.css",
|
|
29
40
|
"dev:website": "turbo run dev --filter=website...",
|
|
30
41
|
"prettier:check": "prettier --check .",
|
|
31
42
|
"format": "prettier --write .",
|
|
@@ -53,9 +64,9 @@
|
|
|
53
64
|
"devDependencies": {
|
|
54
65
|
"@types/node": "^20",
|
|
55
66
|
"@types/react": "^19",
|
|
56
|
-
"bunchee": "^6.5.1",
|
|
57
67
|
"prettier": "3.5.3",
|
|
58
68
|
"react": "^19.0.0",
|
|
69
|
+
"tsup": "8.5.0",
|
|
59
70
|
"turbo": "^2.5.3",
|
|
60
71
|
"typescript": "^5.8.3"
|
|
61
72
|
},
|