react-native-swipeable-actions 0.1.5 → 0.1.7-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,10 @@ class SwipeableModule : Module() {
20
20
  SwipeableView.closeAll(animated ?: true)
21
21
  }
22
22
 
23
+ Function("isOpenByKey") { key: String ->
24
+ SwipeableView.isOpenByKey(key)
25
+ }
26
+
23
27
  View(SwipeableView::class) {
24
28
  Prop("actionsWidth") { view: SwipeableView, width: Float ->
25
29
  view.actionsWidth = width
@@ -89,6 +89,9 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
89
89
  fun clearCache() {
90
90
  openStateCache.evictAll()
91
91
  }
92
+
93
+ /** Check if a recyclingKey is cached as open (for JS-side state initialization) */
94
+ fun isOpenByKey(key: String): Boolean = getOpenState(key)
92
95
  }
93
96
 
94
97
  private val density = context.resources.displayMetrics.density
@@ -182,7 +185,11 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
182
185
 
183
186
  close(animated = false)
184
187
 
185
- // Apply using local shouldOpen (pendingShouldOpen was cleared by close)
188
+ // Apply using local shouldOpen (pendingShouldOpen was cleared by close).
189
+ // Set recycleSnapPending so onViewAdded can position actions immediately
190
+ // when React renders them (isOpenByKey initializes hasActionsRendered=true
191
+ // before snapToOpen runs on the next frame).
192
+ recycleSnapPending = shouldOpen
186
193
  if (shouldOpen) {
187
194
  post { snapToOpen() }
188
195
  }
@@ -197,6 +204,9 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
197
204
  private var isGestureActivated: Boolean = false
198
205
  private var lastEmittedProgress: Float = -1f
199
206
  private var pendingShouldOpen: Boolean = false
207
+ /** Tracks pending snapToOpen from recyclingKey setter. Unlike pendingShouldOpen,
208
+ * this survives close(animated:false) so onViewAdded can position actions correctly. */
209
+ private var recycleSnapPending: Boolean = false
200
210
  private var lastEmittedWillEndState: String? = null
201
211
 
202
212
  // Track if open animation was explicitly interrupted by close() for autoClose
@@ -238,6 +248,41 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
238
248
  // Track when a child (e.g. RNGH gesture handler) claims the touch
239
249
  private var childRequestedDisallowIntercept: Boolean = false
240
250
 
251
+ // Layout guard: re-applies translations for a few frames after a reorder.
252
+ // Fabric may reset child translationX during prop reconciliation after a
253
+ // recyclingKey change. This guard runs for a bounded number of frames to
254
+ // detect and correct mismatches, then stops automatically.
255
+ private var layoutGuardCallback: Choreographer.FrameCallback? = null
256
+ private var layoutGuardFramesRemaining: Int = 0
257
+
258
+ private fun startLayoutGuard(frames: Int = 5) {
259
+ stopLayoutGuard()
260
+ layoutGuardFramesRemaining = frames
261
+ layoutGuardCallback = Choreographer.FrameCallback {
262
+ layoutGuardFramesRemaining--
263
+ if (isOpen && currentTranslation != 0f && !isDragging && !isAnimating) {
264
+ val contentTx = contentView?.translationX ?: 0f
265
+ if (contentTx != currentTranslation) {
266
+ contentView?.translationX = currentTranslation
267
+ updateActionsTransform()
268
+ actionsView?.visibility = View.VISIBLE
269
+ }
270
+ }
271
+ if (layoutGuardFramesRemaining > 0) {
272
+ layoutGuardCallback?.let { Choreographer.getInstance().postFrameCallback(it) }
273
+ } else {
274
+ layoutGuardCallback = null
275
+ }
276
+ }
277
+ layoutGuardCallback?.let { Choreographer.getInstance().postFrameCallback(it) }
278
+ }
279
+
280
+ private fun stopLayoutGuard() {
281
+ layoutGuardCallback?.let { Choreographer.getInstance().removeFrameCallback(it) }
282
+ layoutGuardCallback = null
283
+ layoutGuardFramesRemaining = 0
284
+ }
285
+
241
286
  init {
242
287
  clipChildren = false
243
288
  clipToPadding = false
@@ -283,6 +328,12 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
283
328
  }
284
329
 
285
330
  if (wasActionsNil && actionsView != null) {
331
+ // Prevent child clipping: Yoga lays out children for absoluteFill (full parent width)
332
+ // but our onLayout overrides the actionsView bounds to actionsWidth. Without this,
333
+ // children positioned by Yoga's flex-end would be clipped beyond the narrower bounds.
334
+ (actionsView as? ViewGroup)?.clipChildren = false
335
+ (actionsView as? ViewGroup)?.clipToPadding = false
336
+
286
337
  if (isOpen || isAnimating) {
287
338
  actionsView?.visibility = View.VISIBLE
288
339
  actionsView?.translationX = 0f
@@ -295,6 +346,13 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
295
346
  pendingShouldOpen = false
296
347
  post { snapToOpen() }
297
348
  }
349
+ else if (recycleSnapPending) {
350
+ // Actions were rendered by React (via isOpenByKey) before native snapToOpen ran.
351
+ // Position them immediately so they're visible when UIAutomator checks.
352
+ recycleSnapPending = false
353
+ actionsView?.visibility = View.VISIBLE
354
+ actionsView?.translationX = 0f
355
+ }
298
356
  }
299
357
  }
300
358
 
@@ -313,22 +371,30 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
313
371
 
314
372
  for (i in 0 until childCount) {
315
373
  val child = getChildAt(i)
316
- if (child === actionsView && actionsWidthPx > 0f) {
317
- val actionsWidthInt = actionsWidthPx.toInt()
318
- if (isLeading) {
319
- child.layout(0, 0, actionsWidthInt, height)
320
- } else {
321
- child.layout(width - actionsWidthInt, 0, width, height)
322
- }
323
- } else {
324
- child.layout(0, 0, width, height)
325
- }
374
+ // Don't override actionsView layout - Yoga positions it via absoluteFill
375
+ // and lays out children (flex-end) based on full parent width. Overriding
376
+ // the bounds to actionsWidth causes children to be positioned outside the
377
+ // narrower bounds, making them invisible during FlatList reorder.
378
+ // Instead, use translationX to hide/show the actions.
379
+ child.layout(0, 0, width, height)
326
380
  }
327
381
 
328
- if (!isDragging && !isAnimating && currentTranslation == 0f && actionsWidthPx > 0f) {
382
+ if (!isDragging && !isAnimating && currentTranslation == 0f && actionsWidthPx > 0f && !recycleSnapPending) {
329
383
  val actionsOffset = if (isLeading) -actionsWidthPx else actionsWidthPx
330
384
  actionsView?.translationX = actionsOffset
331
385
  }
386
+
387
+ // Re-apply translations when open. Fabric may reset child translationX during
388
+ // prop reconciliation after a list reorder. The post {} ensures we run after
389
+ // Fabric finishes applying all mutations in the current frame.
390
+ if (isOpen && currentTranslation != 0f && !isDragging && !isAnimating) {
391
+ post {
392
+ if (isOpen && currentTranslation != 0f && !isDragging && !isAnimating) {
393
+ contentView?.translationX = currentTranslation
394
+ updateActionsTransform()
395
+ }
396
+ }
397
+ }
332
398
  }
333
399
 
