@appfunnel-dev/sdk 0.13.0 → 0.15.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/dist/{chunk-CMVB7RQE.js → chunk-7JLCKTX6.js} +3 -3
- package/dist/{chunk-CMVB7RQE.js.map → chunk-7JLCKTX6.js.map} +1 -1
- package/dist/{chunk-EB5VWGR4.js → chunk-H5C2QJIY.js} +158 -167
- package/dist/chunk-H5C2QJIY.js.map +1 -0
- package/dist/{chunk-QG6CE7L7.cjs → chunk-JHR65SVV.cjs} +6 -6
- package/dist/{chunk-QG6CE7L7.cjs.map → chunk-JHR65SVV.cjs.map} +1 -1
- package/dist/{chunk-KEFKKBBP.cjs → chunk-OTBIW5DN.cjs} +157 -166
- package/dist/chunk-OTBIW5DN.cjs.map +1 -0
- package/dist/elements/index.cjs +6 -6
- package/dist/elements/index.js +2 -2
- package/dist/index.cjs +31 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/{internal-twwb8xjX.d.cts → internal-BBWDTB-l.d.cts} +1 -1
- package/dist/{internal-twwb8xjX.d.ts → internal-BBWDTB-l.d.ts} +1 -1
- package/dist/internal.cjs +2 -2
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EB5VWGR4.js.map +0 -1
- package/dist/chunk-KEFKKBBP.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useFunnelContext } from './chunk-
|
|
1
|
+
import { useFunnelContext } from './chunk-H5C2QJIY.js';
|
|
2
2
|
import { useCallback, useSyncExternalStore, useMemo } from 'react';
|
|
3
3
|
|
|
4
4
|
function useResponse(key) {
|
|
@@ -100,5 +100,5 @@ function useNavigation() {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export { useNavigation, useResponse, useResponses };
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
104
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-7JLCKTX6.js.map
|
|
104
|
+
//# sourceMappingURL=chunk-7JLCKTX6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useResponse.ts","../src/hooks/useNavigation.ts"],"names":["useSyncExternalStore","useCallback"],"mappings":";;;AAYO,SAAS,YACd,GAAA,EACyB;AACzB,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,gBAAA,EAAiB;AAC3C,EAAA,MAAM,WAAA,GAAc,WAAW,GAAG,CAAA,CAAA;AAElC,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,EAAA,KAAmB,aAAA,CAAc,SAAA,CAAU,EAAA,EAAI,EAAE,IAAA,EAAM,CAAC,WAAW,CAAA,EAAG,CAAA;AAAA,IACvE,CAAC,eAAe,WAAW;AAAA,GAC7B;AACA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,MAAM,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,IACnC,CAAC,eAAe,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AAEtE,EAAA,MAAM,QAAA,GAAW,WAAA;AAAA,IACf,CAAC,CAAA,KAAS,aAAA,CAAc,GAAA,CAAI,aAAa,CAAC,CAAA;AAAA,IAC1C,CAAC,eAAe,WAAW;AAAA,GAC7B;AAEA,EAAA,OAAO,CAAC,OAAO,QAAQ,CAAA;AACzB;AAYO,SAAS,YAAA,GAA8C;AAC5D,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,gBAAA,EAAiB;AAE3C,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,OAAmB,aAAA,CAAc,SAAA,CAAU,IAAI,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,IACtE,CAAC,aAAa;AAAA,GAChB;AACA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,MAAM,cAAc,QAAA,EAAS;AAAA,IAC7B,CAAC,aAAa;AAAA,GAChB;AACA,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AAE1E,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,MAAM,SAAwC,EAAC;AAC/C,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpD,MAAA,IAAI,GAAA,CAAI,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,QAAA,MAAA,CAAO,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,KAAA;AAAA,MACzB;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAChB;AC3DO,SAAS,aAAA,GAAiC;AAC/C,EAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAe,OAAA,KAAY,gBAAA,EAAiB;AAG5D,EAAAA,oBAAAA;AAAA,IACEC,WAAAA,CAAY,CAAC,EAAA,KAAmB,MAAA,CAAO,UAAU,EAAE,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAAA,IAC9DA,YAAY,MAAM,MAAA,CAAO,aAAY,EAAG,CAAC,MAAM,CAAC,CAAA;AAAA,IAChDA,YAAY,MAAM,MAAA,CAAO,aAAY,EAAG,CAAC,MAAM,CAAC;AAAA,GAClD;AAGA,EAAA,MAAM,aAAA,GAAgBA,WAAAA,CAAY,CAAC,GAAA,KAAgB;AACjD,IAAA,MAAM,IAAA,GAAO,OAAO,cAAA,EAAe;AACnC,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,OAAA,CAAQ,MAAM,WAAA,EAAa;AAAA,QACzB,QAAQ,IAAA,CAAK,GAAA;AAAA,QACb,SAAS,IAAA,CAAK,GAAA;AAAA,QACd,UAAU,IAAA,CAAK;AAAA,OAChB,CAAA;AACD,MAAA,OAAA,CAAQ,iBAAA,CAAkB,KAAK,GAAG,CAAA;AAAA,IACpC;AACA,IAAA,aAAA,CAAc,OAAA,CAAQ;AAAA,MACpB,gBAAA,EAAkB,GAAA;AAAA,MAClB,mBAAA,EAAqB,MAAA,CAAO,cAAA,EAAe,CAAE,MAAA;AAAA,MAC7C,cAAA,EAAgB,MAAA,CAAO,cAAA,EAAe,CAAE,MAAA,GAAS,CAAA;AAAA,MACjD,gBAAA,EAAkB,KAAK,GAAA;AAAI,KAC5B,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,MAAM,YAAA,GAAeA,YAAY,MAAM;AACrC,IAAA,MAAM,YAAA,GAAe,OAAO,cAAA,EAAe;AAC3C,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,OAAA,CAAQ,gBAAA,EAAiB;AAAA,IAC3B;AAGA,IAAA,MAAM,SAAA,GAAY,cAAc,QAAA,EAAS;AACzC,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,YAAA,CAAa,SAAS,CAAA;AAC7C,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,aAAA,CAAc,OAAO,CAAA;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAA,EAAe,aAAa,CAAC,CAAA;AAElD,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,OAAA,CAAQ,gBAAA,EAAiB;AACzB,IAAA,MAAM,OAAA,GAAU,OAAO,MAAA,EAAO;AAC9B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,aAAA,CAAc,OAAO,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,MAAM,QAAA,GAAWA,WAAAA,CAAY,CAAC,OAAA,KAAoB;AAChD,IAAA,OAAA,CAAQ,gBAAA,EAAiB;AACzB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACnC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,aAAA,CAAc,GAAG,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,OAAO;AAAA,IACL,YAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA,EAAa,OAAO,cAAA,EAAe;AAAA,IACnC,WAAA,EAAa,OAAO,cAAA,EAAe;AAAA,IACnC,QAAA,EAAU,OAAO,WAAA;AAAY,GAC/B;AACF","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useResponse.ts","../src/hooks/useNavigation.ts"],"names":["useSyncExternalStore","useCallback"],"mappings":";;;AAYO,SAAS,YACd,GAAA,EACyB;AACzB,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,gBAAA,EAAiB;AAC3C,EAAA,MAAM,WAAA,GAAc,WAAW,GAAG,CAAA,CAAA;AAElC,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,EAAA,KAAmB,aAAA,CAAc,SAAA,CAAU,EAAA,EAAI,EAAE,IAAA,EAAM,CAAC,WAAW,CAAA,EAAG,CAAA;AAAA,IACvE,CAAC,eAAe,WAAW;AAAA,GAC7B;AACA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,MAAM,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,IACnC,CAAC,eAAe,WAAW;AAAA,GAC7B;AAEA,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AAEtE,EAAA,MAAM,QAAA,GAAW,WAAA;AAAA,IACf,CAAC,CAAA,KAAS,aAAA,CAAc,GAAA,CAAI,aAAa,CAAC,CAAA;AAAA,IAC1C,CAAC,eAAe,WAAW;AAAA,GAC7B;AAEA,EAAA,OAAO,CAAC,OAAO,QAAQ,CAAA;AACzB;AAYO,SAAS,YAAA,GAA8C;AAC5D,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,gBAAA,EAAiB;AAE3C,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,OAAmB,aAAA,CAAc,SAAA,CAAU,IAAI,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,IACtE,CAAC,aAAa;AAAA,GAChB;AACA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,MAAM,cAAc,QAAA,EAAS;AAAA,IAC7B,CAAC,aAAa;AAAA,GAChB;AACA,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,SAAA,EAAW,WAAA,EAAa,WAAW,CAAA;AAE1E,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,MAAM,SAAwC,EAAC;AAC/C,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpD,MAAA,IAAI,GAAA,CAAI,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,QAAA,MAAA,CAAO,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,KAAA;AAAA,MACzB;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAChB;AC3DO,SAAS,aAAA,GAAiC;AAC/C,EAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAe,OAAA,KAAY,gBAAA,EAAiB;AAG5D,EAAAA,oBAAAA;AAAA,IACEC,WAAAA,CAAY,CAAC,EAAA,KAAmB,MAAA,CAAO,UAAU,EAAE,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAAA,IAC9DA,YAAY,MAAM,MAAA,CAAO,aAAY,EAAG,CAAC,MAAM,CAAC,CAAA;AAAA,IAChDA,YAAY,MAAM,MAAA,CAAO,aAAY,EAAG,CAAC,MAAM,CAAC;AAAA,GAClD;AAGA,EAAA,MAAM,aAAA,GAAgBA,WAAAA,CAAY,CAAC,GAAA,KAAgB;AACjD,IAAA,MAAM,IAAA,GAAO,OAAO,cAAA,EAAe;AACnC,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,OAAA,CAAQ,MAAM,WAAA,EAAa;AAAA,QACzB,QAAQ,IAAA,CAAK,GAAA;AAAA,QACb,SAAS,IAAA,CAAK,GAAA;AAAA,QACd,UAAU,IAAA,CAAK;AAAA,OAChB,CAAA;AACD,MAAA,OAAA,CAAQ,iBAAA,CAAkB,KAAK,GAAG,CAAA;AAAA,IACpC;AACA,IAAA,aAAA,CAAc,OAAA,CAAQ;AAAA,MACpB,gBAAA,EAAkB,GAAA;AAAA,MAClB,mBAAA,EAAqB,MAAA,CAAO,cAAA,EAAe,CAAE,MAAA;AAAA,MAC7C,cAAA,EAAgB,MAAA,CAAO,cAAA,EAAe,CAAE,MAAA,GAAS,CAAA;AAAA,MACjD,gBAAA,EAAkB,KAAK,GAAA;AAAI,KAC5B,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,MAAM,YAAA,GAAeA,YAAY,MAAM;AACrC,IAAA,MAAM,YAAA,GAAe,OAAO,cAAA,EAAe;AAC3C,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,OAAA,CAAQ,gBAAA,EAAiB;AAAA,IAC3B;AAGA,IAAA,MAAM,SAAA,GAAY,cAAc,QAAA,EAAS;AACzC,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,YAAA,CAAa,SAAS,CAAA;AAC7C,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,aAAA,CAAc,OAAO,CAAA;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAA,EAAe,aAAa,CAAC,CAAA;AAElD,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,OAAA,CAAQ,gBAAA,EAAiB;AACzB,IAAA,MAAM,OAAA,GAAU,OAAO,MAAA,EAAO;AAC9B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,aAAA,CAAc,OAAO,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,MAAM,QAAA,GAAWA,WAAAA,CAAY,CAAC,OAAA,KAAoB;AAChD,IAAA,OAAA,CAAQ,gBAAA,EAAiB;AACzB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACnC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,aAAA,CAAc,GAAG,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,aAAa,CAAC,CAAA;AAEnC,EAAA,OAAO;AAAA,IACL,YAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA,EAAa,OAAO,cAAA,EAAe;AAAA,IACnC,WAAA,EAAa,OAAO,cAAA,EAAe;AAAA,IACnC,QAAA,EAAU,OAAO,WAAA;AAAY,GAC/B;AACF","file":"chunk-7JLCKTX6.js","sourcesContent":["import { useSyncExternalStore, useCallback, useMemo } from 'react'\nimport { useFunnelContext } from '../components/FunnelProvider'\nimport type { VariableValue } from '../types'\n\n/**\n * Read/write a single response variable (answers.*).\n *\n * ```tsx\n * const [goal, setGoal] = useResponse<string>('goal')\n * const [interests, setInterests] = useResponse<string[]>('interests')\n * ```\n */\nexport function useResponse<T extends VariableValue>(\n key: string,\n): [T, (value: T) => void] {\n const { variableStore } = useFunnelContext()\n const prefixedKey = `answers.${key}`\n\n const subscribe = useCallback(\n (cb: () => void) => variableStore.subscribe(cb, { keys: [prefixedKey] }),\n [variableStore, prefixedKey],\n )\n const getSnapshot = useCallback(\n () => variableStore.get(prefixedKey) as T,\n [variableStore, prefixedKey],\n )\n\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n\n const setValue = useCallback(\n (v: T) => variableStore.set(prefixedKey, v),\n [variableStore, prefixedKey],\n )\n\n return [value, setValue]\n}\n\n/**\n * Read all response variables as a flat object (without the `answers.` prefix).\n *\n * Only re-renders when an `answers.*` variable changes.\n *\n * ```tsx\n * const responses = useResponses()\n * // { goal: 'weight_loss', interests: ['yoga', 'running'] }\n * ```\n */\nexport function useResponses(): Record<string, VariableValue> {\n const { variableStore } = useFunnelContext()\n\n const subscribe = useCallback(\n (cb: () => void) => variableStore.subscribe(cb, { prefix: 'answers.' }),\n [variableStore],\n )\n const getSnapshot = useCallback(\n () => variableStore.getState(),\n [variableStore],\n )\n const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n\n return useMemo(() => {\n const result: Record<string, VariableValue> = {}\n for (const [key, value] of Object.entries(variables)) {\n if (key.startsWith('answers.')) {\n result[key.slice(8)] = value\n }\n }\n return result\n }, [variables])\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport { useFunnelContext } from '../components/FunnelProvider'\nimport type { NavigationState } from '../types'\n\n/**\n * Navigation hook — evaluates routes, navigates between pages, tracks progress.\n *\n * Only re-renders when the router's current page changes (not on variable changes).\n * Variables are read lazily at navigation time — callbacks are referentially stable.\n */\nexport function useNavigation(): NavigationState {\n const { router, variableStore, tracker } = useFunnelContext()\n\n // Re-render only when the router's current page changes\n useSyncExternalStore(\n useCallback((cb: () => void) => router.subscribe(cb), [router]),\n useCallback(() => router.getSnapshot(), [router]),\n useCallback(() => router.getSnapshot(), [router]),\n )\n\n /** Called after the router has already navigated to `key`. */\n const afterNavigate = useCallback((key: string) => {\n const page = router.getCurrentPage()\n if (page) {\n tracker.track('page.view', {\n pageId: page.key,\n pageKey: page.key,\n pageName: page.name,\n })\n tracker.startPageTracking(page.key)\n }\n variableStore.setMany({\n 'page.currentId': key,\n 'page.currentIndex': router.getPageHistory().length,\n 'page.current': router.getPageHistory().length + 1,\n 'page.startedAt': Date.now(),\n })\n }, [router, tracker, variableStore])\n\n const goToNextPage = useCallback(() => {\n const previousPage = router.getCurrentPage()\n if (previousPage) {\n tracker.stopPageTracking()\n }\n\n // Read variables at call time — not captured in closure\n const variables = variableStore.getState()\n const nextKey = router.goToNextPage(variables)\n if (nextKey) {\n afterNavigate(nextKey)\n }\n }, [router, tracker, variableStore, afterNavigate])\n\n const goBack = useCallback(() => {\n tracker.stopPageTracking()\n const prevKey = router.goBack()\n if (prevKey) {\n afterNavigate(prevKey)\n }\n }, [router, tracker, afterNavigate])\n\n const goToPage = useCallback((pageKey: string) => {\n tracker.stopPageTracking()\n const key = router.goToPage(pageKey)\n if (key) {\n afterNavigate(key)\n }\n }, [router, tracker, afterNavigate])\n\n return {\n goToNextPage,\n goBack,\n goToPage,\n currentPage: router.getCurrentPage(),\n pageHistory: router.getPageHistory(),\n progress: router.getProgress(),\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext,
|
|
1
|
+
import { createContext, useContext, useRef, useState, useEffect, useMemo, useCallback } from 'react';
|
|
2
2
|
import { Toaster } from 'sonner';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -376,7 +376,8 @@ var Router = class {
|
|
|
376
376
|
this.initialKey = config.pages?.[initialPage] ? initialPage : defaultInitial;
|
|
377
377
|
} else {
|
|
378
378
|
const hasSession = this.hasSessionCookie(campaignSlug);
|
|
379
|
-
|
|
379
|
+
const hasPendingSession = typeof window !== "undefined" && (window.location.search.includes("customer=") || window.location.search.includes("sid="));
|
|
380
|
+
this.initialKey = (hasSession || hasPendingSession) && config.pages?.[initialPage] ? initialPage : defaultInitial;
|
|
380
381
|
}
|
|
381
382
|
} else {
|
|
382
383
|
this.initialKey = initialPage || defaultInitial;
|
|
@@ -1176,6 +1177,121 @@ var I18n = class {
|
|
|
1176
1177
|
this.listeners.forEach((l) => l());
|
|
1177
1178
|
}
|
|
1178
1179
|
};
|
|
1180
|
+
|
|
1181
|
+
// src/runtime/session.ts
|
|
1182
|
+
var API_BASE_URL2 = "https://api.appfunnel.net";
|
|
1183
|
+
var API_HEADERS = { "ngrok-skip-browser-warning": "1" };
|
|
1184
|
+
async function apiFetch(path) {
|
|
1185
|
+
try {
|
|
1186
|
+
const res = await fetch(`${API_BASE_URL2}${path}`, { headers: API_HEADERS });
|
|
1187
|
+
return res.ok ? res.json() : null;
|
|
1188
|
+
} catch {
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function mergeVariables(store, data) {
|
|
1193
|
+
if (Object.keys(data).length === 0) return;
|
|
1194
|
+
store.setState((prev) => {
|
|
1195
|
+
const merged = { ...prev };
|
|
1196
|
+
for (const [key, value] of Object.entries(data)) {
|
|
1197
|
+
if (value !== void 0) merged[key] = value;
|
|
1198
|
+
}
|
|
1199
|
+
return merged;
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
function cleanUrlParams(...keys) {
|
|
1203
|
+
const url = new URL(window.location.href);
|
|
1204
|
+
for (const key of keys) url.searchParams.delete(key);
|
|
1205
|
+
window.history.replaceState({}, "", url.toString());
|
|
1206
|
+
}
|
|
1207
|
+
async function fetchAndRestoreSession(store, sessionId, funnelId) {
|
|
1208
|
+
const result = await apiFetch(`/session/${sessionId}/data`);
|
|
1209
|
+
if (!result?.success) return;
|
|
1210
|
+
if (result.data?.funnelId && result.data.funnelId !== funnelId) return;
|
|
1211
|
+
const savedData = result.data?.data || {};
|
|
1212
|
+
mergeVariables(store, savedData);
|
|
1213
|
+
}
|
|
1214
|
+
async function resolveCheckoutSuccess(ctx, params) {
|
|
1215
|
+
const stripeSessionId = params.get("session_id");
|
|
1216
|
+
cleanUrlParams("checkout", "session_id");
|
|
1217
|
+
const sessionId = ctx.tracker.getSessionId();
|
|
1218
|
+
if (!sessionId) return { ok: false };
|
|
1219
|
+
ctx.store.setMany({
|
|
1220
|
+
"purchase.status": "success",
|
|
1221
|
+
"purchase.success": true,
|
|
1222
|
+
"purchase.cancelled": false
|
|
1223
|
+
});
|
|
1224
|
+
await Promise.all([
|
|
1225
|
+
apiFetch(
|
|
1226
|
+
`/campaign/${ctx.campaignId}/stripe/checkout-status?sessionId=${encodeURIComponent(sessionId)}&checkoutSessionId=${encodeURIComponent(stripeSessionId)}`
|
|
1227
|
+
).then((result) => {
|
|
1228
|
+
if (!result?.success) return;
|
|
1229
|
+
const updates = {
|
|
1230
|
+
"payment.status": result.paymentStatus || "paid"
|
|
1231
|
+
};
|
|
1232
|
+
if (result.stripeCustomerId) {
|
|
1233
|
+
updates["user.stripeCustomerId"] = result.stripeCustomerId;
|
|
1234
|
+
}
|
|
1235
|
+
if (result.subscriptionId) {
|
|
1236
|
+
updates["stripe.subscriptionId"] = result.subscriptionId;
|
|
1237
|
+
updates["subscription.status"] = result.subscriptionStatus || "active";
|
|
1238
|
+
}
|
|
1239
|
+
if (result.paymentIntentId) {
|
|
1240
|
+
updates["stripe.paymentIntentId"] = result.paymentIntentId;
|
|
1241
|
+
}
|
|
1242
|
+
ctx.store.setMany(updates);
|
|
1243
|
+
ctx.tracker.track("purchase.complete", {
|
|
1244
|
+
eventId: stripeSessionId,
|
|
1245
|
+
amount: result.amountTotal ? result.amountTotal / 100 : 0,
|
|
1246
|
+
currency: result.currency || "usd",
|
|
1247
|
+
email: result.customerEmail
|
|
1248
|
+
});
|
|
1249
|
+
}),
|
|
1250
|
+
fetchAndRestoreSession(ctx.store, sessionId, ctx.funnelId)
|
|
1251
|
+
]);
|
|
1252
|
+
return { ok: true };
|
|
1253
|
+
}
|
|
1254
|
+
function resolveCheckoutCanceled(ctx) {
|
|
1255
|
+
cleanUrlParams("checkout", "session_id");
|
|
1256
|
+
ctx.store.setMany({
|
|
1257
|
+
"purchase.status": "cancelled",
|
|
1258
|
+
"purchase.success": false,
|
|
1259
|
+
"purchase.cancelled": true
|
|
1260
|
+
});
|
|
1261
|
+
return { ok: true };
|
|
1262
|
+
}
|
|
1263
|
+
async function resolveCustomer(ctx, customerId) {
|
|
1264
|
+
cleanUrlParams("customer");
|
|
1265
|
+
const result = await apiFetch(
|
|
1266
|
+
`/session/by-customer?customerId=${encodeURIComponent(customerId)}&campaignId=${encodeURIComponent(ctx.campaignId)}&funnelId=${encodeURIComponent(ctx.funnelId)}`
|
|
1267
|
+
);
|
|
1268
|
+
if (!result?.success || !result.sessionId) return { ok: false };
|
|
1269
|
+
ctx.tracker.setSessionId(result.sessionId);
|
|
1270
|
+
if (result.data) {
|
|
1271
|
+
mergeVariables(ctx.store, result.data);
|
|
1272
|
+
}
|
|
1273
|
+
return { ok: true };
|
|
1274
|
+
}
|
|
1275
|
+
async function resolveExistingSession(ctx) {
|
|
1276
|
+
const sessionId = ctx.tracker.getSessionId();
|
|
1277
|
+
if (!sessionId) return { ok: true };
|
|
1278
|
+
await fetchAndRestoreSession(ctx.store, sessionId, ctx.funnelId);
|
|
1279
|
+
return { ok: true };
|
|
1280
|
+
}
|
|
1281
|
+
async function resolveSession(ctx, params) {
|
|
1282
|
+
const checkoutStatus = params.get("checkout");
|
|
1283
|
+
const customerId = params.get("customer");
|
|
1284
|
+
if (checkoutStatus === "success" && params.get("session_id")) {
|
|
1285
|
+
return resolveCheckoutSuccess(ctx, params);
|
|
1286
|
+
}
|
|
1287
|
+
if (checkoutStatus === "canceled") {
|
|
1288
|
+
return resolveCheckoutCanceled(ctx);
|
|
1289
|
+
}
|
|
1290
|
+
if (customerId) {
|
|
1291
|
+
return resolveCustomer(ctx, customerId);
|
|
1292
|
+
}
|
|
1293
|
+
return resolveExistingSession(ctx);
|
|
1294
|
+
}
|
|
1179
1295
|
var FunnelContext = createContext(null);
|
|
1180
1296
|
function useFunnelContext() {
|
|
1181
1297
|
const ctx = useContext(FunnelContext);
|
|
@@ -1197,12 +1313,16 @@ function FunnelProvider({
|
|
|
1197
1313
|
const campaignId = sessionData?.campaignId || config.projectId || "";
|
|
1198
1314
|
const funnelId = sessionData?.funnelId || config.projectId || "";
|
|
1199
1315
|
const disableLoadingScreen = config.settings?.disableLoadingScreen === true;
|
|
1316
|
+
const initialUrlParams = useRef(null);
|
|
1317
|
+
if (!initialUrlParams.current && typeof window !== "undefined") {
|
|
1318
|
+
initialUrlParams.current = new URLSearchParams(window.location.search);
|
|
1319
|
+
}
|
|
1200
1320
|
const [isReady, setIsReady] = useState(() => {
|
|
1201
1321
|
if (disableLoadingScreen) return true;
|
|
1202
1322
|
if (sessionData?.variables) return true;
|
|
1203
1323
|
if (globalThis.__APPFUNNEL_DEV__) return true;
|
|
1204
1324
|
if (typeof window === "undefined") return false;
|
|
1205
|
-
const params =
|
|
1325
|
+
const params = initialUrlParams.current;
|
|
1206
1326
|
if (!params.has("checkout") && !params.has("customer") && !params.has("sid")) {
|
|
1207
1327
|
const hasCookie = document.cookie.includes("fs_");
|
|
1208
1328
|
if (!hasCookie) return true;
|
|
@@ -1221,12 +1341,7 @@ function FunnelProvider({
|
|
|
1221
1341
|
);
|
|
1222
1342
|
}
|
|
1223
1343
|
if (!routerRef.current) {
|
|
1224
|
-
routerRef.current = new Router({
|
|
1225
|
-
config,
|
|
1226
|
-
initialPage,
|
|
1227
|
-
basePath,
|
|
1228
|
-
campaignSlug
|
|
1229
|
-
});
|
|
1344
|
+
routerRef.current = new Router({ config, initialPage, basePath, campaignSlug });
|
|
1230
1345
|
}
|
|
1231
1346
|
if (!trackerRef.current) {
|
|
1232
1347
|
trackerRef.current = new FunnelTracker();
|
|
@@ -1249,163 +1364,18 @@ function FunnelProvider({
|
|
|
1249
1364
|
useEffect(() => {
|
|
1250
1365
|
if (sessionData?.variables) return;
|
|
1251
1366
|
if (globalThis.__APPFUNNEL_DEV__) return;
|
|
1252
|
-
const API_BASE_URL2 = "https://api.appfunnel.net";
|
|
1253
|
-
const markReady = () => setIsReady(true);
|
|
1254
|
-
tracker.init(campaignId, funnelId, campaignSlug, sessionData?.experimentId);
|
|
1255
1367
|
if (typeof window === "undefined") return;
|
|
1256
|
-
|
|
1257
|
-
const
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
url.searchParams.delete("session_id");
|
|
1263
|
-
window.history.replaceState({}, "", url.toString());
|
|
1264
|
-
const sessionId2 = tracker.getSessionId();
|
|
1265
|
-
if (!sessionId2) {
|
|
1266
|
-
markReady();
|
|
1267
|
-
return;
|
|
1368
|
+
tracker.init(campaignId, funnelId, campaignSlug, sessionData?.experimentId);
|
|
1369
|
+
const params = initialUrlParams.current || new URLSearchParams(window.location.search);
|
|
1370
|
+
resolveSession({ store, tracker, campaignId, funnelId }, params).then((result) => {
|
|
1371
|
+
if (!result.ok) {
|
|
1372
|
+
const initialKey = config.initialPageKey || Object.keys(config.pages ?? {})[0];
|
|
1373
|
+
if (initialKey) router.goToPage(initialKey);
|
|
1268
1374
|
}
|
|
1269
|
-
|
|
1270
|
-
"purchase.status": "success",
|
|
1271
|
-
"purchase.success": true,
|
|
1272
|
-
"purchase.cancelled": false
|
|
1273
|
-
});
|
|
1274
|
-
Promise.all([
|
|
1275
|
-
// Checkout details (stripeCustomerId, subscription info, etc.)
|
|
1276
|
-
fetch(
|
|
1277
|
-
`${API_BASE_URL2}/campaign/${campaignId}/stripe/checkout-status?sessionId=${encodeURIComponent(sessionId2)}&checkoutSessionId=${encodeURIComponent(stripeSessionId)}`,
|
|
1278
|
-
{ headers: { "ngrok-skip-browser-warning": "1" } }
|
|
1279
|
-
).then((res) => res.ok ? res.json() : null).then((result) => {
|
|
1280
|
-
if (!result?.success) return;
|
|
1281
|
-
const updates = {};
|
|
1282
|
-
if (result.stripeCustomerId) {
|
|
1283
|
-
updates["user.stripeCustomerId"] = result.stripeCustomerId;
|
|
1284
|
-
}
|
|
1285
|
-
if (result.subscriptionId) {
|
|
1286
|
-
updates["stripe.subscriptionId"] = result.subscriptionId;
|
|
1287
|
-
updates["subscription.status"] = result.subscriptionStatus || "active";
|
|
1288
|
-
}
|
|
1289
|
-
if (result.paymentIntentId) {
|
|
1290
|
-
updates["stripe.paymentIntentId"] = result.paymentIntentId;
|
|
1291
|
-
}
|
|
1292
|
-
updates["payment.status"] = result.paymentStatus || "paid";
|
|
1293
|
-
if (Object.keys(updates).length > 0) {
|
|
1294
|
-
store.setMany(updates);
|
|
1295
|
-
}
|
|
1296
|
-
tracker.track("purchase.complete", {
|
|
1297
|
-
eventId: stripeSessionId,
|
|
1298
|
-
amount: result.amountTotal ? result.amountTotal / 100 : 0,
|
|
1299
|
-
currency: result.currency || "usd",
|
|
1300
|
-
email: result.customerEmail
|
|
1301
|
-
});
|
|
1302
|
-
}).catch(() => {
|
|
1303
|
-
}),
|
|
1304
|
-
// Session variable restoration
|
|
1305
|
-
fetch(`${API_BASE_URL2}/session/${sessionId2}/data`, {
|
|
1306
|
-
headers: { "ngrok-skip-browser-warning": "1" }
|
|
1307
|
-
}).then((res) => res.ok ? res.json() : null).then((result) => {
|
|
1308
|
-
if (!result?.success) return;
|
|
1309
|
-
if (result.data?.funnelId && result.data.funnelId !== funnelId) return;
|
|
1310
|
-
const savedData = result.data?.data || {};
|
|
1311
|
-
if (Object.keys(savedData).length === 0) return;
|
|
1312
|
-
store.setState((prev) => {
|
|
1313
|
-
const merged = { ...prev };
|
|
1314
|
-
for (const [key, value] of Object.entries(savedData)) {
|
|
1315
|
-
if (value !== void 0) merged[key] = value;
|
|
1316
|
-
}
|
|
1317
|
-
return merged;
|
|
1318
|
-
});
|
|
1319
|
-
}).catch(() => {
|
|
1320
|
-
})
|
|
1321
|
-
]).finally(markReady);
|
|
1322
|
-
return;
|
|
1323
|
-
}
|
|
1324
|
-
if (checkoutStatus === "canceled") {
|
|
1325
|
-
const url = new URL(window.location.href);
|
|
1326
|
-
url.searchParams.delete("checkout");
|
|
1327
|
-
url.searchParams.delete("session_id");
|
|
1328
|
-
window.history.replaceState({}, "", url.toString());
|
|
1329
|
-
store.setMany({
|
|
1330
|
-
"purchase.status": "cancelled",
|
|
1331
|
-
"purchase.success": false,
|
|
1332
|
-
"purchase.cancelled": true
|
|
1333
|
-
});
|
|
1334
|
-
markReady();
|
|
1335
|
-
return;
|
|
1336
|
-
}
|
|
1337
|
-
const customerParam = urlParams.get("customer");
|
|
1338
|
-
if (customerParam) {
|
|
1339
|
-
const url = new URL(window.location.href);
|
|
1340
|
-
url.searchParams.delete("customer");
|
|
1341
|
-
window.history.replaceState({}, "", url.toString());
|
|
1342
|
-
fetch(
|
|
1343
|
-
`${API_BASE_URL2}/session/by-customer?customerId=${encodeURIComponent(customerParam)}&campaignId=${encodeURIComponent(campaignId)}&funnelId=${encodeURIComponent(funnelId)}`,
|
|
1344
|
-
{ headers: { "ngrok-skip-browser-warning": "1" } }
|
|
1345
|
-
).then((res) => res.ok ? res.json() : null).then((result) => {
|
|
1346
|
-
if (!result?.success || !result.sessionId) return;
|
|
1347
|
-
tracker.setSessionId(result.sessionId);
|
|
1348
|
-
if (!result.isNew && result.data) {
|
|
1349
|
-
const savedData = result.data;
|
|
1350
|
-
if (Object.keys(savedData).length > 0) {
|
|
1351
|
-
store.setState((prev) => {
|
|
1352
|
-
const merged = { ...prev };
|
|
1353
|
-
for (const [key, value] of Object.entries(savedData)) {
|
|
1354
|
-
if (value !== void 0) merged[key] = value;
|
|
1355
|
-
}
|
|
1356
|
-
return merged;
|
|
1357
|
-
});
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
}).catch(() => {
|
|
1361
|
-
}).finally(markReady);
|
|
1362
|
-
return;
|
|
1363
|
-
}
|
|
1364
|
-
const sessionId = tracker.getSessionId();
|
|
1365
|
-
if (!sessionId) {
|
|
1366
|
-
markReady();
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
fetch(`${API_BASE_URL2}/session/${sessionId}/data`, {
|
|
1370
|
-
headers: { "ngrok-skip-browser-warning": "1" }
|
|
1371
|
-
}).then((res) => res.ok ? res.json() : null).then((result) => {
|
|
1372
|
-
if (!result?.success) return;
|
|
1373
|
-
if (result.data?.funnelId && result.data.funnelId !== funnelId) return;
|
|
1374
|
-
const savedData = result.data?.data || {};
|
|
1375
|
-
if (Object.keys(savedData).length === 0) return;
|
|
1376
|
-
store.setState((prev) => {
|
|
1377
|
-
const merged = { ...prev };
|
|
1378
|
-
for (const [key, value] of Object.entries(savedData)) {
|
|
1379
|
-
if (value !== void 0) merged[key] = value;
|
|
1380
|
-
}
|
|
1381
|
-
return merged;
|
|
1382
|
-
});
|
|
1383
|
-
}).catch(() => {
|
|
1384
|
-
}).finally(markReady);
|
|
1385
|
-
}, []);
|
|
1386
|
-
const products = useMemo(() => {
|
|
1387
|
-
if (!config.products?.items || !priceData) return [];
|
|
1388
|
-
return buildRuntimeProducts(config.products.items, priceData);
|
|
1389
|
-
}, [config.products, priceData]);
|
|
1390
|
-
const defaultProductId = config.products?.defaultId || products[0]?.id || null;
|
|
1391
|
-
const selectedProductIdRef = useRef(defaultProductId);
|
|
1392
|
-
const selectProduct = useCallback((productId) => {
|
|
1393
|
-
selectedProductIdRef.current = productId;
|
|
1394
|
-
store.set("products.selectedProductId", productId);
|
|
1395
|
-
}, [store]);
|
|
1396
|
-
useEffect(() => {
|
|
1397
|
-
const eventBus = new AppFunnelEventBus(store, router, selectProduct);
|
|
1398
|
-
eventBus.attach();
|
|
1399
|
-
eventBusRef.current = eventBus;
|
|
1400
|
-
if (config.integrations && Object.keys(config.integrations).length > 0) {
|
|
1401
|
-
initializeIntegrations(config.integrations);
|
|
1402
|
-
}
|
|
1403
|
-
return () => {
|
|
1404
|
-
eventBus.destroy();
|
|
1405
|
-
eventBusRef.current = null;
|
|
1406
|
-
};
|
|
1375
|
+
}).finally(() => setIsReady(true));
|
|
1407
1376
|
}, []);
|
|
1408
1377
|
useEffect(() => {
|
|
1378
|
+
if (!isReady) return;
|
|
1409
1379
|
tracker.init(campaignId, funnelId, campaignSlug, sessionData?.experimentId);
|
|
1410
1380
|
if (sessionData?.sessionId) {
|
|
1411
1381
|
tracker.setSessionId(sessionData.sessionId);
|
|
@@ -1428,11 +1398,33 @@ function FunnelProvider({
|
|
|
1428
1398
|
tracker.stopPageTracking();
|
|
1429
1399
|
tracker.flushVariables();
|
|
1430
1400
|
};
|
|
1401
|
+
}, [isReady]);
|
|
1402
|
+
const products = useMemo(() => {
|
|
1403
|
+
if (!config.products?.items || !priceData) return [];
|
|
1404
|
+
return buildRuntimeProducts(config.products.items, priceData);
|
|
1405
|
+
}, [config.products, priceData]);
|
|
1406
|
+
const defaultProductId = config.products?.defaultId || products[0]?.id || null;
|
|
1407
|
+
const selectedProductIdRef = useRef(defaultProductId);
|
|
1408
|
+
const selectProduct = useCallback((productId) => {
|
|
1409
|
+
selectedProductIdRef.current = productId;
|
|
1410
|
+
store.set("products.selectedProductId", productId);
|
|
1411
|
+
}, [store]);
|
|
1412
|
+
useEffect(() => {
|
|
1413
|
+
const eventBus = new AppFunnelEventBus(store, router, selectProduct);
|
|
1414
|
+
eventBus.attach();
|
|
1415
|
+
eventBusRef.current = eventBus;
|
|
1416
|
+
if (config.integrations && Object.keys(config.integrations).length > 0) {
|
|
1417
|
+
initializeIntegrations(config.integrations);
|
|
1418
|
+
}
|
|
1419
|
+
return () => {
|
|
1420
|
+
eventBus.destroy();
|
|
1421
|
+
eventBusRef.current = null;
|
|
1422
|
+
};
|
|
1431
1423
|
}, []);
|
|
1432
1424
|
const sessionStartTime = useRef(Date.now());
|
|
1433
1425
|
const pageStartTime = useRef(Date.now());
|
|
1434
1426
|
useEffect(() => {
|
|
1435
|
-
|
|
1427
|
+
store.setMany(computeSystemVariables({
|
|
1436
1428
|
currentPageKey: router.getCurrentPage()?.key || "",
|
|
1437
1429
|
pageHistory: router.getPageHistory(),
|
|
1438
1430
|
pageStartTime: pageStartTime.current,
|
|
@@ -1440,8 +1432,7 @@ function FunnelProvider({
|
|
|
1440
1432
|
totalPages: Object.keys(config.pages ?? {}).length,
|
|
1441
1433
|
funnelId,
|
|
1442
1434
|
campaignId
|
|
1443
|
-
});
|
|
1444
|
-
store.setMany(sysVars);
|
|
1435
|
+
}));
|
|
1445
1436
|
if (defaultProductId) {
|
|
1446
1437
|
store.set("products.selectedProductId", defaultProductId);
|
|
1447
1438
|
}
|
|
@@ -1480,5 +1471,5 @@ function FunnelProvider({
|
|
|
1480
1471
|
}
|
|
1481
1472
|
|
|
1482
1473
|
export { FunnelProvider, __require, registerIntegration, useFunnelContext };
|
|
1483
|
-
//# sourceMappingURL=chunk-
|
|
1484
|
-
//# sourceMappingURL=chunk-
|
|
1474
|
+
//# sourceMappingURL=chunk-H5C2QJIY.js.map
|
|
1475
|
+
//# sourceMappingURL=chunk-H5C2QJIY.js.map
|