@microsoft/fast-element 2.0.0-beta.9 → 2.0.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 (142) hide show
  1. package/.eslintrc.json +1 -1
  2. package/CHANGELOG.json +497 -0
  3. package/CHANGELOG.md +172 -1
  4. package/README.md +1 -9
  5. package/api-extractor.context.json +14 -0
  6. package/api-extractor.di.json +14 -0
  7. package/dist/context/context.api.json +1068 -0
  8. package/dist/di/di.api.json +4929 -0
  9. package/dist/dts/binding/binding.d.ts +49 -0
  10. package/dist/dts/binding/normalize.d.ts +9 -0
  11. package/dist/dts/binding/one-time.d.ts +11 -0
  12. package/dist/dts/binding/one-way.d.ts +20 -0
  13. package/dist/dts/{templating/binding-signal.d.ts → binding/signal.d.ts} +19 -4
  14. package/dist/dts/{templating/binding-two-way.d.ts → binding/two-way.d.ts} +9 -5
  15. package/dist/dts/components/attributes.d.ts +6 -0
  16. package/dist/dts/components/element-controller.d.ts +104 -8
  17. package/dist/dts/components/element-hydration.d.ts +2 -0
  18. package/dist/dts/components/fast-definitions.d.ts +6 -0
  19. package/dist/dts/components/hydration.d.ts +56 -0
  20. package/dist/dts/components/install-hydration.d.ts +1 -0
  21. package/dist/dts/context.d.ts +29 -15
  22. package/dist/dts/di/di.d.ts +0 -5
  23. package/dist/dts/dom-policy.d.ts +83 -0
  24. package/dist/dts/dom.d.ts +100 -0
  25. package/dist/dts/hydration/target-builder.d.ts +63 -0
  26. package/dist/dts/index.d.ts +33 -26
  27. package/dist/dts/index.rollup.d.ts +0 -1
  28. package/dist/dts/index.rollup.debug.d.ts +0 -1
  29. package/dist/dts/interfaces.d.ts +32 -82
  30. package/dist/dts/metadata.d.ts +6 -5
  31. package/dist/dts/observation/arrays.d.ts +1 -1
  32. package/dist/dts/observation/observable.bench.d.ts +18 -0
  33. package/dist/dts/observation/observable.d.ts +5 -5
  34. package/dist/dts/pending-task.d.ts +19 -7
  35. package/dist/dts/platform.d.ts +11 -2
  36. package/dist/dts/polyfills.d.ts +0 -8
  37. package/dist/dts/styles/css-binding-directive.d.ts +60 -0
  38. package/dist/dts/styles/css.d.ts +9 -7
  39. package/dist/dts/styles/element-styles.d.ts +1 -14
  40. package/dist/dts/styles/host.d.ts +2 -5
  41. package/dist/dts/styles/style-strategy.d.ts +42 -0
  42. package/dist/dts/templating/compiler.d.ts +11 -13
  43. package/dist/dts/templating/{binding.d.ts → html-binding-directive.d.ts} +21 -41
  44. package/dist/dts/templating/html-directive.d.ts +44 -140
  45. package/dist/dts/templating/install-hydratable-view-templates.d.ts +1 -0
  46. package/dist/dts/templating/node-observation.d.ts +11 -1
  47. package/dist/dts/templating/ref.d.ts +4 -0
  48. package/dist/dts/templating/render.bench.d.ts +3 -0
  49. package/dist/dts/templating/render.d.ts +49 -9
  50. package/dist/dts/templating/repeat-basic-reverse.bench.d.ts +3 -0
  51. package/dist/dts/templating/repeat-basic-shift.bench.d.ts +3 -0
  52. package/dist/dts/templating/repeat.d.ts +31 -9
  53. package/dist/dts/templating/template.d.ts +97 -12
  54. package/dist/dts/templating/view.d.ts +146 -29
  55. package/dist/dts/templating/when-basic.bench.d.ts +3 -0
  56. package/dist/dts/templating/when-conditional.bench.d.ts +3 -0
  57. package/dist/dts/templating/when-switch.bench.d.ts +3 -0
  58. package/dist/dts/templating/when.d.ts +3 -1
  59. package/dist/dts/testing/fakes.d.ts +12 -1
  60. package/dist/dts/tsdoc-metadata.json +1 -1
  61. package/dist/dts/utilities.d.ts +55 -1
  62. package/dist/esm/binding/binding.js +18 -0
  63. package/dist/esm/binding/normalize.js +17 -0
  64. package/dist/esm/binding/one-time.js +21 -0
  65. package/dist/esm/binding/one-way.js +30 -0
  66. package/dist/esm/{templating/binding-signal.js → binding/signal.js} +22 -6
  67. package/dist/esm/{templating/binding-two-way.js → binding/two-way.js} +18 -12
  68. package/dist/esm/components/attributes.js +16 -1
  69. package/dist/esm/components/element-controller.js +319 -49
  70. package/dist/esm/components/element-hydration.js +2 -0
  71. package/dist/esm/components/fast-definitions.js +12 -4
  72. package/dist/esm/components/fast-element.js +3 -1
  73. package/dist/esm/components/hydration.js +104 -0
  74. package/dist/esm/components/install-hydration.js +3 -0
  75. package/dist/esm/context.js +26 -4
  76. package/dist/esm/debug.js +8 -2
  77. package/dist/esm/di/di.js +9 -12
  78. package/dist/esm/dom-policy.js +345 -0
  79. package/dist/esm/dom.js +101 -0
  80. package/dist/esm/hydration/target-builder.js +175 -0
  81. package/dist/esm/index.js +34 -25
  82. package/dist/esm/index.rollup.debug.js +3 -1
  83. package/dist/esm/index.rollup.js +3 -1
  84. package/dist/esm/interfaces.js +51 -3
  85. package/dist/esm/metadata.js +11 -8
  86. package/dist/esm/observation/arrays.js +1 -1
  87. package/dist/esm/observation/observable.bench.js +79 -0
  88. package/dist/esm/observation/observable.js +20 -15
  89. package/dist/esm/observation/update-queue.js +2 -2
  90. package/dist/esm/pending-task.js +13 -1
  91. package/dist/esm/platform.js +12 -2
  92. package/dist/esm/polyfills.js +3 -61
  93. package/dist/esm/styles/css-binding-directive.js +76 -0
  94. package/dist/esm/styles/css.js +14 -7
  95. package/dist/esm/styles/element-styles.js +0 -33
  96. package/dist/esm/styles/style-strategy.js +1 -0
  97. package/dist/esm/templating/children.js +8 -4
  98. package/dist/esm/templating/compiler.js +37 -44
  99. package/dist/esm/templating/html-binding-directive.js +218 -0
  100. package/dist/esm/templating/html-directive.js +25 -152
  101. package/dist/esm/templating/install-hydratable-view-templates.js +17 -0
  102. package/dist/esm/templating/node-observation.js +14 -8
  103. package/dist/esm/templating/ref.js +1 -1
  104. package/dist/esm/templating/render.bench.js +56 -0
  105. package/dist/esm/templating/render.js +74 -30
  106. package/dist/esm/templating/repeat-basic-reverse.bench.js +43 -0
  107. package/dist/esm/templating/repeat-basic-shift.bench.js +43 -0
  108. package/dist/esm/templating/repeat.js +116 -17
  109. package/dist/esm/templating/template.js +135 -60
  110. package/dist/esm/templating/view.js +254 -34
  111. package/dist/esm/templating/when-basic.bench.js +36 -0
  112. package/dist/esm/templating/when-conditional.bench.js +39 -0
  113. package/dist/esm/templating/when-switch.bench.js +68 -0
  114. package/dist/esm/templating/when.js +12 -5
  115. package/dist/esm/testing/fakes.js +32 -1
  116. package/dist/esm/testing/fixture.js +1 -1
  117. package/dist/esm/utilities.js +97 -1
  118. package/dist/fast-element.api.json +9788 -5666
  119. package/dist/fast-element.d.ts +813 -2392
  120. package/dist/fast-element.debug.js +2785 -969
  121. package/dist/fast-element.debug.min.js +3 -1
  122. package/dist/fast-element.js +2638 -828
  123. package/dist/fast-element.min.js +3 -1
  124. package/dist/fast-element.untrimmed.d.ts +661 -313
  125. package/docs/{api-report.md → api-report.api.md} +238 -151
  126. package/docs/context/api-report.api.md +69 -0
  127. package/docs/di/api-report.api.md +315 -0
  128. package/karma.conf.cjs +2 -1
  129. package/package.json +59 -47
  130. package/scripts/run-api-extractor.js +51 -0
  131. package/scripts/run-benchmarks.js +46 -0
  132. package/tensile.config.js +12 -0
  133. package/dist/dts/templating/dom.d.ts +0 -41
  134. package/dist/esm/templating/binding.js +0 -282
  135. package/dist/esm/templating/dom.js +0 -49
  136. package/docs/guide/declaring-templates.md +0 -230
  137. package/docs/guide/defining-elements.md +0 -214
  138. package/docs/guide/leveraging-css.md +0 -253
  139. package/docs/guide/next-steps.md +0 -13
  140. package/docs/guide/observables-and-state.md +0 -213
  141. package/docs/guide/using-directives.md +0 -576
  142. package/docs/guide/working-with-shadow-dom.md +0 -296
