@memori.ai/memori-react 8.44.0 → 8.45.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 (126) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/MemoriWidget/MemoriWidget.d.ts +1 -0
  3. package/dist/components/MemoriWidget/MemoriWidget.js +59 -1
  4. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  5. package/dist/helpers/nats/getNatsConfig.d.ts +1 -1
  6. package/dist/helpers/nats/getNatsConfig.js +2 -2
  7. package/dist/helpers/nats/getNatsConfig.js.map +1 -1
  8. package/dist/helpers/nats/useNats.d.ts +2 -1
  9. package/dist/helpers/nats/useNats.js +87 -20
  10. package/dist/helpers/nats/useNats.js.map +1 -1
  11. package/dist/helpers/nats/useNatsSession.d.ts +6 -1
  12. package/dist/helpers/nats/useNatsSession.js +49 -8
  13. package/dist/helpers/nats/useNatsSession.js.map +1 -1
  14. package/dist/version.d.ts +1 -1
  15. package/dist/version.js +1 -1
  16. package/esm/components/MemoriWidget/MemoriWidget.d.ts +1 -0
  17. package/esm/components/MemoriWidget/MemoriWidget.js +57 -1
  18. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  19. package/esm/helpers/nats/getNatsConfig.d.ts +1 -1
  20. package/esm/helpers/nats/getNatsConfig.js +2 -2
  21. package/esm/helpers/nats/getNatsConfig.js.map +1 -1
  22. package/esm/helpers/nats/useNats.d.ts +2 -1
  23. package/esm/helpers/nats/useNats.js +87 -20
  24. package/esm/helpers/nats/useNats.js.map +1 -1
  25. package/esm/helpers/nats/useNatsSession.d.ts +6 -1
  26. package/esm/helpers/nats/useNatsSession.js +48 -8
  27. package/esm/helpers/nats/useNatsSession.js.map +1 -1
  28. package/esm/version.d.ts +1 -1
  29. package/esm/version.js +1 -1
  30. package/package.json +1 -1
  31. package/src/components/MemoriWidget/MemoriWidget.tsx +65 -1
  32. package/src/helpers/nats/getNatsConfig.ts +8 -3
  33. package/src/helpers/nats/useNats.test.tsx +81 -0
  34. package/src/helpers/nats/useNats.ts +109 -29
  35. package/src/helpers/nats/useNatsSession.test.ts +16 -0
  36. package/src/helpers/nats/useNatsSession.ts +79 -13
  37. package/src/version.ts +1 -1
  38. package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.css +0 -372
  39. package/dist/components/DrawerFooter/DrawerFooter.css +0 -62
  40. package/dist/components/IconButton/IconButton.css +0 -144
  41. package/dist/components/MobileSessionPanel/MobileSessionPanel.css +0 -459
  42. package/dist/components/PositionPopover/PositionPopover.css +0 -219
  43. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +0 -806
  44. package/dist/components/layouts/fullpage.css +0 -522
  45. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.css +0 -372
  46. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.d.ts +0 -36
  47. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js +0 -113
  48. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js.map +0 -1
  49. package/esm/components/DrawerFooter/DrawerFooter.css +0 -62
  50. package/esm/components/DrawerFooter/DrawerFooter.d.ts +0 -12
  51. package/esm/components/DrawerFooter/DrawerFooter.js +0 -8
  52. package/esm/components/DrawerFooter/DrawerFooter.js.map +0 -1
  53. package/esm/components/IconButton/IconButton.css +0 -144
  54. package/esm/components/IconButton/IconButton.d.ts +0 -9
  55. package/esm/components/IconButton/IconButton.js +0 -33
  56. package/esm/components/IconButton/IconButton.js.map +0 -1
  57. package/esm/components/MobileSessionPanel/MobileSessionPanel.css +0 -459
  58. package/esm/components/MobileSessionPanel/MobileSessionPanel.d.ts +0 -65
  59. package/esm/components/MobileSessionPanel/MobileSessionPanel.js +0 -291
  60. package/esm/components/MobileSessionPanel/MobileSessionPanel.js.map +0 -1
  61. package/esm/components/PositionPopover/PositionPopover.css +0 -219
  62. package/esm/components/PositionPopover/PositionPopover.d.ts +0 -22
  63. package/esm/components/PositionPopover/PositionPopover.js +0 -190
  64. package/esm/components/PositionPopover/PositionPopover.js.map +0 -1
  65. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.d.ts +0 -4
  66. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +0 -61
  67. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +0 -1
  68. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +0 -806
  69. package/esm/components/layouts/fullpage.css +0 -522
  70. package/esm/context/widgetSurfaceContext.d.ts +0 -3
  71. package/esm/context/widgetSurfaceContext.js +0 -7
  72. package/esm/context/widgetSurfaceContext.js.map +0 -1
  73. package/esm/helpers/positionPopover.d.ts +0 -1
  74. package/esm/helpers/positionPopover.js +0 -4
  75. package/esm/helpers/positionPopover.js.map +0 -1
  76. package/esm/helpers/tts/muteSpeaker.d.ts +0 -13
  77. package/esm/helpers/tts/muteSpeaker.js +0 -21
  78. package/esm/helpers/tts/muteSpeaker.js.map +0 -1
  79. package/esm/helpers/usePressTooltip.d.ts +0 -13
  80. package/esm/helpers/usePressTooltip.js +0 -20
  81. package/esm/helpers/usePressTooltip.js.map +0 -1
  82. package/esm/icons/FacebookIcon.d.ts +0 -3
  83. package/esm/icons/FacebookIcon.js +0 -4
  84. package/esm/icons/FacebookIcon.js.map +0 -1
  85. package/esm/icons/LinkedinIcon.d.ts +0 -3
  86. package/esm/icons/LinkedinIcon.js +0 -4
  87. package/esm/icons/LinkedinIcon.js.map +0 -1
  88. package/esm/icons/MemoriIcon.d.ts +0 -3
  89. package/esm/icons/MemoriIcon.js +0 -6
  90. package/esm/icons/MemoriIcon.js.map +0 -1
  91. package/esm/icons/TelegramIcon.d.ts +0 -3
  92. package/esm/icons/TelegramIcon.js +0 -4
  93. package/esm/icons/TelegramIcon.js.map +0 -1
  94. package/esm/icons/TwitterIcon.d.ts +0 -3
  95. package/esm/icons/TwitterIcon.js +0 -4
  96. package/esm/icons/TwitterIcon.js.map +0 -1
  97. package/esm/icons/WhatsappIcon.d.ts +0 -3
  98. package/esm/icons/WhatsappIcon.js +0 -4
  99. package/esm/icons/WhatsappIcon.js.map +0 -1
  100. package/esm/icons/artifacts/DocumentIcon.d.ts +0 -3
  101. package/esm/icons/artifacts/DocumentIcon.js +0 -4
  102. package/esm/icons/artifacts/DocumentIcon.js.map +0 -1
  103. package/esm/icons/artifacts/HtmlIcon.d.ts +0 -3
  104. package/esm/icons/artifacts/HtmlIcon.js +0 -4
  105. package/esm/icons/artifacts/HtmlIcon.js.map +0 -1
  106. package/esm/icons/artifacts/JavascriptIcon.d.ts +0 -3
  107. package/esm/icons/artifacts/JavascriptIcon.js +0 -4
  108. package/esm/icons/artifacts/JavascriptIcon.js.map +0 -1
  109. package/esm/icons/artifacts/MarkdownIcon.d.ts +0 -3
  110. package/esm/icons/artifacts/MarkdownIcon.js +0 -4
  111. package/esm/icons/artifacts/MarkdownIcon.js.map +0 -1
  112. package/esm/icons/artifacts/PythonIcon.d.ts +0 -3
  113. package/esm/icons/artifacts/PythonIcon.js +0 -4
  114. package/esm/icons/artifacts/PythonIcon.js.map +0 -1
  115. package/esm/icons/artifacts/SvgIcon.d.ts +0 -3
  116. package/esm/icons/artifacts/SvgIcon.js +0 -4
  117. package/esm/icons/artifacts/SvgIcon.js.map +0 -1
  118. package/esm/icons/artifacts/XmlIcon.d.ts +0 -3
  119. package/esm/icons/artifacts/XmlIcon.js +0 -4
  120. package/esm/icons/artifacts/XmlIcon.js.map +0 -1
  121. package/esm/icons/artifacts/cssIcon.d.ts +0 -3
  122. package/esm/icons/artifacts/cssIcon.js +0 -4
  123. package/esm/icons/artifacts/cssIcon.js.map +0 -1
  124. package/esm/testUtils.d.ts +0 -5
  125. package/esm/testUtils.js +0 -15
  126. package/esm/testUtils.js.map +0 -1
