svelte-attach-sound 0.1.3 → 0.1.5
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/README.md +2 -47
- package/dist/index.d.ts +53 -0
- package/dist/index.js +1 -0
- package/package.json +14 -25
- package/dist/index.cjs +0 -99
- package/dist/index.d.cts +0 -68
- package/dist/index.d.mts +0 -68
- package/dist/index.mjs +0 -96
package/README.md
CHANGED
|
@@ -2,15 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A Svelte attachment for binding sound playback to DOM events using the [Svelte 5 attachments API](https://svelte.dev/docs/svelte/attachments).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Find CC-Zero licensed sounds at [freesound.org](https://freesound.org/)
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
npm install svelte-attach-sound howler
|
|
13
|
-
```
|
|
5
|
+
You can find CC-Zero licensed sounds at [freesound.org](https://freesound.org/)
|
|
14
6
|
|
|
15
7
|
## Example
|
|
16
8
|
|
|
@@ -24,6 +16,7 @@ npm install svelte-attach-sound howler
|
|
|
24
16
|
|
|
25
17
|
<!-- Inline -->
|
|
26
18
|
<button {@attach sound({ src: click_mp3, events: ["click"] })}>Click</button>
|
|
19
|
+
<button {@attach sound({ src: click_mp3, events: ["mouseenter"] })}>Enter</button>
|
|
27
20
|
|
|
28
21
|
<!-- Factory: reusable with shared defaults -->
|
|
29
22
|
<button {@attach click()}>Click</button>
|
|
@@ -31,41 +24,3 @@ npm install svelte-attach-sound howler
|
|
|
31
24
|
```
|
|
32
25
|
|
|
33
26
|
[Demo](https://joknoll.github.io/svelte-attach-sound/) | [npm](https://www.npmjs.com/package/svelte-attach-sound)
|
|
34
|
-
|
|
35
|
-
## API
|
|
36
|
-
|
|
37
|
-
### `sound(options)`
|
|
38
|
-
|
|
39
|
-
Svelte attachment that plays a sound on a DOM event.
|
|
40
|
-
|
|
41
|
-
| Option | Type | Required | Description |
|
|
42
|
-
| --------- | -------------------------------------------------------------- | -------- | -------------------------------------------------- |
|
|
43
|
-
| `src` | `string \| string[]` | Yes | Audio file URL(s), with fallbacks |
|
|
44
|
-
| `events` | `[playEvent, stopEvent?]` | Yes | DOM event to trigger play, and optionally stop |
|
|
45
|
-
| `...rest` | [`HowlOptions`](https://github.com/goldfire/howler.js#options) | No | Any Howler option (`volume`, `loop`, `rate`, etc.) |
|
|
46
|
-
|
|
47
|
-
### `useSound(src, events, options?)`
|
|
48
|
-
|
|
49
|
-
Factory that returns a reusable attachment with preset defaults. The returned function accepts optional per-call overrides.
|
|
50
|
-
|
|
51
|
-
```svelte
|
|
52
|
-
<script lang="ts">
|
|
53
|
-
const click = useSound(click_mp3, ["pointerdown"], { volume: 0.8 });
|
|
54
|
-
</script>
|
|
55
|
-
|
|
56
|
-
<button {@attach click()}>Uses defaults</button>
|
|
57
|
-
<button {@attach click({ volume: 0.3 })}>Override volume</button>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### `Sound` class
|
|
61
|
-
|
|
62
|
-
For manual control outside of attachments:
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
import { Sound } from "svelte-attach-sound";
|
|
66
|
-
|
|
67
|
-
const s = new Sound(click_mp3, { volume: 0.5 });
|
|
68
|
-
s.play();
|
|
69
|
-
s.stop();
|
|
70
|
-
s.destroy(); // stops playback and frees resources
|
|
71
|
-
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Attachment } from "svelte/attachments";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
type SoundSource = string;
|
|
5
|
+
type SoundEvents = [keyof HTMLElementEventMap, (keyof HTMLElementEventMap)?];
|
|
6
|
+
type SoundOptions = {
|
|
7
|
+
/** Playback volume, 0.0 to 1.0. Default: 1. */volume?: number; /** Whether the sound loops. Default: false. */
|
|
8
|
+
loop?: boolean; /** Playback rate multiplier. Default: 1. */
|
|
9
|
+
rate?: number;
|
|
10
|
+
};
|
|
11
|
+
type Options = {
|
|
12
|
+
src: SoundSource;
|
|
13
|
+
events: SoundEvents;
|
|
14
|
+
} & SoundOptions;
|
|
15
|
+
declare class Sound {
|
|
16
|
+
private buffer;
|
|
17
|
+
private source;
|
|
18
|
+
private options;
|
|
19
|
+
constructor(src: SoundSource, options?: SoundOptions);
|
|
20
|
+
private load;
|
|
21
|
+
play(): void;
|
|
22
|
+
stop(): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a sound attachment that binds playback to DOM events on the element.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```svelte
|
|
29
|
+
* <button {@attach sound({ src: click_mp3, events: ["click"] })}>
|
|
30
|
+
* Click me
|
|
31
|
+
* </button>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function sound(options: Options): Attachment<HTMLElement>;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a pre-configured sound attachment factory reusable across elements.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```svelte
|
|
40
|
+
* <script>
|
|
41
|
+
* import { useSound } from "svelte-attach-sound";
|
|
42
|
+
* import click_mp3 from "./assets/click.mp3";
|
|
43
|
+
*
|
|
44
|
+
* const click = useSound(click_mp3, ["click"]);
|
|
45
|
+
* </script>
|
|
46
|
+
*
|
|
47
|
+
* <button {@attach click()}>Click me</button>
|
|
48
|
+
* <button {@attach click({ volume: 0.5 })}>Quieter</button>
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare function useSound(src: SoundSource, events: SoundEvents, options?: SoundOptions): (overrideOptions?: Partial<Options>) => Attachment<HTMLElement>;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { Sound, sound, useSound };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{on as e}from"svelte/events";let t=null;function n(){return typeof AudioContext>`u`?null:t??=new AudioContext}var r=class{buffer;source=null;options;constructor(e,t={}){this.options=t,this.buffer=this.load(e)}async load(e){let t=n();if(!t)return null;try{let n=await(await fetch(e)).arrayBuffer();return await t.decodeAudioData(n)}catch(t){return console.warn(`[svelte-attach-sound] Failed to load sound:`,e,t),null}}play(){this.buffer.then(e=>{if(!e)return;let t=n();if(!t)return;t.resume();let r=t.createBufferSource();r.buffer=e,r.loop=this.options.loop??!1,r.playbackRate.value=this.options.rate??1;let i=t.createGain();i.gain.value=this.options.volume??1,r.connect(i).connect(t.destination),this.source=r,r.start()})}stop(){try{this.source?.stop()}catch{}this.source=null}};function i(t){return n=>{let{src:i,events:a,...o}=t,[s,c]=a,l=new r(i,o),u=e(n,s,()=>l.play()),d=c?e(n,c,()=>l.stop()):null;return()=>{u(),d?.(),l.stop()}}}function a(e,t,n){return r=>i({src:e,events:t,...n,...r})}export{r as Sound,i as sound,a as useSound};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-attach-sound",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A Svelte attachment for binding sound playback to DOM events using
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "A Svelte attachment for binding sound playback to DOM events using the Web Audio API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"attachment",
|
|
7
|
-
"howler",
|
|
8
7
|
"sound",
|
|
9
8
|
"svelte",
|
|
10
|
-
"svelte5"
|
|
9
|
+
"svelte5",
|
|
10
|
+
"web-audio"
|
|
11
11
|
],
|
|
12
12
|
"homepage": "https://github.com/joknoll/svelte-attach-sound#readme",
|
|
13
13
|
"bugs": {
|
|
@@ -23,37 +23,26 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"type": "module",
|
|
26
|
-
"main": "./dist/index.cjs",
|
|
27
|
-
"module": "./dist/index.mjs",
|
|
28
26
|
"types": "./dist/index.d.cts",
|
|
29
27
|
"exports": {
|
|
30
|
-
".":
|
|
31
|
-
"import": "./dist/index.mjs",
|
|
32
|
-
"require": "./dist/index.cjs"
|
|
33
|
-
},
|
|
28
|
+
".": "./dist/index.js",
|
|
34
29
|
"./package.json": "./package.json"
|
|
35
30
|
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "tsdown",
|
|
38
|
-
"dev": "tsdown --watch",
|
|
39
|
-
"test": "vitest",
|
|
40
|
-
"typecheck": "tsc --noEmit",
|
|
41
|
-
"prepublishOnly": "bun run build"
|
|
42
|
-
},
|
|
43
31
|
"devDependencies": {
|
|
44
|
-
"@types/howler": "^2.2.12",
|
|
45
32
|
"@types/node": "^25.0.3",
|
|
46
33
|
"bumpp": "^11.0.1",
|
|
47
|
-
"howler": "^2.2.4",
|
|
48
|
-
"oxfmt": "^0.41.0",
|
|
49
|
-
"oxlint": "^1.56.0",
|
|
50
34
|
"svelte": "^5.55.0",
|
|
51
|
-
"tsdown": "^0.21.4",
|
|
52
35
|
"typescript": "^6.0.2",
|
|
53
|
-
"
|
|
36
|
+
"vite-plus": "latest",
|
|
37
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
|
54
38
|
},
|
|
55
39
|
"peerDependencies": {
|
|
56
|
-
"howler": ">=2.0.0",
|
|
57
40
|
"svelte": ">=5.55.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "vp pack",
|
|
44
|
+
"dev": "vp pack --watch",
|
|
45
|
+
"test": "vp test",
|
|
46
|
+
"typecheck": "tsc --noEmit"
|
|
58
47
|
}
|
|
59
|
-
}
|
|
48
|
+
}
|
package/dist/index.cjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
let svelte_events = require("svelte/events");
|
|
3
|
-
//#region src/index.ts
|
|
4
|
-
/**
|
|
5
|
-
* A class representing a synthetic sound.
|
|
6
|
-
* Can be used standalone for programmatic playback without any DOM dependency.
|
|
7
|
-
*/
|
|
8
|
-
var Sound = class {
|
|
9
|
-
howl;
|
|
10
|
-
constructor(src, options = {}) {
|
|
11
|
-
this.howl = import("howler/src/howler.core").then(({ Howl }) => new Howl({
|
|
12
|
-
...options,
|
|
13
|
-
src
|
|
14
|
-
})).catch((e) => {
|
|
15
|
-
console.warn("[svelte-attach-sound] Failed to load sound:", e);
|
|
16
|
-
throw e;
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
play() {
|
|
20
|
-
this.howl.then((h) => h.play()).catch(() => {});
|
|
21
|
-
}
|
|
22
|
-
stop() {
|
|
23
|
-
this.howl.then((h) => h.stop()).catch(() => {});
|
|
24
|
-
}
|
|
25
|
-
destroy() {
|
|
26
|
-
this.howl.then((h) => {
|
|
27
|
-
h.stop();
|
|
28
|
-
h.unload();
|
|
29
|
-
}).catch(() => {});
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Creates a sound attachment that binds playback to DOM events on the element.
|
|
34
|
-
*
|
|
35
|
-
* Runs inside a Svelte effect — if options contain reactive state, the attachment
|
|
36
|
-
* will automatically tear down and recreate when that state changes.
|
|
37
|
-
*
|
|
38
|
-
* @param options Options including `src`, `events`, and any Howler options.
|
|
39
|
-
* @returns A Svelte attachment.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```svelte
|
|
43
|
-
* <button {@attach sound({ src: click_mp3, events: ["click"] })}>
|
|
44
|
-
* Click me
|
|
45
|
-
* </button>
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
function sound(options) {
|
|
49
|
-
return (element) => {
|
|
50
|
-
const { src, events, ...howlOptions } = options;
|
|
51
|
-
const [playEvent, stopEvent] = events;
|
|
52
|
-
const instance = new Sound(src, howlOptions);
|
|
53
|
-
const handlePlay = () => instance.play();
|
|
54
|
-
const handleStop = () => instance.stop();
|
|
55
|
-
const offPlay = (0, svelte_events.on)(element, playEvent, handlePlay);
|
|
56
|
-
const offStop = stopEvent ? (0, svelte_events.on)(element, stopEvent, handleStop) : null;
|
|
57
|
-
return () => {
|
|
58
|
-
offPlay();
|
|
59
|
-
offStop?.();
|
|
60
|
-
instance.destroy();
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Creates a pre-configured sound attachment factory that can be reused across
|
|
66
|
-
* multiple elements with optional per-element overrides.
|
|
67
|
-
*
|
|
68
|
-
* @param src The source URL(s) of the sound.
|
|
69
|
-
* @param events The `[playEvent, stopEvent?]` tuple.
|
|
70
|
-
* @param options Optional base Howler options.
|
|
71
|
-
* @returns A factory function that returns a Svelte attachment.
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```svelte
|
|
75
|
-
* <script>
|
|
76
|
-
* import { useSound } from "svelte-attach-sound";
|
|
77
|
-
* import click_mp3 from "./assets/click.mp3";
|
|
78
|
-
*
|
|
79
|
-
* const click = useSound(click_mp3, ["click"]);
|
|
80
|
-
* <\/script>
|
|
81
|
-
*
|
|
82
|
-
* <button {@attach click()}>Click me</button>
|
|
83
|
-
*
|
|
84
|
-
* <!-- Override options per-element -->
|
|
85
|
-
* <button {@attach click({ volume: 0.5 })}>Click me (quieter)</button>
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
function useSound(src, events, options) {
|
|
89
|
-
return (overrideOptions) => sound({
|
|
90
|
-
src,
|
|
91
|
-
events,
|
|
92
|
-
...options,
|
|
93
|
-
...overrideOptions
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
exports.Sound = Sound;
|
|
98
|
-
exports.sound = sound;
|
|
99
|
-
exports.useSound = useSound;
|
package/dist/index.d.cts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { HowlOptions } from "howler";
|
|
2
|
-
import { Attachment } from "svelte/attachments";
|
|
3
|
-
|
|
4
|
-
//#region src/index.d.ts
|
|
5
|
-
type SoundSource = HowlOptions["src"];
|
|
6
|
-
type SoundEvents = [keyof HTMLElementEventMap, (keyof HTMLElementEventMap)?];
|
|
7
|
-
type SoundOptions = Omit<HowlOptions, "src">;
|
|
8
|
-
/**
|
|
9
|
-
* Options for the sound attachment factory.
|
|
10
|
-
*/
|
|
11
|
-
type Options = {
|
|
12
|
-
events: SoundEvents;
|
|
13
|
-
} & HowlOptions;
|
|
14
|
-
/**
|
|
15
|
-
* A class representing a synthetic sound.
|
|
16
|
-
* Can be used standalone for programmatic playback without any DOM dependency.
|
|
17
|
-
*/
|
|
18
|
-
declare class Sound {
|
|
19
|
-
private howl;
|
|
20
|
-
constructor(src: SoundSource, options?: SoundOptions);
|
|
21
|
-
play(): void;
|
|
22
|
-
stop(): void;
|
|
23
|
-
destroy(): void;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Creates a sound attachment that binds playback to DOM events on the element.
|
|
27
|
-
*
|
|
28
|
-
* Runs inside a Svelte effect — if options contain reactive state, the attachment
|
|
29
|
-
* will automatically tear down and recreate when that state changes.
|
|
30
|
-
*
|
|
31
|
-
* @param options Options including `src`, `events`, and any Howler options.
|
|
32
|
-
* @returns A Svelte attachment.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```svelte
|
|
36
|
-
* <button {@attach sound({ src: click_mp3, events: ["click"] })}>
|
|
37
|
-
* Click me
|
|
38
|
-
* </button>
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
declare function sound(options: Options): Attachment<HTMLElement>;
|
|
42
|
-
/**
|
|
43
|
-
* Creates a pre-configured sound attachment factory that can be reused across
|
|
44
|
-
* multiple elements with optional per-element overrides.
|
|
45
|
-
*
|
|
46
|
-
* @param src The source URL(s) of the sound.
|
|
47
|
-
* @param events The `[playEvent, stopEvent?]` tuple.
|
|
48
|
-
* @param options Optional base Howler options.
|
|
49
|
-
* @returns A factory function that returns a Svelte attachment.
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```svelte
|
|
53
|
-
* <script>
|
|
54
|
-
* import { useSound } from "svelte-attach-sound";
|
|
55
|
-
* import click_mp3 from "./assets/click.mp3";
|
|
56
|
-
*
|
|
57
|
-
* const click = useSound(click_mp3, ["click"]);
|
|
58
|
-
* </script>
|
|
59
|
-
*
|
|
60
|
-
* <button {@attach click()}>Click me</button>
|
|
61
|
-
*
|
|
62
|
-
* <!-- Override options per-element -->
|
|
63
|
-
* <button {@attach click({ volume: 0.5 })}>Click me (quieter)</button>
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
declare function useSound(src: SoundSource, events: SoundEvents, options?: SoundOptions): (overrideOptions?: Partial<Options>) => Attachment<HTMLElement>;
|
|
67
|
-
//#endregion
|
|
68
|
-
export { Sound, sound, useSound };
|
package/dist/index.d.mts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { HowlOptions } from "howler";
|
|
2
|
-
import { Attachment } from "svelte/attachments";
|
|
3
|
-
|
|
4
|
-
//#region src/index.d.ts
|
|
5
|
-
type SoundSource = HowlOptions["src"];
|
|
6
|
-
type SoundEvents = [keyof HTMLElementEventMap, (keyof HTMLElementEventMap)?];
|
|
7
|
-
type SoundOptions = Omit<HowlOptions, "src">;
|
|
8
|
-
/**
|
|
9
|
-
* Options for the sound attachment factory.
|
|
10
|
-
*/
|
|
11
|
-
type Options = {
|
|
12
|
-
events: SoundEvents;
|
|
13
|
-
} & HowlOptions;
|
|
14
|
-
/**
|
|
15
|
-
* A class representing a synthetic sound.
|
|
16
|
-
* Can be used standalone for programmatic playback without any DOM dependency.
|
|
17
|
-
*/
|
|
18
|
-
declare class Sound {
|
|
19
|
-
private howl;
|
|
20
|
-
constructor(src: SoundSource, options?: SoundOptions);
|
|
21
|
-
play(): void;
|
|
22
|
-
stop(): void;
|
|
23
|
-
destroy(): void;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Creates a sound attachment that binds playback to DOM events on the element.
|
|
27
|
-
*
|
|
28
|
-
* Runs inside a Svelte effect — if options contain reactive state, the attachment
|
|
29
|
-
* will automatically tear down and recreate when that state changes.
|
|
30
|
-
*
|
|
31
|
-
* @param options Options including `src`, `events`, and any Howler options.
|
|
32
|
-
* @returns A Svelte attachment.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```svelte
|
|
36
|
-
* <button {@attach sound({ src: click_mp3, events: ["click"] })}>
|
|
37
|
-
* Click me
|
|
38
|
-
* </button>
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
declare function sound(options: Options): Attachment<HTMLElement>;
|
|
42
|
-
/**
|
|
43
|
-
* Creates a pre-configured sound attachment factory that can be reused across
|
|
44
|
-
* multiple elements with optional per-element overrides.
|
|
45
|
-
*
|
|
46
|
-
* @param src The source URL(s) of the sound.
|
|
47
|
-
* @param events The `[playEvent, stopEvent?]` tuple.
|
|
48
|
-
* @param options Optional base Howler options.
|
|
49
|
-
* @returns A factory function that returns a Svelte attachment.
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```svelte
|
|
53
|
-
* <script>
|
|
54
|
-
* import { useSound } from "svelte-attach-sound";
|
|
55
|
-
* import click_mp3 from "./assets/click.mp3";
|
|
56
|
-
*
|
|
57
|
-
* const click = useSound(click_mp3, ["click"]);
|
|
58
|
-
* </script>
|
|
59
|
-
*
|
|
60
|
-
* <button {@attach click()}>Click me</button>
|
|
61
|
-
*
|
|
62
|
-
* <!-- Override options per-element -->
|
|
63
|
-
* <button {@attach click({ volume: 0.5 })}>Click me (quieter)</button>
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
declare function useSound(src: SoundSource, events: SoundEvents, options?: SoundOptions): (overrideOptions?: Partial<Options>) => Attachment<HTMLElement>;
|
|
67
|
-
//#endregion
|
|
68
|
-
export { Sound, sound, useSound };
|
package/dist/index.mjs
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { on } from "svelte/events";
|
|
2
|
-
//#region src/index.ts
|
|
3
|
-
/**
|
|
4
|
-
* A class representing a synthetic sound.
|
|
5
|
-
* Can be used standalone for programmatic playback without any DOM dependency.
|
|
6
|
-
*/
|
|
7
|
-
var Sound = class {
|
|
8
|
-
howl;
|
|
9
|
-
constructor(src, options = {}) {
|
|
10
|
-
this.howl = import("howler/src/howler.core").then(({ Howl }) => new Howl({
|
|
11
|
-
...options,
|
|
12
|
-
src
|
|
13
|
-
})).catch((e) => {
|
|
14
|
-
console.warn("[svelte-attach-sound] Failed to load sound:", e);
|
|
15
|
-
throw e;
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
play() {
|
|
19
|
-
this.howl.then((h) => h.play()).catch(() => {});
|
|
20
|
-
}
|
|
21
|
-
stop() {
|
|
22
|
-
this.howl.then((h) => h.stop()).catch(() => {});
|
|
23
|
-
}
|
|
24
|
-
destroy() {
|
|
25
|
-
this.howl.then((h) => {
|
|
26
|
-
h.stop();
|
|
27
|
-
h.unload();
|
|
28
|
-
}).catch(() => {});
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Creates a sound attachment that binds playback to DOM events on the element.
|
|
33
|
-
*
|
|
34
|
-
* Runs inside a Svelte effect — if options contain reactive state, the attachment
|
|
35
|
-
* will automatically tear down and recreate when that state changes.
|
|
36
|
-
*
|
|
37
|
-
* @param options Options including `src`, `events`, and any Howler options.
|
|
38
|
-
* @returns A Svelte attachment.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```svelte
|
|
42
|
-
* <button {@attach sound({ src: click_mp3, events: ["click"] })}>
|
|
43
|
-
* Click me
|
|
44
|
-
* </button>
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
function sound(options) {
|
|
48
|
-
return (element) => {
|
|
49
|
-
const { src, events, ...howlOptions } = options;
|
|
50
|
-
const [playEvent, stopEvent] = events;
|
|
51
|
-
const instance = new Sound(src, howlOptions);
|
|
52
|
-
const handlePlay = () => instance.play();
|
|
53
|
-
const handleStop = () => instance.stop();
|
|
54
|
-
const offPlay = on(element, playEvent, handlePlay);
|
|
55
|
-
const offStop = stopEvent ? on(element, stopEvent, handleStop) : null;
|
|
56
|
-
return () => {
|
|
57
|
-
offPlay();
|
|
58
|
-
offStop?.();
|
|
59
|
-
instance.destroy();
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Creates a pre-configured sound attachment factory that can be reused across
|
|
65
|
-
* multiple elements with optional per-element overrides.
|
|
66
|
-
*
|
|
67
|
-
* @param src The source URL(s) of the sound.
|
|
68
|
-
* @param events The `[playEvent, stopEvent?]` tuple.
|
|
69
|
-
* @param options Optional base Howler options.
|
|
70
|
-
* @returns A factory function that returns a Svelte attachment.
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```svelte
|
|
74
|
-
* <script>
|
|
75
|
-
* import { useSound } from "svelte-attach-sound";
|
|
76
|
-
* import click_mp3 from "./assets/click.mp3";
|
|
77
|
-
*
|
|
78
|
-
* const click = useSound(click_mp3, ["click"]);
|
|
79
|
-
* <\/script>
|
|
80
|
-
*
|
|
81
|
-
* <button {@attach click()}>Click me</button>
|
|
82
|
-
*
|
|
83
|
-
* <!-- Override options per-element -->
|
|
84
|
-
* <button {@attach click({ volume: 0.5 })}>Click me (quieter)</button>
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
function useSound(src, events, options) {
|
|
88
|
-
return (overrideOptions) => sound({
|
|
89
|
-
src,
|
|
90
|
-
events,
|
|
91
|
-
...options,
|
|
92
|
-
...overrideOptions
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
//#endregion
|
|
96
|
-
export { Sound, sound, useSound };
|