UNPKG

@sikka/hawa

Version:

Modern UI Kit made with Tailwind

508 lines (503 loc) • 20.9 kB
"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 };