@microsoft/fast-element 1.7.2 → 1.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 (61) hide show
  1. package/.eslintrc.json +30 -0
  2. package/CHANGELOG.json +133 -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 +24 -23
  33. package/dist/esm/interfaces.js +1 -0
  34. package/dist/esm/observation/array-change-records.js +1 -1
  35. package/dist/esm/observation/array-observer.js +4 -4
  36. package/dist/esm/observation/behavior.js +1 -0
  37. package/dist/esm/observation/notifier.js +2 -1
  38. package/dist/esm/observation/observable.js +245 -236
  39. package/dist/esm/platform.js +23 -0
  40. package/dist/esm/styles/css.js +2 -2
  41. package/dist/esm/styles/element-styles.js +1 -3
  42. package/dist/esm/templating/binding.js +5 -5
  43. package/dist/esm/templating/children.js +2 -2
  44. package/dist/esm/templating/compiler.js +3 -2
  45. package/dist/esm/templating/html-directive.js +1 -1
  46. package/dist/esm/templating/node-observation.js +2 -2
  47. package/dist/esm/templating/ref.js +1 -1
  48. package/dist/esm/templating/repeat.js +6 -6
  49. package/dist/esm/templating/slotted.js +2 -2
  50. package/dist/esm/templating/template.js +6 -6
  51. package/dist/fast-element.api.json +43 -48
  52. package/dist/fast-element.d.ts +53 -13
  53. package/dist/fast-element.js +423 -345
  54. package/dist/fast-element.min.js +1 -1
  55. package/docs/api-report.md +39 -12
  56. package/docs/guide/declaring-templates.md +1 -1
  57. package/docs/guide/next-steps.md +2 -4
  58. package/docs/guide/observables-and-state.md +10 -8
  59. package/docs/guide/using-directives.md +2 -2
  60. package/karma.conf.cjs +152 -0
  61. package/package.json +13 -11
@@ -1,6 +1,6 @@
1
- import { Binding } from "../observation/observable";
2
- import { ElementView, HTMLView, SyntheticView } from "./view";
3
- import { HTMLDirective } from "./html-directive";
1
+ import { Binding } from "../observation/observable.js";
2
+ import { ElementView, HTMLView, SyntheticView } from "./view.js";
3
+ import { HTMLDirective } from "./html-directive.js";
4
4
  /**
5
5
  * A template capable of creating views specifically for rendering custom elements.
6
6
  * @public
@@ -1,5 +1,5 @@
1
- import type { Behavior } from "../observation/behavior";
2
- import type { ExecutionContext } from "../observation/observable";
1
+ import type { Behavior } from "../observation/behavior.js";
2
+ import type { ExecutionContext } from "../observation/observable.js";
3
3
  /**
4
4
  * Represents a collection of DOM nodes which can be bound to a data source.
5
5
  * @public
@@ -1,5 +1,5 @@
1
- import type { Binding } from "../observation/observable";
2
- import type { CaptureType, SyntheticViewTemplate } from "./template";
1
+ import type { Binding } from "../observation/observable.js";
2
+ import type { CaptureType, SyntheticViewTemplate } from "./template.js";
3
3
  /**
4
4
  * A directive that enables basic conditional rendering in a template.
5
5
  * @param binding - The condition to test for rendering.
@@ -1,5 +1,5 @@
1
- import { Observable } from "../observation/observable";
2
- import { DOM } from "../dom";
1
+ import { Observable } from "../observation/observable.js";
2
+ import { DOM } from "../dom.js";
3
3
  /**
4
4
  * A {@link ValueConverter} that converts to and from `boolean` values.
5
5
  * @remarks
@@ -1,7 +1,7 @@
1
- import { DOM } from "../dom";
2
- import { PropertyChangeNotifier } from "../observation/notifier";
3
- import { defaultExecutionContext, Observable } from "../observation/observable";
4
- import { FASTElementDefinition } from "./fast-definitions";
1
+ import { DOM } from "../dom.js";
2
+ import { PropertyChangeNotifier } from "../observation/notifier.js";
3
+ import { defaultExecutionContext, Observable } from "../observation/observable.js";
4
+ import { FASTElementDefinition } from "./fast-definitions.js";
5
5
  const shadowRoots = new WeakMap();
6
6
  const defaultEventOptions = {
7
7
  bubbles: true,
@@ -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,24 @@
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 {} from "./observation/array-change-records.js";
15
+ export { enableArrayObservation } from "./observation/array-observer.js";
16
+ export { DOM } from "./dom.js";
17
+ export * from "./templating/binding.js";
18
+ export * from "./templating/html-directive.js";
19
+ export * from "./templating/ref.js";
20
+ export * from "./templating/when.js";
21
+ export * from "./templating/repeat.js";
22
+ export * from "./templating/slotted.js";
23
+ export * from "./templating/children.js";
24
+ export { elements, } from "./templating/node-observation.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -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;
@@ -0,0 +1 @@
1
+ export {};
@@ -147,7 +147,8 @@ export class PropertyChangeNotifier {
147
147
  subscribers.subscribe(subscriber);
148
148
  }
149
149
  else {
150
- this.sourceSubscribers = (_a = this.sourceSubscribers) !== null && _a !== void 0 ? _a : new SubscriberSet(this.source);
150
+ this.sourceSubscribers =
151
+ (_a = this.sourceSubscribers) !== null && _a !== void 0 ? _a : new SubscriberSet(this.source);
151
152
  this.sourceSubscribers.subscribe(subscriber);
152
153
  }
153
154
  }