@hamzasaleemorg/convex-comments 1.0.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +201 -0
  3. package/README.md +581 -0
  4. package/dist/client/_generated/_ignore.d.ts +1 -0
  5. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  6. package/dist/client/_generated/_ignore.js +3 -0
  7. package/dist/client/_generated/_ignore.js.map +1 -0
  8. package/dist/client/index.d.ts +745 -0
  9. package/dist/client/index.d.ts.map +1 -0
  10. package/dist/client/index.js +579 -0
  11. package/dist/client/index.js.map +1 -0
  12. package/dist/component/_generated/api.d.ts +44 -0
  13. package/dist/component/_generated/api.d.ts.map +1 -0
  14. package/dist/component/_generated/api.js +31 -0
  15. package/dist/component/_generated/api.js.map +1 -0
  16. package/dist/component/_generated/component.d.ts +673 -0
  17. package/dist/component/_generated/component.d.ts.map +1 -0
  18. package/dist/component/_generated/component.js +11 -0
  19. package/dist/component/_generated/component.js.map +1 -0
  20. package/dist/component/_generated/dataModel.d.ts +46 -0
  21. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  22. package/dist/component/_generated/dataModel.js +11 -0
  23. package/dist/component/_generated/dataModel.js.map +1 -0
  24. package/dist/component/_generated/server.d.ts +121 -0
  25. package/dist/component/_generated/server.d.ts.map +1 -0
  26. package/dist/component/_generated/server.js +78 -0
  27. package/dist/component/_generated/server.js.map +1 -0
  28. package/dist/component/convex.config.d.ts +3 -0
  29. package/dist/component/convex.config.d.ts.map +1 -0
  30. package/dist/component/convex.config.js +3 -0
  31. package/dist/component/convex.config.js.map +1 -0
  32. package/dist/component/lib.d.ts +17 -0
  33. package/dist/component/lib.d.ts.map +1 -0
  34. package/dist/component/lib.js +18 -0
  35. package/dist/component/lib.js.map +1 -0
  36. package/dist/component/messages.d.ts +173 -0
  37. package/dist/component/messages.d.ts.map +1 -0
  38. package/dist/component/messages.js +410 -0
  39. package/dist/component/messages.js.map +1 -0
  40. package/dist/component/reactions.d.ts +51 -0
  41. package/dist/component/reactions.d.ts.map +1 -0
  42. package/dist/component/reactions.js +191 -0
  43. package/dist/component/reactions.js.map +1 -0
  44. package/dist/component/schema.d.ts +274 -0
  45. package/dist/component/schema.d.ts.map +1 -0
  46. package/dist/component/schema.js +159 -0
  47. package/dist/component/schema.js.map +1 -0
  48. package/dist/component/threads.d.ts +110 -0
  49. package/dist/component/threads.d.ts.map +1 -0
  50. package/dist/component/threads.js +276 -0
  51. package/dist/component/threads.js.map +1 -0
  52. package/dist/component/typing.d.ts +31 -0
  53. package/dist/component/typing.d.ts.map +1 -0
  54. package/dist/component/typing.js +147 -0
  55. package/dist/component/typing.js.map +1 -0
  56. package/dist/component/zones.d.ts +63 -0
  57. package/dist/component/zones.d.ts.map +1 -0
  58. package/dist/component/zones.js +159 -0
  59. package/dist/component/zones.js.map +1 -0
  60. package/dist/react/AddComment.d.ts +57 -0
  61. package/dist/react/AddComment.d.ts.map +1 -0
  62. package/dist/react/AddComment.js +285 -0
  63. package/dist/react/AddComment.js.map +1 -0
  64. package/dist/react/Comment.d.ts +70 -0
  65. package/dist/react/Comment.d.ts.map +1 -0
  66. package/dist/react/Comment.js +259 -0
  67. package/dist/react/Comment.js.map +1 -0
  68. package/dist/react/Comments.d.ts +74 -0
  69. package/dist/react/Comments.d.ts.map +1 -0
  70. package/dist/react/Comments.js +108 -0
  71. package/dist/react/Comments.js.map +1 -0
  72. package/dist/react/CommentsProvider.d.ts +104 -0
  73. package/dist/react/CommentsProvider.d.ts.map +1 -0
  74. package/dist/react/CommentsProvider.js +98 -0
  75. package/dist/react/CommentsProvider.js.map +1 -0
  76. package/dist/react/ReactionPicker.d.ts +28 -0
  77. package/dist/react/ReactionPicker.d.ts.map +1 -0
  78. package/dist/react/ReactionPicker.js +56 -0
  79. package/dist/react/ReactionPicker.js.map +1 -0
  80. package/dist/react/Thread.d.ts +84 -0
  81. package/dist/react/Thread.d.ts.map +1 -0
  82. package/dist/react/Thread.js +124 -0
  83. package/dist/react/Thread.js.map +1 -0
  84. package/dist/react/TypingIndicator.d.ts +25 -0
  85. package/dist/react/TypingIndicator.d.ts.map +1 -0
  86. package/dist/react/TypingIndicator.js +99 -0
  87. package/dist/react/TypingIndicator.js.map +1 -0
  88. package/dist/react/index.d.ts +15 -0
  89. package/dist/react/index.d.ts.map +1 -0
  90. package/dist/react/index.js +15 -0
  91. package/dist/react/index.js.map +1 -0
  92. package/package.json +106 -0
  93. package/src/client/_generated/_ignore.ts +1 -0
  94. package/src/client/index.ts +813 -0
  95. package/src/component/_generated/api.ts +60 -0
  96. package/src/component/_generated/component.ts +784 -0
  97. package/src/component/_generated/dataModel.ts +60 -0
  98. package/src/component/_generated/server.ts +156 -0
  99. package/src/component/convex.config.ts +3 -0
  100. package/src/component/lib.ts +57 -0
  101. package/src/component/messages.ts +476 -0
  102. package/src/component/reactions.ts +222 -0
  103. package/src/component/schema.ts +169 -0
  104. package/src/component/threads.ts +319 -0
  105. package/src/component/typing.ts +168 -0
  106. package/src/component/zones.ts +180 -0
  107. package/src/react/AddComment.tsx +463 -0
  108. package/src/react/Comment.tsx +519 -0
  109. package/src/react/Comments.tsx +276 -0
  110. package/src/react/CommentsProvider.tsx +197 -0
  111. package/src/react/ReactionPicker.tsx +95 -0
  112. package/src/react/Thread.tsx +336 -0
  113. package/src/react/TypingIndicator.tsx +144 -0
  114. package/src/react/index.ts +45 -0
