@hanzogui/native 7.0.0 → 7.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/cjs/gestureState.cjs +46 -26
  2. package/dist/cjs/gestureState.native.js +50 -29
  3. package/dist/cjs/gestureState.native.js.map +1 -1
  4. package/dist/cjs/setup-gesture-handler.cjs +3 -3
  5. package/dist/cjs/setup-gesture-handler.native.js +3 -3
  6. package/dist/cjs/setup-gesture-handler.native.js.map +1 -1
  7. package/dist/cjs/setup-safe-area.cjs +2 -27
  8. package/dist/cjs/setup-safe-area.native.js +8 -16
  9. package/dist/cjs/setup-safe-area.native.js.map +1 -1
  10. package/dist/esm/PressBoundary.mjs.map +1 -1
  11. package/dist/esm/gestureState.mjs +46 -26
  12. package/dist/esm/gestureState.mjs.map +1 -1
  13. package/dist/esm/gestureState.native.js +50 -29
  14. package/dist/esm/gestureState.native.js.map +1 -1
  15. package/dist/esm/setup-gesture-handler.mjs +3 -3
  16. package/dist/esm/setup-gesture-handler.mjs.map +1 -1
  17. package/dist/esm/setup-gesture-handler.native.js +3 -3
  18. package/dist/esm/setup-gesture-handler.native.js.map +1 -1
  19. package/dist/esm/setup-safe-area.mjs +1 -26
  20. package/dist/esm/setup-safe-area.mjs.map +1 -1
  21. package/dist/esm/setup-safe-area.native.js +8 -16
  22. package/dist/esm/setup-safe-area.native.js.map +1 -1
  23. package/package.json +26 -8
  24. package/src/PressBoundary.tsx +1 -1
  25. package/src/gestureState.ts +74 -36
  26. package/src/index.ts +1 -1
  27. package/src/setup-burnt.ts +1 -1
  28. package/src/setup-gesture-handler.ts +5 -5
  29. package/src/setup-keyboard-controller.ts +1 -1
  30. package/src/setup-safe-area.ts +2 -2
  31. package/src/setup-worklets.ts +1 -1
  32. package/src/setup-zeego.ts +1 -1
  33. package/types/PressBoundary.d.ts +1 -1
  34. package/types/PressBoundary.d.ts.map +1 -1
  35. package/types/gestureState.d.ts.map +2 -2
  36. package/types/index.d.ts +1 -1
  37. package/types/index.d.ts.map +1 -1
  38. package/types/setup-burnt.d.ts.map +1 -1
  39. package/types/setup-gesture-handler.d.ts +1 -1
  40. package/types/setup-gesture-handler.d.ts.map +1 -1
  41. package/types/setup-keyboard-controller.d.ts.map +1 -1
  42. package/types/setup-safe-area.d.ts.map +1 -1
  43. package/types/setup-worklets.d.ts.map +1 -1
  44. package/types/setup-zeego.d.ts.map +1 -1
  45. package/.turbo/turbo-build.log +0 -2
  46. package/gesture-handler/index.cjs +0 -1
  47. package/gesture-handler/index.js +0 -1
  48. package/gesture-handler/index.native.cjs +0 -1
  49. package/gesture-handler/index.native.js +0 -1
  50. package/setup-burnt/index.cjs +0 -2
  51. package/setup-burnt/index.js +0 -2
  52. package/setup-burnt/index.native.cjs +0 -2
  53. package/setup-burnt/index.native.js +0 -2
  54. package/setup-expo-linear-gradient/index.cjs +0 -2
  55. package/setup-expo-linear-gradient/index.js +0 -2
  56. package/setup-expo-linear-gradient/index.native.cjs +0 -2
  57. package/setup-expo-linear-gradient/index.native.js +0 -2
  58. package/setup-gesture-handler/index.cjs +0 -2
  59. package/setup-gesture-handler/index.js +0 -2
  60. package/setup-gesture-handler/index.native.cjs +0 -2
  61. package/setup-gesture-handler/index.native.js +0 -2
  62. package/setup-keyboard-controller/index.cjs +0 -2
  63. package/setup-keyboard-controller/index.js +0 -2
  64. package/setup-keyboard-controller/index.native.cjs +0 -2
  65. package/setup-keyboard-controller/index.native.js +0 -2
  66. package/setup-safe-area/index.cjs +0 -2
  67. package/setup-safe-area/index.js +0 -2
  68. package/setup-safe-area/index.native.cjs +0 -2
  69. package/setup-safe-area/index.native.js +0 -2
  70. package/setup-teleport/index.cjs +0 -2
  71. package/setup-teleport/index.js +0 -2
  72. package/setup-teleport/index.native.cjs +0 -2
  73. package/setup-teleport/index.native.js +0 -2
  74. package/setup-worklets/index.cjs +0 -2
  75. package/setup-worklets/index.js +0 -2
  76. package/setup-worklets/index.native.cjs +0 -2
  77. package/setup-worklets/index.native.js +0 -2
  78. package/setup-zeego/index.cjs +0 -2
  79. package/setup-zeego/index.js +0 -2
  80. package/setup-zeego/index.native.cjs +0 -2
  81. package/setup-zeego/index.native.js +0 -2
  82. package/tsconfig.json +0 -12
@@ -13,6 +13,21 @@ let externalPressDebugId = 0
13
13
 
14
14
  type PressOwnerSource = 'internal' | 'external' | null
15
15
 
