@morgan-and-morgan/intake-agent 1.0.0-alpha.1 → 1.0.0-alpha.3

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,99 +117,58 @@
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:translateX(8px) scale(.94)}to{opacity:1;transform:none}}",
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.
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
+ // Same asset as forthepeople.com (button-text-us-white-bg), already rotated
136
+ // 90deg CW like GTM. Placement matches #messaging_gbm: top 42%, ~38px thick,
137
+ // no translateY(-50%). right:10px keeps a small inset from the viewport edge.
148
138
  // Against the host page the near-max z-index is only the fallback for
149
139
  // browsers without the Popover API — everywhere else the mount rides the top
150
140
  // layer (widget.ts) and outranks any host z-index.
151
- ".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}",
141
+ ".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:none;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}",
152
142
  ".mm-launcher *{user-select:none;-webkit-user-select:none;-webkit-user-drag:none}",
153
- ".mm-launcher:hover{background:var(--mm-yellow-hover);box-shadow:0 12px 32px rgba(17,17,17,.28);transform:translateY(-1px)}",
154
- ".mm-launcher:active{background:var(--mm-yellow-pressed);transform:translateY(0)}",
143
+ ".mm-launcher:hover{transform:translateX(-2px);filter:drop-shadow(0 4px 10px rgba(17,17,17,.18))}",
144
+ ".mm-launcher:active{transform:none;filter:none}",
155
145
  ".mm-launcher:focus-visible{outline:3px solid var(--mm-blue);outline-offset:3px}",
156
- ".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)}",
157
- '.mm-badge::after{content:"";position:absolute;inset:-2px;border-radius:999px;background:var(--mm-blue);animation:mm-ping 2.4s ease-out infinite}',
158
- ".mm-icon{position:absolute;top:50%;left:50%;display:block;width:28px;height:28px;pointer-events:none;transform:translate(-50%,-50%)}",
159
- ".mm-icon-close{display:none}",
160
- '.mm-launcher[aria-expanded="true"] .mm-icon-chat{display:none}',
146
+ ".mm-text-us{display:block;width:38px;height:auto;pointer-events:none}",
147
+ ".mm-icon{position:absolute;top:50%;left:50%;display:none;width:22px;height:22px;pointer-events:none;transform:translate(-50%,-50%)}",
148
+ // Open on desktop: X sits on the chat's top-right corner (chat is bottom:24,
149
+ // height min(640px, 100vh - 48px)).
150
+ '.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}',
151
+ '.mm-launcher[aria-expanded="true"]:hover,.mm-launcher[aria-expanded="true"]:active{transform:none;filter:none;background:var(--mm-blue-hover)}',
152
+ '.mm-launcher[aria-expanded="true"] .mm-text-us{display:none}',
161
153
  '.mm-launcher[aria-expanded="true"] .mm-icon-close{display:block}',
162
- // The panel wears the chat's header/trust-line tint, not its conversation
163
- // tint. Measured on iOS 26: while the panel is full-page, Safari takes the
164
- // colour of its own status-bar and URL-bar bands straight off this background
165
- // — ahead of the host page's `theme-color` and root background, which it
166
- // ignores outright once the chat frame has committed a navigation. So this is
167
- // the lever that decides what the bands look like, and the bands sit right
168
- // against the chat's header and trust line.
169
- // Two flat halves rather than one colour, because the two bands are sampled
170
- // independently: the top one always sits against the chat header, while the
171
- // bottom one sits against the trust line or, with a keyboard up, the composer.
172
- ".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)}",
173
- // Keyboard up, the chat drops its trust line and the composer becomes the
174
- // bottom-most surface, so the bottom band has to follow the composer. Only
175
- // the bottom: the header is still up there against the top one.
154
+ ".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)}",
176
155
  '.mm-chat[data-keyboard="open"]{--mm-panel-bottom:var(--mm-surface-blue)}',
177
156
  '.mm-chat[data-state="closing"]{pointer-events:none;animation-name:mm-panel-out}',
178
157
  '.mm-chat[data-state="closed"]{visibility:hidden;animation-name:none}',
179
158
  ".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%)}",
180
- // A chat tone, never white: the frame paints this in the gap between the
181
- // document's load event and the app's first frame, and on a phone that gap is
182
- // the whole screen.
183
159
  ".mm-frame{display:block;width:100%;height:100%;border:0;background:var(--mm-chrome)}",
184
160
  ".mm-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:5px;background:var(--mm-chrome)}",
185
161
  ".mm-dot{width:8px;height:8px;border-radius:999px;background:var(--mm-muted);animation:mm-dot 1.2s ease-in-out infinite}",
186
162
  ".mm-dot:nth-child(2){animation-delay:.15s}",
187
163
  ".mm-dot:nth-child(3){animation-delay:.3s}",
188
164
  "[hidden]{display:none!important}",
