@sqlrooms/discuss 0.24.26 → 0.24.28-rc.1

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
@@ -126,7 +126,7 @@ import {useStoreWithDiscussion} from '@sqlrooms/discuss';
126
126
  function MyComponent() {
127
127
  // Get discussions
128
128
  const discussions = useStoreWithDiscussion(
129
- (state) => state.config.discuss.discussions,
129
+ (state) => state.discuss.config.discussions,
130
130
  );
131
131
 
132
132
  // Get actions
@@ -160,7 +160,7 @@ import {formatTimeRelative} from '@sqlrooms/utils';
160
160
 
161
161
  const DiscussionPanel = () => {
162
162
  const discussions = useStoreWithDiscussion(
163
- (state) => state.config.discuss.discussions,
163
+ (state) => state.discuss.config.discussions,
164
164
  );
165
165
 
166
166
  return (
@@ -226,7 +226,7 @@ function DataVisualization() {
226
226
  // Highlight related discussion when hovering over data
227
227
  const handleDataPointHover = (dataId: string) => {
228
228
  const discussions =
229
- useStoreWithDiscussion.getState().config.discuss.discussions;
229
+ useStoreWithDiscussion.getState().discuss.config.discussions;
230
230
  const relatedDiscussion = discussions.find((d) => d.anchorId === dataId);
231
231
  if (relatedDiscussion) {
232
232
  setHighlightedDiscussionId(relatedDiscussion.id);
@@ -118,166 +118,122 @@ export declare const Discussion: z.ZodObject<{
118
118
  }>;
119
119
  export type Discussion = z.infer<typeof Discussion>;
120
120
  export declare const DiscussSliceConfig: z.ZodObject<{
121
- discuss: z.ZodObject<{
122
- discussions: z.ZodArray<z.ZodObject<{
121
+ discussions: z.ZodArray<z.ZodObject<{
122
+ id: z.ZodString;
123
+ anchorId: z.ZodOptional<z.ZodString>;
124
+ rootComment: z.ZodObject<{
125
+ id: z.ZodString;
126
+ userId: z.ZodString;
127
+ text: z.ZodString;
128
+ timestamp: z.ZodDate;
129
+ } & {
130
+ parentId: z.ZodOptional<z.ZodString>;
131
+ }, "strip", z.ZodTypeAny, {
132
+ id: string;
133
+ userId: string;
134
+ text: string;
135
+ timestamp: Date;
136
+ parentId?: string | undefined;
137
+ }, {
138
+ id: string;
139
+ userId: string;
140
+ text: string;
141
+ timestamp: Date;
142
+ parentId?: string | undefined;
143
+ }>;
144
+ comments: z.ZodArray<z.ZodObject<{
123
145
  id: z.ZodString;
124
- anchorId: z.ZodOptional<z.ZodString>;
125
- rootComment: z.ZodObject<{
126
- id: z.ZodString;
127
- userId: z.ZodString;
128
- text: z.ZodString;
129
- timestamp: z.ZodDate;
130
- } & {
131
- parentId: z.ZodOptional<z.ZodString>;
132
- }, "strip", z.ZodTypeAny, {
133
- id: string;
134
- userId: string;
135
- text: string;
136
- timestamp: Date;
137
- parentId?: string | undefined;
138
- }, {
139
- id: string;
140
- userId: string;
141
- text: string;
142
- timestamp: Date;
143
- parentId?: string | undefined;
144
- }>;
145
- comments: z.ZodArray<z.ZodObject<{
146
- id: z.ZodString;
147
- userId: z.ZodString;
148
- text: z.ZodString;
149
- timestamp: z.ZodDate;
150
- } & {
151
- parentId: z.ZodOptional<z.ZodString>;
152
- }, "strip", z.ZodTypeAny, {
153
- id: string;
154
- userId: string;
155
- text: string;
156
- timestamp: Date;
157
- parentId?: string | undefined;
158
- }, {
159
- id: string;
160
- userId: string;
161
- text: string;
162
- timestamp: Date;
163
- parentId?: string | undefined;
164
- }>, "many">;
146
+ userId: z.ZodString;
147
+ text: z.ZodString;
148
+ timestamp: z.ZodDate;
149
+ } & {
150
+ parentId: z.ZodOptional<z.ZodString>;
165
151
  }, "strip", z.ZodTypeAny, {
166
152
  id: string;
167
- rootComment: {
168
- id: string;
169
- userId: string;
170
- text: string;
171
- timestamp: Date;
172
- parentId?: string | undefined;
173
- };
174
- comments: {
175
- id: string;
176
- userId: string;
177
- text: string;
178
- timestamp: Date;
179
- parentId?: string | undefined;
180
- }[];
181
- anchorId?: string | undefined;
153
+ userId: string;
154
+ text: string;
155
+ timestamp: Date;
156
+ parentId?: string | undefined;
182
157
  }, {
183
158
  id: string;
184
- rootComment: {
185
- id: string;
186
- userId: string;
187
- text: string;
188
- timestamp: Date;
189
- parentId?: string | undefined;
190
- };
191
- comments: {
192
- id: string;
193
- userId: string;
194
- text: string;
195
- timestamp: Date;
196
- parentId?: string | undefined;
197
- }[];
198
- anchorId?: string | undefined;
159
+ userId: string;
160
+ text: string;
161
+ timestamp: Date;
162
+ parentId?: string | undefined;
199
163
  }>, "many">;
200
164
  }, "strip", z.ZodTypeAny, {
201
- discussions: {
165
+ id: string;
166
+ rootComment: {
167
+ id: string;
168
+ userId: string;
169
+ text: string;
170
+ timestamp: Date;
171
+ parentId?: string | undefined;
172
+ };
173
+ comments: {
202
174
  id: string;
203
- rootComment: {
204
- id: string;
205
- userId: string;
206
- text: string;
207
- timestamp: Date;
208
- parentId?: string | undefined;
209
- };
210
- comments: {
211
- id: string;
212
- userId: string;
213
- text: string;
214
- timestamp: Date;
215
- parentId?: string | undefined;
216
- }[];
217
- anchorId?: string | undefined;
175
+ userId: string;
176
+ text: string;
177
+ timestamp: Date;
178
+ parentId?: string | undefined;
218
179
  }[];
180
+ anchorId?: string | undefined;
219
181
  }, {
220
- discussions: {
182
+ id: string;
183
+ rootComment: {
221
184
  id: string;
222
- rootComment: {
223
- id: string;
224
- userId: string;
225
- text: string;
226
- timestamp: Date;
227
- parentId?: string | undefined;
228
- };
229
- comments: {
230
- id: string;
231
- userId: string;
232
- text: string;
233
- timestamp: Date;
234
- parentId?: string | undefined;
235
- }[];
236
- anchorId?: string | undefined;
185
+ userId: string;
186
+ text: string;
187
+ timestamp: Date;
188
+ parentId?: string | undefined;
189
+ };
190
+ comments: {
191
+ id: string;
192
+ userId: string;
193
+ text: string;
194
+ timestamp: Date;
195
+ parentId?: string | undefined;
237
196
  }[];
238
- }>;
197
+ anchorId?: string | undefined;
198
+ }>, "many">;
239
199
  }, "strip", z.ZodTypeAny, {
240
- discuss: {
241
- discussions: {
200
+ discussions: {
201
+ id: string;
202
+ rootComment: {
203
+ id: string;
204
+ userId: string;
205
+ text: string;
206
+ timestamp: Date;
207
+ parentId?: string | undefined;
208
+ };
209
+ comments: {
242
210
  id: string;
243
- rootComment: {
244
- id: string;
245
- userId: string;
246
- text: string;
247
- timestamp: Date;
248
- parentId?: string | undefined;
249
- };
250
- comments: {
251
- id: string;
252
- userId: string;
253
- text: string;
254
- timestamp: Date;
255
- parentId?: string | undefined;
256
- }[];
257
- anchorId?: string | undefined;
211
+ userId: string;
212
+ text: string;
213
+ timestamp: Date;
214
+ parentId?: string | undefined;
258
215
  }[];
259
- };
216
+ anchorId?: string | undefined;
217
+ }[];
260
218
  }, {
261
- discuss: {
262
- discussions: {
219
+ discussions: {
220
+ id: string;
221
+ rootComment: {
222
+ id: string;
223
+ userId: string;
224
+ text: string;
225
+ timestamp: Date;
226
+ parentId?: string | undefined;
227
+ };
228
+ comments: {
263
229
  id: string;
264
- rootComment: {
265
- id: string;
266
- userId: string;
267
- text: string;
268
- timestamp: Date;
269
- parentId?: string | undefined;
270
- };
271
- comments: {
272
- id: string;
273
- userId: string;
274
- text: string;
275
- timestamp: Date;
276
- parentId?: string | undefined;
277
- }[];
278
- anchorId?: string | undefined;
230
+ userId: string;
231
+ text: string;
232
+ timestamp: Date;
233
+ parentId?: string | undefined;
279
234
  }[];
280
- };
235
+ anchorId?: string | undefined;
236
+ }[];
281
237
  }>;
282
238
  export type DiscussSliceConfig = z.infer<typeof DiscussSliceConfig>;
283
239
  export declare function createDefaultDiscussConfig(): DiscussSliceConfig;
@@ -297,6 +253,7 @@ export type DeleteItem = {
297
253
  export type DiscussSliceState = {
298
254
  discuss: {
299
255
  userId: string;
256
+ config: DiscussSliceConfig;
300
257
  /**
301
258
  * Submit content based on current UI state (add discussion, reply to discussion/comment, or edit).
302
259
  * This automatically handles state management and is the preferred way to submit content.
@@ -346,6 +303,10 @@ export type DiscussSliceState = {
346
303
  * Should be called after the user confirms deletion in the UI.
347
304
  */
348
305
  handleDeleteConfirm: () => void;
306
+ /**
307
+ * Sets the config for the discuss slice.
308
+ */
309
+ setConfig: (config: DiscussSliceConfig) => void;
349
310
  /**
350
311
  * Helper function to get the user ID of the entity being replied to.
351
312
  * Returns '' if no reply context is set, or the user ID if a valid reply context exists.
@@ -365,7 +326,7 @@ export type DiscussSliceState = {
365
326
  };
366
327
  };
367
328
  export type RoomStateWithDiscussion = RoomShellSliceState<BaseRoomConfig> & DiscussSliceState;
368
- export declare function createDiscussSlice<PC extends BaseRoomConfig & DiscussSliceConfig>({ userId }: {
329
+ export declare function createDiscussSlice<PC extends BaseRoomConfig>({ userId, }: {
369
330
  userId: string;
370
331
  }): StateCreator<DiscussSliceState>;
371
332
  type RoomConfigWithDiscuss = BaseRoomConfig & DiscussSliceConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussSlice.d.ts","sourceRoot":"","sources":["../src/DiscussSlice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DiscussSlice.d.ts","sourceRoot":"","sources":["../src/DiscussSlice.ts"],"names":[],"mappings":"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"}
@@ -21,23 +21,25 @@ export const Discussion = z.object({
21
21
  comments: z.array(Comment),
22
22
  });
23
23
  export const DiscussSliceConfig = z.object({
24
- discuss: z.object({
25
- discussions: z.array(Discussion),
26
- }),
24
+ discussions: z.array(Discussion),
27
25
  });
28
26
  export function createDefaultDiscussConfig() {
29
27
  return {
30
- discuss: {
31
- discussions: [],
32
- },
28
+ discussions: [],
33
29
  };
34
30
  }
35
- export function createDiscussSlice({ userId }) {
31
+ export function createDiscussSlice({ userId, }) {
36
32
  return createSlice((set, get) => ({
37
33
  discuss: {
38
34
  userId,
35
+ config: createDefaultDiscussConfig(),
39
36
  // Direct CRUD operations - These are exposed for advanced use cases
40
37
  // For normal usage with UI integration, prefer submitEdit
38
+ setConfig: (config) => {
39
+ set((state) => produce(state, (draft) => {
40
+ draft.discuss.config = config;
41
+ }));
42
+ },
41
43
  /**
42
44
  * Directly adds a new discussion without managing UI state.
43
45
  * For UI-integrated usage, prefer submitEdit.
@@ -57,7 +59,7 @@ export function createDiscussSlice({ userId }) {
57
59
  comments: [],
58
60
  };
59
61
  set((state) => produce(state, (draft) => {
60
- draft.config.discuss.discussions.push(newDiscussion);
62
+ draft.discuss.config.discussions.push(newDiscussion);
61
63
  }));
62
64
  },
63
65
  /**
@@ -66,9 +68,9 @@ export function createDiscussSlice({ userId }) {
66
68
  */
67
69
  removeDiscussion: (id) => {
68
70
  set((state) => produce(state, (draft) => {
69
- const index = draft.config.discuss.discussions.findIndex((a) => a.id === id);
71
+ const index = draft.discuss.config.discussions.findIndex((a) => a.id === id);
70
72
  if (index !== -1) {
71
- draft.config.discuss.discussions.splice(index, 1);
73
+ draft.discuss.config.discussions.splice(index, 1);
72
74
  }
73
75
  }));
74
76
  },
@@ -78,7 +80,7 @@ export function createDiscussSlice({ userId }) {
78
80
  */
79
81
  editDiscussion: (id, text) => {
80
82
  set((state) => produce(state, (draft) => {
81
- const discussion = draft.config.discuss.discussions.find((a) => a.id === id);
83
+ const discussion = draft.discuss.config.discussions.find((a) => a.id === id);
82
84
  if (discussion) {
83
85
  discussion.rootComment.text = text;
84
86
  }
@@ -97,7 +99,7 @@ export function createDiscussSlice({ userId }) {
97
99
  parentId,
98
100
  };
99
101
  set((state) => produce(state, (draft) => {
100
- const discussion = draft.config.discuss.discussions.find((a) => a.id === discussionId);
102
+ const discussion = draft.discuss.config.discussions.find((a) => a.id === discussionId);
101
103
  if (discussion) {
102
104
  discussion.comments.push(newComment);
103
105
  }
@@ -109,7 +111,7 @@ export function createDiscussSlice({ userId }) {
109
111
  */
110
112
  editComment: (discussionId, commentId, text) => {
111
113
  set((state) => produce(state, (draft) => {
112
- const discussion = draft.config.discuss.discussions.find((a) => a.id === discussionId);
114
+ const discussion = draft.discuss.config.discussions.find((a) => a.id === discussionId);
113
115
  if (discussion) {
114
116
  if (discussion.rootComment.id === commentId) {
115
117
  discussion.rootComment.text = text;
@@ -129,7 +131,7 @@ export function createDiscussSlice({ userId }) {
129
131
  */
130
132
  removeComment: (discussionId, commentId) => {
131
133
  set((state) => produce(state, (draft) => {
132
- const discussion = draft.config.discuss.discussions.find((a) => a.id === discussionId);
134
+ const discussion = draft.discuss.config.discussions.find((a) => a.id === discussionId);
133
135
  if (discussion) {
134
136
  // Cannot remove the root comment
135
137
  if (discussion.rootComment.id !== commentId) {
@@ -266,7 +268,7 @@ export function createDiscussSlice({ userId }) {
266
268
  getReplyToUserId: () => {
267
269
  const state = get();
268
270
  const { replyToItem } = state.discuss;
269
- const { discussions } = state.config.discuss;
271
+ const { discussions } = state.discuss.config;
270
272
  if (!replyToItem)
271
273
  return '';
272
274
  const discussion = discussions.find((a) => a.id === replyToItem.discussionId);
@@ -292,7 +294,7 @@ export function createDiscussSlice({ userId }) {
292
294
  getEditingItemText: () => {
293
295
  const state = get();
294
296
  const { editingItem } = state.discuss;
295
- const { discussions } = state.config.discuss;
297
+ const { discussions } = state.discuss.config;
296
298
  if (!editingItem)
297
299
  return '';
298
300
  // Look for the discussion
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussSlice.js","sourceRoot":"","sources":["../src/DiscussSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n createSlice,\n useBaseRoomShellStore,\n type RoomShellSliceState,\n type StateCreator,\n BaseRoomConfig,\n} from '@sqlrooms/room-shell';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\n// Base type with common fields\nexport const CommentBase = z.object({\n id: z.string().cuid2(),\n userId: z.string(),\n text: z.string(),\n timestamp: z.coerce.date(),\n});\nexport type CommentBase = z.infer<typeof CommentBase>;\n\n// Comment type extends base with parentId\nexport const Comment = CommentBase.extend({\n parentId: z.string().optional(),\n});\nexport type Comment = z.infer<typeof Comment>;\n\n// Discussion is a container with a rootComment and collection of reply comments\nexport const Discussion = z.object({\n id: z.string().cuid2(),\n anchorId: z.string().optional(),\n rootComment: Comment,\n comments: z.array(Comment),\n});\nexport type Discussion = z.infer<typeof Discussion>;\n\nexport const DiscussSliceConfig = z.object({\n discuss: z.object({\n discussions: z.array(Discussion),\n }),\n});\nexport type DiscussSliceConfig = z.infer<typeof DiscussSliceConfig>;\n\nexport function createDefaultDiscussConfig(): DiscussSliceConfig {\n return {\n discuss: {\n discussions: [],\n },\n };\n}\n\n// UI state for discussions\nexport type ReplyToItem = {\n discussionId: string;\n commentId?: string;\n};\n\nexport type EditingItem = {\n discussionId: string;\n commentId?: string;\n};\n\nexport type DeleteItem = {\n discussionId: string;\n commentId?: string;\n itemType: string;\n};\n\nexport type DiscussSliceState = {\n discuss: {\n userId: string;\n\n // UI-connected actions - preferred API for most use cases\n /**\n * Submit content based on current UI state (add discussion, reply to discussion/comment, or edit).\n * This automatically handles state management and is the preferred way to submit content.\n */\n submitEdit: (text: string) => void;\n\n // UI state management\n /**\n * Current discussion or comment being replied to.\n * Used by the form to determine context when submitting.\n */\n replyToItem: ReplyToItem | undefined;\n /**\n * Sets the discussion or comment being replied to.\n * Will clear editing state if set.\n */\n setReplyToItem: (replyToItem: ReplyToItem | undefined) => void;\n\n /**\n * Current discussion or comment being edited.\n * Used by the form to determine context when submitting.\n */\n editingItem: EditingItem | undefined;\n /**\n * Sets the discussion or comment being edited.\n * Will clear replyTo state if set.\n */\n setEditingItem: (editingItem: EditingItem | undefined) => void;\n\n /**\n * Item currently targeted for deletion.\n * Used by the delete confirmation dialog.\n */\n itemToDelete: DeleteItem | undefined;\n /**\n * Sets the discussion or comment to be deleted.\n * Should be used before showing the confirmation dialog.\n */\n setItemToDelete: (item: DeleteItem | undefined) => void;\n\n /**\n * Currently highlighted discussion.\n * Used to visually highlight a discussion in the UI.\n */\n highlightedDiscussionId: string | undefined;\n /**\n * Sets the highlighted discussion.\n */\n setHighlightedDiscussionId: (discussionId: string | undefined) => void;\n\n // Delete confirmation handler\n /**\n * Handles the confirmation of a delete operation.\n * Should be called after the user confirms deletion in the UI.\n */\n handleDeleteConfirm: () => void;\n\n // Helpers\n /**\n * Helper function to get the user ID of the entity being replied to.\n * Returns '' if no reply context is set, or the user ID if a valid reply context exists.\n */\n getReplyToUserId: () => string;\n\n /**\n * Helper function to get the text of the item being edited.\n * Returns '' if no editing context is set, or the text content if a valid editing context exists.\n */\n getEditingItemText: () => string;\n\n // Direct CRUD operations - use these only for custom integrations\n // that don't use the built-in UI state management\n addDiscussion: (text: string, anchorId?: string) => void;\n editDiscussion: (id: string, text: string) => void;\n removeDiscussion: (id: string) => void;\n addComment: (discussionId: string, text: string, parentId?: string) => void;\n editComment: (\n discussionId: string,\n commentId: string,\n text: string,\n ) => void;\n removeComment: (discussionId: string, commentId: string) => void;\n };\n};\n\nexport type RoomStateWithDiscussion = RoomShellSliceState<BaseRoomConfig> &\n DiscussSliceState;\n\nexport function createDiscussSlice<\n PC extends BaseRoomConfig & DiscussSliceConfig,\n>({userId}: {userId: string}): StateCreator<DiscussSliceState> {\n return createSlice<PC, DiscussSliceState>((set, get) => ({\n discuss: {\n userId,\n\n // Direct CRUD operations - These are exposed for advanced use cases\n // For normal usage with UI integration, prefer submitEdit\n\n /**\n * Directly adds a new discussion without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n addDiscussion: (text, anchorId) => {\n const id = createId();\n const rootComment: Comment = {\n id: createId(),\n userId,\n text,\n timestamp: new Date(),\n };\n\n const newDiscussion: Discussion = {\n id,\n anchorId,\n rootComment,\n comments: [],\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.config.discuss.discussions.push(newDiscussion);\n }),\n );\n },\n\n /**\n * Directly removes an discussion without managing UI state.\n * For UI-integrated usage, prefer setting itemToDelete and using handleDeleteConfirm.\n */\n removeDiscussion: (id) => {\n set((state) =>\n produce(state, (draft) => {\n const index = draft.config.discuss.discussions.findIndex(\n (a) => a.id === id,\n );\n if (index !== -1) {\n draft.config.discuss.discussions.splice(index, 1);\n }\n }),\n );\n },\n\n /**\n * Directly edits an discussion without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n editDiscussion: (id, text) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.config.discuss.discussions.find(\n (a) => a.id === id,\n );\n if (discussion) {\n discussion.rootComment.text = text;\n }\n }),\n );\n },\n\n /**\n * Directly adds a comment without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n addComment: (discussionId, text, parentId) => {\n const newComment: Comment = {\n id: createId(),\n userId,\n text,\n timestamp: new Date(),\n parentId,\n };\n\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.config.discuss.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n discussion.comments.push(newComment);\n }\n }),\n );\n },\n\n /**\n * Directly edits a comment without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n editComment: (discussionId, commentId, text) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.config.discuss.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n if (discussion.rootComment.id === commentId) {\n discussion.rootComment.text = text;\n } else {\n const comment = discussion.comments.find(\n (c) => c.id === commentId,\n );\n if (comment) {\n comment.text = text;\n }\n }\n }\n }),\n );\n },\n\n /**\n * Directly removes a comment without managing UI state.\n * For UI-integrated usage, prefer setting itemToDelete and using handleDeleteConfirm.\n */\n removeComment: (discussionId, commentId) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.config.discuss.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n // Cannot remove the root comment\n if (discussion.rootComment.id !== commentId) {\n const index = discussion.comments.findIndex(\n (c) => c.id === commentId,\n );\n if (index !== -1) {\n discussion.comments.splice(index, 1);\n }\n }\n }\n }),\n );\n },\n\n // UI state management\n /**\n * Current discussion or comment being replied to.\n * Used by the form to determine context when submitting.\n */\n replyToItem: undefined,\n /**\n * Sets the discussion or comment being replied to.\n * Will clear editing state if set.\n */\n setReplyToItem: (replyToItem) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.replyToItem = replyToItem;\n if (replyToItem) {\n draft.discuss.editingItem = undefined;\n }\n }),\n );\n },\n\n /**\n * Current discussion or comment being edited.\n * Used by the form to determine context when submitting.\n */\n editingItem: undefined,\n /**\n * Sets the discussion or comment being edited.\n * Will clear replyTo state if set.\n */\n setEditingItem: (editingItem) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.editingItem = editingItem;\n if (editingItem) {\n draft.discuss.replyToItem = undefined;\n }\n }),\n );\n },\n\n /**\n * Item currently targeted for deletion.\n * Used by the delete confirmation dialog.\n */\n itemToDelete: undefined,\n /**\n * Sets the discussion or comment to be deleted.\n * Should be used before showing the confirmation dialog.\n */\n setItemToDelete: (item) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.itemToDelete = item;\n }),\n );\n },\n\n /**\n * Currently highlighted discussion.\n * Used to visually highlight a discussion in the UI.\n */\n highlightedDiscussionId: undefined,\n /**\n * Sets the highlighted discussion.\n */\n setHighlightedDiscussionId: (discussionId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.highlightedDiscussionId = discussionId;\n }),\n );\n },\n\n /**\n * Main form submission handler that processes content based on UI state.\n * This is the preferred method to submit discussion/comment content.\n *\n * Will automatically:\n * - Add a new discussion if no context is set\n * - Add a comment as a reply if replyToItem is set\n * - Edit an discussion or comment if editing is set\n * - Clear UI state after submission\n */\n submitEdit: (text) => {\n const state = get();\n const {\n editingItem,\n replyToItem,\n addDiscussion,\n editDiscussion,\n editComment,\n addComment,\n } = state.discuss;\n\n if (editingItem) {\n if (editingItem.commentId) {\n editComment(editingItem.discussionId, editingItem.commentId, text);\n } else {\n editDiscussion(editingItem.discussionId, text);\n }\n state.discuss.setEditingItem(undefined);\n } else if (replyToItem) {\n if (replyToItem.commentId) {\n addComment(replyToItem.discussionId, text, replyToItem.commentId);\n } else {\n addComment(replyToItem.discussionId, text);\n }\n state.discuss.setReplyToItem(undefined);\n } else {\n addDiscussion(text);\n }\n },\n\n /**\n * Handles the confirmation of a delete operation.\n * Should be called after the user confirms deletion in the UI.\n *\n * Will:\n * - Delete the discussion or comment specified in itemToDelete\n * - Clear the itemToDelete state\n */\n handleDeleteConfirm: () => {\n const state = get();\n const {itemToDelete, removeComment, removeDiscussion} = state.discuss;\n\n if (itemToDelete) {\n if (itemToDelete.commentId) {\n removeComment(itemToDelete.discussionId, itemToDelete.commentId);\n } else {\n removeDiscussion(itemToDelete.discussionId);\n }\n state.discuss.setItemToDelete(undefined);\n }\n },\n\n /**\n * Helper function to get the user ID of the entity being replied to.\n * Returns '' if no reply context is set, or the user ID if a valid reply context exists.\n */\n getReplyToUserId: () => {\n const state = get();\n const {replyToItem} = state.discuss;\n const {discussions} = state.config.discuss;\n\n if (!replyToItem) return '';\n\n const discussion = discussions.find(\n (a) => a.id === replyToItem.discussionId,\n );\n\n if (discussion) {\n if (replyToItem.commentId) {\n if (discussion.rootComment.id === replyToItem.commentId) {\n return discussion.rootComment.userId;\n }\n const comment = discussion.comments.find(\n (c) => c.id === replyToItem.commentId,\n );\n if (comment) return comment.userId;\n } else {\n return discussion.rootComment.userId;\n }\n }\n\n return '';\n },\n\n /**\n * Helper function to get the text of the item being edited.\n * Returns '' if no editing context is set, or the text content if a valid editing context exists.\n */\n getEditingItemText: () => {\n const state = get();\n const {editingItem} = state.discuss;\n const {discussions} = state.config.discuss;\n\n if (!editingItem) return '';\n\n // Look for the discussion\n const discussion = discussions.find(\n (a) => a.id === editingItem.discussionId,\n );\n if (!discussion) return '';\n\n // If editing a comment, find the comment\n if (editingItem.commentId) {\n const comment = discussion.comments.find(\n (c) => c.id === editingItem.commentId,\n );\n return comment ? comment.text : '';\n }\n\n // If editing the discussion itself\n return discussion.rootComment.text;\n },\n },\n }));\n}\n\ntype RoomConfigWithDiscuss = BaseRoomConfig & DiscussSliceConfig;\ntype RoomStateWithDiscuss = RoomShellSliceState<RoomConfigWithDiscuss> &\n DiscussSliceState;\n\nexport function useStoreWithDiscussion<T>(\n selector: (state: RoomStateWithDiscuss) => T,\n): T {\n return useBaseRoomShellStore<\n BaseRoomConfig & DiscussSliceConfig,\n RoomStateWithDiscuss,\n T\n >((state) => selector(state as RoomStateWithDiscuss));\n}\n"]}
1
+ {"version":3,"file":"DiscussSlice.js","sourceRoot":"","sources":["../src/DiscussSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n createSlice,\n useBaseRoomShellStore,\n type RoomShellSliceState,\n type StateCreator,\n BaseRoomConfig,\n} from '@sqlrooms/room-shell';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\n// Base type with common fields\nexport const CommentBase = z.object({\n id: z.string().cuid2(),\n userId: z.string(),\n text: z.string(),\n timestamp: z.coerce.date(),\n});\nexport type CommentBase = z.infer<typeof CommentBase>;\n\n// Comment type extends base with parentId\nexport const Comment = CommentBase.extend({\n parentId: z.string().optional(),\n});\nexport type Comment = z.infer<typeof Comment>;\n\n// Discussion is a container with a rootComment and collection of reply comments\nexport const Discussion = z.object({\n id: z.string().cuid2(),\n anchorId: z.string().optional(),\n rootComment: Comment,\n comments: z.array(Comment),\n});\nexport type Discussion = z.infer<typeof Discussion>;\n\nexport const DiscussSliceConfig = z.object({\n discussions: z.array(Discussion),\n});\nexport type DiscussSliceConfig = z.infer<typeof DiscussSliceConfig>;\n\nexport function createDefaultDiscussConfig(): DiscussSliceConfig {\n return {\n discussions: [],\n };\n}\n\n// UI state for discussions\nexport type ReplyToItem = {\n discussionId: string;\n commentId?: string;\n};\n\nexport type EditingItem = {\n discussionId: string;\n commentId?: string;\n};\n\nexport type DeleteItem = {\n discussionId: string;\n commentId?: string;\n itemType: string;\n};\n\nexport type DiscussSliceState = {\n discuss: {\n userId: string;\n config: DiscussSliceConfig;\n\n // UI-connected actions - preferred API for most use cases\n /**\n * Submit content based on current UI state (add discussion, reply to discussion/comment, or edit).\n * This automatically handles state management and is the preferred way to submit content.\n */\n submitEdit: (text: string) => void;\n\n // UI state management\n /**\n * Current discussion or comment being replied to.\n * Used by the form to determine context when submitting.\n */\n replyToItem: ReplyToItem | undefined;\n /**\n * Sets the discussion or comment being replied to.\n * Will clear editing state if set.\n */\n setReplyToItem: (replyToItem: ReplyToItem | undefined) => void;\n\n /**\n * Current discussion or comment being edited.\n * Used by the form to determine context when submitting.\n */\n editingItem: EditingItem | undefined;\n /**\n * Sets the discussion or comment being edited.\n * Will clear replyTo state if set.\n */\n setEditingItem: (editingItem: EditingItem | undefined) => void;\n\n /**\n * Item currently targeted for deletion.\n * Used by the delete confirmation dialog.\n */\n itemToDelete: DeleteItem | undefined;\n /**\n * Sets the discussion or comment to be deleted.\n * Should be used before showing the confirmation dialog.\n */\n setItemToDelete: (item: DeleteItem | undefined) => void;\n\n /**\n * Currently highlighted discussion.\n * Used to visually highlight a discussion in the UI.\n */\n highlightedDiscussionId: string | undefined;\n /**\n * Sets the highlighted discussion.\n */\n setHighlightedDiscussionId: (discussionId: string | undefined) => void;\n\n // Delete confirmation handler\n /**\n * Handles the confirmation of a delete operation.\n * Should be called after the user confirms deletion in the UI.\n */\n handleDeleteConfirm: () => void;\n\n /**\n * Sets the config for the discuss slice.\n */\n setConfig: (config: DiscussSliceConfig) => void;\n\n // Helpers\n /**\n * Helper function to get the user ID of the entity being replied to.\n * Returns '' if no reply context is set, or the user ID if a valid reply context exists.\n */\n getReplyToUserId: () => string;\n\n /**\n * Helper function to get the text of the item being edited.\n * Returns '' if no editing context is set, or the text content if a valid editing context exists.\n */\n getEditingItemText: () => string;\n\n // Direct CRUD operations - use these only for custom integrations\n // that don't use the built-in UI state management\n addDiscussion: (text: string, anchorId?: string) => void;\n editDiscussion: (id: string, text: string) => void;\n removeDiscussion: (id: string) => void;\n addComment: (discussionId: string, text: string, parentId?: string) => void;\n editComment: (\n discussionId: string,\n commentId: string,\n text: string,\n ) => void;\n removeComment: (discussionId: string, commentId: string) => void;\n };\n};\n\nexport type RoomStateWithDiscussion = RoomShellSliceState<BaseRoomConfig> &\n DiscussSliceState;\n\nexport function createDiscussSlice<PC extends BaseRoomConfig>({\n userId,\n}: {\n userId: string;\n}): StateCreator<DiscussSliceState> {\n return createSlice<PC, DiscussSliceState>((set, get) => ({\n discuss: {\n userId,\n config: createDefaultDiscussConfig(),\n // Direct CRUD operations - These are exposed for advanced use cases\n // For normal usage with UI integration, prefer submitEdit\n\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.config = config;\n }),\n );\n },\n\n /**\n * Directly adds a new discussion without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n addDiscussion: (text, anchorId) => {\n const id = createId();\n const rootComment: Comment = {\n id: createId(),\n userId,\n text,\n timestamp: new Date(),\n };\n\n const newDiscussion: Discussion = {\n id,\n anchorId,\n rootComment,\n comments: [],\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.config.discussions.push(newDiscussion);\n }),\n );\n },\n\n /**\n * Directly removes an discussion without managing UI state.\n * For UI-integrated usage, prefer setting itemToDelete and using handleDeleteConfirm.\n */\n removeDiscussion: (id) => {\n set((state) =>\n produce(state, (draft) => {\n const index = draft.discuss.config.discussions.findIndex(\n (a) => a.id === id,\n );\n if (index !== -1) {\n draft.discuss.config.discussions.splice(index, 1);\n }\n }),\n );\n },\n\n /**\n * Directly edits an discussion without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n editDiscussion: (id, text) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.discuss.config.discussions.find(\n (a) => a.id === id,\n );\n if (discussion) {\n discussion.rootComment.text = text;\n }\n }),\n );\n },\n\n /**\n * Directly adds a comment without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n addComment: (discussionId, text, parentId) => {\n const newComment: Comment = {\n id: createId(),\n userId,\n text,\n timestamp: new Date(),\n parentId,\n };\n\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.discuss.config.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n discussion.comments.push(newComment);\n }\n }),\n );\n },\n\n /**\n * Directly edits a comment without managing UI state.\n * For UI-integrated usage, prefer submitEdit.\n */\n editComment: (discussionId, commentId, text) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.discuss.config.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n if (discussion.rootComment.id === commentId) {\n discussion.rootComment.text = text;\n } else {\n const comment = discussion.comments.find(\n (c) => c.id === commentId,\n );\n if (comment) {\n comment.text = text;\n }\n }\n }\n }),\n );\n },\n\n /**\n * Directly removes a comment without managing UI state.\n * For UI-integrated usage, prefer setting itemToDelete and using handleDeleteConfirm.\n */\n removeComment: (discussionId, commentId) => {\n set((state) =>\n produce(state, (draft) => {\n const discussion = draft.discuss.config.discussions.find(\n (a) => a.id === discussionId,\n );\n if (discussion) {\n // Cannot remove the root comment\n if (discussion.rootComment.id !== commentId) {\n const index = discussion.comments.findIndex(\n (c) => c.id === commentId,\n );\n if (index !== -1) {\n discussion.comments.splice(index, 1);\n }\n }\n }\n }),\n );\n },\n\n // UI state management\n /**\n * Current discussion or comment being replied to.\n * Used by the form to determine context when submitting.\n */\n replyToItem: undefined,\n /**\n * Sets the discussion or comment being replied to.\n * Will clear editing state if set.\n */\n setReplyToItem: (replyToItem) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.replyToItem = replyToItem;\n if (replyToItem) {\n draft.discuss.editingItem = undefined;\n }\n }),\n );\n },\n\n /**\n * Current discussion or comment being edited.\n * Used by the form to determine context when submitting.\n */\n editingItem: undefined,\n /**\n * Sets the discussion or comment being edited.\n * Will clear replyTo state if set.\n */\n setEditingItem: (editingItem) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.editingItem = editingItem;\n if (editingItem) {\n draft.discuss.replyToItem = undefined;\n }\n }),\n );\n },\n\n /**\n * Item currently targeted for deletion.\n * Used by the delete confirmation dialog.\n */\n itemToDelete: undefined,\n /**\n * Sets the discussion or comment to be deleted.\n * Should be used before showing the confirmation dialog.\n */\n setItemToDelete: (item) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.itemToDelete = item;\n }),\n );\n },\n\n /**\n * Currently highlighted discussion.\n * Used to visually highlight a discussion in the UI.\n */\n highlightedDiscussionId: undefined,\n /**\n * Sets the highlighted discussion.\n */\n setHighlightedDiscussionId: (discussionId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.discuss.highlightedDiscussionId = discussionId;\n }),\n );\n },\n\n /**\n * Main form submission handler that processes content based on UI state.\n * This is the preferred method to submit discussion/comment content.\n *\n * Will automatically:\n * - Add a new discussion if no context is set\n * - Add a comment as a reply if replyToItem is set\n * - Edit an discussion or comment if editing is set\n * - Clear UI state after submission\n */\n submitEdit: (text) => {\n const state = get();\n const {\n editingItem,\n replyToItem,\n addDiscussion,\n editDiscussion,\n editComment,\n addComment,\n } = state.discuss;\n\n if (editingItem) {\n if (editingItem.commentId) {\n editComment(editingItem.discussionId, editingItem.commentId, text);\n } else {\n editDiscussion(editingItem.discussionId, text);\n }\n state.discuss.setEditingItem(undefined);\n } else if (replyToItem) {\n if (replyToItem.commentId) {\n addComment(replyToItem.discussionId, text, replyToItem.commentId);\n } else {\n addComment(replyToItem.discussionId, text);\n }\n state.discuss.setReplyToItem(undefined);\n } else {\n addDiscussion(text);\n }\n },\n\n /**\n * Handles the confirmation of a delete operation.\n * Should be called after the user confirms deletion in the UI.\n *\n * Will:\n * - Delete the discussion or comment specified in itemToDelete\n * - Clear the itemToDelete state\n */\n handleDeleteConfirm: () => {\n const state = get();\n const {itemToDelete, removeComment, removeDiscussion} = state.discuss;\n\n if (itemToDelete) {\n if (itemToDelete.commentId) {\n removeComment(itemToDelete.discussionId, itemToDelete.commentId);\n } else {\n removeDiscussion(itemToDelete.discussionId);\n }\n state.discuss.setItemToDelete(undefined);\n }\n },\n\n /**\n * Helper function to get the user ID of the entity being replied to.\n * Returns '' if no reply context is set, or the user ID if a valid reply context exists.\n */\n getReplyToUserId: () => {\n const state = get();\n const {replyToItem} = state.discuss;\n const {discussions} = state.discuss.config;\n\n if (!replyToItem) return '';\n\n const discussion = discussions.find(\n (a) => a.id === replyToItem.discussionId,\n );\n\n if (discussion) {\n if (replyToItem.commentId) {\n if (discussion.rootComment.id === replyToItem.commentId) {\n return discussion.rootComment.userId;\n }\n const comment = discussion.comments.find(\n (c) => c.id === replyToItem.commentId,\n );\n if (comment) return comment.userId;\n } else {\n return discussion.rootComment.userId;\n }\n }\n\n return '';\n },\n\n /**\n * Helper function to get the text of the item being edited.\n * Returns '' if no editing context is set, or the text content if a valid editing context exists.\n */\n getEditingItemText: () => {\n const state = get();\n const {editingItem} = state.discuss;\n const {discussions} = state.discuss.config;\n\n if (!editingItem) return '';\n\n // Look for the discussion\n const discussion = discussions.find(\n (a) => a.id === editingItem.discussionId,\n );\n if (!discussion) return '';\n\n // If editing a comment, find the comment\n if (editingItem.commentId) {\n const comment = discussion.comments.find(\n (c) => c.id === editingItem.commentId,\n );\n return comment ? comment.text : '';\n }\n\n // If editing the discussion itself\n return discussion.rootComment.text;\n },\n },\n }));\n}\n\ntype RoomConfigWithDiscuss = BaseRoomConfig & DiscussSliceConfig;\ntype RoomStateWithDiscuss = RoomShellSliceState<RoomConfigWithDiscuss> &\n DiscussSliceState;\n\nexport function useStoreWithDiscussion<T>(\n selector: (state: RoomStateWithDiscuss) => T,\n): T {\n return useBaseRoomShellStore<\n BaseRoomConfig & DiscussSliceConfig,\n RoomStateWithDiscuss,\n T\n >((state) => selector(state as RoomStateWithDiscuss));\n}\n"]}
@@ -9,7 +9,7 @@ import { useStoreWithDiscussion } from './DiscussSlice';
9
9
  const defaultRenderDiscussion = (props) => (_jsx(DiscussionItem, { ...props }));
10
10
  export const DiscussionList = forwardRef(({ className, renderComment = defaultRenderComment, renderDiscussion = defaultRenderDiscussion, ...props }, ref) => {
11
11
  const highlightedDiscussionId = useStoreWithDiscussion((state) => state.discuss.highlightedDiscussionId);
12
- const discussions = useStoreWithDiscussion((state) => state.config.discuss.discussions);
12
+ const discussions = useStoreWithDiscussion((state) => state.discuss.config.discussions);
13
13
  const replyToItem = useStoreWithDiscussion((state) => state.discuss.replyToItem);
14
14
  const editingItem = useStoreWithDiscussion((state) => state.discuss.editingItem);
15
15
  const itemToDelete = useStoreWithDiscussion((state) => state.discuss.itemToDelete);
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionList.js","sourceRoot":"","sources":["../src/DiscussionList.tsx"],"names":[],"mappings":"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","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n Fragment,\n ReactNode,\n useEffect,\n useRef,\n} from 'react';\nimport {CommentItemProps, defaultRenderComment} from './components/CommentItem';\nimport {DeleteConfirmDialog} from './components/DeleteConfirmDialog';\nimport {DiscussionItem, DiscussionItemProps} from './components/DiscussionItem';\nimport {EditCommentForm} from './components/EditCommentForm';\nimport {useStoreWithDiscussion} from './DiscussSlice';\n\n// Main DiscussionList component\ntype DiscussionListProps = ComponentPropsWithoutRef<'div'> & {\n renderDiscussion?: (props: DiscussionItemProps) => ReactNode;\n renderComment?: (props: CommentItemProps) => ReactNode;\n};\n\nconst defaultRenderDiscussion = (props: DiscussionItemProps) => (\n <DiscussionItem {...props} />\n);\n\nexport const DiscussionList = forwardRef<HTMLDivElement, DiscussionListProps>(\n (\n {\n className,\n renderComment = defaultRenderComment,\n renderDiscussion = defaultRenderDiscussion,\n\n ...props\n },\n ref,\n ) => {\n const highlightedDiscussionId = useStoreWithDiscussion(\n (state) => state.discuss.highlightedDiscussionId,\n );\n const discussions = useStoreWithDiscussion(\n (state) => state.config.discuss.discussions,\n );\n const replyToItem = useStoreWithDiscussion(\n (state) => state.discuss.replyToItem,\n );\n const editingItem = useStoreWithDiscussion(\n (state) => state.discuss.editingItem,\n );\n const itemToDelete = useStoreWithDiscussion(\n (state) => state.discuss.itemToDelete,\n );\n const setReplyToItem = useStoreWithDiscussion(\n (state) => state.discuss.setReplyToItem,\n );\n const setEditingItem = useStoreWithDiscussion(\n (state) => state.discuss.setEditingItem,\n );\n const setItemToDelete = useStoreWithDiscussion(\n (state) => state.discuss.setItemToDelete,\n );\n const submitEdit = useStoreWithDiscussion(\n (state) => state.discuss.submitEdit,\n );\n const handleDeleteConfirm = useStoreWithDiscussion(\n (state) => state.discuss.handleDeleteConfirm,\n );\n const getEditingItemText = useStoreWithDiscussion(\n (state) => state.discuss.getEditingItemText,\n );\n\n // Reference to highlighted discussion\n const highlightedRef = useRef<HTMLDivElement>(null);\n\n // Scroll to highlighted discussion\n useEffect(() => {\n if (highlightedDiscussionId && highlightedRef.current) {\n highlightedRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [highlightedDiscussionId]);\n\n // Get the context content (the post being replied to or edited)\n const getContextContent = (): ReactNode => {\n if (editingItem) {\n // When editing, show the original content\n const discussion = discussions.find(\n (d) => d.id === editingItem.discussionId,\n );\n if (!discussion) return null;\n\n if (editingItem.commentId) {\n // Editing a comment\n const comment = discussion.comments.find(\n (c) => c.id === editingItem.commentId,\n );\n if (!comment) return null;\n\n return renderComment({comment, discussion});\n } else {\n // Editing the root discussion\n return renderComment({\n comment: discussion.rootComment,\n discussion,\n });\n }\n }\n\n if (replyToItem) {\n // When replying, show what we're replying to\n const discussion = discussions.find(\n (d) => d.id === replyToItem.discussionId,\n );\n if (!discussion) return null;\n\n if (replyToItem.commentId) {\n // Replying to a comment\n const comment = discussion.comments.find(\n (c) => c.id === replyToItem.commentId,\n );\n if (!comment) return null;\n\n return renderComment({comment, discussion});\n } else {\n // Replying to the root discussion\n return renderComment({\n comment: discussion.rootComment,\n discussion,\n });\n }\n }\n\n return null;\n };\n\n const editingContext = getContextContent();\n\n return (\n <div\n ref={ref}\n className={cn('flex h-full flex-col overflow-hidden', className)}\n {...props}\n >\n {/* Scrollable discussion list */}\n <div className=\"flex-1 overflow-y-auto\">\n <div className=\"flex flex-col gap-4 p-2\">\n {discussions.map((discussion) => (\n <Fragment key={discussion.id}>\n {renderDiscussion({\n discussion,\n renderComment,\n ref:\n highlightedDiscussionId === discussion.id\n ? highlightedRef\n : undefined,\n className: cn(\n 'flex flex-col gap-4 rounded border p-2',\n highlightedDiscussionId === discussion.id &&\n 'border-blue-500 shadow-md transition-all duration-500',\n ),\n })}\n </Fragment>\n ))}\n\n {/* Add padding at the bottom to prevent content from being hidden behind sticky form */}\n <div className=\"h-20\" />\n </div>\n </div>\n\n {/* Sticky form at the bottom */}\n <div className=\"bg-background sticky bottom-0 border-t p-2 shadow-lg\">\n {editingContext ? (\n <div className=\"flex flex-col gap-2 p-1\">\n <div className=\"text-muted-foreground text-xs\">\n {replyToItem ? 'Replying to:' : 'Editing:'}\n </div>\n <div className=\"bg-muted rounded border p-2\">\n {editingContext}\n </div>\n </div>\n ) : null}\n {/* Show editing form when editing */}\n {editingItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText={getEditingItemText()}\n submitLabel=\"Save\"\n onCancel={() => {\n setEditingItem(undefined);\n }}\n />\n )}\n\n {/* Show reply form when replying */}\n {!editingItem && replyToItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText=\"\"\n submitLabel=\"Reply\"\n onCancel={() => {\n setReplyToItem(undefined);\n }}\n />\n )}\n\n {/* Show form for new discussions only when not replying or editing */}\n {!editingItem && !replyToItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText=\"\"\n submitLabel=\"Post\"\n />\n )}\n </div>\n\n <DeleteConfirmDialog\n open={!!itemToDelete}\n onOpenChange={(open) => {\n if (!open) setItemToDelete(undefined);\n }}\n onConfirm={handleDeleteConfirm}\n itemType={itemToDelete?.itemType || 'Item'}\n />\n </div>\n );\n },\n);\nDiscussionList.displayName = 'DiscussionList';\n"]}
1
+ {"version":3,"file":"DiscussionList.js","sourceRoot":"","sources":["../src/DiscussionList.tsx"],"names":[],"mappings":"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","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport {\n ComponentPropsWithoutRef,\n forwardRef,\n Fragment,\n ReactNode,\n useEffect,\n useRef,\n} from 'react';\nimport {CommentItemProps, defaultRenderComment} from './components/CommentItem';\nimport {DeleteConfirmDialog} from './components/DeleteConfirmDialog';\nimport {DiscussionItem, DiscussionItemProps} from './components/DiscussionItem';\nimport {EditCommentForm} from './components/EditCommentForm';\nimport {useStoreWithDiscussion} from './DiscussSlice';\n\n// Main DiscussionList component\ntype DiscussionListProps = ComponentPropsWithoutRef<'div'> & {\n renderDiscussion?: (props: DiscussionItemProps) => ReactNode;\n renderComment?: (props: CommentItemProps) => ReactNode;\n};\n\nconst defaultRenderDiscussion = (props: DiscussionItemProps) => (\n <DiscussionItem {...props} />\n);\n\nexport const DiscussionList = forwardRef<HTMLDivElement, DiscussionListProps>(\n (\n {\n className,\n renderComment = defaultRenderComment,\n renderDiscussion = defaultRenderDiscussion,\n\n ...props\n },\n ref,\n ) => {\n const highlightedDiscussionId = useStoreWithDiscussion(\n (state) => state.discuss.highlightedDiscussionId,\n );\n const discussions = useStoreWithDiscussion(\n (state) => state.discuss.config.discussions,\n );\n const replyToItem = useStoreWithDiscussion(\n (state) => state.discuss.replyToItem,\n );\n const editingItem = useStoreWithDiscussion(\n (state) => state.discuss.editingItem,\n );\n const itemToDelete = useStoreWithDiscussion(\n (state) => state.discuss.itemToDelete,\n );\n const setReplyToItem = useStoreWithDiscussion(\n (state) => state.discuss.setReplyToItem,\n );\n const setEditingItem = useStoreWithDiscussion(\n (state) => state.discuss.setEditingItem,\n );\n const setItemToDelete = useStoreWithDiscussion(\n (state) => state.discuss.setItemToDelete,\n );\n const submitEdit = useStoreWithDiscussion(\n (state) => state.discuss.submitEdit,\n );\n const handleDeleteConfirm = useStoreWithDiscussion(\n (state) => state.discuss.handleDeleteConfirm,\n );\n const getEditingItemText = useStoreWithDiscussion(\n (state) => state.discuss.getEditingItemText,\n );\n\n // Reference to highlighted discussion\n const highlightedRef = useRef<HTMLDivElement>(null);\n\n // Scroll to highlighted discussion\n useEffect(() => {\n if (highlightedDiscussionId && highlightedRef.current) {\n highlightedRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [highlightedDiscussionId]);\n\n // Get the context content (the post being replied to or edited)\n const getContextContent = (): ReactNode => {\n if (editingItem) {\n // When editing, show the original content\n const discussion = discussions.find(\n (d) => d.id === editingItem.discussionId,\n );\n if (!discussion) return null;\n\n if (editingItem.commentId) {\n // Editing a comment\n const comment = discussion.comments.find(\n (c) => c.id === editingItem.commentId,\n );\n if (!comment) return null;\n\n return renderComment({comment, discussion});\n } else {\n // Editing the root discussion\n return renderComment({\n comment: discussion.rootComment,\n discussion,\n });\n }\n }\n\n if (replyToItem) {\n // When replying, show what we're replying to\n const discussion = discussions.find(\n (d) => d.id === replyToItem.discussionId,\n );\n if (!discussion) return null;\n\n if (replyToItem.commentId) {\n // Replying to a comment\n const comment = discussion.comments.find(\n (c) => c.id === replyToItem.commentId,\n );\n if (!comment) return null;\n\n return renderComment({comment, discussion});\n } else {\n // Replying to the root discussion\n return renderComment({\n comment: discussion.rootComment,\n discussion,\n });\n }\n }\n\n return null;\n };\n\n const editingContext = getContextContent();\n\n return (\n <div\n ref={ref}\n className={cn('flex h-full flex-col overflow-hidden', className)}\n {...props}\n >\n {/* Scrollable discussion list */}\n <div className=\"flex-1 overflow-y-auto\">\n <div className=\"flex flex-col gap-4 p-2\">\n {discussions.map((discussion) => (\n <Fragment key={discussion.id}>\n {renderDiscussion({\n discussion,\n renderComment,\n ref:\n highlightedDiscussionId === discussion.id\n ? highlightedRef\n : undefined,\n className: cn(\n 'flex flex-col gap-4 rounded border p-2',\n highlightedDiscussionId === discussion.id &&\n 'border-blue-500 shadow-md transition-all duration-500',\n ),\n })}\n </Fragment>\n ))}\n\n {/* Add padding at the bottom to prevent content from being hidden behind sticky form */}\n <div className=\"h-20\" />\n </div>\n </div>\n\n {/* Sticky form at the bottom */}\n <div className=\"bg-background sticky bottom-0 border-t p-2 shadow-lg\">\n {editingContext ? (\n <div className=\"flex flex-col gap-2 p-1\">\n <div className=\"text-muted-foreground text-xs\">\n {replyToItem ? 'Replying to:' : 'Editing:'}\n </div>\n <div className=\"bg-muted rounded border p-2\">\n {editingContext}\n </div>\n </div>\n ) : null}\n {/* Show editing form when editing */}\n {editingItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText={getEditingItemText()}\n submitLabel=\"Save\"\n onCancel={() => {\n setEditingItem(undefined);\n }}\n />\n )}\n\n {/* Show reply form when replying */}\n {!editingItem && replyToItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText=\"\"\n submitLabel=\"Reply\"\n onCancel={() => {\n setReplyToItem(undefined);\n }}\n />\n )}\n\n {/* Show form for new discussions only when not replying or editing */}\n {!editingItem && !replyToItem && (\n <EditCommentForm\n onSubmit={submitEdit}\n initialText=\"\"\n submitLabel=\"Post\"\n />\n )}\n </div>\n\n <DeleteConfirmDialog\n open={!!itemToDelete}\n onOpenChange={(open) => {\n if (!open) setItemToDelete(undefined);\n }}\n onConfirm={handleDeleteConfirm}\n itemType={itemToDelete?.itemType || 'Item'}\n />\n </div>\n );\n },\n);\nDiscussionList.displayName = 'DiscussionList';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/discuss",
3
- "version": "0.24.26",
3
+ "version": "0.24.28-rc.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,9 +16,9 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@paralleldrive/cuid2": "^2.2.2",
19
- "@sqlrooms/room-shell": "0.24.26",
20
- "@sqlrooms/ui": "0.24.26",
21
- "@sqlrooms/utils": "0.24.26",
19
+ "@sqlrooms/room-shell": "0.24.28-rc.1",
20
+ "@sqlrooms/ui": "0.24.28-rc.1",
21
+ "@sqlrooms/utils": "0.24.28-rc.1",
22
22
  "immer": "^10.1.1",
23
23
  "lucide-react": "^0.474.0",
24
24
  "zod": "^3.25.73"
@@ -33,5 +33,5 @@
33
33
  "lint": "eslint .",
34
34
  "typedoc": "typedoc"
35
35
  },
36
- "gitHead": "1a14d45223319a46b818f9a2b35eb0655f72f6ed"
36
+ "gitHead": "660a717f42062c62335ecc9929f5dc60f00fa99d"
37
37
  }