movie-web/src/hooks/useOverlayRouter.ts

103 lines
2.5 KiB
TypeScript
Raw Normal View History

2023-10-09 21:00:58 +02:00
import { useCallback } from "react";
import { useQueryParam } from "@/hooks/useQueryParams";
2023-10-09 21:00:58 +02:00
import { useOverlayStore } from "@/stores/overlay/store";
2023-10-09 21:00:58 +02:00
function splitPath(path: string, prefix?: string): string[] {
const parts = [prefix ?? "", ...path.split("/")];
return parts.filter((v) => v.length > 0);
}
function joinPath(path: string[]): string {
return `/${path.join("/")}`;
}
export function useInternalOverlayRouter(id: string) {
const [route, setRoute] = useQueryParam("r");
2023-10-09 21:00:58 +02:00
const transition = useOverlayStore((s) => s.transition);
const setTransition = useOverlayStore((s) => s.setTransition);
const setAnchorPoint = useOverlayStore((s) => s.setAnchorPoint);
2023-10-09 21:00:58 +02:00
const routerActive = !!route && route.startsWith(`/${id}`);
function makePath(path: string) {
return joinPath(splitPath(path, id));
}
function navigate(path: string) {
2023-10-09 21:00:58 +02:00
const oldRoute = route;
const newRoute = joinPath(splitPath(path, id));
setTransition({
from: oldRoute ?? "/",
to: newRoute,
});
setRoute(newRoute);
}
2023-10-09 21:00:58 +02:00
function showBackwardsTransition(path: string) {
if (!transition) return "none";
2023-10-09 21:00:58 +02:00
const current = joinPath(splitPath(path, id));
2023-10-09 21:00:58 +02:00
if (current === transition.to && transition.from.startsWith(transition.to))
return "yes";
2023-10-09 21:00:58 +02:00
if (
current === transition.from &&
transition.to.startsWith(transition.from)
)
return "yes";
return "no";
}
2023-10-09 21:00:58 +02:00
function isCurrentPage(path: string) {
return routerActive && route === joinPath(splitPath(path, id));
}
function isOverlayActive() {
return routerActive;
}
2023-10-09 21:00:58 +02:00
const close = useCallback(() => {
setTransition(null);
setRoute(null);
2023-10-09 21:00:58 +02:00
}, [setRoute, setTransition]);
2023-10-09 21:00:58 +02:00
const open = useCallback(() => {
const anchor = document.getElementById(`__overlayRouter::${id}`);
if (anchor) {
const rect = anchor.getBoundingClientRect();
setAnchorPoint({
h: rect.height,
w: rect.width,
x: rect.x,
y: rect.y,
});
} else {
setAnchorPoint(null);
}
2023-10-09 21:00:58 +02:00
setTransition(null);
setRoute(`/${id}`);
}, [id, setRoute, setTransition, setAnchorPoint]);
return {
2023-10-09 21:00:58 +02:00
showBackwardsTransition,
isCurrentPage,
isOverlayActive,
navigate,
close,
open,
makePath,
currentRoute: route,
};
}
2023-10-09 21:00:58 +02:00
export function useOverlayRouter(id: string) {
const router = useInternalOverlayRouter(id);
return {
2023-10-09 21:25:52 +02:00
id,
isRouterActive: router.isOverlayActive(),
2023-10-09 21:00:58 +02:00
open: router.open,
close: router.close,
navigate: router.navigate,
};
}