@microsoft/fast-element 1.10.1 → 2.0.0-beta.2

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 (106) hide show
  1. package/.eslintrc.json +1 -12
  2. package/CHANGELOG.json +432 -1
  3. package/CHANGELOG.md +74 -2
  4. package/README.md +2 -2
  5. package/dist/dts/components/attributes.d.ts +4 -1
  6. package/dist/dts/components/controller.d.ts +12 -11
  7. package/dist/dts/components/fast-definitions.d.ts +10 -2
  8. package/dist/dts/components/fast-element.d.ts +12 -5
  9. package/dist/dts/context.d.ts +157 -0
  10. package/dist/dts/debug.d.ts +1 -0
  11. package/dist/dts/hooks.d.ts +20 -0
  12. package/dist/dts/index.d.ts +16 -15
  13. package/dist/dts/index.debug.d.ts +2 -0
  14. package/dist/dts/index.rollup.d.ts +2 -0
  15. package/dist/dts/index.rollup.debug.d.ts +3 -0
  16. package/dist/dts/interfaces.d.ts +144 -0
  17. package/dist/dts/metadata.d.ts +25 -0
  18. package/dist/dts/observation/arrays.d.ts +207 -0
  19. package/dist/dts/observation/behavior.d.ts +4 -4
  20. package/dist/dts/observation/notifier.d.ts +18 -18
  21. package/dist/dts/observation/observable.d.ts +56 -18
  22. package/dist/dts/observation/splice-strategies.d.ts +13 -0
  23. package/dist/dts/observation/update-queue.d.ts +40 -0
  24. package/dist/dts/platform.d.ts +18 -67
  25. package/dist/dts/polyfills.d.ts +8 -0
  26. package/dist/dts/styles/css-directive.d.ts +43 -5
  27. package/dist/dts/styles/css.d.ts +19 -3
  28. package/dist/dts/styles/element-styles.d.ts +42 -62
  29. package/dist/dts/templating/binding-signal.d.ts +38 -0
  30. package/dist/dts/templating/binding-two-way.d.ts +56 -0
  31. package/dist/dts/templating/binding.d.ts +233 -65
  32. package/dist/dts/templating/children.d.ts +18 -15
  33. package/dist/dts/templating/compiler.d.ts +46 -28
  34. package/dist/dts/templating/dom.d.ts +41 -0
  35. package/dist/dts/templating/html-directive.d.ts +179 -43
  36. package/dist/dts/templating/markup.d.ts +48 -0
  37. package/dist/dts/templating/node-observation.d.ts +45 -29
  38. package/dist/dts/templating/ref.d.ts +6 -12
  39. package/dist/dts/templating/repeat.d.ts +26 -14
  40. package/dist/dts/templating/slotted.d.ts +13 -14
  41. package/dist/dts/templating/template.d.ts +27 -21
  42. package/dist/dts/templating/view.d.ts +15 -22
  43. package/dist/{tsdoc-metadata.json → dts/tsdoc-metadata.json} +1 -1
  44. package/dist/dts/utilities.d.ts +40 -0
  45. package/dist/esm/components/attributes.js +25 -24
  46. package/dist/esm/components/controller.js +77 -57
  47. package/dist/esm/components/fast-definitions.js +16 -22
  48. package/dist/esm/components/fast-element.js +10 -2
  49. package/dist/esm/context.js +159 -0
  50. package/dist/esm/debug.js +29 -0
  51. package/dist/esm/hooks.js +32 -0
  52. package/dist/esm/index.debug.js +2 -0
  53. package/dist/esm/index.js +19 -14
  54. package/dist/esm/index.rollup.debug.js +3 -0
  55. package/dist/esm/index.rollup.js +2 -0
  56. package/dist/esm/interfaces.js +8 -1
  57. package/dist/esm/metadata.js +60 -0
  58. package/dist/esm/observation/arrays.js +269 -0
  59. package/dist/esm/observation/notifier.js +75 -83
  60. package/dist/esm/observation/observable.js +93 -68
  61. package/dist/esm/observation/{array-change-records.js → splice-strategies.js} +136 -62
  62. package/dist/esm/observation/update-queue.js +67 -0
  63. package/dist/esm/platform.js +36 -42
  64. package/dist/esm/polyfills.js +85 -0
  65. package/dist/esm/styles/css-directive.js +29 -13
  66. package/dist/esm/styles/css.js +27 -40
  67. package/dist/esm/styles/element-styles.js +65 -104
  68. package/dist/esm/templating/binding-signal.js +84 -0
  69. package/dist/esm/templating/binding-two-way.js +76 -0
  70. package/dist/esm/templating/binding.js +306 -153
  71. package/dist/esm/templating/children.js +33 -23
  72. package/dist/esm/templating/compiler.js +235 -152
  73. package/dist/esm/templating/dom.js +49 -0
  74. package/dist/esm/templating/html-directive.js +125 -40
  75. package/dist/esm/templating/markup.js +75 -0
  76. package/dist/esm/templating/node-observation.js +50 -45
  77. package/dist/esm/templating/ref.js +7 -16
  78. package/dist/esm/templating/repeat.js +39 -36
  79. package/dist/esm/templating/slotted.js +23 -20
  80. package/dist/esm/templating/template.js +51 -95
  81. package/dist/esm/templating/view.js +44 -43
  82. package/dist/esm/templating/when.js +2 -1
  83. package/dist/esm/utilities.js +139 -0
  84. package/dist/fast-element.api.json +11789 -5377
  85. package/dist/fast-element.d.ts +1177 -531
  86. package/dist/fast-element.debug.js +3717 -0
  87. package/dist/fast-element.debug.min.js +1 -0
  88. package/dist/fast-element.js +3466 -4022
  89. package/dist/fast-element.min.js +1 -1
  90. package/dist/fast-element.untrimmed.d.ts +2697 -0
  91. package/docs/api-report.md +472 -219
  92. package/docs/fast-element-2-changes.md +15 -0
  93. package/docs/guide/declaring-templates.md +5 -4
  94. package/docs/guide/defining-elements.md +3 -2
  95. package/docs/guide/leveraging-css.md +1 -0
  96. package/docs/guide/next-steps.md +3 -2
  97. package/docs/guide/observables-and-state.md +2 -1
  98. package/docs/guide/using-directives.md +2 -1
  99. package/docs/guide/working-with-shadow-dom.md +1 -0
  100. package/karma.conf.cjs +6 -17
  101. package/package.json +65 -15
  102. package/dist/dts/dom.d.ts +0 -112
  103. package/dist/dts/observation/array-change-records.d.ts +0 -48
  104. package/dist/dts/observation/array-observer.d.ts +0 -9
  105. package/dist/esm/dom.js +0 -207
  106. package/dist/esm/observation/array-observer.js +0 -173
