"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// modules/runtime/client/index.tsx
var client_exports = {};
__export(client_exports, {
  bootstrapClient: () => bootstrapClient
});
module.exports = __toCommonJS(client_exports);

// modules/runtime/client/bootstrap.tsx
var import_client = require("react-dom/client");

// modules/runtime/client/constants.ts
var WINDOW_DATA_KEY = "__FW_DATA__";
var ROUTER_DATA_KEY = "__LOLY_ROUTER_DATA__";
var APP_CONTAINER_ID = "__app";
var ROUTER_NAVIGATE_KEY = "__LOLY_ROUTER_NAVIGATE__";

// modules/runtime/client/window-data.ts
var LAYOUT_PROPS_KEY = "__FW_LAYOUT_PROPS__";
function getWindowData() {
  if (typeof window === "undefined") {
    return null;
  }
  return window[WINDOW_DATA_KEY] ?? null;
}
function getPreservedLayoutProps() {
  if (typeof window === "undefined") {
    return null;
  }
  return window[LAYOUT_PROPS_KEY] ?? null;
}
function setPreservedLayoutProps(props) {
  if (typeof window === "undefined") {
    return;
  }
  if (props === null) {
    delete window[LAYOUT_PROPS_KEY];
  } else {
    window[LAYOUT_PROPS_KEY] = props;
  }
}
function getRouterData() {
  if (typeof window === "undefined") {
    return null;
  }
  return window[ROUTER_DATA_KEY] ?? null;
}
function setWindowData(data) {
  window[WINDOW_DATA_KEY] = data;
  if (typeof window !== "undefined") {
    window.dispatchEvent(
      new CustomEvent("fw-data-refresh", {
        detail: { data }
      })
    );
  }
}
function setRouterData(data) {
  window[ROUTER_DATA_KEY] = data;
  if (typeof window !== "undefined") {
    window.dispatchEvent(
      new CustomEvent("fw-router-data-refresh", {
        detail: { data }
      })
    );
  }
}
function getCurrentTheme() {
  return getWindowData()?.theme ?? null;
}

// modules/runtime/client/route-matcher.ts
function buildClientRegexFromPattern(pattern) {
  const segments = pattern.split("/").filter(Boolean);
  const regexParts = [];
  for (let i = 0; i < segments.length; i++) {
    const seg = segments[i];
    if (seg.startsWith("[...") && seg.endsWith("]")) {
      if (i !== segments.length - 1) {
        throw new Error(
          `Catch-all segment "${seg}" in "${pattern}" must be the last segment.`
        );
      }
      regexParts.push("(.+)");
      continue;
    }
    if (seg.startsWith("[") && seg.endsWith("]")) {
      regexParts.push("([^/]+)");
      continue;
    }
    const escaped = seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    regexParts.push(escaped);
  }
  const regexSource = "^/" + regexParts.join("/") + "/?$";
  return new RegExp(regexSource);
}
function matchRouteClient(pathWithSearch, routes) {
  const [pathname] = pathWithSearch.split("?");
  for (const r of routes) {
    const regex = buildClientRegexFromPattern(r.pattern);
    const match = regex.exec(pathname);
    if (!match) continue;
    const params = {};
    r.paramNames.forEach((name, idx) => {
      params[name] = decodeURIComponent(match[idx + 1] || "");
    });
    return { route: r, params };
  }
  return null;
}

