@ilivemylife/react-sdk 0.1.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.
@@ -0,0 +1,205 @@
1
+ import * as react from 'react';
2
+
3
+ /** Build the SSO login URL from ssoUrl + optional route/clientId. */
4
+ declare function getSsoLoginUrl(ssoUrl: string, options?: {
5
+ addTimestamp?: boolean;
6
+ route?: string;
7
+ clientId?: string;
8
+ }): string;
9
+ /** Center a popup on screen. */
10
+ declare function popupCenterParams(width: number, height: number): {
11
+ left: number;
12
+ top: number;
13
+ };
14
+ /** SECURITY: verify a postMessage event came from the iLML SSO origin. */
15
+ declare function isValidSsoOrigin(event: MessageEvent, ssoUrl: string): boolean;
16
+
17
+ interface UseIlmlSsoOptions {
18
+ /** iLML SSO base origin, e.g. "https://ilivemylife.io". */
19
+ ssoUrl: string;
20
+ /** Login route under ssoUrl (e.g. "partnerLogin"). */
21
+ ssoRoute?: string;
22
+ /** Client id passed to the wallet for per-partner branding (not a security boundary). */
23
+ clientId?: string;
24
+ /**
25
+ * Called with the iLML SSO payload `event.data.data` (`{ accessToken, ...user }`)
26
+ * on successful login. The consumer app decides what to do (exchange for its own
27
+ * token, set auth state, etc.). Return value is ignored.
28
+ */
29
+ onSsoData: (data: {
30
+ accessToken?: string;
31
+ [k: string]: unknown;
32
+ }) => void | Promise<void>;
33
+ /** Called on loginError / signupError from the popup. */
34
+ onError?: (kind: 'loginError' | 'signupError') => void;
35
+ /** Called when the login popup is closed WITHOUT a successful login — the user canceled it, or the
36
+ * browser blocked it. Lets the consumer clear a "signing in…" state deterministically instead of
37
+ * guessing via window focus + timers. NOT fired on success (the hook closes the popup itself). */
38
+ onClose?: () => void;
39
+ /** Success type sent by iLML (default "loginSuccess"). */
40
+ responseType?: string;
41
+ windowName?: string;
42
+ width?: number;
43
+ height?: number;
44
+ }
45
+ declare function useIlmlSso(opts: UseIlmlSsoOptions): {
46
+ openLogin: () => void;
47
+ };
48
+
49
+ interface IlmlChatProps {
50
+ /** iLML SSO/app base origin, e.g. "https://ilivemylife.io". */
51
+ ssoUrl: string;
52
+ /** The graph node whose chat to embed (resolved by the consuming app). */
53
+ nodeId: string;
54
+ /**
55
+ * iLML wallet access token, used by the embed when Storage Access API isn't
56
+ * available. Defaults to localStorage "walletAccessToken" (set by useIlmlSso).
57
+ */
58
+ token?: string | null;
59
+ /**
60
+ * Optional readiness gate. A just-created (or just-granted) node lands in the read model a moment
61
+ * after the command succeeds; the embed crashes if it queries the node before then. When provided,
62
+ * the token handshake polls this until it resolves true (bounded ~15s) before handing the token
63
+ * over, so the embed only initialises once the node is readable. Omit for already-existing nodes.
64
+ */
65
+ isNodeReady?: (nodeId: string) => Promise<boolean>;
66
+ /** Optional style/class for the iframe wrapper. */
67
+ className?: string;
68
+ style?: React.CSSProperties;
69
+ }
70
+ /**
71
+ * Renders the iLML chat for `nodeId` as a sandboxed iframe and performs the
72
+ * `messengerReady` -> `initMessenger` token handshake. Origin is verified before
73
+ * any postMessage is sent. Waits for `isNodeReady` (when given) before handing over the token.
74
+ * Shows a loading overlay until the messenger is ready — covers both the iframe's own load and the
75
+ * `isNodeReady` wait, so the user sees progress instead of a blank white frame.
76
+ */
77
+ declare function IlmlChat({ ssoUrl, nodeId, token, isNodeReady, className, style }: IlmlChatProps): react.JSX.Element;
78
+
79
+ interface IlmlChatWidgetProps {
80
+ /** iLML SSO/app base origin. */
81
+ ssoUrl: string;
82
+ /** The conversation node to embed. */
83
+ nodeId: string;
84
+ /** Wallet access token; defaults to localStorage "walletAccessToken". */
85
+ token?: string | null;
86
+ /** Header label — usually the counterpart / conversation name. */
87
+ title?: string;
88
+ /** Close the widget (the owner removes it from its dock). Omit to hide the control. */
89
+ onClose?: () => void;
90
+ /** Minimize (the owner collapses it to a bar). Omit to hide the control. */
91
+ onMinimize?: () => void;
92
+ /** Readiness gate forwarded to IlmlChat — see IlmlChatProps.isNodeReady. */
93
+ isNodeReady?: (nodeId: string) => Promise<boolean>;
94
+ /** Show the expand-to-fullscreen control. Default true. */
95
+ allowFullscreen?: boolean;
96
+ /** Show the "full height" control — stretches the docked box to fill the viewport height at the SAME
97
+ * width (unlike fullscreen, which fills width too). Default true. */
98
+ allowTall?: boolean;
99
+ /** Header background (partner brand colour). Default iLML blue. */
100
+ accentColor?: string;
101
+ /** Docked-state box className/style (the owner may resize/position). Ignored when expanded. */
102
+ className?: string;
103
+ style?: React.CSSProperties;
104
+ }
105
+ declare function IlmlChatWidget({ ssoUrl, nodeId, token, title, onClose, onMinimize, isNodeReady, allowFullscreen, allowTall, accentColor, className, style, }: IlmlChatWidgetProps): react.JSX.Element;
106
+
107
+ interface IlmlButtonProps {
108
+ /** If set, renders an <a> to this href; otherwise a <button>. */
109
+ href?: string;
110
+ onClick?: () => void;
111
+ disabled?: boolean;
112
+ target?: string;
113
+ rel?: string;
114
+ type?: 'button' | 'submit';
115
+ className?: string;
116
+ style?: React.CSSProperties;
117
+ children: React.ReactNode;
118
+ }
119
+ declare function IlmlButton({ href, onClick, disabled, target, rel, type, className, style, children, }: IlmlButtonProps): react.JSX.Element;
120
+
121
+ interface IlmlProfile {
122
+ /** User id in the graph. */
123
+ id?: string;
124
+ /** Display name (falls back to fullName/email). */
125
+ name: string;
126
+ /** Avatar image URL, if the user has one. */
127
+ avatar?: string;
128
+ email?: string;
129
+ }
130
+ interface UseIlmlProfileOptions {
131
+ /** iLML graphql endpoint, e.g. "https://api.ilivemylife.io/graphql/v1" (default). */
132
+ graphqlUrl?: string;
133
+ }
134
+ /**
135
+ * Fetch the current user's profile for a wallet access token.
136
+ * `profile: null` while loading, without a token, or on failure. `invalid: true` marks a DEFINITIVE
137
+ * bad/expired token so the consumer can clear it (sign out); transient errors leave `invalid: false`.
138
+ */
139
+ declare function useIlmlProfile(token: string | null | undefined, opts?: UseIlmlProfileOptions): {
140
+ profile: IlmlProfile | null;
141
+ loading: boolean;
142
+ invalid: boolean;
143
+ };
144
+
145
+ interface UseIlmlSessionOptions {
146
+ /** iLML SSO/app base origin (login popup + deep links). */
147
+ ssoUrl: string;
148
+ /** Login route under ssoUrl (e.g. "partnerLogin"). */
149
+ ssoRoute?: string;
150
+ /** Client id for per-partner login branding (not a security boundary). */
151
+ clientId?: string;
152
+ /** iLML graphql endpoint — resolves the token into `me`. */
153
+ graphqlUrl: string;
154
+ /** App-specific side-effect run once per DISTINCT token (onboarding, analytics). The token is set
155
+ * regardless of the result; return a Promise and a REJECTION lets a later navigation retry (the
156
+ * token is un-remembered), so a transient onboarding failure isn't permanent for the session. */
157
+ onNewToken?: (token: string) => void | Promise<void>;
158
+ /** localStorage key for the wallet token. Defaults to 'walletAccessToken' — the SAME key useIlmlSso
159
+ * writes on login, so the store reads exactly what the handshake saved. */
160
+ tokenKey?: string;
161
+ /** localStorage key for the cached profile (instant chip paint after reload). */
162
+ profileKey?: string;
163
+ /** Called when the login popup closes WITHOUT signing in (cancel / blocked). */
164
+ onLoginClose?: () => void;
165
+ }
166
+ /** Imperative sign-out for non-React code (a transport layer that saw a dead token). Clears the same
167
+ * singleton the hooks read, so the account chip and everything else update. */
168
+ declare function signOutIlmlSession(): void;
169
+ /** The wallet token this browser currently holds (or null) — for non-React callers. */
170
+ declare function getIlmlToken(): string | null;
171
+ /** Read-only view of the shared session (token + profile). */
172
+ interface IlmlSessionState {
173
+ /** The wallet token, or null when signed out. */
174
+ token: string | null;
175
+ isLoggedIn: boolean;
176
+ /** True once the token has been read from storage — gate UI on this to avoid a sign-in flash. */
177
+ ready: boolean;
178
+ /** The signed-in user (name/avatar/email), shared across all consumers; null while loading/out. */
179
+ profile: IlmlProfile | null;
180
+ profileLoading: boolean;
181
+ /** True when the token is DEFINITIVELY bad (already cleared) — vs a transient fetch error. */
182
+ profileInvalid: boolean;
183
+ }
184
+ interface IlmlSession extends IlmlSessionState {
185
+ /** Open the login popup. */
186
+ login: () => void;
187
+ /** Clear the session everywhere. */
188
+ logout: () => void;
189
+ }
190
+ /**
191
+ * Read the shared session (token + profile) WITHOUT instantiating the login handshake — for consumers
192
+ * that only display session state (account chips, gated links, dashboards). A full useIlmlSession()
193
+ * must be mounted somewhere in the app to supply config and drive login. One `me` fetch is shared
194
+ * across every useIlmlSessionState + useIlmlSession consumer.
195
+ */
196
+ declare function useIlmlSessionState(): IlmlSessionState;
197
+ /**
198
+ * Site-wide iLML session (token + profile) PLUS login/logout, shared across every consumer in the
199
+ * app. Login/logout from any surface propagates to all of them. Pass config once; later calls reuse
200
+ * the singleton. Instantiate this where login is driven (e.g. the header); elsewhere prefer the
201
+ * lighter useIlmlSessionState().
202
+ */
203
+ declare function useIlmlSession(opts: UseIlmlSessionOptions): IlmlSession;
204
+
205
+ export { IlmlButton, type IlmlButtonProps, IlmlChat, type IlmlChatProps, IlmlChatWidget, type IlmlChatWidgetProps, type IlmlProfile, type IlmlSession, type IlmlSessionState, type UseIlmlProfileOptions, type UseIlmlSessionOptions, type UseIlmlSsoOptions, getIlmlToken, getSsoLoginUrl, isValidSsoOrigin, popupCenterParams, signOutIlmlSession, useIlmlProfile, useIlmlSession, useIlmlSessionState, useIlmlSso };
@@ -0,0 +1,205 @@
1
+ import * as react from 'react';
2
+
3
+ /** Build the SSO login URL from ssoUrl + optional route/clientId. */
4
+ declare function getSsoLoginUrl(ssoUrl: string, options?: {
5
+ addTimestamp?: boolean;
6
+ route?: string;
7
+ clientId?: string;
8
+ }): string;
9
+ /** Center a popup on screen. */
10
+ declare function popupCenterParams(width: number, height: number): {
11
+ left: number;
12
+ top: number;
13
+ };
14
+ /** SECURITY: verify a postMessage event came from the iLML SSO origin. */
15
+ declare function isValidSsoOrigin(event: MessageEvent, ssoUrl: string): boolean;
16
+
17
+ interface UseIlmlSsoOptions {
18
+ /** iLML SSO base origin, e.g. "https://ilivemylife.io". */
19
+ ssoUrl: string;
20
+ /** Login route under ssoUrl (e.g. "partnerLogin"). */
21
+ ssoRoute?: string;
22
+ /** Client id passed to the wallet for per-partner branding (not a security boundary). */
23
+ clientId?: string;
24
+ /**
25
+ * Called with the iLML SSO payload `event.data.data` (`{ accessToken, ...user }`)
26
+ * on successful login. The consumer app decides what to do (exchange for its own
27
+ * token, set auth state, etc.). Return value is ignored.
28
+ */
29
+ onSsoData: (data: {
30
+ accessToken?: string;
31
+ [k: string]: unknown;
32
+ }) => void | Promise<void>;
33
+ /** Called on loginError / signupError from the popup. */
34
+ onError?: (kind: 'loginError' | 'signupError') => void;
35
+ /** Called when the login popup is closed WITHOUT a successful login — the user canceled it, or the
36
+ * browser blocked it. Lets the consumer clear a "signing in…" state deterministically instead of
37
+ * guessing via window focus + timers. NOT fired on success (the hook closes the popup itself). */
38
+ onClose?: () => void;
39
+ /** Success type sent by iLML (default "loginSuccess"). */
40
+ responseType?: string;
41
+ windowName?: string;
42
+ width?: number;
43
+ height?: number;
44
+ }
45
+ declare function useIlmlSso(opts: UseIlmlSsoOptions): {
46
+ openLogin: () => void;
47
+ };
48
+
49
+ interface IlmlChatProps {
50
+ /** iLML SSO/app base origin, e.g. "https://ilivemylife.io". */
51
+ ssoUrl: string;
52
+ /** The graph node whose chat to embed (resolved by the consuming app). */
53
+ nodeId: string;
54
+ /**
55
+ * iLML wallet access token, used by the embed when Storage Access API isn't
56
+ * available. Defaults to localStorage "walletAccessToken" (set by useIlmlSso).
57
+ */
58
+ token?: string | null;
59
+ /**
60
+ * Optional readiness gate. A just-created (or just-granted) node lands in the read model a moment
61
+ * after the command succeeds; the embed crashes if it queries the node before then. When provided,
62
+ * the token handshake polls this until it resolves true (bounded ~15s) before handing the token
63
+ * over, so the embed only initialises once the node is readable. Omit for already-existing nodes.
64
+ */
65
+ isNodeReady?: (nodeId: string) => Promise<boolean>;
66
+ /** Optional style/class for the iframe wrapper. */
67
+ className?: string;
68
+ style?: React.CSSProperties;
69
+ }
70
+ /**
71
+ * Renders the iLML chat for `nodeId` as a sandboxed iframe and performs the
72
+ * `messengerReady` -> `initMessenger` token handshake. Origin is verified before
73
+ * any postMessage is sent. Waits for `isNodeReady` (when given) before handing over the token.
74
+ * Shows a loading overlay until the messenger is ready — covers both the iframe's own load and the
75
+ * `isNodeReady` wait, so the user sees progress instead of a blank white frame.
76
+ */
77
+ declare function IlmlChat({ ssoUrl, nodeId, token, isNodeReady, className, style }: IlmlChatProps): react.JSX.Element;
78
+
79
+ interface IlmlChatWidgetProps {
80
+ /** iLML SSO/app base origin. */
81
+ ssoUrl: string;
82
+ /** The conversation node to embed. */
83
+ nodeId: string;
84
+ /** Wallet access token; defaults to localStorage "walletAccessToken". */
85
+ token?: string | null;
86
+ /** Header label — usually the counterpart / conversation name. */
87
+ title?: string;
88
+ /** Close the widget (the owner removes it from its dock). Omit to hide the control. */
89
+ onClose?: () => void;
90
+ /** Minimize (the owner collapses it to a bar). Omit to hide the control. */
91
+ onMinimize?: () => void;
92
+ /** Readiness gate forwarded to IlmlChat — see IlmlChatProps.isNodeReady. */
93
+ isNodeReady?: (nodeId: string) => Promise<boolean>;
94
+ /** Show the expand-to-fullscreen control. Default true. */
95
+ allowFullscreen?: boolean;
96
+ /** Show the "full height" control — stretches the docked box to fill the viewport height at the SAME
97
+ * width (unlike fullscreen, which fills width too). Default true. */
98
+ allowTall?: boolean;
99
+ /** Header background (partner brand colour). Default iLML blue. */
100
+ accentColor?: string;
101
+ /** Docked-state box className/style (the owner may resize/position). Ignored when expanded. */
102
+ className?: string;
103
+ style?: React.CSSProperties;
104
+ }
105
+ declare function IlmlChatWidget({ ssoUrl, nodeId, token, title, onClose, onMinimize, isNodeReady, allowFullscreen, allowTall, accentColor, className, style, }: IlmlChatWidgetProps): react.JSX.Element;
106
+
107
+ interface IlmlButtonProps {
108
+ /** If set, renders an <a> to this href; otherwise a <button>. */
109
+ href?: string;
110
+ onClick?: () => void;
111
+ disabled?: boolean;
112
+ target?: string;
113
+ rel?: string;
114
+ type?: 'button' | 'submit';
115
+ className?: string;
116
+ style?: React.CSSProperties;
117
+ children: React.ReactNode;
118
+ }
119
+ declare function IlmlButton({ href, onClick, disabled, target, rel, type, className, style, children, }: IlmlButtonProps): react.JSX.Element;
120
+
121
+ interface IlmlProfile {
122
+ /** User id in the graph. */
123
+ id?: string;
124
+ /** Display name (falls back to fullName/email). */
125
+ name: string;
126
+ /** Avatar image URL, if the user has one. */
127
+ avatar?: string;
128
+ email?: string;
129
+ }
130
+ interface UseIlmlProfileOptions {
131
+ /** iLML graphql endpoint, e.g. "https://api.ilivemylife.io/graphql/v1" (default). */
132
+ graphqlUrl?: string;
133
+ }
134
+ /**
135
+ * Fetch the current user's profile for a wallet access token.
136
+ * `profile: null` while loading, without a token, or on failure. `invalid: true` marks a DEFINITIVE
137
+ * bad/expired token so the consumer can clear it (sign out); transient errors leave `invalid: false`.
138
+ */
139
+ declare function useIlmlProfile(token: string | null | undefined, opts?: UseIlmlProfileOptions): {
140
+ profile: IlmlProfile | null;
141
+ loading: boolean;
142
+ invalid: boolean;
143
+ };
144
+
145
+ interface UseIlmlSessionOptions {
146
+ /** iLML SSO/app base origin (login popup + deep links). */
147
+ ssoUrl: string;
148
+ /** Login route under ssoUrl (e.g. "partnerLogin"). */
149
+ ssoRoute?: string;
150
+ /** Client id for per-partner login branding (not a security boundary). */
151
+ clientId?: string;
152
+ /** iLML graphql endpoint — resolves the token into `me`. */
153
+ graphqlUrl: string;
154
+ /** App-specific side-effect run once per DISTINCT token (onboarding, analytics). The token is set
155
+ * regardless of the result; return a Promise and a REJECTION lets a later navigation retry (the
156
+ * token is un-remembered), so a transient onboarding failure isn't permanent for the session. */
157
+ onNewToken?: (token: string) => void | Promise<void>;
158
+ /** localStorage key for the wallet token. Defaults to 'walletAccessToken' — the SAME key useIlmlSso
159
+ * writes on login, so the store reads exactly what the handshake saved. */
160
+ tokenKey?: string;
161
+ /** localStorage key for the cached profile (instant chip paint after reload). */
162
+ profileKey?: string;
163
+ /** Called when the login popup closes WITHOUT signing in (cancel / blocked). */
164
+ onLoginClose?: () => void;
165
+ }
166
+ /** Imperative sign-out for non-React code (a transport layer that saw a dead token). Clears the same
167
+ * singleton the hooks read, so the account chip and everything else update. */
168
+ declare function signOutIlmlSession(): void;
169
+ /** The wallet token this browser currently holds (or null) — for non-React callers. */
170
+ declare function getIlmlToken(): string | null;
171
+ /** Read-only view of the shared session (token + profile). */
172
+ interface IlmlSessionState {
173
+ /** The wallet token, or null when signed out. */
174
+ token: string | null;
175
+ isLoggedIn: boolean;
176
+ /** True once the token has been read from storage — gate UI on this to avoid a sign-in flash. */
177
+ ready: boolean;
178
+ /** The signed-in user (name/avatar/email), shared across all consumers; null while loading/out. */
179
+ profile: IlmlProfile | null;
180
+ profileLoading: boolean;
181
+ /** True when the token is DEFINITIVELY bad (already cleared) — vs a transient fetch error. */
182
+ profileInvalid: boolean;
183
+ }
184
+ interface IlmlSession extends IlmlSessionState {
185
+ /** Open the login popup. */
186
+ login: () => void;
187
+ /** Clear the session everywhere. */
188
+ logout: () => void;
189
+ }
190
+ /**
191
+ * Read the shared session (token + profile) WITHOUT instantiating the login handshake — for consumers
192
+ * that only display session state (account chips, gated links, dashboards). A full useIlmlSession()
193
+ * must be mounted somewhere in the app to supply config and drive login. One `me` fetch is shared
194
+ * across every useIlmlSessionState + useIlmlSession consumer.
195
+ */
196
+ declare function useIlmlSessionState(): IlmlSessionState;
197
+ /**
198
+ * Site-wide iLML session (token + profile) PLUS login/logout, shared across every consumer in the
199
+ * app. Login/logout from any surface propagates to all of them. Pass config once; later calls reuse
200
+ * the singleton. Instantiate this where login is driven (e.g. the header); elsewhere prefer the
201
+ * lighter useIlmlSessionState().
202
+ */
203
+ declare function useIlmlSession(opts: UseIlmlSessionOptions): IlmlSession;
204
+
205
+ export { IlmlButton, type IlmlButtonProps, IlmlChat, type IlmlChatProps, IlmlChatWidget, type IlmlChatWidgetProps, type IlmlProfile, type IlmlSession, type IlmlSessionState, type UseIlmlProfileOptions, type UseIlmlSessionOptions, type UseIlmlSsoOptions, getIlmlToken, getSsoLoginUrl, isValidSsoOrigin, popupCenterParams, signOutIlmlSession, useIlmlProfile, useIlmlSession, useIlmlSessionState, useIlmlSso };