@sneekin/ui 0.1.2 → 0.2.1
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 +59 -108
- package/dist/component.d.ts +49 -0
- package/dist/fetch-handlers.d.ts +30 -0
- package/dist/index.d.ts +5 -160
- package/dist/index.js +358 -97
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +362 -97
- package/dist/index.mjs.map +1 -1
- package/dist/state.d.ts +63 -0
- package/dist/theme.d.ts +19 -0
- package/dist/use-sneek-otp.d.ts +40 -0
- package/package.json +9 -9
- package/dist/index.d.mts +0 -160
package/README.md
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
# @sneekin/ui
|
|
2
2
|
|
|
3
|
-
Drop-in
|
|
3
|
+
Drop-in passwordless login for React, powered by [Sneek](https://sneek.in).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`@sneekin/ui` runs in the browser, so it **never holds a Sneek API key**. Instead it
|
|
11
|
-
calls **your own backend**, and your backend calls Sneek server-side with your secret
|
|
12
|
-
key (using [`@sneekin/sdk`](../../sdk)).
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
Browser (@sneekin/ui)
|
|
16
|
-
│ POST /api/auth/request-otp { identifier }
|
|
17
|
-
▼
|
|
18
|
-
Your backend ──(@sneekin/sdk, secret key)──► Sneek API ──► SMS / WhatsApp / Email
|
|
19
|
-
│ POST /api/auth/verify-otp { requestId, code }
|
|
20
|
-
▼
|
|
21
|
-
Your backend issues your session / token
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Putting a Sneek key in front-end code would expose it to every visitor. This package
|
|
25
|
-
is designed so that can't happen.
|
|
5
|
+
- **No API key in the browser.** The component calls handlers you supply, which talk to your own backend.
|
|
6
|
+
- **No dependencies, no stylesheet to import.** One `<style>` element is injected at runtime.
|
|
7
|
+
- **Light and dark**, following the visitor's system setting by default.
|
|
8
|
+
- **Accessible**: labelled inputs, a polite live region for status, and a visible focus ring on every control.
|
|
26
9
|
|
|
27
10
|
## Install
|
|
28
11
|
|
|
@@ -30,123 +13,91 @@ is designed so that can't happen.
|
|
|
30
13
|
npm install @sneekin/ui
|
|
31
14
|
```
|
|
32
15
|
|
|
33
|
-
|
|
16
|
+
React 17 or newer, as a peer dependency.
|
|
34
17
|
|
|
35
|
-
##
|
|
18
|
+
## Use it
|
|
36
19
|
|
|
37
20
|
```tsx
|
|
38
21
|
import { SneekOtpLogin, createFetchHandlers } from '@sneekin/ui';
|
|
39
22
|
|
|
40
|
-
export function
|
|
23
|
+
export function Login() {
|
|
41
24
|
return (
|
|
42
25
|
<SneekOtpLogin
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
requestUrl: '/api/auth/request-otp',
|
|
46
|
-
verifyUrl: '/api/auth/verify-otp',
|
|
47
|
-
})}
|
|
48
|
-
onSuccess={() => {
|
|
49
|
-
window.location.href = '/dashboard';
|
|
50
|
-
}}
|
|
26
|
+
{...createFetchHandlers({ baseUrl: '/api/auth' })}
|
|
27
|
+
onSuccess={(session) => router.push('/app')}
|
|
51
28
|
/>
|
|
52
29
|
);
|
|
53
30
|
}
|
|
54
31
|
```
|
|
55
32
|
|
|
56
|
-
|
|
57
|
-
`/api/auth/request-otp` and `/api/auth/verify-otp`.
|
|
33
|
+
`createFetchHandlers` expects two routes on **your** server:
|
|
58
34
|
|
|
59
|
-
|
|
35
|
+
| Route | Body | Returns |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `POST {baseUrl}/request-otp` | `{ identifier }` | `{ requestId, channels, expiresInSeconds }` |
|
|
38
|
+
| `POST {baseUrl}/verify-otp` | `{ requestId, code }` | whatever your session payload is |
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
// POST /api/auth/request-otp body: { identifier }
|
|
63
|
-
import { Sneek } from '@sneekin/sdk';
|
|
64
|
-
const sneek = new Sneek({ apiKey: process.env.SNEEK_API_KEY! });
|
|
40
|
+
Your server holds the Sneek API key and calls Sneek. The browser never sees it.
|
|
65
41
|
|
|
66
|
-
|
|
67
|
-
return { requestId: otp.id, channels: [otp.channel], expiresInSeconds: 300 };
|
|
42
|
+
## Theming
|
|
68
43
|
|
|
69
|
-
|
|
70
|
-
// verify against your store, then return your own session/token
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
> The exact verify call depends on how you persist the OTP request. Sneek returns a
|
|
74
|
-
> message id on send; store it keyed by `requestId` and check the code your way, or use
|
|
75
|
-
> Sneek's verify endpoint if enabled for your app.
|
|
76
|
-
|
|
77
|
-
## Headless usage
|
|
78
|
-
|
|
79
|
-
Want your own markup? Use the hook:
|
|
44
|
+
It follows the system colour scheme out of the box. Pin it if you prefer:
|
|
80
45
|
|
|
81
46
|
```tsx
|
|
82
|
-
|
|
47
|
+
<SneekOtpLogin theme="dark" {...handlers} />
|
|
48
|
+
```
|
|
83
49
|
|
|
84
|
-
|
|
85
|
-
const otp = useSneekOtp({
|
|
86
|
-
...createFetchHandlers(),
|
|
87
|
-
onSuccess: (user) => console.log('signed in', user),
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (otp.step === 'identify') {
|
|
91
|
-
return (
|
|
92
|
-
<form onSubmit={(e) => { e.preventDefault(); otp.sendOtp(); }}>
|
|
93
|
-
<input value={otp.identifier} onChange={(e) => otp.setIdentifier(e.target.value)} />
|
|
94
|
-
<button disabled={otp.isBusy}>{otp.isSending ? 'Sending…' : 'Send code'}</button>
|
|
95
|
-
{otp.error && <p>{otp.error}</p>}
|
|
96
|
-
</form>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
50
|
+
Override the single accent colour — everything else derives from it:
|
|
99
51
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<input value={otp.code} onChange={(e) => otp.setCode(e.target.value)} />
|
|
103
|
-
<button disabled={otp.isBusy}>{otp.isVerifying ? 'Verifying…' : 'Verify'}</button>
|
|
104
|
-
<button type="button" onClick={otp.back}>Back</button>
|
|
105
|
-
<button type="button" onClick={otp.resend}>Resend</button>
|
|
106
|
-
</form>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
52
|
+
```tsx
|
|
53
|
+
<SneekOtpLogin accentColor="#7c3aed" {...handlers} />
|
|
109
54
|
```
|
|
110
55
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
Don't want `fetch`? Provide `requestOtp` / `verifyOtp` directly:
|
|
56
|
+
Swap the mark, drop the sub-heading, or remove the Sneek line:
|
|
114
57
|
|
|
115
58
|
```tsx
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
onSuccess: (result) => {/* … */},
|
|
123
|
-
});
|
|
59
|
+
<SneekOtpLogin
|
|
60
|
+
logo={<MyLogo />}
|
|
61
|
+
subtitle={null}
|
|
62
|
+
showBranding={false}
|
|
63
|
+
{...handlers}
|
|
64
|
+
/>
|
|
124
65
|
```
|
|
125
66
|
|
|
126
|
-
|
|
67
|
+
For anything further, `className` and `style` land on the outer card, and every
|
|
68
|
+
control carries a stable class (`.sneek-otp-input`, `.sneek-otp-button`,
|
|
69
|
+
`.sneek-otp-link`) you can target.
|
|
127
70
|
|
|
128
|
-
|
|
71
|
+
## Props
|
|
129
72
|
|
|
130
|
-
| Prop | Type | Default |
|
|
131
|
-
| --- | --- | --- |
|
|
132
|
-
| `requestOtp` | `(
|
|
133
|
-
| `verifyOtp` | `(
|
|
134
|
-
| `onSuccess` | `(result:
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
73
|
+
| Prop | Type | Default |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `requestOtp` | `(identifier) => Promise<RequestOtpResult>` | — (required) |
|
|
76
|
+
| `verifyOtp` | `(requestId, code) => Promise<TResult>` | — (required) |
|
|
77
|
+
| `onSuccess` | `(result: TResult) => void` | — |
|
|
78
|
+
| `title` | `string` | `'Sign in'` |
|
|
79
|
+
| `subtitle` | `ReactNode \| null` | `'We will send you a one-time code.'` |
|
|
80
|
+
| `identifierLabel` | `string` | `'Email or mobile'` |
|
|
81
|
+
| `identifierPlaceholder` | `string` | `'you@company.com or +91…'` |
|
|
82
|
+
| `theme` | `'auto' \| 'light' \| 'dark'` | `'auto'` |
|
|
83
|
+
| `accentColor` | `string` | Sneek orange, tuned per mode |
|
|
84
|
+
| `logo` | `ReactNode \| null` | Sneek mark |
|
|
85
|
+
| `showBranding` | `boolean` | `true` |
|
|
86
|
+
| `className` / `style` | — | — |
|
|
141
87
|
|
|
142
|
-
|
|
143
|
-
component or hook.
|
|
88
|
+
## Bring your own markup
|
|
144
89
|
|
|
145
|
-
|
|
90
|
+
If the card does not suit you, use the hook and render whatever you like. It
|
|
91
|
+
holds the whole state machine — step, busy flags, errors, resend:
|
|
146
92
|
|
|
147
|
-
|
|
148
|
-
|
|
93
|
+
```tsx
|
|
94
|
+
import { useSneekOtp, createFetchHandlers } from '@sneekin/ui';
|
|
95
|
+
|
|
96
|
+
const otp = useSneekOtp(createFetchHandlers({ baseUrl: '/api/auth' }));
|
|
97
|
+
// otp.step, otp.identifier, otp.code, otp.error,
|
|
98
|
+
// otp.sendOtp(), otp.verify(), otp.resend(), otp.back()
|
|
99
|
+
```
|
|
149
100
|
|
|
150
101
|
## License
|
|
151
102
|
|
|
152
|
-
UNLICENSED — ©
|
|
103
|
+
UNLICENSED — © Abblor Tech Pvt Ltd.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
import { type SneekOtpHandlers } from './use-sneek-otp';
|
|
3
|
+
export type SneekTheme = 'auto' | 'light' | 'dark';
|
|
4
|
+
export interface SneekOtpLoginProps<TResult = unknown> extends SneekOtpHandlers<TResult> {
|
|
5
|
+
/** Heading above the form. @default 'Sign in' */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** Heading once the code has been sent. @default 'Enter the code' */
|
|
8
|
+
verifyTitle?: string;
|
|
9
|
+
/** Sub-heading. Pass `null` to remove it. */
|
|
10
|
+
subtitle?: ReactNode;
|
|
11
|
+
/** Label for the identifier input. */
|
|
12
|
+
identifierLabel?: string;
|
|
13
|
+
/** Placeholder for the identifier input. */
|
|
14
|
+
identifierPlaceholder?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Colour scheme. `auto` follows the visitor's system setting.
|
|
17
|
+
* @default 'auto'
|
|
18
|
+
*/
|
|
19
|
+
theme?: SneekTheme;
|
|
20
|
+
/**
|
|
21
|
+
* Override the single accent colour. Leave unset to use Sneek orange,
|
|
22
|
+
* which is tuned per mode for contrast.
|
|
23
|
+
*/
|
|
24
|
+
accentColor?: string;
|
|
25
|
+
/** Replaces the Sneek mark above the title. Pass `null` to remove it. */
|
|
26
|
+
logo?: ReactNode;
|
|
27
|
+
/** Show the "Secured by Sneek" line under the form. @default true */
|
|
28
|
+
showBranding?: boolean;
|
|
29
|
+
/** Style overrides for the outer card. */
|
|
30
|
+
style?: CSSProperties;
|
|
31
|
+
/** Extra class on the outer card. */
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Drop-in passwordless login card.
|
|
36
|
+
*
|
|
37
|
+
* The component never receives a Sneek API key — it calls the handlers you
|
|
38
|
+
* supply, which talk to your own backend. See `createFetchHandlers` for the
|
|
39
|
+
* common case.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <SneekOtpLogin
|
|
44
|
+
* {...createFetchHandlers({ baseUrl: '/api/auth' })}
|
|
45
|
+
* onSuccess={(session) => router.push('/app')}
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function SneekOtpLogin<TResult = unknown>(props: SneekOtpLoginProps<TResult>): ReactNode;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RequestOtpResult } from './state';
|
|
2
|
+
export interface FetchHandlerOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Partner backend endpoint that sends an OTP. Receives `{ identifier }`,
|
|
5
|
+
* must return `{ requestId, channels?, expiresInSeconds? }`.
|
|
6
|
+
* @default '/api/auth/request-otp'
|
|
7
|
+
*/
|
|
8
|
+
requestUrl?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Partner backend endpoint that verifies an OTP. Receives
|
|
11
|
+
* `{ requestId, code }`, returns whatever your app needs (session, token…).
|
|
12
|
+
* @default '/api/auth/verify-otp'
|
|
13
|
+
*/
|
|
14
|
+
verifyUrl?: string;
|
|
15
|
+
/** Extra headers (e.g. CSRF token) to send on both requests. */
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
/** Forwarded to fetch — set to 'include' if you use cookie sessions. */
|
|
18
|
+
credentials?: RequestCredentials;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build {@link SneekOtpHandlers} that POST to your own backend endpoints.
|
|
22
|
+
* Those endpoints call the Sneek API server-side with your secret key.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createFetchHandlers<TResult = unknown>(options?: FetchHandlerOptions): {
|
|
25
|
+
requestOtp: (identifier: string) => Promise<RequestOtpResult>;
|
|
26
|
+
verifyOtp: (input: {
|
|
27
|
+
requestId: string;
|
|
28
|
+
code: string;
|
|
29
|
+
}) => Promise<TResult>;
|
|
30
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,160 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Kept free of React so it can be unit-tested in isolation and reused by other
|
|
7
|
-
* front-end bindings later (Vue/Svelte). The hook in `use-sneek-otp.ts` is a
|
|
8
|
-
* thin wrapper around this reducer.
|
|
9
|
-
*/
|
|
10
|
-
type SneekChannel = 'sms' | 'whatsapp' | 'email';
|
|
11
|
-
/** Which screen of the two-step flow is showing. */
|
|
12
|
-
type SneekOtpStep = 'identify' | 'verify';
|
|
13
|
-
/** Async lifecycle for the in-flight request. */
|
|
14
|
-
type SneekOtpStatus = 'idle' | 'sending' | 'verifying';
|
|
15
|
-
interface SneekOtpState {
|
|
16
|
-
step: SneekOtpStep;
|
|
17
|
-
status: SneekOtpStatus;
|
|
18
|
-
/** The email / mobile / username the user typed. */
|
|
19
|
-
identifier: string;
|
|
20
|
-
/** The OTP code the user typed on the verify screen. */
|
|
21
|
-
code: string;
|
|
22
|
-
/** Opaque id returned by the partner backend, replayed on verify. */
|
|
23
|
-
requestId: string;
|
|
24
|
-
/** Channels the OTP was actually delivered over. */
|
|
25
|
-
channels: SneekChannel[];
|
|
26
|
-
/** Seconds until the OTP expires (from the request response). */
|
|
27
|
-
expiresInSeconds: number;
|
|
28
|
-
/** User-facing error message, or null. */
|
|
29
|
-
error: string | null;
|
|
30
|
-
}
|
|
31
|
-
declare const initialOtpState: SneekOtpState;
|
|
32
|
-
interface RequestOtpResult {
|
|
33
|
-
requestId: string;
|
|
34
|
-
channels?: SneekChannel[];
|
|
35
|
-
expiresInSeconds?: number;
|
|
36
|
-
}
|
|
37
|
-
type SneekOtpAction = {
|
|
38
|
-
type: 'set_identifier';
|
|
39
|
-
value: string;
|
|
40
|
-
} | {
|
|
41
|
-
type: 'set_code';
|
|
42
|
-
value: string;
|
|
43
|
-
} | {
|
|
44
|
-
type: 'request_start';
|
|
45
|
-
} | {
|
|
46
|
-
type: 'request_success';
|
|
47
|
-
result: RequestOtpResult;
|
|
48
|
-
} | {
|
|
49
|
-
type: 'request_error';
|
|
50
|
-
message: string;
|
|
51
|
-
} | {
|
|
52
|
-
type: 'verify_start';
|
|
53
|
-
} | {
|
|
54
|
-
type: 'verify_error';
|
|
55
|
-
message: string;
|
|
56
|
-
} | {
|
|
57
|
-
type: 'reset';
|
|
58
|
-
} | {
|
|
59
|
-
type: 'back_to_identify';
|
|
60
|
-
};
|
|
61
|
-
declare function otpReducer(state: SneekOtpState, action: SneekOtpAction): SneekOtpState;
|
|
62
|
-
/** "SMS, WhatsApp" — human label for the channels an OTP was sent over. */
|
|
63
|
-
declare function formatChannels(channels: SneekChannel[]): string;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Partner-supplied transport. These call the *partner's own backend*, which in
|
|
67
|
-
* turn talks to the Sneek API with the secret server-side key. The browser
|
|
68
|
-
* never sees a Sneek API key — that is the whole security model of this package.
|
|
69
|
-
*/
|
|
70
|
-
interface SneekOtpHandlers<TResult = unknown> {
|
|
71
|
-
/** Ask the partner backend to send an OTP to `identifier`. */
|
|
72
|
-
requestOtp: (identifier: string) => Promise<RequestOtpResult>;
|
|
73
|
-
/** Verify the code with the partner backend; resolve with the auth result. */
|
|
74
|
-
verifyOtp: (input: {
|
|
75
|
-
requestId: string;
|
|
76
|
-
code: string;
|
|
77
|
-
}) => Promise<TResult>;
|
|
78
|
-
/** Called after a successful verification with the partner's result. */
|
|
79
|
-
onSuccess?: (result: TResult) => void;
|
|
80
|
-
/** Called on any error (request or verify). */
|
|
81
|
-
onError?: (error: unknown) => void;
|
|
82
|
-
}
|
|
83
|
-
interface UseSneekOtp extends SneekOtpState {
|
|
84
|
-
setIdentifier: (value: string) => void;
|
|
85
|
-
setCode: (value: string) => void;
|
|
86
|
-
/** Submit the identify step — triggers `requestOtp`. */
|
|
87
|
-
sendOtp: () => Promise<void>;
|
|
88
|
-
/** Submit the verify step — triggers `verifyOtp`. */
|
|
89
|
-
verify: () => Promise<void>;
|
|
90
|
-
/** Go back to the identify screen (e.g. "use a different email"). */
|
|
91
|
-
back: () => void;
|
|
92
|
-
/** Re-send the OTP to the same identifier. */
|
|
93
|
-
resend: () => Promise<void>;
|
|
94
|
-
/** Convenience booleans. */
|
|
95
|
-
isSending: boolean;
|
|
96
|
-
isVerifying: boolean;
|
|
97
|
-
isBusy: boolean;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Headless hook implementing the passwordless OTP login flow. Bring your own
|
|
101
|
-
* markup, or use the {@link SneekOtpLogin} component for a styled default.
|
|
102
|
-
*/
|
|
103
|
-
declare function useSneekOtp<TResult = unknown>(handlers: SneekOtpHandlers<TResult>): UseSneekOtp;
|
|
104
|
-
|
|
105
|
-
interface SneekOtpLoginProps<TResult = unknown> extends SneekOtpHandlers<TResult> {
|
|
106
|
-
/** Heading shown above the form. @default 'Sign in' */
|
|
107
|
-
title?: string;
|
|
108
|
-
/** Sub-heading. @default 'Passwordless login powered by Sneek' */
|
|
109
|
-
subtitle?: ReactNode;
|
|
110
|
-
/** Label for the identifier input. */
|
|
111
|
-
identifierLabel?: string;
|
|
112
|
-
/** Placeholder for the identifier input. */
|
|
113
|
-
identifierPlaceholder?: string;
|
|
114
|
-
/** Brand colour for the primary button. @default '#56d3b5' */
|
|
115
|
-
accentColor?: string;
|
|
116
|
-
/** Optional logo rendered above the title. */
|
|
117
|
-
logo?: ReactNode;
|
|
118
|
-
/** Override the outer container style. */
|
|
119
|
-
style?: CSSProperties;
|
|
120
|
-
/** Extra className on the outer container. */
|
|
121
|
-
className?: string;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Drop-in, dependency-free passwordless OTP login card. The component never
|
|
125
|
-
* receives a Sneek API key; it calls the partner-supplied handlers, which talk
|
|
126
|
-
* to the partner backend. Use {@link createFetchHandlers} for the common case.
|
|
127
|
-
*/
|
|
128
|
-
declare function SneekOtpLogin<TResult = unknown>(props: SneekOtpLoginProps<TResult>): ReactNode;
|
|
129
|
-
|
|
130
|
-
interface FetchHandlerOptions {
|
|
131
|
-
/**
|
|
132
|
-
* Partner backend endpoint that sends an OTP. Receives `{ identifier }`,
|
|
133
|
-
* must return `{ requestId, channels?, expiresInSeconds? }`.
|
|
134
|
-
* @default '/api/auth/request-otp'
|
|
135
|
-
*/
|
|
136
|
-
requestUrl?: string;
|
|
137
|
-
/**
|
|
138
|
-
* Partner backend endpoint that verifies an OTP. Receives
|
|
139
|
-
* `{ requestId, code }`, returns whatever your app needs (session, token…).
|
|
140
|
-
* @default '/api/auth/verify-otp'
|
|
141
|
-
*/
|
|
142
|
-
verifyUrl?: string;
|
|
143
|
-
/** Extra headers (e.g. CSRF token) to send on both requests. */
|
|
144
|
-
headers?: Record<string, string>;
|
|
145
|
-
/** Forwarded to fetch — set to 'include' if you use cookie sessions. */
|
|
146
|
-
credentials?: RequestCredentials;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Build {@link SneekOtpHandlers} that POST to your own backend endpoints.
|
|
150
|
-
* Those endpoints call the Sneek API server-side with your secret key.
|
|
151
|
-
*/
|
|
152
|
-
declare function createFetchHandlers<TResult = unknown>(options?: FetchHandlerOptions): {
|
|
153
|
-
requestOtp: (identifier: string) => Promise<RequestOtpResult>;
|
|
154
|
-
verifyOtp: (input: {
|
|
155
|
-
requestId: string;
|
|
156
|
-
code: string;
|
|
157
|
-
}) => Promise<TResult>;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
export { type FetchHandlerOptions, type RequestOtpResult, type SneekChannel, type SneekOtpAction, type SneekOtpHandlers, SneekOtpLogin, type SneekOtpLoginProps, type SneekOtpState, type SneekOtpStatus, type SneekOtpStep, type UseSneekOtp, createFetchHandlers, formatChannels, initialOtpState, otpReducer, useSneekOtp };
|
|
1
|
+
export { useSneekOtp, type SneekOtpHandlers, type UseSneekOtp, } from './use-sneek-otp';
|
|
2
|
+
export { SneekOtpLogin, type SneekOtpLoginProps, type SneekTheme, } from './component';
|
|
3
|
+
export { SNEEK_ACCENT_DARK, SNEEK_ACCENT_LIGHT, } from './theme';
|
|
4
|
+
export { createFetchHandlers, type FetchHandlerOptions, } from './fetch-handlers';
|
|
5
|
+
export { otpReducer, initialOtpState, formatChannels, type SneekChannel, type SneekOtpStep, type SneekOtpStatus, type SneekOtpState, type SneekOtpAction, type RequestOtpResult, } from './state';
|