andy-widget-react 2.3.1 → 2.3.2
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/README.md +1 -1
- package/dist/index.cjs +29 -9
- package/dist/index.cjs.map +1 -0
- package/dist/index.esm.js +29 -9
- package/dist/index.esm.js.map +1 -0
- package/package.json +2 -2
- package/src/AndyChat.tsx +6 -5
- package/src/SupportChat.tsx +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "andy-widget-react",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Official React Widget for embeddable Andy agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -67,6 +67,6 @@
|
|
|
67
67
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"andy-widget-core": "2.3.
|
|
70
|
+
"andy-widget-core": "2.3.2"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/src/AndyChat.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getHostClasses,
|
|
13
13
|
createBrowserHandoff,
|
|
14
14
|
parseMarkdown,
|
|
15
|
+
escapeHtml,
|
|
15
16
|
CHAT_BUBBLE_DEFAULT_ICON,
|
|
16
17
|
CHAT_BUBBLE_DEFAULT_ICON_URL,
|
|
17
18
|
SVG_ICONS,
|
|
@@ -713,7 +714,7 @@ const SalesAndyChat: React.FC<SalesAndyChatProps> = ({
|
|
|
713
714
|
bubble.setAttribute('aria-label', strings.openChat)
|
|
714
715
|
|
|
715
716
|
const tooltipHTML = tooltip
|
|
716
|
-
? `<span class="andy-chat-bubble__tooltip" role="tooltip">${tooltip}</span>`
|
|
717
|
+
? `<span class="andy-chat-bubble__tooltip" role="tooltip">${escapeHtml(tooltip)}</span>`
|
|
717
718
|
: ''
|
|
718
719
|
bubble.innerHTML = `${CHAT_BUBBLE_DEFAULT_ICON}${tooltipHTML}`
|
|
719
720
|
shadowRef.current.appendChild(bubble)
|
|
@@ -744,7 +745,7 @@ const SalesAndyChat: React.FC<SalesAndyChatProps> = ({
|
|
|
744
745
|
|
|
745
746
|
const tooltipHTML =
|
|
746
747
|
!isOpen && tooltip && !isPillStyle
|
|
747
|
-
? `<span class="andy-chat-bubble__tooltip" role="tooltip">${tooltip}</span>`
|
|
748
|
+
? `<span class="andy-chat-bubble__tooltip" role="tooltip">${escapeHtml(tooltip)}</span>`
|
|
748
749
|
: ''
|
|
749
750
|
|
|
750
751
|
const configUseBrandColor = config?.useBrandColor ?? true
|
|
@@ -762,12 +763,12 @@ const SalesAndyChat: React.FC<SalesAndyChatProps> = ({
|
|
|
762
763
|
bubble.innerHTML = chevronWithStyle
|
|
763
764
|
} else if (isPillStyle && displayLabel) {
|
|
764
765
|
bubble.innerHTML = `
|
|
765
|
-
<span class="andy-chat-bubble__label">${displayLabel}</span>
|
|
766
|
-
<img src="${bubbleLogoUrl}" alt="Chat" class="andy-chat-bubble__icon--pill" style="${darkModeIconStyle}" />
|
|
766
|
+
<span class="andy-chat-bubble__label">${escapeHtml(displayLabel)}</span>
|
|
767
|
+
<img src="${escapeHtml(bubbleLogoUrl)}" alt="Chat" class="andy-chat-bubble__icon--pill" style="${darkModeIconStyle}" />
|
|
767
768
|
`
|
|
768
769
|
} else {
|
|
769
770
|
if (config?.logoUrl) {
|
|
770
|
-
bubble.innerHTML = `<img src="${config.logoUrl}" alt="Chatbot Logo" class="andy-chat-bubble__logo" style="${darkModeIconStyle}" />${tooltipHTML}`
|
|
771
|
+
bubble.innerHTML = `<img src="${escapeHtml(config.logoUrl)}" alt="Chatbot Logo" class="andy-chat-bubble__logo" style="${darkModeIconStyle}" />${tooltipHTML}`
|
|
771
772
|
} else {
|
|
772
773
|
const defaultIconWithStyle = CHAT_BUBBLE_DEFAULT_ICON.replace(
|
|
773
774
|
'class="andy-chat-bubble__icon"',
|
package/src/SupportChat.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react'
|
|
2
2
|
import { createPortal } from 'react-dom'
|
|
3
|
-
import { generateDesignTokenVariablesString, getContrastTextColor, getSupportStylesheet, type SupportTicket } from 'andy-widget-core'
|
|
3
|
+
import { generateDesignTokenVariablesString, getContrastTextColor, getSupportStylesheet, sanitizeUrl, type SupportTicket } from 'andy-widget-core'
|
|
4
4
|
import type { SupportAndyChatProps } from './types'
|
|
5
5
|
import { useSupportChat } from './hooks/useSupportChat'
|
|
6
6
|
|
|
@@ -96,7 +96,7 @@ const SupportPanel: React.FC<SupportAndyChatProps> = ({ support, lang, orientati
|
|
|
96
96
|
</div>
|
|
97
97
|
{state.view === 'conversation' && <form className='andy-support__composer' onSubmit={event => { event.preventDefault(); send() }}><input aria-label={strings.placeholder} placeholder={strings.placeholder} value={draft} maxLength={10000} disabled={!state.config} onChange={event => setDraft(event.target.value)} /><button type='submit' aria-label={strings.send} disabled={state.busy || !state.config || !draft.trim()}>↑</button></form>}
|
|
98
98
|
{state.view === 'request' && state.ticket && (state.ticket.status !== 'resolved' || reopening) && <form className='andy-support__followup' onSubmit={event => { event.preventDefault(); void followup() }}><label>{reopening ? strings.reopening : strings.reply}<textarea rows={3} maxLength={20000} required value={state.followup?.body ?? replyDraft} readOnly={!!state.followup} disabled={state.busy} onChange={event => setReplyDraft(event.target.value)} /></label><button type='submit' className='andy-support__primary' disabled={state.busy || !replyDraft.trim()}>{state.busy ? strings.loading : reopening ? strings.reopen : strings.send}</button></form>}
|
|
99
|
-
<footer className='andy-support__footer'><span>{strings.powered}</span>{state.config?.branding.footer.map(link => <a key={link.url} href={link.url} target='_blank' rel='noopener noreferrer'>{link.label}</a>)}</footer>
|
|
99
|
+
<footer className='andy-support__footer'><span>{strings.powered}</span>{state.config?.branding.footer.map(link => <a key={link.url} href={sanitizeUrl(link.url)} target='_blank' rel='noopener noreferrer'>{link.label}</a>)}</footer>
|
|
100
100
|
</section>}
|
|
101
101
|
</div>, portal)}
|
|
102
102
|
</div>
|