decap-cms-widget-file 3.0.1 → 3.0.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "decap-cms-widget-file",
3
3
  "description": "Widget for uploading files in Decap CMS.",
4
- "version": "3.0.1",
4
+ "version": "3.0.2",
5
5
  "homepage": "https://www.decapcms.org/docs/widgets/#file",
6
6
  "repository": "https://github.com/decaporg/decap-cms/tree/master/packages/decap-cms-widget-file",
7
7
  "bugs": "https://github.com/decaporg/decap-cms/issues",
@@ -22,9 +22,11 @@
22
22
  "build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward"
23
23
  },
24
24
  "dependencies": {
25
+ "@dnd-kit/core": "^6.0.8",
26
+ "@dnd-kit/modifiers": "^6.0.1",
27
+ "@dnd-kit/sortable": "^7.0.2",
25
28
  "array-move": "4.0.0",
26
- "common-tags": "^1.8.0",
27
- "react-sortable-hoc": "^2.0.0"
29
+ "common-tags": "^1.8.0"
28
30
  },
29
31
  "peerDependencies": {
30
32
  "@emotion/core": "^10.0.35",
@@ -36,5 +38,5 @@
36
38
  "react-immutable-proptypes": "^2.1.0",
37
39
  "uuid": "^3.3.2"
38
40
  },
39
- "gitHead": "2f0f9dbd1654868da59cbdbaa2c9dce1d1bcb2c6"
41
+ "gitHead": "b1eae3bbb1661dfa5e3fc0407f03a2e0d564c14e"
40
42
  }
@@ -17,8 +17,18 @@ import {
17
17
  IconButton,
18
18
  } from 'decap-cms-ui-default';
19
19
  import { basename } from 'decap-cms-lib-util';
20
- import { SortableContainer, SortableElement } from 'react-sortable-hoc';
21
20
  import { arrayMoveImmutable as arrayMove } from 'array-move';
21
+ import {
22
+ DndContext,
23
+ MouseSensor,
24
+ TouchSensor,
25
+ closestCenter,
26
+ useSensor,
27
+ useSensors,
28
+ } from '@dnd-kit/core';
29
+ import { SortableContext, useSortable } from '@dnd-kit/sortable';
30
+ import { CSS } from '@dnd-kit/utilities';
31
+ import { restrictToParentElement } from '@dnd-kit/modifiers';
22
32
 
23
33
  const MAX_DISPLAY_LENGTH = 50;
24
34
 
@@ -64,9 +74,20 @@ function SortableImageButtons({ onRemove, onReplace }) {
64
74
  );
65
75
  }
66
76
 
67
- const SortableImage = SortableElement(({ itemValue, getAsset, field, onRemove, onReplace }) => {
77
+ function SortableImage(props) {
78
+ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
79
+ id: props.id,
80
+ });
81
+
82
+ const style = {
83
+ transform: CSS.Transform.toString(transform),
84
+ transition,
85
+ };
86
+
87
+ const { itemValue, getAsset, field, onRemove, onReplace } = props;
88
+
68
89
  return (
69
- <div>
90
+ <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
70
91
  <ImageWrapper sortable>
71
92
  <Image src={getAsset(itemValue, field) || ''} />
72
93
  </ImageWrapper>
@@ -77,32 +98,61 @@ const SortableImage = SortableElement(({ itemValue, getAsset, field, onRemove, o
77
98
  ></SortableImageButtons>
78
99
  </div>
79
100
  );
80
- });
81
-
82
- const SortableMultiImageWrapper = SortableContainer(
83
- ({ items, getAsset, field, onRemoveOne, onReplaceOne }) => {
84
- return (
85
- <div
86
- css={css`
87
- display: flex;
88
- flex-wrap: wrap;
89
- `}
101
+ }
102
+
103
+ function SortableMultiImageWrapper({
104
+ items,
105
+ getAsset,
106
+ field,
107
+ onSortEnd,
108
+ onRemoveOne,
109
+ onReplaceOne,
110
+ }) {
111
+ const activationConstraint = { distance: 4 };
112
+ const sensors = useSensors(
113
+ useSensor(MouseSensor, { activationConstraint }),
114
+ useSensor(TouchSensor, { activationConstraint }),
115
+ );
116
+
117
+ function handleSortEnd({ active, over }) {
118
+ onSortEnd({
119
+ oldIndex: items.findIndex(item => item.id === active.id),
120
+ newIndex: items.findIndex(item => item.id === over.id),
121
+ });
122
+ }
123
+
124
+ return (
125
+ <div
126
+ // eslint-disable-next-line react/no-unknown-property
127
+ css={css`
128
+ display: flex;
129
+ flex-wrap: wrap;
130
+ `}
131
+ >
132
+ <DndContext
133
+ modifiers={[restrictToParentElement]}
134
+ collisionDetection={closestCenter}
135
+ sensors={sensors}
136
+ onDragEnd={handleSortEnd}
90
137
  >
91
- {items.map((itemValue, index) => (
92
- <SortableImage
93
- key={`item-${itemValue}`}
94
- index={index}
95
- itemValue={itemValue}
96
- getAsset={getAsset}
97
- field={field}
98
- onRemove={onRemoveOne(index)}
99
- onReplace={onReplaceOne(index)}
100
- />
101
- ))}
102
- </div>
103
- );
104
- },
105
- );
138
+ <SortableContext items={items}>
139
+ {items.map((item, index) => (
140
+ <SortableImage
141
+ key={item.id}
142
+ id={item.id}
143
+ index={index}
144
+ itemValue={item.value}
145
+ getAsset={getAsset}
146
+ field={field}
147
+ onRemove={onRemoveOne(index)}
148
+ onReplace={onReplaceOne(index)}
149
+ ></SortableImage>
150
+ ))}
151
+ </SortableContext>
152
+ </DndContext>
153
+ </div>
154
+ );
155
+ }
106
156
 
107
157
  const FileLink = styled.a`
108
158
  margin-bottom: 20px;
@@ -152,7 +202,20 @@ function sizeOfValue(value) {
152
202
  }
153
203
 
154
204
  function valueListToArray(value) {
155
- return List.isList(value) ? value.toArray() : value;
205
+ return List.isList(value) ? value.toArray() : value ?? [];
206
+ }
207
+
208
+ function valueListToSortableArray(value) {
209
+ if (!isMultiple(value)) {
210
+ return value;
211
+ }
212
+
213
+ const valueArray = valueListToArray(value).map(value => ({
214
+ id: uuid(),
215
+ value,
216
+ }));
217
+
218
+ return valueArray;
156
219
  }
157
220
 
158
221
  const warnDeprecatedOptions = once(field =>
@@ -259,7 +322,7 @@ export default function withFileControl({ forImage } = {}) {
259
322
  };
260
323
 
261
324
  onRemoveOne = index => () => {
262
- const { value } = this.props;
325
+ const value = valueListToArray(this.props.value);
263
326
  value.splice(index, 1);
264
327
  return this.props.onChange(sizeOfValue(value) > 0 ? [...value] : null);
265
328
  };
@@ -346,11 +409,11 @@ export default function withFileControl({ forImage } = {}) {
346
409
 
347
410
  renderImages = () => {
348
411
  const { getAsset, value, field } = this.props;
349
-
412
+ const items = valueListToSortableArray(value);
350
413
  if (isMultiple(value)) {
351
414
  return (
352
415
  <SortableMultiImageWrapper
353
- items={value}
416
+ items={items}
354
417
  onSortEnd={this.onSortEnd}
355
418
  onRemoveOne={this.onRemoveOne}
356
419
  onReplaceOne={this.onReplaceOne}