@sikka/hawa 0.0.204 → 0.0.205

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.0.204",
3
+ "version": "0.0.205",
4
4
  "description": "SaaS Oriented UI Kit",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.es.js",
@@ -1,33 +1,39 @@
1
- import React from "react"
2
- import { HawaTextField, HawaAlert, HawaButton } from "../../elements"
1
+ import React, { useState } from "react"
2
+ import {
3
+ HawaTextField,
4
+ HawaAlert,
5
+ HawaButton,
6
+ HawaPinInput,
7
+ } from "../../elements"
3
8
  import { Controller, useForm } from "react-hook-form"
4
9
  import { HawaContainer } from "../../layout"
5
10
 
6
- type CodeConfirmationTypes = {
7
- showError: any
8
- errorTitle: any
9
- errorText: any
10
- texts: {
11
+ type TConfirmation = {
12
+ showError?: any
13
+ errorTitle?: any
14
+ errorText?: any
15
+ texts?: {
16
+ checkYourPhone: string
17
+ weSentCode: string
18
+ didntGetCode: string
19
+ resendCode: string
11
20
  codeLabel: string
12
21
  codePlaceholder: string
13
22
  codeRequiredText: string
14
- confirmText: string
23
+ confirm: string
24
+ cancel
15
25
  }
16
- handleSignIn: any
26
+ phoneNumber?: string
27
+ submitConfirmation?: any
28
+ handleSignIn?: any
17
29
  }
18
- export const CodeConfirmation: React.FunctionComponent<
19
- CodeConfirmationTypes
20
- > = (props) => {
21
- const methods = useForm()
22
- const {
23
- formState: { errors },
24
- handleSubmit,
25
- control,
26
- } = methods
27
30
 
31
+ export const CodeConfirmation: React.FunctionComponent<TConfirmation> = (
32
+ props
33
+ ) => {
34
+ const [pins, setPins] = useState(null)
28
35
  return (
29
36
  <HawaContainer>
30
- {" "}
31
37
  {props.showError && (
32
38
  <HawaAlert
33
39
  title={props.errorTitle}
@@ -35,33 +41,38 @@ export const CodeConfirmation: React.FunctionComponent<
35
41
  severity="error"
36
42
  />
37
43
  )}
38
- <form onSubmit={handleSubmit(props.handleSignIn)}>
39
- <Controller
40
- control={control}
41
- name="code"
42
- render={({ field }) => (
43
- <HawaTextField
44
- width="full"
45
- type="number"
46
- label={props.texts.codeLabel}
47
- helperText={errors.email?.message}
48
- placeholder={props.texts.codePlaceholder}
49
- {...field}
50
- value={field.value ?? ""}
51
- />
52
- )}
53
- rules={{
54
- required: props.texts.codeRequiredText,
55
- }}
56
- />
57
-
58
- <HawaButton
59
- color="primary"
60
- // type="submit"
61
- width="full"
62
- >
63
- {props.texts.confirmText}
64
- </HawaButton>
44
+ <div className="mb-4">
45
+ <div className="text-lg font-bold">
46
+ {props.texts.checkYourPhone ?? "Please check your phone"}
47
+ </div>
48
+ <div className="text-gray-500">
49
+ <span>{props.texts.weSentCode ?? "We've sent a code to "}</span>
50
+ <span>{props.phoneNumber}</span>
51
+ </div>{" "}
52
+ </div>
53
+ <form
54
+ onSubmit={(e) => {
55
+ e.preventDefault()
56
+ if (pins) {
57
+ props.submitConfirmation(pins)
58
+ }
59
+ }}
60
+ >
61
+ <HawaPinInput width="full" digits={6} getPins={(e) => setPins(e)} />
62
+ <div className=" py-2 text-center text-xs">
63
+ <span>{props.texts.didntGetCode ?? "Didn't get the code?"}</span>{" "}
64
+ <span className="cursor-pointer text-buttonPrimary-500">
65
+ {props.texts.resendCode ?? "Click to resend"}
66
+ </span>
67
+ </div>
68
+ <div className="mt-4 grid grid-cols-2 gap-2">
69
+ <HawaButton margins={"none"} variant="outlined" width="full">
70
+ {props.texts.cancel ?? "Cancel"}
71
+ </HawaButton>
72
+ <HawaButton margins={"none"} color="primary" width="full">
73
+ {props.texts.confirm ?? "Confirm"}
74
+ </HawaButton>
75
+ </div>
65
76
  </form>
66
77
  </HawaContainer>
67
78
  )
@@ -9,55 +9,6 @@ import {
9
9
  import { Controller, useForm } from "react-hook-form"
10
10
  import { HawaContainer } from "../../layout"
11
11
 
12
- type SignInFormTypes = {
13
- language?: string
14
- showError?: any
15
- errorTitle?: string
16
- errorText?: string
17
- signInType?: "email" | "username" | "phone"
18
- texts?: {
19
- emailLabel?: string
20
- emailPlaceholder?: string
21
- emailRequiredText?: string
22
- emailInvalidText?: string
23
- usernameLabel?: string
24
- usernamePlaceholder?: string
25
- usernameRequired?: string
26
- phoneRequiredText?: string
27
- passwordLabel?: string
28
- passwordPlaceholder?: string
29
- passwordRequiredText?: string
30
- forgotPasswordText?: string
31
- newUserText?: string
32
- signUpText?: string
33
- signInText?: string
34
- googleButtonLabel?: string
35
- githubButtonLabel?: string
36
- twitterButtonLabel?: string
37
- }
38
- withoutResetPassword?: boolean
39
- withoutSignUp?: boolean
40
- /**
41
- *show spinner if true
42
- */
43
- isLoading?: any
44
- viaGoogle?: boolean
45
- viaGithub?: boolean
46
- viaTwitter?: boolean
47
- /**
48
- * Handle the sign in .
49
- */
50
- handleSignIn?: (e: any) => void
51
- /**
52
- * Handle routing to sign up page
53
- */
54
- handleRouteToSignUp?: () => void
55
- handleForgotPassword?: () => void
56
- handleGoogleSignIn?: () => void
57
- handleGithubSignIn?: () => void
58
- handleTwitterSignIn?: () => void
59
- }
60
-
61
12
  export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
62
13
  const {
63
14
  formState: { errors },
@@ -66,7 +17,7 @@ export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
66
17
  } = useForm()
67
18
 
68
19
  return (
69
- <HawaContainer direction={props.language === "ar" ? "rtl" : "ltr"}>
20
+ <HawaContainer direction={props.direction}>
70
21
  <form onSubmit={handleSubmit((e) => props.handleSignIn(e))}>
71
22
  {props.showError && (
72
23
  <HawaAlert
@@ -128,29 +79,36 @@ export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
128
79
  rules={{ required: props.texts.phoneRequiredText }}
129
80
  />
130
81
  )}
131
- <Controller
132
- control={control}
133
- name="password"
134
- render={({ field }) => (
135
- <HawaTextField
136
- width="full"
137
- type="password"
138
- label={props.texts.passwordLabel}
139
- placeholder={props.texts.passwordPlaceholder}
140
- helperText={errors.password?.message}
141
- onChange={field.onChange}
142
- value={field.value ?? ""}
82
+ {props.signInType !== "phone" && (
83
+ <>
84
+ <Controller
85
+ control={control}
86
+ name="password"
87
+ render={({ field }) => (
88
+ <HawaTextField
89
+ width="full"
90
+ type="password"
91
+ label={props.texts.passwordLabel}
92
+ placeholder={props.texts.passwordPlaceholder}
93
+ helperText={errors.password?.message}
94
+ onChange={field.onChange}
95
+ value={field.value ?? ""}
96
+ />
97
+ )}
98
+ rules={{
99
+ required: props.texts.passwordRequiredText,
100
+ minLength: 5,
101
+ }}
143
102
  />
144
- )}
145
- rules={{ required: props.texts.passwordRequiredText, minLength: 5 }}
146
- />
147
- {!props.withoutResetPassword && (
148
- <div
149
- className="mb-3 w-fit cursor-pointer text-xs dark:text-gray-300"
150
- onClick={props.handleForgotPassword}
151
- >
152
- {props.texts.forgotPasswordText}
153
- </div>
103
+ {!props.withoutResetPassword && (
104
+ <div
105
+ onClick={props.handleForgotPassword}
106
+ className="mb-3 w-fit cursor-pointer text-xs dark:text-gray-300"
107
+ >
108
+ {props.texts.forgotPasswordText}
109
+ </div>
110
+ )}
111
+ </>
154
112
  )}
155
113
 
156
114
  <HawaButton
@@ -159,8 +117,6 @@ export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
159
117
  color="primary"
160
118
  size="medium"
161
119
  width="full"
162
- // type="submit"
163
- // onClick={(e) => console.log("clicking")}
164
120
  >
165
121
  {props.texts.signInText}
166
122
  </HawaButton>
@@ -176,8 +132,8 @@ export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
176
132
  </div>
177
133
  )}
178
134
  </form>
179
- {/* <Divider /> */}
180
- {/* <div className="divide-y divide-gray-900"></div> */}
135
+
136
+ {/* 3rd Party Sign Auth Buttons */}
181
137
  {props.viaGithub || props.viaGoogle || props.viaTwitter ? (
182
138
  <div className="flex flex-col ">
183
139
  {props.viaGoogle && (
@@ -206,3 +162,52 @@ export const SignInForm: React.FunctionComponent<SignInFormTypes> = (props) => {
206
162
  </HawaContainer>
207
163
  )
208
164
  }
165
+
166
+ type SignInFormTypes = {
167
+ direction?: "rtl" | "ltr"
168
+ showError?: any
169
+ errorTitle?: string
170
+ errorText?: string
171
+ signInType?: "email" | "username" | "phone"
172
+ texts?: {
173
+ emailLabel?: string
174
+ emailPlaceholder?: string
175
+ emailRequiredText?: string
176
+ emailInvalidText?: string
177
+ usernameLabel?: string
178
+ usernamePlaceholder?: string
179
+ usernameRequired?: string
180
+ phoneRequiredText?: string
181
+ passwordLabel?: string
182
+ passwordPlaceholder?: string
183
+ passwordRequiredText?: string
184
+ forgotPasswordText?: string
185
+ newUserText?: string
186
+ signUpText?: string
187
+ signInText?: string
188
+ googleButtonLabel?: string
189
+ githubButtonLabel?: string
190
+ twitterButtonLabel?: string
191
+ }
192
+ withoutResetPassword?: boolean
193
+ withoutSignUp?: boolean
194
+ /**
195
+ *show spinner if true
196
+ */
197
+ isLoading?: any
198
+ viaGoogle?: boolean
199
+ viaGithub?: boolean
200
+ viaTwitter?: boolean
201
+ /**
202
+ * Handle the sign in .
203
+ */
204
+ handleSignIn?: (e: any) => void
205
+ /**
206
+ * Handle routing to sign up page
207
+ */
208
+ handleRouteToSignUp?: () => void
209
+ handleForgotPassword?: () => void
210
+ handleGoogleSignIn?: () => void
211
+ handleGithubSignIn?: () => void
212
+ handleTwitterSignIn?: () => void
213
+ }
@@ -11,7 +11,7 @@ import { Controller, FormProvider, useForm } from "react-hook-form"
11
11
  import { HawaContainer } from "../../layout/HawaContainer"
12
12
 
13
13
  type SignUpFormTypes = {
14
- language?: string
14
+ direction?: "rtl" | "ltr"
15
15
  texts: {
16
16
  fullNameLabel: string
17
17
  fullNamePlaceholder: string
@@ -72,7 +72,7 @@ export const SignUpForm: React.FunctionComponent<SignUpFormTypes> = (props) => {
72
72
  } = methods
73
73
 
74
74
  return (
75
- <HawaContainer direction={props.language === "ar" ? "rtl" : "ltr"}>
75
+ <HawaContainer direction={props.direction}>
76
76
  <div>
77
77
  {props.showError && (
78
78
  <HawaAlert
@@ -26,7 +26,7 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
26
26
  isLoading?: boolean
27
27
  }
28
28
 
29
- const baseStyles = "cursor-pointer font-medium rounded transition-all"
29
+ const baseStyles = "cursor-pointer font-medium rounded h-full transition-all"
30
30
 
31
31
  const sizeStyles = {
32
32
  xs: "px-1 py-1",
@@ -1,55 +1,78 @@
1
1
  import clsx from "clsx"
2
- import React from "react"
2
+ import React, { useEffect, useState } from "react"
3
3
 
4
4
  type PinInputTypes = {
5
- label: string
5
+ label?: string
6
6
  icon?: JSX.Element
7
- digits?: number
7
+ digits: number
8
+ width?: "normal" | "full"
9
+ getPins?: any
8
10
  }
9
11
  export const HawaPinInput: React.FunctionComponent<PinInputTypes> = ({
10
12
  label,
11
13
  icon,
14
+ digits,
15
+ width = "normal",
16
+ getPins,
17
+ ...props
12
18
  }) => {
13
- const validate = (evt) => {
14
- var theEvent = evt || window.event
19
+ const [pin, setPin] = useState(Array.from(Array(digits)))
15
20
 
16
- // Handle paste
17
- if (theEvent.type === "paste") {
18
- key = evt.clipboardData.getData("text/plain")
19
- } else {
20
- // Handle key press
21
- var key = theEvent.keyCode || theEvent.which
22
- key = String.fromCharCode(key)
21
+ const handleKeyDown = (e, index) => {
22
+ let backTo = 0
23
+ if (e.key === "Backspace") {
24
+ e.target.value.length === 0 ? (backTo = index - 1) : (backTo = index)
25
+ const previousInput = document.getElementById(`input-${backTo}`)
26
+ previousInput?.focus()
23
27
  }
24
- var regex = /[0-9]|\./
25
- if (!regex.test(key)) {
26
- theEvent.returnValue = false
27
- if (theEvent.preventDefault) theEvent.preventDefault()
28
+ }
29
+ useEffect(() => {
30
+ let unfilled = pin.includes(undefined)
31
+ if (!unfilled) {
32
+ getPins(pin)
33
+ }
34
+ })
35
+ const handleChange = (e, index) => {
36
+ if (!/^\d*$/.test(e.target.value)) {
37
+ const newPin = [...pin]
38
+ newPin[index] = ""
39
+ setPin(newPin)
40
+ return
41
+ } else {
42
+ const newPin = [...pin]
43
+ newPin[index] = e.target.value
44
+ setPin(newPin)
45
+
46
+ if (e.target.value.length === 1) {
47
+ const nextInput = document.getElementById(`input-${index + 1}`)
48
+ nextInput?.focus()
49
+ } else if (e.target.value.length === 0) {
50
+ const previousInput = document.getElementById(`input-${index - 1}`)
51
+ previousInput?.focus()
52
+ }
28
53
  }
29
54
  }
55
+
30
56
  return (
31
- <div className="flex flex-row gap-2">
32
- <SinglePinInput
33
- onInput={
34
- (v) =>
35
- v.target.value.replace(/[^0-9.]/g, "").replace(/(\..*?)\..*/g, "$1")
36
- // .replace(/[^0-9.]/g, "")
37
- // .replace(/(..*?)..*/g, "$1")
38
- // .replace(/^0[^.]/, "0")
39
- }
40
- />
41
- <SinglePinInput />
42
- <SinglePinInput />
43
- <SinglePinInput />
57
+ <div className="flex w-full flex-row justify-center gap-2">
58
+ {pin.map((value, index) => (
59
+ <input
60
+ key={index}
61
+ type="text"
62
+ maxLength={1}
63
+ value={value}
64
+ id={`input-${index}`}
65
+ pattern="[0-9]*"
66
+ className={clsx(
67
+ "h-10 rounded bg-white text-center",
68
+ width === "full" ? "w-full" : "w-10"
69
+ )}
70
+ onChange={(e) => handleChange(e, index)}
71
+ onKeyDown={(e) => handleKeyDown(e, index)}
72
+ onFocus={(e) => e.target.select()}
73
+ {...props}
74
+ />
75
+ ))}
44
76
  </div>
45
77
  )
46
78
  }
47
-
48
- const SinglePinInput = (props) => (
49
- <input
50
- type="text"
51
- maxLength={1}
52
- className="h-10 w-10 bg-gray-200 text-center"
53
- {...props}
54
- />
55
- )
@@ -339,6 +339,7 @@ export const HawaTable: React.FunctionComponent<TableTypes> = ({
339
339
  )}
340
340
  {/* Pagination Settings */}
341
341
  <div className="w-fit ">
342
+ {/* TODO: Hide it when props.pagination is true */}
342
343
  <select
343
344
  value={perPage}
344
345
  className="h-6 rounded text-xs"
package/src/styles.css CHANGED
@@ -775,6 +775,9 @@ video {
775
775
  .mt-3 {
776
776
  margin-top: 0.75rem;
777
777
  }
778
+ .mt-4 {
779
+ margin-top: 1rem;
780
+ }
778
781
  .mt-5 {
779
782
  margin-top: 1.25rem;
780
783
  }
@@ -1055,6 +1058,9 @@ video {
1055
1058
  -moz-appearance: none;
1056
1059
  appearance: none;
1057
1060
  }
1061
+ .grid-cols-2 {
1062
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1063
+ }
1058
1064
  .grid-cols-4 {
1059
1065
  grid-template-columns: repeat(4, minmax(0, 1fr));
1060
1066
  }
@@ -1156,10 +1162,6 @@ video {
1156
1162
  --tw-divide-opacity: 1;
1157
1163
  border-color: rgb(243 244 246 / var(--tw-divide-opacity));
1158
1164
  }
1159
- .divide-gray-900 > :not([hidden]) ~ :not([hidden]) {
1160
- --tw-divide-opacity: 1;
1161
- border-color: rgb(17 24 39 / var(--tw-divide-opacity));
1162
- }
1163
1165
  .self-center {
1164
1166
  align-self: center;
1165
1167
  }
@@ -1738,6 +1740,9 @@ video {
1738
1740
  --tw-text-opacity: 1;
1739
1741
  color: rgb(30 64 175 / var(--tw-text-opacity));
1740
1742
  }
1743
+ .text-buttonPrimary-500 {
1744
+ color: var(--button-primary-500);
1745
+ }
1741
1746
  .text-gray-300 {
1742
1747
  --tw-text-opacity: 1;
1743
1748
  color: rgb(209 213 219 / var(--tw-text-opacity));