@sikka/hawa
Version:
Modern UI Kit made with Tailwind
508 lines (503 loc) • 20.9 kB
JavaScript
"use client";
import {
Textarea
} from "../../chunk-O356IC37.mjs";
import {
Select
} from "../../chunk-2NFENSLV.mjs";
import {
Popover,
Radio
} from "../../chunk-UP7VUUVQ.mjs";
import {
BadEmoji,
GoodEmoji,
VeryBadEmoji,
VeryGoodEmoji
} from "../../chunk-DDWOF6SP.mjs";
import {
Button,
Card,
CardContent,
cn
} from "../../chunk-5MN7WB7B.mjs";
// blocks/feedback/UserReferralSource.tsx
import React, { useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
var UserReferralSource = ({
position = "bottom-right",
options = [],
...props
}) => {
var _a, _b;
const [closed, setClosed] = useState(false);
const popUpRef = useRef(null);
const formSchema = z.object({
source: z.string({ required_error: (_a = props.texts) == null ? void 0 : _a.pleaseSelectOption }),
feedback: z.string().optional()
});
const { handleSubmit, control, formState, watch } = useForm({
resolver: zodResolver(formSchema)
});
const selectedSource = watch("source");
const boxPosition = {
"bottom-right": "hawa-right-4",
"bottom-left": "hawa-left-4"
};
const optionsWithOther = [
...options,
{
value: "other",
label: "Other"
}
];
return /* @__PURE__ */ React.createElement(
"div",
{
className: cn(
"hawa-transition-all",
closed ? "hawa-opacity-0" : "hawa-opacity-100"
),
ref: popUpRef
},
/* @__PURE__ */ React.createElement(
Card,
{
className: cn(
"hawa-fixed hawa-bottom-4 hawa-p-0 ",
boxPosition[position]
),
dir: props.direction
},
/* @__PURE__ */ React.createElement(
"button",
{
type: "button",
className: cn(
props.direction === "rtl" ? "hawa-left-2" : "hawa-right-2",
"hawa-absolute hawa-top-2 hawa-inline-flex hawa-h-8 hawa-w-8 hawa-rounded hawa-p-1.5 hawa-text-gray-400 hawa-transition-all hover:hawa-bg-gray-100 hover:hawa-text-gray-900 focus:hawa-ring-2 focus:hawa-ring-gray-300 dark:hawa-bg-gray-800 dark:hawa-text-gray-500 dark:hover:hawa-bg-gray-700 dark:hover:hawa-text-white"
),
"data-dismiss-target": "#toast-default",
"aria-label": "Close",
onClick: () => {
setClosed(true);
setTimeout(() => {
if (popUpRef == null ? void 0 : popUpRef.current) {
popUpRef == null ? void 0 : popUpRef.current.removeChild(popUpRef == null ? void 0 : popUpRef.current.children[0]);
}
}, 200);
}
},
/* @__PURE__ */ React.createElement(
"svg",
{
"aria-hidden": "true",
className: "hawa-h-5 hawa-w-5",
fill: "currentColor",
viewBox: "0 0 20 20"
},
/* @__PURE__ */ React.createElement(
"path",
{
fillRule: "evenodd",
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",
clipRule: "evenodd"
}
)
)
),
/* @__PURE__ */ React.createElement(CardContent, { headless: true }, /* @__PURE__ */ React.createElement(
"form",
{
noValidate: true,
onSubmit: handleSubmit((e) => {
if (props.onSubmitForm) {
props.onSubmitForm(e);
} else {
console.log("onSubmitForm was not provided");
}
})
},
/* @__PURE__ */ React.createElement(
"div",
{
className: cn(
"hawa-flex hawa-flex-col hawa-gap-4 hawa-transition-all",
closed ? "hawa-opacity-0" : "hawa-opacity-100"
)
},
/* @__PURE__ */ React.createElement("div", { className: "hawa-mt-4 hawa-font-bold" }, props.question),
/* @__PURE__ */ React.createElement("div", { className: "hawa-flex hawa-w-full hawa-flex-row hawa-gap-1 hawa-rounded " }, /* @__PURE__ */ React.createElement(
Controller,
{
control,
name: "source",
render: ({ field }) => {
var _a2, _b2;
return /* @__PURE__ */ React.createElement(
Radio,
{
name: "source",
direction: props.direction,
orientation: "vertical",
options: optionsWithOther,
defaultValue: field.value,
onChange: (e) => field.onChange(e),
helperText: (_b2 = (_a2 = formState.errors.source) == null ? void 0 : _a2.message) == null ? void 0 : _b2.toString()
}
);
}
}
)),
/* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
Controller,
{
control,
name: "feedback",
render: ({ field }) => {
var _a2, _b2;
return /* @__PURE__ */ React.createElement(
Textarea,
{
...field,
textareaProps: {
onChange: (e) => field.onChange(e.target.value),
disabled: selectedSource !== "other"
},
helperText: (_b2 = (_a2 = formState.errors.feedback) == null ? void 0 : _a2.message) == null ? void 0 : _b2.toString()
}
);
}
}
))
),
/* @__PURE__ */ React.createElement(Button, { type: "submit", className: "hawa-mt-4 hawa-w-full" }, ((_b = props.texts) == null ? void 0 : _b.submit) || "Submit")
))
)
);
};
// blocks/feedback/FeedbackRating.tsx
import React2, { useEffect, useRef as useRef2, useState as useState2 } from "react";
var FeedbackRating = ({
position = "bottom-right",
...props
}) => {
const [closed, setClosed] = useState2(false);
const [answered, setAnswered] = useState2(false);
const [clickedOption, setClickedOption] = useState2(null);
const [closingTimer, setClosingTimer] = useState2(5);
const popUpRef = useRef2(null);
const boxPosition = {
"bottom-right": "hawa-right-4",
"bottom-left": "hawa-left-4"
};
useEffect(() => {
const timeoutHide = setTimeout(() => {
if (closingTimer >= 0) {
setClosingTimer(closingTimer - 1);
}
}, 1e3);
return () => {
clearTimeout(timeoutHide);
};
}, [closingTimer]);
const slowClose = () => {
setClosed(true);
setTimeout(() => {
if (popUpRef.current) {
popUpRef.current.removeChild(popUpRef.current.children[0]);
}
}, 200);
};
return /* @__PURE__ */ React2.createElement(
"div",
{
ref: popUpRef,
className: cn(
props.banner ? "hawa-fixed hawa-bottom-0 hawa-left-0 hawa-w-full hawa-px-0 md:hawa-px-4" : "hawa-fixed hawa-bottom-4",
boxPosition[position]
)
},
/* @__PURE__ */ React2.createElement(
"div",
{
className: cn(
"hawa-relative hawa-flex hawa-w-full hawa-flex-col hawa-gap-2 hawa-rounded hawa-border hawa-bg-background hawa-p-4 hawa-shadow-md hawa-transition-all",
closed ? "hawa-opacity-0" : "hawa-opacity-100",
props.banner && "hawa-rounded-none hawa-px-4 md:hawa-rounded-t md:hawa-px-64"
)
},
/* @__PURE__ */ React2.createElement("div", { className: "hawa-absolute hawa-left-2 hawa-top-2 hawa-p-1.5 hawa-text-sm" }, props.title),
/* @__PURE__ */ React2.createElement(
"button",
{
type: "button",
className: "hawa-absolute hawa-right-2 hawa-top-2 hawa-inline-flex hawa-h-8 hawa-w-8 hawa-rounded hawa-p-1.5 hawa-text-gray-400 hover:hawa-bg-gray-100 hover:hawa-text-gray-900 focus:hawa-ring-2 focus:hawa-ring-gray-300 dark:hawa-bg-gray-800 dark:hawa-text-gray-500 dark:hover:hawa-bg-gray-700 dark:hover:hawa-text-white",
"data-dismiss-target": "#toast-default",
"aria-label": "Close",
onClick: () => slowClose()
},
/* @__PURE__ */ React2.createElement(
"svg",
{
"aria-hidden": "true",
className: "hawa-h-5 hawa-w-5",
fill: "currentColor",
viewBox: "0 0 20 20"
},
/* @__PURE__ */ React2.createElement(
"path",
{
fillRule: "evenodd",
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",
clipRule: "evenodd"
}
)
)
),
/* @__PURE__ */ React2.createElement("div", { className: "hawa-mt-8" }, props.question),
/* @__PURE__ */ React2.createElement("div", { className: "hawa-flex hawa-w-full hawa-flex-row hawa-gap-1 hawa-rounded" }, props.options && props.options.map((op, i) => /* @__PURE__ */ React2.createElement(
"span",
{
key: i,
onClick: () => {
if (props.onOptionClicked) {
props.onOptionClicked(op);
}
setClickedOption(op);
setAnswered(true);
const timeoutDestroy = setTimeout(() => {
setClosed(true);
}, 4800);
setTimeout(() => {
var _a, _b;
(_b = popUpRef.current) == null ? void 0 : _b.removeChild(
(_a = popUpRef.current) == null ? void 0 : _a.children[0]
);
clearTimeout(timeoutDestroy);
}, 5300);
},
className: cn(
"hawa-w-full hawa-cursor-pointer hawa-rounded hawa-border hawa-p-4 hawa-text-center hawa-transition-all",
clickedOption === op ? "hawa-bg-gray-500 hawa-text-white" : "hawa-border hawa-bg-background hover:hawa-bg-gray-300 dark:hover:hawa-bg-gray-700"
)
},
op
))),
props.texts && /* @__PURE__ */ React2.createElement("div", { className: "hawa-flex hawa-flex-row hawa-justify-between hawa-text-xs" }, /* @__PURE__ */ React2.createElement("span", null, props.texts.least), /* @__PURE__ */ React2.createElement("span", null, props.texts.most)),
answered && /* @__PURE__ */ React2.createElement("div", { className: "hawa-absolute hawa-left-0 hawa-top-0 hawa-flex hawa-h-full hawa-w-full hawa-flex-col hawa-items-center hawa-justify-center hawa-gap-2 hawa-rounded hawa-bg-black hawa-bg-opacity-80 hawa-p-4 hawa-text-center hawa-transition-all" }, /* @__PURE__ */ React2.createElement("span", { className: "hawa-font-bold hawa-text-white" }, "Thank you for your answer. This box will disappear in", " " + closingTimer, " seconds"), /* @__PURE__ */ React2.createElement("div", { className: "hawa-flex hawa-flex-row hawa-gap-2" }, /* @__PURE__ */ React2.createElement(Button, { variant: "secondary", onClick: () => slowClose() }, "Close")))
)
);
};
// blocks/feedback/FeedbackEmoji.tsx
import React3, { useState as useState3 } from "react";
var FeedbackEmoji = (props) => {
const [selectedEmoji, setSelectedEmoji] = useState3(null);
const [loadingSubmit, setLoadingSubmit] = useState3(false);
const [feedbackText, setFeedbackText] = useState3("");
const [helperText, setHelperText] = useState3(false);
let emojis = [
{ icon: /* @__PURE__ */ React3.createElement(VeryGoodEmoji, null), value: "very-good" },
{ icon: /* @__PURE__ */ React3.createElement(GoodEmoji, null), value: "good" },
{ icon: /* @__PURE__ */ React3.createElement(BadEmoji, null), value: "bad" },
{ icon: /* @__PURE__ */ React3.createElement(VeryBadEmoji, null), value: "very-bad" }
];
const onFeedbackSubmit = async () => {
if (feedbackText) {
setLoadingSubmit(true);
try {
await props.handleSubmit({
choice: selectedEmoji,
feedback: feedbackText
});
} catch (error) {
console.error("Error during submission:", error);
setLoadingSubmit(false);
}
await setLoadingSubmit(false);
} else {
setLoadingSubmit(false);
setHelperText(true);
}
};
return /* @__PURE__ */ React3.createElement(
"div",
{
className: cn(
"hawa-flex hawa-flex-col hawa-rounded hawa-border hawa-p-2 hawa-transition-all",
selectedEmoji ? "hawa-h-[189px] hawa-min-w-fit" : "hawa-h-[44px]"
)
},
/* @__PURE__ */ React3.createElement("div", { className: "hawa-flex hawa-flex-row hawa-items-center hawa-justify-center hawa-gap-2" }, /* @__PURE__ */ React3.createElement("div", { className: "hawa-flex hawa-flex-row hawa-justify-center hawa-gap-0.5" }, emojis.map((emoji, i) => /* @__PURE__ */ React3.createElement(
Button,
{
key: i,
onClick: () => {
if (selectedEmoji === emoji.value) {
setSelectedEmoji("");
} else {
setSelectedEmoji(emoji.value);
}
},
variant: "ghost",
size: "smallIcon",
className: cn(
selectedEmoji === emoji.value ? "hawa-bg-primary/10 hover:hawa-bg-primary/10" : "hawa-text-[#666666]"
)
},
emoji.icon
)))),
/* @__PURE__ */ React3.createElement(
"div",
{
className: cn(
"hawa-flex hawa-flex-col hawa-overflow-clip hawa-transition-all hawa-duration-500 hawa-ease-in-out",
selectedEmoji ? "hawa-visible hawa-opacity-100" : "hawa-invisible hawa-opacity-0"
)
},
props.showSuccess ? /* @__PURE__ */ React3.createElement("div", { className: "hawa-flex hawa-h-full hawa-flex-col hawa-items-center hawa-justify-center hawa-gap-2 hawa-pt-4" }, /* @__PURE__ */ React3.createElement("div", { className: "hawa-rounded hawa-bg-primary hawa-p-2 hawa-text-primary-foreground" }, /* @__PURE__ */ React3.createElement(
"svg",
{
stroke: "currentColor",
fill: "currentColor",
strokeWidth: "0",
viewBox: "0 0 512 512",
height: "0.5em",
width: "0.5em"
},
/* @__PURE__ */ React3.createElement("path", { d: "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z" })
)), /* @__PURE__ */ React3.createElement("div", { className: "hawa-flex hawa-flex-col hawa-text-center hawa-text-sm" }, /* @__PURE__ */ React3.createElement("span", null, "Your feedback has been received!"), /* @__PURE__ */ React3.createElement("span", null, "Thank you for your help"))) : /* @__PURE__ */ React3.createElement("div", { className: "hawa-flex hawa-flex-col hawa-gap-1 hawa-p-1" }, /* @__PURE__ */ React3.createElement(
Popover,
{
className: "hawa-select-none hawa-p-1 hawa-text-xs",
open: helperText,
trigger: /* @__PURE__ */ React3.createElement(
Textarea,
{
classNames: {
textarea: "hawa-mt-2 hawa-h-full hawa-resize-none"
},
textareaProps: {
placeholder: "Your feedback",
onChange: (e) => {
if (e.target.value) {
setHelperText(false);
}
setFeedbackText(e.target.value);
}
}
}
)
},
/* @__PURE__ */ React3.createElement("span", { className: "hawa-m-0" }, "Please enter your feedback")
), /* @__PURE__ */ React3.createElement(
Button,
{
isLoading: loadingSubmit,
onClick: onFeedbackSubmit,
className: "hawa-w-full",
size: "sm"
},
"Submit"
))
)
);
};
// blocks/feedback/FeedbackForm.tsx
import React4 from "react";
import { useForm as useForm2, Controller as Controller2 } from "react-hook-form";
import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
import * as z2 from "zod";
var FeedbackForm = (props) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
const formSchema = z2.object({
requestType: z2.string({ required_error: (_b = (_a = props.texts) == null ? void 0 : _a.requestType) == null ? void 0 : _b.required }).min(1, { message: (_d = (_c = props.texts) == null ? void 0 : _c.requestType) == null ? void 0 : _d.required }),
description: z2.string({ required_error: (_f = (_e = props.texts) == null ? void 0 : _e.description) == null ? void 0 : _f.required }).min(10, { message: (_h = (_g = props.texts) == null ? void 0 : _g.description) == null ? void 0 : _h.tooShort })
});
const { handleSubmit, control, formState, reset } = useForm2({
resolver: zodResolver2(formSchema),
defaultValues: { requestType: "", description: "" }
});
return /* @__PURE__ */ React4.createElement(
Card,
{
className: cn(
props.cardless ? "hawa-border-none hawa-bg-transparent hawa-shadow-none" : ""
),
style: props.cardless ? { boxShadow: "none" } : void 0
},
/* @__PURE__ */ React4.createElement(CardContent, { headless: true, className: props.cardless ? "!hawa-p-0" : "" }, props.sent ? /* @__PURE__ */ React4.createElement("div", { className: "hawa-text-center hawa-min-h-[200px] hawa-flex hawa-flex-col hawa-justify-center" }, /* @__PURE__ */ React4.createElement("div", { className: "hawa-font-bold hawa-text-lg" }, props.texts.sentTitle || "Form submitted"), /* @__PURE__ */ React4.createElement("div", { className: "hawa-text-md" }, props.texts.sentSubtitle || "Thank you for your submission")) : /* @__PURE__ */ React4.createElement(
"form",
{
noValidate: true,
onSubmit: handleSubmit((e) => {
if (props.onSubmit) {
return props.onSubmit(e);
} else {
console.log("Form is submitted but onSubmit prop is missing");
}
}),
className: "hawa-flex hawa-flex-col hawa-gap-4"
},
/* @__PURE__ */ React4.createElement(
Controller2,
{
name: "requestType",
control,
render: ({ field }) => {
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
return /* @__PURE__ */ React4.createElement(
Select,
{
...field,
...props.selectProps,
label: (_b2 = (_a2 = props.texts) == null ? void 0 : _a2.requestType) == null ? void 0 : _b2.label,
onChange: (option) => field.onChange(option.value),
options: props.requestTypes,
helperText: (_d2 = (_c2 = formState.errors.requestType) == null ? void 0 : _c2.message) == null ? void 0 : _d2.toString(),
placeholder: (_f2 = (_e2 = props.texts) == null ? void 0 : _e2.requestType) == null ? void 0 : _f2.placeholder,
texts: {
noOptions: (_h2 = (_g2 = props.texts) == null ? void 0 : _g2.requestType) == null ? void 0 : _h2.noOptions
}
}
);
}
}
),
/* @__PURE__ */ React4.createElement(
Controller2,
{
name: "description",
control,
render: ({ field }) => {
var _a2, _b2, _c2, _d2, _e2, _f2;
return /* @__PURE__ */ React4.createElement(
Textarea,
{
helperText: formState.errors.description && ((_b2 = (_a2 = formState.errors.description) == null ? void 0 : _a2.message) == null ? void 0 : _b2.toString()),
classNames: { textarea: "hawa-h-full hawa-min-h-20" },
label: (_d2 = (_c2 = props.texts) == null ? void 0 : _c2.description) == null ? void 0 : _d2.label,
textareaProps: {
onChange: (e) => {
field.onChange(e.target.value);
},
value: field.value,
placeholder: (_f2 = (_e2 = props.texts) == null ? void 0 : _e2.description) == null ? void 0 : _f2.placeholder
}
}
);
}
}
),
/* @__PURE__ */ React4.createElement(Button, { isLoading: props.loadingSubmission, type: "submit" }, (_i = props.texts) == null ? void 0 : _i.submit)
))
);
};
export {
FeedbackEmoji,
FeedbackForm,
FeedbackRating,
UserReferralSource
};