@morgan-and-morgan/intake-agent 1.6.0 → 1.8.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
@@ -34,3 +34,9 @@ major. Every release is tagged `intake-agent-vx.y.z`.
34
34
  | --- | --- | --- |
35
35
  | `data-chat-url` | Release environment URL | Chat iframe target |
36
36
  | `data-auto-open` | `false` | Open the chat immediately after mount |
37
+
38
+ The consultation modal reads `window.drupalSettings.mxPopup`, falling back to
39
+ `window.mxChatbotSettings.mxPopup` when the Drupal field is absent. Only the
40
+ boolean `false` suppresses the modal, including calls to `showPrompt()`.
41
+ Missing settings preserve the usual display rules. Settings are read when the
42
+ modal is about to appear; the launcher and chat remain available.
@@ -328,6 +328,10 @@
328
328
  const PROMPT_COOLDOWN_KEY = "mm-intake-widget-prompt-dismissed-at";
329
329
  const PROMPT_SESSION_KEY = "mm-intake-widget-prompt-dismissed";
330
330
  const CHAT_CHROME_COLOR = "#e8eef2";
331
+ const matchMediaQuery = (query) => {
332
+ var _a;
333
+ return (_a = globalThis.matchMedia) == null ? void 0 : _a.call(globalThis, query);
334
+ };
331
335
  const KEYBOARD_MIN_SHRINK_PX = 100;
332
336
  const CHAT_READY_FALLBACK_MS = 4e3;
333
337
  const cleanSigningReturnUrl = () => {
@@ -360,32 +364,13 @@
360
364
  } catch {
361
365
  }
362
366
  };
363
- const playPromptSound = async () => {
364
- try {
365
- const context = new AudioContext();
366
- const oscillator = context.createOscillator();
367
- const gain = context.createGain();
368
- oscillator.frequency.setValueAtTime(660, context.currentTime);
369
- oscillator.frequency.exponentialRampToValueAtTime(880, context.currentTime + 0.16);
370
- gain.gain.setValueAtTime(0.08, context.currentTime);
371
- gain.gain.exponentialRampToValueAtTime(1e-3, context.currentTime + 0.2);
372
- oscillator.connect(gain);
373
- gain.connect(context.destination);
374
- oscillator.start();
375
- oscillator.stop(context.currentTime + 0.2);
376
- oscillator.addEventListener("ended", () => void context.close());
377
- await context.resume();
378
- } catch {
379
- }
380
- };
381
367
  const mountIntakeWidget = (config, onDestroy) => {
382
- var _a;
383
368
  const mount = document.createElement("div");
384
369
  mount.dataset.mmIntakeWidget = "";
385
370
  const shadow = mount.attachShadow({ mode: "open" });
386
371
  const assetUrl = (fileName) => {
387
- var _a2;
388
- return new URL(fileName, (_a2 = config.assetBaseUrl) != null ? _a2 : `${config.chatOrigin}/intake-widget/`).href;
372
+ var _a;
373
+ return new URL(fileName, (_a = config.assetBaseUrl) != null ? _a : `${config.chatOrigin}/intake-widget/`).href;
389
374
  };
390
375
  const elements = renderWidgetShell(shadow, assetUrl("button-text-us.png"), assetUrl("consultation-prompt.webp"));
391
376
  document.body.append(mount);
@@ -411,8 +396,8 @@
411
396
  elements.launcher.setAttribute("aria-label", isOpen ? "Close intake chat" : "Open intake chat");
412
397
  };
413
398
  const postToChat = (message) => {
414
- var _a2;
415
- (_a2 = elements.chatFrame.contentWindow) == null ? void 0 : _a2.postMessage(message, config.chatOrigin);
399
+ var _a;
400
+ (_a = elements.chatFrame.contentWindow) == null ? void 0 : _a.postMessage(message, config.chatOrigin);
416
401
  };
417
402
  const postHostReady = () => {
418
403
  const currentUrl = globalThis.location.href;
@@ -440,10 +425,10 @@
440
425
  postToChat(createEmbedProtocolMessage(EMBED_MESSAGE_TYPE.FOCUS_COMPOSER));
441
426
  };
