@lolyjs/core 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1353,6 +1353,9 @@ function createClientConfig(projectRoot, mode) {
1353
1353
  filename: mode === "production" ? "client.[contenthash].css" : "client.css"
1354
1354
  })
1355
1355
  ],
1356
+ externals: {
1357
+ "@lolyjs/core/runtime": "@lolyjs/core/runtime"
1358
+ },
1356
1359
  infrastructureLogging: {
1357
1360
  level: "error"
1358
1361
  },
@@ -5094,7 +5097,7 @@ function applyMetadata(md) {
5094
5097
  }
5095
5098
 
5096
5099
  // modules/runtime/client/AppShell.tsx
5097
- import { useEffect, useState } from "react";
5100
+ import { useEffect, useState, useRef } from "react";
5098
5101
 
5099
5102
  // modules/runtime/client/RouterView.tsx
5100
5103
  import { jsx } from "react/jsx-runtime";
@@ -5457,29 +5460,55 @@ async function navigate(nextUrl, handlers, options) {
5457
5460
  }
5458
5461
  function createClickHandler(navigate2) {
5459
5462
  return function handleClick(ev) {
5460
- if (ev.defaultPrevented) return;
5461
- if (ev.button !== 0) return;
5462
- if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;
5463
- const target = ev.target;
5464
- if (!target) return;
5465
- const tagName = target.tagName.toLowerCase();
5466
- const isInteractiveElement = tagName === "input" || tagName === "textarea" || tagName === "button" || tagName === "select" || target.isContentEditable || target.closest("input, textarea, button, select, [contenteditable]");
5467
- if (isInteractiveElement) return;
5468
- const anchor = target.closest("a[href]");
5469
- if (!anchor) return;
5470
- const href = anchor.getAttribute("href");
5471
- if (!href) return;
5472
- if (href.startsWith("#")) return;
5473
- const url = new URL(href, window.location.href);
5474
- if (url.origin !== window.location.origin) return;
5475
- if (anchor.target && anchor.target !== "_self") return;
5476
- ev.preventDefault();
5477
- const nextUrl = url.pathname + url.search;
5478
- const currentUrl = window.location.pathname + window.location.search;
5479
- if (nextUrl === currentUrl) return;
5480
- const shouldRevalidate = anchor.hasAttribute("data-revalidate") && anchor.getAttribute("data-revalidate") !== "false";
5481
- window.history.pushState({}, "", nextUrl);
5482
- navigate2(nextUrl, shouldRevalidate ? { revalidate: true } : void 0);
5463
+ try {
5464
+ if (ev.defaultPrevented) return;
5465
+ if (ev.type !== "click") return;
5466
+ if (ev.button !== 0) return;
5467
+ if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;
5468
+ if (ev.clientX === 0 && ev.clientY === 0 && ev.detail === 0) {
5469
+ const target2 = ev.target;
5470
+ if (target2) {
5471
+ const tagName2 = target2.tagName.toLowerCase();
5472
+ if (tagName2 === "input" || tagName2 === "textarea" || tagName2 === "button" || tagName2 === "select") {
5473
+ return;
5474
+ }
5475
+ }
5476
+ }
5477
+ const target = ev.target;
5478
+ if (!target) return;
5479
+ const tagName = target.tagName.toLowerCase();
5480
+ if (tagName === "input" || tagName === "textarea" || tagName === "button" || tagName === "select" || target.isContentEditable || target.getAttribute("contenteditable") === "true") {
5481
+ return;
5482
+ }
5483
+ const interactiveParent = target.closest("input, textarea, button, select, [contenteditable], label");
5484
+ if (interactiveParent) {
5485
+ if (interactiveParent.tagName.toLowerCase() === "label") {
5486
+ const label = interactiveParent;
5487
+ if (label.control) {
5488
+ return;
5489
+ }
5490
+ } else {
5491
+ return;
5492
+ }
5493
+ }
5494
+ const anchor = target.closest("a[href]");
5495
+ if (!anchor) return;
5496
+ const href = anchor.getAttribute("href");
5497
+ if (!href) return;
5498
+ if (href.startsWith("#")) return;
5499
+ const url = new URL(href, window.location.href);
5500
+ if (url.origin !== window.location.origin) return;
5501
+ if (anchor.target && anchor.target !== "_self") return;
5502
+ ev.preventDefault();
5503
+ const nextUrl = url.pathname + url.search;
5504
+ const currentUrl = window.location.pathname + window.location.search;
5505
+ if (nextUrl === currentUrl) return;
5506
+ const shouldRevalidate = anchor.hasAttribute("data-revalidate") && anchor.getAttribute("data-revalidate") !== "false";
5507
+ window.history.pushState({}, "", nextUrl);
5508
+ navigate2(nextUrl, shouldRevalidate ? { revalidate: true } : void 0);
5509
+ } catch (error) {
5510
+ console.error("[navigation] Error in click handler:", error);
5511
+ }
5483
5512
  };
5484
5513
  }
5485
5514
  function createPopStateHandler(navigate2) {
@@ -5498,25 +5527,36 @@ function AppShell({
5498
5527
  errorRoute
5499
5528
  }) {
5500
5529
  const [state, setState] = useState(initialState);
5530
+ const handlersRef = useRef({
5531
+ setState,
5532
+ routes,
5533
+ notFoundRoute,
5534
+ errorRoute
5535
+ });
5501
5536
  useEffect(() => {
5502
- const handlers = {
5537
+ handlersRef.current = {
5503
5538
  setState,
5504
5539
  routes,
5505
5540
  notFoundRoute,
5506
5541
  errorRoute
5507
5542
  };
5543
+ }, [routes, notFoundRoute, errorRoute]);
5544
+ useEffect(() => {
5545
+ let isMounted = true;
5508
5546
  async function handleNavigate(nextUrl, options) {
5509
- await navigate(nextUrl, handlers, options);
5547
+ if (!isMounted) return;
5548
+ await navigate(nextUrl, handlersRef.current, options);
5510
5549
  }
5511
5550
  const handleClick = createClickHandler(handleNavigate);
5512
5551
  const handlePopState = createPopStateHandler(handleNavigate);
5513
- window.addEventListener("click", handleClick);
5514
- window.addEventListener("popstate", handlePopState);
5552
+ window.addEventListener("click", handleClick, false);
5553
+ window.addEventListener("popstate", handlePopState, false);
5515
5554
  return () => {
5516
- window.removeEventListener("click", handleClick);
5517
- window.removeEventListener("popstate", handlePopState);
5555
+ isMounted = false;
5556
+ window.removeEventListener("click", handleClick, false);
5557
+ window.removeEventListener("popstate", handlePopState, false);
5518
5558
  };
5519
- }, [routes, notFoundRoute, errorRoute]);
5559
+ }, []);
5520
5560
  const isError = state.route === errorRoute;
5521
5561
  const isNotFound = state.route === notFoundRoute;
5522
5562
  const routeType = isError ? "error" : isNotFound ? "notfound" : "normal";