Skip to content

fix(react): stop pulling @y/prosemirror into the default UI bundle#2902

Merged
nperez0111 merged 1 commit into
mainfrom
feat/conditional-attribution-marks
Jul 20, 2026
Merged

fix(react): stop pulling @y/prosemirror into the default UI bundle#2902
nperez0111 merged 1 commit into
mainfrom
feat/conditional-attribution-marks

Conversation

@nperez0111

@nperez0111 nperez0111 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

@blocknote/react's default UI imported AttributionExtension directly from @blocknote/core/y, which forces bundlers to resolve @y/prosemirror/@y/y even for editors that never enable collaboration.

Rationale

Every consumer of BlockNoteView (via BlockNoteDefaultUI) hit this import at build/runtime, causing Could not resolve "@y/prosemirror" errors for non-collaborative apps that don't have those optional peer dependencies installed.

Changes

  • BlockNoteDefaultUI.tsx: look up the attribution extension via editor.getExtension("attribution") (string key) instead of importing the AttributionExtension value.
  • AttributionTooltipController.tsx: only import type from @blocknote/core/y (erased at build time), use the string-keyed useExtensionState("attribution", ...), and inline the two small DOM helpers it previously imported.
  • useExtension.ts: widen useExtensionState's plugin parameter to accept a string key while still inferring the extension's state type from the generic.

Impact

Non-collaborative editors no longer pull in @y/prosemirror/@y/y through @blocknote/react. No behavior change for apps using collaboration/attribution.

Testing

  • vp run lint — 0 errors
  • vp run test — all tests pass
  • vp run build — verified @blocknote/core/y no longer appears in packages/react/dist/blocknote-react.js

Fixes #2901

Summary by CodeRabbit

  • Bug Fixes

    • Improved attribution tooltip positioning across different anchor elements.
    • Improved attribution tooltip availability when the attribution extension is configured by name.
  • Refactor

    • Enhanced extension state handling to support extension names in addition to extension instances.

BlockNoteDefaultUI and AttributionTooltipController imported the
AttributionExtension value from @blocknote/core/y, which pulls in
@y/prosemirror even for editors without collaboration. Look up the
extension by its string key instead, and inline the two small DOM
helpers it needed, so the collaboration entry point is never resolved
unless the app actually uses it.

Fixes #2901
@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
blocknote Ready Ready Preview Jul 20, 2026 3:00pm
blocknote-website Ready Ready Preview Jul 20, 2026 3:00pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The React extension hook now accepts string identifiers. Attribution UI resolves the extension by "attribution", while the tooltip controller measures the anchor or its first child inline for floating positioning.

Changes

Attribution tooltip integration

Layer / File(s) Summary
String-based extension state lookup
packages/react/src/hooks/useExtension.ts
useExtensionState accepts string plugin identifiers and forwards them to useExtension.
Attribution tooltip extension and geometry
packages/react/src/components/AttributionTooltip/..., packages/react/src/editor/BlockNoteDefaultUI.tsx
Attribution UI uses the "attribution" identifier, and tooltip reference geometry is measured from the anchor or its first child.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

I’m a rabbit with a tooltip bright,
Measuring anchors just right.
By "attribution" I hop,
The floating box knows where to stop,
And UI blooms in gentle light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preventing @y/prosemirror from entering the default UI bundle.
Description check ✅ Passed The description includes the required summary, rationale, changes, impact, and testing sections; only optional sections are omitted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/conditional-attribution-marks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/react/src/components/AttributionTooltip/AttributionTooltipController.tsx (1)

42-68: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract shared logic for finding the target element.

The target element resolution logic is duplicated across getBoundingClientRect and getClientRects. Extracting this into a local helper function within the useMemo will improve readability and maintainability.