@@ -0,0 +1,159 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server.js";
3
+ // ============================================================================
4
+ // Zone Validators
5
+ // ============================================================================
6
+ const zoneValidator = v.object({
7
+ _id: v.id("zones"),
8
+ _creationTime: v.number(),
9
+ entityId: v.string(),
10
+ metadata: v.optional(v.any()),
11
+ createdAt: v.number(),
12
+ });
13
+ // ============================================================================
14
+ // Zone Functions
15
+ // ============================================================================
16
+ /**
17
+ * Get or create a zone for an entity.
18
+ * This is the main entry point - lazily creates a zone if it doesn't exist.
19
+ */
20
+ export const getOrCreateZone = mutation({
21
+ args: {
22
+ entityId: v.string(),
23
+ metadata: v.optional(v.any()),
24
+ },
25
+ returns: v.id("zones"),
26
+ handler: async (ctx, args) => {
27
+ // Check if zone already exists
28
+ const existing = await ctx.db
29
+ .query("zones")
30
+ .withIndex("entityId", (q) => q.eq("entityId", args.entityId))
31
+ .first();
32
+ if (existing) {
33
+ return existing._id;
34
+ }
35
+ // Create new zone
36
+ const zoneId = await ctx.db.insert("zones", {
37
+ entityId: args.entityId,
38
+ metadata: args.metadata,
39
+ createdAt: Date.now(),
40
+ });
41
+ return zoneId;
42
+ },
43
+ });
44
+ /**
45
+ * List all zones with optional pagination.
46
+ */
47
+ export const listZones = query({
48
+ args: {
49
+ limit: v.optional(v.number()),
50
+ },
51
+ returns: v.array(zoneValidator),
52
+ handler: async (ctx, args) => {
53
+ const limit = args.limit ?? 100;
54
+ return await ctx.db.query("zones").take(limit);
55
+ },
56
+ });
57
+ /**
58
+ * Get a zone by entity ID (without creating).
59
+ */
60
+ export const getZone = query({
61
+ args: {
62
+ entityId: v.string(),
63
+ },
64
+ returns: v.union(v.null(), zoneValidator),
65
+ handler: async (ctx, args) => {
66
+ return await ctx.db
67
+ .query("zones")
68
+ .withIndex("entityId", (q) => q.eq("entityId", args.entityId))
69
+ .first();
70
+ },
71
+ });
72
+ /**
73
+ * Get a zone by its ID.
74
+ */
75
+ export const getZoneById = query({
76
+ args: {
77
+ zoneId: v.id("zones"),
78
+ },
79
+ returns: v.union(v.null(), zoneValidator),
80
+ handler: async (ctx, args) => {
81
+ return await ctx.db.get(args.zoneId);
82
+ },
83
+ });
84
+ /**
85
+ * Update zone metadata.
86
+ */
87
+ export const updateZoneMetadata = mutation({
88
+ args: {
89
+ zoneId: v.id("zones"),
90
+ metadata: v.any(),
91
+ },
92
+ returns: v.null(),
93
+ handler: async (ctx, args) => {
94
+ await ctx.db.patch(args.zoneId, {
95
+ metadata: args.metadata,
96
+ });
97
+ return null;
98
+ },
99
+ });
100
+ /**
101
+ * Delete a zone and all its threads/messages.
102
+ * Use with caution - this is a destructive operation.
103
+ */
104
+ export const deleteZone = mutation({
105
+ args: {
106
+ zoneId: v.id("zones"),
107
+ },
108
+ returns: v.object({
109
+ deletedThreads: v.number(),
110
+ deletedMessages: v.number(),
111
+ deletedReactions: v.number(),
112
+ }),
113
+ handler: async (ctx, args) => {
114
+ let deletedThreads = 0;
115
+ let deletedMessages = 0;
116
+ let deletedReactions = 0;
117
+ // Get all threads in this zone
118
+ const threads = await ctx.db
119
+ .query("threads")
120
+ .withIndex("zoneId", (q) => q.eq("zoneId", args.zoneId))
121
+ .collect();
122
+ for (const thread of threads) {
123
+ // Get all messages in this thread
124
+ const messages = await ctx.db
125
+ .query("messages")
126
+ .withIndex("threadId", (q) => q.eq("threadId", thread._id))
127
+ .collect();
128
+ for (const message of messages) {
129
+ // Delete reactions on this message
130
+ const reactions = await ctx.db
131
+ .query("reactions")
132
+ .withIndex("messageId", (q) => q.eq("messageId", message._id))
133
+ .collect();
134
+ for (const reaction of reactions) {
135
+ await ctx.db.delete(reaction._id);
136
+ deletedReactions++;
137
+ }
138
+ // Delete the message
139
+ await ctx.db.delete(message._id);
140
+ deletedMessages++;
141
+ }
142
+ // Delete typing indicators for this thread
143
+ const typingIndicators = await ctx.db
144
+ .query("typingIndicators")
145
+ .withIndex("threadId", (q) => q.eq("threadId", thread._id))
146
+ .collect();
147
+ for (const indicator of typingIndicators) {
148
+ await ctx.db.delete(indicator._id);
149
+ }
150
+ // Delete the thread
151
+ await ctx.db.delete(thread._id);
152
+ deletedThreads++;
153
+ }
154
+ // Delete the zone
155
+ await ctx.db.delete(args.zoneId);
156
+ return { deletedThreads, deletedMessages, deletedReactions };
157
+ },
158
+ });
159
+ //# sourceMappingURL=zones.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zones.js","sourceRoot":"","sources":["../../src/component/zones.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * AddComment Component
3
+ *
4
+ * Composer for adding new comments with mention autocomplete.
5
+ */
6
+ export interface MentionableUser {
7
+ /** User ID */
8
+ id: string;
9
+ /** Display name */
10
+ name: string;
11
+ /** Optional avatar URL */
12
+ avatar?: string;
13
+ }
14
+ export interface AddCommentProps {
15
+ /** Callback when a comment is submitted */
16
+ onSubmit?: (body: string, attachments?: Array<{
17
+ type: "url" | "file" | "image";
18
+ url: string;
19
+ name?: string;
20
+ }>) => void;
21
+ /** Callback when typing state changes */
22
+ onTypingChange?: (isTyping: boolean) => void;
23
+ /** List of users that can be mentioned */
24
+ mentionableUsers?: MentionableUser[];
25
+ /** Whether editing features are enabled */
26
+ allowEditing?: boolean;
27
+ /** Placeholder text */
28
+ placeholder?: string;
29
+ /** Initial value */
30
+ initialValue?: string;
31
+ /** Whether the composer is disabled */
32
+ disabled?: boolean;
33
+ /** Auto-focus on mount */
34
+ autoFocus?: boolean;
35
+ /** Minimum height of the textarea */
36
+ minHeight?: number;
37
+ /** CSS class name */
38
+ className?: string;
39
+ }
40
+ /**
41
+ * Comment composer with mention autocomplete support.
42
+ *
43
+ * Usage:
44
+ * ```tsx
45
+ * <AddComment
46
+ * onSubmit={(body) => addComment({ threadId, body })}
47
+ * onTypingChange={(isTyping) => setIsTyping({ threadId, isTyping })}
48
+ * mentionableUsers={[
49
+ * { id: "user1", name: "Alice" },
50
+ * { id: "user2", name: "Bob" },
51
+ * ]}
52
+ * placeholder="Write a comment..."
53
+ * />
54
+ * ```
55
+ */
56
+ export declare function AddComment({ onSubmit, onTypingChange, mentionableUsers, placeholder, initialValue, disabled, autoFocus, minHeight, className, }: AddCommentProps): import("react/jsx-runtime").JSX.Element;
57
+ //# sourceMappingURL=AddComment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddComment.d.ts","sourceRoot":"","sources":["../../src/react/AddComment.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,MAAM,WAAW,eAAe;IAC5B,cAAc;IACd,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CACP,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;QAC/B,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,KACD,IAAI,CAAC;IACV,yCAAyC;IACzC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,EACvB,QAAQ,EACR,cAAc,EACd,gBAAqB,EACrB,WAAkC,EAClC,YAAiB,EACjB,QAAgB,EAChB,SAAiB,EACjB,SAAc,EACd,SAAc,GACjB,EAAE,eAAe,2CA4XjB"}
@@ -0,0 +1,285 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * AddComment Component
4
+ *
5
+ * Composer for adding new comments with mention autocomplete.
6
+ */
7
+ import { useState, useRef, useCallback, useEffect } from "react";
8
+ import { useComments } from "./CommentsProvider";
9
+ // ============================================================================
10
+ // Component
11
+ // ============================================================================
12
+ /**
13
+ * Comment composer with mention autocomplete support.
14
+ *
15
+ * Usage:
16
+ * ```tsx
17
+ * <AddComment
18
+ * onSubmit={(body) => addComment({ threadId, body })}
19
+ * onTypingChange={(isTyping) => setIsTyping({ threadId, isTyping })}
20
+ * mentionableUsers={[
21
+ * { id: "user1", name: "Alice" },
22
+ * { id: "user2", name: "Bob" },
23
+ * ]}
24
+ * placeholder="Write a comment..."
25
+ * />
26
+ * ```
27
+ */
28
+ export function AddComment({ onSubmit, onTypingChange, mentionableUsers = [], placeholder = "Write a comment...", initialValue = "", disabled = false, autoFocus = false, minHeight = 60, className = "", }) {
29
+ const { userId, styles } = useComments();
30
+ const [body, setBody] = useState(initialValue);
31
+ const [isTyping, setIsTyping] = useState(false);
32
+ const textareaRef = useRef(null);
33
+ const typingTimeoutRef = useRef(null);
34
+ // Mention autocomplete state
35
+ const [showMentionPicker, setShowMentionPicker] = useState(false);
36
+ const [mentionQuery, setMentionQuery] = useState("");
37
+ const [mentionStartPos, setMentionStartPos] = useState(0);
38
+ const [selectedMentionIndex, setSelectedMentionIndex] = useState(0);
39
+ const mentionPickerRef = useRef(null);
40
+ // Filter mentionable users based on query
41
+ const filteredUsers = mentionableUsers.filter((user) => user.name.toLowerCase().includes(mentionQuery.toLowerCase()) ||
42
+ user.id.toLowerCase().includes(mentionQuery.toLowerCase()));
43
+ // Debounced typing indicator
44
+ const updateTypingState = useCallback((typing) => {
45
+ if (typing !== isTyping) {
46
+ setIsTyping(typing);
47
+ onTypingChange?.(typing);
48
+ }
49
+ }, [isTyping, onTypingChange]);
50
+ const handleChange = (e) => {
51
+ const value = e.target.value;
52
+ const cursorPos = e.target.selectionStart;
53
+ setBody(value);
54
+ // Check for mention trigger
55
+ if (mentionableUsers.length > 0) {
56
+ // Find the last @ before cursor that's not already complete
57
+ const textBeforeCursor = value.slice(0, cursorPos);
58
+ const lastAtIndex = textBeforeCursor.lastIndexOf("@");
59
+ if (lastAtIndex >= 0) {
60
+ const textAfterAt = textBeforeCursor.slice(lastAtIndex + 1);
61
+ // Check if there's no space after @ (still typing the mention)
62
+ if (!textAfterAt.includes(" ") && !textAfterAt.includes("\n")) {
63
+ setShowMentionPicker(true);
64
+ setMentionQuery(textAfterAt);
65
+ setMentionStartPos(lastAtIndex);
66
+ setSelectedMentionIndex(0);
67
+ }
68
+ else {
69
+ setShowMentionPicker(false);
70
+ }
71
+ }
72
+ else {
73
+ setShowMentionPicker(false);
74
+ }
75
+ }
76
+ // Start typing indicator
77
+ if (value.length > 0) {
78
+ updateTypingState(true);
79
+ // Clear existing timeout
80
+ if (typingTimeoutRef.current) {
81
+ clearTimeout(typingTimeoutRef.current);
82
+ }
83
+ // Set new timeout to stop typing
84
+ typingTimeoutRef.current = setTimeout(() => {
85
+ updateTypingState(false);
86
+ }, 2000);
87
+ }
88
+ else {
89
+ updateTypingState(false);
90
+ }
91
+ };
92
+ const insertMention = (user) => {
93
+ const beforeMention = body.slice(0, mentionStartPos);
94
+ const afterMention = body.slice(mentionStartPos + 1 + mentionQuery.length);
95
+ const newBody = `${beforeMention}@${user.id} ${afterMention}`;
96
+ setBody(newBody);
97
+ setShowMentionPicker(false);
98
+ setMentionQuery("");
99
+ // Focus textarea and set cursor position
100
+ if (textareaRef.current) {
101
+ const newCursorPos = mentionStartPos + user.id.length + 2; // +2 for @ and space
102
+ textareaRef.current.focus();
103
+ setTimeout(() => {
104
+ textareaRef.current?.setSelectionRange(newCursorPos, newCursorPos);
105
+ }, 0);
106
+ }
107
+ };
108
+ const handleSubmit = (e) => {
109
+ e.preventDefault();
110
+ if (!body.trim() || disabled)
111
+ return;
112
+ // Clear typing indicator
113
+ updateTypingState(false);
114
+ if (typingTimeoutRef.current) {
115
+ clearTimeout(typingTimeoutRef.current);
116
+ }
117
+ onSubmit?.(body.trim());
118
+ setBody("");
119
+ setShowMentionPicker(false);
120
+ // Reset textarea height
121
+ if (textareaRef.current) {
122
+ textareaRef.current.style.height = `${minHeight}px`;
123
+ }
124
+ };
125
+ const handleKeyDown = (e) => {
126
+ // Handle mention picker navigation
127
+ if (showMentionPicker && filteredUsers.length > 0) {
128
+ if (e.key === "ArrowDown") {
129
+ e.preventDefault();
130
+ setSelectedMentionIndex((prev) => prev < filteredUsers.length - 1 ? prev + 1 : prev);
131
+ return;
132
+ }
133
+ if (e.key === "ArrowUp") {
134
+ e.preventDefault();
135
+ setSelectedMentionIndex((prev) => (prev > 0 ? prev - 1 : prev));
136
+ return;
137
+ }
138
+ if (e.key === "Enter" || e.key === "Tab") {
139
+ e.preventDefault();
140
+ insertMention(filteredUsers[selectedMentionIndex]);
141
+ return;
142
+ }
143
+ if (e.key === "Escape") {
144
+ e.preventDefault();
145
+ setShowMentionPicker(false);
146
+ return;
147
+ }
148
+ }
149
+ // Submit on Enter (without Shift)
150
+ if (e.key === "Enter" && !e.shiftKey) {
151
+ e.preventDefault();
152
+ handleSubmit(e);
153
+ }
154
+ };
155
+ // Auto-resize textarea
156
+ useEffect(() => {
157
+ if (textareaRef.current) {
158
+ textareaRef.current.style.height = `${minHeight}px`;
159
+ textareaRef.current.style.height = `${Math.max(minHeight, textareaRef.current.scrollHeight)}px`;
160
+ }
161
+ }, [body, minHeight]);
162
+ // Cleanup typing timeout on unmount
163
+ useEffect(() => {
164
+ return () => {
165
+ if (typingTimeoutRef.current) {
166
+ clearTimeout(typingTimeoutRef.current);
167
+ }
168
+ if (isTyping) {
169
+ onTypingChange?.(false);
170
+ }
171
+ };
172
+ }, [isTyping, onTypingChange]);
173
+ // Close mention picker on click outside
174
+ useEffect(() => {
175
+ const handleClickOutside = (e) => {
176
+ if (mentionPickerRef.current &&
177
+ !mentionPickerRef.current.contains(e.target) &&
178
+ textareaRef.current &&
179
+ !textareaRef.current.contains(e.target)) {
180
+ setShowMentionPicker(false);
181
+ }
182
+ };
183
+ document.addEventListener("mousedown", handleClickOutside);
184
+ return () => document.removeEventListener("mousedown", handleClickOutside);
185
+ }, []);
186
+ if (!userId) {
187
+ return (_jsx("div", { className: className, style: {
188
+ padding: "12px 16px",
189
+ textAlign: "center",
190
+ color: "#6b7280",
191
+ fontSize: "13px",
192
+ }, children: "Sign in to comment" }));
193
+ }
194
+ return (_jsxs("form", { onSubmit: handleSubmit, className: `add-comment ${className}`, style: {
195
+ padding: "12px",
196
+ }, children: [_jsxs("div", { style: { position: "relative" }, children: [_jsx("textarea", { ref: textareaRef, value: body, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, autoFocus: autoFocus, style: {
197
+ width: "100%",
198
+ padding: "10px 12px",
199
+ paddingRight: "80px",
200
+ border: "1px solid #d1d5db",
201
+ borderRadius: styles?.borderRadius ?? "8px",
202
+ fontSize: "14px",
203
+ fontFamily: styles?.fontFamily ?? "inherit",
204
+ resize: "none",
205
+ minHeight: `${minHeight}px`,
206
+ outline: "none",
207
+ transition: "border-color 0.15s",
208
+ }, onFocus: (e) => {
209
+ e.target.style.borderColor = styles?.accentColor ?? "#3b82f6";
210
+ }, onBlur: (e) => {
211
+ e.target.style.borderColor = "#d1d5db";
212
+ } }), showMentionPicker && filteredUsers.length > 0 && (_jsx("div", { ref: mentionPickerRef, style: {
213
+ position: "absolute",
214
+ bottom: "100%",
215
+ left: "0",
216
+ right: "0",
217
+ marginBottom: "4px",
218
+ maxHeight: "200px",
219
+ overflowY: "auto",
220
+ backgroundColor: "#fff",
221
+ border: "1px solid #d1d5db",
222
+ borderRadius: "8px",
223
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
224
+ zIndex: 100,
225
+ }, children: filteredUsers.map((user, index) => (_jsxs("div", { onClick: () => insertMention(user), style: {
226
+ padding: "8px 12px",
227
+ cursor: "pointer",
228
+ display: "flex",
229
+ alignItems: "center",
230
+ gap: "8px",
231
+ backgroundColor: index === selectedMentionIndex
232
+ ? "#f3f4f6"
233
+ : "transparent",
234
+ }, onMouseEnter: () => setSelectedMentionIndex(index), children: [user.avatar ? (_jsx("img", { src: user.avatar, alt: user.name, style: {
235
+ width: "24px",
236
+ height: "24px",
237
+ borderRadius: "50%",
238
+ objectFit: "cover",
239
+ } })) : (_jsx("div", { style: {
240
+ width: "24px",
241
+ height: "24px",
242
+ borderRadius: "50%",
243
+ backgroundColor: "#e5e7eb",
244
+ display: "flex",
245
+ alignItems: "center",
246
+ justifyContent: "center",
247
+ fontSize: "12px",
248
+ fontWeight: 500,
249
+ color: "#6b7280",
250
+ }, children: user.name.charAt(0).toUpperCase() })), _jsxs("div", { children: [_jsx("div", { style: { fontWeight: 500, fontSize: "13px" }, children: user.name }), _jsxs("div", { style: { fontSize: "11px", color: "#9ca3af" }, children: ["@", user.id] })] })] }, user.id))) })), showMentionPicker && filteredUsers.length === 0 && mentionQuery.length > 0 && (_jsxs("div", { style: {
251
+ position: "absolute",
252
+ bottom: "100%",
253
+ left: "0",
254
+ right: "0",
255
+ marginBottom: "4px",
256
+ padding: "12px",
257
+ backgroundColor: "#fff",
258
+ border: "1px solid #d1d5db",
259
+ borderRadius: "8px",
260
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
261
+ color: "#9ca3af",
262
+ fontSize: "13px",
263
+ textAlign: "center",
264
+ }, children: ["No users found matching \"", mentionQuery, "\""] })), _jsx("button", { type: "submit", disabled: !body.trim() || disabled, style: {
265
+ position: "absolute",
266
+ right: "8px",
267
+ bottom: "8px",
268
+ padding: "6px 14px",
269
+ fontSize: "13px",
270
+ fontWeight: 500,
271
+ border: "none",
272
+ borderRadius: "6px",
273
+ backgroundColor: !body.trim() || disabled
274
+ ? "#e5e7eb"
275
+ : styles?.accentColor ?? "#3b82f6",
276
+ color: !body.trim() || disabled ? "#9ca3af" : "white",
277
+ cursor: !body.trim() || disabled ? "not-allowed" : "pointer",
278
+ transition: "background-color 0.15s",
279
+ }, children: "Send" })] }), _jsxs("div", { style: {
280
+ marginTop: "6px",
281
+ fontSize: "11px",
282
+ color: "#9ca3af",
283
+ }, children: ["Press Enter to send, Shift+Enter for new line", mentionableUsers.length > 0 && " • Type @ to mention"] })] }));
284
+ }
285
+ //# sourceMappingURL=AddComment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddComment.js","sourceRoot":"","sources":["../../src/react/AddComment.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Comment Component
3
+ *
4
+ * Displays a single comment/message with reactions and actions.
5
+ */
6
+ export interface MessageData {
7
+ message: {
8
+ _id: string;
9
+ threadId: string;
10
+ authorId: string;
11
+ body: string;
12
+ mentions: Array<{
13
+ userId: string;
14
+ start: number;
15
+ end: number;
16
+ }>;
17
+ links: Array<{
18
+ url: string;
19
+ start: number;
20
+ end: number;
21
+ }>;
22
+ attachments: Array<{
23
+ type: "url" | "file" | "image";
24
+ url: string;
25
+ name?: string;
26
+ mimeType?: string;
27
+ size?: number;
28
+ }>;
29
+ isEdited: boolean;
30
+ isDeleted: boolean;
31
+ createdAt: number;
32
+ editedAt?: number;
33
+ };
34
+ reactions: Array<{
35
+ emoji: string;
36
+ count: number;
37
+ users: string[];
38
+ includesMe: boolean;
39
+ }>;
40
+ }
41
+ export interface CommentProps {
42
+ /** Comment data */
43
+ comment: MessageData;
44
+ /** Whether this comment belongs to the current user */
45
+ mine?: boolean;
46
+ /** Callback when a reaction is toggled */
47
+ onToggleReaction?: (emoji: string) => void;
48
+ /** Callback when the comment is edited */
49
+ onEdit?: (newBody: string) => void;
50
+ /** Callback when the comment is deleted */
51
+ onDelete?: () => void;
52
+ /** CSS class name */
53
+ className?: string;
54
+ }
55
+ /**
56
+ * Component to display a single comment with reactions and actions.
57
+ *
58
+ * Usage:
59
+ * ```tsx
60
+ * <Comment
61
+ * comment={messageData}
62
+ * mine={true}
63
+ * onToggleReaction={(emoji) => toggleReaction({ messageId, emoji })}
64
+ * onEdit={(newBody) => editMessage({ messageId, body: newBody })}
65
+ * onDelete={() => deleteMessage({ messageId })}
66
+ * />
67
+ * ```
68
+ */
69
+ export declare function Comment({ comment, mine, onToggleReaction, onEdit, onDelete, className, }: CommentProps): import("react/jsx-runtime").JSX.Element;
70
+ //# sourceMappingURL=Comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Comment.d.ts","sourceRoot":"","sources":["../../src/react/Comment.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE;QACL,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAChE,KAAK,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC1D,WAAW,EAAE,KAAK,CAAC;YACf,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;YAC/B,GAAG,EAAE,MAAM,CAAC;YACZ,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,IAAI,CAAC,EAAE,MAAM,CAAC;SACjB,CAAC,CAAC;QACH,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,SAAS,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;KACvB,CAAC,CAAC;CACN;AAED,MAAM,WAAW,YAAY;IACzB,mBAAmB;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AA8GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EACpB,OAAO,EACP,IAAY,EACZ,gBAAgB,EAChB,MAAM,EACN,QAAQ,EACR,SAAc,GACjB,EAAE,YAAY,2CA4Ud"}