@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.
@@ -12,30 +12,19 @@
12
12
  };
13
13
  };
14
14
  const OPEN_STATE_KEY = "mm-intake-widget-open";
15
- const UNREAD_STATE_KEY = "mm-intake-widget-unread";
16
- const readFlag = (key, storage) => {
15
+ const readOpenState = (storage = sessionStorage) => {
17
16
  try {
18
- return storage.getItem(key) === "true";
17
+ return storage.getItem(OPEN_STATE_KEY) === "true";
19
18
  } catch {
20
19
  return false;
21
20
  }
22
21
  };
23
- const writeFlag = (key, value, storage) => {
22
+ const writeOpenState = (isOpen, storage = sessionStorage) => {
24
23
  try {
25
- storage.setItem(key, String(value));
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, so the
61
- // launcher's unread dot can mean something. Payload-free: the dot is a dot,
62
- // and only the chat knows a message arrived while only the host knows whether
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:translateY(10px) scale(.85)}to{opacity:1;transform:none}}",
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
- // The launcher stacks above the chat panel: it is the only close affordance
147
- // (the panel is chrome-free), so the full-screen mobile panel must not cover it.
148
- ".mm-launcher{position:fixed;right:24px;bottom:24px;z-index:2147483001;display:grid;width:64px;height:64px;place-items:center;border:2px solid var(--mm-white);border-radius:999px;outline:none;background:var(--mm-yellow);color:var(--mm-ink);box-shadow:0 10px 28px rgba(17,17,17,.24);cursor:pointer;user-select:none;-webkit-user-select:none;-webkit-user-drag:none;animation:mm-launcher-in .25s ease-out;transition:background-color .15s ease,transform .15s ease,box-shadow .15s ease}",
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{background:var(--mm-yellow-hover);box-shadow:0 12px 32px rgba(17,17,17,.28);transform:translateY(-1px)}",
151
- ".mm-launcher:active{background:var(--mm-yellow-pressed);transform:translateY(0)}",
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-badge{position:absolute;top:-2px;right:-2px;width:16px;height:16px;border:2px solid var(--mm-white);border-radius:999px;background:var(--mm-blue)}",
154
- '.mm-badge::after{content:"";position:absolute;inset:-2px;border-radius:999px;background:var(--mm-blue);animation:mm-ping 2.4s ease-out infinite}',
155
- ".mm-icon{position:absolute;top:50%;left:50%;display:block;width:28px;height:28px;pointer-events:none;transform:translate(-50%,-50%)}",
156
- ".mm-icon-close{display:none}",
157
- '.mm-launcher[aria-expanded="true"] .mm-icon-chat{display:none}',
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
- // The panel wears the chat's header/trust-line tint, not its conversation
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
- // The close affordance rides the same tracked viewport as the panel: iOS
187
- // Safari pans the page when the keyboard opens, and a launcher pinned to the
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">${CHAT_ICON}${OPEN_CLOSE_ICON}<span class="mm-badge" aria-hidden="true" hidden></span></button>`,
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", getLauncherLabel(isOpen, hasUnread));
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
- setHasUnread(false);
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
- loadUnreadIndicator();
491
+ syncLauncherLabel();
555
492
  if (completedSigningEnvelopeId !== null || readOpenState()) {
556
493
  openChat();
557
494
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morgan-and-morgan/intake-agent",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.1.0",
4
4
  "description": "Embeddable chat widget loader.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [