@payloadcms/ui 4.0.0-internal.e55ccef → 4.0.0-internal.f851106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/ArrayAction/index.d.ts +2 -0
- package/dist/elements/ArrayAction/index.d.ts.map +1 -1
- package/dist/elements/ArrayAction/index.js +65 -24
- package/dist/elements/ArrayAction/index.js.map +1 -1
- package/dist/elements/ClipboardAction/clipboardUtilities.d.ts +8 -1
- package/dist/elements/ClipboardAction/clipboardUtilities.d.ts.map +1 -1
- package/dist/elements/ClipboardAction/clipboardUtilities.js +40 -8
- package/dist/elements/ClipboardAction/clipboardUtilities.js.map +1 -1
- package/dist/elements/ClipboardAction/clipboardUtilities.spec.js +120 -0
- package/dist/elements/ClipboardAction/clipboardUtilities.spec.js.map +1 -0
- package/dist/elements/ClipboardAction/index.d.ts.map +1 -1
- package/dist/elements/ClipboardAction/index.js +17 -1
- package/dist/elements/ClipboardAction/index.js.map +1 -1
- package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js +144 -0
- package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js.map +1 -0
- package/dist/elements/ClipboardAction/types.d.ts +3 -0
- package/dist/elements/ClipboardAction/types.d.ts.map +1 -1
- package/dist/elements/ClipboardAction/types.js.map +1 -1
- package/dist/elements/ClipboardAction/useCanPasteClipboard.d.ts +10 -0
- package/dist/elements/ClipboardAction/useCanPasteClipboard.d.ts.map +1 -0
- package/dist/elements/ClipboardAction/useCanPasteClipboard.js +21 -0
- package/dist/elements/ClipboardAction/useCanPasteClipboard.js.map +1 -0
- package/dist/exports/layouts.d.ts +0 -1
- package/dist/exports/layouts.d.ts.map +1 -1
- package/dist/exports/layouts.js +0 -1
- package/dist/exports/layouts.js.map +1 -1
- package/dist/exports/shared/index.d.ts +0 -1
- package/dist/exports/shared/index.d.ts.map +1 -1
- package/dist/exports/shared/index.js +2 -2
- package/dist/exports/shared/index.js.map +4 -4
- package/dist/fields/Array/ArrayRow.d.ts.map +1 -1
- package/dist/fields/Array/ArrayRow.js +97 -160
- package/dist/fields/Array/ArrayRow.js.map +1 -1
- package/dist/fields/Blocks/BlockRow.d.ts.map +1 -1
- package/dist/fields/Blocks/BlockRow.js +134 -195
- package/dist/fields/Blocks/BlockRow.js.map +1 -1
- package/dist/fields/Blocks/RowActions.d.ts +2 -0
- package/dist/fields/Blocks/RowActions.d.ts.map +1 -1
- package/dist/fields/Blocks/RowActions.js +23 -20
- package/dist/fields/Blocks/RowActions.js.map +1 -1
- package/dist/forms/RenderFields/index.css +16 -2
- package/dist/layouts/Root/viewport.d.ts +0 -1
- package/dist/layouts/Root/viewport.d.ts.map +1 -1
- package/dist/layouts/Root/viewport.js +1 -4
- package/dist/layouts/Root/viewport.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ClipboardPasteEligibilityArgs } from '../ClipboardAction/types.js';
|
|
2
3
|
import './index.css';
|
|
3
4
|
export type Props = {
|
|
4
5
|
addRow: (current: number, blockType?: string) => Promise<void> | void;
|
|
@@ -8,6 +9,7 @@ export type Props = {
|
|
|
8
9
|
index: number;
|
|
9
10
|
isSortable?: boolean;
|
|
10
11
|
moveRow: (from: number, to: number) => void;
|
|
12
|
+
pasteData: ClipboardPasteEligibilityArgs;
|
|
11
13
|
pasteRow: (index: number) => void;
|
|
12
14
|
removeRow: (index: number) => void;
|
|
13
15
|
rowCount: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/ArrayAction/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/ArrayAction/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAA;AAYhF,OAAO,aAAa,CAAA;AAIpB,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACrE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,SAAS,EAAE,6BAA6B,CAAA;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAqHvC,CAAA"}
|
|
@@ -11,11 +11,12 @@ import { MoreIcon } from '../../icons/More/index.js';
|
|
|
11
11
|
import { PlusIcon } from '../../icons/Plus/index.js';
|
|
12
12
|
import { XIcon } from '../../icons/X/index.js';
|
|
13
13
|
import { useTranslation } from '../../providers/Translation/index.js';
|
|
14
|
+
import { useCanPasteClipboard } from '../ClipboardAction/useCanPasteClipboard.js';
|
|
14
15
|
import { Popup, PopupList } from '../Popup/index.js';
|
|
15
16
|
import './index.css';
|
|
16
17
|
const baseClass = 'array-actions';
|
|
17
18
|
export const ArrayAction = t0 => {
|
|
18
|
-
const $ = _c(
|
|
19
|
+
const $ = _c(29);
|
|
19
20
|
const {
|
|
20
21
|
addRow,
|
|
21
22
|
copyRow,
|
|
@@ -24,6 +25,7 @@ export const ArrayAction = t0 => {
|
|
|
24
25
|
index,
|
|
25
26
|
isSortable,
|
|
26
27
|
moveRow,
|
|
28
|
+
pasteData,
|
|
27
29
|
pasteRow,
|
|
28
30
|
removeRow,
|
|
29
31
|
rowCount
|
|
@@ -31,19 +33,30 @@ export const ArrayAction = t0 => {
|
|
|
31
33
|
const {
|
|
32
34
|
t
|
|
33
35
|
} = useTranslation();
|
|
36
|
+
const {
|
|
37
|
+
canPaste,
|
|
38
|
+
refresh
|
|
39
|
+
} = useCanPasteClipboard(pasteData);
|
|
34
40
|
let t1;
|
|
35
|
-
if ($[0] !== addRow || $[1] !==
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
if ($[0] !== addRow || $[1] !== canPaste || $[2] !== copyRow || $[3] !== duplicateRow || $[4] !== hasMaxRows || $[5] !== index || $[6] !== isSortable || $[7] !== moveRow || $[8] !== pasteRow || $[9] !== refresh || $[10] !== removeRow || $[11] !== rowCount || $[12] !== t) {
|
|
42
|
+
let t2;
|
|
43
|
+
if ($[14] !== refresh) {
|
|
44
|
+
t2 = active => {
|
|
45
|
+
if (active) {
|
|
46
|
+
refresh();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
$[14] = refresh;
|
|
50
|
+
$[15] = t2;
|
|
51
|
+
} else {
|
|
52
|
+
t2 = $[15];
|
|
53
|
+
}
|
|
54
|
+
let t3;
|
|
55
|
+
if ($[16] !== addRow || $[17] !== canPaste || $[18] !== copyRow || $[19] !== duplicateRow || $[20] !== hasMaxRows || $[21] !== index || $[22] !== isSortable || $[23] !== moveRow || $[24] !== pasteRow || $[25] !== removeRow || $[26] !== rowCount || $[27] !== t) {
|
|
56
|
+
t3 = t4 => {
|
|
44
57
|
const {
|
|
45
58
|
close
|
|
46
|
-
} =
|
|
59
|
+
} = t4;
|
|
47
60
|
return _jsxs(PopupList.MenuItem, {
|
|
48
61
|
children: [isSortable && index !== 0 && _jsx(PopupList.Button, {
|
|
49
62
|
className: `${baseClass}__action ${baseClass}__move-up`,
|
|
@@ -101,6 +114,7 @@ export const ArrayAction = t0 => {
|
|
|
101
114
|
children: t("general:copyRow")
|
|
102
115
|
}), _jsx(PopupList.Button, {
|
|
103
116
|
className: `${baseClass}__action ${baseClass}__paste`,
|
|
117
|
+
disabled: !canPaste,
|
|
104
118
|
icon: _jsx(ClipboardIcon, {
|
|
105
119
|
size: 24
|
|
106
120
|
}),
|
|
@@ -121,22 +135,49 @@ export const ArrayAction = t0 => {
|
|
|
121
135
|
children: t("general:remove")
|
|
122
136
|
})]
|
|
123
137
|
});
|
|
124
|
-
}
|
|
138
|
+
};
|
|
139
|
+
$[16] = addRow;
|
|
140
|
+
$[17] = canPaste;
|
|
141
|
+
$[18] = copyRow;
|
|
142
|
+
$[19] = duplicateRow;
|
|
143
|
+
$[20] = hasMaxRows;
|
|
144
|
+
$[21] = index;
|
|
145
|
+
$[22] = isSortable;
|
|
146
|
+
$[23] = moveRow;
|
|
147
|
+
$[24] = pasteRow;
|
|
148
|
+
$[25] = removeRow;
|
|
149
|
+
$[26] = rowCount;
|
|
150
|
+
$[27] = t;
|
|
151
|
+
$[28] = t3;
|
|
152
|
+
} else {
|
|
153
|
+
t3 = $[28];
|
|
154
|
+
}
|
|
155
|
+
t1 = _jsx(Popup, {
|
|
156
|
+
button: _jsx(MoreIcon, {}),
|
|
157
|
+
buttonAriaLabel: t("general:moreOptions"),
|
|
158
|
+
buttonClassName: `${baseClass}__button`,
|
|
159
|
+
caret: false,
|
|
160
|
+
className: baseClass,
|
|
161
|
+
horizontalAlign: "right",
|
|
162
|
+
onToggleOpen: t2,
|
|
163
|
+
render: t3
|
|
125
164
|
});
|
|
126
165
|
$[0] = addRow;
|
|
127
|
-
$[1] =
|
|
128
|
-
$[2] =
|
|
129
|
-
$[3] =
|
|
130
|
-
$[4] =
|
|
131
|
-
$[5] =
|
|
132
|
-
$[6] =
|
|
133
|
-
$[7] =
|
|
134
|
-
$[8] =
|
|
135
|
-
$[9] =
|
|
136
|
-
$[10] =
|
|
137
|
-
$[11] =
|
|
166
|
+
$[1] = canPaste;
|
|
167
|
+
$[2] = copyRow;
|
|
168
|
+
$[3] = duplicateRow;
|
|
169
|
+
$[4] = hasMaxRows;
|
|
170
|
+
$[5] = index;
|
|
171
|
+
$[6] = isSortable;
|
|
172
|
+
$[7] = moveRow;
|
|
173
|
+
$[8] = pasteRow;
|
|
174
|
+
$[9] = refresh;
|
|
175
|
+
$[10] = removeRow;
|
|
176
|
+
$[11] = rowCount;
|
|
177
|
+
$[12] = t;
|
|
178
|
+
$[13] = t1;
|
|
138
179
|
} else {
|
|
139
|
-
t1 = $[
|
|
180
|
+
t1 = $[13];
|
|
140
181
|
}
|
|
141
182
|
return t1;
|
|
142
183
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["c","_c","React","ArrowIcon","ClipboardIcon","CopyIcon","DuplicateIcon","MoreIcon","PlusIcon","XIcon","useTranslation","Popup","PopupList","baseClass","ArrayAction","t0","$","addRow","copyRow","duplicateRow","hasMaxRows","index","isSortable","moveRow","pasteRow","removeRow","rowCount","t","t1","
|
|
1
|
+
{"version":3,"file":"index.js","names":["c","_c","React","ArrowIcon","ClipboardIcon","CopyIcon","DuplicateIcon","MoreIcon","PlusIcon","XIcon","useTranslation","useCanPasteClipboard","Popup","PopupList","baseClass","ArrayAction","t0","$","addRow","copyRow","duplicateRow","hasMaxRows","index","isSortable","moveRow","pasteData","pasteRow","removeRow","rowCount","t","canPaste","refresh","t1","t2","active","t3","t4","close","_jsxs","MenuItem","children","_jsx","Button","className","icon","direction","size","Fragment","disabled","button","buttonAriaLabel","buttonClassName","caret","horizontalAlign","onToggleOpen","render"],"sources":["../../../src/elements/ArrayAction/index.tsx"],"sourcesContent":["'use client'\nimport React from 'react'\n\nimport type { ClipboardPasteEligibilityArgs } from '../ClipboardAction/types.js'\n\nimport { ArrowIcon } from '../../icons/Arrow/index.js'\nimport { ClipboardIcon } from '../../icons/Clipboard/index.js'\nimport { CopyIcon } from '../../icons/Copy/index.js'\nimport { DuplicateIcon } from '../../icons/Duplicate/index.js'\nimport { MoreIcon } from '../../icons/More/index.js'\nimport { PlusIcon } from '../../icons/Plus/index.js'\nimport { XIcon } from '../../icons/X/index.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { useCanPasteClipboard } from '../ClipboardAction/useCanPasteClipboard.js'\nimport { Popup, PopupList } from '../Popup/index.js'\nimport './index.css'\n\nconst baseClass = 'array-actions'\n\nexport type Props = {\n addRow: (current: number, blockType?: string) => Promise<void> | void\n copyRow: (index: number) => void\n duplicateRow: (current: number) => void\n hasMaxRows: boolean\n index: number\n isSortable?: boolean\n moveRow: (from: number, to: number) => void\n pasteData: ClipboardPasteEligibilityArgs\n pasteRow: (index: number) => void\n removeRow: (index: number) => void\n rowCount: number\n}\n\nexport const ArrayAction: React.FC<Props> = ({\n addRow,\n copyRow,\n duplicateRow,\n hasMaxRows,\n index,\n isSortable,\n moveRow,\n pasteData,\n pasteRow,\n removeRow,\n rowCount,\n}) => {\n const { t } = useTranslation()\n\n const { canPaste, refresh } = useCanPasteClipboard(pasteData)\n\n return (\n <Popup\n button={<MoreIcon />}\n buttonAriaLabel={t('general:moreOptions')}\n buttonClassName={`${baseClass}__button`}\n caret={false}\n className={baseClass}\n horizontalAlign=\"right\"\n onToggleOpen={(active) => {\n if (active) {\n refresh()\n }\n }}\n render={({ close }) => {\n return (\n <PopupList.MenuItem>\n {isSortable && index !== 0 && (\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__move-up`}\n icon={<ArrowIcon direction=\"up\" size={24} />}\n onClick={() => {\n moveRow(index, index - 1)\n close()\n }}\n >\n {t('general:moveUp')}\n </PopupList.Button>\n )}\n {isSortable && index < rowCount - 1 && (\n <PopupList.Button\n className={`${baseClass}__action`}\n icon={<ArrowIcon direction=\"down\" size={24} />}\n onClick={() => {\n moveRow(index, index + 1)\n close()\n }}\n >\n {t('general:moveDown')}\n </PopupList.Button>\n )}\n {!hasMaxRows && (\n <React.Fragment>\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__add`}\n icon={<PlusIcon size={24} />}\n onClick={() => {\n void addRow(index + 1)\n close()\n }}\n >\n {t('general:addBelow')}\n </PopupList.Button>\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__duplicate`}\n icon={<DuplicateIcon size={24} />}\n onClick={() => {\n duplicateRow(index)\n close()\n }}\n >\n {t('general:duplicate')}\n </PopupList.Button>\n </React.Fragment>\n )}\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__copy`}\n icon={<CopyIcon size={24} />}\n onClick={() => {\n copyRow(index)\n close()\n }}\n >\n {t('general:copyRow')}\n </PopupList.Button>\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__paste`}\n disabled={!canPaste}\n icon={<ClipboardIcon size={24} />}\n onClick={() => {\n pasteRow(index)\n close()\n }}\n >\n {t('general:pasteRow')}\n </PopupList.Button>\n <PopupList.Button\n className={`${baseClass}__action ${baseClass}__remove`}\n icon={<XIcon size={24} />}\n onClick={() => {\n removeRow(index)\n close()\n }}\n >\n {t('general:remove')}\n </PopupList.Button>\n </PopupList.MenuItem>\n )\n }}\n />\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type { ClipboardCopyActionArgs, ClipboardPasteActionArgs } from './types.js';
|
|
1
|
+
import type { ClipboardCopyActionArgs, ClipboardPasteActionArgs, ClipboardPasteEligibilityArgs } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether the clipboard contents can be pasted into the target field.
|
|
4
|
+
*
|
|
5
|
+
* Returns `false` when the clipboard is empty or its schema is incompatible
|
|
6
|
+
* with the target. Used to disable paste actions when they would fail.
|
|
7
|
+
*/
|
|
8
|
+
export declare function canPasteClipboardData(args: ClipboardPasteEligibilityArgs): boolean;
|
|
2
9
|
/**
|
|
3
10
|
* @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513
|
|
4
11
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboardUtilities.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/clipboardUtilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"clipboardUtilities.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/clipboardUtilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EAGxB,6BAA6B,EAC9B,MAAM,YAAY,CAAA;AAyBnB;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,6BAA6B,GAAG,OAAO,CAgBlF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,GAAG,IAAI,CAc1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EAAE,SAAS,EACf,CAAC,EACD,GAAG,IAAI,EACR,EAAE,wBAAwB,GAAG,MAAM,GAAG,IAAI,CAoB1C"}
|
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import { isClipboardDataValid } from './isClipboardDataValid.js';
|
|
2
2
|
const localStorageClipboardKey = '_payloadClipboard';
|
|
3
|
+
/**
|
|
4
|
+
* Reads and parses the clipboard data from localStorage.
|
|
5
|
+
*
|
|
6
|
+
* @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513
|
|
7
|
+
*/
|
|
8
|
+
function readClipboardData() {
|
|
9
|
+
try {
|
|
10
|
+
const jsonFromClipboard = localStorage.getItem(localStorageClipboardKey);
|
|
11
|
+
if (!jsonFromClipboard) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return JSON.parse(jsonFromClipboard);
|
|
15
|
+
} catch (_err) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Whether the clipboard contents can be pasted into the target field.
|
|
21
|
+
*
|
|
22
|
+
* Returns `false` when the clipboard is empty or its schema is incompatible
|
|
23
|
+
* with the target. Used to disable paste actions when they would fail.
|
|
24
|
+
*/
|
|
25
|
+
export function canPasteClipboardData(args) {
|
|
26
|
+
const dataToPaste = readClipboardData();
|
|
27
|
+
if (!dataToPaste) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const {
|
|
31
|
+
path,
|
|
32
|
+
...schemaArgs
|
|
33
|
+
} = args;
|
|
34
|
+
const dataToValidate = {
|
|
35
|
+
...dataToPaste,
|
|
36
|
+
...schemaArgs,
|
|
37
|
+
fieldPath: path
|
|
38
|
+
};
|
|
39
|
+
return isClipboardDataValid(dataToValidate);
|
|
40
|
+
}
|
|
3
41
|
/**
|
|
4
42
|
* @note This function doesn't use the Clipboard API, but localStorage. See rationale in #11513
|
|
5
43
|
*/
|
|
@@ -29,14 +67,8 @@ export function clipboardPaste({
|
|
|
29
67
|
t,
|
|
30
68
|
...args
|
|
31
69
|
}) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const jsonFromClipboard = localStorage.getItem(localStorageClipboardKey);
|
|
35
|
-
if (!jsonFromClipboard) {
|
|
36
|
-
return t('error:invalidClipboardData');
|
|
37
|
-
}
|
|
38
|
-
dataToPaste = JSON.parse(jsonFromClipboard);
|
|
39
|
-
} catch (_err) {
|
|
70
|
+
const dataToPaste = readClipboardData();
|
|
71
|
+
if (!dataToPaste) {
|
|
40
72
|
return t('error:invalidClipboardData');
|
|
41
73
|
}
|
|
42
74
|
const dataToValidate = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboardUtilities.js","names":["isClipboardDataValid","localStorageClipboardKey","
|
|
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;
|
|
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","
|
|
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":[]}
|