@etsoo/react 1.3.93 → 1.3.94
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/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/mu/DnDList.d.ts +33 -0
- package/lib/mu/DnDList.js +66 -0
- package/package.json +5 -3
- package/src/index.ts +1 -0
- package/src/mu/DnDList.tsx +170 -0
package/lib/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from './mu/CustomFabProps';
|
|
|
38
38
|
export * from './mu/DataGridEx';
|
|
39
39
|
export * from './mu/DataGridRenderers';
|
|
40
40
|
export * from './mu/DialogButton';
|
|
41
|
+
export * from './mu/DnDList';
|
|
41
42
|
export * from './mu/DraggablePaperComponent';
|
|
42
43
|
export * from './mu/EmailInput';
|
|
43
44
|
export * from './mu/FabBox';
|
package/lib/index.js
CHANGED
|
@@ -41,6 +41,7 @@ export * from './mu/CustomFabProps';
|
|
|
41
41
|
export * from './mu/DataGridEx';
|
|
42
42
|
export * from './mu/DataGridRenderers';
|
|
43
43
|
export * from './mu/DialogButton';
|
|
44
|
+
export * from './mu/DnDList';
|
|
44
45
|
export * from './mu/DraggablePaperComponent';
|
|
45
46
|
export * from './mu/EmailInput';
|
|
46
47
|
export * from './mu/FabBox';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DataTypes } from '@etsoo/shared';
|
|
2
|
+
import React, { CSSProperties } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* DnD list props
|
|
5
|
+
*/
|
|
6
|
+
export interface DnDListProps {
|
|
7
|
+
/**
|
|
8
|
+
* Item renderer
|
|
9
|
+
*/
|
|
10
|
+
children: (item: DataTypes.IdItem, index: number, onDelete: (index: number) => void) => React.ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Get list item style callback
|
|
13
|
+
*/
|
|
14
|
+
getItemStyle?: (isDragging: boolean) => CSSProperties;
|
|
15
|
+
/**
|
|
16
|
+
* Get list style callback
|
|
17
|
+
*/
|
|
18
|
+
getListStyle?: (isDraggingOver: boolean) => CSSProperties;
|
|
19
|
+
/**
|
|
20
|
+
* Top and bottom sides renderer
|
|
21
|
+
*/
|
|
22
|
+
sideRenderer?: (top: boolean, onAdd: (item: DataTypes.IdItem) => boolean) => React.ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Name for hidden form input
|
|
25
|
+
*/
|
|
26
|
+
name: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Drag and drop list
|
|
30
|
+
* @param props Props
|
|
31
|
+
* @returns Component
|
|
32
|
+
*/
|
|
33
|
+
export declare function DnDList(props: DnDListProps): JSX.Element;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DataTypes } from '@etsoo/shared';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
|
4
|
+
/**
|
|
5
|
+
* Drag and drop list
|
|
6
|
+
* @param props Props
|
|
7
|
+
* @returns Component
|
|
8
|
+
*/
|
|
9
|
+
export function DnDList(props) {
|
|
10
|
+
// Destruct
|
|
11
|
+
const { children, getItemStyle = (_isDragging) => ({}), getListStyle = () => undefined, name, sideRenderer } = props;
|
|
12
|
+
// State
|
|
13
|
+
const [items, setItems] = React.useState([]);
|
|
14
|
+
// Drag end handler
|
|
15
|
+
const onDragEnd = (result) => {
|
|
16
|
+
console.log(result);
|
|
17
|
+
// Dropped outside the list
|
|
18
|
+
if (!result.destination) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Clone
|
|
22
|
+
const newItems = [...items];
|
|
23
|
+
// Removed item
|
|
24
|
+
const [removed] = newItems.splice(result.source.index, 1);
|
|
25
|
+
// Insert to the destination index
|
|
26
|
+
newItems.splice(result.destination.index, 0, removed);
|
|
27
|
+
// Update the state
|
|
28
|
+
setItems(newItems);
|
|
29
|
+
};
|
|
30
|
+
// Add handler
|
|
31
|
+
const onAdd = (newItem) => {
|
|
32
|
+
// Existence check
|
|
33
|
+
if (items.some((item) => DataTypes.getItemId(item) === DataTypes.getItemId(newItem))) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Clone
|
|
37
|
+
const newItems = [newItem, ...items];
|
|
38
|
+
// Update the state
|
|
39
|
+
setItems(newItems);
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
// Delete handler
|
|
43
|
+
const onDelete = (index) => {
|
|
44
|
+
// Clone
|
|
45
|
+
const newItems = [...items];
|
|
46
|
+
// Remove the item
|
|
47
|
+
newItems.splice(index, 1);
|
|
48
|
+
// Update the state
|
|
49
|
+
setItems(newItems);
|
|
50
|
+
};
|
|
51
|
+
// Layout
|
|
52
|
+
return (React.createElement(React.Fragment, null,
|
|
53
|
+
sideRenderer && sideRenderer(true, onAdd),
|
|
54
|
+
React.createElement(DragDropContext, { onDragEnd: onDragEnd },
|
|
55
|
+
React.createElement(Droppable, { droppableId: name }, (provided, snapshot) => (React.createElement("div", { ...provided.droppableProps, ref: provided.innerRef, style: getListStyle(snapshot.isDraggingOver) },
|
|
56
|
+
items.map((item, index) => {
|
|
57
|
+
const id = DataTypes.getItemId(item);
|
|
58
|
+
return (React.createElement(Draggable, { key: id, draggableId: id, index: index }, (provided, snapshot) => (React.createElement("div", { ref: provided.innerRef, ...provided.draggableProps, ...provided.dragHandleProps, style: {
|
|
59
|
+
...getItemStyle(snapshot.isDragging),
|
|
60
|
+
...provided.draggableProps
|
|
61
|
+
.style
|
|
62
|
+
} }, children(item, index, onDelete)))));
|
|
63
|
+
}),
|
|
64
|
+
provided.placeholder)))),
|
|
65
|
+
sideRenderer && sideRenderer(false, onAdd)));
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.94",
|
|
4
4
|
"description": "TypeScript ReactJs framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"@emotion/react": "^11.7.1",
|
|
51
51
|
"@emotion/style": "^0.8.0",
|
|
52
52
|
"@emotion/styled": "^11.6.0",
|
|
53
|
-
"@etsoo/appscript": "^1.2.
|
|
53
|
+
"@etsoo/appscript": "^1.2.11",
|
|
54
54
|
"@etsoo/notificationbase": "^1.0.95",
|
|
55
|
-
"@etsoo/shared": "^1.0.
|
|
55
|
+
"@etsoo/shared": "^1.0.95",
|
|
56
56
|
"@mui/icons-material": "^5.2.5",
|
|
57
57
|
"@mui/material": "^5.2.6",
|
|
58
58
|
"@reach/router": "^1.3.4",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"@types/reach__router": "^1.3.10",
|
|
62
62
|
"@types/react": "^17.0.38",
|
|
63
63
|
"@types/react-avatar-editor": "^10.3.6",
|
|
64
|
+
"@types/react-beautiful-dnd": "^13.1.2",
|
|
64
65
|
"@types/react-dom": "^17.0.11",
|
|
65
66
|
"@types/react-input-mask": "^3.0.1",
|
|
66
67
|
"@types/react-window": "^1.8.5",
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"pulltorefreshjs": "^0.1.22",
|
|
69
70
|
"react": "^17.0.2",
|
|
70
71
|
"react-avatar-editor": "^12.0.0",
|
|
72
|
+
"react-beautiful-dnd": "^13.1.0",
|
|
71
73
|
"react-dom": "^17.0.2",
|
|
72
74
|
"react-draggable": "^4.4.4",
|
|
73
75
|
"react-imask": "^6.2.2",
|
package/src/index.ts
CHANGED
|
@@ -45,6 +45,7 @@ export * from './mu/CustomFabProps';
|
|
|
45
45
|
export * from './mu/DataGridEx';
|
|
46
46
|
export * from './mu/DataGridRenderers';
|
|
47
47
|
export * from './mu/DialogButton';
|
|
48
|
+
export * from './mu/DnDList';
|
|
48
49
|
export * from './mu/DraggablePaperComponent';
|
|
49
50
|
export * from './mu/EmailInput';
|
|
50
51
|
export * from './mu/FabBox';
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { DataTypes } from '@etsoo/shared';
|
|
2
|
+
import React, { CSSProperties } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
DragDropContext,
|
|
5
|
+
Draggable,
|
|
6
|
+
Droppable,
|
|
7
|
+
DropResult
|
|
8
|
+
} from 'react-beautiful-dnd';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* DnD list props
|
|
12
|
+
*/
|
|
13
|
+
export interface DnDListProps {
|
|
14
|
+
/**
|
|
15
|
+
* Item renderer
|
|
16
|
+
*/
|
|
17
|
+
children: (
|
|
18
|
+
item: DataTypes.IdItem,
|
|
19
|
+
index: number,
|
|
20
|
+
onDelete: (index: number) => void
|
|
21
|
+
) => React.ReactNode;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get list item style callback
|
|
25
|
+
*/
|
|
26
|
+
getItemStyle?: (isDragging: boolean) => CSSProperties;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get list style callback
|
|
30
|
+
*/
|
|
31
|
+
getListStyle?: (isDraggingOver: boolean) => CSSProperties;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Top and bottom sides renderer
|
|
35
|
+
*/
|
|
36
|
+
sideRenderer?: (
|
|
37
|
+
top: boolean,
|
|
38
|
+
onAdd: (item: DataTypes.IdItem) => boolean
|
|
39
|
+
) => React.ReactNode;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Name for hidden form input
|
|
43
|
+
*/
|
|
44
|
+
name: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Drag and drop list
|
|
49
|
+
* @param props Props
|
|
50
|
+
* @returns Component
|
|
51
|
+
*/
|
|
52
|
+
export function DnDList(props: DnDListProps) {
|
|
53
|
+
// Destruct
|
|
54
|
+
const {
|
|
55
|
+
children,
|
|
56
|
+
getItemStyle = (_isDragging) => ({}),
|
|
57
|
+
getListStyle = () => undefined,
|
|
58
|
+
name,
|
|
59
|
+
sideRenderer
|
|
60
|
+
} = props;
|
|
61
|
+
|
|
62
|
+
// State
|
|
63
|
+
const [items, setItems] = React.useState<DataTypes.IdItem[]>([]);
|
|
64
|
+
|
|
65
|
+
// Drag end handler
|
|
66
|
+
const onDragEnd = (result: DropResult) => {
|
|
67
|
+
console.log(result);
|
|
68
|
+
// Dropped outside the list
|
|
69
|
+
if (!result.destination) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Clone
|
|
74
|
+
const newItems = [...items];
|
|
75
|
+
|
|
76
|
+
// Removed item
|
|
77
|
+
const [removed] = newItems.splice(result.source.index, 1);
|
|
78
|
+
|
|
79
|
+
// Insert to the destination index
|
|
80
|
+
newItems.splice(result.destination.index, 0, removed);
|
|
81
|
+
|
|
82
|
+
// Update the state
|
|
83
|
+
setItems(newItems);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Add handler
|
|
87
|
+
const onAdd = (newItem: DataTypes.IdItem) => {
|
|
88
|
+
// Existence check
|
|
89
|
+
if (
|
|
90
|
+
items.some(
|
|
91
|
+
(item) =>
|
|
92
|
+
DataTypes.getItemId(item) === DataTypes.getItemId(newItem)
|
|
93
|
+
)
|
|
94
|
+
) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Clone
|
|
99
|
+
const newItems = [newItem, ...items];
|
|
100
|
+
|
|
101
|
+
// Update the state
|
|
102
|
+
setItems(newItems);
|
|
103
|
+
|
|
104
|
+
return true;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Delete handler
|
|
108
|
+
const onDelete = (index: number) => {
|
|
109
|
+
// Clone
|
|
110
|
+
const newItems = [...items];
|
|
111
|
+
|
|
112
|
+
// Remove the item
|
|
113
|
+
newItems.splice(index, 1);
|
|
114
|
+
|
|
115
|
+
// Update the state
|
|
116
|
+
setItems(newItems);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Layout
|
|
120
|
+
return (
|
|
121
|
+
<React.Fragment>
|
|
122
|
+
{sideRenderer && sideRenderer(true, onAdd)}
|
|
123
|
+
<DragDropContext onDragEnd={onDragEnd}>
|
|
124
|
+
<Droppable droppableId={name}>
|
|
125
|
+
{(provided, snapshot) => (
|
|
126
|
+
<div
|
|
127
|
+
{...provided.droppableProps}
|
|
128
|
+
ref={provided.innerRef}
|
|
129
|
+
style={getListStyle(snapshot.isDraggingOver)}
|
|
130
|
+
>
|
|
131
|
+
{items.map((item, index) => {
|
|
132
|
+
const id = DataTypes.getItemId(item);
|
|
133
|
+
return (
|
|
134
|
+
<Draggable
|
|
135
|
+
key={id}
|
|
136
|
+
draggableId={id}
|
|
137
|
+
index={index}
|
|
138
|
+
>
|
|
139
|
+
{(provided, snapshot) => (
|
|
140
|
+
<div
|
|
141
|
+
ref={provided.innerRef}
|
|
142
|
+
{...provided.draggableProps}
|
|
143
|
+
{...provided.dragHandleProps}
|
|
144
|
+
style={{
|
|
145
|
+
...getItemStyle(
|
|
146
|
+
snapshot.isDragging
|
|
147
|
+
),
|
|
148
|
+
...provided.draggableProps
|
|
149
|
+
.style
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
{children(
|
|
153
|
+
item,
|
|
154
|
+
index,
|
|
155
|
+
onDelete
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
)}
|
|
159
|
+
</Draggable>
|
|
160
|
+
);
|
|
161
|
+
})}
|
|
162
|
+
{provided.placeholder}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
</Droppable>
|
|
166
|
+
</DragDropContext>
|
|
167
|
+
{sideRenderer && sideRenderer(false, onAdd)}
|
|
168
|
+
</React.Fragment>
|
|
169
|
+
);
|
|
170
|
+
}
|