mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-09-04 22:46:55 +08:00
feat: function delete chat dev done
This commit is contained in:
136
app/components/Confirm/index.tsx
Normal file
136
app/components/Confirm/index.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import React, { useState } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import * as AlertDialog from "@radix-ui/react-alert-dialog";
|
||||
import Warning from "@/app/icons/warning.svg";
|
||||
import Btn from "@/app/components/Btn";
|
||||
|
||||
interface ConfirmProps {
|
||||
onOk?: () => Promise<void> | void;
|
||||
onCancel?: () => void;
|
||||
okText: string;
|
||||
cancelText: string;
|
||||
content: React.ReactNode;
|
||||
title: React.ReactNode;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
const baseZIndex = 150;
|
||||
|
||||
const Confirm = (props: ConfirmProps) => {
|
||||
const { visible, onOk, onCancel, okText, cancelText, content, title } = props;
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const mergeOpen = visible ?? open;
|
||||
|
||||
return (
|
||||
<AlertDialog.Root open={mergeOpen} onOpenChange={setOpen}>
|
||||
<AlertDialog.Portal>
|
||||
<AlertDialog.Overlay
|
||||
className="bg-confirm-mask fixed inset-0 animate-mask "
|
||||
style={{ zIndex: baseZIndex - 1 }}
|
||||
/>
|
||||
<AlertDialog.Content
|
||||
className={`
|
||||
fixed inset-0 flex flex-col item-start top-0 left-[50vw] translate-x-[-50%]
|
||||
`}
|
||||
style={{ zIndex: baseZIndex - 1 }}
|
||||
>
|
||||
<div className="flex-1"> </div>
|
||||
<div
|
||||
className={`flex flex-col
|
||||
bg-confirm-panel text-confirm-mask
|
||||
md:p-6 md:w-confirm md:gap-6 md:rounded-lg
|
||||
`}
|
||||
>
|
||||
<AlertDialog.Title
|
||||
className={`
|
||||
flex items-center justify-start gap-3 font-common
|
||||
md:text-chat-header-title md:font-bold md:leading-5
|
||||
`}
|
||||
>
|
||||
<Warning />
|
||||
{title}
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description
|
||||
className={`
|
||||
font-common font-normal
|
||||
md:text-sm-title md:leading-[158%]
|
||||
`}
|
||||
>
|
||||
{content}
|
||||
</AlertDialog.Description>
|
||||
<div
|
||||
style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}
|
||||
>
|
||||
<AlertDialog.Cancel asChild>
|
||||
<Btn
|
||||
className={`
|
||||
md:px-4 md:py-2.5 bg-delete-chat-cancel-btn border border-delete-chat-cancel-btn text-text-delete-chat-cancel-btn rounded-md
|
||||
`}
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
onCancel?.();
|
||||
}}
|
||||
text={cancelText}
|
||||
/>
|
||||
</AlertDialog.Cancel>
|
||||
<AlertDialog.Action asChild>
|
||||
<Btn
|
||||
className={`
|
||||
md:px-4 md:py-2.5 bg-delete-chat-ok-btn text-text-delete-chat-ok-btn rounded-md
|
||||
`}
|
||||
onClick={() => {
|
||||
const toDo = onOk?.();
|
||||
if (toDo instanceof Promise) {
|
||||
toDo.then(() => {
|
||||
setOpen(false);
|
||||
});
|
||||
} else {
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
text={okText}
|
||||
/>
|
||||
</AlertDialog.Action>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1"> </div>
|
||||
</AlertDialog.Content>
|
||||
</AlertDialog.Portal>
|
||||
</AlertDialog.Root>
|
||||
);
|
||||
};
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.id = "confirm-root";
|
||||
div.style.height = "0px";
|
||||
document.body.appendChild(div);
|
||||
|
||||
const show = (props: Omit<ConfirmProps, "visible" | "onCancel" | "onOk">) => {
|
||||
const root = createRoot(div);
|
||||
const closeModal = () => {
|
||||
root.unmount();
|
||||
};
|
||||
|
||||
return new Promise<boolean>((resolve) => {
|
||||
root.render(
|
||||
<Confirm
|
||||
{...props}
|
||||
visible={true}
|
||||
onCancel={() => {
|
||||
closeModal();
|
||||
resolve(false);
|
||||
}}
|
||||
onOk={() => {
|
||||
closeModal();
|
||||
resolve(true);
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
Confirm.show = show;
|
||||
|
||||
export default Confirm;
|
@@ -52,13 +52,13 @@ export function ListItem(props: ListItemProps) {
|
||||
|
||||
const context = useContext(ListContext);
|
||||
|
||||
const [childrenType, setMeta] = useState<ChildrenMeta["type"]>("unknown");
|
||||
const [childrenMeta, setMeta] = useState<ChildrenMeta>({});
|
||||
|
||||
const { inputNextLine, rangeNextLine } = context;
|
||||
|
||||
let internalNextLine;
|
||||
|
||||
switch (childrenType) {
|
||||
switch (childrenMeta.type) {
|
||||
case "input":
|
||||
internalNextLine = !!(nextline || inputNextLine);
|
||||
break;
|
||||
@@ -69,8 +69,8 @@ export function ListItem(props: ListItemProps) {
|
||||
internalNextLine = false;
|
||||
}
|
||||
|
||||
const updateType = useCallback((m: ChildrenMeta) => {
|
||||
setMeta(m.type);
|
||||
const update = useCallback((m: ChildrenMeta) => {
|
||||
setMeta(m);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -88,7 +88,7 @@ export function ListItem(props: ListItemProps) {
|
||||
<div className={` text-sm text-text-list-subtitle`}>{subTitle}</div>
|
||||
)}
|
||||
</div>
|
||||
<ListContext.Provider value={{ ...context, update: updateType }}>
|
||||
<ListContext.Provider value={{ ...context, update }}>
|
||||
<div
|
||||
className={`${
|
||||
internalNextLine ? "mt-[0.625rem]" : "max-w-[70%]"
|
||||
|
@@ -86,13 +86,13 @@ export default function MenuLayout<
|
||||
/>
|
||||
{!isMobileScreen && (
|
||||
<div
|
||||
className={`group absolute right-0 h-[100%] flex items-center`}
|
||||
className={`group/menu-dragger absolute right-0 h-[100%] flex items-center`}
|
||||
onPointerDown={(e) => {
|
||||
startDragWidth.current = config.sidebarWidth;
|
||||
onDragStart(e as any);
|
||||
}}
|
||||
>
|
||||
<div className="opacity-0 group-hover:bg-[rgba($color: #000000, $alpha: 0.01)] group-hover:opacity-20">
|
||||
<div className="opacity-0 group-hover/menu-dragger:bg-[rgba($color: #000000, $alpha: 0.01)] group-hover/menu-dragger:opacity-20">
|
||||
<DragIcon />
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,9 +1,16 @@
|
||||
import useRelativePosition from "@/app/hooks/useRelativePosition";
|
||||
import { getCSSVar } from "@/app/utils";
|
||||
import { useMemo, useState } from "react";
|
||||
import { RefObject, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
const ArrowIcon = ({ color }: { color: string }) => {
|
||||
const ArrowIcon = ({ sibling }: { sibling: RefObject<HTMLDivElement> }) => {
|
||||
const [color, setColor] = useState<string>("");
|
||||
useEffect(() => {
|
||||
if (sibling.current) {
|
||||
const { backgroundColor } = window.getComputedStyle(sibling.current);
|
||||
setColor(backgroundColor);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -33,10 +40,10 @@ if (!popoverRoot) {
|
||||
popoverRoot.style.position = "fixed";
|
||||
popoverRoot.style.bottom = "0";
|
||||
popoverRoot.style.zIndex = "100";
|
||||
popoverRoot.id = "popoverRootName";
|
||||
popoverRoot.id = "popover-root";
|
||||
}
|
||||
|
||||
export default function Popover(props: {
|
||||
export interface PopoverProps {
|
||||
content?: JSX.Element | string;
|
||||
children?: JSX.Element;
|
||||
show?: boolean;
|
||||
@@ -44,10 +51,12 @@ export default function Popover(props: {
|
||||
className?: string;
|
||||
popoverClassName?: string;
|
||||
trigger?: "hover" | "click";
|
||||
placement?: "t" | "lt" | "rt" | "lb" | "rb" | "b";
|
||||
placement?: "t" | "lt" | "rt" | "lb" | "rb" | "b" | "l" | "r";
|
||||
noArrow?: boolean;
|
||||
bgcolor?: string;
|
||||
}) {
|
||||
delayClose?: number;
|
||||
}
|
||||
|
||||
export default function Popover(props: PopoverProps) {
|
||||
const {
|
||||
content,
|
||||
children,
|
||||
@@ -58,7 +67,7 @@ export default function Popover(props: {
|
||||
trigger = "hover",
|
||||
placement = "t",
|
||||
noArrow = false,
|
||||
bgcolor,
|
||||
delayClose = 0,
|
||||
} = props;
|
||||
|
||||
const [internalShow, setShow] = useState(false);
|
||||
@@ -66,111 +75,127 @@ export default function Popover(props: {
|
||||
delay: 0,
|
||||
});
|
||||
|
||||
const {
|
||||
distanceToBottomBoundary = 0,
|
||||
distanceToLeftBoundary = 0,
|
||||
distanceToRightBoundary = -10000,
|
||||
distanceToTopBoundary = 0,
|
||||
targetH = 0,
|
||||
targetW = 0,
|
||||
} = position?.poi || {};
|
||||
|
||||
let placementStyle: React.CSSProperties = {};
|
||||
const popoverCommonClass = `absolute p-2 box-border`;
|
||||
|
||||
const mergedShow = show ?? internalShow;
|
||||
|
||||
let placementClassName;
|
||||
let arrowClassName = "absolute left-[50%] translate-x-[calc(-50%)]";
|
||||
const { arrowClassName, placementStyle } = useMemo(() => {
|
||||
const arrowCommonClassName = `${
|
||||
noArrow ? "hidden" : ""
|
||||
} absolute z-10 left-[50%] translate-x-[calc(-50%)]`;
|
||||
|
||||
arrowClassName += " ";
|
||||
let defaultTopPlacement = true; // when users dont config 't' or 'b'
|
||||
|
||||
switch (placement) {
|
||||
case "b":
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW}px - ${
|
||||
targetW * 0.02
|
||||
}px)`,
|
||||
transform: "translateX(-50%)",
|
||||
};
|
||||
placementClassName =
|
||||
"top-[calc(100%+0.5rem)] left-[50%] translate-x-[calc(-50%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
// case 'l':
|
||||
// placementClassName = '';
|
||||
// break;
|
||||
// case 'r':
|
||||
// placementClassName = '';
|
||||
// break;
|
||||
case "rb":
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "top-[calc(100%+0.5rem)] right-[calc(-2%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
case "rt":
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "bottom-[calc(100%+0.5rem)] right-[calc(-2%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
break;
|
||||
case "lt":
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "bottom-[calc(100%+0.5rem)] left-[calc(-2%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
break;
|
||||
case "lb":
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "top-[calc(100%+0.5rem)] left-[calc(-2%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
case "t":
|
||||
default:
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW}px - ${
|
||||
targetW * 0.02
|
||||
}px)`,
|
||||
transform: "translateX(-50%)",
|
||||
};
|
||||
placementClassName =
|
||||
"bottom-[calc(100%+0.5rem)] left-[50%] translate-x-[calc(-50%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
}
|
||||
const {
|
||||
distanceToBottomBoundary = 0,
|
||||
distanceToLeftBoundary = 0,
|
||||
distanceToRightBoundary = -10000,
|
||||
distanceToTopBoundary = 0,
|
||||
targetH = 0,
|
||||
targetW = 0,
|
||||
} = position?.poi || {};
|
||||
|
||||
if (noArrow) {
|
||||
arrowClassName = "hidden";
|
||||
}
|
||||
if (distanceToBottomBoundary > distanceToTopBoundary) {
|
||||
defaultTopPlacement = false;
|
||||
}
|
||||
|
||||
const internalBgColor = useMemo(() => {
|
||||
return bgcolor ?? getCSSVar("--tip-popover-color");
|
||||
}, [bgcolor]);
|
||||
const placements = {
|
||||
lt: {
|
||||
placementStyle: {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]`,
|
||||
},
|
||||
lb: {
|
||||
placementStyle: {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]`,
|
||||
},
|
||||
rt: {
|
||||
placementStyle: {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]`,
|
||||
},
|
||||
rb: {
|
||||
placementStyle: {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]`,
|
||||
},
|
||||
t: {
|
||||
placementStyle: {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW / 2}px`,
|
||||
transform: "translateX(-50%)",
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]`,
|
||||
},
|
||||
b: {
|
||||
placementStyle: {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW / 2}px`,
|
||||
transform: "translateX(-50%)",
|
||||
},
|
||||
arrowClassName: `${arrowCommonClassName} top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]`,
|
||||
},
|
||||
};
|
||||
|
||||
const getStyle = () => {
|
||||
if (["l", "r"].includes(placement)) {
|
||||
return placements[
|
||||
`${placement}${defaultTopPlacement ? "t" : "b"}` as
|
||||
| "lt"
|
||||
| "lb"
|
||||
| "rb"
|
||||
| "rt"
|
||||
];
|
||||
}
|
||||
return placements[placement as Exclude<typeof placement, "l" | "r">];
|
||||
};
|
||||
|
||||
return getStyle();
|
||||
}, [Object.values(position?.poi || {})]);
|
||||
|
||||
const popoverRef = useRef<HTMLDivElement>(null);
|
||||
const closeTimer = useRef<number>(0);
|
||||
|
||||
if (trigger === "click") {
|
||||
const handleOpen = (e: { currentTarget: any }) => {
|
||||
clearTimeout(closeTimer.current);
|
||||
onShow?.(true);
|
||||
setShow(true);
|
||||
getRelativePosition(e.currentTarget, "");
|
||||
window.document.documentElement.style.overflow = "hidden";
|
||||
};
|
||||
const handleClose = () => {
|
||||
if (delayClose) {
|
||||
closeTimer.current = window.setTimeout(() => {
|
||||
onShow?.(false);
|
||||
setShow(false);
|
||||
}, delayClose);
|
||||
} else {
|
||||
onShow?.(false);
|
||||
setShow(false);
|
||||
}
|
||||
window.document.documentElement.style.overflow = "auto";
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative ${className}`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onShow?.(!mergedShow);
|
||||
setShow(!mergedShow);
|
||||
e.stopPropagation();
|
||||
if (!mergedShow) {
|
||||
getRelativePosition(e.currentTarget, "");
|
||||
window.document.documentElement.style.overflow = "hidden";
|
||||
handleOpen(e);
|
||||
} else {
|
||||
window.document.documentElement.style.overflow = "auto";
|
||||
handleClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -179,29 +204,32 @@ export default function Popover(props: {
|
||||
<>
|
||||
{!noArrow && (
|
||||
<div className={`${arrowClassName}`}>
|
||||
<ArrowIcon color={internalBgColor} />
|
||||
<ArrowIcon sibling={popoverRef} />
|
||||
</div>
|
||||
)}
|
||||
{createPortal(
|
||||
<div
|
||||
className={`${popoverCommonClass} ${popoverClassName} cursor-pointer`}
|
||||
style={{ zIndex: baseZIndex + 1, ...placementStyle }}
|
||||
ref={popoverRef}
|
||||
>
|
||||
{content}
|
||||
</div>,
|
||||
popoverRoot,
|
||||
)}
|
||||
<div
|
||||
className=" fixed w-[100%] h-[100%] top-0 left-0 right-0 bottom-0"
|
||||
style={{ zIndex: baseZIndex }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onShow?.(!mergedShow);
|
||||
setShow(!mergedShow);
|
||||
}}
|
||||
>
|
||||
|
||||
</div>
|
||||
{createPortal(
|
||||
<div
|
||||
className=" fixed w-[100vw] h-[100vh] right-0 bottom-0"
|
||||
style={{ zIndex: baseZIndex }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
|
||||
</div>,
|
||||
popoverRoot,
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -209,18 +237,53 @@ export default function Popover(props: {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`group relative ${className}`}>
|
||||
<div
|
||||
className={`relative ${className}`}
|
||||
onPointerEnter={(e) => {
|
||||
e.preventDefault();
|
||||
clearTimeout(closeTimer.current);
|
||||
onShow?.(true);
|
||||
setShow(true);
|
||||
getRelativePosition(e.currentTarget, "");
|
||||
window.document.documentElement.style.overflow = "hidden";
|
||||
}}
|
||||
onPointerLeave={(e) => {
|
||||
e.preventDefault();
|
||||
if (delayClose) {
|
||||
closeTimer.current = window.setTimeout(() => {
|
||||
onShow?.(false);
|
||||
setShow(false);
|
||||
}, delayClose);
|
||||
} else {
|
||||
onShow?.(false);
|
||||
setShow(false);
|
||||
}
|
||||
window.document.documentElement.style.overflow = "auto";
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
{!noArrow && (
|
||||
<div className={`hidden group-hover:block ${arrowClassName}`}>
|
||||
<ArrowIcon color={internalBgColor} />
|
||||
</div>
|
||||
{mergedShow && (
|
||||
<>
|
||||
<div
|
||||
className={`${
|
||||
noArrow ? "opacity-0" : ""
|
||||
} bg-inherit ${arrowClassName}`}
|
||||
style={{ zIndex: baseZIndex + 1 }}
|
||||
>
|
||||
<ArrowIcon sibling={popoverRef} />
|
||||
</div>
|
||||
{createPortal(
|
||||
<div
|
||||
className={` whitespace-nowrap ${popoverCommonClass} ${popoverClassName} cursor-pointer`}
|
||||
style={{ zIndex: baseZIndex + 1, ...placementStyle }}
|
||||
ref={popoverRef}
|
||||
>
|
||||
{content}
|
||||
</div>,
|
||||
popoverRoot,
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className={`hidden group-hover:block ${popoverCommonClass} ${placementClassName} ${popoverClassName}`}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { useContext, useEffect, useRef } from "react";
|
||||
import { ListContext } from "@/app/components/List";
|
||||
import useResizeObserver from "use-resize-observer";
|
||||
import { useResizeObserver } from "usehooks-ts";
|
||||
|
||||
interface SlideRangeProps {
|
||||
className?: string;
|
||||
@@ -31,13 +31,16 @@ export default function SlideRange(props: SlideRangeProps) {
|
||||
|
||||
const slideRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { ref, width = 1 } = useResizeObserver<HTMLDivElement>();
|
||||
|
||||
ref(slideRef.current);
|
||||
useResizeObserver({
|
||||
ref: slideRef,
|
||||
onResize: () => {
|
||||
setProperty(value);
|
||||
},
|
||||
});
|
||||
|
||||
const transformToWidth = (x: number = start) => {
|
||||
const abs = x - start;
|
||||
const maxWidth = width - margin * 2;
|
||||
const maxWidth = (slideRef.current?.clientWidth || 1) - margin * 2;
|
||||
const result = (abs / stroke) * maxWidth;
|
||||
return result;
|
||||
};
|
||||
@@ -49,10 +52,10 @@ export default function SlideRange(props: SlideRangeProps) {
|
||||
`${initWidth + margin}px`,
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setProperty(value);
|
||||
update?.({ type: "range" });
|
||||
}, [width]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
Reference in New Issue
Block a user