// modules/runtime/client/metadata.ts
function getOrCreateMeta(selector, attributes) {
  let meta = document.querySelector(selector);
  if (!meta) {
    meta = document.createElement("meta");
    if (attributes.name) meta.name = attributes.name;
    if (attributes.property) meta.setAttribute("property", attributes.property);
    if (attributes.httpEquiv) meta.httpEquiv = attributes.httpEquiv;
    document.head.appendChild(meta);
  }
  return meta;
}
function getOrCreateLink(rel, href) {
  const selector = `link[rel="${rel}"]`;
  let link = document.querySelector(selector);
  if (!link) {
    link = document.createElement("link");
    link.rel = rel;
    link.href = href;
    document.head.appendChild(link);
  } else {
    link.href = href;
  }
  return link;
}
function applyMetadata(md) {
  if (!md) return;
  if (md.title) {
    document.title = md.title;
  }
  if (md.description) {
    const meta = getOrCreateMeta('meta[name="description"]', { name: "description" });
    meta.content = md.description;
  }
  if (md.robots) {
    const meta = getOrCreateMeta('meta[name="robots"]', { name: "robots" });
    meta.content = md.robots;
  }
  if (md.themeColor) {
    const meta = getOrCreateMeta('meta[name="theme-color"]', { name: "theme-color" });
    meta.content = md.themeColor;
  }
  if (md.viewport) {
    const meta = getOrCreateMeta('meta[name="viewport"]', { name: "viewport" });
    meta.content = md.viewport;
  }
  if (md.canonical) {
    getOrCreateLink("canonical", md.canonical);
  }
  if (md.openGraph) {
    const og = md.openGraph;
    if (og.title) {
      const meta = getOrCreateMeta('meta[property="og:title"]', { property: "og:title" });
      meta.content = og.title;
    }
    if (og.description) {
      const meta = getOrCreateMeta('meta[property="og:description"]', { property: "og:description" });
      meta.content = og.description;
    }
    if (og.type) {
      const meta = getOrCreateMeta('meta[property="og:type"]', { property: "og:type" });
      meta.content = og.type;
    }
    if (og.url) {
      const meta = getOrCreateMeta('meta[property="og:url"]', { property: "og:url" });
      meta.content = og.url;
    }
    if (og.image) {
      if (typeof og.image === "string") {
        const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
        meta.content = og.image;
      } else {
        const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
        meta.content = og.image.url;
        if (og.image.width) {
          const metaWidth = getOrCreateMeta('meta[property="og:image:width"]', { property: "og:image:width" });
          metaWidth.content = String(og.image.width);
        }
        if (og.image.height) {
          const metaHeight = getOrCreateMeta('meta[property="og:image:height"]', { property: "og:image:height" });
          metaHeight.content = String(og.image.height);
        }
        if (og.image.alt) {
          const metaAlt = getOrCreateMeta('meta[property="og:image:alt"]', { property: "og:image:alt" });
          metaAlt.content = og.image.alt;
        }
      }
    }
    if (og.siteName) {
      const meta = getOrCreateMeta('meta[property="og:site_name"]', { property: "og:site_name" });
      meta.content = og.siteName;
    }
    if (og.locale) {
      const meta = getOrCreateMeta('meta[property="og:locale"]', { property: "og:locale" });
      meta.content = og.locale;
    }
  }
  if (md.twitter) {
    const twitter = md.twitter;
    if (twitter.card) {
      const meta = getOrCreateMeta('meta[name="twitter:card"]', { name: "twitter:card" });
      meta.content = twitter.card;
    }
    if (twitter.title) {
      const meta = getOrCreateMeta('meta[name="twitter:title"]', { name: "twitter:title" });
      meta.content = twitter.title;
    }
    if (twitter.description) {
      const meta = getOrCreateMeta('meta[name="twitter:description"]', { name: "twitter:description" });
      meta.content = twitter.description;
    }
    if (twitter.image) {
      const meta = getOrCreateMeta('meta[name="twitter:image"]', { name: "twitter:image" });
      meta.content = twitter.image;
    }
    if (twitter.imageAlt) {
      const meta = getOrCreateMeta('meta[name="twitter:image:alt"]', { name: "twitter:image:alt" });
      meta.content = twitter.imageAlt;
    }
    if (twitter.site) {
      const meta = getOrCreateMeta('meta[name="twitter:site"]', { name: "twitter:site" });
      meta.content = twitter.site;
    }
    if (twitter.creator) {
      const meta = getOrCreateMeta('meta[name="twitter:creator"]', { name: "twitter:creator" });
      meta.content = twitter.creator;
    }
  }
  if (md.metaTags && Array.isArray(md.metaTags)) {
    md.metaTags.forEach((tag) => {
      let selector = "";
      if (tag.name) {
        selector = `meta[name="${tag.name}"]`;
      } else if (tag.property) {
        selector = `meta[property="${tag.property}"]`;
      } else if (tag.httpEquiv) {
        selector = `meta[http-equiv="${tag.httpEquiv}"]`;
      }
      if (selector) {
        const meta = getOrCreateMeta(selector, {
          name: tag.name,
          property: tag.property,
          httpEquiv: tag.httpEquiv
        });
        meta.content = tag.content;
      }
    });
  }
  if (md.links && Array.isArray(md.links)) {
    md.links.forEach((link) => {
      getOrCreateLink(link.rel, link.href);
    });
  }
}