334
400
  /**
@@ -728,6 +794,7 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
728
794
  return@addEndListener
729
795
  }
730
796
  isAnimating = false
797
+ startLayoutGuard()
731
798
  emitFinalProgress(1f, targetX)
732
799
  // With autoClose, let close() emit onSwipeEnd("open") instead
733
800
  if (!autoClose) {
@@ -763,6 +830,8 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
763
830
  onSwipeStart(emptyMap())
764
831
  }
765
832
 
833
+ startLayoutGuard()
834
+
766
835
  // Emit final progress
767
836
  emitFinalProgress(1f, targetX)
768
837
  }
@@ -770,6 +839,7 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
770
839
  fun close(animated: Boolean = true, velocity: Float = 0f) {
771
840
  cancelAutoClose()
772
841
  stopProgressUpdates()
842
+ stopLayoutGuard()
773
843
 
774
844
  // Cancel any running animations
775
845
  openAnimationInterruptedByClose = true
@@ -957,16 +1027,28 @@ class SwipeableView(context: Context, appContext: AppContext) : ExpoView(context
957
1027
 
958
1028
  override fun onAttachedToWindow() {
959
1029
  super.onAttachedToWindow()
960
- // Re-register in the view registry after reattach (e.g. returning from navigation).
961
- // onDetachedFromWindow unregisters the view, but the recyclingKey prop setter
962
- // short-circuits when the value hasn't changed, so the view is never re-registered
963
- // unless we do it here.
964
1030
  recyclingKey?.let { registerView(this, it) }
1031
+
1032
+ if (isOpen && currentTranslation != 0f) {
1033
+ post {
1034
+ if (isOpen && currentTranslation != 0f && !isDragging && !isAnimating) {
1035
+ contentView?.translationX = currentTranslation
1036
+ updateActionsTransform()
1037
+ actionsView?.visibility = View.VISIBLE
1038
+ }
1039
+ }
1040
+
1041
+ // Restart autoClose timer if it was cancelled during detach
1042
+ if (autoClose) {
1043
+ scheduleAutoClose()
1044
+ }
1045
+ }
965
1046
  }
966
1047
 
967
1048
  override fun onDetachedFromWindow() {
968
1049
  super.onDetachedFromWindow()
969
1050
  stopProgressUpdates()
1051
+ stopLayoutGuard()
970
1052
  cancelGestureTimeout()
971
1053
  cancelAutoClose()
972
1054
  contentSpringAnimation?.cancel()
@@ -1,4 +1,4 @@
1
- import { SwipeableProps, SwipeableMethods } from './Swipeable.types';
1
+ import type { SwipeableMethods, SwipeableProps } from './Swipeable.types';
2
2
  declare const Swipeable: import("react").ForwardRefExoticComponent<Omit<SwipeableProps, "ref"> & import("react").RefAttributes<SwipeableMethods>>;
3
3
  type SwipeableWithStatic = typeof Swipeable & {
4
4
  open: (recyclingKey: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Swipeable.d.ts","sourceRoot":"","sources":["../src/Swipeable.tsx"],"names":[],"mappings":"AAKA,OAAO,EACL,cAAc,EACd,gBAAgB,EAIjB,MAAM,mBAAmB,CAAA;AAe1B,QAAA,MAAM,SAAS,0HA8Hb,CAAA;AAgBF,KAAK,mBAAmB,GAAG,OAAO,SAAS,GAAG;IAC5C,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACzD,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC,CAAA;AAED,QAAA,MAAM,eAAe,EAAgB,mBAAmB,CAAA;AAsBxD,eAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"Swipeable.d.ts","sourceRoot":"","sources":["../src/Swipeable.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EAGf,MAAM,mBAAmB,CAAA;AAe1B,QAAA,MAAM,SAAS,0HAoJb,CAAA;AAgBF,KAAK,mBAAmB,GAAG,OAAO,SAAS,GAAG;IAC5C,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACzD,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC,CAAA;AAED,QAAA,MAAM,eAAe,EAAgB,mBAAmB,CAAA;AAsBxD,eAAe,eAAe,CAAA"}
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const react_1 = require("react");
4
4
  const react_native_1 = require("react-native");
5
- const SwipeableView_1 = require("./SwipeableView");
6
- const SwipeableActions_1 = require("./SwipeableActions");
7
5
  const constants_1 = require("./constants");
8
6
  const nativeModuleUtils_1 = require("./nativeModuleUtils");
7
+ const SwipeableActions_1 = require("./SwipeableActions");
8
+ const SwipeableView_1 = require("./SwipeableView");
9
9
  function normalizeRecyclingKey(key) {
10
10
  if (key == null)
11
11
  return undefined;
@@ -20,13 +20,30 @@ function normalizeRecyclingKey(key) {
20
20
  }
21
21
  const Swipeable = (0, react_1.forwardRef)(function Swipeable({ children, actions, actionsWidth, actionsPosition = constants_1.SWIPE_DEFAULTS.ACTIONS_POSITION, friction = constants_1.SWIPE_DEFAULTS.FRICTION, threshold = constants_1.SWIPE_DEFAULTS.THRESHOLD, gestureEnabled = constants_1.SWIPE_DEFAULTS.GESTURE_ENABLED, dragOffsetFromEdge = constants_1.SWIPE_DEFAULTS.DRAG_OFFSET_FROM_EDGE, style, testID, onSwipeStart, onSwipeStateChange, onSwipeEnd, onProgress, autoClose = false, autoCloseTimeout = 0, recyclingKey }, ref) {
22
22
  const nativeRef = (0, react_1.useRef)(null);
23
- const [hasActionsRendered, setHasActionsRendered] = (0, react_1.useState)(false);
24
- const swipeStartedRef = (0, react_1.useRef)(false);
25
- // Normalize and sync recyclingKey to ref for use in useImperativeHandle
26
- // (set during render to ensure it's always current before callbacks fire)
23
+ // Normalize recyclingKey before hooks that depend on it
27
24
  const normalizedKey = normalizeRecyclingKey(recyclingKey);
28
25
  const recyclingKeyRef = (0, react_1.useRef)(undefined);
29
26
  recyclingKeyRef.current = normalizedKey;
27
+ // Initialize from native cache: if this recyclingKey was open, render actions immediately.
28
+ // This handles FlatList remounting components during data reorder - React state is lost
29
+ // but native cache preserves the open state.
30
+ const [hasActionsRendered, setHasActionsRendered] = (0, react_1.useState)(() => {
31
+ return normalizedKey != null && (0, nativeModuleUtils_1.isOpenByKey)(normalizedKey);
32
+ });
33
+ const swipeStartedRef = (0, react_1.useRef)(false);
34
+ const initialKeyRef = (0, react_1.useRef)(normalizedKey);
35
+ // When recyclingKey changes (FlatList reorder/recycle), sync hasActionsRendered
36
+ // with the native cached open state. FlatList reuses component instances without
37
+ // remounting, so useState initializer doesn't re-run. Skip on initial mount
38
+ // since the useState initializer already handled it.
39
+ (0, react_1.useEffect)(() => {
40
+ if (!normalizedKey)
41
+ return;
42
+ if (normalizedKey === initialKeyRef.current)
43
+ return;
44
+ initialKeyRef.current = normalizedKey;
45
+ setHasActionsRendered((0, nativeModuleUtils_1.isOpenByKey)(normalizedKey));
46
+ }, [normalizedKey]);
30
47
  // Development-time validation
31
48
  if (__DEV__) {
32
49
  if (autoClose && recyclingKey == null) {
@@ -76,7 +93,9 @@ const Swipeable = (0, react_1.forwardRef)(function Swipeable({ children, actions
76
93
  onSwipeEnd?.(event.nativeEvent.state);
77
94
  }, [onSwipeEnd]);
78
95
  return (<SwipeableView_1.SwipeableView ref={nativeRef} style={[styles.container, style]} actionsWidth={actionsWidth} actionsPosition={actionsPosition} friction={friction} threshold={threshold} gestureEnabled={gestureEnabled} dragOffsetFromEdge={dragOffsetFromEdge} autoClose={autoClose} autoCloseTimeout={autoCloseTimeout} {...(normalizedKey ? { recyclingKey: normalizedKey } : {})} {...(testID ? { testID } : {})} onSwipeStart={handleSwipeStart} onSwipeProgress={handleSwipeProgress} onSwipeStateChange={handleSwipeStateChange} onSwipeEnd={handleSwipeEnd}>
79
- {hasActionsRendered && (<SwipeableActions_1.SwipeableActions actionsPosition={actionsPosition}>{actions}</SwipeableActions_1.SwipeableActions>)}
96
+ {hasActionsRendered && (<SwipeableActions_1.SwipeableActions actionsPosition={actionsPosition} {...(testID ? { testID: `${testID}-actions` } : {})}>
97
+ {actions}
98
+ </SwipeableActions_1.SwipeableActions>)}
80
99
 
81
100
  <react_native_1.View style={styles.content}>{children}</react_native_1.View>
82
101
  </SwipeableView_1.SwipeableView>);
@@ -1 +1 @@
1
- {"version":3,"file":"Swipeable.js","sourceRoot":"","sources":["../src/Swipeable.tsx"],"names":[],"mappings":";;AAAA,iCAAsF;AACtF,+CAAyD;AAEzD,mDAA+C;AAC/C,yDAAqD;AAQrD,2CAA4C;AAC5C,2DAAqE;AAErE,SAAS,qBAAqB,CAAC,GAAgC;IAC7D,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,SAAS,CAAA;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAA;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;IAEvE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,qCAAqC,GAAG,qCAAqC,CAAC,CAAA;IAC7F,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,SAAS,GAAG,IAAA,kBAAU,EAAmC,SAAS,SAAS,CAC/E,EACE,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,eAAe,GAAG,0BAAc,CAAC,gBAAgB,EACjD,QAAQ,GAAG,0BAAc,CAAC,QAAQ,EAClC,SAAS,GAAG,0BAAc,CAAC,SAAS,EACpC,cAAc,GAAG,0BAAc,CAAC,eAAe,EAC/C,kBAAkB,GAAG,0BAAc,CAAC,qBAAqB,EACzD,KAAK,EACL,MAAM,EACN,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,SAAS,GAAG,KAAK,EACjB,gBAAgB,GAAG,CAAC,EACpB,YAAY,EACb,EACD,GAAG;IAEH,MAAM,SAAS,GAAG,IAAA,cAAM,EAAqB,IAAI,CAAC,CAAA;IAClD,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAA;IACnE,MAAM,eAAe,GAAG,IAAA,cAAM,EAAC,KAAK,CAAC,CAAA;IAErC,wEAAwE;IACxE,0EAA0E;IAC1E,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAA;IACzD,MAAM,eAAe,GAAG,IAAA,cAAM,EAAqB,SAAS,CAAC,CAAA;IAC7D,eAAe,CAAC,OAAO,GAAG,aAAa,CAAA;IAEvC,8BAA8B;IAC9B,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,SAAS,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CACV,gEAAgE;gBAC9D,kFAAkF,CACrF,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAA,2BAAmB,EACjB,GAAG,EACH,GAAG,EAAE,CAAC,CAAC;QACL,KAAK,EAAE,CAAC,QAAkB,EAAE,EAAE;YAC5B,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAA;YACnC,IAAI,GAAG,EAAE,CAAC;gBACR,IAAA,8BAAU,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;YAC3B,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAA;YACxF,CAAC;QACH,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAA;YACnC,IAAI,GAAG,EAAE,CAAC;gBACR,IAAA,6BAAS,EAAC,GAAG,CAAC,CAAA;YAChB,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAA;YACvF,CAAC;QACH,CAAC;KACF,CAAC,EACF,EAAE,CACH,CAAA;IAED,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACxC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,qBAAqB,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAED,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;YAC7B,eAAe,CAAC,OAAO,GAAG,IAAI,CAAA;YAC9B,YAAY,EAAE,EAAE,CAAA;QAClB,CAAC;IACH,CAAC,EAAE,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC,CAAA;IAEtC,MAAM,mBAAmB,GAAG,IAAA,mBAAW,EACrC,CAAC,KAAyB,EAAE,EAAE;QAC5B,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAA;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAA;QACrD,UAAU,EAAE,CAAC,OAAO,CAAC,CAAA;IACvB,CAAC,EACD,CAAC,UAAU,CAAC,CACb,CAAA;IAED,MAAM,sBAAsB,GAAG,IAAA,mBAAW,EACxC,CAAC,KAAsB,EAAE,EAAE;QACzB,kBAAkB,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC,EACD,CAAC,kBAAkB,CAAC,CACrB,CAAA;IAED,MAAM,cAAc,GAAG,IAAA,mBAAW,EAChC,CAAC,KAAsB,EAAE,EAAE;QACzB,eAAe,CAAC,OAAO,GAAG,KAAK,CAAA;QAC/B,UAAU,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC,EACD,CAAC,UAAU,CAAC,CACb,CAAA;IAED,OAAO,CACL,CAAC,6BAAa,CACZ,GAAG,CAAC,CAAC,SAAS,CAAC,CACf,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACjC,YAAY,CAAC,CAAC,YAAY,CAAC,CAC3B,eAAe,CAAC,CAAC,eAAe,CAAC,CACjC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,SAAS,CAAC,CAAC,SAAS,CAAC,CACrB,cAAc,CAAC,CAAC,cAAc,CAAC,CAC/B,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,SAAS,CAAC,CAAC,SAAS,CAAC,CACrB,gBAAgB,CAAC,CAAC,gBAAgB,CAAC,CACnC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAC3D,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAC/B,YAAY,CAAC,CAAC,gBAAgB,CAAC,CAC/B,eAAe,CAAC,CAAC,mBAAmB,CAAC,CACrC,kBAAkB,CAAC,CAAC,sBAAsB,CAAC,CAC3C,UAAU,CAAC,CAAC,cAAc,CAAC,CAE3B;MAAA,CAAC,kBAAkB,IAAI,CACrB,CAAC,mCAAgB,CAAC,eAAe,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,mCAAgB,CAAC,CACjF,CAED;;MAAA,CAAC,mBAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAI,CAC/C;IAAA,EAAE,6BAAa,CAAC,CACjB,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,MAAM,MAAM,GAAG,yBAAU,CAAC,MAAM,CAAC;IAC/B,SAAS,EAAE;QACT,uDAAuD;QACvD,8DAA8D;QAC9D,QAAQ,EAAE,uBAAQ,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KACvD;IACD,OAAO,EAAE;QACP,KAAK,EAAE,MAAM;KACd;CACF,CAAC,CAAA;AAEF,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AASnC,MAAM,eAAe,GAAG,SAAgC,CAAA;AAExD,eAAe,CAAC,IAAI,GAAG,CAAC,YAAoB,EAAE,EAAE;IAC9C,IAAI,OAAO,IAAI,CAAC,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;QACxE,OAAM;IACR,CAAC;IACD,IAAA,6BAAS,EAAC,YAAY,CAAC,CAAA;AACzB,CAAC,CAAA;AAED,eAAe,CAAC,KAAK,GAAG,CAAC,YAAoB,EAAE,QAAkB,EAAE,EAAE;IACnE,IAAI,OAAO,IAAI,CAAC,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAA;QACzE,OAAM;IACR,CAAC;IACD,IAAA,8BAAU,EAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;AACpC,CAAC,CAAA;AAED,eAAe,CAAC,QAAQ,GAAG,CAAC,QAAkB,EAAE,EAAE;IAChD,IAAA,4BAAQ,EAAC,QAAQ,CAAC,CAAA;AACpB,CAAC,CAAA;AAED,kBAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"Swipeable.js","sourceRoot":"","sources":["../src/Swipeable.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { ReactNode, Ref } from 'react';
2
- import { ViewProps, StyleProp, ViewStyle } from 'react-native';
1
+ import type { ReactNode, Ref } from 'react';
2
+ import type { StyleProp, ViewProps, ViewStyle } from 'react-native';
3
3
  export interface SwipeProgressEvent {
4
4
  nativeEvent: {
5
5
  progress: number;
@@ -1 +1 @@
1
- {"version":3,"file":"Swipeable.types.d.ts","sourceRoot":"","sources":["../src/Swipeable.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Swipeable.types.d.ts","sourceRoot":"","sources":["../src/Swipeable.types.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import React, { ReactNode } from 'react';
1
+ import type { ReactNode } from 'react';
2
2
  /**
3
3
  * Props for SwipeableActions component
4
4
  */
