@sqlrooms/discuss 0.16.4 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -64,7 +64,7 @@ import {DiscussionItem} from '@sqlrooms/discuss';
64
64
 
65
65
  #### Store Setup with `createDiscussSlice`
66
66
 
67
- To use the discussion system, you need to integrate it with your project store using `createDiscussSlice`:
67
+ To use the discussion system, you need to integrate it with your room store using `createDiscussSlice`:
68
68
 
69
69
  ```tsx
70
70
  import {
@@ -74,47 +74,46 @@ import {
74
74
  DiscussSliceState,
75
75
  } from '@sqlrooms/discuss';
76
76
  import {
77
- BaseProjectConfig,
78
- createProjectBuilderSlice,
79
- createProjectBuilderStore,
80
- ProjectBuilderState,
81
- } from '@sqlrooms/project-builder';
77
+ BaseRoomConfig,
78
+ createRoomShellSlice,
79
+ createRoomStore,
80
+ RoomShellSliceState,
81
+ } from '@sqlrooms/room-shell';
82
82
  import {z} from 'zod';
83
83
 
84
84
  // 1. Extend your app config with DiscussSliceConfig
85
- export const AppConfig = BaseProjectConfig.merge(DiscussSliceConfig);
86
- export type AppConfig = z.infer<typeof AppConfig>;
85
+ export const RoomConfig = BaseRoomConfig.merge(DiscussSliceConfig);
86
+ export type RoomConfig = z.infer<typeof RoomConfig>;
87
87
 
88
88
  // 2. Extend your app state with DiscussSliceState
89
- export type AppState = ProjectBuilderState<AppConfig> & DiscussSliceState;
89
+ export type RoomState = RoomShellSliceState<RoomConfig> & DiscussSliceState;
90
90
 
91
91
  // 3. Create the store with discuss slice
92
- export const {projectStore, useProjectStore} = createProjectBuilderStore<
93
- AppConfig,
94
- AppState
95
- >((set, get, store) => ({
96
- // Add the discuss slice with a user ID
97
- ...createDiscussSlice({userId: 'current-user-id'})(set, get, store),
98
-
99
- // Add your project builder slice
100
- ...createProjectBuilderSlice<AppConfig>({
101
- connector: yourDatabaseConnector,
102
- config: {
103
- // Include default discuss config
104
- ...createDefaultDiscussConfig(),
105
- // Your other config...
106
- layout: {
107
- /* your layout */
92
+ export const {roomStore, useRoomStore} = createRoomStore<RoomConfig, RoomState>(
93
+ (set, get, store) => ({
94
+ // Add the discuss slice with a user ID
95
+ ...createDiscussSlice({userId: 'current-user-id'})(set, get, store),
96
+
97
+ // Add your room shell slice
98
+ ...createRoomShellSlice<RoomConfig>({
99
+ connector: yourDatabaseConnector,
100
+ config: {
101
+ // Include default discuss config
102
+ ...createDefaultDiscussConfig(),
103
+ // Your other config...
104
+ layout: {
105
+ /* your layout */
106
+ },
107
+ dataSources: [
108
+ /* your data sources */
109
+ ],
108
110
  },
109
- dataSources: [
110
- /* your data sources */
111
- ],
112
- },
113
- project: {
114
- // Your project configuration
115
- },
116
- })(set, get, store),
117
- }));
111
+ room: {
112
+ // Your room configuration
113
+ },
114
+ })(set, get, store),
115
+ }),
116
+ );
118
117
  ```
119
118
 
120
119
  #### Using the Store Hook
@@ -1,4 +1,4 @@
1
- import { type ProjectBuilderState, type StateCreator, BaseProjectConfig } from '@sqlrooms/project-builder';
1
+ import { type RoomShellSliceState, type StateCreator, BaseRoomConfig } from '@sqlrooms/room-shell';
2
2
  import { z } from 'zod';
3
3
  export declare const CommentBase: z.ZodObject<{
4
4
  id: z.ZodString;
@@ -364,12 +364,12 @@ export type DiscussSliceState = {
364
364
  removeComment: (discussionId: string, commentId: string) => void;
365
365
  };
366
366
  };
