kiru 0.48.0 → 0.48.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.
Files changed (69) hide show
  1. package/dist/appContext.d.ts.map +1 -1
  2. package/dist/appContext.js +3 -5
  3. package/dist/appContext.js.map +1 -1
  4. package/dist/constants.d.ts +2 -1
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +2 -1
  7. package/dist/constants.js.map +1 -1
  8. package/dist/customEvents.d.ts +6 -0
  9. package/dist/customEvents.d.ts.map +1 -0
  10. package/dist/customEvents.js +12 -0
  11. package/dist/customEvents.js.map +1 -0
  12. package/dist/dom.d.ts +3 -1
  13. package/dist/dom.d.ts.map +1 -1
  14. package/dist/dom.js +89 -160
  15. package/dist/dom.js.map +1 -1
  16. package/dist/globalContext.d.ts +4 -3
  17. package/dist/globalContext.d.ts.map +1 -1
  18. package/dist/globalContext.js +0 -2
  19. package/dist/globalContext.js.map +1 -1
  20. package/dist/hooks/useAsync.d.ts +2 -13
  21. package/dist/hooks/useAsync.d.ts.map +1 -1
  22. package/dist/hooks/useAsync.js.map +1 -1
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +7 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/lazy.d.ts +2 -2
  28. package/dist/lazy.d.ts.map +1 -1
  29. package/dist/lazy.js.map +1 -1
  30. package/dist/portal.d.ts +2 -2
  31. package/dist/portal.d.ts.map +1 -1
  32. package/dist/profiling.d.ts +2 -2
  33. package/dist/profiling.d.ts.map +1 -1
  34. package/dist/scheduler.d.ts +1 -0
  35. package/dist/scheduler.d.ts.map +1 -1
  36. package/dist/scheduler.js +17 -17
  37. package/dist/scheduler.js.map +1 -1
  38. package/dist/swr.d.ts +6 -17
  39. package/dist/swr.d.ts.map +1 -1
  40. package/dist/swr.js +26 -18
  41. package/dist/swr.js.map +1 -1
  42. package/dist/transition.d.ts +2 -2
  43. package/dist/transition.d.ts.map +1 -1
  44. package/dist/types.d.ts +20 -18
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/types.dom.d.ts +57 -38
  47. package/dist/types.dom.d.ts.map +1 -1
  48. package/dist/types.utils.d.ts +31 -19
  49. package/dist/types.utils.d.ts.map +1 -1
  50. package/dist/utils.js +9 -10
  51. package/dist/utils.js.map +1 -1
  52. package/package.json +1 -1
  53. package/src/appContext.ts +3 -5
  54. package/src/constants.ts +3 -0
  55. package/src/customEvents.ts +22 -0
  56. package/src/dom.ts +106 -168
  57. package/src/globalContext.ts +4 -6
  58. package/src/hooks/useAsync.ts +7 -24
  59. package/src/index.ts +7 -4
  60. package/src/lazy.ts +6 -2
  61. package/src/portal.ts +1 -1
  62. package/src/profiling.ts +1 -1
  63. package/src/scheduler.ts +27 -18
  64. package/src/swr.ts +28 -37
  65. package/src/transition.ts +1 -1
  66. package/src/types.dom.ts +98 -36
  67. package/src/types.ts +12 -10
  68. package/src/types.utils.ts +43 -14
  69. package/src/utils.ts +8 -8
package/src/scheduler.ts CHANGED
@@ -11,7 +11,14 @@ import {
11
11
  FLAG_MEMO,
12
12
  FLAG_NOOP,
13
13
  } from "./constants.js"
14
- import { commitDeletion, commitWork, createDom, hydrateDom } from "./dom.js"
14
+ import {
15
+ commitDeletion,
16
+ commitWork,
17
+ createDom,
18
+ hydrateDom,
19
+ onAfterFlushDomChanges,
20
+ onBeforeFlushDomChanges,
21
+ } from "./dom.js"
15
22
  import { __DEV__ } from "./env.js"
16
23
  import { KiruError } from "./error.js"