16
+ function getEventPointerId(e: any): number | null {
17
+ const pointerId =
18
+ e?.pointerId ??
19
+ e?.pointer?.id ??
20
+ e?.event?.pointerId ??
21
+ e?.event?.pointer?.id ??
22
+ e?.nativeEvent?.pointerId ??
23
+ e?.nativeEvent?.id ??
24
+ e?.event?.nativeEvent?.pointerId ??
25
+ e?.event?.nativeEvent?.id ??
26
+ null
27
+
28
+ return pointerId == null || Number.isNaN(pointerId) ? null : Number(pointerId)
29
+ }
30
+
16
31
  /**
17
32
  * Global press coordination - ensures only innermost pressable fires press events,
18
33
  * matching RN Pressable/responder system semantics where deepest component wins.
@@ -23,6 +38,7 @@ const pressState = {
23
38
  owner: null as object | null,
24
39
  ownerId: null as number | null,
25
40
  ownerSource: null as PressOwnerSource,
41
+ ownerPointerId: null as number | null,
26
42
  timestamp: 0,
27
43
  }
28
44
 
@@ -57,6 +73,7 @@ function resetPressOwner() {
57
73
  pressState.owner = null
58
74
  pressState.ownerId = null
59
75
  pressState.ownerSource = null
76
+ pressState.ownerPointerId = null
60
77
  pressState.timestamp = 0
61
78
  }
62
79
 
@@ -74,8 +91,6 @@ export function claimExternalPressOwnership(
74
91
 
75
92
  const token = {}
76
93
  const ownerId = ++externalPressDebugId
77
- const previousOwnerId = pressState.ownerId
78
- const previousOwnerSource = pressState.ownerSource
79
94
 
80
95
  pressState.owner = token
81
96
  pressState.ownerId = ownerId
@@ -92,7 +107,6 @@ export function releaseExternalPressOwnership(
92
107
  if (!token || pressState.owner !== token) {
93
108
  return
94
109
  }
95
-
96
110
  resetPressOwner()
97
111
  }
98
112
 
@@ -121,30 +135,36 @@ export function getGestureHandler(): GestureHandlerAccessor {
121
135
  // unique token for this gesture instance - used to track ownership
122
136
  const myToken = {}
123
137
  const myDebugId = ++pressGestureDebugId
138
+ let didLongPress = false
139
+ let didPressIn = false
140
+ let pressInTimer: ReturnType<typeof setTimeout> | null = null
124
141
 
125
142
  // Grace period for child gestures to steal ownership from parent.
126
143
  // RNGH fires parent before child, but we want innermost to win.
127
144
  // Claims typically span a few ms, 24ms gives enough room to observe
128
145
  // ordering while debugging slower frames.
129
- const GRACE_PERIOD_MS = process.env.TAMAGUI_RNGH_PRESS_DELAY
130
- ? +process.env.TAMAGUI_RNGH_PRESS_DELAY
146
+ const GRACE_PERIOD_MS = process.env.GUI_RNGH_PRESS_DELAY
147
+ ? +process.env.GUI_RNGH_PRESS_DELAY
131
148
  : 24
132
149
 
133
- const tryClaimOwnership = () => {
150
+ const tryClaimOwnership = (e: any) => {
134
151
  const now = Date.now()
135
152
  resetStaleOwner(now, config.debugName)
136
153
 
137
- // within grace period, last claimer wins (child fires after parent)
138
- const withinGrace = now - pressState.timestamp < GRACE_PERIOD_MS
139
- const previousOwnerId = pressState.ownerId
140
- const previousOwnerSource = pressState.ownerSource
154
+ const currentPointerId = getEventPointerId(e)
155
+ const isSameTouchPointer =
156
+ currentPointerId == null ||
157
+ pressState.ownerPointerId == null ||
158
+ pressState.ownerPointerId === currentPointerId
159
+
141
160
  if (
142
161
  pressState.owner === null ||
143
- (withinGrace && pressState.ownerSource !== 'external')
162
+ (pressState.ownerSource === 'internal' && isSameTouchPointer)
144
163
  ) {
145
164
  pressState.owner = myToken
146
165
  pressState.ownerId = myDebugId
147
166
  pressState.ownerSource = 'internal'
167
+ pressState.ownerPointerId = currentPointerId
148
168
  pressState.timestamp = now
149
169
  }
150
170
  return pressState.owner === myToken
@@ -153,34 +173,64 @@ export function getGestureHandler(): GestureHandlerAccessor {
153
173
  const isOwner = () => pressState.owner === myToken
154
174
 
155
175
  const releaseOwnership = () => {
176
+ if (pressInTimer) {
177
+ clearTimeout(pressInTimer)
178
+ pressInTimer = null
179
+ }
156
180
  if (pressState.owner === myToken) {
157
181
  resetPressOwner()
158
182
  }
159
183
  }
160
184
 
185
+ const firePressIn = (e: any) => {
186
+ if (!didPressIn && isOwner()) {
187
+ didPressIn = true
188
+ config.onPressIn?.(e)
189
+ }
190
+ }
191
+
192
+ const schedulePressIn = (e: any) => {
193
+ if (pressInTimer) {
194
+ clearTimeout(pressInTimer)
195
+ }
196
+ pressInTimer = setTimeout(() => {
197
+ pressInTimer = null
198
+ if (isOwner()) {
199
+ firePressIn(e)
200
+ }
201
+ }, GRACE_PERIOD_MS + 1)
202
+ }
203
+
161
204
  // Tap gesture for regular presses
162
205
  // Use long maxDuration to not cancel during long presses
163
206
  const tap = Gesture.Tap()
164
207
  .runOnJS(true)
165
208
  .maxDuration(10000) // allow very long presses
166
- .onBegin((e: any) => {
167
- tryClaimOwnership()
168
- // defer onPressIn until after grace period to ensure we're the final owner
169
- setTimeout(() => {
170
- if (isOwner()) {
171
- config.onPressIn?.(e)
172
- }
173
- }, GRACE_PERIOD_MS + 1)
209
+ .onBegin((e: unknown) => {
210
+ didLongPress = false
211
+ didPressIn = false
212
+ tryClaimOwnership(e)
213
+ // Defer onPressIn until after the grace window so child pressables
214
+ // can steal ownership, but flush it on tap end for very fast taps.
215
+ schedulePressIn(e)
174
216
  })
175
- .onEnd((e: any) => {
176
- if (isOwner()) {
217
+ .onEnd((e: unknown) => {
218
+ if (isOwner() && !didLongPress) {
219
+ firePressIn(e)
177
220
  config.onPress?.(e)
178
221
  }
179
222
  })
180
- .onFinalize((e: any) => {
223
+ .onFinalize((e: unknown) => {
181
224
  if (isOwner()) {
182
225
  config.onPressOut?.(e)
183
226
  releaseOwnership()
227
+ } else if (didPressIn) {
228
+ // we already fired onPressIn but lost ownership before finalize
229
+ // (e.g. finger dragged onto a sibling pressable and that one
230
+ // claimed ownership). fire onPressOut so callers can clear their
231
+ // press state — otherwise pressStyle stays stuck on this view.
232
+ didPressIn = false
233
+ config.onPressOut?.(e)
184
234
  }
185
235
  })
186
236
 
@@ -193,25 +243,13 @@ export function getGestureHandler(): GestureHandlerAccessor {
193
243
  const longPress = Gesture.LongPress()
194
244
  .runOnJS(true)
195
245
  .minDuration(longPressDuration)
196
- .onBegin((e: any) => {
197
- tryClaimOwnership()
198
- setTimeout(() => {
199
- if (isOwner()) {
200
- config.onPressIn?.(e)
201
- }
202
- }, GRACE_PERIOD_MS + 1)
203
- })
204
246
  .onStart((e: any) => {
247
+ didLongPress = true
205
248
  if (isOwner()) {
249
+ firePressIn(e)
206
250
  config.onLongPress?.(e)
207
251
  }
208
252
  })
209
- .onFinalize((e: any) => {
210
- if (isOwner()) {
211
- config.onPressOut?.(e)
212
- releaseOwnership()
213
- }
214
- })
215
253
 
216
254
  if (config.hitSlop) longPress.hitSlop(config.hitSlop)
217
255
 
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@
13
13
  * import '@hanzogui/native/expo-linear-gradient'
14
14
  * import '@hanzogui/native/setup-keyboard-controller'
15
15
  *
16
- * // Then use GUI components normally
16
+ * // Then use Gui components normally
17
17
  * // Sheet will automatically use native gestures when available
18
18
  * // LinearGradient will use expo-linear-gradient when installed
19
19
  * ```
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup burnt for GUI native toasts.
2
+ * Setup burnt for Gui native toasts.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup gesture handler for Tamagui native components.
2
+ * Setup gesture handler for Gui native components.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -20,7 +20,7 @@
20
20
  import { getGestureHandler } from './gestureState'
21
21
 
22
22
  export interface GestureHandlerConfig {
23
- /** use RNGH for press events on Tamagui components (default: true) */
23
+ /** use RNGH for press events on Gui components (default: true) */
24
24
  pressEvents?: boolean
25
25
  /** use RNGH for Sheet drag gestures (default: true) */
26
26
  sheet?: boolean
@@ -44,8 +44,8 @@ export function setupGestureHandler(config?: GestureHandlerConfig): void {
44
44
  }
45
45
 
46
46
  // allow re-running setup to change config
47
- const isFirstRun = !g.__tamagui_native_gesture_setup_complete
48
- g.__tamagui_native_gesture_setup_complete = true
47
+ const isFirstRun = !g.__gui_native_gesture_setup_complete
48
+ g.__gui_native_gesture_setup_complete = true
49
49
 
50
50
  try {
51
51
  // dynamically require RNGH - it should already be imported by the app
@@ -62,7 +62,7 @@ export function setupGestureHandler(config?: GestureHandlerConfig): void {
62
62
  })
63
63
 
64
64
  // sheet state - only enable if sheet is true
