@orion-studios/payload-admin-components 0.2.0-beta.8 → 0.2.0-beta.9

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 (105) hide show
  1. package/dist/OrionBlocksFieldImpl-QKEQVSWH.mjs +897 -0
  2. package/dist/client.js +35 -843
  3. package/dist/client.mjs +1 -2
  4. package/package.json +1 -1
  5. package/dist/OrionBlocksFieldImpl-CI4ZCI37.mjs +0 -1555
  6. package/dist/OrionBlocksFieldImpl-H6NQDUTO.mjs +0 -1673
  7. package/dist/OrionBlocksFieldImpl-IFQEHFQE.mjs +0 -1556
  8. package/dist/OrionBlocksFieldImpl-ON5V6RKK.mjs +0 -1672
  9. package/dist/ar-CQPBHJUS.mjs +0 -466
  10. package/dist/ar-PV2VGVQN.mjs +0 -465
  11. package/dist/az-D5NUKNZJ.mjs +0 -511
  12. package/dist/az-MGONV7JN.mjs +0 -510
  13. package/dist/bg-7JF7SMVW.mjs +0 -459
  14. package/dist/bg-TCWX2HSC.mjs +0 -460
  15. package/dist/bn-57KNX42B.mjs +0 -511
  16. package/dist/bn-YZPQUQSN.mjs +0 -510
  17. package/dist/ca-5G7BH4UM.mjs +0 -500
  18. package/dist/ca-V2T4MXPG.mjs +0 -501
  19. package/dist/chunk-2HEQIEE5.mjs +0 -67
  20. package/dist/chunk-4LIGGHC6.mjs +0 -207
  21. package/dist/chunk-64J5ITA3.mjs +0 -38
  22. package/dist/chunk-6DZX6EAA.mjs +0 -37
  23. package/dist/chunk-KD2RXOTI.mjs +0 -69
  24. package/dist/chunk-MB3FF66L.mjs +0 -93
  25. package/dist/chunk-TOFT23KV.mjs +0 -328
  26. package/dist/chunk-TYKFN3MB.mjs +0 -91
  27. package/dist/chunk-YRJ7KIKY.mjs +0 -326
  28. package/dist/cs-KFMDXS5A.mjs +0 -675
  29. package/dist/cs-RWGCPQVC.mjs +0 -674
  30. package/dist/da-LVVHFQOW.mjs +0 -425
  31. package/dist/da-RCFQT7KV.mjs +0 -426
  32. package/dist/de-NIRMSMVD.mjs +0 -544
  33. package/dist/de-VNZDQGMS.mjs +0 -543
  34. package/dist/en-US-B6WPT27F.mjs +0 -437
  35. package/dist/en-US-GJR2OYQI.mjs +0 -436
  36. package/dist/es-CSZOINUC.mjs +0 -445
  37. package/dist/es-LEHJVCDL.mjs +0 -446
  38. package/dist/et-OAHZV6ZW.mjs +0 -528
  39. package/dist/et-XXGXI6Z2.mjs +0 -529
  40. package/dist/fa-IR-7ZTIVM4I.mjs +0 -434
  41. package/dist/fa-IR-LOBAK7VD.mjs +0 -433
  42. package/dist/fr-JUIQDZLO.mjs +0 -411
  43. package/dist/fr-OV4IP3YG.mjs +0 -412
  44. package/dist/he-NLBI7NBV.mjs +0 -489
  45. package/dist/he-S5GGRV7R.mjs +0 -488
  46. package/dist/hr-EROIGR62.mjs +0 -611
  47. package/dist/hr-FDYJ4KGU.mjs +0 -612
  48. package/dist/hu-NWWJ2CK6.mjs +0 -412
  49. package/dist/hu-XW2YVHCK.mjs +0 -411
  50. package/dist/id-53TKE7ZM.mjs +0 -418
  51. package/dist/id-DTWSU2CM.mjs +0 -417
  52. package/dist/is-SBPG5ERH.mjs +0 -425
  53. package/dist/is-WTNKZZWF.mjs +0 -426
  54. package/dist/it-56KOR622.mjs +0 -477
  55. package/dist/it-LCWWUGCM.mjs +0 -476
  56. package/dist/ja-EX772GW3.mjs +0 -439
  57. package/dist/ja-NRDRCGLW.mjs +0 -440
  58. package/dist/ko-HXMYFBIK.mjs +0 -411
  59. package/dist/ko-IJSQPI4Y.mjs +0 -410
  60. package/dist/lt-3CQHQWU4.mjs +0 -561
  61. package/dist/lt-XB5VAB46.mjs +0 -560
  62. package/dist/lv-BB6HCMR5.mjs +0 -600
  63. package/dist/lv-QCJ7CXJE.mjs +0 -599
  64. package/dist/nb-5NSGJNDU.mjs +0 -391
  65. package/dist/nb-SGEZDN7H.mjs +0 -390
  66. package/dist/nl-MOK5HSFQ.mjs +0 -390
  67. package/dist/nl-VKYGAKRW.mjs +0 -391
  68. package/dist/pl-RMRIMLND.mjs +0 -590
  69. package/dist/pl-WKTUYROF.mjs +0 -589
  70. package/dist/pt-BYDKSLFN.mjs +0 -440
  71. package/dist/pt-XATXGSND.mjs +0 -439
  72. package/dist/ro-DUFEXLJ6.mjs +0 -425
  73. package/dist/ro-PWP6CAEL.mjs +0 -426
  74. package/dist/ru-IYXNO3AG.mjs +0 -672
  75. package/dist/ru-ZN3QCPDU.mjs +0 -673
  76. package/dist/sk-DPV2HQKF.mjs +0 -630
  77. package/dist/sk-KESTINRW.mjs +0 -629
  78. package/dist/sl-NPGDHTAC.mjs +0 -714
  79. package/dist/sl-ZFIWVSGK.mjs +0 -715
  80. package/dist/sr-BZ5R6SFL.mjs +0 -600
  81. package/dist/sr-GEFEVWRL.mjs +0 -599
  82. package/dist/sr-Latn-FAHUGH57.mjs +0 -598
  83. package/dist/sr-Latn-FUTTRCPH.mjs +0 -597
  84. package/dist/styles/admin.css +0 -85
  85. package/dist/styles/overrides.css +0 -375
  86. package/dist/styles/themes/brand-dark.css +0 -69
  87. package/dist/styles/themes/brand-light.css +0 -69
  88. package/dist/styles/themes/dark.css +0 -68
  89. package/dist/styles/themes/light.css +0 -68
  90. package/dist/sv-2VABM4W5.mjs +0 -442
  91. package/dist/sv-5VRLD7L3.mjs +0 -441
  92. package/dist/ta-FTX2JPJB.mjs +0 -584
  93. package/dist/ta-MW5MBB7O.mjs +0 -585
  94. package/dist/th-4OMHQZBM.mjs +0 -432
  95. package/dist/th-BDTONIPA.mjs +0 -433
  96. package/dist/tr-6WACY4TC.mjs +0 -444
  97. package/dist/tr-XWXBGB5K.mjs +0 -443
  98. package/dist/uk-36Z6ZYII.mjs +0 -681
  99. package/dist/uk-46V7S742.mjs +0 -682
  100. package/dist/vi-4NKRMD2X.mjs +0 -555
  101. package/dist/vi-IVLSYJLL.mjs +0 -554
  102. package/dist/zh-CN-27B6UU45.mjs +0 -459
  103. package/dist/zh-CN-I2OGDZSI.mjs +0 -460
  104. package/dist/zh-TW-PKL5GABH.mjs +0 -439
  105. package/dist/zh-TW-XU6647SB.mjs +0 -440
