Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Comments

feat(richtext-lexical): unify lexical nested fields with document form state#15683

Draft
AlessioGr wants to merge 27 commits intomainfrom
feat/lexical-form-state-parent
Draft

feat(richtext-lexical): unify lexical nested fields with document form state#15683
AlessioGr wants to merge 27 commits intomainfrom
feat/lexical-form-state-parent

Conversation

@AlessioGr
Copy link
Member

Fixes#10942

Before

Lexical nodes with nested fields (blocks, inline blocks, links, uploads) were fully isolated from the parent document's form system. Each node type managed its own form lifecycle: block and inline block components rendered their own<Form> component directly on the page, with their owninitialState built via a dedicatedbuildInitialState utility, their own state reducer, and their ownonChange hooks to sync field changes back into the Lexical node viaeditor.update(). Links and uploads did the same when their editing drawers opened.

This meant every node with sub-fields was effectively a mini-document with its own form context and submission flow that we had to handle manually - completely separate from the parent document form. From the perspective of Payload's form system, these fields didn't exist:useAllFormFields(),useFormFields(), and other form hooks couldn't see them. They were buried inside the rich text field's serialized JSON value.

After

Nested Lexical fields now live in the parent document's form state, just like array fields, standard blocks, and top-level fields. A lexical block's text field sits atlexicalField.{nodeId}.fieldName in the same flatFormState map. The node ID is the bridge between the freeform Lexical JSON tree and the flat form state - it's the one stable identifier every node with sub-fields already has. Drawers read from and write to the parent form state directly; thedata prop onFieldsDrawer has been removed entirely.

Why

Consistency and simplicity. Nested Lexical fields are Payload fields - they're defined with the same field config, validated the same way, stored the same way. There was no reason for them to be invisible to the rest of the form system. This change makes them first-class fields, which means any component, plugin, or custom hook can read and write Lexical sub-fields using standard form hooks. It also simplifies the client-side architecture: node components no longer need to manage their own state lifecycle,.

How

A newbuildFormState method on theRichTextAdapter interface lets the Lexical adapter hook into the existing form state pipeline. During server-side form state construction, the adapter walks the serialized Lexical tree, finds nodes with sub-fields via feature-providedgetSubFieldsData andgetSchemaPath functions, and calls the standarditerateFields utility to populate form state entries under{richTextPath}.{nodeId}.*. This works similarly to howgenerateSchemaMap already works for the schema map - just now for form state.

On save, abeforeChange hook merges flat form state values back into the Lexical JSON tree before persistence, using the samegetSubFieldsData map. Any feature that registers sub-fields automatically participates in both directions.

On the client, node components no longer receive full field data objects fromdecorate(). They receive only structural identifiers (blockType,id,relationTo,value) and read user-editable field data from the parent form state via standard hooks.getFields() andgetData() have been renamed togetStaleFields() andgetStaleData(), as form state is the source of truth and the editor state for the node fields will be stale until the form state is synced back, which happens in the beforeChange hook.

Links are a special case: as anElementNode, Lexical renders their DOM from internal node data. A targeted sync writes field values back to the link node viaeditor.update() on drawer submit, keeping rendering current.

damnsamn and swheeler7 reacted with hooray emoji
@github-actions
Copy link
Contributor

github-actionsbot commentedFeb 19, 2026
edited
Loading

📦 esbuild Bundle Analysis for payload

This analysis was generated byesbuild-bundle-analyzer. 🤖

Meta FileOut FileSize (raw)Note
packages/next/meta_index.jsonesbuild/index.js950.94 KB✅ No change
packages/payload/meta_index.jsonesbuild/index.js1.32 MB✅ No change
packages/payload/meta_shared.jsonesbuild/exports/shared.js168.55 KB✅ No change
packages/richtext-lexical/meta_client.jsonesbuild/exports/client_optimized/index.js277.34 KB✅ -4.44 KB (-1.6%)
packages/ui/meta_client.jsonesbuild/exports/client_optimized/index.js1.18 MB⚠️ +222 B (+0.0%)
packages/ui/meta_shared.jsonesbuild/exports/shared_optimized/index.js16.32 KB✅ No change
Largest pathsThese visualization shows top 20 largest paths in the bundle.

Meta file: packages/next/meta_index.json, Out file: esbuild/index.js

