@microsoft/fast-element 1.7.1 → 1.9.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 (56) hide show
  1. package/.eslintrc.json +30 -0
  2. package/CHANGELOG.json +73 -1
  3. package/CHANGELOG.md +26 -2
  4. package/dist/dts/components/attributes.d.ts +1 -1
  5. package/dist/dts/components/controller.d.ts +6 -6
  6. package/dist/dts/components/fast-definitions.d.ts +5 -5
  7. package/dist/dts/components/fast-element.d.ts +2 -2
  8. package/dist/dts/dom.d.ts +4 -4
  9. package/dist/dts/index.d.ts +26 -26
  10. package/dist/dts/observation/behavior.d.ts +1 -1
  11. package/dist/dts/observation/observable.d.ts +51 -50
  12. package/dist/dts/platform.d.ts +37 -0
  13. package/dist/dts/styles/css-directive.d.ts +2 -2
  14. package/dist/dts/styles/css.d.ts +2 -2
  15. package/dist/dts/styles/element-styles.d.ts +1 -1
  16. package/dist/dts/templating/binding.d.ts +3 -3
  17. package/dist/dts/templating/children.d.ts +2 -2
  18. package/dist/dts/templating/compiler.d.ts +1 -1
  19. package/dist/dts/templating/html-directive.d.ts +1 -1
  20. package/dist/dts/templating/node-observation.d.ts +1 -1
  21. package/dist/dts/templating/ref.d.ts +2 -2
  22. package/dist/dts/templating/repeat.d.ts +6 -6
  23. package/dist/dts/templating/slotted.d.ts +2 -2
  24. package/dist/dts/templating/template.d.ts +3 -3
  25. package/dist/dts/templating/view.d.ts +2 -2
  26. package/dist/dts/templating/when.d.ts +2 -2
  27. package/dist/esm/components/attributes.js +2 -2
  28. package/dist/esm/components/controller.js +4 -4
  29. package/dist/esm/components/fast-definitions.js +31 -14
  30. package/dist/esm/components/fast-element.js +2 -2
  31. package/dist/esm/dom.js +55 -50
  32. package/dist/esm/index.js +23 -23
  33. package/dist/esm/observation/array-change-records.js +1 -1
  34. package/dist/esm/observation/array-observer.js +12 -6
  35. package/dist/esm/observation/observable.js +244 -236
  36. package/dist/esm/platform.js +23 -0
  37. package/dist/esm/styles/css.js +2 -2
  38. package/dist/esm/styles/element-styles.js +1 -1
  39. package/dist/esm/templating/binding.js +5 -5
  40. package/dist/esm/templating/children.js +2 -2
  41. package/dist/esm/templating/compiler.js +2 -2
  42. package/dist/esm/templating/html-directive.js +1 -1
  43. package/dist/esm/templating/node-observation.js +2 -2
  44. package/dist/esm/templating/ref.js +1 -1
  45. package/dist/esm/templating/repeat.js +6 -6
  46. package/dist/esm/templating/slotted.js +2 -2
  47. package/dist/esm/templating/template.js +6 -6
  48. package/dist/fast-element.api.json +43 -48
  49. package/dist/fast-element.d.ts +53 -13
  50. package/dist/fast-element.js +428 -344
  51. package/dist/fast-element.min.js +1 -1
  52. package/docs/api-report.md +39 -12
  53. package/docs/guide/observables-and-state.md +10 -8
  54. package/docs/guide/using-directives.md +1 -1
  55. package/karma.conf.cjs +152 -0
  56. package/package.json +11 -10
@@ -1,9 +1,24 @@
1
- import { Observable } from "../observation/observable";
2
- import { ElementStyles } from "../styles/element-styles";
3
- import { AttributeDefinition } from "./attributes";
1
+ import { FAST } from "../platform.js";
2
+ import { Observable } from "../observation/observable.js";
3
+ import { ElementStyles } from "../styles/element-styles.js";
4
+ import { AttributeDefinition } from "./attributes.js";
4
5
  const defaultShadowOptions = { mode: "open" };
5
6
  const defaultElementOptions = {};
6
- const fastDefinitions = new Map();
7
+ const fastRegistry = FAST.getById(4 /* elementRegistry */, () => {
8
+ const typeToDefinition = new Map();
9
+ return Object.freeze({
10
+ register(definition) {
11
+ if (typeToDefinition.has(definition.type)) {
12
+ return false;
13
+ }
14
+ typeToDefinition.set(definition.type, definition);
15
+ return true;
16
+ },
17
+ getByType(key) {
18
+ return typeToDefinition.get(key);
19
+ },
20
+ });
21
+ });
7
22
  /**
8
23
  * Defines metadata for a FASTElement.
9
24
  * @public
@@ -55,13 +70,19 @@ export class FASTElementDefinition {
55
70
  ? nameOrConfig.styles
56
71
  : ElementStyles.create([nameOrConfig.styles]);
57
72
  }
73
+ /**
74
+ * Indicates if this element has been defined in at least one registry.
75
+ */
76
+ get isDefined() {
77
+ return !!fastRegistry.getByType(this.type);
78
+ }
58
79
  /**
59
80
  * Defines a custom element based on this definition.
60
81
  * @param registry - The element registry to define the element in.
61
82
  */
62
83
  define(registry = customElements) {
63
84
  const type = this.type;
64
- if (!this.isDefined) {
85
+ if (fastRegistry.register(this)) {
65
86
  const attributes = this.attributes;
66
87
  const proto = type.prototype;
67
88
  for (let i = 0, ii = attributes.length; i < ii; ++i) {
@@ -71,19 +92,15 @@ export class FASTElementDefinition {
71
92
  value: this.observedAttributes,
72
93
  enumerable: true,
73
94
  });
74
- fastDefinitions.set(type, this);
75
- this.isDefined = true;
76
95
  }
77
96
  if (!registry.get(this.name)) {
78
97
  registry.define(this.name, type, this.elementOptions);
79
98
  }
80
99
  return this;
81
100
  }
82
- /**
83
- * Gets the element definition associated with the specified type.
84
- * @param type - The custom element type to retrieve the definition for.
85
- */
86
- static forType(type) {
87
- return fastDefinitions.get(type);
88
- }
89
101
  }
102
+ /**
103
+ * Gets the element definition associated with the specified type.
104
+ * @param type - The custom element type to retrieve the definition for.
105
+ */
106
+ FASTElementDefinition.forType = fastRegistry.getByType;
@@ -1,5 +1,5 @@
1
- import { Controller } from "./controller";
2
- import { FASTElementDefinition } from "./fast-definitions";
1
+ import { Controller } from "./controller.js";
2
+ import { FASTElementDefinition, } from "./fast-definitions.js";
3
3
  /* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
4
4
  function createFASTElement(BaseType) {
5
5
  return class extends BaseType {
package/dist/esm/dom.js CHANGED
@@ -1,27 +1,61 @@
1
- import { $global } from "./platform";
2
- const updateQueue = [];
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
+ });
3
53
  /* eslint-disable */
4
54
  const fastHTMLPolicy = $global.trustedTypes.createPolicy("fast-html", {
5
55
  createHTML: html => html,
6
56
  });
7
57
  /* eslint-enable */
8
58
  let htmlPolicy = fastHTMLPolicy;
9
- // We use a queue so we can ensure errors are thrown in order.
10
- const pendingErrors = [];
11
- function throwFirstError() {
12
- if (pendingErrors.length) {
13
- throw pendingErrors.shift();
14
- }
15
- }
16
- function tryRunTask(task) {
17
- try {
18
- task.call();
19
- }
20
- catch (error) {
21
- pendingErrors.push(error);
22
- setTimeout(throwFirstError, 0);
23
- }
24
- }
25
59
  const marker = `fast-${Math.random().toString(36).substring(2, 8)}`;
26
60
  /** @internal */
27
61
  export const _interpolationStart = `${marker}{`;
@@ -108,12 +142,7 @@ export const DOM = Object.freeze({
108
142
  * Schedules DOM update work in the next async batch.
109
143
  * @param callable - The callable function or object to queue.
110
144
  */
111
- queueUpdate(callable) {
112
- if (updateQueue.length < 1) {
113
- window.requestAnimationFrame(DOM.processUpdates);
114
- }
115
- updateQueue.push(callable);
116
- },
145
+ queueUpdate: updateQueue.enqueue,
117
146
  /**
118
147
  * Immediately processes all work previously scheduled
119
148
  * through queueUpdate.
@@ -121,36 +150,12 @@ export const DOM = Object.freeze({
121
150
  * This also forces nextUpdate promises
122
151
  * to resolve.
123
152
  */
124
- processUpdates() {
125
- const capacity = 1024;
126
- let index = 0;
127
- while (index < updateQueue.length) {
128
- tryRunTask(updateQueue[index]);
129
- index++;
130
- // Prevent leaking memory for long chains of recursive calls to `DOM.queueUpdate`.
131
- // If we call `DOM.queueUpdate` within a task scheduled by `DOM.queueUpdate`, the queue will
132
- // grow, but to avoid an O(n) walk for every task we execute, we don't
133
- // shift tasks off the queue after they have been executed.
134
- // Instead, we periodically shift 1024 tasks off the queue.
135
- if (index > capacity) {
136
- // Manually shift all values starting at the index back to the
137
- // beginning of the queue.
138
- for (let scan = 0, newLength = updateQueue.length - index; scan < newLength; scan++) {
139
- updateQueue[scan] = updateQueue[scan + index];
140
- }
141
- updateQueue.length -= index;
142
- index = 0;
143
- }
144
- }
145
- updateQueue.length = 0;
146
- },
153
+ processUpdates: updateQueue.process,
147
154
  /**
148
155
  * Resolves with the next DOM update.
149
156
  */
150
157
  nextUpdate() {
151
- return new Promise((resolve) => {
152
- DOM.queueUpdate(resolve);
153
- });
158
+ return new Promise(updateQueue.enqueue);
154
159
  },
155
160
  /**
156
161
  * Sets an attribute value on an element.
package/dist/esm/index.js CHANGED
@@ -1,23 +1,23 @@
1
- export * from "./platform";
2
- export * from "./templating/template";
3
- export * from "./components/fast-element";
4
- export { FASTElementDefinition, } from "./components/fast-definitions";
5
- export * from "./components/attributes";
6
- export * from "./components/controller";
7
- export * from "./templating/compiler";
8
- export { ElementStyles, } from "./styles/element-styles";
9
- export { css, cssPartial } from "./styles/css";
10
- export { CSSDirective } from "./styles/css-directive";
11
- export * from "./templating/view";
12
- export * from "./observation/observable";
13
- export * from "./observation/notifier";
14
- export { enableArrayObservation } from "./observation/array-observer";
15
- export { DOM } from "./dom";
16
- export * from "./templating/binding";
17
- export * from "./templating/html-directive";
18
- export * from "./templating/ref";
19
- export * from "./templating/when";
20
- export * from "./templating/repeat";
21
- export * from "./templating/slotted";
22
- export * from "./templating/children";
23
- export { elements, } from "./templating/node-observation";
1
+ export * from "./platform.js";
2
+ export * from "./templating/template.js";
3
+ export * from "./components/fast-element.js";
4
+ export { FASTElementDefinition, } from "./components/fast-definitions.js";
5
+ export * from "./components/attributes.js";
6
+ export * from "./components/controller.js";
7
+ export * from "./templating/compiler.js";
8
+ export { ElementStyles, } from "./styles/element-styles.js";
9
+ export { css, cssPartial } from "./styles/css.js";
10
+ export { CSSDirective } from "./styles/css-directive.js";
11
+ export * from "./templating/view.js";
12
+ export * from "./observation/observable.js";
13
+ export * from "./observation/notifier.js";
14
+ export { enableArrayObservation } from "./observation/array-observer.js";
15
+ export { DOM } from "./dom.js";
16
+ export * from "./templating/binding.js";
17
+ export * from "./templating/html-directive.js";
18
+ export * from "./templating/ref.js";
19
+ export * from "./templating/when.js";
20
+ export * from "./templating/repeat.js";
21
+ export * from "./templating/slotted.js";
22
+ export * from "./templating/children.js";
23
+ export { elements, } from "./templating/node-observation.js";
@@ -1,4 +1,4 @@
1
- import { emptyArray } from "../platform";
1
+ import { emptyArray } from "../platform.js";
2
2
  /** @internal */
3
3
  export function newSplice(index, removed, addedCount) {
4
4
  return {
@@ -1,7 +1,7 @@
1
- import { DOM } from "../dom";
2
- import { calcSplices, newSplice, projectArraySplices } from "./array-change-records";
3
- import { SubscriberSet } from "./notifier";
4
- import { Observable } from "./observable";
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
5
  let arrayObservationEnabled = false;
6
6
  function adjustIndex(changeRecord, array) {
7
7
  let index = changeRecord.index;
@@ -26,7 +26,10 @@ class ArrayObserver extends SubscriberSet {
26
26
  this.splices = void 0;
27
27
  this.needsQueue = true;
28
28
  this.call = this.flush;
29
- source.$fastController = this;
29
+ Reflect.defineProperty(source, "$fastController", {
30
+ value: this,
31
+ enumerable: false,
32
+ });
30
33
  }
31
34
  addSplice(splice) {
32
35
  if (this.splices === void 0) {
@@ -86,7 +89,10 @@ export function enableArrayObservation() {
86
89
  if (proto.$fastPatch) {
87
90
  return;
88
91
  }
89
- proto.$fastPatch = true;
92
+ Reflect.defineProperty(proto, "$fastPatch", {
93
+ value: 1,
94
+ enumerable: false,
95
+ });
90
96
  const pop = proto.pop;
91
97
  const push = proto.push;
92
98
  const reverse = proto.reverse;