@seamly/web-ui 24.3.1 → 24.4.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.
- package/build/dist/lib/index.debug.js +113 -61
- package/build/dist/lib/index.debug.js.map +1 -1
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.map +1 -1
- package/build/dist/lib/index.js +57 -9
- package/build/dist/lib/index.js.map +1 -1
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/index.min.js.map +1 -1
- package/build/dist/lib/styles.css +1 -1
- package/package.json +11 -12
- package/src/javascripts/core/domains/store/slice.ts +26 -4
- package/src/javascripts/core/ui/components/conversation/event/choice-prompt.tsx +7 -0
- package/src/javascripts/core/ui/components/conversation/event/conversation-suggestions.tsx +15 -1
- package/src/javascripts/core/ui/components/entry/entry-container.tsx +2 -6
- package/src/javascripts/core/ui/components/entry/upload/index.tsx +19 -0
- package/src/javascripts/core/ui/components/suggestions/index.tsx +8 -0
package/build/dist/lib/index.js
CHANGED
|
@@ -5427,7 +5427,7 @@ class API {
|
|
|
5427
5427
|
return {
|
|
5428
5428
|
clientName: "@seamly/web-ui",
|
|
5429
5429
|
clientVariant: this.#layoutMode,
|
|
5430
|
-
clientVersion: "24.
|
|
5430
|
+
clientVersion: "24.4.0",
|
|
5431
5431
|
currentUrl: window.location.toString(),
|
|
5432
5432
|
screenResolution: `${window.screen.width}x${window.screen.height}`,
|
|
5433
5433
|
timezone: getTimeZone(),
|
|
@@ -12003,6 +12003,10 @@ const participantReducer = (participantInfo, action) => {
|
|
|
12003
12003
|
};
|
|
12004
12004
|
};
|
|
12005
12005
|
const calculateNewEntryMeta = (entryMeta, channelEvent) => {
|
|
12006
|
+
// Events originating from the client should leave the entry meta as is
|
|
12007
|
+
if (channelEvent?.payload?.fromClient === true) {
|
|
12008
|
+
return entryMeta;
|
|
12009
|
+
}
|
|
12006
12010
|
const entry = channelEvent?.type === 'message' ? channelEvent?.payload.translatedEntry || channelEvent?.payload.entry : {
|
|
12007
12011
|
options: undefined,
|
|
12008
12012
|
type: undefined
|
|
@@ -12224,7 +12228,7 @@ const storeSlice = createSlice({
|
|
|
12224
12228
|
// Use the messages from the payload, as `events` only contains displayable ones.
|
|
12225
12229
|
// The first participant message found is the 'last', as we receive them from newest to oldest.
|
|
12226
12230
|
const lastParticipantEvent = messages.find(m => m.type === 'participant');
|
|
12227
|
-
// @ts-
|
|
12231
|
+
// @ts-expect-error TypeScript incorrectly assumes that the payload can be any of info/message/participant
|
|
12228
12232
|
const lastParticipantId = lastParticipantEvent?.payload?.participant?.id;
|
|
12229
12233
|
const {
|
|
12230
12234
|
entry
|
|
@@ -12238,10 +12242,25 @@ const storeSlice = createSlice({
|
|
|
12238
12242
|
...(entry?.options ? entry.options : {})
|
|
12239
12243
|
}
|
|
12240
12244
|
}, events[events.length - 1]);
|
|
12241
|
-
|
|
12245
|
+
let newFeatures = {
|
|
12242
12246
|
...state.options.features
|
|
12243
12247
|
};
|
|
12248
|
+
// The first service message found is the 'last', as we receive them from newest to oldest.
|
|
12249
|
+
const lastServiceMessage = messages.find(m => !m.payload.fromClient && ['message', 'participant'].includes(m.type));
|
|
12244
12250
|
const newFeaturesHasUpload = newFeatures.hasOwnProperty(featureKeys.uploads);
|
|
12251
|
+
|
|
12252
|
+
// Check for upload enabled by entry type
|
|
12253
|
+
if (newFeaturesHasUpload && lastServiceMessage?.type === 'message') {
|
|
12254
|
+
// @ts-expect-error TypeScript incorrectly assumes that the payload can be any of info/message/participant
|
|
12255
|
+
const entryType = lastServiceMessage.payload.entry?.type || '';
|
|
12256
|
+
newFeatures = {
|
|
12257
|
+
...newFeatures,
|
|
12258
|
+
uploads: {
|
|
12259
|
+
enabled: newFeatures.uploads?.enabled || false,
|
|
12260
|
+
enabledFromEntry: entryType === entryTypes.upload
|
|
12261
|
+
}
|
|
12262
|
+
};
|
|
12263
|
+
}
|
|
12245
12264
|
state.unreadEvents = unreadMessageCount;
|
|
12246
12265
|
state.userHasResponded = userResponded;
|
|
12247
12266
|
state.events = events.filter(e => e.type !== 'participant' || !!e.payload.participant?.introduction);
|
|
@@ -15361,6 +15380,7 @@ const CarouselMessage = ({
|
|
|
15361
15380
|
|
|
15362
15381
|
|
|
15363
15382
|
|
|
15383
|
+
|
|
15364
15384
|
const useChoicePrompt = event => {
|
|
15365
15385
|
const {
|
|
15366
15386
|
payload
|
|
@@ -15371,6 +15391,7 @@ const useChoicePrompt = event => {
|
|
|
15371
15391
|
emitEvent,
|
|
15372
15392
|
sendAction
|
|
15373
15393
|
} = use_seamly_commands();
|
|
15394
|
+
const hasConversation = useSeamlyHasConversation();
|
|
15374
15395
|
const {
|
|
15375
15396
|
activeServiceSessionId
|
|
15376
15397
|
} = useSeamlyServiceInfo();
|
|
@@ -15400,6 +15421,10 @@ const useChoicePrompt = event => {
|
|
|
15400
15421
|
setShowOptions(payload.id === lastEventId);
|
|
15401
15422
|
}, [payload, lastEventId]);
|
|
15402
15423
|
const onChoiceClickHandler = choice => {
|
|
15424
|
+
// Do not allow interaction without a conversation
|
|
15425
|
+
if (!hasConversation()) {
|
|
15426
|
+
return;
|
|
15427
|
+
}
|
|
15403
15428
|
const transactionId = randomId();
|
|
15404
15429
|
const action = {
|
|
15405
15430
|
type: actionTypes.pickChoice,
|
|
@@ -15575,6 +15600,7 @@ const SuggestionsList = ({
|
|
|
15575
15600
|
|
|
15576
15601
|
|
|
15577
15602
|
|
|
15603
|
+
|
|
15578
15604
|
const useSuggestions = event => {
|
|
15579
15605
|
const {
|
|
15580
15606
|
payload
|
|
@@ -15599,6 +15625,7 @@ const ConversationSuggestions = ({
|
|
|
15599
15625
|
emitEvent,
|
|
15600
15626
|
sendAction
|
|
15601
15627
|
} = use_seamly_commands();
|
|
15628
|
+
const hasConversation = useSeamlyHasConversation();
|
|
15602
15629
|
const {
|
|
15603
15630
|
suggestions,
|
|
15604
15631
|
payload
|
|
@@ -15623,6 +15650,10 @@ const ConversationSuggestions = ({
|
|
|
15623
15650
|
id,
|
|
15624
15651
|
question
|
|
15625
15652
|
}) => {
|
|
15653
|
+
// Do not allow interaction without a conversation
|
|
15654
|
+
if (!hasConversation()) {
|
|
15655
|
+
return;
|
|
15656
|
+
}
|
|
15626
15657
|
setIsExpanded(false);
|
|
15627
15658
|
dispatch(setHasResponded(true));
|
|
15628
15659
|
const transactionId = randomId();
|
|
@@ -15643,7 +15674,7 @@ const ConversationSuggestions = ({
|
|
|
15643
15674
|
sendAction(action);
|
|
15644
15675
|
addMessageBubble(question, transactionId);
|
|
15645
15676
|
emitEvent(`action.${action.type}`, action);
|
|
15646
|
-
}, [addMessageBubble, dispatch, emitEvent, payload.id, sendAction]);
|
|
15677
|
+
}, [addMessageBubble, dispatch, emitEvent, hasConversation, payload.id, sendAction]);
|
|
15647
15678
|
if (!isExpanded || userHasResponded || !hasLastTransactionEvent || !showSuggestions) {
|
|
15648
15679
|
return null;
|
|
15649
15680
|
}
|
|
@@ -19809,6 +19840,7 @@ const InOutTransition = ({
|
|
|
19809
19840
|
|
|
19810
19841
|
|
|
19811
19842
|
|
|
19843
|
+
|
|
19812
19844
|
|
|
19813
19845
|
|
|
19814
19846
|
const Suggestions = ({
|
|
@@ -19826,6 +19858,7 @@ const Suggestions = ({
|
|
|
19826
19858
|
emitEvent,
|
|
19827
19859
|
sendAction
|
|
19828
19860
|
} = use_seamly_commands();
|
|
19861
|
+
const hasConversation = useSeamlyHasConversation();
|
|
19829
19862
|
const {
|
|
19830
19863
|
isOpen,
|
|
19831
19864
|
setVisibility
|
|
@@ -19888,6 +19921,10 @@ const Suggestions = ({
|
|
|
19888
19921
|
id,
|
|
19889
19922
|
question
|
|
19890
19923
|
}) => {
|
|
19924
|
+
// Do not allow interaction without a conversation
|
|
19925
|
+
if (!hasConversation()) {
|
|
19926
|
+
return;
|
|
19927
|
+
}
|
|
19891
19928
|
if (hasCountdown) {
|
|
19892
19929
|
endCountdown(true);
|
|
19893
19930
|
}
|
|
@@ -19918,7 +19955,7 @@ const Suggestions = ({
|
|
|
19918
19955
|
});
|
|
19919
19956
|
}
|
|
19920
19957
|
focusSkiplinkTarget();
|
|
19921
|
-
}, [addMessageBubble, continueChat, endCountdown, emitEvent, focusSkiplinkTarget, hasCountdown, hasPrompt, isOpen, payload, sendAction, setVisibility]);
|
|
19958
|
+
}, [addMessageBubble, continueChat, endCountdown, emitEvent, focusSkiplinkTarget, hasConversation, hasCountdown, hasPrompt, isOpen, payload, sendAction, setVisibility]);
|
|
19922
19959
|
(0,hooks_.useEffect)(() => {
|
|
19923
19960
|
if (prevSuggestions.current !== suggestions && !hideSuggestions) {
|
|
19924
19961
|
if (hasSuggestions) {
|
|
@@ -22085,6 +22122,19 @@ const upload_Upload = () => {
|
|
|
22085
22122
|
}
|
|
22086
22123
|
prevIsComplete.current = isComplete;
|
|
22087
22124
|
}, [isUploading, isComplete, clearUploads, cancelEntrySelection, focusSkiplinkTarget, sendPolite, t]);
|
|
22125
|
+
|
|
22126
|
+
// Reset form when service no longer allows uploads
|
|
22127
|
+
(0,hooks_.useEffect)(() => {
|
|
22128
|
+
// If we are currently uploading, don't clear the uploads as that
|
|
22129
|
+
// may be confusing to the user.
|
|
22130
|
+
// When the upload completes and the user clicks the submit button,
|
|
22131
|
+
// there will be an error.
|
|
22132
|
+
if (!serviceAllowsUploads && !isUploading) {
|
|
22133
|
+
clearUploads();
|
|
22134
|
+
cancelEntrySelection();
|
|
22135
|
+
focusSkiplinkTarget();
|
|
22136
|
+
}
|
|
22137
|
+
}, [serviceAllowsUploads, isUploading, clearUploads, cancelEntrySelection, focusSkiplinkTarget]);
|
|
22088
22138
|
const handleSubmit = (0,hooks_.useCallback)(({
|
|
22089
22139
|
fileList
|
|
22090
22140
|
}) => {
|
|
@@ -22277,7 +22327,6 @@ const EntryContainer = () => {
|
|
|
22277
22327
|
upload: entry_upload
|
|
22278
22328
|
});
|
|
22279
22329
|
const [renderEntry, setRenderEntry] = (0,hooks_.useState)(() => activeEntry);
|
|
22280
|
-
const [renderEntryOptions, setRenderEntryOptions] = (0,hooks_.useState)(() => activeEntryOptions);
|
|
22281
22330
|
const config = useConfig();
|
|
22282
22331
|
const {
|
|
22283
22332
|
accountAllowsUploads
|
|
@@ -22308,11 +22357,10 @@ const EntryContainer = () => {
|
|
|
22308
22357
|
}, [hasCountdown, hasResumeConversationPrompt, focusFn]);
|
|
22309
22358
|
(0,hooks_.useEffect)(() => {
|
|
22310
22359
|
setRenderEntry(activeEntry);
|
|
22311
|
-
setRenderEntryOptions(activeEntryOptions);
|
|
22312
22360
|
// This focus action is required for auto entry changes. User driven
|
|
22313
22361
|
// changes should be handled in the originating components.
|
|
22314
22362
|
focusFn();
|
|
22315
|
-
}, [activeEntry,
|
|
22363
|
+
}, [activeEntry, focusFn, entryContainer]);
|
|
22316
22364
|
|
|
22317
22365
|
// Check if the active element is inside this container and save it.
|
|
22318
22366
|
containedFocus.current = !!(entryContainer.current && entryContainer.current.contains(document.activeElement));
|
|
@@ -22321,7 +22369,7 @@ const EntryContainer = () => {
|
|
|
22321
22369
|
// Once we do, this property should be moved to that component instead.
|
|
22322
22370
|
const {
|
|
22323
22371
|
allowManualInput = true
|
|
22324
|
-
} =
|
|
22372
|
+
} = activeEntryOptions;
|
|
22325
22373
|
return /*#__PURE__*/(0,jsx_runtime_namespaceObject.jsxs)("div", {
|
|
22326
22374
|
className: css_className('chat__entry'),
|
|
22327
22375
|
ref: entryContainer,
|