@morgan-and-morgan/intake-agent 1.0.0-alpha.15 → 1.0.0-alpha.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1
- package/dist/consultation-chat.svg +3 -0
- package/dist/consultation-close.svg +3 -0
- package/dist/consultation-john-morgan.png +0 -0
- package/dist/consultation-kuunari.woff2 +0 -0
- package/dist/consultation-nunito-sans.woff2 +0 -0
- package/dist/consultation-online-desktop.svg +3 -0
- package/dist/consultation-online-mobile.svg +3 -0
- package/dist/consultation-team.png +0 -0
- package/dist/mm-intake-widget.js +166 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ Load the widget with a script tag, pinning an exact version:
|
|
|
6
6
|
<script
|
|
7
7
|
src="https://cdn.jsdelivr.net/npm/@morgan-and-morgan/intake-agent@<version>/dist/mm-intake-widget.js"
|
|
8
8
|
data-chat-url="https://example.com/chat"
|
|
9
|
+
data-prompt-delay-seconds="30"
|
|
9
10
|
></script>
|
|
10
11
|
```
|
|
11
12
|
|
|
@@ -34,9 +35,33 @@ major. Every release is tagged `intake-agent-vx.y.z`.
|
|
|
34
35
|
| --- | --- | --- |
|
|
35
36
|
| `data-chat-url` | Release environment URL | Chat iframe target |
|
|
36
37
|
| `data-auto-open` | `false` | Open the chat immediately after mount |
|
|
38
|
+
| `data-prompt-delay-seconds` | `30` | Seconds after mount before showing the consultation modal |
|
|
39
|
+
|
|
40
|
+
Set the delay on the script tag before it loads. Non-negative numbers are
|
|
41
|
+
accepted, including fractions; `0` shows the modal immediately. Missing, empty,
|
|
42
|
+
invalid, negative, or overflowing values (above 2147483.647 seconds) use 30 seconds.
|
|
43
|
+
The value is read locally and adds no configuration request. Changing the
|
|
44
|
+
attribute after the script loads does not reschedule the modal. Existing popup
|
|
45
|
+
suppression and dismissal cooldowns still apply.
|
|
37
46
|
|
|
38
47
|
The consultation modal reads `window.drupalSettings.mxPopup`, falling back to
|
|
39
48
|
`window.mxChatbotSettings.mxPopup` when the Drupal field is absent. Only the
|
|
40
49
|
boolean `false` suppresses the modal, including calls to `showPrompt()`.
|
|
41
50
|
Missing settings preserve the usual display rules. Settings are read when the
|
|
42
|
-
modal is about to appear; the launcher and chat remain available.
|
|
51
|
+
modal is about to appear; the launcher and chat remain available. Set suppression
|
|
52
|
+
before loading the embed when using a zero-second delay, so the first display
|
|
53
|
+
check sees the intended setting.
|
|
54
|
+
|
|
55
|
+
## Consultation prompt design
|
|
56
|
+
|
|
57
|
+
The responsive prompt follows the [desktop and mobile Figma layouts](https://www.figma.com/design/0SxWl42gdhx08KFe2ldpd8/MM-Design-System-v4.0?node-id=21250-169311).
|
|
58
|
+
Portrait, avatar, status dots, and icons are exported from those layers.
|
|
59
|
+
The fonts are the existing website's [Kuunari Bold Compressed](https://www.forthepeople.com/themes/custom/morgan/fonts/Kuunari/kuunari-bold-compressed.woff2)
|
|
60
|
+
and [Nunito Sans](https://www.forthepeople.com/themes/custom/morgan/fonts/NunitoSans/NunitoSans.woff2).
|
|
61
|
+
On forthepeople.com, the prompt loads these fonts from the host site to respect
|
|
62
|
+
its font security policy. Other hosts use the bundled copies.
|
|
63
|
+
Keep prompt assets in `public/` and `apps/expo/public/intake-widget/` identical;
|
|
64
|
+
the asset tests check both the CDN and portal copies.
|
|
65
|
+
|
|
66
|
+
Retain `consultation-prompt.webp` at both asset origins for older deployed widget
|
|
67
|
+
versions. The redesigned prompt does not request it.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="24" height="29" viewBox="0 0 24 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M9.75 22.5V23.25L13.125 20.7188C13.5 20.4375 13.9688 20.25 14.4844 20.25H21C21.375 20.25 21.75 19.9219 21.75 19.5V6C21.75 5.625 21.375 5.25 21 5.25H3C2.57812 5.25 2.25 5.625 2.25 6V19.5C2.25 19.9219 2.57812 20.25 3 20.25H7.5C8.71875 20.25 9.75 21.2812 9.75 22.5ZM9.70312 26.1094L9.46875 26.25L8.67188 26.8594C8.4375 27.0469 8.15625 27.0469 7.875 26.9531C7.64062 26.8125 7.5 26.5781 7.5 26.25V25.2656V24.9844V24.9375V24.75V22.5H5.25H3C1.3125 22.5 0 21.1875 0 19.5V6C0 4.35938 1.3125 3 3 3H21C22.6406 3 24 4.35938 24 6V19.5C24 21.1875 22.6406 22.5 21 22.5H14.4844L9.75 26.0625L9.70312 26.1094ZM7.125 9.75H16.875C17.4844 9.75 18 10.2656 18 10.875C18 11.5312 17.4844 12 16.875 12H7.125C6.46875 12 6 11.5312 6 10.875C6 10.2656 6.46875 9.75 7.125 9.75ZM7.125 14.25H12.375C12.9844 14.25 13.5 14.7656 13.5 15.375C13.5 16.0312 12.9844 16.5 12.375 16.5H7.125C6.46875 16.5 6 16.0312 6 15.375C6 14.7656 6.46875 14.25 7.125 14.25Z" fill="#061E39"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="18" height="29" viewBox="0 0 18 29" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M15.1875 22.3125L9 16.0781L2.76562 22.3125C2.48438 22.5938 2.01562 22.5938 1.6875 22.3125C1.40625 21.9844 1.40625 21.5156 1.6875 21.2344L7.92188 15L1.73438 8.8125C1.40625 8.53125 1.40625 8.0625 1.73438 7.73438C2.01562 7.45312 2.48438 7.45312 2.76562 7.73438L9 13.9688L15.1875 7.73438C15.4688 7.45312 15.9375 7.45312 16.2656 7.73438C16.5469 8.0625 16.5469 8.53125 16.2656 8.8125L10.0312 15L16.2656 21.2344C16.5469 21.5156 16.5469 21.9844 16.2656 22.3125C15.9375 22.5938 15.4688 22.5938 15.1875 22.3125Z" fill="white"/>
|
|
3
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="14.6667" height="14.6667" viewBox="0 0 14.6667 14.6667" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path id="Ellipse 52" d="M13.6667 7.33333C13.6667 10.8311 10.8311 13.6667 7.33333 13.6667C3.83553 13.6667 1 10.8311 1 7.33333C1 3.83553 3.83553 1 7.33333 1C10.8311 1 13.6667 3.83553 13.6667 7.33333Z" fill="#1FC16B" stroke-width="2" stroke="#132A4E"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="11.619" height="11.619" viewBox="0 0 11.619 11.619" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path id="Ellipse 52" d="M10.619 5.80952C10.619 8.46575 8.46575 10.619 5.80952 10.619C3.1533 10.619 1 8.46575 1 5.80952C1 3.1533 3.1533 1 5.80952 1C8.46575 1 10.619 3.1533 10.619 5.80952Z" fill="#1FC16B" stroke-width="2" stroke="#132A4E"/>
|
|
3
|
+
</svg>
|
|
Binary file
|
package/dist/mm-intake-widget.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
(function() {
|
|
2
2
|
"use strict";
|
|
3
|
+
const DEFAULT_PROMPT_DELAY_MS = 3e4;
|
|
4
|
+
const MAX_PROMPT_DELAY_MS = 2147483647;
|
|
5
|
+
const readPromptDelayMs = (seconds) => {
|
|
6
|
+
if (seconds === void 0 || seconds.trim() === "") {
|
|
7
|
+
return DEFAULT_PROMPT_DELAY_MS;
|
|
8
|
+
}
|
|
9
|
+
const delayMs = Number(seconds) * 1e3;
|
|
10
|
+
if (!Number.isFinite(delayMs) || delayMs < 0 || delayMs > MAX_PROMPT_DELAY_MS) {
|
|
11
|
+
return DEFAULT_PROMPT_DELAY_MS;
|
|
12
|
+
}
|
|
13
|
+
return delayMs;
|
|
14
|
+
};
|
|
3
15
|
const readLoaderConfig = (script, baseUri) => {
|
|
4
16
|
var _a;
|
|
5
17
|
const scriptUrl = new URL(script.src, baseUri);
|
|
@@ -9,7 +21,8 @@
|
|
|
9
21
|
assetBaseUrl: new URL(".", scriptUrl).href,
|
|
10
22
|
autoOpen: script.dataset.autoOpen === "true",
|
|
11
23
|
chatOrigin: new URL(chatUrl).origin,
|
|
12
|
-
chatUrl
|
|
24
|
+
chatUrl,
|
|
25
|
+
promptDelayMs: readPromptDelayMs(script.dataset.promptDelaySeconds)
|
|
13
26
|
};
|
|
14
27
|
};
|
|
15
28
|
const ATTRIBUTION_FIELD_MAX_LENGTH = {
|
|
@@ -220,6 +233,130 @@
|
|
|
220
233
|
return false;
|
|
221
234
|
}
|
|
222
235
|
};
|
|
236
|
+
const designSystemColors = {
|
|
237
|
+
// Colors/Base/black
|
|
238
|
+
"base-black": "#000000",
|
|
239
|
+
// Colors/Primary/100
|
|
240
|
+
"primary-100": "#f3f8ff",
|
|
241
|
+
// Colors/Primary/800
|
|
242
|
+
"primary-800": "#132a4e",
|
|
243
|
+
// Colors/Primary/900
|
|
244
|
+
"primary-900": "#061e39",
|
|
245
|
+
// Colors/Secondary/500
|
|
246
|
+
"secondary-500": "#ffec00",
|
|
247
|
+
// Colors/Secondary/700
|
|
248
|
+
"secondary-700": "#e2d100"
|
|
249
|
+
};
|
|
250
|
+
const PROMPT_FONTS = [
|
|
251
|
+
{
|
|
252
|
+
family: "MMIntakeKuunari",
|
|
253
|
+
file: "consultation-kuunari.woff2",
|
|
254
|
+
hostPath: "/themes/custom/morgan/fonts/Kuunari/kuunari-bold-compressed.woff2",
|
|
255
|
+
weight: "700",
|
|
256
|
+
fallbackClass: "mm-prompt-fallback-title"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
family: "MMIntakeNunitoSans",
|
|
260
|
+
file: "consultation-nunito-sans.woff2",
|
|
261
|
+
hostPath: "/themes/custom/morgan/fonts/NunitoSans/NunitoSans.woff2",
|
|
262
|
+
weight: "100 900",
|
|
263
|
+
fallbackClass: "mm-prompt-fallback-status"
|
|
264
|
+
}
|
|
265
|
+
];
|
|
266
|
+
const ownedPromptFonts = /* @__PURE__ */ new WeakMap();
|
|
267
|
+
const updateFontFallback = async (font, target, fallbackClass) => {
|
|
268
|
+
var _a, _b, _c;
|
|
269
|
+
if (font.status !== "loaded") (_a = target.backdrop) == null ? void 0 : _a.classList.add(fallbackClass);
|
|
270
|
+
try {
|
|
271
|
+
await font.loaded;
|
|
272
|
+
(_b = target.backdrop) == null ? void 0 : _b.classList.remove(fallbackClass);
|
|
273
|
+
} catch {
|
|
274
|
+
(_c = target.backdrop) == null ? void 0 : _c.classList.add(fallbackClass);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
const registerPromptFonts = (assetUrl, backdrop, host = globalThis.location) => {
|
|
278
|
+
const target = { backdrop };
|
|
279
|
+
const registrations = [];
|
|
280
|
+
const dispose = () => {
|
|
281
|
+
if (target.backdrop === void 0) return;
|
|
282
|
+
target.backdrop = void 0;
|
|
283
|
+
for (const registration of registrations) {
|
|
284
|
+
registration.users -= 1;
|
|
285
|
+
if (registration.users === 0) {
|
|
286
|
+
document.fonts.delete(registration.font);
|
|
287
|
+
ownedPromptFonts.delete(registration.font);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
if (typeof FontFace === "undefined") {
|
|
292
|
+
backdrop.classList.add(...PROMPT_FONTS.map(({ fallbackClass }) => fallbackClass));
|
|
293
|
+
return dispose;
|
|
294
|
+
}
|
|
295
|
+
const useHostFonts = ["forthepeople.com", "www.forthepeople.com"].includes(host.hostname);
|
|
296
|
+
for (const { family, file, hostPath, weight, fallbackClass } of PROMPT_FONTS) {
|
|
297
|
+
let font = [...document.fonts].find((registered) => registered.family === family);
|
|
298
|
+
if (font === void 0) {
|
|
299
|
+
const url = useHostFonts ? new URL(hostPath, host.origin).href : assetUrl(file);
|
|
300
|
+
font = new FontFace(family, `url(${JSON.stringify(url)})`, { weight, display: "swap" });
|
|
301
|
+
document.fonts.add(font);
|
|
302
|
+
ownedPromptFonts.set(font, { font, users: 0 });
|
|
303
|
+
}
|
|
304
|
+
const registration = ownedPromptFonts.get(font);
|
|
305
|
+
if (registration !== void 0) {
|
|
306
|
+
registration.users += 1;
|
|
307
|
+
registrations.push(registration);
|
|
308
|
+
}
|
|
309
|
+
void updateFontFallback(font, target, fallbackClass);
|
|
310
|
+
}
|
|
311
|
+
return dispose;
|
|
312
|
+
};
|
|
313
|
+
const PROMPT_STYLES = [
|
|
314
|
+
`.mm-prompt-backdrop{--mm-prompt-blue:${designSystemColors["primary-800"]};--mm-prompt-dark:${designSystemColors["primary-900"]};--mm-prompt-yellow:${designSystemColors["secondary-500"]};--mm-prompt-yellow-end:${designSystemColors["secondary-700"]};--mm-prompt-text:${designSystemColors["primary-100"]};position:fixed;inset:0;z-index:2147483002;display:flex;flex-direction:column;align-items:center;padding:12px;overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y pinch-zoom;background:rgba(0,0,0,.5);animation:mm-prompt-backdrop-in .25s cubic-bezier(.23,1,.32,1) both;font-family:"MMIntakeNunitoSans",var(--mm-font);font-variation-settings:"YTLC" 500,"wdth" 100;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}`,
|
|
315
|
+
// Auto margins center the card when it fits and keep its top reachable when it overflows.
|
|
316
|
+
".mm-prompt-card{position:relative;isolation:isolate;display:flex;flex:none;flex-direction:column;margin-block:auto;width:600px;max-width:100%;padding:16px 16px 32px;border-radius:16px;background:var(--mm-prompt-blue);color:var(--mm-white);box-shadow:0 4px 5px rgba(0,0,0,.1),0 7px 10px rgba(0,0,0,.07),0 2px 16px rgba(0,0,0,.08);animation:mm-prompt-card-in .25s cubic-bezier(.23,1,.32,1) both}",
|
|
317
|
+
".mm-prompt-status{position:relative;z-index:1;display:flex;align-items:center;gap:13px;align-self:flex-start;max-width:calc(100% - 52px);padding:8px 40px 8px 8px;border-radius:999px;background:var(--mm-prompt-dark);color:var(--mm-prompt-text)}",
|
|
318
|
+
".mm-prompt-avatar{position:relative;flex:none;width:56px;height:56px}",
|
|
319
|
+
".mm-prompt-team{display:block;width:100%;height:100%;border-radius:50%}",
|
|
320
|
+
// The exported indicator bounds include Figma's 2px outside stroke.
|
|
321
|
+
".mm-prompt-online{position:absolute;right:-2px;top:40.17px;display:block;line-height:0}",
|
|
322
|
+
".mm-prompt-online img{display:block}",
|
|
323
|
+
".mm-prompt-status-text{margin:0;font-size:20px;font-weight:700;line-height:27px;white-space:nowrap}",
|
|
324
|
+
".mm-prompt-hero{position:relative;display:flex;align-items:center;height:304px;margin-top:-40px;padding-left:16px}",
|
|
325
|
+
// The heading extends over the portrait's transparent edge.
|
|
326
|
+
'.mm-prompt-title{position:relative;z-index:1;flex:1;min-width:0;height:232px;display:flex;flex-direction:column;justify-content:flex-end;margin:0;font-family:"MMIntakeKuunari",Impact,sans-serif;font-size:72px;font-weight:700;line-height:64px;letter-spacing:-2px;text-transform:uppercase}',
|
|
327
|
+
".mm-prompt-title-line{display:block;white-space:nowrap}",
|
|
328
|
+
".mm-prompt-mobile-break{display:none}",
|
|
329
|
+
".mm-prompt-portrait{position:relative;flex:none;width:270px;height:304px}",
|
|
330
|
+
".mm-prompt-image{display:block;width:100%;height:100%;pointer-events:none}",
|
|
331
|
+
`.mm-prompt-cta{position:relative;display:flex;align-items:center;justify-content:center;gap:16px;height:56px;margin:0 16px;border-radius:8px;background:linear-gradient(to bottom,var(--mm-prompt-yellow) 41.827%,var(--mm-prompt-yellow-end));box-shadow:0 2px 4px rgba(0,0,0,.05),0 4px 3px rgba(0,0,0,.04),0 1px 2px rgba(0,0,0,.03);color:${designSystemColors["base-black"]};font-size:20px;font-weight:700;line-height:24px}`,
|
|
332
|
+
".mm-prompt-cta-label{min-width:90px}",
|
|
333
|
+
// Preserve the Figma text frames in the SVG exports so centering retains their alignment.
|
|
334
|
+
".mm-prompt-chat-icon{display:block;width:24px;height:29px}",
|
|
335
|
+
// Keep the existing whole-card click target and the two-control focus loop.
|
|
336
|
+
".mm-prompt-open{position:absolute;inset:0;z-index:2;border:0;padding:0;border-radius:16px;background:transparent;cursor:pointer}",
|
|
337
|
+
".mm-prompt-close{position:absolute;top:16px;right:16px;z-index:3;display:grid;place-items:center;width:44px;height:44px;padding:0;border:2px solid var(--mm-prompt-yellow);border-radius:50%;background:var(--mm-prompt-dark);cursor:pointer}",
|
|
338
|
+
".mm-prompt-close-icon{display:block;width:18px;height:29px;pointer-events:none}",
|
|
339
|
+
".mm-prompt-close:hover{background:var(--mm-prompt-blue)}",
|
|
340
|
+
".mm-prompt-open:focus-visible,.mm-prompt-close:focus-visible{outline:3px solid var(--mm-prompt-yellow);outline-offset:3px}",
|
|
341
|
+
'@media(max-width:623px){.mm-prompt-backdrop{background:rgba(0,0,0,.7)}.mm-prompt-card{width:min(360px,calc(100vw - 24px));min-height:496px;padding:16px 12px;overflow:hidden}.mm-prompt-status{align-self:stretch;padding-right:40px}.mm-prompt-avatar{width:40px;height:40px}.mm-prompt-online{top:28.12px}.mm-prompt-status-text{min-width:0;font-size:18px;line-height:22px}.mm-prompt-hero{position:static;flex:1;min-height:332px;align-items:flex-end;height:auto;margin-top:0;padding:0}.mm-prompt-title{top:1px;flex:none;width:100%;height:auto;font-size:64px;line-height:56px;letter-spacing:-1.28px}.mm-prompt-mobile-break{display:block}.mm-prompt-portrait{position:absolute;top:93px;right:-37px;width:253px;height:285px}.mm-prompt-portrait::after{content:"";position:absolute;left:10px;right:0;bottom:0;height:60px;background:linear-gradient(to top,var(--mm-prompt-blue) 8.772%,transparent 94.737%)}.mm-prompt-cta{flex:none;height:48px;margin:24px 0 0}.mm-prompt-close{right:12px}.mm-prompt-open:focus-visible{outline-offset:-4px}}',
|
|
342
|
+
'.mm-prompt-fallback-title .mm-prompt-title{font-family:"MMIntakeKuunari",Arial,sans-serif;font-size:32px;letter-spacing:0}',
|
|
343
|
+
'.mm-prompt-fallback-status .mm-prompt-status-text{font-family:"MMIntakeNunitoSans",Arial,sans-serif;font-size:16px}',
|
|
344
|
+
".mm-prompt-close-contrast{display:none}",
|
|
345
|
+
"@media(forced-colors:active){.mm-prompt-card,.mm-prompt-cta,.mm-prompt-close{border:1px solid ButtonText}.mm-prompt-close-icon,.mm-prompt-chat-icon{display:none}.mm-prompt-close-contrast{display:block;color:ButtonText;font:28px/1 Arial,sans-serif}.mm-prompt-open:focus-visible,.mm-prompt-close:focus-visible{outline:2px solid ButtonText;outline-offset:-4px}}"
|
|
346
|
+
].join("");
|
|
347
|
+
const promptMarkup = (assetUrl) => [
|
|
348
|
+
'<div class="mm-prompt-card">',
|
|
349
|
+
'<div class="mm-prompt-status"><span class="mm-prompt-avatar" aria-hidden="true">',
|
|
350
|
+
`<img loading="lazy" class="mm-prompt-team" src="${assetUrl("consultation-team.png")}" alt="" width="56" height="56" decoding="async" />`,
|
|
351
|
+
`<picture class="mm-prompt-online"><source media="(max-width:623px)" srcset="${assetUrl("consultation-online-mobile.svg")}" /><img loading="lazy" src="${assetUrl("consultation-online-desktop.svg")}" alt="" /></picture>`,
|
|
352
|
+
'</span><p class="mm-prompt-status-text">Our team is <br class="mm-prompt-mobile-break" />available 24/7</p></div>',
|
|
353
|
+
'<div class="mm-prompt-hero"><h2 class="mm-prompt-title"><span class="mm-prompt-title-line">Click <br class="mm-prompt-mobile-break" />to start</span><span class="mm-prompt-title-line">your free</span><span class="mm-prompt-title-line">consultation</span></h2>',
|
|
354
|
+
`<div class="mm-prompt-portrait" aria-hidden="true"><img loading="lazy" class="mm-prompt-image" src="${assetUrl("consultation-john-morgan.png")}" alt="" width="270" height="304" decoding="async" /></div></div>`,
|
|
355
|
+
`<span class="mm-prompt-cta" aria-hidden="true"><img loading="lazy" class="mm-prompt-chat-icon" src="${assetUrl("consultation-chat.svg")}" alt="" width="24" height="29" /><span class="mm-prompt-cta-label">Chat now</span></span>`,
|
|
356
|
+
'<button class="mm-prompt-open" type="button" aria-label="Chat now about a free consultation"></button>',
|
|
357
|
+
`<button class="mm-prompt-close" type="button" aria-label="Dismiss consultation prompt"><img class="mm-prompt-close-icon" src="${assetUrl("consultation-close.svg")}" alt="" width="18" height="29" /><span class="mm-prompt-close-contrast" aria-hidden="true">×</span></button>`,
|
|
358
|
+
"</div>"
|
|
359
|
+
].join("");
|
|
223
360
|
const LUCIDE_ICON_PATHS = {
|
|
224
361
|
"message-circle": '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"/>',
|
|
225
362
|
"x": '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
|
|
@@ -235,7 +372,6 @@
|
|
|
235
372
|
const FULL_PAGE_PANEL_QUERY = "(max-width:600px),(max-height:500px)";
|
|
236
373
|
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>`;
|
|
237
374
|
const OPEN_CLOSE_ICON = lucideIcon("x", "mm-icon mm-icon-close");
|
|
238
|
-
const PROMPT_CLOSE_ICON = lucideIcon("x", "mm-prompt-close-icon", 2.5);
|
|
239
375
|
const WIDGET_STYLES = [
|
|
240
376
|
':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}',
|
|
241
377
|
"*,*::before,*::after{box-sizing:border-box}",
|
|
@@ -278,31 +414,19 @@
|
|
|
278
414
|
".mm-dot{width:8px;height:8px;border-radius:999px;background:var(--mm-muted);animation:mm-dot 1.2s ease-in-out infinite}",
|
|
279
415
|
".mm-dot:nth-child(2){animation-delay:.15s}",
|
|
280
416
|
".mm-dot:nth-child(3){animation-delay:.3s}",
|
|
281
|
-
|
|
282
|
-
".mm-prompt-card{position:relative;width:min(632px,calc(100vw - 32px),calc((100vh - 32px)*1.26148));aspect-ratio:632/501;animation:mm-prompt-card-in .25s cubic-bezier(.23,1,.32,1) both}",
|
|
283
|
-
".mm-prompt-image{display:block;width:100%;height:100%;object-fit:contain;pointer-events:none}",
|
|
284
|
-
".mm-prompt-open,.mm-prompt-close{position:absolute;border:0;outline:none;background:transparent;cursor:pointer}",
|
|
285
|
-
".mm-prompt-open{inset:0;border-radius:24px}",
|
|
286
|
-
".mm-prompt-close{top:4.5%;right:3.1%;z-index:1;display:grid;place-items:center;width:44px;height:44px;border-radius:999px;color:var(--mm-white)}",
|
|
287
|
-
'.mm-prompt-close::before{content:"";position:absolute;width:28px;height:28px;border-radius:999px;background:#050505;box-shadow:0 1px 4px rgba(0,0,0,.35);transition:background-color .12s ease}',
|
|
288
|
-
".mm-prompt-close-icon{position:relative;display:block;width:16px;height:16px;pointer-events:none}",
|
|
289
|
-
".mm-prompt-close:hover::before{background:#252525}",
|
|
290
|
-
".mm-prompt-open:focus-visible{outline:3px solid var(--mm-yellow);outline-offset:-8px}",
|
|
291
|
-
".mm-prompt-close:focus-visible{outline:none}",
|
|
292
|
-
".mm-prompt-close:focus-visible::before{background:#050505;box-shadow:inset 0 0 0 2px var(--mm-yellow),0 1px 4px rgba(0,0,0,.35)}",
|
|
417
|
+
PROMPT_STYLES,
|
|
293
418
|
"[hidden]{display:none!important}",
|
|
294
419
|
`@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))}}`,
|
|
295
|
-
"@media(forced-colors:active){.mm-prompt-close:focus-visible{outline:2px solid ButtonText;outline-offset:-9px}}",
|
|
296
420
|
"@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-prompt-card{animation-name:mm-prompt-backdrop-in}.mm-dot{animation:none}}"
|
|
297
421
|
].join("");
|
|
298
|
-
const widgetMarkup = (
|
|
422
|
+
const widgetMarkup = (assetUrl) => [
|
|
299
423
|
`<style>${WIDGET_STYLES}</style>`,
|
|
300
|
-
`<button class="mm-launcher" type="button" aria-label="Open intake chat" aria-expanded="false" draggable="false"><img class="mm-text-us" src="${
|
|
424
|
+
`<button class="mm-launcher" type="button" aria-label="Open intake chat" aria-expanded="false" draggable="false"><img class="mm-text-us" src="${assetUrl("button-text-us.png")}" alt="" width="38" height="147" decoding="async" />${OPEN_CLOSE_ICON}</button>`,
|
|
301
425
|
'<section class="mm-chat" role="dialog" aria-label="Morgan and Morgan intake chat" inert hidden>',
|
|
302
426
|
'<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>',
|
|
303
427
|
"</section>",
|
|
304
428
|
'<section class="mm-prompt-backdrop" role="dialog" aria-modal="true" aria-label="Start your free consultation" inert hidden>',
|
|
305
|
-
|
|
429
|
+
promptMarkup(assetUrl),
|
|
306
430
|
"</section>"
|
|
307
431
|
].join("");
|
|
308
432
|
const requireElement = (shadow, selector) => {
|
|
@@ -312,9 +436,11 @@
|
|
|
312
436
|
}
|
|
313
437
|
return element;
|
|
314
438
|
};
|
|
315
|
-
const renderWidgetShell = (shadow,
|
|
316
|
-
shadow.innerHTML = widgetMarkup(
|
|
439
|
+
const renderWidgetShell = (shadow, assetUrl) => {
|
|
440
|
+
shadow.innerHTML = widgetMarkup(assetUrl);
|
|
441
|
+
const disposePromptFonts = registerPromptFonts(assetUrl, requireElement(shadow, ".mm-prompt-backdrop"));
|
|
317
442
|
return {
|
|
443
|
+
disposePromptFonts,
|
|
318
444
|
chatDialog: requireElement(shadow, ".mm-chat"),
|
|
319
445
|
chatFrame: requireElement(shadow, ".mm-chat-frame"),
|
|
320
446
|
chatLoading: requireElement(shadow, ".mm-loading"),
|
|
@@ -325,7 +451,6 @@
|
|
|
325
451
|
};
|
|
326
452
|
};
|
|
327
453
|
const PANEL_ANIMATION_MS = 180;
|
|
328
|
-
const PROMPT_DELAY_MS = 5e3;
|
|
329
454
|
const PROMPT_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
|
|
330
455
|
const PROMPT_COOLDOWN_KEY = "mm-intake-widget-prompt-dismissed-at";
|
|
331
456
|
const PROMPT_SESSION_KEY = "mm-intake-widget-prompt-dismissed";
|
|
@@ -367,14 +492,15 @@
|
|
|
367
492
|
}
|
|
368
493
|
};
|
|
369
494
|
const mountIntakeWidget = (config, onDestroy) => {
|
|
495
|
+
var _a;
|
|
370
496
|
const mount = document.createElement("div");
|
|
371
497
|
mount.dataset.mmIntakeWidget = "";
|
|
372
498
|
const shadow = mount.attachShadow({ mode: "open" });
|
|
373
499
|
const assetUrl = (fileName) => {
|
|
374
|
-
var
|
|
375
|
-
return new URL(fileName, (
|
|
500
|
+
var _a2;
|
|
501
|
+
return new URL(fileName, (_a2 = config.assetBaseUrl) != null ? _a2 : `${config.chatOrigin}/intake-widget/`).href;
|
|
376
502
|
};
|
|
377
|
-
const elements = renderWidgetShell(shadow, assetUrl
|
|
503
|
+
const elements = renderWidgetShell(shadow, assetUrl);
|
|
378
504
|
document.body.append(mount);
|
|
379
505
|
if (typeof mount.showPopover === "function") {
|
|
380
506
|
mount.setAttribute("popover", "manual");
|
|
@@ -398,8 +524,8 @@
|
|
|
398
524
|
elements.launcher.setAttribute("aria-label", isOpen ? "Close intake chat" : "Open intake chat");
|
|
399
525
|
};
|
|
400
526
|
const postToChat = (message) => {
|
|
401
|
-
var
|
|
402
|
-
(
|
|
527
|
+
var _a2;
|
|
528
|
+
(_a2 = elements.chatFrame.contentWindow) == null ? void 0 : _a2.postMessage(message, config.chatOrigin);
|
|
403
529
|
};
|
|
404
530
|
const postHostReady = () => {
|
|
405
531
|
const currentUrl = globalThis.location.href;
|
|
@@ -427,10 +553,10 @@
|
|
|
427
553
|
postToChat(createEmbedProtocolMessage(EMBED_MESSAGE_TYPE.FOCUS_COMPOSER));
|
|
428
554
|
};
|
|
429
555
|
const answerAuthTokenRequest = async () => {
|
|
430
|
-
var
|
|
556
|
+
var _a2;
|
|
431
557
|
let token;
|
|
432
558
|
try {
|
|
433
|
-
token = await ((
|
|
559
|
+
token = await ((_a2 = config.getAuthToken) == null ? void 0 : _a2.call(config));
|
|
434
560
|
} catch {
|
|
435
561
|
token = void 0;
|
|
436
562
|
}
|
|
@@ -462,11 +588,11 @@
|
|
|
462
588
|
}
|
|
463
589
|
};
|
|
464
590
|
const showPrompt = () => {
|
|
465
|
-
var
|
|
591
|
+
var _a2, _b, _c;
|
|
466
592
|
globalThis.clearTimeout(promptTimer);
|
|
467
593
|
promptTimer = void 0;
|
|
468
594
|
const host = globalThis;
|
|
469
|
-
const mxPopup = (_c = (
|
|
595
|
+
const mxPopup = (_c = (_a2 = host.drupalSettings) == null ? void 0 : _a2.mxPopup) != null ? _c : (_b = host.mxChatbotSettings) == null ? void 0 : _b.mxPopup;
|
|
470
596
|
if (mxPopup === false || hasPromptCooldown() || elements.chatDialog.dataset.state === "open") {
|
|
471
597
|
return;
|
|
472
598
|
}
|
|
@@ -528,7 +654,7 @@
|
|
|
528
654
|
}
|
|
529
655
|
};
|
|
530
656
|
const restoreHostChrome = () => {
|
|
531
|
-
var
|
|
657
|
+
var _a2, _b;
|
|
532
658
|
if (themeColorBackup === null) {
|
|
533
659
|
return;
|
|
534
660
|
}
|
|
@@ -539,7 +665,7 @@
|
|
|
539
665
|
createdThemeColor = null;
|
|
540
666
|
themeColorBackup = null;
|
|
541
667
|
for (const [index, root] of hostRoots.entries()) {
|
|
542
|
-
root.style.backgroundColor = (
|
|
668
|
+
root.style.backgroundColor = (_a2 = hostBackgroundColorBackup == null ? void 0 : hostBackgroundColorBackup[index]) != null ? _a2 : "";
|
|
543
669
|
root.style.overflow = (_b = hostOverflowBackup == null ? void 0 : hostOverflowBackup[index]) != null ? _b : "";
|
|
544
670
|
}
|
|
545
671
|
hostBackgroundColorBackup = null;
|
|
@@ -565,16 +691,16 @@
|
|
|
565
691
|
syncHostChrome();
|
|
566
692
|
}
|
|
567
693
|
const startViewportTracking = () => {
|
|
568
|
-
var
|
|
569
|
-
(
|
|
694
|
+
var _a2, _b;
|
|
695
|
+
(_a2 = globalThis.visualViewport) == null ? void 0 : _a2.addEventListener("resize", syncViewport);
|
|
570
696
|
(_b = globalThis.visualViewport) == null ? void 0 : _b.addEventListener("scroll", syncViewport);
|
|
571
697
|
fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.addEventListener("change", syncHostChrome);
|
|
572
698
|
syncViewport();
|
|
573
699
|
syncHostChrome();
|
|
574
700
|
};
|
|
575
701
|
const stopViewportTracking = () => {
|
|
576
|
-
var
|
|
577
|
-
(
|
|
702
|
+
var _a2, _b;
|
|
703
|
+
(_a2 = globalThis.visualViewport) == null ? void 0 : _a2.removeEventListener("resize", syncViewport);
|
|
578
704
|
(_b = globalThis.visualViewport) == null ? void 0 : _b.removeEventListener("scroll", syncViewport);
|
|
579
705
|
fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.removeEventListener("change", syncHostChrome);
|
|
580
706
|
setKeyboardOpen(false);
|
|
@@ -611,7 +737,7 @@
|
|
|
611
737
|
}
|
|
612
738
|
};
|
|
613
739
|
const closeChat = () => {
|
|
614
|
-
var
|
|
740
|
+
var _a2;
|
|
615
741
|
elements.launcher.focus();
|
|
616
742
|
writeOpenState(false);
|
|
617
743
|
const wasOpen = elements.chatDialog.dataset.state === "open";
|
|
@@ -624,7 +750,7 @@
|
|
|
624
750
|
if (!wasOpen) {
|
|
625
751
|
return;
|
|
626
752
|
}
|
|
627
|
-
if (((
|
|
753
|
+
if (((_a2 = matchMediaQuery("(prefers-reduced-motion: reduce)")) == null ? void 0 : _a2.matches) === true) {
|
|
628
754
|
finishChatClose();
|
|
629
755
|
return;
|
|
630
756
|
}
|
|
@@ -700,6 +826,7 @@
|
|
|
700
826
|
}
|
|
701
827
|
};
|
|
702
828
|
const destroy = () => {
|
|
829
|
+
elements.disposePromptFonts();
|
|
703
830
|
stopViewportTracking();
|
|
704
831
|
globalThis.clearTimeout(chatCloseTimer);
|
|
705
832
|
globalThis.clearTimeout(chatReadyTimer);
|
|
@@ -740,7 +867,7 @@
|
|
|
740
867
|
if (returnedFromSigning || readOpenState()) {
|
|
741
868
|
openChat();
|
|
742
869
|
} else if (!hasPromptCooldown()) {
|
|
743
|
-
promptTimer = globalThis.setTimeout(showPrompt,
|
|
870
|
+
promptTimer = globalThis.setTimeout(showPrompt, (_a = config.promptDelayMs) != null ? _a : DEFAULT_PROMPT_DELAY_MS);
|
|
744
871
|
}
|
|
745
872
|
return Object.freeze({
|
|
746
873
|
close: closeChat,
|