vue-micro-router 1.0.34 → 1.0.37

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/audio.d.ts CHANGED
@@ -19,8 +19,10 @@ export declare interface AudioAdapter {
19
19
  loop?: boolean;
20
20
  volume?: number;
21
21
  }): void;
22
- /** Stop and unload the current sound */
22
+ /** Stop playback (keeps instance for resume) */
23
23
  stop(): void;
24
+ /** Full teardown — unload audio buffer, release memory */
25
+ destroy(): void;
24
26
  /** Pause playback (preserves position) */
25
27
  pause(): void;
26
28
  /** Resume from paused state */
@@ -49,6 +51,10 @@ export declare interface AudioManagerState {
49
51
  /** Synchronous play — no async gaps, safe in user gesture context for autoplay policy */
50
52
  playSoundSync: (soundSrc: string, loop?: boolean) => void;
51
53
  stopSound: () => void;
54
+ /** Pause BGM without destroying the Howl instance — resumeSound() to continue */
55
+ pauseSound: () => void;
56
+ /** Resume paused BGM — safe to call from non-gesture context (no new Howl created) */
57
+ resumeSound: () => void;
52
58
  updateBackgroundMusic: (route: string, routes?: Map<string, MicroRoute>) => Promise<void>;
53
59
  handleVisibilityChange: () => void;
54
60
  /** Whether audio has successfully started playing at least once */
@@ -70,6 +76,8 @@ export declare class HowlerAdapter implements AudioAdapter {
70
76
  volume?: number;
71
77
  }): void;
72
78
  stop(): void;
79
+ /** Full teardown — unload audio buffer, release memory */
80
+ destroy(): void;
73
81
  pause(): void;
74
82
  resume(): void;
75
83
  fade(from: number, to: number, duration: number): void;
package/dist/index.d.ts CHANGED
@@ -495,6 +495,8 @@ export declare interface MicroRouterStore {
495
495
  restore?: (state: SerializedState) => Promise<void>;
496
496
  playSound?: (soundSrc: string, loop?: boolean) => Promise<void>;
497
497
  stopSound?: () => void;
498
+ pauseSound?: () => void;
499
+ resumeSound?: () => void;
498
500
  updateBackgroundMusic?: (route: string) => Promise<void>;
499
501
  }
500
502
 