367
- export type ProjectStateWithDiscussion = ProjectBuilderState<BaseProjectConfig> & DiscussSliceState;
368
- export declare function createDiscussSlice<PC extends BaseProjectConfig & DiscussSliceConfig>({ userId }: {
367
+ export type RoomStateWithDiscussion = RoomShellSliceState<BaseRoomConfig> & DiscussSliceState;
368
+ export declare function createDiscussSlice<PC extends BaseRoomConfig & DiscussSliceConfig>({ userId }: {
369
369
  userId: string;
370
370
  }): StateCreator<DiscussSliceState>;
371
- type ProjectConfigWithDiscuss = BaseProjectConfig & DiscussSliceConfig;
372
- type ProjectStateWithDiscuss = ProjectBuilderState<ProjectConfigWithDiscuss> & DiscussSliceState;
373
- export declare function useStoreWithDiscussion<T>(selector: (state: ProjectStateWithDiscuss) => T): T;
371
+ type RoomConfigWithDiscuss = BaseRoomConfig & DiscussSliceConfig;
372
+ type RoomStateWithDiscuss = RoomShellSliceState<RoomConfigWithDiscuss> & DiscussSliceState;
373
+ export declare function useStoreWithDiscussion<T>(selector: (state: RoomStateWithDiscuss) => T): T;
374
374
  export {};
375
375
  //# sourceMappingURL=DiscussSlice.d.ts.map
@@ -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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"}
@@ -1,5 +1,5 @@
1
1
  import { createId } from '@paralleldrive/cuid2';
2
- import { createSlice, useBaseProjectBuilderStore, } from '@sqlrooms/project-builder';
2
+ import { createSlice, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
3
3
  import { produce } from 'immer';
4
4
  import { z } from 'zod';
5
5
  // Base type with common fields
@@ -311,6 +311,6 @@ export function createDiscussSlice({ userId }) {
311
311
  }));
312
312
  }
313
313
  export function useStoreWithDiscussion(selector) {
314
- return useBaseProjectBuilderStore((state) => selector(state));
314
+ return useBaseRoomShellStore((state) => selector(state));
315
315
  }
316
316
  //# sourceMappingURL=DiscussSlice.js.map
@@ -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 useBaseProjectBuilderStore,\n type ProjectBuilderState,\n type StateCreator,\n BaseProjectConfig,\n} from '@sqlrooms/project-builder';\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 ProjectStateWithDiscussion =\n ProjectBuilderState<BaseProjectConfig> & DiscussSliceState;\n\nexport function createDiscussSlice<\n PC extends BaseProjectConfig & 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 ProjectConfigWithDiscuss = BaseProjectConfig & DiscussSliceConfig;\ntype ProjectStateWithDiscuss = ProjectBuilderState<ProjectConfigWithDiscuss> &\n DiscussSliceState;\n\nexport function useStoreWithDiscussion<T>(\n selector: (state: ProjectStateWithDiscuss) => T,\n): T {\n return useBaseProjectBuilderStore<\n BaseProjectConfig & DiscussSliceConfig,\n ProjectStateWithDiscuss,\n T\n >((state) => selector(state as ProjectStateWithDiscuss));\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 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"]}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @packageDocumentation
4
4
  */
5
5
  export { DiscussionList } from './DiscussionList';
6
- export { Comment, createDefaultDiscussConfig, createDiscussSlice, Discussion, DiscussSliceConfig, useStoreWithDiscussion, type DiscussSliceState, type ProjectStateWithDiscussion, } from './DiscussSlice';
6
+ export { Comment, createDefaultDiscussConfig, createDiscussSlice, Discussion, DiscussSliceConfig, useStoreWithDiscussion, type DiscussSliceState, type RoomStateWithDiscussion, } from './DiscussSlice';
7
7
  export { CommentItem } from './components/CommentItem';
8
8
  export { DeleteConfirmDialog } from './components/DeleteConfirmDialog';
9
9
  export { DiscussionItem } from './components/DiscussionItem';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EACL,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,GAChC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EACL,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EACL,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {DiscussionList} from './DiscussionList';\nexport {\n Comment,\n createDefaultDiscussConfig,\n createDiscussSlice,\n Discussion,\n DiscussSliceConfig,\n useStoreWithDiscussion,\n type DiscussSliceState,\n type ProjectStateWithDiscussion,\n} from './DiscussSlice';\n\nexport {CommentItem} from './components/CommentItem';\nexport {DeleteConfirmDialog} from './components/DeleteConfirmDialog';\nexport {DiscussionItem} from './components/DiscussionItem';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EACL,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {DiscussionList} from './DiscussionList';\nexport {\n Comment,\n createDefaultDiscussConfig,\n createDiscussSlice,\n Discussion,\n DiscussSliceConfig,\n useStoreWithDiscussion,\n type DiscussSliceState,\n type RoomStateWithDiscussion,\n} from './DiscussSlice';\n\nexport {CommentItem} from './components/CommentItem';\nexport {DeleteConfirmDialog} from './components/DeleteConfirmDialog';\nexport {DiscussionItem} from './components/DiscussionItem';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/discuss",
3
- "version": "0.16.4",
3
+ "version": "0.18.0",
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/project-builder": "0.16.4",
20
- "@sqlrooms/ui": "0.16.4",
21
- "@sqlrooms/utils": "0.16.4",
19
+ "@sqlrooms/room-shell": "0.18.0",
20
+ "@sqlrooms/ui": "0.18.0",
21
+ "@sqlrooms/utils": "0.18.0",
22
22
  "immer": "^10.1.1",
23
23
  "zod": "^3.25.57"
24
24
  },
@@ -32,5 +32,5 @@
32
32
  "lint": "eslint .",
33
33
  "typedoc": "typedoc"
34
34
  },
35
- "gitHead": "4049fe4dd411de90234d5f573d63da22d3eb4835"
35
+ "gitHead": "c1c06c9549ca74b9d4f515f6667b77d3196652df"
36
36
  }