@botpress/webchat 0.5.1 → 1.0.0

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 (295) hide show
  1. package/dist/App.d.ts +10 -0
  2. package/dist/Utils/colors.d.ts +18 -0
  3. package/dist/Utils/eventEmitter.d.ts +12 -0
  4. package/dist/Utils/index.d.ts +2 -0
  5. package/dist/client/MessagingClient.d.ts +27 -0
  6. package/dist/client/adapters/Audio.d.ts +19 -0
  7. package/dist/client/adapters/Card.d.ts +188 -0
  8. package/dist/client/adapters/Carousel.d.ts +147 -0
  9. package/dist/client/adapters/Choice.d.ts +45 -0
  10. package/dist/client/adapters/Dropdown.d.ts +46 -0
  11. package/dist/client/adapters/File.d.ts +19 -0
  12. package/dist/client/adapters/Image.d.ts +19 -0
  13. package/dist/client/adapters/Location.d.ts +27 -0
  14. package/dist/client/adapters/Message.d.ts +433 -0
  15. package/dist/client/adapters/Text.d.ts +20 -0
  16. package/dist/client/adapters/Utils.d.ts +5 -0
  17. package/dist/client/adapters/Video.d.ts +19 -0
  18. package/dist/client/adapters/Voice.d.ts +15 -0
  19. package/dist/client/adapters/index.d.ts +12 -0
  20. package/dist/client/index.d.ts +2 -0
  21. package/dist/components/Avatar.d.ts +6 -0
  22. package/dist/components/Block.d.ts +4 -0
  23. package/dist/components/Composer.d.ts +12 -14
  24. package/dist/components/Container.d.ts +2 -12
  25. package/dist/components/Header.d.ts +36 -26
  26. package/dist/components/LoadingIndicator.d.ts +2 -0
  27. package/dist/components/Message.d.ts +7 -0
  28. package/dist/components/MessageList.d.ts +2 -0
  29. package/dist/components/Modal.d.ts +17 -0
  30. package/dist/components/RestartConversation.d.ts +5 -0
  31. package/dist/components/Webchat.d.ts +6 -0
  32. package/dist/components/dev-tools/DevTools.d.ts +1 -0
  33. package/dist/components/dev-tools/configuration.d.ts +2 -0
  34. package/dist/components/dev-tools/helpers.d.ts +5 -0
  35. package/dist/components/index.d.ts +12 -0
  36. package/dist/components/renderers/Audio.d.ts +3 -0
  37. package/dist/components/renderers/Bubble.d.ts +5 -0
  38. package/dist/components/renderers/Button.d.ts +4 -0
  39. package/dist/components/renderers/Carousel.d.ts +3 -0
  40. package/dist/components/renderers/Column.d.ts +5 -0
  41. package/dist/components/renderers/Dropdown.d.ts +5 -0
  42. package/dist/components/renderers/File.d.ts +3 -0
  43. package/dist/components/renderers/Image.d.ts +3 -0
  44. package/dist/components/renderers/Location.d.ts +3 -0
  45. package/dist/components/renderers/Row.d.ts +5 -0
  46. package/dist/components/renderers/Text.d.ts +4 -0
  47. package/dist/components/renderers/Video.d.ts +3 -0
  48. package/dist/components/renderers/index.d.ts +2 -0
  49. package/dist/contexts/ComposerContext.d.ts +8 -0
  50. package/dist/contexts/MessageContext.d.ts +8 -0
  51. package/dist/contexts/ModalContext.d.ts +14 -0
  52. package/dist/contexts/WebchatContext.d.ts +56 -0
  53. package/dist/contexts/index.d.ts +4 -0
  54. package/dist/hooks/index.d.ts +3 -0
  55. package/dist/hooks/useImageSize.d.ts +2 -0
  56. package/dist/hooks/useRefresh.d.ts +10 -0
  57. package/dist/hooks/useWebchatStore.d.ts +30 -0
  58. package/dist/index.d.ts +3 -17
  59. package/dist/index.js +43569 -48
  60. package/dist/index.umd.cjs +702 -0
  61. package/dist/main.d.ts +11 -13
  62. package/dist/providers/ModalProvider.d.ts +8 -0
  63. package/dist/providers/WebchatProvider.d.ts +13 -0
  64. package/dist/providers/index.d.ts +2 -0
  65. package/dist/schemas/index.d.ts +1 -0
  66. package/dist/schemas/theme.d.ts +3371 -0
  67. package/dist/services/clipboard.d.ts +1 -0
  68. package/dist/services/images.d.ts +2 -0
  69. package/dist/services/index.d.ts +3 -0
  70. package/dist/services/toast.d.ts +17 -0
  71. package/dist/themes/dawn.d.ts +2 -0
  72. package/dist/themes/duskTheme.d.ts +2 -0
  73. package/dist/themes/eggplant.d.ts +2 -0
  74. package/dist/themes/galaxy.d.ts +2 -0
  75. package/dist/themes/index.d.ts +6 -0
  76. package/dist/themes/midnight.d.ts +2 -0
  77. package/dist/themes/prism.d.ts +2 -0
  78. package/dist/twind.config.d.ts +9 -0
  79. package/dist/types/block-type.d.ts +93 -0
  80. package/dist/types/image.d.ts +11 -0
  81. package/dist/types/index.d.ts +2 -0
  82. package/dist/vite.svg +1 -0
  83. package/index.html +18 -0
  84. package/package.json +60 -49
  85. package/public/vite.svg +1 -0
  86. package/src/App.tsx +41 -0
  87. package/src/Utils/colors.ts +45 -0
  88. package/src/Utils/eventEmitter.ts +31 -0
  89. package/src/Utils/index.ts +2 -0
  90. package/src/assets/check-circle-bold.svg +5 -0
  91. package/src/assets/chevron-up.svg +3 -0
  92. package/src/assets/file-05.svg +6 -0
  93. package/src/assets/globe-02.svg +6 -0
  94. package/src/assets/help-circle.svg +3 -0
  95. package/src/assets/info-circle.svg +3 -0
  96. package/src/assets/lock-01.svg +4 -0
  97. package/src/assets/mail-01.svg +6 -0
  98. package/src/assets/minus-circle.svg +3 -0
  99. package/src/assets/phone.svg +6 -0
  100. package/src/assets/send-03.svg +4 -0
  101. package/src/assets/share-04.svg +5 -0
  102. package/src/assets/slash-circle-01.svg +3 -0
  103. package/src/assets/x-circle-bold.svg +5 -0
  104. package/src/assets/x-close.svg +3 -0
  105. package/src/assets/x.svg +3 -0
  106. package/src/client/MessagingClient.ts +87 -0
  107. package/src/client/adapters/Audio.ts +10 -0
  108. package/src/client/adapters/Card.ts +104 -0
  109. package/src/client/adapters/Carousel.ts +11 -0
  110. package/src/client/adapters/Choice.ts +48 -0
  111. package/src/client/adapters/Dropdown.ts +39 -0
  112. package/src/client/adapters/File.ts +10 -0
  113. package/src/client/adapters/Image.ts +10 -0
  114. package/src/client/adapters/Location.ts +18 -0
  115. package/src/client/adapters/Message.ts +26 -0
  116. package/src/client/adapters/Text.ts +11 -0
  117. package/src/client/adapters/Utils.ts +11 -0
  118. package/src/client/adapters/Video.ts +10 -0
  119. package/src/client/adapters/Voice.ts +9 -0
  120. package/src/client/adapters/index.ts +12 -0
  121. package/src/client/index.ts +2 -0
  122. package/src/components/Avatar.tsx +22 -0
  123. package/src/components/Block.tsx +17 -0
  124. package/src/components/Composer.tsx +115 -0
  125. package/src/components/Container.tsx +17 -0
  126. package/src/components/Header.tsx +141 -0
  127. package/src/components/LoadingIndicator.tsx +15 -0
  128. package/src/components/Message.tsx +52 -0
  129. package/src/components/MessageList.tsx +75 -0
  130. package/src/components/Modal.tsx +49 -0
  131. package/src/components/RestartConversation.tsx +52 -0
  132. package/src/components/Webchat.tsx +68 -0
  133. package/src/components/dev-tools/DevTools.tsx +496 -0
  134. package/src/components/dev-tools/configuration.tsx +27 -0
  135. package/src/components/dev-tools/helpers.ts +21 -0
  136. package/src/components/index.ts +12 -0
  137. package/src/components/renderers/Audio.tsx +11 -0
  138. package/src/components/renderers/Bubble.tsx +12 -0
  139. package/src/components/renderers/Button.tsx +59 -0
  140. package/src/components/renderers/Carousel.tsx +51 -0
  141. package/src/components/renderers/Column.tsx +22 -0
  142. package/src/components/renderers/Dropdown.tsx +170 -0
  143. package/src/components/renderers/File.tsx +13 -0
  144. package/src/components/renderers/Image.tsx +63 -0
  145. package/src/components/renderers/Location.tsx +16 -0
  146. package/src/components/renderers/Row.tsx +22 -0
  147. package/src/components/renderers/Text.tsx +32 -0
  148. package/src/components/renderers/Video.tsx +11 -0
  149. package/src/components/renderers/index.ts +28 -0
  150. package/src/contexts/ComposerContext.ts +16 -0
  151. package/src/contexts/MessageContext.ts +16 -0
  152. package/src/contexts/ModalContext.ts +19 -0
  153. package/src/contexts/WebchatContext.ts +61 -0
  154. package/src/contexts/index.ts +4 -0
  155. package/src/hooks/index.ts +3 -0
  156. package/src/hooks/useImageSize.ts +30 -0
  157. package/src/hooks/useRefresh.ts +33 -0
  158. package/src/hooks/useWebchatStore.ts +45 -0
  159. package/src/index.css +18 -0
  160. package/src/index.ts +3 -0
  161. package/src/main.tsx +33 -0
  162. package/src/providers/ModalProvider.tsx +35 -0
  163. package/src/providers/WebchatProvider.tsx +107 -0
  164. package/src/providers/index.ts +2 -0
  165. package/src/schemas/index.ts +1 -0
  166. package/src/schemas/theme.ts +188 -0
  167. package/src/services/clipboard.ts +8 -0
  168. package/src/services/images.ts +39 -0
  169. package/src/services/index.ts +3 -0
  170. package/src/services/toast.tsx +71 -0
  171. package/src/themes/dawn.ts +277 -0
  172. package/src/themes/duskTheme.ts +349 -0
  173. package/src/themes/eggplant.ts +353 -0
  174. package/src/themes/galaxy.ts +323 -0
  175. package/src/themes/index.ts +6 -0
  176. package/src/themes/midnight.ts +276 -0
  177. package/src/themes/prism.ts +349 -0
  178. package/src/twind.config.ts +31 -0
  179. package/src/types/block-type.ts +150 -0
  180. package/src/types/image.ts +10 -0
  181. package/src/types/index.ts +2 -0
  182. package/src/vite-env.d.ts +1 -0
  183. package/tailwind.config.js +0 -0
  184. package/tsconfig.json +30 -0
  185. package/tsconfig.node.json +10 -0
  186. package/vite.config.ts +31 -0
  187. package/README.md +0 -41
  188. package/assets/fonts/roboto/roboto.woff2 +0 -0
  189. package/assets/fonts/roboto/roboto500.woff2 +0 -0
  190. package/assets/fonts/roboto.css +0 -128
  191. package/assets/notification.mp3 +0 -0
  192. package/dist/components/Composer.js +0 -118
  193. package/dist/components/Container.js +0 -62
  194. package/dist/components/ConversationList.d.ts +0 -10
  195. package/dist/components/ConversationList.js +0 -41
  196. package/dist/components/Footer.d.ts +0 -3
  197. package/dist/components/Footer.js +0 -21
  198. package/dist/components/Header.js +0 -181
  199. package/dist/components/VoiceRecorder.d.ts +0 -10
  200. package/dist/components/VoiceRecorder.js +0 -137
  201. package/dist/components/common/Avatar/index.d.ts +0 -9
  202. package/dist/components/common/Avatar/index.js +0 -13
  203. package/dist/components/common/BotInfo/index.d.ts +0 -10
  204. package/dist/components/common/BotInfo/index.js +0 -107
  205. package/dist/components/common/BotInfo/style.scss +0 -88
  206. package/dist/components/common/ConfirmDialog/index.d.ts +0 -11
  207. package/dist/components/common/ConfirmDialog/index.js +0 -78
  208. package/dist/components/common/ConfirmDialog/style.module.scss +0 -48
  209. package/dist/components/common/Dialog/index.d.ts +0 -17
  210. package/dist/components/common/Dialog/index.js +0 -57
  211. package/dist/components/common/Dialog/style.module.scss +0 -29
  212. package/dist/components/common/ToolTip/index.d.ts +0 -10
  213. package/dist/components/common/ToolTip/index.js +0 -163
  214. package/dist/components/common/ToolTip/style.module.scss +0 -108
  215. package/dist/components/common/ToolTip/utils.d.ts +0 -15
  216. package/dist/components/common/ToolTip/utils.js +0 -78
  217. package/dist/components/common/variables.scss +0 -38
  218. package/dist/components/messages/InlineFeedback.d.ts +0 -11
  219. package/dist/components/messages/InlineFeedback.js +0 -56
  220. package/dist/components/messages/Message.d.ts +0 -11
  221. package/dist/components/messages/Message.js +0 -106
  222. package/dist/components/messages/MessageGroup.d.ts +0 -23
  223. package/dist/components/messages/MessageGroup.js +0 -63
  224. package/dist/components/messages/MessageList.d.ts +0 -10
  225. package/dist/components/messages/MessageList.js +0 -148
  226. package/dist/core/api.d.ts +0 -23
  227. package/dist/core/api.js +0 -117
  228. package/dist/core/constants.d.ts +0 -14
  229. package/dist/core/constants.js +0 -29
  230. package/dist/core/socket.d.ts +0 -14
  231. package/dist/core/socket.js +0 -57
  232. package/dist/declaration.d.ts +0 -2
  233. package/dist/declaration.js +0 -1
  234. package/dist/fonts/roboto.d.ts +0 -4
  235. package/dist/fonts/roboto.js +0 -9
  236. package/dist/globals.d.ts +0 -7
  237. package/dist/globals.js +0 -2
  238. package/dist/icons/Add.d.ts +0 -6
  239. package/dist/icons/Add.js +0 -10
  240. package/dist/icons/Cancel.d.ts +0 -5
  241. package/dist/icons/Cancel.js +0 -10
  242. package/dist/icons/Chat.d.ts +0 -6
  243. package/dist/icons/Chat.js +0 -9
  244. package/dist/icons/Close.d.ts +0 -3
  245. package/dist/icons/Close.js +0 -10
  246. package/dist/icons/Delete.d.ts +0 -3
  247. package/dist/icons/Delete.js +0 -11
  248. package/dist/icons/Download.d.ts +0 -3
  249. package/dist/icons/Download.js +0 -10
  250. package/dist/icons/Email.d.ts +0 -3
  251. package/dist/icons/Email.js +0 -8
  252. package/dist/icons/Information.d.ts +0 -3
  253. package/dist/icons/Information.js +0 -12
  254. package/dist/icons/List.d.ts +0 -3
  255. package/dist/icons/List.js +0 -15
  256. package/dist/icons/Microphone.d.ts +0 -5
  257. package/dist/icons/Microphone.js +0 -12
  258. package/dist/icons/Phone.d.ts +0 -3
  259. package/dist/icons/Phone.js +0 -8
  260. package/dist/icons/Reload.d.ts +0 -3
  261. package/dist/icons/Reload.js +0 -10
  262. package/dist/icons/ThumbsDown.d.ts +0 -3
  263. package/dist/icons/ThumbsDown.js +0 -11
  264. package/dist/icons/ThumbsUp.d.ts +0 -3
  265. package/dist/icons/ThumbsUp.js +0 -11
  266. package/dist/icons/Website.d.ts +0 -3
  267. package/dist/icons/Website.js +0 -8
  268. package/dist/main.js +0 -336
  269. package/dist/store/composer.d.ts +0 -17
  270. package/dist/store/composer.js +0 -98
  271. package/dist/store/index.d.ts +0 -89
  272. package/dist/store/index.js +0 -604
  273. package/dist/store/view.d.ts +0 -61
  274. package/dist/store/view.js +0 -365
  275. package/dist/translations/ar.json +0 -30
  276. package/dist/translations/de.json +0 -32
  277. package/dist/translations/en.json +0 -40
  278. package/dist/translations/es.json +0 -19
  279. package/dist/translations/fr.json +0 -40
  280. package/dist/translations/index.d.ts +0 -9
  281. package/dist/translations/index.js +0 -95
  282. package/dist/translations/it.json +0 -38
  283. package/dist/translations/pt.json +0 -19
  284. package/dist/translations/ru.json +0 -24
  285. package/dist/translations/uk.json +0 -24
  286. package/dist/typings.d.ts +0 -410
  287. package/dist/typings.js +0 -2
  288. package/dist/utils/analytics.d.ts +0 -5
  289. package/dist/utils/analytics.js +0 -37
  290. package/dist/utils/index.d.ts +0 -3
  291. package/dist/utils/index.js +0 -27
  292. package/dist/utils/storage.d.ts +0 -16
  293. package/dist/utils/storage.js +0 -129
  294. package/dist/utils/webchatEvents.d.ts +0 -2
  295. package/dist/utils/webchatEvents.js +0 -14
