kiru 0.54.3 → 1.0.1
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/dist/{appContext.d.ts → appHandle.d.ts} +4 -4
- package/dist/appHandle.d.ts.map +1 -0
- package/dist/{appContext.js → appHandle.js} +12 -9
- package/dist/appHandle.js.map +1 -0
- package/dist/components/derive.d.ts +10 -8
- package/dist/components/derive.d.ts.map +1 -1
- package/dist/components/derive.js +50 -47
- package/dist/components/derive.js.map +1 -1
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +0 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/lazy.d.ts.map +1 -1
- package/dist/components/lazy.js +5 -4
- package/dist/components/lazy.js.map +1 -1
- package/dist/components/portal.d.ts.map +1 -1
- package/dist/components/portal.js +2 -3
- package/dist/components/portal.js.map +1 -1
- package/dist/components/transition.d.ts +3 -2
- package/dist/components/transition.d.ts.map +1 -1
- package/dist/components/transition.js +29 -26
- package/dist/components/transition.js.map +1 -1
- package/dist/constants.d.ts +1 -5
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -5
- package/dist/constants.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +25 -19
- package/dist/context.js.map +1 -1
- package/dist/devtools.d.ts +7 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +15 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +25 -58
- package/dist/dom.js.map +1 -1
- package/dist/globalContext.d.ts +15 -16
- package/dist/globalContext.d.ts.map +1 -1
- package/dist/globalContext.js +36 -46
- package/dist/globalContext.js.map +1 -1
- package/dist/globals.d.ts +1 -4
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +1 -4
- package/dist/globals.js.map +1 -1
- package/dist/headlessRender.d.ts +6 -0
- package/dist/headlessRender.d.ts.map +1 -0
- package/dist/{recursiveRender.js → headlessRender.js} +17 -16
- package/dist/headlessRender.js.map +1 -0
- package/dist/hmr.d.ts +5 -7
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +27 -32
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/index.d.ts +3 -14
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -14
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/onBeforeMount.d.ts +9 -0
- package/dist/hooks/onBeforeMount.d.ts.map +1 -0
- package/dist/hooks/onBeforeMount.js +12 -0
- package/dist/hooks/onBeforeMount.js.map +1 -0
- package/dist/hooks/onCleanup.d.ts +8 -0
- package/dist/hooks/onCleanup.d.ts.map +1 -0
- package/dist/hooks/onCleanup.js +15 -0
- package/dist/hooks/onCleanup.js.map +1 -0
- package/dist/hooks/onMount.d.ts +9 -0
- package/dist/hooks/onMount.d.ts.map +1 -0
- package/dist/hooks/onMount.js +12 -0
- package/dist/hooks/onMount.js.map +1 -0
- package/dist/hooks/utils.d.ts +2 -62
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +22 -144
- package/dist/hooks/utils.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/profiling.d.ts +15 -14
- package/dist/profiling.d.ts.map +1 -1
- package/dist/profiling.js +9 -4
- package/dist/profiling.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +12 -25
- package/dist/reconciler.js.map +1 -1
- package/dist/ref.d.ts +4 -0
- package/dist/ref.d.ts.map +1 -0
- package/dist/ref.js +4 -0
- package/dist/ref.js.map +1 -0
- package/dist/renderToString.js +1 -1
- package/dist/renderToString.js.map +1 -1
- package/dist/router/context.d.ts.map +1 -1
- package/dist/router/context.js +1 -2
- package/dist/router/context.js.map +1 -1
- package/dist/router/fileRouter.d.ts +1 -1
- package/dist/router/fileRouter.d.ts.map +1 -1
- package/dist/router/fileRouter.js +17 -11
- package/dist/router/fileRouter.js.map +1 -1
- package/dist/router/fileRouterController.d.ts.map +1 -1
- package/dist/router/fileRouterController.js +68 -55
- package/dist/router/fileRouterController.js.map +1 -1
- package/dist/router/link.d.ts.map +1 -1
- package/dist/router/link.js +19 -23
- package/dist/router/link.js.map +1 -1
- package/dist/router/server/index.d.ts.map +1 -1
- package/dist/router/server/index.js +14 -11
- package/dist/router/server/index.js.map +1 -1
- package/dist/router/types.d.ts +11 -6
- package/dist/router/types.d.ts.map +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +65 -52
- package/dist/scheduler.js.map +1 -1
- package/dist/signals/base.d.ts +0 -1
- package/dist/signals/base.d.ts.map +1 -1
- package/dist/signals/base.js +13 -36
- package/dist/signals/base.js.map +1 -1
- package/dist/signals/computed.d.ts +0 -2
- package/dist/signals/computed.d.ts.map +1 -1
- package/dist/signals/computed.js +1 -40
- package/dist/signals/computed.js.map +1 -1
- package/dist/signals/effect.d.ts +15 -14
- package/dist/signals/effect.d.ts.map +1 -1
- package/dist/signals/effect.js +65 -37
- package/dist/signals/effect.js.map +1 -1
- package/dist/signals/globals.d.ts +0 -5
- package/dist/signals/globals.d.ts.map +1 -1
- package/dist/signals/globals.js +0 -6
- package/dist/signals/globals.js.map +1 -1
- package/dist/signals/index.d.ts +4 -4
- package/dist/signals/index.d.ts.map +1 -1
- package/dist/signals/index.js +4 -4
- package/dist/signals/index.js.map +1 -1
- package/dist/signals/{for.d.ts → jsx.d.ts} +8 -1
- package/dist/signals/jsx.d.ts.map +1 -0
- package/dist/signals/{for.js → jsx.js} +4 -1
- package/dist/signals/jsx.js.map +1 -0
- package/dist/signals/tracking.d.ts +23 -0
- package/dist/signals/tracking.d.ts.map +1 -0
- package/dist/signals/tracking.js +51 -0
- package/dist/signals/tracking.js.map +1 -0
- package/dist/signals/types.d.ts +1 -1
- package/dist/signals/types.d.ts.map +1 -1
- package/dist/signals/utils.d.ts +2 -1
- package/dist/signals/utils.d.ts.map +1 -1
- package/dist/signals/utils.js +9 -2
- package/dist/signals/utils.js.map +1 -1
- package/dist/ssr/client.d.ts +3 -3
- package/dist/ssr/client.d.ts.map +1 -1
- package/dist/ssr/client.js.map +1 -1
- package/dist/ssr/server.js +1 -1
- package/dist/ssr/server.js.map +1 -1
- package/dist/statefulPromise.d.ts +22 -0
- package/dist/statefulPromise.d.ts.map +1 -0
- package/dist/statefulPromise.js +94 -0
- package/dist/statefulPromise.js.map +1 -0
- package/dist/types.d.ts +36 -50
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +4 -7
- package/dist/types.dom.d.ts.map +1 -1
- package/dist/types.utils.d.ts +3 -4
- package/dist/types.utils.d.ts.map +1 -1
- package/dist/utils/vdom.d.ts +8 -6
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +32 -9
- package/dist/utils/vdom.js.map +1 -1
- package/dist/viewTransitions.d.ts +7 -0
- package/dist/viewTransitions.d.ts.map +1 -0
- package/dist/viewTransitions.js +71 -0
- package/dist/viewTransitions.js.map +1 -0
- package/package.json +1 -1
- package/src/{appContext.ts → appHandle.ts} +21 -16
- package/src/components/derive.ts +74 -69
- package/src/components/index.ts +0 -1
- package/src/components/lazy.ts +5 -4
- package/src/components/portal.ts +2 -3
- package/src/components/transition.ts +33 -35
- package/src/constants.ts +0 -8
- package/src/context.ts +30 -23
- package/src/devtools.ts +16 -0
- package/src/dom.ts +29 -63
- package/src/globalContext.ts +57 -74
- package/src/globals.ts +1 -5
- package/src/{recursiveRender.ts → headlessRender.ts} +18 -18
- package/src/hmr.ts +29 -38
- package/src/hooks/index.ts +3 -14
- package/src/hooks/onBeforeMount.ts +12 -0
- package/src/hooks/onCleanup.ts +15 -0
- package/src/hooks/onMount.ts +12 -0
- package/src/hooks/utils.ts +28 -238
- package/src/index.ts +14 -6
- package/src/profiling.ts +22 -20
- package/src/reconciler.ts +18 -30
- package/src/ref.ts +6 -0
- package/src/renderToString.ts +1 -1
- package/src/router/context.ts +1 -2
- package/src/router/fileRouter.ts +23 -13
- package/src/router/fileRouterController.ts +72 -64
- package/src/router/link.ts +11 -25
- package/src/router/server/index.ts +24 -13
- package/src/router/types.ts +15 -8
- package/src/scheduler.ts +74 -71
- package/src/signals/base.ts +12 -41
- package/src/signals/computed.ts +1 -62
- package/src/signals/effect.ts +95 -48
- package/src/signals/globals.ts +0 -7
- package/src/signals/index.ts +4 -4
- package/src/signals/{for.ts → jsx.ts} +10 -0
- package/src/signals/tracking.ts +69 -0
- package/src/signals/types.ts +1 -1
- package/src/signals/utils.ts +9 -1
- package/src/ssr/client.ts +4 -4
- package/src/ssr/server.ts +2 -2
- package/src/statefulPromise.ts +136 -0
- package/src/types.dom.ts +4 -8
- package/src/types.ts +45 -58
- package/src/types.utils.ts +3 -4
- package/src/utils/vdom.ts +44 -15
- package/src/viewTransitions.ts +88 -0
- package/dist/appContext.d.ts.map +0 -1
- package/dist/appContext.js.map +0 -1
- package/dist/components/memo.d.ts +0 -10
- package/dist/components/memo.d.ts.map +0 -1
- package/dist/components/memo.js +0 -23
- package/dist/components/memo.js.map +0 -1
- package/dist/form/index.d.ts +0 -4
- package/dist/form/index.d.ts.map +0 -1
- package/dist/form/index.js +0 -518
- package/dist/form/index.js.map +0 -1
- package/dist/form/types.d.ts +0 -122
- package/dist/form/types.d.ts.map +0 -1
- package/dist/form/types.js +0 -2
- package/dist/form/types.js.map +0 -1
- package/dist/form/utils.d.ts +0 -3
- package/dist/form/utils.d.ts.map +0 -1
- package/dist/form/utils.js +0 -16
- package/dist/form/utils.js.map +0 -1
- package/dist/hooks/useAsync.d.ts +0 -18
- package/dist/hooks/useAsync.d.ts.map +0 -1
- package/dist/hooks/useAsync.js +0 -96
- package/dist/hooks/useAsync.js.map +0 -1
- package/dist/hooks/useCallback.d.ts +0 -7
- package/dist/hooks/useCallback.d.ts.map +0 -1
- package/dist/hooks/useCallback.js +0 -30
- package/dist/hooks/useCallback.js.map +0 -1
- package/dist/hooks/useContext.d.ts +0 -7
- package/dist/hooks/useContext.d.ts.map +0 -1
- package/dist/hooks/useContext.js +0 -59
- package/dist/hooks/useContext.js.map +0 -1
- package/dist/hooks/useEffect.d.ts +0 -8
- package/dist/hooks/useEffect.d.ts.map +0 -1
- package/dist/hooks/useEffect.js +0 -34
- package/dist/hooks/useEffect.js.map +0 -1
- package/dist/hooks/useEffectEvent.d.ts +0 -8
- package/dist/hooks/useEffectEvent.d.ts.map +0 -1
- package/dist/hooks/useEffectEvent.js +0 -23
- package/dist/hooks/useEffectEvent.js.map +0 -1
- package/dist/hooks/useId.d.ts +0 -8
- package/dist/hooks/useId.d.ts.map +0 -1
- package/dist/hooks/useId.js +0 -35
- package/dist/hooks/useId.js.map +0 -1
- package/dist/hooks/useLayoutEffect.d.ts +0 -8
- package/dist/hooks/useLayoutEffect.d.ts.map +0 -1
- package/dist/hooks/useLayoutEffect.js +0 -34
- package/dist/hooks/useLayoutEffect.js.map +0 -1
- package/dist/hooks/useMemo.d.ts +0 -8
- package/dist/hooks/useMemo.d.ts.map +0 -1
- package/dist/hooks/useMemo.js +0 -31
- package/dist/hooks/useMemo.js.map +0 -1
- package/dist/hooks/usePromise.d.ts +0 -8
- package/dist/hooks/usePromise.d.ts.map +0 -1
- package/dist/hooks/usePromise.js +0 -90
- package/dist/hooks/usePromise.js.map +0 -1
- package/dist/hooks/useReducer.d.ts +0 -7
- package/dist/hooks/useReducer.d.ts.map +0 -1
- package/dist/hooks/useReducer.js +0 -44
- package/dist/hooks/useReducer.js.map +0 -1
- package/dist/hooks/useRef.d.ts +0 -10
- package/dist/hooks/useRef.d.ts.map +0 -1
- package/dist/hooks/useRef.js +0 -29
- package/dist/hooks/useRef.js.map +0 -1
- package/dist/hooks/useState.d.ts +0 -7
- package/dist/hooks/useState.d.ts.map +0 -1
- package/dist/hooks/useState.js +0 -54
- package/dist/hooks/useState.js.map +0 -1
- package/dist/hooks/useSyncExternalStore.d.ts +0 -8
- package/dist/hooks/useSyncExternalStore.d.ts.map +0 -1
- package/dist/hooks/useSyncExternalStore.js +0 -50
- package/dist/hooks/useSyncExternalStore.js.map +0 -1
- package/dist/hooks/useViewTransition.d.ts +0 -10
- package/dist/hooks/useViewTransition.d.ts.map +0 -1
- package/dist/hooks/useViewTransition.js +0 -27
- package/dist/hooks/useViewTransition.js.map +0 -1
- package/dist/recursiveRender.d.ts +0 -7
- package/dist/recursiveRender.d.ts.map +0 -1
- package/dist/recursiveRender.js.map +0 -1
- package/dist/signals/for.d.ts.map +0 -1
- package/dist/signals/for.js.map +0 -1
- package/dist/signals/watch.d.ts +0 -21
- package/dist/signals/watch.d.ts.map +0 -1
- package/dist/signals/watch.js +0 -86
- package/dist/signals/watch.js.map +0 -1
- package/dist/store.d.ts +0 -28
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -166
- package/dist/store.js.map +0 -1
- package/dist/swr.d.ts +0 -63
- package/dist/swr.d.ts.map +0 -1
- package/dist/swr.js +0 -236
- package/dist/swr.js.map +0 -1
- package/dist/utils/promise.d.ts +0 -16
- package/dist/utils/promise.d.ts.map +0 -1
- package/dist/utils/promise.js +0 -14
- package/dist/utils/promise.js.map +0 -1
- package/src/components/memo.ts +0 -39
- package/src/form/index.ts +0 -676
- package/src/form/types.ts +0 -262
- package/src/form/utils.ts +0 -19
- package/src/hooks/useAsync.ts +0 -121
- package/src/hooks/useCallback.ts +0 -32
- package/src/hooks/useContext.ts +0 -79
- package/src/hooks/useEffect.ts +0 -40
- package/src/hooks/useEffectEvent.ts +0 -24
- package/src/hooks/useId.ts +0 -42
- package/src/hooks/useLayoutEffect.ts +0 -43
- package/src/hooks/useMemo.ts +0 -34
- package/src/hooks/usePromise.ts +0 -126
- package/src/hooks/useReducer.ts +0 -50
- package/src/hooks/useRef.ts +0 -41
- package/src/hooks/useState.ts +0 -62
- package/src/hooks/useSyncExternalStore.ts +0 -59
- package/src/hooks/useViewTransition.ts +0 -25
- package/src/signals/watch.ts +0 -139
- package/src/store.ts +0 -245
- package/src/swr.ts +0 -351
- package/src/utils/promise.ts +0 -26
package/src/scheduler.ts
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ContextProviderNode,
|
|
3
|
-
DomVNode,
|
|
4
|
-
ErrorBoundaryNode,
|
|
5
|
-
FunctionVNode,
|
|
6
|
-
} from "./types.utils"
|
|
1
|
+
import type { DomVNode, ErrorBoundaryNode, FunctionVNode } from "./types.utils"
|
|
7
2
|
import {
|
|
8
|
-
$CONTEXT_PROVIDER,
|
|
9
3
|
$ERROR_BOUNDARY,
|
|
10
|
-
$MEMO,
|
|
11
4
|
CONSECUTIVE_DIRTY_LIMIT,
|
|
12
5
|
FLAG_DELETION,
|
|
13
6
|
FLAG_DIRTY,
|
|
14
|
-
FLAG_MEMO,
|
|
15
|
-
FLAG_NOOP,
|
|
16
7
|
} from "./constants.js"
|
|
17
8
|
import {
|
|
18
9
|
commitDeletion,
|
|
@@ -24,7 +15,7 @@ import {
|
|
|
24
15
|
} from "./dom.js"
|
|
25
16
|
import { __DEV__ } from "./env.js"
|
|
26
17
|
import { KiruError } from "./error.js"
|
|
27
|
-
import {
|
|
18
|
+
import { node, renderMode } from "./globals.js"
|
|
28
19
|
import { hydrationStack } from "./hydration.js"
|
|
29
20
|
import { reconcileChildren } from "./reconciler.js"
|
|
30
21
|
import {
|
|
@@ -32,17 +23,17 @@ import {
|
|
|
32
23
|
latest,
|
|
33
24
|
traverseApply,
|
|
34
25
|
isExoticType,
|
|
35
|
-
|
|
26
|
+
getVNodeApp,
|
|
36
27
|
findParentErrorBoundary,
|
|
37
28
|
call,
|
|
29
|
+
propsChanged,
|
|
38
30
|
} from "./utils/index.js"
|
|
39
|
-
import type {
|
|
40
|
-
import type { MemoFn } from "./components/memo"
|
|
31
|
+
import type { AppHandle } from "./appHandle"
|
|
41
32
|
import { isHmrUpdate } from "./hmr.js"
|
|
42
33
|
|
|
43
34
|
type VNode = Kiru.VNode
|
|
44
35
|
|
|
45
|
-
let
|
|
36
|
+
let app: AppHandle | null
|
|
46
37
|
let treesInProgress: VNode[] = []
|
|
47
38
|
let isRunningOrQueued = false
|
|
48
39
|
let nextIdleEffects: (() => void)[] = []
|
|
@@ -51,8 +42,8 @@ let isImmediateEffectsMode = false
|
|
|
51
42
|
let immediateEffectDirtiedRender = false
|
|
52
43
|
let isRenderDirtied = false
|
|
53
44
|
let consecutiveDirtyCount = 0
|
|
54
|
-
let preEffects:
|
|
55
|
-
let postEffects:
|
|
45
|
+
let preEffects: Kiru.LifecycleHookCallback[] = []
|
|
46
|
+
let postEffects: Kiru.LifecycleHookCallback[] = []
|
|
56
47
|
let animationFrameHandle = -1
|
|
57
48
|
|
|
58
49
|
/**
|
|
@@ -94,6 +85,14 @@ export function requestUpdate(vNode: VNode): void {
|
|
|
94
85
|
queueUpdate(vNode)
|
|
95
86
|
}
|
|
96
87
|
|
|
88
|
+
export function useRequestUpdate(): () => void {
|
|
89
|
+
const n = node.current
|
|
90
|
+
if (!n) {
|
|
91
|
+
throw new Error("useRequestUpdate must be called inside a Kiru component")
|
|
92
|
+
}
|
|
93
|
+
return () => requestUpdate(n)
|
|
94
|
+
}
|
|
95
|
+
|
|
97
96
|
function queueBeginWork(): void {
|
|
98
97
|
if (isRunningOrQueued) return
|
|
99
98
|
isRunningOrQueued = true
|
|
@@ -116,7 +115,7 @@ function queueUpdate(vNode: VNode): void {
|
|
|
116
115
|
// If this node is currently being rendered, just mark it dirty
|
|
117
116
|
if (node.current === vNode) {
|
|
118
117
|
if (__DEV__) {
|
|
119
|
-
window.__kiru.profilingContext?.emit("updateDirtied",
|
|
118
|
+
window.__kiru.profilingContext?.emit("updateDirtied", app!)
|
|
120
119
|
}
|
|
121
120
|
isRenderDirtied = true
|
|
122
121
|
return
|
|
@@ -146,10 +145,10 @@ function doWork(): void {
|
|
|
146
145
|
if (__DEV__) {
|
|
147
146
|
const n = deletions[0] ?? treesInProgress[0]
|
|
148
147
|
if (n) {
|
|
149
|
-
|
|
150
|
-
window.__kiru.profilingContext?.beginTick(
|
|
148
|
+
app = getVNodeApp(n)!
|
|
149
|
+
window.__kiru.profilingContext?.beginTick(app)
|
|
151
150
|
} else {
|
|
152
|
-
|
|
151
|
+
app = null
|
|
153
152
|
}
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -190,8 +189,8 @@ function doWork(): void {
|
|
|
190
189
|
immediateEffectDirtiedRender = false
|
|
191
190
|
consecutiveDirtyCount++
|
|
192
191
|
if (__DEV__) {
|
|
193
|
-
window.__kiru.profilingContext?.endTick(
|
|
194
|
-
window.__kiru.profilingContext?.emit("updateDirtied",
|
|
192
|
+
window.__kiru.profilingContext?.endTick(app!)
|
|
193
|
+
window.__kiru.profilingContext?.emit("updateDirtied", app!)
|
|
195
194
|
}
|
|
196
195
|
return flushSync()
|
|
197
196
|
}
|
|
@@ -200,9 +199,9 @@ function doWork(): void {
|
|
|
200
199
|
onWorkFinished()
|
|
201
200
|
queueMicrotask(() => flushEffects(postEffects))
|
|
202
201
|
if (__DEV__) {
|
|
203
|
-
window.__kiru.emit("update",
|
|
204
|
-
window.__kiru.profilingContext?.emit("update",
|
|
205
|
-
window.__kiru.profilingContext?.endTick(
|
|
202
|
+
window.__kiru.emit("update", app!)
|
|
203
|
+
window.__kiru.profilingContext?.emit("update", app!)
|
|
204
|
+
window.__kiru.profilingContext?.endTick(app!)
|
|
206
205
|
}
|
|
207
206
|
}
|
|
208
207
|
|
|
@@ -221,13 +220,12 @@ function performUnitOfWork(vNode: VNode): VNode | null {
|
|
|
221
220
|
let nextNode: VNode | null = vNode
|
|
222
221
|
while (nextNode) {
|
|
223
222
|
// queue effects upon ascent
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
nextNode.effects = undefined
|
|
223
|
+
const { hooks } = nextNode
|
|
224
|
+
if (hooks) {
|
|
225
|
+
preEffects.push(...hooks.pre)
|
|
226
|
+
postEffects.push(...hooks.post)
|
|
227
|
+
hooks.pre.length = 0
|
|
228
|
+
hooks.post.length = 0
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
if (nextNode === currentWorkRoot) return null
|
|
@@ -246,8 +244,13 @@ function performUnitOfWork(vNode: VNode): VNode | null {
|
|
|
246
244
|
|
|
247
245
|
function updateVNode(vNode: VNode): VNode | null {
|
|
248
246
|
const { type, props, prev, flags } = vNode
|
|
247
|
+
|
|
249
248
|
if (__DEV__ && isHmrUpdate()) {
|
|
250
|
-
} else if (
|
|
249
|
+
} else if (
|
|
250
|
+
prev &&
|
|
251
|
+
(flags & FLAG_DIRTY) === 0 &&
|
|
252
|
+
(prev.props === props || !propsChanged(prev.props, props))
|
|
253
|
+
) {
|
|
251
254
|
return null
|
|
252
255
|
}
|
|
253
256
|
try {
|
|
@@ -262,7 +265,7 @@ function updateVNode(vNode: VNode): VNode | null {
|
|
|
262
265
|
if (__DEV__) {
|
|
263
266
|
window.__kiru.emit(
|
|
264
267
|
"error",
|
|
265
|
-
|
|
268
|
+
app!,
|
|
266
269
|
error instanceof Error ? error : new Error(String(error))
|
|
267
270
|
)
|
|
268
271
|
}
|
|
@@ -302,16 +305,7 @@ function updateExoticComponent(vNode: VNode): VNode | null {
|
|
|
302
305
|
const { props, type } = vNode
|
|
303
306
|
let children = props.children
|
|
304
307
|
|
|
305
|
-
if (type === $
|
|
306
|
-
const {
|
|
307
|
-
props: { dependents, value },
|
|
308
|
-
prev,
|
|
309
|
-
} = vNode as ContextProviderNode<unknown>
|
|
310
|
-
|
|
311
|
-
if (dependents.size && prev && prev.props.value !== value) {
|
|
312
|
-
dependents.forEach(queueUpdate)
|
|
313
|
-
}
|
|
314
|
-
} else if (type === $ERROR_BOUNDARY) {
|
|
308
|
+
if (type === $ERROR_BOUNDARY) {
|
|
315
309
|
const n = vNode as ErrorBoundaryNode
|
|
316
310
|
const { error } = n
|
|
317
311
|
if (error) {
|
|
@@ -328,18 +322,8 @@ function updateExoticComponent(vNode: VNode): VNode | null {
|
|
|
328
322
|
}
|
|
329
323
|
|
|
330
324
|
function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
331
|
-
const { type, props, subs
|
|
332
|
-
|
|
333
|
-
if (
|
|
334
|
-
prev &&
|
|
335
|
-
(type as MemoFn)[$MEMO](prev.props, props) &&
|
|
336
|
-
!(__DEV__ && isHmrUpdate())
|
|
337
|
-
) {
|
|
338
|
-
vNode.flags |= FLAG_NOOP
|
|
339
|
-
return null
|
|
340
|
-
}
|
|
341
|
-
vNode.flags &= ~FLAG_NOOP
|
|
342
|
-
}
|
|
325
|
+
const { type, props, subs } = vNode
|
|
326
|
+
|
|
343
327
|
try {
|
|
344
328
|
node.current = vNode
|
|
345
329
|
let newChild
|
|
@@ -347,7 +331,6 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
347
331
|
do {
|
|
348
332
|
vNode.flags &= ~FLAG_DIRTY
|
|
349
333
|
isRenderDirtied = false
|
|
350
|
-
hookIndex.current = 0
|
|
351
334
|
|
|
352
335
|
/**
|
|
353
336
|
* remove previous signal subscriptions (if any) every render.
|
|
@@ -364,18 +347,29 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
364
347
|
}
|
|
365
348
|
|
|
366
349
|
if (__DEV__) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
350
|
+
if (isHmrUpdate()) {
|
|
351
|
+
const { hooks } = vNode
|
|
352
|
+
if (vNode.cleanups) {
|
|
353
|
+
Object.values(vNode.cleanups).forEach(call)
|
|
354
|
+
delete vNode.cleanups
|
|
355
|
+
}
|
|
356
|
+
if (hooks) {
|
|
357
|
+
const { preCleanups, postCleanups } = hooks
|
|
358
|
+
preCleanups.forEach(call)
|
|
359
|
+
postCleanups.forEach(call)
|
|
360
|
+
preCleanups.length = postCleanups.length = 0
|
|
361
|
+
}
|
|
362
|
+
delete vNode.render
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (vNode.render) {
|
|
366
|
+
newChild = vNode.render(props)
|
|
367
|
+
} else {
|
|
368
|
+
newChild = latest(type)(props)
|
|
369
|
+
if (typeof newChild === "function") {
|
|
370
|
+
vNode.subs?.forEach(call)
|
|
371
|
+
vNode.render = newChild as (props: any) => unknown
|
|
372
|
+
newChild = vNode.render(props)
|
|
379
373
|
}
|
|
380
374
|
}
|
|
381
375
|
|
|
@@ -389,7 +383,16 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
389
383
|
}
|
|
390
384
|
continue
|
|
391
385
|
}
|
|
392
|
-
|
|
386
|
+
|
|
387
|
+
if (vNode.render) {
|
|
388
|
+
newChild = vNode.render(props)
|
|
389
|
+
} else {
|
|
390
|
+
newChild = type(props)
|
|
391
|
+
if (typeof newChild === "function") {
|
|
392
|
+
vNode.render = newChild as (props: any) => unknown
|
|
393
|
+
newChild = vNode.render(props)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
393
396
|
} while (isRenderDirtied)
|
|
394
397
|
|
|
395
398
|
return (vNode.child = reconcileChildren(vNode, newChild))
|
package/src/signals/base.ts
CHANGED
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
safeStringify,
|
|
4
4
|
sideEffectsEnabled,
|
|
5
5
|
generateRandomID,
|
|
6
|
+
registerVNodeCleanup,
|
|
6
7
|
} from "../utils/index.js"
|
|
7
8
|
import { $HMR_ACCEPT, $SIGNAL } from "../constants.js"
|
|
8
9
|
import { __DEV__ } from "../env.js"
|
|
9
10
|
import { node } from "../globals.js"
|
|
10
|
-
import { useHook } from "../hooks/utils.js"
|
|
11
11
|
import { requestUpdate } from "../scheduler.js"
|
|
12
|
-
import {
|
|
12
|
+
import { signalSubsMap } from "./globals.js"
|
|
13
|
+
import { tracking } from "./tracking.js"
|
|
13
14
|
import type { SignalSubscriber, ReadonlySignal } from "./types.js"
|
|
14
15
|
import type { HMRAccept } from "../hmr.js"
|
|
15
16
|
|
|
@@ -38,6 +39,7 @@ export class Signal<T> {
|
|
|
38
39
|
return this as Signal<any>
|
|
39
40
|
},
|
|
40
41
|
inject: (prev) => {
|
|
42
|
+
if ("window" in globalThis) window.__kiru.devtools?.untrack(prev)
|
|
41
43
|
signalSubsMap.get(this.$id)?.clear?.()
|
|
42
44
|
signalSubsMap.delete(this.$id)
|
|
43
45
|
this.$id = prev.$id
|
|
@@ -56,6 +58,11 @@ export class Signal<T> {
|
|
|
56
58
|
} else {
|
|
57
59
|
this.$subs = new Set()
|
|
58
60
|
}
|
|
61
|
+
|
|
62
|
+
const n = node.current
|
|
63
|
+
if (n) {
|
|
64
|
+
registerVNodeCleanup(n, this.$id, Signal.dispose.bind(null, this))
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
get value() {
|
|
@@ -175,6 +182,8 @@ export class Signal<T> {
|
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
static entangle<T>(signal: Signal<T>) {
|
|
185
|
+
if (tracking.enabled === false) return
|
|
186
|
+
|
|
178
187
|
const vNode = node.current
|
|
179
188
|
const trackedSignalObservations = tracking.current()
|
|
180
189
|
if (trackedSignalObservations) {
|
|
@@ -192,6 +201,7 @@ export class Signal<T> {
|
|
|
192
201
|
signal.$isDisposed = true
|
|
193
202
|
if (__DEV__) {
|
|
194
203
|
signalSubsMap.delete(signal.$id)
|
|
204
|
+
if ("window" in globalThis) window.__kiru.devtools?.untrack(signal)
|
|
195
205
|
return
|
|
196
206
|
}
|
|
197
207
|
signal.$subs!.clear()
|
|
@@ -201,42 +211,3 @@ export class Signal<T> {
|
|
|
201
211
|
export const signal = <T>(initial: T, displayName?: string) => {
|
|
202
212
|
return new Signal(initial, displayName)
|
|
203
213
|
}
|
|
204
|
-
|
|
205
|
-
export const useSignal = <T>(initial: T, displayName?: string) => {
|
|
206
|
-
return useHook(
|
|
207
|
-
"useSignal",
|
|
208
|
-
{ signal: null! as Signal<T> },
|
|
209
|
-
({ hook, isInit, isHMR }) => {
|
|
210
|
-
if (__DEV__) {
|
|
211
|
-
if (isInit) {
|
|
212
|
-
hook.dev = {
|
|
213
|
-
devtools: {
|
|
214
|
-
get: () => ({
|
|
215
|
-
displayName: hook.signal.displayName,
|
|
216
|
-
value: hook.signal.peek(),
|
|
217
|
-
}),
|
|
218
|
-
set: ({ value }) => {
|
|
219
|
-
hook.signal.value = value
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
initialArgs: [initial, displayName],
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (isHMR) {
|
|
226
|
-
const [v, name] = hook.dev!.initialArgs
|
|
227
|
-
if (v !== initial || name !== displayName) {
|
|
228
|
-
hook.cleanup?.()
|
|
229
|
-
isInit = true
|
|
230
|
-
hook.dev!.initialArgs = [initial, displayName]
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (isInit) {
|
|
236
|
-
hook.cleanup = () => Signal.dispose(hook.signal)
|
|
237
|
-
hook.signal = new Signal(initial, displayName)
|
|
238
|
-
}
|
|
239
|
-
return hook.signal
|
|
240
|
-
}
|
|
241
|
-
)
|
|
242
|
-
}
|
package/src/signals/computed.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { __DEV__ } from "../env.js"
|
|
2
2
|
import { $HMR_ACCEPT } from "../constants.js"
|
|
3
|
-
import { depsRequireChange, useHook } from "../hooks/utils.js"
|
|
4
3
|
import { call, latest } from "../utils/index.js"
|
|
5
4
|
import { effectQueue, signalSubsMap } from "./globals.js"
|
|
6
|
-
import { executeWithTracking } from "./
|
|
5
|
+
import { executeWithTracking } from "./tracking.js"
|
|
7
6
|
import { Signal } from "./base.js"
|
|
8
7
|
import type { HMRAccept } from "../hmr.js"
|
|
9
8
|
|
|
@@ -131,63 +130,3 @@ export function computed<T>(
|
|
|
131
130
|
): ComputedSignal<T> {
|
|
132
131
|
return new ComputedSignal(getter, displayName)
|
|
133
132
|
}
|
|
134
|
-
|
|
135
|
-
export function useComputed<T>(
|
|
136
|
-
getter: (prev?: T) => T,
|
|
137
|
-
displayName?: string
|
|
138
|
-
): ComputedSignal<T>
|
|
139
|
-
|
|
140
|
-
export function useComputed<T>(
|
|
141
|
-
getter: (prev?: T) => T,
|
|
142
|
-
deps?: unknown[],
|
|
143
|
-
displayName?: string
|
|
144
|
-
): ComputedSignal<T>
|
|
145
|
-
|
|
146
|
-
export function useComputed<T>(
|
|
147
|
-
getter: (prev?: T) => T,
|
|
148
|
-
depsOrDisplayName?: string | unknown[],
|
|
149
|
-
displayName?: string
|
|
150
|
-
) {
|
|
151
|
-
return useHook(
|
|
152
|
-
"useComputedSignal",
|
|
153
|
-
{
|
|
154
|
-
signal: null! as ComputedSignal<T>,
|
|
155
|
-
deps: void 0 as unknown[] | undefined,
|
|
156
|
-
},
|
|
157
|
-
({ hook, isInit, isHMR }) => {
|
|
158
|
-
if (__DEV__) {
|
|
159
|
-
hook.dev = {
|
|
160
|
-
devtools: {
|
|
161
|
-
get: () => ({
|
|
162
|
-
displayName: hook.signal.displayName,
|
|
163
|
-
value: hook.signal.peek(),
|
|
164
|
-
}),
|
|
165
|
-
},
|
|
166
|
-
}
|
|
167
|
-
if (isHMR) {
|
|
168
|
-
// useComputed is always considered side-effecty, so we need to re-run
|
|
169
|
-
hook.cleanup?.()
|
|
170
|
-
isInit = true
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (isInit) {
|
|
174
|
-
if (typeof depsOrDisplayName === "string") {
|
|
175
|
-
displayName = depsOrDisplayName
|
|
176
|
-
depsOrDisplayName = void 0
|
|
177
|
-
}
|
|
178
|
-
hook.deps = depsOrDisplayName
|
|
179
|
-
hook.cleanup = () => ComputedSignal.dispose(hook.signal)
|
|
180
|
-
hook.signal = computed(getter, displayName)
|
|
181
|
-
} else if (
|
|
182
|
-
hook.deps &&
|
|
183
|
-
typeof depsOrDisplayName !== "string" &&
|
|
184
|
-
depsRequireChange(hook.deps, depsOrDisplayName)
|
|
185
|
-
) {
|
|
186
|
-
hook.deps = depsOrDisplayName
|
|
187
|
-
ComputedSignal.updateGetter(hook.signal, getter)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return hook.signal
|
|
191
|
-
}
|
|
192
|
-
)
|
|
193
|
-
}
|
package/src/signals/effect.ts
CHANGED
|
@@ -1,61 +1,108 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { __DEV__ } from "../env.js"
|
|
2
|
+
import { effectQueue } from "./globals.js"
|
|
3
|
+
import { executeWithTracking } from "./tracking.js"
|
|
4
|
+
import {
|
|
5
|
+
latest,
|
|
6
|
+
generateRandomID,
|
|
7
|
+
call,
|
|
8
|
+
registerVNodeCleanup,
|
|
9
|
+
} from "../utils/index.js"
|
|
5
10
|
import type { Signal } from "./base.js"
|
|
6
11
|
import type { SignalValues } from "./types.js"
|
|
12
|
+
import { node } from "../globals.js"
|
|
7
13
|
|
|
8
|
-
type
|
|
9
|
-
id: string
|
|
10
|
-
subs: Map<string, Function>
|
|
11
|
-
fn: (...values: SignalValues<Deps>) => T
|
|
12
|
-
deps?: Deps
|
|
13
|
-
onDepChanged: () => void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Executes an effect function with dependency tracking enabled, and manages
|
|
18
|
-
* the effect's subscriptions.
|
|
19
|
-
* @param ctx - The execution context
|
|
20
|
-
* @returns The result of the effect function
|
|
21
|
-
*/
|
|
22
|
-
export function executeWithTracking<T, Deps extends readonly Signal<unknown>[]>(
|
|
23
|
-
ctx: TrackedExecutionContext<T, Deps>
|
|
24
|
-
): T {
|
|
25
|
-
const { id, subs, fn, deps = [], onDepChanged } = ctx
|
|
26
|
-
let observations: Map<string, Signal<unknown>> | undefined
|
|
27
|
-
|
|
28
|
-
effectQueue.delete(id)
|
|
29
|
-
const isServer = !!node.current && !sideEffectsEnabled()
|
|
30
|
-
|
|
31
|
-
if (!isServer) {
|
|
32
|
-
observations = new Map<string, Signal<unknown>>()
|
|
33
|
-
tracking.stack.push(observations)
|
|
34
|
-
}
|
|
14
|
+
type EffectCallbackReturn = (() => void) | void
|
|
35
15
|
|
|
36
|
-
|
|
16
|
+
export class Effect<const Deps extends readonly Signal<unknown>[] = []> {
|
|
17
|
+
protected id: string
|
|
18
|
+
protected callback: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
19
|
+
protected deps?: Deps
|
|
20
|
+
protected unsubs: Map<string, Function>
|
|
21
|
+
protected cleanup: (() => void) | null
|
|
22
|
+
protected isRunning?: boolean
|
|
37
23
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
constructor(
|
|
25
|
+
callback: (...values: SignalValues<Deps>) => EffectCallbackReturn,
|
|
26
|
+
deps?: Deps
|
|
27
|
+
) {
|
|
28
|
+
this.id = generateRandomID()
|
|
29
|
+
this.callback = callback
|
|
30
|
+
this.deps = deps
|
|
31
|
+
this.unsubs = new Map()
|
|
32
|
+
this.isRunning = false
|
|
33
|
+
this.cleanup = null
|
|
34
|
+
if (__DEV__ && "window" in globalThis) {
|
|
35
|
+
window.__kiru.HMRContext!.moduleEffects.push(this)
|
|
36
|
+
}
|
|
37
|
+
const n = node.current
|
|
38
|
+
if (n) {
|
|
39
|
+
registerVNodeCleanup(n, this.id, this.stop.bind(this))
|
|
43
40
|
}
|
|
41
|
+
this.start()
|
|
42
|
+
}
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
effectQueue.set(id, onDepChanged)
|
|
44
|
+
start() {
|
|
45
|
+
if (this.isRunning) {
|
|
46
|
+
return
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
this.isRunning = true
|
|
50
|
+
|
|
51
|
+
// postpone execution during HMR
|
|
52
|
+
if (
|
|
53
|
+
__DEV__ &&
|
|
54
|
+
"window" in globalThis &&
|
|
55
|
+
window.__kiru.HMRContext?.isReplacement()
|
|
56
|
+
) {
|
|
57
|
+
return queueMicrotask(() => {
|
|
58
|
+
if (this.isRunning) {
|
|
59
|
+
Effect.run(this as Effect)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
56
62
|
}
|
|
57
|
-
|
|
63
|
+
Effect.run(this as Effect)
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
stop() {
|
|
67
|
+
effectQueue.delete(this.id)
|
|
68
|
+
this.unsubs.forEach(call)
|
|
69
|
+
this.unsubs.clear()
|
|
70
|
+
this.cleanup?.()
|
|
71
|
+
this.cleanup = null
|
|
72
|
+
this.isRunning = false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private static run(watchEffect: Effect) {
|
|
76
|
+
const effect = latest(watchEffect)
|
|
77
|
+
const { id, callback: getter, unsubs: subs, deps } = effect
|
|
78
|
+
|
|
79
|
+
effect.cleanup =
|
|
80
|
+
executeWithTracking({
|
|
81
|
+
id,
|
|
82
|
+
subs,
|
|
83
|
+
fn: getter,
|
|
84
|
+
deps,
|
|
85
|
+
onDepChanged: () => {
|
|
86
|
+
effect.cleanup?.()
|
|
87
|
+
Effect.run(effect)
|
|
88
|
+
},
|
|
89
|
+
}) ?? null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function effect(callback: () => EffectCallbackReturn): Effect
|
|
94
|
+
export function effect<const Deps extends readonly Signal<unknown>[]>(
|
|
95
|
+
dependencies: Deps,
|
|
96
|
+
callback: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
97
|
+
): Effect<Deps>
|
|
98
|
+
export function effect<const Deps extends readonly Signal<unknown>[]>(
|
|
99
|
+
depsOrGetter: Deps | (() => EffectCallbackReturn),
|
|
100
|
+
callback?: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
101
|
+
): Effect<Deps> | Effect {
|
|
102
|
+
if (typeof depsOrGetter === "function") {
|
|
103
|
+
return new Effect<[]>(depsOrGetter)
|
|
104
|
+
}
|
|
105
|
+
const dependencies = depsOrGetter
|
|
106
|
+
const effectGetter = callback!
|
|
107
|
+
return new Effect(effectGetter, dependencies)
|
|
61
108
|
}
|
package/src/signals/globals.ts
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import type { Signal } from "./base.js"
|
|
2
1
|
import type { SignalSubscriber } from "./types.js"
|
|
3
2
|
|
|
4
|
-
export const tracking = {
|
|
5
|
-
stack: new Array<Map<string, Signal<unknown>>>(),
|
|
6
|
-
current: function (): Map<string, Signal<unknown>> | undefined {
|
|
7
|
-
return this.stack[this.stack.length - 1]
|
|
8
|
-
},
|
|
9
|
-
}
|
|
10
3
|
export const effectQueue = new Map<string, Function>()
|
|
11
4
|
export const signalSubsMap: Map<string, Set<SignalSubscriber<any>>> = new Map()
|
package/src/signals/index.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* 2. global computed will lose its vNode subscription on HMR
|
|
5
5
|
* */
|
|
6
6
|
|
|
7
|
-
export { Signal, signal
|
|
8
|
-
export { ComputedSignal, computed
|
|
9
|
-
export {
|
|
7
|
+
export { Signal, signal } from "./base.js"
|
|
8
|
+
export { ComputedSignal, computed } from "./computed.js"
|
|
9
|
+
export { Effect, effect } from "./effect.js"
|
|
10
10
|
export { unwrap, tick } from "./utils.js"
|
|
11
|
-
export * from "./
|
|
11
|
+
export * from "./jsx.js"
|
|
12
12
|
export * from "./types.js"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Signalable } from "../types.js"
|
|
1
2
|
import type { Signal } from "./base.js"
|
|
2
3
|
import { unwrap } from "./utils.js"
|
|
3
4
|
|
|
@@ -28,3 +29,12 @@ export function For<T extends Signal<any[]> | unknown[]>({
|
|
|
28
29
|
if (items.length === 0) return fallback
|
|
29
30
|
return items.map(children)
|
|
30
31
|
}
|
|
32
|
+
|
|
33
|
+
export interface ShowProps {
|
|
34
|
+
children: JSX.Element
|
|
35
|
+
when: Signalable<unknown>
|
|
36
|
+
fallback?: JSX.Element
|
|
37
|
+
}
|
|
38
|
+
export function Show({ children, when, fallback }: ShowProps): JSX.Element {
|
|
39
|
+
return !!unwrap(when, true) ? children : fallback
|
|
40
|
+
}
|