442
427
  const answerAuthTokenRequest = async () => {
443
- var _a2;
428
+ var _a;
444
429
  let token;
445
430
  try {
446
- token = await ((_a2 = config.getAuthToken) == null ? void 0 : _a2.call(config));
431
+ token = await ((_a = config.getAuthToken) == null ? void 0 : _a.call(config));
447
432
  } catch {
448
433
  token = void 0;
449
434
  }
@@ -464,7 +449,7 @@
464
449
  const dismissPrompt = (returnFocus = false) => {
465
450
  globalThis.clearTimeout(promptTimer);
466
451
  promptTimer = void 0;
467
- const wasVisible = !elements.promptBackdrop.hidden;
452
+ const wasVisible = elements.promptBackdrop.hidden === false;
468
453
  elements.promptBackdrop.hidden = true;
469
454
  elements.promptBackdrop.setAttribute("inert", "");
470
455
  rememberPromptDismissal();
@@ -475,16 +460,18 @@
475
460
  }
476
461
  };
477
462
  const showPrompt = () => {
463
+ var _a, _b, _c;
478
464
  globalThis.clearTimeout(promptTimer);
479
465
  promptTimer = void 0;
480
- if (hasPromptCooldown() || elements.chatDialog.dataset.state === "open") {
466
+ const host = globalThis;
467
+ const mxPopup = (_c = (_a = host.drupalSettings) == null ? void 0 : _a.mxPopup) != null ? _c : (_b = host.mxChatbotSettings) == null ? void 0 : _b.mxPopup;
468
+ if (mxPopup === false || hasPromptCooldown() || elements.chatDialog.dataset.state === "open") {
481
469
  return;
482
470
  }
483
471
  promptReturnFocus = document.activeElement instanceof HTMLElement && document.activeElement !== mount ? document.activeElement : null;
484
472
  elements.promptBackdrop.hidden = false;
485
473
  elements.promptBackdrop.removeAttribute("inert");
486
474
  elements.promptClose.focus();
487
- void playPromptSound();
488
475
  };
489
476
  const syncViewport = () => {
490
477
  const viewport = globalThis.visualViewport;
@@ -511,7 +498,7 @@
511
498
  hasReleasedKeyboardEarly = true;
512
499
  setKeyboardOpen(false);
513
500
  };
514
- const fullPagePanelQuery = (_a = globalThis.matchMedia) == null ? void 0 : _a.call(globalThis, FULL_PAGE_PANEL_QUERY);
501
+ const fullPagePanelQuery = matchMediaQuery(FULL_PAGE_PANEL_QUERY);
515
502
  let themeColorBackup = null;
516
503
  let createdThemeColor = null;
517
504
  const hostRoots = [document.documentElement, document.body];
@@ -539,7 +526,7 @@
539
526
  }
540
527
  };
