"use client";
import { type ReactNode, useEffect } from "react";
import {
BrowserRouter,
MemoryRouter,
Navigate,
Outlet,
Route,
Routes,
useLocation,
} from "react-router-dom";
import {
OnboardingProvider,
type OnboardingStepConfig,
type OnboardingWizardConfig,
} from "./onboarding-context";
// =============================================================================
// UTILS
// =============================================================================
/**
* Detect if we're running inside Next.js
* Uses __NEXT_DATA__ which is set by Next.js on the window object
*/
function isNextJs(): boolean {
if (typeof window === "undefined") return false;
return "__NEXT_DATA__" in window;
}
/**
* Get the initial path from the current browser URL, relative to basePath
*/
function getInitialPathFromUrl(basePath: string): string {
if (typeof window === "undefined") return "/";
const normalizedBase = basePath.endsWith("/")
? basePath.slice(0, -1)
: basePath;
const currentPath = window.location.pathname;
if (currentPath.startsWith(normalizedBase)) {
const relativePath = currentPath.slice(normalizedBase.length);
return relativePath || "/";
}
return "/";
}
// =============================================================================
// URL SYNC (for MemoryRouter in Next.js)
// =============================================================================
function UrlSync({ basePath }: { basePath: string }) {
const location = useLocation();
useEffect(() => {
const normalizedBase = basePath.endsWith("/")
? basePath.slice(0, -1)
: basePath;
const path = location.pathname === "/" ? "" : location.pathname;
const fullPath = `${normalizedBase}${path}${location.search}${location.hash}`;
if (
window.location.pathname +
window.location.search +
window.location.hash !==
fullPath
) {
window.history.replaceState(null, "", fullPath);
}
}, [location, basePath]);
return null;
}
// =============================================================================
// ONBOARDING ROUTES
// =============================================================================
interface OnboardingRoutesProps {
steps: OnboardingStepConfig[];
layout?: React.ComponentType<{ children: ReactNode }>;
}
function OnboardingRoutes({ steps, layout: Layout }: OnboardingRoutesProps) {
const firstStepPath = steps[0]?.path || "";
// Wrapper to match dashboard pattern - Layout wraps an Outlet
const LayoutWrapper = Layout
? () => (
( Component: React.ComponentType
, ): React.ComponentType< Omit
> { return function WrappedComponent( props: Omit
,
) {
const { useOnboarding } = require("./onboarding-context");
const onboardingProps = useOnboarding();
return