65
- g.__tamagui_sheet_gesture_state__ = {
65
+ g.__gui_sheet_gesture_state__ = {
66
66
  enabled: currentConfig.sheet !== false,
67
67
  Gesture,
68
68
  GestureDetector,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup keyboard controller for GUI native components.
2
+ * Setup keyboard controller for Gui native components.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup react-native-safe-area-context for GUI native components.
2
+ * Setup react-native-safe-area-context for Gui native components.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -9,7 +9,7 @@
9
9
  * ```
10
10
  *
11
11
  * This automatically detects and configures react-native-safe-area-context
12
- * for use with GUI components that need safe area awareness.
12
+ * for use with Gui components that need safe area awareness.
13
13
  *
14
14
  * Note: You must still wrap your app with SafeAreaProvider yourself:
15
15
  * ```tsx
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup worklets for GUI native components.
2
+ * Setup worklets for Gui native components.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Setup zeego for GUI native menus.
2
+ * Setup zeego for Gui native menus.
3
3
  *
4
4
  * Simply import this module at the top of your app entry point:
5
5
  *
@@ -3,7 +3,7 @@ import { View, type ViewProps } from "react-native";
3
3
  export interface PressBoundaryProps extends ViewProps {
4
4
  enabled?: boolean;
5
5
  /**
6
- * Alias for enabling the boundary. The behavior is limited to Tamagui's
6
+ * Alias for enabling the boundary. The behavior is limited to Gui's
7
7
  * shared press ownership and does not patch arbitrary RN bubbling.
8
8
  */
9
9
  stopPropagation?: boolean;
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "import React from 'react'\nimport { View, type ViewProps } from 'react-native'\nimport {\n claimExternalPressOwnership,\n releaseExternalPressOwnership,\n type ExternalPressOwnershipToken,\n} from './gestureState'\n\nexport interface PressBoundaryProps extends ViewProps {\n enabled?: boolean\n /**\n * Alias for enabling the boundary. The behavior is limited to Tamagui's\n * shared press ownership and does not patch arbitrary RN bubbling.\n */\n stopPropagation?: boolean\n debugName?: string | null\n}\n\nfunction composeFirst<T extends (...args: any[]) => void>(ours: T, theirs?: T) {\n return (...args: Parameters<T>) => {\n ours(...args)\n theirs?.(...args)\n }\n}\n\nfunction composeLast<T extends (...args: any[]) => void>(theirs: T | undefined, ours: T) {\n return (...args: Parameters<T>) => {\n theirs?.(...args)\n ours(...args)\n }\n}\n\nexport const PressBoundary: React.ForwardRefExoticComponent<\n PressBoundaryProps & React.RefAttributes<View>\n> = React.forwardRef<View, PressBoundaryProps>(function PressBoundary(\n {\n enabled,\n stopPropagation,\n debugName,\n onTouchStart,\n onTouchEnd,\n onTouchCancel,\n onResponderGrant,\n onResponderRelease,\n onResponderTerminate,\n ...props\n },\n forwardedRef\n) {\n const tokenRef = React.useRef<ExternalPressOwnershipToken | null>(null)\n const isEnabled = enabled ?? stopPropagation ?? true\n\n const claim = React.useCallback((): void => {\n if (!isEnabled) return\n if (tokenRef.current) {\n releaseExternalPressOwnership(tokenRef.current, debugName)\n }\n tokenRef.current = claimExternalPressOwnership(debugName)\n }, [debugName, isEnabled])\n\n const release = React.useCallback((): void => {\n if (!tokenRef.current) return\n releaseExternalPressOwnership(tokenRef.current, debugName)\n tokenRef.current = null\n }, [debugName])\n\n React.useEffect(() => release, [release])\n\n return (\n <View\n ref={forwardedRef}\n {...props}\n onTouchStart={composeFirst(claim, onTouchStart)}\n onTouchEnd={composeLast(onTouchEnd, release)}\n onTouchCancel={composeLast(onTouchCancel, release)}\n onResponderGrant={composeFirst(claim, onResponderGrant)}\n onResponderRelease={composeLast(onResponderRelease, release)}\n onResponderTerminate={composeLast(onResponderTerminate, release)}\n />\n )\n})\n"
9
+ "import React from 'react'\nimport { View, type ViewProps } from 'react-native'\nimport {\n claimExternalPressOwnership,\n releaseExternalPressOwnership,\n type ExternalPressOwnershipToken,\n} from './gestureState'\n\nexport interface PressBoundaryProps extends ViewProps {\n enabled?: boolean\n /**\n * Alias for enabling the boundary. The behavior is limited to Gui's\n * shared press ownership and does not patch arbitrary RN bubbling.\n */\n stopPropagation?: boolean\n debugName?: string | null\n}\n\nfunction composeFirst<T extends (...args: any[]) => void>(ours: T, theirs?: T) {\n return (...args: Parameters<T>) => {\n ours(...args)\n theirs?.(...args)\n }\n}\n\nfunction composeLast<T extends (...args: any[]) => void>(theirs: T | undefined, ours: T) {\n return (...args: Parameters<T>) => {\n theirs?.(...args)\n ours(...args)\n }\n}\n\nexport const PressBoundary: React.ForwardRefExoticComponent<\n PressBoundaryProps & React.RefAttributes<View>\n> = React.forwardRef<View, PressBoundaryProps>(function PressBoundary(\n {\n enabled,\n stopPropagation,\n debugName,\n onTouchStart,\n onTouchEnd,\n onTouchCancel,\n onResponderGrant,\n onResponderRelease,\n onResponderTerminate,\n ...props\n },\n forwardedRef\n) {\n const tokenRef = React.useRef<ExternalPressOwnershipToken | null>(null)\n const isEnabled = enabled ?? stopPropagation ?? true\n\n const claim = React.useCallback((): void => {\n if (!isEnabled) return\n if (tokenRef.current) {\n releaseExternalPressOwnership(tokenRef.current, debugName)\n }\n tokenRef.current = claimExternalPressOwnership(debugName)\n }, [debugName, isEnabled])\n\n const release = React.useCallback((): void => {\n if (!tokenRef.current) return\n releaseExternalPressOwnership(tokenRef.current, debugName)\n tokenRef.current = null\n }, [debugName])\n\n React.useEffect(() => release, [release])\n\n return (\n <View\n ref={forwardedRef}\n {...props}\n onTouchStart={composeFirst(claim, onTouchStart)}\n onTouchEnd={composeLast(onTouchEnd, release)}\n onTouchCancel={composeLast(onTouchCancel, release)}\n onResponderGrant={composeFirst(claim, onResponderGrant)}\n onResponderRelease={composeLast(onResponderRelease, release)}\n onResponderTerminate={composeLast(onResponderTerminate, release)}\n />\n )\n})\n"
10
10
  ]
11
11
  }
@@ -1,11 +1,11 @@
1
1
  {
2
- "mappings": "AACA,cAAc,oBAAoB;AA2BlC,iBAAiB,OAAO;CACtB;CACA;CACA;CACA;;AAGF,YAAY,qBAAqB;CAC/B;CACA,aAAa;CACb,cAAc;CACd,WAAW;CACX,eAAe;CACf;CACA,mBAAmB;;AAGrB,iBAAiB,uBAAuB;UAC7B;UACA,OAAO;CAChB,IAAI,SAAS,QAAQ;CACrB;CACA,mBAAmB,QAAQ;;AAG7B,YAAY;AAeZ,OAAO,iBAAS,4BACd,4BACC;AAiBH,OAAO,iBAAS,8BACd,OAAO,gDACP;AASF,OAAO,iBAAS,qBAAqB",
2
+ "mappings": "AACA,cAAc,oBAAoB;AA2ClC,iBAAiB,OAAO;CACtB;CACA;CACA;CACA;;AAGF,YAAY,qBAAqB;CAC/B;CACA,aAAa;CACb,cAAc;CACd,WAAW;CACX,eAAe;CACf;CACA,mBAAmB;;AAGrB,iBAAiB,uBAAuB;UAC7B;UACA,OAAO;CAChB,IAAI,SAAS,QAAQ;CACrB;CACA,mBAAmB,QAAQ;;AAG7B,YAAY;AAgBZ,OAAO,iBAAS,4BACd,4BACC;AAeH,OAAO,iBAAS,8BACd,OAAO,gDACP;AAQF,OAAO,iBAAS,qBAAqB",
3
3
  "names": [],
4
4
  "sources": [
5
5
  "src/gestureState.ts"
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "import { createGlobalState } from './globalState'\nimport type { GestureState } from './types'\n\nconst state = createGlobalState<GestureState>(`gesture`, {\n enabled: false,\n Gesture: null,\n GestureDetector: null,\n ScrollView: null,\n})\n\nlet pressGestureDebugId = 0\nlet externalPressDebugId = 0\n\ntype PressOwnerSource = 'internal' | 'external' | null\n\n/**\n * Global press coordination - ensures only innermost pressable fires press events,\n * matching RN Pressable/responder system semantics where deepest component wins.\n * Uses a grace period to allow child gestures to steal ownership from parent,\n * since RNGH fires parent gestures before child gestures.\n */\nconst pressState = {\n owner: null as object | null,\n ownerId: null as number | null,\n ownerSource: null as PressOwnerSource,\n timestamp: 0,\n}\n\nexport interface Insets {\n top?: number\n left?: number\n bottom?: number\n right?: number\n}\n\nexport type PressGestureConfig = {\n debugName?: string | null\n onPressIn?: (e: any) => void\n onPressOut?: (e: any) => void\n onPress?: (e: any) => void\n onLongPress?: (e: any) => void\n delayLongPress?: number\n hitSlop?: number | Insets | null\n}\n\nexport interface GestureHandlerAccessor {\n readonly isEnabled: boolean\n readonly state: GestureState\n set(updates: Partial<GestureState>): void\n disable(): void\n createPressGesture(config: PressGestureConfig): any\n}\n\nexport type ExternalPressOwnershipToken = object\n\nfunction resetPressOwner() {\n pressState.owner = null\n pressState.ownerId = null\n pressState.ownerSource = null\n pressState.timestamp = 0\n}\n\nfunction resetStaleOwner(now: number, debugName?: string | null) {\n if (now - pressState.timestamp > 2000) {\n resetPressOwner()\n }\n}\n\nexport function claimExternalPressOwnership(\n debugName?: string | null\n): ExternalPressOwnershipToken {\n const now = Date.now()\n resetStaleOwner(now, debugName)\n\n const token = {}\n const ownerId = ++externalPressDebugId\n const previousOwnerId = pressState.ownerId\n const previousOwnerSource = pressState.ownerSource\n\n pressState.owner = token\n pressState.ownerId = ownerId\n pressState.ownerSource = 'external'\n pressState.timestamp = now\n\n return token\n}\n\nexport function releaseExternalPressOwnership(\n token: ExternalPressOwnershipToken | null | undefined,\n debugName?: string | null\n): void {\n if (!token || pressState.owner !== token) {\n return\n }\n\n resetPressOwner()\n}\n\nexport function getGestureHandler(): GestureHandlerAccessor {\n return {\n get isEnabled(): boolean {\n return state.get().enabled\n },\n get state(): GestureState {\n return state.get()\n },\n set(updates: Partial<GestureState>): void {\n Object.assign(state.get(), updates)\n },\n\n disable(): void {\n state.get().enabled = false\n },\n\n createPressGesture(config: PressGestureConfig): any {\n const { Gesture } = state.get()\n if (!Gesture) return null\n\n const longPressDuration = config.delayLongPress ?? 500\n\n // unique token for this gesture instance - used to track ownership\n const myToken = {}\n const myDebugId = ++pressGestureDebugId\n\n // Grace period for child gestures to steal ownership from parent.\n // RNGH fires parent before child, but we want innermost to win.\n // Claims typically span a few ms, 24ms gives enough room to observe\n // ordering while debugging slower frames.\n const GRACE_PERIOD_MS = process.env.TAMAGUI_RNGH_PRESS_DELAY\n ? +process.env.TAMAGUI_RNGH_PRESS_DELAY\n : 24\n\n const tryClaimOwnership = () => {\n const now = Date.now()\n resetStaleOwner(now, config.debugName)\n\n // within grace period, last claimer wins (child fires after parent)\n const withinGrace = now - pressState.timestamp < GRACE_PERIOD_MS\n const previousOwnerId = pressState.ownerId\n const previousOwnerSource = pressState.ownerSource\n if (\n pressState.owner === null ||\n (withinGrace && pressState.ownerSource !== 'external')\n ) {\n pressState.owner = myToken\n pressState.ownerId = myDebugId\n pressState.ownerSource = 'internal'\n pressState.timestamp = now\n }\n return pressState.owner === myToken\n }\n\n const isOwner = () => pressState.owner === myToken\n\n const releaseOwnership = () => {\n if (pressState.owner === myToken) {\n resetPressOwner()\n }\n }\n\n // Tap gesture for regular presses\n // Use long maxDuration to not cancel during long presses\n const tap = Gesture.Tap()\n .runOnJS(true)\n .maxDuration(10000) // allow very long presses\n .onBegin((e: any) => {\n tryClaimOwnership()\n // defer onPressIn until after grace period to ensure we're the final owner\n setTimeout(() => {\n if (isOwner()) {\n config.onPressIn?.(e)\n }\n }, GRACE_PERIOD_MS + 1)\n })\n .onEnd((e: any) => {\n if (isOwner()) {\n config.onPress?.(e)\n }\n })\n .onFinalize((e: any) => {\n if (isOwner()) {\n config.onPressOut?.(e)\n releaseOwnership()\n }\n })\n\n if (config.hitSlop) tap.hitSlop(config.hitSlop)\n\n // if no long press handler, just use tap\n if (!config.onLongPress) return tap\n\n // LongPress gesture for long press handling\n const longPress = Gesture.LongPress()\n .runOnJS(true)\n .minDuration(longPressDuration)\n .onBegin((e: any) => {\n tryClaimOwnership()\n setTimeout(() => {\n if (isOwner()) {\n config.onPressIn?.(e)\n }\n }, GRACE_PERIOD_MS + 1)\n })\n .onStart((e: any) => {\n if (isOwner()) {\n config.onLongPress?.(e)\n }\n })\n .onFinalize((e: any) => {\n if (isOwner()) {\n config.onPressOut?.(e)\n releaseOwnership()\n }\n })\n\n if (config.hitSlop) longPress.hitSlop(config.hitSlop)\n\n // exclusive: longPress has priority, tap is fallback for quick presses\n return Gesture.Exclusive(longPress, tap)\n },\n }\n}\n"
9
+ "import { createGlobalState } from './globalState'\nimport type { GestureState } from './types'\n\nconst state = createGlobalState<GestureState>(`gesture`, {\n enabled: false,\n Gesture: null,\n GestureDetector: null,\n ScrollView: null,\n})\n\nlet pressGestureDebugId = 0\nlet externalPressDebugId = 0\n\ntype PressOwnerSource = 'internal' | 'external' | null\n\nfunction getEventPointerId(e: any): number | null {\n const pointerId =\n e?.pointerId ??\n e?.pointer?.id ??\n e?.event?.pointerId ??\n e?.event?.pointer?.id ??\n e?.nativeEvent?.pointerId ??\n e?.nativeEvent?.id ??\n e?.event?.nativeEvent?.pointerId ??\n e?.event?.nativeEvent?.id ??\n null\n\n return pointerId == null || Number.isNaN(pointerId) ? null : Number(pointerId)\n}\n\n/**\n * Global press coordination - ensures only innermost pressable fires press events,\n * matching RN Pressable/responder system semantics where deepest component wins.\n * Uses a grace period to allow child gestures to steal ownership from parent,\n * since RNGH fires parent gestures before child gestures.\n */\nconst pressState = {\n owner: null as object | null,\n ownerId: null as number | null,\n ownerSource: null as PressOwnerSource,\n ownerPointerId: null as number | null,\n timestamp: 0,\n}\n\nexport interface Insets {\n top?: number\n left?: number\n bottom?: number\n right?: number\n}\n\nexport type PressGestureConfig = {\n debugName?: string | null\n onPressIn?: (e: any) => void\n onPressOut?: (e: any) => void\n onPress?: (e: any) => void\n onLongPress?: (e: any) => void\n delayLongPress?: number\n hitSlop?: number | Insets | null\n}\n\nexport interface GestureHandlerAccessor {\n readonly isEnabled: boolean\n readonly state: GestureState\n set(updates: Partial<GestureState>): void\n disable(): void\n createPressGesture(config: PressGestureConfig): any\n}\n\nexport type ExternalPressOwnershipToken = object\n\nfunction resetPressOwner() {\n pressState.owner = null\n pressState.ownerId = null\n pressState.ownerSource = null\n pressState.ownerPointerId = null\n pressState.timestamp = 0\n}\n\nfunction resetStaleOwner(now: number, debugName?: string | null) {\n if (now - pressState.timestamp > 2000) {\n resetPressOwner()\n }\n}\n\nexport function claimExternalPressOwnership(\n debugName?: string | null\n): ExternalPressOwnershipToken {\n const now = Date.now()\n resetStaleOwner(now, debugName)\n\n const token = {}\n const ownerId = ++externalPressDebugId\n\n pressState.owner = token\n pressState.ownerId = ownerId\n pressState.ownerSource = 'external'\n pressState.timestamp = now\n\n return token\n}\n\nexport function releaseExternalPressOwnership(\n token: ExternalPressOwnershipToken | null | undefined,\n debugName?: string | null\n): void {\n if (!token || pressState.owner !== token) {\n return\n }\n resetPressOwner()\n}\n\nexport function getGestureHandler(): GestureHandlerAccessor {\n return {\n get isEnabled(): boolean {\n return state.get().enabled\n },\n get state(): GestureState {\n return state.get()\n },\n set(updates: Partial<GestureState>): void {\n Object.assign(state.get(), updates)\n },\n\n disable(): void {\n state.get().enabled = false\n },\n\n createPressGesture(config: PressGestureConfig): any {\n const { Gesture } = state.get()\n if (!Gesture) return null\n\n const longPressDuration = config.delayLongPress ?? 500\n\n // unique token for this gesture instance - used to track ownership\n const myToken = {}\n const myDebugId = ++pressGestureDebugId\n let didLongPress = false\n let didPressIn = false\n let pressInTimer: ReturnType<typeof setTimeout> | null = null\n\n // Grace period for child gestures to steal ownership from parent.\n // RNGH fires parent before child, but we want innermost to win.\n // Claims typically span a few ms, 24ms gives enough room to observe\n // ordering while debugging slower frames.\n const GRACE_PERIOD_MS = process.env.GUI_RNGH_PRESS_DELAY\n ? +process.env.GUI_RNGH_PRESS_DELAY\n : 24\n\n const tryClaimOwnership = (e: any) => {\n const now = Date.now()\n resetStaleOwner(now, config.debugName)\n\n const currentPointerId = getEventPointerId(e)\n const isSameTouchPointer =\n currentPointerId == null ||\n pressState.ownerPointerId == null ||\n pressState.ownerPointerId === currentPointerId\n\n if (\n pressState.owner === null ||\n (pressState.ownerSource === 'internal' && isSameTouchPointer)\n ) {\n pressState.owner = myToken\n pressState.ownerId = myDebugId\n pressState.ownerSource = 'internal'\n pressState.ownerPointerId = currentPointerId\n pressState.timestamp = now\n }\n return pressState.owner === myToken\n }\n\n const isOwner = () => pressState.owner === myToken\n\n const releaseOwnership = () => {\n if (pressInTimer) {\n clearTimeout(pressInTimer)\n pressInTimer = null\n }\n if (pressState.owner === myToken) {\n resetPressOwner()\n }\n }\n\n const firePressIn = (e: any) => {\n if (!didPressIn && isOwner()) {\n didPressIn = true\n config.onPressIn?.(e)\n }\n }\n\n const schedulePressIn = (e: any) => {\n if (pressInTimer) {\n clearTimeout(pressInTimer)\n }\n pressInTimer = setTimeout(() => {\n pressInTimer = null\n if (isOwner()) {\n firePressIn(e)\n }\n }, GRACE_PERIOD_MS + 1)\n }\n\n // Tap gesture for regular presses\n // Use long maxDuration to not cancel during long presses\n const tap = Gesture.Tap()\n .runOnJS(true)\n .maxDuration(10000) // allow very long presses\n .onBegin((e: unknown) => {\n didLongPress = false\n didPressIn = false\n tryClaimOwnership(e)\n // Defer onPressIn until after the grace window so child pressables\n // can steal ownership, but flush it on tap end for very fast taps.\n schedulePressIn(e)\n })\n .onEnd((e: unknown) => {\n if (isOwner() && !didLongPress) {\n firePressIn(e)\n config.onPress?.(e)\n }\n })\n .onFinalize((e: unknown) => {\n if (isOwner()) {\n config.onPressOut?.(e)\n releaseOwnership()\n } else if (didPressIn) {\n // we already fired onPressIn but lost ownership before finalize\n // (e.g. finger dragged onto a sibling pressable and that one\n // claimed ownership). fire onPressOut so callers can clear their\n // press state — otherwise pressStyle stays stuck on this view.\n didPressIn = false\n config.onPressOut?.(e)\n }\n })\n\n if (config.hitSlop) tap.hitSlop(config.hitSlop)\n\n // if no long press handler, just use tap\n if (!config.onLongPress) return tap\n\n // LongPress gesture for long press handling\n const longPress = Gesture.LongPress()\n .runOnJS(true)\n .minDuration(longPressDuration)\n .onStart((e: any) => {\n didLongPress = true\n if (isOwner()) {\n firePressIn(e)\n config.onLongPress?.(e)\n }\n })\n\n if (config.hitSlop) longPress.hitSlop(config.hitSlop)\n\n // exclusive: longPress has priority, tap is fallback for quick presses\n return Gesture.Exclusive(longPress, tap)\n },\n }\n}\n"
10
10
  ]
11
11
  }
package/types/index.d.ts CHANGED
@@ -13,7 +13,7 @@
13
13
  * import '@hanzogui/native/expo-linear-gradient'
14
14
  * import '@hanzogui/native/setup-keyboard-controller'
15
15
  *
16
- * // Then use GUI components normally
16
+ * // Then use Gui components normally
17
17
  * // Sheet will automatically use native gestures when available
18
18
  * // LinearGradient will use expo-linear-gradient when installed
19
19
  * ```
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * @hanzogui/native\n *\n * Native setup modules for Gui. Import these at the top of your app entry point.\n *\n * @example\n * ```tsx\n * // In your app entry (index.js or App.tsx)\n * import '@hanzogui/native/setup-teleport'\n * import '@hanzogui/native/setup-gesture-handler'\n * import '@hanzogui/native/setup-worklets'\n * import '@hanzogui/native/setup-safe-area'\n * import '@hanzogui/native/expo-linear-gradient'\n * import '@hanzogui/native/setup-keyboard-controller'\n *\n * // Then use GUI components normally\n * // Sheet will automatically use native gestures when available\n * // LinearGradient will use expo-linear-gradient when installed\n * ```\n */\n\n// types\nexport type {\n NativePortalState,\n GestureState,\n WorkletsState,\n SafeAreaState,\n SafeAreaInsets,\n SafeAreaFrame,\n SafeAreaMetrics,\n LinearGradientState,\n ZeegoState,\n BurntState,\n NativePortalProps,\n NativePortalHostProps,\n NativePortalProviderProps,\n} from './types'\n\n// portal\nexport { getPortal } from './portalState'\nexport type { PortalAccessor } from './portalState'\n\n// gesture handler\nexport { getGestureHandler } from './gestureState'\nexport {\n claimExternalPressOwnership as unstable_claimExternalPressOwnership,\n releaseExternalPressOwnership as unstable_releaseExternalPressOwnership,\n} from './gestureState'\nexport type {\n ExternalPressOwnershipToken,\n GestureHandlerAccessor,\n PressGestureConfig,\n} from './gestureState'\n// NOTE: setupGestureHandler is exported from setup-gesture-handler.ts entry point,\n// not here, to avoid bundler pulling in RNGH require during tree-shaking\nexport type { GestureHandlerConfig } from './setup-gesture-handler'\n\n// worklets\nexport { getWorklets } from './workletsState'\nexport type { WorkletsAccessor } from './workletsState'\n\n// safe area\nexport { getSafeArea } from './safeAreaState'\nexport type { SafeAreaAccessor } from './safeAreaState'\n\n// linear gradient\nexport { getLinearGradient } from './linearGradientState'\nexport type { LinearGradientAccessor } from './linearGradientState'\n\n// keyboard controller state exports (safe - no side effects)\nexport {\n isKeyboardControllerEnabled,\n getKeyboardControllerState,\n setKeyboardControllerState,\n} from './keyboardControllerState'\nexport type { KeyboardControllerState } from './keyboardControllerState'\n\n// zeego (native menus)\nexport { getZeego } from './zeegoState'\nexport type { ZeegoAccessor } from './zeegoState'\nexport { NativeMenuContext } from './nativeMenuContext'\n\n// burnt (native toasts)\nexport { getBurnt } from './burntState'\nexport type { BurntAccessor } from './burntState'\n\n// components\nexport { NativePortal, NativePortalHost, NativePortalProvider } from './components'\n"
9
+ "/**\n * @hanzogui/native\n *\n * Native setup modules for Gui. Import these at the top of your app entry point.\n *\n * @example\n * ```tsx\n * // In your app entry (index.js or App.tsx)\n * import '@hanzogui/native/setup-teleport'\n * import '@hanzogui/native/setup-gesture-handler'\n * import '@hanzogui/native/setup-worklets'\n * import '@hanzogui/native/setup-safe-area'\n * import '@hanzogui/native/expo-linear-gradient'\n * import '@hanzogui/native/setup-keyboard-controller'\n *\n * // Then use Gui components normally\n * // Sheet will automatically use native gestures when available\n * // LinearGradient will use expo-linear-gradient when installed\n * ```\n */\n\n// types\nexport type {\n NativePortalState,\n GestureState,\n WorkletsState,\n SafeAreaState,\n SafeAreaInsets,\n SafeAreaFrame,\n SafeAreaMetrics,\n LinearGradientState,\n ZeegoState,\n BurntState,\n NativePortalProps,\n NativePortalHostProps,\n NativePortalProviderProps,\n} from './types'\n\n// portal\nexport { getPortal } from './portalState'\nexport type { PortalAccessor } from './portalState'\n\n// gesture handler\nexport { getGestureHandler } from './gestureState'\nexport {\n claimExternalPressOwnership as unstable_claimExternalPressOwnership,\n releaseExternalPressOwnership as unstable_releaseExternalPressOwnership,\n} from './gestureState'\nexport type {\n ExternalPressOwnershipToken,\n GestureHandlerAccessor,\n PressGestureConfig,\n} from './gestureState'\n// NOTE: setupGestureHandler is exported from setup-gesture-handler.ts entry point,\n// not here, to avoid bundler pulling in RNGH require during tree-shaking\nexport type { GestureHandlerConfig } from './setup-gesture-handler'\n\n// worklets\nexport { getWorklets } from './workletsState'\nexport type { WorkletsAccessor } from './workletsState'\n\n// safe area\nexport { getSafeArea } from './safeAreaState'\nexport type { SafeAreaAccessor } from './safeAreaState'\n\n// linear gradient\nexport { getLinearGradient } from './linearGradientState'\nexport type { LinearGradientAccessor } from './linearGradientState'\n\n// keyboard controller state exports (safe - no side effects)\nexport {\n isKeyboardControllerEnabled,\n getKeyboardControllerState,\n setKeyboardControllerState,\n} from './keyboardControllerState'\nexport type { KeyboardControllerState } from './keyboardControllerState'\n\n// zeego (native menus)\nexport { getZeego } from './zeegoState'\nexport type { ZeegoAccessor } from './zeegoState'\nexport { NativeMenuContext } from './nativeMenuContext'\n\n// burnt (native toasts)\nexport { getBurnt } from './burntState'\nexport type { BurntAccessor } from './burntState'\n\n// components\nexport { NativePortal, NativePortalHost, NativePortalProvider } from './components'\n"
10
10
  ]