@@ -1,3 +1,5 @@
1
+ import type { HostBehavior } from "./styles/host.js";
2
+ import type { ViewBehavior, ViewBehaviorFactory, ViewController } from "./templating/html-directive.js";
1
3
  /**
2
4
  * Retrieves the "composed parent" element of a node, ignoring DOM tree boundaries.
3
5
  * When the parent of a node is a shadow-root, it will return the host
@@ -12,7 +14,7 @@ export declare function composedParent<T extends HTMLElement>(element: T): HTMLE
12
14
  * Determines if the reference element contains the test element in a "composed" DOM tree that
13
15
  * ignores shadow DOM boundaries.
14
16
  *
15
- * Returns true of the test element is a descendent of the reference, or exist in
17
+ * Returns true of the test element is a descendent of the reference, or exists in
16
18
  * a shadow DOM that is a logical descendent of the reference. Otherwise returns false.
17
19
  * @param reference - The element to test for containment against.
18
20
  * @param test - The element being tested for containment.
@@ -20,3 +22,55 @@ export declare function composedParent<T extends HTMLElement>(element: T): HTMLE
20
22
  * @public
21
23
  */
22
24
  export declare function composedContains(reference: HTMLElement, test: HTMLElement): boolean;
25
+ /**
26
+ * An extension of MutationObserver that supports unobserving nodes.
27
+ * @internal
28
+ */
29
+ export declare class UnobservableMutationObserver extends MutationObserver {
30
+ private readonly callback;
31
+ private observedNodes;
32
+ /**
33
+ * Creates an instance of UnobservableMutationObserver.
34
+ * @param callback - The callback to invoke when observed nodes are changed.
35
+ */
36
+ constructor(callback: MutationCallback);
37
+ observe(target: Node, options?: MutationObserverInit | undefined): void;
38
+ unobserve(target: Node): void;
39
+ }
40
+ /**
41
+ * Bridges between ViewBehaviors and HostBehaviors, enabling a host to
42
+ * control ViewBehaviors.
43
+ * @public
44
+ */
45
+ export interface ViewBehaviorOrchestrator<TSource = any, TParent = any> extends ViewController<TSource, TParent>, HostBehavior<TSource> {
46
+ /**
47
+ *
48
+ * @param nodeId - The structural id of the DOM node to which a behavior will apply.
49
+ * @param target - The DOM node associated with the id.
50
+ */
51
+ addTarget(nodeId: string, target: Node): void;
52
+ /**
53
+ * Adds a behavior.
54
+ * @param behavior - The behavior to add.
55
+ */
56
+ addBehavior(behavior: ViewBehavior): void;
57
+ /**
58
+ * Adds a behavior factory.
59
+ * @param factory - The behavior factory to add.
60
+ * @param target - The target the factory will create behaviors for.
61
+ */
62
+ addBehaviorFactory(factory: ViewBehaviorFactory, target: Node): void;
63
+ }
64
+ /**
65
+ * Bridges between ViewBehaviors and HostBehaviors, enabling a host to
66
+ * control ViewBehaviors.
67
+ * @public
68
+ */
69
+ export declare const ViewBehaviorOrchestrator: Readonly<{
70
+ /**
71
+ * Creates a ViewBehaviorOrchestrator.
72
+ * @param source - The source to to associate behaviors with.
73
+ * @returns A ViewBehaviorOrchestrator.
74
+ */
75
+ create<TSource = any, TParent = any>(source: TSource): ViewBehaviorOrchestrator<TSource, TParent>;
76
+ }>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Captures a binding expression along with related information and capabilities.
3
+ *
4
+ * @public
5
+ */
6
+ export class Binding {
7
+ /**
8
+ * Creates a binding.
9
+ * @param evaluate - Evaluates the binding.
10
+ * @param policy - The security policy to associate with this binding.
11
+ * @param isVolatile - Indicates whether the binding is volatile.
12
+ */
13
+ constructor(evaluate, policy, isVolatile = false) {
14
+ this.evaluate = evaluate;
15
+ this.policy = policy;
16
+ this.isVolatile = isVolatile;
17
+ }
18
+ }
@@ -0,0 +1,17 @@
1
+ import { isFunction } from "../interfaces.js";
2
+ import { Binding } from "./binding.js";
3
+ import { oneWay } from "./one-way.js";
4
+ import { oneTime } from "./one-time.js";
5
+ /**
6
+ * Normalizes the input value into a binding.
7
+ * @param value - The value to create the default binding for.
8
+ * @returns A binding configuration for the provided value.
9
+ * @public
10
+ */
11
+ export function normalizeBinding(value) {
12
+ return isFunction(value)
13
+ ? oneWay(value)
14
+ : value instanceof Binding
15
+ ? value
16
+ : oneTime(() => value);
17
+ }
@@ -0,0 +1,21 @@
1
+ import { makeSerializationNoop } from "../platform.js";
2
+ import { Binding } from "./binding.js";
3
+ class OneTimeBinding extends Binding {
4
+ createObserver() {
5
+ return this;
6
+ }
7
+ bind(controller) {
8
+ return this.evaluate(controller.source, controller.context);
9
+ }
10
+ }
11
+ makeSerializationNoop(OneTimeBinding);
12
+ /**
13
+ * Creates a one time binding
14
+ * @param expression - The binding to refresh when signaled.
15
+ * @param policy - The security policy to associate with th binding.
16
+ * @returns A binding configuration.
17
+ * @public
18
+ */
19
+ export function oneTime(expression, policy) {
20
+ return new OneTimeBinding(expression, policy);
21
+ }
@@ -0,0 +1,30 @@
1
+ import { Observable } from "../observation/observable.js";
2
+ import { Binding } from "./binding.js";
3
+ class OneWayBinding extends Binding {
4
+ createObserver(subscriber) {
5
+ return Observable.binding(this.evaluate, subscriber, this.isVolatile);
6
+ }
7
+ }
8
+ /**
9
+ * Creates an standard binding.
10
+ * @param expression - The binding to refresh when changed.
11
+ * @param policy - The security policy to associate with th binding.
12
+ * @param isVolatile - Indicates whether the binding is volatile or not.
13
+ * @returns A binding configuration.
14
+ * @public
15
+ */
16
+ export function oneWay(expression, policy, isVolatile = Observable.isVolatileBinding(expression)) {
17
+ return new OneWayBinding(expression, policy, isVolatile);
18
+ }
19
+ /**
20
+ * Creates an event listener binding.
21
+ * @param expression - The binding to invoke when the event is raised.
22
+ * @param options - Event listener options.
23
+ * @returns A binding configuration.
24
+ * @public
25
+ */
26
+ export function listener(expression, options) {
27
+ const config = new OneWayBinding(expression);
28
+ config.options = options;
29
+ return config;
30
+ }
@@ -1,7 +1,17 @@
1
1
  import { isString } from "../interfaces.js";
