Add react-qr-code dependency; enhance PopupHeader and SharePopup components with draggable functionality; update LinkShare component for improved UI; integrate SettingsModal in HomePage for better user experience.
This commit is contained in:
@@ -18,40 +18,42 @@ export default function LinkShare({ link }: { link: string }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-[3.75vw] bg-[#F3F3F3] flex items-center justify-between gap-[0.833vw] px-[1.111vw] rounded-[1.111vw] relative">
|
||||
<span
|
||||
className="text-ellipsis text-s hover:cursor-pointer overflow-hidden"
|
||||
onClick={handleCopy}
|
||||
>
|
||||
{link}
|
||||
</span>
|
||||
|
||||
{shareState === "default" && (
|
||||
<Button
|
||||
variant="cta"
|
||||
size="medium"
|
||||
className="translate-x-[0.556vw]"
|
||||
<div className="flex flex-col gap-[0.556vw]">
|
||||
<div className="w-full h-[3.75vw] bg-[#F3F3F3] flex items-center justify-between gap-[0.833vw] px-[1.111vw] rounded-[1.111vw] relative">
|
||||
<span
|
||||
className="text-ellipsis text-s hover:cursor-pointer overflow-hidden"
|
||||
onClick={handleCopy}
|
||||
>
|
||||
Копировать
|
||||
</Button>
|
||||
)}
|
||||
{link}
|
||||
</span>
|
||||
|
||||
{shareState === "loading" && (
|
||||
<div className="size-[1.389vw] text-[#7B60F3] animate-spin">
|
||||
<LoaderIcon />
|
||||
</div>
|
||||
)}
|
||||
{shareState === "default" && (
|
||||
<Button
|
||||
variant="cta"
|
||||
size="medium"
|
||||
className="translate-x-[0.556vw]"
|
||||
onClick={handleCopy}
|
||||
>
|
||||
Копировать
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{shareState === "done" && (
|
||||
<>
|
||||
{shareState === "loading" && (
|
||||
<div className="size-[1.389vw] text-[#7B60F3] animate-spin">
|
||||
<LoaderIcon />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shareState === "done" && (
|
||||
<div className="size-[1.389vw] text-[#7B60F3]">
|
||||
<CheckIcon />
|
||||
</div>
|
||||
<div className="caption-s absolute bottom-[-1.25vw] text-[#29AF61] left-0">
|
||||
Ссылка скопирована
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{shareState === "done" && (
|
||||
<div className="caption-s absolutea bottom-[-1.25vw] text-[#29AF61] left-0">
|
||||
Ссылка скопирована
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
interface RangeInputProps {
|
||||
max?: number;
|
||||
min?: number;
|
||||
value?: number;
|
||||
onChange: (value: number) => void;
|
||||
}
|
||||
|
||||
function RangeInput({
|
||||
onChange,
|
||||
value = 50,
|
||||
max = 100,
|
||||
min = 0,
|
||||
}: RangeInputProps) {
|
||||
const [mouseDown, setMouseDown] = useState(false);
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
addEventListener("mouseup", () => setMouseDown(false));
|
||||
addEventListener("mousemove", handleMouseMove);
|
||||
return () => {
|
||||
removeEventListener("mouseup", () => setMouseDown(false));
|
||||
removeEventListener("mousemove", handleMouseMove);
|
||||
};
|
||||
}, [handleMouseMove]);
|
||||
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
if (mouseDown && ref.current) {
|
||||
onChange(
|
||||
Math.min(
|
||||
Math.max(
|
||||
min,
|
||||
((e.clientX - ref.current.getBoundingClientRect().left) /
|
||||
ref.current.clientWidth) *
|
||||
(max - min) +
|
||||
min
|
||||
),
|
||||
max
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function handleMouseDown(e: React.MouseEvent<HTMLDivElement>) {
|
||||
e.preventDefault();
|
||||
if (ref.current) {
|
||||
onChange(
|
||||
Math.min(
|
||||
Math.max(
|
||||
min,
|
||||
((e.clientX - ref.current.getBoundingClientRect().left) /
|
||||
ref.current.clientWidth) *
|
||||
(max - min) +
|
||||
min
|
||||
),
|
||||
max
|
||||
)
|
||||
);
|
||||
}
|
||||
setMouseDown(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="2xl:w-[21.111vw] w-[304px] 2xl:h-[0.139vw] h-[2px] relative bg-[#F0F0F0] 2xl:rounded-[0.556vw] rounded-lg cursor-grab active:cursor-grabbing"
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<div
|
||||
className="bg-[#7B60F3] 2xl:rounded-[0.556vw] h-full absolute left-0 top-0 rounded-lg"
|
||||
style={{ width: `${((value - min) / (max - min)) * 100}%` }}
|
||||
/>
|
||||
<div
|
||||
className="2xl:size-[0.833vw] size-3 rounded-full bg-[#7B60F3] absolute top-1/2 -translate-y-1/2"
|
||||
style={{ left: `${((value - min) / (max - min)) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RangeInput;
|
||||
@@ -0,0 +1,29 @@
|
||||
import clsx from "clsx";
|
||||
|
||||
interface SwitchProps {
|
||||
enabled: boolean;
|
||||
onChange: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
function Switch({ enabled, onChange }: SwitchProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={() => onChange(!enabled)}
|
||||
className={clsx(
|
||||
"2xl:rounded-[0.833vw] rounded-xl 2xl:w-[2.778vw] w-10 2xl:py-[0.139vw] py-[2px] cursor-pointer transition-colors",
|
||||
enabled ? "bg-[#7B60F3]" : "bg-[#F0F0F0]"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"rounded-full 2xl:size-[1.389vw] size-5 bg-white shadow-[0_4px_40px_0_rgba(15,16,17,0.1)] transition-all",
|
||||
enabled
|
||||
? "2xl:translate-x-[1.25vw] translate-x-[18px]"
|
||||
: "2xl:translate-x-[0.139vw] translate-x-[2px]"
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Switch;
|
||||
Reference in New Issue
Block a user