// modules/runtime/client/AppShell.tsx
var import_react2 = require("react");

// modules/runtime/client/RouterView.tsx
var import_jsx_runtime = require("react/jsx-runtime");
function RouterView({ state }) {
  if (!state.route) {
    if (state.components === null) {
      return null;
    }
    return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: "404 - Route not found" });
  }
  if (!state.components) {
    return null;
  }
  const { Page, layouts } = state.components;
  const { params, props } = state;
  let element = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Page, { params, ...props });
  const layoutChain = layouts.slice().reverse();
  for (const Layout of layoutChain) {
    element = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Layout, { params, ...props, children: element });
  }
  return element;
}

// modules/react/cache/client-data-cache/index.ts
var CACHE_KEY = "__FW_DATA_CACHE__";
var MAX_CACHE_SIZE = 100;
function getCacheStore() {
  if (typeof window !== "undefined") {
    if (!window[CACHE_KEY]) {
      window[CACHE_KEY] = {
        data: /* @__PURE__ */ new Map(),
        index: /* @__PURE__ */ new Map(),
        lru: []
      };
    }
    return window[CACHE_KEY];
  }
  return {
    data: /* @__PURE__ */ new Map(),
    index: /* @__PURE__ */ new Map(),
    lru: []
  };
}
var cacheStore = getCacheStore();
var dataCache = cacheStore.data;
var pathIndex = cacheStore.index;
var lru = cacheStore.lru;
function extractPathBase(key) {
  return key.split("?")[0];
}
function addToIndex(key) {
  const pathBase = extractPathBase(key);
  if (!pathIndex.has(pathBase)) {
    pathIndex.set(pathBase, /* @__PURE__ */ new Set());
  }
  pathIndex.get(pathBase).add(key);
}
function removeFromIndex(key) {
  const pathBase = extractPathBase(key);
  const keys = pathIndex.get(pathBase);
  if (keys) {
    keys.delete(key);
    if (keys.size === 0) {
      pathIndex.delete(pathBase);
    }
  }
}
function updateLRU(key) {
  const index = lru.indexOf(key);
  if (index !== -1) {
    lru.splice(index, 1);
  }
  lru.push(key);
}
function evictOldest() {
  while (lru.length >= MAX_CACHE_SIZE && lru.length > 0) {
    const oldestKey = lru.shift();
    dataCache.delete(oldestKey);
    removeFromIndex(oldestKey);
  }
}
function setCacheEntry(key, entry) {
  const existingEntry = dataCache.get(key);
  const wasFulfilled = existingEntry?.status === "fulfilled";
  dataCache.set(key, entry);
  if (entry.status === "fulfilled") {
    if (!wasFulfilled) {
      addToIndex(key);
    }
    updateLRU(key);
    evictOldest();
  } else if (wasFulfilled) {
    removeFromIndex(key);
  }
}
function deleteCacheEntry(key) {
  if (dataCache.has(key)) {
    dataCache.delete(key);
    removeFromIndex(key);
    const lruIndex = lru.indexOf(key);
    if (lruIndex !== -1) {
      lru.splice(lruIndex, 1);
    }
  }
}
function buildDataUrl(url) {
  return url + (url.includes("?") ? "&" : "?") + "__fw_data=1";
}
async function fetchRouteDataOnce(url, skipLayoutHooks = true) {
  const dataUrl = buildDataUrl(url);
  const headers = {
    "x-fw-data": "1",
    Accept: "application/json"
  };
  if (skipLayoutHooks) {
    headers["x-skip-layout-hooks"] = "true";
  }
  const res = await fetch(dataUrl, { headers });
  let json = {};
  try {
    const text = await res.text();
    if (text) {
      json = JSON.parse(text);
    }
  } catch (parseError) {
    console.error(
      "[client][cache] Failed to parse response as JSON:",
      parseError
    );
  }
  const result = {
    ok: res.ok,
    status: res.status,
    json
  };
  return result;
}
async function getRouteData(url, options) {
  const key = buildDataUrl(url);
  if (options?.revalidate) {
    deleteCacheEntry(key);
  }
  const entry = dataCache.get(key);
  if (entry && !options?.revalidate) {
    if (entry.status === "fulfilled") {
      updateLRU(key);
      return entry.value;
    }
    if (entry.status === "pending") {
      return entry.promise;
    }
  }
  const skipLayoutHooks = !options?.revalidate;
  const currentEntry = dataCache.get(key);
  if (currentEntry && !options?.revalidate) {
    if (currentEntry.status === "fulfilled") {
      updateLRU(key);
      return currentEntry.value;
    }
    if (currentEntry.status === "pending") {
      return currentEntry.promise;
    }
  }
  const promise = fetchRouteDataOnce(url, skipLayoutHooks).then((value) => {
    const entryAfterFetch = dataCache.get(key);
    if (!entryAfterFetch || entryAfterFetch.status === "pending") {
      setCacheEntry(key, { status: "fulfilled", value });
    }
    return value;
  }).catch((error) => {
    console.error("[client][cache] Error fetching route data:", error);
    const entryAfterFetch = dataCache.get(key);
    if (!entryAfterFetch || entryAfterFetch.status === "pending") {
      dataCache.set(key, { status: "rejected", error });
    }
    throw error;
  });
  dataCache.set(key, { status: "pending", promise });
  return promise;
}

