@payloadcms/ui 3.63.0-internal.dc01f92 → 3.63.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 (51) hide show
  1. package/dist/elements/PillSelector/index.d.ts.map +1 -1
  2. package/dist/elements/PillSelector/index.js +36 -38
  3. package/dist/elements/PillSelector/index.js.map +1 -1
  4. package/dist/elements/ReactSelect/MultiValue/index.d.ts.map +1 -1
  5. package/dist/elements/ReactSelect/MultiValue/index.js +5 -4
  6. package/dist/elements/ReactSelect/MultiValue/index.js.map +1 -1
  7. package/dist/elements/WhereBuilder/Condition/DefaultFilter/index.d.ts.map +1 -1
  8. package/dist/elements/WhereBuilder/Condition/DefaultFilter/index.js +11 -0
  9. package/dist/elements/WhereBuilder/Condition/DefaultFilter/index.js.map +1 -1
  10. package/dist/elements/WhereBuilder/Condition/Relationship/index.d.ts.map +1 -1
  11. package/dist/elements/WhereBuilder/Condition/Relationship/index.js +3 -4
  12. package/dist/elements/WhereBuilder/Condition/Relationship/index.js.map +1 -1
  13. package/dist/elements/WhereBuilder/Condition/Relationship/types.d.ts +2 -2
  14. package/dist/elements/WhereBuilder/Condition/Relationship/types.d.ts.map +1 -1
  15. package/dist/elements/WhereBuilder/Condition/Relationship/types.js.map +1 -1
  16. package/dist/elements/WhereBuilder/field-types.js +1 -1
  17. package/dist/elements/WhereBuilder/field-types.js.map +1 -1
  18. package/dist/elements/withMergedProps/index.d.ts +1 -1
  19. package/dist/elements/withMergedProps/index.js +1 -1
  20. package/dist/elements/withMergedProps/index.js.map +1 -1
  21. package/dist/exports/client/index.js +12 -12
  22. package/dist/exports/client/index.js.map +3 -3
  23. package/dist/exports/shared/index.js.map +1 -1
  24. package/dist/fields/Upload/HasMany/index.d.ts +1 -0
  25. package/dist/fields/Upload/HasMany/index.d.ts.map +1 -1
  26. package/dist/fields/Upload/HasMany/index.js +50 -45
  27. package/dist/fields/Upload/HasMany/index.js.map +1 -1
  28. package/dist/fields/Upload/HasOne/index.d.ts +1 -0
  29. package/dist/fields/Upload/HasOne/index.d.ts.map +1 -1
  30. package/dist/fields/Upload/HasOne/index.js +3 -1
  31. package/dist/fields/Upload/HasOne/index.js.map +1 -1
  32. package/dist/fields/Upload/Input.d.ts +2 -2
  33. package/dist/fields/Upload/Input.d.ts.map +1 -1
  34. package/dist/fields/Upload/Input.js +270 -125
  35. package/dist/fields/Upload/Input.js.map +1 -1
  36. package/dist/fields/Upload/RelationshipContent/index.d.ts +1 -0
  37. package/dist/fields/Upload/RelationshipContent/index.d.ts.map +1 -1
  38. package/dist/fields/Upload/RelationshipContent/index.js +41 -30
  39. package/dist/fields/Upload/RelationshipContent/index.js.map +1 -1
  40. package/dist/fields/Upload/index.d.ts.map +1 -1
  41. package/dist/fields/Upload/index.js +17 -3
  42. package/dist/fields/Upload/index.js.map +1 -1
  43. package/dist/fields/Upload/types.d.ts +10 -3
  44. package/dist/fields/Upload/types.d.ts.map +1 -1
  45. package/dist/fields/Upload/types.js.map +1 -1
  46. package/dist/providers/TableColumns/buildColumnState/filterFieldsWithPermissions.js +2 -2
  47. package/dist/providers/TableColumns/buildColumnState/filterFieldsWithPermissions.js.map +1 -1
  48. package/dist/utilities/reduceFieldsToOptions.d.ts.map +1 -1
  49. package/dist/utilities/reduceFieldsToOptions.js +20 -6
  50. package/dist/utilities/reduceFieldsToOptions.js.map +1 -1
  51. package/package.json +4 -4