2
- import { Binding } from "./html-directive.js";
2
+ import { makeSerializationNoop } from "../platform.js";
3
+ import { Binding } from "./binding.js";
3
4
  const subscribers = Object.create(null);
5
+ /**
6
+ * The gateway to signal APIs.
7
+ * @public
8
+ */
4
9
  export const Signal = Object.freeze({
10
+ /**
11
+ * Subscribes to a signal.
12
+ * @param signal The signal to subscribe to.
13
+ * @param subscriber The subscriber.
14
+ */
5
15
  subscribe(signal, subscriber) {
6
16
  const found = subscribers[signal];
7
17
  if (found) {
@@ -13,6 +23,11 @@ export const Signal = Object.freeze({
13
23
  subscribers[signal] = subscriber;
14
24
  }
15
25
  },
26
+ /**
27
+ * Unsubscribes from the signal.
28
+ * @param signal The signal to unsubscribe from.
29
+ * @param subscriber The subscriber.
30
+ */
16
31
  unsubscribe(signal, subscriber) {
17
32
  const found = subscribers[signal];
18
33
  if (found && found instanceof Set) {
@@ -23,9 +38,8 @@ export const Signal = Object.freeze({
23
38
  }
24
39
  },
25
40
  /**
26
- * Sends the specified signal to signaled bindings.
41
+ * Sends the specified signal to subscribers.
27
42
  * @param signal - The signal to send.
28
- * @public
29
43
  */
30
44
  send(signal) {
31
45
  const found = subscribers[signal];
@@ -64,8 +78,9 @@ class SignalObserver {
64
78
  : options(controller.source, controller.context);
65
79
  }
66
80
  }
81
+ makeSerializationNoop(SignalObserver);
67
82
  class SignalBinding extends Binding {
68
- createObserver(directive, subscriber) {
83
+ createObserver(subscriber) {
69
84
  return new SignalObserver(this, subscriber);
70
85
  }
71
86
  }
@@ -73,11 +88,12 @@ class SignalBinding extends Binding {
73
88
  * Creates a signal binding configuration with the supplied options.
74
89
  * @param expression - The binding to refresh when signaled.
75
90
  * @param options - The signal name or a binding to use to retrieve the signal name.
91
+ * @param policy - The security policy to associate with th binding.
76
92
  * @returns A binding configuration.
77
93
  * @public
78
94
  */
79
- export function signal(expression, options) {
80
- const binding = new SignalBinding(expression);
95
+ export function signal(expression, options, policy) {
96
+ const binding = new SignalBinding(expression, policy);
81
97
  binding.options = options;
82
98
  return binding;
83
99
  }
@@ -1,7 +1,7 @@
1
1
  import { isString } from "../interfaces.js";
2
2
  import { Observable, } from "../observation/observable.js";
3
- import { FAST } from "../platform.js";
4
- import { Binding } from "./html-directive.js";
3
+ import { FAST, makeSerializationNoop } from "../platform.js";
4
+ import { Binding } from "./binding.js";
5
5
  const defaultOptions = {
6
6
  fromView: v => v,
7
7
  };
@@ -10,6 +10,9 @@ let twoWaySettings = {
10
10
  return "change";
11
11
  },
12
12
  };
13
+ /**
14
+ * Enables configuring two-way binding settings.
15
+ */
13
16
  export const TwoWaySettings = Object.freeze({
14
17
  /**
15
18
  * Configures two-way binding.
@@ -48,7 +51,7 @@ class TwoWayObserver {
48
51
  this.subscriber.handleChange(this.dataBinding.evaluate, this);
49
52
  }
50
53
  handleEvent(event) {
51
- const directive = this.directive;
54
+ const bindingSource = this.directive;
52
55
  const target = event.currentTarget;
53
56
  const notifier = this.notifier;
54
57
  const last = notifier.last; // using internal API!!!
@@ -57,37 +60,40 @@ class TwoWayObserver {
57
60
  return;
58
61
  }
59
62
  let value;
60
- switch (directive.aspectType) {
63
+ switch (bindingSource.aspectType) {
61
64
  case 1:
62
- value = target.getAttribute(directive.targetAspect);
65
+ value = target.getAttribute(bindingSource.targetAspect);
63
66
  break;
64
67
  case 2:
65
- value = target.hasAttribute(directive.targetAspect);
68
+ value = target.hasAttribute(bindingSource.targetAspect);
66
69
  break;
67
70
  case 4:
68
71
  value = target.innerText;
69
72
  break;
70
73
  default:
71
- value = target[directive.targetAspect];
74
+ value = target[bindingSource.targetAspect];
72
75
  break;
73
76
  }
74
- last.propertySource[last.propertyName] = this.dataBinding.options.fromView(value);
77
+ last.propertySource[last.propertyName] =
78
+ this.dataBinding.options.fromView(value);
75
79
  }
76
80
  }
81
+ makeSerializationNoop(TwoWayObserver);
77
82
  class TwoWayBinding extends Binding {
78
- createObserver(directive, subscriber) {
79
- return new TwoWayObserver(directive, subscriber, this);
83
+ createObserver(subscriber, bindingSource) {
84
+ return new TwoWayObserver(bindingSource, subscriber, this);
80
85
  }
81
86
  }
82
87
  /**
83
88
  * Creates a default binding.
84
89
  * @param expression - The binding to refresh when changed.
85
90
  * @param optionsOrChangeEvent - The binding options or the name of the change event to use.
91
+ * @param policy - The security policy to associate with the binding.
86
92
  * @param isBindingVolatile - Indicates whether the binding is volatile or not.
87
93
  * @returns A binding.
88
94
  * @public
89
95
  */
90
- export function twoWay(expression, optionsOrChangeEvent, isBindingVolatile = Observable.isVolatileBinding(expression)) {
96
+ export function twoWay(expression, optionsOrChangeEvent, policy, isBindingVolatile = Observable.isVolatileBinding(expression)) {
91
97
  if (isString(optionsOrChangeEvent)) {
92
98
  optionsOrChangeEvent = { changeEvent: optionsOrChangeEvent };
93
99
  }
@@ -97,7 +103,7 @@ export function twoWay(expression, optionsOrChangeEvent, isBindingVolatile = Obs
97
103
  else if (!optionsOrChangeEvent.fromView) {
98
104
  optionsOrChangeEvent.fromView = defaultOptions.fromView;
99
105
  }
100
- const binding = new TwoWayBinding(expression, isBindingVolatile);
106
+ const binding = new TwoWayBinding(expression, policy, isBindingVolatile);
101
107
  binding.options = optionsOrChangeEvent;
102
108
  return binding;
103
109
  }
@@ -1,7 +1,7 @@
1
1
  import { Observable } from "../observation/observable.js";
2
2
  import { isString } from "../interfaces.js";
3
3
  import { Updates } from "../observation/update-queue.js";
4
- import { DOM } from "../templating/dom.js";
4
+ import { DOM } from "../dom.js";
5
5
  import { createMetadataLocator } from "../platform.js";
6
6
  const booleanMode = "boolean";
7
7
  const reflectMode = "reflect";
@@ -35,6 +35,21 @@ export const booleanConverter = {
35
35
  : true;
36
36
  },
37
37
  };
38
+ /**
39
+ * A {@link ValueConverter} that converts to and from `boolean` values. `null`, `undefined`, `""`,
40
+ * and `void` values are converted to `null`.
41
+ * @public
42
+ */
43
+ export const nullableBooleanConverter = {
44
+ toView(value) {
45
+ return typeof value === "boolean" ? value.toString() : "";
46
+ },
47
+ fromView(value) {
48
+ return [null, undefined, void 0].includes(value)
49
+ ? null
50
+ : booleanConverter.fromView(value);
51
+ },
52
+ };
38
53
  function toNumber(value) {
39
54
  if (value === null || value === undefined) {
40
55
  return null;