11
11
  }
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup burnt for GUI native toasts.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-burnt'\n * ```\n *\n * This automatically detects and configures burnt for use with\n * native Toast functionality.\n */\n\nimport { getBurnt } from './burntState'\n\nfunction setup(): void {\n const g = globalThis as any\n if (g.__gui_native_burnt_setup) return\n g.__gui_native_burnt_setup = true\n\n try {\n const Burnt = require('burnt') as typeof import('burnt')\n\n if (Burnt) {\n getBurnt().set({\n enabled: true,\n toast: Burnt.toast,\n dismissAllAlerts: Burnt.dismissAllAlerts,\n })\n }\n } catch {\n // burnt not installed\n }\n}\n\n// run setup immediately on import\nsetup()\n"
9
+ "/**\n * Setup burnt for Gui native toasts.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-burnt'\n * ```\n *\n * This automatically detects and configures burnt for use with\n * native Toast functionality.\n */\n\nimport { getBurnt } from './burntState'\n\nfunction setup(): void {\n const g = globalThis as any\n if (g.__gui_native_burnt_setup) return\n g.__gui_native_burnt_setup = true\n\n try {\n const Burnt = require('burnt') as typeof import('burnt')\n\n if (Burnt) {\n getBurnt().set({\n enabled: true,\n toast: Burnt.toast,\n dismissAllAlerts: Burnt.dismissAllAlerts,\n })\n }\n } catch {\n // burnt not installed\n }\n}\n\n// run setup immediately on import\nsetup()\n"
10
10
  ]
