@asgard-js/react 0.0.34 → 0.0.37-canary.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.
Files changed (122) hide show
  1. package/dist/components/chatbot/chatbot-footer/chatbot-footer.d.ts.map +1 -1
  2. package/dist/index.js +18022 -18716
  3. package/package.json +2 -2
  4. package/.babelrc +0 -12
  5. package/eslint.config.cjs +0 -12
  6. package/src/components/chatbot/chatbot-body/chatbot-body.module.scss +0 -13
  7. package/src/components/chatbot/chatbot-body/chatbot-body.tsx +0 -45
  8. package/src/components/chatbot/chatbot-body/conversation-message-renderer.tsx +0 -55
  9. package/src/components/chatbot/chatbot-body/index.ts +0 -1
  10. package/src/components/chatbot/chatbot-container/chatbot-container.module.scss +0 -41
  11. package/src/components/chatbot/chatbot-container/chatbot-container.tsx +0 -49
  12. package/src/components/chatbot/chatbot-container/chatbot-full-screen-container.tsx +0 -54
  13. package/src/components/chatbot/chatbot-footer/chatbot-footer.module.scss +0 -67
  14. package/src/components/chatbot/chatbot-footer/chatbot-footer.tsx +0 -144
  15. package/src/components/chatbot/chatbot-footer/index.ts +0 -1
  16. package/src/components/chatbot/chatbot-footer/speech-input-button.tsx +0 -132
  17. package/src/components/chatbot/chatbot-header/chatbot-header.module.scss +0 -48
  18. package/src/components/chatbot/chatbot-header/chatbot-header.tsx +0 -98
  19. package/src/components/chatbot/chatbot-header/index.ts +0 -1
  20. package/src/components/chatbot/chatbot.spec.tsx +0 -8
  21. package/src/components/chatbot/chatbot.tsx +0 -118
  22. package/src/components/chatbot/profile-icon.tsx +0 -26
  23. package/src/components/index.ts +0 -2
  24. package/src/components/templates/avatar/avatar.module.scss +0 -6
  25. package/src/components/templates/avatar/avatar.tsx +0 -28
  26. package/src/components/templates/avatar/index.ts +0 -1
  27. package/src/components/templates/button-template/button-template.module.scss +0 -0
  28. package/src/components/templates/button-template/button-template.tsx +0 -45
  29. package/src/components/templates/button-template/card.module.scss +0 -58
  30. package/src/components/templates/button-template/card.spec.tsx +0 -213
  31. package/src/components/templates/button-template/card.tsx +0 -123
  32. package/src/components/templates/button-template/index.ts +0 -1
  33. package/src/components/templates/carousel-template/carousel-template.module.scss +0 -15
  34. package/src/components/templates/carousel-template/carousel-template.tsx +0 -49
  35. package/src/components/templates/carousel-template/index.ts +0 -1
  36. package/src/components/templates/chart-template/chart-template.module.scss +0 -52
  37. package/src/components/templates/chart-template/chart-template.tsx +0 -75
  38. package/src/components/templates/chart-template/index.ts +0 -1
  39. package/src/components/templates/hint-template/hint-template.module.scss +0 -39
  40. package/src/components/templates/hint-template/hint-template.tsx +0 -71
  41. package/src/components/templates/hint-template/index.ts +0 -1
  42. package/src/components/templates/image-template/image-template.module.scss +0 -67
  43. package/src/components/templates/image-template/image-template.tsx +0 -58
  44. package/src/components/templates/image-template/index.ts +0 -1
  45. package/src/components/templates/index.ts +0 -10
  46. package/src/components/templates/quick-replies/index.ts +0 -1
  47. package/src/components/templates/quick-replies/quick-replies.module.scss +0 -16
  48. package/src/components/templates/quick-replies/quick-replies.tsx +0 -44
  49. package/src/components/templates/template-box/index.ts +0 -2
  50. package/src/components/templates/template-box/template-box-content.module.scss +0 -13
  51. package/src/components/templates/template-box/template-box-content.tsx +0 -30
  52. package/src/components/templates/template-box/template-box.module.scss +0 -19
  53. package/src/components/templates/template-box/template-box.tsx +0 -48
  54. package/src/components/templates/text-template/bot-typing-box.tsx +0 -81
  55. package/src/components/templates/text-template/bot-typing-placeholder.tsx +0 -28
  56. package/src/components/templates/text-template/index.ts +0 -3
  57. package/src/components/templates/text-template/text-template.module.scss +0 -131
  58. package/src/components/templates/text-template/text-template.tsx +0 -90
  59. package/src/components/templates/text-template/use-react-markdown-renderer.spec.tsx +0 -758
  60. package/src/components/templates/time/index.ts +0 -1
  61. package/src/components/templates/time/time.module.scss +0 -6
  62. package/src/components/templates/time/time.tsx +0 -34
  63. package/src/context/asgard-app-initialization-context.tsx +0 -154
  64. package/src/context/asgard-service-context.tsx +0 -139
  65. package/src/context/asgard-template-context.tsx +0 -83
  66. package/src/context/asgard-theme-context.tsx +0 -401
  67. package/src/context/index.ts +0 -4
  68. package/src/hooks/index.ts +0 -11
  69. package/src/hooks/use-asgard-service-client.ts +0 -68
  70. package/src/hooks/use-channel.ts +0 -154
  71. package/src/hooks/use-debounce.ts +0 -18
  72. package/src/hooks/use-deep-compare-memo.ts +0 -19
  73. package/src/hooks/use-is-on-screen-keyboard-open.ts +0 -43
  74. package/src/hooks/use-on-screen-keyboard-scroll-fix.ts +0 -15
  75. package/src/hooks/use-prevent-over-scrolling.ts +0 -77
  76. package/src/hooks/use-react-markdown-renderer.tsx +0 -266
  77. package/src/hooks/use-resize-observer.tsx +0 -27
  78. package/src/hooks/use-update-vh.ts +0 -30
  79. package/src/hooks/use-viewport-size.ts +0 -51
  80. package/src/icons/add_a_photo.svg +0 -3
  81. package/src/icons/bot.svg +0 -14
  82. package/src/icons/close.svg +0 -3
  83. package/src/icons/distance.svg +0 -3
  84. package/src/icons/mic.svg +0 -3
  85. package/src/icons/photo_library.svg +0 -3
  86. package/src/icons/profile.svg +0 -28
  87. package/src/icons/refresh.svg +0 -3
  88. package/src/icons/send.svg +0 -3
  89. package/src/icons/stop.svg +0 -22
  90. package/src/icons/volume_up.svg +0 -3
  91. package/src/index.ts +0 -4
  92. package/src/models/bot-provider.ts +0 -108
  93. package/src/styles/_index.scss +0 -1
  94. package/src/styles/_styles.scss +0 -11
  95. package/src/styles/colors/_colors.scss +0 -10
  96. package/src/styles/colors/_index.scss +0 -1
  97. package/src/styles/colors/_variables.scss +0 -72
  98. package/src/styles/palette/_index.scss +0 -1
  99. package/src/styles/palette/_palette.scss +0 -42
  100. package/src/styles/palette/_variables.scss +0 -40
  101. package/src/styles/radius/_index.scss +0 -1
  102. package/src/styles/radius/_radius.scss +0 -8
  103. package/src/styles/radius/_variables.scss +0 -12
  104. package/src/styles/spacing/_index.scss +0 -1
  105. package/src/styles/spacing/_spacing.scss +0 -8
  106. package/src/styles/spacing/_variables.scss +0 -13
  107. package/src/styles/utils/_index.scss +0 -1
  108. package/src/styles/utils/_map.scss +0 -22
  109. package/src/test-setup.ts +0 -1
  110. package/src/utils/deep-merge.ts +0 -26
  111. package/src/utils/extractors.ts +0 -20
  112. package/src/utils/format-time.ts +0 -8
  113. package/src/utils/index.ts +0 -1
  114. package/src/utils/is.ts +0 -72
  115. package/src/utils/selectors.ts +0 -7
  116. package/src/utils/uri-validation.spec.ts +0 -208
  117. package/src/utils/uri-validation.ts +0 -103
  118. package/tsconfig.json +0 -16
  119. package/tsconfig.lib.json +0 -63
  120. package/tsconfig.spec.json +0 -36
  121. package/tsconfig.tsbuildinfo +0 -1
  122. package/vite.config.ts +0 -63
