19 changed files with 222 additions and 151 deletions
@ -1,18 +1,90 @@ |
|||||||
import { ReactNode } from "react"; |
import { a, easings, useSpring } from "@react-spring/web"; |
||||||
|
import { ReactNode, useEffect, useMemo, useRef } from "react"; |
||||||
|
|
||||||
import { OverlayAnchorPosition } from "@/components/overlays/positions/OverlayAnchorPosition"; |
import { OverlayAnchorPosition } from "@/components/overlays/positions/OverlayAnchorPosition"; |
||||||
import { OverlayMobilePosition } from "@/components/overlays/positions/OverlayMobilePosition"; |
import { OverlayMobilePosition } from "@/components/overlays/positions/OverlayMobilePosition"; |
||||||
import { useIsMobile } from "@/hooks/useIsMobile"; |
import { useIsMobile } from "@/hooks/useIsMobile"; |
||||||
|
import { useInternalOverlayRouter } from "@/hooks/useOverlayRouter"; |
||||||
|
import { useOverlayStore } from "@/stores/overlay/store"; |
||||||
|
|
||||||
interface OverlayRouterProps { |
interface OverlayRouterProps { |
||||||
children?: ReactNode; |
children?: ReactNode; |
||||||
id: string; |
id: string; |
||||||
} |
} |
||||||
|
|
||||||
|
function RouterBase(props: { id: string; children: ReactNode }) { |
||||||
|
const ref = useRef<HTMLDivElement>(null); |
||||||
|
const { isMobile } = useIsMobile(); |
||||||
|
|
||||||
|
const routes = useOverlayStore((s) => s.routes); |
||||||
|
const router = useInternalOverlayRouter(props.id); |
||||||
|
const routeMeta = useMemo( |
||||||
|
() => routes[router.currentRoute ?? ""], |
||||||
|
[routes, router] |
||||||
|
); |
||||||
|
|
||||||
|
const [dimensions, api] = useSpring( |
||||||
|
() => ({ |
||||||
|
from: { |
||||||
|
height: `${routeMeta?.height ?? 0}px`, |
||||||
|
width: isMobile ? "100%" : `${routeMeta?.width ?? 0}px`, |
||||||
|
}, |
||||||
|
config: { |
||||||
|
easing: easings.linear, |
||||||
|
}, |
||||||
|
}), |
||||||
|
[] |
||||||
|
); |
||||||
|
|
||||||
|
const currentState = useRef<null | string>(null); |
||||||
|
useEffect(() => { |
||||||
|
const data = { |
||||||
|
height: routeMeta?.height, |
||||||
|
width: routeMeta?.width, |
||||||
|
isMobile, |
||||||
|
}; |
||||||
|
const dataStr = JSON.stringify(data); |
||||||
|
if (dataStr !== currentState.current) { |
||||||
|
const oldData = currentState.current |
||||||
|
? JSON.parse(currentState.current) |
||||||
|
: null; |
||||||
|
currentState.current = dataStr; |
||||||
|
if (data.isMobile) { |
||||||
|
api.set({ |
||||||
|
width: "100%", |
||||||
|
}); |
||||||
|
api({ |
||||||
|
height: `${routeMeta?.height ?? 0}px`, |
||||||
|
}); |
||||||
|
} else if (oldData?.height === undefined && data.height !== undefined) { |
||||||
|
api.set({ |
||||||
|
height: `${routeMeta?.height ?? 0}px`, |
||||||
|
width: `${routeMeta?.width ?? 0}px`, |
||||||
|
}); |
||||||
|
} else { |
||||||
|
api({ |
||||||
|
height: `${routeMeta?.height ?? 0}px`, |
||||||
|
width: `${routeMeta?.width ?? 0}px`, |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}, [routeMeta?.height, routeMeta?.width, isMobile, api]); |
||||||
|
|
||||||
|
return ( |
||||||
|
<a.div |
||||||
|
ref={ref} |
||||||
|
style={dimensions} |
||||||
|
className="relative flex items-center justify-center overflow-hidden bg-red-500" |
||||||
|
> |
||||||
|
{props.children} |
||||||
|
</a.div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
export function OverlayRouter(props: OverlayRouterProps) { |
export function OverlayRouter(props: OverlayRouterProps) { |
||||||
const { isMobile } = useIsMobile(); |
const { isMobile } = useIsMobile(); |
||||||
const content = props.children; |
const content = <RouterBase id={props.id}>{props.children}</RouterBase>; |
||||||
|
|
||||||
if (isMobile) return <OverlayMobilePosition>{content}</OverlayMobilePosition>; |
if (isMobile) return <OverlayMobilePosition>{content}</OverlayMobilePosition>; |
||||||
return <OverlayAnchorPosition id={props.id}>{content}</OverlayAnchorPosition>; |
return <OverlayAnchorPosition>{content}</OverlayAnchorPosition>; |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue