@funnelsgrove/runtime 0.1.22 → 0.1.24
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/dist/runtime/funnel-flow.d.ts +2 -0
- package/dist/runtime/funnel-flow.js +1 -0
- package/dist/runtime/funnel-runtime.d.ts +1 -0
- package/dist/runtime/funnel-runtime.js +1 -0
- package/dist/runtime/route-resolver.d.ts +1 -0
- package/dist/runtime/route-resolver.js +1 -1
- package/dist/runtime/use-funnel-flow-controller.d.ts +1 -0
- package/dist/runtime/use-funnel-flow-controller.js +49 -13
- package/package.json +1 -1
|
@@ -15,8 +15,10 @@ export declare const resolveNextStepFromContext: <StepId extends string>(input:
|
|
|
15
15
|
resolveRenderableStepId: (stepId: string | null | undefined) => StepId | null;
|
|
16
16
|
getConfiguredNextStepId: (stepId: StepId, context: {
|
|
17
17
|
attributes: FunnelUserAnswers;
|
|
18
|
+
ignoreExperiment?: boolean;
|
|
18
19
|
resolveExperimentVariantKey: (experiment: FunnelManifestExperiment) => string | null;
|
|
19
20
|
}) => StepId | null;
|
|
20
21
|
getSequentialNextStepId: (stepId: StepId) => StepId | null;
|
|
22
|
+
ignoreExperiment?: boolean;
|
|
21
23
|
resolveExperimentVariantKey: (experiment: FunnelManifestExperiment) => string | null;
|
|
22
24
|
}) => StepId;
|
|
@@ -43,6 +43,7 @@ export const resolveNextStepFromContext = (input) => {
|
|
|
43
43
|
var _a, _b;
|
|
44
44
|
const configuredStepId = input.getConfiguredNextStepId(input.stepId, {
|
|
45
45
|
attributes: input.attributes,
|
|
46
|
+
ignoreExperiment: input.ignoreExperiment,
|
|
46
47
|
resolveExperimentVariantKey: input.resolveExperimentVariantKey,
|
|
47
48
|
});
|
|
48
49
|
if (configuredStepId) {
|
|
@@ -29,5 +29,6 @@ export declare const resolveRuntimeInitialStepId: (input: {
|
|
|
29
29
|
}) => FunnelStepId;
|
|
30
30
|
export declare const resolveConfiguredNextStep: (manifest: FunnelManifest, stepId: FunnelStepId, context: {
|
|
31
31
|
attributes: Record<string, unknown>;
|
|
32
|
+
ignoreExperiment?: boolean;
|
|
32
33
|
resolveExperimentVariantKey: (experiment: FunnelManifestExperiment) => string | null;
|
|
33
34
|
}) => FunnelStepId | null;
|
|
@@ -60,6 +60,7 @@ export const resolveConfiguredNextStep = (manifest, stepId, context) => {
|
|
|
60
60
|
manifest,
|
|
61
61
|
currentStepId: stepId,
|
|
62
62
|
attributes: context.attributes,
|
|
63
|
+
ignoreExperiment: context.ignoreExperiment,
|
|
63
64
|
resolveExperimentVariantKey: context.resolveExperimentVariantKey,
|
|
64
65
|
});
|
|
65
66
|
return nextStepId && isManifestStepId(manifest, nextStepId) && getIsFunnelStepId(manifest, nextStepId)
|
|
@@ -13,5 +13,6 @@ export declare const resolveNextStepId: (input: {
|
|
|
13
13
|
manifest: FunnelManifest;
|
|
14
14
|
currentStepId: string;
|
|
15
15
|
attributes: Record<string, unknown>;
|
|
16
|
+
ignoreExperiment?: boolean;
|
|
16
17
|
resolveExperimentVariantKey: (experiment: FunnelManifestExperiment) => string | null;
|
|
17
18
|
}) => string | null;
|
|
@@ -65,7 +65,7 @@ export const resolveInitialStepId = (input) => {
|
|
|
65
65
|
export const resolveNextStepId = (input) => {
|
|
66
66
|
var _a;
|
|
67
67
|
const experiment = getExperimentForStep(input.manifest, input.currentStepId);
|
|
68
|
-
if (experiment) {
|
|
68
|
+
if (experiment && !input.ignoreExperiment) {
|
|
69
69
|
const variantKey = input.resolveExperimentVariantKey(experiment);
|
|
70
70
|
const matchedVariant = variantKey
|
|
71
71
|
? experiment.variants.find((variant) => variant.variantKey === variantKey)
|
|
@@ -36,6 +36,7 @@ type UseFunnelFlowControllerInput<StepId extends string> = {
|
|
|
36
36
|
isFunnelStepId: (value: string) => value is StepId;
|
|
37
37
|
resolveConfiguredNextStep: (stepId: StepId, context: {
|
|
38
38
|
attributes: Record<string, unknown>;
|
|
39
|
+
ignoreExperiment?: boolean;
|
|
39
40
|
resolveExperimentVariantKey: (experiment: FunnelManifestExperiment) => string | null;
|
|
40
41
|
}) => StepId | null;
|
|
41
42
|
resolveRuntimeInitialStepId: (input: {
|
|
@@ -130,14 +130,14 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
130
130
|
}
|
|
131
131
|
return (_a = resolveExperimentVariant(experiment.experimentId)) !== null && _a !== void 0 ? _a : null;
|
|
132
132
|
}, [editorVariantOverrides, postHogReady]);
|
|
133
|
+
const activeExperimentForStep = useMemo(() => funnelExperiments.find((candidate) => candidate.stepId === safeActiveStepId) || null, [funnelExperiments, safeActiveStepId]);
|
|
133
134
|
const renderedStepId = useMemo(() => {
|
|
134
|
-
|
|
135
|
-
if (!experiment) {
|
|
135
|
+
if (!activeExperimentForStep) {
|
|
136
136
|
return safeActiveStepId;
|
|
137
137
|
}
|
|
138
|
-
const override = editorVariantOverrides[
|
|
138
|
+
const override = editorVariantOverrides[activeExperimentForStep.experimentId];
|
|
139
139
|
if (override) {
|
|
140
|
-
const matchedVariant =
|
|
140
|
+
const matchedVariant = activeExperimentForStep.variants.find((variant) => variant.variantKey === override);
|
|
141
141
|
const variantStepId = resolveRenderableStepId((matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.routeToStepId) || null);
|
|
142
142
|
return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
|
|
143
143
|
}
|
|
@@ -145,15 +145,15 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
145
145
|
return safeActiveStepId;
|
|
146
146
|
}
|
|
147
147
|
const assignment = resolveExperimentAssignment({
|
|
148
|
-
experimentId:
|
|
149
|
-
variants:
|
|
148
|
+
experimentId: activeExperimentForStep.experimentId,
|
|
149
|
+
variants: activeExperimentForStep.variants,
|
|
150
150
|
});
|
|
151
151
|
if (!assignment) {
|
|
152
152
|
return safeActiveStepId;
|
|
153
153
|
}
|
|
154
154
|
const variantStepId = resolveRenderableStepId(assignment.routeToStepId);
|
|
155
155
|
return variantStepId !== null && variantStepId !== void 0 ? variantStepId : safeActiveStepId;
|
|
156
|
-
}, [
|
|
156
|
+
}, [activeExperimentForStep, editorVariantOverrides, postHogReady, resolveRenderableStepId, safeActiveStepId]);
|
|
157
157
|
const renderedStepMeta = stepById[renderedStepId];
|
|
158
158
|
const activeStepComponent = stepComponentById[renderedStepId];
|
|
159
159
|
const postHogFeatureFlags = useMemo(() => {
|
|
@@ -188,6 +188,22 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
188
188
|
}
|
|
189
189
|
setActiveStepId(safeStepId);
|
|
190
190
|
}, [getPathForStep, resolveRenderableStepId, safeInitialStepId, shouldLockToInitialStep]);
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (!activeExperimentForStep ||
|
|
193
|
+
renderSuspended ||
|
|
194
|
+
shouldLockToInitialStep ||
|
|
195
|
+
renderedStepId === safeActiveStepId) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
goToStep(renderedStepId);
|
|
199
|
+
}, [
|
|
200
|
+
activeExperimentForStep,
|
|
201
|
+
goToStep,
|
|
202
|
+
renderSuspended,
|
|
203
|
+
renderedStepId,
|
|
204
|
+
safeActiveStepId,
|
|
205
|
+
shouldLockToInitialStep,
|
|
206
|
+
]);
|
|
191
207
|
const setAnswer = useCallback((key, value) => {
|
|
192
208
|
setAttributes((prev) => (Object.assign(Object.assign({}, prev), { [key]: value })));
|
|
193
209
|
}, []);
|
|
@@ -222,7 +238,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
222
238
|
}, 100);
|
|
223
239
|
return () => window.clearInterval(intervalId);
|
|
224
240
|
}, [postHogReady]);
|
|
225
|
-
const resolveNextStepId = useCallback((stepId) => {
|
|
241
|
+
const resolveNextStepId = useCallback((stepId, options) => {
|
|
226
242
|
return resolveNextStepFromContext({
|
|
227
243
|
stepId,
|
|
228
244
|
attributes: attributesRef.current,
|
|
@@ -230,6 +246,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
230
246
|
resolveRenderableStepId,
|
|
231
247
|
getConfiguredNextStepId: (currentStepId, context) => resolveConfiguredNextStep(currentStepId, context),
|
|
232
248
|
getSequentialNextStepId,
|
|
249
|
+
ignoreExperiment: options === null || options === void 0 ? void 0 : options.ignoreExperiment,
|
|
233
250
|
resolveExperimentVariantKey,
|
|
234
251
|
});
|
|
235
252
|
}, [
|
|
@@ -240,8 +257,10 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
240
257
|
safeInitialStepId,
|
|
241
258
|
]);
|
|
242
259
|
const goNext = useCallback(() => {
|
|
243
|
-
goToStep(resolveNextStepId(
|
|
244
|
-
|
|
260
|
+
goToStep(resolveNextStepId(renderedStepId, {
|
|
261
|
+
ignoreExperiment: Boolean(activeExperimentForStep && renderedStepId === safeActiveStepId),
|
|
262
|
+
}));
|
|
263
|
+
}, [activeExperimentForStep, goToStep, renderedStepId, resolveNextStepId, safeActiveStepId]);
|
|
245
264
|
useEffect(() => {
|
|
246
265
|
const localUserId = apiService.getOrCreateClientUserId();
|
|
247
266
|
const urlUserAttributes = resolveUrlUserAttributes();
|
|
@@ -383,6 +402,9 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
383
402
|
return;
|
|
384
403
|
}
|
|
385
404
|
const prevId = prevStepIdRef.current;
|
|
405
|
+
if (prevId === renderedStepId) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
386
408
|
if (prevId && prevId !== renderedStepId) {
|
|
387
409
|
recordStepCompletion(prevId);
|
|
388
410
|
}
|
|
@@ -476,19 +498,22 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
476
498
|
return () => window.removeEventListener('popstate', syncStepWithPath);
|
|
477
499
|
}, [getStepIdFromPath, resolveRenderableStepId, safeInitialStepId, shouldLockToInitialStep]);
|
|
478
500
|
const nextStepId = useMemo(() => resolveNextStepFromContext({
|
|
479
|
-
stepId:
|
|
501
|
+
stepId: renderedStepId,
|
|
480
502
|
attributes,
|
|
481
503
|
safeInitialStepId,
|
|
482
504
|
resolveRenderableStepId,
|
|
483
505
|
getConfiguredNextStepId: (currentStepId, context) => resolveConfiguredNextStep(currentStepId, context),
|
|
484
506
|
getSequentialNextStepId,
|
|
507
|
+
ignoreExperiment: Boolean(activeExperimentForStep && renderedStepId === safeActiveStepId),
|
|
485
508
|
resolveExperimentVariantKey,
|
|
486
509
|
}), [
|
|
510
|
+
activeExperimentForStep,
|
|
487
511
|
attributes,
|
|
488
512
|
getSequentialNextStepId,
|
|
489
513
|
resolveConfiguredNextStep,
|
|
490
514
|
resolveExperimentVariantKey,
|
|
491
515
|
resolveRenderableStepId,
|
|
516
|
+
renderedStepId,
|
|
492
517
|
safeActiveStepId,
|
|
493
518
|
safeInitialStepId,
|
|
494
519
|
]);
|
|
@@ -503,12 +528,23 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
|
|
|
503
528
|
if (!shouldRunAutoAdvanceTimer({ autoAdvanceMs, isPreviewRuntime, shouldLockToInitialStep })) {
|
|
504
529
|
return;
|
|
505
530
|
}
|
|
506
|
-
const autoAdvanceTarget = resolveNextStepId(
|
|
531
|
+
const autoAdvanceTarget = resolveNextStepId(renderedStepId, {
|
|
532
|
+
ignoreExperiment: Boolean(activeExperimentForStep && renderedStepId === safeActiveStepId),
|
|
533
|
+
});
|
|
507
534
|
const timer = window.setTimeout(() => {
|
|
508
535
|
goToStep(autoAdvanceTarget);
|
|
509
536
|
}, autoAdvanceMs);
|
|
510
537
|
return () => window.clearTimeout(timer);
|
|
511
|
-
}, [
|
|
538
|
+
}, [
|
|
539
|
+
activeExperimentForStep,
|
|
540
|
+
autoAdvanceMs,
|
|
541
|
+
goToStep,
|
|
542
|
+
isPreviewRuntime,
|
|
543
|
+
renderedStepId,
|
|
544
|
+
resolveNextStepId,
|
|
545
|
+
safeActiveStepId,
|
|
546
|
+
shouldLockToInitialStep,
|
|
547
|
+
]);
|
|
512
548
|
const handleContinue = useCallback(() => {
|
|
513
549
|
goToStep(nextStepId);
|
|
514
550
|
}, [goToStep, nextStepId]);
|