@mrrocket/sdk 0.16.0 → 0.17.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/CHANGELOG.md +19 -0
- package/README.md +11 -2
- package/dist/api-client.d.ts +7 -1
- package/dist/api-client.js.map +1 -1
- package/dist/browser/mrrocket-flows.js +9 -2
- package/dist/browser/mrrocket-messenger.js +42 -43
- package/dist/browser/mrrocket.js +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/flows-ui.d.ts +1 -1
- package/dist/flows-ui.js +64 -14
- package/dist/flows-ui.js.map +1 -1
- package/dist/flows.d.ts +49 -3
- package/dist/flows.js +86 -7
- package/dist/flows.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/messenger-ui.d.ts +10 -2
- package/dist/messenger-ui.js +57 -46
- package/dist/messenger-ui.js.map +1 -1
- package/dist/react-native/index.d.cts +46 -7
- package/dist/react-native/index.d.ts +46 -7
- package/dist/react-native/index.js +135 -31
- package/dist/react-native/index.js.map +1 -1
- package/dist/styles-css.d.ts +1 -1
- package/dist/styles-css.js +40 -41
- package/dist/styles-css.js.map +1 -1
- package/package.json +1 -1
|
@@ -51,7 +51,7 @@ module.exports = __toCommonJS(native_exports);
|
|
|
51
51
|
var import_react3 = require("react");
|
|
52
52
|
|
|
53
53
|
// src/core.ts
|
|
54
|
-
var SDK_VERSION = "0.
|
|
54
|
+
var SDK_VERSION = "0.17.0";
|
|
55
55
|
var propOf = (person, name) => {
|
|
56
56
|
const want = name.trim().toLowerCase();
|
|
57
57
|
for (const [k, v] of Object.entries(person)) if (k.toLowerCase() === want) return v;
|
|
@@ -242,9 +242,9 @@ var call = async (url, init, signal) => {
|
|
|
242
242
|
};
|
|
243
243
|
var createApi = (c) => {
|
|
244
244
|
const base = `${c.host}/api/sdk`;
|
|
245
|
-
const
|
|
245
|
+
const who2 = { key: c.apiKey, distinctId: c.distinctId, user: c.user, userHash: c.userHash };
|
|
246
246
|
const me = { key: c.apiKey, distinctId: c.distinctId, userHash: c.userHash };
|
|
247
|
-
const post = (path, body, signal) => call(`${base}${path}`, { method: "POST", body: JSON.stringify({ ...
|
|
247
|
+
const post = (path, body, signal) => call(`${base}${path}`, { method: "POST", body: JSON.stringify({ ...who2, ...body }) }, signal);
|
|
248
248
|
return {
|
|
249
249
|
list: (o, signal) => call(`${base}/feedback?${qs({ ...me, board: o.board, sort: o.sort, q: o.q })}`, void 0, signal),
|
|
250
250
|
post: (id, signal) => call(`${base}/feedback/${encodeURIComponent(id)}?${qs(me)}`, void 0, signal),
|
|
@@ -358,6 +358,25 @@ var matchesTrigger = (trigger, event) => {
|
|
|
358
358
|
return t === e || SIGNUP.has(t) && SIGNUP.has(e);
|
|
359
359
|
};
|
|
360
360
|
var startsOnLoad = (trigger) => /^(first (launch|visit|open|session|login|sign ?in|app open)|app (opened|launched)|on load|every visit|always)?$/i.test(trigger.trim());
|
|
361
|
+
var isPageTrigger = (trigger) => trigger.trim().startsWith("/");
|
|
362
|
+
var manual = (trigger) => eventSlug(trigger) === "from_a_checklist";
|
|
363
|
+
var videoEmbed = (url) => {
|
|
364
|
+
const u = (url ?? "").trim();
|
|
365
|
+
if (!/^https?:\/\//i.test(u)) return null;
|
|
366
|
+
let m = u.match(/^https?:\/\/(?:www\.|m\.)?(?:youtube\.com\/(?:watch\?(?:.*&)?v=|embed\/|shorts\/|live\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)([\w-]{6,20})/i);
|
|
367
|
+
if (m) return { kind: "iframe", src: `https://www.youtube-nocookie.com/embed/${m[1]}?rel=0` };
|
|
368
|
+
m = u.match(/^https?:\/\/(?:www\.|player\.)?vimeo\.com\/(?:video\/)?(\d{4,12})/i);
|
|
369
|
+
if (m) return { kind: "iframe", src: `https://player.vimeo.com/video/${m[1]}?dnt=1` };
|
|
370
|
+
m = u.match(/^https?:\/\/(?:www\.)?loom\.com\/(?:share|embed)\/([\w-]{8,64})/i);
|
|
371
|
+
if (m) return { kind: "iframe", src: `https://www.loom.com/embed/${m[1]}` };
|
|
372
|
+
if (/\.(mp4|webm|mov|m4v)(\?|#|$)/i.test(u) || /\/media\/uploads\//.test(u)) return { kind: "file", src: u };
|
|
373
|
+
return null;
|
|
374
|
+
};
|
|
375
|
+
var mediaOf = (step) => {
|
|
376
|
+
const m = step.media;
|
|
377
|
+
if (!m || m.kind !== "image" && m.kind !== "video" || !/^https?:\/\//i.test(m.url ?? "")) return void 0;
|
|
378
|
+
return m.kind === "video" && !videoEmbed(m.url) ? void 0 : m;
|
|
379
|
+
};
|
|
361
380
|
var runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;
|
|
362
381
|
var discounted = (amount, percent) => Math.round(amount * (1 - percent / 100) * 100) / 100;
|
|
363
382
|
var money = (amount, currency) => {
|
|
@@ -405,6 +424,7 @@ var createFlows = (env) => {
|
|
|
405
424
|
const seenEvents = /* @__PURE__ */ new Set();
|
|
406
425
|
const now = () => env.now?.() ?? Date.now();
|
|
407
426
|
let timer = null;
|
|
427
|
+
let returnTo = null;
|
|
408
428
|
const flows = () => config?.onboarding ?? [];
|
|
409
429
|
const flowById = (id) => id ? flows().find((f) => f.id === id) : void 0;
|
|
410
430
|
const prog = (id) => {
|
|
@@ -542,7 +562,14 @@ var createFlows = (env) => {
|
|
|
542
562
|
shown.add(`s:${i.id}`);
|
|
543
563
|
env.track(ONBOARDING_EVENT, { flow: flow.id, step: i.id, kind: "checklist", action: "shown" });
|
|
544
564
|
}
|
|
545
|
-
return {
|
|
565
|
+
return {
|
|
566
|
+
type: "checklist",
|
|
567
|
+
flow,
|
|
568
|
+
items: items.map((s) => {
|
|
569
|
+
const tour = s.startsTour && s.startsTour !== flow.id ? flowById(s.startsTour) : void 0;
|
|
570
|
+
return { step: s, done: p.done.has(s.id), ...tour && nodesOf(tour).length ? { tour } : {} };
|
|
571
|
+
})
|
|
572
|
+
};
|
|
546
573
|
}
|
|
547
574
|
if (!shown.has(`s:${step.id}`)) {
|
|
548
575
|
shown.add(`s:${step.id}`);
|
|
@@ -576,7 +603,28 @@ var createFlows = (env) => {
|
|
|
576
603
|
}
|
|
577
604
|
const ob = onboardingView();
|
|
578
605
|
if (ob) return ob;
|
|
579
|
-
if (active && !holding)
|
|
606
|
+
if (active && !holding) {
|
|
607
|
+
const back = returnTo;
|
|
608
|
+
const ended = active;
|
|
609
|
+
returnTo = null;
|
|
610
|
+
active = null;
|
|
611
|
+
const list = back ? flowById(back.flow) : void 0;
|
|
612
|
+
if (back && list) {
|
|
613
|
+
const item = stepsIn(nodesOf(list)).find((s) => s.id === back.step);
|
|
614
|
+
const p = prog(list.id);
|
|
615
|
+
if (item && !item.event && !progress.get(ended)?.dismissed && !p.done.has(item.id)) {
|
|
616
|
+
markDone(p, item.id);
|
|
617
|
+
record({ flow: list.id, step: item.id, kind: "checklist", action: "completed" });
|
|
618
|
+
}
|
|
619
|
+
active = list.id;
|
|
620
|
+
const again = onboardingView();
|
|
621
|
+
if (again) return again;
|
|
622
|
+
if (!holding) active = null;
|
|
623
|
+
} else if (known) {
|
|
624
|
+
const after = flowById(ended)?.trigger;
|
|
625
|
+
Promise.resolve().then(() => autoStart(after));
|
|
626
|
+
}
|
|
627
|
+
}
|
|
580
628
|
const m = messages.find((x) => !handled.has(x.id));
|
|
581
629
|
return m ? { type: "message", message: m } : null;
|
|
582
630
|
};
|
|
@@ -601,10 +649,15 @@ var createFlows = (env) => {
|
|
|
601
649
|
emit();
|
|
602
650
|
return true;
|
|
603
651
|
};
|
|
604
|
-
const
|
|
652
|
+
const allowed = (f) => f.audience !== "signed_in" || !!env.personId();
|
|
653
|
+
const autoStart = (after) => {
|
|
605
654
|
if (!auto || active || !known) return;
|
|
606
655
|
if (!env.personId() && !env.storage?.()) return;
|
|
607
|
-
const
|
|
656
|
+
const path = env.path?.();
|
|
657
|
+
const same2 = after && !manual(after) ? eventSlug(after) : "";
|
|
658
|
+
const next = flows().find(
|
|
659
|
+
(f) => (isPageTrigger(f.trigger) ? path !== void 0 && pageMatches(f.trigger, path) : startsOnLoad(f.trigger) || !!same2 && eventSlug(f.trigger) === same2) && allowed(f) && nodesOf(f).length && !finished(f)
|
|
660
|
+
);
|
|
608
661
|
if (next) start(next);
|
|
609
662
|
};
|
|
610
663
|
const refresh = () => {
|
|
@@ -614,6 +667,7 @@ var createFlows = (env) => {
|
|
|
614
667
|
seenEvents.clear();
|
|
615
668
|
handled.clear();
|
|
616
669
|
active = null;
|
|
670
|
+
returnTo = null;
|
|
617
671
|
loadedFor = void 0;
|
|
618
672
|
}
|
|
619
673
|
progressFor = pid;
|
|
@@ -652,9 +706,9 @@ var createFlows = (env) => {
|
|
|
652
706
|
};
|
|
653
707
|
const offerAt = (c) => c.round > 1 ? { round: 2 } : c.rule >= 0 ? { rule: c.rule } : {};
|
|
654
708
|
const toOffer = (c) => {
|
|
655
|
-
const
|
|
709
|
+
const who2 = { answer: c.answer, plan: c.options.plan, months: monthsSince(c.options.customerSince, env.now?.()) };
|
|
656
710
|
const rules = c.flow.rules?.[c.reason] ?? [];
|
|
657
|
-
c.rule = rules.findIndex((r) => ruleMatches(r,
|
|
711
|
+
c.rule = rules.findIndex((r) => ruleMatches(r, who2));
|
|
658
712
|
c.offer = c.rule < 0 ? c.flow.offers[c.reason] : rules[c.rule].offer ?? void 0;
|
|
659
713
|
c.round = 1;
|
|
660
714
|
c.screen = c.offer ? "offer" : "confirm";
|
|
@@ -723,6 +777,7 @@ var createFlows = (env) => {
|
|
|
723
777
|
},
|
|
724
778
|
refresh,
|
|
725
779
|
onEvent: (name) => {
|
|
780
|
+
if (name === "$pageview") autoStart();
|
|
726
781
|
if (!name || name.startsWith("$")) return;
|
|
727
782
|
const slug = eventSlug(name);
|
|
728
783
|
const fresh = !!slug && !seenEvents.has(slug);
|
|
@@ -743,12 +798,12 @@ var createFlows = (env) => {
|
|
|
743
798
|
emit();
|
|
744
799
|
} else if (fresh) save();
|
|
745
800
|
if (!auto || !env.personId() && !env.storage?.()) return;
|
|
746
|
-
const next = flows().find((f) => nodesOf(f).length && matchesTrigger(f.trigger, name) && !finished(f));
|
|
801
|
+
const next = flows().find((f) => nodesOf(f).length && !manual(f.trigger) && matchesTrigger(f.trigger, name) && allowed(f) && !finished(f));
|
|
747
802
|
if (next) start(next);
|
|
748
803
|
},
|
|
749
804
|
openCancelFlow,
|
|
750
805
|
startOnboarding: (id) => {
|
|
751
|
-
const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !finished(x));
|
|
806
|
+
const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !manual(x.trigger) && !finished(x));
|
|
752
807
|
if (!f || !nodesOf(f).length) return false;
|
|
753
808
|
const p = prog(f.id);
|
|
754
809
|
p.dismissed = false;
|
|
@@ -844,6 +899,8 @@ var createFlows = (env) => {
|
|
|
844
899
|
env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: "completed" });
|
|
845
900
|
save();
|
|
846
901
|
emit();
|
|
902
|
+
const url = v.step.kind === "modal" ? safeUrl(v.step.url) : void 0;
|
|
903
|
+
if (url) env.openUrl?.(url);
|
|
847
904
|
},
|
|
848
905
|
check: (stepId) => {
|
|
849
906
|
const v = onboardingView();
|
|
@@ -860,9 +917,26 @@ var createFlows = (env) => {
|
|
|
860
917
|
if (!v || v.type !== "step" && v.type !== "checklist") return;
|
|
861
918
|
prog(v.flow.id).dismissed = true;
|
|
862
919
|
env.track(ONBOARDING_EVENT, { flow: v.flow.id, ...v.type === "step" ? { step: v.step.id } : {}, action: "dismissed" });
|
|
863
|
-
active = null;
|
|
920
|
+
active = returnTo && returnTo.flow !== v.flow.id && flowById(returnTo.flow) ? returnTo.flow : null;
|
|
921
|
+
returnTo = null;
|
|
922
|
+
save();
|
|
923
|
+
emit();
|
|
924
|
+
},
|
|
925
|
+
startTour: (stepId) => {
|
|
926
|
+
const v = onboardingView();
|
|
927
|
+
if (v?.type !== "checklist") return false;
|
|
928
|
+
const tour = v.items.find((i) => i.step.id === stepId)?.tour;
|
|
929
|
+
if (!tour) return false;
|
|
930
|
+
const p = prog(tour.id);
|
|
931
|
+
p.done.clear();
|
|
932
|
+
p.at.clear();
|
|
933
|
+
p.dismissed = false;
|
|
934
|
+
returnTo = { flow: v.flow.id, step: stepId };
|
|
935
|
+
active = tour.id;
|
|
936
|
+
env.track(ONBOARDING_EVENT, { flow: tour.id, action: "started", from: v.flow.id });
|
|
864
937
|
save();
|
|
865
938
|
emit();
|
|
939
|
+
return true;
|
|
866
940
|
}
|
|
867
941
|
},
|
|
868
942
|
message: {
|
|
@@ -1474,7 +1548,7 @@ var createClient = (options, deps) => {
|
|
|
1474
1548
|
if (errorsSeen.has(mark)) return;
|
|
1475
1549
|
errorsSeen.add(mark);
|
|
1476
1550
|
errorsSent++;
|
|
1477
|
-
const
|
|
1551
|
+
const who2 = sendId();
|
|
1478
1552
|
errorQueue.push({
|
|
1479
1553
|
...d,
|
|
1480
1554
|
mechanism,
|
|
@@ -1483,7 +1557,7 @@ var createClient = (options, deps) => {
|
|
|
1483
1557
|
ts: now(),
|
|
1484
1558
|
crumbs: crumbs.slice(),
|
|
1485
1559
|
...release ? { release } : {},
|
|
1486
|
-
...
|
|
1560
|
+
...who2 ? { distinctId: who2 } : {},
|
|
1487
1561
|
...session ? { sessionId: session.id } : {}
|
|
1488
1562
|
});
|
|
1489
1563
|
recorder?.mark({ kind: "error", path: currentScreen ?? "/", label: clip2(d.message, 120) });
|
|
@@ -1598,20 +1672,20 @@ var createClient = (options, deps) => {
|
|
|
1598
1672
|
await loadedNow();
|
|
1599
1673
|
if (!apiKey || consent === "off") return { status: "error", reason: !apiKey ? "No public key." : "The consent is off." };
|
|
1600
1674
|
if (!identified) return { status: "not-signed-in" };
|
|
1601
|
-
const
|
|
1602
|
-
const userHash = hashOf(
|
|
1675
|
+
const who2 = identified;
|
|
1676
|
+
const userHash = hashOf(who2);
|
|
1603
1677
|
try {
|
|
1604
1678
|
const permission = await deps.push.permission(o.ask !== false);
|
|
1605
1679
|
if (permission !== "granted") return { status: permission === "denied" ? "denied" : "not-asked" };
|
|
1606
1680
|
const token = await deps.push.token(o.projectId);
|
|
1607
1681
|
if (!token) return { status: "unavailable", reason: "This device has no push token (a simulator, or no EAS project id)." };
|
|
1608
|
-
const status = await post("/api/sdk/push", JSON.stringify({ key: apiKey, distinctId:
|
|
1682
|
+
const status = await post("/api/sdk/push", JSON.stringify({ key: apiKey, distinctId: who2, userHash, platform: "expo", token, app: context }));
|
|
1609
1683
|
if (status < 200 || status >= 300) {
|
|
1610
1684
|
warn(`Push registration was rejected with ${status || "no answer"}. Check the public key and the host.`);
|
|
1611
1685
|
return { status: "error", reason: `MRRocket answered ${status || "nothing"}.` };
|
|
1612
1686
|
}
|
|
1613
1687
|
pushToken = token;
|
|
1614
|
-
pushFor =
|
|
1688
|
+
pushFor = who2;
|
|
1615
1689
|
pushHash = userHash;
|
|
1616
1690
|
listenForOpens();
|
|
1617
1691
|
debug("Registered for push.");
|
|
@@ -2165,6 +2239,22 @@ var MRRocketFlows = ({ flows, paywall, appearance = {} }) => {
|
|
|
2165
2239
|
];
|
|
2166
2240
|
return sheet([top, ...body, error], flows.cancel.close);
|
|
2167
2241
|
}
|
|
2242
|
+
const media = (s) => {
|
|
2243
|
+
const m2 = mediaOf(s);
|
|
2244
|
+
if (!m2) return null;
|
|
2245
|
+
if (m2.kind === "image")
|
|
2246
|
+
return RN.Image ? (0, import_react.createElement)(RN.Image, {
|
|
2247
|
+
key: "media",
|
|
2248
|
+
source: { uri: m2.url },
|
|
2249
|
+
accessibilityLabel: m2.alt,
|
|
2250
|
+
resizeMode: "cover",
|
|
2251
|
+
style: { width: "100%", aspectRatio: 16 / 9, borderRadius: 10, backgroundColor: p.soft }
|
|
2252
|
+
}) : null;
|
|
2253
|
+
const v2 = videoEmbed(m2.url);
|
|
2254
|
+
const open = v2?.kind === "file" ? v2.src : m2.url;
|
|
2255
|
+
return RN.Linking ? btn("\u25B6 Watch the video", "secondary", () => void RN.Linking?.openURL(open).catch(() => {
|
|
2256
|
+
})) : null;
|
|
2257
|
+
};
|
|
2168
2258
|
if (v.type === "step")
|
|
2169
2259
|
return sheet(
|
|
2170
2260
|
[
|
|
@@ -2174,6 +2264,7 @@ var MRRocketFlows = ({ flows, paywall, appearance = {} }) => {
|
|
|
2174
2264
|
v.total > 1 ? muted(`Step ${v.index + 1} of ${v.total}`) : null,
|
|
2175
2265
|
close("Close the tour", flows.onboarding.dismiss)
|
|
2176
2266
|
),
|
|
2267
|
+
media(v.step),
|
|
2177
2268
|
title(v.step.title),
|
|
2178
2269
|
v.step.body ? muted(v.step.body, { fontSize: 15 }) : null,
|
|
2179
2270
|
btn(v.step.button || (v.last ? "Done" : "Next"), "primary", flows.onboarding.next)
|
|
@@ -2194,13 +2285,14 @@ var MRRocketFlows = ({ flows, paywall, appearance = {} }) => {
|
|
|
2194
2285
|
),
|
|
2195
2286
|
muted(`${done} of ${v.items.length} done`),
|
|
2196
2287
|
...v.items.map(
|
|
2197
|
-
({ step, done: d }) => (0, import_react.createElement)(
|
|
2288
|
+
({ step, done: d, tour }) => (0, import_react.createElement)(
|
|
2198
2289
|
RN.Pressable,
|
|
2199
2290
|
{
|
|
2200
2291
|
key: step.id,
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2292
|
+
// 0.17.0: an item that starts a tour opens it; finishing the tour ticks it.
|
|
2293
|
+
disabled: d || !!step.event && !tour,
|
|
2294
|
+
onPress: () => tour ? flows.onboarding.startTour(step.id) : flows.onboarding.check(step.id),
|
|
2295
|
+
accessibilityRole: tour && !d ? "button" : "checkbox",
|
|
2204
2296
|
accessibilityState: { checked: d },
|
|
2205
2297
|
style: { flexDirection: "row", gap: 10, alignItems: "flex-start", paddingVertical: 6 }
|
|
2206
2298
|
},
|
|
@@ -2672,7 +2764,7 @@ var SurveySheet = ({ survey, api, p, onDone }) => {
|
|
|
2672
2764
|
var MRRocketSurveys = ({ client, appearance }) => {
|
|
2673
2765
|
const p = usePalette(appearance);
|
|
2674
2766
|
const [survey, setSurvey] = (0, import_react2.useState)(null);
|
|
2675
|
-
const [
|
|
2767
|
+
const [who2, setWho] = (0, import_react2.useState)(() => client.getDistinctId());
|
|
2676
2768
|
(0, import_react2.useEffect)(() => client.subscribe(() => setWho(client.getDistinctId())), [client]);
|
|
2677
2769
|
(0, import_react2.useEffect)(() => {
|
|
2678
2770
|
let stop = false;
|
|
@@ -2693,7 +2785,7 @@ var MRRocketSurveys = ({ client, appearance }) => {
|
|
|
2693
2785
|
clearTimeout(timer);
|
|
2694
2786
|
ctrl.abort();
|
|
2695
2787
|
};
|
|
2696
|
-
}, [client,
|
|
2788
|
+
}, [client, who2]);
|
|
2697
2789
|
const done = (0, import_react2.useCallback)(() => {
|
|
2698
2790
|
setSurvey((cur) => {
|
|
2699
2791
|
if (cur) client.markSurveyDone(cur.s.id);
|
|
@@ -2815,6 +2907,7 @@ var POLL_IDLE_MS = 3e4;
|
|
|
2815
2907
|
var WAITING_FOR_MS = 10 * 6e4;
|
|
2816
2908
|
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
|
|
2817
2909
|
var whoLabel = { visitor: "You", team: "Team", ai: "AI agent", auto: "Team" };
|
|
2910
|
+
var who = (from, agentName) => from === "ai" && agentName?.trim() || whoLabel[from];
|
|
2818
2911
|
var msgView = "home";
|
|
2819
2912
|
var messengerOpen = opener();
|
|
2820
2913
|
var openAt = (v = "home") => {
|
|
@@ -3199,7 +3292,7 @@ var MessengerSheet = ({
|
|
|
3199
3292
|
k.text(`\u{1F4C4} ${a.title}`, { fontSize: 13 })
|
|
3200
3293
|
)
|
|
3201
3294
|
),
|
|
3202
|
-
m.at ? k.muted(`${mine ? "" : `${
|
|
3295
|
+
m.at ? k.muted(`${mine ? "" : `${who(m.from, o.agentName)} \xB7 `}${isPending ? "Sending\u2026" : timeAgo(m.at)}`, { fontSize: 11, textAlign: mine ? "right" : "left", paddingHorizontal: 6 }) : null
|
|
3203
3296
|
);
|
|
3204
3297
|
};
|
|
3205
3298
|
const row = (a) => (0, import_react2.createElement)(
|
|
@@ -3257,7 +3350,7 @@ var MessengerSheet = ({
|
|
|
3257
3350
|
RN3.View,
|
|
3258
3351
|
{ key: "r", style: { flexDirection: "row", alignItems: "center", gap: 10 } },
|
|
3259
3352
|
title ? teamMark(title, alpha(p.accent, 0.16), p.accent, 26) : null,
|
|
3260
|
-
(0, import_react2.createElement)(RN3.View, { style: { flex: 1, gap: 1 } }, (0, import_react2.createElement)(RN3.Text, { numberOfLines: 1, style: { color: hu.fg, fontSize: 14, fontWeight: "500" } }, last.body || (last.attachments?.length ? `Sent ${last.attachments.length === 1 ? last.attachments[0].name : `${last.attachments.length} files`}` : "")), k.muted(`${last.from === "visitor" ? "You" :
|
|
3353
|
+
(0, import_react2.createElement)(RN3.View, { style: { flex: 1, gap: 1 } }, (0, import_react2.createElement)(RN3.Text, { numberOfLines: 1, style: { color: hu.fg, fontSize: 14, fontWeight: "500" } }, last.body || (last.attachments?.length ? `Sent ${last.attachments.length === 1 ? last.attachments[0].name : `${last.attachments.length} files`}` : "")), k.muted(`${last.from === "visitor" ? "You" : who(last.from, o.agentName)} \xB7 ${timeAgo(last.at)}`, { fontSize: 11.5 })),
|
|
3261
3354
|
chat.unseen.length ? (0, import_react2.createElement)(RN3.View, { style: { width: 8, height: 8, borderRadius: 4, backgroundColor: p.danger } }) : glyph("next", p.muted, 14)
|
|
3262
3355
|
)
|
|
3263
3356
|
], { paddingVertical: 10, paddingHorizontal: 12 })
|
|
@@ -3292,7 +3385,6 @@ var MessengerSheet = ({
|
|
|
3292
3385
|
RN3.View,
|
|
3293
3386
|
{ style: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 6, gap: 8 } },
|
|
3294
3387
|
chat.error ? k.text(chat.error, { color: p.danger, fontSize: 12 }) : null,
|
|
3295
|
-
needEmail ? k.field({ value: email, onChange: setEmail, placeholder: "Your email (optional), so we can follow up", email: true, max: 200, style: { borderWidth: emailOk ? 0 : 1, borderColor: p.danger, borderRadius: r.field, paddingHorizontal: 16, backgroundColor: hu.surface, ...surf } }) : null,
|
|
3296
3388
|
// Photos picked for the next message, each with a way to take it out again.
|
|
3297
3389
|
photos.length ? (0, import_react2.createElement)(
|
|
3298
3390
|
RN3.View,
|
|
@@ -3320,6 +3412,15 @@ var MessengerSheet = ({
|
|
|
3320
3412
|
(0, import_react2.createElement)(
|
|
3321
3413
|
RN3.View,
|
|
3322
3414
|
{ style: { gap: 2, borderRadius: 20, paddingTop: 10, paddingBottom: 6, paddingRight: 6, paddingLeft: 16, backgroundColor: hu.surface, ...surf } },
|
|
3415
|
+
// The optional email: the box's first line, under a hairline the message follows.
|
|
3416
|
+
needEmail ? k.field({
|
|
3417
|
+
value: email,
|
|
3418
|
+
onChange: setEmail,
|
|
3419
|
+
placeholder: "Email for our reply (optional)",
|
|
3420
|
+
email: true,
|
|
3421
|
+
max: 200,
|
|
3422
|
+
style: { minHeight: 0, marginRight: 10, marginBottom: 4, paddingHorizontal: 0, paddingTop: 0, paddingBottom: 8, borderWidth: 0, borderRadius: 0, borderBottomWidth: 1, borderBottomColor: emailOk ? p.line : p.danger, backgroundColor: "transparent", fontSize: 13.5 }
|
|
3423
|
+
}) : null,
|
|
3323
3424
|
k.field({ value: body, onChange: setBody, placeholder: "Write a message\u2026", multiline: true, max: 4e3, style: { minHeight: 28, maxHeight: 120, borderWidth: 0, paddingHorizontal: 0, paddingVertical: 4, backgroundColor: "transparent" } }),
|
|
3324
3425
|
(0, import_react2.createElement)(
|
|
3325
3426
|
RN3.View,
|
|
@@ -3371,11 +3472,13 @@ var MessengerSheet = ({
|
|
|
3371
3472
|
key: v,
|
|
3372
3473
|
onPress: () => setView(v),
|
|
3373
3474
|
accessibilityRole: "tab",
|
|
3475
|
+
accessibilityLabel: name,
|
|
3374
3476
|
accessibilityState: { selected: on },
|
|
3375
|
-
|
|
3477
|
+
// Only the open tab carries its name; the others are icons, so the bar fits a narrow phone.
|
|
3478
|
+
style: { ...on ? { flex: 1 } : { width: 48 }, flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6, height: 36, borderRadius: 18, ...on ? { backgroundColor: hu.segment, ...segLift } : {} }
|
|
3376
3479
|
},
|
|
3377
3480
|
glyph(icon, on ? hu.fg : hu.muted, 17),
|
|
3378
|
-
k.text(name, { fontSize: 13.5, fontWeight: "500", color:
|
|
3481
|
+
on ? k.text(name, { fontSize: 13.5, fontWeight: "500", color: hu.fg }) : null,
|
|
3379
3482
|
badge ? (0, import_react2.createElement)(RN3.View, { style: { position: "absolute", top: 7, right: 12, width: 8, height: 8, borderRadius: 4, backgroundColor: p.danger } }) : null
|
|
3380
3483
|
);
|
|
3381
3484
|
};
|
|
@@ -3389,7 +3492,7 @@ var MessengerSheet = ({
|
|
|
3389
3492
|
const head = (0, import_react2.createElement)(
|
|
3390
3493
|
RN3.View,
|
|
3391
3494
|
{ key: "head", style: { flexDirection: "row", alignItems: "center", gap: 8, paddingLeft: 12, paddingRight: 12, paddingTop: 12, paddingBottom: 6, backgroundColor: ground } },
|
|
3392
|
-
typeof view !== "string" ? back("help", "All articles") : view === "messages" ? back("home", "Back to home") : view === "home" && (o.logo || title) ? o.logo ? (0, import_react2.createElement)(RN3.Image, { key: "logo", source: { uri: o.logo }, accessibilityIgnoresInvertColors: true, style: {
|
|
3495
|
+
typeof view !== "string" ? back("help", "All articles") : view === "messages" ? back("home", "Back to home") : view === "home" && (o.logo || title) ? o.logo ? (0, import_react2.createElement)(RN3.Image, { key: "logo", source: { uri: o.logo }, accessibilityIgnoresInvertColors: true, resizeMode: "contain", style: { height: 28, aspectRatio: 1, maxWidth: 132, borderRadius: 8, marginLeft: 4 } }) : teamMark(title, alpha(p.accent, 0.16), p.accent, 28) : null,
|
|
3393
3496
|
// In the chat: who answers, in the middle.
|
|
3394
3497
|
view === "messages" && title ? (0, import_react2.createElement)(
|
|
3395
3498
|
RN3.View,
|
|
@@ -3453,6 +3556,7 @@ var MRRocketMessenger = ({ client, appearance, options: given = {} }) => {
|
|
|
3453
3556
|
corners: look.corners,
|
|
3454
3557
|
header: look.header,
|
|
3455
3558
|
logo: look.logo,
|
|
3559
|
+
agentName: look.agentName,
|
|
3456
3560
|
...defined
|
|
3457
3561
|
} : given;
|
|
3458
3562
|
const p = usePalette({ theme: appearance?.theme ?? look?.theme, accent: appearance?.accent ?? look?.accent });
|
|
@@ -3542,7 +3646,7 @@ var MRRocketMessenger = ({ client, appearance, options: given = {} }) => {
|
|
|
3542
3646
|
elevation: 6
|
|
3543
3647
|
}
|
|
3544
3648
|
},
|
|
3545
|
-
k.muted(`${
|
|
3649
|
+
k.muted(`${who(banner.from, options.agentName)}${unseen > 1 ? ` \xB7 ${unseen} new` : ""}`, { fontWeight: "600", fontSize: 12 }),
|
|
3546
3650
|
(0, import_react2.createElement)(RN3.Text, { numberOfLines: 3, style: { color: p.fg, fontSize: 15, lineHeight: 20 } }, banner.body)
|
|
3547
3651
|
) : null;
|
|
3548
3652
|
if (!launcher && !toast && !open) return null;
|