@prose-reader/enhancer-gestures 1.228.0 → 1.229.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/dist/index.js CHANGED
@@ -196,6 +196,24 @@ const istMatchingSelectors = (selectors, event) => {
196
196
  });
197
197
  return !!match;
198
198
  };
199
+ const getPositionRelativeToContainer = (event, containerElementRect) => {
200
+ const { x, y } = event;
201
+ const { left, top } = containerElementRect;
202
+ return {
203
+ x: x - left,
204
+ y: y - top
205
+ };
206
+ };
207
+ const calculatePageTurnMargin = (screenWidth) => {
208
+ const minMargin = 0.15;
209
+ const maxMargin = 0.3;
210
+ const minWidth = 400;
211
+ const maxWidth = 1200;
212
+ if (screenWidth <= minWidth) return maxMargin;
213
+ if (screenWidth >= maxWidth) return minMargin;
214
+ const ratio = (screenWidth - minWidth) / (maxWidth - minWidth);
215
+ return maxMargin - ratio * (maxMargin - minMargin);
216
+ };
199
217
  const registerTaps = ({
200
218
  reader,
201
219
  recognizable,
@@ -205,15 +223,20 @@ const registerTaps = ({
205
223
  }) => {
206
224
  const gestures$ = recognizable.events$.pipe(
207
225
  filter((event) => event.recognizer === recognizer),
208
- switchMap(({ event }) => {
226
+ withLatestFrom(reader.context.containerElementRect$),
227
+ switchMap(([{ event }, containerElementRect]) => {
228
+ if (!containerElementRect) return EMPTY;
209
229
  const normalizedEvent = event.event;
210
230
  const { computedPageTurnDirection } = reader.settings.values;
211
231
  if (event.type === "tap" && isNotLink(event) && !istMatchingSelectors(settingsManager.values.ignore, event)) {
212
- const width = window.innerWidth;
213
- const height = window.innerHeight;
214
- const pageTurnMargin = 0.15;
215
232
  if (`x` in normalizedEvent) {
216
- const { x = 0, y } = normalizedEvent;
233
+ const width = containerElementRect.width;
234
+ const height = containerElementRect.height;
235
+ const pageTurnMargin = calculatePageTurnMargin(width);
236
+ const { x, y } = getPositionRelativeToContainer(
237
+ normalizedEvent,
238
+ containerElementRect
239
+ );
217
240
  const beforeTapResults$ = hookManager.execute(
218
241
  "beforeGesture",
219
242
  void 0,
@@ -347,7 +370,7 @@ const gesturesEnhancer = (next) => (options) => {
347
370
  reader,
348
371
  recognizer: zoomPanRecognizer
349
372
  });
350
- const containerUpdate$ = reader.context.containerElement$.pipe(
373
+ const containerUpdate$ = reader.context.watch(`rootElement`).pipe(
351
374
  tap((container) => {
352
375
  recognizable.update({
353
376
  container
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/SettingsManager.ts","../src/gestures/pan.ts","../src/gestures/pinch.ts","../src/gestures/swipe.ts","../src/utils.ts","../src/gestures/taps.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { type Reader, SettingsManager } from \"@prose-reader/core\"\nimport type { InputSettings, OutputSettings } from \"./types\"\nimport { takeUntil, tap } from \"rxjs\"\n\nexport class GesturesSettingsManager extends SettingsManager<\n InputSettings,\n OutputSettings\n> {\n constructor(\n initialSettings: Partial<InputSettings>,\n private reader: Reader,\n ) {\n super(initialSettings)\n\n /**\n * Since we have settings that may be locked due to some reader settings\n * we need to update as soon as they update as well.\n */\n reader.settings.values$\n .pipe(\n tap(() => {\n this.update({})\n }),\n takeUntil(this.destroy$),\n )\n .subscribe()\n }\n\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return {\n ...inputSettings,\n panNavigation:\n this.reader.settings.values.computedPageTurnMode === `scrollable`\n ? false\n : inputSettings.panNavigation,\n }\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n pinchCancelPan: true,\n fontScalePinchEnabled: true,\n fontScalePinchThrottleTime: 500,\n fontScaleMaxScale: 5,\n fontScaleMinScale: 0.2,\n ignore: [],\n }\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, map, switchMap, tap } from \"rxjs\"\nimport type { Hook } from \"../types\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { 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 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(\n { x: event.deltaX, y: event.deltaY },\n { final: true },\n )\n }\n }),\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n\n return gestures$\n}\n","import {\n type HookManager,\n type Reader,\n isHtmlElement,\n} from \"@prose-reader/core\"\nimport type { PinchEvent } from \"gesturx\"\nimport {\n EMPTY,\n animationFrameScheduler,\n filter,\n map,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nconst isHtmlImageElement = (\n target: EventTarget | null,\n): 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 settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchStart\"),\n )\n\n const pinchMove$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchMove\"),\n )\n\n const pinchEnd$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchEnd\"),\n )\n\n const shouldStartZoom = (\n target: EventTarget | null,\n ): 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 (\n viewportState === \"busy\" ||\n shouldStartZoom(pinchStartEvent.event.target) ||\n reader.zoom.isZooming\n )\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(\n fontScalePinchThrottleTime,\n animationFrameScheduler,\n {\n trailing: true,\n },\n ),\n tap((event) => {\n const newScale = Number.parseFloat(\n (lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2),\n )\n\n const newMinMaxedFontScale = Math.max(\n Math.min(\n newScale,\n settingsManager.values.fontScaleMaxScale,\n ),\n settingsManager.values.fontScaleMinScale,\n )\n\n reader.settings.update({\n fontScale: newMinMaxedFontScale,\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$).pipe(\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, filter, map, switchMap, tap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\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 map(({ event }) => ({ event, handled: true })),\n ),\n ),\n )\n\n return gestures$\n}\n","import { isHtmlElement } from \"@prose-reader/core\"\nimport type { GestureEvent } from \"./types\"\n\nexport const isNotLink = (event: GestureEvent[\"event\"]) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n}\n\nexport const istMatchingSelectors = (\n selectors: string[],\n event: GestureEvent[\"event\"],\n): boolean => {\n const target = event.event.target\n\n if (!isHtmlElement(target)) return false\n\n const match = selectors.find((selector) => {\n // Check if the target matches the selector directly\n if (target.matches(selector)) return true\n\n // Check if the target is within an element matching the selector\n if (target.closest(selector)) return true\n\n return false\n })\n\n return !!match\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport type { TapRecognizer } from \"gesturx\"\nimport { EMPTY, combineLatest, filter, first, map, of, switchMap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\nimport { isNotLink, istMatchingSelectors } from \"../utils\"\n\nexport const registerTaps = ({\n reader,\n recognizable,\n hookManager,\n settingsManager,\n recognizer,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n recognizer: TapRecognizer\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filter((event) => event.recognizer === recognizer),\n switchMap(({ event }) => {\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (\n event.type === \"tap\" &&\n isNotLink(event) &&\n !istMatchingSelectors(settingsManager.values.ignore, event)\n ) {\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(\n \"beforeGesture\",\n undefined,\n { event$: of(event) },\n )\n\n return combineLatest([...beforeTapResults$, of(true)]).pipe(\n first(),\n filter((results) => !results.some((result) => result === false)),\n map(() => {\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 (\n isTopArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnLeftOrTop()\n } else if (\n isBottomArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else if (\n isRightArea &&\n computedPageTurnDirection === \"horizontal\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else {\n return { event, handled: false }\n }\n\n return { event, handled: true }\n }),\n )\n }\n }\n\n return EMPTY\n }),\n )\n\n return gestures$\n}\n","import type { Reader } from \"@prose-reader/core\"\nimport type { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({\n reader,\n recognizer,\n}: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panStart\"),\n )\n const panMove$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panMove\"),\n )\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({\n x: startPosition.x + panMoveEvent.deltaX,\n y: startPosition.y + panMoveEvent.deltaY,\n })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, type Reader } from \"@prose-reader/core\"\nimport {\n PanRecognizer,\n PinchRecognizer,\n Recognizable,\n SwipeRecognizer,\n TapRecognizer,\n} from \"gesturx\"\nimport { combineLatest, merge, share, takeUntil, tap } from \"rxjs\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\nimport type { EnhancerAPI, Hook, InputSettings } from \"./types\"\n\nexport * from \"./types\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\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, reader)\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 failWithSelection = {\n start$: reader.selection.selectionStart$,\n end$: reader.selection.selectionEnd$,\n }\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer, failWithSelection],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 15,\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 failWith: [failWithSelection],\n })\n\n const recognizable = new Recognizable({\n recognizers: [\n tapRecognizer,\n panRecognizer,\n swipeRecognizer,\n pinchRecognizer,\n zoomPanRecognizer,\n ],\n disableTextSelection: false,\n })\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n recognizer: tapRecognizer,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\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([\n settingsManager.values$,\n panRecognizer.config$,\n ]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith =\n panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [\n ...(panRecognizerConfig.failWith ?? []),\n pinchRecognizer,\n ],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter(\n (recognizer) => recognizer !== pinchRecognizer,\n ),\n })\n }\n }),\n )\n\n const gestures$ = merge(\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n ).pipe(share())\n\n merge(containerUpdate$, watchSettings$, zoomPanGestures$, gestures$)\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n destroy: () => {\n reader.destroy()\n settingsManager.destroy()\n },\n gestures: {\n settings: settingsManager,\n gestures$,\n hooks: hookManager,\n },\n }\n }\n"],"names":["event"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/SettingsManager.ts","../src/gestures/pan.ts","../src/gestures/pinch.ts","../src/gestures/swipe.ts","../src/utils.ts","../src/gestures/taps.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { type Reader, SettingsManager } from \"@prose-reader/core\"\nimport type { InputSettings, OutputSettings } from \"./types\"\nimport { takeUntil, tap } from \"rxjs\"\n\nexport class GesturesSettingsManager extends SettingsManager<\n InputSettings,\n OutputSettings\n> {\n constructor(\n initialSettings: Partial<InputSettings>,\n private reader: Reader,\n ) {\n super(initialSettings)\n\n /**\n * Since we have settings that may be locked due to some reader settings\n * we need to update as soon as they update as well.\n */\n reader.settings.values$\n .pipe(\n tap(() => {\n this.update({})\n }),\n takeUntil(this.destroy$),\n )\n .subscribe()\n }\n\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return {\n ...inputSettings,\n panNavigation:\n this.reader.settings.values.computedPageTurnMode === `scrollable`\n ? false\n : inputSettings.panNavigation,\n }\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n pinchCancelPan: true,\n fontScalePinchEnabled: true,\n fontScalePinchThrottleTime: 500,\n fontScaleMaxScale: 5,\n fontScaleMinScale: 0.2,\n ignore: [],\n }\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, map, switchMap, tap } from \"rxjs\"\nimport type { Hook } from \"../types\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { 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 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(\n { x: event.deltaX, y: event.deltaY },\n { final: true },\n )\n }\n }),\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n\n return gestures$\n}\n","import {\n type HookManager,\n type Reader,\n isHtmlElement,\n} from \"@prose-reader/core\"\nimport type { PinchEvent } from \"gesturx\"\nimport {\n EMPTY,\n animationFrameScheduler,\n filter,\n map,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nconst isHtmlImageElement = (\n target: EventTarget | null,\n): 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 settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchStart\"),\n )\n\n const pinchMove$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchMove\"),\n )\n\n const pinchEnd$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchEnd\"),\n )\n\n const shouldStartZoom = (\n target: EventTarget | null,\n ): 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 (\n viewportState === \"busy\" ||\n shouldStartZoom(pinchStartEvent.event.target) ||\n reader.zoom.isZooming\n )\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(\n fontScalePinchThrottleTime,\n animationFrameScheduler,\n {\n trailing: true,\n },\n ),\n tap((event) => {\n const newScale = Number.parseFloat(\n (lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2),\n )\n\n const newMinMaxedFontScale = Math.max(\n Math.min(\n newScale,\n settingsManager.values.fontScaleMaxScale,\n ),\n settingsManager.values.fontScaleMinScale,\n )\n\n reader.settings.update({\n fontScale: newMinMaxedFontScale,\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$).pipe(\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, filter, map, switchMap, tap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\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 map(({ event }) => ({ event, handled: true })),\n ),\n ),\n )\n\n return gestures$\n}\n","import { isHtmlElement } from \"@prose-reader/core\"\nimport type { GestureEvent } from \"./types\"\n\nexport const isNotLink = (event: GestureEvent[\"event\"]) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n}\n\nexport const istMatchingSelectors = (\n selectors: string[],\n event: GestureEvent[\"event\"],\n): boolean => {\n const target = event.event.target\n\n if (!isHtmlElement(target)) return false\n\n const match = selectors.find((selector) => {\n // Check if the target matches the selector directly\n if (target.matches(selector)) return true\n\n // Check if the target is within an element matching the selector\n if (target.closest(selector)) return true\n\n return false\n })\n\n return !!match\n}\n\nexport const getPositionRelativeToContainer = (\n event: PointerEvent,\n containerElementRect: DOMRectReadOnly,\n) => {\n const { x, y } = event\n const { left, top } = containerElementRect\n\n return {\n x: x - left,\n y: y - top,\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport type { TapRecognizer } from \"gesturx\"\nimport {\n EMPTY,\n combineLatest,\n filter,\n first,\n map,\n of,\n switchMap,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\nimport {\n getPositionRelativeToContainer,\n isNotLink,\n istMatchingSelectors,\n} from \"../utils\"\n\nconst calculatePageTurnMargin = (screenWidth: number): number => {\n const minMargin = 0.15\n const maxMargin = 0.3\n const minWidth = 400\n const maxWidth = 1200\n\n if (screenWidth <= minWidth) return maxMargin\n if (screenWidth >= maxWidth) return minMargin\n\n // Linear interpolation between min and max\n const ratio = (screenWidth - minWidth) / (maxWidth - minWidth)\n return maxMargin - ratio * (maxMargin - minMargin)\n}\n\nexport const registerTaps = ({\n reader,\n recognizable,\n hookManager,\n settingsManager,\n recognizer,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n recognizer: TapRecognizer\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filter((event) => event.recognizer === recognizer),\n withLatestFrom(reader.context.containerElementRect$),\n switchMap(([{ event }, containerElementRect]) => {\n if (!containerElementRect) return EMPTY\n\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (\n event.type === \"tap\" &&\n isNotLink(event) &&\n !istMatchingSelectors(settingsManager.values.ignore, event)\n ) {\n if (`x` in normalizedEvent) {\n const width = containerElementRect.width\n const height = containerElementRect.height\n const pageTurnMargin = calculatePageTurnMargin(width)\n const { x, y } = getPositionRelativeToContainer(\n normalizedEvent,\n containerElementRect,\n )\n\n const beforeTapResults$ = hookManager.execute(\n \"beforeGesture\",\n undefined,\n { event$: of(event) },\n )\n\n return combineLatest([...beforeTapResults$, of(true)]).pipe(\n first(),\n filter((results) => !results.some((result) => result === false)),\n map(() => {\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 (\n isTopArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnLeftOrTop()\n } else if (\n isBottomArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else if (\n isRightArea &&\n computedPageTurnDirection === \"horizontal\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else {\n return { event, handled: false }\n }\n\n return { event, handled: true }\n }),\n )\n }\n }\n\n return EMPTY\n }),\n )\n\n return gestures$\n}\n","import type { Reader } from \"@prose-reader/core\"\nimport type { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({\n reader,\n recognizer,\n}: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panStart\"),\n )\n const panMove$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panMove\"),\n )\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({\n x: startPosition.x + panMoveEvent.deltaX,\n y: startPosition.y + panMoveEvent.deltaY,\n })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, type Reader } from \"@prose-reader/core\"\nimport {\n PanRecognizer,\n PinchRecognizer,\n Recognizable,\n SwipeRecognizer,\n TapRecognizer,\n} from \"gesturx\"\nimport { combineLatest, merge, share, takeUntil, tap } from \"rxjs\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\nimport type { EnhancerAPI, Hook, InputSettings } from \"./types\"\n\nexport * from \"./types\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\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, reader)\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 failWithSelection = {\n start$: reader.selection.selectionStart$,\n end$: reader.selection.selectionEnd$,\n }\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer, failWithSelection],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 15,\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 failWith: [failWithSelection],\n })\n\n const recognizable = new Recognizable({\n recognizers: [\n tapRecognizer,\n panRecognizer,\n swipeRecognizer,\n pinchRecognizer,\n zoomPanRecognizer,\n ],\n disableTextSelection: false,\n })\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n recognizer: tapRecognizer,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const zoomPanGestures$ = registerZoomPan({\n reader,\n recognizer: zoomPanRecognizer,\n })\n\n const containerUpdate$ = reader.context.watch(`rootElement`).pipe(\n tap((container) => {\n recognizable.update({\n container,\n })\n }),\n )\n\n const watchSettings$ = combineLatest([\n settingsManager.values$,\n panRecognizer.config$,\n ]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith =\n panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [\n ...(panRecognizerConfig.failWith ?? []),\n pinchRecognizer,\n ],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter(\n (recognizer) => recognizer !== pinchRecognizer,\n ),\n })\n }\n }),\n )\n\n const gestures$ = merge(\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n ).pipe(share())\n\n merge(containerUpdate$, watchSettings$, zoomPanGestures$, gestures$)\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n destroy: () => {\n reader.destroy()\n settingsManager.destroy()\n },\n gestures: {\n settings: settingsManager,\n gestures$,\n hooks: hookManager,\n },\n }\n }\n"],"names":["event"],"mappings":"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"}
@@ -197,6 +197,24 @@
197
197
  });
198
198
  return !!match;
199
199
  };
200
+ const getPositionRelativeToContainer = (event, containerElementRect) => {
201
+ const { x, y } = event;
202
+ const { left, top } = containerElementRect;
203
+ return {
204
+ x: x - left,
205
+ y: y - top
206
+ };
207
+ };
208
+ const calculatePageTurnMargin = (screenWidth) => {
209
+ const minMargin = 0.15;
210
+ const maxMargin = 0.3;
211
+ const minWidth = 400;
212
+ const maxWidth = 1200;
213
+ if (screenWidth <= minWidth) return maxMargin;
214
+ if (screenWidth >= maxWidth) return minMargin;
215
+ const ratio = (screenWidth - minWidth) / (maxWidth - minWidth);
216
+ return maxMargin - ratio * (maxMargin - minMargin);
217
+ };
200
218
  const registerTaps = ({
201
219
  reader,
202
220
  recognizable,
@@ -206,15 +224,20 @@
206
224
  }) => {
207
225
  const gestures$ = recognizable.events$.pipe(
208
226
  rxjs.filter((event) => event.recognizer === recognizer),
209
- rxjs.switchMap(({ event }) => {
227
+ rxjs.withLatestFrom(reader.context.containerElementRect$),
228
+ rxjs.switchMap(([{ event }, containerElementRect]) => {
229
+ if (!containerElementRect) return rxjs.EMPTY;
210
230
  const normalizedEvent = event.event;
211
231
  const { computedPageTurnDirection } = reader.settings.values;
212
232
  if (event.type === "tap" && isNotLink(event) && !istMatchingSelectors(settingsManager.values.ignore, event)) {
213
- const width = window.innerWidth;
214
- const height = window.innerHeight;
215
- const pageTurnMargin = 0.15;
216
233
  if (`x` in normalizedEvent) {
217
- const { x = 0, y } = normalizedEvent;
234
+ const width = containerElementRect.width;
235
+ const height = containerElementRect.height;
236
+ const pageTurnMargin = calculatePageTurnMargin(width);
237
+ const { x, y } = getPositionRelativeToContainer(
238
+ normalizedEvent,
239
+ containerElementRect
240
+ );
218
241
  const beforeTapResults$ = hookManager.execute(
219
242
  "beforeGesture",
220
243
  void 0,
@@ -348,7 +371,7 @@
348
371
  reader,
349
372
  recognizer: zoomPanRecognizer
350
373
  });
351
- const containerUpdate$ = reader.context.containerElement$.pipe(
374
+ const containerUpdate$ = reader.context.watch(`rootElement`).pipe(
352
375
  rxjs.tap((container) => {
353
376
  recognizable.update({
354
377
  container
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.cjs","sources":["../src/SettingsManager.ts","../src/gestures/pan.ts","../src/gestures/pinch.ts","../src/gestures/swipe.ts","../src/utils.ts","../src/gestures/taps.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { type Reader, SettingsManager } from \"@prose-reader/core\"\nimport type { InputSettings, OutputSettings } from \"./types\"\nimport { takeUntil, tap } from \"rxjs\"\n\nexport class GesturesSettingsManager extends SettingsManager<\n InputSettings,\n OutputSettings\n> {\n constructor(\n initialSettings: Partial<InputSettings>,\n private reader: Reader,\n ) {\n super(initialSettings)\n\n /**\n * Since we have settings that may be locked due to some reader settings\n * we need to update as soon as they update as well.\n */\n reader.settings.values$\n .pipe(\n tap(() => {\n this.update({})\n }),\n takeUntil(this.destroy$),\n )\n .subscribe()\n }\n\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return {\n ...inputSettings,\n panNavigation:\n this.reader.settings.values.computedPageTurnMode === `scrollable`\n ? false\n : inputSettings.panNavigation,\n }\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n pinchCancelPan: true,\n fontScalePinchEnabled: true,\n fontScalePinchThrottleTime: 500,\n fontScaleMaxScale: 5,\n fontScaleMinScale: 0.2,\n ignore: [],\n }\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, map, switchMap, tap } from \"rxjs\"\nimport type { Hook } from \"../types\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { 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 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(\n { x: event.deltaX, y: event.deltaY },\n { final: true },\n )\n }\n }),\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n\n return gestures$\n}\n","import {\n type HookManager,\n type Reader,\n isHtmlElement,\n} from \"@prose-reader/core\"\nimport type { PinchEvent } from \"gesturx\"\nimport {\n EMPTY,\n animationFrameScheduler,\n filter,\n map,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nconst isHtmlImageElement = (\n target: EventTarget | null,\n): 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 settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchStart\"),\n )\n\n const pinchMove$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchMove\"),\n )\n\n const pinchEnd$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchEnd\"),\n )\n\n const shouldStartZoom = (\n target: EventTarget | null,\n ): 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 (\n viewportState === \"busy\" ||\n shouldStartZoom(pinchStartEvent.event.target) ||\n reader.zoom.isZooming\n )\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(\n fontScalePinchThrottleTime,\n animationFrameScheduler,\n {\n trailing: true,\n },\n ),\n tap((event) => {\n const newScale = Number.parseFloat(\n (lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2),\n )\n\n const newMinMaxedFontScale = Math.max(\n Math.min(\n newScale,\n settingsManager.values.fontScaleMaxScale,\n ),\n settingsManager.values.fontScaleMinScale,\n )\n\n reader.settings.update({\n fontScale: newMinMaxedFontScale,\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$).pipe(\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, filter, map, switchMap, tap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\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 map(({ event }) => ({ event, handled: true })),\n ),\n ),\n )\n\n return gestures$\n}\n","import { isHtmlElement } from \"@prose-reader/core\"\nimport type { GestureEvent } from \"./types\"\n\nexport const isNotLink = (event: GestureEvent[\"event\"]) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n}\n\nexport const istMatchingSelectors = (\n selectors: string[],\n event: GestureEvent[\"event\"],\n): boolean => {\n const target = event.event.target\n\n if (!isHtmlElement(target)) return false\n\n const match = selectors.find((selector) => {\n // Check if the target matches the selector directly\n if (target.matches(selector)) return true\n\n // Check if the target is within an element matching the selector\n if (target.closest(selector)) return true\n\n return false\n })\n\n return !!match\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport type { TapRecognizer } from \"gesturx\"\nimport { EMPTY, combineLatest, filter, first, map, of, switchMap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\nimport { isNotLink, istMatchingSelectors } from \"../utils\"\n\nexport const registerTaps = ({\n reader,\n recognizable,\n hookManager,\n settingsManager,\n recognizer,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n recognizer: TapRecognizer\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filter((event) => event.recognizer === recognizer),\n switchMap(({ event }) => {\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (\n event.type === \"tap\" &&\n isNotLink(event) &&\n !istMatchingSelectors(settingsManager.values.ignore, event)\n ) {\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(\n \"beforeGesture\",\n undefined,\n { event$: of(event) },\n )\n\n return combineLatest([...beforeTapResults$, of(true)]).pipe(\n first(),\n filter((results) => !results.some((result) => result === false)),\n map(() => {\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 (\n isTopArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnLeftOrTop()\n } else if (\n isBottomArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else if (\n isRightArea &&\n computedPageTurnDirection === \"horizontal\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else {\n return { event, handled: false }\n }\n\n return { event, handled: true }\n }),\n )\n }\n }\n\n return EMPTY\n }),\n )\n\n return gestures$\n}\n","import type { Reader } from \"@prose-reader/core\"\nimport type { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({\n reader,\n recognizer,\n}: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panStart\"),\n )\n const panMove$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panMove\"),\n )\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({\n x: startPosition.x + panMoveEvent.deltaX,\n y: startPosition.y + panMoveEvent.deltaY,\n })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, type Reader } from \"@prose-reader/core\"\nimport {\n PanRecognizer,\n PinchRecognizer,\n Recognizable,\n SwipeRecognizer,\n TapRecognizer,\n} from \"gesturx\"\nimport { combineLatest, merge, share, takeUntil, tap } from \"rxjs\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\nimport type { EnhancerAPI, Hook, InputSettings } from \"./types\"\n\nexport * from \"./types\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\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, reader)\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 failWithSelection = {\n start$: reader.selection.selectionStart$,\n end$: reader.selection.selectionEnd$,\n }\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer, failWithSelection],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 15,\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 failWith: [failWithSelection],\n })\n\n const recognizable = new Recognizable({\n recognizers: [\n tapRecognizer,\n panRecognizer,\n swipeRecognizer,\n pinchRecognizer,\n zoomPanRecognizer,\n ],\n disableTextSelection: false,\n })\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n recognizer: tapRecognizer,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\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([\n settingsManager.values$,\n panRecognizer.config$,\n ]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith =\n panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [\n ...(panRecognizerConfig.failWith ?? []),\n pinchRecognizer,\n ],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter(\n (recognizer) => recognizer !== pinchRecognizer,\n ),\n })\n }\n }),\n )\n\n const gestures$ = merge(\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n ).pipe(share())\n\n merge(containerUpdate$, watchSettings$, zoomPanGestures$, gestures$)\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n destroy: () => {\n reader.destroy()\n settingsManager.destroy()\n },\n gestures: {\n settings: settingsManager,\n gestures$,\n hooks: hookManager,\n },\n }\n }\n"],"names":["SettingsManager","tap","takeUntil","switchMap","EMPTY","map","isHtmlElement","filter","withLatestFrom","merge","event","throttleTime","animationFrameScheduler","of","combineLatest","first","HookManager","PinchRecognizer","PanRecognizer","TapRecognizer","SwipeRecognizer","Recognizable","share"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.cjs","sources":["../src/SettingsManager.ts","../src/gestures/pan.ts","../src/gestures/pinch.ts","../src/gestures/swipe.ts","../src/utils.ts","../src/gestures/taps.ts","../src/gestures/zoomPan.ts","../src/index.ts"],"sourcesContent":["import { type Reader, SettingsManager } from \"@prose-reader/core\"\nimport type { InputSettings, OutputSettings } from \"./types\"\nimport { takeUntil, tap } from \"rxjs\"\n\nexport class GesturesSettingsManager extends SettingsManager<\n InputSettings,\n OutputSettings\n> {\n constructor(\n initialSettings: Partial<InputSettings>,\n private reader: Reader,\n ) {\n super(initialSettings)\n\n /**\n * Since we have settings that may be locked due to some reader settings\n * we need to update as soon as they update as well.\n */\n reader.settings.values$\n .pipe(\n tap(() => {\n this.update({})\n }),\n takeUntil(this.destroy$),\n )\n .subscribe()\n }\n\n getOutputSettings(inputSettings: InputSettings): OutputSettings {\n return {\n ...inputSettings,\n panNavigation:\n this.reader.settings.values.computedPageTurnMode === `scrollable`\n ? false\n : inputSettings.panNavigation,\n }\n }\n\n getDefaultSettings(): InputSettings {\n return {\n panNavigation: \"pan\",\n pinchCancelPan: true,\n fontScalePinchEnabled: true,\n fontScalePinchThrottleTime: 500,\n fontScaleMaxScale: 5,\n fontScaleMinScale: 0.2,\n ignore: [],\n }\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, map, switchMap, tap } from \"rxjs\"\nimport type { Hook } from \"../types\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { 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 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(\n { x: event.deltaX, y: event.deltaY },\n { final: true },\n )\n }\n }),\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n\n return gestures$\n}\n","import {\n type HookManager,\n type Reader,\n isHtmlElement,\n} from \"@prose-reader/core\"\nimport type { PinchEvent } from \"gesturx\"\nimport {\n EMPTY,\n animationFrameScheduler,\n filter,\n map,\n merge,\n switchMap,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nconst isHtmlImageElement = (\n target: EventTarget | null,\n): 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 settingsManager: GesturesSettingsManager\n}) => {\n const pinchStart$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchStart\"),\n )\n\n const pinchMove$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchMove\"),\n )\n\n const pinchEnd$ = recognizable.events$.pipe(\n map(({ event }) => event),\n filter((event): event is PinchEvent => event.type === \"pinchEnd\"),\n )\n\n const shouldStartZoom = (\n target: EventTarget | null,\n ): 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 (\n viewportState === \"busy\" ||\n shouldStartZoom(pinchStartEvent.event.target) ||\n reader.zoom.isZooming\n )\n return EMPTY\n\n const lastFontScaleOnPinchStart = reader.settings.values.fontScale\n\n return pinchMove$.pipe(\n throttleTime(\n fontScalePinchThrottleTime,\n animationFrameScheduler,\n {\n trailing: true,\n },\n ),\n tap((event) => {\n const newScale = Number.parseFloat(\n (lastFontScaleOnPinchStart + (event.scale - 1)).toFixed(2),\n )\n\n const newMinMaxedFontScale = Math.max(\n Math.min(\n newScale,\n settingsManager.values.fontScaleMaxScale,\n ),\n settingsManager.values.fontScaleMinScale,\n )\n\n reader.settings.update({\n fontScale: newMinMaxedFontScale,\n })\n }),\n takeUntil(pinchEnd$),\n )\n }),\n )\n\n return merge(zoomGestures$, watchForFontScaleChange$).pipe(\n map((event) => ({ event, handled: true })),\n )\n }),\n )\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport { EMPTY, filter, map, switchMap, tap } from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\n\nexport const registerSwipe = ({\n reader,\n recognizable,\n settingsManager,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\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 map(({ event }) => ({ event, handled: true })),\n ),\n ),\n )\n\n return gestures$\n}\n","import { isHtmlElement } from \"@prose-reader/core\"\nimport type { GestureEvent } from \"./types\"\n\nexport const isNotLink = (event: GestureEvent[\"event\"]) => {\n const target = event.event.target\n\n if (isHtmlElement(target) && target.tagName === \"a\") return false\n\n return true\n}\n\nexport const istMatchingSelectors = (\n selectors: string[],\n event: GestureEvent[\"event\"],\n): boolean => {\n const target = event.event.target\n\n if (!isHtmlElement(target)) return false\n\n const match = selectors.find((selector) => {\n // Check if the target matches the selector directly\n if (target.matches(selector)) return true\n\n // Check if the target is within an element matching the selector\n if (target.closest(selector)) return true\n\n return false\n })\n\n return !!match\n}\n\nexport const getPositionRelativeToContainer = (\n event: PointerEvent,\n containerElementRect: DOMRectReadOnly,\n) => {\n const { x, y } = event\n const { left, top } = containerElementRect\n\n return {\n x: x - left,\n y: y - top,\n }\n}\n","import type { HookManager, Reader } from \"@prose-reader/core\"\nimport type { TapRecognizer } from \"gesturx\"\nimport {\n EMPTY,\n combineLatest,\n filter,\n first,\n map,\n of,\n switchMap,\n withLatestFrom,\n} from \"rxjs\"\nimport type { GesturesSettingsManager } from \"../SettingsManager\"\nimport type { GestureRecognizable, Hook } from \"../types\"\nimport {\n getPositionRelativeToContainer,\n isNotLink,\n istMatchingSelectors,\n} from \"../utils\"\n\nconst calculatePageTurnMargin = (screenWidth: number): number => {\n const minMargin = 0.15\n const maxMargin = 0.3\n const minWidth = 400\n const maxWidth = 1200\n\n if (screenWidth <= minWidth) return maxMargin\n if (screenWidth >= maxWidth) return minMargin\n\n // Linear interpolation between min and max\n const ratio = (screenWidth - minWidth) / (maxWidth - minWidth)\n return maxMargin - ratio * (maxMargin - minMargin)\n}\n\nexport const registerTaps = ({\n reader,\n recognizable,\n hookManager,\n settingsManager,\n recognizer,\n}: {\n recognizable: GestureRecognizable\n reader: Reader\n hookManager: HookManager<Hook>\n recognizer: TapRecognizer\n settingsManager: GesturesSettingsManager\n}) => {\n const gestures$ = recognizable.events$.pipe(\n filter((event) => event.recognizer === recognizer),\n withLatestFrom(reader.context.containerElementRect$),\n switchMap(([{ event }, containerElementRect]) => {\n if (!containerElementRect) return EMPTY\n\n const normalizedEvent = event.event\n const { computedPageTurnDirection } = reader.settings.values\n\n if (\n event.type === \"tap\" &&\n isNotLink(event) &&\n !istMatchingSelectors(settingsManager.values.ignore, event)\n ) {\n if (`x` in normalizedEvent) {\n const width = containerElementRect.width\n const height = containerElementRect.height\n const pageTurnMargin = calculatePageTurnMargin(width)\n const { x, y } = getPositionRelativeToContainer(\n normalizedEvent,\n containerElementRect,\n )\n\n const beforeTapResults$ = hookManager.execute(\n \"beforeGesture\",\n undefined,\n { event$: of(event) },\n )\n\n return combineLatest([...beforeTapResults$, of(true)]).pipe(\n first(),\n filter((results) => !results.some((result) => result === false)),\n map(() => {\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 (\n isTopArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnLeftOrTop()\n } else if (\n isBottomArea &&\n computedPageTurnDirection === \"vertical\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else if (\n isRightArea &&\n computedPageTurnDirection === \"horizontal\"\n ) {\n reader.navigation.turnRightOrBottom()\n } else {\n return { event, handled: false }\n }\n\n return { event, handled: true }\n }),\n )\n }\n }\n\n return EMPTY\n }),\n )\n\n return gestures$\n}\n","import type { Reader } from \"@prose-reader/core\"\nimport type { PanRecognizer } from \"gesturx\"\nimport { filter, switchMap, tap } from \"rxjs\"\n\nexport const registerZoomPan = ({\n reader,\n recognizer,\n}: { recognizer: PanRecognizer; reader: Reader }) => {\n const panStart$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panStart\"),\n )\n const panMove$ = recognizer.events$.pipe(\n filter((event) => event.type === \"panMove\"),\n )\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({\n x: startPosition.x + panMoveEvent.deltaX,\n y: startPosition.y + panMoveEvent.deltaY,\n })\n }\n }),\n )\n }),\n )\n\n return zoomingPan$\n}\n","import { HookManager, type Reader } from \"@prose-reader/core\"\nimport {\n PanRecognizer,\n PinchRecognizer,\n Recognizable,\n SwipeRecognizer,\n TapRecognizer,\n} from \"gesturx\"\nimport { combineLatest, merge, share, takeUntil, tap } from \"rxjs\"\nimport { GesturesSettingsManager } from \"./SettingsManager\"\nimport { registerPan } from \"./gestures/pan\"\nimport { registerPinch } from \"./gestures/pinch\"\nimport { registerSwipe } from \"./gestures/swipe\"\nimport { registerTaps } from \"./gestures/taps\"\nimport { registerZoomPan } from \"./gestures/zoomPan\"\nimport type { EnhancerAPI, Hook, InputSettings } from \"./types\"\n\nexport * from \"./types\"\n\nexport const gesturesEnhancer =\n <InheritOptions, InheritOutput extends Reader>(\n next: (options: InheritOptions) => InheritOutput,\n ) =>\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, reader)\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 failWithSelection = {\n start$: reader.selection.selectionStart$,\n end$: reader.selection.selectionEnd$,\n }\n\n const panRecognizer = new PanRecognizer({\n failWith: [pinchRecognizer, failWithSelection],\n options: {\n // we want to have some margin to trigger zoom\n posThreshold: 15,\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 failWith: [failWithSelection],\n })\n\n const recognizable = new Recognizable({\n recognizers: [\n tapRecognizer,\n panRecognizer,\n swipeRecognizer,\n pinchRecognizer,\n zoomPanRecognizer,\n ],\n disableTextSelection: false,\n })\n\n const tapGestures$ = registerTaps({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n recognizer: tapRecognizer,\n })\n\n const panGestures$ = registerPan({\n hookManager,\n reader,\n recognizer: panRecognizer,\n settingsManager,\n })\n\n const swipeGestures$ = registerSwipe({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const pinchGestures$ = registerPinch({\n hookManager,\n reader,\n recognizable,\n settingsManager,\n })\n\n const zoomPanGestures$ = registerZoomPan({\n reader,\n recognizer: zoomPanRecognizer,\n })\n\n const containerUpdate$ = reader.context.watch(`rootElement`).pipe(\n tap((container) => {\n recognizable.update({\n container,\n })\n }),\n )\n\n const watchSettings$ = combineLatest([\n settingsManager.values$,\n panRecognizer.config$,\n ]).pipe(\n tap(([{ pinchCancelPan }, panRecognizerConfig]) => {\n const pinchAlreadyInFailWith =\n panRecognizerConfig.failWith?.includes(pinchRecognizer)\n\n if (pinchCancelPan && !pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: [\n ...(panRecognizerConfig.failWith ?? []),\n pinchRecognizer,\n ],\n })\n }\n\n if (!pinchCancelPan && pinchAlreadyInFailWith) {\n panRecognizer.update({\n failWith: panRecognizerConfig.failWith?.filter(\n (recognizer) => recognizer !== pinchRecognizer,\n ),\n })\n }\n }),\n )\n\n const gestures$ = merge(\n pinchGestures$,\n tapGestures$,\n swipeGestures$,\n panGestures$,\n ).pipe(share())\n\n merge(containerUpdate$, watchSettings$, zoomPanGestures$, gestures$)\n .pipe(takeUntil(reader.$.destroy$))\n .subscribe()\n\n return {\n ...reader,\n destroy: () => {\n reader.destroy()\n settingsManager.destroy()\n },\n gestures: {\n settings: settingsManager,\n gestures$,\n hooks: hookManager,\n },\n }\n }\n"],"names":["SettingsManager","tap","takeUntil","switchMap","EMPTY","map","isHtmlElement","filter","withLatestFrom","merge","event","throttleTime","animationFrameScheduler","of","combineLatest","first","HookManager","PinchRecognizer","PanRecognizer","TapRecognizer","SwipeRecognizer","Recognizable","share"],"mappings":"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"}
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  import { GestureEvent } from './types';
2
2
  export declare const isNotLink: (event: GestureEvent["event"]) => boolean;
3
3
  export declare const istMatchingSelectors: (selectors: string[], event: GestureEvent["event"]) => boolean;
4
+ export declare const getPositionRelativeToContainer: (event: PointerEvent, containerElementRect: DOMRectReadOnly) => {
5
+ x: number;
6
+ y: number;
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prose-reader/enhancer-gestures",
3
- "version": "1.228.0",
3
+ "version": "1.229.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "test": "vitest run --coverage"
26
26
  },
27
27
  "dependencies": {
28
- "@prose-reader/core": "^1.228.0"
28
+ "@prose-reader/core": "^1.229.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "gesturx": "*",
@@ -35,5 +35,5 @@
35
35
  "gesturx": "1.x",
36
36
  "rxjs": "7.x"
37
37
  },
38
- "gitHead": "f38af897428bb229420eab2bfa2e396d2a13e807"
38
+ "gitHead": "47e5d28bbce8859f6d92485991be5aa0fccee981"
39
39
  }