A headless React component library for Google Docs-style commenting and markdown highlighting. Provides precise positioning logic and markdown highlighting capabilities while leaving the UI implementation to the consumer.
npm install @examind/react-anchored-commentsA headless React component library for Google Docs-style commenting and markdown highlighting. Provides precise positioning logic and markdown highlighting capabilities while leaving the UI implementation to the consumer.
> ā ļø WARNING: Early Alpha Release
>
> This library is in early alpha stage. The API is not stable and may change significantly between versions.
> To avoid breaking changes, please install a specific version:
>
> ``bash`
> npm install --save-exact @examind/react-anchored-comments
>
>
> Do not rely on semver ranges (^, ~) until we reach v1.0.0.
- š Google Docs-style commenting system
- šÆ Precise text selection and highlighting
- šØ UI agnostic - bring your own components
- š¦ Lightweight and tree-shakeable
- šŖ Written in TypeScript
- ā” Framework agnostic positioning logic
`bash
npm install --save-exact @examind/react-anchored-comments
yarn add --save-exact @examind/react-anchored-comments
pnpm add --save-exact @examind/react-anchored-comments
`
`tsx
import {
AnchoredCommentsProvider,
CommentSection,
CommentView,
ContentSection,
ContentView,
Highlight,
NewComment,
} from '@examind/react-anchored-comments';
import type { CommentAnchor } from '@examind/react-anchored-comments';
const commentToAnchor = (comment: MessageComment) =>
({
id: comment.id,
selectionRange: comment.selectionRange,
}) satisfies CommentAnchor;
const commentsToAnchors = (comments: MessageComment[]) =>
comments.map(commentToAnchor);
function App() {
const messages: Message[] = [
{
id: '1',
content:
"Hi",
role: 'user',
},
{
id: '2',
content:
'Hello, how can I help you today?',
role: 'assistant',
},
const comments = [
{
id: 'comment-1',
messageId: '2',
content: 'First comment',
selectionRange: {
contentId: '2',
startOffset: 8,
endOffset: 20,
},
} satisfies MessageComment,
];
return (
{messages.map(message => (
Your markdown content goes here. Users can select text
and add comments to any part of it.
markdown={message.content}
anchors={commentsToAnchors(
comments.filter(
c => c.messageId === message.id,
),
)}
color="#fef2cd"
activeColor="#fcbc03"
/>
))}
{({ selectionRange, onAddSuccess, onCancel }) => (
New Comment Form
)}
{comments.map(comment => (
{({ isActive, onDeleteSuccess }) => (
Render comment here
)}
))}
);
}
`
Root component that provides commenting context and manages state.
Wrapper for all contents that can be commented on.
Wrapper for each markdown content block. Provides text selection.
Component for rendering markdown content with comments. Highlights text based on comments.
Wrapper for all comments.
Component for positioning each comment. You must provide your own comment rendering components.
`tsx`
import type {
CommentAnchor,
SelectionRange,
} from '@examind/react-anchored-comments';
This project uses npm workspaces with a monorepo structure:
``
react-anchored-comments/
āāā packages/
ā āāā core/ # Main library code
āāā demo/ # Demo application
`bash
$3
-
npm run build - Build the core library
- npm run dev - Run both core (watch mode) and demo
- npm run dev:core - Run core in watch mode
- npm run dev:demo - Run demo application$3
To test the library in a local project, you can use
pnpm link:`bash
In the plugin directory (packages/core)
cd packages/core
npm run build # Build your plugin first
npm linkIn your other project
npm link @examind/react-anchored-comments
`$3
To unlink the library:
`bash
In your other project
npm unlink @examind/react-anchored-commentsIn the plugin directory
npm unlink
`Publish
- Bump version in package.json
-
npm install
- Commit with message: Release {version, e.g. 0.1.6}`Contributions are welcome!
MIT Ā© EXAMIND