541
528
  const restoreHostChrome = () => {
542
- var _a2, _b;
529
+ var _a, _b;
543
530
  if (themeColorBackup === null) {
544
531
  return;
545
532
  }
@@ -550,7 +537,7 @@
550
537
  createdThemeColor = null;
551
538
  themeColorBackup = null;
552
539
  for (const [index, root] of hostRoots.entries()) {
553
- root.style.backgroundColor = (_a2 = hostBackgroundColorBackup == null ? void 0 : hostBackgroundColorBackup[index]) != null ? _a2 : "";
540
+ root.style.backgroundColor = (_a = hostBackgroundColorBackup == null ? void 0 : hostBackgroundColorBackup[index]) != null ? _a : "";
554
541
  root.style.overflow = (_b = hostOverflowBackup == null ? void 0 : hostOverflowBackup[index]) != null ? _b : "";
555
542
  }
556
543
  hostBackgroundColorBackup = null;
@@ -560,7 +547,7 @@
560
547
  if (elements.chatDialog.dataset.state !== "open") {
561
548
  return;
562
549
  }
563
- if (fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.matches) {
550
+ if ((fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.matches) === true) {
564
551
  borrowHostChrome();
565
552
  } else {
566
553
  restoreHostChrome();
@@ -576,16 +563,16 @@
576
563
  syncHostChrome();
577
564
  }
578
565
  const startViewportTracking = () => {
579
- var _a2, _b;
580
- (_a2 = globalThis.visualViewport) == null ? void 0 : _a2.addEventListener("resize", syncViewport);
566
+ var _a, _b;
567
+ (_a = globalThis.visualViewport) == null ? void 0 : _a.addEventListener("resize", syncViewport);
581
568
  (_b = globalThis.visualViewport) == null ? void 0 : _b.addEventListener("scroll", syncViewport);
582
569
  fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.addEventListener("change", syncHostChrome);
583
570
  syncViewport();
584
571
  syncHostChrome();
585
572
  };
586
573
  const stopViewportTracking = () => {
587
- var _a2, _b;
588
- (_a2 = globalThis.visualViewport) == null ? void 0 : _a2.removeEventListener("resize", syncViewport);
574
+ var _a, _b;
575
+ (_a = globalThis.visualViewport) == null ? void 0 : _a.removeEventListener("resize", syncViewport);
589
576
  (_b = globalThis.visualViewport) == null ? void 0 : _b.removeEventListener("scroll", syncViewport);
590
577
  fullPagePanelQuery == null ? void 0 : fullPagePanelQuery.removeEventListener("change", syncHostChrome);
591
578
  setKeyboardOpen(false);
@@ -622,7 +609,7 @@
622
609
  }
623
610
  };
624
611
  const closeChat = () => {
625
- var _a2;
612
+ var _a;
626
613
  elements.launcher.focus();
627
614
  writeOpenState(false);
628
615
  const wasOpen = elements.chatDialog.dataset.state === "open";
@@ -635,7 +622,7 @@
635
622
  if (!wasOpen) {
636
623
  return;
637
624
  }
638
- if ((_a2 = globalThis.matchMedia) == null ? void 0 : _a2.call(globalThis, "(prefers-reduced-motion: reduce)").matches) {
625
+ if (((_a = matchMediaQuery("(prefers-reduced-motion: reduce)")) == null ? void 0 : _a.matches) === true) {
639
626
  finishChatClose();
640
627
  return;
641
628
  }
@@ -688,7 +675,7 @@
688
675
  }
689
676
  };
690
677
  const handleKeydown = (event) => {
691
- if (event.key === "Tab" && !elements.promptBackdrop.hidden) {
678
+ if (event.key === "Tab" && elements.promptBackdrop.hidden === false) {
692
679
  const { activeElement } = shadow;
693
680
  if (!event.shiftKey && activeElement === elements.promptClose) {
694
681
  event.preventDefault();
@@ -702,7 +689,7 @@
702
689
  if (event.key !== "Escape") {
703
690
  return;
704
691
  }
705
- if (!elements.promptBackdrop.hidden) {
692
+ if (elements.promptBackdrop.hidden === false) {
706
693
  dismissPrompt(true);
707
694
  return;
708
695
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morgan-and-morgan/intake-agent",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Embeddable chat widget loader.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
@@ -24,15 +24,14 @@
24
24
  "build:bundle": "node scripts/generate-icons.mjs && vite build",
25
25
  "generate:icons": "node scripts/generate-icons.mjs",
26
26
  "test": "node --test 'src/*.test.mjs'",
27
- "typecheck": "tsc --noEmit",
28
- "lint": "eslint \"src/**/*.ts\" --quiet",
29
- "lint:fix": "eslint \"src/**/*.ts\" --quiet --fix",
27
+ "typecheck": "tsgo --noEmit",
30
28
  "prepublishOnly": "pnpm run build:bundle"
31
29
  },
32
30
  "devDependencies": {
33
- "@mmcp/eslint-config": "workspace:*",
34
31
  "@mmcp/tsconfig": "workspace:*",
35
- "eslint": "^9.39.1",
32
+ "@types/jest": "catalog:",
33
+ "@types/node": "catalog:",
34
+ "@typescript/native-preview": "catalog:",
36
35
  "lucide-react-native": "^0.562.0",
37
36
  "typescript": "~5.9.3",
38
37
  "vite": "^7.3.6"