11
11
  }
@@ -1,5 +1,5 @@
1
1
  export interface GestureHandlerConfig {
2
- /** use RNGH for press events on Tamagui components (default: true) */
2
+ /** use RNGH for press events on Gui components (default: true) */
3
3
  pressEvents?: boolean;
4
4
  /** use RNGH for Sheet drag gestures (default: true) */
5
5
  sheet?: boolean;
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup gesture handler for Tamagui native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * // auto-setup with all features enabled\n * import '@hanzogui/native/setup-gesture-handler'\n *\n * // or configure selectively\n * import { setupGestureHandler } from '@hanzogui/native/setup-gesture-handler'\n * setupGestureHandler({ pressEvents: true, sheet: false })\n * ```\n *\n * This automatically detects and configures react-native-gesture-handler\n * for use with Sheet and other gesture-aware components.\n */\n\nimport { getGestureHandler } from './gestureState'\n\nexport interface GestureHandlerConfig {\n /** use RNGH for press events on Tamagui components (default: true) */\n pressEvents?: boolean\n /** use RNGH for Sheet drag gestures (default: true) */\n sheet?: boolean\n}\n\nlet currentConfig: GestureHandlerConfig = {\n pressEvents: true,\n sheet: true,\n}\n\nexport function getGestureHandlerConfig(): GestureHandlerConfig {\n return currentConfig\n}\n\nexport function setupGestureHandler(config?: GestureHandlerConfig): void {\n const g = globalThis as any\n\n // override config if provided\n if (config) {\n currentConfig = config\n }\n\n // allow re-running setup to change config\n const isFirstRun = !g.__tamagui_native_gesture_setup_complete\n g.__tamagui_native_gesture_setup_complete = true\n\n try {\n // dynamically require RNGH - it should already be imported by the app\n const rngh = require('react-native-gesture-handler')\n const { Gesture, GestureDetector, ScrollView } = rngh\n\n if (Gesture && GestureDetector) {\n // only enable if pressEvents is true\n getGestureHandler().set({\n enabled: currentConfig.pressEvents !== false,\n Gesture,\n GestureDetector,\n ScrollView: ScrollView || null,\n })\n\n // sheet state - only enable if sheet is true\n g.__tamagui_sheet_gesture_state__ = {\n enabled: currentConfig.sheet !== false,\n Gesture,\n GestureDetector,\n ScrollView: ScrollView || null,\n }\n }\n } catch {\n // RNGH not available, that's fine\n }\n}\n\n// run setup immediately on import (can be overridden by calling setupGestureHandler)\nsetupGestureHandler()\n"
9
+ "/**\n * Setup gesture handler for Gui native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * // auto-setup with all features enabled\n * import '@hanzogui/native/setup-gesture-handler'\n *\n * // or configure selectively\n * import { setupGestureHandler } from '@hanzogui/native/setup-gesture-handler'\n * setupGestureHandler({ pressEvents: true, sheet: false })\n * ```\n *\n * This automatically detects and configures react-native-gesture-handler\n * for use with Sheet and other gesture-aware components.\n */\n\nimport { getGestureHandler } from './gestureState'\n\nexport interface GestureHandlerConfig {\n /** use RNGH for press events on Gui components (default: true) */\n pressEvents?: boolean\n /** use RNGH for Sheet drag gestures (default: true) */\n sheet?: boolean\n}\n\nlet currentConfig: GestureHandlerConfig = {\n pressEvents: true,\n sheet: true,\n}\n\nexport function getGestureHandlerConfig(): GestureHandlerConfig {\n return currentConfig\n}\n\nexport function setupGestureHandler(config?: GestureHandlerConfig): void {\n const g = globalThis as any\n\n // override config if provided\n if (config) {\n currentConfig = config\n }\n\n // allow re-running setup to change config\n const isFirstRun = !g.__gui_native_gesture_setup_complete\n g.__gui_native_gesture_setup_complete = true\n\n try {\n // dynamically require RNGH - it should already be imported by the app\n const rngh = require('react-native-gesture-handler')\n const { Gesture, GestureDetector, ScrollView } = rngh\n\n if (Gesture && GestureDetector) {\n // only enable if pressEvents is true\n getGestureHandler().set({\n enabled: currentConfig.pressEvents !== false,\n Gesture,\n GestureDetector,\n ScrollView: ScrollView || null,\n })\n\n // sheet state - only enable if sheet is true\n g.__gui_sheet_gesture_state__ = {\n enabled: currentConfig.sheet !== false,\n Gesture,\n GestureDetector,\n ScrollView: ScrollView || null,\n }\n }\n } catch {\n // RNGH not available, that's fine\n }\n}\n\n// run setup immediately on import (can be overridden by calling setupGestureHandler)\nsetupGestureHandler()\n"
10
10
  ]
