react-native-gtkx 0.2.0-alpha.2 → 0.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/aliases/index.d.ts +84 -0
- package/dist/aliases/index.js +208 -0
- package/dist/aliases/index.js.map +1 -0
- package/dist/animated/index.d.ts +2 -0
- package/dist/animated/index.js +5 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/types.d.ts +1 -0
- package/dist/animated/types.js.map +1 -1
- package/dist/animated/value-animation.js +17 -4
- package/dist/animated/value-animation.js.map +1 -1
- package/dist/apis/host.gtkx.js +9 -12
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/apis/index.d.ts +4 -2
- package/dist/apis/index.js +2 -0
- package/dist/apis/index.js.map +1 -1
- package/dist/apis/keyboard.d.ts +60 -0
- package/dist/apis/keyboard.js +63 -0
- package/dist/apis/keyboard.js.map +1 -0
- package/dist/apis/log-box.d.ts +15 -0
- package/dist/apis/log-box.js +46 -0
- package/dist/apis/log-box.js.map +1 -0
- package/dist/apis/platform.d.ts +18 -1
- package/dist/apis/platform.js.map +1 -1
- package/dist/common/index.d.ts +0 -1
- package/dist/common/index.js +24 -1
- package/dist/common/index.js.map +1 -1
- package/dist/components/animated.d.ts +70 -6
- package/dist/components/animated.js +559 -46
- package/dist/components/animated.js.map +1 -1
- package/dist/components/driven-size.d.ts +27 -0
- package/dist/components/driven-size.js +85 -0
- package/dist/components/driven-size.js.map +1 -0
- package/dist/components/find-node-handle.d.ts +11 -0
- package/dist/components/find-node-handle.js +53 -0
- package/dist/components/find-node-handle.js.map +1 -0
- package/dist/components/flat-list.d.ts +3 -2
- package/dist/components/flat-list.js.map +1 -1
- package/dist/components/frame-scheduler.d.ts +16 -0
- package/dist/components/frame-scheduler.js +37 -0
- package/dist/components/frame-scheduler.js.map +1 -0
- package/dist/components/image.d.ts +6 -1
- package/dist/components/image.js +15 -4
- package/dist/components/image.js.map +1 -1
- package/dist/components/index.d.ts +7 -5
- package/dist/components/index.js +5 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/measure.d.ts +51 -1
- package/dist/components/measure.js +101 -2
- package/dist/components/measure.js.map +1 -1
- package/dist/components/pressable.d.ts +61 -1
- package/dist/components/pressable.js +151 -4
- package/dist/components/pressable.js.map +1 -1
- package/dist/components/rect-store.d.ts +58 -0
- package/dist/components/rect-store.js +124 -3
- package/dist/components/rect-store.js.map +1 -1
- package/dist/components/root.js +6 -1
- package/dist/components/root.js.map +1 -1
- package/dist/components/scroll-phase.d.ts +35 -0
- package/dist/components/scroll-phase.js +26 -0
- package/dist/components/scroll-phase.js.map +1 -0
- package/dist/components/scroll-view.d.ts +39 -3
- package/dist/components/scroll-view.js +378 -43
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/text-input.js +9 -25
- package/dist/components/text-input.js.map +1 -1
- package/dist/components/text.d.ts +6 -2
- package/dist/components/text.js +43 -8
- package/dist/components/text.js.map +1 -1
- package/dist/components/use-focus.d.ts +27 -0
- package/dist/components/use-focus.js +116 -0
- package/dist/components/use-focus.js.map +1 -0
- package/dist/components/use-layout-child.d.ts +13 -1
- package/dist/components/use-layout-child.js +188 -5
- package/dist/components/use-layout-child.js.map +1 -1
- package/dist/components/view.d.ts +5 -2
- package/dist/components/view.js +18 -13
- package/dist/components/view.js.map +1 -1
- package/dist/components/virtualized-list.d.ts +45 -5
- package/dist/components/virtualized-list.js +90 -24
- package/dist/components/virtualized-list.js.map +1 -1
- package/dist/components/wheel-scroll-session.d.ts +7 -0
- package/dist/components/wheel-scroll-session.js +53 -0
- package/dist/components/wheel-scroll-session.js.map +1 -0
- package/dist/components/widget-retention.d.ts +35 -0
- package/dist/components/widget-retention.js +169 -0
- package/dist/components/widget-retention.js.map +1 -0
- package/dist/contracts.d.ts +4 -0
- package/dist/contracts.js.map +1 -1
- package/dist/dnd/context.d.ts +69 -0
- package/dist/dnd/context.js +149 -0
- package/dist/dnd/context.js.map +1 -0
- package/dist/dnd/draggable.d.ts +59 -0
- package/dist/dnd/draggable.js +149 -0
- package/dist/dnd/draggable.js.map +1 -0
- package/dist/dnd/droppable.d.ts +24 -0
- package/dist/dnd/droppable.js +74 -0
- package/dist/dnd/droppable.js.map +1 -0
- package/dist/dnd/gtk-controllers.d.ts +39 -0
- package/dist/dnd/gtk-controllers.js +110 -0
- package/dist/dnd/gtk-controllers.js.map +1 -0
- package/dist/dnd/index.d.ts +6 -0
- package/dist/dnd/index.js +31 -0
- package/dist/dnd/index.js.map +1 -0
- package/dist/dnd/order.d.ts +7 -0
- package/dist/dnd/order.js +20 -0
- package/dist/dnd/order.js.map +1 -0
- package/dist/dnd/payload.d.ts +14 -0
- package/dist/dnd/payload.js +41 -0
- package/dist/dnd/payload.js.map +1 -0
- package/dist/dnd/sortable.d.ts +49 -0
- package/dist/dnd/sortable.js +307 -0
- package/dist/dnd/sortable.js.map +1 -0
- package/dist/dnd/types.d.ts +290 -0
- package/dist/dnd/types.js +25 -0
- package/dist/dnd/types.js.map +1 -0
- package/dist/gesture-handler-compat/builder.d.ts +251 -0
- package/dist/gesture-handler-compat/builder.js +513 -0
- package/dist/gesture-handler-compat/builder.js.map +1 -0
- package/dist/gesture-handler-compat/composition.d.ts +23 -0
- package/dist/gesture-handler-compat/composition.js +111 -0
- package/dist/gesture-handler-compat/composition.js.map +1 -0
- package/dist/gesture-handler-compat/deciders.d.ts +3 -0
- package/dist/gesture-handler-compat/deciders.js +47 -0
- package/dist/gesture-handler-compat/deciders.js.map +1 -0
- package/dist/gesture-handler-compat/detector-runtime.d.ts +44 -0
- package/dist/gesture-handler-compat/detector-runtime.js +374 -0
- package/dist/gesture-handler-compat/detector-runtime.js.map +1 -0
- package/dist/gesture-handler-compat/detector.d.ts +22 -0
- package/dist/gesture-handler-compat/detector.js +104 -0
- package/dist/gesture-handler-compat/detector.js.map +1 -0
- package/dist/gesture-handler-compat/fling.d.ts +24 -0
- package/dist/gesture-handler-compat/fling.js +123 -0
- package/dist/gesture-handler-compat/fling.js.map +1 -0
- package/dist/gesture-handler-compat/force-touch.d.ts +13 -0
- package/dist/gesture-handler-compat/force-touch.js +40 -0
- package/dist/gesture-handler-compat/force-touch.js.map +1 -0
- package/dist/gesture-handler-compat/hooks.d.ts +157 -0
- package/dist/gesture-handler-compat/hooks.js +268 -0
- package/dist/gesture-handler-compat/hooks.js.map +1 -0
- package/dist/gesture-handler-compat/hover.d.ts +2 -0
- package/dist/gesture-handler-compat/hover.js +22 -0
- package/dist/gesture-handler-compat/hover.js.map +1 -0
- package/dist/gesture-handler-compat/index.d.ts +98 -0
- package/dist/gesture-handler-compat/index.js +255 -0
- package/dist/gesture-handler-compat/index.js.map +1 -0
- package/dist/gesture-handler-compat/long-press.d.ts +6 -0
- package/dist/gesture-handler-compat/long-press.js +21 -0
- package/dist/gesture-handler-compat/long-press.js.map +1 -0
- package/dist/gesture-handler-compat/manual.d.ts +2 -0
- package/dist/gesture-handler-compat/manual.js +18 -0
- package/dist/gesture-handler-compat/manual.js.map +1 -0
- package/dist/gesture-handler-compat/native.d.ts +7 -0
- package/dist/gesture-handler-compat/native.js +34 -0
- package/dist/gesture-handler-compat/native.js.map +1 -0
- package/dist/gesture-handler-compat/orchestrator.d.ts +77 -0
- package/dist/gesture-handler-compat/orchestrator.js +284 -0
- package/dist/gesture-handler-compat/orchestrator.js.map +1 -0
- package/dist/gesture-handler-compat/pan.d.ts +23 -0
- package/dist/gesture-handler-compat/pan.js +116 -0
- package/dist/gesture-handler-compat/pan.js.map +1 -0
- package/dist/gesture-handler-compat/recognizer.d.ts +268 -0
- package/dist/gesture-handler-compat/recognizer.js +1056 -0
- package/dist/gesture-handler-compat/recognizer.js.map +1 -0
- package/dist/gesture-handler-compat/relations.d.ts +43 -0
- package/dist/gesture-handler-compat/relations.js +128 -0
- package/dist/gesture-handler-compat/relations.js.map +1 -0
- package/dist/gesture-handler-compat/tap.d.ts +6 -0
- package/dist/gesture-handler-compat/tap.js +29 -0
- package/dist/gesture-handler-compat/tap.js.map +1 -0
- package/dist/gesture-handler-compat/touchpad.d.ts +41 -0
- package/dist/gesture-handler-compat/touchpad.js +64 -0
- package/dist/gesture-handler-compat/touchpad.js.map +1 -0
- package/dist/gesture-handler-compat/types.d.ts +441 -0
- package/dist/gesture-handler-compat/types.js +167 -0
- package/dist/gesture-handler-compat/types.js.map +1 -0
- package/dist/gtk/controllers.d.ts +39 -0
- package/dist/gtk/controllers.js +92 -0
- package/dist/gtk/controllers.js.map +1 -0
- package/dist/gtk/index.d.ts +2 -1
- package/dist/gtk/index.js +7 -1
- package/dist/gtk/index.js.map +1 -1
- package/dist/gtkx/bridge/geometry.js +6 -4
- package/dist/gtkx/bridge/geometry.js.map +1 -1
- package/dist/gtkx/bridge/index.d.ts +5 -3
- package/dist/gtkx/bridge/index.js +6 -3
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.js.map +1 -1
- package/dist/gtkx/bridge/use-signal.js +1 -1
- package/dist/gtkx/bridge/use-signal.js.map +1 -1
- package/dist/gtkx/bridge/view-box.d.ts +56 -0
- package/dist/gtkx/bridge/view-box.js +394 -9
- package/dist/gtkx/bridge/view-box.js.map +1 -1
- package/dist/gtkx/bridge/widget-css.d.ts +17 -0
- package/dist/gtkx/bridge/widget-css.js +72 -0
- package/dist/gtkx/bridge/widget-css.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/driven-size.d.ts +12 -0
- package/dist/layout/driven-size.js +70 -0
- package/dist/layout/driven-size.js.map +1 -0
- package/dist/layout/engine.d.ts +17 -1
- package/dist/layout/engine.js +3 -20
- package/dist/layout/engine.js.map +1 -1
- package/dist/layout/node.d.ts +13 -0
- package/dist/layout/node.js +14 -0
- package/dist/layout/node.js.map +1 -1
- package/dist/layout/yoga.d.ts +3 -2
- package/dist/layout/yoga.js +5 -2
- package/dist/layout/yoga.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +257 -60
- package/dist/mcp/data/generated.js +306 -62
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/metro/index.d.ts +10 -0
- package/dist/metro/index.js +21 -12
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/sidebar.d.ts +16 -0
- package/dist/navigation/sidebar.js +65 -1
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/reanimated-compat/animated-ref.d.ts +32 -0
- package/dist/reanimated-compat/animated-ref.js +57 -0
- package/dist/reanimated-compat/animated-ref.js.map +1 -0
- package/dist/reanimated-compat/animation.d.ts +177 -0
- package/dist/reanimated-compat/animation.js +540 -0
- package/dist/reanimated-compat/animation.js.map +1 -0
- package/dist/reanimated-compat/color.d.ts +28 -0
- package/dist/reanimated-compat/color.js +249 -0
- package/dist/reanimated-compat/color.js.map +1 -0
- package/dist/reanimated-compat/decay.d.ts +39 -0
- package/dist/reanimated-compat/decay.js +96 -0
- package/dist/reanimated-compat/decay.js.map +1 -0
- package/dist/reanimated-compat/easing.d.ts +30 -0
- package/dist/reanimated-compat/easing.js +76 -0
- package/dist/reanimated-compat/easing.js.map +1 -0
- package/dist/reanimated-compat/hooks.d.ts +14 -0
- package/dist/reanimated-compat/hooks.js +217 -0
- package/dist/reanimated-compat/hooks.js.map +1 -0
- package/dist/reanimated-compat/index.d.ts +258 -0
- package/dist/reanimated-compat/index.js +464 -0
- package/dist/reanimated-compat/index.js.map +1 -0
- package/dist/reanimated-compat/interpolation.d.ts +18 -0
- package/dist/reanimated-compat/interpolation.js +122 -0
- package/dist/reanimated-compat/interpolation.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-config.d.ts +43 -0
- package/dist/reanimated-compat/layout-animation-config.js +78 -0
- package/dist/reanimated-compat/layout-animation-config.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-presets.d.ts +117 -0
- package/dist/reanimated-compat/layout-animation-presets.js +498 -0
- package/dist/reanimated-compat/layout-animation-presets.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-runtime.d.ts +21 -0
- package/dist/reanimated-compat/layout-animation-runtime.js +311 -0
- package/dist/reanimated-compat/layout-animation-runtime.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-view.d.ts +27 -0
- package/dist/reanimated-compat/layout-animation-view.js +266 -0
- package/dist/reanimated-compat/layout-animation-view.js.map +1 -0
- package/dist/reanimated-compat/layout-animation.d.ts +171 -0
- package/dist/reanimated-compat/layout-animation.js +469 -0
- package/dist/reanimated-compat/layout-animation.js.map +1 -0
- package/dist/reanimated-compat/layout-transitions.d.ts +83 -0
- package/dist/reanimated-compat/layout-transitions.js +350 -0
- package/dist/reanimated-compat/layout-transitions.js.map +1 -0
- package/dist/reanimated-compat/mutable.d.ts +29 -0
- package/dist/reanimated-compat/mutable.js +139 -0
- package/dist/reanimated-compat/mutable.js.map +1 -0
- package/dist/reanimated-compat/props.d.ts +18 -0
- package/dist/reanimated-compat/props.js +111 -0
- package/dist/reanimated-compat/props.js.map +1 -0
- package/dist/reanimated-compat/scroll-handler.d.ts +119 -0
- package/dist/reanimated-compat/scroll-handler.js +274 -0
- package/dist/reanimated-compat/scroll-handler.js.map +1 -0
- package/dist/reanimated-compat/scroll-offset.d.ts +12 -0
- package/dist/reanimated-compat/scroll-offset.js +104 -0
- package/dist/reanimated-compat/scroll-offset.js.map +1 -0
- package/dist/reanimated-compat/style.d.ts +90 -0
- package/dist/reanimated-compat/style.js +452 -0
- package/dist/reanimated-compat/style.js.map +1 -0
- package/dist/reanimated-compat/test-timers.d.ts +28 -0
- package/dist/reanimated-compat/test-timers.js +136 -0
- package/dist/reanimated-compat/test-timers.js.map +1 -0
- package/dist/reanimated-compat/threads.d.ts +13 -0
- package/dist/reanimated-compat/threads.js +41 -0
- package/dist/reanimated-compat/threads.js.map +1 -0
- package/dist/reanimated-compat/tracking.d.ts +41 -0
- package/dist/reanimated-compat/tracking.js +106 -0
- package/dist/reanimated-compat/tracking.js.map +1 -0
- package/dist/reanimated-compat/updater-animations.d.ts +36 -0
- package/dist/reanimated-compat/updater-animations.js +273 -0
- package/dist/reanimated-compat/updater-animations.js.map +1 -0
- package/dist/responder/system.d.ts +80 -7
- package/dist/responder/system.js +143 -23
- package/dist/responder/system.js.map +1 -1
- package/dist/responder/use-responder.d.ts +11 -0
- package/dist/responder/use-responder.js +225 -6
- package/dist/responder/use-responder.js.map +1 -1
- package/dist/runner/host-dev.js +1 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +1 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.js +3 -3
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/gtkx-config-module.js +1 -1
- package/dist/sea/gtkx-config-module.js.map +1 -1
- package/dist/style/absolute-insets.d.ts +26 -0
- package/dist/style/absolute-insets.js +113 -0
- package/dist/style/absolute-insets.js.map +1 -0
- package/dist/style/animated-size.d.ts +25 -0
- package/dist/style/animated-size.js +225 -0
- package/dist/style/animated-size.js.map +1 -0
- package/dist/style/colors.d.ts +17 -0
- package/dist/style/colors.js +25 -6
- package/dist/style/colors.js.map +1 -1
- package/dist/style/imperative-css.d.ts +21 -0
- package/dist/style/imperative-css.js +63 -0
- package/dist/style/imperative-css.js.map +1 -0
- package/dist/style/index.d.ts +2 -1
- package/dist/style/index.js +2 -1
- package/dist/style/index.js.map +1 -1
- package/dist/style/split-style.js +5 -0
- package/dist/style/split-style.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/unsupported-export.d.ts +8 -0
- package/dist/unsupported-export.js +66 -0
- package/dist/unsupported-export.js.map +1 -0
- package/dist/vite/index.d.ts +21 -8
- package/dist/vite/index.js +127 -82
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +2 -2
- package/dist/vitest/index.js.map +1 -1
- package/dist/worklets-compat/index.d.ts +4 -0
- package/dist/worklets-compat/index.js +28 -0
- package/dist/worklets-compat/index.js.map +1 -0
- package/dist/worklets-compat/surface.d.ts +110 -0
- package/dist/worklets-compat/surface.js +153 -0
- package/dist/worklets-compat/surface.js.map +1 -0
- package/package.json +25 -9
- package/types.d.ts +9 -0
- package/dist/common/list.d.ts +0 -82
- package/dist/common/list.js +0 -166
- package/dist/common/list.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector-runtime.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/detector-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["// Everything a mounted `GestureDetector` has to remember between renders, in\n// a closure rather than in the component.\n//\n// This file exists because the mutable state genuinely belongs here, and the\n// React Compiler's lint rules are right to say so: a component may not read\n// or write a ref while rendering. The detector needs things that outlive a\n// render — the current configs, the child's handle, and the child's own\n// forwarded ref — and every one of them is only ever touched from a callback,\n// an effect or a GTK event. Keeping them behind functions makes that\n// structural instead of a promise.\n//\n// It holds a LIST of recognizers rather than one, because a composed gesture\n// is several recognizers on one child. The prop set the child is given is\n// fixed and stable regardless: each entry is a trampoline over whatever\n// recognizers the group currently has, so composing differently on a later\n// render changes the list inside an effect and never during a render.\nimport { widgetForHandle } from \"../components/measure\"\nimport {\n computePointInWindow,\n Gdk,\n Gtk,\n type Gtk as GtkNs,\n} from \"../gtkx/bridge/index\"\nimport type { GestureResponderEvent } from \"../responder/types\"\nimport { requestResponder } from \"../responder/use-responder\"\nimport type { PreparedGesture } from \"./composition\"\nimport { DECIDERS } from \"./deciders\"\nimport { gestureOrchestrator } from \"./orchestrator\"\nimport {\n createRecognizer,\n type ControllerSample,\n type Recognizer,\n type Rect,\n} from \"./recognizer\"\nimport { bindGestureTag, unbindGestureTag } from \"./relations\"\nimport { mintHandlerTag, type GestureKind, type GestureSpec } from \"./types\"\n\n/**\n * The props a recognizer contributes, named once.\n *\n * Fixed rather than read off a recognizer, because the trampolines have to\n * exist before there is a recognizer to read them from: the child renders and\n * registers with the responder system before the detector's own layout effect\n * has run. All three kinds contribute exactly this set.\n */\nconst HANDLER_NAMES = [\n \"onStartShouldSetResponder\",\n \"onMoveShouldSetResponder\",\n \"onTouchStart\",\n \"onTouchMove\",\n \"onTouchEnd\",\n \"onTouchCancel\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n] as const\n\n/** The two responder props that answer a question rather than take an event. */\nexport const PREDICATES = new Set<string>([\n \"onStartShouldSetResponder\",\n \"onMoveShouldSetResponder\",\n])\n\n/** A ref in either of React's two spellings. */\ntype AnyRef =\n ((instance: unknown) => void) | { current: unknown } | null | undefined\n\nlet warnedWithoutWidget = false\n\nconst warnNoWidget = (): void => {\n if (warnedWithoutWidget) {\n return\n }\n warnedWithoutWidget = true\n const isProduction =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"production\"\n if (!isProduction) {\n console.warn(\n \"react-native-gtkx: `GestureDetector`'s child exposed no ref carrying a widget, so the gesture \" +\n \"cannot measure its own view. `hitSlop`, `shouldCancelWhenOutside` and the `x`/`y` fields of \" +\n \"every event will be wrong or ignored. Give the child a `ref` built with the platform's own \" +\n \"measure handle, or wrap it in a `View`. See docs/api.md.\",\n )\n }\n}\n\ntype Mounted = {\n /** The spec object this recognizer currently drives; rebound every render. */\n spec: GestureSpec\n readonly kind: GestureKind\n readonly tag: number\n readonly recognizer: Recognizer\n /**\n * The GTK controller feeding a kind the pointer stream cannot — a `Pinch`, a\n * `Rotation`, a `Hover` or a `ForceTouch` — once the child has produced a\n * widget to attach it to. Null for every pointer kind, and null until then:\n * the child's ref lands before this parent's layout effect, but a child that\n * carries no widget at all never gets one.\n *\n * Typed as the base controller rather than as `Gesture`, because `Hover`'s\n * is a `GtkEventControllerMotion` and that is not a gesture at all.\n */\n controller: GtkNs.EventController | null\n}\n\n/**\n * `GtkGestureZoom` / `GtkGestureRotate` — `Pinch` and `Rotation`.\n *\n * The scale and the angle are taken from the SIGNAL ARGUMENTS rather than read\n * back off the controller, and that is not a style preference:\n * `gtk_gesture_zoom_get_scale_delta` returns 1 the instant the gesture stops\n * being active, so anything asked after the fact reports the gesture undoing\n * itself. The signal carries the same number GTK would have returned, at the\n * moment it is true.\n *\n * The position is `gtk_gesture_get_bounding_box_center`, whose coordinates are\n * relative to the widget the controller is attached to — which is the\n * gesture's own view, so it is already the view-local space upstream's\n * `focalX`/`anchorX` are in (`absoluteToLocal` in its web delegate). When GTK\n * has no bounding box to report, the view's centre stands in: a touchpad\n * pinch's focal point is the pointer, and a pinch with an unknown focal point\n * is still a pinch.\n */\nconst touchpadController = (\n kind: \"pinch\" | \"rotation\",\n widget: GtkNs.Widget,\n channel: NonNullable<Recognizer[\"controller\"]>,\n): GtkNs.Gesture => {\n let scale = 1\n let rotation = 0\n const controller: GtkNs.Gesture =\n kind === \"pinch\" ? new Gtk.GestureZoom() : new Gtk.GestureRotate()\n\n const sample = (): ControllerSample => {\n let x = widget.getWidth() / 2\n let y = widget.getHeight() / 2\n const [known, centreX, centreY] = controller.getBoundingBoxCenter()\n if (known) {\n x = centreX\n y = centreY\n }\n // `gtk_gesture_zoom_filter_event` only lets a touchpad pinch through at\n // exactly two fingers, so this is a constant rather than a reading.\n return { scale, rotation, x, y, pointers: 2 }\n }\n\n controller.on(\"begin\", () => {\n scale = 1\n rotation = 0\n channel.begin(sample())\n })\n if (kind === \"pinch\") {\n ;(controller as GtkNs.GestureZoom).on(\"scale-changed\", (value: number) => {\n scale = value\n channel.update(sample())\n })\n } else {\n // `angle-changed` carries the current absolute angle first and the delta\n // SINCE RECOGNITION second, which is upstream's `rotation` exactly:\n // radians, cumulative, positive clockwise.\n ;(controller as GtkNs.GestureRotate).on(\n \"angle-changed\",\n (_angle: number, delta: number) => {\n rotation = delta\n channel.update(sample())\n },\n )\n }\n controller.on(\"end\", () => {\n channel.end()\n })\n controller.on(\"cancel\", () => {\n channel.cancel()\n })\n return controller\n}\n\n/**\n * `GtkEventControllerMotion` — `Hover`.\n *\n * The plainest of the three, and the reason this gesture turned out to be\n * deliverable at all: `enter` and `motion` carry the pointer's position in the\n * WIDGET's own coordinates, which is already the space every payload field\n * wants, and `leave` carries nothing because there is nothing left to say.\n *\n * `leave` ends the gesture rather than cancelling it — upstream's\n * `onPointerMoveOut` calls `end()`, and it is right to: the pointer leaving is\n * the hover finishing normally, not something taking it away. GTK's own\n * `cancel` has no counterpart on a motion controller, so the channel's\n * `cancel` is reached only through the arbitration registry.\n *\n * Note that this is the same controller `components/pressable.tsx` attaches\n * for its `hovered` state, on possibly the same widget. Two motion controllers\n * on one widget both receive every crossing — they are observers, and neither\n * claims anything — so a `Pressable` inside a `GestureDetector` keeps its own\n * hover styling while the gesture runs.\n */\nconst hoverController = (\n channel: NonNullable<Recognizer[\"controller\"]>,\n): GtkNs.EventController => {\n const controller = new Gtk.EventControllerMotion()\n controller.on(\"enter\", (x: number, y: number) => {\n channel.begin({ x, y, pointers: 1 })\n })\n controller.on(\"motion\", (x: number, y: number) => {\n channel.update({ x, y, pointers: 1 })\n })\n controller.on(\"leave\", () => {\n channel.end()\n })\n return controller\n}\n\n/**\n * `GtkGestureStylus` — `ForceTouch`, and the one controller here that needs\n * hardware nothing in the test suite can synthesize.\n *\n * `getAxis(Gdk.AxisUse.PRESSURE)` returns `[known, value]` and may ONLY be\n * called from inside one of the four signal handlers, which is why the sample\n * is built in each of them rather than from a shared reader. GDK normalises\n * pressure to `[0, 1]`, which is already upstream's documented range for\n * `minForce`/`maxForce`, so nothing is rescaled.\n *\n * `stylusOnly` is left at GTK's default (true), so this controller sees tablet\n * tools and nothing else. A mouse dragging across the widget produces no\n * events here at all — which is the behaviour that keeps a `ForceTouch` from\n * quietly activating at force 0 on a machine with no tablet.\n */\nconst stylusController = (\n channel: NonNullable<Recognizer[\"controller\"]>,\n): GtkNs.EventController => {\n const controller = new Gtk.GestureStylus()\n const pressure = (): number => {\n const [known, value] = controller.getAxis(Gdk.AxisUse.PRESSURE)\n // A tool with no pressure axis reports none, and 0 is the honest reading\n // rather than a stand-in: a gesture whose `minForce` cannot be met simply\n // never activates, which is what a device that cannot measure pressure\n // should produce.\n return known ? value : 0\n }\n controller.on(\"down\", (x: number, y: number) => {\n channel.begin({ x, y, force: pressure(), pointers: 1 })\n })\n controller.on(\"motion\", (x: number, y: number) => {\n channel.update({ x, y, force: pressure(), pointers: 1 })\n })\n controller.on(\"up\", () => {\n channel.end()\n })\n controller.on(\"cancel\", () => {\n channel.cancel()\n })\n return controller\n}\n\nexport type DetectorRuntime = {\n /** The recognizer props to merge into the child. Stable for the mount. */\n handlers: Record<string, (event: GestureResponderEvent) => boolean | void>\n /** The callback ref to put on the child. Stable for the detector's life. */\n assignHandle: (instance: unknown) => void\n /** Called from a layout effect on every render. */\n sync: (prepared: readonly PreparedGesture[], forwarded: AnyRef) => void\n /** Warns once if the child turned out to carry no widget. */\n checkWidget: () => void\n /** Every mounted recognizer, in the order the gestures were written. */\n gestures: () => readonly Mounted[]\n dispose: () => void\n}\n\nexport const createDetectorRuntime = (): DetectorRuntime => {\n let mounted: Mounted[] = []\n let handle: unknown = null\n let forwardedRef: AnyRef = null\n\n const publish = (instance: unknown): void => {\n if (typeof forwardedRef === \"function\") {\n forwardedRef(instance)\n } else if (forwardedRef) {\n forwardedRef.current = instance\n }\n }\n\n const boundsInWindow = (): Rect | null => {\n const widget = widgetForHandle(handle)\n if (!widget) {\n return null\n }\n const origin = computePointInWindow(widget, 0, 0)\n if (!origin) {\n return null\n }\n return {\n x: origin.x,\n y: origin.y,\n width: widget.getWidth(),\n height: widget.getHeight(),\n }\n }\n\n /**\n * Attaches the GTK controller a non-pointer kind is fed by, and pumps it\n * into the recognizer's controller channel.\n *\n * FOUR KINDS, THREE CONTROLLERS, ONE CHANNEL. `GtkGestureZoom` for `Pinch`,\n * `GtkGestureRotate` for `Rotation`, `GtkEventControllerMotion` for `Hover`\n * and `GtkGestureStylus` for `ForceTouch`. Everything past `channel.begin`\n * is the same state machine every pointer kind runs on — see\n * `ControllerChannel` in ./recognizer.\n */\n const attachController = (gesture: Mounted): void => {\n const channel = gesture.recognizer.controller\n if (channel === null || gesture.controller !== null) {\n return\n }\n const widget = widgetForHandle(handle)\n if (!widget) {\n return\n }\n\n if (gesture.kind === \"pinch\" || gesture.kind === \"rotation\") {\n gesture.controller = touchpadController(gesture.kind, widget, channel)\n } else if (gesture.kind === \"hover\") {\n gesture.controller = hoverController(channel)\n } else {\n gesture.controller = stylusController(channel)\n }\n widget.addController(gesture.controller)\n }\n\n const detachController = (gesture: Mounted): void => {\n const controller = gesture.controller\n if (controller === null) {\n return\n }\n gesture.controller = null\n const widget = widgetForHandle(handle)\n widget?.removeController(controller)\n }\n\n const create = (spec: GestureSpec): Mounted => {\n const tag = mintHandlerTag()\n const gesture: Mounted = {\n spec,\n kind: spec.kind,\n tag,\n controller: null,\n // The config is read on every event rather than captured, so a re-render\n // that hands the detector a fresh gesture object takes effect without\n // swapping the handler set mid-drag.\n recognizer: createRecognizer(\n tag,\n DECIDERS[spec.kind],\n () => gesture.spec.config,\n {\n boundsInWindow,\n requestResponder: (): boolean => {\n const widget = widgetForHandle(handle)\n return widget !== null && requestResponder(widget)\n },\n orchestrator: gestureOrchestrator,\n },\n ),\n }\n return gesture\n }\n\n const handlers: Record<\n string,\n (event: GestureResponderEvent) => boolean | void\n > = {}\n for (const name of HANDLER_NAMES) {\n handlers[name] = PREDICATES.has(name)\n ? (event: GestureResponderEvent) => {\n // Either recognizer saying yes is a yes, and every one of them is\n // asked — the same rule RN's own bubbling uses when several views\n // want the responder, and the reason a composed gesture's members\n // all get to see the question.\n let wanted = false\n for (const gesture of mounted) {\n if (gesture.recognizer.handlers[name]?.(event) === true) {\n wanted = true\n }\n }\n return wanted\n }\n : (event: GestureResponderEvent) => {\n for (const gesture of mounted) {\n gesture.recognizer.handlers[name]?.(event)\n }\n }\n }\n\n return {\n handlers,\n\n assignHandle: (instance: unknown) => {\n handle = instance\n publish(instance)\n // No return value: React 19 reads one as a callback-ref cleanup.\n },\n\n sync: (prepared, forwarded) => {\n // A composition whose SHAPE changed is a different set of gestures, so\n // the recognizers that no longer have a counterpart are disposed and\n // the new ones minted. Doing it here rather than during render is what\n // keeps tag minting out of the render phase; the child's props never\n // change, because they are trampolines over this list.\n const next: Mounted[] = []\n const reusable = [...mounted]\n for (const gesture of prepared) {\n const index = reusable.findIndex(\n (candidate) => candidate.kind === gesture.spec.kind,\n )\n const existing =\n index >= 0 ? reusable.splice(index, 1)[0]! : create(gesture.spec)\n existing.spec = gesture.spec\n next.push(existing)\n // Identity for the relation maps: the spec object an app holds points\n // at the tag this mount minted. Re-bound every render because both\n // spellings rebuild the object, and never unbound on re-render, so a\n // memoized gesture holding an earlier render's object still resolves.\n bindGestureTag(gesture.spec, existing.tag)\n gestureOrchestrator.relations.configure(existing.tag, gesture.relations)\n // Idempotent, and attempted on every render rather than once: the\n // child's ref lands before this effect, but a child that is not laid\n // out yet has no widget to carry a controller. The first render that\n // has one attaches it.\n attachController(existing)\n }\n for (const dropped of reusable) {\n unbindGestureTag(dropped.spec)\n detachController(dropped)\n dropped.recognizer.dispose()\n }\n mounted = next\n\n // The child's ref is attached BEFORE this parent's layout effect runs,\n // so the first `assignHandle` happened while there was nothing to\n // forward to. Publishing again here is what gets the handle into a ref\n // the child was given on its very first mount.\n const changed = forwarded !== forwardedRef\n forwardedRef = forwarded\n if (changed && handle !== null) {\n publish(handle)\n }\n },\n\n checkWidget: () => {\n if (widgetForHandle(handle) === null) {\n warnNoWidget()\n }\n },\n\n gestures: () => mounted,\n\n dispose: () => {\n for (const gesture of mounted) {\n unbindGestureTag(gesture.spec)\n detachController(gesture)\n gesture.recognizer.dispose()\n }\n mounted = []\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { type AnyGestureSpec } from "./types";
|
|
3
|
+
export type GestureDetectorProps = {
|
|
4
|
+
gesture: AnyGestureSpec;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Web-only upstream, and inert here — there is no text selection to
|
|
8
|
+
* suppress, no context-menu default to cancel and no CSS `touch-action` on
|
|
9
|
+
* a GTK widget. Accepted so portable source stays portable.
|
|
10
|
+
*/
|
|
11
|
+
userSelect?: string;
|
|
12
|
+
enableContextMenu?: boolean;
|
|
13
|
+
touchAction?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Not a view: exactly one child, whose props it extends.
|
|
17
|
+
*
|
|
18
|
+
* Upstream attaches a ref and subscribes the child's native view; the same
|
|
19
|
+
* idea with the platform substituted, plus the merge that keeps the child's
|
|
20
|
+
* own responder props alive.
|
|
21
|
+
*/
|
|
22
|
+
export declare const GestureDetector: ({ gesture, children, }: GestureDetectorProps) => ReactElement;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// `GestureDetector` — the one piece of the RNGH surface that survives
|
|
2
|
+
// upstream's own migration intact, and the only part of it that renders.
|
|
3
|
+
//
|
|
4
|
+
// IT ADDS NO WIDGET, for exactly the reasons `createAnimatedComponent`
|
|
5
|
+
// records: an extra box changes flex layout, changes what `measureLayout` is
|
|
6
|
+
// relative to, and changes which widget a parent's allocate walks. So it
|
|
7
|
+
// renders its single child unchanged and reaches that child's widget through
|
|
8
|
+
// the handle the child already exposes — `widgetForHandle` in
|
|
9
|
+
// components/measure.ts, the seam reanimated slice 1b built for this shape.
|
|
10
|
+
//
|
|
11
|
+
// The gesture's events arrive through the child's OWN responder registration
|
|
12
|
+
// rather than through a second one. Two `Gtk.GestureDrag` controllers on one
|
|
13
|
+
// widget would report every press twice, and two `register()` calls for one
|
|
14
|
+
// host would silently drop whichever came first — so the recognizer's props
|
|
15
|
+
// are MERGED into the child's, and the child's own responder props keep
|
|
16
|
+
// working alongside them.
|
|
17
|
+
//
|
|
18
|
+
// The widget is still needed, and not for events: `hitSlop`,
|
|
19
|
+
// `shouldCancelWhenOutside` and the `x`/`y` fields of every payload are all
|
|
20
|
+
// measured against the gesture's own view, which is not necessarily the
|
|
21
|
+
// widget the event arrived on.
|
|
22
|
+
//
|
|
23
|
+
// Everything mutable lives in ./detector-runtime, so nothing here reads or
|
|
24
|
+
// writes a ref while rendering.
|
|
25
|
+
import { cloneElement, isValidElement, useLayoutEffect, useState, } from "react";
|
|
26
|
+
import { prepareGestures } from "./composition";
|
|
27
|
+
import { createDetectorRuntime, PREDICATES } from "./detector-runtime";
|
|
28
|
+
import { isAnyGestureSpec } from "./types";
|
|
29
|
+
/**
|
|
30
|
+
* Not a view: exactly one child, whose props it extends.
|
|
31
|
+
*
|
|
32
|
+
* Upstream attaches a ref and subscribes the child's native view; the same
|
|
33
|
+
* idea with the platform substituted, plus the merge that keeps the child's
|
|
34
|
+
* own responder props alive.
|
|
35
|
+
*/
|
|
36
|
+
export const GestureDetector = ({ gesture, children, }) => {
|
|
37
|
+
if (!gesture) {
|
|
38
|
+
throw new Error("react-native-gtkx: `GestureDetector` must have a gesture prop provided.");
|
|
39
|
+
}
|
|
40
|
+
if (!isAnyGestureSpec(gesture)) {
|
|
41
|
+
throw new Error("react-native-gtkx: `GestureDetector` was given something that is not a gesture. " +
|
|
42
|
+
"Build one with `Gesture.Pan()`, `Gesture.Tap()`, `Gesture.LongPress()`, " +
|
|
43
|
+
"`Gesture.Native()`, `Gesture.Pinch()`, `Gesture.Rotation()`, `Gesture.Fling()`, " +
|
|
44
|
+
"`Gesture.Manual()`, `Gesture.Hover()` or `Gesture.ForceTouch()` — or the hook " +
|
|
45
|
+
"spelling of any of them — or compose several with `Gesture.Race()`, " +
|
|
46
|
+
"`Gesture.Simultaneous()` or `Gesture.Exclusive()`. See docs/api.md.");
|
|
47
|
+
}
|
|
48
|
+
if (!isValidElement(children)) {
|
|
49
|
+
throw new Error("react-native-gtkx: `GestureDetector` expects exactly one element child. " +
|
|
50
|
+
"It renders no widget of its own, so there is nothing for a fragment, a string or " +
|
|
51
|
+
"several children to attach to.");
|
|
52
|
+
}
|
|
53
|
+
// One runtime, and one handler tag per recognizer in it, for as long as this
|
|
54
|
+
// detector is mounted. Upstream reassigns tags when the gesture object
|
|
55
|
+
// changes; here the object is not the identity — both spellings rebuild it
|
|
56
|
+
// every render — the mounted detector is, and ./relations is what maps an
|
|
57
|
+
// app's gesture object onto the tag that identity minted.
|
|
58
|
+
const [runtime] = useState(createDetectorRuntime);
|
|
59
|
+
// A composition is flattened to the recognizers it contains, each carrying
|
|
60
|
+
// the relations composition gave it. `Race`, `Simultaneous` and `Exclusive`
|
|
61
|
+
// do all of their work here and contribute no mechanism past this point.
|
|
62
|
+
const prepared = prepareGestures(gesture);
|
|
63
|
+
const childProps = children.props;
|
|
64
|
+
// React 19 made `ref` an ordinary prop, and reading `element.ref` warns that
|
|
65
|
+
// it did. So the child's own ref is read from its props and nowhere else —
|
|
66
|
+
// which is also where `cloneElement` will put ours back.
|
|
67
|
+
const childRef = childProps.ref;
|
|
68
|
+
// The config is read on every event rather than captured, so a re-render
|
|
69
|
+
// that hands over a fresh gesture object takes effect without swapping the
|
|
70
|
+
// handler set mid-drag.
|
|
71
|
+
useLayoutEffect(() => {
|
|
72
|
+
runtime.sync(prepared, childRef);
|
|
73
|
+
});
|
|
74
|
+
useLayoutEffect(() => runtime.dispose, [runtime]);
|
|
75
|
+
// A silent no-op is the failure this repo refuses. Checked after the child's
|
|
76
|
+
// own layout effects have run, which is where its `useImperativeHandle`
|
|
77
|
+
// publishes the handle.
|
|
78
|
+
useLayoutEffect(() => {
|
|
79
|
+
runtime.checkWidget();
|
|
80
|
+
});
|
|
81
|
+
const merged = { ref: runtime.assignHandle };
|
|
82
|
+
for (const [name, own] of Object.entries(runtime.handlers)) {
|
|
83
|
+
const childHandler = childProps[name];
|
|
84
|
+
if (!childHandler) {
|
|
85
|
+
merged[name] = own;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// The child asked for these too. Both run; for the two that answer a
|
|
89
|
+
// question, either saying yes is a yes — the same rule RN's own bubbling
|
|
90
|
+
// uses when several views want the responder.
|
|
91
|
+
merged[name] = PREDICATES.has(name)
|
|
92
|
+
? (event) => {
|
|
93
|
+
const mine = own(event) === true;
|
|
94
|
+
const theirs = childHandler(event) === true;
|
|
95
|
+
return mine || theirs;
|
|
96
|
+
}
|
|
97
|
+
: (event) => {
|
|
98
|
+
own(event);
|
|
99
|
+
childHandler(event);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return cloneElement(children, merged);
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/detector.tsx"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,yEAAyE;AACzE,EAAE;AACF,uEAAuE;AACvE,6EAA6E;AAC7E,yEAAyE;AACzE,6EAA6E;AAC7E,8DAA8D;AAC9D,4EAA4E;AAC5E,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,wEAAwE;AACxE,0BAA0B;AAC1B,EAAE;AACF,6DAA6D;AAC7D,4EAA4E;AAC5E,wEAAwE;AACxE,+BAA+B;AAC/B,EAAE;AACF,2EAA2E;AAC3E,gCAAgC;AAChC,OAAO,EACL,YAAY,EACZ,cAAc,EACd,eAAe,EACf,QAAQ,GAIT,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAuB,MAAM,SAAS,CAAA;AAe/D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,OAAO,EACP,QAAQ,GACa,EAAgB,EAAE;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAA;IACH,CAAC;IACD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,kFAAkF;YAChF,0EAA0E;YAC1E,kFAAkF;YAClF,gFAAgF;YAChF,sEAAsE;YACtE,qEAAqE,CACxE,CAAA;IACH,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,0EAA0E;YACxE,mFAAmF;YACnF,gCAAgC,CACnC,CAAA;IACH,CAAC;IAED,6EAA6E;IAC7E,uEAAuE;IACvE,2EAA2E;IAC3E,0EAA0E;IAC1E,0DAA0D;IAC1D,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAA;IAEjD,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IAEzC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAgC,CAAA;IAC5D,6EAA6E;IAC7E,2EAA2E;IAC3E,yDAAyD;IACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAA+B,CAAA;IAE3D,yEAAyE;IACzE,2EAA2E;IAC3E,wBAAwB;IACxB,eAAe,CAAC,GAAG,EAAE;QACnB,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,eAAe,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEjD,6EAA6E;IAC7E,wEAAwE;IACxE,wBAAwB;IACxB,eAAe,CAAC,GAAG,EAAE;QACnB,OAAO,CAAC,WAAW,EAAE,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,GAA4B,EAAE,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,CAAA;IACrE,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CACY,CAAA;QAChD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAA;YAClB,SAAQ;QACV,CAAC;QACD,qEAAqE;QACrE,yEAAyE;QACzE,8CAA8C;QAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE;gBACf,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,CAAA;gBAChC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAA;gBAC3C,OAAO,IAAI,IAAI,MAAM,CAAA;YACvB,CAAC;YACH,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE;gBACf,GAAG,CAAC,KAAK,CAAC,CAAA;gBACV,YAAY,CAAC,KAAK,CAAC,CAAA;YACrB,CAAC,CAAA;IACP,CAAC;IAED,OAAO,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;AACvC,CAAC,CAAA","sourcesContent":["// `GestureDetector` — the one piece of the RNGH surface that survives\n// upstream's own migration intact, and the only part of it that renders.\n//\n// IT ADDS NO WIDGET, for exactly the reasons `createAnimatedComponent`\n// records: an extra box changes flex layout, changes what `measureLayout` is\n// relative to, and changes which widget a parent's allocate walks. So it\n// renders its single child unchanged and reaches that child's widget through\n// the handle the child already exposes — `widgetForHandle` in\n// components/measure.ts, the seam reanimated slice 1b built for this shape.\n//\n// The gesture's events arrive through the child's OWN responder registration\n// rather than through a second one. Two `Gtk.GestureDrag` controllers on one\n// widget would report every press twice, and two `register()` calls for one\n// host would silently drop whichever came first — so the recognizer's props\n// are MERGED into the child's, and the child's own responder props keep\n// working alongside them.\n//\n// The widget is still needed, and not for events: `hitSlop`,\n// `shouldCancelWhenOutside` and the `x`/`y` fields of every payload are all\n// measured against the gesture's own view, which is not necessarily the\n// widget the event arrived on.\n//\n// Everything mutable lives in ./detector-runtime, so nothing here reads or\n// writes a ref while rendering.\nimport {\n cloneElement,\n isValidElement,\n useLayoutEffect,\n useState,\n type ReactElement,\n type ReactNode,\n type Ref,\n} from \"react\"\nimport { prepareGestures } from \"./composition\"\nimport { createDetectorRuntime, PREDICATES } from \"./detector-runtime\"\nimport { isAnyGestureSpec, type AnyGestureSpec } from \"./types\"\n\nexport type GestureDetectorProps = {\n gesture: AnyGestureSpec\n children?: ReactNode\n /**\n * Web-only upstream, and inert here — there is no text selection to\n * suppress, no context-menu default to cancel and no CSS `touch-action` on\n * a GTK widget. Accepted so portable source stays portable.\n */\n userSelect?: string\n enableContextMenu?: boolean\n touchAction?: string\n}\n\n/**\n * Not a view: exactly one child, whose props it extends.\n *\n * Upstream attaches a ref and subscribes the child's native view; the same\n * idea with the platform substituted, plus the merge that keeps the child's\n * own responder props alive.\n */\nexport const GestureDetector = ({\n gesture,\n children,\n}: GestureDetectorProps): ReactElement => {\n if (!gesture) {\n throw new Error(\n \"react-native-gtkx: `GestureDetector` must have a gesture prop provided.\",\n )\n }\n if (!isAnyGestureSpec(gesture)) {\n throw new Error(\n \"react-native-gtkx: `GestureDetector` was given something that is not a gesture. \" +\n \"Build one with `Gesture.Pan()`, `Gesture.Tap()`, `Gesture.LongPress()`, \" +\n \"`Gesture.Native()`, `Gesture.Pinch()`, `Gesture.Rotation()`, `Gesture.Fling()`, \" +\n \"`Gesture.Manual()`, `Gesture.Hover()` or `Gesture.ForceTouch()` — or the hook \" +\n \"spelling of any of them — or compose several with `Gesture.Race()`, \" +\n \"`Gesture.Simultaneous()` or `Gesture.Exclusive()`. See docs/api.md.\",\n )\n }\n if (!isValidElement(children)) {\n throw new Error(\n \"react-native-gtkx: `GestureDetector` expects exactly one element child. \" +\n \"It renders no widget of its own, so there is nothing for a fragment, a string or \" +\n \"several children to attach to.\",\n )\n }\n\n // One runtime, and one handler tag per recognizer in it, for as long as this\n // detector is mounted. Upstream reassigns tags when the gesture object\n // changes; here the object is not the identity — both spellings rebuild it\n // every render — the mounted detector is, and ./relations is what maps an\n // app's gesture object onto the tag that identity minted.\n const [runtime] = useState(createDetectorRuntime)\n\n // A composition is flattened to the recognizers it contains, each carrying\n // the relations composition gave it. `Race`, `Simultaneous` and `Exclusive`\n // do all of their work here and contribute no mechanism past this point.\n const prepared = prepareGestures(gesture)\n\n const childProps = children.props as Record<string, unknown>\n // React 19 made `ref` an ordinary prop, and reading `element.ref` warns that\n // it did. So the child's own ref is read from its props and nowhere else —\n // which is also where `cloneElement` will put ours back.\n const childRef = childProps.ref as Ref<unknown> | undefined\n\n // The config is read on every event rather than captured, so a re-render\n // that hands over a fresh gesture object takes effect without swapping the\n // handler set mid-drag.\n useLayoutEffect(() => {\n runtime.sync(prepared, childRef)\n })\n\n useLayoutEffect(() => runtime.dispose, [runtime])\n\n // A silent no-op is the failure this repo refuses. Checked after the child's\n // own layout effects have run, which is where its `useImperativeHandle`\n // publishes the handle.\n useLayoutEffect(() => {\n runtime.checkWidget()\n })\n\n const merged: Record<string, unknown> = { ref: runtime.assignHandle }\n for (const [name, own] of Object.entries(runtime.handlers)) {\n const childHandler = childProps[name] as\n ((event: never) => boolean | void) | undefined\n if (!childHandler) {\n merged[name] = own\n continue\n }\n // The child asked for these too. Both run; for the two that answer a\n // question, either saying yes is a yes — the same rule RN's own bubbling\n // uses when several views want the responder.\n merged[name] = PREDICATES.has(name)\n ? (event: never) => {\n const mine = own(event) === true\n const theirs = childHandler(event) === true\n return mine || theirs\n }\n : (event: never) => {\n own(event)\n childHandler(event)\n }\n }\n\n return cloneElement(children, merged)\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RecognizerDecider } from "./recognizer";
|
|
2
|
+
/** Upstream's `DEFAULT_MAX_DURATION_MS`: past this, the fling has failed. */
|
|
3
|
+
export declare const DEFAULT_MAX_DURATION = 800;
|
|
4
|
+
/** Upstream's `DEFAULT_MIN_VELOCITY`, in units per second. */
|
|
5
|
+
export declare const DEFAULT_MIN_VELOCITY = 700;
|
|
6
|
+
/** Upstream's `DEFAULT_DIRECTION`. */
|
|
7
|
+
export declare const DEFAULT_DIRECTION: 1;
|
|
8
|
+
/** Upstream's `DEFAULT_NUMBER_OF_TOUCHES_REQUIRED`. */
|
|
9
|
+
export declare const DEFAULT_NUMBER_OF_POINTERS = 1;
|
|
10
|
+
/** Upstream's `DEFAULT_ALIGNMENT_CONE`, in degrees. */
|
|
11
|
+
export declare const ALIGNMENT_CONE_DEGREES = 30;
|
|
12
|
+
/** cos(15°) — the axial cone. */
|
|
13
|
+
export declare const AXIAL_DEVIATION_COSINE: number;
|
|
14
|
+
/** cos(30°) — the diagonal cone, which is the complement of the axial one. */
|
|
15
|
+
export declare const DIAGONAL_DEVIATION_COSINE: number;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the velocity points along any direction the config asked for.
|
|
18
|
+
*
|
|
19
|
+
* The similarity is a dot product of UNIT vectors, so it is the cosine of the
|
|
20
|
+
* angle between them, and the comparison is strict — upstream's
|
|
21
|
+
* `Vector.isSimilar` uses `>` rather than `>=`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const isAligned: (velocityX: number, velocityY: number, direction: number) => boolean;
|
|
24
|
+
export declare const flingDecider: RecognizerDecider;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { DIAGONAL_DIRECTIONS, DIRECTIONS } from "./types";
|
|
2
|
+
/** Upstream's `DEFAULT_MAX_DURATION_MS`: past this, the fling has failed. */
|
|
3
|
+
export const DEFAULT_MAX_DURATION = 800;
|
|
4
|
+
/** Upstream's `DEFAULT_MIN_VELOCITY`, in units per second. */
|
|
5
|
+
export const DEFAULT_MIN_VELOCITY = 700;
|
|
6
|
+
/** Upstream's `DEFAULT_DIRECTION`. */
|
|
7
|
+
export const DEFAULT_DIRECTION = DIRECTIONS.RIGHT;
|
|
8
|
+
/** Upstream's `DEFAULT_NUMBER_OF_TOUCHES_REQUIRED`. */
|
|
9
|
+
export const DEFAULT_NUMBER_OF_POINTERS = 1;
|
|
10
|
+
/** Upstream's `DEFAULT_ALIGNMENT_CONE`, in degrees. */
|
|
11
|
+
export const ALIGNMENT_CONE_DEGREES = 30;
|
|
12
|
+
/**
|
|
13
|
+
* `coneToDeviation` from `src/web/utils.ts`: the cosine of HALF the cone, so
|
|
14
|
+
* a 30° cone accepts everything within ±15° of the axis.
|
|
15
|
+
*/
|
|
16
|
+
const coneToDeviation = (degrees) => Math.cos((degrees / 2) * (Math.PI / 180));
|
|
17
|
+
/** cos(15°) — the axial cone. */
|
|
18
|
+
export const AXIAL_DEVIATION_COSINE = coneToDeviation(ALIGNMENT_CONE_DEGREES);
|
|
19
|
+
/** cos(30°) — the diagonal cone, which is the complement of the axial one. */
|
|
20
|
+
export const DIAGONAL_DEVIATION_COSINE = coneToDeviation(90 - ALIGNMENT_CONE_DEGREES);
|
|
21
|
+
/**
|
|
22
|
+
* Upstream's `MINIMAL_RECOGNIZABLE_MAGNITUDE`. Below it a vector has no
|
|
23
|
+
* meaningful direction, and upstream's `Vector` zeroes the unit vector rather
|
|
24
|
+
* than dividing by something near zero.
|
|
25
|
+
*/
|
|
26
|
+
const MINIMAL_RECOGNIZABLE_MAGNITUDE = 0.1;
|
|
27
|
+
/** The unit vector each direction bit stands for, in SCREEN coordinates. */
|
|
28
|
+
const DIRECTION_VECTORS = [
|
|
29
|
+
// [bit, x, y] — note that UP is negative Y, which is upstream's mapping and
|
|
30
|
+
// the screen's rather than the maths convention.
|
|
31
|
+
[DIRECTIONS.LEFT, -1, 0],
|
|
32
|
+
[DIRECTIONS.RIGHT, 1, 0],
|
|
33
|
+
[DIRECTIONS.UP, 0, -1],
|
|
34
|
+
[DIRECTIONS.DOWN, 0, 1],
|
|
35
|
+
];
|
|
36
|
+
const DIAGONAL_VECTORS = [
|
|
37
|
+
[DIAGONAL_DIRECTIONS.UP_RIGHT, 1, -1],
|
|
38
|
+
[DIAGONAL_DIRECTIONS.DOWN_RIGHT, 1, 1],
|
|
39
|
+
[DIAGONAL_DIRECTIONS.UP_LEFT, -1, -1],
|
|
40
|
+
[DIAGONAL_DIRECTIONS.DOWN_LEFT, -1, 1],
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* Whether the velocity points along any direction the config asked for.
|
|
44
|
+
*
|
|
45
|
+
* The similarity is a dot product of UNIT vectors, so it is the cosine of the
|
|
46
|
+
* angle between them, and the comparison is strict — upstream's
|
|
47
|
+
* `Vector.isSimilar` uses `>` rather than `>=`.
|
|
48
|
+
*/
|
|
49
|
+
export const isAligned = (velocityX, velocityY, direction) => {
|
|
50
|
+
const magnitude = Math.hypot(velocityX, velocityY);
|
|
51
|
+
if (magnitude <= MINIMAL_RECOGNIZABLE_MAGNITUDE) {
|
|
52
|
+
// Upstream zeroes the unit vector here, which makes every dot product 0
|
|
53
|
+
// and every alignment false. Stated directly rather than reproduced
|
|
54
|
+
// through a zeroed vector, because a division by a near-zero magnitude is
|
|
55
|
+
// the thing being avoided and this says so.
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const unitX = velocityX / magnitude;
|
|
59
|
+
const unitY = velocityY / magnitude;
|
|
60
|
+
const alignedWith = (candidates, threshold) => candidates.some(([bit, x, y]) => {
|
|
61
|
+
// Every bit of the candidate must be set in the config. For an axis that
|
|
62
|
+
// is one bit; for a diagonal it is two, which is why `UP | RIGHT` opts
|
|
63
|
+
// into the diagonal and `UP` alone does not.
|
|
64
|
+
if ((bit & direction) !== bit) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const length = Math.hypot(x, y);
|
|
68
|
+
return unitX * (x / length) + unitY * (y / length) > threshold;
|
|
69
|
+
});
|
|
70
|
+
return (alignedWith(DIRECTION_VECTORS, AXIAL_DEVIATION_COSINE) ||
|
|
71
|
+
alignedWith(DIAGONAL_VECTORS, DIAGONAL_DEVIATION_COSINE));
|
|
72
|
+
};
|
|
73
|
+
export const flingDecider = {
|
|
74
|
+
kind: "fling",
|
|
75
|
+
// Activating a fling is finishing it. Upstream overrides `activate()` to
|
|
76
|
+
// call `end()`; this is that, without a subclass to hang it on.
|
|
77
|
+
endsOnActivate: true,
|
|
78
|
+
/**
|
|
79
|
+
* The deadline. Unlike `Tap`'s it is not a "too slow to be a tap" rule about
|
|
80
|
+
* the press — it is the window inside which a fling has to happen at all,
|
|
81
|
+
* and it is the second of the two guards that keep a slow drag from ever
|
|
82
|
+
* qualifying.
|
|
83
|
+
*/
|
|
84
|
+
timer: () => ({
|
|
85
|
+
delay: DEFAULT_MAX_DURATION,
|
|
86
|
+
elapsed: "fail",
|
|
87
|
+
}),
|
|
88
|
+
/**
|
|
89
|
+
* Never from movement. Upstream's fling has no failure predicate over
|
|
90
|
+
* travel: a pointer wandering the wrong way has simply not flung yet, and it
|
|
91
|
+
* may still turn and fling before the deadline. What fails it is the timer,
|
|
92
|
+
* or lifting without having qualified (the `onRelease` below).
|
|
93
|
+
*/
|
|
94
|
+
shouldFail: () => false,
|
|
95
|
+
shouldActivate: (view, config) => {
|
|
96
|
+
// EXACT equality, in both directions, and against the high-water mark
|
|
97
|
+
// rather than the count right now — a fling is a statement about how many
|
|
98
|
+
// fingers made it.
|
|
99
|
+
if (view.maxPointerCount !==
|
|
100
|
+
(config.numberOfPointers ?? DEFAULT_NUMBER_OF_POINTERS)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (Math.hypot(view.velocityX, view.velocityY) <= DEFAULT_MIN_VELOCITY) {
|
|
104
|
+
// Strict, as upstream's `magnitude > this.minVelocity` is. This is the
|
|
105
|
+
// whole difference between a fling and a drag.
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return isAligned(view.velocityX, view.velocityY, config.direction ?? DEFAULT_DIRECTION);
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* The last chance, and then it is over.
|
|
112
|
+
*
|
|
113
|
+
* Upstream's `onUp` runs `tryEndFling()` one final time and calls `fail()`
|
|
114
|
+
* if it still does not qualify — so the release asks exactly the question a
|
|
115
|
+
* move would have asked, and the answer decides between END and FAILED. The
|
|
116
|
+
* velocity it reads is the last move's, which is upstream's too: neither
|
|
117
|
+
* platform re-measures anything at the moment a button comes up.
|
|
118
|
+
*/
|
|
119
|
+
onRelease: (view, config) => flingDecider.shouldActivate(view, config)
|
|
120
|
+
? { kind: "activate" }
|
|
121
|
+
: { kind: "fail" },
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=fling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fling.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/fling.ts"],"names":[],"mappings":"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","sourcesContent":["// `Gesture.Fling()` — a directional swipe, which is a VELOCITY predicate and\n// a direction predicate over the same machine everything else runs on.\n//\n// THE THING TO GET RIGHT IS THE VELOCITY, and it is the thing a naive test\n// does not catch: a fling is not \"the pointer travelled 200px to the right\".\n// A slow drag travels exactly as far. What tells them apart is how fast the\n// pointer was going when it got there, and upstream guards it twice —\n// `minVelocity` (700 units per second) as the criterion, and `maxDurationMs`\n// (800ms) as a hard deadline that fails the gesture whatever it is doing. A\n// leisurely drag across the same distance misses both.\n//\n// Restated from `src/web/handlers/FlingGestureHandler.ts` at 3.1.0, not\n// transcribed. Four details are worth naming because each is load-bearing and\n// none of them is obvious:\n//\n// - **the decision is made on every MOVE, not on the release.** Upstream\n// calls `tryEndFling()` from `onPointerMove`, so a fling activates the\n// instant the pointer is fast enough and pointed the right way, with the\n// button still down. The release is only the last chance;\n// - **activating IS ending.** `FlingGestureHandler.activate()` is overridden\n// to call `this.end()` immediately, so the progression is\n// BEGAN -> ACTIVE -> END in one synchronous breath and there is never an\n// `onUpdate`. See `RecognizerDecider.endsOnActivate`;\n// - **the direction is a bitmask and the diagonals come free.** A config of\n// `Directions.UP | Directions.RIGHT` sets both bits, so the internal\n// `UP_RIGHT` composite (5) also passes `(composite & config) === composite`\n// and is tested — with a WIDER cone, 60° against the axes' 30°. The two\n// cone widths tile the circle exactly: 4×30 + 4×60 = 360;\n// - **the pointer count is compared for EQUALITY**, against the most\n// pointers the interaction ever had at once. Upstream refuses a mismatch\n// in both directions, so a two-finger fling is not satisfied by one finger\n// and a one-finger fling is not satisfied by two.\n//\n// WHERE THIS PLATFORM'S VELOCITY DIFFERS FROM UPSTREAM'S, said plainly because\n// it is the number the whole gesture turns on. Upstream fits a second-degree\n// least-squares polynomial over up to 20 samples inside a 300ms horizon\n// (`VelocityTracker`) and takes the linear coefficient. This platform's\n// `velocityX`/`velocityY` are the last inter-event delta, which is what\n// `Pan().minVelocity()` has always used here and what every payload reports —\n// so `Fling` reads the same number its own event carries rather than a second,\n// better one nothing else can see. The consequence is that this fling is more\n// sensitive to a single long frame than upstream's; the 800ms deadline and the\n// alignment cone are unaffected, and docs/api.md records the difference.\nimport type {\n RecognizerDecider,\n RecognizerTimer,\n RecognizerView,\n} from \"./recognizer\"\nimport { DIAGONAL_DIRECTIONS, DIRECTIONS, type RecognizerConfig } from \"./types\"\n\n/** Upstream's `DEFAULT_MAX_DURATION_MS`: past this, the fling has failed. */\nexport const DEFAULT_MAX_DURATION = 800\n\n/** Upstream's `DEFAULT_MIN_VELOCITY`, in units per second. */\nexport const DEFAULT_MIN_VELOCITY = 700\n\n/** Upstream's `DEFAULT_DIRECTION`. */\nexport const DEFAULT_DIRECTION = DIRECTIONS.RIGHT\n\n/** Upstream's `DEFAULT_NUMBER_OF_TOUCHES_REQUIRED`. */\nexport const DEFAULT_NUMBER_OF_POINTERS = 1\n\n/** Upstream's `DEFAULT_ALIGNMENT_CONE`, in degrees. */\nexport const ALIGNMENT_CONE_DEGREES = 30\n\n/**\n * `coneToDeviation` from `src/web/utils.ts`: the cosine of HALF the cone, so\n * a 30° cone accepts everything within ±15° of the axis.\n */\nconst coneToDeviation = (degrees: number): number =>\n Math.cos((degrees / 2) * (Math.PI / 180))\n\n/** cos(15°) — the axial cone. */\nexport const AXIAL_DEVIATION_COSINE = coneToDeviation(ALIGNMENT_CONE_DEGREES)\n\n/** cos(30°) — the diagonal cone, which is the complement of the axial one. */\nexport const DIAGONAL_DEVIATION_COSINE = coneToDeviation(\n 90 - ALIGNMENT_CONE_DEGREES,\n)\n\n/**\n * Upstream's `MINIMAL_RECOGNIZABLE_MAGNITUDE`. Below it a vector has no\n * meaningful direction, and upstream's `Vector` zeroes the unit vector rather\n * than dividing by something near zero.\n */\nconst MINIMAL_RECOGNIZABLE_MAGNITUDE = 0.1\n\n/** The unit vector each direction bit stands for, in SCREEN coordinates. */\nconst DIRECTION_VECTORS: readonly (readonly [number, number, number])[] = [\n // [bit, x, y] — note that UP is negative Y, which is upstream's mapping and\n // the screen's rather than the maths convention.\n [DIRECTIONS.LEFT, -1, 0],\n [DIRECTIONS.RIGHT, 1, 0],\n [DIRECTIONS.UP, 0, -1],\n [DIRECTIONS.DOWN, 0, 1],\n]\n\nconst DIAGONAL_VECTORS: readonly (readonly [number, number, number])[] = [\n [DIAGONAL_DIRECTIONS.UP_RIGHT, 1, -1],\n [DIAGONAL_DIRECTIONS.DOWN_RIGHT, 1, 1],\n [DIAGONAL_DIRECTIONS.UP_LEFT, -1, -1],\n [DIAGONAL_DIRECTIONS.DOWN_LEFT, -1, 1],\n]\n\n/**\n * Whether the velocity points along any direction the config asked for.\n *\n * The similarity is a dot product of UNIT vectors, so it is the cosine of the\n * angle between them, and the comparison is strict — upstream's\n * `Vector.isSimilar` uses `>` rather than `>=`.\n */\nexport const isAligned = (\n velocityX: number,\n velocityY: number,\n direction: number,\n): boolean => {\n const magnitude = Math.hypot(velocityX, velocityY)\n if (magnitude <= MINIMAL_RECOGNIZABLE_MAGNITUDE) {\n // Upstream zeroes the unit vector here, which makes every dot product 0\n // and every alignment false. Stated directly rather than reproduced\n // through a zeroed vector, because a division by a near-zero magnitude is\n // the thing being avoided and this says so.\n return false\n }\n const unitX = velocityX / magnitude\n const unitY = velocityY / magnitude\n\n const alignedWith = (\n candidates: readonly (readonly [number, number, number])[],\n threshold: number,\n ): boolean =>\n candidates.some(([bit, x, y]) => {\n // Every bit of the candidate must be set in the config. For an axis that\n // is one bit; for a diagonal it is two, which is why `UP | RIGHT` opts\n // into the diagonal and `UP` alone does not.\n if ((bit & direction) !== bit) {\n return false\n }\n const length = Math.hypot(x, y)\n return unitX * (x / length) + unitY * (y / length) > threshold\n })\n\n return (\n alignedWith(DIRECTION_VECTORS, AXIAL_DEVIATION_COSINE) ||\n alignedWith(DIAGONAL_VECTORS, DIAGONAL_DEVIATION_COSINE)\n )\n}\n\nexport const flingDecider: RecognizerDecider = {\n kind: \"fling\",\n\n // Activating a fling is finishing it. Upstream overrides `activate()` to\n // call `end()`; this is that, without a subclass to hang it on.\n endsOnActivate: true,\n\n /**\n * The deadline. Unlike `Tap`'s it is not a \"too slow to be a tap\" rule about\n * the press — it is the window inside which a fling has to happen at all,\n * and it is the second of the two guards that keep a slow drag from ever\n * qualifying.\n */\n timer: (): RecognizerTimer => ({\n delay: DEFAULT_MAX_DURATION,\n elapsed: \"fail\",\n }),\n\n /**\n * Never from movement. Upstream's fling has no failure predicate over\n * travel: a pointer wandering the wrong way has simply not flung yet, and it\n * may still turn and fling before the deadline. What fails it is the timer,\n * or lifting without having qualified (the `onRelease` below).\n */\n shouldFail: (): boolean => false,\n\n shouldActivate: (view: RecognizerView, config: RecognizerConfig): boolean => {\n // EXACT equality, in both directions, and against the high-water mark\n // rather than the count right now — a fling is a statement about how many\n // fingers made it.\n if (\n view.maxPointerCount !==\n (config.numberOfPointers ?? DEFAULT_NUMBER_OF_POINTERS)\n ) {\n return false\n }\n if (Math.hypot(view.velocityX, view.velocityY) <= DEFAULT_MIN_VELOCITY) {\n // Strict, as upstream's `magnitude > this.minVelocity` is. This is the\n // whole difference between a fling and a drag.\n return false\n }\n return isAligned(\n view.velocityX,\n view.velocityY,\n config.direction ?? DEFAULT_DIRECTION,\n )\n },\n\n /**\n * The last chance, and then it is over.\n *\n * Upstream's `onUp` runs `tryEndFling()` one final time and calls `fail()`\n * if it still does not qualify — so the release asks exactly the question a\n * move would have asked, and the answer decides between END and FAILED. The\n * velocity it reads is the last move's, which is upstream's too: neither\n * platform re-measures anything at the moment a button comes up.\n */\n onRelease: (view: RecognizerView, config: RecognizerConfig) =>\n flingDecider.shouldActivate(view, config)\n ? ({ kind: \"activate\" } as const)\n : ({ kind: \"fail\" } as const),\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RecognizerDecider } from "./recognizer";
|
|
2
|
+
/**
|
|
3
|
+
* Upstream's documented default for `minForce`.
|
|
4
|
+
*
|
|
5
|
+
* A DOC COMMENT rather than a constant, and that is worth flagging: the `0.2`
|
|
6
|
+
* appears only in the JSDoc on `ForceTouchGestureConfig.minForce`
|
|
7
|
+
* (`src/handlers/ForceTouchGestureHandler.ts`), and no JavaScript in upstream
|
|
8
|
+
* assigns it — the real default lives in iOS code this repo cannot read. It is
|
|
9
|
+
* reproduced because a documented default is still upstream's answer, and
|
|
10
|
+
* inventing a different one would be a silent divergence.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_MIN_FORCE = 0.2;
|
|
13
|
+
export declare const forceTouchDecider: RecognizerDecider;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upstream's documented default for `minForce`.
|
|
3
|
+
*
|
|
4
|
+
* A DOC COMMENT rather than a constant, and that is worth flagging: the `0.2`
|
|
5
|
+
* appears only in the JSDoc on `ForceTouchGestureConfig.minForce`
|
|
6
|
+
* (`src/handlers/ForceTouchGestureHandler.ts`), and no JavaScript in upstream
|
|
7
|
+
* assigns it — the real default lives in iOS code this repo cannot read. It is
|
|
8
|
+
* reproduced because a documented default is still upstream's answer, and
|
|
9
|
+
* inventing a different one would be a silent divergence.
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_MIN_FORCE = 0.2;
|
|
12
|
+
export const forceTouchDecider = {
|
|
13
|
+
kind: "forceTouch",
|
|
14
|
+
// See the file header: the stylus gesture is not the pointer session, and a
|
|
15
|
+
// pressure report must not switch the native scroller off.
|
|
16
|
+
claimsResponder: false,
|
|
17
|
+
source: "stylus",
|
|
18
|
+
/**
|
|
19
|
+
* `maxForce` is a CEILING and exceeding it fails the gesture, which is
|
|
20
|
+
* upstream's documented behaviour ("If the pressure is greater, gesture
|
|
21
|
+
* fails"). Unset means no ceiling, which is upstream's shape too — there is
|
|
22
|
+
* no documented default for it.
|
|
23
|
+
*/
|
|
24
|
+
shouldFail: (view, config) => config.maxForce !== undefined && view.force > config.maxForce,
|
|
25
|
+
/**
|
|
26
|
+
* Non-strict, matching every other activation threshold in this module: a
|
|
27
|
+
* value sitting exactly on the bound activates rather than misses. The
|
|
28
|
+
* asymmetry with `shouldFail`'s strict comparison above is the same one
|
|
29
|
+
* `Pan` has and is deliberate in both.
|
|
30
|
+
*/
|
|
31
|
+
shouldActivate: (view, config) => view.force >= (config.minForce ?? DEFAULT_MIN_FORCE),
|
|
32
|
+
/**
|
|
33
|
+
* The ceiling keeps applying after activation, which is the same shape
|
|
34
|
+
* `LongPress`'s `maxDistance` has: pressing harder than `maxForce` is a
|
|
35
|
+
* cancellation of a gesture that was legitimately running, not a failure of
|
|
36
|
+
* one that never started.
|
|
37
|
+
*/
|
|
38
|
+
shouldCancelWhileActive: (view, config) => config.maxForce !== undefined && view.force > config.maxForce,
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=force-touch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"force-touch.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/force-touch.ts"],"names":[],"mappings":"AAoDA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAEpC,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,IAAI,EAAE,YAAY;IAElB,4EAA4E;IAC5E,2DAA2D;IAC3D,eAAe,EAAE,KAAK;IACtB,MAAM,EAAE,QAAQ;IAEhB;;;;;OAKG;IACH,UAAU,EAAE,CAAC,IAAoB,EAAE,MAAwB,EAAW,EAAE,CACtE,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ;IAE/D;;;;;OAKG;IACH,cAAc,EAAE,CAAC,IAAoB,EAAE,MAAwB,EAAW,EAAE,CAC1E,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IAEtD;;;;;OAKG;IACH,uBAAuB,EAAE,CACvB,IAAoB,EACpB,MAAwB,EACf,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ;CAC5E,CAAA","sourcesContent":["// `Gesture.ForceTouch()` — pressure, which is the one input in this module\n// that no ordinary mouse can produce.\n//\n// READ THIS FIRST, because it is the honest label on the tin: **the pressure\n// path is the least verified thing in this module**, and how far short it\n// falls is recorded in docs/api.md rather than left to be discovered. Every\n// other recognizer here is driven end to end by injected input in the test\n// suite. This one is driven by `GtkGestureStylus`, which needs a tablet tool,\n// and what could and could not be produced for it is written down rather than\n// implied.\n//\n// UPSTREAM DOES NOT IMPLEMENT THIS OFF iOS AT ALL, which is worth stating\n// before anything else, because it means there is no web behaviour to restate\n// and the semantics below come from the documented contract rather than from a\n// running implementation:\n//\n// - there is no `src/web/handlers/ForceTouchGestureHandler.ts`. The web\n// `Gestures` registry has nine entries and this is not one of them, so\n// `Gesture.ForceTouch()` under a `GestureDetector` on web throws\n// `\"ForceTouchGestureHandler is not supported on web\"` at handler-creation\n// time;\n// - the LEGACY component is worse and is the failure mode this repo refuses\n// by name: `PlatformConstants.forceTouchAvailable` is hardcoded false off\n// iOS, so `ForceTouchGestureHandler` resolves to a `ForceTouchFallback`\n// that logs one warning and renders its children unchanged — a component\n// that accepts its props, mounts, and silently does nothing;\n// - **there is no v3 hook.** `src/v3/hooks/gestures/` has nine directories\n// and no `forceTouch`; `useForceTouchGesture` does not exist and the\n// `SingleGesture` union omits ForceTouch entirely. Upstream dropped it\n// from the API it is migrating to.\n//\n// So the config below is upstream's documented contract — `minForce` (docs say\n// 0.2), `maxForce` (a ceiling that FAILS the gesture), `feedbackOnActivation`\n// (haptics) — and the enforcement is this file's, because upstream's lives in\n// Swift outside its own JS tree. Where a number had to be chosen rather than\n// read, it is named here and in docs/api.md.\n//\n// WHERE THE PRESSURE COMES FROM. `GtkGestureStylus`, whose `down`/`motion`/\n// `up`/`proximity` signals carry a `getAxis(Gdk.AxisUse.PRESSURE)` returning\n// `[known, value]`, already normalised to `[0, 1]` by GDK — which is\n// upstream's documented range for `minForce`/`maxForce`, so nothing is\n// rescaled on the way in. `wl_pointer` has no pressure axis and never will;\n// the tablet protocol (`zwp_tablet_v2`) does, and a stylus is the only device\n// on this platform that can answer.\n//\n// IT NEVER TAKES THE RESPONDER, same as `Hover` and the touchpad kinds and for\n// a related reason: the stylus gesture is its own GTK sequence, not the\n// pointer session the responder lock arbitrates, and a gesture reporting\n// pressure has no business suspending the scrollers under it.\nimport type { RecognizerDecider, RecognizerView } from \"./recognizer\"\nimport type { RecognizerConfig } from \"./types\"\n\n/**\n * Upstream's documented default for `minForce`.\n *\n * A DOC COMMENT rather than a constant, and that is worth flagging: the `0.2`\n * appears only in the JSDoc on `ForceTouchGestureConfig.minForce`\n * (`src/handlers/ForceTouchGestureHandler.ts`), and no JavaScript in upstream\n * assigns it — the real default lives in iOS code this repo cannot read. It is\n * reproduced because a documented default is still upstream's answer, and\n * inventing a different one would be a silent divergence.\n */\nexport const DEFAULT_MIN_FORCE = 0.2\n\nexport const forceTouchDecider: RecognizerDecider = {\n kind: \"forceTouch\",\n\n // See the file header: the stylus gesture is not the pointer session, and a\n // pressure report must not switch the native scroller off.\n claimsResponder: false,\n source: \"stylus\",\n\n /**\n * `maxForce` is a CEILING and exceeding it fails the gesture, which is\n * upstream's documented behaviour (\"If the pressure is greater, gesture\n * fails\"). Unset means no ceiling, which is upstream's shape too — there is\n * no documented default for it.\n */\n shouldFail: (view: RecognizerView, config: RecognizerConfig): boolean =>\n config.maxForce !== undefined && view.force > config.maxForce,\n\n /**\n * Non-strict, matching every other activation threshold in this module: a\n * value sitting exactly on the bound activates rather than misses. The\n * asymmetry with `shouldFail`'s strict comparison above is the same one\n * `Pan` has and is deliberate in both.\n */\n shouldActivate: (view: RecognizerView, config: RecognizerConfig): boolean =>\n view.force >= (config.minForce ?? DEFAULT_MIN_FORCE),\n\n /**\n * The ceiling keeps applying after activation, which is the same shape\n * `LongPress`'s `maxDistance` has: pressing harder than `maxForce` is a\n * cancellation of a gesture that was legitimately running, not a failure of\n * one that never started.\n */\n shouldCancelWhileActive: (\n view: RecognizerView,\n config: RecognizerConfig,\n ): boolean => config.maxForce !== undefined && view.force > config.maxForce,\n}\n"]}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type { AnyGestureSpec, ComposedGestureSpec, GestureEndEventPayload, GestureEventPayload, GestureHitSlop, GestureRef, GestureSpec, GestureTouchEvent, OffsetBound } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* The relations, in the hook spelling's names.
|
|
4
|
+
*
|
|
5
|
+
* The same three lists the builder's three methods write, renamed and moved
|
|
6
|
+
* into the config object — `simultaneousWithExternalGesture` is
|
|
7
|
+
* `simultaneousWith`, `requireExternalGestureToFail` is `requireToFail`, and
|
|
8
|
+
* `blocksExternalGesture` is `block`. One gesture or several, because
|
|
9
|
+
* upstream accepts both and an app writing one should not have to wrap it.
|
|
10
|
+
*/
|
|
11
|
+
type RelationHookConfig = {
|
|
12
|
+
simultaneousWith?: GestureRef | GestureRef[];
|
|
13
|
+
requireToFail?: GestureRef | GestureRef[];
|
|
14
|
+
block?: GestureRef | GestureRef[];
|
|
15
|
+
};
|
|
16
|
+
/** What every hook spelling accepts, which is upstream's `CommonGestureConfig`. */
|
|
17
|
+
type CommonGestureHookConfig = RelationHookConfig & {
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
hitSlop?: GestureHitSlop;
|
|
20
|
+
shouldCancelWhenOutside?: boolean;
|
|
21
|
+
manualActivation?: boolean;
|
|
22
|
+
runOnJS?: boolean;
|
|
23
|
+
testID?: string;
|
|
24
|
+
onBegin?: (event: GestureEventPayload) => void;
|
|
25
|
+
onActivate?: (event: GestureEventPayload) => void;
|
|
26
|
+
onDeactivate?: (event: GestureEndEventPayload) => void;
|
|
27
|
+
onFinalize?: (event: GestureEndEventPayload) => void;
|
|
28
|
+
onTouchesDown?: (event: GestureTouchEvent) => void;
|
|
29
|
+
onTouchesMove?: (event: GestureTouchEvent) => void;
|
|
30
|
+
onTouchesUp?: (event: GestureTouchEvent) => void;
|
|
31
|
+
onTouchesCancel?: (event: GestureTouchEvent) => void;
|
|
32
|
+
};
|
|
33
|
+
/** The config object `usePanGesture` accepts. */
|
|
34
|
+
export type PanGestureHookConfig = CommonGestureHookConfig & {
|
|
35
|
+
activeOffsetX?: OffsetBound;
|
|
36
|
+
activeOffsetY?: OffsetBound;
|
|
37
|
+
failOffsetX?: OffsetBound;
|
|
38
|
+
failOffsetY?: OffsetBound;
|
|
39
|
+
minDistance?: number;
|
|
40
|
+
minVelocity?: number;
|
|
41
|
+
minVelocityX?: number;
|
|
42
|
+
minVelocityY?: number;
|
|
43
|
+
minPointers?: number;
|
|
44
|
+
maxPointers?: number;
|
|
45
|
+
activateAfterLongPress?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Only a CONTINUOUS gesture has one. Upstream's discrete hooks omit
|
|
48
|
+
* `onUpdate` from their config type by name (`BaseDiscreteGestureConfig` is
|
|
49
|
+
* `Omit<…, "onUpdate">`), which is the same statement in the other
|
|
50
|
+
* direction.
|
|
51
|
+
*/
|
|
52
|
+
onUpdate?: (event: GestureEventPayload) => void;
|
|
53
|
+
};
|
|
54
|
+
/** The config object `useTapGesture` accepts, in upstream's external names. */
|
|
55
|
+
export type TapGestureHookConfig = CommonGestureHookConfig & {
|
|
56
|
+
numberOfTaps?: number;
|
|
57
|
+
maxDuration?: number;
|
|
58
|
+
maxDelay?: number;
|
|
59
|
+
maxDistance?: number;
|
|
60
|
+
maxDeltaX?: number;
|
|
61
|
+
maxDeltaY?: number;
|
|
62
|
+
minPointers?: number;
|
|
63
|
+
};
|
|
64
|
+
/** The config object `useLongPressGesture` accepts. */
|
|
65
|
+
export type LongPressGestureHookConfig = CommonGestureHookConfig & {
|
|
66
|
+
minDuration?: number;
|
|
67
|
+
maxDistance?: number;
|
|
68
|
+
numberOfPointers?: number;
|
|
69
|
+
};
|
|
70
|
+
/** The config object `useNativeGesture` accepts. */
|
|
71
|
+
export type NativeGestureHookConfig = CommonGestureHookConfig & {
|
|
72
|
+
shouldActivateOnStart?: boolean;
|
|
73
|
+
disallowInterruption?: boolean;
|
|
74
|
+
yieldsToContinuousGestures?: boolean;
|
|
75
|
+
/** A native view is continuous upstream, so it reports travel. */
|
|
76
|
+
onUpdate?: (event: GestureEventPayload) => void;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The config object `usePinchGesture` and `useRotationGesture` accept.
|
|
80
|
+
*
|
|
81
|
+
* Nothing of their own, and that is upstream's shape rather than an omission:
|
|
82
|
+
* `PinchGestureNativeProperties` and `RotationGestureNativeProperties` are
|
|
83
|
+
* both `Record<string, never>` in 3.1.0's `src/v3`, and the builder classes
|
|
84
|
+
* add no methods either. Both are continuous, so `onUpdate` is here.
|
|
85
|
+
*/
|
|
86
|
+
export type TouchpadGestureHookConfig = CommonGestureHookConfig & {
|
|
87
|
+
onUpdate?: (event: GestureEventPayload) => void;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* The hook spelling. Rebuilds its spec every render, exactly as the builder
|
|
91
|
+
* chained in a component body does, because the callbacks it closes over are
|
|
92
|
+
* rebuilt every render too — `GestureDetector` reads the config through a ref
|
|
93
|
+
* rather than resubscribing, which is what makes that free.
|
|
94
|
+
*/
|
|
95
|
+
export declare const usePanGesture: (config?: PanGestureHookConfig) => GestureSpec;
|
|
96
|
+
/**
|
|
97
|
+
* `useTapGesture`, the hook spelling of `Gesture.Tap()`.
|
|
98
|
+
*
|
|
99
|
+
* `shouldCancelWhenOutside` defaults to true here, matching the builder.
|
|
100
|
+
* Upstream's own hook does NOT do this even though its builder's constructor
|
|
101
|
+
* does and its native handler config does — `useLongPressGesture` remembers it
|
|
102
|
+
* (`transformLongPressProps`) and `useTapGesture` forgets. Two spellings of
|
|
103
|
+
* one gesture disagreeing about whether a press may wander off the view is a
|
|
104
|
+
* slip rather than a semantic, and reproducing it would make this module's own
|
|
105
|
+
* "two spellings, one implementation" claim false.
|
|
106
|
+
*/
|
|
107
|
+
export declare const useTapGesture: (config?: TapGestureHookConfig) => GestureSpec;
|
|
108
|
+
/** `useLongPressGesture`, the hook spelling of `Gesture.LongPress()`. */
|
|
109
|
+
export declare const useLongPressGesture: (config?: LongPressGestureHookConfig) => GestureSpec;
|
|
110
|
+
/** `useNativeGesture`, the hook spelling of `Gesture.Native()`. */
|
|
111
|
+
export declare const useNativeGesture: (config?: NativeGestureHookConfig) => GestureSpec;
|
|
112
|
+
/**
|
|
113
|
+
* `usePinchGesture`, the hook spelling of `Gesture.Pinch()` — and the spelling
|
|
114
|
+
* upstream's own `@deprecated` tag on `Gesture.Pinch()` points at.
|
|
115
|
+
*
|
|
116
|
+
* `shouldCancelWhenOutside` defaults to FALSE, matching the builder and
|
|
117
|
+
* matching `PinchGestureHandler.init`: a pinch is not addressed to a point the
|
|
118
|
+
* way a tap is, and a focal point that drifts off the view mid-gesture is not
|
|
119
|
+
* a reason to cancel it.
|
|
120
|
+
*/
|
|
121
|
+
export declare const usePinchGesture: (config?: TouchpadGestureHookConfig) => GestureSpec;
|
|
122
|
+
/** `useRotationGesture`, the hook spelling of `Gesture.Rotation()`. */
|
|
123
|
+
export declare const useRotationGesture: (config?: TouchpadGestureHookConfig) => GestureSpec;
|
|
124
|
+
/**
|
|
125
|
+
* The config object `useFlingGesture` accepts.
|
|
126
|
+
*
|
|
127
|
+
* No `onUpdate`, matching upstream: `FlingGestureInternalConfig` is a
|
|
128
|
+
* `BaseDiscreteGestureConfig`, which omits it by name. A fling activates and
|
|
129
|
+
* ends in one breath and has nothing to update with.
|
|
130
|
+
*/
|
|
131
|
+
export type FlingGestureHookConfig = CommonGestureHookConfig & {
|
|
132
|
+
direction?: number;
|
|
133
|
+
numberOfPointers?: number;
|
|
134
|
+
};
|
|
135
|
+
/** The config object `useManualGesture` accepts, which is only the common one. */
|
|
136
|
+
export type ManualGestureHookConfig = CommonGestureHookConfig & {
|
|
137
|
+
onUpdate?: (event: GestureEventPayload) => void;
|
|
138
|
+
};
|
|
139
|
+
/** The config object `useHoverGesture` accepts. */
|
|
140
|
+
export type HoverGestureHookConfig = CommonGestureHookConfig & {
|
|
141
|
+
/**
|
|
142
|
+
* iOS's own pointer effect. Upstream's hook maps `effect` onto the native
|
|
143
|
+
* `hoverEffect` prop; both names arrive at the same inert field here.
|
|
144
|
+
*/
|
|
145
|
+
effect?: number;
|
|
146
|
+
onUpdate?: (event: GestureEventPayload) => void;
|
|
147
|
+
};
|
|
148
|
+
/** `useFlingGesture`, the hook spelling of `Gesture.Fling()`. */
|
|
149
|
+
export declare const useFlingGesture: (config?: FlingGestureHookConfig) => GestureSpec;
|
|
150
|
+
/** `useManualGesture`, the hook spelling of `Gesture.Manual()`. */
|
|
151
|
+
export declare const useManualGesture: (config?: ManualGestureHookConfig) => GestureSpec;
|
|
152
|
+
/** `useHoverGesture`, the hook spelling of `Gesture.Hover()`. */
|
|
153
|
+
export declare const useHoverGesture: (config?: HoverGestureHookConfig) => GestureSpec;
|
|
154
|
+
export declare const useCompetingGestures: (...gestures: AnyGestureSpec[]) => ComposedGestureSpec;
|
|
155
|
+
export declare const useSimultaneousGestures: (...gestures: AnyGestureSpec[]) => ComposedGestureSpec;
|
|
156
|
+
export declare const useExclusiveGestures: (...gestures: AnyGestureSpec[]) => ComposedGestureSpec;
|
|
157
|
+
export {};
|