PathSize
../../node_modules${{\color{Goldenrod}{ ████████████████████▌ }}}$ 82.3%, 779.13 KB
dist/views/Version${{\color{Goldenrod}{ █▎ }}}$ 5.4%, 51.27 KB
dist/views/Dashboard${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 17.16 KB
dist/views/Document${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 16.59 KB
dist/views/List${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 11.38 KB
dist/views/Root${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 9.03 KB
dist/views/Versions${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 6.16 KB
dist/views/API${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.08 KB
dist/elements/Nav${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.96 KB
dist/views/Account${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.54 KB
dist/elements/DocumentHeader${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.81 KB
dist/views/Login${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.40 KB
dist/views/ForgotPassword${{\color{Goldenrod}{ }}}$ 0.3%, 3.09 KB
dist/layouts/Root${{\color{Goldenrod}{ }}}$ 0.3%, 2.91 KB
dist/views/CreateFirstUser${{\color{Goldenrod}{ }}}$ 0.3%, 2.81 KB
dist/templates/Default${{\color{Goldenrod}{ }}}$ 0.3%, 2.63 KB
dist/views/BrowseByFolder${{\color{Goldenrod}{ }}}$ 0.3%, 2.61 KB
dist/views/CollectionFolders${{\color{Goldenrod}{ }}}$ 0.3%, 2.44 KB
dist/views/ResetPassword${{\color{Goldenrod}{ }}}$ 0.3%, 2.40 KB
dist/views/Logout${{\color{Goldenrod}{ }}}$ 0.2%, 1.94 KB
(other)${{\color{Goldenrod}{ ████▍ }}}$ 17.7%, 167.13 KB

Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js

PathSize
../../node_modules${{\color{Goldenrod}{ ████████████████▉ }}}$ 67.7%, 887.23 KB
dist/fields/hooks${{\color{Goldenrod}{ ▊ }}}$ 3.3%, 43.59 KB
dist/collections/operations${{\color{Goldenrod}{ ▊ }}}$ 3.0%, 39.77 KB
dist/versions/migrations${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 18.50 KB
dist/auth/operations${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 15.74 KB
dist/globals/operations${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 13.17 KB
dist/fields/config${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.84 KB
dist/queues/operations${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.80 KB
dist/utilities/configToJSONSchema.js${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 12.21 KB
dist/fields/validations.js${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.54 KB
dist/bin/generateImportMap${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.77 KB
dist/collections/config${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 8.35 KB
dist/index.js${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.69 KB
dist/uploads/fetchAPI-multipart${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.67 KB
dist/database/migrations${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.54 KB
dist/config/orderable${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.83 KB
dist/collections/endpoints${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.22 KB
dist/config/sanitize.js${{\color{Goldenrod}{ }}}$ 0.4%, 5.58 KB
dist/auth/strategies${{\color{Goldenrod}{ }}}$ 0.4%, 5.50 KB
dist/auth/endpoints${{\color{Goldenrod}{ }}}$ 0.4%, 5.42 KB
(other)${{\color{Goldenrod}{ ████████ }}}$ 32.3%, 422.44 KB

Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js

PathSize
../../node_modules${{\color{Goldenrod}{ ███████████████████▎ }}}$ 77.1%, 127.13 KB
dist/fields/validations.js${{\color{Goldenrod}{ █▌ }}}$ 6.4%, 10.54 KB
dist/config/orderable${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 3.13 KB
dist/fields/baseFields${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 2.79 KB
dist/utilities/deepCopyObject.js${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 2.54 KB
dist/auth/cookies.js${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 1.55 KB
dist/utilities/flattenTopLevelFields.js${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 1.42 KB
dist/fields/config${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.28 KB
dist/utilities/getVersionsConfig.js${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 1.04 KB
dist/utilities/flattenAllFields.js${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 943 B
dist/folders/utils${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 916 B
dist/utilities/unflatten.js${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 779 B
dist/utilities/sanitizeUserDataForEmail.js${{\color{Goldenrod}{ }}}$ 0.4%, 713 B
dist/utilities/getFieldPermissions.js${{\color{Goldenrod}{ }}}$ 0.4%, 651 B
dist/collections/config${{\color{Goldenrod}{ }}}$ 0.3%, 570 B
dist/bin/generateImportMap${{\color{Goldenrod}{ }}}$ 0.3%, 561 B
dist/auth/sessions.js${{\color{Goldenrod}{ }}}$ 0.3%, 525 B
dist/fields/getFieldPaths.js${{\color{Goldenrod}{ }}}$ 0.3%, 485 B
dist/utilities/getSafeRedirect.js${{\color{Goldenrod}{ }}}$ 0.3%, 423 B
dist/utilities/deepMerge.js${{\color{Goldenrod}{ }}}$ 0.3%, 413 B
(other)${{\color{Goldenrod}{ █████▋ }}}$ 22.9%, 37.78 KB

Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

PathSize
dist/lexical/plugins${{\color{Goldenrod}{ ██▉ }}}$ 11.7%, 32.00 KB
dist/features/blocks${{\color{Goldenrod}{ ██▊ }}}$ 11.0%, 30.17 KB
dist/lexical/ui${{\color{Goldenrod}{ ██▏ }}}$ 8.9%, 24.36 KB
dist/features/experimental_table${{\color{Goldenrod}{ ██▏ }}}$ 8.6%, 23.70 KB
dist/packages/@lexical${{\color{Goldenrod}{ █▋ }}}$ 6.9%, 18.99 KB
dist/features/link${{\color{Goldenrod}{ █▋ }}}$ 6.7%, 18.38 KB
dist/features/toolbars${{\color{Goldenrod}{ █▋ }}}$ 6.5%, 17.75 KB
dist/features/upload${{\color{Goldenrod}{ █▎ }}}$ 5.1%, 14.00 KB
dist/features/textState${{\color{Goldenrod}{ █ }}}$ 4.0%, 11.08 KB
dist/features/relationship${{\color{Goldenrod}{ ▊ }}}$ 3.3%, 9.03 KB
dist/lexical/utils${{\color{Goldenrod}{ ▊ }}}$ 3.1%, 8.49 KB
dist/features/debug${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 7.39 KB
dist/features/converters${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 7.05 KB
dist/utilities/fieldsDrawer${{\color{Goldenrod}{ ▌ }}}$ 2.3%, 6.38 KB
dist/lexical/config${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 5.08 KB
dist/features/lists${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 5.00 KB
dist/lexical/LexicalEditor.js${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 3.47 KB
dist/features/format${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 3.46 KB
dist/lexical/theme${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 2.62 KB
dist/features/indent${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.50 KB
(other)${{\color{Goldenrod}{ ██████████████████████ }}}$ 88.3%, 242.06 KB

Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

PathSize
../../node_modules${{\color{Goldenrod}{ ████████████▍ }}}$ 49.5%, 578.95 KB
dist/elements/FolderView${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 29.37 KB
dist/elements/BulkUpload${{\color{Goldenrod}{ ▌ }}}$ 2.4%, 27.63 KB
dist/elements/WhereBuilder${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 17.27 KB
dist/views/Edit${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 16.74 KB
dist/fields/Relationship${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.78 KB
dist/elements/Table${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.77 KB
dist/forms/Form${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.31 KB
dist/fields/Upload${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 14.24 KB
dist/fields/Blocks${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 13.69 KB
dist/elements/QueryPresets${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 10.36 KB
dist/elements/PublishButton${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 9.06 KB
dist/providers/Folders${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.47 KB
dist/elements/LivePreview${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.38 KB
dist/elements/ListHeader${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.99 KB
dist/elements/HTMLDiff${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.82 KB
dist/fields/Array${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.73 KB
dist/views/CollectionFolder${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.50 KB
dist/views/List${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.35 KB
dist/elements/ReactSelect${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.34 KB
(other)${{\color{Goldenrod}{ ████████████▋ }}}$ 50.5%, 590.47 KB

Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js

PathSize
dist/graphics/Logo${{\color{Goldenrod}{ █████ }}}$ 20.0%, 3.12 KB
../../node_modules${{\color{Goldenrod}{ ████▎ }}}$ 17.0%, 2.65 KB
dist/graphics/Icon${{\color{Goldenrod}{ ██▍ }}}$ 9.8%, 1.52 KB
dist/utilities/formatDocTitle${{\color{Goldenrod}{ ██▏ }}}$ 8.5%, 1.32 KB
dist/providers/TableColumns${{\color{Goldenrod}{ █▍ }}}$ 5.5%, 862 B
dist/utilities/groupNavItems.js${{\color{Goldenrod}{ █▎ }}}$ 5.2%, 814 B
dist/utilities/getGlobalData.js${{\color{Goldenrod}{ █▏ }}}$ 4.9%, 762 B
dist/utilities/api.js${{\color{Goldenrod}{ █▏ }}}$ 4.8%, 756 B
dist/elements/Translation${{\color{Goldenrod}{ ▊ }}}$ 3.2%, 493 B
dist/utilities/handleTakeOver.js${{\color{Goldenrod}{ ▋ }}}$ 2.8%, 440 B
dist/utilities/traverseForLocalizedFields.js${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 399 B
dist/elements/withMergedProps${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 339 B
dist/utilities/getVisibleEntities.js${{\color{Goldenrod}{ ▌ }}}$ 2.1%, 329 B
dist/utilities/getNavGroups.js${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 301 B
dist/elements/WithServerSideProps${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 232 B
dist/utilities/handleGoBack.js${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 180 B
dist/fields/mergeFieldStyles.js${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 159 B
dist/utilities/handleBackToDashboard.js${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 152 B
dist/forms/Form${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 147 B
dist/utilities/abortAndIgnore.js${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 146 B
(other)${{\color{Goldenrod}{ ████████████████████ }}}$ 80.0%, 12.51 KB
Details

Next to the size is how much the size has increased or decreased compared with the base branch of this PR.

  • ‼️: Size increased by 20% or more. Special attention should be given to this.
  • ⚠️: Size increased in acceptable range (lower than 20%).
  • ✅: No change or even downsized.
  • 🗑️: The out file is deleted: not found in base branch.
  • 🆕: The out file is newly found: will be added to base branch.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@jacobsfletchjacobsfletchAwaiting requested review from jacobsfletchjacobsfletch will be requested when the pull request is marked ready for reviewjacobsfletch is a code owner

@JarrodMFleschJarrodMFleschAwaiting requested review from JarrodMFleschJarrodMFlesch will be requested when the pull request is marked ready for reviewJarrodMFlesch is a code owner

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Lexical Block fields are not accessible via schema path provided byuseAllFormFields and related React Hooks

1 participant

@AlessioGr

[8]ページ先頭

©2009-2026 Movatter.jp