♻️ Proposed refactor
   const reference = useMemo<GenericPopoverReference | undefined>(
-    () =>
-      state
-        ? {
-            element: state.anchor,
-            getBoundingClientRect: () => {
-              const content = state.anchor.firstElementChild ?? state.anchor;
-              const rect = content.getBoundingClientRect();
-              const el =
-                rect.width || rect.height
-                  ? content
-                  : (content.firstElementChild ?? content);
-              return el.getBoundingClientRect();
-            },
-            getClientRects: () => {
-              const content = state.anchor.firstElementChild ?? state.anchor;
-              const rect = content.getBoundingClientRect();
-              const el =
-                rect.width || rect.height
-                  ? content
-                  : (content.firstElementChild ?? content);
-              return el.getClientRects();
-            },
-          }
-        : undefined,
+    () => {
+      if (!state) return undefined;
+      const getTargetElement = () => {
+        const content = state.anchor.firstElementChild ?? state.anchor;
+        const rect = content.getBoundingClientRect();
+        return rect.width || rect.height
+          ? content
+          : (content.firstElementChild ?? content);
+      };
+
+      return {
+        element: state.anchor,
+        getBoundingClientRect: () => getTargetElement().getBoundingClientRect(),
+        getClientRects: () => getTargetElement().getClientRects(),
+      };
+    },
     [state],
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/react/src/components/AttributionTooltip/AttributionTooltipController.tsx`
around lines 42 - 68, In the useMemo callback that creates reference, extract
the duplicated target-element resolution from getBoundingClientRect and
getClientRects into a local helper, then have both methods call it before
retrieving their respective geometry. Preserve the existing fallback behavior
using state.anchor, its first element child, and the child fallback when the
resolved content has no dimensions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/react/src/components/AttributionTooltip/AttributionTooltipController.tsx`:
- Around line 42-68: In the useMemo callback that creates reference, extract the
duplicated target-element resolution from getBoundingClientRect and
getClientRects into a local helper, then have both methods call it before
retrieving their respective geometry. Preserve the existing fallback behavior
using state.anchor, its first element child, and the child fallback when the
resolved content has no dimensions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5601ed66-4a49-4df4-8e07-6eb38fccc6aa

📥 Commits

Reviewing files that changed from the base of the PR and between e6e4c03 and b6e9477.

📒 Files selected for processing (3)
  • packages/react/src/components/AttributionTooltip/AttributionTooltipController.tsx
  • packages/react/src/editor/BlockNoteDefaultUI.tsx
  • packages/react/src/hooks/useExtension.ts

@pkg-pr-new

pkg-pr-new Bot commented Jul 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

@blocknote/ariakit

npm i https://pkg.pr.new/@blocknote/ariakit@2902

@blocknote/code-block

npm i https://pkg.pr.new/@blocknote/code-block@2902

@blocknote/core

npm i https://pkg.pr.new/@blocknote/core@2902

@blocknote/mantine

npm i https://pkg.pr.new/@blocknote/mantine@2902

@blocknote/react

npm i https://pkg.pr.new/@blocknote/react@2902

@blocknote/server-util

npm i https://pkg.pr.new/@blocknote/server-util@2902

@blocknote/shadcn

npm i https://pkg.pr.new/@blocknote/shadcn@2902

@blocknote/xl-ai

npm i https://pkg.pr.new/@blocknote/xl-ai@2902

@blocknote/xl-docx-exporter

npm i https://pkg.pr.new/@blocknote/xl-docx-exporter@2902

@blocknote/xl-email-exporter

npm i https://pkg.pr.new/@blocknote/xl-email-exporter@2902

@blocknote/xl-multi-column

npm i https://pkg.pr.new/@blocknote/xl-multi-column@2902

@blocknote/xl-odt-exporter

npm i https://pkg.pr.new/@blocknote/xl-odt-exporter@2902

@blocknote/xl-pdf-exporter

npm i https://pkg.pr.new/@blocknote/xl-pdf-exporter@2902

commit: b6e9477

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-20 15:06 UTC

@nperez0111
nperez0111 merged commit eaec090 into main Jul 20, 2026
28 checks passed
@nperez0111
nperez0111 deleted the feat/conditional-attribution-marks branch July 20, 2026 15:06
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.

Installing the latest Blocknote version 0.52.0 causes my application to break

1 participant