@payloadcms/ui 3.48.0-canary.6 → 3.48.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.
Files changed (101) hide show
  1. package/dist/elements/FolderView/Breadcrumbs/index.d.ts.map +1 -1
  2. package/dist/elements/FolderView/Breadcrumbs/index.js.map +1 -1
  3. package/dist/elements/FolderView/CurrentFolderActions/index.d.ts.map +1 -1
  4. package/dist/elements/FolderView/CurrentFolderActions/index.js +1 -0
  5. package/dist/elements/FolderView/CurrentFolderActions/index.js.map +1 -1
  6. package/dist/elements/FolderView/DragOverlaySelection/index.d.ts +2 -3
  7. package/dist/elements/FolderView/DragOverlaySelection/index.d.ts.map +1 -1
  8. package/dist/elements/FolderView/DragOverlaySelection/index.js +2 -7
  9. package/dist/elements/FolderView/DragOverlaySelection/index.js.map +1 -1
  10. package/dist/elements/FolderView/DraggableTableRow/index.d.ts.map +1 -1
  11. package/dist/elements/FolderView/DraggableTableRow/index.js +0 -1
  12. package/dist/elements/FolderView/DraggableTableRow/index.js.map +1 -1
  13. package/dist/elements/FolderView/DraggableWithClick/index.d.ts +2 -2
  14. package/dist/elements/FolderView/DraggableWithClick/index.d.ts.map +1 -1
  15. package/dist/elements/FolderView/DraggableWithClick/index.js +11 -6
  16. package/dist/elements/FolderView/DraggableWithClick/index.js.map +1 -1
  17. package/dist/elements/FolderView/DraggableWithClick/index.scss +1 -1
  18. package/dist/elements/FolderView/Drawers/MoveToFolder/index.d.ts +2 -0
  19. package/dist/elements/FolderView/Drawers/MoveToFolder/index.d.ts.map +1 -1
  20. package/dist/elements/FolderView/Drawers/MoveToFolder/index.js +53 -44
  21. package/dist/elements/FolderView/Drawers/MoveToFolder/index.js.map +1 -1
  22. package/dist/elements/FolderView/Drawers/MoveToFolder/index.scss +4 -0
  23. package/dist/elements/FolderView/FilterFolderTypePill/index.d.ts +4 -0
  24. package/dist/elements/FolderView/FilterFolderTypePill/index.d.ts.map +1 -0
  25. package/dist/elements/FolderView/{CollectionTypePill → FilterFolderTypePill}/index.js +1 -1
  26. package/dist/elements/FolderView/FilterFolderTypePill/index.js.map +1 -0
  27. package/dist/elements/FolderView/FolderField/index.server.d.ts +4 -0
  28. package/dist/elements/FolderView/FolderField/index.server.d.ts.map +1 -0
  29. package/dist/elements/FolderView/{Field → FolderField}/index.server.js +1 -1
  30. package/dist/elements/FolderView/FolderField/index.server.js.map +1 -0
  31. package/dist/elements/FolderView/FolderFileCard/index.d.ts +2 -1
  32. package/dist/elements/FolderView/FolderFileCard/index.d.ts.map +1 -1
  33. package/dist/elements/FolderView/FolderFileCard/index.js +89 -48
  34. package/dist/elements/FolderView/FolderFileCard/index.js.map +1 -1
  35. package/dist/elements/FolderView/FolderFileCard/index.scss +30 -18
  36. package/dist/elements/FolderView/FolderFileTable/index.d.ts.map +1 -1
  37. package/dist/elements/FolderView/FolderFileTable/index.js +41 -28
  38. package/dist/elements/FolderView/FolderFileTable/index.js.map +1 -1
  39. package/dist/elements/FolderView/FolderTypeField/index.d.ts +6 -0
  40. package/dist/elements/FolderView/FolderTypeField/index.d.ts.map +1 -0
  41. package/dist/elements/FolderView/FolderTypeField/index.js +127 -0
  42. package/dist/elements/FolderView/FolderTypeField/index.js.map +1 -0
  43. package/dist/elements/FolderView/MoveDocToFolder/index.d.ts.map +1 -1
  44. package/dist/elements/FolderView/MoveDocToFolder/index.js +2 -1
  45. package/dist/elements/FolderView/MoveDocToFolder/index.js.map +1 -1
  46. package/dist/elements/FolderView/SortByPill/index.d.ts.map +1 -1
  47. package/dist/elements/FolderView/SortByPill/index.js +11 -9
  48. package/dist/elements/FolderView/SortByPill/index.js.map +1 -1
  49. package/dist/elements/ListHeader/TitleActions/ListCreateNewDocInFolderButton.d.ts +2 -1
  50. package/dist/elements/ListHeader/TitleActions/ListCreateNewDocInFolderButton.d.ts.map +1 -1
  51. package/dist/elements/ListHeader/TitleActions/ListCreateNewDocInFolderButton.js +25 -22
  52. package/dist/elements/ListHeader/TitleActions/ListCreateNewDocInFolderButton.js.map +1 -1
  53. package/dist/exports/client/index.d.ts +2 -1
  54. package/dist/exports/client/index.d.ts.map +1 -1
  55. package/dist/exports/client/index.js +10 -10
  56. package/dist/exports/client/index.js.map +4 -4
  57. package/dist/exports/rsc/index.d.ts +1 -1
  58. package/dist/exports/rsc/index.d.ts.map +1 -1
  59. package/dist/exports/rsc/index.js +1 -1
  60. package/dist/exports/rsc/index.js.map +1 -1
  61. package/dist/fields/Checkbox/Input.d.ts.map +1 -1
  62. package/dist/fields/Checkbox/Input.js +113 -45
  63. package/dist/fields/Checkbox/Input.js.map +1 -1
  64. package/dist/fields/Select/index.d.ts +2 -0
  65. package/dist/fields/Select/index.d.ts.map +1 -1
  66. package/dist/fields/Select/index.js +1 -1
  67. package/dist/fields/Select/index.js.map +1 -1
  68. package/dist/providers/Folders/groupItemIDsByRelation.d.ts +3 -0
  69. package/dist/providers/Folders/groupItemIDsByRelation.d.ts.map +1 -0
  70. package/dist/providers/Folders/groupItemIDsByRelation.js +10 -0
  71. package/dist/providers/Folders/groupItemIDsByRelation.js.map +1 -0
  72. package/dist/providers/Folders/index.d.ts +4 -1
  73. package/dist/providers/Folders/index.d.ts.map +1 -1
  74. package/dist/providers/Folders/index.js +264 -105
  75. package/dist/providers/Folders/index.js.map +1 -1
  76. package/dist/styles.css +1 -1
  77. package/dist/utilities/getFolderResultsComponentAndData.d.ts +3 -7
  78. package/dist/utilities/getFolderResultsComponentAndData.d.ts.map +1 -1
  79. package/dist/utilities/getFolderResultsComponentAndData.js +36 -20
  80. package/dist/utilities/getFolderResultsComponentAndData.js.map +1 -1
  81. package/dist/views/BrowseByFolder/index.js +27 -12
  82. package/dist/views/BrowseByFolder/index.js.map +1 -1
  83. package/dist/views/CollectionFolder/ListSelection/index.d.ts +2 -0
  84. package/dist/views/CollectionFolder/ListSelection/index.d.ts.map +1 -1
  85. package/dist/views/CollectionFolder/ListSelection/index.js +18 -14
  86. package/dist/views/CollectionFolder/ListSelection/index.js.map +1 -1
  87. package/dist/views/CollectionFolder/index.js +21 -8
  88. package/dist/views/CollectionFolder/index.js.map +1 -1
  89. package/package.json +5 -5
  90. package/dist/elements/FolderView/CollectionTypePill/index.d.ts +0 -4
  91. package/dist/elements/FolderView/CollectionTypePill/index.d.ts.map +0 -1
  92. package/dist/elements/FolderView/CollectionTypePill/index.js.map +0 -1
  93. package/dist/elements/FolderView/Field/index.server.d.ts +0 -4
  94. package/dist/elements/FolderView/Field/index.server.d.ts.map +0 -1
  95. package/dist/elements/FolderView/Field/index.server.js.map +0 -1
  96. package/dist/providers/Folders/selection.d.ts +0 -11
  97. package/dist/providers/Folders/selection.d.ts.map +0 -1
  98. package/dist/providers/Folders/selection.js +0 -38
  99. package/dist/providers/Folders/selection.js.map +0 -1
  100. /package/dist/elements/FolderView/{CollectionTypePill → FilterFolderTypePill}/index.scss +0 -0
  101. /package/dist/elements/FolderView/{Field → FolderField}/index.scss +0 -0
