@microsoft/fast-element 2.9.1 → 2.10.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.
Files changed (93) hide show
  1. package/CHANGELOG.json +58 -0
  2. package/CHANGELOG.md +22 -1
  3. package/dist/context/context.api.json +7 -7
  4. package/dist/di/di.api.json +12 -12
  5. package/dist/dts/binding/one-way.d.ts +1 -1
  6. package/dist/dts/binding/two-way.d.ts +3 -3
  7. package/dist/dts/components/attributes.d.ts +4 -4
  8. package/dist/dts/components/element-controller.d.ts +19 -8
  9. package/dist/dts/components/fast-definitions.d.ts +5 -5
  10. package/dist/dts/components/fast-element.d.ts +2 -2
  11. package/dist/dts/context.d.ts +8 -8
  12. package/dist/dts/di/di.d.ts +15 -15
  13. package/dist/dts/dom-policy.d.ts +8 -8
  14. package/dist/dts/dom.d.ts +2 -2
  15. package/dist/dts/index.d.ts +41 -28
  16. package/dist/dts/interfaces.d.ts +7 -7
  17. package/dist/dts/observable.d.ts +4 -2
  18. package/dist/dts/observation/arrays.d.ts +2 -2
  19. package/dist/dts/observation/observable.d.ts +3 -3
  20. package/dist/dts/observation/update-queue.d.ts +1 -1
  21. package/dist/dts/platform.d.ts +1 -1
  22. package/dist/dts/state/state.d.ts +10 -10
  23. package/dist/dts/state/watch.d.ts +1 -1
  24. package/dist/dts/styles/css-binding-directive.d.ts +2 -2
  25. package/dist/dts/styles/css-directive.d.ts +1 -1
  26. package/dist/dts/styles/css.d.ts +4 -4
  27. package/dist/dts/styles/element-styles.d.ts +2 -2
  28. package/dist/dts/templating/children.d.ts +2 -2
  29. package/dist/dts/templating/compiler.d.ts +3 -3
  30. package/dist/dts/templating/html-binding-directive.d.ts +3 -3
  31. package/dist/dts/templating/html-directive.d.ts +5 -5
  32. package/dist/dts/templating/node-observation.d.ts +2 -2
  33. package/dist/dts/templating/ref.d.ts +1 -1
  34. package/dist/dts/templating/render.d.ts +10 -10
  35. package/dist/dts/templating/repeat.d.ts +4 -4
  36. package/dist/dts/templating/slotted.d.ts +1 -1
  37. package/dist/dts/templating/template.d.ts +4 -4
  38. package/dist/dts/templating/view.d.ts +2 -2
  39. package/dist/esm/binding/one-way.js +1 -1
  40. package/dist/esm/binding/two-way.js +3 -3
  41. package/dist/esm/components/element-controller.js +152 -106
  42. package/dist/esm/components/fast-definitions.js +16 -16
  43. package/dist/esm/context.js +2 -2
  44. package/dist/esm/di/di.js +73 -63
  45. package/dist/esm/dom-policy.js +2 -2
  46. package/dist/esm/dom.js +2 -2
  47. package/dist/esm/index.js +21 -22
  48. package/dist/esm/interfaces.js +38 -0
  49. package/dist/esm/observable.js +1 -1
  50. package/dist/esm/observation/arrays.js +29 -22
  51. package/dist/esm/observation/observable.js +3 -3
  52. package/dist/esm/styles/css.js +2 -2
  53. package/dist/esm/styles/element-styles.js +9 -9
  54. package/dist/esm/templating/children.js +1 -1
  55. package/dist/esm/templating/compiler.js +5 -5
  56. package/dist/esm/templating/html-binding-directive.js +2 -2
  57. package/dist/esm/templating/node-observation.js +1 -1
  58. package/dist/esm/templating/render.js +4 -4
  59. package/dist/esm/templating/repeat.js +11 -11
  60. package/dist/esm/templating/slotted.js +1 -1
  61. package/dist/esm/templating/template.js +7 -7
  62. package/dist/esm/templating/view.js +9 -9
  63. package/dist/fast-element.api.json +96 -37
  64. package/dist/fast-element.d.ts +4 -4
  65. package/dist/fast-element.debug.js +2414 -2321
  66. package/dist/fast-element.debug.min.js +2 -2
  67. package/dist/fast-element.js +2414 -2321
  68. package/dist/fast-element.min.js +2 -2
  69. package/dist/fast-element.untrimmed.d.ts +17 -6
  70. package/docs/api-report.api.md +5 -4
  71. package/docs/di/api-report.api.md +4 -4
  72. package/karma.conf.cjs +13 -7
  73. package/package.json +6 -46
  74. package/playwright.config.ts +18 -0
  75. package/test/index.html +11 -0
  76. package/test/main.ts +10 -0
  77. package/test/vite.config.ts +19 -0
  78. package/dist/dts/observation/observable.bench.d.ts +0 -18
  79. package/dist/dts/templating/render.bench.d.ts +0 -3
  80. package/dist/dts/templating/repeat-basic-reverse.bench.d.ts +0 -3
  81. package/dist/dts/templating/repeat-basic-shift.bench.d.ts +0 -3
  82. package/dist/dts/templating/when-basic.bench.d.ts +0 -3
  83. package/dist/dts/templating/when-conditional.bench.d.ts +0 -3
  84. package/dist/dts/templating/when-switch.bench.d.ts +0 -3
  85. package/dist/esm/observation/observable.bench.js +0 -79
  86. package/dist/esm/templating/render.bench.js +0 -56
  87. package/dist/esm/templating/repeat-basic-reverse.bench.js +0 -43
  88. package/dist/esm/templating/repeat-basic-shift.bench.js +0 -43
  89. package/dist/esm/templating/when-basic.bench.js +0 -36
  90. package/dist/esm/templating/when-conditional.bench.js +0 -39
  91. package/dist/esm/templating/when-switch.bench.js +0 -68
  92. package/scripts/run-benchmarks.js +0 -46
  93. package/tensile.config.js +0 -12
