@sikka/hawa 0.1.8 → 0.1.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sikka/hawa",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "SaaS Oriented UI Kit",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.es.js",
@@ -1,16 +1,16 @@
1
1
  import React, { FC } from "react"
2
+ import { Controller, useForm } from "react-hook-form"
3
+ import clsx from "clsx"
4
+
2
5
  import {
3
6
  HawaTextField,
4
- HawaLogoButton,
5
7
  HawaAlert,
6
8
  HawaPhoneInput,
9
+ InterfaceSettings,
7
10
  } from "../../elements"
8
- import { Controller, useForm } from "react-hook-form"
11
+ import { Card, CardContent, CardFooter } from "../../elements/Card"
9
12
  import { Button } from "../../elements/Button"
10
- import { FaGithub, FaGoogle } from "react-icons/fa"
11
- import { Card, CardContent, CardFooter, CardHeader } from "../../elements/Card"
12
13
  import { Icons } from "../../elements/Icons"
13
- import clsx from "clsx"
14
14
 
15
15
  export const SignInForm: FC<SignInFormTypes> = (props) => {
16
16
  const {
@@ -20,165 +20,189 @@ export const SignInForm: FC<SignInFormTypes> = (props) => {
20
20
  } = useForm()
21
21
 
22
22
  return (
23
- <Card dir={props.direction}>
24
- <CardContent headless>
25
- <form onSubmit={handleSubmit((e) => props.handleSignIn(e))}>
26
- {props.showError && (
23
+ <div>
24
+ <Card dir={props.direction}>
25
+ <CardContent headless>
26
+ <form onSubmit={handleSubmit((e) => props.handleSignIn(e))}>
27
+ {/* an attempt to animate the alert showing */}
28
+ {/* <div
29
+ className={clsx(
30
+ "h-0 overflow-clip bg-blue-500 transition-all",
31
+ props.showError ? "h-auto" : ""
32
+ )}
33
+ >
27
34
  <HawaAlert
28
35
  title={props.errorTitle}
29
36
  text={props.errorText}
30
37
  severity="error"
31
38
  />
32
- )}
33
- {props.signInType === "email" ? (
34
- <Controller
35
- control={control}
36
- name="email"
37
- render={({ field }) => (
38
- <HawaTextField
39
- width="full"
40
- type="text"
41
- autoComplete="email"
42
- label={props.texts.emailLabel}
43
- helpertext={errors.email?.message}
44
- placeholder={props.texts.emailPlaceholder}
45
- value={field.value ?? ""}
46
- onChange={field.onChange}
47
- />
48
- )}
49
- rules={{
50
- required: props.texts.emailRequiredText,
51
- pattern: {
52
- value:
53
- /^(([^<>()[\]\\.,;:\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,}))$/,
54
- message: props.texts.emailInvalidText,
55
- },
56
- }}
57
- />
58
- ) : props.signInType === "username" ? (
59
- <Controller
60
- control={control}
61
- name="username"
62
- render={({ field }) => {
63
- return (
64
- <HawaTextField
65
- width="full"
66
- type="text"
67
- autoComplete="username"
68
- label={props.texts.usernameLabel}
69
- helpertext={errors.username?.message}
70
- placeholder={props.texts.usernamePlaceholder}
71
- onChange={field.onChange}
72
- value={field.value ?? ""}
73
- />
74
- )
75
- }}
76
- rules={{
77
- required: props.texts.usernameRequired,
78
- }}
79
- />
80
- ) : (
81
- <Controller
82
- control={control}
83
- name="phone"
84
- render={({ field }) => <HawaPhoneInput label="Phone number" />}
85
- rules={{ required: props.texts.phoneRequiredText }}
86
- />
87
- )}
88
- {props.signInType !== "phone" && (
89
- <>
39
+ </div> */}
40
+ {props.showError && (
41
+ <HawaAlert
42
+ title={props.errorTitle}
43
+ text={props.errorText}
44
+ severity="error"
45
+ />
46
+ )}
47
+ {props.signInType === "email" ? (
90
48
  <Controller
91
49
  control={control}
92
- name="password"
50
+ name="email"
93
51
  render={({ field }) => (
94
52
  <HawaTextField
95
53
  width="full"
96
- autoComplete="current-password"
97
- type="password"
98
- label={props.texts.passwordLabel}
99
- placeholder={props.texts.passwordPlaceholder}
100
- helpertext={errors.password?.message}
101
- onChange={field.onChange}
54
+ type="text"
55
+ autoComplete="email"
56
+ label={props.texts.emailLabel}
57
+ helpertext={errors.email?.message}
58
+ placeholder={props.texts.emailPlaceholder}
102
59
  value={field.value ?? ""}
60
+ onChange={field.onChange}
103
61
  />
104
62
  )}
105
63
  rules={{
106
- required: props.texts.passwordRequiredText,
107
- minLength: 5,
64
+ required: props.texts.emailRequiredText,
65
+ pattern: {
66
+ value:
67
+ /^(([^<>()[\]\\.,;:\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,}))$/,
68
+ message: props.texts.emailInvalidText,
69
+ },
108
70
  }}
109
71
  />
110
- {!props.withoutResetPassword && (
111
- <div
112
- onClick={props.handleForgotPassword}
113
- className="mb-3 w-fit cursor-pointer text-xs dark:text-gray-300"
114
- >
115
- {props.texts.forgotPasswordText}
116
- </div>
117
- )}
118
- </>
119
- )}
120
-
121
-
122
- <Button className="w-full" isLoading={props.isLoading}>
123
- {props.texts.signInText}
124
- </Button>
125
- {!props.withoutSignUp && (
126
- <div className="p-3 text-center text-sm font-semibold dark:text-gray-300">
127
- {props.texts.newUserText}{" "}
128
- <span
129
- onClick={props.handleRouteToSignUp}
130
- className="clickable-link"
131
- >
132
- {props.texts.createAccount}
133
- </span>
134
- </div>
135
- )}
136
- </form>
137
- </CardContent>
138
-
139
- {/* 3rd Party Sign Auth Buttons */}
140
- {props.viaGithub || props.viaGoogle || props.viaTwitter ? (
141
- <CardFooter className="grid grid-cols-1 gap-2 ">
142
- {props.viaGoogle && (
143
- <Button variant="outline" onClick={props.handleGoogleSignIn}>
144
- <Icons.google
145
- className={clsx(
146
- "h-4 w-4",
147
- props.direction === "rtl" ? "ml-2" : "mr-2"
148
- )}
72
+ ) : props.signInType === "username" ? (
73
+ <Controller
74
+ control={control}
75
+ name="username"
76
+ render={({ field }) => {
77
+ return (
78
+ <HawaTextField
79
+ width="full"
80
+ type="text"
81
+ autoComplete="username"
82
+ label={props.texts.usernameLabel}
83
+ helpertext={errors.username?.message}
84
+ placeholder={props.texts.usernamePlaceholder}
85
+ onChange={field.onChange}
86
+ value={field.value ?? ""}
87
+ />
88
+ )
89
+ }}
90
+ rules={{
91
+ required: props.texts.usernameRequired,
92
+ }}
149
93
  />
150
- {props.texts.signInViaGoogleLabel}
151
- </Button>
152
- )}
153
- {props.viaGithub && (
154
- <Button variant="outline" onClick={props.handleGithubSignIn}>
155
- <Icons.gitHub
156
- className={clsx(
157
- "h-4 w-4",
158
- props.direction === "rtl" ? "ml-2" : "mr-2"
159
- )}
94
+ ) : (
95
+ <Controller
96
+ control={control}
97
+ name="phone"
98
+ render={({ field }) => <HawaPhoneInput label="Phone number" />}
99
+ rules={{ required: props.texts.phoneRequiredText }}
160
100
  />
161
- {props.texts.signInViaGithubLabel}
162
- </Button>
163
- )}
164
- {props.viaTwitter && (
165
- <Button variant="outline" onClick={props.handleTwitterSignIn}>
166
- <Icons.twitter
167
- className={clsx(
168
- "h-4 w-4",
169
- props.direction === "rtl" ? "ml-2" : "mr-2"
101
+ )}
102
+ {props.signInType !== "phone" && (
103
+ <>
104
+ <Controller
105
+ control={control}
106
+ name="password"
107
+ render={({ field }) => (
108
+ <HawaTextField
109
+ width="full"
110
+ autoComplete="current-password"
111
+ type="password"
112
+ label={props.texts.passwordLabel}
113
+ placeholder={props.texts.passwordPlaceholder}
114
+ helpertext={errors.password?.message}
115
+ onChange={field.onChange}
116
+ value={field.value ?? ""}
117
+ />
118
+ )}
119
+ rules={{
120
+ required: props.texts.passwordRequiredText,
121
+ minLength: 5,
122
+ }}
123
+ />
124
+ {!props.withoutResetPassword && (
125
+ <div
126
+ onClick={props.handleForgotPassword}
127
+ className="mb-3 w-fit cursor-pointer text-xs dark:text-gray-300"
128
+ >
129
+ {props.texts.forgotPasswordText}
130
+ </div>
170
131
  )}
171
- />
172
- {props.texts.signInViaTwitterLabel}
132
+ </>
133
+ )}
134
+
135
+ <Button className="w-full" isLoading={props.isLoading}>
136
+ {props.texts.signInText}
173
137
  </Button>
174
- )}
175
- </CardFooter>
176
- ) : null}
177
- </Card>
138
+ {!props.withoutSignUp && (
139
+ <div className="p-3 text-center text-sm font-semibold dark:text-gray-300">
140
+ {props.texts.newUserText}{" "}
141
+ <span
142
+ onClick={props.handleRouteToSignUp}
143
+ className="clickable-link"
144
+ >
145
+ {props.texts.createAccount}
146
+ </span>
147
+ </div>
148
+ )}
149
+ </form>
150
+ </CardContent>
151
+
152
+ {/* 3rd Party Sign Auth Buttons */}
153
+ {props.viaGithub || props.viaGoogle || props.viaTwitter ? (
154
+ <CardFooter className="grid grid-cols-1 gap-2 ">
155
+ {props.viaGoogle && (
156
+ <Button variant="outline" onClick={props.handleGoogleSignIn}>
157
+ <Icons.google
158
+ className={clsx(
159
+ "h-4 w-4",
160
+ props.direction === "rtl" ? "ml-2" : "mr-2"
161
+ )}
162
+ />
163
+ {props.texts.signInViaGoogleLabel}
164
+ </Button>
165
+ )}
166
+ {props.viaGithub && (
167
+ <Button variant="outline" onClick={props.handleGithubSignIn}>
168
+ <Icons.gitHub
169
+ className={clsx(
170
+ "h-4 w-4",
171
+ props.direction === "rtl" ? "ml-2" : "mr-2"
172
+ )}
173
+ />
174
+ {props.texts.signInViaGithubLabel}
175
+ </Button>
176
+ )}
177
+ {props.viaTwitter && (
178
+ <Button variant="outline" onClick={props.handleTwitterSignIn}>
179
+ <Icons.twitter
180
+ className={clsx(
181
+ "h-4 w-4",
182
+ props.direction === "rtl" ? "ml-2" : "mr-2"
183
+ )}
184
+ />
185
+ {props.texts.signInViaTwitterLabel}
186
+ </Button>
187
+ )}
188
+ </CardFooter>
189
+ ) : null}
190
+ </Card>
191
+ <InterfaceSettings
192
+ currentColorMode={props.currentColorMode}
193
+ currentLanguage={props.currentLanguage}
194
+ handleColorMode={props.handleColorMode}
195
+ handleLanguage={props.handleLanguage}
196
+ />
197
+ </div>
178
198
  )
179
199
  }
180
200
 
181
201
  type SignInFormTypes = {
202
+ handleLanguage?: () => void
203
+ currentLanguage?: any
204
+ handleColorMode?: () => void
205
+ currentColorMode?: any
182
206
  direction?: "rtl" | "ltr"
183
207
  showError?: any
184
208
  errorTitle?: string
@@ -2,6 +2,7 @@ import React, { useRef, useState, useEffect } from "react"
2
2
  import clsx from "clsx"
3
3
  import { HawaButton } from "./HawaButton"
4
4
  import { Button } from "./Button"
5
+ // TODO: make handleClose to detect when the alert is closed from outside this component
5
6
 
6
7
  type AlertTypes = {
7
8
  severity: "info" | "warning" | "error" | "success"
@@ -22,9 +22,9 @@ export const HawaRadio: FC<RadioTypes> = ({
22
22
  }) => {
23
23
  const [selectedOption, setSelectedOption] = useState(props.defaultValue)
24
24
  let activeTabStyle =
25
- "inline-block py-2 px-4 w-full text-white bg-primary rounded active"
25
+ "inline-block py-2 px-4 w-full text-white bg-primary rounded active dark:bg-primary dark:text-black"
26
26
  let inactiveTabStyle =
27
- "inline-block py-2 px-4 w-full bg-gray-100 rounded hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-white"
27
+ "inline-block py-2 px-4 w-full dark:bg-background bg-gray-100 rounded hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-white"
28
28
  let orientationStyle = {
29
29
  horizontal: "flex flex-row",
30
30
  vertical: "flex flex-col",
@@ -38,7 +38,7 @@ export const HawaRadio: FC<RadioTypes> = ({
38
38
  props.options?.length > 2
39
39
  ? "flex-wrap xs:max-w-full xs:flex-nowrap"
40
40
  : "",
41
- " max-w-fit whitespace-nowrap rounded bg-gray-100 text-center text-sm font-medium text-gray-500 dark:text-gray-400",
41
+ " max-w-fit whitespace-nowrap rounded border bg-gray-100 text-center text-sm font-medium text-gray-500 dark:bg-background dark:text-gray-400",
42
42
  orientationStyle[orientation]
43
43
  )}
44
44
  >
@@ -0,0 +1,70 @@
1
+ import React, { FC } from "react"
2
+ import { HawaRadio } from "./HawaRadio"
3
+
4
+ type TypographyTypes = {
5
+ handleLanguage: () => void
6
+ currentLanguage: any
7
+ handleColorMode: () => void
8
+ currentColorMode: any
9
+ }
10
+ export const InterfaceSettings: FC<TypographyTypes> = (props) => {
11
+ return (
12
+ <div className="mt-6 flex flex-row justify-between">
13
+ <HawaRadio
14
+ defaultValue={props.currentLanguage}
15
+ onChangeTab={props.handleLanguage}
16
+ design="tabs"
17
+ options={[
18
+ { value: "ar", label: "عربي" },
19
+ { value: "en", label: "English" },
20
+ ]}
21
+ />
22
+ <HawaRadio
23
+ defaultValue={props.currentColorMode}
24
+ onChangeTab={props.handleColorMode}
25
+ design="tabs"
26
+ options={[
27
+ {
28
+ value: "light",
29
+ label: (
30
+ <svg
31
+ width="15"
32
+ height="15"
33
+ viewBox="0 0 15 15"
34
+ fill="none"
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90"
37
+ >
38
+ <path
39
+ d="M7.5 0C7.77614 0 8 0.223858 8 0.5V2.5C8 2.77614 7.77614 3 7.5 3C7.22386 3 7 2.77614 7 2.5V0.5C7 0.223858 7.22386 0 7.5 0ZM2.1967 2.1967C2.39196 2.00144 2.70854 2.00144 2.90381 2.1967L4.31802 3.61091C4.51328 3.80617 4.51328 4.12276 4.31802 4.31802C4.12276 4.51328 3.80617 4.51328 3.61091 4.31802L2.1967 2.90381C2.00144 2.70854 2.00144 2.39196 2.1967 2.1967ZM0.5 7C0.223858 7 0 7.22386 0 7.5C0 7.77614 0.223858 8 0.5 8H2.5C2.77614 8 3 7.77614 3 7.5C3 7.22386 2.77614 7 2.5 7H0.5ZM2.1967 12.8033C2.00144 12.608 2.00144 12.2915 2.1967 12.0962L3.61091 10.682C3.80617 10.4867 4.12276 10.4867 4.31802 10.682C4.51328 10.8772 4.51328 11.1938 4.31802 11.3891L2.90381 12.8033C2.70854 12.9986 2.39196 12.9986 2.1967 12.8033ZM12.5 7C12.2239 7 12 7.22386 12 7.5C12 7.77614 12.2239 8 12.5 8H14.5C14.7761 8 15 7.77614 15 7.5C15 7.22386 14.7761 7 14.5 7H12.5ZM10.682 4.31802C10.4867 4.12276 10.4867 3.80617 10.682 3.61091L12.0962 2.1967C12.2915 2.00144 12.608 2.00144 12.8033 2.1967C12.9986 2.39196 12.9986 2.70854 12.8033 2.90381L11.3891 4.31802C11.1938 4.51328 10.8772 4.51328 10.682 4.31802ZM8 12.5C8 12.2239 7.77614 12 7.5 12C7.22386 12 7 12.2239 7 12.5V14.5C7 14.7761 7.22386 15 7.5 15C7.77614 15 8 14.7761 8 14.5V12.5ZM10.682 10.682C10.8772 10.4867 11.1938 10.4867 11.3891 10.682L12.8033 12.0962C12.9986 12.2915 12.9986 12.608 12.8033 12.8033C12.608 12.9986 12.2915 12.9986 12.0962 12.8033L10.682 11.3891C10.4867 11.1938 10.4867 10.8772 10.682 10.682ZM5.5 7.5C5.5 6.39543 6.39543 5.5 7.5 5.5C8.60457 5.5 9.5 6.39543 9.5 7.5C9.5 8.60457 8.60457 9.5 7.5 9.5C6.39543 9.5 5.5 8.60457 5.5 7.5ZM7.5 4.5C5.84315 4.5 4.5 5.84315 4.5 7.5C4.5 9.15685 5.84315 10.5 7.5 10.5C9.15685 10.5 10.5 9.15685 10.5 7.5C10.5 5.84315 9.15685 4.5 7.5 4.5Z"
40
+ fill="currentColor"
41
+ fill-rule="evenodd"
42
+ clip-rule="evenodd"
43
+ ></path>
44
+ </svg>
45
+ ),
46
+ },
47
+ {
48
+ value: "dark",
49
+ label: (
50
+ <svg
51
+ xmlns="http://www.w3.org/2000/svg"
52
+ width="24"
53
+ height="24"
54
+ viewBox="0 0 24 24"
55
+ fill="none"
56
+ stroke="currentColor"
57
+ stroke-width="2"
58
+ stroke-linecap="round"
59
+ stroke-linejoin="round"
60
+ className="h-[1.2rem] w-[1.2rem] transition-all dark:rotate-0 dark:scale-100"
61
+ >
62
+ <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
63
+ </svg>
64
+ ),
65
+ },
66
+ ]}
67
+ />
68
+ </div>
69
+ )
70
+ }
@@ -60,3 +60,4 @@ export * from "./Label"
60
60
  export * from "./Input"
61
61
  export * from "./Tooltip"
62
62
  export * from "./Card"
63
+ export * from "./InterfaceSettings"
package/src/styles.css CHANGED
@@ -3261,6 +3261,9 @@ body {
3261
3261
  --tw-bg-opacity: 1;
3262
3262
  background-color: rgb(187 247 208 / var(--tw-bg-opacity));
3263
3263
  }
3264
+ :is(.dark .dark\:bg-primary) {
3265
+ background-color: hsl(var(--primary));
3266
+ }
3264
3267
  :is(.dark .dark\:bg-red-200) {
3265
3268
  --tw-bg-opacity: 1;
3266
3269
  background-color: rgb(254 202 202 / var(--tw-bg-opacity));