@asgard-js/react 0.0.40-canary.2 → 0.0.41-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 (146) hide show
  1. package/dist/components/chatbot/chatbot-body/conversation-message-renderer.d.ts.map +1 -1
  2. package/dist/components/chatbot/chatbot-footer/chatbot-footer.d.ts.map +1 -1
  3. package/dist/components/chatbot/chatbot.d.ts +0 -3
  4. package/dist/components/chatbot/chatbot.d.ts.map +1 -1
  5. package/dist/components/templates/index.d.ts +1 -0
  6. package/dist/components/templates/index.d.ts.map +1 -1
  7. package/dist/components/templates/user-image-template/index.d.ts +2 -0
  8. package/dist/components/templates/user-image-template/index.d.ts.map +1 -0
  9. package/dist/components/templates/user-image-template/user-image-template.d.ts +12 -0
  10. package/dist/components/templates/user-image-template/user-image-template.d.ts.map +1 -0
  11. package/dist/context/asgard-service-context.d.ts +1 -0
  12. package/dist/context/asgard-service-context.d.ts.map +1 -1
  13. package/dist/hooks/use-channel.d.ts +1 -1
  14. package/dist/hooks/use-channel.d.ts.map +1 -1
  15. package/dist/index.js +18568 -19052
  16. package/dist/style.css +1 -1
  17. package/dist/utils/file-validation.d.ts +12 -0
  18. package/dist/utils/file-validation.d.ts.map +1 -0
  19. package/package.json +2 -2
  20. package/.babelrc +0 -12
  21. package/dist/components/chatbot/api-key-input/api-key-input.d.ts +0 -11
  22. package/dist/components/chatbot/api-key-input/api-key-input.d.ts.map +0 -1
  23. package/dist/components/chatbot/api-key-input/index.d.ts +0 -2
  24. package/dist/components/chatbot/api-key-input/index.d.ts.map +0 -1
  25. package/eslint.config.cjs +0 -12
  26. package/src/components/chatbot/api-key-input/api-key-input.module.scss +0 -192
  27. package/src/components/chatbot/api-key-input/api-key-input.tsx +0 -119
  28. package/src/components/chatbot/api-key-input/index.ts +0 -1
  29. package/src/components/chatbot/chatbot-body/chatbot-body.module.scss +0 -13
  30. package/src/components/chatbot/chatbot-body/chatbot-body.tsx +0 -45
  31. package/src/components/chatbot/chatbot-body/conversation-message-renderer.tsx +0 -55
  32. package/src/components/chatbot/chatbot-body/index.ts +0 -1
  33. package/src/components/chatbot/chatbot-container/chatbot-container.module.scss +0 -41
  34. package/src/components/chatbot/chatbot-container/chatbot-container.tsx +0 -49
  35. package/src/components/chatbot/chatbot-container/chatbot-full-screen-container.tsx +0 -54
  36. package/src/components/chatbot/chatbot-footer/chatbot-footer.module.scss +0 -67
  37. package/src/components/chatbot/chatbot-footer/chatbot-footer.tsx +0 -140
  38. package/src/components/chatbot/chatbot-footer/index.ts +0 -1
  39. package/src/components/chatbot/chatbot-footer/speech-input-button.tsx +0 -132
  40. package/src/components/chatbot/chatbot-header/chatbot-header.module.scss +0 -48
  41. package/src/components/chatbot/chatbot-header/chatbot-header.tsx +0 -98
  42. package/src/components/chatbot/chatbot-header/index.ts +0 -1
  43. package/src/components/chatbot/chatbot.spec.tsx +0 -8
  44. package/src/components/chatbot/chatbot.tsx +0 -195
  45. package/src/components/chatbot/profile-icon.tsx +0 -26
  46. package/src/components/index.ts +0 -2
  47. package/src/components/templates/avatar/avatar.module.scss +0 -6
  48. package/src/components/templates/avatar/avatar.tsx +0 -28
  49. package/src/components/templates/avatar/index.ts +0 -1
  50. package/src/components/templates/button-template/button-template.module.scss +0 -0
  51. package/src/components/templates/button-template/button-template.tsx +0 -45
  52. package/src/components/templates/button-template/card.module.scss +0 -58
  53. package/src/components/templates/button-template/card.spec.tsx +0 -213
  54. package/src/components/templates/button-template/card.tsx +0 -123
  55. package/src/components/templates/button-template/index.ts +0 -1
  56. package/src/components/templates/carousel-template/carousel-template.module.scss +0 -15
  57. package/src/components/templates/carousel-template/carousel-template.tsx +0 -49
  58. package/src/components/templates/carousel-template/index.ts +0 -1
  59. package/src/components/templates/chart-template/chart-template.module.scss +0 -52
  60. package/src/components/templates/chart-template/chart-template.tsx +0 -75
  61. package/src/components/templates/chart-template/index.ts +0 -1
  62. package/src/components/templates/hint-template/hint-template.module.scss +0 -43
  63. package/src/components/templates/hint-template/hint-template.tsx +0 -76
  64. package/src/components/templates/hint-template/index.ts +0 -1
  65. package/src/components/templates/image-template/image-template.module.scss +0 -67
  66. package/src/components/templates/image-template/image-template.tsx +0 -58
  67. package/src/components/templates/image-template/index.ts +0 -1
  68. package/src/components/templates/index.ts +0 -10
  69. package/src/components/templates/quick-replies/index.ts +0 -1
  70. package/src/components/templates/quick-replies/quick-replies.module.scss +0 -16
  71. package/src/components/templates/quick-replies/quick-replies.tsx +0 -47
  72. package/src/components/templates/template-box/index.ts +0 -2
  73. package/src/components/templates/template-box/template-box-content.module.scss +0 -13
  74. package/src/components/templates/template-box/template-box-content.tsx +0 -30
  75. package/src/components/templates/template-box/template-box.module.scss +0 -19
  76. package/src/components/templates/template-box/template-box.tsx +0 -48
  77. package/src/components/templates/text-template/bot-typing-box.tsx +0 -81
  78. package/src/components/templates/text-template/bot-typing-placeholder.tsx +0 -28
  79. package/src/components/templates/text-template/index.ts +0 -3
  80. package/src/components/templates/text-template/text-template.module.scss +0 -131
  81. package/src/components/templates/text-template/text-template.tsx +0 -94
  82. package/src/components/templates/text-template/use-react-markdown-renderer.spec.tsx +0 -758
  83. package/src/components/templates/time/index.ts +0 -1
  84. package/src/components/templates/time/time.module.scss +0 -6
  85. package/src/components/templates/time/time.tsx +0 -34
  86. package/src/context/asgard-app-initialization-context.tsx +0 -154
  87. package/src/context/asgard-service-context.tsx +0 -145
  88. package/src/context/asgard-template-context.tsx +0 -83
  89. package/src/context/asgard-theme-context.tsx +0 -546
  90. package/src/context/index.ts +0 -4
  91. package/src/hooks/index.ts +0 -11
  92. package/src/hooks/use-asgard-service-client.ts +0 -68
  93. package/src/hooks/use-channel.ts +0 -154
  94. package/src/hooks/use-debounce.ts +0 -18
  95. package/src/hooks/use-deep-compare-memo.ts +0 -19
  96. package/src/hooks/use-is-on-screen-keyboard-open.ts +0 -43
  97. package/src/hooks/use-on-screen-keyboard-scroll-fix.ts +0 -15
  98. package/src/hooks/use-prevent-over-scrolling.ts +0 -77
  99. package/src/hooks/use-react-markdown-renderer.tsx +0 -278
  100. package/src/hooks/use-resize-observer.tsx +0 -27
  101. package/src/hooks/use-update-vh.ts +0 -30
  102. package/src/hooks/use-viewport-size.ts +0 -51
  103. package/src/icons/add_a_photo.svg +0 -3
  104. package/src/icons/bot.svg +0 -14
  105. package/src/icons/close.svg +0 -3
  106. package/src/icons/distance.svg +0 -3
  107. package/src/icons/mic.svg +0 -3
  108. package/src/icons/photo_library.svg +0 -3
  109. package/src/icons/profile.svg +0 -28
  110. package/src/icons/refresh.svg +0 -3
  111. package/src/icons/send.svg +0 -3
  112. package/src/icons/stop.svg +0 -22
  113. package/src/icons/volume_up.svg +0 -3
  114. package/src/index.ts +0 -4
  115. package/src/models/bot-provider.ts +0 -108
  116. package/src/styles/_index.scss +0 -1
  117. package/src/styles/_styles.scss +0 -11
  118. package/src/styles/colors/_colors.scss +0 -10
  119. package/src/styles/colors/_index.scss +0 -1
  120. package/src/styles/colors/_variables.scss +0 -72
  121. package/src/styles/palette/_index.scss +0 -1
  122. package/src/styles/palette/_palette.scss +0 -42
  123. package/src/styles/palette/_variables.scss +0 -40
  124. package/src/styles/radius/_index.scss +0 -1
  125. package/src/styles/radius/_radius.scss +0 -8
  126. package/src/styles/radius/_variables.scss +0 -12
  127. package/src/styles/spacing/_index.scss +0 -1
  128. package/src/styles/spacing/_spacing.scss +0 -8
  129. package/src/styles/spacing/_variables.scss +0 -13
  130. package/src/styles/utils/_index.scss +0 -1
  131. package/src/styles/utils/_map.scss +0 -22
  132. package/src/test-setup.ts +0 -1
  133. package/src/utils/color-utils.ts +0 -52
  134. package/src/utils/deep-merge.ts +0 -26
  135. package/src/utils/extractors.ts +0 -20
  136. package/src/utils/format-time.ts +0 -8
  137. package/src/utils/index.ts +0 -1
  138. package/src/utils/is.ts +0 -72
  139. package/src/utils/selectors.ts +0 -7
  140. package/src/utils/uri-validation.spec.ts +0 -208
  141. package/src/utils/uri-validation.ts +0 -103
  142. package/tsconfig.json +0 -16
  143. package/tsconfig.lib.json +0 -63
  144. package/tsconfig.spec.json +0 -36
  145. package/tsconfig.tsbuildinfo +0 -1
  146. package/vite.config.ts +0 -63