17
24
  import { hookIndex, node, renderMode } from "./globals.js"
@@ -62,15 +69,21 @@ export function flushSync() {
62
69
  doWork()
63
70
  }
64
71
 
72
+ export function renderRootSync(rootNode: VNode) {
73
+ rootNode.flags |= FLAG_DIRTY
74
+ treesInProgress.push(rootNode)
75
+ if (!isRunningOrQueued) {
76
+ isRunningOrQueued = true
77
+ doWork()
78
+ }
79
+ }
80
+
65
81
  /**
66
82
  * Queues a node for an update. Has no effect if the node is already deleted or marked for deletion.
67
83
  */
68
84
  export function requestUpdate(vNode: VNode): void {
69
- if (vNode.flags & FLAG_DELETION) return
70
85
  if (renderMode.current === "hydrate") {
71
- return nextIdle(() => {
72
- vNode.flags & FLAG_DELETION || queueUpdate(vNode)
73
- })
86
+ return nextIdle(() => queueUpdate(vNode))
74
87
  }
75
88
  queueUpdate(vNode)
76
89
  }
@@ -136,6 +149,7 @@ function doWork(): void {
136
149
 
137
150
  let len = 1
138
151
 
152
+ onBeforeFlushDomChanges()
139
153
  while (treesInProgress.length) {
140
154
  if (treesInProgress.length > len) {
141
155
  treesInProgress.sort(depthSort)
@@ -153,11 +167,12 @@ function doWork(): void {
153
167
  while (deletions.length) {
154
168
  commitDeletion(deletions.pop()!)
155
169
  }
156
- commitWork(currentWorkRoot)
157
170
 
171
+ commitWork(currentWorkRoot)
158
172
  currentWorkRoot.flags &= ~FLAG_DIRTY
159
173
  }
160
174
  }
175
+ onAfterFlushDomChanges()
161
176
 
162
177
  isImmediateEffectsMode = true
163
178
  flushEffects(preEffects)
@@ -193,18 +208,16 @@ function performUnitOfWork(vNode: VNode): VNode | void {
193
208
  updateHostComponent(vNode as DomVNode)
194
209
  } else if (isExoticType(vNode.type)) {
195
210
  if (vNode?.type === $CONTEXT_PROVIDER) {
196
- const asProvider = vNode as ContextProviderNode<any>
197
211
  const {
198
212
  props: { dependents, value },
199
213
  prev,
200
- } = asProvider
214
+ } = vNode as ContextProviderNode<unknown>
201
215
 
202
216
  if (dependents.size && prev && prev.props.value !== value) {
203
217
  dependents.forEach(queueUpdate)
204
218
  }
205
219
  }
206
220
  vNode.child = reconcileChildren(vNode, props.children)
207
- queueNodeChildDeletions(vNode)
208
221
  } else {
209
222
  renderChild = updateFunctionComponent(vNode as FunctionVNode)
210
223
  }
@@ -234,6 +247,11 @@ function performUnitOfWork(vNode: VNode): VNode | void {
234
247
  })
235
248
  }
236
249
 
250
+ if (vNode.deletions !== null) {
251
+ vNode.deletions.forEach(queueDelete)
252
+ vNode.deletions = null
253
+ }
254
+
237
255
  if (renderChild && vNode.child) {
238
256
  return vNode.child
239
257
  }
@@ -315,7 +333,6 @@ function updateFunctionComponent(vNode: FunctionVNode) {
315
333
  newChild = type(props)
316
334
  } while (isRenderDirtied)
317
335
  vNode.child = reconcileChildren(vNode, newChild)
318
- queueNodeChildDeletions(vNode)
319
336
  return true
