@jswork/howler-audio-manager 0.0.0-stage → 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,612 @@
1
+ "use strict";
2
+ function _array_like_to_array(arr, len) {
3
+ if (len == null || len > arr.length) len = arr.length;
4
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
5
+ return arr2;
6
+ }
7
+ function _array_without_holes(arr) {
8
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
9
+ }
10
+ function _class_call_check(instance, Constructor) {
11
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
12
+ }
13
+ function _defineProperties(target, props) {
14
+ for(var i = 0; i < props.length; i++){
15
+ var descriptor = props[i];
16
+ descriptor.enumerable = descriptor.enumerable || false;
17
+ descriptor.configurable = true;
18
+ if ("value" in descriptor) descriptor.writable = true;
19
+ Object.defineProperty(target, descriptor.key, descriptor);
20
+ }
21
+ }
22
+ function _create_class(Constructor, protoProps, staticProps) {
23
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
24
+ if (staticProps) _defineProperties(Constructor, staticProps);
25
+ return Constructor;
26
+ }
27
+ function _iterable_to_array(iter) {
28
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
29
+ return Array.from(iter);
30
+ }
31
+ }
32
+ function _non_iterable_spread() {
33
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
34
+ }
35
+ function _to_consumable_array(arr) {
36
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
37
+ }
38
+ function _unsupported_iterable_to_array(o, minLen) {
39
+ if (!o) return;
40
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
41
+ var n = Object.prototype.toString.call(o).slice(8, -1);
42
+ if (n === "Object" && o.constructor) n = o.constructor.name;
43
+ if (n === "Map" || n === "Set") return Array.from(n);
44
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
45
+ }
46
+ Object.defineProperty(exports, "__esModule", {
47
+ value: true
48
+ });
49
+ function _nullishCoalesce(lhs, rhsFn) {
50
+ if (lhs != null) {
51
+ return lhs;
52
+ } else {
53
+ return rhsFn();
54
+ }
55
+ }
56
+ function _optionalChain(ops) {
57
+ var lastAccessLHS = undefined;
58
+ var value = ops[0];
59
+ var i = 1;
60
+ while(i < ops.length){
61
+ var op = ops[i];
62
+ var fn = ops[i + 1];
63
+ i += 2;
64
+ if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
65
+ return undefined;
66
+ }
67
+ if (op === 'access' || op === 'optionalAccess') {
68
+ lastAccessLHS = value;
69
+ value = fn(value);
70
+ } else if (op === 'call' || op === 'optionalCall') {
71
+ var _value;
72
+ value = fn(function() {
73
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
74
+ args[_key] = arguments[_key];
75
+ }
76
+ return (_value = value).call.apply(_value, [
77
+ lastAccessLHS
78
+ ].concat(_to_consumable_array(args)));
79
+ });
80
+ lastAccessLHS = undefined;
81
+ }
82
+ }
83
+ return value;
84
+ } /*!
85
+ * name: @jswork/howler-audio-manager
86
+ * description: Howler.js audio manager, enum-driven sounds for H5.
87
+ * homepage: https://js.work
88
+ * version: 1.0.1
89
+ * date: 2026-10-20 18:54:06
90
+ * license: MIT
91
+ */
92
+ // src/manager.ts
93
+ var _howler = require('howler');
94
+ var AudioManager = /*#__PURE__*/ function() {
95
+ function AudioManager(options, inject) {
96
+ _class_call_check(this, AudioManager);
97
+ this.effectCache = /* @__PURE__ */ new Map();
98
+ this.urlAudioCache = /* @__PURE__ */ new Map();
99
+ this.preloadPromises = /* @__PURE__ */ new Map();
100
+ this.activeUrlHowl = null;
101
+ this.globalVolume = 1;
102
+ this.listeners = /* @__PURE__ */ new Map();
103
+ this.HowlConstructor = _nullishCoalesce(_optionalChain([
104
+ inject,
105
+ 'optionalAccess',
106
+ function(_) {
107
+ return _.HowlClass;
108
+ }
109
+ ]), function() {
110
+ return _howler.Howl;
111
+ });
112
+ this.HowlerInstance = _nullishCoalesce(_optionalChain([
113
+ inject,
114
+ 'optionalAccess',
115
+ function(_2) {
116
+ return _2.HowlerObj;
117
+ }
118
+ ]), function() {
119
+ return _howler.Howler;
120
+ });
121
+ if (typeof _optionalChain([
122
+ options,
123
+ 'optionalAccess',
124
+ function(_3) {
125
+ return _3.defaultVolume;
126
+ }
127
+ ]) === "number") {
128
+ this.setGlobalVolume(options.defaultVolume);
129
+ }
130
+ }
131
+ _create_class(AudioManager, [
132
+ {
133
+ key: "hasEffect",
134
+ value: function hasEffect(key) {
135
+ return this.effectCache.has(key);
136
+ }
137
+ },
138
+ {
139
+ key: "loadEffect",
140
+ value: function loadEffect(key, url) {
141
+ var _this = this;
142
+ if (this.effectCache.has(key)) {
143
+ this.effectCache.get(key).unload();
144
+ }
145
+ var howl = new this.HowlConstructor({
146
+ src: [
147
+ url
148
+ ],
149
+ preload: true
150
+ });
151
+ howl.on("load", function() {
152
+ _this.emit("load", {
153
+ type: "effect",
154
+ key: key,
155
+ url: url
156
+ });
157
+ });
158
+ howl.on("loaderror", function(_id, error) {
159
+ _this.emit("error", {
160
+ type: "effect",
161
+ key: key,
162
+ url: url,
163
+ error: error
164
+ });
165
+ });
166
+ this.effectCache.set(key, howl);
167
+ }
168
+ },
169
+ {
170
+ key: "loadEffects",
171
+ value: function loadEffects(map) {
172
+ var _this = this;
173
+ Object.keys(map).forEach(function(key) {
174
+ var typedKey = isNaN(Number(key)) ? key : Number(key);
175
+ _this.loadEffect(typedKey, map[key]);
176
+ });
177
+ }
178
+ },
179
+ {
180
+ key: "playEffect",
181
+ value: function playEffect(key, options) {
182
+ var _this = this;
183
+ var howl = this.effectCache.get(key);
184
+ if (!howl) {
185
+ console.warn("[AudioManager] Effect not found for key: ".concat(String(key), "."));
186
+ return void 0;
187
+ }
188
+ if (howl.playing()) {
189
+ howl.stop();
190
+ }
191
+ if (typeof _optionalChain([
192
+ options,
193
+ 'optionalAccess',
194
+ function(_4) {
195
+ return _4.volume;
196
+ }
197
+ ]) === "number") {
198
+ howl.volume(options.volume);
199
+ }
200
+ howl.off("play");
201
+ howl.off("end");
202
+ howl.off("stop");
203
+ howl.off("playerror");
204
+ howl.once("play", function(soundId) {
205
+ _optionalChain([
206
+ options,
207
+ 'optionalAccess',
208
+ function(_5) {
209
+ return _5.onStart;
210
+ },
211
+ 'optionalCall',
212
+ function(_6) {
213
+ return _6(soundId);
214
+ }
215
+ ]);
216
+ _this.emit("play", {
217
+ type: "effect",
218
+ key: key,
219
+ soundId: soundId
220
+ });
221
+ });
222
+ howl.once("end", function(soundId) {
223
+ if (typeof _optionalChain([
224
+ options,
225
+ 'optionalAccess',
226
+ function(_7) {
227
+ return _7.volume;
228
+ }
229
+ ]) === "number") {
230
+ howl.volume(1);
231
+ }
232
+ _optionalChain([
233
+ options,
234
+ 'optionalAccess',
235
+ function(_8) {
236
+ return _8.onEnd;
237
+ },
238
+ 'optionalCall',
239
+ function(_9) {
240
+ return _9(soundId);
241
+ }
242
+ ]);
243
+ _this.emit("end", {
244
+ type: "effect",
245
+ key: key,
246
+ soundId: soundId
247
+ });
248
+ });
249
+ howl.once("stop", function(soundId) {
250
+ if (typeof _optionalChain([
251
+ options,
252
+ 'optionalAccess',
253
+ function(_10) {
254
+ return _10.volume;
255
+ }
256
+ ]) === "number") {
257
+ howl.volume(1);
258
+ }
259
+ _optionalChain([
260
+ options,
261
+ 'optionalAccess',
262
+ function(_11) {
263
+ return _11.onStop;
264
+ },
265
+ 'optionalCall',
266
+ function(_12) {
267
+ return _12(soundId);
268
+ }
269
+ ]);
270
+ _this.emit("stop", {
271
+ type: "effect",
272
+ key: key,
273
+ soundId: soundId
274
+ });
275
+ });
276
+ howl.once("playerror", function(soundId, error) {
277
+ _optionalChain([
278
+ options,
279
+ 'optionalAccess',
280
+ function(_13) {
281
+ return _13.onError;
282
+ },
283
+ 'optionalCall',
284
+ function(_14) {
285
+ return _14(soundId, error);
286
+ }
287
+ ]);
288
+ _this.emit("error", {
289
+ type: "effect",
290
+ key: key,
291
+ soundId: soundId,
292
+ error: error
293
+ });
294
+ });
295
+ return howl.play();
296
+ }
297
+ },
298
+ {
299
+ key: "stopEffect",
300
+ value: function stopEffect(key) {
301
+ var howl = this.effectCache.get(key);
302
+ if (howl) {
303
+ howl.stop();
304
+ }
305
+ }
306
+ },
307
+ {
308
+ key: "removeEffect",
309
+ value: function removeEffect(key) {
310
+ var howl = this.effectCache.get(key);
311
+ if (howl) {
312
+ howl.unload();
313
+ this.effectCache.delete(key);
314
+ }
315
+ }
316
+ },
317
+ {
318
+ key: "preloadUrl",
319
+ value: function preloadUrl(url) {
320
+ var _this = this;
321
+ var existing = this.urlAudioCache.get(url);
322
+ if (existing && existing.state() === "loaded") {
323
+ return Promise.resolve();
324
+ }
325
+ var pending = this.preloadPromises.get(url);
326
+ if (pending) {
327
+ return pending;
328
+ }
329
+ var howl = existing && existing.state() !== "unloaded" ? existing : this.createUrlHowl(url);
330
+ var promise = new Promise(function(resolve, reject) {
331
+ howl.once("load", function() {
332
+ resolve();
333
+ });
334
+ howl.once("loaderror", function(_id, error) {
335
+ _this.urlAudioCache.delete(url);
336
+ reject(error);
337
+ });
338
+ });
339
+ this.preloadPromises.set(url, promise);
340
+ var settle = function settle() {
341
+ if (_this.preloadPromises.get(url) === promise) {
342
+ _this.preloadPromises.delete(url);
343
+ }
344
+ };
345
+ promise.then(settle, settle);
346
+ return promise;
347
+ }
348
+ },
349
+ {
350
+ key: "preloadUrls",
351
+ value: function preloadUrls(urls) {
352
+ var _this = this;
353
+ return Promise.all(urls.map(function(url) {
354
+ return _this.preloadUrl(url);
355
+ }));
356
+ }
357
+ },
358
+ {
359
+ key: "createUrlHowl",
360
+ value: function createUrlHowl(url) {
361
+ var _this = this;
362
+ var howl = new this.HowlConstructor({
363
+ src: [
364
+ url
365
+ ],
366
+ preload: true
367
+ });
368
+ howl.on("load", function() {
369
+ _this.emit("load", {
370
+ type: "url",
371
+ url: url
372
+ });
373
+ });
374
+ howl.on("loaderror", function(_id, error) {
375
+ _this.urlAudioCache.delete(url);
376
+ _this.emit("error", {
377
+ type: "url",
378
+ url: url,
379
+ error: error
380
+ });
381
+ });
382
+ this.urlAudioCache.set(url, howl);
383
+ return howl;
384
+ }
385
+ },
386
+ {
387
+ key: "playUrl",
388
+ value: function playUrl(url, options) {
389
+ var _this = this;
390
+ var howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);
391
+ var isSingleton = _optionalChain([
392
+ options,
393
+ 'optionalAccess',
394
+ function(_15) {
395
+ return _15.singleton;
396
+ }
397
+ ]) !== false;
398
+ if (isSingleton && this.activeUrlHowl && this.activeUrlHowl !== howl && this.activeUrlHowl.playing()) {
399
+ this.activeUrlHowl.stop();
400
+ }
401
+ if (howl.playing()) {
402
+ howl.stop();
403
+ }
404
+ if (_optionalChain([
405
+ options,
406
+ 'optionalAccess',
407
+ function(_16) {
408
+ return _16.loop;
409
+ }
410
+ ]) !== void 0) {
411
+ howl.loop(options.loop);
412
+ }
413
+ if (typeof _optionalChain([
414
+ options,
415
+ 'optionalAccess',
416
+ function(_17) {
417
+ return _17.volume;
418
+ }
419
+ ]) === "number") {
420
+ howl.volume(options.volume);
421
+ }
422
+ if (isSingleton) {
423
+ this.activeUrlHowl = howl;
424
+ }
425
+ howl.off("play");
426
+ howl.off("end");
427
+ howl.off("stop");
428
+ howl.off("playerror");
429
+ howl.once("play", function(soundId) {
430
+ _optionalChain([
431
+ options,
432
+ 'optionalAccess',
433
+ function(_18) {
434
+ return _18.onStart;
435
+ },
436
+ 'optionalCall',
437
+ function(_19) {
438
+ return _19(soundId);
439
+ }
440
+ ]);
441
+ _this.emit("play", {
442
+ type: "url",
443
+ url: url,
444
+ soundId: soundId
445
+ });
446
+ });
447
+ howl.once("end", function(soundId) {
448
+ if (typeof _optionalChain([
449
+ options,
450
+ 'optionalAccess',
451
+ function(_20) {
452
+ return _20.volume;
453
+ }
454
+ ]) === "number") {
455
+ howl.volume(1);
456
+ }
457
+ _optionalChain([
458
+ options,
459
+ 'optionalAccess',
460
+ function(_21) {
461
+ return _21.onEnd;
462
+ },
463
+ 'optionalCall',
464
+ function(_22) {
465
+ return _22(soundId);
466
+ }
467
+ ]);
468
+ _this.emit("end", {
469
+ type: "url",
470
+ url: url,
471
+ soundId: soundId
472
+ });
473
+ if (_this.activeUrlHowl === howl && !howl.loop()) {
474
+ _this.activeUrlHowl = null;
475
+ }
476
+ });
477
+ howl.once("stop", function(soundId) {
478
+ if (typeof _optionalChain([
479
+ options,
480
+ 'optionalAccess',
481
+ function(_23) {
482
+ return _23.volume;
483
+ }
484
+ ]) === "number") {
485
+ howl.volume(1);
486
+ }
487
+ _optionalChain([
488
+ options,
489
+ 'optionalAccess',
490
+ function(_24) {
491
+ return _24.onStop;
492
+ },
493
+ 'optionalCall',
494
+ function(_25) {
495
+ return _25(soundId);
496
+ }
497
+ ]);
498
+ _this.emit("stop", {
499
+ type: "url",
500
+ url: url,
501
+ soundId: soundId
502
+ });
503
+ if (_this.activeUrlHowl === howl) {
504
+ _this.activeUrlHowl = null;
505
+ }
506
+ });
507
+ howl.once("playerror", function(soundId, error) {
508
+ _optionalChain([
509
+ options,
510
+ 'optionalAccess',
511
+ function(_26) {
512
+ return _26.onError;
513
+ },
514
+ 'optionalCall',
515
+ function(_27) {
516
+ return _27(soundId, error);
517
+ }
518
+ ]);
519
+ _this.emit("error", {
520
+ type: "url",
521
+ url: url,
522
+ soundId: soundId,
523
+ error: error
524
+ });
525
+ if (_this.activeUrlHowl === howl) {
526
+ _this.activeUrlHowl = null;
527
+ }
528
+ });
529
+ return howl.play();
530
+ }
531
+ },
532
+ {
533
+ key: "stopUrl",
534
+ value: function stopUrl(url) {
535
+ var howl = this.urlAudioCache.get(url);
536
+ if (howl) {
537
+ howl.stop();
538
+ }
539
+ }
540
+ },
541
+ {
542
+ key: "on",
543
+ value: function on(event, handler) {
544
+ var set = _nullishCoalesce(this.listeners.get(event), function() {
545
+ return /* @__PURE__ */ new Set();
546
+ });
547
+ this.listeners.set(event, set);
548
+ set.add(handler);
549
+ return {
550
+ destroy: function destroy() {
551
+ set.delete(handler);
552
+ }
553
+ };
554
+ }
555
+ },
556
+ {
557
+ key: "emit",
558
+ value: function emit(event, payload) {
559
+ var set = this.listeners.get(event);
560
+ if (set) {
561
+ set.forEach(function(handler) {
562
+ try {
563
+ handler(payload);
564
+ } catch (err) {
565
+ console.error("[AudioManager] Error in event listener for ".concat(event, ":"), err);
566
+ }
567
+ });
568
+ }
569
+ }
570
+ },
571
+ {
572
+ key: "setGlobalVolume",
573
+ value: function setGlobalVolume(volume) {
574
+ this.globalVolume = volume;
575
+ this.HowlerInstance.volume(volume);
576
+ }
577
+ },
578
+ {
579
+ key: "mute",
580
+ value: function mute(muted) {
581
+ this.HowlerInstance.mute(muted);
582
+ }
583
+ },
584
+ {
585
+ key: "stopAll",
586
+ value: function stopAll() {
587
+ this.HowlerInstance.stop();
588
+ this.activeUrlHowl = null;
589
+ }
590
+ },
591
+ {
592
+ key: "destroy",
593
+ value: function destroy() {
594
+ this.effectCache.forEach(function(howl) {
595
+ return howl.unload();
596
+ });
597
+ this.urlAudioCache.forEach(function(howl) {
598
+ return howl.unload();
599
+ });
600
+ this.effectCache.clear();
601
+ this.urlAudioCache.clear();
602
+ this.preloadPromises.clear();
603
+ this.listeners.clear();
604
+ this.activeUrlHowl = null;
605
+ }
606
+ }
607
+ ]);
608
+ return AudioManager;
609
+ }();
610
+ exports.AudioManager = AudioManager;
611
+ exports.default = AudioManager;
612
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/afei/github/howler-audio-manager/dist/index.cjs.js","../src/manager.ts"],"names":["Object","defineProperty","exports","value","_nullishCoalesce","lhs","rhsFn","_optionalChain","ops","lastAccessLHS","undefined","i","length","op","fn","args","call","_howler","require","AudioManager","options","inject","effectCache","Map","urlAudioCache","preloadPromises","activeUrlHowl","globalVolume","listeners","HowlConstructor","_","HowlClass","Howl","HowlerInstance","_2","HowlerObj","Howler","_3","defaultVolume","setGlobalVolume","hasEffect","key","has","loadEffect","url","get","unload","howl","src","preload","on","emit","type","_id","error","set","loadEffects","map","keys","forEach","typedKey","isNaN","Number","playEffect","console","warn","String","playing","stop","_4","volume","off","once","soundId","_5","onStart","_6","_7","_8","onEnd","_9","_10","_11","onStop","_12","_13","onError","_14","play","stopEffect","removeEffect","delete","preloadUrl","existing","state","Promise","resolve","pending","createUrlHowl","promise","reject","settle","then","preloadUrls","urls","all","playUrl","isSingleton","_15","singleton","_16","loop","_17","_18","_19","_20","_21","_22","_23","_24","_25","_26","_27","stopUrl","event","handler","Set","add","destroy","payload","err","mute","muted","stopAll","clear","default"],"mappings":"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","sourcesContent":["\"use strict\";Object.defineProperty(exports, \"__esModule\", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }/*!\n * name: @jswork/howler-audio-manager\n * description: Howler.js audio manager, enum-driven sounds for H5.\n * homepage: https://js.work\n * version: 1.0.1\n * date: 2026-10-20 18:54:06\n * license: MIT\n */\n\n\n// src/manager.ts\nvar _howler = require('howler');\nvar AudioManager = class {\n constructor(options, inject) {\n this.effectCache = /* @__PURE__ */ new Map();\n this.urlAudioCache = /* @__PURE__ */ new Map();\n this.preloadPromises = /* @__PURE__ */ new Map();\n this.activeUrlHowl = null;\n this.globalVolume = 1;\n this.listeners = /* @__PURE__ */ new Map();\n this.HowlConstructor = _nullishCoalesce(_optionalChain([inject, 'optionalAccess', _ => _.HowlClass]), () => ( _howler.Howl));\n this.HowlerInstance = _nullishCoalesce(_optionalChain([inject, 'optionalAccess', _2 => _2.HowlerObj]), () => ( _howler.Howler));\n if (typeof _optionalChain([options, 'optionalAccess', _3 => _3.defaultVolume]) === \"number\") {\n this.setGlobalVolume(options.defaultVolume);\n }\n }\n hasEffect(key) {\n return this.effectCache.has(key);\n }\n loadEffect(key, url) {\n if (this.effectCache.has(key)) {\n this.effectCache.get(key).unload();\n }\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on(\"load\", () => {\n this.emit(\"load\", { type: \"effect\", key, url });\n });\n howl.on(\"loaderror\", (_id, error) => {\n this.emit(\"error\", { type: \"effect\", key, url, error });\n });\n this.effectCache.set(key, howl);\n }\n loadEffects(map) {\n Object.keys(map).forEach((key) => {\n const typedKey = isNaN(Number(key)) ? key : Number(key);\n this.loadEffect(typedKey, map[key]);\n });\n }\n playEffect(key, options) {\n const howl = this.effectCache.get(key);\n if (!howl) {\n console.warn(`[AudioManager] Effect not found for key: ${String(key)}.`);\n return void 0;\n }\n if (howl.playing()) {\n howl.stop();\n }\n if (typeof _optionalChain([options, 'optionalAccess', _4 => _4.volume]) === \"number\") {\n howl.volume(options.volume);\n }\n howl.off(\"play\");\n howl.off(\"end\");\n howl.off(\"stop\");\n howl.off(\"playerror\");\n howl.once(\"play\", (soundId) => {\n _optionalChain([options, 'optionalAccess', _5 => _5.onStart, 'optionalCall', _6 => _6(soundId)]);\n this.emit(\"play\", { type: \"effect\", key, soundId });\n });\n howl.once(\"end\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _7 => _7.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _8 => _8.onEnd, 'optionalCall', _9 => _9(soundId)]);\n this.emit(\"end\", { type: \"effect\", key, soundId });\n });\n howl.once(\"stop\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _10 => _10.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _11 => _11.onStop, 'optionalCall', _12 => _12(soundId)]);\n this.emit(\"stop\", { type: \"effect\", key, soundId });\n });\n howl.once(\"playerror\", (soundId, error) => {\n _optionalChain([options, 'optionalAccess', _13 => _13.onError, 'optionalCall', _14 => _14(soundId, error)]);\n this.emit(\"error\", { type: \"effect\", key, soundId, error });\n });\n return howl.play();\n }\n stopEffect(key) {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.stop();\n }\n }\n removeEffect(key) {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.unload();\n this.effectCache.delete(key);\n }\n }\n preloadUrl(url) {\n const existing = this.urlAudioCache.get(url);\n if (existing && existing.state() === \"loaded\") {\n return Promise.resolve();\n }\n const pending = this.preloadPromises.get(url);\n if (pending) {\n return pending;\n }\n const howl = existing && existing.state() !== \"unloaded\" ? existing : this.createUrlHowl(url);\n const promise = new Promise((resolve, reject) => {\n howl.once(\"load\", () => {\n resolve();\n });\n howl.once(\"loaderror\", (_id, error) => {\n this.urlAudioCache.delete(url);\n reject(error);\n });\n });\n this.preloadPromises.set(url, promise);\n const settle = () => {\n if (this.preloadPromises.get(url) === promise) {\n this.preloadPromises.delete(url);\n }\n };\n promise.then(settle, settle);\n return promise;\n }\n preloadUrls(urls) {\n return Promise.all(urls.map((url) => this.preloadUrl(url)));\n }\n createUrlHowl(url) {\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on(\"load\", () => {\n this.emit(\"load\", { type: \"url\", url });\n });\n howl.on(\"loaderror\", (_id, error) => {\n this.urlAudioCache.delete(url);\n this.emit(\"error\", { type: \"url\", url, error });\n });\n this.urlAudioCache.set(url, howl);\n return howl;\n }\n playUrl(url, options) {\n const howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);\n const isSingleton = _optionalChain([options, 'optionalAccess', _15 => _15.singleton]) !== false;\n if (isSingleton && this.activeUrlHowl && this.activeUrlHowl !== howl && this.activeUrlHowl.playing()) {\n this.activeUrlHowl.stop();\n }\n if (howl.playing()) {\n howl.stop();\n }\n if (_optionalChain([options, 'optionalAccess', _16 => _16.loop]) !== void 0) {\n howl.loop(options.loop);\n }\n if (typeof _optionalChain([options, 'optionalAccess', _17 => _17.volume]) === \"number\") {\n howl.volume(options.volume);\n }\n if (isSingleton) {\n this.activeUrlHowl = howl;\n }\n howl.off(\"play\");\n howl.off(\"end\");\n howl.off(\"stop\");\n howl.off(\"playerror\");\n howl.once(\"play\", (soundId) => {\n _optionalChain([options, 'optionalAccess', _18 => _18.onStart, 'optionalCall', _19 => _19(soundId)]);\n this.emit(\"play\", { type: \"url\", url, soundId });\n });\n howl.once(\"end\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _20 => _20.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _21 => _21.onEnd, 'optionalCall', _22 => _22(soundId)]);\n this.emit(\"end\", { type: \"url\", url, soundId });\n if (this.activeUrlHowl === howl && !howl.loop()) {\n this.activeUrlHowl = null;\n }\n });\n howl.once(\"stop\", (soundId) => {\n if (typeof _optionalChain([options, 'optionalAccess', _23 => _23.volume]) === \"number\") {\n howl.volume(1);\n }\n _optionalChain([options, 'optionalAccess', _24 => _24.onStop, 'optionalCall', _25 => _25(soundId)]);\n this.emit(\"stop\", { type: \"url\", url, soundId });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n howl.once(\"playerror\", (soundId, error) => {\n _optionalChain([options, 'optionalAccess', _26 => _26.onError, 'optionalCall', _27 => _27(soundId, error)]);\n this.emit(\"error\", { type: \"url\", url, soundId, error });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n return howl.play();\n }\n stopUrl(url) {\n const howl = this.urlAudioCache.get(url);\n if (howl) {\n howl.stop();\n }\n }\n on(event, handler) {\n const set = _nullishCoalesce(this.listeners.get(event), () => ( /* @__PURE__ */ new Set()));\n this.listeners.set(event, set);\n set.add(handler);\n return {\n destroy: () => {\n set.delete(handler);\n }\n };\n }\n emit(event, payload) {\n const set = this.listeners.get(event);\n if (set) {\n set.forEach((handler) => {\n try {\n handler(payload);\n } catch (err) {\n console.error(`[AudioManager] Error in event listener for ${event}:`, err);\n }\n });\n }\n }\n setGlobalVolume(volume) {\n this.globalVolume = volume;\n this.HowlerInstance.volume(volume);\n }\n mute(muted) {\n this.HowlerInstance.mute(muted);\n }\n stopAll() {\n this.HowlerInstance.stop();\n this.activeUrlHowl = null;\n }\n destroy() {\n this.effectCache.forEach((howl) => howl.unload());\n this.urlAudioCache.forEach((howl) => howl.unload());\n this.effectCache.clear();\n this.urlAudioCache.clear();\n this.preloadPromises.clear();\n this.listeners.clear();\n this.activeUrlHowl = null;\n }\n};\n\n\n\nexports.AudioManager = AudioManager; exports.default = AudioManager;\n","import { Howl, Howler } from 'howler';\nimport type {\n AudioManagerOptions,\n PlayOptions,\n PlayUrlOptions,\n AudioEventType,\n AudioEventPayload,\n EventSubscription,\n SoundResourceMap\n} from './types';\n\nexport class AudioManager<K extends string | number = string> {\n private effectCache = new Map<K, Howl>();\n private urlAudioCache = new Map<string, Howl>();\n private preloadPromises = new Map<string, Promise<void>>();\n private activeUrlHowl: Howl | null = null;\n private globalVolume = 1.0;\n private listeners = new Map<AudioEventType, Set<(payload: AudioEventPayload<K>) => void>>();\n\n private HowlConstructor: typeof Howl;\n private HowlerInstance: typeof Howler;\n\n constructor(\n options?: AudioManagerOptions,\n inject?: { HowlClass?: typeof Howl; HowlerObj?: typeof Howler }\n ) {\n this.HowlConstructor = inject?.HowlClass ?? Howl;\n this.HowlerInstance = inject?.HowlerObj ?? Howler;\n if (typeof options?.defaultVolume === 'number') {\n this.setGlobalVolume(options.defaultVolume);\n }\n }\n\n hasEffect(key: K): boolean {\n return this.effectCache.has(key);\n }\n\n loadEffect(key: K, url: string): void {\n if (this.effectCache.has(key)) {\n this.effectCache.get(key)!.unload();\n }\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on('load', () => {\n this.emit('load', { type: 'effect', key, url });\n });\n howl.on('loaderror', (_id: number, error: unknown) => {\n this.emit('error', { type: 'effect', key, url, error });\n });\n this.effectCache.set(key, howl);\n }\n\n loadEffects(map: SoundResourceMap<K>): void {\n Object.keys(map).forEach((key) => {\n const typedKey = (isNaN(Number(key)) ? key : Number(key)) as K;\n this.loadEffect(typedKey, map[key as any]);\n });\n }\n\n playEffect(key: K, options?: PlayOptions): number | undefined {\n const howl = this.effectCache.get(key);\n if (!howl) {\n console.warn(`[AudioManager] Effect not found for key: ${String(key)}.`);\n return undefined;\n }\n\n if (howl.playing()) {\n howl.stop();\n }\n\n if (typeof options?.volume === 'number') {\n howl.volume(options.volume);\n }\n\n // Clear handlers from previous plays to avoid stale/duplicate callbacks.\n howl.off('play');\n howl.off('end');\n howl.off('stop');\n howl.off('playerror');\n\n howl.once('play', (soundId: number) => {\n options?.onStart?.(soundId);\n this.emit('play', { type: 'effect', key, soundId });\n });\n\n howl.once('end', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onEnd?.(soundId);\n this.emit('end', { type: 'effect', key, soundId });\n });\n\n howl.once('stop', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onStop?.(soundId);\n this.emit('stop', { type: 'effect', key, soundId });\n });\n\n howl.once('playerror', (soundId: number, error: unknown) => {\n options?.onError?.(soundId, error);\n this.emit('error', { type: 'effect', key, soundId, error });\n });\n\n return howl.play();\n }\n\n stopEffect(key: K): void {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.stop();\n }\n }\n\n removeEffect(key: K): void {\n const howl = this.effectCache.get(key);\n if (howl) {\n howl.unload();\n this.effectCache.delete(key);\n }\n }\n\n preloadUrl(url: string): Promise<void> {\n const existing = this.urlAudioCache.get(url);\n if (existing && existing.state() === 'loaded') {\n return Promise.resolve();\n }\n\n const pending = this.preloadPromises.get(url);\n if (pending) {\n return pending;\n }\n\n // A howl in a terminal failed state (unloaded after error) must be replaced\n // so a fresh instance can retry the load.\n const howl = existing && existing.state() !== 'unloaded' ? existing : this.createUrlHowl(url);\n\n const promise = new Promise<void>((resolve, reject) => {\n howl.once('load', () => {\n resolve();\n });\n\n howl.once('loaderror', (_id: number, error: unknown) => {\n this.urlAudioCache.delete(url);\n reject(error);\n });\n });\n\n this.preloadPromises.set(url, promise);\n const settle = () => {\n if (this.preloadPromises.get(url) === promise) {\n this.preloadPromises.delete(url);\n }\n };\n promise.then(settle, settle);\n\n return promise;\n }\n\n preloadUrls(urls: string[]): Promise<void[]> {\n return Promise.all(urls.map((url) => this.preloadUrl(url)));\n }\n\n private createUrlHowl(url: string): Howl {\n const howl = new this.HowlConstructor({\n src: [url],\n preload: true\n });\n howl.on('load', () => {\n this.emit('load', { type: 'url', url });\n });\n howl.on('loaderror', (_id: number, error: unknown) => {\n this.urlAudioCache.delete(url);\n this.emit('error', { type: 'url', url, error });\n });\n this.urlAudioCache.set(url, howl);\n return howl;\n }\n\n playUrl(url: string, options?: PlayUrlOptions): number {\n const howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);\n\n // Singleton mutex: stop currently active URL audio if singleton !== false\n const isSingleton = options?.singleton !== false;\n if (\n isSingleton &&\n this.activeUrlHowl &&\n this.activeUrlHowl !== howl &&\n this.activeUrlHowl.playing()\n ) {\n this.activeUrlHowl.stop();\n }\n\n // Overlap prevention on the same audio instance\n if (howl.playing()) {\n howl.stop();\n }\n\n if (options?.loop !== undefined) {\n howl.loop(options.loop);\n }\n\n if (typeof options?.volume === 'number') {\n howl.volume(options.volume);\n }\n\n if (isSingleton) {\n this.activeUrlHowl = howl;\n }\n\n // Clear handlers from previous plays to avoid stale/duplicate callbacks.\n howl.off('play');\n howl.off('end');\n howl.off('stop');\n howl.off('playerror');\n\n howl.once('play', (soundId: number) => {\n options?.onStart?.(soundId);\n this.emit('play', { type: 'url', url, soundId });\n });\n\n howl.once('end', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onEnd?.(soundId);\n this.emit('end', { type: 'url', url, soundId });\n if (this.activeUrlHowl === howl && !howl.loop()) {\n this.activeUrlHowl = null;\n }\n });\n\n howl.once('stop', (soundId: number) => {\n if (typeof options?.volume === 'number') {\n howl.volume(1);\n }\n options?.onStop?.(soundId);\n this.emit('stop', { type: 'url', url, soundId });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n\n howl.once('playerror', (soundId: number, error: unknown) => {\n options?.onError?.(soundId, error);\n this.emit('error', { type: 'url', url, soundId, error });\n if (this.activeUrlHowl === howl) {\n this.activeUrlHowl = null;\n }\n });\n\n return howl.play();\n }\n\n stopUrl(url: string): void {\n const howl = this.urlAudioCache.get(url);\n if (howl) {\n howl.stop();\n }\n }\n\n on(event: AudioEventType, handler: (payload: AudioEventPayload<K>) => void): EventSubscription {\n const set = this.listeners.get(event) ?? new Set<(payload: AudioEventPayload<K>) => void>();\n this.listeners.set(event, set);\n set.add(handler);\n return {\n destroy: () => {\n set.delete(handler);\n }\n };\n }\n\n protected emit(event: AudioEventType, payload: AudioEventPayload<K>): void {\n const set = this.listeners.get(event);\n if (set) {\n set.forEach((handler) => {\n try {\n handler(payload);\n } catch (err) {\n console.error(`[AudioManager] Error in event listener for ${event}:`, err);\n }\n });\n }\n }\n\n setGlobalVolume(volume: number): void {\n this.globalVolume = volume;\n this.HowlerInstance.volume(volume);\n }\n\n mute(muted: boolean): void {\n this.HowlerInstance.mute(muted);\n }\n\n stopAll(): void {\n this.HowlerInstance.stop();\n this.activeUrlHowl = null;\n }\n\n destroy(): void {\n this.effectCache.forEach((howl) => howl.unload());\n this.urlAudioCache.forEach((howl) => howl.unload());\n this.effectCache.clear();\n this.urlAudioCache.clear();\n this.preloadPromises.clear();\n this.listeners.clear();\n this.activeUrlHowl = null;\n }\n}\n"]}