@@ -1,401 +0,0 @@
1
- import {
2
- createContext,
3
- CSSProperties,
4
- PropsWithChildren,
5
- ReactNode,
6
- useContext,
7
- useMemo,
8
- useCallback,
9
- } from 'react';
10
- import { deepMerge } from '../utils/deep-merge';
11
- import {
12
- useAsgardAppInitializationContext,
13
- Annotations,
14
- } from './asgard-app-initialization-context';
15
-
16
- export interface AsgardThemeContextValue {
17
- chatbot: Pick<
18
- CSSProperties,
19
- | 'width'
20
- | 'height'
21
- | 'maxWidth'
22
- | 'minWidth'
23
- | 'maxHeight'
24
- | 'minHeight'
25
- | 'backgroundColor'
26
- | 'borderColor'
27
- | 'borderRadius'
28
- > & {
29
- contentMaxWidth?: CSSProperties['maxWidth'];
30
- backgroundColor?: CSSProperties['backgroundColor'];
31
- borderColor?: CSSProperties['borderColor'];
32
- inactiveColor?: CSSProperties['color'];
33
- primaryComponent?: {
34
- mainColor?: CSSProperties['color'];
35
- secondaryColor?: CSSProperties['color'];
36
- };
37
- style?: CSSProperties;
38
- header?: Partial<{
39
- style: CSSProperties;
40
- title: {
41
- style: CSSProperties;
42
- };
43
- actionButton?: {
44
- style: CSSProperties;
45
- };
46
- }>;
47
- body?: Partial<{
48
- style: CSSProperties;
49
- }>;
50
- footer?: Partial<{
51
- style: CSSProperties;
52
- textArea: {
53
- style: CSSProperties;
54
- '::placeholder': CSSProperties;
55
- };
56
- submitButton: {
57
- style: CSSProperties;
58
- };
59
- speechInputButton: {
60
- style: CSSProperties;
61
- };
62
- }>;
63
- };
64
- botMessage: Pick<CSSProperties, 'color' | 'backgroundColor'>;
65
- userMessage: Pick<CSSProperties, 'color' | 'backgroundColor'>;
66
- template?: Partial<{
67
- /**
68
- * first level for common/shared properties.
69
- * Check MessageTemplate type for more details (packages/core/src/types/sse-response.ts).
70
- */
71
- quickReplies?: Partial<{
72
- style: CSSProperties;
73
- button: {
74
- style: CSSProperties;
75
- };
76
- }>;
77
- time?: Partial<{
78
- style: CSSProperties;
79
- }>;
80
- /**
81
- * TBD: Fill the necessary properties based on the requirements.
82
- */
83
- TextMessageTemplate: Partial<{ style: CSSProperties }>;
84
- /**
85
- * TBD: Fill the necessary properties based on the requirements.
86
- */
87
- HintMessageTemplate: Partial<{ style: CSSProperties }>;
88
- /**
89
- * TBD: Fill the necessary properties based on the requirements.
90
- */
91
- ImageMessageTemplate: Partial<{ style: CSSProperties }>;
92
- /**
93
- * TBD: Fill the necessary properties based on the requirements.
94
- */
95
- VideoMessageTemplate: Partial<{ style: CSSProperties }>;
96
- /**
97
- * TBD: Fill the necessary properties based on the requirements.
98
- */
99
- AudioMessageTemplate: Partial<{ style: CSSProperties }>;
100
- /**
101
- * TBD: Fill the necessary properties based on the requirements.
102
- */
103
- LocationMessageTemplate: Partial<{ style: CSSProperties }>;
104
- /**
105
- * TBD: Fill the necessary properties based on the requirements.
106
- */
107
- ChartMessageTemplate: Partial<{ style: CSSProperties }>;
108
- /**
109
- * TBD: Fill the necessary properties based on the requirements.
110
- */
111
- ButtonMessageTemplate: Partial<{
112
- style: CSSProperties;
113
- button?: {
114
- style: CSSProperties;
115
- };
116
- }>;
117
- /**
118
- * TBD: Fill the necessary properties based on the requirements.
119
- */
120
- CarouselMessageTemplate: Partial<{
121
- style: CSSProperties;
122
- card: {
123
- style: CSSProperties;
124
- button?: {
125
- style: CSSProperties;
126
- };
127
- };
128
- }>;
129
- }>;
130
- }
131
-
132
- export const defaultAsgardThemeContextValue: AsgardThemeContextValue = {
133
- chatbot: {
134
- width: '375px',
135
- height: '640px',
136
- backgroundColor: 'var(--asg-color-bg)',
137
- borderColor: 'var(--asg-color-border)',
138
- borderRadius: 'var(--asg-radius-md)',
139
- contentMaxWidth: '1200px',
140
- style: {},
141
- header: {
142
- style: {},
143
- title: {
144
- style: {},
145
- },
146
- actionButton: {
147
- style: {},
148
- },
149
- },
150
- body: {
151
- style: {},
152
- },
153
- footer: {
154
- style: {},
155
- textArea: {
156
- style: {},
157
- '::placeholder': {
158
- color: 'var(--asg-color-text-placeholder)',
159
- },
160
- },
161
- submitButton: {
162
- style: {},
163
- },
164
- speechInputButton: {
165
- style: {},
166
- },
167
- },
168
- },
169
- botMessage: {
170
- color: 'var(--asg-color-text)',
171
- backgroundColor: 'var(--asg-color-secondary)',
172
- },
173
- userMessage: {
174
- color: 'var(--asg-color-text)',
175
- backgroundColor: 'var(--asg-color-primary)',
176
- },
177
- template: {
178
- quickReplies: {
179
- style: {},
180
- button: {
181
- style: {},
182
- },
183
- },
184
- time: {
185
- style: {},
186
- },
187
- TextMessageTemplate: {
188
- style: {},
189
- },
190
- HintMessageTemplate: {
191
- style: {},
192
- },
193
- ImageMessageTemplate: {
194
- style: {},
195
- },
196
- VideoMessageTemplate: {
197
- style: {},
198
- },
199
- AudioMessageTemplate: {
200
- style: {},
201
- },
202
- LocationMessageTemplate: {
203
- style: {},
204
- },
205
- ChartMessageTemplate: {
206
- style: {},
207
- },
208
- ButtonMessageTemplate: {
209
- style: {},
210
- button: {
211
- style: {
212
- border: '1px solid var(--asg-color-border)',
213
- },
214
- },
215
- },
216
- CarouselMessageTemplate: {
217
- style: {},
218
- card: {
219
- style: {},
220
- button: {
221
- style: {
222
- border: '1px solid var(--asg-color-border)',
223
- },
224
- },
225
- },
226
- },
227
- },
228
- };
229
-
230
- export const AsgardThemeContext = createContext<AsgardThemeContextValue>(
231
- defaultAsgardThemeContextValue
232
- );
233
-
234
- export function AsgardThemeContextProvider(
235
- props: PropsWithChildren<{
236
- theme?: Partial<AsgardThemeContextValue>;
237
- }>
238
- ): ReactNode {
239
- const { children, theme = {} } = props;
240
- const {
241
- data: { annotations },
242
- } = useAsgardAppInitializationContext();
243
-
244
- const deepMergeTheme = useCallback(
245
- function () {
246
- /**
247
- * Orders of theme (high to low):
248
- * 1. Theme from props
249
- * 2. Theme from annotations
250
- * 3. Default theme
251
- */
252
-
253
- const themeFromAnnotations: Annotations['embedConfig']['theme'] =
254
- annotations?.embedConfig?.theme ?? {
255
- chatbot: {},
256
- botMessage: {},
257
- userMessage: {},
258
- };
259
-
260
- const tempTheme = deepMerge(defaultAsgardThemeContextValue as unknown as Record<string, unknown>, {
261
- chatbot: {
262
- backgroundColor: themeFromAnnotations.chatbot?.backgroundColor,
263
- borderColor: themeFromAnnotations.chatbot?.borderColor,
264
- header: {
265
- style: {
266
- borderBottomColor: themeFromAnnotations.chatbot?.borderColor,
267
- },
268
- title: {
269
- style: {
270
- color:
271
- themeFromAnnotations.chatbot?.primaryComponent
272
- ?.secondaryColor, // Title text color
273
- },
274
- },
275
- actionButton: {
276
- style: {
277
- color: themeFromAnnotations.chatbot?.inactiveColor,
278
- },
279
- },
280
- },
281
- body: {
282
- style: {
283
- // Time/timestamp text color
284
- color: themeFromAnnotations.chatbot?.inactiveColor,
285
- },
286
- },
287
- footer: {
288
- style: {
289
- borderTopColor: themeFromAnnotations.chatbot?.borderColor,
290
- },
291
- textArea: {
292
- style: {
293
- color: themeFromAnnotations.chatbot?.inactiveColor,
294
- backgroundColor: themeFromAnnotations.chatbot?.backgroundColor,
295
- },
296
- '::placeholder': {
297
- color: themeFromAnnotations.chatbot?.inactiveColor,
298
- },
299
- },
300
- submitButton: {
301
- style: {
302
- color:
303
- themeFromAnnotations.chatbot?.primaryComponent
304
- ?.secondaryColor,
305
- },
306
- },
307
- speechInputButton: {
308
- style: {
309
- color:
310
- themeFromAnnotations.chatbot?.primaryComponent
311
- ?.secondaryColor,
312
- },
313
- },
314
- },
315
- },
316
- botMessage: {
317
- backgroundColor: themeFromAnnotations.botMessage?.backgroundColor, // #585858
318
- color: themeFromAnnotations.botMessage?.color,
319
- },
320
- userMessage: {
321
- backgroundColor: themeFromAnnotations.userMessage?.backgroundColor,
322
- color: themeFromAnnotations.userMessage?.color,
323
- },
324
- template: {
325
- quickReplies: {
326
- button: {
327
- style: {
328
- color:
329
- themeFromAnnotations.chatbot?.primaryComponent
330
- ?.secondaryColor, // Button text (#FFFFFF)
331
- borderColor: themeFromAnnotations.chatbot?.borderColor,
332
- backgroundColor: themeFromAnnotations.botMessage
333
- ?.backgroundColor
334
- ? `${themeFromAnnotations.botMessage.backgroundColor}33`
335
- : undefined,
336
- },
337
- },
338
- },
339
- time: {
340
- style: {
341
- color: themeFromAnnotations.chatbot?.inactiveColor,
342
- },
343
- },
344
- TextMessageTemplate: {
345
- style: {
346
- // For unset messages
347
- color:
348
- themeFromAnnotations.chatbot?.primaryComponent?.secondaryColor,
349
- },
350
- },
351
- ButtonMessageTemplate: {
352
- button: {
353
- style: {
354
- borderColor: themeFromAnnotations.chatbot?.borderColor,
355
- backgroundColor:
356
- themeFromAnnotations.chatbot?.primaryComponent?.mainColor,
357
- color:
358
- themeFromAnnotations.chatbot?.primaryComponent
359
- ?.secondaryColor,
360
- },
361
- },
362
- },
363
- CarouselMessageTemplate: {
364
- card: {
365
- style: {
366
- backgroundColor:
367
- themeFromAnnotations.botMessage
368
- ?.carouselButtonBackgroundColor,
369
- },
370
- button: {
371
- style: {
372
- borderColor: themeFromAnnotations.chatbot?.borderColor,
373
- backgroundColor:
374
- themeFromAnnotations.chatbot?.primaryComponent?.mainColor,
375
- color:
376
- themeFromAnnotations.chatbot?.primaryComponent
377
- ?.secondaryColor,
378
- },
379
- },
380
- },
381
- },
382
- },
383
- });
384
-
385
- return deepMerge(tempTheme, theme);
386
- },
387
- [theme, annotations?.embedConfig?.theme]
388
- );
389
-
390
- const value = useMemo(() => deepMergeTheme(), [deepMergeTheme]);
391
-
392
- return (
393
- <AsgardThemeContext.Provider value={value}>
394
- {children}
395
- </AsgardThemeContext.Provider>
396
- );
397
- }
398
-
399
- export function useAsgardThemeContext(): AsgardThemeContextValue {
400
- return useContext(AsgardThemeContext);
401
- }
@@ -1,4 +0,0 @@
1
- export * from './asgard-service-context';
2
- export * from './asgard-template-context';
3
- export * from './asgard-theme-context';
4
- export * from './asgard-app-initialization-context';
@@ -1,11 +0,0 @@
1
- export * from './use-asgard-service-client';
2
- export * from './use-channel';
3
- export * from './use-debounce';
4
- export * from './use-viewport-size';
5
- export * from './use-is-on-screen-keyboard-open';
6
- export * from './use-on-screen-keyboard-scroll-fix';
7
- export * from './use-prevent-over-scrolling';
8
- export * from './use-update-vh';
9
- export * from './use-resize-observer';
10
- export * from './use-deep-compare-memo';
11
- export * from './use-react-markdown-renderer';
@@ -1,68 +0,0 @@
1
- import { ClientConfig, AsgardServiceClient, EventType } from '@asgard-js/core';
2
- import { useEffect, useRef } from 'react';
3
-
4
- interface UseAsgardServiceClientProps {
5
- config: ClientConfig;
6
- }
7
-
8
- export function useAsgardServiceClient(
9
- props: UseAsgardServiceClientProps
10
- ): AsgardServiceClient | null {
11
- const { config } = props;
12
-
13
- const { onRunInit, onProcess, onMessage, onToolCall, onRunDone, onRunError } =
14
- config;
15
-
16
- const clientRef = useRef<AsgardServiceClient | null>(null);
17
-
18
- if (!clientRef.current) {
19
- clientRef.current = new AsgardServiceClient(config);
20
- }
21
-
22
- useEffect(() => {
23
- return (): void => {
24
- if (clientRef.current) {
25
- clientRef.current.close();
26
- clientRef.current = null;
27
- }
28
- };
29
- }, []);
30
-
31
- useEffect(() => {
32
- if (!clientRef.current || !onRunInit) return;
33
-
34
- clientRef.current.on(EventType.INIT, onRunInit);
35
- }, [onRunInit]);
36
-
37
- useEffect(() => {
38
- if (!clientRef.current || !onProcess) return;
39
-
40
- clientRef.current.on(EventType.PROCESS, onProcess);
41
- }, [onProcess]);
42
-
43
- useEffect(() => {
44
- if (!clientRef.current || !onMessage) return;
45
-
46
- clientRef.current.on(EventType.MESSAGE, onMessage);
47
- }, [onMessage]);
48
-
49
- useEffect(() => {
50
- if (!clientRef.current || !onToolCall) return;
51
-
52
- clientRef.current.on(EventType.TOOL_CALL, onToolCall);
53
- }, [onToolCall]);
54
-
55
- useEffect(() => {
56
- if (!clientRef.current || !onRunDone) return;
57
-
58
- clientRef.current.on(EventType.DONE, onRunDone);
59
- }, [onRunDone]);
60
-
61
- useEffect(() => {
62
- if (!clientRef.current || !onRunError) return;
63
-
64
- clientRef.current.on(EventType.ERROR, onRunError);
65
- }, [onRunError]);
66
-
67
- return clientRef.current;
68
- }
@@ -1,154 +0,0 @@
1
- import {
2
- AsgardServiceClient,
3
- Channel,
4
- ChannelStates,
5
- Conversation,
6
- ConversationMessage,
7
- EventType,
8
- FetchSsePayload,
9
- SseResponse,
10
- } from '@asgard-js/core';
11
- import { useCallback, useEffect, useMemo, useState } from 'react';
12
-
13
- export interface UseChannelProps {
14
- defaultIsOpen?: boolean;
15
- resetPayload?: Pick<FetchSsePayload, 'text'> & Partial<Pick<FetchSsePayload, 'payload'>>;
16
- client: AsgardServiceClient | null;
17
- customChannelId: string;
18
- customMessageId?: string;
19
- initMessages?: ConversationMessage[];
20
- onSseMessage?: (
21
- response: SseResponse<EventType>,
22
- context: {
23
- conversation: Conversation | null;
24
- }
25
- ) => void;
26
- }
27
-
28
- export interface UseChannelReturn {
29
- isOpen: boolean;
30
- isResetting: boolean;
31
- isConnecting: boolean;
32
- conversation: Conversation | null;
33
- sendMessage?: (payload: Pick<FetchSsePayload, 'text'> & Partial<Pick<FetchSsePayload, 'payload'>>) => void;
34
- resetChannel?: (payload?: Pick<FetchSsePayload, 'text'> & Partial<Pick<FetchSsePayload, 'payload'>>) => void;
35
- closeChannel?: () => void;
36
- }
37
-
38
- export function useChannel(props: UseChannelProps): UseChannelReturn {
39
- const {
40
- client,
41
- defaultIsOpen,
42
- resetPayload,
43
- customChannelId,
44
- customMessageId,
45
- initMessages,
46
- onSseMessage,
47
- } = props;
48
-
49
- if (!client) {
50
- throw new Error('Client instance is required');
51
- }
52
-
53
- if (!customChannelId) {
54
- throw new Error('Custom channel id is required');
55
- }
56
-
57
- const [channel, setChannel] = useState<Channel | null>(null);
58
- const [isOpen, setIsOpen] = useState(defaultIsOpen ?? true);
59
- const [isResetting, setIsResetting] = useState(false);
60
- const [isConnecting, setIsConnecting] = useState(false);
61
- const [conversation, setConversation] = useState<Conversation | null>(null);
62
-
63
- const resetChannel = useCallback(
64
- async (payload?: Pick<FetchSsePayload, 'text'> & Partial<Pick<FetchSsePayload, 'payload'>>) => {
65
- const conversation = new Conversation({
66
- messages: new Map(
67
- initMessages?.map((message) => [message.messageId, message])
68
- ),
69
- });
70
-
71
- setIsResetting(true);
72
- setIsConnecting(true);
73
- setConversation(conversation);
74
-
75
- const channel = await Channel.reset(
76
- {
77
- client,
78
- customChannelId,
79
- customMessageId,
80
- conversation,
81
- statesObserver: (states: ChannelStates): void => {
82
- setIsConnecting(states.isConnecting);
83
- setConversation(states.conversation);
84
- },
85
- },
86
- payload,
87
- {
88
- onSseCompleted() {
89
- setIsResetting(false);
90
- },
91
- onSseError() {
92
- setIsResetting(false);
93
- },
94
- onSseMessage(response: SseResponse<EventType>) {
95
- onSseMessage?.(response, {
96
- conversation,
97
- });
98
- },
99
- }
100
- );
101
-
102
- setIsOpen(true);
103
- setChannel(channel);
104
- },
105
- [client, customChannelId, customMessageId, initMessages, onSseMessage]
106
- );
107
-
108
- const closeChannel = useCallback(() => {
109
- setChannel((prevChannel: Channel | null) => {
110
- prevChannel?.close();
111
-
112
- return null;
113
- });
114
- setIsOpen(false);
115
- setIsResetting(false);
116
- setIsConnecting(false);
117
- setConversation(null);
118
- }, []);
119
-
120
- const sendMessage = useCallback(
121
- (payload: Pick<FetchSsePayload, 'text'> & Partial<Pick<FetchSsePayload, 'payload'>>) =>
122
- channel?.sendMessage({ ...payload, customMessageId }),
123
- [channel, customMessageId]
124
- );
125
-
126
- useEffect(() => {
127
- if (!channel && isOpen) resetChannel(resetPayload);
128
- }, [channel, isOpen, resetChannel, resetPayload]);
129
-
130
- useEffect(() => {
131
- return (): void => closeChannel();
132
- }, [closeChannel]);
133
-
134
- return useMemo(
135
- () => ({
136
- isOpen,
137
- isResetting,
138
- isConnecting,
139
- conversation,
140
- sendMessage,
141
- resetChannel,
142
- closeChannel,
143
- }),
144
- [
145
- isOpen,
146
- isResetting,
147
- isConnecting,
148
- conversation,
149
- sendMessage,
150
- resetChannel,
151
- closeChannel,
152
- ]
153
- );
154
- }
@@ -1,18 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- export function useDebounce<ValueType>(
4
- value: ValueType,
5
- delay?: number
6
- ): ValueType {
7
- const [debouncedValue, setDebouncedValue] = useState(value);
8
-
9
- useEffect(() => {
10
- const handler = window.setTimeout(() => {
11
- setDebouncedValue(value);
12
- }, delay ?? 300);
13
-
14
- return (): void => clearTimeout(handler);
15
- }, [value, delay]);
16
-
17
- return debouncedValue;
18
- }
@@ -1,19 +0,0 @@
1
- import { useRef } from 'react';
2
- import { isEqual } from '../utils/is';
3
-
4
- /**
5
- * useDeepCompareMemo: React hook that only recomputes the value when deps deeply change.
6
- * @param factory - function to create the value
7
- * @param deps - dependency array (deep compared)
8
- */
9
- export function useDeepCompareMemo<T>(factory: () => T, deps: unknown[]): T {
10
- const valueRef = useRef<T>();
11
- const depsRef = useRef<unknown[]>();
12
-
13
- if (!depsRef.current || !isEqual(depsRef.current, deps)) {
14
- depsRef.current = deps;
15
- valueRef.current = factory();
16
- }
17
-
18
- return valueRef.current as T;
19
- }