11
11
  }
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup keyboard controller for GUI native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-keyboard-controller'\n * ```\n *\n * This automatically detects and configures react-native-keyboard-controller\n * for use with Sheet and other keyboard-aware components.\n *\n * When enabled, Sheet gains:\n * - Frame-by-frame keyboard tracking (60/120 FPS)\n * - Smooth gesture + keyboard handoff\n * - Interactive keyboard dismiss on sheet drag\n */\n\nimport { setKeyboardControllerState } from './keyboardControllerState'\n\nfunction setup() {\n const g = globalThis as any\n if (g.__gui_native_keyboard_controller_setup_complete) {\n return\n }\n g.__gui_native_keyboard_controller_setup_complete = true\n\n try {\n // dynamically require keyboard-controller - it should already be imported by the app\n const rnkc = require('react-native-keyboard-controller')\n const {\n KeyboardProvider,\n KeyboardAwareScrollView,\n useKeyboardHandler,\n useReanimatedKeyboardAnimation,\n KeyboardController,\n KeyboardEvents,\n KeyboardStickyView,\n } = rnkc\n\n if (useKeyboardHandler && KeyboardProvider) {\n setKeyboardControllerState({\n enabled: true,\n KeyboardProvider: KeyboardProvider || null,\n KeyboardAwareScrollView: KeyboardAwareScrollView || null,\n useKeyboardHandler: useKeyboardHandler || null,\n useReanimatedKeyboardAnimation: useReanimatedKeyboardAnimation || null,\n KeyboardController: KeyboardController || null,\n KeyboardEvents: KeyboardEvents || null,\n KeyboardStickyView: KeyboardStickyView || null,\n })\n }\n } catch {\n // keyboard-controller not available, that's fine\n }\n}\n\n// run setup immediately on import\nsetup()\n"
9
+ "/**\n * Setup keyboard controller for Gui native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-keyboard-controller'\n * ```\n *\n * This automatically detects and configures react-native-keyboard-controller\n * for use with Sheet and other keyboard-aware components.\n *\n * When enabled, Sheet gains:\n * - Frame-by-frame keyboard tracking (60/120 FPS)\n * - Smooth gesture + keyboard handoff\n * - Interactive keyboard dismiss on sheet drag\n */\n\nimport { setKeyboardControllerState } from './keyboardControllerState'\n\nfunction setup() {\n const g = globalThis as any\n if (g.__gui_native_keyboard_controller_setup_complete) {\n return\n }\n g.__gui_native_keyboard_controller_setup_complete = true\n\n try {\n // dynamically require keyboard-controller - it should already be imported by the app\n const rnkc = require('react-native-keyboard-controller')\n const {\n KeyboardProvider,\n KeyboardAwareScrollView,\n useKeyboardHandler,\n useReanimatedKeyboardAnimation,\n KeyboardController,\n KeyboardEvents,\n KeyboardStickyView,\n } = rnkc\n\n if (useKeyboardHandler && KeyboardProvider) {\n setKeyboardControllerState({\n enabled: true,\n KeyboardProvider: KeyboardProvider || null,\n KeyboardAwareScrollView: KeyboardAwareScrollView || null,\n useKeyboardHandler: useKeyboardHandler || null,\n useReanimatedKeyboardAnimation: useReanimatedKeyboardAnimation || null,\n KeyboardController: KeyboardController || null,\n KeyboardEvents: KeyboardEvents || null,\n KeyboardStickyView: KeyboardStickyView || null,\n })\n }\n } catch {\n // keyboard-controller not available, that's fine\n }\n}\n\n// run setup immediately on import\nsetup()\n"
10
10
  ]
