UNPKG

use-sound

Version:

### A React Hook for Sound Effects

172 lines (142 loc) 4.93 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } function _interopNamespace(e) { if (e && e.__esModule) { return e; } else { var n = {}; if (e) { Object.keys(e).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); }); } n['default'] = e; return n; } } var React = require('react'); var React__default = _interopDefault(React); function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function useOnMount(callback) { React.useEffect(callback, []); } function useSound(url, _ref) { if (_ref === void 0) { _ref = {}; } var _ref2 = _ref, _ref2$volume = _ref2.volume, volume = _ref2$volume === void 0 ? 1 : _ref2$volume, _ref2$playbackRate = _ref2.playbackRate, playbackRate = _ref2$playbackRate === void 0 ? 1 : _ref2$playbackRate, _ref2$soundEnabled = _ref2.soundEnabled, soundEnabled = _ref2$soundEnabled === void 0 ? true : _ref2$soundEnabled, _ref2$interrupt = _ref2.interrupt, interrupt = _ref2$interrupt === void 0 ? false : _ref2$interrupt, delegated = _objectWithoutPropertiesLoose(_ref2, ["volume", "playbackRate", "soundEnabled", "interrupt"]); var HowlConstructor = React__default.useRef(null); var _React$useState = React__default.useState(false), isPlaying = _React$useState[0], setIsPlaying = _React$useState[1]; var _React$useState2 = React__default.useState(null), sound = _React$useState2[0], setSound = _React$useState2[1]; // We want to lazy-load Howler, since sounds can't play on load anyway. useOnMount(function () { new Promise(function (resolve) { resolve(_interopNamespace(require('howler'))); }).then(function (mod) { HowlConstructor.current = mod.Howl; var sound = new HowlConstructor.current(_extends({ src: [url], volume: volume }, delegated)); setSound(sound); }); }); // When the URL changes, we have to do a whole thing where we recreate // the Howl instance. This is because Howler doesn't expose a way to // tweak the sound React__default.useEffect(function () { if (HowlConstructor.current && sound) { setSound(new HowlConstructor.current(_extends({ src: [url], volume: volume }, delegated))); } // The linter wants to run this effect whenever ANYTHING changes, // but very specifically I only want to recreate the Howl instance // when the `url` changes. Other changes should have no effect. // eslint-disable-next-line react-hooks/exhaustive-deps }, [url]); // Whenever volume/playbackRate are changed, change those properties // on the sound instance. React__default.useEffect(function () { if (sound) { sound.volume(volume); sound.rate(playbackRate); } // A weird bug means that including the `sound` here can trigger an // error on unmount, where the state loses track of the sprites?? // No idea, but anyway I don't need to re-run this if only the `sound` // changes. // eslint-disable-next-line react-hooks/exhaustive-deps }, [volume, playbackRate]); var play = React__default.useCallback(function (options) { if (options === void 0) { options = {}; } if (!sound || !soundEnabled && !options.forceSoundEnabled) { return; } if (interrupt) { sound.stop(); } if (options.playbackRate) { sound.rate(options.playbackRate); } sound.play(options.id); sound.once('end', function () { return setIsPlaying(false); }); setIsPlaying(true); }, [sound, soundEnabled, interrupt]); var stop = React__default.useCallback(function () { if (!sound) { return; } sound.stop(); setIsPlaying(false); }, [sound]); var returnedValue = [play, { sound: sound, stop: stop, isPlaying: isPlaying }]; return returnedValue; } exports.default = useSound; //# sourceMappingURL=use-sound.cjs.development.js.map