mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
more overlay system testing
Co-authored-by: Jip Frijlink <JipFr@users.noreply.github.com>
This commit is contained in:
parent
a05191e1c4
commit
d9855cb244
6 changed files with 67 additions and 29 deletions
|
@ -3,11 +3,11 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
|
|||
import { createPortal } from "react-dom";
|
||||
|
||||
import { Transition } from "@/components/Transition";
|
||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||
|
||||
export interface OverlayProps {
|
||||
id: string;
|
||||
children?: ReactNode;
|
||||
onClose?: () => void;
|
||||
show?: boolean;
|
||||
darken?: boolean;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ export function OverlayDisplay(props: { children: ReactNode }) {
|
|||
}
|
||||
|
||||
export function Overlay(props: OverlayProps) {
|
||||
const router = useOverlayRouter(props.id);
|
||||
const [portalElement, setPortalElement] = useState<Element | null>(null);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const target = useRef<Element | null>(null);
|
||||
|
@ -37,9 +38,9 @@ export function Overlay(props: OverlayProps) {
|
|||
if (e.currentTarget !== e.target) return;
|
||||
if (!startedTarget) return;
|
||||
if (!startedTarget.isEqualNode(e.currentTarget as Element)) return;
|
||||
if (props.onClose) props.onClose();
|
||||
router.close();
|
||||
},
|
||||
[props]
|
||||
[router]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -47,25 +48,21 @@ export function Overlay(props: OverlayProps) {
|
|||
setPortalElement(element ?? document.body);
|
||||
}, []);
|
||||
|
||||
const backdrop = (
|
||||
<Transition animation="fade" isChild>
|
||||
<div
|
||||
onClick={click}
|
||||
className={classNames({
|
||||
"absolute inset-0": true,
|
||||
"bg-black opacity-90": props.darken,
|
||||
})}
|
||||
/>
|
||||
</Transition>
|
||||
);
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
{portalElement
|
||||
? createPortal(
|
||||
<Transition show={props.show} animation="none">
|
||||
<Transition show={router.isOverlayActive()} animation="none">
|
||||
<div className="popout-wrapper pointer-events-auto fixed inset-0 z-[999] select-none">
|
||||
{backdrop}
|
||||
<Transition animation="fade" isChild>
|
||||
<div
|
||||
onClick={click}
|
||||
className={classNames({
|
||||
"absolute inset-0": true,
|
||||
"bg-black opacity-90": props.darken,
|
||||
})}
|
||||
/>
|
||||
</Transition>
|
||||
<Transition animation="slide-up" className="h-0" isChild>
|
||||
{props.children}
|
||||
</Transition>
|
||||
|
|
|
@ -13,7 +13,7 @@ interface Props {
|
|||
active?: boolean; // true if a child view is loaded
|
||||
}
|
||||
|
||||
export function FloatingView(props: Props) {
|
||||
export function OverlayPage(props: Props) {
|
||||
const { isMobile } = useIsMobile();
|
||||
const width = !isMobile ? `${props.width}px` : "100%";
|
||||
return (
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export function LeftSideControls(props: {children: React.ReactNode}) {
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ export function useOverlayRouter(id: string) {
|
|||
const [route, setRoute] = useQueryParam("r");
|
||||
const routeParts = (route ?? "").split("/").filter((v) => v.length > 0);
|
||||
const routerActive = routeParts.length > 0 && routeParts[0] === id;
|
||||
const currentPage = routeParts[routeParts.length - 1] ?? "/";
|
||||
|
||||
function navigate(path: string) {
|
||||
const newRoute = [id, ...path.split("/").filter((v) => v.length > 0)];
|
||||
|
@ -20,7 +19,7 @@ export function useOverlayRouter(id: string) {
|
|||
}
|
||||
|
||||
function isCurrentPage(page: string) {
|
||||
return routerActive && page === currentPage;
|
||||
return routerActive && route === `/${id}${page}`;
|
||||
}
|
||||
|
||||
function isLoaded(page: string) {
|
||||
|
@ -40,7 +39,11 @@ export function useOverlayRouter(id: string) {
|
|||
}
|
||||
|
||||
function close() {
|
||||
navigate("/");
|
||||
setRoute(null);
|
||||
}
|
||||
|
||||
function open() {
|
||||
setRoute(`/${id}`);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -51,5 +54,6 @@ export function useOverlayRouter(id: string) {
|
|||
isCurrentPage,
|
||||
pageProps,
|
||||
isActive,
|
||||
open,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useCallback, useMemo } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
|
||||
export function useQueryParams() {
|
||||
const loc = useLocation();
|
||||
|
@ -19,6 +19,7 @@ export function useQueryParams() {
|
|||
export function useQueryParam(param: string) {
|
||||
const params = useQueryParams();
|
||||
const location = useLocation();
|
||||
const router = useHistory();
|
||||
const currentValue = params[param];
|
||||
|
||||
const set = useCallback(
|
||||
|
@ -26,9 +27,11 @@ export function useQueryParam(param: string) {
|
|||
const parsed = new URLSearchParams(location.search);
|
||||
if (value) parsed.set(param, value);
|
||||
else parsed.delete(param);
|
||||
location.search = parsed.toString();
|
||||
router.push({
|
||||
search: parsed.toString(),
|
||||
});
|
||||
},
|
||||
[param, location]
|
||||
[param, location, router]
|
||||
);
|
||||
|
||||
return [currentValue, set] as const;
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
import { OverlayAnchor } from "@/components/overlays/OverlayAnchor";
|
||||
import { Overlay, OverlayDisplay } from "@/components/overlays/OverlayDisplay";
|
||||
import { OverlayPage } from "@/components/overlays/OverlayPage";
|
||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||
|
||||
// simple empty view, perfect for putting in tests
|
||||
export default function TestView() {
|
||||
return <div />;
|
||||
const router = useOverlayRouter("test");
|
||||
const pages = ["", "/one", "/two"];
|
||||
|
||||
return (
|
||||
<OverlayDisplay>
|
||||
<div className="h-[400px] w-[800px] flex justify-center items-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
router.open();
|
||||
}}
|
||||
>
|
||||
Open
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
router.navigate(pages[Math.floor(pages.length * Math.random())]);
|
||||
}}
|
||||
>
|
||||
random page
|
||||
</button>
|
||||
<OverlayAnchor id="test">
|
||||
<div className="h-20 w-20 bg-white" />
|
||||
</OverlayAnchor>
|
||||
<Overlay id="test">
|
||||
<OverlayPage {...router.pageProps("")}>Home</OverlayPage>
|
||||
<OverlayPage {...router.pageProps("/one")}>Page one</OverlayPage>
|
||||
<OverlayPage {...router.pageProps("/two")}>Page two</OverlayPage>
|
||||
</Overlay>
|
||||
</div>
|
||||
</OverlayDisplay>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue