@seamly/web-ui 24.5.0 → 25.1.0-beta.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 (154) hide show
  1. package/build/dist/lib/index.debug.js +2129 -1810
  2. package/build/dist/lib/index.debug.js.map +1 -1
  3. package/build/dist/lib/index.debug.min.js +1 -1
  4. package/build/dist/lib/index.debug.min.js.LICENSE.txt +49 -7
  5. package/build/dist/lib/index.debug.min.js.map +1 -1
  6. package/build/dist/lib/index.js +732 -398
  7. package/build/dist/lib/index.js.map +1 -1
  8. package/build/dist/lib/index.min.js +1 -1
  9. package/build/dist/lib/index.min.js.LICENSE.txt +16 -1
  10. package/build/dist/lib/index.min.js.map +1 -1
  11. package/build/dist/lib/style-guide.js +305 -93
  12. package/build/dist/lib/style-guide.js.map +1 -1
  13. package/build/dist/lib/style-guide.min.js +1 -1
  14. package/build/dist/lib/style-guide.min.js.map +1 -1
  15. package/build/dist/lib/styles-default-implementation.css +1 -1
  16. package/build/dist/lib/styles.css +1 -1
  17. package/package.json +27 -38
  18. package/src/javascripts/core/api/api.types.ts +3 -0
  19. package/src/javascripts/core/api/asyncapi.types.ts +292 -69
  20. package/src/javascripts/core/api/channel.types.ts +301 -69
  21. package/src/javascripts/core/api/conversation-connector.ts +1 -3
  22. package/src/javascripts/core/api/errors/seamly-api-error.ts +0 -1
  23. package/src/javascripts/core/api/errors/seamly-base-error.ts +1 -1
  24. package/src/javascripts/core/api/index.ts +7 -7
  25. package/src/javascripts/core/api/utils.ts +0 -1
  26. package/src/javascripts/core/domains/app/actions.ts +1 -1
  27. package/src/javascripts/core/domains/app/hooks.ts +1 -1
  28. package/src/javascripts/core/domains/config/hooks.ts +1 -1
  29. package/src/javascripts/core/domains/config/selectors.ts +1 -1
  30. package/src/javascripts/core/domains/config/slice.ts +2 -2
  31. package/src/javascripts/core/domains/forms/context.ts +1 -1
  32. package/src/javascripts/core/domains/forms/hooks.ts +12 -12
  33. package/src/javascripts/core/domains/forms/provider.tsx +9 -9
  34. package/src/javascripts/core/domains/i18n/actions.ts +1 -1
  35. package/src/javascripts/core/domains/i18n/hooks.ts +3 -3
  36. package/src/javascripts/core/domains/interrupt/hooks.ts +1 -1
  37. package/src/javascripts/core/domains/store/index.ts +2 -2
  38. package/src/javascripts/core/domains/store/slice.ts +47 -34
  39. package/src/javascripts/core/domains/store/store.types.ts +3 -7
  40. package/src/javascripts/core/domains/translations/components/options-button.tsx +2 -2
  41. package/src/javascripts/core/domains/translations/components/options-dialog/index.tsx +1 -1
  42. package/src/javascripts/core/domains/translations/components/options-dialog/translation-option.tsx +1 -1
  43. package/src/javascripts/core/domains/translations/components/options-dialog/translation-options.tsx +2 -2
  44. package/src/javascripts/core/domains/translations/components/translation-status.tsx +1 -1
  45. package/src/javascripts/core/domains/translations/hooks.ts +2 -2
  46. package/src/javascripts/core/domains/translations/middleware.ts +4 -2
  47. package/src/javascripts/core/domains/visibility/actions.ts +2 -2
  48. package/src/javascripts/core/domains/visibility/hooks.ts +5 -5
  49. package/src/javascripts/core/lib/debug.ts +1 -1
  50. package/src/javascripts/core/lib/engine/index.tsx +5 -5
  51. package/src/javascripts/core/lib/external-api/index.ts +6 -6
  52. package/src/javascripts/core/lib/mutex.ts +0 -1
  53. package/src/javascripts/core/lib/split-url-params.ts +1 -1
  54. package/src/javascripts/core/lib/store/index.ts +0 -1
  55. package/src/javascripts/core/lib/store/providers/app-storage.js +4 -7
  56. package/src/javascripts/core/lib/store/providers/app-storage.ts +4 -6
  57. package/src/javascripts/core/ui/components/app-options/index.tsx +1 -1
  58. package/src/javascripts/core/ui/components/chat-status/index.tsx +1 -1
  59. package/src/javascripts/core/ui/components/conversation/component-filter.tsx +1 -3
  60. package/src/javascripts/core/ui/components/conversation/conversation.tsx +9 -11
  61. package/src/javascripts/core/ui/components/conversation/event/card-component.tsx +3 -3
  62. package/src/javascripts/core/ui/components/conversation/event/carousel-component/components/pagination.tsx +1 -1
  63. package/src/javascripts/core/ui/components/conversation/event/carousel-component/index.tsx +1 -1
  64. package/src/javascripts/core/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +1 -1
  65. package/src/javascripts/core/ui/components/conversation/event/choice-prompt.tsx +5 -5
  66. package/src/javascripts/core/ui/components/conversation/event/conversation-suggestions.tsx +1 -1
  67. package/src/javascripts/core/ui/components/conversation/event/divider/variants/new-translation.tsx +3 -3
  68. package/src/javascripts/core/ui/components/conversation/event/divider/variants/time-indicator.tsx +1 -1
  69. package/src/javascripts/core/ui/components/conversation/event/event-participant.tsx +1 -1
  70. package/src/javascripts/core/ui/components/conversation/event/event.tsx +1 -1
  71. package/src/javascripts/core/ui/components/conversation/event/image-lightbox.tsx +1 -1
  72. package/src/javascripts/core/ui/components/conversation/event/image.tsx +2 -2
  73. package/src/javascripts/core/ui/components/conversation/event/participant.tsx +1 -1
  74. package/src/javascripts/core/ui/components/conversation/event/splash.tsx +0 -1
  75. package/src/javascripts/core/ui/components/conversation/event/text.tsx +2 -2
  76. package/src/javascripts/core/ui/components/conversation/event/upload.tsx +3 -3
  77. package/src/javascripts/core/ui/components/conversation/event/video.tsx +2 -2
  78. package/src/javascripts/core/ui/components/conversation/event-divider.tsx +1 -1
  79. package/src/javascripts/core/ui/components/conversation/message-container.tsx +2 -4
  80. package/src/javascripts/core/ui/components/conversation/use-chat-scroll.ts +3 -3
  81. package/src/javascripts/core/ui/components/core/seamly-activity-monitor.tsx +1 -1
  82. package/src/javascripts/core/ui/components/core/seamly-api-context.ts +1 -1
  83. package/src/javascripts/core/ui/components/core/seamly-core.tsx +3 -3
  84. package/src/javascripts/core/ui/components/core/seamly-event-subscriber.ts +9 -7
  85. package/src/javascripts/core/ui/components/core/seamly-file-upload.tsx +2 -3
  86. package/src/javascripts/core/ui/components/core/seamly-initializer.tsx +1 -1
  87. package/src/javascripts/core/ui/components/core/seamly-instance-functions-loader.ts +3 -3
  88. package/src/javascripts/core/ui/components/core/seamly-live-region.tsx +1 -1
  89. package/src/javascripts/core/ui/components/core/seamly-new-notifications.ts +1 -1
  90. package/src/javascripts/core/ui/components/core/seamly-read-state.ts +1 -1
  91. package/src/javascripts/core/ui/components/entry/entry-container.tsx +8 -3
  92. package/src/javascripts/core/ui/components/entry/text-entry/hooks.ts +21 -14
  93. package/src/javascripts/core/ui/components/entry/text-entry/index.tsx +1 -1
  94. package/src/javascripts/core/ui/components/entry/text-entry/text-entry-form.tsx +1 -1
  95. package/src/javascripts/core/ui/components/entry/upload/file-upload-form.tsx +1 -1
  96. package/src/javascripts/core/ui/components/entry/upload/index.tsx +1 -1
  97. package/src/javascripts/core/ui/components/entry/upload-toggle.tsx +2 -1
  98. package/src/javascripts/core/ui/components/form-controls/error.tsx +1 -1
  99. package/src/javascripts/core/ui/components/form-controls/file-input.tsx +1 -1
  100. package/src/javascripts/core/ui/components/form-controls/input.tsx +1 -1
  101. package/src/javascripts/core/ui/components/form-controls/wrapper.tsx +1 -1
  102. package/src/javascripts/core/ui/components/layout/agent-info.tsx +1 -1
  103. package/src/javascripts/core/ui/components/layout/chat-frame.tsx +1 -1
  104. package/src/javascripts/core/ui/components/layout/chat.tsx +8 -6
  105. package/src/javascripts/core/ui/components/layout/continue-chat-messages.tsx +1 -1
  106. package/src/javascripts/core/ui/components/layout/header.tsx +1 -1
  107. package/src/javascripts/core/ui/components/layout/interrupt.tsx +1 -1
  108. package/src/javascripts/core/ui/components/layout/pre-chat-messages.tsx +1 -1
  109. package/src/javascripts/core/ui/components/options/options-button.tsx +1 -3
  110. package/src/javascripts/core/ui/components/options/options-frame.tsx +1 -1
  111. package/src/javascripts/core/ui/components/options/transcript/index.tsx +1 -1
  112. package/src/javascripts/core/ui/components/suggestions/index.tsx +2 -2
  113. package/src/javascripts/core/ui/components/suggestions/suggestions-list.tsx +1 -1
  114. package/src/javascripts/core/ui/components/view/index.tsx +3 -3
  115. package/src/javascripts/core/ui/components/view/window-view/collapse-button.tsx +10 -1
  116. package/src/javascripts/core/ui/components/view/window-view/window-open-button.tsx +9 -3
  117. package/src/javascripts/core/ui/components/widgets/in-out-transition.tsx +2 -2
  118. package/src/javascripts/core/ui/components/widgets/lightbox.tsx +1 -1
  119. package/src/javascripts/core/ui/hooks/file-upload-hooks.ts +1 -1
  120. package/src/javascripts/core/ui/hooks/focus-helper-hooks.ts +6 -1
  121. package/src/javascripts/core/ui/hooks/seamly-entry-hooks.ts +1 -1
  122. package/src/javascripts/core/ui/hooks/seamly-option-hooks.ts +1 -1
  123. package/src/javascripts/core/ui/hooks/seamly-state-hooks.ts +9 -4
  124. package/src/javascripts/core/ui/hooks/use-debounce.ts +1 -1
  125. package/src/javascripts/core/ui/hooks/use-interval.ts +0 -1
  126. package/src/javascripts/core/ui/hooks/use-notifications.ts +2 -3
  127. package/src/javascripts/core/ui/hooks/use-seamly-chat.ts +2 -2
  128. package/src/javascripts/core/ui/hooks/use-seamly-commands.ts +2 -2
  129. package/src/javascripts/core/ui/hooks/use-seamly-conversation.ts +1 -1
  130. package/src/javascripts/core/ui/hooks/use-seamly-idle-detach-countdown.ts +15 -10
  131. package/src/javascripts/core/ui/hooks/use-session-expired-command.ts +1 -1
  132. package/src/javascripts/core/ui/hooks/use-single-file-upload.ts +1 -1
  133. package/src/javascripts/core/ui/hooks/utility-hooks.ts +1 -2
  134. package/src/javascripts/core/ui/utils/seamly-utils.ts +0 -2
  135. package/src/javascripts/core/ui/utils/validations.ts +1 -2
  136. package/src/javascripts/style-guide/components/app.tsx +2 -2
  137. package/src/javascripts/style-guide/components/static-core.tsx +2 -2
  138. package/src/javascripts/style-guide/components/view.tsx +1 -1
  139. package/src/javascripts/style-guide/state-helpers/index.ts +0 -2
  140. package/src/javascripts/style-guide/states.ts +5 -42
  141. package/src/javascripts/style-guide/style-guide-engine.tsx +1 -1
  142. package/src/stylesheets/5-components/_message-body.scss +0 -10
  143. package/src/stylesheets/6-default-implementation/_hover.scss +0 -7
  144. package/src/stylesheets/styles.scss +0 -1
  145. package/webpack/config.common.js +4 -11
  146. package/webpack/config.dev.js +0 -1
  147. package/webpack/config.package.js +5 -7
  148. package/webpack/config.site.js +2 -4
  149. package/webpack/config.test.js +1 -2
  150. package/webpack/defaults.js +0 -1
  151. package/webpack/parts/babel-loader-browser-plugins.js +0 -1
  152. package/webpack/parts/dev-server.js +0 -1
  153. package/src/javascripts/core/ui/components/conversation/event/cta.tsx +0 -54
  154. package/src/stylesheets/5-components/_message-cta.scss +0 -17
