@sikka/hawa 0.1.91 → 0.1.93

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/dist/styles.css CHANGED
@@ -422,7 +422,7 @@ video {
422
422
  --border: 240 5.9% 90%;
423
423
  --input: 240 5.9% 90%;
424
424
  --ring: 240 5% 64.9%;
425
- --radius: 0.5rem;
425
+ --radius: 0rem;
426
426
  --radius-inner: calc(var(--radius) - calc(var(--radius) / 3));
427
427
 
428
428
  --layout-primary-700: #b7aff7;
@@ -470,10 +470,11 @@ video {
470
470
  margin-right: 0.25em;
471
471
  width: 0.75em;
472
472
  vertical-align: middle;
473
- color: var(--button-primary-500-hsl);
473
+ color: hsl(var(--primary));
474
+
474
475
  }
475
476
  .link {
476
- color: var(--button-primary-500-hsl);
477
+ color: hsl(var(--primary));
477
478
  }
478
479
  .link:hover {
479
480
  text-decoration: underline;
@@ -531,10 +532,10 @@ video {
531
532
  height: 9px;
532
533
  position: absolute;
533
534
  top: 6px;
534
- left: 11px;
535
+ left: 3px;
535
536
  content: " ";
536
537
  display: block;
537
- background: var(--button-primary-500-hsl);
538
+ background: hsl(var(--primary));
538
539
  }
539
540
  .radio-item-bordered input[type="radio"]:checked + label:after {
540
541
  border-radius: 100%;
@@ -545,7 +546,7 @@ video {
545
546
  left: 23px;
546
547
  content: " ";
547
548
  display: block;
548
- background: var(--button-primary-500-hsl);
549
+ background: hsl(var(--primary));
549
550
  }
550
551
  * {
551
552
  border-color: hsl(var(--border));
@@ -803,6 +804,9 @@ video {
803
804
  .right-0 {
804
805
  right: 0px;
805
806
  }
807
+ .right-1 {
808
+ right: 0.25rem;
809
+ }
806
810
  .right-2 {
807
811
  right: 0.5rem;
808
812
  }
@@ -848,6 +852,9 @@ video {
848
852
  .top-\[22px\] {
849
853
  top: 22px;
850
854
  }
855
+ .top-\[41px\] {
856
+ top: 41px;
857
+ }
851
858
  .top-\[50\%\] {
852
859
  top: 50%;
853
860
  }
@@ -905,6 +912,10 @@ video {
905
912
  margin-left: 0.5rem;
906
913
  margin-right: 0.5rem;
907
914
  }
915
+ .mx-auto {
916
+ margin-left: auto;
917
+ margin-right: auto;
918
+ }
908
919
  .my-0 {
909
920
  margin-top: 0px;
910
921
  margin-bottom: 0px;
@@ -1386,6 +1397,9 @@ video {
1386
1397
  .w-screen {
1387
1398
  width: 100vw;
1388
1399
  }
1400
+ .min-w-0 {
1401
+ min-width: 0px;
1402
+ }
1389
1403
  .min-w-\[220px\] {
1390
1404
  min-width: 220px;
1391
1405
  }
@@ -1418,6 +1432,9 @@ video {
1418
1432
  .max-w-2xs {
1419
1433
  max-width: 250px;
1420
1434
  }
1435
+ .max-w-5xl {
1436
+ max-width: 64rem;
1437
+ }
1421
1438
  .max-w-\[200px\] {
1422
1439
  max-width: 200px;
1423
1440
  }
@@ -1696,6 +1713,13 @@ video {
1696
1713
  -moz-column-gap: 0.75rem;
1697
1714
  column-gap: 0.75rem;
1698
1715
  }
1716
+ .gap-x-8 {
1717
+ -moz-column-gap: 2rem;
1718
+ column-gap: 2rem;
1719
+ }
1720
+ .gap-y-10 {
1721
+ row-gap: 2.5rem;
1722
+ }
1699
1723
  .space-x-1 > :not([hidden]) ~ :not([hidden]) {
1700
1724
  --tw-space-x-reverse: 0;
1701
1725
  margin-right: calc(0.25rem * var(--tw-space-x-reverse));
@@ -2104,6 +2128,10 @@ video {
2104
2128
  --tw-bg-opacity: 1;
2105
2129
  background-color: rgb(34 197 94 / var(--tw-bg-opacity));
2106
2130
  }
2131
+ .bg-indigo-600 {
2132
+ --tw-bg-opacity: 1;
2133
+ background-color: rgb(79 70 229 / var(--tw-bg-opacity));
2134
+ }
2107
2135
  .bg-info {
2108
2136
  --tw-bg-opacity: 1;
2109
2137
  background-color: hsl(var(--info) / var(--tw-bg-opacity));
@@ -2337,6 +2365,10 @@ video {
2337
2365
  padding-top: 0.625rem;
2338
2366
  padding-bottom: 0.625rem;
2339
2367
  }
2368
+ .py-24 {
2369
+ padding-top: 6rem;
2370
+ padding-bottom: 6rem;
2371
+ }
2340
2372
  .py-3 {
2341
2373
  padding-top: 0.75rem;
2342
2374
  padding-bottom: 0.75rem;
@@ -2428,6 +2460,9 @@ video {
2428
2460
  .text-right {
2429
2461
  text-align: right;
2430
2462
  }
2463
+ .text-start {
2464
+ text-align: start;
2465
+ }
2431
2466
  .align-middle {
2432
2467
  vertical-align: middle;
2433
2468
  }
@@ -2524,6 +2559,12 @@ video {
2524
2559
  .leading-4 {
2525
2560
  line-height: 1rem;
2526
2561
  }
2562
+ .leading-7 {
2563
+ line-height: 1.75rem;
2564
+ }
2565
+ .leading-8 {
2566
+ line-height: 2rem;
2567
+ }
2527
2568
  .leading-\[25px\] {
2528
2569
  line-height: 25px;
2529
2570
  }
@@ -2608,6 +2649,10 @@ video {
2608
2649
  --tw-text-opacity: 1;
2609
2650
  color: rgb(21 128 61 / var(--tw-text-opacity));
2610
2651
  }
2652
+ .text-indigo-600 {
2653
+ --tw-text-opacity: 1;
2654
+ color: rgb(79 70 229 / var(--tw-text-opacity));
2655
+ }
2611
2656
  .text-info-foreground {
2612
2657
  --tw-text-opacity: 1;
2613
2658
  color: hsl(var(--info-foreground) / var(--tw-text-opacity));
@@ -2952,6 +2997,10 @@ video {
2952
2997
  .repeat-infinite {
2953
2998
  animation-iteration-count: infinite;
2954
2999
  }
3000
+ .shadow-color-primary {
3001
+ --tw-shadow: 0.25rem 0.25rem hsl(var(--primary));
3002
+ box-shadow: var(--tw-shadow);
3003
+ }
2955
3004
  /* Chrome, Safari and Opera */
2956
3005
  .no-scrollbar::-webkit-scrollbar {
2957
3006
  display: none;
@@ -3321,6 +3370,26 @@ body {
3321
3370
  .focus-visible\:ring-offset-2:focus-visible {
3322
3371
  --tw-ring-offset-width: 2px;
3323
3372
  }
3373
+ .active\:translate-x-0:active {
3374
+ --tw-translate-x: 0px;
3375
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
3376
+ }
3377
+ .active\:translate-x-0\.5:active {
3378
+ --tw-translate-x: 0.125rem;
3379
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
3380
+ }
3381
+ .active\:translate-y-0:active {
3382
+ --tw-translate-y: 0px;
3383
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
3384
+ }
3385
+ .active\:translate-y-0\.5:active {
3386
+ --tw-translate-y: 0.125rem;
3387
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
3388
+ }
3389
+ .active\:shadow-color-primary-active:active {
3390
+ --tw-shadow: 0.125rem 0.125rem hsl(var(--primary));
3391
+ box-shadow: var(--tw-shadow);
3392
+ }
3324
3393
  .disabled\:pointer-events-none:disabled {
3325
3394
  pointer-events: none;
3326
3395
  }
@@ -3798,6 +3867,10 @@ body {
3798
3867
  :is(.dark .dark\:bg-background) {
3799
3868
  background-color: hsl(var(--background));
3800
3869
  }
3870
+ :is(.dark .dark\:bg-black) {
3871
+ --tw-bg-opacity: 1;
3872
+ background-color: rgb(0 0 0 / var(--tw-bg-opacity));
3873
+ }
3801
3874
  :is(.dark .dark\:bg-blue-200) {
3802
3875
  --tw-bg-opacity: 1;
3803
3876
  background-color: rgb(191 219 254 / var(--tw-bg-opacity));
@@ -3993,9 +4066,8 @@ body {
3993
4066
  --tw-ring-opacity: 1;
3994
4067
  --tw-ring-color: rgb(31 41 55 / var(--tw-ring-opacity));
3995
4068
  }
3996
- :is(.dark .peer:checked ~ .dark\:peer-checked\:text-blue-500) {
3997
- --tw-text-opacity: 1;
3998
- color: rgb(59 130 246 / var(--tw-text-opacity));
4069
+ :is(.dark .peer:checked ~ .dark\:peer-checked\:text-primary) {
4070
+ color: hsl(var(--primary));
3999
4071
  }
4000
4072
  @media (min-width: 440px) {
4001
4073
 
@@ -4073,6 +4145,11 @@ body {
4073
4145
  padding: 5rem;
4074
4146
  }
4075
4147
 
4148
+ .sm\:py-32 {
4149
+ padding-top: 8rem;
4150
+ padding-bottom: 8rem;
4151
+ }
4152
+
4076
4153
  .sm\:text-left {
4077
4154
  text-align: left;
4078
4155
  }
@@ -4082,6 +4159,11 @@ body {
4082
4159
  line-height: 2rem;
4083
4160
  }
4084
4161
 
4162
+ .sm\:text-4xl {
4163
+ font-size: 2.25rem;
4164
+ line-height: 2.5rem;
4165
+ }
4166
+
4085
4167
  .sm\:text-base {
4086
4168
  font-size: 1rem;
4087
4169
  line-height: 1.5rem;
@@ -4108,6 +4190,14 @@ body {
4108
4190
  }
4109
4191
  @media (min-width: 768px) {
4110
4192
 
4193
+ .md\:sticky {
4194
+ position: sticky;
4195
+ }
4196
+
4197
+ .md\:top-10 {
4198
+ top: 2.5rem;
4199
+ }
4200
+
4111
4201
  .md\:mb-0 {
4112
4202
  margin-bottom: 0px;
4113
4203
  }
@@ -4128,6 +4218,10 @@ body {
4128
4218
  margin-right: 1rem;
4129
4219
  }
4130
4220
 
4221
+ .md\:mt-0 {
4222
+ margin-top: 0px;
4223
+ }
4224
+
4131
4225
  .md\:h-auto {
4132
4226
  height: auto;
4133
4227
  }
@@ -4136,6 +4230,10 @@ body {
4136
4230
  width: 12rem;
4137
4231
  }
4138
4232
 
4233
+ .md\:w-\[28rem\] {
4234
+ width: 28rem;
4235
+ }
4236
+
4139
4237
  .md\:w-full {
4140
4238
  width: 100%;
4141
4239
  }
@@ -4220,6 +4318,10 @@ body {
4220
4318
  max-width: 80rem;
4221
4319
  }
4222
4320
 
4321
+ .lg\:max-w-none {
4322
+ max-width: none;
4323
+ }
4324
+
4223
4325
  .lg\:columns-4 {
4224
4326
  -moz-columns: 4;
4225
4327
  columns: 4;
@@ -4232,6 +4334,15 @@ body {
4232
4334
  .lg\:grid-cols-4 {
4233
4335
  grid-template-columns: repeat(4, minmax(0, 1fr));
4234
4336
  }
4337
+
4338
+ .lg\:gap-y-16 {
4339
+ row-gap: 4rem;
4340
+ }
4341
+
4342
+ .lg\:px-8 {
4343
+ padding-left: 2rem;
4344
+ padding-right: 2rem;
4345
+ }
4235
4346
  }
4236
4347
  @media (min-width: 1280px) {
4237
4348
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sikka/hawa",
3
- "version": "0.1.91",
3
+ "version": "0.1.93",
4
4
  "description": "Modern UI Kit made with Tailwind & Radix Primitives",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -5,72 +5,121 @@ import { Button } from "../../elements/Button"
5
5
  import { Icons } from "../../elements/Icons"
6
6
 
7
7
  type AppLandingTypes = {
8
- handleSignIn: () => void
9
- handleSignUp: () => void
10
- handleLanguage: () => void
11
- handleColorMode: () => void
12
8
  texts?: {
13
9
  signIn: string
14
10
  signUp: string
15
11
  lang: string
16
12
  newUserText?: string
17
13
  createAccount?: string
14
+ continueWithGoogle?: string
15
+ continueWithTwitter?: string
16
+ continueWithApple?: string
17
+ continueWithMicrosoft?: string
18
+ continueWithGithub?: string
19
+ continueWithEmail?: string
20
+ continueWithPhone?: string
18
21
  }
22
+ viaGoogle?: boolean
23
+ viaTwitter?: boolean
24
+ viaGithub?: boolean
25
+ viaMicrosoft?: boolean
26
+ viaEmail?: boolean
27
+ viaPhone?: boolean
28
+ viaApple?: boolean
29
+
19
30
  withoutSignUp?: boolean
20
- handleRouteToSignUp?: () => void
21
31
  size: "small" | "normal" | "full"
32
+ direction: "rtl" | "ltr"
33
+ handleSignIn: () => void
34
+ handleSignUp: () => void
35
+ handleLanguage: () => void
36
+ handleColorMode: () => void
37
+ handleRouteToSignUp?: () => void
38
+ handleGoogle?: () => void
39
+ handleTwitter?: () => void
40
+ handleApple?: () => void
41
+ handleMicrosoft?: () => void
42
+ handleGithub?: () => void
43
+ handleEmail?: () => void
44
+ handlePhone?: () => void
22
45
  }
23
46
 
24
- //TODO: update Google auth button
25
47
  export const AppLanding: FC<AppLandingTypes> = (props) => {
26
48
  return (
27
- <div>
49
+ <div dir={props.direction}>
28
50
  <Card>
29
51
  <CardContent headless className="flex flex-col gap-6">
30
- <Button
31
- className="flex flex-row items-center gap-2"
32
- variant="outline"
33
- // onClick={props.handleGoogleSignIn}
34
- >
35
- <Icons.google className="h-4 w-4" />
36
- {/* {!props.logosOnly && props.texts.signInViaGoogleLabel} */}
37
- Continue With Google
38
- </Button>
39
- <Button
40
- className="flex flex-row items-center gap-2"
41
- variant="outline"
42
- // onClick={props.handleGoogleSignIn}
43
- >
44
- <Icons.twitter className="h-4 w-4" />
45
- {/* {!props.logosOnly && props.texts.signInViaGoogleLabel} */}
46
- Continue With Twitter
47
- </Button>
48
- <Button
49
- className="flex flex-row items-center gap-2"
50
- variant="outline"
51
- // onClick={props.handleGoogleSignIn}
52
- >
53
- <Icons.apple className="h-4 w-4" />
54
- {/* {!props.logosOnly && props.texts.signInViaGoogleLabel} */}
55
- Continue With Apple
56
- </Button>
57
- <Button
58
- className="flex flex-row items-center gap-2"
59
- variant="outline"
60
- // onClick={props.handleGoogleSignIn}
61
- >
62
- <Icons.mail className="h-4 w-4" />
63
- {/* {!props.logosOnly && props.texts.signInViaGoogleLabel} */}
64
- Continue With Email
65
- </Button>
66
-
67
- {/* {props.handleSignIn && (
68
- <Button onClick={props.handleSignIn}>{props.texts.signIn}</Button>
69
- // <Button onClick={props.handleSignIn}>Continue With Google</Button>
52
+ {props.viaGoogle && (
53
+ <Button
54
+ className="flex flex-row items-center gap-2"
55
+ variant="outline"
56
+ onClick={props.handleGoogle}
57
+ >
58
+ <Icons.google className="h-4 w-4" />
59
+ {props.texts?.continueWithGoogle ?? "Continue With Google"}
60
+ </Button>
61
+ )}
62
+ {props.viaGithub && (
63
+ <Button
64
+ className="flex flex-row items-center gap-2"
65
+ variant="outline"
66
+ onClick={props.handleGithub}
67
+ >
68
+ <Icons.gitHub className="h-4 w-4" />
69
+ {props.texts?.continueWithGithub ?? "Continue With Github"}
70
+ </Button>
71
+ )}
72
+ {props.viaTwitter && (
73
+ <Button
74
+ className="flex flex-row items-center gap-2"
75
+ variant="outline"
76
+ onClick={props.handleTwitter}
77
+ >
78
+ <Icons.twitter className="h-4 w-4" />
79
+ {props.texts?.continueWithTwitter ?? "Continue With Twitter"}
80
+ </Button>
81
+ )}
82
+ {props.viaApple && (
83
+ <Button
84
+ className="flex flex-row items-center gap-2"
85
+ variant="outline"
86
+ onClick={props.handleApple}
87
+ >
88
+ <Icons.apple className="h-4 w-4" />
89
+ {props.texts?.continueWithApple ?? "Continue With Apple"}
90
+ </Button>
70
91
  )}
71
- {props.handleSignUp && (
72
- <Button onClick={props.handleSignUp}>{props.texts.signUp}</Button>
73
- )} */}
92
+ {props.viaMicrosoft && (
93
+ <Button
94
+ className="flex flex-row items-center gap-2"
95
+ variant="outline"
96
+ onClick={props.handleMicrosoft}
97
+ >
98
+ <Icons.microsoft className="h-4 w-4" />
99
+ {props.texts?.continueWithMicrosoft ?? "Continue With Microsoft"}
100
+ </Button>
101
+ )}
102
+ {props.viaEmail && (
103
+ <Button
104
+ className="flex flex-row items-center gap-2"
105
+ variant="outline"
106
+ onClick={props.handleEmail}
107
+ >
108
+ <Icons.mail className="h-4 w-4" />
109
+ {props.texts?.continueWithEmail ?? "Continue With Email"}
110
+ </Button>
111
+ )}
112
+ {props.viaPhone && (
113
+ <Button
114
+ className="flex flex-row items-center gap-2"
115
+ variant="outline"
116
+ onClick={props.handlePhone}
117
+ >
118
+ <Icons.phone className="h-4 w-4" />
119
+ {props.texts?.continueWithPhone ?? "Continue With Phone"}
120
+ </Button>
121
+ )}
122
+
74
123
  {!props.withoutSignUp && (
75
124
  <div className="p-3 text-center text-sm font-normal dark:text-gray-300">
76
125
  {props.texts.newUserText}{" "}
@@ -82,7 +131,6 @@ export const AppLanding: FC<AppLandingTypes> = (props) => {
82
131
  </span>
83
132
  </div>
84
133
  )}
85
-
86
134
  </CardContent>
87
135
  </Card>
88
136
  <div className="mt-6 flex flex-row justify-between">
@@ -25,6 +25,8 @@ type ResetPasswordType = {
25
25
  signUpText: string
26
26
  dontHaveAccount: string
27
27
  }
28
+ headless?: boolean
29
+ direction?: "rtl" | "ltr"
28
30
  }
29
31
 
30
32
  export const ResetPasswordForm: FC<ResetPasswordType> = (props) => {
@@ -36,17 +38,19 @@ export const ResetPasswordForm: FC<ResetPasswordType> = (props) => {
36
38
  control,
37
39
  } = methods
38
40
  return (
39
- <Card>
41
+ <Card dir={props.direction}>
40
42
  {!props.sent ? (
41
43
  <>
42
- <CardHeader>
43
- <CardTitle>Reset Password</CardTitle>
44
- <CardDescription>
45
- Enter your email to reset your account password
46
- </CardDescription>
47
- </CardHeader>
44
+ {!props.headless && (
45
+ <CardHeader>
46
+ <CardTitle>Reset Password</CardTitle>
47
+ <CardDescription>
48
+ Enter your email to reset your account password
49
+ </CardDescription>
50
+ </CardHeader>
51
+ )}
48
52
  <form onSubmit={handleSubmit(props.handleResetPassword)}>
49
- <CardContent>
53
+ <CardContent headless={props.headless}>
50
54
  <Controller
51
55
  control={control}
52
56
  name="email"
@@ -70,7 +74,7 @@ export const ResetPasswordForm: FC<ResetPasswordType> = (props) => {
70
74
  },
71
75
  }}
72
76
  />
73
- <div className=" pb-2 text-left text-sm dark:text-gray-300">
77
+ <div className="pb-2 text-start text-sm dark:text-gray-300">
74
78
  {props.texts?.dontHaveAccount ?? "Don't have an account? "}
75
79
  <span
76
80
  onClick={props.handleRouteToSignUp}
@@ -1,4 +1,4 @@
1
- import React, { FC } from "react"
1
+ import React, { FC, useEffect, useState } from "react"
2
2
  import { HawaTextField } from "../../elements"
3
3
  import { Controller, useForm } from "react-hook-form"
4
4
  import { Card, CardContent, CardFooter } from "../../elements/Card"
@@ -10,6 +10,8 @@ type CreditCardFormTypes = {
10
10
  }
11
11
 
12
12
  export const CreditCardForm: FC<CreditCardFormTypes> = (props) => {
13
+ const [cardNumber, setCardNumber] = useState("")
14
+ const [cardType, setCardType] = useState("")
13
15
  const methods = useForm()
14
16
  const {
15
17
  formState: { errors },
@@ -17,6 +19,56 @@ export const CreditCardForm: FC<CreditCardFormTypes> = (props) => {
17
19
  control,
18
20
  } = methods
19
21
 
22
+ const getCardType = (card_bin) => {
23
+ const visa_regex = /^4[0-9]{0,15}$/m
24
+ const mastercard_regex = /^5$|^5[0-5][0-9]{0,16}$/m
25
+ const amex_regex = /^3$|^3[47][0-9]{0,13}$/m
26
+ const mada_regex =
27
+ /^(440647|440795|446404|457865|968208|457997|474491|636120|417633|468540|468541|468542|468543|968201|446393|409201|458456|484783|462220|455708|410621|455036|486094|486095|486096|504300|440533|489318|489319|445564|968211|410685|406996|432328|428671|428672|428673|968206|446672|543357|434107|407197|407395|412565|431361|604906|521076|529415|535825|543085|524130|554180|549760|968209|524514|529741|537767|535989|536023|513213|520058|558563|588982|589005|531095|530906|532013|968204|422817|422818|422819|428331|483010|483011|483012|589206|968207|419593|439954|530060|531196|420132)/
28
+ const meeza_regex =
29
+ /^507803[0-6][0-9]|507808[3-9][0-9]|507809[0-9][0-9]|507810[0-2][0-9]/
30
+ let card_type = "visa"
31
+ if (card_bin.replace(/[^\d]/g, "").match(mada_regex)) {
32
+ card_type = "mada"
33
+ } else if (card_bin.replace(/[^\d]/g, "").match(meeza_regex)) {
34
+ card_type = "meeza"
35
+ } else if (card_bin.replace(/[^\d]/g, "").match(visa_regex)) {
36
+ card_type = "visa"
37
+ } else if (card_bin.replace(/[^\d]/g, "").match(mastercard_regex)) {
38
+ card_type = "mastercard"
39
+ } else if (card_bin.replace(/[^\d]/g, "").match(amex_regex)) {
40
+ card_type = "amex"
41
+ }
42
+ return card_type
43
+ }
44
+ const onCardNumberChange = (event) => {
45
+ let { value, name } = event.target
46
+ let cardNumber = value
47
+ value = value.replace(/\D/g, "")
48
+ if (/^3[47]\d{0,13}$/.test(value)) {
49
+ cardNumber = value
50
+ .replace(/(\d{4})/, "$1 ")
51
+ .replace(/(\d{4}) (\d{6})/, "$1 $2 ")
52
+ } else if (/^3(?:0[0-5]|[68]\d)\d{0,11}$/.test(value)) {
53
+ // diner's club, 14 digits
54
+ cardNumber = value
55
+ .replace(/(\d{4})/, "$1 ")
56
+ .replace(/(\d{4}) (\d{6})/, "$1 $2 ")
57
+ } else if (/^\d{0,16}$/.test(value)) {
58
+ // regular cc number, 16 digits
59
+ cardNumber = value
60
+ .replace(/(\d{4})/, "$1 ")
61
+ .replace(/(\d{4}) (\d{4})/, "$1 $2 ")
62
+ .replace(/(\d{4}) (\d{4}) (\d{4})/, "$1 $2 $3 ")
63
+ }
64
+ console.log("card number is ", cardNumber.trimRight())
65
+ setCardNumber(cardNumber.trimRight())
66
+ // onUpdateState(name, cardNumber);
67
+ }
68
+ useEffect(() => {
69
+ let cardTypeSlug = getCardType(cardNumber)
70
+ setCardType(cardTypeSlug)
71
+ })
20
72
  return (
21
73
  <Card>
22
74
  <form onSubmit={handleSubmit(props.handle)}>
@@ -24,15 +76,24 @@ export const CreditCardForm: FC<CreditCardFormTypes> = (props) => {
24
76
  <div className="flex flex-row gap-4">
25
77
  <Controller
26
78
  control={control}
27
- name="cardName"
79
+ name="cardNumber"
28
80
  render={({ field }) => (
29
81
  <HawaTextField
30
82
  width="full"
31
83
  name="cardNumber"
32
84
  placeholder="1234 1234 1234 1234"
33
85
  type="number"
86
+ onChange={onCardNumberChange}
87
+ // onChange={(e) => setCardNumber(e.target.value)}
34
88
  label="Card Number"
35
89
  helpertext={errors.password?.message}
90
+ iconInside={
91
+ <img
92
+ src={`https://sikka-images.s3.ap-southeast-1.amazonaws.com/payment-symbols/borderless/${cardType}.png`}
93
+ alt=""
94
+ className="h-8"
95
+ />
96
+ }
36
97
  />
37
98
  )}
38
99
  rules={{
@@ -19,6 +19,8 @@ const buttonVariants = cva(
19
19
  "bg-secondary text-secondary-foreground hover:bg-secondary/80",
20
20
  ghost: "hover:bg-accent hover:text-accent-foreground",
21
21
  link: "text-primary underline-offset-4 hover:underline",
22
+ neoBrutalism:
23
+ "cursor-pointer transition-all uppercase font-mono dark:bg-black font-bold py-2 px-4 rounded border-2 border-primary shadow-color-primary transition-[transform_50ms, box-shadow_50ms] active:translate-x-0.5 active:translate-y-0.5 active:shadow-color-primary-active",
22
24
  },
23
25
  size: {
24
26
  default: "h-10 px-4 py-2",
@@ -59,6 +61,13 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
59
61
  ref
60
62
  ) => {
61
63
  const Comp = "button"
64
+
65
+ // Determine the color for the HawaLoading component based on the variant
66
+ const loadingColor =
67
+ variant === "outline" || variant === "ghost" || variant === "neoBrutalism"
68
+ ? "bg-primary"
69
+ : "bg-primary-foreground"
70
+
62
71
  return (
63
72
  <Comp
64
73
  className={cn(buttonVariants({ variant, size, className }))}
@@ -68,7 +77,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
68
77
  {isLoading ? (
69
78
  <HawaLoading
70
79
  design="dots-pulse"
71
- color="bg-primary-foreground"
80
+ color={loadingColor} // Apply the computed color here
72
81
  size="button"
73
82
  />
74
83
  ) : (