@morgan-and-morgan/intake-agent 1.2.0 → 1.4.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/README.md CHANGED
@@ -21,6 +21,10 @@ placeholder, don't bump it by hand.
21
21
  | `release/**` | `x.y.z-beta.N` | `beta` |
22
22
  | `main` | `x.y.z` | `latest` |
23
23
 
24
+ Each bundle also carries its matching chat environment: development for
25
+ `alpha`, UAT for `beta`, and production for `latest`. `data-chat-url` remains
26
+ an explicit override.
27
+
24
28
  `fix:` bumps the patch, `feat:` the minor, a `BREAKING CHANGE:` footer the
25
29
  major. Every release is tagged `intake-agent-vx.y.z`.
26
30
 
@@ -28,5 +32,5 @@ major. Every release is tagged `intake-agent-vx.y.z`.
28
32
 
29
33
  | Attribute | Default | Purpose |
30
34
  | --- | --- | --- |
31
- | `data-chat-url` | `/embed/intake` | Chat iframe target (resolved against the loader's origin) |
35
+ | `data-chat-url` | Release environment URL | Chat iframe target |
32
36
  | `data-auto-open` | `false` | Open the chat immediately after mount |
Binary file
Binary file
@@ -1,11 +1,12 @@
1
1
  (function() {
2
2
  "use strict";
3
- const DEFAULT_CHAT_PATH = "/embed/intake";
4
3
  const readLoaderConfig = (script, baseUri) => {
5
4
  var _a;
6
5
  const scriptUrl = new URL(script.src, baseUri);
7
- const chatUrl = new URL((_a = script.dataset.chatUrl) != null ? _a : DEFAULT_CHAT_PATH, scriptUrl).href;
6
+ const bundledChatUrl = "https://chat.mx2.law/embed/intake";
7
+ const chatUrl = new URL((_a = script.dataset.chatUrl) != null ? _a : bundledChatUrl, scriptUrl).href;
8
8
  return {
9
+ assetBaseUrl: new URL(".", scriptUrl).href,
9
10
  autoOpen: script.dataset.autoOpen === "true",
10
11
  chatOrigin: new URL(chatUrl).origin,
11
12
  chatUrl
@@ -36,10 +37,10 @@
36
37
  }
37
38
  return Object.keys(sanitized).length === 0 ? null : sanitized;
38
39
  };
39
- const LANDING_PAGE_COOKIE = "tracked_landing_page";
40
- const LANDING_TIMESTAMP_COOKIE = "tracked_landing_timestamp";
40
+ const LANDING_PAGE_COOKIES = ["trackedLandingPage", "tracked_landing_page"];
41
+ const LANDING_TIMESTAMP_COOKIES = ["trackedLandingPageTimestamp", "tracked_landing_timestamp"];
41
42
  const readTimestampCookie = (cookie) => {
42
- const raw = readCookie(cookie, LANDING_TIMESTAMP_COOKIE);
43
+ const raw = readFirstCookie(cookie, LANDING_TIMESTAMP_COOKIES);
43
44
  return raw === void 0 ? void 0 : decodeCookieValue(raw);
44
45
  };
45
46
  const readCookie = (cookie, name) => {
@@ -47,6 +48,15 @@
47
48
  const raw = (_a = cookie.split(";").map((entry) => entry.trim()).find((entry) => entry.startsWith(`${name}=`))) == null ? void 0 : _a.slice(name.length + 1);
48
49
  return raw === void 0 || raw === "" ? void 0 : raw;
49
50
  };
51
+ const readFirstCookie = (cookie, names) => {
52
+ for (const name of names) {
53
+ const raw = readCookie(cookie, name);
54
+ if (raw !== void 0) {
55
+ return raw;
56
+ }
57
+ }
58
+ return void 0;
59
+ };
50
60
  const decodeCookieValue = (raw) => {
51
61
  try {
52
62
  return decodeURIComponent(raw);
@@ -62,7 +72,7 @@
62
72
  }
63
73
  };
64
74
  const readLandingPage = (cookie) => {
65
- const raw = readCookie(cookie, LANDING_PAGE_COOKIE);
75
+ const raw = readFirstCookie(cookie, LANDING_PAGE_COOKIES);
66
76
  if (raw === void 0 || parseUrl(raw) !== null) {
67
77
  return raw;
68
78
  }
@@ -115,6 +125,9 @@
115
125
  const EMBED_MESSAGE_TYPE = Object.freeze({
116
126
  HOST_READY: "mm:intake:host-ready",
117
127
  CHILD_READY: "mm:intake:child-ready",
128
+ // Host asks the embedded chat to put the caret in its composer. Kept
129
+ // separate from HOST_READY so signing-card handshakes never steal focus.
130
+ FOCUS_COMPOSER: "mm:intake:focus-composer",
118
131
  SIGNING_REQUESTED: "mm:intake:signing-requested",
119
132
  SIGNING_RECORDED: "mm:intake:signing-recorded",
120
133
  // Chat asks the host page for a signed-in token; the host answers with
@@ -210,10 +223,10 @@
210
223
  "circle-check": '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
211
224
  "chevron-down": '<path d="m6 9 6 6 6-6"/>'
212
225
  };
213
- const BUTTON_TEXT_US = "data:image/png;base64,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";
214
226
  const FULL_PAGE_PANEL_QUERY = "(max-width:600px),(max-height:500px)";
215
227
  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>`;
216
228
  const OPEN_CLOSE_ICON = lucideIcon("x", "mm-icon mm-icon-close");
229
+ const PROMPT_CLOSE_ICON = lucideIcon("x", "mm-prompt-close-icon", 2.5);
217
230
  const WIDGET_STYLES = [
218
231
  ':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}',
219
232
  "*,*::before,*::after{box-sizing:border-box}",
@@ -222,6 +235,8 @@
222
235
  "@keyframes mm-close-in{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}",
223
236
  "@keyframes mm-panel-in{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}",
224
237
  "@keyframes mm-panel-out{from{opacity:1;transform:none}to{opacity:0;transform:translateY(10px) scale(.98)}}",
238
+ "@keyframes mm-prompt-backdrop-in{from{opacity:0}to{opacity:1}}",
239
+ "@keyframes mm-prompt-card-in{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}",
225
240
  "@keyframes mm-dot{0%,100%{opacity:.4;transform:scale(1)}50%{opacity:1;transform:scale(1.2)}}",
226
241
  // Closed: LivePerson TEXT US sticky under the chat layer. Open: swap for a
227
242
  // blue X disc above the chat so there is always a clear close control.
@@ -254,15 +269,31 @@
254
269
  ".mm-dot{width:8px;height:8px;border-radius:999px;background:var(--mm-muted);animation:mm-dot 1.2s ease-in-out infinite}",
255
270
  ".mm-dot:nth-child(2){animation-delay:.15s}",
256
271
  ".mm-dot:nth-child(3){animation-delay:.3s}",
272
+ ".mm-prompt-backdrop{position:fixed;inset:0;z-index:2147483002;display:grid;place-items:center;padding:16px;overscroll-behavior:contain;touch-action:none;background:rgba(0,0,0,.64);animation:mm-prompt-backdrop-in .25s cubic-bezier(.23,1,.32,1) both;font-family:var(--mm-font)}",
273
+ ".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}",
274
+ ".mm-prompt-image{display:block;width:100%;height:100%;object-fit:contain;pointer-events:none}",
275
+ ".mm-prompt-open,.mm-prompt-close{position:absolute;border:0;outline:none;background:transparent;cursor:pointer}",
276
+ ".mm-prompt-open{inset:0;border-radius:24px}",
277
+ ".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)}",
278
+ '.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}',
279
+ ".mm-prompt-close-icon{position:relative;display:block;width:16px;height:16px;pointer-events:none}",
280
+ ".mm-prompt-close:hover::before{background:#252525}",
281
+ ".mm-prompt-open:focus-visible{outline:3px solid var(--mm-yellow);outline-offset:-8px}",
282
+ ".mm-prompt-close:focus-visible{outline:none}",
283
+ ".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)}",
257
284
  "[hidden]{display:none!important}",
258
285
  `@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))}}`,
259
- "@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-dot{animation:none}}"
286
+ "@media(forced-colors:active){.mm-prompt-close:focus-visible{outline:2px solid ButtonText;outline-offset:-9px}}",
287
+ "@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}}"
260
288
  ].join("");
261
- const WIDGET_MARKUP = [
289
+ const widgetMarkup = (launcherImageUrl, promptImageUrl) => [
262
290
  `<style>${WIDGET_STYLES}</style>`,
263
- `<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="147" decoding="async" />${OPEN_CLOSE_ICON}</button>`,
291
+ `<button class="mm-launcher" type="button" aria-label="Open intake chat" aria-expanded="false" draggable="false"><img class="mm-text-us" src="${launcherImageUrl}" alt="" width="38" height="147" decoding="async" />${OPEN_CLOSE_ICON}</button>`,
264
292
  '<section class="mm-chat" role="dialog" aria-label="Morgan and Morgan intake chat" inert hidden>',
265
293
  '<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>',
294
+ "</section>",
295
+ '<section class="mm-prompt-backdrop" role="dialog" aria-modal="true" aria-label="Start your free consultation" inert hidden>',
296
+ `<div class="mm-prompt-card"><img class="mm-prompt-image" src="${promptImageUrl}" alt="Our team is available 24/7. Chat with a real person. Click to start your free consultation." width="632" height="501" decoding="async" /><button class="mm-prompt-open" type="button" aria-label="Message us about a free consultation"></button><button class="mm-prompt-close" type="button" aria-label="Dismiss consultation prompt">${PROMPT_CLOSE_ICON}</button></div>`,
266
297
  "</section>"
267
298
  ].join("");
268
299
  const requireElement = (shadow, selector) => {
@@ -272,16 +303,23 @@
272
303
  }
273
304
  return element;
274
305
  };
275
- const renderWidgetShell = (shadow) => {
276
- shadow.innerHTML = WIDGET_MARKUP;
306
+ const renderWidgetShell = (shadow, launcherImageUrl, promptImageUrl) => {
307
+ shadow.innerHTML = widgetMarkup(launcherImageUrl, promptImageUrl);
277
308
  return {
278
309
  chatDialog: requireElement(shadow, ".mm-chat"),
279
310
  chatFrame: requireElement(shadow, ".mm-chat-frame"),
280
311
  chatLoading: requireElement(shadow, ".mm-loading"),
281
- launcher: requireElement(shadow, ".mm-launcher")
312
+ launcher: requireElement(shadow, ".mm-launcher"),
313
+ promptBackdrop: requireElement(shadow, ".mm-prompt-backdrop"),
314
+ promptClose: requireElement(shadow, ".mm-prompt-close"),
315
+ promptOpen: requireElement(shadow, ".mm-prompt-open")
282
316
  };
283
317
  };
284
318
  const PANEL_ANIMATION_MS = 180;
319
+ const PROMPT_DELAY_MS = 6e4;
320
+ const PROMPT_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
321
+ const PROMPT_COOLDOWN_KEY = "mm-intake-widget-prompt-dismissed-at";
322
+ const PROMPT_SESSION_KEY = "mm-intake-widget-prompt-dismissed";
285
323
  const CHAT_CHROME_COLOR = "#e8eef2";
286
324
  const KEYBOARD_MIN_SHRINK_PX = 100;
287
325
  const CHAT_READY_FALLBACK_MS = 4e3;
@@ -291,12 +329,58 @@
291
329
  globalThis.history.replaceState(globalThis.history.state, "", cleanedReturnUrl);
292
330
  }
293
331
  };
332
+ const hasPromptCooldown = () => {
333
+ try {
334
+ if (globalThis.sessionStorage.getItem(PROMPT_SESSION_KEY) === "true") {
335
+ return true;
336
+ }
337
+ } catch {
338
+ }
339
+ try {
340
+ const dismissedAt = Number(globalThis.localStorage.getItem(PROMPT_COOLDOWN_KEY));
341
+ return Number.isFinite(dismissedAt) && dismissedAt > 0 && Date.now() - dismissedAt < PROMPT_COOLDOWN_MS;
342
+ } catch {
343
+ return false;
344
+ }
345
+ };
346
+ const rememberPromptDismissal = () => {
347
+ try {
348
+ globalThis.sessionStorage.setItem(PROMPT_SESSION_KEY, "true");
349
+ } catch {
350
+ }
351
+ try {
352
+ globalThis.localStorage.setItem(PROMPT_COOLDOWN_KEY, String(Date.now()));
353
+ } catch {
354
+ }
355
+ };
356
+ const playPromptSound = async () => {
357
+ try {
358
+ const context = new AudioContext();
359
+ const oscillator = context.createOscillator();
360
+ const gain = context.createGain();
361
+ oscillator.frequency.setValueAtTime(660, context.currentTime);
362
+ oscillator.frequency.exponentialRampToValueAtTime(880, context.currentTime + 0.16);
363
+ gain.gain.setValueAtTime(0.08, context.currentTime);
364
+ gain.gain.exponentialRampToValueAtTime(1e-3, context.currentTime + 0.2);
365
+ oscillator.connect(gain);
366
+ gain.connect(context.destination);
367
+ oscillator.start();
368
+ oscillator.stop(context.currentTime + 0.2);
369
+ oscillator.addEventListener("ended", () => void context.close());
370
+ await context.resume();
371
+ } catch {
372
+ }
373
+ };
294
374
  const mountIntakeWidget = (config, onDestroy) => {
295
375
  var _a;
296
376
  const mount = document.createElement("div");
297
377
  mount.dataset.mmIntakeWidget = "";
298
378
  const shadow = mount.attachShadow({ mode: "open" });
299
- const elements = renderWidgetShell(shadow);
379
+ const assetUrl = (fileName) => {
380
+ var _a2;
381
+ return new URL(fileName, (_a2 = config.assetBaseUrl) != null ? _a2 : `${config.chatOrigin}/intake-widget/`).href;
382
+ };
383
+ const elements = renderWidgetShell(shadow, assetUrl("button-text-us.png"), assetUrl("consultation-prompt.webp"));
300
384
  document.body.append(mount);
301
385
  if (typeof mount.showPopover === "function") {
302
386
  mount.setAttribute("popover", "manual");
@@ -310,6 +394,8 @@
310
394
  let chatHasLoaded = false;
311
395
  let chatCloseTimer;
312
396
  let chatReadyTimer;
397
+ let promptTimer;
398
+ let promptReturnFocus = null;
313
399
  let isKeyboardOpen = false;
314
400
  let hasReleasedKeyboardEarly = false;
315
401
  const syncLauncherLabel = () => {
@@ -343,6 +429,9 @@
343
429
  })
344
430
  );
345
431
  };
432
+ const focusChatComposer = () => {
433
+ postToChat(createEmbedProtocolMessage(EMBED_MESSAGE_TYPE.FOCUS_COMPOSER));
434
+ };
346
435
  const answerAuthTokenRequest = async () => {
347
436
  var _a2;
348
437
  let token;
@@ -365,6 +454,31 @@
365
454
  chatReadyTimer = void 0;
366
455
  elements.chatLoading.hidden = true;
367
456
  };
457
+ const dismissPrompt = (returnFocus = false) => {
458
+ globalThis.clearTimeout(promptTimer);
459
+ promptTimer = void 0;
460
+ const wasVisible = !elements.promptBackdrop.hidden;
461
+ elements.promptBackdrop.hidden = true;
462
+ elements.promptBackdrop.setAttribute("inert", "");
463
+ rememberPromptDismissal();
464
+ if (returnFocus && wasVisible) {
465
+ const focusTarget = (promptReturnFocus == null ? void 0 : promptReturnFocus.isConnected) === true ? promptReturnFocus : elements.launcher;
466
+ promptReturnFocus = null;
467
+ focusTarget.focus();
468
+ }
469
+ };
470
+ const showPrompt = () => {
471
+ globalThis.clearTimeout(promptTimer);
472
+ promptTimer = void 0;
473
+ if (hasPromptCooldown() || elements.chatDialog.dataset.state === "open") {
474
+ return;
475
+ }
476
+ promptReturnFocus = document.activeElement instanceof HTMLElement && document.activeElement !== mount ? document.activeElement : null;
477
+ elements.promptBackdrop.hidden = false;
478
+ elements.promptBackdrop.removeAttribute("inert");
479
+ elements.promptClose.focus();
480
+ void playPromptSound();
481
+ };
368
482
  const syncViewport = () => {
369
483
  const viewport = globalThis.visualViewport;
370
484
  if (!viewport || viewport.height === 0) {
@@ -483,6 +597,7 @@
483
597
  stopViewportTracking();
484
598
  };
485
599
  const openChat = () => {
600
+ dismissPrompt();
486
601
  globalThis.clearTimeout(chatCloseTimer);
487
602
  chatCloseTimer = void 0;
488
603
  elements.chatDialog.hidden = false;
@@ -496,6 +611,7 @@
496
611
  writeOpenState(true);
497
612
  if (chatHasLoaded) {
498
613
  postHostReady();
614
+ focusChatComposer();
499
615
  }
500
616
  };
501
617
  const closeChat = () => {
@@ -531,6 +647,9 @@
531
647
  if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.CHILD_READY)) {
532
648
  revealChat();
533
649
  postHostReady();
650
+ if (elements.chatDialog.dataset.state === "open") {
651
+ focusChatComposer();
652
+ }
534
653
  return;
535
654
  }
536
655
  if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.AUTH_TOKEN_REQUEST)) {
@@ -558,9 +677,24 @@
558
677
  }
559
678
  };
560
679
  const handleKeydown = (event) => {
680
+ if (event.key === "Tab" && !elements.promptBackdrop.hidden) {
681
+ const { activeElement } = shadow;
682
+ if (!event.shiftKey && activeElement === elements.promptClose) {
683
+ event.preventDefault();
684
+ elements.promptOpen.focus();
685
+ } else if (event.shiftKey && activeElement === elements.promptOpen) {
686
+ event.preventDefault();
687
+ elements.promptClose.focus();
688
+ }
689
+ return;
690
+ }
561
691
  if (event.key !== "Escape") {
562
692
  return;
563
693
  }
694
+ if (!elements.promptBackdrop.hidden) {
695
+ dismissPrompt(true);
696
+ return;
697
+ }
564
698
  if (elements.chatDialog.dataset.state === "open") {
565
699
  closeChat();
566
700
  }
@@ -569,6 +703,7 @@
569
703
  stopViewportTracking();
570
704
  globalThis.clearTimeout(chatCloseTimer);
571
705
  globalThis.clearTimeout(chatReadyTimer);
706
+ globalThis.clearTimeout(promptTimer);
572
707
  globalThis.removeEventListener("message", handleMessage);
573
708
  document.removeEventListener("keydown", handleKeydown);
574
709
  mount.remove();
@@ -581,6 +716,13 @@
581
716
  openChat();
582
717
  }
583
718
  });
719
+ elements.promptOpen.addEventListener("click", openChat);
720
+ elements.promptClose.addEventListener("click", () => dismissPrompt(true));
721
+ elements.promptBackdrop.addEventListener("click", (event) => {
722
+ if (event.target === elements.promptBackdrop) {
723
+ dismissPrompt(true);
724
+ }
725
+ });
584
726
  elements.chatDialog.addEventListener("animationend", (event) => {
585
727
  if (event.target === elements.chatDialog) {
586
728
  finishChatClose();
@@ -597,11 +739,14 @@
597
739
  syncLauncherLabel();
598
740
  if (returnedFromSigning || readOpenState()) {
599
741
  openChat();
742
+ } else if (!hasPromptCooldown()) {
743
+ promptTimer = globalThis.setTimeout(showPrompt, PROMPT_DELAY_MS);
600
744
  }
601
745
  return Object.freeze({
602
746
  close: closeChat,
603
747
  destroy,
604
748
  open: openChat,
749
+ showPrompt,
605
750
  version: EMBED_PROTOCOL_VERSION
606
751
  });
607
752
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morgan-and-morgan/intake-agent",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Embeddable chat widget loader.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
@@ -23,6 +23,7 @@
23
23
  "build": "pnpm run build:bundle",
24
24
  "build:bundle": "node scripts/generate-icons.mjs && vite build",
25
25
  "generate:icons": "node scripts/generate-icons.mjs",
26
+ "test": "node --test src/release-config.test.mjs",
26
27
  "typecheck": "tsc --noEmit",
27
28
  "lint": "eslint \"src/**/*.ts\" --quiet",
28
29
  "lint:fix": "eslint \"src/**/*.ts\" --quiet --fix",