@@ -11,7 +11,13 @@
11
11
  // The cleanup (`consumerMessages.stop()` + `nc.close()`) is essential: without
12
12
  // it, every `sessionId` change would leave orphan connections / iterators.
13
13
  import { useEffect, useRef, useState, type MutableRefObject } from 'react';
14
- import { wsconnect, NatsConnection } from '@nats-io/nats-core';
14
+ import {
15
+ wsconnect,
16
+ jwtAuthenticator,
17
+ AuthorizationError,
18
+ NatsConnection,
19
+ UserAuthenticationExpiredError,
20
+ } from '@nats-io/nats-core';
15
21
  import {
16
22
  jetstream,
17
23
  DeliverPolicy,
@@ -66,6 +72,24 @@ export type NatsSessionEvent =
66
72
 
67
73
  type JetStreamConsumeMode = 'live' | 'catch-up';
68
74
 
75
+ export interface NatsSessionLifecycle {
76
+ /** Called after the live subscription is installed. */
77
+ onConnected?: () => void;
78
+ /** Called once when this connection is rejected because its JWT expired. */
79
+ onAuthError?: (error: Error) => void;
80
+ }
81
+
82
+ export function isNatsAuthError(error: unknown): error is Error {
83
+ return (
84
+ error instanceof AuthorizationError ||
85
+ error instanceof UserAuthenticationExpiredError ||
86
+ (error instanceof Error &&
87
+ /authorization violation|authentication expired|user authentication expired/i.test(
88
+ error.message
89
+ ))
90
+ );
91
+ }
92
+
69
93
  function readString(
70
94
  raw: Record<string, unknown>,
71
95
  camelKey: string,
@@ -107,7 +131,9 @@ function unwrapDialogState(value: unknown): unknown {
107
131
  /**
108
132
  * Normalizes raw NATS payloads (snake_case or camelCase) into typed events.
109
133
  */
110
- export function normalizeNatsEvent(raw: Record<string, unknown>): NatsSessionEvent {
134
+ export function normalizeNatsEvent(
135
+ raw: Record<string, unknown>
136
+ ): NatsSessionEvent {
111
137
  const eventType = (readString(raw, 'eventType', 'event_type') ??
112
138
  'unknown') as NatsSessionEvent['eventType'];
113
139
 
@@ -130,8 +156,7 @@ export function normalizeNatsEvent(raw: Record<string, unknown>): NatsSessionEve
130
156
  if (eventType === 'dialog_text_entered_response') {
131
157
  return {
132
158
  eventType: 'dialog_text_entered_response',
133
- requestID:
134
- typeof raw.requestID === 'string' ? raw.requestID : undefined,
159
+ requestID: typeof raw.requestID === 'string' ? raw.requestID : undefined,
135
160
  resultCode:
136
161
  typeof raw.resultCode === 'number' ? raw.resultCode : undefined,
137
162
  resultMessage:
@@ -144,7 +169,10 @@ export function normalizeNatsEvent(raw: Record<string, unknown>): NatsSessionEve
144
169
  if (eventType === 'error') {
145
170
  return {
146
171
  eventType: 'error',
147
- errorCode: (raw.errorCode ?? raw.error_code) as string | number | undefined,
172
+ errorCode: (raw.errorCode ?? raw.error_code) as
173
+ | string
174
+ | number
175
+ | undefined,
148
176
  errorMessage: readString(raw, 'errorMessage', 'error_message'),
149
177
  backtrace: typeof raw.backtrace === 'string' ? raw.backtrace : undefined,
150
178
  correlationID,
@@ -174,10 +202,12 @@ function decodeMessage(
174
202
  async function consumeCoreSubscription(
175
203
  nc: NatsConnection,
176
204
  subject: string,
177
- onMessage: (event: NatsSessionEvent) => void
205
+ onMessage: (event: NatsSessionEvent) => void,
206
+ onReady: () => void
178
207
  ) {
179
208
  const sub = nc.subscribe(subject);
180
209
  console.info('[NATS] subscribed to subject', subject);
210
+ onReady();
181
211
  let received = 0;
182
212
  for await (const msg of sub) {
183
213
  received += 1;
@@ -203,7 +233,8 @@ async function consumeJetStream(
203
233
  subject: string,
204
234
  mode: JetStreamConsumeMode,
205
235
  onMessage: (event: NatsSessionEvent) => void,
206
- setConsumerMessages: (messages: ConsumerMessages) => void
236
+ setConsumerMessages: (messages: ConsumerMessages) => void,
237
+ onReady: () => void
207
238
  ) {
208
239
  const js = jetstream(nc);
209
240
  const consumer = config.consumer
@@ -225,6 +256,7 @@ async function consumeJetStream(
225
256
 
226
257
  const messages = await consumer.consume();
227
258
  setConsumerMessages(messages);
259
+ onReady();
228
260
  let received = 0;
229
261
  for await (const msg of messages) {
230
262
  received += 1;
@@ -258,17 +290,19 @@ function closeNatsSession(
258
290
  * change.
259
291
  *
260
292
  * @param sessionId Current session UUID (subscription is skipped when falsy).
261
- * @param config Connection config from `/api/nats` (url + token required).
293
+ * @param config Connection config from `/api/nats` (url + per-session JWT).
262
294
  * @param onMessage Callback invoked for each decoded event.
263
295
  */
264
296
  export function useNatsSession(
265
297
  sessionId: string | undefined,
266
298
  config: NatsConfig | undefined,
267
- onMessage: (event: NatsSessionEvent) => void
299
+ onMessage: (event: NatsSessionEvent) => void,
300
+ lifecycle: NatsSessionLifecycle = {}
268
301
  ) {
269
302
  const connRef = useRef<NatsConnection | null>(null);
270
303
  const consumerMessagesRef = useRef<ConsumerMessages | null>(null);
271
304
  const onMessageRef = useRef(onMessage);
305
+ const lifecycleRef = useRef(lifecycle);
272
306
  const wasHiddenRef = useRef(false);
273
307
  const [resumeGeneration, setResumeGeneration] = useState(0);
274
308
 
@@ -277,6 +311,10 @@ export function useNatsSession(
277
311
  onMessageRef.current = onMessage;
278
312
  }, [onMessage]);
279
313
 
314
+ useEffect(() => {
315
+ lifecycleRef.current = lifecycle;
316
+ }, [lifecycle]);
317
+
280
318
  // Reconnect when the tab returns from background or the network comes back.
281
319
  useEffect(() => {
282
320
  if (!sessionId || !config?.stream) {
@@ -348,7 +386,7 @@ export function useNatsSession(
348
386
  );
349
387
  const nc = await wsconnect({
350
388
  servers: [config.url],
351
- token: config.token,
389
+ authenticator: jwtAuthenticator(config.token),
352
390
  });
353
391
  if (closed) {
354
392
  console.debug(
@@ -363,6 +401,28 @@ export function useNatsSession(
363
401
  const dispatch = (event: NatsSessionEvent) => {
364
402
  onMessageRef.current(event);
365
403
  };
404
+ const ready = () => lifecycleRef.current.onConnected?.();
405
+ let authRefreshRequested = false;
406
+ const requestAuthRefresh = (error: Error) => {
407
+ if (closed || authRefreshRequested) return;
408
+ authRefreshRequested = true;
409
+ lifecycleRef.current.onAuthError?.(error);
410
+ };
411
+
412
+ void (async () => {
413
+ for await (const status of nc.status()) {
414
+ if (status.type === 'error' && isNatsAuthError(status.error)) {
415
+ requestAuthRefresh(status.error);
416
+ return;
417
+ }
418
+ }
419
+ })();
420
+
421
+ void nc.closed().then(error => {
422
+ if (error && isNatsAuthError(error)) {
423
+ requestAuthRefresh(error);
424
+ }
425
+ });
366
426
 
367
427
  if (useJetStream) {
368
428
  await consumeJetStream(
@@ -373,12 +433,18 @@ export function useNatsSession(
373
433
  dispatch,
374
434
  messages => {
375
435
  consumerMessagesRef.current = messages;
376
- }
436
+ },
437
+ ready
377
438
  );
378
439
  } else {
379
- await consumeCoreSubscription(nc, subject, dispatch);
440
+ await consumeCoreSubscription(nc, subject, dispatch, ready);
441
+ }
442
+ })().catch(err => {
443
+ console.error('[NATS] connection error', err);
444
+ if (!closed && isNatsAuthError(err)) {
445
+ lifecycleRef.current.onAuthError?.(err);
380
446
  }
381
- })().catch(err => console.error('[NATS] connection error', err));
447
+ });
382
448
 
383
449
  return () => {
384
450
  console.info('[NATS] cleanup: closing connection for subject', subject);
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const version = '8.44.0';
2
+ export const version = '8.45.0';
@@ -1,372 +0,0 @@
1
- .memori-chat-resume-drawer {
2
- position: fixed;
3
- z-index: 1200;
4
- inset: 0;
5
- pointer-events: none;
6
- }
7
-
8
- .memori-chat-resume-drawer--backdrop {
9
- position: absolute;
10
- border: 0;
11
- background: rgba(0, 0, 0, 0);
12
- cursor: default;
13
- inset: 0;
14
- opacity: 0;
15
- transition: opacity 280ms cubic-bezier(0.32, 0.72, 0, 1);
16
- }
17
-
18
- .memori-chat-resume-drawer--panel {
19
- position: absolute;
20
- top: 0;
21
- right: 0;
22
- display: flex;
23
- width: min(100%, 430px);
24
- height: 100%;
25
- flex-direction: column;
26
- /* background: var(--memori-main-background); */
27
- box-shadow: -10px 0 30px rgba(0, 0, 0, 0.16);
28
- transform: translateX(100%);
29
- transition: transform 280ms cubic-bezier(0.32, 0.72, 0, 1);
30
- }
31
-
32
- .memori-chat-resume-drawer--embedded-shell {
33
- display: flex;
34
- height: 100%;
35
- min-height: 0;
36
- flex: 1;
37
- }
38
-
39
- .memori-chat-resume-drawer--panel-embedded {
40
- position: relative;
41
- width: 100%;
42
- height: 100%;
43
- box-shadow: none;
44
- transform: none;
45
- }
46
-
47
- .memori-chat-resume-drawer--open {
48
- pointer-events: auto;
49
- }
50
-
51
- .memori-chat-resume-drawer--open .memori-chat-resume-drawer--backdrop {
52
- opacity: 0.4;
53
- }
54
-
55
- .memori-chat-resume-drawer--open .memori-chat-resume-drawer--panel {
56
- transform: translateX(0);
57
- }
58
-
59
- .memori-chat-resume-drawer--header {
60
- display: flex;
61
- align-items: center;
62
- padding: 14px 16px 12px;
63
- gap: 8px;
64
- }
65
-
66
- @media (max-width: 768px) {
67
- .memori-chat-resume-drawer--header {
68
- border-bottom: 0.5px solid var(--color-border-tertiary, var(--memori-border-color, #e5e7eb));
69
- }
70
- }
71
-
72
- .memori-chat-resume-drawer--header-icon-button {
73
- display: inline-flex;
74
- width: 28px;
75
- min-width: 28px;
76
- height: 28px;
77
- align-items: center;
78
- justify-content: center;
79
- padding: 0;
80
- border: none;
81
- border-radius: 999px;
82
- background: transparent;
83
- color: var(--color-text-primary, var(--memori-text-color));
84
- cursor: pointer;
85
- }
86
-
87
- .memori-chat-resume-drawer--header-main {
88
- min-width: 0;
89
- flex: 1;
90
- }
91
-
92
- .memori-chat-resume-drawer--title {
93
- overflow: hidden;
94
- margin: 0;
95
- color: var(--color-text-primary, var(--memori-text-color));
96
- font-size: 15px;
97
- font-weight: 500;
98
- text-overflow: ellipsis;
99
- white-space: nowrap;
100
- }
101
-
102
- .memori-chat-resume-drawer--subtitle {
103
- overflow: hidden;
104
- margin: 2px 0 0;
105
- color: color-mix(in oklch, var(--memori-text-color) 66%, transparent);
106
- font-size: 12px;
107
- text-overflow: ellipsis;
108
- white-space: nowrap;
109
- }
110
-
111
- .memori-chat-resume-drawer--summary-banner {
112
- display: flex;
113
- align-items: flex-start;
114
- padding: 10px 12px;
115
- border: 1px solid var(--color-border-tertiary, var(--memori-border-color, #e5e7eb));
116
- border-radius: 8px;
117
- margin: 12px 16px 0;
118
- background: var(--color-background-secondary, var(--memori-secondary-background));
119
- gap: 8px;
120
- }
121
-
122
- .memori-chat-resume-drawer--summary-icon {
123
- margin-top: 1px;
124
- color: color-mix(in oklch, var(--memori-text-color) 68%, transparent);
125
- }
126
-
127
- .memori-chat-resume-drawer--summary-title {
128
- margin: 0 0 2px;
129
- color: var(--color-text-primary, var(--memori-text-color));
130
- font-size: 14px;
131
- font-weight: 600;
132
- }
133
-
134
- .memori-chat-resume-drawer--summary-text {
135
- margin: 0;
136
- color: color-mix(in oklch, var(--memori-text-color) 72%, transparent);
137
- font-size: 14px;
138
- line-height: 1.35;
139
- }
140
-
141
- .memori-chat-resume-drawer--thread {
142
- display: flex;
143
- overflow: hidden;
144
- min-height: 0;
145
- flex: 1;
146
- flex-direction: column;
147
- padding: var(--memori-spacing-lg);
148
- }
149
-
150
- .memori-chat-resume-drawer--embedded-chat {
151
- min-height: 0;
152
- flex: 1;
153
- }
154
-
155
- .memori-chat-resume-drawer--embedded-chat .memori-chat--wrapper {
156
- height: 100%;
157
- }
158
-
159
- .memori-chat-resume-drawer--embedded-chat .memori-chat--history {
160
- height: 100%;
161
- border-radius: 0;
162
- margin: 0;
163
- background: transparent;
164
- }
165
-
166
- .memori-chat-resume-drawer--embedded-chat .memori-chat--content {
167
- padding: 0;
168
- }
169
-
170
- .memori-chat-resume-drawer--embedded-chat .memori-chat--cover {
171
- display: none;
172
- }
173
-
174
- .memori-chat-resume-drawer--embedded-chat .memori-chat--bubble-container {
175
- padding-right: var(--memori-spacing-md);
176
- padding-left: 0;
177
- }
178
-
179
- .memori-chat-resume-drawer--embedded-chat .memori-chat--bubble-message-row {
180
- align-items: flex-start;
181
- }
182
-
183
- /* .memori-chat-resume-drawer--embedded-chat .memori-chat--bubble-container,
184
- .memori-chat-resume-drawer--embedded-chat .memori-chat--timestamp,
185
- .memori-chat-resume-drawer--embedded-chat .memori-media-widget,
186
- .memori-chat-resume-drawer--embedded-chat .memori-chat--bubble-shell {
187
- padding-right: 0;
188
- padding-left: 0;
189
- /* margin-top: var(--memori-spacing-sm);
190
- } */
191
-
192
- .memori-chat-resume-drawer--message-group {
193
- display: flex;
194
- width: 100%;
195
- gap: 8px;
196
- }
197
-
198
- .memori-chat-resume-drawer--message-group-assistant {
199
- justify-content: flex-start;
200
- }
201
-
202
- .memori-chat-resume-drawer--message-group-user {
203
- justify-content: flex-end;
204
- }
205
-
206
- .memori-chat-resume-drawer--avatar {
207
- display: inline-flex;
208
- width: 28px;
209
- min-width: 28px;
210
- height: 28px;
211
- align-items: center;
212
- justify-content: center;
213
- border-radius: 999px;
214
- background: linear-gradient(135deg, #b5a2ff 0%, #8b72ff 100%);
215
- color: #fff;
216
- font-size: 11px;
217
- font-weight: 600;
218
- }
219
-
220
- .memori-chat-resume-drawer--message-content {
221
- display: flex;
222
- max-width: 82%;
223
- flex-direction: column;
224
- gap: 6px;
225
- }
226
-
227
- .memori-chat-resume-drawer--message-group-user .memori-chat-resume-drawer--message-content {
228
- align-items: flex-end;
229
- }
230
-
231
- .memori-chat-resume-drawer--timestamp {
232
- color: color-mix(in oklch, var(--memori-text-color) 64%, transparent);
233
- font-size: 12px;
234
- line-height: 1;
235
- }
236
-
237
- .memori-chat-resume-drawer--attachment-pill {
238
- display: flex;
239
- align-items: center;
240
- padding: 8px 10px;
241
- border: 1px solid var(--color-border-tertiary, var(--memori-border-color, #e5e7eb));
242
- border-radius: 8px;
243
- background: var(--color-background-secondary, var(--memori-secondary-background));
244
- gap: 8px;
245
- }
246
-
247
- .memori-chat-resume-drawer--attachment-ext {
248
- display: inline-flex;
249
- min-width: 34px;
250
- align-items: center;
251
- justify-content: center;
252
- padding: 4px 8px;
253
- border-radius: 6px;
254
- background: #d9e8ff;
255
- color: #2f5fa8;
256
- font-size: 11px;
257
- font-weight: 600;
258
- }
259
-
260
- .memori-chat-resume-drawer--attachment-meta {
261
- display: flex;
262
- min-width: 0;
263
- flex-direction: column;
264
- }
265
-
266
- .memori-chat-resume-drawer--attachment-name {
267
- overflow: hidden;
268
- color: var(--color-text-primary, var(--memori-text-color));
269
- font-size: 13px;
270
- text-overflow: ellipsis;
271
- white-space: nowrap;
272
- }
273
-
274
- .memori-chat-resume-drawer--attachment-info {
275
- color: color-mix(in oklch, var(--memori-text-color) 70%, transparent);
276
- font-size: 12px;
277
- }
278
-
279
- .memori-chat-resume-drawer--bubble {
280
- padding: 10px 12px;
281
- color: var(--color-text-primary, var(--memori-text-color));
282
- font-size: 14px;
283
- line-height: 1.4;
284
- white-space: pre-wrap;
285
- }
286
-
287
- .memori-chat-resume-drawer--bubble-assistant {
288
- border: 0.5px solid var(--color-border-tertiary, var(--memori-border-color, #e5e7eb));
289
- border-radius: 4px 12px 12px 12px;
290
- background: var(--color-background-secondary, var(--memori-secondary-background));
291
- }
292
-
293
- .memori-chat-resume-drawer--bubble-user {
294
- border-radius: 12px 4px 12px 12px;
295
- background: var(--memori-primary);
296
- color: #fff;
297
- }
298
-
299
- .memori-chat-resume-drawer--interrupted {
300
- display: inline-flex;
301
- align-items: center;
302
- color: color-mix(in oklch, var(--memori-text-color) 72%, transparent);
303
- font-size: 14px;
304
- gap: 6px;
305
- }
306
-
307
- .memori-chat-resume-drawer--actions {
308
- display: flex;
309
- flex-direction: column;
310
- flex-shrink: 0;
311
- padding: 16px 24px;
312
- margin-bottom: 1rem;
313
- /* border-top: 0.5px solid var(--color-border-tertiary, var(--memori-border-color, #e5e7eb)); */
314
- /* background: var(--memori-main-background); */
315
- gap: 12px;
316
- }
317
-
318
- .memori-chat-history-drawer--header-download-button {
319
- display: flex;
320
- align-self: baseline;
321
- }
322
-
323
- .memori-chat-resume-drawer--chips-row {
324
- display: flex;
325
- flex-wrap: wrap;
326
- gap: 8px;
327
- }
328
-
329
- .memori-chat-resume-drawer--chip {
330
- min-height: 32px;
331
- padding: 0 14px;
332
- border: 0.5px solid color-mix(in oklch, var(--memori-text-color) 20%, transparent);
333
- border-radius: 20px;
334
- background: transparent;
335
- color: color-mix(in oklch, var(--memori-text-color) 85%, transparent);
336
- cursor: pointer;
337
- font-size: 12px;
338
- font-weight: 500;
339
- }
340
-
341
- .memori-chat-resume-drawer--resume-cta {
342
- width: 100%;
343
- min-height: 44px;
344
- border-radius: 10px;
345
- font-size: 14px;
346
- font-weight: 500;
347
- }
348
-
349
- .memori-chat-resume-drawer--skeletons {
350
- display: flex;
351
- flex-direction: column;
352
- gap: 12px;
353
- }
354
-
355
- .memori-chat-resume-drawer--skeleton-bubble {
356
- width: 72%;
357
- height: 54px;
358
- border-radius: 12px;
359
- animation: memori-chat-resume-shimmer 1.2s infinite;
360
- background: linear-gradient(90deg, rgba(0, 0, 0, 0.04) 0%, rgba(0, 0, 0, 0.08) 50%, rgba(0, 0, 0, 0.04) 100%);
361
- background-size: 200% 100%;
362
- }
363
-
364
- @keyframes memori-chat-resume-shimmer {
365
- from {
366
- background-position: 200% 0;
367
- }
368
-
369
- to {
370
- background-position: -200% 0;
371
- }
372
- }
@@ -1,62 +0,0 @@
1
- .memori-drawer-footer {
2
- flex-shrink: 0;
3
- padding: var(--memori-spacing-md);
4
- border-top: 1px solid var(--memori-border-color, #e5e7eb);
5
- box-shadow: 0 -8px 24px -8px rgba(0, 0, 0, 0.06), 0 -2px 8px -2px rgba(0, 0, 0, 0.03);
6
- }
7
-
8
- .memori-drawer-footer__inner {
9
- display: flex;
10
- flex-direction: row;
11
- flex-wrap: wrap;
12
- align-items: center;
13
- justify-content: space-between;
14
- gap: var(--memori-spacing-lg);
15
- }
16
-
17
- .memori-drawer-footer__start {
18
- display: flex;
19
- align-items: center;
20
- gap: var(--memori-spacing-md);
21
- }
22
-
23
- .memori-drawer-footer__end {
24
- display: flex;
25
- align-items: center;
26
- justify-content: flex-end;
27
- margin-left: auto;
28
- gap: var(--memori-spacing-md);
29
- }
30
-
31
- .memori-drawer-footer__end .memori-button {
32
- min-height: 44px;
33
- padding: 10px var(--memori-spacing-lg);
34
- border-radius: 10px;
35
- font-weight: 500;
36
- transition: transform 0.15s ease, box-shadow 0.15s ease;
37
- }
38
-
39
- .memori-drawer-footer__end .memori-button:hover:not([disabled]) {
40
- transform: translateY(-1px);
41
- }
42
-
43
- .memori-drawer-footer__inner--centered {
44
- justify-content: center;
45
- }
46
-
47
- @media (max-width: 768px) {
48
- .memori-drawer-footer {
49
- padding: var(--memori-spacing-md) var(--memori-spacing-lg);
50
- }
51
-
52
- .memori-drawer-footer__inner {
53
- flex-direction: column;
54
- align-items: stretch;
55
- gap: var(--memori-spacing-md);
56
- }
57
-
58
- .memori-drawer-footer__end {
59
- justify-content: flex-end;
60
- margin-left: 0;
61
- }
62
- }