zero-hour 1.3.1 → 2.0.0

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 CHANGED
@@ -1,42 +1,39 @@
1
- <p align="center"><strong>zero-hour</strong></p>
1
+ # zero-hour
2
2
 
3
- <div align="center">
4
- <p align="center">ZeroHour is a tiny countdown Web Component. It registers <code>&lt;countdown-timer&gt;</code> that renders a <code>DD:HH:MM:SS</code> countdown (with configurable visible units), counts down to a target date/time with an optional UTC offset, ticks on exact second boundaries, and fires a <code>done</code> event when it reaches zero.</p>
3
+ Tiny countdown Web Component that registers `<countdown-timer>` with a configurable DD:HH:MM:SS display.
5
4
 
6
5
  [![npm](https://img.shields.io/npm/v/zero-hour.svg?colorB=brightgreen)](https://www.npmjs.com/package/zero-hour)
7
- [![GitHub package version](https://img.shields.io/github/package-json/v/ux-ui-pro/zero-hour.svg)](https://github.com/ux-ui-pro/zero-hour)
8
- [![NPM Downloads](https://img.shields.io/npm/dm/zero-hour.svg?style=flat)](https://www.npmjs.org/package/zero-hour)
6
+ [![NPM Downloads](https://img.shields.io/npm/dm/zero-hour.svg?style=flat)](https://www.npmjs.com/package/zero-hour)
9
7
 
10
- <a href="https://codepen.io/ux-ui/pen/MYyMpPw">Demo</a>
11
- </div>
12
- <br>
8
+ [Demo](https://codepen.io/ux-ui/pen/MYyMpPw)
13
9
 
14
- ➠ **Install**
10
+ ---
15
11
 
16
- ```console
17
- yarn add zero-hour
18
- ```
19
- <br>
12
+ - Registers `<countdown-timer>` via `customElements.define` on import.
13
+ - Configurable visible units (`d`, `h`, `m`, `s`) and UTC offset for the target moment.
14
+ - Ticks on exact second boundaries; fires a `done` event once when the countdown reaches zero.
15
+ - Optional digit sprites with `static` or `scroll` transition mode.
16
+ - Built-in CSS sidecar and `zeroHourCssText` export for shadow-root styling.
20
17
 
21
- ➠ **Import**
18
+ ---
22
19
 
23
- ```javascript
24
- // Registers <countdown-timer> via customElements.define(...)
25
- import 'zero-hour';
20
+ ## Installation
26
21
 
27
- // Optional helper: subscribe to `done` and apply stylesheets
28
- import { initCountdownTimers } from 'zero-hour';
22
+ ```bash
23
+ npm install zero-hour
29
24
  ```
30
- <br>
31
25
 
32
- **Usage**
26
+ Optional stylesheet (sidecar):
33
27
 
34
- ```javascript
35
- // After importing 'zero-hour', the element is registered.
36
- // Then just place <countdown-timer> in your HTML (see below).
28
+ ```bash
29
+ # import in your bundler entry, or link in HTML:
30
+ # import 'zero-hour/zero-hour.css';
37
31
  ```
38
32
 
39
- <sub>HTML: default start (autostart=true)</sub>
33
+ ## Quick Start
34
+
35
+ Import the package to register the element, then place it in your markup:
36
+
40
37
  ```html
41
38
  <countdown-timer
42
39
  digits-url="/sprites/digits.webp"
@@ -47,111 +44,112 @@ import { initCountdownTimers } from 'zero-hour';
47
44
  ></countdown-timer>
48
45
  ```
49
46
 
50
- <sub>JS: subscribe to completion + optional styles</sub>
51
- ```javascript
52
- import { initCountdownTimers } from 'zero-hour';
47
+ ```js
48
+ import 'zero-hour';
49
+ ```
50
+
51
+ Subscribe to completion and apply optional styles:
52
+
53
+ ```js
54
+ import { initCountdownTimers, zeroHourCssText } from 'zero-hour';
53
55
 
54
56
  initCountdownTimers({
55
57
  selector: 'countdown-timer',
56
58
  onDone: (el) => {
57
- // The component dispatches: el.dispatchEvent(new CustomEvent('done'))
58
- // Note: if the timer is already complete (e.g. user opened the page after the target time),
59
- // `initCountdownTimers` will call `onDone` immediately (catch-up).
60
59
  el.classList.add('is-done');
61
60
  },
62
- // Optional styles:
63
- // - CSSStyleSheet (constructable stylesheet)
64
- // - string (e.g. imported via ?raw from your CSS/SCSS pipeline)
65
- // stylesheet: myCssStyleSheet,
61
+ stylesheet: zeroHourCssText,
66
62
  });
67
63
  ```
68
64
 
69
- <sub>JS: custom styles from `?raw` (CSS/SCSS)</sub>
70
- ```javascript
71
- import { initCountdownTimers } from 'zero-hour';
72
- import ZeroHourCss from './assets/scss/components/zero-hour.scss?raw';
65
+ ## API
66
+
67
+ - **`import 'zero-hour'`** — registers `<countdown-timer>` (side effect).
68
+ - **`initCountdownTimers(options?)`** finds elements, optional `onDone` / `stylesheet` helpers.
69
+ - **`zeroHourCssText`** — minified default CSS text shipped with the package.
73
70
 
71
+ Element instance methods (on `<countdown-timer>` after import):
72
+
73
+ - **`start()`** — starts or restarts the countdown (`digits-url` required).
74
+ - **`stop()`** — stops the timer and clears the scheduled tick.
75
+ - **`reset()`** — clears the done flag; restarts when `autostart=true`.
76
+ - **`isRunning()`** — `true` when a tick is scheduled.
77
+ - **`isDone()`** — `true` when the target moment is in the past.
78
+ - **`adoptStylesheet(sheet)`** — replaces `adoptedStyleSheets` in the shadow root.
79
+ - **`adoptStyles(text)`** — applies CSS text via constructable stylesheet or `<style>` fallback.
80
+
81
+ ## Options
82
+
83
+ | Option (attribute) | Type | Default | Description |
84
+ |:-------------------|:-----|:--------|:------------|
85
+ | `digits-url` | `string` | — | URL to the digits sprite sheet. Required for the graphical display. |
86
+ | `separator-url` | `string` | `null` | URL to the separator sprite (e.g. colon). Omit to hide separators. |
87
+ | `autostart` | `boolean` | `true` | Auto-start on connect (`autostart` or `autostart="false"`). |
88
+ | `date` | `YYYY-MM-DD` | — | Target date. Without `date` the timer resolves to zero. |
89
+ | `time` | `HH:MM[:SS]` | `00:00:00` | Target time. |
90
+ | `utc` | `UTC±H[:MM]` or `±H[:MM]` | `UTC+0` | UTC offset for the target moment (e.g. `UTC+03:00`, `UTC-5`). |
91
+ | `units` | `string` | `"d:h:m:s"` | Visible groups using `d`, `h`, `m`, `s` separated by `:` (e.g. `"h:m:s"`). |
92
+ | `mode` | `"static"` \| `"scroll"` | `"static"` | Digit transition mode (`scroll` = rolling effect). |
93
+
94
+ ## Events
95
+
96
+ | Event | Description |
97
+ |:------|:------------|
98
+ | `done` | Fired once when the countdown reaches zero (again after `reset()`). |
99
+
100
+ ## Methods
101
+
102
+ ```js
74
103
  initCountdownTimers({
75
- stylesheet: ZeroHourCss,
76
- });
104
+ selector?: string; // default: 'countdown-timer'
105
+ onDone?: (el: HTMLElement) => void;
106
+ stylesheet?: CSSStyleSheet | string | null;
107
+ }): HTMLElement[]
77
108
  ```
78
109
 
79
- <sub>JS: default styles shipped with the package</sub>
80
- ```javascript
81
- import { initCountdownTimers, zeroHourCssText } from 'zero-hour';
110
+ If a timer is already complete at init time, `onDone` is called immediately (catch-up).
82
111
 
83
- // Option A: use the built-in CSS text export
84
- initCountdownTimers({
85
- stylesheet: zeroHourCssText,
86
- });
112
+ ## Styling
87
113
 
88
- // Option B: import the package CSS file as raw text (your bundler must support ?raw)
89
- // import ZeroHourCss from 'zero-hour/zero-hour.css?raw';
90
- // initCountdownTimers({ stylesheet: ZeroHourCss });
91
- ```
114
+ Default package CSS:
92
115
 
93
- <sub>JS: manual control (start/stop/reset)</sub>
94
- ```javascript
95
- const el = document.querySelector('countdown-timer');
96
- // @ts-expect-error: methods exist on the custom element instance after import
97
- el?.stop();
98
- // @ts-expect-error
99
- el?.reset();
100
- // @ts-expect-error
101
- el?.start();
102
- ```
116
+ ```js
117
+ import { initCountdownTimers, zeroHourCssText } from 'zero-hour';
103
118
 
104
- <sub>Units (units)</sub>
105
- ```html
106
- <countdown-timer
107
- digits-url="/sprites/digits.webp"
108
- separator-url="/sprites/sep.webp"
109
- date="2025-12-31"
110
- time="23:59:59"
111
- utc="+03:00"
112
- units="h:m:s"
113
- ></countdown-timer>
119
+ initCountdownTimers({ stylesheet: zeroHourCssText });
114
120
  ```
115
- <br>
116
121
 
117
- **Options**
122
+ Or import the sidecar file in your bundler:
118
123
 
119
- | Option (attribute) | Type | Default | Description |
120
- |:--------------------:|:-----------------------:|:------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
121
- | `digits-url` | `string` | — | URL to the digits sprite sheet. **Required** for the graphical display (otherwise only a text fallback is updated in the a11y layer). |
122
- | `separator-url` | `string` | `null` | URL to the separator sprite (e.g. a colon). If omitted, separators are hidden. |
123
- | `autostart` | `boolean` | `true` | Auto-start on connect. Can be a boolean attribute (`autostart`) or a string (`autostart="false"`). |
124
- | `date` | `YYYY-MM-DD` | — | Target date. Without `date` the timer resolves to zero. |
125
- | `time` | `HH:MM[:SS]` | `00:00:00` | Target time. |
126
- | `utc` | `UTC±H[:MM]` or `±H[:MM]` | `UTC+0` | UTC offset used to compute the target moment. Examples: `utc="UTC+03:00"`, `utc="UTC-5"`. |
127
- | `units` | `string` | `"d:h:m:s"` | Visible groups pattern using `d`, `h`, `m`, `s` separated by `:` (e.g. `"h:m:s"`). Empty/invalid value falls back to showing all. |
124
+ ```js
125
+ import 'zero-hour/zero-hour.css';
126
+ ```
128
127
 
129
- <br>
128
+ Custom CSS text from your pipeline:
130
129
 
131
- ➠ **API Methods**
130
+ ```js
131
+ import { initCountdownTimers } from 'zero-hour';
132
+ import ZeroHourCss from './assets/scss/components/zero-hour.scss?raw';
132
133
 
133
- | Method | Description |
134
- |-------------------|--------------------------------------------------------------------------------------------------|
135
- | `initCountdownTimers({ selector?, onDone?, stylesheet? }): HTMLElement[]` | Finds elements by selector (default: `countdown-timer`), subscribes to the `done` event (when `onDone` is provided), and calls `onDone` immediately if a timer is already complete at init time (catch-up). Also optionally applies styles to each element (`stylesheet?: CSSStyleSheet \| string \| null`). When a string is provided, it is applied via `adoptedStyleSheets` when supported, otherwise via a `<style>` fallback inside the shadow root. |
136
- | `start(): void` | Starts/restarts the countdown (only runs when `digits-url` is set). |
137
- | `stop(): void` | Stops the timer and clears the scheduled tick. |
138
- | `reset(): void` | Clears the “done fired” flag and either starts again (if `autostart=true`) or renders a static initial value. |
139
- | `isRunning(): boolean` | Returns `true` if the timer is running and the next tick is scheduled. |
140
- | `isDone(): boolean` | Returns `true` if the computed target moment is in the past (logically complete), regardless of whether a `done` event listener was attached in time. |
141
- | `adoptStylesheet(sheet: CSSStyleSheet): void` | Replaces `adoptedStyleSheets` inside the component’s shadow root. |
134
+ initCountdownTimers({ stylesheet: ZeroHourCss });
135
+ ```
142
136
 
143
- <br>
137
+ Manual control:
144
138
 
145
- ➠ **Notes**
139
+ ```js
140
+ const el = document.querySelector('countdown-timer');
141
+ el?.stop();
142
+ el?.reset();
143
+ el?.start();
144
+ ```
146
145
 
147
- - Updates tick **exactly on second boundaries** (schedules the next tick to the next full second) to keep the display stable.
148
- - Days render as **two digits** and are capped at **99**.
149
- - `units` controls which groups (d/h/m/s) are visible. Separators are auto-hidden when `separator-url` is not set, or when a separator is not needed between visible groups.
150
- - The `done` event fires once per run (after `reset()` it can fire again).
151
- - Digit sprite must be horizontal, frames left-to-right: `0,1,2,3,4,5,6,7,8,9`. The frame index equals the digit.
146
+ ## Notes
152
147
 
153
- <br>
148
+ - Updates tick on exact second boundaries for a stable display.
149
+ - Days render as two digits, capped at 99.
150
+ - `units` controls visible d/h/m/s groups; separators hide when `separator-url` is unset.
151
+ - Digit sprite is horizontal, frames left-to-right `0–9`; frame index equals the digit value.
154
152
 
155
- **License**
153
+ ## License
156
154
 
157
- zero-hour is released under MIT license
155
+ MIT