Coder Social home page Coder Social logo

saas-js / saas-ui Goto Github PK

View Code? Open in Web Editor NEW
1.2K 10.0 110.0 31.55 MB

The React component library for startups, built with Chakra UI.

Home Page: https://saas-ui.dev

License: MIT License

TypeScript 67.37% JavaScript 0.57% CSS 0.10% HTML 0.04% Shell 0.01% Perl 0.25% Raku 0.35% EJS 0.20% MDX 31.12%
react ui chakra-ui design-system react-components uitkit accessible components emotion library

saas-ui's Introduction

Saas UI logo Saas UI logo

The React component library for Startups

NPM npm downloads MIT License follow on Twitter


Saas UI is an advanced component library designed to build beautiful B2B and dashboard style apps with speed. It's built on top of Chakra UI and fully written in Typescript.

This repository contains all open source components, as well as the documentation website.

Links

๐Ÿ’ก Documentation

๐Ÿงญ Roadmap

๐Ÿ–ผ Storybooks

๐ŸŒŸ Saas UI Pro

Sponsors โค๏ธ

Saas UI is sponsored by these amazing companies and people.

Contributing & Support

Want to help? Great! Check out the contributing guidelines and feel free to open a PR or discussion for feature requests and feedback.

If you'd like to support the project financially, you can become a sponsor of Saas UI or consider ordering Saas UI Pro Beta. All funds will go toward the further development of Saas UI. This will give you access to the private Git repository with the beta and our private Discord server for support.

Core

40+ essential open-source components built on top of Chakra UI.

  • Authentication screens
  • Powerful forms manager
  • DatePicker / DateRangePicker
  • Stepper, Timeline, DataTable and much more.

Pro

A premium frontend starter pack designed for SaaS products. Complete source code available in a monorepo that can serve as a starting point or as a reference for your project.

