@absolutejs/absolute 0.19.0-beta.836 → 0.19.0-beta.838

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.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-bA9nAi/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-xc0HoU/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-bA9nAi/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-xc0HoU/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
48
48
  getWarningController()?.maybeWarn(primitiveName);
49
49
  };
50
50
 
51
- // .angular-partial-tmp-bA9nAi/src/core/streamingSlotRegistry.ts
51
+ // .angular-partial-tmp-xc0HoU/src/core/streamingSlotRegistry.ts
52
52
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
53
53
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
54
54
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
@@ -11,6 +11,11 @@ let currentOverlayKind: 'compilation' | 'runtime' | null = null;
11
11
  // a "N of M" badge so you can step through them.
12
12
  const runtimeErrors: ErrorOverlayOptions[] = [];
13
13
  let activeRuntimeIndex = 0;
14
+ let pendingCompilationOpts: ErrorOverlayOptions | null = null;
15
+ // Tracks which queue renderOverlay should pull from. Driven by
16
+ // showErrorOverlay BEFORE renderOverlay runs so the choice is unambiguous
17
+ // (currentOverlayKind reflects what's currently mounted, not what's queued).
18
+ let activeMode: 'runtime' | 'compilation' | null = null;
14
19
 
15
20
  const frameworkLabels: Record<string, string> = {
16
21
  angular: 'Angular',
@@ -48,6 +53,8 @@ export const hideErrorOverlay = () => {
48
53
  // fresh overlay, otherwise stale entries accumulate forever.
49
54
  runtimeErrors.length = 0;
50
55
  activeRuntimeIndex = 0;
56
+ pendingCompilationOpts = null;
57
+ activeMode = null;
51
58
  if (!elm || !elm.parentNode) {
52
59
  removeOverlayElement();
53
60
 
@@ -258,7 +265,7 @@ const formatErrorForCopy = (opts: ErrorOverlayOptions) => {
258
265
 
259
266
  const renderOverlay = () => {
260
267
  const opts =
261
- currentOverlayKind === 'runtime'
268
+ activeMode === 'runtime'
262
269
  ? runtimeErrors[activeRuntimeIndex]
263
270
  : pendingCompilationOpts;
264
271
  if (!opts) return;
@@ -299,7 +306,7 @@ const renderOverlay = () => {
299
306
  // Multi-error nav: visible only when more than one runtime error has
300
307
  // fired since the last dismiss. Compilation errors always replace, so
301
308
  // they never need this row.
302
- if (currentOverlayKind === 'runtime' && runtimeErrors.length > 1) {
309
+ if (activeMode === 'runtime' && runtimeErrors.length > 1) {
303
310
  const navRow = document.createElement('div');
304
311
  navRow.style.cssText =
305
312
  'display:flex;align-items:center;gap:12px;margin-bottom:20px;padding:10px 14px;background:rgba(71,85,105,0.25);border-radius:10px;border:1px solid rgba(71,85,105,0.4);';
@@ -340,7 +347,7 @@ const renderOverlay = () => {
340
347
  if (locSection) content.appendChild(locSection);
341
348
  const stackSection = buildStackSection(stack, message);
342
349
  if (stackSection) content.appendChild(stackSection);
343
- if (currentOverlayKind === 'runtime') {
350
+ if (activeMode === 'runtime') {
344
351
  content.appendChild(buildDiagnosticsSection());
345
352
  }
346
353
 
@@ -412,10 +419,9 @@ const renderOverlay = () => {
412
419
  errorOverlayElement = overlay;
413
420
  };
414
421
 
415
- let pendingCompilationOpts: ErrorOverlayOptions | null = null;
416
-
417
422
  export const showErrorOverlay = (opts: ErrorOverlayOptions) => {
418
423
  const kind = opts.kind || 'compilation';
424
+ activeMode = kind;
419
425
  if (kind === 'runtime') {
420
426
  // Suppress duplicates — Angular and other frameworks often re-throw
421
427
  // the same error from multiple async boundaries (zone, scheduler,
@@ -25,26 +25,30 @@
25
25
  const registrationOrder = Number(id.slice(1));
26
26
 
27
27
  // Register synchronously at script-body time so SSR (which doesn't
28
- // run $effect) sees the registration. The Router itself owns
29
- // rendering of the winning route's content — Route emits no DOM and
30
- // no hydration markers, so a page with N <Route>s produces ONE
31
- // `{#if}` block in the rendered HTML, not N.
32
- const initialCompiled = compilePattern(
33
- joinBasepath(registry.basepath, path)
34
- );
28
+ // run $effect) sees the registration before the template runs.
35
29
  registry.register(id, {
36
- content: content as Snippet<[Record<string, string | undefined>]>,
37
- pattern: initialCompiled,
30
+ pattern: compilePattern(joinBasepath(registry.basepath, path)),
38
31
  registrationOrder
39
32
  });
40
33
 
41
34
  $effect(() => {
42
35
  registry.register(id, {
43
- content: content as Snippet<[Record<string, string | undefined>]>,
44
36
  pattern: compilePattern(joinBasepath(registry.basepath, path)),
45
37
  registrationOrder
46
38
  });
47
39
  });
48
40
 
49
41
  onDestroy(() => registry.deregister(id));
42
+
43
+ // The Router computes the active match across all registered Routes
44
+ // (specificity-ranked). Each Route checks if it's the winner and
45
+ // renders its own content at its own location in the markup. That
46
+ // way `<Route>` nested inside a layout `<section>` renders inside
47
+ // that section instead of getting hoisted to the Router's root.
48
+ const match = $derived(registry.getActiveMatch());
49
+ const isActive = $derived(match?.id === id);
50
50
  </script>
51
+
52
+ {#if isActive && match}
53
+ {@render content(match.params as ExtractRouteParams<Path>)}
54
+ {/if}
@@ -1,15 +1,14 @@
1
1
  <script lang="ts" module>
2
- import type { Snippet } from 'svelte';
3
-
4
2
  type RouteEntry = {
5
3
  // reactive — read by the winner-resolver
6
4
  pattern: ReturnType<typeof import('./matchPath').compilePattern>;
7
5
  // stable — assigned at registration time, used as tiebreaker
8
6
  registrationOrder: number;
9
- // the snippet the winning Route should render — extraction lives
10
- // on the Router so the active branch renders inside ONE if-block
11
- // instead of one per Route (one set of hydration markers, not N)
12
- content: Snippet<[Record<string, string | undefined>]>;
7
+ };
8
+
9
+ type ActiveMatch = {
10
+ id: string;
11
+ params: Record<string, string | undefined>;
13
12
  };
14
13
 
15
14
  export type RouterRegistry = {
@@ -18,11 +17,16 @@
18
17
  register: (id: string, entry: RouteEntry) => void;
19
18
  deregister: (id: string) => void;
20
19
  nextRouteId: () => string;
20
+ // Returns the currently-winning Route's id and matched params, or null
21
+ // if no Route matches. Routes call this to decide whether to render.
22
+ // Reads $state internally, so callers using it inside $derived/$effect
23
+ // auto-subscribe to URL + registration changes.
24
+ getActiveMatch: () => ActiveMatch | null;
21
25
  };
22
26
  </script>
23
27
 
24
28
  <script lang="ts">
25
- import { getContext, onMount, setContext } from 'svelte';
29
+ import { getContext, onMount, setContext, type Snippet } from 'svelte';
26
30
  import type { RouterMode } from '../../types/svelteRouter';
27
31
  import { setRouterMode } from './goto';
28
32
  import { hashPathnameOf } from './hashMode';
@@ -64,15 +68,17 @@
64
68
  const isOutermost = parent === undefined;
65
69
 
66
70
  // Specificity ranking across siblings: each <Route> registers with
67
- // its compiled pattern + content snippet + a stable mount-order
68
- // index. The winner is computed lazily from the current URL — highest
69
- // score wins; ties break by earlier registration order.
71
+ // its compiled pattern + a stable mount-order index. The winner is
72
+ // computed lazily from the current URL — highest score wins; ties
73
+ // break by earlier registration order. The winning Route then renders
74
+ // its own content at ITS location in the markup (so a Route nested
75
+ // inside a layout `<section>` renders inside that section, not at the
76
+ // Router's root).
70
77
  const routes = $state(new Map<string, RouteEntry>());
71
78
  let routeCounter = 0;
72
79
 
73
- const computeWinner = () => {
80
+ const computeWinner = (): ActiveMatch | null => {
74
81
  let bestId: string | null = null;
75
- let bestEntry: RouteEntry | null = null;
76
82
  let bestParams: Record<string, string | undefined> | null = null;
77
83
  let bestScore = -Infinity;
78
84
  let bestOrder = Infinity;
@@ -89,21 +95,25 @@
89
95
  bestScore = entry.pattern.score;
90
96
  bestOrder = entry.registrationOrder;
91
97
  bestId = id;
92
- bestEntry = entry;
93
98
  bestParams = match.params as Record<string, string | undefined>;
94
99
  }
95
100
  }
96
101
 
97
- return bestId && bestEntry && bestParams
98
- ? { content: bestEntry.content, params: bestParams }
102
+ return bestId && bestParams
103
+ ? { id: bestId, params: bestParams }
99
104
  : null;
100
105
  };
101
106
 
107
+ // Recompute on every page.url change OR routes registry mutation.
108
+ // Reading $state during $derived auto-tracks both dependencies.
109
+ const winner = $derived(computeWinner());
110
+
102
111
  const registry: RouterRegistry = {
103
112
  basepath: stackedBasepath,
104
113
  deregister: (id) => {
105
114
  routes.delete(id);
106
115
  },
116
+ getActiveMatch: () => winner,
107
117
  mode: stackedMode,
108
118
  nextRouteId: () => `r${routeCounter++}`,
109
119
  register: (id, entry) => {
@@ -113,10 +123,6 @@
113
123
 
114
124
  setContext<RouterRegistry>(ROUTER_CONTEXT_KEY, registry);
115
125
 
116
- // Recompute on every page.url change OR routes registry mutation.
117
- // Reading $state during $derived auto-tracks both dependencies.
118
- const winner = $derived(computeWinner());
119
-
120
126
  if (isOutermost) {
121
127
  setRouterMode(stackedMode);
122
128
 
@@ -176,6 +182,3 @@
176
182
  </script>
177
183
 
178
184
  {@render children?.()}
179
- {#if winner}
180
- {@render winner.content(winner.params)}
181
- {/if}
package/package.json CHANGED
@@ -384,5 +384,5 @@
384
384
  ]
385
385
  }
386
386
  },
387
- "version": "0.19.0-beta.836"
387
+ "version": "0.19.0-beta.838"
388
388
  }