svelte-analog-clock 0.2.0 → 0.5.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 +7 -1
- package/dist/Clock.svelte +26 -27
- package/dist/Clock.svelte.d.ts +25 -4
- package/package.json +1 -1
- package/src/Clock.svelte +26 -27
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ An analog clock for your Svelte 5 app. Svelte port of [React-Clock](https://gith
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npm install svelte-analog-clock
|
|
8
|
+
npm install svelte-analog-clock svelte-date-utils
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Requires Svelte 5 or later.
|
|
@@ -15,11 +15,17 @@ Requires Svelte 5 or later.
|
|
|
15
15
|
```svelte
|
|
16
16
|
<script lang="ts">
|
|
17
17
|
import Clock from 'svelte-analog-clock';
|
|
18
|
+
import { AdapterDate } from 'svelte-date-utils';
|
|
19
|
+
import { provideDateAdapter } from 'svelte-date-utils';
|
|
20
|
+
|
|
21
|
+
provideDateAdapter(new AdapterDate());
|
|
18
22
|
</script>
|
|
19
23
|
|
|
20
24
|
<Clock value={new Date()} />
|
|
21
25
|
```
|
|
22
26
|
|
|
27
|
+
Install `svelte-date-utils` alongside the clock. Its adapter is required and comes from Svelte context. Call `provideDateAdapter(adapter)` in this component or an ancestor before rendering `Clock`; without it, the clock throws an error. The adapter determines the date object type accepted by `value`. `AdapterDate` uses native `Date`; date-fns, Luxon and `@internationalized/date` adapters are exported from `svelte-date-utils/date-fns`, `svelte-date-utils/luxon` and `svelte-date-utils/internationalized`.
|
|
28
|
+
|
|
23
29
|
Styles are imported automatically. Elements use BEM class names starting with `svelte-clock`.
|
|
24
30
|
|
|
25
31
|
## Props
|
package/dist/Clock.svelte
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
<script lang="ts">
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
2
|
import './Clock.css';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { getDateAdapter } from 'svelte-date-utils';
|
|
3
5
|
|
|
4
6
|
import type { ClassValue } from 'svelte/elements';
|
|
5
7
|
|
|
6
|
-
type ClockProps = {
|
|
8
|
+
type ClockProps<T> = {
|
|
7
9
|
/**
|
|
8
10
|
* Class name(s) that will be added along with `"svelte-clock"` to the main `<time>` element.
|
|
9
11
|
*/
|
|
@@ -144,7 +146,7 @@
|
|
|
144
146
|
* @example new Date()
|
|
145
147
|
* @example '22:15:00'
|
|
146
148
|
*/
|
|
147
|
-
value?:
|
|
149
|
+
value?: T | string | null;
|
|
148
150
|
};
|
|
149
151
|
|
|
150
152
|
let {
|
|
@@ -172,25 +174,27 @@
|
|
|
172
174
|
size = 150,
|
|
173
175
|
useMillisecondPrecision = false,
|
|
174
176
|
value,
|
|
175
|
-
}: ClockProps = $props();
|
|
177
|
+
}: ClockProps<T> = $props();
|
|
178
|
+
|
|
179
|
+
const adapter = getDateAdapter<T>('Clock');
|
|
176
180
|
|
|
177
181
|
const hourMarks = Array.from({ length: 12 }, (_, index) => index);
|
|
178
182
|
const minuteMarks = Array.from({ length: 60 }, (_, index) => index).filter(
|
|
179
183
|
(index) => index % 5 !== 0,
|
|
180
184
|
);
|
|
181
185
|
|
|
182
|
-
let now = $state(
|
|
186
|
+
let now = $state(untrack(() => adapter.date()));
|
|
183
187
|
|
|
184
188
|
$effect(() => {
|
|
185
189
|
if (value !== undefined) {
|
|
186
190
|
return;
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
now =
|
|
193
|
+
now = adapter.date();
|
|
190
194
|
|
|
191
195
|
if (useMillisecondPrecision) {
|
|
192
196
|
let frame = requestAnimationFrame(function tick() {
|
|
193
|
-
now =
|
|
197
|
+
now = adapter.date();
|
|
194
198
|
frame = requestAnimationFrame(tick);
|
|
195
199
|
});
|
|
196
200
|
|
|
@@ -198,33 +202,28 @@
|
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
const interval = setInterval(() => {
|
|
201
|
-
now =
|
|
205
|
+
now = adapter.date();
|
|
202
206
|
}, 1000);
|
|
203
207
|
|
|
204
208
|
return () => clearInterval(interval);
|
|
205
209
|
});
|
|
206
210
|
|
|
207
|
-
function parseTime(input:
|
|
208
|
-
if (input
|
|
209
|
-
return Number.isNaN(input.getTime()) ? null : input;
|
|
210
|
-
}
|
|
211
|
-
|
|
211
|
+
function parseTime(input: T | string): T | null {
|
|
212
|
+
if (typeof input !== 'string') return adapter.isValid(input) ? input : null;
|
|
212
213
|
// Time-only strings, e.g. "22:15" or "22:15:30"
|
|
213
214
|
const match = /^(\d{1,2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?$/.exec(input);
|
|
214
215
|
|
|
215
216
|
if (match) {
|
|
216
|
-
|
|
217
|
-
date.setHours(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
Number((match[4] ?? '0').padEnd(3, '0').slice(0, 3)),
|
|
222
|
-
);
|
|
217
|
+
let date = adapter.date();
|
|
218
|
+
date = adapter.setHours(date, Number(match[1]));
|
|
219
|
+
date = adapter.setMinutes(date, Number(match[2]));
|
|
220
|
+
date = adapter.setSeconds(date, Number(match[3] ?? 0));
|
|
221
|
+
date = adapter.setMilliseconds(date, Number((match[4] ?? '0').padEnd(3, '0').slice(0, 3)));
|
|
223
222
|
return date;
|
|
224
223
|
}
|
|
225
224
|
|
|
226
|
-
const date =
|
|
227
|
-
return
|
|
225
|
+
const date = adapter.date(input);
|
|
226
|
+
return adapter.isValid(date) ? date : null;
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
const date = $derived(value === undefined ? now : value === null ? null : parseTime(value));
|
|
@@ -234,10 +233,10 @@
|
|
|
234
233
|
return null;
|
|
235
234
|
}
|
|
236
235
|
|
|
237
|
-
const hours =
|
|
238
|
-
const minutes =
|
|
239
|
-
const seconds =
|
|
240
|
-
const milliseconds = useMillisecondPrecision ?
|
|
236
|
+
const hours = adapter.getHours(date) % 12;
|
|
237
|
+
const minutes = adapter.getMinutes(date);
|
|
238
|
+
const seconds = adapter.getSeconds(date);
|
|
239
|
+
const milliseconds = useMillisecondPrecision ? adapter.getMilliseconds(date) : 0;
|
|
241
240
|
|
|
242
241
|
return {
|
|
243
242
|
hour: hours * 30 + minutes * 0.5 + seconds / 120,
|
|
@@ -246,7 +245,7 @@
|
|
|
246
245
|
};
|
|
247
246
|
});
|
|
248
247
|
|
|
249
|
-
const datetime = $derived(date ? date.toISOString() : undefined);
|
|
248
|
+
const datetime = $derived(date ? adapter.toJsDate(date).toISOString() : undefined);
|
|
250
249
|
</script>
|
|
251
250
|
|
|
252
251
|
{#snippet hand(
|
package/dist/Clock.svelte.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import './Clock.css';
|
|
2
2
|
import type { ClassValue } from 'svelte/elements';
|
|
3
|
-
type ClockProps = {
|
|
3
|
+
type ClockProps<T> = {
|
|
4
4
|
/**
|
|
5
5
|
* Class name(s) that will be added along with `"svelte-clock"` to the main `<time>` element.
|
|
6
6
|
*/
|
|
@@ -141,8 +141,29 @@ type ClockProps = {
|
|
|
141
141
|
* @example new Date()
|
|
142
142
|
* @example '22:15:00'
|
|
143
143
|
*/
|
|
144
|
-
value?:
|
|
144
|
+
value?: T | string | null;
|
|
145
145
|
};
|
|
146
|
-
declare
|
|
147
|
-
|
|
146
|
+
declare function $$render<T>(): {
|
|
147
|
+
props: ClockProps<T>;
|
|
148
|
+
exports: {};
|
|
149
|
+
bindings: "";
|
|
150
|
+
slots: {};
|
|
151
|
+
events: {};
|
|
152
|
+
};
|
|
153
|
+
declare class __sveltets_Render<T> {
|
|
154
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
155
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
156
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
157
|
+
bindings(): "";
|
|
158
|
+
exports(): {};
|
|
159
|
+
}
|
|
160
|
+
interface $$IsomorphicComponent {
|
|
161
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
162
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
163
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
164
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
165
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
166
|
+
}
|
|
167
|
+
declare const Clock: $$IsomorphicComponent;
|
|
168
|
+
type Clock<T> = InstanceType<typeof Clock<T>>;
|
|
148
169
|
export default Clock;
|
package/package.json
CHANGED
package/src/Clock.svelte
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
<script lang="ts">
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
2
|
import './Clock.css';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { getDateAdapter } from 'svelte-date-utils';
|
|
3
5
|
|
|
4
6
|
import type { ClassValue } from 'svelte/elements';
|
|
5
7
|
|
|
6
|
-
type ClockProps = {
|
|
8
|
+
type ClockProps<T> = {
|
|
7
9
|
/**
|
|
8
10
|
* Class name(s) that will be added along with `"svelte-clock"` to the main `<time>` element.
|
|
9
11
|
*/
|
|
@@ -144,7 +146,7 @@
|
|
|
144
146
|
* @example new Date()
|
|
145
147
|
* @example '22:15:00'
|
|
146
148
|
*/
|
|
147
|
-
value?:
|
|
149
|
+
value?: T | string | null;
|
|
148
150
|
};
|
|
149
151
|
|
|
150
152
|
let {
|
|
@@ -172,25 +174,27 @@
|
|
|
172
174
|
size = 150,
|
|
173
175
|
useMillisecondPrecision = false,
|
|
174
176
|
value,
|
|
175
|
-
}: ClockProps = $props();
|
|
177
|
+
}: ClockProps<T> = $props();
|
|
178
|
+
|
|
179
|
+
const adapter = getDateAdapter<T>('Clock');
|
|
176
180
|
|
|
177
181
|
const hourMarks = Array.from({ length: 12 }, (_, index) => index);
|
|
178
182
|
const minuteMarks = Array.from({ length: 60 }, (_, index) => index).filter(
|
|
179
183
|
(index) => index % 5 !== 0,
|
|
180
184
|
);
|
|
181
185
|
|
|
182
|
-
let now = $state(
|
|
186
|
+
let now = $state(untrack(() => adapter.date()));
|
|
183
187
|
|
|
184
188
|
$effect(() => {
|
|
185
189
|
if (value !== undefined) {
|
|
186
190
|
return;
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
now =
|
|
193
|
+
now = adapter.date();
|
|
190
194
|
|
|
191
195
|
if (useMillisecondPrecision) {
|
|
192
196
|
let frame = requestAnimationFrame(function tick() {
|
|
193
|
-
now =
|
|
197
|
+
now = adapter.date();
|
|
194
198
|
frame = requestAnimationFrame(tick);
|
|
195
199
|
});
|
|
196
200
|
|
|
@@ -198,33 +202,28 @@
|
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
const interval = setInterval(() => {
|
|
201
|
-
now =
|
|
205
|
+
now = adapter.date();
|
|
202
206
|
}, 1000);
|
|
203
207
|
|
|
204
208
|
return () => clearInterval(interval);
|
|
205
209
|
});
|
|
206
210
|
|
|
207
|
-
function parseTime(input:
|
|
208
|
-
if (input
|
|
209
|
-
return Number.isNaN(input.getTime()) ? null : input;
|
|
210
|
-
}
|
|
211
|
-
|
|
211
|
+
function parseTime(input: T | string): T | null {
|
|
212
|
+
if (typeof input !== 'string') return adapter.isValid(input) ? input : null;
|
|
212
213
|
// Time-only strings, e.g. "22:15" or "22:15:30"
|
|
213
214
|
const match = /^(\d{1,2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?$/.exec(input);
|
|
214
215
|
|
|
215
216
|
if (match) {
|
|
216
|
-
|
|
217
|
-
date.setHours(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
Number((match[4] ?? '0').padEnd(3, '0').slice(0, 3)),
|
|
222
|
-
);
|
|
217
|
+
let date = adapter.date();
|
|
218
|
+
date = adapter.setHours(date, Number(match[1]));
|
|
219
|
+
date = adapter.setMinutes(date, Number(match[2]));
|
|
220
|
+
date = adapter.setSeconds(date, Number(match[3] ?? 0));
|
|
221
|
+
date = adapter.setMilliseconds(date, Number((match[4] ?? '0').padEnd(3, '0').slice(0, 3)));
|
|
223
222
|
return date;
|
|
224
223
|
}
|
|
225
224
|
|
|
226
|
-
const date =
|
|
227
|
-
return
|
|
225
|
+
const date = adapter.date(input);
|
|
226
|
+
return adapter.isValid(date) ? date : null;
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
const date = $derived(value === undefined ? now : value === null ? null : parseTime(value));
|
|
@@ -234,10 +233,10 @@
|
|
|
234
233
|
return null;
|
|
235
234
|
}
|
|
236
235
|
|
|
237
|
-
const hours =
|
|
238
|
-
const minutes =
|
|
239
|
-
const seconds =
|
|
240
|
-
const milliseconds = useMillisecondPrecision ?
|
|
236
|
+
const hours = adapter.getHours(date) % 12;
|
|
237
|
+
const minutes = adapter.getMinutes(date);
|
|
238
|
+
const seconds = adapter.getSeconds(date);
|
|
239
|
+
const milliseconds = useMillisecondPrecision ? adapter.getMilliseconds(date) : 0;
|
|
241
240
|
|
|
242
241
|
return {
|
|
243
242
|
hour: hours * 30 + minutes * 0.5 + seconds / 120,
|
|
@@ -246,7 +245,7 @@
|
|
|
246
245
|
};
|
|
247
246
|
});
|
|
248
247
|
|
|
249
|
-
const datetime = $derived(date ? date.toISOString() : undefined);
|
|
248
|
+
const datetime = $derived(date ? adapter.toJsDate(date).toISOString() : undefined);
|
|
250
249
|
</script>
|
|
251
250
|
|
|
252
251
|
{#snippet hand(
|