@mrrocket/sdk 0.15.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 +29 -0
- package/README.md +47 -3
- package/dist/api-client.d.ts +12 -5
- package/dist/api-client.js +12 -8
- package/dist/api-client.js.map +1 -1
- package/dist/api.d.ts +4 -1
- package/dist/api.js +2 -1
- package/dist/api.js.map +1 -1
- package/dist/batch.d.ts +6 -4
- package/dist/batch.js +3 -3
- package/dist/batch.js.map +1 -1
- package/dist/browser/mrrocket-flows.js +9 -2
- package/dist/browser/mrrocket-forms.js +1 -1
- package/dist/browser/mrrocket-messenger.js +42 -43
- package/dist/browser/mrrocket-push.js +1 -1
- package/dist/browser/mrrocket-replay.js +3 -3
- package/dist/browser/mrrocket.js +1 -1
- package/dist/client.d.ts +10 -2
- package/dist/client.js +36 -15
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +5 -1
- package/dist/context.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/errors.d.ts +5 -1
- package/dist/errors.js +8 -2
- package/dist/errors.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-web.d.ts +2 -0
- package/dist/flows-web.js +4 -1
- package/dist/flows-web.js.map +1 -1
- package/dist/flows.d.ts +59 -3
- package/dist/flows.js +88 -7
- package/dist/flows.js.map +1 -1
- package/dist/forms.d.ts +4 -0
- package/dist/forms.js +4 -1
- package/dist/forms.js.map +1 -1
- package/dist/identity.d.ts +42 -0
- package/dist/identity.js +24 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/messenger-ui.d.ts +12 -2
- package/dist/messenger-ui.js +58 -47
- package/dist/messenger-ui.js.map +1 -1
- package/dist/messenger.js +3 -2
- package/dist/messenger.js.map +1 -1
- package/dist/push-web.d.ts +2 -13
- package/dist/push-web.js +4 -2
- package/dist/push-web.js.map +1 -1
- package/dist/react-native/index.d.cts +105 -14
- package/dist/react-native/index.d.ts +105 -14
- package/dist/react-native/index.js +238 -55
- package/dist/react-native/index.js.map +1 -1
- package/dist/replay.d.ts +4 -1
- package/dist/replay.js +8 -2
- package/dist/replay.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.js +2 -0
- package/dist/server.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/dist/user-hash.d.ts +27 -0
- package/dist/user-hash.js +24 -0
- package/dist/user-hash.js.map +1 -0
- package/package.json +5 -1
package/dist/flows.d.ts
CHANGED
|
@@ -11,13 +11,16 @@
|
|
|
11
11
|
* `onCancel`, and only after they succeed is the outcome recorded.
|
|
12
12
|
* - `$onboarding` `{flow, step?, action: "started" | "shown" | "completed" | "dismissed"}`; since 0.11.0 a wait records
|
|
13
13
|
* "shown" when the person reaches it and "completed" when it is over, a condition `{action: "answered", answer: "yes"
|
|
14
|
-
* | "no"}` once it is decided.
|
|
14
|
+
* | "no"}` once it is decided; since 0.17.0 a tour a checklist task started records `{action: "started", from}` with
|
|
15
|
+
* the checklist's id.
|
|
15
16
|
* - `$inapp` `{message, journey, action: "shown" | "clicked" | "dismissed"}`; the journey moves the person on.
|
|
16
17
|
*/
|
|
17
18
|
import type { CockpitConfig } from "./core.js";
|
|
18
19
|
export declare const CANCEL_EVENT = "$cancel_flow";
|
|
19
20
|
export declare const ONBOARDING_EVENT = "$onboarding";
|
|
20
21
|
export declare const INAPP_EVENT = "$inapp";
|
|
22
|
+
/** 0.16.0: the app asked the store's rating dialog for a review request (or found none on the device). */
|
|
23
|
+
export declare const REVIEW_EVENT = "$review_prompt";
|
|
21
24
|
export type CancelOfferKind = "discount" | "pause" | "downgrade" | "contact";
|
|
22
25
|
/** What one answer of the survey offers before the confirmation. An answer without one goes straight to it. */
|
|
23
26
|
export interface CancelOffer {
|
|
@@ -84,6 +87,17 @@ export interface CancelFlowConfig {
|
|
|
84
87
|
offersFor: "business";
|
|
85
88
|
}
|
|
86
89
|
export type OnboardingStepKind = "tour" | "checklist" | "modal";
|
|
90
|
+
/** 0.17.0: where a tour bubble sits next to its element; "auto" (and no value) puts it below, else above, as before. */
|
|
91
|
+
export type TourPlacement = "auto" | "top" | "bottom" | "left" | "right";
|
|
92
|
+
/**
|
|
93
|
+
* 0.17.0: a picture or a video above a tour step's or a modal's text. A video is a YouTube, Vimeo or Loom link (shown
|
|
94
|
+
* through their privacy-friendly players, see `videoEmbed`) or a video file (mp4, webm).
|
|
95
|
+
*/
|
|
96
|
+
export interface FlowMedia {
|
|
97
|
+
kind: "image" | "video";
|
|
98
|
+
url: string;
|
|
99
|
+
alt?: string;
|
|
100
|
+
}
|
|
87
101
|
export interface OnboardingStep {
|
|
88
102
|
id: string;
|
|
89
103
|
kind: OnboardingStepKind;
|
|
@@ -94,6 +108,14 @@ export interface OnboardingStep {
|
|
|
94
108
|
target?: string;
|
|
95
109
|
/** Checklist items: the event that ticks them (`track("<event>")`). Without it the person ticks it themselves. */
|
|
96
110
|
event?: string;
|
|
111
|
+
/** 0.17.0, tour steps: which side of the element the bubble takes (flips when there is no room). */
|
|
112
|
+
placement?: TourPlacement;
|
|
113
|
+
/** 0.17.0, tour steps and modals: a picture or a video above the text. */
|
|
114
|
+
media?: FlowMedia;
|
|
115
|
+
/** 0.17.0, modals: where the button goes (http(s) or a path of the app). */
|
|
116
|
+
url?: string;
|
|
117
|
+
/** 0.17.0, checklist items: the id of a tour (another flow) the item starts; finishing the tour ticks the item. */
|
|
118
|
+
startsTour?: string;
|
|
97
119
|
}
|
|
98
120
|
/** A pause in a flow (0.11.0): the next step shows this long after the one before was done. */
|
|
99
121
|
export interface OnboardingWait {
|
|
@@ -119,9 +141,15 @@ export type OnboardingNode = OnboardingStep | OnboardingWait | OnboardingConditi
|
|
|
119
141
|
/** A live onboarding flow's in-app steps (MRRocket › Conversion › Onboarding); its emails go out from MRRocket. */
|
|
120
142
|
export interface OnboardingFlow {
|
|
121
143
|
id: string;
|
|
144
|
+
/** A checklist's heading; for tours and modals the name MRRocket knows them by. */
|
|
122
145
|
name: string;
|
|
123
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* When it starts: an event's words ("Signed up", "First export"), "First launch" / "First visit", since 0.17.0 a page
|
|
148
|
+
* of the app ("/settings", "/projects/*"), or "From a checklist" (only a checklist task starts it).
|
|
149
|
+
*/
|
|
124
150
|
trigger: string;
|
|
151
|
+
/** 0.17.0: "signed_in" starts it on its own only for someone the app identified. */
|
|
152
|
+
audience?: "signed_in";
|
|
125
153
|
/** What every version shows: with `nodes`, only the in-app steps before the first wait or condition. */
|
|
126
154
|
steps: OnboardingStep[];
|
|
127
155
|
/** 0.11.0+: the whole flow with its waits and conditions. Read instead of `steps` when it is there. */
|
|
@@ -155,6 +183,14 @@ export interface InAppState {
|
|
|
155
183
|
messages: InAppMessage[];
|
|
156
184
|
/** 0.11.0: the events the flows' conditions ask about that this person did (as `eventSlug`s). */
|
|
157
185
|
events?: string[];
|
|
186
|
+
/**
|
|
187
|
+
* 0.16.0: a live review request may ask this person now. The React Native client's `requestReview()` opens the
|
|
188
|
+
* store's own rating dialog (expo-store-review) and reports `$review_prompt`; websites have no store dialog.
|
|
189
|
+
*/
|
|
190
|
+
review?: {
|
|
191
|
+
campaign: string;
|
|
192
|
+
store: string;
|
|
193
|
+
};
|
|
158
194
|
}
|
|
159
195
|
export interface CancelFlowResult {
|
|
160
196
|
/** "cancelled": confirmed; "saved": took the offer; "kept": closed the dialog without cancelling. */
|
|
@@ -218,12 +254,15 @@ export type FlowView = {
|
|
|
218
254
|
index: number;
|
|
219
255
|
total: number;
|
|
220
256
|
last: boolean;
|
|
221
|
-
}
|
|
257
|
+
}
|
|
258
|
+
/** `tour`: the tour the item starts (0.17.0), when the config has it. */
|
|
259
|
+
| {
|
|
222
260
|
type: "checklist";
|
|
223
261
|
flow: OnboardingFlow;
|
|
224
262
|
items: {
|
|
225
263
|
step: OnboardingStep;
|
|
226
264
|
done: boolean;
|
|
265
|
+
tour?: OnboardingFlow;
|
|
227
266
|
}[];
|
|
228
267
|
} | {
|
|
229
268
|
type: "message";
|
|
@@ -272,10 +311,12 @@ export interface FlowsController {
|
|
|
272
311
|
confirm(comment?: string): void;
|
|
273
312
|
close(): void;
|
|
274
313
|
};
|
|
314
|
+
/** `startTour(stepId)` (0.17.0): the tour a checklist item starts; the checklist comes back when it ends. */
|
|
275
315
|
onboarding: {
|
|
276
316
|
next(): void;
|
|
277
317
|
check(stepId: string): void;
|
|
278
318
|
dismiss(): void;
|
|
319
|
+
startTour(stepId: string): boolean;
|
|
279
320
|
};
|
|
280
321
|
message: {
|
|
281
322
|
click(): void;
|
|
@@ -290,6 +331,21 @@ export declare const eventSlug: (s: string) => string;
|
|
|
290
331
|
export declare const matchesTrigger: (trigger: string, event: string) => boolean;
|
|
291
332
|
/** Triggers that mean "the first time the person opens the app": the flow starts on load until it is done. */
|
|
292
333
|
export declare const startsOnLoad: (trigger: string) => boolean;
|
|
334
|
+
/** 0.17.0: the trigger of a tour only a checklist task starts. */
|
|
335
|
+
export declare const FROM_CHECKLIST = "From a checklist";
|
|
336
|
+
/** 0.17.0: a trigger that is a page of the app ("/settings", "/projects/*"): the flow starts when the person opens it. */
|
|
337
|
+
export declare const isPageTrigger: (trigger: string) => boolean;
|
|
338
|
+
/**
|
|
339
|
+
* 0.17.0: how a video link plays. YouTube, Vimeo and Loom through their players without tracking cookies
|
|
340
|
+
* (youtube-nocookie.com, Vimeo's `dnt=1`), a file (mp4, webm, mov, or an upload in MRRocket) in a plain video element;
|
|
341
|
+
* anything else is not shown. Regular expressions only, so React Native can use it too.
|
|
342
|
+
*/
|
|
343
|
+
export declare const videoEmbed: (url: string | undefined) => {
|
|
344
|
+
kind: "iframe" | "file";
|
|
345
|
+
src: string;
|
|
346
|
+
} | null;
|
|
347
|
+
/** 0.17.0: a step's picture or video when the dialogs may load it (http(s), a video they can play), else undefined. */
|
|
348
|
+
export declare const mediaOf: (step: Pick<OnboardingStep, "media">) => FlowMedia | undefined;
|
|
293
349
|
/** A random id for one cancel flow run. */
|
|
294
350
|
export declare const runId: () => string;
|
|
295
351
|
/** The money a discount leaves: `29 EUR` at 30 % → `20.30`. */
|
package/dist/flows.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
var CANCEL_EVENT = "$cancel_flow";
|
|
3
3
|
var ONBOARDING_EVENT = "$onboarding";
|
|
4
4
|
var INAPP_EVENT = "$inapp";
|
|
5
|
+
var REVIEW_EVENT = "$review_prompt";
|
|
5
6
|
var PLAIN_CANCEL = {
|
|
6
7
|
version: 0,
|
|
7
8
|
question: "",
|
|
@@ -21,6 +22,26 @@ var matchesTrigger = (trigger, event) => {
|
|
|
21
22
|
return t === e || SIGNUP.has(t) && SIGNUP.has(e);
|
|
22
23
|
};
|
|
23
24
|
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
|
+
var FROM_CHECKLIST = "From a checklist";
|
|
26
|
+
var isPageTrigger = (trigger) => trigger.trim().startsWith("/");
|
|
27
|
+
var manual = (trigger) => eventSlug(trigger) === "from_a_checklist";
|
|
28
|
+
var videoEmbed = (url) => {
|
|
29
|
+
const u = (url ?? "").trim();
|
|
30
|
+
if (!/^https?:\/\//i.test(u)) return null;
|
|
31
|
+
let m = u.match(/^https?:\/\/(?:www\.|m\.)?(?:youtube\.com\/(?:watch\?(?:.*&)?v=|embed\/|shorts\/|live\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)([\w-]{6,20})/i);
|
|
32
|
+
if (m) return { kind: "iframe", src: `https://www.youtube-nocookie.com/embed/${m[1]}?rel=0` };
|
|
33
|
+
m = u.match(/^https?:\/\/(?:www\.|player\.)?vimeo\.com\/(?:video\/)?(\d{4,12})/i);
|
|
34
|
+
if (m) return { kind: "iframe", src: `https://player.vimeo.com/video/${m[1]}?dnt=1` };
|
|
35
|
+
m = u.match(/^https?:\/\/(?:www\.)?loom\.com\/(?:share|embed)\/([\w-]{8,64})/i);
|
|
36
|
+
if (m) return { kind: "iframe", src: `https://www.loom.com/embed/${m[1]}` };
|
|
37
|
+
if (/\.(mp4|webm|mov|m4v)(\?|#|$)/i.test(u) || /\/media\/uploads\//.test(u)) return { kind: "file", src: u };
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
var mediaOf = (step) => {
|
|
41
|
+
const m = step.media;
|
|
42
|
+
if (!m || m.kind !== "image" && m.kind !== "video" || !/^https?:\/\//i.test(m.url ?? "")) return void 0;
|
|
43
|
+
return m.kind === "video" && !videoEmbed(m.url) ? void 0 : m;
|
|
44
|
+
};
|
|
24
45
|
var runId = () => `cf_${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;
|
|
25
46
|
var discounted = (amount, percent) => Math.round(amount * (1 - percent / 100) * 100) / 100;
|
|
26
47
|
var money = (amount, currency) => {
|
|
@@ -68,6 +89,7 @@ var createFlows = (env) => {
|
|
|
68
89
|
const seenEvents = /* @__PURE__ */ new Set();
|
|
69
90
|
const now = () => env.now?.() ?? Date.now();
|
|
70
91
|
let timer = null;
|
|
92
|
+
let returnTo = null;
|
|
71
93
|
const flows = () => config?.onboarding ?? [];
|
|
72
94
|
const flowById = (id) => id ? flows().find((f) => f.id === id) : void 0;
|
|
73
95
|
const prog = (id) => {
|
|
@@ -205,7 +227,14 @@ var createFlows = (env) => {
|
|
|
205
227
|
shown.add(`s:${i.id}`);
|
|
206
228
|
env.track(ONBOARDING_EVENT, { flow: flow.id, step: i.id, kind: "checklist", action: "shown" });
|
|
207
229
|
}
|
|
208
|
-
return {
|
|
230
|
+
return {
|
|
231
|
+
type: "checklist",
|
|
232
|
+
flow,
|
|
233
|
+
items: items.map((s) => {
|
|
234
|
+
const tour = s.startsTour && s.startsTour !== flow.id ? flowById(s.startsTour) : void 0;
|
|
235
|
+
return { step: s, done: p.done.has(s.id), ...tour && nodesOf(tour).length ? { tour } : {} };
|
|
236
|
+
})
|
|
237
|
+
};
|
|
209
238
|
}
|
|
210
239
|
if (!shown.has(`s:${step.id}`)) {
|
|
211
240
|
shown.add(`s:${step.id}`);
|
|
@@ -239,7 +268,28 @@ var createFlows = (env) => {
|
|
|
239
268
|
}
|
|
240
269
|
const ob = onboardingView();
|
|
241
270
|
if (ob) return ob;
|
|
242
|
-
if (active && !holding)
|
|
271
|
+
if (active && !holding) {
|
|
272
|
+
const back = returnTo;
|
|
273
|
+
const ended = active;
|
|
274
|
+
returnTo = null;
|
|
275
|
+
active = null;
|
|
276
|
+
const list = back ? flowById(back.flow) : void 0;
|
|
277
|
+
if (back && list) {
|
|
278
|
+
const item = stepsIn(nodesOf(list)).find((s) => s.id === back.step);
|
|
279
|
+
const p = prog(list.id);
|
|
280
|
+
if (item && !item.event && !progress.get(ended)?.dismissed && !p.done.has(item.id)) {
|
|
281
|
+
markDone(p, item.id);
|
|
282
|
+
record({ flow: list.id, step: item.id, kind: "checklist", action: "completed" });
|
|
283
|
+
}
|
|
284
|
+
active = list.id;
|
|
285
|
+
const again = onboardingView();
|
|
286
|
+
if (again) return again;
|
|
287
|
+
if (!holding) active = null;
|
|
288
|
+
} else if (known) {
|
|
289
|
+
const after = flowById(ended)?.trigger;
|
|
290
|
+
Promise.resolve().then(() => autoStart(after));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
243
293
|
const m = messages.find((x) => !handled.has(x.id));
|
|
244
294
|
return m ? { type: "message", message: m } : null;
|
|
245
295
|
};
|
|
@@ -264,10 +314,15 @@ var createFlows = (env) => {
|
|
|
264
314
|
emit();
|
|
265
315
|
return true;
|
|
266
316
|
};
|
|
267
|
-
const
|
|
317
|
+
const allowed = (f) => f.audience !== "signed_in" || !!env.personId();
|
|
318
|
+
const autoStart = (after) => {
|
|
268
319
|
if (!auto || active || !known) return;
|
|
269
320
|
if (!env.personId() && !env.storage?.()) return;
|
|
270
|
-
const
|
|
321
|
+
const path = env.path?.();
|
|
322
|
+
const same = after && !manual(after) ? eventSlug(after) : "";
|
|
323
|
+
const next = flows().find(
|
|
324
|
+
(f) => (isPageTrigger(f.trigger) ? path !== void 0 && pageMatches(f.trigger, path) : startsOnLoad(f.trigger) || !!same && eventSlug(f.trigger) === same) && allowed(f) && nodesOf(f).length && !finished(f)
|
|
325
|
+
);
|
|
271
326
|
if (next) start(next);
|
|
272
327
|
};
|
|
273
328
|
const refresh = () => {
|
|
@@ -277,6 +332,7 @@ var createFlows = (env) => {
|
|
|
277
332
|
seenEvents.clear();
|
|
278
333
|
handled.clear();
|
|
279
334
|
active = null;
|
|
335
|
+
returnTo = null;
|
|
280
336
|
loadedFor = void 0;
|
|
281
337
|
}
|
|
282
338
|
progressFor = pid;
|
|
@@ -386,6 +442,7 @@ var createFlows = (env) => {
|
|
|
386
442
|
},
|
|
387
443
|
refresh,
|
|
388
444
|
onEvent: (name) => {
|
|
445
|
+
if (name === "$pageview") autoStart();
|
|
389
446
|
if (!name || name.startsWith("$")) return;
|
|
390
447
|
const slug = eventSlug(name);
|
|
391
448
|
const fresh = !!slug && !seenEvents.has(slug);
|
|
@@ -406,12 +463,12 @@ var createFlows = (env) => {
|
|
|
406
463
|
emit();
|
|
407
464
|
} else if (fresh) save();
|
|
408
465
|
if (!auto || !env.personId() && !env.storage?.()) return;
|
|
409
|
-
const next = flows().find((f) => nodesOf(f).length && matchesTrigger(f.trigger, name) && !finished(f));
|
|
466
|
+
const next = flows().find((f) => nodesOf(f).length && !manual(f.trigger) && matchesTrigger(f.trigger, name) && allowed(f) && !finished(f));
|
|
410
467
|
if (next) start(next);
|
|
411
468
|
},
|
|
412
469
|
openCancelFlow,
|
|
413
470
|
startOnboarding: (id) => {
|
|
414
|
-
const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !finished(x));
|
|
471
|
+
const f = id ? flowById(id) : flows().find((x) => nodesOf(x).length && !manual(x.trigger) && !finished(x));
|
|
415
472
|
if (!f || !nodesOf(f).length) return false;
|
|
416
473
|
const p = prog(f.id);
|
|
417
474
|
p.dismissed = false;
|
|
@@ -507,6 +564,8 @@ var createFlows = (env) => {
|
|
|
507
564
|
env.track(ONBOARDING_EVENT, { flow: v.flow.id, step: v.step.id, kind: v.step.kind, action: "completed" });
|
|
508
565
|
save();
|
|
509
566
|
emit();
|
|
567
|
+
const url = v.step.kind === "modal" ? safeUrl(v.step.url) : void 0;
|
|
568
|
+
if (url) env.openUrl?.(url);
|
|
510
569
|
},
|
|
511
570
|
check: (stepId) => {
|
|
512
571
|
const v = onboardingView();
|
|
@@ -523,9 +582,26 @@ var createFlows = (env) => {
|
|
|
523
582
|
if (!v || v.type !== "step" && v.type !== "checklist") return;
|
|
524
583
|
prog(v.flow.id).dismissed = true;
|
|
525
584
|
env.track(ONBOARDING_EVENT, { flow: v.flow.id, ...v.type === "step" ? { step: v.step.id } : {}, action: "dismissed" });
|
|
526
|
-
active = null;
|
|
585
|
+
active = returnTo && returnTo.flow !== v.flow.id && flowById(returnTo.flow) ? returnTo.flow : null;
|
|
586
|
+
returnTo = null;
|
|
587
|
+
save();
|
|
588
|
+
emit();
|
|
589
|
+
},
|
|
590
|
+
startTour: (stepId) => {
|
|
591
|
+
const v = onboardingView();
|
|
592
|
+
if (v?.type !== "checklist") return false;
|
|
593
|
+
const tour = v.items.find((i) => i.step.id === stepId)?.tour;
|
|
594
|
+
if (!tour) return false;
|
|
595
|
+
const p = prog(tour.id);
|
|
596
|
+
p.done.clear();
|
|
597
|
+
p.at.clear();
|
|
598
|
+
p.dismissed = false;
|
|
599
|
+
returnTo = { flow: v.flow.id, step: stepId };
|
|
600
|
+
active = tour.id;
|
|
601
|
+
env.track(ONBOARDING_EVENT, { flow: tour.id, action: "started", from: v.flow.id });
|
|
527
602
|
save();
|
|
528
603
|
emit();
|
|
604
|
+
return true;
|
|
529
605
|
}
|
|
530
606
|
},
|
|
531
607
|
message: {
|
|
@@ -551,13 +627,17 @@ var createFlows = (env) => {
|
|
|
551
627
|
};
|
|
552
628
|
export {
|
|
553
629
|
CANCEL_EVENT,
|
|
630
|
+
FROM_CHECKLIST,
|
|
554
631
|
INAPP_EVENT,
|
|
555
632
|
ONBOARDING_EVENT,
|
|
556
633
|
PLAIN_CANCEL,
|
|
634
|
+
REVIEW_EVENT,
|
|
557
635
|
createFlows,
|
|
558
636
|
discounted,
|
|
559
637
|
eventSlug,
|
|
638
|
+
isPageTrigger,
|
|
560
639
|
matchesTrigger,
|
|
640
|
+
mediaOf,
|
|
561
641
|
money,
|
|
562
642
|
monthsSince,
|
|
563
643
|
nodesOf,
|
|
@@ -567,6 +647,7 @@ export {
|
|
|
567
647
|
runId,
|
|
568
648
|
safeUrl,
|
|
569
649
|
startsOnLoad,
|
|
650
|
+
videoEmbed,
|
|
570
651
|
waitMs
|
|
571
652
|
};
|
|
572
653
|
//# sourceMappingURL=flows.js.map
|