@payloadcms/ui 4.0.0-internal.e55ccef → 4.0.0-internal.e7d4ebc

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 (98) hide show
  1. package/dist/css/spacing.css +1 -0
  2. package/dist/elements/ArrayAction/index.d.ts +2 -0
  3. package/dist/elements/ArrayAction/index.d.ts.map +1 -1
  4. package/dist/elements/ArrayAction/index.js +65 -24
  5. package/dist/elements/ArrayAction/index.js.map +1 -1
  6. package/dist/elements/BulkUpload/FileSidebar/index.css +4 -0
  7. package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts +2 -2
  8. package/dist/elements/BulkUpload/FormsManager/createFormData.d.ts.map +1 -1
  9. package/dist/elements/BulkUpload/FormsManager/createFormData.js +4 -15
  10. package/dist/elements/BulkUpload/FormsManager/createFormData.js.map +1 -1
  11. package/dist/elements/BulkUpload/FormsManager/index.d.ts.map +1 -1
  12. package/dist/elements/BulkUpload/FormsManager/index.js +1 -1
  13. package/dist/elements/BulkUpload/FormsManager/index.js.map +1 -1
  14. package/dist/elements/ClipboardAction/clipboardUtilities.d.ts +8 -1
  15. package/dist/elements/ClipboardAction/clipboardUtilities.d.ts.map +1 -1
  16. package/dist/elements/ClipboardAction/clipboardUtilities.js +40 -8
  17. package/dist/elements/ClipboardAction/clipboardUtilities.js.map +1 -1
  18. package/dist/elements/ClipboardAction/clipboardUtilities.spec.js +120 -0
  19. package/dist/elements/ClipboardAction/clipboardUtilities.spec.js.map +1 -0
  20. package/dist/elements/ClipboardAction/index.d.ts.map +1 -1
  21. package/dist/elements/ClipboardAction/index.js +17 -1
  22. package/dist/elements/ClipboardAction/index.js.map +1 -1
  23. package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js +144 -0
  24. package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js.map +1 -0
  25. package/dist/elements/ClipboardAction/types.d.ts +3 -0
  26. package/dist/elements/ClipboardAction/types.d.ts.map +1 -1
  27. package/dist/elements/ClipboardAction/types.js.map +1 -1
  28. package/dist/elements/ClipboardAction/useCanPasteClipboard.d.ts +10 -0
  29. package/dist/elements/ClipboardAction/useCanPasteClipboard.d.ts.map +1 -0
  30. package/dist/elements/ClipboardAction/useCanPasteClipboard.js +21 -0
  31. package/dist/elements/ClipboardAction/useCanPasteClipboard.js.map +1 -0
  32. package/dist/elements/FileManager/FilePreview/index.css +3 -3
  33. package/dist/elements/FileManager/index.css +36 -23
  34. package/dist/elements/FileManager/index.d.ts +1 -1
  35. package/dist/elements/FileManager/index.d.ts.map +1 -1
  36. package/dist/elements/FileManager/index.js +14 -4
  37. package/dist/elements/FileManager/index.js.map +1 -1
  38. package/dist/elements/MiniCarousel/index.css +39 -37
  39. package/dist/elements/ReactSelect/MultiValueLabel/index.css +2 -2
  40. package/dist/elements/RelationshipTable/index.css +0 -2
  41. package/dist/elements/RenderTitle/index.css +4 -0
  42. package/dist/elements/RenderTitle/index.d.ts.map +1 -1
  43. package/dist/elements/RenderTitle/index.js +18 -13
  44. package/dist/elements/RenderTitle/index.js.map +1 -1
  45. package/dist/elements/Table/index.css +1 -0
  46. package/dist/elements/Thumbnail/index.d.ts +1 -1
  47. package/dist/elements/Thumbnail/index.d.ts.map +1 -1
  48. package/dist/elements/Thumbnail/index.js.map +1 -1
  49. package/dist/elements/TimezonePicker/index.d.ts.map +1 -1
  50. package/dist/elements/TimezonePicker/index.js +5 -1
  51. package/dist/elements/TimezonePicker/index.js.map +1 -1
  52. package/dist/fields/Array/ArrayRow.d.ts.map +1 -1
  53. package/dist/fields/Array/ArrayRow.js +97 -160
  54. package/dist/fields/Array/ArrayRow.js.map +1 -1
  55. package/dist/fields/Blocks/BlockRow.d.ts.map +1 -1
  56. package/dist/fields/Blocks/BlockRow.js +134 -195
  57. package/dist/fields/Blocks/BlockRow.js.map +1 -1
  58. package/dist/fields/Blocks/RowActions.d.ts +2 -0
  59. package/dist/fields/Blocks/RowActions.d.ts.map +1 -1
  60. package/dist/fields/Blocks/RowActions.js +23 -20
  61. package/dist/fields/Blocks/RowActions.js.map +1 -1
  62. package/dist/fields/Relationship/select-components/MultiValueLabel/index.css +1 -1
  63. package/dist/fields/Slug/index.d.ts.map +1 -1
  64. package/dist/fields/Slug/index.js +33 -24
  65. package/dist/fields/Slug/index.js.map +1 -1
  66. package/dist/fields/Upload/index.css +19 -4
  67. package/dist/forms/Form/index.d.ts.map +1 -1
  68. package/dist/forms/Form/index.js +3 -14
  69. package/dist/forms/Form/index.js.map +1 -1
  70. package/dist/forms/RenderFields/index.css +16 -2
  71. package/dist/providers/DocumentTitle/index.d.ts +1 -0
  72. package/dist/providers/DocumentTitle/index.d.ts.map +1 -1
  73. package/dist/providers/DocumentTitle/index.js +2 -0
  74. package/dist/providers/DocumentTitle/index.js.map +1 -1
  75. package/dist/providers/TableColumns/buildColumnState/index.d.ts.map +1 -1
  76. package/dist/providers/TableColumns/buildColumnState/index.js +1 -1
  77. package/dist/providers/TableColumns/buildColumnState/index.js.map +1 -1
  78. package/dist/providers/TableColumns/buildColumnState/index.spec.js +40 -0
  79. package/dist/providers/TableColumns/buildColumnState/index.spec.js.map +1 -0
  80. package/dist/providers/UploadHandlers/index.d.ts +2 -7
  81. package/dist/providers/UploadHandlers/index.d.ts.map +1 -1
  82. package/dist/providers/UploadHandlers/index.js +102 -42
  83. package/dist/providers/UploadHandlers/index.js.map +1 -1
  84. package/dist/styles.css +2 -1
  85. package/dist/utilities/handleServerFunctions.d.ts +32 -8
  86. package/dist/utilities/handleServerFunctions.d.ts.map +1 -1
  87. package/dist/utilities/handleServerFunctions.js +17 -37
  88. package/dist/utilities/handleServerFunctions.js.map +1 -1
  89. package/dist/utilities/serverFunctionRegistry.d.ts +12 -7
  90. package/dist/utilities/serverFunctionRegistry.d.ts.map +1 -1
  91. package/dist/utilities/serverFunctionRegistry.js +25 -7
  92. package/dist/utilities/serverFunctionRegistry.js.map +1 -1
  93. package/dist/views/Edit/index.css +61 -53
  94. package/dist/views/Root/index.d.ts +12 -1
  95. package/dist/views/Root/index.d.ts.map +1 -1
  96. package/dist/views/Root/index.js +10 -3
  97. package/dist/views/Root/index.js.map +1 -1
  98. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"clipboardUtilities.js","names":["isClipboardDataValid","localStorageClipboardKey","clipboardCopy","args","getDataToCopy","t","rest","dataToWrite","data","localStorage","setItem","JSON","stringify","_err","clipboardPaste","onPaste","path","fieldPath","dataToPaste","jsonFromClipboard","getItem","parse","dataToValidate"],"sources":["../../../src/elements/ClipboardAction/clipboardUtilities.ts"],"sourcesContent":["import type {\n ClipboardCopyActionArgs,\n ClipboardPasteActionArgs,\n ClipboardPasteActionValidateArgs,\n ClipboardPasteData,\n} from './types.js'\n\nimport { isClipboardDataValid } from './isClipboardDataValid.js'\n\nconst localStorageClipboardKey = '_payloadClipboard'\n\n/**\n * @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport function clipboardCopy(args: ClipboardCopyActionArgs): string | true {\n const { getDataToCopy, t, ...rest } = args\n\n const dataToWrite = {\n data: getDataToCopy(),\n ...rest,\n }\n\n try {\n localStorage.setItem(localStorageClipboardKey, JSON.stringify(dataToWrite))\n return true\n } catch (_err) {\n return t('error:unableToCopy')\n }\n}\n\n/**\n * @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport function clipboardPaste({\n onPaste,\n path: fieldPath,\n t,\n ...args\n}: ClipboardPasteActionArgs): string | true {\n let dataToPaste: ClipboardPasteData\n\n try {\n const jsonFromClipboard = localStorage.getItem(localStorageClipboardKey)\n\n if (!jsonFromClipboard) {\n return t('error:invalidClipboardData')\n }\n\n dataToPaste = JSON.parse(jsonFromClipboard)\n } catch (_err) {\n return t('error:invalidClipboardData')\n }\n\n const dataToValidate = {\n ...dataToPaste,\n ...args,\n fieldPath,\n } as ClipboardPasteActionValidateArgs\n\n if (!isClipboardDataValid(dataToValidate)) {\n return t('error:invalidClipboardData')\n }\n\n onPaste(dataToPaste)\n\n return true\n}\n"],"mappings":"AAOA,SAASA,oBAAoB,QAAQ;AAErC,MAAMC,wBAAA,GAA2B;AAEjC;;;AAGA,OAAO,SAASC,cAAcC,IAA6B;EACzD,MAAM;IAAEC,aAAa;IAAEC,CAAC;IAAE,GAAGC;EAAA,CAAM,GAAGH,IAAA;EAEtC,MAAMI,WAAA,GAAc;IAClBC,IAAA,EAAMJ,aAAA;IACN,GAAGE;EACL;EAEA,IAAI;IACFG,YAAA,CAAaC,OAAO,CAACT,wBAAA,EAA0BU,IAAA,CAAKC,SAAS,CAACL,WAAA;IAC9D,OAAO;EACT,EAAE,OAAOM,IAAA,EAAM;IACb,OAAOR,CAAA,CAAE;EACX;AACF;AAEA;;;AAGA,OAAO,SAASS,eAAe;EAC7BC,OAAO;EACPC,IAAA,EAAMC,SAAS;EACfZ,CAAC;EACD,GAAGF;AAAA,CACsB;EACzB,IAAIe,WAAA;EAEJ,IAAI;IACF,MAAMC,iBAAA,GAAoBV,YAAA,CAAaW,OAAO,CAACnB,wBAAA;IAE/C,IAAI,CAACkB,iBAAA,EAAmB;MACtB,OAAOd,CAAA,CAAE;IACX;IAEAa,WAAA,GAAcP,IAAA,CAAKU,KAAK,CAACF,iBAAA;EAC3B,EAAE,OAAON,IAAA,EAAM;IACb,OAAOR,CAAA,CAAE;EACX;EAEA,MAAMiB,cAAA,GAAiB;IACrB,GAAGJ,WAAW;IACd,GAAGf,IAAI;IACPc;EACF;EAEA,IAAI,CAACjB,oBAAA,CAAqBsB,cAAA,GAAiB;IACzC,OAAOjB,CAAA,CAAE;EACX;EAEAU,OAAA,CAAQG,WAAA;EAER,OAAO;AACT","ignoreList":[]}
