@morgan-and-morgan/intake-agent 1.0.0-beta.1 → 1.1.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/mm-intake-widget.js +43 -106
- package/package.json +1 -1
package/dist/mm-intake-widget.js
CHANGED
|
@@ -12,30 +12,19 @@
|
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
14
|
const OPEN_STATE_KEY = "mm-intake-widget-open";
|
|
15
|
-
const
|
|
16
|
-
const readFlag = (key, storage) => {
|
|
15
|
+
const readOpenState = (storage = sessionStorage) => {
|
|
17
16
|
try {
|
|
18
|
-
return storage.getItem(
|
|
17
|
+
return storage.getItem(OPEN_STATE_KEY) === "true";
|
|
19
18
|
} catch {
|
|
20
19
|
return false;
|
|
21
20
|
}
|
|
22
21
|
};
|
|
23
|
-
const
|
|
22
|
+
const writeOpenState = (isOpen, storage = sessionStorage) => {
|
|
24
23
|
try {
|
|
25
|
-
storage.setItem(
|
|
24
|
+
storage.setItem(OPEN_STATE_KEY, String(isOpen));
|
|
26
25
|
} catch {
|
|
27
26
|
}
|
|
28
27
|
};
|
|
29
|
-
const readOpenState = (storage = sessionStorage) => readFlag(OPEN_STATE_KEY, storage);
|
|
30
|
-
const writeOpenState = (isOpen, storage = sessionStorage) => writeFlag(OPEN_STATE_KEY, isOpen, storage);
|
|
31
|
-
const readUnreadState = (storage = sessionStorage) => {
|
|
32
|
-
try {
|
|
33
|
-
return storage.getItem(UNREAD_STATE_KEY) !== "false";
|
|
34
|
-
} catch {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
const writeUnreadState = (hasUnread, storage = sessionStorage) => writeFlag(UNREAD_STATE_KEY, hasUnread, storage);
|
|
39
28
|
const EMBED_PROTOCOL_VERSION = 1;
|
|
40
29
|
const EMBED_MESSAGE_TYPE = Object.freeze({
|
|
41
30
|
HOST_READY: "mm:intake:host-ready",
|
|
@@ -57,10 +46,10 @@
|
|
|
57
46
|
// belongs to the focused field, so losing it means the keyboard is already
|
|
58
47
|
// leaving — which the host's own visual viewport only admits ~500ms later.
|
|
59
48
|
CARET_STATE: "mm:intake:caret-state",
|
|
60
|
-
// Chat tells the host an inbound AI or operator message just landed
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// the panel was closed at the time.
|
|
49
|
+
// Chat tells the host an inbound AI or operator message just landed. Kept in
|
|
50
|
+
// the protocol for a future unread affordance; the TEXT US sticky has no badge
|
|
51
|
+
// today. Payload-free: only the chat knows a message arrived while only the
|
|
52
|
+
// host knows whether the panel was closed at the time.
|
|
64
53
|
MESSAGE_RECEIVED: "mm:intake:message-received"
|
|
65
54
|
});
|
|
66
55
|
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -128,96 +117,56 @@
|
|
|
128
117
|
"circle-check": '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
|
|
129
118
|
"chevron-down": '<path d="m6 9 6 6 6-6"/>'
|
|
130
119
|
};
|
|
120
|
+
const BUTTON_TEXT_US = "data:image/png;base64,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";
|
|
131
121
|
const FULL_PAGE_PANEL_QUERY = "(max-width:600px),(max-height:500px)";
|
|
132
122
|
const lucideIcon = (name, className, strokeWidth = 2) => `<svg class="${className}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${String(strokeWidth)}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${LUCIDE_ICON_PATHS[name]}</svg>`;
|
|
133
|
-
const CHAT_ICON = lucideIcon("message-circle", "mm-icon mm-icon-chat");
|
|
134
123
|
const OPEN_CLOSE_ICON = lucideIcon("x", "mm-icon mm-icon-close");
|
|
135
124
|
const WIDGET_STYLES = [
|
|
136
125
|
':host{all:initial;color-scheme:light;--mm-yellow:#fdeb01;--mm-yellow-hover:#f5de00;--mm-yellow-pressed:#e6cc00;--mm-blue:#115099;--mm-blue-hover:#0b3568;--mm-ink:#111;--mm-white:#fff;--mm-surface-blue:#f3f8ff;--mm-chrome:#e8eef2;--mm-line:#e2e8f0;--mm-muted:#545454;--mm-green:#0f9d58;--mm-font:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}',
|
|
137
126
|
"*,*::before,*::after{box-sizing:border-box}",
|
|
138
127
|
"button{font:inherit}",
|
|
139
|
-
"@keyframes mm-launcher-in{from{opacity:0;transform:
|
|
128
|
+
"@keyframes mm-launcher-in{from{opacity:0;transform:translate(8px,-50%) scale(.94)}to{opacity:1;transform:translateY(-50%) scale(1)}}",
|
|
129
|
+
"@keyframes mm-close-in{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}",
|
|
140
130
|
"@keyframes mm-panel-in{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}",
|
|
141
131
|
"@keyframes mm-panel-out{from{opacity:1;transform:none}to{opacity:0;transform:translateY(10px) scale(.98)}}",
|
|
142
|
-
"@keyframes mm-ping{0%{transform:scale(1);opacity:.55}70%,100%{transform:scale(2.4);opacity:0}}",
|
|
143
|
-
// Same register as the chat's own typing dots (typing-indicator.tsx): rest at
|
|
144
|
-
// .4 opacity, pulse to full with a 1.2x scale, each dot a beat behind the last.
|
|
145
132
|
"@keyframes mm-dot{0%,100%{opacity:.4;transform:scale(1)}50%{opacity:1;transform:scale(1.2)}}",
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
|
|
133
|
+
// Closed: LivePerson TEXT US sticky under the chat layer. Open: swap for a
|
|
134
|
+
// blue X disc above the chat so there is always a clear close control.
|
|
135
|
+
// Site sticky sits a few px in from the viewport edge, not flush.
|
|
136
|
+
// Against the host page the near-max z-index is only the fallback for
|
|
137
|
+
// browsers without the Popover API — everywhere else the mount rides the top
|
|
138
|
+
// layer (widget.ts) and outranks any host z-index.
|
|
139
|
+
".mm-launcher{position:fixed;right:10px;top:42%;z-index:2147482999;display:grid;place-items:center;width:auto;height:auto;padding:0;border:0;border-radius:0;outline:none;background:transparent;color:var(--mm-ink);box-shadow:none;cursor:pointer;user-select:none;-webkit-user-select:none;-webkit-user-drag:none;transform:translateY(-50%);animation:mm-launcher-in .28s cubic-bezier(.23,1,.32,1) both;transition:transform .15s cubic-bezier(.23,1,.32,1),filter .15s ease,background-color .15s ease}",
|
|
149
140
|
".mm-launcher *{user-select:none;-webkit-user-select:none;-webkit-user-drag:none}",
|
|
150
|
-
".mm-launcher:hover{
|
|
151
|
-
".mm-launcher:active{
|
|
141
|
+
".mm-launcher:hover{transform:translateY(-50%) translateX(-2px);filter:drop-shadow(0 4px 10px rgba(17,17,17,.18))}",
|
|
142
|
+
".mm-launcher:active{transform:translateY(-50%) translateX(0);filter:none}",
|
|
152
143
|
".mm-launcher:focus-visible{outline:3px solid var(--mm-blue);outline-offset:3px}",
|
|
153
|
-
".mm-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
'.mm-launcher[aria-expanded="true"]
|
|
144
|
+
".mm-text-us{display:block;width:38px;height:auto;pointer-events:none}",
|
|
145
|
+
".mm-icon{position:absolute;top:50%;left:50%;display:none;width:22px;height:22px;pointer-events:none;transform:translate(-50%,-50%)}",
|
|
146
|
+
// Open on desktop: X sits on the chat's top-right corner (chat is bottom:24,
|
|
147
|
+
// height min(640px, 100vh - 48px)).
|
|
148
|
+
'.mm-launcher[aria-expanded="true"]{top:calc(100vh - 24px - min(640px,100vh - 48px) + 12px);right:36px;bottom:auto;z-index:2147483001;width:44px;height:44px;border-radius:999px;background:var(--mm-blue);color:var(--mm-white);box-shadow:0 4px 14px rgba(17,17,17,.2);transform:none;animation:mm-close-in .2s cubic-bezier(.23,1,.32,1) both;filter:none}',
|
|
149
|
+
'.mm-launcher[aria-expanded="true"]:hover,.mm-launcher[aria-expanded="true"]:active{transform:none;filter:none;background:var(--mm-blue-hover)}',
|
|
150
|
+
'.mm-launcher[aria-expanded="true"] .mm-text-us{display:none}',
|
|
158
151
|
'.mm-launcher[aria-expanded="true"] .mm-icon-close{display:block}',
|
|
159
|
-
|
|
160
|
-
// tint. Measured on iOS 26: while the panel is full-page, Safari takes the
|
|
161
|
-
// colour of its own status-bar and URL-bar bands straight off this background
|
|
162
|
-
// — ahead of the host page's `theme-color` and root background, which it
|
|
163
|
-
// ignores outright once the chat frame has committed a navigation. So this is
|
|
164
|
-
// the lever that decides what the bands look like, and the bands sit right
|
|
165
|
-
// against the chat's header and trust line.
|
|
166
|
-
// Two flat halves rather than one colour, because the two bands are sampled
|
|
167
|
-
// independently: the top one always sits against the chat header, while the
|
|
168
|
-
// bottom one sits against the trust line or, with a keyboard up, the composer.
|
|
169
|
-
".mm-chat{position:fixed;right:24px;bottom:100px;z-index:2147483000;display:flex;flex-direction:column;width:min(400px,calc(100vw - 32px));height:min(640px,calc(100vh - 132px));overflow:hidden;border:1px solid var(--mm-line);border-radius:20px;background:linear-gradient(to bottom,var(--mm-chrome) 0 50%,var(--mm-panel-bottom,var(--mm-chrome)) 50% 100%);box-shadow:0 5px 25px rgba(0,0,0,.2);animation:mm-panel-in .18s ease-out both;font-family:var(--mm-font)}",
|
|
170
|
-
// Keyboard up, the chat drops its trust line and the composer becomes the
|
|
171
|
-
// bottom-most surface, so the bottom band has to follow the composer. Only
|
|
172
|
-
// the bottom: the header is still up there against the top one.
|
|
152
|
+
".mm-chat{position:fixed;right:24px;bottom:24px;z-index:2147483000;display:flex;flex-direction:column;width:min(400px,calc(100vw - 32px));height:min(640px,calc(100vh - 48px));overflow:hidden;border:1px solid var(--mm-line);border-radius:20px;background:linear-gradient(to bottom,var(--mm-chrome) 0 50%,var(--mm-panel-bottom,var(--mm-chrome)) 50% 100%);box-shadow:0 5px 25px rgba(0,0,0,.2);animation:mm-panel-in .18s ease-out both;font-family:var(--mm-font)}",
|
|
173
153
|
'.mm-chat[data-keyboard="open"]{--mm-panel-bottom:var(--mm-surface-blue)}',
|
|
174
154
|
'.mm-chat[data-state="closing"]{pointer-events:none;animation-name:mm-panel-out}',
|
|
175
155
|
'.mm-chat[data-state="closed"]{visibility:hidden;animation-name:none}',
|
|
176
156
|
".mm-frame-wrap{position:relative;min-height:0;flex:1;background:linear-gradient(to bottom,var(--mm-chrome) 0 50%,var(--mm-panel-bottom,var(--mm-chrome)) 50% 100%)}",
|
|
177
|
-
// A chat tone, never white: the frame paints this in the gap between the
|
|
178
|
-
// document's load event and the app's first frame, and on a phone that gap is
|
|
179
|
-
// the whole screen.
|
|
180
157
|
".mm-frame{display:block;width:100%;height:100%;border:0;background:var(--mm-chrome)}",
|
|
181
158
|
".mm-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:5px;background:var(--mm-chrome)}",
|
|
182
159
|
".mm-dot{width:8px;height:8px;border-radius:999px;background:var(--mm-muted);animation:mm-dot 1.2s ease-in-out infinite}",
|
|
183
160
|
".mm-dot:nth-child(2){animation-delay:.15s}",
|
|
184
161
|
".mm-dot:nth-child(3){animation-delay:.3s}",
|
|
185
162
|
"[hidden]{display:none!important}",
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// layout viewport's top would be panned clean off the screen with it.
|
|
189
|
-
//
|
|
190
|
-
// `min-height:0` on the panel so a short landscape viewport shrinks it all the
|
|
191
|
-
// way down instead of overflowing the screen and clipping the chat's own
|
|
192
|
-
// rotate-your-phone overlay.
|
|
193
|
-
//
|
|
194
|
-
// 16px from the corner is right for a normal host site, which has nothing of
|
|
195
|
-
// its own down there. A host that mounts its own bottom chrome — the client
|
|
196
|
-
// portal and its tab bar — sets `--mm-launcher-bottom` on any ancestor of the
|
|
197
|
-
// mount (custom properties reach into the shadow tree) to lift the launcher
|
|
198
|
-
// clear of it. Only the closed launcher: open, it moves to the top corner and
|
|
199
|
-
// tracks the viewport instead.
|
|
200
|
-
// `left:0;right:0` rather than `width:100vw`: `100vw` counts the classic
|
|
201
|
-
// scrollbar the host page still has behind us, so a right-anchored panel that
|
|
202
|
-
// wide starts a scrollbar's width off the left edge and clips its own header.
|
|
203
|
-
//
|
|
204
|
-
// The shadow fills the strip below the panel. Safari's bottom bar is
|
|
205
|
-
// translucent once it collapses — scrolled down, or any time the keyboard is
|
|
206
|
-
// up — and `visualViewport.height` stops short of it, so the host page shows
|
|
207
|
-
// through underneath the chat. `lvh - svh` is exactly that bar's height, and
|
|
208
|
-
// it is 0 wherever the browser has no collapsing bar, so this costs nothing
|
|
209
|
-
// there. A shadow rather than extra height: the trust line and composer must
|
|
210
|
-
// stay above the bar, not slide under it.
|
|
211
|
-
`@media ${FULL_PAGE_PANEL_QUERY}{.mm-launcher{right:16px;bottom:var(--mm-launcher-bottom,16px)}.mm-launcher[aria-expanded="true"]{top:calc(var(--mm-viewport-top,0px) + 10px);right:10px;bottom:auto;width:44px;height:44px;box-shadow:0 4px 14px rgba(17,17,17,.2)}.mm-launcher[aria-expanded="true"] .mm-icon{width:22px;height:22px}.mm-chat{left:0;right:0;top:var(--mm-viewport-top,auto);bottom:0;width:auto;height:var(--mm-viewport-height,100dvh);min-height:0;border:0;border-radius:0;box-shadow:0 calc(100lvh - 100svh) 0 var(--mm-panel-bottom,var(--mm-chrome))}}`,
|
|
212
|
-
"@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-badge::after,.mm-dot{animation:none}}"
|
|
163
|
+
`@media ${FULL_PAGE_PANEL_QUERY}{.mm-launcher[aria-expanded="true"]{top:calc(var(--mm-viewport-top,0px) + 10px);right:10px;bottom:auto;width:44px;height:44px}.mm-chat{left:0;right:0;top:var(--mm-viewport-top,auto);bottom:0;width:auto;height:var(--mm-viewport-height,100dvh);min-height:0;border:0;border-radius:0;box-shadow:0 calc(100lvh - 100svh) 0 var(--mm-panel-bottom,var(--mm-chrome))}}`,
|
|
164
|
+
"@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-dot{animation:none}}"
|
|
213
165
|
].join("");
|
|
214
166
|
const WIDGET_MARKUP = [
|
|
215
167
|
`<style>${WIDGET_STYLES}</style>`,
|
|
216
|
-
`<button class="mm-launcher" type="button" aria-label="Open intake chat" aria-expanded="false" draggable="false"
|
|
168
|
+
`<button class="mm-launcher" type="button" aria-label="Open intake chat" aria-expanded="false" draggable="false"><img class="mm-text-us" src="${BUTTON_TEXT_US}" alt="" width="38" height="146" decoding="async" />${OPEN_CLOSE_ICON}</button>`,
|
|
217
169
|
'<section class="mm-chat" role="dialog" aria-label="Morgan and Morgan intake chat" inert hidden>',
|
|
218
|
-
// Dots rather than a sentence: the panel is up for a second or two and a line
|
|
219
|
-
// of copy reads like an error the visitor has to act on. The label carries the
|
|
220
|
-
// same information for a screen reader.
|
|
221
170
|
'<div class="mm-frame-wrap"><div class="mm-loading" role="status" aria-label="Loading secure chat"><span class="mm-dot"></span><span class="mm-dot"></span><span class="mm-dot"></span></div><iframe class="mm-frame mm-chat-frame" title="Morgan and Morgan intake chat" referrerpolicy="strict-origin-when-cross-origin"></iframe></div>',
|
|
222
171
|
"</section>"
|
|
223
172
|
].join("");
|
|
@@ -234,20 +183,13 @@
|
|
|
234
183
|
chatDialog: requireElement(shadow, ".mm-chat"),
|
|
235
184
|
chatFrame: requireElement(shadow, ".mm-chat-frame"),
|
|
236
185
|
chatLoading: requireElement(shadow, ".mm-loading"),
|
|
237
|
-
launcher: requireElement(shadow, ".mm-launcher")
|
|
238
|
-
unreadBadge: requireElement(shadow, ".mm-badge")
|
|
186
|
+
launcher: requireElement(shadow, ".mm-launcher")
|
|
239
187
|
};
|
|
240
188
|
};
|
|
241
189
|
const PANEL_ANIMATION_MS = 180;
|
|
242
190
|
const CHAT_CHROME_COLOR = "#e8eef2";
|
|
243
191
|
const KEYBOARD_MIN_SHRINK_PX = 100;
|
|
244
192
|
const CHAT_READY_FALLBACK_MS = 4e3;
|
|
245
|
-
const getLauncherLabel = (isOpen, hasUnread) => {
|
|
246
|
-
if (isOpen) {
|
|
247
|
-
return "Close intake chat";
|
|
248
|
-
}
|
|
249
|
-
return hasUnread ? "Open intake chat, new message" : "Open intake chat";
|
|
250
|
-
};
|
|
251
193
|
const cleanSigningReturnUrl = () => {
|
|
252
194
|
const cleanedReturnUrl = buildSigningReturnUrl();
|
|
253
195
|
if (cleanedReturnUrl !== null) {
|
|
@@ -261,26 +203,24 @@
|
|
|
261
203
|
const shadow = mount.attachShadow({ mode: "open" });
|
|
262
204
|
const elements = renderWidgetShell(shadow);
|
|
263
205
|
document.body.append(mount);
|
|
206
|
+
if (typeof mount.showPopover === "function") {
|
|
207
|
+
mount.setAttribute("popover", "manual");
|
|
208
|
+
mount.style.cssText = "position:fixed;inset:0 auto auto 0;width:0;height:0;margin:0;border:0;padding:0;overflow:visible;background:transparent";
|
|
209
|
+
try {
|
|
210
|
+
mount.showPopover();
|
|
211
|
+
} catch {
|
|
212
|
+
}
|
|
213
|
+
}
|
|
264
214
|
const completedSigningEnvelopeId = readCompletedSigningEnvelopeId();
|
|
265
215
|
let chatHasLoaded = false;
|
|
266
216
|
let chatCloseTimer;
|
|
267
217
|
let chatReadyTimer;
|
|
268
218
|
let isKeyboardOpen = false;
|
|
269
219
|
let hasReleasedKeyboardEarly = false;
|
|
270
|
-
let hasUnread = readUnreadState();
|
|
271
|
-
const loadUnreadIndicator = () => {
|
|
272
|
-
elements.unreadBadge.hidden = !hasUnread;
|
|
273
|
-
syncLauncherLabel();
|
|
274
|
-
};
|
|
275
|
-
const setHasUnread = (next) => {
|
|
276
|
-
hasUnread = next;
|
|
277
|
-
writeUnreadState(next);
|
|
278
|
-
loadUnreadIndicator();
|
|
279
|
-
};
|
|
280
220
|
const syncLauncherLabel = () => {
|
|
281
221
|
const isOpen = elements.chatDialog.dataset.state === "open";
|
|
282
222
|
elements.launcher.setAttribute("aria-expanded", String(isOpen));
|
|
283
|
-
elements.launcher.setAttribute("aria-label",
|
|
223
|
+
elements.launcher.setAttribute("aria-label", isOpen ? "Close intake chat" : "Open intake chat");
|
|
284
224
|
};
|
|
285
225
|
const postToChat = (message) => {
|
|
286
226
|
var _a2;
|
|
@@ -443,7 +383,7 @@
|
|
|
443
383
|
elements.chatDialog.dataset.state = "open";
|
|
444
384
|
elements.chatDialog.removeAttribute("aria-hidden");
|
|
445
385
|
elements.chatDialog.removeAttribute("inert");
|
|
446
|
-
|
|
386
|
+
syncLauncherLabel();
|
|
447
387
|
startViewportTracking();
|
|
448
388
|
ensureChatLoaded();
|
|
449
389
|
elements.chatFrame.focus();
|
|
@@ -500,9 +440,6 @@
|
|
|
500
440
|
return;
|
|
501
441
|
}
|
|
502
442
|
if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.MESSAGE_RECEIVED)) {
|
|
503
|
-
if (elements.chatDialog.dataset.state !== "open") {
|
|
504
|
-
setHasUnread(true);
|
|
505
|
-
}
|
|
506
443
|
return;
|
|
507
444
|
}
|
|
508
445
|
if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.SIGNING_REQUESTED)) {
|
|
@@ -551,7 +488,7 @@
|
|
|
551
488
|
});
|
|
552
489
|
globalThis.addEventListener("message", handleMessage);
|
|
553
490
|
document.addEventListener("keydown", handleKeydown);
|
|
554
|
-
|
|
491
|
+
syncLauncherLabel();
|
|
555
492
|
if (completedSigningEnvelopeId !== null || readOpenState()) {
|
|
556
493
|
openChat();
|
|
557
494
|
}
|