Skip to content

Commit

Permalink
feature: add onref, onunref
Browse files Browse the repository at this point in the history
  • Loading branch information
stagas committed Jul 30, 2022
1 parent 1f6d4fc commit 4298f01
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions src/jsx-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ declare global {
*/
key?: string | number

/**
* Custom hook for when element is created.
*/
onref?: (el: any) => (() => void) | void

/**
* Custom hook for when element is removed.
*/
onunref?: (el: any) => (() => void) | void

/**
* Children.
* @private
Expand Down Expand Up @@ -90,6 +100,7 @@ type VNode<T extends string | symbol | typeof Text | typeof Comment | VFn> = {
key?: string
hook?: Hook
keep?: boolean
onunref?: () => void
}

const anchor = new Comment()
Expand Down Expand Up @@ -132,7 +143,10 @@ class Chunk extends Array {
this.dom = [...this]
}
remove() {
this.dom.forEach(el => el.remove())
this.dom.forEach(el => {
;(el as any).onunref?.()
el.remove()
})
this.splice(0)
}
removeChild(x: any) {
Expand Down Expand Up @@ -193,6 +207,7 @@ const reconcile = (parent: TargetEl, nk: VKids, pk: VKids | VKid, doc: Doc) => {
}
for (const pel of pk.dom!) {
if (!keep.has(pel)) {
;(pel as any).onunref?.()
if (parent instanceof Chunk) parent.removeChild(pel)
pel.remove()
;(pk.mapped!.get(pel) as VNode<VFn>)?.hook?.onremove?.()
Expand All @@ -217,6 +232,20 @@ const reconcile = (parent: TargetEl, nk: VKids, pk: VKids | VKid, doc: Doc) => {
nk.running = false
}

// scheduling to prevent triggering ref effects before this render finishes
// TODO: has to be put in a proper queue instead of relying on the microtask
const mount = (el: DomEl & { ref: VRef<any>; onref: any; onunref?: any }) => {
queueMicrotask(() => {
if (el?.ref && el !== el.ref.current) {
el.ref.current = el
}
if (el?.onref) {
el.onunref = el.onref(el)
}
})
return el
}

const diff = (parent: TargetEl, n: DomEl[], p: DomEl[], i = 0, len = n.length, el?: DomEl, last?: DomEl) => {
if (parent instanceof Chunk) {
// parent.splice(0) // , parent.length, ...n)
Expand Down Expand Up @@ -287,10 +316,7 @@ const create = (doc: Doc, n: VKid, p?: VKid, pel?: El | null) => {
if (n.kind === 'foreignObject') doc = html
// render children
render(n.props.children, el, doc)
// scheduling to prevent triggering ref effects before this render finishes
// TODO: has to be put in a proper queue instead of relying on the microtask
if ('ref' in n.props && el !== n.props.ref.current)
queueMicrotask(() => n.props.ref.current = el)
mount(el as any)
} else {
let initial = true
if (!((el = pel!) && (n.hook = (p as VNode<VFn>)?.hook))) {
Expand Down

0 comments on commit 4298f01

Please sign in to comment.