payload 1.1.6 → 1.1.8

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/api.js +8 -3
  3. package/dist/admin/components/elements/Autosave/index.js +5 -3
  4. package/dist/admin/components/elements/Nav/index.scss +1 -5
  5. package/dist/admin/components/elements/WhereBuilder/Condition/Relationship/index.js +2 -2
  6. package/dist/admin/components/forms/Form/context.d.ts +5 -2
  7. package/dist/admin/components/forms/Form/context.js +9 -2
  8. package/dist/admin/components/forms/Form/fieldReducer.d.ts +2 -2
  9. package/dist/admin/components/forms/Form/fieldReducer.js +4 -1
  10. package/dist/admin/components/forms/Form/getSiblingData.js +11 -5
  11. package/dist/admin/components/forms/Form/index.js +12 -12
  12. package/dist/admin/components/forms/Form/initContextState.js +0 -3
  13. package/dist/admin/components/forms/Form/reduceFieldsToValues.js +6 -3
  14. package/dist/admin/components/forms/Form/types.d.ts +49 -7
  15. package/dist/admin/components/forms/field-types/Code/Code.js +0 -1
  16. package/dist/admin/components/forms/field-types/ConfirmPassword/index.js +2 -4
  17. package/dist/admin/components/forms/field-types/Email/index.js +0 -1
  18. package/dist/admin/components/forms/field-types/Number/index.js +0 -1
  19. package/dist/admin/components/forms/field-types/Password/index.js +0 -1
  20. package/dist/admin/components/forms/field-types/Point/index.js +0 -1
  21. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.d.ts +4 -0
  22. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.js +67 -0
  23. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/index.scss +117 -0
  24. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/types.d.ts +6 -0
  25. package/dist/admin/components/forms/field-types/Relationship/AddNew/Modal/types.js +1 -0
  26. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.d.ts +4 -0
  27. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.js +79 -0
  28. package/dist/admin/components/forms/field-types/Relationship/AddNew/index.scss +60 -0
  29. package/dist/admin/components/forms/field-types/Relationship/AddNew/types.d.ts +10 -0
  30. package/dist/admin/components/forms/field-types/Relationship/AddNew/types.js +1 -0
  31. package/dist/admin/components/forms/field-types/Relationship/AddNew/useRelatedCollections.d.ts +2 -0
  32. package/dist/admin/components/forms/field-types/Relationship/AddNew/useRelatedCollections.js +10 -0
  33. package/dist/admin/components/forms/field-types/Relationship/index.js +59 -47
  34. package/dist/admin/components/forms/field-types/Relationship/index.scss +23 -12
  35. package/dist/admin/components/forms/field-types/Relationship/optionsReducer.js +8 -7
  36. package/dist/admin/components/forms/field-types/Relationship/types.d.ts +1 -3
  37. package/dist/admin/components/forms/field-types/RichText/elements/relationship/Button/Fields/index.js +2 -3
  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/Input.js +1 -1
  41. package/dist/admin/components/forms/field-types/Upload/SelectExisting/index.js +2 -2
  42. package/dist/admin/components/forms/useField/index.js +71 -97
  43. package/dist/admin/components/forms/useField/types.d.ts +0 -2
  44. package/dist/admin/components/forms/withCondition/index.js +10 -5
  45. package/dist/admin/components/modals/LeaveWithoutSaving/index.scss +2 -2
  46. package/dist/admin/components/templates/Default/index.scss +1 -1
  47. package/dist/admin/components/utilities/DocumentInfo/index.js +3 -3
  48. package/dist/admin/components/utilities/EditDepth/index.d.ts +3 -0
  49. package/dist/admin/components/utilities/EditDepth/index.js +3 -0
  50. package/dist/admin/components/views/Verify/index.js +1 -1
  51. package/dist/admin/components/views/Version/Compare/index.js +1 -1
  52. package/dist/admin/components/views/collections/Edit/Auth/APIKey.js +2 -3
  53. package/dist/admin/components/views/collections/Edit/Auth/index.js +4 -3
  54. package/dist/admin/components/views/collections/Edit/Default.js +9 -9
  55. package/dist/admin/components/views/collections/Edit/index.js +15 -12
  56. package/dist/admin/components/views/collections/Edit/types.d.ts +6 -0
  57. package/dist/admin/components/views/collections/List/RelationshipProvider/index.js +1 -1
  58. package/dist/admin/hooks/useTitle.js +2 -3
  59. package/dist/admin/index.js +1 -1
  60. package/dist/admin/scss/app.scss +6 -1
  61. package/docs/admin/components.mdx +3 -45
  62. package/docs/admin/customizing-css.mdx +1 -1
  63. package/docs/admin/hooks.mdx +271 -0
  64. package/docs/admin/preferences.mdx +1 -1
  65. package/docs/admin/webpack.mdx +1 -1
  66. package/docs/local-api/overview.mdx +1 -1
  67. package/package.json +2 -1
