@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.
@@ -8,7 +8,7 @@ if (globalThis.FAST === void 0) {
8
8
  }
9
9
  const FAST$1 = globalThis.FAST;
10
10
  const debugMessages = {
11
- [1101 /* needsArrayObservation */]: "Must call enableArrayObservation before observing arrays.",
11
+ [1101 /* needsArrayObservation */]: "Must call ArrayObserver.enable() before observing arrays.",
12
12
  [1201 /* onlySetDOMPolicyOnce */]: "The DOM Policy can only be set once.",
13
13
  [1202 /* bindingInnerHTMLRequiresTrustedTypes */]: "To bind innerHTML, you must use a TrustedTypesPolicy.",
14
14
  [1203 /* twoWayBindingRequiresObservables */]: "View=>Model update skipped. To use twoWay binding, the target property must be observable.",
@@ -1299,6 +1299,19 @@ class Splice {
1299
1299
  return this;
1300
1300
  }
1301
1301
  }
1302
+ /**
1303
+ * A sort array indicates new index positions of array items.
1304
+ * @public
1305
+ */
1306
+ class Sort {
1307
+ /**
1308
+ * Creates a sort update.
1309
+ * @param sorted - The updated index of sorted items.
1310
+ */
1311
+ constructor(sorted) {
1312
+ this.sorted = sorted;
1313
+ }
1314
+ }
1302
1315
  /**
1303
1316
  * Indicates what level of feature support the splice
1304
1317
  * strategy provides.
@@ -1617,7 +1630,7 @@ function project(array, changes) {
1617
1630
  * splices needed to represent the change from the old array to the new array.
1618
1631
  * @public
1619
1632
  */
