🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

hydro-js

Package Overview
Dependencies
Maintainers
1
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hydro-js - npm Package Compare versions

Comparing version

to
1.4.0

6

CHANGELOG.md
# Changelog
## 1.4.0- 2021-05-06
- Refactor h function. Breaking Change: Does not really support SVG anymore. Use html function for this case.
- Performance improvements
- Add non-keyed solution and default to it
## 1.3.5- 2021-05-03

@@ -4,0 +10,0 @@

147

dist/library.cjs.js

@@ -19,2 +19,3 @@ // Safari Polyfills

const bindMap = new WeakMap(); // Bind an Element to Data. If the Data is being unset, the DOM Element disappears too.
const tmpSwap = new WeakMap(); // Take over keyToNodeMap if new value is a hydro Proxy. Save old reactivityMap entry here, in case for a swap operation. [if reuseElements]
const onRenderMap = new WeakMap(); // Lifecycle Hook that is being called after rendering

@@ -28,2 +29,3 @@ const onCleanupMap = new WeakMap(); // Lifecycle Hook that is being called when unmount function is being called

let shouldSetReactivity = true;
let viewElements = false;
const reactivityRegex = /\{\{((\s|.)*?)\}\}/;

@@ -177,3 +179,20 @@ const HTML_FIND_INVALID = /<(\/?)(html|head|body)(>|\s.*?>)/g;

