@payloadcms/ui 3.80.0-internal-debug.daef79f → 3.80.0-internal-debug.cd99b1f

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.
@@ -1 +1 @@
1
- {"version":3,"file":"mergeFormStateFromClipboard.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/mergeFormStateFromClipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpD,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,SAAS,EAAE,SAAS,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,8BAyBA;AAED,wBAAgB,2BAA2B,CAAC,EAC1C,iBAAiB,EAAE,aAAa,EAChC,SAAS,EACT,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,iBAAiB,EAAE,kBAAkB,CAAA;IACrC,SAAS,EAAE,SAAS,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,aAiFA"}
1
+ {"version":3,"file":"mergeFormStateFromClipboard.d.ts","sourceRoot":"","sources":["../../../src/elements/ClipboardAction/mergeFormStateFromClipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAIpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAIpD,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,SAAS,EAAE,SAAS,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,8BAyBA;AAED,wBAAgB,2BAA2B,CAAC,EAC1C,iBAAiB,EAAE,aAAa,EAChC,SAAS,EACT,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,iBAAiB,EAAE,kBAAkB,CAAA;IACrC,SAAS,EAAE,SAAS,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,aAwIA"}
@@ -1,3 +1,5 @@
1
+ import ObjectIdImport from 'bson-objectid';
2
+ const ObjectId = 'default' in ObjectIdImport ? ObjectIdImport.default : ObjectIdImport;
1
3
  export function reduceFormStateByPath({ formState, path, rowIndex }) {
2
4
  const filteredState = {};
3
5
  const prefix = typeof rowIndex !== 'number' ? path : `${path}.${rowIndex}`;
@@ -43,7 +45,7 @@ export function mergeFormStateFromClipboard({ dataFromClipboard: clipboardData,
43
45
  }
44
46
  if (fromRowToField) {
45
47
  const lastRenderedPath = `${path}.0`;
46
- const rowIDFromClipboard = dataFromClipboard[`${pathToReplace}.id`].value;
48
+ const rowIDFromClipboard = dataFromClipboard[`${pathToReplace}.id`]?.value;
47
49
  const hasRows = formState[path].rows?.length;
48
50
  formState[path].rows = [
49
51
  {
@@ -62,6 +64,8 @@ export function mergeFormStateFromClipboard({ dataFromClipboard: clipboardData,
62
64
  }
63
65
  }
64
66
  }
67
+ // Map to track old IDs to new IDs for regenerating nested IDs
68
+ const idReplacements = new Map();
65
69
  for(const clipboardPath in dataFromClipboard){
66
70
  // Pasting a row id, skip overwriting
67
71
  if (!pasteIntoField && clipboardPath.endsWith('.id') || !clipboardPath.startsWith(pathToReplace)) {
@@ -70,12 +74,56 @@ export function mergeFormStateFromClipboard({ dataFromClipboard: clipboardData,
70
74
  const newPath = clipboardPath.replace(pathToReplace, targetSegment);
71
75
  const customComponents = isArray ? formState[newPath]?.customComponents : undefined;
72
76
  const validate = isArray ? formState[newPath]?.validate : undefined;
77
+ // If this is an ID field, generate a new ID to prevent duplicates
78
+ if (clipboardPath.endsWith('.id') && dataFromClipboard[clipboardPath]?.value) {
79
+ const oldID = dataFromClipboard[clipboardPath].value;
80
+ if (typeof oldID === 'string' && ObjectId.isValid(oldID)) {
81
+ const newID = new ObjectId().toHexString();
82
+ idReplacements.set(clipboardPath, newID);
83
+ formState[newPath] = {
84
+ customComponents,
85
+ validate,
86
+ ...dataFromClipboard[clipboardPath],
87
+ initialValue: newID,
88
+ value: newID
89
+ };
90
+ continue;
91
+ }
92
+ }
73
93
  formState[newPath] = {
74
94
  customComponents,
75
95
  validate,
76
96
  ...dataFromClipboard[clipboardPath]
77
97
  };
78
98
  }
99
+ // Update parent field rows with new IDs
100
+ for (const [clipboardPath, newID] of idReplacements){
101
+ const relativePath = clipboardPath.replace(`${pathToReplace}.`, '');
102
+ const segments = relativePath.split('.');
103
+ if (segments.length >= 2) {
104
+ const rowIndex = parseInt(segments[segments.length - 2], 10);
105
+ const parentFieldPath = segments.slice(0, segments.length - 2).join('.');
106
+ const fullParentPath = parentFieldPath ? `${targetSegment}.${parentFieldPath}` : targetSegment;
107
+ if (formState[fullParentPath] && Array.isArray(formState[fullParentPath].rows)) {
108
+ const parentRows = formState[fullParentPath].rows;
109
+ if (!isNaN(rowIndex) && parentRows[rowIndex]) {
110
+ parentRows[rowIndex].id = newID;
111
+ }
112
+ }
113
+ } else if (segments.length === 1 && segments[0] === 'id') {
114
+ // Top-level block ID - extract field path and row index from targetSegment
115
+ const targetParts = targetSegment.split('.');
116
+ const lastPart = targetParts[targetParts.length - 1];
117
+ const rowIndexFromTarget = !isNaN(parseInt(lastPart, 10)) ? parseInt(lastPart, 10) : 0;
118
+ const fieldPath = !isNaN(parseInt(lastPart, 10)) ? targetParts.slice(0, -1).join('.') : targetSegment;
119
+ if (formState[fieldPath] && Array.isArray(formState[fieldPath].rows)) {
120
+ const rows = formState[fieldPath].rows;
121
+ if (rows[rowIndexFromTarget]) {
122
+ rows[rowIndexFromTarget].id = newID;
123
+ }
124
+ }
125
+ }
126
+ }
79
127
  return formState;
80
128
  }
81
129
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/elements/ClipboardAction/mergeFormStateFromClipboard.ts"],"sourcesContent":["import type { FieldState, FormState } from 'payload'\n\nimport type { ClipboardPasteData } from './types.js'\n\nexport function reduceFormStateByPath({\n formState,\n path,\n rowIndex,\n}: {\n formState: FormState\n path: string\n rowIndex?: number\n}) {\n const filteredState: Record<string, FieldState> = {}\n const prefix = typeof rowIndex !== 'number' ? path : `${path}.${rowIndex}`\n\n for (const key in formState) {\n if (!key.startsWith(prefix)) {\n continue\n }\n\n const { customComponents: _, validate: __, ...field } = formState[key]\n\n if (Array.isArray(field.rows)) {\n field.rows = field.rows.map((row) => {\n if (!row || typeof row !== 'object') {\n return row\n }\n const { customComponents: _, ...serializableRow } = row\n return serializableRow\n })\n }\n\n filteredState[key] = field\n }\n\n return filteredState\n}\n\nexport function mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path,\n rowIndex,\n}: {\n dataFromClipboard: ClipboardPasteData\n formState: FormState\n path: string\n rowIndex?: number\n}) {\n const {\n type: typeFromClipboard,\n data: dataFromClipboard,\n path: pathFromClipboard,\n rowIndex: rowIndexFromClipboard,\n } = clipboardData\n\n const copyFromField = typeof rowIndexFromClipboard !== 'number'\n const pasteIntoField = typeof rowIndex !== 'number'\n const fromRowToField = !copyFromField && pasteIntoField\n const isArray = typeFromClipboard === 'array'\n\n let pathToReplace: string\n if (copyFromField && pasteIntoField) {\n pathToReplace = pathFromClipboard\n } else if (copyFromField) {\n pathToReplace = `${pathFromClipboard}.${rowIndex}`\n } else {\n pathToReplace = `${pathFromClipboard}.${rowIndexFromClipboard}`\n }\n\n let targetSegment: string\n if (!pasteIntoField) {\n targetSegment = `${path}.${rowIndex}`\n } else if (fromRowToField) {\n targetSegment = `${path}.0`\n } else {\n targetSegment = path\n }\n\n if (fromRowToField) {\n const lastRenderedPath = `${path}.0`\n const rowIDFromClipboard = dataFromClipboard[`${pathToReplace}.id`].value as string\n const hasRows = formState[path].rows?.length\n\n formState[path].rows = [\n {\n ...(hasRows && isArray ? formState[path].rows[0] : {}),\n id: rowIDFromClipboard,\n isLoading: false,\n lastRenderedPath,\n },\n ]\n formState[path].value = 1\n formState[path].initialValue = 1\n formState[path].disableFormData = true\n\n for (const fieldPath in formState) {\n if (\n fieldPath !== path &&\n !fieldPath.startsWith(lastRenderedPath) &&\n fieldPath.startsWith(path)\n ) {\n delete formState[fieldPath]\n }\n }\n }\n\n for (const clipboardPath in dataFromClipboard) {\n // Pasting a row id, skip overwriting\n if (\n (!pasteIntoField && clipboardPath.endsWith('.id')) ||\n !clipboardPath.startsWith(pathToReplace)\n ) {\n continue\n }\n\n const newPath = clipboardPath.replace(pathToReplace, targetSegment)\n\n const customComponents = isArray ? formState[newPath]?.customComponents : undefined\n const validate = isArray ? formState[newPath]?.validate : undefined\n\n formState[newPath] = {\n customComponents,\n validate,\n ...dataFromClipboard[clipboardPath],\n }\n }\n\n return formState\n}\n"],"names":["reduceFormStateByPath","formState","path","rowIndex","filteredState","prefix","key","startsWith","customComponents","_","validate","__","field","Array","isArray","rows","map","row","serializableRow","mergeFormStateFromClipboard","dataFromClipboard","clipboardData","type","typeFromClipboard","data","pathFromClipboard","rowIndexFromClipboard","copyFromField","pasteIntoField","fromRowToField","pathToReplace","targetSegment","lastRenderedPath","rowIDFromClipboard","value","hasRows","length","id","isLoading","initialValue","disableFormData","fieldPath","clipboardPath","endsWith","newPath","replace","undefined"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/elements/ClipboardAction/mergeFormStateFromClipboard.ts"],"sourcesContent":["import type { FieldState, FormState } from 'payload'\n\nimport ObjectIdImport from 'bson-objectid'\n\nimport type { ClipboardPasteData } from './types.js'\n\nconst ObjectId = 'default' in ObjectIdImport ? ObjectIdImport.default : ObjectIdImport\n\nexport function reduceFormStateByPath({\n formState,\n path,\n rowIndex,\n}: {\n formState: FormState\n path: string\n rowIndex?: number\n}) {\n const filteredState: Record<string, FieldState> = {}\n const prefix = typeof rowIndex !== 'number' ? path : `${path}.${rowIndex}`\n\n for (const key in formState) {\n if (!key.startsWith(prefix)) {\n continue\n }\n\n const { customComponents: _, validate: __, ...field } = formState[key]\n\n if (Array.isArray(field.rows)) {\n field.rows = field.rows.map((row) => {\n if (!row || typeof row !== 'object') {\n return row\n }\n const { customComponents: _, ...serializableRow } = row\n return serializableRow\n })\n }\n\n filteredState[key] = field\n }\n\n return filteredState\n}\n\nexport function mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path,\n rowIndex,\n}: {\n dataFromClipboard: ClipboardPasteData\n formState: FormState\n path: string\n rowIndex?: number\n}) {\n const {\n type: typeFromClipboard,\n data: dataFromClipboard,\n path: pathFromClipboard,\n rowIndex: rowIndexFromClipboard,\n } = clipboardData\n\n const copyFromField = typeof rowIndexFromClipboard !== 'number'\n const pasteIntoField = typeof rowIndex !== 'number'\n const fromRowToField = !copyFromField && pasteIntoField\n const isArray = typeFromClipboard === 'array'\n\n let pathToReplace: string\n if (copyFromField && pasteIntoField) {\n pathToReplace = pathFromClipboard\n } else if (copyFromField) {\n pathToReplace = `${pathFromClipboard}.${rowIndex}`\n } else {\n pathToReplace = `${pathFromClipboard}.${rowIndexFromClipboard}`\n }\n\n let targetSegment: string\n if (!pasteIntoField) {\n targetSegment = `${path}.${rowIndex}`\n } else if (fromRowToField) {\n targetSegment = `${path}.0`\n } else {\n targetSegment = path\n }\n\n if (fromRowToField) {\n const lastRenderedPath = `${path}.0`\n const rowIDFromClipboard = dataFromClipboard[`${pathToReplace}.id`]?.value as string\n const hasRows = formState[path].rows?.length\n\n formState[path].rows = [\n {\n ...(hasRows && isArray ? formState[path].rows[0] : {}),\n id: rowIDFromClipboard,\n isLoading: false,\n lastRenderedPath,\n },\n ]\n formState[path].value = 1\n formState[path].initialValue = 1\n formState[path].disableFormData = true\n\n for (const fieldPath in formState) {\n if (\n fieldPath !== path &&\n !fieldPath.startsWith(lastRenderedPath) &&\n fieldPath.startsWith(path)\n ) {\n delete formState[fieldPath]\n }\n }\n }\n\n // Map to track old IDs to new IDs for regenerating nested IDs\n const idReplacements: Map<string, string> = new Map()\n\n for (const clipboardPath in dataFromClipboard) {\n // Pasting a row id, skip overwriting\n if (\n (!pasteIntoField && clipboardPath.endsWith('.id')) ||\n !clipboardPath.startsWith(pathToReplace)\n ) {\n continue\n }\n\n const newPath = clipboardPath.replace(pathToReplace, targetSegment)\n\n const customComponents = isArray ? formState[newPath]?.customComponents : undefined\n const validate = isArray ? formState[newPath]?.validate : undefined\n\n // If this is an ID field, generate a new ID to prevent duplicates\n if (clipboardPath.endsWith('.id') && dataFromClipboard[clipboardPath]?.value) {\n const oldID = dataFromClipboard[clipboardPath].value as string\n if (typeof oldID === 'string' && ObjectId.isValid(oldID)) {\n const newID = new ObjectId().toHexString()\n idReplacements.set(clipboardPath, newID)\n\n formState[newPath] = {\n customComponents,\n validate,\n ...dataFromClipboard[clipboardPath],\n initialValue: newID,\n value: newID,\n }\n continue\n }\n }\n\n formState[newPath] = {\n customComponents,\n validate,\n ...dataFromClipboard[clipboardPath],\n }\n }\n\n // Update parent field rows with new IDs\n for (const [clipboardPath, newID] of idReplacements) {\n const relativePath = clipboardPath.replace(`${pathToReplace}.`, '')\n const segments = relativePath.split('.')\n\n if (segments.length >= 2) {\n const rowIndex = parseInt(segments[segments.length - 2], 10)\n const parentFieldPath = segments.slice(0, segments.length - 2).join('.')\n const fullParentPath = parentFieldPath ? `${targetSegment}.${parentFieldPath}` : targetSegment\n\n if (formState[fullParentPath] && Array.isArray(formState[fullParentPath].rows)) {\n const parentRows = formState[fullParentPath].rows\n if (!isNaN(rowIndex) && parentRows[rowIndex]) {\n parentRows[rowIndex].id = newID\n }\n }\n } else if (segments.length === 1 && segments[0] === 'id') {\n // Top-level block ID - extract field path and row index from targetSegment\n const targetParts = targetSegment.split('.')\n const lastPart = targetParts[targetParts.length - 1]\n const rowIndexFromTarget = !isNaN(parseInt(lastPart, 10)) ? parseInt(lastPart, 10) : 0\n const fieldPath = !isNaN(parseInt(lastPart, 10))\n ? targetParts.slice(0, -1).join('.')\n : targetSegment\n\n if (formState[fieldPath] && Array.isArray(formState[fieldPath].rows)) {\n const rows = formState[fieldPath].rows\n if (rows[rowIndexFromTarget]) {\n rows[rowIndexFromTarget].id = newID\n }\n }\n }\n }\n\n return formState\n}\n"],"names":["ObjectIdImport","ObjectId","default","reduceFormStateByPath","formState","path","rowIndex","filteredState","prefix","key","startsWith","customComponents","_","validate","__","field","Array","isArray","rows","map","row","serializableRow","mergeFormStateFromClipboard","dataFromClipboard","clipboardData","type","typeFromClipboard","data","pathFromClipboard","rowIndexFromClipboard","copyFromField","pasteIntoField","fromRowToField","pathToReplace","targetSegment","lastRenderedPath","rowIDFromClipboard","value","hasRows","length","id","isLoading","initialValue","disableFormData","fieldPath","idReplacements","Map","clipboardPath","endsWith","newPath","replace","undefined","oldID","isValid","newID","toHexString","set","relativePath","segments","split","parseInt","parentFieldPath","slice","join","fullParentPath","parentRows","isNaN","targetParts","lastPart","rowIndexFromTarget"],"mappings":"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"}
@@ -0,0 +1,389 @@
1
+ import ObjectIdImport from 'bson-objectid';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { mergeFormStateFromClipboard } from './mergeFormStateFromClipboard.js';
4
+ const ObjectId = 'default' in ObjectIdImport ? ObjectIdImport.default : ObjectIdImport;
5
+ describe('mergeFormStateFromClipboard', ()=>{
6
+ describe('block ID regeneration', ()=>{
7
+ it('should generate new IDs when pasting blocks to prevent duplicates', ()=>{
8
+ const copiedBlockID = new ObjectId().toHexString();
9
+ const formState = {
10
+ layout: {
11
+ valid: true,
12
+ value: 0,
13
+ initialValue: 0,
14
+ rows: []
15
+ }
16
+ };
17
+ const clipboardData = {
18
+ type: 'blocks',
19
+ path: 'layout',
20
+ blocks: [],
21
+ data: {
22
+ 'layout.0.id': {
23
+ value: copiedBlockID,
24
+ valid: true
25
+ },
26
+ 'layout.0.blockType': {
27
+ value: 'content',
28
+ valid: true
29
+ },
30
+ 'layout.0.text': {
31
+ value: 'test content',
32
+ valid: true
33
+ }
34
+ },
35
+ rowIndex: 0
36
+ };
37
+ const result = mergeFormStateFromClipboard({
38
+ dataFromClipboard: clipboardData,
39
+ formState,
40
+ path: 'layout'
41
+ });
42
+ // Check that a new ID was generated
43
+ expect(result['layout.0.id']).toBeDefined();
44
+ expect(result['layout.0.id'].value).toBeDefined();
45
+ expect(result['layout.0.id'].value).not.toEqual(copiedBlockID);
46
+ expect(ObjectId.isValid(result['layout.0.id'].value)).toBe(true);
47
+ // Check that the row metadata also has the new ID
48
+ expect(result.layout.rows).toHaveLength(1);
49
+ expect(result.layout.rows?.[0]?.id).not.toEqual(copiedBlockID);
50
+ expect(result.layout.rows?.[0]?.id).toEqual(result['layout.0.id'].value);
51
+ });
52
+ it('should generate new IDs for nested blocks', ()=>{
53
+ const copiedBlockID = new ObjectId().toHexString();
54
+ const copiedNestedBlockID = new ObjectId().toHexString();
55
+ const formState = {
56
+ layout: {
57
+ valid: true,
58
+ value: 0,
59
+ initialValue: 0,
60
+ rows: []
61
+ }
62
+ };
63
+ const clipboardData = {
64
+ type: 'blocks',
65
+ path: 'layout',
66
+ blocks: [],
67
+ data: {
68
+ 'layout.0.id': {
69
+ value: copiedBlockID,
70
+ valid: true
71
+ },
72
+ 'layout.0.blockType': {
73
+ value: 'container',
74
+ valid: true
75
+ },
76
+ 'layout.0.subBlocks': {
77
+ value: 1,
78
+ valid: true,
79
+ rows: [
80
+ {
81
+ id: copiedNestedBlockID
82
+ }
83
+ ]
84
+ },
85
+ 'layout.0.subBlocks.0.id': {
86
+ value: copiedNestedBlockID,
87
+ valid: true
88
+ },
89
+ 'layout.0.subBlocks.0.blockType': {
90
+ value: 'content',
91
+ valid: true
92
+ }
93
+ },
94
+ rowIndex: 0
95
+ };
96
+ const result = mergeFormStateFromClipboard({
97
+ dataFromClipboard: clipboardData,
98
+ formState,
99
+ path: 'layout'
100
+ });
101
+ // Check that parent block got new ID
102
+ expect(result['layout.0.id'].value).not.toEqual(copiedBlockID);
103
+ expect(ObjectId.isValid(result['layout.0.id'].value)).toBe(true);
104
+ // Check that nested block got new ID
105
+ expect(result['layout.0.subBlocks.0.id'].value).not.toEqual(copiedNestedBlockID);
106
+ expect(ObjectId.isValid(result['layout.0.subBlocks.0.id'].value)).toBe(true);
107
+ // Check that parent and nested IDs are different
108
+ expect(result['layout.0.id'].value).not.toEqual(result['layout.0.subBlocks.0.id'].value);
109
+ // Check that parent row metadata has new ID
110
+ expect(result.layout.rows?.[0]?.id).toEqual(result['layout.0.id'].value);
111
+ // Check that nested row metadata has new ID
112
+ expect(result['layout.0.subBlocks'].rows?.[0]?.id).toEqual(result['layout.0.subBlocks.0.id'].value);
113
+ });
114
+ it('should preserve non-ID field values when pasting', ()=>{
115
+ const copiedBlockID = new ObjectId().toHexString();
116
+ const formState = {
117
+ layout: {
118
+ valid: true,
119
+ value: 0,
120
+ initialValue: 0,
121
+ rows: []
122
+ }
123
+ };
124
+ const clipboardData = {
125
+ type: 'blocks',
126
+ path: 'layout',
127
+ blocks: [],
128
+ data: {
129
+ 'layout.0.id': {
130
+ value: copiedBlockID,
131
+ valid: true
132
+ },
133
+ 'layout.0.blockType': {
134
+ value: 'content',
135
+ valid: true
136
+ },
137
+ 'layout.0.text': {
138
+ value: 'preserved text content',
139
+ valid: true
140
+ }
141
+ },
142
+ rowIndex: 0
143
+ };
144
+ const result = mergeFormStateFromClipboard({
145
+ dataFromClipboard: clipboardData,
146
+ formState,
147
+ path: 'layout'
148
+ });
149
+ // Non-ID fields should be preserved
150
+ expect(result['layout.0.blockType'].value).toEqual('content');
151
+ expect(result['layout.0.text'].value).toEqual('preserved text content');
152
+ });
153
+ it('should generate new ID when pasting from row to field', ()=>{
154
+ const copiedBlockID = new ObjectId().toHexString();
155
+ const formState = {
156
+ duplicate: {
157
+ valid: true,
158
+ value: 0,
159
+ initialValue: 0,
160
+ rows: []
161
+ }
162
+ };
163
+ // Simulating copying from blocks.1 and pasting into duplicate field
164
+ const clipboardData = {
165
+ type: 'blocks',
166
+ path: 'blocks',
167
+ blocks: [],
168
+ data: {
169
+ 'blocks.1.id': {
170
+ value: copiedBlockID,
171
+ valid: true
172
+ },
173
+ 'blocks.1.blockType': {
174
+ value: 'number',
175
+ valid: true
176
+ },
177
+ 'blocks.1.number': {
178
+ value: 342,
179
+ valid: true
180
+ }
181
+ },
182
+ rowIndex: 1
183
+ };
184
+ const result = mergeFormStateFromClipboard({
185
+ dataFromClipboard: clipboardData,
186
+ formState,
187
+ path: 'duplicate'
188
+ });
189
+ // Check that a new ID was generated
190
+ expect(result['duplicate.0.id']).toBeDefined();
191
+ expect(result['duplicate.0.id'].value).toBeDefined();
192
+ expect(result['duplicate.0.id'].value).not.toEqual(copiedBlockID);
193
+ expect(ObjectId.isValid(result['duplicate.0.id'].value)).toBe(true);
194
+ // Check that the row metadata has the new ID (not the copied ID)
195
+ expect(result.duplicate.rows).toBeDefined();
196
+ expect(result.duplicate.rows).toHaveLength(1);
197
+ expect(result.duplicate.rows[0].id).not.toEqual(copiedBlockID);
198
+ expect(result.duplicate.rows[0].id).toEqual(result['duplicate.0.id'].value);
199
+ // Check that other fields were preserved
200
+ expect(result['duplicate.0.number'].value).toEqual(342);
201
+ });
202
+ });
203
+ describe('array ID regeneration', ()=>{
204
+ it('should generate new IDs when pasting arrays to prevent duplicates', ()=>{
205
+ const copiedArrayID = new ObjectId().toHexString();
206
+ const formState = {
207
+ items: {
208
+ valid: true,
209
+ value: 0,
210
+ initialValue: 0,
211
+ rows: []
212
+ }
213
+ };
214
+ const clipboardData = {
215
+ type: 'array',
216
+ path: 'items',
217
+ fields: [],
218
+ data: {
219
+ 'items.0.id': {
220
+ value: copiedArrayID,
221
+ valid: true
222
+ },
223
+ 'items.0.text': {
224
+ value: 'test content',
225
+ valid: true
226
+ }
227
+ },
228
+ rowIndex: 0
229
+ };
230
+ const result = mergeFormStateFromClipboard({
231
+ dataFromClipboard: clipboardData,
232
+ formState,
233
+ path: 'items'
234
+ });
235
+ // Check that a new ID was generated
236
+ expect(result['items.0.id']).toBeDefined();
237
+ expect(result['items.0.id'].value).toBeDefined();
238
+ expect(result['items.0.id'].value).not.toEqual(copiedArrayID);
239
+ expect(ObjectId.isValid(result['items.0.id'].value)).toBe(true);
240
+ // Check that the row metadata also has the new ID
241
+ expect(result.items.rows).toHaveLength(1);
242
+ expect(result.items.rows?.[0]?.id).not.toEqual(copiedArrayID);
243
+ expect(result.items.rows?.[0]?.id).toEqual(result['items.0.id'].value);
244
+ });
245
+ it('should generate new IDs for nested arrays', ()=>{
246
+ const copiedArrayID = new ObjectId().toHexString();
247
+ const copiedNestedArrayID = new ObjectId().toHexString();
248
+ const formState = {
249
+ items: {
250
+ valid: true,
251
+ value: 0,
252
+ initialValue: 0,
253
+ rows: []
254
+ }
255
+ };
256
+ const clipboardData = {
257
+ type: 'array',
258
+ path: 'items',
259
+ fields: [],
260
+ data: {
261
+ 'items.0.id': {
262
+ value: copiedArrayID,
263
+ valid: true
264
+ },
265
+ 'items.0.text': {
266
+ value: 'parent array',
267
+ valid: true
268
+ },
269
+ 'items.0.subArray': {
270
+ value: 1,
271
+ valid: true,
272
+ rows: [
273
+ {
274
+ id: copiedNestedArrayID
275
+ }
276
+ ]
277
+ },
278
+ 'items.0.subArray.0.id': {
279
+ value: copiedNestedArrayID,
280
+ valid: true
281
+ },
282
+ 'items.0.subArray.0.text': {
283
+ value: 'nested array',
284
+ valid: true
285
+ }
286
+ },
287
+ rowIndex: 0
288
+ };
289
+ const result = mergeFormStateFromClipboard({
290
+ dataFromClipboard: clipboardData,
291
+ formState,
292
+ path: 'items'
293
+ });
294
+ // Check that parent array got new ID
295
+ expect(result['items.0.id'].value).not.toEqual(copiedArrayID);
296
+ expect(ObjectId.isValid(result['items.0.id'].value)).toBe(true);
297
+ // Check that nested array got new ID
298
+ expect(result['items.0.subArray.0.id'].value).not.toEqual(copiedNestedArrayID);
299
+ expect(ObjectId.isValid(result['items.0.subArray.0.id'].value)).toBe(true);
300
+ // Check that parent and nested IDs are different
301
+ expect(result['items.0.id'].value).not.toEqual(result['items.0.subArray.0.id'].value);
302
+ // Check that parent row metadata has new ID
303
+ expect(result.items.rows?.[0]?.id).toEqual(result['items.0.id'].value);
304
+ // Check that nested row metadata has new ID
305
+ expect(result['items.0.subArray'].rows?.[0]?.id).toEqual(result['items.0.subArray.0.id'].value);
306
+ });
307
+ it('should preserve non-ID field values when pasting arrays', ()=>{
308
+ const copiedArrayID = new ObjectId().toHexString();
309
+ const formState = {
310
+ items: {
311
+ valid: true,
312
+ value: 0,
313
+ initialValue: 0,
314
+ rows: []
315
+ }
316
+ };
317
+ const clipboardData = {
318
+ type: 'array',
319
+ path: 'items',
320
+ fields: [],
321
+ data: {
322
+ 'items.0.id': {
323
+ value: copiedArrayID,
324
+ valid: true
325
+ },
326
+ 'items.0.text': {
327
+ value: 'preserved array text',
328
+ valid: true
329
+ }
330
+ },
331
+ rowIndex: 0
332
+ };
333
+ const result = mergeFormStateFromClipboard({
334
+ dataFromClipboard: clipboardData,
335
+ formState,
336
+ path: 'items'
337
+ });
338
+ // Non-ID fields should be preserved
339
+ expect(result['items.0.text'].value).toEqual('preserved array text');
340
+ });
341
+ it('should generate new ID when pasting from array row to field', ()=>{
342
+ const copiedArrayID = new ObjectId().toHexString();
343
+ const formState = {
344
+ disableSort: {
345
+ valid: true,
346
+ value: 0,
347
+ initialValue: 0,
348
+ rows: []
349
+ }
350
+ };
351
+ // Simulating copying from items.0 and pasting into disableSort field
352
+ const clipboardData = {
353
+ type: 'array',
354
+ path: 'items',
355
+ fields: [],
356
+ data: {
357
+ 'items.0.id': {
358
+ value: copiedArrayID,
359
+ valid: true
360
+ },
361
+ 'items.0.text': {
362
+ value: 'row one',
363
+ valid: true
364
+ }
365
+ },
366
+ rowIndex: 0
367
+ };
368
+ const result = mergeFormStateFromClipboard({
369
+ dataFromClipboard: clipboardData,
370
+ formState,
371
+ path: 'disableSort'
372
+ });
373
+ // Check that a new ID was generated
374
+ expect(result['disableSort.0.id']).toBeDefined();
375
+ expect(result['disableSort.0.id'].value).toBeDefined();
376
+ expect(result['disableSort.0.id'].value).not.toEqual(copiedArrayID);
377
+ expect(ObjectId.isValid(result['disableSort.0.id'].value)).toBe(true);
378
+ // Check that the row metadata has the new ID (not the copied ID)
379
+ expect(result.disableSort.rows).toBeDefined();
380
+ expect(result.disableSort.rows).toHaveLength(1);
381
+ expect(result.disableSort.rows[0].id).not.toEqual(copiedArrayID);
382
+ expect(result.disableSort.rows[0].id).toEqual(result['disableSort.0.id'].value);
383
+ // Check that other fields were preserved
384
+ expect(result['disableSort.0.text'].value).toEqual('row one');
385
+ });
386
+ });
387
+ });
388
+
389
+ //# sourceMappingURL=mergeFormStateFromClipboard.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/elements/ClipboardAction/mergeFormStateFromClipboard.spec.ts"],"sourcesContent":["import type { FormState } from 'payload'\n\nimport ObjectIdImport from 'bson-objectid'\nimport { describe, expect, it } from 'vitest'\n\nimport { mergeFormStateFromClipboard } from './mergeFormStateFromClipboard.js'\nimport type { ClipboardPasteData } from './types.js'\n\nconst ObjectId = (\n 'default' in ObjectIdImport ? ObjectIdImport.default : ObjectIdImport\n) as typeof ObjectIdImport\n\ndescribe('mergeFormStateFromClipboard', () => {\n describe('block ID regeneration', () => {\n it('should generate new IDs when pasting blocks to prevent duplicates', () => {\n const copiedBlockID = new ObjectId().toHexString()\n\n const formState: FormState = {\n layout: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'blocks',\n path: 'layout',\n blocks: [],\n data: {\n 'layout.0.id': {\n value: copiedBlockID,\n valid: true,\n },\n 'layout.0.blockType': {\n value: 'content',\n valid: true,\n },\n 'layout.0.text': {\n value: 'test content',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'layout',\n })\n\n // Check that a new ID was generated\n expect(result['layout.0.id']).toBeDefined()\n expect(result['layout.0.id'].value).toBeDefined()\n expect(result['layout.0.id'].value).not.toEqual(copiedBlockID)\n expect(ObjectId.isValid(result['layout.0.id'].value as string)).toBe(true)\n\n // Check that the row metadata also has the new ID\n expect(result.layout.rows).toHaveLength(1)\n expect(result.layout.rows?.[0]?.id).not.toEqual(copiedBlockID)\n expect(result.layout.rows?.[0]?.id).toEqual(result['layout.0.id'].value)\n })\n\n it('should generate new IDs for nested blocks', () => {\n const copiedBlockID = new ObjectId().toHexString()\n const copiedNestedBlockID = new ObjectId().toHexString()\n\n const formState: FormState = {\n layout: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'blocks',\n path: 'layout',\n blocks: [],\n data: {\n 'layout.0.id': {\n value: copiedBlockID,\n valid: true,\n },\n 'layout.0.blockType': {\n value: 'container',\n valid: true,\n },\n 'layout.0.subBlocks': {\n value: 1,\n valid: true,\n rows: [{ id: copiedNestedBlockID }],\n },\n 'layout.0.subBlocks.0.id': {\n value: copiedNestedBlockID,\n valid: true,\n },\n 'layout.0.subBlocks.0.blockType': {\n value: 'content',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'layout',\n })\n\n // Check that parent block got new ID\n expect(result['layout.0.id'].value).not.toEqual(copiedBlockID)\n expect(ObjectId.isValid(result['layout.0.id'].value as string)).toBe(true)\n\n // Check that nested block got new ID\n expect(result['layout.0.subBlocks.0.id'].value).not.toEqual(copiedNestedBlockID)\n expect(ObjectId.isValid(result['layout.0.subBlocks.0.id'].value as string)).toBe(true)\n\n // Check that parent and nested IDs are different\n expect(result['layout.0.id'].value).not.toEqual(result['layout.0.subBlocks.0.id'].value)\n\n // Check that parent row metadata has new ID\n expect(result.layout.rows?.[0]?.id).toEqual(result['layout.0.id'].value)\n\n // Check that nested row metadata has new ID\n expect(result['layout.0.subBlocks'].rows?.[0]?.id).toEqual(\n result['layout.0.subBlocks.0.id'].value,\n )\n })\n\n it('should preserve non-ID field values when pasting', () => {\n const copiedBlockID = new ObjectId().toHexString()\n\n const formState: FormState = {\n layout: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'blocks',\n path: 'layout',\n blocks: [],\n data: {\n 'layout.0.id': {\n value: copiedBlockID,\n valid: true,\n },\n 'layout.0.blockType': {\n value: 'content',\n valid: true,\n },\n 'layout.0.text': {\n value: 'preserved text content',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'layout',\n })\n\n // Non-ID fields should be preserved\n expect(result['layout.0.blockType'].value).toEqual('content')\n expect(result['layout.0.text'].value).toEqual('preserved text content')\n })\n\n it('should generate new ID when pasting from row to field', () => {\n const copiedBlockID = new ObjectId().toHexString()\n\n const formState: FormState = {\n duplicate: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n // Simulating copying from blocks.1 and pasting into duplicate field\n const clipboardData = {\n type: 'blocks' as const,\n path: 'blocks',\n blocks: [],\n data: {\n 'blocks.1.id': {\n value: copiedBlockID,\n valid: true,\n },\n 'blocks.1.blockType': {\n value: 'number',\n valid: true,\n },\n 'blocks.1.number': {\n value: 342,\n valid: true,\n },\n },\n rowIndex: 1,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'duplicate',\n })\n\n // Check that a new ID was generated\n expect(result['duplicate.0.id']).toBeDefined()\n expect(result['duplicate.0.id'].value).toBeDefined()\n expect(result['duplicate.0.id'].value).not.toEqual(copiedBlockID)\n expect(ObjectId.isValid(result['duplicate.0.id'].value as string)).toBe(true)\n\n // Check that the row metadata has the new ID (not the copied ID)\n expect(result.duplicate.rows).toBeDefined()\n expect(result.duplicate.rows).toHaveLength(1)\n expect(result.duplicate.rows![0].id).not.toEqual(copiedBlockID)\n expect(result.duplicate.rows![0].id).toEqual(result['duplicate.0.id'].value)\n\n // Check that other fields were preserved\n expect(result['duplicate.0.number'].value).toEqual(342)\n })\n })\n\n describe('array ID regeneration', () => {\n it('should generate new IDs when pasting arrays to prevent duplicates', () => {\n const copiedArrayID = new ObjectId().toHexString()\n\n const formState: FormState = {\n items: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'array',\n path: 'items',\n fields: [],\n data: {\n 'items.0.id': {\n value: copiedArrayID,\n valid: true,\n },\n 'items.0.text': {\n value: 'test content',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'items',\n })\n\n // Check that a new ID was generated\n expect(result['items.0.id']).toBeDefined()\n expect(result['items.0.id'].value).toBeDefined()\n expect(result['items.0.id'].value).not.toEqual(copiedArrayID)\n expect(ObjectId.isValid(result['items.0.id'].value as string)).toBe(true)\n\n // Check that the row metadata also has the new ID\n expect(result.items.rows).toHaveLength(1)\n expect(result.items.rows?.[0]?.id).not.toEqual(copiedArrayID)\n expect(result.items.rows?.[0]?.id).toEqual(result['items.0.id'].value)\n })\n\n it('should generate new IDs for nested arrays', () => {\n const copiedArrayID = new ObjectId().toHexString()\n const copiedNestedArrayID = new ObjectId().toHexString()\n\n const formState: FormState = {\n items: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'array',\n path: 'items',\n fields: [],\n data: {\n 'items.0.id': {\n value: copiedArrayID,\n valid: true,\n },\n 'items.0.text': {\n value: 'parent array',\n valid: true,\n },\n 'items.0.subArray': {\n value: 1,\n valid: true,\n rows: [{ id: copiedNestedArrayID }],\n },\n 'items.0.subArray.0.id': {\n value: copiedNestedArrayID,\n valid: true,\n },\n 'items.0.subArray.0.text': {\n value: 'nested array',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'items',\n })\n\n // Check that parent array got new ID\n expect(result['items.0.id'].value).not.toEqual(copiedArrayID)\n expect(ObjectId.isValid(result['items.0.id'].value as string)).toBe(true)\n\n // Check that nested array got new ID\n expect(result['items.0.subArray.0.id'].value).not.toEqual(copiedNestedArrayID)\n expect(ObjectId.isValid(result['items.0.subArray.0.id'].value as string)).toBe(true)\n\n // Check that parent and nested IDs are different\n expect(result['items.0.id'].value).not.toEqual(result['items.0.subArray.0.id'].value)\n\n // Check that parent row metadata has new ID\n expect(result.items.rows?.[0]?.id).toEqual(result['items.0.id'].value)\n\n // Check that nested row metadata has new ID\n expect(result['items.0.subArray'].rows?.[0]?.id).toEqual(\n result['items.0.subArray.0.id'].value,\n )\n })\n\n it('should preserve non-ID field values when pasting arrays', () => {\n const copiedArrayID = new ObjectId().toHexString()\n\n const formState: FormState = {\n items: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n const clipboardData: ClipboardPasteData = {\n type: 'array',\n path: 'items',\n fields: [],\n data: {\n 'items.0.id': {\n value: copiedArrayID,\n valid: true,\n },\n 'items.0.text': {\n value: 'preserved array text',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'items',\n })\n\n // Non-ID fields should be preserved\n expect(result['items.0.text'].value).toEqual('preserved array text')\n })\n\n it('should generate new ID when pasting from array row to field', () => {\n const copiedArrayID = new ObjectId().toHexString()\n\n const formState: FormState = {\n disableSort: {\n valid: true,\n value: 0,\n initialValue: 0,\n rows: [],\n },\n }\n\n // Simulating copying from items.0 and pasting into disableSort field\n const clipboardData = {\n type: 'array' as const,\n path: 'items',\n fields: [],\n data: {\n 'items.0.id': {\n value: copiedArrayID,\n valid: true,\n },\n 'items.0.text': {\n value: 'row one',\n valid: true,\n },\n },\n rowIndex: 0,\n }\n\n const result = mergeFormStateFromClipboard({\n dataFromClipboard: clipboardData,\n formState,\n path: 'disableSort',\n })\n\n // Check that a new ID was generated\n expect(result['disableSort.0.id']).toBeDefined()\n expect(result['disableSort.0.id'].value).toBeDefined()\n expect(result['disableSort.0.id'].value).not.toEqual(copiedArrayID)\n expect(ObjectId.isValid(result['disableSort.0.id'].value as string)).toBe(true)\n\n // Check that the row metadata has the new ID (not the copied ID)\n expect(result.disableSort.rows).toBeDefined()\n expect(result.disableSort.rows).toHaveLength(1)\n expect(result.disableSort.rows![0].id).not.toEqual(copiedArrayID)\n expect(result.disableSort.rows![0].id).toEqual(result['disableSort.0.id'].value)\n\n // Check that other fields were preserved\n expect(result['disableSort.0.text'].value).toEqual('row one')\n })\n })\n})\n"],"names":["ObjectIdImport","describe","expect","it","mergeFormStateFromClipboard","ObjectId","default","copiedBlockID","toHexString","formState","layout","valid","value","initialValue","rows","clipboardData","type","path","blocks","data","rowIndex","result","dataFromClipboard","toBeDefined","not","toEqual","isValid","toBe","toHaveLength","id","copiedNestedBlockID","duplicate","copiedArrayID","items","fields","copiedNestedArrayID","disableSort"],"mappings":"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"}
@@ -1,4 +1,8 @@
1
1
  import React from 'react';
2
+ export declare function createErrorsFromMessage(message: string): {
3
+ errors?: string[];
4
+ message: string;
5
+ };
2
6
  export declare function FieldErrorsToast({ errorMessage }: {
3
7
  errorMessage: any;
4
8
  }): React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"fieldErrors.d.ts","sourceRoot":"","sources":["../../../src/elements/Toasts/fieldErrors.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAwDzB,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE;;CAAA,qBAmBhD"}
1
+ {"version":3,"file":"fieldErrors.d.ts","sourceRoot":"","sources":["../../../src/elements/Toasts/fieldErrors.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AA6BzB,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB,CAwBA;AAED,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE;;CAAA,qBAmBhD"}
@@ -23,8 +23,10 @@ function groupSimilarErrors(items) {
23
23
  }
24
24
  return result;
25
25
  }
26
- function createErrorsFromMessage(message) {
27
- const [intro, errorsString] = message.split(':');
26
+ export function createErrorsFromMessage(message) {
27
+ const colonIndex = message.indexOf(':');
28
+ const intro = colonIndex >= 0 ? message.slice(0, colonIndex) : message;
29
+ const errorsString = colonIndex >= 0 ? message.slice(colonIndex + 1) : undefined;
28
30
  if (!errorsString) {
29
31
  return {
30
32
  message: intro
@@ -52,7 +54,7 @@ export function FieldErrorsToast({ errorMessage }) {
52
54
  children: errors[0]
53
55
  }, void 0, false, {
54
56
  fileName: "src/elements/Toasts/fieldErrors.tsx",
55
- lineNumber: 67,
57
+ lineNumber: 69,
56
58
  columnNumber: 11
57
59
  }, this) : /*#__PURE__*/ _jsxDEV("ul", {
58
60
  "data-testid": "field-errors",
@@ -61,19 +63,19 @@ export function FieldErrorsToast({ errorMessage }) {
61
63
  children: error
62
64
  }, index, false, {
63
65
  fileName: "src/elements/Toasts/fieldErrors.tsx",
64
- lineNumber: 71,
66
+ lineNumber: 73,
65
67
  columnNumber: 22
66
68
  }, this);
67
69
  })
68
70
  }, void 0, false, {
69
71
  fileName: "src/elements/Toasts/fieldErrors.tsx",
70
- lineNumber: 69,
72
+ lineNumber: 71,
71
73
  columnNumber: 11
72
74
  }, this) : null
73
75
  ]
74
76
  }, void 0, true, {
75
77
  fileName: "src/elements/Toasts/fieldErrors.tsx",
76
- lineNumber: 63,
78
+ lineNumber: 65,
77
79
  columnNumber: 5
78
80
  }, this);
79
81
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/elements/Toasts/fieldErrors.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nfunction groupSimilarErrors(items: string[]): string[] {\n const result: string[] = []\n\n for (const item of items) {\n if (item) {\n const parts = item.split(' → ')\n let inserted = false\n\n // Find a place where a similar path exists\n for (let i = 0; i < result.length; i++) {\n if (result[i].startsWith(parts[0])) {\n result.splice(i + 1, 0, item)\n inserted = true\n break\n }\n }\n\n // If no similar path was found, add to the end\n if (!inserted) {\n result.push(item)\n }\n }\n }\n\n return result\n}\n\nfunction createErrorsFromMessage(message: string): {\n errors?: string[]\n message: string\n} {\n const [intro, errorsString] = message.split(':')\n\n if (!errorsString) {\n return {\n message: intro,\n }\n }\n\n const errors = errorsString.split(',').map((error) => error.replaceAll(' > ', ' → ').trim())\n\n if (errors.length === 1) {\n return {\n errors,\n message: `${intro}: `,\n }\n }\n\n return {\n errors: groupSimilarErrors(errors),\n message: `${intro} (${errors.length}):`,\n }\n}\n\nexport function FieldErrorsToast({ errorMessage }) {\n const [{ errors, message }] = React.useState(() => createErrorsFromMessage(errorMessage))\n\n return (\n <div>\n {message}\n {Array.isArray(errors) && errors.length > 0 ? (\n errors.length === 1 ? (\n <span data-testid=\"field-error\">{errors[0]}</span>\n ) : (\n <ul data-testid=\"field-errors\">\n {errors.map((error, index) => {\n return <li key={index}>{error}</li>\n })}\n </ul>\n )\n ) : null}\n </div>\n )\n}\n"],"names":["React","groupSimilarErrors","items","result","item","parts","split","inserted","i","length","startsWith","splice","push","createErrorsFromMessage","message","intro","errorsString","errors","map","error","replaceAll","trim","FieldErrorsToast","errorMessage","useState","div","Array","isArray","span","data-testid","ul","index","li"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,mBAAmBC,KAAe;IACzC,MAAMC,SAAmB,EAAE;IAE3B,KAAK,MAAMC,QAAQF,MAAO;QACxB,IAAIE,MAAM;YACR,MAAMC,QAAQD,KAAKE,KAAK,CAAC;YACzB,IAAIC,WAAW;YAEf,2CAA2C;YAC3C,IAAK,IAAIC,IAAI,GAAGA,IAAIL,OAAOM,MAAM,EAAED,IAAK;gBACtC,IAAIL,MAAM,CAACK,EAAE,CAACE,UAAU,CAACL,KAAK,CAAC,EAAE,GAAG;oBAClCF,OAAOQ,MAAM,CAACH,IAAI,GAAG,GAAGJ;oBACxBG,WAAW;oBACX;gBACF;YACF;YAEA,+CAA+C;YAC/C,IAAI,CAACA,UAAU;gBACbJ,OAAOS,IAAI,CAACR;YACd;QACF;IACF;IAEA,OAAOD;AACT;AAEA,SAASU,wBAAwBC,OAAe;IAI9C,MAAM,CAACC,OAAOC,aAAa,GAAGF,QAAQR,KAAK,CAAC;IAE5C,IAAI,CAACU,cAAc;QACjB,OAAO;YACLF,SAASC;QACX;IACF;IAEA,MAAME,SAASD,aAAaV,KAAK,CAAC,KAAKY,GAAG,CAAC,CAACC,QAAUA,MAAMC,UAAU,CAAC,OAAO,OAAOC,IAAI;IAEzF,IAAIJ,OAAOR,MAAM,KAAK,GAAG;QACvB,OAAO;YACLQ;YACAH,SAAS,GAAGC,MAAM,EAAE,CAAC;QACvB;IACF;IAEA,OAAO;QACLE,QAAQhB,mBAAmBgB;QAC3BH,SAAS,GAAGC,MAAM,EAAE,EAAEE,OAAOR,MAAM,CAAC,EAAE,CAAC;IACzC;AACF;AAEA,OAAO,SAASa,iBAAiB,EAAEC,YAAY,EAAE;IAC/C,MAAM,CAAC,EAAEN,MAAM,EAAEH,OAAO,EAAE,CAAC,GAAGd,MAAMwB,QAAQ,CAAC,IAAMX,wBAAwBU;IAE3E,qBACE,QAACE;;YACEX;YACAY,MAAMC,OAAO,CAACV,WAAWA,OAAOR,MAAM,GAAG,IACxCQ,OAAOR,MAAM,KAAK,kBAChB,QAACmB;gBAAKC,eAAY;0BAAeZ,MAAM,CAAC,EAAE;;;;;qCAE1C,QAACa;gBAAGD,eAAY;0BACbZ,OAAOC,GAAG,CAAC,CAACC,OAAOY;oBAClB,qBAAO,QAACC;kCAAgBb;uBAARY;;;;;gBAClB;;;;;uBAGF;;;;;;;AAGV"}
1
+ {"version":3,"sources":["../../../src/elements/Toasts/fieldErrors.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nfunction groupSimilarErrors(items: string[]): string[] {\n const result: string[] = []\n\n for (const item of items) {\n if (item) {\n const parts = item.split(' → ')\n let inserted = false\n\n // Find a place where a similar path exists\n for (let i = 0; i < result.length; i++) {\n if (result[i].startsWith(parts[0])) {\n result.splice(i + 1, 0, item)\n inserted = true\n break\n }\n }\n\n // If no similar path was found, add to the end\n if (!inserted) {\n result.push(item)\n }\n }\n }\n\n return result\n}\n\nexport function createErrorsFromMessage(message: string): {\n errors?: string[]\n message: string\n} {\n const colonIndex = message.indexOf(':')\n const intro = colonIndex >= 0 ? message.slice(0, colonIndex) : message\n const errorsString = colonIndex >= 0 ? message.slice(colonIndex + 1) : undefined\n\n if (!errorsString) {\n return {\n message: intro,\n }\n }\n\n const errors = errorsString.split(',').map((error) => error.replaceAll(' > ', ' → ').trim())\n\n if (errors.length === 1) {\n return {\n errors,\n message: `${intro}: `,\n }\n }\n\n return {\n errors: groupSimilarErrors(errors),\n message: `${intro} (${errors.length}):`,\n }\n}\n\nexport function FieldErrorsToast({ errorMessage }) {\n const [{ errors, message }] = React.useState(() => createErrorsFromMessage(errorMessage))\n\n return (\n <div>\n {message}\n {Array.isArray(errors) && errors.length > 0 ? (\n errors.length === 1 ? (\n <span data-testid=\"field-error\">{errors[0]}</span>\n ) : (\n <ul data-testid=\"field-errors\">\n {errors.map((error, index) => {\n return <li key={index}>{error}</li>\n })}\n </ul>\n )\n ) : null}\n </div>\n )\n}\n"],"names":["React","groupSimilarErrors","items","result","item","parts","split","inserted","i","length","startsWith","splice","push","createErrorsFromMessage","message","colonIndex","indexOf","intro","slice","errorsString","undefined","errors","map","error","replaceAll","trim","FieldErrorsToast","errorMessage","useState","div","Array","isArray","span","data-testid","ul","index","li"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,SAASC,mBAAmBC,KAAe;IACzC,MAAMC,SAAmB,EAAE;IAE3B,KAAK,MAAMC,QAAQF,MAAO;QACxB,IAAIE,MAAM;YACR,MAAMC,QAAQD,KAAKE,KAAK,CAAC;YACzB,IAAIC,WAAW;YAEf,2CAA2C;YAC3C,IAAK,IAAIC,IAAI,GAAGA,IAAIL,OAAOM,MAAM,EAAED,IAAK;gBACtC,IAAIL,MAAM,CAACK,EAAE,CAACE,UAAU,CAACL,KAAK,CAAC,EAAE,GAAG;oBAClCF,OAAOQ,MAAM,CAACH,IAAI,GAAG,GAAGJ;oBACxBG,WAAW;oBACX;gBACF;YACF;YAEA,+CAA+C;YAC/C,IAAI,CAACA,UAAU;gBACbJ,OAAOS,IAAI,CAACR;YACd;QACF;IACF;IAEA,OAAOD;AACT;AAEA,OAAO,SAASU,wBAAwBC,OAAe;IAIrD,MAAMC,aAAaD,QAAQE,OAAO,CAAC;IACnC,MAAMC,QAAQF,cAAc,IAAID,QAAQI,KAAK,CAAC,GAAGH,cAAcD;IAC/D,MAAMK,eAAeJ,cAAc,IAAID,QAAQI,KAAK,CAACH,aAAa,KAAKK;IAEvE,IAAI,CAACD,cAAc;QACjB,OAAO;YACLL,SAASG;QACX;IACF;IAEA,MAAMI,SAASF,aAAab,KAAK,CAAC,KAAKgB,GAAG,CAAC,CAACC,QAAUA,MAAMC,UAAU,CAAC,OAAO,OAAOC,IAAI;IAEzF,IAAIJ,OAAOZ,MAAM,KAAK,GAAG;QACvB,OAAO;YACLY;YACAP,SAAS,GAAGG,MAAM,EAAE,CAAC;QACvB;IACF;IAEA,OAAO;QACLI,QAAQpB,mBAAmBoB;QAC3BP,SAAS,GAAGG,MAAM,EAAE,EAAEI,OAAOZ,MAAM,CAAC,EAAE,CAAC;IACzC;AACF;AAEA,OAAO,SAASiB,iBAAiB,EAAEC,YAAY,EAAE;IAC/C,MAAM,CAAC,EAAEN,MAAM,EAAEP,OAAO,EAAE,CAAC,GAAGd,MAAM4B,QAAQ,CAAC,IAAMf,wBAAwBc;IAE3E,qBACE,QAACE;;YACEf;YACAgB,MAAMC,OAAO,CAACV,WAAWA,OAAOZ,MAAM,GAAG,IACxCY,OAAOZ,MAAM,KAAK,kBAChB,QAACuB;gBAAKC,eAAY;0BAAeZ,MAAM,CAAC,EAAE;;;;;qCAE1C,QAACa;gBAAGD,eAAY;0BACbZ,OAAOC,GAAG,CAAC,CAACC,OAAOY;oBAClB,qBAAO,QAACC;kCAAgBb;uBAARY;;;;;gBAClB;;;;;uBAGF;;;;;;;AAGV"}
@@ -0,0 +1,60 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createErrorsFromMessage } from './fieldErrors.js';
3
+ describe('createErrorsFromMessage', ()=>{
4
+ it('should return the full message when there is no colon', ()=>{
5
+ const result = createErrorsFromMessage('Something went wrong');
6
+ expect(result).toEqual({
7
+ message: 'Something went wrong'
8
+ });
9
+ });
10
+ it('should split a single field error after the colon', ()=>{
11
+ const result = createErrorsFromMessage('Validation failed: email');
12
+ expect(result).toEqual({
13
+ errors: [
14
+ 'email'
15
+ ],
16
+ message: 'Validation failed: '
17
+ });
18
+ });
19
+ it('should split multiple comma-separated field errors after the colon', ()=>{
20
+ const result = createErrorsFromMessage('The following fields are invalid: email, name');
21
+ expect(result).toEqual({
22
+ errors: [
23
+ 'email',
24
+ 'name'
25
+ ],
26
+ message: 'The following fields are invalid (2):'
27
+ });
28
+ });
29
+ it('should preserve the full message when it contains multiple colons', ()=>{
30
+ const result = createErrorsFromMessage('With: multiple: colons');
31
+ expect(result).toEqual({
32
+ errors: [
33
+ 'multiple: colons'
34
+ ],
35
+ message: 'With: '
36
+ });
37
+ });
38
+ it('should replace " > " with " → " in error paths', ()=>{
39
+ const result = createErrorsFromMessage('Invalid: parent > child');
40
+ expect(result).toEqual({
41
+ errors: [
42
+ 'parent → child'
43
+ ],
44
+ message: 'Invalid: '
45
+ });
46
+ });
47
+ it('should group similar errors and count them', ()=>{
48
+ const result = createErrorsFromMessage('Invalid: blocks > 0, blocks > 1, other');
49
+ expect(result).toEqual({
50
+ errors: [
51
+ 'blocks → 0',
52
+ 'blocks → 1',
53
+ 'other'
54
+ ],
55
+ message: 'Invalid (3):'
56
+ });
57
+ });
58
+ });
59
+
60
+ //# sourceMappingURL=fieldErrors.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/elements/Toasts/fieldErrors.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { createErrorsFromMessage } from './fieldErrors.js'\n\ndescribe('createErrorsFromMessage', () => {\n it('should return the full message when there is no colon', () => {\n const result = createErrorsFromMessage('Something went wrong')\n\n expect(result).toEqual({ message: 'Something went wrong' })\n })\n\n it('should split a single field error after the colon', () => {\n const result = createErrorsFromMessage('Validation failed: email')\n\n expect(result).toEqual({ errors: ['email'], message: 'Validation failed: ' })\n })\n\n it('should split multiple comma-separated field errors after the colon', () => {\n const result = createErrorsFromMessage('The following fields are invalid: email, name')\n\n expect(result).toEqual({\n errors: ['email', 'name'],\n message: 'The following fields are invalid (2):',\n })\n })\n\n it('should preserve the full message when it contains multiple colons', () => {\n const result = createErrorsFromMessage('With: multiple: colons')\n\n expect(result).toEqual({ errors: ['multiple: colons'], message: 'With: ' })\n })\n\n it('should replace \" > \" with \" → \" in error paths', () => {\n const result = createErrorsFromMessage('Invalid: parent > child')\n\n expect(result).toEqual({ errors: ['parent → child'], message: 'Invalid: ' })\n })\n\n it('should group similar errors and count them', () => {\n const result = createErrorsFromMessage('Invalid: blocks > 0, blocks > 1, other')\n\n expect(result).toEqual({\n errors: ['blocks → 0', 'blocks → 1', 'other'],\n message: 'Invalid (3):',\n })\n })\n})\n"],"names":["describe","expect","it","createErrorsFromMessage","result","toEqual","message","errors"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,uBAAuB,QAAQ,mBAAkB;AAE1DH,SAAS,2BAA2B;IAClCE,GAAG,yDAAyD;QAC1D,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YAAEC,SAAS;QAAuB;IAC3D;IAEAJ,GAAG,qDAAqD;QACtD,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YAAEE,QAAQ;gBAAC;aAAQ;YAAED,SAAS;QAAsB;IAC7E;IAEAJ,GAAG,sEAAsE;QACvE,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YACrBE,QAAQ;gBAAC;gBAAS;aAAO;YACzBD,SAAS;QACX;IACF;IAEAJ,GAAG,qEAAqE;QACtE,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YAAEE,QAAQ;gBAAC;aAAmB;YAAED,SAAS;QAAS;IAC3E;IAEAJ,GAAG,kDAAkD;QACnD,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YAAEE,QAAQ;gBAAC;aAAiB;YAAED,SAAS;QAAY;IAC5E;IAEAJ,GAAG,8CAA8C;QAC/C,MAAME,SAASD,wBAAwB;QAEvCF,OAAOG,QAAQC,OAAO,CAAC;YACrBE,QAAQ;gBAAC;gBAAc;gBAAc;aAAQ;YAC7CD,SAAS;QACX;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/elements/WhereBuilder/Condition/Relationship/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAuD,MAAM,OAAO,CAAA;AAG3E,OAAO,KAAK,EAAE,uBAAuB,IAAI,KAAK,EAAqB,MAAM,YAAY,CAAA;AAQrF,OAAO,cAAc,CAAA;AAOrB,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAwZ9C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/elements/WhereBuilder/Condition/Relationship/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAuD,MAAM,OAAO,CAAA;AAG3E,OAAO,KAAK,EAAE,uBAAuB,IAAI,KAAK,EAAqB,MAAM,YAAY,CAAA;AAQrF,OAAO,cAAc,CAAA;AAOrB,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA2Z9C,CAAA"}
@@ -14,9 +14,13 @@ import optionsReducer from './optionsReducer.js';
14
14
  const baseClass = 'condition-value-relationship';
15
15
  const maxResultsPerRequest = 10;
16
16
  export const RelationshipFilter = (props)=>{
17
- const { disabled, field: { admin = {}, hasMany, relationTo }, filterOptions, onChange, value } = props;
17
+ const { disabled, field: { admin = {}, hasMany, relationTo }, filterOptions, onChange, operator, value } = props;
18
18
  const placeholder = 'placeholder' in admin ? admin?.placeholder : undefined;
19
19
  const isSortable = admin?.isSortable;
20
+ const isMultiValue = hasMany || [
21
+ 'in',
22
+ 'not_in'
23
+ ].includes(operator);
20
24
  const { config: { routes: { api } }, getEntityConfig } = useConfig();
21
25
  const hasMultipleRelations = Array.isArray(relationTo);
22
26
  const [options, dispatchOptions] = useReducer(optionsReducer, []);
@@ -136,7 +140,7 @@ export const RelationshipFilter = (props)=>{
136
140
  }, []);
137
141
  const findOptionsByValue = useCallback(()=>{
138
142
  if (value) {
139
- if (hasMany) {
143
+ if (isMultiValue) {
140
144
  if (Array.isArray(value)) {
141
145
  return value.map((val)=>{
142
146
  if (hasMultipleRelations) {
@@ -179,7 +183,7 @@ export const RelationshipFilter = (props)=>{
179
183
  }
180
184
  return undefined;
181
185
  }, [
182
- hasMany,
186
+ isMultiValue,
183
187
  hasMultipleRelations,
184
188
  value,
185
189
  options
@@ -291,7 +295,7 @@ export const RelationshipFilter = (props)=>{
291
295
  * Load any other options that might exist in the value that were not loaded already
292
296
  */ useEffect(()=>{
293
297
  if (value && hasLoadedFirstOptions) {
294
- if (hasMany) {
298
+ if (isMultiValue) {
295
299
  const matchedOptions = findOptionsByValue();
296
300
  (matchedOptions || []).forEach((option, i)=>{
297
301
  if (!option) {
@@ -317,7 +321,7 @@ export const RelationshipFilter = (props)=>{
317
321
  }, [
318
322
  addOptionByID,
319
323
  findOptionsByValue,
320
- hasMany,
324
+ isMultiValue,
321
325
  hasMultipleRelations,
322
326
  relationTo,
323
327
  value,
@@ -336,18 +340,18 @@ export const RelationshipFilter = (props)=>{
336
340
  children: errorLoading
337
341
  }, void 0, false, {
338
342
  fileName: "src/elements/WhereBuilder/Condition/Relationship/index.tsx",
339
- lineNumber: 387,
343
+ lineNumber: 390,
340
344
  columnNumber: 9
341
345
  }, this) : /*#__PURE__*/ _jsxDEV(ReactSelect, {
342
346
  disabled: disabled,
343
- isMulti: hasMany,
347
+ isMulti: isMultiValue,
344
348
  isSortable: isSortable,
345
349
  onChange: (selected)=>{
346
350
  if (!selected) {
347
351
  onChange(null);
348
352
  return;
349
353
  }
350
- if (hasMany && Array.isArray(selected)) {
354
+ if (isMultiValue && Array.isArray(selected)) {
351
355
  onChange(selected ? selected.map((option)=>{
352
356
  if (hasMultipleRelations) {
353
357
  return {
@@ -373,12 +377,12 @@ export const RelationshipFilter = (props)=>{
373
377
  value: valueToRender
374
378
  }, void 0, false, {
375
379
  fileName: "src/elements/WhereBuilder/Condition/Relationship/index.tsx",
376
- lineNumber: 389,
380
+ lineNumber: 392,
377
381
  columnNumber: 9
378
382
  }, this)
379
383
  }, void 0, false, {
380
384
  fileName: "src/elements/WhereBuilder/Condition/Relationship/index.tsx",
381
- lineNumber: 385,
385
+ lineNumber: 388,
382
386
  columnNumber: 5
383
387
  }, this);
384
388
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/elements/WhereBuilder/Condition/Relationship/index.tsx"],"sourcesContent":["'use client'\nimport type { PaginatedDocs, Where } from 'payload'\n\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { useCallback, useEffect, useReducer, useState } from 'react'\n\nimport type { Option } from '../../../ReactSelect/types.js'\nimport type { RelationshipFilterProps as Props, ValueWithRelation } from './types.js'\n\nimport { useDebounce } from '../../../../hooks/useDebounce.js'\nimport { useEffectEvent } from '../../../../hooks/useEffectEvent.js'\nimport { useConfig } from '../../../../providers/Config/index.js'\nimport { useLocale } from '../../../../providers/Locale/index.js'\nimport { useTranslation } from '../../../../providers/Translation/index.js'\nimport { ReactSelect } from '../../../ReactSelect/index.js'\nimport './index.scss'\nimport optionsReducer from './optionsReducer.js'\n\nconst baseClass = 'condition-value-relationship'\n\nconst maxResultsPerRequest = 10\n\nexport const RelationshipFilter: React.FC<Props> = (props) => {\n const {\n disabled,\n field: { admin = {}, hasMany, relationTo },\n filterOptions,\n onChange,\n value,\n } = props\n\n const placeholder = 'placeholder' in admin ? admin?.placeholder : undefined\n const isSortable = admin?.isSortable\n\n const {\n config: {\n routes: { api },\n },\n getEntityConfig,\n } = useConfig()\n\n const hasMultipleRelations = Array.isArray(relationTo)\n const [options, dispatchOptions] = useReducer(optionsReducer, [])\n const [search, setSearch] = useState('')\n const debouncedSearch = useDebounce(search, 300)\n const [errorLoading, setErrorLoading] = useState('')\n const [hasLoadedFirstOptions, setHasLoadedFirstOptions] = useState(false)\n const { i18n, t } = useTranslation()\n const locale = useLocale()\n\n const relationSlugs = hasMultipleRelations ? relationTo : [relationTo]\n\n const loadedRelationships = React.useRef<\n Map<\n string,\n {\n hasLoadedAll: boolean\n nextPage: number\n }\n >\n >(\n new Map(\n relationSlugs.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n ),\n )\n\n const addOptions = useCallback(\n (data, relation) => {\n const collection = getEntityConfig({ collectionSlug: relation })\n dispatchOptions({ type: 'ADD', collection, data, hasMultipleRelations, i18n, relation })\n },\n [hasMultipleRelations, i18n, getEntityConfig],\n )\n\n const loadOptions = useEffectEvent(\n async ({\n abortController,\n relationSlug,\n }: {\n abortController: AbortController\n relationSlug: string\n }) => {\n const loadedRelationship = loadedRelationships.current.get(relationSlug)\n\n if (relationSlug && !loadedRelationship.hasLoadedAll) {\n const collection = getEntityConfig({\n collectionSlug: relationSlug,\n })\n\n const fieldToSearch = collection?.admin?.useAsTitle || 'id'\n\n const where: Where = {\n and: [],\n }\n\n const query = {\n depth: 0,\n limit: maxResultsPerRequest,\n locale: locale.code,\n page: loadedRelationship.nextPage,\n select: {\n [fieldToSearch]: true,\n },\n where,\n }\n\n if (filterOptions && filterOptions?.[relationSlug]) {\n query.where.and.push(filterOptions[relationSlug])\n }\n\n if (debouncedSearch) {\n query.where.and.push({\n [fieldToSearch]: {\n like: debouncedSearch,\n },\n })\n }\n\n try {\n const response = await fetch(\n formatAdminURL({\n apiRoute: api,\n path: `/${relationSlug}${qs.stringify(query, { addQueryPrefix: true })}`,\n }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n signal: abortController.signal,\n },\n )\n\n if (response.ok) {\n const data: PaginatedDocs = await response.json()\n if (data.docs.length > 0) {\n addOptions(data, relationSlug)\n\n if (data.nextPage) {\n loadedRelationships.current.set(relationSlug, {\n hasLoadedAll: false,\n nextPage: data.nextPage,\n })\n } else {\n loadedRelationships.current.set(relationSlug, {\n hasLoadedAll: true,\n nextPage: null,\n })\n }\n }\n } else {\n setErrorLoading(t('error:unspecific'))\n }\n } catch (e) {\n if (!abortController.signal.aborted) {\n console.error(e) // eslint-disable-line no-console\n }\n }\n }\n\n setHasLoadedFirstOptions(true)\n },\n )\n\n const handleScrollToBottom = React.useCallback(() => {\n const relationshipToLoad = loadedRelationships.current.entries().next().value\n\n if (relationshipToLoad[0] && !relationshipToLoad[1].hasLoadedAll) {\n const abortController = new AbortController()\n\n void loadOptions({\n abortController,\n relationSlug: relationshipToLoad[0],\n })\n }\n }, [])\n\n const findOptionsByValue = useCallback((): Option | Option[] => {\n if (value) {\n if (hasMany) {\n if (Array.isArray(value)) {\n return value.map((val) => {\n if (hasMultipleRelations) {\n let matchedOption: Option\n\n options.forEach((opt) => {\n if (opt.options) {\n opt.options.some((subOpt) => {\n if (subOpt?.value == val.value) {\n matchedOption = subOpt\n return true\n }\n\n return false\n })\n }\n })\n\n return matchedOption\n }\n\n return options.find((opt) => opt.value == val)\n })\n }\n\n return undefined\n }\n\n if (hasMultipleRelations) {\n let matchedOption: Option\n\n const valueWithRelation = value as ValueWithRelation\n\n options.forEach((opt) => {\n if (opt?.options) {\n opt.options.some((subOpt) => {\n if (subOpt?.value == valueWithRelation.value) {\n matchedOption = subOpt\n return true\n }\n return false\n })\n }\n })\n\n return matchedOption\n }\n\n return options.find((opt) => opt.value == value)\n }\n\n return undefined\n }, [hasMany, hasMultipleRelations, value, options])\n\n const handleInputChange = useCallback(\n (input: string) => {\n if (input !== search) {\n dispatchOptions({ type: 'CLEAR', i18n, required: false })\n\n const relationSlugs = Array.isArray(relationTo) ? relationTo : [relationTo]\n\n loadedRelationships.current = new Map(\n relationSlugs.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n )\n\n setSearch(input)\n }\n },\n [i18n, relationTo, search],\n )\n\n const addOptionByID = useCallback(\n async (id, relation) => {\n if (!errorLoading && id !== 'null' && id && relation) {\n const response = await fetch(\n formatAdminURL({ apiRoute: api, path: `/${relation}/${id}?depth=0` }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (response.ok) {\n const data = await response.json()\n addOptions({ docs: [data] }, relation)\n } else {\n // eslint-disable-next-line no-console\n console.error(t('error:loadingDocument', { id }))\n }\n }\n },\n [i18n, addOptions, api, errorLoading, t],\n )\n\n /**\n * When `relationTo` changes externally, reset the options and reload them from scratch\n * The `loadOptions` dependency is a useEffectEvent which has no dependencies of its own\n * This means we can safely depend on it without it triggering this effect to run\n * This is useful because this effect should _only_ run when `relationTo` changes\n */\n useEffect(() => {\n const relations = Array.isArray(relationTo) ? relationTo : [relationTo]\n\n loadedRelationships.current = new Map(\n relations.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n )\n\n dispatchOptions({ type: 'CLEAR', i18n, required: false })\n setHasLoadedFirstOptions(false)\n\n const abortControllers: AbortController[] = []\n\n relations.forEach((relation) => {\n const abortController = new AbortController()\n\n void loadOptions({\n abortController,\n relationSlug: relation,\n })\n\n abortControllers.push(abortController)\n })\n\n return () => {\n abortControllers.forEach((controller) => {\n if (controller.signal) {\n try {\n controller.abort()\n } catch (_err) {\n // swallow error\n }\n }\n })\n }\n }, [i18n, relationTo, debouncedSearch, filterOptions])\n\n /**\n * Load any other options that might exist in the value that were not loaded already\n */\n useEffect(() => {\n if (value && hasLoadedFirstOptions) {\n if (hasMany) {\n const matchedOptions = findOptionsByValue()\n\n ;((matchedOptions as Option[]) || []).forEach((option, i) => {\n if (!option) {\n if (hasMultipleRelations) {\n void addOptionByID(value[i].value, value[i].relationTo)\n } else {\n void addOptionByID(value[i], relationTo)\n }\n }\n })\n } else {\n const matchedOption = findOptionsByValue()\n\n if (!matchedOption) {\n if (hasMultipleRelations) {\n const valueWithRelation = value as ValueWithRelation\n void addOptionByID(valueWithRelation.value, valueWithRelation.relationTo)\n } else {\n void addOptionByID(value, relationTo)\n }\n }\n }\n }\n }, [\n addOptionByID,\n findOptionsByValue,\n hasMany,\n hasMultipleRelations,\n relationTo,\n value,\n hasLoadedFirstOptions,\n ])\n\n const classes = ['field-type', baseClass, errorLoading && 'error-loading']\n .filter(Boolean)\n .join(' ')\n\n const valueToRender = (findOptionsByValue() || value) as Option\n\n return (\n <div className={classes}>\n {errorLoading ? (\n <div className={`${baseClass}__error-loading`}>{errorLoading}</div>\n ) : (\n <ReactSelect\n disabled={disabled}\n isMulti={hasMany}\n isSortable={isSortable}\n onChange={(selected) => {\n if (!selected) {\n onChange(null)\n return\n }\n\n if (hasMany && Array.isArray(selected)) {\n onChange(\n selected\n ? selected.map((option) => {\n if (hasMultipleRelations) {\n return {\n relationTo: option?.relationTo,\n value: option?.value,\n }\n }\n\n return option?.value\n })\n : null,\n )\n } else if (hasMultipleRelations && !Array.isArray(selected)) {\n onChange({\n relationTo: selected?.relationTo,\n value: selected?.value,\n })\n } else if (!Array.isArray(selected)) {\n onChange(selected?.value)\n }\n }}\n onInputChange={handleInputChange}\n onMenuScrollToBottom={handleScrollToBottom}\n options={options}\n placeholder={placeholder}\n value={valueToRender}\n />\n )}\n </div>\n )\n}\n"],"names":["formatAdminURL","qs","React","useCallback","useEffect","useReducer","useState","useDebounce","useEffectEvent","useConfig","useLocale","useTranslation","ReactSelect","optionsReducer","baseClass","maxResultsPerRequest","RelationshipFilter","props","disabled","field","admin","hasMany","relationTo","filterOptions","onChange","value","placeholder","undefined","isSortable","config","routes","api","getEntityConfig","hasMultipleRelations","Array","isArray","options","dispatchOptions","search","setSearch","debouncedSearch","errorLoading","setErrorLoading","hasLoadedFirstOptions","setHasLoadedFirstOptions","i18n","t","locale","relationSlugs","loadedRelationships","useRef","Map","map","relation","hasLoadedAll","nextPage","addOptions","data","collection","collectionSlug","type","loadOptions","abortController","relationSlug","loadedRelationship","current","get","fieldToSearch","useAsTitle","where","and","query","depth","limit","code","page","select","push","like","response","fetch","apiRoute","path","stringify","addQueryPrefix","credentials","headers","language","signal","ok","json","docs","length","set","e","aborted","console","error","handleScrollToBottom","relationshipToLoad","entries","next","AbortController","findOptionsByValue","val","matchedOption","forEach","opt","some","subOpt","find","valueWithRelation","handleInputChange","input","required","addOptionByID","id","relations","abortControllers","controller","abort","_err","matchedOptions","option","i","classes","filter","Boolean","join","valueToRender","div","className","isMulti","selected","onInputChange","onMenuScrollToBottom"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/elements/WhereBuilder/Condition/Relationship/index.tsx"],"sourcesContent":["'use client'\nimport type { PaginatedDocs, Where } from 'payload'\n\nimport { formatAdminURL } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React, { useCallback, useEffect, useReducer, useState } from 'react'\n\nimport type { Option } from '../../../ReactSelect/types.js'\nimport type { RelationshipFilterProps as Props, ValueWithRelation } from './types.js'\n\nimport { useDebounce } from '../../../../hooks/useDebounce.js'\nimport { useEffectEvent } from '../../../../hooks/useEffectEvent.js'\nimport { useConfig } from '../../../../providers/Config/index.js'\nimport { useLocale } from '../../../../providers/Locale/index.js'\nimport { useTranslation } from '../../../../providers/Translation/index.js'\nimport { ReactSelect } from '../../../ReactSelect/index.js'\nimport './index.scss'\nimport optionsReducer from './optionsReducer.js'\n\nconst baseClass = 'condition-value-relationship'\n\nconst maxResultsPerRequest = 10\n\nexport const RelationshipFilter: React.FC<Props> = (props) => {\n const {\n disabled,\n field: { admin = {}, hasMany, relationTo },\n filterOptions,\n onChange,\n operator,\n value,\n } = props\n\n const placeholder = 'placeholder' in admin ? admin?.placeholder : undefined\n const isSortable = admin?.isSortable\n\n const isMultiValue = hasMany || ['in', 'not_in'].includes(operator)\n\n const {\n config: {\n routes: { api },\n },\n getEntityConfig,\n } = useConfig()\n\n const hasMultipleRelations = Array.isArray(relationTo)\n const [options, dispatchOptions] = useReducer(optionsReducer, [])\n const [search, setSearch] = useState('')\n const debouncedSearch = useDebounce(search, 300)\n const [errorLoading, setErrorLoading] = useState('')\n const [hasLoadedFirstOptions, setHasLoadedFirstOptions] = useState(false)\n const { i18n, t } = useTranslation()\n const locale = useLocale()\n\n const relationSlugs = hasMultipleRelations ? relationTo : [relationTo]\n\n const loadedRelationships = React.useRef<\n Map<\n string,\n {\n hasLoadedAll: boolean\n nextPage: number\n }\n >\n >(\n new Map(\n relationSlugs.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n ),\n )\n\n const addOptions = useCallback(\n (data, relation) => {\n const collection = getEntityConfig({ collectionSlug: relation })\n dispatchOptions({ type: 'ADD', collection, data, hasMultipleRelations, i18n, relation })\n },\n [hasMultipleRelations, i18n, getEntityConfig],\n )\n\n const loadOptions = useEffectEvent(\n async ({\n abortController,\n relationSlug,\n }: {\n abortController: AbortController\n relationSlug: string\n }) => {\n const loadedRelationship = loadedRelationships.current.get(relationSlug)\n\n if (relationSlug && !loadedRelationship.hasLoadedAll) {\n const collection = getEntityConfig({\n collectionSlug: relationSlug,\n })\n\n const fieldToSearch = collection?.admin?.useAsTitle || 'id'\n\n const where: Where = {\n and: [],\n }\n\n const query = {\n depth: 0,\n limit: maxResultsPerRequest,\n locale: locale.code,\n page: loadedRelationship.nextPage,\n select: {\n [fieldToSearch]: true,\n },\n where,\n }\n\n if (filterOptions && filterOptions?.[relationSlug]) {\n query.where.and.push(filterOptions[relationSlug])\n }\n\n if (debouncedSearch) {\n query.where.and.push({\n [fieldToSearch]: {\n like: debouncedSearch,\n },\n })\n }\n\n try {\n const response = await fetch(\n formatAdminURL({\n apiRoute: api,\n path: `/${relationSlug}${qs.stringify(query, { addQueryPrefix: true })}`,\n }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n signal: abortController.signal,\n },\n )\n\n if (response.ok) {\n const data: PaginatedDocs = await response.json()\n if (data.docs.length > 0) {\n addOptions(data, relationSlug)\n\n if (data.nextPage) {\n loadedRelationships.current.set(relationSlug, {\n hasLoadedAll: false,\n nextPage: data.nextPage,\n })\n } else {\n loadedRelationships.current.set(relationSlug, {\n hasLoadedAll: true,\n nextPage: null,\n })\n }\n }\n } else {\n setErrorLoading(t('error:unspecific'))\n }\n } catch (e) {\n if (!abortController.signal.aborted) {\n console.error(e) // eslint-disable-line no-console\n }\n }\n }\n\n setHasLoadedFirstOptions(true)\n },\n )\n\n const handleScrollToBottom = React.useCallback(() => {\n const relationshipToLoad = loadedRelationships.current.entries().next().value\n\n if (relationshipToLoad[0] && !relationshipToLoad[1].hasLoadedAll) {\n const abortController = new AbortController()\n\n void loadOptions({\n abortController,\n relationSlug: relationshipToLoad[0],\n })\n }\n }, [])\n\n const findOptionsByValue = useCallback((): Option | Option[] => {\n if (value) {\n if (isMultiValue) {\n if (Array.isArray(value)) {\n return value.map((val) => {\n if (hasMultipleRelations) {\n let matchedOption: Option\n\n options.forEach((opt) => {\n if (opt.options) {\n opt.options.some((subOpt) => {\n if (subOpt?.value == val.value) {\n matchedOption = subOpt\n return true\n }\n\n return false\n })\n }\n })\n\n return matchedOption\n }\n\n return options.find((opt) => opt.value == val)\n })\n }\n\n return undefined\n }\n\n if (hasMultipleRelations) {\n let matchedOption: Option\n\n const valueWithRelation = value as ValueWithRelation\n\n options.forEach((opt) => {\n if (opt?.options) {\n opt.options.some((subOpt) => {\n if (subOpt?.value == valueWithRelation.value) {\n matchedOption = subOpt\n return true\n }\n return false\n })\n }\n })\n\n return matchedOption\n }\n\n return options.find((opt) => opt.value == value)\n }\n\n return undefined\n }, [isMultiValue, hasMultipleRelations, value, options])\n\n const handleInputChange = useCallback(\n (input: string) => {\n if (input !== search) {\n dispatchOptions({ type: 'CLEAR', i18n, required: false })\n\n const relationSlugs = Array.isArray(relationTo) ? relationTo : [relationTo]\n\n loadedRelationships.current = new Map(\n relationSlugs.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n )\n\n setSearch(input)\n }\n },\n [i18n, relationTo, search],\n )\n\n const addOptionByID = useCallback(\n async (id, relation) => {\n if (!errorLoading && id !== 'null' && id && relation) {\n const response = await fetch(\n formatAdminURL({ apiRoute: api, path: `/${relation}/${id}?depth=0` }),\n {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n },\n )\n\n if (response.ok) {\n const data = await response.json()\n addOptions({ docs: [data] }, relation)\n } else {\n // eslint-disable-next-line no-console\n console.error(t('error:loadingDocument', { id }))\n }\n }\n },\n [i18n, addOptions, api, errorLoading, t],\n )\n\n /**\n * When `relationTo` changes externally, reset the options and reload them from scratch\n * The `loadOptions` dependency is a useEffectEvent which has no dependencies of its own\n * This means we can safely depend on it without it triggering this effect to run\n * This is useful because this effect should _only_ run when `relationTo` changes\n */\n useEffect(() => {\n const relations = Array.isArray(relationTo) ? relationTo : [relationTo]\n\n loadedRelationships.current = new Map(\n relations.map((relation) => [\n relation,\n {\n hasLoadedAll: false,\n nextPage: 1,\n },\n ]),\n )\n\n dispatchOptions({ type: 'CLEAR', i18n, required: false })\n setHasLoadedFirstOptions(false)\n\n const abortControllers: AbortController[] = []\n\n relations.forEach((relation) => {\n const abortController = new AbortController()\n\n void loadOptions({\n abortController,\n relationSlug: relation,\n })\n\n abortControllers.push(abortController)\n })\n\n return () => {\n abortControllers.forEach((controller) => {\n if (controller.signal) {\n try {\n controller.abort()\n } catch (_err) {\n // swallow error\n }\n }\n })\n }\n }, [i18n, relationTo, debouncedSearch, filterOptions])\n\n /**\n * Load any other options that might exist in the value that were not loaded already\n */\n useEffect(() => {\n if (value && hasLoadedFirstOptions) {\n if (isMultiValue) {\n const matchedOptions = findOptionsByValue()\n\n ;((matchedOptions as Option[]) || []).forEach((option, i) => {\n if (!option) {\n if (hasMultipleRelations) {\n void addOptionByID(value[i].value, value[i].relationTo)\n } else {\n void addOptionByID(value[i], relationTo)\n }\n }\n })\n } else {\n const matchedOption = findOptionsByValue()\n\n if (!matchedOption) {\n if (hasMultipleRelations) {\n const valueWithRelation = value as ValueWithRelation\n void addOptionByID(valueWithRelation.value, valueWithRelation.relationTo)\n } else {\n void addOptionByID(value, relationTo)\n }\n }\n }\n }\n }, [\n addOptionByID,\n findOptionsByValue,\n isMultiValue,\n hasMultipleRelations,\n relationTo,\n value,\n hasLoadedFirstOptions,\n ])\n\n const classes = ['field-type', baseClass, errorLoading && 'error-loading']\n .filter(Boolean)\n .join(' ')\n\n const valueToRender = (findOptionsByValue() || value) as Option\n\n return (\n <div className={classes}>\n {errorLoading ? (\n <div className={`${baseClass}__error-loading`}>{errorLoading}</div>\n ) : (\n <ReactSelect\n disabled={disabled}\n isMulti={isMultiValue}\n isSortable={isSortable}\n onChange={(selected) => {\n if (!selected) {\n onChange(null)\n return\n }\n\n if (isMultiValue && Array.isArray(selected)) {\n onChange(\n selected\n ? selected.map((option) => {\n if (hasMultipleRelations) {\n return {\n relationTo: option?.relationTo,\n value: option?.value,\n }\n }\n\n return option?.value\n })\n : null,\n )\n } else if (hasMultipleRelations && !Array.isArray(selected)) {\n onChange({\n relationTo: selected?.relationTo,\n value: selected?.value,\n })\n } else if (!Array.isArray(selected)) {\n onChange(selected?.value)\n }\n }}\n onInputChange={handleInputChange}\n onMenuScrollToBottom={handleScrollToBottom}\n options={options}\n placeholder={placeholder}\n value={valueToRender}\n />\n )}\n </div>\n )\n}\n"],"names":["formatAdminURL","qs","React","useCallback","useEffect","useReducer","useState","useDebounce","useEffectEvent","useConfig","useLocale","useTranslation","ReactSelect","optionsReducer","baseClass","maxResultsPerRequest","RelationshipFilter","props","disabled","field","admin","hasMany","relationTo","filterOptions","onChange","operator","value","placeholder","undefined","isSortable","isMultiValue","includes","config","routes","api","getEntityConfig","hasMultipleRelations","Array","isArray","options","dispatchOptions","search","setSearch","debouncedSearch","errorLoading","setErrorLoading","hasLoadedFirstOptions","setHasLoadedFirstOptions","i18n","t","locale","relationSlugs","loadedRelationships","useRef","Map","map","relation","hasLoadedAll","nextPage","addOptions","data","collection","collectionSlug","type","loadOptions","abortController","relationSlug","loadedRelationship","current","get","fieldToSearch","useAsTitle","where","and","query","depth","limit","code","page","select","push","like","response","fetch","apiRoute","path","stringify","addQueryPrefix","credentials","headers","language","signal","ok","json","docs","length","set","e","aborted","console","error","handleScrollToBottom","relationshipToLoad","entries","next","AbortController","findOptionsByValue","val","matchedOption","forEach","opt","some","subOpt","find","valueWithRelation","handleInputChange","input","required","addOptionByID","id","relations","abortControllers","controller","abort","_err","matchedOptions","option","i","classes","filter","Boolean","join","valueToRender","div","className","isMulti","selected","onInputChange","onMenuScrollToBottom"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-types.d.ts","sourceRoot":"","sources":["../../../src/elements/WhereBuilder/field-types.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAa1C,eAAO,MAAM,cAAc;;;GAS1B,CAAA;AA8DD,eAAO,MAAM,mBAAmB,EAAE;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC9C,CAAA;CA0DF,CAAA;AAED,eAAO,MAAM,sBAAsB,yBAGhC;IACD,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,KAAG;IACF,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE;QACd,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,EAAE,CAAA;CAwBJ,CAAA"}
1
+ {"version":3,"file":"field-types.d.ts","sourceRoot":"","sources":["../../../src/elements/WhereBuilder/field-types.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAa1C,eAAO,MAAM,cAAc;;;GAS1B,CAAA;AA8DD,eAAO,MAAM,mBAAmB,EAAE;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC9C,CAAA;CA0DF,CAAA;AAED,eAAO,MAAM,sBAAsB,yBAGhC;IACD,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,KAAG;IACF,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE;QACd,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,EAAE,CAAA;CAqBJ,CAAA"}
@@ -187,16 +187,11 @@ export const fieldTypeConditions = {
187
187
  export const getValidFieldOperators = ({ field, operator })=>{
188
188
  let validOperators = [];
189
189
  if (field.type === 'relationship' && Array.isArray(field.relationTo)) {
190
- if ('hasMany' in field && field.hasMany) {
191
- validOperators = [
192
- ...equalsOperators,
193
- exists
194
- ];
195
- } else {
196
- validOperators = [
197
- ...base
198
- ];
199
- }
190
+ // Polymorphic relationships store {relationTo, value} - in/not_in only match value, not both properties
191
+ validOperators = [
192
+ ...equalsOperators,
193
+ exists
194
+ ];
200
195
  } else {
201
196
  validOperators = [
202
197
  ...fieldTypeConditions[field.type].operators
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/elements/WhereBuilder/field-types.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientField } from 'payload'\n\nconst equalsOperators = [\n {\n label: 'equals',\n value: 'equals',\n },\n {\n label: 'isNotEqualTo',\n value: 'not_equals',\n },\n]\n\nexport const arrayOperators = [\n {\n label: 'isIn',\n value: 'in',\n },\n {\n label: 'isNotIn',\n value: 'not_in',\n },\n]\n\nconst exists = {\n label: 'exists',\n value: 'exists',\n}\n\nconst base = [...equalsOperators, ...arrayOperators, exists]\n\nconst numeric = [\n ...base,\n {\n label: 'isGreaterThan',\n value: 'greater_than',\n },\n {\n label: 'isLessThan',\n value: 'less_than',\n },\n {\n label: 'isLessThanOrEqualTo',\n value: 'less_than_equal',\n },\n {\n label: 'isGreaterThanOrEqualTo',\n value: 'greater_than_equal',\n },\n]\n\nconst geo = [\n ...equalsOperators,\n {\n label: 'near',\n value: 'near',\n },\n]\n\nconst within = {\n label: 'within',\n value: 'within',\n}\n\nconst intersects = {\n label: 'intersects',\n value: 'intersects',\n}\n\nconst like = {\n label: 'isLike',\n value: 'like',\n}\n\nconst notLike = {\n label: 'isNotLike',\n value: 'not_like',\n}\n\nconst contains = {\n label: 'contains',\n value: 'contains',\n}\n\nexport const fieldTypeConditions: {\n [key: string]: {\n component: string\n operators: { label: string; value: string }[]\n }\n} = {\n checkbox: {\n component: 'Text',\n operators: [...equalsOperators, exists],\n },\n code: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n date: {\n component: 'Date',\n operators: [...numeric, exists],\n },\n email: {\n component: 'Text',\n operators: [...base, contains],\n },\n json: {\n component: 'Text',\n operators: [...base, like, contains, notLike, within, intersects],\n },\n number: {\n component: 'Number',\n operators: [...numeric, exists],\n },\n point: {\n component: 'Point',\n operators: [...geo, exists, within, intersects],\n },\n radio: {\n component: 'Select',\n operators: [...base],\n },\n relationship: {\n component: 'Relationship',\n operators: [...base],\n },\n richText: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n select: {\n component: 'Select',\n operators: [...base],\n },\n text: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n textarea: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n upload: {\n component: 'Relationship',\n operators: [...base],\n },\n}\n\nexport const getValidFieldOperators = ({\n field,\n operator,\n}: {\n field: ClientField\n operator?: string\n}): {\n validOperator: string\n validOperators: {\n label: string\n value: string\n }[]\n} => {\n let validOperators: {\n label: string\n value: string\n }[] = []\n\n if (field.type === 'relationship' && Array.isArray(field.relationTo)) {\n if ('hasMany' in field && field.hasMany) {\n validOperators = [...equalsOperators, exists]\n } else {\n validOperators = [...base]\n }\n } else {\n validOperators = [...fieldTypeConditions[field.type].operators]\n }\n\n return {\n validOperator:\n operator && validOperators.find(({ value }) => value === operator)\n ? operator\n : validOperators[0].value,\n validOperators,\n }\n}\n"],"names":["equalsOperators","label","value","arrayOperators","exists","base","numeric","geo","within","intersects","like","notLike","contains","fieldTypeConditions","checkbox","component","operators","code","date","email","json","number","point","radio","relationship","richText","select","text","textarea","upload","getValidFieldOperators","field","operator","validOperators","type","Array","isArray","relationTo","hasMany","validOperator","find"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/elements/WhereBuilder/field-types.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientField } from 'payload'\n\nconst equalsOperators = [\n {\n label: 'equals',\n value: 'equals',\n },\n {\n label: 'isNotEqualTo',\n value: 'not_equals',\n },\n]\n\nexport const arrayOperators = [\n {\n label: 'isIn',\n value: 'in',\n },\n {\n label: 'isNotIn',\n value: 'not_in',\n },\n]\n\nconst exists = {\n label: 'exists',\n value: 'exists',\n}\n\nconst base = [...equalsOperators, ...arrayOperators, exists]\n\nconst numeric = [\n ...base,\n {\n label: 'isGreaterThan',\n value: 'greater_than',\n },\n {\n label: 'isLessThan',\n value: 'less_than',\n },\n {\n label: 'isLessThanOrEqualTo',\n value: 'less_than_equal',\n },\n {\n label: 'isGreaterThanOrEqualTo',\n value: 'greater_than_equal',\n },\n]\n\nconst geo = [\n ...equalsOperators,\n {\n label: 'near',\n value: 'near',\n },\n]\n\nconst within = {\n label: 'within',\n value: 'within',\n}\n\nconst intersects = {\n label: 'intersects',\n value: 'intersects',\n}\n\nconst like = {\n label: 'isLike',\n value: 'like',\n}\n\nconst notLike = {\n label: 'isNotLike',\n value: 'not_like',\n}\n\nconst contains = {\n label: 'contains',\n value: 'contains',\n}\n\nexport const fieldTypeConditions: {\n [key: string]: {\n component: string\n operators: { label: string; value: string }[]\n }\n} = {\n checkbox: {\n component: 'Text',\n operators: [...equalsOperators, exists],\n },\n code: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n date: {\n component: 'Date',\n operators: [...numeric, exists],\n },\n email: {\n component: 'Text',\n operators: [...base, contains],\n },\n json: {\n component: 'Text',\n operators: [...base, like, contains, notLike, within, intersects],\n },\n number: {\n component: 'Number',\n operators: [...numeric, exists],\n },\n point: {\n component: 'Point',\n operators: [...geo, exists, within, intersects],\n },\n radio: {\n component: 'Select',\n operators: [...base],\n },\n relationship: {\n component: 'Relationship',\n operators: [...base],\n },\n richText: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n select: {\n component: 'Select',\n operators: [...base],\n },\n text: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n textarea: {\n component: 'Text',\n operators: [...base, like, notLike, contains],\n },\n upload: {\n component: 'Relationship',\n operators: [...base],\n },\n}\n\nexport const getValidFieldOperators = ({\n field,\n operator,\n}: {\n field: ClientField\n operator?: string\n}): {\n validOperator: string\n validOperators: {\n label: string\n value: string\n }[]\n} => {\n let validOperators: {\n label: string\n value: string\n }[] = []\n\n if (field.type === 'relationship' && Array.isArray(field.relationTo)) {\n // Polymorphic relationships store {relationTo, value} - in/not_in only match value, not both properties\n validOperators = [...equalsOperators, exists]\n } else {\n validOperators = [...fieldTypeConditions[field.type].operators]\n }\n\n return {\n validOperator:\n operator && validOperators.find(({ value }) => value === operator)\n ? operator\n : validOperators[0].value,\n validOperators,\n }\n}\n"],"names":["equalsOperators","label","value","arrayOperators","exists","base","numeric","geo","within","intersects","like","notLike","contains","fieldTypeConditions","checkbox","component","operators","code","date","email","json","number","point","radio","relationship","richText","select","text","textarea","upload","getValidFieldOperators","field","operator","validOperators","type","Array","isArray","relationTo","validOperator","find"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/ui",
3
- "version": "3.80.0-internal-debug.daef79f",
3
+ "version": "3.80.0-internal-debug.cd99b1f",
4
4
  "homepage": "https://payloadcms.com",
5
5
  "repository": {
6
6
  "type": "git",
@@ -136,7 +136,7 @@
136
136
  "ts-essentials": "10.0.3",
137
137
  "use-context-selector": "2.0.0",
138
138
  "uuid": "10.0.0",
139
- "@payloadcms/translations": "3.80.0-internal-debug.daef79f"
139
+ "@payloadcms/translations": "3.80.0-internal-debug.cd99b1f"
140
140
  },
141
141
  "devDependencies": {
142
142
  "@babel/cli": "7.27.2",
@@ -151,14 +151,14 @@
151
151
  "babel-plugin-react-compiler": "19.1.0-rc.3",
152
152
  "esbuild": "0.27.1",
153
153
  "esbuild-sass-plugin": "3.3.1",
154
- "@payloadcms/eslint-config": "3.28.0",
155
- "payload": "3.80.0-internal-debug.daef79f"
154
+ "payload": "3.80.0-internal-debug.cd99b1f",
155
+ "@payloadcms/eslint-config": "3.28.0"
156
156
  },
157
157
  "peerDependencies": {
158
158
  "next": ">=15.2.9 <15.3.0 || >=15.3.9 <15.4.0 || >=15.4.11 <15.5.0 || >=16.2.0-canary.10 <17.0.0",
159
159
  "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
160
160
  "react-dom": "^19.0.1 || ^19.1.2 || ^19.2.1",
161
- "payload": "3.80.0-internal-debug.daef79f"
161
+ "payload": "3.80.0-internal-debug.cd99b1f"
162
162
  },
163
163
  "engines": {
164
164
  "node": "^18.20.2 || >=20.9.0"