// modules/runtime/client/navigation.ts
async function handleErrorRoute(nextUrl, json, errorRoute, setState) {
  try {
    const components = await errorRoute.load();
    let theme = "light";
    if (typeof document !== "undefined") {
      const cookieMatch = document.cookie.match(/theme=([^;]+)/);
      if (cookieMatch) {
        theme = cookieMatch[1];
      } else if (json.theme) {
        theme = json.theme;
      } else {
        const currentTheme = getCurrentTheme();
        if (currentTheme) theme = currentTheme;
      }
    } else if (json.theme) {
      theme = json.theme;
    }
    let layoutProps = {};
    if (json.layoutProps !== void 0 && json.layoutProps !== null) {
      layoutProps = json.layoutProps;
      setPreservedLayoutProps(layoutProps);
    } else {
      const preserved = getPreservedLayoutProps();
      if (preserved) {
        layoutProps = preserved;
      }
    }
    const pageProps = json.pageProps ?? json.props ?? {
      error: json.message || "An error occurred"
    };
    const errorProps = {
      ...layoutProps,
      ...pageProps,
      theme
    };
    const windowData = {
      pathname: nextUrl,
      params: json.params || {},
      props: errorProps,
      metadata: json.metadata ?? null,
      theme,
      notFound: false,
      error: true
    };
    setWindowData(windowData);
    const url = new URL(nextUrl, typeof window !== "undefined" ? window.location.origin : "http://localhost");
    const routerData = {
      pathname: url.pathname,
      params: json.params || {},
      searchParams: Object.fromEntries(url.searchParams.entries())
    };
    setRouterData(routerData);
    setState({
      url: nextUrl,
      route: errorRoute,
      params: json.params || {},
      components,
      props: errorProps
    });
    return true;
  } catch (loadError) {
    console.error("\n\u274C [client] Error loading error route components:");
    console.error(loadError);
    if (loadError instanceof Error) {
      console.error(`   Message: ${loadError.message}`);
      if (loadError.stack) {
        console.error(`   Stack: ${loadError.stack.split("\n").slice(0, 3).join("\n   ")}`);
      }
    }
    console.error("\u{1F4A1} Falling back to full page reload\n");
    window.location.href = nextUrl;
    return false;
  }
}
async function handleNotFoundRoute(nextUrl, json, notFoundRoute, setState) {
  let theme = "light";
  if (typeof document !== "undefined") {
    const cookieMatch = document.cookie.match(/theme=([^;]+)/);
    if (cookieMatch) {
      theme = cookieMatch[1];
    } else if (json.theme) {
      theme = json.theme;
    } else {
      const currentTheme = getCurrentTheme();
      if (currentTheme) theme = currentTheme;
    }
  } else if (json.theme) {
    theme = json.theme;
  }
  let layoutProps = {};
  if (json.layoutProps !== void 0 && json.layoutProps !== null) {
    layoutProps = json.layoutProps;
    setPreservedLayoutProps(layoutProps);
  } else {
    const preserved = getPreservedLayoutProps();
    if (preserved) {
      layoutProps = preserved;
    }
  }
  const pageProps = json.pageProps ?? json.props ?? {};
  const notFoundProps = {
    ...layoutProps,
    ...pageProps,
    theme
  };
  const windowData = {
    pathname: nextUrl,
    params: {},
    props: notFoundProps,
    metadata: json.metadata ?? null,
    theme,
    notFound: true,
    error: false
  };
  setWindowData(windowData);
  const url = new URL(nextUrl, typeof window !== "undefined" ? window.location.origin : "http://localhost");
  const routerData = {
    pathname: url.pathname,
    params: {},
    searchParams: Object.fromEntries(url.searchParams.entries())
  };
  setRouterData(routerData);
  if (notFoundRoute) {
    const components = await notFoundRoute.load();
    setState({
      url: nextUrl,
      route: notFoundRoute,
      params: {},
      components,
      props: notFoundProps
    });
  } else {
    setState({
      url: nextUrl,
      route: null,
      params: {},
      components: null,
      props: {}
    });
  }
}
async function handleNormalRoute(nextUrl, json, routes, setState) {
  applyMetadata(json.metadata ?? null);
  let theme = "light";
  if (typeof document !== "undefined") {
    const cookieMatch = document.cookie.match(/theme=([^;]+)/);
    if (cookieMatch) {
      theme = cookieMatch[1];
    } else if (json.theme) {
      theme = json.theme;
    } else {
      const currentTheme = getCurrentTheme();
      if (currentTheme) {
        theme = currentTheme;
      }
    }
  } else if (json.theme) {
    theme = json.theme;
  }
  let layoutProps = {};
  if (json.layoutProps !== void 0 && json.layoutProps !== null) {
    layoutProps = json.layoutProps;
    setPreservedLayoutProps(layoutProps);
  } else {
    const preserved = getPreservedLayoutProps();
    if (preserved) {
      layoutProps = preserved;
    }
  }
  const pageProps = json.pageProps ?? json.props ?? {};
  const combinedProps = {
    ...layoutProps,
    ...pageProps,
    theme
    // Always include theme
  };
  const matched = matchRouteClient(nextUrl, routes);
  if (!matched) {
    window.location.href = nextUrl;
    return false;
  }
  const windowData = {
    pathname: nextUrl,
    params: matched.params,
    props: combinedProps,
    metadata: json.metadata ?? null,
    theme,
    notFound: false,
    error: false
  };
  setWindowData(windowData);
  const url = new URL(nextUrl, typeof window !== "undefined" ? window.location.origin : "http://localhost");
  const routerData = {
    pathname: url.pathname,
    params: matched.params,
    searchParams: Object.fromEntries(url.searchParams.entries())
  };
  setRouterData(routerData);
  const prefetched = prefetchedRoutes.get(matched.route);
  const components = prefetched ? await prefetched : await matched.route.load();
  if (!prefetched) {
    prefetchedRoutes.set(matched.route, Promise.resolve(components));
  }
  window.scrollTo({
    top: 0,
    behavior: "smooth"
  });
  setState({
    url: nextUrl,
    route: matched.route,
    params: matched.params,
    components,
    props: combinedProps
  });
  return true;
}
async function navigate(nextUrl, handlers, options) {
  const { setState, routes, notFoundRoute, errorRoute } = handlers;
  try {
    const { ok, json } = await getRouteData(nextUrl, {
      revalidate: options?.revalidate
    });
    if (json && json.error) {
      if (errorRoute) {
        const handled = await handleErrorRoute(
          nextUrl,
          json,
          errorRoute,
          setState
        );
        if (handled) return;
      } else {
        console.warn(
          "[client] Error route not available, reloading page.",
          errorRoute
        );
        window.location.href = nextUrl;
        return;
      }
    }
    if (!ok) {
      if (json?.redirect) {
        window.location.href = json.redirect.destination;
        return;
      }
      window.location.href = nextUrl;
      return;
    }
    if (json.redirect) {
      window.location.href = json.redirect.destination;
      return;
    }
    if (json.notFound) {
      await handleNotFoundRoute(nextUrl, json, notFoundRoute, setState);
      return;
    }
    await handleNormalRoute(nextUrl, json, routes, setState);
  } catch (err) {
    console.error("[client] Error fetching FW data:", err);
    window.location.href = nextUrl;
  }
}
var prefetchedRoutes = /* @__PURE__ */ new WeakMap();
function prefetchRoute(url, routes, notFoundRoute) {
  const [pathname] = url.split("?");
  const matched = matchRouteClient(pathname, routes);
  if (!matched) {
    if (notFoundRoute) {
      const existing2 = prefetchedRoutes.get(notFoundRoute);
      if (!existing2) {
        const promise = notFoundRoute.load();
        prefetchedRoutes.set(notFoundRoute, promise);
      }
    }
    return;
  }
  const existing = prefetchedRoutes.get(matched.route);
  if (!existing) {
    const promise = matched.route.load();
    prefetchedRoutes.set(matched.route, promise);
  }
}
function createHoverHandler(routes, notFoundRoute) {
  return function handleHover(ev) {
    try {
      const target = ev.target;
      if (!target) return;
      const anchor = target.closest("a[href]");
      if (!anchor) return;
      const href = anchor.getAttribute("href");
      if (!href) return;
      if (href.startsWith("#")) return;
      const url = new URL(href, window.location.href);
      if (url.origin !== window.location.origin) return;
      if (anchor.target && anchor.target !== "_self") return;
      const nextUrl = url.pathname + url.search;
      const currentUrl = window.location.pathname + window.location.search;
      if (nextUrl === currentUrl) return;
      prefetchRoute(nextUrl, routes, notFoundRoute);
    } catch (error) {
    }
  };
}
function createClickHandler(navigate2) {
  return function handleClick(ev) {
    try {
      if (ev.defaultPrevented) return;
      if (ev.type !== "click") return;
      if (ev.button !== 0) return;
      if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;
      const target = ev.target;
      if (ev.clientX === 0 && ev.clientY === 0 && ev.detail === 0) {
        if (target) {
          const tagName2 = target.tagName.toLowerCase();
          if (tagName2 === "input" || tagName2 === "textarea" || tagName2 === "button" || tagName2 === "select") {
            return;
          }
        }
      }
      if (!target) return;
      const tagName = target.tagName.toLowerCase();
      if (tagName === "input" || tagName === "textarea" || tagName === "button" || tagName === "select" || target.isContentEditable || target.getAttribute("contenteditable") === "true") {
        return;
      }
      const interactiveParent = target.closest("input, textarea, button, select, [contenteditable], label");
      if (interactiveParent) {
        if (interactiveParent.tagName.toLowerCase() === "label") {
          const label = interactiveParent;
          if (label.control) {
            return;
          }
        } else {
          return;
        }
      }
      const anchor = target.closest("a[href]");
      if (!anchor) return;
      const href = anchor.getAttribute("href");
      if (!href) return;
      if (href.startsWith("#")) return;
      const url = new URL(href, window.location.href);
      if (url.origin !== window.location.origin) return;
      if (anchor.target && anchor.target !== "_self") return;
      ev.preventDefault();
      const nextUrl = url.pathname + url.search;
      const currentUrl = window.location.pathname + window.location.search;
      if (nextUrl === currentUrl) return;
      const shouldRevalidate = anchor.hasAttribute("data-revalidate") && anchor.getAttribute("data-revalidate") !== "false";
      window.history.pushState({}, "", nextUrl);
      navigate2(nextUrl, shouldRevalidate ? { revalidate: true } : void 0);
    } catch (error) {
      console.error("[navigation] Error in click handler:", error);
    }
  };
}
function createPopStateHandler(navigate2) {
  return function handlePopState() {
    const nextUrl = window.location.pathname + window.location.search;
    navigate2(nextUrl);
  };
}