@@ -7,11 +7,13 @@ export interface SwipeableActionsProps {
7
7
  children: ReactNode;
8
8
  /** Position of actions: 'left' or 'right' */
9
9
  actionsPosition: 'left' | 'right';
10
+ /** Test ID for e2e testing */
11
+ testID?: string;
10
12
  }
11
13
  /**
12
14
  * SwipeableActions - Internal layout component for swipeable actions
13
15
  *
14
16
  * Handles entrance animation when children mount.
15
17
  */
16
- export declare function SwipeableActions({ children, actionsPosition }: SwipeableActionsProps): React.JSX.Element;
18
+ export declare function SwipeableActions({ children, actionsPosition, testID }: SwipeableActionsProps): import("react").JSX.Element;
17
19
  //# sourceMappingURL=SwipeableActions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SwipeableActions.d.ts","sourceRoot":"","sources":["../src/SwipeableActions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGxC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,kCAAkC;IAClC,QAAQ,EAAE,SAAS,CAAA;IACnB,6CAA6C;IAC7C,eAAe,EAAE,MAAM,GAAG,OAAO,CAAA;CAClC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,qBAAqB,qBASpF"}
1
+ {"version":3,"file":"SwipeableActions.d.ts","sourceRoot":"","sources":["../src/SwipeableActions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,kCAAkC;IAClC,QAAQ,EAAE,SAAS,CAAA;IACnB,6CAA6C;IAC7C,eAAe,EAAE,MAAM,GAAG,OAAO,CAAA;IACjC,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,qBAAqB,+BAU5F"}
@@ -1,18 +1,14 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.SwipeableActions = SwipeableActions;
7
- const react_1 = __importDefault(require("react"));
8
4
  const react_native_1 = require("react-native");
9
5
  /**
10
6
  * SwipeableActions - Internal layout component for swipeable actions
11
7
  *
12
8
  * Handles entrance animation when children mount.
13
9
  */
14
- function SwipeableActions({ children, actionsPosition }) {
15
- return (<react_native_1.View style={actionsPosition === 'left' ? styles.actionsLeading : styles.actionsTrailing} pointerEvents={children ? 'auto' : 'none'}>
10
+ function SwipeableActions({ children, actionsPosition, testID }) {
11
+ return (<react_native_1.View style={actionsPosition === 'left' ? styles.actionsLeading : styles.actionsTrailing} pointerEvents={children ? 'auto' : 'none'} testID={testID}>
16
12
  {children}
17
13
  </react_native_1.View>);
18
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SwipeableActions.js","sourceRoot":"","sources":["../src/SwipeableActions.tsx"],"names":[],"mappings":";;;;;AAkBA,4CASC;AA3BD,kDAAwC;AACxC,+CAA+C;AAY/C;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAyB;IACnF,OAAO,CACL,CAAC,mBAAI,CACH,KAAK,CAAC,CAAC,eAAe,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CACnF,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAE1C;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,MAAM,GAAG,yBAAU,CAAC,MAAM,CAAC;IAC/B,eAAe,EAAE;QACf,GAAG,yBAAU,CAAC,YAAY;QAC1B,aAAa,EAAE,KAAK;QACpB,cAAc,EAAE,UAAU;KAC3B;IACD,cAAc,EAAE;QACd,GAAG,yBAAU,CAAC,YAAY;QAC1B,aAAa,EAAE,KAAK;QACpB,cAAc,EAAE,YAAY;KAC7B;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"SwipeableActions.js","sourceRoot":"","sources":["../src/SwipeableActions.tsx"],"names":[],"mappings":";;AAoBA,4CAUC;AA7BD,+CAA+C;AAc/C;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAyB;IAC3F,OAAO,CACL,CAAC,mBAAI,CACH,KAAK,CAAC,CAAC,eAAe,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CACnF,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAC1C,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,MAAM,GAAG,yBAAU,CAAC,MAAM,CAAC;IAC/B,eAAe,EAAE;QACf,GAAG,yBAAU,CAAC,YAAY;QAC1B,aAAa,EAAE,KAAK;QACpB,cAAc,EAAE,UAAU;KAC3B;IACD,cAAc,EAAE;QACd,GAAG,yBAAU,CAAC,YAAY;QAC1B,aAAa,EAAE,KAAK;QACpB,cAAc,EAAE,YAAY;KAC7B;CACF,CAAC,CAAA"}
@@ -1,8 +1,9 @@
1
- import { SwipeableViewProps, NativeSwipeableRef } from './Swipeable.types';
1
+ import type { NativeSwipeableRef, SwipeableViewProps } from './Swipeable.types';
2
2
  interface SwipeableNativeModule {
3
3
  openByKey: (key: string) => void;
4
4
  closeByKey: (key: string, animated?: boolean) => void;
5
5
  closeAll: (animated?: boolean) => void;
6
+ isOpenByKey: (key: string) => boolean;
6
7
  }
7
8
  export declare const SwipeableModule: SwipeableNativeModule;
8
9
  export declare const SwipeableView: import("react").ForwardRefExoticComponent<SwipeableViewProps & import("react").RefAttributes<NativeSwipeableRef>>;
@@ -1 +1 @@
1
- {"version":3,"file":"SwipeableView.d.ts","sourceRoot":"","sources":["../src/SwipeableView.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAK1E,UAAU,qBAAqB;IAC7B,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrD,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAED,eAAO,MAAM,eAAe,uBAA0D,CAAA;AAEtF,eAAO,MAAM,aAAa,mHAIzB,CAAA"}
1
+ {"version":3,"file":"SwipeableView.d.ts","sourceRoot":"","sources":["../src/SwipeableView.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAK/E,UAAU,qBAAqB;IAC7B,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrD,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CACtC;AAED,eAAO,MAAM,eAAe,uBAA0D,CAAA;AAEtF,eAAO,MAAM,aAAa,mHAIzB,CAAA"}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SwipeableView = exports.SwipeableModule = void 0;
4
- const react_1 = require("react");
5
4
  const expo_modules_core_1 = require("expo-modules-core");
5
+ const react_1 = require("react");
6
6
  const NativeView = (0, expo_modules_core_1.requireNativeViewManager)('Swipeable');
7
7
  exports.SwipeableModule = (0, expo_modules_core_1.requireNativeModule)('Swipeable');
8
8
  exports.SwipeableView = (0, react_1.forwardRef)(function SwipeableView(props, ref) {
@@ -1 +1 @@
1
- {"version":3,"file":"SwipeableView.js","sourceRoot":"","sources":["../src/SwipeableView.tsx"],"names":[],"mappings":";;;AAAA,iCAAiE;AACjE,yDAAiF;AAGjF,MAAM,UAAU,GAAG,IAAA,4CAAwB,EAAqB,WAAW,CAAC,CAAA;AAS/D,QAAA,eAAe,GAAG,IAAA,uCAAmB,EAAwB,WAAW,CAAC,CAAA;AAEzE,QAAA,aAAa,GAAG,IAAA,kBAAU,EACrC,SAAS,aAAa,CAAC,KAAK,EAAE,GAAG;IAC/B,OAAO,IAAA,qBAAa,EAAC,UAAU,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,EAAuC,CAAC,CAAA;AAC1F,CAAC,CACF,CAAA;AAED,qBAAa,CAAC,WAAW,GAAG,eAAe,CAAA"}
1
+ {"version":3,"file":"SwipeableView.js","sourceRoot":"","sources":["../src/SwipeableView.tsx"],"names":[],"mappings":";;;AAAA,yDAAiF;AACjF,iCAAsE;AAGtE,MAAM,UAAU,GAAG,IAAA,4CAAwB,EAAqB,WAAW,CAAC,CAAA;AAU/D,QAAA,eAAe,GAAG,IAAA,uCAAmB,EAAwB,WAAW,CAAC,CAAA;AAEzE,QAAA,aAAa,GAAG,IAAA,kBAAU,EACrC,SAAS,aAAa,CAAC,KAAK,EAAE,GAAG;IAC/B,OAAO,IAAA,qBAAa,EAAC,UAAU,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,EAAuC,CAAC,CAAA;AAC1F,CAAC,CACF,CAAA;AAED,qBAAa,CAAC,WAAW,GAAG,eAAe,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
+ export { SWIPE_DEFAULTS, SWIPE_PROGRESS } from './constants';
2
+ export type { NativeModuleError, SwipeableErrorHandler } from './nativeModuleUtils';
3
+ export { setGlobalErrorHandler } from './nativeModuleUtils';
1
4
  export { default as Swipeable } from './Swipeable';
5
+ export type { NativeSwipeableRef, SwipeableMethods, SwipeableProps, SwipeableStatic, SwipeableViewProps, SwipeProgressEvent, SwipeStateEvent } from './Swipeable.types';
2
6
  export { SwipeableView } from './SwipeableView';
3
- export type { SwipeableProps, SwipeableMethods, SwipeableStatic, SwipeableViewProps, SwipeProgressEvent, SwipeStateEvent, NativeSwipeableRef } from './Swipeable.types';
4
- export { SWIPE_PROGRESS, SWIPE_DEFAULTS } from './constants';
5
- export { setGlobalErrorHandler } from './nativeModuleUtils';
6
- export type { SwipeableErrorHandler, NativeModuleError } from './nativeModuleUtils';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EACnB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAG5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5D,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAEnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAClD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA"}
package/build/index.js CHANGED
@@ -3,15 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.setGlobalErrorHandler = exports.SWIPE_DEFAULTS = exports.SWIPE_PROGRESS = exports.SwipeableView = exports.Swipeable = void 0;
7
- var Swipeable_1 = require("./Swipeable");
8
- Object.defineProperty(exports, "Swipeable", { enumerable: true, get: function () { return __importDefault(Swipeable_1).default; } });
9
- var SwipeableView_1 = require("./SwipeableView");
10
- Object.defineProperty(exports, "SwipeableView", { enumerable: true, get: function () { return SwipeableView_1.SwipeableView; } });
6
+ exports.SwipeableView = exports.Swipeable = exports.setGlobalErrorHandler = exports.SWIPE_PROGRESS = exports.SWIPE_DEFAULTS = void 0;
11
7
  var constants_1 = require("./constants");
12
- Object.defineProperty(exports, "SWIPE_PROGRESS", { enumerable: true, get: function () { return constants_1.SWIPE_PROGRESS; } });
13
8
  Object.defineProperty(exports, "SWIPE_DEFAULTS", { enumerable: true, get: function () { return constants_1.SWIPE_DEFAULTS; } });
9
+ Object.defineProperty(exports, "SWIPE_PROGRESS", { enumerable: true, get: function () { return constants_1.SWIPE_PROGRESS; } });
14
10
  // Error handling utilities
15
11
  var nativeModuleUtils_1 = require("./nativeModuleUtils");
16
12
  Object.defineProperty(exports, "setGlobalErrorHandler", { enumerable: true, get: function () { return nativeModuleUtils_1.setGlobalErrorHandler; } });
13
+ var Swipeable_1 = require("./Swipeable");
14
+ Object.defineProperty(exports, "Swipeable", { enumerable: true, get: function () { return __importDefault(Swipeable_1).default; } });
15
+ var SwipeableView_1 = require("./SwipeableView");
16
+ Object.defineProperty(exports, "SwipeableView", { enumerable: true, get: function () { return SwipeableView_1.SwipeableView; } });
17
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAkD;AAAzC,uHAAA,OAAO,OAAa;AAC7B,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AAYtB,yCAA4D;AAAnD,2GAAA,cAAc,OAAA;AAAE,2GAAA,cAAc,OAAA;AAEvC,2BAA2B;AAC3B,yDAA2D;AAAlD,0HAAA,qBAAqB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,yCAA4D;AAAnD,2GAAA,cAAc,OAAA;AAAE,2GAAA,cAAc,OAAA;AAEvC,2BAA2B;AAC3B,yDAA2D;AAAlD,0HAAA,qBAAqB,OAAA;AAC9B,yCAAkD;AAAzC,uHAAA,OAAO,OAAa;AAU7B,iDAA+C;AAAtC,8GAAA,aAAa,OAAA"}
@@ -8,4 +8,5 @@ export declare function setGlobalErrorHandler(handler: SwipeableErrorHandler | u
8
8
  export declare function openByKey(key: string): void;
9
9
  export declare function closeByKey(key: string, animated?: boolean): void;
10
10
  export declare function closeAll(animated?: boolean): void;
11
+ export declare function isOpenByKey(key: string): boolean;
11
12
  //# sourceMappingURL=nativeModuleUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nativeModuleUtils.d.ts","sourceRoot":"","sources":["../src/nativeModuleUtils.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,KACT,IAAI,CAAA;AAIT,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,GAAG,IAAI,CAEtF;AAgBD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAM3C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAMhE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAMjD"}
1
+ {"version":3,"file":"nativeModuleUtils.d.ts","sourceRoot":"","sources":["../src/nativeModuleUtils.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,KACT,IAAI,CAAA;AAIT,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,GAAG,IAAI,CAEtF;AAgBD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAM3C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAMhE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAMjD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMhD"}
@@ -4,6 +4,7 @@ exports.setGlobalErrorHandler = setGlobalErrorHandler;
4
4
  exports.openByKey = openByKey;
5
5
  exports.closeByKey = closeByKey;
6
6
  exports.closeAll = closeAll;
7
+ exports.isOpenByKey = isOpenByKey;
7
8
  const SwipeableView_1 = require("./SwipeableView");
8
9
  let globalErrorHandler;
9
10
  function setGlobalErrorHandler(handler) {
@@ -46,4 +47,12 @@ function closeAll(animated) {
46
47
  handleNativeError(error, 'closeAll');
47
48
  }
48
49
  }
50
+ function isOpenByKey(key) {
51
+ try {
52
+ return SwipeableView_1.SwipeableModule.isOpenByKey(key);
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
49
58
  //# sourceMappingURL=nativeModuleUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nativeModuleUtils.js","sourceRoot":"","sources":["../src/nativeModuleUtils.ts"],"names":[],"mappings":";;AAgBA,sDAEC;AAgBD,8BAMC;AAED,gCAMC;AAED,4BAMC;AAxDD,mDAAiD;AAcjD,IAAI,kBAAqD,CAAA;AAEzD,SAAgB,qBAAqB,CAAC,OAA0C;IAC9E,kBAAkB,GAAG,OAAO,CAAA;AAC9B,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,SAAiB,EAAE,GAAY;IACxE,MAAM,WAAW,GAAsB;QACrC,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/D,GAAG,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpF,CAAA;IAED,IAAI,kBAAkB,EAAE,CAAC;QACvB,kBAAkB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;IACjD,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,eAAe,SAAS,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IACxE,CAAC;AACH,CAAC;AAED,SAAgB,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,+BAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW,EAAE,QAAkB;IACxD,IAAI,CAAC;QACH,+BAAe,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC;AAED,SAAgB,QAAQ,CAAC,QAAkB;IACzC,IAAI,CAAC;QACH,+BAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IACtC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"nativeModuleUtils.js","sourceRoot":"","sources":["../src/nativeModuleUtils.ts"],"names":[],"mappings":";;AAgBA,sDAEC;AAgBD,8BAMC;AAED,gCAMC;AAED,4BAMC;AAED,kCAMC;AAhED,mDAAiD;AAcjD,IAAI,kBAAqD,CAAA;AAEzD,SAAgB,qBAAqB,CAAC,OAA0C;IAC9E,kBAAkB,GAAG,OAAO,CAAA;AAC9B,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,SAAiB,EAAE,GAAY;IACxE,MAAM,WAAW,GAAsB;QACrC,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/D,GAAG,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpF,CAAA;IAED,IAAI,kBAAkB,EAAE,CAAC;QACvB,kBAAkB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;IACjD,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,eAAe,SAAS,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IACxE,CAAC;AACH,CAAC;AAED,SAAgB,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,+BAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW,EAAE,QAAkB;IACxD,IAAI,CAAC;QACH,+BAAe,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC;AAED,SAAgB,QAAQ,CAAC,QAAkB;IACzC,IAAI,CAAC;QACH,+BAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IACtC,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,OAAO,+BAAe,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,57 @@
1
+ import Foundation
2
+
3
+ /// Thread-safe LRU cache for tracking open/closed state of swipeable views by recycling key.
4
+ /// Used by the static registry in SwipeableView to persist state across list recycling.
5
+ public class OpenStateCache {
6
+ private let queue: DispatchQueue
7
+ private let maxSize: Int
8
+ private var cache: [String: Bool] = [:]
9
+ private var insertionOrder: [String] = []
10
+
11
+ public init(maxSize: Int = 1000, queueLabel: String = "com.swipeable.openstate") {
12
+ self.maxSize = maxSize
13
+ self.queue = DispatchQueue(label: queueLabel, qos: .userInteractive)
14
+ }
15
+
16
+ /// Read the cached open state for a key. Returns false if not found.
17
+ public func get(_ key: String) -> Bool {
18
+ queue.sync { cache[key] ?? false }
19
+ }
20
+
21
+ /// Set the open state for a key. Promotes existing keys to most-recently-used.
22
+ /// Evicts the least-recently-used entry when cache exceeds max size.
23
+ public func set(_ key: String, isOpen: Bool) {
24
+ queue.async(flags: .barrier) { [self] in
25
+ if cache[key] != nil {
26
+ insertionOrder.removeAll { $0 == key }
27
+ }
28
+ insertionOrder.append(key)
29
+ cache[key] = isOpen
30
+ if insertionOrder.count > maxSize {
31
+ let oldest = insertionOrder.removeFirst()
32
+ cache.removeValue(forKey: oldest)
33
+ }
34
+ }
35
+ }
36
+
37
+ /// Remove a specific key from the cache.
38
+ public func clear(_ key: String) {
39
+ queue.async(flags: .barrier) { [self] in
40
+ cache.removeValue(forKey: key)
41
+ insertionOrder.removeAll { $0 == key }
42
+ }
43
+ }
44
+
45
+ /// Remove all entries from the cache.
46
+ public func clearAll() {
47
+ queue.async(flags: .barrier) { [self] in
48
+ cache.removeAll()
49
+ insertionOrder.removeAll()
50
+ }
51
+ }
52
+
53
+ /// Synchronously return the number of entries (for testing).
54
+ public var count: Int {
55
+ queue.sync { cache.count }
56
+ }
57
+ }
package/ios/Package.swift CHANGED
@@ -17,7 +17,7 @@ let package = Package(
17
17
  "SwipeableModule.swift",
18
18
  "react-native-swipeable-actions.podspec"
19
19
  ],
20
- sources: ["SwipePhysics.swift", "SwipeAnimationConfig.swift"]
20
+ sources: ["SwipePhysics.swift", "SwipeAnimationConfig.swift", "OpenStateCache.swift"]
21
21
  ),
22
22
  .testTarget(
23
23
  name: "SwipeableActionsTests",
@@ -17,6 +17,10 @@ public class SwipeableModule: Module {
17
17
  SwipeableView.closeAll(animated: animated ?? true)
18
18
  }
19
19
 
20
+ Function("isOpenByKey") { (key: String) -> Bool in
21
+ SwipeableView.getOpenState(for: key)
22
+ }
23
+
20
24
  View(SwipeableView.self) {
21
25
  // Props
22
26
  Prop("actionsWidth") { (view: SwipeableView, width: CGFloat) in
@@ -31,13 +31,23 @@ public class SwipeableView: ExpoView {
31
31
  return typeName.contains("SurfaceTouchHandler") || typeName.contains("RCTTouchHandler")
32
32
  }
33
33
 
34
- /// Walk from a hit-tested view up to (but not including) self, checking for gesture recognizers.
35
- /// Any child view with a gesture recognizer (RNGH, custom, etc.) takes priority over our pan.
36
- private func hasChildGesture(from view: UIView) -> Bool {
34
+ /// Check if a gesture recognizer belongs to react-native-gesture-handler.
35
+ /// RNGH uses custom recognizer classes prefixed with "RNBetter" (e.g. RNBetterPanGestureRecognizer)
36
+ /// and "RNManualActivation" for manual activation recognizers.
37
+ private static func isRNGHGestureHandler(_ recognizer: UIGestureRecognizer) -> Bool {
38
+ let typeName = String(describing: type(of: recognizer))
39
+ return typeName.hasPrefix("RNBetter") || typeName.hasPrefix("RNManualActivation")
40
+ }
41
+
42
+ /// Walk from a hit-tested view up to (but not including) self, checking for RNGH recognizers.
43
+ /// Used to prevent our pan gesture from beginning when the touch landed on a RNGH-managed view.
44
+ private func hasRNGHGesture(from view: UIView) -> Bool {
37
45
  var current: UIView? = view
38
46
  while let v = current, v !== self {
39
- if !(v.gestureRecognizers ?? []).isEmpty {
40
- return true
47
+ for recognizer in v.gestureRecognizers ?? [] {
48
+ if Self.isRNGHGestureHandler(recognizer) {
49
+ return true
50
+ }
41
51
  }
42
52
  current = v.superview
43
53
  }
@@ -47,15 +57,15 @@ public class SwipeableView: ExpoView {
47
57
  // MARK: - Thread-Safe Static Registry
48
58
 
49
59
  private static let registryQueue = DispatchQueue(label: "com.swipeable.registry", qos: .userInteractive)
50
- private static var _openStateCache: [String: Bool] = [:]
60
+ static let openStateCache = OpenStateCache()
51
61
  private static var _viewRegistry: [String: WeakRef<SwipeableView>] = [:]
52
62
 
53
- private static func getOpenState(for key: String) -> Bool {
54
- registryQueue.sync { _openStateCache[key] ?? false }
63
+ static func getOpenState(for key: String) -> Bool {
64
+ openStateCache.get(key)
55
65
  }
56
66
 
57
67
  private static func setOpenState(for key: String, isOpen: Bool) {
58
- registryQueue.async(flags: .barrier) { _openStateCache[key] = isOpen }
68
+ openStateCache.set(key, isOpen: isOpen)
59
69
  }
60
70
 
61
71
  private static func getView(for key: String) -> SwipeableView? {
@@ -71,7 +81,7 @@ public class SwipeableView: ExpoView {
71
81
  }
72
82
 
73
83
  private static func clearOpenState(for key: String) {
74
- registryQueue.async(flags: .barrier) { _openStateCache.removeValue(forKey: key) }
84
+ openStateCache.clear(key)
75
85
  }
76
86
 
77
87
  private static func getAllViews() -> [SwipeableView] {
@@ -215,7 +225,11 @@ public class SwipeableView: ExpoView {
215
225
 
216
226
  // Apply using local shouldOpen (pendingShouldOpen was cleared by close)
217
227
  if shouldOpen {
218
- DispatchQueue.main.async { [weak self] in self?.snapToOpen() }
228
+ let keyAtDispatch = recyclingKey
229
+ DispatchQueue.main.async { [weak self] in
230
+ guard let self = self, self.recyclingKey == keyAtDispatch else { return }
231
+ self.snapToOpen()
232
+ }
219
233
  }
220
234
  }
221
235
  }
@@ -291,17 +305,16 @@ public class SwipeableView: ExpoView {
291
305
  currentAnimator = nil
292
306
  isAnimating = false
293
307
 
294
- // Reset layer properties to prevent corruption
295
- contentView?.transform = .identity
296
- contentView?.layer.zPosition = 0
297
- actionsView?.transform = .identity
298
- actionsView?.layer.zPosition = 0
299
-
300
- // Unregister from static registry and clear cached state
308
+ // Unregister from static registry (re-registered in didMoveToWindow)
301
309
  if let key = recyclingKey {
302
310
  Self.unregisterView(for: key)
303
- Self.clearOpenState(for: key)
304
311
  }
312
+
313
+ // Nil view references so didAddSubview correctly detects new children
314
+ // on re-insertion (wasActionsNil/wasContentNil guards).
315
+ // Do NOT reset transforms - Fabric DELETE+INSERT must preserve open visual state.
316
+ contentView = nil
317
+ actionsView = nil
305
318
  }
306
319
  super.willMove(toSuperview: newSuperview)
307
320
  }
@@ -329,6 +342,28 @@ public class SwipeableView: ExpoView {
329
342
  panGesture.view?.removeGestureRecognizer(panGesture)
330
343
  addGestureRecognizer(panGesture)
331
344
  }
345
+
346
+ // Restore visual state after Fabric reorder (DELETE+INSERT cycle).
347
+ // Fabric may reset child transforms during prop reconciliation. Re-apply
348
+ // on next runloop tick to ensure we run after Fabric finishes mutations.
349
+ if isOpen && currentTranslation != 0 {
350
+ DispatchQueue.main.async { [weak self] in
351
+ guard let self = self,
352
+ self.isOpen,
353
+ self.currentTranslation != 0,
354
+ !self.isDragging,
355
+ !self.isAnimating else { return }
356
+ self.contentView?.transform = CGAffineTransform(translationX: self.currentTranslation, y: 0)
357
+ self.contentView?.layer.zPosition = 1
358
+ self.actionsView?.layer.zPosition = -1
359
+ self.updateActionsTransform()
360
+ }
361
+
362
+ // Restart autoClose timer if it was cancelled during detach
363
+ if autoClose {
364
+ scheduleAutoClose()
365
+ }
366
+ }
332
367
  }
333
368
 
334
369
  public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
@@ -422,6 +457,9 @@ public class SwipeableView: ExpoView {
422
457
  var translation = currentTranslation
423
458
  if isAnimating, let presentationLayer = contentView?.layer.presentation() {
424
459
  translation = presentationLayer.transform.m41 // tx component of transform
460
+ // Keep currentTranslation in sync so layoutSubviews and other guards
461
+ // see the real position, not a stale value from before animation started.
462
+ currentTranslation = translation
425
463
  // Update actions to match content position
426
464
  let progress = min(abs(translation) / actionsWidth, 1.0)
427
465
  let offset = isLeading ? -actionsWidth : actionsWidth
@@ -516,7 +554,7 @@ public class SwipeableView: ExpoView {
516
554
  }
517
555
  }
518
556
 
519
- if currentTranslation != 0 {
557
+ if isOpen && currentTranslation != 0 {
520
558
  contentView?.transform = CGAffineTransform(translationX: currentTranslation, y: 0)
521
559
  updateActionsTransform()
522
560
  }
@@ -875,11 +913,11 @@ extension SwipeableView: UIGestureRecognizerDelegate {
875
913
  let shouldBegin = isOpen || (isLeading ? velocity.x > 0 : velocity.x < 0)
876
914
 
877
915
  if shouldBegin {
878
- // Prevent our pan from starting when the touch is on a child view that has
879
- // its own gesture recognizers (e.g. RNGH). Delegate-based conflict resolution
880
- // doesn't work with RNGH (it overrides delegates), so we yield via hit-test.
916
+ // Prevent our pan from starting when the touch is on a RNGH-managed view.
917
+ // Delegate-based conflict resolution is broken with RNGH (it overrides delegates),
918
+ // so we use hit-test prevention instead.
881
919
  let touchPoint = pan.location(in: self)
882
- if let hitView = super.hitTest(touchPoint, with: nil), hasChildGesture(from: hitView) {
920
+ if let hitView = super.hitTest(touchPoint, with: nil), hasRNGHGesture(from: hitView) {
883
921
  return false
884
922
  }
885
923
  cancelFabricTouches()
package/jestSetup.js CHANGED
@@ -5,7 +5,8 @@ jest.mock('./src/SwipeableView.tsx', () => {
5
5
  const SwipeableModule = {
6
6
  openByKey: jest.fn(),
7
7
  closeByKey: jest.fn(),
8
- closeAll: jest.fn()
8
+ closeAll: jest.fn(),
9
+ isOpenByKey: jest.fn().mockReturnValue(false)
9
10
  }
10
11
 
11
12
  const SwipeableView = React.forwardRef((props, ref) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-swipeable-actions",
3
- "version": "0.1.5",
3
+ "version": "0.1.7-canary.0",
4
4
  "description": "High-performance native swipeable row component for React Native using Expo Modules",
5
5
  "main": "src/index.ts",
6
6
  "types": "build/index.d.ts",
@@ -27,10 +27,11 @@
27
27
  "test:all": "npm test && npm run test:ios && npm run test:android",
28
28
  "test:watch": "jest --watch",
29
29
  "test:coverage": "jest --coverage",
30
- "lint": "eslint src --ext .ts,.tsx",
31
- "lint:fix": "eslint src --ext .ts,.tsx --fix",
32
- "format": "prettier --write src",
33
- "format:check": "prettier --check src",
30
+ "lint": "biome lint src example e2e",
31
+ "lint:fix": "biome lint --write src example e2e",
32
+ "format": "biome format --write src example e2e",
33
+ "format:check": "biome format src example e2e",
34
+ "check": "biome check src example e2e",
34
35
  "typecheck": "tsc --noEmit",
35
36
  "android": "expo run:android",
36
37
  "ios": "expo run:ios",
@@ -64,19 +65,13 @@
64
65
  "react-native": ">=0.73.0"
65
66
  },
66
67
  "devDependencies": {
68
+ "@biomejs/biome": "2.4.9",
67
69
  "@testing-library/react-native": "^12.4.0",
68
70
  "@types/jest": "^29.5.0",
69
71
  "@types/react": "19.1.1",
70
- "@typescript-eslint/eslint-plugin": "^6.0.0",
71
- "@typescript-eslint/parser": "^6.0.0",
72
- "eslint": "^8.57.0",
73
- "eslint-config-prettier": "^9.1.0",
74
- "eslint-plugin-react": "^7.34.0",
75
- "eslint-plugin-react-hooks": "^4.6.0",
76
72
  "expo-modules-core": "^3.0.26",
77
73
  "jest": "^29.7.0",
78
- "prettier": "^3.2.0",
79
- "prettier-config-holepunch": "^2.0.0",
74
+ "prettier": "^3.8.1",
80
75
  "react": "19.1.1",
81
76
  "react-native": "0.82.1",
82
77
  "react-test-renderer": "19.1.1",
package/src/Swipeable.tsx CHANGED
@@ -1,17 +1,16 @@
1
- import { forwardRef, useImperativeHandle, useRef, useCallback, useState } from 'react'
2
- import { StyleSheet, View, Platform } from 'react-native'
3
-
4
- import { SwipeableView } from './SwipeableView'
5
- import { SwipeableActions } from './SwipeableActions'
6
- import {
7
- SwipeableProps,
1
+ import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
2
+ import { Platform, StyleSheet, View } from 'react-native'
3
+ import { SWIPE_DEFAULTS } from './constants'
4
+ import { closeAll, closeByKey, isOpenByKey, openByKey } from './nativeModuleUtils'
5
+ import type {
6
+ NativeSwipeableRef,
8
7
  SwipeableMethods,
8
+ SwipeableProps,
9
9
  SwipeProgressEvent,
10
- SwipeStateEvent,
11
- NativeSwipeableRef
10
+ SwipeStateEvent
12
11
  } from './Swipeable.types'
13
- import { SWIPE_DEFAULTS } from './constants'
14
- import { openByKey, closeByKey, closeAll } from './nativeModuleUtils'
12
+ import { SwipeableActions } from './SwipeableActions'
13
+ import { SwipeableView } from './SwipeableView'
15
14
 
16
15
  function normalizeRecyclingKey(key: string | number | undefined): string | undefined {
17
16
  if (key == null) return undefined
@@ -47,15 +46,32 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(function Swipeabl
47
46
  ref
48
47
  ) {
49
48
  const nativeRef = useRef<NativeSwipeableRef>(null)
50
- const [hasActionsRendered, setHasActionsRendered] = useState(false)
51
- const swipeStartedRef = useRef(false)
52
49
 
53
- // Normalize and sync recyclingKey to ref for use in useImperativeHandle
54
- // (set during render to ensure it's always current before callbacks fire)
50
+ // Normalize recyclingKey before hooks that depend on it
55
51
  const normalizedKey = normalizeRecyclingKey(recyclingKey)
56
52
  const recyclingKeyRef = useRef<string | undefined>(undefined)
57
53
  recyclingKeyRef.current = normalizedKey
58
54
 
55
+ // Initialize from native cache: if this recyclingKey was open, render actions immediately.
56
+ // This handles FlatList remounting components during data reorder - React state is lost
57
+ // but native cache preserves the open state.
58
+ const [hasActionsRendered, setHasActionsRendered] = useState(() => {
59
+ return normalizedKey != null && isOpenByKey(normalizedKey)
60
+ })
61
+ const swipeStartedRef = useRef(false)
62
+ const initialKeyRef = useRef(normalizedKey)
63
+
64
+ // When recyclingKey changes (FlatList reorder/recycle), sync hasActionsRendered
65
+ // with the native cached open state. FlatList reuses component instances without
66
+ // remounting, so useState initializer doesn't re-run. Skip on initial mount
67
+ // since the useState initializer already handled it.
68
+ useEffect(() => {
69
+ if (!normalizedKey) return
70
+ if (normalizedKey === initialKeyRef.current) return
71
+ initialKeyRef.current = normalizedKey
72
+ setHasActionsRendered(isOpenByKey(normalizedKey))
73
+ }, [normalizedKey])
74
+
59
75
  // Development-time validation
60
76
  if (__DEV__) {
61
77
  if (autoClose && recyclingKey == null) {
@@ -144,7 +160,12 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(function Swipeabl
144
160
  onSwipeEnd={handleSwipeEnd}
145
161
  >
146
162
  {hasActionsRendered && (
147
- <SwipeableActions actionsPosition={actionsPosition}>{actions}</SwipeableActions>
163
+ <SwipeableActions
164
+ actionsPosition={actionsPosition}
165
+ {...(testID ? { testID: `${testID}-actions` } : {})}
166
+ >
167
+ {actions}
168
+ </SwipeableActions>
148
169
  )}
149
170
 
150
171
  <View style={styles.content}>{children}</View>
@@ -1,5 +1,5 @@
1
- import { ReactNode, Ref } from 'react'
2
- import { ViewProps, StyleProp, ViewStyle } from 'react-native'
1
+ import type { ReactNode, Ref } from 'react'
2
+ import type { StyleProp, ViewProps, ViewStyle } from 'react-native'
3
3
 
4
4
  export interface SwipeProgressEvent {
5
5
  nativeEvent: {
@@ -1,4 +1,4 @@
1
- import React, { ReactNode } from 'react'
1
+ import type { ReactNode } from 'react'
2
2
  import { StyleSheet, View } from 'react-native'
3
3
 
4
4
  /**
@@ -9,6 +9,8 @@ export interface SwipeableActionsProps {
9
9
  children: ReactNode
10
10
  /** Position of actions: 'left' or 'right' */
11
11
  actionsPosition: 'left' | 'right'
12
+ /** Test ID for e2e testing */
13
+ testID?: string
12
14
  }
13
15
 
14
16
  /**
@@ -16,11 +18,12 @@ export interface SwipeableActionsProps {
16
18
  *
17
19
  * Handles entrance animation when children mount.
18
20
  */
19
- export function SwipeableActions({ children, actionsPosition }: SwipeableActionsProps) {
21
+ export function SwipeableActions({ children, actionsPosition, testID }: SwipeableActionsProps) {
20
22
  return (
21
23
  <View
22
24
  style={actionsPosition === 'left' ? styles.actionsLeading : styles.actionsTrailing}
23
25
  pointerEvents={children ? 'auto' : 'none'}
26
+ testID={testID}
24
27
  >
25
28
  {children}
26
29
  </View>
@@ -1,6 +1,6 @@
1
- import { forwardRef, createElement, ComponentProps } from 'react'
2
- import { requireNativeViewManager, requireNativeModule } from 'expo-modules-core'
3
- import { SwipeableViewProps, NativeSwipeableRef } from './Swipeable.types'
1
+ import { requireNativeModule, requireNativeViewManager } from 'expo-modules-core'
2
+ import { type ComponentProps, createElement, forwardRef } from 'react'
3
+ import type { NativeSwipeableRef, SwipeableViewProps } from './Swipeable.types'
4
4
 
5
5
  const NativeView = requireNativeViewManager<SwipeableViewProps>('Swipeable')
6
6
 
@@ -9,6 +9,7 @@ interface SwipeableNativeModule {
9
9
  openByKey: (key: string) => void
10
10
  closeByKey: (key: string, animated?: boolean) => void
11
11
  closeAll: (animated?: boolean) => void
12
+ isOpenByKey: (key: string) => boolean
12
13
  }
13
14
 
14
15
  export const SwipeableModule = requireNativeModule<SwipeableNativeModule>('Swipeable')
package/src/index.ts CHANGED
@@ -1,18 +1,15 @@
1
+ export { SWIPE_DEFAULTS, SWIPE_PROGRESS } from './constants'
2
+ export type { NativeModuleError, SwipeableErrorHandler } from './nativeModuleUtils'
3
+ // Error handling utilities
4
+ export { setGlobalErrorHandler } from './nativeModuleUtils'
1
5
  export { default as Swipeable } from './Swipeable'
2
- export { SwipeableView } from './SwipeableView'
3
-
4
6
  export type {
5
- SwipeableProps,
7
+ NativeSwipeableRef,
6
8
  SwipeableMethods,
9
+ SwipeableProps,
7
10
  SwipeableStatic,
8
11
  SwipeableViewProps,
9
12
  SwipeProgressEvent,
10
- SwipeStateEvent,
11
- NativeSwipeableRef
13
+ SwipeStateEvent
12
14
  } from './Swipeable.types'
13
-
14
- export { SWIPE_PROGRESS, SWIPE_DEFAULTS } from './constants'
15
-
16
- // Error handling utilities
17
- export { setGlobalErrorHandler } from './nativeModuleUtils'
18
- export type { SwipeableErrorHandler, NativeModuleError } from './nativeModuleUtils'
15
+ export { SwipeableView } from './SwipeableView'
@@ -55,3 +55,11 @@ export function closeAll(animated?: boolean): void {
55
55
  handleNativeError(error, 'closeAll')
56
56
  }
57
57
  }
58
+
59
+ export function isOpenByKey(key: string): boolean {
60
+ try {
61
+ return SwipeableModule.isOpenByKey(key)
62
+ } catch {
63
+ return false
64
+ }
65
+ }