Skip to content

Commit b8898ee

Browse files
committed
Merge branch 'main' into feat/multiple-fallback-locales
2 parents dcb36f6 + 79b2557 commit b8898ee

File tree

245 files changed

+6385
-1967
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

245 files changed

+6385
-1967
lines changed

.github/ISSUE_TEMPLATE/DOCUMENTATION_ISSUE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name: Documentation Issue
33
about: Suggest fix to Payload documentation
44
labels: 'documentation'
5+
assignees: 'zubricks'
56
---
67

78
# Documentation Issue

.github/workflows/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ jobs:
286286
- group-by
287287
- folders
288288
- hooks
289+
- lexical__collections___LexicalFullyFeatured
290+
- lexical__collections__OnDemandForm
289291
- lexical__collections__Lexical__e2e__main
290292
- lexical__collections__Lexical__e2e__blocks
291293
- lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts
@@ -424,6 +426,8 @@ jobs:
424426
- group-by
425427
- folders
426428
- hooks
429+
- lexical__collections___LexicalFullyFeatured
430+
- lexical__collections__OnDemandForm
427431
- lexical__collections__Lexical__e2e__main
428432
- lexical__collections__Lexical__e2e__blocks
429433
- lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,27 @@
269269
"outputCapture": "std",
270270
"request": "launch",
271271
"type": "node-terminal"
272+
},
273+
{
274+
"name": "Debug GraphQL Schema Generation",
275+
"type": "node",
276+
"request": "launch",
277+
"program": "${workspaceFolder}/test/generateGraphQLSchema.ts",
278+
"args": ["graphql"],
279+
"cwd": "${workspaceFolder}",
280+
"env": {
281+
"NODE_OPTIONS": "--no-deprecation --no-experimental-strip-types"
282+
},
283+
"runtimeArgs": [
284+
"--no-deprecation",
285+
"--no-experimental-strip-types",
286+
"--import",
287+
"@swc-node/register/esm-register"
288+
],
289+
"console": "integratedTerminal",
290+
"outputCapture": "std",
291+
"sourceMaps": true,
292+
"skipFiles": ["<node_internals>/**"]
272293
}
273294
],
274295
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387

