Skip to content

feat: add BlockPathMap with incremental updates#2261

Closed
christianhg wants to merge 2 commits intomainfrom
feat/block-path-map
Closed

feat: add BlockPathMap with incremental updates#2261
christianhg wants to merge 2 commits intomainfrom
feat/block-path-map

Conversation

@christianhg
Copy link
Copy Markdown
Member

@christianhg christianhg commented Feb 27, 2026

What changed

Removes the value wrapper and __inline flag from block objects and inline objects in the Slate tree. PT properties now live directly on Slate nodes.

// Before:
{ _type: 'image', _key: 'abc', children: [void-child], value: { asset: {...} }, __inline: false }

// After:
{ _type: 'image', _key: 'abc', children: [void-child], asset: {...} }

The void-child span stays in Slate's tree for cursor behavior — that's a Slate rendering concern, not a data concern. Everything else is pure PT.

Also adds BlockPathMap — an incremental key-to-path index on EditorSnapshot for O(1) block lookups.

Why

Foundation for container (nested block) support. With the tree PT-native, a container block is just an element with real children — no special wrapping, no void model to work around.

How

PT-native tree (18 files, -188 net lines):

  • types/slate.tsVoidElement replaced with ObjectElement
  • values.tstoSlateBlock/fromSlateBlock spread PT properties directly
  • apply-operation-to-portable-text.ts — removed all value/__inline unwrapping
  • operation-to-patches.ts — properties read directly from nodes
  • applyPatch.ts — patches applied directly to nodes
  • slate-plugin.schema.tsisInline uses schema only
  • render.element.tsx / render.inline-object.tsx — schema-based inline detection
  • 4 operation files — insert/set/unset/delete all work with direct properties

BlockPathMap:

  • snapshot.blockPathMap.get(keyPath) — returns the full Slate path
  • snapshot.blockPathMap.getIndex(keyPath) — returns the block's index within its parent
  • Incremental updates via applyOperation()
  • blockIndexMap preserved on snapshot for backward compatibility

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
portable-text-editor-documentation Ready Ready Preview, Comment Feb 27, 2026 4:51pm
portable-text-example-basic Ready Ready Preview, Comment Feb 27, 2026 4:51pm
portable-text-playground Ready Ready Preview, Comment Feb 27, 2026 4:51pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 27, 2026

🦋 Changeset detected

Latest commit: 7e3cf64

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@portabletext/editor Minor
@portabletext/plugin-character-pair-decorator Major
@portabletext/plugin-emoji-picker Patch
@portabletext/plugin-input-rule Patch
@portabletext/plugin-markdown-shortcuts Major
@portabletext/plugin-one-line Major
@portabletext/plugin-paste-link Major
@portabletext/plugin-sdk-value Major
@portabletext/plugin-typeahead-picker Patch
@portabletext/plugin-typography Patch
@portabletext/toolbar Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Adds a new `BlockPathMap` class that maps serialized key-paths to indexed
paths. Unlike `EditorSnapshot.blockIndexMap` which rebuilds on every
structural operation, `BlockPathMap` uses incremental updates,
O(affected siblings) instead of O(total blocks).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant