mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-13 09:25:07 +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
@ -3,11 +3,11 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
|
|||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
|
|
||||||
import { Transition } from "@/components/Transition";
|
import { Transition } from "@/components/Transition";
|
||||||
|
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||||
|
|
||||||
export interface OverlayProps {
|
export interface OverlayProps {
|
||||||
|
id: string;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
onClose?: () => void;
|
|
||||||
show?: boolean;
|
|
||||||
darken?: boolean;
|
darken?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ export function OverlayDisplay(props: { children: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Overlay(props: OverlayProps) {
|
export function Overlay(props: OverlayProps) {
|
||||||
|
const router = useOverlayRouter(props.id);
|
||||||
const [portalElement, setPortalElement] = useState<Element | null>(null);
|
const [portalElement, setPortalElement] = useState<Element | null>(null);
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const target = useRef<Element | null>(null);
|
const target = useRef<Element | null>(null);
|
||||||
@ -37,9 +38,9 @@ export function Overlay(props: OverlayProps) {
|
|||||||
if (e.currentTarget !== e.target) return;
|
if (e.currentTarget !== e.target) return;
|
||||||
if (!startedTarget) return;
|
if (!startedTarget) return;
|
||||||
if (!startedTarget.isEqualNode(e.currentTarget as Element)) return;
|
if (!startedTarget.isEqualNode(e.currentTarget as Element)) return;
|
||||||
if (props.onClose) props.onClose();
|
router.close();
|
||||||
},
|
},
|
||||||
[props]
|
[router]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -47,25 +48,21 @@ export function Overlay(props: OverlayProps) {
|
|||||||
setPortalElement(element ?? document.body);
|
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 (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
{portalElement
|
{portalElement
|
||||||
? createPortal(
|
? 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">
|
<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>
|
<Transition animation="slide-up" className="h-0" isChild>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Transition>
|
</Transition>
|
||||||
|
@ -13,7 +13,7 @@ interface Props {
|
|||||||
active?: boolean; // true if a child view is loaded
|
active?: boolean; // true if a child view is loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FloatingView(props: Props) {
|
export function OverlayPage(props: Props) {
|
||||||
const { isMobile } = useIsMobile();
|
const { isMobile } = useIsMobile();
|
||||||
const width = !isMobile ? `${props.width}px` : "100%";
|
const width = !isMobile ? `${props.width}px` : "100%";
|
||||||
return (
|
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 [route, setRoute] = useQueryParam("r");
|
||||||
const routeParts = (route ?? "").split("/").filter((v) => v.length > 0);
|
const routeParts = (route ?? "").split("/").filter((v) => v.length > 0);
|
||||||
const routerActive = routeParts.length > 0 && routeParts[0] === id;
|
const routerActive = routeParts.length > 0 && routeParts[0] === id;
|
||||||
const currentPage = routeParts[routeParts.length - 1] ?? "/";
|
|
||||||
|
|
||||||
function navigate(path: string) {
|
function navigate(path: string) {
|
||||||
const newRoute = [id, ...path.split("/").filter((v) => v.length > 0)];
|
const newRoute = [id, ...path.split("/").filter((v) => v.length > 0)];
|
||||||
@ -20,7 +19,7 @@ export function useOverlayRouter(id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isCurrentPage(page: string) {
|
function isCurrentPage(page: string) {
|
||||||
return routerActive && page === currentPage;
|
return routerActive && route === `/${id}${page}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLoaded(page: string) {
|
function isLoaded(page: string) {
|
||||||
@ -40,7 +39,11 @@ export function useOverlayRouter(id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
navigate("/");
|
setRoute(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
setRoute(`/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -51,5 +54,6 @@ export function useOverlayRouter(id: string) {
|
|||||||
isCurrentPage,
|
isCurrentPage,
|
||||||
pageProps,
|
pageProps,
|
||||||
isActive,
|
isActive,
|
||||||
|
open,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
|
|
||||||
export function useQueryParams() {
|
export function useQueryParams() {
|
||||||
const loc = useLocation();
|
const loc = useLocation();
|
||||||
@ -19,6 +19,7 @@ export function useQueryParams() {
|
|||||||
export function useQueryParam(param: string) {
|
export function useQueryParam(param: string) {
|
||||||
const params = useQueryParams();
|
const params = useQueryParams();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
const router = useHistory();
|
||||||
const currentValue = params[param];
|
const currentValue = params[param];
|
||||||
|
|
||||||
const set = useCallback(
|
const set = useCallback(
|
||||||
@ -26,9 +27,11 @@ export function useQueryParam(param: string) {
|
|||||||
const parsed = new URLSearchParams(location.search);
|
const parsed = new URLSearchParams(location.search);
|
||||||
if (value) parsed.set(param, value);
|
if (value) parsed.set(param, value);
|
||||||
else parsed.delete(param);
|
else parsed.delete(param);
|
||||||
location.search = parsed.toString();
|
router.push({
|
||||||
|
search: parsed.toString(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[param, location]
|
[param, location, router]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [currentValue, set] as const;
|
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
|
// simple empty view, perfect for putting in tests
|
||||||
export default function TestView() {
|
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 New Issue
Block a user