Comparing version 0.0.23 to 0.0.24
@@ -23,2 +23,3 @@ export declare type ForgoRef<T> = { | ||
error?: (props: TProps, args: ForgoErrorArgs) => ForgoElement<ForgoComponentCtor<TProps>, TProps>; | ||
mount?: (props: TProps, args: ForgoRenderArgs) => void; | ||
unmount?: (props: TProps, args: ForgoRenderArgs) => void; | ||
@@ -25,0 +26,0 @@ shouldUpdate?: (newProps: TProps, oldProps: TProps) => boolean; |
@@ -61,12 +61,21 @@ "use strict"; | ||
const textNode = env.document.createTextNode(text); | ||
attachProps(text, textNode, pendingAttachStates); | ||
if (node) { | ||
// If there are old component states, we might need to unmount some of em. | ||
// After comparing with the new states. | ||
// We have to get oldStates before attachProps; | ||
// coz attachProps will overwrite with new states. | ||
const oldComponentStates = (_a = getForgoState(node)) === null || _a === void 0 ? void 0 : _a.components; | ||
attachProps(text, textNode, pendingAttachStates); | ||
if (oldComponentStates) { | ||
unloadIncompatibleStates(pendingAttachStates, oldComponentStates); | ||
const indexOfFirstIncompatibleState = findIndexOfFirstIncompatibleState(pendingAttachStates, oldComponentStates); | ||
unmountComponents(oldComponentStates, indexOfFirstIncompatibleState); | ||
mountComponents(pendingAttachStates, indexOfFirstIncompatibleState); | ||
} | ||
else { | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
node.replaceWith(textNode); | ||
} | ||
else { | ||
attachProps(text, textNode, pendingAttachStates); | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
return { node: textNode }; | ||
@@ -90,8 +99,2 @@ } | ||
let nodeToBindTo; | ||
// If there are old component states, we might need to unmount some of em. | ||
// After comparing with the new states. | ||
const oldComponentStates = (_a = getForgoState(node)) === null || _a === void 0 ? void 0 : _a.components; | ||
if (oldComponentStates) { | ||
unloadIncompatibleStates(pendingAttachStates, oldComponentStates); | ||
} | ||
// if the nodes are not of the same of the same type, we need to replace. | ||
@@ -108,8 +111,19 @@ if (node.nodeType === TEXT_NODE_TYPE || | ||
} | ||
// We have to get oldStates before attachProps; | ||
// coz attachProps will overwrite with new states. | ||
const oldComponentStates = (_a = getForgoState(node)) === null || _a === void 0 ? void 0 : _a.components; | ||
attachProps(forgoElement, nodeToBindTo, pendingAttachStates); | ||
if (oldComponentStates) { | ||
const indexOfFirstIncompatibleState = findIndexOfFirstIncompatibleState(pendingAttachStates, oldComponentStates); | ||
unmountComponents(oldComponentStates, indexOfFirstIncompatibleState); | ||
mountComponents(pendingAttachStates, indexOfFirstIncompatibleState); | ||
} | ||
else { | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
renderChildNodes(forgoElement, nodeToBindTo, fullRerender, boundary); | ||
return { node: nodeToBindTo }; | ||
} | ||
// There was no node passed in; have to create a new element. | ||
else { | ||
// There was no node passed in, so create a new element. | ||
const newElement = env.document.createElement(forgoElement.type); | ||
@@ -120,2 +134,3 @@ if (forgoElement.props.ref) { | ||
attachProps(forgoElement, newElement, pendingAttachStates); | ||
mountComponents(pendingAttachStates, 0); | ||
renderChildNodes(forgoElement, newElement, fullRerender, boundary); | ||
@@ -263,3 +278,8 @@ return { node: newElement }; | ||
const { node } = internalRender(stringOfPrimitiveNode(forgoChild), undefined, [], fullRerender, boundary); | ||
parentElement.insertBefore(node, childNodes[forgoChildIndex]); | ||
if (childNodes.length > forgoChildIndex) { | ||
parentElement.insertBefore(node, childNodes[forgoChildIndex]); | ||
} | ||
else { | ||
parentElement.appendChild(node); | ||
} | ||
} | ||
@@ -273,3 +293,4 @@ } | ||
for (let i = forgoChildIndex; i < findResult.index; i++) { | ||
unloadNode(childNodes[i]); | ||
const nodesToRemove = Array.from(childNodes).slice(forgoChildIndex, findResult.index); | ||
unloadNodes(nodesToRemove); | ||
} | ||
@@ -292,5 +313,4 @@ internalRender(forgoChild, childNodes[forgoChildIndex], [], fullRerender); | ||
// Everything after forgoChildIndex must go. | ||
for (let i = forgoChildIndex; i < childNodes.length; i++) { | ||
unloadNode(childNodes[i]); | ||
} | ||
const nodesToRemove = Array.from(childNodes).slice(forgoChildIndex); | ||
unloadNodes(nodesToRemove); | ||
} | ||
@@ -303,10 +323,8 @@ /* | ||
*/ | ||
function unloadNode(node) { | ||
node.remove(); | ||
const state = getForgoState(node); | ||
if (state) { | ||
for (const componentState of state.components) { | ||
if (componentState.component.unmount) { | ||
componentState.component.unmount(componentState.props, componentState.args); | ||
} | ||
function unloadNodes(nodes) { | ||
for (const node of nodes) { | ||
node.remove(); | ||
const state = getForgoState(node); | ||
if (state) { | ||
unmountComponents(state.components, 0); | ||
} | ||
@@ -324,3 +342,3 @@ } | ||
*/ | ||
function unloadIncompatibleStates(newStates, oldStates) { | ||
function findIndexOfFirstIncompatibleState(newStates, oldStates) { | ||
let i = 0; | ||
@@ -339,9 +357,20 @@ for (const newState of newStates) { | ||
} | ||
for (let j = i; j < oldStates.length; j++) { | ||
const oldState = oldStates[j]; | ||
if (oldState.component.unmount) { | ||
oldState.component.unmount(oldState.props, oldState.args); | ||
return i; | ||
} | ||
function mountComponents(states, from) { | ||
for (let j = from; j < states.length; j++) { | ||
const state = states[j]; | ||
if (state.component.mount) { | ||
state.component.mount(state.props, state.args); | ||
} | ||
} | ||
} | ||
function unmountComponents(states, from) { | ||
for (let j = from; j < states.length; j++) { | ||
const state = states[j]; | ||
if (state.component.unmount) { | ||
state.component.unmount(state.props, state.args); | ||
} | ||
} | ||
} | ||
/* | ||
@@ -348,0 +377,0 @@ When we try to find replacement candidates for DOM nodes, |
{ | ||
"name": "forgo", | ||
"version": "0.0.23", | ||
"version": "0.0.24", | ||
"main": "./dist", | ||
@@ -5,0 +5,0 @@ "author": "Jeswin Kumar<jeswinpk@agilehead.com>", |
@@ -120,3 +120,3 @@ # forgo | ||
## Unmount | ||
## Component Unmount | ||
@@ -138,2 +138,19 @@ When a component is unmounted, Forgo will invoke the unmount() function if defined for a component. It receives the current props and args as arguments, just as in the render() function. | ||
## Component mount | ||
You'd rarely have to use this. mount() gets called with the same arguments as render () but after getting mounted on a real DOM node. At this point you can expect args.element.node to be populated, where args is the second parameter to mount() and render(). | ||
```jsx | ||
function Greeter(props) { | ||
return { | ||
render(props, args) { | ||
return <div id="hello">Hello {props.firstName}</div>; | ||
}, | ||
mount(props, args) { | ||
console.log(`Mounted on node with id ${args.element.node.id}`); | ||
}, | ||
}; | ||
} | ||
``` | ||
## Bailing out of a render | ||
@@ -140,0 +157,0 @@ |
118
src/index.ts
@@ -52,2 +52,3 @@ /* | ||
) => ForgoElement<ForgoComponentCtor<TProps>, TProps>; | ||
mount?: (props: TProps, args: ForgoRenderArgs) => void; | ||
unmount?: (props: TProps, args: ForgoRenderArgs) => void; | ||
@@ -213,13 +214,27 @@ shouldUpdate?: (newProps: TProps, oldProps: TProps) => boolean; | ||
const textNode = env.document.createTextNode(text); | ||
attachProps(text, textNode, pendingAttachStates); | ||
if (node) { | ||
// If there are old component states, we might need to unmount some of em. | ||
// After comparing with the new states. | ||
// We have to get oldStates before attachProps; | ||
// coz attachProps will overwrite with new states. | ||
const oldComponentStates = getForgoState(node)?.components; | ||
attachProps(text, textNode, pendingAttachStates); | ||
if (oldComponentStates) { | ||
unloadIncompatibleStates(pendingAttachStates, oldComponentStates); | ||
const indexOfFirstIncompatibleState = findIndexOfFirstIncompatibleState( | ||
pendingAttachStates, | ||
oldComponentStates | ||
); | ||
unmountComponents(oldComponentStates, indexOfFirstIncompatibleState); | ||
mountComponents(pendingAttachStates, indexOfFirstIncompatibleState); | ||
} else { | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
node.replaceWith(textNode); | ||
} else { | ||
attachProps(text, textNode, pendingAttachStates); | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
return { node: textNode }; | ||
@@ -250,9 +265,2 @@ } | ||
// If there are old component states, we might need to unmount some of em. | ||
// After comparing with the new states. | ||
const oldComponentStates = getForgoState(node)?.components; | ||
if (oldComponentStates) { | ||
unloadIncompatibleStates(pendingAttachStates, oldComponentStates); | ||
} | ||
// if the nodes are not of the same of the same type, we need to replace. | ||
@@ -270,4 +278,20 @@ if ( | ||
} | ||
// We have to get oldStates before attachProps; | ||
// coz attachProps will overwrite with new states. | ||
const oldComponentStates = getForgoState(node)?.components; | ||
attachProps(forgoElement, nodeToBindTo, pendingAttachStates); | ||
if (oldComponentStates) { | ||
const indexOfFirstIncompatibleState = findIndexOfFirstIncompatibleState( | ||
pendingAttachStates, | ||
oldComponentStates | ||
); | ||
unmountComponents(oldComponentStates, indexOfFirstIncompatibleState); | ||
mountComponents(pendingAttachStates, indexOfFirstIncompatibleState); | ||
} else { | ||
mountComponents(pendingAttachStates, 0); | ||
} | ||
renderChildNodes( | ||
@@ -280,4 +304,5 @@ forgoElement, | ||
return { node: nodeToBindTo }; | ||
} else { | ||
// There was no node passed in, so create a new element. | ||
} | ||
// There was no node passed in; have to create a new element. | ||
else { | ||
const newElement = env.document.createElement(forgoElement.type); | ||
@@ -288,2 +313,3 @@ if (forgoElement.props.ref) { | ||
attachProps(forgoElement, newElement, pendingAttachStates); | ||
mountComponents(pendingAttachStates, 0); | ||
renderChildNodes(forgoElement, newElement, fullRerender, boundary); | ||
@@ -545,3 +571,8 @@ return { node: newElement }; | ||
); | ||
parentElement.insertBefore(node, childNodes[forgoChildIndex]); | ||
if (childNodes.length > forgoChildIndex) { | ||
parentElement.insertBefore(node, childNodes[forgoChildIndex]); | ||
} else { | ||
parentElement.appendChild(node); | ||
} | ||
} | ||
@@ -564,3 +595,7 @@ } else { | ||
for (let i = forgoChildIndex; i < findResult.index; i++) { | ||
unloadNode(childNodes[i]); | ||
const nodesToRemove = Array.from(childNodes).slice( | ||
forgoChildIndex, | ||
findResult.index | ||
); | ||
unloadNodes(nodesToRemove); | ||
} | ||
@@ -591,5 +626,4 @@ internalRender( | ||
// Everything after forgoChildIndex must go. | ||
for (let i = forgoChildIndex; i < childNodes.length; i++) { | ||
unloadNode(childNodes[i]); | ||
} | ||
const nodesToRemove = Array.from(childNodes).slice(forgoChildIndex); | ||
unloadNodes(nodesToRemove); | ||
} | ||
@@ -603,13 +637,8 @@ | ||
*/ | ||
function unloadNode(node: ChildNode) { | ||
node.remove(); | ||
const state = getForgoState(node); | ||
if (state) { | ||
for (const componentState of state.components) { | ||
if (componentState.component.unmount) { | ||
componentState.component.unmount( | ||
componentState.props, | ||
componentState.args | ||
); | ||
} | ||
function unloadNodes(nodes: ChildNode[]) { | ||
for (const node of nodes) { | ||
node.remove(); | ||
const state = getForgoState(node); | ||
if (state) { | ||
unmountComponents(state.components, 0); | ||
} | ||
@@ -628,6 +657,6 @@ } | ||
*/ | ||
function unloadIncompatibleStates( | ||
function findIndexOfFirstIncompatibleState( | ||
newStates: NodeAttachedComponentState<any>[], | ||
oldStates: NodeAttachedComponentState<any>[] | ||
) { | ||
): number { | ||
let i = 0; | ||
@@ -647,6 +676,13 @@ | ||
for (let j = i; j < oldStates.length; j++) { | ||
const oldState = oldStates[j]; | ||
if (oldState.component.unmount) { | ||
oldState.component.unmount(oldState.props, oldState.args); | ||
return i; | ||
} | ||
function mountComponents( | ||
states: NodeAttachedComponentState<any>[], | ||
from: number | ||
) { | ||
for (let j = from; j < states.length; j++) { | ||
const state = states[j]; | ||
if (state.component.mount) { | ||
state.component.mount(state.props, state.args); | ||
} | ||
@@ -656,2 +692,14 @@ } | ||
function unmountComponents( | ||
states: NodeAttachedComponentState<any>[], | ||
from: number | ||
) { | ||
for (let j = from; j < states.length; j++) { | ||
const state = states[j]; | ||
if (state.component.unmount) { | ||
state.component.unmount(state.props, state.args); | ||
} | ||
} | ||
} | ||
type CandidateSearchResult = | ||
@@ -658,0 +706,0 @@ | { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
86510
1480
403