@botonic/react 0.32.0 → 0.33.0-alpha.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 (80) hide show
  1. package/lib/cjs/components/carousel.d.ts +8 -9
  2. package/lib/cjs/components/carousel.js +25 -21
  3. package/lib/cjs/components/carousel.js.map +1 -1
  4. package/lib/cjs/components/element.d.ts +7 -3
  5. package/lib/cjs/components/element.js +6 -6
  6. package/lib/cjs/components/element.js.map +1 -1
  7. package/lib/cjs/components/index-types.d.ts +3 -8
  8. package/lib/cjs/components/message/message-footer.js +2 -2
  9. package/lib/cjs/components/multichannel/index-types.d.ts +0 -4
  10. package/lib/cjs/components/multichannel/multichannel-carousel.d.ts +1 -1
  11. package/lib/cjs/components/multichannel/multichannel-carousel.js +59 -62
  12. package/lib/cjs/components/multichannel/multichannel-carousel.js.map +1 -1
  13. package/lib/cjs/components/multichannel/multichannel-context.d.ts +0 -3
  14. package/lib/cjs/components/multichannel/multichannel-context.js +0 -3
  15. package/lib/cjs/components/multichannel/multichannel-context.js.map +1 -1
  16. package/lib/cjs/components/pic.d.ts +8 -5
  17. package/lib/cjs/components/pic.js +8 -8
  18. package/lib/cjs/components/pic.js.map +1 -1
  19. package/lib/cjs/components/subtitle.d.ts +9 -5
  20. package/lib/cjs/components/subtitle.js +6 -7
  21. package/lib/cjs/components/subtitle.js.map +1 -1
  22. package/lib/cjs/components/title.d.ts +9 -5
  23. package/lib/cjs/components/title.js +6 -7
  24. package/lib/cjs/components/title.js.map +1 -1
  25. package/lib/cjs/components/whatsapp-button-list.js +5 -5
  26. package/lib/cjs/components/whatsapp-button-list.js.map +1 -1
  27. package/lib/cjs/components/whatsapp-cta-url-button.js +2 -2
  28. package/lib/cjs/components/whatsapp-cta-url-button.js.map +1 -1
  29. package/lib/cjs/index-types.d.ts +1 -1
  30. package/lib/cjs/msg-to-botonic.js +2 -2
  31. package/lib/cjs/webchat-app.js +1 -1
  32. package/lib/cjs/webchat-app.js.map +1 -1
  33. package/lib/esm/components/carousel.d.ts +8 -9
  34. package/lib/esm/components/carousel.js +25 -21
  35. package/lib/esm/components/carousel.js.map +1 -1
  36. package/lib/esm/components/element.d.ts +7 -3
  37. package/lib/esm/components/element.js +4 -4
  38. package/lib/esm/components/element.js.map +1 -1
  39. package/lib/esm/components/index-types.d.ts +3 -8
  40. package/lib/esm/components/message/message-footer.js +2 -2
  41. package/lib/esm/components/multichannel/index-types.d.ts +0 -4
  42. package/lib/esm/components/multichannel/multichannel-carousel.d.ts +1 -1
  43. package/lib/esm/components/multichannel/multichannel-carousel.js +61 -64
  44. package/lib/esm/components/multichannel/multichannel-carousel.js.map +1 -1
  45. package/lib/esm/components/multichannel/multichannel-context.d.ts +0 -3
  46. package/lib/esm/components/multichannel/multichannel-context.js +0 -3
  47. package/lib/esm/components/multichannel/multichannel-context.js.map +1 -1
  48. package/lib/esm/components/pic.d.ts +8 -5
  49. package/lib/esm/components/pic.js +6 -6
  50. package/lib/esm/components/pic.js.map +1 -1
  51. package/lib/esm/components/subtitle.d.ts +9 -5
  52. package/lib/esm/components/subtitle.js +4 -5
  53. package/lib/esm/components/subtitle.js.map +1 -1
  54. package/lib/esm/components/title.d.ts +9 -5
  55. package/lib/esm/components/title.js +4 -5
  56. package/lib/esm/components/title.js.map +1 -1
  57. package/lib/esm/components/whatsapp-button-list.js +5 -5
  58. package/lib/esm/components/whatsapp-button-list.js.map +1 -1
  59. package/lib/esm/components/whatsapp-cta-url-button.js +2 -2
  60. package/lib/esm/components/whatsapp-cta-url-button.js.map +1 -1
  61. package/lib/esm/index-types.d.ts +1 -1
  62. package/lib/esm/msg-to-botonic.js +2 -2
  63. package/lib/esm/webchat-app.js +1 -1
  64. package/lib/esm/webchat-app.js.map +1 -1
  65. package/package.json +2 -2
  66. package/src/components/{carousel.jsx → carousel.tsx} +58 -33
  67. package/src/components/{element.jsx → element.tsx} +8 -3
  68. package/src/components/index-types.ts +4 -11
  69. package/src/components/message/message-footer.tsx +2 -2
  70. package/src/components/multichannel/index-types.ts +0 -4
  71. package/src/components/multichannel/multichannel-carousel.jsx +93 -93
  72. package/src/components/multichannel/multichannel-context.jsx +0 -3
  73. package/src/components/{pic.jsx → pic.tsx} +12 -5
  74. package/src/components/{subtitle.jsx → subtitle.tsx} +10 -10
  75. package/src/components/{title.jsx → title.tsx} +8 -6
  76. package/src/components/whatsapp-button-list.tsx +5 -5
  77. package/src/components/whatsapp-cta-url-button.tsx +5 -2
  78. package/src/index-types.ts +2 -0
  79. package/src/msg-to-botonic.jsx +2 -2
  80. package/src/webchat-app.tsx +1 -1
