@botonic/react 0.20.1 → 0.20.4

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 (52) hide show
  1. package/lib/app.js +4 -3
  2. package/lib/app.js.map +1 -1
  3. package/lib/components/button.js +30 -2
  4. package/lib/components/button.js.map +1 -1
  5. package/lib/components/buttons-disabler.js +2 -2
  6. package/lib/components/carousel.js +2 -2
  7. package/lib/components/custom-message.js +2 -2
  8. package/lib/components/document.js +2 -2
  9. package/lib/components/image.js +47 -5
  10. package/lib/components/image.js.map +1 -1
  11. package/lib/components/index.d.ts +7 -3
  12. package/lib/components/message.js +2 -2
  13. package/lib/components/multichannel/facebook/facebook.js +2 -2
  14. package/lib/components/reply.js +2 -2
  15. package/lib/components/subtitle.js +2 -2
  16. package/lib/components/text.js +2 -2
  17. package/lib/components/timestamps.js +2 -2
  18. package/lib/components/title.js +2 -2
  19. package/lib/constants.js +1 -0
  20. package/lib/constants.js.map +1 -1
  21. package/lib/dev-app.js +2 -2
  22. package/lib/index.d.ts +9 -10
  23. package/lib/node-app.js +2 -2
  24. package/lib/react-bot.js +2 -2
  25. package/lib/util/error-boundary.js +2 -2
  26. package/lib/webchat/actions.js +3 -1
  27. package/lib/webchat/actions.js.map +1 -1
  28. package/lib/webchat/header.js +2 -2
  29. package/lib/webchat/hooks.js +11 -2
  30. package/lib/webchat/hooks.js.map +1 -1
  31. package/lib/webchat/message-list.js +2 -2
  32. package/lib/webchat/messages-reducer.js +2 -2
  33. package/lib/webchat/replies.js +2 -2
  34. package/lib/webchat/session-view.js +2 -2
  35. package/lib/webchat/webchat-reducer.js +8 -2
  36. package/lib/webchat/webchat-reducer.js.map +1 -1
  37. package/lib/webchat/webchat.js +25 -6
  38. package/lib/webchat/webchat.js.map +1 -1
  39. package/lib/webchat/webview.js +2 -2
  40. package/lib/webchat-app.js +21 -4
  41. package/lib/webchat-app.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/components/button.jsx +21 -1
  44. package/src/components/image.jsx +33 -4
  45. package/src/components/index.d.ts +7 -3
  46. package/src/constants.js +1 -0
  47. package/src/index.d.ts +9 -10
  48. package/src/webchat/actions.jsx +1 -0
  49. package/src/webchat/hooks.js +8 -0
  50. package/src/webchat/webchat-reducer.js +4 -0
  51. package/src/webchat/webchat.jsx +24 -6
  52. package/src/webchat-app.jsx +19 -5
@@ -102,13 +102,17 @@ export interface PersistentMenuProps {
102
102
  options: any
103
103
  }
104
104
 
105
- export type BlockInputOption = { match: RegExp[]; message: string }
105
+ export type BlockInputOption = {
106
+ preprocess?: (message: string) => string
107
+ match: RegExp[]
108
+ message: string
109
+ }
106
110
 
107
111
  export interface BlobProps {
108
112
  blobTick?: boolean
109
113
  blobTickStyle?: any
110
114
  blobWidth?: string
111
- imagestyle?: any
115
+ imageStyle?: any
112
116
  }
113
117
 
