@mrrocket/sdk 0.18.0 → 0.22.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +36 -1
  3. package/dist/api-client.d.ts +28 -4
  4. package/dist/api-client.js +30 -13
  5. package/dist/api-client.js.map +1 -1
  6. package/dist/browser/mrrocket-flows.js +8 -3
  7. package/dist/browser/mrrocket-messenger.js +38 -5
  8. package/dist/browser/mrrocket.js +1 -1
  9. package/dist/browser.d.ts +2 -2
  10. package/dist/browser.js +2 -1
  11. package/dist/browser.js.map +1 -1
  12. package/dist/client.d.ts +17 -1
  13. package/dist/client.js +25 -5
  14. package/dist/client.js.map +1 -1
  15. package/dist/core.d.ts +5 -1
  16. package/dist/core.js +1 -1
  17. package/dist/core.js.map +1 -1
  18. package/dist/feedback.js +161 -119
  19. package/dist/feedback.js.map +1 -1
  20. package/dist/flows-ui.d.ts +1 -1
  21. package/dist/flows-ui.js +100 -72
  22. package/dist/flows-ui.js.map +1 -1
  23. package/dist/flows-web.js +2 -1
  24. package/dist/flows-web.js.map +1 -1
  25. package/dist/flows.d.ts +38 -6
  26. package/dist/flows.js +51 -17
  27. package/dist/flows.js.map +1 -1
  28. package/dist/i18n.d.ts +22 -0
  29. package/dist/i18n.js +74 -0
  30. package/dist/i18n.js.map +1 -0
  31. package/dist/index.d.ts +4 -1
  32. package/dist/index.js +5 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/messenger-ui.d.ts +9 -3
  35. package/dist/messenger-ui.js +324 -152
  36. package/dist/messenger-ui.js.map +1 -1
  37. package/dist/messenger.d.ts +3 -1
  38. package/dist/messenger.js +3 -2
  39. package/dist/messenger.js.map +1 -1
  40. package/dist/onboarding-report.d.ts +19 -0
  41. package/dist/onboarding-report.js +23 -0
  42. package/dist/onboarding-report.js.map +1 -0
  43. package/dist/onboarding-state.d.ts +3 -0
  44. package/dist/onboarding-state.js +7 -1
  45. package/dist/onboarding-state.js.map +1 -1
  46. package/dist/paywall.js +2 -1
  47. package/dist/paywall.js.map +1 -1
  48. package/dist/react-native/index.d.cts +93 -8
  49. package/dist/react-native/index.d.ts +93 -8
  50. package/dist/react-native/index.js +819 -511
  51. package/dist/react-native/index.js.map +1 -1
  52. package/dist/server.d.ts +4 -2
  53. package/dist/server.js +2 -2
  54. package/dist/server.js.map +1 -1
  55. package/dist/styles-css.d.ts +1 -1
  56. package/dist/styles-css.js +35 -2
  57. package/dist/styles-css.js.map +1 -1
  58. package/dist/survey.js +18 -14
  59. package/dist/survey.js.map +1 -1
  60. package/dist/ui.d.ts +2 -0
  61. package/dist/ui.js +15 -12
  62. package/dist/ui.js.map +1 -1
  63. package/package.json +6 -3
package/dist/flows.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/flows.ts
2
+ import { currentLocale, t, tf } from "./i18n.js";
2
3
  var CANCEL_EVENT = "$cancel_flow";
3
4
  var ONBOARDING_EVENT = "$onboarding";
4
5
  var INAPP_EVENT = "$inapp";
@@ -8,18 +9,20 @@ var PLAIN_CANCEL = {
8
9
  question: "",
9
10
  reasons: [],
10
11
  offers: {},
11
- confirm: { title: "Cancel your subscription?", body: "You keep access until the end of the billing period.", button: "Cancel subscription" },
12
+ // Read when it is shown, so it follows the visitor's language.
13
+ get confirm() {
14
+ return { title: t("Cancel your subscription?"), body: t("You keep access until the end of the billing period."), button: t("Cancel subscription") };
15
+ },
12
16
  offersFor: "business"
13
17
  };
14
- var FAILED = "Something went wrong. Please try again.";
15
18
  var PROGRESS_KEY = "mrrocket:onboarding";
16
19
  var eventSlug = (s) => s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
