-
-
Notifications
You must be signed in to change notification settings - Fork 127
Expand file tree
/
Copy pathindex.ts
More file actions
73 lines (63 loc) · 1.91 KB
/
Copy pathindex.ts
File metadata and controls
73 lines (63 loc) · 1.91 KB
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
65
66
67
68
69
70
71
72
73
import { ReadonlySignal, Signal } from "@preact/signals-core";
import { useSignal } from "@preact/signals";
import { Fragment, createElement, JSX } from "preact";
import { useMemo } from "preact/hooks";
type Falsy = false | 0 | 0n | "" | null | undefined;
interface ShowProps<T = boolean> {
when: Signal<T> | ReadonlySignal<T>;
fallback?: JSX.Element;
children: JSX.Element | ((value: Exclude<T, Falsy>) => JSX.Element);
}
export function Show<T = boolean>(props: ShowProps<T>): JSX.Element | null {
const value = props.when.value;
if (!value) return props.fallback || null;
return typeof props.children === "function"
? props.children(value)
: props.children;
}
interface ForProps<T> {
each:
| Signal<Array<T>>
| ReadonlySignal<Array<T>>
| (() => Signal<Array<T>> | ReadonlySignal<Array<T>>);
fallback?: JSX.Element;
children: (value: T, index: number) => JSX.Element;
}
export function For<T>(props: ForProps<T>): JSX.Element | null {
const cache = useMemo(() => new Map(), []);
let list = (
(typeof props.each === "function" ? props.each() : props.each) as Signal<
Array<T>
>
).value;
if (!list.length) return props.fallback || null;
const items = list.map((value, key) => {
if (!cache.has(value)) {
cache.set(value, props.children(value, key));
}
return cache.get(value);
});
return createElement(Fragment, null, items);
}
export function useLiveSignal<T>(
value: Signal<T> | ReadonlySignal<T>
): Signal<Signal<T> | ReadonlySignal<T>> {
const s = useSignal(value);
if (s.peek() !== value) s.value = value;
return s;
}
export function useSignalRef<T>(value: T): Signal<T> & { current: T } {
const ref = useSignal(value) as Signal<T> & { current: T };
if (!("current" in ref))
Object.defineProperty(ref, "current", refSignalProto);
return ref;
}
const refSignalProto = {
configurable: true,
get(this: Signal) {
return this.value;
},
set(this: Signal, v: any) {
this.value = v;
},
};