// modules/runtime/client/RouterContext.tsx
var import_react = require("react");
var RouterContext = (0, import_react.createContext)(null);

// modules/runtime/client/AppShell.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
function AppShell({
  initialState,
  routes,
  notFoundRoute,
  errorRoute
}) {
  const [state, setState] = (0, import_react2.useState)(initialState);
  const handlersRef = (0, import_react2.useRef)({
    setState,
    routes,
    notFoundRoute,
    errorRoute
  });
  (0, import_react2.useEffect)(() => {
    handlersRef.current = {
      setState,
      routes,
      notFoundRoute,
      errorRoute
    };
  }, [routes, notFoundRoute, errorRoute]);
  const handleNavigate = (0, import_react2.useCallback)(
    async (nextUrl, options) => {
      await navigate(nextUrl, handlersRef.current, {
        revalidate: options?.revalidate
      });
    },
    []
  );
  (0, import_react2.useEffect)(() => {
    if (typeof window !== "undefined") {
      window[ROUTER_NAVIGATE_KEY] = handleNavigate;
      return () => {
        delete window[ROUTER_NAVIGATE_KEY];
      };
    }
  }, [handleNavigate]);
  (0, import_react2.useEffect)(() => {
    let isMounted = true;
    async function handleNavigateInternal(nextUrl, options) {
      if (!isMounted) return;
      await navigate(nextUrl, handlersRef.current, options);
    }
    const handleClick = createClickHandler(handleNavigateInternal);
    const handlePopState = createPopStateHandler(handleNavigateInternal);
    const handleHover = createHoverHandler(routes, notFoundRoute);
    window.addEventListener("click", handleClick, false);
    window.addEventListener("popstate", handlePopState, false);
    window.addEventListener("mouseover", handleHover, false);
    return () => {
      isMounted = false;
      window.removeEventListener("click", handleClick, false);
      window.removeEventListener("popstate", handlePopState, false);
      window.removeEventListener("mouseover", handleHover, false);
    };
  }, [routes, notFoundRoute]);
  (0, import_react2.useEffect)(() => {
    const handleDataRefresh = () => {
      const freshData = window[WINDOW_DATA_KEY];
      if (!freshData) return;
      const currentPathname = window.location.pathname;
      const freshPathname = freshData.pathname;
      if (freshPathname === currentPathname) {
        if (freshData.metadata !== void 0) {
          applyMetadata(freshData.metadata);
        }
        setState((prevState) => ({
          ...prevState,
          props: freshData.props ?? prevState.props,
          params: freshData.params ?? prevState.params
        }));
      }
    };
    window.addEventListener("fw-data-refresh", handleDataRefresh);
    return () => {
      window.removeEventListener("fw-data-refresh", handleDataRefresh);
    };
  }, []);
  const isError = state.route === errorRoute;
  const isNotFound = state.route === notFoundRoute;
  const routeType = isError ? "error" : isNotFound ? "notfound" : "normal";
  const routeKey = `${state.url}:${routeType}`;
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RouterContext.Provider, { value: { navigate: handleNavigate }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RouterView, { state }, routeKey) });
}