@@ -11,36 +11,39 @@ import { parseSearchParams } from '../../utilities/parseSearchParams.js';
11
11
  import { useConfig } from '../Config/index.js';
12
12
  import { useRouteTransition } from '../RouteTransition/index.js';
13
13
  import { useTranslation } from '../Translation/index.js';
14
- import { getMetaSelection, getShiftSelection, groupItemIDsByRelation } from './selection.js';
14
+ import { groupItemIDsByRelation } from './groupItemIDsByRelation.js';
15
15
  const Context = /*#__PURE__*/React.createContext({
16
16
  activeCollectionFolderSlugs: [],
17
17
  allCollectionFolderSlugs: [],
18
18
  allowCreateCollectionSlugs: [],
19
19
  breadcrumbs: [],
20
+ checkIfItemIsDisabled: () => false,
20
21
  clearSelections: () => {},
21
22
  currentFolder: null,
22
23
  documents: [],
24
+ dragOverlayItem: undefined,
23
25
  focusedRowIndex: -1,
24
26
  folderCollectionConfig: null,
25
27
  folderCollectionSlug: '',
26
28
  folderFieldName: 'folder',
27
29
  folderID: undefined,
28
30
  FolderResultsComponent: null,
31
+ folderType: undefined,
29
32
  getFolderRoute: () => '',
30
33
  getSelectedItems: () => [],
31
34
  isDragging: false,
32
35
  itemKeysToMove: undefined,
33
- lastSelectedIndex: null,
34
36
  moveToFolder: () => Promise.resolve(undefined),
35
37
  onItemClick: () => undefined,
36
38
  onItemKeyPress: () => undefined,
37
39
  refineFolderData: () => undefined,
38
40
  search: '',
41
+ selectedFolderCollections: undefined,
39
42
  selectedItemKeys: new Set(),
40
43
  setBreadcrumbs: () => {},
41
44
  setFocusedRowIndex: () => -1,
42
45
  setIsDragging: () => false,
43
- sort: '_folderOrDocumentTitle',
46
+ sort: 'name',
44
47
  subfolders: []
45
48
  });
