@happyvertical/smrt-chat 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/AGENTS.md +35 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +163 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/chunks/ChatService-Dpzc1Pa5.js +2044 -0
  8. package/dist/chunks/ChatService-Dpzc1Pa5.js.map +1 -0
  9. package/dist/collections/AgentSessionCollection.d.ts +57 -0
  10. package/dist/collections/AgentSessionCollection.d.ts.map +1 -0
  11. package/dist/collections/ChatMessageCollection.d.ts +79 -0
  12. package/dist/collections/ChatMessageCollection.d.ts.map +1 -0
  13. package/dist/collections/ChatParticipantCollection.d.ts +26 -0
  14. package/dist/collections/ChatParticipantCollection.d.ts.map +1 -0
  15. package/dist/collections/ChatReactionCollection.d.ts +23 -0
  16. package/dist/collections/ChatReactionCollection.d.ts.map +1 -0
  17. package/dist/collections/ChatRoomCollection.d.ts +43 -0
  18. package/dist/collections/ChatRoomCollection.d.ts.map +1 -0
  19. package/dist/collections/ChatThreadCollection.d.ts +9 -0
  20. package/dist/collections/ChatThreadCollection.d.ts.map +1 -0
  21. package/dist/index.d.ts +5 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +18 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/internal/agent-runtime.d.ts +16 -0
  26. package/dist/internal/agent-runtime.d.ts.map +1 -0
  27. package/dist/internal/agent-runtime.js +5 -0
  28. package/dist/internal/agent-runtime.js.map +1 -0
  29. package/dist/manifest.json +2811 -0
  30. package/dist/models/AgentSession.d.ts +70 -0
  31. package/dist/models/AgentSession.d.ts.map +1 -0
  32. package/dist/models/ChatMessage.d.ts +55 -0
  33. package/dist/models/ChatMessage.d.ts.map +1 -0
  34. package/dist/models/ChatParticipant.d.ts +32 -0
  35. package/dist/models/ChatParticipant.d.ts.map +1 -0
  36. package/dist/models/ChatReaction.d.ts +19 -0
  37. package/dist/models/ChatReaction.d.ts.map +1 -0
  38. package/dist/models/ChatRoom.d.ts +44 -0
  39. package/dist/models/ChatRoom.d.ts.map +1 -0
  40. package/dist/models/ChatThread.d.ts +24 -0
  41. package/dist/models/ChatThread.d.ts.map +1 -0
  42. package/dist/models/index.d.ts +7 -0
  43. package/dist/models/index.d.ts.map +1 -0
  44. package/dist/playground.d.ts +2 -0
  45. package/dist/playground.d.ts.map +1 -0
  46. package/dist/playground.js +166 -0
  47. package/dist/playground.js.map +1 -0
  48. package/dist/services/ChatService.d.ts +390 -0
  49. package/dist/services/ChatService.d.ts.map +1 -0
  50. package/dist/services/index.d.ts +2 -0
  51. package/dist/services/index.d.ts.map +1 -0
  52. package/dist/smrt-knowledge.json +1507 -0
  53. package/dist/svelte/components/agent/AgentChat.svelte +542 -0
  54. package/dist/svelte/components/agent/AgentChat.svelte.d.ts +21 -0
  55. package/dist/svelte/components/agent/AgentChat.svelte.d.ts.map +1 -0
  56. package/dist/svelte/components/agent/AgentSelector.svelte +175 -0
  57. package/dist/svelte/components/agent/AgentSelector.svelte.d.ts +11 -0
  58. package/dist/svelte/components/agent/AgentSelector.svelte.d.ts.map +1 -0
  59. package/dist/svelte/components/agent/AgentSessionPanel.svelte +322 -0
  60. package/dist/svelte/components/agent/AgentSessionPanel.svelte.d.ts +15 -0
  61. package/dist/svelte/components/agent/AgentSessionPanel.svelte.d.ts.map +1 -0
  62. package/dist/svelte/components/agent/ToolCallDisplay.svelte +335 -0
  63. package/dist/svelte/components/agent/ToolCallDisplay.svelte.d.ts +9 -0
  64. package/dist/svelte/components/agent/ToolCallDisplay.svelte.d.ts.map +1 -0
  65. package/dist/svelte/components/agent/message-blocks.d.ts +12 -0
  66. package/dist/svelte/components/agent/message-blocks.d.ts.map +1 -0
  67. package/dist/svelte/components/agent/message-blocks.js +41 -0
  68. package/dist/svelte/components/agent/message-blocks.test.js +31 -0
  69. package/dist/svelte/components/dialogs/RoomCreateDialog.svelte +403 -0
  70. package/dist/svelte/components/dialogs/RoomCreateDialog.svelte.d.ts +16 -0
  71. package/dist/svelte/components/dialogs/RoomCreateDialog.svelte.d.ts.map +1 -0
  72. package/dist/svelte/components/dialogs/SearchMessages.svelte +457 -0
  73. package/dist/svelte/components/dialogs/SearchMessages.svelte.d.ts +17 -0
  74. package/dist/svelte/components/dialogs/SearchMessages.svelte.d.ts.map +1 -0
  75. package/dist/svelte/components/layout/ChatLayout.svelte +150 -0
  76. package/dist/svelte/components/layout/ChatLayout.svelte.d.ts +18 -0
  77. package/dist/svelte/components/layout/ChatLayout.svelte.d.ts.map +1 -0
  78. package/dist/svelte/components/layout/MemberList.svelte +389 -0
  79. package/dist/svelte/components/layout/MemberList.svelte.d.ts +11 -0
  80. package/dist/svelte/components/layout/MemberList.svelte.d.ts.map +1 -0
  81. package/dist/svelte/components/layout/RoomHeader.svelte +241 -0
  82. package/dist/svelte/components/layout/RoomHeader.svelte.d.ts +15 -0
  83. package/dist/svelte/components/layout/RoomHeader.svelte.d.ts.map +1 -0
  84. package/dist/svelte/components/layout/RoomList.svelte +471 -0
  85. package/dist/svelte/components/layout/RoomList.svelte.d.ts +15 -0
  86. package/dist/svelte/components/layout/RoomList.svelte.d.ts.map +1 -0
  87. package/dist/svelte/components/messages/MessageInput.svelte +232 -0
  88. package/dist/svelte/components/messages/MessageInput.svelte.d.ts +20 -0
  89. package/dist/svelte/components/messages/MessageInput.svelte.d.ts.map +1 -0
  90. package/dist/svelte/components/messages/MessageItem.svelte +431 -0
  91. package/dist/svelte/components/messages/MessageItem.svelte.d.ts +19 -0
  92. package/dist/svelte/components/messages/MessageItem.svelte.d.ts.map +1 -0
  93. package/dist/svelte/components/messages/MessageList.svelte +129 -0
  94. package/dist/svelte/components/messages/MessageList.svelte.d.ts +17 -0
  95. package/dist/svelte/components/messages/MessageList.svelte.d.ts.map +1 -0
  96. package/dist/svelte/components/messages/ThreadPanel.svelte +156 -0
  97. package/dist/svelte/components/messages/ThreadPanel.svelte.d.ts +17 -0
  98. package/dist/svelte/components/messages/ThreadPanel.svelte.d.ts.map +1 -0
  99. package/dist/svelte/components/messages/__tests__/MessageInput.test.js +38 -0
  100. package/dist/svelte/components/shared/Avatar.svelte +30 -0
  101. package/dist/svelte/components/shared/Avatar.svelte.d.ts +14 -0
  102. package/dist/svelte/components/shared/Avatar.svelte.d.ts.map +1 -0
  103. package/dist/svelte/components/shared/FileUpload.svelte +382 -0
  104. package/dist/svelte/components/shared/FileUpload.svelte.d.ts +14 -0
  105. package/dist/svelte/components/shared/FileUpload.svelte.d.ts.map +1 -0
  106. package/dist/svelte/components/shared/LinkPreview.svelte +108 -0
  107. package/dist/svelte/components/shared/LinkPreview.svelte.d.ts +18 -0
  108. package/dist/svelte/components/shared/LinkPreview.svelte.d.ts.map +1 -0
  109. package/dist/svelte/components/shared/MentionAutocomplete.svelte +168 -0
  110. package/dist/svelte/components/shared/MentionAutocomplete.svelte.d.ts +18 -0
  111. package/dist/svelte/components/shared/MentionAutocomplete.svelte.d.ts.map +1 -0
  112. package/dist/svelte/components/shared/MessageBubble.svelte +81 -0
  113. package/dist/svelte/components/shared/MessageBubble.svelte.d.ts +16 -0
  114. package/dist/svelte/components/shared/MessageBubble.svelte.d.ts.map +1 -0
  115. package/dist/svelte/components/shared/ReactionPicker.svelte +103 -0
  116. package/dist/svelte/components/shared/ReactionPicker.svelte.d.ts +10 -0
  117. package/dist/svelte/components/shared/ReactionPicker.svelte.d.ts.map +1 -0
  118. package/dist/svelte/components/shared/ReadReceipts.svelte +127 -0
  119. package/dist/svelte/components/shared/ReadReceipts.svelte.d.ts +13 -0
  120. package/dist/svelte/components/shared/ReadReceipts.svelte.d.ts.map +1 -0
  121. package/dist/svelte/components/shared/TypingIndicator.svelte +90 -0
  122. package/dist/svelte/components/shared/TypingIndicator.svelte.d.ts +12 -0
  123. package/dist/svelte/components/shared/TypingIndicator.svelte.d.ts.map +1 -0
  124. package/dist/svelte/components/shared/UserPresence.svelte +65 -0
  125. package/dist/svelte/components/shared/UserPresence.svelte.d.ts +13 -0
  126. package/dist/svelte/components/shared/UserPresence.svelte.d.ts.map +1 -0
  127. package/dist/svelte/components/shared/__tests__/Avatar.test.js +20 -0
  128. package/dist/svelte/components/shared/__tests__/LinkPreview.test.js +29 -0
  129. package/dist/svelte/components/shared/__tests__/MessageBubble.test.js +21 -0
  130. package/dist/svelte/components/shared/__tests__/ReactionPicker.test.js +35 -0
  131. package/dist/svelte/components/shared/__tests__/ReadReceipts.test.js +28 -0
  132. package/dist/svelte/components/shared/__tests__/TypingIndicator.test.js +27 -0
  133. package/dist/svelte/components/shared/__tests__/UserPresence.test.js +23 -0
  134. package/dist/svelte/components/tabs/ChatTab.svelte +240 -0
  135. package/dist/svelte/components/tabs/ChatTab.svelte.d.ts +21 -0
  136. package/dist/svelte/components/tabs/ChatTab.svelte.d.ts.map +1 -0
  137. package/dist/svelte/components/tabs/ChatTabList.svelte +158 -0
  138. package/dist/svelte/components/tabs/ChatTabList.svelte.d.ts +13 -0
  139. package/dist/svelte/components/tabs/ChatTabList.svelte.d.ts.map +1 -0
  140. package/dist/svelte/components/tabs/ChatTabs.svelte +88 -0
  141. package/dist/svelte/components/tabs/ChatTabs.svelte.d.ts +21 -0
  142. package/dist/svelte/components/tabs/ChatTabs.svelte.d.ts.map +1 -0
  143. package/dist/svelte/components/tabs/MiniChat.svelte +253 -0
  144. package/dist/svelte/components/tabs/MiniChat.svelte.d.ts +15 -0
  145. package/dist/svelte/components/tabs/MiniChat.svelte.d.ts.map +1 -0
  146. package/dist/svelte/i18n.d.ts +51 -0
  147. package/dist/svelte/i18n.d.ts.map +1 -0
  148. package/dist/svelte/i18n.js +72 -0
  149. package/dist/svelte/i18n.messages.d.ts +50 -0
  150. package/dist/svelte/i18n.messages.d.ts.map +1 -0
  151. package/dist/svelte/i18n.messages.js +69 -0
  152. package/dist/svelte/index.d.ts +48 -0
  153. package/dist/svelte/index.d.ts.map +1 -0
  154. package/dist/svelte/index.js +117 -0
  155. package/dist/svelte/playground.d.ts +171 -0
  156. package/dist/svelte/playground.d.ts.map +1 -0
  157. package/dist/svelte/playground.js +161 -0
  158. package/dist/svelte/types.d.ts +116 -0
  159. package/dist/svelte/types.d.ts.map +1 -0
  160. package/dist/svelte/types.js +1 -0
  161. package/dist/types.d.ts +99 -0
  162. package/dist/types.d.ts.map +1 -0
  163. package/dist/types.js +2 -0
  164. package/dist/types.js.map +1 -0
  165. package/dist/ui.d.ts +4 -0
  166. package/dist/ui.d.ts.map +1 -0
  167. package/dist/ui.js +92 -0
  168. package/dist/ui.js.map +1 -0
  169. package/package.json +95 -0
