@maheshbvv/react-auth-flow 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.
- package/README.md +180 -0
- package/dist/index.cjs +6 -0
- package/dist/index.js +694 -0
- package/dist/react-auth-flow.css +2 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# react-auth-flow
|
|
2
|
+
|
|
3
|
+
Drop-in authentication UI for React with **sign in**, **sign up**, and **forgot password** in one component.
|
|
4
|
+
|
|
5
|
+
It ports the feature set of the Flutter `flutter_auth_flow` package into a React + TypeScript npm package.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Enable only the auth modes you need
|
|
10
|
+
- Async callbacks for sign in, sign up, and forgot password
|
|
11
|
+
- Success callbacks for each mode
|
|
12
|
+
- Internal loading and error state, with external override support
|
|
13
|
+
- Built-in validation
|
|
14
|
+
- Animated mode transitions
|
|
15
|
+
- Theme tokens for colors, typography, radii, and motion
|
|
16
|
+
- Render-prop customization for header, footer, error, loading, submit button, and mode switcher
|
|
17
|
+
- Demo auth service and React provider for local demos/tests
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install react-auth-flow
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Import the shipped styles once in your app:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import 'react-auth-flow/styles.css';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { AuthFlow } from 'react-auth-flow';
|
|
35
|
+
import 'react-auth-flow/styles.css';
|
|
36
|
+
|
|
37
|
+
export function LoginScreen() {
|
|
38
|
+
return (
|
|
39
|
+
<AuthFlow
|
|
40
|
+
onSignIn={async (email, password) => {
|
|
41
|
+
await api.signIn({ email, password });
|
|
42
|
+
}}
|
|
43
|
+
onSignUp={async (email, password, name) => {
|
|
44
|
+
await api.signUp({ email, password, name });
|
|
45
|
+
}}
|
|
46
|
+
onForgotPassword={async (email) => {
|
|
47
|
+
await api.sendReset(email);
|
|
48
|
+
}}
|
|
49
|
+
onSignInSuccess={() => {
|
|
50
|
+
window.location.assign('/app');
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Presets
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { AuthFlow, AuthFlowType } from 'react-auth-flow';
|
|
61
|
+
|
|
62
|
+
<AuthFlow authFlowType={AuthFlowType.signInOnly()} onSignIn={handleSignIn} />;
|
|
63
|
+
|
|
64
|
+
<AuthFlow
|
|
65
|
+
authFlowType={AuthFlowType.signInAndSignUp()}
|
|
66
|
+
onSignIn={handleSignIn}
|
|
67
|
+
onSignUp={handleSignUp}
|
|
68
|
+
/>;
|
|
69
|
+
|
|
70
|
+
<AuthFlow
|
|
71
|
+
authFlowType={new AuthFlowType({ enabledModes: ['signIn', 'forgotPassword'] })}
|
|
72
|
+
onSignIn={handleSignIn}
|
|
73
|
+
onForgotPassword={handleForgotPassword}
|
|
74
|
+
/>;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API
|
|
78
|
+
|
|
79
|
+
| Prop | Type | Description |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `authFlowType` | `AuthFlowType` | Enabled auth modes. Defaults to all modes. |
|
|
82
|
+
| `onSignIn` | `(email, password) => Promise<void> \| void` | Required when sign-in is enabled. |
|
|
83
|
+
| `onSignUp` | `(email, password, name) => Promise<void> \| void` | Required when sign-up is enabled. |
|
|
84
|
+
| `onForgotPassword` | `(email) => Promise<void> \| void` | Required when forgot-password is enabled. |
|
|
85
|
+
| `onSignInSuccess` | `() => void` | Runs after a successful sign in. |
|
|
86
|
+
| `onSignUpSuccess` | `() => void` | Runs after a successful sign up. |
|
|
87
|
+
| `onForgotPasswordSuccess` | `() => void` | Runs after a successful password reset request. |
|
|
88
|
+
| `isLoading` | `boolean` | Overrides internal loading state. |
|
|
89
|
+
| `errorMessage` | `string \| null` | Overrides internal error messaging. |
|
|
90
|
+
| `initialMode` | `AuthMode` | Starting mode if enabled. |
|
|
91
|
+
| `theme` | `AuthFlowTheme` | Visual customization. |
|
|
92
|
+
| `headerRenderer` | `(props) => ReactNode` | Replaces the default header. |
|
|
93
|
+
| `footerRenderer` | `(props) => ReactNode` | Renders below the form. |
|
|
94
|
+
| `errorRenderer` | `(props) => ReactNode` | Replaces the default error UI. |
|
|
95
|
+
| `loadingRenderer` | `(props) => ReactNode` | Replaces the spinner inside the default submit button. |
|
|
96
|
+
| `submitButtonRenderer` | `(props) => ReactNode` | Replaces the default submit button. |
|
|
97
|
+
| `modeSwitcherRenderer` | `(props) => ReactNode` | Replaces the bottom mode switcher. |
|
|
98
|
+
|
|
99
|
+
## Theming
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
<AuthFlow
|
|
103
|
+
onSignIn={handleSignIn}
|
|
104
|
+
onSignUp={handleSignUp}
|
|
105
|
+
onForgotPassword={handleForgotPassword}
|
|
106
|
+
theme={{
|
|
107
|
+
themeMode: 'system',
|
|
108
|
+
primaryColor: '#4f46e5',
|
|
109
|
+
backgroundColor: '#ffffff',
|
|
110
|
+
inputFillColor: '#f8fafc',
|
|
111
|
+
errorColor: '#dc2626',
|
|
112
|
+
titleStyle: { fontSize: '2rem' },
|
|
113
|
+
buttonTextStyle: { letterSpacing: '0.02em' },
|
|
114
|
+
inputBorderRadius: 14,
|
|
115
|
+
buttonBorderRadius: 14,
|
|
116
|
+
transitionDuration: 280,
|
|
117
|
+
transitionTimingFunction: 'ease-in-out',
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Custom renderers
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<AuthFlow
|
|
126
|
+
onSignIn={handleSignIn}
|
|
127
|
+
onSignUp={handleSignUp}
|
|
128
|
+
onForgotPassword={handleForgotPassword}
|
|
129
|
+
headerRenderer={({ mode }) => <BrandHeader mode={mode} />}
|
|
130
|
+
submitButtonRenderer={({ label, submit, isLoading }) => (
|
|
131
|
+
<MyButton onClick={submit} disabled={isLoading}>
|
|
132
|
+
{label}
|
|
133
|
+
</MyButton>
|
|
134
|
+
)}
|
|
135
|
+
modeSwitcherRenderer={({ links, switchMode }) => (
|
|
136
|
+
<nav>
|
|
137
|
+
{links.map((link) => (
|
|
138
|
+
<button key={link.mode} onClick={() => switchMode(link.mode)}>
|
|
139
|
+
{link.prompt} {link.label}
|
|
140
|
+
</button>
|
|
141
|
+
))}
|
|
142
|
+
</nav>
|
|
143
|
+
)}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Demo auth service
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import {
|
|
151
|
+
AuthFlow,
|
|
152
|
+
DemoAuthService,
|
|
153
|
+
DemoAuthServiceProvider,
|
|
154
|
+
useDemoAuthService,
|
|
155
|
+
} from 'react-auth-flow';
|
|
156
|
+
|
|
157
|
+
const service = new DemoAuthService();
|
|
158
|
+
|
|
159
|
+
function DemoScreen() {
|
|
160
|
+
const auth = useDemoAuthService();
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<AuthFlow
|
|
164
|
+
onSignIn={(email, password) => auth.signIn(email, password).then(() => {})}
|
|
165
|
+
onSignUp={(email, password, name) =>
|
|
166
|
+
auth.signUp(email, password, name).then(() => {})
|
|
167
|
+
}
|
|
168
|
+
onForgotPassword={(email) => auth.forgotPassword(email)}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function App() {
|
|
174
|
+
return (
|
|
175
|
+
<DemoAuthServiceProvider service={service}>
|
|
176
|
+
<DemoScreen />
|
|
177
|
+
</DemoAuthServiceProvider>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);let t=require(`react`);var n=[`signIn`,`signUp`,`forgotPassword`],r=class e{enabledModes;constructor(e){let t=new Set(e?.enabledModes??n);if(t.size===0)throw Error(`AuthFlowType requires at least one enabled mode.`);this.enabledModes=t}static all(){return new e}static signInOnly(){return new e({enabledModes:[`signIn`]})}static signUpOnly(){return new e({enabledModes:[`signUp`]})}static forgotPasswordOnly(){return new e({enabledModes:[`forgotPassword`]})}static signInAndSignUp(){return new e({enabledModes:[`signIn`,`signUp`]})}static signInAndForgotPassword(){return new e({enabledModes:[`signIn`,`forgotPassword`]})}static signUpAndForgotPassword(){return new e({enabledModes:[`signUp`,`forgotPassword`]})}hasMode(e){return this.enabledModes.has(e)}get isSingleMode(){return this.enabledModes.size===1}get singleMode(){return this.isSingleMode?this.defaultMode:null}get defaultMode(){return n.find(e=>this.enabledModes.has(e))??`forgotPassword`}},i=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),a=e((e=>{process.env.NODE_ENV!==`production`&&(function(){function t(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===T?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case g:return`Fragment`;case te:return`Profiler`;case _:return`StrictMode`;case b:return`Suspense`;case x:return`SuspenseList`;case w:return`Activity`}if(typeof e==`object`)switch(typeof e.tag==`number`&&console.error(`Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.`),e.$$typeof){case ee:return`Portal`;case y:return e.displayName||`Context`;case v:return(e._context.displayName||`Context`)+`.Consumer`;case ne:var n=e.render;return e=e.displayName,e||=(e=n.displayName||n.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case S:return n=e.displayName||null,n===null?t(e.type)||`Memo`:n;case C:n=e._payload,e=e._init;try{return t(e(n))}catch{}}return null}function n(e){return``+e}function r(e){try{n(e);var t=!1}catch{t=!0}if(t){t=console;var r=t.error,i=typeof Symbol==`function`&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||`Object`;return r.call(t,`The provided key is an unsupported type %s. This value must be coerced to a string before using it here.`,i),n(e)}}function i(e){if(e===g)return`<>`;if(typeof e==`object`&&e&&e.$$typeof===C)return`<...>`;try{var n=t(e);return n?`<`+n+`>`:`<...>`}catch{return`<...>`}}function a(){var e=E.A;return e===null?null:e.getOwner()}function o(){return Error(`react-stack-top-frame`)}function s(e){if(D.call(e,`key`)){var t=Object.getOwnPropertyDescriptor(e,`key`).get;if(t&&t.isReactWarning)return!1}return e.key!==void 0}function c(e,t){function n(){A||(A=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}n.isReactWarning=!0,Object.defineProperty(e,`key`,{get:n,configurable:!0})}function l(){var e=t(this.type);return j[e]||(j[e]=!0,console.error(`Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.`)),e=this.props.ref,e===void 0?null:e}function u(e,t,n,r,i,a){var o=n.ref;return e={$$typeof:h,type:e,key:t,props:n,_owner:r},(o===void 0?null:o)===null?Object.defineProperty(e,`ref`,{enumerable:!1,value:null}):Object.defineProperty(e,`ref`,{enumerable:!1,get:l}),e._store={},Object.defineProperty(e._store,`validated`,{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,`_debugInfo`,{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,`_debugStack`,{configurable:!1,enumerable:!1,writable:!0,value:i}),Object.defineProperty(e,`_debugTask`,{configurable:!1,enumerable:!1,writable:!0,value:a}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function d(e,n,i,o,l,d){var p=n.children;if(p!==void 0)if(o)if(O(p)){for(o=0;o<p.length;o++)f(p[o]);Object.freeze&&Object.freeze(p)}else console.error(`React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.`);else f(p);if(D.call(n,`key`)){p=t(e);var m=Object.keys(n).filter(function(e){return e!==`key`});o=0<m.length?`{key: someKey, `+m.join(`: ..., `)+`: ...}`:`{key: someKey}`,P[p+o]||(m=0<m.length?`{`+m.join(`: ..., `)+`: ...}`:`{}`,console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
2
|
+
let props = %s;
|
|
3
|
+
<%s {...props} />
|
|
4
|
+
React keys must be passed directly to JSX without using spread:
|
|
5
|
+
let props = %s;
|
|
6
|
+
<%s key={someKey} {...props} />`,o,p,m,p),P[p+o]=!0)}if(p=null,i!==void 0&&(r(i),p=``+i),s(n)&&(r(n.key),p=``+n.key),`key`in n)for(var h in i={},n)h!==`key`&&(i[h]=n[h]);else i=n;return p&&c(i,typeof e==`function`?e.displayName||e.name||`Unknown`:e),u(e,p,i,a(),l,d)}function f(e){p(e)?e._store&&(e._store.validated=1):typeof e==`object`&&e&&e.$$typeof===C&&(e._payload.status===`fulfilled`?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e==`object`&&!!e&&e.$$typeof===h}var m=require(`react`),h=Symbol.for(`react.transitional.element`),ee=Symbol.for(`react.portal`),g=Symbol.for(`react.fragment`),_=Symbol.for(`react.strict_mode`),te=Symbol.for(`react.profiler`),v=Symbol.for(`react.consumer`),y=Symbol.for(`react.context`),ne=Symbol.for(`react.forward_ref`),b=Symbol.for(`react.suspense`),x=Symbol.for(`react.suspense_list`),S=Symbol.for(`react.memo`),C=Symbol.for(`react.lazy`),w=Symbol.for(`react.activity`),T=Symbol.for(`react.client.reference`),E=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,D=Object.prototype.hasOwnProperty,O=Array.isArray,k=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(e){return e()}};var A,j={},M=m.react_stack_bottom_frame.bind(m,o)(),N=k(i(o)),P={};e.Fragment=g,e.jsx=function(e,t,n){var r=1e4>E.recentlyCreatedOwnerStacks++;return d(e,t,n,!1,r?Error(`react-stack-top-frame`):M,r?k(i(e)):N)},e.jsxs=function(e,t,n){var r=1e4>E.recentlyCreatedOwnerStacks++;return d(e,t,n,!0,r?Error(`react-stack-top-frame`):M,r?k(i(e)):N)}})()})),o=e(((e,t)=>{process.env.NODE_ENV===`production`?t.exports=i():t.exports=a()}))(),s={name:``,email:``,password:``,confirmPassword:``},c={background:`#ffffff`,inputFill:`#f6f8fb`,surfaceBorder:`rgba(15, 23, 42, 0.08)`,inputBorder:`rgba(15, 23, 42, 0.12)`,text:`#0f172a`,mutedText:`#64748b`,primary:`#2563eb`,error:`#dc2626`,shadow:`0 18px 40px rgba(15, 23, 42, 0.08)`},l={background:`#0f172a`,inputFill:`#172033`,surfaceBorder:`rgba(148, 163, 184, 0.16)`,inputBorder:`rgba(148, 163, 184, 0.22)`,text:`#e2e8f0`,mutedText:`#94a3b8`,primary:`#60a5fa`,error:`#f87171`,shadow:`0 18px 40px rgba(2, 6, 23, 0.36)`},u={signIn:{title:`Welcome back`,subtitle:`Sign in to your account`,submitLabel:`Sign In`},signUp:{title:`Create account`,subtitle:`Join us today`,submitLabel:`Create Account`},forgotPassword:{title:`Reset password`,subtitle:`We'll send you a reset link`,submitLabel:`Send Reset Link`}};function d(e,t){return t&&e.hasMode(t)?t:e.defaultMode}function f(e){return e instanceof Error?e.message.replace(/^(Exception|Error):\s*/u,``):String(e).replace(/^(Exception|Error):\s*/u,``)}function p(e){return/^[^@]+@[^@]+\.[^@]+$/u.test(e.trim())}function m(e,t){let n={};return e===`signUp`&&(t.name.trim()||(n.name=`Name is required`)),t.email.trim()?p(t.email)||(n.email=`Enter a valid email`):n.email=`Email is required`,e!==`forgotPassword`&&(t.password?e===`signUp`&&t.password.length<8&&(n.password=`Minimum 8 characters`):n.password=`Password is required`),e===`signUp`&&(t.confirmPassword?t.confirmPassword!==t.password&&(n.confirmPassword=`Passwords do not match`):n.confirmPassword=`Please confirm password`),n}function h(e,t){return e===`signIn`&&t.hasMode(`forgotPassword`)&&{label:`Forgot password?`,mode:`forgotPassword`}}function ee(e,t){return e===`signIn`&&t.hasMode(`signUp`)?[{prompt:`Don't have an account?`,label:`Sign up`,mode:`signUp`}]:e===`signUp`&&t.hasMode(`signIn`)?[{prompt:`Already have an account?`,label:`Sign in`,mode:`signIn`}]:e===`forgotPassword`&&t.hasMode(`signIn`)?[{prompt:`Remember your password?`,label:`Sign in`,mode:`signIn`}]:[]}function g(e){let[n,r]=(0,t.useState)(()=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(`(prefers-color-scheme: dark)`).matches);return(0,t.useEffect)(()=>{if(e&&e!==`system`&&typeof window<`u`&&typeof window.matchMedia==`function`||typeof window>`u`||typeof window.matchMedia!=`function`)return;let t=window.matchMedia(`(prefers-color-scheme: dark)`),n=e=>{r(e.matches)};return r(t.matches),t.addEventListener(`change`,n),()=>t.removeEventListener(`change`,n)},[e]),e===`dark`?`dark`:e===`light`?`light`:n?`dark`:`light`}function _(e){return{borderRadius:e?.inputBorderRadius??12,...e?.inputStyle}}function te(){return(0,o.jsx)(`span`,{className:`raf__spinner`,"aria-hidden":`true`})}function v(e){let{name:t,label:n,value:r,type:i=`text`,autoComplete:a,onChange:s,onBlur:c,error:l,theme:u}=e;return(0,o.jsxs)(`label`,{className:`raf__field`,children:[(0,o.jsx)(`span`,{className:`raf__field-label`,children:n}),(0,o.jsx)(`input`,{className:`raf__input`,name:t,type:i,value:r,autoComplete:a,"aria-invalid":!!l,"aria-describedby":l?`${t}-error`:void 0,onChange:e=>s(e.target.value),onBlur:c,style:_(u)}),l?(0,o.jsx)(`span`,{id:`${t}-error`,className:`raf__field-error`,children:l}):null]})}function y(e){let{links:t,switchMode:n,theme:r}=e;if(t.length===0)return null;let[i]=t;return(0,o.jsxs)(`div`,{className:`raf__mode-switcher`,children:[(0,o.jsxs)(`span`,{children:[i.prompt,` `]}),(0,o.jsx)(`button`,{type:`button`,className:`raf__inline-button`,onClick:()=>n(i.mode),style:r?.linkStyle,children:i.label})]})}function ne(e,t){return t?`${e} ${t}`:e}function b(e){let{authFlowType:n=r.all(),onSignIn:i,onSignUp:a,onForgotPassword:p,onSignInSuccess:_,onSignUpSuccess:b,onForgotPasswordSuccess:x,isLoading:S,errorMessage:C,initialMode:w,theme:T,className:E,headerRenderer:D,footerRenderer:O,errorRenderer:k,loadingRenderer:A,submitButtonRenderer:j,modeSwitcherRenderer:M}=e,[N,P]=(0,t.useState)(()=>d(n,w)),[F,I]=(0,t.useState)(s),[re,L]=(0,t.useState)({}),[ie,R]=(0,t.useState)(!1),[ae,z]=(0,t.useState)(!1),[oe,B]=(0,t.useState)(null),V=g(T?.themeMode),H=S??ae,U=C??oe,se=(0,t.useMemo)(()=>m(N,F),[N,F]),W=h(N,n),G=ee(N,n);(0,t.useEffect)(()=>{n.hasMode(N)||(P(d(n,w)),I(s),L({}),R(!1),B(null))},[n,w,N]);let K=(0,t.useCallback)(e=>{n.hasMode(e)&&(P(e),I(s),L({}),R(!1),B(null))},[n]),q=(0,t.useMemo)(()=>({mode:N,switchMode:K,isLoading:H,errorMessage:U,theme:T,authFlowType:n}),[n,U,H,N,K,T]),J=(0,t.useCallback)((e,t)=>{I(n=>({...n,[e]:t}))},[]),Y=(0,t.useCallback)(e=>{if(!(!ie&&!re[e]))return se[e]},[se,ie,re]),X=(0,t.useCallback)(e=>{L(t=>({...t,[e]:!0}))},[]),ce=(0,t.useCallback)(e=>{switch(e){case`signIn`:if(!i)throw Error(`onSignIn is required when signIn mode is enabled.`);return i(F.email.trim(),F.password);case`signUp`:if(!a)throw Error(`onSignUp is required when signUp mode is enabled.`);return a(F.email.trim(),F.password,F.name.trim());case`forgotPassword`:if(!p)throw Error(`onForgotPassword is required when forgotPassword mode is enabled.`);return p(F.email.trim())}},[F.email,F.name,F.password,p,i,a]),le=(0,t.useCallback)(()=>{switch(N){case`signIn`:_?.();break;case`signUp`:b?.();break;case`forgotPassword`:x?.();break}},[N,x,_,b]),Z=(0,t.useCallback)(async()=>{R(!0);let e=m(N,F);if(!(Object.keys(e).length>0||H)){B(null),z(!0);try{await Promise.resolve(ce(N)),le()}catch(e){B(f(e))}finally{z(!1)}}},[H,F,N,ce,le]),ue=(0,t.useCallback)(e=>{e.preventDefault(),Z()},[Z]),Q=V===`dark`?l:c,de={"--raf-background":T?.backgroundColor??Q.background,"--raf-input-fill":T?.inputFillColor??Q.inputFill,"--raf-text":Q.text,"--raf-muted-text":Q.mutedText,"--raf-primary":T?.primaryColor??Q.primary,"--raf-error":T?.errorColor??Q.error,"--raf-surface-border":Q.surfaceBorder,"--raf-input-border":Q.inputBorder,"--raf-shadow":Q.shadow,"--raf-transition-duration":`${T?.transitionDuration??320}ms`,"--raf-transition-timing":T?.transitionTimingFunction??`cubic-bezier(0.4, 0, 0.2, 1)`},$=u[N],fe=A?A(q):(0,o.jsx)(te,{});return(0,o.jsx)(`div`,{className:ne(`raf raf--${V}`,E),style:de,children:(0,o.jsxs)(`div`,{className:`raf__card`,style:T?.cardStyle,children:[D?D(q):(0,o.jsxs)(`header`,{className:`raf__header`,children:[(0,o.jsx)(`h2`,{className:`raf__title`,style:T?.titleStyle,children:$.title}),(0,o.jsx)(`p`,{className:`raf__subtitle`,style:T?.subtitleStyle,children:$.subtitle})]}),U?(0,o.jsx)(`div`,{className:`raf__error-shell`,"aria-live":`polite`,children:k?k({...q,error:U}):(0,o.jsxs)(`div`,{className:`raf__error`,children:[(0,o.jsx)(`strong`,{className:`raf__error-icon`,"aria-hidden":`true`,children:`!`}),(0,o.jsx)(`span`,{children:U})]})}):null,(0,o.jsx)(`div`,{className:`raf__panel`,children:(0,o.jsxs)(`form`,{className:`raf__form`,onSubmit:ue,children:[N===`signUp`?(0,o.jsx)(v,{name:`name`,label:`Full name`,value:F.name,autoComplete:`name`,onChange:e=>J(`name`,e),onBlur:()=>X(`name`),error:Y(`name`),theme:T}):null,(0,o.jsx)(v,{name:`email`,label:`Email`,type:`email`,value:F.email,autoComplete:N===`signUp`?`email`:`username`,onChange:e=>J(`email`,e),onBlur:()=>X(`email`),error:Y(`email`),theme:T}),N===`forgotPassword`?null:(0,o.jsx)(v,{name:`password`,label:`Password`,type:`password`,value:F.password,autoComplete:N===`signUp`?`new-password`:`current-password`,onChange:e=>J(`password`,e),onBlur:()=>X(`password`),error:Y(`password`),theme:T}),N===`signUp`?(0,o.jsx)(v,{name:`confirmPassword`,label:`Confirm password`,type:`password`,value:F.confirmPassword,autoComplete:`new-password`,onChange:e=>J(`confirmPassword`,e),onBlur:()=>X(`confirmPassword`),error:Y(`confirmPassword`),theme:T}):null,W?(0,o.jsx)(`div`,{className:`raf__forgot-shell`,children:(0,o.jsx)(`button`,{type:`button`,className:`raf__inline-button`,onClick:()=>K(W.mode),style:T?.linkStyle,children:W.label})}):null,j?j({...q,label:$.submitLabel,submit:()=>{Z()}}):(0,o.jsx)(`button`,{type:`submit`,className:`raf__submit`,disabled:H,style:{borderRadius:T?.buttonBorderRadius??12,...T?.buttonStyle},children:H?fe:(0,o.jsx)(`span`,{style:T?.buttonTextStyle,children:$.submitLabel})}),G.length>0?M?M({...q,links:G}):(0,o.jsx)(y,{links:G,switchMode:K,theme:T}):null]})},N),O?O(q):null]})})}var x=class extends Error{constructor(e){super(e),this.name=`DemoAuthException`}};function S(e){let t=new TextEncoder().encode(e),n=``;for(let e of t)n+=String.fromCharCode(e);if(typeof globalThis.btoa==`function`)return globalThis.btoa(n);let r=globalThis.Buffer;return r?r.from(t).toString(`base64`):n}function C(){return 1e3+Date.now()%1e3}function w(e){return/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(e)}function T(e){return e.trim().toLowerCase()}function E(e){return new Promise(t=>{globalThis.setTimeout(t,e)})}var D=class{users=new Map;async signIn(e,t){await E(C());let n=T(e),r=this.users.get(n);if(!r||r.passwordHash!==S(t))throw new x(`Invalid email or password`);return{email:r.email,name:r.name}}async signUp(e,t,n){await E(C());let r=T(e);if(!w(r))throw new x(`Please enter a valid email address`);if(t.length<8)throw new x(`Password must be at least 8 characters`);if(this.users.has(r))throw new x(`Email already in use`);let i={email:r,passwordHash:S(t),name:n.trim(),createdAt:new Date};return this.users.set(r,i),{email:i.email,name:i.name}}async forgotPassword(e){if(await E(1e3),!w(T(e)))throw new x(`Please enter a valid email address`)}clearUsers(){this.users.clear()}get userCount(){return this.users.size}getCreatedAt(e){return this.users.get(T(e))?.createdAt??null}},O=(0,t.createContext)(null);function k(e){let{service:t,children:n}=e;return(0,o.jsx)(O.Provider,{value:t,children:n})}function A(){let e=(0,t.useContext)(O);if(!e)throw Error(`useDemoAuthService() must be used inside a DemoAuthServiceProvider.`);return e}function j(){return(0,t.useContext)(O)}exports.AuthFlow=b,exports.AuthFlowType=r,exports.DemoAuthException=x,exports.DemoAuthService=D,exports.DemoAuthServiceProvider=k,exports.useDemoAuthService=A,exports.useMaybeDemoAuthService=j;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
import { createContext as e, useCallback as t, useContext as n, useEffect as r, useMemo as i, useState as a } from "react";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var o = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), s = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
|
|
4
|
+
if (typeof require < "u") return require.apply(this, arguments);
|
|
5
|
+
throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
6
|
+
}), c = [
|
|
7
|
+
"signIn",
|
|
8
|
+
"signUp",
|
|
9
|
+
"forgotPassword"
|
|
10
|
+
], l = class e {
|
|
11
|
+
enabledModes;
|
|
12
|
+
constructor(e) {
|
|
13
|
+
let t = new Set(e?.enabledModes ?? c);
|
|
14
|
+
if (t.size === 0) throw Error("AuthFlowType requires at least one enabled mode.");
|
|
15
|
+
this.enabledModes = t;
|
|
16
|
+
}
|
|
17
|
+
static all() {
|
|
18
|
+
return new e();
|
|
19
|
+
}
|
|
20
|
+
static signInOnly() {
|
|
21
|
+
return new e({ enabledModes: ["signIn"] });
|
|
22
|
+
}
|
|
23
|
+
static signUpOnly() {
|
|
24
|
+
return new e({ enabledModes: ["signUp"] });
|
|
25
|
+
}
|
|
26
|
+
static forgotPasswordOnly() {
|
|
27
|
+
return new e({ enabledModes: ["forgotPassword"] });
|
|
28
|
+
}
|
|
29
|
+
static signInAndSignUp() {
|
|
30
|
+
return new e({ enabledModes: ["signIn", "signUp"] });
|
|
31
|
+
}
|
|
32
|
+
static signInAndForgotPassword() {
|
|
33
|
+
return new e({ enabledModes: ["signIn", "forgotPassword"] });
|
|
34
|
+
}
|
|
35
|
+
static signUpAndForgotPassword() {
|
|
36
|
+
return new e({ enabledModes: ["signUp", "forgotPassword"] });
|
|
37
|
+
}
|
|
38
|
+
hasMode(e) {
|
|
39
|
+
return this.enabledModes.has(e);
|
|
40
|
+
}
|
|
41
|
+
get isSingleMode() {
|
|
42
|
+
return this.enabledModes.size === 1;
|
|
43
|
+
}
|
|
44
|
+
get singleMode() {
|
|
45
|
+
return this.isSingleMode ? this.defaultMode : null;
|
|
46
|
+
}
|
|
47
|
+
get defaultMode() {
|
|
48
|
+
return c.find((e) => this.enabledModes.has(e)) ?? "forgotPassword";
|
|
49
|
+
}
|
|
50
|
+
}, u = /* @__PURE__ */ o(((e) => {
|
|
51
|
+
var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
|
|
52
|
+
function r(e, n, r) {
|
|
53
|
+
var i = null;
|
|
54
|
+
if (r !== void 0 && (i = "" + r), n.key !== void 0 && (i = "" + n.key), "key" in n) for (var a in r = {}, n) a !== "key" && (r[a] = n[a]);
|
|
55
|
+
else r = n;
|
|
56
|
+
return n = r.ref, {
|
|
57
|
+
$$typeof: t,
|
|
58
|
+
type: e,
|
|
59
|
+
key: i,
|
|
60
|
+
ref: n === void 0 ? null : n,
|
|
61
|
+
props: r
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
e.Fragment = n, e.jsx = r, e.jsxs = r;
|
|
65
|
+
})), d = /* @__PURE__ */ o(((e) => {
|
|
66
|
+
process.env.NODE_ENV !== "production" && (function() {
|
|
67
|
+
function t(e) {
|
|
68
|
+
if (e == null) return null;
|
|
69
|
+
if (typeof e == "function") return e.$$typeof === T ? null : e.displayName || e.name || null;
|
|
70
|
+
if (typeof e == "string") return e;
|
|
71
|
+
switch (e) {
|
|
72
|
+
case v: return "Fragment";
|
|
73
|
+
case b: return "Profiler";
|
|
74
|
+
case y: return "StrictMode";
|
|
75
|
+
case x: return "Suspense";
|
|
76
|
+
case S: return "SuspenseList";
|
|
77
|
+
case re: return "Activity";
|
|
78
|
+
}
|
|
79
|
+
if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) {
|
|
80
|
+
case _: return "Portal";
|
|
81
|
+
case te: return e.displayName || "Context";
|
|
82
|
+
case ee: return (e._context.displayName || "Context") + ".Consumer";
|
|
83
|
+
case ne:
|
|
84
|
+
var n = e.render;
|
|
85
|
+
return e = e.displayName, e ||= (e = n.displayName || n.name || "", e === "" ? "ForwardRef" : "ForwardRef(" + e + ")"), e;
|
|
86
|
+
case C: return n = e.displayName || null, n === null ? t(e.type) || "Memo" : n;
|
|
87
|
+
case w:
|
|
88
|
+
n = e._payload, e = e._init;
|
|
89
|
+
try {
|
|
90
|
+
return t(e(n));
|
|
91
|
+
} catch {}
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
function n(e) {
|
|
96
|
+
return "" + e;
|
|
97
|
+
}
|
|
98
|
+
function r(e) {
|
|
99
|
+
try {
|
|
100
|
+
n(e);
|
|
101
|
+
var t = !1;
|
|
102
|
+
} catch {
|
|
103
|
+
t = !0;
|
|
104
|
+
}
|
|
105
|
+
if (t) {
|
|
106
|
+
t = console;
|
|
107
|
+
var r = t.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
|
|
108
|
+
return r.call(t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), n(e);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function i(e) {
|
|
112
|
+
if (e === v) return "<>";
|
|
113
|
+
if (typeof e == "object" && e && e.$$typeof === w) return "<...>";
|
|
114
|
+
try {
|
|
115
|
+
var n = t(e);
|
|
116
|
+
return n ? "<" + n + ">" : "<...>";
|
|
117
|
+
} catch {
|
|
118
|
+
return "<...>";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function a() {
|
|
122
|
+
var e = E.A;
|
|
123
|
+
return e === null ? null : e.getOwner();
|
|
124
|
+
}
|
|
125
|
+
function o() {
|
|
126
|
+
return Error("react-stack-top-frame");
|
|
127
|
+
}
|
|
128
|
+
function c(e) {
|
|
129
|
+
if (D.call(e, "key")) {
|
|
130
|
+
var t = Object.getOwnPropertyDescriptor(e, "key").get;
|
|
131
|
+
if (t && t.isReactWarning) return !1;
|
|
132
|
+
}
|
|
133
|
+
return e.key !== void 0;
|
|
134
|
+
}
|
|
135
|
+
function l(e, t) {
|
|
136
|
+
function n() {
|
|
137
|
+
A || (A = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", t));
|
|
138
|
+
}
|
|
139
|
+
n.isReactWarning = !0, Object.defineProperty(e, "key", {
|
|
140
|
+
get: n,
|
|
141
|
+
configurable: !0
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function u() {
|
|
145
|
+
var e = t(this.type);
|
|
146
|
+
return j[e] || (j[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), e = this.props.ref, e === void 0 ? null : e;
|
|
147
|
+
}
|
|
148
|
+
function d(e, t, n, r, i, a) {
|
|
149
|
+
var o = n.ref;
|
|
150
|
+
return e = {
|
|
151
|
+
$$typeof: g,
|
|
152
|
+
type: e,
|
|
153
|
+
key: t,
|
|
154
|
+
props: n,
|
|
155
|
+
_owner: r
|
|
156
|
+
}, (o === void 0 ? null : o) === null ? Object.defineProperty(e, "ref", {
|
|
157
|
+
enumerable: !1,
|
|
158
|
+
value: null
|
|
159
|
+
}) : Object.defineProperty(e, "ref", {
|
|
160
|
+
enumerable: !1,
|
|
161
|
+
get: u
|
|
162
|
+
}), e._store = {}, Object.defineProperty(e._store, "validated", {
|
|
163
|
+
configurable: !1,
|
|
164
|
+
enumerable: !1,
|
|
165
|
+
writable: !0,
|
|
166
|
+
value: 0
|
|
167
|
+
}), Object.defineProperty(e, "_debugInfo", {
|
|
168
|
+
configurable: !1,
|
|
169
|
+
enumerable: !1,
|
|
170
|
+
writable: !0,
|
|
171
|
+
value: null
|
|
172
|
+
}), Object.defineProperty(e, "_debugStack", {
|
|
173
|
+
configurable: !1,
|
|
174
|
+
enumerable: !1,
|
|
175
|
+
writable: !0,
|
|
176
|
+
value: i
|
|
177
|
+
}), Object.defineProperty(e, "_debugTask", {
|
|
178
|
+
configurable: !1,
|
|
179
|
+
enumerable: !1,
|
|
180
|
+
writable: !0,
|
|
181
|
+
value: a
|
|
182
|
+
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
|
|
183
|
+
}
|
|
184
|
+
function f(e, n, i, o, s, u) {
|
|
185
|
+
var f = n.children;
|
|
186
|
+
if (f !== void 0) if (o) if (O(f)) {
|
|
187
|
+
for (o = 0; o < f.length; o++) p(f[o]);
|
|
188
|
+
Object.freeze && Object.freeze(f);
|
|
189
|
+
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
190
|
+
else p(f);
|
|
191
|
+
if (D.call(n, "key")) {
|
|
192
|
+
f = t(e);
|
|
193
|
+
var m = Object.keys(n).filter(function(e) {
|
|
194
|
+
return e !== "key";
|
|
195
|
+
});
|
|
196
|
+
o = 0 < m.length ? "{key: someKey, " + m.join(": ..., ") + ": ...}" : "{key: someKey}", P[f + o] || (m = 0 < m.length ? "{" + m.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", o, f, m, f), P[f + o] = !0);
|
|
197
|
+
}
|
|
198
|
+
if (f = null, i !== void 0 && (r(i), f = "" + i), c(n) && (r(n.key), f = "" + n.key), "key" in n) for (var h in i = {}, n) h !== "key" && (i[h] = n[h]);
|
|
199
|
+
else i = n;
|
|
200
|
+
return f && l(i, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), d(e, f, i, a(), s, u);
|
|
201
|
+
}
|
|
202
|
+
function p(e) {
|
|
203
|
+
m(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e && e.$$typeof === w && (e._payload.status === "fulfilled" ? m(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
|
|
204
|
+
}
|
|
205
|
+
function m(e) {
|
|
206
|
+
return typeof e == "object" && !!e && e.$$typeof === g;
|
|
207
|
+
}
|
|
208
|
+
var h = s("react"), g = Symbol.for("react.transitional.element"), _ = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), y = Symbol.for("react.strict_mode"), b = Symbol.for("react.profiler"), ee = Symbol.for("react.consumer"), te = Symbol.for("react.context"), ne = Symbol.for("react.forward_ref"), x = Symbol.for("react.suspense"), S = Symbol.for("react.suspense_list"), C = Symbol.for("react.memo"), w = Symbol.for("react.lazy"), re = Symbol.for("react.activity"), T = Symbol.for("react.client.reference"), E = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, D = Object.prototype.hasOwnProperty, O = Array.isArray, k = console.createTask ? console.createTask : function() {
|
|
209
|
+
return null;
|
|
210
|
+
};
|
|
211
|
+
h = { react_stack_bottom_frame: function(e) {
|
|
212
|
+
return e();
|
|
213
|
+
} };
|
|
214
|
+
var A, j = {}, M = h.react_stack_bottom_frame.bind(h, o)(), N = k(i(o)), P = {};
|
|
215
|
+
e.Fragment = v, e.jsx = function(e, t, n) {
|
|
216
|
+
var r = 1e4 > E.recentlyCreatedOwnerStacks++;
|
|
217
|
+
return f(e, t, n, !1, r ? Error("react-stack-top-frame") : M, r ? k(i(e)) : N);
|
|
218
|
+
}, e.jsxs = function(e, t, n) {
|
|
219
|
+
var r = 1e4 > E.recentlyCreatedOwnerStacks++;
|
|
220
|
+
return f(e, t, n, !0, r ? Error("react-stack-top-frame") : M, r ? k(i(e)) : N);
|
|
221
|
+
};
|
|
222
|
+
})();
|
|
223
|
+
})), f = (/* @__PURE__ */ o(((e, t) => {
|
|
224
|
+
process.env.NODE_ENV === "production" ? t.exports = u() : t.exports = d();
|
|
225
|
+
})))(), p = {
|
|
226
|
+
name: "",
|
|
227
|
+
email: "",
|
|
228
|
+
password: "",
|
|
229
|
+
confirmPassword: ""
|
|
230
|
+
}, m = {
|
|
231
|
+
background: "#ffffff",
|
|
232
|
+
inputFill: "#f6f8fb",
|
|
233
|
+
surfaceBorder: "rgba(15, 23, 42, 0.08)",
|
|
234
|
+
inputBorder: "rgba(15, 23, 42, 0.12)",
|
|
235
|
+
text: "#0f172a",
|
|
236
|
+
mutedText: "#64748b",
|
|
237
|
+
primary: "#2563eb",
|
|
238
|
+
error: "#dc2626",
|
|
239
|
+
shadow: "0 18px 40px rgba(15, 23, 42, 0.08)"
|
|
240
|
+
}, h = {
|
|
241
|
+
background: "#0f172a",
|
|
242
|
+
inputFill: "#172033",
|
|
243
|
+
surfaceBorder: "rgba(148, 163, 184, 0.16)",
|
|
244
|
+
inputBorder: "rgba(148, 163, 184, 0.22)",
|
|
245
|
+
text: "#e2e8f0",
|
|
246
|
+
mutedText: "#94a3b8",
|
|
247
|
+
primary: "#60a5fa",
|
|
248
|
+
error: "#f87171",
|
|
249
|
+
shadow: "0 18px 40px rgba(2, 6, 23, 0.36)"
|
|
250
|
+
}, g = {
|
|
251
|
+
signIn: {
|
|
252
|
+
title: "Welcome back",
|
|
253
|
+
subtitle: "Sign in to your account",
|
|
254
|
+
submitLabel: "Sign In"
|
|
255
|
+
},
|
|
256
|
+
signUp: {
|
|
257
|
+
title: "Create account",
|
|
258
|
+
subtitle: "Join us today",
|
|
259
|
+
submitLabel: "Create Account"
|
|
260
|
+
},
|
|
261
|
+
forgotPassword: {
|
|
262
|
+
title: "Reset password",
|
|
263
|
+
subtitle: "We'll send you a reset link",
|
|
264
|
+
submitLabel: "Send Reset Link"
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
function _(e, t) {
|
|
268
|
+
return t && e.hasMode(t) ? t : e.defaultMode;
|
|
269
|
+
}
|
|
270
|
+
function v(e) {
|
|
271
|
+
return e instanceof Error ? e.message.replace(/^(Exception|Error):\s*/u, "") : String(e).replace(/^(Exception|Error):\s*/u, "");
|
|
272
|
+
}
|
|
273
|
+
function y(e) {
|
|
274
|
+
return /^[^@]+@[^@]+\.[^@]+$/u.test(e.trim());
|
|
275
|
+
}
|
|
276
|
+
function b(e, t) {
|
|
277
|
+
let n = {};
|
|
278
|
+
return e === "signUp" && (t.name.trim() || (n.name = "Name is required")), t.email.trim() ? y(t.email) || (n.email = "Enter a valid email") : n.email = "Email is required", e !== "forgotPassword" && (t.password ? e === "signUp" && t.password.length < 8 && (n.password = "Minimum 8 characters") : n.password = "Password is required"), e === "signUp" && (t.confirmPassword ? t.confirmPassword !== t.password && (n.confirmPassword = "Passwords do not match") : n.confirmPassword = "Please confirm password"), n;
|
|
279
|
+
}
|
|
280
|
+
function ee(e, t) {
|
|
281
|
+
return e === "signIn" && t.hasMode("forgotPassword") && {
|
|
282
|
+
label: "Forgot password?",
|
|
283
|
+
mode: "forgotPassword"
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function te(e, t) {
|
|
287
|
+
return e === "signIn" && t.hasMode("signUp") ? [{
|
|
288
|
+
prompt: "Don't have an account?",
|
|
289
|
+
label: "Sign up",
|
|
290
|
+
mode: "signUp"
|
|
291
|
+
}] : e === "signUp" && t.hasMode("signIn") ? [{
|
|
292
|
+
prompt: "Already have an account?",
|
|
293
|
+
label: "Sign in",
|
|
294
|
+
mode: "signIn"
|
|
295
|
+
}] : e === "forgotPassword" && t.hasMode("signIn") ? [{
|
|
296
|
+
prompt: "Remember your password?",
|
|
297
|
+
label: "Sign in",
|
|
298
|
+
mode: "signIn"
|
|
299
|
+
}] : [];
|
|
300
|
+
}
|
|
301
|
+
function ne(e) {
|
|
302
|
+
let [t, n] = a(() => typeof window > "u" || typeof window.matchMedia != "function" ? !1 : window.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
303
|
+
return r(() => {
|
|
304
|
+
if (e && e !== "system" && typeof window < "u" && typeof window.matchMedia == "function" || typeof window > "u" || typeof window.matchMedia != "function") return;
|
|
305
|
+
let t = window.matchMedia("(prefers-color-scheme: dark)"), r = (e) => {
|
|
306
|
+
n(e.matches);
|
|
307
|
+
};
|
|
308
|
+
return n(t.matches), t.addEventListener("change", r), () => t.removeEventListener("change", r);
|
|
309
|
+
}, [e]), e === "dark" ? "dark" : e === "light" ? "light" : t ? "dark" : "light";
|
|
310
|
+
}
|
|
311
|
+
function x(e) {
|
|
312
|
+
return {
|
|
313
|
+
borderRadius: e?.inputBorderRadius ?? 12,
|
|
314
|
+
...e?.inputStyle
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function S() {
|
|
318
|
+
return /* @__PURE__ */ (0, f.jsx)("span", {
|
|
319
|
+
className: "raf__spinner",
|
|
320
|
+
"aria-hidden": "true"
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
function C(e) {
|
|
324
|
+
let { name: t, label: n, value: r, type: i = "text", autoComplete: a, onChange: o, onBlur: s, error: c, theme: l } = e;
|
|
325
|
+
return /* @__PURE__ */ (0, f.jsxs)("label", {
|
|
326
|
+
className: "raf__field",
|
|
327
|
+
children: [
|
|
328
|
+
/* @__PURE__ */ (0, f.jsx)("span", {
|
|
329
|
+
className: "raf__field-label",
|
|
330
|
+
children: n
|
|
331
|
+
}),
|
|
332
|
+
/* @__PURE__ */ (0, f.jsx)("input", {
|
|
333
|
+
className: "raf__input",
|
|
334
|
+
name: t,
|
|
335
|
+
type: i,
|
|
336
|
+
value: r,
|
|
337
|
+
autoComplete: a,
|
|
338
|
+
"aria-invalid": !!c,
|
|
339
|
+
"aria-describedby": c ? `${t}-error` : void 0,
|
|
340
|
+
onChange: (e) => o(e.target.value),
|
|
341
|
+
onBlur: s,
|
|
342
|
+
style: x(l)
|
|
343
|
+
}),
|
|
344
|
+
c ? /* @__PURE__ */ (0, f.jsx)("span", {
|
|
345
|
+
id: `${t}-error`,
|
|
346
|
+
className: "raf__field-error",
|
|
347
|
+
children: c
|
|
348
|
+
}) : null
|
|
349
|
+
]
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
function w(e) {
|
|
353
|
+
let { links: t, switchMode: n, theme: r } = e;
|
|
354
|
+
if (t.length === 0) return null;
|
|
355
|
+
let [i] = t;
|
|
356
|
+
return /* @__PURE__ */ (0, f.jsxs)("div", {
|
|
357
|
+
className: "raf__mode-switcher",
|
|
358
|
+
children: [/* @__PURE__ */ (0, f.jsxs)("span", { children: [i.prompt, " "] }), /* @__PURE__ */ (0, f.jsx)("button", {
|
|
359
|
+
type: "button",
|
|
360
|
+
className: "raf__inline-button",
|
|
361
|
+
onClick: () => n(i.mode),
|
|
362
|
+
style: r?.linkStyle,
|
|
363
|
+
children: i.label
|
|
364
|
+
})]
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
function re(e, t) {
|
|
368
|
+
return t ? `${e} ${t}` : e;
|
|
369
|
+
}
|
|
370
|
+
function T(e) {
|
|
371
|
+
let { authFlowType: n = l.all(), onSignIn: o, onSignUp: s, onForgotPassword: c, onSignInSuccess: u, onSignUpSuccess: d, onForgotPasswordSuccess: y, isLoading: x, errorMessage: T, initialMode: E, theme: D, className: O, headerRenderer: k, footerRenderer: A, errorRenderer: j, loadingRenderer: M, submitButtonRenderer: N, modeSwitcherRenderer: P } = e, [F, I] = a(() => _(n, E)), [L, R] = a(p), [ie, z] = a({}), [ae, B] = a(!1), [oe, se] = a(!1), [ce, V] = a(null), le = ne(D?.themeMode), H = x ?? oe, U = T ?? ce, ue = i(() => b(F, L), [F, L]), W = ee(F, n), G = te(F, n);
|
|
372
|
+
r(() => {
|
|
373
|
+
n.hasMode(F) || (I(_(n, E)), R(p), z({}), B(!1), V(null));
|
|
374
|
+
}, [
|
|
375
|
+
n,
|
|
376
|
+
E,
|
|
377
|
+
F
|
|
378
|
+
]);
|
|
379
|
+
let K = t((e) => {
|
|
380
|
+
n.hasMode(e) && (I(e), R(p), z({}), B(!1), V(null));
|
|
381
|
+
}, [n]), q = i(() => ({
|
|
382
|
+
mode: F,
|
|
383
|
+
switchMode: K,
|
|
384
|
+
isLoading: H,
|
|
385
|
+
errorMessage: U,
|
|
386
|
+
theme: D,
|
|
387
|
+
authFlowType: n
|
|
388
|
+
}), [
|
|
389
|
+
n,
|
|
390
|
+
U,
|
|
391
|
+
H,
|
|
392
|
+
F,
|
|
393
|
+
K,
|
|
394
|
+
D
|
|
395
|
+
]), J = t((e, t) => {
|
|
396
|
+
R((n) => ({
|
|
397
|
+
...n,
|
|
398
|
+
[e]: t
|
|
399
|
+
}));
|
|
400
|
+
}, []), Y = t((e) => {
|
|
401
|
+
if (!(!ae && !ie[e])) return ue[e];
|
|
402
|
+
}, [
|
|
403
|
+
ue,
|
|
404
|
+
ae,
|
|
405
|
+
ie
|
|
406
|
+
]), X = t((e) => {
|
|
407
|
+
z((t) => ({
|
|
408
|
+
...t,
|
|
409
|
+
[e]: !0
|
|
410
|
+
}));
|
|
411
|
+
}, []), de = t((e) => {
|
|
412
|
+
switch (e) {
|
|
413
|
+
case "signIn":
|
|
414
|
+
if (!o) throw Error("onSignIn is required when signIn mode is enabled.");
|
|
415
|
+
return o(L.email.trim(), L.password);
|
|
416
|
+
case "signUp":
|
|
417
|
+
if (!s) throw Error("onSignUp is required when signUp mode is enabled.");
|
|
418
|
+
return s(L.email.trim(), L.password, L.name.trim());
|
|
419
|
+
case "forgotPassword":
|
|
420
|
+
if (!c) throw Error("onForgotPassword is required when forgotPassword mode is enabled.");
|
|
421
|
+
return c(L.email.trim());
|
|
422
|
+
}
|
|
423
|
+
}, [
|
|
424
|
+
L.email,
|
|
425
|
+
L.name,
|
|
426
|
+
L.password,
|
|
427
|
+
c,
|
|
428
|
+
o,
|
|
429
|
+
s
|
|
430
|
+
]), fe = t(() => {
|
|
431
|
+
switch (F) {
|
|
432
|
+
case "signIn":
|
|
433
|
+
u?.();
|
|
434
|
+
break;
|
|
435
|
+
case "signUp":
|
|
436
|
+
d?.();
|
|
437
|
+
break;
|
|
438
|
+
case "forgotPassword":
|
|
439
|
+
y?.();
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
}, [
|
|
443
|
+
F,
|
|
444
|
+
y,
|
|
445
|
+
u,
|
|
446
|
+
d
|
|
447
|
+
]), Z = t(async () => {
|
|
448
|
+
B(!0);
|
|
449
|
+
let e = b(F, L);
|
|
450
|
+
if (!(Object.keys(e).length > 0 || H)) {
|
|
451
|
+
V(null), se(!0);
|
|
452
|
+
try {
|
|
453
|
+
await Promise.resolve(de(F)), fe();
|
|
454
|
+
} catch (e) {
|
|
455
|
+
V(v(e));
|
|
456
|
+
} finally {
|
|
457
|
+
se(!1);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}, [
|
|
461
|
+
H,
|
|
462
|
+
L,
|
|
463
|
+
F,
|
|
464
|
+
de,
|
|
465
|
+
fe
|
|
466
|
+
]), pe = t((e) => {
|
|
467
|
+
e.preventDefault(), Z();
|
|
468
|
+
}, [Z]), Q = le === "dark" ? h : m, me = {
|
|
469
|
+
"--raf-background": D?.backgroundColor ?? Q.background,
|
|
470
|
+
"--raf-input-fill": D?.inputFillColor ?? Q.inputFill,
|
|
471
|
+
"--raf-text": Q.text,
|
|
472
|
+
"--raf-muted-text": Q.mutedText,
|
|
473
|
+
"--raf-primary": D?.primaryColor ?? Q.primary,
|
|
474
|
+
"--raf-error": D?.errorColor ?? Q.error,
|
|
475
|
+
"--raf-surface-border": Q.surfaceBorder,
|
|
476
|
+
"--raf-input-border": Q.inputBorder,
|
|
477
|
+
"--raf-shadow": Q.shadow,
|
|
478
|
+
"--raf-transition-duration": `${D?.transitionDuration ?? 320}ms`,
|
|
479
|
+
"--raf-transition-timing": D?.transitionTimingFunction ?? "cubic-bezier(0.4, 0, 0.2, 1)"
|
|
480
|
+
}, $ = g[F], he = M ? M(q) : /* @__PURE__ */ (0, f.jsx)(S, {});
|
|
481
|
+
return /* @__PURE__ */ (0, f.jsx)("div", {
|
|
482
|
+
className: re(`raf raf--${le}`, O),
|
|
483
|
+
style: me,
|
|
484
|
+
children: /* @__PURE__ */ (0, f.jsxs)("div", {
|
|
485
|
+
className: "raf__card",
|
|
486
|
+
style: D?.cardStyle,
|
|
487
|
+
children: [
|
|
488
|
+
k ? k(q) : /* @__PURE__ */ (0, f.jsxs)("header", {
|
|
489
|
+
className: "raf__header",
|
|
490
|
+
children: [/* @__PURE__ */ (0, f.jsx)("h2", {
|
|
491
|
+
className: "raf__title",
|
|
492
|
+
style: D?.titleStyle,
|
|
493
|
+
children: $.title
|
|
494
|
+
}), /* @__PURE__ */ (0, f.jsx)("p", {
|
|
495
|
+
className: "raf__subtitle",
|
|
496
|
+
style: D?.subtitleStyle,
|
|
497
|
+
children: $.subtitle
|
|
498
|
+
})]
|
|
499
|
+
}),
|
|
500
|
+
U ? /* @__PURE__ */ (0, f.jsx)("div", {
|
|
501
|
+
className: "raf__error-shell",
|
|
502
|
+
"aria-live": "polite",
|
|
503
|
+
children: j ? j({
|
|
504
|
+
...q,
|
|
505
|
+
error: U
|
|
506
|
+
}) : /* @__PURE__ */ (0, f.jsxs)("div", {
|
|
507
|
+
className: "raf__error",
|
|
508
|
+
children: [/* @__PURE__ */ (0, f.jsx)("strong", {
|
|
509
|
+
className: "raf__error-icon",
|
|
510
|
+
"aria-hidden": "true",
|
|
511
|
+
children: "!"
|
|
512
|
+
}), /* @__PURE__ */ (0, f.jsx)("span", { children: U })]
|
|
513
|
+
})
|
|
514
|
+
}) : null,
|
|
515
|
+
/* @__PURE__ */ (0, f.jsx)("div", {
|
|
516
|
+
className: "raf__panel",
|
|
517
|
+
children: /* @__PURE__ */ (0, f.jsxs)("form", {
|
|
518
|
+
className: "raf__form",
|
|
519
|
+
onSubmit: pe,
|
|
520
|
+
children: [
|
|
521
|
+
F === "signUp" ? /* @__PURE__ */ (0, f.jsx)(C, {
|
|
522
|
+
name: "name",
|
|
523
|
+
label: "Full name",
|
|
524
|
+
value: L.name,
|
|
525
|
+
autoComplete: "name",
|
|
526
|
+
onChange: (e) => J("name", e),
|
|
527
|
+
onBlur: () => X("name"),
|
|
528
|
+
error: Y("name"),
|
|
529
|
+
theme: D
|
|
530
|
+
}) : null,
|
|
531
|
+
/* @__PURE__ */ (0, f.jsx)(C, {
|
|
532
|
+
name: "email",
|
|
533
|
+
label: "Email",
|
|
534
|
+
type: "email",
|
|
535
|
+
value: L.email,
|
|
536
|
+
autoComplete: F === "signUp" ? "email" : "username",
|
|
537
|
+
onChange: (e) => J("email", e),
|
|
538
|
+
onBlur: () => X("email"),
|
|
539
|
+
error: Y("email"),
|
|
540
|
+
theme: D
|
|
541
|
+
}),
|
|
542
|
+
F === "forgotPassword" ? null : /* @__PURE__ */ (0, f.jsx)(C, {
|
|
543
|
+
name: "password",
|
|
544
|
+
label: "Password",
|
|
545
|
+
type: "password",
|
|
546
|
+
value: L.password,
|
|
547
|
+
autoComplete: F === "signUp" ? "new-password" : "current-password",
|
|
548
|
+
onChange: (e) => J("password", e),
|
|
549
|
+
onBlur: () => X("password"),
|
|
550
|
+
error: Y("password"),
|
|
551
|
+
theme: D
|
|
552
|
+
}),
|
|
553
|
+
F === "signUp" ? /* @__PURE__ */ (0, f.jsx)(C, {
|
|
554
|
+
name: "confirmPassword",
|
|
555
|
+
label: "Confirm password",
|
|
556
|
+
type: "password",
|
|
557
|
+
value: L.confirmPassword,
|
|
558
|
+
autoComplete: "new-password",
|
|
559
|
+
onChange: (e) => J("confirmPassword", e),
|
|
560
|
+
onBlur: () => X("confirmPassword"),
|
|
561
|
+
error: Y("confirmPassword"),
|
|
562
|
+
theme: D
|
|
563
|
+
}) : null,
|
|
564
|
+
W ? /* @__PURE__ */ (0, f.jsx)("div", {
|
|
565
|
+
className: "raf__forgot-shell",
|
|
566
|
+
children: /* @__PURE__ */ (0, f.jsx)("button", {
|
|
567
|
+
type: "button",
|
|
568
|
+
className: "raf__inline-button",
|
|
569
|
+
onClick: () => K(W.mode),
|
|
570
|
+
style: D?.linkStyle,
|
|
571
|
+
children: W.label
|
|
572
|
+
})
|
|
573
|
+
}) : null,
|
|
574
|
+
N ? N({
|
|
575
|
+
...q,
|
|
576
|
+
label: $.submitLabel,
|
|
577
|
+
submit: () => {
|
|
578
|
+
Z();
|
|
579
|
+
}
|
|
580
|
+
}) : /* @__PURE__ */ (0, f.jsx)("button", {
|
|
581
|
+
type: "submit",
|
|
582
|
+
className: "raf__submit",
|
|
583
|
+
disabled: H,
|
|
584
|
+
style: {
|
|
585
|
+
borderRadius: D?.buttonBorderRadius ?? 12,
|
|
586
|
+
...D?.buttonStyle
|
|
587
|
+
},
|
|
588
|
+
children: H ? he : /* @__PURE__ */ (0, f.jsx)("span", {
|
|
589
|
+
style: D?.buttonTextStyle,
|
|
590
|
+
children: $.submitLabel
|
|
591
|
+
})
|
|
592
|
+
}),
|
|
593
|
+
G.length > 0 ? P ? P({
|
|
594
|
+
...q,
|
|
595
|
+
links: G
|
|
596
|
+
}) : /* @__PURE__ */ (0, f.jsx)(w, {
|
|
597
|
+
links: G,
|
|
598
|
+
switchMode: K,
|
|
599
|
+
theme: D
|
|
600
|
+
}) : null
|
|
601
|
+
]
|
|
602
|
+
})
|
|
603
|
+
}, F),
|
|
604
|
+
A ? A(q) : null
|
|
605
|
+
]
|
|
606
|
+
})
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region src/demoAuthService.tsx
|
|
611
|
+
var E = class extends Error {
|
|
612
|
+
constructor(e) {
|
|
613
|
+
super(e), this.name = "DemoAuthException";
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
function D(e) {
|
|
617
|
+
let t = new TextEncoder().encode(e), n = "";
|
|
618
|
+
for (let e of t) n += String.fromCharCode(e);
|
|
619
|
+
if (typeof globalThis.btoa == "function") return globalThis.btoa(n);
|
|
620
|
+
let r = globalThis.Buffer;
|
|
621
|
+
return r ? r.from(t).toString("base64") : n;
|
|
622
|
+
}
|
|
623
|
+
function O() {
|
|
624
|
+
return 1e3 + Date.now() % 1e3;
|
|
625
|
+
}
|
|
626
|
+
function k(e) {
|
|
627
|
+
return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(e);
|
|
628
|
+
}
|
|
629
|
+
function A(e) {
|
|
630
|
+
return e.trim().toLowerCase();
|
|
631
|
+
}
|
|
632
|
+
function j(e) {
|
|
633
|
+
return new Promise((t) => {
|
|
634
|
+
globalThis.setTimeout(t, e);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
var M = class {
|
|
638
|
+
users = /* @__PURE__ */ new Map();
|
|
639
|
+
async signIn(e, t) {
|
|
640
|
+
await j(O());
|
|
641
|
+
let n = A(e), r = this.users.get(n);
|
|
642
|
+
if (!r || r.passwordHash !== D(t)) throw new E("Invalid email or password");
|
|
643
|
+
return {
|
|
644
|
+
email: r.email,
|
|
645
|
+
name: r.name
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
async signUp(e, t, n) {
|
|
649
|
+
await j(O());
|
|
650
|
+
let r = A(e);
|
|
651
|
+
if (!k(r)) throw new E("Please enter a valid email address");
|
|
652
|
+
if (t.length < 8) throw new E("Password must be at least 8 characters");
|
|
653
|
+
if (this.users.has(r)) throw new E("Email already in use");
|
|
654
|
+
let i = {
|
|
655
|
+
email: r,
|
|
656
|
+
passwordHash: D(t),
|
|
657
|
+
name: n.trim(),
|
|
658
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
659
|
+
};
|
|
660
|
+
return this.users.set(r, i), {
|
|
661
|
+
email: i.email,
|
|
662
|
+
name: i.name
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
async forgotPassword(e) {
|
|
666
|
+
if (await j(1e3), !k(A(e))) throw new E("Please enter a valid email address");
|
|
667
|
+
}
|
|
668
|
+
clearUsers() {
|
|
669
|
+
this.users.clear();
|
|
670
|
+
}
|
|
671
|
+
get userCount() {
|
|
672
|
+
return this.users.size;
|
|
673
|
+
}
|
|
674
|
+
getCreatedAt(e) {
|
|
675
|
+
return this.users.get(A(e))?.createdAt ?? null;
|
|
676
|
+
}
|
|
677
|
+
}, N = e(null);
|
|
678
|
+
function P(e) {
|
|
679
|
+
let { service: t, children: n } = e;
|
|
680
|
+
return /* @__PURE__ */ (0, f.jsx)(N.Provider, {
|
|
681
|
+
value: t,
|
|
682
|
+
children: n
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
function F() {
|
|
686
|
+
let e = n(N);
|
|
687
|
+
if (!e) throw Error("useDemoAuthService() must be used inside a DemoAuthServiceProvider.");
|
|
688
|
+
return e;
|
|
689
|
+
}
|
|
690
|
+
function I() {
|
|
691
|
+
return n(N);
|
|
692
|
+
}
|
|
693
|
+
//#endregion
|
|
694
|
+
export { T as AuthFlow, l as AuthFlowType, E as DemoAuthException, M as DemoAuthService, P as DemoAuthServiceProvider, F as useDemoAuthService, I as useMaybeDemoAuthService };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.raf{color:var(--raf-text);width:100%;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.raf__card{background:var(--raf-background);border:1px solid var(--raf-surface-border);box-shadow:var(--raf-shadow);border-radius:24px;padding:28px}.raf__header{margin-bottom:24px}.raf__title{margin:0;font-size:1.75rem;font-weight:700;line-height:1.2}.raf__subtitle{color:var(--raf-muted-text);margin:8px 0 0;font-size:.95rem}.raf__error-shell{margin-bottom:18px}.raf__error{background:color-mix(in srgb, var(--raf-error) 10%, transparent);border:1px solid color-mix(in srgb, var(--raf-error) 22%, transparent);color:var(--raf-error);border-radius:14px;align-items:center;gap:10px;padding:12px 14px;display:flex}.raf__error-icon{border:1px solid;border-radius:999px;justify-content:center;align-items:center;width:18px;height:18px;font-size:.8rem;display:inline-flex}.raf__panel{animation:raf-enter var(--raf-transition-duration) var(--raf-transition-timing)}.raf__form{flex-direction:column;gap:16px;display:flex}.raf__field{flex-direction:column;gap:8px;display:flex}.raf__field-label{font-size:.95rem;font-weight:600}.raf__input{appearance:none;background:var(--raf-input-fill);border:1px solid var(--raf-input-border);color:var(--raf-text);font:inherit;min-height:48px;transition:border-color var(--raf-transition-duration) ease, box-shadow var(--raf-transition-duration) ease, background-color var(--raf-transition-duration) ease;outline:none;padding:0 14px}.raf__input:focus{border-color:var(--raf-primary);box-shadow:0 0 0 4px color-mix(in srgb, var(--raf-primary) 18%, transparent)}.raf__input[aria-invalid=true]{border-color:var(--raf-error)}.raf__field-error{color:var(--raf-error);font-size:.875rem}.raf__forgot-shell{justify-content:flex-end;margin-top:-6px;display:flex}.raf__inline-button{color:var(--raf-primary);cursor:pointer;font:inherit;background:0 0;border:0;padding:0;font-weight:600}.raf__inline-button:hover{opacity:.88}.raf__submit{background:var(--raf-primary);color:#fff;cursor:pointer;font:inherit;min-height:50px;transition:opacity var(--raf-transition-duration) ease, transform var(--raf-transition-duration) ease;border:none;justify-content:center;align-items:center;padding:0 16px;font-weight:600;display:inline-flex}.raf__submit:hover:not(:disabled){opacity:.94;transform:translateY(-1px)}.raf__submit:disabled{cursor:not-allowed;opacity:.7}.raf__spinner{border:2.5px solid #fff6;border-top-color:#fff;border-radius:999px;width:20px;height:20px;animation:.8s linear infinite raf-spin;display:inline-block}.raf__mode-switcher{color:var(--raf-muted-text);justify-content:center;gap:4px;margin-top:8px;display:flex}@keyframes raf-enter{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes raf-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (width<=480px){.raf__card{border-radius:20px;padding:22px}}
|
|
2
|
+
/*$vite$:1*/
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maheshbvv/react-auth-flow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Drop-in React authentication flow with sign in, sign up, forgot password, theming, transitions, and render prop customization.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"style": "./dist/react-auth-flow.css",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./styles.css": "./dist/react-auth-flow.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"sideEffects": [
|
|
22
|
+
"**/*.css"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json && vite build",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"react",
|
|
32
|
+
"authentication",
|
|
33
|
+
"auth flow",
|
|
34
|
+
"signin",
|
|
35
|
+
"signup",
|
|
36
|
+
"forgot password",
|
|
37
|
+
"component library"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
42
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
46
|
+
"@testing-library/react": "^16.3.2",
|
|
47
|
+
"@testing-library/user-event": "^14.6.1",
|
|
48
|
+
"@types/react": "^19.2.14",
|
|
49
|
+
"@types/react-dom": "^19.2.3",
|
|
50
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
51
|
+
"jsdom": "^29.0.2",
|
|
52
|
+
"react": "^19.2.5",
|
|
53
|
+
"react-dom": "^19.2.5",
|
|
54
|
+
"typescript": "^6.0.2",
|
|
55
|
+
"vite": "^8.0.7",
|
|
56
|
+
"vitest": "^4.1.3"
|
|
57
|
+
}
|
|
58
|
+
}
|