comment-mode 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -8,22 +8,23 @@ Embeddable commenting for live prototypes (Next.js / React). Add a comment overl
8
8
  npm install comment-mode
9
9
  ```
10
10
 
11
- ### Basic usage
11
+ ### Basic usage (recommended)
12
+
13
+ Wrap your app with **Commentator** so the comment surface (tap-to-pin area) and overlay are wired correctly with one component:
12
14
 
13
15
  ```tsx
14
- import { CommentProvider, CommentOverlay } from "comment-mode";
16
+ import { Commentator } from "comment-mode";
15
17
 
16
18
  function App() {
17
19
  return (
18
- <CommentProvider
20
+ <Commentator
19
21
  config={{
20
22
  projectSlug: "my-prototype",
21
23
  surfaceId: window.location.pathname,
22
24
  }}
23
25
  >
24
- {/* your prototype UI */}
25
- <CommentOverlay />
26
- </CommentProvider>
26
+ {/* your prototype UI — taps here create comment pins when comment mode is on */}
27
+ </Commentator>
27
28
  );
28
29
  }
29
30
  ```
@@ -33,9 +34,27 @@ function App() {
33
34
  - **projectSlug** — Identifies your project (e.g. `"my-prototype"`).
34
35
  - **surfaceId** — Identifies the page/surface (e.g. `window.location.pathname`).
35
36
 
37
+ Optional: **position** — `"left"` or `"right"` (default `"right"`) for where the comment panel appears.
38
+
39
+ ### Advanced: separate Provider, Surface, and Overlay
40
+
41
+ If you need custom layout (e.g. only a specific canvas should receive pins), use the building blocks directly. **You must wrap the tappable area with CommentSurface** or taps will not create pins:
42
+
43
+ ```tsx
44
+ import { CommentProvider, CommentSurface, CommentOverlay } from "comment-mode";
45
+
46
+ <CommentProvider config={config}>
47
+ <CommentSurface>
48
+ {/* only this area receives tap-to-pin */}
49
+ </CommentSurface>
50
+ <CommentOverlay position="right" />
51
+ </CommentProvider>
52
+ ```
36
53
 
37
54
  ### What you get
38
55
 
39
- - **CommentProvider** — Wraps your app and connects to the Comment Mode API.
40
- - **CommentOverlay** — Fullscreen overlay with a toggle, comment pins (threads), and a panel to view/add comments.
56
+ - **Commentator** — One wrapper: Provider + Surface + Overlay (use for minimal setup).
57
+ - **CommentProvider** — Connects to the Comment Mode API.
58
+ - **CommentSurface** — The area that receives taps to create pins; must wrap the content that should be commentable.
59
+ - **CommentOverlay** — Toggle, pins, and comment panel.
41
60
  - **useComments** — Hook for creating threads, loading comments, and adding replies.
package/dist/index.d.mts CHANGED
@@ -3,6 +3,7 @@ import { SupabaseClient, User } from '@supabase/supabase-js';
3
3
 
4
4
  type CommentConfig = {
5
5
  projectSlug: string;
6
+ /** Identifies the surface (e.g. pathname or pathname+search for tabs). */
6
7
  surfaceId: string;
7
8
  /**
8
9
  * Optional override for the Comment Mode API base URL.
@@ -17,6 +18,26 @@ type CommentProviderProps = {
17
18
  };
18
19
  declare function CommentProvider(props: CommentProviderProps): JSX.Element;
19
20
 
21
+ type CommentatorProps = {
22
+ /** Project and surface identifiers + optional API URL. */
23
+ config: CommentConfig;
24
+ /** Where the comment panel appears. Default `"right"`. */
25
+ position?: "left" | "right";
26
+ /** Optional style for the surface wrapper (the tappable area for pins). */
27
+ surfaceStyle?: React.CSSProperties;
28
+ /** Optional class for the surface wrapper. */
29
+ surfaceClassName?: string;
30
+ children: React.ReactNode;
31
+ };
32
+ /**
33
+ * All-in-one wrapper: Provider + Surface + Overlay. Use this for minimal setup
34
+ * so the area that receives taps is correctly wired for creating pins.
35
+ *
36
+ * If you need to customize layout (e.g. surface only around a canvas), use
37
+ * CommentProvider, CommentSurface, and CommentOverlay separately.
38
+ */
39
+ declare function Commentator(props: CommentatorProps): JSX.Element;
40
+
20
41
  type CommentSurfaceProps = {
21
42
  children?: React.ReactNode;
22
43
  style?: React.CSSProperties;
@@ -44,7 +65,16 @@ type ThreadAnchor = {
44
65
  type Thread = {
45
66
  id: string;
46
67
  anchor: ThreadAnchor;
68
+ /** CSS selector to resolve the anchored element within the surface. When set, pin is shown only when element exists and visible. */
69
+ anchorSelector?: string | null;
70
+ /** Where within the element the user clicked (0..1). Used with anchorSelector so the pin stays at the exact click spot. */
71
+ anchorRelative?: {
72
+ x: number;
73
+ y: number;
74
+ } | null;
47
75
  status: "open" | "resolved";
76
+ /** Avatar URL of the first comment author (for pin display). */
77
+ firstCommentAuthorAvatarUrl?: string | null;
48
78
  };
49
79
  type Comment = {
50
80
  id: string;
@@ -52,6 +82,7 @@ type Comment = {
52
82
  body: string;
53
83
  createdAt?: string;
54
84
  authorName?: string | null;
85
+ authorAvatarUrl?: string | null;
55
86
  };
56
87
 
57
88
  declare function useComments(): {
@@ -60,9 +91,9 @@ declare function useComments(): {
60
91
  commentsByThread: Record<string, Comment[]>;
61
92
  isLoading: boolean;
62
93
  error: Error | null;
63
- createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null) => Promise<Thread>;
94
+ createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null, anchorElement?: HTMLElement | null, initialAuthorAvatarUrl?: string | null) => Promise<Thread>;
64
95
  loadComments: (threadId: string) => Promise<void>;
65
- addComment: (threadId: string, body: string, authorName?: string | null) => Promise<Comment>;
96
+ addComment: (threadId: string, body: string, authorName?: string | null, authorAvatarUrl?: string | null) => Promise<Comment>;
66
97
  deleteThread: (threadId: string) => Promise<void>;
67
98
  };
68
99
 
@@ -74,6 +105,8 @@ type AuthContextValue = {
74
105
  isReady: boolean;
75
106
  /** Resolved from GitHub: full_name, or username if name not set. Read-only. */
76
107
  displayName: string;
108
+ /** GitHub avatar URL from user_metadata, if available. */
109
+ avatarUrl: string | null;
77
110
  signInWithEmail: (email: string) => Promise<void>;
78
111
  signInWithGitHub: () => Promise<void>;
79
112
  signOut: () => Promise<void>;
@@ -81,4 +114,4 @@ type AuthContextValue = {
81
114
 
82
115
  declare function useCommentAuth(): AuthContextValue;
83
116
 
84
- export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, useCommentAuth, useComments };
117
+ export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, Commentator, type CommentatorProps, useCommentAuth, useComments };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { SupabaseClient, User } from '@supabase/supabase-js';
3
3
 
4
4
  type CommentConfig = {
5
5
  projectSlug: string;
6
+ /** Identifies the surface (e.g. pathname or pathname+search for tabs). */
6
7
  surfaceId: string;
7
8
  /**
8
9
  * Optional override for the Comment Mode API base URL.
@@ -17,6 +18,26 @@ type CommentProviderProps = {
17
18
  };
18
19
  declare function CommentProvider(props: CommentProviderProps): JSX.Element;
19
20
 
21
+ type CommentatorProps = {
22
+ /** Project and surface identifiers + optional API URL. */
23
+ config: CommentConfig;
24
+ /** Where the comment panel appears. Default `"right"`. */
25
+ position?: "left" | "right";
26
+ /** Optional style for the surface wrapper (the tappable area for pins). */
27
+ surfaceStyle?: React.CSSProperties;
28
+ /** Optional class for the surface wrapper. */
29
+ surfaceClassName?: string;
30
+ children: React.ReactNode;
31
+ };
32
+ /**
33
+ * All-in-one wrapper: Provider + Surface + Overlay. Use this for minimal setup
34
+ * so the area that receives taps is correctly wired for creating pins.
35
+ *
36
+ * If you need to customize layout (e.g. surface only around a canvas), use
37
+ * CommentProvider, CommentSurface, and CommentOverlay separately.
38
+ */
39
+ declare function Commentator(props: CommentatorProps): JSX.Element;
40
+
20
41
  type CommentSurfaceProps = {
21
42
  children?: React.ReactNode;
22
43
  style?: React.CSSProperties;
@@ -44,7 +65,16 @@ type ThreadAnchor = {
44
65
  type Thread = {
45
66
  id: string;
46
67
  anchor: ThreadAnchor;
68
+ /** CSS selector to resolve the anchored element within the surface. When set, pin is shown only when element exists and visible. */
69
+ anchorSelector?: string | null;
70
+ /** Where within the element the user clicked (0..1). Used with anchorSelector so the pin stays at the exact click spot. */
71
+ anchorRelative?: {
72
+ x: number;
73
+ y: number;
74
+ } | null;
47
75
  status: "open" | "resolved";
76
+ /** Avatar URL of the first comment author (for pin display). */
77
+ firstCommentAuthorAvatarUrl?: string | null;
48
78
  };
49
79
  type Comment = {
50
80
  id: string;
@@ -52,6 +82,7 @@ type Comment = {
52
82
  body: string;
53
83
  createdAt?: string;
54
84
  authorName?: string | null;
85
+ authorAvatarUrl?: string | null;
55
86
  };
56
87
 
57
88
  declare function useComments(): {
@@ -60,9 +91,9 @@ declare function useComments(): {
60
91
  commentsByThread: Record<string, Comment[]>;
61
92
  isLoading: boolean;
62
93
  error: Error | null;
63
- createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null) => Promise<Thread>;
94
+ createThread: (anchor: ThreadAnchor, initialCommentBody?: string, initialAuthorName?: string | null, anchorElement?: HTMLElement | null, initialAuthorAvatarUrl?: string | null) => Promise<Thread>;
64
95
  loadComments: (threadId: string) => Promise<void>;
65
- addComment: (threadId: string, body: string, authorName?: string | null) => Promise<Comment>;
96
+ addComment: (threadId: string, body: string, authorName?: string | null, authorAvatarUrl?: string | null) => Promise<Comment>;
66
97
  deleteThread: (threadId: string) => Promise<void>;
67
98
  };
68
99
 
@@ -74,6 +105,8 @@ type AuthContextValue = {
74
105
  isReady: boolean;
75
106
  /** Resolved from GitHub: full_name, or username if name not set. Read-only. */
76
107
  displayName: string;
108
+ /** GitHub avatar URL from user_metadata, if available. */
109
+ avatarUrl: string | null;
77
110
  signInWithEmail: (email: string) => Promise<void>;
78
111
  signInWithGitHub: () => Promise<void>;
79
112
  signOut: () => Promise<void>;
@@ -81,4 +114,4 @@ type AuthContextValue = {
81
114
 
82
115
  declare function useCommentAuth(): AuthContextValue;
83
116
 
84
- export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, useCommentAuth, useComments };
117
+ export { type CommentConfig, CommentOverlay, type CommentOverlayProps, CommentProvider, type CommentProviderProps, CommentSettings, CommentSurface, type CommentSurfaceProps, Commentator, type CommentatorProps, useCommentAuth, useComments };