UNPKG

13.5 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14exports.DraggableGrid = void 0;
15var React = require("react");
16var react_1 = require("react");
17var react_native_1 = require("react-native");
18var block_1 = require("./block");
19var utils_1 = require("./utils");
20var activeBlockOffset = { x: 0, y: 0 };
21exports.DraggableGrid = function (props) {
22 var blockPositions = react_1.useState([])[0];
23 var orderMap = react_1.useState({})[0];
24 var itemMap = react_1.useState({})[0];
25 var items = react_1.useState([])[0];
26 var _a = react_1.useState(0), blockHeight = _a[0], setBlockHeight = _a[1];
27 var _b = react_1.useState(0), blockWidth = _b[0], setBlockWidth = _b[1];
28 var gridHeight = react_1.useState(new react_native_1.Animated.Value(0))[0];
29 var _c = react_1.useState(false), hadInitBlockSize = _c[0], setHadInitBlockSize = _c[1];
30 var dragStartAnimatedValue = react_1.useState(new react_native_1.Animated.Value(1))[0];
31 var _d = react_1.useState({
32 x: 0,
33 y: 0,
34 width: 0,
35 height: 0,
36 }), gridLayout = _d[0], setGridLayout = _d[1];
37 var _e = react_1.useState(), activeItemIndex = _e[0], setActiveItemIndex = _e[1];
38 var assessGridSize = function (event) {
39 if (!hadInitBlockSize) {
40 var blockWidth_1 = event.nativeEvent.layout.width / props.numColumns;
41 var blockHeight_1 = props.itemHeight || blockWidth_1;
42 setBlockWidth(blockWidth_1);
43 setBlockHeight(blockHeight_1);
44 setGridLayout(event.nativeEvent.layout);
45 setHadInitBlockSize(true);
46 }
47 };
48 var _f = react_1.useState(false), panResponderCapture = _f[0], setPanResponderCapture = _f[1];
49 var panResponder = react_native_1.PanResponder.create({
50 onStartShouldSetPanResponder: function () { return true; },
51 onStartShouldSetPanResponderCapture: function () { return false; },
52 onMoveShouldSetPanResponder: function () { return panResponderCapture; },
53 onMoveShouldSetPanResponderCapture: function () { return panResponderCapture; },
54 onShouldBlockNativeResponder: function () { return false; },
55 onPanResponderTerminationRequest: function () { return false; },
56 onPanResponderGrant: onStartDrag,
57 onPanResponderMove: onHandMove,
58 onPanResponderRelease: onHandRelease,
59 });
60 function initBlockPositions() {
61 items.forEach(function (_, index) {
62 blockPositions[index] = getBlockPositionByOrder(index);
63 });
64 }
65 function getBlockPositionByOrder(order) {
66 if (blockPositions[order]) {
67 return blockPositions[order];
68 }
69 var columnOnRow = order % props.numColumns;
70 var y = blockHeight * Math.floor(order / props.numColumns);
71 var x = columnOnRow * blockWidth;
72 return {
73 x: x,
74 y: y,
75 };
76 }
77 function resetGridHeight() {
78 var rowCount = Math.ceil(props.data.length / props.numColumns);
79 gridHeight.setValue(rowCount * blockHeight);
80 }
81 function onBlockPress(itemIndex) {
82 props.onItemPress && props.onItemPress(items[itemIndex].itemData);
83 }
84 function onStartDrag(_, gestureState) {
85 var activeItem = getActiveItem();
86 if (!activeItem)
87 return false;
88 props.onDragStart && props.onDragStart(activeItem.itemData);
89 var x0 = gestureState.x0, y0 = gestureState.y0, moveX = gestureState.moveX, moveY = gestureState.moveY;
90 var activeOrigin = blockPositions[orderMap[activeItem.key].order];
91 var x = activeOrigin.x - x0;
92 var y = activeOrigin.y - y0;
93 activeItem.currentPosition.setOffset({
94 x: x,
95 y: y,
96 });
97 activeBlockOffset = {
98 x: x,
99 y: y,
100 };
101 activeItem.currentPosition.setValue({
102 x: moveX,
103 y: moveY,
104 });
105 }
106 function onHandMove(_, gestureState) {
107 var activeItem = getActiveItem();
108 if (!activeItem)
109 return false;
110 var moveX = gestureState.moveX, moveY = gestureState.moveY;
111 props.onDragging && props.onDragging(gestureState);
112 var xChokeAmount = Math.max(0, activeBlockOffset.x + moveX - (gridLayout.width - blockWidth));
113 var xMinChokeAmount = Math.min(0, activeBlockOffset.x + moveX);
114 var dragPosition = {
115 x: moveX - xChokeAmount - xMinChokeAmount,
116 y: moveY,
117 };
118 var originPosition = blockPositions[orderMap[activeItem.key].order];
119 var dragPositionToActivePositionDistance = getDistance(dragPosition, originPosition);
120 activeItem.currentPosition.setValue(dragPosition);
121 var closetItemIndex = activeItemIndex;
122 var closetDistance = dragPositionToActivePositionDistance;
123 items.forEach(function (item, index) {
124 if (item.itemData.disabledReSorted)
125 return;
126 if (index != activeItemIndex) {
127 var dragPositionToItemPositionDistance = getDistance(dragPosition, blockPositions[orderMap[item.key].order]);
128 if (dragPositionToItemPositionDistance < closetDistance &&
129 dragPositionToItemPositionDistance < blockWidth) {
130 closetItemIndex = index;
131 closetDistance = dragPositionToItemPositionDistance;
132 }
133 }
134 });
135 if (activeItemIndex != closetItemIndex) {
136 var closetOrder = orderMap[items[closetItemIndex].key].order;
137 resetBlockPositionByOrder(orderMap[activeItem.key].order, closetOrder);
138 orderMap[activeItem.key].order = closetOrder;
139 props.onResetSort && props.onResetSort(getSortData());
140 }
141 }
142 function onHandRelease() {
143 var activeItem = getActiveItem();
144 if (!activeItem)
145 return false;
146 props.onDragRelease && props.onDragRelease(getSortData());
147 setPanResponderCapture(false);
148 activeItem.currentPosition.flattenOffset();
149 moveBlockToBlockOrderPosition(activeItem.key);
150 setActiveItemIndex(undefined);
151 }
152 function resetBlockPositionByOrder(activeItemOrder, insertedPositionOrder) {
153 var disabledReSortedItemCount = 0;
154 if (activeItemOrder > insertedPositionOrder) {
155 for (var i = activeItemOrder - 1; i >= insertedPositionOrder; i--) {
156 var key = getKeyByOrder(i);
157 var item = itemMap[key];
158 if (item && item.disabledReSorted) {
159 disabledReSortedItemCount++;
160 }
161 else {
162 orderMap[key].order += disabledReSortedItemCount + 1;
163 disabledReSortedItemCount = 0;
164 moveBlockToBlockOrderPosition(key);
165 }
166 }
167 }
168 else {
169 for (var i = activeItemOrder + 1; i <= insertedPositionOrder; i++) {
170 var key = getKeyByOrder(i);
171 var item = itemMap[key];
172 if (item && item.disabledReSorted) {
173 disabledReSortedItemCount++;
174 }
175 else {
176 orderMap[key].order -= disabledReSortedItemCount + 1;
177 disabledReSortedItemCount = 0;
178 moveBlockToBlockOrderPosition(key);
179 }
180 }
181 }
182 }
183 function moveBlockToBlockOrderPosition(itemKey) {
184 var itemIndex = utils_1.findIndex(items, function (item) { return "" + item.key === "" + itemKey; });
185 items[itemIndex].currentPosition.flattenOffset();
186 react_native_1.Animated.timing(items[itemIndex].currentPosition, {
187 toValue: blockPositions[orderMap[itemKey].order],
188 duration: 200,
189 useNativeDriver: false,
190 }).start();
191 }
192 function getKeyByOrder(order) {
193 return utils_1.findKey(orderMap, function (item) { return item.order === order; });
194 }
195 function getSortData() {
196 var sortData = [];
197 items.forEach(function (item) {
198 sortData[orderMap[item.key].order] = item.itemData;
199 });
200 return sortData;
201 }
202 function getDistance(startOffset, endOffset) {
203 var xDistance = startOffset.x + activeBlockOffset.x - endOffset.x;
204 var yDistance = startOffset.y + activeBlockOffset.y - endOffset.y;
205 return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
206 }
207 function setActiveBlock(itemIndex, item) {
208 if (item.disabledDrag)
209 return;
210 props.onDragItemActive && props.onDragItemActive(item);
211 setPanResponderCapture(true);
212 setActiveItemIndex(itemIndex);
213 }
214 function startDragStartAnimation() {
215 if (!props.dragStartAnimation) {
216 dragStartAnimatedValue.setValue(1);
217 react_native_1.Animated.timing(dragStartAnimatedValue, {
218 toValue: 1.1,
219 duration: 100,
220 useNativeDriver: false,
221 }).start();
222 }
223 }
224 function getBlockStyle(itemIndex) {
225 return [
226 {
227 justifyContent: 'center',
228 alignItems: 'center',
229 },
230 hadInitBlockSize && {
231 width: blockWidth,
232 height: blockHeight,
233 position: 'absolute',
234 top: items[itemIndex].currentPosition.getLayout().top,
235 left: items[itemIndex].currentPosition.getLayout().left,
236 },
237 ];
238 }
239 function getDragStartAnimation(itemIndex) {
240 if (activeItemIndex != itemIndex) {
241 return;
242 }
243 var dragStartAnimation = props.dragStartAnimation || getDefaultDragStartAnimation();
244 return __assign({ zIndex: 3 }, dragStartAnimation);
245 }
246 function getActiveItem() {
247 if (activeItemIndex === undefined)
248 return false;
249 return items[activeItemIndex];
250 }
251 function getDefaultDragStartAnimation() {
252 return {
253 transform: [
254 {
255 scale: dragStartAnimatedValue,
256 },
257 ],
258 shadowColor: '#000000',
259 shadowOpacity: 0.2,
260 shadowRadius: 6,
261 shadowOffset: {
262 width: 1,
263 height: 1,
264 },
265 };
266 }
267 function addItem(item, index) {
268 blockPositions.push(getBlockPositionByOrder(items.length));
269 orderMap[item.key] = {
270 order: index,
271 };
272 itemMap[item.key] = item;
273 items.push({
274 key: item.key,
275 itemData: item,
276 currentPosition: new react_native_1.Animated.ValueXY(getBlockPositionByOrder(index)),
277 });
278 }
279 function removeItem(item) {
280 var itemIndex = utils_1.findIndex(items, function (curItem) { return curItem.key === item.key; });
281 items.splice(itemIndex, 1);
282 blockPositions.pop();
283 delete orderMap[item.key];
284 }
285 function diffData() {
286 props.data.forEach(function (item, index) {
287 if (orderMap[item.key]) {
288 if (orderMap[item.key].order != index) {
289 orderMap[item.key].order = index;
290 moveBlockToBlockOrderPosition(item.key);
291 }
292 var currentItem = items.find(function (i) { return i.key === item.key; });
293 if (currentItem) {
294 currentItem.itemData = item;
295 }
296 itemMap[item.key] = item;
297 }
298 else {
299 addItem(item, index);
300 }
301 });
302 var deleteItems = utils_1.differenceBy(items, props.data, 'key');
303 deleteItems.forEach(function (item) {
304 removeItem(item);
305 });
306 }
307 react_1.useEffect(function () {
308 startDragStartAnimation();
309 }, [activeItemIndex]);
310 react_1.useEffect(function () {
311 if (hadInitBlockSize) {
312 initBlockPositions();
313 }
314 }, [gridLayout]);
315 react_1.useEffect(function () {
316 resetGridHeight();
317 });
318 if (hadInitBlockSize) {
319 diffData();
320 }
321 var itemList = items.map(function (item, itemIndex) {
322 return (<block_1.Block onPress={onBlockPress.bind(null, itemIndex)} onLongPress={setActiveBlock.bind(null, itemIndex, item.itemData)} panHandlers={panResponder.panHandlers} style={getBlockStyle(itemIndex)} dragStartAnimationStyle={getDragStartAnimation(itemIndex)} delayLongPress={props.delayLongPress || 300} key={item.key}>
323 {props.renderItem(item.itemData, orderMap[item.key].order)}
324 </block_1.Block>);
325 });
326 return (<react_native_1.Animated.View style={[
327 styles.draggableGrid,
328 props.style,
329 {
330 height: gridHeight,
331 },
332 ]} onLayout={assessGridSize}>
333 {hadInitBlockSize && itemList}
334 </react_native_1.Animated.View>);
335};
336var styles = react_native_1.StyleSheet.create({
337 draggableGrid: {
338 flex: 1,
339 flexDirection: 'row',
340 flexWrap: 'wrap',
341 },
342});
343//# sourceMappingURL=draggable-grid.js.map
\No newline at end of file