@@ -1,5 +1,5 @@
1
- import { createContext } from 'preact'
2
1
  import type { FormContextType } from 'domains/forms/forms.types'
2
+ import { createContext } from 'preact'
3
3
 
4
4
  const FormContext = createContext<FormContextType>({
5
5
  handleSubmit: () => undefined,
@@ -1,3 +1,15 @@
1
+ import type {
2
+ ControlState,
3
+ FormContextType,
4
+ FormControlName,
5
+ } from 'domains/forms/forms.types'
6
+ import {
7
+ getControlTouchedByName,
8
+ getControlValueByName,
9
+ getFormById,
10
+ } from 'domains/forms/selectors'
11
+ import { deregisterControl, registerControl } from 'domains/forms/slice'
12
+ import { useAppDispatch, type RootState } from 'domains/store'
1
13
  import {
2
14
  useCallback,
3
15
  useContext,
@@ -6,20 +18,8 @@ import {
6
18
  useMemo,
7
19
  } from 'preact/hooks'
8
20
  import { useSelector } from 'react-redux'
9
- import {
10
- getControlTouchedByName,
11
- getControlValueByName,
12
- getFormById,
13
- } from 'domains/forms/selectors'
14
- import { deregisterControl, registerControl } from 'domains/forms/slice'
15
- import { useAppDispatch, type RootState } from 'domains/store'
16
21
  import FormContext from './context'
17
22
  import { validate } from './utils'
18
- import type {
19
- ControlState,
20
- FormContextType,
21
- FormControlName,
22
- } from 'domains/forms/forms.types'
23
23
 
24
24
  export function useFormContext(): FormContextType {
25
25
  return useContext(FormContext)
@@ -1,12 +1,3 @@
1
- import { FC } from 'preact/compat'
2
- import {
3
- useCallback,
4
- useEffect,
5
- useLayoutEffect,
6
- useMemo,
7
- useState,
8
- } from 'preact/hooks'
9
- import { useSelector } from 'react-redux'
10
1
  import { setHasResponded } from 'domains/app/slice'
11
2
  import { Provider } from 'domains/forms/context'
12
3
  import { useValidations } from 'domains/forms/hooks'
@@ -18,6 +9,15 @@ import {
18
9
  registerForm,
19
10
  } from 'domains/forms/slice'
20
11
  import { useAppDispatch, type RootState } from 'domains/store'
12
+ import { FC } from 'preact/compat'
13
+ import {
14
+ useCallback,
15
+ useEffect,
16
+ useLayoutEffect,
17
+ useMemo,
18
+ useState,
19
+ } from 'preact/hooks'
20
+ import { useSelector } from 'react-redux'
21
21
 
22
22
  type FormProviderProps = {
23
23
  formId: string
@@ -1,6 +1,6 @@
1
1
  import { createAsyncThunk } from '@reduxjs/toolkit'
2
- import { ThunkAPI } from 'domains/redux/redux.types'
3
2
  import type { I18nState } from 'domains/i18n/i18n.types'
3
+ import { ThunkAPI } from 'domains/redux/redux.types'
4
4
 
5
5
  export const setLocale = createAsyncThunk<
6
6
  {
@@ -3,18 +3,18 @@ import {
3
3
  pluralTypeHandler,
4
4
  selectTypeHandler,
5
5
  } from '@ultraq/icu-message-formatter'
6
- import { useCallback } from 'preact/hooks'
7
- import { useSelector } from 'react-redux'
8
6
  import {
9
7
  selectInitialLocale,
10
8
  selectIsLoading,
11
9
  selectLocale,
12
10
  selectTranslations,
13
11
  } from 'domains/i18n/selectors'
12
+ import { useCallback } from 'preact/hooks'
13
+ import { useSelector } from 'react-redux'
14
14
  // pluralTypeHandler. Since we only use exact plural matches (=0, =1 etc) we can
15
15
  // safely use en-GB all the time.
16
16
  const formatter: {
17
- format: (_translation: string, _values: Object) => string
17
+ format: (_translation: string, _values: object) => string
18
18
  } = new MessageFormatter('en-GB', {
19
19
  plural: pluralTypeHandler,
20
20
  select: selectTypeHandler,
@@ -1,6 +1,6 @@
1
+ import { useI18n } from 'domains/i18n/hooks'
1
2
  import { useMemo } from 'preact/hooks'
2
3
  import { useSelector } from 'react-redux'
3
- import { useI18n } from 'domains/i18n/hooks'
4
4
  import { selectError, selectHasError } from './selectors'
5
5
 
6
6
  export function useInterrupt() {
@@ -1,6 +1,4 @@
1
1
  import { combineReducers, configureStore } from '@reduxjs/toolkit'
2
- import { Events } from 'minivents'
3
- import { useDispatch } from 'react-redux'
4
2
  import API from 'api'
5
3
  import { Config } from 'config.types'
6
4
  import appReducer from 'domains/app/slice'
@@ -15,6 +13,8 @@ import stateReducer from 'domains/store/slice'
15
13
  import createI18nMiddleware from 'domains/translations/middleware'
16
14
  import translationReducer from 'domains/translations/slice'
17
15
  import visibilityReducer from 'domains/visibility/slice'
16
+ import { Events } from 'minivents'
17
+ import { useDispatch } from 'react-redux'
18
18
 
19
19
  type CreateStore = {
20
20
  initialState: undefined
@@ -1,17 +1,11 @@
1
1
  import { PayloadAction, createSlice, isAnyOf } from '@reduxjs/toolkit'
2
2
  import { InitialChannelConversation } from 'api'
3
+ import type {
4
+ ChannelConversation,
5
+ ServiceAttachEntrySettings,
6
+ } from 'api/api.types'
3
7
  import { initializeApp, resetApp } from 'domains/app/actions'
4
8
  import { initializeConfig } from 'domains/config/actions'
5
- import { randomId } from 'lib/id'
6
- import { getTimeFromSeconds } from 'ui/utils/general-utils'
7
- import {
8
- entryTypes,
9
- eventTypes,
10
- featureKeys,
11
- payloadTypes,
12
- readStates,
13
- } from 'ui/utils/seamly-utils'
14
- import type { ChannelConversation } from 'api/api.types'
15
9
  import type {
16
10
  ChannelEvent,
17
11
  CurrentUploadPayload,
@@ -21,6 +15,15 @@ import type {
21
15
  ServiceInfo,
22
16
  StoreState,
23
17
  } from 'domains/store/store.types'
18
+ import { randomId } from 'lib/id'
19
+ import { getTimeFromSeconds } from 'ui/utils/general-utils'
20
+ import {
21
+ entryTypes,
22
+ eventTypes,
23
+ featureKeys,
24
+ payloadTypes,
25
+ readStates,
26
+ } from 'ui/utils/seamly-utils'
24
27
 
25
28
  export type AddEventPayload = ChannelEvent
26
29
 
@@ -106,29 +109,22 @@ export const calculateNewEntryMeta = (
106
109
  entryMeta: StoreState['entryMeta'],
107
110
  channelEvent?: ChannelEvent,
108
111
  ): EntryMeta => {
109
- // Events originating from the client should leave the entry meta as is
110
- if (channelEvent?.payload?.fromClient === true) {
112
+ // Events originating from the client, and incoming events that are not messages,
113
+ // should leave the entry meta as is.
114
+ if (
115
+ channelEvent?.payload?.fromClient === true ||
116
+ channelEvent?.type !== 'message'
117
+ ) {
111
118
  return entryMeta
112
119
  }
113
120
 
114
121
  const entry =
115
- channelEvent?.type === 'message'
116
- ? channelEvent?.payload.translatedEntry || channelEvent?.payload.entry
117
- : { options: undefined, type: undefined }
122
+ channelEvent?.payload?.translatedEntry || channelEvent?.payload?.entry
118
123
 
119
124
  const { blockAutoEntrySwitch } = entryMeta
120
125
  const actions = channelEvent?.payload?.actions || {}
121
126
  const translatedActions = channelEvent?.payload?.translatedActions || {}
122
127
 
123
- if (!entry) {
124
- return {
125
- ...entryMeta,
126
- actions,
127
- optionsOverride: {},
128
- translatedActions,
129
- }
130
- }
131
-
132
128
  const { type, options } = entry || {}
133
129
 
134
130
  let newActive: string | undefined = entryMeta.active
@@ -188,6 +184,7 @@ export const initialStoreState: StoreState = {
188
184
  skiplinkTargetId: randomId(),
189
185
  optionsButtonId: randomId(),
190
186
  headerCollapseButtonId: randomId(),
187
+ windowOpenButtonId: randomId(),
191
188
  serviceData: {},
192
189
  options: {
193
190
  features: {
@@ -222,7 +219,8 @@ export const storeSlice = createSlice({
222
219
  reducers: {
223
220
  addEvent: (state, action: PayloadAction<ChannelEvent>) => {
224
221
  const { type: eventType, payload } = action.payload
225
- const accountHasUploads = state.options.features.hasOwnProperty(
222
+ const accountHasUploads = Object.prototype.hasOwnProperty.call(
223
+ state.options.features,
226
224
  featureKeys.uploads,
227
225
  )
228
226
  let newOptions = { ...state.options }
@@ -379,11 +377,12 @@ export const storeSlice = createSlice({
379
377
  {
380
378
  ...state.entryMeta,
381
379
  ...entry,
382
- active: entry?.default || payloadTypes.text,
383
- // @ts-ignore
384
- options: { ...(entry?.options ? entry.options : {}) },
380
+ active: payloadTypes.text,
381
+ // @ts-expect-error This only has part of the upload related options set
382
+ options: { ...entry?.options },
385
383
  },
386
- events[events.length - 1],
384
+ // Only events of type 'message' can change the entry options
385
+ events.findLast((event) => event.type === 'message'),
387
386
  )
388
387
 
389
388
  let newFeatures = { ...state.options.features }
@@ -392,7 +391,8 @@ export const storeSlice = createSlice({
392
391
  (m) =>
393
392
  !m.payload.fromClient && ['message', 'participant'].includes(m.type),
394
393
  )
395
- const newFeaturesHasUpload = newFeatures.hasOwnProperty(
394
+ const newFeaturesHasUpload = Object.prototype.hasOwnProperty.call(
395
+ newFeatures,
396
396
  featureKeys.uploads,
397
397
  )
398
398
 
@@ -539,7 +539,12 @@ export const storeSlice = createSlice({
539
539
  })
540
540
  },
541
541
  setFeatureEnabledState: (state, { payload }) => {
542
- if (!state.options.features.hasOwnProperty(payload.key)) {
542
+ if (
543
+ !Object.prototype.hasOwnProperty.call(
544
+ state.options.features,
545
+ payload.key,
546
+ )
547
+ ) {
543
548
  return
544
549
  }
545
550
  state.options.features[payload.key].enabled = payload.enabled
@@ -567,9 +572,17 @@ export const storeSlice = createSlice({
567
572
  setBlockAutoEntrySwitch: (state, { payload }) => {
568
573
  state.entryMeta.blockAutoEntrySwitch = payload
569
574
  },
570
- setServiceEntryMetadata: (state, { payload }) => {
571
- state.entryMeta.active = payload.default
572
- state.entryMeta.options = payload.options || {}
575
+ setServiceEntryMetadata: (
576
+ state,
577
+ { payload }: PayloadAction<ServiceAttachEntrySettings>,
578
+ ) => {
579
+ state.entryMeta.options = {
580
+ ...state.entryMeta.options,
581
+ // @ts-expect-error This only has part of the upload related options set
582
+ upload: {
583
+ ...payload.options.upload,
584
+ },
585
+ }
573
586
  state.entryMeta.optionsOverride = {}
574
587
  state.entryMeta.actions = {}
575
588
  state.entryMeta.translatedActions = {}
@@ -1,5 +1,4 @@
1
1
  import { InitialChannelConversation } from 'api'
2
- import { entryTypes } from 'ui/utils/seamly-utils'
3
2
  import type {
4
3
  AsyncAPIComponents,
5
4
  ChannelComponents,
@@ -11,6 +10,7 @@ import type { FormState } from 'domains/forms/forms.types'
11
10
  import type { I18nState } from 'domains/i18n/i18n.types'
12
11
  import type { TranslationState } from 'domains/translations/translations.types'
13
12
  import type { VisibilityState } from 'domains/visibility/visibility.types'
13
+ import { entryTypes } from 'ui/utils/seamly-utils'
14
14
 
15
15
  export type DeepRequired<T> = { [P in keyof T]-?: DeepRequired<T[P]> }
16
16
 
@@ -95,10 +95,6 @@ export type MessageChoicePrompt = MessageType<
95
95
  ChannelComponentsSchemas['MessageBodyChoicePrompt'],
96
96
  'choice_prompt'
97
97
  >
98
- export type MessageCTA = MessageType<
99
- ChannelComponentsSchemas['MessageBodyCTA'],
100
- 'cta'
101
- >
102
98
 
103
99
  export type MessageCustom = MessageType<
104
100
  ChannelComponentsSchemas['MessageBodyCustom'],
@@ -129,7 +125,6 @@ export type MessageEvent =
129
125
  | MessageCard
130
126
  | MessageCarousel
131
127
  | MessageChoicePrompt
132
- | MessageCTA
133
128
  | MessageCustom
134
129
  | MessageImage
135
130
  | MessageText
@@ -251,6 +246,7 @@ export type StoreState = {
251
246
  skiplinkTargetId: string
252
247
  optionsButtonId: string
253
248
  headerCollapseButtonId: string
249
+ windowOpenButtonId: string
254
250
  serviceData: Record<
255
251
  string,
256
252
  AsyncAPIComponents['schemas']['ServiceData']['payload']
@@ -294,6 +290,6 @@ export type ReduxStore = {
294
290
  forms: FormState
295
291
  translations: TranslationState
296
292
  i18n: I18nState
297
- interrupt: {}
293
+ interrupt: object
298
294
  visibility: VisibilityState
299
295
  }
@@ -1,13 +1,13 @@
1
+ import { className } from 'lib/css'
1
2
  import { ComponentChildren } from 'preact'
2
3
  import { useRef, useState } from 'preact/hooks'
3
- import { className } from 'lib/css'
4
+ import type { FramePosition } from 'ui/components/options/options-frame'
4
5
  import InOutTransition, {
5
6
  transitionStartStates,
6
7
  } from 'ui/components/widgets/in-out-transition'
7
8
  import { useGeneratedId } from 'ui/hooks/seamly-hooks'
8
9
  import { focusElement, getKey, keyNames } from 'ui/utils/general-utils'
9
10
  import TranslationsOptionsDialog from './options-dialog'
10
- import type { FramePosition } from 'ui/components/options/options-frame'
11
11
 
12
12
  type TranslationsOptionsButtonProps = {
13
13
  children: ComponentChildren
@@ -1,8 +1,8 @@
1
1
  import { useI18n } from 'domains/i18n/hooks'
2
2
  import TranslationOptions from 'domains/translations/components/options-dialog/translation-options'
3
3
  import OptionsFrame from 'ui/components/options/options-frame'
4
- import { useGeneratedId } from 'ui/hooks/seamly-hooks'
5
4
  import type { FramePosition } from 'ui/components/options/options-frame'
5
+ import { useGeneratedId } from 'ui/hooks/seamly-hooks'
6
6
 
7
7
  type TranslationsOptionsDialogProps = {
8
8
  onClose: () => void
@@ -1,5 +1,5 @@
1
- import { FC } from 'preact/compat'
2
1
  import { className } from 'lib/css'
2
+ import { FC } from 'preact/compat'
3
3
  import Icon from 'ui/components/layout/icon'
4
4
 
5
5
  type TranslationOptionProps = {
@@ -1,12 +1,12 @@
1
- import { useMemo } from 'preact/compat'
2
1
  import { useConfig } from 'domains/config/hooks'
3
2
  import { useI18n } from 'domains/i18n/hooks'
4
3
  import TranslationOption from 'domains/translations/components/options-dialog/translation-option'
5
4
  import { useTranslations } from 'domains/translations/hooks'
5
+ import type { Language } from 'domains/translations/translations.types'
6
6
  import { className } from 'lib/css'
7
+ import { useMemo } from 'preact/compat'
7
8
  import { useSkiplinkTargetFocusing } from 'ui/hooks/focus-helper-hooks'
8
9
  import { sourceTypes } from 'ui/utils/seamly-utils'
9
- import type { Language } from 'domains/translations/translations.types'
10
10
 
11
11
  type TranslationOptionsProps = {
12
12
  onChange: () => void
@@ -1,6 +1,6 @@
1
- import { useSelector } from 'react-redux'
2
1
  import { selectHasError } from 'domains/interrupt/selectors'
3
2
  import { useTranslations } from 'domains/translations/hooks'
3
+ import { useSelector } from 'react-redux'
4
4
  import TranslationProposal from 'ui/components/translation-proposal'
5
5
 
6
6
  export default function TranslationStatus() {
@@ -1,5 +1,3 @@
1
- import { useCallback, useMemo } from 'preact/hooks'
2
- import { useSelector } from 'react-redux'
3
1
  import { useConfig } from 'domains/config/hooks'
4
2
  import { useI18n } from 'domains/i18n/hooks'
5
3
  import { useAppDispatch, RootState } from 'domains/store'
@@ -10,6 +8,8 @@ import {
10
8
  MessageEvent,
11
9
  } from 'domains/store/store.types'
12
10
  import { useVisibility } from 'domains/visibility/hooks'
11
+ import { useCallback, useMemo } from 'preact/hooks'
12
+ import { useSelector } from 'react-redux'
13
13
  import { useElementFocusingById } from 'ui/hooks/focus-helper-hooks'
14
14
  import useSeamlyCommands from 'ui/hooks/use-seamly-commands'
15
15
  import {
@@ -2,10 +2,12 @@ import { Middleware } from '@reduxjs/toolkit'
2
2
  import { initializeApp } from 'domains/app/actions'
3
3
  import { initializeConfig } from 'domains/config/actions'
4
4
  import { setLocale } from 'domains/i18n/actions'
5
- import { addEvent } from 'domains/store/slice'
6
5
  import type { RootState } from 'domains/store'
6
+ import { addEvent } from 'domains/store/slice'
7
7
 
8
- const createI18nMiddleware: Middleware<{}, RootState, any> = ({ dispatch }) => {
8
+ const createI18nMiddleware: Middleware<object, RootState, any> = ({
9
+ dispatch,
10
+ }) => {
9
11
  return (next) => {
10
12
  return (action) => {
11
13
  const result = next(action)
@@ -1,13 +1,13 @@
1
1
  import { createAsyncThunk } from '@reduxjs/toolkit'
2
+ import type { VisibilityOptions } from 'config.types'
2
3
  import { selectUserHasResponded } from 'domains/app/selectors'
3
4
  import * as ConfigSelectors from 'domains/config/selectors'
5
+ import type { ThunkAPI } from 'domains/redux/redux.types'
4
6
  import { calculateVisibility } from 'domains/visibility/utils'
5
7
  import { selectState } from 'ui/hooks/seamly-state-hooks'
6
8
  import { StoreKey, visibilityStates } from './constants'
7
9
  import * as Selectors from './selectors'
8
10
  import type { VisibilityActionArgs } from './visibility.types'
9
- import type { VisibilityOptions } from 'config.types'
10
- import type { ThunkAPI } from 'domains/redux/redux.types'
11
11
 
12
12
  const validVisibilityStates = [
13
13
  visibilityStates.open,
@@ -1,18 +1,18 @@
1
- import { RefObject, createRef } from 'preact'
2
- import { useCallback, useEffect, useState } from 'preact/hooks'
3
- import { useSelector } from 'react-redux'
1
+ import type { VisibilityOptions } from 'config.types'
4
2
  import { useConfig } from 'domains/config/hooks'
5
3
  import { useAppDispatch } from 'domains/store'
6
4
  import { setVisibility } from 'domains/visibility/actions'
7
5
  import { setShowInlineView } from 'domains/visibility/slice'
6
+ import type { VisibilityActionArgs } from 'domains/visibility/visibility.types'
7
+ import { RefObject, createRef } from 'preact'
8
+ import { useCallback, useEffect, useState } from 'preact/hooks'
9
+ import { useSelector } from 'react-redux'
8
10
  import { visibilityStates } from './constants'
9
11
  import {
10
12
  selectShowInlineView,
11
13
  selectVisibility,
12
14
  selectSetInputFocus,
13
15
  } from './selectors'
14
- import type { VisibilityOptions } from 'config.types'
15
- import type { VisibilityActionArgs } from 'domains/visibility/visibility.types'
16
16
 
17
17
  export const useVisibility = () => {
18
18
  const dispatch = useAppDispatch()
@@ -2,7 +2,7 @@ const debug =
2
2
  process.env.NODE_ENV === 'development'
3
3
  ? (namespace) =>
4
4
  (...msg) =>
5
- // eslint-disable-next-line
5
+ // eslint-disable-next-line no-console
6
6
  console.debug(namespace, ...msg)
7
7
  : () => () => null
8
8
 
@@ -1,15 +1,15 @@
1
- import Events, { Events as EventsType } from 'minivents'
2
- import { render } from 'preact'
3
1
  import API from 'api'
2
+ import type { Config } from 'config.types'
4
3
  import { initializeApp } from 'domains/app/actions'
5
4
  import { initializeConfig } from 'domains/config/actions'
6
5
  import { setConfig } from 'domains/config/slice'
7
6
  import { createStore } from 'domains/store'
8
7
  import { initializeVisibility } from 'domains/visibility/actions'
8
+ import type ExternalApi from 'lib/external-api'
9
+ import Events, { Events as EventsType } from 'minivents'
10
+ import { render } from 'preact'
9
11
  import ChatApp from 'ui/components/chat-app'
10
12
  import SeamlyCore from 'ui/components/core/seamly-core'
11
- import type { Config } from 'config.types'
12
- import type ExternalApi from 'lib/external-api'
13
13
 
14
14
  export default class Engine {
15
15
  config: Omit<Config, 'parentElement'>
@@ -20,7 +20,7 @@ export default class Engine {
20
20
 
21
21
  externalApi: ExternalApi
22
22
 
23
- functions: {}
23
+ functions: object
24
24
 
25
25
  eventBus: EventsType
26
26
 
@@ -19,7 +19,6 @@ class ExternalApi {
19
19
  }
20
20
 
21
21
  push(...actionObjects) {
22
- // eslint-disable-next-line no-param-reassign
23
22
  actionObjects = actionObjects
24
23
  .filter(isActionObject)
25
24
  .map(fixActionObjectArgs)
@@ -69,21 +68,23 @@ class ExternalApi {
69
68
  }
70
69
 
71
70
  switch (action) {
72
- case 'setTopic':
71
+ case 'setTopic': {
73
72
  const { name } = args
74
73
  if (name) {
75
74
  this.context.topic = name
76
75
  }
77
76
  return true
77
+ }
78
78
  // Deprecated.
79
- case 'setTranslation':
79
+ case 'setTranslation': {
80
80
  const { enabled, locale } = args
81
81
  if (!!enabled && locale) {
82
82
  this.context.userLocale = locale
83
83
  this.context.source = sourceTypes.windowApi
84
84
  }
85
85
  return true
86
- case 'setContext':
86
+ }
87
+ case 'setContext': {
87
88
  const { userLocale, contentLocale } = args
88
89
  this.context.userLocale = userLocale
89
90
  this.context.contentLocale = contentLocale
@@ -92,6 +93,7 @@ class ExternalApi {
92
93
  }
93
94
 
94
95
  return true
96
+ }
95
97
  case 'setVariables':
96
98
  if (Object.keys(args).length > 0) {
97
99
  this.context.variables = { ...args }
@@ -178,7 +180,6 @@ class ExternalApi {
178
180
  })
179
181
  } else {
180
182
  if (typeof instance === 'string') {
181
- // eslint-disable-next-line no-param-reassign
182
183
  instance = this._instances[instance]
183
184
  }
184
185
  if (instance) {
@@ -188,7 +189,6 @@ class ExternalApi {
188
189
  }
189
190
  }
190
191
 
191
- // eslint-disable-next-line class-methods-use-this
192
192
  getUserConfig(userConfig = {}) {
193
193
  return userConfig
194
194
  }
@@ -7,7 +7,6 @@ export default function createMutex() {
7
7
  while (tasks.length) {
8
8
  const task = tasks.shift()
9
9
  isRunning = true
10
- // eslint-disable-next-line no-await-in-loop
11
10
  await task().catch(() => {
12
11
  // do nothing
13
12
  })
@@ -9,7 +9,7 @@ const splitUrlParams = (url) => {
9
9
  const params = url
10
10
  .slice(searchIndex + 1)
11
11
  .split('&')
12
- .reduce(function (acc, hash) {
12
+ .reduce((acc, hash) => {
13
13
  const [key, val] = hash.split('=')
14
14
  return {
15
15
  ...acc,
@@ -1,4 +1,3 @@
1
- /* eslint-disable */
2
1
  export function objectStore(key, storageProvider) {
3
2
  const sessionStore = storageProvider(key)
4
3
  const object = sessionStore.get() || {}
@@ -1,13 +1,11 @@
1
- // @ts-nocheck
2
1
  export default function appStore() {
3
2
  return {
4
3
  get: () => {
5
4
  // For Android we can retrieve data directly over the bridge
6
5
  // iOS and ReactNative will write the data on the window.seamlyBridgeData object on init
7
- if (window.hasOwnProperty('SeamlyBridge')) {
6
+ if (Object.prototype.hasOwnProperty.call(window, 'SeamlyBridge')) {
8
7
  try {
9
- // eslint-disable-next-line no-undef
10
- return JSON.parse(SeamlyBridge.getData())
8
+ return JSON.parse(window.SeamlyBridge.getData())
11
9
  } catch (e) {
12
10
  console.error('Unexpected or malformed data retrieved from bridge', e)
13
11
  // Android should always return unchanged JSON data.
@@ -30,9 +28,8 @@ export default function appStore() {
30
28
  }
31
29
 
32
30
  // Android
33
- if (window.hasOwnProperty('SeamlyBridge')) {
34
- // eslint-disable-next-line no-undef
35
- SeamlyBridge.setData(JSON.stringify(newData))
31
+ if (Object.prototype.hasOwnProperty.call(window, 'SeamlyBridge')) {
32
+ window.SeamlyBridge.setData(JSON.stringify(newData))
36
33
  }
37
34
 
38
35
  // React Native
@@ -4,10 +4,9 @@ export default function appStore() {
4
4
  get: () => {
5
5
  // For Android we can retrieve data directly over the bridge
6
6
  // iOS and ReactNative will write the data on the window.seamlyBridgeData object on init
7
- if (window.hasOwnProperty('SeamlyBridge')) {
7
+ if (Object.prototype.hasOwnProperty.call(window, 'SeamlyBridge')) {
8
8
  try {
9
- // eslint-disable-next-line no-undef
10
- return JSON.parse(SeamlyBridge.getData())
9
+ return JSON.parse(window.SeamlyBridge.getData())
11
10
  } catch (e) {
12
11
  console.error('Unexpected or malformed data retrieved from bridge', e)
13
12
  // Android should always return unchanged JSON data.
@@ -30,9 +29,8 @@ export default function appStore() {
30
29
  }
31
30
 
32
31
  // Android
33
- if (window.hasOwnProperty('SeamlyBridge')) {
34
- // eslint-disable-next-line no-undef
35
- SeamlyBridge.setData(JSON.stringify(newData))
32
+ if (Object.prototype.hasOwnProperty.call(window, 'SeamlyBridge')) {
33
+ window.SeamlyBridge.setData(JSON.stringify(newData))
36
34
  }
37
35
 
38
36
  // React Native
@@ -1,4 +1,3 @@
1
- import { useSelector } from 'react-redux'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { selectHasError } from 'domains/interrupt/selectors'
4
3
  import TranslationsOptionsButton from 'domains/translations/components/options-button'
@@ -7,6 +6,7 @@ import {
7
6
  useTranslations,
8
7
  } from 'domains/translations/hooks'
9
8
  import { className } from 'lib/css'
9
+ import { useSelector } from 'react-redux'
10
10
  import Icon from 'ui/components/layout/icon'
11
11
  import OptionsButton from 'ui/components/options/options-button'
12
12
  import { useSeamlyOptions } from 'ui/hooks/seamly-hooks'