zsk-use-sound 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # zsk-use-sound
2
+
3
+ A TypeScript-first React hook for sound effects, inspired by the excellent `use-sound` package and extended with a browser-generated fallback mode.
4
+
5
+ ## Why this package
6
+
7
+ This hook gives you one API for two sound strategies:
8
+
9
+ - File mode: Use audio files (mp3, wav, etc.) powered by Howler.
10
+ - Generated mode: If no file is provided, it generates a click-like sound in the browser using the Web Audio API.
11
+
12
+ This is useful when you want sound feedback but do not always want to bundle and manage sound assets.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ bun add zsk-use-sound
18
+ ```
19
+
20
+ or
21
+
22
+ ```bash
23
+ npm install zsk-use-sound
24
+ ```
25
+
26
+ Peer dependency:
27
+
28
+ - React 18+
29
+
30
+ ## Quick Start
31
+
32
+ ```tsx
33
+ import { useSound } from 'zsk-use-sound'
34
+
35
+ export function SaveButton() {
36
+ const [play] = useSound({
37
+ file: '/sounds/click.mp3',
38
+ volume: 0.5,
39
+ })
40
+
41
+ return <button onClick={() => play()}>Save</button>
42
+ }
43
+ ```
44
+
45
+ ## API
46
+
47
+ ### useSound(options?)
48
+
49
+ Returns a tuple:
50
+
51
+ - play: function to trigger sound playback
52
+ - exposedData: helper controls and runtime metadata
53
+
54
+ ```ts
55
+ const [play, exposedData] = useSound(options)
56
+ ```
57
+
58
+ ### Options
59
+
60
+ ```ts
61
+ type BuiltInSoundType = 'click' | 'soft-click' | 'tick'
62
+
63
+ interface UseSoundOptions {
64
+ file?: string | string[]
65
+ type?: BuiltInSoundType
66
+ id?: string
67
+ volume?: number
68
+ playbackRate?: number
69
+ interrupt?: boolean
70
+ soundEnabled?: boolean
71
+ sprite?: Record<string, [number, number]>
72
+ onload?: (this: Howl) => void
73
+
74
+ // Plus delegated Howler options
75
+ }
76
+ ```
77
+
78
+ Behavior:
79
+
80
+ - If file is passed: hook runs in file mode using Howler.
81
+ - If file is omitted: hook runs in generated mode and uses built-in Web Audio click profiles.
82
+ - Default type is click.
83
+
84
+ ### play(options?)
85
+
86
+ ```ts
87
+ interface PlayOptions {
88
+ id?: string
89
+ forceSoundEnabled?: boolean
90
+ playbackRate?: number
91
+ }
92
+ ```
93
+
94
+ ### Exposed data
95
+
96
+ ```ts
97
+ interface ExposedData {
98
+ sound: Howl | null
99
+ stop: (id?: number) => void
100
+ pause: (id?: number) => void
101
+ duration: number | null
102
+ mode: 'file' | 'generated'
103
+ }
104
+ ```
105
+
106
+ ## Usage Patterns
107
+
108
+ ### 1) File mode (use-sound style)
109
+
110
+ ```tsx
111
+ import { useSound } from 'zsk-use-sound'
112
+
113
+ export function NotificationButton() {
114
+ const [play, { stop, mode }] = useSound({
115
+ file: ['/sounds/ping.wav', '/sounds/ping.mp3'],
116
+ volume: 0.4,
117
+ interrupt: true,
118
+ })
119
+
120
+ return (
121
+ <>
122
+ <button onClick={() => play()}>Play</button>
123
+ <button onClick={() => stop()}>Stop</button>
124
+ <small>mode: {mode}</small>
125
+ </>
126
+ )
127
+ }
128
+ ```
129
+
130
+ ### 2) Generated mode (no file)
131
+
132
+ ```tsx
133
+ import { useSound } from 'zsk-use-sound'
134
+
135
+ export function UIInteractions() {
136
+ const [play, { mode }] = useSound({
137
+ type: 'soft-click',
138
+ volume: 0.6,
139
+ })
140
+
141
+ return <button onClick={() => play()}>Click me ({mode})</button>
142
+ }
143
+ ```
144
+
145
+ ### 3) Global sound toggle
146
+
147
+ ```tsx
148
+ import { useSound } from 'zsk-use-sound'
149
+
150
+ export function MutedAwareAction({ isEnabled }: { isEnabled: boolean }) {
151
+ const [play] = useSound({
152
+ file: '/sounds/action.mp3',
153
+ soundEnabled: isEnabled,
154
+ })
155
+
156
+ return <button onClick={() => play()}>Action</button>
157
+ }
158
+ ```
159
+
160
+ ## Why Howler
161
+
162
+ Howler is used for file playback mode because it offers:
163
+
164
+ - Cross-browser audio consistency: normalizes browser differences.
165
+ - Flexible source handling: supports source arrays and format fallback.
166
+ - Sprite support: multiple sounds in one file with IDs.
167
+ - Stable playback controls: volume, rate, stop, pause, and event hooks.
168
+ - Mature ecosystem: widely used and battle-tested.
169
+
170
+ In short, Howler handles the hard edges of browser audio so your hook API stays simple.
171
+
172
+ ## How this package is better for this use case
173
+
174
+ Compared to a direct baseline implementation, this package adds:
175
+
176
+ - Dual-mode behavior: file-based audio plus generated fallback in one hook.
177
+ - No-any TypeScript API: explicit options and return types.
178
+ - Better type surface for consumers: exported public types directly from the package.
179
+ - Built-in sound presets: click, soft-click, tick.
180
+ - Runtime mode visibility: exposedData.mode tells you how playback is happening.
181
+
182
+ ## Credit
183
+
184
+ This package is inspired by:
185
+
186
+ - Josh Comeau's original use-sound project: https://github.com/joshwcomeau/use-sound
187
+
188
+ Many API ideas (tuple return shape, play options, exposed control object, and Howler-based file mode approach) are adapted from that excellent work.
189
+
190
+ Thank you to Josh Comeau for creating and sharing the original library.
191
+
192
+ ## TypeScript Exports
193
+
194
+ You can import runtime and type APIs directly:
195
+
196
+ ```ts
197
+ import { useSound } from 'zsk-use-sound'
198
+ import type {
199
+ BuiltInSoundType,
200
+ UseSoundOptions,
201
+ PlayOptions,
202
+ ExposedData,
203
+ ReturnedValue,
204
+ } from 'zsk-use-sound'
205
+ ```
206
+
207
+ ## Notes
208
+
209
+ - Generated mode relies on Web Audio API availability in the browser.
210
+ - Browsers often require user interaction before sound can play.
211
+ - For SSR environments, playback happens client-side only.
212
+
213
+ ## License
214
+
215
+ ISC
@@ -0,0 +1,37 @@
1
+ import type { Howl, HowlOptions } from 'howler';
2
+ declare global {
3
+ interface Window {
4
+ webkitAudioContext?: typeof AudioContext;
5
+ }
6
+ }
7
+ export type BuiltInSoundType = 'click' | 'soft-click' | 'tick';
8
+ export type SpriteMap = Record<string, [number, number]>;
9
+ type DelegatedHowlOptions = Omit<HowlOptions, 'src' | 'volume' | 'rate' | 'onload' | 'sprite'>;
10
+ export interface UseSoundOptions extends DelegatedHowlOptions {
11
+ file?: string | string[];
12
+ type?: BuiltInSoundType;
13
+ id?: string;
14
+ volume?: number;
15
+ playbackRate?: number;
16
+ interrupt?: boolean;
17
+ soundEnabled?: boolean;
18
+ sprite?: SpriteMap;
19
+ onload?: (this: Howl) => void;
20
+ }
21
+ export interface PlayOptions {
22
+ id?: string;
23
+ forceSoundEnabled?: boolean;
24
+ playbackRate?: number;
25
+ }
26
+ export type PlayFunction = (options?: PlayOptions) => void;
27
+ export interface ExposedData {
28
+ sound: Howl | null;
29
+ stop: (id?: number) => void;
30
+ pause: (id?: number) => void;
31
+ duration: number | null;
32
+ mode: 'file' | 'generated';
33
+ }
34
+ export type ReturnedValue = [PlayFunction, ExposedData];
35
+ export default function useSound({ file, type, id, volume, playbackRate, soundEnabled, interrupt, sprite, onload, ...delegated }?: UseSoundOptions): ReturnedValue;
36
+ export { useSound };
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAG/C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,kBAAkB,CAAC,EAAE,OAAO,YAAY,CAAA;KACzC;CACF;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,YAAY,GAAG,MAAM,CAAA;AAE9D,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAExD,KAAK,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAA;AAE9F,MAAM,WAAW,eAAgB,SAAQ,oBAAoB;IAC3D,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,IAAI,CAAC,EAAE,gBAAgB,CAAA;IACvB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;AAE1D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,GAAG,IAAI,CAAA;IAClB,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;CAC3B;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;AAwCvD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,IAAI,EACJ,IAAc,EACd,EAAE,EACF,MAAU,EACV,YAAgB,EAChB,YAAmB,EACnB,SAAiB,EACjB,MAAM,EACN,MAAM,EACN,GAAG,SAAS,EACb,GAAE,eAAoB,GAAG,aAAa,CA6NtC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,201 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ const GENERATED_PROFILES = {
3
+ click: {
4
+ filterHz: 5000,
5
+ decaySeconds: 0.015,
6
+ gain: 0.6,
7
+ noiseSeconds: 0.02,
8
+ },
9
+ 'soft-click': {
10
+ filterHz: 3200,
11
+ decaySeconds: 0.02,
12
+ gain: 0.35,
13
+ noiseSeconds: 0.018,
14
+ },
15
+ tick: {
16
+ filterHz: 6400,
17
+ decaySeconds: 0.01,
18
+ gain: 0.48,
19
+ noiseSeconds: 0.012,
20
+ },
21
+ };
22
+ const defaultProfile = GENERATED_PROFILES.click;
23
+ function isBrowser() {
24
+ return typeof window !== 'undefined';
25
+ }
26
+ function toArray(src) {
27
+ return Array.isArray(src) ? src : [src];
28
+ }
29
+ export default function useSound({ file, type = 'click', id, volume = 1, playbackRate = 1, soundEnabled = true, interrupt = false, sprite, onload, ...delegated } = {}) {
30
+ const [sound, setSound] = useState(null);
31
+ const [duration, setDuration] = useState(null);
32
+ const isMountedRef = useRef(false);
33
+ const audioCtxRef = useRef(null);
34
+ const mode = file ? 'file' : 'generated';
35
+ const generatedProfile = useMemo(() => GENERATED_PROFILES[type] ?? defaultProfile, [type]);
36
+ const closeAudioContext = useCallback(() => {
37
+ if (audioCtxRef.current && audioCtxRef.current.state !== 'closed') {
38
+ void audioCtxRef.current.close();
39
+ }
40
+ audioCtxRef.current = null;
41
+ }, []);
42
+ const playGenerated = useCallback(() => {
43
+ if (!isBrowser() || !soundEnabled) {
44
+ return;
45
+ }
46
+ const AudioContextClass = window.AudioContext ?? window.webkitAudioContext;
47
+ if (!AudioContextClass) {
48
+ return;
49
+ }
50
+ if (!audioCtxRef.current) {
51
+ audioCtxRef.current = new AudioContextClass();
52
+ }
53
+ const ctx = audioCtxRef.current;
54
+ if (ctx.state === 'suspended') {
55
+ void ctx.resume();
56
+ }
57
+ const bufferSize = Math.max(1, Math.floor(ctx.sampleRate * generatedProfile.noiseSeconds));
58
+ const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
59
+ const data = buffer.getChannelData(0);
60
+ for (let i = 0; i < bufferSize; i += 1) {
61
+ data[i] = Math.random() * 2 - 1;
62
+ }
63
+ const now = ctx.currentTime;
64
+ const noise = ctx.createBufferSource();
65
+ const filter = ctx.createBiquadFilter();
66
+ const gainNode = ctx.createGain();
67
+ noise.buffer = buffer;
68
+ filter.type = 'bandpass';
69
+ filter.frequency.value = generatedProfile.filterHz;
70
+ gainNode.gain.setValueAtTime(generatedProfile.gain * volume, now);
71
+ gainNode.gain.exponentialRampToValueAtTime(0.01, now + generatedProfile.decaySeconds);
72
+ noise.connect(filter);
73
+ filter.connect(gainNode);
74
+ gainNode.connect(ctx.destination);
75
+ noise.start(now);
76
+ }, [generatedProfile, soundEnabled, volume]);
77
+ useEffect(() => {
78
+ if (!file || !isBrowser()) {
79
+ setSound(null);
80
+ setDuration(null);
81
+ return;
82
+ }
83
+ let cancelled = false;
84
+ isMountedRef.current = true;
85
+ const initialize = async () => {
86
+ const mod = await import('howler');
87
+ if (cancelled || !isMountedRef.current) {
88
+ return;
89
+ }
90
+ const nextSound = new mod.Howl({
91
+ src: toArray(file),
92
+ volume,
93
+ rate: playbackRate,
94
+ sprite,
95
+ onload: function onLoad() {
96
+ if (typeof onload === 'function') {
97
+ onload.call(this);
98
+ }
99
+ if (!cancelled && isMountedRef.current) {
100
+ setDuration(this.duration() * 1000);
101
+ setSound(this);
102
+ }
103
+ },
104
+ ...delegated,
105
+ });
106
+ if (!cancelled && isMountedRef.current) {
107
+ setSound(nextSound);
108
+ }
109
+ };
110
+ void initialize();
111
+ return () => {
112
+ cancelled = true;
113
+ isMountedRef.current = false;
114
+ setDuration(null);
115
+ setSound((current) => {
116
+ current?.unload();
117
+ return null;
118
+ });
119
+ };
120
+ }, [file, onload, playbackRate, sprite, volume, delegated]);
121
+ useEffect(() => {
122
+ if (!file) {
123
+ return;
124
+ }
125
+ if (sound) {
126
+ sound.volume(volume);
127
+ if (!sprite) {
128
+ sound.rate(playbackRate);
129
+ }
130
+ }
131
+ }, [file, sound, volume, playbackRate, sprite]);
132
+ useEffect(() => {
133
+ if (file || !soundEnabled || !isBrowser()) {
134
+ return;
135
+ }
136
+ const onMouseDown = () => {
137
+ playGenerated();
138
+ };
139
+ document.addEventListener('mousedown', onMouseDown);
140
+ return () => {
141
+ document.removeEventListener('mousedown', onMouseDown);
142
+ };
143
+ }, [file, playGenerated, soundEnabled]);
144
+ useEffect(() => {
145
+ if (file) {
146
+ return;
147
+ }
148
+ return () => {
149
+ closeAudioContext();
150
+ };
151
+ }, [closeAudioContext, file]);
152
+ const play = useCallback((options) => {
153
+ const currentOptions = options ?? {};
154
+ if (mode === 'generated') {
155
+ if (!soundEnabled && !currentOptions.forceSoundEnabled) {
156
+ return;
157
+ }
158
+ playGenerated();
159
+ return;
160
+ }
161
+ if (!sound || (!soundEnabled && !currentOptions.forceSoundEnabled)) {
162
+ return;
163
+ }
164
+ if (interrupt) {
165
+ sound.stop();
166
+ }
167
+ if (typeof currentOptions.playbackRate === 'number') {
168
+ sound.rate(currentOptions.playbackRate);
169
+ }
170
+ sound.play(currentOptions.id ?? id);
171
+ }, [id, interrupt, mode, playGenerated, sound, soundEnabled]);
172
+ const stop = useCallback((playId) => {
173
+ if (mode === 'generated') {
174
+ closeAudioContext();
175
+ return;
176
+ }
177
+ if (sound) {
178
+ sound.stop(playId);
179
+ }
180
+ }, [closeAudioContext, mode, sound]);
181
+ const pause = useCallback((playId) => {
182
+ if (mode === 'generated') {
183
+ return;
184
+ }
185
+ if (sound) {
186
+ sound.pause(playId);
187
+ }
188
+ }, [mode, sound]);
189
+ return [
190
+ play,
191
+ {
192
+ sound,
193
+ stop,
194
+ pause,
195
+ duration,
196
+ mode,
197
+ },
198
+ ];
199
+ }
200
+ export { useSound };
201
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAmDzE,MAAM,kBAAkB,GAA+C;IACrE,KAAK,EAAE;QACL,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,KAAK;QACnB,IAAI,EAAE,GAAG;QACT,YAAY,EAAE,IAAI;KACnB;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,KAAK;KACpB;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,KAAK;KACpB;CACF,CAAA;AAED,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAA;AAE/C,SAAS,SAAS;IAChB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAA;AACtC,CAAC;AAED,SAAS,OAAO,CAAC,GAAsB;IACrC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,IAAI,EACJ,IAAI,GAAG,OAAO,EACd,EAAE,EACF,MAAM,GAAG,CAAC,EACV,YAAY,GAAG,CAAC,EAChB,YAAY,GAAG,IAAI,EACnB,SAAS,GAAG,KAAK,EACjB,MAAM,EACN,MAAM,EACN,GAAG,SAAS,KACO,EAAE;IACrB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAc,IAAI,CAAC,CAAA;IACrD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IAE7D,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAClC,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAA;IAErD,MAAM,IAAI,GAAwB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAA;IAE7D,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAE1F,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;QACzC,IAAI,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClE,KAAK,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAClC,CAAC;QACD,WAAW,CAAC,OAAO,GAAG,IAAI,CAAA;IAC5B,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;QACrC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,OAAM;QACR,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,kBAAkB,CAAA;QAC1E,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,WAAW,CAAC,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAA;QAC/C,CAAC;QAED,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAA;QAE/B,IAAI,GAAG,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAC9B,KAAK,GAAG,CAAC,MAAM,EAAE,CAAA;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;QAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;QACjC,CAAC;QAED,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAA;QAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,kBAAkB,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,EAAE,CAAA;QACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;QAEjC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;QACrB,MAAM,CAAC,IAAI,GAAG,UAAU,CAAA;QACxB,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAA;QAElD,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,IAAI,GAAG,MAAM,EAAE,GAAG,CAAC,CAAA;QACjE,QAAQ,CAAC,IAAI,CAAC,4BAA4B,CAAC,IAAI,EAAE,GAAG,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;QAErF,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACrB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAEjC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,CAAC,EAAE,CAAC,gBAAgB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,CAAA;YACd,WAAW,CAAC,IAAI,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,YAAY,CAAC,OAAO,GAAG,IAAI,CAAA;QAE3B,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;YAC5B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;YAClC,IAAI,SAAS,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;gBACvC,OAAM;YACR,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;gBAC7B,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC;gBAClB,MAAM;gBACN,IAAI,EAAE,YAAY;gBAClB,MAAM;gBACN,MAAM,EAAE,SAAS,MAAM;oBACrB,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;wBACjC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oBACnB,CAAC;oBAED,IAAI,CAAC,SAAS,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBACvC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAA;wBACnC,QAAQ,CAAC,IAAI,CAAC,CAAA;oBAChB,CAAC;gBACH,CAAC;gBACD,GAAG,SAAS;aACb,CAAC,CAAA;YAEF,IAAI,CAAC,SAAS,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;gBACvC,QAAQ,CAAC,SAAS,CAAC,CAAA;YACrB,CAAC;QACH,CAAC,CAAA;QAED,KAAK,UAAU,EAAE,CAAA;QAEjB,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;YAChB,YAAY,CAAC,OAAO,GAAG,KAAK,CAAA;YAC5B,WAAW,CAAC,IAAI,CAAC,CAAA;YACjB,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE;gBACnB,OAAO,EAAE,MAAM,EAAE,CAAA;gBACjB,OAAO,IAAI,CAAA;YACb,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;IAE3D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAM;QACR,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACpB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAC1C,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,EAAE;YACvB,aAAa,EAAE,CAAA;QACjB,CAAC,CAAA;QAED,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QAEnD,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QACxD,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAA;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,EAAE,CAAC;YACT,OAAM;QACR,CAAC;QAED,OAAO,GAAG,EAAE;YACV,iBAAiB,EAAE,CAAA;QACrB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAA;IAE7B,MAAM,IAAI,GAAiB,WAAW,CACpC,CAAC,OAAO,EAAE,EAAE;QACV,MAAM,cAAc,GAAgB,OAAO,IAAI,EAAE,CAAA;QAEjD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,IAAI,CAAC,cAAc,CAAC,iBAAiB,EAAE,CAAC;gBACvD,OAAM;YACR,CAAC;YACD,aAAa,EAAE,CAAA;YACf,OAAM;QACR,CAAC;QAED,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACnE,OAAM;QACR,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,EAAE,CAAA;QACd,CAAC;QAED,IAAI,OAAO,cAAc,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAA;QACzC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IACrC,CAAC,EACD,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,CAAC,CAC1D,CAAA;IAED,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,MAAe,EAAE,EAAE;QAClB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,iBAAiB,EAAE,CAAA;YACnB,OAAM;QACR,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpB,CAAC;IACH,CAAC,EACD,CAAC,iBAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,CACjC,CAAA;IAED,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,MAAe,EAAE,EAAE;QAClB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,OAAM;QACR,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,EACD,CAAC,IAAI,EAAE,KAAK,CAAC,CACd,CAAA;IAED,OAAO;QACL,IAAI;QACJ;YACE,KAAK;YACL,IAAI;YACJ,KAAK;YACL,QAAQ;YACR,IAAI;SACL;KACF,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "zsk-use-sound",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "keywords": [
6
+ "npm-package",
7
+ "react",
8
+ "sounds",
9
+ "typescript"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/sk-izsk/zsk-react-error.git"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ }
28
+ },
29
+ "scripts": {
30
+ "build": "bunx tsc -p tsconfig.json",
31
+ "lint": "oxlint . --config .oxlintrc.json",
32
+ "lint:fix": "oxlint . --fix --config .oxlintrc.json",
33
+ "format": "oxfmt . --config .oxfmtrc.json --write",
34
+ "format:check": "oxfmt . --config .oxfmtrc.json --check",
35
+ "typecheck": "bunx tsc --noEmit",
36
+ "clean": "rm -rf dist",
37
+ "verify": "bun run format && bun run lint && bun run typecheck && bun run clean && bun run build && npm pack --dry-run",
38
+ "prepublishOnly": "bun run verify",
39
+ "publish:release": "bun publish",
40
+ "release": "bun run verify && bun publish"
41
+ },
42
+ "dependencies": {
43
+ "howler": "^2.2.4"
44
+ },
45
+ "devDependencies": {
46
+ "@types/howler": "^2.2.12",
47
+ "@types/node": "^25.6.0",
48
+ "@types/react": "^19.2.14",
49
+ "oxfmt": "^0.44.0",
50
+ "oxlint": "^1.59.0",
51
+ "react": "^19.2.5",
52
+ "react-dom": "^19.2.5",
53
+ "typescript": "^6.0.2"
54
+ },
55
+ "peerDependencies": {
56
+ "react": ">=18"
57
+ },
58
+ "packageManager": "bun@1.2.5"
59
+ }