@sevenfold/setto-client 0.24.0 → 0.24.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/dist/setto-client.js +761 -151
- package/dist/setto-client.js.map +1 -1
- package/package.json +1 -1
package/dist/setto-client.js
CHANGED
|
@@ -22035,6 +22035,8 @@ function EditModeShell({ children, themeStore, active }) {
|
|
|
22035
22035
|
}
|
|
22036
22036
|
const VISITOR_KEY = "setto-chat-visitor";
|
|
22037
22037
|
const CLOSE_MS = 210;
|
|
22038
|
+
const MIN_COMPOSER_HEIGHT = 36;
|
|
22039
|
+
const MAX_COMPOSER_HEIGHT = 200;
|
|
22038
22040
|
function visitorId() {
|
|
22039
22041
|
try {
|
|
22040
22042
|
const stored = window.localStorage.getItem(VISITOR_KEY);
|
|
@@ -22053,17 +22055,270 @@ function intro(locale, name) {
|
|
|
22053
22055
|
return norwegian(locale) ? `Hei! Jeg er Barista, ${name ? `${name}s` : "nettstedets"} AI-assistent. Jeg svarer ut fra det teamet har delt her, og hjelper deg videre til dem når det trengs.` : `Hello! I’m Barista, the AI assistant for ${name ?? "this website"}. I answer from what the team has shared here and help you reach them when needed.`;
|
|
22054
22056
|
}
|
|
22055
22057
|
function contactTeam() {
|
|
22056
|
-
const link = document.querySelector(
|
|
22058
|
+
const link = document.querySelector(
|
|
22059
|
+
'a[href*="kontakt" i], a[href*="contact" i], a[href^="mailto:"]'
|
|
22060
|
+
);
|
|
22057
22061
|
if (link) link.click();
|
|
22058
22062
|
else window.location.hash = "kontakt";
|
|
22059
22063
|
}
|
|
22060
22064
|
function validColor(value, fallback) {
|
|
22061
|
-
return value && (/^#[0-9a-f]{3,8}$/i.test(value) || /^
|
|
22065
|
+
return value && (/^#[0-9a-f]{3,8}$/i.test(value) || /^rgba?\(/i.test(value)) ? value : fallback;
|
|
22062
22066
|
}
|
|
22063
22067
|
function chatPalette(colors) {
|
|
22064
22068
|
const values = colors?.map((color) => color.value) ?? [];
|
|
22065
|
-
|
|
22066
|
-
|
|
22069
|
+
return {
|
|
22070
|
+
"--setto-chat-crema": validColor(values[0], "#F2EBDF"),
|
|
22071
|
+
"--setto-chat-raised": validColor(values[1], "#FAF6EE"),
|
|
22072
|
+
"--setto-chat-canvas": validColor(values[2], "#FFFFFF"),
|
|
22073
|
+
"--setto-chat-ink": validColor(values[3], "#211711"),
|
|
22074
|
+
"--setto-chat-accent": validColor(values.at(-2) ?? values.at(-1), "#C4502A")
|
|
22075
|
+
};
|
|
22076
|
+
}
|
|
22077
|
+
function MenuIcon() {
|
|
22078
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "22", height: "22", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
22079
|
+
"path",
|
|
22080
|
+
{
|
|
22081
|
+
d: "M4 7h16M4 12h16M4 17h16",
|
|
22082
|
+
fill: "none",
|
|
22083
|
+
stroke: "currentColor",
|
|
22084
|
+
strokeWidth: "2",
|
|
22085
|
+
strokeLinecap: "round"
|
|
22086
|
+
}
|
|
22087
|
+
) });
|
|
22088
|
+
}
|
|
22089
|
+
function CloseIcon({ size = 22 }) {
|
|
22090
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: size, height: size, "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
22091
|
+
"path",
|
|
22092
|
+
{
|
|
22093
|
+
d: "M6 6l12 12M18 6L6 18",
|
|
22094
|
+
fill: "none",
|
|
22095
|
+
stroke: "currentColor",
|
|
22096
|
+
strokeWidth: "2.25",
|
|
22097
|
+
strokeLinecap: "round"
|
|
22098
|
+
}
|
|
22099
|
+
) });
|
|
22100
|
+
}
|
|
22101
|
+
function PlusIcon() {
|
|
22102
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
22103
|
+
"path",
|
|
22104
|
+
{
|
|
22105
|
+
d: "M12 5v14M5 12h14",
|
|
22106
|
+
fill: "none",
|
|
22107
|
+
stroke: "currentColor",
|
|
22108
|
+
strokeWidth: "2",
|
|
22109
|
+
strokeLinecap: "round"
|
|
22110
|
+
}
|
|
22111
|
+
) });
|
|
22112
|
+
}
|
|
22113
|
+
function ArrowIcon() {
|
|
22114
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
22115
|
+
"path",
|
|
22116
|
+
{
|
|
22117
|
+
d: "M12 19V5M5 12l7-7 7 7",
|
|
22118
|
+
fill: "none",
|
|
22119
|
+
stroke: "currentColor",
|
|
22120
|
+
strokeWidth: "2",
|
|
22121
|
+
strokeLinejoin: "round",
|
|
22122
|
+
strokeLinecap: "round"
|
|
22123
|
+
}
|
|
22124
|
+
) });
|
|
22125
|
+
}
|
|
22126
|
+
function BaristaIcon() {
|
|
22127
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "20", height: "20", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
22128
|
+
"path",
|
|
22129
|
+
{
|
|
22130
|
+
d: "M12 2.8c.65 5.25 3.95 8.55 9.2 9.2-5.25.65-8.55 3.95-9.2 9.2-.65-5.25-3.95-8.55-9.2-9.2 5.25-.65 8.55-3.95 9.2-9.2Z",
|
|
22131
|
+
fill: "currentColor"
|
|
22132
|
+
}
|
|
22133
|
+
) });
|
|
22134
|
+
}
|
|
22135
|
+
function SiteChatComposer({
|
|
22136
|
+
value,
|
|
22137
|
+
onChange,
|
|
22138
|
+
onSubmit,
|
|
22139
|
+
busy,
|
|
22140
|
+
queued,
|
|
22141
|
+
placeholder,
|
|
22142
|
+
attachLabel,
|
|
22143
|
+
sendLabel,
|
|
22144
|
+
removeLabel,
|
|
22145
|
+
locale,
|
|
22146
|
+
attachments,
|
|
22147
|
+
onAttach,
|
|
22148
|
+
onRemoveAttachment
|
|
22149
|
+
}) {
|
|
22150
|
+
const textareaRef = useRef(null);
|
|
22151
|
+
const fileRef = useRef(null);
|
|
22152
|
+
const wasBusy = useRef(busy);
|
|
22153
|
+
const [focused, setFocused] = useState(false);
|
|
22154
|
+
useEffect(() => {
|
|
22155
|
+
const textarea = textareaRef.current;
|
|
22156
|
+
if (!textarea) return;
|
|
22157
|
+
textarea.style.height = "auto";
|
|
22158
|
+
const height = Math.min(
|
|
22159
|
+
Math.max(textarea.scrollHeight, MIN_COMPOSER_HEIGHT),
|
|
22160
|
+
MAX_COMPOSER_HEIGHT
|
|
22161
|
+
);
|
|
22162
|
+
textarea.style.height = `${height}px`;
|
|
22163
|
+
}, [value]);
|
|
22164
|
+
useEffect(() => {
|
|
22165
|
+
if (wasBusy.current && !busy) textareaRef.current?.focus();
|
|
22166
|
+
wasBusy.current = busy;
|
|
22167
|
+
}, [busy]);
|
|
22168
|
+
function send() {
|
|
22169
|
+
if (!value.trim() && attachments.length === 0) return;
|
|
22170
|
+
onSubmit();
|
|
22171
|
+
}
|
|
22172
|
+
function handleSubmit(event) {
|
|
22173
|
+
event.preventDefault();
|
|
22174
|
+
send();
|
|
22175
|
+
}
|
|
22176
|
+
function handleKeyDown(event) {
|
|
22177
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
22178
|
+
event.preventDefault();
|
|
22179
|
+
send();
|
|
22180
|
+
}
|
|
22181
|
+
}
|
|
22182
|
+
const canSend = value.trim().length > 0 || attachments.length > 0;
|
|
22183
|
+
const open = focused || value.length > 0 || attachments.length > 0;
|
|
22184
|
+
return /* @__PURE__ */ jsxs(
|
|
22185
|
+
"form",
|
|
22186
|
+
{
|
|
22187
|
+
className: `setto-chat__composer${open ? " is-open" : ""}`,
|
|
22188
|
+
onSubmit: handleSubmit,
|
|
22189
|
+
onPointerDown: (event) => {
|
|
22190
|
+
if (event.target === event.currentTarget) textareaRef.current?.focus();
|
|
22191
|
+
},
|
|
22192
|
+
children: [
|
|
22193
|
+
attachments.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "setto-chat__attachments", children: attachments.map((attachment, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
22194
|
+
/* @__PURE__ */ jsx("img", { src: attachment.preview, alt: attachment.file.name }),
|
|
22195
|
+
/* @__PURE__ */ jsx(
|
|
22196
|
+
"button",
|
|
22197
|
+
{
|
|
22198
|
+
type: "button",
|
|
22199
|
+
onClick: () => onRemoveAttachment(index),
|
|
22200
|
+
"aria-label": `${removeLabel} ${attachment.file.name}`,
|
|
22201
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { size: 12 })
|
|
22202
|
+
}
|
|
22203
|
+
)
|
|
22204
|
+
] }, `${attachment.file.name}-${attachment.preview}`)) }) : null,
|
|
22205
|
+
/* @__PURE__ */ jsx(
|
|
22206
|
+
"textarea",
|
|
22207
|
+
{
|
|
22208
|
+
ref: textareaRef,
|
|
22209
|
+
lang: norwegian(locale) ? "nb" : "en",
|
|
22210
|
+
spellCheck: true,
|
|
22211
|
+
value,
|
|
22212
|
+
onChange: (event) => onChange(event.target.value),
|
|
22213
|
+
onKeyDown: handleKeyDown,
|
|
22214
|
+
onFocus: () => setFocused(true),
|
|
22215
|
+
onBlur: () => setFocused(false),
|
|
22216
|
+
placeholder,
|
|
22217
|
+
rows: 1,
|
|
22218
|
+
maxLength: 1500
|
|
22219
|
+
}
|
|
22220
|
+
),
|
|
22221
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__composer-tools", children: [
|
|
22222
|
+
/* @__PURE__ */ jsx(
|
|
22223
|
+
"input",
|
|
22224
|
+
{
|
|
22225
|
+
ref: fileRef,
|
|
22226
|
+
type: "file",
|
|
22227
|
+
accept: "image/*",
|
|
22228
|
+
multiple: true,
|
|
22229
|
+
hidden: true,
|
|
22230
|
+
onChange: (event) => {
|
|
22231
|
+
const selected = Array.from(event.target.files ?? []);
|
|
22232
|
+
event.target.value = "";
|
|
22233
|
+
if (selected.length) onAttach(selected);
|
|
22234
|
+
}
|
|
22235
|
+
}
|
|
22236
|
+
),
|
|
22237
|
+
/* @__PURE__ */ jsx(
|
|
22238
|
+
"button",
|
|
22239
|
+
{
|
|
22240
|
+
type: "button",
|
|
22241
|
+
className: "setto-chat__attach",
|
|
22242
|
+
onClick: () => fileRef.current?.click(),
|
|
22243
|
+
disabled: busy,
|
|
22244
|
+
"aria-label": attachLabel,
|
|
22245
|
+
title: attachLabel,
|
|
22246
|
+
children: /* @__PURE__ */ jsx(PlusIcon, {})
|
|
22247
|
+
}
|
|
22248
|
+
),
|
|
22249
|
+
/* @__PURE__ */ jsx(
|
|
22250
|
+
"button",
|
|
22251
|
+
{
|
|
22252
|
+
type: "submit",
|
|
22253
|
+
className: `setto-chat__send${queued ? " is-queued" : ""}`,
|
|
22254
|
+
disabled: !canSend,
|
|
22255
|
+
"aria-busy": queued,
|
|
22256
|
+
"aria-label": sendLabel,
|
|
22257
|
+
children: /* @__PURE__ */ jsx(ArrowIcon, {})
|
|
22258
|
+
}
|
|
22259
|
+
)
|
|
22260
|
+
] })
|
|
22261
|
+
]
|
|
22262
|
+
}
|
|
22263
|
+
);
|
|
22264
|
+
}
|
|
22265
|
+
function useChatViewport(active, logRef) {
|
|
22266
|
+
useEffect(() => {
|
|
22267
|
+
if (!active) return;
|
|
22268
|
+
const root = document.documentElement;
|
|
22269
|
+
const body = document.body;
|
|
22270
|
+
const visualViewport = window.visualViewport;
|
|
22271
|
+
const savedScrollY = window.scrollY;
|
|
22272
|
+
const previous = {
|
|
22273
|
+
rootOverflow: root.style.overflow,
|
|
22274
|
+
rootOverscroll: root.style.overscrollBehavior,
|
|
22275
|
+
bodyPosition: body.style.position,
|
|
22276
|
+
bodyTop: body.style.top,
|
|
22277
|
+
bodyLeft: body.style.left,
|
|
22278
|
+
bodyRight: body.style.right,
|
|
22279
|
+
bodyWidth: body.style.width,
|
|
22280
|
+
bodyOverflow: body.style.overflow
|
|
22281
|
+
};
|
|
22282
|
+
root.style.overflow = "hidden";
|
|
22283
|
+
root.style.overscrollBehavior = "none";
|
|
22284
|
+
body.style.position = "fixed";
|
|
22285
|
+
body.style.top = `-${savedScrollY}px`;
|
|
22286
|
+
body.style.left = "0";
|
|
22287
|
+
body.style.right = "0";
|
|
22288
|
+
body.style.width = "100%";
|
|
22289
|
+
body.style.overflow = "hidden";
|
|
22290
|
+
const update = () => {
|
|
22291
|
+
const height = Math.round(visualViewport?.height ?? window.innerHeight);
|
|
22292
|
+
const top = Math.round(visualViewport?.offsetTop ?? 0);
|
|
22293
|
+
root.style.setProperty("--setto-chat-height", `${height}px`);
|
|
22294
|
+
root.style.setProperty("--setto-chat-top", `${top}px`);
|
|
22295
|
+
if (window.scrollY !== 0) window.scrollTo(0, 0);
|
|
22296
|
+
window.requestAnimationFrame(() => {
|
|
22297
|
+
const log = logRef.current;
|
|
22298
|
+
if (log) log.scrollTop = log.scrollHeight;
|
|
22299
|
+
});
|
|
22300
|
+
};
|
|
22301
|
+
update();
|
|
22302
|
+
visualViewport?.addEventListener("resize", update);
|
|
22303
|
+
visualViewport?.addEventListener("scroll", update);
|
|
22304
|
+
window.addEventListener("orientationchange", update);
|
|
22305
|
+
return () => {
|
|
22306
|
+
visualViewport?.removeEventListener("resize", update);
|
|
22307
|
+
visualViewport?.removeEventListener("scroll", update);
|
|
22308
|
+
window.removeEventListener("orientationchange", update);
|
|
22309
|
+
root.style.removeProperty("--setto-chat-height");
|
|
22310
|
+
root.style.removeProperty("--setto-chat-top");
|
|
22311
|
+
root.style.overflow = previous.rootOverflow;
|
|
22312
|
+
root.style.overscrollBehavior = previous.rootOverscroll;
|
|
22313
|
+
body.style.position = previous.bodyPosition;
|
|
22314
|
+
body.style.top = previous.bodyTop;
|
|
22315
|
+
body.style.left = previous.bodyLeft;
|
|
22316
|
+
body.style.right = previous.bodyRight;
|
|
22317
|
+
body.style.width = previous.bodyWidth;
|
|
22318
|
+
body.style.overflow = previous.bodyOverflow;
|
|
22319
|
+
window.scrollTo(0, savedScrollY);
|
|
22320
|
+
};
|
|
22321
|
+
}, [active, logRef]);
|
|
22067
22322
|
}
|
|
22068
22323
|
function SettoChat() {
|
|
22069
22324
|
const { config } = useSetto();
|
|
@@ -22078,37 +22333,119 @@ function SettoChat() {
|
|
|
22078
22333
|
const [draft, setDraft] = useState("");
|
|
22079
22334
|
const [files, setFiles] = useState([]);
|
|
22080
22335
|
const [sending, setSending] = useState(false);
|
|
22336
|
+
const [queued, setQueued] = useState(false);
|
|
22081
22337
|
const [loadingConversation, setLoadingConversation] = useState(false);
|
|
22082
|
-
const [availability, setAvailability] = useState({
|
|
22338
|
+
const [availability, setAvailability] = useState({
|
|
22339
|
+
humanAvailable: false,
|
|
22340
|
+
avatarUrl: null
|
|
22341
|
+
});
|
|
22083
22342
|
const [leadOpen, setLeadOpen] = useState(false);
|
|
22084
22343
|
const [leadStatus, setLeadStatus] = useState("idle");
|
|
22085
|
-
const [lead, setLead] = useState({
|
|
22344
|
+
const [lead, setLead] = useState({
|
|
22345
|
+
name: "",
|
|
22346
|
+
email: "",
|
|
22347
|
+
phone: "",
|
|
22348
|
+
interest: "",
|
|
22349
|
+
consent: false
|
|
22350
|
+
});
|
|
22086
22351
|
const conversationId = useRef(null);
|
|
22087
22352
|
const visitor = useRef(null);
|
|
22088
22353
|
const logRef = useRef(null);
|
|
22089
|
-
const
|
|
22354
|
+
const filesRef = useRef([]);
|
|
22090
22355
|
const formId = useId();
|
|
22091
22356
|
const palette = useMemo(() => chatPalette(config.brandColors), [config.brandColors]);
|
|
22092
22357
|
useChatStyles();
|
|
22358
|
+
useChatViewport(mounted, logRef);
|
|
22093
22359
|
const locale = i18n.language || "no";
|
|
22094
22360
|
const isNo = norwegian(locale);
|
|
22095
22361
|
const siteName = settings?.displayName?.trim() || config.displayName?.trim() || null;
|
|
22096
|
-
const labels = isNo ? {
|
|
22097
|
-
|
|
22098
|
-
|
|
22362
|
+
const labels = isNo ? {
|
|
22363
|
+
open: siteName ? `Åpne chat med ${siteName}` : "Åpne chat",
|
|
22364
|
+
close: "Lukk chatten",
|
|
22365
|
+
title: "Spør Barista",
|
|
22366
|
+
chats: "Chats",
|
|
22367
|
+
newChat: "Ny chat",
|
|
22368
|
+
disclosure: "AI-assistent · svarer fra nettstedets godkjente informasjon",
|
|
22369
|
+
placeholder: "Hva vil du spørre om?",
|
|
22370
|
+
send: "Send melding",
|
|
22371
|
+
sending: "Svarer …",
|
|
22372
|
+
attach: "Legg ved bilde",
|
|
22373
|
+
remove: "Fjern",
|
|
22374
|
+
contact: "Kontakt teamet",
|
|
22375
|
+
followUp: "Be om oppfølging",
|
|
22376
|
+
followUpTitle: "La teamet følge opp",
|
|
22377
|
+
followUpDetail: "Legg igjen kontaktinformasjon hvis du vil at teamet skal følge opp denne samtalen.",
|
|
22378
|
+
name: "Navn",
|
|
22379
|
+
email: "E-post",
|
|
22380
|
+
phone: "Telefon",
|
|
22381
|
+
interest: "Hva vil du ha hjelp med?",
|
|
22382
|
+
consent: "Ja, teamet kan bruke opplysningene mine til å følge opp denne henvendelsen.",
|
|
22383
|
+
leadSend: "Send forespørsel",
|
|
22384
|
+
leadSent: "Takk — forespørselen er sendt til teamet.",
|
|
22385
|
+
leadFailed: "Kunne ikke lagre forespørselen. Prøv igjen eller kontakt teamet direkte.",
|
|
22386
|
+
leadConversation: "Still et spørsmål først, så kan vi knytte oppfølgingen til samtalen.",
|
|
22387
|
+
failed: "Jeg får ikke svart akkurat nå. Kontakt gjerne teamet direkte.",
|
|
22388
|
+
image: "Bilde",
|
|
22389
|
+
team: "Teamet",
|
|
22390
|
+
emptyChats: "Nye samtaler du starter her vises i denne listen."
|
|
22391
|
+
} : {
|
|
22392
|
+
open: siteName ? `Open chat with ${siteName}` : "Open chat",
|
|
22393
|
+
close: "Close chat",
|
|
22394
|
+
title: "Ask Barista",
|
|
22395
|
+
chats: "Chats",
|
|
22396
|
+
newChat: "New chat",
|
|
22397
|
+
disclosure: "AI assistant · answers from this website’s approved information",
|
|
22398
|
+
placeholder: "What would you like to ask?",
|
|
22399
|
+
send: "Send message",
|
|
22400
|
+
sending: "Replying …",
|
|
22401
|
+
attach: "Attach image",
|
|
22402
|
+
remove: "Remove",
|
|
22403
|
+
contact: "Contact the team",
|
|
22404
|
+
followUp: "Ask for follow-up",
|
|
22405
|
+
followUpTitle: "Let the team follow up",
|
|
22406
|
+
followUpDetail: "Leave contact details if you want the team to follow up on this conversation.",
|
|
22407
|
+
name: "Name",
|
|
22408
|
+
email: "Email",
|
|
22409
|
+
phone: "Phone",
|
|
22410
|
+
interest: "What would you like help with?",
|
|
22411
|
+
consent: "Yes, the team may use my details to follow up on this enquiry.",
|
|
22412
|
+
leadSend: "Send request",
|
|
22413
|
+
leadSent: "Thanks — your request has been sent to the team.",
|
|
22414
|
+
leadFailed: "We could not save your request. Please try again or contact the team directly.",
|
|
22415
|
+
leadConversation: "Ask a question first so we can link the follow-up to this conversation.",
|
|
22416
|
+
failed: "I cannot reply right now. Please contact the team directly.",
|
|
22417
|
+
image: "Image",
|
|
22418
|
+
team: "The team",
|
|
22419
|
+
emptyChats: "New conversations you start here will appear in this list."
|
|
22420
|
+
};
|
|
22421
|
+
function ensureVisitor() {
|
|
22422
|
+
return visitor.current ??= visitorId();
|
|
22423
|
+
}
|
|
22424
|
+
async function loadChats() {
|
|
22099
22425
|
const id = visitor.current;
|
|
22100
22426
|
if (!id) return;
|
|
22101
22427
|
try {
|
|
22102
|
-
const
|
|
22103
|
-
|
|
22428
|
+
const query = new URLSearchParams({ visitorId: id });
|
|
22429
|
+
const response = await fetch(
|
|
22430
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/conversations/public?${query}`,
|
|
22431
|
+
{ headers: { Accept: "application/json" } }
|
|
22432
|
+
);
|
|
22433
|
+
if (response.ok) {
|
|
22434
|
+
const body = await response.json();
|
|
22435
|
+
setConversations(body.conversations);
|
|
22436
|
+
}
|
|
22104
22437
|
} catch {
|
|
22105
22438
|
}
|
|
22106
|
-
}
|
|
22107
|
-
|
|
22439
|
+
}
|
|
22440
|
+
async function loadConversation(id) {
|
|
22108
22441
|
const visitorIdValue = ensureVisitor();
|
|
22109
22442
|
setLoadingConversation(true);
|
|
22110
22443
|
try {
|
|
22111
|
-
const
|
|
22444
|
+
const query = new URLSearchParams({ visitorId: visitorIdValue });
|
|
22445
|
+
const response = await fetch(
|
|
22446
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/conversations/${encodeURIComponent(id)}/public?${query}`,
|
|
22447
|
+
{ headers: { Accept: "application/json" } }
|
|
22448
|
+
);
|
|
22112
22449
|
if (!response.ok) return;
|
|
22113
22450
|
const next = await response.json();
|
|
22114
22451
|
conversationId.current = next.conversationId;
|
|
@@ -22118,11 +22455,13 @@ function SettoChat() {
|
|
|
22118
22455
|
} finally {
|
|
22119
22456
|
setLoadingConversation(false);
|
|
22120
22457
|
}
|
|
22121
|
-
}
|
|
22458
|
+
}
|
|
22122
22459
|
useEffect(() => {
|
|
22123
22460
|
if (window.location.pathname.startsWith("/setto")) return;
|
|
22124
22461
|
let cancelled = false;
|
|
22125
|
-
fetch(`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/settings/public`, {
|
|
22462
|
+
fetch(`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/settings/public`, {
|
|
22463
|
+
headers: { Accept: "application/json" }
|
|
22464
|
+
}).then(async (response) => response.ok ? await response.json() : null).then((next) => {
|
|
22126
22465
|
if (!cancelled && next?.enabled) setSettings(next);
|
|
22127
22466
|
}).catch(() => void 0);
|
|
22128
22467
|
return () => {
|
|
@@ -22132,7 +22471,9 @@ function SettoChat() {
|
|
|
22132
22471
|
useEffect(() => {
|
|
22133
22472
|
if (!settings) return;
|
|
22134
22473
|
let cancelled = false;
|
|
22135
|
-
const refresh = () => fetch(`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/availability/public`, {
|
|
22474
|
+
const refresh = () => fetch(`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/availability/public`, {
|
|
22475
|
+
headers: { Accept: "application/json" }
|
|
22476
|
+
}).then(async (response) => response.ok ? await response.json() : null).then((next) => {
|
|
22136
22477
|
if (!cancelled && next) setAvailability(next);
|
|
22137
22478
|
}).catch(() => void 0);
|
|
22138
22479
|
void refresh();
|
|
@@ -22143,18 +22484,40 @@ function SettoChat() {
|
|
|
22143
22484
|
};
|
|
22144
22485
|
}, [apiUrl, config.siteId, settings]);
|
|
22145
22486
|
useEffect(() => {
|
|
22146
|
-
if (mounted
|
|
22147
|
-
|
|
22487
|
+
if (!mounted || !settings || conversationId.current) return;
|
|
22488
|
+
const welcome = intro(locale, settings.displayName ?? void 0);
|
|
22489
|
+
setMessages((current) => {
|
|
22490
|
+
if (current.length === 0) return [{ role: "assistant", content: welcome }];
|
|
22491
|
+
if (current.length === 1 && current[0]?.role === "assistant" && !current[0].id) {
|
|
22492
|
+
return current[0].content === welcome ? current : [{ role: "assistant", content: welcome }];
|
|
22493
|
+
}
|
|
22494
|
+
return current;
|
|
22495
|
+
});
|
|
22496
|
+
}, [mounted, settings, locale]);
|
|
22148
22497
|
useEffect(() => {
|
|
22149
|
-
if (mounted)
|
|
22150
|
-
|
|
22151
|
-
|
|
22498
|
+
if (!mounted) return;
|
|
22499
|
+
const log = logRef.current;
|
|
22500
|
+
if (log) log.scrollTo({ top: log.scrollHeight, behavior: sending ? "auto" : "smooth" });
|
|
22501
|
+
}, [messages, mounted, sending, leadOpen]);
|
|
22502
|
+
useEffect(() => {
|
|
22503
|
+
filesRef.current = files;
|
|
22504
|
+
}, [files]);
|
|
22505
|
+
useEffect(
|
|
22506
|
+
() => () => {
|
|
22507
|
+
for (const image of filesRef.current) URL.revokeObjectURL(image.preview);
|
|
22508
|
+
},
|
|
22509
|
+
[]
|
|
22510
|
+
);
|
|
22152
22511
|
useEffect(() => {
|
|
22153
22512
|
if (!mounted || !conversationId.current || !visitor.current || sending) return;
|
|
22154
22513
|
let cancelled = false;
|
|
22155
22514
|
const refresh = async () => {
|
|
22156
22515
|
try {
|
|
22157
|
-
const
|
|
22516
|
+
const query = new URLSearchParams({ visitorId: visitor.current });
|
|
22517
|
+
const response = await fetch(
|
|
22518
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/conversations/${encodeURIComponent(conversationId.current)}/public?${query}`,
|
|
22519
|
+
{ headers: { Accept: "application/json" } }
|
|
22520
|
+
);
|
|
22158
22521
|
if (!response.ok || cancelled) return;
|
|
22159
22522
|
const next = await response.json();
|
|
22160
22523
|
if (!cancelled) setMessages(next.messages);
|
|
@@ -22167,53 +22530,122 @@ function SettoChat() {
|
|
|
22167
22530
|
window.clearInterval(timer);
|
|
22168
22531
|
};
|
|
22169
22532
|
}, [apiUrl, config.siteId, mounted, sending]);
|
|
22533
|
+
useEffect(() => {
|
|
22534
|
+
if (!sending && queued) {
|
|
22535
|
+
setQueued(false);
|
|
22536
|
+
void sendTurn();
|
|
22537
|
+
}
|
|
22538
|
+
}, [sending, queued]);
|
|
22539
|
+
useEffect(() => {
|
|
22540
|
+
if (!mounted) return;
|
|
22541
|
+
const closeOnEscape = (event) => {
|
|
22542
|
+
if (event.key === "Escape") hide();
|
|
22543
|
+
};
|
|
22544
|
+
window.addEventListener("keydown", closeOnEscape);
|
|
22545
|
+
return () => window.removeEventListener("keydown", closeOnEscape);
|
|
22546
|
+
}, [mounted]);
|
|
22170
22547
|
if (!settings || window.location.pathname.startsWith("/setto")) return null;
|
|
22171
|
-
|
|
22548
|
+
function show() {
|
|
22172
22549
|
setMounted(true);
|
|
22173
22550
|
window.requestAnimationFrame(() => setVisible(true));
|
|
22174
22551
|
ensureVisitor();
|
|
22175
22552
|
void loadChats();
|
|
22176
|
-
}
|
|
22177
|
-
|
|
22553
|
+
}
|
|
22554
|
+
function hide() {
|
|
22555
|
+
if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
|
|
22178
22556
|
setVisible(false);
|
|
22179
22557
|
window.setTimeout(() => {
|
|
22180
22558
|
setMounted(false);
|
|
22181
22559
|
setDrawer(false);
|
|
22182
22560
|
}, CLOSE_MS);
|
|
22183
|
-
}
|
|
22184
|
-
|
|
22561
|
+
}
|
|
22562
|
+
function clearPendingFiles() {
|
|
22563
|
+
setFiles((current) => {
|
|
22564
|
+
for (const image of current) URL.revokeObjectURL(image.preview);
|
|
22565
|
+
return [];
|
|
22566
|
+
});
|
|
22567
|
+
}
|
|
22568
|
+
function startNew() {
|
|
22185
22569
|
conversationId.current = null;
|
|
22186
|
-
setMessages([{ role: "assistant", content: intro(locale, settings
|
|
22570
|
+
setMessages([{ role: "assistant", content: intro(locale, settings?.displayName ?? void 0) }]);
|
|
22571
|
+
setDraft("");
|
|
22572
|
+
setQueued(false);
|
|
22187
22573
|
setLeadOpen(false);
|
|
22188
22574
|
setDrawer(false);
|
|
22189
|
-
|
|
22190
|
-
}
|
|
22191
|
-
|
|
22192
|
-
|
|
22575
|
+
clearPendingFiles();
|
|
22576
|
+
}
|
|
22577
|
+
function addFiles(selected) {
|
|
22578
|
+
setFiles((current) => {
|
|
22579
|
+
const available = Math.max(0, 4 - current.length);
|
|
22580
|
+
const accepted = selected.filter((file) => file.type.startsWith("image/")).slice(0, available).map((file) => ({ file, preview: URL.createObjectURL(file) }));
|
|
22581
|
+
return [...current, ...accepted];
|
|
22582
|
+
});
|
|
22583
|
+
}
|
|
22584
|
+
function removeFile(index) {
|
|
22585
|
+
setFiles((current) => {
|
|
22586
|
+
const removed = current[index];
|
|
22587
|
+
if (removed) URL.revokeObjectURL(removed.preview);
|
|
22588
|
+
return current.filter((_, itemIndex) => itemIndex !== index);
|
|
22589
|
+
});
|
|
22590
|
+
}
|
|
22591
|
+
function queueOrSend() {
|
|
22592
|
+
if (!draft.trim() && files.length === 0) return;
|
|
22593
|
+
if (sending) {
|
|
22594
|
+
setQueued(true);
|
|
22595
|
+
return;
|
|
22596
|
+
}
|
|
22597
|
+
void sendTurn();
|
|
22598
|
+
}
|
|
22599
|
+
async function sendTurn() {
|
|
22193
22600
|
const content = draft.trim();
|
|
22194
|
-
|
|
22601
|
+
const turnFiles = files;
|
|
22602
|
+
if (!content && turnFiles.length === 0) return;
|
|
22195
22603
|
setDraft("");
|
|
22604
|
+
setFiles([]);
|
|
22196
22605
|
setSending(true);
|
|
22197
22606
|
const visitorIdValue = ensureVisitor();
|
|
22198
22607
|
try {
|
|
22199
22608
|
const uploaded = [];
|
|
22200
|
-
for (const image of
|
|
22201
|
-
const file = image.file;
|
|
22609
|
+
for (const image of turnFiles) {
|
|
22202
22610
|
const form = new FormData();
|
|
22203
22611
|
form.set("visitorId", visitorIdValue);
|
|
22204
22612
|
if (conversationId.current) form.set("conversationId", conversationId.current);
|
|
22205
22613
|
form.set("locale", locale);
|
|
22206
22614
|
form.set("page", window.location.href);
|
|
22207
|
-
form.set("file", file, file.name);
|
|
22208
|
-
const response2 = await fetch(
|
|
22615
|
+
form.set("file", image.file, image.file.name);
|
|
22616
|
+
const response2 = await fetch(
|
|
22617
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/attachments`,
|
|
22618
|
+
{ method: "POST", body: form }
|
|
22619
|
+
);
|
|
22209
22620
|
if (!response2.ok) throw new Error("image_upload_failed");
|
|
22210
22621
|
const body = await response2.json();
|
|
22211
22622
|
conversationId.current = body.conversationId;
|
|
22212
22623
|
uploaded.push(body.attachment);
|
|
22213
22624
|
}
|
|
22214
|
-
|
|
22215
|
-
|
|
22216
|
-
|
|
22625
|
+
setMessages((previous) => [
|
|
22626
|
+
...previous,
|
|
22627
|
+
{
|
|
22628
|
+
role: "visitor",
|
|
22629
|
+
content: content || `[${labels.image}]`,
|
|
22630
|
+
attachments: uploaded
|
|
22631
|
+
},
|
|
22632
|
+
{ role: "assistant", content: "" }
|
|
22633
|
+
]);
|
|
22634
|
+
const response = await fetch(
|
|
22635
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/messages`,
|
|
22636
|
+
{
|
|
22637
|
+
method: "POST",
|
|
22638
|
+
headers: { "Content-Type": "application/json", Accept: "text/plain, application/json" },
|
|
22639
|
+
body: JSON.stringify({
|
|
22640
|
+
conversationId: conversationId.current ?? void 0,
|
|
22641
|
+
visitorId: visitorIdValue,
|
|
22642
|
+
locale,
|
|
22643
|
+
page: window.location.href,
|
|
22644
|
+
message: content || void 0,
|
|
22645
|
+
attachmentIds: uploaded.map((attachment) => attachment.id)
|
|
22646
|
+
})
|
|
22647
|
+
}
|
|
22648
|
+
);
|
|
22217
22649
|
const headerConversation = response.headers.get("X-Setto-Conversation");
|
|
22218
22650
|
if (headerConversation) conversationId.current = headerConversation;
|
|
22219
22651
|
if (!response.ok) throw new Error(`chat_failed_${response.status}`);
|
|
@@ -22233,16 +22665,19 @@ function SettoChat() {
|
|
|
22233
22665
|
setMessages((previous) => replaceLastAssistant(previous, answer));
|
|
22234
22666
|
}
|
|
22235
22667
|
answer += decoder.decode();
|
|
22236
|
-
if (!answer.trim())
|
|
22668
|
+
if (!answer.trim()) {
|
|
22669
|
+
setMessages((previous) => replaceLastAssistant(previous, labels.failed));
|
|
22670
|
+
}
|
|
22237
22671
|
}
|
|
22238
22672
|
void loadChats();
|
|
22239
22673
|
} catch {
|
|
22240
22674
|
setMessages((previous) => replaceLastAssistant(previous, labels.failed));
|
|
22241
22675
|
} finally {
|
|
22676
|
+
for (const image of turnFiles) URL.revokeObjectURL(image.preview);
|
|
22242
22677
|
setSending(false);
|
|
22243
22678
|
}
|
|
22244
|
-
}
|
|
22245
|
-
|
|
22679
|
+
}
|
|
22680
|
+
async function submitLead(event) {
|
|
22246
22681
|
event.preventDefault();
|
|
22247
22682
|
if (leadStatus === "sending" || !conversationId.current || !visitor.current) {
|
|
22248
22683
|
setLeadStatus("failed");
|
|
@@ -22250,109 +22685,284 @@ function SettoChat() {
|
|
|
22250
22685
|
}
|
|
22251
22686
|
setLeadStatus("sending");
|
|
22252
22687
|
try {
|
|
22253
|
-
const response = await fetch(
|
|
22688
|
+
const response = await fetch(
|
|
22689
|
+
`${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/leads`,
|
|
22690
|
+
{
|
|
22691
|
+
method: "POST",
|
|
22692
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
22693
|
+
body: JSON.stringify({
|
|
22694
|
+
conversationId: conversationId.current,
|
|
22695
|
+
visitorId: visitor.current,
|
|
22696
|
+
consent: lead.consent,
|
|
22697
|
+
name: lead.name.trim() || void 0,
|
|
22698
|
+
email: lead.email.trim() || void 0,
|
|
22699
|
+
phone: lead.phone.trim() || void 0,
|
|
22700
|
+
interest: lead.interest.trim() || void 0
|
|
22701
|
+
})
|
|
22702
|
+
}
|
|
22703
|
+
);
|
|
22254
22704
|
if (!response.ok) throw new Error("lead_failed");
|
|
22255
22705
|
setLeadStatus("sent");
|
|
22256
22706
|
} catch {
|
|
22257
22707
|
setLeadStatus("failed");
|
|
22258
22708
|
}
|
|
22259
|
-
}
|
|
22260
|
-
return /* @__PURE__ */ jsxs(
|
|
22261
|
-
|
|
22262
|
-
|
|
22263
|
-
|
|
22264
|
-
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
|
|
22268
|
-
|
|
22269
|
-
|
|
22270
|
-
|
|
22271
|
-
|
|
22272
|
-
|
|
22273
|
-
|
|
22274
|
-
|
|
22275
|
-
|
|
22276
|
-
|
|
22277
|
-
|
|
22278
|
-
|
|
22279
|
-
|
|
22280
|
-
|
|
22281
|
-
|
|
22282
|
-
|
|
22283
|
-
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
|
|
22289
|
-
|
|
22290
|
-
|
|
22291
|
-
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
22298
|
-
|
|
22299
|
-
|
|
22300
|
-
|
|
22301
|
-
|
|
22302
|
-
|
|
22303
|
-
|
|
22304
|
-
|
|
22305
|
-
|
|
22306
|
-
|
|
22307
|
-
|
|
22308
|
-
|
|
22309
|
-
|
|
22310
|
-
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
|
|
22314
|
-
|
|
22315
|
-
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
/* @__PURE__ */
|
|
22320
|
-
|
|
22321
|
-
|
|
22322
|
-
|
|
22323
|
-
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
|
|
22345
|
-
|
|
22346
|
-
|
|
22347
|
-
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
|
|
22352
|
-
|
|
22353
|
-
|
|
22354
|
-
|
|
22355
|
-
|
|
22709
|
+
}
|
|
22710
|
+
return /* @__PURE__ */ jsxs(
|
|
22711
|
+
"aside",
|
|
22712
|
+
{
|
|
22713
|
+
className: `setto-chat${mounted ? " setto-chat--mounted" : ""}${visible ? " setto-chat--visible" : ""}`,
|
|
22714
|
+
style: palette,
|
|
22715
|
+
"aria-label": labels.title,
|
|
22716
|
+
"data-setto-ui": true,
|
|
22717
|
+
children: [
|
|
22718
|
+
mounted ? /* @__PURE__ */ jsxs(
|
|
22719
|
+
"section",
|
|
22720
|
+
{
|
|
22721
|
+
className: "setto-chat__shell",
|
|
22722
|
+
role: "dialog",
|
|
22723
|
+
"aria-modal": "true",
|
|
22724
|
+
"aria-labelledby": `${formId}-title`,
|
|
22725
|
+
children: [
|
|
22726
|
+
/* @__PURE__ */ jsx(
|
|
22727
|
+
"button",
|
|
22728
|
+
{
|
|
22729
|
+
className: `setto-chat__scrim${drawer ? " is-open" : ""}`,
|
|
22730
|
+
type: "button",
|
|
22731
|
+
onClick: () => setDrawer(false),
|
|
22732
|
+
"aria-label": labels.close,
|
|
22733
|
+
tabIndex: drawer ? 0 : -1
|
|
22734
|
+
}
|
|
22735
|
+
),
|
|
22736
|
+
/* @__PURE__ */ jsxs(
|
|
22737
|
+
"nav",
|
|
22738
|
+
{
|
|
22739
|
+
className: `setto-chat__chats${drawer ? " setto-chat__chats--open" : ""}`,
|
|
22740
|
+
"aria-label": labels.chats,
|
|
22741
|
+
children: [
|
|
22742
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__chats-heading", children: [
|
|
22743
|
+
/* @__PURE__ */ jsx("span", { children: labels.chats }),
|
|
22744
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setDrawer(false), "aria-label": labels.close, children: /* @__PURE__ */ jsx(CloseIcon, { size: 18 }) })
|
|
22745
|
+
] }),
|
|
22746
|
+
/* @__PURE__ */ jsxs("button", { className: "setto-chat__new", type: "button", onClick: startNew, children: [
|
|
22747
|
+
/* @__PURE__ */ jsx(PlusIcon, {}),
|
|
22748
|
+
labels.newChat
|
|
22749
|
+
] }),
|
|
22750
|
+
/* @__PURE__ */ jsx("div", { className: "setto-chat__chat-list", children: conversations.length ? conversations.map((chat) => /* @__PURE__ */ jsxs(
|
|
22751
|
+
"button",
|
|
22752
|
+
{
|
|
22753
|
+
className: `setto-chat__chat-row${conversationId.current === chat.id ? " is-active" : ""}`,
|
|
22754
|
+
type: "button",
|
|
22755
|
+
onClick: () => void loadConversation(chat.id),
|
|
22756
|
+
children: [
|
|
22757
|
+
/* @__PURE__ */ jsx("span", { children: chat.preview }),
|
|
22758
|
+
/* @__PURE__ */ jsx("time", { children: new Date(chat.lastActivityAt).toLocaleDateString(
|
|
22759
|
+
isNo ? "nb-NO" : "en-GB",
|
|
22760
|
+
{ day: "numeric", month: "short" }
|
|
22761
|
+
) })
|
|
22762
|
+
]
|
|
22763
|
+
},
|
|
22764
|
+
chat.id
|
|
22765
|
+
)) : /* @__PURE__ */ jsx("p", { children: labels.emptyChats }) })
|
|
22766
|
+
]
|
|
22767
|
+
}
|
|
22768
|
+
),
|
|
22769
|
+
/* @__PURE__ */ jsxs("main", { className: "setto-chat__main", children: [
|
|
22770
|
+
/* @__PURE__ */ jsxs("header", { className: "setto-chat__header", children: [
|
|
22771
|
+
/* @__PURE__ */ jsx(
|
|
22772
|
+
"button",
|
|
22773
|
+
{
|
|
22774
|
+
className: "setto-chat__round-button",
|
|
22775
|
+
type: "button",
|
|
22776
|
+
onClick: () => setDrawer((current) => !current),
|
|
22777
|
+
"aria-label": labels.chats,
|
|
22778
|
+
"aria-expanded": drawer,
|
|
22779
|
+
children: /* @__PURE__ */ jsx(MenuIcon, {})
|
|
22780
|
+
}
|
|
22781
|
+
),
|
|
22782
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__brand", children: [
|
|
22783
|
+
/* @__PURE__ */ jsx("h2", { id: `${formId}-title`, children: labels.title }),
|
|
22784
|
+
/* @__PURE__ */ jsx("p", { children: siteName ?? "Barista" })
|
|
22785
|
+
] }),
|
|
22786
|
+
/* @__PURE__ */ jsx(
|
|
22787
|
+
"button",
|
|
22788
|
+
{
|
|
22789
|
+
className: "setto-chat__round-button",
|
|
22790
|
+
type: "button",
|
|
22791
|
+
onClick: hide,
|
|
22792
|
+
"aria-label": labels.close,
|
|
22793
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
22794
|
+
}
|
|
22795
|
+
)
|
|
22796
|
+
] }),
|
|
22797
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__disclosure", children: [
|
|
22798
|
+
/* @__PURE__ */ jsx("span", { children: "BARISTA" }),
|
|
22799
|
+
/* @__PURE__ */ jsx("p", { children: labels.disclosure })
|
|
22800
|
+
] }),
|
|
22801
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__body", children: [
|
|
22802
|
+
/* @__PURE__ */ jsxs(
|
|
22803
|
+
"div",
|
|
22804
|
+
{
|
|
22805
|
+
className: "setto-chat__log",
|
|
22806
|
+
ref: logRef,
|
|
22807
|
+
"aria-live": "polite",
|
|
22808
|
+
"aria-busy": loadingConversation,
|
|
22809
|
+
children: [
|
|
22810
|
+
/* @__PURE__ */ jsx("div", { className: "setto-chat__message-list", children: messages.map((item, index) => /* @__PURE__ */ jsxs(
|
|
22811
|
+
"div",
|
|
22812
|
+
{
|
|
22813
|
+
className: `setto-chat__message setto-chat__message--${item.role}`,
|
|
22814
|
+
children: [
|
|
22815
|
+
item.role === "human" ? /* @__PURE__ */ jsx("span", { className: "setto-chat__speaker", children: labels.team }) : null,
|
|
22816
|
+
/* @__PURE__ */ jsx("span", { className: "setto-chat__message-copy", children: item.content || /* @__PURE__ */ jsx("span", { className: "setto-chat__typing", children: "···" }) }),
|
|
22817
|
+
item.attachments?.map((attachment) => /* @__PURE__ */ jsx(
|
|
22818
|
+
"a",
|
|
22819
|
+
{
|
|
22820
|
+
className: "setto-chat__image",
|
|
22821
|
+
href: attachment.url,
|
|
22822
|
+
target: "_blank",
|
|
22823
|
+
rel: "noreferrer",
|
|
22824
|
+
children: /* @__PURE__ */ jsx("img", { src: attachment.url, alt: labels.image })
|
|
22825
|
+
},
|
|
22826
|
+
attachment.id
|
|
22827
|
+
))
|
|
22828
|
+
]
|
|
22829
|
+
},
|
|
22830
|
+
item.id ?? `${item.role}-${index}`
|
|
22831
|
+
)) }),
|
|
22832
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__actions", children: [
|
|
22833
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: contactTeam, children: [
|
|
22834
|
+
labels.contact,
|
|
22835
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "↗" })
|
|
22836
|
+
] }),
|
|
22837
|
+
/* @__PURE__ */ jsx(
|
|
22838
|
+
"button",
|
|
22839
|
+
{
|
|
22840
|
+
type: "button",
|
|
22841
|
+
onClick: () => {
|
|
22842
|
+
setLeadOpen((value) => !value);
|
|
22843
|
+
setLeadStatus("idle");
|
|
22844
|
+
},
|
|
22845
|
+
"aria-expanded": leadOpen,
|
|
22846
|
+
children: labels.followUp
|
|
22847
|
+
}
|
|
22848
|
+
)
|
|
22849
|
+
] }),
|
|
22850
|
+
leadOpen ? /* @__PURE__ */ jsxs("form", { className: "setto-chat__lead", onSubmit: submitLead, children: [
|
|
22851
|
+
/* @__PURE__ */ jsx("strong", { children: labels.followUpTitle }),
|
|
22852
|
+
/* @__PURE__ */ jsx("p", { children: labels.followUpDetail }),
|
|
22853
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__lead-grid", children: [
|
|
22854
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
22855
|
+
labels.name,
|
|
22856
|
+
/* @__PURE__ */ jsx(
|
|
22857
|
+
"input",
|
|
22858
|
+
{
|
|
22859
|
+
value: lead.name,
|
|
22860
|
+
maxLength: 160,
|
|
22861
|
+
onChange: (event) => setLead((current) => ({ ...current, name: event.target.value }))
|
|
22862
|
+
}
|
|
22863
|
+
)
|
|
22864
|
+
] }),
|
|
22865
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
22866
|
+
labels.email,
|
|
22867
|
+
/* @__PURE__ */ jsx(
|
|
22868
|
+
"input",
|
|
22869
|
+
{
|
|
22870
|
+
type: "email",
|
|
22871
|
+
value: lead.email,
|
|
22872
|
+
maxLength: 320,
|
|
22873
|
+
onChange: (event) => setLead((current) => ({ ...current, email: event.target.value }))
|
|
22874
|
+
}
|
|
22875
|
+
)
|
|
22876
|
+
] }),
|
|
22877
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
22878
|
+
labels.phone,
|
|
22879
|
+
/* @__PURE__ */ jsx(
|
|
22880
|
+
"input",
|
|
22881
|
+
{
|
|
22882
|
+
type: "tel",
|
|
22883
|
+
value: lead.phone,
|
|
22884
|
+
maxLength: 64,
|
|
22885
|
+
onChange: (event) => setLead((current) => ({ ...current, phone: event.target.value }))
|
|
22886
|
+
}
|
|
22887
|
+
)
|
|
22888
|
+
] }),
|
|
22889
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
22890
|
+
labels.interest,
|
|
22891
|
+
/* @__PURE__ */ jsx(
|
|
22892
|
+
"input",
|
|
22893
|
+
{
|
|
22894
|
+
value: lead.interest,
|
|
22895
|
+
maxLength: 500,
|
|
22896
|
+
onChange: (event) => setLead((current) => ({ ...current, interest: event.target.value }))
|
|
22897
|
+
}
|
|
22898
|
+
)
|
|
22899
|
+
] })
|
|
22900
|
+
] }),
|
|
22901
|
+
/* @__PURE__ */ jsxs("label", { className: "setto-chat__consent", children: [
|
|
22902
|
+
/* @__PURE__ */ jsx(
|
|
22903
|
+
"input",
|
|
22904
|
+
{
|
|
22905
|
+
type: "checkbox",
|
|
22906
|
+
checked: lead.consent,
|
|
22907
|
+
onChange: (event) => setLead((current) => ({ ...current, consent: event.target.checked }))
|
|
22908
|
+
}
|
|
22909
|
+
),
|
|
22910
|
+
labels.consent
|
|
22911
|
+
] }),
|
|
22912
|
+
leadStatus === "sent" ? /* @__PURE__ */ jsx("p", { className: "setto-chat__lead-success", children: labels.leadSent }) : null,
|
|
22913
|
+
leadStatus === "failed" ? /* @__PURE__ */ jsx("p", { className: "setto-chat__lead-error", children: conversationId.current ? labels.leadFailed : labels.leadConversation }) : null,
|
|
22914
|
+
leadStatus !== "sent" ? /* @__PURE__ */ jsx(
|
|
22915
|
+
"button",
|
|
22916
|
+
{
|
|
22917
|
+
type: "submit",
|
|
22918
|
+
disabled: leadStatus === "sending" || !lead.consent || !lead.email.trim() && !lead.phone.trim(),
|
|
22919
|
+
children: leadStatus === "sending" ? labels.sending : labels.leadSend
|
|
22920
|
+
}
|
|
22921
|
+
) : null
|
|
22922
|
+
] }) : null
|
|
22923
|
+
]
|
|
22924
|
+
}
|
|
22925
|
+
),
|
|
22926
|
+
/* @__PURE__ */ jsxs("div", { className: "setto-chat__composer-shell", children: [
|
|
22927
|
+
/* @__PURE__ */ jsx(
|
|
22928
|
+
SiteChatComposer,
|
|
22929
|
+
{
|
|
22930
|
+
value: draft,
|
|
22931
|
+
onChange: setDraft,
|
|
22932
|
+
onSubmit: queueOrSend,
|
|
22933
|
+
busy: sending,
|
|
22934
|
+
queued,
|
|
22935
|
+
placeholder: labels.placeholder,
|
|
22936
|
+
attachLabel: labels.attach,
|
|
22937
|
+
sendLabel: labels.send,
|
|
22938
|
+
removeLabel: labels.remove,
|
|
22939
|
+
locale,
|
|
22940
|
+
attachments: files,
|
|
22941
|
+
onAttach: addFiles,
|
|
22942
|
+
onRemoveAttachment: removeFile
|
|
22943
|
+
}
|
|
22944
|
+
),
|
|
22945
|
+
/* @__PURE__ */ jsx("div", { className: "setto-chat__composer-floor", "aria-hidden": "true" })
|
|
22946
|
+
] })
|
|
22947
|
+
] })
|
|
22948
|
+
] })
|
|
22949
|
+
]
|
|
22950
|
+
}
|
|
22951
|
+
) : null,
|
|
22952
|
+
!mounted ? /* @__PURE__ */ jsx(
|
|
22953
|
+
"button",
|
|
22954
|
+
{
|
|
22955
|
+
className: "setto-chat__launcher",
|
|
22956
|
+
type: "button",
|
|
22957
|
+
onClick: show,
|
|
22958
|
+
"aria-label": labels.open,
|
|
22959
|
+
title: labels.open,
|
|
22960
|
+
children: availability.humanAvailable && availability.avatarUrl ? /* @__PURE__ */ jsx("img", { src: availability.avatarUrl, alt: "" }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(BaristaIcon, {}) })
|
|
22961
|
+
}
|
|
22962
|
+
) : null
|
|
22963
|
+
]
|
|
22964
|
+
}
|
|
22965
|
+
);
|
|
22356
22966
|
}
|
|
22357
22967
|
function replaceLastAssistant(messages, content) {
|
|
22358
22968
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
@@ -22370,14 +22980,14 @@ function useChatStyles() {
|
|
|
22370
22980
|
const style = document.createElement("style");
|
|
22371
22981
|
style.dataset.settoChat = "";
|
|
22372
22982
|
style.textContent = `
|
|
22373
|
-
.setto-chat{position:fixed;right:max(18px,env(safe-area-inset-right));bottom:max(18px,env(safe-area-inset-bottom));z-index:2147483000;color:var(--setto-chat-ink);font-family:Archivo,ui
|
|
22374
|
-
.setto-chat__chats{width:
|
|
22375
|
-
.setto-chat__main{
|
|
22376
|
-
.setto-chat__log{min-height:0;overflow:auto;
|
|
22377
|
-
.setto-chat__actions{
|
|
22378
|
-
.setto-chat__composer{
|
|
22379
|
-
.setto-chat__launcher{width:58px;height:58px;padding:3px;border:1px solid rgba(255,255,255,.54);border-radius:50%;background:color-mix(in srgb,var(--setto-chat-
|
|
22380
|
-
@media(max-width:700px){.setto-chat__chats{position:absolute;
|
|
22983
|
+
.setto-chat{position:fixed;right:max(18px,env(safe-area-inset-right));bottom:max(18px,env(safe-area-inset-bottom));z-index:2147483000;color:var(--setto-chat-ink);font-family:"Archivo Variable",Archivo,system-ui,sans-serif;-webkit-font-smoothing:antialiased}.setto-chat *,.setto-chat *::before,.setto-chat *::after{box-sizing:border-box}.setto-chat button,.setto-chat input,.setto-chat textarea{font:inherit}.setto-chat--mounted{top:var(--setto-chat-top,0);right:auto;bottom:auto;left:0;width:100vw;height:var(--setto-chat-height,100svh);overflow:hidden;background:var(--setto-chat-canvas);opacity:0;transition:opacity ${CLOSE_MS}ms ease}.setto-chat--visible{opacity:1}.setto-chat__shell{position:relative;width:100%;height:100%;display:flex;overflow:hidden;background:var(--setto-chat-canvas);opacity:0;transform:translateY(12px) scale(.994);transform-origin:center bottom;transition:opacity ${CLOSE_MS}ms ease,transform ${CLOSE_MS}ms cubic-bezier(.16,1,.3,1)}.setto-chat--visible .setto-chat__shell{opacity:1;transform:none}
|
|
22984
|
+
.setto-chat__scrim{position:absolute;inset:0;z-index:45;border:0;background:rgba(33,23,17,.32);opacity:0;pointer-events:none;transition:opacity 220ms ease}.setto-chat__scrim.is-open{opacity:1;pointer-events:auto}.setto-chat__chats{position:relative;z-index:50;width:min(84vw,280px);height:100%;flex:0 0 280px;padding:1rem .85rem calc(1rem + env(safe-area-inset-bottom));display:flex;flex-direction:column;gap:.9rem;background:color-mix(in srgb,var(--setto-chat-crema) 32%,var(--setto-chat-canvas));border-right:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);overflow:hidden}.setto-chat__chats-heading{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-height:34px;font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent)}.setto-chat__chats-heading button{width:34px;height:34px;padding:0;border:0;border-radius:8px;background:transparent;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.setto-chat__new{display:flex;align-items:center;gap:.55rem;width:100%;padding:.5rem .55rem;border:0;border-radius:8px;background:transparent;color:var(--setto-chat-ink);font-weight:600;font-size:.9rem;text-align:left;cursor:pointer;transition:background 140ms ease}.setto-chat__new:hover{background:color-mix(in srgb,var(--setto-chat-ink) 5%,transparent)}.setto-chat__chat-list{display:flex;flex-direction:column;gap:.1rem;flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;margin-right:-.85rem;padding-right:.3rem}.setto-chat__chat-list p{margin:.35rem .55rem;font-size:.85rem;line-height:1.5;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent)}.setto-chat__chat-row{width:100%;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.4rem;padding:.55rem;border:0;border-radius:8px;background:transparent;color:var(--setto-chat-ink);text-align:left;cursor:pointer}.setto-chat__chat-row:hover,.setto-chat__chat-row.is-active{background:color-mix(in srgb,var(--setto-chat-ink) 7.5%,transparent)}.setto-chat__chat-row span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.9rem;font-weight:600}.setto-chat__chat-row time{font-size:.72rem;color:color-mix(in srgb,var(--setto-chat-ink) 55%,transparent)}
|
|
22985
|
+
.setto-chat__main{position:relative;z-index:1;display:flex;flex:1;min-width:0;max-width:820px;height:100%;margin:0 auto;flex-direction:column;background:var(--setto-chat-canvas)}.setto-chat__header{position:relative;z-index:30;min-height:58px;padding:.35rem .75rem;display:flex;align-items:center;gap:.5rem;flex:0 0 auto;background:transparent;isolation:isolate}.setto-chat__header::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:color-mix(in srgb,var(--setto-chat-crema) 70%,transparent);backdrop-filter:blur(18px) saturate(150%);-webkit-backdrop-filter:blur(18px) saturate(150%);-webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 45%,rgba(0,0,0,.45) 78%,rgba(0,0,0,0) 100%);mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 45%,rgba(0,0,0,.45) 78%,rgba(0,0,0,0) 100%)}.setto-chat__round-button{flex:none;width:46px;height:46px;padding:0;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);border-radius:50%;background:var(--setto-chat-raised);color:var(--setto-chat-ink);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease,border-color 160ms ease,color 160ms ease}.setto-chat__round-button:hover{background:var(--setto-chat-crema);border-color:var(--setto-chat-accent);color:var(--setto-chat-accent)}.setto-chat__round-button:active{transform:scale(.96)}.setto-chat__brand{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;line-height:1.15;text-align:center}.setto-chat__brand h2{margin:0;color:var(--setto-chat-ink);font-size:1.02rem;font-weight:600;line-height:1.15}.setto-chat__brand p{max-width:100%;margin:2px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:color-mix(in srgb,var(--setto-chat-ink) 56%,transparent);font-size:.78rem;line-height:1.15}.setto-chat__disclosure{display:flex;align-items:baseline;gap:.65rem;padding:.9rem .75rem .35rem;flex:0 0 auto}.setto-chat__disclosure span{flex:none;color:var(--setto-chat-accent);font-size:.68rem;font-weight:700;letter-spacing:.12em}.setto-chat__disclosure p{margin:0;color:color-mix(in srgb,var(--setto-chat-ink) 62%,transparent);font-size:.9rem;line-height:1.45}
|
|
22986
|
+
.setto-chat__body{position:relative;display:flex;flex:1 1 auto;min-height:0;flex-direction:column}.setto-chat__log{display:flex;flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;flex-direction:column;padding:1.3rem .75rem 8rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch}.setto-chat__message-list{display:flex;flex-direction:column}.setto-chat__message{display:block;margin-bottom:1.5rem;font-size:16px;line-height:1.65;overflow-wrap:anywhere;white-space:pre-wrap;color:color-mix(in srgb,var(--setto-chat-ink) 88%,transparent)}.setto-chat__message--assistant{align-self:stretch;max-width:100%;padding:0;background:transparent}.setto-chat__message--visitor{align-self:flex-end;max-width:85%;margin-bottom:1.25rem;padding:.65rem .95rem;background:var(--setto-chat-crema);color:var(--setto-chat-ink);border:1px solid color-mix(in srgb,var(--setto-chat-ink) 7%,transparent);border-radius:20px 20px 4px 20px;font-size:.95rem;line-height:1.55;box-shadow:0 1px 2px color-mix(in srgb,var(--setto-chat-ink) 6%,transparent)}.setto-chat__message--human{align-self:stretch;max-width:100%;padding-left:.8rem;border-left:2px solid var(--setto-chat-accent)}.setto-chat__message--system{align-self:center;max-width:85%;padding:.25rem .6rem;color:color-mix(in srgb,var(--setto-chat-ink) 55%,transparent);font-size:.78rem;line-height:1.45;text-align:center}.setto-chat__speaker{display:block;margin-bottom:.15rem;color:var(--setto-chat-accent);font-size:.68rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase}.setto-chat__typing{display:inline-block;animation:setto-chat-pulse 1s ease-in-out infinite}.setto-chat__image{display:block;width:max-content;max-width:100%;margin-top:.65rem;overflow:hidden;border-radius:14px;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 10%,transparent)}.setto-chat__image img{display:block;width:min(280px,100%);max-height:260px;object-fit:cover}
|
|
22987
|
+
.setto-chat__actions{display:flex;flex-wrap:wrap;gap:1.35rem;margin-top:auto;padding:1.2rem 0 .65rem}.setto-chat__actions button{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem 0;border:0;background:transparent;color:var(--setto-chat-accent);font-size:.9rem;font-weight:700;cursor:pointer}.setto-chat__lead{display:grid;gap:.6rem;margin:.5rem 0 1rem;padding:1rem;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);border-radius:16px;background:color-mix(in srgb,var(--setto-chat-crema) 58%,var(--setto-chat-canvas))}.setto-chat__lead strong{font-size:.95rem}.setto-chat__lead p{margin:0;color:color-mix(in srgb,var(--setto-chat-ink) 65%,transparent);font-size:.8rem;line-height:1.45}.setto-chat__lead-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.55rem}.setto-chat__lead label{display:grid;gap:.25rem;font-size:.72rem;font-weight:700}.setto-chat__lead input{min-width:0;padding:.55rem .6rem;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 18%,transparent);border-radius:8px;background:var(--setto-chat-canvas);color:var(--setto-chat-ink);font-size:.85rem}.setto-chat__consent{display:flex!important;align-items:flex-start;gap:.45rem;font-weight:400!important;line-height:1.4}.setto-chat__lead>button{justify-self:start;padding:.55rem .8rem;border:0;border-radius:9px;background:var(--setto-chat-accent);color:var(--setto-chat-raised);font-size:.78rem;font-weight:700;cursor:pointer}.setto-chat__lead>button:disabled{opacity:.4;cursor:default}.setto-chat__lead-success{color:#28633d!important;font-weight:700}.setto-chat__lead-error{color:#a33024!important;font-weight:700}
|
|
22988
|
+
.setto-chat__composer-shell{position:absolute;left:0;right:0;bottom:0;z-index:25;display:grid;grid-template-columns:minmax(0,1fr);padding:1.5rem .75rem 0;background:transparent;isolation:isolate}.setto-chat__composer-shell::before{content:"";position:absolute;inset:0;pointer-events:none;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);-webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,0) 0%,rgba(0,0,0,.4) 34%,rgba(0,0,0,1) 66%);mask-image:linear-gradient(to bottom,rgba(0,0,0,0) 0%,rgba(0,0,0,.4) 34%,rgba(0,0,0,1) 66%)}.setto-chat__composer{position:relative;z-index:1;display:flex;flex-direction:column;gap:.15rem;width:100%;min-width:0;margin:0;padding:.35rem .4rem;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 10%,transparent);border-radius:24px;background:var(--setto-chat-canvas);box-shadow:0 8px 24px -16px color-mix(in srgb,var(--setto-chat-ink) 28%,transparent);transition:padding 220ms cubic-bezier(.16,1,.3,1),border-color 200ms ease,box-shadow 360ms cubic-bezier(.16,1,.3,1)}.setto-chat__composer.is-open{padding:.55rem .5rem}.setto-chat__composer:focus-within{border-color:var(--setto-chat-accent)}.setto-chat__composer textarea{width:100%;min-height:36px;max-height:200px;padding:.45rem .25rem;resize:none;border:0;outline:none;background:transparent;color:var(--setto-chat-ink);font-family:"Archivo Variable",Archivo,system-ui,sans-serif;font-size:16px;line-height:1.35;transition:min-height 220ms cubic-bezier(.16,1,.3,1)}.setto-chat__composer.is-open textarea{min-height:40px}.setto-chat__composer textarea::placeholder{color:color-mix(in srgb,var(--setto-chat-ink) 52%,transparent)}.setto-chat__composer-tools{display:flex;align-items:center;gap:.4rem;width:100%;min-width:0}.setto-chat__attach{flex:none;width:34px;height:34px;padding:0;border:0;border-radius:50%;background:transparent;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease,color 160ms ease}.setto-chat__attach:hover:not(:disabled){background:color-mix(in srgb,var(--setto-chat-ink) 6%,transparent);color:var(--setto-chat-ink)}.setto-chat__attach:disabled{opacity:.4;cursor:default}.setto-chat__send{flex:none;width:36px;height:36px;margin-left:auto;padding:0;border:0;border-radius:50%;background:var(--setto-chat-accent);color:var(--setto-chat-raised);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform 360ms cubic-bezier(.16,1,.3,1),box-shadow 360ms cubic-bezier(.16,1,.3,1),background 200ms ease,opacity 200ms ease}.setto-chat__send:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 12px 24px -12px color-mix(in srgb,var(--setto-chat-ink) 45%,transparent)}.setto-chat__send:active:not(:disabled){transform:translateY(0);box-shadow:0 4px 10px -8px color-mix(in srgb,var(--setto-chat-ink) 40%,transparent);transition-duration:90ms}.setto-chat__send:disabled{opacity:.35;cursor:default}.setto-chat__send.is-queued{animation:setto-chat-queued 1.1s ease-in-out infinite}.setto-chat__attachments{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;margin:0;padding:.15rem .15rem 0}.setto-chat__attachments li{position:relative;width:56px;height:56px;border-radius:10px;overflow:hidden;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);background:var(--setto-chat-crema)}.setto-chat__attachments img{display:block;width:100%;height:100%;object-fit:cover}.setto-chat__attachments button{position:absolute;top:2px;right:2px;width:18px;height:18px;padding:0;border:0;border-radius:50%;background:color-mix(in srgb,var(--setto-chat-ink) 72%,transparent);color:#fff;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.setto-chat__composer-floor{position:relative;z-index:1;width:calc(100% + 1.5rem);height:max(.35rem,env(safe-area-inset-bottom));margin-left:-.75rem}
|
|
22989
|
+
.setto-chat__launcher{width:58px;height:58px;padding:3px;border:1px solid rgba(255,255,255,.54);border-radius:50%;background:color-mix(in srgb,var(--setto-chat-raised) 35%,transparent);box-shadow:0 10px 30px color-mix(in srgb,var(--setto-chat-ink) 24%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--setto-chat-ink) 9%,transparent);backdrop-filter:blur(14px) saturate(115%);-webkit-backdrop-filter:blur(14px) saturate(115%);color:var(--setto-chat-ink);display:grid;place-items:center;cursor:pointer;transition:transform 180ms ease,box-shadow 180ms ease}.setto-chat__launcher:hover{transform:translateY(-2px);box-shadow:0 15px 35px color-mix(in srgb,var(--setto-chat-ink) 28%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--setto-chat-ink) 9%,transparent)}.setto-chat__launcher span{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;background:var(--setto-chat-accent);color:var(--setto-chat-raised)}.setto-chat__launcher img{display:block;width:50px;height:50px;border-radius:50%;object-fit:cover}.setto-chat__launcher:focus-visible,.setto-chat button:focus-visible,.setto-chat textarea:focus-visible,.setto-chat input:focus-visible{outline:2px solid var(--setto-chat-accent);outline-offset:2px}@keyframes setto-chat-pulse{50%{opacity:.35}}@keyframes setto-chat-queued{50%{opacity:.55}}
|
|
22990
|
+
@media(max-width:700px){.setto-chat__chats{position:absolute;inset:0 auto 0 0;transform:translateX(-100%);transition:transform 260ms cubic-bezier(.16,1,.3,1);box-shadow:14px 0 35px color-mix(in srgb,var(--setto-chat-ink) 16%,transparent)}.setto-chat__chats--open{transform:none}.setto-chat__main{width:100%;max-width:none;margin:0}.setto-chat__disclosure{padding-left:.75rem;padding-right:.75rem}.setto-chat__log{padding-left:.75rem;padding-right:.75rem}.setto-chat__lead-grid{grid-template-columns:1fr}.setto-chat__actions{gap:1.1rem}.setto-chat__actions button{font-size:.88rem}}@media(min-width:700px){.setto-chat__header,.setto-chat__disclosure,.setto-chat__log{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-shell{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-floor{width:calc(100% + 2.5rem);margin-left:-1.25rem}.setto-chat__message{font-size:16.5px}}@media(prefers-reduced-motion:reduce){.setto-chat,.setto-chat__shell,.setto-chat__chats,.setto-chat__launcher,.setto-chat__composer,.setto-chat__composer textarea,.setto-chat__send{transition:none!important}.setto-chat__typing,.setto-chat__send.is-queued{animation:none}}
|
|
22381
22991
|
`;
|
|
22382
22992
|
document.head.appendChild(style);
|
|
22383
22993
|
return () => style.remove();
|