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