114
118
  export interface ScrollbarProps {
@@ -185,7 +189,7 @@ export interface ThemeProps extends StyleProp {
185
189
  }
186
190
 
187
191
  export interface CoverComponentOptions {
188
- component: React.Component<CoverComponentProps>
192
+ component: React.ComponentType<CoverComponentProps>
189
193
  props?: any
190
194
  }
191
195
 
package/src/constants.js CHANGED
@@ -65,6 +65,7 @@ export const WEBCHAT = {
65
65
  enableAnimations: 'animations.enable',
66
66
  markdownStyle: 'markdownStyle',
67
67
  scrollbar: 'scrollbar',
68
+ imagePreviewer: 'imagePreviewer',
68
69
  // Mobile
69
70
  mobileBreakpoint: 'mobileBreakpoint',
70
71
  mobileStyle: 'mobileStyle',
package/src/index.d.ts CHANGED
@@ -25,10 +25,6 @@ export interface Route extends core.Route {
25
25
  }
26
26
  type Routes = core.Routes<Route>
27
27
 
28
- export interface BotOptions extends core.BotOptions {
29
- routes: Routes
30
- }
31
-
32
28
  export class ReactBot extends core.CoreBot {
33
29
  renderReactActions({
34
30
  actions,
@@ -37,7 +33,7 @@ export class ReactBot extends core.CoreBot {
37
33
  }
38
34
 
39
35
  export class NodeApp {
40
- constructor(options: Omit<BotOptions, 'renderer'>)
36
+ constructor(options: Omit<core.CoreBotConfig, 'renderer'>)
41
37
  bot: ReactBot
42
38
  input(request: core.BotRequest): Promise<BotResponse>
43
39
  renderNode(args): string
@@ -116,7 +112,7 @@ export interface WebchatArgs {
116
112
  onOpen?: (app: WebchatApp, args: any) => void
117
113
  onConnectionChange?: (app: WebchatApp, isOnline: boolean) => void
118
114
  persistentMenu?: PersistentMenuTheme
119
- storage?: Storage
115
+ storage?: Storage | null
120
116
  storageKey?: any
121
117
  theme?: ThemeProps
122
118
  }
@@ -175,6 +171,7 @@ export class WebchatApp {
175
171
  clearMessages(): void
176
172
  close(): void
177
173
  closeCoverComponent(): void
174
+ destroy(): void
178
175
  getComponent(
179
176
  host: HTMLElement,
180
177
  optionsAtRuntime?: WebchatAppArgs
@@ -191,7 +188,7 @@ export class WebchatApp {
191
188
  onUserInput(args: OnUserInputArgs): Promise<void>
192
189
  open(): void
193
190
  openCoverComponent(): void
194
- render(dest: HTMLElement, optionsAtRuntime: WebchatAppArgs): void
191
+ render(dest?: HTMLElement, optionsAtRuntime?: WebchatAppArgs): void
195
192
  resendUnsentInputs(): Promise<void>
196
193
  resolveWebchatVisibility(optionsAtRuntime: {
197
194
  appId: string
@@ -202,12 +199,14 @@ export class WebchatApp {
202
199
  toggleCoverComponent(): void
203
200
  updateMessageInfo(msgId: string, messageInfo: MessageInfo): void
204
201
  updateLastMessageDate(date: string): void
205
- updateUser(user: core.SessionUser): void
202
+ updateUser(user: Partial<core.SessionUser>): void
206
203
  updateWebchatSettings(settings: WebchatSettingsProps): void
204
+ renderCustomComponent(customComponent: React.ReactNode): void
205
+ unmountCustomComponent(): void
207
206
  }
208
207
 
209
208
  export interface WebchatContextProps {
210
- sendText: (text: string) => void
209
+ sendText: (text: string, payload?: string) => void
211
210
  sendAttachment: (attachment: File) => void
212
211
  sendPayload: (payload: string) => void
213
212
  sendInput: (input: core.Input) => void
@@ -223,7 +222,7 @@ export interface WebchatContextProps {
223
222
  theme: ThemeProps
224
223
  webchatState: WebchatState
225
224
  updateWebchatDevSettings: (settings: WebchatSettingsProps) => void
226
- updateUser: (user: core.SessionUser) => void
225
+ updateUser: (user: Partial<core.SessionUser>) => void
227
226
  }
228
227
  export const WebchatContext: React.Context<WebchatContextProps>
229
228
  export type WebchatContext = React.Context<WebchatContextProps>
@@ -14,6 +14,7 @@ export const TOGGLE_WEBCHAT = 'toggleWebchat'
14
14
  export const TOGGLE_EMOJI_PICKER = 'toggleEmojiPicker'
15
15
  export const TOGGLE_PERSISTENT_MENU = 'togglePersistentMenu'
16
16
  export const TOGGLE_COVER_COMPONENT = 'toggleCoverComponent'
17
+ export const DO_RENDER_CUSTOM_COMPONENT = 'doRenderCustomComponent'
17
18
  export const SET_ERROR = 'setError'
18
19
  export const CLEAR_MESSAGES = 'clearMessages'
19
20
  export const UPDATE_LAST_MESSAGE_DATE = 'updateLastMessageDate'
@@ -6,6 +6,7 @@ import {
6
6
  ADD_MESSAGE,
7
7
  ADD_MESSAGE_COMPONENT,
8
8
  CLEAR_MESSAGES,
9
+ DO_RENDER_CUSTOM_COMPONENT,
9
10
  SET_CURRENT_ATTACHMENT,
10
11
  SET_ERROR,
11
12
  SET_ONLINE,
@@ -59,6 +60,7 @@ export const webchatInitialState = {
59
60
  isEmojiPickerOpen: false,
60
61
  isPersistentMenuOpen: false,
61
62
  isCoverComponentOpen: false,
63
+ isCustomComponentRendered: false,
62
64
  lastMessageUpdate: undefined,
63
65
  currentAttachment: undefined,
64
66
  jwt: null,
@@ -137,6 +139,11 @@ export function useWebchat() {
137
139
  type: TOGGLE_COVER_COMPONENT,
138
140
  payload: toggle,
139
141
  })
142
+ const doRenderCustomComponent = toggle =>
143
+ webchatDispatch({
144
+ type: DO_RENDER_CUSTOM_COMPONENT,
145
+ payload: toggle,
146
+ })
140
147
  const setError = error =>
141
148
  webchatDispatch({
142
149
  type: SET_ERROR,
@@ -192,6 +199,7 @@ export function useWebchat() {
192
199
  toggleEmojiPicker,
193
200
  togglePersistentMenu,
194
201
  toggleCoverComponent,
202
+ doRenderCustomComponent,
195
203
  setError,
196
204
  setOnline,
197
205
  clearMessages,
@@ -1,4 +1,5 @@
1
1
  import {
2
+ DO_RENDER_CUSTOM_COMPONENT,
2
3
  SET_CURRENT_ATTACHMENT,
3
4
  SET_ERROR,
4
5
  SET_ONLINE,
@@ -18,6 +19,7 @@ import {
18
19
  } from './actions'
19
20
  import { messagesReducer } from './messages-reducer'
20
21
 
22
+ // eslint-disable-next-line complexity
21
23
  export function webchatReducer(state, action) {
22
24
  switch (action.type) {
23
25
  case UPDATE_WEBVIEW:
@@ -41,6 +43,8 @@ export function webchatReducer(state, action) {
41
43
  return { ...state, isPersistentMenuOpen: action.payload }
42
44
  case TOGGLE_COVER_COMPONENT:
43
45
  return { ...state, isCoverComponentOpen: action.payload }
46
+ case DO_RENDER_CUSTOM_COMPONENT:
47
+ return { ...state, isCustomComponentRendered: action.payload }
44
48
  case SET_ERROR:
45
49
  return { ...state, error: action.payload || {} }
46
50
  case SET_ONLINE:
@@ -6,6 +6,7 @@ import React, {
6
6
  useEffect,
7
7
  useImperativeHandle,
8
8
  useRef,
9
+ useState,
9
10
  } from 'react'
10
11
  import Textarea from 'react-textarea-autosize'
11
12
  import styled, { StyleSheetManager } from 'styled-components'
@@ -183,6 +184,7 @@ export const Webchat = forwardRef((props, ref) => {
183
184
  toggleEmojiPicker,
184
185
  togglePersistentMenu,
185
186
  toggleCoverComponent,
187
+ doRenderCustomComponent,
186
188
  setError,
187
189
  setOnline,
188
190
  clearMessages,
@@ -199,16 +201,14 @@ export const Webchat = forwardRef((props, ref) => {
199
201
  const { initialSession, initialDevSettings, onStateChange } = props
200
202
  const getThemeProperty = _getThemeProperty(theme)
201
203
 
202
- const storage = props.storage === undefined ? localStorage : props.storage
204
+ const [customComponent, setCustomComponent] = useState(null)
205
+ const storage = props.storage
203
206
  const storageKey =
204
207
  typeof props.storageKey === 'function'
205
208
  ? props.storageKey()
206
209
  : props.storageKey
207
210
 
208
- const [botonicState, saveState] = useStorageState(
209
- storage,
210
- storageKey || WEBCHAT.DEFAULTS.STORAGE_KEY
211
- )
211
+ const [botonicState, saveState] = useStorageState(storage, storageKey)
212
212
 
213
213
  const host = props.host || document.body
214
214
 
@@ -402,9 +402,13 @@ export const Webchat = forwardRef((props, ref) => {
402
402
  )
403
403
 
404
404
  const getBlockInputs = (rule, inputData) => {
405
+ const processedInput = rule.preprocess
406
+ ? rule.preprocess(inputData)
407
+ : inputData
408
+
405
409
  return rule.match.some(regex => {
406
410
  if (typeof regex === 'string') regex = deserializeRegex(regex)
407
- return regex.test(inputData)
411
+ return regex.test(processedInput)
408
412
  })
409
413
  }
410
414
 
@@ -559,6 +563,11 @@ export const Webchat = forwardRef((props, ref) => {
559
563
  toggleWebchat: () => toggleWebchat(!webchatState.isWebchatOpen),
560
564
  openCoverComponent: () => toggleCoverComponent(true),
561
565
  closeCoverComponent: () => toggleCoverComponent(false),
566
+ renderCustomComponent: _customComponent => {
567
+ setCustomComponent(_customComponent)
568
+ doRenderCustomComponent(true)
569
+ },
570
+ unmountCustomComponent: () => doRenderCustomComponent(false),
562
571
  toggleCoverComponent: () =>
563
572
  toggleCoverComponent(!webchatState.isCoverComponentOpen),
564
573
  openWebviewApi: component => openWebviewT(component),
@@ -886,6 +895,11 @@ export const Webchat = forwardRef((props, ref) => {
886
895
  )
887
896
  }
888
897
 
898
+ const _renderCustomComponent = () => {
899
+ if (!customComponent) return <></>
900
+ else return customComponent
901
+ }
902
+
889
903
  const WebchatComponent = (
890
904
  <WebchatContext.Provider
891
905
  value={{
@@ -916,6 +930,7 @@ export const Webchat = forwardRef((props, ref) => {
916
930
  {triggerButton()}
917
931
  </div>
918
932
  )}
933
+
919
934
  {webchatState.isWebchatOpen && (
920
935
  <StyledWebchat
921
936
  // TODO: Distinguis between multiple instances of webchat, e.g. `${uniqueId}-botonic-webchat`
@@ -948,6 +963,9 @@ export const Webchat = forwardRef((props, ref) => {
948
963
  {!webchatState.handoff && userInputArea()}
949
964
  {webchatState.webview && webchatWebview()}
950
965
  {webchatState.isCoverComponentOpen && coverComponent()}
966
+ {webchatState.isCustomComponentRendered &&
967
+ customComponent &&
968
+ _renderCustomComponent()}
951
969
  </StyledWebchat>
952
970
  )}
953
971
  </WebchatContext.Provider>
@@ -1,7 +1,7 @@
1
1
  import { HubtypeService, INPUT } from '@botonic/core'
2
2
  import merge from 'lodash.merge'
3
3
  import React, { createRef } from 'react'
4
- import { render } from 'react-dom'
4
+ import { render, unmountComponentAtNode } from 'react-dom'
5
5
 
6
6
  import { SENDERS, WEBCHAT } from './constants'
7
7
  import { msgToBotonic } from './msg-to-botonic'
@@ -51,8 +51,8 @@ export class WebchatApp {
51
51
  this.hostId = hostId || WEBCHAT.DEFAULTS.HOST_ID
52
52
  this.defaultDelay = defaultDelay
53
53
  this.defaultTyping = defaultTyping
54
- this.storage = storage
55
- this.storageKey = storageKey
54
+ this.storage = storage === undefined ? localStorage : storage
55
+ this.storageKey = storageKey || WEBCHAT.DEFAULTS.STORAGE_KEY
56
56
  this.onInit = onInit
57
57
  this.onOpen = onOpen
58
58
  this.onClose = onClose
@@ -211,6 +211,14 @@ export class WebchatApp {
211
211
  this.webchatRef.current.closeCoverComponent()
212
212
  }
213
213
 
214
+ renderCustomComponent(_customComponent) {
215
+ this.webchatRef.current.renderCustomComponent(_customComponent)
216
+ }
217
+
218
+ unmountCustomComponent() {
219
+ this.webchatRef.current.unmountCustomComponent()
220
+ }
221
+
214
222
  toggleCoverComponent() {
215
223
  this.webchatRef.current.toggleCoverComponent()
216
224
  }
@@ -278,9 +286,9 @@ export class WebchatApp {
278
286
  enableAnimations = enableAnimations || this.enableAnimations
279
287
  defaultDelay = defaultDelay || this.defaultDelay
280
288
  defaultTyping = defaultTyping || this.defaultTyping
281
- storage = storage || this.storage
282
- storageKey = storageKey || this.storageKey
283
289
  server = server || this.server
290
+ this.storage = storage || this.storage
291
+ this.storageKey = storageKey || this.storageKey
284
292
  this.onInit = onInit || this.onInit
285
293
  this.onOpen = onOpen || this.onOpen
286
294
  this.onClose = onClose || this.onClose
@@ -343,6 +351,12 @@ export class WebchatApp {
343
351
  return false
344
352
  }
345
353
 
354
+ destroy() {
355
+ if (this.hubtypeService) this.hubtypeService.destroyPusher()
356
+ unmountComponentAtNode(this.host)
357
+ if (this.storage) this.storage.removeItem(this.storageKey)
358
+ }
359
+
346
360
  async render(dest, optionsAtRuntime = {}) {
347
361
  onDOMLoaded(async () => {
348
362
  const isVisible = await this.resolveWebchatVisibility(optionsAtRuntime)