@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.
@@ -44,6 +44,19 @@ export class Splice {
44
44
  return this;
45
45
  }
46
46
  }
47
+ /**
48
+ * A sort array indicates new index positions of array items.
49
+ * @public
50
+ */
51
+ export class Sort {
52
+ /**
53
+ * Creates a sort update.
54
+ * @param sorted - The updated index of sorted items.
55
+ */
56
+ constructor(sorted) {
57
+ this.sorted = sorted;
58
+ }
59
+ }
47
60
  /**
48
61
  * Indicates what level of feature support the splice
49
62
  * strategy provides.
@@ -362,7 +375,7 @@ function project(array, changes) {
362
375
  * splices needed to represent the change from the old array to the new array.
363
376
  * @public
364
377
  */
365
- let defaultSpliceStrategy = Object.freeze({
378
+ let defaultMutationStrategy = Object.freeze({
366
379
  support: SpliceStrategySupport.optimized,
367
380
  normalize(previous, current, changes) {
368
381
  if (previous === void 0) {
@@ -388,7 +401,12 @@ let defaultSpliceStrategy = Object.freeze({
388
401
  },
389
402
  reverse(array, observer, reverse, args) {
390
403
  const result = reverse.apply(array, args);
391
- observer.reset(array);
404
+ array.sorted++;
405
+ const sortedItems = [];
406
+ for (let i = array.length - 1; i >= 0; i--) {
407
+ sortedItems.push(i);
408
+ }
409
+ observer.addSort(new Sort(sortedItems));
392
410
  return result;
393
411
  },
394
412
  shift(array, observer, shift, args) {
@@ -400,8 +418,20 @@ let defaultSpliceStrategy = Object.freeze({
400
418
  return result;
401
419
  },
402
420
  sort(array, observer, sort, args) {
421
+ const map = new Map();
422
+ for (let i = 0, ii = array.length; i < ii; ++i) {
423
+ const mapValue = map.get(array[i]) || [];
424
+ map.set(array[i], [...mapValue, i]);
425
+ }
403
426
  const result = sort.apply(array, args);
404
- observer.reset(array);
427
+ array.sorted++;
428
+ const sortedItems = [];
429
+ for (let i = 0, ii = array.length; i < ii; ++i) {
430
+ const indexs = map.get(array[i]);
431
+ sortedItems.push(indexs[0]);
432
+ map.set(array[i], indexs.splice(1));
433
+ }
434
+ observer.addSort(new Sort(sortedItems));
405
435
  return result;
406
436
  },
407
437
  splice(array, observer, splice, args) {
@@ -429,13 +459,14 @@ export const SpliceStrategy = Object.freeze({
429
459
  * @param strategy - The splice strategy to use.
430
460
  */
431
461
  setDefaultStrategy(strategy) {
432
- defaultSpliceStrategy = strategy;
462
+ defaultMutationStrategy = strategy;
433
463
  },
434
464
  });
435
- function setNonEnumerable(target, property, value) {
465
+ function setNonEnumerable(target, property, value, writable = true) {
436
466
  Reflect.defineProperty(target, property, {
437
467
  value,
438
468
  enumerable: false,
469
+ writable,
439
470
  });
440
471
  }
441
472
  class DefaultArrayObserver extends SubscriberSet {
@@ -443,9 +474,11 @@ class DefaultArrayObserver extends SubscriberSet {
443
474
  super(subject);
444
475
  this.oldCollection = void 0;
445
476
  this.splices = void 0;
477
+ this.sorts = void 0;
446
478
  this.needsQueue = true;
447
479
  this._strategy = null;
448
480
  this._lengthObserver = void 0;
481
+ this._sortObserver = void 0;
449
482
  this.call = this.flush;
450
483
  setNonEnumerable(subject, "$fastController", this);
451
484
  }
@@ -472,6 +505,23 @@ class DefaultArrayObserver extends SubscriberSet {
472
505
  }
473
506
  return observer;
474
507
  }
508
+ get sortObserver() {
509
+ let observer = this._sortObserver;
510
+ if (observer === void 0) {
511
+ const array = this.subject;
512
+ this._sortObserver = observer = {
513
+ sorted: array.sorted,
514
+ handleChange() {
515
+ if (this.sorted !== array.sorted) {
516
+ this.sorted = array.sorted;
517
+ Observable.notify(observer, "sorted");
518
+ }
519
+ },
520
+ };
521
+ this.subscribe(observer);
522
+ }
523
+ return observer;
524
+ }
475
525
  subscribe(subscriber) {
476
526
  this.flush();
477
527
  super.subscribe(subscriber);
@@ -485,6 +535,15 @@ class DefaultArrayObserver extends SubscriberSet {
485
535
  }
486
536
  this.enqueue();
487
537
  }
538
+ addSort(sort) {
539
+ if (this.sorts === void 0) {
540
+ this.sorts = [sort];
541
+ }
542
+ else {
543
+ this.sorts.push(sort);
544
+ }
545
+ this.enqueue();
546
+ }
488
547
  reset(oldCollection) {
489
548
  this.oldCollection = oldCollection;
490
549
  this.enqueue();
@@ -492,14 +551,18 @@ class DefaultArrayObserver extends SubscriberSet {
492
551
  flush() {
493
552
  var _a;
494
553
  const splices = this.splices;
554
+ const sorts = this.sorts;
495
555
  const oldCollection = this.oldCollection;
496
- if (splices === void 0 && oldCollection === void 0) {
556
+ if (splices === void 0 && oldCollection === void 0 && sorts === void 0) {
497
557
  return;
498
558
  }
499
559
  this.needsQueue = true;
500
560
  this.splices = void 0;
561
+ this.sorts = void 0;
501
562
  this.oldCollection = void 0;
502
- this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy).normalize(oldCollection, this.subject, splices));
563
+ sorts !== void 0
564
+ ? this.notify(sorts)
565
+ : this.notify(((_a = this._strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy).normalize(oldCollection, this.subject, splices));
503
566
  }
504
567
  enqueue() {
505
568
  if (this.needsQueue) {
@@ -514,6 +577,7 @@ let enabled = false;
514
577
  * @public
515
578
  */
516
579
  export const ArrayObserver = Object.freeze({
580
+ sorted: 0,
517
581
  /**
518
582
  * Enables the array observation mechanism.
519
583
  * @remarks
@@ -530,6 +594,7 @@ export const ArrayObserver = Object.freeze({
530
594
  const proto = Array.prototype;
531
595
  if (!proto.$fastPatch) {
532
596
  setNonEnumerable(proto, "$fastPatch", 1);
597
+ setNonEnumerable(proto, "sorted", 0);
533
598
  [
534
599
  proto.pop,
535
600
  proto.push,
@@ -544,7 +609,7 @@ export const ArrayObserver = Object.freeze({
544
609
  const o = this.$fastController;
545
610
  return o === void 0
546
611
  ? method.apply(this, args)
547
- : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultSpliceStrategy)[method.name](this, o, method, args);
612
+ : ((_a = o.strategy) !== null && _a !== void 0 ? _a : defaultMutationStrategy)[method.name](this, o, method, args);
548
613
  };
549
614
  });
550
615
  }
@@ -568,3 +633,21 @@ export function lengthOf(array) {
568
633
  Observable.track(arrayObserver.lengthObserver, "length");
569
634
  return array.length;
570
635
  }
636
+ /**
637
+ * Enables observing the sorted property of an array.
638
+ * @param array - The array to observe the sorted property of.
639
+ * @returns The sorted property.
640
+ * @public
641
+ */
642
+ export function sortedCount(array) {
643
+ if (!array) {
644
+ return 0;
645
+ }
646
+ let arrayObserver = array.$fastController;
647
+ if (arrayObserver === void 0) {
648
+ ArrayObserver.enable();
649
+ arrayObserver = Observable.getNotifier(array);
650
+ }
651
+ Observable.track(arrayObserver.sortObserver, "sorted");
652
+ return array.sorted;
653
+ }
@@ -112,8 +112,11 @@ export class RepeatBehavior {
112
112
  else if (args[0].reset) {
113
113
  this.refreshAllViews();
114
114
  }
115
+ else if (args[0].sorted) {
116
+ this.updateSortedViews(args);
117
+ }
115
118
  else {
116
- this.updateViews(args);
119
+ this.updateSplicedViews(args);
117
120
  }
118
121
  }
119
122
  observeItems(force = false) {
@@ -131,7 +134,27 @@ export class RepeatBehavior {
131
134
  newObserver.subscribe(this);
132
135
  }
133
136
  }
134
- updateViews(splices) {
137
+ updateSortedViews(sorts) {
138
+ const views = this.views;
139
+ for (let i = 0, ii = sorts.length; i < ii; ++i) {
140
+ const sortedItems = sorts[i].sorted.slice();
141
+ const unsortedItems = sortedItems.slice().sort();
142
+ for (let j = 0, jj = sortedItems.length; j < jj; ++j) {
143
+ const sortedIndex = sortedItems.find(value => sortedItems[j] === unsortedItems[value]);
144
+ if (sortedIndex !== j) {
145
+ const removedItems = unsortedItems.splice(sortedIndex, 1);
146
+ unsortedItems.splice(j, 0, ...removedItems);
147
+ const neighbor = views[j];
148
+ const location = neighbor ? neighbor.firstChild : this.location;
149
+ views[sortedIndex].remove();
150
+ views[sortedIndex].insertBefore(location);
151
+ const removedViews = views.splice(sortedIndex, 1);
152
+ views.splice(j, 0, ...removedViews);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ updateSplicedViews(splices) {
135
158
  const views = this.views;
136
159
  const bindView = this.bindView;
137
160
  const items = this.items;
@@ -426,6 +426,52 @@
426
426
  "name": "ArrayObserver",
427
427
  "preserveMemberOrder": false,
428
428
  "members": [
429
+ {
430
+ "kind": "MethodSignature",
431
+ "canonicalReference": "@microsoft/fast-element!ArrayObserver#addSort:member(1)",
432
+ "docComment": "/**\n * Adds a sort to the list of changes.\n *\n * @param sort - The sort to add.\n */\n",
433
+ "excerptTokens": [
434
+ {
435
+ "kind": "Content",
436
+ "text": "addSort(sort: "
437
+ },
438
+ {
439
+ "kind": "Reference",
440
+ "text": "Sort",
441
+ "canonicalReference": "@microsoft/fast-element!Sort:class"
442
+ },
443
+ {
444
+ "kind": "Content",
445
+ "text": "): "
446
+ },
447
+ {
448
+ "kind": "Content",
449
+ "text": "void"
450
+ },
451
+ {
452
+ "kind": "Content",
453
+ "text": ";"
454
+ }
455
+ ],
456
+ "isOptional": false,
457
+ "returnTypeTokenRange": {
458
+ "startIndex": 3,
459
+ "endIndex": 4
460
+ },
461
+ "releaseTag": "Public",
462
+ "overloadIndex": 1,
463
+ "parameters": [
464
+ {
465
+ "parameterName": "sort",
466
+ "parameterTypeTokenRange": {
467
+ "startIndex": 1,
468
+ "endIndex": 2
469
+ },
470
+ "isOptional": false
471
+ }
472
+ ],
473
+ "name": "addSort"
474
+ },
429
475
  {
430
476
  "kind": "MethodSignature",
431
477
  "canonicalReference": "@microsoft/fast-element!ArrayObserver#addSplice:member(1)",
@@ -573,6 +619,34 @@
573
619
  ],
574
620
  "name": "reset"
575
621
  },
622
+ {
623
+ "kind": "PropertySignature",
624
+ "canonicalReference": "@microsoft/fast-element!ArrayObserver#sortObserver:member",
625
+ "docComment": "/**\n * The sort observer for the array.\n */\n",
626
+ "excerptTokens": [
627
+ {
628
+ "kind": "Content",
629
+ "text": "readonly sortObserver: "
630
+ },
631
+ {
632
+ "kind": "Reference",
633
+ "text": "SortObserver",
634
+ "canonicalReference": "@microsoft/fast-element!SortObserver:interface"
635
+ },
636
+ {
637
+ "kind": "Content",
638
+ "text": ";"
639
+ }
640
+ ],
641
+ "isReadonly": true,
642
+ "isOptional": false,
643
+ "releaseTag": "Public",
644
+ "name": "sortObserver",
645
+ "propertyTypeTokenRange": {
646
+ "startIndex": 1,
647
+ "endIndex": 2
648
+ }
649
+ },
576
650
  {
577
651
  "kind": "PropertySignature",
578
652
  "canonicalReference": "@microsoft/fast-element!ArrayObserver#strategy:member",
@@ -629,7 +703,7 @@
629
703
  },
630
704
  {
631
705
  "kind": "Content",
632
- "text": "<{\n readonly enable: () => void;\n}>"
706
+ "text": "<{\n readonly sorted: 0;\n readonly enable: () => void;\n}>"
633
707
  }
634
708
  ],
635
709
  "fileUrlPath": "dist/dts/observation/arrays.d.ts",
@@ -5136,7 +5210,7 @@
5136
5210
  {
5137
5211
  "kind": "Method",
5138
5212
  "canonicalReference": "@microsoft/fast-element!ElementController.forCustomElement:member(1)",
5139
- "docComment": "/**\n * Locates or creates a controller for the specified element.\n *\n * @remarks\n *\n * The specified element must have a {@link FASTElementDefinition} registered either through the use of the {@link customElement} decorator or a call to `FASTElement.define`.\n *\n * @param element - The element to return the controller for.\n */\n",
5213
+ "docComment": "/**\n * Locates or creates a controller for the specified element.\n *\n * @remarks\n *\n * The specified element must have a {@link FASTElementDefinition} registered either through the use of the {@link customElement} decorator or a call to `FASTElement.define`.\n *\n * @param element - The element to return the controller for.\n *\n * @param override - Reset the controller even if one has been defined.\n */\n",
5140
5214
  "excerptTokens": [
5141
5215
  {
5142
5216
  "kind": "Content",
@@ -5147,6 +5221,14 @@
5147
5221
  "text": "HTMLElement",
5148
5222
  "canonicalReference": "!HTMLElement:interface"
5149
5223
  },
5224
+ {
5225
+ "kind": "Content",
5226
+ "text": ", override?: "
5227
+ },
5228
+ {
5229
+ "kind": "Content",
5230
+ "text": "boolean"
5231
+ },
5150
5232
  {
5151
5233
  "kind": "Content",
5152
5234
  "text": "): "
@@ -5163,8 +5245,8 @@
5163
5245
  ],
5164
5246
  "isStatic": true,
5165
5247
  "returnTypeTokenRange": {
5166
- "startIndex": 3,
5167
- "endIndex": 4
5248
+ "startIndex": 5,
5249
+ "endIndex": 6
5168
5250
  },
5169
5251
  "releaseTag": "Public",
5170
5252
  "isProtected": false,
@@ -5177,6 +5259,14 @@
5177
5259
  "endIndex": 2
5178
5260
  },
5179
5261
  "isOptional": false
5262
+ },
5263
+ {
5264
+ "parameterName": "override",
5265
+ "parameterTypeTokenRange": {
5266
+ "startIndex": 3,
5267
+ "endIndex": 4
5268
+ },
5269
+ "isOptional": true
5180
5270
  }
5181
5271
  ],
5182
5272
  "isOptional": false,
@@ -9154,7 +9244,7 @@
9154
9244
  "excerptTokens": [
9155
9245
  {
9156
9246
  "kind": "Content",
9157
- "text": "readonly template?: "
9247
+ "text": "template?: "
9158
9248
  },
9159
9249
  {
9160
9250
  "kind": "Reference",
@@ -9166,7 +9256,7 @@
9166
9256
  "text": ";"
9167
9257
  }
9168
9258
  ],
9169
- "isReadonly": true,
9259
+ "isReadonly": false,
9170
9260
  "isOptional": true,
9171
9261
  "releaseTag": "Public",
9172
9262
  "name": "template",
@@ -16485,6 +16575,15 @@
16485
16575
  "kind": "Content",
16486
16576
  "text": "[] | "
16487
16577
  },
16578
+ {
16579
+ "kind": "Reference",
16580
+ "text": "Sort",
16581
+ "canonicalReference": "@microsoft/fast-element!Sort:class"
16582
+ },
16583
+ {
16584
+ "kind": "Content",
16585
+ "text": "[] | "
16586
+ },
16488
16587
  {
16489
16588
  "kind": "Reference",
16490
16589
  "text": "ExpressionObserver",
@@ -16505,8 +16604,8 @@
16505
16604
  ],
16506
16605
  "isStatic": false,
16507
16606
  "returnTypeTokenRange": {
16508
- "startIndex": 7,
16509
- "endIndex": 8
16607
+ "startIndex": 9,
16608
+ "endIndex": 10
16510
16609
  },
16511
16610
  "releaseTag": "Public",
16512
16611
  "isProtected": false,
@@ -16524,7 +16623,7 @@
16524
16623
  "parameterName": "args",
16525
16624
  "parameterTypeTokenRange": {
16526
16625
  "startIndex": 3,
16527
- "endIndex": 6
16626
+ "endIndex": 8
16528
16627
  },
16529
16628
  "isOptional": false
16530
16629
  }
@@ -17462,6 +17561,204 @@
17462
17561
  }
17463
17562
  ]
17464
17563
  },
17564
+ {
17565
+ "kind": "Class",
17566
+ "canonicalReference": "@microsoft/fast-element!Sort:class",
17567
+ "docComment": "/**\n * A sort array indicates new index positions of array items.\n *\n * @public\n */\n",
17568
+ "excerptTokens": [
17569
+ {
17570
+ "kind": "Content",
17571
+ "text": "export declare class Sort "
17572
+ }
17573
+ ],
17574
+ "fileUrlPath": "dist/dts/observation/arrays.d.ts",
17575
+ "releaseTag": "Public",
17576
+ "isAbstract": false,
17577
+ "name": "Sort",
17578
+ "preserveMemberOrder": false,
17579
+ "members": [
17580
+ {
17581
+ "kind": "Constructor",
17582
+ "canonicalReference": "@microsoft/fast-element!Sort:constructor(1)",
17583
+ "docComment": "/**\n * Creates a sort update.\n *\n * @param sorted - The updated index of sorted items.\n */\n",
17584
+ "excerptTokens": [
17585
+ {
17586
+ "kind": "Content",
17587
+ "text": "constructor(sorted?: "
17588
+ },
17589
+ {
17590
+ "kind": "Content",
17591
+ "text": "number[] | undefined"
17592
+ },
17593
+ {
17594
+ "kind": "Content",
17595
+ "text": ");"
17596
+ }
17597
+ ],
17598
+ "releaseTag": "Public",
17599
+ "isProtected": false,
17600
+ "overloadIndex": 1,
17601
+ "parameters": [
17602
+ {
17603
+ "parameterName": "sorted",
17604
+ "parameterTypeTokenRange": {
17605
+ "startIndex": 1,
17606
+ "endIndex": 2
17607
+ },
17608
+ "isOptional": true
17609
+ }
17610
+ ]
17611
+ },
17612
+ {
17613
+ "kind": "Property",
17614
+ "canonicalReference": "@microsoft/fast-element!Sort#sorted:member",
17615
+ "docComment": "",
17616
+ "excerptTokens": [
17617
+ {
17618
+ "kind": "Content",
17619
+ "text": "sorted?: "
17620
+ },
17621
+ {
17622
+ "kind": "Content",
17623
+ "text": "number[] | undefined"
17624
+ },
17625
+ {
17626
+ "kind": "Content",
17627
+ "text": ";"
17628
+ }
17629
+ ],
17630
+ "isReadonly": false,
17631
+ "isOptional": true,
17632
+ "releaseTag": "Public",
17633
+ "name": "sorted",
17634
+ "propertyTypeTokenRange": {
17635
+ "startIndex": 1,
17636
+ "endIndex": 2
17637
+ },
17638
+ "isStatic": false,
17639
+ "isProtected": false,
17640
+ "isAbstract": false
17641
+ }
17642
+ ],
17643
+ "implementsTokenRanges": []
17644
+ },
17645
+ {
17646
+ "kind": "Function",
17647
+ "canonicalReference": "@microsoft/fast-element!sortedCount:function(1)",
17648
+ "docComment": "/**\n * Enables observing the sorted property of an array.\n *\n * @param array - The array to observe the sorted property of.\n *\n * @returns The sorted property.\n *\n * @public\n */\n",
17649
+ "excerptTokens": [
17650
+ {
17651
+ "kind": "Content",
17652
+ "text": "export declare function sortedCount<T>(array: "
17653
+ },
17654
+ {
17655
+ "kind": "Content",
17656
+ "text": "readonly T[]"
17657
+ },
17658
+ {
17659
+ "kind": "Content",
17660
+ "text": "): "
17661
+ },
17662
+ {
17663
+ "kind": "Content",
17664
+ "text": "number"
17665
+ },
17666
+ {
17667
+ "kind": "Content",
17668
+ "text": ";"
17669
+ }
17670
+ ],
17671
+ "fileUrlPath": "dist/dts/observation/arrays.d.ts",
17672
+ "returnTypeTokenRange": {
17673
+ "startIndex": 3,
17674
+ "endIndex": 4
17675
+ },
17676
+ "releaseTag": "Public",
17677
+ "overloadIndex": 1,
17678
+ "parameters": [
17679
+ {
17680
+ "parameterName": "array",
17681
+ "parameterTypeTokenRange": {
17682
+ "startIndex": 1,
17683
+ "endIndex": 2
17684
+ },
17685
+ "isOptional": false
17686
+ }
17687
+ ],
17688
+ "typeParameters": [
17689
+ {
17690
+ "typeParameterName": "T",
17691
+ "constraintTokenRange": {
17692
+ "startIndex": 0,
17693
+ "endIndex": 0
17694
+ },
17695
+ "defaultTypeTokenRange": {
17696
+ "startIndex": 0,
17697
+ "endIndex": 0
17698
+ }
17699
+ }
17700
+ ],
17701
+ "name": "sortedCount"
17702
+ },
17703
+ {
17704
+ "kind": "Interface",
17705
+ "canonicalReference": "@microsoft/fast-element!SortObserver:interface",
17706
+ "docComment": "/**\n * Observes array sort.\n *\n * @public\n */\n",
17707
+ "excerptTokens": [
17708
+ {
17709
+ "kind": "Content",
17710
+ "text": "export interface SortObserver extends "
17711
+ },
17712
+ {
17713
+ "kind": "Reference",
17714
+ "text": "Subscriber",
17715
+ "canonicalReference": "@microsoft/fast-element!Subscriber:interface"
17716
+ },
17717
+ {
17718
+ "kind": "Content",
17719
+ "text": " "
17720
+ }
17721
+ ],
17722
+ "fileUrlPath": "dist/dts/observation/arrays.d.ts",
17723
+ "releaseTag": "Public",
17724
+ "name": "SortObserver",
17725
+ "preserveMemberOrder": false,
17726
+ "members": [
17727
+ {
17728
+ "kind": "PropertySignature",
17729
+ "canonicalReference": "@microsoft/fast-element!SortObserver#sorted:member",
17730
+ "docComment": "/**\n * The sorted times on the observed array, this should be incremented every time an item in the array changes location.\n */\n",
17731
+ "excerptTokens": [
17732
+ {
17733
+ "kind": "Content",
17734
+ "text": "sorted: "
17735
+ },
17736
+ {
17737
+ "kind": "Content",
17738
+ "text": "number"
17739
+ },
17740
+ {
17741
+ "kind": "Content",
17742
+ "text": ";"
17743
+ }
17744
+ ],
17745
+ "isReadonly": false,
17746
+ "isOptional": false,
17747
+ "releaseTag": "Public",
17748
+ "name": "sorted",
17749
+ "propertyTypeTokenRange": {
17750
+ "startIndex": 1,
17751
+ "endIndex": 2
17752
+ }
17753
+ }
17754
+ ],
17755
+ "extendsTokenRanges": [
17756
+ {
17757
+ "startIndex": 1,
17758
+ "endIndex": 2
17759
+ }
17760
+ ]
17761
+ },
17465
17762
  {
17466
17763
  "kind": "TypeAlias",
17467
17764
  "canonicalReference": "@microsoft/fast-element!SourceLifetime:type",