UNPKG

sisyphus-progressbar

Version:

A animated progress bar inspired by the myth of Sisyphus, featuring physics-based animations and philosophical quotes

234 lines (224 loc) 25.1 kB
import { jsxs, jsx, Fragment } from 'react/jsx-runtime'; import { useState, useRef, useCallback, useEffect } from 'react'; /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var SisyphusProgressBar = function (_a) { var externalProgress = _a.progress, _b = _a.showPercentage, showPercentage = _b === void 0 ? true : _b; var _c = useState(50), internalProgress = _c[0], setInternalProgress = _c[1]; var _d = useState({ boulderPosition: 50, sisyphusPosition: 50, boulderVelocity: 0, targetPosition: 50, phase: 'normal', // 'normal', 'chasing', 'pushing' animationPhase: 0, rollTarget: 0, }), physicsState = _d[0], setPhysicsState = _d[1]; // State for the rotating quotes var _e = useState(0), quoteIndex = _e[0], setQuoteIndex = _e[1]; var quoteRotationIntervalRef = useRef(null); var animationRef = useRef(); var lastTimeRef = useRef(Date.now()); var progress = externalProgress !== undefined ? externalProgress : internalProgress; // Authentic quotes from or inspired by "The Myth of Sisyphus" var quotes = [ "The struggle itself toward the heights is enough to fill a man's heart.", "There is no fate that cannot be surmounted by scorn.", "The gods had thought with some reason that there is no more dreadful punishment than futile and hopeless labor.", "He was superior to his fate. He was stronger than his rock.", "His fate belongs to him. His rock is his thing.", "I leave Sisyphus at the foot of the mountain! One always finds one's burden again.", "The lucidity that was to constitute his torture at the same time crowns his victory." ]; // Physics constants var PHYSICS = { gravity: 120, friction: 0.98, chaseSpeed: 80, pushSpeed: 25, moveSpeed: 40, initialVelocity: 20, rollAmount: 35, // The amount the boulder rolls down when progress is decreased manually }; var getDisplayProgress = useCallback(function (sisyphusPos) { var maxProgress = 95 + (sisyphusPos / 100) * 4.9; return Math.min(Math.max(0, sisyphusPos), maxProgress); }, []); var getPosition = useCallback(function (prog) { var position = Math.max(0, Math.min(100, prog)) / 100; return { x: 10 + (position * 60), y: 95 - (position * 30) }; }, []); // Update target when progress changes useEffect(function () { setPhysicsState(function (prev) { return (__assign(__assign({}, prev), { targetPosition: progress })); }); }, [progress]); // Effect for rotating quotes when stagnant useEffect(function () { // Don't run this logic if the loader is controlled externally. if (externalProgress !== undefined) { if (quoteRotationIntervalRef.current) clearInterval(quoteRotationIntervalRef.current); return; } // Clear previous interval on each interaction to reset the timer if (quoteRotationIntervalRef.current) { clearInterval(quoteRotationIntervalRef.current); } // Set a new interval that rotates the quote every minute quoteRotationIntervalRef.current = setInterval(function () { setQuoteIndex(function (prevIndex) { return (prevIndex + 1) % quotes.length; }); }, 60000); // 1 minute // Cleanup on unmount return function () { if (quoteRotationIntervalRef.current) { clearInterval(quoteRotationIntervalRef.current); } }; }, [internalProgress, externalProgress, quotes.length]); // Re-runs on interaction, resetting the interval. // Effect for random boulder drops useEffect(function () { if (externalProgress !== undefined) return; var randomDropInterval = setInterval(function () { setPhysicsState(function (prev) { // Only trigger a random drop if Sisyphus is in a stable state and not at the very bottom. if (prev.phase === 'normal' && prev.boulderPosition > 20) { var randomDropAmount = Math.floor(Math.random() * 16) + 5; // Drop between 5% and 20% var newRollTarget = Math.max(0, prev.boulderPosition - randomDropAmount); return __assign(__assign({}, prev), { phase: 'chasing', boulderVelocity: PHYSICS.initialVelocity, rollTarget: newRollTarget }); } return prev; }); }, 30000); // Approximately 2 times a minute return function () { return clearInterval(randomDropInterval); }; }, [externalProgress, PHYSICS.initialVelocity]); // Main physics animation loop useEffect(function () { var animate = function () { var currentTime = Date.now(); var deltaTime = Math.min((currentTime - lastTimeRef.current) / 1000, 0.033); // Cap at ~30fps lastTimeRef.current = currentTime; setPhysicsState(function (prev) { var boulderPosition = prev.boulderPosition, sisyphusPosition = prev.sisyphusPosition, boulderVelocity = prev.boulderVelocity, targetPosition = prev.targetPosition, phase = prev.phase, animationPhase = prev.animationPhase; var newState = __assign(__assign({}, prev), { animationPhase: (animationPhase + 1) % 1000 }); switch (phase) { case 'chasing': { var rollTarget = prev.rollTarget; if (boulderPosition > rollTarget) { var newVelocity = boulderVelocity + PHYSICS.gravity * deltaTime; var dampedVelocity = newVelocity * PHYSICS.friction; var newBoulderPos = Math.max(rollTarget, boulderPosition - dampedVelocity * deltaTime); var newSisyphusPos = sisyphusPosition; if (sisyphusPosition > newBoulderPos + 5) { newSisyphusPos = Math.max(newBoulderPos + 5, sisyphusPosition - PHYSICS.chaseSpeed * deltaTime); } return __assign(__assign({}, newState), { boulderPosition: newBoulderPos, sisyphusPosition: newSisyphusPos, boulderVelocity: dampedVelocity }); } else { return __assign(__assign({}, newState), { phase: 'pushing', boulderPosition: rollTarget, sisyphusPosition: rollTarget, boulderVelocity: 0 }); } } case 'pushing': { if (boulderPosition < targetPosition) { var moveAmount = PHYSICS.pushSpeed * deltaTime; var newPos = Math.min(targetPosition, boulderPosition + moveAmount); return __assign(__assign({}, newState), { boulderPosition: newPos, sisyphusPosition: newPos }); } else { return __assign(__assign({}, newState), { phase: 'normal', boulderPosition: targetPosition, sisyphusPosition: targetPosition, boulderVelocity: 0 }); } } default: { // 'normal' var distanceToTarget = Math.abs(boulderPosition - targetPosition); if (distanceToTarget > 0.1) { var direction = targetPosition > boulderPosition ? 1 : -1; if (direction < 0) { var newRollTarget = Math.max(0, boulderPosition - PHYSICS.rollAmount); return __assign(__assign({}, newState), { phase: 'chasing', boulderVelocity: PHYSICS.initialVelocity, rollTarget: newRollTarget }); } var moveAmount = PHYSICS.moveSpeed * deltaTime; var newPos = boulderPosition + direction * moveAmount; return __assign(__assign({}, newState), { boulderPosition: newPos, sisyphusPosition: newPos }); } return __assign(__assign({}, newState), { boulderPosition: targetPosition, sisyphusPosition: targetPosition }); } } }); animationRef.current = requestAnimationFrame(animate); }; animationRef.current = requestAnimationFrame(animate); return function () { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } }; }, []); var displayProgress = getDisplayProgress(physicsState.sisyphusPosition); var sisyphusPos = getPosition(physicsState.sisyphusPosition); var boulderPos = getPosition(physicsState.boulderPosition); var isChasing = physicsState.phase === 'chasing'; var isPushing = physicsState.phase === 'pushing'; var struggleOffset = isPushing ? Math.sin(physicsState.animationPhase / 8) * 0.8 : Math.sin(physicsState.animationPhase / 10) * 0.5; var sisyphusX = sisyphusPos.x + struggleOffset; var sisyphusY = sisyphusPos.y - Math.abs(Math.sin(physicsState.animationPhase / 10)) * 0.3; var boulderRotation = physicsState.boulderPosition * 7.2 + (isChasing ? physicsState.animationPhase * 5 : physicsState.animationPhase * 0.5); var legSpeed = isChasing ? 15 : isPushing ? 30 : 40; var isLeftLegForward = (physicsState.animationPhase % legSpeed) < legSpeed / 2; var currentQuote = quotes[quoteIndex]; return (jsxs("div", { className: "w-full max-w-md mx-auto p-4 space-y-4 font-sans", role: "progressbar", "aria-valuenow": displayProgress, "aria-valuemin": 0, "aria-valuemax": 100, children: [jsxs("div", { className: "relative h-40 bg-amber-50 rounded-lg overflow-hidden shadow-2xl", children: [jsx("div", { className: "absolute inset-0 border-4 border-amber-700 rounded-lg pointer-events-none", children: jsxs("svg", { className: "absolute inset-0 w-full h-full", viewBox: "0 0 100 100", preserveAspectRatio: "none", children: [jsx("defs", { children: jsxs("pattern", { id: "greekKey", x: "0", y: "0", width: "10", height: "10", patternUnits: "userSpaceOnUse", children: [jsx("path", { d: "M 0 0 L 0 5 L 2 5 L 2 2 L 5 2 L 5 0 Z", fill: "none", stroke: "#92400E", strokeWidth: "0.5" }), jsx("path", { d: "M 5 0 L 8 0 L 8 3 L 10 3 L 10 0", fill: "none", stroke: "#92400E", strokeWidth: "0.5" }), jsx("path", { d: "M 10 5 L 8 5 L 8 8 L 5 8 L 5 10 L 10 10", fill: "none", stroke: "#92400E", strokeWidth: "0.5" }), jsx("path", { d: "M 0 10 L 0 7 L 2 7 L 2 10", fill: "none", stroke: "#92400E", strokeWidth: "0.5" })] }) }), jsx("rect", { x: "2", y: "2", width: "96", height: "8", fill: "url(#greekKey)", opacity: "0.3" }), jsx("rect", { x: "2", y: "90", width: "96", height: "8", fill: "url(#greekKey)", opacity: "0.3" })] }) }), jsxs("div", { className: "absolute inset-0 bg-gradient-to-b from-amber-100 via-orange-50 to-amber-50", children: [jsxs("svg", { className: "absolute top-4 right-4 w-12 h-12", children: [jsx("circle", { cx: "24", cy: "24", r: "10", fill: "#FFA500", opacity: "0.8" }), __spreadArray([], Array(8), true).map(function (_, i) { return (jsx("line", { x1: "24", y1: "24", x2: 24 + 20 * Math.cos((i * Math.PI) / 4), y2: 24 + 20 * Math.sin((i * Math.PI) / 4), stroke: "#FFA500", strokeWidth: "1", opacity: "0.4" }, i)); })] }), jsx("svg", { className: "absolute inset-0 w-full h-full", viewBox: "0 0 100 100", children: __spreadArray([], Array(3), true).map(function (_, i) { var orbitRadiusX = 20 + i * 7; var orbitRadiusY = 6 + i * 2; var speed = 0.5 + i * 0.15; var centerX = 50; var centerY = 22; var phaseOffset = i * 150; var angle = (physicsState.animationPhase * speed + phaseOffset) * (Math.PI / 180); var x = centerX + Math.cos(angle) * orbitRadiusX; var y = centerY + Math.sin(angle) * orbitRadiusY; var perspectiveFactor = (Math.sin(angle) + 1) / 2; var scale = 0.6 + perspectiveFactor * 0.4; var opacity = 0.7 + perspectiveFactor * 0.3; return (jsxs("g", { transform: "translate(".concat(x, ", ").concat(y, ") scale(").concat(scale, ")"), opacity: opacity, children: [jsx("ellipse", { cx: "0", cy: "0", rx: "2", ry: "1.2", fill: "#2F4F4F" }), jsx("path", { d: "M -2 0 Q -3.5 -0.8 -4 0 Q -3.5 0.8 -2 0", fill: "#2F4F4F", opacity: "0.8", children: jsx("animate", { attributeName: "d", values: "M -2 0 Q -3.5 -0.8 -4 0 Q -3.5 0.8 -2 0;M -2 0 Q -3.5 -1.5 -4 0 Q -3.5 0.2 -2 0;M -2 0 Q -3.5 -0.8 -4 0 Q -3.5 0.8 -2 0", dur: "1s", repeatCount: "indefinite" }) }), jsx("path", { d: "M 2 0 Q 3.5 -0.8 4 0 Q 3.5 0.8 2 0", fill: "#2F4F4F", opacity: "0.8", children: jsx("animate", { attributeName: "d", values: "M 2 0 Q 3.5 -0.8 4 0 Q 3.5 0.8 2 0;M 2 0 Q 3.5 -1.5 4 0 Q 3.5 0.2 2 0;M 2 0 Q 3.5 -0.8 4 0 Q 3.5 0.8 2 0", dur: "1s", repeatCount: "indefinite" }) }), jsx("circle", { cx: "-1.5", cy: "0", r: "0.4", fill: "#8B4513" })] }, i)); }) })] }), jsxs("svg", { className: "absolute inset-0 w-full h-full", viewBox: "0 0 100 100", preserveAspectRatio: "none", children: [jsx("defs", { children: jsxs("pattern", { id: "marble", x: "0", y: "0", width: "20", height: "20", patternUnits: "userSpaceOnUse", children: [jsx("rect", { width: "20", height: "20", fill: "#D4A373" }), jsx("path", { d: "M 0 5 Q 10 3 20 5", stroke: "#C19660", strokeWidth: "0.5", fill: "none", opacity: "0.5" }), jsx("path", { d: "M 0 15 Q 10 13 20 15", stroke: "#C19660", strokeWidth: "0.5", fill: "none", opacity: "0.5" }), jsx("circle", { cx: "5", cy: "10", r: "1", fill: "#B8956A", opacity: "0.3" }), jsx("circle", { cx: "15", cy: "7", r: "0.5", fill: "#B8956A", opacity: "0.3" })] }) }), jsx("path", { d: "M 0 100 L 85 50 L 100 48 L 100 100 Z", fill: "url(#marble)", stroke: "#8B6914", strokeWidth: "1" }), jsx("path", { d: "M 10 95 Q 30 85 50 70 T 85 53", stroke: "#F5DEB3", strokeWidth: "3", fill: "none", opacity: "0.6" })] }), jsxs("svg", { className: "absolute left-2 bottom-0 w-8 h-16", viewBox: "0 0 20 40", children: [jsx("rect", { x: "4", y: "5", width: "12", height: "30", fill: "#DDD", stroke: "#AAA", strokeWidth: "0.5" }), jsx("rect", { x: "2", y: "0", width: "16", height: "5", fill: "#DDD", stroke: "#AAA", strokeWidth: "0.5" }), jsx("rect", { x: "2", y: "35", width: "16", height: "5", fill: "#DDD", stroke: "#AAA", strokeWidth: "0.5" }), __spreadArray([], Array(4), true).map(function (_, i) { return (jsx("line", { x1: 6 + i * 3, y1: "5", x2: 6 + i * 3, y2: "35", stroke: "#AAA", strokeWidth: "0.3" }, i)); })] }), jsx("svg", { className: "absolute inset-0 w-full h-full", viewBox: "0 0 100 100", children: jsx("g", { transform: "translate(".concat(boulderPos.x, ", ").concat(boulderPos.y - 7, ")"), children: jsxs("g", { transform: "rotate(".concat(boulderRotation, " 0 0)"), children: [jsx("circle", { cx: "0", cy: "0", r: "7", fill: "#8B7D6B", stroke: "#5D4E37", strokeWidth: "0.8" }), jsx("path", { d: "M -3 -3 L -1 0 L -3 3", stroke: "#5D4E37", strokeWidth: "0.3", fill: "none" }), jsx("path", { d: "M 2 -4 L 3 -1 L 1 2", stroke: "#5D4E37", strokeWidth: "0.3", fill: "none" }), jsx("circle", { cx: "-2", cy: "-2", r: "1.5", fill: "#6B5D54", opacity: "0.4" }), jsx("circle", { cx: "2", cy: "1", r: "1", fill: "#6B5D54", opacity: "0.4" })] }) }) }), jsxs("svg", { className: "absolute inset-0 w-full h-full", viewBox: "0 0 100 100", children: [jsx("g", { transform: "translate(".concat(sisyphusX, ", ").concat(sisyphusY, ")"), children: jsxs("g", { transform: "translate(-10, -3) scale(1) rotate(".concat(isChasing ? 5 : isPushing ? -10 : -struggleOffset * 2, " 0 0)"), children: [jsx("ellipse", { cx: "0", cy: "8", rx: "4", ry: "1", fill: "#000", opacity: "0.2" }), jsxs("g", { transform: "rotate(".concat(isLeftLegForward ? -15 : 15, " -1 3)"), children: [jsx("path", { d: "M -1 3 L -3 6 L -3 8", stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" }), jsx("circle", { cx: "-3", cy: "8", r: "1", fill: "#8B4513" })] }), jsx("ellipse", { cx: "0", cy: "0", rx: 3 + Math.sin(physicsState.animationPhase / (isPushing ? 8 : 20)) * 0.2, ry: "4", fill: "#D4A373" }), jsx("path", { d: "M -3 -2 L 3 -2 L 2.5 4 L -2.5 4 Z", fill: "#FFF", opacity: "0.9" }), jsx("path", { d: "M -3 -2 L -2.5 4", stroke: "#DDD", strokeWidth: "0.3" }), jsx("path", { d: "M 3 -2 L 2.5 4", stroke: "#DDD", strokeWidth: "0.3" }), jsx("path", { d: "M -2 0 L 2 0", stroke: "#E6E6E6", strokeWidth: "0.2" }), jsx("path", { d: "M -2 2 L 2 2", stroke: "#E6E6E6", strokeWidth: "0.2" }), isChasing ? (jsxs("g", { children: [jsx("path", { d: "M 2 -1 Q 0 ".concat(isLeftLegForward ? -2 : 0, " -2 ").concat(isLeftLegForward ? -1 : 1), stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" }), jsx("path", { d: "M 2 1 Q 4 ".concat(isLeftLegForward ? 0 : 2, " 5 ").concat(isLeftLegForward ? 1 : -1), stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" })] })) : (jsxs("g", { transform: "rotate(".concat(isPushing ? -5 : Math.sin(physicsState.animationPhase / 15) * 3, " 2 0)"), children: [jsx("path", { d: "M 2 -1 Q 5 -1.5 8 -2", stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" }), jsx("path", { d: "M 2 1 Q 5 0.5 8 0", stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" }), jsx("circle", { cx: "4", cy: "-1", r: "0.5", fill: "#C19660", opacity: "0.3" }), jsx("circle", { cx: "4", cy: "0.5", r: "0.5", fill: "#C19660", opacity: "0.3" })] })), jsxs("g", { transform: "rotate(".concat(!isLeftLegForward ? -15 : 15, " 1 3)"), children: [jsx("path", { d: "M 1 3 L 2 6 L 2 8", stroke: "#D4A373", strokeWidth: "1.8", strokeLinecap: "round", fill: "none" }), jsx("circle", { cx: "2", cy: "8", r: "1", fill: "#8B4513" })] }), jsxs("g", { transform: "translate(0, ".concat(Math.sin(physicsState.animationPhase / 10) * 0.2, ")"), children: [jsx("circle", { cx: "0", cy: "-5", r: "2.5", fill: "#D4A373" }), jsx("path", { d: "M -2.5 -6.5 Q 0 -7.5 2.5 -6.5", fill: "#2F4F4F" }), jsx("path", { d: "M -2 -5 Q -2.5 -3 -2 -3", fill: "#2F4F4F" }), jsx("path", { d: "M 2 -5 Q 2.5 -3 2 -3", fill: "#2F4F4F" }), jsx("path", { d: "M -1.5 -3.5 Q 0 -2.5 1.5 -3.5", fill: "#2F4F4F", opacity: "0.7" }), jsx("path", { d: "M -2.5 -6 Q -2 -7 0 -7.2 Q 2 -7 2.5 -6", stroke: "#228B22", strokeWidth: "0.5", fill: "none" }), jsx("ellipse", { cx: "-2", cy: "-6.5", rx: "0.3", ry: "0.5", fill: "#228B22", transform: "rotate(-30 -2 -6.5)" }), jsx("ellipse", { cx: "2", cy: "-6.5", rx: "0.3", ry: "0.5", fill: "#228B22", transform: "rotate(30 2 -6.5)" }), jsx("circle", { cx: "-0.7", cy: "-5", r: "0.2", fill: "#000" }), jsx("circle", { cx: "0.7", cy: "-5", r: "0.2", fill: "#000" }), jsx("path", { d: "M -0.5 -4.3 Q 0 ".concat(-4 + (isChasing ? -0.3 : isPushing ? 0.2 : Math.sin(physicsState.animationPhase / 8) * 0.1), " 0.5 -4.3"), stroke: "#000", strokeWidth: "0.1", fill: "none" })] }), (isPushing || physicsState.phase === 'normal') && (jsxs(Fragment, { children: [jsx("path", { d: "M 3 -6 L 4 -7", stroke: "#FFD700", strokeWidth: "0.3", opacity: 0.6 + Math.sin(physicsState.animationPhase / 5) * 0.3 }), jsx("path", { d: "M 3.5 -4 L 4.5 -4", stroke: "#FFD700", strokeWidth: "0.3", opacity: 0.6 + Math.sin(physicsState.animationPhase / 7) * 0.3 }), isPushing && (jsx("path", { d: "M 3 -2 L 4 -1", stroke: "#FFD700", strokeWidth: "0.3", opacity: 0.6 + Math.sin(physicsState.animationPhase / 6) * 0.3 }))] }))] }) }), (displayProgress > 30 || isPushing) && !isChasing && (jsxs("circle", { cx: sisyphusX - 10, cy: sisyphusY - 8, r: "0.8", fill: "#4682B4", opacity: "0.6", children: [jsx("animate", { attributeName: "cy", from: sisyphusY - 8, to: sisyphusY + 10, dur: "1.5s", repeatCount: "indefinite" }), jsx("animate", { attributeName: "opacity", from: "0.6", to: "0", dur: "1.5s", repeatCount: "indefinite" })] })), (displayProgress > 60 || isPushing) && !isChasing && (jsxs(Fragment, { children: [jsxs("circle", { cx: sisyphusX - 8, cy: sisyphusY - 10, r: "0.6", fill: "#4682B4", opacity: "0.6", children: [jsx("animate", { attributeName: "cy", from: sisyphusY - 10, to: sisyphusY + 8, dur: "1.8s", repeatCount: "indefinite" }), jsx("animate", { attributeName: "opacity", from: "0.6", to: "0", dur: "1.8s", repeatCount: "indefinite" })] }), jsxs("circle", { cx: sisyphusX - 12, cy: sisyphusY - 6, r: "0.7", fill: "#4682B4", opacity: "0.6", children: [jsx("animate", { attributeName: "cy", from: sisyphusY - 6, to: sisyphusY + 12, dur: "2s", repeatCount: "indefinite" }), jsx("animate", { attributeName: "opacity", from: "0.6", to: "0", dur: "2s", repeatCount: "indefinite" })] })] })), __spreadArray([], Array(3), true).map(function (_, i) { return (jsx("circle", { cx: sisyphusX - 5 + i * 2, cy: sisyphusY + 7, r: "0.3", fill: "#D4A373", opacity: Math.sin(physicsState.animationPhase / (isChasing ? 3 : 10) + i) * 0.3 + 0.2 }, i)); }), isChasing && (jsx("text", { x: sisyphusX - 15, y: sisyphusY - 15, fontSize: "4", fill: "#8B4513", fontWeight: "bold", children: "!!!" }))] }), showPercentage && (jsxs("div", { className: "absolute bottom-3 right-3 text-sm font-bold text-amber-800 bg-amber-100 px-2 py-1 rounded border border-amber-600", children: [displayProgress.toFixed(1), "%"] })), currentQuote && displayProgress < 95 && (jsx("div", { className: "absolute top-2 left-4 right-4 text-center", children: jsxs("div", { className: "text-xs text-amber-900 italic bg-amber-50 bg-opacity-80 p-2 rounded-md shadow", children: ["\"", currentQuote, "\""] }) })), displayProgress >= 95 && (jsx("div", { className: "absolute top-4 left-4 right-4 text-center", children: jsx("div", { className: "text-sm text-amber-900 font-serif italic", children: "\"One must imagine Sisyphus happy.\"" }) }))] }), externalProgress === undefined && (jsxs("div", { className: "space-y-2", children: [jsxs("label", { className: "text-sm font-medium text-gray-700", children: ["Progress Control: ", internalProgress, "%"] }), jsx("input", { type: "range", min: "0", max: "100", value: internalProgress, onChange: function (e) { return setInternalProgress(Number(e.target.value)); }, className: "w-full h-2 bg-amber-200 rounded-lg appearance-none cursor-pointer", style: { background: "linear-gradient(to right, #D97706 0%, #D97706 ".concat(internalProgress, "%, #FED7AA ").concat(internalProgress, "%, #FED7AA 100%)") } }), jsxs("div", { className: "flex justify-between text-xs text-gray-600", children: [jsx("span", { children: "0%" }), jsx("span", { children: "25%" }), jsx("span", { children: "50%" }), jsx("span", { children: "75%" }), jsx("span", { children: "100%" })] })] }))] })); }; export { SisyphusProgressBar, SisyphusProgressBar as default }; //# sourceMappingURL=index.esm.js.map