@sikka/hawa 0.1.92 → 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/index.d.mts +36 -9
- package/dist/index.d.ts +36 -9
- package/dist/index.js +251 -102
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +776 -631
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +89 -9
- package/package.json +1 -1
- package/src/blocks/Payment/CreditCardForm.tsx +63 -2
- package/src/elements/HawaRadio.tsx +13 -13
- package/src/elements/HawaTextField.tsx +7 -2
- package/src/elements/StickyFeatures.tsx +53 -0
- package/src/elements/UserReferralSource.tsx +101 -0
- package/src/elements/index.ts +2 -0
- package/src/styles.css +89 -9
- package/src/tailwind.css +7 -7
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:
|
|
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(--
|
|
473
|
+
color: hsl(var(--primary));
|
|
474
|
+
|
|
474
475
|
}
|
|
475
476
|
.link {
|
|
476
|
-
color: var(--
|
|
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:
|
|
535
|
+
left: 3px;
|
|
535
536
|
content: " ";
|
|
536
537
|
display: block;
|
|
537
|
-
background: var(--
|
|
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(--
|
|
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;
|
|
@@ -2527,6 +2559,12 @@ video {
|
|
|
2527
2559
|
.leading-4 {
|
|
2528
2560
|
line-height: 1rem;
|
|
2529
2561
|
}
|
|
2562
|
+
.leading-7 {
|
|
2563
|
+
line-height: 1.75rem;
|
|
2564
|
+
}
|
|
2565
|
+
.leading-8 {
|
|
2566
|
+
line-height: 2rem;
|
|
2567
|
+
}
|
|
2530
2568
|
.leading-\[25px\] {
|
|
2531
2569
|
line-height: 25px;
|
|
2532
2570
|
}
|
|
@@ -2611,6 +2649,10 @@ video {
|
|
|
2611
2649
|
--tw-text-opacity: 1;
|
|
2612
2650
|
color: rgb(21 128 61 / var(--tw-text-opacity));
|
|
2613
2651
|
}
|
|
2652
|
+
.text-indigo-600 {
|
|
2653
|
+
--tw-text-opacity: 1;
|
|
2654
|
+
color: rgb(79 70 229 / var(--tw-text-opacity));
|
|
2655
|
+
}
|
|
2614
2656
|
.text-info-foreground {
|
|
2615
2657
|
--tw-text-opacity: 1;
|
|
2616
2658
|
color: hsl(var(--info-foreground) / var(--tw-text-opacity));
|
|
@@ -4024,9 +4066,8 @@ body {
|
|
|
4024
4066
|
--tw-ring-opacity: 1;
|
|
4025
4067
|
--tw-ring-color: rgb(31 41 55 / var(--tw-ring-opacity));
|
|
4026
4068
|
}
|
|
4027
|
-
:is(.dark .peer:checked ~ .dark\:peer-checked\:text-
|
|
4028
|
-
|
|
4029
|
-
color: rgb(59 130 246 / var(--tw-text-opacity));
|
|
4069
|
+
:is(.dark .peer:checked ~ .dark\:peer-checked\:text-primary) {
|
|
4070
|
+
color: hsl(var(--primary));
|
|
4030
4071
|
}
|
|
4031
4072
|
@media (min-width: 440px) {
|
|
4032
4073
|
|
|
@@ -4104,6 +4145,11 @@ body {
|
|
|
4104
4145
|
padding: 5rem;
|
|
4105
4146
|
}
|
|
4106
4147
|
|
|
4148
|
+
.sm\:py-32 {
|
|
4149
|
+
padding-top: 8rem;
|
|
4150
|
+
padding-bottom: 8rem;
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4107
4153
|
.sm\:text-left {
|
|
4108
4154
|
text-align: left;
|
|
4109
4155
|
}
|
|
@@ -4113,6 +4159,11 @@ body {
|
|
|
4113
4159
|
line-height: 2rem;
|
|
4114
4160
|
}
|
|
4115
4161
|
|
|
4162
|
+
.sm\:text-4xl {
|
|
4163
|
+
font-size: 2.25rem;
|
|
4164
|
+
line-height: 2.5rem;
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4116
4167
|
.sm\:text-base {
|
|
4117
4168
|
font-size: 1rem;
|
|
4118
4169
|
line-height: 1.5rem;
|
|
@@ -4139,6 +4190,14 @@ body {
|
|
|
4139
4190
|
}
|
|
4140
4191
|
@media (min-width: 768px) {
|
|
4141
4192
|
|
|
4193
|
+
.md\:sticky {
|
|
4194
|
+
position: sticky;
|
|
4195
|
+
}
|
|
4196
|
+
|
|
4197
|
+
.md\:top-10 {
|
|
4198
|
+
top: 2.5rem;
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4142
4201
|
.md\:mb-0 {
|
|
4143
4202
|
margin-bottom: 0px;
|
|
4144
4203
|
}
|
|
@@ -4159,6 +4218,10 @@ body {
|
|
|
4159
4218
|
margin-right: 1rem;
|
|
4160
4219
|
}
|
|
4161
4220
|
|
|
4221
|
+
.md\:mt-0 {
|
|
4222
|
+
margin-top: 0px;
|
|
4223
|
+
}
|
|
4224
|
+
|
|
4162
4225
|
.md\:h-auto {
|
|
4163
4226
|
height: auto;
|
|
4164
4227
|
}
|
|
@@ -4167,6 +4230,10 @@ body {
|
|
|
4167
4230
|
width: 12rem;
|
|
4168
4231
|
}
|
|
4169
4232
|
|
|
4233
|
+
.md\:w-\[28rem\] {
|
|
4234
|
+
width: 28rem;
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4170
4237
|
.md\:w-full {
|
|
4171
4238
|
width: 100%;
|
|
4172
4239
|
}
|
|
@@ -4251,6 +4318,10 @@ body {
|
|
|
4251
4318
|
max-width: 80rem;
|
|
4252
4319
|
}
|
|
4253
4320
|
|
|
4321
|
+
.lg\:max-w-none {
|
|
4322
|
+
max-width: none;
|
|
4323
|
+
}
|
|
4324
|
+
|
|
4254
4325
|
.lg\:columns-4 {
|
|
4255
4326
|
-moz-columns: 4;
|
|
4256
4327
|
columns: 4;
|
|
@@ -4263,6 +4334,15 @@ body {
|
|
|
4263
4334
|
.lg\:grid-cols-4 {
|
|
4264
4335
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
4265
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
|
+
}
|
|
4266
4346
|
}
|
|
4267
4347
|
@media (min-width: 1280px) {
|
|
4268
4348
|
|
package/package.json
CHANGED
|
@@ -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="
|
|
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={{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, FC, useRef, useEffect } from "react"
|
|
2
|
-
import
|
|
2
|
+
import { cn } from "../util"
|
|
3
3
|
|
|
4
4
|
type RadioTypes = {
|
|
5
5
|
orientation?: "vertical" | "horizontal"
|
|
@@ -49,7 +49,7 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
49
49
|
return (
|
|
50
50
|
<ul
|
|
51
51
|
ref={ref}
|
|
52
|
-
className={
|
|
52
|
+
className={cn(
|
|
53
53
|
props.options?.length > 2
|
|
54
54
|
? "flex-wrap xs:max-w-full xs:flex-nowrap"
|
|
55
55
|
: "",
|
|
@@ -65,7 +65,7 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
65
65
|
setSelectedOption(opt.value)
|
|
66
66
|
props.onChangeTab(opt.value)
|
|
67
67
|
}}
|
|
68
|
-
className={
|
|
68
|
+
className={cn(
|
|
69
69
|
"w-full cursor-pointer",
|
|
70
70
|
orientation === "horizontal" &&
|
|
71
71
|
parentDirection === "ltr" &&
|
|
@@ -89,7 +89,7 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
89
89
|
)
|
|
90
90
|
case "bordered":
|
|
91
91
|
return (
|
|
92
|
-
<div className={
|
|
92
|
+
<div className={cn(orientationStyle[orientation], "gap-4")}>
|
|
93
93
|
{props.options.map((opt, i) => (
|
|
94
94
|
<div className="rounded border border-gray-200 ">
|
|
95
95
|
<div
|
|
@@ -106,7 +106,7 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
106
106
|
/>
|
|
107
107
|
<label
|
|
108
108
|
htmlFor={opt.value.toString()}
|
|
109
|
-
className={
|
|
109
|
+
className={cn(
|
|
110
110
|
"ml-2 w-full p-4 pl-3 text-sm font-medium dark:text-white",
|
|
111
111
|
opt.disabled ? "opacity-50" : "cursor-pointer text-gray-900"
|
|
112
112
|
)}
|
|
@@ -120,7 +120,7 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
120
120
|
)
|
|
121
121
|
case "cards":
|
|
122
122
|
return (
|
|
123
|
-
<ul className={
|
|
123
|
+
<ul className={cn(orientationStyle[orientation], "gap-4")}>
|
|
124
124
|
{props.options?.map((opt: any, o) => (
|
|
125
125
|
<li>
|
|
126
126
|
<input
|
|
@@ -134,11 +134,11 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
134
134
|
/>
|
|
135
135
|
<label
|
|
136
136
|
htmlFor={opt.value.toString()}
|
|
137
|
-
className={
|
|
138
|
-
"inline-flex h-full w-full items-center justify-between rounded-lg border border-gray-200 bg-white p-5 text-gray-500 peer-checked:border-blue-600 peer-checked:text-blue-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400
|
|
137
|
+
className={cn(
|
|
138
|
+
"inline-flex h-full w-full items-center justify-between rounded-lg border border-gray-200 bg-white p-5 text-gray-500 peer-checked:border-blue-600 peer-checked:text-blue-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:peer-checked:text-primary",
|
|
139
139
|
opt.disabled
|
|
140
140
|
? "opacity-50"
|
|
141
|
-
: "cursor-pointer hover:bg-gray-100 hover:text-gray-600"
|
|
141
|
+
: "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 dark:hover:text-gray-300 hover:text-gray-600"
|
|
142
142
|
)}
|
|
143
143
|
>
|
|
144
144
|
<div className="block h-full w-full">
|
|
@@ -169,10 +169,10 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
169
169
|
|
|
170
170
|
default:
|
|
171
171
|
return (
|
|
172
|
-
<div className={orientationStyle[orientation]}>
|
|
172
|
+
<div className={cn(orientationStyle[orientation], "gap-2")}>
|
|
173
173
|
{props.options.map((opt, i) => (
|
|
174
174
|
<div
|
|
175
|
-
className="radio-item radio-item-default
|
|
175
|
+
className="radio-item radio-item-default flex items-center transition-all"
|
|
176
176
|
key={i + 1}
|
|
177
177
|
>
|
|
178
178
|
<input
|
|
@@ -185,8 +185,8 @@ export const HawaRadio: FC<RadioTypes> = ({
|
|
|
185
185
|
/>
|
|
186
186
|
<label
|
|
187
187
|
htmlFor={opt.value.toString()}
|
|
188
|
-
className={
|
|
189
|
-
"
|
|
188
|
+
className={cn(
|
|
189
|
+
"text-sm font-medium dark:text-white",
|
|
190
190
|
opt.disabled
|
|
191
191
|
? "text-gray-400"
|
|
192
192
|
: "cursor-pointer text-gray-900"
|
|
@@ -32,6 +32,7 @@ type TextFieldTypes = {
|
|
|
32
32
|
preview?: boolean
|
|
33
33
|
autoComplete?: any
|
|
34
34
|
maxLength?: any
|
|
35
|
+
iconInside?: React.ReactNode
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export const HawaTextField: FC<TextFieldTypes> = ({
|
|
@@ -79,12 +80,16 @@ export const HawaTextField: FC<TextFieldTypes> = ({
|
|
|
79
80
|
className={cn(
|
|
80
81
|
defaultInputStyle,
|
|
81
82
|
props.icon && "pl-10",
|
|
82
|
-
preview && "border-transparent bg-transparent px-0"
|
|
83
|
+
preview && "border-transparent bg-transparent px-0"
|
|
83
84
|
)}
|
|
84
85
|
disabled={preview}
|
|
85
86
|
/>
|
|
86
87
|
</div>
|
|
87
|
-
|
|
88
|
+
{props.iconInside && (
|
|
89
|
+
<div className="absolute right-1 top-[41px] -translate-y-1/2">
|
|
90
|
+
{props.iconInside}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
88
93
|
{props.helpertext ? (
|
|
89
94
|
<p className="mb-0 mt-1 text-xs text-red-600 dark:text-red-500">
|
|
90
95
|
{props.helpertext}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
interface Feature {
|
|
4
|
+
icon: React.ReactNode
|
|
5
|
+
title: string
|
|
6
|
+
description: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type StickyFeaturesType = {
|
|
10
|
+
features?: Feature[]
|
|
11
|
+
tag?: string
|
|
12
|
+
title?: string
|
|
13
|
+
description?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const StickyFeatures: React.FC<StickyFeaturesType> = (props) => {
|
|
17
|
+
return (
|
|
18
|
+
<div className="bg-white py-24 sm:py-32">
|
|
19
|
+
|
|
20
|
+
<div className="mx-auto flex max-w-5xl flex-col items-start gap-10 px-6 md:flex-row lg:px-8">
|
|
21
|
+
<div className="w-full md:sticky md:top-10 md:w-[28rem]">
|
|
22
|
+
<h2 className="text-lg font-semibold leading-8 tracking-tight text-indigo-600">
|
|
23
|
+
{props.tag}
|
|
24
|
+
</h2>
|
|
25
|
+
<p className="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
|
26
|
+
{props.title}
|
|
27
|
+
</p>
|
|
28
|
+
<p className="mb-2 mt-6 text-base leading-7 text-gray-600">
|
|
29
|
+
{props.description}
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
<div className="mt-5 w-full min-w-0 flex-1 md:mt-0">
|
|
33
|
+
<dl className="grid grid-cols-1 gap-x-8 gap-y-10 md:max-w-xl lg:max-w-none lg:gap-y-16">
|
|
34
|
+
{props.features.map((f) => (
|
|
35
|
+
<div className="relative rounded-lg bg-gray-50 p-10">
|
|
36
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-indigo-600">
|
|
37
|
+
{f.icon}
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<dt className="mt-4 text-lg font-semibold leading-7 text-gray-900">
|
|
41
|
+
{f.title}
|
|
42
|
+
</dt>
|
|
43
|
+
<dd className="mt-2 text-base leading-7 text-gray-600">
|
|
44
|
+
{f.description}
|
|
45
|
+
</dd>
|
|
46
|
+
</div>
|
|
47
|
+
))}
|
|
48
|
+
</dl>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { FC, useEffect, useRef, useState } from "react"
|
|
2
|
+
import clsx from "clsx"
|
|
3
|
+
import { HawaButton } from "./HawaButton"
|
|
4
|
+
import { Button } from "./Button"
|
|
5
|
+
import { HawaRadio } from "./HawaRadio"
|
|
6
|
+
import { Card, CardContent, CardHeader, CardTitle } from "./Card"
|
|
7
|
+
import { HawaTextField } from "./HawaTextField"
|
|
8
|
+
import { Textarea } from "./Textarea"
|
|
9
|
+
|
|
10
|
+
type ComponentTypes = {
|
|
11
|
+
title?: string
|
|
12
|
+
question: string
|
|
13
|
+
options?: []
|
|
14
|
+
texts?: {
|
|
15
|
+
least: string
|
|
16
|
+
most: string
|
|
17
|
+
}
|
|
18
|
+
position?: "bottom-right" | "bottom-left"
|
|
19
|
+
onOptionClicked?: (option) => void
|
|
20
|
+
}
|
|
21
|
+
export const UserReferralSource: FC<ComponentTypes> = ({
|
|
22
|
+
position = "bottom-right",
|
|
23
|
+
...props
|
|
24
|
+
}) => {
|
|
25
|
+
const [closed, setClosed] = useState(false)
|
|
26
|
+
const [answered, setAnswered] = useState(false)
|
|
27
|
+
const [clickedOption, setClickedOption] = useState(null)
|
|
28
|
+
const [closingTimer, setClosingTimer] = useState(5)
|
|
29
|
+
const popUpRef = useRef(null)
|
|
30
|
+
|
|
31
|
+
const boxPosition = {
|
|
32
|
+
"bottom-right": "right-4",
|
|
33
|
+
"bottom-left": "left-4",
|
|
34
|
+
}
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
//To change opacity and hide the component
|
|
37
|
+
const timeoutHide = setTimeout(() => {
|
|
38
|
+
if (closingTimer >= 0) {
|
|
39
|
+
setClosingTimer(closingTimer - 1)
|
|
40
|
+
}
|
|
41
|
+
}, 1000)
|
|
42
|
+
|
|
43
|
+
return () => {
|
|
44
|
+
clearTimeout(timeoutHide)
|
|
45
|
+
}
|
|
46
|
+
}, [closingTimer])
|
|
47
|
+
|
|
48
|
+
const slowClose = () => {
|
|
49
|
+
setClosed(true)
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
popUpRef.current.removeChild(popUpRef.current.children[0])
|
|
52
|
+
}, 200)
|
|
53
|
+
}
|
|
54
|
+
return (
|
|
55
|
+
<Card
|
|
56
|
+
ref={popUpRef}
|
|
57
|
+
className={clsx("fixed bottom-4 p-4 ", boxPosition[position])}
|
|
58
|
+
>
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
className="absolute right-2 top-2 inline-flex h-8 w-8 rounded p-1.5 text-gray-400 transition-all hover:bg-gray-100 hover:text-gray-900 focus:ring-2 focus:ring-gray-300 dark:bg-gray-800 dark:text-gray-500 dark:hover:bg-gray-700 dark:hover:text-white"
|
|
62
|
+
data-dismiss-target="#toast-default"
|
|
63
|
+
aria-label="Close"
|
|
64
|
+
onClick={() => slowClose()}
|
|
65
|
+
>
|
|
66
|
+
<svg
|
|
67
|
+
aria-hidden="true"
|
|
68
|
+
className="h-5 w-5"
|
|
69
|
+
fill="currentColor"
|
|
70
|
+
viewBox="0 0 20 20"
|
|
71
|
+
>
|
|
72
|
+
<path
|
|
73
|
+
fillRule="evenodd"
|
|
74
|
+
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
|
75
|
+
clipRule="evenodd"
|
|
76
|
+
></path>
|
|
77
|
+
</svg>
|
|
78
|
+
</button>
|
|
79
|
+
<CardContent headless>
|
|
80
|
+
<div
|
|
81
|
+
className={clsx(
|
|
82
|
+
"flex flex-col gap-4", // "relative flex w-full max-w-sm flex-col gap-2 rounded border bg-background p-4 shadow-md transition-all",
|
|
83
|
+
closed ? "opacity-0" : "opacity-100"
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
<div className="mt-4 font-bold">{props.question}</div>
|
|
87
|
+
<div className="flex w-full flex-row gap-1 rounded ">
|
|
88
|
+
<HawaRadio
|
|
89
|
+
orientation="vertical"
|
|
90
|
+
options={props.options}
|
|
91
|
+
></HawaRadio>
|
|
92
|
+
</div>
|
|
93
|
+
<div>
|
|
94
|
+
<Textarea />
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
<Button className="mt-4 w-full">Submit</Button>
|
|
98
|
+
</CardContent>
|
|
99
|
+
</Card>
|
|
100
|
+
)
|
|
101
|
+
}
|