// modules/runtime/client/hot-reload.ts
function setupHotReload() {
  const nodeEnv = process.env.NODE_ENV || "production";
  const isDev = nodeEnv === "development";
  if (!isDev) {
    return;
  }
  console.log("[hot-reload] Setting up hot reload client...");
  let eventSource = null;
  let reloadTimeout = null;
  let reconnectTimeout = null;
  let reconnectAttempts = 0;
  const MAX_RECONNECT_ATTEMPTS = 10;
  const RECONNECT_DELAY = 1e3;
  const RELOAD_DELAY = 100;
  function connect() {
    try {
      if (eventSource) {
        console.log("[hot-reload] Closing existing EventSource connection");
        eventSource.close();
      }
      const endpoint = "/__fw/hot";
      eventSource = new EventSource(endpoint);
      eventSource.addEventListener("ping", (event) => {
        if ("data" in event) {
          console.log("[hot-reload] \u2705 Connected to hot reload server");
        }
        reconnectAttempts = 0;
      });
      eventSource.addEventListener("message", (event) => {
        const data = event.data;
        if (data && typeof data === "string" && data.startsWith("reload:")) {
          const filePath = data.slice(7);
          console.log(`[hot-reload] \u{1F4DD} File changed: ${filePath}, reloading...`);
          if (reloadTimeout) {
            clearTimeout(reloadTimeout);
          }
          reloadTimeout = setTimeout(() => {
            try {
              window.location.reload();
            } catch (error) {
              console.error("[hot-reload] \u274C Error reloading page:", error);
              setTimeout(() => window.location.reload(), 100);
            }
          }, RELOAD_DELAY);
        }
      });
      eventSource.onopen = () => {
        reconnectAttempts = 0;
      };
      eventSource.onerror = (error) => {
        const states = ["CONNECTING", "OPEN", "CLOSED"];
        const state = states[eventSource?.readyState ?? 0] || "UNKNOWN";
        if (eventSource?.readyState === EventSource.CONNECTING) {
          console.log("[hot-reload] \u23F3 Still connecting...");
          return;
        } else if (eventSource?.readyState === EventSource.OPEN) {
          console.warn("[hot-reload] \u26A0\uFE0F Connection error (but connection is open):", error);
        } else {
          console.warn(`[hot-reload] \u274C Connection closed (readyState: ${state})`);
          if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
            reconnectAttempts++;
            const delay = RECONNECT_DELAY * reconnectAttempts;
            if (reconnectTimeout) {
              clearTimeout(reconnectTimeout);
            }
            reconnectTimeout = setTimeout(() => {
              console.log(`[hot-reload] \u{1F504} Reconnecting... (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
              connect();
            }, delay);
          } else {
            console.error("[hot-reload] \u274C Max reconnect attempts reached. Please refresh the page manually.");
          }
        }
      };
    } catch (error) {
      console.error("[hot-reload] \u274C Failed to create EventSource:", error);
      console.error("[hot-reload] EventSource may not be supported in this browser.");
    }
  }
  connect();
}

// modules/runtime/client/bootstrap.tsx
var import_jsx_runtime3 = require("react/jsx-runtime");
async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute, errorRoute) {
  const isInitialNotFound = initialData?.notFound === true;
  const isInitialError = initialData?.error === true;
  let initialRoute = null;
  let initialParams = {};
  let initialComponents = null;
  if (isInitialError && errorRoute) {
    initialRoute = errorRoute;
    initialParams = initialData?.params ?? {};
    initialComponents = await errorRoute.load();
  } else if (isInitialNotFound && notFoundRoute) {
    initialRoute = notFoundRoute;
    initialParams = {};
    initialComponents = await notFoundRoute.load();
  } else {
    const match = matchRouteClient(initialUrl, routes);
    if (match) {
      initialRoute = match.route;
      initialParams = match.params;
      initialComponents = await match.route.load();
    } else if (notFoundRoute) {
      initialRoute = notFoundRoute;
      initialParams = {};
      initialComponents = await notFoundRoute.load();
    } else {
      console.warn(
        `[client] No route match found for ${initialUrl}. Available routes:`,
        routes.map((r) => r.pattern)
      );
    }
  }
  return {
    url: initialUrl,
    route: initialRoute,
    params: initialParams,
    components: initialComponents,
    props: initialData?.props ?? {}
  };
}
function initializeRouterData(initialUrl, initialData) {
  let routerData = getRouterData();
  if (!routerData) {
    const url = new URL(initialUrl, window.location.origin);
    routerData = {
      pathname: url.pathname,
      params: initialData?.params || {},
      searchParams: Object.fromEntries(url.searchParams.entries())
    };
    setRouterData(routerData);
  }
}
async function hydrateInitialRoute(container, initialUrl, initialData, routes, notFoundRoute, errorRoute) {
  try {
    const initialState = await loadInitialRoute(
      initialUrl,
      initialData,
      routes,
      notFoundRoute,
      errorRoute
    );
    if (initialData?.metadata) {
      try {
        applyMetadata(initialData.metadata);
      } catch (metadataError) {
        console.warn("[client] Error applying metadata:", metadataError);
      }
    }
    (0, import_client.hydrateRoot)(
      container,
      /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
        AppShell,
        {
          initialState,
          routes,
          notFoundRoute,
          errorRoute
        }
      )
    );
  } catch (error) {
    console.error(
      "[client] Error loading initial route components for",
      initialUrl,
      error
    );
    throw error;
  }
}
function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
  setupHotReload();
  (async () => {
    try {
      const container = document.getElementById(APP_CONTAINER_ID);
      if (!container) {
        console.error(`
\u274C [client] Hydration failed: Container #${APP_CONTAINER_ID} not found`);
        console.error("\u{1F4A1} This usually means:");
        console.error("  \u2022 The HTML structure doesn't match what React expects");
        console.error("  \u2022 The container was removed before hydration");
        console.error("  \u2022 There's a mismatch between SSR and client HTML\n");
        return;
      }
      const initialData = getWindowData();
      const initialUrl = window.location.pathname + window.location.search;
      if (initialData?.props) {
        setPreservedLayoutProps(initialData.props);
      }
      initializeRouterData(initialUrl, initialData);
      await hydrateInitialRoute(
        container,
        initialUrl,
        initialData,
        routes,
        notFoundRoute,
        errorRoute
      );
    } catch (error) {
      console.error("\n\u274C [client] Fatal error during bootstrap:");
      console.error(error);
      if (error instanceof Error) {
        console.error("\nError details:");
        console.error(`  Message: ${error.message}`);
        if (error.stack) {
          console.error(`  Stack: ${error.stack}`);
        }
      }
      console.error("\n\u{1F4A1} Attempting page reload to recover...\n");
      window.location.reload();
    }
  })();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  bootstrapClient
});
//# sourceMappingURL=runtime.cjs.map