@quiltt/react 5.0.0 → 5.0.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/CHANGELOG.md +26 -0
- package/README.md +12 -0
- package/dist/components/QuilttProviderRender-12s-pvnc98Lj.cjs +6 -0
- package/dist/components/QuilttSettings-12s-cLPT_GLC.cjs +6 -0
- package/dist/components/index.cjs +212 -0
- package/dist/components/index.d.ts +56 -0
- package/dist/components/index.js +209 -0
- package/dist/{useQuilttConnector-12s-DfCZ1lpS.js → components/useQuilttConnector-12s-3VgurfwU.js} +6 -77
- package/dist/components/useQuilttConnector-12s-zU4NFJ-H.cjs +174 -0
- package/dist/components/useQuilttRenderGuard-12s-D9WbRzZO.cjs +36 -0
- package/dist/components/useQuilttSession-12s-BjyJL1qZ.cjs +133 -0
- package/dist/components/useQuilttSession-12s-VOH0S5zh.js +133 -0
- package/dist/components/useQuilttSettings-12s-aDLXY6z3.cjs +10 -0
- package/dist/components/useScript-12s-CMIDUHrx.cjs +92 -0
- package/dist/{useSession-12s-BlrWOArd.js → components/useSession-12s-BNPsfKY-.js} +27 -6
- package/dist/components/useSession-12s-BNotXj5T.cjs +90 -0
- package/dist/components/useStorage-12s-D7nllsrI.cjs +61 -0
- package/dist/contexts/QuilttSettings-12s-BK-0SQME.js +6 -0
- package/dist/contexts/QuilttSettings-12s-cLPT_GLC.cjs +6 -0
- package/dist/contexts/index.cjs +7 -0
- package/dist/contexts/index.d.ts +8 -0
- package/dist/contexts/index.js +1 -0
- package/dist/hooks/QuilttProviderRender-12s-DtQtubjL.js +6 -0
- package/dist/hooks/QuilttProviderRender-12s-pvnc98Lj.cjs +6 -0
- package/dist/hooks/QuilttSettings-12s-BK-0SQME.js +6 -0
- package/dist/hooks/QuilttSettings-12s-cLPT_GLC.cjs +6 -0
- package/dist/hooks/index.cjs +31 -0
- package/dist/hooks/index.d.ts +142 -0
- package/dist/hooks/index.js +11 -0
- package/dist/hooks/useEventListener-12s-CV8cLxWu.cjs +34 -0
- package/dist/hooks/useIsomorphicLayoutEffect-12s-B8KjaroI.cjs +9 -0
- package/dist/hooks/useQuilttClient-12s-flQYSVdG.cjs +6 -0
- package/dist/hooks/useQuilttConnector-12s-BLZ0GoAH.js +174 -0
- package/dist/hooks/useQuilttConnector-12s-sP-k4D3J.cjs +175 -0
- package/dist/hooks/useQuilttInstitutions-12s-BU_Vm7TY.cjs +82 -0
- package/dist/{useQuilttInstitutions-12s-ClSQJPmP.js → hooks/useQuilttInstitutions-12s-ByXIt9W6.js} +3 -2
- package/dist/hooks/useQuilttRenderGuard-12s-CsS2Ma6Q.js +36 -0
- package/dist/hooks/useQuilttRenderGuard-12s-D9WbRzZO.cjs +36 -0
- package/dist/{useQuilttResolvable-12s-Dm4vsARj.js → hooks/useQuilttResolvable-12s-C5DByktm.js} +3 -2
- package/dist/hooks/useQuilttResolvable-12s-CGEfKPVU.cjs +76 -0
- package/dist/hooks/useQuilttSession-12s-C8kq5S2Y.cjs +139 -0
- package/dist/{useQuilttSession-12s-_8sB_8aP.js → hooks/useQuilttSession-12s-DQFfjmob.js} +1 -1
- package/dist/hooks/useQuilttSettings-12s--rCJoNHD.js +10 -0
- package/dist/hooks/useQuilttSettings-12s-aDLXY6z3.cjs +10 -0
- package/dist/hooks/useScript-12s-CMIDUHrx.cjs +92 -0
- package/dist/hooks/useScript-12s-JCgaTW9n.js +92 -0
- package/dist/hooks/useSession-12s-BNPsfKY-.js +90 -0
- package/dist/hooks/useSession-12s-BNotXj5T.cjs +90 -0
- package/dist/hooks/useStorage-12s-CpG6X57D.js +61 -0
- package/dist/hooks/useStorage-12s-D7nllsrI.cjs +61 -0
- package/dist/index.cjs +149 -0
- package/dist/index.d.ts +3 -216
- package/dist/index.js +3 -190
- package/dist/{QuilttAuthProvider-12s-C_Wt9rkK.js → providers/QuilttAuthProvider-12s-CDgQbarX.js} +14 -12
- package/dist/providers/QuilttAuthProvider-12s-D__FY1Qn.cjs +60 -0
- package/dist/providers/QuilttProviderRender-12s-DtQtubjL.js +6 -0
- package/dist/providers/QuilttProviderRender-12s-pvnc98Lj.cjs +6 -0
- package/dist/providers/QuilttSettings-12s-BK-0SQME.js +6 -0
- package/dist/providers/QuilttSettings-12s-cLPT_GLC.cjs +6 -0
- package/dist/providers/QuilttSettingsProvider-12s-D7e8dsOE.cjs +19 -0
- package/dist/{QuilttSettingsProvider-12s-ZcmFmOiZ.js → providers/QuilttSettingsProvider-12s-DND2gPQm.js} +8 -5
- package/dist/providers/index.cjs +34 -0
- package/dist/providers/index.d.ts +28 -0
- package/dist/providers/index.js +30 -0
- package/dist/utils/index.cjs +89 -0
- package/dist/utils/index.d.ts +31 -0
- package/dist/utils/index.js +77 -0
- package/package.json +33 -7
- package/src/components/QuilttContainer.tsx +3 -0
- package/src/hooks/useSession.ts +32 -6
- package/src/providers/QuilttAuthProvider.tsx +8 -2
- package/src/providers/QuilttProvider.tsx +5 -1
- package/src/providers/QuilttSettingsProvider.tsx +4 -5
- /package/dist/{QuilttProviderRender-12s-DtQtubjL.js → components/QuilttProviderRender-12s-DtQtubjL.js} +0 -0
- /package/dist/{QuilttSettings-12s-BK-0SQME.js → components/QuilttSettings-12s-BK-0SQME.js} +0 -0
- /package/dist/{useQuilttRenderGuard-12s-CsS2Ma6Q.js → components/useQuilttRenderGuard-12s-CsS2Ma6Q.js} +0 -0
- /package/dist/{useQuilttSettings-12s--rCJoNHD.js → components/useQuilttSettings-12s--rCJoNHD.js} +0 -0
- /package/dist/{useScript-12s-JCgaTW9n.js → components/useScript-12s-JCgaTW9n.js} +0 -0
- /package/dist/{useStorage-12s-CpG6X57D.js → components/useStorage-12s-CpG6X57D.js} +0 -0
- /package/dist/{useEventListener-12s-D_-6QIXa.js → hooks/useEventListener-12s-D_-6QIXa.js} +0 -0
- /package/dist/{useIsomorphicLayoutEffect-12s-DeTHOKz1.js → hooks/useIsomorphicLayoutEffect-12s-DeTHOKz1.js} +0 -0
- /package/dist/{useQuilttClient-12s-Dj_MtYTU.js → hooks/useQuilttClient-12s-Dj_MtYTU.js} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var react = require('react');
|
|
3
|
+
var core = require('@quiltt/core');
|
|
4
|
+
var useStorage12s = require('./useStorage-12s-D7nllsrI.cjs');
|
|
5
|
+
|
|
6
|
+
// Initialize JWT parser with our specific claims type
|
|
7
|
+
const parse = core.JsonWebTokenParse;
|
|
8
|
+
// Global timer to manage token expiration across all hook instances
|
|
9
|
+
const sessionTimer = new core.Timeoutable();
|
|
10
|
+
/**
|
|
11
|
+
* Custom hook to manage JWT session state with automatic expiration handling.
|
|
12
|
+
* Provides global singleton access to the session across components and windows.
|
|
13
|
+
*
|
|
14
|
+
* TODO: Support Rotation before Expiry
|
|
15
|
+
*
|
|
16
|
+
* Handles two types of data flow:
|
|
17
|
+
* 1. Bottom-up (Login): Token passed through setSession callback
|
|
18
|
+
* 2. Top-down (Refresh): State reinitialized on page reload
|
|
19
|
+
*
|
|
20
|
+
* @param storageKey - Key used for storing session in useStorage (defaults to 'session')
|
|
21
|
+
* @returns [session, setSession] - Current session state and setter function
|
|
22
|
+
*/ const useSession = (storageKey = 'session')=>{
|
|
23
|
+
const [token, setToken] = useStorage12s.useStorage(storageKey);
|
|
24
|
+
// Parse token into session data, updates when token changes
|
|
25
|
+
const session = react.useMemo(()=>parse(token), [
|
|
26
|
+
token
|
|
27
|
+
]);
|
|
28
|
+
// Handle session expiration
|
|
29
|
+
react.useEffect(()=>{
|
|
30
|
+
if (!session) return;
|
|
31
|
+
const expirationMS = session.claims.exp * 1000;
|
|
32
|
+
const expire = ()=>setToken(null);
|
|
33
|
+
const checkExpiration = ()=>{
|
|
34
|
+
if (Date.now() >= expirationMS) {
|
|
35
|
+
expire();
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
};
|
|
40
|
+
// Clear immediately if already expired
|
|
41
|
+
if (checkExpiration()) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Set timer to clear session at expiration time
|
|
45
|
+
sessionTimer.set(expire, expirationMS - Date.now());
|
|
46
|
+
// Also check expiration when tab becomes visible (handles idle sessions)
|
|
47
|
+
const handleVisibilityChange = ()=>{
|
|
48
|
+
if (!document.hidden) {
|
|
49
|
+
checkExpiration();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
// Only add listener in browser environment
|
|
53
|
+
if (typeof document !== 'undefined') {
|
|
54
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
55
|
+
}
|
|
56
|
+
return ()=>{
|
|
57
|
+
sessionTimer.clear(expire);
|
|
58
|
+
if (typeof document !== 'undefined') {
|
|
59
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}, [
|
|
63
|
+
session,
|
|
64
|
+
setToken
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Validates and updates the session token.
|
|
68
|
+
* - Handles both direct values and updater functions
|
|
69
|
+
* - Validates new tokens before setting them
|
|
70
|
+
* - Prevents unnecessary updates for same token value
|
|
71
|
+
* - Allows clearing the session with null/undefined
|
|
72
|
+
*/ const setSession = react.useCallback((nextState)=>{
|
|
73
|
+
const newState = nextState instanceof Function ? nextState(token) : nextState;
|
|
74
|
+
// Only update if:
|
|
75
|
+
// 1. The token has actually changed AND
|
|
76
|
+
// 2. Either the new state is falsy (clearing session) OR it's a valid token
|
|
77
|
+
if (token !== newState && (!newState || parse(newState))) {
|
|
78
|
+
setToken(newState);
|
|
79
|
+
}
|
|
80
|
+
}, [
|
|
81
|
+
token,
|
|
82
|
+
setToken
|
|
83
|
+
]);
|
|
84
|
+
return [
|
|
85
|
+
session,
|
|
86
|
+
setSession
|
|
87
|
+
];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
exports.useSession = useSession;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var react = require('react');
|
|
3
|
+
var core = require('@quiltt/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Attempt to persist state with local storage, so it remains after refresh and
|
|
7
|
+
* across open documents. Falls back to in memory storage when localStorage is
|
|
8
|
+
* unavailable.
|
|
9
|
+
*
|
|
10
|
+
* This hook is used in the same way as useState except that you must pass the
|
|
11
|
+
* storage key in the 1st parameter. If the window object is not present (as in SSR),
|
|
12
|
+
* useStorage() will return the default nextState.
|
|
13
|
+
*
|
|
14
|
+
* Expect values to remain in sync
|
|
15
|
+
* Across Hooks
|
|
16
|
+
* Across Reloads
|
|
17
|
+
* Across Windows (Documents)
|
|
18
|
+
*
|
|
19
|
+
* @param key
|
|
20
|
+
* @param initialState
|
|
21
|
+
* @returns {Array} [storage, setStorage]
|
|
22
|
+
*/ const useStorage = (key, initialState)=>{
|
|
23
|
+
const getStorage = react.useCallback(()=>{
|
|
24
|
+
const state = core.GlobalStorage.get(key);
|
|
25
|
+
if (state !== undefined) {
|
|
26
|
+
return state;
|
|
27
|
+
}
|
|
28
|
+
return initialState;
|
|
29
|
+
}, [
|
|
30
|
+
key,
|
|
31
|
+
initialState
|
|
32
|
+
]);
|
|
33
|
+
const [hookState, setHookState] = react.useState(getStorage());
|
|
34
|
+
const setStorage = react.useCallback((nextState)=>{
|
|
35
|
+
const newState = nextState instanceof Function ? nextState(hookState) : nextState;
|
|
36
|
+
if (hookState !== newState) {
|
|
37
|
+
core.GlobalStorage.set(key, newState);
|
|
38
|
+
// Immediately update hook state as well
|
|
39
|
+
setHookState(newState);
|
|
40
|
+
}
|
|
41
|
+
}, [
|
|
42
|
+
key,
|
|
43
|
+
hookState
|
|
44
|
+
]);
|
|
45
|
+
react.useEffect(()=>{
|
|
46
|
+
// Subscribe to storage changes from other sources (e.g., other hook instances, browser tabs)
|
|
47
|
+
const handleStorageChange = (newValue)=>{
|
|
48
|
+
setHookState(newValue);
|
|
49
|
+
};
|
|
50
|
+
core.GlobalStorage.subscribe(key, handleStorageChange);
|
|
51
|
+
return ()=>core.GlobalStorage.unsubscribe(key, handleStorageChange);
|
|
52
|
+
}, [
|
|
53
|
+
key
|
|
54
|
+
]);
|
|
55
|
+
return [
|
|
56
|
+
hookState,
|
|
57
|
+
setStorage
|
|
58
|
+
];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
exports.useStorage = useStorage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Q as QuilttSettings } from './QuilttSettings-12s-BK-0SQME.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
3
|
+
var useEventListener12s = require('./useEventListener-12s-CV8cLxWu.cjs');
|
|
4
|
+
var useIsomorphicLayoutEffect12s = require('./useIsomorphicLayoutEffect-12s-B8KjaroI.cjs');
|
|
5
|
+
var useQuilttSession12s = require('./useQuilttSession-12s-C8kq5S2Y.cjs');
|
|
6
|
+
var useQuilttClient12s = require('./useQuilttClient-12s-flQYSVdG.cjs');
|
|
7
|
+
var useQuilttConnector12s = require('./useQuilttConnector-12s-sP-k4D3J.cjs');
|
|
8
|
+
var useQuilttInstitutions12s = require('./useQuilttInstitutions-12s-BU_Vm7TY.cjs');
|
|
9
|
+
var useQuilttRenderGuard12s = require('./useQuilttRenderGuard-12s-D9WbRzZO.cjs');
|
|
10
|
+
var useQuilttResolvable12s = require('./useQuilttResolvable-12s-CGEfKPVU.cjs');
|
|
11
|
+
var useQuilttSettings12s = require('./useQuilttSettings-12s-aDLXY6z3.cjs');
|
|
12
|
+
var useSession12s = require('./useSession-12s-BNotXj5T.cjs');
|
|
13
|
+
var useStorage12s = require('./useStorage-12s-D7nllsrI.cjs');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
exports.useEventListener = useEventListener12s.useEventListener;
|
|
18
|
+
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect12s.useIsomorphicLayoutEffect;
|
|
19
|
+
exports.useAuthenticateSession = useQuilttSession12s.useAuthenticateSession;
|
|
20
|
+
exports.useIdentifySession = useQuilttSession12s.useIdentifySession;
|
|
21
|
+
exports.useImportSession = useQuilttSession12s.useImportSession;
|
|
22
|
+
exports.useQuilttSession = useQuilttSession12s.useQuilttSession;
|
|
23
|
+
exports.useRevokeSession = useQuilttSession12s.useRevokeSession;
|
|
24
|
+
exports.useQuilttClient = useQuilttClient12s.useQuilttClient;
|
|
25
|
+
exports.useQuilttConnector = useQuilttConnector12s.useQuilttConnector;
|
|
26
|
+
exports.useQuilttInstitutions = useQuilttInstitutions12s.useQuilttInstitutions;
|
|
27
|
+
exports.useQuilttRenderGuard = useQuilttRenderGuard12s.useQuilttRenderGuard;
|
|
28
|
+
exports.useQuilttResolvable = useQuilttResolvable12s.useQuilttResolvable;
|
|
29
|
+
exports.useQuilttSettings = useQuilttSettings12s.useQuilttSettings;
|
|
30
|
+
exports.useSession = useSession12s.useSession;
|
|
31
|
+
exports.useStorage = useStorage12s.useStorage;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { RefObject, useEffect, Dispatch, SetStateAction } from 'react';
|
|
2
|
+
import { Maybe, QuilttJWT, PasscodePayload, UnprocessableData, AuthAPI, UsernamePayload, ConnectorSDKConnectorOptions, InstitutionsData } from '@quiltt/core';
|
|
3
|
+
import { useApolloClient } from '@apollo/client/react';
|
|
4
|
+
|
|
5
|
+
declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: boolean | AddEventListenerOptions): void;
|
|
6
|
+
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
|
|
7
|
+
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement>(eventName: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T>, options?: boolean | AddEventListenerOptions): void;
|
|
8
|
+
declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: boolean | AddEventListenerOptions): void;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This hook is a browser hook. But React code could be generated from the server without the Window API.
|
|
12
|
+
* This hook switches between useEffect and useLayoutEffect following the execution environment.
|
|
13
|
+
*/
|
|
14
|
+
declare const useIsomorphicLayoutEffect: typeof useEffect;
|
|
15
|
+
|
|
16
|
+
type SetSession = Dispatch<SetStateAction<Maybe<string> | undefined>>;
|
|
17
|
+
/**
|
|
18
|
+
* Custom hook to manage JWT session state with automatic expiration handling.
|
|
19
|
+
* Provides global singleton access to the session across components and windows.
|
|
20
|
+
*
|
|
21
|
+
* TODO: Support Rotation before Expiry
|
|
22
|
+
*
|
|
23
|
+
* Handles two types of data flow:
|
|
24
|
+
* 1. Bottom-up (Login): Token passed through setSession callback
|
|
25
|
+
* 2. Top-down (Refresh): State reinitialized on page reload
|
|
26
|
+
*
|
|
27
|
+
* @param storageKey - Key used for storing session in useStorage (defaults to 'session')
|
|
28
|
+
* @returns [session, setSession] - Current session state and setter function
|
|
29
|
+
*/
|
|
30
|
+
declare const useSession: (storageKey?: string) => [Maybe<QuilttJWT> | undefined, SetSession];
|
|
31
|
+
|
|
32
|
+
type AuthenticateSessionCallbacks = {
|
|
33
|
+
onSuccess?: () => unknown;
|
|
34
|
+
onFailure?: () => unknown;
|
|
35
|
+
onError?: (errors: UnprocessableData) => unknown;
|
|
36
|
+
};
|
|
37
|
+
type AuthenticateSession = (payload: PasscodePayload, callbacks: AuthenticateSessionCallbacks) => Promise<unknown>;
|
|
38
|
+
type UseAuthenticateSession = (auth: AuthAPI, setSession: SetSession) => AuthenticateSession;
|
|
39
|
+
declare const useAuthenticateSession: UseAuthenticateSession;
|
|
40
|
+
|
|
41
|
+
type IdentifySessionCallbacks = {
|
|
42
|
+
onSuccess?: () => unknown;
|
|
43
|
+
onChallenged?: () => unknown;
|
|
44
|
+
onError?: (errors: UnprocessableData) => unknown;
|
|
45
|
+
onForbidden?: () => unknown;
|
|
46
|
+
};
|
|
47
|
+
type IdentifySession = (payload: UsernamePayload, callbacks: IdentifySessionCallbacks) => Promise<unknown>;
|
|
48
|
+
type UseIdentifySession = (auth: AuthAPI, setSession: SetSession) => IdentifySession;
|
|
49
|
+
declare const useIdentifySession: UseIdentifySession;
|
|
50
|
+
|
|
51
|
+
type ImportSession = (token: string) => Promise<boolean>;
|
|
52
|
+
type UseImportSession = (auth: AuthAPI, session: Maybe<QuilttJWT> | undefined, setSession: SetSession, environmentId?: string) => ImportSession;
|
|
53
|
+
/**
|
|
54
|
+
* Optionally Accepts environmentId to validate session is from with your desired environment
|
|
55
|
+
*/
|
|
56
|
+
declare const useImportSession: UseImportSession;
|
|
57
|
+
|
|
58
|
+
type RevokeSession = () => Promise<void>;
|
|
59
|
+
type UseRevokeSession = (auth: AuthAPI, session: Maybe<QuilttJWT> | undefined, setSession: SetSession) => RevokeSession;
|
|
60
|
+
declare const useRevokeSession: UseRevokeSession;
|
|
61
|
+
|
|
62
|
+
declare const useQuilttClient: typeof useApolloClient;
|
|
63
|
+
|
|
64
|
+
declare const useQuilttConnector: (connectorId?: string, options?: ConnectorSDKConnectorOptions) => {
|
|
65
|
+
open: () => void;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
type UseQuilttInstitutions = (connectorId: string, onErrorCallback?: (msg: string) => void) => {
|
|
69
|
+
searchTerm: string;
|
|
70
|
+
searchResults: InstitutionsData;
|
|
71
|
+
isSearching: boolean;
|
|
72
|
+
setSearchTerm: (term: string) => void;
|
|
73
|
+
};
|
|
74
|
+
declare const useQuilttInstitutions: UseQuilttInstitutions;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Internal hook that detects when a Quiltt SDK component may be rendered
|
|
78
|
+
* in the same component as QuilttProvider, which is an anti-pattern that
|
|
79
|
+
* can cause memory context issues and unexpected behavior.
|
|
80
|
+
*
|
|
81
|
+
* **Limitation**: Due to React context propagation, this will trigger for ALL
|
|
82
|
+
* descendants of QuilttProvider, not just direct children. This means it may
|
|
83
|
+
* produce false positives for valid nested component patterns. However, the
|
|
84
|
+
* primary use case (same-component rendering) is reliably detected.
|
|
85
|
+
*
|
|
86
|
+
* When the flag is set, this hook will emit a console error. This primarily
|
|
87
|
+
* helps catch the anti-pattern but may also flag valid nested structures.
|
|
88
|
+
*
|
|
89
|
+
* @param componentName - The name of the component calling this hook (for error messages)
|
|
90
|
+
*/
|
|
91
|
+
declare const useQuilttRenderGuard: (componentName: string) => void;
|
|
92
|
+
|
|
93
|
+
type UseQuilttResolvable = (connectorId: string, onErrorCallback?: (msg: string) => void) => {
|
|
94
|
+
checkResolvable: (providerId: {
|
|
95
|
+
plaid?: string;
|
|
96
|
+
mock?: string;
|
|
97
|
+
mx?: string;
|
|
98
|
+
finicity?: string;
|
|
99
|
+
akoya?: string;
|
|
100
|
+
}) => Promise<boolean | null>;
|
|
101
|
+
isLoading: boolean;
|
|
102
|
+
isResolvable: boolean | null;
|
|
103
|
+
error: string | null;
|
|
104
|
+
};
|
|
105
|
+
declare const useQuilttResolvable: UseQuilttResolvable;
|
|
106
|
+
|
|
107
|
+
type UseQuilttSession = (environmentId?: string) => {
|
|
108
|
+
session: Maybe<QuilttJWT> | undefined;
|
|
109
|
+
importSession: ImportSession;
|
|
110
|
+
identifySession: IdentifySession;
|
|
111
|
+
authenticateSession: AuthenticateSession;
|
|
112
|
+
revokeSession: RevokeSession;
|
|
113
|
+
forgetSession: (token?: string) => Promise<void>;
|
|
114
|
+
};
|
|
115
|
+
declare const useQuilttSession: UseQuilttSession;
|
|
116
|
+
|
|
117
|
+
declare const useQuilttSettings: () => {
|
|
118
|
+
clientId?: string;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Attempt to persist state with local storage, so it remains after refresh and
|
|
123
|
+
* across open documents. Falls back to in memory storage when localStorage is
|
|
124
|
+
* unavailable.
|
|
125
|
+
*
|
|
126
|
+
* This hook is used in the same way as useState except that you must pass the
|
|
127
|
+
* storage key in the 1st parameter. If the window object is not present (as in SSR),
|
|
128
|
+
* useStorage() will return the default nextState.
|
|
129
|
+
*
|
|
130
|
+
* Expect values to remain in sync
|
|
131
|
+
* Across Hooks
|
|
132
|
+
* Across Reloads
|
|
133
|
+
* Across Windows (Documents)
|
|
134
|
+
*
|
|
135
|
+
* @param key
|
|
136
|
+
* @param initialState
|
|
137
|
+
* @returns {Array} [storage, setStorage]
|
|
138
|
+
*/
|
|
139
|
+
declare const useStorage: <T>(key: string, initialState?: Maybe<T>) => [Maybe<T> | undefined, Dispatch<SetStateAction<Maybe<T> | undefined>>];
|
|
140
|
+
|
|
141
|
+
export { useAuthenticateSession, useEventListener, useIdentifySession, useImportSession, useIsomorphicLayoutEffect, useQuilttClient, useQuilttConnector, useQuilttInstitutions, useQuilttRenderGuard, useQuilttResolvable, useQuilttSession, useQuilttSettings, useRevokeSession, useSession, useStorage };
|
|
142
|
+
export type { AuthenticateSession, IdentifySession, ImportSession, RevokeSession, SetSession, UseQuilttInstitutions, UseQuilttResolvable, UseQuilttSession };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { u as useEventListener } from './useEventListener-12s-D_-6QIXa.js';
|
|
2
|
+
export { u as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect-12s-DeTHOKz1.js';
|
|
3
|
+
export { a as useAuthenticateSession, b as useIdentifySession, c as useImportSession, u as useQuilttSession, d as useRevokeSession } from './useQuilttSession-12s-DQFfjmob.js';
|
|
4
|
+
export { u as useQuilttClient } from './useQuilttClient-12s-Dj_MtYTU.js';
|
|
5
|
+
export { u as useQuilttConnector } from './useQuilttConnector-12s-BLZ0GoAH.js';
|
|
6
|
+
export { u as useQuilttInstitutions } from './useQuilttInstitutions-12s-ByXIt9W6.js';
|
|
7
|
+
export { u as useQuilttRenderGuard } from './useQuilttRenderGuard-12s-CsS2Ma6Q.js';
|
|
8
|
+
export { u as useQuilttResolvable } from './useQuilttResolvable-12s-C5DByktm.js';
|
|
9
|
+
export { u as useQuilttSettings } from './useQuilttSettings-12s--rCJoNHD.js';
|
|
10
|
+
export { u as useSession } from './useSession-12s-BNPsfKY-.js';
|
|
11
|
+
export { u as useStorage } from './useStorage-12s-CpG6X57D.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var react = require('react');
|
|
3
|
+
var useIsomorphicLayoutEffect12s = require('./useIsomorphicLayoutEffect-12s-B8KjaroI.cjs');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supports Window, Element and Document and custom events with almost
|
|
7
|
+
* the same parameters as the native addEventListener options.
|
|
8
|
+
*/ function useEventListener(eventName, handler, element, options) {
|
|
9
|
+
// Create a ref that stores handler
|
|
10
|
+
const savedHandler = react.useRef(handler);
|
|
11
|
+
useIsomorphicLayoutEffect12s.useIsomorphicLayoutEffect(()=>{
|
|
12
|
+
savedHandler.current = handler;
|
|
13
|
+
}, [
|
|
14
|
+
handler
|
|
15
|
+
]);
|
|
16
|
+
react.useEffect(()=>{
|
|
17
|
+
// Define the listening target
|
|
18
|
+
const targetElement = element?.current ?? window;
|
|
19
|
+
if (!targetElement?.addEventListener) return;
|
|
20
|
+
// Create event listener that calls handler function stored in ref
|
|
21
|
+
const listener = (event)=>savedHandler.current(event);
|
|
22
|
+
targetElement.addEventListener(eventName, listener, options);
|
|
23
|
+
// Remove event listener on cleanup
|
|
24
|
+
return ()=>{
|
|
25
|
+
targetElement.removeEventListener(eventName, listener, options);
|
|
26
|
+
};
|
|
27
|
+
}, [
|
|
28
|
+
eventName,
|
|
29
|
+
element,
|
|
30
|
+
options
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.useEventListener = useEventListener;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var react = require('react');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This hook is a browser hook. But React code could be generated from the server without the Window API.
|
|
6
|
+
* This hook switches between useEffect and useLayoutEffect following the execution environment.
|
|
7
|
+
*/ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? react.useLayoutEffect : react.useEffect;
|
|
8
|
+
|
|
9
|
+
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
import { cdnBase } from '@quiltt/core';
|
|
4
|
+
import { u as useQuilttSession } from './useQuilttSession-12s-DQFfjmob.js';
|
|
5
|
+
import { u as useScript } from './useScript-12s-JCgaTW9n.js';
|
|
6
|
+
import { getUserAgent, isDeepEqual } from '../utils/index.js';
|
|
7
|
+
|
|
8
|
+
var version = "5.0.2";
|
|
9
|
+
|
|
10
|
+
const useQuilttConnector = (connectorId, options)=>{
|
|
11
|
+
const userAgent = getUserAgent(version);
|
|
12
|
+
const status = useScript(`${cdnBase}/v1/connector.js?agent=${encodeURIComponent(userAgent)}`, {
|
|
13
|
+
nonce: options?.nonce
|
|
14
|
+
});
|
|
15
|
+
// This ensures we're not destructuring `session` before the script has loaded
|
|
16
|
+
const useQuilttSessionReturn = useQuilttSession();
|
|
17
|
+
const session = useQuilttSessionReturn?.session || null;
|
|
18
|
+
const [connector, setConnector] = useState();
|
|
19
|
+
const [isOpening, setIsOpening] = useState(false);
|
|
20
|
+
// Keep track of the previous connectionId to detect changes
|
|
21
|
+
const prevConnectionIdRef = useRef(options?.connectionId);
|
|
22
|
+
const prevConnectorIdRef = useRef(connectorId);
|
|
23
|
+
const prevInstitutionRef = useRef(options?.institution);
|
|
24
|
+
const connectorCreatedRef = useRef(false);
|
|
25
|
+
// Track whether the connector is currently open
|
|
26
|
+
const isConnectorOpenRef = useRef(false);
|
|
27
|
+
// Store callbacks in refs to maintain stable references
|
|
28
|
+
const callbacksRef = useRef(options || {});
|
|
29
|
+
useEffect(()=>{
|
|
30
|
+
callbacksRef.current = options || {};
|
|
31
|
+
});
|
|
32
|
+
// Set Session
|
|
33
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: trigger effects when script status changes too
|
|
34
|
+
useEffect(()=>{
|
|
35
|
+
if (typeof Quiltt === 'undefined') return;
|
|
36
|
+
Quiltt.authenticate(session?.token);
|
|
37
|
+
}, [
|
|
38
|
+
status,
|
|
39
|
+
session?.token
|
|
40
|
+
]);
|
|
41
|
+
// Set Connector
|
|
42
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: trigger effects when script status changes too
|
|
43
|
+
useEffect(()=>{
|
|
44
|
+
if (typeof Quiltt === 'undefined' || !connectorId) return;
|
|
45
|
+
const currentConnectionId = options?.connectionId;
|
|
46
|
+
const currentInstitution = options?.institution;
|
|
47
|
+
// Check for changes - use deep equality for institution object
|
|
48
|
+
const connectionIdChanged = prevConnectionIdRef.current !== currentConnectionId;
|
|
49
|
+
const connectorIdChanged = prevConnectorIdRef.current !== connectorId;
|
|
50
|
+
const institutionChanged = !isDeepEqual(prevInstitutionRef.current, currentInstitution);
|
|
51
|
+
const hasChanges = connectionIdChanged || connectorIdChanged || institutionChanged || !connectorCreatedRef.current;
|
|
52
|
+
// Update if there are changes, regardless of what the changes are
|
|
53
|
+
if (hasChanges) {
|
|
54
|
+
if (currentConnectionId) {
|
|
55
|
+
// Always use reconnect when connectionId is available
|
|
56
|
+
setConnector(Quiltt.reconnect(connectorId, {
|
|
57
|
+
connectionId: currentConnectionId
|
|
58
|
+
}));
|
|
59
|
+
} else {
|
|
60
|
+
// Use connect for new connections without connectionId
|
|
61
|
+
setConnector(Quiltt.connect(connectorId, {
|
|
62
|
+
institution: currentInstitution
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
// Update refs
|
|
66
|
+
connectorCreatedRef.current = true;
|
|
67
|
+
prevConnectionIdRef.current = currentConnectionId;
|
|
68
|
+
prevConnectorIdRef.current = connectorId;
|
|
69
|
+
prevInstitutionRef.current = currentInstitution;
|
|
70
|
+
}
|
|
71
|
+
}, [
|
|
72
|
+
connectorId,
|
|
73
|
+
options?.connectionId,
|
|
74
|
+
options?.institution,
|
|
75
|
+
status
|
|
76
|
+
]);
|
|
77
|
+
// Internal handlers to track connector state (stable references)
|
|
78
|
+
const handleOpen = useCallback((metadata)=>{
|
|
79
|
+
isConnectorOpenRef.current = true;
|
|
80
|
+
callbacksRef.current?.onOpen?.(metadata);
|
|
81
|
+
}, []);
|
|
82
|
+
const handleExit = useCallback((type, metadata)=>{
|
|
83
|
+
isConnectorOpenRef.current = false;
|
|
84
|
+
callbacksRef.current?.onExit?.(type, metadata);
|
|
85
|
+
}, []);
|
|
86
|
+
// Create stable wrapper functions for callbacks
|
|
87
|
+
const stableOnEvent = useCallback((type, metadata)=>{
|
|
88
|
+
callbacksRef.current?.onEvent?.(type, metadata);
|
|
89
|
+
}, []);
|
|
90
|
+
const stableOnLoad = useCallback((metadata)=>{
|
|
91
|
+
callbacksRef.current?.onLoad?.(metadata);
|
|
92
|
+
}, []);
|
|
93
|
+
const stableOnExitSuccess = useCallback((metadata)=>{
|
|
94
|
+
callbacksRef.current?.onExitSuccess?.(metadata);
|
|
95
|
+
}, []);
|
|
96
|
+
const stableOnExitAbort = useCallback((metadata)=>{
|
|
97
|
+
callbacksRef.current?.onExitAbort?.(metadata);
|
|
98
|
+
}, []);
|
|
99
|
+
const stableOnExitError = useCallback((metadata)=>{
|
|
100
|
+
callbacksRef.current?.onExitError?.(metadata);
|
|
101
|
+
}, []);
|
|
102
|
+
// Register event handlers (only re-runs when connector changes)
|
|
103
|
+
useEffect(()=>{
|
|
104
|
+
if (!connector) return;
|
|
105
|
+
// Capture which handlers we're registering to ensure proper cleanup
|
|
106
|
+
const registered = {
|
|
107
|
+
onEvent: callbacksRef.current?.onEvent ? stableOnEvent : null,
|
|
108
|
+
onOpen: callbacksRef.current?.onOpen ? handleOpen : null,
|
|
109
|
+
onLoad: callbacksRef.current?.onLoad ? stableOnLoad : null,
|
|
110
|
+
onExit: callbacksRef.current?.onExit ? handleExit : null,
|
|
111
|
+
onExitSuccess: callbacksRef.current?.onExitSuccess ? stableOnExitSuccess : null,
|
|
112
|
+
onExitAbort: callbacksRef.current?.onExitAbort ? stableOnExitAbort : null,
|
|
113
|
+
onExitError: callbacksRef.current?.onExitError ? stableOnExitError : null
|
|
114
|
+
};
|
|
115
|
+
if (registered.onEvent) connector.onEvent(registered.onEvent);
|
|
116
|
+
if (registered.onOpen) connector.onOpen(registered.onOpen);
|
|
117
|
+
if (registered.onLoad) connector.onLoad(registered.onLoad);
|
|
118
|
+
if (registered.onExit) connector.onExit(registered.onExit);
|
|
119
|
+
if (registered.onExitSuccess) connector.onExitSuccess(registered.onExitSuccess);
|
|
120
|
+
if (registered.onExitAbort) connector.onExitAbort(registered.onExitAbort);
|
|
121
|
+
if (registered.onExitError) connector.onExitError(registered.onExitError);
|
|
122
|
+
return ()=>{
|
|
123
|
+
if (registered.onEvent) connector.offEvent(registered.onEvent);
|
|
124
|
+
if (registered.onOpen) connector.offOpen(registered.onOpen);
|
|
125
|
+
if (registered.onLoad) connector.offLoad(registered.onLoad);
|
|
126
|
+
if (registered.onExit) connector.offExit(registered.onExit);
|
|
127
|
+
if (registered.onExitSuccess) connector.offExitSuccess(registered.onExitSuccess);
|
|
128
|
+
if (registered.onExitAbort) connector.offExitAbort(registered.onExitAbort);
|
|
129
|
+
if (registered.onExitError) connector.offExitError(registered.onExitError);
|
|
130
|
+
};
|
|
131
|
+
}, [
|
|
132
|
+
connector,
|
|
133
|
+
stableOnEvent,
|
|
134
|
+
handleOpen,
|
|
135
|
+
stableOnLoad,
|
|
136
|
+
handleExit,
|
|
137
|
+
stableOnExitSuccess,
|
|
138
|
+
stableOnExitAbort,
|
|
139
|
+
stableOnExitError
|
|
140
|
+
]);
|
|
141
|
+
// This is used to hide any potential race conditions from usage; allowing
|
|
142
|
+
// interaction before the script may have loaded.
|
|
143
|
+
useEffect(()=>{
|
|
144
|
+
if (connector && isOpening) {
|
|
145
|
+
setIsOpening(false);
|
|
146
|
+
connector.open();
|
|
147
|
+
}
|
|
148
|
+
}, [
|
|
149
|
+
connector,
|
|
150
|
+
isOpening
|
|
151
|
+
]);
|
|
152
|
+
// Cleanup effect - runs when the hook is torn down
|
|
153
|
+
useEffect(()=>{
|
|
154
|
+
return ()=>{
|
|
155
|
+
if (isConnectorOpenRef.current) {
|
|
156
|
+
console.error('[Quiltt] useQuilttConnector: Component unmounted while Connector is still open. ' + 'This may lead to memory leaks or unexpected behavior. ' + 'Ensure the Connector is properly closed before component unmount.');
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}, []);
|
|
160
|
+
const open = useCallback(()=>{
|
|
161
|
+
if (connectorId) {
|
|
162
|
+
setIsOpening(true);
|
|
163
|
+
} else {
|
|
164
|
+
throw new Error('Must provide `connectorId` to `open` Quiltt Connector with Method Call');
|
|
165
|
+
}
|
|
166
|
+
}, [
|
|
167
|
+
connectorId
|
|
168
|
+
]);
|
|
169
|
+
return {
|
|
170
|
+
open
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export { useQuilttConnector as u, version as v };
|