17
20
  var SIGNUP = /* @__PURE__ */ new Set(["signed_up", "signup", "sign_up", "registered", "account_created", "user_signed_up"]);
18
21
  var matchesTrigger = (trigger, event) => {
19
- const t = eventSlug(trigger);
22
+ const t2 = eventSlug(trigger);
20
23
  const e = eventSlug(event);
21
- if (!t || !e) return false;
22
- return t === e || SIGNUP.has(t) && SIGNUP.has(e);
24
+ if (!t2 || !e) return false;
25
+ return t2 === e || SIGNUP.has(t2) && SIGNUP.has(e);
23
26
  };
24
27
  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());
25
28
  var FROM_CHECKLIST = "From a checklist";
@@ -30,16 +33,30 @@ var momentOf = (f) => f.when ?? f.trigger;
30
33
  var manual = (trigger) => eventSlug(trigger) === "from_a_checklist" || eventSlug(trigger) === "from_your_code" || eventSlug(trigger) === eventSlug(NEEDS_NEWER);
31
34
  var AFTER_PREFIX = "after:";
32
35
  var afterOf = (trigger) => {
33
- const t = (trigger ?? "").trim();
34
- return t.toLowerCase().startsWith(AFTER_PREFIX) ? t.slice(AFTER_PREFIX.length).trim() || null : null;
36
+ const t2 = (trigger ?? "").trim();
37
+ return t2.toLowerCase().startsWith(AFTER_PREFIX) ? t2.slice(AFTER_PREFIX.length).trim() || null : null;
35
38
  };
36
39
  var opensOf = (step) => step.opens ?? (step.startsTour ? { kind: "tour", id: step.startsTour } : void 0);
40
+ var OTHER_PREFIX = "other:";
41
+ var scaleOf = (q) => {
42
+ const min = q?.min ?? 0;
43
+ const max = q?.max ?? 10;
44
+ return Array.from({ length: Math.max(0, Math.min(max - min, 20) + 1) }, (_, i) => min + i);
45
+ };
37
46
  var answerOk = (q, value) => {
38
47
  if (!q || value == null) return false;
39
- if (q.type === "choice") return (q.options ?? []).some((o) => o.id === value);
48
+ if (q.type === "choice") {
49
+ if (q.other && value.startsWith(OTHER_PREFIX)) return value.slice(OTHER_PREFIX.length).trim().length > 0;
50
+ return (q.options ?? []).some((o) => o.id === value);
51
+ }
52
+ if (q.type === "scale") return scaleOf(q).some((n) => String(n) === value);
40
53
  return value.trim().length > 0 && value.length <= 500;
41
54
  };