11
11
  }
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup react-native-safe-area-context for GUI native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-safe-area'\n * ```\n *\n * This automatically detects and configures react-native-safe-area-context\n * for use with GUI components that need safe area awareness.\n *\n * Note: You must still wrap your app with SafeAreaProvider yourself:\n * ```tsx\n * import { SafeAreaProvider } from 'react-native-safe-area-context'\n * <SafeAreaProvider>\n * <App />\n * </SafeAreaProvider>\n * ```\n *\n * On web, this is a no-op since CSS env(safe-area-inset-*) values work natively.\n */\n\nimport { getSafeArea } from './safeAreaState'\n\nfunction setup() {\n // only run on native\n if (process.env.GUI_TARGET !== 'native') {\n return\n }\n\n const g = globalThis as any\n if (g.__gui_native_safe_area_setup_complete) {\n return\n }\n g.__gui_native_safe_area_setup_complete = true\n\n try {\n const safeAreaContext = require('react-native-safe-area-context')\n const { useSafeAreaInsets, useSafeAreaFrame, initialWindowMetrics } = safeAreaContext\n\n if (useSafeAreaInsets) {\n getSafeArea().set({\n enabled: true,\n useSafeAreaInsets,\n useSafeAreaFrame: useSafeAreaFrame || null,\n initialMetrics: initialWindowMetrics || null,\n })\n }\n } catch {\n // react-native-safe-area-context not available\n }\n}\n\nsetup()\n"
9
+ "/**\n * Setup react-native-safe-area-context for Gui native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-safe-area'\n * ```\n *\n * This automatically detects and configures react-native-safe-area-context\n * for use with Gui components that need safe area awareness.\n *\n * Note: You must still wrap your app with SafeAreaProvider yourself:\n * ```tsx\n * import { SafeAreaProvider } from 'react-native-safe-area-context'\n * <SafeAreaProvider>\n * <App />\n * </SafeAreaProvider>\n * ```\n *\n * On web, this is a no-op since CSS env(safe-area-inset-*) values work natively.\n */\n\nimport { getSafeArea } from './safeAreaState'\n\nfunction setup() {\n // only run on native\n if (process.env.GUI_TARGET !== 'native') {\n return\n }\n\n const g = globalThis as any\n if (g.__gui_native_safe_area_setup_complete) {\n return\n }\n g.__gui_native_safe_area_setup_complete = true\n\n try {\n const safeAreaContext = require('react-native-safe-area-context')\n const { useSafeAreaInsets, useSafeAreaFrame, initialWindowMetrics } = safeAreaContext\n\n if (useSafeAreaInsets) {\n getSafeArea().set({\n enabled: true,\n useSafeAreaInsets,\n useSafeAreaFrame: useSafeAreaFrame || null,\n initialMetrics: initialWindowMetrics || null,\n })\n }\n } catch {\n // react-native-safe-area-context not available\n }\n}\n\nsetup()\n"
10
10
  ]
