react-editable-photo-grid 1.0.0 → 2.3.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/README.md +195 -1
- package/dist/index.js +1 -1
- package/package.json +12 -7
- package/src/PhotoGrid.tsx +130 -54
- package/src/components/Checkbox.tsx +27 -0
- package/src/components/NonScrollGallery.tsx +188 -0
- package/src/components/PhotoControls.tsx +29 -33
- package/src/components/RowControls.tsx +6 -8
- package/src/components/ScrollGallery.tsx +190 -0
- package/src/index.js +4 -1
- package/src/styles.css +328 -1
- package/src/types.ts +34 -4
- package/src/utils.tsx +120 -24
- package/.babelrc +0 -3
- package/tsconfig.json +0 -18
- package/webpack.config.js +0 -39
package/src/styles.css
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
.photogrid--checkbox {
|
|
2
|
+
background: white;
|
|
3
|
+
border: 2px solid white;
|
|
4
|
+
cursor: pointer;
|
|
5
|
+
width: 18px;
|
|
6
|
+
height: 18px;
|
|
7
|
+
position: absolute;
|
|
8
|
+
top: 10px;
|
|
9
|
+
left: 10px;
|
|
10
|
+
z-index: 10;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.photogrid--checkbox.active {
|
|
14
|
+
background: #333;
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
.photogrid {
|
|
2
18
|
padding: 0 0.125rem;
|
|
3
19
|
}
|
|
@@ -17,6 +33,7 @@
|
|
|
17
33
|
|
|
18
34
|
.photogrid--photo__controls {
|
|
19
35
|
display: block;
|
|
36
|
+
width: 100%;
|
|
20
37
|
position: absolute;
|
|
21
38
|
left: 50%;
|
|
22
39
|
transform: translateX(-50%);
|
|
@@ -32,6 +49,10 @@
|
|
|
32
49
|
margin-left: 0.25rem;
|
|
33
50
|
}
|
|
34
51
|
|
|
52
|
+
.photogrid--row__controls > li + li {
|
|
53
|
+
margin-top: 0.25rem;
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
.photogrid--photo__controls .photo__control, .photogrid--row__controls .row__control {
|
|
36
57
|
width: 36px;
|
|
37
58
|
height: 36px;
|
|
@@ -62,10 +83,47 @@
|
|
|
62
83
|
margin: 0.125rem;
|
|
63
84
|
}
|
|
64
85
|
|
|
86
|
+
.photogrid--photo_overlay, .photogrid__gallery_item__overlay {
|
|
87
|
+
min-height: 0;
|
|
88
|
+
display: none;
|
|
89
|
+
position: absolute;
|
|
90
|
+
bottom: 0;
|
|
91
|
+
left: 0;
|
|
92
|
+
width: 100%;
|
|
93
|
+
background: rgba(0, 0, 0, 0.4);
|
|
94
|
+
color: white;
|
|
95
|
+
padding: 0.5rem;
|
|
96
|
+
z-index: 200;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.photogrid--photo_overlay h4, .photogrid__gallery_item__overlay h4 {
|
|
100
|
+
font-size: 14px;
|
|
101
|
+
font-weight: 600;
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.photogrid--photo_overlay p, .photogrid__gallery_item__overlay p {
|
|
107
|
+
margin: 7px 0 0 0;
|
|
108
|
+
padding: 0;
|
|
109
|
+
font-size: 12px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.photogrid--photo__column > .photo__position {
|
|
113
|
+
position: absolute;
|
|
114
|
+
top: 0;
|
|
115
|
+
z-index: 20;
|
|
116
|
+
left: 50%;
|
|
117
|
+
transform: translateX(-50%);
|
|
118
|
+
background: rgba(0, 0, 0, 0.65);
|
|
119
|
+
color: white;
|
|
120
|
+
padding: 0.1rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
65
123
|
.photogrid--photo__column > img {
|
|
66
124
|
display: block;
|
|
67
125
|
max-width: 100%;
|
|
68
|
-
max-height:
|
|
126
|
+
max-height: 750px;
|
|
69
127
|
height: auto;
|
|
70
128
|
margin: 0;
|
|
71
129
|
-webkit-touch-callout: none;
|
|
@@ -76,7 +134,237 @@
|
|
|
76
134
|
user-select: none;
|
|
77
135
|
}
|
|
78
136
|
|
|
137
|
+
.custom__gallery {
|
|
138
|
+
display: block;
|
|
139
|
+
overflow: hidden;
|
|
140
|
+
position: fixed;
|
|
141
|
+
left: 0;
|
|
142
|
+
top: 0;
|
|
143
|
+
margin: 0 auto;
|
|
144
|
+
width: 100%;
|
|
145
|
+
height: 100vh;
|
|
146
|
+
z-index: 9000;
|
|
147
|
+
background: black;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.custom__gallery .custom__gallery__container {
|
|
151
|
+
vertical-align: middle;
|
|
152
|
+
display: block;
|
|
153
|
+
height: 100%;
|
|
154
|
+
margin: 0 auto;
|
|
155
|
+
position: relative;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.custom__gallery .custom__gallery__container .previous__item {
|
|
159
|
+
display: none;
|
|
160
|
+
height: 50px;
|
|
161
|
+
width: 50px;
|
|
162
|
+
position: absolute;
|
|
163
|
+
top: 50%;
|
|
164
|
+
transform: translateY(-50%);
|
|
165
|
+
background: none;
|
|
166
|
+
border: none;
|
|
167
|
+
color: white;
|
|
168
|
+
font-size: 2rem;
|
|
169
|
+
left: 50px;
|
|
170
|
+
cursor: pointer;
|
|
171
|
+
z-index: 9001;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.custom__gallery .custom__gallery__container .previous__item > * {
|
|
175
|
+
pointer-events: none;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images {
|
|
179
|
+
height: 100vh;
|
|
180
|
+
text-align: center;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item {
|
|
184
|
+
position: relative;
|
|
185
|
+
height: 100vh;
|
|
186
|
+
display: none;
|
|
187
|
+
-webkit-touch-callout: none;
|
|
188
|
+
-webkit-user-select: none;
|
|
189
|
+
-moz-user-select: none;
|
|
190
|
+
user-select: none;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item.active {
|
|
194
|
+
display: block;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item img {
|
|
198
|
+
display: block;
|
|
199
|
+
position: relative;
|
|
200
|
+
top: 50%;
|
|
201
|
+
transform: translateY(-50%);
|
|
202
|
+
max-width: 100%;
|
|
203
|
+
height: auto;
|
|
204
|
+
width: 100%;
|
|
205
|
+
margin: 0 auto;
|
|
206
|
+
line-height: 1;
|
|
207
|
+
vertical-align: middle;
|
|
208
|
+
outline: 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item p {
|
|
212
|
+
color: white;
|
|
213
|
+
margin-top: 12px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.custom__gallery .custom__gallery__container .next__item {
|
|
217
|
+
display: none;
|
|
218
|
+
height: 50px;
|
|
219
|
+
width: 50px;
|
|
220
|
+
position: absolute;
|
|
221
|
+
top: 50%;
|
|
222
|
+
transform: translateY(-50%);
|
|
223
|
+
background: none;
|
|
224
|
+
border: none;
|
|
225
|
+
color: white;
|
|
226
|
+
font-size: 2rem;
|
|
227
|
+
right: 50px;
|
|
228
|
+
cursor: pointer;
|
|
229
|
+
z-index: 9001;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.custom__gallery .custom__gallery__container .next__item > * {
|
|
233
|
+
pointer-events: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.custom__gallery .close__gallery {
|
|
237
|
+
position: absolute;
|
|
238
|
+
z-index: 9999;
|
|
239
|
+
right: 0;
|
|
240
|
+
background: none;
|
|
241
|
+
color: white;
|
|
242
|
+
border: none;
|
|
243
|
+
font-size: 3rem;
|
|
244
|
+
float: right;
|
|
245
|
+
font-weight: 300;
|
|
246
|
+
width: 73px;
|
|
247
|
+
height: 73px;
|
|
248
|
+
overflow: hidden;
|
|
249
|
+
text-decoration: none;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.custom__gallery .close__gallery:active, .custom__gallery .close__gallery:focus {
|
|
253
|
+
text-decoration: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
.photogrid__gallery {
|
|
258
|
+
width: 100%;
|
|
259
|
+
text-align: center;
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
position: fixed;
|
|
262
|
+
height: 100vh;
|
|
263
|
+
left: 0;
|
|
264
|
+
top: 0;
|
|
265
|
+
background-color: black;
|
|
266
|
+
z-index: 400;
|
|
267
|
+
margin: 0 auto;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.photogrid__gallery_scrollcontainer {
|
|
271
|
+
display: flex;
|
|
272
|
+
overflow-x: auto;
|
|
273
|
+
overflow-y: hidden;
|
|
274
|
+
scroll-snap-type: x mandatory;
|
|
275
|
+
scroll-behavior: smooth;
|
|
276
|
+
-webkit-overflow-scrolling: touch;
|
|
277
|
+
height: 100vh;
|
|
278
|
+
margin: 0 auto;
|
|
279
|
+
width: 100%;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.photogrid__gallery_scrollcontainer::-webkit-scrollbar {
|
|
283
|
+
width: 10px;
|
|
284
|
+
height: 10px;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.photogrid__gallery_scrollcontainer::-webkit-scrollbar-thumb {
|
|
288
|
+
background: #ddd;
|
|
289
|
+
border-radius: 10px;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.photogrid__gallery_scrollcontainer::-webkit-scrollbar-track {
|
|
293
|
+
background: transparent;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.photogrid__gallery_item {
|
|
297
|
+
width: 100%;
|
|
298
|
+
height: 100vh;
|
|
299
|
+
scroll-snap-align: start;
|
|
300
|
+
transform-origin: center;
|
|
301
|
+
transform: scale(1);
|
|
302
|
+
position: relative;
|
|
303
|
+
display: flex;
|
|
304
|
+
justify-content: center;
|
|
305
|
+
align-items: center;
|
|
306
|
+
flex-shrink: 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.photogrid__gallery_item +.photogrid__gallery_item {
|
|
310
|
+
margin-left: 1rem;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.photogrid__gallery_item > img {
|
|
314
|
+
max-width: 100%;
|
|
315
|
+
height: auto;
|
|
316
|
+
display: block;
|
|
317
|
+
margin: 0 auto;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.photogrid__gallery__hide {
|
|
321
|
+
text-align: right;
|
|
322
|
+
position: absolute;
|
|
323
|
+
top: 0;
|
|
324
|
+
left: 0;
|
|
325
|
+
width: 100%;
|
|
326
|
+
padding-right: 0.5rem;
|
|
327
|
+
z-index: 500;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.photogrid__gallery__hide > button {
|
|
331
|
+
color: white;
|
|
332
|
+
font-weight: 300;
|
|
333
|
+
width: 73px;
|
|
334
|
+
height: 73px;
|
|
335
|
+
font-size: 3rem;
|
|
336
|
+
background: none;
|
|
337
|
+
border: none;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.photogrid__prev, .photogrid__next {
|
|
341
|
+
display: none;
|
|
342
|
+
width: auto;
|
|
343
|
+
position: absolute;
|
|
344
|
+
top: 50%;
|
|
345
|
+
transform: translateY(-50%);
|
|
346
|
+
color: white;
|
|
347
|
+
z-index: 401;
|
|
348
|
+
font-size: 2rem;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.photogrid__prev > button > *, .photogrid__next > button > * {
|
|
352
|
+
pointer-events: none;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.photogrid__prev {
|
|
356
|
+
left: 1.25rem;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.photogrid__next {
|
|
360
|
+
right: 1.25rem;
|
|
361
|
+
}
|
|
362
|
+
|
|
79
363
|
@media only screen and (min-width: 768px) {
|
|
364
|
+
.custom__gallery .custom__gallery__container .previous__item, .custom__gallery .custom__gallery__container .next__item {
|
|
365
|
+
display: inline-block;
|
|
366
|
+
}
|
|
367
|
+
|
|
80
368
|
.photogrid--photo__row {
|
|
81
369
|
display: flex;
|
|
82
370
|
flex: 1 1 auto;
|
|
@@ -87,3 +375,42 @@
|
|
|
87
375
|
}
|
|
88
376
|
}
|
|
89
377
|
|
|
378
|
+
@media only screen and (min-width: 1024px) {
|
|
379
|
+
.photogrid__prev, .photogrid__next {
|
|
380
|
+
display: block;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
@media only screen and (min-width: 1280px) {
|
|
386
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item img:hover + .custom__gallery__photo__overlay {
|
|
387
|
+
display: block;
|
|
388
|
+
}
|
|
389
|
+
.photogrid--photo__column img:hover + .photogrid--photo_overlay {
|
|
390
|
+
display: block;
|
|
391
|
+
}
|
|
392
|
+
.photogrid__gallery_item > img:hover .photogrid__gallery_item__overlay {
|
|
393
|
+
display: block;
|
|
394
|
+
}
|
|
395
|
+
.photogrid__gallery_scrollcontainer {
|
|
396
|
+
width: 91.6%;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@media only screen and (min-width: 1400px) {
|
|
401
|
+
.custom__gallery .custom__gallery__container {
|
|
402
|
+
width: 92%;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.custom__gallery .custom__gallery__container .custom__gallery__images .custom__gallery__item img {
|
|
406
|
+
max-width: 100%;
|
|
407
|
+
height: 100%;
|
|
408
|
+
width: auto;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@media only screen and (min-width: 1536px) {
|
|
413
|
+
.photogrid__gallery_scrollcontainer {
|
|
414
|
+
width: 75%;
|
|
415
|
+
}
|
|
416
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -5,21 +5,40 @@ export interface PhotoIdAndRowKey {
|
|
|
5
5
|
rowKey: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface ButtonArrows {
|
|
9
|
+
up: string;
|
|
10
|
+
down: string;
|
|
11
|
+
left: string;
|
|
12
|
+
right: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface GalleryButtonArrows {
|
|
16
|
+
prev: string;
|
|
17
|
+
next: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
8
20
|
export interface PhotoItem {
|
|
9
21
|
id: string;
|
|
10
22
|
column: number;
|
|
23
|
+
row: number;
|
|
11
24
|
image_path: string;
|
|
12
25
|
thumbnail_path: string;
|
|
13
|
-
carousel_key: number;
|
|
14
26
|
width: number;
|
|
15
27
|
height: number;
|
|
28
|
+
name?: string;
|
|
29
|
+
description?: string;
|
|
16
30
|
}
|
|
17
31
|
|
|
32
|
+
export enum imgSrcProperty {
|
|
33
|
+
id = 'id',
|
|
34
|
+
thumbnail_path = 'thumbnail_path',
|
|
35
|
+
image_path = 'image_path'
|
|
36
|
+
}
|
|
18
37
|
export interface PhotoRows {
|
|
19
38
|
[key: number]: PhotoItem[];
|
|
20
39
|
}
|
|
21
|
-
|
|
22
40
|
export interface PhotoGridProps {
|
|
41
|
+
photos: PhotoItem[];
|
|
23
42
|
rows: PhotoRows;
|
|
24
43
|
updateRows: (rows: PhotoRows) => void;
|
|
25
44
|
changes: number;
|
|
@@ -27,7 +46,16 @@ export interface PhotoGridProps {
|
|
|
27
46
|
isEditing: boolean;
|
|
28
47
|
selectedPhotos: Array<string>;
|
|
29
48
|
updateSelectedPhotos: (ids: Array<string>) => void;
|
|
30
|
-
|
|
49
|
+
onPhotoClick?: (e: React.MouseEvent<HTMLImageElement>) => void;
|
|
50
|
+
imageSrcPrefix: string;
|
|
51
|
+
imageSrcProperty: imgSrcProperty;
|
|
52
|
+
photoMenu: ReactElement | undefined,
|
|
53
|
+
useGallery?: boolean
|
|
54
|
+
gallerySrcProperty?: imgSrcProperty;
|
|
55
|
+
onGallerySwipe?: (photo: PhotoItem) => void;
|
|
56
|
+
buttonArrows?: ButtonArrows;
|
|
57
|
+
galleryButtonArrows?: GalleryButtonArrows;
|
|
58
|
+
galleryType: string
|
|
31
59
|
}
|
|
32
60
|
|
|
33
61
|
export interface PhotoControlsProps {
|
|
@@ -39,10 +67,12 @@ export interface PhotoControlsProps {
|
|
|
39
67
|
movePhotoUp: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
40
68
|
movePhotoDown: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
41
69
|
movePhotoRight: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
70
|
+
buttonArrows?: ButtonArrows;
|
|
42
71
|
}
|
|
43
72
|
export interface RowControlsProps {
|
|
44
73
|
rowKey: string | number;
|
|
45
74
|
moveRowUp: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
46
75
|
moveRowDown: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
47
|
-
rowCount: number
|
|
76
|
+
rowCount: number;
|
|
77
|
+
buttonArrows?: ButtonArrows;
|
|
48
78
|
}
|
package/src/utils.tsx
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
import { PhotoItem, PhotoRows, PhotoIdAndRowKey, PhotoGridProps } from './types';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Returns true if a photo has details
|
|
6
|
+
* @param photo
|
|
7
|
+
*/
|
|
8
|
+
export const photoHasDetails = (photo: PhotoItem): boolean => {
|
|
9
|
+
if (
|
|
10
|
+
(photo.name != undefined && photo.name !== '')
|
|
11
|
+
|| (photo.description != undefined && photo.description !== '')
|
|
12
|
+
) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Sorts photos into rows
|
|
21
|
+
* @param photos
|
|
22
|
+
*/
|
|
23
|
+
export const sortPhotosIntoRows = (photos: PhotoItem[]): PhotoRows => {
|
|
24
|
+
let rows = {} as PhotoRows;
|
|
25
|
+
|
|
26
|
+
for (const photo of photos) {
|
|
27
|
+
const rowKey = photo.row;
|
|
28
|
+
if (!rows[rowKey]) {
|
|
29
|
+
rows[rowKey] = [];
|
|
30
|
+
}
|
|
31
|
+
rows[rowKey].push(photo);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return rows;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Return the photo property to be used for the src
|
|
39
|
+
* @param photo
|
|
40
|
+
* @param property
|
|
41
|
+
*/
|
|
42
|
+
export const getImageSrcProperty = (photo: PhotoItem, property: string): string => {
|
|
43
|
+
switch (property) {
|
|
44
|
+
case 'id':
|
|
45
|
+
return photo.id;
|
|
46
|
+
case 'thumbnail_path':
|
|
47
|
+
return photo.thumbnail_path;
|
|
48
|
+
case 'image_path':
|
|
49
|
+
return photo.image_path;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return photo.image_path;
|
|
53
|
+
}
|
|
54
|
+
|
|
4
55
|
/**
|
|
5
56
|
* Sorts the photos in a row by column number
|
|
6
57
|
* @param row
|
|
@@ -115,9 +166,12 @@ const getPhotoIdAndRowKey = (e: React.MouseEvent<HTMLButtonElement>): PhotoIdAnd
|
|
|
115
166
|
/**
|
|
116
167
|
* Moves a photo one column to the left
|
|
117
168
|
* @param e
|
|
118
|
-
* @param props
|
|
169
|
+
* @param props
|
|
119
170
|
*/
|
|
120
|
-
export const movePhotoLeft = (
|
|
171
|
+
export const movePhotoLeft = (
|
|
172
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
173
|
+
props: PhotoGridProps
|
|
174
|
+
) => {
|
|
121
175
|
e.preventDefault();
|
|
122
176
|
|
|
123
177
|
const { id, rowKey } = getPhotoIdAndRowKey(e);
|
|
@@ -144,9 +198,12 @@ export const movePhotoLeft = (e: React.MouseEvent<HTMLButtonElement>, props: Pho
|
|
|
144
198
|
/**
|
|
145
199
|
* Move a photo one column to the right
|
|
146
200
|
* @param e
|
|
147
|
-
* @param props
|
|
201
|
+
* @param props
|
|
148
202
|
*/
|
|
149
|
-
export const movePhotoRight = (
|
|
203
|
+
export const movePhotoRight = (
|
|
204
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
205
|
+
props: PhotoGridProps
|
|
206
|
+
) => {
|
|
150
207
|
e.preventDefault();
|
|
151
208
|
|
|
152
209
|
const { id, rowKey } = getPhotoIdAndRowKey(e);
|
|
@@ -201,12 +258,32 @@ const shufflePhotosForwardOneColumn = (row: PhotoItem[], start: number): PhotoIt
|
|
|
201
258
|
return row;
|
|
202
259
|
}
|
|
203
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Deletes a row index from the data if it's empty
|
|
263
|
+
*/
|
|
264
|
+
const deleteRowIfEmpty = (rows: PhotoRows, rowIndex: number) => {
|
|
265
|
+
if (rows[rowIndex] == undefined) {
|
|
266
|
+
Object.entries(rows).map(([index, photos]: [string, PhotoItem[]]) => {
|
|
267
|
+
const thisRowIndex = parseInt(index);
|
|
268
|
+
if (thisRowIndex > rowIndex) {
|
|
269
|
+
delete rows[thisRowIndex];
|
|
270
|
+
rows[thisRowIndex - 1] = photos;
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return rows;
|
|
276
|
+
}
|
|
277
|
+
|
|
204
278
|
/**
|
|
205
279
|
* Moves a photo to the end of the previous row
|
|
206
280
|
* @param e
|
|
207
|
-
* @param props
|
|
281
|
+
* @param props
|
|
208
282
|
*/
|
|
209
|
-
export const movePhotoUp = (
|
|
283
|
+
export const movePhotoUp = (
|
|
284
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
285
|
+
props: PhotoGridProps
|
|
286
|
+
): void => {
|
|
210
287
|
e.preventDefault();
|
|
211
288
|
const { id, rowKey } = getPhotoIdAndRowKey(e);
|
|
212
289
|
|
|
@@ -236,6 +313,8 @@ export const movePhotoUp = (e: React.MouseEvent<HTMLButtonElement>, props: Photo
|
|
|
236
313
|
delete rowsCopy[previousRowKey];
|
|
237
314
|
rowsCopy[previousRowKey] = previousRow;
|
|
238
315
|
|
|
316
|
+
rowsCopy = deleteRowIfEmpty(rowsCopy, rowKey);
|
|
317
|
+
|
|
239
318
|
props.updateRows(rowsCopy);
|
|
240
319
|
props.increaseChanges();
|
|
241
320
|
}
|
|
@@ -243,9 +322,12 @@ export const movePhotoUp = (e: React.MouseEvent<HTMLButtonElement>, props: Photo
|
|
|
243
322
|
/**
|
|
244
323
|
* Moves a photo to the beginning of the next row
|
|
245
324
|
* @param e
|
|
246
|
-
* @param props
|
|
325
|
+
* @param props
|
|
247
326
|
*/
|
|
248
|
-
export const movePhotoDown = (
|
|
327
|
+
export const movePhotoDown = (
|
|
328
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
329
|
+
props: PhotoGridProps
|
|
330
|
+
) => {
|
|
249
331
|
e.preventDefault();
|
|
250
332
|
const { id, rowKey } = getPhotoIdAndRowKey(e);
|
|
251
333
|
|
|
@@ -284,17 +366,16 @@ export const movePhotoDown = (e: React.MouseEvent<HTMLButtonElement>, props: Pho
|
|
|
284
366
|
rowsCopy[rowKey] = thisRow;
|
|
285
367
|
}
|
|
286
368
|
|
|
369
|
+
rowsCopy = deleteRowIfEmpty(rowsCopy, rowKey);
|
|
370
|
+
|
|
287
371
|
props.updateRows(rowsCopy);
|
|
288
372
|
props.increaseChanges();
|
|
289
373
|
}
|
|
290
374
|
|
|
291
375
|
/**
|
|
292
376
|
* Swaps the row order
|
|
293
|
-
* @param
|
|
294
|
-
* @param
|
|
295
|
-
* @param firstRowKey
|
|
296
|
-
* @param secondRow
|
|
297
|
-
* @param secondRowKey
|
|
377
|
+
* @param e
|
|
378
|
+
* @param props
|
|
298
379
|
*/
|
|
299
380
|
const swapRows = (
|
|
300
381
|
rows: PhotoRows,
|
|
@@ -312,11 +393,14 @@ const swapRows = (
|
|
|
312
393
|
}
|
|
313
394
|
|
|
314
395
|
/**
|
|
315
|
-
*
|
|
396
|
+
* Moves a row up
|
|
316
397
|
* @param e
|
|
317
|
-
* @param props
|
|
398
|
+
* @param props
|
|
318
399
|
*/
|
|
319
|
-
export const moveRowUp = (
|
|
400
|
+
export const moveRowUp = (
|
|
401
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
402
|
+
props: PhotoGridProps
|
|
403
|
+
) => {
|
|
320
404
|
e.preventDefault();
|
|
321
405
|
const target = e.currentTarget as HTMLButtonElement;
|
|
322
406
|
let rowKey = target.dataset.row;
|
|
@@ -329,10 +413,15 @@ export const moveRowUp = (e: React.MouseEvent<HTMLButtonElement>, props: PhotoGr
|
|
|
329
413
|
previousRowKey = rowIndex - 1;
|
|
330
414
|
|
|
331
415
|
let rowsCopy = { ...props.rows },
|
|
332
|
-
thisRow = sortRow(rowsCopy[rowIndex])
|
|
333
|
-
previousRow = sortRow(rowsCopy[previousRowKey]);
|
|
416
|
+
thisRow = sortRow(rowsCopy[rowIndex]);
|
|
334
417
|
|
|
335
|
-
|
|
418
|
+
if (rowsCopy[previousRowKey] == undefined) {
|
|
419
|
+
delete rowsCopy[rowIndex];
|
|
420
|
+
rowsCopy[previousRowKey] = thisRow;
|
|
421
|
+
} else {
|
|
422
|
+
let previousRow = sortRow(rowsCopy[previousRowKey]);
|
|
423
|
+
rowsCopy = swapRows(rowsCopy, thisRow, rowIndex, previousRow, previousRowKey);
|
|
424
|
+
}
|
|
336
425
|
|
|
337
426
|
props.updateRows(rowsCopy);
|
|
338
427
|
props.increaseChanges();
|
|
@@ -341,9 +430,12 @@ export const moveRowUp = (e: React.MouseEvent<HTMLButtonElement>, props: PhotoGr
|
|
|
341
430
|
/**
|
|
342
431
|
* Moves a row down
|
|
343
432
|
* @param e
|
|
344
|
-
* @param props
|
|
433
|
+
* @param props
|
|
345
434
|
*/
|
|
346
|
-
export const moveRowDown = (
|
|
435
|
+
export const moveRowDown = (
|
|
436
|
+
e: React.MouseEvent<HTMLButtonElement>,
|
|
437
|
+
props: PhotoGridProps
|
|
438
|
+
) => {
|
|
347
439
|
e.preventDefault();
|
|
348
440
|
const target = e.currentTarget as HTMLButtonElement;
|
|
349
441
|
let rowKey = target.dataset.row;
|
|
@@ -356,10 +448,14 @@ export const moveRowDown = (e: React.MouseEvent<HTMLButtonElement>, props: Photo
|
|
|
356
448
|
nextRowKey = rowIndex + 1;
|
|
357
449
|
|
|
358
450
|
let rowsCopy = { ...props.rows },
|
|
359
|
-
thisRow = sortRow(rowsCopy[rowIndex])
|
|
360
|
-
nextRow = sortRow(rowsCopy[nextRowKey]);
|
|
451
|
+
thisRow = sortRow(rowsCopy[rowIndex]);
|
|
361
452
|
|
|
362
|
-
|
|
453
|
+
if (!rowsCopy[nextRowKey]) {
|
|
454
|
+
throw new TypeError('There is no next row!');
|
|
455
|
+
} else {
|
|
456
|
+
const nextRow = sortRow(rowsCopy[nextRowKey]);
|
|
457
|
+
rowsCopy = swapRows(rowsCopy, thisRow, rowIndex, nextRow, nextRowKey);
|
|
458
|
+
}
|
|
363
459
|
|
|
364
460
|
props.updateRows(rowsCopy);
|
|
365
461
|
props.increaseChanges();
|
package/.babelrc
DELETED
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES5",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"lib": ["dom", "es2015"],
|
|
6
|
-
"jsx": "react",
|
|
7
|
-
"moduleResolution": "node",
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"allowSyntheticDefaultImports": true,
|
|
11
|
-
"strict": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"outDir": "./dist",
|
|
14
|
-
"rootDir": "./src"
|
|
15
|
-
},
|
|
16
|
-
"include": ["src"]
|
|
17
|
-
}
|
|
18
|
-
|