@botpress/webchat 1.0.0 → 1.0.2

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 (105) hide show
  1. package/package.json +2 -1
  2. package/dist/vite.svg +0 -1
  3. package/index.html +0 -18
  4. package/public/vite.svg +0 -1
  5. package/src/App.tsx +0 -41
  6. package/src/Utils/colors.ts +0 -45
  7. package/src/Utils/eventEmitter.ts +0 -31
  8. package/src/Utils/index.ts +0 -2
  9. package/src/assets/check-circle-bold.svg +0 -5
  10. package/src/assets/chevron-up.svg +0 -3
  11. package/src/assets/file-05.svg +0 -6
  12. package/src/assets/globe-02.svg +0 -6
  13. package/src/assets/help-circle.svg +0 -3
  14. package/src/assets/info-circle.svg +0 -3
  15. package/src/assets/lock-01.svg +0 -4
  16. package/src/assets/mail-01.svg +0 -6
  17. package/src/assets/minus-circle.svg +0 -3
  18. package/src/assets/phone.svg +0 -6
  19. package/src/assets/send-03.svg +0 -4
  20. package/src/assets/share-04.svg +0 -5
  21. package/src/assets/slash-circle-01.svg +0 -3
  22. package/src/assets/x-circle-bold.svg +0 -5
  23. package/src/assets/x-close.svg +0 -3
  24. package/src/assets/x.svg +0 -3
  25. package/src/client/MessagingClient.ts +0 -87
  26. package/src/client/adapters/Audio.ts +0 -10
  27. package/src/client/adapters/Card.ts +0 -104
  28. package/src/client/adapters/Carousel.ts +0 -11
  29. package/src/client/adapters/Choice.ts +0 -48
  30. package/src/client/adapters/Dropdown.ts +0 -39
  31. package/src/client/adapters/File.ts +0 -10
  32. package/src/client/adapters/Image.ts +0 -10
  33. package/src/client/adapters/Location.ts +0 -18
  34. package/src/client/adapters/Message.ts +0 -26
  35. package/src/client/adapters/Text.ts +0 -11
  36. package/src/client/adapters/Utils.ts +0 -11
  37. package/src/client/adapters/Video.ts +0 -10
  38. package/src/client/adapters/Voice.ts +0 -9
  39. package/src/client/adapters/index.ts +0 -12
  40. package/src/client/index.ts +0 -2
  41. package/src/components/Avatar.tsx +0 -22
  42. package/src/components/Block.tsx +0 -17
  43. package/src/components/Composer.tsx +0 -115
  44. package/src/components/Container.tsx +0 -17
  45. package/src/components/Header.tsx +0 -141
  46. package/src/components/LoadingIndicator.tsx +0 -15
  47. package/src/components/Message.tsx +0 -52
  48. package/src/components/MessageList.tsx +0 -75
  49. package/src/components/Modal.tsx +0 -49
  50. package/src/components/RestartConversation.tsx +0 -52
  51. package/src/components/Webchat.tsx +0 -68
  52. package/src/components/dev-tools/DevTools.tsx +0 -496
  53. package/src/components/dev-tools/configuration.tsx +0 -27
  54. package/src/components/dev-tools/helpers.ts +0 -21
  55. package/src/components/index.ts +0 -12
  56. package/src/components/renderers/Audio.tsx +0 -11
  57. package/src/components/renderers/Bubble.tsx +0 -12
  58. package/src/components/renderers/Button.tsx +0 -59
  59. package/src/components/renderers/Carousel.tsx +0 -51
  60. package/src/components/renderers/Column.tsx +0 -22
  61. package/src/components/renderers/Dropdown.tsx +0 -170
  62. package/src/components/renderers/File.tsx +0 -13
  63. package/src/components/renderers/Image.tsx +0 -63
  64. package/src/components/renderers/Location.tsx +0 -16
  65. package/src/components/renderers/Row.tsx +0 -22
  66. package/src/components/renderers/Text.tsx +0 -32
  67. package/src/components/renderers/Video.tsx +0 -11
  68. package/src/components/renderers/index.ts +0 -28
  69. package/src/contexts/ComposerContext.ts +0 -16
  70. package/src/contexts/MessageContext.ts +0 -16
  71. package/src/contexts/ModalContext.ts +0 -19
  72. package/src/contexts/WebchatContext.ts +0 -61
  73. package/src/contexts/index.ts +0 -4
  74. package/src/hooks/index.ts +0 -3
  75. package/src/hooks/useImageSize.ts +0 -30
  76. package/src/hooks/useRefresh.ts +0 -33
  77. package/src/hooks/useWebchatStore.ts +0 -45
  78. package/src/index.css +0 -18
  79. package/src/index.ts +0 -3
  80. package/src/main.tsx +0 -33
  81. package/src/providers/ModalProvider.tsx +0 -35
  82. package/src/providers/WebchatProvider.tsx +0 -107
  83. package/src/providers/index.ts +0 -2
  84. package/src/schemas/index.ts +0 -1
  85. package/src/schemas/theme.ts +0 -188
  86. package/src/services/clipboard.ts +0 -8
  87. package/src/services/images.ts +0 -39
  88. package/src/services/index.ts +0 -3
  89. package/src/services/toast.tsx +0 -71
  90. package/src/themes/dawn.ts +0 -277
  91. package/src/themes/duskTheme.ts +0 -349
  92. package/src/themes/eggplant.ts +0 -353
  93. package/src/themes/galaxy.ts +0 -323
  94. package/src/themes/index.ts +0 -6
  95. package/src/themes/midnight.ts +0 -276
  96. package/src/themes/prism.ts +0 -349
  97. package/src/twind.config.ts +0 -31
  98. package/src/types/block-type.ts +0 -150
  99. package/src/types/image.ts +0 -10
  100. package/src/types/index.ts +0 -2
  101. package/src/vite-env.d.ts +0 -1
  102. package/tailwind.config.js +0 -0
  103. package/tsconfig.json +0 -30
  104. package/tsconfig.node.json +0 -10
  105. package/vite.config.ts +0 -31
