@jswork/howler-audio-manager 0.0.0-stage → 1.0.2

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,648 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _class_call_check(instance, Constructor) {
10
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
11
+ }
12
+ function _defineProperties(target, props) {
13
+ for(var i = 0; i < props.length; i++){
14
+ var descriptor = props[i];
15
+ descriptor.enumerable = descriptor.enumerable || false;
16
+ descriptor.configurable = true;
17
+ if ("value" in descriptor) descriptor.writable = true;
18
+ Object.defineProperty(target, descriptor.key, descriptor);
19
+ }
20
+ }
21
+ function _create_class(Constructor, protoProps, staticProps) {
22
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
23
+ if (staticProps) _defineProperties(Constructor, staticProps);
24
+ return Constructor;
25
+ }
26
+ function _iterable_to_array_limit(arr, i) {
27
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
28
+ if (_i == null) return;
29
+ var _arr = [];
30
+ var _n = true;
31
+ var _d = false;
32
+ var _s, _e;
33
+ try {
34
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
35
+ _arr.push(_s.value);
36
+ if (i && _arr.length === i) break;
37
+ }
38
+ } catch (err) {
39
+ _d = true;
40
+ _e = err;
41
+ } finally{
42
+ try {
43
+ if (!_n && _i["return"] != null) _i["return"]();
44
+ } finally{
45
+ if (_d) throw _e;
46
+ }
47
+ }
48
+ return _arr;
49
+ }
50
+ function _non_iterable_rest() {
51
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
52
+ }
53
+ function _sliced_to_array(arr, i) {
54
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
55
+ }
56
+ function _type_of(obj) {
57
+ "@swc/helpers - typeof";
58
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
59
+ }
60
+ function _unsupported_iterable_to_array(o, minLen) {
61
+ if (!o) return;
62
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
63
+ var n = Object.prototype.toString.call(o).slice(8, -1);
64
+ if (n === "Object" && o.constructor) n = o.constructor.name;
65
+ if (n === "Map" || n === "Set") return Array.from(n);
66
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
67
+ }
68
+ /*!
69
+ * name: @jswork/howler-audio-manager
70
+ * description: Howler.js audio manager, enum-driven sounds for H5.
71
+ * homepage: https://js.work
72
+ * version: 1.0.2
73
+ * date: 2026-10-20 20:03:06
74
+ * license: MIT
75
+ */ (function(g, f) {
76
+ if ((typeof exports === "undefined" ? "undefined" : _type_of(exports)) == "object" && (typeof module === "undefined" ? "undefined" : _type_of(module)) < "u") {
77
+ module.exports = f();
78
+ } else if ("function" == typeof define && define.amd) {
79
+ define("urlLiteral", f);
80
+ } else {
81
+ g["urlLiteral"] = f();
82
+ }
83
+ })((typeof globalThis === "undefined" ? "undefined" : _type_of(globalThis)) < "u" ? globalThis : (typeof self === "undefined" ? "undefined" : _type_of(self)) < "u" ? self : this, function() {
84
+ var exports1 = {};
85
+ var __exports = exports1;
86
+ var module1 = {
87
+ exports: exports1
88
+ };
89
+ "use strict";
90
+ var __defProp = Object.defineProperty;
91
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
92
+ var __getOwnPropNames = Object.getOwnPropertyNames;
93
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
94
+ var __export = function __export(target, all) {
95
+ for(var name in all)__defProp(target, name, {
96
+ get: all[name],
97
+ enumerable: true
98
+ });
99
+ };
100
+ var __copyProps = function __copyProps(to, from, except, desc) {
101
+ if (from && (typeof from === "undefined" ? "undefined" : _type_of(from)) === "object" || typeof from === "function") {
102
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
103
+ try {
104
+ var _loop = function() {
105
+ var key = _step.value;
106
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
107
+ get: function get() {
108
+ return from[key];
109
+ },
110
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
111
+ });
112
+ };
113
+ for(var _iterator = __getOwnPropNames(from)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop();
114
+ } catch (err) {
115
+ _didIteratorError = true;
116
+ _iteratorError = err;
117
+ } finally{
118
+ try {
119
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
120
+ _iterator.return();
121
+ }
122
+ } finally{
123
+ if (_didIteratorError) {
124
+ throw _iteratorError;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ return to;
130
+ };
131
+ var __toCommonJS = function __toCommonJS(mod) {
132
+ return __copyProps(__defProp({}, "__esModule", {
133
+ value: true
134
+ }), mod);
135
+ };
136
+ // src/index.ts
137
+ var index_exports = {};
138
+ __export(index_exports, {
139
+ AudioManager: function AudioManager1() {
140
+ return AudioManager;
141
+ },
142
+ AudioManagerProvider: function AudioManagerProvider1() {
143
+ return AudioManagerProvider;
144
+ },
145
+ default: function _default() {
146
+ return AudioManager;
147
+ },
148
+ useAudio: function useAudio1() {
149
+ return useAudio;
150
+ },
151
+ useAudioEvent: function useAudioEvent1() {
152
+ return useAudioEvent;
153
+ },
154
+ useGlobalVolume: function useGlobalVolume1() {
155
+ return useGlobalVolume;
156
+ },
157
+ usePreload: function usePreload1() {
158
+ return usePreload;
159
+ }
160
+ });
161
+ module1.exports = __toCommonJS(index_exports);
162
+ // src/manager.ts
163
+ var import_howler = require("howler");
164
+ var AudioManager = /*#__PURE__*/ function() {
165
+ "use strict";
166
+ function AudioManager(options, inject) {
167
+ _class_call_check(this, AudioManager);
168
+ var _ref, _ref1;
169
+ this.effectCache = /* @__PURE__ */ new Map();
170
+ this.urlAudioCache = /* @__PURE__ */ new Map();
171
+ this.preloadPromises = /* @__PURE__ */ new Map();
172
+ this.activeUrlHowl = null;
173
+ this.globalVolume = 1;
174
+ this.listeners = /* @__PURE__ */ new Map();
175
+ this.HowlConstructor = (_ref = inject === null || inject === void 0 ? void 0 : inject.HowlClass) !== null && _ref !== void 0 ? _ref : import_howler.Howl;
176
+ this.HowlerInstance = (_ref1 = inject === null || inject === void 0 ? void 0 : inject.HowlerObj) !== null && _ref1 !== void 0 ? _ref1 : import_howler.Howler;
177
+ if (typeof (options === null || options === void 0 ? void 0 : options.defaultVolume) === "number") {
178
+ this.setGlobalVolume(options.defaultVolume);
179
+ }
180
+ }
181
+ _create_class(AudioManager, [
182
+ {
183
+ key: "hasEffect",
184
+ value: function hasEffect(key) {
185
+ return this.effectCache.has(key);
186
+ }
187
+ },
188
+ {
189
+ key: "loadEffect",
190
+ value: function loadEffect(key, url) {
191
+ var _this = this;
192
+ if (this.effectCache.has(key)) {
193
+ this.effectCache.get(key).unload();
194
+ }
195
+ var howl = new this.HowlConstructor({
196
+ src: [
197
+ url
198
+ ],
199
+ preload: true
200
+ });
201
+ howl.on("load", function() {
202
+ _this.emit("load", {
203
+ type: "effect",
204
+ key: key,
205
+ url: url
206
+ });
207
+ });
208
+ howl.on("loaderror", function(_id, error) {
209
+ _this.emit("error", {
210
+ type: "effect",
211
+ key: key,
212
+ url: url,
213
+ error: error
214
+ });
215
+ });
216
+ this.effectCache.set(key, howl);
217
+ }
218
+ },
219
+ {
220
+ key: "loadEffects",
221
+ value: function loadEffects(map) {
222
+ var _this = this;
223
+ Object.keys(map).forEach(function(key) {
224
+ var typedKey = isNaN(Number(key)) ? key : Number(key);
225
+ _this.loadEffect(typedKey, map[key]);
226
+ });
227
+ }
228
+ },
229
+ {
230
+ key: "playEffect",
231
+ value: function playEffect(key, options) {
232
+ var _this = this;
233
+ var howl = this.effectCache.get(key);
234
+ if (!howl) {
235
+ console.warn("[AudioManager] Effect not found for key: ".concat(String(key), "."));
236
+ return void 0;
237
+ }
238
+ if (howl.playing()) {
239
+ howl.stop();
240
+ }
241
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
242
+ howl.volume(options.volume);
243
+ }
244
+ howl.off("play");
245
+ howl.off("end");
246
+ howl.off("stop");
247
+ howl.off("playerror");
248
+ howl.once("play", function(soundId) {
249
+ var _options_onStart;
250
+ options === null || options === void 0 ? void 0 : (_options_onStart = options.onStart) === null || _options_onStart === void 0 ? void 0 : _options_onStart.call(options, soundId);
251
+ _this.emit("play", {
252
+ type: "effect",
253
+ key: key,
254
+ soundId: soundId
255
+ });
256
+ });
257
+ howl.once("end", function(soundId) {
258
+ var _options_onEnd;
259
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
260
+ howl.volume(1);
261
+ }
262
+ options === null || options === void 0 ? void 0 : (_options_onEnd = options.onEnd) === null || _options_onEnd === void 0 ? void 0 : _options_onEnd.call(options, soundId);
263
+ _this.emit("end", {
264
+ type: "effect",
265
+ key: key,
266
+ soundId: soundId
267
+ });
268
+ });
269
+ howl.once("stop", function(soundId) {
270
+ var _options_onStop;
271
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
272
+ howl.volume(1);
273
+ }
274
+ options === null || options === void 0 ? void 0 : (_options_onStop = options.onStop) === null || _options_onStop === void 0 ? void 0 : _options_onStop.call(options, soundId);
275
+ _this.emit("stop", {
276
+ type: "effect",
277
+ key: key,
278
+ soundId: soundId
279
+ });
280
+ });
281
+ howl.once("playerror", function(soundId, error) {
282
+ var _options_onError;
283
+ options === null || options === void 0 ? void 0 : (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, soundId, error);
284
+ _this.emit("error", {
285
+ type: "effect",
286
+ key: key,
287
+ soundId: soundId,
288
+ error: error
289
+ });
290
+ });
291
+ return howl.play();
292
+ }
293
+ },
294
+ {
295
+ key: "stopEffect",
296
+ value: function stopEffect(key) {
297
+ var howl = this.effectCache.get(key);
298
+ if (howl) {
299
+ howl.stop();
300
+ }
301
+ }
302
+ },
303
+ {
304
+ key: "removeEffect",
305
+ value: function removeEffect(key) {
306
+ var howl = this.effectCache.get(key);
307
+ if (howl) {
308
+ howl.unload();
309
+ this.effectCache.delete(key);
310
+ }
311
+ }
312
+ },
313
+ {
314
+ key: "preloadUrl",
315
+ value: function preloadUrl(url) {
316
+ var _this = this;
317
+ var existing = this.urlAudioCache.get(url);
318
+ if (existing && existing.state() === "loaded") {
319
+ return Promise.resolve();
320
+ }
321
+ var pending = this.preloadPromises.get(url);
322
+ if (pending) {
323
+ return pending;
324
+ }
325
+ var howl = existing && existing.state() !== "unloaded" ? existing : this.createUrlHowl(url);
326
+ var promise = new Promise(function(resolve, reject) {
327
+ howl.once("load", function() {
328
+ resolve();
329
+ });
330
+ howl.once("loaderror", function(_id, error) {
331
+ _this.urlAudioCache.delete(url);
332
+ reject(error);
333
+ });
334
+ });
335
+ this.preloadPromises.set(url, promise);
336
+ var settle = function settle() {
337
+ if (_this.preloadPromises.get(url) === promise) {
338
+ _this.preloadPromises.delete(url);
339
+ }
340
+ };
341
+ promise.then(settle, settle);
342
+ return promise;
343
+ }
344
+ },
345
+ {
346
+ key: "preloadUrls",
347
+ value: function preloadUrls(urls) {
348
+ var _this = this;
349
+ return Promise.all(urls.map(function(url) {
350
+ return _this.preloadUrl(url);
351
+ }));
352
+ }
353
+ },
354
+ {
355
+ key: "createUrlHowl",
356
+ value: function createUrlHowl(url) {
357
+ var _this = this;
358
+ var howl = new this.HowlConstructor({
359
+ src: [
360
+ url
361
+ ],
362
+ preload: true
363
+ });
364
+ howl.on("load", function() {
365
+ _this.emit("load", {
366
+ type: "url",
367
+ url: url
368
+ });
369
+ });
370
+ howl.on("loaderror", function(_id, error) {
371
+ _this.urlAudioCache.delete(url);
372
+ _this.emit("error", {
373
+ type: "url",
374
+ url: url,
375
+ error: error
376
+ });
377
+ });
378
+ this.urlAudioCache.set(url, howl);
379
+ return howl;
380
+ }
381
+ },
382
+ {
383
+ key: "playUrl",
384
+ value: function playUrl(url, options) {
385
+ var _this = this;
386
+ var howl = this.urlAudioCache.get(url) || this.createUrlHowl(url);
387
+ var isSingleton = (options === null || options === void 0 ? void 0 : options.singleton) !== false;
388
+ if (isSingleton && this.activeUrlHowl && this.activeUrlHowl !== howl && this.activeUrlHowl.playing()) {
389
+ this.activeUrlHowl.stop();
390
+ }
391
+ if (howl.playing()) {
392
+ howl.stop();
393
+ }
394
+ if ((options === null || options === void 0 ? void 0 : options.loop) !== void 0) {
395
+ howl.loop(options.loop);
396
+ }
397
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
398
+ howl.volume(options.volume);
399
+ }
400
+ if (isSingleton) {
401
+ this.activeUrlHowl = howl;
402
+ }
403
+ howl.off("play");
404
+ howl.off("end");
405
+ howl.off("stop");
406
+ howl.off("playerror");
407
+ howl.once("play", function(soundId) {
408
+ var _options_onStart;
409
+ options === null || options === void 0 ? void 0 : (_options_onStart = options.onStart) === null || _options_onStart === void 0 ? void 0 : _options_onStart.call(options, soundId);
410
+ _this.emit("play", {
411
+ type: "url",
412
+ url: url,
413
+ soundId: soundId
414
+ });
415
+ });
416
+ howl.once("end", function(soundId) {
417
+ var _options_onEnd;
418
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
419
+ howl.volume(1);
420
+ }
421
+ options === null || options === void 0 ? void 0 : (_options_onEnd = options.onEnd) === null || _options_onEnd === void 0 ? void 0 : _options_onEnd.call(options, soundId);
422
+ _this.emit("end", {
423
+ type: "url",
424
+ url: url,
425
+ soundId: soundId
426
+ });
427
+ if (_this.activeUrlHowl === howl && !howl.loop()) {
428
+ _this.activeUrlHowl = null;
429
+ }
430
+ });
431
+ howl.once("stop", function(soundId) {
432
+ var _options_onStop;
433
+ if (typeof (options === null || options === void 0 ? void 0 : options.volume) === "number") {
434
+ howl.volume(1);
435
+ }
436
+ options === null || options === void 0 ? void 0 : (_options_onStop = options.onStop) === null || _options_onStop === void 0 ? void 0 : _options_onStop.call(options, soundId);
437
+ _this.emit("stop", {
438
+ type: "url",
439
+ url: url,
440
+ soundId: soundId
441
+ });
442
+ if (_this.activeUrlHowl === howl) {
443
+ _this.activeUrlHowl = null;
444
+ }
445
+ });
446
+ howl.once("playerror", function(soundId, error) {
447
+ var _options_onError;
448
+ options === null || options === void 0 ? void 0 : (_options_onError = options.onError) === null || _options_onError === void 0 ? void 0 : _options_onError.call(options, soundId, error);
449
+ _this.emit("error", {
450
+ type: "url",
451
+ url: url,
452
+ soundId: soundId,
453
+ error: error
454
+ });
455
+ if (_this.activeUrlHowl === howl) {
456
+ _this.activeUrlHowl = null;
457
+ }
458
+ });
459
+ return howl.play();
460
+ }
461
+ },
462
+ {
463
+ key: "stopUrl",
464
+ value: function stopUrl(url) {
465
+ var howl = this.urlAudioCache.get(url);
466
+ if (howl) {
467
+ howl.stop();
468
+ }
469
+ }
470
+ },
471
+ {
472
+ key: "on",
473
+ value: function on(event, handler) {
474
+ var _this_listeners_get;
475
+ var set = (_this_listeners_get = this.listeners.get(event)) !== null && _this_listeners_get !== void 0 ? _this_listeners_get : /* @__PURE__ */ new Set();
476
+ this.listeners.set(event, set);
477
+ set.add(handler);
478
+ return {
479
+ destroy: function destroy() {
480
+ set.delete(handler);
481
+ }
482
+ };
483
+ }
484
+ },
485
+ {
486
+ key: "emit",
487
+ value: function emit(event, payload) {
488
+ var set = this.listeners.get(event);
489
+ if (set) {
490
+ set.forEach(function(handler) {
491
+ try {
492
+ handler(payload);
493
+ } catch (err) {
494
+ console.error("[AudioManager] Error in event listener for ".concat(event, ":"), err);
495
+ }
496
+ });
497
+ }
498
+ }
499
+ },
500
+ {
501
+ key: "getGlobalVolume",
502
+ value: function getGlobalVolume() {
503
+ return this.globalVolume;
504
+ }
505
+ },
506
+ {
507
+ key: "setGlobalVolume",
508
+ value: function setGlobalVolume(volume) {
509
+ this.globalVolume = volume;
510
+ this.HowlerInstance.volume(volume);
511
+ }
512
+ },
513
+ {
514
+ key: "mute",
515
+ value: function mute(muted) {
516
+ this.HowlerInstance.mute(muted);
517
+ }
518
+ },
519
+ {
520
+ key: "stopAll",
521
+ value: function stopAll() {
522
+ this.HowlerInstance.stop();
523
+ this.activeUrlHowl = null;
524
+ }
525
+ },
526
+ {
527
+ key: "destroy",
528
+ value: function destroy() {
529
+ this.effectCache.forEach(function(howl) {
530
+ return howl.unload();
531
+ });
532
+ this.urlAudioCache.forEach(function(howl) {
533
+ return howl.unload();
534
+ });
535
+ this.effectCache.clear();
536
+ this.urlAudioCache.clear();
537
+ this.preloadPromises.clear();
538
+ this.listeners.clear();
539
+ this.activeUrlHowl = null;
540
+ }
541
+ }
542
+ ]);
543
+ return AudioManager;
544
+ }();
545
+ // src/react.tsx
546
+ var import_react = require("react");
547
+ var import_jsx_runtime = require("react/jsx-runtime");
548
+ var AudioManagerContext = (0, import_react.createContext)(null);
549
+ function AudioManagerProvider(param) {
550
+ var manager = param.manager, children = param.children;
551
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AudioManagerContext.Provider, {
552
+ value: manager,
553
+ children: children
554
+ });
555
+ }
556
+ function useAudio() {
557
+ var manager = (0, import_react.useContext)(AudioManagerContext);
558
+ if (!manager) {
559
+ throw new Error("useAudio must be used within an <AudioManagerProvider>.");
560
+ }
561
+ return manager;
562
+ }
563
+ function useAudioEvent(event, handler) {
564
+ var manager = useAudio();
565
+ var handlerRef = (0, import_react.useRef)(handler);
566
+ handlerRef.current = handler;
567
+ (0, import_react.useEffect)(function() {
568
+ var subscription = manager.on(event, function(payload) {
569
+ return handlerRef.current(payload);
570
+ });
571
+ return function() {
572
+ return subscription.destroy();
573
+ };
574
+ }, [
575
+ manager,
576
+ event
577
+ ]);
578
+ }
579
+ function useGlobalVolume() {
580
+ var manager = useAudio();
581
+ var _ref = _sliced_to_array((0, import_react.useState)(function() {
582
+ return manager.getGlobalVolume();
583
+ }), 2), volume = _ref[0], setVolumeState = _ref[1];
584
+ var setVolume = (0, import_react.useCallback)(function(next) {
585
+ manager.setGlobalVolume(next);
586
+ setVolumeState(next);
587
+ }, [
588
+ manager
589
+ ]);
590
+ return [
591
+ volume,
592
+ setVolume
593
+ ];
594
+ }
595
+ function usePreload(urls) {
596
+ var manager = useAudio();
597
+ var urlsKey = JSON.stringify(urls);
598
+ var _ref = _sliced_to_array((0, import_react.useState)({
599
+ status: "idle",
600
+ error: null
601
+ }), 2), state = _ref[0], setState = _ref[1];
602
+ (0, import_react.useEffect)(function() {
603
+ var list = JSON.parse(urlsKey);
604
+ if (list.length === 0) {
605
+ setState({
606
+ status: "idle",
607
+ error: null
608
+ });
609
+ return;
610
+ }
611
+ var cancelled = false;
612
+ setState({
613
+ status: "loading",
614
+ error: null
615
+ });
616
+ manager.preloadUrls(list).then(function() {
617
+ if (!cancelled) setState({
618
+ status: "loaded",
619
+ error: null
620
+ });
621
+ }, function(error) {
622
+ if (!cancelled) setState({
623
+ status: "error",
624
+ error: error
625
+ });
626
+ });
627
+ return function() {
628
+ cancelled = true;
629
+ };
630
+ }, [
631
+ manager,
632
+ urlsKey
633
+ ]);
634
+ return state;
635
+ }
636
+ // Annotate the CommonJS export names for ESM import in node:
637
+ 0 && (module1.exports = {
638
+ AudioManager: AudioManager,
639
+ AudioManagerProvider: AudioManagerProvider,
640
+ useAudio: useAudio,
641
+ useAudioEvent: useAudioEvent,
642
+ useGlobalVolume: useGlobalVolume,
643
+ usePreload: usePreload
644
+ });
645
+ if (__exports != exports1) module1.exports = exports1;
646
+ return module1.exports;
647
+ });
648
+ //# sourceMappingURL=index.umd.js.map