react-native-swappable-grid 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -70
- package/lib/commonjs/ChildWrapper.js +43 -16
- package/lib/commonjs/ChildWrapper.js.map +1 -1
- package/lib/commonjs/SwappableGrid.js +7 -3
- package/lib/commonjs/SwappableGrid.js.map +1 -1
- package/lib/commonjs/utils/helpers/gestures/PanWithLongPress.js +2 -2
- package/lib/commonjs/utils/helpers/gestures/PanWithLongPress.js.map +1 -1
- package/lib/commonjs/utils/useGridLayout.js +2 -2
- package/lib/commonjs/utils/useGridLayout.js.map +1 -1
- package/lib/module/ChildWrapper.js +43 -16
- package/lib/module/ChildWrapper.js.map +1 -1
- package/lib/module/SwappableGrid.js +7 -3
- package/lib/module/SwappableGrid.js.map +1 -1
- package/lib/module/utils/helpers/gestures/PanWithLongPress.js +2 -2
- package/lib/module/utils/helpers/gestures/PanWithLongPress.js.map +1 -1
- package/lib/module/utils/useGridLayout.js +2 -2
- package/lib/module/utils/useGridLayout.js.map +1 -1
- package/lib/typescript/ChildWrapper.d.ts +6 -1
- package/lib/typescript/SwappableGrid.d.ts +10 -1
- package/lib/typescript/utils/helpers/gestures/PanWithLongPress.d.ts +2 -2
- package/lib/typescript/utils/useGridLayout.d.ts +2 -2
- package/package.json +1 -1
- package/src/ChildWrapper.tsx +52 -16
- package/src/SwappableGrid.tsx +17 -4
- package/src/utils/helpers/gestures/PanWithLongPress.ts +6 -4
- package/src/utils/useGridLayout.ts +3 -3
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ A powerful React Native component for creating draggable, swappable grid layouts
|
|
|
7
7
|
- 🎯 **Drag & Drop**: Long press to drag and reorder items in a grid layout
|
|
8
8
|
- 📐 **Flexible Layout**: Automatic column calculation or fixed number of columns
|
|
9
9
|
- 🎨 **Smooth Animations**: Optional wiggle animation during drag mode
|
|
10
|
-
- 🗑️ **Delete Support**: Built-in hold-to-delete or custom delete component
|
|
10
|
+
- 🗑️ **Delete Support**: Built-in hold-still-to-delete or custom delete component (trashcan)
|
|
11
11
|
- ➕ **Trailing Components**: Support for additional components (e.g., "Add" button)
|
|
12
12
|
- 📜 **Auto-scroll**: Automatic scrolling when dragging near edges
|
|
13
13
|
- 🔄 **Order Tracking**: Callbacks for order changes and drag end events
|
|
@@ -16,6 +16,7 @@ A powerful React Native component for creating draggable, swappable grid layouts
|
|
|
16
16
|
## Example Project
|
|
17
17
|
|
|
18
18
|
To see common usages and examples. Check out the example project 🚀
|
|
19
|
+
|
|
19
20
|
- [react-native-swappable-grid-example-app-repo](https://github.com/WilliamDanielsson/react-native-swappable-grid-example)
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
@@ -41,9 +42,9 @@ yarn add react react-native react-native-gesture-handler react-native-reanimated
|
|
|
41
42
|
- [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation/)
|
|
42
43
|
- [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/)
|
|
43
44
|
|
|
44
|
-
**TLDR**: Wrap your app with the GestureHandlerRootView inside RootLayout in _layout.tsx
|
|
45
|
+
**TLDR**: Wrap your app with the GestureHandlerRootView inside RootLayout in \_layout.tsx
|
|
45
46
|
|
|
46
|
-
Additional fix for now: Disable Strict Mode for Reanimated because of logger warnings did I did not manage to get rid of.
|
|
47
|
+
Additional fix for now: Disable Strict Mode for Reanimated because of logger warnings did I did not manage to get rid of.
|
|
47
48
|
|
|
48
49
|
```tsx
|
|
49
50
|
import { Slot } from "expo-router";
|
|
@@ -113,36 +114,55 @@ const MyComponent = () => {
|
|
|
113
114
|
|
|
114
115
|
### SwappableGrid Props
|
|
115
116
|
|
|
116
|
-
| Prop | Type | Usage
|
|
117
|
-
| ------------------------ | --------------------------------------- | -------- | ------- |
|
|
118
|
-
| `children` | `ReactNode` | Required
|
|
119
|
-
| `itemWidth` | `number` | Required
|
|
120
|
-
| `itemHeight` | `number` | Required
|
|
121
|
-
| `gap` | `number` | Optional
|
|
122
|
-
| `containerPadding` | `number` | Optional
|
|
123
|
-
| `
|
|
124
|
-
| `numColumns` | `number` | Optional
|
|
125
|
-
| `wiggle` | `{ duration: number; degrees: number }` | Optional
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
117
|
+
| Prop | Type | Usage | Default | Description |
|
|
118
|
+
| ------------------------ | --------------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
119
|
+
| `children` | `ReactNode` | Required | - | The child components to render in the grid. Each child should have a unique key. |
|
|
120
|
+
| `itemWidth` | `number` | Required | - | Width of each grid item in pixels |
|
|
121
|
+
| `itemHeight` | `number` | Required | - | Height of each grid item in pixels |
|
|
122
|
+
| `gap` | `number` | Optional | `8` | Gap between grid items in pixels |
|
|
123
|
+
| `containerPadding` | `number` | Optional | `8` | Padding around the container in pixels |
|
|
124
|
+
| `holdToDragMs` | `number` | Optional | `300` | Duration in milliseconds to hold before drag starts |
|
|
125
|
+
| `numColumns` | `number` | Optional | Auto | Number of columns in the grid. If not provided, will be calculated automatically based on container width |
|
|
126
|
+
| `wiggle` | `{ duration: number; degrees: number }` | Optional | - | Wiggle animation configuration when items are in drag mode |
|
|
127
|
+
| `wiggleDeleteMode` | `{ duration: number; degrees: number }` | Optional | - | Wiggle animation configuration specifically for delete mode. If not provided, uses 2x degrees and 0.7x duration of `wiggle` prop |
|
|
128
|
+
| `holdStillToDeleteMs` | `number` | Optional | `1000` | Duration in milliseconds to hold an item still before entering delete mode |
|
|
129
|
+
| `onDragEnd` | `(ordered: ChildNode[]) => void` | Optional | - | Callback fired when drag ends, providing the ordered array of child nodes |
|
|
130
|
+
| `onOrderChange` | `(keys: string[]) => void` | Optional | - | Callback fired when the order changes, providing an array of keys in the new order |
|
|
131
|
+
| `onDelete` | `(key: string) => void` | Optional | - | Callback fired when an item is deleted, providing the key of the deleted item |
|
|
132
|
+
| `dragSizeIncreaseFactor` | `number` | Optional | `1.06` | Factor by which the dragged item scales up |
|
|
133
|
+
| `scrollSpeed` | `number` | Optional | `10` | Speed of auto-scrolling when dragging near edges |
|
|
134
|
+
| `scrollThreshold` | `number` | Optional | `100` | Distance from edge in pixels that triggers auto-scroll |
|
|
135
|
+
| `style` | `StyleProp<ViewStyle>` | Optional | - | Custom style for the ScrollView container |
|
|
136
|
+
| `trailingComponent` | `ReactNode` | Optional | - | Component to render after all grid items (e.g., an "Add" button) |
|
|
137
|
+
| `deleteComponent` | `ReactNode` | Optional | - | Component to render as a delete target (shown when dragging), kind of like a trashcan feature. If provided, disables hold-still-to-delete feature |
|
|
138
|
+
| `deleteComponentStyle` | `StyleProp<ViewStyle>` | Optional | - | Custom style for the delete component. If provided, allows custom positioning |
|
|
139
|
+
| `reverse` | `boolean` | Optional | `false` | If true, reverses the order of items (right-to-left, bottom-to-top) |
|
|
137
140
|
|
|
138
141
|
### SwappableGridRef
|
|
139
142
|
|
|
140
143
|
The component can be used with a ref to access imperative methods:
|
|
141
144
|
|
|
145
|
+
Very useful interactive feature for canceling deleteMode when clicking outside the grid. See [example project](<https://github.com/WilliamDanielsson/react-native-swappable-grid-example/blob/main/app/(tabs)/holdToDelete/index.tsx>) for example usage.
|
|
146
|
+
|
|
142
147
|
```tsx
|
|
148
|
+
import { StyleSheet, Pressable} from "react-native";
|
|
149
|
+
import { SwappableGrid, SwappableGridRef } from "react-native-swappable-grid";
|
|
150
|
+
|
|
143
151
|
const gridRef = useRef<SwappableGridRef>(null);
|
|
144
152
|
|
|
145
|
-
|
|
153
|
+
return (
|
|
154
|
+
<Pressable
|
|
155
|
+
style={StyleSheet.absoluteFill}
|
|
156
|
+
onPress={() => {
|
|
157
|
+
// Cancel delete mode when user taps outside the grid
|
|
158
|
+
if (gridRef.current) {
|
|
159
|
+
gridRef.current.cancelDeleteMode();
|
|
160
|
+
}
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
<SwappableGrid ref={gridRef} ... />
|
|
164
|
+
</Pressable>
|
|
165
|
+
)
|
|
146
166
|
|
|
147
167
|
// Cancel delete mode programmatically
|
|
148
168
|
gridRef.current?.cancelDeleteMode();
|
|
@@ -170,45 +190,16 @@ gridRef.current?.cancelDeleteMode();
|
|
|
170
190
|
</SwappableGrid>
|
|
171
191
|
```
|
|
172
192
|
|
|
173
|
-
###
|
|
174
|
-
|
|
175
|
-
```tsx
|
|
176
|
-
<SwappableGrid
|
|
177
|
-
itemWidth={100}
|
|
178
|
-
itemHeight={100}
|
|
179
|
-
numColumns={3}
|
|
180
|
-
onDelete={(key) => {
|
|
181
|
-
setItems(items.filter((item) => item.id !== key));
|
|
182
|
-
}}
|
|
183
|
-
>
|
|
184
|
-
{items.map((item) => (
|
|
185
|
-
<View key={item.id}>{item.content}</View>
|
|
186
|
-
))}
|
|
187
|
-
</SwappableGrid>
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### With Delete Component
|
|
193
|
+
### Auto-calculated Columns
|
|
191
194
|
|
|
192
195
|
```tsx
|
|
193
196
|
<SwappableGrid
|
|
194
197
|
itemWidth={100}
|
|
195
198
|
itemHeight={100}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
backgroundColor: "red",
|
|
201
|
-
borderRadius: 8,
|
|
202
|
-
justifyContent: "center",
|
|
203
|
-
alignItems: "center",
|
|
204
|
-
}}
|
|
205
|
-
>
|
|
206
|
-
<Text style={{ color: "white" }}>Drop to Delete</Text>
|
|
207
|
-
</View>
|
|
208
|
-
}
|
|
209
|
-
onDelete={(key) => {
|
|
210
|
-
setItems(items.filter((item) => item.id !== key));
|
|
211
|
-
}}
|
|
199
|
+
gap={12}
|
|
200
|
+
containerPadding={16}
|
|
201
|
+
// numColumns not provided - will be calculated automatically
|
|
202
|
+
onOrderChange={(keys) => console.log("New order:", keys)}
|
|
212
203
|
>
|
|
213
204
|
{items.map((item) => (
|
|
214
205
|
<View key={item.id}>{item.content}</View>
|
|
@@ -224,6 +215,7 @@ gridRef.current?.cancelDeleteMode();
|
|
|
224
215
|
itemHeight={100}
|
|
225
216
|
numColumns={3}
|
|
226
217
|
trailingComponent={
|
|
218
|
+
/* trailingComponent gets positioned at the end of the grid */
|
|
227
219
|
<Pressable
|
|
228
220
|
onPress={() => addNewItem()}
|
|
229
221
|
style={{
|
|
@@ -243,16 +235,19 @@ gridRef.current?.cancelDeleteMode();
|
|
|
243
235
|
</SwappableGrid>
|
|
244
236
|
```
|
|
245
237
|
|
|
246
|
-
###
|
|
238
|
+
### With Delete Functionality (Hold-still-to-Delete)
|
|
239
|
+
|
|
240
|
+
**Note**: Hold-still-to-delete is only enabled when `onDelete` is provided. If you don't want deletion functionality, simply omit the `onDelete` prop.
|
|
247
241
|
|
|
248
242
|
```tsx
|
|
249
243
|
<SwappableGrid
|
|
250
244
|
itemWidth={100}
|
|
251
245
|
itemHeight={100}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
246
|
+
numColumns={3}
|
|
247
|
+
holdStillToDeleteMs={1500} // Hold for 1.5 seconds to enter delete mode
|
|
248
|
+
onDelete={(key) => {
|
|
249
|
+
setItems(items.filter((item) => item.id !== key));
|
|
250
|
+
}}
|
|
256
251
|
>
|
|
257
252
|
{items.map((item) => (
|
|
258
253
|
<View key={item.id}>{item.content}</View>
|
|
@@ -260,7 +255,9 @@ gridRef.current?.cancelDeleteMode();
|
|
|
260
255
|
</SwappableGrid>
|
|
261
256
|
```
|
|
262
257
|
|
|
263
|
-
###
|
|
258
|
+
### With Delete Component (custom component where you can drag items into it to delete. Kind of like a trashcan)
|
|
259
|
+
|
|
260
|
+
**Note**: By default HoldToDelete is enabled if you have a onDelete prop. If you use DeleteComponent then only DeleteComponent is used as the way to delete. In other words. You can choose to either delete items by holding or by using DeleteComponent.
|
|
264
261
|
|
|
265
262
|
```tsx
|
|
266
263
|
<SwappableGrid
|
|
@@ -268,11 +265,19 @@ gridRef.current?.cancelDeleteMode();
|
|
|
268
265
|
itemHeight={100}
|
|
269
266
|
numColumns={3}
|
|
270
267
|
deleteComponent={
|
|
271
|
-
<View
|
|
272
|
-
|
|
268
|
+
<View
|
|
269
|
+
style={{
|
|
270
|
+
backgroundColor: "red",
|
|
271
|
+
borderRadius: 8,
|
|
272
|
+
justifyContent: "center",
|
|
273
|
+
alignItems: "center",
|
|
274
|
+
}}
|
|
275
|
+
>
|
|
276
|
+
<Text style={{ color: "white" }}>Drop to Delete</Text>
|
|
273
277
|
</View>
|
|
274
278
|
}
|
|
275
279
|
deleteComponentStyle={{
|
|
280
|
+
/* By default DeleteComponent acts like the TrailingComponent. Positioning itself at the end of the grid. By using deleteComponentStyle you can change it to have a static position if you want it to be at a specific place */
|
|
276
281
|
position: "absolute",
|
|
277
282
|
top: 20,
|
|
278
283
|
right: 20,
|
|
@@ -291,11 +296,11 @@ gridRef.current?.cancelDeleteMode();
|
|
|
291
296
|
|
|
292
297
|
## How It Works
|
|
293
298
|
|
|
294
|
-
1. **Long Press**: Hold an item for `
|
|
299
|
+
1. **Long Press**: Hold an item for `holdToDragMs` milliseconds to enter drag mode
|
|
295
300
|
2. **Drag**: Move the item to swap positions with other items
|
|
296
301
|
3. **Auto-scroll**: When dragging near edges, the grid automatically scrolls
|
|
297
302
|
4. **Delete**:
|
|
298
|
-
- **Hold-to-delete**: Hold an item still for
|
|
303
|
+
- **Hold-Still-to-delete**: Hold an item still for `holdStillToDeleteMs` (default: 1000ms) to enter delete mode (shows delete button). Only enabled when `onDelete` is provided.
|
|
299
304
|
- **Delete component**: Drag an item to the delete component to delete it
|
|
300
305
|
5. **Order Change**: The `onOrderChange` callback fires whenever items are reordered
|
|
301
306
|
|
|
@@ -303,9 +308,10 @@ gridRef.current?.cancelDeleteMode();
|
|
|
303
308
|
|
|
304
309
|
- Each child component **must** have a unique `key` prop
|
|
305
310
|
- The component uses `react-native-reanimated` for smooth 60fps animations
|
|
306
|
-
-
|
|
311
|
+
- Deletion is only enabled when `onDelete` is provided. By default hold-still-to-delete is selected delete method. If `deleteComponent` is provided, hold-still-to-delete is automatically disabled and `deleteComponent` is used as the way to delete.
|
|
307
312
|
- The trailing component is positioned after all grid items
|
|
308
313
|
- The delete component appears only when dragging (if provided)
|
|
314
|
+
- If `wiggleDeleteMode` is not provided, delete mode wiggle uses 2x degrees and 0.7x duration of the `wiggle` prop
|
|
309
315
|
|
|
310
316
|
## License
|
|
311
317
|
|
|
@@ -16,6 +16,8 @@ function ChildWrapper({
|
|
|
16
16
|
anyItemInDeleteMode,
|
|
17
17
|
children,
|
|
18
18
|
wiggle,
|
|
19
|
+
wiggleDeleteMode,
|
|
20
|
+
holdStillToDeleteMs = 1000,
|
|
19
21
|
dragSizeIncreaseFactor,
|
|
20
22
|
onDelete,
|
|
21
23
|
disableHoldToDelete = false
|
|
@@ -118,8 +120,8 @@ function ChildWrapper({
|
|
|
118
120
|
// Increment by ~16ms per frame (assuming 60fps)
|
|
119
121
|
stillTimer.value += 16;
|
|
120
122
|
|
|
121
|
-
// Enter delete mode after
|
|
122
|
-
if (stillTimer.value >=
|
|
123
|
+
// Enter delete mode after holdStillToDeleteMs of being held still
|
|
124
|
+
if (stillTimer.value >= holdStillToDeleteMs) {
|
|
123
125
|
deleteModeActive.value = true;
|
|
124
126
|
anyItemInDeleteMode.value = true; // Set global delete mode
|
|
125
127
|
showDelete.value = true;
|
|
@@ -165,7 +167,18 @@ function ChildWrapper({
|
|
|
165
167
|
inDeleteMode,
|
|
166
168
|
anyInDeleteMode
|
|
167
169
|
}) => {
|
|
168
|
-
|
|
170
|
+
// Determine the target wiggle mode
|
|
171
|
+
let targetMode = "none";
|
|
172
|
+
if (inDeleteMode && (wiggleDeleteMode || wiggle)) {
|
|
173
|
+
targetMode = "delete";
|
|
174
|
+
} else if (anyInDeleteMode && !isActive && wiggle) {
|
|
175
|
+
targetMode = "normal";
|
|
176
|
+
} else if (isEditMode && !isActive && wiggle) {
|
|
177
|
+
targetMode = "normal";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If no wiggle is configured at all, stop animation
|
|
181
|
+
if (!wiggle && !wiggleDeleteMode) {
|
|
169
182
|
if (currentWiggleMode.value !== "none") {
|
|
170
183
|
(0, _reactNativeReanimated.cancelAnimation)(rotation);
|
|
171
184
|
currentWiggleMode.value = "none";
|
|
@@ -176,14 +189,28 @@ function ChildWrapper({
|
|
|
176
189
|
return;
|
|
177
190
|
}
|
|
178
191
|
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
// If in delete mode but no wiggleDeleteMode and no wiggle, stop animation
|
|
193
|
+
if (targetMode === "delete" && !wiggleDeleteMode && !wiggle) {
|
|
194
|
+
if (currentWiggleMode.value !== "none") {
|
|
195
|
+
(0, _reactNativeReanimated.cancelAnimation)(rotation);
|
|
196
|
+
currentWiggleMode.value = "none";
|
|
197
|
+
}
|
|
198
|
+
rotation.value = (0, _reactNativeReanimated.withTiming)(0, {
|
|
199
|
+
duration: 150
|
|
200
|
+
});
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// If normal mode but no wiggle, stop animation
|
|
205
|
+
if (targetMode === "normal" && !wiggle) {
|
|
206
|
+
if (currentWiggleMode.value !== "none") {
|
|
207
|
+
(0, _reactNativeReanimated.cancelAnimation)(rotation);
|
|
208
|
+
currentWiggleMode.value = "none";
|
|
209
|
+
}
|
|
210
|
+
rotation.value = (0, _reactNativeReanimated.withTiming)(0, {
|
|
211
|
+
duration: 150
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
187
214
|
}
|
|
188
215
|
|
|
189
216
|
// Only restart animation if mode changed
|
|
@@ -196,13 +223,13 @@ function ChildWrapper({
|
|
|
196
223
|
// Cancel current animation
|
|
197
224
|
(0, _reactNativeReanimated.cancelAnimation)(rotation);
|
|
198
225
|
|
|
199
|
-
// If this item is in delete mode,
|
|
226
|
+
// If this item is in delete mode, use wiggleDeleteMode if provided, otherwise use 2x degrees and 0.7x duration
|
|
200
227
|
if (targetMode === "delete") {
|
|
201
|
-
const deleteWiggleDegrees = wiggle.degrees * 2;
|
|
202
|
-
const deleteWiggleDuration = wiggle.duration * 0.7; // Faster wiggle
|
|
228
|
+
const deleteWiggleDegrees = wiggleDeleteMode ? wiggleDeleteMode.degrees : ((wiggle === null || wiggle === void 0 ? void 0 : wiggle.degrees) ?? 0) * 2;
|
|
229
|
+
const deleteWiggleDuration = wiggleDeleteMode ? wiggleDeleteMode.duration : ((wiggle === null || wiggle === void 0 ? void 0 : wiggle.duration) ?? 200) * 0.7; // Faster wiggle
|
|
203
230
|
|
|
204
231
|
// If transitioning from normal wiggle, preserve the phase by scaling
|
|
205
|
-
if (previousMode === "normal") {
|
|
232
|
+
if (previousMode === "normal" && wiggle) {
|
|
206
233
|
const currentRot = rotation.value;
|
|
207
234
|
const scaleFactor = deleteWiggleDegrees / wiggle.degrees;
|
|
208
235
|
rotation.value = currentRot * scaleFactor;
|
|
@@ -241,7 +268,7 @@ function ChildWrapper({
|
|
|
241
268
|
duration: 150
|
|
242
269
|
});
|
|
243
270
|
}
|
|
244
|
-
}, [dragMode, position.active, deleteModeActive, anyItemInDeleteMode]);
|
|
271
|
+
}, [dragMode, position.active, deleteModeActive, anyItemInDeleteMode, wiggle, wiggleDeleteMode]);
|
|
245
272
|
const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
|
|
246
273
|
const scale = position.active.value ? (0, _reactNativeReanimated.withTiming)(dragSizeIncreaseFactor, {
|
|
247
274
|
duration: 120
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ChildWrapper","position","itemWidth","itemHeight","dragMode","anyItemInDeleteMode","children","wiggle","dragSizeIncreaseFactor","onDelete","disableHoldToDelete","rotation","useSharedValue","currentWiggleMode","previousDragMode","showDelete","deleteModeActive","stillTimer","lastX","x","value","lastY","y","frameCounter","wasReleasedAfterDeleteMode","useDerivedValue","isDragging","isActive","active","dragModeJustEnded","moved","Math","abs","deleteButtonStyle","useAnimatedStyle","shouldShow","opacity","pointerEvents","transform","scale","withTiming","duration","useAnimatedReaction","current","previous","isEditMode","inDeleteMode","anyInDeleteMode","cancelAnimation","targetMode","previousMode","deleteWiggleDegrees","degrees","deleteWiggleDuration","currentRot","scaleFactor","withRepeat","withSequence","easing","Easing","linear","animatedStyle","width","height","translateX","translateY","rotate","zIndex","isInDeleteMode","setIsInDeleteMode","useState","runOnJS","handleDelete","createElement","View","style","Pressable","onPress","top","left","right","bottom","borderRadius","justifyContent","alignItems","Text","fontSize","color","fontWeight"],"sources":["ChildWrapper.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { Text, View, Pressable } from \"react-native\";\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useAnimatedReaction,\n useSharedValue,\n withRepeat,\n withSequence,\n withTiming,\n SharedValue,\n useDerivedValue,\n cancelAnimation,\n runOnJS,\n} from \"react-native-reanimated\";\n\ntype Props = {\n position: {\n x: SharedValue<number>;\n y: SharedValue<number>;\n active: SharedValue<number>;\n };\n itemWidth: number;\n itemHeight: number;\n dragMode: SharedValue<boolean>;\n anyItemInDeleteMode: SharedValue<boolean>;\n children: React.ReactNode;\n wiggle?: { duration: number; degrees: number };\n dragSizeIncreaseFactor: number;\n onDelete?: () => void;\n disableHoldToDelete?: boolean; // If true, disable the hold-to-delete feature\n};\n\nexport default function ChildWrapper({\n position,\n itemWidth,\n itemHeight,\n dragMode,\n anyItemInDeleteMode,\n children,\n wiggle,\n dragSizeIncreaseFactor,\n onDelete,\n disableHoldToDelete = false,\n}: Props) {\n const rotation = useSharedValue(0);\n const currentWiggleMode = useSharedValue<\"none\" | \"normal\" | \"delete\">(\n \"none\"\n );\n const previousDragMode = useSharedValue(false);\n\n const showDelete = useSharedValue(false);\n const deleteModeActive = useSharedValue(false); // Persistent delete mode state\n const stillTimer = useSharedValue(0);\n const lastX = useSharedValue(position.x.value);\n const lastY = useSharedValue(position.y.value);\n const frameCounter = useSharedValue(0);\n const wasReleasedAfterDeleteMode = useSharedValue(false); // Track if item was released after entering delete mode\n\n // Timer logic that runs every frame via useDerivedValue\n useDerivedValue(() => {\n \"worklet\";\n frameCounter.value = frameCounter.value + 1;\n\n // If hold-to-delete is disabled, skip all delete mode logic\n if (disableHoldToDelete) {\n deleteModeActive.value = false;\n showDelete.value = false;\n stillTimer.value = 0;\n anyItemInDeleteMode.value = false;\n return;\n }\n\n const isDragging = dragMode.value;\n const isActive = position.active.value > 0.5;\n const x = position.x.value;\n const y = position.y.value;\n\n // Track dragMode changes for detecting touches outside\n const dragModeJustEnded = previousDragMode.value && !isDragging;\n previousDragMode.value = isDragging;\n\n // If delete mode is active, keep it active unless:\n // 1. Another item becomes active (dragMode true but this item not active)\n // 2. This item becomes active again AFTER it was released (user starts dragging it again)\n // 3. User touches outside (dragMode becomes false and no item is active)\n if (deleteModeActive.value) {\n // Check if item was released (became inactive)\n if (!isActive && !wasReleasedAfterDeleteMode.value) {\n wasReleasedAfterDeleteMode.value = true;\n }\n\n if (isDragging && !isActive) {\n // Another item is being dragged, exit delete mode\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n } else if (isActive && wasReleasedAfterDeleteMode.value) {\n // This item became active again AFTER it was released, exit delete mode\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n } else if (!isDragging && !isActive) {\n // Keep delete mode active (waiting for user interaction)\n // The tap gesture handler in SwappableGrid will cancel it when user taps outside\n showDelete.value = true;\n } else {\n // Keep delete mode active (item can still be held or released)\n showDelete.value = true;\n }\n return;\n }\n\n // Reset release tracking when not in delete mode\n wasReleasedAfterDeleteMode.value = false;\n\n // If not in drag mode or not active, reset timer\n if (!isDragging || !isActive) {\n stillTimer.value = 0;\n return;\n }\n\n // Item is active (being held down) - check if it's still\n // Check if position has changed significantly (more than 10px threshold)\n const moved =\n Math.abs(x - lastX.value) > 10 || Math.abs(y - lastY.value) > 10;\n\n if (moved) {\n // Reset timer if item moved while being held\n stillTimer.value = 0;\n lastX.value = x;\n lastY.value = y;\n return;\n }\n\n // Initialize last position on first frame when active\n if (stillTimer.value === 0) {\n lastX.value = x;\n lastY.value = y;\n }\n\n // If the tile hasn't moved significantly while being held → increment timer\n // Increment by ~16ms per frame (assuming 60fps)\n stillTimer.value += 16;\n\n // Enter delete mode after 1 second (1000ms) of being held still\n if (stillTimer.value >= 1000) {\n deleteModeActive.value = true;\n anyItemInDeleteMode.value = true; // Set global delete mode\n showDelete.value = true;\n wasReleasedAfterDeleteMode.value = false; // Reset on entry\n }\n });\n\n const deleteButtonStyle = useAnimatedStyle(() => {\n // Show delete button when delete mode is active (persists after release)\n const shouldShow = showDelete.value;\n return {\n opacity: shouldShow ? 1 : 0,\n pointerEvents: shouldShow ? \"auto\" : \"none\",\n transform: [\n { scale: withTiming(shouldShow ? 1 : 0.6, { duration: 120 }) },\n ],\n };\n });\n\n // Watch for when global delete mode is cancelled (user tapped outside)\n useAnimatedReaction(\n () => anyItemInDeleteMode.value,\n (current, previous) => {\n \"worklet\";\n // If delete mode was cancelled globally (user tapped outside)\n if (previous && !current && deleteModeActive.value) {\n deleteModeActive.value = false;\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n }\n }\n );\n\n // Wiggle animation — triggers on editMode/active changes and delete mode\n useAnimatedReaction(\n () => ({\n isEditMode: dragMode.value,\n isActive: position.active.value > 0.5,\n inDeleteMode: deleteModeActive.value,\n anyInDeleteMode: anyItemInDeleteMode.value,\n }),\n ({ isEditMode, isActive, inDeleteMode, anyInDeleteMode }) => {\n if (!wiggle) {\n if (currentWiggleMode.value !== \"none\") {\n cancelAnimation(rotation);\n currentWiggleMode.value = \"none\";\n }\n rotation.value = withTiming(0, { duration: 150 });\n return;\n }\n\n // Determine the target wiggle mode\n let targetMode: \"none\" | \"normal\" | \"delete\" = \"none\";\n if (inDeleteMode) {\n targetMode = \"delete\";\n } else if (anyInDeleteMode && !isActive) {\n targetMode = \"normal\";\n } else if (isEditMode && !isActive) {\n targetMode = \"normal\";\n }\n\n // Only restart animation if mode changed\n if (currentWiggleMode.value === targetMode) {\n return; // Already in the correct mode, don't restart\n }\n\n const previousMode = currentWiggleMode.value;\n currentWiggleMode.value = targetMode;\n\n // Cancel current animation\n cancelAnimation(rotation);\n\n // If this item is in delete mode, wiggle more (2x degrees, faster)\n if (targetMode === \"delete\") {\n const deleteWiggleDegrees = wiggle.degrees * 2;\n const deleteWiggleDuration = wiggle.duration * 0.7; // Faster wiggle\n\n // If transitioning from normal wiggle, preserve the phase by scaling\n if (previousMode === \"normal\") {\n const currentRot = rotation.value;\n const scaleFactor = deleteWiggleDegrees / wiggle.degrees;\n rotation.value = currentRot * scaleFactor;\n }\n\n rotation.value = withRepeat(\n withSequence(\n withTiming(deleteWiggleDegrees, {\n duration: deleteWiggleDuration,\n easing: Easing.linear,\n }),\n withTiming(-deleteWiggleDegrees, {\n duration: deleteWiggleDuration,\n easing: Easing.linear,\n })\n ),\n -1, // infinite\n true\n );\n }\n // Normal wiggle (when dragging but not this item, or any item in delete mode)\n else if (targetMode === \"normal\") {\n // If transitioning from delete wiggle, preserve the phase by scaling\n if (previousMode === \"delete\") {\n const currentRot = rotation.value;\n const scaleFactor = wiggle.degrees / (wiggle.degrees * 2);\n rotation.value = currentRot * scaleFactor;\n }\n\n rotation.value = withRepeat(\n withSequence(\n withTiming(wiggle.degrees, {\n duration: wiggle.duration,\n easing: Easing.linear,\n }),\n withTiming(-wiggle.degrees, {\n duration: wiggle.duration,\n easing: Easing.linear,\n })\n ),\n -1, // infinite\n true\n );\n }\n // Stop wiggling\n else {\n rotation.value = withTiming(0, { duration: 150 });\n }\n },\n [dragMode, position.active, deleteModeActive, anyItemInDeleteMode]\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const scale = position.active.value\n ? withTiming(dragSizeIncreaseFactor, { duration: 120 })\n : withTiming(1, { duration: 120 });\n\n return {\n position: \"absolute\",\n width: itemWidth,\n height: itemHeight,\n transform: [\n { translateX: position.x.value as any },\n { translateY: position.y.value as any },\n { scale: scale as any },\n { rotate: `${rotation.value}deg` as any },\n ],\n zIndex: position.active.value ? 2 : 0,\n } as any;\n });\n\n // Track delete mode on JS thread for conditional rendering\n const [isInDeleteMode, setIsInDeleteMode] = useState(false);\n\n useAnimatedReaction(\n () => deleteModeActive.value,\n (current) => {\n runOnJS(setIsInDeleteMode)(current);\n }\n );\n\n const handleDelete = () => {\n // Exit delete mode when delete button is pressed\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n if (onDelete) {\n onDelete();\n }\n };\n\n return (\n <Animated.View style={animatedStyle} pointerEvents=\"box-none\">\n {/* Full-item Pressable for delete - only active when in delete mode */}\n {isInDeleteMode && (\n <Pressable\n onPress={handleDelete}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n width: itemWidth,\n height: itemHeight,\n zIndex: 2,\n }}\n />\n )}\n\n {/* Delete button (×) - visual indicator only */}\n <Animated.View\n style={[\n {\n position: \"absolute\",\n top: itemHeight * 0.01,\n right: itemWidth * 0.04,\n width: itemWidth * 0.2,\n height: itemHeight * 0.2,\n borderRadius: 12,\n justifyContent: \"center\",\n alignItems: \"center\",\n zIndex: 3,\n },\n deleteButtonStyle,\n ]}\n pointerEvents=\"none\"\n >\n <Text\n style={{\n fontSize: itemWidth * 0.2,\n color: \"black\",\n fontWeight: 500,\n }}\n >\n ×\n </Text>\n </Animated.View>\n\n {children}\n </Animated.View>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ChildWrapper","position","itemWidth","itemHeight","dragMode","anyItemInDeleteMode","children","wiggle","wiggleDeleteMode","holdStillToDeleteMs","dragSizeIncreaseFactor","onDelete","disableHoldToDelete","rotation","useSharedValue","currentWiggleMode","previousDragMode","showDelete","deleteModeActive","stillTimer","lastX","x","value","lastY","y","frameCounter","wasReleasedAfterDeleteMode","useDerivedValue","isDragging","isActive","active","dragModeJustEnded","moved","Math","abs","deleteButtonStyle","useAnimatedStyle","shouldShow","opacity","pointerEvents","transform","scale","withTiming","duration","useAnimatedReaction","current","previous","isEditMode","inDeleteMode","anyInDeleteMode","targetMode","cancelAnimation","previousMode","deleteWiggleDegrees","degrees","deleteWiggleDuration","currentRot","scaleFactor","withRepeat","withSequence","easing","Easing","linear","animatedStyle","width","height","translateX","translateY","rotate","zIndex","isInDeleteMode","setIsInDeleteMode","useState","runOnJS","handleDelete","createElement","View","style","Pressable","onPress","top","left","right","bottom","borderRadius","justifyContent","alignItems","Text","fontSize","color","fontWeight"],"sources":["ChildWrapper.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { Text, View, Pressable } from \"react-native\";\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useAnimatedReaction,\n useSharedValue,\n withRepeat,\n withSequence,\n withTiming,\n SharedValue,\n useDerivedValue,\n cancelAnimation,\n runOnJS,\n} from \"react-native-reanimated\";\n\ntype Props = {\n position: {\n x: SharedValue<number>;\n y: SharedValue<number>;\n active: SharedValue<number>;\n };\n itemWidth: number;\n itemHeight: number;\n dragMode: SharedValue<boolean>;\n anyItemInDeleteMode: SharedValue<boolean>;\n children: React.ReactNode;\n wiggle?: { duration: number; degrees: number };\n wiggleDeleteMode?: { duration: number; degrees: number };\n holdStillToDeleteMs?: number;\n dragSizeIncreaseFactor: number;\n onDelete?: () => void;\n disableHoldToDelete?: boolean; // If true, disable the hold-to-delete feature\n};\n\nexport default function ChildWrapper({\n position,\n itemWidth,\n itemHeight,\n dragMode,\n anyItemInDeleteMode,\n children,\n wiggle,\n wiggleDeleteMode,\n holdStillToDeleteMs = 1000,\n dragSizeIncreaseFactor,\n onDelete,\n disableHoldToDelete = false,\n}: Props) {\n const rotation = useSharedValue(0);\n const currentWiggleMode = useSharedValue<\"none\" | \"normal\" | \"delete\">(\n \"none\"\n );\n const previousDragMode = useSharedValue(false);\n\n const showDelete = useSharedValue(false);\n const deleteModeActive = useSharedValue(false); // Persistent delete mode state\n const stillTimer = useSharedValue(0);\n const lastX = useSharedValue(position.x.value);\n const lastY = useSharedValue(position.y.value);\n const frameCounter = useSharedValue(0);\n const wasReleasedAfterDeleteMode = useSharedValue(false); // Track if item was released after entering delete mode\n\n // Timer logic that runs every frame via useDerivedValue\n useDerivedValue(() => {\n \"worklet\";\n frameCounter.value = frameCounter.value + 1;\n\n // If hold-to-delete is disabled, skip all delete mode logic\n if (disableHoldToDelete) {\n deleteModeActive.value = false;\n showDelete.value = false;\n stillTimer.value = 0;\n anyItemInDeleteMode.value = false;\n return;\n }\n\n const isDragging = dragMode.value;\n const isActive = position.active.value > 0.5;\n const x = position.x.value;\n const y = position.y.value;\n\n // Track dragMode changes for detecting touches outside\n const dragModeJustEnded = previousDragMode.value && !isDragging;\n previousDragMode.value = isDragging;\n\n // If delete mode is active, keep it active unless:\n // 1. Another item becomes active (dragMode true but this item not active)\n // 2. This item becomes active again AFTER it was released (user starts dragging it again)\n // 3. User touches outside (dragMode becomes false and no item is active)\n if (deleteModeActive.value) {\n // Check if item was released (became inactive)\n if (!isActive && !wasReleasedAfterDeleteMode.value) {\n wasReleasedAfterDeleteMode.value = true;\n }\n\n if (isDragging && !isActive) {\n // Another item is being dragged, exit delete mode\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n } else if (isActive && wasReleasedAfterDeleteMode.value) {\n // This item became active again AFTER it was released, exit delete mode\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n } else if (!isDragging && !isActive) {\n // Keep delete mode active (waiting for user interaction)\n // The tap gesture handler in SwappableGrid will cancel it when user taps outside\n showDelete.value = true;\n } else {\n // Keep delete mode active (item can still be held or released)\n showDelete.value = true;\n }\n return;\n }\n\n // Reset release tracking when not in delete mode\n wasReleasedAfterDeleteMode.value = false;\n\n // If not in drag mode or not active, reset timer\n if (!isDragging || !isActive) {\n stillTimer.value = 0;\n return;\n }\n\n // Item is active (being held down) - check if it's still\n // Check if position has changed significantly (more than 10px threshold)\n const moved =\n Math.abs(x - lastX.value) > 10 || Math.abs(y - lastY.value) > 10;\n\n if (moved) {\n // Reset timer if item moved while being held\n stillTimer.value = 0;\n lastX.value = x;\n lastY.value = y;\n return;\n }\n\n // Initialize last position on first frame when active\n if (stillTimer.value === 0) {\n lastX.value = x;\n lastY.value = y;\n }\n\n // If the tile hasn't moved significantly while being held → increment timer\n // Increment by ~16ms per frame (assuming 60fps)\n stillTimer.value += 16;\n\n // Enter delete mode after holdStillToDeleteMs of being held still\n if (stillTimer.value >= holdStillToDeleteMs) {\n deleteModeActive.value = true;\n anyItemInDeleteMode.value = true; // Set global delete mode\n showDelete.value = true;\n wasReleasedAfterDeleteMode.value = false; // Reset on entry\n }\n });\n\n const deleteButtonStyle = useAnimatedStyle(() => {\n // Show delete button when delete mode is active (persists after release)\n const shouldShow = showDelete.value;\n return {\n opacity: shouldShow ? 1 : 0,\n pointerEvents: shouldShow ? \"auto\" : \"none\",\n transform: [\n { scale: withTiming(shouldShow ? 1 : 0.6, { duration: 120 }) },\n ],\n };\n });\n\n // Watch for when global delete mode is cancelled (user tapped outside)\n useAnimatedReaction(\n () => anyItemInDeleteMode.value,\n (current, previous) => {\n \"worklet\";\n // If delete mode was cancelled globally (user tapped outside)\n if (previous && !current && deleteModeActive.value) {\n deleteModeActive.value = false;\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n }\n }\n );\n\n // Wiggle animation — triggers on editMode/active changes and delete mode\n useAnimatedReaction(\n () => ({\n isEditMode: dragMode.value,\n isActive: position.active.value > 0.5,\n inDeleteMode: deleteModeActive.value,\n anyInDeleteMode: anyItemInDeleteMode.value,\n }),\n ({ isEditMode, isActive, inDeleteMode, anyInDeleteMode }) => {\n // Determine the target wiggle mode\n let targetMode: \"none\" | \"normal\" | \"delete\" = \"none\";\n if (inDeleteMode && (wiggleDeleteMode || wiggle)) {\n targetMode = \"delete\";\n } else if (anyInDeleteMode && !isActive && wiggle) {\n targetMode = \"normal\";\n } else if (isEditMode && !isActive && wiggle) {\n targetMode = \"normal\";\n }\n\n // If no wiggle is configured at all, stop animation\n if (!wiggle && !wiggleDeleteMode) {\n if (currentWiggleMode.value !== \"none\") {\n cancelAnimation(rotation);\n currentWiggleMode.value = \"none\";\n }\n rotation.value = withTiming(0, { duration: 150 });\n return;\n }\n\n // If in delete mode but no wiggleDeleteMode and no wiggle, stop animation\n if (targetMode === \"delete\" && !wiggleDeleteMode && !wiggle) {\n if (currentWiggleMode.value !== \"none\") {\n cancelAnimation(rotation);\n currentWiggleMode.value = \"none\";\n }\n rotation.value = withTiming(0, { duration: 150 });\n return;\n }\n\n // If normal mode but no wiggle, stop animation\n if (targetMode === \"normal\" && !wiggle) {\n if (currentWiggleMode.value !== \"none\") {\n cancelAnimation(rotation);\n currentWiggleMode.value = \"none\";\n }\n rotation.value = withTiming(0, { duration: 150 });\n return;\n }\n\n // Only restart animation if mode changed\n if (currentWiggleMode.value === targetMode) {\n return; // Already in the correct mode, don't restart\n }\n\n const previousMode = currentWiggleMode.value;\n currentWiggleMode.value = targetMode;\n\n // Cancel current animation\n cancelAnimation(rotation);\n\n // If this item is in delete mode, use wiggleDeleteMode if provided, otherwise use 2x degrees and 0.7x duration\n if (targetMode === \"delete\") {\n const deleteWiggleDegrees = wiggleDeleteMode\n ? wiggleDeleteMode.degrees\n : (wiggle?.degrees ?? 0) * 2;\n const deleteWiggleDuration = wiggleDeleteMode\n ? wiggleDeleteMode.duration\n : (wiggle?.duration ?? 200) * 0.7; // Faster wiggle\n\n // If transitioning from normal wiggle, preserve the phase by scaling\n if (previousMode === \"normal\" && wiggle) {\n const currentRot = rotation.value;\n const scaleFactor = deleteWiggleDegrees / wiggle.degrees;\n rotation.value = currentRot * scaleFactor;\n }\n\n rotation.value = withRepeat(\n withSequence(\n withTiming(deleteWiggleDegrees, {\n duration: deleteWiggleDuration,\n easing: Easing.linear,\n }),\n withTiming(-deleteWiggleDegrees, {\n duration: deleteWiggleDuration,\n easing: Easing.linear,\n })\n ),\n -1, // infinite\n true\n );\n }\n // Normal wiggle (when dragging but not this item, or any item in delete mode)\n else if (targetMode === \"normal\") {\n // If transitioning from delete wiggle, preserve the phase by scaling\n if (previousMode === \"delete\") {\n const currentRot = rotation.value;\n const scaleFactor = wiggle.degrees / (wiggle.degrees * 2);\n rotation.value = currentRot * scaleFactor;\n }\n\n rotation.value = withRepeat(\n withSequence(\n withTiming(wiggle.degrees, {\n duration: wiggle.duration,\n easing: Easing.linear,\n }),\n withTiming(-wiggle.degrees, {\n duration: wiggle.duration,\n easing: Easing.linear,\n })\n ),\n -1, // infinite\n true\n );\n }\n // Stop wiggling\n else {\n rotation.value = withTiming(0, { duration: 150 });\n }\n },\n [\n dragMode,\n position.active,\n deleteModeActive,\n anyItemInDeleteMode,\n wiggle,\n wiggleDeleteMode,\n ]\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const scale = position.active.value\n ? withTiming(dragSizeIncreaseFactor, { duration: 120 })\n : withTiming(1, { duration: 120 });\n\n return {\n position: \"absolute\",\n width: itemWidth,\n height: itemHeight,\n transform: [\n { translateX: position.x.value as any },\n { translateY: position.y.value as any },\n { scale: scale as any },\n { rotate: `${rotation.value}deg` as any },\n ],\n zIndex: position.active.value ? 2 : 0,\n } as any;\n });\n\n // Track delete mode on JS thread for conditional rendering\n const [isInDeleteMode, setIsInDeleteMode] = useState(false);\n\n useAnimatedReaction(\n () => deleteModeActive.value,\n (current) => {\n runOnJS(setIsInDeleteMode)(current);\n }\n );\n\n const handleDelete = () => {\n // Exit delete mode when delete button is pressed\n deleteModeActive.value = false;\n anyItemInDeleteMode.value = false; // Clear global delete mode\n showDelete.value = false;\n stillTimer.value = 0;\n wasReleasedAfterDeleteMode.value = false;\n if (onDelete) {\n onDelete();\n }\n };\n\n return (\n <Animated.View style={animatedStyle} pointerEvents=\"box-none\">\n {/* Full-item Pressable for delete - only active when in delete mode */}\n {isInDeleteMode && (\n <Pressable\n onPress={handleDelete}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n width: itemWidth,\n height: itemHeight,\n zIndex: 2,\n }}\n />\n )}\n\n {/* Delete button (×) - visual indicator only */}\n <Animated.View\n style={[\n {\n position: \"absolute\",\n top: itemHeight * 0.01,\n right: itemWidth * 0.04,\n width: itemWidth * 0.2,\n height: itemHeight * 0.2,\n borderRadius: 12,\n justifyContent: \"center\",\n alignItems: \"center\",\n zIndex: 3,\n },\n deleteButtonStyle,\n ]}\n pointerEvents=\"none\"\n >\n <Text\n style={{\n fontSize: itemWidth * 0.2,\n color: \"black\",\n fontWeight: 500,\n }}\n >\n ×\n </Text>\n </Animated.View>\n\n {children}\n </Animated.View>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -57,12 +57,14 @@ const SwappableGrid = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
57
57
|
itemHeight,
|
|
58
58
|
gap = 8,
|
|
59
59
|
containerPadding = 8,
|
|
60
|
-
|
|
60
|
+
holdToDragMs = 300,
|
|
61
61
|
numColumns,
|
|
62
62
|
onDragEnd,
|
|
63
63
|
onOrderChange,
|
|
64
64
|
onDelete,
|
|
65
65
|
wiggle,
|
|
66
|
+
wiggleDeleteMode,
|
|
67
|
+
holdStillToDeleteMs = 1000,
|
|
66
68
|
style,
|
|
67
69
|
dragSizeIncreaseFactor = 1.06,
|
|
68
70
|
scrollThreshold = 100,
|
|
@@ -115,7 +117,7 @@ const SwappableGrid = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
115
117
|
} = (0, _useGridLayout.useGridLayout)({
|
|
116
118
|
reverse,
|
|
117
119
|
children,
|
|
118
|
-
|
|
120
|
+
holdToDragMs,
|
|
119
121
|
itemWidth,
|
|
120
122
|
itemHeight,
|
|
121
123
|
gap,
|
|
@@ -316,8 +318,10 @@ const SwappableGrid = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
316
318
|
dragMode: dragMode,
|
|
317
319
|
anyItemInDeleteMode: anyItemInDeleteMode,
|
|
318
320
|
wiggle: wiggle,
|
|
321
|
+
wiggleDeleteMode: wiggleDeleteMode,
|
|
322
|
+
holdStillToDeleteMs: holdStillToDeleteMs,
|
|
319
323
|
dragSizeIncreaseFactor: dragSizeIncreaseFactor,
|
|
320
|
-
disableHoldToDelete: !!deleteComponent,
|
|
324
|
+
disableHoldToDelete: !onDelete || !!deleteComponent,
|
|
321
325
|
onDelete: () => {
|
|
322
326
|
deleteItem(key);
|
|
323
327
|
if (onDelete) {
|