vue-micro-router 1.0.1

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.
@@ -0,0 +1,104 @@
1
+ import { AsyncComponentLoader } from 'vue';
2
+ import { Component } from 'vue';
3
+ import { Ref } from 'vue';
4
+
5
+ /**
6
+ * Abstract audio adapter interface — decouples audio playback from a specific library.
7
+ *
8
+ * Ship a HowlerAdapter as default. Users can provide a custom adapter
9
+ * (Web Audio API, Tone.js, etc.) via AudioManagerConfig.adapter.
10
+ */
11
+ export declare interface AudioAdapter {
12
+ /** Play a sound from the given source URL */
13
+ play(src: string, options: {
14
+ loop?: boolean;
15
+ volume?: number;
16
+ }): Promise<void>;
17
+ /** Stop and unload the current sound */
18
+ stop(): void;
19
+ /** Pause playback (preserves position) */
20
+ pause(): void;
21
+ /** Resume from paused state */
22
+ resume(): void;
23
+ /** Crossfade volume from→to over duration ms */
24
+ fade(from: number, to: number, duration: number): void;
25
+ /** Whether audio is currently playing */
26
+ isPlaying(): boolean;
27
+ /** Current load state */
28
+ state(): 'unloaded' | 'loading' | 'loaded';
29
+ /** Clean up all resources */
30
+ cleanup(): void;
31
+ }
32
+
33
+ export declare interface AudioManagerConfig {
34
+ /** Volume ref (0-100). Defaults to 100. */
35
+ volumeRef?: Ref<number>;
36
+ /** Resolve a sound name to a full URL. Defaults to identity (name returned as-is). */
37
+ urlResolver?: (name: string) => string;
38
+ /** Custom audio adapter. Defaults to HowlerAdapter (requires howler peer dep). */
39
+ adapter?: AudioAdapter;
40
+ }
41
+
42
+ export declare interface AudioManagerState {
43
+ playSound: (soundSrc: string, loop?: boolean) => Promise<void>;
44
+ stopSound: () => void;
45
+ updateBackgroundMusic: (route: string, routes?: Map<string, MicroRoute>) => Promise<void>;
46
+ handleVisibilityChange: () => void;
47
+ cleanup: () => void;
48
+ }
49
+
50
+ export declare class HowlerAdapter implements AudioAdapter {
51
+ private sound;
52
+ private howlCtorPromise;
53
+ /** Lazy-load Howler.js — only imported when first sound is played */
54
+ private getHowlCtor;
55
+ play(src: string, options?: {
56
+ loop?: boolean;
57
+ volume?: number;
58
+ }): Promise<void>;
59
+ stop(): void;
60
+ pause(): void;
61
+ resume(): void;
62
+ fade(from: number, to: number, duration: number): void;
63
+ isPlaying(): boolean;
64
+ state(): 'unloaded' | 'loading' | 'loaded';
65
+ cleanup(): void;
66
+ }
67
+
68
+ declare interface MicroRoute {
69
+ /** Unique segment name, e.g. "home", "settings" — used in path like "home/settings" */
70
+ path: string;
71
+ /** Vue component or async loader (() => import('./MyPage.vue')) */
72
+ component: AsyncComponentLoader | Component;
73
+ /** Props passed to the component via useMicroState */
74
+ attrs?: Record<string, unknown>;
75
+ /** Background music track name — resolved by audio manager's urlResolver */
76
+ bgm?: string;
77
+ /** Preloading strategy: 'eager' (on mount), 'adjacent' (after each nav), false (default) */
78
+ preload?: 'eager' | 'adjacent' | false;
79
+ /** Page transition type: 'slide' (default), 'fade', or 'none' to disable */
80
+ transition?: TransitionType | 'none';
81
+ /** Custom transition duration in ms. Defaults: slide=500ms, fade=300ms */
82
+ transitionDuration?: number;
83
+ /** Guard called before navigating TO this route. Return false to cancel. */
84
+ beforeEnter?: NavigationGuard;
85
+ /** Guard called before navigating AWAY from this route. Return false to cancel. */
86
+ beforeLeave?: NavigationGuard;
87
+ /** Internal: cache key for transition identity */
88
+ key?: string;
89
+ /** Internal: incremented to force full component remount */
90
+ componentKey?: number;
91
+ }
92
+
93
+ /**
94
+ * Guard called before navigation. Return false (or resolve to false) to cancel.
95
+ * @param to - target path
96
+ * @param from - current path
97
+ */
98
+ declare type NavigationGuard = (to: string, from: string) => boolean | Promise<boolean>;
99
+
100
+ declare type TransitionType = 'fade' | 'slide' | 'scale';
101
+
102
+ export declare function useAudioManager(config?: AudioManagerConfig): AudioManagerState;
103
+
104
+ export { }
package/dist/audio.mjs ADDED
@@ -0,0 +1,100 @@
1
+ import { ref as v, computed as C, watch as P } from "vue";
2
+ import { d as S } from "./timer-manager.mjs";
3
+ class b {
4
+ constructor() {
5
+ this.sound = null, this.howlCtorPromise = null;
6
+ }
7
+ /** Lazy-load Howler.js — only imported when first sound is played */
8
+ async getHowlCtor() {
9
+ return this.howlCtorPromise || (this.howlCtorPromise = import("howler").then((s) => s.Howl)), this.howlCtorPromise;
10
+ }
11
+ async play(s, u = {}) {
12
+ this.stop();
13
+ const t = await this.getHowlCtor();
14
+ this.sound = new t({
15
+ src: [s],
16
+ autoplay: !0,
17
+ loop: u.loop ?? !1,
18
+ volume: 0
19
+ }), this.sound.fade(0, u.volume ?? 1, 200);
20
+ }
21
+ stop() {
22
+ try {
23
+ this.sound && (this.sound.stop(), this.sound.off(), this.sound.unload(), this.sound = null);
24
+ } catch {
25
+ this.sound = null;
26
+ }
27
+ }
28
+ pause() {
29
+ var s;
30
+ (s = this.sound) != null && s.playing() && this.sound.pause();
31
+ }
32
+ resume() {
33
+ this.sound && this.state() === "loaded" && this.sound.play();
34
+ }
35
+ fade(s, u, t) {
36
+ var a;
37
+ (a = this.sound) != null && a.playing() && this.sound.fade(s, u, t);
38
+ }
39
+ isPlaying() {
40
+ var s;
41
+ return ((s = this.sound) == null ? void 0 : s.playing()) ?? !1;
42
+ }
43
+ state() {
44
+ return this.sound ? this.sound.state() : "unloaded";
45
+ }
46
+ cleanup() {
47
+ this.stop();
48
+ }
49
+ }
50
+ function g(o) {
51
+ let s = !1, u = "default";
52
+ const t = (o == null ? void 0 : o.adapter) ?? new b(), a = v("default"), c = (o == null ? void 0 : o.urlResolver) ?? ((e) => e), d = C(() => {
53
+ var e;
54
+ return (((e = o == null ? void 0 : o.volumeRef) == null ? void 0 : e.value) ?? 100) / 100;
55
+ });
56
+ async function h(e, n = !1) {
57
+ try {
58
+ if (t.isPlaying() && a.value === e) return;
59
+ u = a.value, a.value = e, t.stop(), await S(50), await t.play(c(e), { loop: n, volume: d.value });
60
+ } catch (l) {
61
+ console.error("Sound playback failed:", l), t.stop();
62
+ }
63
+ }
64
+ function f() {
65
+ t.stop();
66
+ }
67
+ async function y(e, n) {
68
+ if (n)
69
+ try {
70
+ const l = e.split("/").pop() || "home", r = n.get(l), i = (r == null ? void 0 : r.bgm) || a.value, p = u;
71
+ p && i && p !== i && await h(i, !0);
72
+ } catch (l) {
73
+ console.error("Error updating background music:", l);
74
+ }
75
+ }
76
+ function m() {
77
+ if (!(typeof document > "u"))
78
+ try {
79
+ document.hidden ? t.isPlaying() && (t.pause(), s = !0) : s && t.state() === "loaded" && (t.resume(), s = !1);
80
+ } catch {
81
+ t.stop();
82
+ }
83
+ }
84
+ function w() {
85
+ t.cleanup();
86
+ }
87
+ return P(d, (e, n) => {
88
+ t.isPlaying() && t.fade(n ?? 0, e, 300);
89
+ }), {
90
+ playSound: h,
91
+ stopSound: f,
92
+ updateBackgroundMusic: y,
93
+ handleVisibilityChange: m,
94
+ cleanup: w
95
+ };
96
+ }
97
+ export {
98
+ b as HowlerAdapter,
99
+ g as useAudioManager
100
+ };