@mrrocket/sdk 0.17.0 → 0.18.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 +7 -1
- package/dist/browser/mrrocket-flows.js +9 -2
- package/dist/browser/mrrocket-messenger.js +3 -3
- package/dist/browser/mrrocket.js +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -1
- package/dist/browser.js.map +1 -1
- package/dist/client.d.ts +23 -3
- package/dist/client.js +15 -1
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +3 -1
- package/dist/context.js.map +1 -1
- package/dist/core.d.ts +3 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/finish-web.d.ts +18 -0
- package/dist/finish-web.js +139 -0
- package/dist/finish-web.js.map +1 -0
- package/dist/flows-ui.d.ts +1 -10
- package/dist/flows-ui.js +105 -6
- package/dist/flows-ui.js.map +1 -1
- package/dist/flows-web.d.ts +8 -1
- package/dist/flows-web.js +8 -0
- package/dist/flows-web.js.map +1 -1
- package/dist/flows.d.ts +159 -7
- package/dist/flows.js +240 -28
- package/dist/flows.js.map +1 -1
- package/dist/icons.d.ts +24 -0
- package/dist/icons.js +61 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/messenger-ui.js +78 -53
- package/dist/messenger-ui.js.map +1 -1
- package/dist/onboarding-state.d.ts +23 -0
- package/dist/onboarding-state.js +43 -0
- package/dist/onboarding-state.js.map +1 -0
- package/dist/react-native/index.d.cts +177 -15
- package/dist/react-native/index.d.ts +177 -15
- package/dist/react-native/index.js +776 -270
- package/dist/react-native/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n type ChangelogEntry,\n type ChatMessage,\n type ChatThread,\n type CockpitProviderProps,\n type CockpitUser,\n type FeedbackBoardInfo,\n type FeedbackBoardProps,\n type FeedbackComment,\n type FeedbackList,\n type FeedbackPost,\n type FeedbackRoadmap,\n type FeedbackWidgetProps,\n type MessengerProps,\n type PostStatus,\n type SurveyAnswer,\n type SurveyDefinition,\n type SurveyQuestion,\n type SurveyQuestionKind,\n CockpitProvider,\n Experiment,\n FeedbackBoard,\n FeedbackWidget,\n Messenger,\n Survey,\n Text,\n WIDGET_CSS,\n createApi,\n useCancelFlow,\n useCockpit,\n useFeedback,\n useFlag,\n useFlagVariant,\n useMessenger,\n usePaywall,\n usePush,\n useStyles,\n useVariant,\n} from \"./browser\";\nexport type { PushResult, PushStatus, WebPushOptions } from \"./push-web\";\n/** `identify(id, props, { hash })` (0.16.0); the hash comes from `userHash()` in `@mrrocket/sdk/next/server`. */\nexport type { IdentifyOptions } from \"./identity\";\nexport {\n type CockpitConfig,\n type CockpitEvent,\n type ConsentChoice,\n type ConsentMode,\n type ReplayConfig,\n type ErrorReport,\n type ExperimentConfig,\n type FlagCondition,\n type FlagConditionSet,\n type FlagConfig,\n type FlagPerson,\n type RedirectConfig,\n type RedirectDecision,\n type VariantConfig,\n type VariantId,\n EMBED_PARAM,\n EXPOSURE_PARAM,\n SDK_VERSION,\n ID_COOKIE,\n PREVIEW_PARAM,\n SESSION_COOKIE,\n assign,\n evaluateFlag,\n parsePreview,\n previewHref,\n redirectFor,\n} from \"./core\";\nexport {\n type CancelFlowConfig,\n type CancelFlowOptions,\n type CancelFlowResult,\n type CancelOffer,\n type InAppMessage,\n type OnboardingFlow,\n type OnboardingStep,\n type FlowMedia,\n type TourPlacement,\n videoEmbed,\n} from \"./flows\";\nexport type { FlowsTheme } from \"./flows-ui\";\nexport { PAYWALL_EVENT, type PaywallConfig, type PaywallOptions, type PaywallPage, type PaywallPlan, type PaywallResult } from \"./paywall\";\nexport {\n type AttributionMode,\n type CheckoutReferral,\n type Referral,\n REFERRAL_COOKIE,\n getReferral,\n readReferralCookie,\n referralForCheckout,\n referralLink,\n} from \"./referral\";\n"],"mappings":";AAAA;AAAA,EAmBI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAIP;AAAA,EAgBI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n type ChangelogEntry,\n type ChatMessage,\n type ChatThread,\n type CockpitProviderProps,\n type CockpitUser,\n type FeedbackBoardInfo,\n type FeedbackBoardProps,\n type FeedbackComment,\n type FeedbackList,\n type FeedbackPost,\n type FeedbackRoadmap,\n type FeedbackWidgetProps,\n type MessengerProps,\n type PostStatus,\n type SurveyAnswer,\n type SurveyDefinition,\n type SurveyQuestion,\n type SurveyQuestionKind,\n CockpitProvider,\n Experiment,\n FeedbackBoard,\n FeedbackWidget,\n Messenger,\n Survey,\n Text,\n WIDGET_CSS,\n createApi,\n useCancelFlow,\n useCockpit,\n useFeedback,\n useFlag,\n useFlagVariant,\n useMessenger,\n useOnboarding,\n usePaywall,\n usePush,\n useStyles,\n useVariant,\n} from \"./browser\";\nexport type { PushResult, PushStatus, WebPushOptions } from \"./push-web\";\n/** `identify(id, props, { hash })` (0.16.0); the hash comes from `userHash()` in `@mrrocket/sdk/next/server`. */\nexport type { IdentifyOptions } from \"./identity\";\nexport {\n type CockpitConfig,\n type CockpitEvent,\n type ConsentChoice,\n type ConsentMode,\n type ReplayConfig,\n type ErrorReport,\n type ExperimentConfig,\n type FlagCondition,\n type FlagConditionSet,\n type FlagConfig,\n type FlagPerson,\n type RedirectConfig,\n type RedirectDecision,\n type VariantConfig,\n type VariantId,\n EMBED_PARAM,\n EXPOSURE_PARAM,\n SDK_VERSION,\n ID_COOKIE,\n PREVIEW_PARAM,\n SESSION_COOKIE,\n assign,\n evaluateFlag,\n parsePreview,\n previewHref,\n redirectFor,\n} from \"./core\";\nexport {\n type CancelFlowConfig,\n type CancelFlowOptions,\n type CancelFlowResult,\n type CancelOffer,\n type InAppMessage,\n type OnboardingFlow,\n type OnboardingStep,\n type FlowMedia,\n type TourPlacement,\n type TaskOpens,\n type FlowIcon,\n type FinishAnimation,\n type OnboardingQuestion,\n type OnboardingItemState,\n videoEmbed,\n} from \"./flows\";\nexport type { UseOnboarding } from \"./onboarding-state\";\nexport { FLOW_ICONS, FLOW_ICON_NAMES, type BuiltinIcon } from \"./icons\";\nexport type { FlowsTheme } from \"./flows-ui\";\nexport { PAYWALL_EVENT, type PaywallConfig, type PaywallOptions, type PaywallPage, type PaywallPlan, type PaywallResult } from \"./paywall\";\nexport {\n type AttributionMode,\n type CheckoutReferral,\n type Referral,\n REFERRAL_COOKIE,\n getReferral,\n readReferralCookie,\n referralForCheckout,\n referralLink,\n} from \"./referral\";\n"],"mappings":";AAAA;AAAA,EAmBI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAIP;AAAA,EAgBI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP;AAAA,EAeI;AAAA,OACG;AAEP,SAAS,YAAY,uBAAyC;AAE9D,SAAS,qBAAsH;AAC/H;AAAA,EAII;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;","names":[]}
|
package/dist/messenger-ui.js
CHANGED
|
@@ -13,6 +13,7 @@ var POLL_OPEN_MS = 4e3;
|
|
|
13
13
|
var POLL_WAITING_MS = 8e3;
|
|
14
14
|
var POLL_IDLE_MS = 3e4;
|
|
15
15
|
var WAITING_FOR_MS = 10 * 6e4;
|
|
16
|
+
var SLOW_SEND_MS = 1500;
|
|
16
17
|
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
|
|
17
18
|
var SEEN_KEY = "ckw_msgr_seen";
|
|
18
19
|
var readSeen = () => {
|
|
@@ -260,7 +261,10 @@ var build = (o) => {
|
|
|
260
261
|
let thread = null;
|
|
261
262
|
let loaded = false;
|
|
262
263
|
let error = "";
|
|
263
|
-
|
|
264
|
+
const sayable = (e) => e.status === 401 ? "The chat is not available right now. Please try again later." : e.message;
|
|
265
|
+
let outbox = [];
|
|
266
|
+
let outboxSeq = 0;
|
|
267
|
+
let flushing = false;
|
|
264
268
|
let lastKnown = null;
|
|
265
269
|
let unseen = [];
|
|
266
270
|
let previewGone = false;
|
|
@@ -644,7 +648,7 @@ var build = (o) => {
|
|
|
644
648
|
const list = el("ol", { class: "ckw-msgs", "aria-live": "polite", "aria-label": "Messages" });
|
|
645
649
|
const needEmail = () => askEmail && !o.user()?.email && !thread?.hasEmail;
|
|
646
650
|
const emailOk = () => !email.value.trim() || EMAIL.test(email.value.trim());
|
|
647
|
-
const canSend = () => (!!text.value.trim() || picked.length > 0) &&
|
|
651
|
+
const canSend = () => (!!text.value.trim() || picked.length > 0) && emailOk();
|
|
648
652
|
const go = (v) => {
|
|
649
653
|
const changed = JSON.stringify(v) !== JSON.stringify(view);
|
|
650
654
|
view = v;
|
|
@@ -666,6 +670,7 @@ var build = (o) => {
|
|
|
666
670
|
return img;
|
|
667
671
|
};
|
|
668
672
|
const bubble = (m, isPending = false) => {
|
|
673
|
+
const slow = isPending && Date.now() - Date.parse(m.at) >= SLOW_SEND_MS;
|
|
669
674
|
const li = el("li", { class: "ckw-msg", "data-from": m.from === "visitor" ? "me" : "them" }, m.body || !m.attachments?.length ? el("div", { class: "ckw-bubble" }, m.body) : null);
|
|
670
675
|
if (isPending) li.setAttribute("aria-busy", "true");
|
|
671
676
|
if (m.attachments?.length)
|
|
@@ -683,7 +688,7 @@ var build = (o) => {
|
|
|
683
688
|
chip.addEventListener("click", () => go({ article: a.id }));
|
|
684
689
|
li.append(chip);
|
|
685
690
|
}
|
|
686
|
-
li.append(el("span", { class: "ckw-msg-meta" }, m.from === "ai" ? agentFace() : null, `${m.from !== "visitor" ? `${whoLabel[m.from]} \xB7 ` : ""}${
|
|
691
|
+
li.append(el("span", { class: "ckw-msg-meta" }, m.from === "ai" ? agentFace() : null, `${m.from !== "visitor" ? `${whoLabel[m.from]} \xB7 ` : ""}${slow ? "Sending\u2026" : timeAgo(m.at)}`));
|
|
687
692
|
return li;
|
|
688
693
|
};
|
|
689
694
|
const articleRow = (a) => {
|
|
@@ -754,7 +759,7 @@ var build = (o) => {
|
|
|
754
759
|
askIn.value = "";
|
|
755
760
|
askGo.disabled = true;
|
|
756
761
|
go("messages");
|
|
757
|
-
if (canSend())
|
|
762
|
+
if (canSend()) submit();
|
|
758
763
|
});
|
|
759
764
|
const drawHome = () => {
|
|
760
765
|
const first = o.user()?.name?.trim().split(/\s+/)[0];
|
|
@@ -884,19 +889,19 @@ var build = (o) => {
|
|
|
884
889
|
const drawMessages = () => {
|
|
885
890
|
const msgs = thread?.messages ?? [];
|
|
886
891
|
const parts = [];
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
const sig = `${msgs.map((m) => m.id).join(",")}|${
|
|
892
|
+
{
|
|
893
|
+
const waiting = outbox.map((o2) => o2.message);
|
|
894
|
+
const sig = `${msgs.map((m) => m.id).join(",")}|${waiting.map((m) => `${m.id}:${Date.now() - Date.parse(m.at) >= SLOW_SEND_MS}`).join(",")}|${Math.floor(Date.now() / 6e4)}`;
|
|
890
895
|
if (sig !== listSig) {
|
|
891
896
|
listSig = sig;
|
|
892
|
-
const greet = el("li", { class: "ckw-msg", "data-from": "them" }, el("div", { class: "ckw-bubble" }, greeting));
|
|
893
|
-
const items = [greet, ...msgs.map((m) => bubble(m)), ...
|
|
897
|
+
const greet = msgs.length || waiting.length ? [] : [el("li", { class: "ckw-msg", "data-from": "them" }, el("div", { class: "ckw-bubble" }, greeting))];
|
|
898
|
+
const items = [...greet, ...msgs.map((m) => bubble(m)), ...waiting.map((m) => bubble(m, true))];
|
|
894
899
|
if (listCount >= 0) items.slice(listCount).forEach((li) => li.setAttribute("data-new", ""));
|
|
895
900
|
listCount = items.length;
|
|
896
901
|
list.replaceChildren(...items);
|
|
897
902
|
}
|
|
898
903
|
parts.push(list);
|
|
899
|
-
const top = !msgs.some((m) => m.from === "visitor") && !
|
|
904
|
+
const top = !msgs.some((m) => m.from === "visitor") && !outbox.length ? (articles ?? []).slice(0, 3) : [];
|
|
900
905
|
if (top.length) {
|
|
901
906
|
if (suggestions.childNodes.length !== top.length)
|
|
902
907
|
suggestions.replaceChildren(
|
|
@@ -909,9 +914,9 @@ var build = (o) => {
|
|
|
909
914
|
parts.push(suggestions);
|
|
910
915
|
}
|
|
911
916
|
}
|
|
912
|
-
if (thread?.conversation?.status === "solved" && !
|
|
917
|
+
if (thread?.conversation?.status === "solved" && !outbox.length) parts.push(el("p", { class: "ckw-fine ckw-msgr-note" }, "This conversation is closed. Write to start a new one."));
|
|
913
918
|
if (body.childNodes.length !== parts.length || parts.some((x, i) => body.childNodes[i] !== x)) body.replaceChildren(...parts);
|
|
914
|
-
const count = msgs.length +
|
|
919
|
+
const count = msgs.length + outbox.length;
|
|
915
920
|
if (count !== drawn) {
|
|
916
921
|
drawn = count;
|
|
917
922
|
body.scrollTop = body.scrollHeight;
|
|
@@ -942,15 +947,18 @@ var build = (o) => {
|
|
|
942
947
|
if (pop.childNodes.length !== kids.length || kids.some((k, i) => pop.childNodes[i] !== k)) pop.replaceChildren(...kids);
|
|
943
948
|
};
|
|
944
949
|
const tick = async () => {
|
|
945
|
-
ctrl
|
|
946
|
-
ctrl = new AbortController();
|
|
950
|
+
if (ctrl) return;
|
|
951
|
+
const mine = ctrl = new AbortController();
|
|
947
952
|
try {
|
|
948
|
-
take(await api().chat(
|
|
953
|
+
take(await api().chat(mine.signal));
|
|
949
954
|
error = "";
|
|
950
955
|
} catch (e) {
|
|
951
956
|
if (e.name === "AbortError") return;
|
|
952
|
-
if (open && view === "messages") error = e
|
|
957
|
+
if (open && view === "messages") error = sayable(e);
|
|
958
|
+
} finally {
|
|
959
|
+
if (ctrl === mine) ctrl = null;
|
|
953
960
|
}
|
|
961
|
+
if (!loaded) listCount = -1;
|
|
954
962
|
loaded = true;
|
|
955
963
|
draw();
|
|
956
964
|
drawFab();
|
|
@@ -969,58 +977,75 @@ var build = (o) => {
|
|
|
969
977
|
else clearTimeout(poll);
|
|
970
978
|
};
|
|
971
979
|
document.addEventListener("visibilitychange", onVisible);
|
|
972
|
-
const
|
|
980
|
+
const flush = async () => {
|
|
981
|
+
if (flushing) return;
|
|
982
|
+
flushing = true;
|
|
983
|
+
while (outbox.length) {
|
|
984
|
+
const { message, files, email: given } = outbox[0];
|
|
985
|
+
await Promise.all(files.map((p) => p.up));
|
|
986
|
+
const ids = files.filter((p) => p.id).map((p) => p.id);
|
|
987
|
+
try {
|
|
988
|
+
if (!message.body && !ids.length) throw new Error(error || "The file could not be sent.");
|
|
989
|
+
const sent = await api().sendChat({
|
|
990
|
+
body: message.body,
|
|
991
|
+
email: given,
|
|
992
|
+
url: window.location.href.slice(0, 500),
|
|
993
|
+
...ids.length ? { attachments: ids } : {},
|
|
994
|
+
// A little context for a bug report; the server reads browser and system from the user agent.
|
|
995
|
+
context: { viewport: `${window.innerWidth}\xD7${window.innerHeight}` }
|
|
996
|
+
});
|
|
997
|
+
ctrl?.abort();
|
|
998
|
+
ctrl = null;
|
|
999
|
+
take(sent);
|
|
1000
|
+
outbox.shift();
|
|
1001
|
+
for (const p of files) {
|
|
1002
|
+
localUrls.delete(p.key);
|
|
1003
|
+
URL.revokeObjectURL(p.local);
|
|
1004
|
+
}
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
const back = outbox.splice(0);
|
|
1007
|
+
text.value = [...back.map((b) => b.message.body), text.value.trim()].filter(Boolean).join("\n");
|
|
1008
|
+
picked = [...back.flatMap((b) => b.files.filter((p) => p.id)), ...picked];
|
|
1009
|
+
for (const b of back) for (const p of b.files) localUrls.delete(p.key);
|
|
1010
|
+
error = sayable(e);
|
|
1011
|
+
}
|
|
1012
|
+
draw();
|
|
1013
|
+
}
|
|
1014
|
+
flushing = false;
|
|
1015
|
+
schedule();
|
|
1016
|
+
};
|
|
1017
|
+
const submit = () => {
|
|
973
1018
|
const msg = text.value.trim();
|
|
974
1019
|
const files = picked;
|
|
975
|
-
if (!msg && !files.length ||
|
|
1020
|
+
if (!msg && !files.length || !emailOk()) return;
|
|
976
1021
|
chime.unlock();
|
|
977
1022
|
for (const p of files) localUrls.set(p.key, p.local);
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1023
|
+
outbox.push({
|
|
1024
|
+
message: {
|
|
1025
|
+
id: `pending-${++outboxSeq}`,
|
|
1026
|
+
from: "visitor",
|
|
1027
|
+
body: msg,
|
|
1028
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1029
|
+
...files.length ? { attachments: files.map((p) => ({ id: p.key, name: p.name, type: p.type, size: p.size })) } : {}
|
|
1030
|
+
},
|
|
1031
|
+
files,
|
|
1032
|
+
email: needEmail() && email.value.trim() ? email.value.trim() : void 0
|
|
1033
|
+
});
|
|
985
1034
|
text.value = "";
|
|
986
1035
|
picked = [];
|
|
987
1036
|
error = "";
|
|
988
1037
|
draw();
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
let sent = false;
|
|
992
|
-
try {
|
|
993
|
-
if (!msg && !ids.length) throw new Error(error || "The file could not be sent.");
|
|
994
|
-
take(
|
|
995
|
-
await api().sendChat({
|
|
996
|
-
body: msg,
|
|
997
|
-
email: needEmail() && email.value.trim() ? email.value.trim() : void 0,
|
|
998
|
-
url: window.location.href.slice(0, 500),
|
|
999
|
-
...ids.length ? { attachments: ids } : {},
|
|
1000
|
-
// A little context for a bug report; the server reads browser and system from the user agent.
|
|
1001
|
-
context: { viewport: `${window.innerWidth}\xD7${window.innerHeight}` }
|
|
1002
|
-
})
|
|
1003
|
-
);
|
|
1004
|
-
sent = true;
|
|
1005
|
-
} catch (e) {
|
|
1006
|
-
text.value = msg;
|
|
1007
|
-
picked = files.filter((p) => p.id);
|
|
1008
|
-
error = e.message;
|
|
1009
|
-
}
|
|
1010
|
-
pending = null;
|
|
1011
|
-
for (const p of files) localUrls.delete(p.key);
|
|
1012
|
-
draw();
|
|
1013
|
-
if (sent) for (const p of files) URL.revokeObjectURL(p.local);
|
|
1014
|
-
schedule();
|
|
1038
|
+
setTimeout(draw, SLOW_SEND_MS + 50);
|
|
1039
|
+
void flush();
|
|
1015
1040
|
};
|
|
1016
1041
|
form.addEventListener("submit", (e) => {
|
|
1017
1042
|
e.preventDefault();
|
|
1018
|
-
|
|
1043
|
+
submit();
|
|
1019
1044
|
});
|
|
1020
1045
|
text.addEventListener("keydown", (e) => {
|
|
1021
1046
|
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) {
|
|
1022
1047
|
e.preventDefault();
|
|
1023
|
-
|
|
1048
|
+
submit();
|
|
1024
1049
|
}
|
|
1025
1050
|
});
|
|
1026
1051
|
text.addEventListener("input", () => send.disabled = !canSend());
|