@microsoft/fast-element 2.0.1 → 2.2.0

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.
@@ -1232,6 +1232,19 @@ class Splice {
1232
1232
  return this;
1233
1233
  }
1234
1234
  }
1235
+ /**
1236
+ * A sort array indicates new index positions of array items.
1237
+ * @public
1238
+ */
1239
+ class Sort {
1240
+ /**
1241
+ * Creates a sort update.
1242
+ * @param sorted - The updated index of sorted items.
1243
+ */
1244
+ constructor(sorted) {
1245
+ this.sorted = sorted;
1246
+ }
1247
+ }
1235
1248
  /**
1236
1249
  * Indicates what level of feature support the splice
1237
1250
  * strategy provides.
@@ -1550,7 +1563,7 @@ function project(array, changes) {
1550
1563
  * splices needed to represent the change from the old array to the new array.
1551
1564
  * @public
1552
1565
  */
1553
- let defaultSpliceStrategy = Object.freeze({
1566
+ let defaultMutationStrategy = Object.freeze({
1554
1567
  support: SpliceStrategySupport.optimized,
1555
1568
  normalize(previous, current, changes) {
1556
1569
  if (previous === void 0) {
@@ -1576,7 +1589,12 @@ let defaultSpliceStrategy = Object.freeze({
1576
1589
  },
1577
1590
  reverse(array, observer, reverse, args) {
1578
1591
  const result = reverse.apply(array, args);
1579
- observer.reset(array);
1592
+ array.sorted++;
1593
+ const sortedItems = [];
1594
+ for (let i = array.length - 1; i >= 0; i--) {
1595
+ sortedItems.push(i);
1596
+ }
1597
+ observer.addSort(new Sort(sortedItems));
1580
1598
  return result;
1581
1599
  },
1582
1600
  shift(array, observer, shift, args) {
@@ -1588,8 +1606,20 @@ let defaultSpliceStrategy = Object.freeze({
1588
1606
  return result;
1589
1607
  },
1590
1608
  sort(array, observer, sort, args) {
1609
+ const map = new Map();
1610
+ for (let i = 0, ii = array.length; i < ii; ++i) {
1611
+ const mapValue = map.get(array[i]) || [];
1612
+ map.set(array[i], [...mapValue, i]);
1613
+ }
1591
1614
  const result = sort.apply(array, args);
1592
- observer.reset(array);
1615
+ array.sorted++;
1616
+ const sortedItems = [];
1617
+ for (let i = 0, ii = array.length; i < ii; ++i) {
1618
+ const indexs = map.get(array[i]);
1619
+ sortedItems.push(indexs[0]);
1620
+ map.set(array[i], indexs.splice(1));
1621
+ }
1622
+ observer.addSort(new Sort(sortedItems));
1593
1623
  return result;
1594
1624
  },
1595
1625
  splice(array, observer, splice, args) {
@@ -1617,13 +1647,14 @@ const SpliceStrategy = Object.freeze({
1617
1647
  * @param strategy - The splice strategy to use.
1618
1648
  */
1619
1649
  setDefaultStrategy(strategy) {
1620
- defaultSpliceStrategy = strategy;
1650
+ defaultMutationStrategy = strategy;
1621
1651
  },
1622
1652
  });
1623
- function setNonEnumerable(target, property, value) {
1653
+ function setNonEnumerable(target, property, value, writable = true) {
1624
1654
  Reflect.defineProperty(target, property, {
1625
1655
  value,
1626
1656
  enumerable: false,
1657
+ writable,
1627
1658
  });
1628
1659
  }
1629
1660
  class DefaultArrayObserver extends SubscriberSet {
@@ -1631,9 +1662,11 @@ class DefaultArrayObserver extends SubscriberSet {
1631
1662
  super(subject);
1632
1663
  this.oldCollection = void 0;
1633
1664
  this.splices = void 0;
1665
+ this.sorts = void 0;
1634
1666
  this.needsQueue = true;
1635
1667
  this._strategy = null;
1636
1668
  this._lengthObserver = void 0;
1669
+ this._sortObserver = void 0;
1637
1670
  this.call = this.flush;
1638
1671
  setNonEnumerable(subject, "$fastController", this);
1639
1672
  }
@@ -1660,6 +1693,23 @@ class DefaultArrayObserver extends SubscriberSet {
1660
1693
  }
1661
1694
  return observer;
1662
1695
  }
1696
+ get sortObserver() {
1697
+ let observer = this._sortObserver;
1698
+ if (observer === void 0) {
1699
+ const array = this.subject;
1700
+ this._sortObserver = observer = {
1701
+ sorted: array.sorted,
1702
+ handleChange() {
1703
+ if (this.sorted !== array.sorted) {
1704
+ this.sorted = array.sorted;
1705
+ Observable.notify(observer, "sorted");
1706
+ }
1707
+ },
1708
+ };
1709
+ this.subscribe(observer);
1710
+ }
1711
+ return observer;
1712
+ }
1663
1713
  subscribe(subscriber) {
1664
1714
  this.flush();
1665
1715
  super.subscribe(subscriber);
@@ -1673,6 +1723,15 @@ class DefaultArrayObserver extends SubscriberSet {
1673
1723
  }
1674
1724
  this.enqueue();
1675
1725
  }
1726
+ addSort(sort) {
1727
+ if (this.sorts === void 0) {
1728
+ this.sorts = [sort];
1729
+ }
1730
+ else {
1731
+ this.sorts.push(sort);
1732
+ }
1733
+ this.enqueue();
1734
+ }
1676
1735
  reset(oldCollection) {
1677
1736
  this.oldCollection = oldCollection;
1678
1737
  this.enqueue();
@@ -1680,14 +1739,18 @@ class DefaultArrayObserver extends SubscriberSet {
1680
1739
  flush() {
1681
1740
  var _a;
1682
1741
  const splices = this.splices;
1742
+ const sorts = this.sorts;
1683
1743
  const oldCollection = this.oldCollection;
1684
- if (splices === void 0 && oldCollection === void 0) {
1744
+ if (splices === void 0 && oldCollection === void 0 && sorts === void 0) {
1685
1745
  return;
1686
1746
  }
1687
1747
  this.needsQueue = true;
1688
1748
  this.splices = void 0;
1749
+ this.sorts = void 0;
1689
1750
  this.oldCollection = void 0;
1690
- this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy).normalize(oldCollection, this.subject, splices));
1751
+ sorts !== void 0
1752
+ ? this.notify(sorts)
1753
+ : this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy).normalize(oldCollection, this.subject, splices));
1691
1754
  }
1692
1755
  enqueue() {
1693
1756
  if (this.needsQueue) {
@@ -1702,6 +1765,7 @@ let enabled = false;
1702
1765
  * @public
1703
1766
  */
1704
1767
  const ArrayObserver = Object.freeze({
1768
+ sorted: 0,
1705
1769
  /**
1706
1770
  * Enables the array observation mechanism.
1707
1771
  * @remarks
@@ -1718,6 +1782,7 @@ const ArrayObserver = Object.freeze({
1718
1782
  const proto = Array.prototype;
1719
1783
  if (!proto.$fastPatch) {
1720
1784
  setNonEnumerable(proto, "$fastPatch", 1);
1785
+ setNonEnumerable(proto, "sorted", 0);
1721
1786
  [
1722
1787
  proto.pop,
1723
1788
  proto.push,
@@ -1732,7 +1797,7 @@ const ArrayObserver = Object.freeze({
1732
1797
  const o = this.$fastController;
1733
1798
  return o === void 0
1734
1799
  ? method.apply(this, args)
1735
- : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy)[method.name](this, o, method, args);
1800
+ : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy)[method.name](this, o, method, args);
1736
1801
  };
1737
1802
  });
1738
1803
  }
@@ -1756,6 +1821,24 @@ function lengthOf(array) {
1756
1821
  Observable.track(arrayObserver.lengthObserver, "length");
1757
1822
  return array.length;
1758
1823
  }
1824
+ /**
1825
+ * Enables observing the sorted property of an array.
1826
+ * @param array - The array to observe the sorted property of.
1827
+ * @returns The sorted property.
1828
+ * @public
1829
+ */
1830
+ function sortedCount(array) {
1831
+ if (!array) {
1832
+ return 0;
1833
+ }
1834
+ let arrayObserver = array.$fastController;
1835
+ if (arrayObserver === void 0) {
1836
+ ArrayObserver.enable();
1837
+ arrayObserver = Observable.getNotifier(array);
1838
+ }
1839
+ Observable.track(arrayObserver.sortObserver, "sorted");
1840
+ return array.sorted;
1841
+ }
1759
1842
 
1760
1843
  /**
1761
1844
  * Captures a binding expression along with related information and capabilities.
@@ -3860,8 +3943,11 @@ class RepeatBehavior {
3860
3943
  else if (args[0].reset) {
3861
3944
  this.refreshAllViews();
3862
3945
  }
3946
+ else if (args[0].sorted) {
3947
+ this.updateSortedViews(args);
3948
+ }
3863
3949
  else {
3864
- this.updateViews(args);
3950
+ this.updateSplicedViews(args);
3865
3951
  }
3866
3952
  }
3867
3953
  observeItems(force = false) {
@@ -3879,7 +3965,27 @@ class RepeatBehavior {
3879
3965
  newObserver.subscribe(this);
3880
3966
  }
3881
3967
  }
3882
- updateViews(splices) {
3968
+ updateSortedViews(sorts) {
3969
+ const views = this.views;
3970
+ for (let i = 0, ii = sorts.length; i < ii; ++i) {
3971
+ const sortedItems = sorts[i].sorted.slice();
3972
+ const unsortedItems = sortedItems.slice().sort();
3973
+ for (let j = 0, jj = sortedItems.length; j < jj; ++j) {
3974
+ const sortedIndex = sortedItems.find(value => sortedItems[j] === unsortedItems[value]);
3975
+ if (sortedIndex !== j) {
3976
+ const removedItems = unsortedItems.splice(sortedIndex, 1);
3977
+ unsortedItems.splice(j, 0, ...removedItems);
3978
+ const neighbor = views[j];
3979
+ const location = neighbor ? neighbor.firstChild : this.location;
3980
+ views[sortedIndex].remove();
3981
+ views[sortedIndex].insertBefore(location);
3982
+ const removedViews = views.splice(sortedIndex, 1);
3983
+ views.splice(j, 0, ...removedViews);
3984
+ }
3985
+ }
3986
+ }
3987
+ }
3988
+ updateSplicedViews(splices) {
3883
3989
  const views = this.views;
3884
3990
  const bindView = this.bindView;
3885
3991
  const items = this.items;
@@ -4313,6 +4419,37 @@ function children(propertyOrOptions) {
4313
4419
  return new ChildrenDirective(propertyOrOptions);
4314
4420
  }
4315
4421
 
4422
+ /******************************************************************************
4423
+ Copyright (c) Microsoft Corporation.
4424
+
4425
+ Permission to use, copy, modify, and/or distribute this software for any
4426
+ purpose with or without fee is hereby granted.
4427
+
4428
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
4429
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
4430
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
4431
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
4432
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
4433
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4434
+ PERFORMANCE OF THIS SOFTWARE.
4435
+ ***************************************************************************** */
4436
+
4437
+ function __decorate(decorators, target, key, desc) {
4438
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4439
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4440
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
4441
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4442
+ }
4443
+
4444
+ function __metadata(metadataKey, metadataValue) {
4445
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
4446
+ }
4447
+
4448
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
4449
+ var e = new Error(message);
4450
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
4451
+ };
4452
+
4316
4453
  const booleanMode = "boolean";
4317
4454
  const reflectMode = "reflect";
4318
4455
  /**
@@ -4524,6 +4661,10 @@ function attr(configOrTarget, prop) {
4524
4661
  const defaultShadowOptions = { mode: "open" };
4525
4662
  const defaultElementOptions = {};
4526
4663
  const fastElementBaseTypes = new Set();
4664
+ /**
4665
+ * The FAST custom element registry
4666
+ * @internal
4667
+ */
4527
4668
  const fastElementRegistry = FAST.getById(KernelServiceId.elementRegistry, () => createTypeRegistry());
4528
4669
  /**
4529
4670
  * Defines metadata for a FASTElement.
@@ -4624,6 +4765,10 @@ FASTElementDefinition.getByType = fastElementRegistry.getByType;
4624
4765
  * @param instance - The custom element instance to retrieve the definition for.
4625
4766
  */
4626
4767
  FASTElementDefinition.getForInstance = fastElementRegistry.getForInstance;
4768
+ __decorate([
4769
+ observable,
4770
+ __metadata("design:type", Object)
4771
+ ], FASTElementDefinition.prototype, "template", void 0);
4627
4772
 
4628
4773
  /**
4629
4774
  * A Behavior that enables advanced rendering.
@@ -5542,20 +5687,27 @@ class ElementController extends PropertyChangeNotifier {
5542
5687
  /**
5543
5688
  * Locates or creates a controller for the specified element.
5544
5689
  * @param element - The element to return the controller for.
5690
+ * @param override - Reset the controller even if one has been defined.
5545
5691
  * @remarks
5546
5692
  * The specified element must have a {@link FASTElementDefinition}
5547
5693
  * registered either through the use of the {@link customElement}
5548
5694
  * decorator or a call to `FASTElement.define`.
5549
5695
  */
5550
- static forCustomElement(element) {
5696
+ static forCustomElement(element, override = false) {
5551
5697
  const controller = element.$fastController;
5552
- if (controller !== void 0) {
5698
+ if (controller !== void 0 && !override) {
5553
5699
  return controller;
5554
5700
  }
5555
5701
  const definition = FASTElementDefinition.getForInstance(element);
5556
5702
  if (definition === void 0) {
5557
5703
  throw FAST.error(1401 /* Message.missingElementDefinition */);
5558
5704
  }
5705
+ Observable.getNotifier(definition).subscribe({
5706
+ handleChange: () => {
5707
+ ElementController.forCustomElement(element, true);
5708
+ element.$fastController.connect();
5709
+ },
5710
+ }, "template");
5559
5711
  return (element.$fastController = new elementControllerStrategy(element, definition));
5560
5712
  }
5561
5713
  /**
@@ -5850,4 +6002,4 @@ function customElement(nameOrDef) {
5850
6002
 
5851
6003
  DOM.setPolicy(DOMPolicy.create());
5852
6004
 
5853
- export { ArrayObserver, AttributeConfiguration, AttributeDefinition, Binding, CSSBindingDirective, CSSDirective, ChildrenDirective, Compiler, DOM, DOMAspect, ElementController, ElementStyles, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, HydratableElementController, HydrationBindingError, InlineTemplateDirective, Markup, NodeObservationDirective, Observable, Parser, PropertyChangeNotifier, RefDirective, RenderBehavior, RenderDirective, RepeatBehavior, RepeatDirective, SlottedDirective, SourceLifetime, Splice, SpliceStrategy, SpliceStrategySupport, StatelessAttachedAttributeDirective, SubscriberSet, Updates, ViewTemplate, attr, booleanConverter, children, css, cssDirective, customElement, elements, emptyArray, html, htmlDirective, lengthOf, listener, normalizeBinding$1 as normalizeBinding, nullableBooleanConverter, nullableNumberConverter, observable, oneTime, oneWay, ref, render, repeat, slotted, volatile, when };
6005
+ export { ArrayObserver, AttributeConfiguration, AttributeDefinition, Binding, CSSBindingDirective, CSSDirective, ChildrenDirective, Compiler, DOM, DOMAspect, ElementController, ElementStyles, ExecutionContext, FAST, FASTElement, FASTElementDefinition, HTMLBindingDirective, HTMLDirective, HTMLView, HydratableElementController, HydrationBindingError, InlineTemplateDirective, Markup, NodeObservationDirective, Observable, Parser, PropertyChangeNotifier, RefDirective, RenderBehavior, RenderDirective, RepeatBehavior, RepeatDirective, SlottedDirective, Sort, SourceLifetime, Splice, SpliceStrategy, SpliceStrategySupport, StatelessAttachedAttributeDirective, SubscriberSet, Updates, ViewTemplate, attr, booleanConverter, children, css, cssDirective, customElement, elements, emptyArray, fastElementRegistry, html, htmlDirective, lengthOf, listener, normalizeBinding$1 as normalizeBinding, nullableBooleanConverter, nullableNumberConverter, observable, oneTime, oneWay, ref, render, repeat, slotted, sortedCount, volatile, when };