soundz
Version:
Sound Effects Wrapper for Components.
496 lines (495 loc) • 15.8 kB
JavaScript
import be, { createContext as Ee, useEffect as ce, useContext as he, useState as ae, useRef as se, useCallback as fe } from "react";
import { Howl as le } from "howler";
import { Trophy as ye, AudioWaveform as ke, AudioLines as Re, Waves as Te, Volume2 as ge } from "lucide-react";
var V = { exports: {} }, W = {};
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var de;
function _e() {
if (de) return W;
de = 1;
var i = Symbol.for("react.transitional.element"), d = Symbol.for("react.fragment");
function a(p, s, u) {
var b = null;
if (u !== void 0 && (b = "" + u), s.key !== void 0 && (b = "" + s.key), "key" in s) {
u = {};
for (var y in s)
y !== "key" && (u[y] = s[y]);
} else u = s;
return s = u.ref, {
$$typeof: i,
type: p,
key: b,
ref: s !== void 0 ? s : null,
props: u
};
}
return W.Fragment = d, W.jsx = a, W.jsxs = a, W;
}
var z = {};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var pe;
function xe() {
return pe || (pe = 1, process.env.NODE_ENV !== "production" && function() {
function i(e) {
if (e == null) return null;
if (typeof e == "function")
return e.$$typeof === L ? null : e.displayName || e.name || null;
if (typeof e == "string") return e;
switch (e) {
case O:
return "Fragment";
case Q:
return "Profiler";
case U:
return "StrictMode";
case ee:
return "Suspense";
case re:
return "SuspenseList";
case N:
return "Activity";
}
if (typeof e == "object")
switch (typeof e.tag == "number" && console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
), e.$$typeof) {
case Z:
return "Portal";
case B:
return (e.displayName || "Context") + ".Provider";
case X:
return (e._context.displayName || "Context") + ".Consumer";
case K:
var r = e.render;
return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
case te:
return r = e.displayName || null, r !== null ? r : i(e.type) || "Memo";
case $:
r = e._payload, e = e._init;
try {
return i(e(r));
} catch {
}
}
return null;
}
function d(e) {
return "" + e;
}
function a(e) {
try {
d(e);
var r = !1;
} catch {
r = !0;
}
if (r) {
r = console;
var t = r.error, o = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
return t.call(
r,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
o
), d(e);
}
}
function p(e) {
if (e === O) return "<>";
if (typeof e == "object" && e !== null && e.$$typeof === $)
return "<...>";
try {
var r = i(e);
return r ? "<" + r + ">" : "<...>";
} catch {
return "<...>";
}
}
function s() {
var e = T.A;
return e === null ? null : e.getOwner();
}
function u() {
return Error("react-stack-top-frame");
}
function b(e) {
if (Y.call(e, "key")) {
var r = Object.getOwnPropertyDescriptor(e, "key").get;
if (r && r.isReactWarning) return !1;
}
return e.key !== void 0;
}
function y(e, r) {
function t() {
D || (D = !0, console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
r
));
}
t.isReactWarning = !0, Object.defineProperty(e, "key", {
get: t,
configurable: !0
});
}
function G() {
var e = i(this.type);
return F[e] || (F[e] = !0, console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
)), e = this.props.ref, e !== void 0 ? e : null;
}
function k(e, r, t, o, f, c, C, E) {
return t = c.ref, e = {
$$typeof: P,
type: e,
key: r,
props: c,
_owner: f
}, (t !== void 0 ? t : null) !== null ? Object.defineProperty(e, "ref", {
enumerable: !1,
get: G
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
configurable: !1,
enumerable: !1,
writable: !0,
value: 0
}), Object.defineProperty(e, "_debugInfo", {
configurable: !1,
enumerable: !1,
writable: !0,
value: null
}), Object.defineProperty(e, "_debugStack", {
configurable: !1,
enumerable: !1,
writable: !0,
value: C
}), Object.defineProperty(e, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: E
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
}
function R(e, r, t, o, f, c, C, E) {
var n = r.children;
if (n !== void 0)
if (o)
if (H(n)) {
for (o = 0; o < n.length; o++)
A(n[o]);
Object.freeze && Object.freeze(n);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else A(n);
if (Y.call(r, "key")) {
n = i(e);
var h = Object.keys(r).filter(function(oe) {
return oe !== "key";
});
o = 0 < h.length ? "{key: someKey, " + h.join(": ..., ") + ": ...}" : "{key: someKey}", q[n + o] || (h = 0 < h.length ? "{" + h.join(": ..., ") + ": ...}" : "{}", console.error(
`A props object containing a "key" prop is being spread into JSX:
let props = %s;
<%s {...props} />
React keys must be passed directly to JSX without using spread:
let props = %s;
<%s key={someKey} {...props} />`,
o,
n,
h,
n
), q[n + o] = !0);
}
if (n = null, t !== void 0 && (a(t), n = "" + t), b(r) && (a(r.key), n = "" + r.key), "key" in r) {
t = {};
for (var g in r)
g !== "key" && (t[g] = r[g]);
} else t = r;
return n && y(
t,
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
), k(
e,
n,
c,
f,
s(),
t,
C,
E
);
}
function A(e) {
typeof e == "object" && e !== null && e.$$typeof === P && e._store && (e._store.validated = 1);
}
var m = be, P = Symbol.for("react.transitional.element"), Z = Symbol.for("react.portal"), O = Symbol.for("react.fragment"), U = Symbol.for("react.strict_mode"), Q = Symbol.for("react.profiler"), X = Symbol.for("react.consumer"), B = Symbol.for("react.context"), K = Symbol.for("react.forward_ref"), ee = Symbol.for("react.suspense"), re = Symbol.for("react.suspense_list"), te = Symbol.for("react.memo"), $ = Symbol.for("react.lazy"), N = Symbol.for("react.activity"), L = Symbol.for("react.client.reference"), T = m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Y = Object.prototype.hasOwnProperty, H = Array.isArray, w = console.createTask ? console.createTask : function() {
return null;
};
m = {
"react-stack-bottom-frame": function(e) {
return e();
}
};
var D, F = {}, S = m["react-stack-bottom-frame"].bind(
m,
u
)(), J = w(p(u)), q = {};
z.Fragment = O, z.jsx = function(e, r, t, o, f) {
var c = 1e4 > T.recentlyCreatedOwnerStacks++;
return R(
e,
r,
t,
!1,
o,
f,
c ? Error("react-stack-top-frame") : S,
c ? w(p(e)) : J
);
}, z.jsxs = function(e, r, t, o, f) {
var c = 1e4 > T.recentlyCreatedOwnerStacks++;
return R(
e,
r,
t,
!0,
o,
f,
c ? Error("react-stack-top-frame") : S,
c ? w(p(e)) : J
);
};
}()), z;
}
var me;
function Se() {
return me || (me = 1, process.env.NODE_ENV === "production" ? V.exports = _e() : V.exports = xe()), V.exports;
}
var v = Se();
const Ce = (i, d) => {
const a = {
className: d ? "sound-indicator" : "",
size: i.size ?? 20,
strokeWidth: i.strokeWidth ?? 2.5
};
switch (i.name) {
case "speaker":
return /* @__PURE__ */ v.jsx(ge, { ...a });
case "waves":
return /* @__PURE__ */ v.jsx(Te, { ...a });
case "audioLines":
return /* @__PURE__ */ v.jsx(Re, { ...a });
case "audioWaves":
return /* @__PURE__ */ v.jsx(ke, { ...a });
case "trophy":
return /* @__PURE__ */ v.jsx(ye, { ...a });
default:
return null;
}
}, we = Ee({});
function Oe({ children: i, ...d }) {
return ce(() => {
const a = () => {
const p = new Audio();
p.muted = !0, p.play().catch(() => {
}), window.removeEventListener("click", a);
};
return window.addEventListener("click", a), () => window.removeEventListener("click", a);
}, []), /* @__PURE__ */ v.jsx(we.Provider, { value: d, children: i });
}
const ie = /* @__PURE__ */ new Map();
function $e(i) {
var ue;
const d = he(we), {
children: a,
providedFX: p = "boop",
customFX: s = null,
noClickSound: u = !1,
loading: b = null,
wrap: y = null,
fetchCooldown: G = 1e4,
clickCooldown: k = 0,
hoverFX: R = null,
enableHaptics: A = !0,
keyboardKey: m = null,
icon: P = null,
showTooltip: Z = !1,
tooltipText: O = "Now playing…",
tooltipPosition: U = "top",
tooltipAnimation: Q = "fade",
theme: X = "auto",
customTheme: B = null,
animationSpeed: K = "1s",
layout: ee = "inline-flex",
className: re = "",
style: te = {},
apiBaseUrl: $
} = { ...d, ...i }, [N, L] = ae(null), [T, Y] = ae(!0), [H, w] = ae(!1), D = se(0), F = se(0), S = se(null), J = typeof window < "u" && ((ue = window.matchMedia) == null ? void 0 : ue.call(window, "(prefers-color-scheme: dark)").matches), q = X === "auto" ? J ? "dark" : "light" : X, e = {
light: { tooltipBg: "#333", tooltipColor: "#fff", pulseColor: "#888" },
dark: { tooltipBg: "#000", tooltipColor: "#fff", pulseColor: "#fff" },
neon: { tooltipBg: "#0ff", tooltipColor: "#000", pulseColor: "#0ff" },
pastel: { tooltipBg: "#ffeef1", tooltipColor: "#222", pulseColor: "#ffaacc" },
mono: { tooltipBg: "#666", tooltipColor: "#eee", pulseColor: "#aaa" }
}, r = e[q] ?? e.light, t = B ? { ...r, ...B } : r, o = {
top: "translateX(-50%)",
bottom: "translateX(-50%)",
left: "translateY(-50%)",
right: "translateY(-50%)"
}, f = {
top: "top: -1.5rem; left: 50%;",
bottom: "bottom: -1.5rem; left: 50%;",
left: "left: -1.5rem; top: 50%;",
right: "right: -1.5rem; top: 50%;"
}, c = {
fade: "opacity 0.3s ease-in-out",
scale: "transform 0.3s ease-in-out",
slide: "top 0.3s ease-in-out"
}, C = y ?? `
.wrap,
.wrap:before,
.wrap:after {
margin: 0;
padding: 0;
}
.wrap {
position: relative;
display: ${ee};
align-items: center;
gap: 0.5rem;
border: none;
font-family: inherit;
cursor: pointer;
color: inherit;
background: transparent;
}
.wrap.disabled {
opacity: 0.5;
pointer-events: none;
}
.sound-indicator {
animation: pulse ${K} ease-in-out infinite;
color: ${t.pulseColor};
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.6; }
100% { transform: scale(1); opacity: 1; }
}
.tooltip {
position: absolute;
${f[U] || f.top}
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-family: inherit;
opacity: 0.9;
white-space: nowrap;
color: ${t.tooltipColor};
background: ${t.tooltipBg};
transform: ${o[U] || "translateX(-50%)"};
transition: ${c[Q] || c.fade};
}
`, E = p || "boop", n = fe((l) => {
if (!l) return;
const j = Date.now();
new le({
src: [`${l}?t=${j}`],
autoplay: !0,
onloaderror: (x, I) => console.error("Howler load error:", I),
onplay: () => w(!0),
onend: () => w(!1)
}).play(), A && window.navigator.vibrate && window.navigator.vibrate(50), k > 0 && (Y(!1), setTimeout(() => Y(!0), k));
}, [k, A]), h = async () => {
const l = Date.now();
if (s) {
ie.set("custom", s), L(s);
return;
}
const j = ie.get(E);
if (j && l - D.current < G) {
L(j);
return;
}
try {
const x = await fetch(`${$ || "https://soundzjs.vercel.app"}/api/sounds?sound=${E}`), I = x.headers.get("content-type");
if (!x.ok)
throw new Error(`Fetch failed: ${x.status} ${x.statusText}`);
if (!(I != null && I.includes("application/json"))) {
const ve = await x.text();
throw new Error(`Expected JSON, got: ${ve.slice(0, 100)}...`);
}
const M = await x.json();
M != null && M.url && (ie.set(E, M.url), L(M.url), D.current = l);
} catch (_) {
console.error("Sound fetch failed:", _);
}
};
ce(() => {
h();
const l = document.createElement("style");
return l.innerHTML = C, document.head.appendChild(l), S.current = l, () => {
S.current && document.head.removeChild(S.current);
};
}, [s, E, C]);
const g = () => {
if (!u) {
const l = Date.now();
if (!N || k > 0 && l - F.current < k) return;
F.current = l, n(N);
}
}, oe = () => {
const l = $ || "https://soundzjs.vercel.app";
R && (R.includes("/") ? new le({
src: [`${R}?t=${Date.now()}`],
autoplay: !0,
onloaderror: (j, _) => console.error("Howler load error:", _),
onplay: () => w(!0),
onend: () => w(!1)
}).play() : new le({
src: [`${l}/sounds/${R}.mp3?t=${Date.now()}`],
autoplay: !0,
onloaderror: (j, _) => console.error("Howler load error:", _),
onplay: () => w(!0),
onend: () => w(!1)
}).play());
}, ne = fe((l) => {
m && l.key.toLowerCase() === m.toLowerCase() && T && g();
}, [m, T, g]);
return ce(() => {
if (m)
return window.addEventListener("keydown", ne), () => window.removeEventListener("keydown", ne);
}, [m, ne]), N ? /* @__PURE__ */ v.jsxs(
"div",
{
className: `wrap ${T ? "" : "disabled"} ${re}`,
onClick: g,
onMouseEnter: oe,
style: te,
tabIndex: 0,
children: [
H && Z && /* @__PURE__ */ v.jsx("div", { className: "tooltip", children: O }),
P && Ce(P, H),
a
]
}
) : b ? b() : /* @__PURE__ */ v.jsx("p", { children: "Loading sound…" });
}
export {
$e as Soundz,
Oe as SoundzProvider
};