@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,26 +0,0 @@
1
- import { ReactNode } from 'react';
2
- import ProfileSvg from '../../icons/profile.svg?react';
3
-
4
- interface ProfileIconProps {
5
- avatar?: string;
6
- }
7
-
8
- export function ProfileIcon(props: ProfileIconProps): ReactNode {
9
- const { avatar } = props;
10
-
11
- if (avatar) {
12
- return (
13
- <img
14
- src={avatar}
15
- alt="avatar"
16
- style={{
17
- width: 33,
18
- height: 32,
19
- borderRadius: '50%',
20
- }}
21
- />
22
- );
23
- }
24
-
25
- return <ProfileSvg />;
26
- }
@@ -1,2 +0,0 @@
1
- export * from './chatbot/chatbot';
2
- export * from './templates';
@@ -1,6 +0,0 @@
1
- .bot_avatar {
2
- flex: 0 0 auto;
3
- width: 24px;
4
- height: 24px;
5
- border-radius: 50%;
6
- }
@@ -1,28 +0,0 @@
1
- import { memo, ReactNode } from 'react';
2
- import styles from './avatar.module.scss';
3
- import BotSvg from '../../../icons/bot.svg?react';
4
- import clsx from 'clsx';
5
-
6
- interface AvatarProps {
7
- avatar?: string;
8
- }
9
-
10
- export const Avatar = memo((props: AvatarProps): ReactNode => {
11
- const { avatar } = props;
12
-
13
- if (avatar) {
14
- return (
15
- <img
16
- src={avatar}
17
- alt="Bot Avatar"
18
- className={clsx('asgard-avatar', styles.bot_avatar)}
19
- />
20
- );
21
- }
22
-
23
- return (
24
- <div className={clsx('asgard-avatar', styles.bot_avatar)}>
25
- <BotSvg />
26
- </div>
27
- );
28
- });
@@ -1 +0,0 @@
1
- export * from './avatar';
@@ -1,45 +0,0 @@
1
- import { ButtonMessageTemplate, ConversationBotMessage } from '@asgard-js/core';
2
- import { ReactNode } from 'react';
3
- import { TemplateBox, TemplateBoxContent } from '../template-box';
4
- import { Avatar } from '../avatar';
5
- import { Card } from './card';
6
- import { useAsgardContext } from '../../../context/asgard-service-context';
7
- import { useAsgardThemeContext } from '../../../context/asgard-theme-context';
8
-
9
- interface ButtonTemplateProps {
10
- message: ConversationBotMessage;
11
- }
12
-
13
- export function ButtonTemplate(props: ButtonTemplateProps): ReactNode {
14
- const { message } = props;
15
-
16
- const { template: themeTemplate } = useAsgardThemeContext();
17
-
18
- const { avatar } = useAsgardContext();
19
-
20
- const template = message.message.template as ButtonMessageTemplate;
21
-
22
- return (
23
- <TemplateBox
24
- className="asgard-button-template"
25
- type="bot"
26
- direction="horizontal"
27
- style={themeTemplate?.ButtonMessageTemplate?.style}
28
- >
29
- <Avatar avatar={avatar} />
30
- <TemplateBoxContent
31
- time={message.time}
32
- quickReplies={template?.quickReplies}
33
- >
34
- <Card
35
- template={template}
36
- customStyle={{
37
- button: {
38
- style: themeTemplate?.ButtonMessageTemplate?.button?.style ?? {},
39
- },
40
- }}
41
- />
42
- </TemplateBoxContent>
43
- </TemplateBox>
44
- );
45
- }
@@ -1,58 +0,0 @@
1
- .card_root {
2
- width: 255px;
3
- height: 368px;
4
- max-height: 380px;
5
- border-radius: 8px;
6
- background: rgba(51, 51, 51, 1);
7
- overflow: hidden;
8
- display: grid;
9
- grid-template-rows: max-content auto;
10
- }
11
-
12
- .card_content {
13
- display: grid;
14
- grid-template-rows: 1.5em auto max-content;
15
- gap: var(--asg-spacing-2);
16
- padding: 12px;
17
- line-height: 1.5em;
18
- }
19
-
20
- .card_title {
21
- color: white;
22
- margin: 0;
23
- font-size: 15px;
24
- }
25
-
26
- .card_description {
27
- color: rgba(140, 140, 140, 1);
28
- font-size: 13px;
29
- font-weight: 400;
30
- max-height: 4.5em;
31
- overflow: hidden;
32
- text-overflow: ellipsis;
33
- display: -webkit-box;
34
- line-clamp: 3;
35
- -webkit-line-clamp: 3;
36
- -webkit-box-orient: vertical;
37
- text-underline-position: from-font;
38
- text-decoration-skip-ink: none;
39
- }
40
-
41
- .card_actions {
42
- display: flex;
43
- flex-direction: column;
44
- gap: 8px;
45
-
46
- > button {
47
- width: 100%;
48
- height: 32px;
49
- line-height: 32px;
50
- text-align: center;
51
- border: none;
52
- border-radius: 4px;
53
- background: rgba(71, 103, 235, 1);
54
- color: white;
55
- font-size: 15px;
56
- cursor: pointer;
57
- }
58
- }
@@ -1,213 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { render, screen, fireEvent } from '@testing-library/react';
3
- import { Card } from './card';
4
- import { MessageTemplateType } from '@asgard-js/core';
5
- import { useAsgardContext } from '../../../context/asgard-service-context';
6
- import { useAsgardTemplateContext } from '../../../context/asgard-template-context';
7
- import * as uriValidation from '../../../utils/uri-validation';
8
-
9
- // Mock the contexts
10
- vi.mock('../../../context/asgard-service-context');
11
- vi.mock('../../../context/asgard-template-context');
12
-
13
- // Mock the URI validation utility
14
- vi.mock('../../../utils/uri-validation');
15
-
16
- const mockUseAsgardContext = vi.mocked(useAsgardContext);
17
- const mockUseAsgardTemplateContext = vi.mocked(useAsgardTemplateContext);
18
- const mockSafeWindowOpen = vi.mocked(uriValidation.safeWindowOpen);
19
-
20
- describe('Card Component - Security Tests', () => {
21
- const mockSendMessage = vi.fn();
22
- const mockOnTemplateBtnClick = vi.fn();
23
- const defaultLinkTarget = '_blank';
24
-
25
- // Define malicious URI as variable to avoid ESLint script URL warning
26
- // eslint-disable-next-line no-script-url
27
- const maliciousJsUri = 'javascript:alert("xss")';
28
-
29
- const baseTemplate = {
30
- type: MessageTemplateType.BUTTON,
31
- title: 'Test Card',
32
- text: 'Test description',
33
- thumbnailImageUrl: 'https://example.com/image.jpg',
34
- imageAspectRatio: 'rectangle' as const,
35
- imageSize: 'cover' as const,
36
- imageBackgroundColor: '#ffffff',
37
- defaultAction: {
38
- type: 'message' as const,
39
- text: 'Default action',
40
- },
41
- quickReplies: [],
42
- buttons: [
43
- {
44
- label: 'Safe Link',
45
- action: {
46
- type: 'uri' as const,
47
- uri: 'https://example.com',
48
- },
49
- },
50
- {
51
- label: 'Malicious Link',
52
- action: {
53
- type: 'uri' as const,
54
- uri: maliciousJsUri,
55
- },
56
- },
57
- ],
58
- };
59
-
60
- beforeEach(() => {
61
- mockUseAsgardContext.mockReturnValue({
62
- sendMessage: mockSendMessage,
63
- client: null,
64
- isOpen: false,
65
- isResetting: false,
66
- isConnecting: false,
67
- conversation: null,
68
- resetChannel: vi.fn(),
69
- closeChannel: vi.fn(),
70
- avatar: null,
71
- });
72
-
73
- mockUseAsgardTemplateContext.mockReturnValue({
74
- onTemplateBtnClick: mockOnTemplateBtnClick,
75
- defaultLinkTarget,
76
- onErrorClick: undefined,
77
- errorMessageRenderer: undefined,
78
- });
79
-
80
- mockSafeWindowOpen.mockReturnValue(null);
81
- });
82
-
83
- afterEach(() => {
84
- vi.clearAllMocks();
85
- });
86
-
87
- describe('URI security validation', () => {
88
- it('should call safeWindowOpen for URI actions instead of window.open directly', () => {
89
- render(<Card template={baseTemplate} />);
90
-
91
- const safeButton = screen.getByText('Safe Link');
92
- fireEvent.click(safeButton);
93
-
94
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
95
- 'https://example.com',
96
- '_blank'
97
- );
98
- });
99
-
100
- it('should call safeWindowOpen for malicious URIs (letting validation utility handle security)', () => {
101
- render(<Card template={baseTemplate} />);
102
-
103
- const maliciousButton = screen.getByText('Malicious Link');
104
- fireEvent.click(maliciousButton);
105
-
106
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
107
- maliciousJsUri,
108
- '_blank'
109
- );
110
- });
111
-
112
- it('should use action target if provided', () => {
113
- const templateWithTarget = {
114
- ...baseTemplate,
115
- buttons: [
116
- {
117
- label: 'Link with Target',
118
- action: {
119
- type: 'uri' as const,
120
- uri: 'https://example.com',
121
- target: '_self' as const,
122
- },
123
- },
124
- ],
125
- };
126
-
127
- render(<Card template={templateWithTarget} />);
128
-
129
- const button = screen.getByText('Link with Target');
130
- fireEvent.click(button);
131
-
132
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
133
- 'https://example.com',
134
- '_self'
135
- );
136
- });
137
-
138
- it('should fallback to defaultLinkTarget when no action target', () => {
139
- mockUseAsgardTemplateContext.mockReturnValue({
140
- onTemplateBtnClick: mockOnTemplateBtnClick,
141
- defaultLinkTarget: '_parent',
142
- });
143
-
144
- render(<Card template={baseTemplate} />);
145
-
146
- const safeButton = screen.getByText('Safe Link');
147
- fireEvent.click(safeButton);
148
-
149
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
150
- 'https://example.com',
151
- '_parent'
152
- );
153
- });
154
-
155
- it('should fallback to _blank when no action target or defaultLinkTarget', () => {
156
- mockUseAsgardTemplateContext.mockReturnValue({
157
- onTemplateBtnClick: mockOnTemplateBtnClick,
158
- defaultLinkTarget: undefined,
159
- });
160
-
161
- render(<Card template={baseTemplate} />);
162
-
163
- const safeButton = screen.getByText('Safe Link');
164
- fireEvent.click(safeButton);
165
-
166
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
167
- 'https://example.com',
168
- '_blank'
169
- );
170
- });
171
-
172
- it('should handle uppercase URI action type', () => {
173
- const templateWithUppercase = {
174
- ...baseTemplate,
175
- buttons: [
176
- {
177
- label: 'Uppercase URI',
178
- action: {
179
- type: 'URI' as const,
180
- uri: 'https://example.com',
181
- },
182
- },
183
- ],
184
- };
185
-
186
- render(<Card template={templateWithUppercase} />);
187
-
188
- const button = screen.getByText('Uppercase URI');
189
- fireEvent.click(button);
190
-
191
- expect(mockSafeWindowOpen).toHaveBeenCalledWith(
192
- 'https://example.com',
193
- '_blank'
194
- );
195
- });
196
- });
197
-
198
- describe('basic rendering', () => {
199
- it('should render card with title and description', () => {
200
- render(<Card template={baseTemplate} />);
201
-
202
- expect(screen.getByText('Test Card')).toBeDefined();
203
- expect(screen.getByText('Test description')).toBeDefined();
204
- });
205
-
206
- it('should render buttons', () => {
207
- render(<Card template={baseTemplate} />);
208
-
209
- expect(screen.getByText('Safe Link')).toBeDefined();
210
- expect(screen.getByText('Malicious Link')).toBeDefined();
211
- });
212
- });
213
- });
@@ -1,123 +0,0 @@
1
- import {
2
- MouseEventHandler,
3
- ReactNode,
4
- useCallback,
5
- useMemo,
6
- CSSProperties,
7
- } from 'react';
8
- import styles from './card.module.scss';
9
- import {
10
- ButtonAction,
11
- ButtonMessageTemplate,
12
- CarouselMessageTemplate,
13
- } from '@asgard-js/core';
14
- import { useAsgardContext } from '../../../context/asgard-service-context';
15
- import { useAsgardTemplateContext } from '../../../context/asgard-template-context';
16
- import { safeWindowOpen } from '../../../utils/uri-validation';
17
- import clsx from 'clsx';
18
-
19
- interface CardProps {
20
- template: ButtonMessageTemplate | CarouselMessageTemplate['columns'][number];
21
- customStyle?: {
22
- style?: CSSProperties;
23
- button?: {
24
- style?: CSSProperties;
25
- };
26
- };
27
- }
28
-
29
- export function Card(props: CardProps): ReactNode {
30
- const { template, customStyle } = props;
31
-
32
- const { sendMessage } = useAsgardContext();
33
- const { onTemplateBtnClick, defaultLinkTarget } = useAsgardTemplateContext();
34
-
35
- const src = useMemo(() => {
36
- return (
37
- template?.thumbnailImageUrl
38
- ?.replace(/^http:/, '')
39
- .replace(/^https:/, '') ||
40
- 'https://via.assets.so/img.jpg?w=200&h=270&tc=white&bg=#eeeeee'
41
- );
42
- }, [template]);
43
-
44
- const aspectRatio = useMemo(() => {
45
- switch (template?.imageAspectRatio) {
46
- case 'square':
47
- return '1 / 1';
48
- case 'rectangle':
49
- default:
50
- return '1.51 / 1';
51
- }
52
- }, [template]);
53
-
54
- const handleClick = useCallback(
55
- (action: ButtonAction): MouseEventHandler<HTMLButtonElement> => {
56
- return function clickHandler() {
57
- switch (action.type) {
58
- case 'message':
59
- case 'MESSAGE':
60
- sendMessage?.({ text: action.text });
61
-
62
- return;
63
- case 'uri':
64
- case 'URI':
65
- safeWindowOpen(
66
- action.uri,
67
- action.target || defaultLinkTarget || '_blank'
68
- );
69
-
70
- return;
71
- case 'emit':
72
- case 'EMIT':
73
- onTemplateBtnClick?.(action.payload, {
74
- sse: {
75
- sendMessage: (payload) => {
76
- sendMessage?.(payload);
77
- },
78
- },
79
- });
80
-
81
- return;
82
- }
83
- };
84
- },
85
- [sendMessage, onTemplateBtnClick, defaultLinkTarget]
86
- );
87
-
88
- return (
89
- <div
90
- className={clsx('asgard-card', styles.card_root)}
91
- style={customStyle?.style}
92
- >
93
- {template?.thumbnailImageUrl && (
94
- <img
95
- alt={template?.title}
96
- src={src}
97
- style={{
98
- display: 'block',
99
- width: '100%',
100
- maxHeight: '170px',
101
- objectFit: template?.imageSize,
102
- aspectRatio,
103
- }}
104
- />
105
- )}
106
- <div className={styles.card_content}>
107
- <h5 className={styles.card_title}>{template?.title}</h5>
108
- <div className={styles.card_description}>{template?.text}</div>
109
- <div className={styles.card_actions}>
110
- {template?.buttons?.map((btn: { label: string; action: ButtonAction }, index: number) => (
111
- <button
112
- key={index}
113
- onClick={handleClick(btn.action)}
114
- style={customStyle?.button?.style}
115
- >
116
- {btn.label}
117
- </button>
118
- ))}
119
- </div>
120
- </div>
121
- </div>
122
- );
123
- }
@@ -1 +0,0 @@
1
- export * from './button-template';
@@ -1,15 +0,0 @@
1
- .carousel_root {
2
- width: 100%;
3
- display: flex;
4
- flex-wrap: nowrap;
5
- overflow-x: scroll;
6
- gap: 8px;
7
-
8
- > div {
9
- flex: 0 0 auto;
10
- }
11
- }
12
-
13
- .carousel_time {
14
- justify-content: flex-end;
15
- }
@@ -1,49 +0,0 @@
1
- import { ReactNode } from 'react';
2
- import { TemplateBox, TemplateBoxContent } from '../template-box';
3
- import { Avatar } from '../avatar';
4
- import styles from './carousel-template.module.scss';
5
- import { Card } from '../button-template/card';
6
- import {
7
- CarouselMessageTemplate,
8
- ConversationBotMessage,
9
- ButtonMessageTemplate,
10
- } from '@asgard-js/core';
11
- import { Time } from '../time';
12
- import { useAsgardContext } from '../../../context/asgard-service-context';
13
- import { useAsgardThemeContext } from '../../../context/asgard-theme-context';
14
-
15
- interface CarouselTemplateProps {
16
- message: ConversationBotMessage;
17
- }
18
-
19
- export function CarouselTemplate(props: CarouselTemplateProps): ReactNode {
20
- const { message } = props;
21
-
22
- const { template: themeTemplate } = useAsgardThemeContext();
23
- const { avatar } = useAsgardContext();
24
-
25
- const template = message.message.template as CarouselMessageTemplate;
26
-
27
- return (
28
- <TemplateBox
29
- className="asgard-carousel-template"
30
- type="bot"
31
- direction="vertical"
32
- style={themeTemplate?.CarouselMessageTemplate?.style}
33
- >
34
- <Avatar avatar={avatar} />
35
- <TemplateBoxContent quickReplies={template.quickReplies}>
36
- <div className={styles.carousel_root}>
37
- {template.columns?.map((column: Omit<ButtonMessageTemplate, 'type' | 'quickReplies'>, index: number) => (
38
- <Card
39
- key={index}
40
- template={column}
41
- customStyle={themeTemplate?.CarouselMessageTemplate?.card}
42
- />
43
- ))}
44
- </div>
45
- </TemplateBoxContent>
46
- <Time className={styles.carousel_time} time={message.time} />
47
- </TemplateBox>
48
- );
49
- }
@@ -1 +0,0 @@
1
- export * from './carousel-template';
@@ -1,52 +0,0 @@
1
- .text {
2
- display: inline-block;
3
- padding: 8px 12px;
4
- border-radius: 8px;
5
- color: white;
6
- word-break: break-all;
7
-
8
- > span {
9
- word-break: break-all;
10
- }
11
-
12
- .md_container {
13
- display: inline-block;
14
-
15
- p {
16
- margin: 0;
17
- }
18
- }
19
- }
20
-
21
- .text--user {
22
- max-width: 75%;
23
- background: #4767eb;
24
- border-top-right-radius: 0;
25
- }
26
-
27
- .text--bot {
28
- max-width: 70%;
29
- background: #585858;
30
- border-top-left-radius: 0;
31
- }
32
-
33
- .chart_time {
34
- justify-content: flex-end;
35
- }
36
-
37
- .quick_replies_box {
38
- display: flex;
39
- flex-wrap: wrap;
40
- gap: 8px;
41
- }
42
-
43
- .quick_reply {
44
- font: inherit;
45
- font-size: 13px;
46
- padding: 4px 8px;
47
- border-radius: 8px;
48
- border: 1px solid #434343;
49
- background: rgba(88, 88, 88, 0.2);
50
- color: white;
51
- cursor: pointer;
52
- }