package/dist/esm/dom.js DELETED
@@ -1,207 +0,0 @@
1
- import { $global } from "./platform.js";
2
- const updateQueue = $global.FAST.getById(1 /* updateQueue */, () => {
3
- const tasks = [];
4
- const pendingErrors = [];
5
- function throwFirstError() {
6
- if (pendingErrors.length) {
7
- throw pendingErrors.shift();
8
- }
9
- }
10
- function tryRunTask(task) {
11
- try {
12
- task.call();
13
- }
14
- catch (error) {
15
- pendingErrors.push(error);
16
- setTimeout(throwFirstError, 0);
17
- }
18
- }
19
- function process() {
20
- const capacity = 1024;
21
- let index = 0;
22
- while (index < tasks.length) {
23
- tryRunTask(tasks[index]);
24
- index++;
25
- // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
26
- // If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
27
- // grow, but to avoid an O(n) walk for every task we execute, we don't
28
- // shift tasks off the queue after they have been executed.
29
- // Instead, we periodically shift 1024 tasks off the queue.
30
- if (index > capacity) {
31
- // Manually shift all values starting at the index back to the
32
- // beginning of the queue.
33
- for (let scan = 0, newLength = tasks.length - index; scan < newLength; scan++) {
34
- tasks[scan] = tasks[scan + index];
35
- }
36
- tasks.length -= index;
37
- index = 0;
38
- }
39
- }
40
- tasks.length = 0;
41
- }
42
- function enqueue(callable) {
43
- if (tasks.length < 1) {
44
- $global.requestAnimationFrame(process);
45
- }
46
- tasks.push(callable);
47
- }
48
- return Object.freeze({
49
- enqueue,
50
- process,
51
- });
52
- });
53
- /* eslint-disable */
54
- const fastHTMLPolicy = $global.trustedTypes.createPolicy("fast-html", {
55
- createHTML: html => html,
56
- });
57
- /* eslint-enable */
58
- let htmlPolicy = fastHTMLPolicy;
59
- const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
60
- /** @internal */
61
- export const _interpolationStart = `${marker}{`;
62
- /** @internal */
63
- export const _interpolationEnd = `}${marker}`;
64
- /**
65
- * Common DOM APIs.
66
- * @public
67
- */
68
- export const DOM = Object.freeze({
69
- /**
70
- * Indicates whether the DOM supports the adoptedStyleSheets feature.
71
- */
72
- supportsAdoptedStyleSheets: Array.isArray(document.adoptedStyleSheets) &&
73
- "replace" in CSSStyleSheet.prototype,
74
- /**
75
- * Sets the HTML trusted types policy used by the templating engine.
76
- * @param policy - The policy to set for HTML.
77
- * @remarks
78
- * This API can only be called once, for security reasons. It should be
79
- * called by the application developer at the start of their program.
80
- */
81
- setHTMLPolicy(policy) {
82
- if (htmlPolicy !== fastHTMLPolicy) {
83
- throw new Error("The HTML policy can only be set once.");
84
- }
85
- htmlPolicy = policy;
86
- },
87
- /**
88
- * Turns a string into trusted HTML using the configured trusted types policy.
89
- * @param html - The string to turn into trusted HTML.
90
- * @remarks
91
- * Used internally by the template engine when creating templates
92
- * and setting innerHTML.
93
- */
94
- createHTML(html) {
95
- return htmlPolicy.createHTML(html);
96
- },
97
- /**
98
- * Determines if the provided node is a template marker used by the runtime.
99
- * @param node - The node to test.
100
- */
101
- isMarker(node) {
102
- return node && node.nodeType === 8 && node.data.startsWith(marker);
103
- },
104
- /**
105
- * Given a marker node, extract the {@link HTMLDirective} index from the placeholder.
106
- * @param node - The marker node to extract the index from.
107
- */
108
- extractDirectiveIndexFromMarker(node) {
109
- return parseInt(node.data.replace(`${marker}:`, ""));
110
- },
111
- /**
112
- * Creates a placeholder string suitable for marking out a location *within*
113
- * an attribute value or HTML content.
114
- * @param index - The directive index to create the placeholder for.
115
- * @remarks
116
- * Used internally by binding directives.
117
- */
118
- createInterpolationPlaceholder(index) {
119
- return `${_interpolationStart}${index}${_interpolationEnd}`;
120
- },
121
- /**
122
- * Creates a placeholder that manifests itself as an attribute on an
123
- * element.
124
- * @param attributeName - The name of the custom attribute.
125
- * @param index - The directive index to create the placeholder for.
126
- * @remarks
127
- * Used internally by attribute directives such as `ref`, `slotted`, and `children`.
128
- */
129
- createCustomAttributePlaceholder(attributeName, index) {
130
- return `${attributeName}="${this.createInterpolationPlaceholder(index)}"`;
131
- },
132
- /**
133
- * Creates a placeholder that manifests itself as a marker within the DOM structure.
134
- * @param index - The directive index to create the placeholder for.
135
- * @remarks
136
- * Used internally by structural directives such as `repeat`.
137
- */
138
- createBlockPlaceholder(index) {
139
- return `<!--${marker}:${index}-->`;
140
- },
141
- /**
142
- * Schedules DOM update work in the next async batch.
143
- * @param callable - The callable function or object to queue.
144
- */
145
- queueUpdate: updateQueue.enqueue,
146
- /**
147
- * Immediately processes all work previously scheduled
148
- * through queueUpdate.
149
- * @remarks
150
- * This also forces nextUpdate promises
151
- * to resolve.
152
- */
153
- processUpdates: updateQueue.process,
154
- /**
155
- * Resolves with the next DOM update.
156
- */
157
- nextUpdate() {
158
- return new Promise(updateQueue.enqueue);
159
- },
160
- /**
161
- * Sets an attribute value on an element.
162
- * @param element - The element to set the attribute value on.
163
- * @param attributeName - The attribute name to set.
164
- * @param value - The value of the attribute to set.
165
- * @remarks
166
- * If the value is `null` or `undefined`, the attribute is removed, otherwise
167
- * it is set to the provided value using the standard `setAttribute` API.
168
- */
169
- setAttribute(element, attributeName, value) {
170
- if (value === null || value === undefined) {
171
- element.removeAttribute(attributeName);
172
- }
173
- else {
174
- element.setAttribute(attributeName, value);
175
- }
176
- },
177
- /**
178
- * Sets a boolean attribute value.
179
- * @param element - The element to set the boolean attribute value on.
180
- * @param attributeName - The attribute name to set.
181
- * @param value - The value of the attribute to set.
182
- * @remarks
183
- * If the value is true, the attribute is added; otherwise it is removed.
184
- */
185
- setBooleanAttribute(element, attributeName, value) {
186
- value
187
- ? element.setAttribute(attributeName, "")
188
- : element.removeAttribute(attributeName);
189
- },
190
- /**
191
- * Removes all the child nodes of the provided parent node.
192
- * @param parent - The node to remove the children from.
193
- */
194
- removeChildNodes(parent) {
195
- for (let child = parent.firstChild; child !== null; child = parent.firstChild) {
196
- parent.removeChild(child);
197
- }
198
- },
199
- /**
200
- * Creates a TreeWalker configured to walk a template fragment.
201
- * @param fragment - The fragment to walk.
202
- */
203
- createTemplateWalker(fragment) {
204
- return document.createTreeWalker(fragment, 133, // element, text, comment
205
- null, false);
206
- },
207
- });
@@ -1,173 +0,0 @@
1
- import { DOM } from "../dom.js";
2
- import { calcSplices, newSplice, projectArraySplices } from "./array-change-records.js";
3
- import { SubscriberSet } from "./notifier.js";
4
- import { Observable } from "./observable.js";
5
- let arrayObservationEnabled = false;
6
- function adjustIndex(changeRecord, array) {
7
- let index = changeRecord.index;
8
- const arrayLength = array.length;
9
- if (index > arrayLength) {
10
- index = arrayLength - changeRecord.addedCount;
11
- }
12
- else if (index < 0) {
13
- index =
14
- arrayLength + changeRecord.removed.length + index - changeRecord.addedCount;
15
- }
16
- if (index < 0) {
17
- index = 0;
18
- }
19
- changeRecord.index = index;
20
- return changeRecord;
21
- }
22
- class ArrayObserver extends SubscriberSet {
23
- constructor(source) {
24
- super(source);
25
- this.oldCollection = void 0;
26
- this.splices = void 0;
27
- this.needsQueue = true;
28
- this.call = this.flush;
29
- Reflect.defineProperty(source, "$fastController", {
30
- value: this,
31
- enumerable: false,
32
- });
33
- }
34
- addSplice(splice) {
35
- if (this.splices === void 0) {
36
- this.splices = [splice];
37
- }
38
- else {
39
- this.splices.push(splice);
40
- }
41
- if (this.needsQueue) {
42
- this.needsQueue = false;
43
- DOM.queueUpdate(this);
44
- }
45
- }
46
- reset(oldCollection) {
47
- this.oldCollection = oldCollection;
48
- if (this.needsQueue) {
49
- this.needsQueue = false;
50
- DOM.queueUpdate(this);
51
- }
52
- }
53
- flush() {
54
- const splices = this.splices;
55
- const oldCollection = this.oldCollection;
56
- if (splices === void 0 && oldCollection === void 0) {
57
- return;
58
- }
59
- this.needsQueue = true;
60
- this.splices = void 0;
61
- this.oldCollection = void 0;
62
- const finalSplices = oldCollection === void 0
63
- ? projectArraySplices(this.source, splices)
64
- : calcSplices(this.source, 0, this.source.length, oldCollection, 0, oldCollection.length);
65
- this.notify(finalSplices);
66
- }
67
- }
68
- /* eslint-disable prefer-rest-params */
69
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
70
- /**
71
- * Enables the array observation mechanism.
72
- * @remarks
73
- * Array observation is enabled automatically when using the
74
- * {@link RepeatDirective}, so calling this API manually is
75
- * not typically necessary.
76
- * @public
77
- */
78
- export function enableArrayObservation() {
79
- if (arrayObservationEnabled) {
80
- return;
81
- }
82
- arrayObservationEnabled = true;
83
- Observable.setArrayObserverFactory((collection) => {
84
- return new ArrayObserver(collection);
85
- });
86
- const proto = Array.prototype;
87
- // Don't patch Array if it has already been patched
88
- // by another copy of fast-element.
89
- if (proto.$fastPatch) {
90
- return;
91
- }
92
- Reflect.defineProperty(proto, "$fastPatch", {
93
- value: 1,
94
- enumerable: false,
95
- });
96
- const pop = proto.pop;
97
- const push = proto.push;
98
- const reverse = proto.reverse;
99
- const shift = proto.shift;
100
- const sort = proto.sort;
101
- const splice = proto.splice;
102
- const unshift = proto.unshift;
103
- proto.pop = function () {
104
- const notEmpty = this.length > 0;
105
- const methodCallResult = pop.apply(this, arguments);
106
- const o = this.$fastController;
107
- if (o !== void 0 && notEmpty) {
108
- o.addSplice(newSplice(this.length, [methodCallResult], 0));
109
- }
110
- return methodCallResult;
111
- };
112
- proto.push = function () {
113
- const methodCallResult = push.apply(this, arguments);
114
- const o = this.$fastController;
115
- if (o !== void 0) {
116
- o.addSplice(adjustIndex(newSplice(this.length - arguments.length, [], arguments.length), this));
117
- }
118
- return methodCallResult;
119
- };
120
- proto.reverse = function () {
121
- let oldArray;
122
- const o = this.$fastController;
123
- if (o !== void 0) {
124
- o.flush();
125
- oldArray = this.slice();
126
- }
127
- const methodCallResult = reverse.apply(this, arguments);
128
- if (o !== void 0) {
129
- o.reset(oldArray);
130
- }
131
- return methodCallResult;
132
- };
133
- proto.shift = function () {
134
- const notEmpty = this.length > 0;
135
- const methodCallResult = shift.apply(this, arguments);
136
- const o = this.$fastController;
137
- if (o !== void 0 && notEmpty) {
138
- o.addSplice(newSplice(0, [methodCallResult], 0));
139
- }
140
- return methodCallResult;
141
- };
142
- proto.sort = function () {
143
- let oldArray;
144
- const o = this.$fastController;
145
- if (o !== void 0) {
146
- o.flush();
147
- oldArray = this.slice();
148
- }
149
- const methodCallResult = sort.apply(this, arguments);
150
- if (o !== void 0) {
151
- o.reset(oldArray);
152
- }
153
- return methodCallResult;
154
- };
155
- proto.splice = function () {
156
- const methodCallResult = splice.apply(this, arguments);
157
- const o = this.$fastController;
158
- if (o !== void 0) {
159
- o.addSplice(adjustIndex(newSplice(+arguments[0], methodCallResult, arguments.length > 2 ? arguments.length - 2 : 0), this));
160
- }
161
- return methodCallResult;
162
- };
163
- proto.unshift = function () {
164
- const methodCallResult = unshift.apply(this, arguments);
165
- const o = this.$fastController;
166
- if (o !== void 0) {
167
- o.addSplice(adjustIndex(newSplice(0, [], arguments.length), this));
168
- }
169
- return methodCallResult;
170
- };
171
- }
172
- /* eslint-enable prefer-rest-params */
173
- /* eslint-enable @typescript-eslint/explicit-function-return-type */