@@ -0,0 +1,897 @@
1
+ 'use client';
2
+ "use client";
3
+ import {
4
+ BlockPicker,
5
+ SectionTabs
6
+ } from "./chunk-3SA5V3QM.mjs";
7
+
8
+ // src/components/OrionBlocksFieldImpl.tsx
9
+ import { getTranslation as getTranslation2 } from "@payloadcms/translations";
10
+ import { fieldBaseClass, useDrawerSlug, useModal as useModal2 } from "@payloadcms/ui";
11
+ import { ArrayAction } from "@payloadcms/ui/elements/ArrayAction";
12
+ import { Banner } from "@payloadcms/ui/elements/Banner";
13
+ import { Button } from "@payloadcms/ui/elements/Button";
14
+ import { ClipboardAction } from "@payloadcms/ui/elements/ClipboardAction";
15
+ import { Collapsible } from "@payloadcms/ui/elements/Collapsible";
16
+ import { DraggableSortable } from "@payloadcms/ui/elements/DraggableSortable";
17
+ import { DraggableSortableItem } from "@payloadcms/ui/elements/DraggableSortable/DraggableSortableItem";
18
+ import { DrawerToggler } from "@payloadcms/ui/elements/Drawer";
19
+ import { ErrorPill } from "@payloadcms/ui/elements/ErrorPill";
20
+ import { Pill } from "@payloadcms/ui/elements/Pill";
21
+ import { RenderCustomComponent } from "@payloadcms/ui/elements/RenderCustomComponent";
22
+ import { ShimmerEffect } from "@payloadcms/ui/elements/ShimmerEffect";
23
+ import { useForm, useFormSubmitted } from "@payloadcms/ui/forms/Form";
24
+ import { NullifyLocaleField } from "@payloadcms/ui/forms/NullifyField";
25
+ import { RenderFields } from "@payloadcms/ui/forms/RenderFields";
26
+ import { RowLabel } from "@payloadcms/ui/forms/RowLabel";
27
+ import { useField } from "@payloadcms/ui/forms/useField";
28
+ import { withCondition } from "@payloadcms/ui/forms/withCondition";
29
+ import { FieldDescription } from "@payloadcms/ui/fields/FieldDescription";
30
+ import { FieldError } from "@payloadcms/ui/fields/FieldError";
31
+ import { FieldLabel } from "@payloadcms/ui/fields/FieldLabel";
32
+ import { useThrottledValue } from "@payloadcms/ui/hooks/useThrottledValue";
33
+ import { useConfig } from "@payloadcms/ui/providers/Config";
34
+ import { useDocumentInfo } from "@payloadcms/ui/providers/DocumentInfo";
35
+ import { useLocale } from "@payloadcms/ui/providers/Locale";
36
+ import { useTranslation as useTranslation2 } from "@payloadcms/ui/providers/Translation";
37
+ import { scrollToID } from "@payloadcms/ui/utilities/scrollToID";
38
+ import { Fragment, useCallback, useMemo as useMemo2, useState } from "react";
39
+ import { toast } from "sonner";
40
+
41
+ // src/components/OrionBlocksDrawer.tsx
42
+ import { getTranslation } from "@payloadcms/translations";
43
+ import { Drawer, useModal, useTranslation } from "@payloadcms/ui";
44
+ import { useMemo } from "react";
45
+ import { jsx } from "react/jsx-runtime";
46
+ function normalizeLabel(label, i18n, fallback) {
47
+ if (typeof label === "string" && label.trim().length > 0) {
48
+ return label;
49
+ }
50
+ if (label && typeof label === "object") {
51
+ const translated = getTranslation(label, i18n);
52
+ if (typeof translated === "string" && translated.trim().length > 0) {
53
+ return translated;
54
+ }
55
+ }
56
+ return fallback;
57
+ }
58
+ function getGroupLabel(block, i18n) {
59
+ const group = block.admin?.group;
60
+ return normalizeLabel(group, i18n, "Other");
61
+ }
62
+ function getBlockDescription(block) {
63
+ const custom = block.admin?.custom;
64
+ if (!custom || typeof custom !== "object") {
65
+ return void 0;
66
+ }
67
+ const description = custom.description;
68
+ return typeof description === "string" && description.trim().length > 0 ? description : void 0;
69
+ }
70
+ function OrionBlocksDrawer(props) {
71
+ const { addRow, addRowIndex, blocks, drawerSlug, labels } = props;
72
+ const { closeModal } = useModal();
73
+ const { i18n, t } = useTranslation();
74
+ const groupedBlocks = useMemo(() => {
75
+ const groupMap = /* @__PURE__ */ new Map();
76
+ const allOptions = blocks.map((block) => ({
77
+ slug: block.slug,
78
+ label: normalizeLabel(block.labels?.singular, i18n, block.slug),
79
+ description: getBlockDescription(block),
80
+ imageURL: block.imageURL
81
+ }));
82
+ for (const block of blocks) {
83
+ const groupLabel = getGroupLabel(block, i18n);
84
+ const option = {
85
+ slug: block.slug,
86
+ label: normalizeLabel(block.labels?.singular, i18n, block.slug),
87
+ description: getBlockDescription(block),
88
+ imageURL: block.imageURL
89
+ };
90
+ const existing = groupMap.get(groupLabel);
91
+ if (existing) {
92
+ existing.push(option);
93
+ } else {
94
+ groupMap.set(groupLabel, [option]);
95
+ }
96
+ }
97
+ const groups = [{ label: "All", options: allOptions }];
98
+ const sortedGroupEntries = Array.from(groupMap.entries()).sort(([a], [b]) => a.localeCompare(b));
99
+ for (const [label, options] of sortedGroupEntries) {
100
+ groups.push({ label, options });
101
+ }
102
+ return groups;
103
+ }, [blocks, i18n]);
104
+ return /* @__PURE__ */ jsx(
105
+ Drawer,
106
+ {
107
+ slug: drawerSlug,
108
+ title: t("fields:addLabel", {
109
+ label: normalizeLabel(labels.singular, i18n, "Block")
110
+ }),
111
+ children: /* @__PURE__ */ jsx(
112
+ SectionTabs,
113
+ {
114
+ tabs: groupedBlocks.map((group) => ({
115
+ label: group.label,
116
+ content: /* @__PURE__ */ jsx(
117
+ BlockPicker,
118
+ {
119
+ blocks: group.options,
120
+ onSelect: (slug) => {
121
+ addRow(addRowIndex, slug);
122
+ closeModal(drawerSlug);
123
+ }
124
+ }
125
+ )
126
+ }))
127
+ }
128
+ )
129
+ }
130
+ );
131
+ }
132
+
133
+ // src/components/OrionBlocksFieldImpl.tsx
134
+ import { Fragment as Fragment2, jsx as jsx2, jsxs } from "react/jsx-runtime";
135
+ var baseClass = "blocks-field";
136
+ var localStorageClipboardKey = "_payloadClipboard";
137
+ function reduceFormStateByPath({ formState, path, rowIndex }) {
138
+ const filteredState = {};
139
+ const prefix = typeof rowIndex !== "number" ? path : `${path}.${rowIndex}`;
140
+ for (const key in formState) {
141
+ if (!key.startsWith(prefix)) {
142
+ continue;
143
+ }
144
+ const { customComponents: _customComponents, validate: _validate, ...field } = formState[key];
145
+ if (Array.isArray(field.rows)) {
146
+ field.rows = field.rows.map((row) => {
147
+ if (!row || typeof row !== "object") {
148
+ return row;
149
+ }
150
+ const { customComponents: _rowCustomComponents, ...serializableRow } = row;
151
+ return serializableRow;
152
+ });
153
+ }
154
+ filteredState[key] = field;
155
+ }
156
+ return filteredState;
157
+ }
158
+ function mergeFormStateFromClipboard({ dataFromClipboard, formState, path, rowIndex }) {
159
+ const typeFromClipboard = dataFromClipboard.type;
160
+ const clipboardFields = dataFromClipboard.data;
161
+ const pathFromClipboard = dataFromClipboard.path;
162
+ const rowIndexFromClipboard = dataFromClipboard.rowIndex;
163
+ if (!clipboardFields || !pathFromClipboard || !typeFromClipboard) {
164
+ return formState;
165
+ }
166
+ const copyFromField = typeof rowIndexFromClipboard !== "number";
167
+ const pasteIntoField = typeof rowIndex !== "number";
168
+ const fromRowToField = !copyFromField && pasteIntoField;
169
+ const isArray = typeFromClipboard === "array";
170
+ let pathToReplace;
171
+ if (copyFromField && pasteIntoField) {
172
+ pathToReplace = pathFromClipboard;
173
+ } else if (copyFromField) {
174
+ pathToReplace = `${pathFromClipboard}.${rowIndex}`;
175
+ } else {
176
+ pathToReplace = `${pathFromClipboard}.${rowIndexFromClipboard}`;
177
+ }
178
+ let targetSegment;
179
+ if (!pasteIntoField) {
180
+ targetSegment = `${path}.${rowIndex}`;
181
+ } else if (fromRowToField) {
182
+ targetSegment = `${path}.0`;
183
+ } else {
184
+ targetSegment = path;
185
+ }
186
+ if (fromRowToField) {
187
+ const lastRenderedPath = `${path}.0`;
188
+ const rowIDPath = `${pathToReplace}.id`;
189
+ const rowIDField = clipboardFields[rowIDPath];
190
+ const rowIDFromClipboard = rowIDField?.value;
191
+ const pathField = formState[path];
192
+ const existingRows = Array.isArray(pathField?.rows) ? pathField.rows : [];
193
+ formState[path] = {
194
+ ...pathField,
195
+ rows: [
196
+ {
197
+ ...existingRows.length > 0 && isArray ? existingRows[0] : {},
198
+ id: rowIDFromClipboard,
199
+ isLoading: false,
200
+ lastRenderedPath
201
+ }
202
+ ],
203
+ value: 1,
204
+ initialValue: 1,
205
+ disableFormData: true
206
+ };
207
+ for (const fieldPath in formState) {
208
+ if (fieldPath !== path && !fieldPath.startsWith(lastRenderedPath) && fieldPath.startsWith(path)) {
209
+ delete formState[fieldPath];
210
+ }
211
+ }
212
+ }
213
+ for (const clipboardPath in clipboardFields) {
214
+ if (!pasteIntoField && clipboardPath.endsWith(".id") || !clipboardPath.startsWith(pathToReplace)) {
215
+ continue;
216
+ }
217
+ const newPath = clipboardPath.replace(pathToReplace, targetSegment);
218
+ const existing = formState[newPath];
219
+ formState[newPath] = {
220
+ customComponents: isArray ? existing?.customComponents : void 0,
221
+ validate: isArray ? existing?.validate : void 0,
222
+ ...clipboardFields[clipboardPath]
223
+ };
224
+ }
225
+ return formState;
226
+ }
227
+ function clipboardCopy({ getDataToCopy, payload, t }) {
228
+ try {
229
+ const dataToWrite = {
230
+ data: getDataToCopy(),
231
+ ...payload
232
+ };
233
+ localStorage.setItem(localStorageClipboardKey, JSON.stringify(dataToWrite));
234
+ return true;
235
+ } catch {
236
+ return t("error:unableToCopy");
237
+ }
238
+ }
239
+ function clipboardPaste({ onPaste, schemaBlocks, t }) {
240
+ let dataToPaste;
241
+ try {
242
+ const jsonFromClipboard = localStorage.getItem(localStorageClipboardKey);
243
+ if (!jsonFromClipboard) {
244
+ return t("error:invalidClipboardData");
245
+ }
246
+ dataToPaste = JSON.parse(jsonFromClipboard);
247
+ } catch {
248
+ return t("error:invalidClipboardData");
249
+ }
250
+ if (!dataToPaste || dataToPaste.type !== "blocks" || !dataToPaste.path || !dataToPaste.data) {
251
+ return t("error:invalidClipboardData");
252
+ }
253
+ const allowedSlugs = new Set(schemaBlocks.map((block) => block.slug));
254
+ const clipboardBlocks = Array.isArray(dataToPaste.blocks) ? dataToPaste.blocks : [];
255
+ for (const block of clipboardBlocks) {
256
+ if (!allowedSlugs.has(block.slug)) {
257
+ return t("error:invalidClipboardData");
258
+ }
259
+ }
260
+ onPaste(dataToPaste);
261
+ return true;
262
+ }
263
+ function toggleAllRows(rows, collapsed) {
264
+ const updatedRows = rows.map((row) => ({ ...row, collapsed }));
265
+ const collapsedIDs = collapsed ? updatedRows.map((row) => row.id) : [];
266
+ return { collapsedIDs, updatedRows };
267
+ }
268
+ function extractRowsAndCollapsedIDs(rows, rowID, collapsed) {
269
+ const updatedRows = rows.map((row) => row.id === rowID ? { ...row, collapsed } : row);
270
+ const collapsedIDs = updatedRows.filter((row) => row.collapsed).map((row) => row.id);
271
+ return { collapsedIDs, updatedRows };
272
+ }
273
+ function OrionRowActions(props) {
274
+ const {
275
+ addRow,
276
+ blocks,
277
+ copyRow,
278
+ duplicateRow,
279
+ hasMaxRows,
280
+ isSortable,
281
+ labels,
282
+ moveRow,
283
+ pasteRow,
284
+ removeRow,
285
+ rowCount,
286
+ rowIndex,
287
+ drawerSlug
288
+ } = props;
289
+ const { closeModal, openModal } = useModal2();
290
+ const [indexToAdd, setIndexToAdd] = useState(null);
291
+ const addViaDrawer = useCallback(
292
+ (rowToAdd, rowBlockType) => {
293
+ addRow(rowToAdd, rowBlockType);
294
+ closeModal(drawerSlug);
295
+ },
296
+ [addRow, closeModal, drawerSlug]
297
+ );
298
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
299
+ /* @__PURE__ */ jsx2(
300
+ OrionBlocksDrawer,
301
+ {
302
+ addRow: (_, rowBlockType) => {
303
+ addViaDrawer(indexToAdd ?? rowIndex, rowBlockType);
304
+ },
305
+ addRowIndex: indexToAdd ?? rowIndex,
306
+ blocks,
307
+ drawerSlug,
308
+ labels
309
+ }
310
+ ),
311
+ /* @__PURE__ */ jsx2(
312
+ ArrayAction,
313
+ {
314
+ addRow: (index) => {
315
+ setIndexToAdd(index);
316
+ openModal(drawerSlug);
317
+ },
318
+ copyRow,
319
+ duplicateRow,
320
+ hasMaxRows,
321
+ index: rowIndex,
322
+ isSortable,
323
+ moveRow,
324
+ pasteRow,
325
+ removeRow,
326
+ rowCount
327
+ }
328
+ )
329
+ ] });
330
+ }
331
+ function OrionBlockRow(props) {
332
+ const {
333
+ addRow,
334
+ attributes,
335
+ block,
336
+ blocks,
337
+ copyRow,
338
+ duplicateRow,
339
+ drawerSlug,
340
+ errorCount,
341
+ fields,
342
+ hasMaxRows,
343
+ isLoading: isLoadingFromProps,
344
+ isSortable,
345
+ Label,
346
+ labels,
347
+ listeners,
348
+ moveRow,
349
+ parentPath,
350
+ pasteRow,
351
+ path,
352
+ permissions,
353
+ readOnly,
354
+ removeRow,
355
+ row,
356
+ rowCount,
357
+ rowIndex,
358
+ schemaPath,
359
+ setCollapse,
360
+ setNodeRef,
361
+ transform
362
+ } = props;
363
+ const { i18n } = useTranslation2();
364
+ const hasSubmitted = useFormSubmitted();
365
+ const isLoading = useThrottledValue(Boolean(isLoadingFromProps), 500);
366
+ const fieldHasErrors = hasSubmitted && errorCount > 0;
367
+ let blockPermissions;
368
+ if (permissions === true) {
369
+ blockPermissions = true;
370
+ } else {
371
+ const permissionsBlockSpecific = permissions?.blocks?.[block.slug] ?? permissions?.blocks;
372
+ if (permissionsBlockSpecific === true) {
373
+ blockPermissions = true;
374
+ } else if (permissionsBlockSpecific && typeof permissionsBlockSpecific === "object" && "fields" in permissionsBlockSpecific) {
375
+ blockPermissions = permissionsBlockSpecific.fields;
376
+ } else if (permissions && typeof permissions === "object") {
377
+ const hasReadPermission = permissions.read === true;
378
+ const missingCreateOrUpdate = !permissions.create || !permissions.update;
379
+ const hasRestrictiveStructure = hasReadPermission && (missingCreateOrUpdate || Object.keys(permissions).length === 1 && permissions.read === true);
380
+ if (hasRestrictiveStructure) {
381
+ blockPermissions = { read: true };
382
+ }
383
+ }
384
+ }
385
+ return /* @__PURE__ */ jsx2(
386
+ "div",
387
+ {
388
+ id: `${parentPath.split(".").join("-")}-row-${rowIndex}`,
389
+ ref: setNodeRef,
390
+ style: { transform },
391
+ children: /* @__PURE__ */ jsx2(
392
+ Collapsible,
393
+ {
394
+ actions: !readOnly ? /* @__PURE__ */ jsx2(
395
+ OrionRowActions,
396
+ {
397
+ addRow,
398
+ blocks,
399
+ copyRow,
400
+ drawerSlug,
401
+ duplicateRow,
402
+ hasMaxRows,
403
+ isSortable,
404
+ labels,
405
+ moveRow,
406
+ pasteRow,
407
+ removeRow,
408
+ rowCount,
409
+ rowIndex
410
+ }
411
+ ) : void 0,
412
+ className: [
413
+ `${baseClass}__row`,
414
+ fieldHasErrors ? `${baseClass}__row--has-errors` : `${baseClass}__row--no-errors`
415
+ ].filter(Boolean).join(" "),
416
+ collapsibleStyle: fieldHasErrors ? "error" : "default",
417
+ dragHandleProps: isSortable ? {
418
+ id: row.id,
419
+ attributes,
420
+ listeners
421
+ } : void 0,
422
+ header: isLoading ? /* @__PURE__ */ jsx2(ShimmerEffect, { height: "1rem", width: "8rem" }) : /* @__PURE__ */ jsxs("div", { className: `${baseClass}__block-header`, children: [
423
+ /* @__PURE__ */ jsx2(
424
+ RowLabel,
425
+ {
426
+ CustomComponent: Label,
427
+ label: /* @__PURE__ */ jsxs(Fragment2, { children: [
428
+ /* @__PURE__ */ jsx2("span", { className: `${baseClass}__block-number`, children: String(rowIndex + 1).padStart(2, "0") }),
429
+ /* @__PURE__ */ jsx2(
430
+ Pill,
431
+ {
432
+ className: `${baseClass}__block-pill ${baseClass}__block-pill-${row.blockType}`,
433
+ pillStyle: "white",
434
+ size: "small",
435
+ children: getTranslation2(block.labels?.singular, i18n)
436
+ }
437
+ )
438
+ ] }),
439
+ path,
440
+ rowNumber: rowIndex
441
+ }
442
+ ),
443
+ fieldHasErrors && /* @__PURE__ */ jsx2(ErrorPill, { count: errorCount, i18n, withMessage: true })
444
+ ] }),
445
+ isCollapsed: Boolean(row.collapsed),
446
+ onToggle: (collapsed) => {
447
+ setCollapse(row.id, collapsed);
448
+ },
449
+ children: isLoading ? /* @__PURE__ */ jsx2(ShimmerEffect, {}) : /* @__PURE__ */ jsx2(
450
+ RenderFields,
451
+ {
452
+ className: `${baseClass}__fields`,
453
+ fields,
454
+ margins: "small",
455
+ parentIndexPath: "",
456
+ parentPath: path,
457
+ parentSchemaPath: schemaPath,
458
+ permissions: blockPermissions,
459
+ readOnly
460
+ }
461
+ )
462
+ }
463
+ )
464
+ }
465
+ );
466
+ }
467
+ var OrionBlocksFieldComponent = (props) => {
468
+ const { i18n, t } = useTranslation2();
469
+ const fieldFromProps = props.field;
470
+ const {
471
+ name,
472
+ type,
473
+ admin: { className, description, isSortable = true, style } = {},
474
+ blockReferences,
475
+ blocks,
476
+ label,
477
+ labels: labelsFromProps,
478
+ localized,
479
+ maxRows,
480
+ minRows: minRowsProp,
481
+ required
482
+ } = fieldFromProps;
483
+ const pathFromProps = props.path;
484
+ const permissions = props.permissions;
485
+ const readOnly = Boolean(props.readOnly);
486
+ const schemaPathFromProps = props.schemaPath;
487
+ const validate = props.validate;
488
+ const schemaPath = schemaPathFromProps ?? name;
489
+ const minRows = minRowsProp ?? (required ? 1 : 0);
490
+ const { setDocFieldPreferences } = useDocumentInfo();
491
+ const { addFieldRow, dispatchFields, getFields, moveFieldRow, removeFieldRow, replaceState, setModified } = useForm();
492
+ const { code: locale } = useLocale();
493
+ const {
494
+ config: { localization },
495
+ config
496
+ } = useConfig();
497
+ const drawerSlug = useDrawerSlug("orion-blocks-drawer");
498
+ const submitted = useFormSubmitted();
499
+ const labels = {
500
+ plural: t("fields:blocks"),
501
+ singular: t("fields:block"),
502
+ ...labelsFromProps
503
+ };
504
+ const editingDefaultLocale = (() => {
505
+ if (localization && localization.fallback) {
506
+ const defaultLocale = localization.defaultLocale;
507
+ return locale === defaultLocale;
508
+ }
509
+ return true;
510
+ })();
511
+ const memoizedValidate = useCallback(
512
+ (value2, options) => {
513
+ if (!editingDefaultLocale && value2 === null) {
514
+ return true;
515
+ }
516
+ if (typeof validate === "function") {
517
+ return validate(value2, {
518
+ ...options,
519
+ maxRows,
520
+ minRows,
521
+ required
522
+ });
523
+ }
524
+ return true;
525
+ },
526
+ [editingDefaultLocale, maxRows, minRows, required, validate]
527
+ );
528
+ const {
529
+ blocksFilterOptions,
530
+ customComponents: {
531
+ AfterInput,
532
+ BeforeInput,
533
+ Description,
534
+ Error,
535
+ Label
536
+ } = {},
537
+ disabled,
538
+ errorPaths,
539
+ path,
540
+ rows = [],
541
+ showError,
542
+ valid,
543
+ value
544
+ } = useField({
545
+ hasRows: true,
546
+ potentiallyStalePath: pathFromProps,
547
+ validate: memoizedValidate
548
+ });
549
+ const safePath = path ?? pathFromProps ?? name;
550
+ const { clientBlocks, clientBlocksAfterFilter } = useMemo2(() => {
551
+ const resolvedBlocks = [];
552
+ if (!blockReferences) {
553
+ resolvedBlocks.push(...blocks);
554
+ } else {
555
+ for (const blockReference of blockReferences) {
556
+ const block = typeof blockReference === "string" ? config.blocksMap[blockReference] : blockReference;
557
+ if (block) {
558
+ resolvedBlocks.push(block);
559
+ }
560
+ }
561
+ }
562
+ if (Array.isArray(blocksFilterOptions)) {
563
+ const filteredBlocks = resolvedBlocks.filter((block) => blocksFilterOptions.includes(block.slug));
564
+ return {
565
+ clientBlocks: resolvedBlocks,
566
+ clientBlocksAfterFilter: filteredBlocks
567
+ };
568
+ }
569
+ return {
570
+ clientBlocks: resolvedBlocks,
571
+ clientBlocksAfterFilter: resolvedBlocks
572
+ };
573
+ }, [blockReferences, blocks, blocksFilterOptions, config.blocksMap]);
574
+ const addRow = useCallback(
575
+ (rowIndex, blockType) => {
576
+ addFieldRow({
577
+ blockType,
578
+ path: safePath,
579
+ rowIndex,
580
+ schemaPath
581
+ });
582
+ setTimeout(() => {
583
+ scrollToID(`${safePath}-row-${rowIndex + 1}`);
584
+ }, 0);
585
+ },
586
+ [addFieldRow, safePath, schemaPath]
587
+ );
588
+ const duplicateRow = useCallback(
589
+ (rowIndex) => {
590
+ dispatchFields({
591
+ type: "DUPLICATE_ROW",
592
+ path: safePath,
593
+ rowIndex
594
+ });
595
+ setModified(true);
596
+ setTimeout(() => {
597
+ scrollToID(`${safePath}-row-${rowIndex + 1}`);
598
+ }, 0);
599
+ },
600
+ [dispatchFields, safePath, setModified]
601
+ );
602
+ const removeRow = useCallback(
603
+ (rowIndex) => {
604
+ removeFieldRow({
605
+ path: safePath,
606
+ rowIndex
607
+ });
608
+ },
609
+ [removeFieldRow, safePath]
610
+ );
611
+ const moveRow = useCallback(
612
+ (moveFromIndex, moveToIndex) => {
613
+ moveFieldRow({
614
+ moveFromIndex,
615
+ moveToIndex,
616
+ path: safePath
617
+ });
618
+ },
619
+ [moveFieldRow, safePath]
620
+ );
621
+ const toggleCollapseAll = useCallback(
622
+ (collapsed) => {
623
+ const { collapsedIDs, updatedRows } = toggleAllRows(rows, collapsed);
624
+ dispatchFields({
625
+ type: "SET_ALL_ROWS_COLLAPSED",
626
+ path: safePath,
627
+ updatedRows
628
+ });
629
+ setDocFieldPreferences(safePath, {
630
+ collapsed: collapsedIDs
631
+ });
632
+ },
633
+ [dispatchFields, rows, safePath, setDocFieldPreferences]
634
+ );
635
+ const setCollapse = useCallback(
636
+ (rowID, collapsed) => {
637
+ const { collapsedIDs, updatedRows } = extractRowsAndCollapsedIDs(rows, rowID, collapsed);
638
+ dispatchFields({
639
+ type: "SET_ROW_COLLAPSED",
640
+ path: safePath,
641
+ updatedRows
642
+ });
643
+ setDocFieldPreferences(safePath, {
644
+ collapsed: collapsedIDs
645
+ });
646
+ },
647
+ [dispatchFields, rows, safePath, setDocFieldPreferences]
648
+ );
649
+ const copyRow = useCallback(
650
+ (rowIndex) => {
651
+ const result = clipboardCopy({
652
+ getDataToCopy: () => reduceFormStateByPath({
653
+ formState: getFields(),
654
+ path: safePath,
655
+ rowIndex
656
+ }),
657
+ payload: {
658
+ type,
659
+ blocks: clientBlocks,
660
+ path: safePath,
661
+ rowIndex
662
+ },
663
+ t
664
+ });
665
+ if (typeof result === "string") {
666
+ toast.error(result);
667
+ } else {
668
+ toast.success(t("general:copied"));
669
+ }
670
+ },
671
+ [clientBlocks, getFields, safePath, t, type]
672
+ );
673
+ const pasteRow = useCallback(
674
+ (rowIndex) => {
675
+ const result = clipboardPaste({
676
+ onPaste: (dataFromClipboard) => {
677
+ const formState = getFields();
678
+ const newState = mergeFormStateFromClipboard({
679
+ dataFromClipboard,
680
+ formState,
681
+ path: safePath,
682
+ rowIndex
683
+ });
684
+ replaceState(newState);
685
+ setModified(true);
686
+ },
687
+ schemaBlocks: clientBlocks,
688
+ t
689
+ });
690
+ if (typeof result === "string") {
691
+ toast.error(result);
692
+ }
693
+ },
694
+ [clientBlocks, getFields, replaceState, safePath, setModified, t]
695
+ );
696
+ const pasteBlocks = useCallback(
697
+ (dataFromClipboard) => {
698
+ const formState = getFields();
699
+ const newState = mergeFormStateFromClipboard({
700
+ dataFromClipboard,
701
+ formState,
702
+ path: safePath
703
+ });
704
+ replaceState(newState);
705
+ setModified(true);
706
+ },
707
+ [getFields, replaceState, safePath, setModified]
708
+ );
709
+ const hasMaxRows = Boolean(maxRows && rows.length >= maxRows);
710
+ const fieldErrorCount = errorPaths.length;
711
+ const fieldHasErrors = submitted && fieldErrorCount + (valid ? 0 : 1) > 0;
712
+ const showMinRows = rows.length < minRows || required && rows.length === 0;
713
+ const showRequired = readOnly && rows.length === 0;
714
+ return /* @__PURE__ */ jsxs(
715
+ "div",
716
+ {
717
+ className: [
718
+ fieldBaseClass,
719
+ baseClass,
720
+ className,
721
+ fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`
722
+ ].filter(Boolean).join(" "),
723
+ id: `field-${safePath.replace(/\./g, "__")}`,
724
+ style,
725
+ children: [
726
+ showError && /* @__PURE__ */ jsx2(
727
+ RenderCustomComponent,
728
+ {
729
+ CustomComponent: Error,
730
+ Fallback: /* @__PURE__ */ jsx2(FieldError, { path: safePath, showError })
731
+ }
732
+ ),
733
+ /* @__PURE__ */ jsxs("header", { className: `${baseClass}__header`, children: [
734
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__header-wrap`, children: [
735
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__heading-with-error`, children: [
736
+ /* @__PURE__ */ jsx2("h3", { children: /* @__PURE__ */ jsx2(
737
+ RenderCustomComponent,
738
+ {
739
+ CustomComponent: Label,
740
+ Fallback: /* @__PURE__ */ jsx2(
741
+ FieldLabel,
742
+ {
743
+ as: "span",
744
+ label,
745
+ localized,
746
+ path: safePath,
747
+ required
748
+ }
749
+ )
750
+ }
751
+ ) }),
752
+ fieldHasErrors && fieldErrorCount > 0 && /* @__PURE__ */ jsx2(ErrorPill, { count: fieldErrorCount, i18n, withMessage: true })
753
+ ] }),
754
+ /* @__PURE__ */ jsxs("ul", { className: `${baseClass}__header-actions`, children: [
755
+ rows.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
756
+ /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(
757
+ "button",
758
+ {
759
+ className: `${baseClass}__header-action`,
760
+ onClick: () => toggleCollapseAll(true),
761
+ type: "button",
762
+ children: t("fields:collapseAll")
763
+ }
764
+ ) }),
765
+ /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(
766
+ "button",
767
+ {
768
+ className: `${baseClass}__header-action`,
769
+ onClick: () => toggleCollapseAll(false),
770
+ type: "button",
771
+ children: t("fields:showAll")
772
+ }
773
+ ) })
774
+ ] }),
775
+ /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(
776
+ ClipboardAction,
777
+ {
778
+ allowCopy: rows.length > 0,
779
+ allowPaste: !readOnly,
780
+ blocks: clientBlocks,
781
+ className: `${baseClass}__header-action`,
782
+ disabled,
783
+ getDataToCopy: () => reduceFormStateByPath({
784
+ formState: getFields(),
785
+ path: safePath
786
+ }),
787
+ onPaste: pasteBlocks,
788
+ path: safePath,
789
+ type
790
+ }
791
+ ) })
792
+ ] })
793
+ ] }),
794
+ /* @__PURE__ */ jsx2(
795
+ RenderCustomComponent,
796
+ {
797
+ CustomComponent: Description,
798
+ Fallback: /* @__PURE__ */ jsx2(FieldDescription, { description, path: safePath })
799
+ }
800
+ )
801
+ ] }),
802
+ BeforeInput,
803
+ /* @__PURE__ */ jsx2(NullifyLocaleField, { fieldValue: value, localized, path: safePath, readOnly }),
804
+ (rows.length > 0 || !valid && (showRequired || showMinRows)) && /* @__PURE__ */ jsxs(
805
+ DraggableSortable,
806
+ {
807
+ className: `${baseClass}__rows`,
808
+ ids: rows.map((row) => row.id),
809
+ onDragEnd: ({ moveFromIndex, moveToIndex }) => moveRow(moveFromIndex, moveToIndex),
810
+ children: [
811
+ rows.map((row, index) => {
812
+ const blockType = row.blockType;
813
+ const blockConfig = config.blocksMap[blockType] ?? clientBlocks.find((block) => block.slug === blockType);
814
+ if (!blockConfig) {
815
+ return null;
816
+ }
817
+ const rowPath = `${safePath}.${index}`;
818
+ const rowErrorCount = errorPaths.filter((errorPath) => errorPath.startsWith(`${rowPath}.`)).length;
819
+ return /* @__PURE__ */ jsx2(DraggableSortableItem, { disabled: readOnly || disabled || !isSortable, id: row.id, children: (draggableSortableItemProps) => /* @__PURE__ */ jsx2(
820
+ OrionBlockRow,
821
+ {
822
+ ...draggableSortableItemProps,
823
+ addRow,
824
+ block: blockConfig,
825
+ blocks: clientBlocks,
826
+ copyRow,
827
+ drawerSlug,
828
+ duplicateRow,
829
+ errorCount: rowErrorCount,
830
+ fields: blockConfig.fields,
831
+ hasMaxRows,
832
+ isLoading: Boolean(row.isLoading),
833
+ isSortable,
834
+ Label: rows[index]?.customComponents?.RowLabel,
835
+ labels,
836
+ moveRow,
837
+ parentPath: safePath,
838
+ pasteRow,
839
+ path: rowPath,
840
+ permissions,
841
+ readOnly: readOnly || Boolean(disabled),
842
+ removeRow,
843
+ row,
844
+ rowCount: rows.length,
845
+ rowIndex: index,
846
+ schemaPath: schemaPath + blockConfig.slug,
847
+ setCollapse
848
+ }
849
+ ) }, row.id);
850
+ }),
851
+ !editingDefaultLocale && /* @__PURE__ */ jsxs(Fragment2, { children: [
852
+ showMinRows && /* @__PURE__ */ jsx2(Banner, { type: "error", children: t("validation:requiresAtLeast", {
853
+ count: minRows,
854
+ label: getTranslation2(minRows > 1 ? labels.plural : labels.singular, i18n) || t(minRows > 1 ? "general:row" : "general:rows")
855
+ }) }),
856
+ showRequired && /* @__PURE__ */ jsx2(Banner, { children: t("validation:fieldHasNo", {
857
+ label: getTranslation2(labels.plural, i18n)
858
+ }) })
859
+ ] })
860
+ ]
861
+ }
862
+ ),
863
+ !hasMaxRows && /* @__PURE__ */ jsxs(Fragment, { children: [
864
+ /* @__PURE__ */ jsx2(DrawerToggler, { className: `${baseClass}__drawer-toggler`, disabled: readOnly || disabled, slug: drawerSlug, children: /* @__PURE__ */ jsx2(
865
+ Button,
866
+ {
867
+ buttonStyle: "icon-label",
868
+ disabled: readOnly || disabled,
869
+ el: "span",
870
+ icon: "plus",
871
+ iconPosition: "left",
872
+ iconStyle: "with-border",
873
+ children: t("fields:addLabel", {
874
+ label: getTranslation2(labels.singular, i18n)
875
+ })
876
+ }
877
+ ) }),
878
+ /* @__PURE__ */ jsx2(
879
+ OrionBlocksDrawer,
880
+ {
881
+ addRow,
882
+ addRowIndex: rows.length || 0,
883
+ blocks: clientBlocksAfterFilter,
884
+ drawerSlug,
885
+ labels
886
+ }
887
+ )
888
+ ] }),
889
+ AfterInput
890
+ ]
891
+ }
892
+ );
893
+ };
894
+ var OrionBlocksFieldImpl = withCondition(OrionBlocksFieldComponent);
895
+ export {
896
+ OrionBlocksFieldImpl
897
+ };