@sigx/lynx-gestures 0.4.0 → 0.4.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.
- package/README.md +42 -0
- package/dist/components/Draggable.js +378 -0
- package/dist/components/Draggable.js.map +1 -0
- package/dist/components/Pressable.d.ts +5 -4
- package/dist/components/Pressable.d.ts.map +1 -1
- package/dist/components/Pressable.js +157 -0
- package/dist/components/Pressable.js.map +1 -0
- package/dist/components/ScrollView.js +85 -0
- package/dist/components/ScrollView.js.map +1 -0
- package/dist/components/Swipeable.js +165 -0
- package/dist/components/Swipeable.js.map +1 -0
- package/dist/components/Swiper.d.ts +65 -0
- package/dist/components/Swiper.d.ts.map +1 -0
- package/dist/components/Swiper.js +124 -0
- package/dist/components/Swiper.js.map +1 -0
- package/dist/index.d.ts +17 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -404
- package/dist/index.js.map +1 -1
- package/dist/scroll-context.js +3 -0
- package/dist/scroll-context.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/use-pinch.d.ts +1 -1
- package/dist/use-pinch.d.ts.map +1 -1
- package/dist/use-pinch.js +106 -0
- package/dist/use-pinch.js.map +1 -0
- package/dist/use-rotation.d.ts +1 -1
- package/dist/use-rotation.d.ts.map +1 -1
- package/dist/use-rotation.js +117 -0
- package/dist/use-rotation.js.map +1 -0
- package/dist/use-swiper-dot-progress.d.ts +129 -0
- package/dist/use-swiper-dot-progress.d.ts.map +1 -0
- package/dist/use-swiper-dot-progress.js +141 -0
- package/dist/use-swiper-dot-progress.js.map +1 -0
- package/dist/utils.js +25 -0
- package/dist/utils.js.map +1 -0
- package/package.json +10 -9
- package/src/components/Draggable.tsx +1 -1
- package/src/components/Pressable.tsx +44 -18
- package/src/components/ScrollView.tsx +1 -1
- package/src/components/Swipeable.tsx +1 -1
- package/src/components/Swiper.tsx +204 -0
- package/src/index.ts +27 -13
- package/src/use-pinch.ts +2 -2
- package/src/use-rotation.ts +2 -2
- package/src/use-swiper-dot-progress.ts +231 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { signal } from '@sigx/lynx';
|
|
2
|
+
import { distance, midpoint } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Two-finger pinch/zoom gesture.
|
|
5
|
+
*
|
|
6
|
+
* Tracks fingers manually since Lynx fires separate touchstart events per
|
|
7
|
+
* finger (each with touches.length=1). Uses proximity-based matching on
|
|
8
|
+
* touchmove since Lynx identifiers are unreliable across events.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: Requires a device/environment that delivers multi-touch events to
|
|
11
|
+
* the same element. Some Lynx hosts (e.g. Lynx Explorer on emulator) may
|
|
12
|
+
* not support this — test on a physical device.
|
|
13
|
+
*/
|
|
14
|
+
export function usePinch(options = {}) {
|
|
15
|
+
const { onPinch } = options;
|
|
16
|
+
const state = signal({
|
|
17
|
+
phase: 'idle',
|
|
18
|
+
scale: 1,
|
|
19
|
+
focalX: 0,
|
|
20
|
+
focalY: 0,
|
|
21
|
+
});
|
|
22
|
+
let baseDistance = 0;
|
|
23
|
+
let active = false;
|
|
24
|
+
let finger1 = null;
|
|
25
|
+
let finger2 = null;
|
|
26
|
+
function onTouchStart(e) {
|
|
27
|
+
const t = e.touches[0];
|
|
28
|
+
if (!t)
|
|
29
|
+
return;
|
|
30
|
+
if (!finger1) {
|
|
31
|
+
finger1 = { ...t };
|
|
32
|
+
}
|
|
33
|
+
else if (!finger2) {
|
|
34
|
+
finger2 = { ...t };
|
|
35
|
+
active = true;
|
|
36
|
+
baseDistance = distance(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
37
|
+
const [fx, fy] = midpoint(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
38
|
+
state.phase = 'began';
|
|
39
|
+
state.scale = 1;
|
|
40
|
+
state.focalX = fx;
|
|
41
|
+
state.focalY = fy;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function onTouchMove(e) {
|
|
45
|
+
if (!active || !finger1 || !finger2)
|
|
46
|
+
return;
|
|
47
|
+
const t = e.changedTouches[0];
|
|
48
|
+
if (!t)
|
|
49
|
+
return;
|
|
50
|
+
// Determine which finger moved by proximity
|
|
51
|
+
const dist1 = distance(t.pageX, t.pageY, finger1.pageX, finger1.pageY);
|
|
52
|
+
const dist2 = distance(t.pageX, t.pageY, finger2.pageX, finger2.pageY);
|
|
53
|
+
if (dist1 < dist2) {
|
|
54
|
+
finger1 = { ...t };
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
finger2 = { ...t };
|
|
58
|
+
}
|
|
59
|
+
const currentDist = distance(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
60
|
+
const scale = baseDistance > 0 ? currentDist / baseDistance : 1;
|
|
61
|
+
const [fx, fy] = midpoint(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
62
|
+
state.phase = 'active';
|
|
63
|
+
state.scale = scale;
|
|
64
|
+
state.focalX = fx;
|
|
65
|
+
state.focalY = fy;
|
|
66
|
+
onPinch?.(state);
|
|
67
|
+
}
|
|
68
|
+
function onTouchEnd() {
|
|
69
|
+
if (active) {
|
|
70
|
+
state.phase = 'ended';
|
|
71
|
+
onPinch?.(state);
|
|
72
|
+
}
|
|
73
|
+
active = false;
|
|
74
|
+
finger1 = null;
|
|
75
|
+
finger2 = null;
|
|
76
|
+
}
|
|
77
|
+
function onTouchCancel() {
|
|
78
|
+
if (active) {
|
|
79
|
+
state.phase = 'cancelled';
|
|
80
|
+
onPinch?.(state);
|
|
81
|
+
}
|
|
82
|
+
active = false;
|
|
83
|
+
finger1 = null;
|
|
84
|
+
finger2 = null;
|
|
85
|
+
}
|
|
86
|
+
function reset() {
|
|
87
|
+
active = false;
|
|
88
|
+
finger1 = null;
|
|
89
|
+
finger2 = null;
|
|
90
|
+
state.phase = 'idle';
|
|
91
|
+
state.scale = 1;
|
|
92
|
+
state.focalX = 0;
|
|
93
|
+
state.focalY = 0;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
state,
|
|
97
|
+
handlers: {
|
|
98
|
+
bindtouchstart: onTouchStart,
|
|
99
|
+
bindtouchmove: onTouchMove,
|
|
100
|
+
bindtouchend: onTouchEnd,
|
|
101
|
+
bindtouchcancel: onTouchCancel,
|
|
102
|
+
},
|
|
103
|
+
reset,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=use-pinch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pinch.js","sourceRoot":"","sources":["../src/use-pinch.ts"],"names":[],"mappings":"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"}
|
package/dist/use-rotation.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-rotation.d.ts","sourceRoot":"","sources":["../src/use-rotation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAIlB,MAAM,
|
|
1
|
+
{"version":3,"file":"use-rotation.d.ts","sourceRoot":"","sources":["../src/use-rotation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAIlB,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CA+G/E"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { signal } from '@sigx/lynx';
|
|
2
|
+
import { angle, angleDelta, distance, midpoint } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Two-finger rotation gesture.
|
|
5
|
+
*
|
|
6
|
+
* Tracks the angle of the line between two fingers; reports cumulative rotation
|
|
7
|
+
* in radians from gesture start. Like usePinch, uses proximity-based finger
|
|
8
|
+
* matching on touchmove (Lynx touch identifiers are not stable across events).
|
|
9
|
+
*
|
|
10
|
+
* NOTE: requires multi-touch delivery to the same element. Some Lynx hosts
|
|
11
|
+
* (Lynx Explorer on emulator) may not support this — test on a physical device.
|
|
12
|
+
*/
|
|
13
|
+
export function useRotation(options = {}) {
|
|
14
|
+
const { onRotation } = options;
|
|
15
|
+
const state = signal({
|
|
16
|
+
phase: 'idle',
|
|
17
|
+
rotation: 0,
|
|
18
|
+
velocity: 0,
|
|
19
|
+
focalX: 0,
|
|
20
|
+
focalY: 0,
|
|
21
|
+
});
|
|
22
|
+
let baseAngle = 0;
|
|
23
|
+
let prevAngle = 0;
|
|
24
|
+
let prevTime = 0;
|
|
25
|
+
let active = false;
|
|
26
|
+
let finger1 = null;
|
|
27
|
+
let finger2 = null;
|
|
28
|
+
function onTouchStart(e) {
|
|
29
|
+
const t = e.touches[0];
|
|
30
|
+
if (!t)
|
|
31
|
+
return;
|
|
32
|
+
if (!finger1) {
|
|
33
|
+
finger1 = { ...t };
|
|
34
|
+
}
|
|
35
|
+
else if (!finger2) {
|
|
36
|
+
finger2 = { ...t };
|
|
37
|
+
active = true;
|
|
38
|
+
baseAngle = angle(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
39
|
+
prevAngle = baseAngle;
|
|
40
|
+
prevTime = Date.now();
|
|
41
|
+
const [fx, fy] = midpoint(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
42
|
+
state.phase = 'began';
|
|
43
|
+
state.rotation = 0;
|
|
44
|
+
state.velocity = 0;
|
|
45
|
+
state.focalX = fx;
|
|
46
|
+
state.focalY = fy;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function onTouchMove(e) {
|
|
50
|
+
if (!active || !finger1 || !finger2)
|
|
51
|
+
return;
|
|
52
|
+
const t = e.changedTouches[0];
|
|
53
|
+
if (!t)
|
|
54
|
+
return;
|
|
55
|
+
const dist1 = distance(t.pageX, t.pageY, finger1.pageX, finger1.pageY);
|
|
56
|
+
const dist2 = distance(t.pageX, t.pageY, finger2.pageX, finger2.pageY);
|
|
57
|
+
if (dist1 < dist2) {
|
|
58
|
+
finger1 = { ...t };
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
finger2 = { ...t };
|
|
62
|
+
}
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
const dt = Math.max(now - prevTime, 1);
|
|
65
|
+
const currentAngle = angle(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
66
|
+
const rotation = angleDelta(baseAngle, currentAngle);
|
|
67
|
+
const velocity = angleDelta(prevAngle, currentAngle) / dt;
|
|
68
|
+
const [fx, fy] = midpoint(finger1.pageX, finger1.pageY, finger2.pageX, finger2.pageY);
|
|
69
|
+
prevAngle = currentAngle;
|
|
70
|
+
prevTime = now;
|
|
71
|
+
state.phase = 'active';
|
|
72
|
+
state.rotation = rotation;
|
|
73
|
+
state.velocity = velocity;
|
|
74
|
+
state.focalX = fx;
|
|
75
|
+
state.focalY = fy;
|
|
76
|
+
onRotation?.(state);
|
|
77
|
+
}
|
|
78
|
+
function onTouchEnd() {
|
|
79
|
+
if (active) {
|
|
80
|
+
state.phase = 'ended';
|
|
81
|
+
onRotation?.(state);
|
|
82
|
+
}
|
|
83
|
+
active = false;
|
|
84
|
+
finger1 = null;
|
|
85
|
+
finger2 = null;
|
|
86
|
+
}
|
|
87
|
+
function onTouchCancel() {
|
|
88
|
+
if (active) {
|
|
89
|
+
state.phase = 'cancelled';
|
|
90
|
+
onRotation?.(state);
|
|
91
|
+
}
|
|
92
|
+
active = false;
|
|
93
|
+
finger1 = null;
|
|
94
|
+
finger2 = null;
|
|
95
|
+
}
|
|
96
|
+
function reset() {
|
|
97
|
+
active = false;
|
|
98
|
+
finger1 = null;
|
|
99
|
+
finger2 = null;
|
|
100
|
+
state.phase = 'idle';
|
|
101
|
+
state.rotation = 0;
|
|
102
|
+
state.velocity = 0;
|
|
103
|
+
state.focalX = 0;
|
|
104
|
+
state.focalY = 0;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
state,
|
|
108
|
+
handlers: {
|
|
109
|
+
bindtouchstart: onTouchStart,
|
|
110
|
+
bindtouchmove: onTouchMove,
|
|
111
|
+
bindtouchend: onTouchEnd,
|
|
112
|
+
bindtouchcancel: onTouchCancel,
|
|
113
|
+
},
|
|
114
|
+
reset,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=use-rotation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-rotation.js","sourceRoot":"","sources":["../src/use-rotation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless `<Swiper>` indicator hooks.
|
|
3
|
+
*
|
|
4
|
+
* `<Swiper>` writes the live scroll offset to a `SharedValue<number>` on
|
|
5
|
+
* the MT thread every frame. To render an indicator the consumer needs
|
|
6
|
+
* one binding per element so `useAnimatedStyle` has a stable call-site —
|
|
7
|
+
* doing that inside `.map()` is fine (per-iteration call-sites are
|
|
8
|
+
* stable across renders), but the bookkeeping (range math, ref alloc)
|
|
9
|
+
* is fiddly and easy to get wrong.
|
|
10
|
+
*
|
|
11
|
+
* These hooks own the bookkeeping and return a `MainThreadRef` the
|
|
12
|
+
* caller spreads onto any element they want animated. That keeps the
|
|
13
|
+
* presentation in user-land (and in `@sigx/lynx-daisyui`'s themed
|
|
14
|
+
* `SwiperIndicator`) while logic lives here.
|
|
15
|
+
*
|
|
16
|
+
* Layering pattern mirrors the daisyui split:
|
|
17
|
+
* - `@sigx/lynx-gestures` owns headless logic (this file + the
|
|
18
|
+
* `<Swiper>` component itself).
|
|
19
|
+
* - `@sigx/lynx-daisyui` ships themed `<SwiperIndicator>` variants
|
|
20
|
+
* that consume these hooks and pick colours from `ThemeProvider`.
|
|
21
|
+
*
|
|
22
|
+
* @example Custom dot using the opacity hook
|
|
23
|
+
* ```tsx
|
|
24
|
+
* function MyDot({ offset, pageWidth, index }) {
|
|
25
|
+
* const ref = useSwiperDotProgress({ offset, pageWidth, index });
|
|
26
|
+
* return (
|
|
27
|
+
* <view
|
|
28
|
+
* main-thread:ref={ref}
|
|
29
|
+
* style={{ width: '8px', height: '8px', borderRadius: '4px',
|
|
30
|
+
* backgroundColor: 'tomato', opacity: '0' }}
|
|
31
|
+
* />
|
|
32
|
+
* );
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import { type MainThread, type MainThreadRef, type SharedValue } from '@sigx/lynx';
|
|
37
|
+
/** Common per-dot inputs — offset is page-pixel space, index is the dot's page. */
|
|
38
|
+
export interface SwiperDotHookInputs {
|
|
39
|
+
/** Live MT-thread pixel offset from the Swiper's `offset` prop. */
|
|
40
|
+
offset: SharedValue<number>;
|
|
41
|
+
/** Page width in CSS pixels. Must match the Swiper's effective page width. */
|
|
42
|
+
pageWidth: number;
|
|
43
|
+
/** Zero-based page index this dot represents. */
|
|
44
|
+
index: number;
|
|
45
|
+
}
|
|
46
|
+
export interface UseSwiperDotProgressOptions extends SwiperDotHookInputs {
|
|
47
|
+
/**
|
|
48
|
+
* Half-width of the input window in `pageWidth` units. The dot's
|
|
49
|
+
* animation runs from `(index − window) * pageWidth` to
|
|
50
|
+
* `(index + window) * pageWidth`. Default `1` — adjacent dots
|
|
51
|
+
* crossfade because their windows overlap.
|
|
52
|
+
*/
|
|
53
|
+
window?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Output values at `[centre − window·pageWidth, centre, centre +
|
|
56
|
+
* window·pageWidth]`. Default `[0, 1, 0]` (triangular). For "always
|
|
57
|
+
* active" decoration use `[0, 1, 0]` with opacity; for "scale
|
|
58
|
+
* pulse" pass e.g. `[1, 1.4, 1]` with channel `'scale'`.
|
|
59
|
+
*/
|
|
60
|
+
outputRange?: readonly [number, number, number];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build a triangular range-map for the given dot index, defaulting to
|
|
64
|
+
* the opacity crossfade `<SwiperDots>` shipped with previously. Returns
|
|
65
|
+
* a `MainThreadRef` — spread it onto whatever element you want
|
|
66
|
+
* animated.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useSwiperDotProgress(opts: UseSwiperDotProgressOptions): MainThreadRef<MainThread.Element | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Scale-pulse variant — active dot scales up, neighbours scale down to
|
|
71
|
+
* the inactive baseline. Defaults: inactive `1`, active `1.4`.
|
|
72
|
+
*
|
|
73
|
+
* Uniform scale (both axes). For width-axis only growth (pill effect
|
|
74
|
+
* that keeps the dot's height stable) use `useSwiperDotGrowX` instead.
|
|
75
|
+
*/
|
|
76
|
+
export declare function useSwiperDotScale(opts: SwiperDotHookInputs & {
|
|
77
|
+
inactive?: number;
|
|
78
|
+
active?: number;
|
|
79
|
+
window?: number;
|
|
80
|
+
}): MainThreadRef<MainThread.Element | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Width-axis growth — the active dot stretches into a pill, neighbours
|
|
83
|
+
* shrink to a circle. Uses the `scaleX` channel, so the element's
|
|
84
|
+
* intrinsic size in the layout stays put; only the visual width
|
|
85
|
+
* changes. If you want surrounding siblings to physically shove apart
|
|
86
|
+
* use `useSwiperDotWidth` instead (it animates the `width` style
|
|
87
|
+
* property, which costs a layout pass each frame).
|
|
88
|
+
*/
|
|
89
|
+
export declare function useSwiperDotGrowX(opts: SwiperDotHookInputs & {
|
|
90
|
+
/** Width multiplier when inactive. Default `1` (the dot's base size). */
|
|
91
|
+
inactive?: number;
|
|
92
|
+
/** Width multiplier when active. Default `3` (a pill ~3× as wide as tall). */
|
|
93
|
+
active?: number;
|
|
94
|
+
window?: number;
|
|
95
|
+
}): MainThreadRef<MainThread.Element | null>;
|
|
96
|
+
/**
|
|
97
|
+
* Layout-aware width growth — animates the element's `width` style in
|
|
98
|
+
* px. Use this when sibling layout must respond (siblings flex away as
|
|
99
|
+
* the pill grows). Slower than `useSwiperDotGrowX` because every frame
|
|
100
|
+
* re-runs layout.
|
|
101
|
+
*
|
|
102
|
+
* Defaults shape an 8px → 24px pill.
|
|
103
|
+
*/
|
|
104
|
+
export declare function useSwiperDotWidth(opts: SwiperDotHookInputs & {
|
|
105
|
+
/** Width in CSS pixels when inactive. Default `8`. */
|
|
106
|
+
inactive?: number;
|
|
107
|
+
/** Width in CSS pixels when active. Default `24`. */
|
|
108
|
+
active?: number;
|
|
109
|
+
window?: number;
|
|
110
|
+
}): MainThreadRef<MainThread.Element | null>;
|
|
111
|
+
/** Inputs for the track-wide translate hook used by the "bar" indicator variant. */
|
|
112
|
+
export interface UseSwiperDotTranslateOptions {
|
|
113
|
+
offset: SharedValue<number>;
|
|
114
|
+
/** Page width in CSS pixels. */
|
|
115
|
+
pageWidth: number;
|
|
116
|
+
/**
|
|
117
|
+
* Distance in CSS pixels that one full page of scroll should move
|
|
118
|
+
* the thumb by — typically `dotWidth + spacing` (the thumb steps to
|
|
119
|
+
* the next dot's centre when the swiper advances by one page).
|
|
120
|
+
*/
|
|
121
|
+
step: number;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Translate a single "thumb" element across the indicator track,
|
|
125
|
+
* proportional to the swiper's scroll progress. Use for the `bar`
|
|
126
|
+
* variant where a single pill slides between fixed dots.
|
|
127
|
+
*/
|
|
128
|
+
export declare function useSwiperDotTranslate(opts: UseSwiperDotTranslateOptions): MainThreadRef<MainThread.Element | null>;
|
|
129
|
+
//# sourceMappingURL=use-swiper-dot-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-swiper-dot-progress.d.ts","sourceRoot":"","sources":["../src/use-swiper-dot-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AAEpB,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,2BAA2B,GAChC,aAAa,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,CAM1C;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,aAAa,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,CAW3C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG;IAC5D,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,aAAa,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,CAW3C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG;IAC5D,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,aAAa,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,CAW3C;AAED,oFAAoF;AACpF,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,4BAA4B,GACjC,aAAa,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ1C"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless `<Swiper>` indicator hooks.
|
|
3
|
+
*
|
|
4
|
+
* `<Swiper>` writes the live scroll offset to a `SharedValue<number>` on
|
|
5
|
+
* the MT thread every frame. To render an indicator the consumer needs
|
|
6
|
+
* one binding per element so `useAnimatedStyle` has a stable call-site —
|
|
7
|
+
* doing that inside `.map()` is fine (per-iteration call-sites are
|
|
8
|
+
* stable across renders), but the bookkeeping (range math, ref alloc)
|
|
9
|
+
* is fiddly and easy to get wrong.
|
|
10
|
+
*
|
|
11
|
+
* These hooks own the bookkeeping and return a `MainThreadRef` the
|
|
12
|
+
* caller spreads onto any element they want animated. That keeps the
|
|
13
|
+
* presentation in user-land (and in `@sigx/lynx-daisyui`'s themed
|
|
14
|
+
* `SwiperIndicator`) while logic lives here.
|
|
15
|
+
*
|
|
16
|
+
* Layering pattern mirrors the daisyui split:
|
|
17
|
+
* - `@sigx/lynx-gestures` owns headless logic (this file + the
|
|
18
|
+
* `<Swiper>` component itself).
|
|
19
|
+
* - `@sigx/lynx-daisyui` ships themed `<SwiperIndicator>` variants
|
|
20
|
+
* that consume these hooks and pick colours from `ThemeProvider`.
|
|
21
|
+
*
|
|
22
|
+
* @example Custom dot using the opacity hook
|
|
23
|
+
* ```tsx
|
|
24
|
+
* function MyDot({ offset, pageWidth, index }) {
|
|
25
|
+
* const ref = useSwiperDotProgress({ offset, pageWidth, index });
|
|
26
|
+
* return (
|
|
27
|
+
* <view
|
|
28
|
+
* main-thread:ref={ref}
|
|
29
|
+
* style={{ width: '8px', height: '8px', borderRadius: '4px',
|
|
30
|
+
* backgroundColor: 'tomato', opacity: '0' }}
|
|
31
|
+
* />
|
|
32
|
+
* );
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import { useAnimatedStyle, useMainThreadRef, } from '@sigx/lynx';
|
|
37
|
+
/**
|
|
38
|
+
* Build a triangular range-map for the given dot index, defaulting to
|
|
39
|
+
* the opacity crossfade `<SwiperDots>` shipped with previously. Returns
|
|
40
|
+
* a `MainThreadRef` — spread it onto whatever element you want
|
|
41
|
+
* animated.
|
|
42
|
+
*/
|
|
43
|
+
export function useSwiperDotProgress(opts) {
|
|
44
|
+
return useSwiperDotChannel({
|
|
45
|
+
...opts,
|
|
46
|
+
channel: 'opacity',
|
|
47
|
+
outputRange: opts.outputRange ?? [0, 1, 0],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Scale-pulse variant — active dot scales up, neighbours scale down to
|
|
52
|
+
* the inactive baseline. Defaults: inactive `1`, active `1.4`.
|
|
53
|
+
*
|
|
54
|
+
* Uniform scale (both axes). For width-axis only growth (pill effect
|
|
55
|
+
* that keeps the dot's height stable) use `useSwiperDotGrowX` instead.
|
|
56
|
+
*/
|
|
57
|
+
export function useSwiperDotScale(opts) {
|
|
58
|
+
const inactive = opts.inactive ?? 1;
|
|
59
|
+
const active = opts.active ?? 1.4;
|
|
60
|
+
return useSwiperDotChannel({
|
|
61
|
+
offset: opts.offset,
|
|
62
|
+
pageWidth: opts.pageWidth,
|
|
63
|
+
index: opts.index,
|
|
64
|
+
window: opts.window,
|
|
65
|
+
channel: 'scale',
|
|
66
|
+
outputRange: [inactive, active, inactive],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Width-axis growth — the active dot stretches into a pill, neighbours
|
|
71
|
+
* shrink to a circle. Uses the `scaleX` channel, so the element's
|
|
72
|
+
* intrinsic size in the layout stays put; only the visual width
|
|
73
|
+
* changes. If you want surrounding siblings to physically shove apart
|
|
74
|
+
* use `useSwiperDotWidth` instead (it animates the `width` style
|
|
75
|
+
* property, which costs a layout pass each frame).
|
|
76
|
+
*/
|
|
77
|
+
export function useSwiperDotGrowX(opts) {
|
|
78
|
+
const inactive = opts.inactive ?? 1;
|
|
79
|
+
const active = opts.active ?? 3;
|
|
80
|
+
return useSwiperDotChannel({
|
|
81
|
+
offset: opts.offset,
|
|
82
|
+
pageWidth: opts.pageWidth,
|
|
83
|
+
index: opts.index,
|
|
84
|
+
window: opts.window,
|
|
85
|
+
channel: 'scaleX',
|
|
86
|
+
outputRange: [inactive, active, inactive],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Layout-aware width growth — animates the element's `width` style in
|
|
91
|
+
* px. Use this when sibling layout must respond (siblings flex away as
|
|
92
|
+
* the pill grows). Slower than `useSwiperDotGrowX` because every frame
|
|
93
|
+
* re-runs layout.
|
|
94
|
+
*
|
|
95
|
+
* Defaults shape an 8px → 24px pill.
|
|
96
|
+
*/
|
|
97
|
+
export function useSwiperDotWidth(opts) {
|
|
98
|
+
const inactive = opts.inactive ?? 8;
|
|
99
|
+
const active = opts.active ?? 24;
|
|
100
|
+
return useSwiperDotChannel({
|
|
101
|
+
offset: opts.offset,
|
|
102
|
+
pageWidth: opts.pageWidth,
|
|
103
|
+
index: opts.index,
|
|
104
|
+
window: opts.window,
|
|
105
|
+
channel: 'width',
|
|
106
|
+
outputRange: [inactive, active, inactive],
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Translate a single "thumb" element across the indicator track,
|
|
111
|
+
* proportional to the swiper's scroll progress. Use for the `bar`
|
|
112
|
+
* variant where a single pill slides between fixed dots.
|
|
113
|
+
*/
|
|
114
|
+
export function useSwiperDotTranslate(opts) {
|
|
115
|
+
const ref = useMainThreadRef(null);
|
|
116
|
+
// factor = step px per pageWidth px of offset. Guard against the
|
|
117
|
+
// divide-by-zero before first layout — a factor of 0 just parks the
|
|
118
|
+
// thumb at translateX(0), which is the correct initial position.
|
|
119
|
+
const factor = opts.pageWidth > 0 ? opts.step / opts.pageWidth : 0;
|
|
120
|
+
useAnimatedStyle(ref, opts.offset, 'translateX', { factor });
|
|
121
|
+
return ref;
|
|
122
|
+
}
|
|
123
|
+
function useSwiperDotChannel(opts) {
|
|
124
|
+
const ref = useMainThreadRef(null);
|
|
125
|
+
// Guard against pre-layout pageWidth=0: collapsing the inputRange to
|
|
126
|
+
// [0, 0, 0] would produce divide-by-zero / NaN in interpolateLinear.
|
|
127
|
+
// Fall back to a non-degenerate window so the binding stays valid; once
|
|
128
|
+
// layout settles and the parent re-renders with a real pageWidth, the
|
|
129
|
+
// values flow through normally.
|
|
130
|
+
const safePageWidth = opts.pageWidth > 0 ? opts.pageWidth : 1;
|
|
131
|
+
const center = opts.index * safePageWidth;
|
|
132
|
+
const w = (opts.window ?? 1) * safePageWidth;
|
|
133
|
+
const params = {
|
|
134
|
+
inputRange: [center - w, center, center + w],
|
|
135
|
+
outputRange: [opts.outputRange[0], opts.outputRange[1], opts.outputRange[2]],
|
|
136
|
+
extrapolate: 'clamp',
|
|
137
|
+
};
|
|
138
|
+
useAnimatedStyle(ref, opts.offset, opts.channel, params);
|
|
139
|
+
return ref;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=use-swiper-dot-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-swiper-dot-progress.js","sourceRoot":"","sources":["../src/use-swiper-dot-progress.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Geometry helpers used by the multi-touch JS-only fallback hooks
|
|
2
|
+
// (`usePinch`, `useRotation`). The arena-driven gesture surface
|
|
3
|
+
// (`Gesture.*` + `useGestureDetector`) computes its own deltas natively;
|
|
4
|
+
// this file is only relevant while the platform's pinch/rotation handlers
|
|
5
|
+
// are unfinished.
|
|
6
|
+
export function distance(x1, y1, x2, y2) {
|
|
7
|
+
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
|
|
8
|
+
}
|
|
9
|
+
export function midpoint(x1, y1, x2, y2) {
|
|
10
|
+
return [(x1 + x2) / 2, (y1 + y2) / 2];
|
|
11
|
+
}
|
|
12
|
+
/** Signed angle in radians from p1 to p2, range (-π, π]. */
|
|
13
|
+
export function angle(x1, y1, x2, y2) {
|
|
14
|
+
return Math.atan2(y2 - y1, x2 - x1);
|
|
15
|
+
}
|
|
16
|
+
/** Shortest signed angular delta between two radians, range (-π, π]. */
|
|
17
|
+
export function angleDelta(from, to) {
|
|
18
|
+
let d = to - from;
|
|
19
|
+
while (d > Math.PI)
|
|
20
|
+
d -= 2 * Math.PI;
|
|
21
|
+
while (d <= -Math.PI)
|
|
22
|
+
d += 2 * Math.PI;
|
|
23
|
+
return d;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,gEAAgE;AAChE,yEAAyE;AACzE,0EAA0E;AAC1E,kBAAkB;AAElB,MAAM,UAAU,QAAQ,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU;IACrE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU;IACrE,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,KAAK,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU;IAClE,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAU;IACjD,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAClB,OAAO,CAAC,GAAG,IAAI,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-gestures",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Gesture system for sigx-lynx - declarative composables for tap, pan, pinch, swipe, long press",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
"author": "Andreas Ekdahl",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@sigx/lynx": "^0.4.
|
|
31
|
+
"@sigx/lynx": "^0.4.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@lynx-js/react": "^0.
|
|
34
|
+
"@lynx-js/react": "^0.121.0",
|
|
35
|
+
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
35
36
|
"typescript": "^6.0.3",
|
|
36
|
-
"
|
|
37
|
-
"@sigx/lynx-runtime-main": "^0.4.
|
|
38
|
-
"@sigx/lynx-testing": "^0.4.
|
|
39
|
-
"@sigx/lynx-plugin": "^0.4.0"
|
|
37
|
+
"@sigx/lynx-plugin": "^0.4.2",
|
|
38
|
+
"@sigx/lynx-runtime-main": "^0.4.2",
|
|
39
|
+
"@sigx/lynx-testing": "^0.4.2"
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
|
-
"build": "
|
|
55
|
-
"dev": "
|
|
54
|
+
"build": "node ../../scripts/clean.mjs dist && tsgo",
|
|
55
|
+
"dev": "tsgo --watch",
|
|
56
|
+
"clean": "node ../../scripts/clean.mjs dist .turbo"
|
|
56
57
|
}
|
|
57
58
|
}
|