This commit is contained in:
Benjamin Toby
2025-07-20 10:35:54 +01:00
parent dd1d05251d
commit a0a0ab8ee4
99 changed files with 5678 additions and 909 deletions
@@ -0,0 +1,63 @@
import React, { DetailedHTMLProps, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
import ReactDOM from "react-dom";
import Button from "../layout/Button";
import { X } from "lucide-react";
import { TWUI_MODAL_PROPS } from "../elements/Modal";
import Paper from "../elements/Paper";
import _ from "lodash";
type Props = TWUI_MODAL_PROPS & {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
/**
* # Modal Main Component
*/
export default function ModalComponent({ open, setOpen, ...props }: Props) {
if (!open) return null;
return ReactDOM.createPortal(
<div
className={twMerge(
"fixed z-[200] top-0 left-0 w-screen h-screen",
"flex flex-col items-center justify-center",
"twui-modal-root"
)}
>
<div
className={twMerge(
"absolute top-0 left-0 bg-dark/80 z-0",
"w-screen h-screen"
)}
onClick={(e) => {
setOpen(false);
}}
></div>
<Paper
{..._.omit(props, ["targetWrapperProps"])}
className={twMerge(
"z-10 max-w-[500px] bg-background-light dark:bg-background-dark",
"w-full relative max-h-[95vh] overflow-y-auto",
"twui-modal-content",
props.className
)}
>
{props.children}
<Button
className="absolute top-0 right-0 p-2"
variant="ghost"
color="gray"
onClick={() => {
setOpen(false);
}}
title="Close Modal Button"
>
<X size={30} />
</Button>
</Paper>
</div>,
document.getElementById("twui-modal-root") as HTMLElement
);
}
@@ -0,0 +1,113 @@
import React from "react";
import { twMerge } from "tailwind-merge";
import ReactDOM from "react-dom";
import { TWUI_MODAL_PROPS } from "../elements/Modal";
import Paper from "../elements/Paper";
import _ from "lodash";
import twuiGrabPopoverStyles from "../(functions)/popver/grab-popover-styles";
type Props = TWUI_MODAL_PROPS & {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
targetElRef?: React.RefObject<HTMLElement | null>;
popoverTargetActiveRef: React.MutableRefObject<boolean>;
popoverContentActiveRef: React.MutableRefObject<boolean>;
};
/**
* # Modal Main Component
*/
export default function PopoverComponent({
open,
setOpen,
targetElRef,
position = "bottom",
trigger = "hover",
debounce,
popoverTargetActiveRef,
popoverContentActiveRef,
popoverReferenceRef,
isPopover,
...props
}: Props) {
if (!open) return null;
const [style, setStyle] = React.useState({});
React.useEffect(() => {
if (open && targetElRef?.current) {
const popoverStyle = twuiGrabPopoverStyles({
position,
targetElRef,
});
setStyle(popoverStyle);
}
}, [open, targetElRef, position]);
let closeTimeout: any;
const popoverEnterFn = React.useCallback(() => {
popoverContentActiveRef.current = true;
popoverTargetActiveRef.current = false;
setOpen(true);
}, []);
const popoverLeaveFn = React.useCallback(() => {
window.clearTimeout(closeTimeout);
closeTimeout = setTimeout(() => {
if (popoverTargetActiveRef.current) {
popoverTargetActiveRef.current = false;
return;
}
setOpen(false);
}, debounce);
}, []);
if (!open) return null;
return ReactDOM.createPortal(
<Paper
{...props}
className={twMerge(
"max-w-[300px]",
"twui-popover-content",
props.className
)}
style={{ ...style, ...props.style }}
onMouseEnter={
trigger === "hover" ? popoverEnterFn : props.onMouseEnter
}
onMouseLeave={
trigger === "hover" ? popoverLeaveFn : props.onMouseLeave
}
>
{/* <div
className="absolute w-0 h-0 border-8 border-transparent bg-white"
style={{
...(position === "bottom" && {
top: "-16px",
left: "50%",
transform: "translateX(-50%)",
}),
...(position === "top" && {
bottom: "-16px",
left: "50%",
transform: "translateX(-50%)",
}),
...(position === "right" && {
top: "50%",
left: "-16px",
transform: "translateY(-50%)",
}),
...(position === "left" && {
top: "50%",
right: "-16px",
transform: "translateY(-50%)",
}),
}}
/> */}
{props.children}
</Paper>,
document.getElementById("twui-popover-root") as HTMLElement
);
}