formatting
This commit is contained in:
@@ -1,88 +1,90 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
|
||||
interface ButtonProps {
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
color?: "primary" | "secondary" | "error" | "warning" | "success";
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
color?: 'primary' | 'secondary' | 'error' | 'warning' | 'success';
|
||||
}
|
||||
|
||||
const ColorBgVariants = {
|
||||
"primary": "bg-liquid-brightmain group-hover:ring-liquid-brightmain",
|
||||
"secondary": "bg-liquid-darkmain group-hover:ring-liquid-darkmain",
|
||||
"error": "bg-liquid-red group-hover:ring-liquid-red",
|
||||
"warning": "bg-liquid-orange group-hover:ring-liquid-orange",
|
||||
"success": "bg-liquid-green group-hover:ring-liquid-green",
|
||||
}
|
||||
primary: 'bg-liquid-brightmain group-hover:ring-liquid-brightmain',
|
||||
secondary: 'bg-liquid-darkmain group-hover:ring-liquid-darkmain',
|
||||
error: 'bg-liquid-red group-hover:ring-liquid-red',
|
||||
warning: 'bg-liquid-orange group-hover:ring-liquid-orange',
|
||||
success: 'bg-liquid-green group-hover:ring-liquid-green',
|
||||
};
|
||||
|
||||
const ColorTextVariants = {
|
||||
"primary": "group-hover:text-liquid-brightmain ",
|
||||
"secondary": "group-hover:text-liquid-brightmain ",
|
||||
"error": "group-hover:text-liquid-red ",
|
||||
"warning": "group-hover:text-liquid-orange ",
|
||||
"success": "group-hover:text-liquid-green ",
|
||||
}
|
||||
primary: 'group-hover:text-liquid-brightmain ',
|
||||
secondary: 'group-hover:text-liquid-brightmain ',
|
||||
error: 'group-hover:text-liquid-red ',
|
||||
warning: 'group-hover:text-liquid-orange ',
|
||||
success: 'group-hover:text-liquid-green ',
|
||||
};
|
||||
|
||||
export const PrimaryButton: React.FC<ButtonProps> = ({
|
||||
disabled = false,
|
||||
text = "",
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
color = "secondary",
|
||||
disabled = false,
|
||||
text = '',
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
color = 'secondary',
|
||||
}) => {
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
"grid relative cursor-pointer select-none group w-fit box-border",
|
||||
disabled && "pointer-events-none",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
"group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300",
|
||||
"rounded-[10px]",
|
||||
"group-hover:bg-liquid-lighter group-hover:ring-[1px] group-hover:ring-liquid-darkmain group-hover:ring-inset",
|
||||
"px-[16px] py-[8px]",
|
||||
ColorBgVariants[color],
|
||||
disabled && "bg-liquid-lighter"
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
"absolute opacity-0 -z-10 h-0 w-0",
|
||||
"[&:focus-visible+*]:outline-liquid-brightmain",
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => { onClick() }}
|
||||
/>
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
'grid relative cursor-pointer select-none group w-fit box-border',
|
||||
disabled && 'pointer-events-none',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
'group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300',
|
||||
'rounded-[10px]',
|
||||
'group-hover:bg-liquid-lighter group-hover:ring-[1px] group-hover:ring-liquid-darkmain group-hover:ring-inset',
|
||||
'px-[16px] py-[8px]',
|
||||
ColorBgVariants[color],
|
||||
disabled && 'bg-liquid-lighter',
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
'absolute opacity-0 -z-10 h-0 w-0',
|
||||
'[&:focus-visible+*]:outline-liquid-brightmain',
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]",
|
||||
"rounded-[10px]",
|
||||
"px-[16px] py-[8px]",
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]",
|
||||
ColorTextVariants[color],
|
||||
disabled && "text-liquid-light"
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]',
|
||||
'rounded-[10px]',
|
||||
'px-[16px] py-[8px]',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]',
|
||||
ColorTextVariants[color],
|
||||
disabled && 'text-liquid-light',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,70 +1,72 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
|
||||
interface ButtonProps {
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ReverseButton: React.FC<ButtonProps> = ({
|
||||
disabled = false,
|
||||
text = "",
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
disabled = false,
|
||||
text = '',
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
"grid relative cursor-pointer select-none group w-fit box-border",
|
||||
disabled && "pointer-events-none",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
"group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300",
|
||||
"rounded-[10px]",
|
||||
"group-hover:bg-liquid-darkmain ",
|
||||
"px-[16px] py-[8px]",
|
||||
"bg-liquid-lighter ring-[1px] ring-liquid-darkmain ring-inset",
|
||||
disabled && "bg-liquid-lighter"
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
"absolute opacity-0 -z-10 h-0 w-0",
|
||||
"[&:focus-visible+*]:outline-liquid-brightmain",
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => { onClick() }}
|
||||
/>
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
'grid relative cursor-pointer select-none group w-fit box-border',
|
||||
disabled && 'pointer-events-none',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
'group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300',
|
||||
'rounded-[10px]',
|
||||
'group-hover:bg-liquid-darkmain ',
|
||||
'px-[16px] py-[8px]',
|
||||
'bg-liquid-lighter ring-[1px] ring-liquid-darkmain ring-inset',
|
||||
disabled && 'bg-liquid-lighter',
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
'absolute opacity-0 -z-10 h-0 w-0',
|
||||
'[&:focus-visible+*]:outline-liquid-brightmain',
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]",
|
||||
"rounded-[10px]",
|
||||
"px-[16px] py-[8px]",
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"transition-all duration-300 text-liquid-brightmain text-[18px] font-bold p-0 m-0 leading-[23px]",
|
||||
"group-hover:text-liquid-white ",
|
||||
disabled && "text-liquid-light"
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]',
|
||||
'rounded-[10px]',
|
||||
'px-[16px] py-[8px]',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'transition-all duration-300 text-liquid-brightmain text-[18px] font-bold p-0 m-0 leading-[23px]',
|
||||
'group-hover:text-liquid-white ',
|
||||
disabled && 'text-liquid-light',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,69 +1,70 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
|
||||
interface ButtonProps {
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
className?: string;
|
||||
onClick: () => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const SecondaryButton: React.FC<ButtonProps> = ({
|
||||
disabled = false,
|
||||
text = "",
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
disabled = false,
|
||||
text = '',
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
"grid relative cursor-pointer select-none group w-fit box-border",
|
||||
disabled && "pointer-events-none",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
"group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300",
|
||||
"rounded-[10px]",
|
||||
"group-hover:bg-liquid-background",
|
||||
"px-[16px] py-[8px]",
|
||||
"bg-liquid-lighter"
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
"absolute opacity-0 -z-10 h-0 w-0",
|
||||
"[&:focus-visible+*]:outline-liquid-brightmain",
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => { onClick() }}
|
||||
/>
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
'grid relative cursor-pointer select-none group w-fit box-border',
|
||||
disabled && 'pointer-events-none',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
'group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300',
|
||||
'rounded-[10px]',
|
||||
'group-hover:bg-liquid-background',
|
||||
'px-[16px] py-[8px]',
|
||||
'bg-liquid-lighter',
|
||||
)}
|
||||
>
|
||||
{/* Скрытый button */}
|
||||
<button
|
||||
className={cn(
|
||||
'absolute opacity-0 -z-10 h-0 w-0',
|
||||
'[&:focus-visible+*]:outline-liquid-brightmain',
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]",
|
||||
"rounded-[10px]",
|
||||
"px-[16px] py-[8px]",
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]",
|
||||
disabled && "text-liquid-light"
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
{/* Граница при выделении через tab */}
|
||||
<div
|
||||
className={cn(
|
||||
'absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]',
|
||||
'rounded-[10px]',
|
||||
'px-[16px] py-[8px]',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]',
|
||||
disabled && 'text-liquid-light',
|
||||
)}
|
||||
>
|
||||
{children || text}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,168 +1,167 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import { motion } from "framer-motion";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const pathVariants = {
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
pathLength: 0,
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
pathLength: 1,
|
||||
transition: {
|
||||
delay: 0.15,
|
||||
duration: 0.4,
|
||||
ease: "easeInOut",
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
pathLength: 0,
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
pathLength: 1,
|
||||
transition: {
|
||||
delay: 0.15,
|
||||
duration: 0.4,
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const sizeVariants = {
|
||||
sm: "h-4 w-4",
|
||||
md: "h-5 w-5",
|
||||
lg: "h-6 w-6",
|
||||
sm: 'h-4 w-4',
|
||||
md: 'h-5 w-5',
|
||||
lg: 'h-6 w-6',
|
||||
};
|
||||
|
||||
const colorsVariants = {
|
||||
default: "bg-default",
|
||||
primary: "bg-liquid-brightmain",
|
||||
secondary: "bg-liquid-darkmain",
|
||||
success: "bg-liquid-green",
|
||||
warning: "bg-liquid-orange",
|
||||
danger: "bg-liquid-red",
|
||||
default: 'bg-default',
|
||||
primary: 'bg-liquid-brightmain',
|
||||
secondary: 'bg-liquid-darkmain',
|
||||
success: 'bg-liquid-green',
|
||||
warning: 'bg-liquid-orange',
|
||||
danger: 'bg-liquid-red',
|
||||
};
|
||||
|
||||
|
||||
const borderColorsVariants = {
|
||||
default: "border-default",
|
||||
primary: "border-liquid-brightmain",
|
||||
secondary: "border-liquid-darkmain",
|
||||
success: "border-liquid-green",
|
||||
warning: "border-liquid-orange",
|
||||
danger: "border-liquid-red",
|
||||
default: 'border-default',
|
||||
primary: 'border-liquid-brightmain',
|
||||
secondary: 'border-liquid-darkmain',
|
||||
success: 'border-liquid-green',
|
||||
warning: 'border-liquid-orange',
|
||||
danger: 'border-liquid-red',
|
||||
};
|
||||
|
||||
const focuseOutlineVariants = {
|
||||
default: "[&:focus-visible+*]:outline-default",
|
||||
primary: "[&:focus-visible+*]:outline-liquid-brightmain",
|
||||
secondary: "[&:focus-visible+*]:outline-liquid-darkmain",
|
||||
success: "[&:focus-visible+*]:outline-liquid-green",
|
||||
warning: "[&:focus-visible+*]:outline-liquid-orange",
|
||||
danger: "[&:focus-visible+*]:outline-liquid-red",
|
||||
default: '[&:focus-visible+*]:outline-default',
|
||||
primary: '[&:focus-visible+*]:outline-liquid-brightmain',
|
||||
secondary: '[&:focus-visible+*]:outline-liquid-darkmain',
|
||||
success: '[&:focus-visible+*]:outline-liquid-green',
|
||||
warning: '[&:focus-visible+*]:outline-liquid-orange',
|
||||
danger: '[&:focus-visible+*]:outline-liquid-red',
|
||||
};
|
||||
|
||||
const radiusVraiants = {
|
||||
none: "",
|
||||
sm: "rounded-[3.5px]",
|
||||
md: "rounded-[5px]",
|
||||
lg: "rounded-[7px]",
|
||||
full: "rounded-full",
|
||||
none: '',
|
||||
sm: 'rounded-[3.5px]',
|
||||
md: 'rounded-[5px]',
|
||||
lg: 'rounded-[7px]',
|
||||
full: 'rounded-full',
|
||||
};
|
||||
|
||||
interface CheckboxProps {
|
||||
size?: "sm" | "md" | "lg";
|
||||
radius?: "none" | "sm" | "md" | "lg" | "full";
|
||||
disabled?: boolean;
|
||||
color?:
|
||||
| "default"
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "danger";
|
||||
label?: string;
|
||||
variant?: "default" | "label";
|
||||
className?: string;
|
||||
defaultState?: boolean;
|
||||
onChange: (state: boolean) => void;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
radius?: 'none' | 'sm' | 'md' | 'lg' | 'full';
|
||||
disabled?: boolean;
|
||||
color?:
|
||||
| 'default'
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'danger';
|
||||
label?: string;
|
||||
variant?: 'default' | 'label';
|
||||
className?: string;
|
||||
defaultState?: boolean;
|
||||
onChange: (state: boolean) => void;
|
||||
}
|
||||
|
||||
export const Checkbox: React.FC<CheckboxProps> = ({
|
||||
size = "md",
|
||||
radius = "md",
|
||||
disabled = false,
|
||||
color = "primary",
|
||||
label = "",
|
||||
variant = "label",
|
||||
className,
|
||||
onChange,
|
||||
defaultState = false,
|
||||
size = 'md',
|
||||
radius = 'md',
|
||||
disabled = false,
|
||||
color = 'primary',
|
||||
label = '',
|
||||
variant = 'label',
|
||||
className,
|
||||
onChange,
|
||||
defaultState = false,
|
||||
}) => {
|
||||
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||
|
||||
React.useEffect(() => onChange(active), [active]);
|
||||
React.useEffect(() => onChange(active), [active]);
|
||||
|
||||
return (
|
||||
<motion.label
|
||||
className={cn(
|
||||
variant == "label" && "grid-cols-[auto_1fr] items-center gap-2",
|
||||
"grid relative cursor-pointer p-2 select-none group ",
|
||||
className,
|
||||
disabled && "pointer-events-none opacity-50",
|
||||
variant == "default" && ""
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"group-hover:bg-default-100 group-active:scale-90 flex items-center justify-center bg-transparent hover:bg-default-100 box-border border-solid border-[1px] border-liquid-white z-10 relative transition-all duration-300",
|
||||
sizeVariants[size],
|
||||
radiusVraiants[radius],
|
||||
active && borderColorsVariants[color]
|
||||
)}
|
||||
>
|
||||
<input
|
||||
className={cn(
|
||||
"absolute opacity-0 -z-10 h-0 w-0",
|
||||
focuseOutlineVariants[color]
|
||||
)}
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
onChange={() => {
|
||||
setActive(!active);
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
"absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-200",
|
||||
sizeVariants[size],
|
||||
radiusVraiants[radius]
|
||||
)}
|
||||
></div>
|
||||
<span
|
||||
className={cn(
|
||||
"absolute transition-all duration-300",
|
||||
sizeVariants[size],
|
||||
colorsVariants[color],
|
||||
radiusVraiants[radius],
|
||||
active && "opacity-100 scale-100",
|
||||
!active && "opacity-0 scale-0"
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{active && (
|
||||
<motion.path
|
||||
strokeWidth="1.5"
|
||||
d="M5 8.22L7.66571 10.44L11.22 6"
|
||||
stroke="white"
|
||||
strokeLinecap="round"
|
||||
variants={pathVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
/>
|
||||
return (
|
||||
<motion.label
|
||||
className={cn(
|
||||
variant == 'label' && 'grid-cols-[auto_1fr] items-center gap-2',
|
||||
'grid relative cursor-pointer p-2 select-none group ',
|
||||
className,
|
||||
disabled && 'pointer-events-none opacity-50',
|
||||
variant == 'default' && '',
|
||||
)}
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
{variant == "label" && (
|
||||
<div className="select-none text-layout-foeground transition-all duration-200">
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
</motion.label>
|
||||
);
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'group-hover:bg-default-100 group-active:scale-90 flex items-center justify-center bg-transparent hover:bg-default-100 box-border border-solid border-[1px] border-liquid-white z-10 relative transition-all duration-300',
|
||||
sizeVariants[size],
|
||||
radiusVraiants[radius],
|
||||
active && borderColorsVariants[color],
|
||||
)}
|
||||
>
|
||||
<input
|
||||
className={cn(
|
||||
'absolute opacity-0 -z-10 h-0 w-0',
|
||||
focuseOutlineVariants[color],
|
||||
)}
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
onChange={() => {
|
||||
setActive(!active);
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
'absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-200',
|
||||
sizeVariants[size],
|
||||
radiusVraiants[radius],
|
||||
)}
|
||||
></div>
|
||||
<span
|
||||
className={cn(
|
||||
'absolute transition-all duration-300',
|
||||
sizeVariants[size],
|
||||
colorsVariants[color],
|
||||
radiusVraiants[radius],
|
||||
active && 'opacity-100 scale-100',
|
||||
!active && 'opacity-0 scale-0',
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{active && (
|
||||
<motion.path
|
||||
strokeWidth="1.5"
|
||||
d="M5 8.22L7.66571 10.44L11.22 6"
|
||||
stroke="white"
|
||||
strokeLinecap="round"
|
||||
variants={pathVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
/>
|
||||
)}
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
{variant == 'label' && (
|
||||
<div className="select-none text-layout-foeground transition-all duration-200">
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
</motion.label>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import { checkMark, chevroneDropDownList } from "../../assets/icons/input";
|
||||
import { useClickOutside } from "../../hooks/useClickOutside";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
import { checkMark, chevroneDropDownList } from '../../assets/icons/input';
|
||||
import { useClickOutside } from '../../hooks/useClickOutside';
|
||||
|
||||
export interface DropDownListItem {
|
||||
text: string;
|
||||
@@ -18,15 +18,16 @@ interface DropDownListProps {
|
||||
|
||||
export const DropDownList: React.FC<DropDownListProps> = ({
|
||||
// disabled = false,
|
||||
className = "",
|
||||
className = '',
|
||||
onChange,
|
||||
defaultState,
|
||||
items = [{ text: "", value: "" }],
|
||||
items = [{ text: '', value: '' }],
|
||||
}) => {
|
||||
if (items.length == 0)
|
||||
items.push({ text: "", value: "" });
|
||||
if (items.length == 0) items.push({ text: '', value: '' });
|
||||
|
||||
const [value, setValue] = React.useState<DropDownListItem>(defaultState != undefined ? defaultState : items[0]);
|
||||
const [value, setValue] = React.useState<DropDownListItem>(
|
||||
defaultState != undefined ? defaultState : items[0],
|
||||
);
|
||||
const [active, setActive] = React.useState<boolean>(false);
|
||||
|
||||
React.useEffect(() => onChange(value.value), [value]);
|
||||
@@ -37,67 +38,73 @@ export const DropDownList: React.FC<DropDownListProps> = ({
|
||||
setActive(false);
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
"relative",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
>
|
||||
<div className={cn(" flex items-center h-[40px] rounded-[10px] bg-liquid-lighter px-[16px] w-[180px]",
|
||||
"text-[18px] font-bold cursor-pointer select-none",
|
||||
"transitin-all active:scale-95 duration-300"
|
||||
)}
|
||||
<div className={cn('relative', className)} ref={ref}>
|
||||
<div
|
||||
className={cn(
|
||||
' flex items-center h-[40px] rounded-[10px] bg-liquid-lighter px-[16px] w-[180px]',
|
||||
'text-[18px] font-bold cursor-pointer select-none',
|
||||
'transitin-all active:scale-95 duration-300',
|
||||
)}
|
||||
onClick={() => {
|
||||
setActive(!active);
|
||||
}
|
||||
}>
|
||||
}}
|
||||
>
|
||||
{value.text}
|
||||
|
||||
</div>
|
||||
|
||||
<img src={chevroneDropDownList}
|
||||
className={cn(" absolute right-[16px] h-[24px] w-[24px] top-[8.5px] rotate-0 transition-all duration-300 pointer-events-none",
|
||||
active && " rotate-180"
|
||||
)} />
|
||||
|
||||
<img
|
||||
src={chevroneDropDownList}
|
||||
className={cn(
|
||||
' absolute right-[16px] h-[24px] w-[24px] top-[8.5px] rotate-0 transition-all duration-300 pointer-events-none',
|
||||
active && ' rotate-180',
|
||||
)}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={cn(" absolute rounded-[10px] bg-liquid-lighter w-[180px] left-0 top-[48px] z-50 transition-all duration-300",
|
||||
"grid overflow-hidden",
|
||||
active ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0",
|
||||
)}>
|
||||
className={cn(
|
||||
' absolute rounded-[10px] bg-liquid-lighter w-[180px] left-0 top-[48px] z-50 transition-all duration-300',
|
||||
'grid overflow-hidden',
|
||||
active
|
||||
? 'grid-rows-[1fr] opacity-100'
|
||||
: 'grid-rows-[0fr] opacity-0',
|
||||
)}
|
||||
>
|
||||
<div className=" overflow-hidden p-[8px]">
|
||||
<div className={cn(
|
||||
" overflow-y-scroll max-h-[200px] thin-scrollbar pr-[8px] ",
|
||||
)}>
|
||||
|
||||
{items.map((v, i) =>
|
||||
<div
|
||||
className={cn(
|
||||
' overflow-y-scroll max-h-[200px] thin-scrollbar pr-[8px] ',
|
||||
)}
|
||||
>
|
||||
{items.map((v, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(
|
||||
"cursor-pointer h-[36px] relative transition-all duration-300",
|
||||
i + 1 != items.length && "border-b-liquid-light border-b-[1px]",
|
||||
"text-[16px] font-medium cursor-pointer select-none flex items-center pl-[8px]",
|
||||
"hover:bg-liquid-background",
|
||||
"first:rounded-t-[6px] last:rounded-b-[6px]"
|
||||
'cursor-pointer h-[36px] relative transition-all duration-300',
|
||||
i + 1 != items.length &&
|
||||
'border-b-liquid-light border-b-[1px]',
|
||||
'text-[16px] font-medium cursor-pointer select-none flex items-center pl-[8px]',
|
||||
'hover:bg-liquid-background',
|
||||
'first:rounded-t-[6px] last:rounded-b-[6px]',
|
||||
)}
|
||||
onClick={() => {
|
||||
setValue(v);
|
||||
setActive(false);
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{v.text}
|
||||
|
||||
{v.text == value.text &&
|
||||
<img src={checkMark} className=" absolute right-[8px]" />
|
||||
}
|
||||
{v.text == value.text && (
|
||||
<img
|
||||
src={checkMark}
|
||||
className=" absolute right-[8px]"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
@@ -1,89 +1,95 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import { eyeClosed, eyeOpen } from "../../assets/icons/input";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
import { eyeClosed, eyeOpen } from '../../assets/icons/input';
|
||||
|
||||
interface inputProps {
|
||||
name?: string;
|
||||
type: "text" | "email" | "password" | "first_name" | "number";
|
||||
error?: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
onChange: (state: string) => void;
|
||||
defaultState?: string;
|
||||
autocomplete?: string;
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||
name?: string;
|
||||
type: 'text' | 'email' | 'password' | 'first_name' | 'number';
|
||||
error?: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
onChange: (state: string) => void;
|
||||
defaultState?: string;
|
||||
autocomplete?: string;
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||
}
|
||||
|
||||
export const Input: React.FC<inputProps> = ({
|
||||
type = "text",
|
||||
error = "",
|
||||
// disabled = false,
|
||||
// required = false,
|
||||
label = "",
|
||||
placeholder = "",
|
||||
className = "",
|
||||
onChange,
|
||||
defaultState = "",
|
||||
name = "",
|
||||
autocomplete = "",
|
||||
onKeyDown,
|
||||
type = 'text',
|
||||
error = '',
|
||||
// disabled = false,
|
||||
// required = false,
|
||||
label = '',
|
||||
placeholder = '',
|
||||
className = '',
|
||||
onChange,
|
||||
defaultState = '',
|
||||
name = '',
|
||||
autocomplete = '',
|
||||
onKeyDown,
|
||||
}) => {
|
||||
const [value, setValue] = React.useState<string>(defaultState);
|
||||
const [visible, setVIsible] = React.useState<boolean>(type != "password");
|
||||
const [value, setValue] = React.useState<string>(defaultState);
|
||||
const [visible, setVIsible] = React.useState<boolean>(type != 'password');
|
||||
|
||||
React.useEffect(() => onChange(value), [value]);
|
||||
React.useEffect(() => setValue(defaultState), [defaultState]);
|
||||
React.useEffect(() => onChange(value), [value]);
|
||||
React.useEffect(() => setValue(defaultState), [defaultState]);
|
||||
|
||||
return (
|
||||
<div className={cn('relative', className)}>
|
||||
<div
|
||||
className={cn(
|
||||
'text-[18px] text-liquid-white font-medium h-[23px] mb-[10px] transition-all',
|
||||
label == '' && 'h-0 mb-0',
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
<div className="relative">
|
||||
<input
|
||||
className={cn(
|
||||
'bg-liquid-lighter w-full rounded-[10px] outline-none pl-[16px] py-[8px] placeholder:text-liquid-light',
|
||||
type == 'password' ? 'h-[40px]' : 'h-[36px]',
|
||||
)}
|
||||
value={value}
|
||||
name={name}
|
||||
autoComplete={autocomplete}
|
||||
type={
|
||||
type == 'password'
|
||||
? visible
|
||||
? 'text'
|
||||
: 'password'
|
||||
: type
|
||||
}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (onKeyDown) onKeyDown(e);
|
||||
}}
|
||||
/>
|
||||
{type == 'password' && (
|
||||
<img
|
||||
src={visible ? eyeOpen : eyeClosed}
|
||||
className="w-[24px] h-[24px] cursor-pointer right-[16px] top-[8px] absolute"
|
||||
onClick={() => {
|
||||
setVIsible(!visible);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
"relative",
|
||||
className
|
||||
)}>
|
||||
<div className={cn("text-[18px] text-liquid-white font-medium h-[23px] mb-[10px] transition-all",
|
||||
label == "" && "h-0 mb-0"
|
||||
)}>
|
||||
{label}
|
||||
</div>
|
||||
<div className="relative">
|
||||
<input
|
||||
className={cn(
|
||||
"bg-liquid-lighter w-full rounded-[10px] outline-none pl-[16px] py-[8px] placeholder:text-liquid-light",
|
||||
type == "password" ? "h-[40px]" : "h-[36px]"
|
||||
)}
|
||||
value={value}
|
||||
name={name}
|
||||
autoComplete={autocomplete}
|
||||
type={type == "password" ? (visible ? "text" : "password") : type}
|
||||
placeholder={placeholder}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (onKeyDown)
|
||||
onKeyDown(e);
|
||||
}
|
||||
}
|
||||
/>
|
||||
{
|
||||
type == "password" &&
|
||||
<img src={visible ? eyeOpen : eyeClosed} className="w-[24px] h-[24px] cursor-pointer right-[16px] top-[8px] absolute" onClick={() => {
|
||||
setVIsible(!visible);
|
||||
}} />
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={cn("text-liquid-red text-[14px] h-[18px] text-right mt-[5px]",
|
||||
error == "" && "h-0 mt-0"
|
||||
)}>
|
||||
{error}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
'text-liquid-red text-[14px] h-[18px] text-right mt-[5px]',
|
||||
error == '' && 'h-0 mt-0',
|
||||
)}
|
||||
>
|
||||
{error}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,78 +1,80 @@
|
||||
import React from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { cn } from "../../lib/cn";
|
||||
import { useClickOutside } from "../../hooks/useClickOutside";
|
||||
import React from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { cn } from '../../lib/cn';
|
||||
import { useClickOutside } from '../../hooks/useClickOutside';
|
||||
|
||||
type ModalBackdrop = "opaque" | "blur";
|
||||
type ModalBackdrop = 'opaque' | 'blur';
|
||||
|
||||
interface ModalProps {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
backdrop?: ModalBackdrop;
|
||||
open: boolean;
|
||||
defaultOpen?: boolean;
|
||||
onOpenChange: (state: boolean) => void;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
backdrop?: ModalBackdrop;
|
||||
open: boolean;
|
||||
defaultOpen?: boolean;
|
||||
onOpenChange: (state: boolean) => void;
|
||||
}
|
||||
|
||||
const modalbgVariants = {
|
||||
closed: { opacity: 0 },
|
||||
open: { opacity: 1 },
|
||||
closed: { opacity: 0 },
|
||||
open: { opacity: 1 },
|
||||
};
|
||||
|
||||
const modalVariants = {
|
||||
closed: { opacity: 0, scale: 0.9 },
|
||||
open: { opacity: 1, scale: 1 },
|
||||
closed: { opacity: 0, scale: 0.9 },
|
||||
open: { opacity: 1, scale: 1 },
|
||||
};
|
||||
|
||||
export const Modal: React.FC<ModalProps> = ({
|
||||
children,
|
||||
open,
|
||||
backdrop,
|
||||
className,
|
||||
onOpenChange,
|
||||
children,
|
||||
open,
|
||||
backdrop,
|
||||
className,
|
||||
onOpenChange,
|
||||
}) => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
useClickOutside(ref, () => {
|
||||
onOpenChange(false);
|
||||
});
|
||||
useClickOutside(ref, () => {
|
||||
onOpenChange(false);
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
initial={modalbgVariants.closed}
|
||||
animate={modalbgVariants.open}
|
||||
exit={modalbgVariants.closed}
|
||||
transition={{ duration: 0.15 }}
|
||||
className={cn(
|
||||
" fixed top-0 left-0 h-svh w-svw backdrop-filter transition-all z-50",
|
||||
backdrop == "blur" && open && "backdrop-blur-sm",
|
||||
backdrop == "opaque" && open && "bg-[#00000055] pointer-events-none",
|
||||
)}
|
||||
></motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<div className="fixed top-0 left-0 h-svh w-svw flex items-center justify-center pointer-events-none z-50">
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"h-fit w-fit rounded-md pointer-events-auto",
|
||||
className
|
||||
)}
|
||||
initial={modalVariants.closed}
|
||||
animate={modalVariants.open}
|
||||
exit={modalVariants.closed}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
initial={modalbgVariants.closed}
|
||||
animate={modalbgVariants.open}
|
||||
exit={modalbgVariants.closed}
|
||||
transition={{ duration: 0.15 }}
|
||||
className={cn(
|
||||
' fixed top-0 left-0 h-svh w-svw backdrop-filter transition-all z-50',
|
||||
backdrop == 'blur' && open && 'backdrop-blur-sm',
|
||||
backdrop == 'opaque' &&
|
||||
open &&
|
||||
'bg-[#00000055] pointer-events-none',
|
||||
)}
|
||||
></motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<div className="fixed top-0 left-0 h-svh w-svw flex items-center justify-center pointer-events-none z-50">
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'h-fit w-fit rounded-md pointer-events-auto',
|
||||
className,
|
||||
)}
|
||||
initial={modalVariants.closed}
|
||||
animate={modalVariants.open}
|
||||
exit={modalVariants.closed}
|
||||
transition={{ duration: 0.15 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,187 +1,191 @@
|
||||
import React from "react";
|
||||
import { cn } from "../../lib/cn";
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
|
||||
/* Варианты размера контейнера */
|
||||
const sizeVariants = {
|
||||
sm: "h-6 w-10",
|
||||
md: "h-7 w-12",
|
||||
lg: "h-8 w-14",
|
||||
sm: 'h-6 w-10',
|
||||
md: 'h-7 w-12',
|
||||
lg: 'h-8 w-14',
|
||||
};
|
||||
|
||||
/* Варианты для скользящего шарика */
|
||||
const switchVariants = {
|
||||
size: {
|
||||
sm: "h-4 w-4",
|
||||
md: "h-5 w-5",
|
||||
lg: "h-6 w-6",
|
||||
},
|
||||
activeSize: {
|
||||
sm: "group-active:w-5",
|
||||
md: "group-active:w-6",
|
||||
lg: "group-active:w-7",
|
||||
},
|
||||
iconSize: {
|
||||
sm: "h-3 w-3",
|
||||
md: "h-[0.875rem] w-[0.875rem]",
|
||||
lg: "h-4 w-4",
|
||||
},
|
||||
size: {
|
||||
sm: 'h-4 w-4',
|
||||
md: 'h-5 w-5',
|
||||
lg: 'h-6 w-6',
|
||||
},
|
||||
activeSize: {
|
||||
sm: 'group-active:w-5',
|
||||
md: 'group-active:w-6',
|
||||
lg: 'group-active:w-7',
|
||||
},
|
||||
iconSize: {
|
||||
sm: 'h-3 w-3',
|
||||
md: 'h-[0.875rem] w-[0.875rem]',
|
||||
lg: 'h-4 w-4',
|
||||
},
|
||||
};
|
||||
|
||||
const colorsVariants = {
|
||||
default: "bg-default",
|
||||
primary: "bg-liquid-brightmain",
|
||||
secondary: "bg-liquid-darkmain",
|
||||
success: "bg-liquid-green",
|
||||
warning: "bg-liquid-orange",
|
||||
danger: "bg-liquid-red",
|
||||
default: 'bg-default',
|
||||
primary: 'bg-liquid-brightmain',
|
||||
secondary: 'bg-liquid-darkmain',
|
||||
success: 'bg-liquid-green',
|
||||
warning: 'bg-liquid-orange',
|
||||
danger: 'bg-liquid-red',
|
||||
};
|
||||
|
||||
const focuseOutlineVariants = {
|
||||
default: "[&:focus-visible+*]:outline-default",
|
||||
primary: "[&:focus-visible+*]:outline-liquid-brightmain",
|
||||
secondary: "[&:focus-visible+*]:outline-liquid-darkmain",
|
||||
success: "[&:focus-visible+*]:outline-liquid-green",
|
||||
warning: "[&:focus-visible+*]:outline-liquid-orange",
|
||||
danger: "[&:focus-visible+*]:outline-liquid-red",
|
||||
default: '[&:focus-visible+*]:outline-default',
|
||||
primary: '[&:focus-visible+*]:outline-liquid-brightmain',
|
||||
secondary: '[&:focus-visible+*]:outline-liquid-darkmain',
|
||||
success: '[&:focus-visible+*]:outline-liquid-green',
|
||||
warning: '[&:focus-visible+*]:outline-liquid-orange',
|
||||
danger: '[&:focus-visible+*]:outline-liquid-red',
|
||||
};
|
||||
|
||||
/**
|
||||
* Иконка солнца
|
||||
*/
|
||||
const sun = (
|
||||
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6 9.5C7.933 9.5 9.5 7.933 9.5 6C9.5 4.067 7.933 2.5 6 2.5C4.067 2.5 2.5 4.067 2.5 6C2.5 7.933 4.067 9.5 6 9.5Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
<path
|
||||
d="M6 11.48C5.725 11.48 5.5 11.275 5.5 11V10.96C5.5 10.685 5.725 10.46 6 10.46C6.275 10.46 6.5 10.685 6.5 10.96C6.5 11.235 6.275 11.48 6 11.48ZM9.57 10.07C9.44 10.07 9.315 10.02 9.215 9.925L9.15 9.86C8.955 9.665 8.955 9.35 9.15 9.155C9.345 8.96 9.66 8.96 9.855 9.155L9.92 9.22C10.115 9.415 10.115 9.73 9.92 9.925C9.825 10.02 9.7 10.07 9.57 10.07ZM2.43 10.07C2.3 10.07 2.175 10.02 2.075 9.925C1.88 9.73 1.88 9.415 2.075 9.22L2.14 9.155C2.335 8.96 2.65 8.96 2.845 9.155C3.04 9.35 3.04 9.665 2.845 9.86L2.78 9.925C2.685 10.02 2.555 10.07 2.43 10.07ZM11 6.5H10.96C10.685 6.5 10.46 6.275 10.46 6C10.46 5.725 10.685 5.5 10.96 5.5C11.235 5.5 11.48 5.725 11.48 6C11.48 6.275 11.275 6.5 11 6.5ZM1.04 6.5H1C0.725 6.5 0.5 6.275 0.5 6C0.5 5.725 0.725 5.5 1 5.5C1.275 5.5 1.52 5.725 1.52 6C1.52 6.275 1.315 6.5 1.04 6.5ZM9.505 2.995C9.375 2.995 9.25 2.945 9.15 2.85C8.955 2.655 8.955 2.34 9.15 2.145L9.215 2.08C9.41 1.885 9.725 1.885 9.92 2.08C10.115 2.275 10.115 2.59 9.92 2.785L9.855 2.85C9.76 2.945 9.635 2.995 9.505 2.995ZM2.495 2.995C2.365 2.995 2.24 2.945 2.14 2.85L2.075 2.78C1.88 2.585 1.88 2.27 2.075 2.075C2.27 1.88 2.585 1.88 2.78 2.075L2.845 2.14C3.04 2.335 3.04 2.65 2.845 2.845C2.75 2.945 2.62 2.995 2.495 2.995ZM6 1.52C5.725 1.52 5.5 1.315 5.5 1.04V1C5.5 0.725 5.725 0.5 6 0.5C6.275 0.5 6.5 0.725 6.5 1C6.5 1.275 6.275 1.52 6 1.52Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M6 9.5C7.933 9.5 9.5 7.933 9.5 6C9.5 4.067 7.933 2.5 6 2.5C4.067 2.5 2.5 4.067 2.5 6C2.5 7.933 4.067 9.5 6 9.5Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
<path
|
||||
d="M6 11.48C5.725 11.48 5.5 11.275 5.5 11V10.96C5.5 10.685 5.725 10.46 6 10.46C6.275 10.46 6.5 10.685 6.5 10.96C6.5 11.235 6.275 11.48 6 11.48ZM9.57 10.07C9.44 10.07 9.315 10.02 9.215 9.925L9.15 9.86C8.955 9.665 8.955 9.35 9.15 9.155C9.345 8.96 9.66 8.96 9.855 9.155L9.92 9.22C10.115 9.415 10.115 9.73 9.92 9.925C9.825 10.02 9.7 10.07 9.57 10.07ZM2.43 10.07C2.3 10.07 2.175 10.02 2.075 9.925C1.88 9.73 1.88 9.415 2.075 9.22L2.14 9.155C2.335 8.96 2.65 8.96 2.845 9.155C3.04 9.35 3.04 9.665 2.845 9.86L2.78 9.925C2.685 10.02 2.555 10.07 2.43 10.07ZM11 6.5H10.96C10.685 6.5 10.46 6.275 10.46 6C10.46 5.725 10.685 5.5 10.96 5.5C11.235 5.5 11.48 5.725 11.48 6C11.48 6.275 11.275 6.5 11 6.5ZM1.04 6.5H1C0.725 6.5 0.5 6.275 0.5 6C0.5 5.725 0.725 5.5 1 5.5C1.275 5.5 1.52 5.725 1.52 6C1.52 6.275 1.315 6.5 1.04 6.5ZM9.505 2.995C9.375 2.995 9.25 2.945 9.15 2.85C8.955 2.655 8.955 2.34 9.15 2.145L9.215 2.08C9.41 1.885 9.725 1.885 9.92 2.08C10.115 2.275 10.115 2.59 9.92 2.785L9.855 2.85C9.76 2.945 9.635 2.995 9.505 2.995ZM2.495 2.995C2.365 2.995 2.24 2.945 2.14 2.85L2.075 2.78C1.88 2.585 1.88 2.27 2.075 2.075C2.27 1.88 2.585 1.88 2.78 2.075L2.845 2.14C3.04 2.335 3.04 2.65 2.845 2.845C2.75 2.945 2.62 2.995 2.495 2.995ZM6 1.52C5.725 1.52 5.5 1.315 5.5 1.04V1C5.5 0.725 5.725 0.5 6 0.5C6.275 0.5 6.5 0.725 6.5 1C6.5 1.275 6.275 1.52 6 1.52Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
/**
|
||||
* Иконка луны
|
||||
*/
|
||||
const moon = (
|
||||
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M10.765 7.965C10.685 7.83 10.46 7.62 9.89999 7.72C9.58999 7.775 9.27499 7.8 8.95999 7.785C7.79499 7.735 6.73999 7.2 6.00499 6.375C5.35499 5.65 4.95499 4.705 4.94999 3.685C4.94999 3.115 5.05999 2.565 5.28499 2.045C5.50499 1.54 5.34999 1.275 5.23999 1.165C5.12499 1.05 4.85499 0.890001 4.32499 1.11C2.27999 1.97 1.01499 4.02 1.16499 6.215C1.31499 8.28 2.76499 10.045 4.68499 10.71C5.14499 10.87 5.62999 10.965 6.12999 10.985C6.20999 10.99 6.28999 10.995 6.36999 10.995C8.04499 10.995 9.61499 10.205 10.605 8.86C10.94 8.395 10.85 8.1 10.765 7.965Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M10.765 7.965C10.685 7.83 10.46 7.62 9.89999 7.72C9.58999 7.775 9.27499 7.8 8.95999 7.785C7.79499 7.735 6.73999 7.2 6.00499 6.375C5.35499 5.65 4.95499 4.705 4.94999 3.685C4.94999 3.115 5.05999 2.565 5.28499 2.045C5.50499 1.54 5.34999 1.275 5.23999 1.165C5.12499 1.05 4.85499 0.890001 4.32499 1.11C2.27999 1.97 1.01499 4.02 1.16499 6.215C1.31499 8.28 2.76499 10.045 4.68499 10.71C5.14499 10.87 5.62999 10.965 6.12999 10.985C6.20999 10.99 6.28999 10.995 6.36999 10.995C8.04499 10.995 9.61499 10.205 10.605 8.86C10.94 8.395 10.85 8.1 10.765 7.965Z"
|
||||
fill="#292D32"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
interface SwitchProps {
|
||||
size?: "sm" | "md" | "lg";
|
||||
disabled?: boolean;
|
||||
color?:
|
||||
| "default"
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "danger";
|
||||
label?: string;
|
||||
variant?: "default" | "label" | "icon" | "theme";
|
||||
className?: string;
|
||||
defaultState?: boolean;
|
||||
onChange: (state: boolean) => void;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
disabled?: boolean;
|
||||
color?:
|
||||
| 'default'
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'danger';
|
||||
label?: string;
|
||||
variant?: 'default' | 'label' | 'icon' | 'theme';
|
||||
className?: string;
|
||||
defaultState?: boolean;
|
||||
onChange: (state: boolean) => void;
|
||||
}
|
||||
|
||||
export const Switch: React.FC<SwitchProps> = ({
|
||||
size = "sm",
|
||||
disabled = false,
|
||||
color = "primary",
|
||||
label = "",
|
||||
variant = "default",
|
||||
className,
|
||||
onChange,
|
||||
defaultState = false,
|
||||
size = 'sm',
|
||||
disabled = false,
|
||||
color = 'primary',
|
||||
label = '',
|
||||
variant = 'default',
|
||||
className,
|
||||
onChange,
|
||||
defaultState = false,
|
||||
}) => {
|
||||
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||
|
||||
React.useEffect(() => onChange(active), [active]);
|
||||
React.useEffect(() => onChange(active), [active]);
|
||||
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
variant == "label" && "grid-cols-[auto_1fr] items-center gap-2",
|
||||
"grid relative cursor-pointer p-2 select-none group",
|
||||
disabled && "pointer-events-none opacity-50",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
" flex items-center justify-center box-border z-10 relative transition-all duration-300 rounded-full",
|
||||
sizeVariants[size],
|
||||
active ? colorsVariants[color] : "bg-default-200"
|
||||
)}
|
||||
>
|
||||
{/* Скрытый checkbox */}
|
||||
<input
|
||||
className={cn(
|
||||
"absolute opacity-0 -z-10 h-0 w-0",
|
||||
focuseOutlineVariants[color]
|
||||
)}
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
onChange={() => {
|
||||
setActive(!active);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-300 rounded-full",
|
||||
sizeVariants[size]
|
||||
)}
|
||||
></div>
|
||||
|
||||
{/* Шарик */}
|
||||
<span
|
||||
className={cn(
|
||||
"bg-white rounded-full absolute transition-all duration-300 m-1 flex items-center justify-center",
|
||||
switchVariants.size[size],
|
||||
switchVariants.activeSize[size],
|
||||
active
|
||||
? "right-[0%]"
|
||||
: "right-[calc(50%-0.25rem)] group-active:right-[calc(50%-0.5rem)]"
|
||||
)}
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
variant == 'label' && 'grid-cols-[auto_1fr] items-center gap-2',
|
||||
'grid relative cursor-pointer p-2 select-none group',
|
||||
disabled && 'pointer-events-none opacity-50',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{variant == "theme" && (
|
||||
<>
|
||||
<div
|
||||
{/* Основной контейнер, */}
|
||||
<div
|
||||
className={cn(
|
||||
"absolute transition-all duration-300",
|
||||
switchVariants.iconSize[size],
|
||||
active ? "opacity-100 scale-100" : "opacity-0 scale-50"
|
||||
' flex items-center justify-center box-border z-10 relative transition-all duration-300 rounded-full',
|
||||
sizeVariants[size],
|
||||
active ? colorsVariants[color] : 'bg-default-200',
|
||||
)}
|
||||
>
|
||||
{moon}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"absolute transition-all duration-300",
|
||||
switchVariants.iconSize[size],
|
||||
active ? "opacity-0 scale-50" : "opacity-100 scale-100"
|
||||
)}
|
||||
>
|
||||
{sun}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
>
|
||||
{/* Скрытый checkbox */}
|
||||
<input
|
||||
className={cn(
|
||||
'absolute opacity-0 -z-10 h-0 w-0',
|
||||
focuseOutlineVariants[color],
|
||||
)}
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
onChange={() => {
|
||||
setActive(!active);
|
||||
}}
|
||||
/>
|
||||
|
||||
{variant == "label" && (
|
||||
<div className="select-none text-layout-foreground transition-all duration-200">
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
</label>
|
||||
);
|
||||
<div
|
||||
className={cn(
|
||||
'absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-300 rounded-full',
|
||||
sizeVariants[size],
|
||||
)}
|
||||
></div>
|
||||
|
||||
{/* Шарик */}
|
||||
<span
|
||||
className={cn(
|
||||
'bg-white rounded-full absolute transition-all duration-300 m-1 flex items-center justify-center',
|
||||
switchVariants.size[size],
|
||||
switchVariants.activeSize[size],
|
||||
active
|
||||
? 'right-[0%]'
|
||||
: 'right-[calc(50%-0.25rem)] group-active:right-[calc(50%-0.5rem)]',
|
||||
)}
|
||||
>
|
||||
{variant == 'theme' && (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'absolute transition-all duration-300',
|
||||
switchVariants.iconSize[size],
|
||||
active
|
||||
? 'opacity-100 scale-100'
|
||||
: 'opacity-0 scale-50',
|
||||
)}
|
||||
>
|
||||
{moon}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'absolute transition-all duration-300',
|
||||
switchVariants.iconSize[size],
|
||||
active
|
||||
? 'opacity-0 scale-50'
|
||||
: 'opacity-100 scale-100',
|
||||
)}
|
||||
>
|
||||
{sun}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{variant == 'label' && (
|
||||
<div className="select-none text-layout-foreground transition-all duration-200">
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user