@sikka/hawa 0.0.13 → 0.0.16

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.
Files changed (42) hide show
  1. package/es/index.es.js +1 -1
  2. package/lib/index.js +1 -1
  3. package/package.json +1 -1
  4. package/src/blocks/Account/UserProfileForm.js +79 -43
  5. package/src/blocks/AuthForms/NewPasswordForm.js +57 -38
  6. package/src/blocks/AuthForms/ResetPasswordForm.js +36 -39
  7. package/src/blocks/AuthForms/SignInForm.js +76 -59
  8. package/src/blocks/AuthForms/SignUpForm.js +65 -44
  9. package/src/blocks/Payment/ChargeWalletForm.js +29 -20
  10. package/src/blocks/Pricing/PricingPlans.js +57 -0
  11. package/src/elements/HawaAlert.js +1 -1
  12. package/src/elements/HawaAppBar.js +139 -0
  13. package/src/elements/HawaListItem.js +21 -0
  14. package/src/elements/HawaPricingCard.js +133 -0
  15. package/src/elements/HawaRadio.js +1 -3
  16. package/src/elements/HawaTextField.js +15 -149
  17. package/src/elements/index.js +3 -1
  18. package/src/layout/HawaAppLayout.js +246 -0
  19. package/src/layout/index.js +1 -0
  20. package/src/stories/BlocksStories/Account/UserProfile.stories.js +25 -1
  21. package/src/stories/BlocksStories/Auth/NewPassword.stories.js +2 -1
  22. package/src/stories/BlocksStories/Auth/ResetPassword.stories.js +1 -2
  23. package/src/stories/BlocksStories/Auth/SignIn.stories.js +9 -1
  24. package/src/stories/BlocksStories/Auth/SignUp.stories.js +8 -0
  25. package/src/stories/BlocksStories/Payment/ChargeWallet.stories.js +6 -1
  26. package/src/stories/BlocksStories/Pricing/BillingPlans.stories.js +63 -0
  27. package/src/stories/BlocksStories/Pricing/LandingPlans.stories.js +63 -0
  28. package/src/stories/ElementsStories/PricingCard.stories.js +76 -12
  29. package/src/stories/LayoutStories/AppBar.stories.js +29 -0
  30. package/src/stories/LayoutStories/AppLayout.stories.js +52 -0
  31. package/src/styles.css +1 -0
  32. package/storybook-static/iframe.html +1 -1
  33. package/storybook-static/index.html +1 -1
  34. package/storybook-static/main.66955578.iframe.bundle.js +1 -0
  35. package/storybook-static/vendors~main.b4186832.iframe.bundle.js +76 -0
  36. package/storybook-static/{vendors~main.5eab66d3.iframe.bundle.js.LICENSE.txt → vendors~main.b4186832.iframe.bundle.js.LICENSE.txt} +0 -0
  37. package/storybook-static/vendors~main.b4186832.iframe.bundle.js.map +1 -0
  38. package/src/blocks/Pricing/SignInForm.js +0 -126
  39. package/src/elements/HawaCard.js +0 -77
  40. package/storybook-static/main.00b064cb.iframe.bundle.js +0 -1
  41. package/storybook-static/vendors~main.5eab66d3.iframe.bundle.js +0 -76
  42. package/storybook-static/vendors~main.5eab66d3.iframe.bundle.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import React from "react";
1
+ import React, { useState } from "react";
2
2
  import { HawaTextField, HawaLogoButton } from "../../elements";
3
- import { FormProvider, useForm } from "react-hook-form";
3
+ import { Controller, FormProvider, useForm } from "react-hook-form";
4
4
  import InputAdornment from "@mui/material/InputAdornment";
5
5
  import EmailIcon from "@mui/icons-material/MailOutline";
6
6
  import PasswordIcon from "@mui/icons-material/HttpsOutlined";