@@ -594,13 +596,20 @@ export declare interface PluginTypedCloseDialog<Dialogs extends string> {
594
596
  * Typed store from plugin(s) — push/openDialog/closeDialog/toggleControl all validate names.
595
597
  * Accepts single plugin or union of plugins: `typeof pluginA | typeof pluginB`
596
598
  */
597
- export declare type PluginTypedMicroRouterStore<T> = Omit<MicroRouterStore, 'push' | 'stepWisePush' | 'stepWiseBack' | 'openDialog' | 'closeDialog' | 'toggleControl'> & {
599
+ export declare type PluginTypedMicroRouterStore<T> = Omit<MicroRouterStore, 'push' | 'stepWisePush' | 'stepWiseBack' | 'openDialog' | 'closeDialog' | 'toggleControl' | 'activePage' | 'fromPage' | 'toPage' | 'activeDialog' | 'fromDialog' | 'toDialog' | 'currentControl'> & {
598
600
  push: PluginTypedPush<ExtractRoutePaths<T>, RegisteredRouteAttrs>;
599
601
  stepWisePush: PluginTypedStepWisePush<ExtractRoutePaths<T>, RegisteredRouteAttrs>;
600
602
  stepWiseBack: PluginTypedStepWiseBack;
601
603
  openDialog: PluginTypedOpenDialog<ExtractDialogPaths<T>, RegisteredDialogAttrs>;
602
604
  closeDialog: PluginTypedCloseDialog<ExtractDialogPaths<T>>;
603
605
  toggleControl: PluginTypedToggleControl<ExtractControlNames<T>, RegisteredControlAttrs>;
606
+ activePage: ComputedRef<ExtractRoutePaths<T>>;
607
+ fromPage: ComputedRef<ExtractRoutePaths<T>>;
608
+ toPage: ComputedRef<ExtractRoutePaths<T>>;
609
+ activeDialog: ComputedRef<ExtractDialogPaths<T> | ''>;
610
+ fromDialog: ComputedRef<ExtractDialogPaths<T> | ''>;
611
+ toDialog: ComputedRef<ExtractDialogPaths<T> | ''>;
612
+ currentControl: ComputedRef<ExtractControlNames<T>>;
604
613
  };
605
614
 
606
615
  export declare interface PluginTypedOpenDialog<Dialogs extends string, AttrsMap = {}> {
@@ -690,13 +699,20 @@ export declare function registerFeaturePlugins(plugins: FeaturePlugin[], store:
690
699
  * Priority: plugin > routeMap > untyped MicroRouterStore
691
700
  * Attrs maps (routeAttrs/dialogAttrs/controlAttrs) are passed through when declared.
692
701
  */
693
- export declare type ResolvedMicroRouterStore = HasRegisteredPlugin extends true ? Omit<MicroRouterStore, 'push' | 'stepWisePush' | 'stepWiseBack' | 'openDialog' | 'closeDialog' | 'toggleControl'> & {
702
+ export declare type ResolvedMicroRouterStore = HasRegisteredPlugin extends true ? Omit<MicroRouterStore, 'push' | 'stepWisePush' | 'stepWiseBack' | 'openDialog' | 'closeDialog' | 'toggleControl' | 'activePage' | 'fromPage' | 'toPage' | 'activeDialog' | 'fromDialog' | 'toDialog' | 'currentControl'> & {
694
703
  push: PluginTypedPush<ExtractRoutePaths<RegisteredPlugin>, RegisteredRouteAttrs>;
695
704
  stepWisePush: PluginTypedStepWisePush<ExtractRoutePaths<RegisteredPlugin>, RegisteredRouteAttrs>;
696
705
  stepWiseBack: PluginTypedStepWiseBack;
697
706
  openDialog: PluginTypedOpenDialog<ExtractDialogPaths<RegisteredPlugin>, RegisteredDialogAttrs>;
698
707
  closeDialog: PluginTypedCloseDialog<ExtractDialogPaths<RegisteredPlugin>>;
699
708
  toggleControl: PluginTypedToggleControl<ExtractControlNames<RegisteredPlugin>, RegisteredControlAttrs>;
709
+ activePage: ComputedRef<ExtractRoutePaths<RegisteredPlugin>>;
710
+ fromPage: ComputedRef<ExtractRoutePaths<RegisteredPlugin>>;
711
+ toPage: ComputedRef<ExtractRoutePaths<RegisteredPlugin>>;
712
+ activeDialog: ComputedRef<ExtractDialogPaths<RegisteredPlugin> | ''>;
713
+ fromDialog: ComputedRef<ExtractDialogPaths<RegisteredPlugin> | ''>;
714
+ toDialog: ComputedRef<ExtractDialogPaths<RegisteredPlugin> | ''>;
715
+ currentControl: ComputedRef<ExtractControlNames<RegisteredPlugin>>;
700
716
  } : HasRegisteredRouteMap extends true ? Omit<MicroRouterStore, 'push'> & {
701
717
  push: TypedPush<RegisteredRouteMap>;
702
718
  } : MicroRouterStore;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { shallowReactive as Y, computed as E, defineAsyncComponent as fe, reactive as de, nextTick as J, ref as ve, inject as F, watch as X, onMounted as j, onBeforeUnmount as Re, provide as N, toRefs as Ge, toRef as Ie, defineComponent as ee, openBlock as B, createBlock as V, resolveDynamicComponent as me, mergeProps as he, Teleport as Be, createElementVNode as Q, normalizeStyle as Ee, normalizeClass as ce, withModifiers as Ne, renderSlot as pe, createElementBlock as q, Fragment as Z, createVNode as De, TransitionGroup as Ce, withCtx as ie, renderList as se, unref as U } from "vue";
1
+ import { shallowReactive as Y, computed as S, defineAsyncComponent as fe, reactive as de, nextTick as J, ref as ve, inject as F, watch as X, onMounted as j, onBeforeUnmount as Re, provide as N, toRefs as Ge, toRef as Ie, defineComponent as ee, openBlock as B, createBlock as V, resolveDynamicComponent as me, mergeProps as he, Teleport as Be, createElementVNode as Q, normalizeStyle as Se, normalizeClass as ce, withModifiers as Ne, renderSlot as pe, createElementBlock as q, Fragment as Z, createVNode as De, TransitionGroup as Ce, withCtx as ie, renderList as se, unref as U } from "vue";
2
2
  import { i as ye, s as Pe, g as x, w as k, p as G, b as K, n as W, u as Oe } from "./use-audio-manager.mjs";
3
- const Se = Symbol("micro-router");
3
+ const Ee = Symbol("micro-router");
4
4
  function lt() {
5
5
  return Symbol("micro-router-nested");
6
6
  }
@@ -26,14 +26,14 @@ function We(e, n) {
26
26
  let c = !1;
27
27
  const r = Y(/* @__PURE__ */ new Map()), u = Y(
28
28
  /* @__PURE__ */ new Map()
29
- ), a = E(() => {
29
+ ), a = S(() => {
30
30
  const s = [];
31
31
  for (const f of r.values())
32
32
  f.activated && s.push(f);
33
33
  return s;
34
- }), d = a, A = E(
34
+ }), d = a, A = S(
35
35
  () => a.value.some((s) => s.name !== o)
36
- ), M = E(() => {
36
+ ), M = S(() => {
37
37
  const s = a.value.find((f) => f.name !== o);
38
38
  return (s == null ? void 0 : s.name) ?? o;
39
39
  });
@@ -257,7 +257,7 @@ function ze(e) {
257
257
  dialogs: Y(/* @__PURE__ */ new Map()),
258
258
  /** Attrs stored separately for useMicroState access inside dialog components */
259
259
  dialogAttrs: Y(/* @__PURE__ */ new Map())
260
- }), l = E(() => {
260
+ }), l = S(() => {
261
261
  const g = [];
262
262
  for (const m of t.dialogs.values())
263
263
  (m.activated || m.closing) && g.push(m);
@@ -359,9 +359,9 @@ function ze(e) {
359
359
  t.dialogAttrs.set(g, { ...s, ...m });
360
360
  }
361
361
  return {
362
- activeDialog: E(() => t.activeDialog),
363
- fromDialog: E(() => t.fromDialog),
364
- toDialog: E(() => t.toDialog),
362
+ activeDialog: S(() => t.activeDialog),
363
+ fromDialog: S(() => t.fromDialog),
364
+ toDialog: S(() => t.toDialog),
365
365
  resolveDialogs: l,
366
366
  openDialog: a,
367
367
  closeDialog: d,
@@ -427,7 +427,7 @@ function xe(e, n) {
427
427
  function r(g, m) {
428
428
  !e.enabled || l || (t < i.length - 1 && i.splice(t + 1), i.push({ path: g, timestamp: Date.now(), props: m ? { ...m } : void 0 }), t = i.length - 1, i.length > o && (i.shift(), t--), c.value++);
429
429
  }
430
- const u = E(() => (c.value, [...i])), a = E(() => (c.value, t > 0)), d = E(() => (c.value, t < i.length - 1));
430
+ const u = S(() => (c.value, [...i])), a = S(() => (c.value, t > 0)), d = S(() => (c.value, t < i.length - 1));
431
431
  async function A(g) {
432
432
  if (g < 0 || g >= i.length) return;
433
433
  const m = i[g];
@@ -561,16 +561,16 @@ function qe(e, n) {
561
561
  routeKeys: Y(/* @__PURE__ */ new Map()),
562
562
  /** Component key per segment — incremented to force Vue full remount (resets local state) */
563
563
  componentKeys: Y(/* @__PURE__ */ new Map())
564
- }), d = /* @__PURE__ */ new Map(), A = E(() => {
564
+ }), d = /* @__PURE__ */ new Map(), A = S(() => {
565
565
  const p = G(a.activePath), h = [];
566
566
  for (const v of p) {
567
567
  const D = r.routes.get(v);
568
568
  if (!D) continue;
569
- const P = a.routeKeys.get(v) || 0, b = a.componentKeys.get(v) || 0, S = `${D.path}-${P}`, R = d.get(v);
570
- if (R && R.key === S && R.componentKey === b)
569
+ const P = a.routeKeys.get(v) || 0, b = a.componentKeys.get(v) || 0, E = `${D.path}-${P}`, R = d.get(v);
570
+ if (R && R.key === E && R.componentKey === b)
571
571
  h.push(R);
572
572
  else {
573
- const O = { ...D, key: S, componentKey: b };
573
+ const O = { ...D, key: E, componentKey: b };
574
574
  d.set(v, O), h.push(O);
575
575
  }
576
576
  }
@@ -585,25 +585,25 @@ function qe(e, n) {
585
585
  const P = v.slice(0, -D), b = K(P);
586
586
  for (let $ = v.length - D; $ < v.length; $++)
587
587
  a.routeAttrs.delete(v[$]);
588
- const S = P.at(-1);
589
- if (S && h) {
590
- const $ = a.routeAttrs.get(S);
591
- a.routeAttrs.set(S, { ...$, ...h }), a.componentKeys.set(
592
- S,
593
- (a.componentKeys.get(S) || 0) + 1
588
+ const E = P.at(-1);
589
+ if (E && h) {
590
+ const $ = a.routeAttrs.get(E);
591
+ a.routeAttrs.set(E, { ...$, ...h }), a.componentKeys.set(
592
+ E,
593
+ (a.componentKeys.get(E) || 0) + 1
594
594
  );
595
595
  }
596
596
  const R = a.activePath;
597
597
  (O = n == null ? void 0 : n.trackPageLeave) == null || O.call(n, R, R, b), a.fromPath = R, a.toPath = b, a.activePath = b, (I = n == null ? void 0 : n.trackPageEnter) == null || I.call(n, b, R, b);
598
598
  }
599
599
  async function T(p, h) {
600
- var b, S;
600
+ var b, E;
601
601
  const v = W(p), D = G(v);
602
602
  await Promise.all(
603
603
  D.map((R) => r.asyncLoaders.get(R)).filter((R) => !!R).map((R) => k(R))
604
604
  );
605
605
  const P = a.activePath;
606
- P !== v && ((b = n == null ? void 0 : n.trackPageLeave) == null || b.call(n, P, P, v)), a.fromPath = P, a.toPath = v, a.activePath = v, h && w(v, h), (S = n == null ? void 0 : n.trackPageEnter) == null || S.call(n, v, P, v);
606
+ P !== v && ((b = n == null ? void 0 : n.trackPageLeave) == null || b.call(n, P, P, v)), a.fromPath = P, a.toPath = v, a.activePath = v, h && w(v, h), (E = n == null ? void 0 : n.trackPageEnter) == null || E.call(n, v, P, v);
607
607
  }
608
608
  function w(p, h) {
609
609
  const v = G(p).at(-1);
@@ -626,19 +626,19 @@ function qe(e, n) {
626
626
  }
627
627
  const v = p.toString();
628
628
  if (v.startsWith("/")) {
629
- const S = G(v), R = G(a.activePath);
630
- if (S.length < R.length && S.every(($, oe) => R[oe] === $)) {
631
- if (R.length - S.length === 1)
629
+ const E = G(v), R = G(a.activePath);
630
+ if (E.length < R.length && E.every(($, oe) => R[oe] === $)) {
631
+ if (R.length - E.length === 1)
632
632
  M(1, h);
633
633
  else {
634
- const oe = R.slice(0, S.length + 1), Te = K(oe);
635
- for (let ae = S.length + 1; ae < R.length; ae++)
634
+ const oe = R.slice(0, E.length + 1), Te = K(oe);
635
+ for (let ae = E.length + 1; ae < R.length; ae++)
636
636
  a.routeAttrs.delete(R[ae]);
637
637
  a.activePath = Te, await J(), M(1, h);
638
638
  }
639
639
  return;
640
640
  }
641
- const I = S.at(-1);
641
+ const I = E.at(-1);
642
642
  I && R.at(-1) === I && a.routeKeys.set(
643
643
  I,
644
644
  (a.routeKeys.get(I) || 0) + 1
@@ -647,10 +647,10 @@ function qe(e, n) {
647
647
  }
648
648
  const D = G(a.activePath), P = D.indexOf(v);
649
649
  if (P !== -1) {
650
- const S = D.length - (P + 1);
651
- if (S === 1)
650
+ const E = D.length - (P + 1);
651
+ if (E === 1)
652
652
  M(1, h);
653
- else if (S > 1) {
653
+ else if (E > 1) {
654
654
  const R = D.slice(0, P + 2), O = K(R);
655
655
  for (let I = P + 2; I < D.length; I++)
656
656
  a.routeAttrs.delete(D[I]);
@@ -691,8 +691,8 @@ function qe(e, n) {
691
691
  }
692
692
  const b = W(a.activePath);
693
693
  await m(p, h);
694
- const S = W(a.activePath);
695
- C == null || C.record(S, h), Fe(S, b, t.afterEach), r.preloadAdjacent(G(a.activePath)), c.schedule(() => {
694
+ const E = W(a.activePath);
695
+ C == null || C.record(E, h), Fe(E, b, t.afterEach), r.preloadAdjacent(G(a.activePath)), c.schedule(() => {
696
696
  u = !1;
697
697
  }, i);
698
698
  } catch (D) {
@@ -726,12 +726,12 @@ function qe(e, n) {
726
726
  stepDelay: i
727
727
  });
728
728
  return {
729
- activePath: E(() => a.activePath),
730
- fromPath: E(() => a.fromPath),
731
- toPath: E(() => a.toPath),
732
- activePage: E(() => x(a.activePath)),
733
- fromPage: E(() => x(a.fromPath)),
734
- toPage: E(() => x(a.toPath)),
729
+ activePath: S(() => a.activePath),
730
+ fromPath: S(() => a.fromPath),
731
+ toPath: S(() => a.toPath),
732
+ activePage: S(() => x(a.activePath)),
733
+ fromPage: S(() => x(a.fromPath)),
734
+ toPage: S(() => x(a.toPath)),
735
735
  resolveRoutes: A,
736
736
  push: y,
737
737
  stepWisePush: _.stepWisePush,
@@ -836,6 +836,8 @@ function Qe(e) {
836
836
  ...l ? {
837
837
  playSound: l.playSound,
838
838
  stopSound: l.stopSound,
839
+ pauseSound: l.pauseSound,
840
+ resumeSound: l.resumeSound,
839
841
  updateBackgroundMusic: l.updateBackgroundMusic
840
842
  } : {}
841
843
  }, r = x(e.defaultPath);
@@ -853,10 +855,10 @@ function Qe(e) {
853
855
  ), l && document.addEventListener("visibilitychange", l.handleVisibilityChange), Ye(c);
854
856
  }), Re(() => {
855
857
  n.cleanupAllSessions(), o.cleanup(), i.cleanup(), t.cleanup(), l && (document.removeEventListener("visibilitychange", l.handleVisibilityChange), l.cleanup());
856
- }), N(Se, c), F(ue, null) || N(ue, c), c;
858
+ }), N(Ee, c), F(ue, null) || N(ue, c), c;
857
859
  }
858
860
  function H(e) {
859
- const n = e != null && e.root ? ue : Se, o = F(n);
861
+ const n = e != null && e.root ? ue : Ee, o = F(n);
860
862
  if (!o)
861
863
  throw new Error(
862
864
  e != null && e.root ? "[vue-micro-router] useMicroRouter({ root: true }) failed — no root <MicroRouterView> found." : "[vue-micro-router] useMicroRouter() must be called inside <MicroRouterView>. Did you forget to wrap your app with <MicroRouterView>?"
@@ -1038,7 +1040,7 @@ const et = /* @__PURE__ */ ee({
1038
1040
  N(Me, o.dialog.path), N(te, () => t(o.dialog.path)), N(ne, (w) => {
1039
1041
  l(o.dialog.path, w);
1040
1042
  });
1041
- const r = E(() => o.dialog.transition ?? "scale"), u = E(() => o.dialog.transitionDuration != null ? o.dialog.transitionDuration : r.value === "slide" ? 500 : 300), a = E(() => o.dialog.position ?? "standard"), d = E(() => o.dialog.seamless ?? !0);
1043
+ const r = S(() => o.dialog.transition ?? "scale"), u = S(() => o.dialog.transitionDuration != null ? o.dialog.transitionDuration : r.value === "slide" ? 500 : 300), a = S(() => o.dialog.position ?? "standard"), d = S(() => o.dialog.seamless ?? !0);
1042
1044
  function A(w) {
1043
1045
  if (o.dialog.persistent) {
1044
1046
  w.preventDefault();
@@ -1082,7 +1084,7 @@ const et = /* @__PURE__ */ ee({
1082
1084
  `dialog-transition-${r.value}`,
1083
1085
  e.dialog.closing && "micro-dialog--closing"
1084
1086
  ]),
1085
- style: Ee({
1087
+ style: Se({
1086
1088
  "--dialog-duration": `${u.value}ms`,
1087
1089
  zIndex: 100 + e.stackIndex,
1088
1090
  width: "100vw",
@@ -1151,16 +1153,16 @@ const et = /* @__PURE__ */ ee({
1151
1153
  fromPath: c,
1152
1154
  toPath: r,
1153
1155
  closeDialog: u
1154
- } = o, a = ve(null), d = E(() => {
1156
+ } = o, a = ve(null), d = S(() => {
1155
1157
  const s = c.value.split("/").filter(Boolean), f = new Set(r.value.split("/").filter(Boolean));
1156
1158
  return s.some((y) => f.has(y));
1157
- }), A = E(() => l.value.length > 0), M = E(() => {
1159
+ }), A = S(() => l.value.length > 0), M = S(() => {
1158
1160
  const s = i.value.at(-1);
1159
1161
  return (s == null ? void 0 : s.transition) ?? "slide";
1160
- }), T = E(() => M.value === "none" ? "" : M.value === "fade" ? "page-fade" : "page-slide"), w = E(() => {
1162
+ }), T = S(() => M.value === "none" ? "" : M.value === "fade" ? "page-fade" : "page-slide"), w = S(() => {
1161
1163
  const s = i.value.at(-1);
1162
1164
  return s != null && s.transitionDuration ? s.transitionDuration : M.value === "fade" ? 300 : 500;
1163
- }), L = E(() => d.value && M.value !== "none");
1165
+ }), L = S(() => d.value && M.value !== "none");
1164
1166
  return (m = n.config.gesture) != null && m.enabled && Ze(n.config.gesture, {
1165
1167
  containerRef: a,
1166
1168
  goBack: () => o.push(-1),
@@ -1179,7 +1181,7 @@ const et = /* @__PURE__ */ ee({
1179
1181
  class: ce({
1180
1182
  deactive: U(i).length > 1 && C !== U(i).length - 1
1181
1183
  }),
1182
- style: Ee({
1184
+ style: Se({
1183
1185
  transition: L.value ? `transform ${w.value}ms cubic-bezier(0.65, 0, 0.35, 1), opacity ${w.value}ms ease` : "none",
1184
1186
  zIndex: C,
1185
1187
  "--mr-page-height": e.nested ? "100%" : "100dvh"
@@ -1225,7 +1227,7 @@ export {
1225
1227
  ne as MICRO_ATTRS_WRITE_KEY,
1226
1228
  Le as MICRO_CONTROL_NAME_KEY,
1227
1229
  Me as MICRO_DIALOG_PATH_KEY,
1228
- Se as MICRO_ROUTER_KEY,
1230
+ Ee as MICRO_ROUTER_KEY,
1229
1231
  ue as MICRO_ROUTER_ROOT_KEY,
1230
1232
  be as MICRO_ROUTE_PATH_KEY,
1231
1233
  et as MicroControlWrapper,
@@ -1,26 +1,26 @@
1
- import { markRaw as w, ref as S, computed as g, watch as C } from "vue";
2
- class H {
1
+ import { markRaw as g, ref as C, computed as H, watch as P } from "vue";
2
+ class b {
3
3
  constructor() {
4
- this.sound = null, this.HowlCtor = null, import("howler").then((o) => {
5
- this.HowlCtor = o.Howl;
4
+ this.sound = null, this.HowlCtor = null, import("howler").then((s) => {
5
+ this.HowlCtor = s.Howl;
6
6
  }).catch(() => {
7
7
  });
8
8
  }
9
- async play(o, u = {}) {
10
- if (this.stop(), !this.HowlCtor) {
11
- const n = await import("howler");
12
- this.HowlCtor = n.Howl;
9
+ async play(s, n = {}) {
10
+ if (this.destroy(), !this.HowlCtor) {
11
+ const u = await import("howler");
12
+ this.HowlCtor = u.Howl;
13
13
  }
14
- const i = this.HowlCtor, e = u.volume ?? 1;
15
- return new Promise((n, d) => {
14
+ const i = this.HowlCtor, e = n.volume ?? 1;
15
+ return new Promise((u, d) => {
16
16
  this.sound = new i({
17
- src: [o],
17
+ src: [s],
18
18
  autoplay: !1,
19
- loop: u.loop ?? !1,
19
+ loop: n.loop ?? !1,
20
20
  volume: 0,
21
21
  onplay: () => {
22
22
  var r;
23
- (r = this.sound) == null || r.fade(0, e, 200), n();
23
+ (r = this.sound) == null || r.fade(0, e, 200), u();
24
24
  },
25
25
  onloaderror: (r, c) => {
26
26
  d(new Error(`Failed to load audio: ${c}`));
@@ -30,21 +30,25 @@ class H {
30
30
  (r = this.sound) == null || r.once("unlock", () => {
31
31
  var c;
32
32
  (c = this.sound) == null || c.play();
33
- }), n();
33
+ }), u();
34
34
  }
35
35
  }), this.sound.play();
36
36
  });
37
37
  }
38
38
  /** Fully synchronous play — uses preloaded HowlCtor. No-op if not preloaded yet. */
39
- playSync(o, u = {}) {
40
- this.HowlCtor && (this.stop(), this.sound = new this.HowlCtor({
41
- src: [o],
39
+ playSync(s, n = {}) {
40
+ this.HowlCtor && (this.destroy(), this.sound = new this.HowlCtor({
41
+ src: [s],
42
42
  autoplay: !0,
43
- loop: u.loop ?? !1,
43
+ loop: n.loop ?? !1,
44
44
  volume: 0
45
- }), this.sound.play(), this.sound.fade(0, u.volume ?? 1, 200));
45
+ }), this.sound.play(), this.sound.fade(0, n.volume ?? 1, 200));
46
46
  }
47
47
  stop() {
48
+ this.sound && this.sound.stop();
49
+ }
50
+ /** Full teardown — unload audio buffer, release memory */
51
+ destroy() {
48
52
  try {
49
53
  this.sound && (this.sound.stop(), this.sound.off(), this.sound.unload(), this.sound = null);
50
54
  } catch {
@@ -52,127 +56,135 @@ class H {
52
56
  }
53
57
  }
54
58
  pause() {
55
- var o;
56
- (o = this.sound) != null && o.playing() && this.sound.pause();
59
+ var s;
60
+ (s = this.sound) != null && s.playing() && this.sound.pause();
57
61
  }
58
62
  resume() {
59
63
  this.sound && this.state() === "loaded" && this.sound.play();
60
64
  }
61
- fade(o, u, i) {
65
+ fade(s, n, i) {
62
66
  var e;
63
- (e = this.sound) != null && e.playing() && this.sound.fade(o, u, i);
67
+ (e = this.sound) != null && e.playing() && this.sound.fade(s, n, i);
64
68
  }
65
69
  isPlaying() {
66
- var o;
67
- return ((o = this.sound) == null ? void 0 : o.playing()) ?? !1;
70
+ var s;
71
+ return ((s = this.sound) == null ? void 0 : s.playing()) ?? !1;
68
72
  }
69
73
  state() {
70
74
  return this.sound ? this.sound.state() : "unloaded";
71
75
  }
72
76
  cleanup() {
73
- this.stop();
77
+ this.destroy();
74
78
  }
75
79
  }
76
- function k(t) {
80
+ function L(t) {
77
81
  return t.startsWith("/") ? t : `/${t}`;
78
82
  }
79
- function B(t) {
83
+ function x(t) {
80
84
  return t.split("/").filter(Boolean);
81
85
  }
82
- function L(t) {
86
+ function A(t) {
83
87
  return `/${t.join("/")}`;
84
88
  }
85
- function P(t) {
86
- const o = t.lastIndexOf("/");
87
- return o === -1 ? t : t.substring(o + 1);
89
+ function k(t) {
90
+ const s = t.lastIndexOf("/");
91
+ return s === -1 ? t : t.substring(s + 1);
88
92
  }
89
- function x(t) {
93
+ function M(t) {
90
94
  try {
91
- return w(t);
95
+ return g(t);
92
96
  } catch {
93
97
  return t;
94
98
  }
95
99
  }
96
- function A(t) {
100
+ function R(t) {
97
101
  return typeof t == "function" && !("__name" in t) && !("setup" in t) && !("render" in t);
98
102
  }
99
- async function M(t) {
103
+ async function V(t) {
100
104
  try {
101
105
  await t();
102
106
  } catch {
103
107
  }
104
108
  }
105
- function R(t) {
106
- let o = !1;
107
- const u = (t == null ? void 0 : t.defaultBgm) ?? "";
109
+ function _(t) {
110
+ let s = !1;
111
+ const n = (t == null ? void 0 : t.defaultBgm) ?? "";
108
112
  let i = "";
109
- const e = (t == null ? void 0 : t.adapter) ?? new H(), n = S(""), d = g(() => {
113
+ const e = (t == null ? void 0 : t.adapter) ?? new b(), u = C(""), d = H(() => {
110
114
  var a;
111
115
  return (((a = t == null ? void 0 : t.volumeRef) == null ? void 0 : a.value) || 0) / 100;
112
116
  });
113
117
  async function r(a, l = !1) {
114
118
  try {
115
- const s = a === "default" ? u : a;
116
- if (!s || e.isPlaying() && n.value === s) return;
117
- i = n.value, n.value = s, e.stop(), await e.play(s, { loop: a === "default" ? !0 : l, volume: d.value });
118
- } catch (s) {
119
- console.error("Sound playback failed:", s), e.stop();
119
+ const o = a === "default" ? n : a;
120
+ if (!o || e.isPlaying() && u.value === o) return;
121
+ i = u.value, u.value = o, await e.play(o, { loop: a === "default" ? !0 : l, volume: d.value });
122
+ } catch (o) {
123
+ console.error("Sound playback failed:", o), e.destroy();
120
124
  }
121
125
  }
122
126
  function c(a, l = !1) {
123
127
  try {
124
- const s = a === "default" ? u : a;
125
- if (!s || e.isPlaying() && n.value === s) return;
126
- i = n.value, n.value = s, e.stop();
127
- const p = a === "default" ? !0 : l;
128
- e.playSync ? e.playSync(s, { loop: p, volume: d.value }) : e.play(s, { loop: p, volume: d.value });
129
- } catch (s) {
130
- console.error("Sound playback failed:", s), e.stop();
128
+ const o = a === "default" ? n : a;
129
+ if (!o || e.isPlaying() && u.value === o) return;
130
+ i = u.value, u.value = o;
131
+ const f = a === "default" ? !0 : l;
132
+ e.playSync ? e.playSync(o, { loop: f, volume: d.value }) : e.play(o, { loop: f, volume: d.value });
133
+ } catch (o) {
134
+ console.error("Sound playback failed:", o), e.stop();
131
135
  }
132
136
  }
133
- function h() {
137
+ function y() {
134
138
  e.stop();
135
139
  }
136
- async function y(a, l) {
140
+ function p() {
141
+ e.pause();
142
+ }
143
+ function m() {
144
+ e.state() === "loaded" ? e.resume() : n && r(n, !0);
145
+ }
146
+ async function v(a, l) {
137
147
  if (l)
138
148
  try {
139
- const s = P(a) || "home", p = l.get(s), f = (p == null ? void 0 : p.bgm) || u;
140
- f && i !== f && await r(f, !0);
141
- } catch (s) {
142
- console.error("Error updating background music:", s);
149
+ const o = k(a) || "home", f = l.get(o), h = (f == null ? void 0 : f.bgm) || n;
150
+ h && i !== h && await r(h, !0);
151
+ } catch (o) {
152
+ console.error("Error updating background music:", o);
143
153
  }
144
154
  }
145
- function m() {
155
+ function w() {
146
156
  if (!(typeof document > "u"))
147
157
  try {
148
- document.hidden ? e.isPlaying() && (e.pause(), o = !0) : o && e.state() === "loaded" && (e.resume(), o = !1);
158
+ document.hidden ? e.isPlaying() && (e.pause(), s = !0) : s && e.state() === "loaded" && (e.resume(), s = !1);
149
159
  } catch {
150
160
  e.stop();
151
161
  }
152
162
  }
153
- function v() {
163
+ function S() {
154
164
  e.cleanup();
155
165
  }
156
- return C(d, (a, l) => {
157
- e.isPlaying() ? e.fade(l ?? 0, a, 300) : a > 0 && n.value && r(n.value, !0);
166
+ return P(d, (a, l) => {
167
+ e.isPlaying() ? e.fade(l ?? 0, a, 300) : a > 0 && u.value && r(u.value, !0);
158
168
  }), {
159
169
  playSound: r,
160
170
  playSoundSync: c,
161
- stopSound: h,
162
- updateBackgroundMusic: y,
171
+ stopSound: y,
172
+ pauseSound: p,
173
+ resumeSound: m,
174
+ updateBackgroundMusic: v,
163
175
  isStarted: () => e.isPlaying() || e.state() === "loaded",
164
- handleVisibilityChange: m,
165
- cleanup: v
176
+ handleVisibilityChange: w,
177
+ cleanup: S
166
178
  };
167
179
  }
168
180
  export {
169
- H,
170
- L as b,
171
- P as g,
172
- A as i,
173
- k as n,
174
- B as p,
175
- x as s,
176
- R as u,
177
- M as w
181
+ b as H,
182
+ A as b,
183
+ k as g,
184
+ R as i,
185
+ L as n,
186
+ x as p,
187
+ M as s,
188
+ _ as u,
189
+ V as w
178
190
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-micro-router",
3
- "version": "1.0.34",
3
+ "version": "1.0.37",
4
4
  "type": "module",
5
5
  "description": "Mobile-app-style navigation for Vue 3 — animated page stacks, modal dialogs, HUD controls. No URL routing.",
6
6
  "author": {