46
49
  export function FolderProvider({
@@ -57,7 +60,7 @@ export function FolderProvider({
57
60
  FolderResultsComponent: InitialFolderResultsComponent,
58
61
  onItemClick: onItemClickFromProps,
59
62
  search,
60
- sort = '_folderOrDocumentTitle',
63
+ sort = 'name',
61
64
  subfolders
62
65
  }) {
63
66
  const parentFolderContext = useFolder();
@@ -76,6 +79,8 @@ export function FolderProvider({
76
79
  const {
77
80
  startRouteTransition
78
81
  } = useRouteTransition();
82
+ const currentlySelectedIndexes = React.useRef(new Set());
83
+ const [selectedFolderCollections, setSelectedFolderCollections] = React.useState([]);
79
84
  const [FolderResultsComponent, setFolderResultsComponent] = React.useState(InitialFolderResultsComponent || (() => null));
80
85
  const [folderCollectionConfig] = React.useState(() => config.collections.find(collection => config.folders && collection.slug === config.folders.slug));
81
86
  const folderCollectionSlug = folderCollectionConfig.slug;
@@ -85,14 +90,16 @@ export function FolderProvider({
85
90
  const [isDragging, setIsDragging] = React.useState(false);
86
91
  const [selectedItemKeys, setSelectedItemKeys] = React.useState(() => new Set());
87
92
  const [focusedRowIndex, setFocusedRowIndex] = React.useState(-1);
88
- const [lastSelectedIndex, setLastSelectedIndex] = React.useState(null);
93
+ // This is used to determine what data to display on the drag overlay
94
+ const [dragOverlayItem, setDragOverlayItem] = React.useState();
89
95
  const [breadcrumbs, setBreadcrumbs] = React.useState(_breadcrumbsFromProps);
90
96
  const lastClickTime = React.useRef(null);
91
97
  const totalCount = subfolders.length + documents.length;
92
98
  const clearSelections = React.useCallback(() => {
93
99
  setFocusedRowIndex(-1);
94
100
  setSelectedItemKeys(new Set());
95
- setLastSelectedIndex(undefined);
101
+ setDragOverlayItem(undefined);
102
+ currentlySelectedIndexes.current = new Set();
96
103
  }, []);
97
104
  const mergeQuery = React.useCallback((newQuery = {}) => {
98
105
  let page = 'page' in newQuery ? newQuery.page : currentQuery?.page;
@@ -103,6 +110,7 @@ export function FolderProvider({
103
110
  ...currentQuery,
104
111
  ...newQuery,
105
112
  page,
113
+ relationTo: 'relationTo' in newQuery ? newQuery.relationTo : currentQuery?.relationTo,
106
114
  search: 'search' in newQuery ? newQuery.search : currentQuery?.search,
107
115
  sort: 'sort' in newQuery ? newQuery.sort : currentQuery?.sort ?? undefined
108
116
  };
@@ -114,7 +122,10 @@ export function FolderProvider({
114
122
  }) => {
115
123
  if (updateURL) {
116
124
  const newQuery_0 = mergeQuery(query);
117
- startRouteTransition(() => router.replace(`${qs.stringify(newQuery_0, {
125
+ startRouteTransition(() => router.replace(`${qs.stringify({
126
+ ...newQuery_0,
127
+ relationTo: JSON.stringify(newQuery_0.relationTo)
128
+ }, {
118
129
  addQueryPrefix: true
119
130
  })}`));
120
131
  setCurrentQuery(newQuery_0);
@@ -151,10 +162,12 @@ export function FolderProvider({
151
162
  }) => {
152
163
  if (drawerDepth === 1) {
153
164
  // not in a drawer (default is 1)
154
- clearSelections();
155
165
  if (collectionSlug === folderCollectionSlug) {
156
166
  // clicked on folder, take the user to the folder view
157
- startRouteTransition(() => router.push(getFolderRoute(docID)));
167
+ startRouteTransition(() => {
168
+ router.push(getFolderRoute(docID));
169
+ clearSelections();
170
+ });
158
171
  } else if (collectionSlug) {
159
172
  // clicked on document, take the user to the documet view
160
173
  startRouteTransition(() => {
@@ -162,17 +175,97 @@ export function FolderProvider({
162
175
  adminRoute: config.routes.admin,
163
176
  path: `/collections/${collectionSlug}/${docID}`
164
177
  }));
178
+ clearSelections();
165
179
  });
166
180
  }
181
+ } else {
182
+ clearSelections();
167
183
  }
168
184
  if (typeof onItemClickFromProps === 'function') {
169
185
  onItemClickFromProps(getItem(`${collectionSlug}-${docID}`));
170
186
  }
171
187
  }, [clearSelections, config.routes.admin, drawerDepth, folderCollectionSlug, getFolderRoute, getItem, onItemClickFromProps, router, startRouteTransition]);
188
+ const handleShiftSelection = React.useCallback(targetIndex => {
189
+ const allItems = [...subfolders, ...documents];
190
+ // Find existing selection boundaries
191
+ const existingIndexes = allItems.reduce((acc_0, item_0, idx) => {
192
+ if (selectedItemKeys.has(item_0.itemKey)) {
193
+ acc_0.push(idx);
194
+ }
195
+ return acc_0;
196
+ }, []);
197
+ if (existingIndexes.length === 0) {
198
+ // No existing selection, just select target
199
+ return [targetIndex];
200
+ }
201
+ const firstSelectedIndex = Math.min(...existingIndexes);
202
+ const lastSelectedIndex = Math.max(...existingIndexes);
203
+ const isWithinBounds = targetIndex >= firstSelectedIndex && targetIndex <= lastSelectedIndex;
204
+ // Choose anchor based on whether we're contracting or extending
205
+ let anchorIndex = targetIndex;
206
+ if (isWithinBounds) {
207
+ // Contracting: if target is at a boundary, use target as anchor
208
+ // Otherwise, use furthest boundary to maintain opposite edge
209
+ if (targetIndex === firstSelectedIndex || targetIndex === lastSelectedIndex) {
210
+ anchorIndex = targetIndex;
211
+ } else {
212
+ const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex);
213
+ const distanceToLast = Math.abs(targetIndex - lastSelectedIndex);
214
+ anchorIndex = distanceToFirst >= distanceToLast ? firstSelectedIndex : lastSelectedIndex;
215
+ }
216
+ } else {
217
+ // Extending: use closest boundary
218
+ const distanceToFirst_0 = Math.abs(targetIndex - firstSelectedIndex);
219
+ const distanceToLast_0 = Math.abs(targetIndex - lastSelectedIndex);
220
+ anchorIndex = distanceToFirst_0 <= distanceToLast_0 ? firstSelectedIndex : lastSelectedIndex;
221
+ }
222
+ // Create range from anchor to target
223
+ const startIndex = Math.min(anchorIndex, targetIndex);
224
+ const endIndex = Math.max(anchorIndex, targetIndex);
225
+ const newRangeIndexes = Array.from({
226
+ length: endIndex - startIndex + 1
227
+ }, (_, i) => startIndex + i);
228
+ if (isWithinBounds) {
229
+ // Contracting: replace with new range
230
+ return newRangeIndexes;
231
+ } else {
232
+ // Extending: union with existing
233
+ return [...new Set([...existingIndexes, ...newRangeIndexes])];
234
+ }
235
+ }, [subfolders, documents, selectedItemKeys]);
236
+ const updateSelections = React.useCallback(({
237
+ indexes
238
+ }) => {
239
+ const allItems_0 = [...subfolders, ...documents];
240
+ const {
241
+ newSelectedFolderCollections,
242
+ newSelectedItemKeys
243
+ } = allItems_0.reduce((acc_1, item_1, index) => {
244
+ if (indexes.includes(index)) {
245
+ acc_1.newSelectedItemKeys.add(item_1.itemKey);
246
+ if (item_1.relationTo === folderCollectionSlug) {
247
+ item_1.value.folderType?.forEach(collectionSlug_0 => {
248
+ if (!acc_1.newSelectedFolderCollections.includes(collectionSlug_0)) {
249
+ acc_1.newSelectedFolderCollections.push(collectionSlug_0);
250
+ }
251
+ });
252
+ } else {
253
+ if (!acc_1.newSelectedFolderCollections.includes(item_1.relationTo)) {
254
+ acc_1.newSelectedFolderCollections.push(item_1.relationTo);
255
+ }
256
+ }
257
+ }
258
+ return acc_1;
259
+ }, {
260
+ newSelectedFolderCollections: [],
261
+ newSelectedItemKeys: new Set()
262
+ });
263
+ setSelectedFolderCollections(newSelectedFolderCollections);
264
+ setSelectedItemKeys(newSelectedItemKeys);
265
+ }, [documents, folderCollectionSlug, subfolders]);
172
266
  const onItemKeyPress = React.useCallback(({
173
267
  event,
174
- index,
175
- item: item_0
268
+ item: currentItem
176
269
  }) => {
177
270
  const {
178
271
  code,
@@ -182,58 +275,58 @@ export function FolderProvider({
182
275
  } = event;
183
276
  const isShiftPressed = shiftKey;
184
277
  const isCtrlPressed = ctrlKey || metaKey;
185
- let newSelectedIndexes = undefined;
278
+ const isCurrentlySelected = selectedItemKeys.has(currentItem.itemKey);
279
+ const allItems_1 = [...subfolders, ...documents];
280
+ const currentItemIndex = allItems_1.findIndex(item_2 => item_2.itemKey === currentItem.itemKey);
186
281
  switch (code) {
187
282
  case 'ArrowDown':
283
+ case 'ArrowLeft':
284
+ case 'ArrowRight':
285
+ case 'ArrowUp':
188
286
  {
189
287
  event.preventDefault();
190
- const nextIndex_0 = Math.min(index + 1, totalCount - 1);
191
- setFocusedRowIndex(nextIndex_0);
192
- if (isCtrlPressed) {
288
+ if (currentItemIndex === -1) {
193
289
  break;
194
290
  }
195
- if (allowMultiSelection && isShiftPressed) {
196
- newSelectedIndexes = getShiftSelection({
197
- selectFromIndex: Math.min(lastSelectedIndex, totalCount),
198
- selectToIndex: Math.min(nextIndex_0, totalCount)
199
- });
200
- } else {
201
- setLastSelectedIndex(nextIndex_0);
202
- newSelectedIndexes = new Set([nextIndex_0]);
291
+ const isBackward = code === 'ArrowLeft' || code === 'ArrowUp';
292
+ const newItemIndex = isBackward ? currentItemIndex - 1 : currentItemIndex + 1;
293
+ if (newItemIndex < 0 || newItemIndex > totalCount - 1) {
294
+ // out of bounds, keep current selection
295
+ return;
203
296
  }
204
- break;
205
- }
206
- case 'ArrowUp':
207
- {
208
- event.preventDefault();
209
- const prevIndex_0 = Math.max(index - 1, 0);
210
- setFocusedRowIndex(prevIndex_0);
297
+ setFocusedRowIndex(newItemIndex);
211
298
  if (isCtrlPressed) {
212
299
  break;
213
300
  }
214
- if (allowMultiSelection && isShiftPressed) {
215
- newSelectedIndexes = getShiftSelection({
216
- selectFromIndex: lastSelectedIndex,
217
- selectToIndex: prevIndex_0
301
+ if (isShiftPressed && allowMultiSelection) {
302
+ const selectedIndexes = handleShiftSelection(newItemIndex);
303
+ updateSelections({
304
+ indexes: selectedIndexes
218
305
  });
219
- } else {
220
- setLastSelectedIndex(prevIndex_0);
221
- newSelectedIndexes = new Set([prevIndex_0]);
306
+ return;
307
+ }
308
+ // Single selection without shift
309
+ if (!isShiftPressed) {
310
+ const newItem = allItems_1[newItemIndex];
311
+ setSelectedItemKeys(new Set([newItem.itemKey]));
222
312
  }
223
313
  break;
224
314
  }
225
315
  case 'Enter':
226
316
  {
227
317
  if (selectedItemKeys.size === 1) {
228
- newSelectedIndexes = new Set([]);
229
318
  setFocusedRowIndex(undefined);
319
+ navigateAfterSelection({
320
+ collectionSlug: currentItem.relationTo,
321
+ docID: extractID(currentItem.value)
322
+ });
323
+ return;
230
324
  }
231
325
  break;
232
326
  }
233
327
  case 'Escape':
234
328
  {
235
- setFocusedRowIndex(undefined);
236
- newSelectedIndexes = new Set([]);
329
+ clearSelections();
237
330
  break;
238
331
  }
239
332
  case 'KeyA':
@@ -241,9 +334,11 @@ export function FolderProvider({
241
334
  if (allowMultiSelection && isCtrlPressed) {
242
335
  event.preventDefault();
243
336
  setFocusedRowIndex(totalCount - 1);
244
- newSelectedIndexes = new Set(Array.from({
245
- length: totalCount
246
- }, (_, i) => i));
337
+ updateSelections({
338
+ indexes: Array.from({
339
+ length: totalCount
340
+ }, (__0, i_0) => i_0)
341
+ });
247
342
  }
248
343
  break;
249
344
  }
@@ -251,27 +346,38 @@ export function FolderProvider({
251
346
  {
252
347
  if (allowMultiSelection && isShiftPressed) {
253
348
  event.preventDefault();
254
- newSelectedIndexes = getMetaSelection({
255
- currentSelection: newSelectedIndexes,
256
- toggleIndex: index
349
+ const allItems_2 = [...subfolders, ...documents];
350
+ updateSelections({
351
+ indexes: allItems_2.reduce((acc_2, item_3, idx_0) => {
352
+ if (item_3.itemKey === currentItem.itemKey) {
353
+ if (isCurrentlySelected) {
354
+ return acc_2;
355
+ } else {
356
+ acc_2.push(idx_0);
357
+ }
358
+ } else if (selectedItemKeys.has(item_3.itemKey)) {
359
+ acc_2.push(idx_0);
360
+ }
361
+ return acc_2;
362
+ }, [])
257
363
  });
258
- setLastSelectedIndex(index);
259
364
  } else {
260
365
  event.preventDefault();
261
- newSelectedIndexes = new Set([index]);
262
- setLastSelectedIndex(index);
366
+ updateSelections({
367
+ indexes: isCurrentlySelected ? [] : [currentItemIndex]
368
+ });
263
369
  }
264
370
  break;
265
371
  }
266
372
  case 'Tab':
267
373
  {
268
374
  if (allowMultiSelection && isShiftPressed) {
269
- const prevIndex = index - 1;
270
- if (prevIndex < 0 && newSelectedIndexes?.size > 0) {
375
+ const prevIndex = currentItemIndex - 1;
376
+ if (prevIndex < 0 && selectedItemKeys?.size > 0) {
271
377
  setFocusedRowIndex(prevIndex);
272
378
  }
273
379
  } else {
274
- const nextIndex = index + 1;
380
+ const nextIndex = currentItemIndex + 1;
275
381
  if (nextIndex === totalCount && selectedItemKeys.size > 0) {
276
382
  setFocusedRowIndex(totalCount - 1);
277
383
  }
@@ -279,75 +385,78 @@ export function FolderProvider({
279
385
  break;
280
386
  }
281
387
  }
282
- if (!newSelectedIndexes) {
283
- return;
284
- }
285
- setSelectedItemKeys([...subfolders, ...documents].reduce((acc_0, item_1, index_0) => {
286
- if (newSelectedIndexes?.size && newSelectedIndexes.has(index_0)) {
287
- acc_0.add(item_1.itemKey);
288
- }
289
- return acc_0;
290
- }, new Set()));
291
- if (selectedItemKeys.size === 1 && code === 'Enter') {
292
- navigateAfterSelection({
293
- collectionSlug: item_0.relationTo,
294
- docID: extractID(item_0.value)
295
- });
296
- }
297
- }, [allowMultiSelection, documents, lastSelectedIndex, navigateAfterSelection, subfolders, totalCount, selectedItemKeys]);
388
+ }, [selectedItemKeys, subfolders, documents, allowMultiSelection, handleShiftSelection, updateSelections, navigateAfterSelection, clearSelections, totalCount]);
298
389
  const onItemClick = React.useCallback(({
299
390
  event: event_0,
300
- index: index_1,
301
- item: item_2
391
+ item: clickedItem
302
392
  }) => {
303
393
  let doubleClicked = false;
304
394
  const isCtrlPressed_0 = event_0.ctrlKey || event_0.metaKey;
305
395
  const isShiftPressed_0 = event_0.shiftKey;
306
- let newSelectedIndexes_0 = undefined;
396
+ const isCurrentlySelected_0 = selectedItemKeys.has(clickedItem.itemKey);
397
+ const allItems_3 = [...subfolders, ...documents];
398
+ const currentItemIndex_0 = allItems_3.findIndex(item_4 => item_4.itemKey === clickedItem.itemKey);
307
399
  if (allowMultiSelection && isCtrlPressed_0) {
308
- newSelectedIndexes_0 = getMetaSelection({
309
- currentSelection: newSelectedIndexes_0,
310
- toggleIndex: index_1
311
- });
312
- } else if (allowMultiSelection && isShiftPressed_0 && lastSelectedIndex !== undefined) {
313
- newSelectedIndexes_0 = getShiftSelection({
314
- selectFromIndex: lastSelectedIndex,
315
- selectToIndex: index_1
400
+ event_0.preventDefault();
401
+ let overlayItemKey;
402
+ const indexes_0 = allItems_3.reduce((acc_3, item_5, idx_1) => {
403
+ if (item_5.itemKey === clickedItem.itemKey) {
404
+ if (isCurrentlySelected_0 && event_0.type !== 'pointermove') {
405
+ return acc_3;
406
+ } else {
407
+ acc_3.push(idx_1);
408
+ overlayItemKey = item_5.itemKey;
409
+ }
410
+ } else if (selectedItemKeys.has(item_5.itemKey)) {
411
+ acc_3.push(idx_1);
412
+ }
413
+ return acc_3;
414
+ }, []);
415
+ updateSelections({
416
+ indexes: indexes_0
316
417
  });
418
+ if (overlayItemKey) {
419
+ setDragOverlayItem(getItem(overlayItemKey));
420
+ }
421
+ } else if (allowMultiSelection && isShiftPressed_0) {
422
+ if (currentItemIndex_0 !== -1) {
423
+ const selectedIndexes_0 = handleShiftSelection(currentItemIndex_0);
424
+ updateSelections({
425
+ indexes: selectedIndexes_0
426
+ });
427
+ }
317
428
  } else if (allowMultiSelection && event_0.type === 'pointermove') {
318
429
  // on drag start of an unselected item
319
- if (!selectedItemKeys.has(item_2.itemKey)) {
320
- newSelectedIndexes_0 = new Set([index_1]);
430
+ if (!isCurrentlySelected_0) {
431
+ updateSelections({
432
+ indexes: allItems_3.reduce((acc_4, item_6, idx_2) => {
433
+ if (item_6.itemKey === clickedItem.itemKey) {
434
+ acc_4.push(idx_2);
435
+ }
436
+ return acc_4;
437
+ }, [])
438
+ });
321
439
  }
322
- setLastSelectedIndex(index_1);
440
+ setDragOverlayItem(getItem(clickedItem.itemKey));
323
441
  } else {
324
442
  // Normal click - select single item
325
- newSelectedIndexes_0 = new Set([index_1]);
326
443
  const now = Date.now();
327
- doubleClicked = now - lastClickTime.current < 400 && lastSelectedIndex === index_1;
444
+ doubleClicked = now - lastClickTime.current < 400 && dragOverlayItem?.itemKey === clickedItem.itemKey;
328
445
  lastClickTime.current = now;
329
- setLastSelectedIndex(index_1);
330
- }
331
- if (!newSelectedIndexes_0) {
332
- setFocusedRowIndex(undefined);
333
- } else {
334
- setFocusedRowIndex(index_1);
335
- }
336
- if (newSelectedIndexes_0) {
337
- setSelectedItemKeys([...subfolders, ...documents].reduce((acc_1, item_3, index_2) => {
338
- if (newSelectedIndexes_0.size && newSelectedIndexes_0.has(index_2)) {
339
- acc_1.add(item_3.itemKey);
340
- }
341
- return acc_1;
342
- }, new Set()));
446
+ if (!doubleClicked) {
447
+ updateSelections({
448
+ indexes: isCurrentlySelected_0 && selectedItemKeys.size === 1 ? [] : [currentItemIndex_0]
449
+ });
450
+ }
451
+ setDragOverlayItem(getItem(clickedItem.itemKey));
343
452
  }
344
453
  if (doubleClicked) {
345
454
  navigateAfterSelection({
346
- collectionSlug: item_2.relationTo,
347
- docID: extractID(item_2.value)
455
+ collectionSlug: clickedItem.relationTo,
456
+ docID: extractID(clickedItem.value)
348
457
  });
349
458
  }
350
- }, [selectedItemKeys, allowMultiSelection, lastSelectedIndex, subfolders, documents, navigateAfterSelection]);
459
+ }, [selectedItemKeys, subfolders, documents, allowMultiSelection, dragOverlayItem, getItem, updateSelections, navigateAfterSelection, handleShiftSelection]);
351
460
  /**
352
461
  * Makes requests to the server to update the folder field on passed in documents
353
462
  *
@@ -377,7 +486,7 @@ export function FolderProvider({
377
486
  toast.error(t('general:error'));
378
487
  }
379
488
  } else {
380
- for (const [collectionSlug_0, ids] of Object.entries(groupItemIDsByRelation(items))) {
489
+ for (const [collectionSlug_1, ids] of Object.entries(groupItemIDsByRelation(items))) {
381
490
  const query_0 = qs.stringify({
382
491
  depth: 0,
383
492
  limit: 0,
@@ -390,7 +499,7 @@ export function FolderProvider({
390
499
  addQueryPrefix: true
391
500
  });
392
501
  try {
393
- await fetch(`${serverURL}${routes.api}/${collectionSlug_0}${query_0}`, {
502
+ await fetch(`${serverURL}${routes.api}/${collectionSlug_1}${query_0}`, {
394
503
  body: JSON.stringify({
395
504
  [folderFieldName]: toFolderID_0 || null
396
505
  }),
@@ -410,6 +519,53 @@ export function FolderProvider({
410
519
  }
411
520
  clearSelections();
412
521
  }, [folderID, clearSelections, folderCollectionSlug, folderFieldName, routes.api, serverURL, t]);
522
+ const checkIfItemIsDisabled = React.useCallback(item_7 => {
523
+ function folderAcceptsItem({
524
+ item: item_8,
525
+ selectedFolderCollections: selectedFolderCollections_0
526
+ }) {
527
+ if (!item_8.value.folderType || Array.isArray(item_8.value.folderType) && item_8.value.folderType.length === 0) {
528
+ // Enable folder that accept all collections
529
+ return false;
530
+ }
531
+ if (selectedFolderCollections_0.length === 0) {
532
+ // If no collections are selected, enable folders that accept all collections
533
+ return Boolean(item_8.value.folderType || item_8.value.folderType.length > 0);
534
+ }
535
+ // Disable folders that do not accept all of the selected collections
536
+ return selectedFolderCollections_0.some(slug => {
537
+ return !item_8.value.folderType.includes(slug);
538
+ });
539
+ }
540
+ if (isDragging) {
541
+ const isSelected = selectedItemKeys.has(item_7.itemKey);
542
+ if (isSelected) {
543
+ return true;
544
+ } else if (item_7.relationTo === folderCollectionSlug) {
545
+ return folderAcceptsItem({
546
+ item: item_7,
547
+ selectedFolderCollections
548
+ });
549
+ } else {
550
+ // Non folder items are disabled on drag
551
+ return true;
552
+ }
553
+ } else if (parentFolderContext?.selectedItemKeys?.size) {
554
+ // Disable selected items from being navigated to in move to drawer
555
+ if (parentFolderContext.selectedItemKeys.has(item_7.itemKey)) {
556
+ return true;
557
+ }
558
+ // Moving items to folder
559
+ if (item_7.relationTo === folderCollectionSlug) {
560
+ return folderAcceptsItem({
561
+ item: item_7,
562
+ selectedFolderCollections: parentFolderContext.selectedFolderCollections
563
+ });
564
+ }
565
+ // If the item is not a folder, it is disabled on move
566
+ return true;
567
+ }
568
+ }, [selectedFolderCollections, isDragging, selectedItemKeys, folderCollectionSlug, parentFolderContext?.selectedFolderCollections, parentFolderContext?.selectedItemKeys]);
413
569
  // If a new component is provided, update the state so children can re-render with the new component
414
570
  React.useEffect(() => {
415
571
  if (InitialFolderResultsComponent) {
@@ -422,8 +578,9 @@ export function FolderProvider({
422
578
  allCollectionFolderSlugs,
423
579
  allowCreateCollectionSlugs,
424
580
  breadcrumbs,
581
+ checkIfItemIsDisabled,
425
582
  clearSelections,
426
- currentFolder: breadcrumbs?.[0]?.id ? formatFolderOrDocumentItem({
583
+ currentFolder: breadcrumbs?.[breadcrumbs.length - 1]?.id !== undefined ? formatFolderOrDocumentItem({
427
584
  folderFieldName,
428
585
  isUpload: false,
429
586
  relationTo: folderCollectionSlug,
@@ -431,22 +588,24 @@ export function FolderProvider({
431
588
  value: breadcrumbs[breadcrumbs.length - 1]
432
589
  }) : null,
433
590
  documents,
591
+ dragOverlayItem,
434
592
  focusedRowIndex,
435
593
  folderCollectionConfig,
436
594
  folderCollectionSlug,
437
595
  folderFieldName,
438
596
  folderID,
439
597
  FolderResultsComponent,
598
+ folderType: breadcrumbs?.[breadcrumbs.length - 1]?.folderType,
440
599
  getFolderRoute,
441
600
  getSelectedItems,
442
601
  isDragging,
443
602
  itemKeysToMove: parentFolderContext.selectedItemKeys,
444
- lastSelectedIndex,
445
603
  moveToFolder,
446
604
  onItemClick,
447
605
  onItemKeyPress,
448
606
  refineFolderData,
449
607
  search,
608
+ selectedFolderCollections,
450
609
  selectedItemKeys,
451
610
  setBreadcrumbs,
452
611
  setFocusedRowIndex,