@@ -14,74 +14,91 @@ export const SignInForm = (props) => {
14
14
  const methods = useForm();
15
15
  const {
16
16
  formState: { errors },
17
- handleSubmit
17
+ handleSubmit,
18
+ register,
19
+ control
18
20
  } = methods;
19
21
 
20
22
  return (
21
- <Container maxWidth="xs" variant="auth">
23
+ <Container
24
+ maxWidth="xs"
25
+ variant="auth"
26
+ style={{ direction: props.lang === "ar" ? "rtl" : "ltr" }}
27
+ >
22
28
  {props.error && (
23
29
  <Alert severity="error">
24
30
  {props.errorTitle && <AlertTitle>{props.errorTitle}</AlertTitle>}
25
31
  {props.errorText}
26
32
  </Alert>
27
33
  )}
28
- <FormProvider {...methods}>
29
- <form onSubmit={handleSubmit(props.handleSignIn)}>
30
- <HawaTextField
31
- fullWidth
32
- type="text"
33
- name="email"
34
- label={props.texts.emailLabel}
35
- placeholder={props.texts.emailPlaceholder}
36
- startAdornment={
37
- <InputAdornment position="start">
38
- <EmailIcon />
39
- </InputAdornment>
40
- }
41
- rules={{
42
- required: props.texts.emailRequired,
43
- pattern: {
44
- value:
45
- /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
46
- message: props.texts.emailInvalidText
34
+ <form onSubmit={handleSubmit(props.handleSignIn)}>
35
+ <Controller
36
+ control={control}
37
+ name="email"
38
+ render={({ field }) => (
39
+ <HawaTextField
40
+ fullWidth
41
+ type="text"
42
+ value={field.value ?? ""}
43
+ label={props.texts.emailLabel}
44
+ helperText={errors.email?.message}
45
+ placeholder={props.texts.emailPlaceholder}
46
+ startAdornment={
47
+ <InputAdornment position="start">
48
+ <EmailIcon />
49
+ </InputAdornment>
47
50
  }
48
- }}
49
- helperText={errors.email?.message}
50
- />
51
-
52
- <HawaTextField
53
- fullWidth
54
- name="password"
55
- placeholder={props.texts.passwordPlaceholder}
56
- type="password"
57
- label={props.texts.passwordLabel}
58
- startAdornment={
59
- <InputAdornment position="start">
60
- <PasswordIcon />
61
- </InputAdornment>
51
+ {...field}
52
+ />
53
+ )}
54
+ rules={{
55
+ required: props.texts.emailRequiredText,
56
+ pattern: {
57
+ value:
58
+ /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
59
+ message: props.texts.emailInvalidText
62
60
  }
63
- rules={{
64
- required: props.texts.passwordRequired
65
- }}
66
- helperText={errors.password?.message}
67
- />
68
- <Typography
69
- style={{
70
- cursor: "pointer",
71
- marginTop: 5,
72
- width: "max-content",
73
- fontSize: 15,
74
- padding: 5
75
- }}
76
- onClick={props.handleForgotPassword}
77
- >
78
- {props.texts.forgotPasswordText}
79
- </Typography>
80
- <Button type="submit" fullWidth variant="last">
81
- {props.texts.signInText}
82
- </Button>
83
- </form>
84
- </FormProvider>
61
+ }}
62
+ />
63
+
64
+ <Controller
65
+ control={control}
66
+ name="password"
67
+ render={({ field }) => (
68
+ <HawaTextField
69
+ fullWidth
70
+ type="password"
71
+ defaultValue={field.value ?? ""}
72
+ value={field.value ?? ""}
73
+ label={props.texts.passwordLabel}
74
+ placeholder={props.texts.passwordPlaceholder}
75
+ helperText={errors.password?.message}
76
+ startAdornment={
77
+ <InputAdornment position="start">
78
+ <PasswordIcon />
79
+ </InputAdornment>
80
+ }
81
+ {...field}
82
+ />
83
+ )}
84
+ rules={{ required: props.texts.passwordRequiredText }}
85
+ />
86
+ <Typography
87
+ style={{
88
+ cursor: "pointer",
89
+ marginTop: 5,
90
+ width: "max-content",
91
+ fontSize: 15,
92
+ padding: 5
93
+ }}
94
+ onClick={props.handleForgotPassword}
95
+ >
96
+ {props.texts.forgotPasswordText}
97
+ </Typography>
98
+ <Button type="submit" fullWidth variant="last">
99
+ {props.texts.signInText}
100
+ </Button>
101
+ </form>
85
102
  <Typography
86
103
  variant="subtitle2"
87
104
  style={{ marginTop: 5, textAlign: "center", padding: 5 }}
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { HawaTextField, HawaLogoButton } from "../../elements";
3
3
  import PropTypes from "prop-types";
4
- import { FormProvider, useForm } from "react-hook-form";
4
+ import { Controller, FormProvider, useForm } from "react-hook-form";
5
5
  import PersonIcon from "@mui/icons-material/PermIdentityOutlined";
6
6
  import InputAdornment from "@mui/material/InputAdornment";
7
7
  import EmailIcon from "@mui/icons-material/MailOutline";
@@ -16,11 +16,16 @@ export const SignUpForm = (props) => {
16
16
  const methods = useForm();
17
17
  const {
18
18
  formState: { errors },
19
- handleSubmit
19
+ handleSubmit,
20
+ control
20
21
  } = methods;
21
22
 
22
23
  return (
23
- <Container maxWidth="xs" variant="auth">
24
+ <Container
25
+ maxWidth="xs"
26
+ variant="auth"
27
+ style={{ direction: props.lang === "ar" ? "rtl" : "ltr" }}
28
+ >
24
29
  {props.error && (
25
30
  <Alert severity="error">
26
31
  {props.errorTitle && <AlertTitle>{props.errorTitle}</AlertTitle>}
@@ -32,32 +37,47 @@ export const SignUpForm = (props) => {
32
37
  )} */}
33
38
  <FormProvider {...methods}>
34
39
  <form onSubmit={handleSubmit(props.handleSignUp)}>
35
- <HawaTextField
36
- fullWidth
37
- type="text"
38
- label={props.texts.fullNameLabel}
40
+ <Controller
41
+ control={control}
39
42
  name="fullName"
40
- placeholder={props.texts.fullNamePlaceholder}
41
- inputLabel={props.texts.fullNameLabel}
42
- startAdornment={
43
- <InputAdornment position="start">
44
- <PersonIcon />
45
- </InputAdornment>
46
- }
47
- helperText={errors.fullName?.message}
43
+ render={({ field }) => (
44
+ <HawaTextField
45
+ fullWidth
46
+ type="text"
47
+ value={field.value ?? ""}
48
+ label={props.texts.fullNameLabel}
49
+ placeholder={props.texts.fullNamePlaceholder}
50
+ helperText={errors.fullName?.message}
51
+ startAdornment={
52
+ <InputAdornment position="start">
53
+ <PersonIcon />
54
+ </InputAdornment>
55
+ }
56
+ />
57
+ )}
58
+ rules={{
59
+ required: props.texts.fullNameRequiredText
60
+ }}
48
61
  />
49
62
 
50
- <HawaTextField
51
- fullWidth
52
- type="text"
53
- label={props.texts.emailLabel}
54
- placeholder={props.texts.emailPlaceholder}
63
+ <Controller
64
+ control={control}
55
65
  name="email"
56
- startAdornment={
57
- <InputAdornment position="start">
58
- <EmailIcon />
59
- </InputAdornment>
60
- }
66
+ render={({ field }) => (
67
+ <HawaTextField
68
+ fullWidth
69
+ type="text"
70
+ value={field.value ?? ""}
71
+ label={props.texts.emailLabel}
72
+ helperText={errors.email?.message}
73
+ placeholder={props.texts.emailPlaceholder}
74
+ startAdornment={
75
+ <InputAdornment position="start">
76
+ <EmailIcon />
77
+ </InputAdornment>
78
+ }
79
+ />
80
+ )}
61
81
  rules={{
62
82
  required: props.texts.emailRequiredText,
63
83
  pattern: {
@@ -66,27 +86,28 @@ export const SignUpForm = (props) => {
66
86
  message: props.texts.emailInvalidText
67
87
  }
68
88
  }}
69
- helperText={errors.email?.message}
70
89
  />
71
- <HawaTextField
72
- fullWidth
90
+ <Controller
91
+ control={control}
73
92
  name="password"
74
- placeholder={props.texts.passwordPlaceholder}
75
- type="password"
76
- label={props.texts.passwordLabel}
77
- startAdornment={
78
- <InputAdornment position="start">
79
- <PasswordIcon />
80
- </InputAdornment>
81
- }
82
- rules={{
83
- required: props.texts.passwordRequiredText,
84
- minLength: {
85
- value: 8,
86
- message: props.texts.passwordTooShortText
87
- }
88
- }}
89
- helperText={errors.password?.message}
93
+ render={({ field }) => (
94
+ <HawaTextField
95
+ fullWidth
96
+ type="password"
97
+ defaultValue={field.value ?? ""}
98
+ value={field.value ?? ""}
99
+ label={props.texts.passwordLabel}
100
+ placeholder={props.texts.passwordPlaceholder}
101
+ helperText={errors.password?.message}
102
+ startAdornment={
103
+ <InputAdornment position="start">
104
+ <PasswordIcon />
105
+ </InputAdornment>
106
+ }
107
+ {...field}
108
+ />
109
+ )}
110
+ rules={{ required: props.texts.passwordRequiredText }}
90
111
  />
91
112
 
92
113
  <Button fullWidth variant="last" type="submit">
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import { HawaTextField } from "../../elements";
3
- import { FormProvider, useForm } from "react-hook-form";
3
+ import { Controller, FormProvider, useForm } from "react-hook-form";
4
4
  import Container from "@mui/material/Container";
5
5
  import Button from "@mui/material/Button";
6
6
  import Typography from "@mui/material/Typography";
@@ -10,34 +10,43 @@ export const ChargeWalletForm = (props) => {
10
10
  const methods = useForm();
11
11
  const {
12
12
  formState: { errors },
13
- handleSubmit
13
+ handleSubmit,
14
+ control
14
15
  } = methods;
15
16
 
16
17
  return (
17
18
  <Container maxWidth="xs">
18
- <Typography align="center" variant="h1">
19
+ <Typography align="center" variant="h2" fontWeight={500}>
19
20
  {Number(walletAmount).toLocaleString("en") || "0"}
20
21
  <Typography>{props.currency || "SAR"}</Typography>
21
22
  </Typography>
22
23
  <FormProvider {...methods}>
23
- <form
24
- onChange={(e) => {
25
- e.preventDefault();
26
- setWalletAmount(methods.getValues().amount);
27
- }}
28
- style={{ marginTop: 10 }}
29
- onSubmit={handleSubmit(props.handleChargeWallet)}
30
- >
31
- <HawaTextField
32
- fullWidth
24
+ <form onSubmit={handleSubmit(props.handleChargeWallet)}>
25
+ <Controller
26
+ control={control}
33
27
  name="amount"
34
- placeholder="Enter amount"
35
- type="number"
36
- value={walletAmount}
37
- rules={{
38
- required: "Password is rquired"
39
- }}
40
- helperText={errors.amount?.message}
28
+ render={({ field }) => (
29
+ <HawaTextField
30
+ fullWidth
31
+ placeholder="Enter amount"
32
+ type="number"
33
+ value={field.value ?? ""}
34
+ // helperText={errors.amount?.message}
35
+ {...field}
36
+ inputProps={{
37
+ inputMode: "numeric",
38
+ min: "0",
39
+ max: "9999999",
40
+ step: "0.01"
41
+ }}
42
+ onChange={(e) => {
43
+ // e.preventDefault();
44
+ field.onChange(parseFloat(e.target.value));
45
+ console.log("e", e.target.value);
46
+ setWalletAmount(e.target.value);
47
+ }}
48
+ />
49
+ )}
41
50
  />
42
51
 
43
52
  <Button
@@ -0,0 +1,57 @@
1
+ import React, { useState } from "react";
2
+ import Container from "@mui/material/Container";
3
+ import { HawaPricingCard, HawaRadio } from "../../elements";
4
+
5
+ export const PricingPlans = (props) => {
6
+ const [currentCurrency, setCurrentCurrency] = useState("sar");
7
+ const [currentCycle, setCurrentCycle] = useState("monthly");
8
+ return (
9
+ <Container style={{ width: "fit-content" }} variant="plain">
10
+ <div
11
+ style={{
12
+ display: "flex",
13
+ flexDirection: "row",
14
+ justifyContent: "space-between",
15
+ marginBottom: 10
16
+ }}
17
+ >
18
+ <HawaRadio
19
+ location="inPricing"
20
+ handleChange={(e) => setCurrentCycle(e)}
21
+ defaultValue="monthly"
22
+ options={[
23
+ { label: `Monthly`, value: `monthly` },
24
+ { label: `3 Months`, value: `3-months` },
25
+ { label: `6 Months`, value: `6-months` },
26
+ { label: `Annually`, value: `annually` }
27
+ ]}
28
+ />
29
+
30
+ <HawaRadio
31
+ location="inPricing"
32
+ handleChange={(e) => {
33
+ setCurrentCurrency(e);
34
+ }}
35
+ defaultValue="sar"
36
+ options={[
37
+ { label: `USD`, value: `usd` },
38
+ { label: `SAR`, value: `sar` }
39
+ ]}
40
+ />
41
+ </div>
42
+
43
+ <Container variant="pricing">
44
+ {props.plans.map((plan) => {
45
+ return (
46
+ <HawaPricingCard
47
+ lang={props.lang}
48
+ {...plan}
49
+ currency={currentCurrency}
50
+ cycleText={currentCycle}
51
+ />
52
+ );
53
+ })}
54
+ </Container>
55
+ </Container>
56
+ );
57
+ };
@@ -27,7 +27,7 @@ export const HawaAlert = (props) => {
27
27
  // });
28
28
 
29
29
  return (
30
- <Alert>
30
+ <Alert {...props}>
31
31
  {props.title && <AlertTitle>{props.title}</AlertTitle>}
32
32
  {props.text}
33
33
  </Alert>
@@ -0,0 +1,139 @@
1
+ import React from "react";
2
+ import AppBar from "@mui/material/AppBar";
3
+ import Box from "@mui/material/Box";
4
+ import Toolbar from "@mui/material/Toolbar";
5
+ import IconButton from "@mui/material/IconButton";
6
+ import Typography from "@mui/material/Typography";
7
+ import Menu from "@mui/material/Menu";
8
+ import MenuIcon from "@mui/icons-material/Menu";
9
+ import Container from "@mui/material/Container";
10
+ import Avatar from "@mui/material/Avatar";
11
+ import Button from "@mui/material/Button";
12
+ import Tooltip from "@mui/material/Tooltip";
13
+ import MenuItem from "@mui/material/MenuItem";
14
+
15
+ const pages = ["Products", "Pricing", "Blog"];
16
+ const settings = ["Profile", "Account", "Dashboard", "Logout"];
17
+
18
+ export const HawaAppBar = (props) => {
19
+ const [anchorElNav, setAnchorElNav] = React.useState(null);
20
+ const [anchorElUser, setAnchorElUser] = React.useState(null);
21
+
22
+ const handleOpenNavMenu = (event) => {
23
+ setAnchorElNav(event.currentTarget);
24
+ };
25
+ const handleOpenUserMenu = (event) => {
26
+ setAnchorElUser(event.currentTarget);
27
+ };
28
+
29
+ const handleCloseNavMenu = () => {
30
+ setAnchorElNav(null);
31
+ };
32
+
33
+ const handleCloseUserMenu = () => {
34
+ setAnchorElUser(null);
35
+ };
36
+
37
+ return (
38
+ <AppBar position="static">
39
+ <Container maxWidth="xl" variant="appbar">
40
+ <Toolbar disableGutters>
41
+ <Typography
42
+ variant="h6"
43
+ noWrap
44
+ component="div"
45
+ sx={{ mr: 2, display: { xs: "none", md: "flex" } }}
46
+ >
47
+ LOGO
48
+ </Typography>
49
+
50
+ <Box sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}>
51
+ <IconButton
52
+ size="large"
53
+ aria-label="account of current user"
54
+ aria-controls="menu-appbar"
55
+ aria-haspopup="true"
56
+ onClick={props.handleOpenSideMenu}
57
+ color="inherit"
58
+ >
59
+ <MenuIcon />
60
+ </IconButton>
61
+ <Menu
62
+ id="menu-appbar"
63
+ anchorEl={anchorElNav}
64
+ anchorOrigin={{
65
+ vertical: "bottom",
66
+ horizontal: "left"
67
+ }}
68
+ keepMounted
69
+ transformOrigin={{
70
+ vertical: "top",
71
+ horizontal: "left"
72
+ }}
73
+ open={Boolean(anchorElNav)}
74
+ onClose={handleCloseNavMenu}
75
+ sx={{
76
+ display: { xs: "block", md: "none" }
77
+ }}
78
+ >
79
+ {pages.map((page) => (
80
+ <MenuItem key={page} onClick={handleCloseNavMenu}>
81
+ <Typography textAlign="center">{page}</Typography>
82
+ </MenuItem>
83
+ ))}
84
+ </Menu>
85
+ </Box>
86
+ <Typography
87
+ variant="h6"
88
+ noWrap
89
+ component="div"
90
+ sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
91
+ >
92
+ LOGO
93
+ </Typography>
94
+ <Box sx={{ flexGrow: 1, display: { xs: "none", md: "flex" } }}>
95
+ {pages.map((page) => (
96
+ <Button
97
+ key={page}
98
+ onClick={handleCloseNavMenu}
99
+ sx={{ my: 2, color: "white", display: "block" }}
100
+ >
101
+ {page}
102
+ </Button>
103
+ ))}
104
+ </Box>
105
+
106
+ <Box sx={{ flexGrow: 0 }}>
107
+ <Tooltip title="Open settings">
108
+ <IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
109
+ <Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
110
+ </IconButton>
111
+ </Tooltip>
112
+ <Menu
113
+ sx={{ mt: "45px" }}
114
+ id="menu-appbar"
115
+ anchorEl={anchorElUser}
116
+ anchorOrigin={{
117
+ vertical: "top",
118
+ horizontal: "right"
119
+ }}
120
+ keepMounted
121
+ transformOrigin={{
122
+ vertical: "top",
123
+ horizontal: "right"
124
+ }}
125
+ open={Boolean(anchorElUser)}
126
+ onClose={handleCloseUserMenu}
127
+ >
128
+ {settings.map((setting) => (
129
+ <MenuItem key={setting} onClick={handleCloseUserMenu}>
130
+ <Typography textAlign="center">{setting}</Typography>
131
+ </MenuItem>
132
+ ))}
133
+ </Menu>
134
+ </Box>
135
+ </Toolbar>
136
+ </Container>
137
+ </AppBar>
138
+ );
139
+ };
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { ListItemButton, ListItemText } from "@mui/material";
3
+ import InboxIcon from "@mui/icons-material/MoveToInbox";
4
+
5
+ export const HawaListItem = (props) => {
6
+ return (
7
+ <ListItemButton
8
+ variant={props.selected && "clicked"}
9
+ key={props.text}
10
+ sx={{
11
+ minHeight: 48,
12
+ justifyContent: props.open ? "initial" : "center",
13
+ px: 2.5
14
+ }}
15
+ >
16
+ <InboxIcon />
17
+ <div style={{ width: 20 }} />
18
+ <ListItemText primary={props.text} sx={{ opacity: props.open ? 1 : 0 }} />
19
+ </ListItemButton>
20
+ );
21
+ };