@@ -1,67 +0,0 @@
1
- .chatbot_footer {
2
- border-top: 1px solid #434343;
3
-
4
- .chatbot_footer__content {
5
- display: grid;
6
- align-items: flex-end;
7
- grid-template-columns: auto 24px;
8
- margin: 0 auto;
9
- max-width: 1200px;
10
- padding: var(--asg-spacing-3) var(--asg-spacing-4);
11
- gap: var(--asg-spacing-2);
12
- }
13
- }
14
-
15
- .chatbot_textarea {
16
- font: inherit;
17
- font-size: 16px;
18
- height: 36px;
19
- max-height: 240px;
20
- padding: 8px;
21
- padding-left: 12px;
22
- background: var(--asg-color-bg);
23
- border: 1px solid rgba(67, 67, 67, 1);
24
- border-radius: 2px;
25
- color: rgba(140, 140, 140, 1);
26
- resize: none;
27
- overflow: hidden;
28
-
29
- &::placeholder {
30
- color: var(--asg-color-text-placeholder);
31
- }
32
- }
33
-
34
- .chatbot_submit_button {
35
- font: inherit;
36
- width: 24px;
37
- height: 100%;
38
- max-height: 38px;
39
- display: flex;
40
- justify-content: center;
41
- align-items: center;
42
- font-size: 16px;
43
- border: none;
44
- background: transparent;
45
- border-radius: 50%;
46
- color: white;
47
- cursor: pointer;
48
-
49
- > svg {
50
- -webkit-touch-callout: none;
51
- -webkit-user-select: none;
52
- user-select: none;
53
- width: auto;
54
- min-width: 16px;
55
- height: 60%;
56
- max-height: 38px;
57
- min-height: 16px;
58
- }
59
-
60
- &.chatbot_submit_button__disabled {
61
- > svg {
62
- > path {
63
- fill: rgba(140, 140, 140, 1);
64
- }
65
- }
66
- }
67
- }
@@ -1,140 +0,0 @@
1
- import {
2
- ChangeEventHandler,
3
- KeyboardEventHandler,
4
- ReactNode,
5
- useCallback,
6
- useEffect,
7
- useMemo,
8
- useRef,
9
- useState,
10
- } from 'react';
11
- import { useAsgardContext } from '../../../context/asgard-service-context';
12
- import styles from './chatbot-footer.module.scss';
13
- import SendSvg from '../../../icons/send.svg?react';
14
- import { SpeechInputButton } from './speech-input-button';
15
- import clsx from 'clsx';
16
- import { useAsgardThemeContext } from '../../../context/asgard-theme-context';
17
-
18
- export function ChatbotFooter(): ReactNode {
19
- const { sendMessage, isConnecting, inputPlaceholder } = useAsgardContext();
20
-
21
- const { chatbot } = useAsgardThemeContext();
22
-
23
- const [value, setValue] = useState('');
24
- const [isComposing, setIsComposing] = useState(false);
25
- const textareaRef = useRef<HTMLTextAreaElement>(null);
26
-
27
- const disabled = useMemo(
28
- () => isConnecting || !value.trim(),
29
- [isConnecting, value]
30
- );
31
-
32
- const contentStyles = useMemo(
33
- () => ({
34
- maxWidth: chatbot?.contentMaxWidth ?? '1200px',
35
- borderTopColor: chatbot?.borderColor,
36
- }),
37
- [chatbot]
38
- );
39
-
40
- const onChange = useCallback<ChangeEventHandler<HTMLTextAreaElement>>(
41
- (event) => {
42
- const element = event.target as HTMLTextAreaElement;
43
- const value = element.value;
44
-
45
- element.style.height = '36px';
46
-
47
- if (value) {
48
- element.style.height = `${element.scrollHeight}px`;
49
- }
50
-
51
- setValue(event.target.value);
52
- },
53
- []
54
- );
55
-
56
- const onSubmit = useCallback(() => {
57
- if (!isComposing && !isConnecting) {
58
- sendMessage?.({ text: value });
59
- setValue('');
60
-
61
- if (textareaRef.current) {
62
- textareaRef.current.style.height = '36px';
63
- }
64
- }
65
- }, [isComposing, isConnecting, sendMessage, value]);
66
-
67
- const onKeyDown = useCallback<KeyboardEventHandler<HTMLTextAreaElement>>(
68
- (event) => {
69
- if (
70
- event.key === 'Enter' &&
71
- !isComposing &&
72
- !isConnecting &&
73
- value.trim()
74
- ) {
75
- sendMessage?.({ text: value });
76
- setValue('');
77
-
78
- const element = event.target as HTMLTextAreaElement;
79
-
80
- element.style.height = '36px';
81
- }
82
- },
83
- [isComposing, isConnecting, sendMessage, value]
84
- );
85
-
86
- useEffect(() => {
87
- if (textareaRef.current) {
88
- textareaRef.current.style.setProperty(
89
- '--asg-color-text-placeholder',
90
- chatbot.footer?.textArea?.['::placeholder']?.color ??
91
- 'var(--asg-color-text-placeholder)'
92
- );
93
- }
94
- }, [chatbot.footer?.textArea]);
95
-
96
- return (
97
- <div
98
- className={clsx('asgard-chatbot-footer', styles.chatbot_footer)}
99
- style={chatbot.footer?.style}
100
- >
101
- <div className={styles.chatbot_footer__content} style={contentStyles}>
102
- <textarea
103
- ref={textareaRef}
104
- className={styles.chatbot_textarea}
105
- style={chatbot.footer?.textArea?.style}
106
- disabled={isConnecting}
107
- cols={40}
108
- value={value}
109
- placeholder={inputPlaceholder || "Enter message"}
110
- onChange={onChange}
111
- onKeyDown={onKeyDown}
112
- onCompositionStart={() => setIsComposing(true)}
113
- onCompositionEnd={() => setIsComposing(false)}
114
- />
115
- {value ? (
116
- <button
117
- className={clsx(
118
- styles.chatbot_submit_button,
119
- disabled && styles.chatbot_submit_button__disabled
120
- )}
121
- style={chatbot.footer?.submitButton?.style}
122
- disabled={disabled}
123
- onClick={onSubmit}
124
- >
125
- <SendSvg />
126
- </button>
127
- ) : (
128
- <SpeechInputButton
129
- setValue={setValue}
130
- className={clsx(
131
- styles.chatbot_submit_button,
132
- isConnecting && styles.chatbot_submit_button__disabled
133
- )}
134
- style={chatbot.footer?.speechInputButton?.style}
135
- />
136
- )}
137
- </div>
138
- </div>
139
- );
140
- }
@@ -1 +0,0 @@
1
- export * from './chatbot-footer';
@@ -1,132 +0,0 @@
1
- import {
2
- Dispatch,
3
- MouseEventHandler,
4
- ReactNode,
5
- SetStateAction,
6
- TouchEventHandler,
7
- useCallback,
8
- useEffect,
9
- useRef,
10
- useState,
11
- CSSProperties,
12
- } from 'react';
13
- import MicSvg from '../../../icons/mic.svg?react';
14
- import StopSvg from '../../../icons/stop.svg?react';
15
-
16
- interface SpeechInputButtonProps {
17
- setValue: Dispatch<SetStateAction<string>>;
18
- className?: string;
19
- style?: CSSProperties;
20
- }
21
-
22
- export function SpeechInputButton(props: SpeechInputButtonProps): ReactNode {
23
- const { setValue, className, style } = props;
24
-
25
- const [listening, setListening] = useState(false);
26
- const recognitionRef = useRef<SpeechRecognition | null>(null);
27
-
28
- useEffect(() => {
29
- const SpeechRecognition =
30
- window.SpeechRecognition || window.webkitSpeechRecognition;
31
-
32
- if (!SpeechRecognition) return;
33
-
34
- const recognition = new SpeechRecognition();
35
- recognition.lang = 'zh-TW';
36
- recognition.continuous = true;
37
- recognition.interimResults = true;
38
-
39
- recognition.onresult = (event: SpeechRecognitionEvent): void => {
40
- for (let i = event.resultIndex; i < event.results.length; i++) {
41
- if (event.results[i].isFinal) {
42
- setValue((prev) => prev + event.results[i][0].transcript);
43
- }
44
- }
45
- };
46
-
47
- recognition.onerror = (event: SpeechRecognitionErrorEvent): void => {
48
- alert(`語音識別錯誤: ${JSON.stringify(event.error)}`);
49
- };
50
-
51
- recognition.onend = (): void => {
52
- setListening(false);
53
- };
54
-
55
- recognitionRef.current = recognition;
56
- }, [setValue]);
57
-
58
- const startListening = useCallback(() => {
59
- if (!recognitionRef.current) {
60
- alert('無法開始辨識: 語音識別器未初始化,請檢查是否有授權使用麥克風');
61
-
62
- return;
63
- }
64
-
65
- try {
66
- recognitionRef.current.start();
67
- setListening(true);
68
- } catch (error) {
69
- alert(`無法開始辨識: ${JSON.stringify(error)}`);
70
- }
71
- }, []);
72
-
73
- const stopListening = useCallback(() => {
74
- if (!recognitionRef.current) return;
75
-
76
- recognitionRef.current.stop();
77
- setListening(false);
78
- }, []);
79
-
80
- const onMouseDown = useCallback<MouseEventHandler<HTMLDivElement>>(
81
- (event) => {
82
- if (!listening) {
83
- event.preventDefault();
84
- startListening();
85
- }
86
- },
87
- [listening, startListening]
88
- );
89
-
90
- const onMouseUp = useCallback<MouseEventHandler<HTMLDivElement>>(
91
- (event) => {
92
- if (listening) {
93
- event.preventDefault();
94
- stopListening();
95
- }
96
- },
97
- [listening, stopListening]
98
- );
99
-
100
- const onTouchStart = useCallback<TouchEventHandler<HTMLDivElement>>(
101
- (event) => {
102
- if (!listening) {
103
- event.preventDefault();
104
- startListening();
105
- }
106
- },
107
- [listening, startListening]
108
- );
109
-
110
- const onTouchEnd = useCallback<TouchEventHandler<HTMLDivElement>>(
111
- (event) => {
112
- if (listening) {
113
- event.preventDefault();
114
- stopListening();
115
- }
116
- },
117
- [listening, stopListening]
118
- );
119
-
120
- return (
121
- <div
122
- className={className}
123
- style={style}
124
- onMouseDown={onMouseDown}
125
- onMouseUp={onMouseUp}
126
- onTouchStart={onTouchStart}
127
- onTouchEnd={onTouchEnd}
128
- >
129
- {listening ? <StopSvg /> : <MicSvg />}
130
- </div>
131
- );
132
- }
@@ -1,48 +0,0 @@
1
- .chatbot_header {
2
- border-bottom: 1px solid #434343;
3
-
4
- .chatbot_header__content {
5
- margin: 0 auto;
6
- max-width: 1200px;
7
- padding: var(--asg-spacing-4);
8
- display: flex;
9
- justify-content: space-between;
10
- }
11
- }
12
-
13
- .chatbot_header__title {
14
- display: flex;
15
- flex-direction: row;
16
- align-items: center;
17
- gap: var(--asg-spacing-2);
18
-
19
- > h4 {
20
- margin: 0;
21
- color: white;
22
- }
23
- }
24
-
25
- .chatbot_header__extra {
26
- display: flex;
27
- flex-direction: row;
28
- align-items: center;
29
- gap: var(--asg-spacing-3);
30
-
31
- > div {
32
- width: 24px;
33
- height: 24px;
34
- display: flex;
35
- justify-content: center;
36
- align-items: center;
37
-
38
- > svg {
39
- width: 15px;
40
- height: 15px;
41
- cursor: pointer;
42
-
43
- &:hover {
44
- opacity: 0.5;
45
- }
46
- }
47
- }
48
- }
@@ -1,98 +0,0 @@
1
- import { MouseEventHandler, ReactNode, useCallback, useMemo } from 'react';
2
- import styles from './chatbot-header.module.scss';
3
- import { ProfileIcon } from '../profile-icon';
4
- import RefreshSvg from '../../../icons/refresh.svg?react';
5
- import CloseSvg from '../../../icons/close.svg?react';
6
- import {
7
- useAsgardAppInitializationContext,
8
- useAsgardThemeContext,
9
- useAsgardContext,
10
- } from '../../../context/';
11
- import clsx from 'clsx';
12
-
13
- interface ChatbotHeaderProps {
14
- title?: string;
15
- customActions?: ReactNode[];
16
- maintainConnectionWhenClosed?: boolean;
17
- onClose?: () => void;
18
- onReset?: () => void;
19
- }
20
-
21
- export function ChatbotHeader(props: ChatbotHeaderProps): ReactNode {
22
- const {
23
- title,
24
- onReset,
25
- onClose,
26
- customActions,
27
- maintainConnectionWhenClosed,
28
- } = props;
29
-
30
- const { chatbot } = useAsgardThemeContext();
31
- const {
32
- data: { annotations },
33
- } = useAsgardAppInitializationContext();
34
-
35
- const { avatar, isResetting, resetChannel, closeChannel } =
36
- useAsgardContext();
37
-
38
- const contentStyles = useMemo(
39
- () => ({
40
- maxWidth: chatbot?.contentMaxWidth ?? '1200px',
41
- borderBottomColor: chatbot?.borderColor,
42
- }),
43
- [chatbot]
44
- );
45
-
46
- const _onReset = useCallback<MouseEventHandler<HTMLDivElement>>(
47
- (e) => {
48
- if (!isResetting) {
49
- e.stopPropagation();
50
- onReset?.();
51
- resetChannel?.();
52
- }
53
- },
54
- [isResetting, onReset, resetChannel]
55
- );
56
-
57
- const _onClose = useCallback<MouseEventHandler<HTMLDivElement>>(
58
- (e) => {
59
- if (!isResetting) {
60
- e.stopPropagation();
61
- onClose?.();
62
-
63
- if (!maintainConnectionWhenClosed) {
64
- closeChannel?.();
65
- }
66
- }
67
- },
68
- [isResetting, onClose, closeChannel, maintainConnectionWhenClosed]
69
- );
70
-
71
- return (
72
- <div
73
- className={clsx('asgard-chatbot-header', styles.chatbot_header)}
74
- style={chatbot?.header?.style}
75
- >
76
- <div className={styles.chatbot_header__content} style={contentStyles}>
77
- <div className={styles.chatbot_header__title}>
78
- <ProfileIcon avatar={avatar} />
79
- <h4 style={chatbot?.header?.title?.style}>
80
- {annotations?.embedConfig?.title || title || 'Bot'}
81
- </h4>
82
- </div>
83
- <div
84
- className={styles.chatbot_header__extra}
85
- style={chatbot?.header?.actionButton?.style}
86
- >
87
- {customActions}
88
- <div onClick={_onReset}>
89
- <RefreshSvg />
90
- </div>
91
- <div onClick={_onClose}>
92
- <CloseSvg />
93
- </div>
94
- </div>
95
- </div>
96
- </div>
97
- );
98
- }
@@ -1 +0,0 @@
1
- export * from './chatbot-header';
@@ -1,8 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
-
3
- describe('Chatbot Component', () => {
4
- it('should have a basic test placeholder', () => {
5
- // Basic test to verify test environment works
6
- expect(true).toBe(true);
7
- });
8
- });
@@ -1,195 +0,0 @@
1
- import {
2
- forwardRef,
3
- ForwardedRef,
4
- ReactNode,
5
- CSSProperties,
6
- } from 'react';
7
- import { ClientConfig, ConversationMessage } from '@asgard-js/core';
8
- import {
9
- AsgardThemeContextProvider,
10
- AsgardThemeContextValue,
11
- } from '../../context/asgard-theme-context';
12
- import {
13
- AsgardServiceContextProvider,
14
- AsgardServiceContextValue,
15
- AsgardTemplateContextProvider,
16
- AsgardTemplateContextValue,
17
- AsgardAppInitializationContextProvider,
18
- AsgardServiceContextProviderProps,
19
- } from '../../context';
20
- import { ApiKeyInput } from './api-key-input';
21
- import { ChatbotHeader } from './chatbot-header';
22
- import { ChatbotBody } from './chatbot-body';
23
- import { ChatbotFooter } from './chatbot-footer';
24
- import { ChatbotContainer } from './chatbot-container/chatbot-container';
25
-
26
- type AuthState = 'loading' | 'needApiKey' | 'authenticated' | 'error';
27
-
28
- interface ChatbotProps extends AsgardTemplateContextValue {
29
- className?: string;
30
- style?: CSSProperties;
31
- title?: string;
32
- customActions?: ReactNode[];
33
- theme?: Partial<AsgardThemeContextValue>;
34
- config: ClientConfig;
35
- customChannelId: string;
36
- initMessages?: ConversationMessage[];
37
- onSseMessage?: AsgardServiceContextProviderProps['onSseMessage'];
38
- fullScreen?: boolean;
39
- avatar?: string;
40
- botTypingPlaceholder?: string;
41
- inputPlaceholder?: string;
42
- enableLoadConfigFromService?: boolean;
43
- maintainConnectionWhenClosed?: boolean;
44
- asyncInitializers?: Record<string, () => Promise<unknown>>;
45
- onReset?: () => void;
46
- onClose?: () => void;
47
- loadingComponent?: ReactNode;
48
- defaultLinkTarget?: '_blank' | '_self' | '_parent' | '_top';
49
-
50
- // Auth state props
51
- authState?: AuthState;
52
- onApiKeySubmit?: (apiKey: string) => Promise<void>;
53
- }
54
-
55
- export interface ChatbotRef {
56
- serviceContext?: AsgardServiceContextValue;
57
- }
58
-
59
- export const Chatbot = forwardRef(function Chatbot(
60
- props: ChatbotProps,
61
- ref: ForwardedRef<ChatbotRef>
62
- ): ReactNode {
63
- const {
64
- title,
65
- customActions,
66
- theme,
67
- config,
68
- customChannelId,
69
- initMessages,
70
- onSseMessage,
71
- fullScreen = false,
72
- avatar,
73
- botTypingPlaceholder,
74
- inputPlaceholder,
75
- enableLoadConfigFromService = false,
76
- maintainConnectionWhenClosed = false,
77
- asyncInitializers = {},
78
- loadingComponent,
79
- onReset,
80
- onClose,
81
- onTemplateBtnClick,
82
- onErrorClick,
83
- errorMessageRenderer,
84
- className,
85
- style,
86
- defaultLinkTarget,
87
- authState = 'authenticated',
88
- onApiKeySubmit,
89
- } = props;
90
-
91
- // Render different content based on authState
92
- const renderContent = () => {
93
- switch (authState) {
94
- case 'loading':
95
- return (
96
- <div style={{
97
- display: 'flex',
98
- alignItems: 'center',
99
- justifyContent: 'center',
100
- flex: 1,
101
- padding: '20px'
102
- }}>
103
- {loadingComponent || <div>Loading...</div>}
104
- </div>
105
- );
106
-
107
- case 'needApiKey':
108
- return (
109
- <div style={{
110
- display: 'flex',
111
- alignItems: 'center',
112
- justifyContent: 'center',
113
- flex: 1,
114
- padding: '20px'
115
- }}>
116
- <ApiKeyInput
117
- title={title}
118
- onSubmit={onApiKeySubmit || (() => {})}
119
- placeholder="Enter your key"
120
- />
121
- </div>
122
- );
123
-
124
- case 'error':
125
- return (
126
- <div style={{
127
- display: 'flex',
128
- alignItems: 'center',
129
- justifyContent: 'center',
130
- flex: 1,
131
- padding: '20px',
132
- color: '#ff6b6b'
133
- }}>
134
- <div style={{ textAlign: 'center' }}>
135
- <div style={{ fontSize: '16px', marginBottom: '8px' }}>⚠️</div>
136
- <div>Something went wrong. Please try again later.</div>
137
- </div>
138
- </div>
139
- );
140
-
141
- case 'authenticated':
142
- default:
143
- return (
144
- <>
145
- <AsgardTemplateContextProvider
146
- onErrorClick={onErrorClick}
147
- errorMessageRenderer={errorMessageRenderer}
148
- onTemplateBtnClick={onTemplateBtnClick}
149
- defaultLinkTarget={defaultLinkTarget}
150
- >
151
- <ChatbotBody />
152
- </AsgardTemplateContextProvider>
153
- <ChatbotFooter />
154
- </>
155
- );
156
- }
157
- };
158
-
159
- return (
160
- <AsgardAppInitializationContextProvider
161
- enabled={enableLoadConfigFromService}
162
- config={config}
163
- asyncInitializers={asyncInitializers}
164
- loadingComponent={loadingComponent}
165
- >
166
- <AsgardThemeContextProvider theme={theme}>
167
- <AsgardServiceContextProvider
168
- parentRef={ref}
169
- avatar={avatar}
170
- config={config}
171
- customChannelId={customChannelId}
172
- initMessages={initMessages}
173
- onSseMessage={onSseMessage}
174
- botTypingPlaceholder={botTypingPlaceholder}
175
- inputPlaceholder={inputPlaceholder}
176
- >
177
- <ChatbotContainer
178
- fullScreen={fullScreen}
179
- className={className}
180
- style={style}
181
- >
182
- <ChatbotHeader
183
- title={title}
184
- onReset={onReset}
185
- onClose={onClose}
186
- customActions={customActions}
187
- maintainConnectionWhenClosed={maintainConnectionWhenClosed}
188
- />
189
- {renderContent()}
190
- </ChatbotContainer>
191
- </AsgardServiceContextProvider>
192
- </AsgardThemeContextProvider>
193
- </AsgardAppInitializationContextProvider>
194
- );
195
- });