veles 1.1.3 → 1.1.4

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.
@@ -151,6 +151,9 @@ function parseChildren({ children, htmlElement, velesNode, portal }) {
151
151
  childComponent.parentVelesElement = velesNode;
152
152
  childComponents.push(childComponent);
153
153
  } else if (childComponent.portal) {
154
+ if (!childComponent.portalAnchor) throw new Error("Portal node is missing its source anchor");
155
+ htmlElement.append(childComponent.portalAnchor);
156
+ lastInsertedNode = childComponent.portalAnchor;
154
157
  childComponent.parentVelesElement = velesNode;
155
158
  childComponents.push(childComponent);
156
159
  } else {
@@ -183,6 +186,7 @@ const FORM_VALUE_TAGS = new Set([
183
186
  "TEXTAREA",
184
187
  "SELECT"
185
188
  ]);
189
+ const ATTRIBUTE_ALIASES = { htmlfor: "for" };
186
190
  const ENUMERATED_BOOLEAN_ATTRIBUTES = {
187
191
  draggable: {
188
192
  trueValue: "true",
@@ -203,6 +207,11 @@ const ENUMERATED_BOOLEAN_ATTRIBUTES = {
203
207
  };
204
208
  function assignDomAttribute({ htmlElement, attributeName, value, previousValue }) {
205
209
  const normalizedAttributeName = attributeName.toLowerCase();
210
+ const domAttributeName = ATTRIBUTE_ALIASES[normalizedAttributeName] ?? attributeName;
211
+ if (normalizedAttributeName === "dangerouslysetinnerhtml") {
212
+ assignInnerHTML(htmlElement, value);
213
+ return;
214
+ }
206
215
  if (normalizedAttributeName === "value" && isFormValueElement(htmlElement)) {
207
216
  assignFormValueProperty(htmlElement, value);
208
217
  return;
@@ -215,7 +224,7 @@ function assignDomAttribute({ htmlElement, attributeName, value, previousValue }
215
224
  assignBooleanProperty(htmlElement, "selected", value);
216
225
  return;
217
226
  }
218
- if (attributeName === "style") {
227
+ if (normalizedAttributeName === "style") {
219
228
  assignStyle({
220
229
  value,
221
230
  previousValue,
@@ -223,21 +232,32 @@ function assignDomAttribute({ htmlElement, attributeName, value, previousValue }
223
232
  });
224
233
  return;
225
234
  }
235
+ if (typeof value === "boolean" && (normalizedAttributeName.startsWith("aria-") || normalizedAttributeName.startsWith("data-"))) {
236
+ htmlElement.setAttribute(domAttributeName, String(value));
237
+ return;
238
+ }
226
239
  if (typeof value === "boolean") {
227
240
  const enumeratedConfig = ENUMERATED_BOOLEAN_ATTRIBUTES[normalizedAttributeName];
228
241
  if (enumeratedConfig) {
229
- htmlElement.setAttribute(attributeName, value ? enumeratedConfig.trueValue : enumeratedConfig.falseValue);
242
+ htmlElement.setAttribute(domAttributeName, value ? enumeratedConfig.trueValue : enumeratedConfig.falseValue);
230
243
  return;
231
244
  }
232
- if (value) htmlElement.setAttribute(attributeName, "");
233
- else htmlElement.removeAttribute(attributeName);
245
+ if (value) htmlElement.setAttribute(domAttributeName, "");
246
+ else htmlElement.removeAttribute(domAttributeName);
234
247
  return;
235
248
  }
236
249
  if (value == null) {
237
- htmlElement.removeAttribute(attributeName);
250
+ htmlElement.removeAttribute(domAttributeName);
251
+ return;
252
+ }
253
+ htmlElement.setAttribute(domAttributeName, value);
254
+ }
255
+ function assignInnerHTML(htmlElement, value) {
256
+ if (value == null) {
257
+ htmlElement.innerHTML = "";
238
258
  return;
239
259
  }
240
- htmlElement.setAttribute(attributeName, value);
260
+ if (typeof value === "object" && "__html" in value) htmlElement.innerHTML = value.__html == null ? "" : String(value.__html);
241
261
  }
242
262
  function isFormValueElement(htmlElement) {
243
263
  return FORM_VALUE_TAGS.has(htmlElement.tagName);
@@ -326,6 +346,7 @@ function createElement(element, props = {}) {
326
346
  velesNode.childComponents = childComponents;
327
347
  velesNode.phantom = phantom;
328
348
  velesNode.portal = portal;
349
+ if (portal) velesNode.portalAnchor = document.createTextNode("");
329
350
  const mountHandlers = [];
330
351
  velesNode._privateMethods = {
331
352
  _addMountHandler(cb) {
@@ -397,10 +418,17 @@ function cleanupComponentFromPortal(componentNode) {
397
418
  //#endregion
398
419
  //#region src/fragment.ts
399
420
  function Fragment({ children }) {
400
- return createElement("div", {
421
+ const fragment = createElement("div", {
401
422
  phantom: true,
402
423
  children
403
424
  });
425
+ if (fragment.childComponents.length === 0) {
426
+ const anchor = createTextElement("");
427
+ anchor.parentVelesElement = fragment;
428
+ fragment.childComponents.push(anchor);
429
+ fragment.html.append(anchor.html);
430
+ }
431
+ return fragment;
404
432
  }
405
433
  //#endregion
406
434
  //#region src/context/index.ts
@@ -523,45 +551,43 @@ function renderTree(component, { parentVelesElement } = {}) {
523
551
  executedNode.html = component.html;
524
552
  if (parentVelesElement) executedNode.parentVelesElement = parentVelesElement;
525
553
  if (component.phantom) executedNode.phantom = component.phantom;
526
- if (component.portal) executedNode.portal = component.portal;
554
+ if (component.portal) {
555
+ if (!component.portalAnchor) throw new Error("Portal node is missing its source anchor");
556
+ executedNode.portal = component.portal;
557
+ executedNode.portalAnchor = component.portalAnchor;
558
+ }
527
559
  executedNode.childComponents = component.childComponents.map((childComponent) => renderTree(childComponent, { parentVelesElement: executedNode }));
528
560
  if (component.needExecutedVersion) component.executedVersion = executedNode;
529
561
  return executedNode;
530
562
  }
531
563
  throw new Error("Unknown component type in renderTree");
532
564
  }
565
+ function getExecutedVelesNodeSourceNode(node) {
566
+ if ("executedVelesNode" in node && node.portal) {
567
+ if (!node.portalAnchor) throw new Error("Portal node is missing its source anchor");
568
+ return node.portalAnchor;
569
+ }
570
+ return node.html;
571
+ }
533
572
  function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
534
573
  if (velesElement.phantom) {
535
574
  let lastInsertedNode = null;
536
575
  velesElement.childComponents.forEach((childComponentofPhantom) => {
537
- if ("executedVelesNode" in childComponentofPhantom) {
538
- if (lastInsertedNode) lastInsertedNode.after(childComponentofPhantom.html);
539
- else if (adjacentNode) adjacentNode.after(childComponentofPhantom.html);
540
- else parentVelesElement.html.prepend(childComponentofPhantom.html);
541
- childComponentofPhantom.parentVelesElement = parentVelesElement;
542
- lastInsertedNode = childComponentofPhantom.html;
543
- } else if ("executedVelesStringElement" in childComponentofPhantom) {
544
- if (lastInsertedNode) lastInsertedNode.after(childComponentofPhantom.html);
545
- else if (adjacentNode) adjacentNode.after(childComponentofPhantom.html);
546
- else parentVelesElement.html.prepend(childComponentofPhantom.html);
547
- childComponentofPhantom.parentVelesElement = parentVelesElement;
548
- lastInsertedNode = childComponentofPhantom.html;
549
- } else {
550
- const executedNode = getExecutedComponentVelesNode(childComponentofPhantom);
551
- if (lastInsertedNode) lastInsertedNode.after(executedNode.html);
552
- else if (adjacentNode) adjacentNode.after(executedNode.html);
553
- else parentVelesElement.html.prepend(executedNode.html);
554
- executedNode.parentVelesElement = parentVelesElement;
555
- lastInsertedNode = executedNode.html;
556
- }
576
+ const lastInsertedChildNode = insertNode({
577
+ velesElement: "executedVelesComponent" in childComponentofPhantom ? getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom,
578
+ adjacentNode: lastInsertedNode ?? adjacentNode,
579
+ parentVelesElement
580
+ });
581
+ if (lastInsertedChildNode) lastInsertedNode = lastInsertedChildNode;
557
582
  });
558
583
  velesElement.parentVelesElement = parentVelesElement;
559
584
  return lastInsertedNode;
560
585
  } else {
561
- if (adjacentNode) adjacentNode.after(velesElement.html);
562
- else parentVelesElement.html.prepend(velesElement.html);
586
+ const sourceNode = getExecutedVelesNodeSourceNode(velesElement);
587
+ if (adjacentNode) adjacentNode.after(sourceNode);
588
+ else parentVelesElement.html.prepend(sourceNode);
563
589
  velesElement.parentVelesElement = parentVelesElement;
564
- return velesElement.html;
590
+ return sourceNode;
565
591
  }
566
592
  }
567
593
  function getMountedNodeExecutedVersion(node, errorMessage) {
@@ -593,4 +619,4 @@ function unique(arr) {
593
619
  return resultArr;
594
620
  }
595
621
  //#endregion
596
- export { onMount as _, identity as a, addPublicContext as c, popPublicContext as d, Fragment as f, hasCurrentLifecycleContext as g, createTextElement as h, getMountedNodeExecutedVersion as i, createContext as l, assignDomAttribute as m, callUnmountHandlers as n, renderTree as o, createElement as p, getExecutedComponentVelesNode as r, unique as s, callMountHandlers as t, getCurrentContext as u, onUnmount as v };
622
+ export { hasCurrentLifecycleContext as _, getMountedNodeExecutedVersion as a, unique as c, getCurrentContext as d, popPublicContext as f, createTextElement as g, assignDomAttribute as h, getExecutedVelesNodeSourceNode as i, addPublicContext as l, createElement as m, callUnmountHandlers as n, identity as o, Fragment as p, getExecutedComponentVelesNode as r, renderTree as s, callMountHandlers as t, createContext as u, onMount as v, onUnmount as y };
@@ -151,6 +151,9 @@ function parseChildren({ children, htmlElement, velesNode, portal }) {
151
151
  childComponent.parentVelesElement = velesNode;
152
152
  childComponents.push(childComponent);
153
153
  } else if (childComponent.portal) {
154
+ if (!childComponent.portalAnchor) throw new Error("Portal node is missing its source anchor");
155
+ htmlElement.append(childComponent.portalAnchor);
156
+ lastInsertedNode = childComponent.portalAnchor;
154
157
  childComponent.parentVelesElement = velesNode;
155
158
  childComponents.push(childComponent);
156
159
  } else {
@@ -183,6 +186,7 @@ const FORM_VALUE_TAGS = new Set([
183
186
  "TEXTAREA",
184
187
  "SELECT"
185
188
  ]);
189
+ const ATTRIBUTE_ALIASES = { htmlfor: "for" };
186
190
  const ENUMERATED_BOOLEAN_ATTRIBUTES = {
187
191
  draggable: {
188
192
  trueValue: "true",
@@ -203,6 +207,11 @@ const ENUMERATED_BOOLEAN_ATTRIBUTES = {
203
207
  };
204
208
  function assignDomAttribute({ htmlElement, attributeName, value, previousValue }) {
205
209
  const normalizedAttributeName = attributeName.toLowerCase();
210
+ const domAttributeName = ATTRIBUTE_ALIASES[normalizedAttributeName] ?? attributeName;
211
+ if (normalizedAttributeName === "dangerouslysetinnerhtml") {
212
+ assignInnerHTML(htmlElement, value);
213
+ return;
214
+ }
206
215
  if (normalizedAttributeName === "value" && isFormValueElement(htmlElement)) {
207
216
  assignFormValueProperty(htmlElement, value);
208
217
  return;
@@ -215,7 +224,7 @@ function assignDomAttribute({ htmlElement, attributeName, value, previousValue }
215
224
  assignBooleanProperty(htmlElement, "selected", value);
216
225
  return;
217
226
  }
218
- if (attributeName === "style") {
227
+ if (normalizedAttributeName === "style") {
219
228
  assignStyle({
220
229
  value,
221
230
  previousValue,
@@ -223,21 +232,32 @@ function assignDomAttribute({ htmlElement, attributeName, value, previousValue }
223
232
  });
224
233
  return;
225
234
  }
235
+ if (typeof value === "boolean" && (normalizedAttributeName.startsWith("aria-") || normalizedAttributeName.startsWith("data-"))) {
236
+ htmlElement.setAttribute(domAttributeName, String(value));
237
+ return;
238
+ }
226
239
  if (typeof value === "boolean") {
227
240
  const enumeratedConfig = ENUMERATED_BOOLEAN_ATTRIBUTES[normalizedAttributeName];
228
241
  if (enumeratedConfig) {
229
- htmlElement.setAttribute(attributeName, value ? enumeratedConfig.trueValue : enumeratedConfig.falseValue);
242
+ htmlElement.setAttribute(domAttributeName, value ? enumeratedConfig.trueValue : enumeratedConfig.falseValue);
230
243
  return;
231
244
  }
232
- if (value) htmlElement.setAttribute(attributeName, "");
233
- else htmlElement.removeAttribute(attributeName);
245
+ if (value) htmlElement.setAttribute(domAttributeName, "");
246
+ else htmlElement.removeAttribute(domAttributeName);
247
+ return;
248
+ }
249
+ if (value == null) {
250
+ htmlElement.removeAttribute(domAttributeName);
234
251
  return;
235
252
  }
253
+ htmlElement.setAttribute(domAttributeName, value);
254
+ }
255
+ function assignInnerHTML(htmlElement, value) {
236
256
  if (value == null) {
237
- htmlElement.removeAttribute(attributeName);
257
+ htmlElement.innerHTML = "";
238
258
  return;
239
259
  }
240
- htmlElement.setAttribute(attributeName, value);
260
+ if (typeof value === "object" && "__html" in value) htmlElement.innerHTML = value.__html == null ? "" : String(value.__html);
241
261
  }
242
262
  function isFormValueElement(htmlElement) {
243
263
  return FORM_VALUE_TAGS.has(htmlElement.tagName);
@@ -326,6 +346,7 @@ function createElement(element, props = {}) {
326
346
  velesNode.childComponents = childComponents;
327
347
  velesNode.phantom = phantom;
328
348
  velesNode.portal = portal;
349
+ if (portal) velesNode.portalAnchor = document.createTextNode("");
329
350
  const mountHandlers = [];
330
351
  velesNode._privateMethods = {
331
352
  _addMountHandler(cb) {
@@ -397,10 +418,17 @@ function cleanupComponentFromPortal(componentNode) {
397
418
  //#endregion
398
419
  //#region src/fragment.ts
399
420
  function Fragment({ children }) {
400
- return createElement("div", {
421
+ const fragment = createElement("div", {
401
422
  phantom: true,
402
423
  children
403
424
  });
425
+ if (fragment.childComponents.length === 0) {
426
+ const anchor = createTextElement("");
427
+ anchor.parentVelesElement = fragment;
428
+ fragment.childComponents.push(anchor);
429
+ fragment.html.append(anchor.html);
430
+ }
431
+ return fragment;
404
432
  }
405
433
  //#endregion
406
434
  //#region src/context/index.ts
@@ -523,45 +551,43 @@ function renderTree(component, { parentVelesElement } = {}) {
523
551
  executedNode.html = component.html;
524
552
  if (parentVelesElement) executedNode.parentVelesElement = parentVelesElement;
525
553
  if (component.phantom) executedNode.phantom = component.phantom;
526
- if (component.portal) executedNode.portal = component.portal;
554
+ if (component.portal) {
555
+ if (!component.portalAnchor) throw new Error("Portal node is missing its source anchor");
556
+ executedNode.portal = component.portal;
557
+ executedNode.portalAnchor = component.portalAnchor;
558
+ }
527
559
  executedNode.childComponents = component.childComponents.map((childComponent) => renderTree(childComponent, { parentVelesElement: executedNode }));
528
560
  if (component.needExecutedVersion) component.executedVersion = executedNode;
529
561
  return executedNode;
530
562
  }
531
563
  throw new Error("Unknown component type in renderTree");
532
564
  }
565
+ function getExecutedVelesNodeSourceNode(node) {
566
+ if ("executedVelesNode" in node && node.portal) {
567
+ if (!node.portalAnchor) throw new Error("Portal node is missing its source anchor");
568
+ return node.portalAnchor;
569
+ }
570
+ return node.html;
571
+ }
533
572
  function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
534
573
  if (velesElement.phantom) {
535
574
  let lastInsertedNode = null;
536
575
  velesElement.childComponents.forEach((childComponentofPhantom) => {
537
- if ("executedVelesNode" in childComponentofPhantom) {
538
- if (lastInsertedNode) lastInsertedNode.after(childComponentofPhantom.html);
539
- else if (adjacentNode) adjacentNode.after(childComponentofPhantom.html);
540
- else parentVelesElement.html.prepend(childComponentofPhantom.html);
541
- childComponentofPhantom.parentVelesElement = parentVelesElement;
542
- lastInsertedNode = childComponentofPhantom.html;
543
- } else if ("executedVelesStringElement" in childComponentofPhantom) {
544
- if (lastInsertedNode) lastInsertedNode.after(childComponentofPhantom.html);
545
- else if (adjacentNode) adjacentNode.after(childComponentofPhantom.html);
546
- else parentVelesElement.html.prepend(childComponentofPhantom.html);
547
- childComponentofPhantom.parentVelesElement = parentVelesElement;
548
- lastInsertedNode = childComponentofPhantom.html;
549
- } else {
550
- const executedNode = getExecutedComponentVelesNode(childComponentofPhantom);
551
- if (lastInsertedNode) lastInsertedNode.after(executedNode.html);
552
- else if (adjacentNode) adjacentNode.after(executedNode.html);
553
- else parentVelesElement.html.prepend(executedNode.html);
554
- executedNode.parentVelesElement = parentVelesElement;
555
- lastInsertedNode = executedNode.html;
556
- }
576
+ const lastInsertedChildNode = insertNode({
577
+ velesElement: "executedVelesComponent" in childComponentofPhantom ? getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom,
578
+ adjacentNode: lastInsertedNode ?? adjacentNode,
579
+ parentVelesElement
580
+ });
581
+ if (lastInsertedChildNode) lastInsertedNode = lastInsertedChildNode;
557
582
  });
558
583
  velesElement.parentVelesElement = parentVelesElement;
559
584
  return lastInsertedNode;
560
585
  } else {
561
- if (adjacentNode) adjacentNode.after(velesElement.html);
562
- else parentVelesElement.html.prepend(velesElement.html);
586
+ const sourceNode = getExecutedVelesNodeSourceNode(velesElement);
587
+ if (adjacentNode) adjacentNode.after(sourceNode);
588
+ else parentVelesElement.html.prepend(sourceNode);
563
589
  velesElement.parentVelesElement = parentVelesElement;
564
- return velesElement.html;
590
+ return sourceNode;
565
591
  }
566
592
  }
567
593
  function getMountedNodeExecutedVersion(node, errorMessage) {
@@ -653,6 +679,12 @@ Object.defineProperty(exports, "getExecutedComponentVelesNode", {
653
679
  return getExecutedComponentVelesNode;
654
680
  }
655
681
  });
682
+ Object.defineProperty(exports, "getExecutedVelesNodeSourceNode", {
683
+ enumerable: true,
684
+ get: function() {
685
+ return getExecutedVelesNodeSourceNode;
686
+ }
687
+ });
656
688
  Object.defineProperty(exports, "getMountedNodeExecutedVersion", {
657
689
  enumerable: true,
658
690
  get: function() {
@@ -1428,6 +1428,7 @@ type VelesElement = {
1428
1428
  html: HTMLElement;
1429
1429
  phantom?: boolean;
1430
1430
  portal?: null | HTMLElement;
1431
+ portalAnchor?: Text;
1431
1432
  needExecutedVersion?: boolean;
1432
1433
  executedVersion?: ExecutedVelesElement; // every element except the most top one should have one
1433
1434
  parentVelesElement?: VelesElement;
@@ -1443,7 +1444,8 @@ type ExecutedVelesElement = {
1443
1444
  executedVelesNode: true;
1444
1445
  html: HTMLElement;
1445
1446
  phantom?: boolean;
1446
- portal?: HTMLElement; // every element except the most top one should have one
1447
+ portal?: HTMLElement;
1448
+ portalAnchor?: Text; // every element except the most top one should have one
1447
1449
  parentVelesElement?: ExecutedVelesElement;
1448
1450
  childComponents: (ExecutedVelesElement | ExecutedVelesComponent | ExecutedVelesStringElement)[]; // not intended to be used directly
1449
1451
  _privateMethods: {
@@ -1428,6 +1428,7 @@ type VelesElement = {
1428
1428
  html: HTMLElement;
1429
1429
  phantom?: boolean;
1430
1430
  portal?: null | HTMLElement;
1431
+ portalAnchor?: Text;
1431
1432
  needExecutedVersion?: boolean;
1432
1433
  executedVersion?: ExecutedVelesElement; // every element except the most top one should have one
1433
1434
  parentVelesElement?: VelesElement;
@@ -1443,7 +1444,8 @@ type ExecutedVelesElement = {
1443
1444
  executedVelesNode: true;
1444
1445
  html: HTMLElement;
1445
1446
  phantom?: boolean;
1446
- portal?: HTMLElement; // every element except the most top one should have one
1447
+ portal?: HTMLElement;
1448
+ portalAnchor?: Text; // every element except the most top one should have one
1447
1449
  parentVelesElement?: ExecutedVelesElement;
1448
1450
  childComponents: (ExecutedVelesElement | ExecutedVelesComponent | ExecutedVelesStringElement)[]; // not intended to be used directly
1449
1451
  _privateMethods: {
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require__utils = require("./_utils-DbrPydEE.cjs");
2
+ const require__utils = require("./_utils-CXVRQTuz.cjs");
3
3
  //#region src/attach-component.ts
4
4
  /**
5
5
  * Attach Veles component tree to a regular HTML node.
@@ -66,69 +66,42 @@ function updateUseValueSelector({ value, selectorTrackingElement, newTrackingSel
66
66
  newVelesElementNode.parentVelesElement = parentVelesElementRendered;
67
67
  if ("executedVelesNode" in newVelesElementNode && newVelesElementNode.phantom) {
68
68
  const insertAllPhantomChildren = (adjacentNode) => {
69
+ const adjacentSourceNode = require__utils.getExecutedVelesNodeSourceNode(adjacentNode);
69
70
  newVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
70
- if ("executedVelesNode" in childComponentofPhantom) {
71
- adjacentNode.html.before(childComponentofPhantom.html);
72
- childComponentofPhantom.parentVelesElement = adjacentNode.parentVelesElement;
73
- } else {
74
- const velesElementNode = require__utils.getExecutedComponentVelesNode(childComponentofPhantom);
75
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
76
- else {
77
- adjacentNode.html.before(velesElementNode.html);
78
- velesElementNode.parentVelesElement = adjacentNode.parentVelesElement;
79
- }
80
- }
71
+ const childNode = "executedVelesComponent" in childComponentofPhantom ? require__utils.getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom;
72
+ adjacentSourceNode.before(require__utils.getExecutedVelesNodeSourceNode(childNode));
73
+ childNode.parentVelesElement = adjacentNode.parentVelesElement;
81
74
  });
82
75
  };
83
76
  if ("executedVelesNode" in oldVelesElementNode && oldVelesElementNode.phantom) {
84
77
  let isInserted = false;
85
78
  oldVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
86
- if ("executedVelesNode" in childComponentofPhantom) {
87
- if (!isInserted) {
88
- insertAllPhantomChildren(childComponentofPhantom);
89
- isInserted = true;
90
- }
91
- childComponentofPhantom.html.remove();
92
- } else {
93
- const velesElementNode = require__utils.getExecutedComponentVelesNode(childComponentofPhantom);
94
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
95
- else {
96
- if (!isInserted) {
97
- insertAllPhantomChildren(velesElementNode);
98
- isInserted = true;
99
- }
100
- velesElementNode.html.remove();
101
- }
79
+ const childNode = "executedVelesComponent" in childComponentofPhantom ? require__utils.getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom;
80
+ if (!isInserted) {
81
+ insertAllPhantomChildren(childNode);
82
+ isInserted = true;
102
83
  }
84
+ require__utils.getExecutedVelesNodeSourceNode(childNode).remove();
103
85
  });
104
86
  } else {
105
87
  insertAllPhantomChildren(oldVelesElementNode);
106
- oldVelesElementNode.html.remove();
88
+ require__utils.getExecutedVelesNodeSourceNode(oldVelesElementNode).remove();
107
89
  }
108
90
  } else if ("executedVelesNode" in oldVelesElementNode && oldVelesElementNode.phantom) {
109
91
  let isInserted = false;
110
92
  oldVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
111
- if ("executedVelesNode" in childComponentofPhantom) {
112
- if (!isInserted) {
113
- childComponentofPhantom.html.before(newVelesElementNode.html);
114
- isInserted = true;
115
- }
116
- childComponentofPhantom.html.remove();
117
- } else {
118
- const velesElementNode = require__utils.getExecutedComponentVelesNode(childComponentofPhantom);
119
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
120
- else {
121
- if (!isInserted) {
122
- velesElementNode.html.before(newVelesElementNode.html);
123
- isInserted = true;
124
- }
125
- velesElementNode.html.remove();
126
- }
93
+ const childSourceNode = require__utils.getExecutedVelesNodeSourceNode("executedVelesComponent" in childComponentofPhantom ? require__utils.getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom);
94
+ if (!isInserted) {
95
+ childSourceNode.before(require__utils.getExecutedVelesNodeSourceNode(newVelesElementNode));
96
+ isInserted = true;
127
97
  }
98
+ childSourceNode.remove();
128
99
  });
129
100
  } else try {
130
- if (parentVelesElementRendered.portal) parentVelesElementRendered.portal.replaceChild(newVelesElementNode.html, oldVelesElementNode.html);
131
- else parentVelesElementRendered.html.replaceChild(newVelesElementNode.html, oldVelesElementNode.html);
101
+ const newSourceNode = require__utils.getExecutedVelesNodeSourceNode(newVelesElementNode);
102
+ const oldSourceNode = require__utils.getExecutedVelesNodeSourceNode(oldVelesElementNode);
103
+ if (parentVelesElementRendered.portal) parentVelesElementRendered.portal.replaceChild(newSourceNode, oldSourceNode);
104
+ else parentVelesElementRendered.html.replaceChild(newSourceNode, oldSourceNode);
132
105
  } catch (e) {
133
106
  console.error("failed to update in renderSelected", e);
134
107
  }
@@ -205,7 +178,7 @@ function updateUseAttributeValue({ element, value }) {
205
178
  //#endregion
206
179
  //#region src/create-state/update-render-each-value.ts
207
180
  function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
208
- const { cb, key, renderedElements, elementsByKey, wrapperComponent, selector, savedContext } = trackingIterator;
181
+ const { anchor, cb, key, renderedElements, elementsByKey, wrapperComponent, selector, savedContext } = trackingIterator;
209
182
  if (!wrapperComponent) {
210
183
  console.error("there is no wrapper component for the iterator");
211
184
  return;
@@ -219,19 +192,19 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
219
192
  const elements = selector ? selector(value) : value;
220
193
  if (Array.isArray(elements)) {
221
194
  const newRenderedElements = [];
222
- const newElementsByKey = {};
223
- const renderedExistingElements = {};
195
+ const newElementsByKey = /* @__PURE__ */ new Map();
196
+ const renderedExistingElements = /* @__PURE__ */ new Set();
224
197
  elements.forEach((element, index) => {
225
- let calculatedKey = "";
198
+ let calculatedKey = null;
226
199
  if (typeof key === "string" && typeof element === "object" && element !== null && key in element) calculatedKey = element[key];
227
200
  else if (typeof key === "function") calculatedKey = key({
228
201
  element,
229
202
  index
230
203
  });
231
- if (!calculatedKey) return;
232
- const existingElement = elementsByKey[calculatedKey];
204
+ if (calculatedKey == null) return;
205
+ const existingElement = elementsByKey.get(calculatedKey);
233
206
  if (existingElement) {
234
- renderedExistingElements[calculatedKey] = true;
207
+ renderedExistingElements.add(calculatedKey);
235
208
  if (existingElement.elementState.get() !== element) existingElement.elementState.set(element);
236
209
  if (existingElement.indexState.get() !== index) existingElement.indexState.set(index);
237
210
  newRenderedElements.push([
@@ -239,12 +212,12 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
239
212
  calculatedKey,
240
213
  existingElement.elementState
241
214
  ]);
242
- newElementsByKey[calculatedKey] = {
215
+ newElementsByKey.set(calculatedKey, {
243
216
  elementState: existingElement.elementState,
244
217
  indexState: existingElement.indexState,
245
218
  indexValue: index,
246
219
  node: existingElement.node
247
- };
220
+ });
248
221
  } else {
249
222
  const elementState = createState(element);
250
223
  const indexState = createState(index);
@@ -260,12 +233,12 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
260
233
  calculatedKey,
261
234
  elementState
262
235
  ]);
263
- newElementsByKey[calculatedKey] = {
236
+ newElementsByKey.set(calculatedKey, {
264
237
  elementState,
265
238
  indexState,
266
239
  indexValue: index,
267
240
  node
268
- };
241
+ });
269
242
  }
270
243
  });
271
244
  const newChildRenderedComponents = [];
@@ -279,61 +252,65 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
279
252
  newChildComponents.push(newRenderedElement[0]);
280
253
  if (positioningOffset[index]) offset = offset + positioningOffset[index];
281
254
  const [newNode, calculatedKey, _newState] = newRenderedElement;
282
- const existingElement = elementsByKey[calculatedKey];
255
+ const existingElement = elementsByKey.get(calculatedKey);
283
256
  if (existingElement) {
284
- const existingElementNode = require__utils.getExecutedComponentVelesNode(require__utils.getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted"));
257
+ const existingElementSourceNode = require__utils.getExecutedVelesNodeSourceNode(require__utils.getExecutedComponentVelesNode(require__utils.getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted")));
285
258
  if (existingElement.indexValue + offset === index) {
286
- currentElement = existingElementNode.html;
259
+ currentElement = existingElementSourceNode;
287
260
  return;
288
261
  }
289
262
  if (existingElement.indexValue + offset > index) {
290
263
  if (currentElement) {
291
- currentElement.after(existingElementNode.html);
264
+ currentElement.after(existingElementSourceNode);
292
265
  positioningOffset[existingElement.indexValue + 1] = -1;
293
266
  } else {
294
267
  const firstRenderedElement = renderedElements[0]?.[0];
295
- if (firstRenderedElement?.executedVersion) require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(existingElementNode.html);
268
+ if (firstRenderedElement?.executedVersion) require__utils.getExecutedVelesNodeSourceNode(require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(existingElementSourceNode);
296
269
  }
297
- currentElement = existingElementNode.html;
270
+ currentElement = existingElementSourceNode;
298
271
  offset = offset + 1;
299
272
  } else {
300
273
  if (currentElement) {
301
- currentElement.after(existingElementNode.html);
274
+ currentElement.after(existingElementSourceNode);
302
275
  positioningOffset[existingElement.indexValue + 1] = 1;
303
276
  } else {
304
277
  const firstRenderedElement = renderedElements[0]?.[0];
305
- if (firstRenderedElement?.executedVersion) require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(existingElementNode.html);
278
+ if (firstRenderedElement?.executedVersion) require__utils.getExecutedVelesNodeSourceNode(require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(existingElementSourceNode);
306
279
  }
307
- currentElement = existingElementNode.html;
280
+ currentElement = existingElementSourceNode;
308
281
  offset = offset - 1;
309
282
  }
310
283
  } else {
311
284
  const newNodeExecutedVersion = require__utils.getMountedNodeExecutedVersion(newNode, "New iterator node is expected to be mounted");
312
285
  const newNodeVelesElement = require__utils.getExecutedComponentVelesNode(newNodeExecutedVersion);
286
+ const newNodeSourceNode = require__utils.getExecutedVelesNodeSourceNode(newNodeVelesElement);
313
287
  newNodeVelesElement.parentVelesElement = parentVelesElement;
314
- if (currentElement) currentElement.after(newNodeVelesElement.html);
288
+ if (currentElement) currentElement.after(newNodeSourceNode);
315
289
  else {
316
290
  const firstRenderedElement = renderedElements[0]?.[0];
317
- if (firstRenderedElement?.executedVersion) require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(newNodeVelesElement.html);
318
- else parentVelesElement.html.prepend(newNodeVelesElement.html);
291
+ if (firstRenderedElement?.executedVersion) require__utils.getExecutedVelesNodeSourceNode(require__utils.getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(newNodeSourceNode);
292
+ else anchor.html.before(newNodeSourceNode);
319
293
  }
320
294
  offset = offset + 1;
321
- currentElement = newNodeVelesElement.html;
295
+ currentElement = newNodeSourceNode;
322
296
  newElementsCount = newElementsCount + 1;
323
297
  require__utils.callMountHandlers(newNodeExecutedVersion);
324
298
  }
325
299
  });
326
300
  if (renderedElements.length === newRenderedElements.length + newElementsCount) {} else renderedElements.forEach(([oldNode, calculatedKey]) => {
327
- if (renderedExistingElements[calculatedKey] === true) return;
301
+ if (renderedExistingElements.has(calculatedKey)) return;
328
302
  else {
329
303
  const oldNodeExecutedVersion = require__utils.getMountedNodeExecutedVersion(oldNode, "Removed iterator node is expected to be mounted");
330
- require__utils.getExecutedComponentVelesNode(oldNodeExecutedVersion).html.remove();
304
+ require__utils.getExecutedVelesNodeSourceNode(require__utils.getExecutedComponentVelesNode(oldNodeExecutedVersion)).remove();
331
305
  require__utils.callUnmountHandlers(oldNodeExecutedVersion);
332
306
  if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNodeExecutedVersion);
333
307
  else throw new Error("Wrapper iterator element is a string");
334
308
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = wrapperComponent.childComponents.filter((childComponent) => childComponent !== oldNode);
335
309
  }
336
310
  });
311
+ if (!anchor.executedVersion) throw new Error("Iterator anchor is expected to be mounted");
312
+ newChildRenderedComponents.push(anchor.executedVersion);
313
+ newChildComponents.push(anchor);
337
314
  if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = newChildRenderedComponents;
338
315
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = newChildComponents;
339
316
  trackingIterator.renderedElements = newRenderedElements;
@@ -781,7 +758,10 @@ function createStateFromCore(core, subscribeCallback) {
781
758
  trackingParams.savedContext = currentContext;
782
759
  const wrapperComponent = require__utils.createElement((_props, componentAPI) => {
783
760
  const children = [];
784
- const elementsByKey = {};
761
+ const anchor = require__utils.createTextElement("");
762
+ anchor.needExecutedVersion = true;
763
+ trackingParams.anchor = anchor;
764
+ const elementsByKey = /* @__PURE__ */ new Map();
785
765
  const stateValue = core.get();
786
766
  const elements = options.selector ? options.selector(stateValue) : stateValue;
787
767
  if (!Array.isArray(elements)) {
@@ -789,7 +769,7 @@ function createStateFromCore(core, subscribeCallback) {
789
769
  return null;
790
770
  }
791
771
  elements.forEach((element, index) => {
792
- let calculatedKey = "";
772
+ let calculatedKey = null;
793
773
  if (typeof options.key === "string" && typeof element === "object" && element !== null && options.key in element) calculatedKey = element[options.key];
794
774
  else if (typeof options.key === "function") calculatedKey = options.key({
795
775
  element,
@@ -797,18 +777,18 @@ function createStateFromCore(core, subscribeCallback) {
797
777
  });
798
778
  const elementState = createState(element);
799
779
  const indexState = createState(index);
800
- if (!calculatedKey) return;
780
+ if (calculatedKey == null) return;
801
781
  let node = cb({
802
782
  elementState,
803
783
  indexState
804
784
  });
805
785
  node.needExecutedVersion = true;
806
- elementsByKey[calculatedKey] = {
786
+ elementsByKey.set(calculatedKey, {
807
787
  node,
808
788
  indexState,
809
789
  indexValue: index,
810
790
  elementState
811
- };
791
+ });
812
792
  children.push([
813
793
  node,
814
794
  calculatedKey,
@@ -825,7 +805,7 @@ function createStateFromCore(core, subscribeCallback) {
825
805
  });
826
806
  return require__utils.createElement("div", {
827
807
  phantom: true,
828
- children: children.map((child) => child[0])
808
+ children: [...children.map((child) => child[0]), anchor]
829
809
  });
830
810
  });
831
811
  wrapperComponent.needExecutedVersion = true;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-C16zCm8L.cjs";
1
+ import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-COsp_SDE.cjs";
2
2
 
3
3
  //#region src/attach-component.d.ts
4
4
  /**
@@ -24,6 +24,7 @@ declare function onUnmount(cb: Function): void;
24
24
  type StateEquality<ValueType> = (value1: ValueType, value2: ValueType) => boolean;
25
25
  type StateLike<ValueType> = State<ValueType>;
26
26
  type ArrayElement<T> = T extends ReadonlyArray<infer Element> ? Element : never;
27
+ type IteratorKey = string | number;
27
28
  type State<ValueType> = {
28
29
  track(cb: (value: ValueType) => void | Function, options?: {
29
30
  callOnMount?: boolean;
@@ -45,7 +46,7 @@ type State<ValueType> = {
45
46
  key: string | ((options: {
46
47
  element: Element;
47
48
  index: number;
48
- }) => string);
49
+ }) => IteratorKey);
49
50
  selector?: undefined;
50
51
  } : never, cb: (props: {
51
52
  elementState: State<Element>;
@@ -55,7 +56,7 @@ type State<ValueType> = {
55
56
  key: string | ((options: {
56
57
  element: Element;
57
58
  index: number;
58
- }) => string);
59
+ }) => IteratorKey);
59
60
  selector: (value: ValueType) => SelectorValueType;
60
61
  }, cb: (props: {
61
62
  elementState: State<Element>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-yC0-T2O-.js";
1
+ import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-CPcYB5D5.js";
2
2
 
3
3
  //#region src/attach-component.d.ts
4
4
  /**
@@ -24,6 +24,7 @@ declare function onUnmount(cb: Function): void;
24
24
  type StateEquality<ValueType> = (value1: ValueType, value2: ValueType) => boolean;
25
25
  type StateLike<ValueType> = State<ValueType>;
26
26
  type ArrayElement<T> = T extends ReadonlyArray<infer Element> ? Element : never;
27
+ type IteratorKey = string | number;
27
28
  type State<ValueType> = {
28
29
  track(cb: (value: ValueType) => void | Function, options?: {
29
30
  callOnMount?: boolean;
@@ -45,7 +46,7 @@ type State<ValueType> = {
45
46
  key: string | ((options: {
46
47
  element: Element;
47
48
  index: number;
48
- }) => string);
49
+ }) => IteratorKey);
49
50
  selector?: undefined;
50
51
  } : never, cb: (props: {
51
52
  elementState: State<Element>;
@@ -55,7 +56,7 @@ type State<ValueType> = {
55
56
  key: string | ((options: {
56
57
  element: Element;
57
58
  index: number;
58
- }) => string);
59
+ }) => IteratorKey);
59
60
  selector: (value: ValueType) => SelectorValueType;
60
61
  }, cb: (props: {
61
62
  elementState: State<Element>;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as onMount, a as identity, c as addPublicContext, d as popPublicContext, f as Fragment, g as hasCurrentLifecycleContext, h as createTextElement, i as getMountedNodeExecutedVersion, l as createContext, m as assignDomAttribute, n as callUnmountHandlers, o as renderTree, p as createElement, r as getExecutedComponentVelesNode, s as unique, t as callMountHandlers, u as getCurrentContext, v as onUnmount } from "./_utils-BnAXelPu.js";
1
+ import { _ as hasCurrentLifecycleContext, a as getMountedNodeExecutedVersion, c as unique, d as getCurrentContext, f as popPublicContext, g as createTextElement, h as assignDomAttribute, i as getExecutedVelesNodeSourceNode, l as addPublicContext, m as createElement, n as callUnmountHandlers, o as identity, p as Fragment, r as getExecutedComponentVelesNode, s as renderTree, t as callMountHandlers, u as createContext, v as onMount, y as onUnmount } from "./_utils-B1lbF1Al.js";
2
2
  //#region src/attach-component.ts
3
3
  /**
4
4
  * Attach Veles component tree to a regular HTML node.
@@ -65,69 +65,42 @@ function updateUseValueSelector({ value, selectorTrackingElement, newTrackingSel
65
65
  newVelesElementNode.parentVelesElement = parentVelesElementRendered;
66
66
  if ("executedVelesNode" in newVelesElementNode && newVelesElementNode.phantom) {
67
67
  const insertAllPhantomChildren = (adjacentNode) => {
68
+ const adjacentSourceNode = getExecutedVelesNodeSourceNode(adjacentNode);
68
69
  newVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
69
- if ("executedVelesNode" in childComponentofPhantom) {
70
- adjacentNode.html.before(childComponentofPhantom.html);
71
- childComponentofPhantom.parentVelesElement = adjacentNode.parentVelesElement;
72
- } else {
73
- const velesElementNode = getExecutedComponentVelesNode(childComponentofPhantom);
74
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
75
- else {
76
- adjacentNode.html.before(velesElementNode.html);
77
- velesElementNode.parentVelesElement = adjacentNode.parentVelesElement;
78
- }
79
- }
70
+ const childNode = "executedVelesComponent" in childComponentofPhantom ? getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom;
71
+ adjacentSourceNode.before(getExecutedVelesNodeSourceNode(childNode));
72
+ childNode.parentVelesElement = adjacentNode.parentVelesElement;
80
73
  });
81
74
  };
82
75
  if ("executedVelesNode" in oldVelesElementNode && oldVelesElementNode.phantom) {
83
76
  let isInserted = false;
84
77
  oldVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
85
- if ("executedVelesNode" in childComponentofPhantom) {
86
- if (!isInserted) {
87
- insertAllPhantomChildren(childComponentofPhantom);
88
- isInserted = true;
89
- }
90
- childComponentofPhantom.html.remove();
91
- } else {
92
- const velesElementNode = getExecutedComponentVelesNode(childComponentofPhantom);
93
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
94
- else {
95
- if (!isInserted) {
96
- insertAllPhantomChildren(velesElementNode);
97
- isInserted = true;
98
- }
99
- velesElementNode.html.remove();
100
- }
78
+ const childNode = "executedVelesComponent" in childComponentofPhantom ? getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom;
79
+ if (!isInserted) {
80
+ insertAllPhantomChildren(childNode);
81
+ isInserted = true;
101
82
  }
83
+ getExecutedVelesNodeSourceNode(childNode).remove();
102
84
  });
103
85
  } else {
104
86
  insertAllPhantomChildren(oldVelesElementNode);
105
- oldVelesElementNode.html.remove();
87
+ getExecutedVelesNodeSourceNode(oldVelesElementNode).remove();
106
88
  }
107
89
  } else if ("executedVelesNode" in oldVelesElementNode && oldVelesElementNode.phantom) {
108
90
  let isInserted = false;
109
91
  oldVelesElementNode.childComponents.forEach((childComponentofPhantom) => {
110
- if ("executedVelesNode" in childComponentofPhantom) {
111
- if (!isInserted) {
112
- childComponentofPhantom.html.before(newVelesElementNode.html);
113
- isInserted = true;
114
- }
115
- childComponentofPhantom.html.remove();
116
- } else {
117
- const velesElementNode = getExecutedComponentVelesNode(childComponentofPhantom);
118
- if (!velesElementNode) console.error("can't find HTML tree in a component chain");
119
- else {
120
- if (!isInserted) {
121
- velesElementNode.html.before(newVelesElementNode.html);
122
- isInserted = true;
123
- }
124
- velesElementNode.html.remove();
125
- }
92
+ const childSourceNode = getExecutedVelesNodeSourceNode("executedVelesComponent" in childComponentofPhantom ? getExecutedComponentVelesNode(childComponentofPhantom) : childComponentofPhantom);
93
+ if (!isInserted) {
94
+ childSourceNode.before(getExecutedVelesNodeSourceNode(newVelesElementNode));
95
+ isInserted = true;
126
96
  }
97
+ childSourceNode.remove();
127
98
  });
128
99
  } else try {
129
- if (parentVelesElementRendered.portal) parentVelesElementRendered.portal.replaceChild(newVelesElementNode.html, oldVelesElementNode.html);
130
- else parentVelesElementRendered.html.replaceChild(newVelesElementNode.html, oldVelesElementNode.html);
100
+ const newSourceNode = getExecutedVelesNodeSourceNode(newVelesElementNode);
101
+ const oldSourceNode = getExecutedVelesNodeSourceNode(oldVelesElementNode);
102
+ if (parentVelesElementRendered.portal) parentVelesElementRendered.portal.replaceChild(newSourceNode, oldSourceNode);
103
+ else parentVelesElementRendered.html.replaceChild(newSourceNode, oldSourceNode);
131
104
  } catch (e) {
132
105
  console.error("failed to update in renderSelected", e);
133
106
  }
@@ -204,7 +177,7 @@ function updateUseAttributeValue({ element, value }) {
204
177
  //#endregion
205
178
  //#region src/create-state/update-render-each-value.ts
206
179
  function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
207
- const { cb, key, renderedElements, elementsByKey, wrapperComponent, selector, savedContext } = trackingIterator;
180
+ const { anchor, cb, key, renderedElements, elementsByKey, wrapperComponent, selector, savedContext } = trackingIterator;
208
181
  if (!wrapperComponent) {
209
182
  console.error("there is no wrapper component for the iterator");
210
183
  return;
@@ -218,19 +191,19 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
218
191
  const elements = selector ? selector(value) : value;
219
192
  if (Array.isArray(elements)) {
220
193
  const newRenderedElements = [];
221
- const newElementsByKey = {};
222
- const renderedExistingElements = {};
194
+ const newElementsByKey = /* @__PURE__ */ new Map();
195
+ const renderedExistingElements = /* @__PURE__ */ new Set();
223
196
  elements.forEach((element, index) => {
224
- let calculatedKey = "";
197
+ let calculatedKey = null;
225
198
  if (typeof key === "string" && typeof element === "object" && element !== null && key in element) calculatedKey = element[key];
226
199
  else if (typeof key === "function") calculatedKey = key({
227
200
  element,
228
201
  index
229
202
  });
230
- if (!calculatedKey) return;
231
- const existingElement = elementsByKey[calculatedKey];
203
+ if (calculatedKey == null) return;
204
+ const existingElement = elementsByKey.get(calculatedKey);
232
205
  if (existingElement) {
233
- renderedExistingElements[calculatedKey] = true;
206
+ renderedExistingElements.add(calculatedKey);
234
207
  if (existingElement.elementState.get() !== element) existingElement.elementState.set(element);
235
208
  if (existingElement.indexState.get() !== index) existingElement.indexState.set(index);
236
209
  newRenderedElements.push([
@@ -238,12 +211,12 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
238
211
  calculatedKey,
239
212
  existingElement.elementState
240
213
  ]);
241
- newElementsByKey[calculatedKey] = {
214
+ newElementsByKey.set(calculatedKey, {
242
215
  elementState: existingElement.elementState,
243
216
  indexState: existingElement.indexState,
244
217
  indexValue: index,
245
218
  node: existingElement.node
246
- };
219
+ });
247
220
  } else {
248
221
  const elementState = createState(element);
249
222
  const indexState = createState(index);
@@ -259,12 +232,12 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
259
232
  calculatedKey,
260
233
  elementState
261
234
  ]);
262
- newElementsByKey[calculatedKey] = {
235
+ newElementsByKey.set(calculatedKey, {
263
236
  elementState,
264
237
  indexState,
265
238
  indexValue: index,
266
239
  node
267
- };
240
+ });
268
241
  }
269
242
  });
270
243
  const newChildRenderedComponents = [];
@@ -278,61 +251,65 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
278
251
  newChildComponents.push(newRenderedElement[0]);
279
252
  if (positioningOffset[index]) offset = offset + positioningOffset[index];
280
253
  const [newNode, calculatedKey, _newState] = newRenderedElement;
281
- const existingElement = elementsByKey[calculatedKey];
254
+ const existingElement = elementsByKey.get(calculatedKey);
282
255
  if (existingElement) {
283
- const existingElementNode = getExecutedComponentVelesNode(getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted"));
256
+ const existingElementSourceNode = getExecutedVelesNodeSourceNode(getExecutedComponentVelesNode(getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted")));
284
257
  if (existingElement.indexValue + offset === index) {
285
- currentElement = existingElementNode.html;
258
+ currentElement = existingElementSourceNode;
286
259
  return;
287
260
  }
288
261
  if (existingElement.indexValue + offset > index) {
289
262
  if (currentElement) {
290
- currentElement.after(existingElementNode.html);
263
+ currentElement.after(existingElementSourceNode);
291
264
  positioningOffset[existingElement.indexValue + 1] = -1;
292
265
  } else {
293
266
  const firstRenderedElement = renderedElements[0]?.[0];
294
- if (firstRenderedElement?.executedVersion) getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(existingElementNode.html);
267
+ if (firstRenderedElement?.executedVersion) getExecutedVelesNodeSourceNode(getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(existingElementSourceNode);
295
268
  }
296
- currentElement = existingElementNode.html;
269
+ currentElement = existingElementSourceNode;
297
270
  offset = offset + 1;
298
271
  } else {
299
272
  if (currentElement) {
300
- currentElement.after(existingElementNode.html);
273
+ currentElement.after(existingElementSourceNode);
301
274
  positioningOffset[existingElement.indexValue + 1] = 1;
302
275
  } else {
303
276
  const firstRenderedElement = renderedElements[0]?.[0];
304
- if (firstRenderedElement?.executedVersion) getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(existingElementNode.html);
277
+ if (firstRenderedElement?.executedVersion) getExecutedVelesNodeSourceNode(getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(existingElementSourceNode);
305
278
  }
306
- currentElement = existingElementNode.html;
279
+ currentElement = existingElementSourceNode;
307
280
  offset = offset - 1;
308
281
  }
309
282
  } else {
310
283
  const newNodeExecutedVersion = getMountedNodeExecutedVersion(newNode, "New iterator node is expected to be mounted");
311
284
  const newNodeVelesElement = getExecutedComponentVelesNode(newNodeExecutedVersion);
285
+ const newNodeSourceNode = getExecutedVelesNodeSourceNode(newNodeVelesElement);
312
286
  newNodeVelesElement.parentVelesElement = parentVelesElement;
313
- if (currentElement) currentElement.after(newNodeVelesElement.html);
287
+ if (currentElement) currentElement.after(newNodeSourceNode);
314
288
  else {
315
289
  const firstRenderedElement = renderedElements[0]?.[0];
316
- if (firstRenderedElement?.executedVersion) getExecutedComponentVelesNode(firstRenderedElement.executedVersion).html.before(newNodeVelesElement.html);
317
- else parentVelesElement.html.prepend(newNodeVelesElement.html);
290
+ if (firstRenderedElement?.executedVersion) getExecutedVelesNodeSourceNode(getExecutedComponentVelesNode(firstRenderedElement.executedVersion)).before(newNodeSourceNode);
291
+ else anchor.html.before(newNodeSourceNode);
318
292
  }
319
293
  offset = offset + 1;
320
- currentElement = newNodeVelesElement.html;
294
+ currentElement = newNodeSourceNode;
321
295
  newElementsCount = newElementsCount + 1;
322
296
  callMountHandlers(newNodeExecutedVersion);
323
297
  }
324
298
  });
325
299
  if (renderedElements.length === newRenderedElements.length + newElementsCount) {} else renderedElements.forEach(([oldNode, calculatedKey]) => {
326
- if (renderedExistingElements[calculatedKey] === true) return;
300
+ if (renderedExistingElements.has(calculatedKey)) return;
327
301
  else {
328
302
  const oldNodeExecutedVersion = getMountedNodeExecutedVersion(oldNode, "Removed iterator node is expected to be mounted");
329
- getExecutedComponentVelesNode(oldNodeExecutedVersion).html.remove();
303
+ getExecutedVelesNodeSourceNode(getExecutedComponentVelesNode(oldNodeExecutedVersion)).remove();
330
304
  callUnmountHandlers(oldNodeExecutedVersion);
331
305
  if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNodeExecutedVersion);
332
306
  else throw new Error("Wrapper iterator element is a string");
333
307
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = wrapperComponent.childComponents.filter((childComponent) => childComponent !== oldNode);
334
308
  }
335
309
  });
310
+ if (!anchor.executedVersion) throw new Error("Iterator anchor is expected to be mounted");
311
+ newChildRenderedComponents.push(anchor.executedVersion);
312
+ newChildComponents.push(anchor);
336
313
  if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = newChildRenderedComponents;
337
314
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = newChildComponents;
338
315
  trackingIterator.renderedElements = newRenderedElements;
@@ -780,7 +757,10 @@ function createStateFromCore(core, subscribeCallback) {
780
757
  trackingParams.savedContext = currentContext;
781
758
  const wrapperComponent = createElement((_props, componentAPI) => {
782
759
  const children = [];
783
- const elementsByKey = {};
760
+ const anchor = createTextElement("");
761
+ anchor.needExecutedVersion = true;
762
+ trackingParams.anchor = anchor;
763
+ const elementsByKey = /* @__PURE__ */ new Map();
784
764
  const stateValue = core.get();
785
765
  const elements = options.selector ? options.selector(stateValue) : stateValue;
786
766
  if (!Array.isArray(elements)) {
@@ -788,7 +768,7 @@ function createStateFromCore(core, subscribeCallback) {
788
768
  return null;
789
769
  }
790
770
  elements.forEach((element, index) => {
791
- let calculatedKey = "";
771
+ let calculatedKey = null;
792
772
  if (typeof options.key === "string" && typeof element === "object" && element !== null && options.key in element) calculatedKey = element[options.key];
793
773
  else if (typeof options.key === "function") calculatedKey = options.key({
794
774
  element,
@@ -796,18 +776,18 @@ function createStateFromCore(core, subscribeCallback) {
796
776
  });
797
777
  const elementState = createState(element);
798
778
  const indexState = createState(index);
799
- if (!calculatedKey) return;
779
+ if (calculatedKey == null) return;
800
780
  let node = cb({
801
781
  elementState,
802
782
  indexState
803
783
  });
804
784
  node.needExecutedVersion = true;
805
- elementsByKey[calculatedKey] = {
785
+ elementsByKey.set(calculatedKey, {
806
786
  node,
807
787
  indexState,
808
788
  indexValue: index,
809
789
  elementState
810
- };
790
+ });
811
791
  children.push([
812
792
  node,
813
793
  calculatedKey,
@@ -824,7 +804,7 @@ function createStateFromCore(core, subscribeCallback) {
824
804
  });
825
805
  return createElement("div", {
826
806
  phantom: true,
827
- children: children.map((child) => child[0])
807
+ children: [...children.map((child) => child[0]), anchor]
828
808
  });
829
809
  });
830
810
  wrapperComponent.needExecutedVersion = true;
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require__utils = require("./_utils-DbrPydEE.cjs");
2
+ const require__utils = require("./_utils-CXVRQTuz.cjs");
3
3
  exports.Fragment = require__utils.Fragment;
4
4
  exports.jsx = require__utils.createElement;
5
5
  exports.jsxDEV = require__utils.createElement;
@@ -1,2 +1,2 @@
1
- import { c as JSX, n as createElement, t as Fragment } from "./fragment-C16zCm8L.cjs";
1
+ import { c as JSX, n as createElement, t as Fragment } from "./fragment-COsp_SDE.cjs";
2
2
  export { Fragment, type JSX, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,2 @@
1
- import { c as JSX, n as createElement, t as Fragment } from "./fragment-yC0-T2O-.js";
1
+ import { c as JSX, n as createElement, t as Fragment } from "./fragment-CPcYB5D5.js";
2
2
  export { Fragment, type JSX, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,2 @@
1
- import { f as Fragment, p as createElement } from "./_utils-BnAXelPu.js";
1
+ import { m as createElement, p as Fragment } from "./_utils-B1lbF1Al.js";
2
2
  export { Fragment, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veles",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "UI library with main focus on performance",
5
5
  "keywords": [
6
6
  "JavaScript",