1
+ {"version":3,"file":"clipboardUtilities.js","names":["isClipboardDataValid","localStorageClipboardKey","readClipboardData","jsonFromClipboard","localStorage","getItem","JSON","parse","_err","canPasteClipboardData","args","dataToPaste","path","schemaArgs","dataToValidate","fieldPath","clipboardCopy","getDataToCopy","t","rest","dataToWrite","data","setItem","stringify","clipboardPaste","onPaste"],"sources":["../../../src/elements/ClipboardAction/clipboardUtilities.ts"],"sourcesContent":["import type {\n ClipboardCopyActionArgs,\n ClipboardPasteActionArgs,\n ClipboardPasteActionValidateArgs,\n ClipboardPasteData,\n ClipboardPasteEligibilityArgs,\n} from './types.js'\n\nimport { isClipboardDataValid } from './isClipboardDataValid.js'\n\nconst localStorageClipboardKey = '_payloadClipboard'\n\n/**\n * Reads and parses the clipboard data from localStorage.\n *\n * @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nfunction readClipboardData(): ClipboardPasteData | null {\n try {\n const jsonFromClipboard = localStorage.getItem(localStorageClipboardKey)\n\n if (!jsonFromClipboard) {\n return null\n }\n\n return JSON.parse(jsonFromClipboard)\n } catch (_err) {\n return null\n }\n}\n\n/**\n * Whether the clipboard contents can be pasted into the target field.\n *\n * Returns `false` when the clipboard is empty or its schema is incompatible\n * with the target. Used to disable paste actions when they would fail.\n */\nexport function canPasteClipboardData(args: ClipboardPasteEligibilityArgs): boolean {\n const dataToPaste = readClipboardData()\n\n if (!dataToPaste) {\n return false\n }\n\n const { path, ...schemaArgs } = args\n\n const dataToValidate = {\n ...dataToPaste,\n ...schemaArgs,\n fieldPath: path,\n } as ClipboardPasteActionValidateArgs\n\n return isClipboardDataValid(dataToValidate)\n}\n\n/**\n * @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport function clipboardCopy(args: ClipboardCopyActionArgs): string | true {\n const { getDataToCopy, t, ...rest } = args\n\n const dataToWrite = {\n data: getDataToCopy(),\n ...rest,\n }\n\n try {\n localStorage.setItem(localStorageClipboardKey, JSON.stringify(dataToWrite))\n return true\n } catch (_err) {\n return t('error:unableToCopy')\n }\n}\n\n/**\n * @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport function clipboardPaste({\n onPaste,\n path: fieldPath,\n t,\n ...args\n}: ClipboardPasteActionArgs): string | true {\n const dataToPaste = readClipboardData()\n\n if (!dataToPaste) {\n return t('error:invalidClipboardData')\n }\n\n const dataToValidate = {\n ...dataToPaste,\n ...args,\n fieldPath,\n } as ClipboardPasteActionValidateArgs\n\n if (!isClipboardDataValid(dataToValidate)) {\n return t('error:invalidClipboardData')\n }\n\n onPaste(dataToPaste)\n\n return true\n}\n"],"mappings":"AAQA,SAASA,oBAAoB,QAAQ;AAErC,MAAMC,wBAAA,GAA2B;AAEjC;;;;;AAKA,SAASC,kBAAA;EACP,IAAI;IACF,MAAMC,iBAAA,GAAoBC,YAAA,CAAaC,OAAO,CAACJ,wBAAA;IAE/C,IAAI,CAACE,iBAAA,EAAmB;MACtB,OAAO;IACT;IAEA,OAAOG,IAAA,CAAKC,KAAK,CAACJ,iBAAA;EACpB,EAAE,OAAOK,IAAA,EAAM;IACb,OAAO;EACT;AACF;AAEA;;;;;;AAMA,OAAO,SAASC,sBAAsBC,IAAmC;EACvE,MAAMC,WAAA,GAAcT,iBAAA;EAEpB,IAAI,CAACS,WAAA,EAAa;IAChB,OAAO;EACT;EAEA,MAAM;IAAEC,IAAI;IAAE,GAAGC;EAAA,CAAY,GAAGH,IAAA;EAEhC,MAAMI,cAAA,GAAiB;IACrB,GAAGH,WAAW;IACd,GAAGE,UAAU;IACbE,SAAA,EAAWH;EACb;EAEA,OAAOZ,oBAAA,CAAqBc,cAAA;AAC9B;AAEA;;;AAGA,OAAO,SAASE,cAAcN,IAA6B;EACzD,MAAM;IAAEO,aAAa;IAAEC,CAAC;IAAE,GAAGC;EAAA,CAAM,GAAGT,IAAA;EAEtC,MAAMU,WAAA,GAAc;IAClBC,IAAA,EAAMJ,aAAA;IACN,GAAGE;EACL;EAEA,IAAI;IACFf,YAAA,CAAakB,OAAO,CAACrB,wBAAA,EAA0BK,IAAA,CAAKiB,SAAS,CAACH,WAAA;IAC9D,OAAO;EACT,EAAE,OAAOZ,IAAA,EAAM;IACb,OAAOU,CAAA,CAAE;EACX;AACF;AAEA;;;AAGA,OAAO,SAASM,eAAe;EAC7BC,OAAO;EACPb,IAAA,EAAMG,SAAS;EACfG,CAAC;EACD,GAAGR;AAAA,CACsB;EACzB,MAAMC,WAAA,GAAcT,iBAAA;EAEpB,IAAI,CAACS,WAAA,EAAa;IAChB,OAAOO,CAAA,CAAE;EACX;EAEA,MAAMJ,cAAA,GAAiB;IACrB,GAAGH,WAAW;IACd,GAAGD,IAAI;IACPK;EACF;EAEA,IAAI,CAACf,oBAAA,CAAqBc,cAAA,GAAiB;IACzC,OAAOI,CAAA,CAAE;EACX;EAEAO,OAAA,CAAQd,WAAA;EAER,OAAO;AACT","ignoreList":[]}
@@ -0,0 +1,120 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { canPasteClipboardData } from './clipboardUtilities.js';
3
+ const localStorageClipboardKey = '_payloadClipboard';
4
+ const textField = {
5
+ name: 'text',
6
+ type: 'text'
7
+ };
8
+ const numberField = {
9
+ name: 'num',
10
+ type: 'number'
11
+ };
12
+ const ctaBlock = {
13
+ slug: 'cta',
14
+ fields: [textField]
15
+ };
16
+ const otherBlock = {
17
+ slug: 'other',
18
+ fields: [numberField]
19
+ };
20
+ const arrayClipboard = {
21
+ type: 'array',
22
+ data: {
23
+ 'items.0.text': {
24
+ valid: true,
25
+ value: 'hi'
26
+ }
27
+ },
28
+ fields: [textField],
29
+ path: 'items',
30
+ rowIndex: 0
31
+ };
32
+ const blocksClipboard = {
33
+ type: 'blocks',
34
+ blocks: [ctaBlock],
35
+ data: {
36
+ 'layout.0.blockType': {
37
+ valid: true,
38
+ value: 'cta'
39
+ }
40
+ },
41
+ path: 'layout',
42
+ rowIndex: 0
43
+ };
44
+ class LocalStorageMock {
45
+ store = {};
46
+ clear() {
47
+ this.store = {};
48
+ }
49
+ getItem(key) {
50
+ return key in this.store ? this.store[key] : null;
51
+ }
52
+ removeItem(key) {
53
+ delete this.store[key];
54
+ }
55
+ setItem(key, value) {
56
+ this.store[key] = String(value);
57
+ }
58
+ }
59
+ describe('canPasteClipboardData', () => {
60
+ let localStorageMock;
61
+ beforeEach(() => {
62
+ localStorageMock = new LocalStorageMock();
63
+ vi.stubGlobal('localStorage', localStorageMock);
64
+ });
65
+ afterEach(() => {
66
+ vi.unstubAllGlobals();
67
+ });
68
+ const writeClipboard = data => {
69
+ localStorageMock.setItem(localStorageClipboardKey, JSON.stringify(data));
70
+ };
71
+ it('should return false when the clipboard is empty', () => {
72
+ expect(canPasteClipboardData({
73
+ path: 'items',
74
+ schemaFields: [textField]
75
+ })).toBe(false);
76
+ });
77
+ it('should return false when the clipboard contains invalid JSON', () => {
78
+ localStorageMock.setItem(localStorageClipboardKey, 'not-json');
79
+ expect(canPasteClipboardData({
80
+ path: 'items',
81
+ schemaFields: [textField]
82
+ })).toBe(false);
83
+ });
84
+ it('should return true for an array field with a matching schema', () => {
85
+ writeClipboard(arrayClipboard);
86
+ expect(canPasteClipboardData({
87
+ path: 'items',
88
+ schemaFields: [textField]
89
+ })).toBe(true);
90
+ });
91
+ it('should return false for an array field with an incompatible schema', () => {
92
+ writeClipboard(arrayClipboard);
93
+ expect(canPasteClipboardData({
94
+ path: 'items',
95
+ schemaFields: [numberField]
96
+ })).toBe(false);
97
+ });
98
+ it('should return true for a blocks field with a matching schema', () => {
99
+ writeClipboard(blocksClipboard);
100
+ expect(canPasteClipboardData({
101
+ path: 'layout',
102
+ schemaBlocks: [ctaBlock]
103
+ })).toBe(true);
104
+ });
105
+ it('should return false for a blocks field with an incompatible schema', () => {
106
+ writeClipboard(blocksClipboard);
107
+ expect(canPasteClipboardData({
108
+ path: 'layout',
109
+ schemaBlocks: [otherBlock]
110
+ })).toBe(false);
111
+ });
112
+ it('should return false when pasting array data into a blocks field', () => {
113
+ writeClipboard(arrayClipboard);
114
+ expect(canPasteClipboardData({
115
+ path: 'layout',
116
+ schemaBlocks: [ctaBlock]
117
+ })).toBe(false);
118
+ });
119
+ });
120
+ //# sourceMappingURL=clipboardUtilities.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboardUtilities.spec.js","names":["afterEach","beforeEach","describe","expect","it","vi","canPasteClipboardData","localStorageClipboardKey","textField","name","type","numberField","ctaBlock","slug","fields","otherBlock","arrayClipboard","data","valid","value","path","rowIndex","blocksClipboard","blocks","LocalStorageMock","store","clear","getItem","key","removeItem","setItem","String","localStorageMock","stubGlobal","unstubAllGlobals","writeClipboard","JSON","stringify","schemaFields","toBe","schemaBlocks"],"sources":["../../../src/elements/ClipboardAction/clipboardUtilities.spec.ts"],"sourcesContent":["import type { ClientBlock, ClientField } from 'payload'\n\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport type { ClipboardPasteData } from './types.js'\n\nimport { canPasteClipboardData } from './clipboardUtilities.js'\n\nconst localStorageClipboardKey = '_payloadClipboard'\n\nconst textField = { name: 'text', type: 'text' } as ClientField\nconst numberField = { name: 'num', type: 'number' } as ClientField\n\nconst ctaBlock = { slug: 'cta', fields: [textField] } as ClientBlock\nconst otherBlock = { slug: 'other', fields: [numberField] } as ClientBlock\n\nconst arrayClipboard: ClipboardPasteData = {\n type: 'array',\n data: { 'items.0.text': { valid: true, value: 'hi' } },\n fields: [textField],\n path: 'items',\n rowIndex: 0,\n}\n\nconst blocksClipboard: ClipboardPasteData = {\n type: 'blocks',\n blocks: [ctaBlock],\n data: { 'layout.0.blockType': { valid: true, value: 'cta' } },\n path: 'layout',\n rowIndex: 0,\n}\n\nclass LocalStorageMock {\n private store: Record<string, string> = {}\n\n clear() {\n this.store = {}\n }\n\n getItem(key: string): null | string {\n return key in this.store ? this.store[key] : null\n }\n\n removeItem(key: string) {\n delete this.store[key]\n }\n\n setItem(key: string, value: string) {\n this.store[key] = String(value)\n }\n}\n\ndescribe('canPasteClipboardData', () => {\n let localStorageMock: LocalStorageMock\n\n beforeEach(() => {\n localStorageMock = new LocalStorageMock()\n vi.stubGlobal('localStorage', localStorageMock)\n })\n\n afterEach(() => {\n vi.unstubAllGlobals()\n })\n\n const writeClipboard = (data: ClipboardPasteData) => {\n localStorageMock.setItem(localStorageClipboardKey, JSON.stringify(data))\n }\n\n it('should return false when the clipboard is empty', () => {\n expect(canPasteClipboardData({ path: 'items', schemaFields: [textField] })).toBe(false)\n })\n\n it('should return false when the clipboard contains invalid JSON', () => {\n localStorageMock.setItem(localStorageClipboardKey, 'not-json')\n\n expect(canPasteClipboardData({ path: 'items', schemaFields: [textField] })).toBe(false)\n })\n\n it('should return true for an array field with a matching schema', () => {\n writeClipboard(arrayClipboard)\n\n expect(canPasteClipboardData({ path: 'items', schemaFields: [textField] })).toBe(true)\n })\n\n it('should return false for an array field with an incompatible schema', () => {\n writeClipboard(arrayClipboard)\n\n expect(canPasteClipboardData({ path: 'items', schemaFields: [numberField] })).toBe(false)\n })\n\n it('should return true for a blocks field with a matching schema', () => {\n writeClipboard(blocksClipboard)\n\n expect(canPasteClipboardData({ path: 'layout', schemaBlocks: [ctaBlock] })).toBe(true)\n })\n\n it('should return false for a blocks field with an incompatible schema', () => {\n writeClipboard(blocksClipboard)\n\n expect(canPasteClipboardData({ path: 'layout', schemaBlocks: [otherBlock] })).toBe(false)\n })\n\n it('should return false when pasting array data into a blocks field', () => {\n writeClipboard(arrayClipboard)\n\n expect(canPasteClipboardData({ path: 'layout', schemaBlocks: [ctaBlock] })).toBe(false)\n })\n})\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,EAAe,MAAM,OAAO,CAAA;AAG5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAQ9D,OAAO,aAAa,CAAA;AAIpB,KAAK,KAAK,GAAG;IACX,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,EAAE,MAAM,0BAA0B,CAAA;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,iBAAiB,CAAA;AAErB;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,KAAK,CA8FrC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,EAAe,MAAM,OAAO,CAAA;AAG5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAS9D,OAAO,aAAa,CAAA;AAIpB,KAAK,KAAK,GAAG;IACX,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,EAAE,MAAM,0BAA0B,CAAA;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,iBAAiB,CAAA;AAErB;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,KAAK,CAyGrC,CAAA"}
@@ -9,6 +9,7 @@ import { MoreIcon } from '../../icons/More/index.js';
9
9
  import { useTranslation } from '../../providers/Translation/index.js';
