react-native-sortable-dynamic 0.1.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.
- package/LICENSE +20 -0
- package/README.md +189 -0
- package/lib/commonjs/Config.js +101 -0
- package/lib/commonjs/Config.js.map +1 -0
- package/lib/commonjs/Item.js +188 -0
- package/lib/commonjs/Item.js.map +1 -0
- package/lib/commonjs/SortableList.js +91 -0
- package/lib/commonjs/SortableList.js.map +1 -0
- package/lib/commonjs/Tile.js +56 -0
- package/lib/commonjs/Tile.js.map +1 -0
- package/lib/commonjs/index.js +28 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/Config.js +93 -0
- package/lib/module/Config.js.map +1 -0
- package/lib/module/Item.js +185 -0
- package/lib/module/Item.js.map +1 -0
- package/lib/module/SortableList.js +86 -0
- package/lib/module/SortableList.js.map +1 -0
- package/lib/module/Tile.js +53 -0
- package/lib/module/Tile.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/package.json +175 -0
- package/src/Config.js +81 -0
- package/src/Item.js +196 -0
- package/src/SortableList.js +86 -0
- package/src/Tile.js +47 -0
- package/src/index.js +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Adam Lee
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# react-native-sortable-dynamic
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
`react-native-sortable-dynamic` is a highly customizable, drag-and-drop library for creating sortable grid and list layouts in React Native. It provides smooth animations and supports reordering items in a dynamic, flexible layout. Ideal for creating dashboards, photo galleries, task boards, and more, with easy-to-use configuration options for both grid and list layouts.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🖱️ **Drag-and-drop**: Easily reorder grid and list items using intuitive gestures.
|
|
10
|
+
- 🖼️ **Grid & List Support**: Configurable for both grid and list views.
|
|
11
|
+
- 🧩 **Flexible Layout**: Customize columns, margins, and item sizes to fit your needs.
|
|
12
|
+
- 🛠️ **Editable Mode**: Toggle between editing and non-editing modes to enable/disable reordering.
|
|
13
|
+
- ⚡ **Smooth Animations**: Built using `react-native-reanimated` for seamless and performant animations.
|
|
14
|
+
- 🔐 **Lock Items**: Mark specific items as non-reorderable or non-draggable.
|
|
15
|
+
- 🧩 **Dynamic Layout Configuration**: Easily switch between grid and list views by configuring the layout dynamically.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Step 1: Install the package
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install react-native-sortable-dynamic
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
##### or
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add react-native-sortable-dynamic
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Step 2: Install dependencies
|
|
32
|
+
|
|
33
|
+
You'll also need to install dependencies like react-native-reanimated and react-native-gesture-handler if you haven't already:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install react-native-reanimated react-native-gesture-handler
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
##### or
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
yarn add react-native-reanimated react-native-gesture-handler
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Step 3: Additional setup
|
|
46
|
+
|
|
47
|
+
1. **Reanimated Setup**: Follow the [react-native-reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation/) to properly set up `react-native-reanimated`. This includes updating the `babel.config.js` file:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
// babel.config.js
|
|
51
|
+
module.exports = {
|
|
52
|
+
presets: ['module:metro-react-native-babel-preset'],
|
|
53
|
+
plugins: [
|
|
54
|
+
'react-native-reanimated/plugin', // Add this line
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
2. **Gesture Handler Setup**: Follow the [react-native-gesture-handler installation guide](https://docs.swmansion.com/react-native-gesture-handler/docs/) to set up `react-native-gesture-handler` correctly.
|
|
60
|
+
|
|
61
|
+
3. **Android Specific Configuration**:
|
|
62
|
+
|
|
63
|
+
- If you're using this library on Android, make sure to wrap the root component with `GestureHandlerRootView`.
|
|
64
|
+
- Update `MainActivity.java` to enable gesture handling:
|
|
65
|
+
|
|
66
|
+
```java
|
|
67
|
+
import com.facebook.react.ReactActivity;
|
|
68
|
+
import com.facebook.react.ReactActivityDelegate;
|
|
69
|
+
import com.facebook.react.ReactRootView;
|
|
70
|
+
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; // Add this import
|
|
71
|
+
|
|
72
|
+
public class MainActivity extends ReactActivity {
|
|
73
|
+
@Override
|
|
74
|
+
protected ReactActivityDelegate createReactActivityDelegate() {
|
|
75
|
+
return new ReactActivityDelegate(this, getMainComponentName()) {
|
|
76
|
+
@Override
|
|
77
|
+
protected ReactRootView createRootView() {
|
|
78
|
+
return new RNGestureHandlerEnabledRootView(MainActivity.this); // Modify this line
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
4. **iOS Specific Configuration**:
|
|
86
|
+
|
|
87
|
+
- For iOS, ensure that you run `pod install` in the `ios` directory of your project after installing the dependencies:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cd ios
|
|
91
|
+
pod install
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
### Basic Example
|
|
97
|
+
|
|
98
|
+
Here's a simple example of how to use `react-native-sortable-dynamic` in your React Native project:
|
|
99
|
+
|
|
100
|
+
```jsx
|
|
101
|
+
import React, { useState } from 'react';
|
|
102
|
+
import { Text, View } from 'react-native';
|
|
103
|
+
import {
|
|
104
|
+
SortableListProvider,
|
|
105
|
+
SortableList,
|
|
106
|
+
Tile,
|
|
107
|
+
} from 'react-native-sortable-dynamic';
|
|
108
|
+
|
|
109
|
+
const tiles = [
|
|
110
|
+
{ id: 1, text: 'Tile 1' },
|
|
111
|
+
{ id: 2, text: 'Tile 2' },
|
|
112
|
+
{ id: 3, text: 'Tile 3' },
|
|
113
|
+
{ id: 4, text: 'Tile 4' },
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
const App = () => {
|
|
117
|
+
const [enableEditing, setEnableEditing] = useState(false);
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<SortableListProvider config={{ MARGIN: 10, COL: 2 }}>
|
|
121
|
+
<SortableList
|
|
122
|
+
tiles={tiles}
|
|
123
|
+
editing={enableEditing}
|
|
124
|
+
onDragEnd={(positions) => console.log(positions)}
|
|
125
|
+
>
|
|
126
|
+
{tiles.map((tile) => (
|
|
127
|
+
<Tile
|
|
128
|
+
key={tile.id}
|
|
129
|
+
id={tile.id}
|
|
130
|
+
onLongPress={() => setEnableEditing(!enableEditing)}
|
|
131
|
+
>
|
|
132
|
+
<View
|
|
133
|
+
style={{
|
|
134
|
+
flex: 1,
|
|
135
|
+
justifyContent: 'center',
|
|
136
|
+
alignItems: 'center',
|
|
137
|
+
backgroundColor: 'red',
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
<Text style={{ color: 'white', fontSize: 20 }}>{tile.text}</Text>
|
|
141
|
+
</View>
|
|
142
|
+
</Tile>
|
|
143
|
+
))}
|
|
144
|
+
</SortableList>
|
|
145
|
+
</SortableListProvider>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export default App;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Props
|
|
153
|
+
|
|
154
|
+
#### `SortableListProvider`
|
|
155
|
+
|
|
156
|
+
| Prop | Type | Description |
|
|
157
|
+
| -------- | -------- | ------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `config` | `object` | Configuration options such as `MARGIN` and `COL`. Use this to dynamically adjust the grid layout. |
|
|
159
|
+
|
|
160
|
+
#### `SortableList`
|
|
161
|
+
|
|
162
|
+
| Prop | Type | Description |
|
|
163
|
+
| ----------- | ---------- | --------------------------------------------------------------------- |
|
|
164
|
+
| `tiles` | `array` | Array of items to be rendered and sorted. |
|
|
165
|
+
| `editing` | `boolean` | If true, allows items to be dragged and reordered. |
|
|
166
|
+
| `onDragEnd` | `function` | Callback function that receives updated positions when the drag ends. |
|
|
167
|
+
|
|
168
|
+
#### `Tile`
|
|
169
|
+
|
|
170
|
+
| Prop | Type | Description |
|
|
171
|
+
| --------------- | ---------- | ------------------------------------------------------------- |
|
|
172
|
+
| `onPress` | `function` | Function called when the tile is pressed. |
|
|
173
|
+
| `onLongPress` | `function` | Function called when the tile is long-pressed. |
|
|
174
|
+
| `activeOpacity` | `number` | The opacity of the tile when it is pressed. Default is `0.7`. |
|
|
175
|
+
|
|
176
|
+
## Roadmap
|
|
177
|
+
|
|
178
|
+
- ✅ Support for grid layouts
|
|
179
|
+
- 🔜 Support for list layouts
|
|
180
|
+
- 🔜 Add more customization options for animations and gestures
|
|
181
|
+
- 🔜 Improve accessibility and performance
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
Contributions are welcome! See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useSortableConfig = exports.getPosition = exports.getOrder = exports.default = exports.animationConfig = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _reactNativeReanimated = require("react-native-reanimated");
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
|
+
// Get screen width to calculate dynamic sizes
|
|
14
|
+
const {
|
|
15
|
+
width
|
|
16
|
+
} = _reactNative.Dimensions.get('window');
|
|
17
|
+
|
|
18
|
+
// Default configuration for the sortable list
|
|
19
|
+
const defaultConfig = {
|
|
20
|
+
MARGIN: 10,
|
|
21
|
+
// Default margin between items
|
|
22
|
+
COL: 2,
|
|
23
|
+
// Default number of columns
|
|
24
|
+
// Default size for each item, calculated based on the number of columns and margin
|
|
25
|
+
SIZE: width / 2 - 10 // (width / COL - MARGIN)
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Create a Context for the sortable list configuration
|
|
29
|
+
const ConfigContext = /*#__PURE__*/(0, _react.createContext)(defaultConfig);
|
|
30
|
+
|
|
31
|
+
// Custom hook to use the sortable configuration context
|
|
32
|
+
const useSortableConfig = () => (0, _react.useContext)(ConfigContext);
|
|
33
|
+
|
|
34
|
+
// Configuration for animation settings
|
|
35
|
+
exports.useSortableConfig = useSortableConfig;
|
|
36
|
+
const animationConfig = exports.animationConfig = {
|
|
37
|
+
easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease),
|
|
38
|
+
duration: 350
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Helper function to calculate the item's position based on its index
|
|
42
|
+
// This is used to position items in a grid layout
|
|
43
|
+
const getPosition = (position, COL, SIZE) => {
|
|
44
|
+
'worklet';
|
|
45
|
+
|
|
46
|
+
// Necessary for Reanimated 2 to run this function on the UI thread
|
|
47
|
+
return {
|
|
48
|
+
x: position % COL === 0 ? 0 : SIZE * (position % COL),
|
|
49
|
+
y: Math.floor(position / COL) * SIZE
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Helper function to determine the new order of items during drag-and-drop
|
|
54
|
+
exports.getPosition = getPosition;
|
|
55
|
+
const getOrder = (tx, ty, max, COL, SIZE) => {
|
|
56
|
+
'worklet';
|
|
57
|
+
|
|
58
|
+
// Necessary for Reanimated 2 to run this function on the UI thread
|
|
59
|
+
const x = Math.round(tx / SIZE) * SIZE;
|
|
60
|
+
const y = Math.round(ty / SIZE) * SIZE;
|
|
61
|
+
const row = Math.max(y, 0) / SIZE;
|
|
62
|
+
const col = Math.max(x, 0) / SIZE;
|
|
63
|
+
return Math.min(row * COL + col, max);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* SortableListProvider component
|
|
68
|
+
*
|
|
69
|
+
* Wrap your sortable list components with this provider to set custom configuration.
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} config - Custom configuration to override the default settings.
|
|
72
|
+
* @param {number} config.MARGIN - Margin between items.
|
|
73
|
+
* @param {number} config.COL - Number of columns in the grid.
|
|
74
|
+
* @param {React.ReactNode} children - Child components that will use this configuration.
|
|
75
|
+
*
|
|
76
|
+
* Usage:
|
|
77
|
+
*
|
|
78
|
+
* <SortableListProvider config={{ MARGIN: 15, COL: 3 }}>
|
|
79
|
+
* <YourSortableList />
|
|
80
|
+
* </SortableListProvider>
|
|
81
|
+
*/
|
|
82
|
+
exports.getOrder = getOrder;
|
|
83
|
+
const SortableListProvider = ({
|
|
84
|
+
children,
|
|
85
|
+
config
|
|
86
|
+
}) => {
|
|
87
|
+
// Merge custom config with the default configuration
|
|
88
|
+
const mergedConfig = {
|
|
89
|
+
...defaultConfig,
|
|
90
|
+
...config
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Recalculate SIZE based on COL and MARGIN
|
|
94
|
+
mergedConfig.SIZE = width / mergedConfig.COL - mergedConfig.MARGIN;
|
|
95
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ConfigContext.Provider, {
|
|
96
|
+
value: mergedConfig,
|
|
97
|
+
children: children
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
var _default = exports.default = SortableListProvider;
|
|
101
|
+
//# sourceMappingURL=Config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_reactNativeReanimated","_react","_interopRequireWildcard","_jsxRuntime","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","width","Dimensions","defaultConfig","MARGIN","COL","SIZE","ConfigContext","createContext","useSortableConfig","useContext","exports","animationConfig","easing","Easing","inOut","ease","duration","getPosition","position","x","y","Math","floor","getOrder","tx","ty","max","round","row","col","min","SortableListProvider","children","config","mergedConfig","jsx","Provider","value","_default"],"sourceRoot":"../../src","sources":["Config.js"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
|
|
10
|
+
var _reactNativeGestureHandler = require("react-native-gesture-handler");
|
|
11
|
+
var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
|
|
12
|
+
var _Config = require("./Config.js");
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
15
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
16
|
+
/**
|
|
17
|
+
* Item Component
|
|
18
|
+
*
|
|
19
|
+
* This component represents a draggable item in the sortable grid. It manages the gesture handling
|
|
20
|
+
* and animations needed to drag and reorder the item within the grid.
|
|
21
|
+
*
|
|
22
|
+
* Props:
|
|
23
|
+
* @param {React.ReactNode} children - The content to render inside the item.
|
|
24
|
+
* @param {object} positions - Shared value that contains the current positions of all items.
|
|
25
|
+
* @param {number} id - Unique identifier for the item.
|
|
26
|
+
* @param {function} onDragEnd - Callback function triggered when dragging ends.
|
|
27
|
+
* @param {object} scrollView - Reference to the scroll view for scrolling during drag.
|
|
28
|
+
* @param {object} scrollY - Shared value representing the current scroll position.
|
|
29
|
+
* @param {boolean} editing - Whether the list is in editing mode.
|
|
30
|
+
* @param {boolean} draggable - Whether the item is draggable (default: true).
|
|
31
|
+
* @param {Array} tiles - Array of tile items used to check reorderable state.
|
|
32
|
+
*/const Item = ({
|
|
33
|
+
children,
|
|
34
|
+
positions,
|
|
35
|
+
id,
|
|
36
|
+
onDragEnd,
|
|
37
|
+
scrollView,
|
|
38
|
+
scrollY,
|
|
39
|
+
editing,
|
|
40
|
+
draggable = true,
|
|
41
|
+
tiles
|
|
42
|
+
}) => {
|
|
43
|
+
// Get safe area insets for accurate height calculation
|
|
44
|
+
const inset = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
|
|
45
|
+
const containerHeight = _reactNative.Dimensions.get('window').height - inset.top - inset.bottom;
|
|
46
|
+
|
|
47
|
+
// Get the configuration for columns and size
|
|
48
|
+
const {
|
|
49
|
+
COL,
|
|
50
|
+
SIZE
|
|
51
|
+
} = (0, _Config.useSortableConfig)();
|
|
52
|
+
|
|
53
|
+
// Calculate content height based on the number of items
|
|
54
|
+
const contentHeight = Object.keys(positions.value).length / COL * SIZE;
|
|
55
|
+
const isGestureActive = (0, _reactNativeReanimated.useSharedValue)(false); // Whether the item is being actively dragged
|
|
56
|
+
|
|
57
|
+
// Calculate initial position of the item
|
|
58
|
+
const position = (0, _Config.getPosition)(positions.value[id], COL, SIZE);
|
|
59
|
+
const translateX = (0, _reactNativeReanimated.useSharedValue)(position.x);
|
|
60
|
+
const translateY = (0, _reactNativeReanimated.useSharedValue)(position.y);
|
|
61
|
+
|
|
62
|
+
// Effect to reset isGestureActive when not in editing mode
|
|
63
|
+
(0, _react.useEffect)(() => {
|
|
64
|
+
if (!editing) {
|
|
65
|
+
isGestureActive.value = false;
|
|
66
|
+
}
|
|
67
|
+
}, [editing, isGestureActive]);
|
|
68
|
+
|
|
69
|
+
// React to changes in the positions object
|
|
70
|
+
(0, _reactNativeReanimated.useAnimatedReaction)(() => positions.value[id],
|
|
71
|
+
// Track changes to this item's position
|
|
72
|
+
newOrder => {
|
|
73
|
+
if (!isGestureActive.value) {
|
|
74
|
+
const pos = (0, _Config.getPosition)(newOrder, COL, SIZE);
|
|
75
|
+
translateX.value = (0, _reactNativeReanimated.withTiming)(pos.x, _Config.animationConfig);
|
|
76
|
+
translateY.value = (0, _reactNativeReanimated.withTiming)(pos.y, _Config.animationConfig);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Gesture handler for dragging
|
|
81
|
+
const onGestureEvent = (0, _reactNativeReanimated.useAnimatedGestureHandler)({
|
|
82
|
+
onStart: (_, ctx) => {
|
|
83
|
+
if (editing && draggable) {
|
|
84
|
+
// Store the starting position
|
|
85
|
+
ctx.x = translateX.value;
|
|
86
|
+
ctx.y = translateY.value;
|
|
87
|
+
isGestureActive.value = false; // TODO: Set to false when grouping is implemented
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
onActive: ({
|
|
91
|
+
translationX,
|
|
92
|
+
translationY
|
|
93
|
+
}, ctx) => {
|
|
94
|
+
if (editing && draggable) {
|
|
95
|
+
// Calculate new position
|
|
96
|
+
translateX.value = ctx.x + translationX;
|
|
97
|
+
translateY.value = ctx.y + translationY;
|
|
98
|
+
|
|
99
|
+
// Calculate new order based on position
|
|
100
|
+
const newOrder = (0, _Config.getOrder)(translateX.value, translateY.value, Object.keys(positions.value).length - 1, COL, SIZE);
|
|
101
|
+
const oldOrder = positions.value[id];
|
|
102
|
+
if (newOrder !== oldOrder) {
|
|
103
|
+
// Find the item to swap positions with
|
|
104
|
+
const idToSwap = Object.keys(positions.value).find(key => positions.value[key] === newOrder);
|
|
105
|
+
|
|
106
|
+
// Only swap if the target item is reorderable
|
|
107
|
+
const targetItem = tiles.find(tile => tile.id === Number(idToSwap));
|
|
108
|
+
if (idToSwap && targetItem?.reorderable !== false) {
|
|
109
|
+
const newPositions = {
|
|
110
|
+
...positions.value
|
|
111
|
+
};
|
|
112
|
+
newPositions[id] = newOrder;
|
|
113
|
+
newPositions[idToSwap] = oldOrder;
|
|
114
|
+
positions.value = newPositions;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Handle scrolling during drag
|
|
119
|
+
const lowerBound = scrollY.value;
|
|
120
|
+
const upperBound = lowerBound + containerHeight - SIZE;
|
|
121
|
+
const maxScroll = contentHeight - containerHeight;
|
|
122
|
+
const leftToScrollDown = maxScroll - scrollY.value;
|
|
123
|
+
|
|
124
|
+
// Scroll up
|
|
125
|
+
if (translateY.value < lowerBound) {
|
|
126
|
+
const diff = Math.min(lowerBound - translateY.value, lowerBound);
|
|
127
|
+
scrollY.value -= diff;
|
|
128
|
+
(0, _reactNativeReanimated.scrollTo)(scrollView, 0, scrollY.value, false);
|
|
129
|
+
ctx.y -= diff;
|
|
130
|
+
translateY.value = ctx.y + translationY;
|
|
131
|
+
}
|
|
132
|
+
// Scroll down
|
|
133
|
+
if (translateY.value > upperBound) {
|
|
134
|
+
const diff = Math.min(translateY.value - upperBound, leftToScrollDown);
|
|
135
|
+
scrollY.value += diff;
|
|
136
|
+
(0, _reactNativeReanimated.scrollTo)(scrollView, 0, scrollY.value, false);
|
|
137
|
+
ctx.y += diff;
|
|
138
|
+
translateY.value = ctx.y + translationY;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
onEnd: () => {
|
|
143
|
+
if (draggable) {
|
|
144
|
+
// Snap the item back into its place when the drag ends
|
|
145
|
+
const newPosition = (0, _Config.getPosition)(positions.value[id], COL, SIZE);
|
|
146
|
+
translateX.value = (0, _reactNativeReanimated.withTiming)(newPosition.x, _Config.animationConfig, () => {
|
|
147
|
+
isGestureActive.value = false; // Set gesture to inactive
|
|
148
|
+
(0, _reactNativeReanimated.runOnJS)(onDragEnd)(positions.value); // Call onDragEnd on the JS thread
|
|
149
|
+
});
|
|
150
|
+
translateY.value = (0, _reactNativeReanimated.withTiming)(newPosition.y, _Config.animationConfig);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Animated style for the item
|
|
156
|
+
const style = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
|
|
157
|
+
const zIndex = isGestureActive.value ? 100 : 0; // Bring the item to front when active
|
|
158
|
+
const scale = editing && isGestureActive.value ? (0, _reactNativeReanimated.withSpring)(1.05) : (0, _reactNativeReanimated.withSpring)(1); // Slightly enlarge the item when dragging
|
|
159
|
+
return {
|
|
160
|
+
position: 'absolute',
|
|
161
|
+
top: 0,
|
|
162
|
+
left: 0,
|
|
163
|
+
width: SIZE,
|
|
164
|
+
height: SIZE,
|
|
165
|
+
zIndex,
|
|
166
|
+
transform: [{
|
|
167
|
+
translateX: translateX.value
|
|
168
|
+
}, {
|
|
169
|
+
translateY: translateY.value
|
|
170
|
+
}, {
|
|
171
|
+
scale
|
|
172
|
+
}]
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
176
|
+
style: style,
|
|
177
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.PanGestureHandler, {
|
|
178
|
+
enabled: editing,
|
|
179
|
+
onGestureEvent: onGestureEvent,
|
|
180
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
181
|
+
style: _reactNative.StyleSheet.absoluteFill,
|
|
182
|
+
children: children
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
var _default = exports.default = Item;
|
|
188
|
+
//# sourceMappingURL=Item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_reactNativeGestureHandler","_reactNativeSafeAreaContext","_Config","_jsxRuntime","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","Item","children","positions","id","onDragEnd","scrollView","scrollY","editing","draggable","tiles","inset","useSafeAreaInsets","containerHeight","Dimensions","height","top","bottom","COL","SIZE","useSortableConfig","contentHeight","keys","value","length","isGestureActive","useSharedValue","position","getPosition","translateX","x","translateY","y","useEffect","useAnimatedReaction","newOrder","pos","withTiming","animationConfig","onGestureEvent","useAnimatedGestureHandler","onStart","_","ctx","onActive","translationX","translationY","getOrder","oldOrder","idToSwap","find","key","targetItem","tile","Number","reorderable","newPositions","lowerBound","upperBound","maxScroll","leftToScrollDown","diff","Math","min","scrollTo","onEnd","newPosition","runOnJS","style","useAnimatedStyle","zIndex","scale","withSpring","left","width","transform","jsx","View","PanGestureHandler","enabled","StyleSheet","absoluteFill","_default","exports"],"sourceRoot":"../../src","sources":["Item.js"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
|
|
9
|
+
var _Item = _interopRequireDefault(require("./Item.js"));
|
|
10
|
+
var _Config = require("./Config.js");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
14
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
15
|
+
/**
|
|
16
|
+
* SortableList Component
|
|
17
|
+
*
|
|
18
|
+
* This component renders a scrollable list of items that can be reordered using drag-and-drop gestures.
|
|
19
|
+
* It manages the overall layout of the items and provides the necessary props to each child `Item` component
|
|
20
|
+
* to enable dragging, scrolling, and reordering functionality.
|
|
21
|
+
*
|
|
22
|
+
* Props:
|
|
23
|
+
* @param {React.ReactNode[]} children - The list of items to render inside the sortable list.
|
|
24
|
+
* @param {boolean} editing - Whether the list is in editing mode, enabling drag-and-drop.
|
|
25
|
+
* @param {Array} tiles - Array of tile data to manage the reordering state.
|
|
26
|
+
* @param {function} onDragEnd - Callback function called with the updated positions when the drag ends.
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
*
|
|
30
|
+
* <SortableList editing={isEditing} tiles={tiles} onDragEnd={handleDragEnd}>
|
|
31
|
+
* {tiles.map((tile) => (
|
|
32
|
+
* <YourTileComponent key={tile.id} id={tile.id} />
|
|
33
|
+
* ))}
|
|
34
|
+
* </SortableList>
|
|
35
|
+
*/const SortableList = ({
|
|
36
|
+
children,
|
|
37
|
+
editing,
|
|
38
|
+
tiles,
|
|
39
|
+
onDragEnd
|
|
40
|
+
}) => {
|
|
41
|
+
// Get the configuration for columns and size from context
|
|
42
|
+
const {
|
|
43
|
+
COL,
|
|
44
|
+
SIZE
|
|
45
|
+
} = (0, _Config.useSortableConfig)();
|
|
46
|
+
|
|
47
|
+
// Shared values to track scrolling and item positions
|
|
48
|
+
const scrollY = (0, _reactNativeReanimated.useSharedValue)(0); // Current scroll position
|
|
49
|
+
const scrollView = (0, _reactNativeReanimated.useAnimatedRef)(); // Reference to the scroll view
|
|
50
|
+
const positions = (0, _reactNativeReanimated.useSharedValue)(children.reduce((acc, child, index) => ({
|
|
51
|
+
...acc,
|
|
52
|
+
[child.props.id]: index
|
|
53
|
+
}), {}));
|
|
54
|
+
|
|
55
|
+
// Scroll event handler to update scrollY shared value
|
|
56
|
+
const onScroll = (0, _reactNativeReanimated.useAnimatedScrollHandler)({
|
|
57
|
+
onScroll: ({
|
|
58
|
+
contentOffset: {
|
|
59
|
+
y
|
|
60
|
+
}
|
|
61
|
+
}) => {
|
|
62
|
+
scrollY.value = y;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.ScrollView, {
|
|
66
|
+
onScroll: onScroll,
|
|
67
|
+
ref: scrollView,
|
|
68
|
+
contentContainerStyle: {
|
|
69
|
+
// Calculate the total height needed for the scroll view content
|
|
70
|
+
height: Math.ceil(children.length / COL) * SIZE
|
|
71
|
+
},
|
|
72
|
+
showsVerticalScrollIndicator: false,
|
|
73
|
+
bounces: false,
|
|
74
|
+
scrollEventThrottle: 16 // Control scroll event frequency
|
|
75
|
+
,
|
|
76
|
+
children: children.map(child => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Item.default, {
|
|
77
|
+
id: child.props.id,
|
|
78
|
+
positions: positions,
|
|
79
|
+
editing: editing,
|
|
80
|
+
draggable: child.props.draggable,
|
|
81
|
+
reorderable: child.props.reorderable,
|
|
82
|
+
tiles: tiles,
|
|
83
|
+
onDragEnd: onDragEnd,
|
|
84
|
+
scrollView: scrollView,
|
|
85
|
+
scrollY: scrollY,
|
|
86
|
+
children: child
|
|
87
|
+
}, child.props.id))
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
var _default = exports.default = /*#__PURE__*/(0, _react.memo)(SortableList);
|
|
91
|
+
//# sourceMappingURL=SortableList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNativeReanimated","_Item","_interopRequireDefault","_Config","_jsxRuntime","e","__esModule","default","_getRequireWildcardCache","WeakMap","r","t","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","SortableList","children","editing","tiles","onDragEnd","COL","SIZE","useSortableConfig","scrollY","useSharedValue","scrollView","useAnimatedRef","positions","reduce","acc","child","index","props","id","onScroll","useAnimatedScrollHandler","contentOffset","y","value","jsx","ScrollView","ref","contentContainerStyle","height","Math","ceil","length","showsVerticalScrollIndicator","bounces","scrollEventThrottle","map","draggable","reorderable","_default","exports","memo"],"sourceRoot":"../../src","sources":["SortableList.js"],"mappings":"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","ignoreList":[]}
|