Compare commits

..

168 Commits

Author SHA1 Message Date
Sasha
76d1f00765 remove auth 2024-11-26 16:47:09 +02:00
Sasha
0b05eb8f38 feat: enforce maximum call depth for local api operations 2024-11-26 16:25:25 +02:00
Elliot DeNolf
4c4eb2ae2b chore: some strictNullChecks mitigation (#9528) 2024-11-26 09:04:06 -05:00
Paul
71c2f63722 fix(plugin-form-builder): allow overrides to the payment fields group (#9522)
Co-authored-by: mikecebul <mikecebul@gmail.com>
2024-11-25 22:40:34 -06:00
Said Akhrarov
4e3be4414b docs: fix link for storage-uploadthing (#9527)
### What?
Fixes a link to the `storage-uploadthing` adapter in Github.

### Why?
To link readers to the correct package location.

### How?
Change to `docs/upload/storage-adapters.mdx`.

Credit to rik in Discord for the catch.
2024-11-26 03:46:25 +00:00
Patrik
d0af8e8d06 chore(examples): migrates draft-preview example to 3.0 (#9362) 2024-11-25 22:13:15 -05:00
Paul
82145f7bb0 fix(ui): remove overflow hidden from app-header wrappers since it breaks any popout elements (#9525)
Unblocks https://github.com/payloadcms/payload/pull/9391

It was previously impossible to create popout, dropdown or other menus
from buttons added to the app-header component
2024-11-25 18:26:54 -06:00
Jacob Fletcher
0757e06e71 feat: deprecates react-animate-height in favor of native css (#9456)
Deprecates `react-animate-height` in favor of native CSS, specifically
the `interpolate-size: allow-keywords;` property which can be used to
animate to `height: auto`—the primary reason this package exists. This
is one less dependency in our `node_modules`. Tried to replicate the
current DOM structure, class names, and API of `react-animate-height`
for best compatibility.

Note that this CSS property is experimental BUT this PR includes a patch
for browsers without native support. Once full support is reached, the
patch can be safely removed.
2024-11-25 17:48:16 -05:00
Elliot DeNolf
058bd02ebd chore(release): v3.1.1 [skip ci] 2024-11-25 16:42:21 -05:00
Tylan Davis
aa26312b96 docs: adds custom anchor tags to docs with duplicate headings (#9521)
### What?
Adds custom anchor tags to docs where duplicate headings exist.

### Why?
Anchor links would not correctly navigate to the proper point on the
page if there were multiple headings with the same string.

### How?
The website now supports adding custom `#anchor` to a heading in
markdown that will attach to the headings and table of content list
items. This PR adds custom anchors to the docs that have duplicate
headings.

**Example:**
```md
/docs/upload/storage-adapters.mdx

### Usage#vercel-blob-installation
```
Generates the path:
`/docs/upload/storage-adapters#vercel-blob-installation`
2024-11-25 16:31:08 -05:00
Sasha
b5f89d5199 fix(db-mongodb): sanitizeRelationshipIDs named tabs within tabs (#9400)
Ensures `sanitizeRelationshipIDs` works properly in any case
Updates predefinedMigration to work with new globals
Skips ObjectID creation errors to not fail with outdated data to the
schema.
2024-11-25 16:27:47 -05:00
dependabot[bot]
c8589a640c chore(deps): bump eslint-plugin-playwright from 1.7.0 to 2.1.0 (#9474)
Bumps
[eslint-plugin-playwright](https://github.com/playwright-community/eslint-plugin-playwright)
from 1.7.0 to 2.1.0.
2024-11-25 15:29:52 -05:00
Elliot DeNolf
da788413eb ci: only security PRs from dependabot 2024-11-25 15:20:14 -05:00
Said Akhrarov
0c7e418dbc fix(translations): add sl to acceptedLanguages (#9506)
<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
### What?
This PR adds `'sl'` to list of accepted languages, dedupes languages not
implemented from langs that have been supported, and adjusts the string
match for `'sl'` in importDateFNSLocale to the correct locale.

### Why?
To fix TS errors and runtime errors encountered while adding Slovenian
language to config, and then selecting it in `/account` view.

### How?
- Addition of `'sl'` to `acceptLanguages` array
- Change from `'sl'` to `'sl-SI'` in `importDateFNSLocale.ts`

Fixes #9504

---------

Co-authored-by: Jessica Chowdhury <jessica@trbl.design>
2024-11-25 20:17:05 +00:00
Jacob Fletcher
8383426313 fix(ui): prevents column reset on sort (#9517)
Fixes #9492. Sorting columns would unintentionally clear column
preferences.
2024-11-25 15:15:07 -05:00
Francisco Lourenço
af096a374a fix(ui): z-index on react-select menu (#9512)
The [previous fix](https://github.com/payloadcms/payload/pull/8735)
worked but was a breaking change because it set a `z-index` in the
`.react-select` wrapper instead of the `.rs__menu`, creating a new
stacking-context, therefore making any existing customizations to the
menu's `z-index` not work. This was a way to fix a regression introduced
by the css-layers, in which Payload's custom `z-index: 4` no longer took
precedence over react-select's default `z-index: 1`.

With this PR we remove the default `z-index: 1` applied by react-select,
so that the `z-index: 4` set in the "payload-default" css layer can take
effect. An alternative to this fix would be to use `z-index: 4
!important`, but this has the advantage of allowing the `z-index` to be
easily customized by the consumers of the CMS, as with all the other
styles.

### Screenshots

![2024-11-25 18 21
22](https://github.com/user-attachments/assets/3dc9a067-901a-41ea-b04e-c811788f8415)
2024-11-25 14:10:20 -06:00
Jarrod Flesch
6ffd4c7825 fix: incorrect locale registration in datepicker (#9516)
### What?
This log was appearing when the DatePicker loaded without a registered
locale:
```
A locale object was not found for the provided string ["enUS"].
```
Also fixes css misalignment of icons inside date picker field

### Why?
If i`18n.dateFNS` had not loaded, we were registering the locale with an
undefined value.

### How?
Only register the locale for react-datepicker if i18n.dateFNS is
present.
2024-11-25 15:05:15 -05:00
Elliot DeNolf
08270426ba ci: update release-canary name 2024-11-25 14:08:18 -05:00
Jacob Fletcher
f136a7db2a fix: improper spread of list preferences (#9510)
List preferences were improperly saving their own records onto
themselves when building table state through the server function. This
was happening because the entire preference document was being spread
onto the new preferences, as opposed to just the value itself:

```diff
const mergedPrefs = {
-  ...(preferencesResult || {}),
+  ...(preferencesResult?.value || {}),
   columns,
}
```

This PR also swaps `dequal` out for `dequal/lite`.
2024-11-25 13:56:35 -05:00
Sasha
e176b8b764 fix: correct migrations sorting in getMigrations (#9330)
### What?
We sorted migrations by `-name` in `getMigrations` as by assumption from
generated file names, however, it may be not true as the improved (+
unflaked, previously it failed sometimes) test for `migrate:down` can
reproduce. As in result, `migrateDown` / `migrateRefresh` may execute in
order different from `migrate`.

Unflakes the 'should commit multiple operations async'  test.
We shouldn't pass the same `req` that doesn't contain a transaction to
different operations that execute in parallel (via `Promise.all`)
without either creating a transaction before or using
`isolateObjectProperty(req, 'transactionID')`. It leads to a race
condition because operation can commit a wrong transaction, different
from inited
2024-11-25 13:53:44 -05:00
Elliot DeNolf
3c8f042d1d ci: update release-canary workflow 2024-11-25 13:38:38 -05:00
Sasha
e5cc9153aa fix(db-postgres): allow to clear select fields with hasMany: true (#9464)
### What?
Previously, using Postgres, select fields with `hasMany: true` weren't
clearable.
Meaning, you couldn't pass an empty array:
```ts
const updatedDoc = await payload.update({
  id,
  collection: 'select-fields',
  data: {
    selectHasMany: [],
  },
})
```

### Why?
To achieve the same behavior with MongoDB.

### How?
Modifies logic in `packages/drizzle/src/upsertRow/index.ts` to include
empty arrays.
2024-11-25 11:15:19 -05:00
Sasha
b96475b7b9 fix: run queues via the /payload-jobs/run endpoint without workflows (#9509)
Fixes https://github.com/payloadcms/payload/discussions/9418 (the
`/api/payload-jobs/run` endpoint) when the config doesn't have any
`workflows` but only `tasks`
2024-11-25 17:57:51 +02:00
Sasha
cae300e8e3 perf: flattenedFields collection/global property, remove deep copying in validateQueryPaths (#9299)
### What?
Improves querying performance of the Local API, reduces copying overhead

### How?

Adds `flattenedFields` property for sanitized collection/global config
which contains fields in database schema structure.
For example, It removes rows / collapsible / unnamed tabs and merges
them to the parent `fields`, ignores UI fields, named tabs are added as
`type: 'tab'`.
This simplifies code in places like Drizzle `transform/traverseFields`.
Also, now we can avoid calling `flattenTopLevelFields` which adds some
overhead and use `collection.flattenedFields` / `field.flattenedFields`.

By refactoring `configToJSONSchema.ts` with `flattenedFields` it also
1. Fixes https://github.com/payloadcms/payload/issues/9467
2. Fixes types for UI fields were generated for `select`



Removes this deep copying for each `where` query constraint
58ac784425/packages/payload/src/database/queryValidation/validateQueryPaths.ts (L69-L73)
which potentially can add overhead if you have a large collection/global
config

UPD:
The overhead is even much more than in the benchmark below if you have
Lexical with blocks.

Benchmark in `relationships/int.spec.ts`:
```ts
const now = Date.now()
for (let i = 0; i < 10; i++) {
  const now = Date.now()
  for (let i = 0; i < 300; i++) {
    const query = await payload.find({
      collection: 'chained',
      where: {
        'relation.relation.name': {
          equals: 'third',
        },
        and: [
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
          {
            'relation.relation.name': {
              equals: 'third',
            },
          },
        ],
      },
    })
  }

  payload.logger.info(`#${i + 1} ${Date.now() - now}`)
}
payload.logger.info(`Total ${Date.now() - now}`)
```

Before:
```
[02:11:48] INFO: #1 3682
[02:11:50] INFO: #2 2199
[02:11:54] INFO: #3 3483
[02:11:56] INFO: #4 2516
[02:11:59] INFO: #5 2467
[02:12:01] INFO: #6 1987
[02:12:03] INFO: #7 1986
[02:12:05] INFO: #8 2375
[02:12:07] INFO: #9 2040
[02:12:09] INFO: #10 1920
    [PASS] Relationships > Querying > Nested Querying > should allow querying two levels deep (24667ms)
[02:12:09] INFO: Total 24657
```

After:
```
[02:12:36] INFO: #1 2113
[02:12:38] INFO: #2 1854
[02:12:40] INFO: #3 1700
[02:12:42] INFO: #4 1797
[02:12:44] INFO: #5 2121
[02:12:46] INFO: #6 1774
[02:12:47] INFO: #7 1670
[02:12:49] INFO: #8 1610
[02:12:50] INFO: #9 1596
[02:12:52] INFO: #10 1576
    [PASS] Relationships > Querying > Nested Querying > should allow querying two levels deep (17828ms)
[02:12:52] INFO: Total 17818
```
2024-11-25 10:28:07 -05:00
Elliot DeNolf
8658945d7b chore(templates): remove unneeded lock files, add hook (#9508)
- Update lock files for blank, website
- Delete unneeded lock files
- Adds git hook to ensure no new lockfiles are added for _other than_
blank and website.
2024-11-25 10:04:41 -05:00
Sasha
aa1d300062 feat(templates): website template performance improvements (#9466)
- Uses `pagination: false` where we don't need `totalDocs`.
- in `preview/route.ts` uses `depth: 0`, select of only ID to improve
performance
- in `search` uses `select` to select only needed properties
- adds type safety best practices to collection configs with
`defaultPopulate`
- uses `payload.count` to resolve SSG `pageNumber`s
2024-11-25 10:02:27 -05:00
Sasha
150c55de79 chore(next): remove deep copying of docPermissions in the Version View (#9491)
Removes unnecessary `deepCopyObject(docPermissions)` in the Version View
which slows down loading speed.
The comment seems to be resolved, I'm not getting this error and here
for example in the same case
3c0e832a9a/packages/next/src/views/Document/index.tsx (L327)
we don't do deep copying.
2024-11-25 09:20:22 -05:00
Jeffrey Arts
4b4cfbeca7 docs: add migration-guide note public dir changes (#9498)
The location of public directory has changed, this addition highlights
this change and how to resolve it
2024-11-25 09:17:34 -05:00
Sasha
7eb388d403 fix: ensure deleteJobOnComplete property for jobs works (#9283)
Ensures that the `deleteJobOnComplete` (which is `true` by default)
property works properly
2024-11-25 09:11:15 -05:00
Harley Salas
07c76aa3b9 chore(translations): improve russian translation for noResults (#9496)
### What?
The "noResults" translation key, for Russian, which is displayed when
searching a collection list and receiving no results.

![image](https://github.com/user-attachments/assets/b83204c9-0467-42e4-9f38-5a38548e5459)


### Why?
Unlike English, Slavic languages like Russian have the concept of
genders and depending on the ending of a particular word, the endings of
adjectives can be different, to correspond with those genders. The
current version only works with feminine words, directly translating to
"No {{label}} found. Either {{label}} doesn't exist yet, or none of them
match the filters you specified above."
The new version translates to "Nothing found. {{label}} may not exist
yet or doesn't match the specified filters.", which is a more loose
translation, but holds the same meaning, while being grammatically
correct in all scenarios, regardless of the gender.
2024-11-25 12:37:34 +02:00
Said Akhrarov
9c59359da6 docs: fix invalid links (#9500)
### What?
This PR fixes a variety of links around the docs.

### Why?
To link readers to the correct location in the docs

### How?
Changes and fixes to a number of doc links.
2024-11-24 19:18:33 -07:00
Indy
3c0e832a9a docs: spelling error in README.md (#9478)
## Title

fix(docs): correct "kayout" typo to "layout" in README.md

### What?
- Corrected a typo in the `README.md` file where "kayout" was
incorrectly written instead of "layout".

### Why?
- To improve the documentation's readability and professionalism.

### How?
- Located the typo in `README.md` and replaced "kayout" with "layout".

Fixes #9472

----


### Before
<img width="1148" alt="before"
src="https://github.com/user-attachments/assets/232d0e01-ea06-4568-b283-afad09719f0c">

### After
<img width="1208" alt="after"
src="https://github.com/user-attachments/assets/f96f3b6c-6ccc-4d2e-8de3-88b9057a6cab">

---------

Co-authored-by: Indy S <billabong@Mac.attlocal.net>
2024-11-24 08:30:18 +00:00
Alessio Gravili
13fc94dc4d chore: upgrade to TypeScript 5.7, ensure tsconfig targed and lib properties match the APIs we support (#9473)
TS 5.7 added support for ES2024. By keeping target: “esnext”, we would
have accidentally set our minimum supported ES version to ES2024.

This sets it to ES2022, which is the version supported by Node 18
2024-11-23 16:35:27 -07:00
Paul
23d54a76c1 fix(templates): website template firefox logo fix and images fix on vercel (#9459)
Fixes logo not showing up on firefox and images not loading properly
when hosting with Vercel
2024-11-22 23:53:06 +00:00
Elliot DeNolf
f155e00f00 docs: proper readme (#9458)
Updated `packages/payload` README by copying down the top-level README.
We incorrectly thought this was some sort of caching issue on NPM.

Closes #9452
2024-11-22 18:01:50 -05:00
Paul
09abebd58c fix(templates): vercel website template payload config regression (#9455) 2024-11-22 20:18:04 +00:00
Paul
90fedbc16b fix(templates): fixes imports in website template from @payloadcms/ui to be direct (#9451) 2024-11-22 19:08:38 +00:00
Paul
322738fca3 chore(templates): copy over improvements to the vercel website template and add vscode debug config (#9450)
Copied over the improvements from the website template into the vercel
website template.

Add vscode debug config to both templates.
2024-11-22 18:42:28 +00:00
Paul
be8cd7f4d9 feat(templates): website optimisations for image sizes and loading (#9447)
Adds defaultPopulate on pages and posts
Further optimises images and fetching staticParams
2024-11-22 18:21:56 +00:00
Jacob Fletcher
b9d02aa3a8 chore: removes leftover references to beta (#9445)
Still a few leftover references to beta in various JSDocs and other
places.
2024-11-22 13:19:20 -05:00
Elliot DeNolf
65ac739da9 chore(release): v3.1.0 [skip ci] 2024-11-22 11:54:08 -05:00
Jacob Fletcher
ae6c71b3b5 fix(live-preview): client-side live preview cannot clear all array rows (#9439)
When using Client-side Live Preview, array fields are unable to clear
all their rows. This is because `reduceFieldsToValues` sets the array's
value as 0 within form-state when no rows exist, as opposed to an empty
array as one might expect. For now, we can simply handle this data shape
within Live Preview's merge logic. In the future we may want to take to
consider changing the behavior of empty arrays within form-state itself.
2024-11-22 16:43:48 +00:00
Riley Pearce
27acdaee7a fix(ui): add disabled attribute to blocks drawer toggler (#9424)
### What?

When `update` access control is set to `false`, the blocks drawer can
still be accessed. Blocks still cannot be saved to the document, making
this more of a QoL improvement.

### Why?

The blocks `DrawerToggler` is missing the `disabled` attribute.

### How?

Adding the `disabled` attribute to the blocks `DrawerToggler`.

### Reproduction steps

https://github.com/rilrom/payload/tree/issue/disabled-add-block-button

1. Navigate to the posts collection.
2. Click the 'Add blocks' button.
3. Blocks can be selected (however they are still readonly in the
document and cannot be saved).

### Recordings

Before


https://github.com/user-attachments/assets/da12829d-5b27-4da9-bbd1-067d679a89ba

After


https://github.com/user-attachments/assets/67166477-b83a-4495-98ae-2d272542103b
2024-11-22 08:59:38 -07:00
Jessica Chowdhury
fb3242df0a feat: add skip and force accept flags to migration commands (#8843)
1. Adds flag `--skip-empty` to `migrate:create` to bypass the empty
migration file prompt.
    - Blank migration file will not be created if this flag is passed.
3. Adds flag `--force-accept-warning` to `migrate:fresh` to bypass the
drop database prompt
2024-11-22 10:37:54 -05:00
Germán Jabloñski
251c4c30d7 chore: fix path and samples for lexical-mdx tests (#9433)
Later we could add better examples that test complex use cases, but at
least this allows the code to compile.
2024-11-22 14:55:39 +00:00
Alessio Gravili
9e31e17e31 feat(richtext-lexical): more powerful custom Block RSCs, improved selection handling (#9422)
Now, custom Lexical block & inline block components are re-rendered if
the fields drawer is saved. This ensures that RSCs receive the updated
values, without having to resort to a client component that utilizes the
`useForm` hook.

Additionally, this PRs fixes the lexical selection jumping around after
opening a Block or InlineBlock drawer and clicking inside of it.
2024-11-22 02:34:29 +00:00
Alessio Gravili
b9cc4d4083 fix(richtext-lexical): error when changing block collapsed state in rare cases (#9421) 2024-11-22 01:13:03 +00:00
Alessio Gravili
a891e98bfc fix(richtext-lexical): slash menu from + button did not trigger item select action (#9420)
Fixes a bug I introduced through
https://github.com/payloadcms/payload/pull/9396 and adds an e2e test
2024-11-22 00:48:45 +00:00
Alessio Gravili
38de760ca5 feat(richtext-lexical): allow customizing maxActiveItems for toolbar groups (#9417)
Previously, they were hardcoded to 1. This is useful for lexical toolbar
groups where multiple items can be active at the same time.
2024-11-21 23:53:29 +00:00
Paul
18b139b9de fix(templates): website template breaking change by renaming hero image to jpg (#9416) 2024-11-21 21:42:29 +00:00
Alessio Gravili
3b68671348 feat(richtext-lexical): export lexical drawer hooks (#9415) 2024-11-21 21:12:17 +00:00
Sasha
91dcf6dc08 fix: invalid payload.collections type (#9414)
### What?
`payload.collections` was improperly typed.
This doesn't seem to work: (the type is `{}`)
```
collections: {
  [slug: CollectionSlug]: Collection
} = {}
```
<img width="794" alt="image"
src="https://github.com/user-attachments/assets/7daceab9-8f43-433b-9201-1bf8c48fb8ca">

However, this does:
```ts
collections: Record<CollectionSlug, Collection> = {}
```
<img width="540" alt="image"
src="https://github.com/user-attachments/assets/e37d595d-f5b4-4b02-b190-bb5d4063787d">


Additionally, the same fix applied to `Permissions`,
`PolymorphicUploadField['admin']['sortOptions']`,
`PolymorphicRelationshipField['admin']['sortOptions']`
2024-11-21 22:58:04 +02:00
Jacob Fletcher
f5683b0a64 fix(next): threads server props to custom providers (#9412)
When defining custom providers as server components, they currently do
not receive any of the server props that custom components expect to
receive, like `payload`, `i18n`, `user`, and so on.
2024-11-21 15:44:32 -05:00
Paul
2036a566fd feat(templates): update website styles and new home hero image (#9413) 2024-11-21 20:39:56 +00:00
Friggo
0b4e5a6ece chore(templates): updates github urls in seed data (#9376)
Update the GitHub URLs to website template to point to main instead of beta
2024-11-21 15:35:07 -05:00
Alessio Gravili
e3866c4035 fix(ui): stale server components when rows are moved (#9410)
We need to trigger server component re-rendering for moving rows, just
like we do for adding or deleting rows.

Video of the issue:


https://github.com/user-attachments/assets/32fb31c5-f304-4082-8028-59a6ad723fbe
2024-11-21 20:14:57 +00:00
Patrik
f338c5c40c chore(examples): updates custom-components,email & multi-tenant to latest payload version (#9411)
### What?

Although the following examples:

- `custom-components`
- `email`
- `multi-tenant`

were recently migrated to 3.0 - they were still using the latest `beta`
version instead of latest payload (i.e `3.0`)
2024-11-21 14:56:34 -05:00
Jacob Fletcher
118b442883 docs: custom server providers and filter components (#9303)
- Removes mention of custom providers needing to be client components
- Documents custom field `Filter` components
- Adjusts language and other misc. grammar and spelling
2024-11-21 14:25:37 -05:00
Jarrod Flesch
ee1a91ee7c fix: unable to load documents with non-standard ids (#9407)
### What?
Non-standard ids caused an issue when finding the document on the
server.

This is an odd regression, in 2.0 we were fetching the document on the
client so the request would handle decoding the url. Now we are fetching
the document on the server and need to do this manually when reading id
from route params.

### Why?
The slug pulled out of the url for an id of `id 1` would equate to
`id%201` which would fail in the `payload.find` call since there is not
an id stored as `id%201` but instead `id 1`.

### How?
Wherever we are calling payload.find in the views and querying by `id`
it gets ran through a helper function that decodes it properly.

Fixes #9373
2024-11-21 14:16:01 -05:00
Patrik
304ecd29ac docs: removes public demo references (#9408)
### What?

Removes all references to the `public-demo` from the docs
2024-11-21 14:09:08 -05:00
Jarrod Flesch
204b08bc25 chore: update issue templates (#9409)
Removes mentions of `beta` in issue templates now that 3.0 has been
released.
2024-11-21 13:56:16 -05:00
Sasha
f2205d1694 fix(next): next@15.0.3 compatibillity for turbopack warnings patch (#9341)
Added patch to `withPayload` for hiding turbopack external deps warnings
from this PR https://github.com/payloadcms/payload/pull/9147 didn't work
on `next@15.0.3`, now it works on both `15.0.0` and `15.0.3`.
2024-11-21 20:46:09 +02:00
Germán Jabloñski
082e546159 chore: fix test/lexical-mdx imports (#9405)
missing from #9229
2024-11-21 18:38:16 +00:00
Jarrod Flesch
d7ad1733f2 chore: type getViewFromConfig, add viewActions to serverProps (#9404)
### What?
`viewActions` are not easily accessible in custom views.

### Why?
We extract view actions when we call `getViewFromConfig`, but never pass
them to the custom views.

### How?
Properly types return type for serverProps inside `getViewFromConfig`
and adds viewActions to serverProps so they are spread into props when
we build the custom view components.

Now custom server views will get the viewActions as a prop.

Fixes #9338
2024-11-21 11:58:05 -05:00
Sasha
d499de1e0f fix(db-postgres): joins with versions and hasMany relationship (#9370)
Fixes errors when having joins with versions +drafts on `hasMany: true`
relationships.
Removes `joinQuery` overhead if we don't need it for the current
operation. Right now, in all adapters we support joins only for `find`,
`findOne`, and `queryDrafts`.


Fixes https://github.com/payloadcms/payload/issues/9369
2024-11-21 10:42:05 -05:00
Alessio Gravili
3d0424bc77 fix(richtext-lexical): slash menu query doesn't disappear after selecting slash menu item (#9396)
This happened only for certain slash menu items like inline blocks.

Fixes https://github.com/payloadcms/payload/issues/9326
2024-11-21 06:15:22 +00:00
Germán Jabloñski
0960290558 fix(richtext-lexical): preserve indent and text-align when converting Lexical <-> HTML (#9165)
Fixes #5146 

This had been solved in https://github.com/facebook/lexical/pull/6693
but we are using another serialization. I open
https://github.com/payloadcms/payload/discussions/9166 to discuss/track
how we can improve this in the future
2024-11-20 22:24:45 -07:00
Alessio Gravili
48b60fc905 chore(richtext-lexical): enable strict: true (#9394)
Thanks to @GermanJablo for doing most of the work by enabling
`noImplicitAny` and `strictNullChecks` in previous PRs
2024-11-21 04:19:18 +00:00
Alessio Gravili
90e37fe78d fix(ui): error when collapsing sidebar groups (#9393)
Fixes
https://discord.com/channels/967097582721572934/1308933812914229368/1308933812914229368

![CleanShot 2024-11-20 at 19 04
45@2x](https://github.com/user-attachments/assets/3c2c8054-9d09-4090-adf8-57aef8635baf)
2024-11-21 02:17:45 +00:00
Alessio Gravili
9470f9b01f fix: error when opening admin panel without any permissions (#9392)
We were getting the following error when opening the create first user
page, as sanitizedPermissions is `{}` if the user has no permissions at
all

![CleanShot 2024-11-20 at 18 48
46@2x](https://github.com/user-attachments/assets/90270a0b-10e5-4f22-a91e-174f82a559b2)
2024-11-21 02:10:40 +00:00
Germán Jabloñski
1f92b5b412 chore(richtext-lexical): add noImplicitAny to the richtext-lexical package (#8763) 2024-11-21 01:46:28 +00:00
Elliot DeNolf
025d917fa0 chore(release): v3.0.2 [skip ci] 2024-11-20 16:06:04 -05:00
Alessio Gravili
c67291d538 fix(ui): invalid permissions passed to group and named tab sub-fields (#9366)
Fixes https://github.com/payloadcms/payload/issues/9363

This fixes the following issues that caused fields to be either hidden,
or incorrectly set to readOnly in certain configurations:
- In some cases, permissions were sanitized incorrectly. This PR
rewrites the sanitizePermissions function and adds new unit tests
- after a document save, the client was receiving unsanitized
permissions. Moving the sanitization logic to the endpoint fixes this
- Various incorrect handling of permissions in our form state endpoints
/ RenderFields
2024-11-20 13:03:35 -07:00
Alessio Gravili
5db7e1e864 fix(richtext-lexical): use copy of @lexical/markdown that does not install @lexical/code (#9382)
Fixes https://github.com/payloadcms/payload/issues/9378

We’ve found out that @lexical/markdown imports cannot be reliably
dynamically imported by Node.js for an unknown reason. Frequently,
Node.js simply exits before the dynamic import is done.

We’re suspecting the reason for this to be its dependency on
@lexical/code that installs prism.

This will not only (hopefully) fix the import issue, but also reduce the
bundle size & compilation speed of richtext-lexical.
2024-11-20 13:02:57 -07:00
Jacob Fletcher
07a9125f9c fix(next): properly sets doc id types when using postgres (#9381)
Fixes #9351. When using Postgres, doc ids were being treated as a string
as opposed to a number within the admin panel. This led to issues for
anything relying on the `docID` from context, such as the join field not
properly populating initial data when creating new documents, etc.
2024-11-20 15:02:08 -05:00
Jacob Fletcher
ef3748319e fix(ui): bulk update and delete ignoring search query (#9377)
Fixes #9374.
2024-11-20 13:22:43 -05:00
Jarrod Flesch
439dcd493e fix: prioritize server rendered Actions in ActionsProvider (#9379)
### What?
Actions were not being re-rendered when router.refresh was called.
[Discord
Link](https://discord.com/channels/967097582721572934/1308636510203154462/1308648116031066173)

### Why?
They were stored in state and the state was persisting.

### How?
Spread the stateful actions and the Actions from props on top of the
client state actions.
2024-11-20 13:18:28 -05:00
Elliot DeNolf
ff0386f276 docs: improve migration guide for running db migrations 2024-11-20 11:34:57 -05:00
Said Akhrarov
568e1a274b docs: fix custom component links in admin (#9368)
### What?
Fixes links for custom components in a few places in admin docs.

### Why?
To link users to the correct location in the docs.

### How?
Changes to `docs/admin/components.mdx` and
`docs/admin/customizing-css.mdx`
2024-11-20 09:05:56 -05:00
Jacob Fletcher
9e85be0006 fix(next): autosave document rendering (#9364)
Closes #9242 and #9365. Autosave-enabled documents rendered within a
drawer were not being properly handled. This was causing multiple draft
documents to be created upon opening the drawer, as well as an empty
document returned from the server function, etc.
2024-11-19 19:01:54 -05:00
Jarrod Flesch
4030e212f5 fix: allow self referencing relationships when adding new collections to config (#9360)
### What?
Unable to add collections to the config dynamically if they reference
their own collection in a relationship field.

This was discovered while working on the folder view feature which
dynamically adds collections to your config if it is enabled per
collection.

### Why?
When `sanitizeCollection` runs, it takes the current config. If you are
sanitizing a collection before adding it to the config, that collection
cannot have any self referencing relationship fields on it otherwise it
fails the validRelationships check.

### How?
Using a reducer we now initialize the validRelationships variable with
the incoming collection slug.
2024-11-19 16:22:23 -05:00
Evan Cusack
646a5345a8 docs: update what-is-payload.mdx (#9353)
### What? 
instead of saying "it", wanted to give more context to what goes into
your Next app folder.

### Why? 
clarification

### How? 
edited docs
2024-11-19 14:53:48 -05:00
Patrik
1dc8094905 chore(templates): adds getURL util to website & with-vercel-website templates (#9336) 2024-11-19 14:43:22 -05:00
Elliot DeNolf
9ea26638e9 chore(release): v3.0.1 [skip ci] 2024-11-19 14:33:41 -05:00
Elliot DeNolf
4f1a4a28a3 chore: remove changelog.md from git staging 2024-11-19 14:33:10 -05:00
Elliot DeNolf
41d2e64a3a ci(scripts): remove updating changelog.md 2024-11-19 14:31:55 -05:00
Jarrod Flesch
661f450c61 fix(ui): client side doc data not updating after save (#9340)
### What?
When a document is saved the data from useDocumentInfo was stale.

### Why?
Previously we would refresh the entire document by calling the
form-state endpoint, we no longer do that.

### How?
Adds a new variable accessible from useDocumentInfo,
`savedDocumentData`, that is updated when the document is successfully
saved and defaults to initialData.
2024-11-19 13:22:23 -05:00
Elliot DeNolf
69b7a11a28 ci: remove v3 tagging, assumed 2024-11-19 13:15:20 -05:00
Said Akhrarov
2c7ea6362a fix(ui): show required indicator for select fields (#9348)
### What?
Select field was not showing required indicator despite being marked
required in config.

### Why?
To give end-user feedback when editting required select fields.

### How?
Replacing hardcoded required prop with required prop passed in from
config.

[See
here.](https://github.com/payloadcms/payload/blob/main/packages/ui/src/fields/Select/Input.tsx#L100)
2024-11-19 12:55:26 -05:00
Jessica Chowdhury
077d3e7d16 chore: adjust api code preview indentation (#9114) 2024-11-19 12:42:36 -05:00
Jacob Fletcher
188baec34c fix(ui): proper permissions within version diff view (#9346)
Fixes #9337. The version view was not able to render its diff because of
an invalid permissions lookup. This was a result of a change to how
access results are returned from the API, which are now sanitized:
https://github.com/payloadcms/payload/pull/7335
2024-11-19 12:39:05 -05:00
Elliot DeNolf
d9c6288cb2 chore: update migration guide link 2024-11-19 12:25:35 -05:00
Jessica Chowdhury
037662d9f5 chore(examples): migrates custom-component example to latest beta [skip-lint] (#9170)
Updates the `Custom Components` example, including packages, readme,
lockfile, types and the custom fields.

---------

Co-authored-by: Patrik Kozak <patrik@payloadcms.com>
2024-11-19 11:40:20 -05:00
Patrik
389ef16a5f chore(examples): migrates whitelabel example to 3.0 (#9316) 2024-11-19 11:36:28 -05:00
Elliot DeNolf
cb3d7b37ef chore: remove v2 changelog 2024-11-19 11:29:15 -05:00
Marc Maceira
d542bd774d docs: fix broken links to release notes in migration guide (#9333) 2024-11-19 11:17:26 -05:00
Paul
7f65c83a98 fix(templates): website logo not showing (#9334) 2024-11-19 15:06:56 +00:00
Jacob Fletcher
0f3f6e73da fix(ui): addFieldRow set modified (#9324)
Fixes #9264. When externally updating array or block rows through the
`addFieldRow` or `replaceFieldRow` methods, nested rich text fields
along with any custom components within them are never rendered. This is
because unless the form is explicitly set to modified, as the default
array and blocks fields currently do, the newly generated form-state
will skip the rendering step. Now, the underlying callbacks themselves
automatically set the form to modified to trigger rendering.
2024-11-19 08:52:50 -05:00
James Mikrut
a50029f659 Update README.md 2024-11-19 08:44:22 -05:00
James Mikrut
197a22fb28 chore: uses payload.auth in website template seed function (#9331)
Uses `payload.auth` in the website template seed function, which is
better than manually verifying the JWT.
2024-11-19 08:36:53 -05:00
garrettgrohman
6d74fbc6cb docs: fixes generic grammar mistakes 2024-11-19 08:28:32 -05:00
Jarrod Flesch
f42b1e1e05 fix: could not save selection from upload has many drawer (#9325)
### What?
Could not finalize selection of `hasMany` uploads inside of the drawer.

### Why?
The Select component was not being rendered in the beforeActions prop of
the ListControls when row selections was enabled.

### How?
Renders the Select component when row selections are enabled and
onBulkSelect is present.
2024-11-19 08:23:02 -05:00
Sean Zubrickas
bb4f69fb0c chore: updates README banner 2024-11-19 07:00:19 -05:00
Paul
26cb1e1546 fix(templates): seeding in website template moved to a separate route so timeout can be customised (#9327) 2024-11-19 00:03:22 -06:00
Alessio Gravili
5d2b0b30b0 perf: significantly reduce HTML we send to the client. Up to 4x smaller (#9321)
The biggest difference comes from calling `RenderServerComponent` as a
function, instead of rendering it by using `<RenderServerComponent`.

This gets rid of wasteful blocks of codes sent to the client that look
like this:

![CleanShot 2024-11-18 at 20 41
20@2x](https://github.com/user-attachments/assets/edb67d72-f4a5-459b-93f4-68dc65aeffb6)


HTML size comparison:

## Admin test suite

| View | Before | After |
|------|---------|--------|
| Dashboard | 331 kB | 83 kB |
| collections/custom-views-one Edit | 285 kB | 76.6 kB |

## Fields test suite

| View | Before | After |
|------|---------|--------|
| collections/lexical Edit | 189 kB | 94.4 kB |
| collections/lexical List | 152 kB | 62.9 kB |

## Community test suite

| View | Before | After |
|------|---------|--------|
| Dashboard | 78.9 kB | 43.1 kB |
2024-11-19 04:30:21 +00:00
Alessio Gravili
1425d58b57 chore: make uploads e2e test suite not flaky (#9323)
The problem was that the uploads test suite was trying to log in to
payload before it was even initialized.

In the rare event where payload started up before the uploads test suite
was trying to log in, our tests passed.
2024-11-19 03:50:35 +00:00
Blain Maguire
d3b0a045be fix: allow setting admin path route from config (#8085) 2024-11-18 21:20:23 -05:00
Elliot DeNolf
7e41f17ec2 chore: update README for 3.0 2024-11-18 20:53:13 -05:00
Elliot DeNolf
763ccdcf00 chore(release): eslint/3.0.0 2024-11-18 20:39:54 -05:00
Elliot DeNolf
76286136ba chore(cpa): update init next to use latest 2024-11-18 20:29:07 -05:00
Elliot DeNolf
6145accb83 chore(templates): bump all templates to 3.0 2024-11-18 20:25:52 -05:00
Elliot DeNolf
6407e577d3 chore(release): v3.0.0 [skip ci] 2024-11-18 20:10:16 -05:00
Elliot DeNolf
7fe207937f ci: update release script for v3 2024-11-18 20:05:55 -05:00
Elliot DeNolf
cc04396a4f chore(cpa): unpin template version tag for release 2024-11-18 20:00:38 -05:00
Dan Ribbens
0d63dc9f9c chore: remove unused transaction in website seed (#9319) 2024-11-18 19:55:27 -05:00
Alessio Gravili
f7fc8a2ea0 perf(richtext-lexical): do not send default lexical editor config to client (#9318)
We can just get the default config from the client, if the server passes
undefined. This wasted bandwidth and unnecessarily increased the html
size
2024-11-18 17:28:55 -07:00
Elliot DeNolf
fade739f77 chore(release): v3.0.0-beta.135 [skip ci] 2024-11-18 19:19:55 -05:00
Said Akhrarov
1a31e63b4d fix(ui): safely accesses field in default filter component (#9276)
### What?
In the WhereBuilder Condition DefaultFilter component, there is a switch
statement that contains components to return based on the built filter
in the admin ui. Having a filter built out then navigating to another
collection list view causes an error to occur due to InternalField being
undefined but the DefaultFilter tries to access the field on it.

### Why?
To fix unexpected `cannot access property field of undefined` errors.

### How?
Adding a conditional chaining operator.

Odd thing here is that the `Text` component where this error originates
from doesn't actually make use of the passed `InternalField`. Might be
worth it to take a closer look at it.

Fixes #9179
2024-11-18 17:52:29 -05:00
Dan Ribbens
a25ddc5448 docs: migration guide more info (#9305) 2024-11-18 17:35:36 -05:00
Elliot DeNolf
ecbafbf181 fix(templates): remove req from seed script 2024-11-18 16:58:16 -05:00
Elliot DeNolf
7314990b0c chore(templates): add .npmrc files 2024-11-18 16:38:36 -05:00
Elliot DeNolf
58eeb6e47c chore(templates): bring back needed lock files 2024-11-18 16:35:56 -05:00
Germán Jabloñski
f1eab5d5d3 chore(richtext-lexical): re-export lexical (#9229)
Co-authored-by: Alessio Gravili <alessio@gravili.de>
2024-11-18 16:27:36 -05:00
James Mikrut
6873b139e2 chore(examples): removes nested docs, redirects, virtual fields, custom server, and hierarchy examples (#9112)
Removes examples that are now duplicative or unnecessary due to new
features in 3.0:

### Custom server

This one can be removed in favor of [Next.js
documentation](https://nextjs.org/docs/pages/building-your-application/configuring/custom-server)

### Hierarchy

The new `join` field can solve for many of the use cases for the
`hierarchy` example. Bi-directional relationships with the `join` field
should be preferred here.

### Nested Docs, Redirects

Our website template showcases how to use the `nested-docs` and
`redirects` plugins in-depth, with real-world examples.

### Virtual Fields

Virtual fields have gotten significantly easier and can now be defined
by specifying `virtual: true`. Not a big need for a full example any
longer.

---------

Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
2024-11-18 16:11:21 -05:00
Sophia Michelle Andren
54379eccf4 feat: new Payload logo (#9240)
Introducing the new Payload logo! 🎉


![Payload_Opengraph](https://github.com/user-attachments/assets/387e0841-9498-43df-bf01-f78adb7cdfcf)
2024-11-18 16:08:59 -05:00
Jarrod Flesch
7989563bc1 chore: updates multi tenant example to use baseListFilter (#9308)
### What?
Implements new `baseListFilter` into the multi-tenant example

---------

Co-authored-by: Patrik Kozak <patrik@payloadcms.com>
2024-11-18 15:59:54 -05:00
Patrik
7babe6bcf5 chore(examples): migrates multi-tenant example to latest beta (#9300) 2024-11-18 15:45:20 -05:00
Nate
bccb7c0ff7 chore: update README.md (#9304)
Fixes url to banner asset.
2024-11-18 15:44:42 -05:00
Elliot DeNolf
333da1bb42 fix(templates): seed from url (#9306)
Update website template seeding to use URLs instead of image assets.
Images are not available when deployed to vercel.
2024-11-18 15:41:20 -05:00
Elliot DeNolf
2b955a4aa3 chore(cpa): remove beta from vercel pg and sqlite 2024-11-18 15:40:18 -05:00
Elliot DeNolf
e796ff2330 chore(templates): add back payload cloud to plugins array 2024-11-18 15:31:45 -05:00
mattddean
0075b99eec fix(graphql): loading of polymorphic hasMany relationships (#9175)
### What?

Bug #9173

### Why?

`collectionSlug` is an array when `isRelatedToManyCollections` is true

### How?

Compare array to array

Fixes #9173

![Screenshot 2024-11-13 at 12 37
52 PM](https://github.com/user-attachments/assets/3eae497d-90d8-474a-afd0-baf69f017459)
2024-11-18 22:25:42 +02:00
Sasha
e40141b559 fix: queues types with strict: true (#9281)
Fixes types for workflows / jobs `input` and `output` when using
`strict: true` or `strictNullChecks: true` by ensuring that all
properties in generates types are requried
2024-11-18 21:49:08 +02:00
Jacob Fletcher
ec95ce8758 fix(next): passes doc through edit view handler (#9302)
The Edit and Live Preview views were duplicately making the same Local
API requests for document data. This is because while the top-level
document view handler makes these requests _before_ rendering the Live
Preview view, it wasn't passing it's data through as props. This has
also led to inconsistencies in the options being passed through the
requests themselves, such as `locale`, `user`, and `overrideAccess:
false`. Everything is now standardized as expected through the existing
`getDocumentData` utility.
2024-11-18 14:27:40 -05:00
Mikkel Wied Frederiksen
54ac8b9cd2 fix(next): passes locale through requests in live preview edit view (#9298)
Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
2024-11-18 13:41:12 -05:00
Alessio Gravili
0a6f530007 fix: nav jumping around if no nav preferences are set (#9301)
If you start a fresh dev server and open payload, the nav will initially
show as closed and then jump to its open state. This is because no
preferences are set, so the server tells the client to initially keep it
closed, despite the default nav state being _open_.
2024-11-18 18:36:56 +00:00
Jarrod Flesch
58ac784425 fix(next): initialize payload with importMap (#9297)
### What?
Custom providers could not be resolved because payload was not
initialized in the Root layout with the importMap passed in from props.

### How?
Pass importMap from props into the getPayload function in the Root
layout.
2024-11-18 11:07:40 -05:00
Jarrod Flesch
5503afdf29 fix: sanitize sub block field permissions correctly (#9296)
Fixes https://github.com/payloadcms/payload/issues/9288

### What?
When a block had a subfield named `blocks`, sanitization would throw an
error.

### Why?
An incorrect check for the key of `"fields"` would then attempt to pass
`data.blocks[key].fields` aka `data.blocks.fields.fields` to the next
call of `areAllPermissionsTrue` which would be undefined. Instead if the
key is `fields` it should pass `data.blocks[key]`.

### How?
Remove the second `.fields` property accessor.
2024-11-18 10:47:57 -05:00
Jacob Fletcher
30947d2173 perf!: removes unnecessary field styles from initial page response (#9286)
Optimizes initial page responses by removing unnecessary inline field
styles that were being sent through the HTML response. The Client Config
contains a large number of duplicates of the string:
`"style\":{\"flex\":\"1 1 auto\"}`, one for every single field within
the entirely of the config. This leads to hundreds or potentially
thousands of instances of this same string, depending on the number of
fields within the config itself. This is regardless of custom field
widths being defined. Instead, we can do this entirely client-side,
preventing this string from ever being transmitted over the network in
the first place.

## Breaking Changes

This only effects those who are importing Payload's field components
into your own Custom Components or front-end application. The `width`
prop no longer exists. It has been consolidated into the existing
`style` prop. To migrate, simply move this prop as follows:

```diff
import { TextInput } from '@payloadcms/ui

export const MyCustomComponent = () => {
  return (
    <TextInput 
-      width="60%"
       style={{
+        width: "60%,
       }}
    />
  )
}
```
2024-11-18 10:03:26 -05:00
Sasha
665b3536d3 fix(db-mongodb): potential errors in sanitizeRelationshipIDs with ref being a non object (#9292)
### What?
Fixes potential errors when passed to `sanitizeRelationships` `ref`
could potentially be a non object (for example `string`) because of
having in the database data in old structure.
```
"Cannot create property 'a' on string 'B'",
``` 

### Why?
Necessary particularly for the migration script, as it migrates
everything including versions that can have outdated data.

### How?
Ensures passed `ref` is an `object`.
2024-11-18 16:10:13 +02:00
Dan Ribbens
488c28c99c fix: getPayload node exits on webpack-hmr websocket failure (#9279)
### What?
When a script attempts to load payload using `getPayload()`, it will end
with: `Error: connect ECONNREFUSED 127.0.0.1:3000` etc...

### Why?

Even though there is a try/catch, it still errors because WebSocket
connection failures happen asynchronously after the ws object is
instantiated.

### How?

Added the error handling function cached.ws.onerror to prevent exit.
2024-11-18 09:03:52 -05:00
Jacob Fletcher
7489c29704 chore: dedupes field description functions and defers rendering static field descriptions to the client (#9277)
Custom field description functions were being duplicately called in both
the Client Config and form state. Static field descriptions were also
being rendered in form state unnecessarily. Now, field description
functions are only executed once within form state, and static
descriptions are deferred to the client for rendering.
2024-11-17 22:37:35 -05:00
Jacob Fletcher
3eb8b5939e chore: extracts dependency checker from root layout (#9272)
Cleans up the Root Layout by extracting the dependency checker and
related code away from component logic.
2024-11-17 21:46:18 -05:00
Alessio Gravili
d4f1add2ab feat(richtext-lexical): mdx support (#9160)
Supports bi-directional import/export between MDX <=> Lexical. JSX will
be mapped to lexical blocks back and forth.

This will allow editing our mdx docs in payload while keeping mdx as the
source of truth

---------

Co-authored-by: Germán Jabloñski <43938777+GermanJablo@users.noreply.github.com>
2024-11-17 15:03:45 -07:00
Elliot DeNolf
324af8a5f9 chore: update all githubusercontent links after branch rename 2024-11-17 16:46:23 -05:00
Elliot DeNolf
c9040b6095 chore(templates): update templates after branch rename 2024-11-17 12:52:18 -05:00
Elliot DeNolf
0107a48374 ci: update dependabot config after branch rename 2024-11-17 12:35:34 -05:00
Elliot DeNolf
a31c29b1ff ci: update workflows after branch rename 2024-11-17 12:13:19 -05:00
Elliot DeNolf
cb6ceaec76 chore(release): v3.0.0-beta.134 [skip ci] 2024-11-17 11:43:43 -05:00
Sasha
ef2475d804 fix(ui): avoid calling getTableState from join field on create (#9256)
### What?
Fixes the issue when visiting the create view with the Join Field and
using postgres adapter
```
invalid input syntax for type integer: "NaN"
```
This happens because we don't have an ID yet and we send to the
database:
`WHERE id = NaN`

### How?
Avoids calling `getTableState` inside of `RelationshipTable` if there's
no ID yet, as it will always lead to the same empty result. While we
_could_ avoid error directly in the database adapter, I don't think we
should do that render request

Fixes https://github.com/payloadcms/payload/issues/9193
2024-11-17 11:32:50 -05:00
Sasha
d21fca9156 feat: support relationship writes using objects instead of IDs (#9253)
### What?
Previously, this code led to a validation error because `movie` is an
object and you needed to use `movie.id` instead.
```ts
const movie = await payload.create({ collection: 'movies', data: {} })
const result = await payload.create({
  collection: 'object-writes',
  data: {
    many: [movie],
    manyPoly: [{ relationTo: 'movies', value: movie }],
    one: movie,
    onePoly: {
      relationTo: 'movies',
      value: movie,
    },
  },
})
```
While it's simple to modify this example, it's more painful when you
have a data with `depth` > 0 and then you want to update that document.

### Why?
Better DX as less checks needed, and TypeScript says that we can pass an
object.

### How?
Sanitizes the field value in the root `beforeValidate` hook
2024-11-17 11:25:32 +02:00
Alessio Gravili
35917c67d7 perf(richtext-lexical)!: significantly reduce lexical rerendering and amount of network requests from blocks (#9255)
The field RSC now provides an initial state for all lexical blocks. This
completely obliterates any flashes and lexical block loading states when
loading or saving a document.

Previously, when a document is loaded or saved, every lexical block was
sending a network request in order to fetch their form state. Now, this
is batched and handled in the lexical server component. All lexical
block form states are sent to the client together with the parent
lexical field, and are thus available immediately.

We also do the same with block collapsed preferences. Thus, there are no
loading states or layout shifts/flashes of blocks anymore.

Additionally, when saving a document while your cursor is inside a
lexical field, the cursor position is preserved. Previously, a document
save would kick your cursor out of the lexical field.

## Look at how nice this is:


https://github.com/user-attachments/assets/21d736d4-8f80-4df0-a782-7509edd993da

**BREAKING:**

This removes the `feature.hooks.load` and `feature.hooks.save`
interfaces from custom lexical features, as they weren't used internally
and added unnecessary, additional overhead.

If you have custom features that use those, you can migrate to using
normal payload hooks that run on the server instead of the client.
2024-11-17 08:31:55 +00:00
Jacob Fletcher
abe4cc87ca docs: updates migration guide (#9251)
Documents more breaking changes within the migration guide, improves
overview, reorganizes everything, adds section headings, table of
contents, and more.
2024-11-16 23:34:14 -05:00
Sasha
8efb926be9 chore: split e2e-admin__e2e__1 test suite (#9254)
Speeds up the longest test suite.
From:
<img width="494" alt="image"
src="https://github.com/user-attachments/assets/76d96ece-696a-4b56-9192-deaa307a0442">
To:
<img width="477" alt="image"
src="https://github.com/user-attachments/assets/a9d46180-a9cc-4ef9-8727-0130b422baf0">
2024-11-17 00:47:38 +02:00
Alessio Gravili
63cc9668df feat(richtext-lexical): allow replacing entire blocks with custom components (#9234)
With this PR, you can now customize the way that `blocks` and
`inlineBlocks` are rendered within Lexical's `BlocksFeature` by passing
your own React components.

This is super helpful when you need to create "previews" or more
accurate UI for your Lexical blocks.

For example, let's say you have a `gallery` block where your admins
select a bunch of images. By default, Lexical would just render a
collapsible with your block's fields in it. But now you can customize
the `admin.components.Block` property on your `block` config by passing
it a custom React component for us to render instead.

So using that, with this `gallery` example, you could make a dynamic
gallery React component that shows the images to your editors - and then
render our built-in `BlockEditButton` to allow your editors to manage
your gallery in a drawer.


Here is an example where the BlockEditButton is added to the default
Block Collapsible/Header:


![image](https://github.com/user-attachments/assets/db8c13f1-2650-4b33-bc11-2582bb937f3d)

---------

Co-authored-by: James <james@trbl.design>
2024-11-16 15:30:18 -07:00
Elliot DeNolf
55d5edda6b ci: update pr action 2024-11-16 17:05:44 -05:00
Elliot DeNolf
da22c6abee ci: dynamic base for lockfile pr 2024-11-16 16:01:14 -05:00
Elliot DeNolf
29c7cc8796 ci: do not run release-commenter on workflow_dispatch 2024-11-16 15:37:34 -05:00
James Mikrut
31b32ef941 feat: deprecates getPayloadHMR in favor of simpler getPayload (#9249)
Deprecates `getPayloadHMR` and simplifies this pattern into a single
`import { getPayload } from 'payload'`.

We will still retain the exported `getPayloadHMR` but it now will throw
a deprecation warning with instructions for how to migrate.
2024-11-16 15:30:05 -05:00
Elliot DeNolf
67ff23a6e2 chore(templates): deprecate vercel-postgres, superceded by with-vercel-postgres 2024-11-16 15:24:10 -05:00
Elliot DeNolf
aacc4745b6 ci: allow workflow_dispatch on post-release 2024-11-16 15:00:17 -05:00
Jacob Fletcher
ed21c1c036 fix!: proper casing for default root views (#9248)
Custom `account` and `dashboard` views now defined as lowercase in the
config. This is to maintain consistency with all other custom views
throughout the config. The underlying reason for this change is that
previously, you could define React Components directly on these
properties. Now, these are strictly _view configuration objects_, and
the property names have been adjusted in order to semantically reflect
that. These two views in particular, however, were never updated
accordingly.

## Breaking Changes

```diff
import { buildConfig } from 'payload'

const config = buildConfig({
  // ...
  admin: {
    components: {
      // ...
      views: {
        // ...
-       Account: ...
-       Dashboard: ...
+       account: ...
+       dashboard: ...
      },
    },
  },
})
```
2024-11-16 14:35:35 -05:00
Elliot DeNolf
447587a01e ci: adjust post-release pr permissions 2024-11-16 14:20:45 -05:00
Jacob Fletcher
c4269d25d3 fix(next): custom default root views (#9247)
Fixes #9246. Custom default root views (account and dashboard) were not
being properly thread to the custom component renderer. Custom account
views were also improperly _stacking_ instead of _replacing_ the default
view.

Tests for this are incoming. To properly test this we need to wrap our
default root views with custom ones, so that out existing `admin` test
suite can continue to work alongside tests specifically for this issue.
2024-11-16 14:05:50 -05:00
Elliot DeNolf
457be31ed2 chore(release): v3.0.0-beta.133 [skip ci] 2024-11-16 13:59:41 -05:00
Elliot DeNolf
bfbee4e604 ci: bump templates post release (#9241)
Automatically create a PR that bumps the lockfiles of the templates post
release.
2024-11-16 13:51:01 -05:00
James Mikrut
9b00b59df0 fix: corrects cases of false positive identification of custom id fields (#9245)
This PR fixes cases where you may have a field called `id` within a
group or a named tab, which would have incorrectly been treated as a
custom ID field for the collection.

However, custom IDs need to be defined at the root level - and now
Payload only respects custom IDs defined at the root level.
2024-11-16 16:29:48 +00:00
Elliot DeNolf
1393d84bca feat(templates): programmatic migration gen (#9238)
Programmatically generate lockfiles and postgres migrations
2024-11-15 21:47:05 -05:00
1340 changed files with 49479 additions and 135667 deletions

View File

@@ -1,6 +1,6 @@
name: Functionality Bug
description: '[REPRODUCTION REQUIRED] - Create a bug report'
labels: ['status: needs-triage', 'v3', 'validate-reproduction']
labels: ['status: needs-triage', 'validate-reproduction']
body:
- type: textarea
attributes:
@@ -14,7 +14,7 @@ body:
label: Link to the code that reproduces this issue
description: >-
_REQUIRED_: Please provide a link to your reproduction. Note, if the URL is invalid (404 or a private repository), we may close the issue.
Either use `npx create-payload-app@beta -t blank` then push to a repo or follow the [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
Either use `pnpx create-payload-app@latest -t blank` then push to a repo or follow the [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
validations:
required: true
@@ -57,7 +57,7 @@ body:
- type: textarea
attributes:
label: Environment Info
description: Paste output from `pnpm payload info` (>= beta.92) _or_ Payload, Node.js, and Next.js versions.
description: Paste output from `pnpm payload info` _or_ Payload, Node.js, and Next.js versions.
render: text
placeholder: |
Payload:

View File

@@ -20,7 +20,7 @@ body:
- type: textarea
attributes:
label: Environment Info
description: Paste output from `pnpm payload info` (>= beta.92) _or_ Payload, Node.js, and Next.js versions.
description: Paste output from `pnpm payload info` _or_ Payload, Node.js, and Next.js versions.
render: text
placeholder: |
Payload:

View File

@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "ES2022",
"lib": ["es2020.string"],
"noEmit": true,
"strict": true,

View File

@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "ES2022",
"lib": ["es2020.string"],
"noEmit": true,
"strict": true,

View File

@@ -8,7 +8,7 @@ updates:
- /.github/workflows
- /.github/actions/* # Not working until resolved: https://github.com/dependabot/dependabot-core/issues/6345
- /.github/actions/setup
target-branch: beta
target-branch: main
schedule:
interval: monthly
timezone: America/Detroit
@@ -20,7 +20,8 @@ updates:
- package-ecosystem: npm
directory: /
target-branch: beta
target-branch: main
open-pull-requests-limit: 0 # Only allow security updates
schedule:
interval: weekly
day: sunday
@@ -38,8 +39,6 @@ updates:
- patch
patterns:
- '*'
exclude-patterns:
- 'drizzle*'
dev-deps:
dependency-type: development
update-types:
@@ -47,13 +46,11 @@ updates:
- patch
patterns:
- '*'
exclude-patterns:
- 'drizzle*'
# Only bump patch versions for 2.x
- package-ecosystem: npm
directory: /
target-branch: main
target-branch: 2.x
open-pull-requests-limit: 0 # Only allow security updates
schedule:
interval: weekly
day: sunday
@@ -70,5 +67,3 @@ updates:
- patch
patterns:
- '*'
exclude-patterns:
- 'drizzle*'

View File

@@ -40,7 +40,7 @@ There are a couple ways run integration tests:
- **Granularly** - you can run individual tests in vscode by installing the Jest Runner plugin and using that to run individual tests. Clicking the `debug` button will run the test in debug mode allowing you to set break points.
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/github/int-debug.png" />
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/assets/images/github/int-debug.png" />
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
@@ -57,7 +57,7 @@ The easiest way to run E2E tests is to install
Once they are installed you can open the `testing` tab in vscode sidebar and drill down to the test you want to run, i.e. `/test/_community/e2e.spec.ts`
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/github/e2e-debug.png" />
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/assets/images/github/e2e-debug.png" />
#### Notes

View File

@@ -9,7 +9,6 @@ on:
push:
branches:
- main
- beta
concurrency:
# <workflow_name>-<branch_name>-<true || commit_sha if branch is protected>
@@ -284,7 +283,7 @@ jobs:
tests-e2e:
runs-on: ubuntu-latest
needs: build
name: ${{ matrix.suite }}
name: e2e-${{ matrix.suite }}
strategy:
fail-fast: false
matrix:
@@ -294,6 +293,7 @@ jobs:
- access-control
- admin__e2e__1
- admin__e2e__2
- admin__e2e__3
- admin-root
- auth
- field-error-states
@@ -414,6 +414,10 @@ jobs:
- template: with-vercel-postgres
database: postgres
# Re-enable once PG conncection is figured out
# - template: with-vercel-website
# database: postgres
name: ${{ matrix.template }}-${{ matrix.database }}
env:
@@ -525,7 +529,7 @@ jobs:
publish-canary:
name: Publish Canary
runs-on: ubuntu-latest
if: ${{ needs.all-green.result == 'success' && github.ref_name == 'beta' }}
if: ${{ needs.all-green.result == 'success' && github.ref_name == 'main' }}
needs:
- all-green
@@ -533,4 +537,4 @@ jobs:
# debug github.ref output
- run: |
echo github.ref: ${{ github.ref }}
echo isBeta: ${{ github.ref == 'refs/heads/beta' }}
echo isV3: ${{ github.ref == 'refs/heads/main' }}

View File

@@ -5,16 +5,26 @@ on:
types:
- published
workflow_dispatch:
inputs:
tag:
description: 'Release tag to process (optional)'
required: false
default: ''
env:
NODE_VERSION: 22.6.0
PNPM_VERSION: 9.7.1
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry
jobs:
post_release:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Only needed if debugging on a branch other than default
# ref: ${{ github.event.release.target_commitish || github.ref }}
- uses: ./.github/actions/release-commenter
continue-on-error: true
env:
@@ -28,3 +38,70 @@ jobs:
comment-template: |
🚀 This is included in version {release_link}
update_templates:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- name: Update template lockfiles and migrations
run: pnpm script:gen-templates
- name: Determine Release Tag
id: determine_tag
run: |
if [ "${{ github.event.inputs.tag }}" != "" ]; then
echo "Using tag from input: ${{ github.event.inputs.tag }}"
echo "release_tag=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
else
echo "Using tag from release event: ${{ github.event.release.tag_name }}"
echo "release_tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
fi
- name: Commit and push changes
id: commit
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -ex
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
export BRANCH_NAME=chore/templates-${{ steps.determine_tag.outputs.release_tag }}
git checkout -b $BRANCH_NAME
git add -A
# If no files have changed, exit early with success
git diff --cached --quiet --exit-code && exit 0
git commit -m "chore(templates): bump lockfiles after ${{ steps.determine_tag.outputs.release_tag }}"
git push origin $BRANCH_NAME
echo "committed=true" >> "$GITHUB_OUTPUT"
echo "branch=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
- name: Debug Branches
run: |
echo "Target Commitish: ${{ github.event.release.target_commitish }}"
echo "Branch: ${{ steps.commit.outputs.branch }}"
echo "Ref: ${{ github.ref }}"
- name: Create pull request
uses: peter-evans/create-pull-request@v7
if: steps.commit.outputs.committed == 'true'
with:
token: ${{ secrets.GITHUB_TOKEN }}
labels: 'area: templates'
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
commit-message: 'Automated update after release'
branch: ${{ steps.commit.outputs.branch }}
base: ${{ github.event_name != 'workflow_dispatch' && github.event.release.target_commitish || github.ref }}
title: 'chore(templates): bump lockfiles after ${{ steps.determine_tag.outputs.release_tag }}'
body: 'Automated bump of template lockfiles after release ${{ steps.determine_tag.outputs.release_tag }}'

View File

@@ -109,13 +109,8 @@ jobs:
runs-on: ubuntu-latest
if: github.event.action == 'opened'
steps:
- name: Tag with main branch with v2
if: github.event.pull_request.base.ref == 'main'
- name: Tag with 2.x branch with v2
if: github.event.pull_request.base.ref == '2.x'
uses: actions-ecosystem/action-add-labels@v1
with:
labels: v2
- name: Tag with beta branch with v3
if: github.event.pull_request.base.ref == 'beta'
uses: actions-ecosystem/action-add-labels@v1
with:
labels: v3

View File

@@ -2,8 +2,6 @@ name: release-canary
on:
workflow_dispatch:
branches:
- beta
env:
NODE_VERSION: 22.6.0
@@ -13,6 +11,7 @@ env:
jobs:
release:
name: release-canary-${{ github.ref_name }}-${{ github.sha }}
permissions:
id-token: write
runs-on: ubuntu-latest

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@ There are a couple ways to do this:
- **Granularly** - you can run individual tests in vscode by installing the Jest Runner plugin and using that to run individual tests. Clicking the `debug` button will run the test in debug mode allowing you to set break points.
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/src/admin/assets/images/github/int-debug.png" />
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/assets/images/github/int-debug.png" />
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
@@ -62,7 +62,7 @@ The easiest way to run E2E tests is to install
Once they are installed you can open the `testing` tab in vscode sidebar and drill down to the test you want to run, i.e. `/test/_community/e2e.spec.ts`
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/src/admin/assets/images/github/e2e-debug.png" />
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/assets/images/github/e2e-debug.png" />
#### Notes

View File

@@ -1,4 +1,4 @@
<a href="https://payloadcms.com"><img width="100%" src="https://github.com/payloadcms/payload/blob/beta/packages/payload/src/assets/images/github-banner-nextjs-native.jpg" alt="Payload headless CMS Admin panel built with React" /></a>
<a href="https://payloadcms.com"><img width="100%" src="https://l4wlsi8vxy8hre4v.public.blob.vercel-storage.com/github-banner-new-logo.jpg" alt="Payload headless CMS Admin panel built with React" /></a>
<br />
<br />
@@ -15,12 +15,12 @@
</p>
<hr/>
<h4>
<a target="_blank" href="https://payloadcms.com/docs/beta/getting-started/what-is-payload" rel="dofollow"><strong>Explore the Docs</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://payloadcms.com/community-help" rel="dofollow"><strong>Community Help</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://github.com/payloadcms/payload/discussions/1539" rel="dofollow"><strong>Roadmap</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://www.g2.com/products/payload-cms/reviews#reviews" rel="dofollow"><strong>View G2 Reviews</strong></a>
<a target="_blank" href="https://payloadcms.com/docs/getting-started/what-is-payload" rel="dofollow"><strong>Explore the Docs</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://payloadcms.com/community-help" rel="dofollow"><strong>Community Help</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://github.com/payloadcms/payload/discussions/1539" rel="dofollow"><strong>Roadmap</strong></a>&nbsp;·&nbsp;<a target="_blank" href="https://www.g2.com/products/payload-cms/reviews#reviews" rel="dofollow"><strong>View G2 Reviews</strong></a>
</h4>
<hr/>
> [!IMPORTANT]
> 🚨 <strong>We're about to release 3.0 stable.</strong> Star this repo or keep an eye on it to follow along.
> 🎉 <strong>We've released 3.0!</strong> Star this repo or keep an eye on it to follow along.
Payload is the first-ever Next.js native CMS that can install directly in your existing `/app` folder. It's the start of a new era for headless CMS.
@@ -38,25 +38,25 @@ Payload is the first-ever Next.js native CMS that can install directly in your e
## Quickstart
Before beginning to work with Payload, make sure you have all of the [required software](https://payloadcms.com/docs/beta/getting-started/installation).
Before beginning to work with Payload, make sure you have all of the [required software](https://payloadcms.com/docs/getting-started/installation).
```text
pnpx create-payload-app@beta
pnpx create-payload-app@latest
```
**If you're new to Payload, you should start with the 3.0 beta website template** (`pnpx create-payload-app@beta -t website`). It shows how to do _everything_ - including custom Rich Text blocks, on-demand revalidation, live preview, and more. It comes with a frontend built with Tailwind all in one `/app` folder.
**If you're new to Payload, you should start with the website template** (`pnpx create-payload-app@latest -t website`). It shows how to do _everything_ - including custom Rich Text blocks, on-demand revalidation, live preview, and more. It comes with a frontend built with Tailwind all in one `/app` folder.
## One-click templates
Jumpstart your next project by starting with a pre-made template. These are production-ready, end-to-end solutions designed to get you to market as fast as possible.
### [🌐 Website](https://github.com/payloadcms/payload/tree/beta/templates/website)
### [🌐 Website](https://github.com/payloadcms/payload/tree/main/templates/website)
Build any kind of website, blog, or portfolio from small to enterprise. Comes with a fully functional front-end built with RSCs and Tailwind.
We're constantly adding more templates to our [Templates Directory](https://github.com/payloadcms/payload/tree/beta/templates). If you maintain your own template, consider adding the `payload-template` topic to your GitHub repository for others to find.
We're constantly adding more templates to our [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates). If you maintain your own template, consider adding the `payload-template` topic to your GitHub repository for others to find.
- [Official Templates](https://github.com/payloadcms/payload/tree/beta/templates)
- [Official Templates](https://github.com/payloadcms/payload/tree/main/templates)
- [Community Templates](https://github.com/topics/payload-template)
## ✨ Features
@@ -66,15 +66,15 @@ We're constantly adding more templates to our [Templates Directory](https://gith
- Use server components to extend Payload UI
- Query your database directly in server components, no need for REST / GraphQL
- Fully TypeScript with automatic types for your data
- [Auth out of the box](https://payloadcms.com/docs/beta/authentication/overview)
- [Versions and drafts](https://payloadcms.com/docs/beta/versions/overview)
- [Localization](https://payloadcms.com/docs/beta/configuration/localization)
- [Block-based kayout builder](https://payloadcms.com/docs/beta/fields/blocks)
- [Customizable React admin](https://payloadcms.com/docs/beta/admin/overview)
- [Lexical rich text editor](https://payloadcms.com/docs/beta/fields/rich-text)
- [Conditional field logic](https://payloadcms.com/docs/beta/fields/overview#conditional-logic)
- Extremely granular [Access Control](https://payloadcms.com/docs/beta/access-control/overview)
- [Document and field-level hooks](https://payloadcms.com/docs/beta/hooks/overview) for every action Payload provides
- [Auth out of the box](https://payloadcms.com/docs/authentication/overview)
- [Versions and drafts](https://payloadcms.com/docs/versions/overview)
- [Localization](https://payloadcms.com/docs/configuration/localization)
- [Block-based layout builder](https://payloadcms.com/docs/fields/blocks)
- [Customizable React admin](https://payloadcms.com/docs/admin/overview)
- [Lexical rich text editor](https://payloadcms.com/docs/fields/rich-text)
- [Conditional field logic](https://payloadcms.com/docs/fields/overview#conditional-logic)
- Extremely granular [Access Control](https://payloadcms.com/docs/access-control/overview)
- [Document and field-level hooks](https://payloadcms.com/docs/hooks/overview) for every action Payload provides
- Intensely fast API
- Highly secure thanks to HTTP-only cookies, CSRF protection, and more
@@ -82,9 +82,9 @@ We're constantly adding more templates to our [Templates Directory](https://gith
## 🗒️ Documentation
Check out the [Payload website](https://payloadcms.com/docs/beta/getting-started/what-is-payload) to find in-depth documentation for everything that Payload offers.
Check out the [Payload website](https://payloadcms.com/docs/getting-started/what-is-payload) to find in-depth documentation for everything that Payload offers.
Migrating from v1 to v2? Check out the [2.0 Release Notes](https://github.com/payloadcms/payload/releases/tag/v2.0.0) on how to do it.
Migrating from v2 to v3? Check out the [3.0 Migration Guide](https://github.com/payloadcms/payload/blob/main/docs/migration-guide/overview.mdx) on how to do it.
## 🙋 Contributing

View File

@@ -315,7 +315,7 @@ The following arguments are provided to the `unlock` function:
If the Collection has [Versions](../versions/overview) enabled, the `readVersions` Access Control function determines whether or not the currently logged in user can access the version history of a Document.
To add Read Versions Access Control to a Collection, use the `readVersions` property in the [Collection Config](../collections/overview):
To add Read Versions Access Control to a Collection, use the `readVersions` property in the [Collection Config](../configuration/collections):
```ts
import type { CollectionConfig } from 'payload'

View File

@@ -8,7 +8,7 @@ keywords: admin, components, custom, documentation, Content Management System, c
The Payload [Admin Panel](./overview) is designed to be as minimal and straightforward as possible to allow for easy customization and full control over the UI. In order for Payload to support this level of customization, Payload provides a pattern for you to supply your own React components through your [Payload Config](../configuration/overview).
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default. This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
<Banner type="success">
<strong>Note:</strong>
@@ -151,7 +151,7 @@ export default buildConfig({
## Building Custom Components
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default, with the exception of [Custom Providers](#custom-providers). This enables the use of the [Local API](../local-api/overview) directly on the front-end, among other things.
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default. This enables the use of the [Local API](../local-api/overview) directly on the front-end, among other things.
### Default Props
@@ -185,7 +185,7 @@ Each Custom Component receives the following props by default:
<Banner type="warning">
<strong>Reminder:</strong>
All Custom Components also receive various other props that are specific component being rendered. See [Root Components](#root-components), [Collection Components](#collection-components), [Global Components](#global-components), or [Field Components](#custom-field-components) for a complete list of all default props per component.
All Custom Components also receive various other props that are specific component being rendered. See [Root Components](#root-components), [Collection Components](./collections#custom-components), [Global Components](./globals#custom-components), or [Field Components](./fields#custom-components) for a complete list of all default props per component.
</Banner>
### Custom Props
@@ -546,5 +546,5 @@ export const useMyCustomContext = () => useContext(MyCustomContext)
```
<Banner type="warning">
<strong>Reminder:</strong> Custom Providers are by definition Client Components. This means they must include the `use client` directive at the top of their files and cannot use server-only code.
<strong>Reminder:</strong>React Context exists only within Client Components. This means they must include the `use client` directive at the top of their files and cannot contain server-only code. To use a Server Component here, simply _wrap_ your Client Component with it.
</Banner>

View File

@@ -8,7 +8,7 @@ keywords: admin, css, scss, documentation, Content Management System, cms, headl
Customizing the Payload [Admin Panel](./overview) through CSS alone is one of the easiest and most powerful ways to customize the look and feel of the dashboard. To allow for this level of customization, Payload:
1. Exposes a [root-level stylesheet](#global-css) for you to easily to inject custom selectors
1. Exposes a [root-level stylesheet](#global-css) for you to inject custom selectors
1. Provides a [CSS library](#css-library) that can be easily overridden or extended
1. Uses [BEM naming conventions](http://getbem.com) so that class names are globally accessible
@@ -30,7 +30,7 @@ Here is an example of how you might target the Dashboard View and change the bac
<Banner type="warning">
<strong>Note:</strong>
If you are building [Custom Components](./overview), it is best to import your own stylesheets directly into your components, rather than using the global stylesheet. You can continue to use the [CSS library](#css-library) as needed.
If you are building [Custom Components](./components), it is best to import your own stylesheets directly into your components, rather than using the global stylesheet. You can continue to use the [CSS library](#css-library) as needed.
</Banner>
### Specificity rules
@@ -62,13 +62,13 @@ You can also override Payload's built-in [CSS Variables](https://developer.mozil
The following variables are defined and can be overridden:
- [Breakpoints](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/queries.scss)
- [Colors](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/colors.scss)
- [Breakpoints](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss/queries.scss)
- [Colors](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss/colors.scss)
- Base color shades (white to black by default)
- Success / warning / error color shades
- Theme-specific colors (background, input background, text color, etc.)
- Elevation colors (used to determine how "bright" something should be when compared to the background)
- [Sizing](https://github.com/payloadcms/payload/blob/beta/packages/ui/src/scss/app.scss)
- [Sizing](https://github.com/payloadcms/payload/blob/main/packages/ui/src/scss/app.scss)
- Horizontal gutter
- Transition speeds
- Font sizes

View File

@@ -66,7 +66,7 @@ A description can be configured in three ways:
- As a function which returns a string. [More details](#description-functions).
- As a React component. [More details](#description).
To easily add a Custom Description to a field, use the `admin.description` property in your [Field Config](../fields/overview):
To add a Custom Description to a field, use the `admin.description` property in your [Field Config](../fields/overview):
```ts
import type { SanitizedCollectionConfig } from 'payload'
@@ -95,7 +95,7 @@ export const MyCollectionConfig: SanitizedCollectionConfig = {
Custom Descriptions can also be defined as a function. Description Functions are executed on the server and can be used to format simple descriptions based on the user's current [Locale](../configuration/localization).
To easily add a Description Function to a field, set the `admin.description` property to a _function_ in your [Field Config](../fields/overview):
To add a Description Function to a field, set the `admin.description` property to a _function_ in your [Field Config](../fields/overview):
```ts
import type { SanitizedCollectionConfig } from 'payload'
@@ -121,6 +121,11 @@ All Description Functions receive the following arguments:
| -------------- | ---------------------------------------------------------------- |
| **`t`** | The `t` function used to internationalize the Admin Panel. [More details](../configuration/i18n) |
<Banner type="info">
<strong>Note:</strong>
If you need to subscribe to live updates within your form, use a Description Component instead. [More details](#description).
</Banner>
## Conditional Logic
You can show and hide fields based on what other fields are doing by utilizing conditional logic on a field by field basis. The `condition` property on a field's admin config accepts a function which takes three arguments:
@@ -168,7 +173,7 @@ Within the [Admin Panel](./overview), fields are represented in three distinct p
- [Cell](#cell) - The table cell component rendered in the List View.
- [Filter](#filter) - The filter component rendered in the List View.
To easily swap in Field Components with your own, use the `admin.components` property in your [Field Config](../fields/overview):
To swap in Field Components with your own, use the `admin.components` property in your [Field Config](../fields/overview):
```ts
import type { CollectionConfig } from 'payload'
@@ -206,7 +211,7 @@ The following options are available:
The Field Component is the actual form field rendered in the Edit View. This is the input that user's will interact with when editing a document.
To easily swap in your own Field Component, use the `admin.components.Field` property in your [Field Config](../fields/overview):
To swap in your own Field Component, use the `admin.components.Field` property in your [Field Config](../fields/overview):
```ts
import type { CollectionConfig } from 'payload'
@@ -307,7 +312,7 @@ import type {
The Cell Component is rendered in the table of the List View. It represents the value of the field when displayed in a table cell.
To easily swap in your own Cell Component, use the `admin.components.Cell` property in your [Field Config](../fields/overview):
To swap in your own Cell Component, use the `admin.components.Cell` property in your [Field Config](../fields/overview):
```ts
import type { Field } from 'payload'
@@ -332,11 +337,35 @@ All Cell Components receive the same [Default Field Component Props](#field), pl
For details on how to build Custom Components themselves, see [Building Custom Components](./components#building-custom-components).
### Filter
The Filter Component is the actual input element rendered within the "Filter By" dropdown of the List View used to represent this field when building filters.
To swap in your own Filter Component, use the `admin.components.Filter` property in your [Field Config](../fields/overview):
```ts
import type { Field } from 'payload'
export const myField: Field = {
name: 'myField',
type: 'text',
admin: {
components: {
Filter: '/path/to/MyCustomFilterComponent', // highlight-line
},
},
}
```
All Custom Filter Components receive the same [Default Field Component Props](#field).
For details on how to build Custom Components themselves, see [Building Custom Components](./components#building-custom-components).
### Label
The Label Component is rendered anywhere a field needs to be represented by a label. This is typically used in the Edit View, but can also be used in the List View and elsewhere.
To easily swap in your own Label Component, use the `admin.components.Label` property in your [Field Config](../fields/overview):
To swap in your own Label Component, use the `admin.components.Label` property in your [Field Config](../fields/overview):
```ts
import type { Field } from 'payload'
@@ -372,7 +401,7 @@ import type {
Alternatively to the [Description Property](#the-description-property), you can also use a [Custom Component](./components) as the Field Description. This can be useful when you need to provide more complex feedback to the user, such as rendering dynamic field values or other interactive elements.
To easily add a Description Component to a field, use the `admin.components.Description` property in your [Field Config](../fields/overview):
To add a Description Component to a field, use the `admin.components.Description` property in your [Field Config](../fields/overview):
```ts
import type { SanitizedCollectionConfig } from 'payload'
@@ -414,7 +443,7 @@ import type {
The Error Component is rendered when a field fails validation. It is typically displayed beneath the field input in a visually-compelling style.
To easily swap in your own Error Component, use the `admin.components.Error` property in your [Field Config](../fields/overview):
To swap in your own Error Component, use the `admin.components.Error` property in your [Field Config](../fields/overview):
```ts
import type { Field } from 'payload'

View File

@@ -785,7 +785,7 @@ const Greeting: React.FC = () => {
## useConfig
Used to easily retrieve the Payload [Client Config](./components#accessing-the-payload-config).
Used to retrieve the Payload [Client Config](./components#accessing-the-payload-config).
```tsx
'use client'

View File

@@ -177,7 +177,7 @@ The following options are available:
<Banner type="success">
<strong>Tip:</strong>
You can easily add _new_ routes to the Admin Panel through [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Views](./views).
You can easily add _new_ routes to the Admin Panel through [Custom Endpoints](../rest-api/overview#custom-endpoints) and [Custom Views](./views).
</Banner>
#### Customizing Root-level Routes
@@ -237,7 +237,7 @@ The following options are available:
## I18n
The Payload Admin Panel is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/beta/packages/translations). Languages are automatically detected based on the user's browser and used by the Admin Panel to display all text in that language. If no language was detected, or if the user's language is not yet supported, English will be chosen. Users can easily specify their language by selecting one from their account page. See [I18n](../configuration/i18n) for more information.
The Payload Admin Panel is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/main/packages/translations). Languages are automatically detected based on the user's browser and used by the Admin Panel to display all text in that language. If no language was detected, or if the user's language is not yet supported, English will be chosen. Users can easily specify their language by selecting one from their account page. See [I18n](../configuration/i18n) for more information.
## Light and Dark Modes

View File

@@ -47,7 +47,7 @@ Payload automatically creates an internally used `payload-preferences` Collectio
## APIs
Preferences are available to both [GraphQL](/docs/graphql/overview#preferences) and [REST](/docs/rest-api/overview#) APIs.
Preferences are available to both [GraphQL](/docs/graphql/overview#preferences) and [REST](/docs/rest-api/overview#preferences) APIs.
## Adding or reading Preferences in your own components

View File

@@ -21,7 +21,7 @@ To swap in your own Custom View, first consult the list of available components,
Root Views are the main views of the [Admin Panel](./overview). These are views that are scoped directly under the `/admin` route, such as the Dashboard or Account views.
To easily swap Root Views with your own, or to [create entirely new ones](#adding-new-root-views), use the `admin.components.views` property of your root [Payload Config](../configuration/overview):
To swap Root Views with your own, or to [create entirely new ones](#adding-new-root-views), use the `admin.components.views` property of your root [Payload Config](../configuration/overview):
```ts
import { buildConfig } from 'payload'
@@ -143,7 +143,7 @@ The above example shows how to add a new [Root View](#root-views), but the patte
Collection Views are views that are scoped under the `/collections` route, such as the Collection List and Document Edit views.
To easily swap out Collection Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property of your [Collection Config](../collections/overview):
To swap out Collection Views with your own, or to [create entirely new ones](#adding-new-views), use the `admin.components.views` property of your [Collection Config](../collections/overview):
```ts
import type { SanitizedCollectionConfig } from 'payload'
@@ -198,7 +198,7 @@ The following options are available:
Global Views are views that are scoped under the `/globals` route, such as the Document Edit View.
To easily swap out Global Views with your own or [create entirely new ones](#adding-new-views), use the `admin.components.views` property in your [Global Config](../globals/overview):
To swap out Global Views with your own or [create entirely new ones](#adding-new-views), use the `admin.components.views` property in your [Global Config](../globals/overview):
```ts
import type { SanitizedGlobalConfig } from 'payload'
@@ -248,7 +248,7 @@ The following options are available:
Document Views are views that are scoped under the `/collections/:collectionSlug/:id` or the `/globals/:globalSlug` route, such as the Edit View or the API View. All Document Views keep their overall structure across navigation changes, such as their title and tabs, and replace only the content below.
To easily swap out Document Views with your own, or to [create entirely new ones](#adding-new-document-views), use the `admin.components.views.Edit[key]` property in your [Collection Config](../collections/overview) or [Global Config](../globals/overview):
To swap out Document Views with your own, or to [create entirely new ones](#adding-new-document-views), use the `admin.components.views.Edit[key]` property in your [Collection Config](../collections/overview) or [Global Config](../globals/overview):
```ts
import type { SanitizedCollectionConfig } from 'payload'
@@ -350,6 +350,8 @@ export const MyCollectionConfig: SanitizedCollectionConfig = {
}
```
### Default Props
Your Custom Views will be provided with the following props:
| Prop | Description |
@@ -359,6 +361,7 @@ Your Custom Views will be provided with the following props:
| **`importMap`** | The import map object. |
| **`params`** | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
| **`searchParams`** | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
| **`doc`** | The document being edited. Only available in Document Views. [More details](#document-views). |
<Banner type="success">
<strong>Reminder:</strong>

View File

@@ -273,7 +273,7 @@ const result = await payload.verifyEmail({
If a user locks themselves out and you wish to deliberately unlock them, you can utilize the Unlock operation. The [Admin Panel](../admin/overview) features an Unlock control automatically for all collections that feature max login attempts, but you can programmatically unlock users as well by using the Unlock operation.
To restrict who is allowed to unlock users, you can utilize the [`unlock`](../access-control/overview#unlock) access control function.
To restrict who is allowed to unlock users, you can utilize the [`unlock`](../access-control/collections#unlock) access control function.
**Example REST API unlock**:

View File

@@ -22,7 +22,7 @@ Here are some common use cases of Authentication in your own applications:
When Authentication is enabled on a [Collection](../configuration/collections), Payload injects all necessary functionality to support the entire user flow. This includes all [auth-related operations](./operations) like account creation, logging in and out, and resetting passwords, all [auth-related emails](./email) like email verification and password reset, as well as any necessary UI to manage users from the Admin Panel.
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collection#auth):
To enable Authentication on a Collection, use the `auth` property in the [Collection Config](../configuration/collections#config-options):
```ts
import type { CollectionConfig } from 'payload'

View File

@@ -46,6 +46,6 @@ _Creating a new project from an existing repository._
<Banner type="warning">
<strong>Note:</strong> In order to make use of the features of Payload Cloud in your own codebase,
you will need to add the [Cloud Plugin](https://github.com/payloadcms/plugin-cloud) to your
you will need to add the [Cloud Plugin](https://github.com/payloadcms/payload/tree/main/packages/payload-cloud) to your
Payload app.
</Banner>

View File

@@ -28,7 +28,7 @@ Your Payload Cloud project comes with a MongoDB serverless Atlas DB instance or
Payload Cloud gives you S3 file storage backed by Cloudflare as a CDN, and this plugin extends Payload so that all of your media will be stored in S3 rather than locally.
AWS Cognito is used for authentication to your S3 bucket. The [Payload Cloud Plugin](https://github.com/payloadcms/plugin-cloud) will automatically pick up these values. These values are only if you'd like to access your files directly, outside of Payload Cloud.
AWS Cognito is used for authentication to your S3 bucket. The [Payload Cloud Plugin](https://github.com/payloadcms/payload/tree/main/packages/payload-cloud) will automatically pick up these values. These values are only if you'd like to access your files directly, outside of Payload Cloud.
### Accessing Files Outside of Payload Cloud

View File

@@ -52,7 +52,7 @@ export const Posts: CollectionConfig = {
<Banner type="success">
<strong>Reminder:</strong>
For a more complex example, see the [Public Demo](https://github.com/payloadcms/public-demo) source code on GitHub, or the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
</Banner>
The following options are available:

View File

@@ -6,7 +6,7 @@ desc: Set up your Global config for your needs by defining fields, adding slugs
keywords: globals, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
---
Globals are in many ways similar to [Collections](../configuration/collections), except they correspond to only a single Document. You can define as many Globals as your application needs. Each Global Document is stored in the [Database](../database/overview) based on the [Fields](../fields/overview) that you define, and automatically generates a [Local API](../local-api/overview), [REST API](../rest-api/overview), and [GraphQL API](../graphql/overview) used to manage your Documents.
Globals are in many ways similar to [Collections](../configuration/collections), except that they correspond to only a single Document. You can define as many Globals as your application needs. Each Global Document is stored in the [Database](../database/overview) based on the [Fields](../fields/overview) that you define, and automatically generates a [Local API](../local-api/overview), [REST API](../rest-api/overview), and [GraphQL API](../graphql/overview) used to manage your Documents.
Globals are the primary way to structure singletons in Payload, such as a header navigation, site-wide banner alerts, or app-wide localized strings. Each Global can have its own unique [Access Control](../access-control/overview), [Hooks](../hooks/overview), [Admin Options](#admin-options), and more.
@@ -60,7 +60,7 @@ export const Nav: GlobalConfig = {
<Banner type="success">
<strong>Reminder:</strong>
For a more complex example, see the [Public Demo](https://github.com/payloadcms/public-demo) source code on GitHub, or the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
</Banner>
The following options are available:

View File

@@ -6,9 +6,9 @@ desc: Manage and customize internationalization support in your CMS editor exper
keywords: internationalization, i18n, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
---
The [Admin Panel](../admin/overview) is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/beta/packages/translations). With I18n, editors can navigate the interface and read API error messages in their preferred language. This is similar to [Localization](./localization), but instead of managing translations for the data itself, you are managing translations for your application's interface.
The [Admin Panel](../admin/overview) is translated in over [30 languages and counting](https://github.com/payloadcms/payload/tree/main/packages/translations). With I18n, editors can navigate the interface and read API error messages in their preferred language. This is similar to [Localization](./localization), but instead of managing translations for the data itself, you are managing translations for your application's interface.
By default, Payload comes with preinstalled with English, but you can easily load other languages into your own application. Languages are automatically detected based on the request. If no language was detected, or if the user's language is not yet supported by your application, English will be chosen.
By default, Payload comes preinstalled with English, but you can easily load other languages into your own application. Languages are automatically detected based on the request. If no language is detected, or if the user's language is not yet supported by your application, English will be chosen.
To configure I18n, use the `i18n` key in your [Payload Config](./overview):

View File

@@ -58,13 +58,13 @@ export default buildConfig({
<Banner type="success">
<strong>Note:</strong>
For a more complex example, see the [Public Demo](https://github.com/payloadcms/public-demo) source code on GitHub, or the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
</Banner>
The following options are available:
| Option | Description |
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`admin`** | The configuration options for the Admin Panel, including Custom Components, Live Preview, etc. [More details](../admin/overview#admin-options). |
| **`bin`** | Register custom bin scripts for Payload to execute. |
| **`editor`** | The Rich Text Editor which will be used by `richText` fields. [More details](../rich-text/overview). |
@@ -83,6 +83,7 @@ The following options are available:
| **`defaultDepth`** | If a user does not specify `depth` while requesting a resource, this depth will be used. [More details](../queries/depth). |
| **`defaultMaxTextLength`** | The maximum allowed string length to be permitted application-wide. Helps to prevent malicious public document creation. |
| **`maxDepth`** | The maximum allowed depth to be permitted application-wide. This setting helps prevent against malicious queries. Defaults to `10`. [More details](../queries/depth). |
| **`maxCallDepth`** | The maximum allowed call depth for Local API operations. This setting helps prevent against hooks that lead to infinity loops. Can be disabled with passing `false`. Defaults to `30`. |
| **`indexSortableFields`** | Automatically index all sortable top-level fields in the database to improve sort performance and add database compatibility for Azure Cosmos and similar. |
| **`upload`** | Base Payload upload configuration. [More details](../upload/overview#payload-wide-upload-options). |
| **`routes`** | Control the routing structure that Payload binds itself to. [More details](../admin/overview#root-level-routes). |

View File

@@ -12,18 +12,13 @@ Examples are changing every day, so be sure to check back often to see what new
- [Auth](https://github.com/payloadcms/payload/tree/main/examples/auth)
- [Custom Components](https://github.com/payloadcms/payload/tree/main/examples/custom-components)
- [Custom Server](https://github.com/payloadcms/payload/tree/main/examples/custom-server)
- [Draft Preview](https://github.com/payloadcms/payload/tree/main/examples/draft-preview)
- [Email](https://github.com/payloadcms/payload/tree/main/examples/email)
- [Form Builder](https://github.com/payloadcms/payload/tree/main/examples/form-builder)
- [Hierarchy](https://github.com/payloadcms/payload/tree/main/examples/hierarchy)
- [Live Preview](https://github.com/payloadcms/payload/tree/main/examples/live-preview)
- [Multi-tenant](https://github.com/payloadcms/payload/tree/main/examples/multi-tenant)
- [Nested Docs](https://github.com/payloadcms/payload/tree/main/examples/nested-docs)
- [Redirects](https://github.com/payloadcms/payload/tree/main/examples/redirects)
- [Tailwind / Shadcn-ui](https://github.com/payloadcms/payload/tree/main/examples/tailwind-shadcn-ui)
- [Tests](https://github.com/payloadcms/payload/tree/main/examples/testing)
- [Virtual Fields](https://github.com/payloadcms/payload/tree/main/examples/virtual-fields)
- [White-label Admin UI](https://github.com/payloadcms/payload/tree/main/examples/whitelabel)
When necessary, some examples include a front-end. Examples that require a front-end share this folder structure:

View File

@@ -84,6 +84,51 @@ The Blocks Field inherits all of the default options from the base [Field Admin
| **`initCollapsed`** | Set the initial collapsed state |
| **`isSortable`** | Disable order sorting by setting this value to `false` |
#### Customizing the way your block is rendered in Lexical
If you're using this block within the [Lexical editor](/docs/lexical/overview), you can also customize how the block is rendered in the Lexical editor itself by specifying custom components.
- `admin.components.Label` - pass a custom React component here to customize the way that the label is rendered for this block
- `admin.components.Block` - pass a component here to completely override the way the block is rendered in Lexical with your own component
This is super handy if you'd like to present your editors with a very deliberate and nicely designed block "preview" right in your rich text.
For example, if you have a `gallery` block, you might want to actually render the gallery of images directly in your Lexical block. With the `admin.components.Block` property, you can do exactly that!
<Banner type="success">
<strong>Tip:</strong><br/>
If you customize the way your block is rendered in Lexical, you can import utility components to easily edit / remove your block - so that you don't have to build all of this yourself.
</Banner>
To import these utility components for one of your custom blocks, you can import the following:
```ts
import {
// Edit block buttons (choose the one that corresponds to your usage)
// When clicked, this will open a drawer with your block's fields
// so your editors can edit them
InlineBlockEditButton,
BlockEditButton,
// Buttons that will remove this block from Lexical
// (choose the one that corresponds to your usage)
InlineBlockRemoveButton,
BlockRemoveButton,
// The label that should be rendered for an inline block
InlineBlockLabel,
// The default "container" that is rendered for an inline block
// if you want to re-use it
InlineBlockContainer,
// The default "collapsible" UI that is rendered for a regular block
// if you want to re-use it
BlockCollapsible,
} from '@payloadcms/richtext-lexical/client'
```
## Block Configs
Blocks are defined as separate configs of their own.

View File

@@ -19,8 +19,8 @@ Payload's rich text field is built on an "adapter pattern" which lets you specif
Right now, Payload is officially supporting two rich text editors:
1. [SlateJS](/docs/rich-text/slate) - stable, backwards-compatible with 1.0
2. [Lexical](/docs/lexical/overview) - beta, where things will be moving
1. [SlateJS](/docs/rich-text/slate) - legacy, backwards-compatible with 1.0
2. [Lexical](/docs/lexical/overview) - recommended
<Banner type="success">
<strong>

View File

@@ -108,7 +108,7 @@ called with an argument object with the following properties:
| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation |
| `user` | An object containing the currently authenticated user |
## Example
### Example#filter-options-example
```ts
const uploadField = {

View File

@@ -34,7 +34,7 @@ Hooks allow you to execute your own side effects during specific events of the D
## Authentication
Payload provides a secure, portable way to manage user accounts out of the box. Payload Authentication is designed to be used in both the Admin Panel, all well as your own external applications. [More details](../authentication/overview).
Payload provides a secure, portable way to manage user accounts out of the box. Payload Authentication is designed to be used in both the Admin Panel, as well as your own external applications. [More details](../authentication/overview).
## Access Control
@@ -68,15 +68,10 @@ Here's a quick example of a React Server Component fetching data using the Local
```tsx
import React from 'react'
import config from '@payload-config'
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { getPayload } from 'payload'
const MyServerComponent: React.FC = () => {
// If you're working in Next.js, and you want HMR,
// you should get Payload via the `getPayloadHMR` function.
const payload = await getPayloadHMR({ config })
// If you are writing a standalone script and do not need HMR,
// you can get Payload via import { getPayload } from 'payload' instead.
const payload = await getPayload({ config })
// The `findResult` here will be fully typed as `PaginatedDocs<Page>`,
// where you will have the `docs` that are returned as well as
@@ -156,7 +151,7 @@ Whereas Payload itself is responsible for direct database access, and control ov
`@payloadcms/graphql`
All of Payload's GraphQL functionality is abstracted into a separate package. Payload, its Admin UI, and REST API have absolutely no overlap with GraphQL, and you will incur no performance overhead from GraphQL if you are not using it. However, it's installed within in the `@payloadcms/next` package so you don't have to install it manually. You do, however, need to have GraphQL installed separately in your `package.json` if you are using GraphQL.
All of Payload's GraphQL functionality is abstracted into a separate package. Payload, its Admin UI, and REST API have absolutely no overlap with GraphQL, and you will incur no performance overhead from GraphQL if you are not using it. However, it's installed within the `@payloadcms/next` package so you don't have to install it manually. You do, however, need to have GraphQL installed separately in your `package.json` if you are using GraphQL.
`@payloadcms/ui`

View File

@@ -24,14 +24,14 @@ Payload requires the following software:
To quickly scaffold a new Payload app in the fastest way possible, you can use [create-payload-app](https://npmjs.com/package/create-payload-app). To do so, run the following command:
```
npx create-payload-app@beta
npx create-payload-app
```
Then just follow the prompts! You'll get set up with a new folder and a functioning Payload app inside. You can then start [configuring your application](../configuration/overview).
## Adding to an existing app
Adding Payload to an existing Next.js app is super straightforward. You can either run the `npx create-payload-app@beta` command inside your Next.js project's folder, or manually install Payload by following the steps below.
Adding Payload to an existing Next.js app is super straightforward. You can either run the `npx create-payload-app` command inside your Next.js project's folder, or manually install Payload by following the steps below.
If you don't have a Next.js app already, but you still want to start a project from a blank Next.js app, you can create a new Next.js app using `npx create-next-app` - and then just follow the steps below to install Payload.
@@ -44,7 +44,7 @@ If you don't have a Next.js app already, but you still want to start a project f
First, you'll want to add the required Payload packages to your project and can do so by running the command below:
```bash
pnpm i payload@beta @payloadcms/next@beta @payloadcms/richtext-lexical@beta sharp graphql
pnpm i payload @payloadcms/next @payloadcms/richtext-lexical sharp graphql
```
<Banner type="warning">
@@ -58,12 +58,12 @@ To install a Database Adapter, you can run **one** of the following commands:
- To install the [MongoDB Adapter](../database/mongodb), run:
```bash
pnpm i @payloadcms/db-mongodb@beta
pnpm i @payloadcms/db-mongodb
```
- To install the [Postgres Adapter](../database/postgres), run:
```bash
pnpm i @payloadcms/db-postgres@beta
pnpm i @payloadcms/db-postgres
```
<Banner type="success">
@@ -73,7 +73,7 @@ To install a Database Adapter, you can run **one** of the following commands:
#### 2. Copy Payload files into your Next.js app folder
Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template](https://github.com/payloadcms/payload/tree/beta/templates/blank/src/app/(payload)) on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template](https://github.com/payloadcms/payload/tree/main/templates/blank/src/app/(payload)) on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
```plaintext
app/
@@ -181,6 +181,6 @@ Once you have a Payload Config, update your `tsconfig` to include a `path` that
#### 5. Fire it up!
After you've gotten this far, it's time to boot up Payload. Start your project in your application's folder to get going. By default, the Next.js dev script is `pnpm dev` (or `npm run dev` if using NPM).
After you've reached this point, it's time to boot up Payload. Start your project in your application's folder to get going. By default, the Next.js dev script is `pnpm dev` (or `npm run dev` if using NPM).
After it starts, you can go to `http://localhost:3000/admin` to create your first Payload user!

View File

@@ -3,7 +3,7 @@ title: What is Payload?
label: What is Payload?
order: 10
desc: Payload is a next-gen application framework that can be used as a Content Management System, enterprise tool framework, headless commerce platform, or digital asset management tool.
keywords: documentation, getting started, guide, Content Management System, cms, headless, javascript, node, react, express
keywords: documentation, getting started, guide, Content Management System, cms, headless, javascript, node, react
---
<YouTube
@@ -24,7 +24,7 @@ keywords: documentation, getting started, guide, Content Management System, cms,
### Instant backend superpowers
No matter what you're building, Payload will give you backend superpowers. It can be installed in one line into any existing Next.js app, and is designed to catapult your development process. Payload takes the most complex and time-consuming parts of any modern web app and makes them simple.
No matter what you're building, Payload will give you backend superpowers. Your entire Payload config can be installed in one line into any existing Next.js app, and is designed to catapult your development process. Payload takes the most complex and time-consuming parts of any modern web app and makes them simple.
### Open source - deploy anywhere, including Vercel
@@ -95,12 +95,6 @@ Payload can integrate with any payment processor like Stripe and its content aut
If you can build your storefront with a single backend, and only offload things like payment processing, the code will be simpler and the editing experience will be significantly streamlined. Manage products, catalogs, page content, media, and more—all in one spot.
Payload's official Ecommerce template gives you everything you need for a storefront out of the box, including a Next.js frontend, product variations, and a full Stripe implementation:
```
npx create-payload-app@latest -t ecommerce
```
### Digital Asset Management
Payload's API-first tagging, sorting, and querying engine lends itself perfectly to all types of content that a CMS might ordinarily store, but these strong fundamentals also make it a formidable Digital Asset Management (DAM) tool as well.

View File

@@ -13,7 +13,7 @@ In Payload the schema is controlled by your collections and globals. All you nee
Install `@payloadcms/graphql` as a dev dependency:
```bash
pnpm add @payloadcms/graphql@beta -D
pnpm add @payloadcms/graphql -D
```
Run the following command to generate the schema:

View File

@@ -32,7 +32,7 @@ Examples:
**Periodic sync or similar scheduled action**
Some applications may need to perform a regularly scheduled operation of some type. Jobs are perfect for this because you can execute their logic using `cron`, scheduled nightly, every twelve hours, or some similar time period.
Some applications may need to perform a regularly scheduled operation of some type. Jobs are perfect for this because you can execute their logic using `cron`, scheduled nightly, every twelve hours, or some similar time period.
Examples:
@@ -49,22 +49,22 @@ Examples:
- You need to create (and then keep in sync) vector embeddings of your documents as they change, but you use an open source model to generate embeddings
- You have a PDF generator that needs to dynamically build and send PDF versions of documents to customers
- You need to use a headless browser to perform some type of logic
- You need to perform a series of actions, each of which depends on a prior action and should be run in as "durable" of a fashion as possible
- You need to perform a series of actions, each of which depends on a prior action and should be run in as "durable" of a fashion as possible
### How it works
There are a few concepts that you should become familiarized with before using Payload's Jobs Queue. We recommend learning what each of these does in order to fully understand how to leverage the power of Payload's Jobs Queue.
1. [Tasks](/docs/beta/jobs-queue/tasks)
1. [Workflows](/docs/beta/jobs-queue/workflows)
1. [Jobs](/docs/beta/jobs-queue/jobs)
1. [Queues](/docs/beta/jobs-queue/queues)
1. [Tasks](/docs/jobs-queue/tasks)
1. [Workflows](/docs/jobs-queue/workflows)
1. [Jobs](/docs/jobs-queue/jobs)
1. [Queues](/docs/jobs-queue/queues)
All of these pieces work together in order to allow you to offload long-running, expensive, or future scheduled work from your main APIs.
All of these pieces work together in order to allow you to offload long-running, expensive, or future scheduled work from your main APIs.
Here's a quick overview:
- A Task is a specific function that performs business logic
- Workflows are groupings of specific tasks which should be run in-order, and can be retried from a specific point of failure
- A Job is an instance of a single task or workflow which will be executed
- A Queue is a way to segment your jobs into different "groups" - for example, some to run nightly, and others to run every 10 minutes
- A Queue is a way to segment your jobs into different "groups" - for example, some to run nightly, and others to run every 10 minutes

View File

@@ -2,7 +2,7 @@
title: Tasks
label: Tasks
order: 20
desc: A Task is a distinct function declaration that can be run within Payload's Jobs Queue.
desc: A Task is a distinct function declaration that can be run within Payload's Jobs Queue.
keywords: jobs queue, application framework, typescript, node, react, nextjs
---
@@ -10,7 +10,7 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
A <strong>"Task"</strong> is a function definition that performs business logic and whose input and output are both strongly typed.
</Banner>
You can register Tasks on the Payload config, and then create [Jobs](/docs/beta/jobs-queue/jobs) or [Workflows](/docs/beta/jobs-queue/workflows) that use them. Think of Tasks like tidy, isolated "functions that do one specific thing".
You can register Tasks on the Payload config, and then create [Jobs](/docs/jobs-queue/jobs) or [Workflows](/docs/jobs-queue/workflows) that use them. Think of Tasks like tidy, isolated "functions that do one specific thing".
Payload Tasks can be configured to automatically retried if they fail, which makes them valuable for "durable" workflows like AI applications where LLMs can return non-deterministic results, and might need to be retried.

View File

@@ -77,13 +77,13 @@ export const MyFeature = createServerFeature({
This allows you to add i18n translations scoped to your feature. This specific example translation will be available under `lexical:myFeature:label` - `myFeature` being your feature key.
### Markdown Transformers
### Markdown Transformers#server-feature-markdown-transformers
The Server Feature, just like the Client Feature, allows you to add markdown transformers. Markdown transformers on the server are used when [converting the editor from or to markdown](/docs/lexical/converters#markdown-lexical).
```ts
import { createServerFeature } from '@payloadcms/richtext-lexical';
import type { ElementTransformer } from '@lexical/markdown'
import type { ElementTransformer } from '@payloadcms/richtext-lexical/lexical/markdown'
import {
$createMyNode,
$isMyNode,
@@ -120,7 +120,7 @@ export const MyFeature = createServerFeature({
In this example, the node will be outputted as `+++` in Markdown, and the markdown `+++` will be converted to a `MyNode` node in the editor.
### Nodes
### Nodes#server-feature-nodes
While nodes added to the server feature do not control how the node is rendered in the editor, they control other aspects of the node:
- HTML conversion
@@ -266,7 +266,7 @@ export const MyClientFeature = createClientFeature({
Explore the APIs available through ClientFeature to add the specific functionality you need. Remember, do not import directly from `'@payloadcms/richtext-lexical'` when working on the client-side, as it will cause errors with webpack or turbopack. Instead, use `'@payloadcms/richtext-lexical/client'` for all client-side imports. Type-imports are excluded from this rule and can always be imported.
### Nodes
### Nodes#client-feature-nodes
Add nodes to the `nodes` array in **both** your client & server feature. On the server side, nodes are utilized for backend operations like HTML conversion in a headless editor. On the client side, these nodes are integral to how content is displayed and managed in the editor, influencing how they are rendered, behave, and saved in the database.
@@ -299,9 +299,9 @@ import type {
EditorConfig,
LexicalNode,
SerializedLexicalNode,
} from 'lexical'
} from '@payloadcms/richtext-lexical/lexical'
import { $applyNodeReplacement, DecoratorNode } from 'lexical'
import { $applyNodeReplacement, DecoratorNode } from '@payloadcms/richtext-lexical/lexical'
// SerializedLexicalNode is the default lexical node.
// By setting your SerializedMyNode type to SerializedLexicalNode,
@@ -448,17 +448,17 @@ Example plugin.tsx:
'use client'
import type {
LexicalCommand,
} from 'lexical'
} from '@payloadcms/richtext-lexical/lexical'
import {
createCommand,
$getSelection,
$isRangeSelection,
COMMAND_PRIORITY_EDITOR
} from 'lexical'
} from '@payloadcms/richtext-lexical/lexical'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
import { $insertNodeToNearestRoot } from '@lexical/utils'
import { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext.js'
import { $insertNodeToNearestRoot } from '@payloadcms/richtext-lexical/lexical/utils'
import { useEffect } from 'react'
import type { PluginComponent } from '@payloadcms/richtext-lexical' // type imports can be imported from @payloadcms/richtext-lexical - even on the client
@@ -589,7 +589,7 @@ import { createClientFeature, toolbarAddDropdownGroupWithItems } from '@payloadc
import { IconComponent } from './icon';
import { $isHorizontalRuleNode } from './nodes/MyNode';
import { INSERT_MYNODE_COMMAND } from './plugin';
import { $isNodeSelection } from 'lexical'
import { $isNodeSelection } from '@payloadcms/richtext-lexical/lexical'
export const MyClientFeature = createClientFeature({
toolbarFixed: {
@@ -705,13 +705,13 @@ export const MyClientFeature = createClientFeature({
| **`keywords`** | Keywords are used to match the item for different texts typed after the '/'. E.g. you might want to show a horizontal rule item if you type both /hr, /separator, /horizontal etc. In addition to the keywords, the label and key will be used to find the right slash menu item. |
### Markdown Transformers
### Markdown Transformers#client-feature-markdown-transformers
The Client Feature, just like the Server Feature, allows you to add markdown transformers. Markdown transformers on the client are used to create new nodes when a certain markdown pattern is typed in the editor.
```ts
import { createClientFeature } from '@payloadcms/richtext-lexical/client';
import type { ElementTransformer } from '@lexical/markdown'
import type { ElementTransformer } from '@payloadcms/richtext-lexical/lexical/markdown'
import {
$createMyNode,
$isMyNode,
@@ -836,4 +836,4 @@ The reason the client feature does not have the same props available as the serv
## More information
Have a look at the [features we've already built](https://github.com/payloadcms/payload/tree/beta/packages/richtext-lexical/src/features) - understanding how they work will help you understand how to create your own. There is no difference between the features included by default and the ones you create yourself - since those features are all isolated from the "core", you have access to the same APIs, whether the feature is part of Payload or not!
Have a look at the [features we've already built](https://github.com/payloadcms/payload/tree/main/packages/richtext-lexical/src/features) - understanding how they work will help you understand how to create your own. There is no difference between the features included by default and the ones you create yourself - since those features are all isolated from the "core", you have access to the same APIs, whether the feature is part of Payload or not!

View File

@@ -200,7 +200,7 @@ Lexical provides a seamless way to perform conversions between various other for
A headless editor can perform such conversions outside of the main editor instance. Follow this method to initiate a headless editor:
```ts
import { createHeadlessEditor } from '@lexical/headless' // <= make sure this package is installed
import { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless'
import { getEnabledNodes, sanitizeServerEditorConfig } from '@payloadcms/richtext-lexical'
const yourEditorConfig // <= your editor config here
@@ -237,7 +237,7 @@ If you have access to the sanitized collection config, you can get access to the
```ts
import type { CollectionConfig, RichTextField } from 'payload'
import { createHeadlessEditor } from '@lexical/headless'
import { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless'
import type { LexicalRichTextAdapter, SanitizedServerEditorConfig } from '@payloadcms/richtext-lexical'
import {
getEnabledNodes,
@@ -292,8 +292,8 @@ export const MyCollection: CollectionConfig = {
Once you have your headless editor instance, you can use it to convert HTML to Lexical:
```ts
import { $generateNodesFromDOM } from '@lexical/html'
import { $getRoot, $getSelection } from 'lexical'
import { $generateNodesFromDOM } from '@payloadcms/richtext-lexical/lexical/html'
import { $getRoot, $getSelection } from '@payloadcms/richtext-lexical/lexical'
import { JSDOM } from 'jsdom'
headlessEditor.update(
@@ -334,8 +334,7 @@ This has been taken from the [lexical serialization & deserialization docs](http
Convert markdown content to the Lexical editor format with the following:
```ts
import { $convertFromMarkdownString } from '@lexical/markdown'
import { sanitizeServerEditorConfig } from '@payloadcms/richtext-lexical'
import { sanitizeServerEditorConfig, $convertFromMarkdownString } from '@payloadcms/richtext-lexical'
const yourSanitizedEditorConfig = sanitizeServerEditorConfig(yourEditorConfig, payloadConfig) // <= your editor config & Payload Config here
const markdown = `# Hello World`
@@ -361,9 +360,9 @@ Export content from the Lexical editor into Markdown format using these steps:
Here's the code for it:
```ts
import { $convertToMarkdownString } from '@lexical/markdown'
import { $convertToMarkdownString } from '@payloadcms/richtext-lexical/lexical/markdown'
import { sanitizeServerEditorConfig } from '@payloadcms/richtext-lexical'
import type { SerializedEditorState } from 'lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
const yourSanitizedEditorConfig = sanitizeServerEditorConfig(yourEditorConfig, payloadConfig) // <= your editor config & Payload Config here
const yourEditorState: SerializedEditorState // <= your current editor state here
@@ -397,8 +396,8 @@ Export content from the Lexical editor into plain text using these steps:
Here's the code for it:
```ts
import type { SerializedEditorState } from 'lexical'
import { $getRoot } from 'lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
import { $getRoot } from '@payloadcms/richtext-lexical/lexical'
const yourEditorState: SerializedEditorState // <= your current editor state here

View File

@@ -10,12 +10,6 @@ One of Payload's goals is to build the best rich text editor experience that we
Classically, we've used SlateJS to work toward this goal, but building custom elements into Slate has proven to be more difficult than we'd like, and we've been keeping our options open.
<Banner type="warning">
Payload's Lexical rich text editor is currently in beta. It's stable enough to use as you build on
Payload, so if you're up for helping us fine-tune it, you should use it. But if you're looking for
stability, use Slate instead.
</Banner>
Lexical is extremely impressive and trivializes a lot of the hard parts of building new elements into a rich text editor. It has a few distinct advantages over Slate, including the following:
1. A "/" menu, which allows editors to easily add new elements while never leaving their keyboard

View File

@@ -34,11 +34,11 @@ Then, render the `RefreshRouteOnSave` component anywhere in your `page.tsx`. Her
```tsx
import { RefreshRouteOnSave } from './RefreshRouteOnSave.tsx'
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { getPayload } from 'payload'
import config from '../payload.config'
export default async function Page() {
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const page = await payload.findByID({
collection: 'pages',

View File

@@ -18,12 +18,9 @@ Payload can be used completely outside of Next.js which is helpful in cases like
Payload provides a convenient way to run standalone scripts, which can be useful for tasks like seeding your database or performing one-off operations.
In standalone scripts, can simply import the Payload Config and use it right away. If you need an initialized copy of Payload, you can then use the `getPayload` function. This can be useful for tasks like seeding your database or performing other one-off operations.
In standalone scripts, you can simply import the Payload Config and use it right away. If you need an initialized copy of Payload, you can then use the `getPayload` function. This can be useful for tasks like seeding your database or performing other one-off operations.
```ts
// We are importing `getPayload` because we don't need HMR
// for a standalone script. For usage of Payload inside Next.js,
// you should always use `import { getPayloadHMR } from '@payloadcms/next/utilities'` instead.
import { getPayload } from 'payload'
import config from '@payload-config'

View File

@@ -43,27 +43,6 @@ const afterChangeHook: CollectionAfterChangeHook = async ({ req: { payload } })
If you want to import Payload in places where you don't have the option to access it from function arguments or `req`, you can import it and initialize it.
There are two places to import Payload:
**Option 1 - using HMR, within Next.js**
```ts
import { getPayloadHMR } from '@payloadcms/next/utilities'
import config from '@payload-config'
const payload = await getPayloadHMR({ config })
```
You should import Payload using the first option (`getPayloadHMR`) if you are using Payload inside of Next.js (like route handlers, server components, and similar.)
This way, in Next.js development mode, Payload will work with Hot Module Replacement (HMR), and as you make changes to your Payload Config, your usage of Payload will always be in sync with your changes. In production, `getPayloadHMR` simply disables all HMR functionality so you don't need to write your code any differently. We handle optimization for you in production mode.
If you are accessing Payload via function arguments or `req.payload`, HMR is automatically supported if you are using it within Next.js.
**Option 2 - outside of Next.js**
If you are using Payload outside of Next.js, for example in standalone scripts or in other frameworks, you can import Payload with no HMR functionality. Instead of using `getPayloadHMR`, you can use `getPayload`.
```ts
import { getPayload } from 'payload'
import config from '@payload-config'
@@ -71,7 +50,11 @@ import config from '@payload-config'
const payload = await getPayload({ config })
```
Both options function in exactly the same way outside of one having HMR support and the other not. For more information about using Payload outside of Next.js, [click here](./outside-nextjs).
If you're working in Next.js' development mode, Payload will work with Hot Module Replacement (HMR), and as you make changes to your Payload Config, your usage of Payload will always be in sync with your changes. In production, `getPayload` simply disables all HMR functionality so you don't need to write your code any differently. We handle optimization for you in production mode.
If you are accessing Payload via function arguments or `req.payload`, HMR is automatically supported if you are using it within Next.js.
For more information about using Payload outside of Next.js, [click here](./outside-nextjs).
## Local options available
@@ -119,7 +102,7 @@ const post = await payload.find({
The following Collection operations are available through the Local API:
### Create
### Create#collection-create
```js
// The created Post document is returned
@@ -151,7 +134,7 @@ const post = await payload.create({
})
```
### Find
### Find#collection-find
```js
// Result will be a paginated set of Posts.
@@ -172,7 +155,7 @@ const result = await payload.find({
})
```
### Find by ID
### Find by ID#collection-find-by-id
```js
// Result will be a Post document.
@@ -188,7 +171,7 @@ const result = await payload.findByID({
})
```
### Count
### Count#collection-count
```js
// Result will be an object with:
@@ -204,7 +187,7 @@ const result = await payload.count({
})
```
### Update by ID
### Update by ID#collection-update-by-id
```js
// Result will be the updated Post document.
@@ -236,7 +219,7 @@ const result = await payload.update({
})
```
### Update Many
### Update Many#collection-update-many
```js
// Result will be an object with:
@@ -275,7 +258,7 @@ const result = await payload.update({
})
```
### Delete
### Delete#collection-delete
```js
// Result will be the now-deleted Post document.
@@ -292,7 +275,7 @@ const result = await payload.delete({
})
```
### Delete Many
### Delete Many#collection-delete-many
```js
// Result will be an object with:
@@ -411,7 +394,7 @@ const result = await payload.verifyEmail({
The following Global operations are available through the Local API:
### Find
### Find#global-find
```js
// Result will be the Header Global.
@@ -426,7 +409,7 @@ const result = await payload.findGlobal({
})
```
### Update
### Update#global-update
```js
// Result will be the updated Header Global.

View File

@@ -1,15 +1,124 @@
# 🚧 **DRAFT:** 3.0 Migration Guide / Breaking Changes
---
title: 2.0 to 3.0 Migration Guide
label: 2.0 to 3.0 Migration Guide
order: 10
desc: Upgrade guide for Payload 2.x projects migrating to 3.0.
keywords: local api, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react
---
> [!IMPORTANT]
> This document will continue to be updated and cleaned up until the 3.0 release.
# Payload 2.0 to 3.0 Migration Guide
Payload 3.0 completely replatforms the Admin Panel from a React Router single-page application onto the Next.js App Router with full support for React Server Components. This change completely separates Payload "core" from its rendering and HTTP layers, making it truly Node-safe and portable.
## What has changed?
The core logic and principles of Payload remain the same from 2.0 to 3.0, with the majority of changes affecting specifically the HTTP layer and the Admin Panel, which is now built upon Next.js. With this change, your entire application can be served within a single repo. Payload endpoints are now opened directly within your own Next.js application, right alongside your frontend. All Payload APIs remain exactly the same (with a few new features), and the Payload Config is generally the same, with the breaking changes detailed below.
The core logic and principles of Payload remain the same from 2.0 to 3.0, with the majority of changes affecting specifically the HTTP layer and the Admin Panel, which is now built upon Next.js. With this change, your entire application can be served within a single repo, with Payload endpoints are now opened within your own Next.js application, directly alongside your frontend. Payload is still headless, you will still be able to leverage it completely headlessly just as you do now with Sveltekit, etc. All Payload APIs remain exactly the same (with a few new features), and the Payload Config is generally the same, with the breaking changes detailed below.
Payload is still headless, you will still be able to leverage it completely headlessly just as you do now with Sveltekit, etc. In fact, Payload itself is now _truly_ portable because it is fully Node.js compatible and completely separate from the HTTP layer. The entire Payload suite of packages has been modularized to make this possible.
### Table of Contents
## To migrate from Payload 2.0 to 3.0:
All breaking changes are listed below. If you encounter changes that are not explicitly listed here, please consider contributing to this documentation by submitting a PR.
- [Installation](#installation)
- [Breaking Changes](#breaking-changes)
- [Custom Components](#custom-components)
- [Endpoints](#endpoints)
- [React Hooks](#react-hooks)
- [Types](#types)
- [Email Adapters](#email-adapters)
- [Plugins](#plugins)
## Installation
Payload 3.0 requires a set of auto-generated files that you will need to bring into your existing project. The easiest way of acquiring these is by initializing a new project via `create-payload-app`, then replace the provided Payload Config with your own.
```bash
npx create-payload-app
```
For more details, see the [Documentation](https://payloadcms.com/docs/getting-started/installation).
1. **Install new dependencies of payload, next.js and react**:
Refer to the package.json file made in the create-payload-app, including peerDependencies, devDependencies, and dependencies. The core package and plugins require all versions to be synced. Previously, on 2.x it was possible to be running the latest version of payload 2.x with an older version of db-mongodb for example. This is no longer the case.
```bash
pnpm i next react react-dom payload @payloadcms/ui @payloadcms/next
```
Also install the other @payloadcms packages specific to the plugins and adapters you are using. Depending on your project, these may include:
- @payloadcms/db-mongodb
- @payloadcms/db-postgres
- @payloadcms/richtext-slate
- @payloadcms/richtext-lexical
- @payloadcms/plugin-form-builder
- @payloadcms/plugin-nested-docs
- @payloadcms/plugin-redirects
- @payloadcms/plugin-relationship
- @payloadcms/plugin-search
- @payloadcms/plugin-sentry
- @payloadcms/plugin-seo
- @payloadcms/plugin-stripe
- @payloadcms/plugin-cloud-storage - Read [More](#@payloadcms/plugin-cloud-storage).
1. Uninstall deprecated packages:
```bash
pnpm remove express nodemon @payloadcms/bundler-webpack @payloadcms/bundler-vite
```
1. Database Adapter Migrations
_If you have existing data_ and are using the MongoDB or Postgres adapters, you will need to run the database migrations to ensure your database schema is up-to-date.
- [postgres](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.39)
- [mongodb](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.131)
2. For Payload Cloud users, the plugin has changed.
Uninstall the old package:
```bash
pnpm remove @payloadcms/plugin-cloud
```
Install the new package:
```bash
pnpm i @payloadcms/payload-cloud
```
```diff
// payload.config.ts
- import { payloadCloud } from '@payloadcms/plugin-cloud'
+ import { payloadCloudPlugin } from '@payloadcms/payload-cloud'
buildConfig({
// ...
plugins: [
- payloadCloud()
+ payloadCloudPlugin()
]
})
```
3. **Optional** sharp dependency
If you have upload enabled collections that use `formatOptions`, `imageSizes`, or `resizeOptions`—payload expects to have `sharp` installed. In 2.0 this was a dependency was installed for you. Now it is only installed if needed. If you have any of these options set, you will need to install `sharp` and add it to your payload.config.ts:
```bash
pnpm i sharp
```
```diff
// payload.config.ts
import sharp from 'sharp'
buildConfig({
// ...
+ sharp,
})
```
## Breaking Changes
1. Delete the `admin.bundler` property from your Payload Config. Payload no longer bundles the Admin Panel. Instead, we rely directly on Next.js for bundling.
@@ -39,6 +148,23 @@ Payload is still headless, you will still be able to leverage it completely head
})
```
1. Environment variables prefixed with `PAYLOAD_PUBLIC` will no longer be available on the client. In order to access them on the client, those will now have to be prefixed with `NEXT_PUBLIC` instead.
```diff
'use client'
- const var = process.env.PAYLOAD_PUBLIC_MY_ENV_VAR
+ const var = process.env.NEXT_PUBLIC_MY_ENV_VAR
```
For more details, see the [Documentation](https://payloadcms.com/docs/configuration/environment-vars).
1. The `req` object used to extend the [Express Request](https://expressjs.com/), but now extends the [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). You may need to update your code accordingly to reflect this change. For example:
```diff
- req.headers['content-type']
+ req.headers.get('content-type')
```
1. The `admin.css` and `admin.scss` properties in the Payload Config have been removed.
```diff
@@ -133,6 +259,160 @@ Payload is still headless, you will still be able to leverage it completely head
}
```
1. Fields with `unique: true` now automatically be appended with “- Copy” through the new `admin.beforeDuplicate` field hooks (see previous bullet).
1. The `upload.staticDir` property must now be an absolute path. Before it would attempt to use the location of the Payload Config and merge the relative path set for staticDir.
```diff
// collections/Media.ts
import type { CollectionConfig } from 'payload'
import path from 'path'
+ import { fileURLToPath } from 'url'
+ const filename = fileURLToPath(import.meta.url)
+ const dirname = path.dirname(filename)
export const MediaCollection: CollectionConfig = {
slug: 'media',
upload: {
- staticDir: path.resolve(__dirname, './uploads'),
+ staticDir: path.resolve(dirname, '../uploads'),
},
}
```
1. The `upload.staticURL` property has been removed. If you were using this format URLs when using an external provider, you can leverage the `generateFileURL` functions in order to do the same.
```diff
// collections/Media.ts
import type { CollectionConfig } from 'payload'
export const MediaCollection: CollectionConfig = {
slug: 'media',
upload: {
- staticURL: '',
},
}
```
1. The `admin.favicon` property is now `admin.icons` and the types have changed:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
- favicon: 'path-to-favicon.svg',
+ icons: [{
+ path: 'path-to-favicon.svg',
+ sizes: '32x32'
+ }]
}
})
```
For more details, see the [Documentation](https://payloadcms.com/docs/admin/metadata#icons).
1. The `admin.meta.ogImage` property has been replaced by `admin.meta.openGraph.images`:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
meta: {
- ogImage: '',
+ openGraph: {
+ images: []
+ }
}
}
})
```
For more details, see the [Documentation](https://payloadcms.com/docs/admin/metadata#open-graph).
1. The args of the `admin.livePreview.url` function have changed. It no longer receives `documentInfo` as an arg, and instead, now has `collectionConfig` and `globalConfig`.
```diff
// payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
// ...
admin: {
// ...
livePreview: ({
- documentInfo,
+ collectionConfig,
+ globalConfig
}) => ''
}
})
```
1. The `admin.logoutRoute` and `admin.inactivityRoute` properties have been consolidated into a single `admin.routes` property. To migrate, simply move those two keys as follows:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
- logoutRoute: '/custom-logout',
+ inactivityRoute: '/custom-inactivity'
+ routes: {
+ logout: '/custom-logout',
+ inactivity: '/custom-inactivity'
+ }
}
})
```
1. The `custom` property in the Payload Config, i.e. Collections, Globals, and Fields is now **server only** and will **not** appear in the client-side bundle. To add custom properties to the client bundle, use the new `admin.custom` property, which will be available on _both_ the server and the client.
```diff
// payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
custom: {
someProperty: 'My Server Prop' // Now server only!
},
admin: {
+ custom: {
+ name: 'My Client Prop' // Available in server AND client
+ }
},
})
```
1. `hooks.afterError` is now an array of functions instead of a single function. The args have also been expanded. Read [More](https://payloadcms.com/docs/hooks/overview#root-hooks).
```diff
// payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
hooks: {
- afterError: async ({ error }) => {
+ afterError: [
+ async ({ error, req, res }) => {
+ // ...
+ }
+ ]
}
})
```
1. The `./src/public` directory is now located directly at root level `./public` [see nextJS docs for details](https://nextjs.org/docs/pages/building-your-application/optimizing/static-assets)
## Custom Components
1. All Payload React components have been moved from the `payload` package to `@payloadcms/ui`. If you were previously importing components into your app from the `payload` package, for example to create Custom Components, you will need to change your import paths:
```diff
@@ -141,13 +421,6 @@ Payload is still headless, you will still be able to leverage it completely head
```
*Note: for brevity, not _all_ modules are listed here*
1. The `BlockField` and related types have been renamed to `BlocksField` for semantic accuracy.
```diff
- import type { BlockField, BlockFieldProps } from 'payload'
+ import type { BlocksField, BlocksFieldProps } from 'payload'
```
1. All Custom Components are now defined as _file paths_ instead of direct imports. If you are using Custom Components in your Payload Config, remove the imported module and point to the file's path instead:
```diff
@@ -167,7 +440,7 @@ Payload is still headless, you will still be able to leverage it completely head
})
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/admin/components#component-paths).
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#component-paths).
1. All Custom Components are now server-rendered by default, and therefore, cannot use state or hooks directly. If youre using Custom Components in your app that requires state or hooks, add the `'use client'` directive at the top of the file.
@@ -187,102 +460,186 @@ Payload is still headless, you will still be able to leverage it completely head
}
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/admin/components#client-components).
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#client-components).
1. The `custom` property in the Payload Config, i.e. Collections, Globals, and Fields is now **server only** and will **not** appear in the client-side bundle. To add custom properties to the client bundle, use the new `admin.custom` property, which will be available on _both_ the server and the client.
1. The `admin.description` property within Collection, Globals, and Fields no longer accepts a React Component. Instead, you must define it as a Custom Component.
1. For Collections, use the `admin.components.edit.Description` key:
```diff
// payload.config.ts
// collections/Posts.ts
import type { CollectionConfig } from 'payload'
- import { MyCustomDescription } from '../components/MyCustomDescription'
export const PostsCollection: CollectionConfig = {
slug: 'posts',
admin: {
- description: MyCustomDescription,
+ components: {
+ edit: {
+ Description: 'path/to/MyCustomDescription'
+ }
+ }
}
}
```
2. For Globals, use the `admin.components.elements.Description` key:
```diff
// globals/Site.ts
import type { GlobalConfig } from 'payload'
- import { MyCustomDescription } from '../components/MyCustomDescription'
export const SiteGlobal: GlobalConfig = {
slug: 'site',
admin: {
- description: MyCustomDescription,
+ components: {
+ elements: {
+ Description: 'path/to/MyCustomDescription'
+ }
+ }
}
}
```
3. For Fields, use the `admin.components.Description` key:
```diff
// fields/MyField.ts
import type { FieldConfig } from 'payload'
- import { MyCustomDescription } from '../components/MyCustomDescription'
export const MyField: FieldConfig = {
type: 'text',
admin: {
- description: MyCustomDescription,
+ components: {
+ Description: 'path/to/MyCustomDescription'
+ }
}
}
```
1. Array Field row labels and Collapsible Field label now _only_ accepts a React Component, and no longer accepts a plain string or record:
```diff
// file: Collection.tsx
import type { CollectionConfig } from 'payload'
- import { MyCustomRowLabel } from './components/MyCustomRowLabel.tsx'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
fields: [
{
name: 'my-array',
type: 'array',
admin: {
components: {
- RowLabel: 'My Array Row Label,
+ RowLabel: './components/RowLabel.ts'
}
},
fields: [...]
},
{
name: 'my-collapsible',
type: 'collapsible',
admin: {
components: {
- Label: 'My Collapsible Label',
+ Label: './components/RowLabel.ts'
}
},
fields: [...]
}
]
}
```
1. All default view keys are now camelcase:
For example, for Root Views:
```diff
// file: payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
custom: {
someProperty: 'My Server Prop' // Now server only!
},
admin: {
+ custom: {
+ name: 'My Client Prop' // Available in server AND client
+ }
},
})
```
1. The `useTitle` hook has been consolidated into the `useDocumentInfo` hook. Instead, you can get title directly from document info context:
```diff
'use client'
- import { useTitle } from 'payload'
+ import { useDocumentInfo } from '@payloadcms/ui'
export const MyComponent = () => {
- const title = useTitle()
+ const { title } = useDocumentInfo()
// ...
}
```
1. The `Fields` type was renamed to `FormState` for improved semantics. If you were previously importing this type in your own application, simply change the import name:
```diff
- import type { Fields } from 'payload'
+ import type { FormState } from 'payload'
```
1. The `useDocumentInfo` hook no longer returns `collection` or `global`. Instead, various properties of the config are passed, like `collectionSlug` and `globalSlug`. You can use these to access a client-side config, if needed, through the `useConfig` hook (see next bullet).
```diff
'use client'
import { useDocumentInfo } from '@payloadcms/ui'
export const MyComponent = () => {
const {
- collection,
- global,
+ collectionSlug,
+ globalSlug
} = useDocumentInfo()
// ...
}
```
1. The `useConfig` hook now returns a `ClientConfig` and not a `SanitizedConfig`. This is because the config itself is not serializable and so it is not able to be thread through to the client. This means that all non-serializable props have been omitted from the Client Config, such as `db`, `bundler`, etc.
```diff
'use client'
- import { useConfig } from 'payload'
+ import { useConfig } from '@payloadcms/ui'
export const MyComponent = () => {
- const config = useConfig() // used to be a 'SanitizedConfig'
+ const { config } = useConfig() // now is a 'ClientConfig'
// ...
}
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/admin/components#accessing-the-payload-config).
1. The args of the `admin.livePreview.url` function have changed. It no longer receives `documentInfo` as an arg, and instead, now has `collectionConfig` and `globalConfig`.
```diff
// payload.config.ts
import { buildConfig } from 'payload'
export default buildConfig({
// ...
admin: {
// ...
livePreview: ({
- documentInfo,
+ collectionConfig,
+ globalConfig
}) => ''
admin: {
views: {
- Account: ...
+ account: ...
}
})
```
Or Document Views:
```diff
// file: Collection.tsx
import type { CollectionConfig } from 'payload'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
admin: {
views: {
- Edit: {
- Default: ...
- }
+ edit: {
+ default: ...
+ }
}
}
}
```
1. Custom Views within the config no longer accept React Components directly, instead, you must use their `Component` property:
```diff
// file: Collection.tsx
import type { CollectionConfig } from 'payload'
- import { MyCustomView } from './components/MyCustomView.tsx'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
admin: {
views: {
- Edit: MyCustomView
+ edit: {
+ Component: './components/MyCustomView.tsx'
+ }
}
}
}
```
This also means that Custom Root Views are no longer defined on the `edit` key. Instead, use the new `views.root` key:
```diff
// file: Collection.tsx
import type { CollectionConfig } from 'payload'
- import { MyCustomRootView } from './components/MyCustomRootView.tsx'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
admin: {
views: {
- Edit: MyCustomRootView
edit: {
+ root: {
+ Component: './components/MyCustomRootView.tsx'
+ }
}
}
}
}
```
1. The `href` and `isActive` functions on View Tabs no longer includes the `match` or `location` arguments. This is is a property specific to React Router, not Next.js. If you need to do URL matching similar to this, use a custom tab that fires of some hooks, i.e. `usePathname()` and run it through your own utility functions:
```diff
@@ -303,8 +660,8 @@ Payload is still headless, you will still be able to leverage it completely head
+ edit: {
+ tab: {
+ isActive: ({ href }) => true,
+ href: ({ href }) => ''
+ Component: './path/to/CustomComponent.tsx', // Or use a Custom Component
+ href: ({ href }) => '' // or use a Custom Component (see below)
+ // Component: './path/to/CustomComponent.tsx'
+ }
+ },
},
@@ -324,12 +681,12 @@ Payload is still headless, you will still be able to leverage it completely head
admin: {
components: {
- views: {
- edit: {
- Edit: {
- Tab: {
- pillLabel: 'Hello, world!',
- },
- },
+ Edit: {
+ edit: {
+ tab: {
+ Pill: './path/to/CustomPill.tsx',
+ }
@@ -340,106 +697,6 @@ Payload is still headless, you will still be able to leverage it completely head
}
```
1. Unique fields will now automatically be appended with “- Copy” through the new `admin.beforeDuplicate` field hooks (detailed aboved).
1. The `useCollapsible` hook has had slight changes to its property names. `collapsed` is now `isCollapsed` and `withinCollapsible` is now `isWithinCollapsible`.
```diff
'use client'
import { useCollapsible } from '@payloadcms/ui'
export const MyComponent = () => {
- const { collapsed, withinCollapsible } = useCollapsible()
+ const { isCollapsed, isWithinCollapsible } = useCollapsible()
}
```
1. The `admin.favicon` property is now `admin.icons` and the types have changed:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
- favicon: 'path-to-favicon.svg',
+ icons: [{
+ path: 'path-to-favicon.svg',
+ sizes: '32x32'
+ }]
}
})
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/admin/metadata#icons).
1. The `admin.meta.ogImage` property has been replaced by `admin.meta.openGraph.images`:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
meta: {
- ogImage: '',
+ openGraph: {
+ images: []
+ }
}
}
})
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/admin/metadata#open-graph).
1. The `admin.logoutRoute` and `admin.inactivityRoute` properties have been consolidated into a single `admin.routes` property. To migrate, simply move those two keys as follows:
```diff
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
// ...
admin: {
- logoutRoute: '/custom-logout',
+ inactivityRoute: '/custom-inactivity'
+ routes: {
+ logout: '/custom-logout',
+ inactivity: '/custom-inactivity'
+ }
}
})
```
1. Environment variables prefixed with `PAYLOAD_PUBLIC` will no longer be available on the client. In order to access them on the client, those will now have to be prefixed with `NEXT_PUBLIC` instead.
```diff
'use client'
- const var = process.env.PAYLOAD_PUBLIC_MY_ENV_VAR
+ const var = process.env.NEXT_PUBLIC_MY_ENV_VAR
```
For more details, see the [Documentation](https://payloadcms.com/docs/beta/configuration/environment-vars).
1. The `useTranslation` hook no longer takes any options, any translations using shorthand accessors will need to use the entire `group:key`
```diff
'use client'
- import { useTranslation } from 'payload'
+ import { useTranslation } from '@payloadcms/ui'
export const MyComponent = () => {
- const { i18n, t } = useTranslation('general')
+ const { i18n, t } = useTranslation()
- return <p>{t('cancel')}</p>
+ return <p>{t('general:cancel')}</p>
}
```
1. `react-i18n` was removed, the `Trans` component from `react-i18n` has been replaced with a Payload-provided solution:
```diff
@@ -467,7 +724,9 @@ Payload is still headless, you will still be able to leverage it completely head
}
```
1. All other endpoint handlers have changed. The args no longer include `res`, and `next`, and the return type now expects a valid HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) instead of `res.json`, `res.send`, etc.:
## Endpoints
1. All endpoint handlers have changed. The args no longer include `res`, and `next`, and the return type now expects a valid HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) instead of `res.json`, `res.send`, etc.:
```diff
// collections/Posts.ts
@@ -542,47 +801,102 @@ Payload is still headless, you will still be able to leverage it completely head
}
```
1. The `req` object used to extend the [Express Request](https://expressjs.com/), but now extends the [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). You may need to update your code accordingly to reflect this change. For example:
## React Hooks
1. The `useTitle` hook has been consolidated into the `useDocumentInfo` hook. Instead, you can get title directly from document info context:
```diff
- req.headers['content-type']
+ req.headers.get('content-type')
```
'use client'
- import { useTitle } from 'payload'
+ import { useDocumentInfo } from '@payloadcms/ui'
1. `staticDir` must now be an absolute path. Before it would attempt to use the location of the Payload Config and merge the relative path set for staticDir.
export const MyComponent = () => {
- const title = useTitle()
+ const { title } = useDocumentInfo()
```diff
// collections/Media.ts
import type { CollectionConfig } from 'payload'
import path from 'path'
+ import { fileURLToPath } from 'url'
+ const filename = fileURLToPath(import.meta.url)
+ const dirname = path.dirname(filename)
export const MediaCollection: CollectionConfig = {
slug: 'media',
upload: {
- staticDir: path.resolve(__dirname, './uploads'),
+ staticDir: path.resolve(dirname, '../uploads'),
},
// ...
}
```
1. `staticURL` has been removed. If you were using this format URLs when using an external provider, you can leverage the `generateFileURL` functions in order to do the same.
1. The `useDocumentInfo` hook no longer returns `collection` or `global`. Instead, various properties of the config are passed, like `collectionSlug` and `globalSlug`. You can use these to access a client-side config, if needed, through the `useConfig` hook (see next bullet).
```diff
// collections/Media.ts
import type { CollectionConfig } from 'payload'
'use client'
import { useDocumentInfo } from '@payloadcms/ui'
export const MediaCollection: CollectionConfig = {
slug: 'media',
upload: {
- staticURL: '',
},
export const MyComponent = () => {
const {
- collection,
- global,
+ collectionSlug,
+ globalSlug
} = useDocumentInfo()
// ...
}
```
1. The `useConfig` hook now returns a `ClientConfig` and not a `SanitizedConfig`. This is because the config itself is not serializable and so it is not able to be thread through to the client. This means that all non-serializable props have been omitted from the Client Config, such as `db`, `bundler`, etc.
```diff
'use client'
- import { useConfig } from 'payload'
+ import { useConfig } from '@payloadcms/ui'
export const MyComponent = () => {
- const config = useConfig() // used to be a 'SanitizedConfig'
+ const { config } = useConfig() // now is a 'ClientConfig'
// ...
}
```
For more details, see the [Documentation](https://payloadcms.com/docs/admin/components#accessing-the-payload-config).
1. The `useCollapsible` hook has had slight changes to its property names. `collapsed` is now `isCollapsed` and `withinCollapsible` is now `isWithinCollapsible`.
```diff
'use client'
import { useCollapsible } from '@payloadcms/ui'
export const MyComponent = () => {
- const { collapsed, withinCollapsible } = useCollapsible()
+ const { isCollapsed, isWithinCollapsible } = useCollapsible()
}
```
1. The `useTranslation` hook no longer takes any options, any translations using shorthand accessors will need to use the entire `group:key`
```diff
'use client'
- import { useTranslation } from 'payload'
+ import { useTranslation } from '@payloadcms/ui'
export const MyComponent = () => {
- const { i18n, t } = useTranslation('general')
+ const { i18n, t } = useTranslation()
- return <p>{t('cancel')}</p>
+ return <p>{t('general:cancel')}</p>
}
```
## Types
1. The `Fields` type was renamed to `FormState` for improved semantics. If you were previously importing this type in your own application, simply change the import name:
```diff
- import type { Fields } from 'payload'
+ import type { FormState } from 'payload'
```
1. The `BlockField` and related types have been renamed to `BlocksField` for semantic accuracy.
```diff
- import type { BlockField, BlockFieldProps } from 'payload'
+ import type { BlocksField, BlocksFieldProps } from 'payload'
```
## Email Adapters
Email functionality has been abstracted out into email adapters.
@@ -647,7 +961,7 @@ export default buildConfig({
- Now only available if using custom server and using express or similar
# Plugins
## Plugins
1. *All* plugins have been standardized to use _named exports_ (as opposed to default exports). Most also have a suffix of `Plugin` to make it clear what is being imported.
@@ -670,10 +984,10 @@ export default buildConfig({
| Service | Package |
| -------------------- | ---------------------------------------------------------------------------- |
| Vercel Blob | https://github.com/payloadcms/payload/tree/beta/packages/storage-vercel-blob |
| AWS S3 | https://github.com/payloadcms/payload/tree/beta/packages/storage-s3 |
| Azure | https://github.com/payloadcms/payload/tree/beta/packages/storage-azure |
| Google Cloud Storage | https://github.com/payloadcms/payload/tree/beta/packages/storage-gcs |
| Vercel Blob | https://github.com/payloadcms/payload/tree/main/packages/storage-vercel-blob |
| AWS S3 | https://github.com/payloadcms/payload/tree/main/packages/storage-s3 |
| Azure | https://github.com/payloadcms/payload/tree/main/packages/storage-azure |
| Google Cloud Storage | https://github.com/payloadcms/payload/tree/main/packages/storage-gcs |
```tsx
// ❌ Before (required peer dependencies depending on adapter)
@@ -785,4 +1099,4 @@ plugins: [
## `@payloadcms/richtext-lexical`
// TODO: Add migration guide for `@payloadcms/richtext-lexical`
If you have custom features for `@payloadcms/richtext-lexical` you will need to migrate your code to the new API. Read more about the new API in the [documentation](https://payloadcms.com/docs/lexical/building-custom-features).

View File

@@ -36,7 +36,7 @@ Forms can be as simple or complex as you need, from a basic contact form, to a m
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-form-builder@beta
pnpm add @payloadcms/plugin-form-builder
```
## Basic Usage
@@ -103,7 +103,7 @@ formBuilder({
### `beforeEmail`
The `beforeEmail` property is a [beforeChange](<[beforeChange](https://payloadcms.com/docs/hooks/globals#beforechange)>) hook that is called just after emails are prepared, but before they are sent. This is a great place to inject your own HTML template to add custom styles.
The `beforeEmail` property is a [beforeChange](https://payloadcms.com/docs/hooks/globals#beforechange) hook that is called just after emails are prepared, but before they are sent. This is a great place to inject your own HTML template to add custom styles.
```ts
// payload.config.ts
@@ -215,7 +215,7 @@ formBuilder({
### `handlePayment`
The `handlePayment` property is a [beforeChange](<[beforeChange](https://payloadcms.com/docs/hooks/globals#beforechange)>) hook that is called upon form submission. You can integrate into any third-party payment processing API here to accept payment based on form input. You can use the `getPaymentTotal` function to calculate the total cost after all conditions have been applied. This is only applicable if the form has enabled the `payment` field.
The `handlePayment` property is a [beforeChange](https://payloadcms.com/docs/hooks/globals#beforechange) hook that is called upon form submission. You can integrate into any third-party payment processing API here to accept payment based on form input. You can use the `getPaymentTotal` function to calculate the total cost after all conditions have been applied. This is only applicable if the form has enabled the `payment` field.
First import the utility function. This will execute all of the price conditions that you have set in your form's `payment` field and returns the total price.

View File

@@ -48,7 +48,7 @@ Install the plugin using any JavaScript package manager like [Yarn](https://yarn
or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-nested-docs@beta
pnpm add @payloadcms/plugin-nested-docs
```
## Basic Usage
@@ -102,8 +102,8 @@ level and stores the following fields.
| Field | Description |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label` | The label of the breadcrumb. This field is automatically set to either the `collection.admin.useAsTitle` (if defined) or is set to the `ID` of the document. You can also dynamically define the `label` by passing a function to the options property of [`generateLabel`](#generateLabel). |
| `url` | The URL of the breadcrumb. By default, this field is undefined. You can manually define this field by passing a property called function to the plugin options property of [`generateURL`](#generateURL). |
| `label` | The label of the breadcrumb. This field is automatically set to either the `collection.admin.useAsTitle` (if defined) or is set to the `ID` of the document. You can also dynamically define the `label` by passing a function to the options property of [`generateLabel`](#generatelabel). |
| `url` | The URL of the breadcrumb. By default, this field is undefined. You can manually define this field by passing a property called function to the plugin options property of [`generateURL`](#generateurl). |
### Options
@@ -226,7 +226,7 @@ const examplePageConfig: CollectionConfig = {
This plugin supports localization by default. If the `localization` property is set in your Payload Config,
the `breadcrumbs` field is automatically localized. For more details on how localization works in Payload, see
the [Localization](https://payloadcms.com/docs/localization/overview) docs.
the [Localization](https://payloadcms.com/docs/configuration/localization) docs.
## TypeScript
@@ -238,10 +238,4 @@ import { PluginConfig, GenerateURL, GenerateLabel } from '@payloadcms/plugin-nes
## Examples
The [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) contains an
official [Nested Docs Plugin Example](https://github.com/payloadcms/payload/tree/main/examples/nested-docs) which
demonstrates exactly how to configure this plugin in Payload and implement it on your front-end.
The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates) also contains an
official [Website Template](https://github.com/payloadcms/payload/tree/main/templates/website)
and [E-commerce Template](https://github.com/payloadcms/payload/tree/main/templates/ecommerce), both of which use this
plugin.
The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates) also contains an official [Website Template](https://github.com/payloadcms/payload/tree/main/templates/website) and [E-commerce Template](https://github.com/payloadcms/payload/tree/main/templates/ecommerce), both of which use this plugin.

View File

@@ -8,7 +8,7 @@ keywords: plugins, config, configuration, extensions, custom, documentation, Con
Payload Plugins take full advantage of the modularity of the [Payload Config](../configuration/overview), allowing developers developers to easily inject custom—sometimes complex—functionality into Payload apps from a very small touch-point. This is especially useful is sharing your work across multiple projects or with the greater Payload community.
There are many [Official Plugins](#official-plugins) available that solve for some of the most common uses cases, such as the [Form Builder Plugin](./seo) or [SEO Plugin](./seo). There are also [Community Plugins](#community-plugins) available, maintained entirely by contributing members. To extend Payload's functionality in some other way, you can easily [build your own plugin](./build-your-own).
There are many [Official Plugins](#official-plugins) available that solve for some of the most common uses cases, such as the [Form Builder Plugin](./form-builder) or [SEO Plugin](./seo). There are also [Community Plugins](#community-plugins) available, maintained entirely by contributing members. To extend Payload's functionality in some other way, you can easily [build your own plugin](./build-your-own).
To configure Plugins, use the `plugins` property in your [Payload Config](../configuration/overview):
@@ -68,7 +68,7 @@ Plugins are changing every day, so be sure to check back often to see what new p
Community Plugins are those that are maintained entirely by outside contributors. They are a great way to share your work across the ecosystem for others to use. You can discover Community Plugins by browsing the `payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin).
Some plugins have become so widely used that they are adopted as an [Official Plugin](#official-plugin), such as the [Lexical Plugin](https://github.com/AlessioGr/payload-plugin-lexical). If you have a plugin that you think should be an Official Plugin, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
Some plugins have become so widely used that they are adopted as an [Official Plugin](#official-plugins), such as the [Lexical Plugin](https://github.com/AlessioGr/payload-plugin-lexical). If you have a plugin that you think should be an Official Plugin, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
<Banner type="warning">
For maintainers building plugins for others to use, please add the `payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin) to help others find it.

View File

@@ -32,7 +32,7 @@ For example, if you have a page at `/about` and you want to change it to `/about
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-redirects@beta
pnpm add @payloadcms/plugin-redirects
```
## Basic Usage
@@ -102,4 +102,4 @@ import { PluginConfig } from '@payloadcms/plugin-redirects/types'
## Examples
The [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) contains an official [Redirects Plugin Example](https://github.com/payloadcms/payload/tree/main/examples/redirects) which demonstrates exactly how to configure this plugin in Payload and implement it on your front-end. The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates) also contains an official [Website Template](https://github.com/payloadcms/payload/tree/main/templates/website) and [E-commerce Template](https://github.com/payloadcms/payload/tree/main/templates/ecommere), both of which use this plugin.
The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates) also contains an official [Website Template](https://github.com/payloadcms/payload/tree/main/templates/website) and [E-commerce Template](https://github.com/payloadcms/payload/tree/main/templates/ecommerce), both of which use this plugin.

View File

@@ -39,7 +39,7 @@ This plugin is a great way to implement a fast, immersive search experience such
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-search@beta
pnpm add @payloadcms/plugin-search
```
## Basic Usage
@@ -134,7 +134,7 @@ Note that the `fields` property is a function that receives an object with a `de
#### `beforeSync`
Before creating or updating a search record, the `beforeSync` function runs. This is an [afterChange](<[afterChange](https://payloadcms.com/docs/hooks/globals#afterchange)>) hook that allows you to modify the data or provide fallbacks before its search record is created or updated.
Before creating or updating a search record, the `beforeSync` function runs. This is an [afterChange](https://payloadcms.com/docs/hooks/globals#afterchange) hook that allows you to modify the data or provide fallbacks before its search record is created or updated.
```ts
// payload.config.ts

View File

@@ -31,7 +31,7 @@ This multi-faceted software offers a range of features that will help you manage
- **Integrations**: Connects with various tools and services for enhanced workflow and issue management
<Banner type="info">
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/beta/packages/plugin-sentry). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-sentry%3A) with as much detail as possible.
This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-sentry). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-sentry%3A) with as much detail as possible.
</Banner>
## Installation
@@ -39,7 +39,7 @@ This multi-faceted software offers a range of features that will help you manage
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-sentry@beta
pnpm add @payloadcms/plugin-sentry
```
## Sentry for Next.js setup

View File

@@ -37,7 +37,7 @@ To help you visualize what your page might look like in a search engine, a previ
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-seo@beta
pnpm add @payloadcms/plugin-seo
```
## Basic Usage
@@ -171,7 +171,7 @@ A function that allows you to return any meta description, including from docume
}
```
For a full list of arguments, see the [`generateTitle`](#generateTitle) function.
For a full list of arguments, see the [`generateTitle`](#generatetitle) function.
##### `generateImage`
@@ -187,7 +187,7 @@ A function that allows you to return any meta image, including from document's c
}
```
For a full list of arguments, see the [`generateTitle`](#generateTitle) function.
For a full list of arguments, see the [`generateTitle`](#generatetitle) function.
##### `generateURL`
@@ -204,7 +204,7 @@ A function called by the search preview component to display the actual URL of y
}
```
For a full list of arguments, see the [`generateTitle`](#generateTitle) function.
For a full list of arguments, see the [`generateTitle`](#generatetitle) function.
#### `interfaceName`

View File

@@ -8,7 +8,7 @@ keywords: plugins, stripe, payments, ecommerce
[![NPM](https://img.shields.io/npm/v/@payloadcms/plugin-stripe)](https://www.npmjs.com/package/@payloadcms/plugin-stripe)
With this plugin you can easily integrate [Stripe](https://stripe.com) into Payload. Simply provide your Stripe credentials and this plugin will open up a two-way communication channel between the two platforms. This enables you to easily sync data back and forth, as well as proxy the Stripe REST API through Payload's [Access Control](../access-control). Use this plugin to completely offload billing to Stripe and retain full control over your application's data.
With this plugin you can easily integrate [Stripe](https://stripe.com) into Payload. Simply provide your Stripe credentials and this plugin will open up a two-way communication channel between the two platforms. This enables you to easily sync data back and forth, as well as proxy the Stripe REST API through Payload's [Access Control](../access-control/overview). Use this plugin to completely offload billing to Stripe and retain full control over your application's data.
For example, you might be building an e-commerce or SaaS application, where you have a `products` or a `plans` collection that requires either a one-time payment or a subscription. You can to tie each of these products to Stripe, then easily subscribe to billing-related events to perform your application's business logic, such as active purchases or subscription cancellations.
@@ -39,7 +39,7 @@ The beauty of this plugin is the entirety of your application's content and busi
Install the plugin using any JavaScript package manager like [Yarn](https://yarnpkg.com), [NPM](https://npmjs.com), or [PNPM](https://pnpm.io):
```bash
pnpm add @payloadcms/plugin-stripe@beta
pnpm add @payloadcms/plugin-stripe
```
## Basic Usage

View File

@@ -147,11 +147,11 @@ But, if you do, and you still want to use an ephemeral filesystem provider, you
Payload provides a list of official cloud storage adapters for you to use:
- [Azure Blob Storage](https://github.com/payloadcms/payload/tree/beta/packages/storage-azure)
- [Google Cloud Storage](https://github.com/payloadcms/payload/tree/beta/packages/storage-gcs)
- [AWS S3](https://github.com/payloadcms/payload/tree/beta/packages/storage-s3)
- [Uploadthing](https://github.com/payloadcms/payload/tree/beta/packages/storage-uploadthing)
- [Vercel Blob Storage](https://github.com/payloadcms/payload/tree/beta/packages/storage-vercel-blob)
- [Azure Blob Storage](https://github.com/payloadcms/payload/tree/main/packages/storage-azure)
- [Google Cloud Storage](https://github.com/payloadcms/payload/tree/main/packages/storage-gcs)
- [AWS S3](https://github.com/payloadcms/payload/tree/main/packages/storage-s3)
- [Uploadthing](https://github.com/payloadcms/payload/tree/main/packages/storage-uploadthing)
- [Vercel Blob Storage](https://github.com/payloadcms/payload/tree/main/packages/storage-vercel-blob)
Follow the docs to configure any one of these storage providers. For local development, it might be handy to simply store uploads on your own computer, and then when it comes to production, simply enable the plugin for the cloud storage vendor of your choice.

View File

@@ -107,9 +107,9 @@ const getPosts = async () => {
The `defaultPopulate` property allows you specify which fields to select when populating the collection from another document.
This is especially useful for links where only the `slug` is needed instead of the entire document.
With this feature, you can dramatically reduce the amount of JSON that is populated from [Relationship](/docs/beta/fields/relationship) or [Upload](/docs/beta/fields/upload) fields.
With this feature, you can dramatically reduce the amount of JSON that is populated from [Relationship](/docs/fields/relationship) or [Upload](/docs/fields/upload) fields.
For example, in your content model, you might have a `Link` field which links out to a different page. When you go to retrieve these links, you really only need the `slug` of the page.
For example, in your content model, you might have a `Link` field which links out to a different page. When you go to retrieve these links, you really only need the `slug` of the page.
Loading all of the page content, its related links, and everything else is going to be overkill and will bog down your Payload APIs. Instead, you can define the `defaultPopulate` property on your `Pages` collection, so that when Payload "populates" a related Page, it only selects the `slug` field and therefore returns significantly less JSON:

View File

@@ -501,7 +501,7 @@ Globals cannot be created or deleted, so there are only two REST endpoints opene
## Preferences
In addition to the dynamically generated endpoints above Payload also has REST endpoints to manage the admin user [preferences](/docs/admin/overview#preferences) for data specific to the authenticated user.
In addition to the dynamically generated endpoints above Payload also has REST endpoints to manage the admin user [preferences](/docs/admin/preferences) for data specific to the authenticated user.
<RestExamples
data={[

View File

@@ -9,7 +9,7 @@ keywords: slatejs, lexical, rich text, json, custom editor, javascript, typescri
Payload currently supports two official rich text editors and you can choose either one depending on your needs.
1. [SlateJS](/docs/rich-text/slate) - stable, backwards-compatible with 1.0
2. [Lexical](/docs/lexical/overview) - beta, where things will be moving in the future
2. [Lexical](/docs/lexical/overview) - recommended
These editors are built on an "adapter pattern" which means that you will need to install the editor you'd like to use. Take a look at the docs for the editor you'd like to use for instructions on how to install it.

View File

@@ -9,23 +9,23 @@ keywords: uploads, images, media, storage, adapters, s3, vercel, google cloud, a
Payload offers additional storage adapters to handle file uploads. These adapters allow you to store files in different locations, such as Amazon S3, Vercel Blob Storage, Google Cloud Storage, and more.
| Service | Package |
| -------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Vercel Blob | [`@payloadcms/storage-vercel-blob`](https://github.com/payloadcms/payload/tree/beta/packages/storage-vercel-blob) |
| AWS S3 | [`@payloadcms/storage-s3`](https://github.com/payloadcms/payload/tree/beta/packages/storage-s3) |
| Azure | [`@payloadcms/storage-azure`](https://github.com/payloadcms/payload/tree/beta/packages/storage-azure) |
| Google Cloud Storage | [`@payloadcms/storage-gcs`](https://github.com/payloadcms/payload/tree/beta/packages/storage-gcs) |
| Uploadthing | [`@payloadcms/storage-uploadthing`](https://github.com/payloadcms/payload/tree/beta/packages/uploadthing) |
| -------------------- |-------------------------------------------------------------------------------------------------------------------|
| Vercel Blob | [`@payloadcms/storage-vercel-blob`](https://github.com/payloadcms/payload/tree/main/packages/storage-vercel-blob) |
| AWS S3 | [`@payloadcms/storage-s3`](https://github.com/payloadcms/payload/tree/main/packages/storage-s3) |
| Azure | [`@payloadcms/storage-azure`](https://github.com/payloadcms/payload/tree/main/packages/storage-azure) |
| Google Cloud Storage | [`@payloadcms/storage-gcs`](https://github.com/payloadcms/payload/tree/main/packages/storage-gcs) |
| Uploadthing | [`@payloadcms/storage-uploadthing`](https://github.com/payloadcms/payload/tree/main/packages/storage-uploadthing) |
## Vercel Blob Storage
[`@payloadcms/storage-vercel-blob`](https://www.npmjs.com/package/@payloadcms/storage-vercel-blob)
### Installation
### Installation#vercel-blob-installation
```sh
pnpm add @payloadcms/storage-vercel-blob@beta
pnpm add @payloadcms/storage-vercel-blob
```
### Usage
### Usage#vercel-blob-usage
- Configure the `collections` object to specify which collections should use the Vercel Blob adapter. The slug _must_ match one of your existing collection slugs.
- Ensure you have `BLOB_READ_WRITE_TOKEN` set in your Vercel environment variables. This is usually set by Vercel automatically after adding blob storage to your project.
@@ -55,7 +55,7 @@ export default buildConfig({
})
```
### Configuration Options
### Configuration Options#vercel-blob-configuration
| Option | Description | Default |
| -------------------- | -------------------------------------------------------------------- | ----------------------------- |
@@ -68,13 +68,13 @@ export default buildConfig({
## S3 Storage
[`@payloadcms/storage-s3`](https://www.npmjs.com/package/@payloadcms/storage-s3)
### Installation
### Installation#s3-installation
```sh
pnpm add @payloadcms/storage-s3@beta
pnpm add @payloadcms/storage-s3
```
### Usage
### Usage#s3-usage
- Configure the `collections` object to specify which collections should use the S3 Storage adapter. The slug _must_ match one of your existing collection slugs.
- The `config` object can be any [`S3ClientConfig`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3) object (from [`@aws-sdk/client-s3`](https://github.com/aws/aws-sdk-js-v3)). _This is highly dependent on your AWS setup_. Check the AWS documentation for more information.
@@ -109,20 +109,20 @@ export default buildConfig({
})
```
#### Configuration Options
### Configuration Options#s3-configuration
See the the [AWS SDK Package](https://github.com/aws/aws-sdk-js-v3) and [`S3ClientConfig`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3) object for guidance on AWS S3 configuration.
## Azure Blob Storage
[`@payloadcms/storage-azure`](https://www.npmjs.com/package/@payloadcms/storage-azure)
### Installation
### Installation#azure-installation
```sh
pnpm add @payloadcms/storage-azure@beta
pnpm add @payloadcms/storage-azure
```
### Usage
### Usage#azure-usage
- Configure the `collections` object to specify which collections should use the Azure Blob adapter. The slug _must_ match one of your existing collection slugs.
- When enabled, this package will automatically set `disableLocalStorage` to `true` for each collection.
@@ -151,7 +151,7 @@ export default buildConfig({
})
```
### Configuration Options
### Configuration Options#azure-configuration
| Option | Description | Default |
| ---------------------- | ------------------------------------------------------------------------ | ------- |
@@ -165,13 +165,13 @@ export default buildConfig({
## Google Cloud Storage
[`@payloadcms/storage-gcs`](https://www.npmjs.com/package/@payloadcms/storage-gcs)
### Installation
### Installation#gcs-installation
```sh
pnpm add @payloadcms/storage-gcs@beta
pnpm add @payloadcms/storage-gcs
```
### Usage
### Usage#gcs-usage
- Configure the `collections` object to specify which collections should use the Google Cloud Storage adapter. The slug _must_ match one of your existing collection slugs.
- When enabled, this package will automatically set `disableLocalStorage` to `true` for each collection.
@@ -201,7 +201,7 @@ export default buildConfig({
})
```
### Configuration Options
### Configuration Options#gcs-configuration
| Option | Description | Default |
| ------------- | --------------------------------------------------------------------------------------------------- | --------- |
@@ -215,13 +215,13 @@ export default buildConfig({
## Uploadthing Storage
[`@payloadcms/storage-uploadthing`](https://www.npmjs.com/package/@payloadcms/storage-uploadthing)
### Installation
### Installation#uploadthing-installation
```sh
pnpm add @payloadcms/storage-uploadthing@beta
pnpm add @payloadcms/storage-uploadthing
```
### Usage
### Usage#uploadthing-usage
- Configure the `collections` object to specify which collections should use uploadthing. The slug _must_ match one of your existing collection slugs and be an `upload` type.
- Get a token from Uploadthing and set it as `token` in the `options` object.
@@ -244,7 +244,7 @@ export default buildConfig({
})
```
### Configuration Options
### Configuration Options#uploadthing-configuration
| Option | Description | Default |
| ---------------- | ----------------------------------------------- | ------------- |
@@ -259,11 +259,11 @@ export default buildConfig({
If you need to create a custom storage adapter, you can use the [`@payloadcms/plugin-cloud-storage`](https://www.npmjs.com/package/@payloadcms/plugin-cloud-storage) package. This package is used internally by the storage adapters mentioned above.
### Installation
### Installation#custom-installation
`pnpm add @payloadcms/plugin-cloud-storage@beta`
`pnpm add @payloadcms/plugin-cloud-storage`
### Usage
### Usage#custom-usage
Reference any of the existing storage adapters for guidance on how this should be structured. Create an adapter following the `GeneratedAdapter` interface. Then, pass the adapter to the `cloudStorage` plugin.

View File

@@ -28,7 +28,7 @@ export const rootParserOptions = {
ecmaVersion: 'latest',
projectService: {
maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING: 40,
allowDefaultProject: ['scripts/*.ts', '*.js', '*.mjs', '*.spec.ts', '*.d.ts'],
allowDefaultProject: ['scripts/*.ts', '*.js', '*.mjs', '*.d.ts'],
},
}

View File

@@ -1,27 +1,26 @@
import React from 'react'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import { Gutter } from '../Gutter'
import { HeaderNav } from './Nav'
import classes from './index.module.scss'
import { HeaderNav } from './Nav'
export function Header() {
return (
<header className={classes.header}>
<Gutter className={classes.wrap}>
<Link href="/" className={classes.logo}>
<Link className={classes.logo} href="/">
<picture>
<source
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-light.svg"
media="(prefers-color-scheme: dark)"
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-light.svg"
/>
<Image
width={150}
height={30}
alt="Payload Logo"
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-dark.svg"
height={30}
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-dark.svg"
width={150}
/>
</picture>
</Link>

View File

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"target": "ES2022",
"lib": [
"DOM",
"DOM.Iterable",
"ES2022"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,

View File

@@ -1,27 +1,26 @@
import React from 'react'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import { Gutter } from '../Gutter'
import { HeaderNav } from './Nav'
import classes from './index.module.scss'
import { HeaderNav } from './Nav'
export const Header: React.FC = () => {
return (
<header className={classes.header}>
<Gutter className={classes.wrap}>
<Link href="/" className={classes.logo}>
<Link className={classes.logo} href="/">
<picture>
<source
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-light.svg"
media="(prefers-color-scheme: dark)"
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-light.svg"
/>
<Image
width={150}
height={30}
alt="Payload Logo"
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-dark.svg"
height={30}
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-dark.svg"
width={150}
/>
</picture>
</Link>

View File

@@ -1,10 +1,10 @@
{
"compilerOptions": {
"target": "es5",
"target": "ES2022",
"lib": [
"dom",
"dom.iterable",
"esnext"
"DOM",
"DOM.Iterable",
"ES2022"
],
"allowJs": true,
"skipLibCheck": true,

View File

@@ -48,12 +48,12 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
```ts
import { headers as getHeaders } from 'next/headers.js'
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { getPayload } from 'payload'
import config from '../../payload.config'
export default async function AccountPage({ searchParams }) {
const headers = getHeaders()
const payload = await getPayloadHMR({ config: configPromise })
const payload = await getPayload({ config: configPromise })
const { permissions, user } = await payload.auth({ headers })
if (!user) {

View File

@@ -3,8 +3,8 @@ import Link from 'next/link'
import React from 'react'
import { Gutter } from '../Gutter'
import { HeaderNav } from './Nav'
import classes from './index.module.scss'
import { HeaderNav } from './Nav'
export function Header() {
return (
@@ -14,12 +14,12 @@ export function Header() {
<picture>
<source
media="(prefers-color-scheme: dark)"
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-light.svg"
srcSet="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-light.svg"
/>
<Image
alt="Payload Logo"
height={30}
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/payload-logo-dark.svg"
src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/ui/src/assets/payload-logo-dark.svg"
width={150}
/>
</picture>

View File

@@ -1,7 +1,7 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import Link from 'next/link'
import { redirect } from 'next/navigation'
import { getPayload } from 'payload'
import React, { Fragment } from 'react'
import config from '../../../payload.config'
@@ -14,7 +14,7 @@ import classes from './index.module.scss'
export default async function Account() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { permissions, user } = await payload.auth({ headers })
if (!user) {

View File

@@ -1,6 +1,6 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import { redirect } from 'next/navigation'
import { getPayload } from 'payload'
import React from 'react'
import config from '../../../payload.config'
@@ -11,7 +11,7 @@ import classes from './index.module.scss'
export default async function CreateAccount() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers })
if (user) {

View File

@@ -1,17 +1,17 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import { redirect } from 'next/navigation'
import { getPayload } from 'payload'
import React from 'react'
import config from '../../../payload.config'
import { Gutter } from '../_components/Gutter'
import { RenderParams } from '../_components/RenderParams'
import { LoginForm } from './LoginForm'
import classes from './index.module.scss'
import { LoginForm } from './LoginForm'
export default async function Login() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers })
if (user) {

View File

@@ -1,16 +1,16 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import Link from 'next/link'
import { getPayload } from 'payload'
import React from 'react'
import config from '../../../payload.config'
import { Gutter } from '../_components/Gutter'
import { LogoutPage } from './LogoutPage'
import classes from './index.module.scss'
import { LogoutPage } from './LogoutPage'
export default async function Logout() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers })
if (!user) {

View File

@@ -1,6 +1,6 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import Link from 'next/link'
import { getPayload } from 'payload'
import React, { Fragment } from 'react'
import config from '../../payload.config'
@@ -9,7 +9,7 @@ import { HydrateClientUser } from './_components/HydrateClientUser'
export default async function HomePage() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { permissions, user } = await payload.auth({ headers })
return (

View File

@@ -1,16 +1,16 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import { redirect } from 'next/navigation'
import { getPayload } from 'payload'
import React from 'react'
import config from '../../../payload.config'
import { Gutter } from '../_components/Gutter'
import { RecoverPasswordForm } from './RecoverPasswordForm'
import classes from './index.module.scss'
import { RecoverPasswordForm } from './RecoverPasswordForm'
export default async function RecoverPassword() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers })
if (user) {

View File

@@ -1,16 +1,16 @@
import { getPayloadHMR } from '@payloadcms/next/utilities'
import { headers as getHeaders } from 'next/headers.js'
import { redirect } from 'next/navigation'
import { getPayload } from 'payload'
import React from 'react'
import config from '../../../payload.config'
import { Gutter } from '../_components/Gutter'
import { ResetPasswordForm } from './ResetPasswordForm'
import classes from './index.module.scss'
import { ResetPasswordForm } from './ResetPasswordForm'
export default async function ResetPassword() {
const headers = getHeaders()
const payload = await getPayloadHMR({ config })
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers })
if (user) {

View File

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"DOM",
"DOM.Iterable",
"ES2022"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,

View File

@@ -1,46 +1,67 @@
# Payload Custom Components Example
This example demonstrates how to use Custom Components in [Payload](https://github.com/payloadcms/payload) Admin Panel. This example includes custom components for every field type available in Payload, including both server and client components. It also includes custom views, custom nav links, and more.
This example demonstrates how to use Custom Components in the [Payload](https://github.com/payloadcms/payload) Admin Panel. Custom components allow you to extend Payload by providing custom UI elements for fields, collections, and views. This example covers custom components for every field type available in Payload, including both server and client components.
## Quick Start
To spin up this example locally, follow these steps:
To spin up this example locally, follow the steps below:
1. Clone this repo
1. `cd` into this directory and run `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
1. Navigate into the project directory and install dependencies using your preferred package manager:
> \*If you are running using pnpm within the Payload Monorepo, the `--ignore-workspace` flag is needed so that pnpm generates a lockfile in this example's directory despite the fact that one exists in root.
- `pnpm i --ignore-workspace`\*, `yarn`, or `npm install`
1. `pnpm dev`, `yarn dev` or `npm run dev` to start the server
- Press `y` when prompted to seed the database
1. `open http://localhost:3000` to access the home page
1. `open http://localhost:3000/admin` to access the admin panel
- Login with email `demo@payloadcms.com` and password `demo`
> \*NOTE: The --ignore-workspace flag is needed if you are running this example within the Payload monorepo to avoid workspace conflicts.
1. Start the server:
- Depending on your package manager, run `pnpm dev`, `yarn dev` or `npm run dev`
- When prompted, type `y` then `enter` to seed the database with sample data
1. Access the application:
- Open your browser and navigate to `http://localhost:3000` to access the homepage.
- Open `http://localhost:3000/admin` to access the admin panel.
1. Login:
- Use the following credentials to log into the admin panel:
> `Email: demo@payloadcms.com` > `Password: demo`
## How it works
### Collections
See the [Collections](https://payloadcms.com/docs/configuration/collections) docs for details on how to extend any of this functionality.
[Collections](https://payloadcms.com/docs/configuration/collections) in Payload allow you to define structured content types. This example includes multiple collections, with a focus on:
- #### Users
The `users` collection is auth-enabled which provides access to the admin panel.
The `users` collection is **auth-enabled**, providing access to the admin panel and enabling user authentication. This collection shows how to implement a basic user collection with authentication.
For additional help with authentication, see the official [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth/cms#readme) or the [Authentication](https://payloadcms.com/docs/authentication/overview#authentication-overview) docs.
- For more details on setting up authentication, checkout the [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth/cms#readme) and the [Authentication Overview](https://payloadcms.com/docs/authentication/overview#authentication-overview).
- #### Fields
The `fields` collection contains every field type available in Payload, each with custom components filled in every available "slot", i.e. `admin.components.Field`, `admin.components.Label`, etc. There are two of every field, one for server components, and the other for client components. This pattern shows how to use custom components in both environments, no matter which field type you are using.
The `fields` collection demonstrates all the **field types** available in Payload, each one configured with custom components. This includes every available "slot" for custom components (e.g., `admin.components.Field`, `admin.components.Label`, `admin.components.Input`, etc.). For each field type, two examples are provided: one using **server-side components** and the other using **client-side components**. This pattern illustrates how to customize both types of components across different field types.
- **Custom Field Components**: Custom components allow you to tailor the UI and behavior of the admin panel fields. This can be useful for implementing complex interactions, custom validation, or UI enhancements. For example, you might use a custom component to replace a simple text input with a date picker or a rich text editor.
- #### Views
The `views` collection demonstrates how to add collection-level views, including the default view and custom tabs.
The `views` collection demonstrates how to create **collection-level views**, such as custom tabs or layout configurations. This is where you can modify how data is displayed in the admin panel beyond the default list and edit views. Custom views give you full control over how content is presented to users.
- #### Root Views
The `root-views` collection demonstrates how to add a root document-level view to the admin panel.
The `root-views` collection shows how to implement **root-level views** in the admin panel. These views can be used to modify the global admin interface, adding custom sections or settings that appear outside of collections.
## Troubleshooting
If you encounter any issues during setup or while running the example, here are a few things to try:
- **Missing dependencies**: If you see errors related to missing packages, try deleting the `node_modules` folder and the lockfile (`package-lock.json` or `pnpm-lock.yaml`), then rerun `npm install` or `pnpm i`.
- **Port conflicts**: If the development server isn't starting, ensure that port `3000` isn't being used by another process. You can change the port by modifying the `package.json` file or setting the `PORT` environment variable.
- **Seed data issues**: If the database seeding fails, try clearing the database and then rerun the seeding process.
## Questions
If you have any issues or questions, reach out to us on [Discord](https://discord.com/invite/payload) or start a [GitHub discussion](https://github.com/payloadcms/payload/discussions).
For more detailed documentation on how to extend and customize Payload, check out the full [Payload documentation](https://payloadcms.com/docs).

View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

View File

@@ -5,10 +5,10 @@
"license": "MIT",
"type": "module",
"scripts": {
"_dev": "cross-env NODE_OPTIONS=--no-deprecation && pnpm generate:importmap && next dev",
"_dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"dev": "cross-env NODE_OPTIONS=--no-deprecation && pnpm generate:importmap && pnpm seed && next dev --turbo",
"generate:importmap": "payload generate:importmap",
"dev": "cross-env PAYLOAD_SEED=true PAYLOAD_DROP_DATABASE=true NODE_OPTIONS=--no-deprecation next dev",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
"generate:schema": "payload-graphql generate:schema",
"generate:types": "payload generate:types",
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
@@ -16,28 +16,41 @@
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
},
"dependencies": {
"@payloadcms/db-mongodb": "3.0.0-beta.106",
"@payloadcms/next": "3.0.0-beta.106",
"@payloadcms/richtext-lexical": "3.0.0-beta.106",
"@payloadcms/ui": "3.0.0-beta.106",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/next": "latest",
"@payloadcms/richtext-lexical": "latest",
"@payloadcms/ui": "latest",
"cross-env": "^7.0.3",
"dotenv": "^8.2.0",
"graphql": "^16.9.0",
"next": "15.0.0-canary.160",
"payload": "3.0.0-beta.106",
"react": "19.0.0-rc-5dcb0097-20240918",
"react-dom": "19.0.0-rc-5dcb0097-20240918"
"install": "^0.13.0",
"next": "^15.0.0",
"payload": "latest",
"react": "19.0.0-rc-65a56d0e-20241020",
"react-dom": "19.0.0-rc-65a56d0e-20241020"
},
"devDependencies": {
"@payloadcms/graphql": "3.0.0-beta.106",
"@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"@payloadcms/graphql": "latest",
"@swc/core": "^1.6.13",
"@types/ejs": "^3.1.5",
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"eslint": "^8.57.0",
"eslint-config-next": "15.0.0-canary.146",
"tsx": "^4.7.1",
"eslint-config-next": "^15.0.0",
"tsx": "^4.16.2",
"typescript": "5.5.2"
},
"engines": {
"node": "^18.20.2 || >=20.9.0"
},
"pnpm": {
"overrides": {
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
}
},
"overrides": {
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,12 @@ import { generatePageMetadata, NotFoundPage } from '@payloadcms/next/views'
import { importMap } from '../importMap.js'
type Args = {
params: {
params: Promise<{
segments: string[]
}
searchParams: {
}>
searchParams: Promise<{
[key: string]: string | string[]
}
}>
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>

View File

@@ -8,14 +8,13 @@ import { generatePageMetadata, RootPage } from '@payloadcms/next/views'
import { importMap } from '../importMap.js'
type Args = {
params: {
params: Promise<{
segments: string[]
}
searchParams: {
}>
searchParams: Promise<{
[key: string]: string | string[]
}
}>
}
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
generatePageMetadata({ config, params, searchParams })

View File

@@ -1,162 +1,113 @@
import { CustomArrayFieldLabelServer as CustomArrayFieldLabelServer_0 } from '@/collections/Fields/array/components/server/Label'
import { CustomArrayFieldServer as CustomArrayFieldServer_1 } from '@/collections/Fields/array/components/server/Field'
import { CustomArrayFieldLabelClient as CustomArrayFieldLabelClient_2 } from '@/collections/Fields/array/components/client/Label'
import { CustomArrayFieldClient as CustomArrayFieldClient_3 } from '@/collections/Fields/array/components/client/Field'
import { CustomBlocksFieldServer as CustomBlocksFieldServer_4 } from '@/collections/Fields/blocks/components/server/Field'
import { CustomBlocksFieldClient as CustomBlocksFieldClient_5 } from '@/collections/Fields/blocks/components/client/Field'
import { CustomCheckboxFieldLabelServer as CustomCheckboxFieldLabelServer_6 } from '@/collections/Fields/checkbox/components/server/Label'
import { CustomCheckboxFieldServer as CustomCheckboxFieldServer_7 } from '@/collections/Fields/checkbox/components/server/Field'
import { CustomCheckboxFieldLabelClient as CustomCheckboxFieldLabelClient_8 } from '@/collections/Fields/checkbox/components/client/Label'
import { CustomCheckboxFieldClient as CustomCheckboxFieldClient_9 } from '@/collections/Fields/checkbox/components/client/Field'
import { CustomDateFieldLabelServer as CustomDateFieldLabelServer_10 } from '@/collections/Fields/date/components/server/Label'
import { CustomDateFieldServer as CustomDateFieldServer_11 } from '@/collections/Fields/date/components/server/Field'
import { CustomDateFieldLabelClient as CustomDateFieldLabelClient_12 } from '@/collections/Fields/date/components/client/Label'
import { CustomDateFieldClient as CustomDateFieldClient_13 } from '@/collections/Fields/date/components/client/Field'
import { CustomEmailFieldLabelServer as CustomEmailFieldLabelServer_14 } from '@/collections/Fields/email/components/server/Label'
import { CustomEmailFieldServer as CustomEmailFieldServer_15 } from '@/collections/Fields/email/components/server/Field'
import { CustomEmailFieldLabelClient as CustomEmailFieldLabelClient_16 } from '@/collections/Fields/email/components/client/Label'
import { CustomEmailFieldClient as CustomEmailFieldClient_17 } from '@/collections/Fields/email/components/client/Field'
import { CustomNumberFieldLabelServer as CustomNumberFieldLabelServer_18 } from '@/collections/Fields/number/components/server/Label'
import { CustomNumberFieldServer as CustomNumberFieldServer_19 } from '@/collections/Fields/number/components/server/Field'
import { CustomNumberFieldLabelClient as CustomNumberFieldLabelClient_20 } from '@/collections/Fields/number/components/client/Label'
import { CustomNumberFieldClient as CustomNumberFieldClient_21 } from '@/collections/Fields/number/components/client/Field'
import { CustomPointFieldLabelServer as CustomPointFieldLabelServer_22 } from '@/collections/Fields/point/components/server/Label'
import { CustomPointFieldServer as CustomPointFieldServer_23 } from '@/collections/Fields/point/components/server/Field'
import { CustomPointFieldLabelClient as CustomPointFieldLabelClient_24 } from '@/collections/Fields/point/components/client/Label'
import { CustomPointFieldClient as CustomPointFieldClient_25 } from '@/collections/Fields/point/components/client/Field'
import { CustomRadioFieldLabelServer as CustomRadioFieldLabelServer_26 } from '@/collections/Fields/radio/components/server/Label'
import { CustomRadioFieldServer as CustomRadioFieldServer_27 } from '@/collections/Fields/radio/components/server/Field'
import { CustomRadioFieldLabelClient as CustomRadioFieldLabelClient_28 } from '@/collections/Fields/radio/components/client/Label'
import { CustomRadioFieldClient as CustomRadioFieldClient_29 } from '@/collections/Fields/radio/components/client/Field'
import { CustomRelationshipFieldLabelServer as CustomRelationshipFieldLabelServer_30 } from '@/collections/Fields/relationship/components/server/Label'
import { CustomRelationshipFieldServer as CustomRelationshipFieldServer_31 } from '@/collections/Fields/relationship/components/server/Field'
import { CustomRelationshipFieldLabelClient as CustomRelationshipFieldLabelClient_32 } from '@/collections/Fields/relationship/components/client/Label'
import { CustomRelationshipFieldClient as CustomRelationshipFieldClient_33 } from '@/collections/Fields/relationship/components/client/Field'
import { CustomSelectFieldLabelServer as CustomSelectFieldLabelServer_34 } from '@/collections/Fields/select/components/server/Label'
import { CustomSelectFieldServer as CustomSelectFieldServer_35 } from '@/collections/Fields/select/components/server/Field'
import { CustomSelectFieldLabelClient as CustomSelectFieldLabelClient_36 } from '@/collections/Fields/select/components/client/Label'
import { CustomSelectFieldClient as CustomSelectFieldClient_37 } from '@/collections/Fields/select/components/client/Field'
import { CustomTextFieldLabelServer as CustomTextFieldLabelServer_38 } from '@/collections/Fields/text/components/server/Label'
import { CustomTextFieldServer as CustomTextFieldServer_39 } from '@/collections/Fields/text/components/server/Field'
import { CustomTextFieldLabelClient as CustomTextFieldLabelClient_40 } from '@/collections/Fields/text/components/client/Label'
import { CustomTextFieldClient as CustomTextFieldClient_41 } from '@/collections/Fields/text/components/client/Field'
import { CustomTextareaFieldLabelServer as CustomTextareaFieldLabelServer_42 } from '@/collections/Fields/textarea/components/server/Label'
import { CustomTextareaFieldServer as CustomTextareaFieldServer_43 } from '@/collections/Fields/textarea/components/server/Field'
import { CustomTextareaFieldLabelClient as CustomTextareaFieldLabelClient_44 } from '@/collections/Fields/textarea/components/client/Label'
import { CustomTextareaFieldClient as CustomTextareaFieldClient_45 } from '@/collections/Fields/textarea/components/client/Field'
import { CustomTabEditView as CustomTabEditView_46 } from '@/collections/Views/components/CustomTabEditView'
import { CustomDefaultEditView as CustomDefaultEditView_47 } from '@/collections/Views/components/CustomDefaultEditView'
import { CustomRootEditView as CustomRootEditView_48 } from '@/collections/RootViews/components/CustomRootEditView'
import { LinkToCustomView as LinkToCustomView_49 } from '@/components/afterNavLinks/LinkToCustomView'
import { LinkToCustomMinimalView as LinkToCustomMinimalView_50 } from '@/components/afterNavLinks/LinkToCustomMinimalView'
import { LinkToCustomDefaultView as LinkToCustomDefaultView_51 } from '@/components/afterNavLinks/LinkToCustomDefaultView'
import { CustomRootView as CustomRootView_52 } from '@/components/views/CustomRootView'
import { CustomDefaultRootView as CustomDefaultRootView_53 } from '@/components/views/CustomDefaultRootView'
import { CustomMinimalRootView as CustomMinimalRootView_54 } from '@/components/views/CustomMinimalRootView'
import { CustomArrayFieldLabelServer as CustomArrayFieldLabelServer_f8d063e9b7f25c350451c1865199c947 } from '@/collections/Fields/array/components/server/Label'
import { CustomArrayFieldServer as CustomArrayFieldServer_4c3c139a9b1a198103c8a2ec2869c837 } from '@/collections/Fields/array/components/server/Field'
import { CustomArrayFieldLabelClient as CustomArrayFieldLabelClient_c07dc2c547c47aca8e9f471795279e9d } from '@/collections/Fields/array/components/client/Label'
import { CustomArrayFieldClient as CustomArrayFieldClient_60ede271f2b85983daf36710010ad8ab } from '@/collections/Fields/array/components/client/Field'
import { CustomBlocksFieldServer as CustomBlocksFieldServer_61732537ad2c492ac9938959902f6954 } from '@/collections/Fields/blocks/components/server/Field'
import { CustomBlocksFieldClient as CustomBlocksFieldClient_2ef3a03de3974b6f18f07623af0cd515 } from '@/collections/Fields/blocks/components/client/Field'
import { CustomCheckboxFieldLabelServer as CustomCheckboxFieldLabelServer_48cd2d9639f54745ad4cdb6905c825d9 } from '@/collections/Fields/checkbox/components/server/Label'
import { CustomCheckboxFieldServer as CustomCheckboxFieldServer_85023d60242dd4cca7c406a728ec37a8 } from '@/collections/Fields/checkbox/components/server/Field'
import { CustomCheckboxFieldLabelClient as CustomCheckboxFieldLabelClient_f2b214145c1cbe98957573cf62455194 } from '@/collections/Fields/checkbox/components/client/Label'
import { CustomCheckboxFieldClient as CustomCheckboxFieldClient_a13e6003bc89da826df764d7234782de } from '@/collections/Fields/checkbox/components/client/Field'
import { CustomDateFieldLabelServer as CustomDateFieldLabelServer_ae9eb459b79a1363a40d62b1e463aa6b } from '@/collections/Fields/date/components/server/Label'
import { CustomDateFieldServer as CustomDateFieldServer_9d448604d99b3b06826ea95986ffd27b } from '@/collections/Fields/date/components/server/Field'
import { CustomDateFieldLabelClient as CustomDateFieldLabelClient_0b6c1439c63aadfd306cf432713a52d8 } from '@/collections/Fields/date/components/client/Label'
import { CustomDateFieldClient as CustomDateFieldClient_4ef537c727f5de7c26aaea94024a0b2c } from '@/collections/Fields/date/components/client/Field'
import { CustomEmailFieldLabelServer as CustomEmailFieldLabelServer_a5097abb06efbe71fc6ba1636f7194ab } from '@/collections/Fields/email/components/server/Label'
import { CustomEmailFieldServer as CustomEmailFieldServer_457ae84519701bf0b287c30a994ddab1 } from '@/collections/Fields/email/components/server/Field'
import { CustomEmailFieldLabelClient as CustomEmailFieldLabelClient_147edabdb378c855b9c8c06b8c627e50 } from '@/collections/Fields/email/components/client/Label'
import { CustomEmailFieldClient as CustomEmailFieldClient_e22bcec891915f255e5ac6e1850aeb97 } from '@/collections/Fields/email/components/client/Field'
import { CustomNumberFieldLabelServer as CustomNumberFieldLabelServer_1b47d0cd70ad88e23dcf9c4f91bf319f } from '@/collections/Fields/number/components/server/Label'
import { CustomNumberFieldServer as CustomNumberFieldServer_54fc6ad95d89a3b66b59136e84d20b86 } from '@/collections/Fields/number/components/server/Field'
import { CustomNumberFieldLabelClient as CustomNumberFieldLabelClient_dd3e3dcfc7b07c3a02f947ac81718a51 } from '@/collections/Fields/number/components/client/Label'
import { CustomNumberFieldClient as CustomNumberFieldClient_5d5605680426c77470fd74d010fe051f } from '@/collections/Fields/number/components/client/Field'
import { CustomPointFieldLabelServer as CustomPointFieldLabelServer_c5fb0c717f353a8c6149238dd7d92ec9 } from '@/collections/Fields/point/components/server/Label'
import { CustomPointFieldServer as CustomPointFieldServer_a23d13971ed0ff10615e3248bb1ee55d } from '@/collections/Fields/point/components/server/Field'
import { CustomPointFieldLabelClient as CustomPointFieldLabelClient_3c6c8c891bc098021e618d5cf4dc3150 } from '@/collections/Fields/point/components/client/Label'
import { CustomPointFieldClient as CustomPointFieldClient_abb4ee1633cbc83b4cec9b8abb95f132 } from '@/collections/Fields/point/components/client/Field'
import { CustomRadioFieldLabelServer as CustomRadioFieldLabelServer_5c732ac2af72bb41657cc9a1a22bc67b } from '@/collections/Fields/radio/components/server/Label'
import { CustomRadioFieldServer as CustomRadioFieldServer_b7edb363e225e2976a994da8e8803e60 } from '@/collections/Fields/radio/components/server/Field'
import { CustomRadioFieldLabelClient as CustomRadioFieldLabelClient_d46d0583023d87065f05972901727bbf } from '@/collections/Fields/radio/components/client/Label'
import { CustomRadioFieldClient as CustomRadioFieldClient_42845db96f999817cb9f0a590413d669 } from '@/collections/Fields/radio/components/client/Field'
import { CustomRelationshipFieldLabelServer as CustomRelationshipFieldLabelServer_7c45510caabe204587b638c40f0d0a70 } from '@/collections/Fields/relationship/components/server/Label'
import { CustomRelationshipFieldServer as CustomRelationshipFieldServer_d2e0b17d4b1c00b1fc726f0ea55ddc16 } from '@/collections/Fields/relationship/components/server/Field'
import { CustomRelationshipFieldLabelClient as CustomRelationshipFieldLabelClient_37b268226ded7dd38d5cb8f2952f4b3a } from '@/collections/Fields/relationship/components/client/Label'
import { CustomRelationshipFieldClient as CustomRelationshipFieldClient_eb1bc838beb92b05ba1bb9c1fdfd7869 } from '@/collections/Fields/relationship/components/client/Field'
import { CustomSelectFieldLabelServer as CustomSelectFieldLabelServer_653acab80b672fd4ebeeed757e09d4c9 } from '@/collections/Fields/select/components/server/Label'
import { CustomSelectFieldServer as CustomSelectFieldServer_ee886c859ef756c29ae7383a2be0a08a } from '@/collections/Fields/select/components/server/Field'
import { CustomSelectFieldLabelClient as CustomSelectFieldLabelClient_2db542ef2e0a664acaa5679fc14aa54b } from '@/collections/Fields/select/components/client/Label'
import { CustomSelectFieldClient as CustomSelectFieldClient_c8b4c7f3e98b5887ca262dd841bffa2f } from '@/collections/Fields/select/components/client/Field'
import { CustomTextFieldLabelServer as CustomTextFieldLabelServer_64a4b68861269d69d4c16a0f651b7ac9 } from '@/collections/Fields/text/components/server/Label'
import { CustomTextFieldServer as CustomTextFieldServer_e0caaef49c00003336b08d834c0c9fe9 } from '@/collections/Fields/text/components/server/Field'
import { CustomTextFieldLabelClient as CustomTextFieldLabelClient_9af2b9e4733a9fc79fb9dfb1578c18bf } from '@/collections/Fields/text/components/client/Label'
import { CustomTextFieldClient as CustomTextFieldClient_c7c0687b5204b201f8b1af831f34fd98 } from '@/collections/Fields/text/components/client/Field'
import { CustomTextareaFieldLabelServer as CustomTextareaFieldLabelServer_5c8f706a3452bccefa9f5044e2cd250c } from '@/collections/Fields/textarea/components/server/Label'
import { CustomTextareaFieldServer as CustomTextareaFieldServer_3f7b621f5c4c42971fc099a1fa492d99 } from '@/collections/Fields/textarea/components/server/Field'
import { CustomTextareaFieldLabelClient as CustomTextareaFieldLabelClient_9959ee64353edb5f2606b52187275823 } from '@/collections/Fields/textarea/components/client/Label'
import { CustomTextareaFieldClient as CustomTextareaFieldClient_4fd3331c38982e86768c64dcc9a10691 } from '@/collections/Fields/textarea/components/client/Field'
import { CustomTabEditView as CustomTabEditView_0a7acb05a3192ecfa7e07f8b42e7a193 } from '@/collections/Views/components/CustomTabEditView'
import { CustomDefaultEditView as CustomDefaultEditView_2d3c652c5909d3a3dc3464f0547d5424 } from '@/collections/Views/components/CustomDefaultEditView'
import { CustomRootEditView as CustomRootEditView_ba37229da543ad3c8dc40f7a48771f99 } from '@/collections/RootViews/components/CustomRootEditView'
import { LinkToCustomView as LinkToCustomView_6f16fe358985478a2ead2354ef2cc9a0 } from '@/components/afterNavLinks/LinkToCustomView'
import { LinkToCustomMinimalView as LinkToCustomMinimalView_fd2cefb054695a5b60b860a69d67d15d } from '@/components/afterNavLinks/LinkToCustomMinimalView'
import { LinkToCustomDefaultView as LinkToCustomDefaultView_4c5f581c8bfa951ce2f83c24c4f36b3b } from '@/components/afterNavLinks/LinkToCustomDefaultView'
import { CustomRootView as CustomRootView_1ebb91ef5ff1ea4dc9a27ceb8e9ee0ab } from '@/components/views/CustomRootView'
import { CustomDefaultRootView as CustomDefaultRootView_a2f8ce99b3a1692f7ec03a907e1ea4ce } from '@/components/views/CustomDefaultRootView'
import { CustomMinimalRootView as CustomMinimalRootView_9211f699dea5524a957f33011b786586 } from '@/components/views/CustomMinimalRootView'
export const importMap = {
'@/collections/Fields/array/components/server/Label#CustomArrayFieldLabelServer':
CustomArrayFieldLabelServer_0,
'@/collections/Fields/array/components/server/Field#CustomArrayFieldServer':
CustomArrayFieldServer_1,
'@/collections/Fields/array/components/client/Label#CustomArrayFieldLabelClient':
CustomArrayFieldLabelClient_2,
'@/collections/Fields/array/components/client/Field#CustomArrayFieldClient':
CustomArrayFieldClient_3,
'@/collections/Fields/blocks/components/server/Field#CustomBlocksFieldServer':
CustomBlocksFieldServer_4,
'@/collections/Fields/blocks/components/client/Field#CustomBlocksFieldClient':
CustomBlocksFieldClient_5,
'@/collections/Fields/checkbox/components/server/Label#CustomCheckboxFieldLabelServer':
CustomCheckboxFieldLabelServer_6,
'@/collections/Fields/checkbox/components/server/Field#CustomCheckboxFieldServer':
CustomCheckboxFieldServer_7,
'@/collections/Fields/checkbox/components/client/Label#CustomCheckboxFieldLabelClient':
CustomCheckboxFieldLabelClient_8,
'@/collections/Fields/checkbox/components/client/Field#CustomCheckboxFieldClient':
CustomCheckboxFieldClient_9,
'@/collections/Fields/date/components/server/Label#CustomDateFieldLabelServer':
CustomDateFieldLabelServer_10,
'@/collections/Fields/date/components/server/Field#CustomDateFieldServer':
CustomDateFieldServer_11,
'@/collections/Fields/date/components/client/Label#CustomDateFieldLabelClient':
CustomDateFieldLabelClient_12,
'@/collections/Fields/date/components/client/Field#CustomDateFieldClient':
CustomDateFieldClient_13,
'@/collections/Fields/email/components/server/Label#CustomEmailFieldLabelServer':
CustomEmailFieldLabelServer_14,
'@/collections/Fields/email/components/server/Field#CustomEmailFieldServer':
CustomEmailFieldServer_15,
'@/collections/Fields/email/components/client/Label#CustomEmailFieldLabelClient':
CustomEmailFieldLabelClient_16,
'@/collections/Fields/email/components/client/Field#CustomEmailFieldClient':
CustomEmailFieldClient_17,
'@/collections/Fields/number/components/server/Label#CustomNumberFieldLabelServer':
CustomNumberFieldLabelServer_18,
'@/collections/Fields/number/components/server/Field#CustomNumberFieldServer':
CustomNumberFieldServer_19,
'@/collections/Fields/number/components/client/Label#CustomNumberFieldLabelClient':
CustomNumberFieldLabelClient_20,
'@/collections/Fields/number/components/client/Field#CustomNumberFieldClient':
CustomNumberFieldClient_21,
'@/collections/Fields/point/components/server/Label#CustomPointFieldLabelServer':
CustomPointFieldLabelServer_22,
'@/collections/Fields/point/components/server/Field#CustomPointFieldServer':
CustomPointFieldServer_23,
'@/collections/Fields/point/components/client/Label#CustomPointFieldLabelClient':
CustomPointFieldLabelClient_24,
'@/collections/Fields/point/components/client/Field#CustomPointFieldClient':
CustomPointFieldClient_25,
'@/collections/Fields/radio/components/server/Label#CustomRadioFieldLabelServer':
CustomRadioFieldLabelServer_26,
'@/collections/Fields/radio/components/server/Field#CustomRadioFieldServer':
CustomRadioFieldServer_27,
'@/collections/Fields/radio/components/client/Label#CustomRadioFieldLabelClient':
CustomRadioFieldLabelClient_28,
'@/collections/Fields/radio/components/client/Field#CustomRadioFieldClient':
CustomRadioFieldClient_29,
'@/collections/Fields/relationship/components/server/Label#CustomRelationshipFieldLabelServer':
CustomRelationshipFieldLabelServer_30,
'@/collections/Fields/relationship/components/server/Field#CustomRelationshipFieldServer':
CustomRelationshipFieldServer_31,
'@/collections/Fields/relationship/components/client/Label#CustomRelationshipFieldLabelClient':
CustomRelationshipFieldLabelClient_32,
'@/collections/Fields/relationship/components/client/Field#CustomRelationshipFieldClient':
CustomRelationshipFieldClient_33,
'@/collections/Fields/select/components/server/Label#CustomSelectFieldLabelServer':
CustomSelectFieldLabelServer_34,
'@/collections/Fields/select/components/server/Field#CustomSelectFieldServer':
CustomSelectFieldServer_35,
'@/collections/Fields/select/components/client/Label#CustomSelectFieldLabelClient':
CustomSelectFieldLabelClient_36,
'@/collections/Fields/select/components/client/Field#CustomSelectFieldClient':
CustomSelectFieldClient_37,
'@/collections/Fields/text/components/server/Label#CustomTextFieldLabelServer':
CustomTextFieldLabelServer_38,
'@/collections/Fields/text/components/server/Field#CustomTextFieldServer':
CustomTextFieldServer_39,
'@/collections/Fields/text/components/client/Label#CustomTextFieldLabelClient':
CustomTextFieldLabelClient_40,
'@/collections/Fields/text/components/client/Field#CustomTextFieldClient':
CustomTextFieldClient_41,
'@/collections/Fields/textarea/components/server/Label#CustomTextareaFieldLabelServer':
CustomTextareaFieldLabelServer_42,
'@/collections/Fields/textarea/components/server/Field#CustomTextareaFieldServer':
CustomTextareaFieldServer_43,
'@/collections/Fields/textarea/components/client/Label#CustomTextareaFieldLabelClient':
CustomTextareaFieldLabelClient_44,
'@/collections/Fields/textarea/components/client/Field#CustomTextareaFieldClient':
CustomTextareaFieldClient_45,
'@/collections/Views/components/CustomTabEditView#CustomTabEditView': CustomTabEditView_46,
'@/collections/Views/components/CustomDefaultEditView#CustomDefaultEditView':
CustomDefaultEditView_47,
'@/collections/RootViews/components/CustomRootEditView#CustomRootEditView': CustomRootEditView_48,
'@/components/afterNavLinks/LinkToCustomView#LinkToCustomView': LinkToCustomView_49,
'@/components/afterNavLinks/LinkToCustomMinimalView#LinkToCustomMinimalView':
LinkToCustomMinimalView_50,
'@/components/afterNavLinks/LinkToCustomDefaultView#LinkToCustomDefaultView':
LinkToCustomDefaultView_51,
'@/components/views/CustomRootView#CustomRootView': CustomRootView_52,
'@/components/views/CustomDefaultRootView#CustomDefaultRootView': CustomDefaultRootView_53,
'@/components/views/CustomMinimalRootView#CustomMinimalRootView': CustomMinimalRootView_54,
"@/collections/Fields/array/components/server/Label#CustomArrayFieldLabelServer": CustomArrayFieldLabelServer_f8d063e9b7f25c350451c1865199c947,
"@/collections/Fields/array/components/server/Field#CustomArrayFieldServer": CustomArrayFieldServer_4c3c139a9b1a198103c8a2ec2869c837,
"@/collections/Fields/array/components/client/Label#CustomArrayFieldLabelClient": CustomArrayFieldLabelClient_c07dc2c547c47aca8e9f471795279e9d,
"@/collections/Fields/array/components/client/Field#CustomArrayFieldClient": CustomArrayFieldClient_60ede271f2b85983daf36710010ad8ab,
"@/collections/Fields/blocks/components/server/Field#CustomBlocksFieldServer": CustomBlocksFieldServer_61732537ad2c492ac9938959902f6954,
"@/collections/Fields/blocks/components/client/Field#CustomBlocksFieldClient": CustomBlocksFieldClient_2ef3a03de3974b6f18f07623af0cd515,
"@/collections/Fields/checkbox/components/server/Label#CustomCheckboxFieldLabelServer": CustomCheckboxFieldLabelServer_48cd2d9639f54745ad4cdb6905c825d9,
"@/collections/Fields/checkbox/components/server/Field#CustomCheckboxFieldServer": CustomCheckboxFieldServer_85023d60242dd4cca7c406a728ec37a8,
"@/collections/Fields/checkbox/components/client/Label#CustomCheckboxFieldLabelClient": CustomCheckboxFieldLabelClient_f2b214145c1cbe98957573cf62455194,
"@/collections/Fields/checkbox/components/client/Field#CustomCheckboxFieldClient": CustomCheckboxFieldClient_a13e6003bc89da826df764d7234782de,
"@/collections/Fields/date/components/server/Label#CustomDateFieldLabelServer": CustomDateFieldLabelServer_ae9eb459b79a1363a40d62b1e463aa6b,
"@/collections/Fields/date/components/server/Field#CustomDateFieldServer": CustomDateFieldServer_9d448604d99b3b06826ea95986ffd27b,
"@/collections/Fields/date/components/client/Label#CustomDateFieldLabelClient": CustomDateFieldLabelClient_0b6c1439c63aadfd306cf432713a52d8,
"@/collections/Fields/date/components/client/Field#CustomDateFieldClient": CustomDateFieldClient_4ef537c727f5de7c26aaea94024a0b2c,
"@/collections/Fields/email/components/server/Label#CustomEmailFieldLabelServer": CustomEmailFieldLabelServer_a5097abb06efbe71fc6ba1636f7194ab,
"@/collections/Fields/email/components/server/Field#CustomEmailFieldServer": CustomEmailFieldServer_457ae84519701bf0b287c30a994ddab1,
"@/collections/Fields/email/components/client/Label#CustomEmailFieldLabelClient": CustomEmailFieldLabelClient_147edabdb378c855b9c8c06b8c627e50,
"@/collections/Fields/email/components/client/Field#CustomEmailFieldClient": CustomEmailFieldClient_e22bcec891915f255e5ac6e1850aeb97,
"@/collections/Fields/number/components/server/Label#CustomNumberFieldLabelServer": CustomNumberFieldLabelServer_1b47d0cd70ad88e23dcf9c4f91bf319f,
"@/collections/Fields/number/components/server/Field#CustomNumberFieldServer": CustomNumberFieldServer_54fc6ad95d89a3b66b59136e84d20b86,
"@/collections/Fields/number/components/client/Label#CustomNumberFieldLabelClient": CustomNumberFieldLabelClient_dd3e3dcfc7b07c3a02f947ac81718a51,
"@/collections/Fields/number/components/client/Field#CustomNumberFieldClient": CustomNumberFieldClient_5d5605680426c77470fd74d010fe051f,
"@/collections/Fields/point/components/server/Label#CustomPointFieldLabelServer": CustomPointFieldLabelServer_c5fb0c717f353a8c6149238dd7d92ec9,
"@/collections/Fields/point/components/server/Field#CustomPointFieldServer": CustomPointFieldServer_a23d13971ed0ff10615e3248bb1ee55d,
"@/collections/Fields/point/components/client/Label#CustomPointFieldLabelClient": CustomPointFieldLabelClient_3c6c8c891bc098021e618d5cf4dc3150,
"@/collections/Fields/point/components/client/Field#CustomPointFieldClient": CustomPointFieldClient_abb4ee1633cbc83b4cec9b8abb95f132,
"@/collections/Fields/radio/components/server/Label#CustomRadioFieldLabelServer": CustomRadioFieldLabelServer_5c732ac2af72bb41657cc9a1a22bc67b,
"@/collections/Fields/radio/components/server/Field#CustomRadioFieldServer": CustomRadioFieldServer_b7edb363e225e2976a994da8e8803e60,
"@/collections/Fields/radio/components/client/Label#CustomRadioFieldLabelClient": CustomRadioFieldLabelClient_d46d0583023d87065f05972901727bbf,
"@/collections/Fields/radio/components/client/Field#CustomRadioFieldClient": CustomRadioFieldClient_42845db96f999817cb9f0a590413d669,
"@/collections/Fields/relationship/components/server/Label#CustomRelationshipFieldLabelServer": CustomRelationshipFieldLabelServer_7c45510caabe204587b638c40f0d0a70,
"@/collections/Fields/relationship/components/server/Field#CustomRelationshipFieldServer": CustomRelationshipFieldServer_d2e0b17d4b1c00b1fc726f0ea55ddc16,
"@/collections/Fields/relationship/components/client/Label#CustomRelationshipFieldLabelClient": CustomRelationshipFieldLabelClient_37b268226ded7dd38d5cb8f2952f4b3a,
"@/collections/Fields/relationship/components/client/Field#CustomRelationshipFieldClient": CustomRelationshipFieldClient_eb1bc838beb92b05ba1bb9c1fdfd7869,
"@/collections/Fields/select/components/server/Label#CustomSelectFieldLabelServer": CustomSelectFieldLabelServer_653acab80b672fd4ebeeed757e09d4c9,
"@/collections/Fields/select/components/server/Field#CustomSelectFieldServer": CustomSelectFieldServer_ee886c859ef756c29ae7383a2be0a08a,
"@/collections/Fields/select/components/client/Label#CustomSelectFieldLabelClient": CustomSelectFieldLabelClient_2db542ef2e0a664acaa5679fc14aa54b,
"@/collections/Fields/select/components/client/Field#CustomSelectFieldClient": CustomSelectFieldClient_c8b4c7f3e98b5887ca262dd841bffa2f,
"@/collections/Fields/text/components/server/Label#CustomTextFieldLabelServer": CustomTextFieldLabelServer_64a4b68861269d69d4c16a0f651b7ac9,
"@/collections/Fields/text/components/server/Field#CustomTextFieldServer": CustomTextFieldServer_e0caaef49c00003336b08d834c0c9fe9,
"@/collections/Fields/text/components/client/Label#CustomTextFieldLabelClient": CustomTextFieldLabelClient_9af2b9e4733a9fc79fb9dfb1578c18bf,
"@/collections/Fields/text/components/client/Field#CustomTextFieldClient": CustomTextFieldClient_c7c0687b5204b201f8b1af831f34fd98,
"@/collections/Fields/textarea/components/server/Label#CustomTextareaFieldLabelServer": CustomTextareaFieldLabelServer_5c8f706a3452bccefa9f5044e2cd250c,
"@/collections/Fields/textarea/components/server/Field#CustomTextareaFieldServer": CustomTextareaFieldServer_3f7b621f5c4c42971fc099a1fa492d99,
"@/collections/Fields/textarea/components/client/Label#CustomTextareaFieldLabelClient": CustomTextareaFieldLabelClient_9959ee64353edb5f2606b52187275823,
"@/collections/Fields/textarea/components/client/Field#CustomTextareaFieldClient": CustomTextareaFieldClient_4fd3331c38982e86768c64dcc9a10691,
"@/collections/Views/components/CustomTabEditView#CustomTabEditView": CustomTabEditView_0a7acb05a3192ecfa7e07f8b42e7a193,
"@/collections/Views/components/CustomDefaultEditView#CustomDefaultEditView": CustomDefaultEditView_2d3c652c5909d3a3dc3464f0547d5424,
"@/collections/RootViews/components/CustomRootEditView#CustomRootEditView": CustomRootEditView_ba37229da543ad3c8dc40f7a48771f99,
"@/components/afterNavLinks/LinkToCustomView#LinkToCustomView": LinkToCustomView_6f16fe358985478a2ead2354ef2cc9a0,
"@/components/afterNavLinks/LinkToCustomMinimalView#LinkToCustomMinimalView": LinkToCustomMinimalView_fd2cefb054695a5b60b860a69d67d15d,
"@/components/afterNavLinks/LinkToCustomDefaultView#LinkToCustomDefaultView": LinkToCustomDefaultView_4c5f581c8bfa951ce2f83c24c4f36b3b,
"@/components/views/CustomRootView#CustomRootView": CustomRootView_1ebb91ef5ff1ea4dc9a27ceb8e9ee0ab,
"@/components/views/CustomDefaultRootView#CustomDefaultRootView": CustomDefaultRootView_a2f8ce99b3a1692f7ec03a907e1ea4ce,
"@/components/views/CustomMinimalRootView#CustomMinimalRootView": CustomMinimalRootView_9211f699dea5524a957f33011b786586
}

View File

@@ -1,8 +1,10 @@
import type { ServerFunctionClient } from 'payload'
import '@payloadcms/next/css'
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
import config from '@payload-config'
import '@payloadcms/next/css'
import { RootLayout } from '@payloadcms/next/layouts'
import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts'
import React from 'react'
import { importMap } from './admin/importMap.js'
@@ -12,8 +14,17 @@ type Args = {
children: React.ReactNode
}
const serverFunction: ServerFunctionClient = async function (args) {
'use server'
return handleServerFunctions({
...args,
config,
importMap,
})
}
const Layout = ({ children }: Args) => (
<RootLayout config={config} importMap={importMap}>
<RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>
{children}
</RootLayout>
)

View File

@@ -4,6 +4,6 @@ import type { ArrayFieldClientComponent } from 'payload'
import { ArrayField } from '@payloadcms/ui'
import React from 'react'
export const CustomArrayFieldClient: ArrayFieldClientComponent = ({ field }) => {
return <ArrayField field={field} />
export const CustomArrayFieldClient: ArrayFieldClientComponent = (props) => {
return <ArrayField field={props?.field} path={props?.path} permissions={props?.permissions} />
}

View File

@@ -4,6 +4,6 @@ import type { ArrayFieldLabelClientComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomArrayFieldLabelClient: ArrayFieldLabelClientComponent = ({ field }) => {
return <FieldLabel field={field} />
export const CustomArrayFieldLabelClient: ArrayFieldLabelClientComponent = (props) => {
return <FieldLabel label={props?.label} path={props?.path} />
}

View File

@@ -3,6 +3,7 @@ import type React from 'react'
import { ArrayField } from '@payloadcms/ui'
export const CustomArrayFieldServer: ArrayFieldServerComponent = ({ clientField }) => {
return <ArrayField field={clientField} />
export const CustomArrayFieldServer: ArrayFieldServerComponent = (props) => {
const path = (props?.path || props?.field?.name || '') as string
return <ArrayField field={props.clientField} path={path} permissions={props?.permissions} />
}

View File

@@ -3,6 +3,6 @@ import type { ArrayFieldLabelServerComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomArrayFieldLabelServer: ArrayFieldLabelServerComponent = ({ clientField }) => {
return <FieldLabel field={clientField} />
export const CustomArrayFieldLabelServer: ArrayFieldLabelServerComponent = (props) => {
return <FieldLabel label={props?.label} />
}

View File

@@ -4,6 +4,6 @@ import type { BlocksFieldClientComponent } from 'payload'
import { BlocksField } from '@payloadcms/ui'
import React from 'react'
export const CustomBlocksFieldClient: BlocksFieldClientComponent = ({ field }) => {
return <BlocksField field={field} />
export const CustomBlocksFieldClient: BlocksFieldClientComponent = (props) => {
return <BlocksField field={props?.field} path={props.path} permissions={props?.permissions} />
}

View File

@@ -4,6 +4,6 @@ import type { BlocksFieldLabelClientComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomBlocksFieldLabelClient: BlocksFieldLabelClientComponent = ({ field }) => {
return <FieldLabel field={field} />
export const CustomBlocksFieldLabelClient: BlocksFieldLabelClientComponent = (props) => {
return <FieldLabel label={props?.label} />
}

View File

@@ -3,6 +3,7 @@ import type React from 'react'
import { BlocksField } from '@payloadcms/ui'
export const CustomBlocksFieldServer: BlocksFieldServerComponent = ({ clientField }) => {
return <BlocksField field={clientField} />
export const CustomBlocksFieldServer: BlocksFieldServerComponent = (props) => {
const path = (props?.path || props?.field?.name || '') as string
return <BlocksField field={props?.clientField} path={path} permissions={props?.permissions} />
}

View File

@@ -3,6 +3,6 @@ import type { BlocksFieldLabelServerComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomBlocksFieldLabelServer: BlocksFieldLabelServerComponent = ({ clientField }) => {
return <FieldLabel field={clientField} />
export const CustomBlocksFieldLabelServer: BlocksFieldLabelServerComponent = (props) => {
return <FieldLabel label={props?.label} />
}

View File

@@ -4,6 +4,6 @@ import type { CheckboxFieldClientComponent } from 'payload'
import { CheckboxField } from '@payloadcms/ui'
import React from 'react'
export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = ({ field }) => {
return <CheckboxField field={field} />
export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (props) => {
return <CheckboxField field={props?.field} path={props?.path} />
}

View File

@@ -4,6 +4,6 @@ import type { CheckboxFieldLabelClientComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent = ({ field }) => {
return <FieldLabel field={field} />
export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent = (props) => {
return <FieldLabel label={props?.label} path={props?.path} />
}

View File

@@ -3,6 +3,7 @@ import type React from 'react'
import { CheckboxField } from '@payloadcms/ui'
export const CustomCheckboxFieldServer: CheckboxFieldServerComponent = ({ clientField }) => {
return <CheckboxField field={clientField} />
export const CustomCheckboxFieldServer: CheckboxFieldServerComponent = (props) => {
const path = (props?.path || props?.field?.name || '') as string
return <CheckboxField field={props?.clientField} path={path} />
}

View File

@@ -3,9 +3,6 @@ import type { CheckboxFieldLabelServerComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent = ({
clientField,
label,
}) => {
return <FieldLabel field={clientField} label={label} />
export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent = (props) => {
return <FieldLabel label={props?.label} path={props?.path} />
}

View File

@@ -4,6 +4,6 @@ import type { DateFieldClientComponent } from 'payload'
import { DateTimeField } from '@payloadcms/ui'
import React from 'react'
export const CustomDateFieldClient: DateFieldClientComponent = ({ field }) => {
return <DateTimeField field={field} />
export const CustomDateFieldClient: DateFieldClientComponent = (props) => {
return <DateTimeField field={props?.field} path={props?.path} />
}

View File

@@ -4,6 +4,6 @@ import type { DateFieldLabelClientComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomDateFieldLabelClient: DateFieldLabelClientComponent = ({ field }) => {
return <FieldLabel field={field} />
export const CustomDateFieldLabelClient: DateFieldLabelClientComponent = (props) => {
return <FieldLabel label={props?.label} path={props?.path} />
}

View File

@@ -3,6 +3,7 @@ import type React from 'react'
import { DateTimeField } from '@payloadcms/ui'
export const CustomDateFieldServer: DateFieldServerComponent = ({ clientField }) => {
return <DateTimeField field={clientField} />
export const CustomDateFieldServer: DateFieldServerComponent = (props) => {
const path = (props?.path || props?.field?.name || '') as string
return <DateTimeField field={props?.clientField} path={path} />
}

View File

@@ -3,6 +3,6 @@ import type { DateFieldLabelServerComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomDateFieldLabelServer: DateFieldLabelServerComponent = ({ clientField }) => {
return <FieldLabel field={clientField} />
export const CustomDateFieldLabelServer: DateFieldLabelServerComponent = (props) => {
return <FieldLabel label={props?.label} />
}

View File

@@ -4,6 +4,6 @@ import type { EmailFieldClientComponent } from 'payload'
import { EmailField } from '@payloadcms/ui'
import React from 'react'
export const CustomEmailFieldClient: EmailFieldClientComponent = ({ field }) => {
return <EmailField field={field} />
export const CustomEmailFieldClient: EmailFieldClientComponent = (props) => {
return <EmailField field={props?.field} path={props?.path} />
}

View File

@@ -4,6 +4,6 @@ import type { EmailFieldLabelClientComponent } from 'payload'
import { FieldLabel } from '@payloadcms/ui'
import React from 'react'
export const CustomEmailFieldLabelClient: EmailFieldLabelClientComponent = ({ field }) => {
return <FieldLabel field={field} />
export const CustomEmailFieldLabelClient: EmailFieldLabelClientComponent = (props) => {
return <FieldLabel label={props?.label} />
}

Some files were not shown because too many files have changed in this diff Show More