payload 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/components/forms.ts +10 -0
  2. package/dist/admin/components/elements/Autosave/index.js +3 -3
  3. package/dist/admin/components/elements/Nav/index.scss +1 -5
  4. package/dist/admin/components/elements/ReactSelect/index.scss +5 -1
  5. package/dist/admin/components/forms/Form/context.d.ts +5 -2
  6. package/dist/admin/components/forms/Form/context.js +9 -2
  7. package/dist/admin/components/forms/Form/fieldReducer.d.ts +2 -2
  8. package/dist/admin/components/forms/Form/fieldReducer.js +4 -1
  9. package/dist/admin/components/forms/Form/getSiblingData.js +11 -5
  10. package/dist/admin/components/forms/Form/index.js +12 -12
  11. package/dist/admin/components/forms/Form/initContextState.js +0 -3
  12. package/dist/admin/components/forms/Form/reduceFieldsToValues.js +6 -3
  13. package/dist/admin/components/forms/Form/types.d.ts +49 -7
  14. package/dist/admin/components/forms/field-types/Code/Code.js +0 -1
  15. package/dist/admin/components/forms/field-types/ConfirmPassword/index.js +2 -4
  16. package/dist/admin/components/forms/field-types/Email/index.js +0 -1
  17. package/dist/admin/components/forms/field-types/Number/index.js +0 -1
  18. package/dist/admin/components/forms/field-types/Password/index.js +0 -1
  19. package/dist/admin/components/forms/field-types/Point/index.js +0 -1
  20. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.d.ts +4 -0
  21. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.js +67 -0
  22. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.scss +117 -0
  23. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/types.d.ts +6 -0
  24. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/types.js +1 -0
  25. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.d.ts +4 -0
  26. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.js +79 -0
  27. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.scss +60 -0
  28. package/dist/admin/components/forms/field-types/Relationship/AddNew/types.d.ts +10 -0
  29. package/dist/admin/components/forms/field-types/Relationship/AddNew/types.js +1 -0
  30. package/dist/admin/components/forms/field-types/Relationship/AddNew/useRelatedCollections.d.ts +2 -0
  31. package/dist/admin/components/forms/field-types/Relationship/AddNew/useRelatedCollections.js +10 -0
  32. package/dist/admin/components/forms/field-types/Relationship/index.js +57 -45
  33. package/dist/admin/components/forms/field-types/Relationship/index.scss +15 -12
  34. package/dist/admin/components/forms/field-types/Relationship/optionsReducer.js +8 -7
  35. package/dist/admin/components/forms/field-types/Relationship/types.d.ts +1 -3
  36. package/dist/admin/components/forms/field-types/RichText/elements/relationship/Button/Fields/index.js +2 -3
  37. package/dist/admin/components/forms/field-types/Select/index.scss +1 -9
  38. package/dist/admin/components/forms/field-types/Text/index.js +0 -1
  39. package/dist/admin/components/forms/field-types/Textarea/index.js +0 -1
  40. package/dist/admin/components/forms/field-types/Upload/SelectExisting/index.js +2 -2
  41. package/dist/admin/components/forms/useField/index.js +71 -97
  42. package/dist/admin/components/forms/useField/types.d.ts +0 -2
  43. package/dist/admin/components/forms/withCondition/index.js +10 -5
  44. package/dist/admin/components/modals/LeaveWithoutSaving/index.scss +2 -2
  45. package/dist/admin/components/templates/Default/index.scss +1 -1
  46. package/dist/admin/components/utilities/EditDepth/index.d.ts +3 -0
  47. package/dist/admin/components/utilities/EditDepth/index.js +3 -0
  48. package/dist/admin/components/views/collections/Edit/Auth/APIKey.js +2 -3
  49. package/dist/admin/components/views/collections/Edit/Auth/index.js +3 -3
  50. package/dist/admin/components/views/collections/Edit/Default.js +9 -9
  51. package/dist/admin/components/views/collections/Edit/index.js +15 -12
  52. package/dist/admin/components/views/collections/Edit/types.d.ts +6 -0
  53. package/dist/admin/hooks/useTitle.js +2 -3
  54. package/dist/admin/index.js +1 -1
  55. package/dist/admin/scss/app.scss +6 -1
  56. package/dist/collections/config/defaults.d.ts +5 -5
  57. package/dist/config/types.d.ts +6 -1
  58. package/dist/express/types.d.ts +2 -2
  59. package/dist/fields/config/types.d.ts +2 -2
  60. package/docs/admin/components.mdx +3 -45
  61. package/docs/admin/customizing-css.mdx +1 -1
  62. package/docs/admin/hooks.mdx +271 -0
  63. package/docs/admin/preferences.mdx +1 -1
  64. package/docs/admin/webpack.mdx +1 -1
  65. package/docs/local-api/overview.mdx +1 -1
  66. package/package.json +2 -1
  67. package/types.d.ts +4 -0
