native-document 1.0.35 → 1.0.36

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.
@@ -165,10 +165,11 @@ var NativeDocument = (function (exports) {
165
165
  }
166
166
  for(const methodName in plugin) {
167
167
  if(/^on[A-Z]/.test(methodName)) {
168
- if(!$pluginByEvents.has(methodName)) {
169
- $pluginByEvents.set(methodName, new Set());
168
+ const eventName = methodName.replace(/^on/, '');
169
+ if(!$pluginByEvents.has(eventName)) {
170
+ $pluginByEvents.set(eventName, new Set());
170
171
  }
171
- $pluginByEvents.get(methodName).add(plugin);
172
+ $pluginByEvents.get(eventName).add(plugin);
172
173
  }
173
174
  }
174
175
  },
@@ -190,20 +191,19 @@ var NativeDocument = (function (exports) {
190
191
  }
191
192
  $plugins.delete(pluginName);
192
193
  },
193
- emit(event, ...data) {
194
- const eventMethodName = 'on'+event;
195
- if(!$pluginByEvents.has(eventMethodName)) {
194
+ emit(eventName, ...data) {
195
+ if(!$pluginByEvents.has(eventName)) {
196
196
  return;
197
197
  }
198
- const plugins = $pluginByEvents.get(eventMethodName);
198
+ const plugins = $pluginByEvents.get(eventName);
199
199
 
200
200
  for(const plugin of plugins) {
201
- const callback = plugin[eventMethodName];
201
+ const callback = plugin[eventName];
202
202
  if(typeof callback === 'function') {
203
203
  try{
204
204
  callback.call(plugin, ...data);
205
205
  } catch (error) {
206
- DebugManager$1.error('Plugin Manager', `Error in plugin ${plugin.$name} for event ${eventMethodName}`, error);
206
+ DebugManager$1.error('Plugin Manager', `Error in plugin ${plugin.$name} for event ${eventName}`, error);
207
207
  }
208
208
  }
209
209
  }
@@ -217,7 +217,7 @@ var NativeDocument = (function (exports) {
217
217
  * @class ObservableItem
218
218
  */
219
219
  function ObservableItem(value) {
220
- this.$previousValue = value;
220
+ this.$previousValue = null;
221
221
  this.$currentValue = value;
222
222
  this.$isCleanedUp = false;
223
223
 
@@ -241,19 +241,33 @@ var NativeDocument = (function (exports) {
241
241
  ObservableItem.prototype.__$isObservable = true;
242
242
 
243
243
  const noneTrigger = function() {};
244
+ ObservableItem.prototype.triggerFirstListener = function(operations) {
245
+ this.$listeners[0](this.$currentValue, this.$previousValue, operations || {});
246
+ };
244
247
  ObservableItem.prototype.triggerListeners = function(operations) {
245
248
  const $listeners = this.$listeners;
246
249
  const $previousValue = this.$previousValue;
247
250
  const $currentValue = this.$currentValue;
248
251
 
249
- operations = operations || {};
250
- if($listeners?.length) {
251
- for(let i = 0, length = $listeners.length; i < length; i++) {
252
- $listeners[i]($currentValue, $previousValue, operations);
253
- }
252
+ operations = operations || DEFAULT_OPERATIONS;
253
+ for(let i = 0, length = $listeners.length; i < length; i++) {
254
+ $listeners[i]($currentValue, $previousValue, operations);
254
255
  }
255
256
  };
256
257
 
258
+ const handleWatcherCallback = function(callbacks, value) {
259
+ if(typeof callbacks === "function") {
260
+ callbacks(value);
261
+ return;
262
+ }
263
+ if (callbacks.set) {
264
+ callbacks.set(value);
265
+ return;
266
+ }
267
+ callbacks.forEach(callback => {
268
+ callback.set ? callback.set(value) : callback(value);
269
+ });
270
+ };
257
271
  ObservableItem.prototype.triggerWatchers = function() {
258
272
  if(!this.$watchers) {
259
273
  return;
@@ -265,28 +279,11 @@ var NativeDocument = (function (exports) {
265
279
 
266
280
  if($watchers.has($currentValue)) {
267
281
  const $currentValueCallbacks = $watchers.get($currentValue);
268
- if(typeof $currentValueCallbacks === "function") {
269
- $currentValueCallbacks(true);
270
- } else if ($currentValueCallbacks.set) {
271
- $currentValueCallbacks.set(true);
272
- }
273
- else {
274
- $currentValueCallbacks.forEach(callback => {
275
- callback.set ? callback.set(true) : callback(true);
276
- });
277
- }
282
+ handleWatcherCallback($currentValueCallbacks, true);
278
283
  }
279
284
  if($watchers.has($previousValue)) {
280
285
  const $previousValueCallbacks = $watchers.get($previousValue);
281
- if(typeof $previousValueCallbacks === "function") {
282
- $previousValueCallbacks(false);
283
- } else if($previousValueCallbacks.set) {
284
- $previousValueCallbacks.set(false);
285
- } else {
286
- $previousValueCallbacks.forEach(callback => {
287
- callback.set ? callback.set(false) : callback(false);
288
- });
289
- }
286
+ handleWatcherCallback($previousValueCallbacks, false);
290
287
  }
291
288
  };
292
289
 
@@ -295,13 +292,18 @@ var NativeDocument = (function (exports) {
295
292
  this.triggerWatchers();
296
293
  };
297
294
 
295
+ ObservableItem.prototype.triggerWatchersAndFirstListener = function(operations) {
296
+ this.triggerListeners(operations);
297
+ this.triggerWatchers();
298
+ };
299
+
298
300
  ObservableItem.prototype.assocTrigger = function() {
299
301
  if(this.$watchers?.size && this.$listeners?.length) {
300
- this.trigger = this.triggerAll;
302
+ this.trigger = (this.$listeners.length === 1) ? this.triggerWatchersAndFirstListener : this.triggerAll;
301
303
  return;
302
304
  }
303
305
  if(this.$listeners?.length) {
304
- this.trigger = this.triggerListeners;
306
+ this.trigger = (this.$listeners.length === 1) ? this.triggerFirstListener : this.triggerListeners;
305
307
  return;
306
308
  }
307
309
  if(this.$watchers?.size) {
@@ -461,7 +463,7 @@ var NativeDocument = (function (exports) {
461
463
  if(!Validator.isObject(item)) {
462
464
  return item;
463
465
  }
464
- return item[key] ?? defaultKey;
466
+ return item[key]?.val?.() ?? item[key] ?? defaultKey;
465
467
  };
466
468
 
467
469
  const trim = function(str, char) {
@@ -633,35 +635,7 @@ var NativeDocument = (function (exports) {
633
635
  }
634
636
  NDElement.prototype.__$isNDElement = true;
635
637
 
636
- for(const event of EVENTS) {
637
- const eventName = event.toLowerCase();
638
- NDElement.prototype['on'+event] = function(callback) {
639
- this.$element.addEventListener(eventName, callback);
640
- return this;
641
- };
642
- NDElement.prototype['onPrevent'+event] = function(callback) {
643
- this.$element.addEventListener(eventName, function(event) {
644
- event.preventDefault();
645
- callback && callback(event);
646
- });
647
- return this;
648
- };
649
- NDElement.prototype['onStop'+event] = function(callback) {
650
- this.$element.addEventListener(eventName, function(event) {
651
- event.stopPropagation();
652
- callback && callback(event);
653
- });
654
- return this;
655
- };
656
- NDElement.prototype['onPreventStop'+event] = function(callback) {
657
- this.$element.addEventListener(eventName, function(event) {
658
- event.stopPropagation();
659
- event.preventDefault();
660
- callback && callback(event);
661
- });
662
- return this;
663
- };
664
- }
638
+
665
639
 
666
640
  NDElement.prototype.valueOf = function() {
667
641
  return this.$element;
@@ -717,20 +691,26 @@ var NativeDocument = (function (exports) {
717
691
 
718
692
  NDElement.prototype.node = NDElement.prototype.htmlElement;
719
693
 
720
- NDElement.prototype.attach = function(methodName, bindingHydrator) {
721
- bindingHydrator.$hydrate(this.$element, methodName);
694
+ NDElement.prototype.attach = function(bindingHydrator) {
695
+ bindingHydrator.$hydrate(this.$element);
722
696
  return this.$element;
723
697
  };
724
698
 
699
+ const COMMON_NODE_TYPES = {
700
+ ELEMENT: 1,
701
+ TEXT: 3,
702
+ DOCUMENT_FRAGMENT: 11
703
+ };
704
+
725
705
  const Validator = {
726
706
  isObservable(value) {
727
- return value instanceof ObservableItem || value instanceof ObservableChecker || value?.__$isObservable;
707
+ return value?.__$isObservable || value instanceof ObservableItem || value instanceof ObservableChecker;
728
708
  },
729
709
  isProxy(value) {
730
710
  return value?.__isProxy__
731
711
  },
732
712
  isObservableChecker(value) {
733
- return value instanceof ObservableChecker || value?.__$isObservableChecker;
713
+ return value?.__$isObservableChecker || value instanceof ObservableChecker;
734
714
  },
735
715
  isArray(value) {
736
716
  return Array.isArray(value);
@@ -754,13 +734,17 @@ var NativeDocument = (function (exports) {
754
734
  return typeof value === 'object';
755
735
  },
756
736
  isJson(value) {
757
- return typeof value === 'object' && value !== null && value.constructor.name === 'Object' && !Array.isArray(value);
737
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && value.constructor.name === 'Object';
758
738
  },
759
739
  isElement(value) {
760
- return value instanceof HTMLElement || value instanceof DocumentFragment || value instanceof Text;
740
+ return value && (
741
+ value.nodeType === COMMON_NODE_TYPES.ELEMENT ||
742
+ value.nodeType === COMMON_NODE_TYPES.TEXT ||
743
+ value.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT
744
+ );
761
745
  },
762
746
  isFragment(value) {
763
- return value instanceof DocumentFragment;
747
+ return value?.nodeType === COMMON_NODE_TYPES.DOCUMENT_FRAGMENT;
764
748
  },
765
749
  isStringOrObservable(value) {
766
750
  return this.isString(value) || this.isObservable(value);
@@ -773,7 +757,7 @@ var NativeDocument = (function (exports) {
773
757
  ['string', 'number', 'boolean'].includes(typeof child);
774
758
  },
775
759
  isNDElement(child) {
776
- return child instanceof NDElement || child?.constructor?.__$isNDElement;
760
+ return child?.__$isNDElement || child instanceof NDElement;
777
761
  },
778
762
  isValidChildren(children) {
779
763
  if (!Array.isArray(children)) {
@@ -818,7 +802,16 @@ var NativeDocument = (function (exports) {
818
802
  }
819
803
  return /\{\{#ObItem::\([0-9]+\)\}\}/.test(data);
820
804
  },
821
- validateAttributes(attributes) {
805
+ validateAttributes(attributes) {},
806
+
807
+ validateEventCallback(callback) {
808
+ if (typeof callback !== 'function') {
809
+ throw new NativeDocumentError('Event callback must be a function');
810
+ }
811
+ }
812
+ };
813
+ {
814
+ Validator.validateAttributes = function(attributes) {
822
815
  if (!attributes || typeof attributes !== 'object') {
823
816
  return attributes;
824
817
  }
@@ -831,14 +824,8 @@ var NativeDocument = (function (exports) {
831
824
  }
832
825
 
833
826
  return attributes;
834
- },
835
-
836
- validateEventCallback(callback) {
837
- if (typeof callback !== 'function') {
838
- throw new NativeDocumentError('Event callback must be a function');
839
- }
840
- }
841
- };
827
+ };
828
+ }
842
829
 
843
830
  function Anchor(name, isUniqueChild = false) {
844
831
  const element = document.createDocumentFragment();
@@ -852,10 +839,7 @@ var NativeDocument = (function (exports) {
852
839
  element.nativeInsertBefore = element.insertBefore;
853
840
  element.nativeAppendChild = element.appendChild;
854
841
 
855
- const isParentUniqueChild = (parent) => {
856
- console.log('on passwr ici ', isUniqueChild || (parent.firstChild === anchorStart && parent.lastChild === anchorEnd));
857
- return isUniqueChild || (parent.firstChild === anchorStart && parent.lastChild === anchorEnd);
858
- };
842
+ const isParentUniqueChild = (parent) => (isUniqueChild || (parent.firstChild === anchorStart && parent.lastChild === anchorEnd));
859
843
 
860
844
  const insertBefore = function(parent, child, target) {
861
845
  const element = Validator.isElement(child) ? child : ElementCreator.getChild(child);
@@ -863,25 +847,21 @@ var NativeDocument = (function (exports) {
863
847
  parent.nativeInsertBefore(element, target);
864
848
  return;
865
849
  }
866
- if(isParentUniqueChild(parent)) {
867
- parent.append(element, anchorEnd);
850
+ if(isParentUniqueChild(parent) || target === anchorEnd) {
851
+ parent.append(element, target);
868
852
  return;
869
853
  }
870
854
  parent.insertBefore(element, target);
871
855
  };
872
856
 
873
857
  element.appendElement = function(child, before = null) {
874
- if(isParentUniqueChild(anchorEnd.parentNode)) {
875
- (before && before !== anchorEnd)
876
- ? anchorEnd.parentNode.insertBefore(child, anchorEnd)
877
- : anchorEnd.parentNode.append(child, anchorEnd);
858
+ const parentNode = anchorStart.parentNode;
859
+ const targetBefore = before || anchorEnd;
860
+ if(parentNode === element) {
861
+ parentNode.nativeInsertBefore(child, targetBefore);
878
862
  return;
879
863
  }
880
- if(anchorEnd.parentNode === element) {
881
- anchorEnd.parentNode.nativeInsertBefore(child, before || anchorEnd);
882
- return;
883
- }
884
- anchorEnd.parentNode?.insertBefore(child, before || anchorEnd);
864
+ parentNode?.insertBefore(child, targetBefore);
885
865
  };
886
866
 
887
867
  element.appendChild = function(child, before = null) {
@@ -960,10 +940,22 @@ var NativeDocument = (function (exports) {
960
940
  element.endElement = function() {
961
941
  return anchorEnd;
962
942
  };
943
+
963
944
  element.startElement = function() {
964
945
  return anchorStart;
965
946
  };
966
947
 
948
+ element.getByIndex = function(index) {
949
+ let currentNode = anchorStart;
950
+ for(let i = 0; i <= index; i++) {
951
+ if(!currentNode.nextSibling) {
952
+ return null;
953
+ }
954
+ currentNode = currentNode.nextSibling;
955
+ }
956
+ return currentNode !== anchorStart ? currentNode : null;
957
+ };
958
+
967
959
  return element;
968
960
  }
969
961
 
@@ -1018,6 +1010,26 @@ var NativeDocument = (function (exports) {
1018
1010
  setInterval(() => MemoryManager.cleanObservables(threshold), interval);
1019
1011
  };
1020
1012
 
1013
+ function toggleElementClass(element, className, shouldAdd) {
1014
+ element.classes.toggle(className, shouldAdd);
1015
+ }
1016
+ function toggleElementStyle(element, styleName, newValue) {
1017
+ element.style[styleName] = newValue;
1018
+ }
1019
+ function updateInputFromObserver(element, attributeName, newValue) {
1020
+ if(Validator.isBoolean(newValue)) {
1021
+ element[attributeName] = newValue;
1022
+ return;
1023
+ }
1024
+ element[attributeName] = newValue === element.value;
1025
+ }
1026
+ function updateObserverFromInput(element, attributeName, defaultValue, value) {
1027
+ if(Validator.isBoolean(defaultValue)) {
1028
+ value.set(element[attributeName]);
1029
+ return;
1030
+ }
1031
+ value.set(element.value);
1032
+ }
1021
1033
  /**
1022
1034
  *
1023
1035
  * @param {HTMLElement} element
@@ -1027,23 +1039,22 @@ var NativeDocument = (function (exports) {
1027
1039
  for(let className in data) {
1028
1040
  const value = data[className];
1029
1041
  if(Validator.isObservable(value)) {
1030
- element.classList.toggle(className, value.val());
1031
- value.subscribe(newValue => element.classList.toggle(className, newValue));
1042
+ element.classes.toggle(className, value.val());
1043
+ value.subscribe(toggleElementClass.bind(null, element, className));
1032
1044
  continue;
1033
1045
  }
1034
1046
  if(value.$observer) {
1035
- element.classList.toggle(className, value.$observer.val() === value.$target);
1036
- value.$observer.on(value.$target, function(isTargetValue) {
1037
- element.classList.toggle(className, isTargetValue);
1038
- });
1047
+ element.classes.toggle(className, value.$observer.val() === value.$target);
1048
+ value.$observer.on(value.$target, toggleElementClass.bind(null, element, className));
1039
1049
  continue;
1040
1050
  }
1041
1051
  if(value.$hydrate) {
1042
1052
  value.$hydrate(element, className);
1043
1053
  continue;
1044
1054
  }
1045
- element.classList.toggle(className, value);
1055
+ element.classes.toggle(className, value);
1046
1056
  }
1057
+ data = null;
1047
1058
  }
1048
1059
 
1049
1060
  /**
@@ -1056,9 +1067,7 @@ var NativeDocument = (function (exports) {
1056
1067
  const value = data[styleName];
1057
1068
  if(Validator.isObservable(value)) {
1058
1069
  element.style[styleName] = value.val();
1059
- value.subscribe(newValue => {
1060
- element.style[styleName] = newValue;
1061
- });
1070
+ value.subscribe(toggleElementStyle.bind(null, element, styleName));
1062
1071
  continue;
1063
1072
  }
1064
1073
  element.style[styleName] = value;
@@ -1081,21 +1090,9 @@ var NativeDocument = (function (exports) {
1081
1090
  }
1082
1091
  if(Validator.isObservable(value)) {
1083
1092
  if(['checked'].includes(attributeName)) {
1084
- element.addEventListener('input', () => {
1085
- if(Validator.isBoolean(defaultValue)) {
1086
- value.set(element[attributeName]);
1087
- return;
1088
- }
1089
- value.set(element.value);
1090
- });
1093
+ element.addEventListener('input', updateObserverFromInput.bind(null, element, attributeName, defaultValue));
1091
1094
  }
1092
- value.subscribe(newValue => {
1093
- if(Validator.isBoolean(newValue)) {
1094
- element[attributeName] = newValue;
1095
- return;
1096
- }
1097
- element[attributeName] = newValue === element.value;
1098
- });
1095
+ value.subscribe(updateInputFromObserver.bind(null, element, attributeName));
1099
1096
  }
1100
1097
  }
1101
1098
 
@@ -1149,11 +1146,11 @@ var NativeDocument = (function (exports) {
1149
1146
  return value.map(item => Validator.isObservable(item) ? item.val() : item).join(' ') || ' ';
1150
1147
  }, observables);
1151
1148
  }
1152
- if(attributeName === 'class' && Validator.isJson(value)) {
1149
+ if(attributeName === 'class' && Validator.isObject(value)) {
1153
1150
  bindClassAttribute(element, value);
1154
1151
  continue;
1155
1152
  }
1156
- if(attributeName === 'style' && Validator.isJson(value)) {
1153
+ if(attributeName === 'style' && Validator.isObject(value)) {
1157
1154
  bindStyleAttribute(element, value);
1158
1155
  continue;
1159
1156
  }
@@ -1165,6 +1162,10 @@ var NativeDocument = (function (exports) {
1165
1162
  bindAttributeWithObservable(element, attributeName, value);
1166
1163
  continue;
1167
1164
  }
1165
+ if(value.$hydrate) {
1166
+ value.$hydrate(element, attributeName);
1167
+ continue;
1168
+ }
1168
1169
  element.setAttribute(attributeName, value);
1169
1170
 
1170
1171
  }
@@ -1241,14 +1242,19 @@ var NativeDocument = (function (exports) {
1241
1242
  */
1242
1243
  processChildren(children, parent) {
1243
1244
  if(children === null) return;
1244
- const childrenArray = Array.isArray(children) ? children : [children];
1245
-
1246
1245
  PluginsManager.emit('BeforeProcessChildren', parent);
1247
-
1248
- for(let i = 0, length = childrenArray.length; i < length; i++) {
1249
- let child = this.getChild(childrenArray[i]);
1250
- if (child === null) continue;
1251
- parent.appendChild(child);
1246
+ if(!Array.isArray(children)) {
1247
+ let child = this.getChild(children);
1248
+ if(child) {
1249
+ parent.appendChild(child);
1250
+ }
1251
+ }
1252
+ else {
1253
+ for(let i = 0, length = children.length; i < length; i++) {
1254
+ let child = this.getChild(children[i]);
1255
+ if (child === null) continue;
1256
+ parent.appendChild(child);
1257
+ }
1252
1258
  }
1253
1259
 
1254
1260
  PluginsManager.emit('AfterProcessChildren', parent);
@@ -1315,13 +1321,60 @@ var NativeDocument = (function (exports) {
1315
1321
  Object.defineProperty(HTMLElement.prototype, 'nd', {
1316
1322
  configurable: true,
1317
1323
  get() {
1318
- if(this.$nd) {
1319
- return this.$nd;
1324
+ return new NDElement(this);
1325
+ }
1326
+ });
1327
+
1328
+ const classListMethods = {
1329
+ getClasses() {
1330
+ return this.$element.className?.split(' ').filter(Boolean);
1331
+ },
1332
+ add(value) {
1333
+ const classes = this.getClasses();
1334
+ if(classes.indexOf(value) >= 0) {
1335
+ return;
1336
+ }
1337
+ classes.push(value);
1338
+ this.$element.className = classes.join(' ');
1339
+ },
1340
+ remove(value) {
1341
+ const classes = this.getClasses();
1342
+ const index = classes.indexOf(value);
1343
+ if(index < 0) {
1344
+ return;
1320
1345
  }
1346
+ classes.splice(index, 1);
1347
+ this.$element.className = classes.join(' ');
1348
+ },
1349
+ toggle(value, force = undefined) {
1350
+ const classes = this.getClasses();
1351
+ const index = classes.indexOf(value);
1352
+ if(index >= 0) {
1353
+ if(force === true) {
1354
+ return;
1355
+ }
1356
+ classes.splice(index, 1);
1357
+ }
1358
+ else {
1359
+ if(force === false) {
1360
+ return;
1361
+ }
1362
+ classes.push(value);
1363
+ }
1364
+ this.$element.className = classes.join(' ');
1365
+ },
1366
+ contains(value) {
1367
+ return this.getClasses().indexOf(value) >= 0;
1368
+ }
1369
+ };
1321
1370
 
1322
- this.$nd = new NDElement(this);
1323
- this.$nd.nd = this.$nd;
1324
- return this.$nd;
1371
+ Object.defineProperty(HTMLElement.prototype, 'classes', {
1372
+ configurable: true,
1373
+ get() {
1374
+ return {
1375
+ $element: this,
1376
+ ...classListMethods
1377
+ };
1325
1378
  }
1326
1379
  });
1327
1380
 
@@ -1457,13 +1510,17 @@ var NativeDocument = (function (exports) {
1457
1510
  };
1458
1511
 
1459
1512
 
1460
- function createHtmlElement($tagName, _attributes, _children = null, customWrapper) {
1461
- const { props: attributes, children = null } = normalizeComponentArgs(_attributes, _children);
1462
- const element = ElementCreator.createElement($tagName);
1463
- const finalElement = (typeof customWrapper === 'function') ? customWrapper(element) : element;
1513
+ function createHtmlElement($tagName, customWrapper, _attributes, _children = null) {
1514
+ let { props: attributes, children = null } = normalizeComponentArgs(_attributes, _children);
1515
+ let element = ElementCreator.createElement($tagName);
1516
+ let finalElement = (customWrapper && typeof customWrapper === 'function') ? customWrapper(element) : element;
1464
1517
 
1465
- ElementCreator.processAttributes(finalElement, attributes);
1466
- ElementCreator.processChildren(children, finalElement);
1518
+ if(attributes) {
1519
+ ElementCreator.processAttributes(finalElement, attributes);
1520
+ }
1521
+ if(children) {
1522
+ ElementCreator.processChildren(children, finalElement);
1523
+ }
1467
1524
 
1468
1525
  return ElementCreator.setup(finalElement, attributes, customWrapper);
1469
1526
  }
@@ -1475,24 +1532,23 @@ var NativeDocument = (function (exports) {
1475
1532
  * @returns {Function}
1476
1533
  */
1477
1534
  function HtmlElementWrapper(name, customWrapper) {
1478
- return (_attributes, _children = null) => createHtmlElement(name.toLowerCase(), _attributes, _children, customWrapper);
1535
+ return createHtmlElement.bind(null, name.toLowerCase(), customWrapper);
1479
1536
  }
1480
1537
 
1481
1538
  const cloneBindingsDataCache = new WeakMap();
1482
1539
 
1483
1540
 
1484
1541
  const bindAttributes = (node, bindDingData, data) => {
1485
- if(!bindDingData) {
1486
- return null;
1487
- }
1488
- const attributes = { };
1542
+ let attributes = null;
1489
1543
  if(bindDingData.attributes) {
1544
+ attributes = attributes || {};
1490
1545
  for (const attr in bindDingData.attributes) {
1491
1546
  attributes[attr] = bindDingData.attributes[attr](...data);
1492
1547
  }
1493
1548
  }
1494
1549
 
1495
1550
  if(bindDingData.classes) {
1551
+ attributes = attributes || {};
1496
1552
  attributes.class = {};
1497
1553
  for (const className in bindDingData.classes) {
1498
1554
  attributes.class[className] = bindDingData.classes[className](...data);
@@ -1500,30 +1556,27 @@ var NativeDocument = (function (exports) {
1500
1556
  }
1501
1557
 
1502
1558
  if(bindDingData.styles) {
1559
+ attributes = attributes || {};
1503
1560
  attributes.style = {};
1504
1561
  for (const property in bindDingData.styles) {
1505
1562
  attributes.style[property] = bindDingData.styles[property](...data);
1506
1563
  }
1507
1564
  }
1508
1565
 
1509
- if(Object.keys(attributes)) {
1566
+ if(attributes) {
1510
1567
  ElementCreator.processAttributes(node, attributes);
1511
- return attributes;
1568
+ return true;
1512
1569
  }
1513
1570
 
1514
1571
  return null;
1515
1572
  };
1516
1573
 
1517
1574
 
1518
- const bindAttachesMethods = function(node, bindDingData, data) {
1519
- if(!bindDingData?.attaches) {
1575
+ const bindAttachMethods = function(node, bindDingData, data) {
1576
+ if(!bindDingData.attach) {
1520
1577
  return null;
1521
1578
  }
1522
- for(const methodName in bindDingData.attaches) {
1523
- node.nd[methodName](function(...args) {
1524
- bindDingData.attaches[methodName].call(this, ...[...args, ...data]);
1525
- });
1526
- }
1579
+ bindDingData.attach(node, ...data);
1527
1580
  };
1528
1581
 
1529
1582
  function TemplateCloner($fn) {
@@ -1531,18 +1584,20 @@ var NativeDocument = (function (exports) {
1531
1584
 
1532
1585
  const clone = (node, data) => {
1533
1586
  const bindDingData = cloneBindingsDataCache.get(node);
1534
- if(node instanceof Text) {
1535
- if(bindDingData?.value) {
1587
+ if(node.nodeType === 3) {
1588
+ if(bindDingData && bindDingData.value) {
1536
1589
  return bindDingData.value(data);
1537
1590
  }
1538
1591
  return node.cloneNode(true);
1539
1592
  }
1540
1593
  const nodeCloned = node.cloneNode();
1541
- bindAttributes(nodeCloned, bindDingData, data);
1542
- bindAttachesMethods(nodeCloned, bindDingData, data);
1543
-
1544
- for(let i = 0, length = node.childNodes.length; i < length; i++) {
1545
- const childNode = node.childNodes[i];
1594
+ if(bindDingData) {
1595
+ bindAttributes(nodeCloned, bindDingData, data);
1596
+ bindAttachMethods(nodeCloned, bindDingData, data);
1597
+ }
1598
+ const childNodes = node.childNodes;
1599
+ for(let i = 0, length = childNodes.length; i < length; i++) {
1600
+ const childNode = childNodes[i];
1546
1601
  const childNodeCloned = clone(childNode, data);
1547
1602
  nodeCloned.appendChild(childNodeCloned);
1548
1603
  }
@@ -1553,26 +1608,30 @@ var NativeDocument = (function (exports) {
1553
1608
  if(!$node) {
1554
1609
  $node = $fn(this);
1555
1610
  }
1556
- const cloneNode = clone($node, data);
1557
- PluginsManager.emit('NodeTemplateInstanceCreated', cloneNode);
1558
- return cloneNode;
1611
+ return clone($node, data);
1612
+ };
1613
+
1614
+ const $hydrateFn = function(hydrateFunction, target, element, property) {
1615
+ if(!cloneBindingsDataCache.has(element)) {
1616
+ // { classes, styles, attributes, value, attach }
1617
+ cloneBindingsDataCache.set(element, {});
1618
+ }
1619
+ const hydrationState = cloneBindingsDataCache.get(element);
1620
+ if(target === 'value') {
1621
+ hydrationState.value = hydrateFunction;
1622
+ return;
1623
+ }
1624
+ if(target === 'attach') {
1625
+ hydrationState.attach = hydrateFunction;
1626
+ return;
1627
+ }
1628
+ hydrationState[target] = hydrationState[target] || {};
1629
+ hydrationState[target][property] = hydrateFunction;
1559
1630
  };
1560
1631
 
1561
1632
  const createBinding = (hydrateFunction, target) => {
1562
1633
  return {
1563
- $hydrate : function(element, property) {
1564
- if(!cloneBindingsDataCache.has(element)) {
1565
- // { classes, styles, attributes, value, attaches }
1566
- cloneBindingsDataCache.set(element, {});
1567
- }
1568
- const hydrationState = cloneBindingsDataCache.get(element);
1569
- if(target === 'value') {
1570
- hydrationState.value = hydrateFunction;
1571
- return;
1572
- }
1573
- hydrationState[target] = hydrationState[target] || {};
1574
- hydrationState[target][property] = hydrateFunction;
1575
- }
1634
+ $hydrate : (element, property) => $hydrateFn(hydrateFunction, target, element, property),
1576
1635
  }
1577
1636
  };
1578
1637
 
@@ -1582,31 +1641,46 @@ var NativeDocument = (function (exports) {
1582
1641
  this.class = (fn) => {
1583
1642
  return createBinding(fn, 'classes');
1584
1643
  };
1585
- this.value = (fn) => {
1644
+ this.property = (propertyName) => {
1645
+ return this.value(propertyName);
1646
+ };
1647
+ this.value = (callbackOrProperty) => {
1648
+ if(typeof callbackOrProperty !== 'function') {
1649
+ return createBinding(function(data) {
1650
+ const firstArgument = data[0];
1651
+ return createTextNode(firstArgument[callbackOrProperty]);
1652
+ }, 'value');
1653
+ }
1586
1654
  return createBinding(function(data) {
1587
- return createTextNode(fn(...data));
1655
+ return createTextNode(callbackOrProperty(...data));
1588
1656
  }, 'value');
1589
1657
  };
1590
1658
  this.attr = (fn) => {
1591
1659
  return createBinding(fn, 'attributes');
1592
1660
  };
1593
1661
  this.attach = (fn) => {
1594
- return createBinding(fn, 'attaches');
1662
+ return createBinding(fn, 'attach');
1595
1663
  };
1596
1664
  }
1597
1665
 
1598
1666
  function useCache(fn) {
1599
1667
  let $cache = null;
1600
- PluginsManager.emit('NodeTemplateStored', fn);
1601
1668
 
1602
- return function(...args) {
1669
+ const wrapper = function(args) {
1603
1670
  if(!$cache) {
1604
1671
  $cache = new TemplateCloner(fn);
1605
- PluginsManager.emit('NodeTemplateCreated', $cache);
1606
1672
  }
1607
-
1608
1673
  return $cache.clone(args);
1609
1674
  };
1675
+
1676
+ if(fn.length < 2) {
1677
+ return function(...args) {
1678
+ return wrapper(args);
1679
+ };
1680
+ }
1681
+ return function(_, __, ...args) {
1682
+ return wrapper([_, __, ...args]);
1683
+ };
1610
1684
  }
1611
1685
 
1612
1686
  Function.prototype.args = function(...args) {
@@ -1666,6 +1740,118 @@ var NativeDocument = (function (exports) {
1666
1740
  });
1667
1741
  };
1668
1742
 
1743
+ (function() {
1744
+ const DelegatedEventsCallbackStore = {};
1745
+
1746
+ const addCallbackToCallbacksStore = function(element, eventName, callback) {
1747
+ if(!element) return;
1748
+ if(!DelegatedEventsCallbackStore[eventName]) {
1749
+ const eventStore = new WeakMap();
1750
+ DelegatedEventsCallbackStore[eventName] = eventStore;
1751
+ eventStore.set(element, callback);
1752
+ return;
1753
+ }
1754
+ const eventStore = DelegatedEventsCallbackStore[eventName];
1755
+
1756
+ if(!eventStore.has(element)) {
1757
+ eventStore.set(element, callback);
1758
+ return;
1759
+ }
1760
+ const existingCallbacks = eventStore.get(element);
1761
+ if(!Validator.isArray(existingCallbacks)) {
1762
+ eventStore.set(element, [store[eventName], callback]);
1763
+ return;
1764
+ }
1765
+ existingCallbacks.push(callback);
1766
+ };
1767
+
1768
+ const handleDelegatedCallbacks = function(container, eventName) {
1769
+ container.addEventListener(eventName, (event) => {
1770
+ const eventStore = DelegatedEventsCallbackStore[eventName];
1771
+ if(!eventStore) {
1772
+ return;
1773
+ }
1774
+ let target = event.target;
1775
+ while(target && target !== container) {
1776
+ const callback = eventStore.get(target);
1777
+ if(!callback) {
1778
+ target = target.parentElement;
1779
+ continue;
1780
+ }
1781
+
1782
+ if(Validator.isFunction(callback)) {
1783
+ callback.call(target, event);
1784
+ }
1785
+ else {
1786
+ for(let i = 0; i < callback.length; i++) {
1787
+ callback[i].call(target, event);
1788
+ }
1789
+ }
1790
+ return;
1791
+ }
1792
+ });
1793
+ };
1794
+
1795
+
1796
+ const preventDefaultWrapper = function(element, eventName, callback) {
1797
+ element.addEventListener(eventName, (event) => {
1798
+ event.preventDefault();
1799
+ callback && callback.call(element, event);
1800
+ });
1801
+ return this;
1802
+ };
1803
+ const stopPropagationWrapper = function(element, eventName, callback) {
1804
+ element.addEventListener(eventName, (event) => {
1805
+ event.stopPropagation();
1806
+ callback && callback.call(element, event);
1807
+ });
1808
+ return this;
1809
+ };
1810
+ const preventDefaultAndStopPropagationWrapper = function(element, eventName, callback) {
1811
+ element.addEventListener(eventName, (event) => {
1812
+ event.stopPropagation();
1813
+ event.preventDefault();
1814
+ callback && callback.call(element, event);
1815
+ });
1816
+ return this;
1817
+ };
1818
+ const captureEventWrapper = function(element, eventName, directHandler) {
1819
+ if(directHandler) {
1820
+ element.addEventListener(eventName, directHandler);
1821
+ return this;
1822
+ }
1823
+ handleDelegatedCallbacks(element, eventName);
1824
+ return this;
1825
+ };
1826
+
1827
+ for(const event of EVENTS) {
1828
+ const eventName = event.toLowerCase();
1829
+ NDElement.prototype['on'+event] = function(callback) {
1830
+ this.$element.addEventListener(eventName, callback);
1831
+ return this;
1832
+ };
1833
+ NDElement.prototype['onPrevent'+event] = function(callback) {
1834
+ return preventDefaultWrapper(this.$element, eventName, callback);
1835
+ };
1836
+ NDElement.prototype['onStop'+event] = function(callback) {
1837
+ return stopPropagationWrapper(this.$element, eventName, callback);
1838
+ };
1839
+ NDElement.prototype['onPreventStop'+event] = function(callback) {
1840
+ return preventDefaultAndStopPropagationWrapper(this.$element, eventName, callback);
1841
+ };
1842
+
1843
+ NDElement.prototype['when'+event] = function(callback) {
1844
+ addCallbackToCallbacksStore(this.$element, eventName, callback);
1845
+ return this;
1846
+ };
1847
+
1848
+ NDElement.prototype['capture'+event] = function(directHandler) {
1849
+ captureEventWrapper(this.$element, eventName, directHandler);
1850
+ return this;
1851
+ };
1852
+ }
1853
+ }());
1854
+
1669
1855
  const cssPropertyAccumulator = function(initialValue = {}) {
1670
1856
  let data = Validator.isString(initialValue) ? initialValue.split(';').filter(Boolean) : initialValue;
1671
1857
  const isArray = Validator.isArray(data);
@@ -1778,9 +1964,9 @@ var NativeDocument = (function (exports) {
1778
1964
  return observer.val().length;
1779
1965
  };
1780
1966
 
1781
- const overrideMethods = ['map', 'filter', 'reduce', 'some', 'every', 'find', 'findIndex', 'concat'];
1967
+ const overrideMethods = ['map', 'filter', 'reduce', 'some', 'every', 'find', 'findIndex', 'concat', 'includes', 'indexOf'];
1782
1968
  overrideMethods.forEach((method) => {
1783
- observer[method] = function(...args) {
1969
+ observer[method] = (...args) => {
1784
1970
  return observer.val()[method](...args);
1785
1971
  };
1786
1972
  });
@@ -1810,13 +1996,13 @@ var NativeDocument = (function (exports) {
1810
1996
 
1811
1997
  /**
1812
1998
  *
1813
- * @param {Object} value
1999
+ * @param {Object} initialValue
1814
2000
  * @returns {Proxy}
1815
2001
  */
1816
- Observable.init = function(value) {
2002
+ Observable.init = function(initialValue) {
1817
2003
  const data = {};
1818
- for(const key in value) {
1819
- const itemValue = value[key];
2004
+ for(const key in initialValue) {
2005
+ const itemValue = initialValue[key];
1820
2006
  if(Validator.isJson(itemValue)) {
1821
2007
  data[key] = Observable.init(itemValue);
1822
2008
  continue;
@@ -1845,8 +2031,11 @@ var NativeDocument = (function (exports) {
1845
2031
  const $clone = function() {
1846
2032
 
1847
2033
  };
2034
+ const $updateWith = function(values) {
2035
+ Observable.update(proxy, values);
2036
+ };
1848
2037
 
1849
- return new Proxy(data, {
2038
+ const proxy = new Proxy(data, {
1850
2039
  get(target, property) {
1851
2040
  if(property === '__isProxy__') {
1852
2041
  return true;
@@ -1857,6 +2046,12 @@ var NativeDocument = (function (exports) {
1857
2046
  if(property === '$clone') {
1858
2047
  return $clone;
1859
2048
  }
2049
+ if(property === '$observables') {
2050
+ return Object.values(target);
2051
+ }
2052
+ if(property === '$updateWith') {
2053
+ return $updateWith;
2054
+ }
1860
2055
  if(target[property] !== undefined) {
1861
2056
  return target[property];
1862
2057
  }
@@ -1864,10 +2059,25 @@ var NativeDocument = (function (exports) {
1864
2059
  },
1865
2060
  set(target, prop, newValue) {
1866
2061
  if(target[prop] !== undefined) {
1867
- target[prop].set(newValue);
2062
+ Validator.isObservable(newValue)
2063
+ ? target[prop].set(newValue.val())
2064
+ : target[prop].set(newValue);
2065
+ return true;
1868
2066
  }
2067
+ return true;
1869
2068
  }
1870
- })
2069
+ });
2070
+
2071
+ return proxy;
2072
+ };
2073
+
2074
+ /**
2075
+ *
2076
+ * @param {any[]} data
2077
+ * @return Proxy[]
2078
+ */
2079
+ Observable.arrayOfObject = function(data) {
2080
+ return data.map(item => Observable.object(item));
1871
2081
  };
1872
2082
 
1873
2083
  /**
@@ -1895,13 +2105,16 @@ var NativeDocument = (function (exports) {
1895
2105
 
1896
2106
 
1897
2107
  Observable.update = function($target, data) {
2108
+ if(Validator.isProxy(data)) {
2109
+ data = data.$value;
2110
+ }
1898
2111
  for(const key in data) {
1899
2112
  const targetItem = $target[key];
1900
2113
  const newValue = data[key];
1901
2114
 
1902
2115
  if(Validator.isObservable(targetItem)) {
1903
2116
  if(Validator.isArray(newValue)) {
1904
- Observable.update(targetItem, newValue);
2117
+ targetItem.set([...newValue]);
1905
2118
  continue;
1906
2119
  }
1907
2120
  targetItem.set(newValue);
@@ -1939,7 +2152,15 @@ var NativeDocument = (function (exports) {
1939
2152
  return observable;
1940
2153
  }
1941
2154
 
1942
- dependencies.forEach(dependency => dependency.subscribe(updatedValue));
2155
+ dependencies.forEach(dependency => {
2156
+ if(Validator.isProxy(dependency)) {
2157
+ dependency.$observables.forEach((observable) => {
2158
+ observable.subscribe(updatedValue);
2159
+ });
2160
+ return;
2161
+ }
2162
+ dependency.subscribe(updatedValue);
2163
+ });
1943
2164
 
1944
2165
  return observable;
1945
2166
  };
@@ -2021,10 +2242,11 @@ var NativeDocument = (function (exports) {
2021
2242
  *
2022
2243
  * @param {Array|Object|ObservableItem} data
2023
2244
  * @param {Function} callback
2024
- * @param {?Function} key
2245
+ * @param {?Function|?string} key
2246
+ * @param {{shouldKeepItemsInCache: boolean}?} configs
2025
2247
  * @returns {DocumentFragment}
2026
2248
  */
2027
- function ForEach(data, callback, key) {
2249
+ function ForEach(data, callback, key, { shouldKeepItemsInCache = false } = {}) {
2028
2250
  const element = new Anchor('ForEach');
2029
2251
  const blockEnd = element.endElement();
2030
2252
  element.startElement();
@@ -2039,6 +2261,9 @@ var NativeDocument = (function (exports) {
2039
2261
  };
2040
2262
 
2041
2263
  const cleanCache = (parent) => {
2264
+ if(shouldKeepItemsInCache) {
2265
+ return;
2266
+ }
2042
2267
  for(const [keyId, cacheItem] of cache.entries()) {
2043
2268
  if(keyIds.has(keyId)) {
2044
2269
  continue;
@@ -2071,6 +2296,9 @@ var NativeDocument = (function (exports) {
2071
2296
  try {
2072
2297
  const indexObserver = callback.length >= 2 ? Observable(indexKey) : null;
2073
2298
  let child = ElementCreator.getChild(callback(item, indexObserver));
2299
+ if(!child || Validator.isFragment(child)) {
2300
+ throw new NativeDocumentError("ForEachArray child can't be null or undefined!");
2301
+ }
2074
2302
  cache.set(keyId, { keyId, isNew: true, child: new WeakRef(child), indexObserver});
2075
2303
  } catch (e) {
2076
2304
  DebugManager$1.error('ForEach', `Error creating element for key ${keyId}` , e);
@@ -2122,7 +2350,7 @@ var NativeDocument = (function (exports) {
2122
2350
  keyIds.clear();
2123
2351
  if(Array.isArray(items)) {
2124
2352
  for(let i = 0, length = items.length; i < length; i++) {
2125
- const keyId= handleContentItem(items[i], i);
2353
+ const keyId = handleContentItem(items[i], i);
2126
2354
  keyIds.add(keyId);
2127
2355
  }
2128
2356
  } else {
@@ -2200,14 +2428,12 @@ var NativeDocument = (function (exports) {
2200
2428
  if(!cacheItem) {
2201
2429
  return;
2202
2430
  }
2203
- const child = cacheItem.child;
2204
- cacheItem.indexObserver?.deref()?.cleanup();
2205
- cacheItem.child = null;
2206
- cacheItem.indexObserver = null;
2207
2431
  if(removeChild) {
2432
+ const child = cacheItem.child;
2208
2433
  child?.remove();
2209
2434
  cache.delete(cacheItem.keyId);
2210
2435
  }
2436
+ cacheItem.indexObserver?.deref()?.cleanup();
2211
2437
  };
2212
2438
 
2213
2439
  const removeCacheItemByKey = (keyId, removeChild = true) => {
@@ -2215,6 +2441,13 @@ var NativeDocument = (function (exports) {
2215
2441
  };
2216
2442
 
2217
2443
  const cleanCache = () => {
2444
+ if(configs.shouldKeepItemsInCache) {
2445
+ return;
2446
+ }
2447
+ if(!isIndexRequired) {
2448
+ cache.clear();
2449
+ return;
2450
+ }
2218
2451
  for (const [keyId, cacheItem] of cache.entries()) {
2219
2452
  removeCacheItem(cacheItem, false);
2220
2453
  }
@@ -2236,6 +2469,9 @@ var NativeDocument = (function (exports) {
2236
2469
 
2237
2470
  const indexObserver = isIndexRequired ? Observable(indexKey) : null;
2238
2471
  let child = ElementCreator.getChild(callback(item, indexObserver));
2472
+ if(!child || Validator.isFragment(child)) {
2473
+ throw new NativeDocumentError("ForEachArray child can't be null or undefined!");
2474
+ }
2239
2475
  cache.set(keyId, {
2240
2476
  keyId,
2241
2477
  child: child,
@@ -2278,12 +2514,12 @@ var NativeDocument = (function (exports) {
2278
2514
  toFragment(items, startIndexFrom = 0){
2279
2515
  const fragment = document.createDocumentFragment();
2280
2516
  for(let i = 0, length = items.length; i < length; i++) {
2281
- fragment.append(buildItem(items[i], lastNumberOfItems));
2517
+ fragment.appendChild(buildItem(items[i], lastNumberOfItems));
2282
2518
  lastNumberOfItems++;
2283
2519
  }
2284
2520
  return fragment;
2285
2521
  },
2286
- add(items, delay = 0) {
2522
+ add(items, delay = 2) {
2287
2523
  const fragment = Actions.toFragment(items);
2288
2524
  setTimeout(() => {
2289
2525
  element.appendElement(fragment);
@@ -2310,7 +2546,7 @@ var NativeDocument = (function (exports) {
2310
2546
  },
2311
2547
  clear,
2312
2548
  merge(items) {
2313
- Actions.add(items, 0);
2549
+ Actions.add(items);
2314
2550
  },
2315
2551
  push(items) {
2316
2552
  let delay = 0;
@@ -2417,7 +2653,9 @@ var NativeDocument = (function (exports) {
2417
2653
  updateIndexObservers(items, 0);
2418
2654
  };
2419
2655
 
2420
- buildContent(data.val(), null, {action: null});
2656
+ if(data.val().length) {
2657
+ buildContent(data.val(), null, {action: null});
2658
+ }
2421
2659
  if(Validator.isObservable(data)) {
2422
2660
  data.subscribe(buildContent);
2423
2661
  }
@@ -2430,10 +2668,10 @@ var NativeDocument = (function (exports) {
2430
2668
  *
2431
2669
  * @param {ObservableItem|ObservableChecker} condition
2432
2670
  * @param {*} child
2433
- * @param {string|null} comment
2671
+ * @param {{comment?: string|null, shouldKeepInCache?: Boolean}} comment
2434
2672
  * @returns {DocumentFragment}
2435
2673
  */
2436
- const ShowIf = function(condition, child, comment = null) {
2674
+ const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
2437
2675
  if(!(Validator.isObservable(condition))) {
2438
2676
  return DebugManager$1.warn('ShowIf', "ShowIf : condition must be an Observable / "+comment, condition);
2439
2677
  }
@@ -2441,10 +2679,13 @@ var NativeDocument = (function (exports) {
2441
2679
 
2442
2680
  let childElement = null;
2443
2681
  const getChildElement = () => {
2444
- if(childElement) {
2682
+ if(childElement && shouldKeepInCache) {
2445
2683
  return childElement;
2446
2684
  }
2447
2685
  childElement = ElementCreator.getChild(child);
2686
+ if(Validator.isFragment(childElement)) {
2687
+ childElement = Array.from(childElement.children);
2688
+ }
2448
2689
  return childElement;
2449
2690
  };
2450
2691
 
@@ -2516,6 +2757,9 @@ var NativeDocument = (function (exports) {
2516
2757
  return null;
2517
2758
  }
2518
2759
  item = ElementCreator.getChild(item);
2760
+ if(Validator.isFragment(item)) {
2761
+ item = Array.from(item.children);
2762
+ }
2519
2763
  shouldKeepInCache && cache.set(key, item);
2520
2764
  return item;
2521
2765
  };