@jsenv/navi 0.18.28 → 0.18.30

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.
@@ -12512,16 +12512,25 @@ const RootElement = () => {
12512
12512
  };
12513
12513
  const SlotContext = createContext(null);
12514
12514
  const RouteInfoContext = createContext(null);
12515
+ const UpdateOnlyContext = createContext(false);
12516
+ const ElementSignalMapContext = createContext(null);
12515
12517
  const Routes = ({
12516
12518
  element = jsx(RootElement, {}),
12517
12519
  children
12518
12520
  }) => {
12519
12521
  const routeInfo = useMatchingRouteInfo();
12520
12522
  const route = routeInfo?.route;
12521
- return jsx(Route, {
12522
- route: route,
12523
- element: element,
12524
- children: children
12523
+ const elementSignalMapRef = useRef(null);
12524
+ if (!elementSignalMapRef.current) {
12525
+ elementSignalMapRef.current = new Map();
12526
+ }
12527
+ return jsx(ElementSignalMapContext.Provider, {
12528
+ value: elementSignalMapRef.current,
12529
+ children: jsx(Route, {
12530
+ route: route,
12531
+ element: element,
12532
+ children: children
12533
+ })
12525
12534
  });
12526
12535
  };
12527
12536
  const useMatchingRouteInfo = () => useContext(RouteInfoContext);
@@ -12538,7 +12547,29 @@ const Route = ({
12538
12547
  const forceRender = useForceRender();
12539
12548
  const hasDiscoveredRef = useRef(false);
12540
12549
  const matchingInfoRef = useRef(null);
12550
+ const isUpdateOnly = useContext(UpdateOnlyContext);
12551
+ const elementSignalMap = useContext(ElementSignalMapContext);
12552
+
12553
+ // Update the element signal for this route.
12554
+ // In update-only mode this is the only purpose of rendering this Route.
12555
+ if (route && elementSignalMap && elementSignalMap.has(route)) {
12556
+ elementSignalMap.get(route).value = element;
12557
+ }
12558
+ if (isUpdateOnly) {
12559
+ if (children) {
12560
+ return jsx(UpdateOnlyContext.Provider, {
12561
+ value: true,
12562
+ children: children
12563
+ });
12564
+ }
12565
+ return null;
12566
+ }
12541
12567
  if (!hasDiscoveredRef.current) {
12568
+ // Create the element signal during discovery
12569
+ if (route && elementSignalMap && !elementSignalMap.has(route)) {
12570
+ // eslint-disable-next-line signals/no-signal-in-component-body
12571
+ elementSignalMap.set(route, signal(element));
12572
+ }
12542
12573
  return jsx(RouteMatchManager, {
12543
12574
  element: element,
12544
12575
  action: action,
@@ -12562,7 +12593,14 @@ const Route = ({
12562
12593
  const {
12563
12594
  MatchingElement
12564
12595
  } = matchingInfo;
12565
- return jsx(MatchingElement, {});
12596
+ // After discovery: render MatchingElement for visible output, and keep
12597
+ // children alive in update-only mode so their element signals stay current.
12598
+ return jsxs(Fragment, {
12599
+ children: [jsx(MatchingElement, {}), children ? jsx(UpdateOnlyContext.Provider, {
12600
+ value: true,
12601
+ children: children
12602
+ }) : null]
12603
+ });
12566
12604
  };
12567
12605
  const RegisterChildRouteContext = createContext(null);
12568
12606
 
@@ -12585,6 +12623,7 @@ const RouteMatchManager = ({
12585
12623
  throw new Error("Route cannot have both route and fallback props");
12586
12624
  }
12587
12625
  const parentRegisterChildRoute = useContext(RegisterChildRouteContext);
12626
+ const elementSignalMap = useContext(ElementSignalMapContext);
12588
12627
  const elementId = getElementSignature(element);
12589
12628
  const candidateSet = new Set();
12590
12629
  let indexCandidate = null;
@@ -12615,6 +12654,7 @@ const RouteMatchManager = ({
12615
12654
  useLayoutEffect(() => {
12616
12655
  initRouteObserver({
12617
12656
  element,
12657
+ elementSignalMap,
12618
12658
  action,
12619
12659
  route,
12620
12660
  index,
@@ -12635,6 +12675,7 @@ const RouteMatchManager = ({
12635
12675
  };
12636
12676
  const initRouteObserver = ({
12637
12677
  element,
12678
+ elementSignalMap,
12638
12679
  action,
12639
12680
  route,
12640
12681
  index,
@@ -12725,18 +12766,23 @@ const initRouteObserver = ({
12725
12766
  const matchingRouteInfoSignal = signal();
12726
12767
  const SlotMatchingElementSignal = signal();
12727
12768
  const MatchingElement = () => {
12769
+ // Read element from the signal (updated by update-only renders) when
12770
+ // available, falling back to the closure variable for routes without
12771
+ // a route prop (e.g. the Routes wrapper).
12772
+ const elementSignal = route && elementSignalMap ? elementSignalMap.get(route) : undefined;
12773
+ const currentElement = elementSignal ? elementSignal.value : element;
12728
12774
  const matchingRouteInfo = matchingRouteInfoSignal.value;
12729
12775
  useUITransitionContentId(matchingRouteInfo ? matchingRouteInfo.route.urlPattern : fallback ? "fallback" : undefined);
12730
12776
  const SlotMatchingElement = SlotMatchingElementSignal.value;
12731
- element = action ? jsx(ActionRenderer, {
12777
+ const renderedElement = action ? jsx(ActionRenderer, {
12732
12778
  action: action,
12733
- children: element
12734
- }) : element;
12779
+ children: currentElement
12780
+ }) : currentElement;
12735
12781
  return jsx(RouteInfoContext.Provider, {
12736
12782
  value: matchingRouteInfo,
12737
12783
  children: jsx(SlotContext.Provider, {
12738
12784
  value: SlotMatchingElement,
12739
- children: element
12785
+ children: renderedElement
12740
12786
  })
12741
12787
  });
12742
12788
  };