@@ -1,33 +0,0 @@
1
- import { useState } from 'react'
2
- import { useAsync } from 'react-use'
3
-
4
- export const defaultGetRefreshTime = (expiresAt: Date) => {
5
- const now = new Date()
6
- return expiresAt.getTime() - now.getTime()
7
- }
8
-
9
- /**
10
- * Utility hooks to force a state fresh based on a date
11
- * @example
12
- * const [onRefresh, setDate] = useDateRefresh()
13
- * useEffect(() => {}, [onRefresh])
14
- * setDate(futureDate) // The refresh function will trigger when the date passes
15
- * @returns value to observe for refreshing and a function that set the refresh date
16
- */
17
- export const useRefresh = (getRefreshTimeInMs = defaultGetRefreshTime): [number, (date: Date) => void] => {
18
- const [onRefresh, setOnRefresh] = useState(0)
19
- const [refreshDate, setRefreshDate] = useState<Date>()
20
-
21
- const incrementRefresh = () => setOnRefresh((onRefresh) => onRefresh + 1)
22
-
23
- useAsync(async () => {
24
- if (refreshDate) {
25
- const refreshTimeout = setTimeout(incrementRefresh, getRefreshTimeInMs(refreshDate))
26
- return () => {
27
- clearTimeout(refreshTimeout)
28
- }
29
- }
30
- }, [refreshDate])
31
-
32
- return [onRefresh, setRefreshDate]
33
- }
@@ -1,45 +0,0 @@
1
- import { UserCredentials } from '@botpress/messaging-socket'
2
- import { create } from 'zustand'
3
- import { devtools, persist } from 'zustand/middleware'
4
-
5
- type WebchatState = {
6
- messageHistory: {
7
- [key: string]: string[]
8
- }
9
- user?: UserCredentials
10
- conversationId?: string
11
- addMessageToHistory: (props: { userId: string; message: string }) => void
12
- setUser: (userId?: UserCredentials) => void
13
- setConversationId: (conversationId?: string) => void
14
- }
15
-
16
- export const useWebchatStore = create<WebchatState>()(
17
- devtools(
18
- persist(
19
- (set) => ({
20
- messageHistory: {},
21
- addMessageToHistory: ({ userId, message }) =>
22
- set((state) => ({
23
- ...state,
24
- messageHistory: {
25
- ...state.messageHistory,
26
- [userId]: [message, ...(state.messageHistory[userId] ?? []).slice(0, 100)],
27
- },
28
- })),
29
- setUser: (user) =>
30
- set((state) => ({
31
- ...state,
32
- user,
33
- })),
34
- setConversationId: (conversationId) =>
35
- set((state) => ({
36
- ...state,
37
- conversationId,
38
- })),
39
- }),
40
- {
41
- name: 'botpress-webchat',
42
- }
43
- )
44
- )
45
- )
package/src/index.css DELETED
@@ -1,18 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- :root {
6
-
7
- /* font-family: 'Fira Code', monospace;
8
- font-family: 'IBM Plex Sans', sans-serif;
9
- font-family: 'Rubik', sans-serif; */
10
- font-family: 'Inter', sans-serif;
11
-
12
-
13
- font-synthesis: none;
14
- text-rendering: optimizeLegibility;
15
- -webkit-font-smoothing: antialiased;
16
- -moz-osx-font-smoothing: grayscale;
17
- -webkit-text-size-adjust: 100%;
18
- }
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './components'
2
- export * from './providers'
3
- export * from './types'
package/src/main.tsx DELETED
@@ -1,33 +0,0 @@
1
- import ReactDOM from 'react-dom/client'
2
- import { App } from './App.tsx'
3
- import './index.css'
4
-
5
- import { StrictMode } from 'react'
6
-
7
- import { install } from '@twind/core'
8
- import { config } from './twind.config.ts'
9
- import { ThemeSchema } from './schemas'
10
- import { prismTheme } from './themes'
11
- import { WebchatClient } from './client/MessagingClient.ts'
12
-
13
- export const twObject = install(config)
14
-
15
- export const webchatClient = new WebchatClient({
16
- url: 'https://messaging.botpress.cloud',
17
- clientId: 'b390bfce-4eed-4078-b180-655f8202a12d',
18
- })
19
-
20
- //bot a louis
21
- // 09d8ea5b-2781-4fe4-a0b5-d75798b24c50
22
-
23
- //hello sarah
24
- // b390bfce-4eed-4078-b180-655f8202a12d
25
-
26
- ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
27
- <StrictMode>
28
- <div className="grid h-screen w-screen grid-flow-col grid-cols-[24rem_1fr] grid-rows-[auto_1fr] gap-8 p-8">
29
- <App theme={ThemeSchema.parse(prismTheme)} client={webchatClient} />
30
- <App theme={ThemeSchema.parse(prismTheme)} client={webchatClient} />
31
- </div>
32
- </StrictMode>
33
- )
@@ -1,35 +0,0 @@
1
- import { PropsWithChildren, ReactNode, useState } from 'react'
2
- import { Modal } from '../components'
3
- import { ModalContext } from '../contexts'
4
-
5
- export type ModalProps = {
6
- title: string | null
7
- content: ReactNode | null
8
- }
9
-
10
- type Props = PropsWithChildren
11
-
12
- export const ModalProvider = ({ children }: Props) => {
13
- const [open, setOpen] = useState(false)
14
- const [title, setTitle] = useState<string>('')
15
- const [content, setContent] = useState<ReactNode | null>(null)
16
-
17
- const showModal = ({ title, content }: { title: string; content: ReactNode }) => {
18
- setTitle(title)
19
- setContent(content)
20
- setOpen(true)
21
- }
22
-
23
- const hideModal = () => {
24
- setOpen(false)
25
- }
26
-
27
- return (
28
- <ModalContext.Provider value={{ hideModal, showModal, title, content, open }}>
29
- <Modal open={open} onOpenChange={setOpen}>
30
- <Modal.Content title={title}>{content}</Modal.Content>
31
- </Modal>
32
- {children}
33
- </ModalContext.Provider>
34
- )
35
- }
@@ -1,107 +0,0 @@
1
- import { ComponentProps, ReactNode, useState } from 'react'
2
- import { Configuration, Renderers, WebchatContext } from '../contexts'
3
- import { eventEmitter } from '../Utils'
4
- import { renderers as defaultRenderers } from '../components'
5
- import { defaultConfiguration } from '../components/dev-tools/configuration'
6
- import { MessageObject } from '../types'
7
- import { Theme } from '../schemas'
8
- import { useAsync, useEffectOnce } from 'react-use'
9
- import { type WebchatClient, MessageContentSchema } from '../client'
10
- import { Message } from '@botpress/messaging-socket'
11
- import { useWebchatStore } from '../hooks'
12
-
13
- type Props = {
14
- styles?: Theme
15
- renderers?: Renderers
16
- client: WebchatClient
17
- configuration: Configuration
18
- children?: ReactNode | ((configuration: Configuration) => ReactNode)
19
- } & Omit<ComponentProps<typeof WebchatContext.Provider>, 'value' | 'children'>
20
-
21
- export const WebchatProvider = ({ styles = {}, renderers, client, children, configuration, ...props }: Props) => {
22
- const [messages, setMessages] = useState<MessageObject[]>([])
23
- const [state, setWebchatState] = useState({ disableComposer: false })
24
- const [config, setConfig] = useState(configuration)
25
- const [theme, setTheme] = useState<Theme>(styles) // TODO: remove this once dev theme switching is figured out
26
- const addMessageToHistory = useWebchatStore((state) => state.addMessageToHistory)
27
- const setConversationId = useWebchatStore((state) => state.setConversationId)
28
- const user = useWebchatStore((state) => state.user)
29
- const setUser = useWebchatStore((state) => state.setUser)
30
-
31
- const providerProps = {
32
- ...props,
33
- value: {
34
- theme,
35
- renderers: { ...defaultRenderers, ...renderers },
36
- messages,
37
- eventEmitter,
38
- configuration,
39
- setConfiguration: setConfig,
40
- state,
41
- setState: (newState: Partial<typeof state>) => setWebchatState({ ...state, ...newState }),
42
- setTheme,
43
- client: {
44
- sendMessage: async (message: string) => {
45
- await client.sendMessage(message)
46
- setMessages((messages) => [
47
- ...messages,
48
- {
49
- direction: 'outgoing',
50
- sender: { name: 'You' },
51
- timestamp: new Date(),
52
- block: { type: 'bubble', block: { type: 'text', text: message } },
53
- },
54
- ])
55
-
56
- if (client.userId) {
57
- addMessageToHistory({ message, userId: client.userId })
58
- }
59
- },
60
- on: client.on,
61
- restartConversation: async () => {
62
- await client.newConversation()
63
- setMessages([])
64
- },
65
- },
66
- },
67
- }
68
-
69
- useEffectOnce(() => {
70
- return client.on('message', (message: Message) => {
71
- try {
72
- const payload = MessageContentSchema.parse(message.payload)
73
- setMessages((messages) => [
74
- ...messages,
75
- {
76
- direction: 'incoming',
77
- sender: { name: 'Bot', avatar: config.botAvatar },
78
- timestamp: message.sentOn,
79
- block: payload,
80
- },
81
- ])
82
- } catch (err) {
83
- console.error('Invalid message payload')
84
- }
85
- })
86
- })
87
-
88
- useEffectOnce(() => {
89
- return client.on('conversation', (conversationId) => {
90
- setConversationId(conversationId)
91
- })
92
- })
93
-
94
- useAsync(async () => {
95
- const newUser = await client.connect(user)
96
- setUser(newUser)
97
- return () => {
98
- client.disconnect()
99
- }
100
- }, [])
101
-
102
- return (
103
- <WebchatContext.Provider {...providerProps}>
104
- {typeof children === 'function' ? children(config) : children}
105
- </WebchatContext.Provider>
106
- )
107
- }
@@ -1,2 +0,0 @@
1
- export * from './ModalProvider'
2
- export * from './WebchatProvider'
@@ -1 +0,0 @@
1
- export * from './theme'
@@ -1,188 +0,0 @@
1
- import { CSSProperties } from 'react'
2
- import { markdownTypes } from '../types'
3
- import { z } from 'zod'
4
- import { tw } from '@twind/core'
5
-
6
- const StyleOptionSchema = z.object({
7
- className: z
8
- .string()
9
- .optional()
10
- .transform((val) => {
11
- if (val) {
12
- return tw(val)
13
- }
14
- }),
15
- style: z
16
- .object({})
17
- .passthrough()
18
- .optional()
19
- .transform((val) => {
20
- if (val) {
21
- return val as CSSProperties
22
- }
23
- }),
24
- })
25
-
26
- export const BlocksSchema = z.object({
27
- button: StyleOptionSchema.optional(),
28
- text: z.record(z.enum(markdownTypes), StyleOptionSchema.optional()),
29
- image: z
30
- .object({
31
- image: StyleOptionSchema.optional(),
32
- placeholder: StyleOptionSchema.optional(),
33
- })
34
- .optional(),
35
- audio: StyleOptionSchema.optional(),
36
- video: StyleOptionSchema.optional(),
37
- file: z
38
- .object({
39
- container: StyleOptionSchema.optional(),
40
- title: StyleOptionSchema.optional(),
41
- icon: StyleOptionSchema.optional(),
42
- })
43
- .optional(),
44
- location: z
45
- .object({
46
- container: StyleOptionSchema.optional(),
47
- title: StyleOptionSchema.optional(),
48
- icon: StyleOptionSchema.optional(),
49
- })
50
- .optional(),
51
- column: StyleOptionSchema.optional(),
52
- row: StyleOptionSchema.optional(),
53
- bubble: StyleOptionSchema.optional(),
54
- carousel: z
55
- .object({
56
- container: StyleOptionSchema.optional(),
57
- slidesContainer: StyleOptionSchema.optional(),
58
- backButton: StyleOptionSchema.optional(),
59
- nextButton: StyleOptionSchema.optional(),
60
- })
61
- .optional(),
62
- dropdown: z
63
- .object({
64
- button: z
65
- .object({
66
- container: StyleOptionSchema.optional(),
67
- icon: StyleOptionSchema.optional(),
68
- text: StyleOptionSchema.optional(),
69
- })
70
- .optional(),
71
- content: z
72
- .object({
73
- container: StyleOptionSchema.optional(),
74
- item: StyleOptionSchema.optional(),
75
- })
76
- .optional(),
77
- })
78
- .optional(),
79
- })
80
-
81
- export type Theme = z.infer<typeof ThemeSchema>
82
- export const ThemeSchema = z.object({
83
- container: StyleOptionSchema.optional(),
84
- modal: z
85
- .object({
86
- overlay: StyleOptionSchema.optional(),
87
- container: StyleOptionSchema.optional(),
88
- dialog: z
89
- .object({
90
- container: StyleOptionSchema.optional(),
91
- title: z
92
- .object({
93
- container: StyleOptionSchema.optional(),
94
- text: StyleOptionSchema.optional(),
95
- closeIcon: StyleOptionSchema.optional(),
96
- })
97
- .optional(),
98
- content: StyleOptionSchema.optional(),
99
- })
100
- .optional(),
101
- })
102
- .optional(),
103
- notification: z
104
- .object({
105
- container: StyleOptionSchema.optional(),
106
- title: StyleOptionSchema.optional(),
107
- description: StyleOptionSchema.optional(),
108
- icon: StyleOptionSchema.optional(),
109
- closeIcon: StyleOptionSchema.optional(),
110
- })
111
- .optional(),
112
- header: z
113
- .object({
114
- container: StyleOptionSchema.optional(),
115
- content: z.object({
116
- container: StyleOptionSchema.optional(),
117
- title: StyleOptionSchema.optional(),
118
- description: StyleOptionSchema.optional(),
119
- avatar: z
120
- .object({
121
- container: StyleOptionSchema.optional(),
122
- image: StyleOptionSchema.optional(),
123
- fallback: StyleOptionSchema.optional(),
124
- })
125
- .optional(),
126
- actions: z
127
- .object({
128
- container: StyleOptionSchema.optional(),
129
- icons: StyleOptionSchema.optional(),
130
- })
131
- .optional(),
132
- }),
133
- expandedContent: z
134
- .object({
135
- container: StyleOptionSchema.optional(),
136
- descriptionItems: z
137
- .object({
138
- container: StyleOptionSchema.optional(),
139
- icon: StyleOptionSchema.optional(),
140
- text: StyleOptionSchema.optional(),
141
- link: StyleOptionSchema.optional(),
142
- })
143
- .optional(),
144
- })
145
- .optional(),
146
- description: z
147
- .object({
148
- container: StyleOptionSchema.optional(),
149
- title: StyleOptionSchema.optional(),
150
- subtitle: StyleOptionSchema.optional(),
151
- })
152
- .optional(),
153
- newConversationIcon: StyleOptionSchema.optional(),
154
- })
155
- .optional(),
156
- composer: z
157
- .object({
158
- container: StyleOptionSchema.optional(),
159
- input: StyleOptionSchema.optional(),
160
- button: z
161
- .object({
162
- container: StyleOptionSchema.optional(),
163
- icon: StyleOptionSchema.optional(),
164
- })
165
- .optional(),
166
- })
167
- .optional(),
168
- messageList: StyleOptionSchema.optional(),
169
- message: z
170
- .object({
171
- container: StyleOptionSchema.optional(),
172
- avatar: z
173
- .object({
174
- container: StyleOptionSchema.optional(),
175
- image: StyleOptionSchema.optional(),
176
- fallback: StyleOptionSchema.optional(),
177
- })
178
- .optional(),
179
- blocks: BlocksSchema.optional(),
180
- })
181
- .optional(),
182
- loadingIndicator: z
183
- .object({
184
- container: StyleOptionSchema.optional(),
185
- loader: StyleOptionSchema.optional(),
186
- })
187
- .optional(),
188
- })
@@ -1,8 +0,0 @@
1
- import { showToast } from '.'
2
-
3
- export function copyToClipboard(value: string, description?: string) {
4
- const message = description ? `The ${description} has been copied to your clipboard.` : 'Copied to clipboard.'
5
- return navigator.clipboard.writeText(value).then(() => {
6
- return showToast({ title: message, type: 'success' })
7
- })
8
- }
@@ -1,39 +0,0 @@
1
- import { Dimensions, Options } from '../types'
2
-
3
- export const getImageSize = (url: string, options: Options = {}): Promise<Dimensions> => {
4
- return new Promise((resolve, reject) => {
5
- if (typeof window === 'undefined') {
6
- return reject('Window is not defined')
7
- }
8
-
9
- if (!url) {
10
- return reject('Url is not defined')
11
- }
12
-
13
- let timer: number | null = null
14
-
15
- const img = new Image()
16
-
17
- img.addEventListener('load', () => {
18
- if (timer) {
19
- clearTimeout(timer)
20
- }
21
-
22
- resolve({ width: img.naturalWidth, height: img.naturalHeight })
23
- })
24
-
25
- img.addEventListener('error', (event) => {
26
- if (timer) {
27
- clearTimeout(timer)
28
- }
29
-
30
- reject(`${event.type}: ${event.message}`)
31
- })
32
-
33
- img.src = url
34
-
35
- if (options.timeout) {
36
- timer = setTimeout(() => reject('Timeout'), options.timeout)
37
- }
38
- })
39
- }
@@ -1,3 +0,0 @@
1
- export * from './clipboard'
2
- export * from './images'
3
- export * from './toast'
@@ -1,71 +0,0 @@
1
- /* eslint-disable react-refresh/only-export-components */
2
- import { toast } from 'react-hot-toast'
3
- import { Transition } from '@headlessui/react'
4
- import { ReactComponent as CircleCheckIcon } from '../assets/check-circle-bold.svg'
5
- import { ReactComponent as XCloseIcon } from '../assets/x-close.svg'
6
- import { ReactComponent as CircleXIcon } from '../assets/x-circle-bold.svg'
7
- import { FC, PropsWithChildren, ReactNode } from 'react'
8
- import { useWebchatContext } from '../contexts'
9
-
10
- type ToastType = ToastProps['type'] | CustomToastProps['type']
11
- type CustomToastProps = {
12
- type: 'custom'
13
- content?: ReactNode
14
- }
15
- type ToastProps = {
16
- type?: 'success' | 'error' | 'neutral'
17
- title: string
18
- icon?: FC<{ className?: string; type?: ToastType }>
19
- description?: string
20
- }
21
-
22
- export function showToast(props: ToastProps | CustomToastProps) {
23
- return toast.custom((t) => (
24
- <ToastContainer type={props.type} show={t.visible}>
25
- {props.type === 'custom' ? props.content : <ToastContent {...props} toastId={t.id} />}
26
- </ToastContainer>
27
- ))
28
- }
29
-
30
- type ToastContentProps = ToastProps & { toastId: string }
31
- const ToastContent = ({ icon: Icon, type, title, description, toastId }: ToastContentProps) => {
32
- const {
33
- theme: { notification: styles },
34
- } = useWebchatContext()
35
-
36
- return (
37
- <>
38
- {Icon ? <Icon {...styles?.icon} /> : <ToastIcon {...styles?.icon} type={type} />}
39
- <p {...styles?.title}>{title}</p>
40
- {description ? <p {...styles?.description}>{description}</p> : null}
41
- <XCloseIcon {...styles?.closeIcon} onClick={() => toast.dismiss(toastId)} />
42
- </>
43
- )
44
- }
45
-
46
- type ToastContainerProps = PropsWithChildren<{
47
- type?: ToastType
48
- show: boolean
49
- }>
50
- const ToastContainer = ({ type, ...props }: ToastContainerProps) => {
51
- const {
52
- theme: { notification: styles },
53
- } = useWebchatContext()
54
-
55
- return <Transition {...props} {...styles?.container} appear data-type={type ?? 'neutral'} />
56
- }
57
-
58
- type ToastIconProps = {
59
- type?: ToastType
60
- className?: string
61
- }
62
- const ToastIcon = ({ type, className }: ToastIconProps) => {
63
- switch (type) {
64
- case 'success':
65
- return <CircleCheckIcon className={className} />
66
- case 'error':
67
- return <CircleXIcon className={className} />
68
- default:
69
- return null
70
- }
71
- }