@microsoft/fast-element 2.0.0-beta.9 → 2.0.1

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 +518 -0
  3. package/CHANGELOG.md +181 -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 +7 -1
  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 +19 -6
  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 +9789 -5667
  119. package/dist/fast-element.d.ts +813 -2392
  120. package/dist/fast-element.debug.js +2788 -974
  121. package/dist/fast-element.debug.min.js +3 -1
  122. package/dist/fast-element.js +2641 -833
  123. package/dist/fast-element.min.js +3 -1
  124. package/dist/fast-element.untrimmed.d.ts +662 -314
  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,213 +0,0 @@
1
- ---
2
- id: observables-and-state
3
- title: Observables and State
4
- sidebar_label: Observables and State
5
- custom_edit_url: https://github.com/microsoft/fast/edit/master/packages/web-components/fast-element/docs/guide/observables-and-state.md
6
- description: To enable binding tracking and change notification, properties must be decorated with either @attr or @observable.
7
- ---
8
-
9
- ## Reactivity
10
-
11
- The arrow function bindings and directives used in templates allow the `fast-element` templating engine to intelligently react by only updating the parts of the DOM that actually change, with no need for a virtual DOM, VDOM diffing, or DOM reconciliation algorithms. This approach enables top-tier initial render time, industry-leading incremental DOM updates, and ultra-low memory allocation.
12
-
13
- When a binding is used within a template, the underlying engine uses a technique to capture which properties are accessed in that expression. With the list of properties captured, it then subscribes to changes in their values. Any time a value changes, a task is scheduled on the DOM update queue. When the queue is processed, all updates run as a batch, updating precisely the aspects of the DOM that have changed.
14
-
15
- ## Observables
16
-
17
- To enable binding tracking and change notification, properties must be decorated with either `@attr` or `@observable`. Use `@attr` for primitive properties (string, bool, number) that are intended to be surfaced on your element as HTML attributes. Use `@observable` for all other properties. In addition to observing properties, the templating system can also observe arrays. The `repeat` directive is able to efficiently respond to array change records, updating the DOM based on changes in the collection.
18
-
19
- These decorators are a means of meta-programming the properties on your class, such that they include all the implementation needed to support state tracking, observation, and reactivity. You can access any property within your template, but if it hasn't been decorated with one of these two decorators, its value will not update after the initial render.
20
-
21
- :::important
22
- The `@attr` decorator can only be used in a `FASTElement` but the `@observable` decorator can be used in any class.
23
- :::
24
-
25
- :::important
26
- Properties with only a getter, that function as a computed property over other observables, should not be decorated with `@attr` or `@observable`. However, they may need to be decorated with `@volatile`, depending on the internal logic.
27
- :::
28
-
29
- ## Observable Features
30
-
31
- ### Access tracking
32
-
33
- When `@attr` and `@observable` decorated properties are accessed during template rendering, they are tracked, allowing the engine to deeply understand the relationship between your model and view. These decorators serves to meta-program the property for you, injecting code to enable the observation system. However, if you do not like this approach, for `@observable`, you can always implement notification manually. Here's what that would look like:
34
-
35
- **Example: Manual Observer Implementation**
36
-
37
- ```ts
38
- import { Observable } from '@microsoft/fast-element';
39
-
40
- export class Person {
41
- private _firstName: string;
42
- private _lastName: string;
43
-
44
- get firstName() {
45
- Observable.track(this, 'firstName');
46
- return this._firstName;
47
- }
48
-
49
- set firstName(value: string) {
50
- this._firstName = value;
51
- Observable.notify(this, 'firstName');
52
- }
53
-
54
- get lastName() {
55
- Observable.track(this, 'lastName');
56
- return this._lastName;
57
- }
58
-
59
- set lastName(value: string) {
60
- this._lastName = value;
61
- Observable.notify(this, 'lastName');
62
- }
63
-
64
- get fullName() {
65
- return `${this.firstName} ${this.lastName}`;
66
- }
67
- }
68
- ```
69
-
70
- Notice that the `fullName` property does not need any special code, since it's computing based on properties that are already observable. There is one special exception to this: if you have a computed property with branching code paths, such as ternary operators, if/else conditions, etc, then you must tell the observation system that your computed property has *volatile* dependencies. In other words, which properties need to be observed may change from invocation to invocation based on which code path executes.
71
-
72
- Here's how you would do that with a decorator:
73
-
74
- ```ts
75
- import { observable, volatile } from '@microsoft/fast-element';
76
-
77
- export class MyClass {
78
- @observable someBoolean = false;
79
- @observable valueA = 0;
80
- @observable valueB = 42;
81
-
82
- @volatile
83
- get computedValue() {
84
- return this.someBoolean ? this.valueA : this.valueB;
85
- }
86
- }
87
- ```
88
-
89
- Here's how you would do it without a decorator:
90
-
91
- ```ts
92
- import { Observable, observable } from '@microsoft/fast-element';
93
-
94
- export class MyClass {
95
- @observable someBoolean = false;
96
- @observable valueA = 0;
97
- @observable valueB = 42;
98
-
99
- get computedValue() {
100
- Observable.trackVolatile();
101
- return this.someBoolean ? this.valueA : this.valueB;
102
- }
103
- }
104
- ```
105
-
106
- ### Internal observation
107
-
108
- On the class where the `@attr` or `@observable` is defined, you can optionally implement a *propertyName*Changed method to easily respond to changes in your own state.
109
-
110
- **Example: Property Change Callbacks**
111
-
112
- ```ts
113
- import { observable } from '@microsoft/fast-element';
114
-
115
- export class Person {
116
- @observable name: string;
117
-
118
- nameChanged(oldValue: string, newValue: string) {
119
-
120
- }
121
- }
122
- ```
123
-
124
- ### External observation
125
-
126
- Decorated properties can be subscribed to, to receive notification of changes in the property value. The templating engine uses this, but you can also directly subscribe. Here's how you would subscribe to changes in the `name` property of a `Person` class:
127
-
128
- **Example: Subscribing to an Observable**
129
-
130
- ```ts
131
- import { Observable } from '@microsoft/fast-element';
132
-
133
- const person = new Person();
134
- const notifier = Observable.getNotifier(person);
135
- const handler = {
136
- handleChange(source: any, propertyName: string) {
137
- // respond to the change here
138
- // source will be the person instance
139
- // propertyName will be "name"
140
- }
141
- };
142
-
143
- notifier.subscribe(handler, 'firstName')
144
- notifier.unsubscribe(handler, 'lastName');
145
- ```
146
-
147
- ## Observing Arrays
148
-
149
- So far, we've only seen how to observe properties on objects, but it's also possible to observe arrays for changes. Given an instance of an array, it can be observed like this:
150
-
151
- **Example: Observing an Array**
152
-
153
- ```ts
154
- const arr = [];
155
- const notifier = Observable.getNotifier(arr);
156
- const handler = {
157
- handleChange(source: any, splices: Splice[]) {
158
- // respond to the change here
159
- // source will be the array instance
160
- // splices will be an array of change records
161
- // describing the mutations in the array in
162
- // terms of splice operations
163
- }
164
- };
165
-
166
- notifier.subscribe(handler);
167
- ```
168
-
169
- There are a couple of important details to note with array observation:
170
-
171
- * The `fast-element` library's ability to observe arrays is opt-in, in order that the functionality remain tree-shakeable. If you use a `repeat` directive anywhere in your code, you will be automatically opted in. However, if you wish to use the above APIs and are not using `repeat`, you will need to enable array observation by importing and calling the `enableArrayObservation()` function.
172
- * The observation system cannot track changes made directly through an index update. e.g. `arr[3] = 'new value';`. This is due to a limitation in JavaScript. To work around this, update arrays with the equivalent `splice` code e.g. `arr.splice(3, 1, 'new value');`
173
- * If the array is a property of an object, you will often want to observe both the property and the array. Observing the property will allow you to detect when the array instance is completely replaced on the object, while observing the array will allow you to detect changes in the array instance itself. When the property changes, be sure to unsubscribe to the old array and set up a subscription to the new array instance.
174
- * Observing an array only notifies on changes to the array itself. It does not notify on changes to properties on objects held within the array. Separate observers would need to be set up for those individual properties. These could be set up and torn down in response to changes in the array though.
175
-
176
- ## Observing Volatile Properties
177
-
178
- In addition to watching properties and arrays, you can also watch volatile properties.
179
-
180
- **Example: Subscribing to a Volatile Property**
181
-
182
- ```ts
183
- import { Observable, defaultExecutionContext } from '@microsoft/fast-element';
184
-
185
- const myObject = new MyClass();
186
- const handler = {
187
- handleChange(source: any) {
188
- // respond to the change here
189
- // the source is the volatile binding itself
190
- }
191
- };
192
- const bindingObserver = Observable.binding(myObject.computedValue, handler);
193
- bindingObserver.observe(myObject, defaultExecutionContext);
194
-
195
- // Call this to dismantle the observer
196
- bindingObserver.disconnect();
197
- ```
198
-
199
- ### Records
200
-
201
- To inspect which observable objects and properties were accessed from a `BindingObserver`, you can get the observation records from `BindingObserver.records()` after observing the binding.
202
-
203
- **Example: Getting observation records**
204
- ```ts
205
- const binding = (x: MyClass) => x.someBoolean ? x.valueA : x.valueB;
206
- const bindingObserver = Observable.binding(binding);
207
- const value = bindingObserver.observe({}, defaultExecutionContext);
208
-
209
- for (const record of bindingObserver.records()) {
210
- // Do something with the binding's observable dependencies
211
- console.log(record.propertySource, record.propertyName)
212
- }
213
- ```