native-document 1.0.32 → 1.0.33

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.
@@ -264,14 +264,24 @@ var NativeDocument = (function (exports) {
264
264
  const $currentValue = this.$currentValue;
265
265
 
266
266
  if($watchers.has($currentValue)) {
267
- $watchers.get($currentValue).forEach(callback => {
268
- callback.set ? callback.set(true) : callback(true);
269
- });
267
+ const $currentValueCallbacks = $watchers.get($currentValue);
268
+ if(!Validator.isArray($currentValueCallbacks)) {
269
+ $currentValueCallbacks.set ? $currentValueCallbacks.set(true) : $currentValueCallbacks(true);
270
+ } else {
271
+ $currentValueCallbacks.forEach(callback => {
272
+ callback.set ? callback.set(true) : callback(true);
273
+ });
274
+ }
270
275
  }
271
276
  if($watchers.has($previousValue)) {
272
- $watchers.get($previousValue).forEach(callback => {
273
- callback.set ? callback.set(false) : callback(false);
274
- });
277
+ const $previousValueCallbacks = $watchers.get($previousValue);
278
+ if(typeof $previousValueCallbacks === "function") {
279
+ $previousValueCallbacks.set ? $previousValueCallbacks.set(false) : $previousValueCallbacks(false);
280
+ } else {
281
+ $previousValueCallbacks.forEach(callback => {
282
+ callback.set ? callback.set(false) : callback(false);
283
+ });
284
+ }
275
285
  }
276
286
  };
277
287
 
@@ -323,7 +333,9 @@ var NativeDocument = (function (exports) {
323
333
  this.$currentValue = null;
324
334
  if(this.$watchers) {
325
335
  for (const [_, watchValueList] of this.$watchers) {
326
- watchValueList.splice(0);
336
+ if(Validator.isArray(watchValueList)) {
337
+ watchValueList.splice(0);
338
+ }
327
339
  }
328
340
  }
329
341
  this.$watchers?.clear();
@@ -369,17 +381,25 @@ var NativeDocument = (function (exports) {
369
381
  this.$watchers = this.$watchers ?? new Map();
370
382
 
371
383
  let watchValueList = this.$watchers.get(value);
384
+
372
385
  if(!watchValueList) {
373
- watchValueList = [];
386
+ this.$watchers.set(value, callback);
387
+ } else if(!Validator.isArray(watchValueList)) {
388
+ watchValueList = [watchValueList];
374
389
  this.$watchers.set(value, watchValueList);
390
+ return;
391
+ } else {
392
+ watchValueList.push(callback);
375
393
  }
376
394
 
377
- watchValueList.push(callback);
378
395
  this.assocTrigger();
379
396
  return () => {
380
397
  const index = watchValueList.indexOf(callback);
381
398
  watchValueList?.splice(index, 1);
382
- if(watchValueList.size === 0) {
399
+ if(watchValueList.size === 1) {
400
+ this.$watchers.set(value, watchValueList[0]);
401
+ }
402
+ else if(watchValueList.size === 0) {
383
403
  this.$watchers?.delete(value);
384
404
  watchValueList = null;
385
405
  }
@@ -692,6 +712,11 @@ var NativeDocument = (function (exports) {
692
712
 
693
713
  NDElement.prototype.node = NDElement.prototype.htmlElement;
694
714
 
715
+ NDElement.prototype.attach = function(methodName, bindingHydrator) {
716
+ bindingHydrator.$hydrate(this.$element, methodName);
717
+ return this.$element;
718
+ };
719
+
695
720
  const Validator = {
696
721
  isObservable(value) {
697
722
  return value instanceof ObservableItem || value instanceof ObservableChecker || value?.__$isObservable;
@@ -1003,6 +1028,10 @@ var NativeDocument = (function (exports) {
1003
1028
  });
1004
1029
  continue;
1005
1030
  }
1031
+ if(value.$hydrate) {
1032
+ value.$hydrate(element, className);
1033
+ continue;
1034
+ }
1006
1035
  element.classList.toggle(className, value);
1007
1036
  }
1008
1037
  }
@@ -1155,6 +1184,17 @@ var NativeDocument = (function (exports) {
1155
1184
  parent && parent.appendChild(text);
1156
1185
  return text;
1157
1186
  },
1187
+ /**
1188
+ *
1189
+ * @param {HTMLElement|DocumentFragment} parent
1190
+ * @param {{$hydrate: Function}} item
1191
+ * @returns {Text}
1192
+ */
1193
+ createHydratableNode(parent, item) {
1194
+ const text = ElementCreator.createTextNode();
1195
+ item.$hydrate(text);
1196
+ return text;
1197
+ },
1158
1198
 
1159
1199
  /**
1160
1200
  *
@@ -1233,6 +1273,9 @@ var NativeDocument = (function (exports) {
1233
1273
  PluginsManager.emit('BeforeProcessComponent', child);
1234
1274
  return this.getChild(child());
1235
1275
  }
1276
+ if(child?.$hydrate) {
1277
+ return ElementCreator.createHydratableNode(null, child);
1278
+ }
1236
1279
  return ElementCreator.createStaticTextNode(null, child);
1237
1280
  },
1238
1281
  /**
@@ -1384,7 +1427,7 @@ var NativeDocument = (function (exports) {
1384
1427
  }
1385
1428
 
1386
1429
  const normalizeComponentArgs = function(props, children = null) {
1387
- if(!Validator.isJson(props)) {
1430
+ if(!Validator.isJson(props) || props?.$hydrate) {
1388
1431
  const temp = children;
1389
1432
  children = props;
1390
1433
  props = temp;
@@ -1392,6 +1435,18 @@ var NativeDocument = (function (exports) {
1392
1435
  return { props, children };
1393
1436
  };
1394
1437
 
1438
+ /**
1439
+ *
1440
+ * @param {*} value
1441
+ * @returns {Text}
1442
+ */
1443
+ const createTextNode = function(value) {
1444
+ return (Validator.isObservable(value))
1445
+ ? ElementCreator.createObservableNode(null, value)
1446
+ : ElementCreator.createStaticTextNode(null, value);
1447
+ };
1448
+
1449
+
1395
1450
  function createHtmlElement($tagName, _attributes, _children = null, customWrapper) {
1396
1451
  const { props: attributes, children = null } = normalizeComponentArgs(_attributes, _children);
1397
1452
  const element = ElementCreator.createElement($tagName);
@@ -1413,6 +1468,133 @@ var NativeDocument = (function (exports) {
1413
1468
  return (_attributes, _children = null) => createHtmlElement(name.toLowerCase(), _attributes, _children, customWrapper);
1414
1469
  }
1415
1470
 
1471
+ const cloneBindingsDataCache = new WeakMap();
1472
+
1473
+
1474
+ const bindAttributes = (node, bindDingData, data) => {
1475
+ if(!bindDingData) {
1476
+ return null;
1477
+ }
1478
+ const attributes = { };
1479
+ if(bindDingData.attributes) {
1480
+ for (const attr in bindDingData.attributes) {
1481
+ attributes[attr] = bindDingData.attributes[attr](...data);
1482
+ }
1483
+ }
1484
+
1485
+ if(bindDingData.classes) {
1486
+ attributes.class = {};
1487
+ for (const className in bindDingData.classes) {
1488
+ attributes.class[className] = bindDingData.classes[className](...data);
1489
+ }
1490
+ }
1491
+
1492
+ if(bindDingData.styles) {
1493
+ attributes.style = {};
1494
+ for (const property in bindDingData.styles) {
1495
+ attributes.style[property] = bindDingData.styles[property](...data);
1496
+ }
1497
+ }
1498
+
1499
+ if(Object.keys(attributes)) {
1500
+ ElementCreator.processAttributes(node, attributes);
1501
+ return attributes;
1502
+ }
1503
+
1504
+ return null;
1505
+ };
1506
+
1507
+
1508
+ const bindAttachesMethods = function(node, bindDingData, data) {
1509
+ if(!bindDingData?.attaches) {
1510
+ return null;
1511
+ }
1512
+ for(const methodName in bindDingData.attaches) {
1513
+ node.nd[methodName](function(...args) {
1514
+ bindDingData.attaches[methodName].call(this, ...[...args, ...data]);
1515
+ });
1516
+ }
1517
+ };
1518
+
1519
+ function TemplateCloner($fn) {
1520
+ let $node = null;
1521
+
1522
+ const clone = (node, data) => {
1523
+ const bindDingData = cloneBindingsDataCache.get(node);
1524
+ if(node instanceof Text) {
1525
+ if(bindDingData?.value) {
1526
+ return bindDingData.value(data);
1527
+ }
1528
+ return node.cloneNode(true);
1529
+ }
1530
+ const nodeCloned = node.cloneNode();
1531
+ bindAttributes(nodeCloned, bindDingData, data);
1532
+ bindAttachesMethods(nodeCloned, bindDingData, data);
1533
+
1534
+ for(let i = 0, length = node.childNodes.length; i < length; i++) {
1535
+ const childNode = node.childNodes[i];
1536
+ const childNodeCloned = clone(childNode, data);
1537
+ nodeCloned.appendChild(childNodeCloned);
1538
+ }
1539
+ return nodeCloned;
1540
+ };
1541
+
1542
+ this.clone = (data) => {
1543
+ if(!$node) {
1544
+ $node = $fn(this);
1545
+ }
1546
+ return clone($node, data);
1547
+ };
1548
+
1549
+ const createBinding = (hydrateFunction, target) => {
1550
+ return {
1551
+ $hydrate : function(element, property) {
1552
+ if(!cloneBindingsDataCache.has(element)) {
1553
+ // { classes, styles, attributes, value, attaches }
1554
+ cloneBindingsDataCache.set(element, {});
1555
+ }
1556
+ const hydrationState = cloneBindingsDataCache.get(element);
1557
+ if(target === 'value') {
1558
+ hydrationState.value = hydrateFunction;
1559
+ return;
1560
+ }
1561
+ hydrationState[target] = hydrationState[target] || {};
1562
+ hydrationState[target][property] = hydrateFunction;
1563
+ }
1564
+ }
1565
+ };
1566
+
1567
+ this.style = (fn) => {
1568
+ return createBinding(fn, 'styles');
1569
+ };
1570
+ this.class = (fn) => {
1571
+ return createBinding(fn, 'classes');
1572
+ };
1573
+ this.value = (fn) => {
1574
+ return createBinding(function(data) {
1575
+ return createTextNode(fn(...data));
1576
+ }, 'value');
1577
+ };
1578
+ this.attr = (fn) => {
1579
+ return createBinding(fn, 'attributes');
1580
+ };
1581
+ this.attach = (fn) => {
1582
+ return createBinding(fn, 'attaches');
1583
+ };
1584
+ }
1585
+
1586
+ function useCache(fn) {
1587
+ let $cache = null;
1588
+
1589
+ return function(...args) {
1590
+ if(!$cache) {
1591
+ $cache = new TemplateCloner(fn);
1592
+ }
1593
+
1594
+ return $cache.clone(args);
1595
+ };
1596
+ }
1597
+
1416
1598
  Function.prototype.args = function(...args) {
1417
1599
  return exports.withValidation(this, args);
1418
1600
  };
@@ -2111,7 +2293,6 @@ var NativeDocument = (function (exports) {
2111
2293
  },
2112
2294
  removeOne(element, index) {
2113
2295
  removeCacheItemByKey(getItemKey(element, index), true);
2114
- child = null;
2115
2296
  },
2116
2297
  clear,
2117
2298
  merge(items) {
@@ -3402,11 +3583,14 @@ var NativeDocument = (function (exports) {
3402
3583
  exports.NDElement = NDElement;
3403
3584
  exports.Observable = Observable;
3404
3585
  exports.Store = Store;
3586
+ exports.TemplateCloner = TemplateCloner;
3405
3587
  exports.classPropertyAccumulator = classPropertyAccumulator;
3588
+ exports.createTextNode = createTextNode;
3406
3589
  exports.cssPropertyAccumulator = cssPropertyAccumulator;
3407
3590
  exports.elements = elements;
3408
3591
  exports.normalizeComponentArgs = normalizeComponentArgs;
3409
3592
  exports.router = router;
3593
+ exports.useCache = useCache;
3410
3594
 
3411
3595
  return exports;
3412
3596