@prose-reader/enhancer-gestures 1.81.0
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/LICENCE +7 -0
- package/dist/SettingsManager.d.ts +6 -0
- package/dist/gestures/pan.d.ts +12 -0
- package/dist/gestures/pinch.d.ts +12 -0
- package/dist/gestures/swipe.d.ts +11 -0
- package/dist/gestures/taps.d.ts +11 -0
- package/dist/gestures/zoomPan.d.ts +6 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +314 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.umd.cjs +315 -0
- package/dist/index.umd.cjs.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/utils.d.ts +4 -0
- package/package.json +40 -0
package/LICENCE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2021 @prose-reader/core
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SettingsManager } from '@prose-reader/core';
|
|
2
|
+
import { InputSettings, OutputSettings } from './types';
|
|
3
|
+
export declare class GesturesSettingsManager extends SettingsManager<InputSettings, OutputSettings> {
|
|
4
|
+
getOutputSettings(inputSettings: InputSettings): OutputSettings;
|
|
5
|
+
getDefaultSettings(): InputSettings;
|
|
6
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HookManager, Reader } from '@prose-reader/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { GestureEvent, Hook } from '../types';
|
|
4
|
+
import { GesturesSettingsManager } from '../SettingsManager';
|
|
5
|
+
import { PanRecognizer } from 'gesturx';
|
|
6
|
+
export declare const registerPan: ({ reader, recognizer, settingsManager, }: {
|
|
7
|
+
recognizer: PanRecognizer;
|
|
8
|
+
reader: Reader;
|
|
9
|
+
hookManager: HookManager<Hook>;
|
|
10
|
+
unhandledEvent$: Subject<GestureEvent>;
|
|
11
|
+
settingsManager: GesturesSettingsManager;
|
|
12
|
+
}) => import('rxjs').Observable<import('gesturx').PanEvent>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HookManager, Reader } from '@prose-reader/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { GestureEvent, GestureRecognizable, Hook } from '../types';
|
|
4
|
+
import { GesturesSettingsManager } from '../SettingsManager';
|
|
5
|
+
import { PinchEvent } from 'gesturx';
|
|
6
|
+
export declare const registerPinch: ({ reader, recognizable, settingsManager, }: {
|
|
7
|
+
recognizable: GestureRecognizable;
|
|
8
|
+
reader: Reader;
|
|
9
|
+
hookManager: HookManager<Hook>;
|
|
10
|
+
unhandledEvent$: Subject<GestureEvent>;
|
|
11
|
+
settingsManager: GesturesSettingsManager;
|
|
12
|
+
}) => import('rxjs').Observable<PinchEvent>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HookManager, Reader } from '@prose-reader/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { GestureEvent, GestureRecognizable, Hook } from '../types';
|
|
4
|
+
import { GesturesSettingsManager } from '../SettingsManager';
|
|
5
|
+
export declare const registerSwipe: ({ reader, recognizable, settingsManager, }: {
|
|
6
|
+
recognizable: GestureRecognizable;
|
|
7
|
+
reader: Reader;
|
|
8
|
+
hookManager: HookManager<Hook>;
|
|
9
|
+
unhandledEvent$: Subject<GestureEvent>;
|
|
10
|
+
settingsManager: GesturesSettingsManager;
|
|
11
|
+
}) => import('rxjs').Observable<import('gesturx').SwipeEvent>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HookManager, Reader } from '@prose-reader/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { GestureEvent, GestureRecognizable, Hook } from '../types';
|
|
4
|
+
import { GesturesSettingsManager } from '../SettingsManager';
|
|
5
|
+
export declare const registerTaps: ({ reader, recognizable, unhandledEvent$, hookManager, }: {
|
|
6
|
+
recognizable: GestureRecognizable;
|
|
7
|
+
reader: Reader;
|
|
8
|
+
hookManager: HookManager<Hook>;
|
|
9
|
+
unhandledEvent$: Subject<GestureEvent>;
|
|
10
|
+
settingsManager: GesturesSettingsManager;
|
|
11
|
+
}) => import('rxjs').Observable<import('gesturx').TapEvent | import('gesturx').PanEvent | import('gesturx').SwipeEvent | import('gesturx').PinchEvent>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Reader } from '@prose-reader/core';
|
|
2
|
+
import { EnhancerAPI, InputSettings } from './types';
|
|
3
|
+
export declare const gesturesEnhancer: <InheritOptions, InheritOutput extends Reader>(next: (options: InheritOptions) => InheritOutput) => (options: InheritOptions & {
|
|
4
|
+
gestures?: Partial<InputSettings>;
|
|
5
|
+
}) => InheritOutput & EnhancerAPI;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { isHtmlElement, SettingsManager, HookManager } from "@prose-reader/core";
|
|
2
|
+
import { filter, tap, switchMap, EMPTY, withLatestFrom, merge, throttleTime, animationFrameScheduler, takeUntil, Subject, combineLatest } from "rxjs";
|
|
3
|
+
import { PinchRecognizer, PanRecognizer, TapRecognizer, SwipeRecognizer, Recognizable } from "gesturx";
|
|
4
|
+
const filterNotLink = (stream) => stream.pipe(
|
|
5
|
+
filter((event) => {
|
|
6
|
+
const target = event.event.target;
|
|
7
|
+
if (isHtmlElement(target) && target.tagName === "a") return false;
|
|
8
|
+
return true;
|
|
9
|
+
})
|
|
10
|
+
);
|
|
11
|
+
const registerTaps = ({
|
|
12
|
+
reader,
|
|
13
|
+
recognizable,
|
|
14
|
+
unhandledEvent$,
|
|
15
|
+
hookManager
|
|
16
|
+
}) => {
|
|
17
|
+
const gestures$ = recognizable.events$.pipe(
|
|
18
|
+
filterNotLink,
|
|
19
|
+
tap((event) => {
|
|
20
|
+
const normalizedEvent = event.event;
|
|
21
|
+
const { computedPageTurnDirection } = reader.settings.values;
|
|
22
|
+
if (event.type === "tap") {
|
|
23
|
+
const width = window.innerWidth;
|
|
24
|
+
const height = window.innerHeight;
|
|
25
|
+
const pageTurnMargin = 0.15;
|
|
26
|
+
if (`x` in normalizedEvent) {
|
|
27
|
+
const { x = 0, y } = normalizedEvent;
|
|
28
|
+
const beforeTapResults = hookManager.execute("beforeTap", void 0, { event });
|
|
29
|
+
if (beforeTapResults.some((result) => result === false)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const isTopArea = y < height * pageTurnMargin;
|
|
33
|
+
const isBottomArea = y > height * (1 - pageTurnMargin);
|
|
34
|
+
const isLeftArea = x < width * pageTurnMargin;
|
|
35
|
+
const isRightArea = x > width * (1 - pageTurnMargin);
|
|
36
|
+
if (isLeftArea && computedPageTurnDirection === "horizontal") {
|
|
37
|
+
reader.navigation.turnLeftOrTop();
|
|
38
|
+
} else if (isTopArea && computedPageTurnDirection === "vertical") {
|
|
39
|
+
reader.navigation.turnLeftOrTop();
|
|
40
|
+
} else if (isBottomArea && computedPageTurnDirection === "vertical") {
|
|
41
|
+
reader.navigation.turnRightOrBottom();
|
|
42
|
+
} else if (isRightArea && computedPageTurnDirection === "horizontal") {
|
|
43
|
+
reader.navigation.turnRightOrBottom();
|
|
44
|
+
} else {
|
|
45
|
+
unhandledEvent$.next(event);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
return gestures$;
|
|
52
|
+
};
|
|
53
|
+
const DELAY_IGNORE_PAN = 400;
|
|
54
|
+
const registerPan = ({
|
|
55
|
+
reader,
|
|
56
|
+
recognizer,
|
|
57
|
+
settingsManager
|
|
58
|
+
}) => {
|
|
59
|
+
const gestures$ = settingsManager.values$.pipe(
|
|
60
|
+
switchMap(({ panNavigation }) => {
|
|
61
|
+
if (panNavigation !== "pan") return EMPTY;
|
|
62
|
+
return recognizer.events$.pipe(
|
|
63
|
+
tap((event) => {
|
|
64
|
+
if (reader.zoom.isZooming) return;
|
|
65
|
+
if (event.type === `panStart`) {
|
|
66
|
+
if (event.delay > DELAY_IGNORE_PAN) return;
|
|
67
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: 0, y: 0 }, { start: true });
|
|
68
|
+
}
|
|
69
|
+
if (event.type === `panMove`) {
|
|
70
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: event.deltaX, y: event.deltaY });
|
|
71
|
+
}
|
|
72
|
+
if (event.type === `panEnd`) {
|
|
73
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: event.deltaX, y: event.deltaY }, { final: true });
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
return gestures$;
|
|
80
|
+
};
|
|
81
|
+
const registerSwipe = ({
|
|
82
|
+
reader,
|
|
83
|
+
recognizable,
|
|
84
|
+
settingsManager
|
|
85
|
+
}) => {
|
|
86
|
+
const gestures$ = settingsManager.values$.pipe(
|
|
87
|
+
switchMap(
|
|
88
|
+
({ panNavigation }) => panNavigation !== "swipe" ? EMPTY : recognizable.events$.pipe(
|
|
89
|
+
filter((event) => event.type === "swipe"),
|
|
90
|
+
tap((event) => {
|
|
91
|
+
const { computedPageTurnDirection } = reader.settings.values;
|
|
92
|
+
if (computedPageTurnDirection === "vertical") {
|
|
93
|
+
if (event.velocityY < -0.5) {
|
|
94
|
+
reader == null ? void 0 : reader.navigation.turnRight();
|
|
95
|
+
}
|
|
96
|
+
if (event.velocityY > 0.5) {
|
|
97
|
+
reader == null ? void 0 : reader.navigation.turnLeft();
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
if (event.velocityX < -0.5) {
|
|
101
|
+
reader == null ? void 0 : reader.navigation.turnRight();
|
|
102
|
+
}
|
|
103
|
+
if (event.velocityX > 0.5) {
|
|
104
|
+
reader == null ? void 0 : reader.navigation.turnLeft();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
);
|
|
111
|
+
return gestures$;
|
|
112
|
+
};
|
|
113
|
+
class GesturesSettingsManager extends SettingsManager {
|
|
114
|
+
getOutputSettings(inputSettings) {
|
|
115
|
+
return inputSettings;
|
|
116
|
+
}
|
|
117
|
+
getDefaultSettings() {
|
|
118
|
+
return {
|
|
119
|
+
panNavigation: "pan",
|
|
120
|
+
fontScalePinchEnabled: false,
|
|
121
|
+
fontScalePinchThrottleTime: 500,
|
|
122
|
+
pinchCancelPan: true
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const isHtmlImageElement = (target) => isHtmlElement(target) && !!target.ownerDocument.defaultView && target instanceof target.ownerDocument.defaultView.HTMLImageElement;
|
|
127
|
+
const registerPinch = ({
|
|
128
|
+
reader,
|
|
129
|
+
recognizable,
|
|
130
|
+
settingsManager
|
|
131
|
+
}) => {
|
|
132
|
+
const pinchStart$ = recognizable.events$.pipe(filter((event) => event.type === "pinchStart"));
|
|
133
|
+
const pinchMove$ = recognizable.events$.pipe(filter((event) => event.type === "pinchMove"));
|
|
134
|
+
const pinchEnd$ = recognizable.events$.pipe(filter((event) => event.type === "pinchEnd"));
|
|
135
|
+
const shouldStartZoom = (target) => isHtmlImageElement(target) && !reader.zoom.isZooming;
|
|
136
|
+
return settingsManager.values$.pipe(
|
|
137
|
+
switchMap(({ fontScalePinchEnabled, fontScalePinchThrottleTime }) => {
|
|
138
|
+
const zoomGestures$ = pinchStart$.pipe(
|
|
139
|
+
withLatestFrom(reader.viewportState$),
|
|
140
|
+
switchMap(([event, viewportState]) => {
|
|
141
|
+
const target = event.event.target;
|
|
142
|
+
const startScale = reader.zoom.currentScale;
|
|
143
|
+
if (viewportState === "busy") return EMPTY;
|
|
144
|
+
if (shouldStartZoom(target)) {
|
|
145
|
+
reader.zoom.enter(target);
|
|
146
|
+
}
|
|
147
|
+
if (!reader.zoom.isZooming) return EMPTY;
|
|
148
|
+
return merge(
|
|
149
|
+
pinchMove$.pipe(
|
|
150
|
+
tap((event2) => {
|
|
151
|
+
if (reader.zoom.isZooming) {
|
|
152
|
+
const newScale = startScale + (event2.scale - 1);
|
|
153
|
+
if (newScale < 1) {
|
|
154
|
+
reader.zoom.exit();
|
|
155
|
+
} else {
|
|
156
|
+
reader.zoom.scaleAt(newScale);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
})
|
|
163
|
+
);
|
|
164
|
+
const watchForFontScaleChange$ = !fontScalePinchEnabled ? EMPTY : pinchStart$.pipe(
|
|
165
|
+
withLatestFrom(reader.viewportState$),
|
|
166
|
+
switchMap(([pinchStartEvent, viewportState]) => {
|
|
167
|
+
if (viewportState === "busy" || shouldStartZoom(pinchStartEvent.event.target) || reader.zoom.isZooming)
|
|
168
|
+
return EMPTY;
|
|
169
|
+
const lastFontScaleOnPinchStart = reader.settings.values.fontScale;
|
|
170
|
+
return pinchMove$.pipe(
|
|
171
|
+
throttleTime(fontScalePinchThrottleTime, animationFrameScheduler, {
|
|
172
|
+
trailing: true
|
|
173
|
+
}),
|
|
174
|
+
tap((event) => {
|
|
175
|
+
reader.settings.update({
|
|
176
|
+
fontScale: parseFloat((lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2))
|
|
177
|
+
});
|
|
178
|
+
}),
|
|
179
|
+
takeUntil(pinchEnd$)
|
|
180
|
+
);
|
|
181
|
+
})
|
|
182
|
+
);
|
|
183
|
+
return merge(zoomGestures$, watchForFontScaleChange$);
|
|
184
|
+
})
|
|
185
|
+
);
|
|
186
|
+
};
|
|
187
|
+
const registerZoomPan = ({ reader, recognizer }) => {
|
|
188
|
+
const panStart$ = recognizer.events$.pipe(filter((event) => event.type === "panStart"));
|
|
189
|
+
const panMove$ = recognizer.events$.pipe(filter((event) => event.type === "panMove"));
|
|
190
|
+
const zoomingPan$ = panStart$.pipe(
|
|
191
|
+
switchMap(() => {
|
|
192
|
+
const startPosition = reader.zoom.currentPosition;
|
|
193
|
+
return panMove$.pipe(
|
|
194
|
+
tap((panMoveEvent) => {
|
|
195
|
+
if (reader.zoom.isZooming) {
|
|
196
|
+
reader.zoom.moveAt({ x: startPosition.x + panMoveEvent.deltaX, y: startPosition.y + panMoveEvent.deltaY });
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
);
|
|
200
|
+
})
|
|
201
|
+
);
|
|
202
|
+
return zoomingPan$;
|
|
203
|
+
};
|
|
204
|
+
const gesturesEnhancer = (next) => (options) => {
|
|
205
|
+
const { gestures = {}, ...rest } = options;
|
|
206
|
+
const reader = next(rest);
|
|
207
|
+
const settingsManager = new GesturesSettingsManager(gestures);
|
|
208
|
+
const hookManager = new HookManager();
|
|
209
|
+
const pinchRecognizer = new PinchRecognizer({
|
|
210
|
+
options: {
|
|
211
|
+
/**
|
|
212
|
+
* @important
|
|
213
|
+
* To be less than pan otherwise it will not fail before it starts
|
|
214
|
+
*/
|
|
215
|
+
posThreshold: 20
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
const panRecognizer = new PanRecognizer({
|
|
219
|
+
failWith: [pinchRecognizer],
|
|
220
|
+
options: {
|
|
221
|
+
// we want to have some margin to trigger zoom
|
|
222
|
+
posThreshold: 30
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
const zoomPanRecognizer = new PanRecognizer({
|
|
226
|
+
options: {
|
|
227
|
+
posThreshold: 1
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const tapRecognizer = new TapRecognizer({
|
|
231
|
+
failWith: [panRecognizer]
|
|
232
|
+
});
|
|
233
|
+
const swipeRecognizer = new SwipeRecognizer();
|
|
234
|
+
const recognizable = new Recognizable({
|
|
235
|
+
recognizers: [tapRecognizer, panRecognizer, swipeRecognizer, pinchRecognizer, zoomPanRecognizer]
|
|
236
|
+
});
|
|
237
|
+
const unhandledEvent$ = new Subject();
|
|
238
|
+
const tapGestures$ = registerTaps({
|
|
239
|
+
hookManager,
|
|
240
|
+
reader,
|
|
241
|
+
recognizable,
|
|
242
|
+
unhandledEvent$,
|
|
243
|
+
settingsManager
|
|
244
|
+
});
|
|
245
|
+
const panGestures$ = registerPan({
|
|
246
|
+
hookManager,
|
|
247
|
+
reader,
|
|
248
|
+
recognizer: panRecognizer,
|
|
249
|
+
unhandledEvent$,
|
|
250
|
+
settingsManager
|
|
251
|
+
});
|
|
252
|
+
const swipeGestures$ = registerSwipe({
|
|
253
|
+
hookManager,
|
|
254
|
+
reader,
|
|
255
|
+
recognizable,
|
|
256
|
+
unhandledEvent$,
|
|
257
|
+
settingsManager
|
|
258
|
+
});
|
|
259
|
+
const pinchGestures$ = registerPinch({
|
|
260
|
+
hookManager,
|
|
261
|
+
reader,
|
|
262
|
+
recognizable,
|
|
263
|
+
settingsManager,
|
|
264
|
+
unhandledEvent$
|
|
265
|
+
});
|
|
266
|
+
const zoomPanGestures$ = registerZoomPan({
|
|
267
|
+
reader,
|
|
268
|
+
recognizer: zoomPanRecognizer
|
|
269
|
+
});
|
|
270
|
+
const containerUpdate$ = reader.context.containerElement$.pipe(
|
|
271
|
+
tap((container) => {
|
|
272
|
+
recognizable.update({
|
|
273
|
+
container
|
|
274
|
+
});
|
|
275
|
+
})
|
|
276
|
+
);
|
|
277
|
+
const watchSettings$ = combineLatest([settingsManager.values$, panRecognizer.config$]).pipe(
|
|
278
|
+
tap(([{ pinchCancelPan }, panRecognizerConfig]) => {
|
|
279
|
+
var _a, _b;
|
|
280
|
+
const pinchAlreadyInFailWith = (_a = panRecognizerConfig.failWith) == null ? void 0 : _a.includes(pinchRecognizer);
|
|
281
|
+
if (pinchCancelPan && !pinchAlreadyInFailWith) {
|
|
282
|
+
panRecognizer.update({
|
|
283
|
+
failWith: [...panRecognizerConfig.failWith ?? [], pinchRecognizer]
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (!pinchCancelPan && pinchAlreadyInFailWith) {
|
|
287
|
+
panRecognizer.update({
|
|
288
|
+
failWith: (_b = panRecognizerConfig.failWith) == null ? void 0 : _b.filter((recognizer) => recognizer !== pinchRecognizer)
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
merge(
|
|
294
|
+
containerUpdate$,
|
|
295
|
+
watchSettings$,
|
|
296
|
+
zoomPanGestures$,
|
|
297
|
+
pinchGestures$,
|
|
298
|
+
tapGestures$,
|
|
299
|
+
swipeGestures$,
|
|
300
|
+
panGestures$
|
|
301
|
+
).pipe(takeUntil(reader.$.destroy$)).subscribe();
|
|
302
|
+
return {
|
|
303
|
+
...reader,
|
|
304
|
+
gestures: {
|
|
305
|
+
settings: settingsManager,
|
|
306
|
+
unhandledEvent$: unhandledEvent$.asObservable(),
|
|
307
|
+
hookManager
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
export {
|
|
312
|
+
gesturesEnhancer
|
|
313
|
+
};
|
|
314
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils.ts","../src/gestures/taps.ts","../src/gestures/pan.ts","../src/gestures/swipe.ts","../src/SettingsManager.ts","../src/gestures/pinch.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { isHtmlElement } from \"@prose-reader/core\"\nimport { filter, Observable } from \"rxjs\"\n\nexport const filterNotLink = <Event extends { event: PointerEvent }>(stream: Observable<Event>) =>\n stream.pipe(\n filter((event) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n }),\n )\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { Subject, tap } from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { filterNotLink } from \"../utils\"\n\nexport const registerTaps = ({\n reader,\n recognizable,\n unhandledEvent$,\n hookManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filterNotLink,\n tap((event) => {\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (event.type === \"tap\") {\n const width = window.innerWidth\n const height = window.innerHeight\n const pageTurnMargin = 0.15\n\n if (`x` in normalizedEvent) {\n const { x = 0, y } = normalizedEvent\n\n const beforeTapResults = hookManager.execute(\"beforeTap\", undefined, { event })\n\n if (beforeTapResults.some((result) => result === false)) {\n return\n }\n\n const isTopArea = y < height * pageTurnMargin\n const isBottomArea = y > height * (1 - pageTurnMargin)\n const isLeftArea = x < width * pageTurnMargin\n const isRightArea = x > width * (1 - pageTurnMargin)\n\n if (isLeftArea && computedPageTurnDirection === \"horizontal\") {\n reader.navigation.turnLeftOrTop()\n } else if (isTopArea && computedPageTurnDirection === \"vertical\") {\n reader.navigation.turnLeftOrTop()\n } else if (isBottomArea && computedPageTurnDirection === \"vertical\") {\n reader.navigation.turnRightOrBottom()\n } else if (isRightArea && computedPageTurnDirection === \"horizontal\") {\n reader.navigation.turnRightOrBottom()\n } else {\n unhandledEvent$.next(event)\n }\n }\n }\n }),\n )\n\n return gestures$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, Subject, switchMap, tap } from \"rxjs\"\nimport { GestureEvent, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { PanRecognizer } from \"gesturx\"\n\nconst DELAY_IGNORE_PAN = 400\n\nexport const registerPan = ({\n reader,\n recognizer,\n settingsManager,\n}: {\n recognizer: PanRecognizer\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = settingsManager.values$.pipe(\n switchMap(({ panNavigation }) => {\n if (panNavigation !== \"pan\") return EMPTY\n\n return recognizer.events$.pipe(\n tap((event) => {\n if (reader.zoom.isZooming) return\n\n if (event.type === `panStart`) {\n /**\n * We let the user select\n */\n if (event.delay > DELAY_IGNORE_PAN) return\n\n reader?.navigation.moveTo({ x: 0, y: 0 }, { start: true })\n }\n\n if (event.type === `panMove`) {\n reader?.navigation.moveTo({ x: event.deltaX, y: event.deltaY })\n }\n\n if (event.type === `panEnd`) {\n reader?.navigation.moveTo({ x: event.deltaX, y: event.deltaY }, { final: true })\n }\n }),\n )\n }),\n )\n\n return gestures$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, Subject, filter, switchMap, tap } from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = settingsManager.values$.pipe(\n switchMap(({ panNavigation }) =>\n panNavigation !== \"swipe\"\n ? EMPTY\n : recognizable.events$.pipe(\n filter((event) => event.type === \"swipe\"),\n tap((event) => {\n const { computedPageTurnDirection } = reader.settings.values\n\n if (computedPageTurnDirection === \"vertical\") {\n if (event.velocityY < -0.5) {\n reader?.navigation.turnRight()\n }\n if (event.velocityY > 0.5) {\n reader?.navigation.turnLeft()\n }\n } else {\n if (event.velocityX < -0.5) {\n reader?.navigation.turnRight()\n }\n if (event.velocityX > 0.5) {\n reader?.navigation.turnLeft()\n }\n }\n }),\n ),\n ),\n )\n\n return gestures$\n}\n","import { SettingsManager } from \"@prose-reader/core\"\nimport { InputSettings, OutputSettings } from \"./types\"\n\nexport class GesturesSettingsManager extends SettingsManager<InputSettings, OutputSettings> {\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return inputSettings\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n fontScalePinchEnabled: false,\n fontScalePinchThrottleTime: 500,\n pinchCancelPan: true,\n }\n }\n}\n","import { HookManager, isHtmlElement, Reader } from \"@prose-reader/core\"\nimport {\n EMPTY,\n Subject,\n animationFrameScheduler,\n filter,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { PinchEvent } from \"gesturx\"\n\nconst isHtmlImageElement = (target: EventTarget | null): target is HTMLImageElement =>\n isHtmlElement(target) &&\n !!target.ownerDocument.defaultView &&\n target instanceof target.ownerDocument.defaultView.HTMLImageElement\n\nexport const registerPinch = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchStart\"))\n\n const pinchMove$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchMove\"))\n\n const pinchEnd$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchEnd\"))\n\n const shouldStartZoom = (target: EventTarget | null): target is HTMLImageElement =>\n isHtmlImageElement(target) && !reader.zoom.isZooming\n\n return settingsManager.values$.pipe(\n switchMap(({ fontScalePinchEnabled, fontScalePinchThrottleTime }) => {\n const zoomGestures$ = pinchStart$.pipe(\n withLatestFrom(reader.viewportState$),\n switchMap(([event, viewportState]) => {\n const target = event.event.target\n const startScale = reader.zoom.currentScale\n\n if (viewportState === \"busy\") return EMPTY\n\n if (shouldStartZoom(target)) {\n reader.zoom.enter(target)\n }\n\n if (!reader.zoom.isZooming) return EMPTY\n\n return merge(\n pinchMove$.pipe(\n tap((event) => {\n if (reader.zoom.isZooming) {\n const newScale = startScale + (event.scale - 1)\n\n if (newScale < 1) {\n reader.zoom.exit()\n } else {\n reader.zoom.scaleAt(newScale)\n }\n }\n }),\n ),\n )\n }),\n )\n\n const watchForFontScaleChange$ = !fontScalePinchEnabled\n ? EMPTY\n : pinchStart$.pipe(\n withLatestFrom(reader.viewportState$),\n switchMap(([pinchStartEvent, viewportState]) => {\n if (viewportState === \"busy\" || shouldStartZoom(pinchStartEvent.event.target) || reader.zoom.isZooming)\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(fontScalePinchThrottleTime, animationFrameScheduler, {\n trailing: true,\n }),\n tap((event) => {\n reader.settings.update({\n fontScale: parseFloat((lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2)),\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$)\n }),\n )\n}\n","import { Reader } from \"@prose-reader/core\"\nimport { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({ reader, recognizer }: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(filter((event) => event.type === \"panStart\"))\n const panMove$ = recognizer.events$.pipe(filter((event) => event.type === \"panMove\"))\n\n const zoomingPan$ = panStart$.pipe(\n switchMap(() => {\n const startPosition = reader.zoom.currentPosition\n\n return panMove$.pipe(\n tap((panMoveEvent) => {\n if (reader.zoom.isZooming) {\n reader.zoom.moveAt({ x: startPosition.x + panMoveEvent.deltaX, y: startPosition.y + panMoveEvent.deltaY })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { ObservedValueOf, Subject, combineLatest, merge, takeUntil, tap } from \"rxjs\"\nimport { PanRecognizer, PinchRecognizer, Recognizable, SwipeRecognizer, TapRecognizer } from \"gesturx\"\nimport { EnhancerAPI, InputSettings, Hook } from \"./types\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(next: (options: InheritOptions) => InheritOutput) =>\n (\n options: InheritOptions & {\n gestures?: Partial<InputSettings>\n },\n ): InheritOutput & EnhancerAPI => {\n const { gestures = {}, ...rest } = options\n const reader = next(rest as InheritOptions)\n\n const settingsManager = new GesturesSettingsManager(gestures)\n\n const hookManager = new HookManager<Hook>()\n\n const pinchRecognizer = new PinchRecognizer({\n options: {\n /**\n * @important\n * To be less than pan otherwise it will not fail before it starts\n */\n posThreshold: 20,\n },\n })\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 30,\n },\n })\n\n const zoomPanRecognizer = new PanRecognizer({\n options: {\n posThreshold: 1,\n },\n })\n\n const tapRecognizer = new TapRecognizer({\n failWith: [panRecognizer],\n })\n\n const swipeRecognizer = new SwipeRecognizer()\n\n const recognizable = new Recognizable({\n recognizers: [tapRecognizer, panRecognizer, swipeRecognizer, pinchRecognizer, zoomPanRecognizer],\n })\n\n const unhandledEvent$ = new Subject<ObservedValueOf<typeof recognizable.events$>>()\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n unhandledEvent$,\n settingsManager,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n unhandledEvent$,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n unhandledEvent$,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n unhandledEvent$,\n })\n\n const zoomPanGestures$ = registerZoomPan({\n reader,\n recognizer: zoomPanRecognizer,\n })\n\n const containerUpdate$ = reader.context.containerElement$.pipe(\n tap((container) => {\n recognizable.update({\n container,\n })\n }),\n )\n\n const watchSettings$ = combineLatest([settingsManager.values$, panRecognizer.config$]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith = panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [...(panRecognizerConfig.failWith ?? []), pinchRecognizer],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter((recognizer) => recognizer !== pinchRecognizer),\n })\n }\n }),\n )\n\n merge(\n containerUpdate$,\n watchSettings$,\n zoomPanGestures$,\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n )\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n gestures: {\n settings: settingsManager,\n unhandledEvent$: unhandledEvent$.asObservable(),\n hookManager,\n },\n }\n }\n"],"names":["event"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@prose-reader/core"), require("rxjs"), require("gesturx")) : typeof define === "function" && define.amd ? define(["exports", "@prose-reader/core", "rxjs", "gesturx"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["prose-reader-enhancer-gestures"] = {}, global.core, global.rxjs, global.gesturx));
|
|
3
|
+
})(this, function(exports2, core, rxjs, gesturx) {
|
|
4
|
+
"use strict";
|
|
5
|
+
const filterNotLink = (stream) => stream.pipe(
|
|
6
|
+
rxjs.filter((event) => {
|
|
7
|
+
const target = event.event.target;
|
|
8
|
+
if (core.isHtmlElement(target) && target.tagName === "a") return false;
|
|
9
|
+
return true;
|
|
10
|
+
})
|
|
11
|
+
);
|
|
12
|
+
const registerTaps = ({
|
|
13
|
+
reader,
|
|
14
|
+
recognizable,
|
|
15
|
+
unhandledEvent$,
|
|
16
|
+
hookManager
|
|
17
|
+
}) => {
|
|
18
|
+
const gestures$ = recognizable.events$.pipe(
|
|
19
|
+
filterNotLink,
|
|
20
|
+
rxjs.tap((event) => {
|
|
21
|
+
const normalizedEvent = event.event;
|
|
22
|
+
const { computedPageTurnDirection } = reader.settings.values;
|
|
23
|
+
if (event.type === "tap") {
|
|
24
|
+
const width = window.innerWidth;
|
|
25
|
+
const height = window.innerHeight;
|
|
26
|
+
const pageTurnMargin = 0.15;
|
|
27
|
+
if (`x` in normalizedEvent) {
|
|
28
|
+
const { x = 0, y } = normalizedEvent;
|
|
29
|
+
const beforeTapResults = hookManager.execute("beforeTap", void 0, { event });
|
|
30
|
+
if (beforeTapResults.some((result) => result === false)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const isTopArea = y < height * pageTurnMargin;
|
|
34
|
+
const isBottomArea = y > height * (1 - pageTurnMargin);
|
|
35
|
+
const isLeftArea = x < width * pageTurnMargin;
|
|
36
|
+
const isRightArea = x > width * (1 - pageTurnMargin);
|
|
37
|
+
if (isLeftArea && computedPageTurnDirection === "horizontal") {
|
|
38
|
+
reader.navigation.turnLeftOrTop();
|
|
39
|
+
} else if (isTopArea && computedPageTurnDirection === "vertical") {
|
|
40
|
+
reader.navigation.turnLeftOrTop();
|
|
41
|
+
} else if (isBottomArea && computedPageTurnDirection === "vertical") {
|
|
42
|
+
reader.navigation.turnRightOrBottom();
|
|
43
|
+
} else if (isRightArea && computedPageTurnDirection === "horizontal") {
|
|
44
|
+
reader.navigation.turnRightOrBottom();
|
|
45
|
+
} else {
|
|
46
|
+
unhandledEvent$.next(event);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
return gestures$;
|
|
53
|
+
};
|
|
54
|
+
const DELAY_IGNORE_PAN = 400;
|
|
55
|
+
const registerPan = ({
|
|
56
|
+
reader,
|
|
57
|
+
recognizer,
|
|
58
|
+
settingsManager
|
|
59
|
+
}) => {
|
|
60
|
+
const gestures$ = settingsManager.values$.pipe(
|
|
61
|
+
rxjs.switchMap(({ panNavigation }) => {
|
|
62
|
+
if (panNavigation !== "pan") return rxjs.EMPTY;
|
|
63
|
+
return recognizer.events$.pipe(
|
|
64
|
+
rxjs.tap((event) => {
|
|
65
|
+
if (reader.zoom.isZooming) return;
|
|
66
|
+
if (event.type === `panStart`) {
|
|
67
|
+
if (event.delay > DELAY_IGNORE_PAN) return;
|
|
68
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: 0, y: 0 }, { start: true });
|
|
69
|
+
}
|
|
70
|
+
if (event.type === `panMove`) {
|
|
71
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: event.deltaX, y: event.deltaY });
|
|
72
|
+
}
|
|
73
|
+
if (event.type === `panEnd`) {
|
|
74
|
+
reader == null ? void 0 : reader.navigation.moveTo({ x: event.deltaX, y: event.deltaY }, { final: true });
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
return gestures$;
|
|
81
|
+
};
|
|
82
|
+
const registerSwipe = ({
|
|
83
|
+
reader,
|
|
84
|
+
recognizable,
|
|
85
|
+
settingsManager
|
|
86
|
+
}) => {
|
|
87
|
+
const gestures$ = settingsManager.values$.pipe(
|
|
88
|
+
rxjs.switchMap(
|
|
89
|
+
({ panNavigation }) => panNavigation !== "swipe" ? rxjs.EMPTY : recognizable.events$.pipe(
|
|
90
|
+
rxjs.filter((event) => event.type === "swipe"),
|
|
91
|
+
rxjs.tap((event) => {
|
|
92
|
+
const { computedPageTurnDirection } = reader.settings.values;
|
|
93
|
+
if (computedPageTurnDirection === "vertical") {
|
|
94
|
+
if (event.velocityY < -0.5) {
|
|
95
|
+
reader == null ? void 0 : reader.navigation.turnRight();
|
|
96
|
+
}
|
|
97
|
+
if (event.velocityY > 0.5) {
|
|
98
|
+
reader == null ? void 0 : reader.navigation.turnLeft();
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (event.velocityX < -0.5) {
|
|
102
|
+
reader == null ? void 0 : reader.navigation.turnRight();
|
|
103
|
+
}
|
|
104
|
+
if (event.velocityX > 0.5) {
|
|
105
|
+
reader == null ? void 0 : reader.navigation.turnLeft();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
return gestures$;
|
|
113
|
+
};
|
|
114
|
+
class GesturesSettingsManager extends core.SettingsManager {
|
|
115
|
+
getOutputSettings(inputSettings) {
|
|
116
|
+
return inputSettings;
|
|
117
|
+
}
|
|
118
|
+
getDefaultSettings() {
|
|
119
|
+
return {
|
|
120
|
+
panNavigation: "pan",
|
|
121
|
+
fontScalePinchEnabled: false,
|
|
122
|
+
fontScalePinchThrottleTime: 500,
|
|
123
|
+
pinchCancelPan: true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const isHtmlImageElement = (target) => core.isHtmlElement(target) && !!target.ownerDocument.defaultView && target instanceof target.ownerDocument.defaultView.HTMLImageElement;
|
|
128
|
+
const registerPinch = ({
|
|
129
|
+
reader,
|
|
130
|
+
recognizable,
|
|
131
|
+
settingsManager
|
|
132
|
+
}) => {
|
|
133
|
+
const pinchStart$ = recognizable.events$.pipe(rxjs.filter((event) => event.type === "pinchStart"));
|
|
134
|
+
const pinchMove$ = recognizable.events$.pipe(rxjs.filter((event) => event.type === "pinchMove"));
|
|
135
|
+
const pinchEnd$ = recognizable.events$.pipe(rxjs.filter((event) => event.type === "pinchEnd"));
|
|
136
|
+
const shouldStartZoom = (target) => isHtmlImageElement(target) && !reader.zoom.isZooming;
|
|
137
|
+
return settingsManager.values$.pipe(
|
|
138
|
+
rxjs.switchMap(({ fontScalePinchEnabled, fontScalePinchThrottleTime }) => {
|
|
139
|
+
const zoomGestures$ = pinchStart$.pipe(
|
|
140
|
+
rxjs.withLatestFrom(reader.viewportState$),
|
|
141
|
+
rxjs.switchMap(([event, viewportState]) => {
|
|
142
|
+
const target = event.event.target;
|
|
143
|
+
const startScale = reader.zoom.currentScale;
|
|
144
|
+
if (viewportState === "busy") return rxjs.EMPTY;
|
|
145
|
+
if (shouldStartZoom(target)) {
|
|
146
|
+
reader.zoom.enter(target);
|
|
147
|
+
}
|
|
148
|
+
if (!reader.zoom.isZooming) return rxjs.EMPTY;
|
|
149
|
+
return rxjs.merge(
|
|
150
|
+
pinchMove$.pipe(
|
|
151
|
+
rxjs.tap((event2) => {
|
|
152
|
+
if (reader.zoom.isZooming) {
|
|
153
|
+
const newScale = startScale + (event2.scale - 1);
|
|
154
|
+
if (newScale < 1) {
|
|
155
|
+
reader.zoom.exit();
|
|
156
|
+
} else {
|
|
157
|
+
reader.zoom.scaleAt(newScale);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
const watchForFontScaleChange$ = !fontScalePinchEnabled ? rxjs.EMPTY : pinchStart$.pipe(
|
|
166
|
+
rxjs.withLatestFrom(reader.viewportState$),
|
|
167
|
+
rxjs.switchMap(([pinchStartEvent, viewportState]) => {
|
|
168
|
+
if (viewportState === "busy" || shouldStartZoom(pinchStartEvent.event.target) || reader.zoom.isZooming)
|
|
169
|
+
return rxjs.EMPTY;
|
|
170
|
+
const lastFontScaleOnPinchStart = reader.settings.values.fontScale;
|
|
171
|
+
return pinchMove$.pipe(
|
|
172
|
+
rxjs.throttleTime(fontScalePinchThrottleTime, rxjs.animationFrameScheduler, {
|
|
173
|
+
trailing: true
|
|
174
|
+
}),
|
|
175
|
+
rxjs.tap((event) => {
|
|
176
|
+
reader.settings.update({
|
|
177
|
+
fontScale: parseFloat((lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2))
|
|
178
|
+
});
|
|
179
|
+
}),
|
|
180
|
+
rxjs.takeUntil(pinchEnd$)
|
|
181
|
+
);
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
return rxjs.merge(zoomGestures$, watchForFontScaleChange$);
|
|
185
|
+
})
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
const registerZoomPan = ({ reader, recognizer }) => {
|
|
189
|
+
const panStart$ = recognizer.events$.pipe(rxjs.filter((event) => event.type === "panStart"));
|
|
190
|
+
const panMove$ = recognizer.events$.pipe(rxjs.filter((event) => event.type === "panMove"));
|
|
191
|
+
const zoomingPan$ = panStart$.pipe(
|
|
192
|
+
rxjs.switchMap(() => {
|
|
193
|
+
const startPosition = reader.zoom.currentPosition;
|
|
194
|
+
return panMove$.pipe(
|
|
195
|
+
rxjs.tap((panMoveEvent) => {
|
|
196
|
+
if (reader.zoom.isZooming) {
|
|
197
|
+
reader.zoom.moveAt({ x: startPosition.x + panMoveEvent.deltaX, y: startPosition.y + panMoveEvent.deltaY });
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
);
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
return zoomingPan$;
|
|
204
|
+
};
|
|
205
|
+
const gesturesEnhancer = (next) => (options) => {
|
|
206
|
+
const { gestures = {}, ...rest } = options;
|
|
207
|
+
const reader = next(rest);
|
|
208
|
+
const settingsManager = new GesturesSettingsManager(gestures);
|
|
209
|
+
const hookManager = new core.HookManager();
|
|
210
|
+
const pinchRecognizer = new gesturx.PinchRecognizer({
|
|
211
|
+
options: {
|
|
212
|
+
/**
|
|
213
|
+
* @important
|
|
214
|
+
* To be less than pan otherwise it will not fail before it starts
|
|
215
|
+
*/
|
|
216
|
+
posThreshold: 20
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
const panRecognizer = new gesturx.PanRecognizer({
|
|
220
|
+
failWith: [pinchRecognizer],
|
|
221
|
+
options: {
|
|
222
|
+
// we want to have some margin to trigger zoom
|
|
223
|
+
posThreshold: 30
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
const zoomPanRecognizer = new gesturx.PanRecognizer({
|
|
227
|
+
options: {
|
|
228
|
+
posThreshold: 1
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
const tapRecognizer = new gesturx.TapRecognizer({
|
|
232
|
+
failWith: [panRecognizer]
|
|
233
|
+
});
|
|
234
|
+
const swipeRecognizer = new gesturx.SwipeRecognizer();
|
|
235
|
+
const recognizable = new gesturx.Recognizable({
|
|
236
|
+
recognizers: [tapRecognizer, panRecognizer, swipeRecognizer, pinchRecognizer, zoomPanRecognizer]
|
|
237
|
+
});
|
|
238
|
+
const unhandledEvent$ = new rxjs.Subject();
|
|
239
|
+
const tapGestures$ = registerTaps({
|
|
240
|
+
hookManager,
|
|
241
|
+
reader,
|
|
242
|
+
recognizable,
|
|
243
|
+
unhandledEvent$,
|
|
244
|
+
settingsManager
|
|
245
|
+
});
|
|
246
|
+
const panGestures$ = registerPan({
|
|
247
|
+
hookManager,
|
|
248
|
+
reader,
|
|
249
|
+
recognizer: panRecognizer,
|
|
250
|
+
unhandledEvent$,
|
|
251
|
+
settingsManager
|
|
252
|
+
});
|
|
253
|
+
const swipeGestures$ = registerSwipe({
|
|
254
|
+
hookManager,
|
|
255
|
+
reader,
|
|
256
|
+
recognizable,
|
|
257
|
+
unhandledEvent$,
|
|
258
|
+
settingsManager
|
|
259
|
+
});
|
|
260
|
+
const pinchGestures$ = registerPinch({
|
|
261
|
+
hookManager,
|
|
262
|
+
reader,
|
|
263
|
+
recognizable,
|
|
264
|
+
settingsManager,
|
|
265
|
+
unhandledEvent$
|
|
266
|
+
});
|
|
267
|
+
const zoomPanGestures$ = registerZoomPan({
|
|
268
|
+
reader,
|
|
269
|
+
recognizer: zoomPanRecognizer
|
|
270
|
+
});
|
|
271
|
+
const containerUpdate$ = reader.context.containerElement$.pipe(
|
|
272
|
+
rxjs.tap((container) => {
|
|
273
|
+
recognizable.update({
|
|
274
|
+
container
|
|
275
|
+
});
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
const watchSettings$ = rxjs.combineLatest([settingsManager.values$, panRecognizer.config$]).pipe(
|
|
279
|
+
rxjs.tap(([{ pinchCancelPan }, panRecognizerConfig]) => {
|
|
280
|
+
var _a, _b;
|
|
281
|
+
const pinchAlreadyInFailWith = (_a = panRecognizerConfig.failWith) == null ? void 0 : _a.includes(pinchRecognizer);
|
|
282
|
+
if (pinchCancelPan && !pinchAlreadyInFailWith) {
|
|
283
|
+
panRecognizer.update({
|
|
284
|
+
failWith: [...panRecognizerConfig.failWith ?? [], pinchRecognizer]
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (!pinchCancelPan && pinchAlreadyInFailWith) {
|
|
288
|
+
panRecognizer.update({
|
|
289
|
+
failWith: (_b = panRecognizerConfig.failWith) == null ? void 0 : _b.filter((recognizer) => recognizer !== pinchRecognizer)
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
);
|
|
294
|
+
rxjs.merge(
|
|
295
|
+
containerUpdate$,
|
|
296
|
+
watchSettings$,
|
|
297
|
+
zoomPanGestures$,
|
|
298
|
+
pinchGestures$,
|
|
299
|
+
tapGestures$,
|
|
300
|
+
swipeGestures$,
|
|
301
|
+
panGestures$
|
|
302
|
+
).pipe(rxjs.takeUntil(reader.$.destroy$)).subscribe();
|
|
303
|
+
return {
|
|
304
|
+
...reader,
|
|
305
|
+
gestures: {
|
|
306
|
+
settings: settingsManager,
|
|
307
|
+
unhandledEvent$: unhandledEvent$.asObservable(),
|
|
308
|
+
hookManager
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
exports2.gesturesEnhancer = gesturesEnhancer;
|
|
313
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
314
|
+
});
|
|
315
|
+
//# sourceMappingURL=index.umd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.cjs","sources":["../src/utils.ts","../src/gestures/taps.ts","../src/gestures/pan.ts","../src/gestures/swipe.ts","../src/SettingsManager.ts","../src/gestures/pinch.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { isHtmlElement } from \"@prose-reader/core\"\nimport { filter, Observable } from \"rxjs\"\n\nexport const filterNotLink = <Event extends { event: PointerEvent }>(stream: Observable<Event>) =>\n stream.pipe(\n filter((event) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n }),\n )\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { Subject, tap } from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { filterNotLink } from \"../utils\"\n\nexport const registerTaps = ({\n reader,\n recognizable,\n unhandledEvent$,\n hookManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filterNotLink,\n tap((event) => {\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (event.type === \"tap\") {\n const width = window.innerWidth\n const height = window.innerHeight\n const pageTurnMargin = 0.15\n\n if (`x` in normalizedEvent) {\n const { x = 0, y } = normalizedEvent\n\n const beforeTapResults = hookManager.execute(\"beforeTap\", undefined, { event })\n\n if (beforeTapResults.some((result) => result === false)) {\n return\n }\n\n const isTopArea = y < height * pageTurnMargin\n const isBottomArea = y > height * (1 - pageTurnMargin)\n const isLeftArea = x < width * pageTurnMargin\n const isRightArea = x > width * (1 - pageTurnMargin)\n\n if (isLeftArea && computedPageTurnDirection === \"horizontal\") {\n reader.navigation.turnLeftOrTop()\n } else if (isTopArea && computedPageTurnDirection === \"vertical\") {\n reader.navigation.turnLeftOrTop()\n } else if (isBottomArea && computedPageTurnDirection === \"vertical\") {\n reader.navigation.turnRightOrBottom()\n } else if (isRightArea && computedPageTurnDirection === \"horizontal\") {\n reader.navigation.turnRightOrBottom()\n } else {\n unhandledEvent$.next(event)\n }\n }\n }\n }),\n )\n\n return gestures$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, Subject, switchMap, tap } from \"rxjs\"\nimport { GestureEvent, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { PanRecognizer } from \"gesturx\"\n\nconst DELAY_IGNORE_PAN = 400\n\nexport const registerPan = ({\n reader,\n recognizer,\n settingsManager,\n}: {\n recognizer: PanRecognizer\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = settingsManager.values$.pipe(\n switchMap(({ panNavigation }) => {\n if (panNavigation !== \"pan\") return EMPTY\n\n return recognizer.events$.pipe(\n tap((event) => {\n if (reader.zoom.isZooming) return\n\n if (event.type === `panStart`) {\n /**\n * We let the user select\n */\n if (event.delay > DELAY_IGNORE_PAN) return\n\n reader?.navigation.moveTo({ x: 0, y: 0 }, { start: true })\n }\n\n if (event.type === `panMove`) {\n reader?.navigation.moveTo({ x: event.deltaX, y: event.deltaY })\n }\n\n if (event.type === `panEnd`) {\n reader?.navigation.moveTo({ x: event.deltaX, y: event.deltaY }, { final: true })\n }\n }),\n )\n }),\n )\n\n return gestures$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, Subject, filter, switchMap, tap } from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = settingsManager.values$.pipe(\n switchMap(({ panNavigation }) =>\n panNavigation !== \"swipe\"\n ? EMPTY\n : recognizable.events$.pipe(\n filter((event) => event.type === \"swipe\"),\n tap((event) => {\n const { computedPageTurnDirection } = reader.settings.values\n\n if (computedPageTurnDirection === \"vertical\") {\n if (event.velocityY < -0.5) {\n reader?.navigation.turnRight()\n }\n if (event.velocityY > 0.5) {\n reader?.navigation.turnLeft()\n }\n } else {\n if (event.velocityX < -0.5) {\n reader?.navigation.turnRight()\n }\n if (event.velocityX > 0.5) {\n reader?.navigation.turnLeft()\n }\n }\n }),\n ),\n ),\n )\n\n return gestures$\n}\n","import { SettingsManager } from \"@prose-reader/core\"\nimport { InputSettings, OutputSettings } from \"./types\"\n\nexport class GesturesSettingsManager extends SettingsManager<InputSettings, OutputSettings> {\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return inputSettings\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n fontScalePinchEnabled: false,\n fontScalePinchThrottleTime: 500,\n pinchCancelPan: true,\n }\n }\n}\n","import { HookManager, isHtmlElement, Reader } from \"@prose-reader/core\"\nimport {\n EMPTY,\n Subject,\n animationFrameScheduler,\n filter,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport { GestureEvent, GestureRecognizable, Hook } from \"../types\"\nimport { GesturesSettingsManager } from \"../SettingsManager\"\nimport { PinchEvent } from \"gesturx\"\n\nconst isHtmlImageElement = (target: EventTarget | null): target is HTMLImageElement =>\n isHtmlElement(target) &&\n !!target.ownerDocument.defaultView &&\n target instanceof target.ownerDocument.defaultView.HTMLImageElement\n\nexport const registerPinch = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n unhandledEvent$: Subject<GestureEvent>\n settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchStart\"))\n\n const pinchMove$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchMove\"))\n\n const pinchEnd$ = recognizable.events$.pipe(filter((event): event is PinchEvent => event.type === \"pinchEnd\"))\n\n const shouldStartZoom = (target: EventTarget | null): target is HTMLImageElement =>\n isHtmlImageElement(target) && !reader.zoom.isZooming\n\n return settingsManager.values$.pipe(\n switchMap(({ fontScalePinchEnabled, fontScalePinchThrottleTime }) => {\n const zoomGestures$ = pinchStart$.pipe(\n withLatestFrom(reader.viewportState$),\n switchMap(([event, viewportState]) => {\n const target = event.event.target\n const startScale = reader.zoom.currentScale\n\n if (viewportState === \"busy\") return EMPTY\n\n if (shouldStartZoom(target)) {\n reader.zoom.enter(target)\n }\n\n if (!reader.zoom.isZooming) return EMPTY\n\n return merge(\n pinchMove$.pipe(\n tap((event) => {\n if (reader.zoom.isZooming) {\n const newScale = startScale + (event.scale - 1)\n\n if (newScale < 1) {\n reader.zoom.exit()\n } else {\n reader.zoom.scaleAt(newScale)\n }\n }\n }),\n ),\n )\n }),\n )\n\n const watchForFontScaleChange$ = !fontScalePinchEnabled\n ? EMPTY\n : pinchStart$.pipe(\n withLatestFrom(reader.viewportState$),\n switchMap(([pinchStartEvent, viewportState]) => {\n if (viewportState === \"busy\" || shouldStartZoom(pinchStartEvent.event.target) || reader.zoom.isZooming)\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(fontScalePinchThrottleTime, animationFrameScheduler, {\n trailing: true,\n }),\n tap((event) => {\n reader.settings.update({\n fontScale: parseFloat((lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2)),\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$)\n }),\n )\n}\n","import { Reader } from \"@prose-reader/core\"\nimport { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({ reader, recognizer }: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(filter((event) => event.type === \"panStart\"))\n const panMove$ = recognizer.events$.pipe(filter((event) => event.type === \"panMove\"))\n\n const zoomingPan$ = panStart$.pipe(\n switchMap(() => {\n const startPosition = reader.zoom.currentPosition\n\n return panMove$.pipe(\n tap((panMoveEvent) => {\n if (reader.zoom.isZooming) {\n reader.zoom.moveAt({ x: startPosition.x + panMoveEvent.deltaX, y: startPosition.y + panMoveEvent.deltaY })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, Reader } from \"@prose-reader/core\"\nimport { ObservedValueOf, Subject, combineLatest, merge, takeUntil, tap } from \"rxjs\"\nimport { PanRecognizer, PinchRecognizer, Recognizable, SwipeRecognizer, TapRecognizer } from \"gesturx\"\nimport { EnhancerAPI, InputSettings, Hook } from \"./types\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(next: (options: InheritOptions) => InheritOutput) =>\n (\n options: InheritOptions & {\n gestures?: Partial<InputSettings>\n },\n ): InheritOutput & EnhancerAPI => {\n const { gestures = {}, ...rest } = options\n const reader = next(rest as InheritOptions)\n\n const settingsManager = new GesturesSettingsManager(gestures)\n\n const hookManager = new HookManager<Hook>()\n\n const pinchRecognizer = new PinchRecognizer({\n options: {\n /**\n * @important\n * To be less than pan otherwise it will not fail before it starts\n */\n posThreshold: 20,\n },\n })\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 30,\n },\n })\n\n const zoomPanRecognizer = new PanRecognizer({\n options: {\n posThreshold: 1,\n },\n })\n\n const tapRecognizer = new TapRecognizer({\n failWith: [panRecognizer],\n })\n\n const swipeRecognizer = new SwipeRecognizer()\n\n const recognizable = new Recognizable({\n recognizers: [tapRecognizer, panRecognizer, swipeRecognizer, pinchRecognizer, zoomPanRecognizer],\n })\n\n const unhandledEvent$ = new Subject<ObservedValueOf<typeof recognizable.events$>>()\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n unhandledEvent$,\n settingsManager,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n unhandledEvent$,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n unhandledEvent$,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n unhandledEvent$,\n })\n\n const zoomPanGestures$ = registerZoomPan({\n reader,\n recognizer: zoomPanRecognizer,\n })\n\n const containerUpdate$ = reader.context.containerElement$.pipe(\n tap((container) => {\n recognizable.update({\n container,\n })\n }),\n )\n\n const watchSettings$ = combineLatest([settingsManager.values$, panRecognizer.config$]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith = panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [...(panRecognizerConfig.failWith ?? []), pinchRecognizer],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter((recognizer) => recognizer !== pinchRecognizer),\n })\n }\n }),\n )\n\n merge(\n containerUpdate$,\n watchSettings$,\n zoomPanGestures$,\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n )\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n gestures: {\n settings: settingsManager,\n unhandledEvent$: unhandledEvent$.asObservable(),\n hookManager,\n },\n }\n }\n"],"names":["filter","isHtmlElement","tap","switchMap","EMPTY","SettingsManager","withLatestFrom","merge","event","throttleTime","animationFrameScheduler","takeUntil","HookManager","PinchRecognizer","PanRecognizer","TapRecognizer","SwipeRecognizer","Recognizable","Subject","combineLatest"],"mappings":";;;;AAGa,QAAA,gBAAgB,CAAwC,WACnE,OAAO;AAAA,IACLA,KAAA,OAAO,CAAC,UAAU;AACV,YAAA,SAAS,MAAM,MAAM;AAE3B,UAAIC,KAAAA,cAAc,MAAM,KAAK,OAAO,YAAY,IAAY,QAAA;AAErD,aAAA;AAAA,IAAA,CACR;AAAA,EACH;ACNK,QAAM,eAAe,CAAC;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAMM;AACE,UAAA,YAAY,aAAa,QAAQ;AAAA,MACrC;AAAA,MACAC,KAAA,IAAI,CAAC,UAAU;AACb,cAAM,kBAAkB,MAAM;AAC9B,cAAM,EAAE,0BAA8B,IAAA,OAAO,SAAS;AAElD,YAAA,MAAM,SAAS,OAAO;AACxB,gBAAM,QAAQ,OAAO;AACrB,gBAAM,SAAS,OAAO;AACtB,gBAAM,iBAAiB;AAEvB,cAAI,OAAO,iBAAiB;AAC1B,kBAAM,EAAE,IAAI,GAAG,EAAA,IAAM;AAErB,kBAAM,mBAAmB,YAAY,QAAQ,aAAa,QAAW,EAAE,OAAO;AAE9E,gBAAI,iBAAiB,KAAK,CAAC,WAAW,WAAW,KAAK,GAAG;AACvD;AAAA,YACF;AAEM,kBAAA,YAAY,IAAI,SAAS;AACzB,kBAAA,eAAe,IAAI,UAAU,IAAI;AACjC,kBAAA,aAAa,IAAI,QAAQ;AACzB,kBAAA,cAAc,IAAI,SAAS,IAAI;AAEjC,gBAAA,cAAc,8BAA8B,cAAc;AAC5D,qBAAO,WAAW;YAAc,WACvB,aAAa,8BAA8B,YAAY;AAChE,qBAAO,WAAW;YAAc,WACvB,gBAAgB,8BAA8B,YAAY;AACnE,qBAAO,WAAW;YAAkB,WAC3B,eAAe,8BAA8B,cAAc;AACpE,qBAAO,WAAW;YAAkB,OAC/B;AACL,8BAAgB,KAAK,KAAK;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAAA,MAAA,CACD;AAAA,IAAA;AAGI,WAAA;AAAA,EACT;ACtDA,QAAM,mBAAmB;AAElB,QAAM,cAAc,CAAC;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAMM;AACE,UAAA,YAAY,gBAAgB,QAAQ;AAAA,MACxCC,eAAU,CAAC,EAAE,oBAAoB;AAC3B,YAAA,kBAAkB,MAAc,QAAAC;AAEpC,eAAO,WAAW,QAAQ;AAAA,UACxBF,KAAA,IAAI,CAAC,UAAU;AACT,gBAAA,OAAO,KAAK,UAAW;AAEvB,gBAAA,MAAM,SAAS,YAAY;AAIzB,kBAAA,MAAM,QAAQ,iBAAkB;AAE5B,+CAAA,WAAW,OAAO,EAAE,GAAG,GAAG,GAAG,KAAK,EAAE,OAAO,KAAM;AAAA,YAC3D;AAEI,gBAAA,MAAM,SAAS,WAAW;AACpB,+CAAA,WAAW,OAAO,EAAE,GAAG,MAAM,QAAQ,GAAG,MAAM,OAAA;AAAA,YACxD;AAEI,gBAAA,MAAM,SAAS,UAAU;AAC3B,+CAAQ,WAAW,OAAO,EAAE,GAAG,MAAM,QAAQ,GAAG,MAAM,OAAO,GAAG,EAAE,OAAO,KAAM;AAAA,YACjF;AAAA,UAAA,CACD;AAAA,QAAA;AAAA,MACH,CACD;AAAA,IAAA;AAGI,WAAA;AAAA,EACT;AC5CO,QAAM,gBAAgB,CAAC;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAMM;AACE,UAAA,YAAY,gBAAgB,QAAQ;AAAA,MACxCC,KAAA;AAAA,QAAU,CAAC,EAAE,cAAc,MACzB,kBAAkB,UACdC,aACA,aAAa,QAAQ;AAAA,UACnBJ,KAAAA,OAAO,CAAC,UAAU,MAAM,SAAS,OAAO;AAAA,UACxCE,KAAA,IAAI,CAAC,UAAU;AACb,kBAAM,EAAE,0BAA8B,IAAA,OAAO,SAAS;AAEtD,gBAAI,8BAA8B,YAAY;AACxC,kBAAA,MAAM,YAAY,MAAM;AAC1B,iDAAQ,WAAW;AAAA,cACrB;AACI,kBAAA,MAAM,YAAY,KAAK;AACzB,iDAAQ,WAAW;AAAA,cACrB;AAAA,YAAA,OACK;AACD,kBAAA,MAAM,YAAY,MAAM;AAC1B,iDAAQ,WAAW;AAAA,cACrB;AACI,kBAAA,MAAM,YAAY,KAAK;AACzB,iDAAQ,WAAW;AAAA,cACrB;AAAA,YACF;AAAA,UAAA,CACD;AAAA,QACH;AAAA,MACN;AAAA,IAAA;AAGK,WAAA;AAAA,EACT;AAAA,EC3CO,MAAM,gCAAgCG,KAAAA,gBAA+C;AAAA,IAC1F,kBAAkB,eAA8C;AACvD,aAAA;AAAA,IACT;AAAA,IAEA,qBAAoC;AAC3B,aAAA;AAAA,QACL,eAAe;AAAA,QACf,uBAAuB;AAAA,QACvB,4BAA4B;AAAA,QAC5B,gBAAgB;AAAA,MAAA;AAAA,IAEpB;AAAA,EACF;ACCA,QAAM,qBAAqB,CAAC,WAC1BJ,KAAA,cAAc,MAAM,KACpB,CAAC,CAAC,OAAO,cAAc,eACvB,kBAAkB,OAAO,cAAc,YAAY;AAE9C,QAAM,gBAAgB,CAAC;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAMM;AACE,UAAA,cAAc,aAAa,QAAQ,KAAKD,KAAAA,OAAO,CAAC,UAA+B,MAAM,SAAS,YAAY,CAAC;AAE3G,UAAA,aAAa,aAAa,QAAQ,KAAKA,KAAAA,OAAO,CAAC,UAA+B,MAAM,SAAS,WAAW,CAAC;AAEzG,UAAA,YAAY,aAAa,QAAQ,KAAKA,KAAAA,OAAO,CAAC,UAA+B,MAAM,SAAS,UAAU,CAAC;AAEvG,UAAA,kBAAkB,CAAC,WACvB,mBAAmB,MAAM,KAAK,CAAC,OAAO,KAAK;AAE7C,WAAO,gBAAgB,QAAQ;AAAA,MAC7BG,KAAAA,UAAU,CAAC,EAAE,uBAAuB,iCAAiC;AACnE,cAAM,gBAAgB,YAAY;AAAA,UAChCG,KAAA,eAAe,OAAO,cAAc;AAAA,UACpCH,KAAAA,UAAU,CAAC,CAAC,OAAO,aAAa,MAAM;AAC9B,kBAAA,SAAS,MAAM,MAAM;AACrB,kBAAA,aAAa,OAAO,KAAK;AAE3B,gBAAA,kBAAkB,OAAe,QAAAC;AAEjC,gBAAA,gBAAgB,MAAM,GAAG;AACpB,qBAAA,KAAK,MAAM,MAAM;AAAA,YAC1B;AAEA,gBAAI,CAAC,OAAO,KAAK,UAAkB,QAAAA,KAAAA;AAE5B,mBAAAG,KAAA;AAAA,cACL,WAAW;AAAA,gBACTL,KAAA,IAAI,CAACM,WAAU;AACT,sBAAA,OAAO,KAAK,WAAW;AACnB,0BAAA,WAAW,cAAcA,OAAM,QAAQ;AAE7C,wBAAI,WAAW,GAAG;AAChB,6BAAO,KAAK;oBAAK,OACZ;AACE,6BAAA,KAAK,QAAQ,QAAQ;AAAA,oBAC9B;AAAA,kBACF;AAAA,gBAAA,CACD;AAAA,cACH;AAAA,YAAA;AAAA,UACF,CACD;AAAA,QAAA;AAGH,cAAM,2BAA2B,CAAC,wBAC9BJ,KAAA,QACA,YAAY;AAAA,UACVE,KAAA,eAAe,OAAO,cAAc;AAAA,UACpCH,KAAAA,UAAU,CAAC,CAAC,iBAAiB,aAAa,MAAM;AAC1C,gBAAA,kBAAkB,UAAU,gBAAgB,gBAAgB,MAAM,MAAM,KAAK,OAAO,KAAK;AACpF,qBAAAC;AAEH,kBAAA,4BAA4B,OAAO,SAAS,OAAO;AAEzD,mBAAO,WAAW;AAAA,cAChBK,KAAA,aAAa,4BAA4BC,8BAAyB;AAAA,gBAChE,UAAU;AAAA,cAAA,CACX;AAAA,cACDR,KAAA,IAAI,CAAC,UAAU;AACb,uBAAO,SAAS,OAAO;AAAA,kBACrB,WAAW,YAAY,6BAA6B,MAAM,QAAQ,IAAI,QAAQ,CAAC,CAAC;AAAA,gBAAA,CACjF;AAAA,cAAA,CACF;AAAA,cACDS,KAAAA,UAAU,SAAS;AAAA,YAAA;AAAA,UACrB,CACD;AAAA,QAAA;AAGA,eAAAJ,KAAA,MAAM,eAAe,wBAAwB;AAAA,MAAA,CACrD;AAAA,IAAA;AAAA,EAEL;ACnGO,QAAM,kBAAkB,CAAC,EAAE,QAAQ,iBAAgE;AAClG,UAAA,YAAY,WAAW,QAAQ,KAAKP,KAAAA,OAAO,CAAC,UAAU,MAAM,SAAS,UAAU,CAAC;AAChF,UAAA,WAAW,WAAW,QAAQ,KAAKA,KAAAA,OAAO,CAAC,UAAU,MAAM,SAAS,SAAS,CAAC;AAEpF,UAAM,cAAc,UAAU;AAAA,MAC5BG,KAAAA,UAAU,MAAM;AACR,cAAA,gBAAgB,OAAO,KAAK;AAElC,eAAO,SAAS;AAAA,UACdD,KAAA,IAAI,CAAC,iBAAiB;AAChB,gBAAA,OAAO,KAAK,WAAW;AACzB,qBAAO,KAAK,OAAO,EAAE,GAAG,cAAc,IAAI,aAAa,QAAQ,GAAG,cAAc,IAAI,aAAa,OAAQ,CAAA;AAAA,YAC3G;AAAA,UAAA,CACD;AAAA,QAAA;AAAA,MACH,CACD;AAAA,IAAA;AAGI,WAAA;AAAA,EACT;ACZO,QAAM,mBACX,CAA+C,SAC/C,CACE,YAGgC;AAChC,UAAM,EAAE,WAAW,CAAA,GAAI,GAAG,SAAS;AAC7B,UAAA,SAAS,KAAK,IAAsB;AAEpC,UAAA,kBAAkB,IAAI,wBAAwB,QAAQ;AAEtD,UAAA,cAAc,IAAIU,KAAAA;AAElB,UAAA,kBAAkB,IAAIC,wBAAgB;AAAA,MAC1C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,QAKP,cAAc;AAAA,MAChB;AAAA,IAAA,CACD;AAEK,UAAA,gBAAgB,IAAIC,sBAAc;AAAA,MACtC,UAAU,CAAC,eAAe;AAAA,MAC1B,SAAS;AAAA;AAAA,QAEP,cAAc;AAAA,MAChB;AAAA,IAAA,CACD;AAEK,UAAA,oBAAoB,IAAIA,sBAAc;AAAA,MAC1C,SAAS;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,IAAA,CACD;AAEK,UAAA,gBAAgB,IAAIC,sBAAc;AAAA,MACtC,UAAU,CAAC,aAAa;AAAA,IAAA,CACzB;AAEK,UAAA,kBAAkB,IAAIC,QAAAA;AAEtB,UAAA,eAAe,IAAIC,qBAAa;AAAA,MACpC,aAAa,CAAC,eAAe,eAAe,iBAAiB,iBAAiB,iBAAiB;AAAA,IAAA,CAChG;AAEK,UAAA,kBAAkB,IAAIC,KAAAA;AAE5B,UAAM,eAAe,aAAa;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAED,UAAM,eAAe,YAAY;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,IAAA,CACD;AAED,UAAM,iBAAiB,cAAc;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAED,UAAM,iBAAiB,cAAc;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAED,UAAM,mBAAmB,gBAAgB;AAAA,MACvC;AAAA,MACA,YAAY;AAAA,IAAA,CACb;AAEK,UAAA,mBAAmB,OAAO,QAAQ,kBAAkB;AAAA,MACxDhB,KAAA,IAAI,CAAC,cAAc;AACjB,qBAAa,OAAO;AAAA,UAClB;AAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA;AAGG,UAAA,iBAAiBiB,mBAAc,CAAC,gBAAgB,SAAS,cAAc,OAAO,CAAC,EAAE;AAAA,MACrFjB,KAAAA,IAAI,CAAC,CAAC,EAAE,eAAe,GAAG,mBAAmB,MAAM;;AACjD,cAAM,0BAAyB,yBAAoB,aAApB,mBAA8B,SAAS;AAElE,YAAA,kBAAkB,CAAC,wBAAwB;AAC7C,wBAAc,OAAO;AAAA,YACnB,UAAU,CAAC,GAAI,oBAAoB,YAAY,CAAA,GAAK,eAAe;AAAA,UAAA,CACpE;AAAA,QACH;AAEI,YAAA,CAAC,kBAAkB,wBAAwB;AAC7C,wBAAc,OAAO;AAAA,YACnB,WAAU,yBAAoB,aAApB,mBAA8B,OAAO,CAAC,eAAe,eAAe;AAAA,UAAe,CAC9F;AAAA,QACH;AAAA,MAAA,CACD;AAAA,IAAA;AAGHK,SAAA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,EAEC,KAAKI,KAAAA,UAAU,OAAO,EAAE,QAAQ,CAAC,EACjC;AAEI,WAAA;AAAA,MACL,GAAG;AAAA,MACH,UAAU;AAAA,QACR,UAAU;AAAA,QACV,iBAAiB,gBAAgB,aAAa;AAAA,QAC9C;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;;;;"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Observable, ObservedValueOf } from 'rxjs';
|
|
2
|
+
import { PanRecognizer, PinchRecognizer, Recognizable, SwipeRecognizer, TapRecognizer, TapEvent } from 'gesturx';
|
|
3
|
+
import { HookManager } from '../../core/dist/hooks/HookManager';
|
|
4
|
+
import { GesturesSettingsManager } from './SettingsManager';
|
|
5
|
+
export type Hook = {
|
|
6
|
+
name: "beforeTap";
|
|
7
|
+
runFn: (params: {
|
|
8
|
+
event: TapEvent;
|
|
9
|
+
}) => boolean;
|
|
10
|
+
};
|
|
11
|
+
export type GestureRecognizable = Recognizable<(TapRecognizer | PanRecognizer | SwipeRecognizer | PinchRecognizer)[]>;
|
|
12
|
+
export type GestureEvent = ObservedValueOf<GestureRecognizable["events$"]>;
|
|
13
|
+
export type InputSettings = {
|
|
14
|
+
panNavigation: "pan" | "swipe" | false;
|
|
15
|
+
fontScalePinchEnabled: boolean;
|
|
16
|
+
fontScalePinchThrottleTime: number;
|
|
17
|
+
pinchCancelPan: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type OutputSettings = InputSettings;
|
|
20
|
+
export type EnhancerAPI = {
|
|
21
|
+
gestures: {
|
|
22
|
+
settings: GesturesSettingsManager;
|
|
23
|
+
unhandledEvent$: Observable<GestureEvent>;
|
|
24
|
+
hookManager: HookManager<Hook>;
|
|
25
|
+
};
|
|
26
|
+
};
|
package/dist/utils.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prose-reader/enhancer-gestures",
|
|
3
|
+
"version": "1.81.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"private": false,
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public",
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.umd.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"/dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"start": "vite build --watch --mode development",
|
|
24
|
+
"build": "tsc && vite build",
|
|
25
|
+
"lint:read": "prettier --check . && eslint . --ext .ts,.tsx,.js,.jsx",
|
|
26
|
+
"lint:write": "prettier --write . && eslint --fix . --ext .ts,.tsx,.js,.jsx",
|
|
27
|
+
"test": "vitest run --coverage"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@prose-reader/core": "^1.81.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"gesturx": "^1.8.2"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"gesturx": "*",
|
|
37
|
+
"rxjs": "*"
|
|
38
|
+
},
|
|
39
|
+
"gitHead": "5eacda3e3f1e62ead3edb1d925d82a286d62b9a6"
|
|
40
|
+
}
|