kiru 0.48.0 → 0.48.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiru",
3
- "version": "0.48.0",
3
+ "version": "0.48.2",
4
4
  "description": "A batteries-included, easy-to-use rendering library with a tiny footprint",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
package/src/appContext.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FLAG_STATIC_DOM } from "./constants.js"
2
2
  import { createElement } from "./element.js"
3
3
  import { __DEV__ } from "./env.js"
4
- import { requestUpdate, flushSync } from "./scheduler.js"
4
+ import { renderRootSync } from "./scheduler.js"
5
5
 
6
6
  type VNode = Kiru.VNode
7
7
 
@@ -53,14 +53,12 @@ export function mount(
53
53
 
54
54
  function render(children: JSX.Element) {
55
55
  rootNode.props.children = children
56
- requestUpdate(rootNode)
57
- flushSync()
56
+ renderRootSync(rootNode)
58
57
  }
59
58
 
60
59
  function unmount() {
61
60
  rootNode.props.children = null
62
- requestUpdate(rootNode)
63
- flushSync()
61
+ renderRootSync(rootNode)
64
62
  if (__DEV__) {
65
63
  delete container.__kiruNode
66
64
  delete rootNode.app
package/src/constants.ts CHANGED
@@ -9,6 +9,7 @@ export {
9
9
  $HYDRATION_BOUNDARY,
10
10
  CONSECUTIVE_DIRTY_LIMIT,
11
11
  REGEX_UNIT,
12
+ EVENT_PREFIX_REGEX,
12
13
  FLAG_UPDATE,
13
14
  FLAG_PLACEMENT,
14
15
  FLAG_DELETION,
@@ -50,6 +51,8 @@ const REGEX_UNIT = {
50
51
  ALPHA_UPPER_G: /[A-Z]/g,
51
52
  } as const
52
53
 
54
+ const EVENT_PREFIX_REGEX = /^on:?/
55
+
53
56
  const voidElements = new Set([
54
57
  "area",
55
58
  "base",
@@ -0,0 +1,22 @@
1
+ export class CustomEvents {
2
+ private constructor() {}
3
+
4
+ static on<K extends keyof Kiru.CustomEvents & string>(
5
+ type: K,
6
+ callback: (event: CustomEvent<Kiru.CustomEvents[K]>) => void
7
+ ) {
8
+ window.addEventListener(type, callback as unknown as EventListener)
9
+ return () =>
10
+ window.removeEventListener(type, callback as unknown as EventListener)
11
+ }
12
+
13
+ static dispatch<K extends keyof Kiru.CustomEvents & string>(
14
+ type: K,
15
+ detail: Kiru.CustomEvents[K],
16
+ target?: Element
17
+ ) {
18
+ ;(target || document).dispatchEvent(
19
+ new CustomEvent(type, { detail, bubbles: true })
20
+ )
21
+ }
22
+ }
package/src/dom.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  FLAG_STATIC_DOM,
13
13
  svgTags,
14
14
  FLAG_NOOP,
15
+ EVENT_PREFIX_REGEX,
15
16
  } from "./constants.js"
16
17
  import { Signal } from "./signals/base.js"
17
18
  import { unwrap } from "./signals/utils.js"
@@ -29,17 +30,47 @@ import type {
29
30
  } from "./types.utils"
30
31
  import type { AppContext } from "./appContext.js"
31
32
 
32
- export { commitWork, commitDeletion, createDom, hydrateDom }
33
+ export {
34
+ commitWork,
35
+ onBeforeFlushDomChanges,
36
+ onAfterFlushDomChanges,
37
+ commitDeletion,
38
+ createDom,
39
+ hydrateDom,
40
+ }
33
41
 
34
42
  type VNode = Kiru.VNode
35
43
  type HostNode = {
36
44
  node: ElementVNode
37
45
  lastChild?: SomeDom
38
46
  }
39
- type PlacementScope = {
40
- parent: VNode
41
- active: boolean
42
- child?: VNode
47
+
48
+ let persistingFocus = false
49
+ let didBlurActiveElement = false
50
+ const placementBlurHandler = (event: Event) => {
51
+ event.preventDefault()
52
+ event.stopPropagation()
53
+ didBlurActiveElement = true
54
+ }
55
+
56
+ let currentActiveElement: Element | null = null
57
+ function onBeforeFlushDomChanges() {
58
+ persistingFocus = true
59
+ currentActiveElement = document.activeElement
60
+ if (currentActiveElement && currentActiveElement !== document.body) {
61
+ currentActiveElement.addEventListener("blur", placementBlurHandler)
62
+ }
63
+ }
64
+
65
+ function onAfterFlushDomChanges() {
66
+ if (didBlurActiveElement) {
67
+ currentActiveElement!.removeEventListener("blur", placementBlurHandler)
68
+ if (currentActiveElement!.isConnected) {
69
+ ;(currentActiveElement as any).focus()
70
+ }
71
+ didBlurActiveElement = false
72
+ }
73
+ persistingFocus = false
43
74
  }
44
75
 
45
76
  function setDomRef(ref: Kiru.Ref<SomeDom | null>, value: SomeDom | null) {
@@ -81,42 +112,6 @@ function createTextNode(vNode: VNode): Text {
81
112
  return textNode
82
113
  }
83
114
 
84
- /**
85
- * toggled when we fire a focus event on an element
86
- * persist focus when the currently focused element is moved.
87
- */
88
- let persistingFocus = false
89
-
90
- // gets set prior to dom commits
91
- let currentActiveElement: Element | null = null
92
-
93
- let didBlurActiveElement = false
94
- const placementBlurHandler = (event: Event) => {
95
- event.preventDefault()
96
- event.stopPropagation()
97
- didBlurActiveElement = true
98
- }
99
-
100
- function handlePrePlacementFocusPersistence() {
101
- persistingFocus = true
102
- currentActiveElement = document.activeElement
103
- if (currentActiveElement && currentActiveElement !== document.body) {
104
- currentActiveElement.addEventListener("blur", placementBlurHandler)
105
- }
106
- }
107
-
108
- function handlePostPlacementFocusPersistence() {
109
- if (!didBlurActiveElement) {
110
- persistingFocus = false
111
- return
112
- }
113
- currentActiveElement?.removeEventListener("blur", placementBlurHandler)
114
- if (currentActiveElement?.isConnected) {
115
- if ("focus" in currentActiveElement) (currentActiveElement as any).focus()
116
- }
117
- persistingFocus = false
118
- }
119
-
120
115
  function wrapFocusEventHandler(
121
116
  vNode: VNode,
122
117
  evtName: "focus" | "blur",
@@ -169,7 +164,8 @@ function updateDom(vNode: VNode) {
169
164
 
170
165
  if (propFilters.isEvent(key)) {
171
166
  if (prev !== next || renderMode.current === "hydrate") {
172
- const evtName = key.toLowerCase().substring(2)
167
+ const evtName = key.replace(EVENT_PREFIX_REGEX, "")
168
+
173
169
  const isFocusEvent = evtName === "focus" || evtName === "blur"
174
170
  if (key in prevProps) {
175
171
  dom.removeEventListener(
@@ -604,128 +600,49 @@ function commitWork(vNode: VNode) {
604
600
  if (renderMode.current === "hydrate") {
605
601
  return traverseApply(vNode, commitSnapshot)
606
602
  }
607
- handlePrePlacementFocusPersistence()
608
-
609
- const hostNodes: HostNode[] = []
610
- let currentHostNode: HostNode | undefined
611
- const placementScopes: PlacementScope[] = []
612
- let currentPlacementScope: PlacementScope | undefined
613
603
 
614
- const root = vNode
615
- const rootChild = root.child
616
-
617
- const onAscent = (node: VNode) => {
618
- let inheritsPlacement = false
619
- if (currentPlacementScope?.child === node) {
620
- currentPlacementScope.active = true
621
- inheritsPlacement = true
622
- }
623
- if (node.dom) {
624
- if (!currentHostNode) {
625
- currentHostNode = { node: getDomParent(node) }
626
- hostNodes.push(currentHostNode)
627
- }
628
- if (!(node.flags & FLAG_STATIC_DOM)) {
629
- commitDom(node as DomVNode, currentHostNode, inheritsPlacement)
630
- }
631
- }
632
- commitSnapshot(node)
604
+ const host: HostNode = {
605
+ node: vNode.dom ? (vNode as ElementVNode) : getDomParent(vNode),
633
606
  }
634
-
635
- if (!rootChild) {
636
- onAscent(root)
637
- return
607
+ commitWork_impl(vNode, host, (vNode.flags & FLAG_PLACEMENT) > 0)
608
+ if (vNode.dom && !(vNode.flags & FLAG_STATIC_DOM)) {
609
+ commitDom(vNode as DomVNode, host, false)
638
610
  }
611
+ commitSnapshot(vNode)
612
+ }
639
613
 
640
- const onDescent = (node: VNode) => {
641
- if (node.dom) {
642
- // collect host nodes as we go
643
- currentHostNode = { node: node as ElementVNode }
644
- hostNodes.push(currentHostNode)
645
-
646
- if (node.prev && "innerHTML" in node.prev.props) {
647
- /**
648
- * We need to update innerHTML during descent in cases
649
- * where we previously set innerHTML on this element but
650
- * now we provide children. Setting innerHTML _after_
651
- * appending children will yeet em into the abyss.
652
- */
653
- delete node.props.innerHTML
654
- setInnerHTML(node.dom as SomeElement, "")
655
- // remove innerHTML from prev to prevent our ascension pass from doing this again
656
- delete node.prev.props.innerHTML
657
- }
658
-
659
- if (currentPlacementScope?.active) {
660
- currentPlacementScope.child = node
661
- // prevent scope applying to descendants of this element node
662
- currentPlacementScope.active = false
614
+ function commitWork_impl(
615
+ vNode: VNode,
616
+ currentHostNode: HostNode,
617
+ inheritsPlacement: boolean
618
+ ) {
619
+ let child: VNode | null = vNode.child
620
+ while (child) {
621
+ if (child.flags & FLAG_NOOP) {
622
+ if (child.flags & FLAG_PLACEMENT) {
623
+ placeAndCommitNoopChildren(child, currentHostNode)
663
624
  }
664
- } else if (node.flags & FLAG_PLACEMENT) {
665
- currentPlacementScope = { parent: node, active: true }
666
- placementScopes.push(currentPlacementScope)
625
+ commitSnapshot(child)
626
+ child = child.sibling
627
+ continue
667
628
  }
668
- }
669
629
 
670
- onDescent(root)
671
- let branch = rootChild
672
- while (branch) {
673
- let c = branch
674
- while (c) {
675
- if (!c.child) break
676
- if (c.flags & FLAG_NOOP) {
677
- if (c.flags & FLAG_PLACEMENT) {
678
- const directDomChildren = findDirectDomChildren(c)
679
- if (directDomChildren.length === 0) {
680
- break
681
- }
682
- if (!currentHostNode) {
683
- currentHostNode = { node: getDomParent(c) }
684
- hostNodes.push(currentHostNode)
685
- }
686
- const { node, lastChild } = currentHostNode
687
- if (lastChild) {
688
- lastChild.after(...directDomChildren)
689
- } else {
690
- const nextSiblingDom = getNextSiblingDom(c, node)
691
- const parentDom = node.dom
692
- if (nextSiblingDom) {
693
- const [first, ...rest] = directDomChildren
694
- parentDom.insertBefore(first, nextSiblingDom)
695
- first.after(...rest)
696
- } else {
697
- parentDom.append(...directDomChildren)
698
- }
699
- }
700
- currentHostNode.lastChild =
701
- directDomChildren[directDomChildren.length - 1]
702
- }
703
- break
630
+ if (child.dom) {
631
+ commitWork_impl(child, { node: child as ElementVNode }, false)
632
+ if (!(child.flags & FLAG_STATIC_DOM)) {
633
+ commitDom(child as DomVNode, currentHostNode, inheritsPlacement)
704
634
  }
705
- onDescent(c)
706
- c = c.child
635
+ } else {
636
+ commitWork_impl(
637
+ child,
638
+ currentHostNode,
639
+ (child.flags & FLAG_PLACEMENT) > 0 || inheritsPlacement
640
+ )
707
641
  }
708
642
 
709
- while (c && c !== root) {
710
- onAscent(c)
711
- if (c.sibling) {
712
- branch = c.sibling
713
- break
714
- }
715
- if (currentPlacementScope?.parent === c) {
716
- placementScopes.pop()
717
- currentPlacementScope = placementScopes[placementScopes.length - 1]
718
- }
719
- if (currentHostNode?.node === c.parent) {
720
- hostNodes.pop()
721
- currentHostNode = hostNodes[hostNodes.length - 1]
722
- }
723
- c = c.parent!
724
- }
725
- if (c === root) break
643
+ commitSnapshot(child)
644
+ child = child.sibling
726
645
  }
727
- onAscent(root)
728
- handlePostPlacementFocusPersistence()
729
646
  }
730
647
 
731
648
  function commitDom(
@@ -762,12 +679,16 @@ function commitDeletion(vNode: VNode) {
762
679
  dom,
763
680
  props: { ref },
764
681
  } = node
682
+
765
683
  subs?.forEach((unsub) => unsub())
766
684
  if (cleanups) Object.values(cleanups).forEach((c) => c())
767
685
  while (hooks?.length) hooks.pop()!.cleanup?.()
768
686
 
769
687
  if (__DEV__) {
770
688
  window.__kiru?.profilingContext?.emit("removeNode", ctx)
689
+ if (dom instanceof Element) {
690
+ delete dom.__kiruNode
691
+ }
771
692
  }
772
693
 
773
694
  if (dom) {
@@ -782,24 +703,41 @@ function commitDeletion(vNode: VNode) {
782
703
  vNode.parent = null
783
704
  }
784
705
 
785
- function findDirectDomChildren(vNode: VNode): SomeDom[] {
706
+ function placeAndCommitNoopChildren(
707
+ parent: VNode,
708
+ currentHostNode: HostNode
709
+ ): void {
710
+ if (!parent.child) return
711
+
786
712
  const domChildren: SomeDom[] = []
713
+ collectDomNodes(parent.child, domChildren)
714
+ if (domChildren.length === 0) return
787
715
 
788
- function collectDomNodes(node: VNode | null): void {
789
- while (node) {
790
- if (node.dom) {
791
- // Found a DOM node, add it to the collection
792
- domChildren.push(node.dom)
793
- } else if (node.child) {
794
- // This is a component or fragment, traverse its children
795
- collectDomNodes(node.child)
796
- }
797
- node = node.sibling
716
+ const { node, lastChild } = currentHostNode
717
+ if (lastChild) {
718
+ lastChild.after(...domChildren)
719
+ } else {
720
+ const nextSiblingDom = getNextSiblingDom(parent, node)
721
+ const parentDom = node.dom
722
+ if (nextSiblingDom) {
723
+ const [first, ...rest] = domChildren
724
+ parentDom.insertBefore(first, nextSiblingDom)
725
+ first.after(...rest)
726
+ } else {
727
+ parentDom.append(...domChildren)
798
728
  }
799
729
  }
730
+ currentHostNode.lastChild = domChildren[domChildren.length - 1]
731
+ }
800
732
 
801
- // Start collecting from the memo's children
802
- collectDomNodes(vNode.child)
803
-
804
- return domChildren
733
+ function collectDomNodes(firstChild: VNode, children: SomeDom[]): void {
734
+ let child: VNode | null = firstChild
735
+ while (child) {
736
+ if (child.dom) {
737
+ children.push(child.dom)
738
+ } else if (child.child) {
739
+ collectDomNodes(child.child, children)
740
+ }
741
+ child = child.sibling
742
+ }
805
743
  }
@@ -1,8 +1,9 @@
1
- import type { AppContext } from "./appContext"
2
1
  import { __DEV__ } from "./env.js"
3
2
  import { createHMRContext } from "./hmr.js"
4
3
  import { createProfilingContext } from "./profiling.js"
5
- import { Store } from "./store"
4
+ import type { AppContext } from "./appContext"
5
+ import type { Store } from "./store"
6
+ import type { SWRCache } from "./swr"
6
7
 
7
8
  export { createKiruGlobalContext, type GlobalKiruEvent, type KiruGlobalContext }
8
9
 
@@ -75,7 +76,7 @@ interface KiruGlobalContext {
75
76
  stores?: ReactiveMap<Store<any, any>>
76
77
  HMRContext?: ReturnType<typeof createHMRContext>
77
78
  profilingContext?: ReturnType<typeof createProfilingContext>
78
- globalState: Record<symbol, any>
79
+ SWRGlobalCache?: SWRCache
79
80
  emit<T extends Evt>(event: T["name"], ctx: AppContext, data?: T["data"]): void
80
81
  on<T extends Evt>(
81
82
  event: T["name"],
@@ -93,8 +94,6 @@ function createKiruGlobalContext(): KiruGlobalContext {
93
94
  GlobalKiruEvent,
94
95
  Set<(ctx: AppContext, data?: Evt["data"]) => void>
95
96
  >()
96
- const globalState: Record<symbol, any> = {}
97
-
98
97
  let stores: ReactiveMap<Store<any, any>> | undefined
99
98
  let HMRContext: ReturnType<typeof createHMRContext> | undefined
100
99
  let profilingContext: ReturnType<typeof createProfilingContext> | undefined
@@ -137,7 +136,6 @@ function createKiruGlobalContext(): KiruGlobalContext {
137
136
  get profilingContext() {
138
137
  return profilingContext
139
138
  },
140
- globalState,
141
139
  emit,
142
140
  on,
143
141
  off,
@@ -1,24 +1,9 @@
1
1
  import { __DEV__ } from "../env.js"
2
2
  import { noop } from "../utils.js"
3
3
  import { depsRequireChange, sideEffectsEnabled, useHook } from "./utils.js"
4
+ import type { AsyncTaskState } from "../types.utils.js"
4
5
 
5
- export type UseAsyncState<T> = (
6
- | /** loading*/ {
7
- data: null
8
- loading: true
9
- error: null
10
- }
11
- | /** loaded */ {
12
- data: T
13
- loading: false
14
- error: null
15
- }
16
- | /** error */ {
17
- data: null
18
- loading: false
19
- error: UseAsyncError
20
- }
21
- ) & {
6
+ export type UseAsyncState<T> = AsyncTaskState<T, UseAsyncError> & {
22
7
  invalidate: () => void
23
8
  }
24
9
 
@@ -34,7 +19,7 @@ export class UseAsyncError extends Error {
34
19
  }
35
20
  }
36
21
 
37
- type AsyncTaskState<T> = {
22
+ type InternalTaskState<T> = {
38
23
  data: T | null
39
24
  loading: boolean
40
25
  error: Error | null
@@ -62,10 +47,8 @@ export function useAsync<T>(
62
47
  {
63
48
  deps,
64
49
  id: 0,
65
- task: null as any as AsyncTaskState<T>,
66
- load: noop as (
67
- func: (ctx: UseAsyncCallbackContext) => Promise<T>
68
- ) => void,
50
+ task: null as any as InternalTaskState<T>,
51
+ load: noop as (func: (ctx: UseAsyncCallbackContext) => Promise<T>) => void,
69
52
  },
70
53
  ({ hook, isInit, isHMR, update }) => {
71
54
  if (__DEV__) {
@@ -83,7 +66,7 @@ export function useAsync<T>(
83
66
  invalidated = true
84
67
  })
85
68
  const id = ++hook.id
86
- const task: AsyncTaskState<T> = (hook.task = {
69
+ const task: InternalTaskState<T> = (hook.task = {
87
70
  abortController,
88
71
  data: null,
89
72
  loading: true,
@@ -130,7 +113,7 @@ export function useAsync<T>(
130
113
  )
131
114
  }
132
115
 
133
- function abortTask<T>(task: AsyncTaskState<T> | null): void {
116
+ function abortTask<T>(task: InternalTaskState<T> | null): void {
134
117
  if (task === null || task.abortController.signal.aborted) return
135
118
  task.abortController.abort()
136
119
  }
package/src/index.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { createKiruGlobalContext } from "./globalContext.js"
2
1
  import { __DEV__ } from "./env.js"
2
+ import { createKiruGlobalContext } from "./globalContext.js"
3
3
 
4
4
  export type * from "./types"
5
5
  export * from "./signals/index.js"
6
6
  export * from "./appContext.js"
7
- export * from "./context.js"
8
7
  export * from "./cloneVNode.js"
8
+ export * from "./context.js"
9
+ export * from "./customEvents.js"
9
10
  export * from "./element.js"
10
11
  export * from "./hooks/index.js"
11
12
  export * from "./lazy.js"
@@ -16,6 +17,8 @@ export { nextIdle, flushSync, requestUpdate } from "./scheduler.js"
16
17
  export * from "./store.js"
17
18
  export * from "./transition.js"
18
19
 
19
- if ("window" in globalThis) {
20
- globalThis.window.__kiru ??= createKiruGlobalContext()
20
+ if (__DEV__) {
21
+ if ("window" in globalThis) {
22
+ globalThis.window.__kiru ??= createKiruGlobalContext()
23
+ }
21
24
  }
package/src/lazy.ts CHANGED
@@ -14,13 +14,17 @@ import {
14
14
  import type { SomeDom } from "./types.utils"
15
15
  import { noop } from "./utils.js"
16
16
 
17
- type FCModule = { default: Kiru.FC<any> }
17
+ interface FCModule {
18
+ default: Kiru.FC<any>
19
+ }
20
+
18
21
  type LazyImportValue = Kiru.FC<any> | FCModule
22
+
19
23
  type InferLazyImportProps<T extends LazyImportValue> = T extends FCModule
20
24
  ? Kiru.InferProps<T["default"]>
21
25
  : Kiru.InferProps<T>
22
26
 
23
- type LazyState = {
27
+ interface LazyState {
24
28
  fn: string
25
29
  promise: Promise<LazyImportValue>
26
30
  result: Kiru.FC | null
package/src/portal.ts CHANGED
@@ -5,7 +5,7 @@ import { renderMode } from "./globals.js"
5
5
  import { useVNode } from "./hooks/utils.js"
6
6
  import { nextIdle, requestUpdate } from "./scheduler.js"
7
7
 
8
- type PortalProps = {
8
+ interface PortalProps {
9
9
  children?: JSX.Children
10
10
  container: HTMLElement | (() => HTMLElement)
11
11
  }
package/src/profiling.ts CHANGED
@@ -14,7 +14,7 @@ const ProfilingEvents = [
14
14
 
15
15
  export type ProfilingEvent = (typeof ProfilingEvents)[number]
16
16
 
17
- type TickTS = {
17
+ interface TickTS {
18
18
  start: number
19
19
  end: number
20
20
  }