42
- var answerLabel = (q, value) => q?.type === "choice" ? q.options?.find((o) => o.id === value)?.label ?? value : value.trim();
55
+ var answerLabel = (q, value) => {
56
+ if (q?.type !== "choice") return value.trim();
57
+ if (q.other && value.startsWith(OTHER_PREFIX)) return value.slice(OTHER_PREFIX.length).trim();
58
+ return q.options?.find((o) => o.id === value)?.label ?? value;
59
+ };
43
60
  var videoEmbed = (url) => {
44
61
  const u = (url ?? "").trim();
45
62
  if (!/^https?:\/\//i.test(u)) return null;
@@ -61,12 +78,14 @@ var runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toS
61
78
  var discounted = (amount, percent) => Math.round(amount * (1 - percent / 100) * 100) / 100;
62
79
  var money = (amount, currency) => {
63
80
  try {
64
- return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(amount);
81
+ return new Intl.NumberFormat(currentLocale(), { style: "currency", currency }).format(amount);
65
82
  } catch {
66
83
  return `${amount.toFixed(2)} ${currency}`;
67
84
  }
68
85
  };
69
- var offerButton = (o) => o.kind === "contact" ? "Send to the team" : o.kind === "pause" ? "Pause instead" : o.kind === "downgrade" ? "Switch plan" : "Accept offer";
86
+ var offerButton = (o) => o.kind === "contact" ? t("Send to the team") : o.kind === "pause" ? t("Pause instead") : o.kind === "downgrade" ? t("Switch plan") : t("Accept offer");
87
+ var monthsWord = (n) => n === 1 ? t("1 month") : tf("{n} months", { n });
88
+ var forMonths = (n) => tf("for {months}", { months: monthsWord(n) });
70
89
  var safeUrl = (url) => {
71
90
  const u = (url ?? "").trim();
72
91
  return /^https?:\/\//i.test(u) || /^\/(?!\/)/.test(u) ? u : void 0;
@@ -261,8 +280,8 @@ var createFlows = (env) => {
261
280
  flow,
262
281
  items: items.map((s) => {
263
282
  const o = opensOf(s);
264
- const t = o && (o.kind === "tour" || o.kind === "modal") && o.id !== flow.id ? flowById(o.id) : void 0;
265
- const target = t && t.shownBy !== "code" && nodesOf(t).length ? t : void 0;
283
+ const t2 = o && (o.kind === "tour" || o.kind === "modal") && o.id !== flow.id ? flowById(o.id) : void 0;
284
+ const target = t2 && t2.shownBy !== "code" && nodesOf(t2).length ? t2 : void 0;
266
285
  const opens = o && (o.kind === "page" ? !!o.target.trim() : o.kind === "code" || !!target) ? o : void 0;
267
286
  return {
268
287
  step: s,
@@ -401,7 +420,7 @@ var createFlows = (env) => {
401
420
  };
402
421
  const answerStep = (flow, step, raw) => {
403
422
  const q = step.question;
404
- const value = q.type === "text" ? raw.trim().slice(0, 500) : raw;
423
+ const value = q.type === "text" ? raw.trim().slice(0, 500) : raw.startsWith(OTHER_PREFIX) ? OTHER_PREFIX + raw.slice(OTHER_PREFIX.length).trim().slice(0, 490) : raw;
405
424
  answers.set(q.key, value);
406
425
  drafts.delete(step.id);
407
426
  markDone(prog(flow.id), step.id);
@@ -512,7 +531,7 @@ var createFlows = (env) => {
512
531
  () => finish(c, r),
513
532
  () => {
514
533
  c.busy = false;
515
- c.error = FAILED;
534
+ c.error = t("Something went wrong. Please try again.");
516
535
  emit();
517
536
  }
518
537
  );
@@ -592,8 +611,8 @@ var createFlows = (env) => {
592
611
  answer: (text) => {
593
612
  const c = cancel;
594
613
  if (!c || c.busy || c.screen !== "followup") return;
595
- const t = text.slice(0, 500);
596
- c.answer = t.trim() ? t : void 0;
614
+ const t2 = text.slice(0, 500);
615
+ c.answer = t2.trim() ? t2 : void 0;
597
616
  emit();
598
617
  },
599
618
  next: () => {
@@ -735,6 +754,17 @@ var createFlows = (env) => {
735
754
  drafts.set(v.step.id, String(value).slice(0, 500));
736
755
  emit();
737
756
  },
757
+ skip: () => {
758
+ const v = onboardingView();
759
+ const q = v?.type === "step" && v.step.kind === "question" ? v.step.question : void 0;
760
+ if (v?.type !== "step" || !q?.optional) return;
761
+ drafts.delete(v.step.id);
762
+ markDone(prog(v.flow.id), v.step.id);
763
+ env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: "question", action: "completed", question: q.key, skipped: true });
764
+ celebrate(v.flow);
765
+ save();
766
+ emit();
767
+ },
738
768
  back: () => {
739
769
  const v = onboardingView();
740
770
  if (v?.type !== "step" || v.step.kind !== "question" || !v.back) return;
@@ -837,6 +867,7 @@ export {
837
867
  INAPP_EVENT,
838
868
  NEEDS_NEWER,
839
869
  ONBOARDING_EVENT,
870
+ OTHER_PREFIX,
840
871
  PLAIN_CANCEL,
841
872
  REVIEW_EVENT,
842
873
  afterOf,
@@ -845,12 +876,14 @@ export {
845
876
  createFlows,
846
877
  discounted,
847
878
  eventSlug,
879
+ forMonths,
848
880
  isPageTrigger,
849
881
  matchesTrigger,
850
882
  mediaOf,
851
883
  momentOf,
852
884
  money,
853
885
  monthsSince,
886
+ monthsWord,
854
887
  nodesOf,
855
888
  offerButton,
856
889
  opensOf,
@@ -858,6 +891,7 @@ export {
858
891
  ruleMatches,
859
892
  runId,
860
893
  safeUrl,
894
+ scaleOf,
861
895
  startsOnLoad,
862
896
  videoEmbed,
863
897
  waitMs