vue-multi-router 0.1.0

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 ADDED
@@ -0,0 +1,1028 @@
1
+ import { computed, defineComponent, getCurrentInstance, h, inject, onBeforeUnmount, provide, ref, shallowRef } from "vue";
2
+ import { RouterLink, RouterView, createRouter, routeLocationKey, routerKey, routerViewLocationKey, viewDepthKey } from "vue-router";
3
+
4
+ //#region src/history/storage/types.ts
5
+ function isPromise(value) {
6
+ return value instanceof Promise;
7
+ }
8
+ function resolveValue(value, callback) {
9
+ if (isPromise(value)) value.then(callback);
10
+ else callback(value);
11
+ }
12
+ function mapMaybePromise(value, fn) {
13
+ if (isPromise(value)) return value.then(fn);
14
+ return fn(value);
15
+ }
16
+ function flatMapMaybePromise(value, fn) {
17
+ if (isPromise(value)) return value.then(fn);
18
+ return fn(value);
19
+ }
20
+
21
+ //#endregion
22
+ //#region src/history/storage/session-storage-adapter.ts
23
+ const STACK_STORAGE_PREFIX = "__multiRouter_stack_";
24
+ const ACTIVE_CONTEXT_STORAGE_KEY = "__multiRouterActiveContext";
25
+ const ACTIVE_HISTORY_CONTEXT_STORAGE_KEY = "__multiRouterActiveHistoryContext";
26
+ var SessionStorageAdapter = class {
27
+ getStackStorageKey(contextKey) {
28
+ return `${STACK_STORAGE_PREFIX}${contextKey}`;
29
+ }
30
+ saveStack(contextKey, stack) {
31
+ try {
32
+ const data = {
33
+ entries: stack.entries,
34
+ position: stack.position
35
+ };
36
+ sessionStorage.setItem(this.getStackStorageKey(contextKey), JSON.stringify(data));
37
+ } catch (e) {
38
+ console.warn("[SessionStorageAdapter] Failed to save stack:", e);
39
+ }
40
+ }
41
+ restoreStack(contextKey) {
42
+ try {
43
+ const stored = sessionStorage.getItem(this.getStackStorageKey(contextKey));
44
+ if (!stored) return null;
45
+ const data = JSON.parse(stored);
46
+ if (data && Array.isArray(data.entries) && data.entries.length > 0) {
47
+ const position = Math.min(Math.max(0, data.position ?? 0), data.entries.length - 1);
48
+ return {
49
+ entries: data.entries,
50
+ position
51
+ };
52
+ }
53
+ } catch (e) {
54
+ console.warn("[SessionStorageAdapter] Failed to restore stack:", e);
55
+ }
56
+ return null;
57
+ }
58
+ clearStack(contextKey) {
59
+ try {
60
+ sessionStorage.removeItem(this.getStackStorageKey(contextKey));
61
+ } catch (e) {
62
+ console.warn("[SessionStorageAdapter] Failed to clear stack:", e);
63
+ }
64
+ }
65
+ saveActiveContext(contextKey) {
66
+ try {
67
+ sessionStorage.setItem(ACTIVE_CONTEXT_STORAGE_KEY, contextKey);
68
+ } catch (e) {
69
+ console.warn("[SessionStorageAdapter] Failed to save active context:", e);
70
+ }
71
+ }
72
+ getActiveContext() {
73
+ try {
74
+ return sessionStorage.getItem(ACTIVE_CONTEXT_STORAGE_KEY);
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+ saveActiveHistoryContext(contextKey) {
80
+ try {
81
+ sessionStorage.setItem(ACTIVE_HISTORY_CONTEXT_STORAGE_KEY, contextKey);
82
+ } catch (e) {
83
+ console.warn("[SessionStorageAdapter] Failed to save active history context:", e);
84
+ }
85
+ }
86
+ getActiveHistoryContext() {
87
+ try {
88
+ return sessionStorage.getItem(ACTIVE_HISTORY_CONTEXT_STORAGE_KEY);
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+ };
94
+
95
+ //#endregion
96
+ //#region src/history/types.ts
97
+ let NavigationType = /* @__PURE__ */ function(NavigationType$1) {
98
+ NavigationType$1["pop"] = "pop";
99
+ NavigationType$1["push"] = "push";
100
+ return NavigationType$1;
101
+ }({});
102
+ let NavigationDirection = /* @__PURE__ */ function(NavigationDirection$1) {
103
+ NavigationDirection$1["back"] = "back";
104
+ NavigationDirection$1["forward"] = "forward";
105
+ NavigationDirection$1["unknown"] = "";
106
+ return NavigationDirection$1;
107
+ }({});
108
+
109
+ //#endregion
110
+ //#region src/history/storage.ts
111
+ var VirtualStackStorage = class {
112
+ adapter;
113
+ constructor(adapter) {
114
+ this.adapter = adapter ?? new SessionStorageAdapter();
115
+ }
116
+ save(contextKey, stack) {
117
+ return this.adapter.saveStack(contextKey, stack);
118
+ }
119
+ restore(contextKey) {
120
+ return this.adapter.restoreStack(contextKey);
121
+ }
122
+ clear(contextKey) {
123
+ return this.adapter.clearStack(contextKey);
124
+ }
125
+ saveActiveContext(contextKey) {
126
+ return this.adapter.saveActiveContext(contextKey);
127
+ }
128
+ getActiveContext() {
129
+ return this.adapter.getActiveContext();
130
+ }
131
+ saveActiveHistoryContext(contextKey) {
132
+ return this.adapter.saveActiveHistoryContext(contextKey);
133
+ }
134
+ getActiveHistoryContext() {
135
+ return this.adapter.getActiveHistoryContext();
136
+ }
137
+ resolveValue = resolveValue;
138
+ };
139
+
140
+ //#endregion
141
+ //#region src/history/virtual-stack.ts
142
+ var VirtualStackManager = class {
143
+ contexts = /* @__PURE__ */ new Map();
144
+ storage;
145
+ constructor(storageAdapter) {
146
+ this.storage = new VirtualStackStorage(storageAdapter);
147
+ }
148
+ has(contextKey) {
149
+ return this.contexts.has(contextKey);
150
+ }
151
+ get(contextKey) {
152
+ return this.contexts.get(contextKey);
153
+ }
154
+ create(contextKey, initialStack, historyEnabled = true) {
155
+ this.contexts.set(contextKey, {
156
+ virtualStack: initialStack,
157
+ listeners: /* @__PURE__ */ new Set(),
158
+ historyEnabled
159
+ });
160
+ }
161
+ isHistoryEnabled(contextKey) {
162
+ return this.contexts.get(contextKey)?.historyEnabled ?? true;
163
+ }
164
+ remove(contextKey) {
165
+ this.contexts.delete(contextKey);
166
+ this.storage.clear(contextKey);
167
+ }
168
+ clear() {
169
+ this.contexts.clear();
170
+ }
171
+ getLocation(contextKey, fallback) {
172
+ const context = this.contexts.get(contextKey);
173
+ if (!context) return fallback;
174
+ return context.virtualStack.entries[context.virtualStack.position]?.location ?? fallback;
175
+ }
176
+ getState(contextKey) {
177
+ const context = this.contexts.get(contextKey);
178
+ if (!context) return {};
179
+ return context.virtualStack.entries[context.virtualStack.position]?.state ?? {};
180
+ }
181
+ push(contextKey, location, state) {
182
+ const context = this.contexts.get(contextKey);
183
+ if (!context) throw new Error(`[VirtualStackManager] Context "${contextKey}" not found`);
184
+ context.virtualStack.entries = context.virtualStack.entries.slice(0, context.virtualStack.position + 1);
185
+ context.virtualStack.entries.push({
186
+ location,
187
+ state
188
+ });
189
+ context.virtualStack.position = context.virtualStack.entries.length - 1;
190
+ this.save(contextKey);
191
+ return context.virtualStack.position;
192
+ }
193
+ replace(contextKey, location, state) {
194
+ const context = this.contexts.get(contextKey);
195
+ if (!context) throw new Error(`[VirtualStackManager] Context "${contextKey}" not found`);
196
+ context.virtualStack.entries[context.virtualStack.position] = {
197
+ location,
198
+ state
199
+ };
200
+ this.save(contextKey);
201
+ return context.virtualStack.position;
202
+ }
203
+ navigate(contextKey, delta) {
204
+ const context = this.contexts.get(contextKey);
205
+ if (!context) return null;
206
+ const newPosition = context.virtualStack.position + delta;
207
+ if (newPosition < 0 || newPosition >= context.virtualStack.entries.length) return null;
208
+ const from = context.virtualStack.entries[context.virtualStack.position].location;
209
+ context.virtualStack.position = newPosition;
210
+ const to = context.virtualStack.entries[newPosition].location;
211
+ this.save(contextKey);
212
+ return {
213
+ from,
214
+ to,
215
+ newPosition
216
+ };
217
+ }
218
+ setPosition(contextKey, position) {
219
+ const context = this.contexts.get(contextKey);
220
+ if (!context) return;
221
+ if (position >= 0 && position < context.virtualStack.entries.length) {
222
+ context.virtualStack.position = position;
223
+ this.save(contextKey);
224
+ }
225
+ }
226
+ ensureEntriesUpTo(contextKey, position, fallbackLocation) {
227
+ const context = this.contexts.get(contextKey);
228
+ if (!context) return;
229
+ while (context.virtualStack.entries.length <= position) context.virtualStack.entries.push({
230
+ location: fallbackLocation,
231
+ state: {}
232
+ });
233
+ }
234
+ addListener(contextKey, callback) {
235
+ const context = this.contexts.get(contextKey);
236
+ if (!context) throw new Error(`[VirtualStackManager] Context "${contextKey}" not found`);
237
+ context.listeners.add(callback);
238
+ return () => context.listeners.delete(callback);
239
+ }
240
+ notifyListeners(contextKey, to, from, info) {
241
+ const context = this.contexts.get(contextKey);
242
+ if (!context) return;
243
+ context.listeners.forEach((callback) => callback(to, from, info));
244
+ }
245
+ save(contextKey) {
246
+ const context = this.contexts.get(contextKey);
247
+ if (context) return this.storage.save(contextKey, context.virtualStack);
248
+ }
249
+ restore(contextKey) {
250
+ return this.storage.restore(contextKey);
251
+ }
252
+ saveActiveContext(contextKey) {
253
+ return this.storage.saveActiveContext(contextKey);
254
+ }
255
+ getStoredActiveContext() {
256
+ return this.storage.getActiveContext();
257
+ }
258
+ saveActiveHistoryContext(contextKey) {
259
+ return this.storage.saveActiveHistoryContext(contextKey);
260
+ }
261
+ getStoredActiveHistoryContext() {
262
+ return this.storage.getActiveHistoryContext();
263
+ }
264
+ entries() {
265
+ return this.contexts.entries();
266
+ }
267
+ };
268
+
269
+ //#endregion
270
+ //#region src/history/manager.ts
271
+ var ContextHistoryProxy = class {
272
+ constructor(contextKey, manager) {
273
+ this.contextKey = contextKey;
274
+ this.manager = manager;
275
+ }
276
+ get base() {
277
+ return this.manager.base;
278
+ }
279
+ get location() {
280
+ return this.manager.getContextLocation(this.contextKey);
281
+ }
282
+ get state() {
283
+ return this.manager.getContextState(this.contextKey);
284
+ }
285
+ push(to, data) {
286
+ this.manager.push(this.contextKey, to, data);
287
+ }
288
+ replace(to, data) {
289
+ this.manager.replace(this.contextKey, to, data);
290
+ }
291
+ go(delta, triggerListeners) {
292
+ this.manager.go(this.contextKey, delta, triggerListeners);
293
+ }
294
+ listen(callback) {
295
+ return this.manager.listen(this.contextKey, callback);
296
+ }
297
+ createHref(location) {
298
+ return this.manager.createHref(location);
299
+ }
300
+ destroy() {
301
+ this.manager.removeContextHistory(this.contextKey);
302
+ }
303
+ };
304
+ const CONTEXT_KEY_STATE = "__multiRouterContext";
305
+ const STACK_INDEX_STATE = "__multiRouterStackIndex";
306
+ var MultiRouterHistoryManager = class {
307
+ baseHistory;
308
+ stacks;
309
+ activeHistoryContextKey = null;
310
+ historyContextStack = [];
311
+ baseHistoryCleanup = null;
312
+ contextSwitchMode;
313
+ onContextActivate;
314
+ constructor(historyBuilder, options) {
315
+ this.baseHistory = historyBuilder();
316
+ this.stacks = new VirtualStackManager(options?.storageAdapter);
317
+ this.contextSwitchMode = options?.contextSwitchMode ?? "replace";
318
+ this.onContextActivate = options?.onContextActivate;
319
+ this.baseHistoryCleanup = this.baseHistory.listen(this.handlePopState.bind(this));
320
+ }
321
+ get base() {
322
+ return this.baseHistory.base;
323
+ }
324
+ get location() {
325
+ return this.baseHistory.location;
326
+ }
327
+ get state() {
328
+ return this.baseHistory.state;
329
+ }
330
+ createContextHistory(contextKey, options) {
331
+ if (this.stacks.has(contextKey)) return new ContextHistoryProxy(contextKey, this);
332
+ const { location, initialLocation, historyEnabled = true } = options ?? {};
333
+ return flatMapMaybePromise(this.stacks.getStoredActiveContext(), (lastActiveContext) => {
334
+ const isLastActive = lastActiveContext === contextKey;
335
+ if (location) {
336
+ const virtualStack = this.createInitialVirtualStack(location);
337
+ console.debug("[MultiRouterHistory] Created context with forced location", {
338
+ contextKey,
339
+ location
340
+ });
341
+ return this.finalizeContextCreation(contextKey, virtualStack, isLastActive, historyEnabled);
342
+ }
343
+ return mapMaybePromise(this.stacks.restore(contextKey), (restoredStack) => {
344
+ let virtualStack;
345
+ if (restoredStack) {
346
+ if (isLastActive && historyEnabled) {
347
+ const browserUrl = this.baseHistory.location;
348
+ restoredStack.entries[restoredStack.position] = {
349
+ location: browserUrl,
350
+ state: this.baseHistory.state ?? {}
351
+ };
352
+ console.debug("[MultiRouterHistory] Restored from storage with browser URL", {
353
+ contextKey,
354
+ browserUrl
355
+ });
356
+ } else console.debug("[MultiRouterHistory] Restored from storage", {
357
+ contextKey,
358
+ historyEnabled
359
+ });
360
+ virtualStack = restoredStack;
361
+ } else if (isLastActive && historyEnabled) {
362
+ const browserUrl = this.baseHistory.location;
363
+ virtualStack = this.createInitialVirtualStack(browserUrl);
364
+ console.debug("[MultiRouterHistory] Created with browser URL (last active)", {
365
+ contextKey,
366
+ browserUrl
367
+ });
368
+ } else if (initialLocation) {
369
+ virtualStack = this.createInitialVirtualStack(initialLocation);
370
+ console.debug("[MultiRouterHistory] Created with initialLocation", {
371
+ contextKey,
372
+ initialLocation
373
+ });
374
+ } else {
375
+ virtualStack = this.createInitialVirtualStack();
376
+ console.debug("[MultiRouterHistory] Created with default location", { contextKey });
377
+ }
378
+ return this.finalizeContextCreation(contextKey, virtualStack, isLastActive, historyEnabled);
379
+ });
380
+ });
381
+ }
382
+ finalizeContextCreation(contextKey, virtualStack, isLastActive, historyEnabled) {
383
+ this.stacks.create(contextKey, virtualStack, historyEnabled);
384
+ if (isLastActive && historyEnabled) {
385
+ this.activeHistoryContextKey = contextKey;
386
+ this.restoreUrlFromVirtualStack(contextKey);
387
+ }
388
+ return new ContextHistoryProxy(contextKey, this);
389
+ }
390
+ tryRestoreActiveHistoryContext(contextKey) {
391
+ return mapMaybePromise(this.stacks.getStoredActiveHistoryContext(), (storedKey) => {
392
+ if (storedKey === contextKey && this.stacks.has(contextKey) && this.stacks.isHistoryEnabled(contextKey)) {
393
+ this.activeHistoryContextKey = contextKey;
394
+ this.restoreUrlFromVirtualStack(contextKey);
395
+ return true;
396
+ }
397
+ return false;
398
+ });
399
+ }
400
+ removeContextHistory(contextKey) {
401
+ this.stacks.remove(contextKey);
402
+ if (this.activeHistoryContextKey === contextKey) this.fallbackToPreviousHistoryContext();
403
+ this.historyContextStack = this.historyContextStack.filter((k) => k !== contextKey);
404
+ }
405
+ setActiveHistoryContext(contextKey) {
406
+ if (!this.stacks.has(contextKey)) throw new Error(`[MultiRouterHistory] Context "${contextKey}" not registered`);
407
+ if (this.activeHistoryContextKey === contextKey) return;
408
+ const previousKey = this.activeHistoryContextKey;
409
+ if (previousKey) {
410
+ this.historyContextStack = this.historyContextStack.filter((k) => k !== previousKey);
411
+ this.historyContextStack.push(previousKey);
412
+ }
413
+ this.activeHistoryContextKey = contextKey;
414
+ this.stacks.saveActiveContext(contextKey);
415
+ this.stacks.saveActiveHistoryContext(contextKey);
416
+ this.restoreUrlFromVirtualStack(contextKey);
417
+ console.debug("[MultiRouterHistory] setActiveHistoryContext", {
418
+ from: previousKey,
419
+ to: contextKey
420
+ });
421
+ }
422
+ clearActiveHistoryContext(contextKey) {
423
+ if (this.activeHistoryContextKey !== contextKey) return;
424
+ this.fallbackToPreviousHistoryContext();
425
+ }
426
+ saveActiveContext(contextKey) {
427
+ this.stacks.saveActiveContext(contextKey);
428
+ }
429
+ getActiveHistoryContextKey() {
430
+ return this.activeHistoryContextKey;
431
+ }
432
+ fallbackToPreviousHistoryContext() {
433
+ const previousKey = this.historyContextStack.pop();
434
+ if (previousKey && this.stacks.has(previousKey)) this.activeHistoryContextKey = previousKey;
435
+ else this.activeHistoryContextKey = null;
436
+ console.debug("[MultiRouterHistory] fallbackToPreviousHistoryContext", { to: this.activeHistoryContextKey });
437
+ }
438
+ createInitialVirtualStack(initialLocation) {
439
+ return {
440
+ entries: [{
441
+ location: initialLocation ?? "/",
442
+ state: {}
443
+ }],
444
+ position: 0
445
+ };
446
+ }
447
+ restoreUrlFromVirtualStack(contextKey) {
448
+ if (this.contextSwitchMode === "none") return;
449
+ const context = this.stacks.get(contextKey);
450
+ if (!context) return;
451
+ const entry = context.virtualStack.entries[context.virtualStack.position];
452
+ if (!entry) return;
453
+ const state = {
454
+ ...entry.state,
455
+ [CONTEXT_KEY_STATE]: contextKey,
456
+ [STACK_INDEX_STATE]: context.virtualStack.position
457
+ };
458
+ if (this.contextSwitchMode === "push") if (entry.location !== this.baseHistory.location) this.baseHistory.push(entry.location, state);
459
+ else this.baseHistory.replace(entry.location, state);
460
+ else this.baseHistory.replace(entry.location, state);
461
+ }
462
+ handlePopState(to, from, info) {
463
+ const stateContextKey = this.baseHistory.state?.[CONTEXT_KEY_STATE];
464
+ const stateStackIndex = this.baseHistory.state?.[STACK_INDEX_STATE];
465
+ console.debug("[MultiRouterHistory] popstate raw", {
466
+ stateContextKey,
467
+ stateStackIndex,
468
+ browserTo: to,
469
+ browserFrom: from,
470
+ delta: info.delta,
471
+ virtualStacks: Object.fromEntries(Array.from(this.stacks.entries()).map(([k, v]) => [k, {
472
+ position: v.virtualStack.position,
473
+ entries: v.virtualStack.entries.map((e) => e.location)
474
+ }]))
475
+ });
476
+ let ownerContextKey = null;
477
+ let targetStackIndex = null;
478
+ if (stateContextKey && this.stacks.has(stateContextKey)) {
479
+ ownerContextKey = stateContextKey;
480
+ targetStackIndex = stateStackIndex ?? null;
481
+ }
482
+ if (!ownerContextKey) ownerContextKey = this.activeHistoryContextKey;
483
+ if (!ownerContextKey) return;
484
+ const context = this.stacks.get(ownerContextKey);
485
+ let newPosition;
486
+ if (targetStackIndex !== null) newPosition = targetStackIndex;
487
+ else newPosition = context.virtualStack.position + info.delta;
488
+ this.stacks.ensureEntriesUpTo(ownerContextKey, newPosition, to);
489
+ if (newPosition >= 0 && newPosition < context.virtualStack.entries.length) {
490
+ const previousLocation = context.virtualStack.entries[context.virtualStack.position]?.location ?? from;
491
+ this.stacks.setPosition(ownerContextKey, newPosition);
492
+ const targetLocation = context.virtualStack.entries[newPosition]?.location ?? to;
493
+ console.debug("[MultiRouterHistory] popstate result", {
494
+ ownerContext: ownerContextKey,
495
+ activeContext: this.activeHistoryContextKey,
496
+ browserUrl: to,
497
+ contextUrl: targetLocation,
498
+ targetStackIndex: newPosition,
499
+ previousLocation,
500
+ delta: info.delta
501
+ });
502
+ if (this.onContextActivate) this.onContextActivate(ownerContextKey);
503
+ this.stacks.notifyListeners(ownerContextKey, targetLocation, previousLocation, info);
504
+ }
505
+ }
506
+ push(contextKey, to, data) {
507
+ const stackIndex = this.stacks.push(contextKey, to, data ?? {});
508
+ const historyEnabled = this.stacks.isHistoryEnabled(contextKey);
509
+ if (this.activeHistoryContextKey === contextKey && historyEnabled) this.baseHistory.push(to, {
510
+ ...data,
511
+ [CONTEXT_KEY_STATE]: contextKey,
512
+ [STACK_INDEX_STATE]: stackIndex
513
+ });
514
+ console.debug("[MultiRouterHistory] push", {
515
+ contextKey,
516
+ to,
517
+ stackIndex,
518
+ isActive: this.activeHistoryContextKey === contextKey,
519
+ historyEnabled
520
+ });
521
+ }
522
+ replace(contextKey, to, data) {
523
+ const stackIndex = this.stacks.replace(contextKey, to, data ?? {});
524
+ const historyEnabled = this.stacks.isHistoryEnabled(contextKey);
525
+ if (this.activeHistoryContextKey === contextKey && historyEnabled) this.baseHistory.replace(to, {
526
+ ...data,
527
+ [CONTEXT_KEY_STATE]: contextKey,
528
+ [STACK_INDEX_STATE]: stackIndex
529
+ });
530
+ console.debug("[MultiRouterHistory] replace", {
531
+ contextKey,
532
+ to,
533
+ stackIndex,
534
+ isActive: this.activeHistoryContextKey === contextKey,
535
+ historyEnabled
536
+ });
537
+ }
538
+ go(contextKey, delta, triggerListeners = true) {
539
+ if (!this.stacks.has(contextKey)) throw new Error(`[MultiRouterHistory] Context "${contextKey}" not registered`);
540
+ if (this.activeHistoryContextKey === contextKey) this.baseHistory.go(delta, triggerListeners);
541
+ else {
542
+ const result = this.stacks.navigate(contextKey, delta);
543
+ if (result && triggerListeners) this.stacks.notifyListeners(contextKey, result.to, result.from, {
544
+ type: NavigationType.pop,
545
+ direction: delta < 0 ? NavigationDirection.back : NavigationDirection.forward,
546
+ delta
547
+ });
548
+ }
549
+ }
550
+ listen(contextKey, callback) {
551
+ return this.stacks.addListener(contextKey, callback);
552
+ }
553
+ getContextLocation(contextKey) {
554
+ return this.stacks.getLocation(contextKey, this.baseHistory.location);
555
+ }
556
+ getContextState(contextKey) {
557
+ return this.stacks.getState(contextKey);
558
+ }
559
+ createHref(location) {
560
+ return this.baseHistory.createHref(location);
561
+ }
562
+ destroy() {
563
+ if (this.baseHistoryCleanup) {
564
+ this.baseHistoryCleanup();
565
+ this.baseHistoryCleanup = null;
566
+ }
567
+ this.stacks.clear();
568
+ this.baseHistory.destroy();
569
+ }
570
+ getLastActiveContextKey() {
571
+ return this.stacks.getStoredActiveContext();
572
+ }
573
+ };
574
+
575
+ //#endregion
576
+ //#region src/contextManager.ts
577
+ var MultiRouterManagerInstance = class {
578
+ started = false;
579
+ activeContext = shallowRef();
580
+ activeHistoryContext = shallowRef();
581
+ registered = /* @__PURE__ */ new Map();
582
+ onContextInitListeners = [];
583
+ historyManager;
584
+ constructor(app, types, historyManagerOptions, makeRouter) {
585
+ this.types = types;
586
+ this.makeRouter = makeRouter;
587
+ const { historyBuilder, ...historyOptions } = historyManagerOptions;
588
+ this.historyManager = new MultiRouterHistoryManager(historyBuilder, {
589
+ ...historyOptions,
590
+ onContextActivate: (contextKey) => {
591
+ this.setActive(contextKey, false);
592
+ }
593
+ });
594
+ }
595
+ getHistoryManager() {
596
+ return this.historyManager;
597
+ }
598
+ getActiveContext() {
599
+ return this.activeContext.value;
600
+ }
601
+ getActiveContextRef() {
602
+ return this.activeContext;
603
+ }
604
+ getActiveHistoryContext() {
605
+ return this.activeHistoryContext.value;
606
+ }
607
+ getActiveHistoryContextRef() {
608
+ return this.activeHistoryContext;
609
+ }
610
+ setActive(key, updateHistory) {
611
+ const item = this.registered.get(key);
612
+ if (!item) throw new Error(`[MultiRouter] Context "${key}" not found`);
613
+ let modified = false;
614
+ if (this.activeContext.value?.key !== key) {
615
+ this.activeContext.value = {
616
+ key,
617
+ context: item
618
+ };
619
+ modified = true;
620
+ }
621
+ if (updateHistory) {
622
+ this.historyManager.saveActiveContext(key);
623
+ if (item.historyEnabled && this.activeHistoryContext.value?.key !== key) {
624
+ this.activeHistoryContext.value = this.activeContext.value;
625
+ this.historyManager.setActiveHistoryContext(key);
626
+ }
627
+ }
628
+ if (modified) console.debug("[MultiRouterContextManager] setActive", {
629
+ key,
630
+ updateHistory,
631
+ historyEnabled: item.historyEnabled
632
+ });
633
+ return modified;
634
+ }
635
+ clearHistoryContext(key) {
636
+ if (this.activeHistoryContext.value?.key === key) {
637
+ this.historyManager.clearActiveHistoryContext(key);
638
+ const newActiveKey = this.historyManager.getActiveHistoryContextKey();
639
+ if (newActiveKey) {
640
+ const newContext = this.registered.get(newActiveKey);
641
+ if (newContext) this.activeHistoryContext.value = {
642
+ key: newActiveKey,
643
+ context: newContext
644
+ };
645
+ } else this.activeHistoryContext.value = void 0;
646
+ }
647
+ }
648
+ markAsStarted() {
649
+ this.started = true;
650
+ }
651
+ getRouter(key) {
652
+ return this.registered.get(key).router;
653
+ }
654
+ has(key) {
655
+ return this.registered.has(key);
656
+ }
657
+ register(type, key, options) {
658
+ if (!this.types[type]) throw new Error(`[MultiRouter] Context type "${type}" not found`);
659
+ const historyEnabled = options?.historyEnabled ?? true;
660
+ const isDefault = options?.default ?? false;
661
+ return mapMaybePromise(this.historyManager.createContextHistory(key, {
662
+ location: options?.location,
663
+ initialLocation: options?.initialLocation,
664
+ historyEnabled
665
+ }), (history) => {
666
+ const router = this.makeRouter(key, history);
667
+ this.registered.set(key, {
668
+ type,
669
+ router,
670
+ history,
671
+ initialized: false,
672
+ historyEnabled
673
+ });
674
+ router.push(history.location).catch((err) => {
675
+ console.warn("Unexpected error when starting the router:", err);
676
+ });
677
+ router.isReady().then(() => {
678
+ this.markAsStarted();
679
+ mapMaybePromise(this.historyManager.tryRestoreActiveHistoryContext(key), (restored) => {
680
+ if (restored && !this.activeHistoryContext.value) {
681
+ console.debug("[MultiRouterContextManager] Restored activeHistoryContext", { key });
682
+ this.activeHistoryContext.value = {
683
+ key,
684
+ context: this.registered.get(key)
685
+ };
686
+ }
687
+ });
688
+ mapMaybePromise(this.historyManager.getLastActiveContextKey(), (resolvedLastActiveKey) => {
689
+ if (resolvedLastActiveKey === key && !this.activeContext.value) {
690
+ console.debug("[MultiRouterContextManager] Auto-activating last active context", { key });
691
+ this.setActive(key, true);
692
+ } else if (isDefault && !resolvedLastActiveKey && !this.activeContext.value) {
693
+ console.debug("[MultiRouterContextManager] Activating default context", {
694
+ key,
695
+ historyEnabled
696
+ });
697
+ this.setActive(key, true);
698
+ }
699
+ });
700
+ });
701
+ });
702
+ }
703
+ getContextLocation(key) {
704
+ return this.historyManager.getContextLocation(key);
705
+ }
706
+ getContextHistoryEnabled(key) {
707
+ return this.registered.get(key)?.historyEnabled ?? true;
708
+ }
709
+ unregister(key) {
710
+ if (this.registered.get(key)) {
711
+ console.debug("[MultiRouterContextManager] unregister", { key });
712
+ this.historyManager.removeContextHistory(key);
713
+ this.registered.delete(key);
714
+ }
715
+ }
716
+ initialize(key) {
717
+ this.registered.get(key).initialized = true;
718
+ this.onContextInitListeners.forEach((fn) => fn(key));
719
+ }
720
+ onContextInit(fn) {
721
+ if (this.started) throw new Error("[MultiRouter] adding listener after start is not allowed");
722
+ this.onContextInitListeners.push(fn);
723
+ }
724
+ };
725
+
726
+ //#endregion
727
+ //#region src/symbols.ts
728
+ const multiRouterContextManager = Symbol("multi-router-context-manager");
729
+ const multiRouterContext = Symbol("multi-router-context-key");
730
+
731
+ //#endregion
732
+ //#region src/injectionSymbols.ts
733
+ const multiRouterContextManagerKey = multiRouterContextManager;
734
+ const multiRouterContextKey = multiRouterContext;
735
+
736
+ //#endregion
737
+ //#region src/multi-router.ts
738
+ const START_LOCATION_NORMALIZED = {
739
+ path: "/",
740
+ name: void 0,
741
+ params: {},
742
+ query: {},
743
+ hash: "",
744
+ fullPath: "/",
745
+ matched: [],
746
+ meta: {},
747
+ redirectedFrom: void 0
748
+ };
749
+ const getCurrentInstance$1 = () => getCurrentInstance();
750
+ function installContextAwareRouterResolvers(app, contextManager) {
751
+ if (app._context.provides[routerKey]) throw new Error("Router installed to app, this may cause unexpected behavior");
752
+ function isVueDevtoolsCall() {
753
+ return !!(/* @__PURE__ */ new Error()).stack?.includes("chrome-extension://nhdogjmejiglipccpnnnanhbledajbpd");
754
+ }
755
+ function getInstanceContextKey() {
756
+ const instance = getCurrentInstance$1();
757
+ if (!instance) {
758
+ if (isVueDevtoolsCall()) return null;
759
+ throw new Error("No instance found");
760
+ }
761
+ const contextKey = instance.provides[multiRouterContext];
762
+ if (!contextKey) throw new Error("Context key not found");
763
+ return contextKey;
764
+ }
765
+ const routerProperty = {
766
+ enumerable: true,
767
+ get() {
768
+ const contextKey = getInstanceContextKey();
769
+ if (!contextKey) return null;
770
+ if (!contextManager.has(contextKey)) {
771
+ if (isVueDevtoolsCall()) return null;
772
+ throw new Error(`Router not found for context ${contextKey}`);
773
+ }
774
+ return contextManager.getRouter(contextKey);
775
+ }
776
+ };
777
+ const routeProperty = {
778
+ enumerable: true,
779
+ get() {
780
+ const contextKey = getInstanceContextKey();
781
+ if (!contextKey || !contextManager.has(contextKey)) return null;
782
+ const currentRoute = contextManager.getRouter(contextKey).currentRoute;
783
+ const reactiveRoute = {};
784
+ for (const key in START_LOCATION_NORMALIZED) Object.defineProperty(reactiveRoute, key, {
785
+ get: () => currentRoute.value[key],
786
+ enumerable: true
787
+ });
788
+ return reactiveRoute;
789
+ }
790
+ };
791
+ Object.defineProperty(app._context.provides, routerKey, routerProperty);
792
+ Object.defineProperty(app.config.globalProperties, "$router", routerProperty);
793
+ Object.defineProperty(app._context.provides, routeLocationKey, routeProperty);
794
+ Object.defineProperty(app.config.globalProperties, "$route", routeProperty);
795
+ Object.defineProperty(app._context.provides, routerViewLocationKey, {
796
+ enumerable: true,
797
+ configurable: true,
798
+ get() {
799
+ const contextKey = getInstanceContextKey();
800
+ if (!contextKey || !contextManager.has(contextKey)) return null;
801
+ return contextManager.getRouter(contextKey).currentRoute;
802
+ },
803
+ set() {}
804
+ });
805
+ }
806
+ function installComponents(app) {
807
+ app.component("RouterLink", RouterLink);
808
+ app.component("RouterView", RouterView);
809
+ }
810
+ const contextTemplateWindows = { window: {
811
+ canUseAsHistoryContext: true,
812
+ single: false
813
+ } };
814
+ const contextTemplateTabs = { tab: {
815
+ canUseAsHistoryContext: true,
816
+ single: false
817
+ } };
818
+ const contextTemplateMainWithWindows = {
819
+ main: {
820
+ canUseAsHistoryContext: true,
821
+ single: true
822
+ },
823
+ ...contextTemplateWindows
824
+ };
825
+ const contextTemplateDesktopWithWindows = {
826
+ desktop: {
827
+ canUseAsHistoryContext: false,
828
+ single: true
829
+ },
830
+ ...contextTemplateWindows
831
+ };
832
+ const contextTemplateTabsWithWindows = {
833
+ ...contextTemplateTabs,
834
+ ...contextTemplateWindows
835
+ };
836
+ function createMultiRouter(options) {
837
+ let contextManager;
838
+ return {
839
+ getByContextName: (name) => {
840
+ return contextManager.getRouter(name);
841
+ },
842
+ install: (app) => {
843
+ const makeRouter = (contextKey, history) => {
844
+ const router = createRouter({
845
+ ...options,
846
+ history
847
+ });
848
+ Object.assign(router, { contextKey });
849
+ return router;
850
+ };
851
+ contextManager = new MultiRouterManagerInstance(app, options.types, {
852
+ historyBuilder: options.history,
853
+ ...options.historyOptions
854
+ }, makeRouter);
855
+ app.provide(multiRouterContextManagerKey, contextManager);
856
+ installComponents(app);
857
+ installContextAwareRouterResolvers(app, contextManager);
858
+ }
859
+ };
860
+ }
861
+
862
+ //#endregion
863
+ //#region src/components/MultiRouterContext.vue?vue&type=script&lang.ts
864
+ const MultiRouterContextInner = defineComponent({
865
+ name: "MultiRouterContextInner",
866
+ props: {
867
+ type: {
868
+ type: String,
869
+ required: true
870
+ },
871
+ name: {
872
+ type: String,
873
+ required: true
874
+ },
875
+ location: {
876
+ type: String,
877
+ required: false
878
+ },
879
+ initialLocation: {
880
+ type: String,
881
+ required: false
882
+ },
883
+ historyEnabled: {
884
+ type: Boolean,
885
+ default: true
886
+ },
887
+ default: {
888
+ type: Boolean,
889
+ default: false
890
+ }
891
+ },
892
+ setup(props, { slots }) {
893
+ const manager = inject(multiRouterContextManagerKey);
894
+ console.debug("[MultiRouterContext] setup", {
895
+ type: props.type,
896
+ name: props.name,
897
+ location: props.location,
898
+ initialLocation: props.initialLocation
899
+ });
900
+ if (manager.has(props.name)) {
901
+ console.warn(`[MultiRouterContext] Context "${props.name}" already registered, skipping`);
902
+ return () => slots.default?.();
903
+ }
904
+ manager.register(props.type, props.name, {
905
+ location: props.location,
906
+ initialLocation: props.initialLocation,
907
+ historyEnabled: props.historyEnabled,
908
+ default: props.default
909
+ });
910
+ provide(multiRouterContext, props.name);
911
+ provide(viewDepthKey, ref(0));
912
+ onBeforeUnmount(() => {
913
+ manager.unregister(props.name);
914
+ });
915
+ return () => slots.default?.();
916
+ }
917
+ });
918
+ var MultiRouterContext_vue_vue_type_script_lang_default = defineComponent({
919
+ name: "MultiRouterContext",
920
+ props: {
921
+ type: {
922
+ type: String,
923
+ required: true
924
+ },
925
+ name: {
926
+ type: String,
927
+ required: true
928
+ },
929
+ location: {
930
+ type: String,
931
+ required: false
932
+ },
933
+ initialLocation: {
934
+ type: String,
935
+ required: false
936
+ },
937
+ historyEnabled: {
938
+ type: Boolean,
939
+ default: true
940
+ },
941
+ default: {
942
+ type: Boolean,
943
+ default: false
944
+ }
945
+ },
946
+ setup(props, { slots }) {
947
+ return () => h(MultiRouterContextInner, {
948
+ key: `${props.name}:${props.location ?? ""}`,
949
+ type: props.type,
950
+ name: props.name,
951
+ location: props.location,
952
+ initialLocation: props.initialLocation,
953
+ historyEnabled: props.historyEnabled,
954
+ default: props.default
955
+ }, slots.default);
956
+ }
957
+ });
958
+
959
+ //#endregion
960
+ //#region src/components/MultiRouterContext.vue
961
+ var MultiRouterContext_default = MultiRouterContext_vue_vue_type_script_lang_default;
962
+
963
+ //#endregion
964
+ //#region src/components/MultiRouterContextActivator.vue?vue&type=script&lang.ts
965
+ var MultiRouterContextActivator_vue_vue_type_script_lang_default = defineComponent({
966
+ props: { as: {
967
+ type: String,
968
+ default: null
969
+ } },
970
+ setup(props, { slots }) {
971
+ const contextKey = inject(multiRouterContextKey);
972
+ const manager = inject(multiRouterContextManagerKey);
973
+ if (!contextKey || !manager) {
974
+ console.warn("[MultiRouterContextActivator] Must be used within MultiRouterContext");
975
+ return () => slots.default?.();
976
+ }
977
+ const onActivate = (e) => {
978
+ e.stopPropagation();
979
+ if (manager.setActive(contextKey, true)) console.debug("[MultiRouterContextActivator] activated", contextKey);
980
+ };
981
+ return () => {
982
+ const children = slots.default?.();
983
+ if (!props.as) {
984
+ if (children && children.length === 1) return h(children[0], { onMousedown: onActivate });
985
+ return h("span", { onMousedown: onActivate }, children);
986
+ }
987
+ return h(props.as, { onMousedown: onActivate }, children);
988
+ };
989
+ }
990
+ });
991
+
992
+ //#endregion
993
+ //#region src/components/MultiRouterContextActivator.vue
994
+ var MultiRouterContextActivator_default = MultiRouterContextActivator_vue_vue_type_script_lang_default;
995
+
996
+ //#endregion
997
+ //#region src/composables/useMultiRouterContext.ts
998
+ function useMultiRouterContext() {
999
+ const manager = inject(multiRouterContextManagerKey);
1000
+ const contextKey = inject(multiRouterContextKey);
1001
+ if (!manager) throw new Error("[useMultiRouterContext] Must be used within MultiRouterContextProvider");
1002
+ if (!contextKey) throw new Error("[useMultiRouterContext] Must be used within MultiRouterContext");
1003
+ const router = computed(() => manager.getRouter(contextKey));
1004
+ const route = computed(() => router.value.currentRoute.value);
1005
+ const isActive = computed(() => manager.getActiveContextRef().value?.key === contextKey);
1006
+ const activeContextKey = computed(() => manager.getActiveContextRef().value?.key);
1007
+ const activeHistoryContextKey = computed(() => manager.getActiveHistoryContextRef().value?.key);
1008
+ const isHistoryActive = computed(() => manager.getActiveHistoryContextRef().value?.key === contextKey);
1009
+ const historyEnabled = computed(() => manager.getContextHistoryEnabled(contextKey));
1010
+ const activate = (updateHistory = true) => {
1011
+ manager.setActive(contextKey, updateHistory);
1012
+ };
1013
+ return {
1014
+ manager,
1015
+ contextKey,
1016
+ router,
1017
+ route,
1018
+ isActive,
1019
+ isHistoryActive,
1020
+ activeContextKey,
1021
+ activeHistoryContextKey,
1022
+ historyEnabled,
1023
+ activate
1024
+ };
1025
+ }
1026
+
1027
+ //#endregion
1028
+ export { MultiRouterContext_default as MultiRouterContext, MultiRouterContextActivator_default as MultiRouterContextActivator, contextTemplateDesktopWithWindows, contextTemplateMainWithWindows, contextTemplateTabs, contextTemplateTabsWithWindows, contextTemplateWindows, createMultiRouter, multiRouterContextKey, multiRouterContextManagerKey, useMultiRouterContext };