UNPKG

vault66-crt-effect

Version:

A customizable CRT (retro monitor) visual effect for React, Vue, and Web Components

394 lines (393 loc) 9.54 kB
const ne = { /** * FALLOUT */ fallout: { theme: "green", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.25, scanlineThickness: 2, scanlineGap: 3, enableSweep: !0, sweepDuration: 12, sweepThickness: 6, sweepStyle: "classic", sweepColor: "rgba(91, 179, 135, 0.5)", enableGlow: !1, enableEdgeGlow: !0, edgeGlowColor: "rgba(91, 179, 135, 0.5)", edgeGlowSize: 40, enableFlicker: !0, flickerIntensity: 0.05, flickerSpeed: 1.5, enableVignette: !0, vignetteIntensity: 0.3, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.6, enableNoise: !0, noiseOpacity: 0.2 }, /** * DOS - Classic DOS/Hercules monitor */ dos: { theme: "custom", scanlineColor: "rgba(255, 100, 0, 0.3)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.2, scanlineThickness: 2, scanlineGap: 4, enableSweep: !1, enableGlow: !1, enableEdgeGlow: !1, enableFlicker: !1, enableVignette: !0, vignetteIntensity: 0.25, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.55 }, /** * CYBERPUNK */ cyberpunk: { theme: "custom", scanlineColor: "rgba(255, 0, 255, 0.3)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.35, scanlineThickness: 2, scanlineGap: 2, enableSweep: !0, sweepDuration: 5, sweepThickness: 8, sweepStyle: "classic", sweepColor: "rgba(255, 0, 200, 0.5)", enableGlow: !0, glowColor: "rgba(255, 0, 200, 0.5)", enableEdgeGlow: !0, edgeGlowColor: "rgba(200, 0, 255, 0.6)", edgeGlowSize: 50, enableFlicker: !0, flickerIntensity: 0.08, flickerSpeed: 0.8, enableVignette: !0, vignetteIntensity: 0.4, enableGlitch: !0, glitchIntensity: 0.3, glitchSpeed: 1, glitchChromatic: !0, enableCurvature: !0, curvatureIntensity: 0.7, enableGlare: !0, glareIntensity: 0.25, enableNoise: !0, noiseOpacity: 0.18 }, /** * COMMODORE 64 - 8-bit computer */ commodore64: { theme: "custom", scanlineColor: "rgba(160, 160, 255, 0.35)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.35, scanlineThickness: 3, scanlineGap: 2, enableSweep: !0, sweepDuration: 10, sweepThickness: 6, sweepStyle: "classic", sweepColor: "rgba(160, 160, 255, 0.5)", enableGlow: !1, enableEdgeGlow: !1, enableFlicker: !0, flickerIntensity: 0.05, flickerSpeed: 1.5, enableVignette: !0, vignetteIntensity: 0.35, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.6, enableNoise: !0, noiseOpacity: 0.15 }, /** * APPLE II - Vintage Apple computer terminal */ apple2: { theme: "custom", scanlineColor: "rgba(120, 220, 80, 0.3)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.3, scanlineThickness: 1, scanlineGap: 2, enableSweep: !1, enableGlow: !1, enableEdgeGlow: !1, enableFlicker: !1, enableVignette: !0, vignetteIntensity: 0.2, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.55 }, /** * ARCADE - Retro arcade cabinet monitor */ arcade: { theme: "custom", scanlineColor: "rgba(0, 255, 100, 0.4)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.4, scanlineThickness: 3, scanlineGap: 3, enableSweep: !0, sweepDuration: 4, sweepThickness: 8, sweepStyle: "classic", sweepColor: "rgba(0, 255, 100, 0.5)", enableGlow: !0, glowColor: "rgba(0, 255, 100, 0.5)", enableEdgeGlow: !0, edgeGlowColor: "rgba(0, 255, 100, 0.6)", edgeGlowSize: 45, enableFlicker: !0, flickerIntensity: 0.08, flickerSpeed: 0.8, enableVignette: !0, vignetteIntensity: 0.45, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.7, enableGlare: !0, glareIntensity: 0.3 }, /** * VT100 - Classic DEC terminal */ vt100: { theme: "custom", scanlineColor: "rgba(220, 255, 235, 0.2)", tintText: !0, enableScanlines: !0, scanlineOpacity: 0.15, scanlineThickness: 2, scanlineGap: 4, enableSweep: !1, enableGlow: !1, enableEdgeGlow: !1, enableFlicker: !1, enableVignette: !0, vignetteIntensity: 0.15, enableGlitch: !1, enableCurvature: !0, curvatureIntensity: 0.45 }, /** * MINIMAL - Subtle CRT effect */ minimal: { theme: "green", enableScanlines: !0, scanlineOpacity: 0.1, scanlineThickness: 1, scanlineGap: 4, enableSweep: !1, enableGlow: !1, enableEdgeGlow: !1, enableFlicker: !1, enableVignette: !0, vignetteIntensity: 0.2, enableGlitch: !1 } }, te = { enabled: !0, sweepDuration: 10, sweepThickness: 10, sweepStyle: "classic", scanlineOpacity: 0.2, scanlineColor: "rgba(91, 179, 135, 0.2)", scanlineThickness: 2, scanlineGap: 3, enableScanlines: !0, enableSweep: !0, theme: "green", enableGlow: !1, glowColor: "rgba(0, 255, 128, 0.3)", enableEdgeGlow: !1, edgeGlowColor: "rgba(0, 255, 128, 0.2)", edgeGlowSize: 30, enableFlicker: !1, scanlineOrientation: "horizontal", glitchIntensity: 1, glitchSpeed: 0.6, flickerIntensity: 0.08, flickerSpeed: 0.8, enableGlitch: !1, enableVignette: !1, vignetteIntensity: 0.4, enableCurvature: !1, curvatureIntensity: 0.5, enableGlare: !1, glareIntensity: 0.18, enableNoise: !1, noiseOpacity: 0.15, glitchChromatic: !1, tintText: !1, textColor: void 0, sweepColor: void 0, fill: !1 }; function h(e) { const n = {}; for (const i in e) { const a = e[i]; a !== void 0 && (n[i] = a); } return n; } function le(e) { const n = e.trim(), i = n.match(/^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i); if (i) { const t = i[1]; return (t.length <= 4 ? t.slice(0, 3).split("").map((s) => s + s) : [t.slice(0, 2), t.slice(2, 4), t.slice(4, 6)]).map((s) => Number.parseInt(s, 16)).join(", "); } const a = n.match(/^rgba?\((.*)\)$/i); if (a) { const t = a[1].split("/")[0].trim().split(/[\s,]+/).filter(Boolean).slice(0, 3); if (t.length === 3 && t.every((r) => /^\d*\.?\d+%?$/.test(r))) return t.join(", "); } return "91, 179, 135"; } const d = { green: "91, 179, 135", // Classic CRT green amber: "255, 200, 100", // Vintage amber monitor blue: "100, 200, 255" // Retro blue terminal }; function y(e, n) { return typeof e == "number" ? e : n[e]; } function G(e, n) { return typeof e == "number" ? `${e}s` : n[e]; } function ie(e = {}) { const { preset: n, ...i } = e, a = n ? ne[n] : {}, t = { ...te, ...h(a), ...h(i) }, { enabled: r, sweepDuration: s, sweepThickness: m, sweepStyle: k, scanlineOpacity: v, scanlineColor: C, scanlineThickness: S, scanlineGap: I, enableScanlines: x, enableSweep: o, theme: u, enableGlow: T, glowColor: O, enableEdgeGlow: b, edgeGlowColor: V, edgeGlowSize: E, enableFlicker: F, scanlineOrientation: N, glitchIntensity: $, glitchSpeed: z, flickerIntensity: D, flickerSpeed: B, enableGlitch: p, enableVignette: j, vignetteIntensity: M, enableCurvature: R, curvatureIntensity: H, enableGlare: q, glareIntensity: A, enableNoise: J, noiseOpacity: K, glitchChromatic: L, tintText: g, textColor: P, sweepColor: c, fill: w } = t, f = u !== "custom" ? d[u] ?? d.green : le(C), Q = P ?? `rgb(${f})`, U = y(D, { low: 0.05, medium: 0.08, high: 0.12 }), W = G(B, { low: "1.5s", medium: "0.8s", high: "0.4s" }), X = y($, { low: 0.3, medium: 0.6, high: 0.9 }), Y = G(z, { low: "1s", medium: "0.6s", high: "0.3s" }), Z = [ "crt-effect-wrapper", x && "scanlines-on", o && (k === "classic" ? "sweep-on" : "sweep-soft"), o && c && "sweep-colored", b && "edge-glow-on", F && "flicker-on" ].filter(Boolean).join(" "), l = { position: "relative", overflow: "hidden", "--sweep-duration": `${s}s`, "--sweep-thickness": `${m}px`, "--scanline-opacity": v, "--scanline-color-rgb": f, "--scanline-thickness": `${S}px`, "--scanline-gap": `${I}px`, "--glow-color": O, "--edge-glow-color": V, "--edge-glow-size": `${E}px`, "--scanline-gradient-direction": N === "horizontal" ? "to bottom" : "to right", "--glitch-speed": Y, "--glitch-intensity": X, "--flicker-speed": W, "--flicker-intensity": U, "--vignette-intensity": M, "--curvature-intensity": H, "--glare-intensity": A, "--noise-opacity": K }; g && (l["--crt-text-color"] = Q), c && (l["--sweep-color"] = c), T && (l.filter = "drop-shadow(0 0 6px var(--glow-color)) drop-shadow(0 0 12px var(--glow-color)) drop-shadow(0 0 20px var(--glow-color))"), w && (l.width = "100%", l.height = "100%", l.display = "flex", l.flexDirection = "column"); const _ = [ "crt-inner", p && "glitch-on", p && L && "chromatic-on", g && "tint-text-on" ].filter(Boolean).join(" "), ee = [ R && "crt-curvature", J && "crt-noise", q && "crt-glare", b && "crt-edge-glow", j && "crt-vignette" ].filter(Boolean); return { enabled: r, wrapper: { className: Z, style: l }, inner: { className: _, style: w ? { display: "flex", flexDirection: "column" } : void 0 }, overlays: ee }; } export { ie as computeCrt, ne as presets };