@@ -0,0 +1,471 @@
1
+ <script lang="ts">
2
+ /**
3
+ * RoomList - Sidebar room navigation with grouping and unread badges
4
+ * Groups rooms by type: channels, DMs, and agent conversations
5
+ */
6
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
7
+ import { M } from '../../i18n.messages.js';
8
+ import type { ChatRoomData } from '../../types.js';
9
+
10
+ const { t } = useI18n();
11
+
12
+ export interface Props {
13
+ /** Available chat rooms */
14
+ rooms: ChatRoomData[];
15
+ /** Currently selected room ID */
16
+ currentRoomId?: string;
17
+ /** Callback when a room is selected */
18
+ onselectroom: (roomId: string) => void;
19
+ /** Callback to open create room dialog */
20
+ oncreateroom?: () => void;
21
+ }
22
+
23
+ let { rooms, currentRoomId, onselectroom, oncreateroom }: Props = $props();
24
+
25
+ let collapsedGroups = $state<Record<string, boolean>>({});
26
+
27
+ const channels = $derived(
28
+ rooms.filter((r) => r.roomType === 'public' || r.roomType === 'private'),
29
+ );
30
+ const directMessages = $derived(rooms.filter((r) => r.roomType === 'dm'));
31
+ const agentRooms = $derived(rooms.filter((r) => r.roomType === 'agent'));
32
+
33
+ function toggleGroup(group: string) {
34
+ collapsedGroups[group] = !collapsedGroups[group];
35
+ }
36
+
37
+ function getRoomIcon(room: ChatRoomData): string {
38
+ switch (room.roomType) {
39
+ case 'public':
40
+ return '#';
41
+ case 'private':
42
+ return '\u{1F512}';
43
+ case 'dm':
44
+ return '';
45
+ case 'agent':
46
+ return '';
47
+ default:
48
+ return '#';
49
+ }
50
+ }
51
+
52
+ function formatTimestamp(date?: string | Date | null): string {
53
+ if (!date) return '';
54
+ const d = typeof date === 'string' ? new Date(date) : date;
55
+ const now = new Date();
56
+ const diff = now.getTime() - d.getTime();
57
+ const oneDay = 86400000;
58
+ if (diff < oneDay) {
59
+ return d.toLocaleTimeString(undefined, {
60
+ hour: 'numeric',
61
+ minute: '2-digit',
62
+ });
63
+ }
64
+ if (diff < 7 * oneDay) {
65
+ return d.toLocaleDateString(undefined, { weekday: 'short' });
66
+ }
67
+ return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
68
+ }
69
+ </script>
70
+
71
+ <nav class="room-list" aria-label={t(M['chat.room_list.rooms_label'])}>
72
+ {#if oncreateroom}
73
+ <div class="room-list__header">
74
+ <button
75
+ class="create-room-btn"
76
+ type="button"
77
+ onclick={oncreateroom}
78
+ aria-label={t(M['chat.room_list.create_new_room'])}
79
+ >
80
+ {t(M['chat.room_list.new_room'])}
81
+ </button>
82
+ </div>
83
+ {/if}
84
+
85
+ {#if channels.length > 0}
86
+ <section class="room-group">
87
+ <button
88
+ class="room-group__header"
89
+ type="button"
90
+ onclick={() => toggleGroup('channels')}
91
+ aria-expanded={!collapsedGroups['channels']}
92
+ >
93
+ <span class="room-group__chevron" class:room-group__chevron--collapsed={collapsedGroups['channels']}>
94
+ &#9662;
95
+ </span>
96
+ <span class="room-group__label">Channels</span>
97
+ <span class="room-group__count">{channels.length}</span>
98
+ </button>
99
+
100
+ {#if !collapsedGroups['channels']}
101
+ <ul class="room-group__list" role="list">
102
+ {#each channels as room (room.id)}
103
+ <li>
104
+ <button
105
+ class="room-item"
106
+ class:room-item--active={room.id === currentRoomId}
107
+ class:room-item--muted={room.isMuted}
108
+ type="button"
109
+ onclick={() => onselectroom(room.id)}
110
+ aria-current={room.id === currentRoomId ? 'true' : undefined}
111
+ >
112
+ <span class="room-item__icon">{getRoomIcon(room)}</span>
113
+ <span class="room-item__name">{room.name}</span>
114
+ {#if room.unreadCount > 0}
115
+ <span class="unread-badge" aria-label={t(M['chat.room_list.unread_messages'], { count: room.unreadCount })}>
116
+ {room.unreadCount > 99 ? '99+' : room.unreadCount}
117
+ </span>
118
+ {/if}
119
+ </button>
120
+ </li>
121
+ {/each}
122
+ </ul>
123
+ {/if}
124
+ </section>
125
+ {/if}
126
+
127
+ {#if directMessages.length > 0}
128
+ <section class="room-group">
129
+ <button
130
+ class="room-group__header"
131
+ type="button"
132
+ onclick={() => toggleGroup('dms')}
133
+ aria-expanded={!collapsedGroups['dms']}
134
+ >
135
+ <span class="room-group__chevron" class:room-group__chevron--collapsed={collapsedGroups['dms']}>
136
+ &#9662;
137
+ </span>
138
+ <span class="room-group__label">{t(M['chat.room_list.direct_messages'])}</span>
139
+ <span class="room-group__count">{directMessages.length}</span>
140
+ </button>
141
+
142
+ {#if !collapsedGroups['dms']}
143
+ <ul class="room-group__list" role="list">
144
+ {#each directMessages as room (room.id)}
145
+ <li>
146
+ <button
147
+ class="room-item"
148
+ class:room-item--active={room.id === currentRoomId}
149
+ class:room-item--muted={room.isMuted}
150
+ type="button"
151
+ onclick={() => onselectroom(room.id)}
152
+ aria-current={room.id === currentRoomId ? 'true' : undefined}
153
+ >
154
+ {#if room.avatarUrl}
155
+ <img class="room-item__avatar" src={room.avatarUrl} alt="" />
156
+ {:else}
157
+ <span class="room-item__avatar-placeholder">
158
+ {room.name.charAt(0).toUpperCase()}
159
+ </span>
160
+ {/if}
161
+ <span class="room-item__details">
162
+ <span class="room-item__name">{room.name}</span>
163
+ {#if room.lastMessage}
164
+ <span class="room-item__preview">{room.lastMessage.content}</span>
165
+ {/if}
166
+ </span>
167
+ <span class="room-item__meta">
168
+ {#if room.lastMessageAt}
169
+ <span class="room-item__time">{formatTimestamp(room.lastMessageAt)}</span>
170
+ {/if}
171
+ {#if room.unreadCount > 0}
172
+ <span class="unread-badge" aria-label={t(M['chat.room_list.unread_messages'], { count: room.unreadCount })}>
173
+ {room.unreadCount > 99 ? '99+' : room.unreadCount}
174
+ </span>
175
+ {/if}
176
+ </span>
177
+ </button>
178
+ </li>
179
+ {/each}
180
+ </ul>
181
+ {/if}
182
+ </section>
183
+ {/if}
184
+
185
+ {#if agentRooms.length > 0}
186
+ <section class="room-group">
187
+ <button
188
+ class="room-group__header"
189
+ type="button"
190
+ onclick={() => toggleGroup('agents')}
191
+ aria-expanded={!collapsedGroups['agents']}
192
+ >
193
+ <span class="room-group__chevron" class:room-group__chevron--collapsed={collapsedGroups['agents']}>
194
+ &#9662;
195
+ </span>
196
+ <span class="room-group__label">Agents</span>
197
+ <span class="room-group__count">{agentRooms.length}</span>
198
+ </button>
199
+
200
+ {#if !collapsedGroups['agents']}
201
+ <ul class="room-group__list" role="list">
202
+ {#each agentRooms as room (room.id)}
203
+ <li>
204
+ <button
205
+ class="room-item"
206
+ class:room-item--active={room.id === currentRoomId}
207
+ type="button"
208
+ onclick={() => onselectroom(room.id)}
209
+ aria-current={room.id === currentRoomId ? 'true' : undefined}
210
+ >
211
+ <span class="room-item__agent-icon" aria-hidden="true">&#9881;</span>
212
+ <span class="room-item__name">{room.name}</span>
213
+ {#if room.unreadCount > 0}
214
+ <span class="unread-badge" aria-label={t(M['chat.room_list.unread_messages'], { count: room.unreadCount })}>
215
+ {room.unreadCount > 99 ? '99+' : room.unreadCount}
216
+ </span>
217
+ {/if}
218
+ </button>
219
+ </li>
220
+ {/each}
221
+ </ul>
222
+ {/if}
223
+ </section>
224
+ {/if}
225
+
226
+ {#if rooms.length === 0}
227
+ <div class="room-list__empty">
228
+ <p>{t(M['chat.room_list.no_rooms'])}</p>
229
+ {#if oncreateroom}
230
+ <button class="create-link" type="button" onclick={oncreateroom}>
231
+ {t(M['chat.room_list.create_first_room'])}
232
+ </button>
233
+ {/if}
234
+ </div>
235
+ {/if}
236
+ </nav>
237
+
238
+ <style>
239
+ .room-list {
240
+ display: flex;
241
+ flex-direction: column;
242
+ height: 100%;
243
+ padding: 0.5rem 0;
244
+ }
245
+
246
+ .room-list__header {
247
+ padding: 0.5rem 0.75rem;
248
+ }
249
+
250
+ .create-room-btn {
251
+ width: 100%;
252
+ padding: 0.5rem 0.75rem;
253
+ border: 1px dashed var(--smrt-color-outline, #74777f);
254
+ border-radius: var(--smrt-radius-medium, 0.5rem);
255
+ background: transparent;
256
+ color: var(--smrt-color-primary, #005ac1);
257
+ font: var(--smrt-typography-label-large-font, 500 0.875rem / 1.25 sans-serif);
258
+ cursor: pointer;
259
+ transition: background var(--smrt-duration-short2, 150ms);
260
+ }
261
+
262
+ .create-room-btn:hover {
263
+ background: var(--smrt-color-primary-container, #d6e3ff);
264
+ }
265
+
266
+ .create-room-btn:focus-visible {
267
+ outline: 2px solid var(--smrt-color-primary, #005ac1);
268
+ outline-offset: -2px;
269
+ }
270
+
271
+ .room-group {
272
+ margin-top: 0.25rem;
273
+ }
274
+
275
+ .room-group__header {
276
+ display: flex;
277
+ align-items: center;
278
+ gap: 0.25rem;
279
+ width: 100%;
280
+ padding: 0.375rem 0.75rem;
281
+ border: none;
282
+ background: none;
283
+ cursor: pointer;
284
+ font: var(--smrt-typography-label-small-font, 500 0.6875rem / 1 sans-serif);
285
+ color: var(--smrt-color-on-surface-variant, #43474e);
286
+ text-transform: uppercase;
287
+ letter-spacing: var(--smrt-typography-label-small-tracking, 0.05em);
288
+ }
289
+
290
+ .room-group__header:hover {
291
+ color: var(--smrt-color-on-surface, #1a1c1e);
292
+ }
293
+
294
+ .room-group__chevron {
295
+ font-size: var(--smrt-typography-label-small-size, 0.625rem);
296
+ transition: transform var(--smrt-duration-short2, 150ms);
297
+ }
298
+
299
+ .room-group__chevron--collapsed {
300
+ transform: rotate(-90deg);
301
+ }
302
+
303
+ .room-group__label {
304
+ flex: 1;
305
+ text-align: left;
306
+ }
307
+
308
+ .room-group__count {
309
+ color: var(--smrt-color-outline, #74777f);
310
+ font-size: var(--smrt-typography-label-small-size, 0.625rem);
311
+ }
312
+
313
+ .room-group__list {
314
+ list-style: none;
315
+ margin: 0;
316
+ padding: 0;
317
+ }
318
+
319
+ .room-item {
320
+ display: flex;
321
+ align-items: center;
322
+ gap: 0.5rem;
323
+ width: 100%;
324
+ padding: 0.375rem 0.75rem;
325
+ border: none;
326
+ background: none;
327
+ cursor: pointer;
328
+ font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
329
+ color: var(--smrt-color-on-surface, #1a1c1e);
330
+ border-radius: var(--smrt-radius-small, 0.25rem);
331
+ text-align: left;
332
+ transition: background var(--smrt-duration-short2, 150ms);
333
+ }
334
+
335
+ .room-item:hover {
336
+ background: var(--smrt-color-surface-variant, #e1e2ec);
337
+ }
338
+
339
+ .room-item--active {
340
+ background: var(--smrt-color-secondary-container, #d7e3f7);
341
+ font-weight: var(--smrt-typography-weight-medium, 500);
342
+ }
343
+
344
+ .room-item--muted {
345
+ opacity: 0.6;
346
+ }
347
+
348
+ .room-item:focus-visible {
349
+ outline: 2px solid var(--smrt-color-primary, #005ac1);
350
+ outline-offset: -2px;
351
+ }
352
+
353
+ .room-item__icon {
354
+ flex-shrink: 0;
355
+ width: 1.25rem;
356
+ text-align: center;
357
+ color: var(--smrt-color-on-surface-variant, #43474e);
358
+ font-weight: var(--smrt-typography-weight-semibold, 600);
359
+ }
360
+
361
+ .room-item__agent-icon {
362
+ flex-shrink: 0;
363
+ width: 1.25rem;
364
+ text-align: center;
365
+ font-size: var(--smrt-typography-body-large-size, 1rem);
366
+ }
367
+
368
+ .room-item__avatar {
369
+ flex-shrink: 0;
370
+ width: 2rem;
371
+ height: 2rem;
372
+ border-radius: var(--smrt-radius-full, 9999px);
373
+ object-fit: cover;
374
+ }
375
+
376
+ .room-item__avatar-placeholder {
377
+ flex-shrink: 0;
378
+ width: 2rem;
379
+ height: 2rem;
380
+ border-radius: var(--smrt-radius-full, 9999px);
381
+ background: var(--smrt-color-primary-container, #d6e3ff);
382
+ color: var(--smrt-color-on-primary-container, #001a41);
383
+ display: inline-flex;
384
+ align-items: center;
385
+ justify-content: center;
386
+ font: var(--smrt-typography-label-medium-font, 500 0.75rem / 1 sans-serif);
387
+ }
388
+
389
+ .room-item__details {
390
+ flex: 1;
391
+ min-width: 0;
392
+ display: flex;
393
+ flex-direction: column;
394
+ gap: 0.125rem;
395
+ }
396
+
397
+ .room-item__name {
398
+ flex: 1;
399
+ overflow: hidden;
400
+ text-overflow: ellipsis;
401
+ white-space: nowrap;
402
+ }
403
+
404
+ .room-item__preview {
405
+ font: var(--smrt-typography-body-small-font, 0.75rem / 1.25 sans-serif);
406
+ color: var(--smrt-color-on-surface-variant, #43474e);
407
+ overflow: hidden;
408
+ text-overflow: ellipsis;
409
+ white-space: nowrap;
410
+ }
411
+
412
+ .room-item__meta {
413
+ flex-shrink: 0;
414
+ display: flex;
415
+ flex-direction: column;
416
+ align-items: flex-end;
417
+ gap: 0.25rem;
418
+ }
419
+
420
+ .room-item__time {
421
+ font: var(--smrt-typography-label-small-font, 500 0.6875rem / 1 sans-serif);
422
+ color: var(--smrt-color-on-surface-variant, #43474e);
423
+ }
424
+
425
+ .unread-badge {
426
+ flex-shrink: 0;
427
+ min-width: 1.25rem;
428
+ height: 1.25rem;
429
+ display: inline-flex;
430
+ align-items: center;
431
+ justify-content: center;
432
+ border-radius: var(--smrt-radius-full, 9999px);
433
+ background: var(--smrt-color-primary, #005ac1);
434
+ color: var(--smrt-color-on-primary, #fff);
435
+ font: var(--smrt-typography-label-small-font, 500 0.6875rem / 1 sans-serif);
436
+ padding: 0 0.25rem;
437
+ }
438
+
439
+ .room-list__empty {
440
+ display: flex;
441
+ flex-direction: column;
442
+ align-items: center;
443
+ justify-content: center;
444
+ gap: 0.5rem;
445
+ padding: 2rem 1rem;
446
+ text-align: center;
447
+ color: var(--smrt-color-on-surface-variant, #43474e);
448
+ }
449
+
450
+ .room-list__empty p {
451
+ margin: 0;
452
+ font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
453
+ }
454
+
455
+ .create-link {
456
+ border: none;
457
+ background: none;
458
+ color: var(--smrt-color-primary, #005ac1);
459
+ font: var(--smrt-typography-label-large-font, 500 0.875rem / 1.25 sans-serif);
460
+ cursor: pointer;
461
+ text-decoration: underline;
462
+ }
463
+
464
+ @media (prefers-reduced-motion: reduce) {
465
+ .room-item,
466
+ .create-room-btn,
467
+ .room-group__chevron {
468
+ transition: none;
469
+ }
470
+ }
471
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { ChatRoomData } from '../../types.js';
2
+ export interface Props {
3
+ /** Available chat rooms */
4
+ rooms: ChatRoomData[];
5
+ /** Currently selected room ID */
6
+ currentRoomId?: string;
7
+ /** Callback when a room is selected */
8
+ onselectroom: (roomId: string) => void;
9
+ /** Callback to open create room dialog */
10
+ oncreateroom?: () => void;
11
+ }
12
+ declare const RoomList: import("svelte").Component<Props, {}, "">;
13
+ type RoomList = ReturnType<typeof RoomList>;
14
+ export default RoomList;
15
+ //# sourceMappingURL=RoomList.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoomList.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/layout/RoomList.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,MAAM,WAAW,KAAK;IACpB,2BAA2B;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AA6LD,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}