@@ -51,7 +51,7 @@ export function UploadInput(props) {
51
51
  value
52
52
  } = props;
53
53
  const [populatedDocs, setPopulatedDocs] = React.useState();
54
- const [activeRelationTo, setActiveRelationTo] = React.useState(Array.isArray(relationTo) ? relationTo[0] : relationTo);
54
+ const [activeRelationTo] = React.useState(Array.isArray(relationTo) ? relationTo[0] : relationTo);
55
55
  const {
56
56
  openModal
57
57
  } = useModal();
@@ -60,7 +60,8 @@ export function UploadInput(props) {
60
60
  setCollectionSlug,
61
61
  setInitialFiles,
62
62
  setMaxFiles,
63
- setOnSuccess
63
+ setOnSuccess,
64
+ setSelectableCollections
64
65
  } = useBulkUpload();
65
66
  const {
66
67
  permissions
@@ -72,18 +73,57 @@ export function UploadInput(props) {
72
73
  i18n,
73
74
  t
74
75
  } = useTranslation();
76
+ // This will be used by the bulk upload to allow you to select only collections you have create permissions for
77
+ const collectionSlugsWithCreatePermission = useMemo(() => {
78
+ if (Array.isArray(relationTo)) {
79
+ return relationTo.filter(relation => permissions?.collections && permissions.collections?.[relation]?.create);
80
+ }
81
+ return [];
82
+ }, [relationTo, permissions]);
75
83
  const filterOptions = useMemo(() => {
76
- return {
77
- ...filterOptionsFromProps,
78
- [activeRelationTo]: {
79
- ...(filterOptionsFromProps?.[activeRelationTo] || {}),
80
- id: {
81
- ...(filterOptionsFromProps?.[activeRelationTo]?.id || {}),
82
- not_in: (filterOptionsFromProps?.[activeRelationTo]?.id?.not_in || []).concat(...(Array.isArray(value) || value ? [value] : []))
84
+ const isPoly = Array.isArray(relationTo);
85
+ if (!value) {
86
+ return filterOptionsFromProps;
87
+ }
88
+ // Group existing IDs by relation
89
+ const existingIdsByRelation = {};
90
+ const values = Array.isArray(value) ? value : [value];
91
+ for (const val of values) {
92
+ if (isPoly && typeof val === 'object' && 'relationTo' in val) {
93
+ // Poly upload - group by relationTo
94
+ if (!existingIdsByRelation[val.relationTo]) {
95
+ existingIdsByRelation[val.relationTo] = [];
96
+ }
97
+ existingIdsByRelation[val.relationTo].push(val.value);
98
+ } else if (!isPoly) {
99
+ // Non-poly upload - all IDs belong to the single collection
100
+ const collection = relationTo;
101
+ if (!existingIdsByRelation[collection]) {
102
+ existingIdsByRelation[collection] = [];
103
+ }
104
+ const id = typeof val === 'object' && 'value' in val ? val.value : val;
105
+ if (typeof id === 'string' || typeof id === 'number') {
106
+ existingIdsByRelation[collection].push(id);
83
107
  }
84
108
  }
109
+ }
110
+ // Build filter options for each collection
111
+ const newFilterOptions = {
112
+ ...filterOptionsFromProps
85
113
  };
86
- }, [value, activeRelationTo, filterOptionsFromProps]);
114
+ const relations = isPoly ? relationTo : [relationTo];
115
+ relations.forEach(relation_0 => {
116
+ const existingIds = existingIdsByRelation[relation_0] || [];
117
+ newFilterOptions[relation_0] = {
118
+ ...(filterOptionsFromProps?.[relation_0] || {}),
119
+ id: {
120
+ ...(filterOptionsFromProps?.[relation_0]?.id || {}),
121
+ not_in: (filterOptionsFromProps?.[relation_0]?.id?.not_in || []).concat(existingIds)
122
+ }
123
+ };
124
+ });
125
+ return newFilterOptions;
126
+ }, [value, filterOptionsFromProps, relationTo]);
87
127
  const [ListDrawer,, {
88
128
  closeDrawer: closeListDrawer,
89
129
  openDrawer: openListDrawer
@@ -98,9 +138,9 @@ export function UploadInput(props) {
98
138
  collectionSlug: activeRelationTo
99
139
  });
100
140
  /**
101
- * Prevent initial retrieval of documents from running more than once
141
+ * Track the last loaded value to prevent unnecessary reloads
102
142
  */
103
- const loadedValueDocsRef = React.useRef(false);
143
+ const loadedValueRef = React.useRef(null);
104
144
  const canCreate = useMemo(() => {
105
145
  if (!allowCreate) {
106
146
  return false;
@@ -117,69 +157,113 @@ export function UploadInput(props) {
117
157
  onChangeFromProps(newValue);
118
158
  }
119
159
  }, [onChangeFromProps]);
120
- const populateDocs = React.useCallback(async (ids, relatedCollectionSlug) => {
121
- if (!ids.length) {
122
- return;
160
+ const populateDocs = React.useCallback(async items => {
161
+ if (!items?.length) {
162
+ return [];
123
163
  }
124
- const query = {
125
- depth: 0,
126
- draft: true,
127
- limit: ids.length,
128
- locale: code,
129
- where: {
130
- and: [{
131
- id: {
132
- in: ids
133
- }
134
- }]
164
+ // 1. Group IDs by collection
165
+ const grouped = {};
166
+ items.forEach(({
167
+ relationTo: relationTo_0,
168
+ value: value_0
169
+ }) => {
170
+ if (!grouped[relationTo_0]) {
171
+ grouped[relationTo_0] = [];
135
172
  }
136
- };
137
- const response = await fetch(`${serverURL}${api}/${relatedCollectionSlug}`, {
138
- body: qs.stringify(query),
139
- credentials: 'include',
140
- headers: {
141
- 'Accept-Language': i18n.language,
142
- 'Content-Type': 'application/x-www-form-urlencoded',
143
- 'X-Payload-HTTP-Method-Override': 'GET'
144
- },
145
- method: 'POST'
173
+ grouped[relationTo_0].push(value_0);
146
174
  });
147
- if (response.ok) {
148
- const json = await response.json();
149
- let sortedDocs = ids.map(id => json.docs.find(doc => {
150
- return String(doc.id) === String(id);
151
- }));
152
- if (sortedDocs.includes(undefined) && hasMany) {
153
- sortedDocs = sortedDocs.map((doc_0, index) => doc_0 ? doc_0 : {
154
- id: ids[index],
155
- filename: `${t('general:untitled')} - ID: ${ids[index]}`,
156
- isPlaceholder: true
157
- });
175
+ // 2. Fetch per collection
176
+ const fetches = Object.entries(grouped).map(async ([collection_0, ids]) => {
177
+ const query = {
178
+ depth: 0,
179
+ draft: true,
180
+ limit: ids.length,
181
+ locale: code,
182
+ where: {
183
+ and: [{
184
+ id: {
185
+ in: ids
186
+ }
187
+ }]
188
+ }
189
+ };
190
+ const response = await fetch(`${serverURL}${api}/${collection_0}`, {
191
+ body: qs.stringify(query),
192
+ credentials: 'include',
193
+ headers: {
194
+ 'Accept-Language': i18n.language,
195
+ 'Content-Type': 'application/x-www-form-urlencoded',
196
+ 'X-Payload-HTTP-Method-Override': 'GET'
197
+ },
198
+ method: 'POST'
199
+ });
200
+ let docs = [];
201
+ if (response.ok) {
202
+ const data = await response.json();
203
+ docs = data.docs;
158
204
  }
205
+ // Map docs by ID for fast lookup
206
+ const docsById = docs.reduce((acc, doc) => {
207
+ acc[doc.id] = doc;
208
+ return acc;
209
+ }, {});
159
210
  return {
160
- ...json,
161
- docs: sortedDocs
211
+ collection: collection_0,
212
+ docsById
162
213
  };
163
- }
164
- return null;
165
- }, [code, serverURL, api, i18n.language, t, hasMany]);
214
+ });
215
+ const results = await Promise.all(fetches);
216
+ // 3. Build lookup
217
+ const lookup = {};
218
+ results.forEach(({
219
+ collection: collection_1,
220
+ docsById: docsById_0
221
+ }) => {
222
+ lookup[collection_1] = docsById_0;
223
+ });
224
+ // 4. Reconstruct in input order, add placeholders if missing
225
+ const sortedDocs = items.map(({
226
+ relationTo: relationTo_1,
227
+ value: value_1
228
+ }) => {
229
+ const doc_0 = lookup[relationTo_1]?.[value_1] || {
230
+ id: value_1,
231
+ filename: `${t('general:untitled')} - ID: ${value_1}`,
232
+ isPlaceholder: true
233
+ };
234
+ return {
235
+ relationTo: relationTo_1,
236
+ value: doc_0
237
+ };
238
+ });
239
+ return sortedDocs;
240
+ }, [serverURL, api, code, i18n.language, t]);
166
241
  const onUploadSuccess = useCallback(uploadedForms => {
242
+ const isPoly_0 = Array.isArray(relationTo);
167
243
  if (hasMany) {
168
- const mergedValue = [...(Array.isArray(value) ? value : []), ...uploadedForms.map(form => form.doc.id)];
244
+ const newValues = uploadedForms.map(form => isPoly_0 ? {
245
+ relationTo: form.collectionSlug,
246
+ value: form.doc.id
247
+ } : form.doc.id);
248
+ const mergedValue = [...(Array.isArray(value) ? value : []), ...newValues];
169
249
  onChange(mergedValue);
170
250
  setPopulatedDocs(currentDocs => [...(currentDocs || []), ...uploadedForms.map(form_0 => ({
171
251
  relationTo: form_0.collectionSlug,
172
252
  value: form_0.doc
173
253
  }))]);
174
254
  } else {
175
- const firstDoc = uploadedForms[0].doc;
176
- onChange(firstDoc.id);
255
+ const firstDoc = uploadedForms[0];
256
+ const newValue_0 = isPoly_0 ? {
257
+ relationTo: firstDoc.collectionSlug,
258
+ value: firstDoc.doc.id
259
+ } : firstDoc.doc.id;
260
+ onChange(newValue_0);
177
261
  setPopulatedDocs([{
178
262
  relationTo: firstDoc.collectionSlug,
179
- value: firstDoc
263
+ value: firstDoc.doc
180
264
  }]);
181
265
  }
182
- }, [value, onChange, hasMany]);
266
+ }, [value, onChange, hasMany, relationTo]);
183
267
  const onLocalFileSelection = React.useCallback(fileList => {
184
268
  let fileListToUse = fileList;
185
269
  if (!hasMany && fileList && fileList.length > 1) {
@@ -190,126 +274,185 @@ export function UploadInput(props) {
190
274
  if (fileListToUse) {
191
275
  setInitialFiles(fileListToUse);
192
276
  }
193
- setCollectionSlug(relationTo);
277
+ // Use activeRelationTo for poly uploads, or relationTo as string for single collection
278
+ const collectionToUse = Array.isArray(relationTo) ? activeRelationTo : relationTo;
279
+ setCollectionSlug(collectionToUse);
280
+ if (Array.isArray(collectionSlugsWithCreatePermission)) {
281
+ setSelectableCollections(collectionSlugsWithCreatePermission);
282
+ }
194
283
  if (typeof maxRows === 'number') {
195
284
  setMaxFiles(maxRows);
196
285
  }
197
286
  openModal(drawerSlug);
198
- }, [drawerSlug, hasMany, openModal, relationTo, setCollectionSlug, setInitialFiles, maxRows, setMaxFiles]);
287
+ }, [hasMany, relationTo, activeRelationTo, setCollectionSlug, collectionSlugsWithCreatePermission, maxRows, openModal, drawerSlug, setInitialFiles, setSelectableCollections, setMaxFiles]);
199
288
  // only hasMany can bulk select
200
- const onListBulkSelect = React.useCallback(async docs => {
289
+ const onListBulkSelect = React.useCallback(async docs_0 => {
290
+ const isPoly_1 = Array.isArray(relationTo);
201
291
  const selectedDocIDs = [];
202
- for (const [id_0, isSelected] of docs) {
292
+ for (const [id_0, isSelected] of docs_0) {
203
293
  if (isSelected) {
204
294
  selectedDocIDs.push(id_0);
205
295
  }
206
296
  }
207
- const loadedDocs = await populateDocs(selectedDocIDs, activeRelationTo);
297
+ const itemsToLoad = selectedDocIDs.map(id_1 => ({
298
+ relationTo: activeRelationTo,
299
+ value: id_1
300
+ }));
301
+ const loadedDocs = await populateDocs(itemsToLoad);
208
302
  if (loadedDocs) {
209
- setPopulatedDocs(currentDocs_0 => [...(currentDocs_0 || []), ...loadedDocs.docs.map(doc_1 => ({
210
- relationTo: activeRelationTo,
211
- value: doc_1
212
- }))]);
303
+ setPopulatedDocs(currentDocs_0 => [...(currentDocs_0 || []), ...loadedDocs]);
213
304
  }
214
- onChange([...(Array.isArray(value) ? value : []), ...selectedDocIDs]);
305
+ const newValues_0 = selectedDocIDs.map(id_2 => isPoly_1 ? {
306
+ relationTo: activeRelationTo,
307
+ value: id_2
308
+ } : id_2);
309
+ onChange([...(Array.isArray(value) ? value : []), ...newValues_0]);
215
310
  closeListDrawer();
216
- }, [activeRelationTo, closeListDrawer, onChange, populateDocs, value]);
217
- const onDocCreate = React.useCallback(data => {
218
- if (data.doc) {
311
+ }, [activeRelationTo, closeListDrawer, onChange, populateDocs, value, relationTo]);
312
+ const onDocCreate = React.useCallback(data_0 => {
313
+ const isPoly_2 = Array.isArray(relationTo);
314
+ if (data_0.doc) {
219
315
  setPopulatedDocs(currentDocs_1 => [...(currentDocs_1 || []), {
220
316
  relationTo: activeRelationTo,
221
- value: data.doc
317
+ value: data_0.doc
222
318
  }]);
223
- onChange(data.doc.id);
319
+ const newValue_1 = isPoly_2 ? {
320
+ relationTo: activeRelationTo,
321
+ value: data_0.doc.id
322
+ } : data_0.doc.id;
323
+ onChange(newValue_1);
224
324
  }
225
325
  closeCreateDocDrawer();
226
- }, [closeCreateDocDrawer, activeRelationTo, onChange]);
326
+ }, [closeCreateDocDrawer, activeRelationTo, onChange, relationTo]);
227
327
  const onListSelect = useCallback(async ({
228
328
  collectionSlug,
229
- doc: doc_2
329
+ doc: doc_1
230
330
  }) => {
231
- const loadedDocs_0 = await populateDocs([doc_2.id], collectionSlug);
232
- const selectedDoc = loadedDocs_0 ? loadedDocs_0.docs?.[0] : null;
331
+ const isPoly_3 = Array.isArray(relationTo);
332
+ const loadedDocs_0 = await populateDocs([{
333
+ relationTo: collectionSlug,
334
+ value: doc_1.id
335
+ }]);
336
+ const selectedDoc = loadedDocs_0?.[0] || null;
233
337
  setPopulatedDocs(currentDocs_2 => {
234
338
  if (selectedDoc) {
235
339
  if (hasMany) {
236
- return [...(currentDocs_2 || []), {
237
- relationTo: activeRelationTo,
238
- value: selectedDoc
239
- }];
340
+ return [...(currentDocs_2 || []), selectedDoc];
240
341
  }
241
- return [{
242
- relationTo: activeRelationTo,
243
- value: selectedDoc
244
- }];
342
+ return [selectedDoc];
245
343
  }
246
344
  return currentDocs_2;
247
345
  });
346
+ const newValue_2 = isPoly_3 ? {
347
+ relationTo: collectionSlug,
348
+ value: doc_1.id
349
+ } : doc_1.id;
248
350
  if (hasMany) {
249
- onChange([...(Array.isArray(value) ? value : []), doc_2.id]);
351
+ const valueToUse = [...(Array.isArray(value) ? value : []), newValue_2];
352
+ onChange(valueToUse);
250
353
  } else {
251
- onChange(doc_2.id);
354
+ const valueToUse_0 = isPoly_3 ? {
355
+ relationTo: collectionSlug,
356
+ value: doc_1.id
357
+ } : doc_1.id;
358
+ onChange(valueToUse_0);
252
359
  }
253
360
  closeListDrawer();
254
- }, [closeListDrawer, hasMany, populateDocs, onChange, value, activeRelationTo]);
361
+ }, [closeListDrawer, hasMany, populateDocs, onChange, value, relationTo]);
255
362
  const reloadDoc = React.useCallback(async (docID, collectionSlug_0) => {
256
- const {
257
- docs: docs_0
258
- } = await populateDocs([docID], collectionSlug_0);
259
- if (docs_0[0]) {
363
+ const docs_1 = await populateDocs([{
364
+ relationTo: collectionSlug_0,
365
+ value: docID
366
+ }]);
367
+ if (docs_1[0]) {
260
368
  let updatedDocsToPropogate = [];
261
369
  setPopulatedDocs(currentDocs_3 => {
262
- const existingDocIndex = currentDocs_3?.findIndex(doc_3 => {
263
- const hasExisting = doc_3.value?.id === docs_0[0].id || doc_3.value?.isPlaceholder;
264
- return hasExisting && doc_3.relationTo === collectionSlug_0;
370
+ const existingDocIndex = currentDocs_3?.findIndex(doc_2 => {
371
+ const hasExisting = doc_2.value?.id === docs_1[0].value.id || doc_2.value?.isPlaceholder;
372
+ return hasExisting && doc_2.relationTo === collectionSlug_0;
265
373
  });
266
374
  if (existingDocIndex > -1) {
267
375
  const updatedDocs = [...currentDocs_3];
268
- updatedDocs[existingDocIndex] = {
269
- relationTo: collectionSlug_0,
270
- value: docs_0[0]
271
- };
376
+ updatedDocs[existingDocIndex] = docs_1[0];
272
377
  updatedDocsToPropogate = updatedDocs;
273
378
  return updatedDocs;
274
379
  }
380
+ return currentDocs_3;
275
381
  });
276
382
  if (updatedDocsToPropogate.length && hasMany) {
277
- onChange(updatedDocsToPropogate.map(doc_4 => doc_4.value?.id));
383
+ onChange(updatedDocsToPropogate.map(doc_3 => doc_3.value?.id));
278
384
  }
279
385
  }
280
386
  }, [populateDocs, onChange, hasMany]);
281
387
  // only hasMany can reorder
282
- const onReorder = React.useCallback(newValue_0 => {
283
- const newValueIDs = newValue_0.map(({
284
- value: value_0
285
- }) => value_0.id);
286
- onChange(newValueIDs);
287
- setPopulatedDocs(newValue_0);
288
- }, [onChange]);
289
- const onRemove = React.useCallback(newValue_1 => {
290
- const newValueIDs_0 = newValue_1 ? newValue_1.map(({
291
- value: value_1
292
- }) => value_1.id) : null;
293
- onChange(hasMany ? newValueIDs_0 : newValueIDs_0 ? newValueIDs_0[0] : null);
294
- setPopulatedDocs(newValue_1 ? newValue_1 : []);
295
- }, [onChange, hasMany]);
388
+ const onReorder = React.useCallback(newValue_3 => {
389
+ const isPoly_4 = Array.isArray(relationTo);
390
+ const newValueToSave = newValue_3.map(({
391
+ relationTo: rel,
392
+ value: value_2
393
+ }) => isPoly_4 ? {
394
+ relationTo: rel,
395
+ value: value_2.id
396
+ } : value_2.id);
397
+ onChange(newValueToSave);
398
+ setPopulatedDocs(newValue_3);
399
+ }, [onChange, relationTo]);
400
+ const onRemove = React.useCallback(newValue_4 => {
401
+ const isPoly_5 = Array.isArray(relationTo);
402
+ if (!newValue_4 || newValue_4.length === 0) {
403
+ onChange(hasMany ? [] : null);
404
+ setPopulatedDocs(hasMany ? [] : null);
405
+ return;
406
+ }
407
+ const newValueToSave_0 = newValue_4.map(({
408
+ relationTo: rel_0,
409
+ value: value_3
410
+ }) => isPoly_5 ? {
411
+ relationTo: rel_0,
412
+ value: value_3.id
413
+ } : value_3.id);
414
+ onChange(hasMany ? newValueToSave_0 : newValueToSave_0[0]);
415
+ setPopulatedDocs(newValue_4);
416
+ }, [onChange, hasMany, relationTo]);
296
417
  useEffect(() => {
297
418
  async function loadInitialDocs() {
298
419
  if (value) {
299
- loadedValueDocsRef.current = true;
300
- const loadedDocs_1 = await populateDocs(Array.isArray(value) ? value : [value], activeRelationTo);
420
+ let itemsToLoad_0;
421
+ if (Array.isArray(relationTo) && (typeof value === 'object' && 'relationTo' in value || Array.isArray(value) && value.length > 0 && typeof value[0] === 'object' && 'relationTo' in value[0])) {
422
+ // For poly uploads, value should already be in the format { relationTo, value }
423
+ const values_0 = Array.isArray(value) ? value : [value];
424
+ itemsToLoad_0 = values_0.filter(v => typeof v === 'object' && 'relationTo' in v);
425
+ } else {
426
+ // This check is here to satisfy TypeScript that relationTo is a string
427
+ if (!Array.isArray(relationTo)) {
428
+ // For single collection uploads, we need to wrap the IDs
429
+ const ids_0 = Array.isArray(value) ? value : [value];
430
+ itemsToLoad_0 = ids_0.map(id_3 => {
431
+ const idValue = typeof id_3 === 'object' && 'value' in id_3 ? id_3.value : id_3;
432
+ return {
433
+ relationTo,
434
+ value: idValue
435
+ };
436
+ });
437
+ }
438
+ }
439
+ const loadedDocs_1 = await populateDocs(itemsToLoad_0);
301
440
  if (loadedDocs_1) {
302
- setPopulatedDocs(loadedDocs_1.docs.map(doc_5 => ({
303
- relationTo: activeRelationTo,
304
- value: doc_5
305
- })));
441
+ setPopulatedDocs(loadedDocs_1);
442
+ loadedValueRef.current = value;
306
443
  }
444
+ } else {
445
+ // Clear populated docs when value is cleared
446
+ setPopulatedDocs([]);
447
+ loadedValueRef.current = null;
307
448
  }
308
449
  }
309
- if (!loadedValueDocsRef.current) {
450
+ // Only load if value has changed from what we last loaded
451
+ const valueChanged = loadedValueRef.current !== value;
452
+ if (valueChanged) {
310
453
  void loadInitialDocs();
311
454
  }
312
- }, [populateDocs, activeRelationTo, value]);
455
+ }, [populateDocs, value, relationTo]);
313
456
  useEffect(() => {
314
457
  setOnSuccess(onUploadSuccess);
315
458
  }, [value, path, onUploadSuccess, setOnSuccess]);
@@ -346,12 +489,13 @@ export function UploadInput(props) {
346
489
  onReorder: onReorder,
347
490
  readonly: readOnly,
348
491
  reloadDoc: reloadDoc,
349
- serverURL: serverURL
492
+ serverURL: serverURL,
493
+ showCollectionSlug: Array.isArray(relationTo)
350
494
  }) : /*#__PURE__*/_jsx("div", {
351
495
  className: `${baseClass}__loadingRows`,
352
- children: value.map(id_1 => /*#__PURE__*/_jsx(ShimmerEffect, {
496
+ children: value.map(id_4 => /*#__PURE__*/_jsx(ShimmerEffect, {
353
497
  height: "40px"
354
- }, id_1))
498
+ }, typeof id_4 === 'object' ? id_4.value : id_4))
355
499
  })
356
500
  }) : null, !hasMany && value ? /*#__PURE__*/_jsx(_Fragment, {
357
501
  children: populatedDocs && populatedDocs?.length > 0 && populatedDocs[0].value ? /*#__PURE__*/_jsx(UploadComponentHasOne, {
@@ -360,7 +504,8 @@ export function UploadInput(props) {
360
504
  onRemove: onRemove,
361
505
  readonly: readOnly,
362
506
  reloadDoc: reloadDoc,
363
- serverURL: serverURL
507
+ serverURL: serverURL,
508
+ showCollectionSlug: Array.isArray(relationTo)
364
509
  }) : populatedDocs && value && !populatedDocs?.[0]?.value ? /*#__PURE__*/_jsxs(_Fragment, {
365
510
  children: [t('general:untitled'), " - ID: ", value]
366
511
  }) : /*#__PURE__*/_jsx(ShimmerEffect, {