11
11
  }
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup worklets for GUI native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-worklets'\n * ```\n *\n * This automatically detects and configures react-native-worklets-core\n * for use with Sheet and other components that benefit from synchronous\n * native-thread execution.\n *\n * When combined with setup-gesture-handler, Sheet gets native-quality\n * gesture coordination between sheet dragging and scroll views.\n *\n * @see https://docs.swmansion.com/react-native-worklets/docs/\n */\n\nimport { getWorklets } from './workletsState'\n\nfunction setup() {\n const g = globalThis as any\n if (g.__gui_native_worklets_setup_complete) {\n return\n }\n g.__gui_native_worklets_setup_complete = true\n\n try {\n // dynamically require worklets-core\n const worklets = require('react-native-worklets-core')\n\n if (worklets) {\n getWorklets().set({\n enabled: true,\n Worklets: worklets.Worklets,\n useRunOnJS: worklets.useRunOnJS,\n useWorklet: worklets.useWorklet,\n createWorkletContextValue: worklets.createWorkletContextValue,\n })\n }\n } catch {\n // worklets not available, that's fine - will fall back to JS thread\n }\n}\n\n// run setup immediately on import\nsetup()\n"
9
+ "/**\n * Setup worklets for Gui native components.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-worklets'\n * ```\n *\n * This automatically detects and configures react-native-worklets-core\n * for use with Sheet and other components that benefit from synchronous\n * native-thread execution.\n *\n * When combined with setup-gesture-handler, Sheet gets native-quality\n * gesture coordination between sheet dragging and scroll views.\n *\n * @see https://docs.swmansion.com/react-native-worklets/docs/\n */\n\nimport { getWorklets } from './workletsState'\n\nfunction setup() {\n const g = globalThis as any\n if (g.__gui_native_worklets_setup_complete) {\n return\n }\n g.__gui_native_worklets_setup_complete = true\n\n try {\n // dynamically require worklets-core\n const worklets = require('react-native-worklets-core')\n\n if (worklets) {\n getWorklets().set({\n enabled: true,\n Worklets: worklets.Worklets,\n useRunOnJS: worklets.useRunOnJS,\n useWorklet: worklets.useWorklet,\n createWorkletContextValue: worklets.createWorkletContextValue,\n })\n }\n } catch {\n // worklets not available, that's fine - will fall back to JS thread\n }\n}\n\n// run setup immediately on import\nsetup()\n"
10
10
  ]
11
11
  }
@@ -6,6 +6,6 @@
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Setup zeego for GUI native menus.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-zeego'\n * ```\n *\n * This automatically detects and configures zeego for use with\n * Menu and ContextMenu native mode.\n */\n\nimport { getZeego } from './zeegoState'\n\nfunction setup(): void {\n const g = globalThis as any\n if (g.__gui_native_zeego_setup) return\n g.__gui_native_zeego_setup = true\n\n try {\n const DropdownMenu = require('zeego/dropdown-menu')\n const ContextMenu = require('zeego/context-menu')\n\n if (DropdownMenu && ContextMenu) {\n getZeego().set({\n enabled: true,\n DropdownMenu,\n ContextMenu,\n })\n }\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(`Error setting up Zeego`, err)\n }\n // zeego not installed\n }\n}\n\n// run setup immediately on import\nsetup()\n"
9
+ "/**\n * Setup zeego for Gui native menus.\n *\n * Simply import this module at the top of your app entry point:\n *\n * @example\n * ```tsx\n * import '@hanzogui/native/setup-zeego'\n * ```\n *\n * This automatically detects and configures zeego for use with\n * Menu and ContextMenu native mode.\n */\n\nimport { getZeego } from './zeegoState'\n\nfunction setup(): void {\n const g = globalThis as any\n if (g.__gui_native_zeego_setup) return\n g.__gui_native_zeego_setup = true\n\n try {\n const DropdownMenu = require('zeego/dropdown-menu')\n const ContextMenu = require('zeego/context-menu')\n\n if (DropdownMenu && ContextMenu) {\n getZeego().set({\n enabled: true,\n DropdownMenu,\n ContextMenu,\n })\n }\n } catch (err) {\n if (process.env.NODE_ENV === 'development') {\n console.warn(`Error setting up Zeego`, err)\n }\n // zeego not installed\n }\n}\n\n// run setup immediately on import\nsetup()\n"
10
10
  ]
11
11
  }
@@ -1,2 +0,0 @@
1
- $ hanzo-gui-build
2
- built @hanzogui/native in 2743 ms
@@ -1 +0,0 @@
1
- Object.assign(module.exports, require('../dist/cjs/gesture-handler.cjs'))
@@ -1 +0,0 @@
1
- Object.assign(module.exports, require('../dist/cjs/gesture-handler.cjs'))
@@ -1 +0,0 @@
1
- Object.assign(module.exports, require('../dist/cjs/gesture-handler.native.js'))
@@ -1 +0,0 @@
1
- Object.assign(module.exports, require('../dist/cjs/gesture-handler.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-burnt.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-burnt.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-burnt.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-burnt.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-expo-linear-gradient.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-expo-linear-gradient.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-expo-linear-gradient.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-expo-linear-gradient.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-gesture-handler.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-gesture-handler.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-gesture-handler.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-gesture-handler.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-keyboard-controller.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-keyboard-controller.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-keyboard-controller.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-keyboard-controller.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-safe-area.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-safe-area.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-safe-area.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-safe-area.native.js'))
@@ -1,2 +0,0 @@
1
- // compat with hanzo-gui static compiler
2
- Object.assign(module.exports, require('../dist/cjs/setup-teleport.cjs'))
@@ -1,2 +0,0 @@
1
- // compat with metro without package exports
2
- Object.assign(module.exports, require('../dist/cjs/setup-teleport.cjs'))