@@ -80,6 +80,13 @@ export const SpliceStrategySupport = Object.freeze({
80
80
  const reset = new Splice(0, emptyArray, 0);
81
81
  reset.reset = true;
82
82
  const resetSplices = [reset];
83
+ var Edit;
84
+ (function (Edit) {
85
+ Edit[Edit["leave"] = 0] = "leave";
86
+ Edit[Edit["update"] = 1] = "update";
87
+ Edit[Edit["add"] = 2] = "add";
88
+ Edit[Edit["delete"] = 3] = "delete";
89
+ })(Edit || (Edit = {}));
83
90
  // Note: This function is *based* on the computation of the Levenshtein
84
91
  // "edit" distance. The one change is that "updates" are treated as two
85
92
  // edits - not one. With Array splices, an update is really a delete
@@ -131,12 +138,12 @@ function spliceOperationsFromEditDistances(distances) {
131
138
  const edits = [];
132
139
  while (i > 0 || j > 0) {
133
140
  if (i === 0) {
134
- edits.push(2 /* Edit.add */);
141
+ edits.push(Edit.add);
135
142
  j--;
136
143
  continue;
137
144
  }
138
145
  if (j === 0) {
139
- edits.push(3 /* Edit.delete */);
146
+ edits.push(Edit.delete);
140
147
  i--;
141
148
  continue;
142
149
  }
@@ -152,22 +159,22 @@ function spliceOperationsFromEditDistances(distances) {
152
159
  }
153
160
  if (min === northWest) {
154
161
  if (northWest === current) {
155
- edits.push(0 /* Edit.leave */);
162
+ edits.push(Edit.leave);
156
163
  }
157
164
  else {
158
- edits.push(1 /* Edit.update */);
165
+ edits.push(Edit.update);
159
166
  current = northWest;
160
167
  }
161
168
  i--;
162
169
  j--;
163
170
  }
164
171
  else if (min === west) {
165
- edits.push(3 /* Edit.delete */);
172
+ edits.push(Edit.delete);
166
173
  i--;
167
174
  current = west;
168
175
  }
169
176
  else {
170
- edits.push(2 /* Edit.add */);
177
+ edits.push(Edit.add);
171
178
  j--;
172
179
  current = north;
173
180
  }
@@ -258,7 +265,7 @@ function calc(current, currentStart, currentEnd, old, oldStart, oldEnd) {
258
265
  let oldIndex = oldStart;
259
266
  for (let i = 0; i < ops.length; ++i) {
260
267
  switch (ops[i]) {
261
- case 0 /* Edit.leave */:
268
+ case Edit.leave:
262
269
  if (splice !== void 0) {
263
270
  splices.push(splice);
264
271
  splice = void 0;
@@ -266,7 +273,7 @@ function calc(current, currentStart, currentEnd, old, oldStart, oldEnd) {
266
273
  index++;
267
274
  oldIndex++;
268
275
  break;
269
- case 1 /* Edit.update */:
276
+ case Edit.update:
270
277
  if (splice === void 0) {
271
278
  splice = new Splice(index, [], 0);
272
279
  }
@@ -275,14 +282,14 @@ function calc(current, currentStart, currentEnd, old, oldStart, oldEnd) {
275
282
  splice.removed.push(old[oldIndex]);
276
283
  oldIndex++;
277
284
  break;
278
- case 2 /* Edit.add */:
285
+ case Edit.add:
279
286
  if (splice === void 0) {
280
287
  splice = new Splice(index, [], 0);
281
288
  }
282
289
  splice.addedCount++;
283
290
  index++;
284
291
  break;
285
- case 3 /* Edit.delete */:
292
+ case Edit.delete:
286
293
  if (splice === void 0) {
287
294
  splice = new Splice(index, [], 0);
288
295
  }
@@ -470,18 +477,6 @@ function setNonEnumerable(target, property, value, writable = true) {
470
477
  });
471
478
  }
472
479
  class DefaultArrayObserver extends SubscriberSet {
473
- constructor(subject) {
474
- super(subject);
475
- this.oldCollection = void 0;
476
- this.splices = void 0;
477
- this.sorts = void 0;
478
- this.needsQueue = true;
479
- this._strategy = null;
480
- this._lengthObserver = void 0;
481
- this._sortObserver = void 0;
482
- this.call = this.flush;
483
- setNonEnumerable(subject, "$fastController", this);
484
- }
485
480
  get strategy() {
486
481
  return this._strategy;
487
482
  }
@@ -522,6 +517,18 @@ class DefaultArrayObserver extends SubscriberSet {
522
517
  }
523
518
  return observer;
524
519
  }
520
+ constructor(subject) {
521
+ super(subject);
522
+ this.oldCollection = void 0;
523
+ this.splices = void 0;
524
+ this.sorts = void 0;
525
+ this.needsQueue = true;
526
+ this._strategy = null;
527
+ this._lengthObserver = void 0;
528
+ this._sortObserver = void 0;
529
+ this.call = this.flush;
530
+ setNonEnumerable(subject, "$fastController", this);
531
+ }
525
532
  subscribe(subscriber) {
526
533
  this.flush();
527
534
  super.subscribe(subscriber);
@@ -1,7 +1,7 @@
1
- import { isFunction, isString, KernelServiceId, } from "../interfaces.js";
1
+ import { isFunction, isString, KernelServiceId, Message, } from "../interfaces.js";
2
2
  import { createMetadataLocator, FAST, makeSerializationNoop } from "../platform.js";
3
- import { Updates } from "./update-queue.js";
4
3
  import { PropertyChangeNotifier, SubscriberSet } from "./notifier.js";
4
+ import { Updates } from "./update-queue.js";
5
5
  /**
6
6
  * Describes how the source's lifetime relates to its controller's lifetime.
7
7
  * @public
@@ -27,7 +27,7 @@ export const Observable = FAST.getById(KernelServiceId.observable, () => {
27
27
  const notifierLookup = new WeakMap();
28
28
  let watcher = void 0;
29
29
  let createArrayObserver = (array) => {
30
- throw FAST.error(1101 /* Message.needsArrayObservation */);
30
+ throw FAST.error(Message.needsArrayObservation);
31
31
  };
32
32
  function getNotifier(source) {
33
33
  var _a;
@@ -1,9 +1,9 @@
1
- import { isFunction, isString } from "../interfaces.js";
2
1
  import { Binding } from "../binding/binding.js";
3
2
  import { oneWay } from "../binding/one-way.js";
3
+ import { isFunction, isString } from "../interfaces.js";
4
+ import { CSSBindingDirective } from "./css-binding-directive.js";
4
5
  import { CSSDirective } from "./css-directive.js";
5
6
  import { ElementStyles } from "./element-styles.js";
6
- import { CSSBindingDirective } from "./css-binding-directive.js";
7
7
  const marker = `${Math.random().toString(36).substring(2, 8)}`;
8
8
  let varId = 0;
9
9
  const nextCSSVariable = () => `--v${marker}${++varId}`;
@@ -9,6 +9,15 @@ function reduceStyles(styles) {
9
9
  * @public
10
10
  */
11
11
  export class ElementStyles {
12
+ /**
13
+ * Gets the StyleStrategy associated with these element styles.
14
+ */
15
+ get strategy() {
16
+ if (this._strategy === null) {
17
+ this.withStrategy(DefaultStyleStrategy);
18
+ }
19
+ return this._strategy;
20
+ }
12
21
  /**
13
22
  * Creates an instance of ElementStyles.
14
23
  * @param styles - The styles that will be associated with elements.
@@ -21,15 +30,6 @@ export class ElementStyles {
21
30
  .map((x) => x instanceof ElementStyles ? x.behaviors : null)
22
31
  .reduce((prev, curr) => (curr === null ? prev : prev === null ? curr : prev.concat(curr)), null);
23
32
  }
24
- /**
25
- * Gets the StyleStrategy associated with these element styles.
26
- */
27
- get strategy() {
28
- if (this._strategy === null) {
29
- this.withStrategy(DefaultStyleStrategy);
30
- }
31
- return this._strategy;
32
- }
33
33
  /** @internal */
34
34
  addStylesTo(target) {
35
35
  this.strategy.addStylesTo(target);
@@ -1,6 +1,6 @@
1
1
  import { isString, noop } from "../interfaces.js";
2
2
  import { HTMLDirective } from "./html-directive.js";
3
- import { NodeObservationDirective } from "./node-observation.js";
3
+ import { NodeObservationDirective, } from "./node-observation.js";
4
4
  /**
5
5
  * The runtime behavior for child node observation.
6
6
  * @public
@@ -1,11 +1,11 @@
1
- import { isFunction, isString } from "../interfaces.js";
2
- import { FAST } from "../platform.js";
3
- import { DOM } from "../dom.js";
4
1
  import { oneTime } from "../binding/one-time.js";
5
2
  import { oneWay } from "../binding/one-way.js";
6
- import { nextId, Parser } from "./markup.js";
3
+ import { DOM } from "../dom.js";
4
+ import { isFunction, isString, Message } from "../interfaces.js";
5
+ import { FAST } from "../platform.js";
7
6
  import { HTMLBindingDirective } from "./html-binding-directive.js";
8
7
  import { HTMLDirective, } from "./html-directive.js";
8
+ import { nextId, Parser } from "./markup.js";
9
9
  import { HTMLView } from "./view.js";
10
10
  const targetIdFrom = (parentId, nodeIndex) => `${parentId}.${nodeIndex}`;
11
11
  const descriptorCache = {};
@@ -16,7 +16,7 @@ const next = {
16
16
  };
17
17
  function tryWarn(name) {
18
18
  if (!name.startsWith("fast-")) {
19
- FAST.warn(1204 /* Message.hostBindingWithoutHost */, { name });
19
+ FAST.warn(Message.hostBindingWithoutHost, { name });
20
20
  }
21
21
  }
22
22
  const warningHost = new Proxy(document.createElement("div"), {
@@ -1,6 +1,6 @@
1
1
  import { isHydratable } from "../components/hydration.js";
2
2
  import { DOM, DOMAspect } from "../dom.js";
3
- import "../interfaces.js";
3
+ import { Message } from "../interfaces.js";
4
4
  import { ExecutionContext, } from "../observation/observable.js";
5
5
  import { FAST } from "../platform.js";
6
6
  import { HTMLDirective, } from "./html-directive.js";
@@ -150,7 +150,7 @@ export class HTMLBindingDirective {
150
150
  const sink = sinkLookup[this.aspectType];
151
151
  const policy = (_a = this.dataBinding.policy) !== null && _a !== void 0 ? _a : this.policy;
152
152
  if (!sink) {
153
- throw FAST.error(1205 /* Message.unsupportedBindingBehavior */);
153
+ throw FAST.error(Message.unsupportedBindingBehavior);
154
154
  }
155
155
  this.data = `${this.id}-d`;
156
156
  this.updateTarget = policy.protect(this.targetTagName, this.aspectType, this.targetAspect, sink);
@@ -1,5 +1,5 @@
1
1
  import { emptyArray } from "../platform.js";
2
- import { StatelessAttachedAttributeDirective } from "./html-directive.js";
2
+ import { StatelessAttachedAttributeDirective, } from "./html-directive.js";
3
3
  const selectElements = (value) => value.nodeType === 1;
4
4
  /**
5
5
  * Creates a function that can be used to filter a Node array, selecting only elements.
@@ -1,10 +1,10 @@
1
- import { FASTElementDefinition } from "../components/fast-definitions.js";
2
- import { isHydratable } from "../components/hydration.js";
3
- import { isFunction, isString } from "../interfaces.js";
4
1
  import { Binding } from "../binding/binding.js";
2
+ import { normalizeBinding } from "../binding/normalize.js";
5
3
  import { oneTime } from "../binding/one-time.js";
6
4
  import { oneWay } from "../binding/one-way.js";
7
- import { normalizeBinding } from "../binding/normalize.js";
5
+ import { FASTElementDefinition } from "../components/fast-definitions.js";
6
+ import { isHydratable } from "../components/hydration.js";
7
+ import { isFunction, isString } from "../interfaces.js";
8
8
  import { HTMLDirective, } from "./html-directive.js";
9
9
  import { Markup } from "./markup.js";
10
10
  import { html, ViewTemplate, } from "./template.js";
@@ -1,11 +1,11 @@
1
+ import { normalizeBinding } from "../binding/normalize.js";
1
2
  import { HydrationMarkup, isHydratable } from "../components/hydration.js";
2
- import { ArrayObserver } from "../observation/arrays.js";
3
- import { Observable } from "../observation/observable.js";
3
+ import { ArrayObserver, Sort, Splice } from "../observation/arrays.js";
4
+ import { Observable, } from "../observation/observable.js";
4
5
  import { emptyArray } from "../platform.js";
5
- import { normalizeBinding } from "../binding/normalize.js";
6
6
  import { HTMLDirective, } from "./html-directive.js";
7
7
  import { Markup } from "./markup.js";
8
- import { HTMLView, HydrationStage } from "./view.js";
8
+ import { HTMLView, HydrationStage, HydrationView } from "./view.js";
9
9
  const defaultRepeatOptions = Object.freeze({
10
10
  positioning: false,
11
11
  recycle: true,
@@ -348,6 +348,13 @@ export class RepeatBehavior {
348
348
  * @public
349
349
  */
350
350
  export class RepeatDirective {
351
+ /**
352
+ * Creates a placeholder string based on the directive's index within the template.
353
+ * @param index - The index of the directive within the template.
354
+ */
355
+ createHTML(add) {
356
+ return Markup.comment(add(this));
357
+ }
351
358
  /**
352
359
  * Creates an instance of RepeatDirective.
353
360
  * @param dataBinding - The binding that provides the array to render.
@@ -360,13 +367,6 @@ export class RepeatDirective {
360
367
  this.options = options;
361
368
  ArrayObserver.enable();
362
369
  }
363
- /**
364
- * Creates a placeholder string based on the directive's index within the template.
365
- * @param index - The index of the directive within the template.
366
- */
367
- createHTML(add) {
368
- return Markup.comment(add(this));
369
- }
370
370
  /**
371
371
  * Creates a behavior for the provided target node.
372
372
  * @param target - The node instance to create the behavior for.
@@ -1,6 +1,6 @@
1
1
  import { isString } from "../interfaces.js";
2
2
  import { HTMLDirective } from "./html-directive.js";
3
- import { NodeObservationDirective } from "./node-observation.js";
3
+ import { NodeObservationDirective, } from "./node-observation.js";
4
4
  const slotEvent = "slotchange";
5
5
  /**
6
6
  * The runtime behavior for slotted node observation.
@@ -1,10 +1,10 @@
1
- import { isFunction, isString } from "../interfaces.js";
2
1
  import { Binding } from "../binding/binding.js";
3
- import { FAST, makeSerializationNoop } from "../platform.js";
4
- import { oneWay } from "../binding/one-way.js";
5
2
  import { oneTime } from "../binding/one-time.js";
6
- import { HTMLBindingDirective } from "./html-binding-directive.js";
3
+ import { oneWay } from "../binding/one-way.js";
4
+ import { isFunction, isString, Message } from "../interfaces.js";
5
+ import { FAST, makeSerializationNoop } from "../platform.js";
7
6
  import { Compiler } from "./compiler.js";
7
+ import { HTMLBindingDirective } from "./html-binding-directive.js";
8
8
  import { HTMLDirective, } from "./html-directive.js";
9
9
  import { nextId } from "./markup.js";
10
10
  // Much thanks to LitHTML for working this out!
@@ -100,10 +100,10 @@ export class ViewTemplate {
100
100
  */
101
101
  withPolicy(policy) {
102
102
  if (this.result) {
103
- throw FAST.error(1208 /* Message.cannotSetTemplatePolicyAfterCompilation */);
103
+ throw FAST.error(Message.cannotSetTemplatePolicyAfterCompilation);
104
104
  }
105
105
  if (this.policy) {
106
- throw FAST.error(1207 /* Message.onlySetTemplatePolicyOnce */);
106
+ throw FAST.error(Message.onlySetTemplatePolicyOnce);
107
107
  }
108
108
  this.policy = policy;
109
109
  return this;
@@ -177,7 +177,7 @@ export const html = ((strings, ...values) => {
177
177
  if (Array.isArray(strings) && Array.isArray(strings.raw)) {
178
178
  return ViewTemplate.create(strings, values);
179
179
  }
180
- throw FAST.error(1206 /* Message.directCallToHTMLTagNotAllowed */);
180
+ throw FAST.error(Message.directCallToHTMLTagNotAllowed);
181
181
  });
182
182
  html.partial = (html) => {
183
183
  return new InlineTemplateDirective(html);
@@ -278,6 +278,15 @@ export class HydrationBindingError extends Error {
278
278
  }
279
279
  }
280
280
  export class HydrationView extends DefaultExecutionContext {
281
+ get hydrationStage() {
282
+ return this._hydrationStage;
283
+ }
284
+ get targets() {
285
+ return this._targets;
286
+ }
287
+ get bindingViewBoundaries() {
288
+ return this._bindingViewBoundaries;
289
+ }
281
290
  constructor(firstChild, lastChild, sourceTemplate, hostBindingTarget) {
282
291
  super();
283
292
  this.firstChild = firstChild;
@@ -297,15 +306,6 @@ export class HydrationView extends DefaultExecutionContext {
297
306
  this._targets = {};
298
307
  this.factories = sourceTemplate.compile().factories;
299
308
  }
300
- get hydrationStage() {
301
- return this._hydrationStage;
302
- }
303
- get targets() {
304
- return this._targets;
305
- }
306
- get bindingViewBoundaries() {
307
- return this._bindingViewBoundaries;
308
- }
309
309
  /**
310
310
  * no-op. Hydrated views are don't need to be moved from a documentFragment
311
311
  * to the target node.