@asgard-js/react 0.0.43-canary.2 → 0.0.43-canary.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/chatbot/api-key-input/api-key-input.d.ts +2 -1
- package/dist/components/chatbot/api-key-input/api-key-input.d.ts.map +1 -1
- package/dist/components/chatbot/chatbot.d.ts +1 -1
- package/dist/components/chatbot/chatbot.d.ts.map +1 -1
- package/dist/context/asgard-theme-context.d.ts +2 -0
- package/dist/context/asgard-theme-context.d.ts.map +1 -1
- package/dist/index.js +11165 -11148
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/.DS_Store +0 -0
- package/src/components/chatbot/api-key-input/api-key-input.module.scss +35 -44
- package/src/components/chatbot/api-key-input/api-key-input.tsx +32 -34
- package/src/components/chatbot/chatbot.tsx +21 -2
- package/src/context/asgard-theme-context.tsx +7 -0
- package/src/icons/eye-off.svg +4 -0
- package/src/icons/eye.svg +4 -0
package/package.json
CHANGED
package/src/components/.DS_Store
CHANGED
|
Binary file
|
|
@@ -1,52 +1,51 @@
|
|
|
1
|
-
.
|
|
1
|
+
.api_key_input {
|
|
2
2
|
width: 220px;
|
|
3
3
|
background-color: var(--asg-color-bg);
|
|
4
4
|
border-radius: 12px;
|
|
5
|
-
padding: 20px;
|
|
5
|
+
padding: 12px 20px;
|
|
6
6
|
border: 0.5px solid var(--asg-color-border);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.form {
|
|
9
|
+
.api_key_input__header {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
gap: 4px;
|
|
13
|
+
align-items: center;
|
|
14
|
+
margin-bottom: 12px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.api_key_input__icon {
|
|
18
|
+
width: 24px;
|
|
19
|
+
height: 24px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.api_key_input__title {
|
|
23
|
+
margin: 0;
|
|
24
|
+
font-size: 18px;
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
color: white;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.api_key_input__form {
|
|
31
30
|
width: 100%;
|
|
32
31
|
display: flex;
|
|
33
32
|
flex-direction: column;
|
|
34
33
|
gap: 20px;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
.
|
|
36
|
+
.api_key_input__label {
|
|
38
37
|
display: block;
|
|
39
38
|
font-size: 14px;
|
|
40
39
|
color: rgba(255, 255, 255, 0.7);
|
|
41
40
|
margin-bottom: 8px;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
.
|
|
43
|
+
.api_key_input__input_wrapper {
|
|
45
44
|
position: relative;
|
|
46
45
|
width: 100%;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
.
|
|
48
|
+
.api_key_input__input {
|
|
50
49
|
width: 100%;
|
|
51
50
|
height: 42px;
|
|
52
51
|
padding: 0 40px 0 12px;
|
|
@@ -69,18 +68,18 @@
|
|
|
69
68
|
background: rgba(255, 255, 255, 0.08);
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
&--error {
|
|
73
72
|
border-color: rgba(255, 69, 58, 0.6);
|
|
74
73
|
background: rgba(255, 69, 58, 0.05);
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
&--disabled {
|
|
78
77
|
opacity: 0.5;
|
|
79
78
|
cursor: not-allowed;
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
.
|
|
82
|
+
.api_key_input__toggle_button {
|
|
84
83
|
position: absolute;
|
|
85
84
|
right: 8px;
|
|
86
85
|
top: 50%;
|
|
@@ -107,23 +106,23 @@
|
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
.
|
|
109
|
+
.api_key_input__toggle_icon {
|
|
111
110
|
width: 16px;
|
|
112
111
|
height: 16px;
|
|
113
112
|
}
|
|
114
113
|
|
|
115
|
-
.
|
|
114
|
+
.api_key_input__error_message {
|
|
116
115
|
margin-top: 6px;
|
|
117
116
|
font-size: 12px;
|
|
118
117
|
color: rgba(255, 69, 58, 0.8);
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
.
|
|
120
|
+
.api_key_input__submit_button {
|
|
122
121
|
width: 100%;
|
|
123
122
|
height: 42px;
|
|
124
|
-
background: #5856d6;
|
|
125
123
|
border: none;
|
|
126
124
|
border-radius: 6px;
|
|
125
|
+
background-color: #5856d6;
|
|
127
126
|
color: white;
|
|
128
127
|
font-size: 14px;
|
|
129
128
|
font-weight: 500;
|
|
@@ -131,14 +130,6 @@
|
|
|
131
130
|
transition: all 0.2s ease;
|
|
132
131
|
outline: none;
|
|
133
132
|
|
|
134
|
-
&:hover:not(:disabled) {
|
|
135
|
-
background: #4845c7;
|
|
136
|
-
transform: translateY(-1px);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
&:active:not(:disabled) {
|
|
140
|
-
transform: translateY(0);
|
|
141
|
-
}
|
|
142
133
|
|
|
143
134
|
&:disabled {
|
|
144
135
|
opacity: 0.5;
|
|
@@ -146,7 +137,7 @@
|
|
|
146
137
|
transform: none;
|
|
147
138
|
}
|
|
148
139
|
|
|
149
|
-
|
|
140
|
+
&--loading {
|
|
150
141
|
position: relative;
|
|
151
142
|
color: transparent;
|
|
152
143
|
|
|
@@ -178,7 +169,7 @@
|
|
|
178
169
|
|
|
179
170
|
// 響應式設計
|
|
180
171
|
@media (max-width: 280px) {
|
|
181
|
-
.
|
|
172
|
+
.api_key_input {
|
|
182
173
|
width: 100%;
|
|
183
174
|
min-width: 200px;
|
|
184
175
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { useState, FormEvent, ChangeEvent } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { useAsgardThemeContext } from '../../../context/asgard-theme-context';
|
|
4
|
+
import { useAsgardContext } from '../../../context/asgard-service-context';
|
|
5
|
+
import { ProfileIcon } from '../profile-icon';
|
|
6
|
+
import EyeSvg from '../../../icons/eye.svg?react';
|
|
7
|
+
import EyeOffSvg from '../../../icons/eye-off.svg?react';
|
|
4
8
|
import styles from './api-key-input.module.scss';
|
|
5
9
|
|
|
6
10
|
export interface ApiKeyInputProps {
|
|
@@ -8,6 +12,7 @@ export interface ApiKeyInputProps {
|
|
|
8
12
|
loading?: boolean;
|
|
9
13
|
error?: string;
|
|
10
14
|
placeholder?: string;
|
|
15
|
+
title?: string;
|
|
11
16
|
showToggle?: boolean;
|
|
12
17
|
className?: string;
|
|
13
18
|
}
|
|
@@ -17,12 +22,14 @@ export function ApiKeyInput({
|
|
|
17
22
|
loading = false,
|
|
18
23
|
error,
|
|
19
24
|
placeholder = 'Enter your key',
|
|
25
|
+
title = 'Preview',
|
|
20
26
|
showToggle = true,
|
|
21
27
|
className,
|
|
22
28
|
}: ApiKeyInputProps): JSX.Element {
|
|
23
29
|
const [apiKey, setApiKey] = useState('');
|
|
24
30
|
const [showPassword, setShowPassword] = useState(false);
|
|
25
31
|
const { chatbot } = useAsgardThemeContext();
|
|
32
|
+
const { avatar } = useAsgardContext();
|
|
26
33
|
|
|
27
34
|
const handleSubmit = (e: FormEvent): void => {
|
|
28
35
|
e.preventDefault();
|
|
@@ -41,24 +48,29 @@ export function ApiKeyInput({
|
|
|
41
48
|
|
|
42
49
|
return (
|
|
43
50
|
<div
|
|
44
|
-
className={clsx(styles.
|
|
51
|
+
className={clsx(styles.api_key_input, className)}
|
|
45
52
|
style={{
|
|
46
53
|
backgroundColor: chatbot.backgroundColor,
|
|
47
54
|
borderColor: chatbot.borderColor,
|
|
48
55
|
}}
|
|
49
56
|
>
|
|
50
|
-
<
|
|
57
|
+
<div className={styles.api_key_input__header}>
|
|
58
|
+
<ProfileIcon avatar={avatar} />
|
|
59
|
+
<h2 className={styles.api_key_input__title} style={chatbot?.header?.title?.style}>{title}</h2>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<form onSubmit={handleSubmit} className={styles.api_key_input__form}>
|
|
51
63
|
<div className={styles.inputGroup}>
|
|
52
|
-
<label className={styles.
|
|
53
|
-
<div className={styles.
|
|
64
|
+
<label className={styles.api_key_input__label}>Key</label>
|
|
65
|
+
<div className={styles.api_key_input__input_wrapper}>
|
|
54
66
|
<input
|
|
55
67
|
type={showPassword ? 'text' : 'password'}
|
|
56
68
|
value={apiKey}
|
|
57
69
|
onChange={handleInputChange}
|
|
58
70
|
placeholder={placeholder}
|
|
59
|
-
className={clsx(styles.
|
|
60
|
-
[styles
|
|
61
|
-
[styles
|
|
71
|
+
className={clsx(styles.api_key_input__input, {
|
|
72
|
+
[styles['api_key_input__input--error']]: error,
|
|
73
|
+
[styles['api_key_input__input--disabled']]: loading,
|
|
62
74
|
})}
|
|
63
75
|
disabled={loading}
|
|
64
76
|
autoComplete="off"
|
|
@@ -67,45 +79,31 @@ export function ApiKeyInput({
|
|
|
67
79
|
<button
|
|
68
80
|
type="button"
|
|
69
81
|
onClick={togglePasswordVisibility}
|
|
70
|
-
className={styles.
|
|
82
|
+
className={styles.api_key_input__toggle_button}
|
|
71
83
|
disabled={loading}
|
|
72
84
|
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
|
73
85
|
>
|
|
74
|
-
|
|
75
|
-
className={styles.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
fill="none"
|
|
80
|
-
stroke="currentColor"
|
|
81
|
-
strokeWidth="2"
|
|
82
|
-
strokeLinecap="round"
|
|
83
|
-
strokeLinejoin="round"
|
|
84
|
-
>
|
|
85
|
-
{showPassword ? (
|
|
86
|
-
<>
|
|
87
|
-
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" />
|
|
88
|
-
<line x1="1" y1="1" x2="23" y2="23" />
|
|
89
|
-
</>
|
|
90
|
-
) : (
|
|
91
|
-
<>
|
|
92
|
-
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
93
|
-
<circle cx="12" cy="12" r="3" />
|
|
94
|
-
</>
|
|
95
|
-
)}
|
|
96
|
-
</svg>
|
|
86
|
+
{showPassword ? (
|
|
87
|
+
<EyeOffSvg className={styles.api_key_input__toggle_icon} />
|
|
88
|
+
) : (
|
|
89
|
+
<EyeSvg className={styles.api_key_input__toggle_icon} />
|
|
90
|
+
)}
|
|
97
91
|
</button>
|
|
98
92
|
)}
|
|
99
93
|
</div>
|
|
100
|
-
{error && <div className={styles.
|
|
94
|
+
{error && <div className={styles.api_key_input__error_message}>{error}</div>}
|
|
101
95
|
</div>
|
|
102
96
|
|
|
103
97
|
<button
|
|
104
98
|
type="submit"
|
|
105
99
|
disabled={!apiKey.trim() || loading}
|
|
106
|
-
className={clsx(styles.
|
|
107
|
-
[styles
|
|
100
|
+
className={clsx(styles.api_key_input__submit_button, {
|
|
101
|
+
[styles['api_key_input__submit_button--loading']]: loading,
|
|
108
102
|
})}
|
|
103
|
+
style={{
|
|
104
|
+
backgroundColor: chatbot?.mainColor,
|
|
105
|
+
color: chatbot?.secondaryColor,
|
|
106
|
+
}}
|
|
109
107
|
>
|
|
110
108
|
{loading ? 'Loading...' : 'Continue'}
|
|
111
109
|
</button>
|
|
@@ -23,7 +23,7 @@ import { ChatbotBody } from './chatbot-body';
|
|
|
23
23
|
import { ChatbotFooter } from './chatbot-footer';
|
|
24
24
|
import { ChatbotContainer } from './chatbot-container/chatbot-container';
|
|
25
25
|
|
|
26
|
-
type AuthState = 'loading' | 'needApiKey' | 'authenticated' | 'error';
|
|
26
|
+
type AuthState = 'loading' | 'needApiKey' | 'authenticated' | 'error' | 'invalidApiKey';
|
|
27
27
|
|
|
28
28
|
interface ChatbotProps extends AsgardTemplateContextValue {
|
|
29
29
|
className?: string;
|
|
@@ -116,12 +116,31 @@ export const Chatbot = forwardRef(function Chatbot(
|
|
|
116
116
|
padding: '20px'
|
|
117
117
|
}}>
|
|
118
118
|
<ApiKeyInput
|
|
119
|
+
title={title}
|
|
119
120
|
onSubmit={onApiKeySubmit || (() => {})}
|
|
120
121
|
placeholder="Enter your key"
|
|
121
122
|
/>
|
|
122
123
|
</div>
|
|
123
124
|
);
|
|
124
125
|
|
|
126
|
+
case 'invalidApiKey':
|
|
127
|
+
return (
|
|
128
|
+
<div style={{
|
|
129
|
+
display: 'flex',
|
|
130
|
+
alignItems: 'center',
|
|
131
|
+
justifyContent: 'center',
|
|
132
|
+
flex: 1,
|
|
133
|
+
padding: '20px'
|
|
134
|
+
}}>
|
|
135
|
+
<ApiKeyInput
|
|
136
|
+
title={title}
|
|
137
|
+
onSubmit={onApiKeySubmit || (() => {})}
|
|
138
|
+
placeholder="Enter your key"
|
|
139
|
+
error="Please check if the key is correct."
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
|
|
125
144
|
case 'error':
|
|
126
145
|
return (
|
|
127
146
|
<div style={{
|
|
@@ -158,7 +177,7 @@ export const Chatbot = forwardRef(function Chatbot(
|
|
|
158
177
|
};
|
|
159
178
|
|
|
160
179
|
// Don't initialize SSE connection when explicitly needing API key or in error state
|
|
161
|
-
if (authState !== 'needApiKey' && authState !== 'error') {
|
|
180
|
+
if (authState !== 'needApiKey' && authState !== 'error' && authState !== 'invalidApiKey') {
|
|
162
181
|
return (
|
|
163
182
|
<AsgardAppInitializationContextProvider
|
|
164
183
|
enabled={enableLoadConfigFromService}
|
|
@@ -31,6 +31,8 @@ export interface AsgardThemeContextValue {
|
|
|
31
31
|
backgroundColor?: CSSProperties['backgroundColor'];
|
|
32
32
|
borderColor?: CSSProperties['borderColor'];
|
|
33
33
|
inactiveColor?: CSSProperties['color'];
|
|
34
|
+
mainColor?: CSSProperties['color'];
|
|
35
|
+
secondaryColor?: CSSProperties['color'];
|
|
34
36
|
primaryComponent?: {
|
|
35
37
|
mainColor?: CSSProperties['color'];
|
|
36
38
|
secondaryColor?: CSSProperties['color'];
|
|
@@ -267,6 +269,9 @@ export function AsgardThemeContextProvider(
|
|
|
267
269
|
chatbot: {
|
|
268
270
|
backgroundColor: themeFromAnnotations.chatbot?.backgroundColor,
|
|
269
271
|
borderColor: themeFromAnnotations.chatbot?.borderColor,
|
|
272
|
+
mainColor: themeFromAnnotations.chatbot?.primaryComponent?.mainColor,
|
|
273
|
+
secondaryColor: themeFromAnnotations.chatbot?.primaryComponent?.secondaryColor,
|
|
274
|
+
|
|
270
275
|
header: {
|
|
271
276
|
style: {
|
|
272
277
|
borderBottomColor: themeFromAnnotations.chatbot?.borderColor,
|
|
@@ -407,6 +412,8 @@ export function AsgardThemeContextProvider(
|
|
|
407
412
|
chatbot: {
|
|
408
413
|
backgroundColor: propsTheme.chatbot?.backgroundColor,
|
|
409
414
|
borderColor: propsTheme.chatbot?.borderColor,
|
|
415
|
+
mainColor: propsTheme.chatbot?.primaryComponent?.mainColor,
|
|
416
|
+
secondaryColor: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
410
417
|
header: {
|
|
411
418
|
style: {
|
|
412
419
|
borderBottomColor: propsTheme.chatbot?.borderColor,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/>
|
|
3
|
+
<line x1="1" y1="1" x2="23" y2="23"/>
|
|
4
|
+
</svg>
|