const DOM = parser(DOMString);
const root = document.createNodeIterator(DOM, NodeFilter.SHOW_ELEMENT, {
// Delay Elemen iteration and manipulation after the elements have been added to the DOM.
if (viewElements) {
onRender(fillDOM, DOM.firstChild, DOM.firstChild, insertNodes, eventFunctions);
}
else {
fillDOM(DOM, insertNodes, eventFunctions);
}
// Return DocumentFragment
if (DOM.childNodes.length > 1)
return DOM;
// Return Text Node
if (!DOM.firstChild)
return document.createTextNode("");
// Return Element
return DOM.firstChild;
}
function fillDOM(elem, insertNodes, eventFunctions) {
const root = document.createNodeIterator(elem, NodeFilter.SHOW_ELEMENT, {
acceptNode(element) {

@@ -185,23 +204,18 @@ return element.localName.endsWith("-dummy" /* dummy */)

});
let elem;
while ((elem = root.nextNode())) {
const tag = elem.localName.replace("-dummy" /* dummy */, "");
let nextNode;
while ((nextNode = root.nextNode())) {
const tag = nextNode.localName.replace("-dummy" /* dummy */, "");
const replacement = document.createElement(tag);
//@ts-ignore
replacement.append(...elem.childNodes);
elem.replaceWith(replacement);
replacement.append(...nextNode.childNodes);
nextNode.replaceWith(replacement);
}
// Insert HTML Elements, which were stored in insertNodes
DOM.querySelectorAll("template[id^=lbInsertNodes]").forEach((template) => template.replaceWith(insertNodes.shift()));
elem
.querySelectorAll("template[id^=lbInsertNodes]")
.forEach((template) => template.replaceWith(insertNodes.shift()));
if (shouldSetReactivity)
setReactivity(DOM, eventFunctions);
// Return DocumentFragment
if (DOM.childNodes.length > 1)
return DOM;
// Return Text Node
if (!DOM.firstChild)
return document.createTextNode("");
// Return Element
return DOM.firstChild;
setReactivity(elem, eventFunctions);
}
/* c8 ignore start */
function h(name, props, ...children) {

@@ -211,8 +225,14 @@ if (isFunction(name))

const flatChildren = children
.map((child) =>
/* c8 ignore next 1 */
isObject(child) && !isNode(child) ? Object.values(child) : child)
.map((child) => isObject(child) && !isNode(child) ? Object.values(child) : child)
.flat();
return html `<${name} ${props || {}}>${flatChildren}</${name}>`;
const elem = document.createElement(name);
for (let i in props) {
//@ts-ignore
i in elem ? (elem[i] = props[i]) : setAttribute(elem, i, props[i]);
}
elem.append(...flatChildren);
onRender(setReactivity, elem, elem);
return elem;
}
/* c8 ignore end */
function setReactivity(DOM, eventFunctions) {

@@ -569,6 +589,9 @@ // Set events and reactive behaviour(checks for {{ key }} where key is on hydro)

const fn = lifecyleMap.get(node);
/* c8 ignore next 3 */
if (globalSchedule) {
if (viewElements) {
schedule(fn);
/* c8 ignore next 3 */
}
else if (globalSchedule) {
window.requestIdleCallback(fn);
}
else {

@@ -948,2 +971,3 @@ fn();

// Remove item from array
/* c8 ignore next 4 */
if (!internReset && Array.isArray(receiver)) {

@@ -967,4 +991,5 @@ receiver.splice(key, 1);

let subItem = receiver[key][i];
/* c8 ignore next 3 */
if (isObject(subItem) && isProxy(subItem)) {
subItem = null;
receiver[key][i] = null;
}

@@ -1002,5 +1027,7 @@ }

else {
if (Array.isArray(receiver) &&
if (!reuseElements &&
Array.isArray(receiver) &&
receiver.includes(oldVal) &&
receiver.includes(val) &&
/* c8 ignore start */
bindMap.has(val)) {

@@ -1023,2 +1050,3 @@ const [elem] = bindMap.get(val);

else {
/* c8 ignore end */
returnSet = Reflect.set(target, key, val, receiver);

@@ -1039,3 +1067,11 @@ }

if (reactivityMap.has(oldVal)) {
reactivityMap.set(oldVal, reactivityMap.get(val));
// Store old reactivityMap if it is a swap operation
reuseElements && tmpSwap.set(oldVal, reactivityMap.get(oldVal));
if (tmpSwap.has(val)) {
reactivityMap.set(oldVal, tmpSwap.get(val));
tmpSwap.delete(val);
}
else {
reactivityMap.set(oldVal, reactivityMap.get(val));
}
}

@@ -1050,3 +1086,3 @@ }

// If oldVal is a Proxy - clean it
schedule(cleanProxy, oldVal);
!reuseElements && cleanProxy(oldVal);
return returnSet;

@@ -1116,2 +1152,3 @@ },

}
/* c8 ignore next 3 */
}

@@ -1136,2 +1173,3 @@ else {

reactivityMap.delete(proxy);
/* c8 ignore next 4 */
if (bindMap.has(proxy)) {

@@ -1262,31 +1300,40 @@ bindMap.get(proxy).forEach(removeElement);

}
function template(elem, placeholders, events) {
let wrapper = elem.content.cloneNode(true).firstChild;
let innerHTML = wrapper.innerHTML;
for (const [key, value] of Object.entries(placeholders)) {
innerHTML = innerHTML.replace(key, String(value));
}
wrapper.innerHTML = innerHTML;
setReactivity(wrapper.firstChild, events);
return wrapper.firstChild;
}
function view(root, data, renderFunction) {
getValue(data).forEach((item, i) => {
const elem = renderFunction(item, i);
$(root).appendChild(elem);
});
viewElements = true;
const rootElem = $(root);
const elements = getValue(data).map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem, onRenderMap));
viewElements = false;
observe(data, (newData, oldData) => {
const rootElem = $(root);
if (!newData?.length || oldData?.[0] !== newData?.[0]) {
rootElem.innerHTML = "";
/* c8 ignore start */
viewElements = true;
// Reset or re-use
if (!newData?.length ||
(!reuseElements && newData?.length === oldData?.length)) {
rootElem.textContent = "";
}
else if (reuseElements) {
for (let i = 0; i < oldData?.length && newData?.length; i++) {
oldData[i].id = newData[i].id;
oldData[i].label = newData[i].label;
newData[i] = oldData[i];
}
}
// Add to existing
if (oldData?.length && newData?.length > oldData?.length) {
rootElem.append(...newData.slice(oldData.length).map(renderFunction));
const length = oldData.length;
const slicedData = newData.slice(length);
const newElements = slicedData.map((item, i) => renderFunction(item, i + length));
rootElem.append(...newElements);
newElements.forEach((elem) => runLifecyle(elem, onRenderMap));
}
else {
newData?.forEach((item, i) => {
const elem = renderFunction(item, i);
rootElem.insertBefore(elem, null);
});
// Add new
else if (oldData?.length === 0 || (!reuseElements && newData?.length)) {
const elements = newData.map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem, onRenderMap));
}
viewElements = false;
/* c8 ignore end */
});

@@ -1300,2 +1347,2 @@ }

};
module.exports = { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, template, view, };
module.exports = { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, view, };

@@ -67,3 +67,2 @@ declare global {

declare function onCleanup(fn: Function, elem: ReturnType<typeof html>, ...args: Array<any>): void;
declare function template(elem: HTMLTemplateElement, placeholders: Record<string, any>, events: Record<string, any>): Element;
declare function view(root: string, data: reactiveObject<Array<any>>, renderFunction: (value: any, index: number) => Node): void;

@@ -84,2 +83,2 @@ declare const hydro: hydroObject;

};
export { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, template, view, };
export { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, view, };

@@ -19,2 +19,3 @@ // Safari Polyfills

const bindMap = new WeakMap(); // Bind an Element to Data. If the Data is being unset, the DOM Element disappears too.
const tmpSwap = new WeakMap(); // Take over keyToNodeMap if new value is a hydro Proxy. Save old reactivityMap entry here, in case for a swap operation. [if reuseElements]
const onRenderMap = new WeakMap(); // Lifecycle Hook that is being called after rendering

@@ -28,2 +29,3 @@ const onCleanupMap = new WeakMap(); // Lifecycle Hook that is being called when unmount function is being called

let shouldSetReactivity = true;
let viewElements = false;
const reactivityRegex = /\{\{((\s|.)*?)\}\}/;

@@ -177,3 +179,20 @@ const HTML_FIND_INVALID = /<(\/?)(html|head|body)(>|\s.*?>)/g;

const DOM = parser(DOMString);
const root = document.createNodeIterator(DOM, NodeFilter.SHOW_ELEMENT, {
// Delay Elemen iteration and manipulation after the elements have been added to the DOM.
if (viewElements) {
onRender(fillDOM, DOM.firstChild, DOM.firstChild, insertNodes, eventFunctions);
}
else {
fillDOM(DOM, insertNodes, eventFunctions);
}
// Return DocumentFragment
if (DOM.childNodes.length > 1)
return DOM;
// Return Text Node
if (!DOM.firstChild)
return document.createTextNode("");
// Return Element
return DOM.firstChild;
}
function fillDOM(elem, insertNodes, eventFunctions) {
const root = document.createNodeIterator(elem, NodeFilter.SHOW_ELEMENT, {
acceptNode(element) {

@@ -185,23 +204,18 @@ return element.localName.endsWith("-dummy" /* dummy */)

});
let elem;
while ((elem = root.nextNode())) {
const tag = elem.localName.replace("-dummy" /* dummy */, "");
let nextNode;
while ((nextNode = root.nextNode())) {
const tag = nextNode.localName.replace("-dummy" /* dummy */, "");
const replacement = document.createElement(tag);
//@ts-ignore
replacement.append(...elem.childNodes);
elem.replaceWith(replacement);
replacement.append(...nextNode.childNodes);
nextNode.replaceWith(replacement);
}
// Insert HTML Elements, which were stored in insertNodes
DOM.querySelectorAll("template[id^=lbInsertNodes]").forEach((template) => template.replaceWith(insertNodes.shift()));
elem
.querySelectorAll("template[id^=lbInsertNodes]")
.forEach((template) => template.replaceWith(insertNodes.shift()));
if (shouldSetReactivity)
setReactivity(DOM, eventFunctions);
// Return DocumentFragment
if (DOM.childNodes.length > 1)
return DOM;
// Return Text Node
if (!DOM.firstChild)
return document.createTextNode("");
// Return Element
return DOM.firstChild;
setReactivity(elem, eventFunctions);
}
/* c8 ignore start */
function h(name, props, ...children) {

@@ -211,8 +225,14 @@ if (isFunction(name))

const flatChildren = children
.map((child) =>
/* c8 ignore next 1 */
isObject(child) && !isNode(child) ? Object.values(child) : child)
.map((child) => isObject(child) && !isNode(child) ? Object.values(child) : child)
.flat();
return html `<${name} ${props || {}}>${flatChildren}</${name}>`;
const elem = document.createElement(name);
for (let i in props) {
//@ts-ignore
i in elem ? (elem[i] = props[i]) : setAttribute(elem, i, props[i]);
}
elem.append(...flatChildren);
onRender(setReactivity, elem, elem);
return elem;
}
/* c8 ignore end */
function setReactivity(DOM, eventFunctions) {

@@ -569,6 +589,9 @@ // Set events and reactive behaviour(checks for {{ key }} where key is on hydro)

const fn = lifecyleMap.get(node);
/* c8 ignore next 3 */
if (globalSchedule) {
if (viewElements) {
schedule(fn);
/* c8 ignore next 3 */
}
else if (globalSchedule) {
window.requestIdleCallback(fn);
}
else {

@@ -948,2 +971,3 @@ fn();

// Remove item from array
/* c8 ignore next 4 */
if (!internReset && Array.isArray(receiver)) {

@@ -967,4 +991,5 @@ receiver.splice(key, 1);

let subItem = receiver[key][i];
/* c8 ignore next 3 */
if (isObject(subItem) && isProxy(subItem)) {
subItem = null;
receiver[key][i] = null;
}

@@ -1002,5 +1027,7 @@ }

else {
if (Array.isArray(receiver) &&
if (!reuseElements &&
Array.isArray(receiver) &&
receiver.includes(oldVal) &&
receiver.includes(val) &&
/* c8 ignore start */
bindMap.has(val)) {

@@ -1023,2 +1050,3 @@ const [elem] = bindMap.get(val);

else {
/* c8 ignore end */
returnSet = Reflect.set(target, key, val, receiver);

@@ -1039,3 +1067,11 @@ }

if (reactivityMap.has(oldVal)) {
reactivityMap.set(oldVal, reactivityMap.get(val));
// Store old reactivityMap if it is a swap operation
reuseElements && tmpSwap.set(oldVal, reactivityMap.get(oldVal));
if (tmpSwap.has(val)) {
reactivityMap.set(oldVal, tmpSwap.get(val));
tmpSwap.delete(val);
}
else {
reactivityMap.set(oldVal, reactivityMap.get(val));
}
}

@@ -1050,3 +1086,3 @@ }

// If oldVal is a Proxy - clean it
schedule(cleanProxy, oldVal);
!reuseElements && cleanProxy(oldVal);
return returnSet;

@@ -1116,2 +1152,3 @@ },

}
/* c8 ignore next 3 */
}

@@ -1136,2 +1173,3 @@ else {

reactivityMap.delete(proxy);
/* c8 ignore next 4 */
if (bindMap.has(proxy)) {

@@ -1262,31 +1300,40 @@ bindMap.get(proxy).forEach(removeElement);

}
function template(elem, placeholders, events) {
let wrapper = elem.content.cloneNode(true).firstChild;
let innerHTML = wrapper.innerHTML;
for (const [key, value] of Object.entries(placeholders)) {
innerHTML = innerHTML.replace(key, String(value));
}
wrapper.innerHTML = innerHTML;
setReactivity(wrapper.firstChild, events);
return wrapper.firstChild;
}
function view(root, data, renderFunction) {
getValue(data).forEach((item, i) => {
const elem = renderFunction(item, i);
$(root).appendChild(elem);
});
viewElements = true;
const rootElem = $(root);
const elements = getValue(data).map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem, onRenderMap));
viewElements = false;
observe(data, (newData, oldData) => {
const rootElem = $(root);
if (!newData?.length || oldData?.[0] !== newData?.[0]) {
rootElem.innerHTML = "";
/* c8 ignore start */
viewElements = true;
// Reset or re-use
if (!newData?.length ||
(!reuseElements && newData?.length === oldData?.length)) {
rootElem.textContent = "";
}
else if (reuseElements) {
for (let i = 0; i < oldData?.length && newData?.length; i++) {
oldData[i].id = newData[i].id;
oldData[i].label = newData[i].label;
newData[i] = oldData[i];
}
}
// Add to existing
if (oldData?.length && newData?.length > oldData?.length) {
rootElem.append(...newData.slice(oldData.length).map(renderFunction));
const length = oldData.length;
const slicedData = newData.slice(length);
const newElements = slicedData.map((item, i) => renderFunction(item, i + length));
rootElem.append(...newElements);
newElements.forEach((elem) => runLifecyle(elem, onRenderMap));
}
else {
newData?.forEach((item, i) => {
const elem = renderFunction(item, i);
rootElem.insertBefore(elem, null);
});
// Add new
else if (oldData?.length === 0 || (!reuseElements && newData?.length)) {
const elements = newData.map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem, onRenderMap));
}
viewElements = false;
/* c8 ignore end */
});

@@ -1300,2 +1347,2 @@ }

};
export { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, template, view, };
export { render, html, h, hydro, setGlobalSchedule, setReuseElements, setInsertDiffing, setShouldSetReactivity, reactive, unset, setAsyncUpdate, unobserve, observe, ternary, emit, watchEffect, internals, getValue, onRender, onCleanup, setReactivity, $, $$, view, };
{
"name": "hydro-js",
"version": "1.3.5",
"version": "1.4.0",
"description": "A lightweight reactive library",

@@ -33,3 +33,3 @@ "type": "module",

"@types/concurrently": "^6.0.1",
"@web/test-runner": "^0.13.3",
"@web/test-runner": "^0.13.4",
"@web/test-runner-playwright": "^0.8.5",

@@ -36,0 +36,0 @@ "concurrently": "^6.0.2",

@@ -1,6 +0,6 @@

<img align="right" alt="97% Coverage" src="coverage.svg">
<img align="right" alt="100% Coverage" src="coverage.svg">
# hydro-js
> A lightweight (~4.5K <em>compressed</em>) reactive UI library via template literal tags.<br> Support in all modern Browsers.
> A lightweight (below 5K <em>compressed</em>) reactive UI library via template literal tags.<br> Support in all modern Browsers.

@@ -300,2 +300,19 @@ ## Installation

### view
Render the elements whenever the data changes. It will handle the operation for deletion, addition, swapping etc. This defaults to a non-keyed solution but it can be changed by calling `setReuseElements` with false.
args:
- root: `string` (CSS selector)<br>
- data: `ReturnType<typeof reactive>`<br>
- renderFunction: `function`, args: item: `any`, i: `number`<br>
#### Example
```js
const data = reactive([{ id: 4, label: "Red Onions" }])
view('.table', data, (item, i) => <tr>Reactive: {data[i].id}, Non-reactive: {item.id}<tr>)
```
### emit

@@ -302,0 +319,0 @@

@@ -101,2 +101,3 @@ declare const window: any;

const bindMap = new WeakMap<hydroObject, Array<Element>>(); // Bind an Element to Data. If the Data is being unset, the DOM Element disappears too.
const tmpSwap = new WeakMap<hydroObject, keyToNodeMap>(); // Take over keyToNodeMap if new value is a hydro Proxy. Save old reactivityMap entry here, in case for a swap operation. [if reuseElements]
const onRenderMap = new WeakMap<ReturnType<typeof html>, Function>(); // Lifecycle Hook that is being called after rendering

@@ -111,2 +112,3 @@ const onCleanupMap = new WeakMap<ReturnType<typeof html>, Function>(); // Lifecycle Hook that is being called when unmount function is being called

let shouldSetReactivity = true;
let viewElements = false;

@@ -285,3 +287,30 @@ const reactivityRegex = /\{\{((\s|.)*?)\}\}/;

const root = document.createNodeIterator(DOM, NodeFilter.SHOW_ELEMENT, {
// Delay Elemen iteration and manipulation after the elements have been added to the DOM.
if (viewElements) {
onRender(
fillDOM,
DOM.firstChild as Element,
DOM.firstChild,
insertNodes,
eventFunctions
);
} else {
fillDOM(DOM, insertNodes, eventFunctions);
}
// Return DocumentFragment
if (DOM.childNodes.length > 1) return DOM;
// Return Text Node
if (!DOM.firstChild) return document.createTextNode("");
// Return Element
return DOM.firstChild as Element;
}
function fillDOM(
elem: DocumentFragment | Element,
insertNodes: Node[],
eventFunctions: eventFunctions
) {
const root = document.createNodeIterator(elem, NodeFilter.SHOW_ELEMENT, {
acceptNode(element: Element) {

@@ -293,28 +322,20 @@ return element.localName.endsWith(Placeholder.dummy)

});
let elem;
while ((elem = root.nextNode())) {
const tag = (elem as Element).localName.replace(Placeholder.dummy, "");
let nextNode;
while ((nextNode = root.nextNode())) {
const tag = (nextNode as Element).localName.replace(Placeholder.dummy, "");
const replacement = document.createElement(tag);
//@ts-ignore
replacement.append(...(elem as Element).childNodes);
(elem as Element).replaceWith(replacement);
replacement.append(...(nextNode as Element).childNodes);
(nextNode as Element).replaceWith(replacement);
}
// Insert HTML Elements, which were stored in insertNodes
DOM.querySelectorAll("template[id^=lbInsertNodes]").forEach((template) =>
template.replaceWith(insertNodes.shift()!)
);
elem
.querySelectorAll("template[id^=lbInsertNodes]")
.forEach((template) => template.replaceWith(insertNodes.shift()!));
if (shouldSetReactivity) setReactivity(DOM, eventFunctions);
// Return DocumentFragment
if (DOM.childNodes.length > 1) return DOM;
// Return Text Node
if (!DOM.firstChild) return document.createTextNode("");
// Return Element
return DOM.firstChild as Element;
if (shouldSetReactivity) setReactivity(elem, eventFunctions);
}
/* c8 ignore start */
function h(

@@ -328,9 +349,17 @@ name: string | ((...args: any[]) => ReturnType<typeof h>),

const flatChildren = children
.map((child) =>
/* c8 ignore next 1 */
.map((child: any) =>
isObject(child) && !isNode(child as Node) ? Object.values(child) : child
)
.flat();
return html`<${name} ${props || {}}>${flatChildren}</${name}>`;
const elem = document.createElement(name);
for (let i in props) {
//@ts-ignore
i in elem ? (elem[i] = props[i]) : setAttribute(elem, i, props[i]);
}
elem.append(...flatChildren);
onRender(setReactivity, elem, elem);
return elem;
}
/* c8 ignore end */
function setReactivity(DOM: Node, eventFunctions?: eventFunctions) {

@@ -776,5 +805,7 @@ // Set events and reactive behaviour(checks for {{ key }} where key is on hydro)

/* c8 ignore next 3 */
if (globalSchedule) {
if (viewElements) {
schedule(fn);
/* c8 ignore next 3 */
} else if (globalSchedule) {
window.requestIdleCallback(fn);
} else {

@@ -1226,2 +1257,3 @@ fn();

// Remove item from array
/* c8 ignore next 4 */
if (!internReset && Array.isArray(receiver)) {

@@ -1249,4 +1281,5 @@ receiver.splice((key as unknown) as number, 1);

let subItem = receiver[key][i];
/* c8 ignore next 3 */
if (isObject(subItem) && isProxy(subItem)) {
subItem = null;
receiver[key][i] = null;
}

@@ -1284,5 +1317,7 @@ }

if (
!reuseElements &&
Array.isArray(receiver) &&
receiver.includes(oldVal) &&
receiver.includes(val) &&
/* c8 ignore start */
bindMap.has(val)

@@ -1308,2 +1343,3 @@ ) {

} else {
/* c8 ignore end */
returnSet = Reflect.set(target, key, val, receiver);

@@ -1326,3 +1362,11 @@ }

if (reactivityMap.has(oldVal)) {
reactivityMap.set(oldVal, reactivityMap.get(val)!);
// Store old reactivityMap if it is a swap operation
reuseElements && tmpSwap.set(oldVal, reactivityMap.get(oldVal)!);
if (tmpSwap.has(val)) {
reactivityMap.set(oldVal, tmpSwap.get(val)!);
tmpSwap.delete(val);
} else {
reactivityMap.set(oldVal, reactivityMap.get(val)!);
}
}

@@ -1339,3 +1383,3 @@ }

// If oldVal is a Proxy - clean it
schedule(cleanProxy, oldVal);
!reuseElements && cleanProxy(oldVal);

@@ -1408,2 +1452,3 @@ return returnSet;

}
/* c8 ignore next 3 */
} else {

@@ -1429,2 +1474,3 @@ map.clear();

reactivityMap.delete(proxy);
/* c8 ignore next 4 */
if (bindMap.has(proxy)) {

@@ -1566,16 +1612,2 @@ bindMap.get(proxy)!.forEach(removeElement);

}
function template(
elem: HTMLTemplateElement,
placeholders: Record<string, any>,
events: Record<string, any>
) {
let wrapper = elem.content.cloneNode(true).firstChild as HTMLElement;
let innerHTML = wrapper.innerHTML;
for (const [key, value] of Object.entries(placeholders)) {
innerHTML = innerHTML.replace(key, String(value));
}
wrapper.innerHTML = innerHTML;
setReactivity(wrapper.firstChild!, events);
return wrapper.firstChild as Element;
}
function view(

@@ -1586,21 +1618,45 @@ root: string,

) {
getValue(data).forEach((item: any, i: number) => {
const elem = renderFunction(item, i);
$(root)!.appendChild(elem);
});
viewElements = true;
const rootElem = $(root)!;
const elements = getValue(data).map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem as Element, onRenderMap));
viewElements = false;
observe(data, (newData: typeof data, oldData: typeof data) => {
/* c8 ignore start */
viewElements = true;
observe(data, (newData: Array<any>, oldData: Array<any>) => {
const rootElem = $(root)!;
if (!newData?.length || oldData?.[0] !== newData?.[0]) {
rootElem.innerHTML = "";
// Reset or re-use
if (
!newData?.length ||
(!reuseElements && newData?.length === oldData?.length)
) {
rootElem.textContent = "";
} else if (reuseElements) {
for (let i = 0; i < oldData?.length && newData?.length; i++) {
oldData[i].id = newData[i].id;
oldData[i].label = newData[i].label;
newData[i] = oldData[i];
}
}
// Add to existing
if (oldData?.length && newData?.length > oldData?.length) {
rootElem.append(...newData.slice(oldData.length).map(renderFunction));
} else {
newData?.forEach((item, i) => {
const elem = renderFunction(item, i);
rootElem.insertBefore(elem, null);
});
const length = oldData.length;
const slicedData = newData.slice(length);
const newElements = slicedData.map((item, i) =>
renderFunction(item, i + length)
);
rootElem.append(...newElements);
newElements.forEach((elem) => runLifecyle(elem as Element, onRenderMap));
}
// Add new
else if (oldData?.length === 0 || (!reuseElements && newData?.length)) {
const elements = newData.map(renderFunction);
rootElem.append(...elements);
elements.forEach((elem) => runLifecyle(elem as Element, onRenderMap));
}
viewElements = false;
/* c8 ignore end */
});

@@ -1640,4 +1696,3 @@ }

$$,
template,
view,
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display