@seamly/web-ui 18.1.1 → 18.3.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.
- package/build/dist/lib/index.debug.js +286 -99
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.LICENSE.txt +84 -16
- package/build/dist/lib/index.js +4104 -3887
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/standalone.js +4351 -4084
- package/build/dist/lib/standalone.min.js +1 -1
- package/build/dist/lib/style-guide.js +746 -641
- package/build/dist/lib/style-guide.min.js +1 -1
- package/build/dist/lib/styles.css +1 -1
- package/build/dist/lib/utils.js +0 -1
- package/build/dist/lib/utils.min.js +1 -1
- package/build/dist/translations/de-informal.js +0 -1
- package/build/dist/translations/de-informal.min.js +1 -1
- package/build/dist/translations/en.js +0 -1
- package/build/dist/translations/en.min.js +1 -1
- package/build/dist/translations/es-informal.js +0 -1
- package/build/dist/translations/es-informal.min.js +1 -1
- package/build/dist/translations/nl-formal.js +0 -1
- package/build/dist/translations/nl-formal.min.js +1 -1
- package/build/dist/translations/nl-informal.js +0 -1
- package/build/dist/translations/nl-informal.min.js +1 -1
- package/package.json +4 -2
- package/src/javascripts/api/index.js +9 -9
- package/src/javascripts/api/producer.js +8 -8
- package/src/javascripts/config.js +9 -11
- package/src/javascripts/domains/app/actions.js +25 -0
- package/src/javascripts/domains/app/index.js +3 -0
- package/src/javascripts/domains/config/actions.js +6 -0
- package/src/javascripts/domains/config/hooks.js +6 -0
- package/src/javascripts/domains/config/index.js +8 -0
- package/src/javascripts/domains/config/middleware.js +26 -0
- package/src/javascripts/domains/config/reducer.js +74 -0
- package/src/javascripts/domains/config/selectors.js +23 -0
- package/src/javascripts/domains/forms/actions.js +1 -1
- package/src/javascripts/domains/forms/hooks.js +10 -14
- package/src/javascripts/domains/forms/provider.js +4 -6
- package/src/javascripts/domains/forms/selectors.js +3 -3
- package/src/javascripts/domains/i18n/index.js +9 -5
- package/src/javascripts/domains/interrupt/actions.js +6 -0
- package/src/javascripts/domains/interrupt/hooks.js +29 -0
- package/src/javascripts/domains/interrupt/index.js +9 -0
- package/src/javascripts/domains/interrupt/middleware.js +30 -0
- package/src/javascripts/domains/interrupt/reducer.js +22 -0
- package/src/javascripts/domains/interrupt/selectors.js +5 -0
- package/src/javascripts/domains/options/index.js +1 -0
- package/src/javascripts/domains/options/middleware.js +35 -0
- package/src/javascripts/domains/redux/create-redux-store.js +14 -6
- package/src/javascripts/domains/redux/hooks.js +2 -2
- package/src/javascripts/domains/redux/index.js +2 -1
- package/src/javascripts/domains/redux/provider.js +5 -0
- package/src/javascripts/domains/store/index.js +38 -0
- package/src/javascripts/{ui → domains}/store/state-reducer.js +4 -7
- package/src/javascripts/domains/translations/actions.js +3 -3
- package/src/javascripts/domains/translations/components/chat-status.js +6 -12
- package/src/javascripts/domains/translations/components/options-button.js +3 -3
- package/src/javascripts/domains/translations/components/options-dialog/form.js +2 -2
- package/src/javascripts/domains/translations/components/options-dialog/index.js +2 -5
- package/src/javascripts/domains/translations/hooks.js +1 -1
- package/src/javascripts/domains/translations/reducer.js +2 -2
- package/src/javascripts/domains/translations/selectors.js +2 -2
- package/src/javascripts/index.js +17 -5
- package/src/javascripts/lib/css.js +5 -5
- package/src/javascripts/lib/engine/index.js +38 -11
- package/src/javascripts/lib/external-api/index.js +6 -6
- package/src/javascripts/lib/i18n.js +2 -2
- package/src/javascripts/lib/parse-body.js +1 -1
- package/src/javascripts/lib/redux-helpers/index.js +18 -4
- package/src/javascripts/lib/split-url-params.js +2 -2
- package/src/javascripts/lib/store/providers/app-storage.js +1 -1
- package/src/javascripts/lib/store/providers/cookie-storage.js +1 -1
- package/src/javascripts/package/utils.js +0 -1
- package/src/javascripts/style-guide/components/app.js +5 -12
- package/src/javascripts/style-guide/components/links.js +6 -6
- package/src/javascripts/style-guide/components/static-core.js +23 -7
- package/src/javascripts/style-guide/state-helpers/index.js +1 -1
- package/src/javascripts/style-guide/states.js +27 -67
- package/src/javascripts/style-guide/style-guide-engine.js +1 -1
- package/src/javascripts/ui/components/chat-app.js +2 -2
- package/src/javascripts/ui/components/conversation/component-filter.js +2 -2
- package/src/javascripts/ui/components/conversation/conversation.js +2 -2
- package/src/javascripts/ui/components/conversation/event/card-component.js +29 -4
- package/src/javascripts/ui/components/conversation/event/carousel-component/components/pagination.js +2 -2
- package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -3
- package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -1
- package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +2 -2
- package/src/javascripts/ui/components/conversation/event/choice-prompt.js +11 -6
- package/src/javascripts/ui/components/conversation/event/cta.js +1 -6
- package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +1 -1
- package/src/javascripts/ui/components/conversation/event/event-participant.js +3 -5
- package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +2 -2
- package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +3 -3
- package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +3 -3
- package/src/javascripts/ui/components/conversation/event/participant.js +2 -2
- package/src/javascripts/ui/components/conversation/event/upload.js +12 -27
- package/src/javascripts/ui/components/conversation/message-container.js +4 -6
- package/src/javascripts/ui/components/core/seamly-activity-monitor.js +4 -5
- package/src/javascripts/ui/components/core/seamly-core.js +6 -7
- package/src/javascripts/ui/components/core/seamly-event-subscriber.js +16 -17
- package/src/javascripts/ui/components/core/seamly-file-upload.js +5 -6
- package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +2 -6
- package/src/javascripts/ui/components/core/seamly-initializer.js +7 -60
- package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +10 -10
- package/src/javascripts/ui/components/core/seamly-live-region.js +1 -1
- package/src/javascripts/ui/components/core/seamly-new-notifications.js +1 -1
- package/src/javascripts/ui/components/core/seamly-read-state.js +2 -2
- package/src/javascripts/ui/components/entry/entry-container.js +7 -10
- package/src/javascripts/ui/components/entry/toggle-button.js +24 -10
- package/src/javascripts/ui/components/entry/upload/index.js +4 -11
- package/src/javascripts/ui/components/faq/faq.js +4 -4
- package/src/javascripts/ui/components/form-controls/error.js +22 -0
- package/src/javascripts/ui/components/form-controls/file-input.js +3 -9
- package/src/javascripts/ui/components/form-controls/select.js +1 -1
- package/src/javascripts/ui/components/form-controls/wrapper.js +2 -9
- package/src/javascripts/ui/components/layout/agent-info.js +4 -4
- package/src/javascripts/ui/components/layout/app-frame.js +5 -5
- package/src/javascripts/ui/components/layout/chat-frame.js +3 -5
- package/src/javascripts/ui/components/layout/header.js +4 -18
- package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
- package/src/javascripts/ui/components/options/cobrowsing.js +3 -7
- package/src/javascripts/ui/components/options/options-button.js +9 -13
- package/src/javascripts/ui/components/options/options-frame.js +1 -1
- package/src/javascripts/ui/components/options/transcript/index.js +2 -2
- package/src/javascripts/ui/components/options/transcript/transcript-form.js +1 -1
- package/src/javascripts/ui/components/warnings/cobrowsing-active-frame.js +3 -6
- package/src/javascripts/ui/components/warnings/idle-detach-warning.js +2 -6
- package/src/javascripts/ui/components/widgets/in-out-transition.js +2 -2
- package/src/javascripts/ui/components/widgets/lightbox.js +4 -4
- package/src/javascripts/ui/components/widgets/modal.js +3 -3
- package/src/javascripts/ui/components/widgets/upload-progress.js +2 -13
- package/src/javascripts/ui/hooks/component-helper-hooks.js +4 -15
- package/src/javascripts/ui/hooks/file-upload-hooks.js +3 -3
- package/src/javascripts/ui/hooks/focus-helper-hooks.js +4 -4
- package/src/javascripts/ui/hooks/live-region-hooks.js +2 -2
- package/src/javascripts/ui/hooks/seamly-entry-hooks.js +7 -6
- package/src/javascripts/ui/hooks/seamly-hooks.js +3 -9
- package/src/javascripts/ui/hooks/seamly-option-hooks.js +4 -4
- package/src/javascripts/ui/hooks/seamly-state-hooks.js +8 -16
- package/src/javascripts/ui/hooks/use-event-component-mapping.js +1 -1
- package/src/javascripts/ui/hooks/use-seamly-chat.js +1 -0
- package/src/javascripts/ui/hooks/use-seamly-commands.js +27 -49
- package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +3 -3
- package/src/javascripts/ui/hooks/use-seamly-stored-visibility.js +3 -3
- package/src/javascripts/ui/hooks/use-seamly-visibility.js +3 -3
- package/src/javascripts/ui/hooks/utility-hooks.js +2 -2
- package/src/javascripts/ui/utils/form-utils.js +3 -3
- package/src/javascripts/ui/utils/general-utils.js +17 -11
- package/src/javascripts/ui/utils/seamly-utils.js +15 -83
- package/src/javascripts/ui/utils/validations.js +10 -7
- package/src/stylesheets/5-components/_card.scss +0 -1
- package/src/stylesheets/5-components/_choice-prompt.scss +5 -0
- package/src/stylesheets/5-components/_message.scss +10 -0
- package/src/stylesheets/5-components/_options.scss +3 -2
- package/translations/de-informal.js +0 -2
- package/translations/en.js +0 -2
- package/translations/es-informal.js +0 -2
- package/translations/nl-formal.js +0 -2
- package/translations/nl-informal.js +0 -2
- package/webpack/config.common.js +3 -3
- package/webpack/config.package.js +4 -4
- package/webpack/config.site.js +8 -6
- package/CHANGELOG.md +0 -551
- package/src/javascripts/ui/components/core/seamly-api.js +0 -44
- package/src/javascripts/ui/hooks/use-seamly-interrupt.js +0 -62
- package/src/javascripts/ui/store/index.js +0 -37
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'preact/hooks'
|
|
2
|
-
import {
|
|
3
|
-
getSeamlyConfig,
|
|
4
|
-
getUrlParams,
|
|
5
|
-
getUrlSearchString,
|
|
6
|
-
randomId,
|
|
7
|
-
} from '@seamly/web-ui'
|
|
2
|
+
import { getUrlParams, getUrlSearchString, randomId } from '@seamly/web-ui'
|
|
8
3
|
import StyleGuideView from './view'
|
|
9
4
|
import StyleGuideLinks from './links'
|
|
10
5
|
import { getStateObj } from '../states'
|
|
@@ -34,7 +29,7 @@ const StyleGuideApp = ({ config, styleGuideConfig, headingLevel = 2 }) => {
|
|
|
34
29
|
})
|
|
35
30
|
|
|
36
31
|
const updateState = useCallback(
|
|
37
|
-
state => {
|
|
32
|
+
(state) => {
|
|
38
33
|
if (stateUpdateCallback) {
|
|
39
34
|
setStaticState(stateUpdateCallback(state))
|
|
40
35
|
} else {
|
|
@@ -46,7 +41,7 @@ const StyleGuideApp = ({ config, styleGuideConfig, headingLevel = 2 }) => {
|
|
|
46
41
|
|
|
47
42
|
const getState = useCallback(
|
|
48
43
|
(layoutMode, feature) => {
|
|
49
|
-
const {
|
|
44
|
+
const { defaults } = config
|
|
50
45
|
const { headingText } = mainState[feature]
|
|
51
46
|
setSelectedStateDescription(headingText)
|
|
52
47
|
const bareState = mainState[feature][layoutMode]
|
|
@@ -57,13 +52,11 @@ const StyleGuideApp = ({ config, styleGuideConfig, headingLevel = 2 }) => {
|
|
|
57
52
|
...bareState,
|
|
58
53
|
config: {
|
|
59
54
|
...bareState.config,
|
|
60
|
-
...
|
|
55
|
+
...config,
|
|
61
56
|
layoutMode: bareState.config.layoutMode,
|
|
62
57
|
...(overrideMessages ? { messages: overrideMessages } : {}),
|
|
63
58
|
showFaq,
|
|
64
59
|
},
|
|
65
|
-
showDisclaimer:
|
|
66
|
-
showDisclaimer != null ? showDisclaimer : bareState.showDisclaimer,
|
|
67
60
|
headerTitles: {
|
|
68
61
|
...bareState.headerTitles,
|
|
69
62
|
subTitle: agentName || bareState.headerTitles.subTitle,
|
|
@@ -82,7 +75,7 @@ const StyleGuideApp = ({ config, styleGuideConfig, headingLevel = 2 }) => {
|
|
|
82
75
|
const overlay = document.querySelector('[aria-modal="true"]')
|
|
83
76
|
if (overlay) {
|
|
84
77
|
overlay.addEventListener('click', () => {
|
|
85
|
-
setStaticState(s => ({
|
|
78
|
+
setStaticState((s) => ({
|
|
86
79
|
...s,
|
|
87
80
|
visible: 'minimized',
|
|
88
81
|
}))
|
|
@@ -4,7 +4,7 @@ import { categories } from '../states'
|
|
|
4
4
|
const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
|
|
5
5
|
const CategoryHeading = `h${headingLevel.toString()}`
|
|
6
6
|
const FeatureHeading = `h${(parseInt(headingLevel, 10) + 1).toString()}`
|
|
7
|
-
const onClickHandler = actionObj => {
|
|
7
|
+
const onClickHandler = (actionObj) => {
|
|
8
8
|
window.history.pushState(
|
|
9
9
|
null,
|
|
10
10
|
null,
|
|
@@ -18,9 +18,9 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
|
|
|
18
18
|
return (
|
|
19
19
|
<nav aria-label="Style guide navigation" className="nav--styleguide">
|
|
20
20
|
<ol className="list--styleguidestates">
|
|
21
|
-
{Object.keys(categories).map(category => {
|
|
21
|
+
{Object.keys(categories).map((category) => {
|
|
22
22
|
const { heading, description } = categories[category]
|
|
23
|
-
const features = Object.keys(states).filter(feature => {
|
|
23
|
+
const features = Object.keys(states).filter((feature) => {
|
|
24
24
|
const { category: featureCategory } = states[feature]
|
|
25
25
|
return featureCategory === category
|
|
26
26
|
})
|
|
@@ -30,7 +30,7 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
|
|
|
30
30
|
<CategoryHeading>{heading}</CategoryHeading>
|
|
31
31
|
<span className="category__description">{description}</span>
|
|
32
32
|
<ol>
|
|
33
|
-
{features.map(feature => {
|
|
33
|
+
{features.map((feature) => {
|
|
34
34
|
const featureState = { ...states[feature] }
|
|
35
35
|
delete featureState.category
|
|
36
36
|
const {
|
|
@@ -50,7 +50,7 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
|
|
|
50
50
|
</span>
|
|
51
51
|
)}
|
|
52
52
|
<ul className="list--styleguidelayouts">
|
|
53
|
-
{Object.keys(rest).map(layoutMode => (
|
|
53
|
+
{Object.keys(rest).map((layoutMode) => (
|
|
54
54
|
<li
|
|
55
55
|
key={layoutMode}
|
|
56
56
|
className={
|
|
@@ -74,7 +74,7 @@ const StyleGuideLinks = ({ setSelectedState, states, headingLevel }) => {
|
|
|
74
74
|
? 'page'
|
|
75
75
|
: null
|
|
76
76
|
}
|
|
77
|
-
onClick={e => {
|
|
77
|
+
onClick={(e) => {
|
|
78
78
|
e.preventDefault()
|
|
79
79
|
if (layoutMode === 'inline') {
|
|
80
80
|
setTimeout(() => {
|
|
@@ -6,10 +6,15 @@ import {
|
|
|
6
6
|
StoreProvider,
|
|
7
7
|
createReduxStore,
|
|
8
8
|
} from '@seamly/web-ui'
|
|
9
|
-
import stateReducer from '../../
|
|
9
|
+
import stateReducer from '../../domains/store/state-reducer'
|
|
10
10
|
import { Reducer as formReducer } from '../../domains/forms'
|
|
11
11
|
import { Reducer as translationsReducer } from '../../domains/translations'
|
|
12
12
|
import { Reducer as i18nReducer } from '../../domains/i18n'
|
|
13
|
+
import { Reducer as interruptReducer } from '../../domains/interrupt'
|
|
14
|
+
import {
|
|
15
|
+
Reducer as configReducer,
|
|
16
|
+
Actions as ConfigActions,
|
|
17
|
+
} from '../../domains/config'
|
|
13
18
|
|
|
14
19
|
const bareApi = {
|
|
15
20
|
send: () => {},
|
|
@@ -22,20 +27,31 @@ const bareApi = {
|
|
|
22
27
|
const SeamlyTestCore = ({ state, children }) => {
|
|
23
28
|
const liveMsgRef = useRef(() => {})
|
|
24
29
|
const eventBusRef = useRef({ emit: () => {} })
|
|
30
|
+
|
|
25
31
|
const store = useMemo(() => {
|
|
26
|
-
const {
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
const {
|
|
33
|
+
translations: translationsSlice,
|
|
34
|
+
interrupt: interruptSlice,
|
|
35
|
+
config: configSlice,
|
|
36
|
+
...restState
|
|
37
|
+
} = state || {}
|
|
38
|
+
const newStore = createReduxStore({
|
|
39
|
+
reducers: {
|
|
29
40
|
state: stateReducer,
|
|
41
|
+
[String(configReducer)]: configReducer,
|
|
30
42
|
[String(formReducer)]: formReducer,
|
|
31
43
|
[String(translationsReducer)]: translationsReducer,
|
|
32
44
|
[String(i18nReducer)]: i18nReducer,
|
|
45
|
+
[String(interruptReducer)]: interruptReducer,
|
|
33
46
|
},
|
|
34
|
-
{
|
|
47
|
+
initialState: {
|
|
35
48
|
state: restState,
|
|
36
|
-
|
|
49
|
+
[String(translationsReducer)]: translationsSlice,
|
|
50
|
+
[String(interruptReducer)]: interruptSlice,
|
|
37
51
|
},
|
|
38
|
-
)
|
|
52
|
+
})
|
|
53
|
+
newStore.dispatch(ConfigActions.initialize(configSlice || {}))
|
|
54
|
+
return newStore
|
|
39
55
|
}, [state])
|
|
40
56
|
|
|
41
57
|
return (
|
|
@@ -42,7 +42,7 @@ export function addTranslationData(event) {
|
|
|
42
42
|
? 'NL - ' + event.payload.body.buttonText
|
|
43
43
|
: undefined,
|
|
44
44
|
choices: event.payload.body.choices
|
|
45
|
-
? event.payload.body.choices.map(choice => ({
|
|
45
|
+
? event.payload.body.choices.map((choice) => ({
|
|
46
46
|
...choice,
|
|
47
47
|
text: 'NL - ' + choice.text,
|
|
48
48
|
}))
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
visibilityStates,
|
|
3
|
+
randomId,
|
|
4
|
+
SeamlyOfflineError,
|
|
5
|
+
SeamlyGeneralError,
|
|
6
|
+
SeamlyConfigurationError,
|
|
7
|
+
} from '@seamly/web-ui'
|
|
2
8
|
import { addTranslationData } from './state-helpers'
|
|
3
9
|
|
|
4
10
|
const baseState = {
|
|
@@ -8,6 +14,7 @@ const baseState = {
|
|
|
8
14
|
accountConfig: {},
|
|
9
15
|
hideOnNoUserResponse: false,
|
|
10
16
|
showFaq: false,
|
|
17
|
+
showDisclaimer: false,
|
|
11
18
|
},
|
|
12
19
|
initialState: {},
|
|
13
20
|
unreadEvents: 0,
|
|
@@ -27,14 +34,12 @@ const baseState = {
|
|
|
27
34
|
subTitle: 'Test subtitle',
|
|
28
35
|
},
|
|
29
36
|
interrupt: {
|
|
30
|
-
|
|
31
|
-
meta: {},
|
|
37
|
+
error: undefined,
|
|
32
38
|
},
|
|
33
39
|
historyLoaded: false,
|
|
34
40
|
skiplinkTargetId: randomId(),
|
|
35
41
|
optionsButtonId: randomId(),
|
|
36
42
|
cobrowseContainerId: randomId(),
|
|
37
|
-
showDisclaimer: false,
|
|
38
43
|
serviceData: {},
|
|
39
44
|
options: {
|
|
40
45
|
features: {},
|
|
@@ -117,8 +122,7 @@ const newTranslationDividerStart = {
|
|
|
117
122
|
body: {
|
|
118
123
|
language: 'Nederlands',
|
|
119
124
|
subtype: 'new_translation',
|
|
120
|
-
text:
|
|
121
|
-
'[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
|
|
125
|
+
text: '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
|
|
122
126
|
translationEnabled: true,
|
|
123
127
|
translationLocale: 'nl',
|
|
124
128
|
},
|
|
@@ -304,7 +308,7 @@ const ctaMessage = {
|
|
|
304
308
|
type: 'message',
|
|
305
309
|
payload: {
|
|
306
310
|
body: {
|
|
307
|
-
description: '
|
|
311
|
+
description: 'Thanks for chatting!\n\nMore info about our **products**?',
|
|
308
312
|
buttonLink: 'https://seamly.ai',
|
|
309
313
|
buttonText: 'View website',
|
|
310
314
|
buttonNewTab: true,
|
|
@@ -329,8 +333,7 @@ const longTextMessage = {
|
|
|
329
333
|
type: 'message',
|
|
330
334
|
payload: {
|
|
331
335
|
body: {
|
|
332
|
-
text:
|
|
333
|
-
'What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am.',
|
|
336
|
+
text: 'What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am.',
|
|
334
337
|
type: 'text',
|
|
335
338
|
variables: {},
|
|
336
339
|
},
|
|
@@ -422,8 +425,7 @@ const textMessageWithLongLink = {
|
|
|
422
425
|
variables: {
|
|
423
426
|
link_1: {
|
|
424
427
|
id: '1',
|
|
425
|
-
name:
|
|
426
|
-
'click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee',
|
|
428
|
+
name: 'click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee',
|
|
427
429
|
newTab: false,
|
|
428
430
|
type: 'link',
|
|
429
431
|
url: 'https://google.com',
|
|
@@ -450,8 +452,7 @@ const textMesageWithBullets = {
|
|
|
450
452
|
type: 'message',
|
|
451
453
|
payload: {
|
|
452
454
|
body: {
|
|
453
|
-
text:
|
|
454
|
-
'<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
|
|
455
|
+
text: '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
|
|
455
456
|
type: 'text',
|
|
456
457
|
variables: {},
|
|
457
458
|
},
|
|
@@ -553,8 +554,7 @@ const choicePromptMessage = {
|
|
|
553
554
|
choices: [
|
|
554
555
|
{
|
|
555
556
|
id: '703db9b3-2157-4d4a-9f9b-c382c6a10531',
|
|
556
|
-
text:
|
|
557
|
-
'Dialog (this is intentionally made longer for testing purposes)',
|
|
557
|
+
text: 'Dialog (this is intentionally made longer for testing purposes)',
|
|
558
558
|
type: 'choice',
|
|
559
559
|
},
|
|
560
560
|
{
|
|
@@ -579,7 +579,8 @@ const choicePromptMessage = {
|
|
|
579
579
|
},
|
|
580
580
|
{
|
|
581
581
|
id: '9fd9a28f-462d-4f07-9661-606dbe3b9466',
|
|
582
|
-
|
|
582
|
+
category: 'secondary',
|
|
583
|
+
text: 'Something else',
|
|
583
584
|
type: 'choice',
|
|
584
585
|
},
|
|
585
586
|
],
|
|
@@ -630,8 +631,7 @@ const userMessageLong = {
|
|
|
630
631
|
type: 'message',
|
|
631
632
|
payload: {
|
|
632
633
|
body: {
|
|
633
|
-
text:
|
|
634
|
-
'This is what the user typed. And sometimes the user has quite a lot to say and then we get longer lines that need to wrap well and not break the styling so here goes with just such a line right here!!',
|
|
634
|
+
text: 'This is what the user typed. And sometimes the user has quite a lot to say and then we get longer lines that need to wrap well and not break the styling so here goes with just such a line right here!!',
|
|
635
635
|
type: 'text',
|
|
636
636
|
variables: {},
|
|
637
637
|
},
|
|
@@ -652,7 +652,6 @@ const fileDownloadPayload = {
|
|
|
652
652
|
meta: {},
|
|
653
653
|
body: {
|
|
654
654
|
contentType: 'image/jpg',
|
|
655
|
-
deleteAt: 1000 * (Date.now() + 3600000),
|
|
656
655
|
filename: 'placeholder.jpg',
|
|
657
656
|
filesize: 991078,
|
|
658
657
|
url: 'https://via.placeholder.com/150',
|
|
@@ -675,7 +674,6 @@ const deletedFileDownloadAgentMessage = {
|
|
|
675
674
|
...fileDownloadAgentMessage.payload,
|
|
676
675
|
body: {
|
|
677
676
|
...fileDownloadAgentMessage.payload.body,
|
|
678
|
-
deleteAt: 1000 * (Date.now() - 3600000),
|
|
679
677
|
},
|
|
680
678
|
id: randomId(),
|
|
681
679
|
},
|
|
@@ -691,18 +689,6 @@ const fileDownloadUserMessage = {
|
|
|
691
689
|
},
|
|
692
690
|
}
|
|
693
691
|
|
|
694
|
-
const deletedFileDownloadUserMessage = {
|
|
695
|
-
...fileDownloadUserMessage,
|
|
696
|
-
payload: {
|
|
697
|
-
id: randomId(),
|
|
698
|
-
...fileDownloadUserMessage.payload,
|
|
699
|
-
body: {
|
|
700
|
-
...fileDownloadUserMessage.payload.body,
|
|
701
|
-
deleteAt: 1000 * (Date.now() - 3600000),
|
|
702
|
-
},
|
|
703
|
-
},
|
|
704
|
-
}
|
|
705
|
-
|
|
706
692
|
const emptyUrlFileDownloadUserMessage = {
|
|
707
693
|
...fileDownloadUserMessage,
|
|
708
694
|
payload: {
|
|
@@ -807,7 +793,8 @@ const cardAskText = {
|
|
|
807
793
|
type: 'ask',
|
|
808
794
|
},
|
|
809
795
|
buttonText: 'Ask about pizzas!',
|
|
810
|
-
description:
|
|
796
|
+
description:
|
|
797
|
+
'Pizza Margherita is a **typical Neapolitan pizza**.\n\nIt is made with San Marzano tomatoes, mozzarella cheese, fresh basil, salt, and extra-virgin olive oil.',
|
|
811
798
|
image:
|
|
812
799
|
'https://via.placeholder.com/400x200/dee3e5/6a7f8c?text=Margherita',
|
|
813
800
|
title: 'Pizza Margherita',
|
|
@@ -826,7 +813,7 @@ const cardNavigate = {
|
|
|
826
813
|
type: 'navigate',
|
|
827
814
|
},
|
|
828
815
|
buttonText: 'Order now!',
|
|
829
|
-
description: 'Pizza Margherita is a typical Neapolitan pizza
|
|
816
|
+
description: 'Pizza Margherita is a **typical Neapolitan pizza**.',
|
|
830
817
|
image:
|
|
831
818
|
'https://via.placeholder.com/400x200/dee3e5/6a7f8c?text=Margherita',
|
|
832
819
|
title: 'Pizza Margherita',
|
|
@@ -891,7 +878,6 @@ const standardState = {
|
|
|
891
878
|
textMessageWithLongLink,
|
|
892
879
|
imageMessageWithLightbox,
|
|
893
880
|
fileDownloadUserMessage,
|
|
894
|
-
deletedFileDownloadUserMessage,
|
|
895
881
|
emptyUrlFileDownloadUserMessage,
|
|
896
882
|
textMesageWithBullets,
|
|
897
883
|
choicePromptMessage,
|
|
@@ -908,7 +894,6 @@ const standardState = {
|
|
|
908
894
|
userMessage,
|
|
909
895
|
userMessageLong,
|
|
910
896
|
fileDownloadUserMessage,
|
|
911
|
-
deletedFileDownloadUserMessage,
|
|
912
897
|
emptyUrlFileDownloadUserMessage,
|
|
913
898
|
],
|
|
914
899
|
},
|
|
@@ -1114,8 +1099,7 @@ const standardState = {
|
|
|
1114
1099
|
occurredAt: Date.now() * 1000,
|
|
1115
1100
|
id: randomId(),
|
|
1116
1101
|
body: {
|
|
1117
|
-
text:
|
|
1118
|
-
'Above me should be a time indicator showing me the dialog continues today',
|
|
1102
|
+
text: 'Above me should be a time indicator showing me the dialog continues today',
|
|
1119
1103
|
type: 'text',
|
|
1120
1104
|
variables: {},
|
|
1121
1105
|
},
|
|
@@ -1165,14 +1149,7 @@ const standardState = {
|
|
|
1165
1149
|
description: '',
|
|
1166
1150
|
...baseState,
|
|
1167
1151
|
interrupt: {
|
|
1168
|
-
|
|
1169
|
-
meta: {
|
|
1170
|
-
title: 'Connection issues',
|
|
1171
|
-
message:
|
|
1172
|
-
'There might be a problem with your or our network connection. The chat session should resume as soon the connection is available again.',
|
|
1173
|
-
srText:
|
|
1174
|
-
'The chat has connection issues. There might be a problem with your or our network connection. The chat session should resume as soon as the connection is available again.',
|
|
1175
|
-
},
|
|
1152
|
+
error: new SeamlyOfflineError(),
|
|
1176
1153
|
},
|
|
1177
1154
|
},
|
|
1178
1155
|
generalErrorInterrupt: {
|
|
@@ -1182,15 +1159,7 @@ const standardState = {
|
|
|
1182
1159
|
description: '',
|
|
1183
1160
|
...baseState,
|
|
1184
1161
|
interrupt: {
|
|
1185
|
-
|
|
1186
|
-
meta: {
|
|
1187
|
-
title: 'Something went wrong',
|
|
1188
|
-
message: 'Do you want to start a new chat session?',
|
|
1189
|
-
buttonText: 'Restart chat',
|
|
1190
|
-
action: 'reset',
|
|
1191
|
-
srText:
|
|
1192
|
-
'Something went wrong with the chat session. You can restart the chat.',
|
|
1193
|
-
},
|
|
1162
|
+
error: new SeamlyGeneralError(),
|
|
1194
1163
|
},
|
|
1195
1164
|
},
|
|
1196
1165
|
configErrorInterrupt: {
|
|
@@ -1200,13 +1169,7 @@ const standardState = {
|
|
|
1200
1169
|
description: '',
|
|
1201
1170
|
...baseState,
|
|
1202
1171
|
interrupt: {
|
|
1203
|
-
|
|
1204
|
-
meta: {
|
|
1205
|
-
title: 'Chat configuration error.',
|
|
1206
|
-
message: 'We are sorry this happened, please retry at a later time.',
|
|
1207
|
-
srText:
|
|
1208
|
-
'A chat configuration error occurred. Our apologies, please retry at a later time.',
|
|
1209
|
-
},
|
|
1172
|
+
error: new SeamlyConfigurationError(),
|
|
1210
1173
|
},
|
|
1211
1174
|
},
|
|
1212
1175
|
privacyDisclaimer: {
|
|
@@ -1218,7 +1181,6 @@ const standardState = {
|
|
|
1218
1181
|
...baseState.config,
|
|
1219
1182
|
showDisclaimer: true,
|
|
1220
1183
|
},
|
|
1221
|
-
showDisclaimer: true,
|
|
1222
1184
|
},
|
|
1223
1185
|
cobrowserBar: {
|
|
1224
1186
|
category: categoryKeys.features,
|
|
@@ -1756,7 +1718,6 @@ const standardState = {
|
|
|
1756
1718
|
textMessageWithLongLink,
|
|
1757
1719
|
imageMessageWithLightbox,
|
|
1758
1720
|
fileDownloadUserMessage,
|
|
1759
|
-
deletedFileDownloadUserMessage,
|
|
1760
1721
|
emptyUrlFileDownloadUserMessage,
|
|
1761
1722
|
textMesageWithBullets,
|
|
1762
1723
|
choicePromptMessage,
|
|
@@ -1794,9 +1755,8 @@ const buildStandardState = (layoutModes, customComponentEventBodies = []) => {
|
|
|
1794
1755
|
}, {}),
|
|
1795
1756
|
}
|
|
1796
1757
|
return Object.keys(intermediateState).reduce((acc, key) => {
|
|
1797
|
-
const { headingText, category, description, ...rest } =
|
|
1798
|
-
key
|
|
1799
|
-
]
|
|
1758
|
+
const { headingText, category, description, ...rest } =
|
|
1759
|
+
intermediateState[key]
|
|
1800
1760
|
return {
|
|
1801
1761
|
...acc,
|
|
1802
1762
|
[key]: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import View from './layout/view'
|
|
2
2
|
import SeamlyCore from './core/seamly-core'
|
|
3
3
|
|
|
4
|
-
const ChatApp = (
|
|
4
|
+
const ChatApp = (props) => {
|
|
5
5
|
return (
|
|
6
|
-
<SeamlyCore
|
|
6
|
+
<SeamlyCore {...props}>
|
|
7
7
|
<View />
|
|
8
8
|
</SeamlyCore>
|
|
9
9
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'preact/hooks'
|
|
2
|
-
import {
|
|
2
|
+
import { useConfig } from '../../../domains/config'
|
|
3
3
|
import ComponentContext from './component-context'
|
|
4
4
|
import ChoicePrompt from './event/choice-prompt'
|
|
5
5
|
import Text from './event/text'
|
|
@@ -37,7 +37,7 @@ const eventTypeMapping = {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const ComponentFilter = ({ children }) => {
|
|
40
|
-
const { customComponents } =
|
|
40
|
+
const { customComponents } = useConfig()
|
|
41
41
|
|
|
42
42
|
const resolvedComponents = useMemo(() => {
|
|
43
43
|
// Calculates a combined component mapping object based on the defaults with
|
|
@@ -33,7 +33,7 @@ const Conversation = () => {
|
|
|
33
33
|
|
|
34
34
|
const renderEvents = () => {
|
|
35
35
|
let prevParticipant = null
|
|
36
|
-
return events.map(event => {
|
|
36
|
+
return events.map((event) => {
|
|
37
37
|
const { type, payload } = event
|
|
38
38
|
const { participant, fromClient } = payload
|
|
39
39
|
let participantChanged = false
|
|
@@ -56,7 +56,7 @@ const Conversation = () => {
|
|
|
56
56
|
})
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const onClickHandler = e => {
|
|
59
|
+
const onClickHandler = (e) => {
|
|
60
60
|
e.preventDefault()
|
|
61
61
|
focusSkiplinkTarget()
|
|
62
62
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { useCallback, useMemo } from 'preact/hooks'
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
|
|
2
2
|
import { className } from '../../../../lib/css'
|
|
3
|
+
import parseBody from '../../../../lib/parse-body'
|
|
3
4
|
import { useGeneratedId, useSeamlyCommands } from '../../../hooks/seamly-hooks'
|
|
4
5
|
import { cardTypes, actionTypes } from '../../../utils/seamly-utils'
|
|
5
6
|
|
|
@@ -8,11 +9,15 @@ const CardComponent = ({
|
|
|
8
9
|
action,
|
|
9
10
|
buttonText,
|
|
10
11
|
description,
|
|
12
|
+
hasFocus,
|
|
11
13
|
image,
|
|
12
14
|
title,
|
|
15
|
+
isCarouselItem,
|
|
13
16
|
}) => {
|
|
17
|
+
const cardRef = useRef(null)
|
|
14
18
|
const { sendMessage, sendAction, emitEvent } = useSeamlyCommands()
|
|
15
19
|
const descriptionId = useGeneratedId()
|
|
20
|
+
const isMounted = useRef()
|
|
16
21
|
|
|
17
22
|
const CardActionComponent =
|
|
18
23
|
action.type === cardTypes.navigate ? 'a' : 'button'
|
|
@@ -52,15 +57,35 @@ const CardComponent = ({
|
|
|
52
57
|
[action, handleClick, emitCardEvent],
|
|
53
58
|
)
|
|
54
59
|
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (isCarouselItem) {
|
|
62
|
+
if (hasFocus && isMounted.current) {
|
|
63
|
+
window.requestAnimationFrame(() => cardRef.current.focus())
|
|
64
|
+
} else {
|
|
65
|
+
cardRef.current.blur()
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
isMounted.current = true
|
|
69
|
+
}, [hasFocus, isCarouselItem])
|
|
70
|
+
|
|
55
71
|
return (
|
|
56
|
-
<div
|
|
57
|
-
|
|
72
|
+
<div
|
|
73
|
+
className={className('card__wrapper')}
|
|
74
|
+
id={id}
|
|
75
|
+
tabIndex="-1" // set tabIndex of -1 so card can be focussed
|
|
76
|
+
ref={cardRef}
|
|
77
|
+
>
|
|
78
|
+
<img className={className('card__image')} src={image} alt="" />
|
|
58
79
|
<div className={className('card__content')} id={id}>
|
|
59
80
|
{title && <h2 className={className('card__title')}>{title}</h2>}
|
|
60
81
|
{description && (
|
|
61
|
-
<
|
|
82
|
+
<div
|
|
83
|
+
className={className('card__description')}
|
|
84
|
+
dangerouslySetInnerHTML={{ __html: parseBody(description) }}
|
|
85
|
+
/>
|
|
62
86
|
)}
|
|
63
87
|
<CardActionComponent
|
|
88
|
+
tabIndex={isCarouselItem && !hasFocus ? '-1' : undefined} // disable to prevent tabbing through cards
|
|
64
89
|
className={className('button', 'button--primary')}
|
|
65
90
|
aria-describedby={descriptionId}
|
|
66
91
|
{...actionProps}
|
package/src/javascripts/ui/components/conversation/event/carousel-component/components/pagination.js
CHANGED
|
@@ -10,7 +10,7 @@ export default function CarouselPagination({
|
|
|
10
10
|
}) {
|
|
11
11
|
const itemCount = items.length
|
|
12
12
|
const handlePaginate = useCallback(
|
|
13
|
-
event => {
|
|
13
|
+
(event) => {
|
|
14
14
|
const slideIndex = Number(event.target.dataset.item || '0')
|
|
15
15
|
const nextIndex = Math.min(itemCount - 1, Math.max(0, slideIndex))
|
|
16
16
|
if (nextIndex !== currentIndex) {
|
|
@@ -27,7 +27,7 @@ export default function CarouselPagination({
|
|
|
27
27
|
const isActive = currentIndex === idx
|
|
28
28
|
return (
|
|
29
29
|
<li
|
|
30
|
-
key={getItemKey(item, idx)}
|
|
30
|
+
key={getItemKey(item, idx, 'pagination-item-')}
|
|
31
31
|
className={className(
|
|
32
32
|
'carousel-pagination__item',
|
|
33
33
|
isActive ? 'is-active' : undefined,
|
|
@@ -6,8 +6,8 @@ import CarouselPagination from './components/pagination'
|
|
|
6
6
|
import CarouselControls from './components/controls'
|
|
7
7
|
import CarouselMessageSlide from '../carousel-message/components/slide'
|
|
8
8
|
|
|
9
|
-
const defaultGetItemKey = (item, idx) => idx
|
|
10
|
-
const defaultGetItemLabel = item => item.label
|
|
9
|
+
const defaultGetItemKey = (item, idx, prefix) => `${prefix}${idx}`
|
|
10
|
+
const defaultGetItemLabel = (item) => item.label
|
|
11
11
|
|
|
12
12
|
export default function CarouselComponent({
|
|
13
13
|
currentIndex: originalIndex,
|
|
@@ -66,7 +66,7 @@ export default function CarouselComponent({
|
|
|
66
66
|
const isActive = currentIndex === idx
|
|
67
67
|
return (
|
|
68
68
|
<div
|
|
69
|
-
key={idx}
|
|
69
|
+
key={getItemKey(item, idx, 'item-')}
|
|
70
70
|
ref={slideRefs.current[idx]}
|
|
71
71
|
className={className(
|
|
72
72
|
'carousel__slide',
|
|
@@ -78,6 +78,7 @@ export default function CarouselComponent({
|
|
|
78
78
|
item={item}
|
|
79
79
|
items={items}
|
|
80
80
|
currentIndex={currentIndex}
|
|
81
|
+
isActive={isActive}
|
|
81
82
|
/>
|
|
82
83
|
</div>
|
|
83
84
|
)
|
package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js
CHANGED
|
@@ -6,6 +6,7 @@ export default function CarouselMessageSlide({
|
|
|
6
6
|
item: slide,
|
|
7
7
|
items,
|
|
8
8
|
currentIndex,
|
|
9
|
+
isActive,
|
|
9
10
|
}) {
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
|
|
@@ -19,7 +20,7 @@ export default function CarouselMessageSlide({
|
|
|
19
20
|
total: items.length,
|
|
20
21
|
})}
|
|
21
22
|
>
|
|
22
|
-
<CardComponent {...slide} />
|
|
23
|
+
<CardComponent {...slide} isCarouselItem={true} hasFocus={isActive} />
|
|
23
24
|
</div>
|
|
24
25
|
)
|
|
25
26
|
}
|
|
@@ -2,8 +2,8 @@ import MessageContainer from '../../message-container'
|
|
|
2
2
|
import CarouselComponent from '../carousel-component'
|
|
3
3
|
import CarouselMessageSlide from './components/slide'
|
|
4
4
|
|
|
5
|
-
const getItemKey = item => item.title
|
|
6
|
-
const getItemLabel = item => item.title
|
|
5
|
+
const getItemKey = (item, idx, prefix = '') => `${prefix}${item.title}:${idx}`
|
|
6
|
+
const getItemLabel = (item) => item.title
|
|
7
7
|
const CarouselMessage = ({ event }) => {
|
|
8
8
|
const slides = event.payload.body.cards
|
|
9
9
|
|