senangwebs-epoch 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -6
- package/dist/swe.js +1 -1
- package/examples/index.html +418 -39
- package/index.js +7 -0
- package/package.json +28 -27
- package/src/js/swe.js +51 -14
- package/webpack.config.js +2 -5
- package/dist/style.js +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
[](https://use.senangwebs.com)
|
|
2
|
-
Learn more at [SenangWebs.com](https://use.senangwebs.com)
|
|
3
|
-
|
|
4
1
|
# SenangWebs Epoch (SWE)
|
|
5
2
|
|
|
6
3
|
SenangWebs Epoch (SWE) is a lightweight JavaScript library for creating dynamic countdown timers and time displays. Whether you need to count down to a specific date, create a duration-based timer, or display the current time, SWE provides an elegant solution with minimal setup. The library supports flexible formatting, responsive design, and comprehensive event handling.
|
|
@@ -97,6 +94,25 @@ Include SenangWebs Epoch directly in your HTML file:
|
|
|
97
94
|
- `data-swe-second`
|
|
98
95
|
- `data-swe-format`: Specifies display format for each unit
|
|
99
96
|
|
|
97
|
+
### Format Options
|
|
98
|
+
|
|
99
|
+
The format string determines zero-padding based on its length:
|
|
100
|
+
|
|
101
|
+
| Unit | Format | Output Example | Description |
|
|
102
|
+
|------|--------|----------------|-------------|
|
|
103
|
+
| Year | `yyyy` | `2026` | Four-digit year |
|
|
104
|
+
| Month | `m` | `5` | Single digit month |
|
|
105
|
+
| Month | `mm` | `05` | Two-digit month |
|
|
106
|
+
| Day | `d` | `5` | Single digit day |
|
|
107
|
+
| Day | `dd` | `05` | Two-digit day |
|
|
108
|
+
| Day | `ddd` | `005` | Three-digit day (for long countdowns) |
|
|
109
|
+
| Hour | `H` | `9` | Single digit hour |
|
|
110
|
+
| Hour | `HH` | `09` | Two-digit hour |
|
|
111
|
+
| Minute | `m` | `7` | Single digit minute |
|
|
112
|
+
| Minute | `mm` | `07` | Two-digit minute |
|
|
113
|
+
| Second | `s` | `3` | Single digit second |
|
|
114
|
+
| Second | `ss` | `03` | Two-digit second |
|
|
115
|
+
|
|
100
116
|
### JavaScript Initialization
|
|
101
117
|
|
|
102
118
|
```javascript
|
|
@@ -193,10 +209,8 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
193
209
|
|
|
194
210
|
## License
|
|
195
211
|
|
|
196
|
-
|
|
212
|
+
MIT License
|
|
197
213
|
|
|
198
214
|
## Support
|
|
199
215
|
|
|
200
216
|
If you encounter any issues or have questions, please file an issue on the GitHub repository.
|
|
201
|
-
|
|
202
|
-
Keep tracking time with style!
|
package/dist/swe.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SWE=e():t.SWE=e()}(this,(()=>(()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);n<e;n++)i[n]=t[n];return i}function o(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,r(i.key),i)}}function r(t){var e=function(t){if("object"!=n(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,"string");if("object"!=n(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==n(e)?e:e+""}t.d(e,{default:()=>s});var a=function(){return t=function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.element=e,this.options={autostart:void 0===n.autostart||n.autostart,duration:n.duration,countdownEnd:n.countdownEnd,onTick:n.onTick,onEnd:n.onEnd,onStart:n.onStart,onPause:n.onPause,onResume:n.onResume,onReset:n.onReset,onStop:n.onStop},this.intervalId=null,this.isPaused=!1,this.startTime=null,this.pausedTimeRemaining=null,this.endTime=null,this.initialize()},(e=[{key:"initialize",value:function(){if(!(this.element&&this.element instanceof HTMLElement))throw new Error("SWE: Invalid element provided");if(this.mode=this.determineMode(),this.setupElements(),this.options.autostart)this.start();else if("countdown-duration"===this.mode&&this.options.duration)this.updateDisplay(1e3*this.options.duration);else if("countdown-end"===this.mode&&this.options.countdownEnd){var t=new Date(this.options.countdownEnd),e=new Date,n=t.getTime()-e.getTime();this.updateDisplay(n>0?n:0)}}},{key:"determineMode",value:function(){if(this.options.countdownEnd)return"countdown-end";if(this.options.duration)return"countdown-duration";if(this.element.hasAttribute("data-swe-countdown-end"))return"countdown-end";if(this.element.hasAttribute("data-swe-countdown-duration"))return"countdown-duration";if(this.element.hasAttribute("data-swe-current"))return"current";if(this.options.countdownEnd)return"countdown-end";throw new Error("SWE: Invalid mode - missing required configuration")}},{key:"setupElements",value:function(){this.elements={year:this.element.querySelector("[data-swe-year]"),month:this.element.querySelector("[data-swe-month]"),day:this.element.querySelector("[data-swe-day]"),hour:this.element.querySelector("[data-swe-hour]"),minute:this.element.querySelector("[data-swe-minute]"),second:this.element.querySelector("[data-swe-second]")}}},{key:"start",value:function(){if(!this.intervalId){switch(this.isPaused=!1,this.startTime=Date.now(),this.mode){case"countdown-end":this.startCountdownToDate();break;case"countdown-duration":this.startCountdownDuration();break;case"current":this.startCurrentTime()}this.dispatchEvent("start")}}},{key:"startCountdownToDate",value:function(){var t=new Date(this.options.countdownEnd||this.element.getAttribute("data-swe-countdown-end"));if(isNaN(t.getTime()))throw new Error("SWE: Invalid end date format");this.endTime=t.getTime(),this.updateTimer()}},{key:"startCountdownDuration",value:function(){var t=this.options.duration||parseInt(this.element.getAttribute("data-swe-countdown-duration"),10);if(isNaN(t)||t<0)throw new Error("SWE: Invalid duration");null!==this.pausedTimeRemaining?this.endTime=Date.now()+this.pausedTimeRemaining:this.endTime=Date.now()+1e3*t,this.updateTimer()}},{key:"updateTimer",value:function(){var t=this,e=function(){var e=Date.now(),n=t.endTime-e;if(n<=0)return t.stop(),t.updateDisplay(0),void t.dispatchEvent("end");t.updateDisplay(n),t.dispatchEvent("tick")};e(),this.intervalId=setInterval(e,1e3)}},{key:"startCurrentTime",value:function(){var t=this,e=function(){var e=new Date;t.updateCurrentTimeDisplay(e),t.dispatchEvent("tick")};e(),this.intervalId=setInterval(e,1e3)}},{key:"updateDisplay",value:function(t){var e=this,n=this.calculateTimeUnits(t);Object.entries(this.elements).forEach((function(t){var o=function(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],u=!0,d=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;u=!1}else for(;!(u=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);u=!0);}catch(t){d=!0,o=t}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(d)throw o}}return s}}(t,e)||function(t,e){if(t){if("string"==typeof t)return i(t,e);var n={}.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(t,2),r=o[0],a=o[1];a&&e.updateElement(a,n[r])}))}},{key:"updateCurrentTimeDisplay",value:function(t){this.elements.hour&&this.updateElement(this.elements.hour,t.getHours()),this.elements.minute&&this.updateElement(this.elements.minute,t.getMinutes()),this.elements.second&&this.updateElement(this.elements.second,t.getSeconds())}},{key:"updateElement",value:function(t,e){var n=t.getAttribute("data-swe-format");t.textContent=this.formatValue(e,n)}},{key:"formatValue",value:function(t,e){return e?t.toString().padStart(e.length,"0"):t.toString()}},{key:"calculateTimeUnits",value:function(t){var e=Math.floor(t/1e3),n=Math.floor(e/60),i=Math.floor(n/60),o=Math.floor(i/24),r=
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SWE=e():t.SWE=e()}(this,(()=>(()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);n<e;n++)i[n]=t[n];return i}function o(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,r(i.key),i)}}function r(t){var e=function(t){if("object"!=n(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,"string");if("object"!=n(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==n(e)?e:e+""}t.d(e,{default:()=>s});var a=function(){return t=function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.element=e,this.options={autostart:void 0===n.autostart||n.autostart,duration:n.duration,countdownEnd:n.countdownEnd,onTick:n.onTick,onEnd:n.onEnd,onStart:n.onStart,onPause:n.onPause,onResume:n.onResume,onReset:n.onReset,onStop:n.onStop},this.intervalId=null,this.isPaused=!1,this.startTime=null,this.pausedTimeRemaining=null,this.endTime=null,this.initialize()},(e=[{key:"initialize",value:function(){if(!(this.element&&this.element instanceof HTMLElement))throw new Error("SWE: Invalid element provided");if(this.mode=this.determineMode(),this.setupElements(),this.options.autostart)this.start();else if("countdown-duration"===this.mode&&this.options.duration)this.updateDisplay(1e3*this.options.duration);else if("countdown-end"===this.mode&&this.options.countdownEnd){var t=new Date(this.options.countdownEnd),e=new Date,n=t.getTime()-e.getTime();this.updateDisplay(n>0?n:0)}}},{key:"determineMode",value:function(){if(this.options.countdownEnd)return"countdown-end";if(this.options.duration)return"countdown-duration";if(this.element.hasAttribute("data-swe-countdown-end"))return"countdown-end";if(this.element.hasAttribute("data-swe-countdown-duration"))return"countdown-duration";if(this.element.hasAttribute("data-swe-current"))return"current";if(this.options.countdownEnd)return"countdown-end";throw new Error("SWE: Invalid mode - missing required configuration")}},{key:"setupElements",value:function(){this.elements={year:this.element.querySelector("[data-swe-year]"),month:this.element.querySelector("[data-swe-month]"),day:this.element.querySelector("[data-swe-day]"),hour:this.element.querySelector("[data-swe-hour]"),minute:this.element.querySelector("[data-swe-minute]"),second:this.element.querySelector("[data-swe-second]")}}},{key:"start",value:function(){if(!this.intervalId){switch(this.isPaused=!1,this.startTime=Date.now(),this.mode){case"countdown-end":this.startCountdownToDate();break;case"countdown-duration":this.startCountdownDuration();break;case"current":this.startCurrentTime()}this.dispatchEvent("start")}}},{key:"startCountdownToDate",value:function(){var t=new Date(this.options.countdownEnd||this.element.getAttribute("data-swe-countdown-end"));if(isNaN(t.getTime()))throw new Error("SWE: Invalid end date format");this.endTime=t.getTime(),this.updateTimer()}},{key:"startCountdownDuration",value:function(){var t=this.options.duration||parseInt(this.element.getAttribute("data-swe-countdown-duration"),10);if(isNaN(t)||t<0)throw new Error("SWE: Invalid duration");null!==this.pausedTimeRemaining?this.endTime=Date.now()+this.pausedTimeRemaining:this.endTime=Date.now()+1e3*t,this.updateTimer()}},{key:"updateTimer",value:function(){var t=this,e=function(){var e=Date.now(),n=t.endTime-e;if(n<=0)return t.stop(),t.updateDisplay(0),void t.dispatchEvent("end");t.updateDisplay(n),t.dispatchEvent("tick")};e(),this.intervalId=setInterval(e,1e3)}},{key:"startCurrentTime",value:function(){var t=this,e=function(){var e=new Date;t.updateCurrentTimeDisplay(e),t.dispatchEvent("tick")};e(),this.intervalId=setInterval(e,1e3)}},{key:"updateDisplay",value:function(t){var e=this,n=this.calculateTimeUnits(t);Object.entries(this.elements).forEach((function(t){var o=function(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var i,o,r,a,s=[],u=!0,d=!1;try{if(r=(n=n.call(t)).next,0===e){if(Object(n)!==n)return;u=!1}else for(;!(u=(i=r.call(n)).done)&&(s.push(i.value),s.length!==e);u=!0);}catch(t){d=!0,o=t}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(d)throw o}}return s}}(t,e)||function(t,e){if(t){if("string"==typeof t)return i(t,e);var n={}.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(t,2),r=o[0],a=o[1];a&&e.updateElement(a,n[r])}))}},{key:"updateCurrentTimeDisplay",value:function(t){this.elements.hour&&this.updateElement(this.elements.hour,t.getHours()),this.elements.minute&&this.updateElement(this.elements.minute,t.getMinutes()),this.elements.second&&this.updateElement(this.elements.second,t.getSeconds())}},{key:"updateElement",value:function(t,e){var n=t.getAttribute("data-swe-format");t.textContent=this.formatValue(e,n)}},{key:"formatValue",value:function(t,e){return e?t.toString().padStart(e.length,"0"):t.toString()}},{key:"calculateTimeUnits",value:function(t){var e=Math.floor(t/1e3),n=Math.floor(e/60),i=Math.floor(n/60),o=(Math.floor(i/24),new Date),r=new Date(o.getTime()+t),a=r.getFullYear()-o.getFullYear(),s=r.getMonth()-o.getMonth(),u=r.getDate()-o.getDate();return u<0&&(s--,u+=new Date(r.getFullYear(),r.getMonth(),0).getDate()),s<0&&(a--,s+=12),{year:a,month:s,day:u,hour:i%24,minute:n%60,second:e%60}}},{key:"dispatchEvent",value:function(t){var e="on".concat(t.charAt(0).toUpperCase()+t.slice(1));"function"==typeof this.options[e]&&this.options[e].call(this);var n=new CustomEvent("swe:".concat(t),{bubbles:!0,detail:{instance:this}});this.element.dispatchEvent(n)}},{key:"pause",value:function(){this.intervalId&&!this.isPaused&&(clearInterval(this.intervalId),this.intervalId=null,this.isPaused=!0,this.pausedTimeRemaining=this.endTime-Date.now(),this.dispatchEvent("pause"))}},{key:"resume",value:function(){if(this.isPaused){switch(this.isPaused=!1,this.startTime=Date.now(),this.mode){case"countdown-end":this.startCountdownToDate();break;case"countdown-duration":this.startCountdownDuration();break;case"current":this.startCurrentTime()}this.dispatchEvent("resume")}}},{key:"reset",value:function(){if(this.stop(),this.pausedTimeRemaining=null,this.endTime=null,"countdown-end"===this.mode&&this.options.countdownEnd){var t=new Date(this.options.countdownEnd),e=new Date,n=t.getTime()-e.getTime();this.updateDisplay(n>0?n:0)}else"countdown-duration"===this.mode&&this.options.duration&&this.updateDisplay(1e3*this.options.duration);this.dispatchEvent("reset"),this.options.autostart&&this.start()}},{key:"stop",value:function(){var t=null!==this.intervalId;this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),this.isPaused=!1,t&&this.dispatchEvent("stop")}}])&&o(t.prototype,e),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,e}();document.addEventListener("DOMContentLoaded",(function(){document.querySelectorAll("[data-swe]").forEach((function(t){new a(t)}))}));const s=a;return"undefined"!=typeof window&&(window.SWE=a),e.default})()));
|
package/examples/index.html
CHANGED
|
@@ -4,71 +4,450 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>SenangWebs Epoch
|
|
7
|
+
<title>SenangWebs Epoch - Examples & Use Cases</title>
|
|
8
8
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
9
|
<link rel="stylesheet" href="../dist/swe.css">
|
|
10
|
+
<link rel="stylesheet" href="https://unpkg.com/@bookklik/senangstart-icons/dist/senangstart.min.css" />
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
12
|
+
<script>
|
|
13
|
+
tailwind.config = {
|
|
14
|
+
theme: {
|
|
15
|
+
extend: {
|
|
16
|
+
fontFamily: {
|
|
17
|
+
sans: ['Outfit', 'sans-serif'],
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
<style>
|
|
24
|
+
.gradient-text {
|
|
25
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
26
|
+
-webkit-background-clip: text;
|
|
27
|
+
-webkit-text-fill-color: transparent;
|
|
28
|
+
background-clip: text;
|
|
29
|
+
}
|
|
30
|
+
.glass-card {
|
|
31
|
+
background: rgba(255, 255, 255, 0.7);
|
|
32
|
+
backdrop-filter: blur(10px);
|
|
33
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
34
|
+
}
|
|
35
|
+
.timer-unit {
|
|
36
|
+
transition: all 0.3s ease;
|
|
37
|
+
}
|
|
38
|
+
.timer-unit:hover {
|
|
39
|
+
transform: scale(1.05);
|
|
40
|
+
}
|
|
41
|
+
@keyframes pulse-glow {
|
|
42
|
+
0%, 100% { box-shadow: 0 0 20px rgba(239, 68, 68, 0.3); }
|
|
43
|
+
50% { box-shadow: 0 0 40px rgba(239, 68, 68, 0.6); }
|
|
44
|
+
}
|
|
45
|
+
.flash-sale-glow {
|
|
46
|
+
animation: pulse-glow 2s infinite;
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
10
49
|
</head>
|
|
11
50
|
|
|
12
|
-
<body class="min-h-screen bg-
|
|
51
|
+
<body class="min-h-screen bg-gradient-to-br from-slate-50 via-white to-slate-100 font-sans">
|
|
52
|
+
|
|
53
|
+
<!-- Hero Header -->
|
|
54
|
+
<header class="bg-gradient-to-br from-[#00FF99] to-[#007370] text-white py-16">
|
|
55
|
+
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
|
56
|
+
<h1 class="text-4xl lg:text-5xl font-extrabold mb-4 drop-shadow-lg">SenangWebs Epoch</h1>
|
|
57
|
+
<p class="text-xl text-white/90 max-w-2xl mx-auto">A lightweight JavaScript library for creating dynamic countdown timers and time displays. Perfect for any time-sensitive content.</p>
|
|
58
|
+
</div>
|
|
59
|
+
</header>
|
|
13
60
|
|
|
14
61
|
<!-- Main Content -->
|
|
15
|
-
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<div
|
|
26
|
-
|
|
62
|
+
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
|
63
|
+
|
|
64
|
+
<!-- Section: Event Countdowns -->
|
|
65
|
+
<section class="mb-16">
|
|
66
|
+
<h2 class="text-2xl font-bold text-gray-800 mb-2 flex items-center gap-2"><span class="ss ss-calendar text-2xl"></span> Event Countdowns</h2>
|
|
67
|
+
<p class="text-gray-600 mb-6">Perfect for building anticipation for upcoming events, launches, or celebrations.</p>
|
|
68
|
+
|
|
69
|
+
<div class="grid md:grid-cols-2 gap-6">
|
|
70
|
+
|
|
71
|
+
<!-- New Year Countdown -->
|
|
72
|
+
<div class="glass-card rounded-2xl p-6 shadow-lg">
|
|
73
|
+
<div class="flex items-center gap-3 mb-4">
|
|
74
|
+
<span class="ss ss-star text-3xl text-amber-500"></span>
|
|
75
|
+
<div>
|
|
76
|
+
<h3 class="text-lg font-bold text-gray-800">New Year Countdown</h3>
|
|
77
|
+
<p class="text-sm text-gray-500">Count down to the new year celebration</p>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
<div id="new-year" data-swe data-swe-countdown-end="2027-01-01 00:00:00" class="flex flex-wrap gap-3 justify-center">
|
|
81
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-amber-400 to-orange-500 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
82
|
+
<span data-swe-day data-swe-format="ddd" class="text-2xl font-bold"></span>
|
|
83
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Days</span>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-amber-400 to-orange-500 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
86
|
+
<span data-swe-hour data-swe-format="HH" class="text-2xl font-bold"></span>
|
|
87
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Hours</span>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-amber-400 to-orange-500 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
90
|
+
<span data-swe-minute data-swe-format="mm" class="text-2xl font-bold"></span>
|
|
91
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Mins</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-amber-400 to-orange-500 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
94
|
+
<span data-swe-second data-swe-format="ss" class="text-2xl font-bold"></span>
|
|
95
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Secs</span>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<!-- Product Launch -->
|
|
101
|
+
<div class="glass-card rounded-2xl p-6 shadow-lg">
|
|
102
|
+
<div class="flex items-center gap-3 mb-4">
|
|
103
|
+
<span class="ss ss-bolt text-3xl text-blue-500"></span>
|
|
104
|
+
<div>
|
|
105
|
+
<h3 class="text-lg font-bold text-gray-800">Product Launch</h3>
|
|
106
|
+
<p class="text-sm text-gray-500">Building excitement for your next big release</p>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
<div id="product-launch" data-swe data-swe-countdown-end="2026-06-15 09:00:00" class="flex flex-wrap gap-3 justify-center">
|
|
110
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-blue-500 to-cyan-400 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
111
|
+
<span data-swe-month data-swe-format="mm" class="text-2xl font-bold"></span>
|
|
112
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Months</span>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-blue-500 to-cyan-400 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
115
|
+
<span data-swe-day data-swe-format="dd" class="text-2xl font-bold"></span>
|
|
116
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Days</span>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-blue-500 to-cyan-400 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
119
|
+
<span data-swe-hour data-swe-format="HH" class="text-2xl font-bold"></span>
|
|
120
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Hours</span>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-blue-500 to-cyan-400 text-white rounded-xl p-4 min-w-[70px] shadow-lg">
|
|
123
|
+
<span data-swe-minute data-swe-format="mm" class="text-2xl font-bold"></span>
|
|
124
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Mins</span>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
</div>
|
|
130
|
+
</section>
|
|
131
|
+
|
|
132
|
+
<!-- Section: E-Commerce -->
|
|
133
|
+
<section class="mb-16">
|
|
134
|
+
<h2 class="text-2xl font-bold text-gray-800 mb-2 flex items-center gap-2"><span class="ss ss-shopping-cart text-2xl"></span> E-Commerce & Sales</h2>
|
|
135
|
+
<p class="text-gray-600 mb-6">Create urgency and drive conversions with time-limited offers.</p>
|
|
136
|
+
|
|
137
|
+
<div class="grid md:grid-cols-2 gap-6">
|
|
138
|
+
|
|
139
|
+
<!-- Flash Sale -->
|
|
140
|
+
<div class="bg-gradient-to-br from-red-600 to-rose-700 rounded-2xl p-6 shadow-xl flash-sale-glow">
|
|
141
|
+
<div class="flex items-center gap-3 mb-4">
|
|
142
|
+
<span class="ss ss-thunder text-3xl text-yellow-300 animate-bounce"></span>
|
|
143
|
+
<div>
|
|
144
|
+
<h3 class="text-lg font-bold text-white">Flash Sale Ending Soon!</h3>
|
|
145
|
+
<p class="text-sm text-white/80">Up to 70% OFF - Limited Time</p>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
<div id="flash-sale" class="flex flex-wrap gap-3 justify-center">
|
|
149
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
150
|
+
<span data-swe-hour data-swe-format="HH" class="text-3xl font-bold"></span>
|
|
151
|
+
<span class="text-xs uppercase tracking-wider">Hours</span>
|
|
152
|
+
</div>
|
|
153
|
+
<div class="text-3xl font-bold text-white self-center">:</div>
|
|
154
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
155
|
+
<span data-swe-minute data-swe-format="mm" class="text-3xl font-bold"></span>
|
|
156
|
+
<span class="text-xs uppercase tracking-wider">Mins</span>
|
|
157
|
+
</div>
|
|
158
|
+
<div class="text-3xl font-bold text-white self-center">:</div>
|
|
159
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
160
|
+
<span data-swe-second data-swe-format="ss" class="text-3xl font-bold"></span>
|
|
161
|
+
<span class="text-xs uppercase tracking-wider">Secs</span>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
<button class="mt-4 w-full bg-white text-red-600 font-bold py-3 px-6 rounded-xl hover:bg-gray-100 transition-colors">
|
|
165
|
+
Shop Now →
|
|
166
|
+
</button>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<!-- Limited Offer -->
|
|
170
|
+
<div class="bg-gradient-to-br from-emerald-500 to-teal-600 rounded-2xl p-6 shadow-xl">
|
|
171
|
+
<div class="flex items-center gap-3 mb-4">
|
|
172
|
+
<span class="ss ss-gift text-3xl text-white"></span>
|
|
173
|
+
<div>
|
|
174
|
+
<h3 class="text-lg font-bold text-white">Free Shipping Offer</h3>
|
|
175
|
+
<p class="text-sm text-white/80">Order now to get free delivery!</p>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<div id="shipping-offer" class="flex flex-wrap gap-3 justify-center">
|
|
179
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
180
|
+
<span data-swe-hour data-swe-format="HH" class="text-3xl font-bold"></span>
|
|
181
|
+
<span class="text-xs uppercase tracking-wider">Hours</span>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
184
|
+
<span data-swe-minute data-swe-format="mm" class="text-3xl font-bold"></span>
|
|
185
|
+
<span class="text-xs uppercase tracking-wider">Mins</span>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="timer-unit flex flex-col items-center bg-white/20 backdrop-blur text-white rounded-xl p-4 min-w-[70px]">
|
|
188
|
+
<span data-swe-second data-swe-format="ss" class="text-3xl font-bold"></span>
|
|
189
|
+
<span class="text-xs uppercase tracking-wider">Secs</span>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
<div class="mt-4 text-center text-white/90 text-sm">
|
|
193
|
+
<span class="ss ss-truck mr-1"></span> Orders placed within this time ship FREE!
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
27
197
|
</div>
|
|
198
|
+
</section>
|
|
199
|
+
|
|
200
|
+
<!-- Section: Productivity & Utility -->
|
|
201
|
+
<section class="mb-16">
|
|
202
|
+
<h2 class="text-2xl font-bold text-gray-800 mb-2 flex items-center gap-2"><span class="ss ss-cog-6-tooth text-2xl"></span> Productivity & Utility</h2>
|
|
203
|
+
<p class="text-gray-600 mb-6">Useful timers for sessions, focus work, and everyday tasks.</p>
|
|
204
|
+
|
|
205
|
+
<div class="grid md:grid-cols-3 gap-6">
|
|
206
|
+
|
|
207
|
+
<!-- Session Timer -->
|
|
208
|
+
<div class="glass-card rounded-2xl p-6 shadow-lg">
|
|
209
|
+
<div class="flex items-center gap-3 mb-4">
|
|
210
|
+
<span class="ss ss-lock-closed text-3xl text-gray-700"></span>
|
|
211
|
+
<div>
|
|
212
|
+
<h3 class="text-lg font-bold text-gray-800">Session Timeout</h3>
|
|
213
|
+
<p class="text-sm text-gray-500">Auto-logout warning timer</p>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
<div id="session-timer" class="text-center">
|
|
217
|
+
<div class="inline-flex items-center gap-2 bg-yellow-100 text-yellow-800 rounded-full px-4 py-2 text-sm font-medium mb-3">
|
|
218
|
+
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
|
|
219
|
+
Session expires in
|
|
220
|
+
</div>
|
|
221
|
+
<div class="flex justify-center gap-2">
|
|
222
|
+
<div class="timer-unit bg-gray-800 text-white rounded-lg px-4 py-3 min-w-[60px]">
|
|
223
|
+
<span data-swe-minute data-swe-format="mm" class="text-2xl font-mono font-bold"></span>
|
|
224
|
+
</div>
|
|
225
|
+
<span class="text-2xl font-bold text-gray-400 self-center">:</span>
|
|
226
|
+
<div class="timer-unit bg-gray-800 text-white rounded-lg px-4 py-3 min-w-[60px]">
|
|
227
|
+
<span data-swe-second data-swe-format="ss" class="text-2xl font-mono font-bold"></span>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<!-- Pomodoro Timer -->
|
|
234
|
+
<div class="glass-card rounded-2xl p-6 shadow-lg">
|
|
235
|
+
<div class="flex items-center gap-3 mb-4">
|
|
236
|
+
<span class="ss ss-crosshair text-3xl text-red-500"></span>
|
|
237
|
+
<div>
|
|
238
|
+
<h3 class="text-lg font-bold text-gray-800">Pomodoro Timer</h3>
|
|
239
|
+
<p class="text-sm text-gray-500">25-minute focus sessions</p>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
<div id="pomodoro" class="text-center">
|
|
243
|
+
<div class="relative inline-flex items-center justify-center w-32 h-32 rounded-full bg-gradient-to-br from-red-400 to-red-600 shadow-lg mb-3">
|
|
244
|
+
<div class="flex items-baseline gap-1 text-white">
|
|
245
|
+
<span data-swe-minute data-swe-format="mm" class="text-3xl font-bold"></span>
|
|
246
|
+
<span class="text-xl">:</span>
|
|
247
|
+
<span data-swe-second data-swe-format="ss" class="text-3xl font-bold"></span>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="flex justify-center gap-2">
|
|
251
|
+
<button id="pomodoro-pause" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-4 py-2 rounded-lg text-sm font-medium transition-colors">Pause</button>
|
|
252
|
+
<button id="pomodoro-reset" class="bg-red-100 hover:bg-red-200 text-red-700 px-4 py-2 rounded-lg text-sm font-medium transition-colors">Reset</button>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
<!-- Current Time Clock -->
|
|
258
|
+
<div class="glass-card rounded-2xl p-6 shadow-lg">
|
|
259
|
+
<div class="flex items-center gap-3 mb-4">
|
|
260
|
+
<span class="ss ss-clock text-3xl text-slate-700"></span>
|
|
261
|
+
<div>
|
|
262
|
+
<h3 class="text-lg font-bold text-gray-800">Live Clock</h3>
|
|
263
|
+
<p class="text-sm text-gray-500">Current local time display</p>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
<div id="live-clock" data-swe data-swe-current class="text-center">
|
|
267
|
+
<div class="inline-flex items-center gap-1 bg-gradient-to-br from-slate-700 to-slate-900 text-white rounded-xl p-4 shadow-lg">
|
|
268
|
+
<span data-swe-hour data-swe-format="HH" class="text-4xl font-mono font-bold"></span>
|
|
269
|
+
<span class="text-4xl font-bold animate-pulse">:</span>
|
|
270
|
+
<span data-swe-minute data-swe-format="mm" class="text-4xl font-mono font-bold"></span>
|
|
271
|
+
<span class="text-4xl font-bold animate-pulse">:</span>
|
|
272
|
+
<span data-swe-second data-swe-format="ss" class="text-4xl font-mono font-bold"></span>
|
|
273
|
+
</div>
|
|
274
|
+
<p class="mt-3 text-gray-500 text-sm">Auto-updates every second</p>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
28
277
|
|
|
29
|
-
<!-- Countdown for 10 seconds -->
|
|
30
|
-
<div data-swe data-swe-countdown-duration="10">
|
|
31
|
-
<div data-swe-second data-swe-format="ss"></div>
|
|
32
278
|
</div>
|
|
279
|
+
</section>
|
|
33
280
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
281
|
+
<!-- Section: Interactive Demo -->
|
|
282
|
+
<section class="mb-16">
|
|
283
|
+
<h2 class="text-2xl font-bold text-gray-800 mb-2 flex items-center gap-2"><span class="ss ss-controller text-2xl"></span> Interactive Controls</h2>
|
|
284
|
+
<p class="text-gray-600 mb-6">Demonstrates the full control API with pause, resume, and reset functionality.</p>
|
|
285
|
+
|
|
286
|
+
<div class="glass-card rounded-2xl p-8 shadow-lg max-w-xl mx-auto">
|
|
287
|
+
<div class="text-center mb-6">
|
|
288
|
+
<h3 class="text-lg font-bold text-gray-800 mb-2">Controllable Timer</h3>
|
|
289
|
+
<p class="text-sm text-gray-500">A 60-second timer with full controls</p>
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
<div id="interactive-timer" class="flex justify-center gap-4 mb-6">
|
|
293
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-violet-500 to-purple-600 text-white rounded-xl p-5 min-w-[80px] shadow-lg">
|
|
294
|
+
<span data-swe-minute data-swe-format="mm" class="text-4xl font-bold"></span>
|
|
295
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Mins</span>
|
|
296
|
+
</div>
|
|
297
|
+
<div class="timer-unit flex flex-col items-center bg-gradient-to-br from-violet-500 to-purple-600 text-white rounded-xl p-5 min-w-[80px] shadow-lg">
|
|
298
|
+
<span data-swe-second data-swe-format="ss" class="text-4xl font-bold"></span>
|
|
299
|
+
<span class="text-xs uppercase tracking-wider opacity-90">Secs</span>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<div class="flex flex-wrap justify-center gap-3">
|
|
304
|
+
<button id="btn-start" class="flex items-center gap-2 bg-emerald-500 hover:bg-emerald-600 text-white px-5 py-2.5 rounded-xl font-medium transition-colors shadow-md">
|
|
305
|
+
<span class="ss ss-play text-lg"></span>
|
|
306
|
+
Start
|
|
307
|
+
</button>
|
|
308
|
+
<button id="btn-pause" class="flex items-center gap-2 bg-amber-500 hover:bg-amber-600 text-white px-5 py-2.5 rounded-xl font-medium transition-colors shadow-md">
|
|
309
|
+
<span class="ss ss-pause text-lg"></span>
|
|
310
|
+
Pause
|
|
311
|
+
</button>
|
|
312
|
+
<button id="btn-resume" class="flex items-center gap-2 bg-blue-500 hover:bg-blue-600 text-white px-5 py-2.5 rounded-xl font-medium transition-colors shadow-md">
|
|
313
|
+
<span class="ss ss-play-circle text-lg"></span>
|
|
314
|
+
Resume
|
|
315
|
+
</button>
|
|
316
|
+
<button id="btn-reset" class="flex items-center gap-2 bg-rose-500 hover:bg-rose-600 text-white px-5 py-2.5 rounded-xl font-medium transition-colors shadow-md">
|
|
317
|
+
<span class="ss ss-arrow-path text-lg"></span>
|
|
318
|
+
Reset
|
|
319
|
+
</button>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
<div id="event-log" class="mt-6 bg-gray-900 text-green-400 font-mono text-xs p-4 rounded-xl max-h-32 overflow-y-auto">
|
|
323
|
+
<p class="text-gray-500"># Event log - interactions will appear here</p>
|
|
324
|
+
</div>
|
|
39
325
|
</div>
|
|
326
|
+
</section>
|
|
40
327
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
328
|
+
<!-- Section: Code Examples -->
|
|
329
|
+
<section class="mb-16">
|
|
330
|
+
<h2 class="text-2xl font-bold text-gray-800 mb-2 flex items-center gap-2"><span class="ss ss-code text-2xl"></span> Quick Start Guide</h2>
|
|
331
|
+
<p class="text-gray-600 mb-6">Get started with SenangWebs Epoch in seconds.</p>
|
|
332
|
+
|
|
333
|
+
<div class="grid md:grid-cols-2 gap-6">
|
|
334
|
+
<div class="bg-gray-900 rounded-2xl p-6 shadow-xl">
|
|
335
|
+
<h4 class="text-white font-semibold mb-4 flex items-center gap-2">
|
|
336
|
+
<span class="bg-green-500 text-xs px-2 py-1 rounded">HTML</span>
|
|
337
|
+
Data Attribute Method
|
|
338
|
+
</h4>
|
|
339
|
+
<pre class="text-sm text-gray-300 overflow-x-auto"><code><!-- Countdown to date -->
|
|
340
|
+
<div data-swe data-swe-countdown-end="2026-12-31 00:00:00">
|
|
341
|
+
<div data-swe-day data-swe-format="dd"></div>
|
|
342
|
+
<div data-swe-hour data-swe-format="HH"></div>
|
|
343
|
+
<div data-swe-minute data-swe-format="mm"></div>
|
|
344
|
+
<div data-swe-second data-swe-format="ss"></div>
|
|
345
|
+
</div></code></pre>
|
|
346
|
+
</div>
|
|
347
|
+
|
|
348
|
+
<div class="bg-gray-900 rounded-2xl p-6 shadow-xl">
|
|
349
|
+
<h4 class="text-white font-semibold mb-4 flex items-center gap-2">
|
|
350
|
+
<span class="bg-yellow-500 text-xs px-2 py-1 rounded text-black">JS</span>
|
|
351
|
+
JavaScript Method
|
|
352
|
+
</h4>
|
|
353
|
+
<pre class="text-sm text-gray-300 overflow-x-auto"><code>const timer = new SWE(element, {
|
|
354
|
+
autostart: true,
|
|
355
|
+
duration: 300, // 5 minutes
|
|
356
|
+
onTick: () => console.log('Tick!'),
|
|
357
|
+
onEnd: () => alert('Time is up!')
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Control methods
|
|
361
|
+
timer.pause();
|
|
362
|
+
timer.resume();
|
|
363
|
+
timer.reset();</code></pre>
|
|
364
|
+
</div>
|
|
46
365
|
</div>
|
|
47
|
-
</
|
|
366
|
+
</section>
|
|
48
367
|
|
|
49
368
|
</main>
|
|
50
369
|
|
|
51
370
|
<script src="../dist/swe.js"></script>
|
|
52
371
|
|
|
53
372
|
<script>
|
|
54
|
-
let timer;
|
|
55
373
|
document.addEventListener('DOMContentLoaded', () => {
|
|
56
|
-
|
|
374
|
+
|
|
375
|
+
// Flash Sale - 2 hours countdown
|
|
376
|
+
const flashSale = new SWE(document.querySelector('#flash-sale'), {
|
|
57
377
|
autostart: true,
|
|
58
|
-
duration:
|
|
59
|
-
// countdownEnd: '2025-01-01 00:00:00',
|
|
60
|
-
onTick: () => {
|
|
61
|
-
console.log('Timer ticked!');
|
|
62
|
-
},
|
|
378
|
+
duration: 7200, // 2 hours
|
|
63
379
|
onEnd: () => {
|
|
64
|
-
|
|
380
|
+
document.querySelector('#flash-sale').innerHTML = '<p class="text-white text-xl font-bold">Sale Ended!</p>';
|
|
65
381
|
}
|
|
66
382
|
});
|
|
67
383
|
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
384
|
+
// Free Shipping Offer - 4 hours
|
|
385
|
+
const shippingOffer = new SWE(document.querySelector('#shipping-offer'), {
|
|
386
|
+
autostart: true,
|
|
387
|
+
duration: 14400, // 4 hours
|
|
71
388
|
});
|
|
389
|
+
|
|
390
|
+
// Session Timer - 5 minutes
|
|
391
|
+
const sessionTimer = new SWE(document.querySelector('#session-timer'), {
|
|
392
|
+
autostart: true,
|
|
393
|
+
duration: 300,
|
|
394
|
+
onEnd: () => {
|
|
395
|
+
alert('Your session has expired! Please log in again.');
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Pomodoro Timer - 25 minutes
|
|
400
|
+
let pomodoroTimer = new SWE(document.querySelector('#pomodoro'), {
|
|
401
|
+
autostart: true,
|
|
402
|
+
duration: 1500, // 25 minutes
|
|
403
|
+
onEnd: () => {
|
|
404
|
+
alert('🍅 Pomodoro complete! Take a 5-minute break.');
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
document.querySelector('#pomodoro-pause').addEventListener('click', () => {
|
|
409
|
+
pomodoroTimer.isPaused ? pomodoroTimer.resume() : pomodoroTimer.pause();
|
|
410
|
+
document.querySelector('#pomodoro-pause').textContent = pomodoroTimer.isPaused ? 'Resume' : 'Pause';
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
document.querySelector('#pomodoro-reset').addEventListener('click', () => {
|
|
414
|
+
pomodoroTimer.reset();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Interactive Timer - 60 seconds
|
|
418
|
+
const interactiveTimer = new SWE(document.querySelector('#interactive-timer'), {
|
|
419
|
+
autostart: false,
|
|
420
|
+
duration: 60,
|
|
421
|
+
onStart: () => logEvent('Timer started'),
|
|
422
|
+
onPause: () => logEvent('Timer paused'),
|
|
423
|
+
onResume: () => logEvent('Timer resumed'),
|
|
424
|
+
onReset: () => logEvent('Timer reset'),
|
|
425
|
+
onTick: () => {}, // Silent tick
|
|
426
|
+
onEnd: () => logEvent('⏰ Timer ended!')
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Control buttons
|
|
430
|
+
document.querySelector('#btn-start').addEventListener('click', () => interactiveTimer.start());
|
|
431
|
+
document.querySelector('#btn-pause').addEventListener('click', () => interactiveTimer.pause());
|
|
432
|
+
document.querySelector('#btn-resume').addEventListener('click', () => interactiveTimer.resume());
|
|
433
|
+
document.querySelector('#btn-reset').addEventListener('click', () => interactiveTimer.reset());
|
|
434
|
+
|
|
435
|
+
// Event log
|
|
436
|
+
function logEvent(message) {
|
|
437
|
+
const log = document.querySelector('#event-log');
|
|
438
|
+
const time = new Date().toLocaleTimeString();
|
|
439
|
+
log.innerHTML += `<p>[${time}] ${message}</p>`;
|
|
440
|
+
log.scrollTop = log.scrollHeight;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Listen for events
|
|
444
|
+
const timerEl = document.querySelector('#interactive-timer');
|
|
445
|
+
['start', 'pause', 'resume', 'reset', 'end'].forEach(event => {
|
|
446
|
+
timerEl.addEventListener(`swe:${event}`, () => {
|
|
447
|
+
logEvent(`Event: swe:${event} fired`);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
72
451
|
});
|
|
73
452
|
</script>
|
|
74
453
|
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "senangwebs-epoch",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Lightweight JavaScript library for creating dynamic countdown timers and time displays.",
|
|
5
|
-
"main": "
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
"@babel/
|
|
20
|
-
"babel-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"webpack
|
|
26
|
-
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "senangwebs-epoch",
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "Lightweight JavaScript library for creating dynamic countdown timers and time displays.",
|
|
5
|
+
"main": "dist/swe.js",
|
|
6
|
+
"module": "dist/swe.js",
|
|
7
|
+
"directories": {
|
|
8
|
+
"example": "examples"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "webpack --mode production",
|
|
12
|
+
"dev": "webpack --mode development --watch",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"keywords": ["countdown", "timer", "time", "epoch", "javascript", "date", "clock"],
|
|
16
|
+
"author": "a-hakim",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@babel/core": "^7.25.8",
|
|
20
|
+
"@babel/preset-env": "^7.25.8",
|
|
21
|
+
"babel-loader": "^9.2.1",
|
|
22
|
+
"css-loader": "^7.1.2",
|
|
23
|
+
"mini-css-extract-plugin": "^2.9.1",
|
|
24
|
+
"style-loader": "^4.0.0",
|
|
25
|
+
"webpack": "^5.95.0",
|
|
26
|
+
"webpack-cli": "^5.1.4"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/js/swe.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SenangWebs Epoch (SWE) - A JavaScript library for countdown timers and time display
|
|
3
|
-
* Version: 1.1.
|
|
3
|
+
* Version: 1.1.2
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import '../css/swe.css';
|
|
7
|
+
|
|
6
8
|
class SWE {
|
|
7
9
|
constructor(element, options = {}) {
|
|
8
10
|
this.element = element;
|
|
@@ -208,20 +210,38 @@ class SWE {
|
|
|
208
210
|
}
|
|
209
211
|
|
|
210
212
|
calculateTimeUnits(milliseconds) {
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
|
|
213
|
+
// Calculate using proper date math for accuracy
|
|
214
|
+
const totalSeconds = Math.floor(milliseconds / 1000);
|
|
215
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
216
|
+
const totalHours = Math.floor(totalMinutes / 60);
|
|
217
|
+
const totalDays = Math.floor(totalHours / 24);
|
|
218
|
+
|
|
219
|
+
// Use date-based calculation for months and years
|
|
220
|
+
const now = new Date();
|
|
221
|
+
const futureDate = new Date(now.getTime() + milliseconds);
|
|
222
|
+
|
|
223
|
+
let years = futureDate.getFullYear() - now.getFullYear();
|
|
224
|
+
let months = futureDate.getMonth() - now.getMonth();
|
|
225
|
+
let days = futureDate.getDate() - now.getDate();
|
|
226
|
+
|
|
227
|
+
// Normalize negative values
|
|
228
|
+
if (days < 0) {
|
|
229
|
+
months--;
|
|
230
|
+
const prevMonth = new Date(futureDate.getFullYear(), futureDate.getMonth(), 0);
|
|
231
|
+
days += prevMonth.getDate();
|
|
232
|
+
}
|
|
233
|
+
if (months < 0) {
|
|
234
|
+
years--;
|
|
235
|
+
months += 12;
|
|
236
|
+
}
|
|
217
237
|
|
|
218
238
|
return {
|
|
219
239
|
year: years,
|
|
220
|
-
month: months
|
|
221
|
-
day: days
|
|
222
|
-
hour:
|
|
223
|
-
minute:
|
|
224
|
-
second:
|
|
240
|
+
month: months,
|
|
241
|
+
day: days,
|
|
242
|
+
hour: totalHours % 24,
|
|
243
|
+
minute: totalMinutes % 60,
|
|
244
|
+
second: totalSeconds % 60
|
|
225
245
|
};
|
|
226
246
|
}
|
|
227
247
|
|
|
@@ -252,7 +272,21 @@ class SWE {
|
|
|
252
272
|
|
|
253
273
|
resume() {
|
|
254
274
|
if (this.isPaused) {
|
|
255
|
-
this.
|
|
275
|
+
this.isPaused = false;
|
|
276
|
+
this.startTime = Date.now();
|
|
277
|
+
|
|
278
|
+
switch (this.mode) {
|
|
279
|
+
case 'countdown-end':
|
|
280
|
+
this.startCountdownToDate();
|
|
281
|
+
break;
|
|
282
|
+
case 'countdown-duration':
|
|
283
|
+
this.startCountdownDuration();
|
|
284
|
+
break;
|
|
285
|
+
case 'current':
|
|
286
|
+
this.startCurrentTime();
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
|
|
256
290
|
this.dispatchEvent('resume');
|
|
257
291
|
}
|
|
258
292
|
}
|
|
@@ -279,10 +313,13 @@ class SWE {
|
|
|
279
313
|
}
|
|
280
314
|
|
|
281
315
|
stop() {
|
|
316
|
+
const wasRunning = this.intervalId !== null;
|
|
282
317
|
if (this.intervalId) {
|
|
283
318
|
clearInterval(this.intervalId);
|
|
284
319
|
this.intervalId = null;
|
|
285
|
-
|
|
320
|
+
}
|
|
321
|
+
this.isPaused = false;
|
|
322
|
+
if (wasRunning) {
|
|
286
323
|
this.dispatchEvent('stop');
|
|
287
324
|
}
|
|
288
325
|
}
|
package/webpack.config.js
CHANGED
|
@@ -2,12 +2,9 @@ const path = require('path');
|
|
|
2
2
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
entry:
|
|
6
|
-
swe: './src/js/swe.js',
|
|
7
|
-
style: './src/css/swe.css',
|
|
8
|
-
},
|
|
5
|
+
entry: './src/js/swe.js',
|
|
9
6
|
output: {
|
|
10
|
-
filename: '
|
|
7
|
+
filename: 'swe.js',
|
|
11
8
|
path: path.resolve(__dirname, 'dist'),
|
|
12
9
|
library: {
|
|
13
10
|
name: 'SWE',
|
package/dist/style.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SWE=t():e.SWE=t()}(this,(()=>(()=>{"use strict";var e={};return e.default})()));
|