@botonic/react 0.23.0 → 0.23.1-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 (46) hide show
  1. package/lib/cjs/components/image.js +3 -1
  2. package/lib/cjs/components/image.js.map +1 -1
  3. package/lib/cjs/components/index-types.d.ts +7 -0
  4. package/lib/cjs/components/index-types.js.map +1 -1
  5. package/lib/cjs/components/multichannel/index-types.d.ts +1 -0
  6. package/lib/cjs/components/multichannel/multichannel-text.js +53 -18
  7. package/lib/cjs/components/multichannel/multichannel-text.js.map +1 -1
  8. package/lib/cjs/components/multichannel/multichannel-utils.d.ts +2 -0
  9. package/lib/cjs/components/multichannel/multichannel-utils.js +3 -1
  10. package/lib/cjs/components/multichannel/multichannel-utils.js.map +1 -1
  11. package/lib/cjs/components/webchat-settings.d.ts +3 -10
  12. package/lib/cjs/components/webchat-settings.js +9 -14
  13. package/lib/cjs/components/webchat-settings.js.map +1 -1
  14. package/lib/cjs/components/whatsapp-button-list.d.ts +1 -1
  15. package/lib/cjs/util/environment.js +1 -1
  16. package/lib/cjs/util/environment.js.map +1 -1
  17. package/lib/cjs/webchat/webchat.js +3 -1
  18. package/lib/cjs/webchat/webchat.js.map +1 -1
  19. package/lib/esm/components/image.js +3 -1
  20. package/lib/esm/components/image.js.map +1 -1
  21. package/lib/esm/components/index-types.d.ts +7 -0
  22. package/lib/esm/components/index-types.js.map +1 -1
  23. package/lib/esm/components/multichannel/index-types.d.ts +1 -0
  24. package/lib/esm/components/multichannel/multichannel-text.js +55 -20
  25. package/lib/esm/components/multichannel/multichannel-text.js.map +1 -1
  26. package/lib/esm/components/multichannel/multichannel-utils.d.ts +2 -0
  27. package/lib/esm/components/multichannel/multichannel-utils.js +2 -0
  28. package/lib/esm/components/multichannel/multichannel-utils.js.map +1 -1
  29. package/lib/esm/components/webchat-settings.d.ts +3 -10
  30. package/lib/esm/components/webchat-settings.js +9 -13
  31. package/lib/esm/components/webchat-settings.js.map +1 -1
  32. package/lib/esm/components/whatsapp-button-list.d.ts +1 -1
  33. package/lib/esm/util/environment.js +1 -1
  34. package/lib/esm/util/environment.js.map +1 -1
  35. package/lib/esm/webchat/webchat.js +3 -1
  36. package/lib/esm/webchat/webchat.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/components/image.jsx +3 -1
  39. package/src/components/index-types.ts +7 -0
  40. package/src/components/multichannel/index-types.ts +1 -0
  41. package/src/components/multichannel/multichannel-text.jsx +99 -25
  42. package/src/components/multichannel/multichannel-utils.js +2 -0
  43. package/src/components/{webchat-settings.jsx → webchat-settings.tsx} +8 -8
  44. package/src/components/whatsapp-button-list.tsx +1 -1
  45. package/src/util/environment.js +1 -1
  46. package/src/webchat/webchat.jsx +4 -2
@@ -1,6 +1,8 @@
1
+ import { INPUT } from '@botonic/core/lib/esm/models/legacy-types'
1
2
  import React, { useContext } from 'react'
2
3
 
3
4
  import { RequestContext } from '../../contexts'
5
+ import { WhatsappButtonList } from '..'
4
6
  import { Text } from '../text'
5
7
  import { MultichannelFacebook } from './facebook/facebook'
6
8
  import { MultichannelButton } from './multichannel-button'
@@ -16,7 +18,9 @@ import {
16
18
  getMultichannelReplies,
17
19
  isFacebook,
18
20
  isWhatsapp,
21
+ MENU_BUTOON_WHATSAPP_BUTTON_LIST,
19
22
  MULTICHANNEL_WHATSAPP_PROPS,
23
+ WHATSAPP_LIST_MAX_BUTTONS,
20
24
  WHATSAPP_MAX_BUTTONS,
21
25
  } from './multichannel-utils'
22
26
  import { whatsappMarkdown } from './whatsapp/markdown'