@@ -0,0 +1,141 @@
1
+ import * as Collapsible from '@radix-ui/react-collapsible'
2
+ import { ComponentProps, FC, PropsWithChildren, ReactNode, forwardRef, memo, useState } from 'react'
3
+ import { Avatar, AvatarFallback, AvatarImage } from '.'
4
+ import { StyleOptions, useWebchatContext } from '../contexts'
5
+ import { ReactComponent as ShareIcon } from '../assets/share-04.svg'
6
+ import { copyToClipboard } from '../services'
7
+
8
+ type HeaderProps = {
9
+ defaultOpen?: boolean
10
+ open?: boolean
11
+ disabled?: boolean
12
+ onOpenChange?(open: boolean): void
13
+ } & ComponentProps<'div'>
14
+ const Header = memo(
15
+ forwardRef<HTMLDivElement, HeaderProps>((props, ref) => {
16
+ const {
17
+ theme: { header },
18
+ } = useWebchatContext()
19
+ const [open, setOpen] = useState(false)
20
+ return <Collapsible.Root {...props} {...header?.container} open={open} onOpenChange={setOpen} ref={ref} />
21
+ })
22
+ )
23
+
24
+ type ContentProps = {
25
+ asChild?: true | undefined
26
+ } & ComponentProps<'button'>
27
+ const Content = forwardRef<HTMLButtonElement, ContentProps>((props, ref) => {
28
+ const {
29
+ theme: { header },
30
+ } = useWebchatContext()
31
+ return <Collapsible.Trigger {...props} {...header?.content?.container} ref={ref} />
32
+ })
33
+
34
+ type ExpandedContentProps = {
35
+ asChild?: true | undefined
36
+ forceMount?: true | undefined
37
+ } & ComponentProps<'div'>
38
+ const ExpandedContent = forwardRef<HTMLDivElement, ExpandedContentProps>((props, ref) => {
39
+ const {
40
+ theme: { header },
41
+ } = useWebchatContext()
42
+ return <Collapsible.Content {...props} {...header?.expandedContent?.container} ref={ref} />
43
+ })
44
+
45
+ type HeaderAvatarProps = PropsWithChildren<{
46
+ src?: string
47
+ }>
48
+ const HeaderAvatar = forwardRef<HTMLSpanElement, HeaderAvatarProps>(({ src, children }, ref) => {
49
+ const {
50
+ theme: { header },
51
+ } = useWebchatContext()
52
+ return (
53
+ <Avatar ref={ref} {...header?.content?.avatar?.container}>
54
+ <AvatarImage {...header?.content?.avatar?.image} src={src} />
55
+ <AvatarFallback {...header?.content?.avatar?.fallback}>{children}</AvatarFallback>
56
+ </Avatar>
57
+ )
58
+ })
59
+
60
+ const Title = forwardRef<HTMLHeadingElement, ComponentProps<'h2'>>((props, ref) => {
61
+ const {
62
+ theme: { header },
63
+ } = useWebchatContext()
64
+ return <h2 {...props} {...header?.content?.title} ref={ref} />
65
+ })
66
+
67
+ const Description = forwardRef<HTMLParagraphElement, ComponentProps<'p'>>((props, ref) => {
68
+ const {
69
+ theme: { header },
70
+ } = useWebchatContext()
71
+ return <p {...props} {...header?.content?.description} ref={ref} />
72
+ })
73
+
74
+ const Actions = forwardRef<HTMLDivElement, ComponentProps<'div'>>((props, ref) => {
75
+ const {
76
+ theme: { header },
77
+ } = useWebchatContext()
78
+ return <div {...props} {...header?.content?.actions?.container} ref={ref} />
79
+ })
80
+
81
+ type DescriptionItemProps = {
82
+ title?: ReactNode
83
+ icon?: FC<StyleOptions>
84
+ link?: string
85
+ }
86
+ const DescriptionItem = ({ icon, title, link, ...props }: DescriptionItemProps) => {
87
+ const {
88
+ theme: { header },
89
+ } = useWebchatContext()
90
+ const Icon = icon ?? ShareIcon
91
+
92
+ const handleClick = (value: string | null) => {
93
+ if (value) {
94
+ copyToClipboard(value)
95
+ }
96
+ }
97
+
98
+ if (!link && !title) {
99
+ return null
100
+ }
101
+
102
+ //TODO: This can be refactored to be more generic
103
+ if (link) {
104
+ return (
105
+ <a
106
+ {...props}
107
+ {...header?.expandedContent?.descriptionItems?.container}
108
+ href={link}
109
+ target="_blank"
110
+ rel="noopener"
111
+ >
112
+ <Icon {...header?.expandedContent?.descriptionItems?.icon} />
113
+ <p {...header?.expandedContent?.descriptionItems?.link}>{title}</p>
114
+ </a>
115
+ )
116
+ }
117
+
118
+ return (
119
+ <div
120
+ {...props}
121
+ {...header?.expandedContent?.descriptionItems?.container}
122
+ onClick={(e) => {
123
+ handleClick(e.currentTarget.textContent)
124
+ }}
125
+ >
126
+ <Icon {...header?.expandedContent?.descriptionItems?.icon} />
127
+ <p {...header?.expandedContent?.descriptionItems?.text}>{title}</p>
128
+ </div>
129
+ )
130
+ }
131
+
132
+ const HeaderNamespace = Object.assign(Header, {
133
+ Content,
134
+ ExpandedContent,
135
+ Avatar: HeaderAvatar,
136
+ Description,
137
+ Title,
138
+ Actions,
139
+ DescriptionItem,
140
+ })
141
+ export { HeaderNamespace as Header }
@@ -0,0 +1,15 @@
1
+ import { useWebchatContext } from '../contexts'
2
+ import { ComponentProps, memo } from 'react'
3
+ import { clsx } from 'clsx'
4
+
5
+ export const LoadingIndicator = memo(({ ...props }: ComponentProps<'div'>) => {
6
+ const {
7
+ theme: { loadingIndicator },
8
+ } = useWebchatContext()
9
+
10
+ return (
11
+ <div {...props} {...loadingIndicator?.container}>
12
+ <div {...loadingIndicator?.loader} />
13
+ </div>
14
+ )
15
+ })
@@ -0,0 +1,52 @@
1
+ import { ComponentProps, forwardRef, useEffect, useState } from 'react'
2
+ import { useMount } from 'react-use'
3
+ import { Avatar, AvatarFallback, AvatarImage } from '.'
4
+ import { MessageContext } from '../contexts'
5
+ import { useWebchatContext } from '../contexts'
6
+ import type { MessageObject } from '../types'
7
+ import { Block } from './Block'
8
+
9
+ type MessageProps = {
10
+ scroll: () => void
11
+ } & Partial<MessageObject> &
12
+ ComponentProps<'div'>
13
+ export const Message = forwardRef<HTMLDivElement, MessageProps>(
14
+ ({ direction, block, scroll, disableInput, children, sender, ...props }, ref) => {
15
+ const [isLoading, setIsLoading] = useState<string[]>([])
16
+
17
+ const {
18
+ theme: { message: styles },
19
+ configuration: { botAvatar, botName },
20
+ } = useWebchatContext()
21
+
22
+ useMount(() => {
23
+ scroll()
24
+ })
25
+
26
+ useEffect(() => {
27
+ if (isLoading.length === 0) {
28
+ scroll()
29
+ }
30
+ }, [isLoading.length])
31
+
32
+ return (
33
+ <MessageContext.Provider value={{ isLoading, setIsLoading }}>
34
+ <div
35
+ {...props}
36
+ {...styles?.container}
37
+ data-loaded={isLoading.length === 0}
38
+ data-disable-input={!!disableInput}
39
+ data-direction={direction}
40
+ ref={ref}
41
+ >
42
+ <Avatar {...styles?.avatar?.container}>
43
+ <AvatarImage {...styles?.avatar?.image} src={sender?.avatar ?? botAvatar} />
44
+ <AvatarFallback {...styles?.avatar?.fallback}>{sender?.name[0] ?? botName?.[0]}</AvatarFallback>
45
+ </Avatar>
46
+ {block && <Block block={block} styles={styles?.blocks} />}
47
+ {children}
48
+ </div>
49
+ </MessageContext.Provider>
50
+ )
51
+ }
52
+ )
@@ -0,0 +1,75 @@
1
+ import { ComponentProps, memo, useEffect, useRef, useState } from 'react'
2
+ import { Message } from '.'
3
+ import { useWebchatContext } from '../contexts'
4
+ import { useEffectOnce, useScroll } from 'react-use'
5
+ import { LoadingIndicator } from './LoadingIndicator.tsx'
6
+ import { useRefresh } from '../hooks'
7
+
8
+ const TYPING_DELAY = 10000 // 10 seconds
9
+
10
+ export const MessageList = memo(({ ...props }: ComponentProps<'ul'>) => {
11
+ const {
12
+ theme: { messageList },
13
+ } = useWebchatContext()
14
+ const { messages, setState, client } = useWebchatContext()
15
+ const [isAtBottom, setIsAtBottom] = useState(true)
16
+
17
+ const containerRef = useRef<HTMLUListElement>(null)
18
+ const { y } = useScroll(containerRef)
19
+
20
+ const [isTyping, setIsTyping] = useState(false)
21
+
22
+ const [onRefresh, setRefreshDate] = useRefresh()
23
+
24
+ const scroll = () => {
25
+ if (!containerRef.current) return
26
+ const { scrollHeight } = containerRef.current
27
+ if (isAtBottom) {
28
+ containerRef.current.scrollTo({ top: scrollHeight })
29
+ }
30
+ }
31
+
32
+ useEffect(() => {
33
+ const NineSecondsAgo = new Date(Date.now() - TYPING_DELAY + 2000)
34
+ if (messages.length > 0 && messages[messages.length - 1].timestamp < NineSecondsAgo) {
35
+ setIsTyping(false)
36
+ }
37
+ }, [onRefresh])
38
+
39
+ useEffectOnce(() => {
40
+ return client.on('messageSent', () => {
41
+ setIsTyping(true)
42
+ setRefreshDate(new Date(Date.now() + TYPING_DELAY))
43
+ })
44
+ })
45
+
46
+ useEffectOnce(() => {
47
+ return client.on('message', () => {
48
+ setIsTyping(false)
49
+ })
50
+ })
51
+
52
+ useEffect(() => {
53
+ const lastMessage = messages[messages.length - 1]
54
+ setState({ disableComposer: !!lastMessage?.disableInput })
55
+ }, [messages.length])
56
+
57
+ useEffect(() => {
58
+ if (!containerRef.current) return
59
+ const { offsetHeight, scrollHeight, scrollTop } = containerRef.current
60
+ setIsAtBottom(scrollHeight <= scrollTop + offsetHeight + 100)
61
+ }, [y])
62
+
63
+ return (
64
+ <ul {...props} {...messageList} ref={containerRef}>
65
+ {messages.map((message, index) => (
66
+ <Message scroll={scroll} key={index} {...message} />
67
+ ))}
68
+ {isTyping && (
69
+ <Message scroll={scroll} direction={'incoming'}>
70
+ <LoadingIndicator />
71
+ </Message>
72
+ )}
73
+ </ul>
74
+ )
75
+ })
@@ -0,0 +1,49 @@
1
+ import * as Dialog from '@radix-ui/react-dialog'
2
+ import { ReactNode } from 'react'
3
+ import { useWebchatContext } from '../contexts'
4
+ import { XMarkIcon } from '@heroicons/react/24/outline'
5
+
6
+ export function Modal({
7
+ open,
8
+ onOpenChange,
9
+ children,
10
+ }: {
11
+ open?: boolean
12
+ onOpenChange?: (open: boolean) => void
13
+ children: ReactNode
14
+ }) {
15
+ return (
16
+ <Dialog.Root open={open} onOpenChange={onOpenChange}>
17
+ {children}
18
+ </Dialog.Root>
19
+ )
20
+ }
21
+
22
+ function ModalContent({ title, children }: { title: string; children: ReactNode }) {
23
+ const {
24
+ theme: { modal },
25
+ } = useWebchatContext()
26
+
27
+ return (
28
+ // <Dialog.Portal>
29
+ <>
30
+ <Dialog.Overlay {...modal?.overlay} />
31
+ <div {...modal?.container}>
32
+ <Dialog.Content {...modal?.dialog?.container}>
33
+ <div {...modal?.dialog?.title?.container}>
34
+ <Dialog.Title {...modal?.dialog?.title?.text}>{title}</Dialog.Title>
35
+ <Dialog.Close>
36
+ <XMarkIcon role="button" tabIndex={0} {...modal?.dialog?.title?.closeIcon} />
37
+ </Dialog.Close>
38
+ </div>
39
+ <div {...modal?.dialog?.content}>{children}</div>
40
+ </Dialog.Content>
41
+ </div>
42
+ </>
43
+ // </Dialog.Portal>
44
+ )
45
+ }
46
+
47
+ Modal.Button = Dialog.Trigger
48
+ Modal.Close = Dialog.Close
49
+ Modal.Content = ModalContent
@@ -0,0 +1,52 @@
1
+ import { ArrowPathIcon } from '@heroicons/react/20/solid'
2
+ import { ComponentProps } from 'react'
3
+ import { useModalContext, useWebchatContext } from '../contexts'
4
+ import { Modal } from '.'
5
+
6
+ type Props = {
7
+ // onConfirm: () => void
8
+ } & ComponentProps<typeof ArrowPathIcon>
9
+
10
+ export const RestartConversation = ({ ...props }: Props) => {
11
+ //TODO: Fix this, this was done quick to avoid the app component re-rendering
12
+ const {
13
+ theme: { header },
14
+ client: { restartConversation: onConfirm },
15
+ } = useWebchatContext()
16
+
17
+ const { showModal } = useModalContext()
18
+
19
+ const onSelect = (e: React.SyntheticEvent) => {
20
+ e.stopPropagation()
21
+ showModal({
22
+ title: 'Restart Conversation',
23
+ content: (
24
+ <>
25
+ <p>Are you sure you want to restart a new conversation?</p>
26
+ <Modal.Close asChild>
27
+ <button
28
+ className="ml-auto mt-4 rounded-md border border-blue-700 bg-blue-600 px-2 py-1 text-white"
29
+ onClick={onConfirm}
30
+ >
31
+ clear
32
+ </button>
33
+ </Modal.Close>
34
+ </>
35
+ ),
36
+ })
37
+ }
38
+ return (
39
+ <ArrowPathIcon
40
+ {...props}
41
+ {...header?.content?.actions?.icons}
42
+ role="button"
43
+ tabIndex={0}
44
+ onClick={onSelect}
45
+ onKeyDown={(e) => {
46
+ if (e.key === 'Enter') {
47
+ onSelect(e)
48
+ }
49
+ }}
50
+ />
51
+ )
52
+ }
@@ -0,0 +1,68 @@
1
+ import { Container } from './Container'
2
+ import { Header } from './Header'
3
+ import { RestartConversation } from './RestartConversation'
4
+ import { MessageList } from './MessageList'
5
+ import { Composer, ComposerButton, ComposerInput } from './Composer'
6
+ import { DocumentTextIcon, EnvelopeIcon, GlobeAltIcon, LockClosedIcon, PhoneIcon } from '@heroicons/react/24/solid'
7
+ import { Configuration } from '../contexts'
8
+
9
+ type Props = {
10
+ configuration: Configuration
11
+ }
12
+
13
+ export const Webchat = ({ configuration }: Props) => {
14
+ return (
15
+ <Container>
16
+ <Header>
17
+ <Header.Content>
18
+ <Header.Avatar src={configuration.botAvatar}>{(configuration.botName || 'My Bot').slice(0, 2)}</Header.Avatar>
19
+ <Header.Title>{configuration.botName || 'My Bot'}</Header.Title>
20
+ <Header.Description>{configuration.botDescription}</Header.Description>
21
+ <Header.Actions>
22
+ <RestartConversation />
23
+ </Header.Actions>
24
+ </Header.Content>
25
+ <Header.ExpandedContent>
26
+ <Header.DescriptionItem
27
+ data-email=""
28
+ icon={EnvelopeIcon}
29
+ title={configuration.email?.title}
30
+ link={configuration.email?.link}
31
+ />
32
+
33
+ <Header.DescriptionItem
34
+ data-phone=""
35
+ icon={PhoneIcon}
36
+ title={configuration.phone?.title}
37
+ link={configuration.phone?.link}
38
+ />
39
+
40
+ <Header.DescriptionItem
41
+ data-website=""
42
+ link={configuration.website?.link}
43
+ icon={GlobeAltIcon}
44
+ title={configuration.website?.title}
45
+ />
46
+
47
+ <Header.DescriptionItem
48
+ data-terms=""
49
+ link={configuration.termsOfService?.link}
50
+ icon={DocumentTextIcon}
51
+ title={configuration.termsOfService?.title}
52
+ />
53
+ <Header.DescriptionItem
54
+ data-privacy=""
55
+ link={configuration.privacyPolicy?.link}
56
+ icon={LockClosedIcon}
57
+ title={configuration.privacyPolicy?.title}
58
+ />
59
+ </Header.ExpandedContent>
60
+ </Header>
61
+ <MessageList />
62
+ <Composer>
63
+ <ComposerInput placeholder={configuration.composerPlaceholder || 'Type your message'} />
64
+ <ComposerButton />
65
+ </Composer>
66
+ </Container>
67
+ )
68
+ }