10
10
  import { Popup, PopupList } from '../Popup/index.js';
11
11
  import { clipboardCopy, clipboardPaste } from './clipboardUtilities.js';
12
+ import { useCanPasteClipboard } from './useCanPasteClipboard.js';
12
13
  import './index.css';
13
14
  const baseClass = 'clipboard-action';
14
15
  /**
@@ -30,6 +31,16 @@ export const ClipboardAction = ({
30
31
  const {
31
32
  t
32
33
  } = useTranslation();
34
+ const {
35
+ canPaste,
36
+ refresh
37
+ } = useCanPasteClipboard(rest.type === 'array' ? {
38
+ path,
39
+ schemaFields: rest.fields
40
+ } : {
41
+ path,
42
+ schemaBlocks: rest.blocks
43
+ });
33
44
  const classes = [`${baseClass}__popup`, className].filter(Boolean).join(' ');
34
45
  const handleCopy = useCallback(() => {
35
46
  const clipboardResult = clipboardCopy({
@@ -70,6 +81,11 @@ export const ClipboardAction = ({
70
81
  className: classes,
71
82
  disabled: disabled,
72
83
  horizontalAlign: "right",
84
+ onToggleOpen: active => {
85
+ if (active) {
86
+ refresh();
87
+ }
88
+ },
73
89
  render: ({
74
90
  close
75
91
  }) => /*#__PURE__*/_jsxs(PopupList.MenuItem, {
@@ -86,7 +102,7 @@ export const ClipboardAction = ({
86
102
  children: isRow ? t('general:copyRow') : t('general:copyField')
87
103
  }), /*#__PURE__*/_jsx(PopupList.Button, {
88
104
  className: pasteClassName,
89
- disabled: !allowPaste,
105
+ disabled: !allowPaste || !canPaste,
90
106
  icon: /*#__PURE__*/_jsx(ClipboardIcon, {}),
91
107
  onClick: () => {
92
108
  void handlePaste();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useCallback","toast","ClipboardIcon","CopyIcon","MoreIcon","useTranslation","Popup","PopupList","clipboardCopy","clipboardPaste","baseClass","ClipboardAction","allowCopy","allowPaste","className","copyClassName","disabled","isRow","onPaste","pasteClassName","path","rest","t","classes","filter","Boolean","join","handleCopy","clipboardResult","error","success","handlePaste","type","schemaFields","fields","schemaBlocks","blocks","_jsx","button","buttonAriaLabel","buttonClassName","caret","horizontalAlign","render","close","_jsxs","MenuItem","Button","icon","size","onClick","verticalAlign"],"sources":["../../../src/elements/ClipboardAction/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FormStateWithoutComponents } from 'payload'\n\nimport { type FC, useCallback } from 'react'\nimport { toast } from 'sonner'\n\nimport type { ClipboardCopyData, OnPasteFn } from './types.js'\n\nimport { ClipboardIcon } from '../../icons/Clipboard/index.js'\nimport { CopyIcon } from '../../icons/Copy/index.js'\nimport { MoreIcon } from '../../icons/More/index.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { Popup, PopupList } from '../Popup/index.js'\nimport { clipboardCopy, clipboardPaste } from './clipboardUtilities.js'\nimport './index.css'\n\nconst baseClass = 'clipboard-action'\n\ntype Props = {\n allowCopy?: boolean\n allowPaste?: boolean\n className?: string\n copyClassName?: string\n disabled?: boolean\n getDataToCopy: () => FormStateWithoutComponents\n isRow?: boolean\n onPaste: OnPasteFn\n pasteClassName?: string\n} & ClipboardCopyData\n\n/**\n * Menu actions for copying and pasting fields. Currently, this is only used in Arrays and Blocks.\n * @note This component doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport const ClipboardAction: FC<Props> = ({\n allowCopy,\n allowPaste,\n className,\n copyClassName,\n disabled,\n isRow,\n onPaste,\n pasteClassName,\n path,\n ...rest\n}) => {\n const { t } = useTranslation()\n\n const classes = [`${baseClass}__popup`, className].filter(Boolean).join(' ')\n\n const handleCopy = useCallback(() => {\n const clipboardResult = clipboardCopy({\n path,\n t,\n ...rest,\n })\n\n if (typeof clipboardResult === 'string') {\n toast.error(clipboardResult)\n } else {\n toast.success(t('general:copied'))\n }\n }, [t, rest, path])\n\n const handlePaste = useCallback(() => {\n const clipboardResult = clipboardPaste(\n rest.type === 'array'\n ? {\n onPaste,\n path,\n schemaFields: rest.fields,\n t,\n }\n : {\n onPaste,\n path,\n schemaBlocks: rest.blocks,\n t,\n },\n )\n\n if (typeof clipboardResult === 'string') {\n toast.error(clipboardResult)\n }\n }, [onPaste, rest, path, t])\n\n if (!allowPaste && !allowCopy) {\n return null\n }\n\n return (\n <Popup\n button={<MoreIcon />}\n buttonAriaLabel={t('general:moreOptions')}\n buttonClassName={`${baseClass}__button`}\n caret={false}\n className={classes}\n disabled={disabled}\n horizontalAlign=\"right\"\n render={({ close }) => (\n <PopupList.MenuItem>\n <PopupList.Button\n className={copyClassName}\n disabled={!allowCopy}\n icon={<CopyIcon size={24} />}\n onClick={() => {\n void handleCopy()\n close()\n }}\n >\n {isRow ? t('general:copyRow') : t('general:copyField')}\n </PopupList.Button>\n <PopupList.Button\n className={pasteClassName}\n disabled={!allowPaste}\n icon={<ClipboardIcon />}\n onClick={() => {\n void handlePaste()\n close()\n }}\n >\n {isRow ? t('general:pasteRow') : t('general:pasteField')}\n </PopupList.Button>\n </PopupList.MenuItem>\n )}\n verticalAlign=\"bottom\"\n />\n )\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useCallback","toast","ClipboardIcon","CopyIcon","MoreIcon","useTranslation","Popup","PopupList","clipboardCopy","clipboardPaste","useCanPasteClipboard","baseClass","ClipboardAction","allowCopy","allowPaste","className","copyClassName","disabled","isRow","onPaste","pasteClassName","path","rest","t","canPaste","refresh","type","schemaFields","fields","schemaBlocks","blocks","classes","filter","Boolean","join","handleCopy","clipboardResult","error","success","handlePaste","_jsx","button","buttonAriaLabel","buttonClassName","caret","horizontalAlign","onToggleOpen","active","render","close","_jsxs","MenuItem","Button","icon","size","onClick","verticalAlign"],"sources":["../../../src/elements/ClipboardAction/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FormStateWithoutComponents } from 'payload'\n\nimport { type FC, useCallback } from 'react'\nimport { toast } from 'sonner'\n\nimport type { ClipboardCopyData, OnPasteFn } from './types.js'\n\nimport { ClipboardIcon } from '../../icons/Clipboard/index.js'\nimport { CopyIcon } from '../../icons/Copy/index.js'\nimport { MoreIcon } from '../../icons/More/index.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { Popup, PopupList } from '../Popup/index.js'\nimport { clipboardCopy, clipboardPaste } from './clipboardUtilities.js'\nimport { useCanPasteClipboard } from './useCanPasteClipboard.js'\nimport './index.css'\n\nconst baseClass = 'clipboard-action'\n\ntype Props = {\n allowCopy?: boolean\n allowPaste?: boolean\n className?: string\n copyClassName?: string\n disabled?: boolean\n getDataToCopy: () => FormStateWithoutComponents\n isRow?: boolean\n onPaste: OnPasteFn\n pasteClassName?: string\n} & ClipboardCopyData\n\n/**\n * Menu actions for copying and pasting fields. Currently, this is only used in Arrays and Blocks.\n * @note This component doesn't use the Clipboard API, but localStorage. See rationale in #11513\n */\nexport const ClipboardAction: FC<Props> = ({\n allowCopy,\n allowPaste,\n className,\n copyClassName,\n disabled,\n isRow,\n onPaste,\n pasteClassName,\n path,\n ...rest\n}) => {\n const { t } = useTranslation()\n\n const { canPaste, refresh } = useCanPasteClipboard(\n rest.type === 'array'\n ? { path, schemaFields: rest.fields }\n : { path, schemaBlocks: rest.blocks },\n )\n\n const classes = [`${baseClass}__popup`, className].filter(Boolean).join(' ')\n\n const handleCopy = useCallback(() => {\n const clipboardResult = clipboardCopy({\n path,\n t,\n ...rest,\n })\n\n if (typeof clipboardResult === 'string') {\n toast.error(clipboardResult)\n } else {\n toast.success(t('general:copied'))\n }\n }, [t, rest, path])\n\n const handlePaste = useCallback(() => {\n const clipboardResult = clipboardPaste(\n rest.type === 'array'\n ? {\n onPaste,\n path,\n schemaFields: rest.fields,\n t,\n }\n : {\n onPaste,\n path,\n schemaBlocks: rest.blocks,\n t,\n },\n )\n\n if (typeof clipboardResult === 'string') {\n toast.error(clipboardResult)\n }\n }, [onPaste, rest, path, t])\n\n if (!allowPaste && !allowCopy) {\n return null\n }\n\n return (\n <Popup\n button={<MoreIcon />}\n buttonAriaLabel={t('general:moreOptions')}\n buttonClassName={`${baseClass}__button`}\n caret={false}\n className={classes}\n disabled={disabled}\n horizontalAlign=\"right\"\n onToggleOpen={(active) => {\n if (active) {\n refresh()\n }\n }}\n render={({ close }) => (\n <PopupList.MenuItem>\n <PopupList.Button\n className={copyClassName}\n disabled={!allowCopy}\n icon={<CopyIcon size={24} />}\n onClick={() => {\n void handleCopy()\n close()\n }}\n >\n {isRow ? t('general:copyRow') : t('general:copyField')}\n </PopupList.Button>\n <PopupList.Button\n className={pasteClassName}\n disabled={!allowPaste || !canPaste}\n icon={<ClipboardIcon />}\n onClick={() => {\n void handlePaste()\n close()\n }}\n >\n {isRow ? t('general:pasteRow') : t('general:pasteField')}\n </PopupList.Button>\n </PopupList.MenuItem>\n )}\n verticalAlign=\"bottom\"\n />\n )\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,144 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { isClipboardDataValid } from './isClipboardDataValid.js';
3
+ const textField = {
4
+ name: 'text',
5
+ type: 'text'
6
+ };
7
+ const numberField = {
8
+ name: 'num',
9
+ type: 'number'
10
+ };
11
+ const renamedTextField = {
12
+ name: 'title',
13
+ type: 'text'
14
+ };
15
+ const subArrayField = {
16
+ name: 'sub',
17
+ type: 'array',
18
+ fields: [textField]
19
+ };
20
+ const subArrayFieldMismatch = {
21
+ name: 'sub',
22
+ type: 'array',
23
+ fields: [numberField]
24
+ };
25
+ const ctaBlock = {
26
+ slug: 'cta',
27
+ fields: [textField]
28
+ };
29
+ const otherBlock = {
30
+ slug: 'other',
31
+ fields: [numberField]
32
+ };
33
+ const baseData = {
34
+ 'items.0.text': {
35
+ valid: true,
36
+ value: 'hi'
37
+ }
38
+ };
39
+ const buildArrayArgs = ({
40
+ fields,
41
+ schemaFields,
42
+ ...overrides
43
+ }) => ({
44
+ type: 'array',
45
+ data: baseData,
46
+ fieldPath: 'items',
47
+ fields,
48
+ path: 'items',
49
+ rowIndex: 0,
50
+ schemaFields,
51
+ ...overrides
52
+ });
53
+ const buildBlocksArgs = ({
54
+ blocks,
55
+ schemaBlocks
56
+ }) => ({
57
+ type: 'blocks',
58
+ blocks,
59
+ data: {
60
+ 'layout.0.blockType': {
61
+ valid: true,
62
+ value: 'cta'
63
+ }
64
+ },
65
+ fieldPath: 'layout',
66
+ path: 'layout',
67
+ rowIndex: 0,
68
+ schemaBlocks
69
+ });
70
+ describe('isClipboardDataValid', () => {
71
+ it('should return false when data is undefined', () => {
72
+ expect(isClipboardDataValid(buildArrayArgs({
73
+ data: undefined,
74
+ fields: [textField],
75
+ schemaFields: [textField]
76
+ }))).toBe(false);
77
+ });
78
+ it('should return false when path is missing', () => {
79
+ expect(isClipboardDataValid(buildArrayArgs({
80
+ fields: [textField],
81
+ path: '',
82
+ schemaFields: [textField]
83
+ }))).toBe(false);
84
+ });
85
+ describe('array fields', () => {
86
+ it('should return true for a matching schema', () => {
87
+ expect(isClipboardDataValid(buildArrayArgs({
88
+ fields: [textField],
89
+ schemaFields: [textField]
90
+ }))).toBe(true);
91
+ });
92
+ it('should return false when field types differ', () => {
93
+ expect(isClipboardDataValid(buildArrayArgs({
94
+ fields: [textField],
95
+ schemaFields: [numberField]
96
+ }))).toBe(false);
97
+ });
98
+ it('should return false when field names differ', () => {
99
+ expect(isClipboardDataValid(buildArrayArgs({
100
+ fields: [textField],
101
+ schemaFields: [renamedTextField]
102
+ }))).toBe(false);
103
+ });
104
+ it('should return false when field counts differ', () => {
105
+ expect(isClipboardDataValid(buildArrayArgs({
106
+ fields: [textField],
107
+ schemaFields: [textField, numberField]
108
+ }))).toBe(false);
109
+ });
110
+ it('should return true for matching nested sub-fields', () => {
111
+ expect(isClipboardDataValid(buildArrayArgs({
112
+ fields: [subArrayField],
113
+ schemaFields: [subArrayField]
114
+ }))).toBe(true);
115
+ });
116
+ it('should return false for mismatching nested sub-fields', () => {
117
+ expect(isClipboardDataValid(buildArrayArgs({
118
+ fields: [subArrayField],
119
+ schemaFields: [subArrayFieldMismatch]
120
+ }))).toBe(false);
121
+ });
122
+ });
123
+ describe('blocks fields', () => {
124
+ it('should return true for a matching block schema', () => {
125
+ expect(isClipboardDataValid(buildBlocksArgs({
126
+ blocks: [ctaBlock],
127
+ schemaBlocks: [ctaBlock]
128
+ }))).toBe(true);
129
+ });
130
+ it('should return false when a copied block slug is not in the target config', () => {
131
+ expect(isClipboardDataValid(buildBlocksArgs({
132
+ blocks: [ctaBlock],
133
+ schemaBlocks: [otherBlock]
134
+ }))).toBe(false);
135
+ });
136
+ it('should return false when the target has no blocks configured', () => {
137
+ expect(isClipboardDataValid(buildBlocksArgs({
138
+ blocks: [ctaBlock],
139
+ schemaBlocks: []
140
+ }))).toBe(false);
141
+ });
142
+ });
143
+ });
144
+ //# sourceMappingURL=isClipboardDataValid.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isClipboardDataValid.spec.js","names":["describe","expect","it","isClipboardDataValid","textField","name","type","numberField","renamedTextField","subArrayField","fields","subArrayFieldMismatch","ctaBlock","slug","otherBlock","baseData","valid","value","buildArrayArgs","schemaFields","overrides","data","fieldPath","path","rowIndex","buildBlocksArgs","blocks","schemaBlocks","undefined","toBe"],"sources":["../../../src/elements/ClipboardAction/isClipboardDataValid.spec.ts"],"sourcesContent":["import type { ClientBlock, ClientField } from 'payload'\n\nimport { describe, expect, it } from 'vitest'\n\nimport type { ClipboardPasteActionValidateArgs, ClipboardPasteData } from './types.js'\n\nimport { isClipboardDataValid } from './isClipboardDataValid.js'\n\nconst textField = { name: 'text', type: 'text' } as ClientField\nconst numberField = { name: 'num', type: 'number' } as ClientField\nconst renamedTextField = { name: 'title', type: 'text' } as ClientField\n\nconst subArrayField = { name: 'sub', type: 'array', fields: [textField] } as ClientField\nconst subArrayFieldMismatch = { name: 'sub', type: 'array', fields: [numberField] } as ClientField\n\nconst ctaBlock = { slug: 'cta', fields: [textField] } as ClientBlock\nconst otherBlock = { slug: 'other', fields: [numberField] } as ClientBlock\n\nconst baseData: ClipboardPasteData['data'] = { 'items.0.text': { valid: true, value: 'hi' } }\n\nconst buildArrayArgs = ({\n fields,\n schemaFields,\n ...overrides\n}: {\n fields: ClientField[]\n schemaFields: ClientField[]\n} & Partial<ClipboardPasteActionValidateArgs>): ClipboardPasteActionValidateArgs =>\n ({\n type: 'array',\n data: baseData,\n fieldPath: 'items',\n fields,\n path: 'items',\n rowIndex: 0,\n schemaFields,\n ...overrides,\n }) as ClipboardPasteActionValidateArgs\n\nconst buildBlocksArgs = ({\n blocks,\n schemaBlocks,\n}: {\n blocks: ClientBlock[]\n schemaBlocks: ClientBlock[]\n}): ClipboardPasteActionValidateArgs =>\n ({\n type: 'blocks',\n blocks,\n data: { 'layout.0.blockType': { valid: true, value: 'cta' } },\n fieldPath: 'layout',\n path: 'layout',\n rowIndex: 0,\n schemaBlocks,\n }) as ClipboardPasteActionValidateArgs\n\ndescribe('isClipboardDataValid', () => {\n it('should return false when data is undefined', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ data: undefined, fields: [textField], schemaFields: [textField] }),\n ),\n ).toBe(false)\n })\n\n it('should return false when path is missing', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ fields: [textField], path: '', schemaFields: [textField] }),\n ),\n ).toBe(false)\n })\n\n describe('array fields', () => {\n it('should return true for a matching schema', () => {\n expect(\n isClipboardDataValid(buildArrayArgs({ fields: [textField], schemaFields: [textField] })),\n ).toBe(true)\n })\n\n it('should return false when field types differ', () => {\n expect(\n isClipboardDataValid(buildArrayArgs({ fields: [textField], schemaFields: [numberField] })),\n ).toBe(false)\n })\n\n it('should return false when field names differ', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ fields: [textField], schemaFields: [renamedTextField] }),\n ),\n ).toBe(false)\n })\n\n it('should return false when field counts differ', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ fields: [textField], schemaFields: [textField, numberField] }),\n ),\n ).toBe(false)\n })\n\n it('should return true for matching nested sub-fields', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ fields: [subArrayField], schemaFields: [subArrayField] }),\n ),\n ).toBe(true)\n })\n\n it('should return false for mismatching nested sub-fields', () => {\n expect(\n isClipboardDataValid(\n buildArrayArgs({ fields: [subArrayField], schemaFields: [subArrayFieldMismatch] }),\n ),\n ).toBe(false)\n })\n })\n\n describe('blocks fields', () => {\n it('should return true for a matching block schema', () => {\n expect(\n isClipboardDataValid(buildBlocksArgs({ blocks: [ctaBlock], schemaBlocks: [ctaBlock] })),\n ).toBe(true)\n })\n\n it('should return false when a copied block slug is not in the target config', () => {\n expect(\n isClipboardDataValid(buildBlocksArgs({ blocks: [ctaBlock], schemaBlocks: [otherBlock] })),\n ).toBe(false)\n })\n\n it('should return false when the target has no blocks configured', () => {\n expect(isClipboardDataValid(buildBlocksArgs({ blocks: [ctaBlock], schemaBlocks: [] }))).toBe(\n false,\n )\n })\n })\n})\n"],"mappings":"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","ignoreList":[]}
@@ -42,4 +42,7 @@ export type ClipboardPasteActionValidateArgs = {
42
42
  schemaFields: ClientField[];
43
43
  type: 'array';
44
44
  }) & ClipboardPasteData;
45
+ export type ClipboardPasteEligibilityArgs = {
46
+ path: string;
47
+ } & (ClipboardCopyBlocksSchema | ClipboardCopyFieldsSchema);
45
48
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEnF,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,CAAC,uBAAuB,GAAG,uBAAuB,CAAC,CAAA;AAEvD,MAAM,MAAM,uBAAuB,GAAG;IACpC,aAAa,EAAE,MAAM,0BAA0B,CAAA;IAC/C,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,iBAAiB,CAAA;AAErB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,0BAA0B,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,CAAC,uBAAuB,GAAG,uBAAuB,CAAC,CAAA;AAEvD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;AAE1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,CAAC,yBAAyB,GAAG,yBAAyB,CAAC,CAAA;AAE3D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,CACA;IACE,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,IAAI,EAAE,QAAQ,CAAA;CACf,GACD;IACE,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,IAAI,EAAE,OAAO,CAAA;CACd,CACJ,GACC,kBAAkB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAEnF,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,CAAC,uBAAuB,GAAG,uBAAuB,CAAC,CAAA;AAEvD,MAAM,MAAM,uBAAuB,GAAG;IACpC,aAAa,EAAE,MAAM,0BAA0B,CAAA;IAC/C,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,iBAAiB,CAAA;AAErB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,0BAA0B,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,CAAC,uBAAuB,GAAG,uBAAuB,CAAC,CAAA;AAEvD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;AAE1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,CAAC,yBAAyB,GAAG,yBAAyB,CAAC,CAAA;AAE3D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,CACA;IACE,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,IAAI,EAAE,QAAQ,CAAA;CACf,GACD;IACE,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,IAAI,EAAE,OAAO,CAAA;CACd,CACJ,GACC,kBAAkB,CAAA;AAEpB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CAAC,yBAAyB,GAAG,yBAAyB,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/elements/ClipboardAction/types.ts"],"sourcesContent":["import type { TFunction } from '@payloadcms/translations'\nimport type { ClientBlock, ClientField, FormStateWithoutComponents } from 'payload'\n\nexport type ClipboardCopyBlocksSchema = {\n schemaBlocks: ClientBlock[]\n}\n\nexport type ClipboardCopyBlocksData = {\n blocks: ClientBlock[]\n type: 'blocks'\n}\n\nexport type ClipboardCopyFieldsSchema = {\n schemaFields: ClientField[]\n}\n\nexport type ClipboardCopyFieldsData = {\n fields: ClientField[]\n type: 'array'\n}\n\nexport type ClipboardCopyData = {\n path: string\n rowIndex?: number\n} & (ClipboardCopyBlocksData | ClipboardCopyFieldsData)\n\nexport type ClipboardCopyActionArgs = {\n getDataToCopy: () => FormStateWithoutComponents\n t: TFunction\n} & ClipboardCopyData\n\nexport type ClipboardPasteData = {\n data: FormStateWithoutComponents\n path: string\n rowIndex?: number\n} & (ClipboardCopyBlocksData | ClipboardCopyFieldsData)\n\nexport type OnPasteFn = (data: ClipboardPasteData) => void\n\nexport type ClipboardPasteActionArgs = {\n onPaste: OnPasteFn\n path: string\n t: TFunction\n} & (ClipboardCopyBlocksSchema | ClipboardCopyFieldsSchema)\n\nexport type ClipboardPasteActionValidateArgs = {\n fieldPath: string\n} & (\n | {\n schemaBlocks: ClientBlock[]\n type: 'blocks'\n }\n | {\n schemaFields: ClientField[]\n type: 'array'\n }\n) &\n ClipboardPasteData\n"],"mappings":"AA6CA","ignoreList":[]}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/elements/ClipboardAction/types.ts"],"sourcesContent":["import type { TFunction } from '@payloadcms/translations'\nimport type { ClientBlock, ClientField, FormStateWithoutComponents } from 'payload'\n\nexport type ClipboardCopyBlocksSchema = {\n schemaBlocks: ClientBlock[]\n}\n\nexport type ClipboardCopyBlocksData = {\n blocks: ClientBlock[]\n type: 'blocks'\n}\n\nexport type ClipboardCopyFieldsSchema = {\n schemaFields: ClientField[]\n}\n\nexport type ClipboardCopyFieldsData = {\n fields: ClientField[]\n type: 'array'\n}\n\nexport type ClipboardCopyData = {\n path: string\n rowIndex?: number\n} & (ClipboardCopyBlocksData | ClipboardCopyFieldsData)\n\nexport type ClipboardCopyActionArgs = {\n getDataToCopy: () => FormStateWithoutComponents\n t: TFunction\n} & ClipboardCopyData\n\nexport type ClipboardPasteData = {\n data: FormStateWithoutComponents\n path: string\n rowIndex?: number\n} & (ClipboardCopyBlocksData | ClipboardCopyFieldsData)\n\nexport type OnPasteFn = (data: ClipboardPasteData) => void\n\nexport type ClipboardPasteActionArgs = {\n onPaste: OnPasteFn\n path: string\n t: TFunction\n} & (ClipboardCopyBlocksSchema | ClipboardCopyFieldsSchema)\n\nexport type ClipboardPasteActionValidateArgs = {\n fieldPath: string\n} & (\n | {\n schemaBlocks: ClientBlock[]\n type: 'blocks'\n }\n | {\n schemaFields: ClientField[]\n type: 'array'\n }\n) &\n ClipboardPasteData\n\nexport type ClipboardPasteEligibilityArgs = {\n path: string\n} & (ClipboardCopyBlocksSchema | ClipboardCopyFieldsSchema)\n"],"mappings":"AA2DA","ignoreList":[]}
@@ -0,0 +1,10 @@
1
+ import type { ClipboardPasteEligibilityArgs } from './types.js';
2
+ /**
3
+ * Tracks whether the clipboard contents can be pasted into the target field.
4
+ * Call `refresh` when a paste menu opens to re-check against the field's schema.
5
+ */
6
+ export declare function useCanPasteClipboard(args: ClipboardPasteEligibilityArgs): {
7
+ canPaste: boolean;
8
+ refresh: () => void;
9
+ };
10
+ //# sourceMappingURL=useCanPasteClipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCanPasteClipboard.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/useCanPasteClipboard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAA;AAI/D;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,6BAA6B,GAAG;IACzE,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAWA"}
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useRef, useState } from 'react';
4
+ import { canPasteClipboardData } from './clipboardUtilities.js';
5
+ /**
6
+ * Tracks whether the clipboard contents can be pasted into the target field.
7
+ * Call `refresh` when a paste menu opens to re-check against the field's schema.
8
+ */
9
+ export function useCanPasteClipboard(args) {
10
+ const [canPaste, setCanPaste] = useState(false);
11
+ const argsRef = useRef(args);
12
+ argsRef.current = args;
13
+ const refresh = useCallback(() => {
14
+ setCanPaste(canPasteClipboardData(argsRef.current));
15
+ }, []);
16
+ return {
17
+ canPaste,
18
+ refresh
19
+ };
20
+ }
21
+ //# sourceMappingURL=useCanPasteClipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCanPasteClipboard.js","names":["useCallback","useRef","useState","canPasteClipboardData","useCanPasteClipboard","args","canPaste","setCanPaste","argsRef","current","refresh"],"sources":["../../../src/elements/ClipboardAction/useCanPasteClipboard.ts"],"sourcesContent":["'use client'\nimport { useCallback, useRef, useState } from 'react'\n\nimport type { ClipboardPasteEligibilityArgs } from './types.js'\n\nimport { canPasteClipboardData } from './clipboardUtilities.js'\n\n/**\n * Tracks whether the clipboard contents can be pasted into the target field.\n * Call `refresh` when a paste menu opens to re-check against the field's schema.\n */\nexport function useCanPasteClipboard(args: ClipboardPasteEligibilityArgs): {\n canPaste: boolean\n refresh: () => void\n} {\n const [canPaste, setCanPaste] = useState<boolean>(false)\n\n const argsRef = useRef(args)\n argsRef.current = args\n\n const refresh = useCallback(() => {\n setCanPaste(canPasteClipboardData(argsRef.current))\n }, [])\n\n return { canPaste, refresh }\n}\n"],"mappings":"AAAA;;AACA,SAASA,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAQ;AAI9C,SAASC,qBAAqB,QAAQ;AAEtC;;;;AAIA,OAAO,SAASC,qBAAqBC,IAAmC;EAItE,MAAM,CAACC,QAAA,EAAUC,WAAA,CAAY,GAAGL,QAAA,CAAkB;EAElD,MAAMM,OAAA,GAAUP,MAAA,CAAOI,IAAA;EACvBG,OAAA,CAAQC,OAAO,GAAGJ,IAAA;EAElB,MAAMK,OAAA,GAAUV,WAAA,CAAY;IAC1BO,WAAA,CAAYJ,qBAAA,CAAsBK,OAAA,CAAQC,OAAO;EACnD,GAAG,EAAE;EAEL,OAAO;IAAEH,QAAA;IAAUI;EAAQ;AAC7B","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  @layer payload-default {
2
2
  .file-preview {
3
3
  display: flex;
4
- flex-direction: row;
4
+ flex-direction: column-reverse;
5
5
  flex: 1 1 0;
6
6
  min-height: 0;
7
7
  /* Visible so the mini carousel can grow past the panel as the headers scroll away. */
@@ -75,9 +75,9 @@
75
75
  min-width: 0;
76
76
  }
77
77
 
78
- @container edit-main (max-width: 768px) {
78
+ @container edit-main (min-width: 768px) {
79
79
  .file-preview {
80
- flex-direction: column-reverse;
80
+ flex-direction: row;
81
81
  }
82
82
  }
83
83
  }
@@ -1,13 +1,14 @@
1
1
  @layer payload-default {
2
2
  .file-manager {
3
+ --file-fields-max-width: 600px;
3
4
  position: relative;
4
- flex: 1 0 0;
5
5
  align-self: stretch;
6
6
  width: 100%;
7
7
  margin-bottom: 0;
8
8
  border-radius: 0;
9
9
  background: var(--color-bg-secondary);
10
- min-height: 100px;
10
+ min-height: 400px;
11
+ border-bottom: var(--stroke-width-small) solid var(--color-border);
11
12
 
12
13
  .dropzone {
13
14
  border: none;
@@ -16,25 +17,23 @@
16
17
  }
17
18
 
18
19
  .file-manager__panel {
19
- position: sticky;
20
- top: var(--doc-controls-height);
21
- height: calc(
22
- 100dvh - var(--app-header-height) - var(--doc-controls-height) - var(--doc-header-height)
23
- );
20
+ position: static;
21
+ height: auto;
22
+ min-height: 400px;
24
23
  display: flex;
25
24
  flex-direction: column;
26
25
  /* Visible so the mini carousel can grow past the panel to fill the area left behind as the
27
26
  app/doc headers scroll away (see MiniCarousel). */
28
27
  overflow: visible;
29
- /* Scroll-driven: grow height as the app header and doc header scroll away, matching the
30
- extra space they free up. Mirrors the MiniCarousel approach. Falls back to static height. */
31
28
  }
32
29
 
33
30
  .file-manager__content {
34
31
  display: flex;
35
- flex-direction: row;
36
- flex: 1 1 0;
37
- min-height: 0;
32
+ flex-direction: column;
33
+ /* flex-basis: auto (not 0) so this sizes to its content when the panel's height is auto
34
+ (stacked layout) instead of collapsing — flex-basis 0 only makes sense when the panel
35
+ has a definite height to grow into (see the min-width override below). */
36
+ flex: 1 1 auto;
38
37
  overflow: visible;
39
38
  }
40
39
 
@@ -44,7 +43,8 @@
44
43
  flex-direction: column;
45
44
  align-items: center;
46
45
  justify-content: center;
47
- padding: var(--spacer-4);
46
+ gap: var(--spacer-4);
47
+ padding: var(--spacer-4) var(--gutter-h);
48
48
  position: relative;
49
49
  }
50
50
 
@@ -58,10 +58,10 @@
58
58
  justify-content: center;
59
59
  }
60
60
 
61
- .file-manager__remove {
61
+ .file-manager__upload .file-manager__remove {
62
62
  position: absolute;
63
- top: var(--spacer-2);
64
- right: var(--spacer-2);
63
+ top: var(--gutter-h);
64
+ right: var(--gutter-h);
65
65
  margin: 0;
66
66
  z-index: 1;
67
67
  }
@@ -135,20 +135,33 @@
135
135
  color: var(--color-text-tertiary);
136
136
  }
137
137
 
138
- @container edit-main (max-width: 1024px) {
138
+ @container edit-main (min-width: 1024px) {
139
139
  .file-manager {
140
- min-height: 400px;
141
- border-bottom: var(--stroke-width-small) solid var(--color-border);
140
+ min-height: 100px;
141
+ border-bottom: none;
142
+ }
143
+
144
+ .file-manager__upload {
145
+ padding: var(--spacer-4);
146
+ }
147
+
148
+ .file-manager__file-adjustments {
149
+ max-width: var(--file-fields-max-width);
142
150
  }
143
151
 
144
152
  .file-manager__panel {
145
- position: static;
146
- height: auto;
147
- min-height: 400px;
153
+ position: sticky;
154
+ top: var(--doc-controls-height);
155
+ /* Scroll-driven: grow height as the app header and doc header scroll away, matching the
156
+ extra space they free up. Mirrors the MiniCarousel approach. Falls back to static height. */
157
+ height: calc(
158
+ 100dvh - var(--app-header-height) - var(--doc-controls-height) - var(--doc-header-height)
159
+ );
148
160
  }
149
161
 
150
162
  .file-manager__content {
151
- flex-direction: column;
163
+ flex-direction: row;
164
+ min-height: 0;
152
165
  }
153
166
  }
154
167
  }
@@ -10,7 +10,7 @@ export type FileManagerProps = {
10
10
  */
11
11
  readonly resetUploadEdits?: () => void;
12
12
  readonly updateUploadEdits?: (args: UploadEdits) => void;
13
- readonly uploadConfig: SanitizedCollectionConfig['upload'];
13
+ readonly uploadConfig: Omit<SanitizedCollectionConfig['upload'], 'uploadInstructions'>;
14
14
  readonly UploadControls?: React.ReactNode;
15
15
  readonly uploadEdits?: UploadEdits;
16
16
  readonly UploadFilePreview?: React.ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/FileManager/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIrE,OAAO,KAA6D,MAAM,OAAO,CAAA;AA2BjF,OAAO,aAAa,CAAA;AAcpB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,SAAS,EAAE,SAAS,CAAA;IACnD;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IACtC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IACxD,QAAQ,CAAC,YAAY,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAA;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAqalD,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/FileManager/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIrE,OAAO,KAA6D,MAAM,OAAO,CAAA;AA2BjF,OAAO,aAAa,CAAA;AAcpB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,SAAS,EAAE,SAAS,CAAA;IACnD;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IACtC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;IACxD,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,CAAA;IACtF,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7C,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAkblD,CAAA"}