@botpress/webchat 1.0.0 → 1.0.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 (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,59 +0,0 @@
1
- import { ComponentProps, useEffect, useState } from 'react'
2
- import { ButtonBlock, CommonBlockProps } from '../../types'
3
- import { useWebchatContext } from '../../contexts'
4
-
5
- type Props = CommonBlockProps & ButtonBlock
6
- export const Button = ({ text, buttonValue, type, styles, variant, groupId, reusable, ...props }: Props) => {
7
- const { eventEmitter, client } = useWebchatContext()
8
- const [activated, setActivated] = useState(false)
9
- const [groupActivated, setGroupActivated] = useState(false)
10
- const [disabled, setDisabled] = useState(false)
11
-
12
- useEffect(() => {
13
- if (!groupId) return
14
- return eventEmitter.on(`button-group-${groupId}-click`, () => {
15
- setGroupActivated(true)
16
- if (!reusable) setDisabled(true)
17
- })
18
- }, [eventEmitter, groupId, reusable])
19
-
20
- function onClick() {
21
- if (groupId) {
22
- eventEmitter.emit(`button-group-${groupId}-click`)
23
- }
24
- setActivated(true)
25
- if (!reusable) setDisabled(true)
26
- if (variant === 'link') return
27
- client.sendMessage(buttonValue)
28
- }
29
-
30
- return (
31
- <ButtonOrAnchor
32
- {...props}
33
- variant={variant}
34
- onClick={onClick}
35
- disabled={disabled}
36
- data-activated={activated ? '' : undefined}
37
- data-group-activated={groupActivated ? '' : undefined}
38
- data-type={variant}
39
- value={buttonValue}
40
- {...styles?.[type]}
41
- >
42
- {text}
43
- </ButtonOrAnchor>
44
- )
45
- }
46
- type ButtonOrAnchorProps =
47
- | ({ variant: 'action' } & ComponentProps<'button'>)
48
- | ({ variant: 'link'; value: string } & ComponentProps<'a'>)
49
- const ButtonOrAnchor = (props: ButtonOrAnchorProps) => {
50
- if (props.variant === 'link') {
51
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
- const { value, variant, ...rest } = props
53
- return <a {...rest} href={value} target="_blank" rel="noopener noreferrer" />
54
- }
55
-
56
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
- const { variant, ...rest } = props
58
- return <button {...rest} />
59
- }
@@ -1,51 +0,0 @@
1
- import { forwardRef, useCallback, useEffect, useState } from 'react'
2
- import { CarouselBlock, CommonBlockProps } from '../../types'
3
- import useEmblaCarousel, { EmblaCarouselType } from 'embla-carousel-react'
4
- import { Block } from '../Block'
5
- import { ChevronRightIcon, ChevronLeftIcon } from '@heroicons/react/24/solid'
6
-
7
- type Props = CommonBlockProps & CarouselBlock
8
- export const Carousel = forwardRef<HTMLDivElement, Props>(({ type, styles, blocks }, ref) => {
9
- const [emblaRef, emblaApi] = useEmblaCarousel({ skipSnaps: true })
10
-
11
- const [prevBtnDisabled, setPrevBtnDisabled] = useState(true)
12
- const [nextBtnDisabled, setNextBtnDisabled] = useState(true)
13
-
14
- const scrollPrev = useCallback(() => emblaApi && emblaApi.scrollPrev(), [emblaApi])
15
- const scrollNext = useCallback(() => emblaApi && emblaApi.scrollNext(), [emblaApi])
16
-
17
- const carouselStyles = styles?.[type]
18
-
19
- const onSelect = useCallback((emblaApi: EmblaCarouselType) => {
20
- setPrevBtnDisabled(!emblaApi.canScrollPrev())
21
- setNextBtnDisabled(!emblaApi.canScrollNext())
22
- }, [])
23
-
24
- useEffect(() => {
25
- if (!emblaApi) return
26
- onSelect(emblaApi)
27
- emblaApi.on('reInit', onSelect)
28
- emblaApi.on('select', onSelect)
29
- }, [emblaApi, onSelect])
30
-
31
- return (
32
- <div {...carouselStyles?.container} data-container="carousel" ref={emblaRef}>
33
- <div ref={ref} {...carouselStyles?.slidesContainer}>
34
- {blocks.map((block, index) => (
35
- <Block key={index} styles={styles} block={block} />
36
- ))}
37
- </div>
38
- <ChevronLeftIcon
39
- {...carouselStyles?.backButton}
40
- data-disabled={prevBtnDisabled ? '' : undefined}
41
- onClick={scrollPrev}
42
- />
43
-
44
- <ChevronRightIcon
45
- {...carouselStyles?.nextButton}
46
- data-disabled={nextBtnDisabled ? '' : undefined}
47
- onClick={scrollNext}
48
- />
49
- </div>
50
- )
51
- })
@@ -1,22 +0,0 @@
1
- import { ComponentProps, forwardRef } from 'react'
2
- import { ColumnBlock, CommonBlockProps } from '../../types'
3
- import { Block } from '../Block'
4
-
5
- type Props = CommonBlockProps & ColumnBlock & ComponentProps<'div'>
6
- export const Column = forwardRef<HTMLDivElement, Props>(
7
- ({ blocks, styles, type, horizontalAlignment, verticalAlignment, ...props }, ref) => {
8
- return (
9
- <div
10
- data-horizontal={horizontalAlignment}
11
- data-vertical={verticalAlignment}
12
- {...props}
13
- {...styles?.[type]}
14
- ref={ref}
15
- >
16
- {blocks.map((block, index) => (
17
- <Block key={index} styles={styles} block={block} />
18
- ))}
19
- </div>
20
- )
21
- }
22
- )
@@ -1,170 +0,0 @@
1
- // export const Dropdown = ({ styles, type, options, label, ...props }: Props) => {
2
- import * as React from 'react'
3
- import {
4
- useFloating,
5
- useClick,
6
- useDismiss,
7
- useRole,
8
- useListNavigation,
9
- useInteractions,
10
- FloatingFocusManager,
11
- useTypeahead,
12
- offset,
13
- flip,
14
- size,
15
- autoUpdate,
16
- FloatingPortal,
17
- } from '@floating-ui/react'
18
- import { CommonBlockProps, DropdownBlock } from '../../types'
19
- import { ComponentProps } from 'react'
20
- import { ChevronDownIcon } from '@heroicons/react/20/solid'
21
- import { clsx } from 'clsx'
22
- import { useWebchatContext } from '../../contexts'
23
-
24
- // const options = ['Red', 'Orange', 'Yellow', 'Green', 'Cyan', 'Blue', 'Purple', 'Pink', 'Maroon', 'Black', 'White']
25
- type Props = CommonBlockProps & DropdownBlock & ComponentProps<'div'>
26
-
27
- export const Dropdown = ({ styles, type, options, label, reusable }: Props) => {
28
- const [isOpen, setIsOpen] = React.useState(false)
29
- const [activeIndex, setActiveIndex] = React.useState<number | null>(null)
30
- const [selectedIndex, setSelectedIndex] = React.useState<number | null>(null)
31
- const { client } = useWebchatContext()
32
-
33
- const optionsDict = options.reduce((acc, option) => {
34
- acc[option.label] = option.value
35
- return acc
36
- }, {} as { [key: string]: string })
37
-
38
- const labels = optionsDict ? Object.keys(optionsDict) : []
39
-
40
- const onOpenChange = (open: boolean) => {
41
- if (selectedIndex !== null && !reusable) {
42
- setIsOpen(false)
43
- } else {
44
- setIsOpen(open)
45
- }
46
- }
47
-
48
- const { refs, floatingStyles, context } = useFloating({
49
- placement: 'bottom-start',
50
- open: isOpen,
51
- onOpenChange,
52
- whileElementsMounted: autoUpdate,
53
- middleware: [
54
- offset(5),
55
- flip({ padding: 10 }),
56
- size({
57
- apply({ rects, elements, availableHeight }) {
58
- Object.assign(elements.floating.style, {
59
- maxHeight: `${availableHeight}px`,
60
- minWidth: `${rects.reference.width}px`,
61
- })
62
- },
63
- padding: 10,
64
- }),
65
- ],
66
- })
67
-
68
- const listRef = React.useRef<Array<HTMLElement | null>>([])
69
- const listContentRef = React.useRef(labels)
70
- const isTypingRef = React.useRef(false)
71
-
72
- const click = useClick(context, { event: 'mousedown' })
73
- const dismiss = useDismiss(context)
74
- const role = useRole(context, { role: 'listbox' })
75
- const listNav = useListNavigation(context, {
76
- listRef,
77
- activeIndex,
78
- selectedIndex,
79
- onNavigate: setActiveIndex,
80
- // This is a large list, allow looping.
81
- loop: true,
82
- })
83
- const typeahead = useTypeahead(context, {
84
- listRef: listContentRef,
85
- activeIndex,
86
- selectedIndex,
87
- onMatch: isOpen ? setActiveIndex : setSelectedIndex,
88
- onTypingChange(isTyping) {
89
- isTypingRef.current = isTyping
90
- },
91
- })
92
-
93
- const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
94
- dismiss,
95
- role,
96
- listNav,
97
- typeahead,
98
- click,
99
- ])
100
-
101
- const handleSelect = (index: number) => {
102
- setSelectedIndex(index)
103
- client.sendMessage(optionsDict[labels[index]])
104
- setIsOpen(false)
105
- }
106
-
107
- const selectedItemLabel = selectedIndex !== null ? labels[selectedIndex] : undefined
108
-
109
- return (
110
- <>
111
- <div
112
- tabIndex={0}
113
- ref={refs.setReference}
114
- aria-labelledby="select-label"
115
- aria-autocomplete="none"
116
- data-disabled={selectedIndex !== null && !reusable ? '' : undefined}
117
- {...styles?.[type]?.button?.container}
118
- {...getReferenceProps()}
119
- >
120
- <span {...styles?.[type]?.button?.text}>{selectedItemLabel || label || 'Select...'}</span>
121
- <ChevronDownIcon {...styles?.[type]?.button?.icon} />
122
- </div>
123
- {isOpen && (
124
- <FloatingPortal>
125
- <FloatingFocusManager context={context} modal={false}>
126
- <div
127
- ref={refs.setFloating}
128
- className={styles?.[type]?.content?.container?.className}
129
- // className="min-w-[100px] overflow-y-auto rounded-md border border-gray-200 bg-white text-sm text-gray-700 outline-none"
130
- style={{ ...floatingStyles, ...styles?.[type]?.content?.container?.style }}
131
- {...getFloatingProps()}
132
- >
133
- {labels.map((value, i) => (
134
- <div
135
- key={value}
136
- ref={(node) => {
137
- listRef.current[i] = node
138
- }}
139
- role="option"
140
- tabIndex={i === activeIndex ? 0 : -1}
141
- aria-selected={i === selectedIndex && i === activeIndex}
142
- data-active={i === activeIndex ? '' : undefined}
143
- {...styles?.[type]?.content?.item}
144
- {...getItemProps({
145
- onClick() {
146
- handleSelect(i)
147
- },
148
- onKeyDown(event) {
149
- if (event.key === 'Enter') {
150
- event.preventDefault()
151
- handleSelect(i)
152
- }
153
-
154
- if (event.key === ' ' && !isTypingRef.current) {
155
- event.preventDefault()
156
- handleSelect(i)
157
- }
158
- },
159
- })}
160
- >
161
- {value}
162
- </div>
163
- ))}
164
- </div>
165
- </FloatingFocusManager>
166
- </FloatingPortal>
167
- )}
168
- </>
169
- )
170
- }
@@ -1,13 +0,0 @@
1
- import { forwardRef } from 'react'
2
- import { CommonBlockProps, FileBlock } from '../../types'
3
- import { DocumentArrowDownIcon } from '@heroicons/react/20/solid'
4
-
5
- type Props = CommonBlockProps & FileBlock
6
- export const File = forwardRef<HTMLAnchorElement, Props>(({ type, title, styles, url, ...props }, ref) => {
7
- return (
8
- <a {...props} {...styles?.[type]?.container} href={url} download ref={ref}>
9
- <p {...styles?.[type]?.title}>{title || url}</p>
10
- <DocumentArrowDownIcon {...styles?.[type]?.icon} />
11
- </a>
12
- )
13
- })
@@ -1,63 +0,0 @@
1
- import { forwardRef, useEffect, useId, useLayoutEffect, useState } from 'react'
2
- import { CommonBlockProps, ImageBlock } from '../../types'
3
- import { useMessageContext } from '../../contexts'
4
- import { getImageSize } from '../../services'
5
-
6
- type Props = CommonBlockProps & ImageBlock
7
- export const Image = forwardRef<HTMLImageElement, Props>(
8
- ({ url, type, styles, orientation = 'auto', ...props }, ref) => {
9
- const id = useId()
10
- const { setIsLoading } = useMessageContext()
11
- const [imageOrientation, setImageOrientation] = useState(orientation)
12
- const [loaded, setLoaded] = useState(false)
13
-
14
- useLayoutEffect(() => {
15
- setIsLoading((prev) => [...prev, id])
16
- }, [])
17
-
18
- useEffect(() => {
19
- if (!url) return
20
- if (imageOrientation === 'auto') {
21
- getImageSize(url).then(({ width, height }) => {
22
- setImageOrientation(getClosestAspectRatio(width, height))
23
- setIsLoading((prev) => {
24
- return prev.filter((currId) => currId !== id)
25
- })
26
- })
27
- }
28
- }, [url])
29
-
30
- return (
31
- <>
32
- {loaded ? null : <div data-orientation={imageOrientation} {...styles?.[type]?.placeholder} />}
33
- <img
34
- data-orientation={imageOrientation}
35
- data-loaded={loaded}
36
- {...props}
37
- {...styles?.[type]?.image}
38
- src={url}
39
- alt=""
40
- ref={ref}
41
- loading="lazy"
42
- onLoad={() => {
43
- setLoaded(true)
44
- }}
45
- />
46
- </>
47
- )
48
- }
49
- )
50
-
51
- function getClosestAspectRatio(width: number, height: number) {
52
- type aspects = keyof typeof aspects
53
- const aspects = {
54
- square: 1,
55
- portrait: 3 / 4,
56
- landscape: 4 / 3,
57
- } as const
58
- const aspect = width / height
59
- const closest = (Object.keys(aspects) as aspects[]).reduce((prev, curr) => {
60
- return Math.abs(aspects[curr] - aspect) < Math.abs(aspects[prev] - aspect) ? curr : prev
61
- })
62
- return closest
63
- }
@@ -1,16 +0,0 @@
1
- import { forwardRef } from 'react'
2
- import { CommonBlockProps, LocationBlock } from '../../types'
3
- import { MapPinIcon } from '@heroicons/react/20/solid'
4
-
5
- type Props = CommonBlockProps & LocationBlock
6
- export const Location = forwardRef<HTMLAnchorElement, Props>(
7
- ({ type, latitude, longitude, title, styles, ...props }, ref) => {
8
- const link = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`
9
- return (
10
- <a {...props} {...styles?.[type]?.container} href={link} type="_blank" rel="noopener" ref={ref}>
11
- <p {...styles?.[type]?.title}>{title}</p>
12
- <MapPinIcon {...styles?.[type]?.icon} />
13
- </a>
14
- )
15
- }
16
- )
@@ -1,22 +0,0 @@
1
- import { ComponentProps, forwardRef } from 'react'
2
- import { RowBlock, CommonBlockProps } from '../../types'
3
- import { Block } from '../Block'
4
-
5
- type Props = CommonBlockProps & RowBlock & ComponentProps<'div'>
6
- export const Row = forwardRef<HTMLDivElement, Props>(
7
- ({ blocks, styles, type, horizontalAlignment, verticalAlignment, ...props }, ref) => {
8
- return (
9
- <div
10
- data-horizontal={horizontalAlignment}
11
- data-vertical={verticalAlignment}
12
- {...props}
13
- {...styles?.[type]}
14
- ref={ref}
15
- >
16
- {blocks.map((block, index) => (
17
- <Block key={index} styles={styles} block={block} />
18
- ))}
19
- </div>
20
- )
21
- }
22
- )
@@ -1,32 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { CommonBlockProps, TextBlock } from '../../types'
3
- import ReactMarkdown from 'react-markdown'
4
-
5
- import { ComponentProps } from 'react'
6
-
7
- type Props = CommonBlockProps & TextBlock
8
- export const Text = ({ text, type, styles }: Props) => {
9
- const markdownStyles = styles?.[type]
10
-
11
- const markdownComponents: ComponentProps<typeof ReactMarkdown>['components'] = {
12
- h1: ({ node, ...props }) => <h1 {...props} {...markdownStyles?.heading1} />,
13
- h2: ({ node, ...props }) => <h2 {...props} {...markdownStyles?.heading2} />,
14
- h3: ({ node, ...props }) => <h3 {...props} {...markdownStyles?.heading3} />,
15
- h4: 'h3',
16
- h5: 'h3',
17
- h6: 'h3',
18
- em: ({ node, ...props }) => <em {...props} {...markdownStyles?.italic} />,
19
- strong: ({ node, ...props }) => <strong {...props} {...markdownStyles?.bold} />,
20
- p: ({ node, ...props }) => <p {...props} {...markdownStyles?.text} />,
21
- hr: ({ node, ...props }) => <hr {...props} {...markdownStyles?.horizontalRule} />,
22
- a: ({ node, ...props }) => <a {...props} {...markdownStyles?.link} />,
23
- ol: ({ node, ordered, ...props }) => <ol {...props} {...markdownStyles?.orderedList} />,
24
- ul: ({ node, ordered, ...props }) => <ul {...props} {...markdownStyles?.unorderedList} />,
25
- li: ({ node, ordered, ...props }) => <li {...props} {...markdownStyles?.listItem} />,
26
- br: ({ node, ...props }) => <br {...props} {...markdownStyles?.lineBreak} />,
27
- img: () => null,
28
- pre: () => null,
29
- }
30
-
31
- return <ReactMarkdown components={markdownComponents}>{text}</ReactMarkdown>
32
- }
@@ -1,11 +0,0 @@
1
- import { forwardRef } from 'react'
2
- import { CommonBlockProps, VideoBlock } from '../../types'
3
-
4
- type Props = CommonBlockProps & VideoBlock
5
- export const Video = forwardRef<HTMLVideoElement, Props>(({ url, type, styles, ...props }, ref) => {
6
- return (
7
- <div>
8
- <video {...props} controls src={url} {...styles?.[type]} ref={ref} />
9
- </div>
10
- )
11
- })
@@ -1,28 +0,0 @@
1
- import { Text } from './Text'
2
- import { Button } from './Button'
3
- import { Bubble } from './Bubble'
4
- import { Renderers } from '../../contexts'
5
- import { Image } from './Image'
6
- import { Video } from './Video'
7
- import { Audio } from './Audio'
8
- import { Location } from './Location'
9
- import { Column } from './Column'
10
- import { Row } from './Row'
11
- import { Carousel } from './Carousel'
12
- import { Dropdown } from './Dropdown'
13
- import { File } from './File'
14
-
15
- export const renderers: Renderers = {
16
- text: Text,
17
- button: Button,
18
- bubble: Bubble,
19
- audio: Audio,
20
- column: Column,
21
- file: File,
22
- image: Image,
23
- location: Location,
24
- row: Row,
25
- video: Video,
26
- carousel: Carousel,
27
- dropdown: Dropdown,
28
- }
@@ -1,16 +0,0 @@
1
- import { createContext, useContext } from 'react'
2
-
3
- type ComposerContextValue = {
4
- value: string
5
- setValue: (value: string) => void
6
- }
7
-
8
- export const ComposerContext = createContext<ComposerContextValue | null>(null)
9
-
10
- export function useComposerContext() {
11
- const context = useContext(ComposerContext)
12
- if (!context) {
13
- throw new Error('useComposerContext must be used within a Message')
14
- }
15
- return context
16
- }
@@ -1,16 +0,0 @@
1
- import { Dispatch, SetStateAction, createContext, useContext } from 'react'
2
-
3
- type MessageContextVaue = {
4
- isLoading: string[]
5
- setIsLoading: Dispatch<SetStateAction<string[]>>
6
- }
7
-
8
- export const MessageContext = createContext<MessageContextVaue | null>(null)
9
-
10
- export function useMessageContext() {
11
- const context = useContext(MessageContext)
12
- if (!context) {
13
- throw new Error('useMessageContext must be used within a Message')
14
- }
15
- return context
16
- }
@@ -1,19 +0,0 @@
1
- import { ReactNode, createContext, useContext } from 'react'
2
-
3
- type ModalContextVaue = {
4
- open: boolean
5
- showModal: (props: { title: string; content: ReactNode }) => void
6
- hideModal: () => void
7
- title: string
8
- content: ReactNode | null
9
- }
10
-
11
- export const ModalContext = createContext<ModalContextVaue | null>(null)
12
-
13
- export function useModalContext() {
14
- const context = useContext(ModalContext)
15
- if (!context) {
16
- throw new Error('useModalContext must be used within a ModalProvider')
17
- }
18
- return context
19
- }
@@ -1,61 +0,0 @@
1
- import { CSSProperties, FC, ReactNode, createContext, useContext } from 'react'
2
- import type { BlockObject, BlockStyles, MessageObject } from '../types'
3
- import { EventEmitter, Events } from '../Utils'
4
- import { Theme } from '../schemas'
5
- import { type WebchatClient } from '../client'
6
-
7
- export type StyleOptions = {
8
- className?: string
9
- style?: CSSProperties
10
- }
11
-
12
- type DescriptionItem = {
13
- title: string
14
- link?: string
15
- }
16
-
17
- export type Configuration = {
18
- composerPlaceholder?: string
19
- botName?: string
20
- botAvatar?: string
21
- botDescription?: string
22
- website?: DescriptionItem
23
- email?: DescriptionItem
24
- phone?: DescriptionItem
25
- privacyPolicy?: DescriptionItem
26
- termsOfService?: DescriptionItem
27
- }
28
-
29
- export type Renderers<P extends BlockObject = BlockObject> = {
30
- [T in P['type']]: FC<Extract<P, { type: T }> & { styles: BlockStyles }>
31
- }
32
-
33
- export type ModalProps = {
34
- title: string | null
35
- content: ReactNode | null
36
- }
37
-
38
- type ContextVaue = {
39
- theme: Theme
40
- renderers: Renderers
41
- messages: MessageObject[]
42
- eventEmitter: EventEmitter<Events>
43
- configuration: Configuration
44
- setConfiguration: React.Dispatch<React.SetStateAction<Configuration>>
45
- state: {
46
- disableComposer: boolean
47
- }
48
- client: { on: WebchatClient['on']; sendMessage: WebchatClient['sendMessage']; restartConversation: () => void }
49
- setState: (state: Partial<ContextVaue['state']>) => void
50
- setTheme: (styles: Partial<Theme>) => void // Temporary while I decide how to do the theme switching in dev mode
51
- }
52
-
53
- export const WebchatContext = createContext<ContextVaue | null>(null)
54
-
55
- export function useWebchatContext() {
56
- const context = useContext(WebchatContext)
57
- if (!context) {
58
- throw new Error('useWebchatContext must be used within a WebchatProvider')
59
- }
60
- return context
61
- }
@@ -1,4 +0,0 @@
1
- export * from './ComposerContext'
2
- export * from './MessageContext'
3
- export * from './ModalContext'
4
- export * from './WebchatContext'
@@ -1,3 +0,0 @@
1
- export * from './useImageSize'
2
- export * from './useWebchatStore'
3
- export * from './useRefresh.ts'
@@ -1,30 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import { getImageSize } from '../services'
3
- import { Dimensions, Options, UseImageSizeResult } from '../types'
4
-
5
- export const useImageSize = (url: string, options?: Options): UseImageSizeResult => {
6
- const [dimensions, setDimensions] = useState<Dimensions | null>(null)
7
- const [loading, setLoading] = useState(false)
8
- const [error, setError] = useState<string | null>(null)
9
-
10
- useEffect(() => {
11
- const fetch = async () => {
12
- setLoading(true)
13
- setDimensions(null)
14
-
15
- try {
16
- const { width, height } = await getImageSize(url, options)
17
-
18
- setDimensions({ width, height })
19
- } catch (error: unknown) {
20
- setError((error as string).toString())
21
- } finally {
22
- setLoading(false)
23
- }
24
- }
25
-
26
- fetch()
27
- }, [url, options])
28
-
29
- return [dimensions, { loading, error }]
30
- }