react-night-light
Version:
A React component that simulates a night light with pull-to-toggle functionality
814 lines (813 loc) • 23 kB
JavaScript
import se, { useState as ie, useRef as C, useCallback as L, useEffect as te } from "react";
import { useSpring as V, config as ae, animated as M } from "@react-spring/web";
var K = { exports: {} }, Y = {};
/**
* @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 re;
function le() {
if (re) return Y;
re = 1;
var d = Symbol.for("react.transitional.element"), m = Symbol.for("react.fragment");
function b(l, a, u) {
var y = null;
if (u !== void 0 && (y = "" + u), a.key !== void 0 && (y = "" + a.key), "key" in a) {
u = {};
for (var j in a)
j !== "key" && (u[j] = a[j]);
} else u = a;
return a = u.ref, {
$$typeof: d,
type: l,
key: y,
ref: a !== void 0 ? a : null,
props: u
};
}
return Y.Fragment = m, Y.jsx = b, Y.jsxs = b, Y;
}
var I = {};
/**
* @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 ne;
function ce() {
return ne || (ne = 1, process.env.NODE_ENV !== "production" && function() {
function d(e) {
if (e == null) return null;
if (typeof e == "function")
return e.$$typeof === N ? null : e.displayName || e.name || null;
if (typeof e == "string") return e;
switch (e) {
case k:
return "Fragment";
case f:
return "Profiler";
case g:
return "StrictMode";
case T:
return "Suspense";
case A:
return "SuspenseList";
case W:
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 $:
return "Portal";
case B:
return (e.displayName || "Context") + ".Provider";
case H:
return (e._context.displayName || "Context") + ".Consumer";
case Q:
var r = e.render;
return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
case F:
return r = e.displayName || null, r !== null ? r : d(e.type) || "Memo";
case R:
r = e._payload, e = e._init;
try {
return d(e(r));
} catch {
}
}
return null;
}
function m(e) {
return "" + e;
}
function b(e) {
try {
m(e);
var r = !1;
} catch {
r = !0;
}
if (r) {
r = console;
var o = r.error, s = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
return o.call(
r,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
s
), m(e);
}
}
function l(e) {
if (e === k) return "<>";
if (typeof e == "object" && e !== null && e.$$typeof === R)
return "<...>";
try {
var r = d(e);
return r ? "<" + r + ">" : "<...>";
} catch {
return "<...>";
}
}
function a() {
var e = c.A;
return e === null ? null : e.getOwner();
}
function u() {
return Error("react-stack-top-frame");
}
function y(e) {
if (G.call(e, "key")) {
var r = Object.getOwnPropertyDescriptor(e, "key").get;
if (r && r.isReactWarning) return !1;
}
return e.key !== void 0;
}
function j(e, r) {
function o() {
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
));
}
o.isReactWarning = !0, Object.defineProperty(e, "key", {
get: o,
configurable: !0
});
}
function z() {
var e = d(this.type);
return U[e] || (U[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 S(e, r, o, s, w, x, J, X) {
return o = x.ref, e = {
$$typeof: _,
type: e,
key: r,
props: x,
_owner: w
}, (o !== void 0 ? o : null) !== null ? Object.defineProperty(e, "ref", {
enumerable: !1,
get: z
}) : 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: J
}), Object.defineProperty(e, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: X
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
}
function E(e, r, o, s, w, x, J, X) {
var i = r.children;
if (i !== void 0)
if (s)
if (q(i)) {
for (s = 0; s < i.length; s++)
p(i[s]);
Object.freeze && Object.freeze(i);
} 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 p(i);
if (G.call(r, "key")) {
i = d(e);
var O = Object.keys(r).filter(function(oe) {
return oe !== "key";
});
s = 0 < O.length ? "{key: someKey, " + O.join(": ..., ") + ": ...}" : "{key: someKey}", ee[i + s] || (O = 0 < O.length ? "{" + O.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} />`,
s,
i,
O,
i
), ee[i + s] = !0);
}
if (i = null, o !== void 0 && (b(o), i = "" + o), y(r) && (b(r.key), i = "" + r.key), "key" in r) {
o = {};
for (var Z in r)
Z !== "key" && (o[Z] = r[Z]);
} else o = r;
return i && j(
o,
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
), S(
e,
i,
x,
w,
a(),
o,
J,
X
);
}
function p(e) {
typeof e == "object" && e !== null && e.$$typeof === _ && e._store && (e._store.validated = 1);
}
var v = se, _ = Symbol.for("react.transitional.element"), $ = Symbol.for("react.portal"), k = Symbol.for("react.fragment"), g = Symbol.for("react.strict_mode"), f = Symbol.for("react.profiler"), H = Symbol.for("react.consumer"), B = Symbol.for("react.context"), Q = Symbol.for("react.forward_ref"), T = Symbol.for("react.suspense"), A = Symbol.for("react.suspense_list"), F = Symbol.for("react.memo"), R = Symbol.for("react.lazy"), W = Symbol.for("react.activity"), N = Symbol.for("react.client.reference"), c = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, G = Object.prototype.hasOwnProperty, q = Array.isArray, P = console.createTask ? console.createTask : function() {
return null;
};
v = {
"react-stack-bottom-frame": function(e) {
return e();
}
};
var D, U = {}, n = v["react-stack-bottom-frame"].bind(
v,
u
)(), h = P(l(u)), ee = {};
I.Fragment = k, I.jsx = function(e, r, o, s, w) {
var x = 1e4 > c.recentlyCreatedOwnerStacks++;
return E(
e,
r,
o,
!1,
s,
w,
x ? Error("react-stack-top-frame") : n,
x ? P(l(e)) : h
);
}, I.jsxs = function(e, r, o, s, w) {
var x = 1e4 > c.recentlyCreatedOwnerStacks++;
return E(
e,
r,
o,
!0,
s,
w,
x ? Error("react-stack-top-frame") : n,
x ? P(l(e)) : h
);
};
}()), I;
}
process.env.NODE_ENV === "production" ? K.exports = le() : K.exports = ce();
var t = K.exports;
const ue = () => /* @__PURE__ */ t.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 150 180", children: [
/* @__PURE__ */ t.jsx("defs", { children: /* @__PURE__ */ t.jsxs(
"radialGradient",
{
id: "bulbOffGradient",
cx: "50%",
cy: "50%",
r: "50%",
fx: "45%",
fy: "40%",
children: [
/* @__PURE__ */ t.jsx("stop", { offset: "0%", stopColor: "#f8f8f8" }),
/* @__PURE__ */ t.jsx("stop", { offset: "60%", stopColor: "#e0e0e0" }),
/* @__PURE__ */ t.jsx("stop", { offset: "100%", stopColor: "#b0b0b0" })
]
}
) }),
/* @__PURE__ */ t.jsx(
"circle",
{
cx: "75",
cy: "72",
r: "50",
fill: "url(#bulbOffGradient)",
stroke: "#ccc",
strokeWidth: "1.5"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M62,0 L88,0 L88,22 L62,22 Z",
fill: "#d0d0d0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "65",
y: "22",
width: "20",
height: "10",
fill: "#d0d0d0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "67",
y: "32",
width: "16",
height: "10",
fill: "#c0c0c0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M67,40 Q75,48 83,40",
stroke: "#888",
strokeWidth: "2",
fill: "none"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M55,92 Q70,107 95,102",
stroke: "#888",
strokeWidth: "1.5",
fill: "none"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M90,52 Q100,57 95,67",
stroke: "#d6d6d6",
strokeWidth: "1.5",
fill: "none"
}
)
] }), fe = () => /* @__PURE__ */ t.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 150 180", children: [
/* @__PURE__ */ t.jsx("defs", { children: /* @__PURE__ */ t.jsxs(
"radialGradient",
{
id: "bulbOnGradient",
cx: "0.5",
cy: "0.5",
r: "0.5",
fx: "0.45",
fy: "0.45",
children: [
/* @__PURE__ */ t.jsx("stop", { offset: "0%", stopColor: "#fffef0" }),
/* @__PURE__ */ t.jsx("stop", { offset: "50%", stopColor: "#fff8d0" }),
/* @__PURE__ */ t.jsx("stop", { offset: "100%", stopColor: "#ffeeaa" })
]
}
) }),
/* @__PURE__ */ t.jsx(
"circle",
{
cx: "75",
cy: "72",
r: "50",
fill: "url(#bulbOnGradient)",
stroke: "#e5ca80",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M62,0 L88,0 L88,22 L62,22 Z",
fill: "#d0d0d0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "65",
y: "22",
width: "20",
height: "10",
fill: "#d0d0d0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "67",
y: "32",
width: "16",
height: "10",
fill: "#c0c0c0",
stroke: "#bbb",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M67,40 Q75,48 83,40",
stroke: "#ffb84d",
strokeWidth: "2",
fill: "none"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M55,92 Q70,107 95,102",
stroke: "#ca9",
strokeWidth: "1.5",
fill: "none"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M90,52 Q100,57 95,67",
stroke: "#fff",
strokeWidth: "2",
fill: "none",
opacity: "0.8"
}
),
/* @__PURE__ */ t.jsx(
"line",
{
x1: "75",
y1: "30",
x2: "75",
y2: "45",
stroke: "rgba(255, 255, 200, 0.8)",
strokeWidth: "1.5"
}
),
/* @__PURE__ */ t.jsx(
"line",
{
x1: "100",
y1: "47",
x2: "85",
y2: "47",
stroke: "rgba(255, 255, 200, 0.8)",
strokeWidth: "1.5"
}
),
/* @__PURE__ */ t.jsx(
"line",
{
x1: "50",
y1: "47",
x2: "65",
y2: "47",
stroke: "rgba(255, 255, 200, 0.8)",
strokeWidth: "1.5"
}
)
] }), de = () => /* @__PURE__ */ t.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 30 60", children: [
/* @__PURE__ */ t.jsx(
"rect",
{
x: "7",
y: "2",
width: "20",
height: "50",
rx: "5",
ry: "5",
fill: "#888",
opacity: "0.3"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "5",
y: "0",
width: "20",
height: "50",
rx: "5",
ry: "5",
fill: "#bbb",
stroke: "#999",
strokeWidth: "1"
}
),
/* @__PURE__ */ t.jsx(
"rect",
{
x: "7",
y: "5",
width: "16",
height: "40",
rx: "3",
ry: "3",
fill: "#aaa",
stroke: "#999",
strokeWidth: "0.5"
}
),
/* @__PURE__ */ t.jsx("rect", { x: "10", y: "10", width: "10", height: "30", rx: "2", ry: "2", fill: "#999" }),
/* @__PURE__ */ t.jsx("line", { x1: "13", y1: "15", x2: "17", y2: "15", stroke: "#777", strokeWidth: "1.5" }),
/* @__PURE__ */ t.jsx("line", { x1: "13", y1: "20", x2: "17", y2: "20", stroke: "#777", strokeWidth: "1.5" }),
/* @__PURE__ */ t.jsx("line", { x1: "13", y1: "25", x2: "17", y2: "25", stroke: "#777", strokeWidth: "1.5" }),
/* @__PURE__ */ t.jsx("line", { x1: "13", y1: "30", x2: "17", y2: "30", stroke: "#777", strokeWidth: "1.5" }),
/* @__PURE__ */ t.jsx(
"line",
{
x1: "9",
y1: "10",
x2: "9",
y2: "40",
stroke: "#ccc",
strokeWidth: "0.75",
opacity: "0.6"
}
)
] });
function me({
isOn: d,
onToggle: m,
wireColor: b = "#888",
maxPullDistance: l = 90,
initialWireLength: a = 30,
className: u = "",
ref: y
// React 19 allows ref as a direct prop
}) {
const [j, z] = ie(!1), S = d !== void 0, E = S ? d : j, p = C(!1), v = C(0), _ = C(null), $ = l * 0.6, k = C(!1), [{ y: g }, f] = V(() => ({
y: 0,
config: { ...ae.gentle, tension: 170, friction: 26 },
immediate: !1,
onRest: () => {
const n = g.get();
(n > l || n < 0) && f.start({ y: 0 });
}
})), H = V({
config: { mass: 1, tension: 120, friction: 14 }
}), B = V({
opacity: E ? 1 : 0,
config: { mass: 1, tension: 120, friction: 14 }
}), Q = V({
opacity: E ? 0 : 1,
config: { mass: 1, tension: 120, friction: 14 }
}), T = C(null), A = () => {
T.current !== null && (window.clearTimeout(T.current), T.current = null);
}, F = L(
(n) => {
if ("touches" in n) {
const h = n.target;
_.current && _.current.contains(h) && (n.preventDefault(), p.current = !0, k.current = !0, v.current = n.touches[0].clientY);
} else
n.preventDefault(), p.current = !0, k.current = !0, v.current = n.clientY;
},
[]
), R = L(
(n) => {
if (!p.current) return;
A();
const h = Math.max(
0,
Math.min(l, n - v.current)
);
f.start({ y: h, immediate: !0 });
},
[f, l]
), W = L(
(n) => {
R(n.clientY);
},
[R]
), N = L(
(n) => {
p.current && k.current && (n.preventDefault(), R(n.touches[0].clientY));
},
[R]
), c = L(() => {
if (!p.current) return;
p.current = !1, k.current = !1, A();
let n;
try {
n = g.get(), (isNaN(n) || !isFinite(n)) && (n = 0), n = Math.max(0, Math.min(l, n));
} catch {
n = 0;
}
if (f.stop(), n > $) {
const h = !E;
S || z(h), m == null || m(h);
}
f.start({
y: 0,
immediate: !1,
config: {
mass: 1,
tension: 180,
friction: 20,
// Use very minimal velocity to avoid extreme spring effects
velocity: 0,
clamp: !0,
// Clamp to prevent overshoot
bounce: 0
}
}), T.current = window.setTimeout(() => {
f.start({ y: 0, immediate: !1 });
}, 500);
}, [f, E, S, m, $, g, l]);
te(() => () => {
A(), f.stop();
}, [f]), te(() => (window.addEventListener("mousemove", W), window.addEventListener("mouseup", c), window.addEventListener("touchmove", N, {
passive: !1
// Need non-passive to be able to preventDefault only when needed
}), window.addEventListener("touchend", c), window.addEventListener("mouseleave", c), window.addEventListener("blur", c), () => {
window.removeEventListener("mousemove", W), window.removeEventListener("mouseup", c), window.removeEventListener("touchmove", N), window.removeEventListener("touchend", c), window.removeEventListener("mouseleave", c), window.removeEventListener("blur", c);
}), [W, c, N]);
const G = 140, q = a, P = 40, D = l, U = G + q + P + D;
return (
// @ts-ignore - React-spring has issues with TypeScript in React 19
/* @__PURE__ */ t.jsxs(
M.div,
{
ref: y,
className: u,
style: {
...H,
width: "150px",
// Default width that fits the components
height: `${U}px`,
position: "relative",
overflow: "visible",
// Allow handle to extend beyond container
display: "flex",
justifyContent: "flex-start",
// Align from left instead of center
alignItems: "flex-start"
// Align from top
},
children: [
/* @__PURE__ */ t.jsxs(
"div",
{
style: {
position: "absolute",
width: "120px",
height: "140px",
left: 0,
// Position at left
top: 0
// Start from top
},
children: [
/* @__PURE__ */ t.jsx(
M.div,
{
style: {
...Q,
position: "absolute",
top: 0,
left: 0,
width: "100%"
},
children: /* @__PURE__ */ t.jsx(ue, {})
}
),
/* @__PURE__ */ t.jsx(
M.div,
{
style: {
...B,
position: "absolute",
top: 0,
left: 0,
width: "100%"
},
children: /* @__PURE__ */ t.jsx(fe, {})
}
)
]
}
),
/* @__PURE__ */ t.jsxs(
"div",
{
style: {
position: "absolute",
display: "flex",
flexDirection: "column",
alignItems: "center",
top: 0,
// Position at the top of container
right: 0
// Position at the right side of the container
},
children: [
/* @__PURE__ */ t.jsx(
"div",
{
style: {
height: a,
width: 2,
background: b,
margin: "0 auto"
}
}
),
/* @__PURE__ */ t.jsx(
"div",
{
style: {
position: "relative",
height: 0,
margin: 0,
padding: 0
},
children: /* @__PURE__ */ t.jsx(
M.div,
{
style: {
position: "absolute",
top: 0,
left: "50%",
marginLeft: -1,
height: g,
width: 2,
background: b,
transformOrigin: "top"
}
}
)
}
),
/* @__PURE__ */ t.jsxs(
M.div,
{
ref: _,
style: {
y: g,
width: "30px",
height: "40px",
display: "flex",
justifyContent: "center",
alignItems: "flex-start",
// Align to top to connect with wire
cursor: "grab",
zIndex: 10,
touchAction: "none",
// Use none specifically for the handle to prevent scrolling when interacting with it
// Connect handle to wire
marginTop: 0
},
onMouseDown: F,
onTouchStart: F,
children: [
/* @__PURE__ */ t.jsx(
"div",
{
style: {
position: "absolute",
top: 0,
left: "50%",
marginLeft: -1,
width: 2,
height: 2,
background: b
}
}
),
/* @__PURE__ */ t.jsx("div", { style: { width: "100%", pointerEvents: "none" }, children: /* @__PURE__ */ t.jsx(de, {}) })
]
}
)
]
}
)
]
}
)
);
}
export {
me as NightLight
};
//# sourceMappingURL=index.esm.js.map