@@ -1,9 +1,12 @@
1
- import { isWhatsapp } from '@botonic/core'
1
+ import { isDev, isFacebook, isWebchat, isWhatsapp } from '@botonic/core'
2
2
  import React, { useContext } from 'react'
3
3
 
4
4
  import { RequestContext } from '../../contexts'
5
+ import { Button } from '../button'
5
6
  import { Carousel } from '../carousel'
6
- import { MultichannelText } from './multichannel-text'
7
+ import { Image } from '../image'
8
+ import { Text } from '../text'
9
+ import { WhatsappCTAUrlButton } from '../whatsapp-cta-url-button'
7
10
  import {
8
11
  getFilteredElements,
9
12
  isMultichannelButton,
@@ -11,102 +14,99 @@ import {
11
14
  isNodeSubtitle,
12
15
  isNodeTitle,
13
16
  } from './multichannel-utils'
17
+ import { convertToMarkdownMeta } from './whatsapp/markdown-meta'
14
18
 
15
19
  export const MultichannelCarousel = props => {
16
20
  const requestContext = useContext(RequestContext)
17
21
 
18
- const getButtons = node =>
19
- [].concat(getFilteredElements(node, isMultichannelButton))
20
-
21
- if (isWhatsapp(requestContext.session)) {
22
- const elements = props.children
23
- .map(e => e.props.children)
24
- .map((element, i) => {
25
- let imageProps = undefined
26
- let title = undefined
27
- let subtitle = undefined
28
- const buttons = []
29
-
30
- for (const node of element) {
31
- if (isNodePic(node)) {
32
- imageProps = node.props
33
- }
34
- if (isNodeTitle(node)) {
35
- title = node.props.children
36
- }
37
- if (isNodeSubtitle(node)) {
38
- subtitle = node.props.children
39
- }
40
-
41
- if (isMultichannelButton(node)) {
42
- buttons.push(node)
43
- }
44
- //TODO support fragment containing an array
45
- if (Array.isArray(node)) {
46
- buttons.push(getButtons(node))
47
- }
48
- }
49
-
50
- let header = ''
51
- if (props.showTitle && title) {
52
- header += `${title ? `**${title}**` : ''}`
53
- if (title && subtitle) {
54
- header += ' '
55
- }
56
- }
57
- if (props.showSubtitle && subtitle) {
58
- header += `_${subtitle}_`
59
- }
60
-
61
- return (
62
- // TODO: newkey only for 1 nested button
63
- <MultichannelText
64
- key={i}
65
- newkey={i}
66
- indexMode={props.indexMode}
67
- buttonsAsText={props.buttonsAsText}
68
- >
69
- {header || null}
70
- {buttons}
71
- </MultichannelText>
72
- )
73
-
74
- // TODO: in the future, this would be the default mode
75
- // } else {
76
- // return (
77
- // <React.Fragment key={i}>
78
- // <Image
79
- // src={imageSrc}
80
- // caption={carouselToCaption(
81
- // i + 1,
82
- // title,
83
- // subtitle,
84
- // imageSrc,
85
- // buttonProps
86
- // )}
87
- // ></Image>
88
- // </React.Fragment>
89
- // )
90
- // }
91
- })
92
- return elements
93
- } else {
22
+ if (isDev(requestContext.session) || isWebchat(requestContext.session)) {
94
23
  return <Carousel {...props}>{props.children}</Carousel>
95
24
  }
25
+
26
+ const messages = []
27
+ const childrenElements = props.children.map(e => e.props.children)
28
+
29
+ childrenElements.forEach((element, i) => {
30
+ const { imageProps, title, subtitle, buttons } =
31
+ parseCarouselElement(element)
32
+
33
+ const textMessage = getTextMessage(requestContext.session, title, subtitle)
34
+
35
+ if (imageProps?.src) {
36
+ const messageWithImage = <Image src={imageProps.src} />
37
+ messages.push(messageWithImage)
38
+ }
39
+
40
+ if (
41
+ isWhatsapp(requestContext.session) &&
42
+ buttons.some(button => button.url)
43
+ ) {
44
+ const messageWithButtonUrl = (
45
+ <WhatsappCTAUrlButton
46
+ key={`carousel-element-${i}-cta-url`}
47
+ body={title}
48
+ footer={`_${subtitle}_`}
49
+ displayText={buttons[0].text}
50
+ url={buttons[0].url}
51
+ />
52
+ )
53
+ messages.push(messageWithButtonUrl)
54
+ }
55
+
56
+ const messageWithButtons = buttons.some(button => button.payload) ? (
57
+ <Text key={`carousel-element-${i}-text`}>
58
+ {textMessage}
59
+ {buttons
60
+ .filter(button => isWhatsapp(requestContext.session) && !button.url)
61
+ .map(button => (
62
+ <Button
63
+ key={`carousel-element-${i}-button`}
64
+ payload={button.payload}
65
+ url={button.url}
66
+ >
67
+ {button.text}
68
+ </Button>
69
+ ))}
70
+ </Text>
71
+ ) : (
72
+ []
73
+ )
74
+ messages.push(messageWithButtons)
75
+ })
76
+
77
+ return <>{messages}</>
78
+ }
79
+
80
+ function getButtons(node) {
81
+ return [].concat(getFilteredElements(node, isMultichannelButton))
82
+ }
83
+
84
+ function parseCarouselElement(element) {
85
+ let imageProps, title, subtitle
86
+ const buttonsChildren = []
87
+
88
+ for (const node of element) {
89
+ if (isNodePic(node)) imageProps = node.props
90
+ if (isNodeTitle(node)) title = node.props.children
91
+ if (isNodeSubtitle(node)) subtitle = node.props.children
92
+ if (isMultichannelButton(node)) buttonsChildren.push(node)
93
+ if (Array.isArray(node)) buttonsChildren.push(...getButtons(node))
94
+ }
95
+
96
+ const buttons = buttonsChildren.map(button => {
97
+ return {
98
+ text: button.props.children,
99
+ payload: button.props.payload,
100
+ url: button.props.url,
101
+ }
102
+ })
103
+
104
+ return { imageProps, title, subtitle, buttons }
96
105
  }
97
106
 
98
- // const carouselToCaption = (index, title, subtitle, imageSrc, buttonProps) => {
99
- // let caption = ''
100
- // let header = `${title ? `*${title}*` : ''}`
101
- // header += `${subtitle ? ` - _${subtitle}_` : ''}`
102
- // let buttons = ''
103
- // if (buttonProps.url) {
104
- // buttons += ` - ${buttonProps.children}: ${buttonProps.url}`
105
- // caption = `${header ? `${header}\n` : ''}${buttons}`
106
- // }
107
- // if (buttonProps.payload || buttonProps.path) {
108
- // buttons += `${index}. `
109
- // caption = `${buttons}${buttonProps.children}`
110
- // }
111
- // return caption
112
- // }
107
+ function getTextMessage(session, title, subtitle) {
108
+ const formattedTextMessage = `**${title}**${subtitle ? ` _${subtitle}_` : ''}`
109
+ return isWhatsapp(session) || isFacebook(session)
110
+ ? convertToMarkdownMeta(formattedTextMessage)
111
+ : formattedTextMessage
112
+ }
@@ -2,9 +2,6 @@ import React from 'react'
2
2
 
3
3
  export const MultichannelContext = React.createContext({
4
4
  boldIndex: true,
5
- carousel: {
6
- indexMode: undefined,
7
- },
8
5
  text: {
9
6
  indexMode: 'letter',
10
7
  },
@@ -10,18 +10,25 @@ const PicStyled = styled.img`
10
10
  border-top-right-radius: 8px;
11
11
  width: ${WEBCHAT.DEFAULTS.ELEMENT_WIDTH}px;
12
12
  height: 140px;
13
- background: ${COLORS.SOLID_WHITE} url(${props => props.src}) no-repeat
14
- center/cover;
13
+ background: ${COLORS.SOLID_WHITE};
14
+ object-fit: center/cover;
15
15
  border-bottom: 1px solid ${COLORS.SEASHELL_WHITE};
16
16
  `
17
+ export interface PicProps {
18
+ src: string
19
+ }
17
20
 
18
- export const Pic = props => {
21
+ export const Pic = (props: PicProps) => {
19
22
  props = { ...props, src: staticAsset(props.src) }
23
+
20
24
  const renderBrowser = () => <PicStyled src={props.src} />
25
+
26
+ // @ts-ignore
21
27
  const renderNode = () => <pic>{props.src}</pic>
28
+
22
29
  return renderComponent({ renderBrowser, renderNode })
23
30
  }
24
31
 
25
- Pic.serialize = picProps => {
26
- return { pic: picProps.src }
32
+ Pic.serialize = (props: PicProps) => {
33
+ return { pic: props.src }
27
34
  }
@@ -9,21 +9,21 @@ const SubtitleContainer = styled.div`
9
9
  padding: 0px 15px 10px 15px;
10
10
  color: ${COLORS.MID_GRAY};
11
11
  `
12
- export const Subtitle = props => {
12
+
13
+ export interface SubtitleProps {
14
+ children: React.ReactNode
15
+ }
16
+
17
+ export const Subtitle = (props: SubtitleProps) => {
13
18
  const renderBrowser = () => (
14
- <SubtitleContainer
15
- style={{
16
- ...props.style,
17
- }}
18
- >
19
- {props.children}
20
- </SubtitleContainer>
19
+ <SubtitleContainer>{props.children}</SubtitleContainer>
21
20
  )
21
+
22
22
  const renderNode = () => <desc>{props.children}</desc>
23
23
 
24
24
  return renderComponent({ renderBrowser, renderNode })
25
25
  }
26
26
 
27
- Subtitle.serialize = subtitleProps => {
28
- return { subtitle: subtitleProps.children }
27
+ Subtitle.serialize = (props: SubtitleProps) => {
28
+ return { subtitle: props.children }
29
29
  }
@@ -7,16 +7,18 @@ const TitleContainer = styled.div`
7
7
  font-size: 14px;
8
8
  padding: 10px 15px;
9
9
  `
10
+ export interface TitleProps {
11
+ children: React.ReactNode
12
+ }
13
+
14
+ export const Title = (props: TitleProps) => {
15
+ const renderBrowser = () => <TitleContainer>{props.children}</TitleContainer>
10
16
 
11
- export const Title = props => {
12
- const renderBrowser = () => (
13
- <TitleContainer style={{ ...props.style }}>{props.children}</TitleContainer>
14
- )
15
17
  const renderNode = () => <title>{props.children}</title>
16
18
 
17
19
  return renderComponent({ renderBrowser, renderNode })
18
20
  }
19
21
 
20
- Title.serialize = titleProps => {
21
- return { title: titleProps.children }
22
+ Title.serialize = (props: TitleProps) => {
23
+ return { title: props.children }
22
24
  }
@@ -32,15 +32,15 @@ export interface WhatsappButtonListProps {
32
32
  }
33
33
 
34
34
  const serialize = _whatsappButtonListProps => {
35
- // TODO: Implement to have data persistance in localStorage, not needed for this WhatsApp development
35
+ // TODO: Implement to have data persistence in localStorage, not needed for this WhatsApp development
36
36
  return {}
37
37
  }
38
38
 
39
39
  export const WhatsappButtonList = (props: WhatsappButtonListProps) => {
40
- const trucateSectionsContents = (
40
+ const truncateSectionsContents = (
41
41
  sections: WhatsappButtonListSectionProps[]
42
42
  ): WhatsappButtonListSectionProps[] => {
43
- const trucateRowContents = (
43
+ const truncateRowContents = (
44
44
  row: WhatsappButtonListRowProps
45
45
  ): WhatsappButtonListRowProps => {
46
46
  const title = truncateText(row.title, WHATSAPP_MAX_BUTTON_LIST_CHARS)
@@ -62,7 +62,7 @@ export const WhatsappButtonList = (props: WhatsappButtonListProps) => {
62
62
  title: section.title
63
63
  ? truncateText(section.title, WHATSAPP_MAX_BUTTON_LIST_CHARS)
64
64
  : undefined,
65
- rows: section.rows.map(trucateRowContents),
65
+ rows: section.rows.map(truncateRowContents),
66
66
  }))
67
67
  }
68
68
 
@@ -87,7 +87,7 @@ export const WhatsappButtonList = (props: WhatsappButtonListProps) => {
87
87
  {...props}
88
88
  body={convertToMarkdownMeta(props.body)}
89
89
  button={truncateText(props.button, WHATSAPP_MAX_BUTTON_CHARS)}
90
- sections={JSON.stringify(trucateSectionsContents(props.sections))}
90
+ sections={JSON.stringify(truncateSectionsContents(props.sections))}
91
91
  type={INPUT.WHATSAPP_BUTTON_LIST}
92
92
  />
93
93
  )
@@ -36,7 +36,7 @@ export type WhatsappCTAUrlButtonProps =
36
36
  | WhatsappCTAUrlButtonWebviewProps
37
37
 
38
38
  const serialize = _whatsappCTAUrlButtonProps => {
39
- // TODO: Implement to have data persistance in localStorage, not needed for this WhatsApp development
39
+ // TODO: Implement to have data persistence in localStorage, not needed for this WhatsApp development
40
40
  return {}
41
41
  }
42
42
 
@@ -66,7 +66,10 @@ export const WhatsappCTAUrlButton = (props: WhatsappCTAUrlButtonProps) => {
66
66
  WHATSAPP_MAX_BODY_CHARS
67
67
  ),
68
68
  footer: props.footer
69
- ? truncateText(props.footer, WHATSAPP_MAX_FOOTER_CHARS)
69
+ ? truncateText(
70
+ convertToMarkdownMeta(props.footer),
71
+ WHATSAPP_MAX_FOOTER_CHARS
72
+ )
70
73
  : undefined,
71
74
  displayText: truncateText(props.displayText, WHATSAPP_MAX_BUTTON_CHARS),
72
75
  url:
@@ -213,3 +213,5 @@ interface UpdateMessageInfoEvent {
213
213
  message: MessageInfo
214
214
  isError?: boolean
215
215
  }
216
+
217
+ export { CaseEventQueuePositionChangedInput } from '@botonic/core'
@@ -129,7 +129,7 @@ function textToBotonic(msg) {
129
129
  return (
130
130
  <Text {...msg} key={msg.key}>
131
131
  {txt}
132
- {quickrepliesParse(msg)}
132
+ {parseQuickReplies(msg)}
133
133
  </Text>
134
134
  )
135
135
  if (msg.buttons && msg.buttons.length)
@@ -182,7 +182,7 @@ function buttonsParse(buttons) {
182
182
  })
183
183
  }
184
184
 
185
- function quickrepliesParse(msg) {
185
+ function parseQuickReplies(msg) {
186
186
  let replies = null
187
187
  if (msg.replies) {
188
188
  replies = msg.replies.map((el, i) => {
@@ -279,7 +279,7 @@ export class WebchatApp {
279
279
  delete message.sent_by
280
280
  const response = msgToBotonic(
281
281
  message,
282
- // TODO: Review if is neded allow declar customTypes inside and ouside theme
282
+ // TODO: Review if is needed allow declar customTypes inside and outside theme
283
283
  this.theme?.message?.customTypes || this.theme?.customMessageTypes
284
284
  )
285
285