@funnelsgrove/runtime 0.1.0 → 0.1.2
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/README.md +20 -1
- package/dist/components/FunnelContext.d.ts +5 -2
- package/dist/components/FunnelContext.js +3 -0
- package/dist/components/FunnelEditorPanel.d.ts +3 -5
- package/dist/components/FunnelEditorPanel.js +3 -3
- package/dist/components/ManageSubscriptionScreen.d.ts +51 -0
- package/dist/components/ManageSubscriptionScreen.js +349 -0
- package/dist/components/RuntimeDevInfoBox.d.ts +23 -0
- package/dist/components/RuntimeDevInfoBox.js +363 -0
- package/dist/components/SubscriptionHandoffScreen.d.ts +31 -0
- package/dist/components/SubscriptionHandoffScreen.js +338 -0
- package/dist/config/builder-preview.protocol.d.ts +73 -0
- package/dist/config/builder-preview.protocol.js +3 -0
- package/dist/config/env.config.d.ts +44 -0
- package/dist/config/env.config.js +161 -0
- package/dist/config/font-config.d.ts +14 -0
- package/dist/config/font-config.js +101 -0
- package/dist/config/funnel-theme.d.ts +61 -10
- package/dist/config/funnel-theme.js +355 -35
- package/dist/config/funnel.manifest.types.d.ts +13 -7
- package/dist/content/step-content.d.ts +130 -0
- package/dist/content/step-content.js +381 -0
- package/dist/index.d.ts +33 -21
- package/dist/index.js +33 -21
- package/dist/runtime/browser-helpers.d.ts +1 -0
- package/dist/runtime/browser-helpers.js +14 -0
- package/dist/runtime/experiment-assignment.d.ts +13 -4
- package/dist/runtime/experiment-assignment.js +9 -27
- package/dist/runtime/funnel-attribution.d.ts +18 -0
- package/dist/runtime/funnel-attribution.js +226 -0
- package/dist/runtime/funnel-flow.d.ts +9 -10
- package/dist/runtime/funnel-flow.js +4 -18
- package/dist/runtime/funnel-manifest.validation.d.ts +1 -1
- package/dist/runtime/funnel-manifest.validation.js +2 -6
- package/dist/runtime/funnel-runtime.d.ts +2 -3
- package/dist/runtime/funnel-runtime.js +6 -13
- package/dist/runtime/posthog-flags.d.ts +30 -0
- package/dist/runtime/posthog-flags.js +71 -0
- package/dist/runtime/preview-bridge.d.ts +12 -2
- package/dist/runtime/preview-bridge.js +95 -4
- package/dist/runtime/preview-definition-overrides.d.ts +20 -0
- package/dist/runtime/preview-definition-overrides.js +148 -0
- package/dist/runtime/route-resolver.d.ts +2 -3
- package/dist/runtime/route-resolver.js +15 -26
- package/dist/runtime/subscription-handoff.d.ts +32 -0
- package/dist/runtime/subscription-handoff.js +113 -0
- package/dist/runtime/use-funnel-flow-controller.d.ts +19 -10
- package/dist/runtime/use-funnel-flow-controller.js +190 -159
- package/dist/sdk/userAnswers.d.ts +2 -2
- package/dist/services/api.service.d.ts +21 -4
- package/dist/services/api.service.js +165 -35
- package/dist/services/funnel-state.service.d.ts +8 -0
- package/dist/services/funnel-state.service.js +44 -0
- package/dist/services/preview-frame.service.d.ts +2 -2
- package/dist/services/preview-frame.service.js +2 -2
- package/dist/services/public-env.d.ts +69 -0
- package/dist/services/public-env.js +105 -0
- package/dist/services/runtime-api.config.d.ts +5 -0
- package/dist/services/runtime-api.config.js +12 -7
- package/dist/services/runtime-mode.service.d.ts +3 -0
- package/dist/services/runtime-mode.service.js +142 -4
- package/package.json +8 -2
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export type RuntimeMode = 'test' | 'live';
|
|
2
|
+
export type FunnelMode = 'test' | 'production';
|
|
2
3
|
export declare const isEditorEnabled: () => boolean;
|
|
4
|
+
export declare const getFunnelMode: () => FunnelMode;
|
|
3
5
|
export declare const getRuntimeMode: () => RuntimeMode;
|
|
6
|
+
export declare const setFunnelMode: (mode: FunnelMode) => void;
|
|
4
7
|
export declare const setRuntimeMode: (mode: RuntimeMode) => void;
|
|
5
8
|
export declare const useRuntimeMode: () => [RuntimeMode, (mode: RuntimeMode) => void];
|
|
@@ -1,12 +1,48 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
const EDITOR_MODE_STORAGE_KEY = 'funnel:editor:mode';
|
|
4
|
+
const FUNNEL_MODE_STORAGE_KEY = 'funnel-mode';
|
|
5
|
+
const FUNNEL_MODE_COOKIE_NAME = 'funnel-mode';
|
|
4
6
|
const MODE_CHANGE_EVENT = 'funnel:editor-mode-changed';
|
|
7
|
+
const DEFAULT_FUNNEL_DOMAIN_SIGNAL = 'funnelsgrove';
|
|
8
|
+
const FUNNEL_MODE_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
5
9
|
const canUseDom = () => {
|
|
6
10
|
return typeof window !== 'undefined';
|
|
7
11
|
};
|
|
12
|
+
const toFunnelMode = (value) => {
|
|
13
|
+
if (typeof value !== 'string') {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const normalized = value.trim().toLowerCase();
|
|
17
|
+
if (normalized === 'test') {
|
|
18
|
+
return 'test';
|
|
19
|
+
}
|
|
20
|
+
if (normalized === 'prod' || normalized === 'production' || normalized === 'live') {
|
|
21
|
+
return 'production';
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
8
25
|
const toRuntimeMode = (value) => {
|
|
9
|
-
return value === '
|
|
26
|
+
return toFunnelMode(value) === 'production' ? 'live' : 'test';
|
|
27
|
+
};
|
|
28
|
+
const toRuntimeModeFromFunnelMode = (mode) => {
|
|
29
|
+
return mode === 'production' ? 'live' : 'test';
|
|
30
|
+
};
|
|
31
|
+
const toFunnelModeFromRuntimeMode = (mode) => {
|
|
32
|
+
return mode === 'live' ? 'production' : 'test';
|
|
33
|
+
};
|
|
34
|
+
const normalizeHostname = (value) => {
|
|
35
|
+
return value.trim().toLowerCase().replace(/\.+$/, '');
|
|
36
|
+
};
|
|
37
|
+
const isDefaultPublishedDomain = () => {
|
|
38
|
+
if (!canUseDom()) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const hostname = normalizeHostname(window.location.hostname || '');
|
|
42
|
+
if (!hostname) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return hostname.includes(DEFAULT_FUNNEL_DOMAIN_SIGNAL);
|
|
10
46
|
};
|
|
11
47
|
export const isEditorEnabled = () => {
|
|
12
48
|
if (!canUseDom()) {
|
|
@@ -34,6 +70,79 @@ const readStoredEditorMode = () => {
|
|
|
34
70
|
return null;
|
|
35
71
|
}
|
|
36
72
|
};
|
|
73
|
+
const readCookieValue = (name) => {
|
|
74
|
+
if (typeof document === 'undefined') {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const target = `${encodeURIComponent(name)}=`;
|
|
79
|
+
const entry = document.cookie
|
|
80
|
+
.split(';')
|
|
81
|
+
.map((item) => item.trim())
|
|
82
|
+
.find((item) => item.startsWith(target));
|
|
83
|
+
return entry ? decodeURIComponent(entry.slice(target.length)) : null;
|
|
84
|
+
}
|
|
85
|
+
catch (_a) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const writeFunnelModeCookie = (mode) => {
|
|
90
|
+
if (typeof document === 'undefined') {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
document.cookie = [
|
|
95
|
+
`${encodeURIComponent(FUNNEL_MODE_COOKIE_NAME)}=${encodeURIComponent(mode)}`,
|
|
96
|
+
'Path=/',
|
|
97
|
+
`Max-Age=${FUNNEL_MODE_COOKIE_MAX_AGE_SECONDS}`,
|
|
98
|
+
'SameSite=Lax',
|
|
99
|
+
].join('; ');
|
|
100
|
+
}
|
|
101
|
+
catch (_a) {
|
|
102
|
+
// ignore cookie failures
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const readFunnelModeCookie = () => {
|
|
106
|
+
return toFunnelMode(readCookieValue(FUNNEL_MODE_COOKIE_NAME));
|
|
107
|
+
};
|
|
108
|
+
const readFunnelModeStorage = () => {
|
|
109
|
+
if (!canUseDom()) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
return toFunnelMode(window.localStorage.getItem(FUNNEL_MODE_STORAGE_KEY));
|
|
114
|
+
}
|
|
115
|
+
catch (_a) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const persistFunnelMode = (mode, options = {}) => {
|
|
120
|
+
if (!canUseDom()) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
window.localStorage.setItem(FUNNEL_MODE_STORAGE_KEY, mode);
|
|
125
|
+
}
|
|
126
|
+
catch (_a) {
|
|
127
|
+
// ignore storage failures
|
|
128
|
+
}
|
|
129
|
+
writeFunnelModeCookie(mode);
|
|
130
|
+
if (options.emit === false) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
emitModeChange(toRuntimeModeFromFunnelMode(mode));
|
|
134
|
+
};
|
|
135
|
+
const readQueryFunnelMode = () => {
|
|
136
|
+
if (!canUseDom()) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
return toFunnelMode(new URLSearchParams(window.location.search).get('mode'));
|
|
141
|
+
}
|
|
142
|
+
catch (_a) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
37
146
|
const emitModeChange = (mode) => {
|
|
38
147
|
if (!canUseDom()) {
|
|
39
148
|
return;
|
|
@@ -44,15 +153,44 @@ const emitModeChange = (mode) => {
|
|
|
44
153
|
},
|
|
45
154
|
}));
|
|
46
155
|
};
|
|
156
|
+
export const getFunnelMode = () => {
|
|
157
|
+
if (!canUseDom()) {
|
|
158
|
+
return 'production';
|
|
159
|
+
}
|
|
160
|
+
const queryMode = readQueryFunnelMode();
|
|
161
|
+
if (queryMode) {
|
|
162
|
+
persistFunnelMode(queryMode, { emit: false });
|
|
163
|
+
return queryMode;
|
|
164
|
+
}
|
|
165
|
+
const cookieMode = readFunnelModeCookie();
|
|
166
|
+
if (cookieMode) {
|
|
167
|
+
return cookieMode;
|
|
168
|
+
}
|
|
169
|
+
if (isDefaultPublishedDomain()) {
|
|
170
|
+
return 'test';
|
|
171
|
+
}
|
|
172
|
+
return readFunnelModeStorage() || 'production';
|
|
173
|
+
};
|
|
47
174
|
export const getRuntimeMode = () => {
|
|
48
175
|
if (!canUseDom()) {
|
|
49
176
|
return 'live';
|
|
50
177
|
}
|
|
178
|
+
const queryMode = readQueryFunnelMode();
|
|
179
|
+
if (queryMode) {
|
|
180
|
+
persistFunnelMode(queryMode, { emit: false });
|
|
181
|
+
return toRuntimeModeFromFunnelMode(queryMode);
|
|
182
|
+
}
|
|
51
183
|
if (!isEditorEnabled()) {
|
|
52
|
-
return
|
|
184
|
+
return toRuntimeModeFromFunnelMode(getFunnelMode());
|
|
53
185
|
}
|
|
54
186
|
return readStoredEditorMode() || 'test';
|
|
55
187
|
};
|
|
188
|
+
export const setFunnelMode = (mode) => {
|
|
189
|
+
if (!canUseDom()) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
persistFunnelMode(mode);
|
|
193
|
+
};
|
|
56
194
|
export const setRuntimeMode = (mode) => {
|
|
57
195
|
if (!canUseDom()) {
|
|
58
196
|
return;
|
|
@@ -64,7 +202,7 @@ export const setRuntimeMode = (mode) => {
|
|
|
64
202
|
catch (_a) {
|
|
65
203
|
// ignore storage failures
|
|
66
204
|
}
|
|
67
|
-
|
|
205
|
+
persistFunnelMode(toFunnelModeFromRuntimeMode(normalizedMode));
|
|
68
206
|
};
|
|
69
207
|
const subscribeRuntimeMode = (listener) => {
|
|
70
208
|
if (!canUseDom()) {
|
|
@@ -76,7 +214,7 @@ const subscribeRuntimeMode = (listener) => {
|
|
|
76
214
|
listener(toRuntimeMode((_a = customEvent.detail) === null || _a === void 0 ? void 0 : _a.mode));
|
|
77
215
|
};
|
|
78
216
|
const onStorageChanged = (event) => {
|
|
79
|
-
if (event.key !== EDITOR_MODE_STORAGE_KEY) {
|
|
217
|
+
if (event.key !== EDITOR_MODE_STORAGE_KEY && event.key !== FUNNEL_MODE_STORAGE_KEY) {
|
|
80
218
|
return;
|
|
81
219
|
}
|
|
82
220
|
listener(getRuntimeMode());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./config/env.config": {
|
|
16
|
+
"types": "./dist/config/env.config.d.ts",
|
|
17
|
+
"import": "./dist/config/env.config.js",
|
|
18
|
+
"default": "./dist/config/env.config.js"
|
|
14
19
|
}
|
|
15
20
|
},
|
|
16
21
|
"files": [
|
|
@@ -20,12 +25,13 @@
|
|
|
20
25
|
"access": "public"
|
|
21
26
|
},
|
|
22
27
|
"scripts": {
|
|
23
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
28
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/fix-esm-relative-imports.mjs dist",
|
|
24
29
|
"lint": "eslint .",
|
|
25
30
|
"prepublishOnly": "npm run build",
|
|
26
31
|
"test:run": "vitest run --passWithNoTests"
|
|
27
32
|
},
|
|
28
33
|
"dependencies": {
|
|
34
|
+
"posthog-js": "^1.369.2",
|
|
29
35
|
"react": "19.2.3",
|
|
30
36
|
"react-dom": "19.2.3"
|
|
31
37
|
},
|