react-native-gtkx 0.3.0-alpha.1 → 0.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/adw/index.d.ts +3 -2
- package/dist/adw/index.js +21 -4
- package/dist/adw/index.js.map +1 -1
- package/dist/adw/widgets.generated.d.ts +1 -1
- package/dist/adw/widgets.generated.js +2 -2
- package/dist/adw/widgets.generated.js.map +1 -1
- package/dist/animated/create-animated.d.ts +2 -0
- package/dist/animated/create-animated.js +2 -0
- package/dist/animated/create-animated.js.map +1 -1
- package/dist/animated/event.d.ts +15 -0
- package/dist/animated/event.js +80 -0
- package/dist/animated/event.js.map +1 -0
- package/dist/animated/index.d.ts +4 -0
- package/dist/animated/index.js +8 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/spring.d.ts +10 -0
- package/dist/animated/spring.js +20 -6
- package/dist/animated/spring.js.map +1 -1
- package/dist/animated/timing.d.ts +10 -0
- package/dist/animated/timing.js +21 -13
- package/dist/animated/timing.js.map +1 -1
- package/dist/apis/host.gtkx.js +70 -11
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/common/navigation-stack.d.ts +6 -3
- package/dist/common/navigation-stack.js +8 -1
- package/dist/common/navigation-stack.js.map +1 -1
- package/dist/common/widget.js +2 -11
- package/dist/common/widget.js.map +1 -1
- package/dist/components/animated.d.ts +1 -0
- package/dist/components/animated.js +28 -4
- package/dist/components/animated.js.map +1 -1
- package/dist/components/app-registry.js +32 -8
- package/dist/components/app-registry.js.map +1 -1
- package/dist/components/request-animation-frame.d.ts +33 -0
- package/dist/components/request-animation-frame.js +83 -0
- package/dist/components/request-animation-frame.js.map +1 -0
- package/dist/components/scroll-view.js +60 -2
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/virtualized-list.js +1 -4
- package/dist/components/virtualized-list.js.map +1 -1
- package/dist/dnd/autoscroll.d.ts +44 -0
- package/dist/dnd/autoscroll.js +176 -0
- package/dist/dnd/autoscroll.js.map +1 -0
- package/dist/dnd/grid-order.d.ts +45 -0
- package/dist/dnd/grid-order.js +151 -0
- package/dist/dnd/grid-order.js.map +1 -0
- package/dist/dnd/grid.d.ts +44 -0
- package/dist/dnd/grid.js +397 -0
- package/dist/dnd/grid.js.map +1 -0
- package/dist/dnd/gtk-controllers.d.ts +16 -2
- package/dist/dnd/gtk-controllers.js +23 -3
- package/dist/dnd/gtk-controllers.js.map +1 -1
- package/dist/dnd/index.d.ts +4 -2
- package/dist/dnd/index.js +9 -2
- package/dist/dnd/index.js.map +1 -1
- package/dist/dnd/order-state.d.ts +14 -0
- package/dist/dnd/order-state.js +55 -0
- package/dist/dnd/order-state.js.map +1 -0
- package/dist/dnd/order.d.ts +19 -0
- package/dist/dnd/order.js +19 -0
- package/dist/dnd/order.js.map +1 -1
- package/dist/dnd/sortable.d.ts +29 -4
- package/dist/dnd/sortable.js +308 -115
- package/dist/dnd/sortable.js.map +1 -1
- package/dist/dnd/types.d.ts +236 -14
- package/dist/dnd/types.js +30 -0
- package/dist/dnd/types.js.map +1 -1
- package/dist/gesture-handler-compat/attach-context.d.ts +29 -0
- package/dist/gesture-handler-compat/attach-context.js +90 -0
- package/dist/gesture-handler-compat/attach-context.js.map +1 -0
- package/dist/gesture-handler-compat/detector-runtime.d.ts +14 -3
- package/dist/gesture-handler-compat/detector-runtime.js +15 -5
- package/dist/gesture-handler-compat/detector-runtime.js.map +1 -1
- package/dist/gesture-handler-compat/detector.js +57 -2
- package/dist/gesture-handler-compat/detector.js.map +1 -1
- package/dist/gesture-handler-compat/gesture-state-manager.d.ts +5 -0
- package/dist/gesture-handler-compat/gesture-state-manager.js +77 -0
- package/dist/gesture-handler-compat/gesture-state-manager.js.map +1 -0
- package/dist/gesture-handler-compat/index.d.ts +2 -2
- package/dist/gesture-handler-compat/index.js +38 -33
- package/dist/gesture-handler-compat/index.js.map +1 -1
- package/dist/gesture-handler-compat/recognizer.d.ts +12 -1
- package/dist/gesture-handler-compat/recognizer.js +23 -9
- package/dist/gesture-handler-compat/recognizer.js.map +1 -1
- package/dist/gesture-handler-compat/tag-registry.d.ts +14 -0
- package/dist/gesture-handler-compat/tag-registry.js +19 -0
- package/dist/gesture-handler-compat/tag-registry.js.map +1 -0
- package/dist/globals/index.d.ts +47 -0
- package/dist/globals/index.js +181 -0
- package/dist/globals/index.js.map +1 -0
- package/dist/globals/install.d.ts +1 -0
- package/dist/globals/install.js +14 -0
- package/dist/globals/install.js.map +1 -0
- package/dist/gtkx/bridge/adw-namespace.d.ts +2 -0
- package/dist/gtkx/bridge/adw-namespace.js +26 -0
- package/dist/gtkx/bridge/adw-namespace.js.map +1 -0
- package/dist/gtkx/bridge/adw.d.ts +23 -0
- package/dist/gtkx/bridge/adw.js +93 -0
- package/dist/gtkx/bridge/adw.js.map +1 -0
- package/dist/gtkx/bridge/color-scheme-parse.d.ts +11 -0
- package/dist/gtkx/bridge/color-scheme-parse.js +42 -0
- package/dist/gtkx/bridge/color-scheme-parse.js.map +1 -0
- package/dist/gtkx/bridge/color-scheme-portal.d.ts +24 -0
- package/dist/gtkx/bridge/color-scheme-portal.js +172 -0
- package/dist/gtkx/bridge/color-scheme-portal.js.map +1 -0
- package/dist/gtkx/bridge/core.d.ts +25 -0
- package/dist/gtkx/bridge/core.js +69 -0
- package/dist/gtkx/bridge/core.js.map +1 -0
- package/dist/gtkx/bridge/drag-layer.d.ts +27 -0
- package/dist/gtkx/bridge/drag-layer.js +177 -0
- package/dist/gtkx/bridge/drag-layer.js.map +1 -0
- package/dist/gtkx/bridge/index.d.ts +1 -27
- package/dist/gtkx/bridge/index.js +12 -71
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/widgets.generated.adw.d.ts +1 -0
- package/dist/gtkx/bridge/widgets.generated.adw.js +16 -0
- package/dist/gtkx/bridge/widgets.generated.adw.js.map +1 -0
- package/dist/gtkx/bridge/widgets.generated.d.ts +0 -1
- package/dist/gtkx/bridge/widgets.generated.js +3 -3
- package/dist/gtkx/bridge/widgets.generated.js.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +41 -20
- package/dist/mcp/data/generated.js +46 -20
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/metro/index.d.ts +1 -0
- package/dist/metro/index.js +12 -0
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/sidebar.js +2 -45
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/reanimated-compat/animatable-value.d.ts +158 -0
- package/dist/reanimated-compat/animatable-value.js +316 -0
- package/dist/reanimated-compat/animatable-value.js.map +1 -0
- package/dist/reanimated-compat/animation.d.ts +34 -13
- package/dist/reanimated-compat/animation.js +97 -25
- package/dist/reanimated-compat/animation.js.map +1 -1
- package/dist/reanimated-compat/mutable.js +6 -6
- package/dist/reanimated-compat/mutable.js.map +1 -1
- package/dist/reanimated-compat/updater-animations.js +32 -12
- package/dist/reanimated-compat/updater-animations.js.map +1 -1
- package/dist/runner/host-dev.js +5 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +9 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/vite/index.js +130 -0
- package/dist/vite/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/gtkx/bridge/theme.d.ts +0 -4
- package/dist/gtkx/bridge/theme.js +0 -5
- package/dist/gtkx/bridge/theme.js.map +0 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// The fallback attach seam: how a mounted gesture reaches a widget when
|
|
2
|
+
// `GestureDetector`'s immediate child does not forward one.
|
|
3
|
+
//
|
|
4
|
+
// THE GAP THIS CLOSES. `./detector.tsx`'s primary mechanism clones the
|
|
5
|
+
// recognizer's ref and handler props straight onto the child element —
|
|
6
|
+
// correct for a plain `View`, an `Animated.View`, or anything else that
|
|
7
|
+
// forwards a measure handle, which is every OTHER gesture surface on this
|
|
8
|
+
// platform (the gesture-detector gallery section, gorhom's sheet,
|
|
9
|
+
// reanimated-dnd). `react-native-sortables`'s v3 gesture-handler path put a
|
|
10
|
+
// different shape in front of it: `DraggableView` hands `GestureDetector` an
|
|
11
|
+
// `<ItemCell>` element, a plain composite that renders an `Animated.View` but
|
|
12
|
+
// forwards neither its own ref nor its unknown props onto it — so the merged
|
|
13
|
+
// ref is silently dropped and the ten responder props that ARE the touch
|
|
14
|
+
// chain never reach a widget at all. Confirmed by instrumenting a real drag
|
|
15
|
+
// in the built gallery (docs/research/upstream-libraries.md): zero
|
|
16
|
+
// `onTouchStart` calls, ever, for any grid item.
|
|
17
|
+
//
|
|
18
|
+
// WHY the child not forwarding a ref is not a bug on the library's side
|
|
19
|
+
// either. Upstream's own v3 `NativeDetector` does not reach through the
|
|
20
|
+
// child for this: it wraps it in its OWN native view, styled
|
|
21
|
+
// `display: "contents"` — a real host view for gesture attachment that adds
|
|
22
|
+
// no box of its own, so it does not disturb the child's layout. This
|
|
23
|
+
// platform's `display` is `"none" | "flex"` only (contracts.ts) — there is
|
|
24
|
+
// no equivalent primitive to reproduce that wrap, and a PLAIN wrapping `View`
|
|
25
|
+
// is not a substitute: react-native-sortables' items are positioned via an
|
|
26
|
+
// explicit `top`/`left` (first resolved by flex-wrap, later frozen to
|
|
27
|
+
// absolute coordinates) relative to the grid's own container, and inserting
|
|
28
|
+
// any REAL layout-participating box between that container and an item would
|
|
29
|
+
// either break the initial flex-wrap columns or — if made to fill its
|
|
30
|
+
// parent so the child's math still resolves — turn the wrapper into a
|
|
31
|
+
// grid-sized overlay that steals every OTHER item's touches too. Neither is
|
|
32
|
+
// acceptable, so this context reaches past the opaque composite via React
|
|
33
|
+
// CONTEXT instead of via a ref or a new widget.
|
|
34
|
+
//
|
|
35
|
+
// THE PROTOCOL. `GestureDetector` provides null while its direct, ref-based
|
|
36
|
+
// attachment is still being tried — every existing gesture surface never
|
|
37
|
+
// sees anything but null, so nothing about them changes. Only once a layout
|
|
38
|
+
// effect confirms the child produced no widget does it start providing the
|
|
39
|
+
// real value, and only this package's OWN host components consume it
|
|
40
|
+
// (`Animated.View` today): the first one encountered descending the tree
|
|
41
|
+
// claims it — registering its own already-existing widget as the gesture's
|
|
42
|
+
// handle and merging the handlers into its own responder registration — and
|
|
43
|
+
// re-provides null to ITS children, so nothing deeper claims a second time.
|
|
44
|
+
import { createContext, useContext } from "react";
|
|
45
|
+
/**
|
|
46
|
+
* Null everywhere except between a `GestureDetector` whose direct attachment
|
|
47
|
+
* failed and the first of this package's own components willing to claim it.
|
|
48
|
+
*/
|
|
49
|
+
export const GestureAttachContext = createContext(null);
|
|
50
|
+
export const useGestureAttach = () => useContext(GestureAttachContext);
|
|
51
|
+
/**
|
|
52
|
+
* The two responder props that answer a question rather than take an event.
|
|
53
|
+
* Canonical here rather than in ./detector-runtime (which re-exports it),
|
|
54
|
+
* because `mergeGestureHandlers` below needs it and this is a leaf module —
|
|
55
|
+
* a component using the fallback should not have to pull in the rest of the
|
|
56
|
+
* recognizer machinery (the orchestrator, the tag registry, every recognizer
|
|
57
|
+
* kind) just to merge two names' worth of predicate rules.
|
|
58
|
+
*/
|
|
59
|
+
export const PREDICATES = new Set([
|
|
60
|
+
"onStartShouldSetResponder",
|
|
61
|
+
"onMoveShouldSetResponder",
|
|
62
|
+
]);
|
|
63
|
+
/**
|
|
64
|
+
* Merges a gesture's handlers into a component's own responder props, the
|
|
65
|
+
* same rule `GestureDetector` applies when the child declares one of these
|
|
66
|
+
* itself: for the two that answer a question, either side saying yes is a
|
|
67
|
+
* yes; for the rest, both run.
|
|
68
|
+
*/
|
|
69
|
+
export const mergeGestureHandlers = (own, handlers) => {
|
|
70
|
+
const merged = { ...own };
|
|
71
|
+
for (const [name, gestureHandler] of Object.entries(handlers)) {
|
|
72
|
+
const ownHandler = own[name];
|
|
73
|
+
if (!ownHandler) {
|
|
74
|
+
merged[name] = gestureHandler;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
merged[name] = PREDICATES.has(name)
|
|
78
|
+
? (event) => {
|
|
79
|
+
const gestureWants = gestureHandler(event) === true;
|
|
80
|
+
const ownWants = ownHandler(event) === true;
|
|
81
|
+
return gestureWants || ownWants;
|
|
82
|
+
}
|
|
83
|
+
: (event) => {
|
|
84
|
+
gestureHandler(event);
|
|
85
|
+
ownHandler(event);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return merged;
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=attach-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach-context.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/attach-context.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,4DAA4D;AAC5D,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,0EAA0E;AAC1E,kEAAkE;AAClE,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,mEAAmE;AACnE,iDAAiD;AACjD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,6DAA6D;AAC7D,4EAA4E;AAC5E,qEAAqE;AACrE,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,sEAAsE;AACtE,4EAA4E;AAC5E,6EAA6E;AAC7E,sEAAsE;AACtE,sEAAsE;AACtE,4EAA4E;AAC5E,0EAA0E;AAC1E,gDAAgD;AAChD,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;AACzE,4EAA4E;AAC5E,2EAA2E;AAC3E,qEAAqE;AACrE,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAUjD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAA;AAE7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAyB,EAAE,CACzD,UAAU,CAAC,oBAAoB,CAAC,CAAA;AAElC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS;IACxC,2BAA2B;IAC3B,0BAA0B;CAC3B,CAAC,CAAA;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,GAAM,EACN,QAAmC,EAChC,EAAE;IACL,MAAM,MAAM,GAA4B,EAAE,GAAG,GAAG,EAAE,CAAA;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CACqB,CAAA;QAChD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAA;YAC7B,SAAQ;QACV,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE;gBACf,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,CAAA;gBACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI,CAAA;gBAC3C,OAAO,YAAY,IAAI,QAAQ,CAAA;YACjC,CAAC;YACH,CAAC,CAAC,CAAC,KAAY,EAAE,EAAE;gBACf,cAAc,CAAC,KAAK,CAAC,CAAA;gBACrB,UAAU,CAAC,KAAK,CAAC,CAAA;YACnB,CAAC,CAAA;IACP,CAAC;IACD,OAAO,MAAW,CAAA;AACpB,CAAC,CAAA","sourcesContent":["// The fallback attach seam: how a mounted gesture reaches a widget when\n// `GestureDetector`'s immediate child does not forward one.\n//\n// THE GAP THIS CLOSES. `./detector.tsx`'s primary mechanism clones the\n// recognizer's ref and handler props straight onto the child element —\n// correct for a plain `View`, an `Animated.View`, or anything else that\n// forwards a measure handle, which is every OTHER gesture surface on this\n// platform (the gesture-detector gallery section, gorhom's sheet,\n// reanimated-dnd). `react-native-sortables`'s v3 gesture-handler path put a\n// different shape in front of it: `DraggableView` hands `GestureDetector` an\n// `<ItemCell>` element, a plain composite that renders an `Animated.View` but\n// forwards neither its own ref nor its unknown props onto it — so the merged\n// ref is silently dropped and the ten responder props that ARE the touch\n// chain never reach a widget at all. Confirmed by instrumenting a real drag\n// in the built gallery (docs/research/upstream-libraries.md): zero\n// `onTouchStart` calls, ever, for any grid item.\n//\n// WHY the child not forwarding a ref is not a bug on the library's side\n// either. Upstream's own v3 `NativeDetector` does not reach through the\n// child for this: it wraps it in its OWN native view, styled\n// `display: \"contents\"` — a real host view for gesture attachment that adds\n// no box of its own, so it does not disturb the child's layout. This\n// platform's `display` is `\"none\" | \"flex\"` only (contracts.ts) — there is\n// no equivalent primitive to reproduce that wrap, and a PLAIN wrapping `View`\n// is not a substitute: react-native-sortables' items are positioned via an\n// explicit `top`/`left` (first resolved by flex-wrap, later frozen to\n// absolute coordinates) relative to the grid's own container, and inserting\n// any REAL layout-participating box between that container and an item would\n// either break the initial flex-wrap columns or — if made to fill its\n// parent so the child's math still resolves — turn the wrapper into a\n// grid-sized overlay that steals every OTHER item's touches too. Neither is\n// acceptable, so this context reaches past the opaque composite via React\n// CONTEXT instead of via a ref or a new widget.\n//\n// THE PROTOCOL. `GestureDetector` provides null while its direct, ref-based\n// attachment is still being tried — every existing gesture surface never\n// sees anything but null, so nothing about them changes. Only once a layout\n// effect confirms the child produced no widget does it start providing the\n// real value, and only this package's OWN host components consume it\n// (`Animated.View` today): the first one encountered descending the tree\n// claims it — registering its own already-existing widget as the gesture's\n// handle and merging the handlers into its own responder registration — and\n// re-provides null to ITS children, so nothing deeper claims a second time.\nimport { createContext, useContext } from \"react\"\nimport type { GestureResponderEvent } from \"../responder/types\"\n\nexport type GestureAttach = {\n /** The same callback ref `GestureDetector` would have put on its child. */\n assignHandle: (instance: unknown) => void\n /** The same recognizer props `GestureDetector` merges onto its child. */\n handlers: Record<string, (event: GestureResponderEvent) => boolean | void>\n}\n\n/**\n * Null everywhere except between a `GestureDetector` whose direct attachment\n * failed and the first of this package's own components willing to claim it.\n */\nexport const GestureAttachContext = createContext<GestureAttach | null>(null)\n\nexport const useGestureAttach = (): GestureAttach | null =>\n useContext(GestureAttachContext)\n\n/**\n * The two responder props that answer a question rather than take an event.\n * Canonical here rather than in ./detector-runtime (which re-exports it),\n * because `mergeGestureHandlers` below needs it and this is a leaf module —\n * a component using the fallback should not have to pull in the rest of the\n * recognizer machinery (the orchestrator, the tag registry, every recognizer\n * kind) just to merge two names' worth of predicate rules.\n */\nexport const PREDICATES = new Set<string>([\n \"onStartShouldSetResponder\",\n \"onMoveShouldSetResponder\",\n])\n\n/**\n * Merges a gesture's handlers into a component's own responder props, the\n * same rule `GestureDetector` applies when the child declares one of these\n * itself: for the two that answer a question, either side saying yes is a\n * yes; for the rest, both run.\n */\nexport const mergeGestureHandlers = <T extends Record<string, unknown>>(\n own: T,\n handlers: GestureAttach[\"handlers\"],\n): T => {\n const merged: Record<string, unknown> = { ...own }\n for (const [name, gestureHandler] of Object.entries(handlers)) {\n const ownHandler = own[name] as\n ((event: never) => boolean | void) | undefined\n if (!ownHandler) {\n merged[name] = gestureHandler\n continue\n }\n merged[name] = PREDICATES.has(name)\n ? (event: never) => {\n const gestureWants = gestureHandler(event) === true\n const ownWants = ownHandler(event) === true\n return gestureWants || ownWants\n }\n : (event: never) => {\n gestureHandler(event)\n ownHandler(event)\n }\n }\n return merged as T\n}\n"]}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { type Gtk as GtkNs } from "../gtkx/bridge/index";
|
|
2
2
|
import type { GestureResponderEvent } from "../responder/types";
|
|
3
|
+
import { PREDICATES } from "./attach-context";
|
|
3
4
|
import type { PreparedGesture } from "./composition";
|
|
4
5
|
import { type Recognizer } from "./recognizer";
|
|
5
6
|
import { type GestureKind, type GestureSpec } from "./types";
|
|
6
|
-
/**
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The two responder props that answer a question rather than take an event.
|
|
9
|
+
* Canonical in ./attach-context now (components/animated.tsx's fallback
|
|
10
|
+
* needs the same set without pulling in the rest of this file); re-exported
|
|
11
|
+
* here so ./detector.tsx's own import keeps working.
|
|
12
|
+
*/
|
|
13
|
+
export { PREDICATES };
|
|
8
14
|
/** A ref in either of React's two spellings. */
|
|
9
15
|
type AnyRef = ((instance: unknown) => void) | {
|
|
10
16
|
current: unknown;
|
|
@@ -34,6 +40,12 @@ export type DetectorRuntime = {
|
|
|
34
40
|
assignHandle: (instance: unknown) => void;
|
|
35
41
|
/** Called from a layout effect on every render. */
|
|
36
42
|
sync: (prepared: readonly PreparedGesture[], forwarded: AnyRef) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the child (reached directly, via the ref merged onto it) has
|
|
45
|
+
* produced a widget yet. False for a child that forwards no ref at all —
|
|
46
|
+
* see ./attach-context for what happens next.
|
|
47
|
+
*/
|
|
48
|
+
hasWidget: () => boolean;
|
|
37
49
|
/** Warns once if the child turned out to carry no widget. */
|
|
38
50
|
checkWidget: () => void;
|
|
39
51
|
/** Every mounted recognizer, in the order the gestures were written. */
|
|
@@ -41,4 +53,3 @@ export type DetectorRuntime = {
|
|
|
41
53
|
dispose: () => void;
|
|
42
54
|
};
|
|
43
55
|
export declare const createDetectorRuntime: () => DetectorRuntime;
|
|
44
|
-
export {};
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
import { widgetForHandle } from "../components/measure";
|
|
18
18
|
import { computePointInWindow, Gdk, Gtk, } from "../gtkx/bridge/index";
|
|
19
19
|
import { requestResponder } from "../responder/use-responder";
|
|
20
|
+
import { PREDICATES } from "./attach-context";
|
|
20
21
|
import { DECIDERS } from "./deciders";
|
|
21
22
|
import { gestureOrchestrator } from "./orchestrator";
|
|
22
23
|
import { createRecognizer, } from "./recognizer";
|
|
23
24
|
import { bindGestureTag, unbindGestureTag } from "./relations";
|
|
25
|
+
import { registerRecognizer, unregisterRecognizer } from "./tag-registry";
|
|
24
26
|
import { mintHandlerTag } from "./types";
|
|
25
27
|
/**
|
|
26
28
|
* The props a recognizer contributes, named once.
|
|
@@ -42,11 +44,13 @@ const HANDLER_NAMES = [
|
|
|
42
44
|
"onResponderRelease",
|
|
43
45
|
"onResponderTerminate",
|
|
44
46
|
];
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The two responder props that answer a question rather than take an event.
|
|
49
|
+
* Canonical in ./attach-context now (components/animated.tsx's fallback
|
|
50
|
+
* needs the same set without pulling in the rest of this file); re-exported
|
|
51
|
+
* here so ./detector.tsx's own import keeps working.
|
|
52
|
+
*/
|
|
53
|
+
export { PREDICATES };
|
|
50
54
|
let warnedWithoutWidget = false;
|
|
51
55
|
const warnNoWidget = () => {
|
|
52
56
|
if (warnedWithoutWidget) {
|
|
@@ -283,6 +287,9 @@ export const createDetectorRuntime = () => {
|
|
|
283
287
|
orchestrator: gestureOrchestrator,
|
|
284
288
|
}),
|
|
285
289
|
};
|
|
290
|
+
// Populated the instant a recognizer exists — this IS "at GestureDetector
|
|
291
|
+
// mount" for the gesture the tag belongs to. See ./tag-registry.
|
|
292
|
+
registerRecognizer(tag, gesture.recognizer);
|
|
286
293
|
return gesture;
|
|
287
294
|
};
|
|
288
295
|
const handlers = {};
|
|
@@ -341,6 +348,7 @@ export const createDetectorRuntime = () => {
|
|
|
341
348
|
}
|
|
342
349
|
for (const dropped of reusable) {
|
|
343
350
|
unbindGestureTag(dropped.spec);
|
|
351
|
+
unregisterRecognizer(dropped.tag);
|
|
344
352
|
detachController(dropped);
|
|
345
353
|
dropped.recognizer.dispose();
|
|
346
354
|
}
|
|
@@ -355,6 +363,7 @@ export const createDetectorRuntime = () => {
|
|
|
355
363
|
publish(handle);
|
|
356
364
|
}
|
|
357
365
|
},
|
|
366
|
+
hasWidget: () => widgetForHandle(handle) !== null,
|
|
358
367
|
checkWidget: () => {
|
|
359
368
|
if (widgetForHandle(handle) === null) {
|
|
360
369
|
warnNoWidget();
|
|
@@ -364,6 +373,7 @@ export const createDetectorRuntime = () => {
|
|
|
364
373
|
dispose: () => {
|
|
365
374
|
for (const gesture of mounted) {
|
|
366
375
|
unbindGestureTag(gesture.spec);
|
|
376
|
+
unregisterRecognizer(gesture.tag);
|
|
367
377
|
detachController(gesture);
|
|
368
378
|
gesture.recognizer.dispose();
|
|
369
379
|
}
|
|
@@ -1 +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"]}
|
|
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 { PREDICATES } from \"./attach-context\"\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 { registerRecognizer, unregisterRecognizer } from \"./tag-registry\"\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/**\n * The two responder props that answer a question rather than take an event.\n * Canonical in ./attach-context now (components/animated.tsx's fallback\n * needs the same set without pulling in the rest of this file); re-exported\n * here so ./detector.tsx's own import keeps working.\n */\nexport { PREDICATES }\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 /**\n * Whether the child (reached directly, via the ref merged onto it) has\n * produced a widget yet. False for a child that forwards no ref at all —\n * see ./attach-context for what happens next.\n */\n hasWidget: () => boolean\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 // Populated the instant a recognizer exists — this IS \"at GestureDetector\n // mount\" for the gesture the tag belongs to. See ./tag-registry.\n registerRecognizer(tag, gesture.recognizer)\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 unregisterRecognizer(dropped.tag)\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 hasWidget: () => widgetForHandle(handle) !== null,\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 unregisterRecognizer(gesture.tag)\n detachController(gesture)\n gesture.recognizer.dispose()\n }\n mounted = []\n },\n }\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
// `GestureDetector` — the one piece of the RNGH surface that survives
|
|
2
3
|
// upstream's own migration intact, and the only part of it that renders.
|
|
3
4
|
//
|
|
@@ -20,9 +21,30 @@
|
|
|
20
21
|
// measured against the gesture's own view, which is not necessarily the
|
|
21
22
|
// widget the event arrived on.
|
|
22
23
|
//
|
|
24
|
+
// WHEN THE CHILD FORWARDS NOTHING. The merge above assumes the child either
|
|
25
|
+
// IS a widget-backed component or forwards its ref to one — true for a plain
|
|
26
|
+
// `View`, an `Animated.View`, anything this package or an app writes by hand.
|
|
27
|
+
// `react-native-sortables`'s v3 gesture-handler path hands this component an
|
|
28
|
+
// opaque composite instead (`ItemCell`: renders an `Animated.View`, forwards
|
|
29
|
+
// neither its ref nor its own unknown props onto it), so the cloned ref is
|
|
30
|
+
// dropped and the merged handlers never reach a widget — confirmed by
|
|
31
|
+
// instrumenting a real drag in the built gallery: zero touches, ever
|
|
32
|
+
// (docs/research/upstream-libraries.md). Upstream does not hit this, because
|
|
33
|
+
// its own v3 detector does not reach through the child either — it wraps in
|
|
34
|
+
// its OWN `display: "contents"` native view, a primitive this platform's
|
|
35
|
+
// layout does not have (contracts.ts's `display` is "none" | "flex" only,
|
|
36
|
+
// and a plain wrapping box would break react-native-sortables' own absolute
|
|
37
|
+
// item positioning rather than fix it — see ./attach-context for the full
|
|
38
|
+
// account). So the fallback there is used here instead: try the direct ref
|
|
39
|
+
// first, and only once a layout effect confirms it produced nothing does
|
|
40
|
+
// this component start providing ./attach-context, letting one of this
|
|
41
|
+
// package's own components somewhere inside the child claim the gesture on
|
|
42
|
+
// ITS OWN widget instead.
|
|
43
|
+
//
|
|
23
44
|
// Everything mutable lives in ./detector-runtime, so nothing here reads or
|
|
24
45
|
// writes a ref while rendering.
|
|
25
46
|
import { cloneElement, isValidElement, useLayoutEffect, useState, } from "react";
|
|
47
|
+
import { GestureAttachContext } from "./attach-context";
|
|
26
48
|
import { prepareGestures } from "./composition";
|
|
27
49
|
import { createDetectorRuntime, PREDICATES } from "./detector-runtime";
|
|
28
50
|
import { isAnyGestureSpec } from "./types";
|
|
@@ -56,6 +78,18 @@ export const GestureDetector = ({ gesture, children, }) => {
|
|
|
56
78
|
// every render — the mounted detector is, and ./relations is what maps an
|
|
57
79
|
// app's gesture object onto the tag that identity minted.
|
|
58
80
|
const [runtime] = useState(createDetectorRuntime);
|
|
81
|
+
// The fallback attach value handed to ./attach-context, built once: its
|
|
82
|
+
// two fields are already stable for the runtime's whole life, so there is
|
|
83
|
+
// nothing to recompute on a later render.
|
|
84
|
+
const [attach] = useState(() => ({
|
|
85
|
+
assignHandle: runtime.assignHandle,
|
|
86
|
+
handlers: runtime.handlers,
|
|
87
|
+
}));
|
|
88
|
+
// False until a layout effect below finds the direct ref produced nothing.
|
|
89
|
+
// Never reset back to false: once a child needed the fallback it keeps
|
|
90
|
+
// needing it, and flipping back and forth on every render would detach and
|
|
91
|
+
// reattach the responder registration the fallback's own consumer made.
|
|
92
|
+
const [useFallback, setUseFallback] = useState(false);
|
|
59
93
|
// A composition is flattened to the recognizers it contains, each carrying
|
|
60
94
|
// the relations composition gave it. `Race`, `Simultaneous` and `Exclusive`
|
|
61
95
|
// do all of their work here and contribute no mechanism past this point.
|
|
@@ -74,8 +108,29 @@ export const GestureDetector = ({ gesture, children, }) => {
|
|
|
74
108
|
useLayoutEffect(() => runtime.dispose, [runtime]);
|
|
75
109
|
// A silent no-op is the failure this repo refuses. Checked after the child's
|
|
76
110
|
// own layout effects have run, which is where its `useImperativeHandle`
|
|
77
|
-
// publishes the handle.
|
|
111
|
+
// publishes the handle. The direct ref gets exactly one render to prove
|
|
112
|
+
// itself before the fallback engages — every child that forwards one
|
|
113
|
+
// (a plain View, an Animated.View, this package's own components) resolves
|
|
114
|
+
// synchronously within that same render's effects, so this never
|
|
115
|
+
// second-guesses a child that was going to work anyway.
|
|
116
|
+
//
|
|
117
|
+
// react-hooks/set-state-in-effect is disabled rather than worked around,
|
|
118
|
+
// the same call gtk/controllers.tsx's own `Controllers` already makes: the
|
|
119
|
+
// rule guards effects that derive state from PROPS, which belongs in render
|
|
120
|
+
// instead. This derives it from whether the child produced a widget, which
|
|
121
|
+
// does not exist until after the commit — an effect is the only place that
|
|
122
|
+
// can come from. `!useFallback` guards it, so it runs once and settles;
|
|
123
|
+
// there is no cascade for the rule to be protecting against. No dependency
|
|
124
|
+
// array is deliberate too, matching the `sync` effect above: every render
|
|
125
|
+
// re-checks, because a child that starts producing a widget only after a
|
|
126
|
+
// LATER render (an app's own delayed ref, say) should still be found.
|
|
127
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
128
|
useLayoutEffect(() => {
|
|
129
|
+
if (!useFallback && !runtime.hasWidget()) {
|
|
130
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
131
|
+
setUseFallback(true);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
79
134
|
runtime.checkWidget();
|
|
80
135
|
});
|
|
81
136
|
const merged = { ref: runtime.assignHandle };
|
|
@@ -99,6 +154,6 @@ export const GestureDetector = ({ gesture, children, }) => {
|
|
|
99
154
|
childHandler(event);
|
|
100
155
|
};
|
|
101
156
|
}
|
|
102
|
-
return cloneElement(children, merged);
|
|
157
|
+
return (_jsx(GestureAttachContext.Provider, { value: useFallback ? attach : null, children: cloneElement(children, merged) }));
|
|
103
158
|
};
|
|
104
159
|
//# sourceMappingURL=detector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/detector.tsx"],"names":[],"mappings":"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","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"]}
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/detector.tsx"],"names":[],"mappings":"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","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// WHEN THE CHILD FORWARDS NOTHING. The merge above assumes the child either\n// IS a widget-backed component or forwards its ref to one — true for a plain\n// `View`, an `Animated.View`, anything this package or an app writes by hand.\n// `react-native-sortables`'s v3 gesture-handler path hands this component an\n// opaque composite instead (`ItemCell`: renders an `Animated.View`, forwards\n// neither its ref nor its own unknown props onto it), so the cloned ref is\n// dropped and the merged handlers never reach a widget — confirmed by\n// instrumenting a real drag in the built gallery: zero touches, ever\n// (docs/research/upstream-libraries.md). Upstream does not hit this, because\n// its own v3 detector does not reach through the child either — it wraps in\n// its OWN `display: \"contents\"` native view, a primitive this platform's\n// layout does not have (contracts.ts's `display` is \"none\" | \"flex\" only,\n// and a plain wrapping box would break react-native-sortables' own absolute\n// item positioning rather than fix it — see ./attach-context for the full\n// account). So the fallback there is used here instead: try the direct ref\n// first, and only once a layout effect confirms it produced nothing does\n// this component start providing ./attach-context, letting one of this\n// package's own components somewhere inside the child claim the gesture on\n// ITS OWN widget instead.\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 { GestureAttachContext, type GestureAttach } from \"./attach-context\"\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 // The fallback attach value handed to ./attach-context, built once: its\n // two fields are already stable for the runtime's whole life, so there is\n // nothing to recompute on a later render.\n const [attach] = useState<GestureAttach>(() => ({\n assignHandle: runtime.assignHandle,\n handlers: runtime.handlers,\n }))\n // False until a layout effect below finds the direct ref produced nothing.\n // Never reset back to false: once a child needed the fallback it keeps\n // needing it, and flipping back and forth on every render would detach and\n // reattach the responder registration the fallback's own consumer made.\n const [useFallback, setUseFallback] = useState(false)\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. The direct ref gets exactly one render to prove\n // itself before the fallback engages — every child that forwards one\n // (a plain View, an Animated.View, this package's own components) resolves\n // synchronously within that same render's effects, so this never\n // second-guesses a child that was going to work anyway.\n //\n // react-hooks/set-state-in-effect is disabled rather than worked around,\n // the same call gtk/controllers.tsx's own `Controllers` already makes: the\n // rule guards effects that derive state from PROPS, which belongs in render\n // instead. This derives it from whether the child produced a widget, which\n // does not exist until after the commit — an effect is the only place that\n // can come from. `!useFallback` guards it, so it runs once and settles;\n // there is no cascade for the rule to be protecting against. No dependency\n // array is deliberate too, matching the `sync` effect above: every render\n // re-checks, because a child that starts producing a widget only after a\n // LATER render (an app's own delayed ref, say) should still be found.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n if (!useFallback && !runtime.hasWidget()) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setUseFallback(true)\n return\n }\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 (\n <GestureAttachContext.Provider value={useFallback ? attach : null}>\n {cloneElement(children, merged)}\n </GestureAttachContext.Provider>\n )\n}\n"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// `GestureStateManager` — upstream's standalone export, reversed 2026-08-05.
|
|
2
|
+
//
|
|
3
|
+
// The refusal this replaces (docs/api.md, "What stays refused") described
|
|
4
|
+
// upstream's OLD, deprecated shape: `GestureStateManager.create(tag)`, a
|
|
5
|
+
// factory returning a begin/activate/fail/end object looked up in a global
|
|
6
|
+
// `NodeManager`. That is not what `react-native-gesture-handler` 3.1.0
|
|
7
|
+
// exports under this name — its package entry re-exports `./v3`'s
|
|
8
|
+
// `GestureStateManager` (`src/v3/gestureStateManager.ts`), three STATIC
|
|
9
|
+
// methods keyed by tag: `activate`, `fail`, `deactivate`. The `.create()`
|
|
10
|
+
// factory survives only as `LegacyGestureStateManagerType`, a TYPE the
|
|
11
|
+
// package no longer exports a value for. Read from the installed package
|
|
12
|
+
// rather than assumed — the previous refusal was written against a shape
|
|
13
|
+
// upstream had already moved on from.
|
|
14
|
+
//
|
|
15
|
+
// react-native-sortables' v3 gesture-handler adapter calls exactly this
|
|
16
|
+
// shape (docs/research/upstream-libraries.md, "Wall 4, confirmed"):
|
|
17
|
+
// `GestureStateManager.activate(event.handlerTag)` from its own
|
|
18
|
+
// `onTouchesMove`, once a drag survives `dragActivationDelay`. That is the
|
|
19
|
+
// ordinary case for any real drag, not an edge one, and this platform's
|
|
20
|
+
// export used to throw on the property READ before the call could even
|
|
21
|
+
// happen. ./tag-registry is the new fact that makes the reversal possible —
|
|
22
|
+
// a numeric tag can now be turned back into the recognizer that minted it.
|
|
23
|
+
//
|
|
24
|
+
// EACH METHOD ROUTES THROUGH THE SAME MACHINERY `Gesture.Manual()` already
|
|
25
|
+
// uses: ./recognizer's `stateManager`, the very object handed to
|
|
26
|
+
// `onTouchesDown`/`onTouchesMove`/`onTouchesUp`/`onTouchesCancel`. Nothing
|
|
27
|
+
// new is built. `.activate()` is still a REQUEST through the ordinary
|
|
28
|
+
// arbitration loop — it can come back parked behind
|
|
29
|
+
// `requireExternalGestureToFail`, or cancelled — and calling any of the
|
|
30
|
+
// three on a gesture that is not BEGAN/ACTIVE (already active, already
|
|
31
|
+
// failed, already ended) is the same no-op ./recognizer's own state checks
|
|
32
|
+
// already produce for `Gesture.Manual()`'s app-driven calls. `deactivate` is
|
|
33
|
+
// upstream's name for what ./recognizer calls `end()`; both mean BEGAN or
|
|
34
|
+
// ACTIVE -> END, successfully.
|
|
35
|
+
import { recognizerForTag } from "./tag-registry";
|
|
36
|
+
const isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
|
|
37
|
+
/**
|
|
38
|
+
* A call naming a tag with no mounted recognizer behind it. Not thrown: a
|
|
39
|
+
* `Manual` gesture's own `.activate()`/`.fail()`/`.end()` already no-op when
|
|
40
|
+
* the state does not allow the transition, and a call arriving after its
|
|
41
|
+
* `GestureDetector` unmounted is the same kind of stale request. Warned
|
|
42
|
+
* rather than silent, because a tag that never resolves at all is more often
|
|
43
|
+
* a bug than a race.
|
|
44
|
+
*/
|
|
45
|
+
const warnUnknownTag = (method, handlerTag) => {
|
|
46
|
+
if (!isProduction) {
|
|
47
|
+
console.warn(`react-native-gtkx: GestureStateManager.${method}(${handlerTag}) named a handler tag ` +
|
|
48
|
+
"with no mounted GestureDetector. Ignored.");
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export const GestureStateManager = {
|
|
52
|
+
activate: (handlerTag) => {
|
|
53
|
+
const recognizer = recognizerForTag(handlerTag);
|
|
54
|
+
if (!recognizer) {
|
|
55
|
+
warnUnknownTag("activate", handlerTag);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
recognizer.stateManager.activate();
|
|
59
|
+
},
|
|
60
|
+
fail: (handlerTag) => {
|
|
61
|
+
const recognizer = recognizerForTag(handlerTag);
|
|
62
|
+
if (!recognizer) {
|
|
63
|
+
warnUnknownTag("fail", handlerTag);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
recognizer.stateManager.fail();
|
|
67
|
+
},
|
|
68
|
+
deactivate: (handlerTag) => {
|
|
69
|
+
const recognizer = recognizerForTag(handlerTag);
|
|
70
|
+
if (!recognizer) {
|
|
71
|
+
warnUnknownTag("deactivate", handlerTag);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
recognizer.stateManager.end();
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=gesture-state-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture-state-manager.js","sourceRoot":"","sources":["../../src/gesture-handler-compat/gesture-state-manager.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,uEAAuE;AACvE,kEAAkE;AAClE,wEAAwE;AACxE,0EAA0E;AAC1E,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,sCAAsC;AACtC,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,gEAAgE;AAChE,2EAA2E;AAC3E,wEAAwE;AACxE,uEAAuE;AACvE,4EAA4E;AAC5E,2EAA2E;AAC3E,EAAE;AACF,2EAA2E;AAC3E,iEAAiE;AACjE,2EAA2E;AAC3E,sEAAsE;AACtE,oDAAoD;AACpD,wEAAwE;AACxE,uEAAuE;AACvE,2EAA2E;AAC3E,6EAA6E;AAC7E,0EAA0E;AAC1E,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjD,MAAM,YAAY,GAChB,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAA;AAEzE;;;;;;;GAOG;AACH,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,UAAkB,EAAQ,EAAE;IAClE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CACV,0CAA0C,MAAM,IAAI,UAAU,wBAAwB;YACpF,2CAA2C,CAC9C,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ,EAAE,CAAC,UAAkB,EAAQ,EAAE;QACrC,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QACD,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAA;IACpC,CAAC;IAED,IAAI,EAAE,CAAC,UAAkB,EAAQ,EAAE;QACjC,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;YAClC,OAAM;QACR,CAAC;QACD,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAA;IAChC,CAAC;IAED,UAAU,EAAE,CAAC,UAAkB,EAAQ,EAAE;QACvC,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,cAAc,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;YACxC,OAAM;QACR,CAAC;QACD,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,CAAA;IAC/B,CAAC;CACF,CAAA","sourcesContent":["// `GestureStateManager` — upstream's standalone export, reversed 2026-08-05.\n//\n// The refusal this replaces (docs/api.md, \"What stays refused\") described\n// upstream's OLD, deprecated shape: `GestureStateManager.create(tag)`, a\n// factory returning a begin/activate/fail/end object looked up in a global\n// `NodeManager`. That is not what `react-native-gesture-handler` 3.1.0\n// exports under this name — its package entry re-exports `./v3`'s\n// `GestureStateManager` (`src/v3/gestureStateManager.ts`), three STATIC\n// methods keyed by tag: `activate`, `fail`, `deactivate`. The `.create()`\n// factory survives only as `LegacyGestureStateManagerType`, a TYPE the\n// package no longer exports a value for. Read from the installed package\n// rather than assumed — the previous refusal was written against a shape\n// upstream had already moved on from.\n//\n// react-native-sortables' v3 gesture-handler adapter calls exactly this\n// shape (docs/research/upstream-libraries.md, \"Wall 4, confirmed\"):\n// `GestureStateManager.activate(event.handlerTag)` from its own\n// `onTouchesMove`, once a drag survives `dragActivationDelay`. That is the\n// ordinary case for any real drag, not an edge one, and this platform's\n// export used to throw on the property READ before the call could even\n// happen. ./tag-registry is the new fact that makes the reversal possible —\n// a numeric tag can now be turned back into the recognizer that minted it.\n//\n// EACH METHOD ROUTES THROUGH THE SAME MACHINERY `Gesture.Manual()` already\n// uses: ./recognizer's `stateManager`, the very object handed to\n// `onTouchesDown`/`onTouchesMove`/`onTouchesUp`/`onTouchesCancel`. Nothing\n// new is built. `.activate()` is still a REQUEST through the ordinary\n// arbitration loop — it can come back parked behind\n// `requireExternalGestureToFail`, or cancelled — and calling any of the\n// three on a gesture that is not BEGAN/ACTIVE (already active, already\n// failed, already ended) is the same no-op ./recognizer's own state checks\n// already produce for `Gesture.Manual()`'s app-driven calls. `deactivate` is\n// upstream's name for what ./recognizer calls `end()`; both mean BEGAN or\n// ACTIVE -> END, successfully.\nimport { recognizerForTag } from \"./tag-registry\"\n\nconst isProduction =\n typeof process !== \"undefined\" && process.env.NODE_ENV === \"production\"\n\n/**\n * A call naming a tag with no mounted recognizer behind it. Not thrown: a\n * `Manual` gesture's own `.activate()`/`.fail()`/`.end()` already no-op when\n * the state does not allow the transition, and a call arriving after its\n * `GestureDetector` unmounted is the same kind of stale request. Warned\n * rather than silent, because a tag that never resolves at all is more often\n * a bug than a race.\n */\nconst warnUnknownTag = (method: string, handlerTag: number): void => {\n if (!isProduction) {\n console.warn(\n `react-native-gtkx: GestureStateManager.${method}(${handlerTag}) named a handler tag ` +\n \"with no mounted GestureDetector. Ignored.\",\n )\n }\n}\n\nexport const GestureStateManager = {\n activate: (handlerTag: number): void => {\n const recognizer = recognizerForTag(handlerTag)\n if (!recognizer) {\n warnUnknownTag(\"activate\", handlerTag)\n return\n }\n recognizer.stateManager.activate()\n },\n\n fail: (handlerTag: number): void => {\n const recognizer = recognizerForTag(handlerTag)\n if (!recognizer) {\n warnUnknownTag(\"fail\", handlerTag)\n return\n }\n recognizer.stateManager.fail()\n },\n\n deactivate: (handlerTag: number): void => {\n const recognizer = recognizerForTag(handlerTag)\n if (!recognizer) {\n warnUnknownTag(\"deactivate\", handlerTag)\n return\n }\n recognizer.stateManager.end()\n },\n}\n"]}
|
|
@@ -2,8 +2,9 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { StyleProp } from "../contracts";
|
|
3
3
|
import { Gesture } from "./builder";
|
|
4
4
|
import { GestureDetector } from "./detector";
|
|
5
|
+
import { GestureStateManager } from "./gesture-state-manager";
|
|
5
6
|
import { useCompetingGestures, useExclusiveGestures, useFlingGesture, useHoverGesture, useLongPressGesture, useManualGesture, useNativeGesture, usePanGesture, usePinchGesture, useRotationGesture, useSimultaneousGestures, useTapGesture } from "./hooks";
|
|
6
|
-
export { Gesture, GestureDetector, useCompetingGestures, useExclusiveGestures, useFlingGesture, useHoverGesture, useLongPressGesture, useManualGesture, useNativeGesture, usePanGesture, usePinchGesture, useRotationGesture, useSimultaneousGestures, useTapGesture, };
|
|
7
|
+
export { Gesture, GestureDetector, GestureStateManager, useCompetingGestures, useExclusiveGestures, useFlingGesture, useHoverGesture, useLongPressGesture, useManualGesture, useNativeGesture, usePanGesture, usePinchGesture, useRotationGesture, useSimultaneousGestures, useTapGesture, };
|
|
7
8
|
export { FlingGestureBuilder, ForceTouchGestureBuilder, HoverGestureBuilder, LongPressGestureBuilder, ManualGestureBuilder, NativeGestureBuilder, PanGestureBuilder, PinchGestureBuilder, RotationGestureBuilder, TapGestureBuilder, } from "./builder";
|
|
8
9
|
export type { GestureDetectorProps } from "./detector";
|
|
9
10
|
export type { FlingGestureHookConfig, HoverGestureHookConfig, LongPressGestureHookConfig, ManualGestureHookConfig, NativeGestureHookConfig, PanGestureHookConfig, TapGestureHookConfig, } from "./hooks";
|
|
@@ -35,7 +36,6 @@ export declare const RotationGestureHandler: any;
|
|
|
35
36
|
export declare const TapGestureHandler: any;
|
|
36
37
|
export declare const legacy_createNativeWrapper: any;
|
|
37
38
|
export declare const GestureDetectorType: any;
|
|
38
|
-
export declare const GestureStateManager: any;
|
|
39
39
|
export declare const InterceptingGestureDetector: any;
|
|
40
40
|
export declare const VirtualGestureDetector: any;
|
|
41
41
|
export declare const State: {
|