ultisuite-client/components/demo/demo-navigation-guard.tsx
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

86 lines
2.3 KiB
TypeScript

"use client"
import { useEffect } from "react"
import { usePathname } from "next/navigation"
import { toast } from "sonner"
import {
getDemoRouteRoot,
isHrefWithinDemoScope,
} from "@/lib/demo/demo-navigation"
const DEMO_NAV_TOAST_ID = "demo-nav-blocked"
function showDemoNavBlockedToast() {
toast.message("Navigation hors démo", {
id: DEMO_NAV_TOAST_ID,
description:
"Créez un compte pour accéder à toute la suite — la démo reste sur cette application.",
})
}
function urlArgToHref(url: string | URL | null | undefined): string | null {
if (url == null || url === "") return null
return typeof url === "string" ? url : url.toString()
}
/** Bloque liens et router client hors du scope `/demo/<app>/…`. */
export function DemoNavigationGuard() {
const pathname = usePathname()
const demoRouteRoot = getDemoRouteRoot(pathname)
useEffect(() => {
if (!demoRouteRoot) return
const origin = window.location.origin
const isAllowed = (href: string | null) => {
if (!href) return true
return isHrefWithinDemoScope(href, demoRouteRoot, origin)
}
const originalPushState = history.pushState.bind(history)
const originalReplaceState = history.replaceState.bind(history)
history.pushState = (state, title, url) => {
const href = urlArgToHref(url)
if (!isAllowed(href)) {
showDemoNavBlockedToast()
return
}
return originalPushState(state, title, url)
}
history.replaceState = (state, title, url) => {
const href = urlArgToHref(url)
if (!isAllowed(href)) {
showDemoNavBlockedToast()
return
}
return originalReplaceState(state, title, url)
}
const handleClick = (event: MouseEvent) => {
const anchor = (event.target as Element).closest("a[href]")
if (!anchor) return
if (anchor.getAttribute("target") === "_blank") return
const href = anchor.getAttribute("href")
if (!href || isAllowed(href)) return
event.preventDefault()
event.stopPropagation()
showDemoNavBlockedToast()
}
document.addEventListener("click", handleClick, true)
return () => {
history.pushState = originalPushState
history.replaceState = originalReplaceState
document.removeEventListener("click", handleClick, true)
}
}, [demoRouteRoot])
return null
}