1620
- let defaultSpliceStrategy = Object.freeze({
1633
+ let defaultMutationStrategy = Object.freeze({
1621
1634
  support: SpliceStrategySupport.optimized,
1622
1635
  normalize(previous, current, changes) {
1623
1636
  if (previous === void 0) {
@@ -1643,7 +1656,12 @@ let defaultSpliceStrategy = Object.freeze({
1643
1656
  },
1644
1657
  reverse(array, observer, reverse, args) {
1645
1658
  const result = reverse.apply(array, args);
1646
- observer.reset(array);
1659
+ array.sorted++;
1660
+ const sortedItems = [];
1661
+ for (let i = array.length - 1; i >= 0; i--) {
1662
+ sortedItems.push(i);
1663
+ }
1664
+ observer.addSort(new Sort(sortedItems));
1647
1665
  return result;
1648
1666
  },
1649
1667
  shift(array, observer, shift, args) {
@@ -1655,8 +1673,20 @@ let defaultSpliceStrategy = Object.freeze({
1655
1673
  return result;
1656
1674
  },
1657
1675
  sort(array, observer, sort, args) {
1676
+ const map = new Map();
1677
+ for (let i = 0, ii = array.length; i < ii; ++i) {
1678
+ const mapValue = map.get(array[i]) || [];
1679
+ map.set(array[i], [...mapValue, i]);
1680
+ }
1658
1681
  const result = sort.apply(array, args);
1659
- observer.reset(array);
1682
+ array.sorted++;
1683
+ const sortedItems = [];
1684
+ for (let i = 0, ii = array.length; i < ii; ++i) {
1685
+ const indexs = map.get(array[i]);
1686
+ sortedItems.push(indexs[0]);
1687
+ map.set(array[i], indexs.splice(1));
1688
+ }
1689
+ observer.addSort(new Sort(sortedItems));
1660
1690
  return result;
1661
1691
  },
1662
1692
  splice(array, observer, splice, args) {
@@ -1684,13 +1714,14 @@ const SpliceStrategy = Object.freeze({
1684
1714
  * @param strategy - The splice strategy to use.
1685
1715
  */
1686
1716
  setDefaultStrategy(strategy) {
1687
- defaultSpliceStrategy = strategy;
1717
+ defaultMutationStrategy = strategy;
1688
1718
  },
1689
1719
  });
1690
- function setNonEnumerable(target, property, value) {
1720
+ function setNonEnumerable(target, property, value, writable = true) {
1691
1721
  Reflect.defineProperty(target, property, {
1692
1722
  value,
1693
1723
  enumerable: false,
1724
+ writable,
1694
1725
  });
1695
1726
  }
1696
1727
  class DefaultArrayObserver extends SubscriberSet {
@@ -1698,9 +1729,11 @@ class DefaultArrayObserver extends SubscriberSet {
1698
1729
  super(subject);
1699
1730
  this.oldCollection = void 0;
1700
1731
  this.splices = void 0;
1732
+ this.sorts = void 0;
1701
1733
  this.needsQueue = true;
1702
1734
  this._strategy = null;
1703
1735
  this._lengthObserver = void 0;
1736
+ this._sortObserver = void 0;
1704
1737
  this.call = this.flush;
1705
1738
  setNonEnumerable(subject, "$fastController", this);
1706
1739
  }
@@ -1727,6 +1760,23 @@ class DefaultArrayObserver extends SubscriberSet {
1727
1760
  }
1728
1761
  return observer;
1729
1762
  }
1763
+ get sortObserver() {
1764
+ let observer = this._sortObserver;
1765
+ if (observer === void 0) {
1766
+ const array = this.subject;
1767
+ this._sortObserver = observer = {
1768
+ sorted: array.sorted,
1769
+ handleChange() {
1770
+ if (this.sorted !== array.sorted) {
1771
+ this.sorted = array.sorted;
1772
+ Observable.notify(observer, "sorted");
1773
+ }
1774
+ },
1775
+ };
1776
+ this.subscribe(observer);
1777
+ }
1778
+ return observer;
1779
+ }
1730
1780
  subscribe(subscriber) {
1731
1781
  this.flush();
1732
1782
  super.subscribe(subscriber);
@@ -1740,6 +1790,15 @@ class DefaultArrayObserver extends SubscriberSet {
1740
1790
  }
1741
1791
  this.enqueue();
1742
1792
  }
1793
+ addSort(sort) {
1794
+ if (this.sorts === void 0) {
1795
+ this.sorts = [sort];
1796
+ }
1797
+ else {
1798
+ this.sorts.push(sort);
1799
+ }
1800
+ this.enqueue();
1801
+ }
1743
1802
  reset(oldCollection) {
1744
1803
  this.oldCollection = oldCollection;
1745
1804
  this.enqueue();
@@ -1747,14 +1806,18 @@ class DefaultArrayObserver extends SubscriberSet {
1747
1806
  flush() {
1748
1807
  var _a;
1749
1808
  const splices = this.splices;
1809
+ const sorts = this.sorts;
1750
1810
  const oldCollection = this.oldCollection;
1751
- if (splices === void 0 && oldCollection === void 0) {
1811
+ if (splices === void 0 && oldCollection === void 0 && sorts === void 0) {
1752
1812
  return;
1753
1813
  }
1754
1814
  this.needsQueue = true;
1755
1815
  this.splices = void 0;
1816
+ this.sorts = void 0;
1756
1817
  this.oldCollection = void 0;
1757
- this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy).normalize(oldCollection, this.subject, splices));
1818
+ sorts !== void 0
1819
+ ? this.notify(sorts)
1820
+ : this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy).normalize(oldCollection, this.subject, splices));
1758
1821
  }
1759
1822
  enqueue() {
1760
1823
  if (this.needsQueue) {
@@ -1769,6 +1832,7 @@ let enabled = false;
1769
1832
  * @public
1770
1833
  */
1771
1834
  const ArrayObserver = Object.freeze({
1835
+ sorted: 0,
1772
1836
  /**
1773
1837
  * Enables the array observation mechanism.
1774
1838
  * @remarks
@@ -1785,6 +1849,7 @@ const ArrayObserver = Object.freeze({
1785
1849
  const proto = Array.prototype;
1786
1850
  if (!proto.$fastPatch) {
1787
1851
  setNonEnumerable(proto, "$fastPatch", 1);
1852
+ setNonEnumerable(proto, "sorted", 0);
1788
1853
  [
1789
1854
  proto.pop,
1790
1855
  proto.push,
@@ -1799,7 +1864,7 @@ const ArrayObserver = Object.freeze({
1799
1864
  const o = this.$fastController;
1800
1865
  return o === void 0
1801
1866
  ? method.apply(this, args)
1802
- : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy)[method.name](this, o, method, args);
1867
+ : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy)[method.name](this, o, method, args);
1803
1868
  };
1804
1869
  });
1805
1870
  }
@@ -1823,6 +1888,24 @@ function lengthOf(array) {
1823
1888
  Observable.track(arrayObserver.lengthObserver, "length");
1824
1889
  return array.length;
1825
1890
  }
1891
+ /**
1892
+ * Enables observing the sorted property of an array.
1893
+ * @param array - The array to observe the sorted property of.
1894
+ * @returns The sorted property.
1895
+ * @public
1896
+ */
1897
+ function sortedCount(array) {
1898
+ if (!array) {
1899
+ return 0;
1900
+ }
1901
+ let arrayObserver = array.$fastController;
1902
+ if (arrayObserver === void 0) {
1903
+ ArrayObserver.enable();
1904
+ arrayObserver = Observable.getNotifier(array);
1905
+ }
1906
+ Observable.track(arrayObserver.sortObserver, "sorted");
1907
+ return array.sorted;
1908
+ }
1826
1909
 
1827
1910
  /**
1828
1911
  * Captures a binding expression along with related information and capabilities.
@@ -3927,8 +4010,11 @@ class RepeatBehavior {
3927
4010
  else if (args[0].reset) {
3928
4011
  this.refreshAllViews();
3929
4012
  }
4013
+ else if (args[0].sorted) {
4014
+ this.updateSortedViews(args);
4015
+ }
3930
4016
  else {
3931
- this.updateViews(args);
4017
+ this.updateSplicedViews(args);
3932
4018
  }
3933
4019
  }
3934
4020
  observeItems(force = false) {
@@ -3946,7 +4032,27 @@ class RepeatBehavior {
3946
4032
  newObserver.subscribe(this);
3947
4033
  }
3948
4034
  }
3949
- updateViews(splices) {
4035
+ updateSortedViews(sorts) {
4036
+ const views = this.views;
4037
+ for (let i = 0, ii = sorts.length; i < ii; ++i) {
4038
+ const sortedItems = sorts[i].sorted.slice();
4039
+ const unsortedItems = sortedItems.slice().sort();
4040
+ for (let j = 0, jj = sortedItems.length; j < jj; ++j) {
4041
+ const sortedIndex = sortedItems.find(value => sortedItems[j] === unsortedItems[value]);
4042
+ if (sortedIndex !== j) {
4043
+ const removedItems = unsortedItems.splice(sortedIndex, 1);
4044
+ unsortedItems.splice(j, 0, ...removedItems);
4045
+ const neighbor = views[j];
4046
+ const location = neighbor ? neighbor.firstChild : this.location;
4047
+ views[sortedIndex].remove();
4048
+ views[sortedIndex].insertBefore(location);
4049
+ const removedViews = views.splice(sortedIndex, 1);
4050
+ views.splice(j, 0, ...removedViews);
4051
+ }
4052
+ }
4053
+ }
4054
+ }
4055
+ updateSplicedViews(splices) {
3950
4056
  const views = this.views;
3951
4057
  const bindView = this.bindView;
3952
4058
  const items = this.items;
@@ -4380,6 +4486,37 @@ function children(propertyOrOptions) {
4380
4486
  return new ChildrenDirective(propertyOrOptions);
4381
4487
  }
4382
4488
 
4489
+ /******************************************************************************
4490
+ Copyright (c) Microsoft Corporation.
4491
+
4492
+ Permission to use, copy, modify, and/or distribute this software for any
4493
+ purpose with or without fee is hereby granted.
4494
+
4495
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
4496
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
4497
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
4498
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
4499
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
4500
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4501
+ PERFORMANCE OF THIS SOFTWARE.
4502
+ ***************************************************************************** */
4503
+
4504
+ function __decorate(decorators, target, key, desc) {
4505
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4506
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4507
+ 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;
4508
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4509
+ }
4510
+
4511
+ function __metadata(metadataKey, metadataValue) {
4512
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
4513
+ }
4514
+
4515
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
4516
+ var e = new Error(message);
4517
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
4518
+ };
4519
+
4383
4520
  const booleanMode = "boolean";
4384
4521
  const reflectMode = "reflect";
4385
4522
  /**
@@ -4591,6 +4728,10 @@ function attr(configOrTarget, prop) {
4591
4728
  const defaultShadowOptions = { mode: "open" };
4592
4729
  const defaultElementOptions = {};
4593
4730
  const fastElementBaseTypes = new Set();
4731
+ /**
4732
+ * The FAST custom element registry
4733
+ * @internal
4734
+ */
4594
4735
  const fastElementRegistry = FAST.getById(KernelServiceId.elementRegistry, () => createTypeRegistry());
4595
4736
  /**
4596
4737
  * Defines metadata for a FASTElement.
@@ -4691,6 +4832,10 @@ FASTElementDefinition.getByType = fastElementRegistry.getByType;
4691
4832
  * @param instance - The custom element instance to retrieve the definition for.
4692
4833
  */
4693
4834
  FASTElementDefinition.getForInstance = fastElementRegistry.getForInstance;
4835
+ __decorate([
4836
+ observable,
4837
+ __metadata("design:type", Object)
4838
+ ], FASTElementDefinition.prototype, "template", void 0);
4694
4839
 
4695
4840
  /**
4696
4841
  * A Behavior that enables advanced rendering.
@@ -5609,20 +5754,27 @@ class ElementController extends PropertyChangeNotifier {
5609
5754
  /**
5610
5755
  * Locates or creates a controller for the specified element.
5611
5756
  * @param element - The element to return the controller for.
5757
+ * @param override - Reset the controller even if one has been defined.
5612
5758
  * @remarks
5613
5759
  * The specified element must have a {@link FASTElementDefinition}
5614
5760
  * registered either through the use of the {@link customElement}
5615
5761
  * decorator or a call to `FASTElement.define`.
5616
5762
  */
5617
- static forCustomElement(element) {
5763
+ static forCustomElement(element, override = false) {
5618
5764
  const controller = element.$fastController;
5619
- if (controller !== void 0) {
5765
+ if (controller !== void 0 && !override) {
5620
5766
  return controller;
5621
5767
  }
5622
5768
  const definition = FASTElementDefinition.getForInstance(element);
5623
5769
  if (definition === void 0) {
5624
5770
  throw FAST.error(1401 /* Message.missingElementDefinition */);
5625
5771
  }
5772
+ Observable.getNotifier(definition).subscribe({
5773
+ handleChange: () => {
5774
+ ElementController.forCustomElement(element, true);
5775
+ element.$fastController.connect();
5776
+ },
5777
+ }, "template");
5626
5778
  return (element.$fastController = new elementControllerStrategy(element, definition));
5627
5779
  }
5628
5780
  /**
@@ -5917,4 +6069,4 @@ function customElement(nameOrDef) {
5917
6069
 
5918
6070
  DOM.setPolicy(DOMPolicy.create());
5919
6071
 
5920
- 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 };
6072
+ 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 };