1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 |
x4
x4
x4
x4
x4
x4
x17
x4
x4
x250
x942
x314
x750
x4
x4
x69
x69
x74
x74
x74
x74
x129
x69
x72
x72
x72
x286
x69
x77
x77
x77
x4
x4
x250
x251
x251
x251
x251
x251
x250
x483
x483
x262
x268
x2144
x268
x262
x250
x4
x4 |
|
import { type Cache, type Directive, Phase } from "@mizu/internal/engine"
export type * from "@mizu/internal/engine"
export const _refresh: Directive<{
Cache: WeakMap<HTMLElement | Comment, { id: number; interval: number }>
}> = {
name: "*refresh",
phase: Phase.POSTPROCESSING,
init(this: typeof _refresh, renderer) {
renderer.cache<Cache<typeof this>>(this.name, new WeakMap())
},
setup(this: typeof _refresh, _, __, { state }) {
if (!("$refresh" in state)) {
Object.assign(state, { $refresh: false })
}
return { state }
},
async execute(this: typeof _refresh, renderer, element, { attributes: [attribute], cache, ...options }) {
const value = await renderer.evaluate(element, attribute.value, options) as string
if (value === null) {
clearTimeout(cache.get(element)?.id)
cache.delete(element)
return
}
const interval = Number.parseInt(`${1000 * Number(value)}`)
if ((Number.isNaN(interval)) || (interval <= 0)) {
renderer.warn(`[${this.name}] expects a finite positive number but got ${value}, ignoring`, element)
return
}
const cached = cache.get(element) ?? cache.set(element, { interval, id: NaN }).get(element)!
if (((cached.interval !== interval) && (!Number.isNaN(cached.id))) || (options.state[renderer.internal("refreshing")])) {
clearTimeout(cached.id)
cached.id = NaN
}
},
cleanup(this: typeof _refresh, renderer, element, { cache, ...options }) {
if ((renderer.isComment(element)) && (cache.has(renderer.cache("*").get(element)!))) {
element = renderer.cache("*").get(element)!
clearTimeout(cache.get(element)?.id)
cache.delete(element)
return
}
if (!Number.isNaN(cache.get(element)?.id)) {
return
}
cache.get(element)!.id = setTimeout(() => {
if (element.isConnected) {
renderer.render(element as HTMLElement, { ...options, state: { ...options.state, $refresh: true, [renderer.internal("refreshing")]: true } })
}
}, cache.get(element)!.interval)
},
}
export default _refresh
|