@payloadcms/ui 4.0.0-canary.26 → 4.0.0-canary.28
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/BulkUpload/AddFilesView/index.css +10 -4
- package/dist/elements/BulkUpload/AddFilesView/index.d.ts.map +1 -1
- package/dist/elements/BulkUpload/AddFilesView/index.js +71 -51
- package/dist/elements/BulkUpload/AddFilesView/index.js.map +1 -1
- package/dist/elements/Button/index.d.ts.map +1 -1
- package/dist/elements/Button/index.js +2 -0
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.d.ts.map +1 -1
- package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.js +10 -3
- package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.js.map +1 -1
- package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.spec.js +345 -1
- package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.spec.js.map +1 -1
- package/dist/elements/Dropzone/index.css +10 -4
- package/dist/elements/FileManager/index.css +0 -30
- package/dist/elements/FileManager/index.d.ts.map +1 -1
- package/dist/elements/FileManager/index.js +379 -287
- package/dist/elements/FileManager/index.js.map +1 -1
- package/dist/elements/Upload/UploadFromURLModal/index.d.ts +1 -1
- package/dist/elements/Upload/UploadFromURLModal/index.d.ts.map +1 -1
- package/dist/elements/Upload/UploadFromURLModal/index.js.map +1 -1
- package/dist/elements/Upload/index.css +39 -32
- package/dist/elements/Upload/index.d.ts.map +1 -1
- package/dist/elements/Upload/index.js +37 -99
- package/dist/elements/Upload/index.js.map +1 -1
- package/dist/elements/Upload/usePasteFromClipboard.d.ts +14 -0
- package/dist/elements/Upload/usePasteFromClipboard.d.ts.map +1 -0
- package/dist/elements/Upload/usePasteFromClipboard.js +93 -0
- package/dist/elements/Upload/usePasteFromClipboard.js.map +1 -0
- package/dist/elements/Upload/useUploadFromUrl.d.ts +20 -0
- package/dist/elements/Upload/useUploadFromUrl.d.ts.map +1 -0
- package/dist/elements/Upload/useUploadFromUrl.js +201 -0
- package/dist/elements/Upload/useUploadFromUrl.js.map +1 -0
- package/dist/elements/UploadDropzoneContent/index.css +31 -0
- package/dist/elements/UploadDropzoneContent/index.d.ts +17 -0
- package/dist/elements/UploadDropzoneContent/index.d.ts.map +1 -0
- package/dist/elements/UploadDropzoneContent/index.js +62 -0
- package/dist/elements/UploadDropzoneContent/index.js.map +1 -0
- package/dist/elements/WhereBuilder/conditionValue.d.ts +32 -0
- package/dist/elements/WhereBuilder/conditionValue.d.ts.map +1 -0
- package/dist/elements/WhereBuilder/conditionValue.js +32 -0
- package/dist/elements/WhereBuilder/conditionValue.js.map +1 -0
- package/dist/elements/WhereBuilder/conditionValue.spec.js +65 -0
- package/dist/elements/WhereBuilder/conditionValue.spec.js.map +1 -0
- package/dist/elements/WhereBuilder/index.d.ts.map +1 -1
- package/dist/elements/WhereBuilder/index.js +15 -4
- package/dist/elements/WhereBuilder/index.js.map +1 -1
- package/dist/fields/Upload/Input.d.ts.map +1 -1
- package/dist/fields/Upload/Input.js +26 -0
- package/dist/fields/Upload/Input.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utilities/formatMetadata.d.ts.map +1 -1
- package/dist/utilities/formatMetadata.js +0 -5
- package/dist/utilities/formatMetadata.js.map +1 -1
- package/dist/utilities/getFilesFromClipboard.d.ts +10 -0
- package/dist/utilities/getFilesFromClipboard.d.ts.map +1 -0
- package/dist/utilities/getFilesFromClipboard.js +49 -0
- package/dist/utilities/getFilesFromClipboard.js.map +1 -0
- package/dist/utilities/slugify.d.ts.map +1 -1
- package/dist/utilities/slugify.js +1 -0
- package/dist/utilities/slugify.js.map +1 -1
- package/dist/views/Root/getCustomCollectionViewByRoute.d.ts.map +1 -1
- package/dist/views/Root/getCustomCollectionViewByRoute.js.map +1 -1
- package/dist/views/Root/getCustomGlobalViewByRoute.d.ts.map +1 -1
- package/dist/views/Root/getCustomGlobalViewByRoute.js.map +1 -1
- package/dist/views/Root/getCustomViewByKey.d.ts.map +1 -1
- package/dist/views/Root/getCustomViewByKey.js.map +1 -1
- package/dist/views/Version/generateVersionViewMetadata.js.map +1 -1
- package/dist/views/Versions/generateVersionsViewMetadata.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useTranslation } from '../../providers/Translation/index.js';
|
|
6
|
+
import { Button } from '../Button/index.js';
|
|
7
|
+
import './index.css';
|
|
8
|
+
const baseClass = 'upload-dropzone-content';
|
|
9
|
+
export function UploadDropzoneContent({
|
|
10
|
+
acceptMimeTypes,
|
|
11
|
+
className,
|
|
12
|
+
extraControls,
|
|
13
|
+
multiple,
|
|
14
|
+
onFilesSelected,
|
|
15
|
+
onPasteFromClipboard,
|
|
16
|
+
pasteButtonClassName,
|
|
17
|
+
pasteTooltip
|
|
18
|
+
}) {
|
|
19
|
+
const {
|
|
20
|
+
t
|
|
21
|
+
} = useTranslation();
|
|
22
|
+
const inputRef = React.useRef(null);
|
|
23
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
24
|
+
className: [baseClass, className].filter(Boolean).join(' '),
|
|
25
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
26
|
+
className: `${baseClass}__buttons`,
|
|
27
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
|
28
|
+
buttonStyle: "secondary",
|
|
29
|
+
onClick: () => inputRef.current?.click(),
|
|
30
|
+
size: "medium",
|
|
31
|
+
children: t('upload:selectFile')
|
|
32
|
+
}), /*#__PURE__*/_jsx("input", {
|
|
33
|
+
accept: acceptMimeTypes,
|
|
34
|
+
"aria-hidden": "true",
|
|
35
|
+
className: `${baseClass}__hidden-input`,
|
|
36
|
+
hidden: true,
|
|
37
|
+
multiple: multiple,
|
|
38
|
+
onChange: e => {
|
|
39
|
+
if (e.target.files && e.target.files.length > 0) {
|
|
40
|
+
onFilesSelected(e.target.files);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
ref: inputRef,
|
|
44
|
+
type: "file"
|
|
45
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
46
|
+
className: `${baseClass}__or-text`,
|
|
47
|
+
children: t('general:or')
|
|
48
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
49
|
+
buttonStyle: "secondary",
|
|
50
|
+
className: [`${baseClass}__pasteFromClipboard`, pasteButtonClassName].filter(Boolean).join(' '),
|
|
51
|
+
icon: "clipboard",
|
|
52
|
+
onClick: onPasteFromClipboard,
|
|
53
|
+
size: "medium",
|
|
54
|
+
tooltip: pasteTooltip
|
|
55
|
+
}), extraControls]
|
|
56
|
+
}), /*#__PURE__*/_jsxs("p", {
|
|
57
|
+
className: `${baseClass}__drag-text`,
|
|
58
|
+
children: [t('general:or'), " ", t('upload:dragAndDrop')]
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["React","useTranslation","Button","baseClass","UploadDropzoneContent","acceptMimeTypes","className","extraControls","multiple","onFilesSelected","onPasteFromClipboard","pasteButtonClassName","pasteTooltip","t","inputRef","useRef","_jsxs","filter","Boolean","join","_jsx","buttonStyle","onClick","current","click","size","accept","hidden","onChange","e","target","files","length","ref","type","icon","tooltip"],"sources":["../../../src/elements/UploadDropzoneContent/index.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { Button } from '../Button/index.js'\nimport './index.css'\n\nconst baseClass = 'upload-dropzone-content'\n\nexport type UploadDropzoneContentProps = {\n readonly acceptMimeTypes?: string\n readonly className?: string\n /** Extra controls rendered alongside the select/paste buttons, e.g. the single-upload field's custom `UploadControls`. */\n readonly extraControls?: React.ReactNode\n /** Allows selecting more than one file at once, used by the bulk upload drawer. */\n readonly multiple?: boolean\n readonly onFilesSelected: (files: FileList) => void\n readonly onPasteFromClipboard: () => void\n /** Additional className kept on the paste button for callers with existing selectors depending on it. */\n readonly pasteButtonClassName?: string\n readonly pasteTooltip: string\n}\n\nexport function UploadDropzoneContent({\n acceptMimeTypes,\n className,\n extraControls,\n multiple,\n onFilesSelected,\n onPasteFromClipboard,\n pasteButtonClassName,\n pasteTooltip,\n}: UploadDropzoneContentProps) {\n const { t } = useTranslation()\n const inputRef = React.useRef<HTMLInputElement>(null)\n\n return (\n <div className={[baseClass, className].filter(Boolean).join(' ')}>\n <div className={`${baseClass}__buttons`}>\n <Button buttonStyle=\"secondary\" onClick={() => inputRef.current?.click()} size=\"medium\">\n {t('upload:selectFile')}\n </Button>\n <input\n accept={acceptMimeTypes}\n aria-hidden=\"true\"\n className={`${baseClass}__hidden-input`}\n hidden\n multiple={multiple}\n onChange={(e) => {\n if (e.target.files && e.target.files.length > 0) {\n onFilesSelected(e.target.files)\n }\n }}\n ref={inputRef}\n type=\"file\"\n />\n <span className={`${baseClass}__or-text`}>{t('general:or')}</span>\n <Button\n buttonStyle=\"secondary\"\n className={[`${baseClass}__pasteFromClipboard`, pasteButtonClassName]\n .filter(Boolean)\n .join(' ')}\n icon=\"clipboard\"\n onClick={onPasteFromClipboard}\n size=\"medium\"\n tooltip={pasteTooltip}\n />\n {extraControls}\n </div>\n <p className={`${baseClass}__drag-text`}>\n {t('general:or')} {t('upload:dragAndDrop')}\n </p>\n </div>\n )\n}\n"],"mappings":"AAAA;;;AAEA,OAAOA,KAAA,MAAW;AAElB,SAASC,cAAc,QAAQ;AAC/B,SAASC,MAAM,QAAQ;AACvB,OAAO;AAEP,MAAMC,SAAA,GAAY;AAgBlB,OAAO,SAASC,sBAAsB;EACpCC,eAAe;EACfC,SAAS;EACTC,aAAa;EACbC,QAAQ;EACRC,eAAe;EACfC,oBAAoB;EACpBC,oBAAoB;EACpBC;AAAY,CACe;EAC3B,MAAM;IAAEC;EAAC,CAAE,GAAGZ,cAAA;EACd,MAAMa,QAAA,GAAWd,KAAA,CAAMe,MAAM,CAAmB;EAEhD,oBACEC,KAAA,CAAC;IAAIV,SAAA,EAAW,CAACH,SAAA,EAAWG,SAAA,CAAU,CAACW,MAAM,CAACC,OAAA,EAASC,IAAI,CAAC;4BAC1DH,KAAA,CAAC;MAAIV,SAAA,EAAW,GAAGH,SAAA,WAAoB;8BACrCiB,IAAA,CAAClB,MAAA;QAAOmB,WAAA,EAAY;QAAYC,OAAA,EAASA,CAAA,KAAMR,QAAA,CAASS,OAAO,EAAEC,KAAA;QAASC,IAAA,EAAK;kBAC5EZ,CAAA,CAAE;uBAELO,IAAA,CAAC;QACCM,MAAA,EAAQrB,eAAA;QACR,eAAY;QACZC,SAAA,EAAW,GAAGH,SAAA,gBAAyB;QACvCwB,MAAM;QACNnB,QAAA,EAAUA,QAAA;QACVoB,QAAA,EAAWC,CAAA;UACT,IAAIA,CAAA,CAAEC,MAAM,CAACC,KAAK,IAAIF,CAAA,CAAEC,MAAM,CAACC,KAAK,CAACC,MAAM,GAAG,GAAG;YAC/CvB,eAAA,CAAgBoB,CAAA,CAAEC,MAAM,CAACC,KAAK;UAChC;QACF;QACAE,GAAA,EAAKnB,QAAA;QACLoB,IAAA,EAAK;uBAEPd,IAAA,CAAC;QAAKd,SAAA,EAAW,GAAGH,SAAA,WAAoB;kBAAGU,CAAA,CAAE;uBAC7CO,IAAA,CAAClB,MAAA;QACCmB,WAAA,EAAY;QACZf,SAAA,EAAW,CAAC,GAAGH,SAAA,sBAA+B,EAAEQ,oBAAA,CAAqB,CAClEM,MAAM,CAACC,OAAA,EACPC,IAAI,CAAC;QACRgB,IAAA,EAAK;QACLb,OAAA,EAASZ,oBAAA;QACTe,IAAA,EAAK;QACLW,OAAA,EAASxB;UAEVL,aAAA;qBAEHS,KAAA,CAAC;MAAEV,SAAA,EAAW,GAAGH,SAAA,aAAsB;iBACpCU,CAAA,CAAE,eAAc,KAAEA,CAAA,CAAE;;;AAI7B","ignoreList":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { UpdateCondition } from './types.js';
|
|
2
|
+
type UpdateType = Parameters<UpdateCondition>[0]['type'];
|
|
3
|
+
/**
|
|
4
|
+
* A row that holds no value yet. Empty arrives as `''` from the URL, `null` from a cleared
|
|
5
|
+
* select, or `undefined` from a row that was added but never filled in.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isEmptyConditionValue: ({ value }: {
|
|
8
|
+
value: unknown;
|
|
9
|
+
}) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The value a row renders with. Only a missing value becomes `undefined`. `0` and `false` are
|
|
12
|
+
* real filter values, so they must survive.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getDisplayedConditionValue: <T>({ value }: {
|
|
15
|
+
value: T;
|
|
16
|
+
}) => T | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Whether an edit leaves the row unchanged, and so must not be committed.
|
|
19
|
+
*
|
|
20
|
+
* An empty row renders blank and reports `undefined` back up as soon as it mounts. Committing
|
|
21
|
+
* that stores `{ [operator]: undefined }`, which `qs.stringify` drops when the query is written
|
|
22
|
+
* to the URL — so the row is gone on the next parse.
|
|
23
|
+
*
|
|
24
|
+
* Field and operator edits change the row even while it holds no value, so they always commit.
|
|
25
|
+
*/
|
|
26
|
+
export declare const isNoOpConditionValueUpdate: ({ type, incomingValue, storedValue, }: {
|
|
27
|
+
incomingValue: unknown;
|
|
28
|
+
storedValue: unknown;
|
|
29
|
+
type: UpdateType;
|
|
30
|
+
}) => boolean;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=conditionValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditionValue.d.ts","sourceRoot":"","sources":["../../../src/elements/WhereBuilder/conditionValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,KAAK,UAAU,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,cAAe;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,KAAG,OACf,CAAA;AAEvD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GAAI,CAAC,aAAa;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,KAAG,CAAC,GAAG,SACxD,CAAA;AAEpB;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,0CAIpC;IACD,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;CACjB,KAAG,OAG6C,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A row that holds no value yet. Empty arrives as `''` from the URL, `null` from a cleared
|
|
3
|
+
* select, or `undefined` from a row that was added but never filled in.
|
|
4
|
+
*/export const isEmptyConditionValue = ({
|
|
5
|
+
value
|
|
6
|
+
}) => value === undefined || value === null || value === '';
|
|
7
|
+
/**
|
|
8
|
+
* The value a row renders with. Only a missing value becomes `undefined`. `0` and `false` are
|
|
9
|
+
* real filter values, so they must survive.
|
|
10
|
+
*/
|
|
11
|
+
export const getDisplayedConditionValue = ({
|
|
12
|
+
value
|
|
13
|
+
}) => value ?? undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Whether an edit leaves the row unchanged, and so must not be committed.
|
|
16
|
+
*
|
|
17
|
+
* An empty row renders blank and reports `undefined` back up as soon as it mounts. Committing
|
|
18
|
+
* that stores `{ [operator]: undefined }`, which `qs.stringify` drops when the query is written
|
|
19
|
+
* to the URL — so the row is gone on the next parse.
|
|
20
|
+
*
|
|
21
|
+
* Field and operator edits change the row even while it holds no value, so they always commit.
|
|
22
|
+
*/
|
|
23
|
+
export const isNoOpConditionValueUpdate = ({
|
|
24
|
+
type,
|
|
25
|
+
incomingValue,
|
|
26
|
+
storedValue
|
|
27
|
+
}) => type === 'value' && isEmptyConditionValue({
|
|
28
|
+
value: storedValue
|
|
29
|
+
}) && isEmptyConditionValue({
|
|
30
|
+
value: incomingValue
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=conditionValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditionValue.js","names":["isEmptyConditionValue","value","undefined","getDisplayedConditionValue","isNoOpConditionValueUpdate","type","incomingValue","storedValue"],"sources":["../../../src/elements/WhereBuilder/conditionValue.ts"],"sourcesContent":["import type { UpdateCondition } from './types.js'\n\ntype UpdateType = Parameters<UpdateCondition>[0]['type']\n\n/**\n * A row that holds no value yet. Empty arrives as `''` from the URL, `null` from a cleared\n * select, or `undefined` from a row that was added but never filled in.\n */\nexport const isEmptyConditionValue = ({ value }: { value: unknown }): boolean =>\n value === undefined || value === null || value === ''\n\n/**\n * The value a row renders with. Only a missing value becomes `undefined`. `0` and `false` are\n * real filter values, so they must survive.\n */\nexport const getDisplayedConditionValue = <T>({ value }: { value: T }): T | undefined =>\n value ?? undefined\n\n/**\n * Whether an edit leaves the row unchanged, and so must not be committed.\n *\n * An empty row renders blank and reports `undefined` back up as soon as it mounts. Committing\n * that stores `{ [operator]: undefined }`, which `qs.stringify` drops when the query is written\n * to the URL — so the row is gone on the next parse.\n *\n * Field and operator edits change the row even while it holds no value, so they always commit.\n */\nexport const isNoOpConditionValueUpdate = ({\n type,\n incomingValue,\n storedValue,\n}: {\n incomingValue: unknown\n storedValue: unknown\n type: UpdateType\n}): boolean =>\n type === 'value' &&\n isEmptyConditionValue({ value: storedValue }) &&\n isEmptyConditionValue({ value: incomingValue })\n"],"mappings":"AAIA;;;GAIA,OAAO,MAAMA,qBAAA,GAAwBA,CAAC;EAAEC;AAAK,CAAsB,KACjEA,KAAA,KAAUC,SAAA,IAAaD,KAAA,KAAU,QAAQA,KAAA,KAAU;AAErD;;;;AAIA,OAAO,MAAME,0BAAA,GAA6BA,CAAI;EAAEF;AAAK,CAAgB,KACnEA,KAAA,IAASC,SAAA;AAEX;;;;;;;;;AASA,OAAO,MAAME,0BAAA,GAA6BA,CAAC;EACzCC,IAAI;EACJC,aAAa;EACbC;AAAW,CAKZ,KACCF,IAAA,KAAS,WACTL,qBAAA,CAAsB;EAAEC,KAAA,EAAOM;AAAY,MAC3CP,qBAAA,CAAsB;EAAEC,KAAA,EAAOK;AAAc","ignoreList":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getDisplayedConditionValue, isEmptyConditionValue, isNoOpConditionValueUpdate } from './conditionValue.js';
|
|
3
|
+
describe('isEmptyConditionValue', () => {
|
|
4
|
+
it.each([['undefined', undefined], ['null', null], ['an empty string', '']])('should treat %s as empty', (_label, value) => {
|
|
5
|
+
expect(isEmptyConditionValue({
|
|
6
|
+
value
|
|
7
|
+
})).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
it.each([['a string', 'option1'], ['zero', 0], ['false', false]])('should treat %s as a real value', (_label, value) => {
|
|
10
|
+
expect(isEmptyConditionValue({
|
|
11
|
+
value
|
|
12
|
+
})).toBe(false);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('getDisplayedConditionValue', () => {
|
|
16
|
+
it.each([['undefined', undefined], ['null', null]])('should display %s as no value', (_label, value) => {
|
|
17
|
+
expect(getDisplayedConditionValue({
|
|
18
|
+
value
|
|
19
|
+
})).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
it.each([['zero', 0], ['false', false], ['an empty string', ''], ['a string', 'option1']])('should display %s as itself', (_label, value) => {
|
|
22
|
+
expect(getDisplayedConditionValue({
|
|
23
|
+
value
|
|
24
|
+
})).toBe(value);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('isNoOpConditionValueUpdate', () => {
|
|
28
|
+
it('should skip the empty value a row reports back for a stored empty string', () => {
|
|
29
|
+
// The row this covers comes from a URL such as `?where[or][0][and][0][field][equals]=`.
|
|
30
|
+
expect(isNoOpConditionValueUpdate({
|
|
31
|
+
incomingValue: undefined,
|
|
32
|
+
storedValue: '',
|
|
33
|
+
type: 'value'
|
|
34
|
+
})).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it.each([['undefined', 'an empty string', undefined, ''], ['null', 'undefined', null, undefined], ['undefined', 'undefined', undefined, undefined]])('should skip a %s value stored as %s', (_incomingLabel, _storedLabel, incomingValue, storedValue) => {
|
|
37
|
+
expect(isNoOpConditionValueUpdate({
|
|
38
|
+
incomingValue,
|
|
39
|
+
storedValue,
|
|
40
|
+
type: 'value'
|
|
41
|
+
})).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
it('should commit a value typed into an empty row', () => {
|
|
44
|
+
expect(isNoOpConditionValueUpdate({
|
|
45
|
+
incomingValue: 'option1',
|
|
46
|
+
storedValue: '',
|
|
47
|
+
type: 'value'
|
|
48
|
+
})).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it('should commit a row the user cleared', () => {
|
|
51
|
+
expect(isNoOpConditionValueUpdate({
|
|
52
|
+
incomingValue: undefined,
|
|
53
|
+
storedValue: 'option1',
|
|
54
|
+
type: 'value'
|
|
55
|
+
})).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it.each([['field'], ['operator']])('should commit a %s edit on a row that holds no value', type => {
|
|
58
|
+
expect(isNoOpConditionValueUpdate({
|
|
59
|
+
incomingValue: undefined,
|
|
60
|
+
storedValue: '',
|
|
61
|
+
type
|
|
62
|
+
})).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=conditionValue.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditionValue.spec.js","names":["describe","expect","it","getDisplayedConditionValue","isEmptyConditionValue","isNoOpConditionValueUpdate","each","undefined","_label","value","toBe","toBeUndefined","incomingValue","storedValue","type","_incomingLabel","_storedLabel"],"sources":["../../../src/elements/WhereBuilder/conditionValue.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport {\n getDisplayedConditionValue,\n isEmptyConditionValue,\n isNoOpConditionValueUpdate,\n} from './conditionValue.js'\n\ndescribe('isEmptyConditionValue', () => {\n it.each([\n ['undefined', undefined],\n ['null', null],\n ['an empty string', ''],\n ])('should treat %s as empty', (_label, value) => {\n expect(isEmptyConditionValue({ value })).toBe(true)\n })\n\n it.each([\n ['a string', 'option1'],\n ['zero', 0],\n ['false', false],\n ])('should treat %s as a real value', (_label, value) => {\n expect(isEmptyConditionValue({ value })).toBe(false)\n })\n})\n\ndescribe('getDisplayedConditionValue', () => {\n it.each([\n ['undefined', undefined],\n ['null', null],\n ])('should display %s as no value', (_label, value) => {\n expect(getDisplayedConditionValue({ value })).toBeUndefined()\n })\n\n it.each([\n ['zero', 0],\n ['false', false],\n ['an empty string', ''],\n ['a string', 'option1'],\n ])('should display %s as itself', (_label, value) => {\n expect(getDisplayedConditionValue({ value })).toBe(value)\n })\n})\n\ndescribe('isNoOpConditionValueUpdate', () => {\n it('should skip the empty value a row reports back for a stored empty string', () => {\n // The row this covers comes from a URL such as `?where[or][0][and][0][field][equals]=`.\n expect(\n isNoOpConditionValueUpdate({ incomingValue: undefined, storedValue: '', type: 'value' }),\n ).toBe(true)\n })\n\n it.each([\n ['undefined', 'an empty string', undefined, ''],\n ['null', 'undefined', null, undefined],\n ['undefined', 'undefined', undefined, undefined],\n ])(\n 'should skip a %s value stored as %s',\n (_incomingLabel, _storedLabel, incomingValue, storedValue) => {\n expect(isNoOpConditionValueUpdate({ incomingValue, storedValue, type: 'value' })).toBe(true)\n },\n )\n\n it('should commit a value typed into an empty row', () => {\n expect(\n isNoOpConditionValueUpdate({ incomingValue: 'option1', storedValue: '', type: 'value' }),\n ).toBe(false)\n })\n\n it('should commit a row the user cleared', () => {\n expect(\n isNoOpConditionValueUpdate({\n incomingValue: undefined,\n storedValue: 'option1',\n type: 'value',\n }),\n ).toBe(false)\n })\n\n it.each([['field'], ['operator']] as const)(\n 'should commit a %s edit on a row that holds no value',\n (type) => {\n expect(isNoOpConditionValueUpdate({ incomingValue: undefined, storedValue: '', type })).toBe(\n false,\n )\n },\n )\n})\n"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ;AAErC,SACEC,0BAA0B,EAC1BC,qBAAqB,EACrBC,0BAA0B,QACrB;AAEPL,QAAA,CAAS,yBAAyB;EAChCE,EAAA,CAAGI,IAAI,CAAC,CACN,CAAC,aAAaC,SAAA,CAAU,EACxB,CAAC,QAAQ,KAAK,EACd,CAAC,mBAAmB,GAAG,CACxB,EAAE,4BAA4B,CAACC,MAAA,EAAQC,KAAA;IACtCR,MAAA,CAAOG,qBAAA,CAAsB;MAAEK;IAAM,IAAIC,IAAI,CAAC;EAChD;EAEAR,EAAA,CAAGI,IAAI,CAAC,CACN,CAAC,YAAY,UAAU,EACvB,CAAC,QAAQ,EAAE,EACX,CAAC,SAAS,MAAM,CACjB,EAAE,mCAAmC,CAACE,MAAA,EAAQC,KAAA;IAC7CR,MAAA,CAAOG,qBAAA,CAAsB;MAAEK;IAAM,IAAIC,IAAI,CAAC;EAChD;AACF;AAEAV,QAAA,CAAS,8BAA8B;EACrCE,EAAA,CAAGI,IAAI,CAAC,CACN,CAAC,aAAaC,SAAA,CAAU,EACxB,CAAC,QAAQ,KAAK,CACf,EAAE,iCAAiC,CAACC,MAAA,EAAQC,KAAA;IAC3CR,MAAA,CAAOE,0BAAA,CAA2B;MAAEM;IAAM,IAAIE,aAAa;EAC7D;EAEAT,EAAA,CAAGI,IAAI,CAAC,CACN,CAAC,QAAQ,EAAE,EACX,CAAC,SAAS,MAAM,EAChB,CAAC,mBAAmB,GAAG,EACvB,CAAC,YAAY,UAAU,CACxB,EAAE,+BAA+B,CAACE,MAAA,EAAQC,KAAA;IACzCR,MAAA,CAAOE,0BAAA,CAA2B;MAAEM;IAAM,IAAIC,IAAI,CAACD,KAAA;EACrD;AACF;AAEAT,QAAA,CAAS,8BAA8B;EACrCE,EAAA,CAAG,4EAA4E;IAC7E;IACAD,MAAA,CACEI,0BAAA,CAA2B;MAAEO,aAAA,EAAeL,SAAA;MAAWM,WAAA,EAAa;MAAIC,IAAA,EAAM;IAAQ,IACtFJ,IAAI,CAAC;EACT;EAEAR,EAAA,CAAGI,IAAI,CAAC,CACN,CAAC,aAAa,mBAAmBC,SAAA,EAAW,GAAG,EAC/C,CAAC,QAAQ,aAAa,MAAMA,SAAA,CAAU,EACtC,CAAC,aAAa,aAAaA,SAAA,EAAWA,SAAA,CAAU,CACjD,EACC,uCACA,CAACQ,cAAA,EAAgBC,YAAA,EAAcJ,aAAA,EAAeC,WAAA;IAC5CZ,MAAA,CAAOI,0BAAA,CAA2B;MAAEO,aAAA;MAAeC,WAAA;MAAaC,IAAA,EAAM;IAAQ,IAAIJ,IAAI,CAAC;EACzF;EAGFR,EAAA,CAAG,iDAAiD;IAClDD,MAAA,CACEI,0BAAA,CAA2B;MAAEO,aAAA,EAAe;MAAWC,WAAA,EAAa;MAAIC,IAAA,EAAM;IAAQ,IACtFJ,IAAI,CAAC;EACT;EAEAR,EAAA,CAAG,wCAAwC;IACzCD,MAAA,CACEI,0BAAA,CAA2B;MACzBO,aAAA,EAAeL,SAAA;MACfM,WAAA,EAAa;MACbC,IAAA,EAAM;IACR,IACAJ,IAAI,CAAC;EACT;EAEAR,EAAA,CAAGI,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,EAC/B,wDACCQ,IAAA;IACCb,MAAA,CAAOI,0BAAA,CAA2B;MAAEO,aAAA,EAAeL,SAAA;MAAWM,WAAA,EAAa;MAAIC;IAAK,IAAIJ,IAAI,CAC1F;EAEJ;AAEJ","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/WhereBuilder/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAKV,iBAAiB,EAClB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/WhereBuilder/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAKV,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAanB,OAAO,aAAa,CAAA;AAKpB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6RpD,CAAA"}
|
|
@@ -10,6 +10,7 @@ import { useTranslation } from '../../providers/Translation/index.js';
|
|
|
10
10
|
import { reduceFieldsToOptions } from '../../utilities/reduceFieldsToOptions.js';
|
|
11
11
|
import { Button } from '../Button/index.js';
|
|
12
12
|
import { Condition } from './Condition/index.js';
|
|
13
|
+
import { getDisplayedConditionValue, isEmptyConditionValue, isNoOpConditionValueUpdate } from './conditionValue.js';
|
|
13
14
|
import './index.css';
|
|
14
15
|
import { fieldTypeConditions, getValidFieldOperators } from './field-types.js';
|
|
15
16
|
const baseClass = 'where-builder';
|
|
@@ -92,9 +93,10 @@ export const WhereBuilder = props => {
|
|
|
92
93
|
}) => {
|
|
93
94
|
// Virtual first row: conditions not yet committed, build from scratch
|
|
94
95
|
if (conditions.length === 0) {
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
// Field and operator picks carry empty values too, but must fall through to build the row.
|
|
97
|
+
if (type === 'value' && isEmptyConditionValue({
|
|
98
|
+
value: value_0
|
|
99
|
+
})) {
|
|
98
100
|
return;
|
|
99
101
|
}
|
|
100
102
|
const {
|
|
@@ -127,6 +129,13 @@ export const WhereBuilder = props => {
|
|
|
127
129
|
if (typeof existingValue !== 'undefined' && existingValue === value_0) {
|
|
128
130
|
return;
|
|
129
131
|
}
|
|
132
|
+
if (isNoOpConditionValueUpdate({
|
|
133
|
+
type,
|
|
134
|
+
incomingValue: value_0,
|
|
135
|
+
storedValue: existingValue
|
|
136
|
+
})) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
130
139
|
const newRowCondition = {
|
|
131
140
|
[String(field_0.fieldPath)]: {
|
|
132
141
|
[validOperator_0]: value_0
|
|
@@ -250,7 +259,9 @@ export const WhereBuilder = props => {
|
|
|
250
259
|
const condition = displayConditions[orIndex_3].and[andIndex_3];
|
|
251
260
|
const fieldPath = Object.keys(condition)[0];
|
|
252
261
|
const operator = Object.keys(condition?.[fieldPath] || {})?.[0] || undefined;
|
|
253
|
-
const value_1 =
|
|
262
|
+
const value_1 = getDisplayedConditionValue({
|
|
263
|
+
value: condition?.[fieldPath]?.[operator]
|
|
264
|
+
});
|
|
254
265
|
const isFirstCondition = orIndex_3 === 0 && andIndex_3 === 0;
|
|
255
266
|
const join_0 = andIndex_3 === 0 ? 'or' : 'and';
|
|
256
267
|
return /*#__PURE__*/_jsx(Condition, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["dequal","isFieldDisabled","transformWhereQuery","validateWhereQuery","React","useMemo","CirclePlusIcon","useAuth","useTranslation","reduceFieldsToOptions","Button","Condition","fieldTypeConditions","getValidFieldOperators","baseClass","WhereBuilder","props","collectionSlug","fields","onChange","handleWhereChange","onEmptyRemove","renderedFilters","undefined","resolvedFilterOptions","value","i18n","t","permissions","fieldPermissions","collections","reducedFields","firstField","find","f","field","conditions","or","transformedWhere","addCondition","useCallback","andIndex","orIndex","relation","newConditions","structuredClone","defaultOperator","type","operators","and","splice","String","fieldPath","push","updateCondition","operator","incomingOperator","length","validOperator","existingCondition","existingValue","newRowCondition","removeCondition","updateJoin","join","flattened","forEach","orGroup","oIdx","cond","aIdx","isTarget","currentJoin","itemJoin","index","addFirstFilter","makeRow","displayConditions","disableRemoveButton","_jsx","className","_jsxs","map","compoundOrKey","Array","isArray","_","condition","Object","keys","isFirstCondition","filterOptions","get","RenderedFilter","buttonStyle","icon","size","iconPosition","onClick"],"sources":["../../../src/elements/WhereBuilder/index.tsx"],"sourcesContent":["'use client'\nimport type { Operator } from 'payload'\n\nimport { dequal } from 'dequal/lite'\nimport { isFieldDisabled, transformWhereQuery, validateWhereQuery } from 'payload/shared'\nimport React, { useMemo } from 'react'\n\nimport type {\n AddCondition,\n RemoveCondition,\n UpdateCondition,\n UpdateJoin,\n WhereBuilderProps,\n} from './types.js'\n\nimport { CirclePlusIcon } from '../../icons/CirclePlus/index.js'\nimport { useAuth } from '../../providers/Auth/index.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { reduceFieldsToOptions } from '../../utilities/reduceFieldsToOptions.js'\nimport { Button } from '../Button/index.js'\nimport { Condition } from './Condition/index.js'\nimport './index.css'\nimport { fieldTypeConditions, getValidFieldOperators } from './field-types.js'\n\nconst baseClass = 'where-builder'\n\nexport { WhereBuilderProps }\n\n/**\n * Presentational filter builder. It renders the conditions described by `value` and\n * reports edits through `onChange`. It is unaware of where its value is stored — the\n * list view wires it to list query state via {@link ListWhereBuilder}, and the Query\n * Presets drawer wires it to form state.\n */\nexport const WhereBuilder: React.FC<WhereBuilderProps> = (props) => {\n const {\n collectionSlug,\n fields,\n onChange: handleWhereChange,\n onEmptyRemove,\n renderedFilters = undefined,\n resolvedFilterOptions = undefined,\n value,\n } = props\n const { i18n, t } = useTranslation()\n const { permissions } = useAuth()\n\n const fieldPermissions = permissions?.collections?.[collectionSlug]?.fields\n\n const reducedFields = useMemo(\n () =>\n reduceFieldsToOptions({\n fieldPermissions,\n fields: fields ?? [],\n i18n,\n }),\n [fieldPermissions, fields, i18n],\n )\n\n const firstField = useMemo(\n () => reducedFields.find((f) => !isFieldDisabled(f.field, 'filter')),\n [reducedFields],\n )\n\n const conditions = useMemo(() => {\n if (value) {\n if (validateWhereQuery(value)) {\n return value.or ?? []\n }\n\n const transformedWhere = transformWhereQuery(value)\n if (validateWhereQuery(transformedWhere)) {\n return transformedWhere.or ?? []\n }\n }\n\n return []\n }, [value])\n\n const addCondition: AddCondition = React.useCallback(\n ({ andIndex, field, orIndex, relation }) => {\n const newConditions = structuredClone(conditions)\n\n const defaultOperator = fieldTypeConditions[field.field.type].operators[0].value\n\n if (relation === 'and') {\n newConditions[orIndex].and.splice(andIndex, 0, {\n [String(field.fieldPath)]: {\n [defaultOperator]: undefined,\n },\n })\n } else {\n newConditions.push({\n and: [\n {\n [String(field.fieldPath)]: {\n [defaultOperator]: undefined,\n },\n },\n ],\n })\n }\n\n void handleWhereChange({ or: newConditions })\n },\n [conditions, handleWhereChange],\n )\n\n const updateCondition: UpdateCondition = React.useCallback(\n ({ type, andIndex, field, operator: incomingOperator, orIndex, value }) => {\n // Virtual first row: conditions not yet committed, build from scratch\n if (conditions.length === 0) {\n // Ignore empty value edits so a cleared row doesn't re-commit itself. Field and\n // operator picks carry empty values too, but must fall through to build the row.\n if (type === 'value' && (value === undefined || value === null || value === '')) {\n return\n }\n\n const { validOperator } = getValidFieldOperators({\n field: field.field,\n operator: incomingOperator,\n })\n void handleWhereChange({\n or: [{ and: [{ [String(field.fieldPath)]: { [validOperator]: value } }] }],\n })\n return\n }\n\n const existingCondition = conditions[orIndex].and[andIndex]\n\n if (typeof existingCondition === 'object' && field?.fieldPath) {\n const { validOperator } = getValidFieldOperators({\n field: field.field,\n operator: incomingOperator,\n })\n\n // Skip if nothing changed\n const existingValue = existingCondition[String(field.fieldPath)]?.[validOperator]\n if (typeof existingValue !== 'undefined' && existingValue === value) {\n return\n }\n\n const newRowCondition = {\n [String(field.fieldPath)]: { [validOperator]: value },\n }\n\n if (dequal(existingCondition, newRowCondition)) {\n return\n }\n\n const newConditions = structuredClone(conditions)\n newConditions[orIndex].and[andIndex] = newRowCondition\n\n void handleWhereChange({ or: newConditions })\n }\n },\n [conditions, handleWhereChange],\n )\n\n const removeCondition: RemoveCondition = React.useCallback(\n ({ andIndex, orIndex }) => {\n // Virtual first row: removing it just closes the panel\n if (conditions.length === 0) {\n onEmptyRemove?.()\n return\n }\n\n const newConditions = structuredClone(conditions)\n newConditions[orIndex].and.splice(andIndex, 1)\n\n if (newConditions[orIndex].and.length === 0) {\n newConditions.splice(orIndex, 1)\n }\n\n void handleWhereChange({ or: newConditions })\n\n // Removing the last remaining condition closes the filters panel.\n if (newConditions.length === 0) {\n onEmptyRemove?.()\n }\n },\n [conditions, handleWhereChange, onEmptyRemove],\n )\n\n const updateJoin: UpdateJoin = React.useCallback(\n ({ andIndex, join, orIndex }) => {\n // Flatten the nested or/and structure into a single ordered list, tracking\n // the join relation that connects each condition to the previous one.\n const flattened: { cond: (typeof conditions)[number]['and'][number]; join: 'and' | 'or' }[] =\n []\n\n conditions.forEach((orGroup, oIdx) => {\n orGroup.and.forEach((cond, aIdx) => {\n const isTarget = oIdx === orIndex && aIdx === andIndex\n const currentJoin = flattened.length === 0 ? null : aIdx === 0 ? 'or' : 'and'\n\n flattened.push({ cond, join: isTarget ? join : currentJoin })\n })\n })\n\n // Rebuild the or/and structure from the flattened list using the join relations.\n const newConditions: typeof conditions = []\n\n flattened.forEach(({ cond, join: itemJoin }, index) => {\n if (index === 0 || itemJoin === 'or') {\n newConditions.push({ and: [cond] })\n } else {\n newConditions[newConditions.length - 1].and.push(cond)\n }\n })\n\n void handleWhereChange({ or: newConditions })\n },\n [conditions, handleWhereChange],\n )\n\n const addFirstFilter = React.useCallback(() => {\n if (!firstField) {\n return\n }\n\n // With no committed conditions, only the virtual placeholder row is shown. Commit it\n // and append a new row so a second row appears on the first click.\n if (conditions.length === 0) {\n const defaultOperator = firstField.operators[0].value\n const makeRow = () => ({\n and: [{ [String(firstField.fieldPath)]: { [defaultOperator]: undefined } }],\n })\n\n void handleWhereChange({ or: [makeRow(), makeRow()] })\n return\n }\n\n void addCondition({\n andIndex: 0,\n field: firstField,\n orIndex: conditions.length,\n relation: 'or',\n })\n }, [addCondition, conditions.length, firstField, handleWhereChange])\n\n // When conditions is empty, show a virtual first row so the panel never opens blank.\n const displayConditions =\n conditions.length === 0 && firstField\n ? ([\n { and: [{ [firstField.fieldPath]: { [firstField.operators[0].value]: undefined } }] },\n ] as typeof conditions)\n : conditions\n\n // Disable the remove button only when there are no committed conditions and this host\n // doesn't provide an empty-state removal handler.\n const disableRemoveButton = conditions.length === 0 && !onEmptyRemove\n\n return (\n <div className={baseClass}>\n <div className={`${baseClass}__or-filters`}>\n {displayConditions.map((or, orIndex) => {\n const compoundOrKey = `${orIndex}_${Array.isArray(or?.and) ? or.and.length : ''}`\n\n return (\n <div className={`${baseClass}__and-filters`} key={compoundOrKey}>\n {Array.isArray(or?.and) &&\n or.and.map((_, andIndex) => {\n const condition = displayConditions[orIndex].and[andIndex]\n const fieldPath = Object.keys(condition)[0]\n\n const operator =\n (Object.keys(condition?.[fieldPath] || {})?.[0] as Operator) || undefined\n\n const value = condition?.[fieldPath]?.[operator] || undefined\n\n const isFirstCondition = orIndex === 0 && andIndex === 0\n const join: 'and' | 'or' = andIndex === 0 ? 'or' : 'and'\n\n return (\n <Condition\n addCondition={addCondition}\n andIndex={andIndex}\n disableRemoveButton={disableRemoveButton}\n fieldPath={fieldPath}\n filterOptions={resolvedFilterOptions?.get(fieldPath)}\n isFirstCondition={isFirstCondition}\n join={join}\n key={andIndex}\n operator={operator}\n orIndex={orIndex}\n reducedFields={reducedFields}\n removeCondition={removeCondition}\n RenderedFilter={renderedFilters?.get(fieldPath)}\n updateCondition={updateCondition}\n updateJoin={updateJoin}\n value={value}\n />\n )\n })}\n </div>\n )\n })}\n <div className={`${baseClass}__add-or-row`}>\n <Button\n buttonStyle=\"ghost\"\n className={`${baseClass}__add-or`}\n icon={<CirclePlusIcon size={24} />}\n iconPosition=\"left\"\n onClick={addFirstFilter}\n >\n {t('general:addFilter')}\n </Button>\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"AAAA;;;AAGA,SAASA,MAAM,QAAQ;AACvB,SAASC,eAAe,EAAEC,mBAAmB,EAAEC,kBAAkB,QAAQ;AACzE,OAAOC,KAAA,IAASC,OAAO,QAAQ;AAU/B,SAASC,cAAc,QAAQ;AAC/B,SAASC,OAAO,QAAQ;AACxB,SAASC,cAAc,QAAQ;AAC/B,SAASC,qBAAqB,QAAQ;AACtC,SAASC,MAAM,QAAQ;AACvB,SAASC,SAAS,QAAQ;AAC1B,OAAO;AACP,SAASC,mBAAmB,EAAEC,sBAAsB,QAAQ;AAE5D,MAAMC,SAAA,GAAY;AAIlB;;;;;;AAMA,OAAO,MAAMC,YAAA,GAA6CC,KAAA;EACxD,MAAM;IACJC,cAAc;IACdC,MAAM;IACNC,QAAA,EAAUC,iBAAiB;IAC3BC,aAAa;IACbC,eAAA,GAAkBC,SAAS;IAC3BC,qBAAA,GAAwBD,SAAS;IACjCE;EAAK,CACN,GAAGT,KAAA;EACJ,MAAM;IAAEU,IAAI;IAAEC;EAAC,CAAE,GAAGnB,cAAA;EACpB,MAAM;IAAEoB;EAAW,CAAE,GAAGrB,OAAA;EAExB,MAAMsB,gBAAA,GAAmBD,WAAA,EAAaE,WAAA,GAAcb,cAAA,CAAe,EAAEC,MAAA;EAErE,MAAMa,aAAA,GAAgB1B,OAAA,CACpB,MACEI,qBAAA,CAAsB;IACpBoB,gBAAA;IACAX,MAAA,EAAQA,MAAA,IAAU,EAAE;IACpBQ;EACF,IACF,CAACG,gBAAA,EAAkBX,MAAA,EAAQQ,IAAA,CAAK;EAGlC,MAAMM,UAAA,GAAa3B,OAAA,CACjB,MAAM0B,aAAA,CAAcE,IAAI,CAAEC,CAAA,IAAM,CAACjC,eAAA,CAAgBiC,CAAA,CAAEC,KAAK,EAAE,YAC1D,CAACJ,aAAA,CAAc;EAGjB,MAAMK,UAAA,GAAa/B,OAAA,CAAQ;IACzB,IAAIoB,KAAA,EAAO;MACT,IAAItB,kBAAA,CAAmBsB,KAAA,GAAQ;QAC7B,OAAOA,KAAA,CAAMY,EAAE,IAAI,EAAE;MACvB;MAEA,MAAMC,gBAAA,GAAmBpC,mBAAA,CAAoBuB,KAAA;MAC7C,IAAItB,kBAAA,CAAmBmC,gBAAA,GAAmB;QACxC,OAAOA,gBAAA,CAAiBD,EAAE,IAAI,EAAE;MAClC;IACF;IAEA,OAAO,EAAE;EACX,GAAG,CAACZ,KAAA,CAAM;EAEV,MAAMc,YAAA,GAA6BnC,KAAA,CAAMoC,WAAW,CAClD,CAAC;IAAEC,QAAQ;IAAEN,KAAK;IAAEO,OAAO;IAAEC;EAAQ,CAAE;IACrC,MAAMC,aAAA,GAAgBC,eAAA,CAAgBT,UAAA;IAEtC,MAAMU,eAAA,GAAkBlC,mBAAmB,CAACuB,KAAA,CAAMA,KAAK,CAACY,IAAI,CAAC,CAACC,SAAS,CAAC,EAAE,CAACvB,KAAK;IAEhF,IAAIkB,QAAA,KAAa,OAAO;MACtBC,aAAa,CAACF,OAAA,CAAQ,CAACO,GAAG,CAACC,MAAM,CAACT,QAAA,EAAU,GAAG;QAC7C,CAACU,MAAA,CAAOhB,KAAA,CAAMiB,SAAS,IAAI;UACzB,CAACN,eAAA,GAAkBvB;QACrB;MACF;IACF,OAAO;MACLqB,aAAA,CAAcS,IAAI,CAAC;QACjBJ,GAAA,EAAK,CACH;UACE,CAACE,MAAA,CAAOhB,KAAA,CAAMiB,SAAS,IAAI;YACzB,CAACN,eAAA,GAAkBvB;UACrB;QACF;MAEJ;IACF;IAEA,KAAKH,iBAAA,CAAkB;MAAEiB,EAAA,EAAIO;IAAc;EAC7C,GACA,CAACR,UAAA,EAAYhB,iBAAA,CAAkB;EAGjC,MAAMkC,eAAA,GAAmClD,KAAA,CAAMoC,WAAW,CACxD,CAAC;IAAEO,IAAI;IAAEN,QAAQ,EAARA,UAAQ;IAAEN,KAAK,EAALA,OAAK;IAAEoB,QAAA,EAAUC,gBAAgB;IAAEd,OAAO,EAAPA,SAAO;IAAEjB,KAAK,EAALA;EAAK,CAAE;IACpE;IACA,IAAIW,UAAA,CAAWqB,MAAM,KAAK,GAAG;MAC3B;MACA;MACA,IAAIV,IAAA,KAAS,YAAYtB,OAAA,KAAUF,SAAA,IAAaE,OAAA,KAAU,QAAQA,OAAA,KAAU,EAAC,GAAI;QAC/E;MACF;MAEA,MAAM;QAAEiC;MAAa,CAAE,GAAG7C,sBAAA,CAAuB;QAC/CsB,KAAA,EAAOA,OAAA,CAAMA,KAAK;QAClBoB,QAAA,EAAUC;MACZ;MACA,KAAKpC,iBAAA,CAAkB;QACrBiB,EAAA,EAAI,CAAC;UAAEY,GAAA,EAAK,CAAC;YAAE,CAACE,MAAA,CAAOhB,OAAA,CAAMiB,SAAS,IAAI;cAAE,CAACM,aAAA,GAAgBjC;YAAM;UAAE;QAAG;MAC1E;MACA;IACF;IAEA,MAAMkC,iBAAA,GAAoBvB,UAAU,CAACM,SAAA,CAAQ,CAACO,GAAG,CAACR,UAAA,CAAS;IAE3D,IAAI,OAAOkB,iBAAA,KAAsB,YAAYxB,OAAA,EAAOiB,SAAA,EAAW;MAC7D,MAAM;QAAEM,aAAa,EAAbA;MAAa,CAAE,GAAG7C,sBAAA,CAAuB;QAC/CsB,KAAA,EAAOA,OAAA,CAAMA,KAAK;QAClBoB,QAAA,EAAUC;MACZ;MAEA;MACA,MAAMI,aAAA,GAAgBD,iBAAiB,CAACR,MAAA,CAAOhB,OAAA,CAAMiB,SAAS,EAAE,GAAGM,eAAA,CAAc;MACjF,IAAI,OAAOE,aAAA,KAAkB,eAAeA,aAAA,KAAkBnC,OAAA,EAAO;QACnE;MACF;MAEA,MAAMoC,eAAA,GAAkB;QACtB,CAACV,MAAA,CAAOhB,OAAA,CAAMiB,SAAS,IAAI;UAAE,CAACM,eAAA,GAAgBjC;QAAM;MACtD;MAEA,IAAIzB,MAAA,CAAO2D,iBAAA,EAAmBE,eAAA,GAAkB;QAC9C;MACF;MAEA,MAAMjB,eAAA,GAAgBC,eAAA,CAAgBT,UAAA;MACtCQ,eAAa,CAACF,SAAA,CAAQ,CAACO,GAAG,CAACR,UAAA,CAAS,GAAGoB,eAAA;MAEvC,KAAKzC,iBAAA,CAAkB;QAAEiB,EAAA,EAAIO;MAAc;IAC7C;EACF,GACA,CAACR,UAAA,EAAYhB,iBAAA,CAAkB;EAGjC,MAAM0C,eAAA,GAAmC1D,KAAA,CAAMoC,WAAW,CACxD,CAAC;IAAEC,QAAQ,EAARA,UAAQ;IAAEC,OAAO,EAAPA;EAAO,CAAE;IACpB;IACA,IAAIN,UAAA,CAAWqB,MAAM,KAAK,GAAG;MAC3BpC,aAAA;MACA;IACF;IAEA,MAAMuB,eAAA,GAAgBC,eAAA,CAAgBT,UAAA;IACtCQ,eAAa,CAACF,SAAA,CAAQ,CAACO,GAAG,CAACC,MAAM,CAACT,UAAA,EAAU;IAE5C,IAAIG,eAAa,CAACF,SAAA,CAAQ,CAACO,GAAG,CAACQ,MAAM,KAAK,GAAG;MAC3Cb,eAAA,CAAcM,MAAM,CAACR,SAAA,EAAS;IAChC;IAEA,KAAKtB,iBAAA,CAAkB;MAAEiB,EAAA,EAAIO;IAAc;IAE3C;IACA,IAAIA,eAAA,CAAca,MAAM,KAAK,GAAG;MAC9BpC,aAAA;IACF;EACF,GACA,CAACe,UAAA,EAAYhB,iBAAA,EAAmBC,aAAA,CAAc;EAGhD,MAAM0C,UAAA,GAAyB3D,KAAA,CAAMoC,WAAW,CAC9C,CAAC;IAAEC,QAAQ,EAARA,UAAQ;IAAEuB,IAAI;IAAEtB,OAAO,EAAPA;EAAO,CAAE;IAC1B;IACA;IACA,MAAMuB,SAAA,GACJ,EAAE;IAEJ7B,UAAA,CAAW8B,OAAO,CAAC,CAACC,OAAA,EAASC,IAAA;MAC3BD,OAAA,CAAQlB,GAAG,CAACiB,OAAO,CAAC,CAACG,IAAA,EAAMC,IAAA;QACzB,MAAMC,QAAA,GAAWH,IAAA,KAAS1B,SAAA,IAAW4B,IAAA,KAAS7B,UAAA;QAC9C,MAAM+B,WAAA,GAAcP,SAAA,CAAUR,MAAM,KAAK,IAAI,OAAOa,IAAA,KAAS,IAAI,OAAO;QAExEL,SAAA,CAAUZ,IAAI,CAAC;UAAEgB,IAAA;UAAML,IAAA,EAAMO,QAAA,GAAWP,IAAA,GAAOQ;QAAY;MAC7D;IACF;IAEA;IACA,MAAM5B,eAAA,GAAmC,EAAE;IAE3CqB,SAAA,CAAUC,OAAO,CAAC,CAAC;MAAEG,IAAI,EAAJA,MAAI;MAAEL,IAAA,EAAMS;IAAQ,CAAE,EAAEC,KAAA;MAC3C,IAAIA,KAAA,KAAU,KAAKD,QAAA,KAAa,MAAM;QACpC7B,eAAA,CAAcS,IAAI,CAAC;UAAEJ,GAAA,EAAK,CAACoB,MAAA;QAAM;MACnC,OAAO;QACLzB,eAAa,CAACA,eAAA,CAAca,MAAM,GAAG,EAAE,CAACR,GAAG,CAACI,IAAI,CAACgB,MAAA;MACnD;IACF;IAEA,KAAKjD,iBAAA,CAAkB;MAAEiB,EAAA,EAAIO;IAAc;EAC7C,GACA,CAACR,UAAA,EAAYhB,iBAAA,CAAkB;EAGjC,MAAMuD,cAAA,GAAiBvE,KAAA,CAAMoC,WAAW,CAAC;IACvC,IAAI,CAACR,UAAA,EAAY;MACf;IACF;IAEA;IACA;IACA,IAAII,UAAA,CAAWqB,MAAM,KAAK,GAAG;MAC3B,MAAMX,iBAAA,GAAkBd,UAAA,CAAWgB,SAAS,CAAC,EAAE,CAACvB,KAAK;MACrD,MAAMmD,OAAA,GAAUA,CAAA,MAAO;QACrB3B,GAAA,EAAK,CAAC;UAAE,CAACE,MAAA,CAAOnB,UAAA,CAAWoB,SAAS,IAAI;YAAE,CAACN,iBAAA,GAAkBvB;UAAU;QAAE;MAC3E;MAEA,KAAKH,iBAAA,CAAkB;QAAEiB,EAAA,EAAI,CAACuC,OAAA,IAAWA,OAAA;MAAW;MACpD;IACF;IAEA,KAAKrC,YAAA,CAAa;MAChBE,QAAA,EAAU;MACVN,KAAA,EAAOH,UAAA;MACPU,OAAA,EAASN,UAAA,CAAWqB,MAAM;MAC1Bd,QAAA,EAAU;IACZ;EACF,GAAG,CAACJ,YAAA,EAAcH,UAAA,CAAWqB,MAAM,EAAEzB,UAAA,EAAYZ,iBAAA,CAAkB;EAEnE;EACA,MAAMyD,iBAAA,GACJzC,UAAA,CAAWqB,MAAM,KAAK,KAAKzB,UAAA,GACtB,CACC;IAAEiB,GAAA,EAAK,CAAC;MAAE,CAACjB,UAAA,CAAWoB,SAAS,GAAG;QAAE,CAACpB,UAAA,CAAWgB,SAAS,CAAC,EAAE,CAACvB,KAAK,GAAGF;MAAU;IAAE;EAAG,EACrF,GACDa,UAAA;EAEN;EACA;EACA,MAAM0C,mBAAA,GAAsB1C,UAAA,CAAWqB,MAAM,KAAK,KAAK,CAACpC,aAAA;EAExD,oBACE0D,IAAA,CAAC;IAAIC,SAAA,EAAWlE,SAAA;cACd,aAAAmE,KAAA,CAAC;MAAID,SAAA,EAAW,GAAGlE,SAAA,cAAuB;iBACvC+D,iBAAA,CAAkBK,GAAG,CAAC,CAAC7C,EAAA,EAAIK,SAAA;QAC1B,MAAMyC,aAAA,GAAgB,GAAGzC,SAAA,IAAW0C,KAAA,CAAMC,OAAO,CAAChD,EAAA,EAAIY,GAAA,IAAOZ,EAAA,CAAGY,GAAG,CAACQ,MAAM,GAAG,IAAI;QAEjF,oBACEsB,IAAA,CAAC;UAAIC,SAAA,EAAW,GAAGlE,SAAA,eAAwB;oBACxCsE,KAAA,CAAMC,OAAO,CAAChD,EAAA,EAAIY,GAAA,KACjBZ,EAAA,CAAGY,GAAG,CAACiC,GAAG,CAAC,CAACI,CAAA,EAAG7C,UAAA;YACb,MAAM8C,SAAA,GAAYV,iBAAiB,CAACnC,SAAA,CAAQ,CAACO,GAAG,CAACR,UAAA,CAAS;YAC1D,MAAMW,SAAA,GAAYoC,MAAA,CAAOC,IAAI,CAACF,SAAA,CAAU,CAAC,EAAE;YAE3C,MAAMhC,QAAA,GACJiC,MAAC,CAAOC,IAAI,CAACF,SAAA,GAAYnC,SAAA,CAAU,IAAI,CAAC,KAAK,EAAE,IAAiB7B,SAAA;YAElE,MAAME,OAAA,GAAQ8D,SAAA,GAAYnC,SAAA,CAAU,GAAGG,QAAA,CAAS,IAAIhC,SAAA;YAEpD,MAAMmE,gBAAA,GAAmBhD,SAAA,KAAY,KAAKD,UAAA,KAAa;YACvD,MAAMuB,MAAA,GAAqBvB,UAAA,KAAa,IAAI,OAAO;YAEnD,oBACEsC,IAAA,CAACpE,SAAA;cACC4B,YAAA,EAAcA,YAAA;cACdE,QAAA,EAAUA,UAAA;cACVqC,mBAAA,EAAqBA,mBAAA;cACrB1B,SAAA,EAAWA,SAAA;cACXuC,aAAA,EAAenE,qBAAA,EAAuBoE,GAAA,CAAIxC,SAAA;cAC1CsC,gBAAA,EAAkBA,gBAAA;cAClB1B,IAAA,EAAMA,MAAA;cAENT,QAAA,EAAUA,QAAA;cACVb,OAAA,EAASA,SAAA;cACTX,aAAA,EAAeA,aAAA;cACf+B,eAAA,EAAiBA,eAAA;cACjB+B,cAAA,EAAgBvE,eAAA,EAAiBsE,GAAA,CAAIxC,SAAA;cACrCE,eAAA,EAAiBA,eAAA;cACjBS,UAAA,EAAYA,UAAA;cACZtC,KAAA,EAAOA;eARFgB,UAAA;UAWX;WAlC8C0C,aAAA;MAqCtD,I,aACAJ,IAAA,CAAC;QAAIC,SAAA,EAAW,GAAGlE,SAAA,cAAuB;kBACxC,aAAAiE,IAAA,CAACrE,MAAA;UACCoF,WAAA,EAAY;UACZd,SAAA,EAAW,GAAGlE,SAAA,UAAmB;UACjCiF,IAAA,eAAMhB,IAAA,CAACzE,cAAA;YAAe0F,IAAA,EAAM;;UAC5BC,YAAA,EAAa;UACbC,OAAA,EAASvB,cAAA;oBAERhD,CAAA,CAAE;;;;;AAMf","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["dequal","isFieldDisabled","transformWhereQuery","validateWhereQuery","React","useMemo","CirclePlusIcon","useAuth","useTranslation","reduceFieldsToOptions","Button","Condition","getDisplayedConditionValue","isEmptyConditionValue","isNoOpConditionValueUpdate","fieldTypeConditions","getValidFieldOperators","baseClass","WhereBuilder","props","collectionSlug","fields","onChange","handleWhereChange","onEmptyRemove","renderedFilters","undefined","resolvedFilterOptions","value","i18n","t","permissions","fieldPermissions","collections","reducedFields","firstField","find","f","field","conditions","or","transformedWhere","addCondition","useCallback","andIndex","orIndex","relation","newConditions","structuredClone","defaultOperator","type","operators","and","splice","String","fieldPath","push","updateCondition","operator","incomingOperator","length","validOperator","existingCondition","existingValue","incomingValue","storedValue","newRowCondition","removeCondition","updateJoin","join","flattened","forEach","orGroup","oIdx","cond","aIdx","isTarget","currentJoin","itemJoin","index","addFirstFilter","makeRow","displayConditions","disableRemoveButton","_jsx","className","_jsxs","map","compoundOrKey","Array","isArray","_","condition","Object","keys","isFirstCondition","filterOptions","get","RenderedFilter","buttonStyle","icon","size","iconPosition","onClick"],"sources":["../../../src/elements/WhereBuilder/index.tsx"],"sourcesContent":["'use client'\nimport type { Operator } from 'payload'\n\nimport { dequal } from 'dequal/lite'\nimport { isFieldDisabled, transformWhereQuery, validateWhereQuery } from 'payload/shared'\nimport React, { useMemo } from 'react'\n\nimport type {\n AddCondition,\n RemoveCondition,\n UpdateCondition,\n UpdateJoin,\n WhereBuilderProps,\n} from './types.js'\n\nimport { CirclePlusIcon } from '../../icons/CirclePlus/index.js'\nimport { useAuth } from '../../providers/Auth/index.js'\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { reduceFieldsToOptions } from '../../utilities/reduceFieldsToOptions.js'\nimport { Button } from '../Button/index.js'\nimport { Condition } from './Condition/index.js'\nimport {\n getDisplayedConditionValue,\n isEmptyConditionValue,\n isNoOpConditionValueUpdate,\n} from './conditionValue.js'\nimport './index.css'\nimport { fieldTypeConditions, getValidFieldOperators } from './field-types.js'\n\nconst baseClass = 'where-builder'\n\nexport { WhereBuilderProps }\n\n/**\n * Presentational filter builder. It renders the conditions described by `value` and\n * reports edits through `onChange`. It is unaware of where its value is stored — the\n * list view wires it to list query state via {@link ListWhereBuilder}, and the Query\n * Presets drawer wires it to form state.\n */\nexport const WhereBuilder: React.FC<WhereBuilderProps> = (props) => {\n const {\n collectionSlug,\n fields,\n onChange: handleWhereChange,\n onEmptyRemove,\n renderedFilters = undefined,\n resolvedFilterOptions = undefined,\n value,\n } = props\n const { i18n, t } = useTranslation()\n const { permissions } = useAuth()\n\n const fieldPermissions = permissions?.collections?.[collectionSlug]?.fields\n\n const reducedFields = useMemo(\n () =>\n reduceFieldsToOptions({\n fieldPermissions,\n fields: fields ?? [],\n i18n,\n }),\n [fieldPermissions, fields, i18n],\n )\n\n const firstField = useMemo(\n () => reducedFields.find((f) => !isFieldDisabled(f.field, 'filter')),\n [reducedFields],\n )\n\n const conditions = useMemo(() => {\n if (value) {\n if (validateWhereQuery(value)) {\n return value.or ?? []\n }\n\n const transformedWhere = transformWhereQuery(value)\n if (validateWhereQuery(transformedWhere)) {\n return transformedWhere.or ?? []\n }\n }\n\n return []\n }, [value])\n\n const addCondition: AddCondition = React.useCallback(\n ({ andIndex, field, orIndex, relation }) => {\n const newConditions = structuredClone(conditions)\n\n const defaultOperator = fieldTypeConditions[field.field.type].operators[0].value\n\n if (relation === 'and') {\n newConditions[orIndex].and.splice(andIndex, 0, {\n [String(field.fieldPath)]: {\n [defaultOperator]: undefined,\n },\n })\n } else {\n newConditions.push({\n and: [\n {\n [String(field.fieldPath)]: {\n [defaultOperator]: undefined,\n },\n },\n ],\n })\n }\n\n void handleWhereChange({ or: newConditions })\n },\n [conditions, handleWhereChange],\n )\n\n const updateCondition: UpdateCondition = React.useCallback(\n ({ type, andIndex, field, operator: incomingOperator, orIndex, value }) => {\n // Virtual first row: conditions not yet committed, build from scratch\n if (conditions.length === 0) {\n // Field and operator picks carry empty values too, but must fall through to build the row.\n if (type === 'value' && isEmptyConditionValue({ value })) {\n return\n }\n\n const { validOperator } = getValidFieldOperators({\n field: field.field,\n operator: incomingOperator,\n })\n void handleWhereChange({\n or: [{ and: [{ [String(field.fieldPath)]: { [validOperator]: value } }] }],\n })\n return\n }\n\n const existingCondition = conditions[orIndex].and[andIndex]\n\n if (typeof existingCondition === 'object' && field?.fieldPath) {\n const { validOperator } = getValidFieldOperators({\n field: field.field,\n operator: incomingOperator,\n })\n\n // Skip if nothing changed\n const existingValue = existingCondition[String(field.fieldPath)]?.[validOperator]\n if (typeof existingValue !== 'undefined' && existingValue === value) {\n return\n }\n\n if (\n isNoOpConditionValueUpdate({ type, incomingValue: value, storedValue: existingValue })\n ) {\n return\n }\n\n const newRowCondition = {\n [String(field.fieldPath)]: { [validOperator]: value },\n }\n\n if (dequal(existingCondition, newRowCondition)) {\n return\n }\n\n const newConditions = structuredClone(conditions)\n newConditions[orIndex].and[andIndex] = newRowCondition\n\n void handleWhereChange({ or: newConditions })\n }\n },\n [conditions, handleWhereChange],\n )\n\n const removeCondition: RemoveCondition = React.useCallback(\n ({ andIndex, orIndex }) => {\n // Virtual first row: removing it just closes the panel\n if (conditions.length === 0) {\n onEmptyRemove?.()\n return\n }\n\n const newConditions = structuredClone(conditions)\n newConditions[orIndex].and.splice(andIndex, 1)\n\n if (newConditions[orIndex].and.length === 0) {\n newConditions.splice(orIndex, 1)\n }\n\n void handleWhereChange({ or: newConditions })\n\n // Removing the last remaining condition closes the filters panel.\n if (newConditions.length === 0) {\n onEmptyRemove?.()\n }\n },\n [conditions, handleWhereChange, onEmptyRemove],\n )\n\n const updateJoin: UpdateJoin = React.useCallback(\n ({ andIndex, join, orIndex }) => {\n // Flatten the nested or/and structure into a single ordered list, tracking\n // the join relation that connects each condition to the previous one.\n const flattened: { cond: (typeof conditions)[number]['and'][number]; join: 'and' | 'or' }[] =\n []\n\n conditions.forEach((orGroup, oIdx) => {\n orGroup.and.forEach((cond, aIdx) => {\n const isTarget = oIdx === orIndex && aIdx === andIndex\n const currentJoin = flattened.length === 0 ? null : aIdx === 0 ? 'or' : 'and'\n\n flattened.push({ cond, join: isTarget ? join : currentJoin })\n })\n })\n\n // Rebuild the or/and structure from the flattened list using the join relations.\n const newConditions: typeof conditions = []\n\n flattened.forEach(({ cond, join: itemJoin }, index) => {\n if (index === 0 || itemJoin === 'or') {\n newConditions.push({ and: [cond] })\n } else {\n newConditions[newConditions.length - 1].and.push(cond)\n }\n })\n\n void handleWhereChange({ or: newConditions })\n },\n [conditions, handleWhereChange],\n )\n\n const addFirstFilter = React.useCallback(() => {\n if (!firstField) {\n return\n }\n\n // With no committed conditions, only the virtual placeholder row is shown. Commit it\n // and append a new row so a second row appears on the first click.\n if (conditions.length === 0) {\n const defaultOperator = firstField.operators[0].value\n const makeRow = () => ({\n and: [{ [String(firstField.fieldPath)]: { [defaultOperator]: undefined } }],\n })\n\n void handleWhereChange({ or: [makeRow(), makeRow()] })\n return\n }\n\n void addCondition({\n andIndex: 0,\n field: firstField,\n orIndex: conditions.length,\n relation: 'or',\n })\n }, [addCondition, conditions.length, firstField, handleWhereChange])\n\n // When conditions is empty, show a virtual first row so the panel never opens blank.\n const displayConditions =\n conditions.length === 0 && firstField\n ? ([\n { and: [{ [firstField.fieldPath]: { [firstField.operators[0].value]: undefined } }] },\n ] as typeof conditions)\n : conditions\n\n // Disable the remove button only when there are no committed conditions and this host\n // doesn't provide an empty-state removal handler.\n const disableRemoveButton = conditions.length === 0 && !onEmptyRemove\n\n return (\n <div className={baseClass}>\n <div className={`${baseClass}__or-filters`}>\n {displayConditions.map((or, orIndex) => {\n const compoundOrKey = `${orIndex}_${Array.isArray(or?.and) ? or.and.length : ''}`\n\n return (\n <div className={`${baseClass}__and-filters`} key={compoundOrKey}>\n {Array.isArray(or?.and) &&\n or.and.map((_, andIndex) => {\n const condition = displayConditions[orIndex].and[andIndex]\n const fieldPath = Object.keys(condition)[0]\n\n const operator =\n (Object.keys(condition?.[fieldPath] || {})?.[0] as Operator) || undefined\n\n const value = getDisplayedConditionValue({\n value: condition?.[fieldPath]?.[operator],\n })\n\n const isFirstCondition = orIndex === 0 && andIndex === 0\n const join: 'and' | 'or' = andIndex === 0 ? 'or' : 'and'\n\n return (\n <Condition\n addCondition={addCondition}\n andIndex={andIndex}\n disableRemoveButton={disableRemoveButton}\n fieldPath={fieldPath}\n filterOptions={resolvedFilterOptions?.get(fieldPath)}\n isFirstCondition={isFirstCondition}\n join={join}\n key={andIndex}\n operator={operator}\n orIndex={orIndex}\n reducedFields={reducedFields}\n removeCondition={removeCondition}\n RenderedFilter={renderedFilters?.get(fieldPath)}\n updateCondition={updateCondition}\n updateJoin={updateJoin}\n value={value}\n />\n )\n })}\n </div>\n )\n })}\n <div className={`${baseClass}__add-or-row`}>\n <Button\n buttonStyle=\"ghost\"\n className={`${baseClass}__add-or`}\n icon={<CirclePlusIcon size={24} />}\n iconPosition=\"left\"\n onClick={addFirstFilter}\n >\n {t('general:addFilter')}\n </Button>\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/fields/Upload/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EAEnB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,WAAW,IAAI,eAAe,EAC9B,iBAAiB,EAClB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKjD,OAAO,KAA0C,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/fields/Upload/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EAEnB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,WAAW,IAAI,eAAe,EAC9B,iBAAiB,EAClB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKjD,OAAO,KAA0C,MAAM,OAAO,CAAA;AAuB9D,OAAO,aAAa,CAAA;AAGpB,eAAO,MAAM,SAAS,WAAW,CAAA;AAIjC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAA;IAC5C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAA;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAA;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,mBAAmB,CAAA;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAA;IACpF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAA,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,CAAA;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,CAAA;CACjG,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,qBAsuBlD"}
|
|
@@ -5,6 +5,7 @@ import { useModal } from '@faceless-ui/modal';
|
|
|
5
5
|
import { formatAdminURL } from 'payload/shared';
|
|
6
6
|
import * as qs from 'qs-esm';
|
|
7
7
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
8
|
+
import { toast } from 'sonner';
|
|
8
9
|
import { useBulkUpload } from '../../elements/BulkUpload/index.js';
|
|
9
10
|
import { Button } from '../../elements/Button/index.js';
|
|
10
11
|
import { useDocumentDrawer } from '../../elements/DocumentDrawer/index.js';
|
|
@@ -18,6 +19,7 @@ import { FieldLabel } from '../../fields/FieldLabel/index.js';
|
|
|
18
19
|
import { useAuth } from '../../providers/Auth/index.js';
|
|
19
20
|
import { useLocale } from '../../providers/Locale/index.js';
|
|
20
21
|
import { useTranslation } from '../../providers/Translation/index.js';
|
|
22
|
+
import { getFilesFromClipboard } from '../../utilities/getFilesFromClipboard.js';
|
|
21
23
|
import { normalizeRelationshipValue } from '../../utilities/normalizeRelationshipValue.js';
|
|
22
24
|
import { fieldBaseClass } from '../shared/index.js';
|
|
23
25
|
import { UploadComponentHasMany } from './HasMany/index.js';
|
|
@@ -298,6 +300,18 @@ export function UploadInput(props) {
|
|
|
298
300
|
}
|
|
299
301
|
openModal(drawerSlug);
|
|
300
302
|
}, [hasMany, relationTo, activeRelationTo, setCollectionSlug, collectionSlugsWithCreatePermission, maxRows, openModal, drawerSlug, setInitialFiles, setSelectableCollections, setMaxFiles]);
|
|
303
|
+
const handlePasteFromClipboard = useCallback(async () => {
|
|
304
|
+
try {
|
|
305
|
+
const files = await getFilesFromClipboard();
|
|
306
|
+
if (!files) {
|
|
307
|
+
toast.error(t('error:noFileFoundInClipboard'));
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
onLocalFileSelection(files);
|
|
311
|
+
} catch (_err) {
|
|
312
|
+
toast.error(t('error:unableToReadClipboard'));
|
|
313
|
+
}
|
|
314
|
+
}, [onLocalFileSelection, t]);
|
|
301
315
|
// only hasMany can bulk select
|
|
302
316
|
const onListBulkSelect = React.useCallback(async (docs_0, collectionSlug) => {
|
|
303
317
|
const isPoly_1 = Array.isArray(relationTo);
|
|
@@ -579,6 +593,18 @@ export function UploadInput(props) {
|
|
|
579
593
|
onClick: openListDrawer,
|
|
580
594
|
size: "medium",
|
|
581
595
|
children: t('fields:chooseFromExisting')
|
|
596
|
+
}), canCreate && !readOnly && /*#__PURE__*/_jsxs(_Fragment, {
|
|
597
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
598
|
+
className: `${baseClass}__dropzoneContent__orText`,
|
|
599
|
+
children: t('general:or')
|
|
600
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
601
|
+
buttonStyle: "secondary",
|
|
602
|
+
className: `${baseClass}__pasteFromClipboard`,
|
|
603
|
+
icon: "clipboard",
|
|
604
|
+
onClick: handlePasteFromClipboard,
|
|
605
|
+
size: "medium",
|
|
606
|
+
tooltip: t('upload:pasteFromClipboard')
|
|
607
|
+
})]
|
|
582
608
|
}), /*#__PURE__*/_jsx(CreateDocDrawer, {
|
|
583
609
|
onSave: onDocCreate
|
|
584
610
|
}), /*#__PURE__*/_jsx(ListDrawer, {
|