@asgard-js/react 0.0.38-canary.5 → 0.0.38-canary.7
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/templates/hint-template/hint-template.d.ts.map +1 -1
- package/dist/components/templates/quick-replies/quick-replies.d.ts.map +1 -1
- package/dist/components/templates/text-template/text-template.d.ts.map +1 -1
- package/dist/context/asgard-theme-context.d.ts +6 -1
- package/dist/context/asgard-theme-context.d.ts.map +1 -1
- package/dist/hooks/use-react-markdown-renderer.d.ts.map +1 -1
- package/dist/index.js +14329 -14179
- package/dist/style.css +1 -1
- package/dist/utils/color-utils.d.ts +15 -0
- package/dist/utils/color-utils.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/components/chatbot/chatbot-footer/chatbot-footer.module.scss +1 -0
- package/src/components/templates/hint-template/hint-template.module.scss +4 -0
- package/src/components/templates/hint-template/hint-template.tsx +6 -1
- package/src/components/templates/quick-replies/quick-replies.tsx +5 -2
- package/src/components/templates/text-template/text-template.tsx +6 -2
- package/src/context/asgard-theme-context.tsx +146 -1
- package/src/hooks/use-react-markdown-renderer.tsx +14 -2
- package/src/utils/color-utils.ts +52 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Darkens a color by a given percentage
|
|
3
|
+
* @param color - Hex color string (e.g., "#640000")
|
|
4
|
+
* @param percentage - Percentage to darken (e.g., 0.2 for 20%)
|
|
5
|
+
* @returns Darkened hex color string
|
|
6
|
+
*/
|
|
7
|
+
export declare function darkenColor(color: string, percentage: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Lightens a color by mixing with white
|
|
10
|
+
* @param color - Hex color string (e.g., "#640000")
|
|
11
|
+
* @param percentage - Percentage to lighten (e.g., 0.8 for 20% original, 80% white)
|
|
12
|
+
* @returns Lightened hex color string
|
|
13
|
+
*/
|
|
14
|
+
export declare function lightenColor(color: string, percentage: number): string;
|
|
15
|
+
//# sourceMappingURL=color-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-utils.d.ts","sourceRoot":"","sources":["../../src/utils/color-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAmBrE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAkBtE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asgard-js/react",
|
|
3
|
-
"version": "0.0.38-canary.
|
|
3
|
+
"version": "0.0.38-canary.7",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vitest": "^1.6.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@asgard-js/core": "^0.0.38-canary.
|
|
57
|
+
"@asgard-js/core": "^0.0.38-canary.7",
|
|
58
58
|
"react": "^18.0.0",
|
|
59
59
|
"react-dom": "^18.0.0"
|
|
60
60
|
},
|
|
@@ -65,7 +65,12 @@ export function HintTemplate(props: HintTemplateProps): ReactNode {
|
|
|
65
65
|
style={themeTemplate?.HintMessageTemplate?.style}
|
|
66
66
|
>
|
|
67
67
|
<div className={classes.time}>{formatTime(message.time)}</div>
|
|
68
|
-
|
|
68
|
+
<div
|
|
69
|
+
className={classes.hint_text}
|
|
70
|
+
style={themeTemplate?.HintMessageTemplate?.style}
|
|
71
|
+
>
|
|
72
|
+
{template.text}
|
|
73
|
+
</div>
|
|
69
74
|
</div>
|
|
70
75
|
);
|
|
71
76
|
}
|
|
@@ -11,7 +11,7 @@ interface QuickRepliesProps {
|
|
|
11
11
|
export function QuickReplies(props: QuickRepliesProps): ReactNode {
|
|
12
12
|
const { quickReplies } = props;
|
|
13
13
|
|
|
14
|
-
const { template } = useAsgardThemeContext();
|
|
14
|
+
const { template, botMessage } = useAsgardThemeContext();
|
|
15
15
|
const { sendMessage, isConnecting } = useAsgardContext();
|
|
16
16
|
|
|
17
17
|
const onClick = useCallback(
|
|
@@ -32,7 +32,10 @@ export function QuickReplies(props: QuickRepliesProps): ReactNode {
|
|
|
32
32
|
<button
|
|
33
33
|
key={quickReply.text}
|
|
34
34
|
className={styles.quick_reply}
|
|
35
|
-
style={
|
|
35
|
+
style={{
|
|
36
|
+
...template?.quickReplies?.button?.style,
|
|
37
|
+
backgroundColor: botMessage?.quickReplyBackgroundColor || template?.quickReplies?.button?.style?.backgroundColor,
|
|
38
|
+
}}
|
|
36
39
|
disabled={isConnecting}
|
|
37
40
|
onClick={() => onClick(quickReply.text)}
|
|
38
41
|
>
|
|
@@ -19,6 +19,7 @@ export function TextTemplate(props: TextTemplateProps): ReactNode {
|
|
|
19
19
|
const { avatar } = useAsgardContext();
|
|
20
20
|
|
|
21
21
|
const theme = useAsgardThemeContext();
|
|
22
|
+
const { botMessage } = theme;
|
|
22
23
|
|
|
23
24
|
const { htmlBlocks, lastTypingText } = useMarkdownRenderer(
|
|
24
25
|
(message as ConversationBotMessage)?.message?.text || '',
|
|
@@ -40,9 +41,12 @@ export function TextTemplate(props: TextTemplateProps): ReactNode {
|
|
|
40
41
|
backgroundColor: theme?.botMessage?.backgroundColor,
|
|
41
42
|
};
|
|
42
43
|
default:
|
|
43
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
color: theme?.chatbot?.primaryComponent?.secondaryColor || theme?.template?.TextMessageTemplate?.style?.color,
|
|
46
|
+
backgroundColor: botMessage?.unsentBackgroundColor,
|
|
47
|
+
};
|
|
44
48
|
}
|
|
45
|
-
}, [message, theme]);
|
|
49
|
+
}, [message, theme, botMessage]);
|
|
46
50
|
|
|
47
51
|
if (message.type === 'error') return null;
|
|
48
52
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
useCallback,
|
|
9
9
|
} from 'react';
|
|
10
10
|
import { deepMerge } from '../utils/deep-merge';
|
|
11
|
+
import { darkenColor } from '../utils/color-utils';
|
|
11
12
|
import {
|
|
12
13
|
useAsgardAppInitializationContext,
|
|
13
14
|
Annotations,
|
|
@@ -61,7 +62,12 @@ export interface AsgardThemeContextValue {
|
|
|
61
62
|
};
|
|
62
63
|
}>;
|
|
63
64
|
};
|
|
64
|
-
botMessage: Pick<CSSProperties, 'color' | 'backgroundColor'
|
|
65
|
+
botMessage: Pick<CSSProperties, 'color' | 'backgroundColor'> & {
|
|
66
|
+
carouselButtonBackgroundColor?: CSSProperties['backgroundColor'];
|
|
67
|
+
linkColor?: CSSProperties['color'];
|
|
68
|
+
unsentBackgroundColor?: CSSProperties['backgroundColor'];
|
|
69
|
+
quickReplyBackgroundColor?: CSSProperties['backgroundColor'];
|
|
70
|
+
};
|
|
65
71
|
userMessage: Pick<CSSProperties, 'color' | 'backgroundColor'>;
|
|
66
72
|
template?: Partial<{
|
|
67
73
|
/**
|
|
@@ -316,6 +322,15 @@ export function AsgardThemeContextProvider(
|
|
|
316
322
|
botMessage: {
|
|
317
323
|
backgroundColor: themeFromAnnotations.botMessage?.backgroundColor, // #585858
|
|
318
324
|
color: themeFromAnnotations.botMessage?.color,
|
|
325
|
+
linkColor: themeFromAnnotations.botMessage?.backgroundColor
|
|
326
|
+
? darkenColor(themeFromAnnotations.botMessage.backgroundColor, 0.2)
|
|
327
|
+
: undefined,
|
|
328
|
+
unsentBackgroundColor: themeFromAnnotations.botMessage?.backgroundColor
|
|
329
|
+
? `color-mix(in srgb, ${themeFromAnnotations.botMessage.backgroundColor} 20%, transparent)`
|
|
330
|
+
: undefined,
|
|
331
|
+
quickReplyBackgroundColor: themeFromAnnotations.botMessage?.backgroundColor
|
|
332
|
+
? `color-mix(in srgb, ${themeFromAnnotations.botMessage.backgroundColor} 20%, transparent)`
|
|
333
|
+
: undefined,
|
|
319
334
|
},
|
|
320
335
|
userMessage: {
|
|
321
336
|
backgroundColor: themeFromAnnotations.userMessage?.backgroundColor,
|
|
@@ -382,6 +397,136 @@ export function AsgardThemeContextProvider(
|
|
|
382
397
|
},
|
|
383
398
|
});
|
|
384
399
|
|
|
400
|
+
// Handle theme prop that contains backend format (like themeFromAnnotations)
|
|
401
|
+
const propsTheme = theme as any; // Cast to handle backend format
|
|
402
|
+
const propsHasBackendFormat = propsTheme.chatbot?.primaryComponent || propsTheme.chatbot?.backgroundColor || propsTheme.botMessage || propsTheme.userMessage;
|
|
403
|
+
|
|
404
|
+
if (propsHasBackendFormat) {
|
|
405
|
+
// Apply same transformation logic as tempTheme for props theme
|
|
406
|
+
const transformedPropsTheme = deepMerge(defaultAsgardThemeContextValue as unknown as Record<string, unknown>, {
|
|
407
|
+
chatbot: {
|
|
408
|
+
backgroundColor: propsTheme.chatbot?.backgroundColor,
|
|
409
|
+
borderColor: propsTheme.chatbot?.borderColor,
|
|
410
|
+
header: {
|
|
411
|
+
style: {
|
|
412
|
+
borderBottomColor: propsTheme.chatbot?.borderColor,
|
|
413
|
+
},
|
|
414
|
+
title: {
|
|
415
|
+
style: {
|
|
416
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
actionButton: {
|
|
420
|
+
style: {
|
|
421
|
+
color: propsTheme.chatbot?.inactiveColor,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
body: {
|
|
426
|
+
style: {
|
|
427
|
+
// Time/timestamp text color
|
|
428
|
+
color: propsTheme.chatbot?.inactiveColor,
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
footer: {
|
|
432
|
+
style: {
|
|
433
|
+
borderTopColor: propsTheme.chatbot?.borderColor,
|
|
434
|
+
},
|
|
435
|
+
textArea: {
|
|
436
|
+
style: {
|
|
437
|
+
color: propsTheme.chatbot?.inactiveColor,
|
|
438
|
+
backgroundColor: propsTheme.chatbot?.backgroundColor,
|
|
439
|
+
},
|
|
440
|
+
'::placeholder': {
|
|
441
|
+
color: propsTheme.chatbot?.inactiveColor,
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
submitButton: {
|
|
445
|
+
style: {
|
|
446
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
speechInputButton: {
|
|
450
|
+
style: {
|
|
451
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
botMessage: {
|
|
457
|
+
backgroundColor: propsTheme.botMessage?.backgroundColor,
|
|
458
|
+
color: propsTheme.botMessage?.color,
|
|
459
|
+
linkColor: propsTheme.botMessage?.backgroundColor
|
|
460
|
+
? darkenColor(propsTheme.botMessage.backgroundColor, 0.2)
|
|
461
|
+
: undefined,
|
|
462
|
+
unsentBackgroundColor: propsTheme.botMessage?.backgroundColor
|
|
463
|
+
? `color-mix(in srgb, ${propsTheme.botMessage.backgroundColor} 20%, transparent)`
|
|
464
|
+
: undefined,
|
|
465
|
+
quickReplyBackgroundColor: propsTheme.botMessage?.backgroundColor
|
|
466
|
+
? `color-mix(in srgb, ${propsTheme.botMessage.backgroundColor} 20%, transparent)`
|
|
467
|
+
: undefined,
|
|
468
|
+
},
|
|
469
|
+
userMessage: {
|
|
470
|
+
backgroundColor: propsTheme.userMessage?.backgroundColor,
|
|
471
|
+
color: propsTheme.userMessage?.color,
|
|
472
|
+
},
|
|
473
|
+
template: {
|
|
474
|
+
quickReplies: {
|
|
475
|
+
button: {
|
|
476
|
+
style: {
|
|
477
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
478
|
+
borderColor: propsTheme.chatbot?.borderColor,
|
|
479
|
+
backgroundColor: propsTheme.botMessage?.backgroundColor
|
|
480
|
+
? `${propsTheme.botMessage.backgroundColor}33`
|
|
481
|
+
: undefined,
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
time: {
|
|
486
|
+
style: {
|
|
487
|
+
color: propsTheme.chatbot?.inactiveColor,
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
TextMessageTemplate: {
|
|
491
|
+
style: {
|
|
492
|
+
// For unset messages
|
|
493
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
HintMessageTemplate: {
|
|
497
|
+
style: {
|
|
498
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
ButtonMessageTemplate: {
|
|
502
|
+
button: {
|
|
503
|
+
style: {
|
|
504
|
+
borderColor: propsTheme.chatbot?.borderColor,
|
|
505
|
+
backgroundColor: propsTheme.chatbot?.primaryComponent?.mainColor,
|
|
506
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
CarouselMessageTemplate: {
|
|
511
|
+
card: {
|
|
512
|
+
style: {
|
|
513
|
+
backgroundColor: propsTheme.botMessage?.carouselButtonBackgroundColor,
|
|
514
|
+
},
|
|
515
|
+
button: {
|
|
516
|
+
style: {
|
|
517
|
+
borderColor: propsTheme.chatbot?.borderColor,
|
|
518
|
+
backgroundColor: propsTheme.chatbot?.primaryComponent?.mainColor,
|
|
519
|
+
color: propsTheme.chatbot?.primaryComponent?.secondaryColor,
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
return deepMerge(tempTheme, transformedPropsTheme);
|
|
528
|
+
}
|
|
529
|
+
|
|
385
530
|
return deepMerge(tempTheme, theme);
|
|
386
531
|
},
|
|
387
532
|
[theme, annotations?.embedConfig?.theme]
|
|
@@ -14,6 +14,7 @@ import rehypeKatex from 'rehype-katex';
|
|
|
14
14
|
import 'katex/dist/katex.min.css';
|
|
15
15
|
import classes from '../components/templates/text-template/text-template.module.scss';
|
|
16
16
|
import { useAsgardTemplateContext } from '../context/asgard-template-context';
|
|
17
|
+
import { useAsgardThemeContext } from '../context/asgard-theme-context';
|
|
17
18
|
import { safeWindowOpen } from '../utils/uri-validation';
|
|
18
19
|
|
|
19
20
|
interface MarkdownRenderResult {
|
|
@@ -98,9 +99,10 @@ const CodeRenderer = ({ children, className, ...props }: React.ComponentProps<'c
|
|
|
98
99
|
);
|
|
99
100
|
};
|
|
100
101
|
|
|
101
|
-
// Custom link renderer to integrate defaultLinkTarget prop
|
|
102
|
+
// Custom link renderer to integrate defaultLinkTarget prop and theme colors
|
|
102
103
|
const LinkRenderer = ({ children, href, ...props }: React.ComponentProps<'a'>): ReactNode => {
|
|
103
104
|
const { defaultLinkTarget } = useAsgardTemplateContext();
|
|
105
|
+
const { botMessage } = useAsgardThemeContext();
|
|
104
106
|
|
|
105
107
|
const handleClick = useCallback(
|
|
106
108
|
(e: React.MouseEvent) => {
|
|
@@ -113,7 +115,17 @@ const LinkRenderer = ({ children, href, ...props }: React.ComponentProps<'a'>):
|
|
|
113
115
|
);
|
|
114
116
|
|
|
115
117
|
return (
|
|
116
|
-
<a
|
|
118
|
+
<a
|
|
119
|
+
href={href}
|
|
120
|
+
onClick={handleClick}
|
|
121
|
+
rel="noopener noreferrer"
|
|
122
|
+
style={{
|
|
123
|
+
color: botMessage?.linkColor || '#0066cc',
|
|
124
|
+
textDecoration: 'underline',
|
|
125
|
+
...props.style
|
|
126
|
+
}}
|
|
127
|
+
{...props}
|
|
128
|
+
>
|
|
117
129
|
{children}
|
|
118
130
|
</a>
|
|
119
131
|
);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Darkens a color by a given percentage
|
|
3
|
+
* @param color - Hex color string (e.g., "#640000")
|
|
4
|
+
* @param percentage - Percentage to darken (e.g., 0.2 for 20%)
|
|
5
|
+
* @returns Darkened hex color string
|
|
6
|
+
*/
|
|
7
|
+
export function darkenColor(color: string, percentage: number): string {
|
|
8
|
+
// Remove # if present
|
|
9
|
+
const hex = color.replace('#', '');
|
|
10
|
+
|
|
11
|
+
// Parse RGB values
|
|
12
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
13
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
14
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
15
|
+
|
|
16
|
+
// Apply darkening (multiply by 1 - percentage)
|
|
17
|
+
const factor = 1 - percentage;
|
|
18
|
+
const newR = Math.round(r * factor);
|
|
19
|
+
const newG = Math.round(g * factor);
|
|
20
|
+
const newB = Math.round(b * factor);
|
|
21
|
+
|
|
22
|
+
// Convert back to hex
|
|
23
|
+
const toHex = (n: number): string => n.toString(16).padStart(2, '0');
|
|
24
|
+
|
|
25
|
+
return `#${toHex(newR)}${toHex(newG)}${toHex(newB)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Lightens a color by mixing with white
|
|
30
|
+
* @param color - Hex color string (e.g., "#640000")
|
|
31
|
+
* @param percentage - Percentage to lighten (e.g., 0.8 for 20% original, 80% white)
|
|
32
|
+
* @returns Lightened hex color string
|
|
33
|
+
*/
|
|
34
|
+
export function lightenColor(color: string, percentage: number): string {
|
|
35
|
+
// Remove # if present
|
|
36
|
+
const hex = color.replace('#', '');
|
|
37
|
+
|
|
38
|
+
// Parse RGB values
|
|
39
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
40
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
41
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
42
|
+
|
|
43
|
+
// Mix with white: original + (255 - original) * percentage
|
|
44
|
+
const newR = Math.round(r + (255 - r) * percentage);
|
|
45
|
+
const newG = Math.round(g + (255 - g) * percentage);
|
|
46
|
+
const newB = Math.round(b + (255 - b) * percentage);
|
|
47
|
+
|
|
48
|
+
// Convert back to hex
|
|
49
|
+
const toHex = (n: number): string => n.toString(16).padStart(2, '0');
|
|
50
|
+
|
|
51
|
+
return `#${toHex(newR)}${toHex(newG)}${toHex(newB)}`;
|
|
52
|
+
}
|