@@ -0,0 +1,117 @@
1
+ @import '../../../../../../scss/styles.scss';
2
+
3
+ .relationship-add-new-modal {
4
+ display: flex;
5
+ overflow: hidden;
6
+ position: fixed;
7
+ height: 100vh;
8
+
9
+ &__blur-bg {
10
+ @include blur-bg();
11
+ position: absolute;
12
+ z-index: 1;
13
+ top: 0;
14
+ right: 0;
15
+ bottom: 0;
16
+ left: 0;
17
+ opacity: 0;
18
+ transition: all 300ms ease-out;
19
+ }
20
+
21
+ .collection-edit {
22
+ @include blur-bg();
23
+ transform: translateX(#{base(4)});
24
+ opacity: 0;
25
+ transition: all 300ms ease-out;
26
+ position: relative;
27
+ z-index: 2;
28
+ }
29
+
30
+ .collection-edit__form {
31
+ overflow: auto;
32
+ position: relative;
33
+ z-index: 1;
34
+ }
35
+
36
+ .collection-edit__document-actions {
37
+
38
+ &:before,
39
+ &:after {
40
+ content: none;
41
+ }
42
+ }
43
+
44
+ &--animated {
45
+
46
+ .collection-edit,
47
+ .relationship-add-new-modal__blur-bg,
48
+ .relationship-add-new-modal__close {
49
+ opacity: 1;
50
+ }
51
+
52
+ .collection-edit {
53
+ transform: translateX(0);
54
+ }
55
+ }
56
+
57
+ .collection-edit__document-actions {
58
+ margin-top: base(2.75);
59
+ }
60
+
61
+ &__close {
62
+ @extend %btn-reset;
63
+ position: relative;
64
+ z-index: 2;
65
+ flex-shrink: 0;
66
+ text-indent: -9999px;
67
+ background: rgba(0, 0, 0, 0.08);
68
+ cursor: pointer;
69
+ opacity: 0;
70
+ transition: all 300ms ease-in-out;
71
+ transition-delay: 100ms;
72
+
73
+ &:active,
74
+ &:focus {
75
+ outline: 0;
76
+ }
77
+ }
78
+
79
+ &__header {
80
+ display: flex;
81
+ justify-content: space-between;
82
+ align-items: flex-start;
83
+ margin-top: base(2.5);
84
+ }
85
+
86
+ &__header-close {
87
+ svg {
88
+ width: base(2.5);
89
+ height: base(2.5);
90
+ position: relative;
91
+ top: base(-.5);
92
+ right: base(-.75);
93
+
94
+ .stroke {
95
+ stroke-width: .5px;
96
+ }
97
+ }
98
+ }
99
+
100
+ @include mid-break {
101
+ &__header-close {
102
+ svg {
103
+ top: base(-.75);
104
+ }
105
+ }
106
+
107
+ &__close {
108
+ width: base(1);
109
+ }
110
+ }
111
+ }
112
+
113
+ html[data-theme=dark] {
114
+ .relationship-add-new-modal__close {
115
+ background: rgba(0, 0, 0, 0.2);
116
+ }
117
+ }
@@ -0,0 +1,6 @@
1
+ import { SanitizedCollectionConfig } from '../../../../../../../collections/config/types';
2
+ export declare type Props = {
3
+ modalSlug: string;
4
+ modalCollection: SanitizedCollectionConfig;
5
+ onSave: (json: Record<string, unknown>) => void;
6
+ };
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { Props } from './types';
3
+ import './index.scss';
4
+ export declare const AddNewRelation: React.FC<Props>;
@@ -0,0 +1,79 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { useModal } from '@faceless-ui/modal';
3
+ import Button from '../../../../elements/Button';
4
+ import Popup from '../../../../elements/Popup';
5
+ import { useRelatedCollections } from './useRelatedCollections';
6
+ import { useAuth } from '../../../../utilities/Auth';
7
+ import { AddNewRelationModal } from './Modal';
8
+ import { useEditDepth } from '../../../../utilities/EditDepth';
9
+ import Plus from '../../../../icons/Plus';
10
+ import './index.scss';
11
+ const baseClass = 'relationship-add-new';
12
+ export const AddNewRelation = ({ path, hasMany, relationTo, value, setValue, dispatchOptions }) => {
13
+ const relatedCollections = useRelatedCollections(relationTo);
14
+ const { toggleModal, modalState } = useModal();
15
+ const { permissions } = useAuth();
16
+ const [hasPermission, setHasPermission] = useState(false);
17
+ const [modalCollection, setModalCollection] = useState();
18
+ const [popupOpen, setPopupOpen] = useState(false);
19
+ const editDepth = useEditDepth();
20
+ const modalSlug = `${path}-add-modal-depth-${editDepth}`;
21
+ const openModal = useCallback(async (collection) => {
22
+ setModalCollection(collection);
23
+ toggleModal(modalSlug);
24
+ }, [toggleModal, modalSlug]);
25
+ const onSave = useCallback((json) => {
26
+ const newValue = Array.isArray(relationTo) ? {
27
+ relationTo: modalCollection.slug,
28
+ value: json.doc.id,
29
+ } : json.doc.id;
30
+ dispatchOptions({
31
+ type: 'ADD',
32
+ hasMultipleRelations: Array.isArray(relationTo),
33
+ collection: modalCollection,
34
+ docs: [
35
+ json.doc,
36
+ ],
37
+ sort: true,
38
+ });
39
+ if (hasMany) {
40
+ setValue([...(Array.isArray(value) ? value : []), newValue]);
41
+ }
42
+ else {
43
+ setValue(newValue);
44
+ }
45
+ setModalCollection(undefined);
46
+ toggleModal(modalSlug);
47
+ }, [relationTo, modalCollection, hasMany, toggleModal, modalSlug, setValue, value, dispatchOptions]);
48
+ const onPopopToggle = useCallback((state) => {
49
+ setPopupOpen(state);
50
+ }, []);
51
+ useEffect(() => {
52
+ if (permissions) {
53
+ if (relatedCollections.length === 1) {
54
+ setHasPermission(permissions.collections[relatedCollections[0].slug].create.permission);
55
+ }
56
+ else {
57
+ setHasPermission(relatedCollections.some((collection) => permissions.collections[collection.slug].create.permission));
58
+ }
59
+ }
60
+ }, [permissions, relatedCollections]);
61
+ useEffect(() => {
62
+ var _a;
63
+ if (!((_a = modalState[modalSlug]) === null || _a === void 0 ? void 0 : _a.isOpen)) {
64
+ setModalCollection(undefined);
65
+ }
66
+ }, [modalState, modalSlug]);
67
+ return hasPermission ? (React.createElement("div", { className: baseClass, id: `${path}-add-new` },
68
+ relatedCollections.length === 1 && (React.createElement(Button, { className: `${baseClass}__add-button`, onClick: () => openModal(relatedCollections[0]), buttonStyle: "none", tooltip: `Add new ${relatedCollections[0].labels.singular}` },
69
+ React.createElement(Plus, null))),
70
+ relatedCollections.length > 1 && (React.createElement(Popup, { buttonType: "custom", horizontalAlign: "center", onToggleOpen: onPopopToggle, button: (React.createElement(Button, { className: `${baseClass}__add-button`, buttonStyle: "none", tooltip: popupOpen ? undefined : 'Add new' },
71
+ React.createElement(Plus, null))), render: ({ close: closePopup }) => (React.createElement("ul", { className: `${baseClass}__relations` }, relatedCollections.map((relatedCollection) => {
72
+ if (permissions.collections[relatedCollection.slug].create.permission) {
73
+ return (React.createElement("li", { key: relatedCollection.slug },
74
+ React.createElement("button", { className: `${baseClass}__relation-button ${baseClass}__relation-button--${relatedCollection.slug}`, type: "button", onClick: () => { closePopup(); openModal(relatedCollection); } }, relatedCollection.labels.singular)));
75
+ }
76
+ return null;
77
+ }))) })),
78
+ modalCollection && (React.createElement(AddNewRelationModal, { ...{ onSave, modalSlug, modalCollection } })))) : null;
79
+ };
@@ -0,0 +1,60 @@
1
+ @import '../../../../../scss/styles.scss';
2
+
3
+ .relationship-add-new {
4
+ display: flex;
5
+ align-items: stretch;
6
+
7
+ .popup__wrapper {
8
+ display: flex;
9
+ align-items: stretch;
10
+ height: 100%;
11
+ }
12
+
13
+ &__add-button {
14
+ @include formInput;
15
+ height: 100%;
16
+ margin-left: -1px;
17
+ display: flex;
18
+ padding: 0;
19
+
20
+ .btn__content,
21
+ .btn__label {
22
+ display: flex;
23
+ }
24
+
25
+ .btn__content,
26
+ .btn__label {
27
+ height: 100%;
28
+ }
29
+
30
+ .btn__label {
31
+ padding: 0 base(.5);
32
+ align-items: center;
33
+ }
34
+ }
35
+
36
+
37
+ &__relations {
38
+ list-style: none;
39
+ margin: 0;
40
+ padding: 0;
41
+
42
+ li:not(:last-child) {
43
+ margin-bottom: base(.375);
44
+ }
45
+ }
46
+
47
+ &__relation-button {
48
+ @extend %btn-reset;
49
+ cursor: pointer;
50
+ @extend %btn-reset;
51
+ display: block;
52
+ padding: base(.125) 0;
53
+ text-align: center;
54
+ width: 100%;
55
+
56
+ &:hover {
57
+ opacity: .7;
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Action } from '../types';
3
+ export declare type Props = {
4
+ hasMany: boolean;
5
+ relationTo: string | string[];
6
+ path: string;
7
+ value: unknown;
8
+ setValue: (value: unknown) => void;
9
+ dispatchOptions: React.Dispatch<Action>;
10
+ };
@@ -0,0 +1,2 @@
1
+ import { SanitizedCollectionConfig } from '../../../../../../collections/config/types';
2
+ export declare const useRelatedCollections: (relationTo: string | string[]) => SanitizedCollectionConfig[];
@@ -0,0 +1,10 @@
1
+ import { useState } from 'react';
2
+ import { useConfig } from '../../../../utilities/Config';
3
+ export const useRelatedCollections = (relationTo) => {
4
+ const config = useConfig();
5
+ const [relatedCollections] = useState(() => {
6
+ const relations = typeof relationTo === 'string' ? [relationTo] : relationTo;
7
+ return relations.map((relation) => config.collections.find((collection) => collection.slug === relation));
8
+ });
9
+ return relatedCollections;
10
+ };
@@ -10,13 +10,16 @@ import Label from '../../Label';
10
10
  import Error from '../../Error';
11
11
  import FieldDescription from '../../FieldDescription';
12
12
  import { relationship } from '../../../../../fields/validations';
13
- import { useFormProcessing, useWatchForm } from '../../Form/context';
13
+ import { useFormProcessing, useAllFormFields } from '../../Form/context';
14
14
  import optionsReducer from './optionsReducer';
15
15
  import { createRelationMap } from './createRelationMap';
16
16
  import { useDebouncedCallback } from '../../../../hooks/useDebouncedCallback';
17
17
  import { useDocumentInfo } from '../../../utilities/DocumentInfo';
18
18
  import { getFilterOptionsQuery } from '../getFilterOptionsQuery';
19
19
  import wordBoundariesRegex from '../../../../../utilities/wordBoundariesRegex';
20
+ import reduceFieldsToValues from '../../Form/reduceFieldsToValues';
21
+ import getSiblingData from '../../Form/getSiblingData';
22
+ import { AddNewRelation } from './AddNew';
20
23
  import './index.scss';
21
24
  const maxResultsPerRequest = 10;
22
25
  const baseClass = 'relationship';
@@ -25,7 +28,7 @@ const Relationship = (props) => {
25
28
  const { serverURL, routes: { api, }, collections, } = useConfig();
26
29
  const { id } = useDocumentInfo();
27
30
  const { user, permissions } = useAuth();
28
- const { getData, getSiblingData } = useWatchForm();
31
+ const [fields] = useAllFormFields();
29
32
  const formProcessing = useFormProcessing();
30
33
  const hasMultipleRelations = Array.isArray(relationTo);
31
34
  const [options, dispatchOptions] = useReducer(optionsReducer, required || hasMany ? [] : [{ value: null, label: 'None' }]);
@@ -37,6 +40,7 @@ const Relationship = (props) => {
37
40
  const [search, setSearch] = useState('');
38
41
  const [enableWordBoundarySearch, setEnableWordBoundarySearch] = useState(false);
39
42
  const firstRun = useRef(true);
43
+ const fieldsRef = useRef(fields);
40
44
  const memoizedValidate = useCallback((value, validationOptions) => {
41
45
  return validate(value, { ...validationOptions, required });
42
46
  }, [validate, required]);
@@ -45,6 +49,12 @@ const Relationship = (props) => {
45
49
  validate: memoizedValidate,
46
50
  condition,
47
51
  });
52
+ const getFormData = useCallback(() => {
53
+ return [
54
+ reduceFieldsToValues(fieldsRef.current, true),
55
+ getSiblingData(fieldsRef.current, path),
56
+ ];
57
+ }, [fieldsRef, path]);
48
58
  const getResults = useCallback(async ({ lastFullyLoadedRelation: lastFullyLoadedRelationArg, lastLoadedPage: lastLoadedPageArg, search: searchArg, value: valueArg, sort, }) => {
49
59
  if (!permissions) {
50
60
  return;
@@ -92,7 +102,7 @@ const Relationship = (props) => {
92
102
  const data = await response.json();
93
103
  if (data.docs.length > 0) {
94
104
  resultsFetched += data.docs.length;
95
- dispatchOptions({ type: 'ADD', data, relation, hasMultipleRelations, collection, sort });
105
+ dispatchOptions({ type: 'ADD', docs: data.docs, hasMultipleRelations, collection, sort });
96
106
  setLastLoadedPage(data.page);
97
107
  if (!data.nextPage) {
98
108
  setLastFullyLoadedRelation(relations.indexOf(relation));
@@ -107,7 +117,7 @@ const Relationship = (props) => {
107
117
  else if (response.status === 403) {
108
118
  setLastFullyLoadedRelation(relations.indexOf(relation));
109
119
  lastLoadedPageToUse = 1;
110
- dispatchOptions({ type: 'ADD', data: { docs: [] }, relation, hasMultipleRelations, collection, sort, ids: relationMap[relation] });
120
+ dispatchOptions({ type: 'ADD', docs: [], hasMultipleRelations, collection, sort, ids: relationMap[relation] });
111
121
  }
112
122
  else {
113
123
  setErrorLoading('An error has occurred.');
@@ -175,11 +185,11 @@ const Relationship = (props) => {
175
185
  getResults({ search: searchArg, value: valueArg, sort: true });
176
186
  setSearch(searchArg);
177
187
  }, [getResults]);
178
- const handleInputChange = (searchArg, valueArg) => {
188
+ const handleInputChange = useCallback((searchArg, valueArg) => {
179
189
  if (search !== searchArg) {
180
190
  updateSearch(searchArg, valueArg);
181
191
  }
182
- };
192
+ }, [search, updateSearch]);
183
193
  // ///////////////////////////
184
194
  // Fetch value options when initialValue changes
185
195
  // ///////////////////////////
@@ -207,10 +217,10 @@ const Relationship = (props) => {
207
217
  const collection = collections.find((coll) => coll.slug === relation);
208
218
  if (response.ok) {
209
219
  const data = await response.json();
210
- dispatchOptions({ type: 'ADD', data, relation, hasMultipleRelations, collection, sort: true, ids });
220
+ dispatchOptions({ type: 'ADD', docs: data.docs, hasMultipleRelations, collection, sort: true, ids });
211
221
  }
212
222
  else if (response.status === 403) {
213
- dispatchOptions({ type: 'ADD', data: { docs: [] }, relation, hasMultipleRelations, collection, sort: true, ids });
223
+ dispatchOptions({ type: 'ADD', docs: [], hasMultipleRelations, collection, sort: true, ids });
214
224
  }
215
225
  }
216
226
  }
@@ -219,20 +229,20 @@ const Relationship = (props) => {
219
229
  }
220
230
  }, [hasMany, hasMultipleRelations, relationTo, initialValue, hasLoadedValueOptions, errorLoading, collections, api, serverURL]);
221
231
  useEffect(() => {
222
- if (!filterOptions) {
232
+ if (!filterOptions)
223
233
  return;
224
- }
234
+ const [data, siblingData] = getFormData();
225
235
  const newOptionFilters = getFilterOptionsQuery(filterOptions, {
226
236
  id,
227
- data: getData(),
237
+ data,
228
238
  relationTo,
229
- siblingData: getSiblingData(path),
239
+ siblingData,
230
240
  user,
231
241
  });
232
242
  if (!equal(newOptionFilters, optionFilters)) {
233
243
  setOptionFilters(newOptionFilters);
234
244
  }
235
- }, [relationTo, filterOptions, optionFilters, id, getData, getSiblingData, path, user]);
245
+ }, [relationTo, filterOptions, optionFilters, id, getFormData, path, user]);
236
246
  useEffect(() => {
237
247
  if (optionFilters || !filterOptions) {
238
248
  setHasLoadedValueOptions(false);
@@ -279,39 +289,41 @@ const Relationship = (props) => {
279
289
  } },
280
290
  React.createElement(Error, { showError: showError, message: errorMessage }),
281
291
  React.createElement(Label, { htmlFor: path, label: label, required: required }),
282
- !errorLoading && (React.createElement(ReactSelect, { isDisabled: readOnly, onInputChange: (newSearch) => handleInputChange(newSearch, value), onChange: !readOnly ? (selected) => {
283
- if (hasMany) {
284
- setValue(selected ? selected.map((option) => {
285
- if (hasMultipleRelations) {
286
- return {
287
- relationTo: option.relationTo,
288
- value: option.value,
289
- };
290
- }
291
- return option.value;
292
- }) : null);
293
- }
294
- else if (hasMultipleRelations) {
295
- setValue({
296
- relationTo: selected.relationTo,
297
- value: selected.value,
292
+ !errorLoading && (React.createElement("div", { className: `${baseClass}__wrap` },
293
+ React.createElement(ReactSelect, { isDisabled: readOnly, onInputChange: (newSearch) => handleInputChange(newSearch, value), onChange: !readOnly ? (selected) => {
294
+ if (hasMany) {
295
+ setValue(selected ? selected.map((option) => {
296
+ if (hasMultipleRelations) {
297
+ return {
298
+ relationTo: option.relationTo,
299
+ value: option.value,
300
+ };
301
+ }
302
+ return option.value;
303
+ }) : null);
304
+ }
305
+ else if (hasMultipleRelations) {
306
+ setValue({
307
+ relationTo: selected.relationTo,
308
+ value: selected.value,
309
+ });
310
+ }
311
+ else {
312
+ setValue(selected.value);
313
+ }
314
+ } : undefined, onMenuScrollToBottom: () => {
315
+ getResults({
316
+ lastFullyLoadedRelation,
317
+ lastLoadedPage: lastLoadedPage + 1,
318
+ search,
319
+ value: initialValue,
320
+ sort: false,
298
321
  });
299
- }
300
- else {
301
- setValue(selected.value);
302
- }
303
- } : undefined, onMenuScrollToBottom: () => {
304
- getResults({
305
- lastFullyLoadedRelation,
306
- lastLoadedPage: lastLoadedPage + 1,
307
- search,
308
- value: initialValue,
309
- sort: false,
310
- });
311
- }, value: valueToRender, showError: showError, disabled: formProcessing, options: options, isMulti: hasMany, isSortable: isSortable, filterOption: enableWordBoundarySearch ? (item, searchFilter) => {
312
- const r = wordBoundariesRegex(searchFilter || '');
313
- return r.test(item.label);
314
- } : undefined })),
322
+ }, value: valueToRender, showError: showError, disabled: formProcessing, options: options, isMulti: hasMany, isSortable: isSortable, filterOption: enableWordBoundarySearch ? (item, searchFilter) => {
323
+ const r = wordBoundariesRegex(searchFilter || '');
324
+ return r.test(item.label);
325
+ } : undefined }),
326
+ !readOnly && (React.createElement(AddNewRelation, { ...{ path, hasMany, relationTo, value, setValue, dispatchOptions } })))),
315
327
  errorLoading && (React.createElement("div", { className: `${baseClass}__error-loading` }, errorLoading)),
316
328
  React.createElement(FieldDescription, { value: value, description: description })));
317
329
  };
@@ -5,18 +5,21 @@
5
5
  margin-bottom: $baseline;
6
6
  }
7
7
 
8
- .relationship__error-loading {
9
- border: 1px solid var(--theme-error-500);
10
- min-height: base(2);
11
- padding: base(.5) base(.75);
12
- background-color: var(--theme-error-500);
13
- color: var(--theme-elevation-0);
14
- }
8
+ .relationship {
9
+ &__wrap {
10
+ display: flex;
11
+ width: 100%;
15
12
 
16
- .relationship--read-only {
17
- div.react-select {
18
- div.rs__control {
19
- background: var(--theme-elevation-100);
13
+ div.react-select {
14
+ flex-grow: 1;
20
15
  }
21
16
  }
22
- }
17
+
18
+ &__error-loading {
19
+ border: 1px solid var(--theme-error-500);
20
+ min-height: base(2);
21
+ padding: base(.5) base(.75);
22
+ background-color: var(--theme-error-500);
23
+ color: var(--theme-elevation-0);
24
+ }
25
+ }
@@ -23,24 +23,25 @@ const optionsReducer = (state, action) => {
23
23
  return [];
24
24
  }
25
25
  case 'ADD': {
26
- const { hasMultipleRelations, collection, relation, data, sort, ids = [] } = action;
26
+ const { hasMultipleRelations, collection, docs, sort, ids = [] } = action;
27
+ const relation = collection.slug;
27
28
  const labelKey = collection.admin.useAsTitle || 'id';
28
29
  const loadedIDs = reduceToIDs(state);
29
30
  if (!hasMultipleRelations) {
30
31
  const options = [
31
32
  ...state,
32
- ...data.docs.reduce((docs, doc) => {
33
+ ...docs.reduce((docOptions, doc) => {
33
34
  if (loadedIDs.indexOf(doc.id) === -1) {
34
35
  loadedIDs.push(doc.id);
35
36
  return [
36
- ...docs,
37
+ ...docOptions,
37
38
  {
38
39
  label: doc[labelKey] || `Untitled - ID: ${doc.id}`,
39
40
  value: doc.id,
40
41
  },
41
42
  ];
42
43
  }
43
- return docs;
44
+ return docOptions;
44
45
  }, []),
45
46
  ];
46
47
  ids.forEach((id) => {
@@ -55,11 +56,11 @@ const optionsReducer = (state, action) => {
55
56
  }
56
57
  const newOptions = [...state];
57
58
  const optionsToAddTo = newOptions.find((optionGroup) => optionGroup.label === collection.labels.plural);
58
- const newSubOptions = data.docs.reduce((docs, doc) => {
59
+ const newSubOptions = docs.reduce((docSubOptions, doc) => {
59
60
  if (loadedIDs.indexOf(doc.id) === -1) {
60
61
  loadedIDs.push(doc.id);
61
62
  return [
62
- ...docs,
63
+ ...docSubOptions,
63
64
  {
64
65
  label: doc[labelKey] || `Untitled - ID: ${doc.id}`,
65
66
  relationTo: relation,
@@ -67,7 +68,7 @@ const optionsReducer = (state, action) => {
67
68
  },
68
69
  ];
69
70
  }
70
- return docs;
71
+ return docSubOptions;
71
72
  }, []);
72
73
  ids.forEach((id) => {
73
74
  if (!loadedIDs.includes(id)) {
@@ -1,5 +1,4 @@
1
1
  import { SanitizedCollectionConfig } from '../../../../../collections/config/types';
2
- import { PaginatedDocs } from '../../../../../mongoose/types';
3
2
  import { RelationshipField } from '../../../../../fields/config/types';
4
3
  export declare type Props = Omit<RelationshipField, 'type'> & {
5
4
  path?: string;
@@ -15,8 +14,7 @@ declare type CLEAR = {
15
14
  };
16
15
  declare type ADD = {
17
16
  type: 'ADD';
18
- data: PaginatedDocs<any>;
19
- relation: string;
17
+ docs: any[];
20
18
  hasMultipleRelations: boolean;
21
19
  collection: SanitizedCollectionConfig;
22
20
  sort?: boolean;
@@ -1,7 +1,7 @@
1
1
  import React, { Fragment, useState, useEffect } from 'react';
2
2
  import { useConfig } from '../../../../../../../utilities/Config';
3
3
  import { useAuth } from '../../../../../../../utilities/Auth';
4
- import { useWatchForm } from '../../../../../../Form/context';
4
+ import { useFormFields } from '../../../../../../Form/context';
5
5
  import Relationship from '../../../../../Relationship';
6
6
  import Select from '../../../../../Select';
7
7
  const createOptions = (collections, permissions) => collections.reduce((options, collection) => {
@@ -21,8 +21,7 @@ const RelationshipFields = () => {
21
21
  const { collections } = useConfig();
22
22
  const { permissions } = useAuth();
23
23
  const [options, setOptions] = useState(() => createOptions(collections, permissions));
24
- const { getData } = useWatchForm();
25
- const { relationTo } = getData();
24
+ const relationTo = useFormFields(([fields]) => { var _a; return (_a = fields.relationTo) === null || _a === void 0 ? void 0 : _a.value; });
26
25
  useEffect(() => {
27
26
  setOptions(createOptions(collections, permissions));
28
27
  }, [collections, permissions]);
@@ -3,12 +3,4 @@
3
3
  .field-type.select {
4
4
  position: relative;
5
5
  margin-bottom: $baseline;
6
- }
7
-
8
- .select--read-only {
9
- div.react-select {
10
- div.rs__control {
11
- background: var(--theme-elevation-100);
12
- }
13
- }
14
- }
6
+ }
@@ -12,7 +12,6 @@ const Text = (props) => {
12
12
  const field = useField({
13
13
  path,
14
14
  validate: memoizedValidate,
15
- enableDebouncedValue: true,
16
15
  condition,
17
16
  });
18
17
  const { value, showError, setValue, errorMessage, } = field;
@@ -13,7 +13,6 @@ const Textarea = (props) => {
13
13
  const { value, showError, setValue, errorMessage, } = useField({
14
14
  path,
15
15
  validate: memoizedValidate,
16
- enableDebouncedValue: true,
17
16
  condition,
18
17
  });
19
18
  return (React.createElement(TextareaInput, { path: path, name: name, onChange: (e) => {