@@ -161,51 +161,9 @@ const CustomTextField: React.FC<Props> = ({ path }) => {
161
161
  }
162
162
  ```
163
163
 
164
- ### Getting other field values from the form
165
-
166
- There are times when a custom field component needs to have access to data from other fields. This can be done using `getDataByPath` from `useWatchForm` as follows:
167
-
168
- ```tsx
169
- import { useWatchForm } from 'payload/components/forms';
170
-
171
- const DisplayFee: React.FC = () => {
172
- const { getDataByPath } = useWatchForm();
173
-
174
- const amount = getDataByPath('amount');
175
- const feePercentage = getDataByPath('feePercentage');
176
-
177
- if (amount && feePercentage) {
178
- return (
179
- <span>The fee is ${(amount * feePercentage) / 100}</span>
180
- );
181
- }
182
- };
183
- ```
184
-
185
- ### Getting the document ID
186
-
187
- The document ID can be very useful for certain custom components. You can get the `id` from the `useDocumentInfo` hook. Here is an example of a `UI` field using `id` to link to related collections:
188
-
189
- ```tsx
190
- import { useDocumentInfo } from 'payload/components/utilities';
191
-
192
- const LinkFromCategoryToPosts: React.FC = () => {
193
- // highlight-start
194
- const { id } = useDocumentInfo();
195
- // highlight-end
196
-
197
- // id will be undefined on the create form
198
- if (!id) {
199
- return null;
200
- }
201
-
202
- return (
203
- <a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`} >
204
- View posts
205
- </a>
206
- )
207
- };
208
- ```
164
+ <Banner type="success">
165
+ For more information regarding the hooks that are available to you while you build custom components, including the <strong>useField</strong> hook, <a href="/docs/admin/hooks" style={{color: 'black'}}>click here</a>.
166
+ </Banner>
209
167
 
210
168
  ## Custom routes
211
169
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Customizing CSS & SCSS
3
3
  label: Customizing CSS
4
- order: 30
4
+ order: 40
5
5
  desc: Customize your Payload admin panel further by adding your own CSS or SCSS style sheet to the configuration, powerful theme and design options are waiting for you.
6
6
  keywords: admin, css, scss, documentation, Content Management System, cms, headless, javascript, node, react, express
7
7
  ---
@@ -0,0 +1,271 @@
1
+ ---
2
+ title: React Hooks
3
+ label: React Hooks
4
+ order: 30
5
+ desc: Make use of all of the powerful React hooks that Payload provides.
6
+ keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, express
7
+ ---
8
+
9
+ Payload provides a variety of powerful hooks that can be used within your own React components. With them, you can interface with Payload itself and build just about any type of complex customization you can think of—directly in familiar React code.
10
+
11
+ ### useField
12
+
13
+ The `useField` hook is used internally within every applicable Payload field component, and it manages sending and receiving a field's state from its parent form.
14
+
15
+ Outside of internal use, its most common use-case is in custom `Field` components. When you build a custom React `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
16
+
17
+ ```tsx
18
+ import { useField } from 'payload/components/forms'
19
+
20
+ type Props = { path: string }
21
+
22
+ const CustomTextField: React.FC<Props> = ({ path }) => {
23
+ // highlight-start
24
+ const { value, setValue } = useField<string>({ path })
25
+ // highlight-end
26
+
27
+ return <input onChange={e => setValue(e.target.value)} value={value.path} />
28
+ }
29
+ ```
30
+
31
+ The `useField` hook accepts an `args` object and sends back information and helpers for you to make use of:
32
+
33
+ ```ts
34
+ const field = useField<string>({
35
+ path: 'fieldPathHere', // required
36
+ validate: myValidateFunc, // optional
37
+ disableFormData?: false, // if true, the field's data will be ignored
38
+ condition?: myConditionHere, // optional, used to skip validation if condition fails
39
+ })
40
+
41
+ // Here is what `useField` sends back
42
+ const {
43
+ showError, // whether or not the field should show as errored
44
+ errorMessage, // the error message to show, if showError
45
+ value, // the current value of the field from the form
46
+ formSubmitted, // if the form has been submitted
47
+ formProcessing, // if the form is currently processing
48
+ setValue, // method to set the field's value in form state
49
+ initialValue, // the initial value that the field mounted with
50
+ } = field;
51
+
52
+ // The rest of your component goes here
53
+ ```
54
+
55
+ ### useFormFields
56
+
57
+ There are times when a custom field component needs to have access to data from other fields, and you have a few options to do so. The `useFormFields` hook is a powerful and highly performant way to retrieve a form's field state, as well as to retrieve the `dispatchFields` method, which can be helpful for setting other fields' form states from anywhere within a form.
58
+
59
+ <Banner type="success">
60
+ <strong>This hook is great for retrieving only certain fields from form state</strong> because it ensures that it will only cause a rerender when the items that you ask for change.
61
+ </Banner>
62
+
63
+ Thanks to the awesome package [`use-context-selector`](https://github.com/dai-shi/use-context-selector), you can retrieve a specific field's state easily. This is ideal because you can ensure you have an up-to-date field state, and your component will only re-render when _that field's state_ changes.
64
+
65
+ You can pass a Redux-like selector into the hook, which will ensure that you retrieve only the field that you want. The selector takes an argument with type of `[fields: Fields, dispatch: React.Dispatch<Action>]]`.
66
+
67
+ ```tsx
68
+ import { useFormFields } from 'payload/components/forms';
69
+
70
+ const MyComponent: React.FC = () => {
71
+ // Get only the `amount` field state, and only cause a rerender when that field changes
72
+ const amount = useFormFields(([fields, dispatch]) => fields.amount);
73
+
74
+ // Do the same thing as above, but to the `feePercentage` field
75
+ const feePercentage = useFormFields(([fields, dispatch]) => fields.feePercentage);
76
+
77
+ if (typeof amount?.value !== 'undefined' && typeof feePercentage?.value !== 'undefined') {
78
+ return (
79
+ <span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
80
+ );
81
+ }
82
+ };
83
+ ```
84
+
85
+ ### useAllFormFields
86
+
87
+ **To retrieve more than one field**, you can use the `useAllFormFields` hook. Your component will re-render when _any_ field changes, so use this hook only if you absolutely need to. Unlike the `useFormFields` hook, this hook does not accept a "selector", and it always returns an array with type of `[fields: Fields, dispatch: React.Dispatch<Action>]]`.
88
+
89
+ You can do lots of powerful stuff by retrieving the full form state, like using built-in helper functions to reduce field state to values only, or to retrieve sibling data by path.
90
+
91
+ ```tsx
92
+ import { useAllFormFields, reduceFieldsToValues, getSiblingData } from 'payload/components/forms';
93
+
94
+ const ExampleComponent: React.FC = () => {
95
+ // the `fields` const will be equal to all fields' state,
96
+ // and the `dispatchFields` method is usable to send field state up to the form
97
+ const [fields, dispatchFields] = useAllFormFields();
98
+
99
+ // Pass in fields, and indicate if you'd like to "unflatten" field data.
100
+ // The result below will reflect the data stored in the form at the given time
101
+ const formData = reduceFieldsToValues(fields, true);
102
+
103
+ // Pass in field state and a path,
104
+ // and you will be sent all sibling data of the path that you've specified
105
+ const siblingData = getSiblingData(fields, 'someFieldName');
106
+
107
+ return (
108
+ // return some JSX here if necessary
109
+ )
110
+ };
111
+ ```
112
+
113
+ ##### Updating other fields' values
114
+
115
+ If you are building a custom component, then you should use `setValue` which is returned from the `useField` hook to programmatically set your field's value. But if you're looking to update _another_ field's value, you can use `dispatchFields` returned from `useFormFields`.
116
+
117
+ You can send the following actions to the `dispatchFields` function.
118
+
119
+ | Action | Description |
120
+ |------------------------|----------------------------------------------------------------------------|
121
+ | **`ADD_ROW`** | Adds a row of data (useful in array / block field data) |
122
+ | **`DUPLICATE_ROW`** | Duplicates a row of data (useful in array / block field data) |
123
+ | **`MODIFY_CONDITION`** | Updates a field's conditional logic result (true / false) |
124
+ | **`MOVE_ROW`** | Moves a row of data (useful in array / block field data) |
125
+ | **`REMOVE`** | Removes a field from form state |
126
+ | **`REMOVE_ROW`** | Removes a row of data from form state (useful in array / block field data) |
127
+ | **`REPLACE_STATE`** | Completely replaces form state |
128
+ | **`UPDATE`** | Update any property of a specific field's state |
129
+
130
+ To see types for each action supported within the `dispatchFields` hook, check out the Form types [here](https://github.com/payloadcms/payload/blob/master/src/admin/components/forms/Form/types.ts).
131
+
132
+ ### useForm
133
+
134
+ The `useForm` hook can be used to interact with the form itself, and sends back many methods that can be used to reactively fetch form state without causing rerenders within your components each time a field is changed. This is useful if you have action-based callbacks that your components fire, and need to interact with form state _based on a user action_.
135
+
136
+ <Banner type="warning">
137
+ <strong>Warning:</strong><br/>
138
+ This hook is optimized to avoid causing rerenders when fields change, and as such, its `fields` property will be out of date. You should only leverage this hook if you need to perform actions against the form in response to your users' actions. Do not rely on its returned "fields" as being up-to-date. They will be removed from this hook's response in an upcoming version.
139
+ </Banner>
140
+
141
+ The `useForm` hook returns an object with the following properties:
142
+
143
+ | Action | Description |
144
+ |----------------------|---------------------------------------------------------------------|
145
+ | **`fields`** | Deprecated. This property cannot be relied on as up-to-date. |
146
+ | **`submit`** | Method to trigger the form to submit |
147
+ | **`dispatchFields`** | Dispatch actions to the form field state |
148
+ | **`validateForm`** | Trigger a validation of the form state |
149
+ | **`createFormData`** | Create a `multipart/form-data` object from the current form's state |
150
+ | **`disabled`** | Boolean denoting whether or not the form is disabled |
151
+ | **`getFields`** | Gets all fields from state |
152
+ | **`getField`** | Gets a single field from state by path |
153
+ | **`getData`** | Returns the data stored in the form |
154
+ | **`getSiblingData`** | Returns form sibling data for the given field path |
155
+ | **`setModified`** | Set the form's `modified` state |
156
+ | **`setProcessing`** | Set the form's `processing` state |
157
+ | **`setSubmitted`** | Set the form's `submitted` state |
158
+ | **`formRef`** | The ref from the form HTML element |
159
+ | **`reset`** | Method to reset the form to its initial state |
160
+
161
+ ### useDocumentInfo
162
+
163
+ The `useDocumentInfo` hook provides lots of information about the document currently being edited, including the following:
164
+
165
+ | Property | Description |
166
+ |---------------------------|------------------------------------------------------------------------------------|
167
+ | **`collection`** | If the doc is a collection, its collection config will be returned |
168
+ | **`global`** | If the doc is a global, its global config will be returned |
169
+ | **`type`** | The type of document being edited (collection or global) |
170
+ | **`id`** | If the doc is a collection, its ID will be returned |
171
+ | **`preferencesKey`** | The `preferences` key to use when interacting with document-level user preferences |
172
+ | **`versions`** | Versions of the current doc |
173
+ | **`unpublishedVersions`** | Unpublished versions of the current doc |
174
+ | **`publishedDoc`** | The currently published version of the doc being edited |
175
+ | **`getVersions`** | Method to trigger the retrieval of document versions |
176
+
177
+ **Example:**
178
+
179
+ ```tsx
180
+ import { useDocumentInfo } from 'payload/components/utilities';
181
+
182
+ const LinkFromCategoryToPosts: React.FC = () => {
183
+ // highlight-start
184
+ const { id } = useDocumentInfo();
185
+ // highlight-end
186
+
187
+ // id will be undefined on the create form
188
+ if (!id) {
189
+ return null;
190
+ }
191
+
192
+ return (
193
+ <a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`} >
194
+ View posts
195
+ </a>
196
+ )
197
+ };
198
+ ```
199
+
200
+ ### useLocale
201
+
202
+ In any custom component you can get the selected locale with the `useLocale` hook. Here is a simple example:
203
+
204
+ ```tsx
205
+ import { useLocale } from 'payload/components/utilities';
206
+
207
+ const Greeting: React.FC = () => {
208
+ // highlight-start
209
+ const locale = useLocale();
210
+ // highlight-end
211
+
212
+ const trans = {
213
+ en: 'Hello',
214
+ es: 'Hola',
215
+ };
216
+
217
+ return (
218
+ <span> { trans[locale] } </span>
219
+ );
220
+ };
221
+ ```
222
+
223
+ ### useAuth
224
+
225
+ Useful to retrieve info about the currently logged in user as well as methods for interacting with it. It sends back an object with the following properties:
226
+
227
+ | Property | Description |
228
+ |---------------------|-----------------------------------------------------------------------------------------|
229
+ | **`user`** | The currently logged in user |
230
+ | **`logOut`** | A method to log out the currently logged in user |
231
+ | **`refreshCookie`** | A method to trigger the silent refreshing of a user's auth token |
232
+ | **`setToken`** | Set the token of the user, to be decoded and used to reset the user and token in memory |
233
+ | **`token`** | The logged in user's token (useful for creating preview links, etc.) |
234
+ | **`permissions`** | The permissions of the current user |
235
+
236
+ ```tsx
237
+ import { useAuth } from 'payload/components/utilities';
238
+ import { User } from '../payload-types.ts';
239
+
240
+ const Greeting: React.FC = () => {
241
+ // highlight-start
242
+ const { user } = useConfig<User>();
243
+ // highlight-end
244
+
245
+ return (
246
+ <span>Hi, {user.email}!</span>
247
+ );
248
+ };
249
+ ```
250
+
251
+ ### useConfig
252
+
253
+ Used to easily fetch the full Payload config.
254
+
255
+ ```tsx
256
+ import { useConfig } from 'payload/components/utilities';
257
+
258
+ const MyComponent: React.FC = () => {
259
+ // highlight-start
260
+ const config = useConfig();
261
+ // highlight-end
262
+
263
+ return (
264
+ <span>{config.serverURL}</span>
265
+ );
266
+ };
267
+ ```
268
+
269
+ ### usePreferences
270
+
271
+ Returns methods to set and get user preferences. More info can be found [here](https://payloadcms.com/docs/admin/preferences).
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Managing User Preferences
3
3
  label: Preferences
4
- order: 40
4
+ order: 50
5
5
  desc: Store the preferences of your users as they interact with the Admin panel.
6
6
  keywords: admin, preferences, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, express
7
7
  ---
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Webpack
3
3
  label: Webpack
4
- order: 50
4
+ order: 60
5
5
  desc: The Payload admin panel uses Webpack 5 and supports many common functionalities such as SCSS and Typescript out of the box to give you more freedom.
6
6
  keywords: admin, webpack, documentation, Content Management System, cms, headless, javascript, node, react, express
7
7
  ---
@@ -323,7 +323,7 @@ const result = await payload.updateGlobal({
323
323
 
324
324
  ## TypeScript
325
325
 
326
- Local API calls also support passing in a generic. This is especially useful if you generate your TS types using a [generate types script](/docs/typescript/generate-types).
326
+ Local API calls also support passing in a generic. This is especially useful if you generate your TS types using a [generate types script](/docs/typescript/generating-types).
327
327
 
328
328
  Here is an example of usage:
329
329
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Node, React and MongoDB Headless CMS and Application Framework",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -181,6 +181,7 @@
181
181
  "terser-webpack-plugin": "^5.0.3",
182
182
  "ts-essentials": "^7.0.1",
183
183
  "url-loader": "^4.1.1",
184
+ "use-context-selector": "^1.4.1",
184
185
  "uuid": "^8.1.0",
185
186
  "webpack": "^5.6.0",
186
187
  "webpack-bundle-analyzer": "^4.4.1",