@folio-agent/widget 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/styles.d.ts +1 -1
- package/dist/styles.js +22 -4
- package/dist/widget-element.js +51 -8
- package/package.json +2 -2
package/dist/styles.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const WIDGET_STYLES = "\n :host {\n all: initial;\n color: inherit;\n color-scheme: inherit;\n font-family: var(--folio-agent-font, inherit);\n\n --_surface: var(--folio-agent-surface, Canvas);\n --_text: var(--folio-agent-text, CanvasText);\n --_accent: var(--folio-agent-accent, var(--_text));\n --_accent-contrast: var(--folio-agent-accent-contrast, var(--_surface));\n --_muted: var(--folio-agent-muted, color-mix(in srgb, var(--_text) 62%, var(--_surface)));\n --_hair: color-mix(in srgb, var(--_text) 12%, transparent);\n --_glass: color-mix(in srgb, var(--_surface) 76%, transparent);\n --_glass-strong: color-mix(in srgb, var(--_surface) 94%, transparent);\n --_field: color-mix(in srgb, var(--_text) 5%, color-mix(in srgb, var(--_surface) 80%, transparent));\n --_chip: color-mix(in srgb, var(--_surface) 60%, transparent);\n --_focus: color-mix(in srgb, var(--_accent) 70%, var(--_text));\n }\n * {\n box-sizing: border-box;\n }\n button,\n textarea {\n font: inherit;\n }\n svg {\n display: block;\n }\n\n .toggle {\n position: fixed;\n right: 20px;\n bottom: calc(20px + env(safe-area-inset-bottom, 0px));\n z-index: 2147483000;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 46px;\n padding: 0 18px 0 14px;\n border-radius: 999px;\n border: 1px solid color-mix(in srgb, var(--_accent-contrast) 14%, transparent);\n background: color-mix(in srgb, var(--_accent) 88%, transparent);\n -webkit-backdrop-filter: blur(16px) saturate(1.6);\n backdrop-filter: blur(16px) saturate(1.6);\n color: var(--_accent-contrast);\n font-size: 14px;\n font-weight: 600;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow: 0 10px 30px rgba(16, 20, 28, 0.22);\n transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.2s ease;\n }\n .toggle:hover {\n transform: translateY(-1px);\n }\n .toggle:active {\n transform: scale(0.97);\n }\n .toggle svg {\n width: 20px;\n height: 20px;\n flex: none;\n }\n .root.open .toggle {\n opacity: 0;\n transform: scale(0.85);\n pointer-events: none;\n }\n\n .panel {\n position: fixed;\n right: 20px;\n bottom: calc(20px + env(safe-area-inset-bottom, 0px));\n z-index: 2147483001;\n width: min(400px, calc(100vw - 40px));\n height: min(620px, calc(100dvh - 40px));\n display: flex;\n flex-direction: column;\n border-radius: 22px;\n border: 1px solid var(--_hair);\n background: var(--_glass);\n -webkit-backdrop-filter: blur(28px) saturate(1.8);\n backdrop-filter: blur(28px) saturate(1.8);\n box-shadow: 0 24px 64px rgba(16, 20, 28, 0.2), 0 2px 6px rgba(16, 20, 28, 0.08);\n color: var(--_text);\n overflow: hidden;\n transform-origin: calc(100% - 40px) calc(100% - 20px);\n opacity: 0;\n visibility: hidden;\n transform: translateY(10px) scale(0.9);\n transition:\n opacity 0.2s ease,\n transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1),\n visibility 0s linear 0.32s;\n }\n .root.open .panel {\n opacity: 1;\n visibility: visible;\n transform: none;\n transition:\n opacity 0.22s ease,\n transform 0.38s cubic-bezier(0.2, 0.9, 0.25, 1.05),\n visibility 0s;\n }\n\n .header {\n display: flex;\n align-items: center;\n gap:
|
|
1
|
+
export declare const WIDGET_STYLES = "\n :host {\n all: initial;\n color: inherit;\n color-scheme: inherit;\n font-family: var(--folio-agent-font, inherit);\n\n --_surface: var(--folio-agent-surface, Canvas);\n --_text: var(--folio-agent-text, CanvasText);\n --_accent: var(--folio-agent-accent, var(--_text));\n --_accent-contrast: var(--folio-agent-accent-contrast, var(--_surface));\n --_muted: var(--folio-agent-muted, color-mix(in srgb, var(--_text) 62%, var(--_surface)));\n --_hair: color-mix(in srgb, var(--_text) 12%, transparent);\n --_glass: color-mix(in srgb, var(--_surface) 76%, transparent);\n --_glass-strong: color-mix(in srgb, var(--_surface) 94%, transparent);\n --_field: color-mix(in srgb, var(--_text) 5%, color-mix(in srgb, var(--_surface) 80%, transparent));\n --_chip: color-mix(in srgb, var(--_surface) 60%, transparent);\n --_focus: color-mix(in srgb, var(--_accent) 70%, var(--_text));\n }\n * {\n box-sizing: border-box;\n }\n button,\n textarea {\n font: inherit;\n }\n svg {\n display: block;\n }\n /* \u30DB\u30B9\u30C8\u5074\u306E ::selection \u306F Shadow DOM \u306E\u4E2D\u3078\u5C4A\u304B\u306A\u3044\u306E\u3067\u3001\u3053\u3053\u3067 accent \u304B\u3089\u4F5C\u308B\u3002\n \u6307\u5B9A\u3057\u306A\u3044\u3068\u30D6\u30E9\u30A6\u30B6\u65E2\u5B9A\u306E\u9752\u306B\u306A\u308A\u3001\u30B5\u30A4\u30C8\u306E\u914D\u8272\u304B\u3089\u6D6E\u304F */\n ::selection {\n background: color-mix(in srgb, var(--_accent) 32%, transparent);\n color: var(--_text);\n }\n\n .toggle {\n position: fixed;\n right: 20px;\n bottom: calc(20px + env(safe-area-inset-bottom, 0px));\n z-index: 2147483000;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 46px;\n padding: 0 18px 0 14px;\n border-radius: 999px;\n border: 1px solid color-mix(in srgb, var(--_accent-contrast) 14%, transparent);\n background: color-mix(in srgb, var(--_accent) 88%, transparent);\n -webkit-backdrop-filter: blur(16px) saturate(1.6);\n backdrop-filter: blur(16px) saturate(1.6);\n color: var(--_accent-contrast);\n font-size: 14px;\n font-weight: 600;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow: 0 10px 30px rgba(16, 20, 28, 0.22);\n transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.2s ease;\n }\n .toggle:hover {\n transform: translateY(-1px);\n }\n .toggle:active {\n transform: scale(0.97);\n }\n .toggle svg {\n width: 20px;\n height: 20px;\n flex: none;\n }\n .root.open .toggle {\n opacity: 0;\n transform: scale(0.85);\n pointer-events: none;\n }\n\n .panel {\n position: fixed;\n right: 20px;\n bottom: calc(20px + env(safe-area-inset-bottom, 0px));\n z-index: 2147483001;\n width: min(400px, calc(100vw - 40px));\n height: min(620px, calc(100dvh - 40px));\n display: flex;\n flex-direction: column;\n border-radius: 22px;\n border: 1px solid var(--_hair);\n background: var(--_glass);\n -webkit-backdrop-filter: blur(28px) saturate(1.8);\n backdrop-filter: blur(28px) saturate(1.8);\n box-shadow: 0 24px 64px rgba(16, 20, 28, 0.2), 0 2px 6px rgba(16, 20, 28, 0.08);\n color: var(--_text);\n overflow: hidden;\n transform-origin: calc(100% - 40px) calc(100% - 20px);\n opacity: 0;\n visibility: hidden;\n transform: translateY(10px) scale(0.9);\n transition:\n opacity 0.2s ease,\n transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1),\n visibility 0s linear 0.32s;\n }\n .root.open .panel {\n opacity: 1;\n visibility: visible;\n transform: none;\n transition:\n opacity 0.22s ease,\n transform 0.38s cubic-bezier(0.2, 0.9, 0.25, 1.05),\n visibility 0s;\n }\n\n .header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 14px 12px 12px 18px;\n border-bottom: 1px solid var(--_hair);\n }\n .titles {\n flex: 1;\n min-width: 0;\n }\n .heading {\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n }\n .subheading {\n font-size: 12px;\n line-height: 1.4;\n color: var(--_muted);\n }\n .close,\n .reset {\n flex: none;\n display: grid;\n place-items: center;\n width: 34px;\n height: 34px;\n border: 0;\n border-radius: 50%;\n background: color-mix(in srgb, var(--_text) 7%, transparent);\n color: var(--_text);\n cursor: pointer;\n }\n .reset {\n background: transparent;\n color: var(--_muted);\n }\n .reset[hidden] {\n display: none;\n }\n .close:hover,\n .reset:hover {\n background: color-mix(in srgb, var(--_text) 12%, transparent);\n }\n .close svg,\n .reset svg {\n width: 16px;\n height: 16px;\n }\n\n .messages {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 18px 18px 8px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n font-size: 15px;\n line-height: 1.7;\n }\n .message,\n .greeting {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n animation: fade-in 0.28s ease both;\n }\n .message.assistant,\n .greeting {\n align-self: stretch;\n }\n .message.user {\n align-self: flex-end;\n max-width: 85%;\n padding: 8px 14px;\n border-radius: 18px 18px 6px 18px;\n background: color-mix(in srgb, var(--_accent) 14%, var(--_surface));\n border: 1px solid color-mix(in srgb, var(--_accent) 28%, var(--_surface));\n }\n @keyframes fade-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: none; }\n }\n\n .suggestions {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n .suggestions button {\n padding: 7px 14px;\n border: 1px solid var(--_hair);\n border-radius: 999px;\n background: var(--_chip);\n color: var(--_text);\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n transition: background 0.15s ease;\n }\n .suggestions button:hover {\n background: color-mix(in srgb, var(--_text) 8%, transparent);\n }\n\n .typing {\n display: inline-flex;\n gap: 5px;\n padding: 8px 0;\n }\n .typing span {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--_muted);\n animation: typing-dot 1.1s ease-in-out infinite;\n }\n .typing span:nth-child(2) {\n animation-delay: 0.15s;\n }\n .typing span:nth-child(3) {\n animation-delay: 0.3s;\n }\n @keyframes typing-dot {\n 0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }\n 40% { opacity: 1; transform: translateY(-3px); }\n }\n\n form {\n padding: 8px 12px calc(10px + env(safe-area-inset-bottom, 0px));\n }\n .field {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n padding: 6px 6px 6px 14px;\n border: 1px solid var(--_hair);\n border-radius: 22px;\n background: var(--_field);\n transition: border-color 0.15s ease;\n }\n .field:focus-within {\n border-color: color-mix(in srgb, var(--_text) 32%, transparent);\n }\n textarea {\n flex: 1;\n min-width: 0;\n max-height: 144px;\n padding: 6px 0;\n border: 0;\n outline: 0;\n resize: none;\n background: transparent;\n color: var(--_text);\n caret-color: var(--_accent);\n /* 16px \u672A\u6E80\u3060\u3068 iOS Safari \u304C\u30D5\u30A9\u30FC\u30AB\u30B9\u6642\u306B\u30DA\u30FC\u30B8\u3092\u62E1\u5927\u3059\u308B */\n font-size: 16px;\n line-height: 1.5;\n }\n textarea::placeholder {\n color: var(--_muted);\n }\n .send {\n flex: none;\n display: grid;\n place-items: center;\n width: 34px;\n height: 34px;\n border: 0;\n border-radius: 50%;\n background: var(--_accent);\n color: var(--_accent-contrast);\n cursor: pointer;\n transition: opacity 0.15s ease, transform 0.15s ease;\n }\n .send:disabled {\n opacity: 0.25;\n cursor: default;\n }\n .send:not(:disabled):active {\n transform: scale(0.92);\n }\n .send svg {\n width: 18px;\n height: 18px;\n }\n .disclosure {\n margin: 8px 0 0;\n font-size: 11px;\n line-height: 1.5;\n text-align: center;\n color: var(--_muted);\n }\n .disclosure a {\n color: inherit;\n }\n\n .toggle:focus-visible,\n .close:focus-visible,\n .reset:focus-visible,\n .send:focus-visible,\n .suggestions button:focus-visible {\n outline: 2px solid var(--_focus);\n outline-offset: 2px;\n }\n\n @media (max-width: 640px) {\n .toggle {\n right: 16px;\n bottom: calc(16px + env(safe-area-inset-bottom, 0px));\n }\n /* \u9AD8\u3055\u3068\u4E0A\u7AEF\u306F visualViewport \u304B\u3089 JS \u304C\u6D41\u3057\u8FBC\u3080\u3002\u30AD\u30FC\u30DC\u30FC\u30C9\u8868\u793A\u4E2D\u3082\u5165\u529B\u6B04\u3092\u898B\u3048\u308B\u4F4D\u7F6E\u306B\u4FDD\u3064\u305F\u3081 */\n .panel {\n top: var(--vv-top, 0px);\n right: 0;\n bottom: auto;\n left: 0;\n width: 100%;\n height: var(--vv-height, 100dvh);\n border: 0;\n border-radius: 0;\n background: var(--_glass-strong);\n transform-origin: 50% 100%;\n transform: translateY(32px);\n }\n .header {\n padding-top: calc(12px + env(safe-area-inset-top, 0px));\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .toggle,\n .panel,\n .root.open .panel {\n transform: none;\n }\n .panel {\n transition: opacity 0.15s linear, visibility 0s linear 0.15s;\n }\n .root.open .panel {\n transition: opacity 0.15s linear;\n }\n .message,\n .greeting,\n .typing span {\n animation: none;\n }\n }\n";
|
package/dist/styles.js
CHANGED
|
@@ -33,6 +33,12 @@ export const WIDGET_STYLES = `
|
|
|
33
33
|
svg {
|
|
34
34
|
display: block;
|
|
35
35
|
}
|
|
36
|
+
/* ホスト側の ::selection は Shadow DOM の中へ届かないので、ここで accent から作る。
|
|
37
|
+
指定しないとブラウザ既定の青になり、サイトの配色から浮く */
|
|
38
|
+
::selection {
|
|
39
|
+
background: color-mix(in srgb, var(--_accent) 32%, transparent);
|
|
40
|
+
color: var(--_text);
|
|
41
|
+
}
|
|
36
42
|
|
|
37
43
|
.toggle {
|
|
38
44
|
position: fixed;
|
|
@@ -113,7 +119,7 @@ export const WIDGET_STYLES = `
|
|
|
113
119
|
.header {
|
|
114
120
|
display: flex;
|
|
115
121
|
align-items: center;
|
|
116
|
-
gap:
|
|
122
|
+
gap: 6px;
|
|
117
123
|
padding: 14px 12px 12px 18px;
|
|
118
124
|
border-bottom: 1px solid var(--_hair);
|
|
119
125
|
}
|
|
@@ -131,7 +137,8 @@ export const WIDGET_STYLES = `
|
|
|
131
137
|
line-height: 1.4;
|
|
132
138
|
color: var(--_muted);
|
|
133
139
|
}
|
|
134
|
-
.close
|
|
140
|
+
.close,
|
|
141
|
+
.reset {
|
|
135
142
|
flex: none;
|
|
136
143
|
display: grid;
|
|
137
144
|
place-items: center;
|
|
@@ -143,10 +150,19 @@ export const WIDGET_STYLES = `
|
|
|
143
150
|
color: var(--_text);
|
|
144
151
|
cursor: pointer;
|
|
145
152
|
}
|
|
146
|
-
.
|
|
153
|
+
.reset {
|
|
154
|
+
background: transparent;
|
|
155
|
+
color: var(--_muted);
|
|
156
|
+
}
|
|
157
|
+
.reset[hidden] {
|
|
158
|
+
display: none;
|
|
159
|
+
}
|
|
160
|
+
.close:hover,
|
|
161
|
+
.reset:hover {
|
|
147
162
|
background: color-mix(in srgb, var(--_text) 12%, transparent);
|
|
148
163
|
}
|
|
149
|
-
.close svg
|
|
164
|
+
.close svg,
|
|
165
|
+
.reset svg {
|
|
150
166
|
width: 16px;
|
|
151
167
|
height: 16px;
|
|
152
168
|
}
|
|
@@ -255,6 +271,7 @@ export const WIDGET_STYLES = `
|
|
|
255
271
|
resize: none;
|
|
256
272
|
background: transparent;
|
|
257
273
|
color: var(--_text);
|
|
274
|
+
caret-color: var(--_accent);
|
|
258
275
|
/* 16px 未満だと iOS Safari がフォーカス時にページを拡大する */
|
|
259
276
|
font-size: 16px;
|
|
260
277
|
line-height: 1.5;
|
|
@@ -299,6 +316,7 @@ export const WIDGET_STYLES = `
|
|
|
299
316
|
|
|
300
317
|
.toggle:focus-visible,
|
|
301
318
|
.close:focus-visible,
|
|
319
|
+
.reset:focus-visible,
|
|
302
320
|
.send:focus-visible,
|
|
303
321
|
.suggestions button:focus-visible {
|
|
304
322
|
outline: 2px solid var(--_focus);
|
package/dist/widget-element.js
CHANGED
|
@@ -5,6 +5,7 @@ const WIDGET_TEXT = {
|
|
|
5
5
|
headingText: "このサイトについて質問",
|
|
6
6
|
subheadingText: "公開している情報をもとに AI が答えます",
|
|
7
7
|
closeLabel: "閉じる",
|
|
8
|
+
resetLabel: "新しい会話",
|
|
8
9
|
greetingText: "制作実績・記事の内容・仕事の依頼について答えます。",
|
|
9
10
|
suggestions: ["どんな制作実績がありますか?", "どんな考え方で仕事をしていますか?", "仕事を依頼するには?"],
|
|
10
11
|
inputPlaceholder: "質問を入力",
|
|
@@ -21,6 +22,7 @@ const WIDGET_TEXT = {
|
|
|
21
22
|
headingText: "Ask about this site",
|
|
22
23
|
subheadingText: "AI answers from what this site publishes",
|
|
23
24
|
closeLabel: "Close",
|
|
25
|
+
resetLabel: "New conversation",
|
|
24
26
|
greetingText: "Ask about past work, articles, or how to request a project.",
|
|
25
27
|
suggestions: ["What have you built?", "How do you approach your work?", "How can I request a project?"],
|
|
26
28
|
inputPlaceholder: "Type a question",
|
|
@@ -35,6 +37,7 @@ const WIDGET_TEXT = {
|
|
|
35
37
|
};
|
|
36
38
|
const CHAT_ICON = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 12.5c0 3.9-3.6 7-8 7-1.1 0-2.2-.2-3.1-.6L4.5 20l1.2-3.4C4.6 15.5 4 14 4 12.5c0-3.9 3.6-7 8-7s8 3.1 8 7Z"/><path d="M9 12.5h.01M12 12.5h.01M15 12.5h.01" stroke-width="2.4"/></svg>`;
|
|
37
39
|
const CLOSE_ICON = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>`;
|
|
40
|
+
const RESET_ICON = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h8"/><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>`;
|
|
38
41
|
const SEND_ICON = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M6 11l6-6 6 6"/></svg>`;
|
|
39
42
|
const COMPACT_QUERY = "(max-width: 640px)";
|
|
40
43
|
const FINE_POINTER_QUERY = "(pointer: fine)";
|
|
@@ -60,12 +63,15 @@ export class FolioAgentWidgetElement extends HTMLElement {
|
|
|
60
63
|
#toggleEl;
|
|
61
64
|
#panelEl;
|
|
62
65
|
#closeEl;
|
|
66
|
+
#resetEl;
|
|
63
67
|
#messagesEl;
|
|
64
68
|
#suggestionsEl;
|
|
65
69
|
#typingEl;
|
|
66
70
|
#inputEl;
|
|
67
71
|
#sendEl;
|
|
68
72
|
#scrollLocked = false;
|
|
73
|
+
// 会話をやり直すたびに進める。やり直す前に送った質問の回答が遅れて届いても、描画しない
|
|
74
|
+
#conversation = 0;
|
|
69
75
|
#previousOverflow = "";
|
|
70
76
|
#onViewportChange = () => this.#syncViewport();
|
|
71
77
|
connectedCallback() {
|
|
@@ -122,23 +128,55 @@ export class FolioAgentWidgetElement extends HTMLElement {
|
|
|
122
128
|
close.setAttribute("aria-label", this.#text.closeLabel);
|
|
123
129
|
close.innerHTML = CLOSE_ICON;
|
|
124
130
|
close.addEventListener("click", () => this.#setOpen(false));
|
|
125
|
-
|
|
131
|
+
const reset = element("button", "reset");
|
|
132
|
+
reset.type = "button";
|
|
133
|
+
reset.hidden = true;
|
|
134
|
+
reset.setAttribute("aria-label", this.#text.resetLabel);
|
|
135
|
+
reset.title = this.#text.resetLabel;
|
|
136
|
+
reset.innerHTML = RESET_ICON;
|
|
137
|
+
reset.addEventListener("click", () => this.#resetConversation());
|
|
138
|
+
header.append(titles, reset, close);
|
|
126
139
|
const messages = element("div", "messages");
|
|
127
140
|
messages.setAttribute("aria-live", "polite");
|
|
141
|
+
panel.append(header, messages, this.#buildForm());
|
|
142
|
+
this.#panelEl = panel;
|
|
143
|
+
this.#closeEl = close;
|
|
144
|
+
this.#resetEl = reset;
|
|
145
|
+
this.#messagesEl = messages;
|
|
146
|
+
this.#renderIntro();
|
|
147
|
+
return panel;
|
|
148
|
+
}
|
|
149
|
+
#renderIntro() {
|
|
150
|
+
if (!this.#messagesEl)
|
|
151
|
+
return;
|
|
128
152
|
const greeting = this.getAttribute("greeting") ?? this.#text.greetingText;
|
|
129
153
|
if (greeting.trim()) {
|
|
130
154
|
const greetingEl = element("div", "greeting");
|
|
131
155
|
greetingEl.textContent = greeting;
|
|
132
|
-
|
|
156
|
+
this.#messagesEl.appendChild(greetingEl);
|
|
133
157
|
}
|
|
134
158
|
const suggestions = this.#buildSuggestions();
|
|
135
159
|
if (suggestions)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.#
|
|
140
|
-
|
|
141
|
-
|
|
160
|
+
this.#messagesEl.appendChild(suggestions);
|
|
161
|
+
}
|
|
162
|
+
#resetConversation() {
|
|
163
|
+
if (!this.#messagesEl)
|
|
164
|
+
return;
|
|
165
|
+
this.#conversation += 1;
|
|
166
|
+
this.#messages = [];
|
|
167
|
+
this.#setPending(false);
|
|
168
|
+
this.#messagesEl.replaceChildren();
|
|
169
|
+
this.#suggestionsEl = undefined;
|
|
170
|
+
this.#renderIntro();
|
|
171
|
+
if (this.#resetEl)
|
|
172
|
+
this.#resetEl.hidden = true;
|
|
173
|
+
if (this.#inputEl)
|
|
174
|
+
this.#inputEl.value = "";
|
|
175
|
+
this.#syncInput();
|
|
176
|
+
if (matches(FINE_POINTER_QUERY))
|
|
177
|
+
this.#inputEl?.focus();
|
|
178
|
+
else
|
|
179
|
+
this.#closeEl?.focus({ preventScroll: true });
|
|
142
180
|
}
|
|
143
181
|
#buildSuggestions() {
|
|
144
182
|
const attr = this.getAttribute("suggestions");
|
|
@@ -302,6 +340,7 @@ export class FolioAgentWidgetElement extends HTMLElement {
|
|
|
302
340
|
this.#appendMessage({ role: "assistant", text: this.#text.configErrorText });
|
|
303
341
|
return;
|
|
304
342
|
}
|
|
343
|
+
const conversation = this.#conversation;
|
|
305
344
|
this.#setPending(true);
|
|
306
345
|
let answer;
|
|
307
346
|
try {
|
|
@@ -316,11 +355,15 @@ export class FolioAgentWidgetElement extends HTMLElement {
|
|
|
316
355
|
catch {
|
|
317
356
|
answer = this.#text.networkErrorText;
|
|
318
357
|
}
|
|
358
|
+
if (conversation !== this.#conversation)
|
|
359
|
+
return;
|
|
319
360
|
this.#setPending(false);
|
|
320
361
|
this.#appendMessage({ role: "assistant", text: answer });
|
|
321
362
|
}
|
|
322
363
|
#appendMessage(message) {
|
|
323
364
|
this.#messages.push(message);
|
|
365
|
+
if (this.#resetEl)
|
|
366
|
+
this.#resetEl.hidden = false;
|
|
324
367
|
if (!this.#messagesEl)
|
|
325
368
|
return;
|
|
326
369
|
const el = element("div", `message ${message.role}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@folio-agent/widget",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Framework-agnostic reception chat widget (silent until clicked)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,6 +32,6 @@
|
|
|
32
32
|
"prepublishOnly": "tsc -b --force"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"happy-dom": "^20.14.
|
|
35
|
+
"happy-dom": "^20.14.5"
|
|
36
36
|
}
|
|
37
37
|
}
|