native-document 1.0.114 → 1.0.116

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.
@@ -1,10 +1,10 @@
1
1
  var NativeDocument = (function (exports) {
2
2
  'use strict';
3
3
 
4
- let DebugManager$1 = {};
4
+ let DebugManager = {};
5
5
 
6
6
  {
7
- DebugManager$1 = {
7
+ DebugManager = {
8
8
  enabled: false,
9
9
 
10
10
  enable() {
@@ -35,7 +35,7 @@ var NativeDocument = (function (exports) {
35
35
  };
36
36
 
37
37
  }
38
- var DebugManager = DebugManager$1;
38
+ var DebugManager$1 = DebugManager;
39
39
 
40
40
  class NativeDocumentError extends Error {
41
41
  constructor(message, context = {}) {
@@ -313,10 +313,10 @@ var NativeDocument = (function (exports) {
313
313
  subtree: true,
314
314
  });
315
315
 
316
- let PluginsManager$1 = null;
316
+ let PluginsManager = null;
317
317
 
318
318
  {
319
- PluginsManager$1 = (function() {
319
+ PluginsManager = (function() {
320
320
 
321
321
  const $plugins = new Map();
322
322
  const $pluginByEvents = new Map();
@@ -382,7 +382,7 @@ var NativeDocument = (function (exports) {
382
382
  try{
383
383
  callback.call(plugin, ...data);
384
384
  } catch (error) {
385
- DebugManager.error('Plugin Manager', `Error in plugin ${plugin.$name} for event ${eventName}`, error);
385
+ DebugManager$1.error('Plugin Manager', `Error in plugin ${plugin.$name} for event ${eventName}`, error);
386
386
  }
387
387
  }
388
388
  }
@@ -391,12 +391,12 @@ var NativeDocument = (function (exports) {
391
391
  }());
392
392
  }
393
393
 
394
- var PluginsManager = PluginsManager$1;
394
+ var PluginsManager$1 = PluginsManager;
395
395
 
396
396
  function NDElement(element) {
397
397
  this.$element = element;
398
398
  {
399
- PluginsManager.emit('NDElementCreated', element, this);
399
+ PluginsManager$1.emit('NDElementCreated', element, this);
400
400
  }
401
401
  }
402
402
 
@@ -528,21 +528,6 @@ var NativeDocument = (function (exports) {
528
528
  return this.shadow('closed', style);
529
529
  };
530
530
 
531
- /**
532
- * Attaches a template binding to the element by hydrating it with the specified method.
533
- *
534
- * @param {string} methodName - Name of the hydration method to call
535
- * @param {BindingHydrator} bindingHydrator - Template binding with $hydrate method
536
- * @returns {HTMLElement} The underlying HTML element
537
- * @example
538
- * const onClick = $binder.attach((event, data) => console.log(data));
539
- * element.nd.attach('onClick', onClick);
540
- */
541
- NDElement.prototype.attach = function(methodName, bindingHydrator) {
542
- bindingHydrator.$hydrate(this.$element, methodName);
543
- return this.$element;
544
- };
545
-
546
531
  /**
547
532
  * Extends the current NDElement instance with custom methods.
548
533
  * Methods are bound to the instance and available for chaining.
@@ -576,7 +561,7 @@ var NativeDocument = (function (exports) {
576
561
  }
577
562
  {
578
563
  if (this[name] && !this.$localExtensions.has(name)) {
579
- DebugManager.warn('NDElement.extend', `Method "${name}" already exists and will be overwritten`);
564
+ DebugManager$1.warn('NDElement.extend', `Method "${name}" already exists and will be overwritten`);
580
565
  }
581
566
  this.$localExtensions.set(name, method);
582
567
  }
@@ -627,23 +612,23 @@ var NativeDocument = (function (exports) {
627
612
  const method = methods[name];
628
613
 
629
614
  if (typeof method !== 'function') {
630
- DebugManager.warn('NDElement.extend', `"${name}" is not a function, skipping`);
615
+ DebugManager$1.warn('NDElement.extend', `"${name}" is not a function, skipping`);
631
616
  continue;
632
617
  }
633
618
 
634
619
  if (protectedMethods.has(name)) {
635
- DebugManager.error('NDElement.extend', `Cannot override protected method "${name}"`);
620
+ DebugManager$1.error('NDElement.extend', `Cannot override protected method "${name}"`);
636
621
  throw new NativeDocumentError(`Cannot override protected method "${name}"`);
637
622
  }
638
623
 
639
624
  if (NDElement.prototype[name]) {
640
- DebugManager.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
625
+ DebugManager$1.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
641
626
  }
642
627
 
643
628
  NDElement.prototype[name] = method;
644
629
  }
645
630
  {
646
- PluginsManager.emit('NDElementExtended', methods);
631
+ PluginsManager$1.emit('NDElementExtended', methods);
647
632
  }
648
633
 
649
634
  return NDElement;
@@ -794,171 +779,13 @@ var NativeDocument = (function (exports) {
794
779
  const foundReserved = Object.keys(attributes).filter(key => reserved.includes(key));
795
780
 
796
781
  if (foundReserved.length > 0) {
797
- DebugManager.warn('Validator', `Reserved attributes found: ${foundReserved.join(', ')}`);
782
+ DebugManager$1.warn('Validator', `Reserved attributes found: ${foundReserved.join(', ')}`);
798
783
  }
799
784
 
800
785
  return attributes;
801
786
  };
802
787
  }
803
788
 
804
- function Anchor(name, isUniqueChild = false) {
805
- const anchorFragment = document.createDocumentFragment();
806
- anchorFragment.__Anchor__ = true;
807
-
808
- const anchorStart = document.createComment('Anchor Start : '+name);
809
- const anchorEnd = document.createComment('/ Anchor End '+name);
810
-
811
- anchorFragment.appendChild(anchorStart);
812
- anchorFragment.appendChild(anchorEnd);
813
-
814
- anchorFragment.nativeInsertBefore = anchorFragment.insertBefore;
815
- anchorFragment.nativeAppendChild = anchorFragment.appendChild;
816
- anchorFragment.nativeAppend = anchorFragment.append;
817
-
818
- const isParentUniqueChild = isUniqueChild
819
- ? () => true
820
- : (parent) => (parent.firstChild === anchorStart && parent.lastChild === anchorEnd);
821
-
822
- const insertBefore = function(parent, child, target) {
823
- const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
824
- if(parent === anchorFragment) {
825
- parent.nativeInsertBefore(childElement, target);
826
- return;
827
- }
828
- if(isParentUniqueChild(parent) && target === anchorEnd) {
829
- parent.append(childElement, target);
830
- return;
831
- }
832
- parent.insertBefore(childElement, target);
833
- };
834
-
835
- anchorFragment.appendElement = function(child, before = null) {
836
- const parentNode = anchorStart.parentNode;
837
- const targetBefore = before || anchorEnd;
838
- if(parentNode === anchorFragment) {
839
- parentNode.nativeInsertBefore(child, targetBefore);
840
- return;
841
- }
842
- parentNode?.insertBefore(child, targetBefore);
843
- };
844
-
845
- anchorFragment.appendChild = function(child, before = null) {
846
- const parent = anchorEnd.parentNode;
847
- if(!parent) {
848
- DebugManager.error('Anchor', 'Anchor : parent not found', child);
849
- return;
850
- }
851
- before = before ?? anchorEnd;
852
- insertBefore(parent, child, before);
853
- };
854
-
855
- anchorFragment.append = function(...args ) {
856
- return anchorFragment.appendChild(args);
857
- };
858
-
859
- anchorFragment.removeChildren = function() {
860
- const parent = anchorEnd.parentNode;
861
- if(parent === anchorFragment) {
862
- return;
863
- }
864
- if(isParentUniqueChild(parent)) {
865
- parent.replaceChildren(anchorStart, anchorEnd);
866
- return;
867
- }
868
-
869
- let itemToRemove = anchorStart.nextSibling, tempItem;
870
- while(itemToRemove && itemToRemove !== anchorEnd) {
871
- tempItem = itemToRemove.nextSibling;
872
- itemToRemove.remove();
873
- itemToRemove = tempItem;
874
- }
875
- };
876
-
877
- anchorFragment.remove = function() {
878
- const parent = anchorEnd.parentNode;
879
- if(parent === anchorFragment) {
880
- return;
881
- }
882
- if(isParentUniqueChild(parent)) {
883
- parent.replaceChildren(anchorStart, anchorEnd);
884
- return;
885
- }
886
- let itemToRemove = anchorStart.nextSibling, tempItem;
887
- while(itemToRemove && itemToRemove !== anchorEnd) {
888
- tempItem = itemToRemove.nextSibling;
889
- anchorFragment.nativeAppend(itemToRemove);
890
- itemToRemove = tempItem;
891
- }
892
- };
893
-
894
- anchorFragment.removeWithAnchors = function() {
895
- anchorFragment.removeChildren();
896
- anchorStart.remove();
897
- anchorEnd.remove();
898
- };
899
-
900
- anchorFragment.replaceContent = function(child) {
901
- const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
902
- const parent = anchorEnd.parentNode;
903
- if(!parent) {
904
- return;
905
- }
906
- if(isParentUniqueChild(parent)) {
907
- parent.replaceChildren(anchorStart, childElement, anchorEnd);
908
- return;
909
- }
910
- anchorFragment.removeChildren();
911
- parent.insertBefore(childElement, anchorEnd);
912
- };
913
-
914
- anchorFragment.setContent = anchorFragment.replaceContent;
915
-
916
- anchorFragment.insertBefore = function(child, anchor = null) {
917
- anchorFragment.appendChild(child, anchor);
918
- };
919
-
920
- anchorFragment.endElement = function() {
921
- return anchorEnd;
922
- };
923
-
924
- anchorFragment.startElement = function() {
925
- return anchorStart;
926
- };
927
- anchorFragment.restore = function() {
928
- anchorFragment.appendChild(anchorFragment);
929
- };
930
- anchorFragment.clear = anchorFragment.remove;
931
- anchorFragment.detach = anchorFragment.remove;
932
-
933
- anchorFragment.getByIndex = function(index) {
934
- let currentNode = anchorStart;
935
- for(let i = 0; i <= index; i++) {
936
- if(!currentNode.nextSibling) {
937
- return null;
938
- }
939
- currentNode = currentNode.nextSibling;
940
- }
941
- return currentNode !== anchorStart ? currentNode : null;
942
- };
943
-
944
- return anchorFragment;
945
- }
946
- /**
947
- *
948
- * @param {HTMLElement|DocumentFragment|Text|String|Array} children
949
- * @param {{ parent?: HTMLElement, name?: String}} configs
950
- * @returns {DocumentFragment}
951
- */
952
- function createPortal(children, { parent, name = 'unnamed' } = {}) {
953
- const anchor = Anchor('Portal '+name);
954
- anchor.appendChild(ElementCreator.getChild(children));
955
-
956
- (parent || document.body).appendChild(anchor);
957
- return anchor;
958
- }
959
-
960
- DocumentFragment.prototype.setAttribute = () => {};
961
-
962
789
  const BOOLEAN_ATTRIBUTES = new Set([
963
790
  'checked',
964
791
  'selected',
@@ -1039,7 +866,7 @@ var NativeDocument = (function (exports) {
1039
866
  }
1040
867
  }
1041
868
  if (cleanedCount > 0) {
1042
- DebugManager.log('Memory Auto Clean', `🧹 Cleaned ${cleanedCount} orphaned observables`);
869
+ DebugManager$1.log('Memory Auto Clean', `🧹 Cleaned ${cleanedCount} orphaned observables`);
1043
870
  }
1044
871
  }
1045
872
  };
@@ -1241,7 +1068,7 @@ var NativeDocument = (function (exports) {
1241
1068
  const $getStoreOrThrow = (method, name) => {
1242
1069
  const item = $stores.get(name);
1243
1070
  if (!item) {
1244
- DebugManager.error('Store', `Store.${method}('${name}') : store not found. Did you call Store.create('${name}') first?`);
1071
+ DebugManager$1.error('Store', `Store.${method}('${name}') : store not found. Did you call Store.create('${name}') first?`);
1245
1072
  throw new NativeDocumentError(
1246
1073
  `Store.${method}('${name}') : store not found.`
1247
1074
  );
@@ -1254,7 +1081,7 @@ var NativeDocument = (function (exports) {
1254
1081
  */
1255
1082
  const $applyReadOnly = (observer, name, context) => {
1256
1083
  const readOnlyError = (method) => () => {
1257
- DebugManager.error('Store', `Store.${context}('${name}') is read-only. '${method}()' is not allowed.`);
1084
+ DebugManager$1.error('Store', `Store.${context}('${name}') is read-only. '${method}()' is not allowed.`);
1258
1085
  throw new NativeDocumentError(
1259
1086
  `Store.${context}('${name}') is read-only.`
1260
1087
  );
@@ -1285,7 +1112,7 @@ var NativeDocument = (function (exports) {
1285
1112
  */
1286
1113
  create(name, value) {
1287
1114
  if ($stores.has(name)) {
1288
- DebugManager.warn('Store', `Store.create('${name}') : a store with this name already exists. Use Store.get('${name}') to retrieve it.`);
1115
+ DebugManager$1.warn('Store', `Store.create('${name}') : a store with this name already exists. Use Store.get('${name}') to retrieve it.`);
1289
1116
  throw new NativeDocumentError(
1290
1117
  `Store.create('${name}') : a store with this name already exists.`
1291
1118
  );
@@ -1306,7 +1133,7 @@ var NativeDocument = (function (exports) {
1306
1133
  */
1307
1134
  createResettable(name, value) {
1308
1135
  if ($stores.has(name)) {
1309
- DebugManager.warn('Store', `Store.createResettable('${name}') : a store with this name already exists.`);
1136
+ DebugManager$1.warn('Store', `Store.createResettable('${name}') : a store with this name already exists.`);
1310
1137
  throw new NativeDocumentError(
1311
1138
  `Store.createResettable('${name}') : a store with this name already exists.`
1312
1139
  );
@@ -1342,7 +1169,7 @@ var NativeDocument = (function (exports) {
1342
1169
  */
1343
1170
  createComposed(name, computation, dependencies) {
1344
1171
  if ($stores.has(name)) {
1345
- DebugManager.warn('Store', `Store.createComposed('${name}') : a store with this name already exists.`);
1172
+ DebugManager$1.warn('Store', `Store.createComposed('${name}') : a store with this name already exists.`);
1346
1173
  throw new NativeDocumentError(
1347
1174
  `Store.createComposed('${name}') : a store with this name already exists.`
1348
1175
  );
@@ -1365,7 +1192,7 @@ var NativeDocument = (function (exports) {
1365
1192
  }
1366
1193
  const depItem = $stores.get(depName);
1367
1194
  if (!depItem) {
1368
- DebugManager.error('Store', `Store.createComposed('${name}') : dependency '${depName}' not found. Create it first.`);
1195
+ DebugManager$1.error('Store', `Store.createComposed('${name}') : dependency '${depName}' not found. Create it first.`);
1369
1196
  throw new NativeDocumentError(
1370
1197
  `Store.createComposed('${name}') : dependency store '${depName}' not found.`
1371
1198
  );
@@ -1399,13 +1226,13 @@ var NativeDocument = (function (exports) {
1399
1226
  reset(name) {
1400
1227
  const item = $getStoreOrThrow('reset', name);
1401
1228
  if (item.composed) {
1402
- DebugManager.error('Store', `Store.reset('${name}') : composed stores cannot be reset. Their value is derived from dependencies.`);
1229
+ DebugManager$1.error('Store', `Store.reset('${name}') : composed stores cannot be reset. Their value is derived from dependencies.`);
1403
1230
  throw new NativeDocumentError(
1404
1231
  `Store.reset('${name}') : composed stores cannot be reset.`
1405
1232
  );
1406
1233
  }
1407
1234
  if (!item.resettable) {
1408
- DebugManager.error('Store', `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`);
1235
+ DebugManager$1.error('Store', `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`);
1409
1236
  throw new NativeDocumentError(
1410
1237
  `Store.reset('${name}') : this store is not resettable. Use Store.createResettable('${name}', value) instead of Store.create().`
1411
1238
  );
@@ -1426,7 +1253,7 @@ var NativeDocument = (function (exports) {
1426
1253
  const item = $getStoreOrThrow('use', name);
1427
1254
 
1428
1255
  if (item.composed) {
1429
- DebugManager.error('Store', `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`);
1256
+ DebugManager$1.error('Store', `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`);
1430
1257
  throw new NativeDocumentError(
1431
1258
  `Store.use('${name}') : composed stores are read-only. Use Store.follow('${name}') instead.`
1432
1259
  );
@@ -1493,7 +1320,7 @@ var NativeDocument = (function (exports) {
1493
1320
  get(name) {
1494
1321
  const item = $stores.get(name);
1495
1322
  if (!item) {
1496
- DebugManager.warn('Store', `Store.get('${name}') : store not found.`);
1323
+ DebugManager$1.warn('Store', `Store.get('${name}') : store not found.`);
1497
1324
  return null;
1498
1325
  }
1499
1326
  return item.observer;
@@ -1515,7 +1342,7 @@ var NativeDocument = (function (exports) {
1515
1342
  delete(name) {
1516
1343
  const item = $stores.get(name);
1517
1344
  if (!item) {
1518
- DebugManager.warn('Store', `Store.delete('${name}') : store not found, nothing to delete.`);
1345
+ DebugManager$1.warn('Store', `Store.delete('${name}') : store not found, nothing to delete.`);
1519
1346
  return;
1520
1347
  }
1521
1348
  item.subscribers.forEach(follower => follower.destroy());
@@ -1617,7 +1444,7 @@ var NativeDocument = (function (exports) {
1617
1444
  return undefined;
1618
1445
  },
1619
1446
  set(target, prop, value) {
1620
- DebugManager.error('Store', `Forbidden: You cannot overwrite the store key '${String(prop)}'. Use .use('${String(prop)}').set(value) instead.`);
1447
+ DebugManager$1.error('Store', `Forbidden: You cannot overwrite the store key '${String(prop)}'. Use .use('${String(prop)}').set(value) instead.`);
1621
1448
  throw new NativeDocumentError(`Store structure is immutable. Use .set() on the observable.`);
1622
1449
  },
1623
1450
  deleteProperty(target, prop) {
@@ -1749,7 +1576,7 @@ var NativeDocument = (function (exports) {
1749
1576
  }
1750
1577
  }
1751
1578
  {
1752
- PluginsManager.emit('CreateObservable', this);
1579
+ PluginsManager$1.emit('CreateObservable', this);
1753
1580
  }
1754
1581
  }
1755
1582
 
@@ -1853,12 +1680,12 @@ var NativeDocument = (function (exports) {
1853
1680
  this.$previousValue = this.$currentValue;
1854
1681
  this.$currentValue = newValue;
1855
1682
  {
1856
- PluginsManager.emit('ObservableBeforeChange', this);
1683
+ PluginsManager$1.emit('ObservableBeforeChange', this);
1857
1684
  }
1858
1685
  this.trigger();
1859
1686
  this.$previousValue = null;
1860
1687
  {
1861
- PluginsManager.emit('ObservableAfterChange', this);
1688
+ PluginsManager$1.emit('ObservableAfterChange', this);
1862
1689
  }
1863
1690
  };
1864
1691
 
@@ -1936,7 +1763,7 @@ var NativeDocument = (function (exports) {
1936
1763
  ObservableItem.prototype.subscribe = function(callback) {
1937
1764
  {
1938
1765
  if (this.$isCleanedUp) {
1939
- DebugManager.warn('Observable subscription', '⚠️ Attempted to subscribe to a cleaned up observable.');
1766
+ DebugManager$1.warn('Observable subscription', '⚠️ Attempted to subscribe to a cleaned up observable.');
1940
1767
  return;
1941
1768
  }
1942
1769
  if (typeof callback !== 'function') {
@@ -1948,7 +1775,7 @@ var NativeDocument = (function (exports) {
1948
1775
  this.$listeners.push(callback);
1949
1776
  this.assocTrigger();
1950
1777
  {
1951
- PluginsManager.emit('ObservableSubscribe', this);
1778
+ PluginsManager$1.emit('ObservableSubscribe', this);
1952
1779
  }
1953
1780
  };
1954
1781
 
@@ -2059,7 +1886,7 @@ var NativeDocument = (function (exports) {
2059
1886
  }
2060
1887
  this.assocTrigger();
2061
1888
  {
2062
- PluginsManager.emit('ObservableUnsubscribe', this);
1889
+ PluginsManager$1.emit('ObservableUnsubscribe', this);
2063
1890
  }
2064
1891
  };
2065
1892
 
@@ -2535,7 +2362,7 @@ var NativeDocument = (function (exports) {
2535
2362
  Function.prototype.toNdElement = function () {
2536
2363
  const child = this;
2537
2364
  {
2538
- PluginsManager.emit('BeforeProcessComponent', child);
2365
+ PluginsManager$1.emit('BeforeProcessComponent', child);
2539
2366
  }
2540
2367
  return ElementCreator.getChild(child());
2541
2368
  };
@@ -2647,7 +2474,6 @@ var NativeDocument = (function (exports) {
2647
2474
  this.$hydrate(element, attributeName);
2648
2475
  };
2649
2476
 
2650
- const $nodeCache = new Map();
2651
2477
  let $textNodeCache = null;
2652
2478
 
2653
2479
  const ElementCreator = {
@@ -2677,7 +2503,7 @@ var NativeDocument = (function (exports) {
2677
2503
  * @param {{$hydrate: Function}} item
2678
2504
  * @returns {Text}
2679
2505
  */
2680
- createHydratableNode(parent, item) {
2506
+ createHydratableNode: (parent, item) => {
2681
2507
  const text = ElementCreator.createTextNode();
2682
2508
  item.$hydrate(text);
2683
2509
  return text;
@@ -2689,7 +2515,7 @@ var NativeDocument = (function (exports) {
2689
2515
  * @param {*} value
2690
2516
  * @returns {Text}
2691
2517
  */
2692
- createStaticTextNode(parent, value) {
2518
+ createStaticTextNode: (parent, value) => {
2693
2519
  let text = ElementCreator.createTextNode();
2694
2520
  text.nodeValue = value;
2695
2521
  parent && parent.appendChild(text);
@@ -2701,15 +2527,10 @@ var NativeDocument = (function (exports) {
2701
2527
  * @returns {HTMLElement|DocumentFragment}
2702
2528
  */
2703
2529
  createElement: (name) => {
2704
- if(name) {
2705
- const cacheNode = $nodeCache.get(name);
2706
- if(cacheNode) {
2707
- return cacheNode.cloneNode();
2708
- }
2709
- const node = document.createElement(name);
2710
- $nodeCache.set(name, node);
2711
- return node.cloneNode();
2712
- }
2530
+ const node = document.createElement(name);
2531
+ return node.cloneNode();
2532
+ },
2533
+ createFragment: (name) => {
2713
2534
  return Anchor('Fragment');
2714
2535
  },
2715
2536
  bindTextNode: (textNode, value) => {
@@ -2725,17 +2546,17 @@ var NativeDocument = (function (exports) {
2725
2546
  * @param {*} children
2726
2547
  * @param {HTMLElement|DocumentFragment} parent
2727
2548
  */
2728
- processChildren(children, parent) {
2549
+ processChildren: (children, parent) => {
2729
2550
  if(children === null) return;
2730
2551
  {
2731
- PluginsManager.emit('BeforeProcessChildren', parent);
2552
+ PluginsManager$1.emit('BeforeProcessChildren', parent);
2732
2553
  }
2733
- let child = this.getChild(children);
2554
+ let child = ElementCreator.getChild(children);
2734
2555
  if(child) {
2735
2556
  parent.appendChild(child);
2736
2557
  }
2737
2558
  {
2738
- PluginsManager.emit('AfterProcessChildren', parent);
2559
+ PluginsManager$1.emit('AfterProcessChildren', parent);
2739
2560
  }
2740
2561
  },
2741
2562
  async safeRemove(element) {
@@ -2777,6 +2598,164 @@ var NativeDocument = (function (exports) {
2777
2598
  processStyleAttribute: bindStyleAttribute,
2778
2599
  };
2779
2600
 
2601
+ function Anchor(name, isUniqueChild = false) {
2602
+ const anchorFragment = document.createDocumentFragment();
2603
+ anchorFragment.__Anchor__ = true;
2604
+
2605
+ const anchorStart = document.createComment('Anchor Start : '+name);
2606
+ const anchorEnd = document.createComment('/ Anchor End '+name);
2607
+
2608
+ anchorFragment.appendChild(anchorStart);
2609
+ anchorFragment.appendChild(anchorEnd);
2610
+
2611
+ anchorFragment.nativeInsertBefore = anchorFragment.insertBefore;
2612
+ anchorFragment.nativeAppendChild = anchorFragment.appendChild;
2613
+ anchorFragment.nativeAppend = anchorFragment.append;
2614
+
2615
+ const isParentUniqueChild = isUniqueChild
2616
+ ? () => true
2617
+ : (parent) => (parent.firstChild === anchorStart && parent.lastChild === anchorEnd);
2618
+
2619
+ const insertBefore = function(parent, child, target) {
2620
+ const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2621
+ if(parent === anchorFragment) {
2622
+ parent.nativeInsertBefore(childElement, target);
2623
+ return;
2624
+ }
2625
+ if(isParentUniqueChild(parent) && target === anchorEnd) {
2626
+ parent.append(childElement, target);
2627
+ return;
2628
+ }
2629
+ parent.insertBefore(childElement, target);
2630
+ };
2631
+
2632
+ anchorFragment.appendElement = function(child, before = null) {
2633
+ const parentNode = anchorStart.parentNode;
2634
+ const targetBefore = before || anchorEnd;
2635
+ if(parentNode === anchorFragment) {
2636
+ parentNode.nativeInsertBefore(child, targetBefore);
2637
+ return;
2638
+ }
2639
+ parentNode?.insertBefore(child, targetBefore);
2640
+ };
2641
+
2642
+ anchorFragment.appendChild = function(child, before = null) {
2643
+ const parent = anchorEnd.parentNode;
2644
+ if(!parent) {
2645
+ DebugManager$1.error('Anchor', 'Anchor : parent not found', child);
2646
+ return;
2647
+ }
2648
+ before = before ?? anchorEnd;
2649
+ insertBefore(parent, child, before);
2650
+ };
2651
+
2652
+ anchorFragment.append = function(...args ) {
2653
+ return anchorFragment.appendChild(args);
2654
+ };
2655
+
2656
+ anchorFragment.removeChildren = function() {
2657
+ const parent = anchorEnd.parentNode;
2658
+ if(parent === anchorFragment) {
2659
+ return;
2660
+ }
2661
+ if(isParentUniqueChild(parent)) {
2662
+ parent.replaceChildren(anchorStart, anchorEnd);
2663
+ return;
2664
+ }
2665
+
2666
+ let itemToRemove = anchorStart.nextSibling, tempItem;
2667
+ while(itemToRemove && itemToRemove !== anchorEnd) {
2668
+ tempItem = itemToRemove.nextSibling;
2669
+ itemToRemove.remove();
2670
+ itemToRemove = tempItem;
2671
+ }
2672
+ };
2673
+
2674
+ anchorFragment.remove = function() {
2675
+ const parent = anchorEnd.parentNode;
2676
+ if(parent === anchorFragment) {
2677
+ return;
2678
+ }
2679
+ if(isParentUniqueChild(parent)) {
2680
+ parent.replaceChildren(anchorStart, anchorEnd);
2681
+ return;
2682
+ }
2683
+ let itemToRemove = anchorStart.nextSibling, tempItem;
2684
+ while(itemToRemove && itemToRemove !== anchorEnd) {
2685
+ tempItem = itemToRemove.nextSibling;
2686
+ anchorFragment.nativeAppend(itemToRemove);
2687
+ itemToRemove = tempItem;
2688
+ }
2689
+ };
2690
+
2691
+ anchorFragment.removeWithAnchors = function() {
2692
+ anchorFragment.removeChildren();
2693
+ anchorStart.remove();
2694
+ anchorEnd.remove();
2695
+ };
2696
+
2697
+ anchorFragment.replaceContent = function(child) {
2698
+ const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2699
+ const parent = anchorEnd.parentNode;
2700
+ if(!parent) {
2701
+ return;
2702
+ }
2703
+ if(isParentUniqueChild(parent)) {
2704
+ parent.replaceChildren(anchorStart, childElement, anchorEnd);
2705
+ return;
2706
+ }
2707
+ anchorFragment.removeChildren();
2708
+ parent.insertBefore(childElement, anchorEnd);
2709
+ };
2710
+
2711
+ anchorFragment.setContent = anchorFragment.replaceContent;
2712
+
2713
+ anchorFragment.insertBefore = function(child, anchor = null) {
2714
+ anchorFragment.appendChild(child, anchor);
2715
+ };
2716
+
2717
+ anchorFragment.endElement = function() {
2718
+ return anchorEnd;
2719
+ };
2720
+
2721
+ anchorFragment.startElement = function() {
2722
+ return anchorStart;
2723
+ };
2724
+ anchorFragment.restore = function() {
2725
+ anchorFragment.appendChild(anchorFragment);
2726
+ };
2727
+ anchorFragment.clear = anchorFragment.remove;
2728
+ anchorFragment.detach = anchorFragment.remove;
2729
+
2730
+ anchorFragment.getByIndex = function(index) {
2731
+ let currentNode = anchorStart;
2732
+ for(let i = 0; i <= index; i++) {
2733
+ if(!currentNode.nextSibling) {
2734
+ return null;
2735
+ }
2736
+ currentNode = currentNode.nextSibling;
2737
+ }
2738
+ return currentNode !== anchorStart ? currentNode : null;
2739
+ };
2740
+
2741
+ return anchorFragment;
2742
+ }
2743
+ /**
2744
+ *
2745
+ * @param {HTMLElement|DocumentFragment|Text|String|Array} children
2746
+ * @param {{ parent?: HTMLElement, name?: String}} configs
2747
+ * @returns {DocumentFragment}
2748
+ */
2749
+ function createPortal(children, { parent, name = 'unnamed' } = {}) {
2750
+ const anchor = Anchor('Portal '+name);
2751
+ anchor.appendChild(ElementCreator.getChild(children));
2752
+
2753
+ (parent || document.body).appendChild(anchor);
2754
+ return anchor;
2755
+ }
2756
+
2757
+ DocumentFragment.prototype.setAttribute = () => {};
2758
+
2780
2759
  const EVENTS = [
2781
2760
  "Click",
2782
2761
  "DblClick",
@@ -2926,16 +2905,16 @@ var NativeDocument = (function (exports) {
2926
2905
  "ContextMenu"
2927
2906
  ];
2928
2907
 
2929
- const property = {
2908
+ const property$1 = {
2930
2909
  configurable: true,
2931
2910
  get() {
2932
2911
  return new NDElement(this);
2933
2912
  }
2934
2913
  };
2935
2914
 
2936
- Object.defineProperty(HTMLElement.prototype, 'nd', property);
2915
+ Object.defineProperty(HTMLElement.prototype, 'nd', property$1);
2937
2916
 
2938
- Object.defineProperty(DocumentFragment.prototype, 'nd', property);
2917
+ Object.defineProperty(DocumentFragment.prototype, 'nd', property$1);
2939
2918
 
2940
2919
  Object.defineProperty(NDElement.prototype, 'nd', {
2941
2920
  configurable: true,
@@ -3180,7 +3159,10 @@ var NativeDocument = (function (exports) {
3180
3159
  }
3181
3160
 
3182
3161
  const normalizeComponentArgs = function(props, children = null) {
3183
- if(Array.isArray(props) || typeof props !== 'object' || props === null || props.constructor.name !== 'Object' || props.$hydrate) { // IF it's not a JSON
3162
+ if(props && children) {
3163
+ return { props, children };
3164
+ }
3165
+ if(typeof props !== 'object' || Array.isArray(props) || props === null || props.constructor.name !== 'Object' || props.$hydrate) { // IF it's not a JSON
3184
3166
  return { props: children, children: props }
3185
3167
  }
3186
3168
  return { props, children };
@@ -3191,22 +3173,20 @@ var NativeDocument = (function (exports) {
3191
3173
  * @param {*} value
3192
3174
  * @returns {Text}
3193
3175
  */
3194
- const createTextNode = function(value) {
3176
+ const createTextNode = (value) => {
3195
3177
  return (Validator.isObservable(value))
3196
3178
  ? ElementCreator.createObservableNode(null, value)
3197
3179
  : ElementCreator.createStaticTextNode(null, value);
3198
3180
  };
3199
3181
 
3200
3182
 
3201
- function createHtmlElement($tagName, customWrapper, _attributes, _children = null) {
3183
+ const createHtmlElement = (element, _attributes, _children = null) => {
3202
3184
  let { props: attributes, children = null } = normalizeComponentArgs(_attributes, _children);
3203
- let element = ElementCreator.createElement($tagName);
3204
- let finalElement = (customWrapper && typeof customWrapper === 'function') ? customWrapper(element) : element;
3205
3185
 
3206
- ElementCreator.processAttributes(finalElement, attributes);
3207
- ElementCreator.processChildren(children, finalElement);
3208
- return finalElement;
3209
- }
3186
+ ElementCreator.processAttributes(element, attributes);
3187
+ ElementCreator.processChildren(children, element);
3188
+ return element;
3189
+ };
3210
3190
 
3211
3191
  /**
3212
3192
  *
@@ -3215,341 +3195,241 @@ var NativeDocument = (function (exports) {
3215
3195
  * @returns {Function}
3216
3196
  */
3217
3197
  function HtmlElementWrapper(name, customWrapper = null) {
3218
- return createHtmlElement.bind(null, name, customWrapper);
3219
- }
3220
-
3221
- const cloneBindingsDataCache = new WeakMap();
3198
+ if(name) {
3199
+ if(customWrapper) {
3200
+ let node = null;
3201
+ let createElement = (attr, children) => {
3202
+ node = document.createElement(name);
3203
+ createElement = (attr, children) => {
3204
+ return createHtmlElement(customWrapper(node.cloneNode()), attr, children);
3205
+ };
3206
+ return createHtmlElement(customWrapper(node.cloneNode()), attr, children); };
3207
+
3208
+ return (attr, children) => createElement(attr, children)
3209
+ }
3210
+
3211
+ let node = null;
3212
+ let createElement = (attr, children) => {
3213
+ node = document.createElement(name);
3214
+ createElement = (attr, children) => {
3215
+ return createHtmlElement(node.cloneNode(), attr, children);
3216
+ };
3217
+ return createHtmlElement(node.cloneNode(), attr, children);
3218
+ };
3222
3219
 
3223
- const pathProcess = (target, path, data) => {
3224
- if(path.HYDRATE_TEXT) {
3225
- const value = path.value;
3226
- ElementCreator.bindTextNode(target, path.isString ? data[0][value] : value.apply(null, data));
3227
- return;
3228
- }
3229
- if(path.ATTACH_METHOD) {
3230
- const bindingData = path.bindingData;
3231
- for(let i = 0, length = bindingData._attachLength; i < length; i++) {
3232
- const method = bindingData.attach[i];
3233
- target.nd[method.methodName](function() {
3234
- method.fn.call(this, ...data, ...arguments);
3235
- });
3236
- }
3237
- }
3238
- if(path.HYDRATE_ATTRIBUTES) {
3239
- path.hydrator(target, path.bindingData, data);
3220
+ return (attr, children) => createElement(attr, children)
3240
3221
  }
3241
- };
3242
-
3243
- const buildAttributesCache = (bindDingData) => {
3244
- const cache = { };
3245
- if(bindDingData.attributes) cache.attributes = {};
3246
- if(bindDingData.classes) cache.class = {};
3247
- if(bindDingData.styles) cache.style = {};
3248
- bindDingData._cache = cache;
3249
- };
3250
-
3251
- const prepareBindingMetadata = (bindDingData) => {
3252
- const attributes = [];
3253
- const classAndStyles = [];
3222
+ return () => Anchor('');
3223
+ }
3254
3224
 
3255
- if(bindDingData.attributes) {
3256
- for (const attr in bindDingData.attributes) {
3257
- attributes.push({
3258
- name: attr,
3259
- value: bindDingData.attributes[attr]
3260
- });
3261
- }
3262
- }
3225
+ function NodeCloner($element) {
3226
+ this.$element = $element;
3227
+ this.$classes = null;
3228
+ this.$styles = null;
3229
+ this.$attrs = null;
3230
+ this.$ndMethods = null;
3231
+ }
3263
3232
 
3264
- if(bindDingData.classes) {
3265
- for (const className in bindDingData.classes) {
3266
- bindDingData._hasClassAttribute = true;
3267
- classAndStyles.push({
3268
- name: 'class',
3269
- key: className,
3270
- value: bindDingData.classes[className]
3271
- });
3272
- }
3273
- }
3274
3233
 
3275
- if(bindDingData.styles) {
3276
- for (const property in bindDingData.styles) {
3277
- bindDingData._hasStyleAttribute = true;
3278
- classAndStyles.push({
3279
- name: 'style',
3280
- key: property,
3281
- value: bindDingData.styles[property]
3282
- });
3283
- }
3234
+ /**
3235
+ * Attaches a template binding to the element by hydrating it with the specified method.
3236
+ *
3237
+ * @param {string} methodName - Name of the hydration method to call
3238
+ * @param {BindingHydrator} bindingHydrator - Template binding with $hydrate method
3239
+ * @returns {HTMLElement} The underlying HTML element
3240
+ * @example
3241
+ * const onClick = $binder.attach((event, data) => console.log(data));
3242
+ * element.nd.attach('onClick', onClick);
3243
+ */
3244
+ NDElement.prototype.attach = function(methodName, bindingHydrator) {
3245
+ if(typeof bindingHydrator === 'function') {
3246
+ const element = this.$element;
3247
+ element.nodeCloner = element.nodeCloner || new NodeCloner(element);
3248
+ element.nodeCloner.attach(methodName, bindingHydrator);
3249
+ return element;
3284
3250
  }
3285
-
3286
- bindDingData._flatAttributes = attributes;
3287
- bindDingData._flatAttributesLength = attributes.length;
3288
- bindDingData._flatDynamique = classAndStyles;
3289
- bindDingData._flatDynamiqueLength = classAndStyles.length;
3290
- bindDingData._attachLength = bindDingData.attach.length;
3251
+ bindingHydrator.$hydrate(this.$element, methodName);
3252
+ return this.$element;
3291
3253
  };
3292
3254
 
3255
+ NodeCloner.prototype.__$isNodeCloner = true;
3293
3256
 
3294
- const $hydrateFn = function(hydrateFunction, targetType, element, property) {
3295
- if(!cloneBindingsDataCache.has(element)) {
3296
- cloneBindingsDataCache.set(element, { attach: [] });
3257
+ const buildProperties = (cache, properties, data) => {
3258
+ for(const key in properties) {
3259
+ cache[key] = properties[key].apply(null, data);
3297
3260
  }
3298
- const hydrationState = cloneBindingsDataCache.get(element);
3261
+ return cache;
3262
+ };
3299
3263
 
3300
- if(targetType === 'value') {
3301
- hydrationState.value = hydrateFunction;
3302
- return;
3303
- }
3304
- if(targetType === 'attach') {
3305
- hydrationState.attach = hydrationState.attach || [];
3306
- hydrationState.attach.push({ methodName: property, fn: hydrateFunction});
3264
+ NodeCloner.prototype.resolve = function() {
3265
+ if(this.$content) {
3307
3266
  return;
3308
3267
  }
3309
- hydrationState[targetType] = hydrationState[targetType] || {};
3310
- hydrationState[targetType][property] = hydrateFunction;
3311
- };
3312
-
3313
- const bindAttachMethods = (node, bindDingData, data) => {
3314
- for(let i = 0, length = bindDingData._attachLength; i < length; i++) {
3315
- const method = bindDingData.attach[i];
3316
- node.nd[method.methodName](function() {
3317
- method.fn.call(this, ...data, ...arguments);
3268
+ const steps = [];
3269
+ if(this.$ndMethods) {
3270
+ steps.push((clonedNode, data) => {
3271
+ for(const methodName in this.$ndMethods) {
3272
+ clonedNode.nd[methodName](this.$ndMethods[methodName].bind(clonedNode, ...data));
3273
+ }
3318
3274
  });
3319
3275
  }
3320
- };
3321
-
3322
- const optimizeBindingData = (bindDingData) => {
3323
- buildAttributesCache(bindDingData);
3324
- prepareBindingMetadata(bindDingData);
3325
- };
3326
-
3327
-
3328
- const $applyBindingParents = [];
3329
- const hydrateClonedNode = (root, data, paths, pathSize) => {
3330
- const rootPath = paths[pathSize];
3331
- $applyBindingParents[rootPath.id] = root;
3332
- pathProcess(root, rootPath, data);
3333
-
3334
- let target = null, path = null;
3335
- for(let i = 0; i < pathSize; i++) {
3336
- path = paths[i];
3337
- target = $applyBindingParents[path.parentId].childNodes[path.index];
3338
- $applyBindingParents[path.id] = target;
3339
-
3340
- if(path.HYDRATE_TEXT) {
3341
- const value = path.value;
3342
- ElementCreator.bindTextNode(target, path.isString ? data[0][value] : value.apply(null, data));
3343
- continue;
3344
- }
3345
- if(path.ATTACH_METHOD) {
3346
- const bindingData = path.bindingData;
3347
- for(let i = 0, length = bindingData._attachLength; i < length; i++) {
3348
- const method = bindingData.attach[i];
3349
- target.nd[method.methodName](function() {
3350
- method.fn.call(this, ...data, ...arguments);
3351
- });
3352
- }
3353
- }
3354
- if(path.HYDRATE_ATTRIBUTES) {
3355
- path.hydrator(target, path.bindingData, data);
3356
- }
3276
+ if(this.$classes) {
3277
+ const cache = {};
3278
+ steps.push((clonedNode, data) => {
3279
+ ElementCreator.processClassAttribute(clonedNode, buildProperties(cache, this.$classes, data));
3280
+ });
3357
3281
  }
3358
-
3359
- for (let i = 0; i <= pathSize; i++) {
3360
- $applyBindingParents[i] = null;
3282
+ if(this.$styles) {
3283
+ const cache = {};
3284
+ steps.push((clonedNode, data) => {
3285
+ ElementCreator.processStyleAttribute(clonedNode, buildProperties(cache, this.$styles, data));
3286
+ });
3361
3287
  }
3362
- };
3363
-
3364
- const hydrateFull = (node, bindDingData, data) => {
3365
- const cacheAttributes = bindDingData._cache;
3366
-
3367
- for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
3368
- const attr = bindDingData._flatAttributes[i];
3369
- cacheAttributes[attr.name] = attr.value.apply(null, data);
3288
+ if(this.$attrs) {
3289
+ const cache = {};
3290
+ steps.push((clonedNode, data) => {
3291
+ ElementCreator.processAttributes(clonedNode, buildProperties(cache, this.$attrs, data));
3292
+ });
3370
3293
  }
3371
3294
 
3372
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
3373
- const dyn = bindDingData._flatDynamique[i];
3374
- cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
3375
- }
3295
+ const stepsCount = steps.length;
3376
3296
 
3377
- ElementCreator.processAttributesDirect(node, cacheAttributes);
3378
- return true;
3297
+ this.cloneNode = function(data) {
3298
+ const clonedNode = this.$element.cloneNode(false);
3299
+ for(let i = 0; i < stepsCount; i++) {
3300
+ steps[i](clonedNode, data);
3301
+ }
3302
+ return clonedNode;
3303
+ };
3379
3304
  };
3380
3305
 
3381
- const hydrateDynamic = (node, bindDingData, data) => {
3382
- const cacheAttributes = bindDingData._cache;
3383
-
3384
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
3385
- const dyn = bindDingData._flatDynamique[i];
3386
- cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
3387
- }
3388
-
3389
- ElementCreator.processClassAttribute(node, cacheAttributes.class);
3390
- ElementCreator.processStyleAttribute(node, cacheAttributes.style);
3391
- return true;
3306
+ NodeCloner.prototype.cloneNode = function(data) {
3307
+ return this.$element.cloneNode(false);
3392
3308
  };
3393
3309
 
3394
- const hydrateClassAttribute = (node, bindDingData, data) => {
3395
- const classAttributes = bindDingData._cache.class;
3396
-
3397
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
3398
- const dyn = bindDingData._flatDynamique[i];
3399
- classAttributes[dyn.key] = dyn.value.apply(null, data);
3400
- }
3401
-
3402
- ElementCreator.processClassAttribute(node, classAttributes);
3403
- return true;
3310
+ NodeCloner.prototype.cloneTextNodeByProperty = function(data) {
3311
+ return createTextNode(data[0][this.$content]);
3404
3312
  };
3405
3313
 
3406
- const hydrateStyleAttribute = (node, bindDingData, data) => {
3407
- const styleAttributes = bindDingData._cache;
3408
-
3409
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
3410
- const dyn = bindDingData._flatDynamique[i];
3411
- styleAttributes[dyn.key] = dyn.value.apply(null, data);
3412
- }
3413
-
3414
- ElementCreator.processStyleAttribute(node, styleAttributes);
3415
- return true;
3314
+ NodeCloner.prototype.cloneTextNodeByCallback = function(data) {
3315
+ return createTextNode(this.$content.apply(null, data));
3416
3316
  };
3417
3317
 
3418
- const hydrateAttributes = (node, bindDingData, data) => {
3419
- const cacheAttributes = bindDingData._cache;
3318
+ NodeCloner.prototype.attach = function(methodName, callback) {
3319
+ this.$ndMethods = this.$ndMethods || {};
3320
+ this.$ndMethods[methodName] = callback;
3321
+ return this;
3322
+ };
3420
3323
 
3421
- for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
3422
- const attr = bindDingData._flatAttributes[i];
3423
- cacheAttributes[attr.name] = attr.value.apply(null, data);
3324
+ NodeCloner.prototype.text = function(value) {
3325
+ this.$content = value;
3326
+ if(typeof value === 'function') {
3327
+ this.cloneNode = NodeCloner.prototype.cloneTextNodeByCallback;
3328
+ return this;
3424
3329
  }
3425
-
3426
- ElementCreator.processAttributesDirect(node, cacheAttributes);
3427
- return true;
3330
+ this.cloneNode = NodeCloner.prototype.cloneTextNodeByProperty;
3331
+ return this;
3428
3332
  };
3429
3333
 
3430
- const getHydrator = (bindDingData) => {
3431
- if(!bindDingData._cache) {
3432
- return noUpdate;
3433
- }
3434
- if(bindDingData._flatAttributesLength && bindDingData._flatDynamiqueLength) {
3435
- return hydrateFull;
3334
+ NodeCloner.prototype.attr = function(attrName, value) {
3335
+ if(attrName === 'class') {
3336
+ this.$classes = this.$classes || {};
3337
+ this.$classes[value.property] = value.value;
3338
+ return this;
3436
3339
  }
3437
- if(bindDingData._flatAttributesLength) {
3438
- return hydrateAttributes;
3340
+ if(attrName === 'style') {
3341
+ this.$styles = this.$styles || {};
3342
+ this.$styles[value.property] = value.value;
3343
+ return this;
3439
3344
  }
3440
- if(bindDingData._hasClassAttribute && bindDingData._hasStyleAttribute) {
3441
- return hydrateDynamic;
3345
+ this.$attrs = this.$attrs || {};
3346
+ this.$attrs[attrName] = value.value;
3347
+ return this;
3348
+ };
3349
+
3350
+ const $hydrateFn = function(value, targetType, element, property) {
3351
+ element.nodeCloner = element.nodeCloner || new NodeCloner(element);
3352
+ if(targetType === 'value') {
3353
+ element.nodeCloner.text(value);
3354
+ return;
3442
3355
  }
3443
- if(bindDingData._hasClassAttribute) {
3444
- return hydrateClassAttribute;
3356
+ if(targetType === 'attach') {
3357
+ element.nodeCloner.attach(property, value);
3358
+ return;
3445
3359
  }
3446
- return hydrateStyleAttribute;
3360
+ element.nodeCloner.attr(targetType, { property, value });
3447
3361
  };
3448
3362
 
3449
3363
  function TemplateCloner($fn) {
3450
3364
  let $node = null;
3451
- let $hasBindingData = false;
3452
3365
 
3453
- let $bindingTreePathSize = 0;
3454
- const $bindingTreePath = [
3455
- {
3456
- id: 0,
3457
- parentId: null
3458
- }
3459
- ];
3460
-
3461
- let pathCounter = 0;
3462
- const clone = (node, data, currentPath) => {
3463
- const bindDingData = cloneBindingsDataCache.get(node);
3464
- if(bindDingData) {
3465
- optimizeBindingData(bindDingData);
3466
- }
3467
- if(node.nodeType === 3) {
3468
- if(bindDingData && bindDingData.value) {
3469
- const value = bindDingData.value;
3470
- const textNode = node.cloneNode();
3471
- currentPath.value = value;
3472
- currentPath.HYDRATE_TEXT = true;
3473
- currentPath.operation = true;
3474
- currentPath.isString = (typeof value === 'string');
3475
- ElementCreator.bindTextNode(textNode, (currentPath.isString ? data[0][value] : value.apply(null, data)));
3476
- return textNode;
3366
+ const assignClonerToNode = ($node) => {
3367
+ const childNodes = $node.childNodes;
3368
+ let containDynamicNode = !!$node.nodeCloner;
3369
+ const childNodesLength = childNodes.length;
3370
+ for(let i = 0; i < childNodesLength; i++) {
3371
+ const child = childNodes[i];
3372
+ if(child.nodeCloner) {
3373
+ containDynamicNode = true;
3477
3374
  }
3478
- return node.cloneNode(true);
3479
- }
3480
- const nodeCloned = node.cloneNode();
3481
- if(bindDingData) {
3482
- const hydrator = getHydrator(bindDingData);
3483
- hydrator(nodeCloned, bindDingData, data);
3484
- bindAttachMethods(nodeCloned, bindDingData, data);
3485
-
3486
- const hasAttributes = bindDingData.classes || bindDingData.styles || bindDingData.attributes;
3487
- const hasAttachMethods = bindDingData.attach.length;
3488
-
3489
- currentPath.bindingData = bindDingData;
3490
- currentPath.hydrator = hydrator;
3491
-
3492
- if(hasAttributes) {
3493
- currentPath.HYDRATE_ATTRIBUTES = true;
3494
- currentPath.operation = true;
3495
- }
3496
- if(hasAttachMethods) {
3497
- currentPath.ATTACH_METHOD = true;
3498
- currentPath.operation = true;
3375
+ const localContainDynamicNode = assignClonerToNode(child);
3376
+ if(localContainDynamicNode) {
3377
+ containDynamicNode = true;
3499
3378
  }
3500
3379
  }
3501
- const childNodes = node.childNodes;
3502
- const parentId = currentPath.id;
3503
3380
 
3504
- for(let i = 0, length = childNodes.length; i < length; i++) {
3505
- const childNode = childNodes[i];
3506
- const path = { parentId, id: ++pathCounter, index: i };
3507
- const childNodeCloned = clone(childNode, data, path);
3508
- if(path.hasChildren || path.operation) {
3509
- $bindingTreePath.push(path);
3510
- currentPath.hasChildren = true;
3381
+ if(!containDynamicNode) {
3382
+ $node.dynamicCloneNode = $node.cloneNode.bind($node, true);
3383
+ } else {
3384
+ if($node.nodeCloner) {
3385
+ $node.nodeCloner.resolve();
3386
+ $node.dynamicCloneNode = (data) => {
3387
+ const clonedNode = $node.nodeCloner.cloneNode(data);
3388
+ for(let i = 0; i < childNodesLength; i++) {
3389
+ const child = childNodes[i].dynamicCloneNode(data);
3390
+ clonedNode.appendChild(child);
3391
+ }
3392
+ return clonedNode;
3393
+ };
3394
+ } else {
3395
+ $node.dynamicCloneNode = (data) => {
3396
+ const clonedNode = $node.cloneNode();
3397
+ for(let i = 0; i < childNodesLength; i++) {
3398
+ const child = childNodes[i].dynamicCloneNode(data);
3399
+ clonedNode.appendChild(child);
3400
+ }
3401
+ return clonedNode;
3402
+ };
3511
3403
  }
3512
- nodeCloned.appendChild(childNodeCloned);
3513
3404
  }
3514
- return nodeCloned;
3515
- };
3516
3405
 
3517
- const cloneWithBindingPaths = (data) => {
3518
- let root = $node.cloneNode(true);
3519
-
3520
- hydrateClonedNode(root, data, $bindingTreePath, $bindingTreePathSize);
3521
- return root;
3406
+ return containDynamicNode;
3522
3407
  };
3523
3408
 
3524
3409
  this.clone = (data) => {
3525
3410
  const binder = createTemplateCloner(this);
3526
3411
  $node = $fn(binder);
3527
- if(!$hasBindingData) {
3528
- this.clone = () => $node.cloneNode(true);
3529
- return $node.cloneNode(true);
3412
+ if(!$node.nodeCloner) {
3413
+ console.log('nodeCloner not found on :');
3414
+ $node.nodeCloner = new NodeCloner($node);
3530
3415
  }
3531
-
3532
- const firstClone = clone($node, data, $bindingTreePath[0]);
3533
- $bindingTreePath.reverse();
3534
- $bindingTreePathSize = $bindingTreePath.length - 1;
3535
-
3536
- this.clone = cloneWithBindingPaths;
3537
- return firstClone;
3416
+ assignClonerToNode($node);
3417
+ this.clone = (data) => $node.dynamicCloneNode(data);
3418
+ return $node.dynamicCloneNode(data);
3538
3419
  };
3539
3420
 
3540
3421
 
3541
3422
  const createBinding = (hydrateFunction, targetType) => {
3542
3423
  return new TemplateBinding((element, property) => {
3543
- $hasBindingData = true;
3544
3424
  $hydrateFn(hydrateFunction, targetType, element, property);
3545
3425
  });
3546
3426
  };
3547
3427
 
3548
3428
  this.style = (fn) => {
3549
- return createBinding(fn, 'styles');
3429
+ return createBinding(fn, 'style');
3550
3430
  };
3551
3431
  this.class = (fn) => {
3552
- return createBinding(fn, 'classes');
3432
+ return createBinding(fn, 'class');
3553
3433
  };
3554
3434
  this.property = (propertyName) => {
3555
3435
  return this.value(propertyName);
@@ -4179,7 +4059,7 @@ var NativeDocument = (function (exports) {
4179
4059
 
4180
4060
  ObservableItem.call(this, target, configs);
4181
4061
  {
4182
- PluginsManager.emit('CreateObservableArray', this);
4062
+ PluginsManager$1.emit('CreateObservableArray', this);
4183
4063
  }
4184
4064
  };
4185
4065
 
@@ -4811,7 +4691,7 @@ var NativeDocument = (function (exports) {
4811
4691
  const observable = new ObservableItem(initialValue);
4812
4692
  const updatedValue = nextTick(() => observable.set(callback()));
4813
4693
  {
4814
- PluginsManager.emit('CreateObservableComputed', observable, dependencies);
4694
+ PluginsManager$1.emit('CreateObservableComputed', observable, dependencies);
4815
4695
  }
4816
4696
 
4817
4697
  if(Validator.isFunction(dependencies)) {
@@ -4910,7 +4790,7 @@ var NativeDocument = (function (exports) {
4910
4790
  }
4911
4791
  cache.set(keyId, { keyId, isNew: true, child: new WeakRef(child), indexObserver});
4912
4792
  } catch (e) {
4913
- DebugManager.error('ForEach', `Error creating element for key ${keyId}` , e);
4793
+ DebugManager$1.error('ForEach', `Error creating element for key ${keyId}` , e);
4914
4794
  throw e;
4915
4795
  }
4916
4796
  return keyId;
@@ -5300,7 +5180,7 @@ var NativeDocument = (function (exports) {
5300
5180
  */
5301
5181
  const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
5302
5182
  if(!(Validator.isObservable(condition)) && !Validator.isObservableWhenResult(condition)) {
5303
- return DebugManager.warn('ShowIf', "ShowIf : condition must be an Observable / "+comment, condition);
5183
+ return DebugManager$1.warn('ShowIf', "ShowIf : condition must be an Observable / "+comment, condition);
5304
5184
  }
5305
5185
  const element = Anchor('Show if : '+(comment || ''));
5306
5186
 
@@ -6719,7 +6599,7 @@ var NativeDocument = (function (exports) {
6719
6599
  window.history.pushState({ name: route.name(), params, path}, route.name() || path , path);
6720
6600
  this.handleRouteChange(route, params, query, path);
6721
6601
  } catch (e) {
6722
- DebugManager.error('HistoryRouter', 'Error in pushState', e);
6602
+ DebugManager$1.error('HistoryRouter', 'Error in pushState', e);
6723
6603
  }
6724
6604
  };
6725
6605
  /**
@@ -6732,7 +6612,7 @@ var NativeDocument = (function (exports) {
6732
6612
  window.history.replaceState({ name: route.name(), params, path}, route.name() || path , path);
6733
6613
  this.handleRouteChange(route, params, {}, path);
6734
6614
  } catch(e) {
6735
- DebugManager.error('HistoryRouter', 'Error in replaceState', e);
6615
+ DebugManager$1.error('HistoryRouter', 'Error in replaceState', e);
6736
6616
  }
6737
6617
  };
6738
6618
  this.forward = function() {
@@ -6759,7 +6639,7 @@ var NativeDocument = (function (exports) {
6759
6639
  }
6760
6640
  this.handleRouteChange(route, params, query, path);
6761
6641
  } catch(e) {
6762
- DebugManager.error('HistoryRouter', 'Error in popstate event', e);
6642
+ DebugManager$1.error('HistoryRouter', 'Error in popstate event', e);
6763
6643
  }
6764
6644
  });
6765
6645
  const { route, params, query, path } = this.resolve(defaultPath || (window.location.pathname+window.location.search));
@@ -6984,7 +6864,7 @@ var NativeDocument = (function (exports) {
6984
6864
  listener(request);
6985
6865
  next && next(request);
6986
6866
  } catch (e) {
6987
- DebugManager.warn('Route Listener', 'Error in listener:', e);
6867
+ DebugManager$1.warn('Route Listener', 'Error in listener:', e);
6988
6868
  }
6989
6869
  }
6990
6870
  };
@@ -7162,7 +7042,7 @@ var NativeDocument = (function (exports) {
7162
7042
  */
7163
7043
  Router.create = function(options, callback) {
7164
7044
  if(!Validator.isFunction(callback)) {
7165
- DebugManager.error('Router', 'Callback must be a function');
7045
+ DebugManager$1.error('Router', 'Callback must be a function');
7166
7046
  throw new RouterError('Callback must be a function');
7167
7047
  }
7168
7048
  const router = new Router(options);
@@ -7366,7 +7246,7 @@ var NativeDocument = (function (exports) {
7366
7246
  exports.HtmlElementWrapper = HtmlElementWrapper;
7367
7247
  exports.NDElement = NDElement;
7368
7248
  exports.Observable = Observable;
7369
- exports.PluginsManager = PluginsManager;
7249
+ exports.PluginsManager = PluginsManager$1;
7370
7250
  exports.SingletonView = SingletonView;
7371
7251
  exports.Store = Store;
7372
7252
  exports.StoreFactory = StoreFactory;