Skip to content

Add anchored awareness positions#720

Draft
zhyd1997 wants to merge 4 commits into
nextfrom
awareness-anchored-positions-1778945364
Draft

Add anchored awareness positions#720
zhyd1997 wants to merge 4 commits into
nextfrom
awareness-anchored-positions-1778945364

Conversation

@zhyd1997
Copy link
Copy Markdown
Member

Summary

Adds editor-agnostic anchored cursor and selection support to @softmaple/awareness, plus a separate pointer presence field with explicit coordinate space. Consumers can now resolve opaque anchors at render time or locally remap offset-only remote positions after document changes without rebroadcasting.

Changes

  • Added PositionAnchor, PointerPosition, PresenceResolver, and PositionMapper types.
  • Added local-only remapRemotePositions, pointer state operations, useRemapRemotePositions, and useUpdatePointer.
  • Wired resolver support through PresenceProvider and usePeerCursors.
  • Extended WebSocket and BroadcastChannel validation/wire clear handling for anchors and pointer presence.
  • Added resolver/remap exports and documented anchored positions and pointer usage.
  • Added tests for remapping behavior, resolver rendering, pointer updates, provider local-only remaps, and validation.

Validation

  • pnpm --filter @softmaple/awareness typecheck
  • pnpm --filter @softmaple/awareness check
  • pnpm --filter @softmaple/awareness test
  • pnpm --filter @softmaple/awareness build

Note: the package-specific Storybook/Vitest project ran as part of the awareness test command. The softmaple-awareness-storybook-mcp tools referenced in package instructions were not exposed in this Codex session.

Co-authored-by: Codex <noreply@openai.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 16, 2026

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

Project Deployment Actions Updated (UTC)
softmaple-playground Ready Ready Preview, Comment May 16, 2026 4:09pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
softmaple-editor Skipped Skipped May 16, 2026 4:09pm
softmaple-web Skipped Skipped May 16, 2026 4:09pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a0625091-2018-4c95-a215-091b96ee3bea

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch awareness-anchored-positions-1778945364

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 and usage tips.

@chromatic-com
Copy link
Copy Markdown

chromatic-com Bot commented May 16, 2026

Warning

Testing paused

Monthly snapshot limit reached. Update your plan to get more snapshots and resume testing.

zhyd1997 and others added 3 commits May 17, 2026 00:00
Anchored cursor/selection resolution was only invoked inside usePeerCursors,
so consumers rendering selections from useOthers/useOther saw raw,
unresolved offsets. Extract the resolution into a shared applyResolver
helper, apply it when deriving `others` in PresenceProvider, and apply it
on demand in useOther and the includeSelf branch of usePeersInBlock. A
resolver returning null now clears just the affected field instead of
dropping the peer entirely, so the user stays in the roster.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The WebSocket and BroadcastChannel adapters carried byte-identical copies of
isRecord / isCursorPosition / isSelectionRange / isPointerPosition. Lift
them into src/types/guards.ts so the wire shape lives in one place and
future fields cannot drift between adapters. The adapter-specific
isPresenceUser and update-payload guards stay local since they validate
different field sets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The provider was constructing a throwaway PresenceState (with dummy
activities and connectionStatus) just to invoke the state-shaped helper,
and then mutating presenceRef.current inside the setPresence updater.
Add a Map-level remapRemoteUsers helper next to remapRemotePositions, call
that from the provider, and let the existing useEffect([presence]) keep
presenceRef in sync — the mutation inside the updater was a side-effect
that concurrent renders could replay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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