189
- // The close affordance rides the same tracked viewport as the panel: iOS
190
- // Safari pans the page when the keyboard opens, and a launcher pinned to the
191
- // layout viewport's top would be panned clean off the screen with it.
192
- //
193
- // `min-height:0` on the panel so a short landscape viewport shrinks it all the
194
- // way down instead of overflowing the screen and clipping the chat's own
195
- // rotate-your-phone overlay.
196
- //
197
- // 16px from the corner is right for a normal host site, which has nothing of
198
- // its own down there. A host that mounts its own bottom chrome — the client
199
- // portal and its tab bar — sets `--mm-launcher-bottom` on any ancestor of the
200
- // mount (custom properties reach into the shadow tree) to lift the launcher
201
- // clear of it. Only the closed launcher: open, it moves to the top corner and
202
- // tracks the viewport instead.
203
- // `left:0;right:0` rather than `width:100vw`: `100vw` counts the classic
204
- // scrollbar the host page still has behind us, so a right-anchored panel that
205
- // wide starts a scrollbar's width off the left edge and clips its own header.
206
- //
207
- // The shadow fills the strip below the panel. Safari's bottom bar is
208
- // translucent once it collapses — scrolled down, or any time the keyboard is
209
- // up — and `visualViewport.height` stops short of it, so the host page shows
210
- // through underneath the chat. `lvh - svh` is exactly that bar's height, and
211
- // it is 0 wherever the browser has no collapsing bar, so this costs nothing
212
- // there. A shadow rather than extra height: the trust line and composer must
213
- // stay above the bar, not slide under it.
214
- `@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))}}`,
215
- "@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-badge::after,.mm-dot{animation:none}}"
165
+ `@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))}}`,
166
+ "@media(prefers-reduced-motion:reduce){.mm-launcher,.mm-chat{animation:none;transition:none}.mm-dot{animation:none}}"
216
167
  ].join("");
217
168
  const WIDGET_MARKUP = [
218
169
  `<style>${WIDGET_STYLES}</style>`,
219
- `<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>`,
170
+ `<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>`,
220
171
  '<section class="mm-chat" role="dialog" aria-label="Morgan and Morgan intake chat" inert hidden>',
221
- // Dots rather than a sentence: the panel is up for a second or two and a line
222
- // of copy reads like an error the visitor has to act on. The label carries the
223
- // same information for a screen reader.
224
172
  '<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>',
225
173
  "</section>"
226
174
  ].join("");
@@ -237,20 +185,13 @@
237
185
  chatDialog: requireElement(shadow, ".mm-chat"),
238
186
  chatFrame: requireElement(shadow, ".mm-chat-frame"),
239
187
  chatLoading: requireElement(shadow, ".mm-loading"),
240
- launcher: requireElement(shadow, ".mm-launcher"),
241
- unreadBadge: requireElement(shadow, ".mm-badge")
188
+ launcher: requireElement(shadow, ".mm-launcher")
242
189
  };
243
190
  };
244
191
  const PANEL_ANIMATION_MS = 180;
245
192
  const CHAT_CHROME_COLOR = "#e8eef2";
246
193
  const KEYBOARD_MIN_SHRINK_PX = 100;
247
194
  const CHAT_READY_FALLBACK_MS = 4e3;
248
- const getLauncherLabel = (isOpen, hasUnread) => {
249
- if (isOpen) {
250
- return "Close intake chat";
251
- }
252
- return hasUnread ? "Open intake chat, new message" : "Open intake chat";
253
- };
254
195
  const cleanSigningReturnUrl = () => {
255
196
  const cleanedReturnUrl = buildSigningReturnUrl();
256
197
  if (cleanedReturnUrl !== null) {
@@ -278,20 +219,10 @@
278
219
  let chatReadyTimer;
279
220
  let isKeyboardOpen = false;
280
221
  let hasReleasedKeyboardEarly = false;
281
- let hasUnread = readUnreadState();
282
- const loadUnreadIndicator = () => {
283
- elements.unreadBadge.hidden = !hasUnread;
284
- syncLauncherLabel();
285
- };
286
- const setHasUnread = (next) => {
287
- hasUnread = next;
288
- writeUnreadState(next);
289
- loadUnreadIndicator();
290
- };
291
222
  const syncLauncherLabel = () => {
292
223
  const isOpen = elements.chatDialog.dataset.state === "open";
293
224
  elements.launcher.setAttribute("aria-expanded", String(isOpen));
294
- elements.launcher.setAttribute("aria-label", getLauncherLabel(isOpen, hasUnread));
225
+ elements.launcher.setAttribute("aria-label", isOpen ? "Close intake chat" : "Open intake chat");
295
226
  };
296
227
  const postToChat = (message) => {
297
228
  var _a2;
@@ -454,7 +385,7 @@
454
385
  elements.chatDialog.dataset.state = "open";
455
386
  elements.chatDialog.removeAttribute("aria-hidden");
456
387
  elements.chatDialog.removeAttribute("inert");
457
- setHasUnread(false);
388
+ syncLauncherLabel();
458
389
  startViewportTracking();
459
390
  ensureChatLoaded();
460
391
  elements.chatFrame.focus();
@@ -511,9 +442,6 @@
511
442
  return;
512
443
  }
513
444
  if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.MESSAGE_RECEIVED)) {
514
- if (elements.chatDialog.dataset.state !== "open") {
515
- setHasUnread(true);
516
- }
517
445
  return;
518
446
  }
519
447
  if (isEmbedProtocolMessage(message, EMBED_MESSAGE_TYPE.SIGNING_REQUESTED)) {
@@ -562,7 +490,7 @@
562
490
  });
563
491
  globalThis.addEventListener("message", handleMessage);
564
492
  document.addEventListener("keydown", handleKeydown);
565
- loadUnreadIndicator();
493
+ syncLauncherLabel();
566
494
  if (completedSigningEnvelopeId !== null || readOpenState()) {
567
495
  openChat();
568
496
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morgan-and-morgan/intake-agent",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "Embeddable chat widget loader.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [