1
+ import { CLASSNAMES } from "./constants" ;
1
2
import { Options , Context } from "./types" ;
2
3
import { isElement } from "./utils" ;
3
4
@@ -14,6 +15,7 @@ function draggy({ target, ...options }: Options) {
14
15
removeMouseMove : null ,
15
16
delay : 100 ,
16
17
lastMove : - 1 ,
18
+ multiple : [ ] ,
17
19
options : {
18
20
optimistic : true ,
19
21
direction : "vertical" ,
@@ -46,12 +48,10 @@ function draggy({ target, ...options }: Options) {
46
48
const onMouseDown = ( ev : MouseEvent ) => {
47
49
ev . preventDefault ( ) ;
48
50
handleMouseDown ( context , ev , c ) ;
49
- if ( context . options . onStart && context . origin ) {
50
- context . options . onStart ( ev , {
51
- dragged : context . origin ,
52
- dropzone : context . zone ,
53
- } ) ;
54
- }
51
+ context . options . onStart ?.( ev , {
52
+ origin : context . origin ,
53
+ zone : context . zone ,
54
+ } ) ;
55
55
} ;
56
56
c . addEventListener ( "mousedown" , onMouseDown ) ;
57
57
context . events . set ( c , onMouseDown ) ;
@@ -63,26 +63,36 @@ function draggy({ target, ...options }: Options) {
63
63
64
64
if ( context . options . onBeforeDrop && context . originZone && context . origin ) {
65
65
const bool = context . options . onBeforeDrop ( ev , {
66
- dragged : context . origin ,
67
- dropzone : context . zone ,
66
+ origin : context . origin ,
67
+ zone : context . zone ,
68
68
} ) ;
69
69
70
70
if ( ! bool ) {
71
71
context . originZone . insertBefore ( context . origin , context . nextSibling ) ;
72
72
}
73
73
}
74
74
75
- if ( context . options . onDrop && context . origin ) {
76
- context . options . onDrop ( ev , {
77
- dragged : context . origin ,
78
- dropzone : context . zone ,
79
- } ) ;
80
- }
75
+ context . options . onDrop ?.( ev , {
76
+ origin : context . origin ,
77
+ zone : context . zone ,
78
+ } ) ;
81
79
82
80
context . shadow ?. remove ( ) ;
83
81
context . shadow = null ;
84
82
85
- context . origin ?. classList . remove ( "placeholder" ) ;
83
+ if ( context . multiple && context . zone && context . origin ) {
84
+ for ( let i = 0 ; i < context . multiple . length ; i ++ ) {
85
+ const m = context . multiple [ i ] ;
86
+ if ( ! m || ! m . origin ) return ;
87
+ context . zone . insertBefore ( m . origin , context . origin . nextElementSibling ) ;
88
+ m . origin . style . display = m . style . display ;
89
+ m . origin . classList . remove ( CLASSNAMES . selection ) ;
90
+ }
91
+
92
+ context . multiple = [ ] ;
93
+ }
94
+
95
+ context . origin ?. classList . remove ( CLASSNAMES . origin ) ;
86
96
context . origin = null ;
87
97
88
98
context . removeMouseMove ?.( ) ;
@@ -106,37 +116,64 @@ function draggy({ target, ...options }: Options) {
106
116
}
107
117
108
118
const handleMouseDown = ( context : Context , ev : MouseEvent , el : HTMLElement ) => {
109
- context . shadow = createShadow ( context , el , ev . clientX , ev . clientY ) ;
119
+ if ( ev . shiftKey ) {
120
+ context . multiple . push ( {
121
+ origin : el ,
122
+ style : {
123
+ display : el . style . display ,
124
+ } ,
125
+ originZone : el . parentElement ,
126
+ nextSibling : el . nextElementSibling as HTMLElement | null ,
127
+ } ) ;
128
+
129
+ el . classList . add ( CLASSNAMES . selection ) ;
130
+
131
+ return ;
132
+ }
110
133
111
- el . classList . add ( "placeholder" ) ;
134
+ context . shadow = createShadow ( context , ev , el ) ;
135
+
136
+ el . classList . add ( CLASSNAMES . origin ) ;
112
137
context . origin = el ;
113
138
139
+ if ( context . multiple . length ) {
140
+ for ( let i = 0 ; i < context . multiple . length ; i ++ ) {
141
+ const m = context . multiple [ i ] ;
142
+ if ( ! m ?. origin ) return ;
143
+ if ( m . origin !== context . origin ) {
144
+ m . origin . style . display = "none" ;
145
+ }
146
+ }
147
+ }
148
+
114
149
context . originZone = el . parentElement ;
115
150
context . nextSibling = el . nextElementSibling as HTMLElement | null ;
116
151
117
152
handleChildren ( context ) ;
118
153
} ;
119
154
120
- const createShadow = (
121
- context : Context ,
122
- el : HTMLElement ,
123
- clientX : number ,
124
- clientY : number ,
125
- ) => {
155
+ const createShadow = ( context : Context , ev : MouseEvent , el : HTMLElement ) => {
126
156
const shadow = el . cloneNode ( true ) as HTMLElement ;
127
157
128
- shadow . classList . add ( " dragging" ) ;
158
+ shadow . classList . add ( CLASSNAMES . dragging ) ;
129
159
shadow . style . position = "absolute" ;
130
160
shadow . style . pointerEvents = "none" ;
131
161
shadow . style . width = `${ el . offsetWidth } px` ;
132
162
shadow . style . height = `${ el . offsetHeight } px` ;
133
163
shadow . style . zIndex = "9999" ;
134
164
135
165
const rect = el . getBoundingClientRect ( ) ;
136
- const offsets = { x : clientX - rect . left , y : clientY - rect . top } ;
166
+ const offsets = { x : ev . clientX - rect . left , y : ev . clientY - rect . top } ;
167
+
168
+ shadow . style . left = `${ ev . clientX - offsets . x + scrollX } px` ;
169
+ shadow . style . top = `${ ev . clientY - offsets . y + scrollY } px` ;
137
170
138
- shadow . style . left = `${ clientX - offsets . x + scrollX } px` ;
139
- shadow . style . top = `${ clientY - offsets . y + scrollY } px` ;
171
+ context . options . onShadow ?.( ev , {
172
+ shadow,
173
+ origin : el ,
174
+ zone : context . zone ,
175
+ multiple : context . multiple ,
176
+ } ) ;
140
177
141
178
const onMouseMove = ( ev : Event ) => handleMouseMove ( ev , offsets ) ;
142
179
document . addEventListener ( "mousemove" , onMouseMove ) ;
@@ -158,12 +195,10 @@ const createShadow = (
158
195
}
159
196
160
197
if ( context . zone && ! context . zone . contains ( point ) ) {
161
- if ( context . options . onLeave && context . origin ) {
162
- context . options . onLeave ( ev , {
163
- dragged : context . origin ,
164
- dropzone : context . zone ,
165
- } ) ;
166
- }
198
+ context . options . onLeave ?.( ev , {
199
+ origin : context . origin ,
200
+ zone : context . zone ,
201
+ } ) ;
167
202
context . zone = null ;
168
203
}
169
204
@@ -179,19 +214,15 @@ const createShadow = (
179
214
if ( z . contains ( point ) ) {
180
215
if ( context . zone !== z ) {
181
216
context . zone = z ;
182
- if ( context . options . onEnter && context . origin ) {
183
- context . options . onEnter ( ev , {
184
- dragged : context . origin ,
185
- dropzone : context . zone ,
186
- } ) ;
187
- }
188
- }
189
- if ( context . options . onOver && context . origin ) {
190
- context . options . onOver ( ev , {
191
- dragged : context . origin ,
192
- dropzone : context . zone ,
217
+ context . options . onEnter ?.( ev , {
218
+ origin : context . origin ,
219
+ zone : context . zone ,
193
220
} ) ;
194
221
}
222
+ context . options . onOver ?.( ev , {
223
+ origin : context . origin ,
224
+ zone : context . zone ,
225
+ } ) ;
195
226
handlePushing ( context , x , y ) ;
196
227
break ;
197
228
}
@@ -254,7 +285,7 @@ const handlePushing = (context: Context, x: number, y: number) => {
254
285
}
255
286
256
287
const children = Array . from ( z . children ) . filter (
257
- ( c ) => c !== placeholder && ! c . classList . contains ( "placeholder" ) ,
288
+ ( c ) => c !== placeholder && ! c . classList . contains ( CLASSNAMES . origin ) ,
258
289
) ;
259
290
const zones = children . map ( ( c ) => c . getBoundingClientRect ( ) ) ;
260
291
0 commit comments