2022-09-02 19:00:41 +00:00
|
|
|
import { useId } from "@radix-ui/react-id";
|
|
|
|
import { Root as ToggleGroupPrimitive, Item as ToggleGroupItemPrimitive } from "@radix-ui/react-toggle-group";
|
|
|
|
import { useState } from "react";
|
|
|
|
|
|
|
|
import classNames from "@calcom/lib/classNames";
|
|
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|
|
|
|
2022-11-04 15:40:46 +00:00
|
|
|
import { Label } from "../../../components/form/inputs/Label";
|
2022-09-02 19:00:41 +00:00
|
|
|
|
|
|
|
const boolean = (yesNo: "yes" | "no") => (yesNo === "yes" ? true : yesNo === "no" ? false : undefined);
|
|
|
|
const yesNo = (boolean?: boolean) => (boolean === true ? "yes" : boolean === false ? "no" : undefined);
|
|
|
|
|
|
|
|
export const BooleanToggleGroup = function BooleanToggleGroup({
|
|
|
|
defaultValue = true,
|
|
|
|
value,
|
2023-01-04 13:30:46 +00:00
|
|
|
disabled = false,
|
2022-09-02 19:00:41 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
|
|
onValueChange = () => {},
|
2023-03-16 05:10:20 +00:00
|
|
|
...passThrough
|
2022-09-02 19:00:41 +00:00
|
|
|
}: {
|
|
|
|
defaultValue?: boolean;
|
|
|
|
value?: boolean;
|
|
|
|
onValueChange?: (value?: boolean) => void;
|
2023-01-04 13:30:46 +00:00
|
|
|
disabled?: boolean;
|
2022-09-02 19:00:41 +00:00
|
|
|
}) {
|
|
|
|
// Maintain a state because it is not necessary that onValueChange the parent component would re-render. Think react-hook-form
|
|
|
|
// Also maintain a string as boolean isn't accepted as ToggleGroupPrimitive value
|
|
|
|
const [yesNoValue, setYesNoValue] = useState<"yes" | "no" | undefined>(yesNo(value));
|
|
|
|
|
|
|
|
if (!yesNoValue) {
|
|
|
|
setYesNoValue(yesNo(defaultValue));
|
|
|
|
onValueChange(defaultValue);
|
|
|
|
return null;
|
|
|
|
}
|
2023-04-06 08:17:53 +00:00
|
|
|
const commonClass = classNames(
|
|
|
|
"w-full inline-flex items-center justify-center rounded py-[10px] px-4 text-sm font-medium leading-4",
|
|
|
|
disabled && "cursor-not-allowed"
|
|
|
|
);
|
2023-04-05 18:14:46 +00:00
|
|
|
const selectedClass = classNames(commonClass, "bg-emphasis text-emphasis");
|
|
|
|
const unselectedClass = classNames(commonClass, "text-default hover:bg-subtle hover:text-emphasis");
|
2022-09-02 19:00:41 +00:00
|
|
|
return (
|
|
|
|
<ToggleGroupPrimitive
|
|
|
|
value={yesNoValue}
|
|
|
|
type="single"
|
2023-01-04 13:30:46 +00:00
|
|
|
disabled={disabled}
|
2023-05-02 21:49:17 +00:00
|
|
|
className="border-subtle flex h-9 space-x-2 rounded-md border p-1 rtl:space-x-reverse"
|
2022-09-02 19:00:41 +00:00
|
|
|
onValueChange={(yesNoValue: "yes" | "no") => {
|
|
|
|
setYesNoValue(yesNoValue);
|
|
|
|
onValueChange(boolean(yesNoValue));
|
2023-03-16 05:10:20 +00:00
|
|
|
}}
|
|
|
|
{...passThrough}>
|
2022-09-02 19:00:41 +00:00
|
|
|
<ToggleGroupItemPrimitive
|
|
|
|
className={classNames(boolean(yesNoValue) ? selectedClass : unselectedClass)}
|
2023-01-04 13:30:46 +00:00
|
|
|
disabled={disabled}
|
2022-09-02 19:00:41 +00:00
|
|
|
value="yes">
|
|
|
|
Yes
|
|
|
|
</ToggleGroupItemPrimitive>
|
2023-04-06 08:17:53 +00:00
|
|
|
|
2022-09-02 19:00:41 +00:00
|
|
|
<ToggleGroupItemPrimitive
|
2023-01-04 13:30:46 +00:00
|
|
|
disabled={disabled}
|
2022-09-02 19:00:41 +00:00
|
|
|
className={classNames(!boolean(yesNoValue) ? selectedClass : unselectedClass)}
|
|
|
|
value="no">
|
|
|
|
No
|
|
|
|
</ToggleGroupItemPrimitive>
|
|
|
|
</ToggleGroupPrimitive>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const BooleanToggleGroupField = function BooleanToggleGroupField(
|
|
|
|
props: Parameters<typeof BooleanToggleGroup>[0] & {
|
|
|
|
label?: string;
|
|
|
|
containerClassName?: string;
|
|
|
|
name?: string;
|
|
|
|
labelProps?: React.ComponentProps<typeof Label>;
|
|
|
|
className?: string;
|
|
|
|
error?: string;
|
|
|
|
}
|
|
|
|
) {
|
|
|
|
const { t } = useLocale();
|
|
|
|
const { label = t(props.name || ""), containerClassName, labelProps, className, ...passThrough } = props;
|
|
|
|
const id = useId();
|
|
|
|
return (
|
|
|
|
<div className={classNames(containerClassName)}>
|
|
|
|
<div className={className}>
|
|
|
|
{!!label && (
|
2023-04-05 18:14:46 +00:00
|
|
|
<Label htmlFor={id} {...labelProps} className={classNames(props.error && "text-error", "mt-4")}>
|
2022-09-02 19:00:41 +00:00
|
|
|
{label}
|
|
|
|
</Label>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
<BooleanToggleGroup {...passThrough} />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|