mirror of
https://github.com/movie-web/movie-web.git
synced 2024-06-03 05:08:45 +02:00
138 lines
3.4 KiB
TypeScript
138 lines
3.4 KiB
TypeScript
import { useCallback, useEffect, useMemo } from "react";
|
|
|
|
import { useQueryParam } from "@/hooks/useQueryParams";
|
|
import { useOverlayStore } from "@/stores/overlay/store";
|
|
|
|
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 useRouterAnchorUpdate(id: string) {
|
|
const [route] = useQueryParam("r");
|
|
const setAnchorPoint = useOverlayStore((s) => s.setAnchorPoint);
|
|
const routerActive = useMemo(
|
|
() => !!route && route.startsWith(`/${id}`),
|
|
[route, id],
|
|
);
|
|
|
|
const update = useCallback(() => {
|
|
if (!routerActive) return;
|
|
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,
|
|
});
|
|
}
|
|
}, [routerActive, setAnchorPoint, id]);
|
|
|
|
useEffect(() => {
|
|
update();
|
|
}, [routerActive, update]);
|
|
|
|
useEffect(() => {
|
|
function resizeEvent() {
|
|
update();
|
|
}
|
|
window.addEventListener("resize", resizeEvent);
|
|
return () => {
|
|
window.removeEventListener("resize", resizeEvent);
|
|
};
|
|
}, [update]);
|
|
}
|
|
|
|
export function useInternalOverlayRouter(id: string) {
|
|
const [route, setRoute] = useQueryParam("r");
|
|
const transition = useOverlayStore((s) => s.transition);
|
|
const setTransition = useOverlayStore((s) => s.setTransition);
|
|
const routerActive = !!route && route.startsWith(`/${id}`);
|
|
|
|
function makePath(path: string) {
|
|
return joinPath(splitPath(path, id));
|
|
}
|
|
|
|
function navigate(path: string) {
|
|
const oldRoute = route;
|
|
const newRoute = joinPath(splitPath(path, id));
|
|
setTransition({
|
|
from: oldRoute ?? "/",
|
|
to: newRoute,
|
|
});
|
|
setRoute(newRoute);
|
|
}
|
|
|
|
function showBackwardsTransition(path: string) {
|
|
if (!transition) return "none";
|
|
const current = joinPath(splitPath(path, id));
|
|
|
|
if (current === transition.to && transition.from.startsWith(transition.to))
|
|
return "yes";
|
|
if (
|
|
current === transition.from &&
|
|
transition.to.startsWith(transition.from)
|
|
)
|
|
return "yes";
|
|
return "no";
|
|
}
|
|
|
|
function isCurrentPage(path: string) {
|
|
return routerActive && route === joinPath(splitPath(path, id));
|
|
}
|
|
|
|
function isOverlayActive() {
|
|
return routerActive;
|
|
}
|
|
|
|
const close = useCallback(
|
|
(preventRouteClear?: boolean) => {
|
|
if (route && !preventRouteClear) setRoute(null);
|
|
setTransition(null);
|
|
},
|
|
[setRoute, route, setTransition],
|
|
);
|
|
|
|
const open = useCallback(
|
|
(defaultRoute = "/") => {
|
|
setTransition(null);
|
|
setRoute(joinPath(splitPath(defaultRoute, id)));
|
|
},
|
|
[id, setRoute, setTransition],
|
|
);
|
|
|
|
const activeRoute = routerActive
|
|
? joinPath(splitPath(route.slice(`/${id}`.length)))
|
|
: "/";
|
|
|
|
return {
|
|
activeRoute,
|
|
showBackwardsTransition,
|
|
isCurrentPage,
|
|
isOverlayActive,
|
|
navigate,
|
|
close,
|
|
open,
|
|
makePath,
|
|
currentRoute: route,
|
|
};
|
|
}
|
|
|
|
export function useOverlayRouter(id: string) {
|
|
const router = useInternalOverlayRouter(id);
|
|
return {
|
|
id,
|
|
route: router.activeRoute,
|
|
isRouterActive: router.isOverlayActive(),
|
|
open: router.open,
|
|
close: router.close,
|
|
navigate: router.navigate,
|
|
};
|
|
}
|