320
337
  } finally {
321
338
  node.current = null
@@ -342,20 +359,12 @@ function updateHostComponent(vNode: DomVNode) {
342
359
  // text should _never_ have children
343
360
  if (type !== "#text") {
344
361
  vNode.child = reconcileChildren(vNode, props.children)
345
- queueNodeChildDeletions(vNode)
346
362
  if (vNode.child && renderMode.current === "hydrate") {
347
363
  hydrationStack.push(vNode.dom!)
348
364
  }
349
365
  }
350
366
  }
351
367
 
352
- function queueNodeChildDeletions(vNode: VNode) {
353
- if (vNode.deletions) {
354
- vNode.deletions.forEach(queueDelete)
355
- vNode.deletions = null
356
- }
357
- }
358
-
359
368
  function checkForTooManyConsecutiveDirtyRenders() {
360
369
  if (consecutiveDirtyCount > CONSECUTIVE_DIRTY_LIMIT) {
361
370
  throw new KiruError(
package/src/swr.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { __DEV__ } from "./env.js"
2
2
  import { useHook } from "./hooks/utils.js"
3
3
  import { Signal } from "./signals/base.js"
4
+ import { AsyncTaskState } from "./types.utils.js"
4
5
  import {
5
6
  noop,
6
7
  deepCompare,
@@ -9,23 +10,7 @@ import {
9
10
  shallowCompare,
10
11
  } from "./utils.js"
11
12
 
12
- export type UseSWRState<T> = (
13
- | {
14
- data: null
15
- error: null
16
- loading: true
17
- }
18
- | {
19
- data: T
20
- error: null
21
- loading: false
22
- }
23
- | {
24
- data: null
25
- error: UseSWRError
26
- loading: false
27
- }
28
- ) & {
13
+ export type UseSWRState<T> = AsyncTaskState<T, UseSWRError> & {
29
14
  mutate: (callback: () => Promise<T>) => void
30
15
  isMutating: Signal<boolean>
31
16
  isValidating: Signal<boolean>
@@ -51,7 +36,7 @@ export type SWRRetryState = {
51
36
  delay: number
52
37
  } | null
53
38
 
54
- export type SWRCacheEntry<T> = {
39
+ export interface SWRCacheEntry<T> {
55
40
  key: any
56
41
  resource: Signal<SWRResourceState<T>>
57
42
  fetcher: (args: any) => Promise<T>
@@ -65,7 +50,7 @@ export type SWRCacheEntry<T> = {
65
50
 
66
51
  export type SWRCache = Map<string, SWRCacheEntry<any>>
67
52
 
68
- export type SWROptions = {
53
+ export interface SWROptions {
69
54
  /**
70
55
  * Specify `false` to disable revalidation on focus
71
56
  */
@@ -103,19 +88,24 @@ export type SWRKey =
103
88
  | undefined
104
89
  | false
105
90
 
106
- let SWR_GLOBAL_CACHE: SWRCache
107
- let IS_ONLINE = false
91
+ const SWRGlobalState = {
92
+ cache: null as any as SWRCache,
93
+ online: false,
94
+ }
108
95
 
109
96
  if ("window" in globalThis) {
110
- SWR_GLOBAL_CACHE = window.__kiru!.globalState[Symbol.for("SWR_GLOBAL")] ??=
111
- new Map()
97
+ if (__DEV__) {
98
+ SWRGlobalState.cache = window.__kiru!.SWRGlobalCache ??= new Map()
99
+ } else {
100
+ SWRGlobalState.cache = new Map()
101
+ }
112
102
 
113
- IS_ONLINE = navigator.onLine
103
+ SWRGlobalState.online = navigator.onLine
114
104
  window.addEventListener("online", () => {
115
- IS_ONLINE = true
105
+ SWRGlobalState.online = true
116
106
  })
117
107
  window.addEventListener("offline", () => {
118
- IS_ONLINE = false
108
+ SWRGlobalState.online = false
119
109
  })
120
110
 
121
111
  let blurStart: number | null = null
@@ -127,11 +117,12 @@ if ("window" in globalThis) {
127
117
  blurStart = null
128
118
  if (blurDuration < 3_000) return // only trigger revalidation after 3 seconds
129
119
 
130
- SWR_GLOBAL_CACHE.forEach((entry) => {
120
+ SWRGlobalState.cache.forEach((entry) => {
131
121
  if (
132
122
  entry.subscribers.size === 0 ||
133
123
  entry.options.revalidateOnFocus === false ||
134
- (entry.options.refetchWhenOffline === false && IS_ONLINE === false)
124
+ (entry.options.refetchWhenOffline === false &&
125
+ SWRGlobalState.online === false)
135
126
  ) {
136
127
  return
137
128
  }
@@ -171,16 +162,16 @@ export function preloadSWR<T>(
171
162
  if (!("window" in globalThis)) return
172
163
 
173
164
  const strKey = safeStringify(key, { functions: false })
174
- if (!SWR_GLOBAL_CACHE.has(strKey)) {
165
+ if (!SWRGlobalState.cache.has(strKey)) {
175
166
  const entry = createSWRCacheEntry(key, fetcher)
176
- SWR_GLOBAL_CACHE.set(strKey, entry)
167
+ SWRGlobalState.cache.set(strKey, entry)
177
168
  performFetch(entry)
178
169
  }
179
170
  }
180
171
 
181
172
  export function getSWRState<T>(key: SWRKey): SWRCacheEntry<T> | null {
182
173
  const strKey = safeStringify(key, { functions: false })
183
- return SWR_GLOBAL_CACHE.get(strKey) ?? null
174
+ return SWRGlobalState.cache.get(strKey) ?? null
184
175
  }
185
176
 
186
177
  export function useSWR<T, K extends SWRKey>(
@@ -201,14 +192,14 @@ export function useSWR<T, K extends SWRKey>(
201
192
  devtools: {
202
193
  get: () => ({
203
194
  key: hook.strKey,
204
- value: SWR_GLOBAL_CACHE.get(strKey)!,
195
+ value: SWRGlobalState.cache.get(strKey)!,
205
196
  }),
206
197
  },
207
198
  initialArgs: [key, options],
208
199
  }
209
200
  }
210
201
  if (isHMR) {
211
- const entry = SWR_GLOBAL_CACHE.get(hook.strKey)
202
+ const entry = SWRGlobalState.cache.get(hook.strKey)
212
203
  const [k, o] = hook.dev!.initialArgs
213
204
  hook.dev!.initialArgs = [key, options]
214
205
 
@@ -239,10 +230,10 @@ export function useSWR<T, K extends SWRKey>(
239
230
  hook.update = update
240
231
 
241
232
  let isNewEntry = false
242
- if (!SWR_GLOBAL_CACHE.has(strKey)) {
233
+ if (!SWRGlobalState.cache.has(strKey)) {
243
234
  isNewEntry = true
244
235
  entry = createSWRCacheEntry(key, fetcher)
245
- SWR_GLOBAL_CACHE.set(strKey, entry)
236
+ SWRGlobalState.cache.set(strKey, entry)
246
237
 
247
238
  entry.resource.subscribe(() => {
248
239
  entry.subscribers.forEach((sub) => sub.update())
@@ -251,7 +242,7 @@ export function useSWR<T, K extends SWRKey>(
251
242
  performFetch(entry)
252
243
  }
253
244
 
254
- entry ??= SWR_GLOBAL_CACHE.get(strKey)!
245
+ entry ??= SWRGlobalState.cache.get(strKey)!
255
246
  const subs = entry.subscribers
256
247
  if (subs.size === 0) {
257
248
  if (!isNewEntry) {
@@ -279,7 +270,7 @@ export function useSWR<T, K extends SWRKey>(
279
270
  }
280
271
  }
281
272
 
282
- entry ??= SWR_GLOBAL_CACHE.get(strKey)!
273
+ entry ??= SWRGlobalState.cache.get(strKey)!
283
274
  const { resource, isMutating, isValidating } = entry
284
275
  const { data, loading, error } = resource.peek()
285
276
 
package/src/transition.ts CHANGED
@@ -5,7 +5,7 @@ import { useRef } from "./hooks/useRef.js"
5
5
  import { useState } from "./hooks/useState.js"
6
6
 
7
7
  export type TransitionState = "entering" | "entered" | "exiting" | "exited"
8
- type TransitionProps = {
8
+ interface TransitionProps {
9
9
  in: boolean
10
10
  /**
11
11
  * Initial state of the transition
package/src/types.dom.ts CHANGED
@@ -164,7 +164,7 @@ type ListOfUrlsOrPaths = string
164
164
  type FileName = string
165
165
 
166
166
  type MediaPreload = "none" | "metadata" | "auto" | ""
167
- type HTMLMediaElementAttrs = {
167
+ interface HTMLMediaElementAttrs {
168
168
  autoplay?: boolean
169
169
  controls?: boolean
170
170
  crossOrigin?: string
@@ -298,7 +298,7 @@ type FormMethod = "get" | "post" | "dialog"
298
298
 
299
299
  type Direction = "ltr" | "rtl" | "auto"
300
300
 
301
- type GlobalAttributes = {
301
+ interface GlobalAttributes {
302
302
  accessKey?: string
303
303
  autocapitalize?: "on" | "off" | "none" | "sentences" | "words" | "characters"
304
304
  className?: string
@@ -364,41 +364,103 @@ declare global {
364
364
  bivarianceHack(event: E): void
365
365
  }["bivarianceHack"]
366
366
 
367
- type BaseEventHandler<T = Element> = EventHandler<DOMEvent<Event, T>>
368
- type AnimationEvent<T = Element> = DOMEvent<NativeAnimationEvent, T>
369
- type ClipboardEvent<T = Element> = DOMEvent<NativeClipboardEvent, T>
370
- type CompositionEvent<T = Element> = DOMEvent<NativeCompositionEvent, T>
371
- type DragEvent<T = Element> = DOMEvent<NativeDragEvent, T>
372
- type FocusEvent<T = Element> = DOMEvent<NativeFocusEvent, T>
373
- type FormEvent<T = Element> = DOMEvent<Event, T>
374
- type KeyboardEvent<T = Element> = DOMEvent<NativeKeyboardEvent, T>
375
- type MouseEvent<T = Element> = DOMEvent<NativeMouseEvent, T>
376
- type PointerEvent<T = Element> = DOMEvent<NativePointerEvent, T>
377
- type SubmitEvent<T = Element> = DOMEvent<NativeSubmitEvent, T>
378
- type TouchEvent<T = Element> = DOMEvent<NativeTouchEvent, T>
379
- type ToggleEvent<T = Element> = DOMEvent<NativeToggleEvent, T>
380
- type TransitionEvent<T = Element> = DOMEvent<NativeTransitionEvent, T>
381
- type UIEvent<T = Element> = DOMEvent<NativeUIEvent, T>
382
- type WheelEvent<T = Element> = DOMEvent<NativeWheelEvent, T>
383
-
384
- type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>
385
- type CompositionEventHandler<T = Element> = EventHandler<
367
+ interface BaseEventHandler<T extends Element = Element>
368
+ extends DOMEvent<Event, T> {}
369
+
370
+ interface AnimationEvent<T extends Element = Element>
371
+ extends DOMEvent<NativeAnimationEvent, T> {}
372
+
373
+ interface ClipboardEvent<T extends Element = Element>
374
+ extends DOMEvent<NativeClipboardEvent, T> {}
375
+
376
+ interface CompositionEvent<T extends Element = Element>
377
+ extends DOMEvent<NativeCompositionEvent, T> {}
378
+
379
+ interface DragEvent<T extends Element = Element>
380
+ extends DOMEvent<NativeDragEvent, T> {}
381
+
382
+ interface FocusEvent<T extends Element = Element>
383
+ extends DOMEvent<NativeFocusEvent, T> {}
384
+
385
+ interface FormEvent<T extends Element = Element>
386
+ extends DOMEvent<Event, T> {}
387
+
388
+ interface KeyboardEvent<T extends Element = Element>
389
+ extends DOMEvent<NativeKeyboardEvent, T> {}
390
+
391
+ interface MouseEvent<T extends Element = Element>
392
+ extends DOMEvent<NativeMouseEvent, T> {}
393
+
394
+ interface PointerEvent<T extends Element = Element>
395
+ extends DOMEvent<NativePointerEvent, T> {}
396
+
397
+ interface SubmitEvent<T extends Element = Element>
398
+ extends DOMEvent<NativeSubmitEvent, T> {}
399
+
400
+ interface TouchEvent<T extends Element = Element>
401
+ extends DOMEvent<NativeTouchEvent, T> {}
402
+
403
+ interface ToggleEvent<T extends Element = Element>
404
+ extends DOMEvent<NativeToggleEvent, T> {}
405
+
406
+ interface TransitionEvent<T extends Element = Element>
407
+ extends DOMEvent<NativeTransitionEvent, T> {}
408
+
409
+ interface UIEvent<T extends Element = Element>
410
+ extends DOMEvent<NativeUIEvent, T> {}
411
+
412
+ interface WheelEvent<T extends Element = Element>
413
+ extends DOMEvent<NativeWheelEvent, T> {}
414
+
415
+ type ClipboardEventHandler<T extends Element = Element> = EventHandler<
416
+ ClipboardEvent<T>
417
+ >
418
+ type CompositionEventHandler<T extends Element = Element> = EventHandler<
386
419
  CompositionEvent<T>
387
420
  >
388
- type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>
389
- type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>
390
- type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>
391
- type KeyboardEventHandler<T = Element> = EventHandler<KeyboardEvent<T>>
392
- type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>
393
- type TouchEventHandler<T = Element> = EventHandler<TouchEvent<T>>
394
- type PointerEventHandler<T = Element> = EventHandler<PointerEvent<T>>
395
- type UIEventHandler<T = Element> = EventHandler<UIEvent<T>>
396
- type WheelEventHandler<T = Element> = EventHandler<WheelEvent<T>>
397
- type AnimationEventHandler<T = Element> = EventHandler<AnimationEvent<T>>
398
- type ToggleEventHandler<T = Element> = EventHandler<ToggleEvent<T>>
399
- type TransitionEventHandler<T = Element> = EventHandler<TransitionEvent<T>>
400
-
401
- type EventAttributes<T = Element> = {
421
+ type DragEventHandler<T extends Element = Element> = EventHandler<
422
+ DragEvent<T>
423
+ >
424
+ type FocusEventHandler<T extends Element = Element> = EventHandler<
425
+ FocusEvent<T>
426
+ >
427
+ type FormEventHandler<T extends Element = Element> = EventHandler<
428
+ FormEvent<T>
429
+ >
430
+ type KeyboardEventHandler<T extends Element = Element> = EventHandler<
431
+ KeyboardEvent<T>
432
+ >
433
+ type MouseEventHandler<T extends Element = Element> = EventHandler<
434
+ MouseEvent<T>
435
+ >
436
+ type TouchEventHandler<T extends Element = Element> = EventHandler<
437
+ TouchEvent<T>
438
+ >
439
+ type PointerEventHandler<T extends Element = Element> = EventHandler<
440
+ PointerEvent<T>
441
+ >
442
+ type UIEventHandler<T extends Element = Element> = EventHandler<UIEvent<T>>
443
+ type WheelEventHandler<T extends Element = Element> = EventHandler<
444
+ WheelEvent<T>
445
+ >
446
+ type AnimationEventHandler<T extends Element = Element> = EventHandler<
447
+ AnimationEvent<T>
448
+ >
449
+ type ToggleEventHandler<T extends Element = Element> = EventHandler<
450
+ ToggleEvent<T>
451
+ >
452
+ type TransitionEventHandler<T extends Element = Element> = EventHandler<
453
+ TransitionEvent<T>
454
+ >
455
+
456
+ type CustomEventAttributes = {
457
+ [Key in keyof Kiru.CustomEvents as `on:${Key}`]?: (
458
+ event: CustomEvent<Kiru.CustomEvents[Key]>
459
+ ) => void
460
+ }
461
+
462
+ interface EventAttributes<T extends Element = Element>
463
+ extends CustomEventAttributes {
402
464
  // Clipboard Events
403
465
  oncopy?: ClipboardEventHandler<T> | undefined
404
466
  oncut?: ClipboardEventHandler<T> | undefined
@@ -524,7 +586,7 @@ declare global {
524
586
 
525
587
  type ElementReference<T extends HTMLElement> = T | null | string
526
588
 
527
- type PopoverControlAttributes = {
589
+ interface PopoverControlAttributes {
528
590
  popoverTarget?: string
529
591
  popoverTargetAction?: "show" | "hide" | "toggle"
530
592
  }
package/src/types.ts CHANGED
@@ -16,10 +16,10 @@ import type {
16
16
  HTMLTagToElement,
17
17
  SVGTagToElement,
18
18
  } from "./types.dom"
19
- import { Signalable, SomeDom } from "./types.utils"
19
+ import { AsyncTaskState, Prettify, Signalable, SomeDom } from "./types.utils"
20
20
  import type { AppContext } from "./appContext"
21
21
 
22
- export type { ElementProps, StyleObject }
22
+ export type { AsyncTaskState, ElementProps, Prettify, Signalable, StyleObject }
23
23
 
24
24
  type ElementProps<T extends keyof JSX.IntrinsicElements> =
25
25
  JSX.IntrinsicElements[T]
@@ -102,7 +102,7 @@ declare global {
102
102
  | PrimitiveChild
103
103
  | Kiru.Signal<PrimitiveChild>
104
104
 
105
- type ElementAttributes = {
105
+ interface ElementAttributes {
106
106
  key?: JSX.ElementKey
107
107
  children?: JSX.Children
108
108
  innerHTML?:
@@ -112,11 +112,13 @@ declare global {
112
112
  }
113
113
  }
114
114
  namespace Kiru {
115
- type ProviderProps<T> = {
115
+ interface CustomEvents {}
116
+
117
+ interface ProviderProps<T> {
116
118
  value: T
117
119
  children?: JSX.Children | ((value: T) => JSX.Element)
118
120
  }
119
- type Context<T> = {
121
+ interface Context<T> {
120
122
  [$CONTEXT]: true
121
123
  Provider: (({ value, children }: ProviderProps<T>) => JSX.Element) & {
122
124
  displayName?: string
@@ -133,7 +135,7 @@ declare global {
133
135
  type FCProps<T = {}> = T & { children?: JSX.Children }
134
136
  type InferProps<T> = T extends Kiru.FC<infer P> ? P : never
135
137
 
136
- type HookDevtoolsProvisions<T extends Record<string, any>> = {
138
+ interface HookDevtoolsProvisions<T extends Record<string, any>> {
137
139
  get: () => T
138
140
  set?: (value: T) => void
139
141
  }
@@ -146,10 +148,10 @@ declare global {
146
148
  devtools?: HookDevtoolsProvisions<any>
147
149
  }
148
150
  }
149
- type RefObject<T> = {
151
+ interface RefObject<T> {
150
152
  readonly current: T | null
151
153
  }
152
- type MutableRefObject<T> = {
154
+ interface MutableRefObject<T> {
153
155
  current: T
154
156
  }
155
157
  type RefCallback<T> = {
@@ -169,7 +171,7 @@ declare global {
169
171
  | typeof $CONTEXT_PROVIDER
170
172
  | typeof $HYDRATION_BOUNDARY
171
173
 
172
- type VNode = {
174
+ interface VNode {
173
175
  app?: AppContext
174
176
  dom?: SomeDom
175
177
  lastChildDom?: SomeDom
@@ -203,7 +205,7 @@ declare global {
203
205
  hmrUpdated?: boolean
204
206
  }
205
207
  }
206
- type VNodeSnapshot = {
208
+ interface VNodeSnapshot {
207
209
  props: Kiru.VNode["props"]
208
210
  memoizedProps: Kiru.VNode["memoizedProps"]
209
211
  index: number
@@ -1,35 +1,47 @@
1
- import type { $CONTEXT_PROVIDER, $HYDRATION_BOUNDARY } from "./constants"
1
+ import type {
2
+ $CONTEXT_PROVIDER,
3
+ $FRAGMENT,
4
+ $HYDRATION_BOUNDARY,
5
+ } from "./constants"
2
6
  import type { HydrationBoundaryMode } from "./ssr/hydrationBoundary"
3
7
  import type { Signal } from "./signals"
4
8
 
5
9
  export type SomeElement = HTMLElement | SVGElement
6
10
  export type SomeDom = HTMLElement | SVGElement | Text
11
+ export type MaybeElement = SomeElement | undefined
7
12
  export type MaybeDom = SomeDom | undefined
8
13
 
9
- type VNode = Kiru.VNode
10
-
11
- export type FunctionVNode = Omit<VNode, "type"> & {
12
- type: (...args: any) => any
13
- }
14
- export type ExoticVNode = Omit<VNode, "type"> & {
15
- type: Kiru.ExoticSymbol
14
+ export interface FunctionVNode extends Kiru.VNode {
15
+ type: (...args: any) => JSX.Element
16
16
  }
17
- export type ElementVNode = Omit<VNode, "dom" | "type"> & {
17
+
18
+ export interface ElementVNode extends Kiru.VNode {
18
19
  dom: SomeElement
19
20
  type: string
20
21
  }
21
- export type DomVNode = Omit<VNode, "dom" | "type"> & {
22
+ export interface DomVNode extends Kiru.VNode {
22
23
  dom: SomeDom
23
24
  type: "#text" | (string & {})
24
25
  }
25
26
 
26
- export type ContextProviderNode<T> = Kiru.VNode & {
27
+ export interface ContextProviderNode<T> extends Kiru.VNode {
27
28
  type: typeof $CONTEXT_PROVIDER
28
- props: { value: T; ctx: Kiru.Context<T>; dependents: Set<Kiru.VNode> }
29
+ props: Kiru.VNode["props"] & {
30
+ value: T
31
+ ctx: Kiru.Context<T>
32
+ dependents: Set<Kiru.VNode>
33
+ }
29
34
  }
30
- export type HydrationBoundaryNode = Kiru.VNode & {
35
+
36
+ export interface HydrationBoundaryNode extends Kiru.VNode {
31
37
  type: typeof $HYDRATION_BOUNDARY
32
- props: { mode: HydrationBoundaryMode }
38
+ props: Kiru.VNode["props"] & {
39
+ mode: HydrationBoundaryMode
40
+ }
41
+ }
42
+
43
+ export interface FragmentNode extends Kiru.VNode {
44
+ type: typeof $FRAGMENT
33
45
  }
34
46
 
35
47
  export type Prettify<T> = {
@@ -37,3 +49,20 @@ export type Prettify<T> = {
37
49
  } & {}
38
50
 
39
51
  export type Signalable<T> = T | Signal<T>
52
+
53
+ export type AsyncTaskState<T, E extends Error = Error> =
54
+ | {
55
+ data: null
56
+ error: null
57
+ loading: true
58
+ }
59
+ | {
60
+ data: T
61
+ error: null
62
+ loading: false
63
+ }
64
+ | {
65
+ data: null
66
+ error: E
67
+ loading: false
68
+ }
package/src/utils.ts CHANGED
@@ -155,15 +155,15 @@ function vNodeContains(haystack: VNode, needle: VNode): boolean {
155
155
  }
156
156
 
157
157
  function traverseApply(vNode: VNode, func: (node: VNode) => void): void {
158
- let applyToSiblings = false
159
- const nodes: VNode[] = [vNode]
160
- const apply = (node: VNode) => {
161
- func(node)
162
- node.child && nodes.push(node.child)
163
- applyToSiblings && node.sibling && nodes.push(node.sibling)
164
- applyToSiblings = true
158
+ func(vNode)
159
+ let child = vNode.child
160
+ while (child) {
161
+ func(child)
162
+ if (child.child) {
163
+ traverseApply(child, func)
164
+ }
165
+ child = child.sibling
165
166
  }
166
- while (nodes.length) apply(nodes.shift()!)
167
167
  }
168
168
 
169
169
  function findParent(vNode: Kiru.VNode, predicate: (n: Kiru.VNode) => boolean) {