@@ -55,8 +59,8 @@ export const MultichannelText = props => {
55
59
  const webviewButtons = []
56
60
  for (const button of getButtonsAndReplies()) {
57
61
  if (elementHasUrl(button)) urlButtons.push(button)
58
- if (elementHasPostback(button)) postbackButtons.push(button)
59
- if (elementHasWebview(button)) webviewButtons.push(button)
62
+ else if (elementHasWebview(button)) webviewButtons.push(button)
63
+ else if (elementHasPostback(button)) postbackButtons.push(button)
60
64
  }
61
65
  return { postbackButtons, urlButtons, webviewButtons }
62
66
  }
@@ -77,11 +81,14 @@ export const MultichannelText = props => {
77
81
  const asText =
78
82
  type === buttonTypes.POSTBACK ? postbackButtonsAsText : true
79
83
  const newline =
80
- multichannelContext.messageSeparator == null &&
84
+ multichannelContext.messageSeparator === null &&
81
85
  !newLineFirstButton &&
82
86
  i === 0
83
87
  ? ''
84
88
  : '\n'
89
+ if (type !== buttonTypes.POSTBACK && multichannelButton.props.payload) {
90
+ delete multichannelButton.props.payload
91
+ }
85
92
  return (
86
93
  <MultichannelButton
87
94
  key={`${type}${i}`}
@@ -96,14 +103,19 @@ export const MultichannelText = props => {
96
103
  return generator
97
104
  }
98
105
 
99
- const splitPostbackButtons = postbackButtons => {
106
+ const splitInWhatsappListButtons = postbackButtons => {
100
107
  const messages = []
101
- for (let i = 0; i < postbackButtons.length; i += WHATSAPP_MAX_BUTTONS) {
102
- messages.push(postbackButtons.slice(i, i + WHATSAPP_MAX_BUTTONS))
108
+ for (
109
+ let i = 0;
110
+ i < postbackButtons.length;
111
+ i += WHATSAPP_LIST_MAX_BUTTONS
112
+ ) {
113
+ messages.push(postbackButtons.slice(i, i + WHATSAPP_LIST_MAX_BUTTONS))
103
114
  }
104
115
  return messages
105
116
  }
106
117
 
118
+ // START WHATSAPP LOGIC
107
119
  if (isWhatsapp(requestContext)) {
108
120
  const texts = getText(props.children)
109
121
  const { postbackButtons, urlButtons, webviewButtons } = getWhatsappButtons()
@@ -120,45 +132,105 @@ export const MultichannelText = props => {
120
132
  const buttonsTextSeparator =
121
133
  props.buttonsTextSeparator || DEFAULT_WHATSAPP_MAX_BUTTON_SEPARATOR
122
134
 
135
+ //MORE THAN 3 BUTTONS
123
136
  if (
124
137
  !postbackButtonsAsText &&
125
138
  postbackButtons.length > WHATSAPP_MAX_BUTTONS
126
139
  ) {
140
+ const menuButtonTextWhatsappList =
141
+ props.menuButtonTextWhatsappList || MENU_BUTOON_WHATSAPP_BUTTON_LIST
142
+
127
143
  const urlButtonElements = urlButtons.map(
128
144
  regenerateMultichannelButtons(!!texts.length)
129
145
  )
130
146
  const postbackButtonElements = postbackButtons.map(
131
147
  regenerateMultichannelButtons(!!texts.length || !!urlButtons.length)
132
148
  )
133
- const messagesPostbackButtons = splitPostbackButtons(
149
+
150
+ const messagesPostbackButtonList = splitInWhatsappListButtons(
134
151
  postbackButtonElements
135
152
  )
136
153
 
137
- const messages = messagesPostbackButtons.map((postbackButtons, i) => {
138
- if (i === 0) {
139
- return [].concat(
140
- ...textElements,
141
- ...urlButtonElements,
142
- ...postbackButtons
143
- )
144
- } else {
145
- return [].concat(buttonsTextSeparator, ...postbackButtons)
154
+ const messages = messagesPostbackButtonList.map(
155
+ (postbackButtons, index) => {
156
+ if (postbackButtons.length < 4) {
157
+ return {
158
+ type: INPUT.TEXT,
159
+ children: [...buttonsTextSeparator, ...postbackButtons],
160
+ }
161
+ }
162
+ const rows = postbackButtons.map(postbackButton => {
163
+ const row = {
164
+ id: postbackButton.props.path
165
+ ? `__PATH_PAYLOAD__${postbackButton.props.path}`
166
+ : postbackButton.props.payload,
167
+ title: postbackButton.props.children,
168
+ }
169
+ console.log({ row })
170
+ return row
171
+ })
172
+ const whatsbuttonlistProps = {
173
+ body: index === 0 ? textElements : buttonsTextSeparator,
174
+ button: menuButtonTextWhatsappList,
175
+ sections: [{ rows }],
176
+ }
177
+
178
+ return {
179
+ type: INPUT.WHATSAPP_BUTTON_LIST,
180
+ props: whatsbuttonlistProps,
181
+ }
146
182
  }
147
- })
148
- if (webviewButtonElements.length) {
149
- messages.push([buttonsTextSeparator, ...webviewButtonElements])
150
- }
183
+ )
184
+
185
+ const messageWithUrlButtonElements = (
186
+ <Text
187
+ key={`msg-with-url-button`}
188
+ {...MULTICHANNEL_WHATSAPP_PROPS}
189
+ {...props}
190
+ >
191
+ {urlButtonElements}
192
+ </Text>
193
+ )
194
+
195
+ const messageWithWebviewButtonElements = (
196
+ <Text
197
+ key={`msg-with-webview-button`}
198
+ {...MULTICHANNEL_WHATSAPP_PROPS}
199
+ {...props}
200
+ >
201
+ {buttonsTextSeparator}
202
+ {webviewButtonElements}
203
+ </Text>
204
+ )
151
205
 
152
206
  return (
153
207
  <>
154
- {messages.map((message, i) => (
155
- <Text key={i} {...MULTICHANNEL_WHATSAPP_PROPS} {...props}>
156
- {message}
157
- </Text>
158
- ))}
208
+ {messages.map((message, i) => {
209
+ if (message.type === INPUT.WHATSAPP_BUTTON_LIST)
210
+ return (
211
+ <WhatsappButtonList
212
+ key={`msg-${i}-whatsapp-list`}
213
+ {...message.props}
214
+ />
215
+ )
216
+ return (
217
+ <Text
218
+ key={`msg-${i}-with-postback-buttons`}
219
+ {...MULTICHANNEL_WHATSAPP_PROPS}
220
+ {...props}
221
+ >
222
+ {message.children}
223
+ </Text>
224
+ )
225
+ })}
226
+ {urlButtonElements.length ? messageWithUrlButtonElements : null}
227
+ {webviewButtonElements.length
228
+ ? messageWithWebviewButtonElements
229
+ : null}
159
230
  </>
160
231
  )
161
232
  }
233
+ // END LOGIC WHATSAPP WITH MORE THAN 3 BUTTONS
162
234
 
163
235
  multichannelContext.currentIndex = getDefaultIndex()
164
236
  const postbackButtonElements = postbackButtons.map(
@@ -192,7 +264,9 @@ export const MultichannelText = props => {
192
264
 
193
265
  return <>{messages}</>
194
266
  }
267
+ // END WHATSAPP LOGIC
195
268
 
269
+ // START FACEBOOK LOGIC
196
270
  if (isFacebook(requestContext)) {
197
271
  const text = getText(props.children)
198
272
  const multichannelFacebook = new MultichannelFacebook()
@@ -8,8 +8,10 @@ import { Providers } from '@botonic/core'
8
8
  export const MULTICHANNEL_WHATSAPP_PROPS = { markdown: false }
9
9
 
10
10
  export const WHATSAPP_MAX_BUTTONS = 3
11
+ export const WHATSAPP_LIST_MAX_BUTTONS = 10
11
12
  export const WHATSAPP_MAX_BUTTON_CHARS = 20
12
13
  export const DEFAULT_WHATSAPP_MAX_BUTTON_SEPARATOR = 'More options:'
14
+ export const MENU_BUTOON_WHATSAPP_BUTTON_LIST = 'Menu'
13
15
 
14
16
  export function isMultichannelButton(node) {
15
17
  return isNodeKind(node, 'MultichannelButton')
@@ -4,6 +4,7 @@ import React, { useContext } from 'react'
4
4
  import { WebchatContext } from '../contexts'
5
5
  import { renderComponent } from '../util/react'
6
6
  import { stringifyWithRegexs } from '../util/regexs'
7
+ import { WebchatSettingsProps } from '.'
7
8
 
8
9
  export const WebchatSettings = ({
9
10
  theme,
@@ -13,7 +14,7 @@ export const WebchatSettings = ({
13
14
  enableAttachments,
14
15
  enableUserInput,
15
16
  enableAnimations,
16
- }) => {
17
+ }: WebchatSettingsProps) => {
17
18
  const renderBrowser = () => {
18
19
  // eslint-disable-next-line react-hooks/rules-of-hooks
19
20
  const { updateWebchatDevSettings } = useContext(WebchatContext)
@@ -39,16 +40,17 @@ export const WebchatSettings = ({
39
40
  enableAnimations,
40
41
  })
41
42
  return (
43
+ //@ts-ignore
42
44
  <message
43
45
  type={INPUT.WEBCHAT_SETTINGS}
44
46
  settings={stringifyWithRegexs({ theme: updatedTheme })}
45
- ></message>
47
+ />
46
48
  )
47
49
  }
48
50
  return renderComponent({ renderBrowser, renderNode })
49
51
  }
50
52
 
51
- export const normalizeWebchatSettings = settings => {
53
+ export const normalizeWebchatSettings = (settings: WebchatSettingsProps) => {
52
54
  let {
53
55
  theme,
54
56
  blockInputs,
@@ -60,9 +62,7 @@ export const normalizeWebchatSettings = settings => {
60
62
  } = settings
61
63
  if (!theme) theme = {}
62
64
  if (!theme.userInput) theme.userInput = {}
63
- if (!theme.animations) theme.animations = {}
64
65
  if (persistentMenu !== undefined) {
65
- if (!theme.userInput.persistentMenu) theme.userInput.persistentMenu = {}
66
66
  theme.userInput.persistentMenu = persistentMenu
67
67
  }
68
68
  if (enableEmojiPicker !== undefined) {
@@ -74,13 +74,13 @@ export const normalizeWebchatSettings = settings => {
74
74
  theme.userInput.attachments.enable = enableAttachments
75
75
  }
76
76
  if (enableUserInput !== undefined) {
77
- if (!theme.userInput.enable) theme.userInput.enable = {}
78
77
  theme.userInput.enable = enableUserInput
79
78
  }
79
+ if (blockInputs !== undefined) theme.userInput.blockInputs = blockInputs
80
+
81
+ if (!theme.animations) theme.animations = {}
80
82
  if (enableAnimations !== undefined) {
81
- if (!theme.animations.enable) theme.animations.enable = {}
82
83
  theme.animations.enable = enableAnimations
83
84
  }
84
- if (blockInputs !== undefined) theme.userInput.blockInputs = blockInputs
85
85
  return theme
86
86
  }
@@ -14,7 +14,7 @@ export interface WhatsappButtonListSectionProps {
14
14
  export interface WhatsappButtonListRowProps {
15
15
  id: string
16
16
  title: string
17
- description: string
17
+ description?: string
18
18
  }
19
19
 
20
20
  export interface WhatsappButtonListProps {
@@ -24,7 +24,7 @@ export const resolveImage = src => {
24
24
 
25
25
  export const isURL = urlPath => {
26
26
  // @stephenhay (38 chars) from: https://mathiasbynens.be/demo/url-regex
27
- const pattern = new RegExp(/^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/)
27
+ const pattern = new RegExp(/^(blob:)?(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/)
28
28
  return !!pattern.test(urlPath)
29
29
  }
30
30
 
@@ -496,8 +496,10 @@ export const Webchat = forwardRef((props, ref) => {
496
496
  from: SENDERS.user,
497
497
  src: temporaryDisplayUrl,
498
498
  }
499
- if (isImage(input)) messageComponent = <Image {...mediaProps} />
500
- else if (isAudio(input)) messageComponent = <Audio {...mediaProps} />
499
+ if (isImage(input)) {
500
+ mediaProps.input = input
501
+ messageComponent = <Image {...mediaProps} />
502
+ } else if (isAudio(input)) messageComponent = <Audio {...mediaProps} />
501
503
  else if (isVideo(input)) messageComponent = <Video {...mediaProps} />
502
504
  else if (isDocument(input))
503
505
  messageComponent = <Document {...mediaProps} />