docs/authentication/jwt.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,17 @@ export const UsersWithoutJWTs: CollectionConfig = {
5353
},
5454
}
5555
```
56+
57+
## External JWT Validation
58+
59+
When validating Payload-generated JWT tokens in external services, use the processed secret rather than your original secret key:
60+
61+
```ts
62+
import crypto from 'node:crypto'
63+
64+
const secret = crypto.createHash('sha256').update(process.env.PAYLOAD_SECRET).digest('hex').slice(0, 32)
65+
```
66+
67+
<Banner type="info">
68+
**Note:** Payload processes your secret using SHA-256 hash and takes the first 32 characters. This processed value is what's used for JWT operations, not your original secret.
69+
</Banner>

docs/configuration/overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ The following options are available:
7070
| **`admin`** | The configuration options for the Admin Panel, including Custom Components, Live Preview, etc. [More details](../admin/overview#admin-options). |
7171
| **`bin`** | Register custom bin scripts for Payload to execute. [More Details](#custom-bin-scripts). |
7272
| **`editor`** | The Rich Text Editor which will be used by `richText` fields. [More details](../rich-text/overview). |
73-
| **`experimental`** | Configure experimental features for Payload. These may be unstable and may change or be removed in future releases. [More details](../experimental). |
73+
| **`experimental`** | Configure experimental features for Payload. These may be unstable and may change or be removed in future releases. [More details](../experimental/overview). |
7474
| **`db`** \* | The Database Adapter which will be used by Payload. [More details](../database/overview). |
7575
| **`serverURL`** | A string used to define the absolute URL of your app. This includes the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port. |
7676
| **`collections`** | An array of Collections for Payload to manage. [More details](./collections). |

docs/experimental/overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Experimental Features
33
label: Overview
44
order: 10
5-
desc: Enable and configure experimental functionality within Payload. These featuresmay be unstable and may change or be removed without notice.
5+
desc: Enable and configure experimental functionality within Payload. These features may be unstable and may change or be removed without notice.
66
keywords: experimental, unstable, beta, preview, features, configuration, Payload, cms, headless, javascript, node, react, nextjs
77
---
88

docs/fields/blocks.mdx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,34 @@ As you build your own Block configs, you might want to store them in separate fi
389389
```ts
390390
import type { Block } from 'payload'
391391
```
392+
393+
## Conditional Blocks
394+
395+
Blocks can be conditionally enabled using the `filterOptions` property on the blocks field. It allows you to provide a function that returns which block slugs should be available based on the given context.
396+
397+
### Behavior
398+
399+
- `filterOptions` is re-evaluated as part of the form state request, whenever the document data changes.
400+
- If a block is present in the field but no longer allowed by `filterOptions`, a validation error will occur when saving.
401+
402+
### Example
403+
404+
```ts
405+
{
406+
name: 'blocksWithDynamicFilterOptions',
407+
type: 'blocks',
408+
filterOptions: ({ siblingData }) => {
409+
return siblingData?.enabledBlocks?.length
410+
? [siblingData.enabledBlocks] // allow only the matching block
411+
: true // allow all blocks if no value is set
412+
},
413+
blocks: [
414+
{ slug: 'block1', fields: [{ type: 'text', name: 'block1Text' }] },
415+
{ slug: 'block2', fields: [{ type: 'text', name: 'block2Text' }] },
416+
{ slug: 'block3', fields: [{ type: 'text', name: 'block3Text' }] },
417+
// ...
418+
],
419+
}
420+
```
421+
422+
In this example, the list of available blocks is determined by the enabledBlocks sibling field. If no value is set, all blocks remain available.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: Rendering On Demand
3+
label: Rendering On Demand
4+
order: 50
5+
desc: Rendering rich text on demand
6+
keywords: lexical, rich text, editor, headless cms, render, rendering
7+
---
8+
9+
Lexical in Payload is a **React Server Component (RSC)**. Historically that created three headaches: 1. You couldn't render the editor directly from the client. 2. Features like blocks, tables and link drawers require the server to know the shape of nested sub-fields at render time. If you tried to render on demand, the server didn't know those schemas. 3. The rich text field is designed to live inside a `Form`. For simple use cases, setting up a full form just to manage editor state was cumbersome.
10+
11+
To simplify rendering richtext on demand, <RenderLexical />, that renders a Lexical editor while still covering the full feature set. On mount, it calls a server action to render the editor on the server using the new `render-field` server function. That server render gives Lexical everything it needs (including nested field schemas) and returns a ready-to-hydrate editor.
12+
13+
<Banner type="warning">
14+
`RenderLexical` and the underlying `render-field` server function are
15+
experimental and may change in minor releases.
16+
</Banner>
17+
18+
## Inside an existing Form
19+
20+
If you have an existing Form and want to render a richtext field within it, you can use the `RenderLexical` component like this:
21+
22+
```tsx
23+
'use client'
24+
25+
import type { JSONFieldClientComponent } from 'payload'
26+
27+
import {
28+
buildEditorState,
29+
RenderLexical,
30+
} from '@payloadcms/richtext-lexical/client'
31+
32+
import { lexicalFullyFeaturedSlug } from '../../slugs.js'
33+
34+
export const Component: JSONFieldClientComponent = (args) => {
35+
return (
36+
<RenderLexical
37+
field={{
38+
name: 'myFieldName' /* Make sure this matches the field name present in your form */,
39+
}}
40+
initialValue={buildEditorState({ text: 'default value' })}
41+
schemaPath={`collection.${lexicalFullyFeaturedSlug}.richText`}
42+
/>
43+
)
44+
}
45+
```
46+
47+
## Outside of a Form (you control state)
48+
49+
```tsx
50+
'use client'
51+
52+
import type { DefaultTypedEditorState } from '@payloadcms/richtext-lexical'
53+
import type { JSONFieldClientComponent } from 'payload'
54+
55+
import {
56+
buildEditorState,
57+
RenderLexical,
58+
} from '@payloadcms/richtext-lexical/client'
59+
import React, { useState } from 'react'
60+
61+
import { lexicalFullyFeaturedSlug } from '../../slugs.js'
62+
63+
export const Component: JSONFieldClientComponent = (args) => {
64+
// Manually manage the editor state
65+
const [value, setValue] = useState<DefaultTypedEditorState | undefined>(() =>
66+
buildEditorState({ text: 'state default' }),
67+
)
68+
69+
const handleReset = React.useCallback(() => {
70+
setValue(buildEditorState({ text: 'state default' }))
71+
}, [])
72+
73+
return (
74+
<div>
75+
<RenderLexical
76+
field={{ name: 'myField' }}
77+
initialValue={buildEditorState({ text: 'default value' })}
78+
schemaPath={`collection.${lexicalFullyFeaturedSlug}.richText`}
79+
setValue={setValue as any}
80+
value={value}
81+
/>
82+
<button onClick={handleReset} style={{ marginTop: 8 }} type="button">
83+
Reset Editor State
84+
</button>
85+
</div>
86+
)
87+
}
88+
```
89+
90+
## Choosing the schemaPath
91+
92+
`schemaPath` tells the server which richText field to render. This gives the server the exact nested field schemas (blocks, relationship drawers, upload fields, tables, etc.).
93+
94+
Format:
95+
96+
- `collection.<collectionSlug>.<fieldPath>`
97+
- `global.<globalSlug>.<fieldPath>`
98+
99+
Example (top level): `collection.posts.richText`
100+
101+
Example (nested in a group/tab): `collection.posts.content.richText`
102+
103+
<Banner type="info">
104+
**Tip:** If your target editor lives deep in arrays/blocks and you're unsure of the exact path, you can define a **hidden top-level richText** purely as a "render anchor":
105+
106+
```ts
107+
{
108+
name: 'onDemandAnchor',
109+
type: 'richText',
110+
admin: { hidden: true }
111+
}
112+
```
113+
114+
Then use `schemaPath="collection.posts.onDemandAnchor"`
115+
116+
</Banner>

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@
147147
"@types/jest": "29.5.12",
148148
"@types/minimist": "1.2.5",
149149
"@types/node": "22.15.30",
150-
"@types/react": "19.1.8",
151-
"@types/react-dom": "19.1.6",
150+
"@types/react": "19.1.12",
151+
"@types/react-dom": "19.1.9",
152152
"@types/shelljs": "0.8.15",
153153
"chalk": "^4.1.2",
154154
"comment-json": "^4.2.3",
@@ -175,16 +175,16 @@
175175
"playwright": "1.54.1",
176176
"playwright-core": "1.54.1",
177177
"prettier": "3.5.3",
178-
"react": "19.1.0",
179-
"react-dom": "19.1.0",
178+
"react": "19.1.1",
179+
"react-dom": "19.1.1",
180180
"rimraf": "6.0.1",
181181
"sharp": "0.32.6",
182182
"shelljs": "0.8.5",
183183
"slash": "3.0.0",
184184
"sort-package-json": "^2.10.0",
185185
"swc-plugin-transform-remove-imports": "4.0.4",
186186
"tempy": "1.0.1",
187-
"tstyche": "^3.1.1",
187+
"tstyche": "3.5.0",
188188
"tsx": "4.19.2",
189189
"turbo": "^2.5.4",
190190
"typescript": "5.7.3"

packages/admin-bar/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
},
4343
"devDependencies": {
4444
"@payloadcms/eslint-config": "workspace:*",
45-
"@types/react": "19.1.8",
46-
"@types/react-dom": "19.1.6",
45+
"@types/react": "19.1.12",
46+
"@types/react-dom": "19.1.9",
4747
"payload": "workspace:*"
4848
},
4949
"peerDependencies": {

0 commit comments

Comments
 (0)