theme-tokens

  • Example Next.js SaaS app (https://demo.saas-ui.dev)
  • Authentication screens (Supabase/Magic/Clerk/Custom)
  • App layout
  • DataGrid and DataBoard (Kanban) with filtering/pagination
  • Charts / Sparklines
  • User account pages
  • Settings pages
  • Feature flags
  • Billing/subscription management (Lemonsqueezy)
  • Mocked API with React Query
  • Custom color schemes
  • Glass theme
  • Onboarding flows
  • Example pages (CRM, Inbox)

Using this repo

The docs website depends on private packages (@saas-ui-pro/react), and won't build fully without access to the private Git submodule.

This repository uses Yarn workspaces, to get started run:

yarn

Storybook

yarn storybook

Build

yarn build:packages

Website

Before running the website you need to build the props-docs by running this.

yarn build:props-docs

After that run the website with this command.

yarn w website dev

or

cd apps/website && yarn dev

License

All code in this repository, except for the Saas UI branding assets are licensed under MIT.

saas-ui's People

Contributors

0wczar avatar brewhousedigital avatar elcharitas avatar eliandersoh avatar iamclaytonray avatar itsjbecks avatar jgillich avatar kalpesh3000 avatar keks0r avatar kenzobenzo avatar maheshchandra10 avatar milanvanschaik avatar nadilas avatar ochrstn avatar omeraplak avatar pagebakers avatar prajjwalyd avatar robert-j-webb avatar rondinelly avatar saakshii12 avatar segfaultd avatar sh4d0wy avatar shraddha761 avatar singodiyashubham87 avatar thisisdayal avatar waptik avatar yl-btr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

saas-ui's Issues

ModalsManager typings are incorrect

Using useModals will result in a type error when used like this:

const modals = useModals()

modals.open({})

Error: Cannot invoke an object which is possibly 'undefined'.ts(2722)

This is incorrect, as it's never undefined.

Yarn install fails

Hello, I attempted to install the dependencies and got this error after deleting the yarn.lock and starting fresh, because the included yarn.lock was generating a similar error.

 YN0041: โ”‚ @saas-ui/next-workspaces@npm:^0.1.1: Invalid authentication (as an anonymous user)
โžค YN0000: โ”” Completed in 0s 751ms
โžค YN0000: Failed with errors in 0s 756ms

It seems that a private npm module is being requested for which the public does not have access.

Setup CI

Setup Github actions to run test automatically.

Also look into automating publishing.

Feature: Allow form UI to be customized

Currently, if you had a Stack, Box, etc in between some fields, those fields' state will be removed. I'm proposing an API that gives developers flexibility with how things are laid out

StepForm

A multi step form component.

Depends on #2

Auth does not trigger onError callback on error

Firstly, thanks for your work on this project! ๐Ÿ™‚

Today I used patch-package to patch @saas-ui/auth@^0.6.1 for the project I'm working on.

Here is the diff that solved my problem:

# generated by patch-package 6.4.8 on 2022-03-06 12:15:51
#
# command:
#   npx patch-package @saas-ui/auth
#
# declared package:
#   @saas-ui/auth: ^0.6.1
#
diff --git a/node_modules/@saas-ui/auth/dist/index.modern.js b/node_modules/@saas-ui/auth/dist/index.modern.js
index ee7c337..333a51b 100644
--- a/node_modules/@saas-ui/auth/dist/index.modern.js
+++ b/node_modules/@saas-ui/auth/dist/index.modern.js
@@ -1,2 +1,738 @@
-import*as e from"react";import{usePromise as t}from"@saas-ui/hooks";import{useTheme as n,Alert as r,AlertIcon as l,AlertTitle as o,AlertDescription as a,SimpleGrid as i,Icon as s,omitThemingProps as c,StylesProvider as u,chakra as d,useStyles as m,useColorModeValue as p,Link as E}from"@chakra-ui/react";import{useMultiStyleConfig as f}from"@saas-ui/system";import{Form as h,FormLayout as b,Field as g}from"@saas-ui/forms";import{Button as L}from"@saas-ui/button";const{createContext:v,useState:y,useContext:w,useEffect:S,useCallback:k}=e,P=v(null),O=({onLoadUser:t=(()=>Promise.resolve()),onSignup:n=(()=>Promise.resolve()),onLogin:r=(()=>Promise.resolve()),onVerifyOtp:l=(()=>Promise.resolve()),onLogout:o=(()=>Promise.resolve()),onAuthStateChange:a,onGetToken:i,onResetPassword:s,onUpdatePassword:c,children:u})=>{const[d,m]=y(!1),[p,E]=y(),[f,h]=y(!0);S(()=>{if(a){const e=a(e=>{m(!!e)});return()=>{e()}}},[]),S(()=>{g()},[d]);const b=k(async()=>{try{i&&m(!!await i())}catch(e){m(!1)}},[i]);S(()=>(window.addEventListener("focus",b),b(),()=>{window.removeEventListener("focus",b)}),[b]);const g=k(async()=>{if(d){const e=await t();e?E(e):m(!1)}h(!1)},[t,d]),L=k(async(e,t)=>{const r=await n(e,t);return b(),r},[n]),v=k(async(e,t)=>{const n=await r(e,t);return b(),n},[r]),w=k(async()=>{await o(),E(null),m(!1)},[o]),O=k(async(e,t)=>await l(e,t),[l]),x=k(async(e,t)=>{await(null==s?void 0:s(e,t))},[s]),A=k(async(e,t)=>{await(null==c?void 0:c(e,t))},[c]),V=k(async()=>null==i?void 0:i(),[i]);/*#__PURE__*/return e.createElement(P.Provider,{value:{isAuthenticated:d,isLoggingIn:d&&!p,isLoading:f,user:p,signUp:L,logIn:v,logOut:w,verifyOtp:O,loadUser:g,getToken:V,resetPassword:x,updatePassword:A}},u)},x=()=>w(P),A=()=>x().user,V=({action:e="logIn"}={})=>{const n=x();return t(t=>{var r;return null==(r=n[e])?void 0:r.call(n,t)})},C=()=>{const{signUp:e}=x();return t(t=>e(t))},I=()=>{const{verifyOtp:e}=x();return t(t=>e(t))},_=()=>{const{resetPassword:e}=x();return t(t=>e(t))},T=()=>{const{updatePassword:e}=x();return t(t=>e(t))};function W(){return W=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},W.apply(this,arguments)}function F(e,t){if(null==e)return{};var n,r,l={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(l[n]=e[n]);return l}const G=["children"];function R(t){var r;let{children:l}=t,o=F(t,G);const a=W({p:6,colorScheme:"gray"},null==(r=n().components.LoginButton)?void 0:r.defaultProps);/*#__PURE__*/return e.createElement(L,W({},a,o),l)}const U=["title","description"],D=t=>{let{title:n,description:i}=t,s=F(t,U);/*#__PURE__*/return e.createElement(r,W({status:"success",variant:"subtle",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center"},s),/*#__PURE__*/e.createElement(l,{boxSize:"40px",mr:0}),/*#__PURE__*/e.createElement(o,{mt:4,mb:1,fontSize:"lg"},n),/*#__PURE__*/e.createElement(a,{maxWidth:"sm"},i))},N=["schema","action","onSuccess","onError","onValidationError","submitLabel","defaultValues","renderSuccess","children"];function q({email:t}){/*#__PURE__*/return e.createElement(D,{title:"Check your mailbox!",description:/*#__PURE__*/e.createElement(e.Fragment,null,`We've sent a magic link to ${t||"your email address"}.`/*#__PURE__*/,e.createElement("br",null),"Click on the link to continue.")})}const j=t=>{let{schema:n,action:r="logIn",onSuccess:l=(()=>null),onError:o=(()=>null),onValidationError:a,submitLabel:i="Continue with Email",defaultValues:s,renderSuccess:c=(t=>/*#__PURE__*/e.createElement(q,{email:null==t?void 0:t.email})),children:u}=t,d=F(t,N);const[{isLoading:m,isResolved:p,data:E},f]=V({action:r});return p?c(E):/*#__PURE__*/e.createElement(h,W({schema:n,onSubmit:({email:e})=>f({email:e}).then(l).catch(o),onError:a,defaultValues:W({email:""},s)},d),/*#__PURE__*/e.createElement(b,null,/*#__PURE__*/e.createElement(g,{name:"email",label:"Email",type:"email",rules:{required:!0}}),u,/*#__PURE__*/e.createElement(R,{type:"submit",isLoading:m,isFullWidth:!0,label:i})))},z=["action","schema","onSuccess","onError","onValidationError","submitLabel","defaultValues","children","renderSuccess"],B=t=>{let{action:n="logIn",schema:r,onSuccess:l=(()=>null),onError:o=(()=>null),onValidationError:a,submitLabel:i="Log in",defaultValues:s,children:c,renderSuccess:u=(()=>/*#__PURE__*/e.createElement(D,{title:"Success!",description:"Check your mailbox to verify your account."}))}=t,d=F(t,z);const[{isLoading:m,isResolved:p,data:E},f]=V({action:n});return p&&"signUp"===n?u(E):/*#__PURE__*/e.createElement(h,W({schema:r,onSubmit:e=>f(e).then(l).catch(o),onError:a,defaultValues:W({email:"",password:""},s)},d),/*#__PURE__*/e.createElement(b,null,/*#__PURE__*/e.createElement(g,{name:"email",label:"Email",type:"email",rules:{required:!0}}),/*#__PURE__*/e.createElement(g,{name:"password",label:"Password",type:"password",rules:{required:!0}}),c,/*#__PURE__*/e.createElement(R,{type:"submit",isFullWidth:!0,isLoading:m},i)))},Y=["schema","onSuccess","onError","onValidationError","submitLabel","label","helpText","pinLength","children","renderSuccess"],$=t=>{let{schema:n,onSuccess:r=(()=>null),onError:l=(()=>null),onValidationError:o,submitLabel:a="Verify",label:i,helpText:s,pinLength:c=4,children:u,renderSuccess:d=(()=>/*#__PURE__*/e.createElement(D,{title:"Success!",description:"You are now logged in."}))}=t,m=F(t,Y);const[{isLoading:p,data:E},f]=I();return E?d(E):/*#__PURE__*/e.createElement(h,W({schema:n,onSubmit:e=>f(e).then(r).catch(l),onError:o,defaultValues:{otp:""}},m),/*#__PURE__*/e.createElement(b,null,/*#__PURE__*/e.createElement(g,{name:"otp",label:i,help:s,type:"pin",pinLength:c,rules:{required:!0}}),u,/*#__PURE__*/e.createElement(R,{type:"submit",isFullWidth:!0,isLoading:p},a)))};$.defaultProps={helpText:"You can find your one-time password in the Google Authenticator or Authy app.",submitLabel:"Verify",label:"Your verification code"};const H=["children"];function J(t){var r;let{children:l}=t,o=F(t,H);const a=W({p:6,variant:"outline"},null==(r=n().components.ProviderButton)?void 0:r.defaultProps);/*#__PURE__*/return e.createElement(L,W({},a,o),l)}const K=["providers","redirectTo","label"],M=t=>{let{providers:n,redirectTo:r,label:l="Continue with"}=t,o=F(t,K);const{logIn:a}=x();if(!n)return null;const c=e=>async()=>{await a({provider:e},{redirectTo:r})};/*#__PURE__*/return e.createElement(i,W({spacing:4},o),Object.entries(n).map(([t,n])=>{const{name:r,icon:o,color:a}=n;/*#__PURE__*/return e.createElement(J,{onClick:c(t),color:a,leftIcon:o&&/*#__PURE__*/e.createElement(s,{as:o}),key:t},l," ",r)}))},Q=["schema","onSuccess","onError","onValidationError","submitLabel","label","helpText","children","renderSuccess"],X=t=>{let{schema:n,onSuccess:r=(()=>null),onError:l=(()=>null),onValidationError:o,submitLabel:a,label:i,children:s,renderSuccess:c=(()=>/*#__PURE__*/e.createElement(D,{title:"Success!",description:"Please check your email for instructions to reset your password."}))}=t,u=F(t,Q);const[{isLoading:d,data:m},p]=_();return m?c(m):/*#__PURE__*/e.createElement(h,W({schema:n,onSubmit:e=>p(e).then(r).catch(l),onError:o,defaultValues:{email:""}},u),/*#__PURE__*/e.createElement(b,null,/*#__PURE__*/e.createElement(g,{name:"email",label:i,type:"email",rules:{required:!0}}),s,/*#__PURE__*/e.createElement(R,{type:"submit",isFullWidth:!0,isLoading:d},a)))};X.defaultProps={submitLabel:"Reset password",label:"Your email address"};const Z=["schema","onSuccess","onError","onValidationError","submitLabel","label","confirmLabel","helpText","children"],ee=t=>{let{schema:n,onSuccess:r=(()=>null),onError:l=(()=>null),onValidationError:o,submitLabel:a,label:i,confirmLabel:s,children:c}=t,u=F(t,Z);const[{isLoading:d},m]=T(),p=e.useRef(null),E=e.useCallback(e=>{var t;return e===(null==(t=p.current)?void 0:t.getValues("password"))},[]);/*#__PURE__*/return e.createElement(h,W({schema:n,onSubmit:({password:e})=>m({password:e}).then(r).catch(l),onError:o,defaultValues:{password:"",confirmPassword:""},ref:p},u),/*#__PURE__*/e.createElement(b,null,/*#__PURE__*/e.createElement(g,{name:"password",label:i,type:"password",rules:{required:!0}}),/*#__PURE__*/e.createElement(g,{name:"confirmPassword",label:s,type:"password",rules:{validate:E}}),c,/*#__PURE__*/e.createElement(R,{type:"submit",isFullWidth:!0,isLoading:d},a)))};ee.defaultProps={submitLabel:"Update password",label:"New password",confirmLabel:"Confirm password"};const te=["type","providers","title","providerLabel","dividerLabel","footer"],ne=["label"],re=["children"],le=["title","footer"],oe=["title","footer"],ae=["title","footer"],ie=t=>{const{type:n,providers:r,title:l,providerLabel:o,dividerLabel:a,footer:i}=t,s=F(t,te);let c;return c=/*#__PURE__*/e.createElement("password"===n?B:j,s),/*#__PURE__*/e.createElement(se,null,"string"==typeof l?/*#__PURE__*/e.createElement(ue,null,l):l,r&&/*#__PURE__*/e.createElement(e.Fragment,null,/*#__PURE__*/e.createElement(M,{providers:r,label:o}),/*#__PURE__*/e.createElement(ce,{label:a})),c,i)};ie.defaultProps={type:"magiclink",providerLabel:"Continue with",dividerLabel:"or continue with"};const se=t=>{const{children:n}=t,r=f("AuthForm",t),l=c(t),o=W({display:"flex",flexDirection:"column",alignItems:"stretch",width:"full"},r.container);/*#__PURE__*/return e.createElement(u,{value:r},/*#__PURE__*/e.createElement(d.div,W({__css:o},l),n))},ce=t=>{let{label:n}=t,r=F(t,ne);const l=m(),o={borderBottomWidth:"1px",content:'""',position:"relative",display:"inline-block",width:"50%",top:"50%"},a=W({display:"flex",flexDirection:"row",alignItems:"center",whiteSpace:"nowrap",py:8,color:p("gray.400","whiteAlpha.300"),_before:o,_after:o},l.divider);/*#__PURE__*/return e.createElement(d.div,W({__css:a},r),n&&/*#__PURE__*/e.createElement(d.span,{__css:{display:"inline-block",flexShrink:0,mx:2}},n))},ue=t=>{let{children:n}=t,r=F(t,re);const l=W({fontSize:"2xl",fontWeight:"bold",textAlign:"center",mb:8},m().title);/*#__PURE__*/return e.createElement(d.h2,W({__css:l},r),n)},de=t=>/*#__PURE__*/e.createElement(ie,W({action:"logIn"},t));de.defaultProps={title:"Log in",submitLabel:"Log in"};const me=t=>/*#__PURE__*/e.createElement(ie,W({action:"signUp"},t));me.defaultProps={title:"Sign up",submitLabel:"Sign up"};const pe=t=>{const{title:n,footer:r}=t,l=F(t,le);/*#__PURE__*/return e.createElement(se,null,"string"==typeof n?/*#__PURE__*/e.createElement(ue,null,n):n,/*#__PURE__*/e.createElement($,l),r)};pe.defaultProps={title:"One-time password"};const Ee=t=>{const{title:n,footer:r}=t,l=F(t,oe);/*#__PURE__*/return e.createElement(se,null,"string"==typeof n?/*#__PURE__*/e.createElement(ue,null,n):n,/*#__PURE__*/e.createElement(X,l),r)};Ee.defaultProps={title:"Forgot password"};const fe=t=>{const{title:n,footer:r}=t,l=F(t,ae);/*#__PURE__*/return e.createElement(se,null,"string"==typeof n?/*#__PURE__*/e.createElement(ue,null,n):n,/*#__PURE__*/e.createElement(ee,l),r)};fe.defaultProps={title:"Choose a new password"};const he=["view","providers","signupLink","loginLink","forgotLink","backLink","noAccount","haveAccount"],be={LOGIN:"login",SIGNUP:"signup",FORGOT_PASSWORD:"forgot_password",UPDATE_PASSWORD:"update_password",OTP:"otp"},ge=t=>{const{view:n=be.LOGIN,providers:r,signupLink:l,loginLink:o,forgotLink:a,backLink:i,noAccount:s,haveAccount:c}=t,u=F(t,he),{type:d}=u,[m,p]=e.useState(n);switch(e.useEffect(()=>{p(n)},[n]),m){case be.LOGIN:/*#__PURE__*/return e.createElement(de,W({providers:r,footer:/*#__PURE__*/e.createElement(Le,{onClick:()=>p(be.SIGNUP),label:s,link:l})},u),"password"===d&&("string"==typeof a?/*#__PURE__*/e.createElement(E,{fontSize:"md",color:"muted",float:"right",onClick:()=>p(be.FORGOT_PASSWORD)},a):a));case be.SIGNUP:/*#__PURE__*/return e.createElement(me,W({providers:r,footer:/*#__PURE__*/e.createElement(Le,{onClick:()=>p(be.LOGIN),label:c,link:o})},u));case be.FORGOT_PASSWORD:/*#__PURE__*/return e.createElement(Ee,W({footer:/*#__PURE__*/e.createElement(Le,{onClick:()=>p(be.LOGIN),link:i})},u));case be.UPDATE_PASSWORD:/*#__PURE__*/return e.createElement(fe,u);case be.OTP:/*#__PURE__*/return e.createElement(pe,u)}return null},Le=({label:t,link:n,onClick:r})=>/*#__PURE__*/e.createElement(d.div,{__css:{textAlign:"center",py:8,fontSize:"md"}},t&&/*#__PURE__*/e.createElement(d.span,{color:"muted"},t)," ","string"==typeof n?/*#__PURE__*/e.createElement(E,{onClick:r},n):n);ge.defaultProps={noAccount:"No account yet?",haveAccount:"Already have an account?",signupLink:"Sign up",loginLink:"Log in",forgotLink:"Forgot password?",backLink:"Back to log in"};export{ge as Auth,ie as AuthForm,se as AuthFormContainer,ce as AuthFormDivider,ue as AuthFormTitle,O as AuthProvider,Ee as ForgotPasswordView,R as LoginButton,de as LoginView,j as MagicLinkForm,q as MagicLinkSuccess,$ as OtpForm,pe as OtpView,B as PasswordForm,J as ProviderButton,M as Providers,me as SignupView,fe as UpdatePasswordView,be as VIEWS,x as useAuth,A as useCurrentUser,V as useLogin,I as useOtp,_ as useResetPassword,C as useSignUp,T as useUpdatePassword};
+import * as e from "react";
+import {
+    usePromise as t
+}
+from "@saas-ui/hooks";
+import {
+    useTheme as n, Alert as r, AlertIcon as l, AlertTitle as o, AlertDescription as a, SimpleGrid as i, Icon as s, omitThemingProps as c, StylesProvider as u, chakra as d, useStyles as m, useColorModeValue as p, Link as E
+}
+from "@chakra-ui/react";
+import {
+    useMultiStyleConfig as f
+}
+from "@saas-ui/system";
+import {
+    Form as h, FormLayout as b, Field as g
+}
+from "@saas-ui/forms";
+import {
+    Button as L
+}
+from "@saas-ui/button";
+const {
+    createContext: v,
+    useState: y,
+    useContext: w,
+    useEffect: S,
+    useCallback: k
+} = e, P = v(null), O = ({
+    onLoadUser: t = (() => Promise.resolve()),
+    onSignup: n = (() => Promise.resolve()),
+    onLogin: r = (() => Promise.resolve()),
+    onVerifyOtp: l = (() => Promise.resolve()),
+    onLogout: o = (() => Promise.resolve()),
+    onAuthStateChange: a,
+    onGetToken: i,
+    onResetPassword: s,
+    onUpdatePassword: c,
+    children: u
+}) => {
+    const [d, m] = y(!1), [p, E] = y(), [f, h] = y(!0);
+    S(() => {
+        if (a) {
+            const e = a(e => {
+                m(!!e)
+            });
+            return () => {
+                e()
+            }
+        }
+    }, []), S(() => {
+        g()
+    }, [d]);
+    const b = k(async() => {
+        try {
+            i && m(!!await i())
+        } catch (e) {
+            m(!1)
+        }
+    }, [i]);
+    S(() => (window.addEventListener("focus", b), b(), () => {
+        window.removeEventListener("focus", b)
+    }), [b]);
+    const g = k(async() => {
+            if (d) {
+                const e = await t();
+                e ? E(e) : m(!1)
+            }
+            h(!1)
+        }, [t, d]),
+        L = k(async(e, t) => {
+            const r = await n(e, t);
+            return b(), r
+        }, [n]),
+        v = k(async(e, t) => {
+            try {
+                const n = await r(e, t);
+                console.log(n,n,n)
+                return b(), n
+            } catch(e) {
+                throw e;
+            }
+        }, [r]),
+        w = k(async() => {
+            await o(), E(null), m(!1)
+        }, [o]),
+        O = k(async(e, t) => await l(e, t), [l]),
+        x = k(async(e, t) => {
+            await(null == s ? void 0 : s(e, t))
+        }, [s]),
+        A = k(async(e, t) => {
+            await(null == c ? void 0 : c(e, t))
+        }, [c]),
+        V = k(async() => null == i ? void 0 : i(), [i]); /*#__PURE__*/
+    return e.createElement(P.Provider, {
+        value: {
+            isAuthenticated: d,
+            isLoggingIn: d && !p,
+            isLoading: f,
+            user: p,
+            signUp: L,
+            logIn: v,
+            logOut: w,
+            verifyOtp: O,
+            loadUser: g,
+            getToken: V,
+            resetPassword: x,
+            updatePassword: A
+        }
+    }, u)
+}, x = () => w(P), A = () => x().user, V = ({
+    action: e = "logIn"
+} = {}) => {
+    const n = x();
+    return t(t => {
+        var r;
+        return null == (r = n[e]) ? void 0 : r.call(n, t)
+    })
+}, C = () => {
+    const {
+        signUp: e
+    } = x();
+    return t(t => e(t))
+}, I = () => {
+    const {
+        verifyOtp: e
+    } = x();
+    return t(t => e(t))
+}, _ = () => {
+    const {
+        resetPassword: e
+    } = x();
+    return t(t => e(t))
+}, T = () => {
+    const {
+        updatePassword: e
+    } = x();
+    return t(t => e(t))
+};
+
+function W() {
+    return W = Object.assign || function(e) {
+        for (var t = 1; t < arguments.length; t++) {
+            var n = arguments[t];
+            for (var r in n) Object.prototype.hasOwnProperty.call(n, r) && (e[r] = n[r])
+        }
+        return e
+    }, W.apply(this, arguments)
+}
+
+function F(e, t) {
+    if (null == e) return {};
+    var n, r, l = {},
+        o = Object.keys(e);
+    for (r = 0; r < o.length; r++) t.indexOf(n = o[r]) >= 0 || (l[n] = e[n]);
+    return l
+}
+const G = ["children"];
+
+function R(t) {
+    var r;
+    let {
+        children: l
+    } = t, o = F(t, G);
+    const a = W({
+        p: 6,
+        colorScheme: "gray"
+    }, null == (r = n().components.LoginButton) ? void 0 : r.defaultProps); /*#__PURE__*/
+    return e.createElement(L, W({}, a, o), l)
+}
+const U = ["title", "description"],
+    D = t => {
+        let {
+            title: n,
+            description: i
+        } = t, s = F(t, U); /*#__PURE__*/
+        return e.createElement(r, W({
+            status: "success",
+            variant: "subtle",
+            flexDirection: "column",
+            alignItems: "center",
+            justifyContent: "center",
+            textAlign: "center"
+        }, s), /*#__PURE__*/ e.createElement(l, {
+            boxSize: "40px",
+            mr: 0
+        }), /*#__PURE__*/ e.createElement(o, {
+            mt: 4,
+            mb: 1,
+            fontSize: "lg"
+        }, n), /*#__PURE__*/ e.createElement(a, {
+            maxWidth: "sm"
+        }, i))
+    },
+    N = ["schema", "action", "onSuccess", "onError", "onValidationError", "submitLabel", "defaultValues", "renderSuccess", "children"];
+
+function q({
+    email: t
+}) { /*#__PURE__*/
+    return e.createElement(D, {
+        title: "Check your mailbox!",
+        description: /*#__PURE__*/ e.createElement(e.Fragment, null, `We've sent a magic link to ${t||"your email address"}.` /*#__PURE__*/ , e.createElement("br", null), "Click on the link to continue.")
+    })
+}
+const j = t => {
+        let {
+            schema: n,
+            action: r = "logIn",
+            onSuccess: l = (() => null),
+            onError: o = (() => null),
+            onValidationError: a,
+            submitLabel: i = "Continue with Email",
+            defaultValues: s,
+            renderSuccess: c = (t => /*#__PURE__*/ e.createElement(q, {
+                email: null == t ? void 0 : t.email
+            })),
+            children: u
+        } = t, d = F(t, N);
+        const [{
+            isLoading: m,
+            isResolved: p,
+            isRejected,
+            error,
+            data: E
+        }, f] = V({
+            action: r
+        });
+        e.useEffect(() => {
+            if(isRejected) {
+              o(error);
+            }
+            if(p) {
+                l();
+            }
+          }, [error, isRejected, p]);
+        return p ? c(E) : /*#__PURE__*/ e.createElement(h, W({
+            schema: n,
+            onSubmit: ({
+                email: e
+            }) => f({
+                email: e
+            }),
+            onError: a,
+            defaultValues: W({
+                email: ""
+            }, s)
+        }, d), /*#__PURE__*/ e.createElement(b, null, /*#__PURE__*/ e.createElement(g, {
+            name: "email",
+            label: "Email",
+            type: "email",
+            rules: {
+                required: !0
+            }
+        }), u, /*#__PURE__*/ e.createElement(R, {
+            type: "submit",
+            isLoading: m,
+            isFullWidth: !0,
+            label: i
+        })))
+    },
+    z = ["action", "schema", "onSuccess", "onError", "onValidationError", "submitLabel", "defaultValues", "children", "renderSuccess"],
+    B = t => {
+        let {
+            action: n = "logIn",
+            schema: r,
+            onSuccess: l = (() => null),
+            onError: o = (() => null),
+            onValidationError: a,
+            submitLabel: i = "Log in",
+            defaultValues: s,
+            children: c,
+            renderSuccess: u = (() => /*#__PURE__*/ e.createElement(D, {
+                title: "Success!",
+                description: "Check your mailbox to verify your account."
+            }))
+        } = t, d = F(t, z);
+        const [{
+            isLoading: m,
+            isResolved: p,
+            isRejected,
+            error,
+            data: E
+        }, f] = V({
+            action: n
+        });
+        e.useEffect(() => {
+            if(isRejected) {
+              o(error);
+            }
+            if(p) {
+                l();
+            }
+          }, [error, isRejected, p]);
+        return p && "signUp" === n ? u(E) : /*#__PURE__*/ e.createElement(h, W({
+            schema: r,
+            onSubmit: e => f(e),
+            onError: a,
+            defaultValues: W({
+                email: "",
+                password: ""
+            }, s)
+        }, d), /*#__PURE__*/ e.createElement(b, null, /*#__PURE__*/ e.createElement(g, {
+            name: "email",
+            label: "Email",
+            type: "email",
+            rules: {
+                required: !0
+            }
+        }), /*#__PURE__*/ e.createElement(g, {
+            name: "password",
+            label: "Password",
+            type: "password",
+            rules: {
+                required: !0
+            }
+        }), c, /*#__PURE__*/ e.createElement(R, {
+            type: "submit",
+            isFullWidth: !0,
+            isLoading: m
+        }, i)))
+    },
+    Y = ["schema", "onSuccess", "onError", "onValidationError", "submitLabel", "label", "helpText", "pinLength", "children", "renderSuccess"],
+    $ = t => {
+        let {
+            schema: n,
+            onSuccess: r = (() => null),
+            onError: l = (() => null),
+            onValidationError: o,
+            submitLabel: a = "Verify",
+            label: i,
+            helpText: s,
+            pinLength: c = 4,
+            children: u,
+            renderSuccess: d = (() => /*#__PURE__*/ e.createElement(D, {
+                title: "Success!",
+                description: "You are now logged in."
+            }))
+        } = t, m = F(t, Y);
+        const [{
+            isLoading: p,
+            data: E
+        }, f] = I();
+        return E ? d(E) : /*#__PURE__*/ e.createElement(h, W({
+            schema: n,
+            onSubmit: e => f(e).then(r).catch(l),
+            onError: o,
+            defaultValues: {
+                otp: ""
+            }
+        }, m), /*#__PURE__*/ e.createElement(b, null, /*#__PURE__*/ e.createElement(g, {
+            name: "otp",
+            label: i,
+            help: s,
+            type: "pin",
+            pinLength: c,
+            rules: {
+                required: !0
+            }
+        }), u, /*#__PURE__*/ e.createElement(R, {
+            type: "submit",
+            isFullWidth: !0,
+            isLoading: p
+        }, a)))
+    };
+$.defaultProps = {
+    helpText: "You can find your one-time password in the Google Authenticator or Authy app.",
+    submitLabel: "Verify",
+    label: "Your verification code"
+};
+const H = ["children"];
+
+function J(t) {
+    var r;
+    let {
+        children: l
+    } = t, o = F(t, H);
+    const a = W({
+        p: 6,
+        variant: "outline"
+    }, null == (r = n().components.ProviderButton) ? void 0 : r.defaultProps); /*#__PURE__*/
+    return e.createElement(L, W({}, a, o), l)
+}
+const K = ["providers", "redirectTo", "label"],
+    M = t => {
+        let {
+            providers: n,
+            redirectTo: r,
+            label: l = "Continue with"
+        } = t, o = F(t, K);
+        const {
+            logIn: a
+        } = x();
+        if (!n) return null;
+        const c = e => async() => {
+            await a({
+                provider: e
+            }, {
+                redirectTo: r
+            })
+        }; /*#__PURE__*/
+        return e.createElement(i, W({
+            spacing: 4
+        }, o), Object.entries(n).map(([t, n]) => {
+            const {
+                name: r,
+                icon: o,
+                color: a
+            } = n; /*#__PURE__*/
+            return e.createElement(J, {
+                onClick: c(t),
+                color: a,
+                leftIcon: o && /*#__PURE__*/ e.createElement(s, {
+                    as: o
+                }),
+                key: t
+            }, l, " ", r)
+        }))
+    },
+    Q = ["schema", "onSuccess", "onError", "onValidationError", "submitLabel", "label", "helpText", "children", "renderSuccess"],
+    X = t => {
+        let {
+            schema: n,
+            onSuccess: r = (() => null),
+            onError: l = (() => null),
+            onValidationError: o,
+            submitLabel: a,
+            label: i,
+            children: s,
+            renderSuccess: c = (() => /*#__PURE__*/ e.createElement(D, {
+                title: "Success!",
+                description: "Please check your email for instructions to reset your password."
+            }))
+        } = t, u = F(t, Q);
+        const [{
+            isLoading: d,
+            data: m
+        }, p] = _();
+        return m ? c(m) : /*#__PURE__*/ e.createElement(h, W({
+            schema: n,
+            onSubmit: e => p(e).then(r).catch(l),
+            onError: o,
+            defaultValues: {
+                email: ""
+            }
+        }, u), /*#__PURE__*/ e.createElement(b, null, /*#__PURE__*/ e.createElement(g, {
+            name: "email",
+            label: i,
+            type: "email",
+            rules: {
+                required: !0
+            }
+        }), s, /*#__PURE__*/ e.createElement(R, {
+            type: "submit",
+            isFullWidth: !0,
+            isLoading: d
+        }, a)))
+    };
+X.defaultProps = {
+    submitLabel: "Reset password",
+    label: "Your email address"
+};
+const Z = ["schema", "onSuccess", "onError", "onValidationError", "submitLabel", "label", "confirmLabel", "helpText", "children"],
+    ee = t => {
+        let {
+            schema: n,
+            onSuccess: r = (() => null),
+            onError: l = (() => null),
+            onValidationError: o,
+            submitLabel: a,
+            label: i,
+            confirmLabel: s,
+            children: c
+        } = t, u = F(t, Z);
+        const [{
+            isLoading: d
+        }, m] = T(), p = e.useRef(null), E = e.useCallback(e => {
+            var t;
+            return e === (null == (t = p.current) ? void 0 : t.getValues("password"))
+        }, []); /*#__PURE__*/
+        return e.createElement(h, W({
+            schema: n,
+            onSubmit: ({
+                password: e
+            }) => m({
+                password: e
+            }).then(r).catch(l),
+            onError: o,
+            defaultValues: {
+                password: "",
+                confirmPassword: ""
+            },
+            ref: p
+        }, u), /*#__PURE__*/ e.createElement(b, null, /*#__PURE__*/ e.createElement(g, {
+            name: "password",
+            label: i,
+            type: "password",
+            rules: {
+                required: !0
+            }
+        }), /*#__PURE__*/ e.createElement(g, {
+            name: "confirmPassword",
+            label: s,
+            type: "password",
+            rules: {
+                validate: E
+            }
+        }), c, /*#__PURE__*/ e.createElement(R, {
+            type: "submit",
+            isFullWidth: !0,
+            isLoading: d
+        }, a)))
+    };
+ee.defaultProps = {
+    submitLabel: "Update password",
+    label: "New password",
+    confirmLabel: "Confirm password"
+};
+const te = ["type", "providers", "title", "providerLabel", "dividerLabel", "footer"],
+    ne = ["label"],
+    re = ["children"],
+    le = ["title", "footer"],
+    oe = ["title", "footer"],
+    ae = ["title", "footer"],
+    ie = t => {
+        const {
+            type: n,
+            providers: r,
+            title: l,
+            providerLabel: o,
+            dividerLabel: a,
+            footer: i
+        } = t, s = F(t, te);
+        let c;
+        return c = /*#__PURE__*/ e.createElement("password" === n ? B : j, s), /*#__PURE__*/ e.createElement(se, null, "string" == typeof l ? /*#__PURE__*/ e.createElement(ue, null, l) : l, r && /*#__PURE__*/ e.createElement(e.Fragment, null, /*#__PURE__*/ e.createElement(M, {
+            providers: r,
+            label: o
+        }), /*#__PURE__*/ e.createElement(ce, {
+            label: a
+        })), c, i)
+    };
+ie.defaultProps = {
+    type: "magiclink",
+    providerLabel: "Continue with",
+    dividerLabel: "or continue with"
+};
+const se = t => {
+        const {
+            children: n
+        } = t, r = f("AuthForm", t), l = c(t), o = W({
+            display: "flex",
+            flexDirection: "column",
+            alignItems: "stretch",
+            width: "full"
+        }, r.container); /*#__PURE__*/
+        return e.createElement(u, {
+            value: r
+        }, /*#__PURE__*/ e.createElement(d.div, W({
+            __css: o
+        }, l), n))
+    },
+    ce = t => {
+        let {
+            label: n
+        } = t, r = F(t, ne);
+        const l = m(),
+            o = {
+                borderBottomWidth: "1px",
+                content: '""',
+                position: "relative",
+                display: "inline-block",
+                width: "50%",
+                top: "50%"
+            },
+            a = W({
+                display: "flex",
+                flexDirection: "row",
+                alignItems: "center",
+                whiteSpace: "nowrap",
+                py: 8,
+                color: p("gray.400", "whiteAlpha.300"),
+                _before: o,
+                _after: o
+            }, l.divider); /*#__PURE__*/
+        return e.createElement(d.div, W({
+            __css: a
+        }, r), n && /*#__PURE__*/ e.createElement(d.span, {
+            __css: {
+                display: "inline-block",
+                flexShrink: 0,
+                mx: 2
+            }
+        }, n))
+    },
+    ue = t => {
+        let {
+            children: n
+        } = t, r = F(t, re);
+        const l = W({
+            fontSize: "2xl",
+            fontWeight: "bold",
+            textAlign: "center",
+            mb: 8
+        }, m().title); /*#__PURE__*/
+        return e.createElement(d.h2, W({
+            __css: l
+        }, r), n)
+    },
+    de = t => /*#__PURE__*/ e.createElement(ie, W({
+        action: "logIn"
+    }, t));
+de.defaultProps = {
+    title: "Log in",
+    submitLabel: "Log in"
+};
+const me = t => /*#__PURE__*/ e.createElement(ie, W({
+    action: "signUp"
+}, t));
+me.defaultProps = {
+    title: "Sign up",
+    submitLabel: "Sign up"
+};
+const pe = t => {
+    const {
+        title: n,
+        footer: r
+    } = t, l = F(t, le); /*#__PURE__*/
+    return e.createElement(se, null, "string" == typeof n ? /*#__PURE__*/ e.createElement(ue, null, n) : n, /*#__PURE__*/ e.createElement($, l), r)
+};
+pe.defaultProps = {
+    title: "One-time password"
+};
+const Ee = t => {
+    const {
+        title: n,
+        footer: r
+    } = t, l = F(t, oe); /*#__PURE__*/
+    return e.createElement(se, null, "string" == typeof n ? /*#__PURE__*/ e.createElement(ue, null, n) : n, /*#__PURE__*/ e.createElement(X, l), r)
+};
+Ee.defaultProps = {
+    title: "Forgot password"
+};
+const fe = t => {
+    const {
+        title: n,
+        footer: r
+    } = t, l = F(t, ae); /*#__PURE__*/
+    return e.createElement(se, null, "string" == typeof n ? /*#__PURE__*/ e.createElement(ue, null, n) : n, /*#__PURE__*/ e.createElement(ee, l), r)
+};
+fe.defaultProps = {
+    title: "Choose a new password"
+};
+const he = ["view", "providers", "signupLink", "loginLink", "forgotLink", "backLink", "noAccount", "haveAccount"],
+    be = {
+        LOGIN: "login",
+        SIGNUP: "signup",
+        FORGOT_PASSWORD: "forgot_password",
+        UPDATE_PASSWORD: "update_password",
+        OTP: "otp"
+    },
+    ge = t => {
+        const {
+            view: n = be.LOGIN,
+            providers: r,
+            signupLink: l,
+            loginLink: o,
+            forgotLink: a,
+            backLink: i,
+            noAccount: s,
+            haveAccount: c
+        } = t, u = F(t, he), {
+            type: d
+        } = u, [m, p] = e.useState(n);
+        switch (e.useEffect(() => {
+            p(n)
+        }, [n]), m) {
+            case be.LOGIN:
+                /*#__PURE__*/ return e.createElement(de, W({
+                    providers: r,
+                    footer: /*#__PURE__*/ e.createElement(Le, {
+                        onClick: () => p(be.SIGNUP),
+                        label: s,
+                        link: l
+                    })
+                }, u), "password" === d && ("string" == typeof a ? /*#__PURE__*/ e.createElement(E, {
+                    fontSize: "md",
+                    color: "muted",
+                    float: "right",
+                    onClick: () => p(be.FORGOT_PASSWORD)
+                }, a) : a));
+            case be.SIGNUP:
+                /*#__PURE__*/ return e.createElement(me, W({
+                    providers: r,
+                    footer: /*#__PURE__*/ e.createElement(Le, {
+                        onClick: () => p(be.LOGIN),
+                        label: c,
+                        link: o
+                    })
+                }, u));
+            case be.FORGOT_PASSWORD:
+                /*#__PURE__*/ return e.createElement(Ee, W({
+                    footer: /*#__PURE__*/ e.createElement(Le, {
+                        onClick: () => p(be.LOGIN),
+                        link: i
+                    })
+                }, u));
+            case be.UPDATE_PASSWORD:
+                /*#__PURE__*/ return e.createElement(fe, u);
+            case be.OTP:
+                /*#__PURE__*/ return e.createElement(pe, u)
+        }
+        return null
+    },
+    Le = ({
+        label: t,
+        link: n,
+        onClick: r
+    }) => /*#__PURE__*/ e.createElement(d.div, {
+        __css: {
+            textAlign: "center",
+            py: 8,
+            fontSize: "md"
+        }
+    }, t && /*#__PURE__*/ e.createElement(d.span, {
+        color: "muted"
+    }, t), " ", "string" == typeof n ? /*#__PURE__*/ e.createElement(E, {
+        onClick: r
+    }, n) : n);
+ge.defaultProps = {
+    noAccount: "No account yet?",
+    haveAccount: "Already have an account?",
+    signupLink: "Sign up",
+    loginLink: "Log in",
+    forgotLink: "Forgot password?",
+    backLink: "Back to log in"
+};
+export {
+    ge as Auth, ie as AuthForm, se as AuthFormContainer, ce as AuthFormDivider, ue as AuthFormTitle, O as AuthProvider, Ee as ForgotPasswordView, R as LoginButton, de as LoginView, j as MagicLinkForm, q as MagicLinkSuccess, $ as OtpForm, pe as OtpView, B as PasswordForm, J as ProviderButton, M as Providers, me as SignupView, fe as UpdatePasswordView, be as VIEWS, x as useAuth, A as useCurrentUser, V as useLogin, I as useOtp, _ as useResetPassword, C as useSignUp, T as useUpdatePassword
+};
 //# sourceMappingURL=index.modern.js.map
\ No newline at end of file
diff --git a/node_modules/@saas-ui/auth/src/components/password-form.tsx b/node_modules/@saas-ui/auth/src/components/password-form.tsx
index 5cc0dbc..d9346cd 100644
--- a/node_modules/@saas-ui/auth/src/components/password-form.tsx
+++ b/node_modules/@saas-ui/auth/src/components/password-form.tsx
@@ -42,10 +42,10 @@ export const PasswordForm: React.FC<PasswordFormProps> = ({
   ),
   ...formProps
 }) => {
-  const [{ isLoading, isResolved, data }, submit] = useLogin({ action })
+  const [{ isLoading, isResolved, data, isRejected, error }, submit] = useLogin({ action })
 
   const handleSubmit = (params: SubmitParams) => {
-    return submit(params).then(onSuccess).catch(onError)
+    return submit(params)
   }
 
   // Show a default success message on signup.
@@ -53,6 +53,14 @@ export const PasswordForm: React.FC<PasswordFormProps> = ({
     return renderSuccess(data)
   }
 
+  React.useEffect(() => {
+    if(isRejected) {
+      onError(error);
+    } else if(isResolved) {
+      onSuccess(data);
+    }
+  }, [error, isRejected, isResolved, data])
+
   return (
     <Form
       schema={schema}
diff --git a/node_modules/@saas-ui/auth/src/provider.tsx b/node_modules/@saas-ui/auth/src/provider.tsx
index 5e924ac..9177f3b 100644
--- a/node_modules/@saas-ui/auth/src/provider.tsx
+++ b/node_modules/@saas-ui/auth/src/provider.tsx
@@ -191,9 +191,13 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({
 
   const logIn = useCallback(
     async (params: AuthParams, options?: AuthOptions) => {
-      const result = await onLogin(params, options)
-      checkAuth() // In case the auth service authenticates the user directly.
-      return result
+      try {
+        const result = await onLogin(params, options)
+        checkAuth() // In case the auth service authenticates the user directly.
+        return result
+      } catch (err) {
+        throw err
+      }
     },
     [onLogin]
   )

This issue body was partially generated by patch-package.

children on SubmitButton is always overruled by label

The Button component has shorthand prop 'label' which always takes precedence over the children prop.

This results in the SubmitButton always renders 'Submit' when using children.

<SubmitButton>Create post</SubmitButton>

Improve ListItem composition

The ListItem and ListItemLabel have a primary and secondary property to display a title and description, which are not consistent with other components and it's not directly clear what their purpose is.

Propose a better api for this.

<List>
  <ListItem>
  <ListItemIcon />
   <ListItemLabel>
     
   </ListItemLabel>
  <ListItemAction>
    <IconButton />
   </ListItemAction>
  </ListItem>
</List>

Type error for <StepForm /> children

So i am using the code at https://www.saas-ui.dev/docs/forms/step-form#access-stepper-state, vscode showing some typeDef errors but the code works fine.

Here is my base tsconfig:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Next.js",
  "extends": "./base.json",
  "compilerOptions": {
    "declaration": false,
    "declarationMap": false,
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "strictNullChecks": true,
    "useUnknownInCatchVariables": true
  },
  "include": ["src", "next-env.d.ts"],
  "exclude": ["node_modules"]
}

Below is the screenshot showing the error.
image

Typos in copy - 'build on' should be 'built on'

Hi, awesome work so far - looks great.

Noticed a few instances where the grammatically correct term would be 'built on' but the term used has been 'build on'.

For example, inside apps/website/src/pages/index.tsx, line 731:

Saas UI is build on top of Chakra UI

This same grammatical error can be seen in your footer. Best of luck with this project - I will be sure to give SaaS UI a try in the near future! ๐Ÿ‘

Screenshot 2022-07-05 at 11 12 28

Screenshot 2022-07-05 at 11 12 44

DataTable does not inherint TableOptions props

As the title says, the DataTable components have not inherited props from TableOptions such as columns, data according to vscode's typescript IntelliSense.
I copied example code from https://www.saas-ui.dev/docs/data-display/data-table#typescript
image

I thought it was because of types issues regarding columns, so I removed them but the error still persisted
image

Removing columns from DataTable now shows that prop data does not exist
image

Type error disappears after removing all props

image

React 18 & Chakra 2 support

I started implementing React 18 support which uses @chakra-ui/[email protected]

Code can be found in the next branch.

yarn add @saas-ui/[email protected]

Haven't run into much issues yet, other then incorrect types and some downstream dependencies aren't up to date yet.

Let me know if you run into any issues.

`id` should be passed to `FormControl` in the `Field` component

Right now if you pass an id prop to the Field component, the id is passed only to the Input, Select, etc component. Chakra is unaware of those so it generates its own id and htmlFor props for the FormLabel component. To ensure fields are fully accessible, the id prop should instead be passed to FormControl component so that Chakra uses the proper id and htmlFor attributes for the label, input, etc.

Example code below. I was unable to test this because I could not get the saas-ui project running locally (yarn install failed because I currently have not purchased saas ui pro).

// packages/saas-ui-forms/src/field.tsx

export const BaseField: React.FC<FieldProps> = (props) => {
  const { id, name, label, help, variant, hideLabel, children, ...controlProps } =
    props

  // ...

  return (
    <FormControl id={id} variant={variant} {...controlProps} isInvalid={!!error}>
      // ...
    </FormControl>
  )
}

const createField = (
  InputComponent: React.FC<any>,
  { displayName, hideLabel, BaseField }: CreateFieldProps
) => {
  const Field = forwardRef<FieldProps, typeof FormControl>((props, ref) => {
    const {
      id,
     // ...
    } = props

    return (
      <BaseField
        id={id}
        // ...
      >
        // ...
      </BaseField>
    )
  })

  // ...

  return Field
}

Simplify useModals api

Right now the only way to open custom modal components is by configuring them in the ModalsProvider.

The proposed new api would be by simply passing the component instead of a modal config directly in the open method.

const modals = useModals()

modals.open(CustomModal)

Separate auth logic from auth forms

The auth forms cannot be used standalone since they use the AuthProvider context internally. Extract this dependency so that the forms can be used in stand alone situations.

error with FormDialog AutoForm

When following the example at https://www.saas-ui.dev/docs/overlay/form-dialog#auto-form, i get the following error in my own implementation TypeError: Cannot read properties of undefined (reading 'map')

function App(){
  const disclosure = useDisclosure();
  const initialRef = useRef<HTMLInputElement | null>(null);
  const { mutateAsync, isLoading } = trpc.useMutation(['viewer.addChurch']);
  const toast = useSnackbar();

  const schema = yup.object().shape({
    name: yup.string().required().label('Name').min(3),
    // .meta({ ref: initialRef })
    location: yup.string().required().label('Location').min(3),
    abbreviatedName: yup.string().required().label('Abbreviation').min(3),
    description: yup.string().required().label('Mission').min(3),
    pastor: yup.string().required().label('Pastor').min(3),
  });

  const footer = (
    <ModalFooter>
      <Button
        label="Cancel"
        variant="ghost"
        mr={3}
        onClick={disclosure.onClose}
      />
      <SubmitButton
        disableIfInvalid
        disableIfUntouched
        isLoading={isLoading}
        label="Submit"
        colorScheme={'blue'}
      />
    </ModalFooter>
  );

  return (
    <>
      <Button onClick={() => disclosure.onOpen()} {...trigger} />

      <FormDialog
        title="New Chruch"
        {...disclosure}
        resolver={yupResolver(schema)}
        onSubmit={async (data: any) => {
          console.log({data})
        }}
        footer={footer}
        initialFocusRef={initialRef}
      />
    </>
  );

}

Auth component throw error

I am using Auth component in nextjs.
Provider is setting with a supabase client.

<SaasProvider theme={theme} {...createAuthService(supabase)}>
    <AuthProvider>
        <Component {...pageProps} />
    </AuthProvider>
  </SaasProvider>

I use Auth component with a github provider which is support in supabase.

<Auth
    providers={{
      google: {
          name: 'GitHub',
          icon: FaGithub
        }
      }}
      type="password"
 />

this error is thrown

Unhandled Runtime Error
TypeError: Cannot destructure property 'logIn' of 'x(...)' as it is null.

Call Stack
M
node_modules/.pnpm/@saas-ui+auth@0.6.1_ae4b258d679467cd3105b6a0b1e43c4d/node_modules/@saas-ui/auth/dist/index.modern.js (365:0)
renderWithHooks

I can only render component by removing providers props. But once I login with password.
TypeError: Cannot read properties of null (reading 'logIn')

Call Stack
eval
node_modules/.pnpm/@[email protected]_ae4b258d679467cd3105b6a0b1e43c4d/node_modules/@saas-ui/auth/dist/index.modern.js (111:0)
eval
node_modules/.pnpm/@saas-ui[email protected][email protected]/node_modules/@saas-ui/hooks/dist/index.modern.js (1:261)
onSubmit
node_modules/.pnpm/@[email protected]_ae4b258d679467cd3105b6a0b1e43c4d/node_modules/@saas-ui/auth/dist/index.modern.js (270:0)
eval

this error is thrown

Feature: Magic Link

I saw auth as something being added in the future (or is in the paid option; i don't have access so don't know)

https://magic.link/ is super cool + super affordable, especially for early stage startups. I'm using in production and have a really positive experience with it. Just thought it was worth mentioning ๐Ÿ™‚

Fix peerDependencies

Some packages don't have the correct peerDependencies, resulting in yarn showing warnings.

โžค YN0002: โ”‚ @saas-ui/auth@workspace:packages/saas-ui-auth doesn't provide yup (pf4fb4), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/auth@workspace:packages/saas-ui-auth [79818] doesn't provide yup (pb9f06), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/auth@workspace:packages/saas-ui-auth [92726] doesn't provide yup (p4d960), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/auth@workspace:packages/saas-ui-auth [b9efc] doesn't provide yup (pd850d), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/data-table@workspace:packages/saas-ui-data-table [79818] doesn't provide @chakra-ui/system (p36039), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/data-table@workspace:packages/saas-ui-data-table [b9efc] doesn't provide @chakra-ui/system (pf4dda), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/hotkeys@workspace:packages/saas-ui-hotkeys doesn't provide @chakra-ui/react (p79500), requested by @saas-ui/search-input
โžค YN0002: โ”‚ @saas-ui/hotkeys@workspace:packages/saas-ui-hotkeys [79818] doesn't provide @chakra-ui/react (pa46ac), requested by @saas-ui/search-input
โžค YN0002: โ”‚ @saas-ui/hotkeys@workspace:packages/saas-ui-hotkeys [92726] doesn't provide @chakra-ui/react (p1bd71), requested by @saas-ui/search-input
โžค YN0002: โ”‚ @saas-ui/hotkeys@workspace:packages/saas-ui-hotkeys [b9efc] doesn't provide @chakra-ui/react (p542e5), requested by @saas-ui/search-input
โžค YN0002: โ”‚ @saas-ui/layout@workspace:packages/saas-ui-layout doesn't provide @chakra-ui/system (p59f41), requested by @saas-ui/provider
โžค YN0002: โ”‚ @saas-ui/layout@workspace:packages/saas-ui-layout [d6baa] doesn't provide @chakra-ui/system (p19449), requested by @saas-ui/provider
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals doesn't provide @chakra-ui/system (p4c026), requested by @saas-ui/button
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals doesn't provide @chakra-ui/system (p10bdc), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals doesn't provide yup (p23bc0), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals [79818] doesn't provide yup (pa132b), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals [92726] doesn't provide @chakra-ui/system (p0e6e8), requested by @saas-ui/button
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals [92726] doesn't provide @chakra-ui/system (p1bcfb), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals [92726] doesn't provide yup (pbca64), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/modals@workspace:packages/saas-ui-modals [b9efc] doesn't provide yup (pcc048), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide @emotion/react (p1ea87), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide @emotion/styled (p72e24), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide framer-motion (pdb284), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide react (p466ef), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide react-dom (pe693c), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/props-docs@workspace:tooling/props-docs doesn't provide typescript (p9bfaa), requested by react-docgen-typescript
โžค YN0002: โ”‚ @saas-ui/react@workspace:packages/saas-ui-react doesn't provide yup (p41862), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/react@workspace:packages/saas-ui-react [c0f88] doesn't provide yup (p82484), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/react@workspace:packages/saas-ui-react [ed598] doesn't provide yup (pe507a), requested by @saas-ui/forms
โžค YN0002: โ”‚ @saas-ui/search-input@workspace:packages/saas-ui-search-input [4fbbd] doesn't provide @chakra-ui/system (paee19), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/search-input@workspace:packages/saas-ui-search-input [79818] doesn't provide @chakra-ui/system (pc8d67), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/search-input@workspace:packages/saas-ui-search-input [b9efc] doesn't provide @chakra-ui/system (p1402c), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/search-input@workspace:packages/saas-ui-search-input [d7d93] doesn't provide @chakra-ui/system (p54b88), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/select@workspace:packages/saas-ui-select [79818] doesn't provide @chakra-ui/system (p8065a), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/select@workspace:packages/saas-ui-select [b9efc] doesn't provide @chakra-ui/system (p2bd5d), requested by @chakra-ui/icons
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @chakra-ui/system (p651f2), requested by @saas-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @emotion/react (p39859), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @emotion/styled (pfe45e), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @storybook/addons (pb2bd6), requested by @storybook/testing-react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @storybook/client-api (pbfb5d), requested by @storybook/testing-react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @storybook/preview-web (p5c218), requested by @storybook/testing-react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @storybook/react (pa4b9e), requested by @storybook/testing-react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide @testing-library/dom (p8d13e), requested by @testing-library/user-event
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide framer-motion (p325de), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide framer-motion (pa9c70), requested by @saas-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide react-dom (p1e4de), requested by @chakra-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide react-dom (p274bf), requested by @saas-ui/react
โžค YN0002: โ”‚ @saas-ui/test-utils@workspace:tooling/test-utils doesn't provide react-dom (p82c10), requested by @testing-library/react
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme doesn't provide @chakra-ui/system (p7f6df), requested by @saas-ui/palette
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme doesn't provide @chakra-ui/system (p285be), requested by @saas-ui/system
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme [79818] doesn't provide @chakra-ui/system (p73c34), requested by @saas-ui/palette
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme [b6806] doesn't provide @chakra-ui/system (paffd4), requested by @saas-ui/palette
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme [b6806] doesn't provide @chakra-ui/system (p4911a), requested by @saas-ui/system
โžค YN0002: โ”‚ @saas-ui/theme@workspace:packages/saas-ui-theme [b9efc] doesn't provide @chakra-ui/system (pbd5c2), requested by @saas-ui/palette
โžค YN0002: โ”‚ palette-docs@workspace:apps/palette doesn't provide @chakra-ui/system (p19e4a), requested by @saas-ui/palette
โžค YN0002: โ”‚ palette-docs@workspace:apps/palette doesn't provide @chakra-ui/system (p8c43d), requested by @saas-ui/react
โžค YN0060: โ”‚ palette-docs@workspace:apps/palette provides framer-motion (p76887) with version 4.1.17, which doesn't satisfy what @saas-ui/react and some of its descendants request
โžค YN0002: โ”‚ react-dev-utils@npm:11.0.4 doesn't provide typescript (p79ddf), requested by fork-ts-checker-webpack-plugin
โžค YN0002: โ”‚ react-dev-utils@npm:11.0.4 doesn't provide webpack (p2af19), requested by fork-ts-checker-webpack-plugin
โžค YN0002: โ”‚ saas-ui@workspace:. doesn't provide @chakra-ui/system (p734e8), requested by @chakra-ui/icons
โžค YN0002: โ”‚ saas-ui@workspace:. doesn't provide @storybook/addons (p1b171), requested by @storybook/testing-react
โžค YN0002: โ”‚ saas-ui@workspace:. doesn't provide @storybook/client-api (p41d2f), requested by @storybook/testing-react
โžค YN0002: โ”‚ saas-ui@workspace:. doesn't provide @storybook/preview-web (p5b73e), requested by @storybook/testing-react
โžค YN0002: โ”‚ saas-ui@workspace:. doesn't provide @typescript-eslint/parser (p0c8ae), requested by @typescript-eslint/eslint-plugin
โžค YN0002: โ”‚ storybook-addon-performance@npm:0.16.1 [1cf47] doesn't provide react-is (p98f8e), requested by styled-components
โžค YN0060: โ”‚ website@workspace:apps/website provides react (p7a5f5) with version 17.0.2, which doesn't satisfy what react-live and some of its descendants request
โžค YN0060: โ”‚ website@workspace:apps/website provides react-dom (p48215) with version 17.0.2, which doesn't satisfy what react-live and some of its descendants request
โžค YN0000: โ”‚ Some peer dependencies are incorrectly met; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code

Theme inconsistencies

There are a couple of theme inconsistencies, not all components using the same color scale.

The focus ring is still visible with mouse navigation for some components.

Cannot find module '@saas-ui/forms/zod' or its corresponding type declarations

After upgrading to version 1.0.1 from 1.0.0-rc.15, I'm no longer able to import zodFieldResolver, zodResolver from @saas-ui/forms/zod.
This is how i was using it

// BaseForm.tsx
import { zodFieldResolver, zodResolver } from "@saas-ui/forms/zod";
import { Form as BaseForm } from "@saas-ui/react";
import { ZodTypeAny } from "zod";

BaseForm.getResolver = (schema: ZodTypeAny) => zodResolver(schema); // @hookform/resolvers
BaseForm.getFieldResolver = (schema: ZodTypeAny) => zodFieldResolver(schema); // AutoForm field resolver

export default BaseForm;

UPDATE: this issue always happens when I upgrade @saas-ui/react to the latest released version. Even if I revert back to the previous version after that, the problem still persists. So I delete node_modules and yarn.lock then I do a fresh installation of packages inside package.json

Write tests

Tests for all packages

  • Test a11y in all packages.
  • auth
  • banner
  • button
  • card
  • collapse
  • data-table
  • forms
  • hooks
  • hotkeys
  • input-right-button
  • layout
  • list
  • context-menu (menu package)
  • modals
  • nprogress
  • number-input
  • palette
  • password-input
  • persona
  • pin-input
  • property
  • provider
  • radio
  • search-input
  • select
  • snackbar
  • web3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.