comment-mode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/index.d.mts +84 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +1116 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1109 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Commentator
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
## Comment Mode
|
|
2
|
+
|
|
3
|
+
Embeddable commenting for live prototypes (Next.js / React) that talks to your Comment Mode API.
|
|
4
|
+
|
|
5
|
+
### Pushing to GitHub
|
|
6
|
+
|
|
7
|
+
The project is already a git repo with an initial commit. To put it on GitHub:
|
|
8
|
+
|
|
9
|
+
1. **Create a new repository** on [GitHub](https://github.com/new): name it e.g. `commentator` (or `comment-mode`). Do **not** initialize with a README, .gitignore, or license—they already exist locally.
|
|
10
|
+
2. **Add the remote and push:**
|
|
11
|
+
```bash
|
|
12
|
+
git remote add origin https://github.com/YOUR_USERNAME/commentator.git
|
|
13
|
+
git branch -M main
|
|
14
|
+
git push -u origin main
|
|
15
|
+
```
|
|
16
|
+
Replace `YOUR_USERNAME` with your GitHub username (or org) and `commentator` with the repo name you chose.
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install comment-mode
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Basic usage
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { CommentProvider, CommentOverlay } from "comment-mode";
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<CommentProvider
|
|
32
|
+
config={{
|
|
33
|
+
projectSlug: "my-prototype",
|
|
34
|
+
surfaceId: window.location.pathname,
|
|
35
|
+
// Optional: override if you self-host the API
|
|
36
|
+
// apiBaseUrl: "https://api.commentmode.dev",
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{/* your prototype UI */}
|
|
40
|
+
<CommentOverlay />
|
|
41
|
+
</CommentProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The current implementation includes:
|
|
47
|
+
|
|
48
|
+
- **CommentProvider**: React context that holds configuration and talks to the Comment Mode HTTP API.
|
|
49
|
+
- **CommentOverlay**: A fullscreen overlay with a toggle button, persisted pins (threads), and a basic comments panel per pin.
|
|
50
|
+
- **useComments**: Hook exposing thread and comment APIs (create thread, load comments, add comment).
|
|
51
|
+
|
|
52
|
+
By default, the package calls the shared API at `https://api.commentmode.dev`. You can override with `apiBaseUrl` in the config if you run your own backend.
|
|
53
|
+
|
|
54
|
+
### Backend API sketch
|
|
55
|
+
|
|
56
|
+
At minimum, the backend behind `apiBaseUrl` should expose:
|
|
57
|
+
|
|
58
|
+
- **POST `/threads`**
|
|
59
|
+
- Request JSON:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"projectSlug": "my-prototype",
|
|
64
|
+
"surfaceId": "/some/route",
|
|
65
|
+
"anchorX": 0.42,
|
|
66
|
+
"anchorY": 0.17
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- Response JSON:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"id": "thread-uuid"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This backend can be implemented in a separate Next.js app that owns your Supabase credentials and inserts rows into `threads` (and later `comments`, `users`, etc.).
|
|
79
|
+
|
|
80
|
+
### Running the shared API (one backend for everyone)
|
|
81
|
+
|
|
82
|
+
If you want to run a **shared API** so that everyone who installs `comment-mode` can use it without running their own backend:
|
|
83
|
+
|
|
84
|
+
1. **Deploy the API**
|
|
85
|
+
The `commentator-api` folder in this repo is a Next.js app. Deploy it to [Vercel](https://vercel.com) (or similar):
|
|
86
|
+
- Connect your GitHub repo and set the **root directory** to `commentator-api` (or deploy from inside that folder).
|
|
87
|
+
- Add **Environment Variables** in the Vercel project:
|
|
88
|
+
- `SUPABASE_URL` — your Supabase project URL
|
|
89
|
+
- `SUPABASE_SERVICE_ROLE_KEY` — service role key (API uses this for threads/comments)
|
|
90
|
+
- `SUPABASE_ANON_KEY` — anon key (exposed to the client via `/auth/config` for Supabase Auth)
|
|
91
|
+
- Deploy. Add your custom domain (e.g. `api.commentmode.dev`) in Vercel so the API is served there.
|
|
92
|
+
|
|
93
|
+
2. **SDK default**
|
|
94
|
+
The package already defaults to `https://api.commentmode.dev` (see `src/constants.ts`). After you deploy the API to that URL, run `npm run build` and publish the package; anyone who installs `comment-mode` will use your shared API by default.
|
|
95
|
+
|
|
96
|
+
3. **Configure Supabase for production**
|
|
97
|
+
In **Supabase Dashboard → Authentication → URL Configuration**:
|
|
98
|
+
- **Site URL**: your main production app URL (e.g. `https://commentmode.dev` or the URL of a prototype that uses the SDK).
|
|
99
|
+
- **Redirect URLs**: add every origin where the commenting UI will run (e.g. `https://commentmode.dev`, `https://commentmode.dev/**`, and any other prototype domains). You can add more later as people use the SDK on different sites.
|
|
100
|
+
|
|
101
|
+
### Supabase URLs when going live
|
|
102
|
+
|
|
103
|
+
If you run your own API (e.g. the `commentator-api` in this repo) and use Supabase Auth (magic link, GitHub, etc.), you must configure URLs in the **Supabase Dashboard** so auth works on production:
|
|
104
|
+
|
|
105
|
+
1. **Authentication → URL Configuration**
|
|
106
|
+
- **Site URL**: set to your production app origin (e.g. `https://my-prototype.vercel.app`). This is the main URL where the SDK runs.
|
|
107
|
+
- **Redirect URLs**: add every origin where the commenting UI will load. For example:
|
|
108
|
+
- `https://my-prototype.vercel.app`
|
|
109
|
+
- `https://my-prototype.vercel.app/**`
|
|
110
|
+
- Any other prototype or app domains that use the same Comment Mode API.
|
|
111
|
+
|
|
112
|
+
Without these, Supabase will block redirects from localhost-only and auth (sign-in, magic link) will fail on deployed sites.
|
|
113
|
+
|
|
114
|
+
To build the package:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm install
|
|
118
|
+
npm run build
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
You can now link or publish the resulting package and import it into your Next.js prototypes.
|
|
122
|
+
|
|
123
|
+
### Publishing to npm
|
|
124
|
+
|
|
125
|
+
To publish this package as **comment-mode**:
|
|
126
|
+
|
|
127
|
+
1. **npm account**
|
|
128
|
+
Create an account at [npmjs.com](https://www.npmjs.com/signup) and log in with `npm login`.
|
|
129
|
+
|
|
130
|
+
2. **Point repo URLs to your repo**
|
|
131
|
+
In `package.json`, set `repository.url`, `bugs.url`, and `homepage` to your real GitHub (or other) repo (replace `your-org` with your org/username, e.g. `https://github.com/your-org/comment-mode`).
|
|
132
|
+
|
|
133
|
+
3. **Optional: LICENSE**
|
|
134
|
+
A root `LICENSE` file (e.g. MIT) is included; update the copyright holder if needed.
|
|
135
|
+
|
|
136
|
+
4. **Publish**
|
|
137
|
+
From the repo root:
|
|
138
|
+
```bash
|
|
139
|
+
npm run build
|
|
140
|
+
npm publish
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
5. **Later releases**
|
|
144
|
+
Bump `version` in `package.json` (e.g. `0.1.1`), then `npm publish` again.
|
|
145
|
+
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SupabaseClient, User } from '@supabase/supabase-js';
|
|
3
|
+
|
|
4
|
+
type CommentConfig = {
|
|
5
|
+
projectSlug: string;
|
|
6
|
+
surfaceId: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional override for the Comment Mode API base URL.
|
|
9
|
+
* Defaults to the shared API (see DEFAULT_API_BASE_URL in constants.ts).
|
|
10
|
+
*/
|
|
11
|
+
apiBaseUrl?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CommentProviderProps = {
|
|
15
|
+
config: CommentConfig;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
};
|
|
18
|
+
declare function CommentProvider(props: CommentProviderProps): JSX.Element;
|
|
19
|
+
|
|
20
|
+
type CommentSurfaceProps = {
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
className?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Wraps the area that can receive comment pins. When comment mode is on,
|
|
27
|
+
* mouse move highlights the element under the cursor and click creates a thread.
|
|
28
|
+
* Pins are rendered inside the surface so they scroll with the content.
|
|
29
|
+
* Must be used inside CommentProvider and wrap the same DOM that CommentOverlay covers.
|
|
30
|
+
*/
|
|
31
|
+
declare function CommentSurface(props: CommentSurfaceProps): JSX.Element;
|
|
32
|
+
|
|
33
|
+
type CommentOverlayProps = {
|
|
34
|
+
position?: "left" | "right";
|
|
35
|
+
};
|
|
36
|
+
declare function CommentOverlay(props: CommentOverlayProps): JSX.Element;
|
|
37
|
+
|
|
38
|
+
declare function CommentSettings(): JSX.Element;
|
|
39
|
+
|
|
40
|
+
type ThreadAnchor = {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
};
|
|
44
|
+
type Thread = {
|
|
45
|
+
id: string;
|
|
46
|
+
anchor: ThreadAnchor;
|
|
47
|
+
status: "open" | "resolved";
|
|
48
|
+
};
|
|
49
|
+
type Comment = {
|
|
50
|
+
id: string;
|
|
51
|
+
threadId: string;
|
|
52
|
+
body: string;
|
|
53
|
+
createdAt?: string;
|
|
54
|
+
authorName?: string | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
declare function useComments(): {
|
|
58
|
+
config: CommentConfig;
|
|
59
|
+
threads: Thread[];
|
|
60
|
+
commentsByThread: Record<string, Comment[]>;
|
|
61
|
+
isLoading: boolean;
|
|
62
|
+
error: Error | null;
|
|
63
|
+
createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null) => Promise<Thread>;
|
|
64
|
+
loadComments: (threadId: string) => Promise<void>;
|
|
65
|
+
addComment: (threadId: string, body: string, authorName?: string | null) => Promise<Comment>;
|
|
66
|
+
deleteThread: (threadId: string) => Promise<void>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type AuthUser = Pick<User, "id" | "email">;
|
|
70
|
+
type AuthContextValue = {
|
|
71
|
+
supabase: SupabaseClient | null;
|
|
72
|
+
user: AuthUser | null;
|
|
73
|
+
accessToken: string | null;
|
|
74
|
+
isReady: boolean;
|
|
75
|
+
/** Resolved from GitHub: full_name, or username if name not set. Read-only. */
|
|
76
|
+
displayName: string;
|
|
77
|
+
signInWithEmail: (email: string) => Promise<void>;
|
|
78
|
+
signInWithGitHub: () => Promise<void>;
|
|
79
|
+
signOut: () => Promise<void>;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
declare function useCommentAuth(): AuthContextValue;
|
|
83
|
+
|
|
84
|
+
export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, useCommentAuth, useComments };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SupabaseClient, User } from '@supabase/supabase-js';
|
|
3
|
+
|
|
4
|
+
type CommentConfig = {
|
|
5
|
+
projectSlug: string;
|
|
6
|
+
surfaceId: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional override for the Comment Mode API base URL.
|
|
9
|
+
* Defaults to the shared API (see DEFAULT_API_BASE_URL in constants.ts).
|
|
10
|
+
*/
|
|
11
|
+
apiBaseUrl?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CommentProviderProps = {
|
|
15
|
+
config: CommentConfig;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
};
|
|
18
|
+
declare function CommentProvider(props: CommentProviderProps): JSX.Element;
|
|
19
|
+
|
|
20
|
+
type CommentSurfaceProps = {
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
className?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Wraps the area that can receive comment pins. When comment mode is on,
|
|
27
|
+
* mouse move highlights the element under the cursor and click creates a thread.
|
|
28
|
+
* Pins are rendered inside the surface so they scroll with the content.
|
|
29
|
+
* Must be used inside CommentProvider and wrap the same DOM that CommentOverlay covers.
|
|
30
|
+
*/
|
|
31
|
+
declare function CommentSurface(props: CommentSurfaceProps): JSX.Element;
|
|
32
|
+
|
|
33
|
+
type CommentOverlayProps = {
|
|
34
|
+
position?: "left" | "right";
|
|
35
|
+
};
|
|
36
|
+
declare function CommentOverlay(props: CommentOverlayProps): JSX.Element;
|
|
37
|
+
|
|
38
|
+
declare function CommentSettings(): JSX.Element;
|
|
39
|
+
|
|
40
|
+
type ThreadAnchor = {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
};
|
|
44
|
+
type Thread = {
|
|
45
|
+
id: string;
|
|
46
|
+
anchor: ThreadAnchor;
|
|
47
|
+
status: "open" | "resolved";
|
|
48
|
+
};
|
|
49
|
+
type Comment = {
|
|
50
|
+
id: string;
|
|
51
|
+
threadId: string;
|
|
52
|
+
body: string;
|
|
53
|
+
createdAt?: string;
|
|
54
|
+
authorName?: string | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
declare function useComments(): {
|
|
58
|
+
config: CommentConfig;
|
|
59
|
+
threads: Thread[];
|
|
60
|
+
commentsByThread: Record<string, Comment[]>;
|
|
61
|
+
isLoading: boolean;
|
|
62
|
+
error: Error | null;
|
|
63
|
+
createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null) => Promise<Thread>;
|
|
64
|
+
loadComments: (threadId: string) => Promise<void>;
|
|
65
|
+
addComment: (threadId: string, body: string, authorName?: string | null) => Promise<Comment>;
|
|
66
|
+
deleteThread: (threadId: string) => Promise<void>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type AuthUser = Pick<User, "id" | "email">;
|
|
70
|
+
type AuthContextValue = {
|
|
71
|
+
supabase: SupabaseClient | null;
|
|
72
|
+
user: AuthUser | null;
|
|
73
|
+
accessToken: string | null;
|
|
74
|
+
isReady: boolean;
|
|
75
|
+
/** Resolved from GitHub: full_name, or username if name not set. Read-only. */
|
|
76
|
+
displayName: string;
|
|
77
|
+
signInWithEmail: (email: string) => Promise<void>;
|
|
78
|
+
signInWithGitHub: () => Promise<void>;
|
|
79
|
+
signOut: () => Promise<void>;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
declare function useCommentAuth(): AuthContextValue;
|
|
83
|
+
|
|
84
|
+
export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, useCommentAuth, useComments };
|